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
STATUS_CANCELLED
I/O 要求已取消。 如需詳細資訊,請參閱。
STATUS_INVALID_DEVICE_REQUEST
  • 驅動程式沒有擁有 I/O 要求。
  • I/O 要求已經可取消。
 

這個方法也可能傳回其他 NTSTATUS值

如果驅動程式提供無效的物件句柄,就會發生錯誤檢查。

備註

驅動程式從架構 收到 I/O 要求 之後,驅動程式可以呼叫 WdfRequestMarkCancelable ,或從 KMDF 1.9 版開始, WdfRequestMarkCancelableEx 來取消要求。 如需在兩種方法之間選擇的資訊,請參閱 WdfRequestMarkCancelable

呼叫 WdfRequestMarkCancelableEx 時,您的驅動程式必須指定 EvtRequestCancel 回呼函式。 如果 I/O 管理員或其他驅動程式嘗試取消 I/O 要求,架構會呼叫回呼函式。

如果 WdfRequestMarkCancelableEx 傳回失敗,驅動程式必須執行 EvtRequestCancel 回呼函式執行的相同取消活動。 例如:

  1. 完成或停止處理要求,以及可能已建立的子查詢。
  2. 呼叫 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 以啟用取消。
如需 WdfRequestMarkCancelableEx 的詳細資訊,請參閱 取消 I/O 要求

範例

下列程式代碼範例顯示兩個回呼函式的一部分:

  • 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)

另請參閱

EvtRequestCancel

WdfRequestComplete

WdfRequestForwardToIoQueue

WdfRequestMarkCancelable

WdfRequestUnmarkCancelable