取り消しと完了のコードの同期化
I/O 要求を取り消し可能にするために、ドライバーで WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出す場合、同期に関する問題が発生する可能性があります。たとえば、ドライバーとデバイスが EvtInterruptIsr と EvtInterruptDpc の各コールバック関数によってデバイスの I/O 操作を非同期で実行する場合に、EvtInterruptDpc と EvtRequestCancel の各コールバック関数の両方に WdfRequestComplete への呼び出しが含まれている場合がこれに該当します。
ドライバーは、要求の完了または取り消しのために、WdfRequestComplete を一度だけ呼び出す必要があります。ただし、EvtInterruptDpc と EvtRequestCancel の各コールバック関数が互いに同期されていない場合、フレームワークが一方の実行中にもう一方を呼び出す可能性があります。
ドライバーでフレームワークの自動同期を使用している場合は、自動同期によってコールバック関数が確実に一度に 1 つだけ呼び出されるようになるため、この問題を簡単に回避できます。
ドライバーでフレームワークの自動同期を使用していない場合は、フレームワークのロックを使用して、取り消しと完了のコードを同期させることができます。
ドライバーでフレームワークの自動同期を使用するか、または独自の同期コードを指定するかにかかわらず、ドライバーの EvtRequestCancel コールバック関数では、WdfRequestComplete を呼び出して要求を取り消す必要があります。ドライバーの EvtInterruptDpc コールバック関数では、次のように指定して WdfRequestUnmarkCancelable を呼び出す必要があります。
Status = WdfRequestUnmarkCancelable(Request);
if( Status != STATUS_CANCELLED ) {
WdfRequestComplete(Request, RequestStatus);
}
ドライバーが既に WdfRequestComplete を呼び出して要求を取り消している場合は、このコードを使用することにより、このメソッドを呼び出して要求を完了することがないようにできます。
WdfRequestUnmarkCancelable の呼び出し時にドライバーが従う必要のある規則の詳細については、WdfRequestUnmarkCancelable を参照してください。