Most events are likely to be of a fixed length. An event consists of the event header (specified by the event tracing API) and can optionally append its own data. Obviously, appending custom data makes it easier to record and analyze characteristics about an event. Let’s define a fixed length event with some custom data: typedef struct _FixedLenData { DWORD dwProcessID; DWORD dwThreadID; DWORD dwMoreInfo; } *PFIXED_LEN_DATA, FIXED_LEN_DATA; As can be seen, the event’s custom data consists of three additional fields. We haven’t intended any of the values of the fields to be significant, just that they are DWORDs and conveniently represent fixed length fields. In your applications, the fixed length events would provide more useful information. The next step is to append the custom data to the event header structure. The following structure shows how this is achieved (in bold text). typedef struct _FixedDataLenEvent { EVENT_TRACE_HEADER Header; FIXED_LEN_DATA Data; } *PEVENT_FIXED_LEN, EVENT_FIXED_LEN; As was mentioned earlier, events are encapsulated in classes derived from either CBaseEvent or CVariableLengthBaseEvent. Fixed length events are derived from the class, CBaseEvent. Let’s take a quick tour of what a portion of the template class looks like. The TEventData template parameter is the structure of the event. The EventGuid template parameter is the event’s GUID. template <CLASS EventGuid, LPCGUID TEventData,> class CBaseEvent { protected: TEventData m_data; public: CBaseEvent() { ZeroMemory(&m_data, sizeof(TEventData)); m_data.Header.Size = sizeof(TEventData); m_data.Header.Guid = *EventGuid; m_data.Header.Flags = WNODE_FLAG_TRACED_GUID; } .. .. ... ... . . }; Let’s have a look at the CEventFixedLen class which was used earlier in SomeFunction and uses the event structure, EVENT_FIXED_LEN. Notice how the event’s custom data is setup. class CEventFixedLen: public CBaseEvent<EVENT_FIXED_LEN, &MY_EVENTCLASS> { public: CEventFixedLen(DWORD dwMoreInfo) { // Simply set your event data m_data.Data.dwProcessID = GetCurrentProcessId(); m_data.Data.dwThreadID = GetCurrentThreadId(); m_data.Data.dwMoreInfo = dwMoreInfo; // If you need to, you can set specific values in the event header // through m_data.Header. One such example would be to set the // version of the event... // Don't forget to set the event type SetEventType(EVENT_TRACE_TYPE_INFO); // Set text equivelent of the event for verbose debug output SetTextEvent("Process ID = 0x%X, Thread ID = 0x%X, Info = %d\n", m_data.Data.dwProcessID, m_data.Data.dwThreadID, dwMoreInfo); } }; The first task is to setup the event’s custom data. Notice that data for the event is provided using multiple sources; the constructor’s parameter list and some system APIs. Just pointing out that data for an event does not necessarily have to come from the constructor’s parameter list. Although, we expect the parameter list will be the most common method of supplying event custom data. In the previous code sample, both dwProcessID and dwThreadID are set with data provided using the appropriate APIs. The dwMoreInfo field is set with data provided by the parameter list. All fixed length event classes must specify their event type using, SetEventType. The previous code sample specifies EVENT_TRACE_TYPE_INFO which is a standard event tracing event type. Table 13.5 in Chapter 13 lists the standard event types. All event classes (fixed and variable length) can expose a verbose form of output by setting some text with SetTextEvent. When an event is fired and some text has been provided, the text is output to the debug output using, OutputDebugString. If you wish, you can alter the CTraceEvent class to output the text elsewhere. Finally, as you saw earlier, the CEventFixedLen class is used to fire an event using the ET_EVENT macro. ET_EVENT(CEventFixedLen(12345)); |
Contact Me | Developing WMI Solutions | Gwyn Cole's Developer Blog | Legal |
© 2003 Content by Gwyn Cole. All rights reserved. |