You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
7.5 KiB
306 lines
7.5 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
tracedp.c
|
|
|
|
Abstract:
|
|
|
|
Sample trace provider program.
|
|
|
|
--*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <windows.h>
|
|
#include <shellapi.h>
|
|
#include <tchar.h>
|
|
#include <wmistr.h>
|
|
|
|
#include <guiddef.h>
|
|
#include <evntrace.h>
|
|
|
|
#define DEFAULT_EVENTS 5000
|
|
#define MAXSTR 1024
|
|
|
|
TRACEHANDLE LoggerHandle;
|
|
|
|
// Control GUID for this provider.
|
|
GUID ControlGuid =
|
|
{0xd58c126f, 0xb309, 0x11d1, 0x96, 0x9e, 0x00, 0x00, 0xf8, 0x75, 0xa5, 0xbc};
|
|
|
|
|
|
// Only one transaction GUID will be registered for this provider.
|
|
GUID TransactionGuid =
|
|
{0xce5b1020, 0x8ea9, 0x11d0, 0xa4, 0xec, 0x00, 0xa0, 0xc9, 0x06, 0x29, 0x10};
|
|
// Array for transaction GUID registration.
|
|
TRACE_GUID_REGISTRATION TraceGuidReg[] =
|
|
{
|
|
{ (LPGUID)&TransactionGuid,
|
|
NULL
|
|
}
|
|
};
|
|
|
|
// User event layout: one ULONG.
|
|
typedef struct _USER_EVENT {
|
|
EVENT_TRACE_HEADER Header;
|
|
ULONG EventInfo;
|
|
} USER_EVENT, *PUSER_EVENT;
|
|
|
|
// Registration handle.
|
|
TRACEHANDLE RegistrationHandle;
|
|
// Trace on/off switch, level, and flag.
|
|
BOOLEAN TraceOnFlag;
|
|
ULONG EnableLevel = 0;
|
|
ULONG EnableFlags = 0;
|
|
|
|
// Number of events to be logged. The actual number can be less if disabled early.
|
|
ULONG MaxEvents = DEFAULT_EVENTS;
|
|
// To keep track of events logged.
|
|
ULONG EventCount = 0;
|
|
|
|
// ControlCallback function for enable/disable.
|
|
ULONG
|
|
ControlCallback(
|
|
IN WMIDPREQUESTCODE RequestCode,
|
|
IN PVOID Context,
|
|
IN OUT ULONG *InOutBufferSize,
|
|
IN OUT PVOID Buffer
|
|
);
|
|
|
|
// Main work to be traced is done here.
|
|
void
|
|
DoWork();
|
|
|
|
__cdecl main(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
main() routine.
|
|
|
|
Arguments:
|
|
|
|
Usage: TraceDp [number of events]
|
|
[number of events] default is 5000
|
|
|
|
Return Value:
|
|
|
|
Error Code defined in winerror.h : If the function succeeds,
|
|
it returns ERROR_SUCCESS (== 0).
|
|
|
|
--*/
|
|
{
|
|
ULONG Status, i;
|
|
LPTSTR *targv, *utargv = NULL;
|
|
|
|
TraceOnFlag = FALSE;
|
|
|
|
#ifdef UNICODE
|
|
if ((targv = CommandLineToArgvW(
|
|
GetCommandLineW(), // pointer to a command-line string
|
|
&argc // receives the argument count
|
|
)) == NULL)
|
|
{
|
|
return (GetLastError());
|
|
};
|
|
utargv = targv;
|
|
#else
|
|
targv = argv;
|
|
#endif
|
|
|
|
// process command line arguments to override defaults
|
|
if (argc == 2) {
|
|
targv ++;
|
|
if (**targv >= _T('0') && **targv <= _T('9')) {
|
|
MaxEvents = _ttoi(targv[0]);
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("/?")) || !_tcsicmp(targv[0], _T("-?"))) {
|
|
printf("Usage: TraceDp [number of events]\n");
|
|
printf("\t[number of events] default is 5000\n");
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
// Free temporary argument buffer.
|
|
if (utargv != NULL) {
|
|
GlobalFree(utargv);
|
|
}
|
|
|
|
// Event provider registration.
|
|
Status = RegisterTraceGuids(
|
|
(WMIDPREQUEST)ControlCallback, // callback function
|
|
0,
|
|
&ControlGuid,
|
|
1,
|
|
TraceGuidReg,
|
|
NULL,
|
|
NULL,
|
|
&RegistrationHandle
|
|
);
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
_tprintf(_T("Trace registration failed. Status=%d\n"), Status);
|
|
return(Status);
|
|
}
|
|
else {
|
|
_tprintf(_T("Trace registered successfully\n"));
|
|
}
|
|
|
|
_tprintf(_T("Testing Logger with %d events\n"),
|
|
MaxEvents);
|
|
|
|
// Sleep until enabled by a trace controller. In this sample, we wait to be
|
|
// enabled for tracing. However, normal applications should continue and log
|
|
// events when enabled later on.
|
|
while (!TraceOnFlag) {
|
|
_sleep(1000);
|
|
}
|
|
|
|
// Do the work while logging events. We trace two events (START and END) for
|
|
// each call to DoWork.
|
|
for (i = 0; i < MaxEvents / 2; i++) {
|
|
DoWork();
|
|
}
|
|
|
|
// Unregister.
|
|
UnregisterTraceGuids(RegistrationHandle);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
ULONG
|
|
ControlCallback(
|
|
IN WMIDPREQUESTCODE RequestCode,
|
|
IN PVOID Context,
|
|
IN OUT ULONG *InOutBufferSize,
|
|
IN OUT PVOID Buffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback function when enabled.
|
|
|
|
Arguments:
|
|
|
|
RequestCode - Flag for either enable or disable.
|
|
Context - User-defined context.
|
|
InOutBufferSize - not used.
|
|
Buffer - WNODE_HEADER for the logger session.
|
|
|
|
Return Value:
|
|
|
|
Error Status. ERROR_SUCCESS if successful.
|
|
|
|
--*/
|
|
{
|
|
ULONG Status;
|
|
ULONG RetSize;
|
|
|
|
Status = ERROR_SUCCESS;
|
|
|
|
switch (RequestCode)
|
|
{
|
|
case WMI_ENABLE_EVENTS:
|
|
{
|
|
RetSize = 0;
|
|
LoggerHandle = GetTraceLoggerHandle( Buffer );
|
|
EnableLevel = GetTraceEnableLevel(LoggerHandle);
|
|
EnableFlags = GetTraceEnableFlags(LoggerHandle);
|
|
_tprintf(_T("Logging enabled to 0x%016I64x(%d,%d,%d)\n"),
|
|
LoggerHandle, RequestCode, EnableLevel, EnableFlags);
|
|
TraceOnFlag = TRUE;
|
|
break;
|
|
}
|
|
case WMI_DISABLE_EVENTS:
|
|
{
|
|
TraceOnFlag = FALSE;
|
|
RetSize = 0;
|
|
LoggerHandle = 0;
|
|
_tprintf(_T("\nLogging Disabled\n"));
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
RetSize = 0;
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
*InOutBufferSize = RetSize;
|
|
return(Status);
|
|
}
|
|
|
|
void
|
|
DoWork()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Logs events.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
USER_EVENT UserEvent;
|
|
ULONG Status;
|
|
|
|
RtlZeroMemory(&UserEvent, sizeof(UserEvent));
|
|
UserEvent.Header.Size = sizeof(USER_EVENT);
|
|
UserEvent.Header.Flags = WNODE_FLAG_TRACED_GUID;
|
|
UserEvent.Header.Guid = TransactionGuid;
|
|
|
|
// Log START event to indicate a start of a routine or activity.
|
|
// We log EventCount as data.
|
|
if (TraceOnFlag) {
|
|
UserEvent.Header.Class.Type = EVENT_TRACE_TYPE_START;
|
|
UserEvent.EventInfo = ++EventCount;
|
|
Status = TraceEvent(
|
|
LoggerHandle,
|
|
(PEVENT_TRACE_HEADER) & UserEvent);
|
|
if (Status != ERROR_SUCCESS) {
|
|
// TraceEvent() failed. This could happen when the logger
|
|
// cannot keep up with too many events logged rapidly.
|
|
// In such cases, the return valid is
|
|
// ERROR_NOT_ENOUGH_MEMORY.
|
|
_tprintf(_T("TraceEvent failed. Status=%d\n"), Status);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Main body of the work in this routine comes here.
|
|
//
|
|
_sleep(1);
|
|
|
|
// Log END event to indicate an end of a routine or activity.
|
|
// We log EventCount as data.
|
|
if (TraceOnFlag) {
|
|
UserEvent.Header.Class.Type = EVENT_TRACE_TYPE_END;
|
|
UserEvent.EventInfo = ++EventCount;
|
|
Status = TraceEvent(
|
|
LoggerHandle,
|
|
(PEVENT_TRACE_HEADER) & UserEvent);
|
|
if (Status != ERROR_SUCCESS) {
|
|
// TraceEvent() failed. This could happen when the logger
|
|
// cannot keep up with too many events logged rapidly.
|
|
// In such cases, the return valid is
|
|
// ERROR_NOT_ENOUGH_MEMORY.
|
|
_tprintf(_T("TraceEvent failed. Status=%d\n"), Status);
|
|
}
|
|
}
|
|
}
|
|
|