Partager via


Création d’irps pour les pilotes Lower-Level

Pour allouer un IRP pour une requête asynchrone, qui sera traitée dans un contexte de thread arbitraire par des pilotes inférieurs, une routine DispatchReadWrite peut appeler l’une des routines de support suivantes :

  • IoAllocateIrp, qui alloue un IRP et un certain nombre d’emplacements de pile d’E/S à initialisation zéro

    La routine de répartition doit configurer l’emplacement de pile d’E/S du pilote inférieur suivant pour l’IRP nouvellement alloué, généralement en copiant (éventuellement modifié) les informations de son propre emplacement de pile dans l’IRP d’origine. Si un pilote de niveau supérieur alloue son propre emplacement de pile d’E/S pour un IRP nouvellement alloué, la routine de répartition peut y configurer des informations de contexte par demande pour que la routine IoCompletion puisse l’utiliser.

  • IoBuildAsynchronousFsdRequest, qui configure l’emplacement de pile d’E/S du pilote inférieur suivant pour l’appelant, en fonction des paramètres spécifiés par l’appelant

    Les pilotes de niveau supérieur peuvent appeler cette routine pour allouer des irps pour les demandes IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS et IRP_MJ_SHUTDOWN .

    Lorsqu’une routine IoCompletion est appelée pour une telle IRP, elle peut case activée le bloc d’E/S status et, si nécessaire (ou possible), configurer l’emplacement de la pile d’E/S du pilote inférieur suivant dans l’IRP et réessayer la demande ou le réutiliser. Toutefois, la routine IoCompletion n’a pas de stockage de contexte local pour elle-même dans l’IRP. Le pilote doit donc conserver le contexte de la requête d’origine ailleurs dans la mémoire résidente.

  • IoMakeAssociatedIrp, qui alloue un IRP et un certain nombre d’emplacements de pile d’E/S à initialisation zéro, et associe l’IRP à un IRP master.

    Les pilotes intermédiaires ne peuvent pas appeler IoMakeAssociatedIrp pour créer des irps pour les pilotes inférieurs.

    Tout pilote de niveau supérieur qui appelle IoMakeAssociatedIrp pour créer des IRP pour les pilotes inférieurs peut retourner le contrôle au gestionnaire d’E/S après avoir envoyé ses IRPs associés sur et appelé IoMarkIrpPending pour l’IRP d’origine, master. Un pilote de niveau supérieur peut s’appuyer sur le gestionnaire d’E/S pour effectuer les master IRP lorsque tous les IPS associés ont été effectués par des pilotes inférieurs.

    Les pilotes définissent rarement une routine IoCompletion pour un IRP associé. Si un pilote de niveau supérieur appelle IoSetCompletionRoutine pour un IRP associé qu’il crée, le gestionnaire d’E/S ne termine pas la master IRP si le pilote retourne STATUS_MORE_PROCESSING_REQUIRED à partir de sa routine IoCompletion. Dans ce cas, la routine IoCompletion du pilote doit remplir explicitement le master IRP avec IoCompleteRequest.

Si un pilote alloue son propre emplacement de pile d’E/S dans un nouvel IRP, la routine de répartition doit appeler IoSetNextIrpStackLocation avant d’appeler IoGetCurrentIrpStackLocation pour configurer le contexte dans son propre emplacement de pile d’E/S pour la routine IoCompletion . Pour plus d’informations, consultez Traitement des IRP dans un pilote Intermediate-Level.

La routine de répartition doit appeler IoMarkIrpPending avec l’IRP d’origine, mais pas avec les IRP alloués par le pilote, car la routine IoCompletion les libère.

Si la routine de répartition alloue des IRPs pour des transferts partiels et que le pilote de périphérique sous-jacent peut contrôler un périphérique multimédia amovible, la routine de répartition doit configurer le contexte du thread dans ses nouveaux IRP alloués à partir de la valeur tail.Overlay.Thread dans l’IRP d’origine.

Un pilote sous-jacent pour un périphérique multimédia amovible peut appeler IoSetHardErrorOrVerifyDevice, qui fait référence au pointeur sur Irp-Tail.Overlay.Thread>, pour un IRP alloué au pilote. Si le pilote appelle cette routine de prise en charge, le pilote du système de fichiers peut envoyer une boîte de dialogue au thread utilisateur approprié qui invite l’utilisateur à annuler, réessayer ou échouer une opération que le pilote n’a pas pu satisfaire. Pour plus d’informations, consultez Prise en charge du support amovible .

Les routines de répartition doivent retourner STATUS_PENDING après avoir envoyé tous les IRP alloués aux pilotes inférieurs.

La routine IoCompletion d’un pilote doit libérer tous les IRP alloués au pilote avec IoFreeIrp avant d’appeler IoCompleteRequest pour l’IRP d’origine. Lorsqu’elle termine l’IRP d’origine, la routine IoCompletion doit libérer tous les IRP alloués par le pilote avant qu’elle ne retourne le contrôle.

Chaque pilote de niveau supérieur configure tous les IIP alloués (et réutilisés) pour les pilotes inférieurs de telle sorte qu’il n’est pas important pour le pilote de périphérique sous-jacent qu’une demande donnée provient d’un pilote intermédiaire ou provient d’une autre source, telle qu’un système de fichiers ou une application en mode utilisateur.

Les pilotes de niveau supérieur peuvent appeler IoMakeAssociatedIrp pour allouer des irps et les configurer pour une chaîne de pilotes inférieurs. Le gestionnaire d’E/S termine automatiquement l’IRP d’origine lorsque tous ses IRP associés ont été terminés, tant que le pilote n’appelle pas IoSetCompletionRoutine avec l’IRP d’origine ou avec l’un des irp associés qu’il alloue. Toutefois, les pilotes de plus haut niveau ne doivent pas allouer d’irps associés pour les IRP qui demandent une opération d’E/S mise en mémoire tampon.

Un pilote de niveau intermédiaire ne peut pas allouer des IRPs pour les pilotes de niveau inférieur en appelant IoMakeAssociatedIrp. Tout IRP reçu par un pilote intermédiaire peut déjà être un IRP associé, et un pilote ne peut pas associer un autre IRP à un tel IRP.

Au lieu de cela, si un pilote intermédiaire crée des irps pour les pilotes inférieurs, il doit appeler IoAllocateIrp, IoBuildDeviceIoControlRequest, IoBuildSynchronousFsdRequest ou IoBuildAsynchronousFsdRequest. Toutefois, IoBuildSynchronousFsdRequest ne peut être appelé que dans les cas suivants :

  • Par un thread créé par un pilote pour générer des irps pour les demandes de lecture ou d’écriture, car un tel thread peut attendre dans un contexte de thread non linéaire (son propre) sur un objet de répartiteur, tel qu’un événement initialisé par le pilote passé à IoBuildSynchronousFsdRequest

  • Dans le contexte du thread système pendant l’initialisation ou lors du déchargement

  • Pour générer des irps pour les opérations intrinsèquement synchrones, telles que les demandes de création, de vidage, d’arrêt, de fermeture et de contrôle d’appareil

Toutefois, un pilote est plus susceptible d’appeler IoBuildDeviceIoControlRequest pour allouer des IRPs de contrôle d’appareil que IoBuildSynchronousFsdRequest.