ETW_GUID_ENTRY

The ETW_GUID_ENTRY structure is the kernel’s record of an event provider.

Documentation Status

The ETW_GUID_ENTRY structure is not documented.

Variability

For a non-trivial structure that is plainly very much internal to the kernel, the ETW_GUID_ENTRY has been very stable. In the following table of sizes, different builds of Windows Vista are distinguished as early and late because they are known to vary the layout even though they don’t change the size.

Version Size (x86) Size (x64)
early 6.0 (before SP1);
late 6.0
0x0158 0x0170
6.1 0x0178 0x01B0
6.2 to 6.3 0x0160 0x0178
10.0 0x0160 0x0180
1511 to 1903 0x0168 0x0190
2004 0x0178 0x01A8

Layout

The preceding sizes, and the offsets, types and names in the table below are from Microsoft’s symbol files for the kernel starting with Windows Vista.

Offset (x86) Offset (x64) Definition Versions
0x00 0x00
LIST_ENTRY GuidList;
6.0 and higher
0x08 0x10
LIST_ENTRY SiloGuidList;
2004 and higher
0x08 (6.0 to 1903);
0x10
0x10 (6.0 to 1903);
0x20
LONG_PTR volatile RefCount;
6.0 and higher
0x0C (6.0 to 1903);
0x14
0x18 (6.0 to 1903);
0x28
GUID Guid;
6.0 and higher
0x1C (6.0 to 1903);
0x24
0x28 (6.0 to 1903);
0x38
LIST_ENTRY RegListHead;
6.0 and higher
0x24 (6.0 to 1903);
0x2C
0x38 (6.0 to 1903);
0x48
PSECURITY_DESCRIPTOR SecurityDescriptor;
6.0 and higher
0x28 (early 6.0) 0x40 (early 6.0)
TRACE_ENABLE_CONTEXT LegacyEnableContext;
early 6.0 only
0x30 (early 6.0) 0x48 (early 6.0)
ULONG LegacyProviderEnabled;
early 6.0 only
0x28 (late 6.0 to 1903);
0x30
0x40 (late 6.0 to 1903);
0x50
ETW_LAST_ENABLE_INFO LastEnable;
late 6.0 only
union {
    ETW_LAST_ENABLE_INFO LastEnable;
    ULONGLONG MatchId;
};
6.1 and higher
0x38 (6.0 to 1903);
0x40
0x50 (6.0 to 1903);
0x60
TRACE_ENABLE_INFO ProviderEnableInfo;
6.0 and higher
0x58 (6.0 to 1903);
0x60
0x70 (6.0 to 1903);
0x80
TRACE_ENABLE_INFO EnableInfo [8];
6.0 and higher
0x0158 (6.1 to 1903);
0x0160
0x0170 (6.1 to 1903);
0x0180
EVENT_FILTER_HEADER *FilterData [8];
6.1 only
EVENT_FILTER_HEADER **FilterData;
6.2 only
ETW_FILTER_HEADER *FilterData;
6.3 and higher
0x015C (10.0 to 1903);
0x0164
0x0178 (10.0 to 1903);
0x0188
ESILO *ServerSilo;
10.0 only
UCHAR HostSilo;
1511 only
ETW_SILODRIVERSTATE *SiloState;
1607 and higher
0x0168 0x0190
ETW_GUID_ENTRY *HostEntry;
2004 and higher
0x0160 (1511 to 1903);
0x016C
0x0180 (1511 to 1903);
0x0198
EX_PUSH_LOCK Lock;
1511 and higher
0x0164 (1511 to 1903);
0x0170
0x0188 (1511 to 1903);
0x01A0
ETHREAD *LockOwner;
1511 and higher

The Guid is not unique to an ETW_GUID_ENTRY. This is because event providers come in different types: trace provider; notification provider; and provider group (this last being new for Windows 10). Providers that have a different ETW_GUID_TYPE can have the same Guid because the corresponding ETW_GUID_ENTRY instances go into different lists. Windows 10 not only adds a list but also allows for multiplicity within each list: providers that register in multiple silos get a different instance for each silo. Whichever list an ETW_GUID_ENTRY goes into, it’s linked through its GuidList member.

Each registration of an event provider creates an ETW_REG_ENTRY structure. To register an event provider is in effect to open it with the intention of writing events through it. Registration from user mode formalises this by opening an Object Manager handle to the ETW_REG_ENTRY structure. An event provider can have concurrent registrations. The most notable purpose to this in practice is that an event provider can be distributed across multiple executable modules, including to mix kernel and user modes, which each write their selection of events through the one provider. The ETW_REG_ENTRY structures for the possibly many registrations of a provider are kept in the provider’s RegListHead, linking through their RegList member.

A provider can be concurrently enabled for at most eight tracing sesions, also known as loggers. The EnableInfo array records what the provider knows about these loggers. This includes, of course, the 16-bit LoggerId, but also parameters such as the Level, MatchAnyKeyword and MatchAllKeyword that the logger has specified for matching against event definitions to decide which events the logger is and is not interested in receiving. (The TRACE_ENABLE_INFO structure is declared in Microsoft’s EVNTRACE.H and is documented, though for reasons that are far removed from its use in the ETW_GUID_ENTRY.)

The ProviderEnableInfo member is an aggregate over all loggers, so that the provider can see quickly not to proceed with writing an event that is not enabled for any logger. It has the highest of any logger’s Level, a bit-wise OR of all loggers’ MatchAnyKeyword and a bit-wise AND of all loggers’ MatchAllKeyword.

Schematized event filters—also called provider-side filters—were added at kernel level for Windows 7. Loggers can specify one filter each. The original implementation has FilterData as an array of eight pointers to EVENT_FILTER_HEADER structures. The filter data for each logger is this header plus variable-size data, for a total size given by the header’s Size member. Version 6.2 changed to having one pointer to an array of eight pointers, each again to an EVENT_FILTER_HEADER and variable-size data. In version 6.3 and higher, the pointer is to an array of eight ETW_FILTER_HEADER structures, for each of which the EVENT_FILTER_HEADER and variable-size data is pointed to by the ProviderSideFilter member.

The new Lock for the 1511 release of Windows 10 allows that operations on one provider, such as adding an ETW_REG_ENTRY, do not delay operations on another. Earlier versions have a mutex in the kernel’s data.