1.Windows驅動程式分為兩類:NT式驅動程式,WDM式驅動程式。
2.驅動程式的入口函數DriverEntry,它有兩個參數DriverObject 和RegistryPath。
DriverEntry函數由IO管理器負責排程,這兩個函數也是由IO管理器負責配置設定和指定的。第一個代表IO管理器傳遞進來的驅動程式對象,第二個指向此驅動程式負責的系統資料庫。
3.裝置類型FILE_DEVICE_UNKNOWN此種裝置為獨占裝置,即裝置隻能被一個應用程式所使用。
4.裝置對記憶體的操作有兩種方式:DO_BUFFERED_IO和 DO_DIRECT_IO
5.驅動解除安裝例程
VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pNextObj;
pNextObj = pDriverObject->DeviceObject;
//周遊裝置對象連結清單,删除裝置
while (pNextObj != NULL)
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension;
//删除符号連結
UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
IoDeleteSymbolicLink(&pLinkName);
pNextObj = pNextObj->NextDevice;
IoDeleteDevice( pDevExt->pDevice );
}
}
6.在VS2005中配置驅動開發環境參考:http://blog.sina.com.cn/s/blog_5371d2790100bsy2.html
在visual c++ 6.0 中配置驅動開發環境參考《windows驅動程式開發技術詳解》--1.3.2節
7.NT或WDM式的驅動程式在預設情況下是隐藏的,但也可以通過裝置管理器來檢視,路徑如下:
裝置管理器--->檢視---->顯示隐藏的裝置----->非即插即用裝置
8.有些代碼中會看到這樣的字段,比如:
#pragma INITCODE
NTSTATUS DriverEntry().........
其中的#pragma 指明函數是加載到INIT記憶體區域中的。INIT标志指明該函數隻是在加載的時候需要裝入記憶體,當程式被解除安裝以後,該函數可以從記憶體區域中解除安裝掉。
可以通過以下方式定義分頁記憶體,非分頁記憶體,初始化記憶體等:
#define PAGEDCODE code_seg("PAGE")//分頁記憶體
#define LOCKEDCODE code_seg() //非分頁記憶體
#define INITCODE code_seg("INIT")//初始化記憶體
#define PAGEDDATA data_seg("PAGE")//分頁記憶體
#define LOCKEDDATA data_seg() //非分頁記憶體
#define INITDATA data_seg("INIT")//初始化記憶體
8.WDM驅動程式中有一個dispatch 例程:AddDevice,該dispatch routine是用來建立裝置對象并由PNP管理器調用的。
DriverObject->DriverExtension->AddDevice = DriverAddDeviceRoutine;
9.俄從去年就開始研究WDM驅動程式,到現在才發現俺寫的一直都是NT式的驅動程式。唉..........
10.WDM和NT式驅動的一個重要差別就是要對IRP_MJ_PNP請求進行處理。還有一個就是AddDevice例程。
11.PAGED_CODE()
這是一個DDK提供的宏,隻在check版中有效。當此例程所在的中斷請求級别超過APC_LEVEL時,會産生一個斷言,斷言會使程式終止,并報告出錯的位址。
12.WDM 驅動程式的加載
WDM驅動程式不能像NT式驅動程式一樣以服務的形式加載到系統中,需要自己編寫一個inf檔案,可以使用由DriverStufio自帶的EzDriverInstaller工具。
還可以才用如下的方式:
控制台--->新增硬體--->"是,我已經連接配接了此硬體"--->“添加新的硬體裝置”--->“安裝我手動從清單中選擇的硬體(進階)”--->顯示所有裝置--->從磁盤安裝。
這種方式比較繁瑣,而且需要等待系統枚舉所有的裝置,可能要等很長時間,是以還是推薦使用EzDriverInstaller安裝、啟動、關閉、解除安裝、重新開機。
13.科普知識
Windows 9X系列:Windows95、Windows98、Windows ME
Windows NT系列:Windows NT3.1(93年7)、Windows NT3.5(94年9)、Windows NT4.0(96年7)
Windows 2000(99年12)、Windows XP(01年8)、Windows Server 2003(03年3)
14.Windows驅動程式和普通win32的應用程式一樣,也是PE格式的檔案。C語言中對變量的聲明必須在函數的首部,而C++則沒有這個限制。但是C++的許多進階特性是不适合用來開發驅動程式的,是以可以使用C++的簡單特性來寫驅動程式。但最好還是用C。
15.當一個函數被調用的時候,首先壓入函數的各個參數,然後壓入函數的傳回位址。當函數退出的時候以相反的順序依次退出堆棧,進而保持了堆棧的平衡。
C語言調用約定:(__cdecl)從右到左參數入棧,調用者恢複堆棧。
标準調用約定:(__stdcall)從右向左參數入棧,函數本身負責恢複堆棧
Windows驅動程式的編譯需要使用标準調用約定,尤其是入口函數。是以用VC編譯器的時候應該将VC的C語言調用約定更改為标準調用約定。(Vs2005中我沒有更改,編寫的驅動也是照樣可以運作,是以此說法有待驗證。)如果用DDK編譯則可以忽略這個環節。
16.在C++中添加C語言的程式,需要用extern "C"來修飾
有時候 出現下面的錯誤,可以考慮在代碼前面加上以上修飾符。
:error LNK2001:unresolved external symbol "unsigned long __cdecl 。。。。"
17.Windows作業系統規定,在核心模式的程式無法調用使用者模式的程式,而使用者模式的程式可以調用核心态的程式。
18.WDM驅動程式加載
(1)Windows在安裝的時候會提供很多INF檔案,根據不同的VernderID何ProductID,會找出合适這個裝置的INF檔案,如果系統中沒有合适的INF檔案,系統會向使用者詢問是否可以提供這個INF檔案,如果不能則嘗試到微軟網站去尋找。找到INF檔案後,系統會根據INF檔案上的訓示,将驅動程式(.sys檔案)和相關檔案複制到系統指定目錄下,并且修改系統資料庫。同時通知PNP管理器和I/O管理器,建立新裝置,并運作驅動程式的入口程式DriverEntry。
(2)INF檔案剖析:INF檔案是一個文本檔案,由若幹個節(Section)組成。每個節的名稱用一個方括号訓示,緊接着方括号後面的就是節的内容。每一行就是一項内容,其形式都是類似SomeEntry = SomeValue。每個項的順序是可以颠倒的,但系統分析INF檔案的時候,是順序解析的。INF中注釋語句是用分号開頭的。