Geoff Chappell, Software Analyst
The TRACE_ENABLE_FLAG_EXTENSION was introduced for Windows version 5.1 as a reinterpretation of the 32-bit EnableFlags in the EVENT_TRACE_PROPERTIES and WMI_LOGGER_INFORMATION structures to allow for many more flags. Of these two structures, the former is the input and output for the user-mode API functions such as StartTrace and the latter is its repackaging for the native API function NtTraceControl. The structures therefore have compatibility considerations. The aim to this particular design for the EnableFlags appears to have been that the extended flags could be added in space after either structure without having to change the structures.
Version 6.0 elaborated the elaboration, turning the TRACE_ENABLE_FLAG_EXTENSION into a more generalised indicator that the EVENT_TRACE_PROPERTIES or WMI_LOGGER_INFORMATION may come not just with extended flags but with various types of extended information.
The TRACE_ENABLE_FLAG_EXTENSION is not documented. Neither are the closely related TRACE_ENABLE_FLAG_EXT_HEADER and TRACE_ENABLE_FLAG_EXT_ITEM structures, which this note also describes.
Even the EVENT_TRACE_FLAG_EXTENSION flag, which is what indicates that the EnableFlags are interpreted differently from the documentation, is not documented. Microsoft does, however, publish a macro definition for it in the C-language header EVNTRACE.H from Microsoft’s various Windows development kits—even from as far back as the Device Driver Kit (DDK) for Windows 2000. (Yes, the suggestion is that the opening statement about introduction for version 5.1 may be incorrect about how early the extension was developed).
Only two other public disclosures are known from Microsoft. One is in packages of symbol files that Microsoft publishes as debugging aids. Curiously, type information for these structures is not in symbol files for the kernel or for low-level user-mode DLLs, where the structures are interpreted, but is instead in symbol files for such user-mode oddities as AppXDeploymentClient.dll and only then in Windows 8 and higher. The other public disclosure is C-language definitions in NTWMI.H from the Enterprise edition of the Windows Driver Kit (WDK) for Windows 10 version 1511. This disclosure is not repeated in subsequent editions and is here thought to be an oversight. Still, published it is, which means that this note uses Microsoft’s names throughout.
The essential point to the TRACE_ENABLE_FLAG_EXTENSION is that it overlays the EnableFlags. It is therefore four bytes in both 32-bit and 64-bit Windows:
Offset | Definition | Versions |
---|---|---|
0x00 |
USHORT Offset; |
5.1 and higher |
0x02 |
UCHAR Length; |
5.1 and higher |
0x03 |
UCHAR Flag; |
5.1 and higher |
In the original implementation, the Offset measures in bytes from the start of the containing structure (EVENT_TRACE_PROPERTIES or WMI_LOGGER_INFORMATION) to an array of dwords that are the extended EnableFlags. The Length counts the dwords in the array.
What distinguishes the EnableFlags for reinterpretation is that its highest bit, which Microsoft defines as EVENT_TRACE_FLAG_EXTENSION, is set. Thus, the Flag byte in a TRACE_ENABLE_FLAG_EXTENSION necessarily has its highest bit set. No use is known of other bits in the Flag.
In the elaboration for version 6.0 and higher, not only does Flag have its high bit set (to confirm that EnableFlags is a TRACE_ENABLE_FLAG_EXTENSION) but the Length has the otherwise implausible value 0xFF. This signifies that the array of dwords at Offset bytes from the start of the containing structure has a new interpretation not as an array to extend one dword of EnableFlags but as a more general extension to a sequence of items.
The first dword of this more general extension is specifically a TRACE_ENABLE_FLAG_EXT_HEADER:
Offset | Definition | Versions |
---|---|---|
0x00 |
USHORT Length; |
6.0 and higher |
0x02 |
USHORT Items; |
6.0 and higher |
The Length, as before, is the number of dwords in the array, which now includes the TRACE_ENABLE_FLAG_EXT_HEADER. Subsequent dwords in the array are a sequence of Items items.
Each item is introduced by its own header. This is the one-dword TRACE_ENABLE_FLAG_EXT_ITEM structure:
Offset | Definition | Versions |
---|---|---|
0x00 |
USHORT Offset; |
6.0 and higher |
0x02 |
USHORT Type; |
6.0 and higher |
Perhaps confusingly, this Offset measures not bytes but dwords from the start of this item to the next item (or to the non-inclusive end of the array). It is equivalently the number of dwords in the item, including the TRACE_ENABLE_FLAG_EXT_ITEM. Subsequent dwords in the item are data for the item. Their interpretation depends on the Type. Microsoft’s names are known from NTWMI.H:
Value | Name | Versions | Item Data |
---|---|---|---|
0x0001 | ETW_EXT_ENABLE_FLAGS | 6.0 and higher | as many as eight dwords for a PERFINFO_GROUPMASK |
0x0002 | ETW_EXT_PIDS | 6.0 and higher | each dword is a process ID |
0x0003 | ETW_EXT_STACKWALK_FILTER | 6.0 and higher | each dword is a 16-bit hook ID |
0x0004 | ETW_EXT_POOLTAG_FILTER | 6.1 and higher | each dword is a pool tag |
0x0005 | ETW_EXT_STACK_CACHING | 6.2 and higher | exactly two dwords as an ETW_STACK_CACHING_CONFIG |
The 8-byte ETW_STACK_CACHING_CONFIG is known from both NTWMI.H and from those few public symbol files.