Uso de eliminación de bloqueos
Las rutinas de bloqueo de eliminación proporcionan una manera de realizar un seguimiento del número de operaciones de E/S pendientes en un dispositivo y determinar cuándo es seguro desasociar y eliminar el objeto de dispositivo de un controlador. El sistema proporciona estas rutinas a los escritores de controladores como alternativa a implementar su propio mecanismo de seguimiento.
Un controlador puede usar este mecanismo para dos propósitos:
Para asegurarse de que la rutina DispatchPnP del controlador no complete una solicitud de IRP_MN_REMOVE_DEVICE mientras se mantiene el bloqueo (por ejemplo, mientras que otra rutina de controlador accede al dispositivo).
Para contar el número de motivos por los que el controlador no debe eliminar su objeto de dispositivo y establecer un evento cuando ese recuento va a cero.
Para inicializar un bloqueo de eliminación, un controlador debe asignar una estructura IO_REMOVE_LOCK en su extensión de dispositivo y, a continuación, llamar a IoInitializeRemoveLock. Normalmente, un controlador llama a IoInitializeRemoveLock en su rutina AddDevice, cuando el controlador inicializa el resto de la extensión de dispositivo para un objeto de dispositivo.
El controlador debe llamar a IoAcquireRemoveLock cada vez que inicie una operación de E/S. El controlador debe llamar a IoReleaseRemoveLock cada vez que finalice una operación de E/S. Un controlador puede adquirir el bloqueo más de una vez. Las rutinas de bloqueo de eliminación mantienen un recuento de las adquisiciones pendientes del bloqueo. Cada llamada a IoAcquireRemoveLock incrementa el recuento y IoReleaseRemoveLock disminuye el recuento.
El controlador también debe llamar a IoAcquireRemoveLock cuando pasa una referencia a su código (para temporizadores, DPCs, devoluciones de llamada, etc.). A continuación, el controlador debe llamar a IoReleaseRemoveLock cuando se haya devuelto el evento.
En su código de envío para IRP_MN_REMOVE_DEVICE, el controlador debe adquirir el bloqueo una vez más y, a continuación, llamar a IoReleaseRemoveLockAndWait. Esta rutina no vuelve hasta que se han liberado todas las adquisiciones pendientes del bloqueo. Para permitir que se completen las operaciones de E/S en cola, cada controlador debe llamar a IoReleaseRemoveLockAndWait después de pasar la solicitud de IRP_MN_REMOVE_DEVICE al controlador inferior siguiente y antes de liberar memoria, llama a IoDetachDevice o llama a IoDeleteDevice. Después de llamar a IoReleaseRemoveLockAndWait para un bloqueo de eliminación determinado, se producirá un error en todas las llamadas posteriores a IoAcquireRemoveLock para el mismo bloqueo de eliminación.
Después de que IoReleaseRemoveLockAndWait vuelva, el controlador debe considerar que el dispositivo está en un estado en el que está listo para quitarse y no puede realizar operaciones de E/S. Por lo tanto, el controlador no debe llamar a IoInitializeRemoveLock para volver a inicializar el bloqueo de eliminación. La infracción de esta regla mientras el comprobador de controladores comprueba el controlador producirá una comprobación de errores.
Dado que un controlador almacena una estructura IO_REMOVE_LOCK en la extensión de dispositivo de un objeto de dispositivo, el bloqueo de eliminación se elimina cuando el controlador elimina la extensión del dispositivo mientras procesa una solicitud de IRP_MN_REMOVE_DEVICE .