Geoff Chappell - Software Analyst
SKETCH OF HOW RESEARCH MIGHT CONTINUE AND RESULTS BE PRESENTED
An event provider calls this function to write an event.
ULONG EtwEventWrite ( REGHANDLE RegHandle, EVENT_DESCRIPTOR const *EventDescriptor, ULONG UserDataCount, EVENT_DATA_DESCRIPTOR *UserData);
The required RegHandle argument identifies which registration of an event provider is writing the event.
The required EventDescriptor argument tells which event is to be written.
The optional UserDataCount and UserData arguments are respectively the element count and address of an array of structures that supply event-specific data to record with the event.
The function returns zero for success, else a Win32 error code.
The EtwEventWrite function is exported by name from NTDLL.DLL in version 6.0 and higher. Well-behaved software does not call this function but instead calls EventWrite, which is exported by name from ADVAPI32.DLL in version 6.0 and higher as a forward to EtwEventWrite.
As with many NTDLL exports, Microsoft does not document EtwEventWrite. The higher-level ADVAPI32 function EventWrite is documented.
A C-language declaration of EtwEventWrite is published by Microsoft in a file named NTETW.H in the Enterprise edition of the Windows Driver Kit (WDK) for Windows 10 Version 1511.
Or so things stood. Apparently too late for a downloadable package of documentation in 2017 but now dated to 2018 online, Microsoft documented EtwEventWrite among some Developer Notes. It is there said explicitly to be internal. Among the Requirements is the Header named ntetw.h which Microsoft is not known to have published except in the one case above.
If EventDescriptor is NULL, the function has no event to write: it returns ERROR_INVALID_PARAMETER.
If the RegHandle is not valid, the function has no event provider to write an event from: it returns ERROR_INVALID_HANDLE. A valid REGHANDLE is produced by the EtwEventRegister function and is made invalid by EtwEventUnregister.
Event providers send events into the ETW mechanism. Tracing sessions receive them. Each tracing session chooses which event providers they want events from. For each event provider that they so enable, a tracing session may also specify a level and keyword to match against events from that provider. In later versions, they may also specify properties that affect the matching. If the Level and Keyword in at EventDescriptor match this specification, then the event is said to be enabled for the session.
If the event is enabled for any private tracing session, the function writes the event to the user-mode tracing buffers of each such session for which the event is enabled. Failure to write to any such session is failure for the function.
If the event is enabled for any tracing session that is managed by the kernel, the function sends the event to the kernel for distribution to each tracing session for which the event is enabled. Inputs and defaults are packaged as an EVENT_HEADER for NtTraceEvent with ETW_NT_FLAGS_TRACE_EVENT as its Flags argument. Failure from the kernel is failure for the function.