次の方法で共有


I/O 要求の完了

UMDF ドライバーは、最終的にすべての I/O 要求を完了する必要があります。要求を完了するには、IWDFIoRequest::Complete メソッドまたは IWDFIoRequest::CompleteWithInformation メソッドを呼び出します。要求を完了するときには、次のどの場合に当てはまるかを指定します。

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

  • 要求された I/O 操作が開始されたが、完了前に失敗した場合。

  • 要求された I/O 操作がサポートされていないか受け取った時点で有効でなかったために、デバイスと通信できない場合。

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

要求操作に関する追加情報を渡す場合は、IWDFIoRequest::CompleteWithInformation メソッドを呼び出します。たとえば、読み取り操作の場合は、読み取ったバイト数を渡す必要があります。

I/O 要求を完了するには、IWDFIoRequest::Complete または IWDFIoRequest::CompleteWithInformation の呼び出しで、CompletionStatus パラメーターに適切な完了状態を渡す必要があります。ドライバーは、完了した要求の状態を、HRESULT コードを使用して伝えます。

UMDF ドライバー ホスト プロセスは、完了した要求をリフレクター (Wudfrd.sys) に渡す前に、その HRESULT コードを NTSTATUS コードに変換します。リフレクターは、その NTSTATUS コードをオペレーティング システムに渡します。オペレーティング システムは、NTSTATUS コードを Microsoft Win32 エラー コードに変換してから、結果を呼び出し元のアプリケーションに提示します。

ドライバーのエラー コードが正しく変換されるようにするには、次のいずれかの方法でエラー コードを作成する必要があります。

  • Winerror.h のエラー コードを使用して、HRESULT_FROM_WIN32 マクロを適用する。

  • Ntstatus.h のエラー コードを使用して、HRESULT_FROM_NT マクロを適用する。

これらのマクロの詳細については、Microsoft Windows SDK のドキュメントを参照してください。

次のコード例では、適切なエラー コードを使用して要求を完了する方法を示します。

  VOID
STDMETHODCALLTYPE
CMyQueue::OnWrite(
    __in IWDFIoQueue *pWdfQueue,
    __in IWDFIoRequest *pWdfRequest,
    __in SIZE_T BytesToWrite
    )
{
            -------------------- 
    if( BytesToWrite > MAX_WRITE_LENGTH ) {
        pWdfRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_MORE_DATA), 0);
        return;
    }
            ---------------------
}

要求が正常に完了した場合、ドライバーは HRESULT 値の S_OK を返します。S_OK は Winerror.h の NO_ERROR および Ntstatus.h の STATUS_SUCCESS に相当するため、変換マクロは必要ありません。

リフレクターで Driver Verifier が有効になっている場合は、無効な状態コードが特定されて、システム バグ チェックが実行されます。

   Driver Verifier for Windows XP には、値が 10 進数の 1024 (1024L) を超える Win32 エラー コードに対してシステム バグ チェックが実行される問題があります。Windows XP 上で動作するドライバーでは、リフレクターで Driver Verifier を有効にする場合にこの問題に注意してください。

ドライバーで、下位レベルのドライバーに要求を送信した場合は、その下位レベルのドライバーが要求を完了したときに通知を受ける必要があります。通知を登録するには、IWDFIoRequest::SetCompletionCallback メソッドを呼び出して、下位レベルのドライバーが要求を完了したときにフレームワークが呼び出すメソッドのインターフェイスを登録します。ドライバーには、要求を完了するのに必要な操作を実行するための IRequestCallbackRequestCompletion::OnCompletion コールバック関数が実装されています。

ドライバーは、IWDFIoRequest::Complete の呼び出しによって作成した I/O 要求を完了しません。代わりに、ドライバーは (通常は I/O ターゲットが要求を完了した後で) IWDFObject::DeleteWdfObject を呼び出して要求オブジェクトを削除する必要があります。

たとえば、ドライバーが、その I/O ターゲットが一度に処理できる量を超えるデータの読み取りまたは書き込み要求を受け取ったとします。ドライバーはデータをいくつかの小さい要求に分割して、それらの小さい要求を 1 つ以上の I/O ターゲットに送信する必要があります。この状況に対処するには、下記の方法があります。

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

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

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

    ドライバーの I/O ターゲットは、これらの複数の要求を非同期的に処理できます。ドライバーは、小さい要求のそれぞれに対して OnCompletion コールバック関数を登録できます。OnCompletion コールバック関数が呼び出されるたびに、このコールバック関数は IWDFObject::DeleteWdfObject を呼び出してドライバー作成の要求オブジェクトを削除できます。I/O ターゲットが小さい要求をすべて完了したら、ドライバーは IWDFIoRequest::Complete を呼び出して元の要求を完了できます。

完了情報の取得

他のドライバーが完了した I/O 要求に関する情報を取得するために、UMDF ベースのドライバーは次の処理を実行できます。

そのほか、IWDFIoRequest2::GetStatus メソッドを使用して I/O 要求の現在の状態を (要求が完了しているかどうかに関係なく) 取得することもできます。