Windows ETW 学习与使用三
一、注册一个ETW
1.使用EventRegister注册一个ETW,使用EventWrite写入事件
// WritingManifestbasedEvents.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <stdio.h> #include <evntprov.h> //#include "provider.h" // Generated from manifest //**********************************************************************` //* This is an include file generated by Message Compiler. *` //* *` //* Copyright (c) Microsoft Corporation. All Rights Reserved. *` //**********************************************************************` #pragma once //+ // Provider Microsoft-Windows-ETWProvider Event Count 1 //+ EXTERN_C __declspec(selectany) const GUID ProviderGuid = {0xd8909c24, 0x5be9, 0x4502, {0x98, 0xca, 0xab, 0x7b, 0xdc, 0x24, 0x89, 0x9d}}; // // Keyword // #define READ_KEYWORD 0x1 #define WRITE_KEYWORD 0x2 #define LOCAL_KEYWORD 0x4 #define REMOTE_KEYWORD 0x8 // // Event Descriptors // EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR TransferEvent = {0x1, 0x0, 0x0, 0x4, 0x0, 0x0, 0x5}; #define TransferEvent_value 0x1 #define MSG_Provider_Name 0x90000001L #define MSG_Event_WhenToTransfer 0xB0000001L #define MSG_Map_Download 0xD0000001L #define MSG_Map_Upload 0xD0000002L #define MSG_Map_UploadReply 0xD0000003L #define MSG_Map_Sunday 0xF0000001L #define MSG_Map_Monday 0xF0000002L #define MSG_Map_Tuesday 0xF0000003L #define MSG_Map_Wednesday 0xF0000004L #define MSG_Map_Thursday 0xF0000005L #define MSG_Map_Friday 0xF0000006L #define MSG_Map_Saturday 0xF0000007L #define SUNDAY 0X1 #define MONDAY 0X2 #define TUESDAY 0X4 #define WEDNESDAY 0X8 #define THURSDAY 0X10 #define FRIDAY 0X20 #define SATURDAY 0X40 enum TRANSFER_TYPE { Download = 1, Upload, UploadReply }; #define MAX_NAMEDVALUES 5 // Maximum array size #define MAX_PAYLOAD_DESCRIPTORS 9 + (2 * MAX_NAMEDVALUES) typedef struct _namedvalue { LPWSTR name; USHORT value; } NAMEDVALUE, *PNAMEDVALUE; int _tmain(int argc, _TCHAR* argv[]) { DWORD status = ERROR_SUCCESS; REGHANDLE RegistrationHandle = NULL; EVENT_DATA_DESCRIPTOR Descriptors[MAX_PAYLOAD_DESCRIPTORS]; DWORD i = 0; // Data to load into event descriptors USHORT Scores[3] = {45, 63, 21}; ULONG pImage = (ULONG)&Scores; DWORD TransferType = Upload; DWORD Day = MONDAY | TUESDAY; LPWSTR Path = L"c:\\path\\folder\\file.ext"; BYTE Cert[11] = {0x2, 0x4, 0x8, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x0, 0x1}; PBYTE Guid = (PBYTE) &ProviderGuid; USHORT ArraySize = MAX_NAMEDVALUES; BOOL IsLocal = TRUE; NAMEDVALUE NamedValues[MAX_NAMEDVALUES] = { {L"Bill", 1}, {L"Bob", 2}, {L"William", 3}, {L"Robert", 4}, {L"", 5} }; status = EventRegister( &ProviderGuid, // GUID that identifies the provider NULL, // Callback not used NULL, // Context noot used &RegistrationHandle // Used when calling EventWrite and EventUnregister ); if (ERROR_SUCCESS != status) { wprintf(L"EventRegister failed with %lu\n", status); goto cleanup; } // Load the array of data descriptors for the TransferEvent event. // Add the data to the array in the order of the <data> elements // defined in the event's template. EventDataDescCreate(&Descriptors[i++], &pImage, sizeof(ULONG)); EventDataDescCreate(&Descriptors[i++], Scores, sizeof(Scores)); EventDataDescCreate(&Descriptors[i++], Guid, sizeof(GUID)); EventDataDescCreate(&Descriptors[i++], Cert, sizeof(Cert)); EventDataDescCreate(&Descriptors[i++], &IsLocal, sizeof(BOOL)); EventDataDescCreate(&Descriptors[i++], Path, (ULONG)(wcslen(Path) + 1) * sizeof(WCHAR)); EventDataDescCreate(&Descriptors[i++], &ArraySize, sizeof(USHORT)); // If your event contains a structure, you should write each member // of the structure separately. If the structure contained integral data types // such as DWORDs and the data types were aligned on an 8-byte boundary, you // could use the following call to write the structure, however, you are // encouraged to write the members separately. // // EventDataDescCreate(&EvtData, struct, sizeof(struct)); // // Because the array of structures in this example contains both strings // and numbers, you must write each member of the structure separately. for (int j = 0; j < MAX_NAMEDVALUES; j++) { EventDataDescCreate(&Descriptors[i++], NamedValues[j].name, (ULONG)(wcslen(NamedValues[j].name)+1) * sizeof(WCHAR) ); EventDataDescCreate(&Descriptors[i++], &(NamedValues[j].value), sizeof(USHORT) ); } EventDataDescCreate(&Descriptors[i++], &Day, sizeof(DWORD)); EventDataDescCreate(&Descriptors[i++], &TransferType, sizeof(DWORD)); // Write the event. You do not have to verify if your provider is enabled before // writing the event. ETW will write the event to any session that enabled // the provider. If no session enabled the provider, the event is not // written. If you need to perform extra work to write an event that you // would not otherwise do, you may want to call the EventEnabled function // before performing the extra work. The EventEnabled function tells you if a // session has enabled your provider, so you know if you need to perform the // extra work or not. status = EventWrite( RegistrationHandle, // From EventRegister &TransferEvent, // EVENT_DESCRIPTOR generated from the manifest (ULONG)MAX_PAYLOAD_DESCRIPTORS, // Size of the array of EVENT_DATA_DESCRIPTORs &Descriptors[0] // Array of descriptors that contain the event data ); if (status != ERROR_SUCCESS) { wprintf(L"EventWrite failed with 0x%x", status); } cleanup: EventUnregister(RegistrationHandle); getchar(); return 0; }
目前该方案,可以用前面的基础知识,传入ProviderGuid来进行解析,数据在pEvent->UserData中
typedef struct _EVENT_RECORD { EVENT_HEADER EventHeader; // Event header ETW_BUFFER_CONTEXT BufferContext; // Buffer context USHORT ExtendedDataCount; // Number of extended // data items USHORT UserDataLength; // User data length PEVENT_HEADER_EXTENDED_DATA_ITEM // Pointer to an array of ExtendedData; // extended data items PVOID UserData; // Pointer to user data PVOID UserContext; // Context from OpenTrace } EVENT_RECORD, *PEVENT_RECORD;
2.发布一个ETW
Publishing Your Event Schema for a Manifest-based Provider
<!-- <?xml version="1.0" encoding="UTF-16"?> --> <instrumentationManifest xmlns="http://schemas.microsoft.com/win/2004/08/events" xmlns:win="https://manifests.microsoft.com/win/2004/08/windows/events" xmlns:xs="https://www.w3.org/2001/XMLSchema" > <instrumentation> <events> <provider name="Microsoft-Windows-ETWProvider" guid="{D8909C24-5BE9-4502-98CA-AB7BDC24899D}" symbol="ProviderGuid" resourceFileName="c:\code\etw\v2provider\debug\v2provider.exe" messageFileName="c:\code\etw\v2provider\debug\v2provider.exe" message="$(string.Provider.Name)" > <keywords> <keyword name="Read" symbol="READ_KEYWORD" mask="0x1" /> <keyword name="Write" symbol="WRITE_KEYWORD" mask="0x2" /> <keyword name="Local" symbol="LOCAL_KEYWORD" mask="0x4" /> <keyword name="Remote" symbol="REMOTE_KEYWORD" mask="0x8" /> </keywords> <maps> <valueMap name="TransferType"> <map value="1" message="$(string.Map.Download)"/> <map value="2" message="$(string.Map.Upload)"/> <map value="3" message="$(string.Map.UploadReply)"/> </valueMap> <bitMap name="DaysOfTheWeek"> <map value="0x1" message="$(string.Map.Sunday)"/> <map value="0x2" message="$(string.Map.Monday)"/> <map value="0x4" message="$(string.Map.Tuesday)"/> <map value="0x8" message="$(string.Map.Wednesday)"/> <map value="0x10" message="$(string.Map.Thursday)"/> <map value="0x20" message="$(string.Map.Friday)"/> <map value="0x40" message="$(string.Map.Saturday)"/> </bitMap> </maps> <templates> <template tid="TransferTemplate"> <data name="Image" inType="win:Pointer"/> <data name="Scores" inType="win:UInt16" count="3"/> <data name="ID" inType="win:GUID"/> <data name="Certificate" inType="win:Binary" length="11" /> <data name="IsLocal" inType="win:Boolean" /> <data name="Path" inType="win:UnicodeString" /> <data name="ValuesCount" inType="win:UInt16" /> <struct name="Values" count="ValuesCount" > <data name="Name" inType="win:UnicodeString" /> <data name="Value" inType="win:UInt16" /> </struct> <data name="Day" inType="win:UInt32" map="DaysOfTheWeek"/> <data name="Transfer" inType="win:UInt32" map="TransferType"/> <UserData> <EventData xmlns="ProviderNamespace"> <Transfer> %10 </Transfer> <Day> %9 </Day> <ValuesCount> %7 </ValuesCount> <Values> %8 </Values> <Path> %6 </Path> <IsLocal> %5 </IsLocal> <Scores> %2 </Scores> <Image> %1 </Image> <Certificate> %4 </Certificate> <ID> %3 </ID> </EventData> </UserData> </template> </templates> <events> <event value="1" level="win:Informational" template="TransferTemplate" symbol="TransferEvent" message ="$(string.Event.WhenToTransfer)" keywords="Read Local" /> </events> </provider> </events> </instrumentation> <localization> <resources culture="en-US"> <stringTable> <string id="Provider.Name" value="Microsoft-Windows-ETWProvider"/> <string id="Map.Download" value="Download"/> <string id="Map.Upload" value="Upload"/> <string id="Map.UploadReply" value="Upload-reply"/> <string id="Map.Sunday" value="Sunday"/> <string id="Map.Monday" value="Monday"/> <string id="Map.Tuesday" value="Tuesday"/> <string id="Map.Wednesday" value="Wednesday"/> <string id="Map.Thursday" value="Thursday"/> <string id="Map.Friday" value="Friday"/> <string id="Map.Saturday" value="Saturday"/> <string id="Event.WhenToTransfer" value="The %10 transfer will occur %9."/> </stringTable> </resources> </localization> </instrumentationManifest>
具体如何使用xml可以参考UIForETW项目的ETWProviders.dll编写