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_INSTANCE_GUID_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_INSTANCE_GUID_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.
An event that begins with an EVENT_INSTANCE_GUID_HEADER gets into the trace buffers by being presented to the kernel through the NtTraceEvent function. The expected user-mode caller is the NTDLL function EtwTraceEventInstance, which is in turn typically (and better) called as a forward from the documented ADVAPI32 export TraceEventInstance. The NTDLL function creates the EVENT_INSTANCE_GUID_HEADER from the EVENT_INSTANCE_HEADER and EVENT_INSTANCE_INFO structures that are its inputs. Well-behaved user-mode software other than NTDLL therefore has no need to know of the EVENT_INSTANCE_GUID_HEADER.
The EVENT_INSTANCE_GUID_HEADER structure is not documented.
Only two public disclosures are known from Microsoft, not that either is any sort of plain-English documentation. One is that a previously unpublished header named NTWMI.H was published in the original and Version 1511 editions of the Windows Driver Kit (WDK) for Windows 10, and this header contains a C-language definition of the structure.
Were it not for this limited and possibly unintended disclosure of NTWMI.H, a practical equivalent of the C-language definition (but missing comments, of course) would anyway be known from type information in symbol files. But this too has the look of an oversight. Type information for this structure has never appeared in any public symbol files for the kernel or for the obvious low-level user-mode DLLs. It has instead slipped out in symbol files for a smattering of higher-level user-mode DLLs, starting with Windows 8. For these few, the readily available symbol files actually are private symbol files and show that the unpublished NTWMI.H was included when compiling the corresponding binaries.
Incidentally, the definition in NTWMI.H is preceded by several lines of comment. This would be unusual enough, but is specially instructive for what it says of an intention that the structure is not public:
// New struct that replaces EVENT_INSTANCE_GUID_HEADER. It is basically // EVENT_TRACE_HEADER + 2 Guids. // For XP, we will not publish this struct and hide it from users. // TRACE_VERSION in LOG_FILE_HEADER will tell the consumer APIs to use // this struct instead of EVENT_TRACE_HEADER.
The EVENT_INSTANCE_GUID_HEADER is 0x48 bytes in both 32-bit and 64-bit Windows in all known versions that have it, i.e., 5.2 and higher.
Offset | Definition | NtTraceEvent Input and Output |
---|---|---|
0x00 |
USHORT Size; |
both (may change) |
0x02 |
union { USHORT FieldTypeFlags; struct { UCHAR HeaderType; UCHAR MarkerFlags; }; }; |
output |
0x04 |
union { ULONG Version; struct { UCHAR Type; UCHAR Level; USHORT Version; } Class; }; |
passed through |
0x08 |
ULONG ThreadId; |
output |
0x0C |
ULONG ProcessId; |
output |
0x10 |
LARGE_INTEGER TimeStamp; |
output |
0x18 |
union { GUID Guid; ULONGLONG GuidPtr; }; |
Guid is both (may change); GuidPtr is input |
0x28 |
union { struct { ULONG ClientContext; ULONG Flags; }; struct { ULONG KernelTime; ULONG UserTime; }; ULONG64 ProcessorTime; }; |
Flags are input; KernelTime is output; UserTime is output |
0x30 |
ULONG InstanceId; |
passed through |
0x34 |
ULONG ParentInstanceId; |
passed through |
0x38 |
GUID ParentGuid; |
passed through |
The first 4 bytes have common elements in all the various Trace Headers. They are distinguished from the WNODE_HEADER by making its 32-bit BufferSize look implausible for having its highest bit set. For the EVENT_INSTANCE_GUID_HEADER, this is the high bit in the MarkerFlags at offset 0x03. Of trace headers that have the two highest bits set, what distinguishes a header as continuing specifically as an EVENT_INSTANCE_GUID_HEADER is the HeaderType at offset 0x02:
Value | Name | Implied Layout |
---|---|---|
0x0B | TRACE_HEADER_TYPE_INSTANCE32 | 0x48 bytes of header followed by 32-bit event data |
0x15 | TRACE_HEADER_TYPE_INSTANCE64 | 0x48 bytes of header followed by 64-bit event data |
These names are from Microsoft’s NTWMI.H. Also given in the similarly semi-secret NTETW.H are 32-bit values for the first four bytes without the Size:
Value | Name |
---|---|
0xC00B0000 | TRACE_HEADER_INSTANCE32 |
0xC0150000 | TRACE_HEADER_INSTANCE64 |
The first 0x30 bytes of the EVENT_INSTANCE_GUID_HEADER are those of the EVENT_TRACE_HEADER. The additional members support the event’s placement in a hierarchical relationship of events. The InstanceId labels this event, along with its Guid. All being well, the ParentInstanceId and ParentGuid for this event are the InstanceId and Guid of some other event, which can then be recognised as this event’s parent.