使用 WDM 驅動程式的函式角色類型宣告函式

注意

從 Windows 10 版本 2004 開始,靜態驅動程式驗證程式 (SDV) 不再需要批註來識別 WDM 驅動程式的角色分派常式類型。 Please follow the guidance in the Basic and Advanced Initializations section of this page.

若要在分析 WDM 驅動程式時通知 SDV 驅動程式的進入點,您必須使用函式角色類型宣告來宣告函式。 函式角色類型定義于 Wdm.h 中。 WDM 驅動程式中 DriverEntry 常式中的每個進入點都必須藉由指定對應的角色類型來宣告。 角色類型是預先定義的 typedef,對應至 WDM 驅動程式中已辨識的進入點。

例如,若要為名為CsampUnload的驅動程式Unload常式建立函式角色類型宣告,請使用預先定義的 typedef DRIVER_UNLOAD角色類型宣告。 函式角色類型宣告必須出現在函式定義之前。

DRIVER_UNLOAD CsampUnload;

CsampUnload函式的定義保持不變:

VOID
CsampUnload(
    IN PDRIVER_OBJECT DriverObject
    )
{
    ...
}

SDV 可辨識下表所示的進入點類型。

WDM 函式角色類型 WDM 常式

DRIVER_INITIALIZE

DriverEntry

DRIVER_STARTIO

StartIO

DRIVER_UNLOAD

卸載

DRIVER_ADD_DEVICE

AddDevice

Dispatch_type (類型) DRIVER_DISPATCH

驅動程式所使用的分派常式 () 。 請參閱 撰寫分派常式

IO_COMPLETION_ROUTINE

IoCompletion

IoCompletion常式是藉由呼叫IoSetCompletionRoutine 或 IoSetCompletionRoutineEx,並將函式指標傳遞至IoCompletion常式做為第二個參數來設定。

DRIVER_CANCEL

取消

Cancel常式是藉由呼叫IoSetCancelRoutine,並將函式指標傳遞至 IRP 的取消常式,作為函式的第二個參數。

IO_DPC_ROUTINE

DpcForIsr

DpcForIsr常式是藉由呼叫IoInitializeDpcRequest,並將函式指標傳遞至DpcForIsr常式做為第二個參數來註冊。 若要將 DPC 排入佇列,請使用相同的 DPC 物件,從 ISR 常式呼叫 IoQueueDpc

KDEFERRED_ROUTINE

CustomDpc

CustomDpc常式是藉由呼叫KeInitializeDpc,並將函式指標傳遞至CustomDpc做為第二個參數來設定。 若要將 Driver 的 CustomDpc 排入佇列,請使用相同的 DPC 物件,從 ISR 常式呼叫 KeInsertQueueDpc

KSERVICE_ROUTINE

InterruptService

If 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
 )
{
}

執行驅動程式的程式碼分析來驗證函式宣告

若要協助您判斷原始程式碼是否已備妥,請 執行 Drivers 的程式碼分析。 驅動程式的程式碼分析會檢查函式角色類型宣告,並可協助識別可能遺漏的函式宣告,或在函式定義的參數不符合函式角色類型的參數時警告您。