DRAFT: Take more than your usual care.

TraceMessage

This function writes a message event to an event tracing session from user mode.

Declaration

ULONG
TraceMessage (
    TRACEHANDLE SessionHandle,
    ULONG MessageFlags,
    GUID *MessageGuid,
    USHORT MessageNumber, 
    ...);

Parameters

The required SessionHandle selects the event tracing session, also called a logger, to which the event is to be written.

The MessageFlags argument directs the logger to add items to the event in addition to the message arguments. The following bits are recognised:

Value Name Meaning
0x00000001 TRACE_MESSAGE_SEQUENCE include sequence number as event-specific data
0x00000002 TRACE_MESSAGE_GUID include GUID as event-specific data
0x00000004 TRACE_MESSAGE_COMPONENTID include component ID as event-specific data
0x00000008 TRACE_MESSAGE_TIMESTAMP include time stamp as event-specific data
0x00000010 TRACE_MESSAGE_PERFORMANCE_TIMESTAMP use performance counter for time stamp
0x00000020 TRACE_MESSAGE_SYSTEMINFO include thread and process IDs as event-specific data

The optional MessageGuid argument supplies either a component ID or a GUID to add to the event as an identifier.

The MessageNumber argument is the primary identifier of the event. The plain intention is that events that have the same MessageNumber, perhaps in combination with the identifier from MessageGuid, are recurrences of the one event and have the same interpretation of message arguments.

The remaining arguments, if any, present the message arguments. Successive pairs of function arguments each provide respectively the address and size of one message argument. This sequence ends with a function argument that would represent a NULL address. The concatenation of these message arguments becomes event-specific data to add to the event. The function does not interpret the message arguments.

Return Value

The function returns zero for success, else a Win32 error code.

The return value is also set as the thread’s last error, such that it can be retrieved by calling GetLastError.

Availability

The TraceMessage function is exported by name from ADVAPI32 in version 5.1 and higher. Starting with version 5.2, it is merely a forward to the NTDLL export EtwTraceMessage in its versions 5.2 and higher. For the NTDLL implementation, which behaves differently in ways that may be significant, follow the link: this note is concerned only with the function as implemented in ADVAPI32.

Usage

Given that very similar functionality can be arranged in version 5.0 through the TraceEvent function with an MOF_FIELD array for the message arguments, the TraceMessage function might be just a development of TraceEvent for programming convenience. It is more, with distinctly new functionality in one important sense: events that are written through TraceMessage get a distinctive type of trace header, a MESSAGE_TRACE_HEADER, in contrast to the EVENT_TRACE_HEADER.

This new functionality looks to have been devised as special support for Windows Pre-Processor (WPP) Tracing. This is diagnostic magic that turns drivers, services, DLLs and other low-level program code into event providers that write events for seemingly no more trouble than calling a programmer-defined function in the familiar style of printf from the C Run-Time library. Each source file is assigned a MessageGuid and the trace statements within a source file are each assigned a MessageNumber. The format strings for the trace statements go to the PDB file (with the happy side-effect that the tracing neither bloats the executable nor helps reverse engineers). Interpretation of the message arguments for each combination of MessageGuid and MessageNumber is done by an event consumer that has the PDB file.

Documentation Status

The TraceMessage function is documented.

Behaviour

Broadly, the TraceMessage function creates an event from the function’s inputs and sends it into whichever of the kernel-mode or user-mode event tracing machinery is appropriate for the session.

The only difference between TraceMessage and TraceMessageVa is of form. Both assemble the message arguments from an array. The former has the array on the stack as function arguments. The latter receives the array’s address as one function argument.