2009年10月9日 星期五

DDK 字串處理

ASCII字串及寬字元
ANSI字元 char *str1 = "abc";
UNICODE wchar_t *str2 = L"abc";

DDK自訂字串
typedef struct _STRING {
USHORT Length;
USHORT MaximumLength;
PCHAR Buffer;
} STRING;
typedef STRING *PSTRING;

typedef STRING ANSI_STRING;
typedef PSTRING PANSI_STRING;
typedef STRING OEM_STRING;
typedef PSTRING POEM_STRING;

//初始字串
RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString);
RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString);

//拷貝字串
RtlCopyString(PSTRING DestinationString, PSTRING SourceString);
RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString );

範例:
//初始化UnicodeString1
#define BUFFER_SIZE 1024
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1,L"Hello World");

//初始化UnicodeString2,因為有分配記憶體空間,最後要記得free
UNICODE_STRING UnicodeString2={0};
UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
UnicodeString2.MaximumLength = BUFFER_SIZE;

//將初始化UnicodeString2拷貝到UnicodeString1
RtlCopyUnicodeString(&UnicodeString2,&UnicodeString1);

//銷毀UnicodeString2
RtlFreeUnicodeString(&UnicodeString2);

==========================================================================
//字串比較
RtlCompareString(PSTRING String1, PSTRING String2, BOOLEAN CaseInSensitive);
RtlCompareUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive);

//轉成大寫 , AllocateDestinationString 是否為DestinationString分配記憶體
RtlUpperString(PSTRING DestinationString, PSTRING SourceString);
RtlUpcaseUnicodeString(PUNICODE_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString);

//ANSI_STRING UNICODE_STRING 字串互轉
RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString,
PANSI_STRING SourceString,
BOOLEAN AllocateDestinationString
);
RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString,
PUNICODE_STRING SourceString,
BOOLEAN AllocateDestinationString
);

2009年10月7日 星期三

DDk 記憶體複製、填充、比較

DDK提供以下的記憶體操作的function,也可以使用memcpy,memset等function
但為了保證程式碼可攜,要儘量使用標準的function

//記憶體比較
RtlEqualMemory(Destination,Source,Length);

//記憶體複製,可重疊
RtlMoveMemory(Destination,Source,Length);

//記憶體複製,不可重疊
RtlCopyMemory(Destination,Source,Length);

//記憶體填充
RtlFillMemory(Destination,Length,Fill);

//將記憶體清成0
RtlZeroMemory(Destination,Length);


範例
VOID RtlTest()
{
PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool,BUFFER_SIZE);
//用零填充記憶體
RtlZeroMemory(pBuffer,BUFFER_SIZE);

PUCHAR pBuffer2 = (PUCHAR)ExAllocatePool(PagedPool,BUFFER_SIZE);
//用固定位元組填充記憶體
RtlFillMemory(pBuffer2,BUFFER_SIZE,0xAA);

//記憶體拷貝
RtlCopyMemory(pBuffer,pBuffer2,BUFFER_SIZE);

//判斷記憶體是否一致
ULONG ulRet = RtlCompareMemory(pBuffer,pBuffer2,BUFFER_SIZE);
if (ulRet==BUFFER_SIZE)
{
KdPrint(("The two blocks are same.\n"));
}
}

DDK 記憶體配置及Linked-list處理

1.
分配Kernal記憶體
PVOID ExAllocatePool(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes);
PVOID ExAllocatePoolWithTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag);
PVOID ExAllocatePoolWithQuota(IN POOL_TYPE, IN SIZE_T);
PVOID ExAllocatePoolWithQuataTag(IN POOL_TYPE, IN SIZE_T, IN UNLONG);
釋放Kernal記憶體
VOID ExFreePool(IN PVOID P);
NTKERNELAPI VOID ExFreePoolWithTag(IN PVOID P, ULONG tag);

2.
Kernal使用link-list:
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY* Flink;
struct _LIST_ENTRY* Blink;
} LIST_ENTRY, *PLIST_ENTRY;

判斷 linked-list是否為空
IsListEmpty(PLIST_ENTRY);

插入element至 linked-list
InsertHeadList(PLIST_ENTRY head, PLIST_ENTRY entry);
InsertTailList(PLIST_ENTRY tail, PLIST_ENTRY entry);

從linked-list刪除element
RemoveHeadList(PLIST_ENTRY)
RemoveTailList(PLIST_ENTRY)

將element轉換成自訂資料結構
CONTAINING_RECORD(address, type, field) ;
address:自訂資料結構的位址
type:自訂的資料結構
filed:自訂資料結構中的pEntry

範例:
typedef struct _MYDATASTRUCT
{
ULONG number;
LIST_ENTRY ListEntry;
} MYDATASTRUCT, *PMYDATASTRUCT;

#pragma INITCODE
VOID LinkListTest()
{
LIST_ENTRY linkListHead;
//初始化鏈表
InitializeListHead(&linkListHead);

MYDATASTRUCT *pData;
ULONG i = 0;
//在鏈表中插入10個元素
KdPrint(("Begin insert to link list"));
for (i=0 ; i<5 ; i++)
{
pData = (MYDATASTRUCT *)ExAllocatePool(PagedPool,sizeof(MYDATASTRUCT));
pData->number = i;
InsertTailList(&linkListHead,&pData->ListEntry);
}

KdPrint(("Begin remove from link list\n"));
while(!IsListEmpty(&linkListHead))
{
PLIST_ENTRY pEntry = RemoveTailList(&linkListHead);
pData = CONTAINING_RECORD(pEntry,
MYDATASTRUCT,
ListEntry);
KdPrint(("%d\n",pData->number));
ExFreePool(pData);
}
}

3.
Lookaside結構:
避免頻繁配置及釋放記憶體,產生記憶體破碎的情況
使用前先要初始化,非分頁及分頁兩種方式
ExInitializeNPagedLookasideList (
IN PNPAGED_LOOKASIDE_LIST Lookaside,
IN PALLOCATE_FUNCTION Allocate,
IN PFREE_FUNCTION Free,
IN ULONG Flags,
IN SIZE_T Size,
IN ULONG Tag,
IN USHORT Depth
);

ExInitializePagedLookasideList (
IN PPAGED_LOOKASIDE_LIST Lookaside,
IN PALLOCATE_FUNCTION Allocate,
IN PFREE_FUNCTION Free,
IN ULONG Flags,
IN SIZE_T Size,
IN ULONG Tag,
IN USHORT Depth
);

配置記憶體
PVOID ExAllocateFromNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST);
PVOIDExAllocateFromPagedLookasideList(IN PPAGED_LOOKASIDE_LIST);
釋放記憶體
VOID ExFreeToNPagedLookasideList(IN PNPAGED_LOOKASIDE, IN PVOID);
VOID ExFreeToPagedLookasideList(IN PPAGED_LOOKASIDE, IN PVOID);
使用完需要刪除Lookaside物件
VOID ExDeleteNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST);
VOID ExDeletePagedLookasideList(IN PPAGED_LOOKASIDE_LIST);

範例:
typedef struct _MYDATASTRUCT
{
CHAR buffer[64];
} MYDATASTRUCT, *PMYDATASTRUCT;

#pragma INITCODE
VOID LookasideTest()
{
PAGED_LOOKASIDE_LIST pageList;
ExInitializePagedLookasideList(&pageList,NULL,NULL,0,sizeof(MYDATASTRUCT),'1234',0);

#define ARRAY_NUMBER 50
PMYDATASTRUCT MyObjectArray[ARRAY_NUMBER];
for (int i=0;i {
MyObjectArray[i] = (PMYDATASTRUCT)ExAllocateFromPagedLookasideList(&pageList);
KdPrint(("Alloc MyObjectArray[%d]\n",i));
}

//模擬頻繁回收記憶體
for (i=0;i {
KdPrint(("Free MyObjectArray[%d]\n",i));
ExFreeToPagedLookasideList(&pageList,MyObjectArray[i]);

MyObjectArray[i] = NULL;

}

ExDeletePagedLookasideList(&pageList);
//刪除Lookaside物件
}

DDK 使用VC6開發

DDK版本是Windows Server 2003 Sp1 Ddk
專案名稱是 MyDriver
步驟
1.File->New->Project->Win32 Application->輸入專案名稱->An Empty project

2.將.c與.h加入到專案

3.Build->Configuration 去掉Debug,Release,增加Driver Check Edition

4.project->Setting->General中,Intermediate files與Output Files改成MyDriver_Check

5.project->Setting->C/C++->Project Options,全部刪除,改成
/nologo /Gz /MLd /W3 /WX /Z7 /Od /D WIN32=100 /D _X86_=1 /D WINVER=0x500 /D DBG=1 /Fo"MyDriver_Check/" /Fd"MyDriver_Check/" /FD /c

6.project->Setting->Link->Project Options,全部刪除,改成
ntoskrnl.lib /nologo /base:"0x10000" /stack:0x400000,0x1000 /entry:"DriverEntry" /subsystem:console /incremental:no /pdb:"DriverDev___Win32_Driver_Release_Edtion/HelloDDK.pdb" /map:"DriverDev___Win32_Driver_Release_Edtion/HelloDDK.map" /debug /machine:I386 /nodefaultlib /out:"MyDriver_Check/HelloDDK.sys" /pdbtype:sept /subsystem:native /driver /SECTION:INIT,D /RELEASE /IGNORE:4078

7.修改VC lib及Include目錄,Tool->Option->Directoies->Show Directories for:
->Include Files加入DDK路徑\INC\W2K 以及INC\DDK\W2K
->Library Files加入DDK路徑\LIB\W2K\I386

2009年10月6日 星期二

PDO與FDO

在WDM的架構當中,
PDO如何得知上層FDO
->透過AttachedDevice 子欄位
ex:
PDEVICE_OBJECT pDevice = pDriverObject->DeviceObject;
pDevice->AttachedDevice

FDO如何得知下層的裝置
->透過裝置擴充紀錄
ex:
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT fdo;
PDEVICE_OBJECT NextStackDevice;
UNICODE_STRING ustrDeviceName; // 裝置名
UNICODE_STRING ustrSymLinkName; // 符號連結名
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);

2009年8月13日 星期四

c#練習 - int,字串互轉

int to string
int num = 5;
string str = num.ToString();

string to int
string str= "5";
int num = int.parse(str);

2009年8月8日 星期六

希臘蜜月 - Day 6 - Imerovigli

原本導遊安排在Kamari之後,要先回去飯店休息,因為趙伯伯他們年紀比較大,

而且今天會在Oia看夕陽,怕他們體力不支,不過趙伯伯在Kamari那裡打瞌睡後,

精神就好多啦!於是乎,我們就提早前往Oia,途中會在Imerovigli拍拍照,

在途上,我也不小心瞇了一下下…醒來,已經到了Imerovigli了~

希臘的車型,跟台灣的有點不太一樣,像台灣跟泰國一大堆的Altis,

在希臘好像沒看到耶~而希臘有些車型,在台灣也是沒看到…

向下面這台Toyota的車,比Yaris還可愛耶~

附近的籃球場,

附帶一提的是希臘人很愛籃球,晚上的時候他們都在看籃球轉播,前陣子還有個新聞,

說希臘的球隊想要簽Iverson耶,可見他們對籃球的熱愛,

一口廢棄的井,小丸子很愛演… = =

附帶一提的是,Santorini的水,都是抽取地下水來淡化的,旅館的老闆都需要叫水車來加水,

光是加滿游泳池的水就要花上好幾萬塊台幣,我們洗澡的水,嘗起來確實有嫌鹹的味道

在Imerovigli主要是來看看洞穴屋,這裡有一些民宅,也有飯店,

在Santorini住洞穴屋可不便宜,可以說是高級旅館,有錢想住的話,還不簡單耶…

在旺季的時候,需要一年前就訂位,而且需要連續住上好幾個晚上,老闆才肯讓你入住…

這時候剛好是下午時刻,希臘人通常都在睡午覺,導遊要我們小聲一點,

由於地勢的關係,這一戶的陽台,可能是下一戶的屋頂,可能走著走著,就會走到別人家的屋頂,

走到上面去,映入眼簾的就是這張經典的景象,以地中海為背景,屋子以白色為基調,襯托著藍頂教堂與鐘樓…

不管是月曆或明信片,常常都會有這張照片的出沒…哈

美景當前,當然也要來個甜蜜的合照囉…當然,情侶裝也是必備的!!

一整排的建在懸崖邊的洞穴屋,形成一副特殊的景觀

這裡真的是很漂亮,找間咖啡店,跟心愛的人在這裡靜靜地坐上一個下午,

忘卻所有的煩惱、憂愁,細細品味這裡的景色,咀嚼屬於Santorini的味道,人生夫復何求呢?

近一點,再來一張~

我也要來solo一下~

眺望遠方的愛之船…

濃濃的希臘小島fu

再來這張更厲害啦…

本人犧牲色相,露出修長的美腿,歐耶~~

在這裡泡泡水,看著地中海的景色,真是一大享受阿!

另一個角度再來一張!

這是從下面往上拍的藍頂教堂&鐘樓

鐘樓

下面那張圖的海岬是可以走過去的,可是導遊說路況不好,再加上風滿大的,

所以我們就沒去了,也是明信片級的風景!

陽光灑落在十字架上,感覺滿聖潔的,好像有神蹟發生…哈哈

在這裡發生了一件小插曲…就是從Kamari到這裡路程還滿長的,

結果,到了之後一直想來個山洪爆發,可是導遊說…他之前常跟這裡的餐廳借廁所,

可是團員都沒有消費,久而久之,店家就不願意讓我們借廁所了…

慘了,大家已知道憋尿對身體不好阿,那…乾脆就回歸大自然吧!!!

找個廢墟的又隱密的地方,快樂的舒暢一下…讚啦!!!

雖然心沒有遺留在愛情海,但至少還是留下些東西在愛情海呢!

什麼東西都可以遺留在愛情海…可是把」夢遺留在愛情海」就不好啦…

(有點A,滿18歲的才可以反白看喔!科科~)

好啦,再休息一下下…下篇介紹最迷人的Oia…

敬請期待~~~

winsock2.h redefined問題

解法: #define _WINSOCKAPI_    // stops windows.h including winsock.h #include #include