| //**********************************************************************` | |
| //* This is an include file generated by Message Compiler. *` | |
| //* *` | |
| //* Copyright (c) Microsoft Corporation. All Rights Reserved. *` | |
| //**********************************************************************` | |
| #pragma once | |
| //***************************************************************************** | |
| // | |
| // Notes on the ETW event code generated by MC: | |
| // | |
| // - Structures and arrays of structures are treated as an opaque binary blob. | |
| // The caller is responsible for packing the data for the structure into a | |
| // single region of memory, with no padding between values. The macro will | |
| // have an extra parameter for the length of the blob. | |
| // - Arrays of nul-terminated strings must be packed by the caller into a | |
| // single binary blob containing the correct number of strings, with a nul | |
| // after each string. The size of the blob is specified in characters, and | |
| // includes the final nul. | |
| // - Arrays of SID are treated as a single binary blob. The caller is | |
| // responsible for packing the SID values into a single region of memory with | |
| // no padding. | |
| // - The length attribute on the data element in the manifest is significant | |
| // for values with intype win:UnicodeString, win:AnsiString, or win:Binary. | |
| // The length attribute must be specified for win:Binary, and is optional for | |
| // win:UnicodeString and win:AnsiString (if no length is given, the strings | |
| // are assumed to be nul-terminated). For win:UnicodeString, the length is | |
| // measured in characters, not bytes. | |
| // - For an array of win:UnicodeString, win:AnsiString, or win:Binary, the | |
| // length attribute applies to every value in the array, so every value in | |
| // the array must have the same length. The values in the array are provided | |
| // to the macro via a single pointer -- the caller is responsible for packing | |
| // all of the values into a single region of memory with no padding between | |
| // values. | |
| // - Values of type win:CountedUnicodeString, win:CountedAnsiString, and | |
| // win:CountedBinary can be generated and collected on Vista or later. | |
| // However, they may not decode properly without the Windows 10 2018 Fall | |
| // Update. | |
| // - Arrays of type win:CountedUnicodeString, win:CountedAnsiString, and | |
| // win:CountedBinary must be packed by the caller into a single region of | |
| // memory. The format for each item is a UINT16 byte-count followed by that | |
| // many bytes of data. When providing the array to the generated macro, you | |
| // must provide the total size of the packed array data, including the UINT16 | |
| // sizes for each item. In the case of win:CountedUnicodeString, the data | |
| // size is specified in WCHAR (16-bit) units. In the case of | |
| // win:CountedAnsiString and win:CountedBinary, the data size is specified in | |
| // bytes. | |
| // | |
| //***************************************************************************** | |
| #include <wmistr.h> | |
| #include <evntrace.h> | |
| #include <evntprov.h> | |
| #ifndef ETW_INLINE | |
| #ifdef _ETW_KM_ | |
| // In kernel mode, save stack space by never inlining templates. | |
| #define ETW_INLINE DECLSPEC_NOINLINE __inline | |
| #else | |
| // In user mode, save code size by inlining templates as appropriate. | |
| #define ETW_INLINE __inline | |
| #endif | |
| #endif // ETW_INLINE | |
| #if defined(__cplusplus) | |
| extern "C" { | |
| #endif | |
| // | |
| // MCGEN_DISABLE_PROVIDER_CODE_GENERATION macro: | |
| // Define this macro to have the compiler skip the generated functions in this | |
| // header. | |
| // | |
| #ifndef MCGEN_DISABLE_PROVIDER_CODE_GENERATION | |
| // | |
| // MCGEN_USE_KERNEL_MODE_APIS macro: | |
| // Controls whether the generated code uses kernel-mode or user-mode APIs. | |
| // - Set to 0 to use Windows user-mode APIs such as EventRegister. | |
| // - Set to 1 to use Windows kernel-mode APIs such as EtwRegister. | |
| // Default is based on whether the _ETW_KM_ macro is defined (i.e. by wdm.h). | |
| // Note that the APIs can also be overridden directly, e.g. by setting the | |
| // MCGEN_EVENTWRITETRANSFER or MCGEN_EVENTREGISTER macros. | |
| // | |
| #ifndef MCGEN_USE_KERNEL_MODE_APIS | |
| #ifdef _ETW_KM_ | |
| #define MCGEN_USE_KERNEL_MODE_APIS 1 | |
| #else | |
| #define MCGEN_USE_KERNEL_MODE_APIS 0 | |
| #endif | |
| #endif // MCGEN_USE_KERNEL_MODE_APIS | |
| // | |
| // MCGEN_HAVE_EVENTSETINFORMATION macro: | |
| // Controls how McGenEventSetInformation uses the EventSetInformation API. | |
| // - Set to 0 to disable the use of EventSetInformation | |
| // (McGenEventSetInformation will always return an error). | |
| // - Set to 1 to directly invoke MCGEN_EVENTSETINFORMATION. | |
| // - Set to 2 to to locate EventSetInformation at runtime via GetProcAddress | |
| // (user-mode) or MmGetSystemRoutineAddress (kernel-mode). | |
| // Default is determined as follows: | |
| // - If MCGEN_EVENTSETINFORMATION has been customized, set to 1 | |
| // (i.e. use MCGEN_EVENTSETINFORMATION). | |
| // - Else if the target OS version has EventSetInformation, set to 1 | |
| // (i.e. use MCGEN_EVENTSETINFORMATION). | |
| // - Else set to 2 (i.e. try to dynamically locate EventSetInformation). | |
| // Note that an McGenEventSetInformation function will only be generated if one | |
| // or more provider in a manifest has provider traits. | |
| // | |
| #ifndef MCGEN_HAVE_EVENTSETINFORMATION | |
| #ifdef MCGEN_EVENTSETINFORMATION // if MCGEN_EVENTSETINFORMATION has been customized, | |
| #define MCGEN_HAVE_EVENTSETINFORMATION 1 // directly invoke MCGEN_EVENTSETINFORMATION(...). | |
| #elif MCGEN_USE_KERNEL_MODE_APIS // else if using kernel-mode APIs, | |
| #if NTDDI_VERSION >= 0x06040000 // if target OS is Windows 10 or later, | |
| #define MCGEN_HAVE_EVENTSETINFORMATION 1 // directly invoke MCGEN_EVENTSETINFORMATION(...). | |
| #else // else | |
| #define MCGEN_HAVE_EVENTSETINFORMATION 2 // find "EtwSetInformation" via MmGetSystemRoutineAddress. | |
| #endif // else (using user-mode APIs) | |
| #else // if target OS and SDK is Windows 8 or later, | |
| #if WINVER >= 0x0602 && defined(EVENT_FILTER_TYPE_SCHEMATIZED) | |
| #define MCGEN_HAVE_EVENTSETINFORMATION 1 // directly invoke MCGEN_EVENTSETINFORMATION(...). | |
| #else // else | |
| #define MCGEN_HAVE_EVENTSETINFORMATION 2 // find "EventSetInformation" via GetModuleHandleExW/GetProcAddress. | |
| #endif | |
| #endif | |
| #endif // MCGEN_HAVE_EVENTSETINFORMATION | |
| // | |
| // MCGEN Override Macros | |
| // | |
| // The following override macros may be defined before including this header | |
| // to control the APIs used by this header: | |
| // | |
| // - MCGEN_EVENTREGISTER | |
| // - MCGEN_EVENTUNREGISTER | |
| // - MCGEN_EVENTSETINFORMATION | |
| // - MCGEN_EVENTWRITETRANSFER | |
| // | |
| // If the macro is undefined, the MC implementation will default to the | |
| // corresponding ETW APIs. For example, if the MCGEN_EVENTREGISTER macro is | |
| // undefined, the EventRegister[MyProviderName] macro will use EventRegister | |
| // in user mode and will use EtwRegister in kernel mode. | |
| // | |
| // To prevent issues from conflicting definitions of these macros, the value | |
| // of the override macro will be used as a suffix in certain internal function | |
| // names. Because of this, the override macros must follow certain rules: | |
| // | |
| // - The macro must be defined before any MC-generated header is included and | |
| // must not be undefined or redefined after any MC-generated header is | |
| // included. Different translation units (i.e. different .c or .cpp files) | |
| // may set the macros to different values, but within a translation unit | |
| // (within a single .c or .cpp file), the macro must be set once and not | |
| // changed. | |
| // - The override must be an object-like macro, not a function-like macro | |
| // (i.e. the override macro must not have a parameter list). | |
| // - The override macro's value must be a simple identifier, i.e. must be | |
| // something that starts with a letter or '_' and contains only letters, | |
| // numbers, and '_' characters. | |
| // - If the override macro's value is the name of a second object-like macro, | |
| // the second object-like macro must follow the same rules. (The override | |
| // macro's value can also be the name of a function-like macro, in which | |
| // case the function-like macro does not need to follow the same rules.) | |
| // | |
| // For example, the following will cause compile errors: | |
| // | |
| // #define MCGEN_EVENTWRITETRANSFER MyNamespace::MyClass::MyFunction // Value has non-identifier characters (colon). | |
| // #define MCGEN_EVENTWRITETRANSFER GetEventWriteFunctionPointer(7) // Value has non-identifier characters (parentheses). | |
| // #define MCGEN_EVENTWRITETRANSFER(h,e,a,r,c,d) EventWrite(h,e,c,d) // Override is defined as a function-like macro. | |
| // #define MY_OBJECT_LIKE_MACRO MyNamespace::MyClass::MyEventWriteFunction | |
| // #define MCGEN_EVENTWRITETRANSFER MY_OBJECT_LIKE_MACRO // Evaluates to something with non-identifier characters (colon). | |
| // | |
| // The following would be ok: | |
| // | |
| // #define MCGEN_EVENTWRITETRANSFER MyEventWriteFunction1 // OK, suffix will be "MyEventWriteFunction1". | |
| // #define MY_OBJECT_LIKE_MACRO MyEventWriteFunction2 | |
| // #define MCGEN_EVENTWRITETRANSFER MY_OBJECT_LIKE_MACRO // OK, suffix will be "MyEventWriteFunction2". | |
| // #define MY_FUNCTION_LIKE_MACRO(h,e,a,r,c,d) MyNamespace::MyClass::MyEventWriteFunction3(h,e,c,d) | |
| // #define MCGEN_EVENTWRITETRANSFER MY_FUNCTION_LIKE_MACRO // OK, suffix will be "MY_FUNCTION_LIKE_MACRO". | |
| // | |
| #ifndef MCGEN_EVENTREGISTER | |
| #if MCGEN_USE_KERNEL_MODE_APIS | |
| #define MCGEN_EVENTREGISTER EtwRegister | |
| #else | |
| #define MCGEN_EVENTREGISTER EventRegister | |
| #endif | |
| #endif // MCGEN_EVENTREGISTER | |
| #ifndef MCGEN_EVENTUNREGISTER | |
| #if MCGEN_USE_KERNEL_MODE_APIS | |
| #define MCGEN_EVENTUNREGISTER EtwUnregister | |
| #else | |
| #define MCGEN_EVENTUNREGISTER EventUnregister | |
| #endif | |
| #endif // MCGEN_EVENTUNREGISTER | |
| #ifndef MCGEN_EVENTSETINFORMATION | |
| #if MCGEN_USE_KERNEL_MODE_APIS | |
| #define MCGEN_EVENTSETINFORMATION EtwSetInformation | |
| #else | |
| #define MCGEN_EVENTSETINFORMATION EventSetInformation | |
| #endif | |
| #endif // MCGEN_EVENTSETINFORMATION | |
| #ifndef MCGEN_EVENTWRITETRANSFER | |
| #if MCGEN_USE_KERNEL_MODE_APIS | |
| #define MCGEN_EVENTWRITETRANSFER EtwWriteTransfer | |
| #else | |
| #define MCGEN_EVENTWRITETRANSFER EventWriteTransfer | |
| #endif | |
| #endif // MCGEN_EVENTWRITETRANSFER | |
| // | |
| // MCGEN_EVENT_ENABLED macro: | |
| // Override to control how the EventWrite[EventName] macros determine whether | |
| // an event is enabled. The default behavior is for EventWrite[EventName] to | |
| // use the EventEnabled[EventName] macros. | |
| // | |
| #ifndef MCGEN_EVENT_ENABLED | |
| #define MCGEN_EVENT_ENABLED(EventName) EventEnabled##EventName() | |
| #endif | |
| // | |
| // MCGEN_EVENT_ENABLED_FORCONTEXT macro: | |
| // Override to control how the EventWrite[EventName]_ForContext macros | |
| // determine whether an event is enabled. The default behavior is for | |
| // EventWrite[EventName]_ForContext to use the | |
| // EventEnabled[EventName]_ForContext macros. | |
| // | |
| #ifndef MCGEN_EVENT_ENABLED_FORCONTEXT | |
| #define MCGEN_EVENT_ENABLED_FORCONTEXT(pContext, EventName) EventEnabled##EventName##_ForContext(pContext) | |
| #endif | |
| // | |
| // MCGEN_ENABLE_CHECK macro: | |
| // Determines whether the specified event would be considered as enabled | |
| // based on the state of the specified context. Slightly faster than calling | |
| // McGenEventEnabled directly. | |
| // | |
| #ifndef MCGEN_ENABLE_CHECK | |
| #define MCGEN_ENABLE_CHECK(Context, Descriptor) (Context.IsEnabled && McGenEventEnabled(&Context, &Descriptor)) | |
| #endif | |
| #if !defined(MCGEN_TRACE_CONTEXT_DEF) | |
| #define MCGEN_TRACE_CONTEXT_DEF | |
| // This structure is for use by MC-generated code and should not be used directly. | |
| typedef struct _MCGEN_TRACE_CONTEXT | |
| { | |
| TRACEHANDLE RegistrationHandle; | |
| TRACEHANDLE Logger; // Used as pointer to provider traits. | |
| ULONGLONG MatchAnyKeyword; | |
| ULONGLONG MatchAllKeyword; | |
| ULONG Flags; | |
| ULONG IsEnabled; | |
| UCHAR Level; | |
| UCHAR Reserve; | |
| USHORT EnableBitsCount; | |
| PULONG EnableBitMask; | |
| const ULONGLONG* EnableKeyWords; | |
| const UCHAR* EnableLevel; | |
| } MCGEN_TRACE_CONTEXT, *PMCGEN_TRACE_CONTEXT; | |
| #endif // MCGEN_TRACE_CONTEXT_DEF | |
| #if !defined(MCGEN_LEVEL_KEYWORD_ENABLED_DEF) | |
| #define MCGEN_LEVEL_KEYWORD_ENABLED_DEF | |
| // | |
| // Determines whether an event with a given Level and Keyword would be | |
| // considered as enabled based on the state of the specified context. | |
| // Note that you may want to use MCGEN_ENABLE_CHECK instead of calling this | |
| // function directly. | |
| // | |
| FORCEINLINE | |
| BOOLEAN | |
| McGenLevelKeywordEnabled( | |
| _In_ PMCGEN_TRACE_CONTEXT EnableInfo, | |
| _In_ UCHAR Level, | |
| _In_ ULONGLONG Keyword | |
| ) | |
| { | |
| // | |
| // Check if the event Level is lower than the level at which | |
| // the channel is enabled. | |
| // If the event Level is 0 or the channel is enabled at level 0, | |
| // all levels are enabled. | |
| // | |
| if ((Level <= EnableInfo->Level) || // This also covers the case of Level == 0. | |
| (EnableInfo->Level == 0)) { | |
| // | |
| // Check if Keyword is enabled | |
| // | |
| if ((Keyword == (ULONGLONG)0) || | |
| ((Keyword & EnableInfo->MatchAnyKeyword) && | |
| ((Keyword & EnableInfo->MatchAllKeyword) == EnableInfo->MatchAllKeyword))) { | |
| return TRUE; | |
| } | |
| } | |
| return FALSE; | |
| } | |
| #endif // MCGEN_LEVEL_KEYWORD_ENABLED_DEF | |
| #if !defined(MCGEN_EVENT_ENABLED_DEF) | |
| #define MCGEN_EVENT_ENABLED_DEF | |
| // | |
| // Determines whether the specified event would be considered as enabled based | |
| // on the state of the specified context. Note that you may want to use | |
| // MCGEN_ENABLE_CHECK instead of calling this function directly. | |
| // | |
| FORCEINLINE | |
| BOOLEAN | |
| McGenEventEnabled( | |
| _In_ PMCGEN_TRACE_CONTEXT EnableInfo, | |
| _In_ PCEVENT_DESCRIPTOR EventDescriptor | |
| ) | |
| { | |
| return McGenLevelKeywordEnabled(EnableInfo, EventDescriptor->Level, EventDescriptor->Keyword); | |
| } | |
| #endif // MCGEN_EVENT_ENABLED_DEF | |
| #if !defined(MCGEN_CONTROL_CALLBACK) | |
| #define MCGEN_CONTROL_CALLBACK | |
| // This function is for use by MC-generated code and should not be used directly. | |
| DECLSPEC_NOINLINE __inline | |
| VOID | |
| __stdcall | |
| McGenControlCallbackV2( | |
| _In_ LPCGUID SourceId, | |
| _In_ ULONG ControlCode, | |
| _In_ UCHAR Level, | |
| _In_ ULONGLONG MatchAnyKeyword, | |
| _In_ ULONGLONG MatchAllKeyword, | |
| _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, | |
| _Inout_opt_ PVOID CallbackContext | |
| ) | |
| /*++ | |
| Routine Description: | |
| This is the notification callback for Windows Vista and later. | |
| Arguments: | |
| SourceId - The GUID that identifies the session that enabled the provider. | |
| ControlCode - The parameter indicates whether the provider | |
| is being enabled or disabled. | |
| Level - The level at which the event is enabled. | |
| MatchAnyKeyword - The bitmask of keywords that the provider uses to | |
| determine the category of events that it writes. | |
| MatchAllKeyword - This bitmask additionally restricts the category | |
| of events that the provider writes. | |
| FilterData - The provider-defined data. | |
| CallbackContext - The context of the callback that is defined when the provider | |
| called EtwRegister to register itself. | |
| Remarks: | |
| ETW calls this function to notify provider of enable/disable | |
| --*/ | |
| { | |
| PMCGEN_TRACE_CONTEXT Ctx = (PMCGEN_TRACE_CONTEXT)CallbackContext; | |
| ULONG Ix; | |
| #ifndef MCGEN_PRIVATE_ENABLE_CALLBACK_V2 | |
| UNREFERENCED_PARAMETER(SourceId); | |
| UNREFERENCED_PARAMETER(FilterData); | |
| #endif | |
| if (Ctx == NULL) { | |
| return; | |
| } | |
| switch (ControlCode) { | |
| case EVENT_CONTROL_CODE_ENABLE_PROVIDER: | |
| Ctx->Level = Level; | |
| Ctx->MatchAnyKeyword = MatchAnyKeyword; | |
| Ctx->MatchAllKeyword = MatchAllKeyword; | |
| Ctx->IsEnabled = EVENT_CONTROL_CODE_ENABLE_PROVIDER; | |
| for (Ix = 0; Ix < Ctx->EnableBitsCount; Ix += 1) { | |
| if (McGenLevelKeywordEnabled(Ctx, Ctx->EnableLevel[Ix], Ctx->EnableKeyWords[Ix]) != FALSE) { | |
| Ctx->EnableBitMask[Ix >> 5] |= (1 << (Ix % 32)); | |
| } else { | |
| Ctx->EnableBitMask[Ix >> 5] &= ~(1 << (Ix % 32)); | |
| } | |
| } | |
| break; | |
| case EVENT_CONTROL_CODE_DISABLE_PROVIDER: | |
| Ctx->IsEnabled = EVENT_CONTROL_CODE_DISABLE_PROVIDER; | |
| Ctx->Level = 0; | |
| Ctx->MatchAnyKeyword = 0; | |
| Ctx->MatchAllKeyword = 0; | |
| if (Ctx->EnableBitsCount > 0) { | |
| #pragma warning(suppress: 26451) // Arithmetic overflow cannot occur, no matter the value of EnableBitCount | |
| RtlZeroMemory(Ctx->EnableBitMask, (((Ctx->EnableBitsCount - 1) / 32) + 1) * sizeof(ULONG)); | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| #ifdef MCGEN_PRIVATE_ENABLE_CALLBACK_V2 | |
| // | |
| // Call user defined callback | |
| // | |
| MCGEN_PRIVATE_ENABLE_CALLBACK_V2( | |
| SourceId, | |
| ControlCode, | |
| Level, | |
| MatchAnyKeyword, | |
| MatchAllKeyword, | |
| FilterData, | |
| CallbackContext | |
| ); | |
| #endif // MCGEN_PRIVATE_ENABLE_CALLBACK_V2 | |
| return; | |
| } | |
| #endif // MCGEN_CONTROL_CALLBACK | |
| #ifndef _mcgen_PENABLECALLBACK | |
| #if MCGEN_USE_KERNEL_MODE_APIS | |
| #define _mcgen_PENABLECALLBACK PETWENABLECALLBACK | |
| #else | |
| #define _mcgen_PENABLECALLBACK PENABLECALLBACK | |
| #endif | |
| #endif // _mcgen_PENABLECALLBACK | |
| #if !defined(_mcgen_PASTE2) | |
| // This macro is for use by MC-generated code and should not be used directly. | |
| #define _mcgen_PASTE2(a, b) _mcgen_PASTE2_imp(a, b) | |
| #define _mcgen_PASTE2_imp(a, b) a##b | |
| #endif // _mcgen_PASTE2 | |
| #if !defined(_mcgen_PASTE3) | |
| // This macro is for use by MC-generated code and should not be used directly. | |
| #define _mcgen_PASTE3(a, b, c) _mcgen_PASTE3_imp(a, b, c) | |
| #define _mcgen_PASTE3_imp(a, b, c) a##b##_##c | |
| #endif // _mcgen_PASTE3 | |
| // | |
| // Macro validation | |
| // | |
| // Validate MCGEN_EVENTREGISTER: | |
| // Trigger an error if MCGEN_EVENTREGISTER is not an unqualified (simple) identifier: | |
| struct _mcgen_PASTE2(MCGEN_EVENTREGISTER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTREGISTER); | |
| // Trigger an error if MCGEN_EVENTREGISTER is redefined: | |
| typedef struct _mcgen_PASTE2(MCGEN_EVENTREGISTER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTREGISTER) | |
| MCGEN_EVENTREGISTER_must_not_be_redefined_between_headers; | |
| // Trigger an error if MCGEN_EVENTREGISTER is defined as a function-like macro: | |
| typedef void MCGEN_EVENTREGISTER_must_not_be_a_functionLike_macro_MCGEN_EVENTREGISTER; | |
| typedef int _mcgen_PASTE2(MCGEN_EVENTREGISTER_must_not_be_a_functionLike_macro_, MCGEN_EVENTREGISTER); | |
| // Validate MCGEN_EVENTUNREGISTER: | |
| // Trigger an error if MCGEN_EVENTUNREGISTER is not an unqualified (simple) identifier: | |
| struct _mcgen_PASTE2(MCGEN_EVENTUNREGISTER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTUNREGISTER); | |
| // Trigger an error if MCGEN_EVENTUNREGISTER is redefined: | |
| typedef struct _mcgen_PASTE2(MCGEN_EVENTUNREGISTER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTUNREGISTER) | |
| MCGEN_EVENTUNREGISTER_must_not_be_redefined_between_headers; | |
| // Trigger an error if MCGEN_EVENTUNREGISTER is defined as a function-like macro: | |
| typedef void MCGEN_EVENTUNREGISTER_must_not_be_a_functionLike_macro_MCGEN_EVENTUNREGISTER; | |
| typedef int _mcgen_PASTE2(MCGEN_EVENTUNREGISTER_must_not_be_a_functionLike_macro_, MCGEN_EVENTUNREGISTER); | |
| // Validate MCGEN_EVENTSETINFORMATION: | |
| // Trigger an error if MCGEN_EVENTSETINFORMATION is not an unqualified (simple) identifier: | |
| struct _mcgen_PASTE2(MCGEN_EVENTSETINFORMATION_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTSETINFORMATION); | |
| // Trigger an error if MCGEN_EVENTSETINFORMATION is redefined: | |
| typedef struct _mcgen_PASTE2(MCGEN_EVENTSETINFORMATION_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTSETINFORMATION) | |
| MCGEN_EVENTSETINFORMATION_must_not_be_redefined_between_headers; | |
| // Trigger an error if MCGEN_EVENTSETINFORMATION is defined as a function-like macro: | |
| typedef void MCGEN_EVENTSETINFORMATION_must_not_be_a_functionLike_macro_MCGEN_EVENTSETINFORMATION; | |
| typedef int _mcgen_PASTE2(MCGEN_EVENTSETINFORMATION_must_not_be_a_functionLike_macro_, MCGEN_EVENTSETINFORMATION); | |
| // Validate MCGEN_EVENTWRITETRANSFER: | |
| // Trigger an error if MCGEN_EVENTWRITETRANSFER is not an unqualified (simple) identifier: | |
| struct _mcgen_PASTE2(MCGEN_EVENTWRITETRANSFER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTWRITETRANSFER); | |
| // Trigger an error if MCGEN_EVENTWRITETRANSFER is redefined: | |
| typedef struct _mcgen_PASTE2(MCGEN_EVENTWRITETRANSFER_definition_must_be_an_unqualified_identifier_, MCGEN_EVENTWRITETRANSFER) | |
| MCGEN_EVENTWRITETRANSFER_must_not_be_redefined_between_headers;; | |
| // Trigger an error if MCGEN_EVENTWRITETRANSFER is defined as a function-like macro: | |
| typedef void MCGEN_EVENTWRITETRANSFER_must_not_be_a_functionLike_macro_MCGEN_EVENTWRITETRANSFER; | |
| typedef int _mcgen_PASTE2(MCGEN_EVENTWRITETRANSFER_must_not_be_a_functionLike_macro_, MCGEN_EVENTWRITETRANSFER); | |
| #ifndef McGenEventWrite_def | |
| #define McGenEventWrite_def | |
| // This macro is for use by MC-generated code and should not be used directly. | |
| #define McGenEventWrite _mcgen_PASTE2(McGenEventWrite_, MCGEN_EVENTWRITETRANSFER) | |
| // This function is for use by MC-generated code and should not be used directly. | |
| DECLSPEC_NOINLINE __inline | |
| ULONG __stdcall | |
| McGenEventWrite( | |
| _In_ PMCGEN_TRACE_CONTEXT Context, | |
| _In_ PCEVENT_DESCRIPTOR Descriptor, | |
| _In_opt_ LPCGUID ActivityId, | |
| _In_range_(1, 128) ULONG EventDataCount, | |
| _Pre_cap_(EventDataCount) EVENT_DATA_DESCRIPTOR* EventData | |
| ) | |
| { | |
| const USHORT UNALIGNED* Traits; | |
| // Some customized MCGEN_EVENTWRITETRANSFER macros might ignore ActivityId. | |
| UNREFERENCED_PARAMETER(ActivityId); | |
| Traits = (const USHORT UNALIGNED*)(UINT_PTR)Context->Logger; | |
| if (Traits == NULL) { | |
| EventData[0].Ptr = 0; | |
| EventData[0].Size = 0; | |
| EventData[0].Reserved = 0; | |
| } else { | |
| EventData[0].Ptr = (ULONG_PTR)Traits; | |
| EventData[0].Size = *Traits; | |
| EventData[0].Reserved = 2; // EVENT_DATA_DESCRIPTOR_TYPE_PROVIDER_METADATA | |
| } | |
| return MCGEN_EVENTWRITETRANSFER( | |
| Context->RegistrationHandle, | |
| Descriptor, | |
| ActivityId, | |
| NULL, | |
| EventDataCount, | |
| EventData); | |
| } | |
| #endif // McGenEventWrite_def | |
| #if !defined(McGenEventRegisterUnregister) | |
| #define McGenEventRegisterUnregister | |
| // This macro is for use by MC-generated code and should not be used directly. | |
| #define McGenEventRegister _mcgen_PASTE2(McGenEventRegister_, MCGEN_EVENTREGISTER) | |
| #pragma warning(push) | |
| #pragma warning(disable:6103) | |
| // This function is for use by MC-generated code and should not be used directly. | |
| DECLSPEC_NOINLINE __inline | |
| ULONG __stdcall | |
| McGenEventRegister( | |
| _In_ LPCGUID ProviderId, | |
| _In_opt_ _mcgen_PENABLECALLBACK EnableCallback, | |
| _In_opt_ PVOID CallbackContext, | |
| _Inout_ PREGHANDLE RegHandle | |
| ) | |
| /*++ | |
| Routine Description: | |
| This function registers the provider with ETW. | |
| Arguments: | |
| ProviderId - Provider ID to register with ETW. | |
| EnableCallback - Callback to be used. | |
| CallbackContext - Context for the callback. | |
| RegHandle - Pointer to registration handle. | |
| Remarks: | |
| Should not be called if the provider is already registered (i.e. should not | |
| be called if *RegHandle != 0). Repeatedly registering a provider is a bug | |
| and may indicate a race condition. However, for compatibility with previous | |
| behavior, this function will return SUCCESS in this case. | |
| --*/ | |
| { | |
| ULONG Error; | |
| if (*RegHandle != 0) | |
| { | |
| Error = 0; // ERROR_SUCCESS | |
| } | |
| else | |
| { | |
| Error = MCGEN_EVENTREGISTER(ProviderId, EnableCallback, CallbackContext, RegHandle); | |
| } | |
| return Error; | |
| } | |
| #pragma warning(pop) | |
| // This macro is for use by MC-generated code and should not be used directly. | |
| #define McGenEventUnregister _mcgen_PASTE2(McGenEventUnregister_, MCGEN_EVENTUNREGISTER) | |
| // This function is for use by MC-generated code and should not be used directly. | |
| DECLSPEC_NOINLINE __inline | |
| ULONG __stdcall | |
| McGenEventUnregister(_Inout_ PREGHANDLE RegHandle) | |
| /*++ | |
| Routine Description: | |
| Unregister from ETW and set *RegHandle = 0. | |
| Arguments: | |
| RegHandle - the pointer to the provider registration handle | |
| Remarks: | |
| If provider has not been registered (i.e. if *RegHandle == 0), | |
| return SUCCESS. It is safe to call McGenEventUnregister even if the | |
| call to McGenEventRegister returned an error. | |
| --*/ | |
| { | |
| ULONG Error; | |
| if(*RegHandle == 0) | |
| { | |
| Error = 0; // ERROR_SUCCESS | |
| } | |
| else | |
| { | |
| Error = MCGEN_EVENTUNREGISTER(*RegHandle); | |
| *RegHandle = (REGHANDLE)0; | |
| } | |
| return Error; | |
| } | |
| #endif // McGenEventRegisterUnregister | |
| #ifndef _mcgen_EVENT_BIT_SET | |
| #if defined(_M_IX86) || defined(_M_X64) | |
| // This macro is for use by MC-generated code and should not be used directly. | |
| #define _mcgen_EVENT_BIT_SET(EnableBits, BitPosition) ((((const unsigned char*)EnableBits)[BitPosition >> 3] & (1u << (BitPosition & 7))) != 0) | |
| #else // CPU type | |
| // This macro is for use by MC-generated code and should not be used directly. | |
| #define _mcgen_EVENT_BIT_SET(EnableBits, BitPosition) ((EnableBits[BitPosition >> 5] & (1u << (BitPosition & 31))) != 0) | |
| #endif // CPU type | |
| #endif // _mcgen_EVENT_BIT_SET | |
| #endif // MCGEN_DISABLE_PROVIDER_CODE_GENERATION | |
| //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
| // Provider "microsoft-windows-mimalloc" event count 2 | |
| //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
| // Provider GUID = 138f4dbb-ee04-4899-aa0a-572ad4475779 | |
| EXTERN_C __declspec(selectany) const GUID ETW_MI_Provider = {0x138f4dbb, 0xee04, 0x4899, {0xaa, 0x0a, 0x57, 0x2a, 0xd4, 0x47, 0x57, 0x79}}; | |
| #ifndef ETW_MI_Provider_Traits | |
| #define ETW_MI_Provider_Traits NULL | |
| #endif // ETW_MI_Provider_Traits | |
| // | |
| // Event Descriptors | |
| // | |
| EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR ETW_MI_ALLOC = {0x64, 0x1, 0x0, 0x4, 0x0, 0x0, 0x0}; | |
| #define ETW_MI_ALLOC_value 0x64 | |
| EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR ETW_MI_FREE = {0x65, 0x1, 0x0, 0x4, 0x0, 0x0, 0x0}; | |
| #define ETW_MI_FREE_value 0x65 | |
| // | |
| // MCGEN_DISABLE_PROVIDER_CODE_GENERATION macro: | |
| // Define this macro to have the compiler skip the generated functions in this | |
| // header. | |
| // | |
| #ifndef MCGEN_DISABLE_PROVIDER_CODE_GENERATION | |
| // | |
| // Event Enablement Bits | |
| // These variables are for use by MC-generated code and should not be used directly. | |
| // | |
| EXTERN_C __declspec(selectany) DECLSPEC_CACHEALIGN ULONG microsoft_windows_mimallocEnableBits[1]; | |
| EXTERN_C __declspec(selectany) const ULONGLONG microsoft_windows_mimallocKeywords[1] = {0x0}; | |
| EXTERN_C __declspec(selectany) const unsigned char microsoft_windows_mimallocLevels[1] = {4}; | |
| // | |
| // Provider context | |
| // | |
| EXTERN_C __declspec(selectany) MCGEN_TRACE_CONTEXT ETW_MI_Provider_Context = {0, (ULONG_PTR)ETW_MI_Provider_Traits, 0, 0, 0, 0, 0, 0, 1, microsoft_windows_mimallocEnableBits, microsoft_windows_mimallocKeywords, microsoft_windows_mimallocLevels}; | |
| // | |
| // Provider REGHANDLE | |
| // | |
| #define microsoft_windows_mimallocHandle (ETW_MI_Provider_Context.RegistrationHandle) | |
| // | |
| // This macro is set to 0, indicating that the EventWrite[Name] macros do not | |
| // have an Activity parameter. This is controlled by the -km and -um options. | |
| // | |
| #define ETW_MI_Provider_EventWriteActivity 0 | |
| // | |
| // Register with ETW using the control GUID specified in the manifest. | |
| // Invoke this macro during module initialization (i.e. program startup, | |
| // DLL process attach, or driver load) to initialize the provider. | |
| // Note that if this function returns an error, the error means that | |
| // will not work, but no action needs to be taken -- even if EventRegister | |
| // returns an error, it is generally safe to use EventWrite and | |
| // EventUnregister macros (they will be no-ops if EventRegister failed). | |
| // | |
| #ifndef EventRegistermicrosoft_windows_mimalloc | |
| #define EventRegistermicrosoft_windows_mimalloc() McGenEventRegister(&ETW_MI_Provider, McGenControlCallbackV2, &ETW_MI_Provider_Context, µsoft_windows_mimallocHandle) | |
| #endif | |
| // | |
| // Register with ETW using a specific control GUID (i.e. a GUID other than what | |
| // is specified in the manifest). Advanced scenarios only. | |
| // | |
| #ifndef EventRegisterByGuidmicrosoft_windows_mimalloc | |
| #define EventRegisterByGuidmicrosoft_windows_mimalloc(Guid) McGenEventRegister(&(Guid), McGenControlCallbackV2, &ETW_MI_Provider_Context, µsoft_windows_mimallocHandle) | |
| #endif | |
| // | |
| // Unregister with ETW and close the provider. | |
| // Invoke this macro during module shutdown (i.e. program exit, DLL process | |
| // detach, or driver unload) to unregister the provider. | |
| // Note that you MUST call EventUnregister before DLL or driver unload | |
| // (not optional): failure to unregister a provider before DLL or driver unload | |
| // will result in crashes. | |
| // | |
| #ifndef EventUnregistermicrosoft_windows_mimalloc | |
| #define EventUnregistermicrosoft_windows_mimalloc() McGenEventUnregister(µsoft_windows_mimallocHandle) | |
| #endif | |
| // | |
| // MCGEN_ENABLE_FORCONTEXT_CODE_GENERATION macro: | |
| // Define this macro to enable support for caller-allocated provider context. | |
| // | |
| #ifdef MCGEN_ENABLE_FORCONTEXT_CODE_GENERATION | |
| // | |
| // Advanced scenarios: Caller-allocated provider context. | |
| // Use when multiple differently-configured provider handles are needed, | |
| // e.g. for container-aware drivers, one context per container. | |
| // | |
| // Usage: | |
| // | |
| // - Caller enables the feature before including this header, e.g. | |
| // #define MCGEN_ENABLE_FORCONTEXT_CODE_GENERATION 1 | |
| // - Caller allocates memory, e.g. pContext = malloc(sizeof(McGenContext_microsoft_windows_mimalloc)); | |
| // - Caller registers the provider, e.g. EventRegistermicrosoft_windows_mimalloc_ForContext(pContext); | |
| // - Caller writes events, e.g. EventWriteMyEvent_ForContext(pContext, ...); | |
| // - Caller unregisters, e.g. EventUnregistermicrosoft_windows_mimalloc_ForContext(pContext); | |
| // - Caller frees memory, e.g. free(pContext); | |
| // | |
| typedef struct tagMcGenContext_microsoft_windows_mimalloc { | |
| // The fields of this structure are subject to change and should | |
| // not be accessed directly. To access the provider's REGHANDLE, | |
| // use microsoft_windows_mimallocHandle_ForContext(pContext). | |
| MCGEN_TRACE_CONTEXT Context; | |
| ULONG EnableBits[1]; | |
| } McGenContext_microsoft_windows_mimalloc; | |
| #define EventRegistermicrosoft_windows_mimalloc_ForContext(pContext) _mcgen_PASTE2(_mcgen_RegisterForContext_microsoft_windows_mimalloc_, MCGEN_EVENTREGISTER)(&ETW_MI_Provider, pContext) | |
| #define EventRegisterByGuidmicrosoft_windows_mimalloc_ForContext(Guid, pContext) _mcgen_PASTE2(_mcgen_RegisterForContext_microsoft_windows_mimalloc_, MCGEN_EVENTREGISTER)(&(Guid), pContext) | |
| #define EventUnregistermicrosoft_windows_mimalloc_ForContext(pContext) McGenEventUnregister(&(pContext)->Context.RegistrationHandle) | |
| // | |
| // Provider REGHANDLE for caller-allocated context. | |
| // | |
| #define microsoft_windows_mimallocHandle_ForContext(pContext) ((pContext)->Context.RegistrationHandle) | |
| // This function is for use by MC-generated code and should not be used directly. | |
| // Initialize and register the caller-allocated context. | |
| __inline | |
| ULONG __stdcall | |
| _mcgen_PASTE2(_mcgen_RegisterForContext_microsoft_windows_mimalloc_, MCGEN_EVENTREGISTER)( | |
| _In_ LPCGUID pProviderId, | |
| _Out_ McGenContext_microsoft_windows_mimalloc* pContext) | |
| { | |
| RtlZeroMemory(pContext, sizeof(*pContext)); | |
| pContext->Context.Logger = (ULONG_PTR)ETW_MI_Provider_Traits; | |
| pContext->Context.EnableBitsCount = 1; | |
| pContext->Context.EnableBitMask = pContext->EnableBits; | |
| pContext->Context.EnableKeyWords = microsoft_windows_mimallocKeywords; | |
| pContext->Context.EnableLevel = microsoft_windows_mimallocLevels; | |
| return McGenEventRegister( | |
| pProviderId, | |
| McGenControlCallbackV2, | |
| &pContext->Context, | |
| &pContext->Context.RegistrationHandle); | |
| } | |
| // This function is for use by MC-generated code and should not be used directly. | |
| // Trigger a compile error if called with the wrong parameter type. | |
| FORCEINLINE | |
| _Ret_ McGenContext_microsoft_windows_mimalloc* | |
| _mcgen_CheckContextType_microsoft_windows_mimalloc(_In_ McGenContext_microsoft_windows_mimalloc* pContext) | |
| { | |
| return pContext; | |
| } | |
| #endif // MCGEN_ENABLE_FORCONTEXT_CODE_GENERATION | |
| // | |
| // Enablement check macro for event "ETW_MI_ALLOC" | |
| // | |
| #define EventEnabledETW_MI_ALLOC() _mcgen_EVENT_BIT_SET(microsoft_windows_mimallocEnableBits, 0) | |
| #define EventEnabledETW_MI_ALLOC_ForContext(pContext) _mcgen_EVENT_BIT_SET(_mcgen_CheckContextType_microsoft_windows_mimalloc(pContext)->EnableBits, 0) | |
| // | |
| // Event write macros for event "ETW_MI_ALLOC" | |
| // | |
| #define EventWriteETW_MI_ALLOC(Address, Size) \ | |
| MCGEN_EVENT_ENABLED(ETW_MI_ALLOC) \ | |
| ? _mcgen_TEMPLATE_FOR_ETW_MI_ALLOC(&ETW_MI_Provider_Context, &ETW_MI_ALLOC, Address, Size) : 0 | |
| #define EventWriteETW_MI_ALLOC_AssumeEnabled(Address, Size) \ | |
| _mcgen_TEMPLATE_FOR_ETW_MI_ALLOC(&ETW_MI_Provider_Context, &ETW_MI_ALLOC, Address, Size) | |
| #define EventWriteETW_MI_ALLOC_ForContext(pContext, Address, Size) \ | |
| MCGEN_EVENT_ENABLED_FORCONTEXT(pContext, ETW_MI_ALLOC) \ | |
| ? _mcgen_TEMPLATE_FOR_ETW_MI_ALLOC(&(pContext)->Context, &ETW_MI_ALLOC, Address, Size) : 0 | |
| #define EventWriteETW_MI_ALLOC_ForContextAssumeEnabled(pContext, Address, Size) \ | |
| _mcgen_TEMPLATE_FOR_ETW_MI_ALLOC(&_mcgen_CheckContextType_microsoft_windows_mimalloc(pContext)->Context, &ETW_MI_ALLOC, Address, Size) | |
| // This macro is for use by MC-generated code and should not be used directly. | |
| #define _mcgen_TEMPLATE_FOR_ETW_MI_ALLOC _mcgen_PASTE2(McTemplateU0xx_, MCGEN_EVENTWRITETRANSFER) | |
| // | |
| // Enablement check macro for event "ETW_MI_FREE" | |
| // | |
| #define EventEnabledETW_MI_FREE() _mcgen_EVENT_BIT_SET(microsoft_windows_mimallocEnableBits, 0) | |
| #define EventEnabledETW_MI_FREE_ForContext(pContext) _mcgen_EVENT_BIT_SET(_mcgen_CheckContextType_microsoft_windows_mimalloc(pContext)->EnableBits, 0) | |
| // | |
| // Event write macros for event "ETW_MI_FREE" | |
| // | |
| #define EventWriteETW_MI_FREE(Address, Size) \ | |
| MCGEN_EVENT_ENABLED(ETW_MI_FREE) \ | |
| ? _mcgen_TEMPLATE_FOR_ETW_MI_FREE(&ETW_MI_Provider_Context, &ETW_MI_FREE, Address, Size) : 0 | |
| #define EventWriteETW_MI_FREE_AssumeEnabled(Address, Size) \ | |
| _mcgen_TEMPLATE_FOR_ETW_MI_FREE(&ETW_MI_Provider_Context, &ETW_MI_FREE, Address, Size) | |
| #define EventWriteETW_MI_FREE_ForContext(pContext, Address, Size) \ | |
| MCGEN_EVENT_ENABLED_FORCONTEXT(pContext, ETW_MI_FREE) \ | |
| ? _mcgen_TEMPLATE_FOR_ETW_MI_FREE(&(pContext)->Context, &ETW_MI_FREE, Address, Size) : 0 | |
| #define EventWriteETW_MI_FREE_ForContextAssumeEnabled(pContext, Address, Size) \ | |
| _mcgen_TEMPLATE_FOR_ETW_MI_FREE(&_mcgen_CheckContextType_microsoft_windows_mimalloc(pContext)->Context, &ETW_MI_FREE, Address, Size) | |
| // This macro is for use by MC-generated code and should not be used directly. | |
| #define _mcgen_TEMPLATE_FOR_ETW_MI_FREE _mcgen_PASTE2(McTemplateU0xx_, MCGEN_EVENTWRITETRANSFER) | |
| #endif // MCGEN_DISABLE_PROVIDER_CODE_GENERATION | |
| // | |
| // MCGEN_DISABLE_PROVIDER_CODE_GENERATION macro: | |
| // Define this macro to have the compiler skip the generated functions in this | |
| // header. | |
| // | |
| #ifndef MCGEN_DISABLE_PROVIDER_CODE_GENERATION | |
| // | |
| // Template Functions | |
| // | |
| // | |
| // Function for template "ETW_CUSTOM_HEAP_ALLOC_DATA" (and possibly others). | |
| // This function is for use by MC-generated code and should not be used directly. | |
| // | |
| #ifndef McTemplateU0xx_def | |
| #define McTemplateU0xx_def | |
| ETW_INLINE | |
| ULONG | |
| _mcgen_PASTE2(McTemplateU0xx_, MCGEN_EVENTWRITETRANSFER)( | |
| _In_ PMCGEN_TRACE_CONTEXT Context, | |
| _In_ PCEVENT_DESCRIPTOR Descriptor, | |
| _In_ const unsigned __int64 _Arg0, | |
| _In_ const unsigned __int64 _Arg1 | |
| ) | |
| { | |
| #define McTemplateU0xx_ARGCOUNT 2 | |
| EVENT_DATA_DESCRIPTOR EventData[McTemplateU0xx_ARGCOUNT + 1]; | |
| EventDataDescCreate(&EventData[1],&_Arg0, sizeof(const unsigned __int64) ); | |
| EventDataDescCreate(&EventData[2],&_Arg1, sizeof(const unsigned __int64) ); | |
| return McGenEventWrite(Context, Descriptor, NULL, McTemplateU0xx_ARGCOUNT + 1, EventData); | |
| } | |
| #endif // McTemplateU0xx_def | |
| #endif // MCGEN_DISABLE_PROVIDER_CODE_GENERATION | |
| #if defined(__cplusplus) | |
| } | |
| #endif |