Fonction IoBuildAsynchronousFsdRequest (wdm.h)

La routine IoBuildAsynchronousFsdRequest alloue et configure un IRP à envoyer aux pilotes de niveau inférieur.

Syntaxe

__drv_aliasesMem PIRP IoBuildAsynchronousFsdRequest(
  [in]           ULONG            MajorFunction,
  [in]           PDEVICE_OBJECT   DeviceObject,
  [in, out]      PVOID            Buffer,
  [in, optional] ULONG            Length,
  [in, optional] PLARGE_INTEGER   StartingOffset,
  [in, optional] PIO_STATUS_BLOCK IoStatusBlock
);

Paramètres

[in] MajorFunction

Code de fonction principale à définir dans l’IRP. Ce code peut être IRP_MJ_PNP, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS ou IRP_MJ_SHUTDOWN.

[in] DeviceObject

Pointeur vers l’objet de périphérique du pilote inférieur suivant. Cet objet représente l’appareil cible pour l’opération de lecture, d’écriture, de vidage ou d’arrêt.

[in, out] Buffer

Pointeur vers une mémoire tampon dans laquelle les données sont lues ou à partir de laquelle les données sont écrites. La valeur de cet argument est NULL pour les demandes de vidage et d’arrêt.

[in, optional] Length

Longueur, en octets, de la mémoire tampon pointée par Buffer. Pour les appareils tels que les disques, cette valeur doit être un multiple entier de la taille du secteur. À compter de Windows 8, la taille du secteur peut être de 4 096 ou 512 octets. Dans les versions antérieures de Windows, la taille de secteur est toujours de 512 octets. Ce paramètre est requis pour les demandes de lecture et d’écriture, mais doit être égal à zéro pour les demandes de vidage et d’arrêt.

[in, optional] StartingOffset

Pointeur vers le décalage de départ sur le média d’entrée/sortie. La valeur de cet argument est zéro pour les demandes de vidage et d’arrêt.

[in, optional] IoStatusBlock

Pointeur vers l’adresse d’un bloc d’E/S status dans lequel les pilotes à appeler retournent des status finales sur l’opération demandée.

Valeur retournée

IoBuildAsynchronousFsdRequest retourne un pointeur vers un IRP ou un pointeur NULL si l’IRP ne peut pas être alloué.

Remarques

Les pilotes intermédiaires ou de plus haut niveau peuvent appeler IoBuildAsynchronousFsdRequest pour configurer des irps pour les demandes envoyées aux pilotes de niveau inférieur. Le pilote appelant doit fournir une routine IoCompletion pour l’IRP, afin que l’IRP puisse être libéré avec IoFreeIrp. Pour plus d’informations sur la désallocation IRP, consultez Exemples.

L’IRP qui est généré contient uniquement suffisamment d’informations pour démarrer l’opération et terminer l’IRP. Aucune autre information de contexte n’est suivie, car une requête asynchrone est indépendante du contexte.

Les pilotes de niveau inférieur peuvent imposer des restrictions sur les paramètres fournis à cette routine. Par exemple, les pilotes de disque peuvent exiger que les valeurs fournies pour Length et StartingOffset soient des multiples entiers de la taille de secteur de l’appareil.

Un pilote intermédiaire ou de niveau supérieur peut également appeler IoBuildDeviceIoControlRequest, IoAllocateIrp ou IoBuildSynchronousFsdRequest pour configurer les demandes qu’il envoie aux pilotes de niveau inférieur. Seul un pilote de niveau supérieur peut appeler IoMakeAssociatedIrp.

Lors d’un appel IoBuildAsynchronousFsdRequest , le gestionnaire d’E/S définit le membre Tail.Overlay.Thread de la structure IRP pour qu’il pointe vers l’objet thread de l’appelant, mais ne prend pas de référence comptée à l’objet thread pour le compte de l’appelant. Une fois que l’appelant a envoyé l’IRP au pilote de l’appareil cible, ce pilote peut utiliser le membre Tail.Overlay.Thread pour accéder à l’objet thread. Par exemple, un pilote de stockage peut appeler la routine IoSetHardErrorOrVerifyDevice et fournir un pointeur vers l’IRP en tant que paramètre d’entrée. Pendant cet appel, IoSetHardErrorOrVerifyDevice utilise le membre Tail.Overlay.Thread pour accéder à l’objet thread. Lorsque l’objet thread est accessible de cette façon, le pilote qui a appelé IoBuildAsynchronousFsdRequest pour allouer l’IRP est chargé de s’assurer que l’objet thread reste valide pendant la gestion de l’IRP.

Pour que l’objet thread reste valide, le pilote qui appelle IoBuildAsynchronousFsdRequest peut prendre une référence comptée sur l’objet thread avant d’envoyer l’IRP. Par exemple, ce pilote peut appeler la routine ObReferenceObjectByPointerWithTag et fournir, en tant que paramètre Object , le pointeur d’objet du membre Tail.Overlay.Thread de la structure IRP . Plus tard, la routine d’achèvement de ce pilote peut déréférencer l’objet en appelant une routine telle que ObDereferenceObjectWithTag.

Un pilote peut appeler IoBuildAsynchronousFsdRequest dans un thread et envoyer l’IRP allouée par cet appel dans un autre thread. Avant d’envoyer l’IRP, ce pilote doit définir le membre Tail.Overlay.Thread de l’IRP pour qu’il pointe vers l’objet thread du thread d’envoi. En règle générale, le pilote appelle la routine PsGetCurrentThread pour obtenir le pointeur d’objet thread.

Un pilote qui appelle IoBuildAsynchronousFsdRequest pour allouer un IRP n’a pas nécessairement besoin de prendre une référence comptée sur l’objet thread pointé par le membre Tail.Overlay.Thread de l’IRP. À la place, le pilote peut utiliser une autre technique pour garantir que cet objet thread reste valide pendant la gestion de l’IRP. Par exemple, si le pilote a créé le thread, le thread peut attendre que l’IRP soit terminé pour se terminer lui-même.

Exemples

Avant d’appeler IoFreeIrp, une étape supplémentaire est nécessaire pour libérer la mémoire tampon d’un IRP généré par IoBuildAsynchronousFsdRequest si les éléments suivants sont tous vrais :

  • La mémoire tampon a été allouée à partir du pool de mémoire système.

  • Dans l’objet device de l’appareil cible, l’indicateur DO_DIRECT_IO est défini dans le champ DeviceObject-Flags>.

  • Le champ Irp-MdlAddress> n’est pas NULL.

Avant de libérer la mémoire tampon pour cette IRP, appelez la routine MmUnlockPages avec Irp-MdlAddress> comme valeur de paramètre. Cet appel décrémente le nombre de références supplémentaires qu’IoBuildAsynchronousFsdRequest a ajouté aux pages du pool dans la MDL. Sinon, l’appel suivant à IoFreeMdl aura un bogue case activée, car le nombre de références pour ces pages de pool sera de 2, et non de 1. L’exemple de code suivant montre les appels MmUnlockPages, IoFreeMdl et IoFreeIrp pour ce cas :

if (((DeviceObject->Flags & DO_DIRECT_IO) == DO_DIRECT_IO) &&
    (Irp->MdlAddress != NULL))
{
    MmUnlockPages(Irp->MdlAddress);
}

IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);

Configuration requise

Condition requise Valeur
Plateforme cible Universal
En-tête wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
Bibliothèque NtosKrnl.lib
DLL NtosKrnl.exe
IRQL IRQL <= APC_LEVEL
Règles de conformité DDI ForwardedAtBadIrqlFsdAsync(wdm), HwStorPortProhibitedDDDIs(storport), IoBuildFsdComplete(wdm), IoBuildFsdForward(wdm), IoBuildFsdFree(wdm)

Voir aussi

IO_STACK_LOCATION

IRP

IoAllocateIrp

IoBuildDeviceIoControlRequest

IoBuildSynchronousFsdRequest

IoCallDriver

IoFreeIrp

IoFreeMdl

IoMakeAssociatedIrp

IoSetCompletionRoutine

IoSetHardErrorOrVerifyDevice

MmUnlockPages

ObDereferenceObjectWithTag

ObReferenceObjectByPointerWithTag

PsGetCurrentThread