Hinzufügen der WPP-Softwareablaufverfolgung zu einem Windows-Treiber

Um die WPP-Softwareablaufverfolgung in einem Ablaufverfolgungsanbieter wie einem Kernelmodustreiber oder einer Benutzermodusanwendung zu verwenden, müssen Sie code (oder instrumentieren) die Treiberquelldateien hinzufügen und das Treiberprojekt ändern. In diesem Abschnitt werden diese Schritte beschrieben.

Tipp Die einfachste Möglichkeit zum Hinzufügen der WPP-Ablaufverfolgung zu Ihrem Treiber besteht darin, eine der KMDF- oder UMDF-Treibervorlagen in Visual Studio zu verwenden. Wenn Sie die Vorlagen verwenden, ist ein Großteil des Codes, den Sie hinzufügen müssen, bereits für Sie erledigt. Wählen Sie in Visual Studio Datei > Neues > Projekt und dann das WDF-Projekt Windows-Treiber (Benutzermodus oder Kernelmodus) aus. Die WPP-Makros werden in der Headerdatei Trace.h definiert, die als Teil des Projekts enthalten ist. Wenn Sie eine der Vorlagen verwenden, können Sie mit Schritt 5 fortfahren.

Schritt 1: Definieren der Steuerelement-GUID und Ablaufverfolgungsflags

Jeder Ablaufverfolgungsanbieter (z. B. ein Treiber oder eine Benutzermodus-App) muss eindeutig definiert sein. Dazu fügen Sie das makro WPP_CONTROL_GUIDS hinzu, das eine Steuerelement-GUID, einen Bezeichner und Ablaufverfolgungsflags definiert. Dies erfolgt, damit Sie ermitteln und steuern können, wann und was Sie nachverfolgen möchten. Während jeder Treiber in der Regel über eine separate Steuerelement-GUID verfügt, kann ein Treiber über mehrere Steuerelement-GUIDs verfügen, oder mehrere Treiber können eine Steuerelement-GUID gemeinsam nutzen.

Der Einfachheit halber wird das makro WPP_CONTROL_GUIDS in der Regel in einer allgemeinen Headerdatei definiert. Die Headerdatei muss (#include) in jeder Quelldatei enthalten sein, die Sie für die Ablaufverfolgung instrumentieren möchten.

So fügen Sie ihrem Treiber WPP_CONTROL_GUIDS Makro hinzu:

  1. Fügen Sie Ihrem Visual Studio-Projekt eine neue C++-Headerdatei hinzu, die Sie zum Definieren der WPP-Ablaufverfolgungsmakros verwenden können. Wählen Sie z. B. den Treiber in Projektmappen-Explorer aus, halten sie gedrückt (oder klicken Sie mit der rechten Maustaste darauf), und wählen Sie Neues Element hinzufügen >aus. Speichern Sie die Datei (z. B. als Trace.h).

  2. Fügen Sie ein WPP_CONTROL_GUIDS Makro hinzu, um den Anzeigenamen für den Ablaufverfolgungsanbieter anzugeben, eine Steuerelement-GUID zu definieren und die Ablaufverfolgungsflags zu definieren, mit denen Sie bestimmte Ablaufverfolgungsmeldungen qualifizieren können.

    Das makro WPP_CONTROL_GUIDS weist die folgende Syntax auf:

    Syntax für 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) \
            )
    

    Der folgende Code verwendet beispielsweise myDriverTraceGuid als GUIDFriendlyName. Beachten Sie, dass ControlGUID ein etwas anderes Format hat als die Standardform einer 32-stelligen hexadezimalen GUID. Die ControlGUID enthält die fünf Felder, aber sie werden durch Kommas getrennt und durch Klammern anstelle der üblichen Bindestriche und geschweiften Klammern klammern. Beispielsweise geben Sie ((84bdb2e9,829e,41b3,b891,02f454bc2bd7) anstelle von {84bdb2e9-829e-41b3-b891-02f454bc2bd7} an.

    Beispiel für eine WPP_CONTROL_GUIDS-Anweisung

    #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 */ \
            )                             
    

    Tipp Sie können diesen Codeausschnitt in eine Headerdatei kopieren. Achten Sie darauf, die Steuerelement-GUID und den Anzeigenamen zu ändern. Sie können GUIDgen.exe verwenden, um die Steuerelement-GUID zu generieren. Die Guidgen.exe ist in Visual Studio enthalten (Tools > Create GUID). Sie können auch das Uuidgen.exe-Tool verwenden, das über das Visual Studio-Eingabeaufforderungsfenster verfügbar ist (geben Sie uuidgen.exe /? ein, um weitere Informationen zu erhalten.

  3. Definieren Sie die Ablaufverfolgungsflags für Ihren Ablaufverfolgungsanbieter .

    Die WPP_DEFINE_BIT Elemente des WPP_CONTROL_GUIDS Makros definieren die Ablaufverfolgungsflags für den Ablaufverfolgungsanbieter. In der Regel stellen die Flags immer detailliertere Berichtsebenen dar, aber Sie können Flags beliebig als Bedingungen für das Generieren von Ablaufverfolgungsmeldungen verwenden. Im WPP_CONTROL_GUIDS Beispiel definiert die WPP_DEFINE_BIT vier Ablaufverfolgungsflags (MYDRIVER_ALL_INFO, TRACE_DRIVER, TRACE_DEVICE und TRACE_QUEUE).

    Sie können bis zu 31 Ablaufverfolgungsflags definieren. WPP weist den Elementen Bitwerte in der Reihenfolge zu, in der sie angezeigt werden, z. B. Bit 0 (0x1), Bit 1 (0x2), Bit 2 (0x4), Bit 3 (0x8) usw. Sie verwenden die Ablaufverfolgungsflags, wenn Sie Ihrem Quellcode Ablaufverfolgungsnachrichtenfunktionen hinzufügen (beschrieben in Schritt 5: Instrumentieren des Treibercodes zum Generieren von Ablaufverfolgungsmeldungen an geeigneten Stellen).

    Hinweis Mithilfe der Ablaufverfolgungsflags können Sie steuern, wann bestimmte Komponenten (z. B. bestimmte E/A-Anforderungen oder Aktivitäten von Geräte- oder Treiberobjekten) nachverfolgt werden sollen. Sie fügen das Ablaufverfolgungsflag ihrer Ablaufverfolgungsmeldungsanweisung hinzu (z. B DoTraceMessage (TRACE_DRIVER, "Hello World!\n"). . Wenn Sie eine Ablaufverfolgungssitzung mit einem Ablaufverfolgungscontroller wie Tracelog erstellen, geben Sie die Option -flag an, die für den Ablaufverfolgungsanbieter in dieser Sitzung verwendet werden soll. In diesem Fall ist das Flag Bit 1 (0x1), das dem flag TRACE_DRIVER entspricht. Wenn Sie die Ablaufverfolgungssitzung starten, werden alle Ablaufverfolgungsmeldungen, die dieses Ablaufverfolgungsflag angeben, in das Protokoll geschrieben.

Schritt 2: Wählen Sie aus, welche Ablaufverfolgungsnachrichtenfunktionen Sie verwenden möchten, und definieren Sie die WPP-Makros für diese Funktionen.

Wie eine Debugdruckfunktion ist eine Ablaufverfolgungsmeldungsfunktion eine Funktion (oder ein Makro), die Sie ihrem Code hinzufügen, um Ablaufverfolgungsmeldungen zu schreiben.

Auswählen einer Ablaufverfolgungsmeldungsfunktion

  1. Die Standardfunktion für Ablaufverfolgungsmeldungen ist das DoTraceMessage-Makro . Wenn Sie die Standardfunktion verwenden, können Sie mithilfe der Werte des Ablaufverfolgungsflags für Ihren Anbieter steuern, wann Nachrichten generiert werden sollen. Die Werte für Ablaufverfolgungsflags sind die Flags, die Sie beim Erstellen der Steuerelement-GUID in Schritt 1 definiert haben. Wenn Sie DoTraceMessage verwenden, sind die standardmäßigen WPP-Makros bereits für Sie definiert (WPP_LEVEL_ENABLED und WPP_LEVEL_LOGGER), sodass Sie den Rest dieses Schritts überspringen und mit Schritt 5 fortfahren können.

  2. Wenn Sie eine der KMDF- oder UMDF-Vorlagen verwenden, sind die TraceEvents-Funktion und die erforderlichen WPP-Makros bereits definiert, um diese Funktion zu aktivieren, sodass Sie mit Schritt 5 fortfahren können.

  3. Wenn Sie eine eigene Ablaufverfolgungsmeldungsfunktion erstellen oder eine vorhandene Debugdruckfunktion konvertieren, fahren Sie mit dem Rest dieses Schritts fort.

Erstellen oder Anpassen einer Ablaufverfolgungsmeldungsfunktion

  1. Wenn Sie benutzerdefinierte Ablaufverfolgungsnachrichtenfunktionen verwenden oder Debugdruckfunktionen (z. B. KdPrint) konvertieren möchten, um Ablaufverfolgungsmeldungen zu generieren, müssen Sie WPP-Makros definieren, die die Funktionen für Ablaufverfolgungsnachrichten in Ihrem Ablaufverfolgungsanbieter identifizieren und aktivieren. Fügen Sie diese Makros in die Headerdatei Trace.h ein, die Sie Ihrem Projekt hinzugefügt haben.

  2. Definieren Sie die WPP-Makros, um die Ablaufverfolgungsfunktion zu aktivieren.

    Jede verwendete Ablaufverfolgungsmeldungsfunktion muss über ein entsprechendes Makropaar verfügen. Diese Makros identifizieren den Ablaufverfolgungsanbieter und geben die Bedingungen an, die die Nachrichten generieren. In der Regel definieren Sie ein Paar von Makros, WPP_<condition>_LOGGER und WPP_<condition>_ENABLED in Bezug auf die Standardmakros WPP_LEVEL_ENABLED und WPP_LEVEL_LOGGER Makros.

Jede verwendete Ablaufverfolgungsmeldungsfunktion muss über ein entsprechendes Makropaar verfügen. Diese Makros identifizieren den Ablaufverfolgungsanbieter und geben die Bedingungen an, die die Nachrichten generieren. In der Regel definieren Sie ein Paar von Makros, WPP_<condition>_LOGGER und WPP_<condition>_ENABLED in Bezug auf die Standardmakros WPP_LEVEL_ENABLED und WPP_LEVEL_LOGGER Makros.

Begriff Beschreibung

WPP_CONDITIONS_LOGGER

Wird verwendet, um die ablaufverfolgungssitzung zu finden, die dem Anbieter zugeordnet ist, und gibt ein Handle an die Sitzung zurück.

WPP_CONDITIONS_ENABLED

Wird verwendet, um zu bestimmen, ob die Protokollierung mit der angegebenen Bedingung aktiviert ist.

Für die WPP-Makros, die Sie definieren, stellen die BEDINGUNGEN die Bedingungen dar, die die Ablaufverfolgungsmeldungsfunktion unterstützt, in der Reihenfolge, in der sie in der Parameterliste der Funktion angezeigt werden, getrennt durch Unterstriche. Die Standardmäßige Ablaufverfolgungsmeldungsfunktion DoTraceMessage unterstützt beispielsweise nur das Ablaufverfolgungsflag als Bedingung, sodass nur ein Parameter in den Makronamen (WPP_LEVEL_ENABLED) vorhanden ist.

Hinweis Leider scheinen die Namen der Standardmakros (WPP_LEVEL_ENABLED und WPP_LEVEL_LOGGER) den Parameter Ablaufverfolgungsebene anzugeben, aber sie verweisen tatsächlich auf das Ablaufverfolgungsflag.

Wenn Sie eine benutzerdefinierte Ablaufverfolgungsmeldungsfunktion verwenden, können Sie zusätzliche Qualifizierer festlegen, z. B. die Ablaufverfolgungsebene. Die Ablaufverfolgungsebene wird in der Datei "Evntrace.h" definiert, und die Ablaufverfolgungsebenen bieten eine bequeme Möglichkeit, die Ablaufverfolgungsmeldungen als Fehler-, Warnungs- und Informationsmeldungen zu klassifizieren.

Beispielsweise können Sie den folgenden Codeausschnitt der Headerdatei hinzufügen, die Sie Ihrem Projekt hinzugefügt haben. Der folgende Code definiert die benutzerdefinierten WPP-Makros für eine Ablaufverfolgungsmeldungsfunktion, die sowohl Ablaufverfolgungsebene als auch Ablaufverfolgungsflagsparameter als Bedingungen zum Generieren von Ablaufverfolgungsmeldungen unterstützt. Das WPP_LEVEL_FLAGS_ENABLED Makro gibt TRUE zurück, wenn die Protokollierung für den angegebenen FLAGS-Wert aktiviert ist und der aktivierte LEVEL-Wert größer oder gleich dem level-Argument ist, das im Funktionsaufruf der Ablaufverfolgungsmeldung verwendet wird.

#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)

Als Nächstes müssen Sie die benutzerdefinierten Ablaufverfolgungsfunktionen im WPP-Konfigurationsblock angeben (begin_wpp Konfiguration und end_wpp). Wenn Sie beispielsweise die Vorlage für UMDF- oder KMDF-Treiberprojekte in Visual Studio verwenden, definiert die Vorlage die WPP-Makros für eine benutzerdefinierte Ablaufverfolgungsmeldungsfunktion namens TraceEvents. Die TraceEvents-Makrofunktion verwendet Ablaufverfolgungsebene und Ablaufverfolgungsflag als Bedingungen zum Generieren von Nachrichten. Wenn Sie das WPP_LEVEL_FLAGS_ENABLED Makro in der Trace.h-Headerdatei definiert haben, können Sie die folgende Makrodefinition hinzufügen.

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

Sie können auch vorhandene Debugdruckanweisungen in Anweisungen für Ablaufverfolgungsmeldungen konvertieren, indem Sie eine ähnliche FUNC-Deklaration im WPP-Konfigurationsblock hinzugefügt haben. Im folgenden Beispiel wird beispielsweise der Code hinzugefügt, um die vorhandenen KdPrint-Anweisungen zu konvertieren. Die FUNC-Deklaration definiert auch global den KdPrint , um die angegebene Ablaufverfolgungsebene und das angegebene Flag {LEVEL=TRACE_LEVEL_INFORMATION, FLAGS=TRACE_DRIVER} zu verwenden. Anstatt die Ausgabe an den Debugger zu senden, werden die Debugdruckanweisungen an das Ablaufverfolgungsprotokoll gesendet.

//
// 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
//

Hinweis Wenn Sie KdPrintEx in eine Ablaufverfolgungsmeldungsfunktion konvertieren möchten, müssen Sie einige zusätzliche Schritte ausführen. Im Vergleich zu KdPrint akzeptiert die KdPrintEx-Funktion zwei zusätzliche Argumente. Um die KdPrintEx-Funktion zu konvertieren, müssen Sie eine WPP_DEFINE_BIT für die ComponentID definieren und benutzerdefinierte makros WPP_<condition>_LOGGER und WPP_<condition>_ENABLED definieren. Der zweite Parameter für KdPrintEx gibt an, dass die Ebene von den Werten der Ablaufverfolgungsebene ähnelt, sodass Sie sie nicht unbedingt neu definieren müssen.


#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
//

Schritt 3: Einschließen der zugeordneten Ablaufverfolgungsheaderdateien (.h und .tmh) in Ihre C- oder C++-Quelldateien

Wenn Sie die Steuerelement-GUID und Ablaufverfolgungsflags für Ihren Treiber in einer Headerdatei (z. B. trace.h) definiert haben, müssen Sie die Headerdatei in die Quelldateien einschließen, in denen Sie WPP initialisieren und entladen (Schritt 4) oder Ablaufverfolgungsnachrichtenfunktionen aufrufen.

Darüber hinaus müssen Sie eine #include-Anweisung für die Ablaufverfolgungsnachrichtenheaderdatei (.tmh) hinzufügen. Wenn Sie den Treiber oder die Anwendung erstellen, generiert der WPP-Präprozessor die Headerdateien für Ablaufverfolgungsmeldungen (TMH) für jede Quelldatei, die Ablaufverfolgungsnachrichtenfunktionen enthält.

/* -- 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 */

Schritt 4: Hinzufügen von Makros zu den entsprechenden Rückruffunktionen zum Initialisieren und sauber WPP

So initialisieren Sie WPP für den Treibereintrag

  • Fügen Sie das makro WPP_INIT_TRACING der DriverEntry-Routine eines Kernelmodustreibers oder UMDF 2.0-Treibers oder der DLLMain-Routine eines Benutzermodustreibers (UMDF 1.x) oder einer Anwendung hinzu.

So sauber WPP-Ressourcen beim Beenden des Treibers

  • Fügen Sie das makro WPP_CLEANUP der Treiberentladungsroutine (z. B . DriverContextCleanup oder DriverUnload) eines Kernelmodustreibers oder UMDF 2.0-Treibers hinzu.

    Fügen Sie für einen Benutzermodustreiber (UMDF 1.x) oder eine Anwendung das makro WPP_CLEANUP der DLLMain-Routine hinzu.

    Sie sollten auch das makro WPP_CLEANUP der DriverEntry-Routine hinzufügen, falls driverEntry fehlschlägt. Wenn beispielsweise driverEntry fehlschlägt, wird die Entladeroutine des Treibers nicht aufgerufen. Sehen Sie sich den Aufruf von WdfDriverCreate im folgenden Beispiel an.

Beispiel für einen Kernelmodustreiber mit WPP_INIT_TRACING und WPP_CLEANUP in 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;

}

Beispiel für einen Kernelmodustreiber mit WPP_CLEANUP in DriverContextCleanup



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

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

   // ...

}

Beispiel für den UMDF 2.0-Treiber mit WPP_INIT_TRACING in 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 );

Beispiel für die Verwendung von WPP_INIT_TRACING- und WPP_CLEANUP-Makros in DLLMain für DEN UMDF 1.0-Treiber

/
// 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);
}

Schritt 5: Instrumentieren des Treibercodes zum Generieren von Ablaufverfolgungsmeldungen an geeigneten Punkten

Sie können jede von Ihnen ausgewählte Ablaufverfolgungsmeldungsfunktion verwenden, sofern die Ablaufverfolgungsmeldungsfunktion, die Ablaufverfolgungsflags und -ebenen entsprechend definiert sind. Die Standardfunktion für Ablaufverfolgungsmeldungen ist das DoTraceMessage-Makro . Sie können dieses Makro ihrem Code hinzufügen, um Nachrichten in die Protokolldatei zu schreiben. In der folgenden Tabelle sind einige der vordefinierten Funktionen für Ablaufverfolgungsnachrichten und die Debugdruckfunktionen aufgeführt, die Sie zum Erstellen von Ablaufverfolgungsmeldungen verwenden können.

Beispielfunktionen für Ablaufverfolgungsnachrichten Verwendung
DoTraceMessage

Dies ist die Standardfunktion für Ablaufverfolgungsmeldungen. Der Vorteil der Verwendung von DoTraceMessage besteht darin, dass die Funktion bereits für Sie definiert ist. Sie können die Ablaufverfolgungsflags verwenden, die Sie im makro WPP_CONFIG_GUIDS angeben. Der Nachteil der Verwendung von DoTraceMessage besteht darin, dass die Funktion nur einen bedingten Parameter akzeptiert, d. h. Ablaufverfolgungsflags. Wenn Sie Ablaufverfolgungsebenen verwenden möchten, um nur Fehler- oder Warnmeldungen zu protokollieren, können Sie das DoDebugTrace-Makro oder TraceEvents verwenden, das sowohl Ablaufverfolgungsflags als auch Ablaufverfolgungsebenen verwendet.

TraceEvents

Wenn Sie einen Treiber mithilfe von WDF-Vorlagen in Visual Studio erstellen, ist dies die Standardfunktion für Ablaufverfolgungsmeldungen. Der Vorteil der Verwendung von TraceEvents besteht darin, dass die Ablaufverfolgungsmeldungsfunktion, die Ablaufverfolgungsflags und die Ablaufverfolgungsebene bereits für Sie definiert sind. Darüber hinaus enthalten die Vorlagen auch eine Instrumentierung, die beim Funktionseintrag und -beenden Meldungen in die Protokolldatei schreibt.

KdPrint, KdPrintEx, DbgPrint, DbgPrintEx

Der Vorteil der Verwendung der Debugdruckfunktionen besteht darin, dass Sie Ihre vorhandenen Debugdruckanweisungen nicht ändern müssen. Sie können ganz einfach vom Anzeigen von Nachrichten im Debugger zur Aufzeichnung von Ablaufverfolgungsmeldungen in einer Datei wechseln. Wenn Sie die Ablaufverfolgungsmeldungsfunktion so angepasst haben, dass sie eine der Debugdruckfunktionen enthält, müssen Sie keine weiteren Aufgaben ausführen. Wenn Sie eine Ablaufverfolgungssitzung mit Logman, Tracelog oder einem anderen Ablaufverfolgungscontroller erstellen, geben Sie einfach die Flags und Ebenen für Ihren Anbieter an. Alle Debugdruckanweisungen, die die von Ihnen angegebenen Bedingungen erfüllen, werden im Protokoll ausgegeben.

Verwenden von DoTraceMessage-Anweisungen

  1. Fügen Sie ihrem Code das DoTraceMessage-Makro wie eine Debugdruckroutine hinzu. Das DoTraceMessage-Makro akzeptiert drei Parameter: die Flagebene (TraceFlagName), die die Bedingung definiert, wenn die Ablaufverfolgungsnachricht geschrieben wird, die Meldungszeichenfolge und die optionale Variablenliste.

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

    Die folgende DoTraceMessage-Anweisung schreibt beispielsweise den Namen der Funktion, die die DoTraceMessage-Anweisung enthält, wenn das in WPP_CONTROL_GUIDS definierte TRACE_DRIVER-Flag für die Ablaufverfolgungssitzung aktiviert ist.

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

    Im Beispiel wird eine vordefinierte Zeichenfolge für die der derzeit ausgeführten Funktion (%FUNC!) verwendet. Weitere Informationen zu WPP-definierten Formatspezifikationszeichenfolgen finden Sie unter Was sind die WPP-Spezifikationszeichenfolgen für erweiterte Formate?

  2. Um die Ablaufverfolgungsnachricht zu generieren, erstellen Sie eine Ablaufverfolgungssitzung für Ihren Ablaufverfolgungsanbieter mithilfe von Logman oder Tracelog, und geben Sie ein Ablaufverfolgungsflag an, das das TRACE_DRIVER-Flag (Bit 1, 0x2) festlegt.

//
//  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);

Wenn Sie die Windows-Treibervorlagen in Visual Studio verwenden, wird das TraceEvents-Makro in der Headerdatei Trace.h für Sie definiert.

Verwenden von TraceEvents-Anweisungen

  1. Fügen Sie ihrem Code das Makro TraceEvents wie eine Debugdruckroutine hinzu. Das TraceEvents-Makro verwendet die folgenden Parameter: die Ablaufverfolgungsebene (Level) und das Ablaufverfolgungsflag (Flags), die die Bedingung definieren, wenn die Ablaufverfolgungsnachricht geschrieben wird, die Meldungszeichenfolge und die optionale Variablenliste.

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

    Die folgende TraceEvents-Anweisung schreibt beispielsweise den Namen der Funktion, die die TraceEvents-Anweisung enthält, wenn die in den Parametern Ablaufverfolgungsebene und Ablaufverfolgungsflag angegebenen Bedingungen erfüllt sind. Die Ablaufverfolgungsebene ist ein ganzzahliger Wert. Alle Elemente, die auf oder unter der für diese Ablaufverfolgungssitzung angegebenen Ablaufverfolgungsebene liegen, werden nachverfolgt. Die TRACE_LEVEL_INFORMATION ist in Evntrace.h definiert und weist den Wert 4 auf. Das TRACE_DRIVER-Flag (Bit 1, 0x2) wird in WPP_CONTROL_GUIDS definiert. Wenn dieses TRACE_DRIVER Bit für die Ablaufverfolgungssitzung festgelegt ist und die Ablaufverfolgungsebene 4 oder höher ist, schreibt TraceEvents die Ablaufverfolgungsmeldung .

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

    Im Beispiel wird eine vordefinierte Zeichenfolge für die der derzeit ausgeführten Funktion (%FUNC!) verwendet. Weitere Informationen zu WPP-definierten Formatspezifikationszeichenfolgen finden Sie unter Was sind die WPP-Spezifikationszeichenfolgen für erweiterte Formate?

  2. Um die Ablaufverfolgungsnachricht zu generieren, erstellen Sie mithilfe von Logman oder Tracelog eine Ablaufverfolgungssitzung für Ihren Ablaufverfolgungsanbieter. Geben Sie eine Ablaufverfolgungsebene auf TRACE_LEVEL_INFORMATION (4) oder höher an, und geben Sie eine Ablaufverfolgungsebene an, die das TRACE_DRIVER Bit (Bit 1, 0x2) festlegt.

//
//  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__);

Schritt 6: Ändern des Visual Studio-Projekts zum Ausführen des WPP-Präprozessors und Erstellen der Projektmappe

Das WDK bietet Unterstützung für den WPP-Präprozessor, sodass Sie den Präprozessor mithilfe von Visual Studio und der MSBuild-Umgebung ausführen können.

So führen Sie den WPP-Präprozessor aus

  1. Halten Sie das Treiberprojekt in Projektmappen Explorer gedrückt (oder klicken Sie mit der rechten Maustaste darauf), und wählen Sie Eigenschaften aus.
  2. Wählen Sie auf der Eigenschaftenseite des Projekts die Option Konfigurationseigenschaften und dann WPP-Ablaufverfolgung aus.
  3. Legen Sie unter Allgemein die Option WPP ausführen auf Ja fest.
  4. Fügen Sie unter Befehlszeile alle zusätzlichen Optionen hinzu, um das Ablaufverfolgungsverhalten anzupassen. Informationen dazu, was Sie hinzufügen können, finden Sie unter WPP-Präprozessor.
  5. Erstellen Sie das Projekt oder die Projektmappe für Ihre Zielkonfiguration und Plattform. Weitere Informationen finden Sie unter Erstellen eines Treibers mit dem WDK.

Informationen zum Buildprozess finden Sie unter TraceWPP-Aufgabe und WDK- und Visual Studio-Buildumgebung.

Sie können den Präprozessor auch getrennt von der Buildumgebung ausführen, indem Sie das TraceWPP-Tool (TraceWPP.exe) verwenden. Dieses Tool befindet sich im Unterverzeichnis bin/x86 und bin/x64 des WDK.

Schritt 7: Starten einer Ablaufverfolgungssitzung zum Erfassen und Überprüfen Ihrer Ablaufverfolgungsmeldungen

Um zu überprüfen, ob Sie die WPP-Ablaufverfolgung ordnungsgemäß eingerichtet haben, sollten Sie Den Treiber oder die Anwendung auf einem Testcomputer installieren und dann eine Ablaufverfolgungssitzung erstellen, um die Ablaufverfolgungsmeldungen zu erfassen. Sie können eine Ablaufverfolgungssitzung für Ihren Ablaufverfolgungsanbieter erstellen, indem Sie einen beliebigen Ablaufverfolgungscontroller wie Logman, Tracelog oder TraceView verwenden. Sie können die Nachrichten in eine Protokolldatei schreiben oder an einen Kerneldebugger senden lassen. Abhängig von den von Ihnen verwendeten Ablaufverfolgungsnachrichtenfunktionen müssen Sie unbedingt die Ablaufverfolgungsflags und Ablaufverfolgungsebenen angeben, die die Nachrichten generieren.

Wenn Sie beispielsweise die in Evntrace.h definierten Ablaufverfolgungsebenen verwenden und TRACE_LEVEL_INFORMATION (4) oder höher erfassen möchten, müssen Sie die Ebene auf 4 festlegen. Wenn Sie die Ebene auf 4 für die Ablaufverfolgungssitzung festlegen, werden auch alle Informationsmeldungen (4), Warnungen (3), Fehler (2) und kritische Nachrichten (1) erfasst, sofern alle anderen Bedingungen, z. B. Ablaufverfolgungsflags, ebenfalls erfüllt sind.

Um zu überprüfen, ob alle Nachrichten generiert werden, können Sie einfach die Ablaufverfolgungsebene und die Ablaufverfolgungsflags auf Maximalwerte festlegen, damit alle Nachrichten generiert werden. Die Ablaufverfolgungsflags verwenden eine Bitmaske (ULONG), sodass Sie alle Bits festlegen können (z. B. 0xFFFFFFFF). Ablaufverfolgungsebenen werden durch einen Bytewert dargestellt. Wenn Sie beispielsweise Logman verwenden, können Sie angeben, 0xFF für alle Ebenen.

(Beispiel) Starten einer Ablaufverfolgungssitzung mithilfe von 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"

(Beispiel) Starten einer Ablaufverfolgungssitzung mithilfe von TraceLog

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

Der Tracelog-Befehl enthält den Parameter -f , um den Namen und den Speicherort der Ereignisablaufverfolgungsprotokolldatei anzugeben. Sie enthält den Parameter -flag , um die festgelegten Flags anzugeben, und den Parameter -level , um die Leveleinstellung anzugeben. Sie können diese Parameter weglassen, aber einige Ablaufverfolgungsanbieter generieren keine Ablaufverfolgungsmeldungen, es sei denn, Sie legen das Flag oder die Ebene fest. Die Ablaufverfolgungsebene wird in der Datei "Evntrace.h" definiert, und die Ablaufverfolgungsebenen bieten eine bequeme Möglichkeit, die Ablaufverfolgungsmeldungen als kritische, Fehler-, Warnungs- und Informationsmeldungen zu klassifizieren.