Partager via


Gestion d’une demande de IRP_MN_SURPRISE_REMOVAL

Le gestionnaire PnP Windows 2000 et ultérieur envoie cette IRP pour informer les pilotes qu’un appareil n’est plus disponible pour les opérations d’E/S et qu’il a probablement été supprimé de manière inattendue de la machine (« suppression surprise »).

Le gestionnaire PnP envoie une demande de IRP_MN_SURPRISE_REMOVAL pour les raisons suivantes :

  • Si le bus a une notification de prise à chaud, il avertit le pilote de bus parent de l’appareil que l’appareil a disparu. Le pilote de bus appelle IoInvalidateDeviceRelations. En réponse, le gestionnaire PnP interroge le pilote de bus pour ses enfants (IRP_MN_QUERY_DEVICE_RELATIONS pour BusRelations). Le gestionnaire PnP détermine que l’appareil ne figure pas dans la nouvelle liste d’enfants et lance ses opérations de suppression de surprise pour l’appareil.

  • Le bus est énuméré pour une autre raison et l’appareil supprimé par surprise n’est pas inclus dans la liste des enfants. Le gestionnaire PnP lance ses opérations de suppression surprise.

  • Le pilote de fonction de l’appareil détermine que le périphérique n’est plus présent (car, par exemple, ses demandes expirent à plusieurs reprises). Le bus peut être énumérable, mais il n’a pas de notification de prise à chaud. Dans ce cas, le pilote de fonction appelle IoInvalidateDeviceState. En réponse, le gestionnaire PnP envoie une requête IRP_MN_QUERY_PNP_DEVICE_STATE à la pile d’appareils. Le pilote de fonction définit l’indicateur PNP_DEVICE_FAILED dans le masque de bits PNP_DEVICE_STATE indiquant que le périphérique a échoué.

  • La pile de pilotes termine correctement une demande de IRP_MN_STOP_DEVICE , mais échoue ensuite à une demande de IRP_MN_START_DEVICE suivante. Dans ce cas, l’appareil est probablement toujours connecté.

Tous les pilotes PnP doivent gérer cette IRP et définir Irp-IoStatus.Status> sur STATUS_SUCCESS. Un pilote pour un périphérique PnP doit être prêt à gérer IRP_MN_SURPRISE_REMOVAL à tout moment après l’appel de la routine AddDevice du pilote. Une gestion correcte de l’IRP permet aux pilotes et au gestionnaire PnP de :

  1. Désactivez l’appareil, au cas où il est toujours connecté.

    Si la pile des pilotes a réussi à effectuer une demande de IRP_MN_STOP_DEVICE , mais que, pour une raison quelconque, a échoué une demande de IRP_MN_START_DEVICE suivante, l’appareil doit être désactivé.

  2. Libérez les ressources matérielles affectées à l’appareil et mettez-les à la disposition d’un autre appareil.

    Dès qu’un appareil n’est plus disponible, ses ressources matérielles doivent être libérées. Le gestionnaire PnP peut ensuite réaffecter les ressources à un autre appareil, y compris le même appareil, qu’un utilisateur peut reconnecter à chaud à l’ordinateur.

  3. Réduisez le risque de perte de données et d’interruption du système.

    Les appareils qui prennent en charge le branchement à chaud et leurs pilotes doivent être conçus pour gérer le retrait surprise. Les utilisateurs s’attendent à pouvoir supprimer les appareils qui prennent en charge le branchement à chaud à tout moment.

Le gestionnaire PnP envoie une IRP_MN_SURPRISE_REMOVAL à IRQL = PASSIVE_LEVEL dans le contexte d’un thread système.

Le gestionnaire PnP envoie cette IRP aux pilotes avant de notifier les applications en mode utilisateur et d’autres composants en mode noyau. Une fois l’IRP terminée, le gestionnaire PnP envoie une notification EventCategoryTargetDeviceChange avec GUID_TARGET_DEVICE_REMOVE_COMPLETE aux composants en mode noyau inscrits pour cette notification sur l’appareil.

Le IRP_MN_SURPRISE_REMOVAL IRP est géré d’abord par le pilote supérieur dans la pile de périphériques, puis par chaque pilote inférieur suivant.

En réponse à IRP_MN_SURPRISE_REMOVAL, un pilote doit effectuer les opérations suivantes, dans l’ordre indiqué :

  1. Déterminez si l’appareil a été supprimé.

    Le pilote doit toujours tenter de déterminer si l’appareil est toujours connecté. Si c’est le cas, le pilote doit tenter d’arrêter l’appareil et de le désactiver.

  2. Libérez les ressources matérielles de l’appareil (interruptions, ports d’E/S, registres de mémoire et canaux DMA).

  3. Dans un pilote de bus parent, mettez hors tension l’emplacement de bus si le pilote est capable de le faire. Appelez PoSetPowerState pour avertir le gestionnaire d’alimentation. Pour plus d’informations, consultez Gestion de l’alimentation.

  4. Empêcher toute nouvelle opération d’E/S sur l’appareil.

    Un pilote doit traiter les demandes de IRP_MJ_CLEANUP, de IRP_MJ_CLOSE, de IRP_MJ_POWER et de IRP_MJ_PNP ultérieures, mais le pilote doit empêcher toute nouvelle opération d’E/S. Un pilote doit échouer à tous les IRP ultérieurs qu’il aurait gérés si l’appareil était présent, en plus de fermer, propre-up et PnP IRP.

    Un pilote peut définir un bit dans l’extension de périphérique pour indiquer que l’appareil a été supprimé par surprise. Les routines de répartition du pilote doivent case activée ce bit.

  5. Les demandes d’E/S en attente sur l’appareil échouent.

  6. Continuez à transmettre tous les IRP que le pilote ne gère pas pour l’appareil.

  7. Désactivez les interfaces d’appareil avec IoSetDeviceInterfaceState.

  8. Nettoyez les allocations, la mémoire, les événements ou autres ressources système spécifiques à l’appareil.

    Un pilote peut reporter ces propre jusqu’à ce qu’il reçoive la demande de IRP_MN_REMOVE_DEVICE suivante, mais si un composant hérité a un handle ouvert qui ne peut pas être fermé, l’IRP de suppression ne sera jamais envoyé.

  9. Laissez l’objet d’appareil attaché à la pile d’appareils.

    Ne détachez et ne supprimez pas l’objet d’appareil avant la demande de IRP_MN_REMOVE_DEVICE suivante.

  10. Terminez l’IRP.

    Dans un pilote de fonction ou de filtre :

    • Définissez Irp-IoStatus.Status> sur STATUS_SUCCESS.

    • Configurez l’emplacement de pile suivant avec IoSkipCurrentIrpStackLocation et passez l’IRP au pilote inférieur suivant avec IoCallDriver.

    • Propagez le status à partir d’IoCallDriver en tant que status de retour à partir de la routine DispatchPnP.

    • Ne terminez pas le IRP.

    Dans un pilote de bus (qui gère cette IRP pour un PDO enfant) :

    • Définissez Irp-IoStatus.Status> sur STATUS_SUCCESS.

    • Terminez l’IRP (IoCompleteRequest) avec IO_NO_INCREMENT.

    • Retour à partir de la routine DispatchPnP .

Une fois que cette IRP a réussi et que tous les handles ouverts sur l’appareil sont fermés, le gestionnaire PnP envoie une requête IRP_MN_REMOVE_DEVICE à la pile de l’appareil. En réponse à l’IRP de suppression, les pilotes détachent leurs objets d’appareil de la pile et les suppriment. Si un composant hérité a un descripteur ouvert sur l’appareil et qu’il le laisse ouvert malgré des échecs d’E/S, le gestionnaire PnP n’envoie jamais l’IRP de suppression.

Tous les pilotes doivent gérer cette IRP et doivent noter que l’appareil a été physiquement supprimé de la machine. Toutefois, certains conducteurs ne provoqueront pas de résultats défavorables s’ils ne gèrent pas le IRP. Par exemple, un appareil qui ne consomme pas de ressources matérielles système et qui réside sur un bus basé sur un protocole, tel qu’USB ou 1394, ne peut pas attacher de ressources matérielles, car il n’en consomme aucune. Il n’existe aucun risque que les pilotes tentent d’accéder à l’appareil après sa suppression, car les pilotes de fonction et de filtre accèdent à l’appareil uniquement par le biais du pilote de bus parent. Étant donné que le bus prend en charge la notification de suppression, le pilote de bus parent est averti lorsque l’appareil disparaît et que le pilote de bus échoue toutes les tentatives d’accès ultérieures à l’appareil.

Sur Windows 98/Me, le gestionnaire PnP n’envoie pas cette IRP. Si un utilisateur supprime un appareil sans utiliser au préalable l’interface utilisateur appropriée, le gestionnaire PnP envoie uniquement une demande de IRP_MN_REMOVE_DEVICE aux pilotes de l’appareil. Tous les pilotes WDM doivent gérer les IRP_MN_SURPRISE_REMOVAL et les IRP_MN_REMOVE_DEVICE. Le code de IRP_MN_REMOVE_DEVICE doit case activée si le pilote a déjà reçu un IRP de suppression de surprise et doit gérer les deux cas.

Utilisation de GUID_REENUMERATE_SELF_INTERFACE_STANDARD

L’interface GUID_REENUMERATE_SELF_INTERFACE_STANDARD permet à un pilote de demander que son appareil soit réinumé.

Pour utiliser cette interface, envoyez un IRP IRP_MN_QUERY_INTERFACE à votre pilote de bus avec InterfaceType = GUID_REENUMERATE_SELF_INTERFACE_STANDARD. Le pilote de bus fournit un pointeur vers une structure REENUMERATE_SELF_INTERFACE_STANDARD qui contient des pointeurs vers les routines individuelles de l’interface. Une routine ReenumerateSelf demande à un pilote de bus d’énumérer un appareil enfant.

À propos de PNP_DEVICE_STATE

Le type PNP_DEVICE_STATE est un masque de bits qui décrit l’état PnP d’un appareil. Un pilote retourne une valeur de ce type en réponse à une demande de IRP_MN_QUERY_PNP_DEVICE_STATE .

typedef ULONG PNP_DEVICE_STATE, *PPNP_DEVICE_STATE;

Les bits d’indicateur dans une valeur PNP_DEVICE_STATE sont définis comme suit.

Bit d’indicateur Description
PNP_DEVICE_DISABLED

L’appareil est physiquement présent, mais est désactivé dans le matériel.

PNP_DEVICE_DONT_DISPLAY_IN_UI

N’affichez pas l’appareil dans l’interface utilisateur. Défini pour un appareil physiquement présent mais non utilisable dans la configuration actuelle, tel qu’un port de jeu sur un ordinateur portable qui n’est pas utilisable lorsque l’ordinateur portable est dénudé. (Consultez également l’indicateur NoDisplayInUI dans la structure DEVICE_CAPABILITIES .)

PNP_DEVICE_FAILED

L’appareil est présent, mais ne fonctionne pas correctement.

Lorsque cet indicateur et ce PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED sont définis, l’appareil doit être arrêté avant que le gestionnaire PnP n’affecte de nouvelles ressources matérielles (le rééquilibrage sans interruption n’est pas pris en charge pour l’appareil).

PNP_DEVICE_NOT_DISABLEABLE

L’appareil est requis au démarrage de l’ordinateur. Un tel appareil ne doit pas être désactivé.

Un pilote définit ce bit pour un appareil requis pour le bon fonctionnement du système. Par exemple, si un pilote reçoit une notification indiquant qu’un appareil se trouve dans le chemin de pagination (IRP_MN_DEVICE_USAGE_NOTIFICATION pour DeviceUsageTypePaging), le pilote appelle IoInvalidateDeviceState et définit cet indicateur dans la demande IRP_MN_QUERY_PNP_DEVICE_STATE résultante.

Si ce bit est défini pour un appareil, le gestionnaire PnP propage ce paramètre à l’appareil parent de l’appareil, à l’appareil parent de son parent, etc.

Si ce bit est défini pour un appareil énuméré par la racine, l’appareil ne peut pas être désactivé ou désinstallé.

PNP_DEVICE_REMOVED

L’appareil a été physiquement supprimé.

PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED

Les besoins en ressources de l’appareil ont changé.

En règle générale, un pilote de bus définit cet indicateur lorsqu’il a déterminé qu’il doit développer ses besoins en ressources afin d’énumérer un nouveau périphérique enfant.

PNP_DEVICE_DISCONNECTED

Le pilote de périphérique est chargé, mais ce pilote a détecté que l’appareil n’est plus connecté à l’ordinateur. En règle générale, cet indicateur est utilisé pour les pilotes de fonction qui communiquent avec les périphériques sans fil. Par exemple, l’indicateur est défini lorsque l’appareil sort de la plage et est effacé une fois que l’appareil revient dans la plage et se reconnecte.

Un pilote de bus ne définit généralement pas cet indicateur. Le pilote de bus doit à la place arrêter d’énumérer l’appareil enfant si celui-ci n’est plus connecté. Cet indicateur est utilisé uniquement si le pilote de fonction gère la connexion.

Le seul objectif de cet indicateur est d’informer les clients si l’appareil est connecté. La définition de l’indicateur n’affecte pas si le pilote est chargé.

Le gestionnaire PnP interroge les PNP_DEVICE_STATE d’un appareil juste après le démarrage de l’appareil en envoyant une demande de IRP_MN_QUERY_PNP_DEVICE_STATE à la pile d’appareils. En réponse à cette IRP, les pilotes de l’appareil définissent les indicateurs appropriés dans PNP_DEVICE_STATE.

Si l’une des caractéristiques d’état change après la requête initiale, un pilote avertit le gestionnaire PnP en appelant IoInvalidateDeviceState. En réponse à un appel à IoInvalidateDeviceState, le gestionnaire PnP interroge à nouveau les PNP_DEVICE_STATE de l’appareil.

Si un appareil est marqué PNP_DEVICE_NOT_DISABLEABLE, le débogueur affiche un indicateur utilisateur DNUF_NOT_DISABLEABLE pour le devnode. Le débogueur affiche également une valeur DisableableDepends qui compte le nombre de raisons pour lesquelles l’appareil ne peut pas être désactivé. Cette valeur est la somme de X+Y, où X est un si l’appareil ne peut pas être désactivé et Y est le nombre d’appareils enfants de l’appareil qui ne peuvent pas être désactivés.