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を返します。 それ以外の場合、このメソッドは次のいずれかの値を返す可能性があります。
リターン コード | 説明 |
---|---|
|
I/O 要求が取り消されました。 詳細については、「解説」を参照してください。 |
|
|
このメソッドは、他の NTSTATUS 値も返す場合があります。
ドライバーが無効なオブジェクト ハンドルを提供すると、バグ チェックが発生します。
注釈
ドライバーがフレームワークから I/O 要求を受信した 後、ドライバーは WdfRequestMarkCancelable を呼び出すか、KMDF バージョン 1.9 以降の WdfRequestMarkCancelableEx を呼び出して要求を取り消すことができます。 2 つのメソッドの選択方法については、「 WdfRequestMarkCancelable」を参照してください。
WdfRequestMarkCancelableEx を呼び出すとき、ドライバーは EvtRequestCancel コールバック関数を指定する必要があります。 I/O マネージャーまたは別のドライバーが I/O 要求を取り消そうとしている場合、フレームワークはコールバック関数を呼び出します。
WdfRequestMarkCancelableEx がエラーを返した場合、ドライバーは EvtRequestCancel コールバック関数が実行するのと同じキャンセル アクティビティを実行する必要があります。 例:
- 作成した可能性のあるサブ要求と共に、要求の処理を完了または停止します。
- STATUS_CANCELLEDの状態値を指定して、 WdfRequestComplete を呼び出します。
WdfRequestMarkCancelableEx はEvtRequestCancel を呼び出さないため、このメソッドは、「WdfRequestMarkCancelable の備考」で説明されているデッドロック リスクから安全です。
キャンセルを有効にした後の要求の処理
ドライバーが WdfRequestMarkCancelableEx を呼び出して取り消しを有効にした後、ドライバーが WdfRequestUnmarkCancelable を呼び出さない限り、ドライバーが要求オブジェクトを所有している間、要求はキャンセル可能なままになります。ドライバーが WdfRequestMarkCancelableEx を呼び出し、ドライバーの EvtRequestCancel コールバック関数が実行されず、WdfRequestComplete を呼び出した場合、ドライバーは EvtRequestCancel コールバック関数の外部で WdfRequestComplete を呼び出す前に WdfRequestUnmarkCancelable を呼び出す必要があります。
ドライバーが WdfRequestForwardToIoQueue を呼び出して要求を別のキューに転送する場合、次の規則が適用されます。
-
ドライバーが別のキューに転送する場合、I/O 要求を取り消すことはできません。
通常、ドライバーは WdfRequestMarkCancelableEx を呼び出して 、WdfRequestForwardToIoQueue を呼び出す前に要求の取り消しを有効にしないでください。 ドライバーが要求を取り消し可能にする場合は、WdfRequestForwardToIoQueue を呼び出す前に、WdfRequestUnmarkCancelable を呼び出してキャンセルを無効にする必要があります。
-
要求が 2 番目のキューにある間、フレームワークはそれを所有し、ドライバーに通知せずに取り消すことができます。
ドライバーがキャンセル通知を必要とする場合 ( WdfRequestForwardToIoQueue を呼び出す前に割り当てたリソースの割り当てを解除できるように)、ドライバーは EvtIoCanceledOnQueue コールバック関数を登録する必要があり、要求固有のコンテキスト メモリを使用して要求のリソースに関する情報を格納する必要があります。
- フレームワークが 2 番目のキューからの要求をデキューし、ドライバーに配信した後、ドライバーは WdfRequestMarkCancelableEx を呼び出してキャンセルを有効にすることができます。
例
次のコード例は、2 つのコールバック関数の一部を示しています。
- 要求固有の作業 (I/O ターゲットに送信するサブ要求の作成など) を実行する EvtIoRead コールバック関数は、受信した I/O 要求の取り消しを有効にします。
- I/O 要求を取り消す EvtRequestCancel コールバック関数。
例 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 |
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) |