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.

WMI_BUFFER_HEADER

The WMI_BUFFER_HEADER structure (formally _WMI_BUFFER_HEADER) begins each trace 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 original and Version 1511 editions of the Windows Driver Kit (WDK) for Windows 10.

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 creation from and compatibility with the documented WNODE_HEADER is explicit.

Offset Definition Versions
0x00
union {
    WNODE_HEADER Wnode;
    struct {
        /* see below (Lists)  */
    };
    struct {
        /* see below (WNODE-compatible)  */
    };
};
5.0 to 5.2
union {
    WNODE_HEADER Wnode;
    struct {
        /*  see below (WNODE-compatible)  */
    };
};
6.0 only
/*  unstructured members, see below (WNODE-compatible)  */
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 (Tail)  */
};
5.0 and higher

For Microsoft’s names for the possible values of BufferFlag and BufferType, follow the links.

WNODE Header Overlay

In versions before 6.0, the WMI_BUFFER_HEADER begins with a WNODE_HEADER in union with two unnamed structures. Version 6.0 removed the first, and version 6.1 did away with the union by removing the WNODE_HEADER.

Lists

The first of the unnamed structures that overlays the WNODE_HEADER 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 and 0x20, for x86 and x64, respectively):

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. Versions 5.1 and 5.2 keep a single-linked list with an SLIST_HEADER, linking through SlistEntry. While no use of SlistEntry is known in version 5.0 and none of Entry in versions 5.1 and 5.2, It is here inferred that SlistEntry was not yet defined for version 5.0 and Entry was retained from version 5.0.

WNODE-Compatible

When the two list entries were moved beyond the WNODE_HEADER to offset 0x38 for version 6.0, the first unnamed structure in 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. Its members then became direct members of the WMI_BUFFER_HEADER:

Offset Definition Versions Remarks
0x00
LONG ReferenceCount;
5.0 to 5.2 next as LONG volatile at 0x0C
ULONG BufferSize;
6.0 and higher  
0x04
ULONG SavedOffset;
5.0 and higher  
0x08
ULONG CurrentOffset;
5.0 to 5.2  
ULONG volatile CurrentOffset;
6.0 and higher  
0x0C
ULONG UsePerfClock;
5.0 to 5.2  
LONG volatile ReferenceCount;
6.0 and higher previously LONG at 0x00
0x10
LARGE_INTEGER TimeStamp;
5.0 to 5.2  
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  
ETW_BUFFER_CONTEXT ClientContext;
6.0 and higher  
0x2C
ULONG Flags;
5.0 only  
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. 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 removes it.

Tail

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
0x38
GUID InstanceGuid;
5.0 to 5.2  
ULONG Padding1 [4];
6.0 and higher  
0x38
LARGE_INTEGER StartTime;
6.0 only  
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 (x86) and 0x20 (x64);
next at 0x20
0x38
struct {
    PVOID LoggerContext;
    SINGLE_LIST_ENTRY GlobalEntry;
};
5.0 to 5.2  
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