キャンセルと完了コードの同期

ドライバーが WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出して I/O 要求を取り消し可能にする場合、同期の問題が発生する可能性があります。 たとえば、ドライバーとデバイスは、EvtInterruptIsr および EvtInterruptDpc コールバック関数を使用してデバイス I/O 操作を非同期的に実行し、EvtInterruptDpc コールバック関数と EvtRequestCancel コールバック関数の両方に WdfRequestComplete の呼び出しが含まれている可能性があります。

ドライバーは、要求を完了または取り消すために、WdfRequestComplete を 1 回だけ呼び出す必要があります。 ただし、EvtInterruptDpc コールバック関数と EvtRequestCancel コールバック関数が互いに同期されていない場合、フレームワークはもう一方が実行している間に 1 つを呼び出すことができます。

自動同期によってコールバック関数が一度に 1 つずつ呼び出されるため、ドライバーがフレームワークの自動同期を使用する場合、この問題を回避するのは容易です。

ドライバーがフレームワークの自動同期を使用していない場合は、フレームワーク ロックを使用してキャンセルコードと完了コードを同期できます。

ドライバーがフレームワークの自動同期を使用するか、独自の同期を提供するかにかかわらず、ドライバーの EvtRequestCancel コールバック関数は、要求を取り消すために WdfRequestComplete を呼び出す必要があります。 ドライバーの EvtInterruptDpc コールバック関数は、次のように WdfRequestUnmarkCancelable を呼び出す必要があります。

Status = WdfRequestUnmarkCancelable(Request);
if( Status != STATUS_CANCELLED ) {
    WdfRequestComplete(Request, RequestStatus);
    }

このコードは、ドライバーが要求を取り消すために既に呼び出している場合、要求を完了するために WdfRequestComplete を呼び出さないことを確認します。

ドライバーが WdfRequestUnmarkCancelable を呼び出すときに従う必要がある規則については、「WdfRequestUnmarkCancelable」を参照してください。