Partager via


IRP_MN_QUERY_INTERFACE

La requête IRP_MN_QUERY_INTERFACE permet à un pilote d’exporter une interface d’appel direct vers d’autres pilotes.

Un pilote de bus qui exporte une interface doit gérer cette demande pour ses appareils enfants (PPO enfants). La fonction et le filtre peuvent éventuellement gérer cette requête.

Une « interface » dans ce contexte se compose d’une ou plusieurs routines, et éventuellement de données, exportées par un pilote ou un ensemble de pilotes. Une interface a une structure qui décrit son contenu et un GUID qui identifie son type.

Par exemple, le pilote de bus PCMCIA exporte une interface de type GUID_PCMCIA_INTERFACE_STANDARD qui contient des routines pour des opérations telles que l’obtention de la condition de protection en écriture d’un carte de mémoire PCMCIA. Le pilote de fonction d’un tel carte de mémoire peut envoyer une demande de IRP_MN_QUERY_INTERFACE au pilote de bus PCMCIA parent pour obtenir des pointeurs vers les routines d’interface PCMCIA.

Notes

Lors de l’introduction d’une nouvelle version d’une interface existante, créez un GUID au lieu de réviser les champs Taille ou Version de la structure INTERFACE . Pour plus d’informations, consultez Utilisation d’interfaces Driver-Defined.

Cette section décrit l’IRP de l’interface de requête en tant que mécanisme général. Les pilotes qui exposent une interface doivent fournir des informations supplémentaires sur leur interface spécifique.

Valeur

0x08

Code majeur

IRP_MJ_PNP

Date d’envoi

Un pilote ou un composant système envoie cette IRP pour obtenir des informations sur une interface exportée par un pilote pour un appareil.

Un pilote ou un composant système envoie cette IRP à IRQL = PASSIVE_LEVEL dans un contexte de thread arbitraire.

Un pilote peut recevoir cette IRP à tout moment après l’appel de la routine AddDevice du pilote pour l’appareil. L’appareil peut ou ne pas être démarré lors de l’envoi de cette IRP (autrement dit, vous ne pouvez pas supposer que le pilote a correctement effectué une demande de IRP_MN_START_DEVICE pour l’appareil).

Paramètres d’entrée

Le membre Parameters.QueryInterface de la structure IO_STACK_LOCATION est lui-même une structure, qui décrit l’interface demandée. La structure contient les informations suivantes :

CONST GUID *InterfaceType;
USHORT Size;
USHORT Version;
PINTERFACE Interface;
PVOID InterfaceSpecificData

Les membres de la structure sont définis comme suit :

InterfaceType
Pointe vers un GUID qui identifie l’interface demandée. Le GUID peut être pour une interface définie par le système, telle que GUID_BUS_INTERFACE_STANDARD, ou une interface personnalisée. Les GUID pour les interfaces définies par le système sont répertoriés dans Wdmguid.h. Les GUID pour les interfaces personnalisées doivent être générés avec Uuidgen.

Taille
Spécifie la taille de l’interface demandée. Les pilotes qui gèrent cette IRP ne doivent pas retourner une structure INTERFACE supérieure à size octets.

Version
Spécifie la version de l’interface demandée.

Si un pilote prend en charge plusieurs versions d’une interface, il retourne la version prise en charge la plus proche sans dépasser la version demandée. Le composant qui a envoyé l’IRP doit examiner le champ Interface.Version retourné et déterminer ce qu’il faut faire en fonction de cette valeur.

Interface
Pointe vers une structure dans laquelle retourner l’interface demandée. Cette structure doit contenir une structure INTERFACE comme premier membre. Le composant qui envoie l’IRP alloue cette structure à partir de la mémoire paginée.

Un pilote qui exporte une interface définit un nouveau type de structure contenant la structure INTERFACE , ainsi que des membres pour les routines et/ou les données dans l’interface. (Le pilote définit également un GUID pour l’interface, comme décrit dans le membre InterfaceType ci-dessus.)

Un pilote qui exporte une interface définit l’environnement d’exécution pour chaque routine de l’interface, y compris l’IRQL auquel la routine peut être appelée, etc.

InterfaceSpecificData
Spécifie des informations supplémentaires sur l’interface demandée.

Pour certaines interfaces, le composant qui envoie l’IRP spécifie des informations supplémentaires dans ce champ. En règle générale, ce champ a la valeur NULL et les valeurs InterfaceType et Version sont suffisantes pour identifier l’interface demandée.

Paramètres de sortie

En cas de réussite, un pilote remplit les membres de la structure Parameters.QueryInterface.Interface .

Bloc d’état E/S

Un pilote définit Irp-IoStatus.Status> sur STATUS_SUCCESS ou sur un status d’erreur approprié.

En cas de réussite, un pilote de bus définit Irp-IoStatus.Information> sur zéro.

Si un pilote de fonction ou de filtre ne gère pas cette IRP, il appelle IoSkipCurrentIrpStackLocation et transmet l’IRP au pilote suivant. Un tel pilote ne doit pas modifier Irp-IoStatus.Status> et ne doit pas terminer l’IRP.

Si un pilote de bus n’exporte pas l’interface demandée et ne gère donc pas cette IRP pour un PDO enfant, le pilote de bus laisse Irp-IoStatus.Status> tel quel et termine l’IRP.

Opération

Un pilote gère cette IRP si les paramètres spécifient une interface prise en charge par le pilote.

Un pilote ne doit pas mettre en file d’attente cette IRP si l’IRP demande une interface que le pilote ne prend pas en charge. Un pilote doit case activée Parameters.QueryInterface.InterfaceType dans sa structure IO_STACK_LOCATION. Si l’interface n’est pas prise en charge par le pilote, le pilote doit passer l’IRP au pilote inférieur suivant dans la pile de périphériques sans se bloquer.

Chaque interface doit fournir des routines InterfaceReference et InterfaceDereference , et le pilote qui exporte l’interface doit fournir les adresses de ces routines dans la structure INTERFACE . Avant qu’un pilote retourne une interface en réponse à l’IRP, il doit incrémenter le nombre de références de l’interface en appelant sa routine InterfaceReference . Lorsque le pilote qui a demandé l’interface a fini de l’utiliser, il doit décrémenter le nombre de références en appelant la routine InterfaceDereference de l’interface.

Si le pilote qui envoie ultérieurement l’IRP (pilote x) passe l’interface à un autre pilote (pilote y), le pilote x doit incrémenter le nombre de références de l’interface et le pilote y doit le décrémenter.

Un pilote qui gère cette IRP doit éviter de passer l’IRP à une autre pile de périphériques pour obtenir l’interface demandée. Une telle conception créerait des dépendances entre les piles d’appareils qui sont difficiles à gérer. Par exemple, l’appareil représenté par la deuxième pile de périphériques ne peut pas être supprimé tant que le pilote approprié dans la première pile n’a pas déréférence l’interface.

Les interfaces peuvent être spécifiques au bus ou indépendantes du bus. Les interfaces spécifiques aux bus sont définies dans les fichiers d’en-tête de ces bus. Le système définit une interface indépendante du bus, BUS_INTERFACE_STANDARD, pour l’exportation d’interfaces de bus standard.

Consultez Plug-and-Play pour connaître les règles générales de gestion Plug-and-Play irps mineurs.

Cette IRP est utilisée spécifiquement pour passer des points d’entrée de routine entre des pilotes en mode noyau en couches pour un appareil. Ne confondez pas les interfaces exposées par cette IRP avec les interfaces d’appareil. Une interface d’appareil est principalement utilisée pour exposer un chemin d’accès à un appareil à utiliser par des composants en mode utilisateur ou d’autres composants du noyau. Pour plus d’informations sur les interfaces d’appareil, consultez Classes d’interface d’appareil.

Envoi de cette IRP

Pour plus d’informations sur l’envoi des IRP, consultez Gestion des irps . Les étapes suivantes s’appliquent spécifiquement à cette IRP :

  • Allouez une structure INTERFACE à partir d’un pool paginé et initialisez-la à zéros. Si l’interface est appelée à l’adresse IRQL >= DISPATCH_LEVEL, en fonction du contrat d’interface, l’appelant peut copier le contenu en mémoire alloué à partir d’un pool non paginé.

  • Définissez les valeurs dans l’emplacement de pile d’E/S suivant de l’IRP : définissez MajorFunction sur IRP_MJ_PNP, définissez MinorFunction sur IRP_MN_QUERY_INTERFACE et définissez les valeurs appropriées dans Parameters.QueryInterface.

  • Initialisez IoStatus.Status sur STATUS_NOT_SUPPORTED.

  • Libérez l’IRP et la structure INTERFACE quand ils ne sont plus nécessaires.

  • Utilisez les routines d’interface et le paramètre de contexte, comme décrit dans la spécification de l’interface.

  • Décrémentez le nombre de références à l’aide de la routine InterfaceDereference lorsque l’interface n’est plus nécessaire. N’appelez aucune routine d’interface après la déréférencement de l’interface.

Un pilote envoie généralement cette IRP en haut de la pile de périphériques dans laquelle le pilote est attaché. Si un pilote envoie cette IRP à une autre pile de périphériques, le pilote doit s’inscrire à la notification de périphérique cible sur l’autre appareil si l’autre appareil n’est pas un ancêtre de l’appareil que le pilote entretient. Un tel pilote appelle IoRegisterPlugPlayNotification avec un EventCategoryde EventCategoryTargetDeviceChange. Lorsque le pilote reçoit une notification de type GUID_TARGET_DEVICE_QUERY_REMOVE, il doit déréférencer l’interface. Le pilote peut effectuer une nouvelle requête pour l’interface s’il reçoit une notification de GUID_TARGET_DEVICE_REMOVE_CANCELLED suivante.

Spécifications

En-tête

Wdm.h (inclure Wdm.h, Ntddk.h ou Ntifs.h)

Voir aussi

BUS_INTERFACE_STANDARD

INTERFACE

IoRegisterPlugPlayNotification