Geoff Chappell, Software Analyst
DRAFT: Take more than your usual care.
This function writes a message event to an event tracing session from user mode.
ULONG TraceMessage ( TRACEHANDLE SessionHandle, ULONG MessageFlags, GUID *MessageGuid, USHORT MessageNumber, ...);
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.
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.
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.
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.
The TraceMessage function is documented.
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.