De l’exemple de code au pilote de production - Ce qu’il faut modifier dans les exemples

Cette rubrique décrit les modifications importantes qui doivent être apportées aux pilotes d’exemple WDK avant de publier des pilotes de périphérique basés sur le code d’exemple.

En plus des modifications décrites ici, tous les pilotes doivent utiliser les bonnes pratiques décrites dans Créer des pilotes en mode noyau fiables et dans Bonnes pratiques de développement de pilotes de l’équipe Surface. Tous les pilotes doivent également respecter les directives fournies dans Directives de sécurité des pilotes.

Échantillons de pilotes WDK - Identificateurs uniques

Le Windows Driver Kit (WDK) contient une grande variété de pilotes d’exemple qui démontrent des techniques utiles pour le développement de pilotes. Vous pouvez utiliser ces exemples comme base pour vos propres pilotes, mais avant de publier le pilote, vous devez modifier certains aspects spécifiques à l’appareil de l’exemple, au-delà du simple code opérationnel, pour qu’ils s’appliquent de manière unique à votre propre appareil et pilote. Les rédacteurs de pilotes négligent parfois ces détails.

Les éléments exacts que vous devez modifier varient d’un exemple à l’autre, mais en général, ils identifient un appareil, une interface ou un pilote spécifique. Par exemple, si le pilote d’exemple contient l’un des éléments suivants, vous devez les modifier pour les adapter à votre pilote et appareil :

  • Identificateurs uniques globaux (GUIDs)

  • Noms de liens symboliques

  • Nom de l’objet appareil

  • Étiquettes de pool

  • Définitions des codes de contrôle d’E/S (IOCTL)

  • Noms de tous les fichiers copiés dans le dossier système

  • ID de périphérique Plug and Play, ID matériel et ID compatibles

  • Nom du service du pilote

  • Description de l’appareil

  • Fichier de ressources

Oublier de faire ces modifications peut entraîner l’échec de l’installation, des conflits avec d’autres appareils et pilotes sur le système, ainsi que des difficultés de débogage, et d’autres erreurs.

Par exemple, si vous recevez une erreur telle que ...\toastDrv\kmdf\toastmon\wdftoastmon.inx(18-18): error 1284: Class "Sample" is reserved for use by Microsoft., cela indique que le nom "Sample" doit être changé pour un nom unique pour votre pilote d’exemple.

GUID

Les pilotes utilisent des GUIDs pour identifier les classes de configuration des périphériques, les classes d’interface des périphériques, les événements personnalisés PnP, les événements personnalisés Windows Management Instrumentation (WMI), et les fournisseurs de traces Windows PreProcessor (WPP). Certains GUIDs sont définis par Microsoft, et d’autres sont définis par les vendeurs de périphériques et de pilotes.

Les GUIDs de classe de configuration des périphériques, les GUIDs de classe d’interface de périphérique et les GUIDs WMI pour les périphériques courants et les données WMI sont définis dans le WDK ou dans des fichiers d’en-tête publics pour être utilisés par n’importe quel pilote. Vous ne devez pas changer ces GUIDs.

Par exemple, si vous implémentez une souris, vous continuerez d’utiliser GUID_DEVINTERFACE_MOUSE, qui est défini dans le fichier d’en-tête Ntddmou.h du WDK, en tant que classe d’interface de périphérique. Cependant, si vous définissez une nouvelle classe de configuration de périphérique, vous devez générer un nouveau GUID de classe de configuration de périphérique et un nom de classe de configuration, et éventuellement un nouveau GUID de classe d’interface de périphérique également. Le GUID de classe de configuration et le GUID de classe d’interface de périphérique doivent être des valeurs uniques ; ils ne peuvent pas partager un GUID.

Pour la plupart des pilotes basés sur des exemples, vous devez uniquement changer les GUIDs définis dans l’en-tête local ou le fichier source de l’exemple et qui sont donc spécifiques à l’exemple. Ces GUIDs peuvent inclure les suivants :

  • Événements personnalisés PnP

  • Événements personnalisés WMI

  • Classes d’interface de périphérique pour les nouveaux appareils ou appareils personnalisés

  • Fournisseurs de traces WPP

L’utilisation d’un GUID défini pour un autre pilote peut provoquer des conflits si les deux pilotes sont chargés sur le même système. Par exemple, si deux pilotes différents utilisent le même GUID pour enregistrer une interface de périphérique, les clients qui essaient d’ouvrir l’interface de périphérique pourraient ouvrir par inadvertance le mauvais périphérique.

L’extrait suivant provient du fichier Driver.h inclus dans tous les exemples de pilotes Toaster. Il définit le GUID de l’interface de périphérique pour les appareils Toaster :

DEFINE_GUID(GUID_TOASTER_INTERFACE_STANDARD, \
            0xe0b27630, 0x5434, 0x11d3, 0xb8, 0x90, 0x0, 0xc0, \
            0x4f, 0xad, 0x51, 0x71);
// {E0B27630-5434-11d3-B890-00C04FAD5171}

Si vous utilisez ce fichier dans votre propre pilote, assurez-vous de remplacer le GUID d’exemple (affiché ci-dessus en gras) par le GUID de l’interface pour votre propre appareil. Pour créer un GUID, utilisez l’outil Create GUID dans Microsoft Visual Studio ou Guidgen.exe, tous deux inclus dans le kit de développement logiciel (SDK) Microsoft Windows. Vous pouvez ensuite associer le GUID à une constante symbolique dans le fichier d’en-tête du pilote, comme le montre l’exemple.

Il peut également être nécessaire de créer de nouveaux GUIDs pour les événements WMI du pilote. Les exemples de pilotes Toaster définissent le GUID suivant pour la notification de l’arrivée d’un appareil Toaster :

DEFINE_GUID (TOASTER_NOTIFY_DEVICE_ARRIVAL_EVENT, \
             0x1cdaff1, 0xc901, 0x45b4, 0xb3, 0x59, 0xb5, 0x54, \
             0x27, 0x25, 0xe2, 0x9c);
// {01CDAFF1-C901-45b4-B359-B5542725E29C}

Vous devez créer un nouveau GUID pour chaque événement WMI dans votre pilote.

Si le pilote d’exemple utilise la journalisation logicielle WPP, générez un nouveau GUID de fournisseur de traces pour tous les pilotes que vous basez sur l’exemple. Par exemple, le fichier d’en-tête Trace.h de l’exemple Osrusbfx2 dans %WinDDK%\Src\Kmdf\Osrusbfx2\Final définit un GUID de contrôle comme suit :

#define WPP_CONTROL_GUIDS \
    WPP_DEFINE_CONTROL_GUID( \
           OsrUsbFxTraceGuid,(d23a0c5a,d307,4f0e,ae8e,E2A355AD5DAB), \
        WPP_DEFINE_BIT(DBG_INIT)          /* bit  0 = 0x00000001 */ \
        WPP_DEFINE_BIT(DBG_PNP)           /* bit  1 = 0x00000002 */ \
        WPP_DEFINE_BIT(DBG_POWER)         /* bit  2 = 0x00000004 */ \
        WPP_DEFINE_BIT(DBG_WMI)           /* bit  3 = 0x00000008 */ \
        WPP_DEFINE_BIT(DBG_CREATE_CLOSE)  /* bit  4 = 0x00000010 */ \
        WPP_DEFINE_BIT(DBG_IOCTL)         /* bit  5 = 0x00000020 */ \
        WPP_DEFINE_BIT(DBG_WRITE)         /* bit  6 = 0x00000040 */ \
        WPP_DEFINE_BIT(DBG_READ)          /* bit  7 = 0x00000080 */ \
       )

Dans votre propre pilote, vous remplaceriez le texte en gras par un nom spécifique au pilote et le GUID que vous avez créé.

Si l’exemple définit un nom de lien symbolique, remplacez le nom de l’exemple par un nom applicable à votre propre pilote. Cependant, ne changez pas les noms de lien bien connus comme \DosDevices\COM1. En général, si le nom de lien est assez similaire au nom de l’exemple (tel que \DosDevices\CancelSamp), vous devriez le modifier.

L’utilisation du même lien symbolique qu’un autre pilote a le même effet que l’utilisation du mauvais GUID d’interface de périphérique, car les interfaces de périphériques sont essentiellement des liens symboliques.

Le pilote de filtre KMDF Toaster dans %WinDDK\Src\Kmdf\Toaster\Filter crée un nom de lien symbolique qui utilise une chaîne définie comme suit dans le fichier d’en-tête Filter.h :

#define SYMBOLIC_NAME_STRING     L"\\DosDevices\\ToasterFilter"

Modifiez la chaîne en gras pour décrire plus précisément votre propre pilote.

Nom de l’objet appareil

Si l’exemple crée un nom pour l’objet appareil, vous devez changer le nom lorsque vous adaptez le code de l’exemple.

Le pilote de filtre KMDF Toaster nomme son objet appareil dans le fichier d’en-tête Filter.h comme suit :

#define NTDEVICE_NAME_STRING      L\\Device\\ToasterFilter

Comme pour le nom du lien symbolique, vous devez modifier la chaîne pour décrire votre pilote.

Rappelez-vous que les objets appareil nommés peuvent représenter un risque pour la sécurité. Les objets appareils physiques (PDO) doivent avoir des noms, et la plupart de ces noms sont générés par le système plutôt que spécifiquement attribués par un pilote. Les autres objets appareils ne devraient être nommés que s’ils représentent des objets appareils de contrôle, qui sont utilisés pour la communication hors bande entre une application et un pilote. Le framework de pilotes en mode noyau (KMDF) et le modèle de pilotes Windows (WDM) vous permettent tous deux de laisser Windows générer le nom. Cette approche garantit que le nom de l’objet appareil est unique et que les utilisateurs non privilégiés ne peuvent pas y accéder. Pour plus de détails, consultez Contrôle de l’accès à l’espace de noms des périphériques et Contrôle de l’accès aux périphériques dans les pilotes KMDF.

Étiquettes de pool

Une étiquette de pool est un littéral d’un à quatre caractères qui identifie une allocation de mémoire spécifique et peut faciliter le débogage.

De nombreux pilotes d’exemple définissent une étiquette de pool dans le fichier d’en-tête du pilote, comme dans la ligne suivante de Toaster.h :

#define TOASTER_POOL_TAG (ULONG) 'saoT'

Le pilote définit l’étiquette à l’envers car le débogueur l’affiche dans l’ordre inverse. Ainsi, cette étiquette apparaît comme Toas dans la sortie du débogueur. Au lieu d’utiliser l’étiquette définie par l’exemple, modifiez la chaîne pour identifier de manière unique votre propre code.

Le fichier Pooltag.txt répertorie les étiquettes de pool utilisées par les composants en mode noyau et les pilotes fournis avec Windows. Pooltag.txt est installé avec le WDK dans %winddk%\Tools\Other<i>platform\Poolmon, où platform est amd64, i386 ou ia64. N’utilisez aucune des étiquettes qui apparaissent dans cette liste.

Définitions IOCTL

Modifiez les codes de contrôle d’E/S définis dans l’exemple pour utiliser un nom, un type de périphérique, un code fonction, un type de transfert et un type d’accès qui sont appropriés pour votre périphérique et pilote.

Par exemple, l’exemple Osrusbfx2 inclut la définition suivante pour IOCTL_OSRUSBFX2_READ_SWITCHES :

#define IOCTL_OSRUSBFX2_READ_SWITCHES   
                    CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
                             IOCTL_INDEX + 6, \
                             METHOD_BUFFERED, \
                             FILE_READ_ACCESS)

Un pilote basé sur un exemple pour un périphérique différent nécessiterait des modifications à cette définition.

Noms de fichiers

Dans le fichier INF ou INX, modifiez les noms du pilote, du co-installeur fourni par le vendeur, et de tout autre fichier que la procédure d’installation copie dans le dossier système. Ces noms de fichiers apparaissent généralement dans les sections [SourceDisksFiles] et [ClassInstall32] de l’INF et dans les entrées CopyFiles.

L’exemple suivant provient du fichier INX de l’exemple KMDF Featured Toaster, disponible dans %WinDDK%\src\kmdf\Toaster\Func\Featured. Les noms de fichiers qui doivent être modifiés sont affichés en gras :

[ClassInstall32]
Addreg=ToasterClassReg
CopyFiles=ToasterClassInstallerCopyFileshighlight

[ToasterClassReg]
...
HKR,,Installer32,,"tostrcls.dll,ToasterClassInstaller"
...

[ToasterClassInstallerCopyFiles]
tostrcls.dll									    
...

Pour adapter cette partie du fichier à un autre pilote, vous remplaceriez « tostrcls.dll » par le nom de fichier de votre installateur de classe et vous modifieriez la chaîne « ToasterClassInstaller » pour décrire votre propre installateur. Ces modifications garantissent que la procédure d’installation copie le bon fichier de co-installeur et que la clé de registre enregistre le nom de fichier correct.

Ne changez pas le nom des co-installeurs fournis dans le WDK ou avec Windows, tels que les co-installeurs KMDF, UMDF et WinUSB.

Des modifications supplémentaires sont requises plus tard dans la section Device Install du fichier, comme montré dans cet exemple :

[Toaster_Device.NT]
CopyFiles=Toaster_Device.NT.Copy

[Toaster_Device.NT.Copy]
wdffeatured.sys

Dans cet exemple, vous modifieriez le nom de fichier en gras pour le remplacer par le nom de votre fichier de pilote généré.

Lorsque Setup copie les fichiers INF et de catalogue du pilote, il les renomme, donc il n’est pas strictement nécessaire de modifier leurs noms dans votre package de pilote. Cependant, il est généralement recommandé de s’assurer que les noms de fichiers INF et de catalogue sont similaires au nom du fichier de pilote.

ID de périphérique PnP, ID matériel et ID compatibles

Setup utilise l’ID de périphérique ainsi que les ID matériels et les ID compatibles pour sélectionner l’INF à utiliser pour l’installation du périphérique.

L’ID de périphérique est une chaîne définie par le vendeur qui identifie de manière unique un périphérique spécifique. Chaque périphérique a exactement un ID de périphérique. Le pilote de bus signale l’ID de périphérique lors de l’énumération, et Setup l’utilise pour faire correspondre le périphérique avec le fichier INF approprié. L’ID de périphérique est défini dans la section [Manufacturer] de l’INF.

L’exemple suivant montre l’ID de périphérique pour le périphérique OSR USB Fx2, tel qu’il est spécifié dans le fichier Osrusbfx2.inx :

[Manufacturer]
%MfgName%=Microsoft,NT$ARCH$

; For Win2K
[Microsoft]
%USB\VID_045E&PID_930A.DeviceDesc%=osrusbfx2.Dev, 
        USB\VID_0547&PID_1002
...

; For XP and later
[Microsoft.NT$ARCH$]
%USB\VID_045E&PID_930A.DeviceDesc%=osrusbfx2.Dev, 
        USB\VID_0547&PID_1002

Pour adapter cette directive INF à votre propre pilote, remplacez l’ID de périphérique affiché en gras par l’ID de périphérique pour votre propre périphérique. Vous devriez également modifier le nom du fabricant par le nom de votre entreprise.

L’ID matériel et l’ID compatible sont des identifiants moins spécifiques que Setup utilise s’il ne peut pas faire correspondre l’ID de périphérique à un INF. Si votre INF peut prendre en charge d’autres périphériques, vous devriez modifier ces valeurs en plus de l’ID de périphérique. L’exemple suivant du pilote KMDF Featured Toaster montre un ID matériel :

[Manufacturer]
%StdMfg%=Standard,NT$ARCH$

; For Win2K
[Standard]
; DisplayName                   Section           DeviceId
; -----------                   -------           --------
%ToasterDevice.DeviceDesc%=Toaster_Device, 
         {b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster

; For XP and later
[Standard.NT$ARCH$]
%ToasterDevice.DeviceDesc%=Toaster_Device, 
         {b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster

Pour adapter cette directive INF à votre propre pilote, remplacez l’ID matériel par l’ID de périphérique de votre pilote et changez « MsToaster » par une chaîne plus descriptive.

Nom du service du pilote

Mettez à jour le nom du service dans la directive AddService du fichier INF par une valeur appropriée à votre pilote. Si le nom du service du pilote entre en conflit avec celui d’un autre pilote sur le système, le pilote ne s’installera pas ou ne se chargera pas.

Le pilote KMDF Featured Toaster nomme son service comme suit :

[Toaster_Device.NT.Services]
AddService = wdffeatured, %SPSVCINST_ASSOCSERVICE%,
     wdffeatured_Service_Inst
      

Le nom du service est la première entrée dans la directive AddService. Pour adapter l’INF du Toaster avec fonctionnalités, vous remplaceriez la chaîne en gras par une chaîne plus adaptée à votre pilote. Dans l’exemple, l’entrée wdffeatured_Service_Inst fait simplement référence à une section définie dans l’INF, donc il n’est pas crucial de la modifier.

Description de l’appareil

La description du périphérique consiste en plusieurs chaînes qui sont généralement définies dans la section [Strings] de l’INF et sont utilisées à divers endroits dans l’INF. Par exemple, l’exemple KMDF Featured Toaster définit les chaînes suivantes dans le fichier WdfFeatured.inx :

[Strings]
SPSVCINST_ASSOCSERVICE   = 0x00000002
MSFT                     = "Microsoft"
StdMfg                   = "(Standard system devices)"
ClassName                = "Toaster"
DiskId1                  = "Toaster Device Installation Disk #1"
ToasterDevice.DeviceDesc = "Microsoft WDF Featured Toaster"
Toaster.SVCDESC          = "Microsoft WDF Toaster Featured Device Driver"

Pour modifier ce fichier afin d’installer votre propre pilote, vous devez changer les chaînes en gras pour refléter des informations sur votre entreprise, périphérique et pilote.

Si le nom de l’entreprise apparaît également dans une section [Manufacturer] de l’INF, vous devez également modifier ce nom.

Fichier de ressources

Les pilotes et autres composants tels que les co-installeurs spécifiques à l’exemple ont également des fichiers de ressources (.rc), qui définissent des chaînes spécifiques aux pilotes, y compris le nom du produit, la version du fichier et le nom de l’entreprise. Modifiez ces chaînes pour des valeurs appropriées à votre package de pilote.

Résumé - Que devez-vous faire ?

Avant de publier un pilote basé sur un exemple WDK, remplacez toutes les informations spécifiques à l’exemple dans les fichiers source, le fichier INF et toute autre ressource que vous avez utilisée pour créer votre propre pilote. Les modifications nécessaires varient d’un exemple à l’autre, mais incluent généralement toute information qui identifie de manière unique le pilote d’exemple ou son appareil. Voici quelques exemples typiques des modifications que vous devez apporter :

  • Générez et utilisez des GUIDs spécifiques à votre pilote, le cas échéant.

  • Mettez à jour le nom du lien symbolique.

  • Mettez à jour le nom de l’objet appareil ou utilisez un nom généré automatiquement.

  • Utilisez des étiquettes de pool qui identifient votre pilote et n’entrent pas en conflit avec des étiquettes connues.

  • Définissez des codes IOCTL appropriés à votre pilote et appareil.

  • Mettez à jour les noms de tous les fichiers copiés dans le dossier système.

  • Insérez l’ID de périphérique Plug and Play correct, les ID matériels et les ID compatibles dans l’INF.

  • Mettez à jour le nom du service du pilote dans l’INF.

  • Modifiez la description du périphérique.

  • Modifiez toutes les chaînes spécifiques au pilote dans le fichier de ressources.

  • Respectez les bonnes pratiques de sécurité et de fiabilité

Informations supplémentaires

Livres

Développement de pilotes avec la Windows Driver Foundation, par Penny Orwick et Guy Smith

Rubriques WDK

Définition et exportation de nouveaux GUID

Contrôle de l’accès aux appareils dans les pilotes KMDF

Développement, test et déploiement de pilotes

Création de pilotes fiables en mode noyau

Meilleures pratiques de développement de pilotes de l'équipe Surface

Conseils de sécurité pour les pilotes

Écrire votre premier pilote