Sincronización del código de cancelación y finalización
Si el controlador llama a WdfRequestMarkCancelable o WdfRequestMarkCancelableEx para que se pueda cancelar una solicitud de E/S, es posible que se produzca un problema de sincronización. Por ejemplo, el controlador y el dispositivo pueden realizar operaciones de E/S de dispositivo de forma asincrónica mediante las funciones de devolución de llamada EvtInterruptIsr y EvtInterruptDpc y EvtRequestCancel pueden contener llamadas a WdfRequestComplete.
El controlador debe llamar a WdfRequestComplete solo una vez, para completar o cancelar la solicitud. Pero si las funciones de devolución de llamada EvtInterruptDpc y EvtRequestCancel no se sincronizan entre sí, el marco puede llamar a uno mientras se ejecuta el otro.
Evitar este problema es fácil si el controlador usa la sincronización automática del marco, ya que la sincronización automática garantiza que se llamará a las funciones de devolución de llamada de una en una.
Si el controlador no usa la sincronización automática del marco, puede usar bloqueos de marco para sincronizar el código de cancelación y finalización.
Tanto si el controlador usa la sincronización automática del marco como si proporciona su propia sincronización, la función de devolución de llamada EvtRequestCancel del controlador debe llamar a WdfRequestComplete para cancelar una solicitud. La función de devolución de llamada EvtInterruptDpc del controlador debe llamar a WdfRequestUnmarkCancelable de la siguiente manera:
Status = WdfRequestUnmarkCancelable(Request);
if( Status != STATUS_CANCELLED ) {
WdfRequestComplete(Request, RequestStatus);
}
Este código garantiza que el controlador no llame a WdfRequestComplete para completar la solicitud si el controlador ya lo ha llamado para cancelar la solicitud.
Para obtener más información sobre las reglas que el controlador debe seguir cuando llama a WdfRequestUnmarkCancelable, vea WdfRequestUnmarkCancelable.