WdfRequestUnmarkCancelable 函数 (wdfrequest.h)
[适用于 KMDF 和 UMDF]
WdfRequestUnmarkCancelable 方法禁用取消指定的 I/O 请求。
语法
NTSTATUS WdfRequestUnmarkCancelable(
[in] WDFREQUEST Request
);
参数
[in] Request
框架请求对象的句柄。
返回值
如果操作成功,WdfRequestUnmarkCancelable 将返回STATUS_SUCCESS。 否则,此方法可能会返回以下值之一:
返回代码 | 说明 |
---|---|
|
输入参数无效或请求已不可取消。 |
|
驱动程序不拥有请求。 |
|
请求已取消。 |
此方法还可能返回其他 NTSTATUS 值。
如果驱动程序提供无效的对象句柄,则会发生 bug 检查。
注解
如果驱动程序以前调用 WdfRequestMarkCancelable 或 WdfRequestMarkCancelable 以启用请求取消,则驱动程序可以调用 WdfRequestUnmarkCancelable 来禁用取消 I/O 请求。
如果 WdfRequestUnmarkCancelable 返回STATUS_CANCELLED以外的值,则不会为请求调用驱动程序的 EvtRequestCancel 回调函数。
如果驱动程序以前名为 WdfRequestMarkCancelable 或 WdfRequestMarkCancelableEx,则驱动程序的 EvtRequestCancel 回调函数可以使用 status 参数 STATUS_CANCELLED 调用 WdfRequestComplete。 EvtRequestCancel 回调函数不必调用 WdfRequestUnmarkCancelable。 如果驱动程序在其 EvtRequestCancel 回调函数外部调用 WdfRequestComplete,则驱动程序必须首先调用 WdfRequestUnmarkCancelable。
但是,在 EvtRequestCancel 调用 WdfRequestComplete 后,驱动程序不得调用 WdfRequestUnmarkCancelable。 在以下示例部分中,该示例存储请求句柄的本地副本,然后在 EvtRequestCancel 回调函数调用 WdfRequestComplete 时清除该副本。 如果已清除请求句柄的本地副本,驱动程序不会调用 WdfRequestUnmarkCancelable 。 此示例使用框架的 自动同步 来同步回调函数。
请注意,调用 WdfObjectReference 以添加对请求对象的附加引用不会使驱动程序在驱动程序的 EvtRequestCancel 回调函数调用 WdfRequestComplete 之后调用 WdfRequestUnmarkCancelable。
如果 WdfRequestUnmarkCancelable 返回STATUS_CANCELLED,然后 EvtRequestCancel 完成请求,则驱动程序随后不得使用请求对象。
如果 WdfRequestUnmarkCancelable 返回STATUS_CANCELLED,则驱动程序在框架调用 EvtRequestCancel 之前不得完成请求。 否则,框架可能会使用无效请求调用驱动程序的 EvtRequestCancel 。 有关相关代码示例,请参阅 IWDFIoRequest::UnmarkCancelable。
有关 WdfRequestUnmarkCancelable 的详细信息,请参阅 取消 I/O 请求。
示例
下面的代码示例提供了 ECHO 示例驱动程序包含的 EvtIoRead、EvtRequestCancel 和 EvtTimerFunc 回调函数的简化版本。 此示例演示如何在使用框架自动同步的驱动程序中调用 WdfRequestMarkCancelable、WdfRequestUnmarkCancelable 和 WdfRequestComplete。 (ECHO 示例使用设备级 synchronization.)
如果驱动程序不使用框架的自动同步,请参阅 IWDFIoRequest::UnmarkCancelable 上的两个示例。 在为 UMDF 驱动程序编写时,这些示例演示了可用于管理取消回调与另一个调用 Unmark 例程的线程之间的同步的技术。
VOID
EchoEvtIoRead(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
PQUEUE_CONTEXT queueContext = QueueGetContext(Queue);
// Prepare for read operation here.
// (See the Echo sample driver for details.)
...
// Enable cancellation.
WdfRequestMarkCancelable(
Request,
EchoEvtRequestCancel
);
// Save the request handle. We'll clear it after
// we call WdfRequestComplete.
queueContext->CurrentRequest = Request;
return
}
VOID
EchoEvtRequestCancel(
IN WDFREQUEST Request
)
{
PQUEUE_CONTEXT queueContext =
QueueGetContext(WdfRequestGetIoQueue(Request));
WdfRequestComplete(
Request,
STATUS_CANCELLED,
);
// Clear the request handle so EchEvtTimerFunc will
// know that we called WdfRequestComplete.
queueContext->CurrentRequest = NULL;
return;
}
VOID
EchoEvtTimerFunc(
IN WDFTIMER Timer
)
{
NTSTATUS Status;
WDFREQUEST Request;
WDFQUEUE queue;
PQUEUE_CONTEXT queueContext;
// Retrieve our saved copy of the request handle.
queue = WdfTimerGetParentObject(Timer);
queueContext = QueueGetContext(queue);
Request = queueContext->CurrentRequest;
// We cannot call WdfRequestUnmarkCancelable
// after a request completes, so check here to see
// if EchoEvtRequestCancel cleared our saved
// request handle.
if( Request != NULL ) {
Status = WdfRequestUnmarkCancelable(Request);
if(Status != STATUS_CANCELLED) {
queueContext->CurrentRequest = NULL;
Status = queueContext->CurrentStatus;
WdfRequestComplete(
Request,
Status
);
}
}
return;
}
要求
要求 | 值 |
---|---|
目标平台 | 通用 |
最低 KMDF 版本 | 1.0 |
最低 UMDF 版本 | 2.0 |
标头 | wdfrequest.h (包括 Wdf.h) |
Library | Wdf01000.sys (KMDF) ;WUDFx02000.dll (UMDF) |
IRQL | <=DISPATCH_LEVEL |
DDI 符合性规则 | CompleteCanceledReq (kmdf) 、 DeferredRequestCompleted (kmdf) 、 DriverCreate (kmdf) 、 EvtIoStopCancel (kmdf) 、 InvalidReqAccess (kmdf) 、 InvalidReqAccessLocal (kmdf) 、 KmdfIrql (kmdf) 、 KmdfIrql2 (kmdf) 、KmdfIrqlExplicit (kmdf) , MarkCancOnCancReqLocal (kmdf) , ReqIsCancOnCancCancReq (kmdf) , ReqMarkCancelableSend (kmdf) 、 ReqNotCanceledLocal (kmdf) |