Partager via


Prise en charge des clients Kernel-Mode dans les pilotes UMDF 1.x

Avertissement

UMDF 2 est la dernière version d’UMDF et remplace UMDF 1. Tous les nouveaux pilotes UMDF doivent être écrits à l’aide d’UMDF 2. Aucune nouvelle fonctionnalité n’est ajoutée à UMDF 1 et la prise en charge d’UMDF 1 est limitée sur les versions plus récentes de Windows 10. Les pilotes Windows universels doivent utiliser UMDF 2.

Les exemples UMDF 1 archivés se trouvent dans la Windows 11, version 22H2 - Mise à jour des exemples de pilotes de mai 2022.

Pour plus d’informations, consultez Prise en main avec UMDF.

Avertissement

Consultez également Prise en charge des clients Kernel-Mode dans UMDF 2.x.

Les versions UMDF 1.9 et ultérieures autorisent les pilotes UMDF à prendre en charge les clients en mode noyau. Un client en mode noyau peut être l’un des éléments suivants :

  • Pilote en mode noyau qui existe au-dessus d’un pilote UMDF dans la pile de pilotes d’un appareil.

  • Un pilote en mode noyau pour une pile d’appareils, qui prend en charge un appareil, ouvre un handle sur un autre appareil, et la pile de pilotes de ce dernier appareil contient un pilote UMDF.

En d’autres termes, un pilote UMDF qui prend en charge les clients en mode noyau peut recevoir des demandes d’E/S d’un pilote en mode noyau. Le pilote en mode noyau peut transférer les demandes d’E/S qu’il a reçues d’une application en mode utilisateur, ou peut créer de nouvelles demandes d’E/S et les envoyer au pilote en mode utilisateur.

Pour déterminer si votre pilote UMDF doit prendre en charge les clients en mode noyau, vous devez comprendre la pile de pilotes à laquelle votre pilote sera ajouté et l’emplacement dans cette pile où résidera votre pilote. Vous devez également déterminer si un pilote d’une autre pile peut envoyer des demandes d’E/S à l’appareil de votre pilote.

Votre pilote doit prendre en charge les clients en mode noyau si :

  • Un pilote en mode noyau peut se trouver directement au-dessus de votre pilote UMDF dans une pile de pilotes. Par exemple, un pilote de filtre en mode noyau peut se trouver directement au-dessus d’un pilote de fonction basé sur UMDF.

  • Un pilote en mode noyau d’une autre pile peut envoyer des demandes d’E/S à l’appareil de votre pilote. Par exemple, votre pilote peut créer un lien symbolique qu’un pilote en mode noyau d’une autre pile peut utiliser pour ouvrir un handle sur l’appareil de votre pilote. Le pilote en mode noyau peut ensuite envoyer des demandes d’E/S à l’appareil.

Comment prendre en charge les clients en mode noyau dans un pilote UMDF

Un pilote UMDF peut recevoir des demandes d’E/S d’un pilote en mode noyau uniquement si le pilote UMDF a activé la prise en charge des clients en mode noyau. En outre, si une installation d’appareil tente de charger des pilotes en mode noyau au-dessus d’un pilote UMDF dans la pile de pilotes de l’appareil, l’infrastructure autorise les pilotes à se charger uniquement si le pilote UMDF a activé la prise en charge des clients en mode noyau.

Pour activer la prise en charge d’un pilote UMDF pour les clients en mode noyau, le fichier INF du pilote UMDF doit inclure une directive UmdfKernelModeClientPolicy dans son DDInstall INF. Section WDF . Si le fichier INF du pilote UMDF n’inclut pas cette directive, UMDF n’autorise pas l’exécution d’un pilote en mode noyau installé au-dessus du pilote UMDF.

L’infrastructure fournit deux méthodes utiles pour les pilotes qui prennent en charge les clients en mode noyau. Un pilote peut appeler la méthode IWDFIoRequest2::GetRequestorMode pour déterminer si une requête d’E/S provient du mode noyau ou du mode utilisateur. Si la demande d’E/S provient du mode utilisateur, le pilote peut appeler IWDFIoRequest2::IsFromUserModeDriver pour déterminer si la demande provient d’une application ou d’un autre pilote en mode utilisateur.

Restrictions sur les pilotes en mode noyau

Un pilote UMDF peut traiter les demandes d’E/S à partir d’un pilote en mode noyau uniquement si le pilote en mode noyau répond aux exigences suivantes :

  • Le pilote en mode noyau doit s’exécuter à IRQL = PASSIVE_LEVEL quand il envoie la demande d’E/S.

  • À moins que le pilote n’ait défini la directive INF UmdfFileObjectPolicy sur AllowNullAndUnknownFileObjects, chaque demande d’E/S envoyée par un pilote en mode noyau à un pilote en mode utilisateur doit avoir un objet de fichier associé. L’infrastructure doit avoir été informée que le gestionnaire d’E/S a créé l’objet de fichier. (Une telle notification entraîne l’appel de la fonction de rappel IQueueCallbackCreate::OnCreateFile du pilote en mode utilisateur, mais cette fonction de rappel est facultative.)

  • La demande d’E/S ne peut pas contenir de code de fonction IRP_MJ_INTERNAL_DEVICE_CONTROL .

  • Les mémoires tampons de la demande d’E/S ne doivent pas contenir de pointeurs vers des informations supplémentaires, car le pilote en mode utilisateur ne peut pas déréférencer les pointeurs.

  • Si la demande d’E/S contient un code de contrôle d’E/S qui spécifie la méthode d’accès à la mémoire tampon « aucun », le pilote en mode noyau doit envoyer la demande d’E/S dans le contexte de processus de l’application qui a créé la demande d’E/S. Pour plus d’informations sur la prise en charge de la méthode « ni » dans un pilote de base UMDF, consultez Utilisation des E/S mises en mémoire tampon ni des E/S directes dans les pilotes UMDF.

  • Le pilote UMDF peut modifier les données de sortie d’une demande d’E/S, en mode utilisateur. Par conséquent, le pilote en mode noyau doit valider toutes les données de sortie qu’il reçoit du pilote en mode utilisateur.

  • Le client en mode noyau doit généralement valider la valeur Information qu’un pilote UMDF transmet à IWDFIoRequest::CompleteWithInformation. Si le client est un pilote KMDF, il peut appeler WdfRequestGetCompletionParams pour obtenir ces informations dans une structure IO_STATUS_BLOCK.

    En règle générale, l’infrastructure ne valide pas la valeur d’information qu’un pilote UMDF transmet à IWDFIoRequest::CompleteWithInformation. (Ce paramètre spécifie généralement le nombre d’octets transférés.) L’infrastructure valide la valeur des informations uniquement pour les mémoires tampons de sortie et uniquement pour la méthode d’accès aux données d’E/S mise en mémoire tampon . (Par exemple, l’infrastructure vérifie que le nombre d’octets transférés ne dépasse pas la taille de la mémoire tampon de sortie d’une opération de lecture, si la méthode d’accès est mise en mémoire tampon d’E/S.)

Gestion des valeurs de status de retour dans un pilote UMDF 1.x

Le passage de valeurs de retour status du mode utilisateur au mode noyau nécessite une attention particulière, comme suit :

  • Les pilotes UMDF version 1 reçoivent généralement des valeurs de retour de type HRESULT, tandis que les pilotes en mode noyau KMDF et WDM reçoivent généralement des valeurs de type NTSTATUS. Si un UMDF 1. x pilote effectue une demande d’E/S, et si le pilote a un client en mode noyau, l’appel du pilote à IWDFIoRequest::Complete ou IWDFIoRequest::CompleteWithInformation doit spécifier une valeur HRESULT que le pilote génère à partir d’une valeur NTSTATUS. En général, UMDF 1. Les pilotes x doivent utiliser la macro HRESULT_FROM_NT (définie dans Winerror.h) pour retourner status à un client en mode noyau. L’exemple suivant montre comment utiliser cette macro lors de l’exécution d’une demande.

    hr = HRESULT_FROM_NT(STATUS_BUFFER_OVERFLOW)
    request->Complete(HRESULT_FROM_NT(STATUS_BUFFER_OVERFLOW);
    return hr;
    

    Pour renvoyer une valeur HRESULT spécifique à un client en mode noyau, les rappels suivants doivent utiliser la macro HRESULT_FROM_NT :

    Pour utiliser les valeurs NTSTATUS définies dans ntstatus.h, un UMDF 1. Le pilote x doit inclure ces deux lignes avant d’inclure des en-têtes supplémentaires.

    #define UMDF_USING_NTSTATUS
    #include <ntstatus.h>
    

    N’utilisez pas la macro HRESULT_FROM_NT pour convertir STATUS_SUCCESS d’une valeur NTSTATUS en valeur HRESULT. Retournez simplement S_OK, comme illustré dans l’exemple suivant.

    request->Complete(S_OK);
    
  • L’infrastructure effectue certaines demandes d’E/S pour le compte des pilotes UMDF. Parfois, l’infrastructure ne convertit pas les valeurs de retour de type HRESULT en valeurs NTSTATUS équivalentes, de sorte que l’infrastructure peut passer une status d’achèvement de type HRESULT à un client en mode noyau.

    En raison de cette situation, les clients en mode noyau ne doivent pas utiliser la macro NT_ERROR lors du test de l’status d’achèvement d’une demande d’E/S, car la macro NT_ERROR ne retourne pas TRUE pour les valeurs d’erreur HRESULT. Les pilotes en mode noyau doivent utiliser la macro NT_SUCCESS lors du test de la status d’achèvement d’une demande d’E/S.

Prise en charge du client en mode noyau dans les versions antérieures d’UMDF

Pour les versions UMDF antérieures à la version 1.9, le fichier INF d’un pilote peut inclure une directive ADDReg INF pour créer une valeur de Registre UpperDriverOk de taille REG_DWORD sous la sous-clé WUDF de la clé matérielle de l’appareil.

Si la valeur de Registre UpperDriverOk est définie sur un nombre différent de zéro, l’infrastructure permet aux pilotes en mode noyau de se charger au-dessus du pilote en mode utilisateur. Les pilotes en mode noyau peuvent transférer des demandes d’E/S d’applications en mode utilisateur vers le pilote UMDF, mais les pilotes en mode noyau ne peuvent pas envoyer de demandes d’E/S créées en mode noyau au pilote UMDF.

Pour les versions UMDF 1.9 et ultérieures, la valeur de Registre UpperDriverOk est obsolète et prise en charge uniquement pour les pilotes existants. Les nouveaux pilotes doivent utiliser la directive UmdfKernelModeClientPolicy .