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。 否則,這個方法可能會傳回下列其中一個值:
傳回碼 | Description |
---|---|
|
I/O 要求已取消。 如需詳細資訊,請參閱。 |
|
|
這個方法也可能傳回其他 NTSTATUS值。
如果驅動程式提供無效的物件句柄,就會發生錯誤檢查。
備註
驅動程式從架構 收到 I/O 要求 之後,驅動程式可以呼叫 WdfRequestMarkCancelable ,或從 KMDF 1.9 版開始, WdfRequestMarkCancelableEx 來取消要求。 如需在兩種方法之間選擇的資訊,請參閱 WdfRequestMarkCancelable。
呼叫 WdfRequestMarkCancelableEx 時,您的驅動程式必須指定 EvtRequestCancel 回呼函式。 如果 I/O 管理員或其他驅動程式嘗試取消 I/O 要求,架構會呼叫回呼函式。
如果 WdfRequestMarkCancelableEx 傳回失敗,驅動程式必須執行 EvtRequestCancel 回呼函式執行的相同取消活動。 例如:
- 完成或停止處理要求,以及可能已建立的子查詢。
- 呼叫 WdfRequestComplete,並指定狀態值STATUS_CANCELLED。
因為 WdfRequestMarkCancelableEx 絕不會呼叫 EvtRequestCancel,所以此方法安全無虞,不受 WdfRequestMarkCancelable 備註中所述的死結風險。
啟用取消之後處理要求
驅動程式呼叫 WdfRequestMarkCancelableEx 以啟用取消之後,除非驅動程式呼叫 WdfRequestUnmarkCancelable,否則要求仍可取消,而驅動程式擁有要求物件。如果驅動程式已呼叫 WdfRequestMarkCancelableEx,而且驅動程式的 EvtRequestCancel 回呼函式尚未執行並呼叫 WdfRequestComplete,則驅動程式必須在呼叫 WdfRequestUnmarkCancelable 之前呼叫 WdfRequestComplete,再呼叫 EvtRequestCancel 回呼函式以外的 WdfRequestComplete。
如果驅動程式呼叫 WdfRequestForwardToIoQueue 以將要求轉送至不同的佇列,則適用下列規則:
-
當驅動程式將其轉送至不同的佇列時,無法取消 I/O 要求。
一般而言,您的驅動程式不應該呼叫 WdfRequestMarkCancelableEx ,在呼叫 WdfRequestForwardToIoQueue 之前啟用取消要求。 如果驅動程式確實將要求設為可取消,它必須呼叫 WdfRequestUnmarkCancelable 才能停用取消,再呼叫 WdfRequestForwardToIoQueue。
-
當要求位於第二個佇列中時,架構會擁有它,而且可以在不通知驅動程序的情況下取消它。
如果驅動程式需要取消通知 (,讓它可以在呼叫 WdfRequestForwardToIoQueue) 之前解除分配它可能配置的任何資源,驅動程式應該註冊 EvtIoCanceledOnQueue 回呼函式,而且應該使用要求特定的內容記憶體來儲存要求資源的相關信息。
- 在架構從第二個佇列中清除要求並傳遞至驅動程序之後,驅動程式可以呼叫 WdfRequestMarkCancelableEx 以啟用取消。
範例
下列程式代碼範例顯示兩個回呼函式的一部分:
- EvtIoRead 回呼函式,可執行要求特定工作 (,例如建立子佇列以傳送至 I/O 目標) ,然後啟用已接收 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);
}
規格需求
需求 | 值 |
---|---|
目標平台 | Universal |
最低 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) 、 KmdfIrqlExplicit (kmdf ) , MarkCancOnCancReqLocal (kmdf) 、 ReqIsCancOnCancReq (kmdf) 、 ReqMarkCancelableSend (kmdf ) 、 ReqNotCanceledLocal (kmdf) 、 RequestCompleted (kmdf) 、 RequestCompletedLocal (kmdf) |