Geoff Chappell, Software Analyst
PLACEHOLDER FOR WORK THAT MAY NEVER BE DONE - PREVIEW ONLY
When given 0x0F as its FunctionCode argument, the NtTraceControl function tells the kernel about a user-mode registration of an event provider. 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 provider is represented by a GUID and can have any number of registrations. For a user-mode registration, the effect really is like opening a provider in that it produces an Object Manager handle to the underlying registration object. As well as opening this handle for the user-mode caller, the function also produces information. In all versions, this includes to describe a tracing session, if any, that has started in anticipation of the provider’s registration. Starting with version 6.1, the output can continue with a description of a schematized event filter that is already known for the GUID.
The function returns STATUS_INVALID_PARAMETER if any of the following are true:
Microsoft’s name for the 0xA0 bytes of fixed-size input and output is not known. Indeed, it is not known that Microsoft defines them as one structure. They certainly are interpreted in parts, not that Microsoft’s names are known for these either. A 0x28-byte header describes the event provider, both to tell the kernel about the provider and to return the handle that the kernel creates for the registration.
Offset | Definition | Versions | Remarks |
---|---|---|---|
0x00 | the provider’s GUID | 6.0 and higher | input |
0x10 | an ETW_NOTIFICATION_TYPE | 6.0 and higher | input |
0x14 | the process’s 16-bit index for this registration | 6.0 and higher | input |
0x18 | a 64-bit allowance for a HANDLE to the provider’s ETW_REG_ENTRY | 6.0 and higher | output |
0x20 | apparently reserved for future definition | 6.0 to 6.2 | |
a 64-bit allowance for the address of the provider’s callback function | 6.3 and higher | input |
Incidentally, that the kernel is nowadays told of the provider’s user-mode callback function is not because the kernel has any role in the calling back. It is instead so that the kernel can identify the calling module. This matters in version 6.3 and higher because tracing sessions can get system-defined events written to them to record which providers were enabled for the session.
Though the remaining 0x78 bytes are expected on input, they are used only for output. Moreover, though the header looks to be particular to this function code, the remaining 0x78 bytes (and any variable-size data that follows) are shared with function code 0x11 to describe how a provider is enabled for a tracing session. In this case, the tracing session that’s described as output for function code 0x0F is the logger for which the provider was most recently enabled. Microsoft’s name for this structure is not known. Relevant routines refer to it as an enable notification: the name ETW_ENABLE_NOTIFICATION_PACKET would follow a pattern that might be induced from the known name for another structure that begins with an ETW_NOTIFICATION_HEADER, but is too much of a guess to commit to here.
Offset | Definition | Versions | Remarks |
---|---|---|---|
0x00 | an ETW_NOTIFICATION_HEADER | 6.0 and higher | NotificationSize for output (but see note after table) |
0x48 | a TRACE_ENABLE_INFO | 6.0 and higher | output |
0x68 | a TRACE_ENABLE_CONTEXT | 6.0 and higher | output |
0x70 | 0 to disable events; 1 to enable events |
6.0 and higher | output |
0x74 | apparently reserved for future definition | 6.0 only | |
indicator of what data follows | 6.1 and higher | output |
The ETW_NOTIFICATION_HEADER appears to be just a formality—literally from sharing the form of data that does matter for function code 0x11. For function code 0x0F, the version 6.0 kernel ignores this header completely and in no version does the kernel set anything in this header other than the NotificationSize. Even then, versions 6.1 and 6.2 set it only if following with variable-size data. It’s set always on success in versions 6.3 and higher, but to the size of the whole output when surely what would be expected is the size just from the notification header onwards. (NTDLL, however, expects nothing.)
What can follow this fixed-size data is a description of the schematized event filters that yet apply to the provider. The format for this description is version-dependent. In versions 6.1 and 6.2, it is a sequence of EVENT_FILTER_HEADER structures, each introducing variable-size data. The header’s Size member is the total size, in bytes, of the header and data. Its NextOffset member is the possibly larger number of bytes from the header to the next header, or is zero in the last header. In version 6.3 and higher, there is first an EVENT_FILTER_DESCRIPTOR. Its Ptr member is the number of bytes from the notification header to the EVENT_FILTER_HEADER sequence. Its Size is that of the sequence. This change of format also affects the indicator at offset 0x74. In versions 6.1 and 6.2, this is 0x80000000, which may be intended as the filter type, specifically EVENT_FILTER_TYPE_SCHEMATIZED. In later versions, the indicator is boolean and the filter type is explicitly in the Type member of the EVENT_FILTER_DESCRIPTOR.
This function code is expressly not for registering the security provider. If the provider’s GUID is {54849625-5478-4994-A5BA-3E3B0328C30D}, which Microsoft represents symbolically as SecurityProviderGuid, the function fails, returning STATUS_ACCESS_DENIED.
TO BE DONE