Partager via


Isolation du package de pilote

L’isolation du package de pilote est une exigence pour les pilotes Windows qui rend les packages de pilotes plus résilients aux changements externes, plus faciles à mettre à jour et plus simples à installer.

Remarque

Bien que l’isolation du package de pilote soit requise pour les pilotes Windows, les pilotes Windows Desktop en bénéficient également en termes de résilience et de maintenabilité améliorées.

Le tableau suivant montre, dans la colonne de gauche, certaines pratiques de package de pilote héritées qui ne sont plus autorisées pour les pilotes Windows, ainsi que le comportement requis pour les pilotes Windows dans la colonne de droite.

Pilote non isolé Pilote isolé
INF copie des fichiers dans %windir%\System32 ou %windir%\System32\drivers Les fichiers du pilote sont exécutés à partir du magasin de pilotes
Interagit avec les piles de dispositifs/pilotes en utilisant des chemins codés en dur Interagit avec les piles de dispositifs/pilotes en utilisant des fonctions fournies par le système ou des interfaces de dispositifs
Code en dur le chemin vers des emplacements globaux du registre Utilise HKR et des fonctions fournies par le système pour la localisation relative du registre et l’état des fichiers
Écrit des fichiers à n’importe quel emplacement à l’exécution Les fichiers sont écrits de manière relative aux emplacements fournis par le système d’exploitation

Pour obtenir de l’aide afin de déterminer si votre package de pilote respecte les exigences d’isolation du package de pilote, veuillez consulter la section Validation des pilotes Windows. Pour des exemples de mise à jour d’un INF afin de respecter les exigences d’isolation du package de pilote, veuillez consulter la section Portage d’un INF pour suivre l’isolation du package de pilote.

Exécution à partir du magasin de pilotes

Tous les packages de pilotes isolés laissent leurs fichiers de package de pilote dans le magasin de pilotes. Cela signifie qu’ils spécifient DIRID 13 dans leur INF pour indiquer l’emplacement des fichiers du package de pilote lors de l’installation. Pour plus d’informations sur l’utilisation de cette option dans un package de pilote, veuillez consulter la section Exécution à partir du magasin de pilotes.

Lecture et écriture d’état

Remarque

Si votre composant utilise les propriétés de dispositif ou d’interface de dispositif pour stocker l’état, continuez d’utiliser cette méthode et les API appropriées du système d’exploitation pour stocker et accéder à l’état. Les conseils suivants concernant l’état du registre et des fichiers concernent d’autres états qui doivent être stockés par un composant.

L’accès à divers états de registre et de fichiers doit se faire en appelant des fonctions qui fournissent à l’appelant l’emplacement de l’état, puis cet état est lu/écrit de manière relative à cet emplacement. N’utilisez pas de chemins de registre absolus et codés en dur, ni de chemins de fichiers.

Cette section comporte les sous-sections suivantes :

État du registre

Cette section comporte les sous-sections suivantes :

État du registre des dispositifs PnP

Les packages de pilotes isolés et les composants en mode utilisateur utilisent généralement l’un des deux emplacements suivants pour stocker l’état des dispositifs dans le registre. Il s’agit de la clé matérielle (clé de dispositif) pour le dispositif et de la clé logicielle (clé du pilote) pour le dispositif. La clé matérielle est généralement utilisée pour les paramètres relatifs à la manière dont une instance de dispositif interagit avec le matériel. Par exemple, pour activer une fonctionnalité matérielle ou mettre le matériel dans un mode spécifique. La clé logicielle est généralement utilisée pour les paramètres relatifs à la manière dont une instance de dispositif interagit avec le système et les autres logiciels. Par exemple, pour configurer l’emplacement d’un fichier de données, pour interagir avec un framework, ou pour accéder aux paramètres d’application d’un dispositif. Pour récupérer un handle vers ces emplacements du registre, utilisez l’une des options suivantes :

[ExampleDDInstall.HW]
AddReg = Example_DDInstall.AddReg

[Example_DDInstall.AddReg] 
HKR,,ExampleValue,,%13%\ExampleFile.dll

État du registre de l’interface des dispositifs

Pour lire et écrire l’état du registre de l’interface des dispositifs, utilisez l’une des options suivantes :

État du registre du service

L’état du service doit être classé en l’une des 3 catégories suivantes :

État immuable du registre du service

L’état immuable du service est l’état fourni par le package de pilotes qui installe le service. Ces valeurs de registre, définies par l’INF pour les services de pilotes et Win32, doivent être stockées sous la sous-clé « Parameters » du service en fournissant une ligne HKR dans une section AddReg, puis en référant cette section dans la section d’installation du service dans l’INF. Par exemple :

[ExampleDDInstall.Services]
Addservice = ExampleService, 0x2, Example_Service_Inst

[Example_Service_Inst]
DisplayName    = %ExampleService.SvcDesc%
ServiceType    = 1
StartType      = 3
ErrorControl   = 1
ServiceBinary  = %13%\ExampleService.sys
AddReg=Example_Service_Inst.AddReg

[Example_Service_Inst.AddReg]
HKR, Parameters, ExampleValue, 0x00010001, 1

Pour accéder à l’emplacement de cet état à partir du service à l’exécution, utilisez l’une de ces fonctions :

Ces valeurs de registre fournies par l’INF dans la sous-clé « Parameters » du service ne doivent être lues qu’à l’exécution et ne doivent pas être modifiées. Elles doivent être traitées comme des données en lecture seule.

Si les valeurs de registre fournies par l’INF sont des paramètres par défaut qui peuvent être remplacés à l’exécution, les valeurs de remplacement doivent être écrites dans l’État interne du registre du service ou dans l’État partagé du registre du service pour le service. Lors de la récupération des paramètres, le paramètre peut être recherché d’abord dans l’état mutable. S’il n’existe pas à cet endroit, alors le paramètre peut être recherché dans l’état immuable. RtlQueryRegistryValueWithFallback peut être utilisé pour aider à interroger des paramètres comme ceux-ci, qui ont une valeur de remplacement et une valeur par défaut.

État interne du registre du service

L’état interne du service est un état écrit à l’exécution, possédé et géré uniquement par le service lui-même et n’est accessible qu’à ce service. Pour accéder à l’emplacement de l’état interne du service, utilisez l’une de ces fonctions à partir du service :

Si le service souhaite permettre à d’autres composants de modifier ces paramètres, le service doit exposer une interface qu’un autre composant peut appeler pour indiquer au service comment modifier ces paramètres. Par exemple, un service Win32 pourrait exposer une interface COM ou RPC et un service de pilote pourrait exposer une interface IOCTL via une interface de dispositif.

État partagé du registre du service

L’état partagé du service est un état écrit à l’exécution et peut être partagé avec d’autres composants en mode utilisateur s’ils sont suffisamment privilégiés. Pour accéder à l’emplacement de cet état partagé du service, utilisez l’une de ces fonctions :

État des fichiers

Cette section comporte les sous-sections suivantes :

État des fichiers de dispositif

Si des fichiers liés à un dispositif doivent être écrits à l’exécution, ces fichiers doivent être stockés de manière relative à un handle ou un chemin de fichier fourni via les API du système d’exploitation. Les fichiers de configuration spécifiques à ce dispositif sont un exemple des types de fichiers à stocker ici. Pour accéder à l’emplacement de cet état partagé du service, utilisez l’une de ces fonctions :

État des fichiers de service

L’état des fichiers de service peut être classé dans l’une des 3 catégories suivantes :

État immuable des fichiers de service

L’état immuable des fichiers de service correspond aux fichiers qui font partie du package de pilotes. Pour plus d’informations sur l’accès à ces fichiers, veuillez consulter la section Exécution à partir du magasin de pilotes.

État interne des fichiers de service

L’état interne des fichiers de service est un état qui est écrit à l’exécution, possédé et géré uniquement par le service lui-même, et n’est accessible qu’à ce service. Pour accéder à l’emplacement de l’état interne du service, utilisez l’une de ces fonctions à partir du service :

Si le service souhaite permettre à d’autres composants de modifier ces paramètres, le service doit exposer une interface qu’un autre composant peut appeler pour indiquer au service comment modifier ces paramètres. Par exemple, un service Win32 pourrait exposer une interface COM ou RPC et un service de pilote pourrait exposer une interface IOCTL via une interface de dispositif.

État partagé des fichiers de service

L’état partagé des fichiers de service est un état écrit à l’exécution et peut être partagé avec d’autres composants en mode utilisateur s’ils sont suffisamment privilégiés. Pour accéder à l’emplacement de cet état partagé du service, utilisez l’une de ces fonctions :

  • IoGetDriverDirectory (WDM, KMDF) avec le paramètre DirectoryType défini sur DriverDirectorySharedData

  • GetSharedServiceDirectory (services Win32) avec le paramètre DirectoryType défini sur ServiceSharedDirectoryPersistentState

DriverData et ProgramData

Les fichiers qui peuvent être partagés avec d’autres composants mais qui ne correspondent pas à la catégorie état partagé des fichiers de service peuvent être écrits dans les emplacements DriverData ou ProgramData.

Ces emplacements offrent aux composants un endroit où écrire un état temporaire ou un état destiné à être consommé par d’autres composants, et potentiellement collecté et copié depuis un système pour être traité par un autre système. Par exemple, les fichiers journaux personnalisés ou les vidages de mémoire (crash dumps) correspondent à cette description.

Évitez d’écrire des fichiers à la racine des répertoires DriverData ou ProgramData. Au lieu de cela, créez un sous-répertoire avec le nom de votre entreprise, puis écrivez des fichiers et des sous-répertoires supplémentaires dans ce répertoire.

Par exemple, pour une entreprise nommée Contoso, un pilote en mode noyau pourrait écrire un journal personnalisé dans \DriverData\Contoso\Logs et une application en mode utilisateur pourrait collecter ou analyser les fichiers journaux à partir de %DriverData%\Contoso\Logs.

DriverData

Le répertoire DriverData est disponible dans Windows 10, version 1803 et versions ultérieures, et est accessible aux administrateurs et aux pilotes UMDF.

Les pilotes en mode noyau accèdent au répertoire DriverData en utilisant un lien symbolique fourni par le système appelé \DriverData.

Les programmes en mode utilisateur accèdent au répertoire DriverData en utilisant la variable d’environnement %DriverData%.

ProgramData

La variable d’environnement %ProgramData% en mode utilisateur est disponible pour que les composants en mode utilisateur puissent l’utiliser lorsqu’ils stockent des données.

Fichiers temporaires

Les fichiers temporaires sont généralement utilisés dans des opérations intermédiaires. Ils peuvent être écrits dans un sous-chemin sous les variables d’environnement %TEMP% ou %TMP%. Étant donné que ces emplacements sont accessibles via des variables d’environnement, cette capacité est limitée aux composants en mode utilisateur. Il n’y a aucune garantie sur la durée de vie ou la persistance de ces fichiers temporaires après la fermeture des handles les concernant. Le système d’exploitation ou l’utilisateur peut les supprimer à tout moment et ils peuvent ne pas persister après un redémarrage.

Évitez d’écrire des fichiers à la racine des répertoires %TEMP% ou %TMP%. Au lieu de cela, créez un sous-répertoire avec le nom de votre entreprise, puis écrivez des fichiers et des sous-répertoires supplémentaires dans ce répertoire.

État des propriétés

Les dispositifs et les interfaces de dispositifs prennent tous deux en charge le stockage d’état via le modèle de propriété PnP. Le modèle de propriété permet de stocker des données de propriété structurées sur un dispositif ou une interface de dispositif. Cela est destiné à des données de taille réduite qui correspondent raisonnablement aux types de propriétés pris en charge par le modèle de propriété.

Pour accéder aux propriétés des dispositifs, ces API peuvent être utilisées :

Pour accéder aux propriétés de l’interface du périphérique, les API suivantes peuvent être utilisées :

Utilisation des interfaces d’appareils

Si un pilote souhaite permettre à d’autres composants de lire ou de modifier l’état interne du pilote, celui-ci doit exposer une interface qu’un autre composant peut appeler pour indiquer au pilote quels paramètres retourner ou comment modifier certains paramètres. Par exemple, le service du pilote pourrait exposer une interface IOCTL via une interface de dispositif.

En général, le pilote qui possède l’état expose une interface de dispositif dans une classe d’interface de dispositif personnalisée. Lorsque le pilote est prêt à ce que d’autres composants aient accès à l’état, il active l’interface. Pour être notifiés lorsqu’une interface de dispositif est activée, les composants en mode utilisateur peuvent s’inscrire aux notifications d’arrivée d’interface de dispositif et les composants en mode noyau peuvent utiliser IoRegisterPlugPlayNotification. Pour que ces composants accèdent à l’état, le pilote activant l’interface doit définir un contrat pour sa classe d’interface de dispositif personnalisée. Ce contrat est généralement de deux types :

  • Un contrat E/S peut être associé à cette classe d’interface de dispositif, qui fournit un mécanisme d’accès à l’état. Les autres composants utilisent l’interface de dispositif activée pour envoyer des requêtes d’E/S conformes au contrat.

  • Une interface d’appel direct qui est renvoyée via une interface de requête. D’autres pilotes pourraient envoyer IRP_MN_QUERY_INTERFACE pour récupérer des pointeurs de fonction à partir du pilote à appeler.

Alternativement, si le pilote qui possède l’état permet un accès direct à celui-ci, d’autres pilotes pourraient accéder à l’état en utilisant des fonctions fournies par le système pour l’accès programmatique à l’état de l’interface de dispositif. Veuillez consulter la section État du registre de l’interface de dispositif pour plus d’informations.

Ces interfaces ou états (selon la méthode de partage utilisée) doivent être correctement versionnés afin que le pilote qui possède l’état puisse être mis à jour indépendamment des autres composants qui accèdent à cet état. Les fournisseurs de pilotes ne peuvent pas compter sur le fait que d’autres composants seront mis à jour en même temps que le pilote et resteront à la même version.

Étant donné que les dispositifs et les pilotes contrôlant les interfaces vont et viennent, les pilotes et applications doivent éviter d’appeler IoGetDeviceInterfaces au démarrage du composant pour obtenir une liste des interfaces activées. La meilleure approche consiste plutôt à s’inscrire aux notifications d’arrivée ou de suppression d’interface de dispositif, puis à appeler la fonction appropriée pour obtenir la liste des interfaces activées existantes sur la machine.

Pour plus d’informations sur les interfaces de dispositifs, consultez :

Référence rapide du support du système d’exploitation pour les API de gestion d’état

La plupart des packages de pilotes doivent prendre en charge une gamme de versions du système d’exploitation. Veuillez consulter la section Prise en charge de plusieurs versions du système d’exploitation pour plus d’informations sur la manière d’y parvenir dans un package de pilote. Les tableaux suivants fournissent une référence rapide du moment où le support du système d’exploitation a été ajouté pour diverses API de gestion d’état.

Pilotes WDM

Système d’exploitation Support ajouté
Windows 2000 IoOpenDeviceRegistryKey
IoOpenDeviceInterfaceRegistryKey
Windows Vista IoGetDevicePropertyData
IoSetDevicePropertyData
Windows 8 IoGetDeviceInterfacePropertyData
IoSetDeviceInterfacePropertyData
Windows 8.1 IoQueryFullDriverPath
Windows 10 1803 IoOpenDriverRegistryKey pour RegKeyType de DriverRegKeyParameters et DriverRegKeyPersistentState
IoGetDeviceDirectory
IoGetDriverDirectory pour DirectoryType de DriverDirectoryImage et DriverDirectoryData
Windows 10 1809 RtlQueryRegistryValueWithFallback
Windows 11 21H2 IoOpenDriverRegistryKey pour RegKeyType de DriverRegKeySharedPersistentState
IoGetDriverDirectory pour DirectoryType de DriverDirectorySharedData

Pilotes KMDF

Version KMDF Support ajouté
1.0 WdfDeviceOpenRegistryKey
WdfFdoInitOpenRegistryKey
WdfDriverOpenParametersRegistryKey
WdfDeviceQueryProperty
WdfDeviceAllocAndQueryProperty
WdfFdoInitQueryProperty
WdfFdoInitAllocAndQueryProperty
1.13 WdfDeviceQueryPropertyEx
WdfDeviceAllocAndQueryPropertyEx
WdfDeviceAssignProperty
WdfFdoInitQueryPropertyEx
WdfFdoInitAllocAndQueryPropertyEx
1,25 WdfDriverOpenPersistentStateRegistryKey (Windows 10 1803)

Pilotes UMDF

Version UMDF Support ajouté
2.0 WdfDeviceOpenRegistryKey
WdfFdoInitOpenRegistryKey
WdfDriverOpenParametersRegistryKey
WdfDeviceQueryProperty
WdfDeviceAllocAndQueryProperty
WdfDeviceQueryPropertyEx
WdfDeviceAllocAndQueryPropertyEx
WdfDeviceAssignProperty
WdfFdoInitQueryProperty
WdfFdoInitAllocAndQueryProperty
WdfFdoInitQueryPropertyEx
WdfFdoInitAllocAndQueryPropertyEx
WdfDeviceQueryInterfaceProperty (Windows 8.1)
WdfDeviceAllocAndQueryInterfaceProperty (Windows 8.1)
WdfDeviceAssignInterfaceProperty (Windows 8.1)
2.25 WdfDeviceRetrieveDeviceDirectoryString
WdfDriverOpenPersistentStateRegistryKey (Windows 10 1803)
2,27 WdfDriverRetrieveDriverDataDirectoryString

Code en mode utilisateur

Système d’exploitation Support ajouté
Windows 2000 CM_Open_DevNode_Key
Windows Vista CM_Open_Device_Interface_Key
CM_Get_DevNode_Property
CM_Set_DevNode_Property
CM_Get_Device_Interface_Property
CM_Set_Device_Interface_Property
Windows 10 2004 GetServiceRegistryStateKey
GetServiceDirectory
Windows 11 21H2 GetSharedServiceRegistryStateKey
GetSharedServiceDirectory