CURRENT WORK ITEM - PREVIEW ONLY

WMI_LOGGER_INFORMATION

The WMI_LOGGER_INFORMATION structure describes an event logger across the NtTraceControl interface between user mode and kernel mode. It is exchanged when starting, stopping, querying, updating or flushing a logger. It thus provides the input for what the kernel builds as the WMI_LOGGER_CONTEXT and is the means of returning information about a logger.

To the documented user-mode functions such as StartTrace and ControlTrace that go through NtTraceControl to reach the kernel-mode implementation for these operations, the WMI_LOGGER_INFORMATION is a slight repackaging of the documented EVENT_TRACE_PROPERTIES. Indeed, the user-mode perspective is that EVENT_TRACE_PROPERTIES is the external structure for these functions’ descriptions of loggers and WMI_LOGGER_INFORMATION is the internal representation, not only for reaching the kernel but also for private loggers which are implemented almost entirely in user mode.

This internal representation in user mode is as old as version 5.0, and so it is in kernel mode too for although versions before 6.0 do not have NtTraceControl, they do have the WMI_LOGGER_INFORMATION as the input and output for Device I/O Control requests that are sent to the kernel’s built-in WMI support device.

Versions 5.1 and 5.2 also have the WMI_LOGGER_INFORMATION as input and output for the undocumented kernel exports WmiStartTrace, WmiStopTrace, WmiQueryTrace, WmiUpdateTrace and WmiFlushTrace. These do not survive to version 6.0, but the WMI_LOGGER_INFORMATION has an internal kernel-mode use to support tracing sessions that the kernel itself starts from AutoLogger settings in the registry.

Documentation Status

The WMI_LOGGER_INFORMATION structure is not documented, but Microsoft has published a C-language definition 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.

Layout

Though the WMI_LOGGER_INFORMATION is shared between kernel and user modes, which would ordinarily encourage its stability, it took some time to settle. The following changes of size are known:

Version Size
5.0 0x88
5.1 0xA8
5.2 and higher 0xB0

The WMI_LOGGER_INFORMATION is the same in 32-bit and 64-bit Windows because from as early as version 5.1, members that are pointers or handles or that contain pointers are defined in union with artificial members that widen the 32-bit definition to the 64-bit. Other members are defined in unions because the different branches of the union are intended for different operations, or because one branch is for input and the other for output. It is not yet certain when some of this differentiation started.

Offset Definition Versions
0x00
WNODE_HEADER Wnode;
5.0 and higher
0x30
ULONG BufferSize;
5.0 and higher
0x34
ULONG MinimumBuffers;
5.0 and higher
0x38
ULONG MaximumBuffers;
5.0 and higher
0x3C
ULONG MaximumFileSize;
5.0 and higher
0x40
ULONG LogFileMode;
5.0 and higher
0x44
ULONG FlushTimer;
5.0 and higher
0x48
ULONG EnableFlags;
5.0 and higher
0x4C
LONG AgeLimit;
 
union {
    LONG AgeLimit;
    LONG FlushThreshold;
};
6.1 and higher
0x50
ULONG Wow;
5.2 and higher
0x50 (5.0 to 5.1);
0x58
HANDLE LogFileHandle;
5.0 only
union {
    HANDLE LogFileHandle;
    ULONG64 LogFileHandle64;
};
5.1 and higher
0x54 (5.0);
0x58 (5.1);
0x60
ULONG NumberOfBuffers;
 
union {
    ULONG NumberOfBuffers;
    ULONG InstanceCount;
};
 
0x58 (5.0);
0x5C (5.1);
0x64
ULONG FreeBuffers;
 
union {
    ULONG FreeBuffers;
    ULONG InstanceId;
};
 
0x5C (5.0);
0x60 (5.1);
0x68
union {
    ULONG EventsLost;
    ULONG NumberOfProcessors;
};
5.0 and higher
0x60 (5.0);
0x64 (5.1);
0x6C
ULONG BuffersWritten;
5.0 and higher
0x64 (5.0);
0x68 (5.1);
0x70
ULONG LogBuffersLost;
5.0 to 5.2
union {
    ULONG LogBuffersLost;
    ULONG Flags;
};
6.0 and higher
0x68 (5.0);
0x6C (5.1);
0x74
ULONG RealTimeBuffersLost;
5.0 and higher
0x6C (5.0);
0x70 (5.1);
0x78
HANDLE LoggerThreadId;
5.0 only
union {
    HANDLE LoggerThreadId;
    ULONG64 LoggerThreadId64;
};
5.1 and higher
0x70 (5.0);
0x78 (5.1);
0x80
UNICODE_STRING LogFileName;
5.0 only
union {
    UNICODE_STRING LogFileName;
    UNICODE_STRING64 LogFileName64;
};
5.1 and higher
0x78 (5.0);
0x88 (5.1);
0x90
UNICODE_STRING LoggerName;
5.0
union {
    UNICODE_STRING LoggerName;
    UNICODE_STRING64 LoggerName64;
};
5.1 and higher
0x80 (5.0);
0x98 (5.1);
0xA0 (5.2)
unknown PVOID 5.0 only
unknown PVOID and ULONG64 in union 5.1 to 5.2
0xA0
ULONG RealTimeConsumerCount;
6.0 and higher
0xA4
ULONG SpareUlong;
6.0 and higher
0xA0 (5.1);
0xA8
union {
    PVOID LoggerExtension;
    ULONG64 LoggerExtension64;
};
5.1 and higher

The BufferSize is in kilobytes.

The LogFileMode is a set of bit flags. These are subject to many constraints, both among themselves and in common with other members.

Though the AgeLimit remains formally defined in version 6.0 and higher, it is ignored in version 6.0 and is replaced by the FlushThreshold in version 6.1.

The LogFileHandle is required input except if either of the following are set in the LogFileMode:

The NumberOfBuffers has an undocumented meaning on input in Windows Vista and higher. It is how an AutoLogger session communicates what has been set for its FileCounter value.

The Flags are something of a mystery even with Microsoft’s disclosure of NTWMI.H. This header file’s definition of the structure shows the Flags, of course, but not what flags are defined for it. The 0x01 and 0x02 bits on input become the Persistent and AutoLogger bits of the Flags in the WMI_LOGGER_CONTEXT.

The unknown pointer near the end of the structure for versions before 6.0 tells the kernel what to expect in the Event Trace Log (ETL) file. These versions let the user-mode caller create the log file, write its first buffer, and pass the file handle as LogFileHandle on input. Every ETL file begins with a WMI_BUFFER_HEADER, a SYSTEM_TRACE_HEADER and a TRACE_LOGFILE_HEADER. The unknown pointer provides the kernel with the WNODE_HEADER from the WMI_BUFFER_HEADER and with the whole of the fixed-size TRACE_LOGFILE_HEADER. The kernel saves them in paged memory, keeping the address as the LoggerHeader member of the WMI_LOGGER_CONTEXT. In these versions, the WMI_BUFFER_HEADER begins with a WNODE_HEADER, which must match what’s saved. In the TRACE_LOGFILE_HEADER, the first 0x38 bytes must match.