Création de requêtes IOCTL dans les pilotes

Un pilote de classe ou un autre pilote de niveau supérieur peut allouer des IRPs pour les demandes de contrôle d’E/S et les envoyer au pilote inférieur suivant comme suit :

  1. Allouez ou réutilisez un paquet de demandes d’E/S (IRP) avec le code de fonction principal IRP_MJ_DEVICE_CONTROL ou IRP_MJ_INTERNAL_DEVICE_CONTROL. Vous pouvez utiliser la routine IoBuildDeviceIoControlRequest pour allouer spécifiquement un IRP IOCTL. Vous pouvez également utiliser des routines de création et d’initialisation IRP à usage général, telles que IoAllocateIrp, IoReuseIrp ou IoInitializeIrp. Pour plus d’informations sur l’allocation IRP, consultez Création d’IRP pour les pilotes Lower-Level.

  2. Configurez l’emplacement de pile d’E/S du pilote inférieur pour l’IRP avec le code IOCTL_XXX et les paramètres appropriés.

  3. Si la demande IOCTL doit être effectuée de manière asynchrone, appelez la routine KeInitializeEvent pour initialiser un objet d’événement en tant qu’événement de notification. Le pilote utilise cet événement pour attendre la fin d’une opération d’E/S.

  4. Appelez IoSetCompletionRoutine avec l’IRP afin que le pilote supérieur puisse fournir une routine IoCompletion , si nécessaire, pour effectuer les opérations suivantes :

    • Déterminez comment le pilote inférieur a géré une requête donnée.

    • Réutilisez l’IRP pour envoyer une autre demande ou supprimer l’IRP créé par le pilote, une fois que le pilote inférieur a terminé une opération demandée. Le pilote ne peut pas réutiliser les IIP créés par IoBuildDeviceIoControlRequest . Pour plus d’informations, consultez Réutilisation des IRP.

  5. Appelez IoCallDriver pour transmettre la demande au pilote inférieur.

  6. Si IoCallDriver retourne STATUS_PENDING, appelez la routine KeWaitForSingleObject pour placer le thread actuel dans un état d’attente. Le pilote définit le paramètre Object de la routine sur l’adresse de l’objet d’événement initialisé dans l’appel à KeInitializeEvent.

    Note Si le pilote appelle KeWaitForSingleObject avec son paramètre Timeout défini sur NULL ou sur l’adresse d’une variable qui contient une valeur différente de zéro, le pilote doit s’exécuter à IRQL <= APC_LEVEL dans un contexte de thread non binaire. Sinon, le pilote doit s’exécuter à IRQL <= DISPATCH_LEVEL.

L’événement est signalé par sa routine IoCompletion lorsque la demande IOCTL est terminée. Une fois l’événement signalé, le thread reprend l’exécution.

Important Si le pilote alloue l’objet événement en tant que variable locale sur la pile, le pilote doit appeler KeWaitForSingleObject avec son paramètre WaitMode défini sur KernelMode. Cette valeur de paramètre empêche la pile d’être paginée.

Pour éviter les problèmes de synchronisation et les violations d’accès possibles, les paramètres des codes de contrôle d’E/S incluent rarement des pointeurs incorporés. À l’exception de certaines requêtes SCSI, les mémoires tampons sur Irp-AssociatedIrp>. SystemBuffer, sur Irp-MdlAddress> et surParamètres. DeviceIoControl. Type3InputBuffer dans l’emplacement de la pile d’E/S d’un pilote ne contient pas de pointeurs vers d’autres mémoires tampons de données, ni de structures qui contiennent des pointeurs pour les codes de contrôle d’E/S définis par le système. Pour plus d’informations sur l’utilisation des mémoires tampons de données avec les irps qui contiennent des codes de contrôle d’E/S, consultez Descriptions des tampons pour les codes de contrôle d’E/S.

Néanmoins, une paire de pilotes de classe/port qui définissent des codes de contrôle d’E/S internes peut passer un pointeur incorporé vers la mémoire allouée au pilote de niveau supérieur vers le pilote de niveau inférieur. Une telle paire de pilotes de classe/port est chargée de s’assurer que les éléments suivants sont vrais :

  • Un seul pilote à la fois peut accéder aux données.

  • Les mémoires tampons de données privées sont accessibles dans un contexte de thread arbitraire par le pilote de port.

Les pilotes d’affichage peuvent appeler la fonction GDI EngDeviceIoControl pour envoyer des demandes de contrôle d’E/S spécifiques à l’appareil définies en privé, ainsi que des demandes de contrôle d’E/S publiques définies par le système, par le biais du pilote de port vidéo système jusqu’aux pilotes de miniport vidéo correspondants spécifiques à l’adaptateur.

Tout composant en mode utilisateur d’un package de pilotes peut appeler DeviceIoControl pour envoyer des demandes de contrôle d’E/S à une pile de pilotes. Le gestionnaire d’E/S crée une requête IRP_MJ_DEVICE_CONTROL et la remet au pilote de niveau supérieur.