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

Documentation Status

The ETW_GUID_ENTRY structure is not documented.


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 Windows Vista SP1) 0x0158 0x0170
late 6.0 (Windows Vista SP1 and higher)
6.1 0x0178 0x01B0
6.2 to 6.3 0x0160 0x0178
10.0 0x0160 0x0180
1511 and higher 0x0168 0x0190


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
6.0 and higher
0x08 0x10
LONG_PTR volatile RefCount;
6.0 and higher
0x0C 0x18
GUID Guid;
6.0 and higher
0x1C 0x28
6.0 and higher
0x24 0x38
6.0 and higher
0x28 0x40
ULONG LegacyProviderEnabled;
early 6.0 only
late 6.0 only
union {
    ULONGLONG MatchId;
6.1 and higher
0x38 0x50
TRACE_ENABLE_INFO ProviderEnableInfo;
6.0 and higher
0x58 0x70
6.0 and higher
0x0158 0x0170
6.1 only
6.2 only
6.3 and higher
0x015C 0x0178
ESILO *ServerSilo;
10.0 only
UCHAR HostSilo;
1511 only
1607 and higher
0x0160 0x0180
1511 and higher
0x0164 0x0188
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.