Geoff Chappell, Software Analyst
SKETCH OF HOW RESEARCH MIGHT CONTINUE AND RESULTS BE PRESENTED
When given 0x0B as its FunctionCode argument, the NtTraceControl function connects a real-time consumer to a logger. Microsoft’s name for this function code is not known. This note deals only with the function’s behaviour that is specific to this function code. The function’s general behaviour is here taken as assumed knowledge.
A fixed-size context is expected as both input and output. Microsoft’s name for this real-time connection context is not known (though an insufficiently substantial hint is that another structure’s pointer to this structure is named RealtimeConnectContext). It is the same in both 32-bit and 64-bit Windows but has changed between versions, notably to be reworked significantly for Windows 7. The following changes of size are known.
Versions | Size |
---|---|
6.0 | 0x20 |
6.1 to 6.2 | 0x50 |
6.3 and higher | 0x60 |
In version 6.1 and higher, most of the structure provides input for creation of an EtwConsumer object. Internally this is an ETW_REALTIME_CONSUMER structure. Type information for this is available in public symbol files and it seems highly likely that Microsoft uses the same names and types in both structures for members that correspond closely. Where pointers are padded to 64 bits so that the kernel deals with one format for both 32-bit and 64-bit callers, type information that Microsoft has disclosed for other structures that are involved with NtTraceControl, e.g., WMI_LOGGER_INFORMATION, suggests a convention that Microsoft perhaps uses for this structure too.
Offset | Definition | Versions | Remarks |
---|---|---|---|
0x00 |
ULONG LoggerId; |
6.0 and higher | input |
0x04 |
ULONG ReservedBufferSpaceSize; |
6.1 and higher | input |
0x08 |
union { UCHAR *ReservedBufferSpace; ULONG64 ReservedBufferSpace64; }; |
6.1 and higher | input |
0x10 | a 64-bit allowance for the address of a buffer to use for the ReservedBufferSpaceBitMap | 6.1 and higher | input |
0x18 |
union { HANDLE DisconnectEvent; ULONG64 DisconnectEvent64; }; |
6.1 and higher | input |
0x20 |
union { HANDLE DataAvailableEvent; ULONG64 DataAvailableEvent64; }; |
6.1 and higher | input |
0x28 |
union { SINGLE_LIST_ENTRY *UserBufferListHead; ULONG64 UserBufferListHead64; }; |
6.1 and higher | input |
0x30 |
union { ULONG *UserBufferCount; ULONG64 UserBufferCount64; }; |
6.1 and higher | input |
0x38 |
union { ULONG *EventsLostCount; ULONG64 EventsLostCount64; }; |
6.3 and higher | input |
0x40 |
union { ULONG *BuffersLostCount; ULONG64 BuffersLostCount; }; |
6.3 and higher | input |
0x04 (6.0) | a 32-bit consumer ID | 6.0 only | output |
0x08 (6.0); 0x38 (6.1); 0x48 |
a 64-bit allowance for a HANDLE to a pipe | 6.0 only | output |
a 64-bit allowance for a HANDLE to the EtwConsumer object | 6.1 and higher | output | |
0x10 (6.0); 0x40 (6.1); 0x50 |
an ETW_REF_CLOCK | 6.0 and higher | output |
Version 6.0 defines no object type for real-time event consumers and therefore has a very different implementation. Each connection of a real-time consumer to a logger is represented not by a handle but by a sequence number. When tracing events, the kernel does not have direct access to the user-mode memory supplied by the consumer but instead writes through a pipe.
If the input and output buffers are not both exactly the expected size, the function returns STATUS_INVALID_PARAMETER.
TO BE DONE?