Partager via


Ajouter le suivi logiciel WPP à un pilote Windows

Pour utiliser le traçage logiciel WPP dans un fournisseur de traçage, tel qu'un pilote en mode noyau ou une application en mode utilisateur, vous devez ajouter du code (ou instrumenter) les fichiers sources du pilote et modifier le projet du pilote. Cette section décrit ces étapes.

Note

Le moyen le plus simple d’ajouter le suivi WPP à votre pilote consiste à utiliser l’un des modèles de pilotes KMDF ou UMDF dans Visual Studio. Si vous utilisez les modèles, une grande partie du code que vous devez ajouter est déjà effectuée pour vous. Dans Visual Studio, sélectionnez Nouveau >> projet de fichier, puis sélectionnez le projet WDF Windows Driver (mode utilisateur ou mode noyau). Les macros WPP sont définies dans le fichier d’en-tête Trace.h inclus dans le cadre du projet. Si vous utilisez l’un des modèles, vous pouvez passer à l’étape 5.

Étape 1 : Définir le GUID de contrôle et les indicateurs de trace

Chaque fournisseur de trace (par exemple, un pilote ou une application en mode utilisateur) doit être défini de manière unique. Pour ce faire, ajoutez la macro WPP_CONTROL_GUIDS qui définit un GUID de contrôle, un identificateur et des indicateurs de trace. Pour cela, vous pouvez identifier et contrôler quand et ce que vous souhaitez tracer. Bien que chaque pilote possède généralement un GUID de contrôle distinct, un pilote peut avoir plusieurs GUID de contrôle, ou plusieurs pilotes peuvent partager un GUID de contrôle.

Pour plus de commodité, la macro WPP_CONTROL_GUIDS est généralement définie dans un fichier d’en-tête commun. Le fichier d’en-tête doit être inclus (#include) dans n’importe quel fichier source que vous souhaitez instrumenter pour le traçage.

Pour ajouter WPP_CONTROL_GUIDS macro à votre pilote :

  1. Ajoutez un nouveau fichier d’en-tête C++ à votre projet Visual Studio que vous pouvez utiliser pour définir les macros de trace WPP. Par exemple, sélectionnez et maintenez enfoncé (ou cliquez avec le bouton droit) le pilote dans l’Explorateur de solutions, puis sélectionnez Ajouter > un nouvel élément. Enregistrez le fichier (comme Trace.h, par exemple).

  2. Ajoutez une macro WPP_CONTROL_GUIDS pour spécifier un nom convivial pour le fournisseur de trace, définir un GUID de contrôle et définir les indicateurs de trace que vous pouvez utiliser pour qualifier des messages de trace spécifiques.

    La macro WPP_CONTROL_GUIDS a la syntaxe suivante :

    Syntaxe pour WPP_CONTROL_GUIDS

    #define WPP_CONTROL_GUIDS \
        WPP_DEFINE_CONTROL_GUID(GUIDFriendlyName, (ControlGUID),  \
            WPP_DEFINE_BIT(NameOfTraceFlag1)  \
            WPP_DEFINE_BIT(NameOfTraceFlag2)  \
            .............................   \
            .............................   \
            WPP_DEFINE_BIT(NameOfTraceFlag31) \
            )
    

    Par exemple, le code suivant utilise myDriverTraceGuid comme GUIDFriendlyName. Notez que ControlGUID a un format légèrement différent de celui d’un GUID hexadécimal à 32 chiffres. ControlGUID a les cinq champs, mais ils sont séparés par des virgules et entre parenthèses, au lieu des traits d’union habituels et des accolades. Par exemple, vous spécifiez ((84bdb2e9,829e,41b3,b891,02f454bc2bd7) au lieu de {84bdb2e9-829e-41b3-b891-02f454bc2bd7}.

    Exemple d’instruction WPP_CONTROL_GUIDS

    #define WPP_CONTROL_GUIDS                                              \
        WPP_DEFINE_CONTROL_GUID(                                           \
            myDriverTraceGuid, (84bdb2e9,829e,41b3,b891,02f454bc2bd7), \
            WPP_DEFINE_BIT(MYDRIVER_ALL_INFO)        /* bit  0 = 0x00000001 */ \
            WPP_DEFINE_BIT(TRACE_DRIVER)             /* bit  1 = 0x00000002 */ \
            WPP_DEFINE_BIT(TRACE_DEVICE)             /* bit  2 = 0x00000004 */ \
            WPP_DEFINE_BIT(TRACE_QUEUE)              /* bit  3 = 0x00000008 */ \
            )                             
    

    Note

    Vous pouvez copier cet extrait de code dans un fichier d’en-tête. Veillez à modifier le GUID de contrôle et le nom convivial. Vous pouvez utiliser GUIDgen.exe pour générer le GUID de contrôle. Le Guidgen.exe est inclus dans Visual Studio (Tools > Create GUID). Vous pouvez également utiliser l’outil Uuidgen.exe, qui est disponible à partir de la fenêtre d’invite de commandes Visual Studio (tapez uuidgen.exe / ? pour plus d’informations).

  3. Définissez les indicateurs de trace pour votre fournisseur de trace.

    Les éléments WPP_DEFINE_BIT de la macro WPP_CONTROL_GUIDS définissent les indicateurs de trace pour le fournisseur de trace. En règle générale, les indicateurs représentent des niveaux de reporting de plus en plus détaillés, mais vous pouvez utiliser des indicateurs de la manière que vous souhaitez pour générer des messages de suivi. Dans l’exemple WPP_CONTROL_GUIDS, le WPP_DEFINE_BIT définit quatre indicateurs de trace (MYDRIVER_ALL_INFO, TRACE_DRIVER, TRACE_DEVICE et TRACE_QUEUE).

    Vous pouvez définir jusqu’à 31 indicateurs de trace. WPP affecte des valeurs de bits aux éléments dans l’ordre dans lequel ils apparaissent, par exemple, bit 0 (0x1), bit 1 (0x2), bit 2 (0x4), bit 3 (0x8), et ainsi de suite. Vous utilisez les indicateurs de trace lorsque vous ajoutez des fonctions de message de trace à votre code source (décrit à l’étape 5 : instrumentez le code du pilote pour générer des messages de suivi à des points appropriés).

    Note

    À l’aide des indicateurs de trace, vous pouvez contrôler quand tracer des composants spécifiques (par exemple, des requêtes d’E/S spécifiques ou des activités d’objets de périphérique ou de pilote). Vous ajoutez l’indicateur de trace à votre instruction de message de trace (par exemple, DoTraceMessage (TRACE_DRIVER, "Hello World!\n"). Lorsque vous créez une session de trace avec un contrôleur de trace, comme Tracelog, vous spécifiez l’option -flag à utiliser pour le fournisseur de trace dans cette session, dans ce cas, l’indicateur est bit 1 (0x1), qui correspond à l’indicateur de TRACE_DRIVER. Lorsque vous démarrez la session de suivi, tous les messages de suivi qui spécifient le drapeau de suivi sont écrits dans le journal.

Étape 2 : Choisir les fonctions de message de suivi que vous envisagez d’utiliser et définir les macros WPP pour ces fonctions

Comme une fonction d’impression de débogage, une fonction de message de trace est une fonction (ou macro) que vous ajoutez à votre code pour écrire des messages de trace.

Choix d’une fonction de message de trace

  • La fonction de message de trace par défaut est la macro DoTraceMessage . Si vous utilisez la fonction par défaut, vous pouvez contrôler le moment de génération des messages en utilisant les valeurs Trace Flag de votre fournisseur. Les valeurs des indicateurs de trace sont les indicateurs que vous avez définis lors de la création du GUID de contrôle à l’étape 1. Si vous utilisez DoTraceMessage, les macros WPP par défaut sont déjà définies pour vous (WPP_LEVEL_ENABLED et WPP_LEVEL_LOGGER), vous pouvez donc ignorer le reste de cette étape et passer à l’étape 5.

  • Si vous utilisez l’un des modèles KMDF ou UMDF, la fonction TraceEvents et les macros WPP nécessaires sont déjà définies pour activer cette fonction. Vous pouvez donc passer à l’étape 5.

  • Si vous créez votre propre fonction de message de trace ou que vous convertissez une fonction d’impression de débogage existante, poursuivez avec le reste de cette étape.

Création ou personnalisation d’une fonction de message de trace

  1. Si vous utilisez des fonctions de message de trace personnalisées ou que vous souhaitez convertir des fonctions d’impression de débogage (par exemple, KdPrint) pour générer des messages de trace, vous devez définir des macros WPP qui identifient et activent les fonctions de message de trace dans votre fournisseur de trace. Placez ces macros dans le fichier d’en-tête Trace.h que vous avez ajouté à votre projet.

  2. Définissez les macros WPP pour activer la fonction de trace.

    Chaque fonction de message de trace que vous utilisez doit avoir une paire correspondante de macros. Ces macros identifient le fournisseur de trace et spécifient les conditions qui génèrent les messages. Vous définissez généralement une paire de macros, WPP_<condition>_LOGGER et WPP_<condition>_ENABLED en termes de macros par défaut WPP_LEVEL_ENABLED et WPP_LEVEL_LOGGER.

Terme Descriptif
WPP_CONDITIONS_LOGGER Utilisé pour rechercher la session de trace associée au fournisseur et retourne un handle à la session.
WPP_CONDITIONS_ENABLED Permet de déterminer si la journalisation est activée avec la condition spécifiée.

Pour les macros WPP que vous définissez, les CONDITIONS représentent les conditions que la fonction de message de trace prend en charge, dans l’ordre dans lequel elles apparaissent dans la liste des paramètres de la fonction, séparées par des traits de soulignement. Par exemple, la fonction de message de trace par défaut, DoTraceMessage, prend uniquement en charge l’indicateur de trace comme condition. Par conséquent, il n’existe qu’un seul paramètre dans les noms de macros (WPP_LEVEL_ENABLED).

Note

Malheureusement, les noms des macros par défaut (WPP_LEVEL_ENABLED et WPP_LEVEL_LOGGER) semblent indiquer le paramètre Niveau de trace, mais ils font réellement référence à l’indicateur de trace.

Si vous utilisez une fonction de message de trace personnalisée, vous pouvez définir des qualificateurs supplémentaires, tels que le niveau de trace. Le niveau de trace est défini dans le fichier Evntrace.h et les niveaux de trace offrent un moyen pratique de classifier les messages de trace comme des messages d’erreur, d’avertissement et d’information.

Par exemple, vous pouvez ajouter l’extrait de code suivant au fichier d’en-tête que vous avez ajouté à votre projet. Le code suivant définit les macros WPP personnalisées pour une fonction de message de trace qui prend en charge les paramètres Trace Level et Trace Flag en tant que conditions pour générer des messages de trace. La macro WPP_LEVEL_FLAGS_ENABLED retourne TRUE si la journalisation est activée pour la valeur FLAGS spécifiée et que la valeur LEVEL activée est supérieure ou égale à l’argument de niveau utilisé dans l’appel de fonction de message de trace.

#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
           WPP_LEVEL_LOGGER(flags)

#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
           (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)

Ensuite, vous devez spécifier les fonctions de trace personnalisées dans le bloc de configuration WPP (begin_wpp configuration et end_wpp) Par exemple, si vous utilisez le modèle pour les projets UMDF ou KMDF Driver dans Visual Studio, le modèle définit les macros WPP pour une fonction de message de trace personnalisée appelée TraceEvents. La fonction macro TraceEvents utilise le niveau de trace et l’indicateur de trace comme conditions pour générer des messages. Si vous avez défini la macro WPP_LEVEL_FLAGS_ENABLED dans votre fichier d’en-tête Trace.h, vous pouvez ajouter la définition de macro suivante.

//
// This comment block is scanned by the trace preprocessor to define the 
// TraceEvents function.
//
// begin_wpp config
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//

Vous pouvez également convertir des instructions d'impression de débogage existantes en instructions de messages de trace en ajoutant une déclaration similaire FUNC dans le bloc de configuration WPP. Par exemple, l’exemple suivant ajoute le code pour convertir les instructions KdPrint existantes. La déclaration FUNC définit également globalement KdPrint pour utiliser le niveau de trace spécifié et l’indicateur {LEVEL=TRACE_LEVEL_INFORMATION, FLAGS=TRACE_DRIVER}. Au lieu d’envoyer la sortie au débogueur, les instructions d’impression de débogage sont envoyées au journal de suivi.

//
// This comment block is scanned by the trace preprocessor to define the
// TraceEvents function and conversion for KdPrint. Note the double parentheses for the KdPrint message, for compatibility with the KdPrint function.
//
// begin_wpp config
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// FUNC KdPrint{LEVEL=TRACE_LEVEL_INFORMATION, FLAGS=TRACE_DRIVER}((MSG, ...));
// end_wpp
//

Note

Si vous souhaitez convertir KdPrintEx en fonction de message de trace, vous devez effectuer quelques étapes supplémentaires. Par rapport à KdPrint, la fonction KdPrintEx prend deux arguments supplémentaires. Pour convertir la fonction KdPrintEx , vous devez définir une WPP_DEFINE_BIT pour componentID et définir des macros personnalisées WPP_<condition>_LOGGER et WPP_<condition>_ENABLED . Le deuxième paramètre pour KdPrintEx spécifie le niveau, similaire aux valeurs de niveau de trace, vous n’avez donc pas nécessairement besoin de les redéfinir.


#define WPP_CONTROL_GUIDS                                              \
    WPP_DEFINE_CONTROL_GUID(\
    myDriverTraceGuid, (11C3AAE4, 0D88, 41b3, 43BD, AC38BF747E19), \    /* change GUID for your provider */
        WPP_DEFINE_BIT(MYDRIVER_ALL_INFO)        /* bit  0 = 0x00000001 */ \
        WPP_DEFINE_BIT(TRACE_DRIVER)             /* bit  1 = 0x00000002 */ \
        WPP_DEFINE_BIT(TRACE_DEVICE)             /* bit  2 = 0x00000004 */ \
        WPP_DEFINE_BIT(TRACE_QUEUE)              /* bit  3 = 0x00000008 */ \
        WPP_DEFINE_BIT(DPFLTR_IHVDRIVER_ID)      /* bit  4 = 0x00000010 */\         /* Added for the ComponentID param of KdPrintEx */
    )

#define WPP_Flags_LEVEL_LOGGER(Flags, level)                                  \
    WPP_LEVEL_LOGGER(Flags)

#define WPP_Flags_LEVEL_ENABLED(Flags, level)                                 \
    (WPP_LEVEL_ENABLED(Flags) && \
    WPP_CONTROL(WPP_BIT_ ## Flags).Level >= level)



//
// This comment block is scanned by the trace preprocessor to convert the KdPrintEx function.
// Note the double parentheses for the KdPrint message, for compatiblility with the KdPrintEx function.
//
// begin_wpp config
// FUNC KdPrintEx((Flags, LEVEL, MSG, ...));   
// end_wpp
//

Étape 3 : Inclure les fichiers d’en-tête de trace associés (.h et .tmh) dans vos fichiers sources C ou C++

Si vous avez défini le GUID de contrôle et les indicateurs de trace pour votre pilote dans un fichier d’en-tête (par exemple, trace.h), vous devez inclure le fichier d’en-tête dans les fichiers sources où vous allez initialiser et décharger WPP (étape 4) ou appeler des fonctions de message de trace.

En outre, vous devez ajouter une instruction #include pour le Trace Message Header File (.tmh). Lorsque vous générez le pilote ou l’application, le préprocesseur WPP génère les fichiers d’en-tête de message de trace (.tmh) pour chaque fichier source qui contient des fonctions de message de trace.

/* -- driver.c  - include the *.tmh file that is generated by WPP --*/

#include "trace.h"     /* file that defines WPP_CONFIG_GUIDS and trace flags */
#include "driver.tmh"  /* this file is auto-generated */

Étape 4 : Ajouter des macros aux fonctions de rappel appropriées pour initialiser et nettoyer WPP

Pour initialiser WPP lors de l’entrée du pilote

  • Ajoutez la macro WPP_INIT_TRACING à la routine DriverEntry d’un pilote en mode noyau ou d’un pilote UMDF 2.0, ou à la routine DLLMain d’un pilote en mode utilisateur (UMDF 1.x) ou une application.

Pour nettoyer les ressources WPP lors de la sortie du pilote

  • Ajoutez la macro WPP_CLEANUP à la routine de déchargement du pilote (par exemple , DriverContextCleanup ouDriverUnload) d’un pilote en mode noyau ou d’un pilote UMDF 2.0.

    Pour un pilote en mode utilisateur (UMDF 1.x) ou une application, ajoutez la macro WPP_CLEANUP à la routine DLLMain .

    Vous devez également ajouter la macro WPP_CLEANUP à la routine DriverEntry en cas d’échec de DriverEntry . Par exemple, si DriverEntry échoue, la routine de déchargement du pilote ne sera pas appelée. Consultez l’appel à WdfDriverCreate dans l’exemple suivant.

Exemple de pilote en mode noyau utilisant WPP_INIT_TRACING et WPP_CLEANUP dans DriverEntry


NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )
{  

          //  ... 

                //
    // Initialize WPP Tracing in DriverEntry
    //
    WPP_INIT_TRACING( DriverObject, RegistryPath );

                //  ...


 //
    // Create a framework driver object to represent our driver.
    //
    status = WdfDriverCreate(
        DriverObject,
        RegistryPath,
        &attributes, // Driver Object Attributes
        &config,          // Driver Config Info
        WDF_NO_HANDLE // hDriver
        );

    if (!NT_SUCCESS(status)) {

        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
                "WdfDriverCreate failed with status 0x%x\n", status);
        //
        // Cleanup tracing here because DriverContextCleanup will not be called
        // as we have failed to create WDFDRIVER object itself.
        // Please note that if you return failure from DriverEntry after the
        // WDFDRIVER object is created successfully, you don't have to
        // call WPP cleanup because in those cases DriverContextCleanup
        // will be executed when the framework deletes the DriverObject.
        //
        WPP_CLEANUP(DriverObject);

    }

                return status;

}

Exemple de pilote en mode noyau utilisant WPP_CLEANUP dans DriverContextCleanup



VOID
DriverContextCleanup(
       PDRIVER_OBJECT DriverObject
       )
{
    // ...

    // Clean up WPP resources on unload
    //
    WPP_CLEANUP(DriverObject);

   // ...

}

Exemple de pilote UMDF 2.0 utilisant WPP_INIT_TRACING dans DriverEntry


/
// Driver specific #defines in trace header file (trace.h)
//
#define MYDRIVER_TRACING_ID      L"Microsoft\\UMDF2.0\\UMDF2_0Driver1 V1.0"

 // Initialize WPP Tracing in the DriverEntry routine
 //
    WPP_INIT_TRACING( MYDRIVER_TRACING_ID );

Exemple d'utilisation du pilote UMDF 1.0 avec les macros WPP_INIT_TRACING et WPP_CLEANUP dans DLLMain.

/
// Driver specific #defines in trace header file (for example, trace.h)
//
#define MYDRIVER_TRACING_ID      L"Microsoft\\UMDF1.X\\UMDF1_XDriver1"


//
// DLL Entry Point - UMDF 1.0 example in the source file where you implement the DLL exports.
// 

extern "C"
BOOL
WINAPI
DllMain(
    HINSTANCE hInstance,
    DWORD dwReason,
    LPVOID lpReserved
    )
{
    if (dwReason == DLL_PROCESS_ATTACH) {
        WPP_INIT_TRACING(MYDRIVER_TRACING_ID);              // Initialize WPP tracing

        g_hInstance = hInstance;
        DisableThreadLibraryCalls(hInstance);

    } else if (dwReason == DLL_PROCESS_DETACH) {
        WPP_CLEANUP();                                                                                                              // Deactivate and cleanup WPP tracing
    }

    return _AtlModule.DllMain(dwReason, lpReserved);
}

Étape 5 : Instrumenter le code du pilote pour générer des messages de trace aux points appropriés

Vous pouvez utiliser n’importe quelle fonction de message de trace que vous choisissez, à condition que la fonction de message de trace, les indicateurs de trace et les niveaux soient définis de manière appropriée. La fonction de message de trace par défaut est la macro DoTraceMessage . Vous pouvez ajouter cette macro à votre code pour écrire des messages dans le fichier journal. Le tableau suivant répertorie certaines des fonctions de message de trace prédéfinies et les fonctions d’impression de débogage que vous pouvez utiliser pour créer des messages de suivi.

Exemples de fonctions de message de trace Quand utiliser
DoTraceMessage Il s’agit de la fonction de message de trace par défaut. L’avantage de l’utilisation de DoTraceMessage est que la fonction est déjà définie pour vous. Vous pouvez utiliser les indicateurs de trace que vous spécifiez dans la macro WPP_CONFIG_GUIDS. L’inconvénient de l’utilisation de DoTraceMessage est que la fonction ne prend qu’un seul paramètre conditionnel, c’est-à-dire des indicateurs de trace. Si vous souhaitez utiliser des niveaux de trace, pour consigner uniquement les messages d’erreur ou d’avertissement, vous pouvez utiliser la macro DoDebugTrace ou utiliser TraceEvents, qui utilise à la fois des indicateurs de trace et des niveaux de trace.
TraceEvents Si vous créez un pilote à l’aide de modèles WDF dans Visual Studio, il s’agit de la fonction de message de trace par défaut. L’avantage de l’utilisation de TraceEvents est que la fonction de message de trace, les indicateurs de trace et le niveau de trace sont déjà définis pour vous. En outre, les modèles incluent également l’instrumentation qui écrit des messages dans le fichier journal lors de l’entrée et de la sortie de la fonction.
KdPrint, KdPrintEx, DbgPrint, DbgPrintEx L’avantage de l’utilisation des fonctions d’impression de débogage est que vous n’avez pas besoin de modifier vos instructions d’impression de débogage existantes. Vous pouvez facilement passer de l’affichage des messages dans le débogueur, à l’enregistrement des messages de trace dans un fichier. Si vous avez personnalisé la fonction de message de trace pour inclure l’une des fonctions d’impression de débogage, vous n’avez pas besoin d’effectuer plus de travail. Lorsque vous créez une session de suivi avec Logman ou Tracelog, ou un autre contrôleur de trace, vous spécifiez simplement les indicateurs et les niveaux de votre fournisseur. Toutes les instructions de journalisation de débogage qui répondent aux conditions que vous spécifiez sont imprimées dans le journal des événements.

Utilisation des déclarations DoTraceMessage

  1. Ajoutez la macro DoTraceMessage à votre code comme vous le feriez pour une routine d’impression de débogage. La macro DoTraceMessage prend 3 paramètres : le niveau d’indicateur (TraceFlagName), qui définit la condition lorsque le message de trace est écrit, la chaîne message et la liste de variables facultative.

    DoTraceMessage(TraceFlagName, Message, [VariableList... ])
    

    Par exemple, l’instruction DoTraceMessage suivante écrit le nom de la fonction qui contient l’instruction DoTraceMessage lorsque l’indicateur TRACE_DRIVER, tel que défini dans WPP_CONTROL_GUIDS, est activé pour la session de trace.

         DoTraceMessage( TRACE_DRIVER, "\nEntering %!FUNC!" );
    
    

    L’exemple utilise une chaîne prédéfinie pour la fonction en cours d’exécution (%FUNC!). Pour plus d’informations sur les chaînes de spécification de format définies par WPP, consultez Quelles sont les chaînes de spécification de format étendu WPP ?

  2. Pour générer le message de trace, créez une session de trace pour votre fournisseur de trace, à l’aide de Logman ou tracelog, puis spécifiez un indicateur de trace qui définit l’indicateur de TRACE_DRIVER (bit 1, 0x2).

//
//  DoTraceMessage examples
// 

     ...

// writes the name of the function that contains the trace statement when the flag, TRACE_DRIVER (bit 1, 0x2), 
// as defined in WPP_CONTROL_GUIDS, is enabled for the trace session.

     DoTraceMessage( TRACE_DRIVER, "\nEntering %!FUNC!" );

     ...

// writes the name of the function, the line number, and the error code 

      DoTraceMessage(
            TRACE_DRIVER,
            "[%s] Failed at %d (error code= %d)\n",
            __FUNCTION__,
            __LINE__,
            dwLastError);

Utilisation des instructions TraceEvents

Si vous utilisez les modèles de pilotes Windows dans Visual Studio, la macro TraceEvents est définie pour vous dans le fichier d’en-tête Trace.h.

  1. Ajoutez la macro TraceEvents à votre code comme vous le feriez pour une routine d’impression de débogage. La macro TraceEvents prend les paramètres suivants : le niveau de trace (niveau) et l’indicateur de trace (indicateurs), qui définissent la condition lorsque le message de trace est écrit, la chaîne message et la liste de variables facultatives.

    TraceEvents(Level, Flags, Message, [VariableList... ])
    

    Par exemple, l’instruction TraceEvents suivante écrit le nom de la fonction qui contient l’instruction TraceEvents lorsque les conditions spécifiées dans les paramètres Trace Level et Trace Flag sont remplies. Le niveau de trace est une valeur entière ; toute valeur au niveau de trace spécifié ou inférieur à celui de la session de trace sera tracée. La TRACE_LEVEL_INFORMATION est définie dans Evntrace.h et a la valeur 4. L’indicateur TRACE_DRIVER (bit 1, 0x2) est défini dans WPP_CONTROL_GUIDS. Si ce bit TRACE_DRIVER est défini pour la session de trace et que le niveau de trace est 4 ou supérieur, TraceEvents écrit le message de trace.

            TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
    
    

    L’exemple utilise une chaîne prédéfinie pour la fonction en cours d’exécution (%FUNC!). Pour plus d’informations sur les chaînes de spécification de format définies par WPP, consultez Quelles sont les chaînes de spécification de format étendu WPP ?

  2. Pour générer le message de suivi, créez une session de trace pour votre fournisseur de trace, à l’aide de Logman ou tracelog. Spécifiez un niveau de trace à TRACE_LEVEL_INFORMATION (4) ou supérieur et spécifiez un niveau de trace qui définit le TRACE_DRIVER bit (bit 1, 0x2).

//
//  TraceEvents examples
// 


    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

//


    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
                       "OSRUSBFX2 Driver Sample - Driver Framework Edition.\n");

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
                "Built %s %s\n", __DATE__, __TIME__);

Étape 6 : Modifier le projet Visual Studio pour exécuter le préprocesseur WPP et générer la solution

WdK prend en charge le préprocesseur WPP afin de pouvoir exécuter le préprocesseur à l’aide de Visual Studio et de l’environnement MSBuild.

Pour exécuter le préprocesseur WPP

  1. Sélectionnez et maintenez enfoncé (ou cliquez avec le bouton droit) le projet de pilote dans l’Explorateur de solutions, puis sélectionnez Propriétés.
  2. Dans la page de propriétés du projet, sélectionnez Propriétés de configuration et sélectionnez Suivi WPP.
  3. Sous Général, définissez l’option Exécuter WPP sur Oui.
  4. Sous Ligne de commande, ajoutez toutes les options supplémentaires pour personnaliser le comportement de suivi. Pour plus d’informations sur ce que vous pouvez ajouter, consultez le préprocesseur WPP.
  5. Générez le projet ou la solution pour votre configuration et plateforme cible. Voir Génération d’un pilote avec wdK.

Pour plus d’informations sur le processus de génération, consultez la tâche TraceWPP et l’environnement de génération WDK et Visual Studio.

Vous pouvez également exécuter le préprocesseur distinct de l’environnement de génération à l’aide de l’outil TraceWPP (TraceWPP.exe). Cet outil se trouve dans le sous-répertoire bin/x86 et bin/x64 du WDK.

Étape 7 : Démarrer une session de suivi pour capturer et vérifier vos messages de trace

Pour vérifier que vous avez correctement configuré le suivi WPP, vous devez installer votre pilote ou votre application sur un ordinateur de test, puis créer une session de suivi pour capturer les messages de trace. Vous pouvez créer une session de trace pour votre fournisseur de trace, à l’aide de n’importe quel contrôleur de trace, tel que Logman, Tracelog ou TraceView. Vous pouvez avoir les messages écrits dans un fichier journal ou envoyés à un débogueur de noyau. Selon les fonctions de message de trace que vous utilisez, vous devez être sûr de spécifier les indicateurs de trace et les niveaux de trace qui généreront les messages.

Par exemple, si vous utilisez les niveaux de trace définis dans Evntrace.h et que vous souhaitez capturer TRACE_LEVEL_INFORMATION (4) ou supérieur, vous devez définir le niveau sur 4. Lorsque vous définissez le niveau sur 4 pour la session de suivi, tous les messages d’avertissement (4), d’avertissement (3), d’erreur (2) et critique (1) sont également capturés, en supposant que d’autres conditions, telles que les indicateurs de trace, sont également satisfaits.

Pour vérifier que tous vos messages sont générés, vous pouvez simplement définir le niveau de trace et les indicateurs de trace sur des valeurs maximales afin que tous les messages soient générés. Les indicateurs de trace utilisent un masque de bits (ULONG), ce qui vous permet de définir tous les bits (par exemple, 0xFFFFFFFF). Les niveaux de trace sont représentés par une valeur d’octet. Par exemple, si vous utilisez Logman, vous pouvez spécifier 0xFF pour couvrir tous les niveaux.

(Exemple) Démarrage d’une session de trace à l’aide de Logman

logman create trace "myWPP_session" -p {11C3AAE4-0D88-41b3-43BD-AC38BF747E19} 0xffffffff 0xff -o c:\DriverTest\TraceFile.etl 

logman start "myWPP_session"

logman stop "myWPP_session"

(Exemple) Démarrage d’une session de trace à l’aide de TraceLog

tracelog -start MyTrace -guid  MyProvider.guid -f d:\traces\testtrace.etl -flag 2 -level 0xFFFF

La commande Tracelog inclut le paramètre -f pour spécifier le nom et l’emplacement du fichier journal de suivi des événements. Il inclut le paramètre -flag pour spécifier le jeu d’indicateurs et le paramètre -level pour spécifier le paramètre de niveau. Vous pouvez omettre ces paramètres, mais certains fournisseurs de trace ne génèrent aucun message de trace, sauf si vous définissez l’indicateur ou le niveau. Le niveau de trace est défini dans le fichier Evntrace.h, et les niveaux de trace offrent un moyen pratique de classer les messages de trace comme des messages critiques, d’erreur, d’avertissement et d’information.