Controlar una solicitud de IRP_MN_QUERY_STOP_DEVICE (Windows 2000 y versiones posteriores)
El controlador superior de la pila de dispositivos controla primero una solicitud de IRP_MN_QUERY_STOP_DEVICE y, a continuación, cada controlador inferior siguiente. Un controlador controla los IRP de detención en su rutina DispatchPnP .
En respuesta a un IRP_MN_QUERY_STOP_DEVICE, un controlador debe hacer lo siguiente:
Determine si el dispositivo se puede detener y sus recursos de hardware liberados, sin efectos adversos.
Un controlador debe producir un error en un IRP de detención de consulta si se cumple alguna de las siguientes condiciones:
Se ha notificado al controlador (a través de IRP_MN_DEVICE_USAGE_NOTIFICATION) que el dispositivo está en la ruta de acceso de un archivo de paginación, hibernación o volcado de memoria.
No se pueden liberar los recursos de hardware del dispositivo.
Un controlador podría producir un error en un IRP de detención de consulta si se cumple lo siguiente:
El controlador no debe quitar las solicitudes de E/S y no tiene un mecanismo para poner en cola irP.
Mientras el dispositivo está en estado detenido, un controlador debe contener IRP que requieran acceso al dispositivo. Si un controlador no pone en cola los IRP, no debe permitir que el dispositivo se detenga y, por tanto, debe producir un error irP de detención de consulta.
La excepción a esta regla es un dispositivo que puede quitar E/S. Los controladores de este tipo de dispositivo pueden realizar correctamente las solicitudes de detención y detención de consultas sin poner en cola los IRP.
Si el dispositivo no se puede detener, produzca un error en el IRP de detención de consultas.
Establezca Irp-IoStatus.Status> en un estado de error adecuado, llame a IoCompleteRequest con IO_NO_INCREMENT y vuelva de la rutina DispatchPnP del controlador. No pase el IRP al siguiente controlador inferior.
Si el dispositivo se puede detener y los IRP de colas de controladores, establezca la marca de HOLD_NEW_REQUESTS en la extensión del dispositivo para que se ponga en cola los IRP subsiguientes (consulte Mantener los IRP entrantes cuando un dispositivo está en pausa).
Como alternativa, los controladores de un dispositivo pueden aplazar completamente el dispositivo hasta que los controladores reciban la solicitud de IRP_MN_STOP_DEVICE posterior. Sin embargo, estos controladores deben poner en cola las solicitudes que impidan que se realicen inmediatamente correctamente el IRP de detención cuando llegue. Hasta que se reinicie el dispositivo, estos controladores deben poner en cola solicitudes como las siguientes:
IRP_MN_DEVICE_USAGE_NOTIFICATION solicitudes (por ejemplo, para colocar un archivo de paginación en el dispositivo).
Solicitudes de transferencias isócrónicas.
Cree solicitudes que impidan que los controladores realicen correctamente un IRP de detención.
Si el dispositivo no puede tener un IRP en curso, asegúrese de que se hayan completado las solicitudes pendientes que se hayan pasado a otras rutinas de controlador y a controladores inferiores.
Una manera de lograr esto es usar un recuento de referencias y un evento para asegurarse de que se han completado todas las solicitudes:
En su rutina AddDevice , el controlador define un recuento de referencias de E/S en la extensión del dispositivo e inicializa el recuento en uno.
Además, en su rutina AddDevice , el controlador crea un evento con KeInitializeEvent e inicializa el evento en el estado Not-Signaled con KeClearEvent.
Cada vez que procesa un IRP, el controlador incrementa el recuento de referencias con InterlockedIncrement.
Cada vez que completa una solicitud, el controlador disminuye el recuento de referencias con InterlockedDecrement.
El controlador disminuye el recuento de referencias en la rutina IoCompletion , si la solicitud tiene una o justo después de la llamada a IoCallDriver si el controlador no usa ninguna rutina de IoCompletion para la solicitud.
Cuando el controlador recibe un IRP_MN_QUERY_STOP_DEVICE, disminuye el recuento de referencias con InterlockedDecrement. Si no hay solicitudes pendientes, esto reduce el recuento de referencias a cero.
Cuando el recuento de referencias alcanza cero, el controlador establece el evento con KeSetEvent que indica que el código de detención de consulta puede continuar.
Como alternativa al procedimiento anterior, un controlador puede serializar la IRP_MN_QUERY_STOP_DEVICE IRP detrás de cualquier IRP en curso.
Realice los demás pasos necesarios para colocar el dispositivo en el estado stop-pending.
Una vez que un controlador se realiza correctamente en un IRP de detención de consulta, debe estar listo para realizar correctamente una IRP_MN_STOP_DEVICE.
Finalice el IRP.
En una función o un controlador de filtro:
Establezca Irp-IoStatus.Status> en STATUS_SUCCESS.
Configure la siguiente ubicación de pila con IoSkipCurrentIrpStackLocation y pase el IRP al siguiente controlador inferior con IoCallDriver.
Propague el estado de IoCallDriver como estado devuelto de la rutina DispatchPnP .
No complete el IRP.
En un conductor de autobús:
Establezca Irp-IoStatus.Status> en STATUS_SUCCESS.
Sin embargo, si los dispositivos del bus usan recursos de hardware, vuelva a evaluar los requisitos de recursos del bus y los dispositivos secundarios. Si alguno de los requisitos ha cambiado, devuelva STATUS_RESOURCE_REQUIREMENTS_CHANGED en lugar de STATUS_SUCCESS. Este estado indica que el administrador de PnP vuelve a consultar los recursos antes de enviar el IRP de detención.
Complete el IRP (IoCompleteRequest) con IO_NO_INCREMENT.
Vuelva de la rutina DispatchPnP .
Si se produce un error en algún controlador de la pila de dispositivos IRP_MN_QUERY_STOP_DEVICE, el administrador de PnP envía un IRP_MN_CANCEL_STOP_DEVICE a la pila del dispositivo. Esto impide que los controladores requieran una rutina de IoCompletion para un IRP de detención de consultas para detectar si un controlador inferior produjo un error en el IRP.