893 lines
24 KiB
C
893 lines
24 KiB
C
/*++
|
|
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
PARTICULAR PURPOSE.
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved
|
|
|
|
Module Name:
|
|
|
|
tracelog.c
|
|
|
|
Abstract:
|
|
|
|
Sample trace control program. Allows user to start, update, query, stop
|
|
event tracing, etc.
|
|
|
|
|
|
--*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <windows.h>
|
|
#include <shellapi.h>
|
|
#include <tchar.h>
|
|
#include <wmistr.h>
|
|
#include <initguid.h>
|
|
#include <guiddef.h>
|
|
#include <evntrace.h>
|
|
|
|
#define MAXSTR 1024
|
|
|
|
//
|
|
// Default trace file name.
|
|
//
|
|
|
|
#define DEFAULT_LOGFILE_NAME _T("C:\\LogFile.Etl")
|
|
|
|
//
|
|
// On Windows 2000, we support up to 32 loggers at once.
|
|
// On Windows XP and .NET server, we support up to 64 loggers.
|
|
//
|
|
|
|
#define MAXIMUM_LOGGERS 64
|
|
|
|
//
|
|
// In this sample, we support the following actions.
|
|
// Additional actions that we do not use in this sample include
|
|
// Flush and Enumerate Guids functionalities. They are supported
|
|
// only on XP or higher version.
|
|
//
|
|
|
|
#define ACTION_QUERY 0
|
|
#define ACTION_START 1
|
|
#define ACTION_STOP 2
|
|
#define ACTION_UPDATE 3
|
|
#define ACTION_LIST 4
|
|
#define ACTION_ENABLE 5
|
|
#define ACTION_HELP 6
|
|
|
|
#define ACTION_UNDEFINED 10
|
|
|
|
VOID
|
|
PrintLoggerStatus(
|
|
__in PEVENT_TRACE_PROPERTIES LoggerInfo,
|
|
__in ULONG Status
|
|
);
|
|
|
|
ULONG
|
|
HexToLong(
|
|
__in TCHAR *String
|
|
);
|
|
|
|
VOID
|
|
StringToGuid(
|
|
__in TCHAR *String,
|
|
__out LPGUID Guid
|
|
);
|
|
|
|
VOID
|
|
PrintHelpMessage(
|
|
VOID
|
|
);
|
|
|
|
|
|
LONG
|
|
main(
|
|
__in INT argc,
|
|
__in_ecount(argc) LPTSTR* argv
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
It is the main function.
|
|
|
|
Arguments:
|
|
|
|
argc - Number of the arguments passed to the command line.
|
|
|
|
argv - Array of strings which holds each argument value.
|
|
|
|
Return Value:
|
|
|
|
Error Code defined in winerror.h : If the function succeeds,
|
|
it returns ERROR_SUCCESS(=0).
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG LoggerCounter;
|
|
ULONG Status = ERROR_SUCCESS;
|
|
LPTSTR *targv;
|
|
LPTSTR *utargv = NULL;
|
|
|
|
//
|
|
// Action to be taken
|
|
//
|
|
|
|
USHORT Action = ACTION_UNDEFINED;
|
|
|
|
LPTSTR LoggerName;
|
|
LPTSTR LogFileName;
|
|
|
|
//
|
|
// We will store the custom logger settings in LoggerInfo.
|
|
//
|
|
|
|
PEVENT_TRACE_PROPERTIES LoggerInfo;
|
|
|
|
TRACEHANDLE LoggerHandle = 0;
|
|
|
|
//
|
|
// Target GUID, level and flags for enable/disable
|
|
//
|
|
|
|
GUID TargetGuid = {0};
|
|
BOOLEAN TargetGuidProvided = FALSE;
|
|
|
|
ULONG Enable = TRUE;
|
|
|
|
ULONG SizeNeeded = 0;
|
|
|
|
//
|
|
// We will enable Process, Thread, Disk, and Network events
|
|
// if the Kernel Logger is requested.
|
|
//
|
|
|
|
BOOL IsKernelLogger = FALSE;
|
|
|
|
//
|
|
// Allocate and initialize EVENT_TRACE_PROPERTIES structure first.
|
|
//
|
|
|
|
SizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) +
|
|
2 * MAXSTR * sizeof(TCHAR);
|
|
|
|
LoggerInfo = (PEVENT_TRACE_PROPERTIES)malloc(SizeNeeded);
|
|
if (LoggerInfo == NULL) {
|
|
return (ERROR_OUTOFMEMORY);
|
|
}
|
|
|
|
RtlZeroMemory(LoggerInfo, SizeNeeded);
|
|
|
|
LoggerInfo->Wnode.BufferSize = SizeNeeded;
|
|
LoggerInfo->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
|
LoggerInfo->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
|
LoggerInfo->LogFileNameOffset = LoggerInfo->LoggerNameOffset +
|
|
MAXSTR * sizeof(TCHAR);
|
|
|
|
LoggerName = (LPTSTR)((PCHAR)LoggerInfo + LoggerInfo->LoggerNameOffset);
|
|
LogFileName = (LPTSTR)((PCHAR)LoggerInfo + LoggerInfo->LogFileNameOffset);
|
|
|
|
//
|
|
// If the logger name is not given, we will assume the kernel logger.
|
|
//
|
|
|
|
_tcscpy_s(LoggerName, MAXSTR, KERNEL_LOGGER_NAME);
|
|
|
|
#ifdef UNICODE
|
|
UNREFERENCED_PARAMETER(argv);
|
|
if ((targv = CommandLineToArgvW(GetCommandLineW(),
|
|
&argc)) == NULL) {
|
|
free(LoggerInfo);
|
|
return (GetLastError());
|
|
};
|
|
utargv = targv;
|
|
#else
|
|
targv = argv;
|
|
#endif
|
|
|
|
//
|
|
// Parse the command line options to determine actions and parameters.
|
|
//
|
|
|
|
while (--argc > 0) {
|
|
++targv;
|
|
if (**targv == '-' || **targv == '/') { // argument found
|
|
if (targv[0][0] == '/' ) {
|
|
targv[0][0] = '-';
|
|
}
|
|
|
|
//
|
|
// Determine actions.
|
|
//
|
|
|
|
if (_tcsicmp(targv[0], _T("-start")) == 0) {
|
|
Action = ACTION_START;
|
|
if (argc > 1) {
|
|
if ((targv[1][0] != '-') && (targv[1][0] != '/')) {
|
|
++targv;
|
|
--argc;
|
|
_tcscpy_s(LoggerName, MAXSTR, targv[0]);
|
|
}
|
|
}
|
|
} else if (_tcsicmp(targv[0], _T("-enable")) == 0) {
|
|
Action = ACTION_ENABLE;
|
|
if (argc > 1) {
|
|
if ((targv[1][0] != '-') && (targv[1][0] != '/')) {
|
|
++targv;
|
|
--argc;
|
|
_tcscpy_s(LoggerName, MAXSTR, targv[0]);
|
|
}
|
|
}
|
|
} else if (_tcsicmp(targv[0], _T("-disable")) == 0) {
|
|
Action = ACTION_ENABLE;
|
|
Enable = FALSE;
|
|
if (argc > 1) {
|
|
if ((targv[1][0] != '-') && (targv[1][0] != '/')) {
|
|
++targv;
|
|
--argc;
|
|
_tcscpy_s(LoggerName, MAXSTR, targv[0]);
|
|
}
|
|
}
|
|
} else if (_tcsicmp(targv[0], _T("-stop")) == 0) {
|
|
Action = ACTION_STOP;
|
|
if (argc > 1) {
|
|
if ((targv[1][0] != '-') && (targv[1][0] != '/')) {
|
|
++targv;
|
|
--argc;
|
|
_tcscpy_s(LoggerName, MAXSTR, targv[0]);
|
|
}
|
|
}
|
|
} else if (_tcsicmp(targv[0], _T("-update")) == 0) {
|
|
Action = ACTION_UPDATE;
|
|
if (argc > 1) {
|
|
if ((targv[1][0] != '-') && (targv[1][0] != '/')) {
|
|
++targv;
|
|
--argc;
|
|
_tcscpy_s(LoggerName, MAXSTR, targv[0]);
|
|
}
|
|
}
|
|
} else if (_tcsicmp(targv[0], _T("-query")) == 0) {
|
|
Action = ACTION_QUERY;
|
|
if (argc > 1) {
|
|
if ((targv[1][0] != '-') && (targv[1][0] != '/')) {
|
|
++targv;
|
|
--argc;
|
|
_tcscpy_s(LoggerName, MAXSTR, targv[0]);
|
|
}
|
|
}
|
|
} else if (_tcsicmp(targv[0], _T("-list")) == 0) {
|
|
Action = ACTION_LIST;
|
|
}
|
|
|
|
//
|
|
// Get other parameters.
|
|
// Users can customize logger settings further by adding/changing
|
|
// values to LoggerInfo. Refer to EVENT_TRACE_PROPERTIES
|
|
// documentation for available options.
|
|
// In this sample, we allow changing maximum number of buffers and
|
|
// specifying user mode (private) logger.
|
|
// We also take trace file name and guid for enable/disable.
|
|
//
|
|
|
|
else if (_tcsicmp(targv[0], _T("-f")) == 0) {
|
|
if (argc > 1) {
|
|
_tfullpath(LogFileName, targv[1], MAXSTR);
|
|
++targv;
|
|
--argc;
|
|
}
|
|
} else if (_tcsicmp(targv[0], _T("-guid")) == 0) {
|
|
if (argc > 1) {
|
|
|
|
//
|
|
// Before the guid value, we expect "#"
|
|
// -guid #xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
//
|
|
|
|
if (targv[1][0] == _T('#')) {
|
|
StringToGuid(&targv[1][1], &TargetGuid);
|
|
TargetGuidProvided = TRUE;
|
|
++targv;
|
|
--argc;
|
|
}
|
|
}
|
|
} else if (_tcsicmp(targv[0], _T("-max")) == 0) {
|
|
if (argc > 1) {
|
|
LoggerInfo->MaximumBuffers = _ttoi(targv[1]);
|
|
++targv;
|
|
--argc;
|
|
}
|
|
} else if (_tcsicmp(targv[0], _T("-um")) == 0) {
|
|
LoggerInfo->LogFileMode |= EVENT_TRACE_PRIVATE_LOGGER_MODE;
|
|
|
|
} else if ((targv[0][1] == 'h') ||
|
|
(targv[0][1] == 'H') ||
|
|
(targv[0][1] == '?')) {
|
|
|
|
Action = ACTION_HELP;
|
|
PrintHelpMessage();
|
|
|
|
if (utargv != NULL) {
|
|
GlobalFree(utargv);
|
|
}
|
|
|
|
free(LoggerInfo);
|
|
|
|
return (ERROR_SUCCESS);
|
|
|
|
} else {
|
|
Action = ACTION_UNDEFINED;
|
|
}
|
|
} else {
|
|
_tprintf(_T("Invalid option given: %s\n"), targv[0]);
|
|
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
goto CleanUpAndExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the kernel logger parameters.
|
|
//
|
|
|
|
if (_tcscmp(LoggerName, KERNEL_LOGGER_NAME) == 0) {
|
|
|
|
//
|
|
// Set enable flags. Users can add options to add additional kernel events
|
|
// or remove some of these events.
|
|
//
|
|
|
|
LoggerInfo->EnableFlags |= EVENT_TRACE_FLAG_PROCESS;
|
|
LoggerInfo->EnableFlags |= EVENT_TRACE_FLAG_THREAD;
|
|
LoggerInfo->EnableFlags |= EVENT_TRACE_FLAG_DISK_IO;
|
|
LoggerInfo->EnableFlags |= EVENT_TRACE_FLAG_NETWORK_TCPIP;
|
|
|
|
LoggerInfo->Wnode.Guid = SystemTraceControlGuid;
|
|
IsKernelLogger = TRUE;
|
|
|
|
} else if (LoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
|
|
|
|
//
|
|
// We must provide a control GUID for a private logger.
|
|
//
|
|
|
|
if (TargetGuidProvided != FALSE) {
|
|
LoggerInfo->Wnode.Guid = TargetGuid;
|
|
} else {
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
goto CleanUpAndExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Process the request.
|
|
//
|
|
|
|
switch (Action) {
|
|
case ACTION_START:
|
|
{
|
|
|
|
//
|
|
// Use default file name if not given
|
|
//
|
|
|
|
if (_tcslen(LogFileName) == 0) {
|
|
_tcscpy_s(LogFileName, MAXSTR, DEFAULT_LOGFILE_NAME);
|
|
}
|
|
|
|
Status = StartTrace(&LoggerHandle, LoggerName, LoggerInfo);
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
_tprintf(_T("Could not start logger: %s\n")
|
|
_T("Operation Status: %uL\n"),
|
|
LoggerName,
|
|
Status);
|
|
|
|
break;
|
|
}
|
|
_tprintf(_T("Logger Started...\n"));
|
|
}
|
|
case ACTION_ENABLE:
|
|
{
|
|
|
|
//
|
|
// We can allow enabling a GUID during START operation
|
|
// (Note no break in case ACTION_START).
|
|
// In that case, we do not need to get LoggerHandle separately.
|
|
//
|
|
|
|
if (Action == ACTION_ENABLE) {
|
|
|
|
//
|
|
// Get Logger Handle though Query.
|
|
//
|
|
|
|
Status = ControlTrace((TRACEHANDLE)0,
|
|
LoggerName,
|
|
LoggerInfo,
|
|
EVENT_TRACE_CONTROL_QUERY);
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
_tprintf(_T("ERROR: Logger not started\n")
|
|
_T("Operation Status: %uL\n"),
|
|
Status);
|
|
break;
|
|
}
|
|
LoggerHandle = LoggerInfo->Wnode.HistoricalContext;
|
|
}
|
|
|
|
//
|
|
// We do not allow EnableTrace on the Kernel Logger in this sample,
|
|
// users can use EnableFlags to enable/disable certain kernel events.
|
|
//
|
|
|
|
if (IsKernelLogger == FALSE) {
|
|
_tprintf(_T("Enabling trace to logger %d\n"), LoggerHandle);
|
|
|
|
//
|
|
// In this sample, we use EnableFlag = EnableLebel = 0.
|
|
//
|
|
|
|
Status = EnableTrace(Enable,
|
|
0,
|
|
0,
|
|
&TargetGuid,
|
|
LoggerHandle);
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
_tprintf(_T("ERROR: Failed to enable Guid...\n"));
|
|
_tprintf(_T("Operation Status: %uL\n"), Status);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ACTION_STOP:
|
|
{
|
|
LoggerHandle = (TRACEHANDLE)0;
|
|
|
|
Status = ControlTrace(LoggerHandle,
|
|
LoggerName,
|
|
LoggerInfo,
|
|
EVENT_TRACE_CONTROL_STOP);
|
|
break;
|
|
}
|
|
case ACTION_LIST:
|
|
{
|
|
ULONG ReturnCount;
|
|
PEVENT_TRACE_PROPERTIES LoggerInfo[MAXIMUM_LOGGERS];
|
|
PEVENT_TRACE_PROPERTIES Storage;
|
|
PEVENT_TRACE_PROPERTIES TempStorage;
|
|
ULONG SizeForOneProperty = sizeof(EVENT_TRACE_PROPERTIES) +
|
|
2 * MAXSTR * sizeof(TCHAR);
|
|
|
|
//
|
|
// We need to prepare space to receieve the inforamtion for the loggers.
|
|
// Each logger information needs one EVENT_TRACE_PROPERTIES sturucture
|
|
// followed by the logger name and the logfile path strings.
|
|
//
|
|
|
|
SizeNeeded = MAXIMUM_LOGGERS * SizeForOneProperty;
|
|
|
|
Storage = (PEVENT_TRACE_PROPERTIES)malloc(SizeNeeded);
|
|
if (Storage == NULL) {
|
|
Status = ERROR_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
RtlZeroMemory(Storage, SizeNeeded);
|
|
|
|
//
|
|
// Save the pointer for free() later.
|
|
//
|
|
|
|
TempStorage = Storage;
|
|
|
|
//
|
|
// Initialize the LoggerInfo array, before passing it to QueryAllTraces.
|
|
//
|
|
|
|
for (LoggerCounter = 0; LoggerCounter < MAXIMUM_LOGGERS; LoggerCounter++) {
|
|
|
|
Storage->Wnode.BufferSize = SizeForOneProperty;
|
|
Storage->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
|
|
|
Storage->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) +
|
|
MAXSTR * sizeof(TCHAR);
|
|
|
|
LoggerInfo[LoggerCounter] = Storage;
|
|
|
|
//
|
|
// Move Storage to point to the next allocated buffer for the
|
|
// logger information.
|
|
//
|
|
|
|
Storage = (PEVENT_TRACE_PROPERTIES)((PUCHAR)Storage +
|
|
Storage->Wnode.BufferSize);
|
|
}
|
|
|
|
Status = QueryAllTraces(LoggerInfo,
|
|
MAXIMUM_LOGGERS,
|
|
&ReturnCount);
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
for (LoggerCounter = 0; LoggerCounter < ReturnCount; LoggerCounter++) {
|
|
PrintLoggerStatus(LoggerInfo[LoggerCounter], Status);
|
|
_tprintf(_T("\n"));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Free the memory allocated for the logger information buffers.
|
|
//
|
|
|
|
free(TempStorage);
|
|
break;
|
|
}
|
|
|
|
case ACTION_UPDATE:
|
|
{
|
|
|
|
//
|
|
// In this sample, users can only update MaximumBuffers and log file name.
|
|
// User can add more options for other parameters as needed.
|
|
//
|
|
|
|
Status = ControlTrace(LoggerHandle,
|
|
LoggerName,
|
|
LoggerInfo,
|
|
EVENT_TRACE_CONTROL_UPDATE);
|
|
break;
|
|
}
|
|
case ACTION_QUERY:
|
|
{
|
|
Status = ControlTrace(LoggerHandle,
|
|
LoggerName,
|
|
LoggerInfo,
|
|
EVENT_TRACE_CONTROL_QUERY);
|
|
break;
|
|
}
|
|
case ACTION_HELP:
|
|
{
|
|
PrintHelpMessage();
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
_tprintf(_T("Error: no action specified\n"));
|
|
PrintHelpMessage();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((Action != ACTION_HELP) &&
|
|
(Action != ACTION_UNDEFINED) &&
|
|
(Action != ACTION_LIST)) {
|
|
|
|
PrintLoggerStatus(LoggerInfo, Status);
|
|
}
|
|
|
|
CleanUpAndExit:
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
SetLastError(Status);
|
|
}
|
|
|
|
if (utargv != NULL) {
|
|
GlobalFree(utargv);
|
|
}
|
|
|
|
free(LoggerInfo);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintLoggerStatus(
|
|
__in PEVENT_TRACE_PROPERTIES LoggerInfo,
|
|
__in ULONG Status
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints out the status of the specified logger.
|
|
|
|
Arguments:
|
|
|
|
LoggerInfo - The pointer to the resident EVENT_TRACE_PROPERTIES that has
|
|
the information about the current logger.
|
|
|
|
Status - The operation status of the current logger.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
LPTSTR LoggerName;
|
|
LPTSTR LogFileName;
|
|
|
|
if ((LoggerInfo->LoggerNameOffset > 0) &&
|
|
(LoggerInfo->LoggerNameOffset < LoggerInfo->Wnode.BufferSize)) {
|
|
|
|
LoggerName = (LPTSTR)((PUCHAR)LoggerInfo +
|
|
LoggerInfo->LoggerNameOffset);
|
|
} else {
|
|
LoggerName = NULL;
|
|
}
|
|
|
|
if ((LoggerInfo->LogFileNameOffset > 0) &&
|
|
(LoggerInfo->LogFileNameOffset < LoggerInfo->Wnode.BufferSize)) {
|
|
|
|
LogFileName = (LPTSTR)((PUCHAR)LoggerInfo +
|
|
LoggerInfo->LogFileNameOffset);
|
|
} else {
|
|
LogFileName = NULL;
|
|
}
|
|
|
|
_tprintf(_T("Operation Status: %uL\n"), Status);
|
|
|
|
_tprintf(_T("Logger Name: %s\n"),
|
|
(LoggerName == NULL) ?
|
|
_T(" ") : LoggerName);
|
|
|
|
|
|
_tprintf(_T("Logger Id: %I64x\n"), LoggerInfo->Wnode.HistoricalContext);
|
|
|
|
_tprintf(_T("Logger Thread Id: %d\n"), LoggerInfo->LoggerThreadId);
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
_tprintf(_T("Buffer Size: %d Kb"), LoggerInfo->BufferSize);
|
|
|
|
if (LoggerInfo->LogFileMode & EVENT_TRACE_USE_PAGED_MEMORY) {
|
|
_tprintf(_T(" using paged memory\n"));
|
|
} else {
|
|
_tprintf(_T("\n"));
|
|
}
|
|
_tprintf(_T("Maximum Buffers: %d\n"), LoggerInfo->MaximumBuffers);
|
|
_tprintf(_T("Minimum Buffers: %d\n"), LoggerInfo->MinimumBuffers);
|
|
_tprintf(_T("Number of Buffers: %d\n"), LoggerInfo->NumberOfBuffers);
|
|
_tprintf(_T("Free Buffers: %d\n"), LoggerInfo->FreeBuffers);
|
|
_tprintf(_T("Buffers Written: %d\n"), LoggerInfo->BuffersWritten);
|
|
_tprintf(_T("Events Lost: %d\n"), LoggerInfo->EventsLost);
|
|
_tprintf(_T("Log Buffers Lost: %d\n"), LoggerInfo->LogBuffersLost);
|
|
_tprintf(_T("Real Time Buffers Lost: %d\n"), LoggerInfo->RealTimeBuffersLost);
|
|
_tprintf(_T("AgeLimit: %d\n"), LoggerInfo->AgeLimit);
|
|
|
|
if (LogFileName == NULL) {
|
|
_tprintf(_T("Buffering Mode: "));
|
|
} else {
|
|
_tprintf(_T("Log File Mode: "));
|
|
}
|
|
|
|
if (LoggerInfo->LogFileMode & EVENT_TRACE_FILE_MODE_APPEND) {
|
|
_tprintf(_T("Append "));
|
|
}
|
|
|
|
if (LoggerInfo->LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR) {
|
|
_tprintf(_T("Circular\n"));
|
|
} else if (LoggerInfo->LogFileMode & EVENT_TRACE_FILE_MODE_SEQUENTIAL) {
|
|
_tprintf(_T("Sequential\n"));
|
|
} else {
|
|
_tprintf(_T("Sequential\n"));
|
|
}
|
|
|
|
if (LoggerInfo->LogFileMode & EVENT_TRACE_REAL_TIME_MODE) {
|
|
_tprintf(_T("Real Time mode enabled"));
|
|
_tprintf(_T("\n"));
|
|
}
|
|
|
|
if (LoggerInfo->MaximumFileSize > 0) {
|
|
_tprintf(_T("Maximum File Size: %d Mb\n"), LoggerInfo->MaximumFileSize);
|
|
}
|
|
|
|
if (LoggerInfo->FlushTimer > 0) {
|
|
_tprintf(_T("Buffer Flush Timer: %d secs\n"), LoggerInfo->FlushTimer);
|
|
}
|
|
|
|
if (LoggerInfo->EnableFlags != 0) {
|
|
_tprintf(_T("Enabled tracing: "));
|
|
|
|
if ((LoggerName != NULL) && (_tcscmp(LoggerName, KERNEL_LOGGER_NAME) == 0)) {
|
|
|
|
if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_PROCESS) {
|
|
_tprintf(_T("Process "));
|
|
}
|
|
if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_THREAD) {
|
|
_tprintf(_T("Thread "));
|
|
}
|
|
if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_DISK_IO) {
|
|
_tprintf(_T("Disk "));
|
|
}
|
|
if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_DISK_FILE_IO) {
|
|
_tprintf(_T("File "));
|
|
}
|
|
if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_MEMORY_PAGE_FAULTS) {
|
|
_tprintf(_T("PageFaults "));
|
|
}
|
|
if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_MEMORY_HARD_FAULTS){
|
|
_tprintf(_T("HardFaults "));
|
|
}
|
|
if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_IMAGE_LOAD) {
|
|
_tprintf(_T("ImageLoad "));
|
|
}
|
|
if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_NETWORK_TCPIP) {
|
|
_tprintf(_T("TcpIp "));
|
|
}
|
|
if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_REGISTRY) {
|
|
_tprintf(_T("Registry "));
|
|
}
|
|
} else {
|
|
_tprintf(_T("0x%08x"), LoggerInfo->EnableFlags);
|
|
}
|
|
|
|
_tprintf(_T("\n"));
|
|
}
|
|
|
|
if (LogFileName != NULL) {
|
|
_tprintf(_T("Log Filename: %s\n"), LogFileName);
|
|
}
|
|
|
|
}
|
|
|
|
ULONG
|
|
HexToLong(
|
|
__in TCHAR *String
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a hex string into a number.
|
|
|
|
Arguments:
|
|
|
|
String - A hex string in TCHAR.
|
|
|
|
Return Value:
|
|
|
|
ULONG - The number in the string.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG HexDigit = 0;
|
|
ULONG Base = 1;
|
|
ULONG HexValue = 0;
|
|
INT Length = (INT)_tcslen(String);
|
|
|
|
while (--Length >= 0) {
|
|
if ((String[Length] == 'x' || String[Length] == 'X') &&
|
|
(String[Length - 1] == '0')) {
|
|
|
|
break;
|
|
}
|
|
|
|
if ((String[Length] >= '0') && (String[Length] <= '9')) {
|
|
HexDigit = String[Length] - '0';
|
|
} else if ((String[Length] >= 'a') && (String[Length] <= 'f')) {
|
|
HexDigit = (String[Length] - 'a') + 10;
|
|
} else if ((String[Length] >= 'A') && (String[Length] <= 'F')) {
|
|
HexDigit = (String[Length] - 'A') + 10;
|
|
} else {
|
|
continue;
|
|
}
|
|
|
|
HexValue |= HexDigit * Base;
|
|
Base <<= 4;
|
|
}
|
|
|
|
return HexValue;
|
|
}
|
|
|
|
VOID
|
|
StringToGuid(
|
|
__in TCHAR *String,
|
|
__out LPGUID Guid
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a string into a GUID.
|
|
|
|
Arguments:
|
|
|
|
String - A string in TCHAR.
|
|
|
|
Guid - The pointer to a GUID that will have the converted GUID.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
TCHAR Temp[10];
|
|
INT Index;
|
|
|
|
_tcsncpy_s(Temp, 10, String, 8);
|
|
Temp[8] = 0;
|
|
Guid->Data1 = HexToLong(Temp);
|
|
|
|
_tcsncpy_s(Temp, 10, &String[9], 4);
|
|
Temp[4] = 0;
|
|
Guid->Data2 = (USHORT)HexToLong(Temp);
|
|
|
|
_tcsncpy_s(Temp, 10, &String[14], 4);
|
|
Temp[4] = 0;
|
|
Guid->Data3 = (USHORT)HexToLong(Temp);
|
|
|
|
for (Index = 0; Index < 2; Index++) {
|
|
_tcsncpy_s(Temp, 10, &String[19 + Index * 2], 2);
|
|
Temp[2] = 0;
|
|
Guid->Data4[Index] = (UCHAR)HexToLong(Temp);
|
|
}
|
|
|
|
for (Index = 2; Index < 8; Index++) {
|
|
_tcsncpy_s(Temp, 10, &String[20 + Index * 2], 2);
|
|
Temp[2] = 0;
|
|
Guid->Data4[Index] = (UCHAR)HexToLong(Temp);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
PrintHelpMessage(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints out a help message.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
_tprintf(_T("Usage: tracelog [actions] [options] | [-h | -help | -?]\n"));
|
|
_tprintf(_T("\n actions:\n"));
|
|
_tprintf(_T("\t-start [LoggerName] Starts up the [LoggerName] trace session\n"));
|
|
_tprintf(_T("\t-stop [LoggerName] Stops the [LoggerName] trace session\n"));
|
|
_tprintf(_T("\t-update [LoggerName] Updates the [LoggerName] trace session\n"));
|
|
_tprintf(_T("\t-enable [LoggerName] Enables providers for the [LoggerName] session\n"));
|
|
_tprintf(_T("\t-disable [LoggerName] Disables providers for the [LoggerName] session\n"));
|
|
_tprintf(_T("\t-query [LoggerName] Query status of [LoggerName] trace session\n"));
|
|
_tprintf(_T("\t-list List all trace sessions\n"));
|
|
|
|
_tprintf(_T("\n options:\n"));
|
|
_tprintf(_T("\t-um Use Process Private tracing\n"));
|
|
_tprintf(_T("\t-max <n> Sets maximum buffers\n"));
|
|
_tprintf(_T("\t-f <name> Log to file <name>\n"));
|
|
_tprintf(_T("\t-guid #<guid> Provider GUID to enable/disable\n"));
|
|
_tprintf(_T("\n"));
|
|
_tprintf(_T("\t-h\n"));
|
|
_tprintf(_T("\t-help\n"));
|
|
_tprintf(_T("\t-? Display usage information\n"));
|
|
}
|