次の方法で共有


WdfRequestMarkCancelable 関数 (wdfrequest.h)

[KMDF と UMDF に適用]

WdfRequestMarkCancelable メソッドを使用すると、指定した I/O 要求の取り消しが可能になります。

構文

void WdfRequestMarkCancelable(
  [in] WDFREQUEST             Request,
  [in] PFN_WDF_REQUEST_CANCEL EvtRequestCancel
);

パラメーター

[in] Request

フレームワーク要求オブジェクトへのハンドル。

[in] EvtRequestCancel

ドライバー定義の EvtRequestCancel コールバック関数へのポインター。フレームワークが I/O 要求を取り消した場合にフレームワークによって呼び出されます。

戻り値

なし

解説

ドライバーが無効なオブジェクト ハンドルを提供すると、バグ チェックが発生します。

ドライバーがフレームワークから I/O 要求を受信した 後、ドライバーは WdfRequestMarkCancelable を呼び出すか、KMDF バージョン 1.9 以降の WdfRequestMarkCancelableEx を呼び出して要求を取り消すことができます。

WdfRequestMarkCancelable を呼び出すとき、ドライバーは EvtRequestCancel コールバック関数を指定する必要があります。 I/O マネージャーまたは別のドライバーが I/O 要求を取り消そうとしている場合、フレームワークはコールバック関数を呼び出します。

WdfRequestMarkCancelable と WdfRequestMarkCancelableEx の選択

ドライバーがフレームワークの 自動同期を使用している場合、ドライバーは WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出すことができます。

ドライバーが自動同期を使用しない場合は、次の理由で WdfRequestMarkCancelable ではなく WdfRequestMarkCancelableEx を呼び出す必要があります。

  • 指定した要求が既に取り消されている場合、 WdfRequestMarkCancelable は、ドライバーの EvtRequestCancel コールバック関数を呼び出してから、 を返します。 ドライバーが WdfRequestMarkCancelable を呼び出す前にスピンロックを取得し、EvtRequestCancel 内で同じスピンロックを取得しようとすると、同じスレッドが同じスピンロックを 2 回取得しようとしてデッドロックが発生します。
  • ただし、 WdfRequestMarkCancelableEx はEvtRequestCancel を呼び出さないため、このシナリオは発生しません。 要求が既に取り消されている場合、WdfRequestMarkCancelableEx はSTATUS_CANCELLEDを返します。 WdfRequestMarkCancelableEx を呼び出す前にドライバーがスピンロック (IRQL をDISPATCH_LEVELに設定) を取得し、WdfRequestMarkCancelableEx が戻った後にスピンロック (IRQL をPASSIVE_LEVELに設定) を解放した場合、スピンロックが解放される前に EvtRequestCancel コールバック関数は呼び出されません。 したがって、 EvtRequestCancel コールバック関数が同じスピンロックを使用している場合でも、デッドロックは発生しません。

キャンセルを有効にした後の要求の処理

ドライバーが WdfRequestMarkCancelable を呼び出してキャンセルを有効にした後、ドライバーが WdfRequestUnmarkCancelable を呼び出さない限り、ドライバーが要求オブジェクトを所有している間、要求は取り消し可能なままになります。

ドライバーが WdfRequestMarkCancelable を呼び出し、ドライバーの EvtRequestCancel コールバック関数が実行されておらず、WdfRequestComplete を呼び出していない場合、ドライバーは EvtRequestCancel コールバック関数の外部で WdfRequestComplete を呼び出す前に WdfRequestUnmarkCancelable を呼び出す必要があります。

ドライバーが WdfRequestForwardToIoQueue を呼び出して要求を別のキューに転送する場合、次の規則が適用されます。

  • ドライバーが別のキューに転送する場合、I/O 要求を取り消すことはできません。

    通常、ドライバーは WdfRequestMarkCancelable を呼び出して 、WdfRequestForwardToIoQueue を呼び出す前に要求の取り消しを有効にしないでください。 ドライバーが要求を取り消し可能にする場合は、WdfRequestForwardToIoQueue を呼び出す前に、WdfRequestUnmarkCancelable を呼び出してキャンセルを無効にする必要があります。

  • 要求が 2 番目のキューにある間、フレームワークはそれを所有し、ドライバーに通知せずに取り消すことができます。

    ドライバーがキャンセル通知を必要とする場合 ( WdfRequestForwardToIoQueue を呼び出す前に割り当てたリソースの割り当てを解除できるように)、ドライバーは EvtIoCanceledOnQueue コールバック関数を登録する必要があり、要求固有のコンテキスト メモリを使用して要求のリソースに関する情報を格納する必要があります。

  • フレームワークが 2 番目のキューからの要求をデキューし、ドライバーに配信した後、ドライバーは WdfRequestMarkCancelable を呼び出してキャンセルを有効にすることができます。
WdfRequestMarkCancelable の詳細については、「I/O 要求の取り消し」を参照してください。

次のコード例は、2 つのコールバック関数の一部を示しています。

  • 要求固有の作業 (I/O ターゲットに送信するサブ要求の作成など) を実行する EvtIoRead コールバック関数は、受信した I/O 要求の取り消しを有効にします。
  • I/O 要求を取り消す EvtRequestCancel コールバック関数。
ドライバーは、フレームワークの 自動同期を使用する必要があります。
VOID
MyEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
...
    // Perform request-specific work here
    // (such as creating subrequests 
    // to send to an I/O target). 
...
    WdfRequestMarkCancelable(
                             Request,
                             MyEvtRequestCancel
                             );
    }
...
}
VOID
MyEvtRequestCancel(
    IN WDFREQUEST  Request
    )
{
    // Remove request-specific work here, because
    // we don't want the work to be done if the
    // request was canceled.

    WdfRequestComplete(
                       Request,
                       STATUS_CANCELLED
                       );
}

要件

要件
対象プラットフォーム ユニバーサル
最小 KMDF バージョン 1.0
最小 UMDF バージョン 2.0
Header wdfrequest.h (Wdf.h を含む)
Library Wdf01000.sys (KMDF);WUDFx02000.dll (UMDF)
IRQL <=DISPATCH_LEVEL
DDI コンプライアンス規則 DeferredRequestCompleted(kmdf), DriverCreate(kmdf), EvtIoStopCancel(kmdf), InvalidReqAccess(kmdf), InvalidReqAccessLocal(kmdf), KmdfIrql(kmdf)KmdfIrql2(kmdf)、KmdfIrqlExplicit(kmdf)、 MarkCancOnCancReqLocal(kmdf)ReqIsCancOnCancReqReq(kmdf)ReqMarkCancelableSend(kmdf)ReqNotCanceledLocal(kmdf)RequestCompleted(kmdf)RequestCompletedLocal(kmdf)

こちらもご覧ください

EvtRequestCancel

WdfRequestComplete

WdfRequestForwardToIoQueue

WdfRequestMarkCancelableEx

WdfRequestUnmarkCancelable