Geoff Chappell - Software Analyst
This page is being prepared for a substantial reworking. Some content may be temporarily missing. Temporarily may turn into indefinitely. New content may be more than usually defective. The page is now published only as a revision in progress. Use with caution.
The EVENT_HEADER (formally _EVENT_HEADER) is one of several types of fixed-size header that introduce variable-size data for events that are logged through Event Tracing for Windows (ETW). As with other types of event, those that begin with an EVENT_HEADER accumulate first in trace buffers. To have these events persist in this raw form for ready inspection, configure the event tracing session to flush the trace buffers to an Event Trace Log (ETL) file.
Among the various trace headers, the EVENT_HEADER is unusual in that it is not just a transitory implementation detail for how one type of event gets packed into the trace buffers or even for how NTDLL passes events to the kernel. It is also the header, within an EVENT_RECORD, when event data is unpacked for event consumers—even of event data that had a different header while in the trace buffers. This article is concerned only with the packed form.
The EVENT_HEADER was introduced for Windows Vista.
Two ways are known that an event begins with an EVENT_HEADER rather than some other trace header. One is that it is delivered to the kernel through the NtTraceEvent function. For this, the Flags argument masked with ETW_NT_TRACE_TYPE_MASK must be ETW_NT_FLAGS_TRACE_EVENT. The Fields argument must then address an event
Presumably because of its role in interfaces that support event consumers, the EVENT_HEADER structure is defined in the EVNTCONS.H header for user-mode programming and is documented.
Note, however, that the EVENT_HEADER is documented merely as “defines information about the event” as if the structure exists solely for delivering the event to an event consumer. One might easily miss that the structure has a very much longer role in the life of most events, including even when NTDLL prepares an event for sending to the kernel.
The EVENT_HEADER is 0x50 bytes in both 32-bit and 64-bit Windows in all versions that are known to have it.
Offset | Definition |
---|---|
0x00 |
USHORT Size; |
0x02 |
USHORT HeaderType; |
0x04 |
USHORT Flags; |
0x06 |
USHORT EventProperty; |
0x08 |
ULONG ThreadId; |
0x0C |
ULONG ProcessId; |
0x10 |
LARGE_INTEGER TimeStamp; |
0x18 |
GUID ProviderId; |
0x28 |
EVENT_DESCRIPTOR EventDescriptor; |
0x38 |
union { struct { ULONG KernelTime; ULONG UserTime; }; ULONG64 ProcessorTime; }; |
0x40 |
GUID ActivityId; |
The Size is the total, in bytes, of the EVENT_HEADER and all the event data that follows. To understand the fixed-size header, it helps to know that the variable-size data that follows it is broadly in two parts:
What distinguishes the EVENT_HEADER from other trace headers are special values in the bytes at offset 0x02 and 0x03. For the EVENT_HEADER, but for no other types of trace header, Microsoft models these bytes together as a 16-bit HeaderType. Whether they’re defined as two bytes or one word, two combinations of these bytes at offsets 0x02 and 0x03 distinguish that a trace header is specifically an EVENT_HEADER. Microsoft’s names for them as values for the HeaderType are known from an NTETW.H which Microsoft distributed with the original and Version 1511 editions of the Windows Driver Kit (WDK) for Windows 10:
Value | Name | Implied Layout |
---|---|---|
0xC012 | EVENT_HEADER_EVENT32 | 0x50 bytes of header followed by 32-bit event data |
0xC013 | EVENT_HEADER_EVENT64 | 0x50 bytes of header followed by 64-bit event data |
Microsoft defines the following in EVNTCONS.H as bits for the Flags:
Value | Name | SDK Versions |
---|---|---|
0x0001 | EVENT_HEADER_FLAG_EXTENDED_INFO | 6.0 and higher |
0x0002 | EVENT_HEADER_FLAG_PRIVATE_SESSION | 6.0 and higher |
0x0004 | EVENT_HEADER_FLAG_STRING_ONLY | 6.0 and higher |
0x0008 | EVENT_HEADER_FLAG_TRACE_MESSAGE | 6.0 and higher |
0x0010 | EVENT_HEADER_FLAG_NO_CPUTIME | 6.0 and higher |
0x0020 | EVENT_HEADER_FLAG_32_BIT_HEADER | 6.0 and higher |
0x0040 | EVENT_HEADER_FLAG_64_BIT_HEADER | 6.0 and higher |
0x0080 | EVENT_HEADER_FLAG_DECODE_GUID | 1709 and higher |
0x0100 | EVENT_HEADER_FLAG_CLASSIC_HEADER | 6.0 and higher |
0x0200 | EVENT_HEADER_FLAG_PROCESSOR_INDEX | 6.2 and higher |
Microsoft defines them because they are set for the structure that is presented to event consumers. The Flags are mostly not meaningful (and cannot be set) in an EVENT_HEADER that is in the trace buffers. Some exist precisely to tell the event consumer that the event originated differently. For instance, an event that gets EVENT_HEADER_FLAG_TRACE_MESSAGE set in its presentation to an event consumer actually started its life with a MESSAGE_TRACE_HEADER.
Microsoft defines the following for EventProperty:
Value | Name |
---|---|
0x0001 | EVENT_HEADER_PROPERTY_XML |
0x0002 | EVENT_HEADER_PROPERTY_FORWARDED_XML |
0x0004 | EVENT_HEADER_PROPERTY_LEGACY_EVENTLOG |
0x0008 | EVENT_HEADER_PROPERTY_RELOGGABLE |
Most of the other members are generated at logging-time. The ProviderGuid and ActivityId are saved from function arguments.
The kernel sets EVENT_HEADER_FLAG_EXTENDED_INFO in the Flags to indicate that the EVENT_HEADER is followed by at least one extended data item. Each such item appears, after 8-byte alignment, as a fixed-size header and variable-size data. The header is an EVENT_HEADER_EXTENDED_DATA_ITEM, not quite as defined in EVNTCONS.H:
Offset | Definition |
---|---|
0x00 |
USHORT Reserved1; |
0x02 |
USHORT ExtType; |
0x04 |
struct { USHORT Linkage : 1; USHORT Reserved2 : 15; }; |
0x06 |
USHORT DataSize; |
0x08 |
ULONGLONG DataPtr; |
The key difference is that DataPtr is not space for a 32-bit or 64-bit pointer to wherever the unpacking has placed the variable-size data. Instead, it holds that data, or at least the beginning of that data. The Reserved1 member is the total size, i.e., of the first 8 bytes of the EVENT_HEADER_EXTENDED_DATA_ITEM plus the DataSize bytes of variable-size data. The form of that data depends on the ExtType. Microsoft’s EVNTCONS.H defines the following values and names:
Value | Name | DataPtr Replacement |
---|---|---|
0x0001 | EVENT_HEADER_EXT_TYPE_RELATED_ACTIVITYID | EVENT_EXTENDED_ITEM_RELATED_ACTIVITYID |
0x0002 | EVENT_HEADER_EXT_TYPE_SID | SID |
0x0003 | EVENT_HEADER_EXT_TYPE_TS_ID | EVENT_EXTENDED_ITEM_TS_ID |
0x0004 | EVENT_HEADER_EXT_TYPE_INSTANCE_INFO | EVENT_EXTENDED_ITEM_INSTANCE |
0x0005 | EVENT_HEADER_EXT_TYPE_STACK_TRACE32 | EVENT_EXTENDED_ITEM_STACK_TRACE32 |
0x0006 | EVENT_HEADER_EXT_TYPE_STACK_TRACE64 | EVENT_EXTENDED_ITEM_STACK_TRACE64 |
0x0007 | EVENT_HEADER_EXT_TYPE_PEBS_INDEX | |
0x0008 | EVENT_HEADER_EXT_TYPE_PMC_COUNTERS | |
0x0009 | EVENT_HEADER_EXT_TYPE_PSM_KEY | |
0x000A | EVENT_HEADER_EXT_TYPE_EVENT_KEY | EVENT_EXTENDED_ITEM_EVENT_KEY |
0x000B | EVENT_HEADER_EXT_TYPE_EVENT_SCHEMA_TL | |
0x000C | EVENT_HEADER_EXT_TYPE_PROV_TRAITS | byte array |
0x000D | EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY | EVENT_EXTENDED_ITEM_PROCESS_START_KEY |
0x000E | EVENT_HEADER_EXT_TYPE_MAX |
TO BE CONTINUED