Share via


送信済み要求の取り消しの同期化

ドライバーは、I/O ターゲットに転送した I/O 要求の取り消しを試行する際に、有効な要求ハンドルを WdfRequestCancelSentRequest メソッドに確実に渡す必要があります。要求ハンドルは、I/O ターゲットが要求を完了すると無効になります。これは、ドライバーの CompletionRoutine コールバック関数が、要求オブジェクトの削除を試行する WdfRequestComplete を呼び出すからです。

この問題を回避するには、ドライバーで要求オブジェクトのコレクションを作成するなどの方法で、I/O ターゲットに送信した要求を記録します。ドライバーで WdfSpinLockAcquire を呼び出すと、コレクションへのアクセスを同期できます。

ドライバーの CompletionRoutine コールバック関数は、呼び出されるとロックを取得し、完了した要求のハンドルをコレクションから削除し、WdfSpinLockRelease を呼び出してロックを解除します。

ドライバーでは、I/O ターゲットに転送した要求を取り消す前に、次の処理を実行できます。

  1. WdfSpinLockAcquire を呼び出してスピン ロックを取得します。

  2. コレクションで要求オブジェクトのハンドルを検索して、ドライバーの完了ルーチンによって要求が完了されておらず、コレクションからハンドルが削除されていないことを確認します。

  3. オブジェクトが削除されないようにするために、WdfObjectReference を呼び出して要求オブジェクトの参照カウントをインクリメントします。

  4. WdfSpinLockRelease を呼び出してスピン ロックを解除します。

  5. WdfRequestCancelSentRequest を呼び出します。

  6. WdfObjectDereference を呼び出してオブジェクトの参照カウントをデクリメントします。

この順序で操作することで、ドライバーが WdfRequestCancelSentRequest を呼び出す前に I/O ターゲットが要求を完了した場合に、ドライバーの CompletionRoutine コールバック関数によって WdfRequestComplete が呼び出されていても、要求のハンドルは有効なままになります (参照カウントがインクリメントされたため)。