WMI_BUFFER_HEADER

The WMI_BUFFER_HEADER structure begins each buffer that an event logger, or more formally an event tracing sesssion, uses for storing event data on the way to an Event Trace Log (ETL) file. Indeed, because such buffers are flushed as is, header and all, the structure is not only at the beginning of every ETL file but also recurs throughout.

The rest of each buffer, after the fixed-size WMI_BUFFER_HEADER, is a sequence of variable-size WMI data blocks. In the formulation for Windows Management Instrumentation (WMI), each data block begins with a fixed-size WNODE_HEADER. Event Tracing for Windows (ETW) repurposes the scheme so that each data block begins with one of several possible fixed-size Trace Headers.

Documentation Status

The WMI_BUFFER_HEADER structure is not documented. A C-language definition is published in NTWMI.H from the Enterprise edition of the Windows Driver Kit (WDK) for Windows 10 version 1511.

Layout

The WMI_BUFFER_HEADER is 0x48 bytes in both 32-bit and 64-bit Windows in all versions for which the structure is known, meaning 5.0 and higher. Offsets, names and types below are from type information for the structure in symbol files for the kernel, starting with Windows XP SP3 and Windows Server 2003 SP2. Since symbol files for earlier versions do not contain type information for this structure, what’s known for them is instead inferred from what use these versions of the kernel are seen to make of the structure in comparison with those for which Microsoft’s names and types are known. Where the correspondence is close, it seems reasonable to suppose continuity. Some use, however, has no correspondence, the code having changed too much. Even where the use hasn’t changed, tracking it down exhaustively would be difficult, if not impossible, even with source code.

The structure’s development is hard enough to track even for the versions that do have type information in public symbol files. The modern layout has been very nearly stable since Windows 7. The description of earlier versions is complicated because the structure’s compatibility with the documented WNODE_HEADER is explicit.

Offset Definition Versions
0x00
union {
    WNODE_HEADER Wnode;
    /*  unnamed structures, see below  */
};
5.0 to 5.2
union {
    WNODE_HEADER Wnode;
    /*  unnamed structure, see below  */
};
6.0 only
/*  unstructured members, see below  */
6.1 and higher
0x30
ULONG Offset;
5.0 and higher
0x34 (5.0 to 5.1)
ULONG EventsLost;
5.0 to 5.1
0x34
USHORT BufferFlag;
5.2  and higher
0x36
USHORT BufferType;
5.2 and higher
0x38
union {
    /*  changing members, see below  */
};
5.0 and higher

Microsoft’s names of values for the BufferFlag and BufferType are listed below, after all structures and unions.

WNODE Header

In versions before 6.0, the WMI_BUFFER_HEADER begins with a WNODE_HEADER in union with two unnamed structures. The first seems only ever to have had two meaningful members, SlistEntry and Entry, defined in that order but placed with Entry (at offset 0x18) before SlistEntry (at 0x1C).

Offset Definition Versions Remarks
0x00
ULONGLONG Reserved1;
5.0 to 5.2  
0x08
ULONGLONG Reserved2;
5.0 to 5.2  
0x10
LARGE_INTEGER Reserved3;
5.0 to 5.2  
0x18
LIST_ENTRY Entry;
5.0 only  
union {
    struct {
        PVOID Alignment;
        SINGLE_LIST_ENTRY SlistEntry;
    };
    LIST_ENTRY Entry;
};
5.1 to 5.2 SlistEntry next at offset 0x38;
Entry next at offset 0x38

Versions 5.0 to 5.2 cache free buffers. Version 5.0 keeps a double-linked list, linked through Entry at offset 0x18. Versions 5.1 and 5.2 keep a single-linked list with an SLIST_HEADER, linking through SlistEntry at offset 0x1C. While no use of the SlistEntry is known in version 5.0, it is here supposed to have been not yet defined.

When the two list entries were moved beyond the WNODE_HEADER to offset 0x38 for version 6.0, this branch of the union was removed. The other unnamed structure was anyway the one that more closely overlaid the WNODE_HEADER, duplicating the latter’s TimeStamp and Guid (and BufferSize, eventually) and keeping at least the names of the ClientContext and Flags members. It remained in union with the WNODE_HEADER until the latter was removed for version 6.1. Since then, its members are directly those of the WMI_BUFFER_HEADER:

Offset Definition Versions Remarks Notes
0x00
LONG ReferenceCount;
5.0 to 5.2 next as LONG volatile at 0x0C 5.0 known to use
ULONG BufferSize;
6.0 and higher    
0x04
ULONG SavedOffset;
5.0 and higher   5.0 known to use
0x08
ULONG CurrentOffset;
5.0 to 5.2   5.0 known to use
ULONG volatile CurrentOffset;
6.0 and higher    
0x0C
ULONG UsePerfClock;
5.0 to 5.2   5.0 known to use
LONG volatile ReferenceCount;
6.0 and higher previously LONG at 0x00  
0x10
LARGE_INTEGER TimeStamp;
5.0 to 5.2   5.0 known to use
union {
    LARGE_INTEGER TimeStamp;
    LARGE_INTEGER StartPerfClock;
};
6.0 only    
LARGE_INTEGER TimeStamp;
6.1 and higher    
0x18 (5.0 to 5.2)
GUID Guid;
5.0 to 5.2    
0x18
LONGLONG SequenceNumber;
6.0 and higher    
0x20
ULONG Spare0;
ULONG Spare1;
early 6.0    
union {
    ULONG Padding0 [2];
    SINGLE_LIST_ENTRY SlistEntry;
    WMI_BUFFER_HEADER *NextBuffer;
};
late 6.0 to 6.1 SlistEntry previously at 0x38;
NextBuffer previously at 0x38;
 
union {
    struct {
        ULONGLONG ClockType : 3;
        ULONGLONG Frequency : 61;
    };
    SINGLE_LIST_ENTRY SlistEntry;
    WMI_BUFFER_HEADER *NextBuffer;
};
6.2 and higher    
0x28
WMI_CLIENT_CONTEXT ClientContext;
5.0 to 5.2   5.0 known to clear
ETW_BUFFER_CONTEXT ClientContext;
6.0 and higher    
0x2C
ULONG Flags;
5.0 only   5.0 known to use
union {
    WMI_BUFFER_STATE State;
    ULONG Flags;
};
5.1 to 5.2    
union {
    ETW_BUFFER_STATE State;
    ULONG Flags;
};
6.0 only    
ETW_BUFFER_STATE State;
6.1 and higher    

For a WMI_BUFFER_HEADER in an ETL file, the BufferSize might as well be regarded as the offset in bytes to the next buffer in the file (or to the end of the file). The SavedOffset is similarly the number of bytes that are valid within the buffer, both of the WMI_BUFFER_HEADER and the events that follow.

The WMI_BUFFER_STATE is a structure of ULONG bit fields (see below). It is not known to be accessed as bit fields in version 5.0 and is here regarded as being not yet defined for that version. The ETW_BUFFER_STATE that supersedes it is an enumeration. Though the Flags member is retained for version 6.0, it will no longer have been useful for allowing the bit fields of the WMI_BUFFER_STATE to be manipulated together, and version 6.1 removed it.

End

The last 0x10 bytes, at offset 0x38, of the WMI_BUFFER_HEADER are an unnamed union in all versions, with numerous complications for orderly description:

Offset Definition Versions Remarks Notes
0x38
GUID InstanceGuid;
5.0 to 5.2    
ULONG Padding1 [4];
6.0 and higher    
0x38
LARGE_INTEGER StartTime;
6.0    
ETW_REF_CLOCK ReferenceTime;
6.1 and higher    
0x38
LIST_ENTRY Entry;
6.0 only previously at 0x18  
0x38
SINGLE_LIST_ENTRY SlistEntry;
early 6.0 only previously at 0x1C;
next at 0x20
 
0x38
struct {
    PVOID LoggerContext;
    SINGLE_LIST_ENTRY GlobalEntry;
};
5.0 to 5.2   5.0 known to use LoggerContext at 0x38
struct {
    WMI_BUFFER_HEADER *NextBuffer;
    SINGLE_LIST_ENTRY GlobalEntry;
};
early 6.0 NextBuffer next at 0x20  
struct {
    PVOID Padding2;
    SINGLE_LIST_ENTRY GlobalEntry;
};
late 6.0    
LIST_ENTRY GlobalEntry;
6.1 and higher    
0x38
struct {
    PVOID Pointer0;
    PVOID Pointer1;
};
late 6.0 and higher    

Client Context

The WMI_CLIENT_CONTEXT (before version 6.0) and ETW_BUFFER_CONTEXT that different versions have as a ClientContext at offset 0x28 were just different names for the one thing until version 6.2 widened the 8-bit ProcessorNumber to a 16-bit ProcessorIndex:

Offset Definition Versions Notes
0x00
UCHAR ProcessorNumber;
UCHAR Alignment;
5.0 to 6.1 5.0 known to use ProcessorNumber
union {
    struct {
        UCHAR ProcessorNumber;
        UCHAR Alignment;
    };
    USHORT ProcessorIndex;
};
6.2 and higher  
0x02
USHORT LoggerId;
5.0 and higher  

State

The WMI_BUFFER_STATE at offset 0x2C in versions before 6.0 is a 4-byte structure of ULONG bit fields:

Mask Definition Versions
0x00000001
ULONG Free : 1;
5.0 to 5.2
0x00000002
ULONG InUse : 1;
5.0 to 5.2
0x00000004
ULONG Flush : 1;
5.0 to 5.2
 
ULONG Unused : 29;
5.0 to 5.2

The ETW_BUFFER_STATE that supersedes the WMI_BUFFER_STATE in version 6.0 is an enumeration:

Value Name Versions
0 EtwBufferStateFree 6.0 and higher
1 EtwBufferStateGeneralLogging 6.0 and higher
2 EtwBufferStateCSwitch 6.0 and higher
3 EtwBufferStateFlush 6.0 and higher
4 EtwBufferStateMaximum 6.0 and higher

Buffer Flag and Type

For the BufferFlag that all versions 5.2 and higher have at offset 0x34, Microsoft’s names for the possible values (which are defined by macros and thus to not pass into symbol files as type information) are known from the semi-secret NTWMI.H:

Value Name Versions
0x0000 ETW_BUFFER_FLAG_NORMAL  
0x0001 ETW_BUFFER_FLAG_FLUSH_MARKER  
0x0002 ETW_BUFFER_FLAG_EVENTS_LOST  
0x0004 ETW_BUFFER_FLAG_BUFFER_LOST  
0x0008 ETW_BUFFER_FLAG_RTBACKUP_CORRUPT  
0x0010 ETW_BUFFER_FLAG_RTBACKUP  
0x0020 ETW_BUFFER_FLAG_PROC_INDEX  
0x0040 ETW_BUFFER_FLAG_COMPRESSED  

This is true also for the BufferType at offset 0x36:

Value Name Versions
0x0000 ETW_BUFFER_TYPE_GENERIC  
0x0001 ETW_BUFFER_TYPE_RUNDOWN  
0x0002 ETW_BUFFER_TYPE_CTX_SWAP  
0x0003 ETW_BUFFER_TYPE_REFTIME  
0x0004 ETW_BUFFER_TYPE_HEADER  
0x0005 ETW_BUFFER_TYPE_BATCHED  
0x0006 ETW_BUFFER_TYPE_EMPTY_MARKER  
0x0007 ETW_BUFFER_TYPE_DBG_INFO  
0x0008 ETW_BUFFER_TYPE_MAXIMUM