Ajout du suivi logiciel WPP à un pilote Windows

Pour utiliser le suivi logiciel WPP dans un fournisseur de traces, 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 de pilote. Cette section décrit ces étapes.

Pointe Le moyen le plus simple d’ajouter le suivi WPP à votre pilote consiste à utiliser l’un des modèles de pilote 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 Fichier > Nouveau > projet, puis sélectionnez le projet WDF pilote Windows (mode utilisateur ou noyau). Les macros WPP sont définies dans le fichier d’en-tête Trace.h inclus dans le 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 traces (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. Cela vous permet d’identifier et de contrôler quand et ce que vous souhaitez tracer. Bien que chaque pilote ait 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 des raisons pratiques, 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 tout fichier source que vous envisagez d’instrumenter pour le suivi.

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 la touche (ou cliquez avec le bouton droit) sur le pilote dans Explorateur de solutions, puis sélectionnez Ajouter un > nouvel élément. Enregistrez le fichier (en tant que 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 la forme standard d’un GUID hexadécimal à 32 chiffres. Le ControlGUID comporte les cinq champs, mais ils sont séparés par des virgules et placés entre parenthèses, au lieu des traits d’union et accolades habituels. 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 */ \
            )                             
    

    Pointe Vous pouvez copier cet extrait de code dans un fichier d’en-tête. Veillez à modifier le GUID du 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 (Outils > Create GUID). Vous pouvez également utiliser l’outil Uuidgen.exe disponible dans la fenêtre d’invite de commandes de Visual Studio (tapez uuidgen.exe /? pour plus d’informations).

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

    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 rapport de plus en plus détaillés, mais vous pouvez utiliser des indicateurs comme vous le souhaitez comme conditions pour générer des messages de trace. 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 dans Étape 5 : Instrumenter le code du pilote pour générer des messages de trace aux points appropriés).

    Note À l’aide des indicateurs de trace, vous pouvez contrôler quand tracer des composants spécifiques (par exemple, des demandes 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 suivi avec un contrôleur de trace, tel que 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 TRACE_DRIVER. Lorsque vous démarrez la session de suivi, tous les messages de trace qui spécifient cet indicateur de trace sont écrits dans le journal.

Étape 2 : Choisir les fonctions de message de trace 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 suivi.

Choix d’une fonction de message de trace

  1. 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 quand générer des messages à l’aide des valeurs d’indicateur de trace pour votre fournisseur. Les valeurs indicateurs de trace sont les indicateurs que vous avez définis lorsque vous avez créé le 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.

  2. 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.

  3. Si vous créez votre propre fonction de message de trace ou que vous convertissez une fonction d’impression de débogage existante, passez au reste de cette étape.

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

  1. Si vous utilisez des fonctions de message de suivi personnalisées ou si 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 suivi 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 de macros correspondante. Ces macros identifient le fournisseur de traces 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 WPP_LEVEL_ENABLED et WPP_LEVEL_LOGGER par défaut.

Chaque fonction de message de trace que vous utilisez doit avoir une paire de macros correspondante. Ces macros identifient le fournisseur de traces 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 WPP_LEVEL_ENABLED et WPP_LEVEL_LOGGER par défaut.

Terme Description

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, de sorte qu’il n’y a qu’un seul paramètre dans les noms de macro (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 en fait 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 classer les messages de trace en tant que 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 à la fois le niveau de trace et les paramètres d’indicateur de trace comme 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 si la valeur LEVEL activée est supérieure ou égale à l’argument level 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 suivi de messages en ajoutant une déclaration FUNC similaire 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 et l’indicateur spécifiés {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 un WPP_DEFINE_BIT pour l’ID de composant et définir des macros personnalisées WPP_<condition>_LOGGER et WPP_<condition>_ENABLED . Le deuxième paramètre pour KdPrintEx spécifie que le niveau de est 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 fichier d’en-tête de message de trace (.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 suivi.

/* -- 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 propre 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 à un pilote UMDF 2.0, ou à la routine DLLMain d’un pilote en mode utilisateur (UMDF 1.x) ou d’une application.

Pour propre des ressources WPP à la sortie du pilote

  • Ajoutez la macro WPP_CLEANUP à la routine de déchargement du pilote (par exemple, DriverContextCleanup ou DriverUnload) 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 n’est 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 des 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 suivi 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 suivi 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 l’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 enregistrer uniquement les messages d’erreur ou d’avertissement, vous pouvez utiliser la macro DoDebugTrace ou 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 une 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 plus besoin d’effectuer 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 d’impression de débogage qui répondent aux conditions que vous spécifiez sont imprimées dans le journal.

Utilisation d’instructions 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 de l’indicateur (TraceFlagName), qui définit la condition lors de l’écriture du message de trace, 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 le de 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 Que 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 suivi 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);

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

Utilisation des instructions TraceEvents

  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 lors de l’écriture du message de trace, 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 Niveau de trace et Indicateur de trace sont remplies. Le niveau de trace est une valeur entière ; Tout ce qui se trouve au niveau de trace spécifié pour cette session de trace est suivi. 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 TRACE_DRIVER bit est défini pour la session de trace et que le niveau de trace est égal ou supérieur à 4, TraceEvents écrit le message de trace.

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

    L’exemple utilise une chaîne prédéfinie pour le de 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 Que 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 suivi pour votre fournisseur de trace, à l’aide de Logman ou de Tracelog. Spécifiez un niveau de trace sur TRACE_LEVEL_INFORMATION (4) ou supérieur, et spécifiez un niveau de trace qui définit le bit TRACE_DRIVER (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, ce qui vous permet d’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 la touche (ou cliquez avec le bouton droit) sur le projet de pilote dans Solutions Explorer, puis sélectionnez Propriétés.
  2. Dans la page de propriétés du projet, sélectionnez Propriétés de configuration , puis suivi WPP.
  3. Sous Général, définissez l’option Exécuter WPP sur Oui.
  4. Sous Ligne de commande, ajoutez des options supplémentaires pour personnaliser le comportement de suivi. Pour plus d’informations sur ce que vous pouvez ajouter, consultez Préprocesseur WPP.
  5. Générez le projet ou la solution pour votre configuration et votre plateforme cible. Consultez Génération d’un pilote avec wdk.

Pour plus d’informations sur le processus de génération, consultez Tâche TraceWPP et ENVIRONNEMENT de build WDK et Visual Studio.

Vous pouvez également exécuter le préprocesseur séparément de l’environnement de build à 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 suivi pour votre fournisseur de traces, à l’aide de n’importe quel contrôleur de trace, tel que Logman, Tracelog ou TraceView. Les messages peuvent être écrits dans un fichier journal ou envoyés à un débogueur de noyau. En fonction des fonctions de message de suivi que vous utilisez, vous devez vous assurer 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’information (4), d’avertissement (3), d’erreur (2) et critiques (1) sont également capturés, en supposant que toutes les autres conditions, telles que les indicateurs de trace, sont également satisfaites.

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 suivi à 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 suivi à 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 trace 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 pas de messages de suivi, 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 fournissent un moyen pratique de classer les messages de trace en tant que messages critiques, d’erreur, d’avertissement et d’information.