同步取消和完成代码

如果驱动程序调用 WdfRequestMarkCancelableWdfRequestMarkCancelableEx 以使 I/O 请求可取消,则可能存在同步问题。 例如,驱动程序和设备可能通过 EvtInterruptIsrEvtInterruptDpc 回调函数异步执行设备 I/O 操作, EvtInterruptDpcEvtRequestCancel 回调函数可能包含对 WdfRequestComplete 的调用。

驱动程序必须仅调用 WdfRequestComplete 一次,才能完成或取消请求。 但是,如果 EvtInterruptDpcEvtRequestCancel 回调函数彼此不同步,框架可以在另一个正在执行时调用其中一个。

如果驱动程序使用框架的 自动同步,则避免此问题很容易,因为自动同步可确保一次调用一个回调函数。

如果驱动程序不使用框架的自动同步,则可以使用 框架锁 来同步取消和完成代码。

无论驱动程序是使用框架的自动同步还是提供自己的同步,驱动程序的 EvtRequestCancel 回调函数都必须调用 WdfRequestComplete 来取消请求。 驱动程序的 EvtInterruptDpc 回调函数应调用 WdfRequestUnmarkCancelable ,如下所示:

Status = WdfRequestUnmarkCancelable(Request);
if( Status != STATUS_CANCELLED ) {
    WdfRequestComplete(Request, RequestStatus);
    }

如果驱动程序已调用 WdfRequestComplete 来取消请求,则此代码可确保驱动程序不会调用 WdfRequestComplete 来完成请求。

有关驱动程序在调用 WdfRequestUnmarkCancelable 时必须遵循的规则的详细信息,请参阅 WdfRequestUnmarkCancelable