windows-nt/Source/XPSP1/NT/admin/services/drizzle/utils/log.cpp
2020-09-26 16:20:57 +08:00

527 lines
12 KiB
C++

/************************************************************************
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