1335 lines
45 KiB
C
1335 lines
45 KiB
C
/*++
|
|
|
|
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.
|
|
|
|
|
|
--*/
|
|
#ifndef UNICODE
|
|
#define UNICODE
|
|
#endif
|
|
#ifndef _UNICODE
|
|
#define _UNICODE
|
|
#endif
|
|
|
|
#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
|
|
#define DEFAULT_LOGFILE_NAME _T("C:\\LogFile.Etl")
|
|
#define NT_LOGGER _T("NT Kernel Logger")
|
|
#define MAXIMUM_LOGGERS 32
|
|
#define MAXGUIDS 128
|
|
|
|
#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_FLUSH 7
|
|
#define ACTION_ENUM_GUID 8
|
|
#define ACTION_UNDEFINED 10
|
|
|
|
#define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
|
|
//
|
|
// Functions not implemented on Win2K need to be searched and loaded separately.
|
|
// To make further accesses easy, an array of function pointers will be used.
|
|
// The following list serves as indices to that array.
|
|
//
|
|
#define FUNC_FLUSH_TRACE 0
|
|
#define FUNC_ENUM_TRACE_GUIDS 1
|
|
// Funtion pointer array for unimplemented functions on Win2K.
|
|
// Note: This may not work if this code is ported to C++, because
|
|
// all the function pointers may be typedefed differently.
|
|
#define MAXFUNC 10
|
|
FARPROC FuncArray[MAXFUNC];
|
|
HINSTANCE advapidll;
|
|
|
|
BOOLEAN XP;
|
|
|
|
void
|
|
PrintLoggerStatus(
|
|
IN PEVENT_TRACE_PROPERTIES LoggerInfo,
|
|
IN ULONG Status,
|
|
IN BOOL PrintStatus
|
|
);
|
|
|
|
#define PRINTSTATUS TRUE
|
|
#define NOPRINTSTATUS FALSE
|
|
|
|
LPTSTR
|
|
DecodeStatus(
|
|
IN ULONG Status
|
|
);
|
|
|
|
LONG
|
|
GetGuids(
|
|
IN LPTSTR GuidFile,
|
|
OUT LPGUID *GuidArray
|
|
);
|
|
|
|
ULONG
|
|
ahextoi(
|
|
IN TCHAR *s
|
|
);
|
|
|
|
void
|
|
StringToGuid(
|
|
IN TCHAR *str,
|
|
OUT LPGUID guid
|
|
);
|
|
|
|
PTCHAR
|
|
GuidToString(
|
|
IN OUT PTCHAR s,
|
|
IN LPGUID piid
|
|
);
|
|
|
|
TCHAR ErrorMsg[MAXSTR];
|
|
|
|
void
|
|
PrintHelpMessage();
|
|
|
|
|
|
//
|
|
// main function
|
|
//
|
|
__cdecl main(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
It is the main function.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Error Code defined in winerror.h : If the function succeeds,
|
|
it returns ERROR_SUCCESS (== 0).
|
|
|
|
|
|
--*/{
|
|
ULONG i, j;
|
|
LONG GuidCount;
|
|
USHORT Action = ACTION_UNDEFINED;
|
|
ULONG Status = 0;
|
|
LPTSTR LoggerName;
|
|
LPTSTR LogFileName;
|
|
TCHAR GuidFile[MAXSTR];
|
|
PEVENT_TRACE_PROPERTIES pLoggerInfo;
|
|
TRACEHANDLE LoggerHandle = 0;
|
|
LPTSTR *targv, *utargv = NULL;
|
|
LPGUID *GuidArray;
|
|
char *Space;
|
|
char *save;
|
|
BOOL bKill = FALSE;
|
|
BOOL bForceKill = FALSE ;
|
|
BOOL bEnable = TRUE;
|
|
ULONG iLevel = 0;
|
|
ULONG iFlags = 0;
|
|
ULONG SizeNeeded = 0;
|
|
ULONG specialLogger = 0;
|
|
ULONG GlobalLoggerStartValue = 0;
|
|
PULONG pFlags = NULL;
|
|
|
|
BOOL bProcess = TRUE;
|
|
BOOL bThread = TRUE;
|
|
BOOL bDisk = TRUE;
|
|
BOOL bNetwork = TRUE;
|
|
|
|
TCHAR tstrLogFileName[MAXSTR];
|
|
|
|
OSVERSIONINFO OSVersion;
|
|
|
|
OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
XP = FALSE;
|
|
if (GetVersionEx(&OSVersion)) {
|
|
XP = (OSVersion.dwMajorVersion > 5) ||
|
|
((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion > 0));
|
|
}
|
|
// Load functions that are not implemented on Win2K
|
|
for (i = 0; i < MAXFUNC; ++i)
|
|
FuncArray[i] = NULL;
|
|
if (XP) {
|
|
advapidll = LoadLibrary(_T("advapi32.dll"));
|
|
if (advapidll != NULL) {
|
|
#ifdef UNICODE
|
|
FuncArray[FUNC_FLUSH_TRACE] = GetProcAddress(advapidll, "FlushTraceW");
|
|
#else
|
|
FuncArray[FUNC_FLUSH_TRACE] = GetProcAddress(advapidll, "FlushTraceA");
|
|
#endif
|
|
FuncArray[FUNC_ENUM_TRACE_GUIDS] = GetProcAddress(advapidll, "EnumerateTraceGuids");
|
|
}
|
|
}
|
|
|
|
// Initialize structure first
|
|
SizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + 2 * MAXSTR * sizeof(TCHAR);
|
|
pLoggerInfo = (PEVENT_TRACE_PROPERTIES) malloc(SizeNeeded);
|
|
if (pLoggerInfo == NULL) {
|
|
if (advapidll != NULL)
|
|
FreeLibrary(advapidll);
|
|
return (ERROR_OUTOFMEMORY);
|
|
}
|
|
|
|
|
|
RtlZeroMemory(pLoggerInfo, SizeNeeded);
|
|
|
|
pLoggerInfo->Wnode.BufferSize = SizeNeeded;
|
|
pLoggerInfo->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
|
pLoggerInfo->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
|
pLoggerInfo->LogFileNameOffset = pLoggerInfo->LoggerNameOffset + MAXSTR * sizeof(TCHAR);
|
|
|
|
LoggerName = (LPTSTR)((char*)pLoggerInfo + pLoggerInfo->LoggerNameOffset);
|
|
LogFileName = (LPTSTR)((char*)pLoggerInfo + pLoggerInfo->LogFileNameOffset);
|
|
_tcscpy(LoggerName, NT_LOGGER);
|
|
|
|
Space = (char*) malloc( (MAXGUIDS * sizeof(GuidArray)) +
|
|
(MAXGUIDS * sizeof(GUID) ));
|
|
if (Space == NULL) {
|
|
free(pLoggerInfo);
|
|
if (advapidll != NULL)
|
|
FreeLibrary(advapidll);
|
|
return(ERROR_OUTOFMEMORY);
|
|
}
|
|
save = Space;
|
|
GuidArray = (LPGUID *) Space;
|
|
Space += MAXGUIDS * sizeof(GuidArray);
|
|
|
|
for (GuidCount=0; GuidCount<MAXGUIDS; GuidCount++) {
|
|
GuidArray[GuidCount] = (LPGUID) Space;
|
|
Space += sizeof(GUID);
|
|
}
|
|
GuidCount = 0;
|
|
|
|
#ifdef UNICODE
|
|
if ((targv = CommandLineToArgvW(
|
|
GetCommandLineW(), // pointer to a command-line string
|
|
&argc // receives the argument count
|
|
)) == NULL) {
|
|
free(pLoggerInfo);
|
|
free(save);
|
|
if (advapidll != NULL)
|
|
FreeLibrary(advapidll);
|
|
return (GetLastError());
|
|
};
|
|
utargv = targv;
|
|
#else
|
|
targv = argv;
|
|
#endif
|
|
|
|
pFlags = &pLoggerInfo->EnableFlags;
|
|
//
|
|
// Add default flags.
|
|
//
|
|
while (--argc > 0) {
|
|
++targv;
|
|
if (**targv == '-' || **targv == '/') { // argument found
|
|
if(targv[0][0] == '/' ) targv[0][0] = '-';
|
|
if (!_tcsicmp(targv[0], _T("-start"))) {
|
|
Action = ACTION_START;
|
|
if (argc > 1) {
|
|
if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
++targv; --argc;
|
|
_tcscpy(LoggerName, targv[0]);
|
|
}
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-enable"))) {
|
|
Action = ACTION_ENABLE;
|
|
if (argc > 1) {
|
|
if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
++targv; --argc;
|
|
_tcscpy(LoggerName, targv[0]);
|
|
}
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-disable"))) {
|
|
Action = ACTION_ENABLE;
|
|
bEnable = FALSE;
|
|
if (argc > 1) {
|
|
if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
++targv; --argc;
|
|
_tcscpy(LoggerName, targv[0]);
|
|
}
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-stop"))) {
|
|
Action = ACTION_STOP;
|
|
if (argc > 1) {
|
|
if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
++targv; --argc;
|
|
_tcscpy(LoggerName, targv[0]);
|
|
}
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-update"))) {
|
|
Action = ACTION_UPDATE;
|
|
if (argc > 1) {
|
|
if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
++targv; --argc;
|
|
_tcscpy(LoggerName, targv[0]);
|
|
}
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-q"))) {
|
|
Action = ACTION_QUERY;
|
|
if (argc > 1) {
|
|
if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
++targv; --argc;
|
|
_tcscpy(LoggerName, targv[0]);
|
|
}
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-flush"))) {
|
|
Action = ACTION_FLUSH;
|
|
if (argc > 1) {
|
|
if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
++targv; --argc;
|
|
_tcscpy(LoggerName, targv[0]);
|
|
}
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-enumguid"))) {
|
|
Action = ACTION_ENUM_GUID;
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-f"))) {
|
|
if (argc > 1) {
|
|
_tcscpy(LogFileName, targv[1]);
|
|
_tcscpy(tstrLogFileName, targv[1]);
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-append"))) {
|
|
if (argc > 1) {
|
|
_tfullpath(LogFileName, targv[1], MAXSTR);
|
|
_tcscpy(tstrLogFileName, LogFileName);
|
|
++targv; --argc;
|
|
pLoggerInfo->LogFileMode |= EVENT_TRACE_FILE_MODE_APPEND;
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-guid"))) {
|
|
if (argc > 1) {
|
|
if (targv[1][0] == _T('#')) {
|
|
StringToGuid(&targv[1][1], GuidArray[0]);
|
|
++targv; --argc;
|
|
GuidCount = 1;
|
|
}
|
|
else if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
_tfullpath(GuidFile, targv[1], MAXSTR);
|
|
++targv; --argc;
|
|
GuidCount = GetGuids(GuidFile, GuidArray);
|
|
if (GuidCount < 0) {
|
|
_tprintf( _T("Error: %s does no exist\n"), GuidFile );
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
goto CleanupExit;
|
|
}
|
|
else if (GuidCount == 0){
|
|
_tprintf( _T("Error: %s is invalid\n"), GuidFile );
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
goto CleanupExit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-seq"))) {
|
|
if (argc > 1) {
|
|
pLoggerInfo->LogFileMode |= EVENT_TRACE_FILE_MODE_SEQUENTIAL;
|
|
pLoggerInfo->MaximumFileSize = _ttoi(targv[1]);
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-newfile"))) {
|
|
if (argc > 1) {
|
|
pLoggerInfo->LogFileMode |= EVENT_TRACE_FILE_MODE_NEWFILE;
|
|
pLoggerInfo->MaximumFileSize = _ttoi(targv[1]);
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-cir"))) {
|
|
if (argc > 1) {
|
|
pLoggerInfo->LogFileMode |= EVENT_TRACE_FILE_MODE_CIRCULAR;
|
|
pLoggerInfo->MaximumFileSize = _ttoi(targv[1]);
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-b"))) {
|
|
if (argc > 1) {
|
|
pLoggerInfo->BufferSize = _ttoi(targv[1]);
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-flag")) || !_tcsicmp(targv[0], _T("-flags"))) {
|
|
if (argc > 1) {
|
|
if (targv[1][1] == _T('x') || targv[1][1] == _T('X')) {
|
|
pLoggerInfo->EnableFlags |= ahextoi(targv[1]);
|
|
} else {
|
|
pLoggerInfo->EnableFlags |= _ttoi(targv[1]);
|
|
}
|
|
iFlags = pLoggerInfo->EnableFlags ; // Copy for EnableTrace
|
|
++targv; --argc;
|
|
// Do not accept flags with MSB = 1.
|
|
|
|
if (0x80000000 & pLoggerInfo->EnableFlags) {
|
|
_tprintf(_T("Invalid Flags: 0x%0X(%d.)\n"),
|
|
pLoggerInfo->EnableFlags, pLoggerInfo->EnableFlags);
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
goto CleanupExit;
|
|
}
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-min"))) {
|
|
if (argc > 1) {
|
|
pLoggerInfo->MinimumBuffers = _ttoi(targv[1]);
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-max"))) {
|
|
if (argc > 1) {
|
|
pLoggerInfo->MaximumBuffers = _ttoi(targv[1]);
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-level"))) {
|
|
if (argc > 1) {
|
|
iLevel = _ttoi(targv[1]);
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-ft"))) {
|
|
if (argc > 1) {
|
|
pLoggerInfo->FlushTimer = _ttoi(targv[1]);
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-um"))) {
|
|
pLoggerInfo->LogFileMode |= EVENT_TRACE_PRIVATE_LOGGER_MODE;
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-paged"))) {
|
|
pLoggerInfo->LogFileMode |= EVENT_TRACE_USE_PAGED_MEMORY;
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-rt"))) {
|
|
pLoggerInfo->LogFileMode |= EVENT_TRACE_REAL_TIME_MODE;
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-age"))) {
|
|
if (argc > 1) {
|
|
pLoggerInfo->AgeLimit = _ttoi(targv[1]);
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-l"))) {
|
|
Action = ACTION_LIST;
|
|
bKill = FALSE;
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-x"))) {
|
|
Action = ACTION_LIST;
|
|
bKill = TRUE;
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-xf"))) {
|
|
Action = ACTION_LIST;
|
|
bKill = TRUE;
|
|
bForceKill = TRUE ;
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-noprocess"))) {
|
|
bProcess = FALSE;
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-nothread"))) {
|
|
bThread = FALSE;
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-nodisk"))) {
|
|
bDisk = FALSE;
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-nonet"))) {
|
|
bNetwork = FALSE;
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-fio"))) {
|
|
if (pFlags == &pLoggerInfo->EnableFlags) {
|
|
*pFlags |= EVENT_TRACE_FLAG_DISK_FILE_IO;
|
|
}
|
|
else {
|
|
_tprintf(_T("Option -fio cannot be used with -eflags. Ignored\n"));
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-pf"))) {
|
|
if (pFlags == &pLoggerInfo->EnableFlags) {
|
|
*pFlags |= EVENT_TRACE_FLAG_MEMORY_PAGE_FAULTS;
|
|
}
|
|
else {
|
|
_tprintf(_T("Option -pf cannot be used with -eflags. Ignored\n"));
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-hf"))) {
|
|
if (pFlags == &pLoggerInfo->EnableFlags) {
|
|
*pFlags |= EVENT_TRACE_FLAG_MEMORY_HARD_FAULTS;
|
|
}
|
|
else {
|
|
_tprintf(_T("Option -hf cannot be used with -eflags. Ignored\n"));
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-img"))) {
|
|
if (pFlags == &pLoggerInfo->EnableFlags) {
|
|
*pFlags |= EVENT_TRACE_FLAG_IMAGE_LOAD;
|
|
}
|
|
else {
|
|
_tprintf(_T("Option -img cannot be used with -eflags. Ignored\n"));
|
|
}
|
|
}
|
|
else if (!_tcsicmp(targv[0], _T("-cm"))) {
|
|
if (pFlags == &pLoggerInfo->EnableFlags) {
|
|
*pFlags |= EVENT_TRACE_FLAG_REGISTRY;
|
|
}
|
|
else {
|
|
_tprintf(_T("Option -cm cannot be used with -eflags. Ignored\n"));
|
|
}
|
|
}
|
|
else if ( targv[0][1] == 'h' || targv[0][1] == 'H' || targv[0][1] == '?'){
|
|
Action = ACTION_HELP;
|
|
PrintHelpMessage();
|
|
goto CleanupExit;
|
|
}
|
|
else Action = ACTION_UNDEFINED;
|
|
}
|
|
else {
|
|
_tprintf(_T("Invalid option given: %s\n"), targv[0]);
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
goto CleanupExit;
|
|
}
|
|
}
|
|
if (!_tcscmp(LoggerName, NT_LOGGER)) {
|
|
if (pFlags == &pLoggerInfo->EnableFlags) {
|
|
if (bProcess)
|
|
*pFlags |= EVENT_TRACE_FLAG_PROCESS;
|
|
if (bThread)
|
|
*pFlags |= EVENT_TRACE_FLAG_THREAD;
|
|
if (bDisk)
|
|
*pFlags |= EVENT_TRACE_FLAG_DISK_IO;
|
|
if (bNetwork)
|
|
*pFlags |= EVENT_TRACE_FLAG_NETWORK_TCPIP;
|
|
}
|
|
|
|
pLoggerInfo->Wnode.Guid = SystemTraceControlGuid; // defaults to OS
|
|
specialLogger = 1;
|
|
}
|
|
if ( !(pLoggerInfo->LogFileMode & EVENT_TRACE_REAL_TIME_MODE) ) {
|
|
if (specialLogger != 3 && _tcslen(LogFileName) <= 0 && Action == ACTION_START) {
|
|
_tcscpy(LogFileName, DEFAULT_LOGFILE_NAME); // for now...
|
|
_tcscpy(tstrLogFileName, DEFAULT_LOGFILE_NAME);
|
|
}
|
|
}
|
|
|
|
switch (Action) {
|
|
case ACTION_START:
|
|
{
|
|
|
|
if (pLoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
|
|
if (GuidCount != 1) {
|
|
_tprintf(_T("Need exactly one GUID for PRIVATE loggers\n"));
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
pLoggerInfo->Wnode.Guid = *GuidArray[0];
|
|
}
|
|
Status = StartTrace(&LoggerHandle, LoggerName, pLoggerInfo);
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
_tprintf(_T("Could not start logger: %s\n")
|
|
_T("Operation Status: %uL\n")
|
|
_T("%s\n"),
|
|
LoggerName,
|
|
Status,
|
|
DecodeStatus(Status));
|
|
|
|
break;
|
|
}
|
|
_tprintf(_T("Logger Started...\n"));
|
|
|
|
case ACTION_ENABLE:
|
|
|
|
if (Action == ACTION_ENABLE ){
|
|
|
|
if (pLoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE)
|
|
{
|
|
if (GuidCount != 1)
|
|
{
|
|
_tprintf(_T("Need one GUID for PRIVATE loggers\n"));
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
pLoggerInfo->Wnode.Guid = *GuidArray[0];
|
|
}
|
|
|
|
Status = ControlTrace((TRACEHANDLE) 0, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_QUERY);
|
|
if( Status != ERROR_SUCCESS ){
|
|
_tprintf( _T("ERROR: Logger not started\n")
|
|
_T("Operation Status: %uL\n")
|
|
_T("%s\n"),
|
|
Status,
|
|
DecodeStatus(Status));
|
|
break;
|
|
}
|
|
LoggerHandle = pLoggerInfo->Wnode.HistoricalContext;
|
|
}
|
|
|
|
if ( (GuidCount > 0) && (specialLogger == 0)) {
|
|
_tprintf(_T("Enabling trace to logger %d\n"), LoggerHandle);
|
|
for (i = 0; i < (ULONG)GuidCount; i++) {
|
|
Status = EnableTrace (
|
|
bEnable,
|
|
iFlags,
|
|
iLevel,
|
|
GuidArray[i],
|
|
LoggerHandle);
|
|
|
|
//
|
|
// If some of the Guids can not be enabled, consider it a benign
|
|
// failure. Print a warning message and continue.
|
|
//
|
|
if (Status == ERROR_INVALID_OPERATION) {
|
|
_tprintf(_T("WARNING: Could not enable some guids.\n"));
|
|
_tprintf(_T("Check your Guids file\n"));
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
_tprintf(_T("ERROR: Failed to enable Guid [%d]...\n"), i);
|
|
_tprintf(_T("Operation Status: %uL\n"), Status);
|
|
_tprintf(_T("%s\n"),DecodeStatus(Status));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (GuidCount > 0) {
|
|
_tprintf(_T("ERROR: System Logger does not accept application guids...\n"));
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ACTION_STOP :
|
|
LoggerHandle = (TRACEHANDLE) 0;
|
|
Status = ERROR_SUCCESS;
|
|
if (pLoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
|
|
if (GuidCount != 1) {
|
|
_tprintf(_T("Need exactly one GUID for PRIVATE loggers\n"));
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
pLoggerInfo->Wnode.Guid = *GuidArray[0];
|
|
}
|
|
if (specialLogger != 0) {
|
|
if (pLoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
|
|
Status = ControlTrace(LoggerHandle, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_QUERY);
|
|
if (Status != ERROR_SUCCESS)
|
|
break;
|
|
LoggerHandle = pLoggerInfo->Wnode.HistoricalContext;
|
|
Status = EnableTrace( FALSE,
|
|
EVENT_TRACE_PRIVATE_LOGGER_MODE,
|
|
0,
|
|
GuidArray[0],
|
|
LoggerHandle );
|
|
}
|
|
else {
|
|
Status = ControlTrace(LoggerHandle, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_QUERY);
|
|
if (Status == ERROR_WMI_INSTANCE_NOT_FOUND)
|
|
break;
|
|
LoggerHandle = pLoggerInfo->Wnode.HistoricalContext;
|
|
|
|
for (i = 0; i < (ULONG)GuidCount; i++) {
|
|
Status = EnableTrace( FALSE,
|
|
0,
|
|
0,
|
|
GuidArray[i],
|
|
LoggerHandle);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
Status = ControlTrace(LoggerHandle, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_STOP);
|
|
break;
|
|
|
|
case ACTION_LIST :
|
|
{
|
|
ULONG i, returnCount ;
|
|
ULONG SizeNeeded;
|
|
PEVENT_TRACE_PROPERTIES pLoggerInfo[MAXIMUM_LOGGERS];
|
|
PEVENT_TRACE_PROPERTIES pStorage;
|
|
PVOID Storage;
|
|
|
|
SizeNeeded = MAXIMUM_LOGGERS * (sizeof(EVENT_TRACE_PROPERTIES)
|
|
+ 2 * MAXSTR * sizeof(TCHAR));
|
|
|
|
Storage = malloc(SizeNeeded);
|
|
if (Storage == NULL) {
|
|
Status = ERROR_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
RtlZeroMemory(Storage, SizeNeeded);
|
|
|
|
pStorage = (PEVENT_TRACE_PROPERTIES)Storage;
|
|
for (i=0; i<MAXIMUM_LOGGERS; i++) {
|
|
pStorage->Wnode.BufferSize = sizeof(EVENT_TRACE_PROPERTIES)
|
|
+ 2 * MAXSTR * sizeof(TCHAR);
|
|
pStorage->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES)
|
|
+ MAXSTR * sizeof(TCHAR);
|
|
pStorage->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
|
pLoggerInfo[i] = pStorage;
|
|
pStorage = (PEVENT_TRACE_PROPERTIES) (
|
|
(char*)pStorage +
|
|
pStorage->Wnode.BufferSize);
|
|
}
|
|
|
|
Status = QueryAllTraces(pLoggerInfo,
|
|
MAXIMUM_LOGGERS,
|
|
& returnCount);
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
for (j= 0; j < returnCount; j++)
|
|
{
|
|
LPTSTR LoggerName;
|
|
TCHAR asked = _T('?') ;
|
|
BOOL StatusPrint = FALSE ;
|
|
if (bKill)
|
|
{
|
|
|
|
LoggerName = (LPTSTR) ((char*)pLoggerInfo[j] +
|
|
pLoggerInfo[j]->LoggerNameOffset);
|
|
if (!bForceKill) {
|
|
while (!(asked == _T('y')) && !(asked == _T('n'))) {
|
|
_tprintf(_T("Do you want to kill Logger \"%s\" (Y or N)?"),LoggerName);
|
|
_tscanf(_T(" %c"),&asked);
|
|
if (asked == _T('Y')) {
|
|
asked = _T('y') ;
|
|
} else if (asked == _T('N')) {
|
|
asked = _T('n') ;
|
|
}
|
|
}
|
|
} else {
|
|
asked = _T('y');
|
|
}
|
|
if (asked == _T('y')) {
|
|
if (!IsEqualGUID(& pLoggerInfo[j]->Wnode.Guid,
|
|
& SystemTraceControlGuid))
|
|
{
|
|
LoggerHandle = pLoggerInfo[j]->Wnode.HistoricalContext;
|
|
Status = EnableTrace(
|
|
FALSE,
|
|
(pLoggerInfo[j]->LogFileMode &
|
|
EVENT_TRACE_PRIVATE_LOGGER_MODE)
|
|
? (EVENT_TRACE_PRIVATE_LOGGER_MODE)
|
|
: (0),
|
|
0,
|
|
& pLoggerInfo[j]->Wnode.Guid,
|
|
LoggerHandle);
|
|
}
|
|
Status = ControlTrace((TRACEHANDLE) 0,
|
|
LoggerName,
|
|
pLoggerInfo[j],
|
|
EVENT_TRACE_CONTROL_STOP);
|
|
_tprintf(_T("Logger \"%s\" has been killed\n"),LoggerName);
|
|
StatusPrint = TRUE ;
|
|
} else {
|
|
_tprintf(_T("Logger \"%s\" has not been killed, current Status is\n"),LoggerName);
|
|
StatusPrint = FALSE ;
|
|
}
|
|
}
|
|
PrintLoggerStatus(pLoggerInfo[j],
|
|
Status,
|
|
StatusPrint);
|
|
_tprintf(_T("\n"));
|
|
}
|
|
}
|
|
|
|
i = 0;
|
|
free(Storage);
|
|
break;
|
|
}
|
|
|
|
case ACTION_UPDATE :
|
|
case ACTION_FLUSH :
|
|
case ACTION_QUERY :
|
|
if (pLoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
|
|
if (GuidCount != 1) {
|
|
_tprintf(_T("Need exactly one GUID for PRIVATE loggers\n"));
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
pLoggerInfo->Wnode.Guid = *GuidArray[0];
|
|
}
|
|
if (Action == ACTION_QUERY) {
|
|
Status = ControlTrace(LoggerHandle, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_QUERY);
|
|
}
|
|
|
|
else if (Action == ACTION_UPDATE) {
|
|
Status = ControlTrace(LoggerHandle, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_UPDATE);
|
|
}
|
|
else if (Action == ACTION_FLUSH) {
|
|
// Since FlushTrace is not implemented on Win2K, use the function pointer
|
|
// loaded from advapi32.dll separately.
|
|
// Originally, this block had one line:
|
|
// Status = FlushTrace(LoggerHandle, LoggerName, pLoggerInfo);
|
|
if (FuncArray[FUNC_FLUSH_TRACE] == NULL) {
|
|
_tprintf(_T("Flush Trace is not supported on this system\n"));
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
Status = (ULONG)(*FuncArray[FUNC_FLUSH_TRACE])(LoggerHandle, LoggerName, pLoggerInfo);
|
|
}
|
|
|
|
break;
|
|
|
|
case ACTION_ENUM_GUID:
|
|
{
|
|
ULONG i;
|
|
ULONG PropertyArrayCount=10;
|
|
PTRACE_GUID_PROPERTIES *GuidPropertiesArray;
|
|
ULONG GuidCount;
|
|
ULONG SizeStorage;
|
|
PVOID StorageNeeded;
|
|
PTRACE_GUID_PROPERTIES CleanStorage;
|
|
TCHAR str[MAXSTR];
|
|
|
|
// Since EnumTraceGuids is not implemented on Win2K, use the function pointer
|
|
// loaded from advapi32.dll separately.
|
|
if (FuncArray[FUNC_ENUM_TRACE_GUIDS] == NULL) {
|
|
_tprintf(_T("Enumerating trace GUIDS is not supported on this system\n"));
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
Retry:
|
|
SizeStorage = PropertyArrayCount * (sizeof(TRACE_GUID_PROPERTIES) + sizeof(PTRACE_GUID_PROPERTIES));
|
|
StorageNeeded = malloc(SizeStorage);
|
|
if (StorageNeeded== NULL) {
|
|
Status = ERROR_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
RtlZeroMemory(StorageNeeded, SizeStorage);
|
|
GuidPropertiesArray = (PTRACE_GUID_PROPERTIES *)StorageNeeded;
|
|
CleanStorage = (PTRACE_GUID_PROPERTIES)((char*)StorageNeeded + PropertyArrayCount * sizeof(PTRACE_GUID_PROPERTIES));
|
|
for (i=0; i < PropertyArrayCount; i++) {
|
|
GuidPropertiesArray[i] = CleanStorage;
|
|
CleanStorage = (PTRACE_GUID_PROPERTIES) (
|
|
(char*)CleanStorage + sizeof(TRACE_GUID_PROPERTIES)
|
|
);
|
|
}
|
|
// Use function pointer for EnumTraceGuids
|
|
Status = (ULONG)(*FuncArray[FUNC_ENUM_TRACE_GUIDS])(GuidPropertiesArray,PropertyArrayCount,&GuidCount);
|
|
if(Status == ERROR_MORE_DATA)
|
|
{
|
|
PropertyArrayCount=GuidCount;
|
|
free(StorageNeeded);
|
|
goto Retry;
|
|
|
|
}
|
|
|
|
//
|
|
// print the GUID_PROPERTIES and Free Strorage
|
|
//
|
|
|
|
_tprintf(_T(" Guid Enabled LoggerId Level Flags\n"));
|
|
_tprintf(_T("------------------------------------------------------------\n"));
|
|
for (i=0; i < GuidCount; i++) {
|
|
_tprintf(_T("%s %5s %d %d %d\n"),
|
|
GuidToString(&str[0],&GuidPropertiesArray[i]->Guid),
|
|
(GuidPropertiesArray[i]->IsEnable) ? _T("TRUE") : _T("FALSE"),
|
|
GuidPropertiesArray[i]->LoggerId,
|
|
GuidPropertiesArray[i]->EnableLevel,
|
|
GuidPropertiesArray[i]->EnableFlags
|
|
);
|
|
}
|
|
free(StorageNeeded);
|
|
}
|
|
break;
|
|
|
|
case ACTION_HELP:
|
|
PrintHelpMessage();
|
|
break;
|
|
default :
|
|
_tprintf(_T("Error: no action specified\n"));
|
|
PrintHelpMessage();
|
|
break;
|
|
}
|
|
|
|
if ((Action != ACTION_HELP) && (Action != ACTION_ENUM_GUID)
|
|
&& (Action != ACTION_UNDEFINED) && (Action != ACTION_LIST))
|
|
PrintLoggerStatus(pLoggerInfo,
|
|
Status,
|
|
PRINTSTATUS);
|
|
CleanupExit:
|
|
SetLastError(Status);
|
|
if (utargv != NULL) {
|
|
GlobalFree(utargv);
|
|
}
|
|
free(pLoggerInfo);
|
|
free(save);
|
|
if (advapidll != NULL)
|
|
FreeLibrary(advapidll);
|
|
return(Status);
|
|
}
|
|
|
|
|
|
void
|
|
PrintLoggerStatus(
|
|
IN PEVENT_TRACE_PROPERTIES LoggerInfo,
|
|
IN ULONG Status,
|
|
IN BOOL PrintStatus
|
|
)
|
|
/*++
|
|
|
|
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 returned status of the last executed command
|
|
or
|
|
the operation status of the current logger.
|
|
|
|
PrintStatus - Determines which type of status it is using.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
LPTSTR LoggerName, LogFileName;
|
|
|
|
if ((LoggerInfo->LoggerNameOffset > 0) &&
|
|
(LoggerInfo->LoggerNameOffset < LoggerInfo->Wnode.BufferSize)) {
|
|
LoggerName = (LPTSTR) ((char*)LoggerInfo +
|
|
LoggerInfo->LoggerNameOffset);
|
|
}
|
|
else LoggerName = NULL;
|
|
|
|
if ((LoggerInfo->LogFileNameOffset > 0) &&
|
|
(LoggerInfo->LogFileNameOffset < LoggerInfo->Wnode.BufferSize)) {
|
|
LogFileName = (LPTSTR) ((char*)LoggerInfo +
|
|
LoggerInfo->LogFileNameOffset);
|
|
}
|
|
else LogFileName = NULL;
|
|
|
|
if (PrintStatus) {
|
|
_tprintf(_T("Operation Status: %uL\t"), Status);
|
|
_tprintf(_T("%s\n"), DecodeStatus(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 != 0)
|
|
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,NT_LOGGER))) {
|
|
|
|
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);
|
|
}
|
|
|
|
}
|
|
|
|
LPTSTR
|
|
DecodeStatus(
|
|
IN ULONG Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Decodes WIN32 error into a string in the default language.
|
|
|
|
Arguments:
|
|
|
|
Status - The error status from the last executed command
|
|
or
|
|
the operation status of the current logger.
|
|
|
|
Return Value:
|
|
|
|
LPTSTR - String containing the decoded message.
|
|
|
|
|
|
--*/
|
|
{
|
|
memset( ErrorMsg, 0, MAXSTR );
|
|
FormatMessage(
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
Status,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
(LPTSTR) ErrorMsg,
|
|
MAXSTR,
|
|
NULL );
|
|
|
|
return ErrorMsg;
|
|
}
|
|
|
|
LONG
|
|
GetGuids(
|
|
IN LPTSTR GuidFile,
|
|
IN OUT LPGUID *GuidArray
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads GUIDs from a file and stores them in an GUID array.
|
|
|
|
Arguments:
|
|
|
|
GuidFile - The file containing GUIDs.
|
|
GuidArray - The GUID array that will have GUIDs read from the file.
|
|
|
|
Return Value:
|
|
|
|
ULONG - The number of GUIDs processed.
|
|
|
|
|
|
--*/
|
|
{
|
|
FILE *f;
|
|
TCHAR line[MAXSTR], arg[MAXSTR];
|
|
LPGUID Guid;
|
|
int i, n;
|
|
|
|
f = _tfopen((TCHAR*)GuidFile, _T("r"));
|
|
|
|
if (f == NULL)
|
|
return -1;
|
|
|
|
n = 0;
|
|
while ( _fgetts(line, MAXSTR, f) != NULL ) {
|
|
if (_tcslen(line) < 36)
|
|
continue;
|
|
if (line[0] == ';' ||
|
|
line[0] == '\0' ||
|
|
line[0] == '#' ||
|
|
line[0] == '/')
|
|
continue;
|
|
Guid = (LPGUID) GuidArray[n];
|
|
n ++;
|
|
|
|
_tcsncpy(arg, line, 8);
|
|
arg[8] = 0;
|
|
Guid->Data1 = ahextoi(arg);
|
|
_tcsncpy(arg, &line[9], 4);
|
|
arg[4] = 0;
|
|
Guid->Data2 = (USHORT) ahextoi(arg);
|
|
_tcsncpy(arg, &line[14], 4);
|
|
arg[4] = 0;
|
|
Guid->Data3 = (USHORT) ahextoi(arg);
|
|
|
|
for (i=0; i<2; i++) {
|
|
_tcsncpy(arg, &line[19 + (i*2)], 2);
|
|
arg[2] = 0;
|
|
Guid->Data4[i] = (UCHAR) ahextoi(arg);
|
|
}
|
|
for (i=2; i<8; i++) {
|
|
_tcsncpy(arg, &line[20 + (i*2)], 2);
|
|
arg[2] = 0;
|
|
Guid->Data4[i] = (UCHAR) ahextoi(arg);
|
|
}
|
|
}
|
|
return (ULONG)n;
|
|
}
|
|
|
|
ULONG
|
|
ahextoi(
|
|
IN TCHAR *s
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a hex string into a number.
|
|
|
|
Arguments:
|
|
|
|
s - A hex string in TCHAR.
|
|
|
|
Return Value:
|
|
|
|
ULONG - The number in the string.
|
|
|
|
|
|
--*/
|
|
{
|
|
int len;
|
|
ULONG num, base, hex;
|
|
|
|
len = _tcslen(s);
|
|
hex = 0; base = 1; num = 0;
|
|
while (--len >= 0) {
|
|
if ( (s[len] == 'x' || s[len] == 'X') &&
|
|
(s[len-1] == '0') )
|
|
break;
|
|
if (s[len] >= '0' && s[len] <= '9')
|
|
num = s[len] - '0';
|
|
else if (s[len] >= 'a' && s[len] <= 'f')
|
|
num = (s[len] - 'a') + 10;
|
|
else if (s[len] >= 'A' && s[len] <= 'F')
|
|
num = (s[len] - 'A') + 10;
|
|
else
|
|
continue;
|
|
|
|
hex += num * base;
|
|
base = base * 16;
|
|
}
|
|
return hex;
|
|
}
|
|
|
|
|
|
void
|
|
StringToGuid(
|
|
IN TCHAR *str,
|
|
IN OUT LPGUID guid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a string into a GUID.
|
|
|
|
Arguments:
|
|
|
|
str - A string in TCHAR.
|
|
guid - The pointer to a GUID that will have the converted GUID.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
{
|
|
TCHAR temp[10];
|
|
int i, n;
|
|
|
|
temp[8]=_T('\0');
|
|
_tcsncpy(temp, str, 8);
|
|
_stscanf(temp, _T("%x"), &(guid->Data1));
|
|
|
|
temp[4]=_T('\0');
|
|
_tcsncpy(temp, &str[9], 4);
|
|
_stscanf(temp, _T("%x"), &(guid->Data2));
|
|
|
|
_tcsncpy(temp, &str[14], 4);
|
|
_stscanf(temp, _T("%x"), &(guid->Data3));
|
|
|
|
temp[2]='\0';
|
|
for(i=0;i<8;i++)
|
|
{
|
|
temp[0]=str[19+((i<2)?2*i:2*i+1)]; // to accomodate the minus sign after
|
|
temp[1]=str[20+((i<2)?2*i:2*i+1)]; // the first two chars
|
|
_stscanf(temp, _T("%x"), &n); // if used more than byte alloc
|
|
guid->Data4[i]=(unsigned char)n; // causes overrun of memory
|
|
}
|
|
}
|
|
|
|
void PrintHelpMessage()
|
|
/*++
|
|
|
|
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"));
|
|
if (XP) {
|
|
_tprintf(_T("\t-flush [LoggerName] Flushes the [LoggerName] active buffers\n"));
|
|
_tprintf(_T("\t-enumguid Enumerate Registered Trace Guids\n"));
|
|
}
|
|
_tprintf(_T("\t-q [LoggerName] Query status of [LoggerName] trace session\n"));
|
|
_tprintf(_T("\t-l List all trace sessions\n"));
|
|
_tprintf(_T("\t-x Stops all active trace sessions\n"));
|
|
|
|
_tprintf(_T("\n options:\n"));
|
|
_tprintf(_T("\t-b <n> Sets buffer size to <n> Kbytes\n"));
|
|
_tprintf(_T("\t-min <n> Sets minimum buffers\n"));
|
|
_tprintf(_T("\t-max <n> Sets maximum buffers\n"));
|
|
_tprintf(_T("\t-f <name> Log to file <name>\n"));
|
|
if (XP) {
|
|
_tprintf(_T("\t-append <name> Append to file <name>\n"));
|
|
}
|
|
_tprintf(_T("\t-seq <n> Sequential logfile of up to n Mbytes\n"));
|
|
_tprintf(_T("\t-cir <n> Circular logfile of n Mbytes\n"));
|
|
if (XP) {
|
|
_tprintf(_T("\t-newfile <n> Log to a new file after every n Mbytes\n"));
|
|
}
|
|
_tprintf(_T("\t-ft <n> Set flush timer to n seconds\n"));
|
|
if (XP) {
|
|
_tprintf(_T("\t-paged Use pageable memory for buffers\n"));
|
|
}
|
|
_tprintf(_T("\t-noprocess Disable Process Start/End tracing\n"));
|
|
_tprintf(_T("\t-nothread Disable Thread Start/End tracing\n"));
|
|
_tprintf(_T("\t-nodisk Disable Disk I/O tracing\n"));
|
|
_tprintf(_T("\t-nonet Disable Network TCP/IP tracing\n"));
|
|
_tprintf(_T("\t-fio Enable file I/O tracing\n"));
|
|
_tprintf(_T("\t-pf Enable page faults tracing\n"));
|
|
_tprintf(_T("\t-hf Enable hard faults tracing\n"));
|
|
_tprintf(_T("\t-img Enable image load tracing\n"));
|
|
_tprintf(_T("\t-cm Enable registry calls tracing\n"));
|
|
_tprintf(_T("\t-um Enable Process Private tracing\n"));
|
|
_tprintf(_T("\t-guid <file> Start tracing for providers in file\n"));
|
|
_tprintf(_T("\t-rt Enable tracing in real time mode\n"));
|
|
_tprintf(_T("\t-age <n> Modify aging decay time to n minutes\n"));
|
|
_tprintf(_T("\t-level <n> Enable Level passed to the providers\n"));
|
|
_tprintf(_T("\t-flag <n> Enable Flags passed to the providers\n"));
|
|
_tprintf(_T("\n"));
|
|
_tprintf(_T("\t-h\n"));
|
|
_tprintf(_T("\t-help\n"));
|
|
_tprintf(_T("\t-? Display usage information\n"));
|
|
}
|
|
|
|
|
|
PTCHAR
|
|
GuidToString(
|
|
IN OUT PTCHAR s,
|
|
LPGUID piid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a GUID into a string.
|
|
|
|
Arguments:
|
|
|
|
s - A string in TCHAR that will have the converted GUID.
|
|
piid - The pointer to a GUID.
|
|
|
|
Return Value:
|
|
|
|
PTCHAR - The string containig the convereted GUID.
|
|
|
|
|
|
--*/
|
|
{
|
|
_stprintf(s, _T("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"),
|
|
piid->Data1, piid->Data2,
|
|
piid->Data3,
|
|
piid->Data4[0], piid->Data4[1],
|
|
piid->Data4[2], piid->Data4[3],
|
|
piid->Data4[4], piid->Data4[5],
|
|
piid->Data4[6], piid->Data4[7]);
|
|
return(s);
|
|
}
|
|
|