次の方法で共有


WdfRequestMarkCancelableEx 関数 (wdfrequest.h)

[KMDF と UMDF に適用]

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

構文

NTSTATUS WdfRequestMarkCancelableEx(
  [in] WDFREQUEST             Request,
  [in] PFN_WDF_REQUEST_CANCEL EvtRequestCancel
);

パラメーター

[in] Request

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

[in] EvtRequestCancel

ドライバー定義 EvtRequestCancel コールバック関数へのポインター。フレームワークは、I/O 要求を取り消すと呼び出します。

戻り値

WdfRequestMarkCancelableEx は、指定された I/O 要求の取り消しが正常に有効にされた場合にSTATUS_SUCCESSを返します。 それ以外の場合、このメソッドは次のいずれかの値を返す可能性があります。

リターン コード 形容
STATUS_CANCELLED
I/O 要求が取り消されました。 詳細については、「解説」を参照してください。
STATUS_INVALID_DEVICE_REQUEST
  • ドライバーは I/O 要求を所有していません。
  • I/O 要求は既に取り消し可能です。
 

このメソッドは、他の NTSTATUS 値返す場合もあります。

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

備考

ドライバーがフレームワークから I/O 要求 を受け取 後、ドライバーは WdfRequestMarkCancelable 呼び出すか、KMDF バージョン 1.9 以降 WdfRequestMarkCancelableEx を呼び出して要求を取り消すことができます。 2 つの方法の選択については、「WdfRequestMarkCancelable を参照してください。

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

WdfRequestMarkCancelableEx エラーが返された場合、ドライバーは、EvtRequestCancel コールバック関数が実行するのと同じキャンセル アクティビティを実行する必要があります。 例えば:

  1. 作成した可能性のあるサブ要求と共に、要求の処理を完了または停止します。
  2. STATUS_CANCELLEDの状態値 指定して、WdfRequestCompleteを呼び出します。
実装については、以下のコード例を参照してください。

WdfRequestMarkCancelableEx EvtRequestCancel 呼び出すことはありませんので、このメソッドは、WdfRequestMarkCancelableの解説で説明されているデッドロック リスクから安全です。

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

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

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

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

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

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

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

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

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

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

  • 要求固有の処理 (I/O ターゲットに送信するサブ要求の作成など) を実行する EvtIoRead コールバック関数は、受信した I/O 要求の取り消しを有効にします。
  • EvtRequestCancel I/O 要求を取り消すコールバック関数です。
最初の例では、ドライバーはフレームワークの 自動同期を使用しています。 2 番目の例では、ドライバーはスピンロックを使用して独自の同期を提供しています。

例 1: 自動同期を使用するドライバー。

VOID
MyEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
...
    NTSTATUS status;
...
    // Perform request-specific work here
    // (such as creating subrequests 
    // to send to an I/O target). 
...
    status = WdfRequestMarkCancelableEx(
                                        Request,
                                        MyEvtRequestCancel
                                        );

    if (!NT_SUCCESS(status)) {
       // Remove request-specific work here, because
       // we don't want the work to be done if the
       // request was canceled or an error occurred.

        WdfRequestComplete (Request, status);
    }
...
}

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
                       );
}

例 2: 独自の同期を使用するドライバー。

VOID
MyEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
...
    NTSTATUS status;
...
    WdfSpinlockAcquire(MyCancelSpinLock);
    // Perform request-specific work here
    // (such as creating subrequests 
    // to send to an I/O target). 
...
    status = WdfRequestMarkCancelableEx(
                                        Request,
                                        MyEvtRequestCancel
                                        );

    if (!NT_SUCCESS(status)) {
        // Remove request-specific work here, because
        // we don't want the work to be done if the
        // request was canceled or an error occurred.
     }
    WdfSpinlockRelease(MyCancelSpinLock);
    if (!NT_SUCCESS(status)) {
        WdfRequestComplete (
                            Request,
                            Status
                            );
    }
...
}
VOID
MyEvtRequestCancel(
    IN WDFREQUEST  Request
 )
{
    WdfSpinlockAcquire(MyCancelSpinLock);
    // Remove request-specific work here, because
    // we don't want the work to be done if the
    // request was canceled.
    WdfSpinlockRelease(MyCancelSpinLock);
    WdfRequestComplete (Request, STATUS_CANCELLED);
}

必要条件

要件 価値
ターゲット プラットフォーム 万国
最小 KMDF バージョン 1.9
UMDF の最小バージョン する 2.0
ヘッダー wdfrequest.h (Wdf.h を含む)
ライブラリ Wdf01000.sys (KMDF);WUDFx02000.dll (UMDF)
IRQL <=DISPATCH_LEVEL
DDI コンプライアンス規則 する DeferredRequestCompleted(kmdf), DriverCreate(kmdf), EvtIoStopCancel(kmdf), InvalidReqAccess(kmdf) ), InvalidReqAccessLocal(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplic MarkCancOnCancReqLocal(kmdf), ReqIsCancOnCancReq(kmdf), ReqMarkCancelableSend() kmdf), ReqNotCanceledLocal(kmdf), RequestCompleted(kmdf), RequestCompletedLocal(kmdf)

関連項目

EvtRequestCancel

WdfRequestComplete

WdfRequestForwardToIoQueue

WdfRequestMarkCancelable

WdfRequestUnmarkCancelable