視窗驅動程式模型（Windows Driver Model，簡稱 WDM），是微軟視窗作業系統的驅動程式設計架構，包括對於各項裝置（Device）的支援，如鍵盤（Keyboard）、滑鼠（Mouse）、網路卡（Network Driver Interface Specification，Ndis）、通用序列匯流排（Universal Serial Bus，USB）等。WDM 可支援 Windows 98, Windows 98 Second Edition, Windows Me, Windows 2000, Windows XP 以及 Windows Server 2003 在 x86 平台上的建制工作。這個架構分成好幾個管理層面：


* 核心（Kernel）

* 物件管理（Object Manager）

* 執行（Executive）

* 輸入輸出管理（I/O Manager）

* 記憶體管理（Memory Manager）

* 行程服務（Process Service）

* 執行時期函式庫（Run-time Library）

* 電源管理（Power Manager）

* 隨插即用子系統（Plug and Play Subsystem）

* 視窗管理指令（Windows Management Instrumentation，WMI）

* 核心流（Kernel Streaming）

* 硬體抽象層（Hardware Abstraction Layer）



種類

驅動程式的種類有匯流排驅動程式（bus driver）、功能驅動程式（function driver）、篩選驅動程式（filter driver）三種：


* 匯流排驅動程式（bus drivers）
  
* 虛擬匯流排驅動程式（Virtual bus drivers）：呼叫 IoInvalidateDeviceRelations 通知 PnP Manager。

* 功能驅動程式（function drivers）
  
* 微埠型驅動程式（miniport drivers）：屬於 USB, Audio, SCSI 以及 network 的轉換器（adapters）。
  
* 虛擬裝置驅動程式（Virtual device drivers）
  
* 類型驅動程式（Class drivers）

* 篩選性驅動程式（filter drivers）
  
* 上層篩選性驅動程式（upper-filter drivers）
  
* 下層篩選性驅動程式（lower-filter drivers）



程式進入點

如同許多語言從 main 函式開始，WDM 驅動程式的載入（Loading）乃至於動作，以及其解除安裝（Unload）行為，都有其步驟與規則。WDM 驅動程式可以動態式的載入與解除安裝，當偵測到裝置（Device）插入的時候，依據「PnP Manager」會自動地載入相對應的裝置驅動程式，然後成為「Driver Object」，並呼叫 DriverEntry 函式。所有的 WDM 驅動程式，都必須擁有這個 DriverEntry 常式（routine），而且「此一名稱不可改變」的，所有的驅動程式也是從這裡開始執行的，I/O Manager 首先呼叫驅動程式的 `DriverEntry()`。DriverEntry 在 DDK Compiler 編譯出來的輸出符號表是「`DriverEntry@8`」，原因是微軟的 C 編譯器把 stdcall 函示（例如 VcDCall）的名稱加上「記號」，加上一個＠符號，在附上參數的總位元組個數，8 指此 function 的所有參數所佔的 byte 數。

DriverEntry 函式有兩個參數，其中第一個參數 `PDRIVER_OBJECT DriverObject` 是指向該驅動程式對應的物件指標；`PUNICODE_STRING RegistryPath`，驅動程式的服務主要鍵碼，這個參數的使用時機並不多。以下是一個簡單而標準的 DriverEntry 基本實作：



IRQL

DriverEntry 運作在 IRQL = PASSIVE\_LEVEL 等級，所以可以使用分頁記憶體。WDM 有數個經常實作的 PASSIVE\_LEVEL 等級如下：


* DriverEntry

* Dispatch Function：DispatchXxx

* Unload：UnloadXxx

* AddDevice: XxxAddDevice

* Reinitialize: XxxReinitialize

另外還有幾個 DISPATCH\_LEVEL 等級的函式如下：


* StartIo

* AdapterControl

* ControllerControl

* IoTimer

* Dpc（延遲程式呼叫，Deferred Procedure Call）



派送行程

當 _DriverEntry_ 函式完成物件的初始化與系統註冊之後，接下來的重點便會落在 Dispatch Function 身上。每當 I/O Manager 得到一個請求時（例如按鍵，移動滑鼠），它使用請求的函式代碼（IoControlCode）呼叫驅動程式中幾個 Dispatch 行程。



解除安裝

Unload 負責在驅動程式被停止前做一些必要的處理動作，如釋放資源，記錄最後狀態等。



編譯

驅動程式的編譯需要使用 DDK（_Device Driver Kit_）中的 build 指令，它是一道命令列程式，一般會在後面加上參數：-ceZ。例如：

DDK 可用於建立用於 Windows 2000、Windows XP、Microsoft Windows Server 2003、Vista 的建置環境，但在 Windows 作業系統並非預設的功能，必須另行安裝。安裝完成後你會看到 Build Enviroment，free 是指 release 版，check 則是 debug 版。


* Windows XP checked 64 Bit Build Environment

* Windows XP checked Build Environment

* Windows XP free 64 Bit Build Environment

* Windows XP free Build Environment

build 指令一開始呼叫 Build.exe 編譯連結器，從系統「環境變數」（Environment Variable）Include 中得到參照檔案的位址，然後呼叫 Visual C++ 的編譯連結器 Nmake.exe 進行實際的編譯連結工作。在編譯過程中遇到的錯誤，遇到的警告，會記錄到 buildxxx.log，buildxxx.wrn，buildxxx.err 等檔案中。



安裝

安裝過程分成兩個步驟：


* 首先將編譯成的.sys 檔案複製到 Windows NT 的 System32\\Drivers\\ 目錄下；

* 接著在 Registry 的 HKEY\_LOCAL\_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\ 下建立和.sys 檔案同名的鍵，然後在之下建立名為 Start、Type、ErrorControl 的三種 REG\_DWORD 類型的鍵值。



範例

Microsoft DDK 提供了大量的 WDM 範例（samples）參考，這些範例隨著 DDK 的安裝，會進駐我們的系統之中（WINDDK\xx00\src）。一般人不大可能從輪子造起一個新的驅動程式，大部份要靠「既有的範例」來改良一個新的驅動程式。


* 1394

* Audio

* AVStream

* filesys

* general

* hid

* input

* ir

* kernel



批評


* WDM 學習曲線過長。

* 電源管理（power management）事件與隨插即用（Plug-and-play）差異太大。導致系統的睡眠（sleep）與清醒（wake up）狀態容易產生問題。

* I/O cancellation 幾乎不可能達成。

* 每支驅動程式動輒要撰寫數千行的程式碼。

* 不支援純使用者模式（pure user-mode）驅動程式。



相關條目


* Windows Driver Foundation

* Windows Display Driver Model

* VxD



外部連結


* Windows Driver Foundation Homepage

* Introducing Windows Driver Framework，written by well-known Windows driver developer, Walter Oney.

* Building and deploying a basic WDF Kernel Mode Driver，CodeProject

* Developing a WDF USB Kernel Mode Driver for the OSR USB FX2，CodeProject

* A simple demo for WDM Driver development



參考


* Walter Oney，《Windows Driver Model》