I/O 要求の完了

すべてのフレームワークベースのドライバーは、最終的にフレームワークから受信するすべての I/O 要求を完了する必要があります。 ドライバーは、要求オブジェクトの WdfRequestCompleteWdfRequestCompleteWithInformation、または WdfRequestCompleteWithPriorityBoost メソッドを呼び出すことによって要求を完了します。

要求を完了するタイミング

ドライバーは、次のいずれかのケースが当てはまると判断したときに要求を完了する必要があります。

  • 要求された I/O 操作が正常に完了しました。

  • 要求された I/O 操作は開始されましたが、完了する前に失敗しました。

  • 要求された I/O 操作がサポートされていないか、受信した時点で無効であり、開始できませんでした。

  • 要求された I/O 操作が 取り消されました。

ドライバーがデバイスで I/O アクティビティを作成して I/O 要求を処理する場合、ドライバーは通常、EvtInterruptDpc または EvtDpcFunc コールバック関数から WdfRequestComplete を呼び出します。

ドライバーは、サポートされていない要求または無効な要求を受信した場合、通常、要求を受信した要求ハンドラーから WdfRequestComplete を呼び出します。

I/O 操作が取り消された場合、ドライバーは通常、EvtRequestCancel コールバック関数から WdfRequestComplete を呼び出します。

ドライバー が I/O 要求を I/O ターゲット転送する 場合、次のように、I/O ターゲットが要求を完了した後、ドライバーは要求を完了します。

  • ドライバーが I/O 要求 を I/O ターゲットに同期的に転送する場合、ドライバーの I/O ターゲットへの呼び出しは、下位レベルのドライバーが要求を完了するまで返されません (エラーが発生しない限り)。 I/O ターゲットが戻った後、ドライバーは WdfRequestComplete を呼び出す必要があります。

  • ドライバーが I/O 要求を非同期的に転送する場合は、下位レベルのドライバーが要求を完了したときにドライバーに通知してもらうようにします。 ドライバーが CompletionRoutine コールバック関数を登録すると、フレームワークは I/O ターゲットが要求を完了した後、このコールバック関数を呼び出します。 CompletionRoutine コールバック関数は通常、WdfRequestComplete を呼び出します。

CompletionRoutine コールバック関数を登録するには、ドライバーが I/O 要求を I/O ターゲットに転送する前に、WdfRequestSetCompletionRoutine を呼び出す必要があります。

I/O ターゲットが非同期転送 I/O 要求を完了したときに、ドライバーが通知を受ける必要がない場合、ドライバーは CompletionRoutine コールバック関数を登録する必要はありません。 代わりに、ドライバーは WdfRequestSend を呼び出すときに WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET フラグを設定できます。 この場合、ドライバーは WdfRequestComplete を呼び出しません。

ドライバーは、WdfRequestCreate または WdfRequestCreateFromIrp を呼び出すことによって作成された I/O 要求を完了しません。 代わりにドライバーは、通常 I/O ターゲットが要求を完了した後に、WdfObjectDelete を呼び出して要求オブジェクトを削除する必要があります。です。

たとえば、ドライバーは、ドライバーの I/O ターゲットが一度に処理できるよりも大きい量のデータの読み取りまたは書き込み要求を受け取る場合があります。 ドライバーは、データを複数の小さな要求に分割し、これらの小さな要求を 1 つ以上の I/O ターゲットに送信する必要があります。 この状況を処理する手法は次のとおりです。

  • WdfRequestCreate を呼び出して、小さい要求を表す 1 つの追加の要求オブジェクトを作成します。

    ドライバーは、I/O ターゲットに同期的にこの要求を送信できます。 小さい要求の CompletionRoutine コールバック関数は、ドライバーが要求を再利用して I/O ターゲットに再度送信できるように、WdfRequestReuse を呼び出すことができます。 I/O ターゲットが最後の小さい要求を完了すると、CompletionRoutine コールバック関数は WdfObjectDelete を呼び出してドライバーが作成した要求オブジェクトを削除し、ドライバーは WdfRequestComplete を呼び出して元の要求を完了できます。

  • WdfRequestCreate を呼び出して、小さい要求を表す複数の追加の要求オブジェクトを作成します。

    ドライバーの I/O ターゲットは、これらの複数の小さな要求を非同期的に処理できます。 ドライバーは、小さい要求ごとに CompletionRoutine コールバック関数を登録できます。 CompletionRoutine コールバック関数が呼び出されるたびに、WdfObjectDelete を呼び出して、ドライバーによって作成された要求オブジェクトを削除できます。 I/O ターゲットがすべての小さい要求を完了すると、ドライバーは WdfRequestComplete を呼び出して元の要求を完了できます。

完了情報の提供

ドライバーが要求を完了すると、必要に応じて、他のドライバーがアクセスできる追加情報を提供できます。 たとえばドライバーは、読み取りまたは書き込み要求に転送されたバイト数を提供する場合があります。 この情報を提供するために、ドライバーは次のいずれかを実行できます。

完了情報の取得

別のドライバーが完了した I/O 要求に関する情報を取得するには、ドライバーは次のことができます。

  • WdfRequestGetStatus を呼び出して、下位レベルのドライバーが WdfRequestComplete を呼び出したときに指定した完了状態の値を取得します。

  • WdfRequestGetCompletionParams を呼び出して、要求のバッファーを表すメモリ オブジェクトへのハンドルやバス固有の情報など、完了した要求に関する追加情報を含む WDF_REQUEST_COMPLETION_PARAMS 構造体を取得します。

    ドライバーは、WdfRequestSend を呼び出して I/O 要求を同期的または非同期的に I/O ターゲットに送信した後にのみ、WdfRequestGetCompletionParams を呼び出すことができます。 ドライバーは、I/O 要求を同期的にのみに (WdfIoTargetSendReadSynchronously など) I/O ターゲットに送信するメソッドのいずれかを呼び出した後、WdfRequestGetCompletionParams を呼び出してはなりません。

  • WdfRequestGetInformation を呼び出して、下位レベルのドライバーが WdfRequestSetInformation または WdfRequestCompleteWithInformation を呼び出したときに指定した追加の I/O 完了情報を取得します (ドライバー スタック内のドライバーがそのような情報を提供する場合)。

ドライバーが I/O 要求を同期的に送信する場合、通常、同期呼び出しが返された後、WdfRequestGetStatusWdfRequestGetCompletionParams、および WdfRequestGetInformation を呼び出します。 ドライバーが I/O 要求を非同期的に送信する場合は、通常、CompletionRoutine コールバック関数内からこれらのメソッドを呼び出します。

I/O 要求の完了の詳細については、「取り消しコードと完了コードの同期」を参照してください。