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中註釋語句是用分號開頭的。