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 :
IoOpenDeviceRegistryKey (WDM)
CM_Open_DevNode_Key (code en mode utilisateur)
Directive INF AddReg utilisant des entrées HKR reg-root dans une add-registry-section référencée à partir d’une section INF DDInstall ou d’une section DDInstall.HW, comme illustré ci-dessous :
[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 :
CM_Open_Device_Interface_Key (code en mode utilisateur)
Directive INF AddReg utilisant des entrées HKR racine-registre dans une add-registry-section référencée à partir d’une add-interface-section
É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 :
IoOpenDriverRegistryKey (WDM) avec un DRIVER_REGKEY_TYPE de DriverRegKeyParameters
GetServiceRegistryStateKey (services Win32) avec un SERVICE_REGISTRY_STATE_TYPE de ServiceRegistryStateParameters
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 :
IoOpenDriverRegistryKey (WDM) avec un DRIVER_REGKEY_TYPE de DriverRegKeyPersistentState
GetServiceRegistryStateKey (services Win32) avec un SERVICE_REGISTRY_STATE_TYPE de ServiceRegistryStatePersistent
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 :
IoOpenDriverRegistryKey (WDM) avec un DRIVER_REGKEY_TYPE de DriverRegKeySharedPersistentState
GetSharedServiceRegistryStateKey (services Win32) avec un SERVICE_SHARED_REGISTRY_STATE_TYPE de ServiceSharedRegistryPersistentState
É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 :
IoGetDeviceDirectory (WDM) avec le paramètre DirectoryType défini sur DeviceDirectoryData
É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 :
IoGetDriverDirectory (WDM, KMDF) avec le paramètre DirectoryType défini sur DriverDirectoryData
GetServiceDirectory (services Win32) avec le paramètre eDirectoryType défini sur ServiceDirectoryPersistentState
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 :
Pilotes WDM
Pilotes WDF
Code en mode utilisateur
Pour accéder aux propriétés de l’interface du périphérique, les API suivantes peuvent être utilisées :
Pilotes WDM
Pilotes WDF
Code en mode utilisateur
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
Pilotes UMDF
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 |