A classic event provider calls this function from within a notification callback to retrieve a handle to the event tracing session that is the subject of the notification.


TRACEHANDLE EtwGetTraceLoggerHandle (PVOID Buffer);


The Buffer is the address of a WNODE_HEADER that the provider has received as the callback routine’s Buffer argument. The provider will have set the callback routine as the RequestAddress argument when registering through the EtwRegisterTraceGuids function.

Return Value

The function returns a 64-bit trace handle for success, else INVALID_HANDLE_VALUE (cast to the TRACEHANDLE type).

On failure, a non-zero Win32 error code will have been set as the thread’s last error and may be retrieved through such functions as GetLastError.


The EtwGetTraceLoggerHandle function is exported by name from NTDLL in version 5.2 and higher. It has higher-level availability as a forward from the ADVAPI32 export GetTraceLoggerHandle in its versions 5.2 and higher.

This note is concerned only with the function as implemented in NTDLL version 5.2 and higher. The earlier implementations in ADVAPI32 versions 5.0 and 5.1 are left for separate treatment some other time.

Documentation Status

The EtwGetTraceLoggerHandle function is not documented. Well-behaved user-mode software would call the documented GetTraceLoggerHandle function instead. Note, however, that a strict reading of Microsoft’s documentation prohibits calling the higher-level function, but not the lower-level, from a DllMain routine. For some hint that Microsoft has experience either of or closely related to this point, see the cautionary note about the loader lock in Microsoft’s documentation of the WMIDPREQUEST callback function.


This function lets the event provider extract the TRACEHANDLE from the HistoricalContext member of the WNODE_HEADER without having to depend on being given specifically a WNODE_HEADER. NTDLL creates this structure expressly for the callback routine. The structure does not outlive the routine. It also does not continue with more data. Indeed, it contains little that is meaningful and is best treated as opaque.

That said, while talking of implementation details, note that in the expected circumstances, i.e., during the callback routine, this TRACEHANDLE as put in the WNODE_HEADER is actually a TRACE_ENABLE_CONTEXT and therefore contains the logger ID and the logger’s enable flags and level. It is arguably only for learning these last two that the provider needs the handle—as if this function’s intended, and perhaps only, use is as preparation for calling the EtwGetTraceEnableFlags and EtwGetTraceEnableLevel functions.

If Buffer is NULL, the function fails, with ERROR_INVALID_PARAMETER as its error code. The function also fails, but with ERROR_BAD_LENGTH as its error code, if the BufferSize member of the presumed WNODE_HEADER is not at least the size of a WNODE_HEADER.

As always for a TRACEHANDLE, the low 16 bits are the logger ID. Except that 0xFFFF conventionally represents the NT Kernel Logger, the logger ID is a 0-based index into the kernel’s list of loggers and must be less than MAXLOGGERS (64 in the applicable versions, at least to the original Windows 10), else the function fails, with ERROR_INVALID_HANDLE as its error code.