Control de una solicitud de IRP_MN_SURPRISE_REMOVAL
El administrador de PnP de Windows 2000 y versiones posteriores envía este IRP para notificar a los controladores que un dispositivo ya no está disponible para las operaciones de E/S y probablemente se haya quitado inesperadamente de la máquina ("eliminación sorpresa").
El administrador de PnP envía una solicitud de IRP_MN_SURPRISE_REMOVAL por los siguientes motivos:
Si el bus tiene una notificación de conexión activa, notifica al controlador de autobús primario del dispositivo que el dispositivo ha desaparecido. El controlador de autobús llama a IoInvalidateDeviceRelations. En respuesta, el administrador de PnP consulta al controlador de bus para sus elementos secundarios (IRP_MN_QUERY_DEVICE_RELATIONS para BusRelations). El administrador de PnP determina que el dispositivo no está en la nueva lista de elementos secundarios e inicia sus operaciones de eliminación sorpresa para el dispositivo.
El bus se enumera por otra razón y el dispositivo eliminado sorpresa no se incluye en la lista de elementos secundarios. El administrador de PnP inicia sus operaciones de eliminación sorpresa.
El controlador de función para el dispositivo determina que el dispositivo ya no está presente (porque, por ejemplo, sus solicitudes agotan repetidamente el tiempo de espera). Es posible que el bus sea enumerable, pero no tiene notificación de conexión activa. En este caso, el controlador de función llama a IoInvalidateDeviceState. En respuesta, el administrador de PnP envía una solicitud de IRP_MN_QUERY_PNP_DEVICE_STATE a la pila de dispositivos. El controlador de función establece la marca PNP_DEVICE_FAILED en la máscara de bits PNP_DEVICE_STATE que indica que el dispositivo ha producido un error.
La pila de controladores completa correctamente una solicitud de IRP_MN_STOP_DEVICE pero, a continuación, produce un error en una solicitud de IRP_MN_START_DEVICE posterior. En tales casos, es probable que el dispositivo todavía esté conectado.
Todos los controladores PnP deben controlar este IRP y deben establecer Irp-IoStatus.Status> en STATUS_SUCCESS. Un controlador para un dispositivo PnP debe estar preparado para controlar IRP_MN_SURPRISE_REMOVAL en cualquier momento después de llamar a la rutina AddDevice del controlador. El control adecuado del IRP permite que los controladores y el administrador de PnP:
Deshabilite el dispositivo, en caso de que todavía esté conectado.
Si la pila de controladores completó correctamente una solicitud de IRP_MN_STOP_DEVICE pero, por algún motivo, produjo un error en una solicitud de IRP_MN_START_DEVICE posterior, el dispositivo debe estar deshabilitado.
Libere los recursos de hardware asignados al dispositivo y haga que estén disponibles para otro dispositivo.
Tan pronto como un dispositivo ya no esté disponible, sus recursos de hardware deben liberarse. Después, el administrador de PnP puede reasignar los recursos a otro dispositivo, incluido el mismo dispositivo, que un usuario podría volver a conectar de nuevo a la máquina.
Minimice el riesgo de pérdida de datos e interrupciones del sistema.
Los dispositivos que admiten la conexión activa y sus controladores deben diseñarse para controlar la eliminación sorpresa. Los usuarios esperan poder quitar dispositivos que admitan el acoplamiento frecuente en cualquier momento.
El administrador de PnP envía un IRP_MN_SURPRISE_REMOVAL en IRQL = PASSIVE_LEVEL en el contexto de un subproceso del sistema.
El administrador de PnP envía este IRP a los controladores antes de notificar a las aplicaciones en modo de usuario y otros componentes del modo kernel. Una vez completado el IRP, el administrador de PnP envía una notificación EventCategoryTargetDeviceChange con GUID_TARGET_DEVICE_REMOVE_COMPLETE a los componentes en modo kernel registrados para dicha notificación en el dispositivo.
La IRP_MN_SURPRISE_REMOVAL IRP se controla primero por el controlador superior de la pila de dispositivos y, a continuación, por cada controlador inferior siguiente.
En respuesta a IRP_MN_SURPRISE_REMOVAL, un controlador debe hacer lo siguiente en el orden indicado:
Determine si se ha quitado el dispositivo.
El controlador siempre debe intentar determinar si el dispositivo sigue conectado. Si es así, el controlador debe intentar detener el dispositivo y deshabilitarlo.
Libere los recursos de hardware del dispositivo (interrupciones, puertos de E/S, registros de memoria y canales DMA).
En un conductor de autobús primario, apague la ranura del autobús si el conductor es capaz de hacerlo. Llame a PoSetPowerState para notificar al administrador de energía. Para obtener más información, consulte Administración de energía.
Evite las nuevas operaciones de E/S en el dispositivo.
Un controlador debe procesar las solicitudes de IRP_MJ_CLEANUP, IRP_MJ_CLOSE, IRP_MJ_POWER y IRP_MJ_PNP posteriores, pero el controlador debe evitar las nuevas operaciones de E/S. Un controlador debe producir un error en los IRP posteriores que el controlador habría controlado si el dispositivo estuviera presente, además de cerrar, limpiar e IRP PnP.
Un controlador puede establecer un bit en la extensión del dispositivo para indicar que el dispositivo se ha quitado por sorpresa. Las rutinas de envío del controlador deben comprobar este bit.
Se produce un error en las solicitudes de E/S pendientes en el dispositivo.
Siga pasando los IRP que el controlador no controla para el dispositivo.
Deshabilite las interfaces de dispositivo con IoSetDeviceInterfaceState.
Limpie cualquier asignación, memoria, eventos u otros recursos del sistema específicos del dispositivo.
Un controlador podría posponer dicha limpieza hasta que reciba la solicitud de IRP_MN_REMOVE_DEVICE posterior, pero si un componente heredado tiene un identificador abierto que no se puede cerrar, nunca se enviará el IRP de eliminación.
Deje el objeto de dispositivo conectado a la pila de dispositivos.
No desasocie y elimine el objeto de dispositivo hasta la solicitud de IRP_MN_REMOVE_DEVICE posterior.
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.
Propaga el estado de IoCallDriver como estado devuelto de la rutina DispatchPnP .
No complete el IRP.
En un controlador de autobús (que controla este IRP para un PDO secundario):
Establezca Irp-IoStatus.Status> en STATUS_SUCCESS.
Complete el IRP (IoCompleteRequest) con IO_NO_INCREMENT.
Vuelva de la rutina DispatchPnP .
Una vez que este IRP se realiza correctamente y se cierran todos los identificadores abiertos en el dispositivo, el administrador de PnP envía una solicitud de IRP_MN_REMOVE_DEVICE a la pila de dispositivos. En respuesta a la eliminación de IRP, los controladores desasocian sus objetos de dispositivo de la pila y los eliminan. Si un componente heredado tiene un identificador abierto al dispositivo y deja abierto el identificador a pesar de los errores de E/S, el administrador de PnP nunca envía el IRP de eliminación.
Todos los controladores deben controlar este IRP y deben tener en cuenta que el dispositivo se ha quitado físicamente de la máquina. Sin embargo, algunos controladores no provocarán resultados adversos si no controlan el IRP. Por ejemplo, un dispositivo que no consume recursos de hardware del sistema y reside en un bus basado en protocolos, como USB o 1394, no puede vincular recursos de hardware porque no consume ninguno. No hay ningún riesgo de que los controladores intenten acceder al dispositivo después de que se haya quitado porque la función y los controladores de filtro acceden al dispositivo solo a través del controlador de bus primario. Dado que el bus admite la notificación de eliminación, se notifica al controlador de autobús primario cuando el dispositivo desaparece y el controlador de autobús produce un error en todos los intentos posteriores de acceder al dispositivo.
En Windows 98/Me, el administrador de PnP no envía este IRP. Si un usuario quita un dispositivo sin usar primero la interfaz de usuario adecuada, el administrador de PnP envía solo una solicitud de IRP_MN_REMOVE_DEVICE a los controladores del dispositivo. Todos los controladores WDM deben controlar IRP_MN_SURPRISE_REMOVAL y IRP_MN_REMOVE_DEVICE. El código de IRP_MN_REMOVE_DEVICE debe comprobar si el controlador recibió un IRP de eliminación sorpresa anterior y debe controlar ambos casos.
Uso de GUID_REENUMERATE_SELF_INTERFACE_STANDARD
La interfaz de GUID_REENUMERATE_SELF_INTERFACE_STANDARD permite que un controlador solicite que su dispositivo se vuelva aumer.
Para usar esta interfaz, envíe un IRP de IRP_MN_QUERY_INTERFACE al controlador de autobús con InterfaceType = GUID_REENUMERATE_SELF_INTERFACE_STANDARD. El controlador de bus proporciona un puntero a una estructura de REENUMERATE_SELF_INTERFACE_STANDARD que contiene punteros a las rutinas individuales de la interfaz. Una rutina ReenumerateSelf solicita que un controlador de autobús vuelva a enumerar un dispositivo secundario.
Acerca de PNP_DEVICE_STATE
El tipo PNP_DEVICE_STATE es una máscara de bits que describe el estado PnP de un dispositivo. Un controlador devuelve un valor de este tipo en respuesta a una solicitud de IRP_MN_QUERY_PNP_DEVICE_STATE .
typedef ULONG PNP_DEVICE_STATE, *PPNP_DEVICE_STATE;
Los bits de marca de un valor de PNP_DEVICE_STATE se definen de la siguiente manera.
Bit de marca | Descripción |
---|---|
PNP_DEVICE_DISABLED | El dispositivo está presente físicamente, pero está deshabilitado en el hardware. |
PNP_DEVICE_DONT_DISPLAY_IN_UI | No muestre el dispositivo en la interfaz de usuario. Se establece para un dispositivo que está físicamente presente pero no utilizable en la configuración actual, como un puerto de juego en un portátil que no se puede usar cuando el portátil está desacoplar. (Vea también la marca NoDisplayInUI en la estructura DEVICE_CAPABILITIES ). |
PNP_DEVICE_FAILED | El dispositivo está presente pero no funciona correctamente. Cuando se establece esta marca y PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED, el dispositivo debe detenerse antes de que el administrador de PnP asigne nuevos recursos de hardware (no se admite el reequilibrio sin escalas para el dispositivo). |
PNP_DEVICE_NOT_DISABLEABLE | El dispositivo es necesario cuando se inicia el equipo. Este dispositivo no debe estar deshabilitado. Un controlador establece este bit para un dispositivo necesario para el funcionamiento adecuado del sistema. Por ejemplo, si un controlador recibe una notificación de que un dispositivo está en la ruta de acceso de paginación (IRP_MN_DEVICE_USAGE_NOTIFICATION para DeviceUsageTypePaging), el controlador llama a IoInvalidateDeviceState y establece esta marca en la solicitud de IRP_MN_QUERY_PNP_DEVICE_STATE resultante. Si este bit se establece para un dispositivo, el administrador de PnP propaga esta configuración al dispositivo primario del dispositivo, el dispositivo primario de su elemento primario, etc. Si este bit se establece para un dispositivo enumerado por raíz, el dispositivo no se puede deshabilitar ni desinstalar. |
PNP_DEVICE_REMOVED | El dispositivo se ha quitado físicamente. |
PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED | Los requisitos de recursos para el dispositivo han cambiado. Normalmente, un controlador de bus establece esta marca cuando ha determinado que debe expandir sus requisitos de recursos para enumerar un nuevo dispositivo secundario. |
PNP_DEVICE_DISCONNECTED | El controlador de dispositivo se carga, pero este controlador ha detectado que el dispositivo ya no está conectado al equipo. Normalmente, esta marca se usa para los controladores de función que se comunican con dispositivos inalámbricos. Por ejemplo, la marca se establece cuando el dispositivo se mueve fuera del intervalo y se borra después de que el dispositivo vuelva al intervalo y vuelva a conectarse. Normalmente, un controlador de autobús no establece esta marca. En su lugar, el controlador de bus debe dejar de enumerar el dispositivo secundario si el dispositivo ya no está conectado. Esta marca solo se usa si el controlador de función administra la conexión. El único propósito de esta marca es informar a los clientes de si el dispositivo está conectado. Establecer la marca no afecta a si se carga el controlador. |
El administrador de PnP consulta el PNP_DEVICE_STATE de un dispositivo justo después de iniciar el dispositivo mediante el envío de una solicitud de IRP_MN_QUERY_PNP_DEVICE_STATE a la pila de dispositivos. En respuesta a este IRP, los controladores del dispositivo establecen las marcas adecuadas en PNP_DEVICE_STATE.
Si alguna de las características de estado cambia después de la consulta inicial, un controlador notifica al administrador de PnP mediante una llamada a IoInvalidateDeviceState. En respuesta a una llamada a IoInvalidateDeviceState, el administrador de PnP consulta de nuevo la PNP_DEVICE_STATE del dispositivo.
Si un dispositivo está marcado PNP_DEVICE_NOT_DISABLEABLE, el depurador muestra una marca de usuario DNUF_NOT_DISABLEABLE para el devnode. El depurador también muestra un valor DisableableDepends que cuenta el número de motivos por los que el dispositivo no se puede deshabilitar. Este valor es la suma de X+Y, donde X es una si el dispositivo no se puede deshabilitar y Y es el recuento de los dispositivos secundarios del dispositivo que no se pueden deshabilitar.