Geoff Chappell, Software Analyst
CURRENT WORK ITEM - PREVIEW ONLY
This function registers a kernel-mode event provider.
NTSTATUS NTKERNELAPI EtwRegister ( LPCGUID ProviderId, PETWENABLECALLBACK EnableCallback, PVOID CallbackContext, REGHANDLE *RegHandle);
The ProviderId argument is the address of a GUID that represents the event provider.
The EnableCallback argument is the address of a routine that is to be called back whenever a tracing session interacts with the provider. This argument can be NULL to mean that the caller does not want to be called back.
The CallbackContext argument is a caller-defined context that is to be passed back to the caller as one of the arguments of the callback routine. This argument is valid only if a callback routine is supplied.
The RegHandle argument is the address of a 64-bit variable that is to receive a registration handle to the provider. The caller may use this as an argument when calling other ETW functions, notably to write events through this provider, and ultimately to call EtwUnregister.
The function returns STATUS_SUCCESS if successful, else a negative error code.
The callback routine has the prototype
VOID EnableCallback ( LPCGUID SourceId, ULONG ControlCode, // originally named IsEnabled UCHAR Level, ULONGLONG MatchAnyKeyword, ULONGLONG MatchAllKeyword, EVENT_FILTER_DESCRIPTOR *FilterData, PVOID CallbackContext);
Note that the callback routine can be called not just back, i.e., after EtwRegister returns, but within. This happens when the provider was already enabled in one or more tracing sessions. The SourceId in this case is null, the ControlCode is EVENT_CONTROL_CODE_ENABLE_PROVIDER and the Level, MatchAnyKeyword, MatchAllKeyword and FilterData arguments are aggregated over the tracing sessions.
The EtwRegister is exported by name from the kernel in version 6.0 and higher. It is documented from its start, i.e., as early as the Windows Driver Kit (WDK) for Windows Vista.
The EtwRegister function does much the same for kernel-mode event providers as is done for user-mode event providers by the NTDLL function EtwEventRegister (which is typically accessed as the ADVAPI32 function EventRegister). That said, this function is not the kernel-mode core of the user-mode functionality. The coding is largely separate and there are differences in behaviour.
A key point to understand is that an event provider is an abstracted entity for writing a set of events. Although it will often be that an event provider is implemented wholly in one executable module, this is only the simplest scheme. Multiple modules, both in kernel and user mode, can each write events as if from the one event provider. All tell the kernel of their intention by calling EtwRegister (or corresponding user-mode function) with the same GUID as the ProviderId argument. Each may supply their own EnableCallback and CallbackContext. Each receives its own registration handle.
Another key point is that event providers are abstracted enough to exist before any module has yet registered for writing events through the provider. This is a vital provision for a tracing session (or sessions) to receive events that record the applicable modules' initialisation. An implication is that an event provider can be known to the kernel either from being registered (for an intended writing of events) or from being enabled (with the intention of reading events).
Because of these two points together, the function works with two important structures. It first ensures the existence of an ETW_GUID_ENTRY structure that represents the provider. If none exists already, the function creates one. Then it creates an ETW_REG_ENTRY for this registration. This is the structure that the caller will subsequently access through the returned registration handle. Originally, this handle was an index into a table. Starting with Windows 8, it is simply the address of the ETW_REG_ENTRY.
The implementation details that (will) follow are from analysis up to and including the original release of Window 10. Beware that the later releases rework some of the details non-trivially for the increasing role of silos. It is not impossible that the presentation of these details even for earlier versions will not stay here.
TO BE DONE