windows-nt/Source/XPSP1/NT/sdktools/trace/tracelog/tracelog.c

2366 lines
84 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
// begin_sdk
/*++
Copyright (c) 1997-1999 Microsoft Corporation
Module Name:
tracelog.c
Abstract:
Sample trace control program. Allows user to start, stop event tracing
// end_sdk
Author:
Jee Fung Pang (jeepang) 03-Dec-1997
Revision History:
Insung Park (insungp) 28-Nov-2000
Now tracelog can be used to set the registry keys to start or stop
GlobalLogger. Other options also works except a few (such as -enable).
e.g.
tracelog -start GlobalLogger
tracelog -stop GlobalLogger
tracelog -q GlobalLogger
However, "-start" option does not start GlobalLogger immediately. The
machine must be rebooted. "-stop" option resets the registry keys and
stop GlobalLogger.
Users can use other options to customize the GlobalLogger sessions
such as minimum and maximum buffers, buffer size, flush timer, and so on.
One catch is, if any of the enable flags is set, GlobalLogger turns into
NT Kernel Logger and its instance vanishes. Any attempt to access
GlobalLogger with its name will fail with ERROR_WMI_INSTANCE_NOT_FOUND.
"-stop" option will still reset registry keys so that the next time the
machine boots GlobalLogger will not start.
If any of the flags is set, users should access NT Kernel Logger to
control it.
Modified/updated functions include GetGlobalLoggerSettings,
SetGlobalLoggerSettings, main, PrintLoggerStatus.
Insung Park (insungp) 19-Dec-2000
Changed trace function calls so that tracelog can be used on Win2K.
FlushTrace and EnumTraceGuids are not implemented on Win2K, but they do
not stop the execution of tracelog. An attempt to use FlushTrace or
EnumTraceGuids on W2K will generate an error message.
Fixed "-flags -1" bug. tracelog does not accept any flag with MSB=1.
Insung Park (insungp) 21-Dec-2000
Added a version display.
Fixed PrintHelpMessage() so that options not available on Win2K will
not be printed. ("-paged", "-flush", "-enumguid", "-append", "-newfile",
"-eflag", "-ls", "-gs")
Cleaned up the if blocks in main() so that tracelog frees allocated
space properly before exiting regardless of error status.
// begin_sdk
--*/
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#include <stdio.h>
#include <stdlib.h>
// end_sdk
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
// begin_sdk
#include <windows.h>
#include <shellapi.h>
#include <tchar.h>
#include <wmistr.h>
#include <initguid.h>
#include <guiddef.h>
#include <evntrace.h>
#include <wmiguid.h>
// end_sdk
#include <ntwmi.h>
// begin_sdk
#define MAXSTR 1024
#define DEFAULT_LOGFILE_NAME _T("C:\\LogFile.Etl")
// end_sdk
#define GLOBAL_LOGGER _T("GlobalLogger")
#define EVENT_LOGGER _T("WMI Event Logger")
#define MAXENABLEFLAGS 10
// begin_sdk
#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
// end_sdk
#define ACTION_REMOVE 9
// begin_sdk
#define ACTION_UNDEFINED 10
#define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
#define WSTRSIZE(str) (ULONG) ( (str) ? ((PCHAR) &str[wcslen(str)] - (PCHAR)str) + sizeof(UNICODE_NULL) : 0 )
// 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.
//
// If new functions are added to evntrace.h, the following list should be updated
// as well as the array initialization routine at the beginning of main().
#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 Whistler;
void
PrintLoggerStatus(
IN PEVENT_TRACE_PROPERTIES LoggerInfo,
// end_sdk
IN ULONG GlobalLoggerStartValue,
// begin_sdk
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();
// end_sdk
ULONG
SetGlobalLoggerSettings(
IN DWORD StartValue,
IN PEVENT_TRACE_PROPERTIES LoggerInfo,
IN DWORD ClockType
);
ULONG
GetGlobalLoggerSettings(
IN OUT PEVENT_TRACE_PROPERTIES LoggerInfo,
OUT PULONG ClockType,
OUT PDWORD pdwStart
);
// begin_sdk
//
// 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);
Whistler = FALSE;
if (GetVersionEx(&OSVersion))
Whistler = (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 (Whistler) {
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);
// end_sdk
SizeNeeded += MAXENABLEFLAGS * sizeof(ULONG); // for extension enable flags
// begin_sdk
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, KERNEL_LOGGER_NAME);
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. Should consider options to control this independently
//
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]);
}
}
}
// end_sdk
else if (!_tcsicmp(targv[0], _T("-remove"))) {
Action = ACTION_REMOVE;
if (argc > 1) {
if (targv[1][0] != '-' && targv[1][0] != '/') {
++targv; --argc;
_tcscpy(LoggerName, targv[0]);
}
}
// if it is not GlobalLogger, nothing happens.
}
// begin_sdk
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) {
if (Whistler)
_tcscpy(LogFileName, targv[1]);
else
_tfullpath(LogFileName, targv[1], MAXSTR);
_tcscpy(tstrLogFileName, targv[1]);
++targv; --argc;
// _tprintf(_T("Setting log file to: %s\n"), LogFileName);
}
}
else if (!_tcsicmp(targv[0], _T("-append"))) {
// _tprintf(_T("Appending log file: %s\n"), LogFileName);
pLoggerInfo->LogFileMode |= EVENT_TRACE_FILE_MODE_APPEND;
}
else if (!_tcsicmp(targv[0], _T("-prealloc"))) {
// _tprintf(_T("Preallocating log file: %s\n"), LogFileName);
pLoggerInfo->LogFileMode |= EVENT_TRACE_FILE_MODE_PREALLOCATE;
}
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;
// _tprintf(_T("Getting guids from %s\n"), GuidFile);
GuidCount = GetGuids(GuidFile, GuidArray);
if (GuidCount < 0) {
_tprintf( _T("Error: %s does no exist\n"), GuidFile );
}
else if (GuidCount == 0){
_tprintf( _T("Error: %s is invalid\n"), GuidFile );
Status = ERROR_INVALID_PARAMETER;
goto CleanupExit;
}
}
}
}
// end_sdk
else if (!_tcsicmp(targv[0], _T("-UsePerfCounter"))) {
pLoggerInfo->Wnode.ClientContext = 1;
}
else if (!_tcsicmp(targv[0], _T("-UseSystemTime"))) {
pLoggerInfo->Wnode.ClientContext = 2;
}
else if (!_tcsicmp(targv[0], _T("-UseCPUCycle"))) {
pLoggerInfo->Wnode.ClientContext = 3;
}
// begin_sdk
else if (!_tcsicmp(targv[0], _T("-seq"))) {
if (argc > 1) {
pLoggerInfo->LogFileMode |= EVENT_TRACE_FILE_MODE_SEQUENTIAL;
pLoggerInfo->MaximumFileSize = _ttoi(targv[1]);
++targv; --argc;
// _tprintf(_T("Setting maximum sequential logfile size to: %d\n"),
// pLoggerInfo->MaximumFileSize);
}
}
else if (!_tcsicmp(targv[0], _T("-newfile"))) {
if (argc > 1) {
pLoggerInfo->LogFileMode |= EVENT_TRACE_FILE_MODE_NEWFILE;
pLoggerInfo->MaximumFileSize = _ttoi(targv[1]);
++targv; --argc;
// _tprintf(_T("Setting maximum logfile size to: %d\n"),
// pLoggerInfo->MaximumFileSize);
}
}
else if (!_tcsicmp(targv[0], _T("-cir"))) {
if (argc > 1) {
pLoggerInfo->LogFileMode |= EVENT_TRACE_FILE_MODE_CIRCULAR;
pLoggerInfo->MaximumFileSize = _ttoi(targv[1]);
++targv; --argc;
// _tprintf(_T("Setting maximum circular logfile size to: %d\n"),
// pLoggerInfo->MaximumFileSize);
}
}
else if (!_tcsicmp(targv[0], _T("-b"))) {
if (argc > 1) {
pLoggerInfo->BufferSize = _ttoi(targv[1]);
++targv; --argc;
// _tprintf(_T("Changing buffer size to %d\n"),
// pLoggerInfo->BufferSize);
}
}
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;
}
// _tprintf(_T("Setting logger flags to 0x%0X(%d.)\n"),
// pLoggerInfo->EnableFlags, pLoggerInfo->EnableFlags );
}
}
// end_sdk
else if (!_tcsicmp(targv[0], _T("-eflag"))) {
if (argc > 2) {
USHORT nFlag = (USHORT) _ttoi(targv[1]);
USHORT i, offset;
PTRACE_ENABLE_FLAG_EXTENSION FlagExt;
++targv; --argc;
if (nFlag > MAXENABLEFLAGS || nFlag < 1) {
_tprintf(_T("Error: Invalid number of enable flags\n"));
Status = ERROR_INVALID_PARAMETER;
goto CleanupExit;
}
offset = (USHORT)
(SizeNeeded - (sizeof(ULONG) * MAXENABLEFLAGS));
pLoggerInfo->EnableFlags = EVENT_TRACE_FLAG_EXTENSION;
FlagExt = (PTRACE_ENABLE_FLAG_EXTENSION)
&pLoggerInfo->EnableFlags;
FlagExt->Offset = offset;
FlagExt->Length = (UCHAR) nFlag;
pFlags = (PULONG) ( offset + (PCHAR) pLoggerInfo );
for (i=0; i<nFlag && argc > 1; i++) {
if (targv[1][0] == '/' || targv[1][0] == '-') {
// Correct the number of eflags when the user
// types an incorrect number.
// However, this does not work if the next
// argument is Logger Name.
break;
}
pFlags[i] = ahextoi(targv[1]);
++targv; --argc;
// _tprintf(_T("Setting logger flags to 0x%0X(%d.)\n"),
// pFlags[i], pFlags[i] );
}
nFlag = i;
for ( ; i < MAXENABLEFLAGS; i++) {
pFlags[i] = 0;
}
if (FlagExt->Length != (UCHAR)nFlag) {
// _tprintf(_T("Correcting the number of eflags to %d\n"), i),
FlagExt->Length = (UCHAR)nFlag;
}
}
}
else if (!_tcsicmp(targv[0], _T("-pids"))) {
if (argc > 2) {
USHORT nFlag = (USHORT) _ttoi(targv[1]);
USHORT i, offset;
PTRACE_ENABLE_FLAG_EXTENSION FlagExt;
++targv; --argc;
if (nFlag > MAXENABLEFLAGS || nFlag < 1) {
_tprintf(_T("Error: Invalid number of enable flags\n"));
Status = ERROR_INVALID_PARAMETER;
goto CleanupExit;
}
offset = (USHORT)
(SizeNeeded - (sizeof(ULONG) * MAXENABLEFLAGS));
pLoggerInfo->EnableFlags = EVENT_TRACE_FLAG_EXTENSION;
FlagExt = (PTRACE_ENABLE_FLAG_EXTENSION)
&pLoggerInfo->EnableFlags;
FlagExt->Offset = offset;
FlagExt->Length = (UCHAR) nFlag;
pFlags = (PULONG) ( offset + (PCHAR) pLoggerInfo );
for (i=0; i<nFlag && argc > 1; i++) {
if (targv[1][0] == '/' || targv[1][0] == '-') {
// Correct the number of eflags when the user
// types an incorrect number.
// However, this does not work if the next
// argument is Logger Name.
break;
}
pFlags[i] = _ttol((PTCHAR)targv[1]);
++targv; --argc;
// _tprintf(_T("Setting logger flags to 0x%0X(%d.)\n"),
// pFlags[i], pFlags[i] );
}
nFlag = i;
for ( ; i < MAXENABLEFLAGS; i++) {
pFlags[i] = 0;
}
if (FlagExt->Length != (UCHAR)nFlag) {
// _tprintf(_T("Correcting the number of eflags to %d\n"), i),
FlagExt->Length = (UCHAR)nFlag;
}
}
}
else if (!_tcsicmp(targv[0],_T("-ls"))) {
pLoggerInfo->LogFileMode |= EVENT_TRACE_USE_LOCAL_SEQUENCE ;
}
else if (!_tcsicmp(targv[0],_T("-gs"))) {
pLoggerInfo->LogFileMode |= EVENT_TRACE_USE_GLOBAL_SEQUENCE ;
}
// begin_sdk
else if (!_tcsicmp(targv[0], _T("-min"))) {
if (argc > 1) {
pLoggerInfo->MinimumBuffers = _ttoi(targv[1]);
++targv; --argc;
// _tprintf(_T("Changing Minimum Number of Buffers to %d\n"),
// pLoggerInfo->MinimumBuffers);
}
}
else if (!_tcsicmp(targv[0], _T("-max"))) {
if (argc > 1) {
pLoggerInfo->MaximumBuffers = _ttoi(targv[1]);
++targv; --argc;
// _tprintf(_T("Changing Maximum Number of Buffers to %d\n"),
// pLoggerInfo->MaximumBuffers);
}
}
else if (!_tcsicmp(targv[0], _T("-level"))) {
if (argc > 1) {
iLevel = _ttoi(targv[1]);
++targv; --argc;
// _tprintf(_T("Setting tracing level to %d\n"), iLevel);
}
}
else if (!_tcsicmp(targv[0], _T("-ft"))) {
if (argc > 1) {
pLoggerInfo->FlushTimer = _ttoi(targv[1]);
++targv; --argc;
// _tprintf(_T("Setting buffer flush timer to %d seconds\n"),
// pLoggerInfo->FlushTimer);
}
}
else if (!_tcsicmp(targv[0], _T("-um"))) {
pLoggerInfo->LogFileMode |= EVENT_TRACE_PRIVATE_LOGGER_MODE;
// _tprintf(_T("Setting Private Logger Flags\n"));
}
else if (!_tcsicmp(targv[0], _T("-paged"))) {
pLoggerInfo->LogFileMode |= EVENT_TRACE_USE_PAGED_MEMORY;
// _tprintf(_T("Setting Paged Memory Flag\n"));
}
else if (!_tcsicmp(targv[0], _T("-rt"))) {
pLoggerInfo->LogFileMode |= EVENT_TRACE_REAL_TIME_MODE;
// _tprintf(_T("Setting real time mode\n"));
// end_sdk
if (argc > 1) {
if (targv[1][0] != '-' && targv[1][0] != '/') {
++targv; --argc;
if (targv[0][0] == 'b')
pLoggerInfo->LogFileMode |= EVENT_TRACE_BUFFERING_MODE;
}
}
// begin_sdk
}
else if (!_tcsicmp(targv[0], _T("-age"))) {
if (argc > 1) {
pLoggerInfo->AgeLimit = _ttoi(targv[1]);
++targv; --argc;
// _tprintf(_T("Changing Aging Decay Time to %d\n"),
// pLoggerInfo->AgeLimit);
}
}
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 { // get here if "-" or "/" given
_tprintf(_T("Invalid option given: %s\n"), targv[0]);
Status = ERROR_INVALID_PARAMETER;
goto CleanupExit;
}
}
if (!_tcscmp(LoggerName, KERNEL_LOGGER_NAME)) {
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;
}
// end_sdk
if (!_tcscmp(LoggerName, GLOBAL_LOGGER)) {
pLoggerInfo->Wnode.Guid = GlobalLoggerGuid;
specialLogger = 3;
}
else if (!_tcscmp(LoggerName, EVENT_LOGGER)) {
pLoggerInfo->Wnode.Guid = WmiEventLoggerGuid;
specialLogger = 2;
}
// begin_sdk
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];
}
if (pLoggerInfo->LogFileMode & EVENT_TRACE_FILE_MODE_PREALLOCATE &&
pLoggerInfo->MaximumFileSize == 0) {
_tprintf(_T("Need file size for preallocated log file\n"));
Status = ERROR_INVALID_PARAMETER;
break;
}
// end_sdk
if (specialLogger == 3) { // Global Logger
Status = SetGlobalLoggerSettings(1L, pLoggerInfo, pLoggerInfo->Wnode.ClientContext);
if (Status != ERROR_SUCCESS)
break;
Status = GetGlobalLoggerSettings(pLoggerInfo, &pLoggerInfo->Wnode.ClientContext, &GlobalLoggerStartValue);
break;
}
// begin_sdk
if(pLoggerInfo->EnableFlags & EVENT_TRACE_FLAG_EXTENSION){
if(IsEqualGUID(&CritSecGuid,GuidArray[0]) ||
IsEqualGUID(&HeapGuid,GuidArray[0])){
pLoggerInfo->Wnode.HistoricalContext = iLevel;
}
}
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 ){
if( Status != ERROR_SUCCESS ){
if( IsEqualGUID(&HeapGuid,&pLoggerInfo->Wnode.Guid)
|| IsEqualGUID(&CritSecGuid,&pLoggerInfo->Wnode.Guid)
){
//do nothing
} else {
_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 the Guid can not be enabled, it is a benign
// failure. Print Warning message and continue.
//
if (Status == 4317) {
_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];
}
// end_sdk
if (specialLogger == 3)
Status = GetGlobalLoggerSettings(pLoggerInfo, &pLoggerInfo->Wnode.ClientContext, &GlobalLoggerStartValue);
// begin_sdk
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;
// end_sdk
case ACTION_REMOVE :
if (specialLogger == 3) { // Global Logger
Status = SetGlobalLoggerSettings(0L, pLoggerInfo, pLoggerInfo->Wnode.ClientContext);
if (Status != ERROR_SUCCESS)
break;
Status = GetGlobalLoggerSettings(pLoggerInfo, &pLoggerInfo->Wnode.ClientContext, &GlobalLoggerStartValue);
if (Status != ERROR_SUCCESS)
break;
}
break;
// begin_sdk
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],
// end_sdk
0,
// begin_sdk
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) {
// end_sdk
if (specialLogger == 3) {
Status = GetGlobalLoggerSettings(pLoggerInfo, &pLoggerInfo->Wnode.ClientContext, &GlobalLoggerStartValue);
}
// begin_sdk
Status = ControlTrace(LoggerHandle, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_QUERY);
}
else if (Action == ACTION_UPDATE) {
// end_sdk
if (specialLogger == 3) {
Status = GetGlobalLoggerSettings(pLoggerInfo, &pLoggerInfo->Wnode.ClientContext, &GlobalLoggerStartValue);
}
// begin_sdk
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,
// end_sdk
GlobalLoggerStartValue,
// begin_sdk
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,
// end_sdk
IN ULONG GlobalLoggerStartValue,
// begin_sdk
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.
// end_sdk
GlobalLoggerStartValue - The Start value for GlobalLogger (not used if it is
not GlobalLogger).
// begin_sdk
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);
// end_sdk
if (LoggerName == NULL || !_tcscmp(LoggerName, GLOBAL_LOGGER)) {
// Logger ID
_tprintf(_T("Status: %s\n"),
GlobalLoggerStartValue ?
_T("Registry set to start") : _T("Registry set to stop"));
_tprintf(_T("Logger Id: %I64x\n"), LoggerInfo->Wnode.HistoricalContext);
_tprintf(_T("Logger Thread Id: %p\n"), LoggerInfo->LoggerThreadId);
if (LoggerInfo->BufferSize == 0)
_tprintf(_T("Buffer Size: default value\n"));
else
_tprintf(_T("Buffer Size: %d Kb\n"), LoggerInfo->BufferSize);
if (LoggerInfo->MaximumBuffers == 0)
_tprintf(_T("Maximum Buffers: default value\n"));
else
_tprintf(_T("Maximum Buffers: %d\n"), LoggerInfo->MaximumBuffers);
if (LoggerInfo->MinimumBuffers == 0)
_tprintf(_T("Minimum Buffers: default value\n"));
else
_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->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))) {
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 || _tcslen(LogFileName) == 0) {
_tprintf(_T("Log Filename: default location\n"));
_tprintf(_T(" %%SystemRoot%%\\System32\\LogFiles\\WMI\\trace.log\n"));
}
else
_tprintf(_T("Log Filename: %s\n"), LogFileName);
if (LoggerInfo->LogFileMode & EVENT_TRACE_USE_LOCAL_SEQUENCE) {
_tprintf(_T("Local Sequence numbers in use\n"));
}
else if (LoggerInfo->LogFileMode & EVENT_TRACE_USE_GLOBAL_SEQUENCE) {
_tprintf(_T("Global Sequence numbers in use\n"));
}
}
else {
// begin_sdk
_tprintf(_T("Logger Id: %I64x\n"), LoggerInfo->Wnode.HistoricalContext);
_tprintf(_T("Logger Thread Id: %p\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"));
// end_sdk
if (LoggerInfo->LogFileMode & EVENT_TRACE_BUFFERING_MODE) {
_tprintf(_T(": buffering only"));
}
// begin_sdk
_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))) {
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);
}
// end_sdk
if (LoggerInfo->LogFileMode & EVENT_TRACE_USE_LOCAL_SEQUENCE) {
_tprintf(_T("Local Sequence numbers in use\n"));
}
else if (LoggerInfo->LogFileMode & EVENT_TRACE_USE_GLOBAL_SEQUENCE) {
_tprintf(_T("Global Sequence numbers in use\n"));
}
}
// begin_sdk
}
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
DisplayVersionInfo()
/*++
Routine Description:
prints out a version information.
Arguments:
None.
Return Value:
None.
--*/
{
TCHAR buffer[512];
TCHAR strProgram[MAXSTR];
DWORD dw;
BYTE* pVersionInfo;
LPTSTR pVersion = NULL;
LPTSTR pProduct = NULL;
LPTSTR pCopyRight = NULL;
dw = GetModuleFileName(NULL, strProgram, MAXSTR);
if( dw>0 ){
dw = GetFileVersionInfoSize( strProgram, &dw );
if( dw > 0 ){
pVersionInfo = (BYTE*)malloc(dw);
if( NULL != pVersionInfo ){
if(GetFileVersionInfo( strProgram, 0, dw, pVersionInfo )){
LPDWORD lptr = NULL;
VerQueryValue( pVersionInfo, _T("\\VarFileInfo\\Translation"), (void**)&lptr, (UINT*)&dw );
if( lptr != NULL ){
_stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("ProductVersion") );
VerQueryValue( pVersionInfo, buffer, (void**)&pVersion, (UINT*)&dw );
_stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("OriginalFilename") );
VerQueryValue( pVersionInfo, buffer, (void**)&pProduct, (UINT*)&dw );
_stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("LegalCopyright") );
VerQueryValue( pVersionInfo, buffer, (void**)&pCopyRight, (UINT*)&dw );
}
if( pProduct != NULL && pVersion != NULL && pCopyRight != NULL ){
_tprintf( _T("\nMicrosoft (R) %s (%s)\n%s\n\n"), pProduct, pVersion, pCopyRight );
}
}
free( pVersionInfo );
}
}
}
}
void PrintHelpMessage()
/*++
Routine Description:
prints out a help message.
Arguments:
None.
Return Value:
None.
--*/
{
// end_sdk
DisplayVersionInfo();
// begin_sdk
_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 (Whistler)
_tprintf(_T("\t-flush [LoggerName] Flushes the [LoggerName] active buffers\n"));
// end_sdk
_tprintf(_T("\t-remove GlobalLogger Removes registry keys that activate GlobalLogger\n"));
// begin_sdk
if (Whistler)
_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 (Whistler) {
_tprintf(_T("\t-append Append to file\n"));
_tprintf(_T("\t-prealloc Pre-allocate\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 (Whistler)
_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 (Whistler)
_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"));
// end_sdk
if (Whistler) {
_tprintf(_T("\t-eflag <n> <flag...> Enable flags (several) to providers\n"));
_tprintf(_T("\t-ls Generate Local Sequence Numbers\n"));
_tprintf(_T("\t-gs Generate Global Squence Numbers\n"));
_tprintf(_T("\t-pids <n> <pid1 pid2 ... >\n"));
_tprintf(_T("\t Tracing for Heap and Crit Sect for different process\n"));
}
// begin_sdk
_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);
}
// end_sdk
LPCWSTR cszGlobalLoggerKey = L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\WMI\\GlobalLogger";
LPCWSTR cszStartValue = L"Start";
LPCWSTR cszBufferSizeValue = L"BufferSize";
LPCWSTR cszMaximumBufferValue = L"MaximumBuffers";
LPCWSTR cszMinimumBufferValue = L"MinimumBuffers";
LPCWSTR cszFlushTimerValue = L"FlushTimer";
LPCWSTR cszFileNameValue = L"FileName";
LPCWSTR cszEnableKernelValue = L"EnableKernelFlags";
LPCWSTR cszClockTypeValue = L"ClockType";
//
// GlobalLogger functions
//
ULONG
SetGlobalLoggerSettings(
IN DWORD StartValue,
IN PEVENT_TRACE_PROPERTIES LoggerInfo,
IN DWORD ClockType
)
/*++
Since it is a standalone utility, there is no need for extensive comments.
Routine Description:
Depending on the value given in "StartValue", it sets or resets event
trace registry. If the StartValue is 0 (Global logger off), it deletes
all the keys (that the user may have set previsouly).
Users are allowed to set or reset individual keys using this function,
but only when "-start GlobalLogger" is used.
The section that uses non NTAPIs is not guaranteed to work.
Arguments:
StartValue - The "Start" value to be set in the registry.
0: Global logger off
1: Global logger on
LoggerInfo - The poniter to the resident EVENT_TRACE_PROPERTIES instance.
whose members are used to set registry keys.
ClockType - The type of the clock to be set.
Return Value:
Error Code defined in winerror.h : If the function succeeds,
it returns ERROR_SUCCESS.
--*/
{
DWORD dwValue;
NTSTATUS status;
HANDLE KeyHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING UnicodeLoggerKey, UnicodeString;
ULONG Disposition, TitleIndex;
RtlZeroMemory(&ObjectAttributes, sizeof(OBJECT_ATTRIBUTES));
RtlInitUnicodeString((&UnicodeLoggerKey),(cszGlobalLoggerKey));
InitializeObjectAttributes(
&ObjectAttributes,
&UnicodeLoggerKey,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
// instead of opening, create a new key because it may not exist.
// if one exists already, that handle will be passed.
// if none exists, it will create one.
status = NtCreateKey(&KeyHandle,
KEY_QUERY_VALUE | KEY_SET_VALUE,
&ObjectAttributes,
0L, // not used within this call anyway.
NULL,
REG_OPTION_NON_VOLATILE,
&Disposition);
RtlFreeUnicodeString(&UnicodeLoggerKey);
if(!NT_SUCCESS(status)) {
return RtlNtStatusToDosError(status);
}
TitleIndex = 0L;
if (StartValue == 1) { // ACTION_START: set filename only when it is given by a user.
// setting BufferSize
if (LoggerInfo->BufferSize > 0) {
dwValue = LoggerInfo->BufferSize;
RtlInitUnicodeString((&UnicodeString),(cszBufferSizeValue));
status = NtSetValueKey(
KeyHandle,
&UnicodeString,
TitleIndex,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(dwValue)
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status)) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
TitleIndex++;
}
// setting MaximumBuffers
if (LoggerInfo->MaximumBuffers > 0) {
dwValue = LoggerInfo->MaximumBuffers;
RtlInitUnicodeString((&UnicodeString),(cszMaximumBufferValue));
status = NtSetValueKey(
KeyHandle,
&UnicodeString,
TitleIndex,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(dwValue)
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status)) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
TitleIndex++;
}
// setting MinimumBuffers
if (LoggerInfo->MinimumBuffers > 0) {
dwValue = LoggerInfo->MinimumBuffers;
RtlInitUnicodeString((&UnicodeString),(cszMinimumBufferValue));
status = NtSetValueKey(
KeyHandle,
&UnicodeString,
TitleIndex,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(dwValue)
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status)) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
TitleIndex++;
}
// setting FlushTimer
if (LoggerInfo->FlushTimer > 0) {
dwValue = LoggerInfo->FlushTimer;
RtlInitUnicodeString((&UnicodeString),(cszFlushTimerValue));
status = NtSetValueKey(
KeyHandle,
&UnicodeString,
TitleIndex,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(dwValue)
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status)) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
TitleIndex++;
}
// setting EnableFlags
if (LoggerInfo->EnableFlags > 0) {
dwValue = LoggerInfo->EnableFlags;
RtlInitUnicodeString((&UnicodeString),(cszEnableKernelValue));
status = NtSetValueKey(
KeyHandle,
&UnicodeString,
TitleIndex,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(dwValue)
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status)) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
TitleIndex++;
}
dwValue = 0;
if (LoggerInfo->LogFileNameOffset > 0) {
UNICODE_STRING UnicodeFileName;
#ifndef UNICODE
WCHAR TempString[MAXSTR];
MultiByteToWideChar(CP_ACP,
0,
(PCHAR)(LoggerInfo->LogFileNameOffset + (PCHAR) LoggerInfo),
strlen((PCHAR)(LoggerInfo->LogFileNameOffset + (PCHAR) LoggerInfo)),
TempString,
MAXSTR
);
RtlInitUnicodeString((&UnicodeFileName), TempString);
#else
RtlInitUnicodeString((&UnicodeFileName), (PWCHAR)(LoggerInfo->LogFileNameOffset + (PCHAR) LoggerInfo));
#endif
RtlInitUnicodeString((&UnicodeString),(cszFileNameValue));
status = NtSetValueKey(
KeyHandle,
&UnicodeString,
TitleIndex,
REG_SZ,
UnicodeFileName.Buffer,
UnicodeFileName.Length + sizeof(UNICODE_NULL)
);
RtlFreeUnicodeString(&UnicodeString);
RtlFreeUnicodeString(&UnicodeFileName);
if (!NT_SUCCESS(status)) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
TitleIndex++;
}
}
else { // if ACTION_STOP then delete the keys that users might have set previously.
// delete buffer size
RtlInitUnicodeString((&UnicodeString),(cszBufferSizeValue));
status = NtDeleteValueKey(
KeyHandle,
&UnicodeString
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status) && status != STATUS_OBJECT_NAME_NOT_FOUND) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
// delete maximum buffers
RtlInitUnicodeString((&UnicodeString),(cszMaximumBufferValue));
status = NtDeleteValueKey(
KeyHandle,
&UnicodeString
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status) && status != STATUS_OBJECT_NAME_NOT_FOUND) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
// delete minimum buffers
RtlInitUnicodeString((&UnicodeString),(cszMinimumBufferValue));
status = NtDeleteValueKey(
KeyHandle,
&UnicodeString
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status) && status != STATUS_OBJECT_NAME_NOT_FOUND) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
// delete flush timer
RtlInitUnicodeString((&UnicodeString),(cszFlushTimerValue));
status = NtDeleteValueKey(
KeyHandle,
&UnicodeString
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status) && status != STATUS_OBJECT_NAME_NOT_FOUND) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
// delete enable falg
RtlInitUnicodeString((&UnicodeString),(cszEnableKernelValue));
status = NtDeleteValueKey(
KeyHandle,
&UnicodeString
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status) && status != STATUS_OBJECT_NAME_NOT_FOUND) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
// delete filename
RtlInitUnicodeString((&UnicodeString),(cszFileNameValue));
status = NtDeleteValueKey(
KeyHandle,
&UnicodeString
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status) && status != STATUS_OBJECT_NAME_NOT_FOUND) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
}
// setting ClockType
if (ClockType > 0) {
dwValue = ClockType;
RtlInitUnicodeString((&UnicodeString),(cszClockTypeValue));
status = NtSetValueKey(
KeyHandle,
&UnicodeString,
TitleIndex,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(dwValue)
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status)) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
TitleIndex++;
}
// Setting StartValue
dwValue = StartValue;
RtlInitUnicodeString((&UnicodeString),(cszStartValue));
status = NtSetValueKey(
KeyHandle,
&UnicodeString,
TitleIndex,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(dwValue)
);
RtlFreeUnicodeString(&UnicodeString);
if (!NT_SUCCESS(status)) {
NtClose(KeyHandle);
return RtlNtStatusToDosError(status);
}
TitleIndex++;
NtClose(KeyHandle);
return 0;
}
ULONG
GetGlobalLoggerSettings(
IN OUT PEVENT_TRACE_PROPERTIES LoggerInfo,
OUT PULONG ClockType,
OUT PDWORD pdwStart
)
/*++
Routine Description:
It reads registry for golbal logger and updates LoggerInfo. It uses
NtEnumerateValueKey() to retrieve the values of the required subkeys.
The section that uses non NTAPIs is not guaranteed to work.
Arguments:
LoggerInfo - The poniter to the resident EVENT_TRACE_PROPERTIES instance.
whose members are updated as the result.
ClockType - The type of the clock to be updated.
pdwStart - The "Start" value of currently retained in the registry.
Return Value:
WINERROR - Error Code defined in winerror.h. If the function succeeds,
it returns ERROR_SUCCESS.
--*/
{
ULONG i, j;
NTSTATUS status;
HANDLE KeyHandle;
WCHAR SubKeyName[MAXSTR];
PVOID Buffer;
ULONG BufferLength, RequiredLength, KeyNameLength, KeyDataOffset, KeyDataLength;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING UnicodeLoggerKey;
*pdwStart = 0;
RtlInitUnicodeString((&UnicodeLoggerKey),(cszGlobalLoggerKey));
RtlZeroMemory(&ObjectAttributes, sizeof(OBJECT_ATTRIBUTES));
InitializeObjectAttributes(
&ObjectAttributes,
&UnicodeLoggerKey,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = NtOpenKey(
&KeyHandle,
KEY_QUERY_VALUE | KEY_SET_VALUE,
&ObjectAttributes
);
RtlFreeUnicodeString(&UnicodeLoggerKey);
if(!NT_SUCCESS(status))
return RtlNtStatusToDosError(status);
// KEY_VALUE_FULL_INFORMATION + name (1 WSTR) + data.
BufferLength = sizeof(KEY_VALUE_FULL_INFORMATION) + 2 * MAXSTR * sizeof(TCHAR);
Buffer = (PVOID) malloc(BufferLength);
if (Buffer == NULL) {
NtClose(KeyHandle);
return (ERROR_OUTOFMEMORY);
}
i = 0;
do {
// Using Key Enumeration
status = NtEnumerateValueKey(
KeyHandle,
i++,
KeyValueFullInformation,
Buffer,
BufferLength,
&RequiredLength
);
if (!NT_SUCCESS(status)) {
if (status == STATUS_NO_MORE_ENTRIES)
break;
else if (status == STATUS_BUFFER_OVERFLOW) {
Buffer = realloc(Buffer, RequiredLength);
if (Buffer == NULL) {
NtClose(KeyHandle);
return (ERROR_OUTOFMEMORY);
}
status = NtEnumerateValueKey(
KeyHandle,
i++,
KeyValueFullInformation,
Buffer,
BufferLength,
&RequiredLength
);
if (!NT_SUCCESS(status)) {
NtClose(KeyHandle);
free(Buffer);
return RtlNtStatusToDosError(status);
}
}
else {
NtClose(KeyHandle);
free(Buffer);
return RtlNtStatusToDosError(status);
}
}
KeyNameLength = ((PKEY_VALUE_FULL_INFORMATION)Buffer)->NameLength;
RtlCopyMemory(SubKeyName,
(PUCHAR)(((PKEY_VALUE_FULL_INFORMATION)Buffer)->Name),
KeyNameLength
);
KeyNameLength /= sizeof(WCHAR);
SubKeyName[KeyNameLength] = L'\0';
KeyDataOffset = ((PKEY_VALUE_FULL_INFORMATION)Buffer)->DataOffset;
KeyDataLength = ((PKEY_VALUE_FULL_INFORMATION)Buffer)->DataLength;
// Find out what the key is
if (!_wcsicmp(SubKeyName, cszStartValue)) { //StartValue
RtlCopyMemory(pdwStart,
(PUCHAR)Buffer + KeyDataOffset,
KeyDataLength);
}
else if (!_wcsicmp(SubKeyName, cszBufferSizeValue)) { // BufferSizeValue
RtlCopyMemory(&(LoggerInfo->BufferSize),
(PUCHAR)Buffer + KeyDataOffset,
KeyDataLength);
}
else if (!_wcsicmp(SubKeyName, cszMaximumBufferValue)) { // MaximumBufferValue
RtlCopyMemory(&(LoggerInfo->MaximumBuffers),
(PUCHAR)Buffer + KeyDataOffset,
KeyDataLength);
}
else if (!_wcsicmp(SubKeyName, cszMinimumBufferValue)) { // MinimumBuffers
RtlCopyMemory(&(LoggerInfo->MinimumBuffers),
(PUCHAR)Buffer + KeyDataOffset,
KeyDataLength);
}
else if (!_wcsicmp(SubKeyName, cszFlushTimerValue)) { // FlushTimer
RtlCopyMemory(&(LoggerInfo->FlushTimer),
(PUCHAR)Buffer + KeyDataOffset,
KeyDataLength);
}
else if (!_wcsicmp(SubKeyName, cszEnableKernelValue)) { // EnableKernelValue
RtlCopyMemory(&(LoggerInfo->EnableFlags),
(PUCHAR)Buffer + KeyDataOffset,
KeyDataLength);
}
else if (!_wcsicmp(SubKeyName, cszClockTypeValue)) { // ClockTypeValue
RtlCopyMemory(ClockType,
(PUCHAR)Buffer + KeyDataOffset,
KeyDataLength);
}
else if (!_wcsicmp(SubKeyName, cszFileNameValue)) { // FileName
#ifndef UNICODE
WCHAR TempString[MAXSTR];
RtlCopyMemory(TempString, (PUCHAR)Buffer + KeyDataOffset, KeyDataLength);
WideCharToMultiByte(CP_ACP,
0,
TempString,
wcslen(TempString),
(PUCHAR)LoggerInfo + LoggerInfo->LogFileNameOffset,
KeyDataLength,
NULL,
NULL);
#else
RtlCopyMemory((PUCHAR)LoggerInfo + LoggerInfo->LogFileNameOffset,
(PUCHAR)Buffer + KeyDataOffset,
KeyDataLength);
#endif
}
else { // Some other keys are in there
_tprintf(_T("Warning: Unidentified Key in the trace registry: %s\n"), SubKeyName);
}
}
while (1);
NtClose(KeyHandle);
free(Buffer);
return 0;
}