|
|
/************************************************************************
Copyright (c) 2000 - 2000 Microsoft Corporation
Module Name :
log.cpp
Abstract :
Log controller functions.
Author :
Revision History :
***********************************************************************/
#include "qmgrlibp.h"
#include <wmistr.h>
#include <initguid.h>
#include <guiddef.h>
#include <evntrace.h>
#if !defined(BITS_V12_ON_NT4)
#include "log.tmh"
#endif
TRACEHANDLE hTraceSessionHandle = NULL; EVENT_TRACE_PROPERTIES *pTraceProperties = NULL;
LPCTSTR BITSLoggerName = _T("BITS"); LPCTSTR BITSLogFileName = _T("BITS.log"); LPCTSTR BITSLogFileNameBackup = _T("BITS.bak"); const ULONG MAX_STRLEN = 1024; ULONG BITSMaxLogSize = C_QMGR_LOGFILE_SIZE_DEFAULT; // Size in MB
ULONG BITSFlags = C_QMGR_LOGFILE_FLAGS_DEFAULT; ULONG BITSLogMinMemory = C_QMGR_LOGFILE_MINMEMORY_DEFAULT; // Size in MB
const ULONG BITSDefaultLevel = 0; const ULONG BITSLogFileMode = EVENT_TRACE_FILE_MODE_CIRCULAR | EVENT_TRACE_USE_LOCAL_SEQUENCE;
#if !defined(BITS_V12_ON_NT4)
// Compatibility wrappers since these arn't in WIN2k
ULONG BITSStopTrace( TRACEHANDLE TraceHandle, LPCWSTR InstanceName, PEVENT_TRACE_PROPERTIES Properties ) { return ControlTraceW( TraceHandle, InstanceName, Properties, EVENT_TRACE_CONTROL_STOP ); }
ULONG BITSQueryTrace( TRACEHANDLE TraceHandle, LPCWSTR InstanceName, PEVENT_TRACE_PROPERTIES Properties ) { return ControlTraceW( TraceHandle, InstanceName, Properties, EVENT_TRACE_CONTROL_QUERY ); }
#endif
bool Log_LoadSetting() { // returns true is a logger should be
// started if it isn't already started
HKEY hBITSKey;
LONG lResult = RegOpenKey( HKEY_LOCAL_MACHINE, C_QMGR_REG_KEY, &hBITSKey );
if ( ERROR_SUCCESS == lResult ) {
BITSMaxLogSize = GlobalInfo::RegGetDWORD( hBITSKey, C_QMGR_LOGFILE_SIZE, C_QMGR_LOGFILE_SIZE_DEFAULT );
BITSFlags = GlobalInfo::RegGetDWORD( hBITSKey, C_QMGR_LOGFILE_FLAGS, C_QMGR_LOGFILE_FLAGS_DEFAULT );
BITSLogMinMemory = GlobalInfo::RegGetDWORD( hBITSKey, C_QMGR_LOGFILE_MINMEMORY, C_QMGR_LOGFILE_MINMEMORY_DEFAULT );
RegCloseKey( hBITSKey );
}
// Determine if the settings justify starting the logger
if ( !BITSMaxLogSize || !BITSFlags) return false; // 0 size or no flags
MEMORYSTATUS MemoryStatus; GlobalMemoryStatus( &MemoryStatus );
SIZE_T MemorySize = MemoryStatus.dwTotalPhys / 0x100000; if ( MemorySize < BITSLogMinMemory ) return false;
return true; //enable the logger if it isn't already started
}
#if !defined(BITS_V12_ON_NT4)
void Log_StartLogger() { try { if (!Log_LoadSetting()) { return; }
// Allocate trace properties
ULONG SizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + (2 * MAX_STRLEN * sizeof(TCHAR));
pTraceProperties = (PEVENT_TRACE_PROPERTIES) new char[SizeNeeded];
memset( pTraceProperties, 0, SizeNeeded ); // SEC: REVIEWED 2002-03-28
pTraceProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES); pTraceProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + (MAX_STRLEN * sizeof(TCHAR)); pTraceProperties->Wnode.BufferSize = SizeNeeded; pTraceProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
// Setup trace session properties
TCHAR *LoggerName = (LPTSTR)((char*)pTraceProperties + pTraceProperties->LoggerNameOffset); TCHAR *LogFileName = (LPTSTR)((char*)pTraceProperties + pTraceProperties->LogFileNameOffset);
THROW_HRESULT( StringCchCopy( LoggerName, MAX_STRLEN, BITSLoggerName ));
_tfullpath(LogFileName, BITSLogFileName, MAX_STRLEN);
pTraceProperties->LogFileMode |= BITSLogFileMode; pTraceProperties->MaximumFileSize = BITSMaxLogSize;
ULONG Status;
// if an existing session is started, if so just use that
// session unmodified
Status = BITSQueryTrace( NULL, LoggerName, pTraceProperties);
if ( ERROR_SUCCESS == Status) { LogInfo("Using existing BITS logger session"); return; }
MoveFileEx( BITSLogFileName, BITSLogFileNameBackup, MOVEFILE_REPLACE_EXISTING );
Status = StartTrace( &hTraceSessionHandle, LoggerName, pTraceProperties);
if ( ERROR_SUCCESS != Status ) { hTraceSessionHandle = NULL; return; }
Status = EnableTrace( TRUE, BITSFlags, BITSDefaultLevel, &BITSCtrlGuid, hTraceSessionHandle);
LogInfo("Started new logger session"); LogInfo("Max log size is %u MB", BITSMaxLogSize ); LogInfo("Log Flags %x", BITSFlags ); LogInfo("Min Memory settings %u MB", BITSLogMinMemory ); } catch ( ComError err ) { delete[] pTraceProperties; pTraceProperties = NULL; } }
void Log_StopLogger() { if ( !pTraceProperties ) return;
if ( hTraceSessionHandle ) { BITSStopTrace( hTraceSessionHandle, NULL, pTraceProperties); hTraceSessionHandle = NULL;
}
delete[] pTraceProperties; pTraceProperties = NULL; }
BOOL Log_Init(void) {
WPP_INIT_TRACING(L"Microsoft\\BITS"); return TRUE; }
void Log_Close() { Log_StopLogger(); WPP_CLEANUP(); }
#endif
#if defined(BITS_V12_ON_NT4)
#define MAX_LOG_STRING 4000
#define MAX_REPLACED_FORMAT 256
CRITICAL_SECTION g_LogCs; static HANDLE g_LogFile = INVALID_HANDLE_VALUE; static bool g_LogInitialized = false;
struct FormatReplaceElement { DWORD SearchSize; const char *SearchString; DWORD ReplacementSize; const char *ReplacementString; };
// sort table first by size, then by string
FormatReplaceElement g_FormatReplaceElements[] = { { 5, "%!ts!", 3, "%ls" }, { 6, "%!sid!", 2, "%p" }, { 7, "%!guid!", 2, "%p" }, { 7, "%!tstr!", 3, "%ls" }, { 9, "%!winerr!", 7, "0x%8.8X" }, { 10, "%!netrate!", 2, "%G" }, { 12, "%!timestamp!", 9, "0x%16.16X" } };
const DWORD NumberOfFormatReplaceElements = sizeof( g_FormatReplaceElements ) / sizeof( *g_FormatReplaceElements );
int __cdecl FormatReplaceElementComparison( const void *elem1, const void *elem2 ) {
const FormatReplaceElement *felem1 = (const FormatReplaceElement*)elem1; const FormatReplaceElement *felem2 = (const FormatReplaceElement*)elem2;
if ( felem1->SearchSize != felem2->SearchSize ) return felem1->SearchSize - felem2->SearchSize;
return _stricmp( felem1->SearchString, felem2->SearchString );
}
void LogGenerateNewFormat( char *NewFormat, const char *Format, DWORD BufferSize ) {
if ( !BufferSize ) return;
BufferSize--; // Dont count the terminating NULL
while( 1 ) {
if ( !BufferSize || !*Format ) { *NewFormat = '\0'; return; }
if ( '%' == Format[0] && '!' == Format[1] ) {
const char *Begin = Format; const char *End = Format + 2;
while( *End != '!' ) {
if ( '\0' == *End++ ) goto NormalChar;
}
FormatReplaceElement Key = { (DWORD)(End - Begin) + 1, Begin, (DWORD)(End - Begin) + 1, Begin };
FormatReplaceElement *Replacement = (FormatReplaceElement*) bsearch( &Key, &g_FormatReplaceElements, NumberOfFormatReplaceElements, sizeof( *g_FormatReplaceElements ), &FormatReplaceElementComparison );
if ( !Replacement ) goto NormalChar;
if ( Replacement->ReplacementSize > BufferSize ) { *NewFormat = '\0'; return; }
memcpy( NewFormat, Replacement->ReplacementString, sizeof( char ) * Replacement->ReplacementSize ); NewFormat += Replacement->ReplacementSize; BufferSize -= Replacement->ReplacementSize; Format = End + 1;
} else { NormalChar: *NewFormat++ = *Format++; BufferSize--; }
}
}
void Log(const CHAR *Prefix, const CHAR *Format, va_list ArgList ) {
if ( !g_LogInitialized) return;
EnterCriticalSection( &g_LogCs );
if ( !g_LogInitialized) return;
static char OutputString[ MAX_LOG_STRING ];
DWORD ThreadId = GetCurrentThreadId(); DWORD ProcessId = GetCurrentProcessId();
SYSTEMTIME Time;
GetSystemTime( &Time );
int CharsWritten = _snprintf( OutputString, sizeof( OutputString ) - 3, "%.2u/%.2u/%.4u-%.2u:%.2u:%.2u.%.3u %X.%X ", Time.wMonth, Time.wDay, Time.wYear, Time.wHour, Time.wMinute, Time.wSecond, Time.wMilliseconds, ProcessId, ThreadId );
if ( -1 != CharsWritten ) {
int CharsWritten2 = _snprintf( OutputString + CharsWritten, sizeof( OutputString ) - CharsWritten - 3, "%s", Prefix );
if ( -1 == CharsWritten2 ) goto overflow;
CharsWritten += CharsWritten2;
char NewFormat[ MAX_REPLACED_FORMAT ];
LogGenerateNewFormat( NewFormat, Format, MAX_REPLACED_FORMAT );
int CharsWritten3 = _vsnprintf( OutputString + CharsWritten, sizeof( OutputString ) - CharsWritten - 3, NewFormat, ArgList );
if ( -1 == CharsWritten3 ) goto overflow;
CharsWritten += CharsWritten3; OutputString[ CharsWritten++ ] = '\r'; OutputString[ CharsWritten++ ] = '\n'; OutputString[ CharsWritten++ ] = '\0';
} else { overflow: OutputString[ sizeof( OutputString ) - 3 ] = '\r'; OutputString[ sizeof( OutputString ) - 2 ] = '\n'; OutputString[ sizeof( OutputString ) - 1 ] = '\0'; CharsWritten = sizeof( OutputString ); }
if ( INVALID_HANDLE_VALUE != g_LogFile ) { DWORD BytesWritten;
WriteFile( g_LogFile, OutputString, CharsWritten, &BytesWritten, NULL );
}
#if defined( DBG )
OutputDebugStringA( OutputString ); #endif
LeaveCriticalSection( &g_LogCs );
}
void Log_StartLogger() {
if (!Log_LoadSetting()) return;
if ( BITSLogFileName && BITSFlags ) {
g_LogFile = CreateFile( BITSLogFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, // overwrite any existing file
FILE_ATTRIBUTE_NORMAL, NULL );
}
}
void Log_StopLogger() { if ( g_LogFile ) { CloseHandle( g_LogFile ); } g_LogInitialized = true; }
BOOL Log_Init(void) { if ( !InitializeCriticalSectionAndSpinCount( &g_LogCs, 0x80000000 ) ) return FALSE;
g_LogInitialized = true; return TRUE; }
void Log_Close() { EnterCriticalSection( &g_LogCs ); Log_StopLogger(); g_LogInitialized = false; DeleteCriticalSection( &g_LogCs ); }
#endif
|