Partager via


Gestion d’une demande de IRP_MN_QUERY_STOP_DEVICE (Windows 2000 et versions ultérieures)

Une requête IRP_MN_QUERY_STOP_DEVICE est gérée d’abord par le pilote supérieur de la pile de périphériques, puis par chaque pilote inférieur suivant. Un pilote gère les irps d’arrêt dans sa routine DispatchPnP .

En réponse à un IRP_MN_QUERY_STOP_DEVICE, un pilote doit effectuer les opérations suivantes :

  1. Déterminez si l’appareil peut être arrêté et si ses ressources matérielles sont libérées, sans effets négatifs.

    Un pilote doit échouer un IRP d’arrêt de requête si l’une des conditions suivantes est vraie :

    • Un pilote a été averti (via IRP_MN_DEVICE_USAGE_NOTIFICATION) que l’appareil se trouve dans le chemin d’accès d’un fichier de pagination, de mise en veille prolongée ou de vidage sur incident.

    • Les ressources matérielles de l’appareil ne peuvent pas être libérées.

    Un pilote peut échouer un IRP d’arrêt de requête si la valeur suivante est vraie :

    • Le pilote ne doit pas supprimer les demandes d’E/S et ne dispose pas d’un mécanisme pour mettre en file d’attente les IRP.

      Lorsque l’appareil est à l’état arrêté, un pilote doit contenir des irps qui nécessitent l’accès à l’appareil. Si un pilote ne met pas en file d’attente les IRPs, il ne doit pas autoriser l’arrêt de l’appareil et doit donc échouer une IRP d’arrêt de requête.

      L’exception à cette règle est un appareil qui est autorisé à supprimer les E/S. Les pilotes d’un tel appareil peuvent réussir les requêtes d’arrêt et d’arrêt des requêtes sans mettre en file d’attente les IRP.

  2. Si l’appareil ne peut pas être arrêté, échouez l’IRP d’arrêt de requête.

    Définissez Irp-IoStatus.Status> sur une status d’erreur appropriée, appelez IoCompleteRequest avec IO_NO_INCREMENT et retournez à partir de la routine DispatchPnP du pilote. Ne passez pas l’IRP au pilote inférieur suivant.

  3. Si l’appareil peut être arrêté et que le pilote met en file d’attente les IRP, définissez l’indicateur HOLD_NEW_REQUESTS dans l’extension de l’appareil afin que les IIP suivants soient mis en file d’attente (voir Conservation des IIP entrants lorsqu’un appareil est suspendu).

    Les pilotes d’un appareil peuvent également différer complètement la suspension de l’appareil jusqu’à ce que les pilotes reçoivent la demande de IRP_MN_STOP_DEVICE suivante. Ces pilotes, toutefois, doivent mettre en file d’attente toutes les demandes qui les empêcheraient de réussir immédiatement l’IRP d’arrêt lorsqu’il arrive. Jusqu’à ce que l’appareil soit redémarré, ces pilotes doivent mettre en file d’attente les demandes telles que les suivantes :

    • IRP_MN_DEVICE_USAGE_NOTIFICATION demandes (par exemple, pour placer un fichier de pagination sur l’appareil).

    • Demandes de transferts isochronieux.

    • Créez des requêtes qui empêcheraient les pilotes de réussir une IRP d’arrêt.

  4. Si l’appareil ne peut pas avoir d’IRP en cours d’échec, assurez-vous que toutes les demandes en suspens qui ont été transmises à d’autres routines de pilotes et à des pilotes inférieurs sont terminées.

    Une façon pour un pilote d’y parvenir consiste à utiliser un nombre de références et un événement pour s’assurer que toutes les demandes ont été effectuées :

    • Dans sa routine AddDevice , le pilote définit un nombre de références d’E/S dans l’extension de l’appareil et initialise le nombre à un.

    • Dans sa routine AddDevice également, le pilote crée un événement avec KeInitializeEvent et initialise l’événement à l’état Not-Signaled avec KeClearEvent.

    • Chaque fois qu’il traite un IRP, le pilote incrémente le nombre de références avec InterlockedIncrement.

    • Chaque fois qu’il termine une requête, le pilote décrémente le nombre de références avec InterlockedDecrement.

      Le pilote décrémente le nombre de références dans la routine IoCompletion , si la requête en a une, ou juste après l’appel à IoCallDriver si le pilote n’utilise aucune routine IoCompletion pour la requête.

    • Lorsque le pilote reçoit une IRP_MN_QUERY_STOP_DEVICE, il décrémente le nombre de références avec InterlockedDecrement. Si aucune demande n’est en suspens, le nombre de références est réduit à zéro.

    • Lorsque le nombre de références atteint zéro, le pilote définit l’événement avec KeSetEvent signalant que le code d’arrêt de requête peut continuer.

    En guise d’alternative à la procédure ci-dessus, un pilote peut sérialiser les IRP_MN_QUERY_STOP_DEVICE IRP derrière tous les IRP en cours.

  5. Effectuez toutes les autres étapes requises pour placer l’appareil à l’état en attente d’arrêt.

    Une fois qu’un pilote réussit un IRP d’arrêt de requête, il doit être prêt à réussir une IRP_MN_STOP_DEVICE.

  6. 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 l’IRP.

    Dans un pilote de bus :

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

      Si, toutefois, les appareils du bus utilisent des ressources matérielles, réévaluez les besoins en ressources du bus et des appareils enfants. Si l’une des conditions requises a changé, retournez STATUS_RESOURCE_REQUIREMENTS_CHANGED au lieu de STATUS_SUCCESS. Cette status indique la réussite, mais demande au gestionnaire PnP de réapprequer vos ressources avant d’envoyer l’IRP d’arrêt.

    • Terminez l’IRP (IoCompleteRequest) avec IO_NO_INCREMENT.

    • Retour à partir de la routine DispatchPnP .

Si un pilote de la pile d’appareils échoue IRP_MN_QUERY_STOP_DEVICE, le gestionnaire PnP envoie un IRP_MN_CANCEL_STOP_DEVICE à la pile d’appareils. Cela empêche les pilotes d’exiger une routine IoCompletion pour une IRP d’arrêt de requête afin de détecter si un pilote inférieur a échoué à l’IRP.