天天看點

Windows驅動開發技術詳解 筆記1

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