Gestion d'une requête IRP_MN_QUERY_REMOVE_DEVICE
Le gestionnaire PnP envoie cette IRP pour informer les pilotes qu’un appareil est sur le point d’être supprimé de la machine et de demander si l’appareil peut être supprimé sans interrompre la machine. Il envoie également cet IRP lorsqu’un utilisateur demande de mettre à jour les pilotes pour l’appareil.
Le gestionnaire PnP envoie cet IRP à IRQL PASSIVE_LEVEL dans le contexte d'un thread système.
Il effectue les opérations suivantes avant d’envoyer cet IRP aux pilotes d’un appareil :
Avertit toutes les applications en mode utilisateur inscrites pour la notification sur l’appareil (ou un appareil associé).
Cela inclut les applications qui se sont inscrites pour recevoir une notification sur l'appareil, sur l'un des descendants de l'appareil (appareil enfant, enfant d'enfant, etc.) ou sur l'une des relations de suppression de l'appareil. Une application s’inscrit pour cette notification en appelant CM_Register_Notification ou RegisterDeviceNotification.
En réponse à cette notification, une application se prépare à la suppression de l'appareil (fermeture des poignées de l'appareil) ou fait échouer la requête. Pour plus d'informations sur la manière de gérer ces notifications, reportez-vous à la section Enregistrement pour la notification de l'arrivée d'une interface de périphérique et de la suppression d'un appareil.
Notifie tous les pilotes en mode noyau qui se sont enregistrés pour recevoir une notification sur l'appareil (ou un appareil connexe).
Cela inclut les pilotes qui se sont enregistrés pour recevoir une notification sur l'appareil, sur l'un des descendants de l'appareil ou sur l'une des relations de retrait de l'appareil. Un pilote s’inscrit pour cette notification en appelant IoRegisterPlugPlayNotification avec une catégorie d’événement de EventCategoryTargetDeviceChange.
En réponse à cette notification, le pilote se prépare à la suppression de l'appareil (fermeture des handles de l'appareil) ou rejette la requête.
Il envoie des IRP IRP_MN_QUERY_REMOVE_DEVICE aux pilotes des descendants de l'appareil. Pour plus d’informations sur la façon dont une pile d’appareils gère cet IRP, voir ci-dessous.
(Systèmes Windows 2000 et versions ultérieures) Si un système de fichiers est monté sur l’appareil, le gestionnaire PnP envoie une demande de suppression de requête au système de fichiers et à tous les filtres de système de fichiers. S'il existe des poignées ouvertes sur l'appareil, le système de fichiers échoue généralement à traiter la requête de suppression. En cas d'échec, le système de fichiers verrouille généralement le volume pour empêcher toute création future. Si un système de fichiers monté ne prend pas en charge une demande de suppression de requête, le gestionnaire PnP échoue la demande de suppression de requête pour l’appareil.
Si toutes les étapes ci-dessus réussissent, le gestionnaire PnP envoie le IRP_MN_QUERY_REMOVE_DEVICE aux pilotes de l’appareil.
Une requête IRP_MN_QUERY_REMOVE_DEVICE est gérée en premier par le pilote supérieur de la pile d’appareils, puis par chaque pilote inférieur suivant. Un pilote traite les IRP de suppression dans sa routine DispatchPnP.
En réponse à une IRP_MN_QUERY_REMOVE_DEVICE, un pilote doit effectuer les opérations suivantes :
Déterminez si l’appareil peut être supprimé de la machine en toute sécurité.
Un pilote doit faire échouer une IRP de demande de retrait si l'une des conditions suivantes est remplie :
Si vous supprimez l’appareil, vous risquez de perdre des données.
Si un composant a un handle ouvert sur l'appareil. (Il s’agit d’un problème uniquement sur Windows 98/Me. Windows 2000 et les versions ultérieures de Windows suivent les poignées ouvertes et échouent à la requête s'il y a des poignées ouvertes après que le IRP_MN_QUERY_REMOVE_DEVICE soit terminé.)
Si un pilote a été informé (par une IRP_MN_DEVICE_USAGE_NOTIFICATION) que l'appareil se trouve sur le chemin d'un fichier de pagination, de vidage de mémoire ou d'hibernation.
Si le pilote a une référence d'interface en suspens par rapport à l'appareil. C'est-à-dire, le pilote a mis à disposition une interface en réponse à une demande de IRP_MN_QUERY_INTERFACE et l’interface n’a pas été déréférencée.
Si l'appareil ne peut pas être supprimé, l'IRP query-remove échoue.
Définissez Irp->IoStatus.Status sur un état d’erreur approprié (généralement STATUS_UNSUCCESSFUL), appelez IoCompleteRequest avec IO_NO_INCREMENT, puis revenez de la routine DispatchPnP du pilote. Ne passez pas l’IRP au prochain pilote de niveau inférieur.
Si le pilote a précédemment envoyé une requête IRP_MN_WAIT_WAKE pour activer le réveil de l'appareil, annulez l'IRP wait-wake.
Enregistrez l’état PnP précédent de l’appareil.
Un pilote doit enregistrer l’état PnP dans lequel l’appareil se trouvait lorsque le pilote a reçu la demande de IRP_MN_QUERY_REMOVE_DEVICE, car le pilote doit renvoyer l’appareil à cet état si la requête est annulée (IRP_MN_CANCEL_REMOVE_DEVICE). L’état précédent est généralement « démarré », c’est-à-dire l’état que l’appareil entre lorsque le pilote termine correctement une demande de IRP_MN_START_DEVICE.
Toutefois, d’autres états précédents sont possibles. Par exemple, l’utilisateur a peut-être désactivé l’appareil via device Manager. Ou, en réponse à une requête IRP_MN_QUERY_CAPABILITIES, le pilote de bus parent (ou un pilote de filtre sur le pilote de bus) peut avoir signalé que le matériel de l'appareil est désactivé. Dans les deux cas, le pilote de l'appareil désactivé peut recevoir une requête IRP_MN_QUERY_REMOVE_DEVICE avant de recevoir une requête IRP_MN_START_DEVICE.
Terminez l'IRP :
Dans une fonction ou un pilote de filtre :
Mettez Irp->IoStatus.Status à STATUS_SUCCESS.
Configurez l'emplacement de la pile suivante avec IoSkipCurrentIrpStackLocation et transmettez l'IRP au pilote immédiatement inférieur avec IoCallDriver.
Transmettez l'état de IoCallDriver comme état de retour de la routine DispatchPnP.
Ne terminez pas l’IRP.
Dans un pilote de bus :
Mettez Irp->IoStatus.Status à STATUS_SUCCESS.
Terminez l'IRP (IoCompleteRequest) avec IO_NO_INCREMENT.
Retournez à la routine DispatchPnP.
Si un pilote de la pile d'appareils échoue à une IRP_MN_QUERY_REMOVE_DEVICE, le gestionnaire PnP envoie une IRP_MN_CANCEL_REMOVE_DEVICE à la pile d'appareils. Cela évite aux pilotes d'avoir besoin d'une routine IoCompletion pour une IRP de requête-relèvement afin de détecter si un pilote inférieur a échoué l'IRP.
Lorsqu'un pilote réussit une IRP_MN_QUERY_REMOVE_DEVICE et qu'il considère que l'appareil est dans l'état « remove-pending », il doit faire échouer toute requête de création ultérieure pour l'appareil. Le pilote traite tous les autres IRPs comme d’habitude, jusqu’à ce que le pilote reçoive un IRP_MN_CANCEL_REMOVE_DEVICE ou un IRP_MN_REMOVE_DEVICE.