I/O キューへの IRP のディスパッチ
[KMDF と UMDF に適用]
フレームワークベースのドライバーは、受信 IRP のターゲット キューを動的に指定できます。 特定のキューに IRP をディスパッチするには、ドライバーは WdfDeviceWdmDispatchIrpToIoQueue メソッドを呼び出す必要があります。
通常、ドライバーは、その EvtDeviceWdmIrpPreprocess または EvtDeviceWdmIrpDispatch コールバック関数から WdfDeviceWdmDispatchIrpToIoQueue を呼び出します。 最適なパフォーマンスを得るため、ほとんどのドライバーは、両方のコールバック関数は提供しません。
注: UMDF ドライバーは EvtDeviceWdmIrpDispatch コールバック関数を提供できますが、EvtDeviceWdmIrpPreprocess を提供できるのは KMDF ドライバーだけです。
ドライバーが EvtDeviceWdmIrpPreprocess を既に提供している場合は、それを使用してキューを動的に選択できます。 そうでない場合は、EvtDeviceWdmIrpDispatch を提供し、そのコールバック関数内から WdfDeviceWdmDispatchIrpToIoQueue を呼び出します。
さらに、次の制限事項に注意する必要があります。
I/O キューに IRP をディスパッチする別の方法は、既定のキューを作成し、キューのハンドラー内から WdfRequestForwardToIoQueue を呼び出すことです。 この手法は KMDF 1.0 以降で使用できますが、順方向進行キューではうまく機能せず、一般的には低速です。 代わりに WdfDeviceWdmDispatchIrpToIoQueue を使用することを検討してください。
EvtDeviceWdmIrpDispatch コールバック関数を登録するために WdfDeviceConfigureWdmIrpDispatchCallback を呼び出す場合、ドライバーは MajorFunction パラメーターを IRP_MJ_DEVICE_CONTROL、IRP_MJ_INTERNAL_DEVICE_CONTROL、IRP_MJ_READ、IRP_MJ_WRITE のいずれかに設定する必要があります。 この要件は EvtDeviceWdmIrpPreprocess には適用されませんが、指定されたキューに動的にディスパッチできるのは、これらの型の IRP のみです。
EvtDeviceWdmIrpPreprocess に送られる IRP には、追加のスタックの場所があります。 EvtDeviceWdmIrpDispatch に送られる IRP (先に EvtDeviceWdmIrpPreprocess が呼び出だされない) は行いません。
EvtDeviceWdmIrpPreprocess はドライバー定義のコンテキスト情報の送信を容易にしませんが、EvtDeviceWdmIrpDispatch はドライバー定義のコンテキスト情報を送信しません。
前処理されていない IRP のディスパッチ
ドライバーの EvtDeviceWdmIrpDispatch コールバック関数から IRP をディスパッチするには、次の手順を使用します。
ドライバーは、EvtDriverDeviceAdd コールバック関数から WdfDeviceConfigureWdmIrpDispatchCallback を呼び出して EvtDeviceWdmIrpDispatch コールバック関数を登録します。
ターゲットが親デバイスの I/O キューである場合、KMDF ドライバーは WdfDeviceCreate を呼び出す前に WdfPdoInitAllowForwardingRequestToParent を呼び出す必要があります。 KMDF ドライバーが EvtDeviceWdmIrpPreprocess コールバック関数も提供している場合、フレームワークは IRP が到着したときに最初にその関数を呼び出します。 コールバック関数は、要求を前処理した後、WdfDeviceWdmDispatchPreprocessedIrp を呼び出して IRP をフレームワークに返します。
フレームワークは、ドライバーの EvtDeviceWdmIrpDispatch コールバック関数を呼び出します。
EvtDeviceWdmIrpDispatch 内から、ドライバーは WdfDeviceWdmDispatchIrpToIoQueue または WdfDeviceWdmDispatchIrp を呼び出すことができますが、両方を呼び出すことはできません。 KMDF ドライバーには、これらのどちらのメソッドも呼び出さず、代わりに IRP を完了するか、保留にするという追加オプションがあります。
KMDF ドライバーが WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK フラグを設定し、ターゲット I/O キューの転送の確実な順方向進行が有効でない場合、フレームワークはドライバーの EvtIoInCallerContext を呼び出します (指定されている場合)。 要求を前処理した後、コールバック関数は WdfDeviceEnqueueRequest を呼び出してキューに登録するか、WdfRequestComplete を呼び出して完了する必要があります。
前処理されていない IRP のディスパッチ
ドライバーの EvtDeviceWdmIrpPreprocess コールバック関数から特定の I/O キューに IRP をディスパッチするには、次の手順を使用します。
- ドライバーは、WdfDeviceInitAssignWdmIrpPreprocessCallback を呼び出すことによって EvtDeviceWdmIrpPreprocess コールバック関数を登録します。
- ターゲットが親デバイスの I/O キューである場合、ドライバーは WdfPdoInitAllowForwardingRequestToParent を呼び出します。
- EvtDeviceWdmIrpPreprocess から、Flags を WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP に設定して WdfDeviceWdmDispatchIrpToIoQueue を呼び出します。
- ドライバーが WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK フラグを設定し、ターゲット I/O キューの転送の確実な順方向進行が有効でない場合、フレームワークはドライバーの EvtIoInCallerContext を呼び出します (指定されている場合)。 コールバック関数は、要求の前処理を完了した後、WdfDeviceEnqueueRequest を呼び出してキューに登録するか、WdfRequestComplete を呼び出して完了する必要があります。