使用 WDM 驅動程式的函式角色類型宣告函式
注意
從 Windows 10 版本 2004 開始, 靜態驅動程式驗證器 (SDV) 不再需要註釋來識別 WDM 驅動程式的角色分派例程類型。 請遵循此頁面的基本和進階初始化一節中的指引。
若要在分析 WDM 驅動程式時通知 SDV 驅動程式的進入點,您必須使用函式角色類型宣告來宣告函式。 函式角色類型定義於 Wdm.h 中。 WDM 驅動程式中 DriverEntry 例程中的每個進入點都必須藉由指定對應的角色類型來宣告。 角色類型是預先定義的 typedefs,對應至 WDM 驅動程式中已辨識的進入點。
例如,若要為名為 CsampUnload 的驅動程式 Unload 例程建立函式角色類型宣告,請使用預先定義的 typedef DRIVER_UNLOAD角色類型宣告。 函式角色類型宣告必須出現在函式定義之前。
DRIVER_UNLOAD CsampUnload;
CsampUnload 函式的定義保持不變:
VOID
CsampUnload(
IN PDRIVER_OBJECT DriverObject
)
{
...
}
SDV 可辨識下表所示的進入點類型。
WDM 函式角色類型 | WDM 例程 |
---|---|
DRIVER_INITIALIZE |
|
DRIVER_STARTIO |
|
DRIVER_UNLOAD |
|
DRIVER_ADD_DEVICE |
|
Dispatch_type(類型) DRIVER_DISPATCH | 驅動程式所使用的分派例程。 請參閱 撰寫分派例程。 |
IO_COMPLETION_ROUTINE |
IoCompletion 例程是藉由呼叫 IoSetCompletionRoutine 或 IoSetCompletionRoutineEx,並將函式指標傳遞至 IoCompletion 例程做為第二個參數來設定。 |
DRIVER_CANCEL |
Cancel 例程是藉由呼叫 IoSetCancelRoutine 並將函式指標傳遞至 IRP 的取消例程,作為函式的第二個參數。 |
IO_DPC_ROUTINE |
DpcForIsr 例程會藉由呼叫 IoInitializeDpcRequest 來註冊,並將函式指標傳遞至 DpcForIsr 例程做為第二個參數。 若要將 DPC 排入佇列,請使用相同的 DPC 物件,從 ISR 例程呼叫 IoQueueDpc 。 |
KDEFERRED_ROUTINE |
CustomDpc 例程是藉由呼叫 KeInitializeDpc 並將函式指標傳遞至 CustomDpc 作為第二個參數來設定。 若要將驅動程式的 CustomDpc 排入佇列,請使用相同的 DPC 物件,從 ISR 例程呼叫 KeInsertQueueDpc。 |
KSERVICE_ROUTINE |
如果必要,InterruptService 例程 (ISR) 會服務裝置中斷,並排程接收數據的中斷後處理。 |
REQUEST_POWER_COMPLETE |
PowerCompletion 回呼例程會完成Power IRP的處理。 如果驅動程式必須在所有其他驅動程式完成 IRP 之後執行其他工作,驅動程式會在呼叫配置 IRP 的 PoRequestPowerIrp 例程期間註冊 PowerCompletion 回呼例程。 |
WORKER_THREAD_ROUTINE |
常規 例程是在 ExInitializeWorkItem 函式的第二個參數中指定的回呼例程。 只有當驅動程式呼叫 ExQueueWorkItem 將工作專案新增至系統佇列時,才應該以這種方式宣告例程。 |
宣告驅動程式分派例程
從 Windows 10 版本 2004 開始,分派例程的函式角色類型宣告會根據 WDM 驅動程式 DriverEntry 例程中的 DriverObject-MajorFunction> 數據表初始化,自動調整其 IRP 類別。
驅動程式 Foo 必須使用基本或進階的宣告樣式來完成角色宣告,才能符合 SDV 規範。
基本和進階初始化
您可以在下列範例中看到基本樣式(請注意分派例程名稱 FooCreate 和 FooCleanup 只是範例,可以使用任何適當的名稱):
DriverObject->MajorFunction[IRP_MJ_CREATE] = FooCreate; //Basic style
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FooCleanup;
若要縮短所需的清單,可以採取更進階的方法。 雖然相同的分派例程用於多個 IRP 類別,但驅動程式可能會以這種方式編碼兩個初始化:
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FooCreateCleanup; // Advanced style for a multi-role dispatch routine
為了讓驅動程式能夠正確執行 SDV,驅動程式只能使用上面所示的基本或進階樣式。 如果未使用這兩種方法之一,驅動程式 上的 SDV 驗證將無法如預期 般運作。
函式參數和函式角色類型
在 C 程式設計語言中,您在函式定義中使用的參數類型必須符合函式原型的參數類型,或在此案例中為函式角色類型。 SDV 取決於函式簽章進行分析,並忽略簽章不相符的函式。
例如,您應該使用IO_COMPLETION_ROUTINE函式角色類型來宣告 IoCompletion 例程:
IO_COMPLETION_ROUTINE myCompletionRoutine;
當您實作 myCompletionRoutine 時,參數類型必須符合IO_COMPLETION_ROUTINE所使用的類型,也就是PDEVICE_OBJECT、PIRP 和 PVOID(請參閱語法的 IoCompletion 例程)。
NTSTATUS
myCompletionRoutine(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
)
{
}
執行驅動程式的程式代碼分析以驗證函式宣告
若要協助您判斷原始程式碼是否已備妥,請執行 驅動程式的程式代碼分析。 驅動程式的程式代碼分析會檢查函式角色類型宣告,並有助於識別函式宣告,當函式定義的參數不符合函式角色類型的參數時,可能會遺漏或警告您。