WDM ドライバーの関数役割型を使用した関数の宣言

Note

Windows 10 バージョン 2004 以降、 静的ドライバー検証ツール (SDV) では、WDM ドライバーのディスパッチ ルーチンの役割の種類を識別するための注釈が不要になります。 このページの 「基本および高度な初期化」 セクションのガイダンスに従ってください。

WDM ドライバーを分析するときに、ドライバーのエントリ ポイントについて SDV に通知するには、関数の役割の型宣言を使用して関数を宣言する必要があります。 関数の役割の種類は Wdm.h で定義されています。 WDM ドライバーの DriverEntry ルーチンの各エントリ ポイントは、対応するロールの種類を指定して宣言する必要があります。 ロールの種類は、WDM ドライバーで認識されるエントリ ポイントに対応する定義済みの typedef です。

例えば、ドライバーの アンロード ルーチンのために CsampUnloadという関数のロール型宣言を作成するには、定義済みのtypedef DRIVER_UNLOADロール型宣言を使用します。 関数ロール型宣言は、関数定義の前に指定する必要があります。

DRIVER_UNLOAD CsampUnload;

CsampUnload 関数の定義メインが変更されていません。

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

SDV は、次の表に示すエントリ ポイントの種類を認識します。

WDM 関数ロール型 WDM ルーティン

DRIVER_INITIALIZE

DriverEntry

DRIVER_STARTIO

StartIO

DRIVER_UNLOAD

Unload

DRIVER_ADD_DEVICE

AddDevice

Dispatch_type() DRIVER_DISPATCH

ドライバーによって使用されるディスパッチ ルーチン。 ディスパッチ ルーチンの記述参照

IO_COMPLETION_ROUTINE

IoCompletion

IoCompletion ルーチンは、 IoSetCompletionRoutine または IoSetCompletionRoutineEx を呼び出し、関数ポインターを IoCompletion ルーチンに 2 番目のパラメーターとして渡すことによって設定されます。

DRIVER_CANCEL

キャンセル

キャンセル ルーチンは、 IoSetCancelRoutine を呼び出し、関数への 2 番目のパラメーターとして IRP のキャンセル ルーチンへの関数ポインターを渡すことによって設定されます。

IO_DPC_ROUTINE

DpcForIsr

DpcForIsr ルーチンは、 IoInitializeDpcRequest を呼び出し、関数ポインターを 2 番目のパラメーターとして DpcForIsr ルーチンに渡すことによって登録されます。 DPC をキューに登録するには、同じ DPC オブジェクトを使用して ISR ルーチンから IoQueueDpc を呼び出します。

KDEFERRED_ROUTINE

CustomDpc

CustomDpc ルーチンは、 KeInitializeDpc を呼び出し、2 番目のパラメーターとして CustomDpc への関数ポインターを渡すことによって設定されます。 ドライバーの CustomDpc をキューに登録するには、同じ DPC オブジェクトを使用して ISR ルーチンから KeInsertQueueDpc を呼び出します。

KSERVICE_ROUTINE

InterruptService

InterruptService ルーチン (ISR) は、デバイスの割り込みを処理し、必要に応じて、受信したデータの割り込み後処理をスケジュールします。

REQUEST_POWER_COMPLETE

PowerCompletion コールバック ルーチンは、Power IRP の処理を完了します。 他のすべてのドライバーが IRP を完了した後、ドライバーが追加のタスクを実行する必要がある場合、ドライバーは、IRP を割り当てる PoRequestPowerIrp ルーチンへの呼び出し中に PowerCompletion コールバック ルーチンを登録します。

WORKER_THREAD_ROUTINE

ルーチンによって返される値

Routine は、 ExInitializeWorkItem 関数の第 2 パラメーターで指定されるコールバック ルーチンです。

この ルーチン は、ドライバーが 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 カテゴリに対して同じディスパッチ ルーチンが使用されますが、ドライバーは次の方法で 2 つの初期化をエンコードできます。

DriverObject->MajorFunction[IRP_MJ_CREATE] = 
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FooCreateCleanup; // Advanced style for a multi-role dispatch routine 

ドライバーが SDV を正しく実行できるようにするには、 ドライバーは上記の 基本 または 高度な スタイルのみを使用する必要があります。 これら 2 つのメソッドのいずれかが使用されていない場合、ドライバー の 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
 )
{
}

ドライバーのコード分析を実行して関数の宣言を確認する

ソース コードが準備されているかどうかを判断するには、ドライバーのコード分析を実行 します。 ドライバーのコード分析は、関数ロールの型宣言のチェックし、関数定義のパラメーターが関数ロール型のパラメーターと一致しない場合に、見落とされた可能性がある関数宣言を識別したり警告したりするのに役立ちます。