2366 lines
84 KiB
C
2366 lines
84 KiB
C
// 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;
|
|
|
|
}
|