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 SYSTEM_TRACE_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 a SYSTEM_TRACE_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.
The SYSTEM_TRACE_HEADER is not documented, but a C-language definition is published in the NTWMI.H from the Enterprise edition of the Windows Driver Kit (WDK) for Windows 10 version 1511.
Were it not for this relatively recent and possibly unintended disclosure, much would anyway be known from type information in symbol files. Curiously though, 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. In the whole of Microsoft’s packages of public symbol files, at least to the original Windows 10, relevant type information is unknown before Windows 8 and appears in symbol files only for AppXDeploymentClient.dll, CertEnroll.dll (before Windows 10) and Windows.Storage.ApplicationData.dll.
The SYSTEM_TRACE_HEADER is 0x20 bytes in both 32-bit and 64-bit Windows in all versions that are known to have it at all, i.e., 5.0 and higher. Be aware, however, that the structure can exist in a so-called compact form that is only the first 0x18 bytes.
Offset | Definition | Remarks |
---|---|---|
0x00 |
union { ULONG Marker; struct { USHORT Version; UCHAR HeaderType; UCHAR Flags; }; }; |
|
0x04 |
union { ULONG Header; WMI_TRACE_PACKET Packet; }; |
|
0x08 |
ULONG ThreadId; |
|
0x0C |
ULONG ProcessId; |
|
0x10 |
LARGE_INTEGER SystemTime; |
last member in compact SYSTEM_TRACE_HEADER |
0x18 |
ULONG KernelTime; |
|
0x1C |
ULONG UserTime; |
The first 4 bytes have common elements in all the various Trace Headers. All have the high bit set in the Flags at offset 0x03. Of those that have the two highest bits set, what distinguishes a header as continuing specifically as a SYSTEM_TRACE_HEADER is the HeaderType at offset 0x02:
Value | Name | Implied Layout |
---|---|---|
0x01 | TRACE_HEADER_TYPE_SYSTEM32 | full 0x20 bytes of header followed by 32-bit event data |
0x02 | TRACE_HEADER_TYPE_SYSTEM64 | full 0x20 bytes of header followed by 64-bit event data |
0x03 | TRACE_HEADER_TYPE_COMPACT32 | first 0x18 bytes of header followed by 32-bit event data |
0x04 | TRACE_HEADER_TYPE_COMPACT64 | first 0x18 bytes of header followed by 64-bit event data |
Also defined in NTWMI.H are combinations of the Flags and HeaderType, ready for use as a basis for the Marker as the first dword:
Value (x86) | Value (x64) | Name |
---|---|---|
0xC0010000 | 0xC0020000 | SYSTEM_TRACE_MARKER |
0xC0030000 |
0xC0040000 | COMPACT_TRACE_MARKER |
To these markers must yet be added the Version. Though the Version is formally the low word, the kernel treats it as 8-bit. It is presently thought that this Version is not of the header but of the event-specific data that follows the header. Both 0x02 and 0x03 are observed in Windows 10.
The second four bytes are shared by SYSTEM_TRACE_HEADER and PERFINFO_TRACE_HEADER, these being the old and less old headers for system events.
The WMI_TRACE_PACKET at offset 0x04 is two words:
Offset | Definition |
---|---|
0x00 |
USHORT Size; |
0x02 |
union { USHORT HookId; struct { UCHAR Type; UCHAR Group; }; }; |
The total size of data for the event, i.e., both the fixed-size header and the variable-size event data, is given by the Size member of the Packet, i.e., at offset 0x04 in the header. The HookId at offset 0x06 in the header tells what type of event is logged and determines the meaning of whatever event data follows the header. In the absence of an EVENT_DESCRIPTOR for events that have a SYSTEM_TRACE_HEADER, the HookId is effectively the event identifier (no matter that by the time it gets translated for consumers its Group and Type show as a ProviderId and Opcode). A list of the known Hook IDs for NT Kernel Logger Events is presented separately.
The remaining members may pass as self-explanatory, but note that the SystemTime is named in contrast to the kernel and user times, not to imply use of system time as the clock.