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。如果驅動程式不使用自動同步處理,它必須呼叫 WdfRequestMarkCancelableEx ,而不是 WdfRequestMarkCancelable ,原因如下:
- 如果指定的要求已經取消, WdfRequestMarkCancelable 會在傳回之前先呼叫驅動程式的 EvtRequestCancel 回呼函式。 如果驅動程式在呼叫 WdfRequestMarkCancelable 之前取得微調鎖定,並嘗試在 EvtRequestCancel 內取得相同的微調鎖定,則相同的線程會嘗試取得相同的微調鎖定兩次,導致死結。
- 不過,因為 WdfRequestMarkCancelableEx 永遠不會呼叫 EvtRequestCancel,所以不會發生此案例。 如果要求已經取消, WdfRequestMarkCancelableEx 會 傳回STATUS_CANCELLED。 如果您的驅動程式在呼叫 WdfRequestMarkCancelableEx 之前取得微調鎖定 (,這會在 WdfRequestMarkCancelable (Ex 之前將 IRQL 設定為 DISPATCH_LEVEL) PASSIVE_LEVEL) ,則會在 WdfRequestMarkCancelableEx 傳回之前呼叫 EvtRequestCancel 回呼函式。 因此,即使 EvtRequestCancel 回呼函式使用相同的微調鎖定,也不會發生死結。
啟用取消之後處理要求
驅動程式呼叫 WdfRequestMarkCancelable 以啟用取消之後,除非驅動程式呼叫 WdfRequestUnmarkCancelable,否則要求仍可取消,而驅動程式擁有要求物件。如果驅動程式已呼叫 WdfRequestMarkCancelable,而且驅動程式的 EvtRequestCancel 回呼函式尚未執行並呼叫 WdfRequestComplete,則驅動程式必須先呼叫 WdfRequestUnmarkCancelable,再呼叫 EvtRequestCancel 回呼函式以外的 WdfRequestComplete。
如果驅動程式呼叫 WdfRequestForwardToIoQueue 以將要求轉送至不同的佇列,則適用下列規則:
-
當驅動程式將其轉送至不同的佇列時,無法取消 I/O 要求。
一般而言,您的驅動程式不應該呼叫 WdfRequestMarkCancelable 來啟用取消要求,再呼叫 WdfRequestForwardToIoQueue。 如果驅動程式確實將要求設為可取消,它必須呼叫 WdfRequestUnmarkCancelable 才能停用取消,再呼叫 WdfRequestForwardToIoQueue。
-
當要求位於第二個佇列中時,架構會擁有它,而且可以在不通知驅動程序的情況下取消它。
如果驅動程式需要取消通知 (,讓它可以在呼叫 WdfRequestForwardToIoQueue) 之前解除分配它可能配置的任何資源,驅動程式應該註冊 EvtIoCanceledOnQueue 回呼函式,而且應該使用要求特定的內容記憶體來儲存要求資源的相關信息。
- 在架構從第二個佇列中清除要求並傳遞至驅動程序之後,驅動程式可以呼叫 WdfRequestMarkCancelable 來啟用取消。
範例
下列程式代碼範例顯示兩個回呼函式的一部分:
- EvtIoRead 回呼函式,可執行要求特定工作 (,例如建立子佇列以傳送至 I/O 目標) ,然後啟用已接收 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
);
}
規格需求
需求 | 值 |
---|---|
目標平台 | Universal |
最低 KMDF 版本 | 1.0 |
最低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) |