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

410 lines
11 KiB
C++

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
log.cpp
Abstract:
This file implements the BITS server extensions logging
--*/
#include "precomp.h"
#include "sddl.h"
const DWORD g_LogLineSize = 160;
typedef char LOG_LINE_TYPE[g_LogLineSize];
CRITICAL_SECTION g_LogCs;
bool g_LogFileEnabled = false;
bool g_LogDebuggerEnabled = false;
UINT32 g_LogFlags = DEFAULT_LOG_FLAGS;
HANDLE g_LogFile = INVALID_HANDLE_VALUE;
HANDLE g_LogFileMapping = NULL;
char g_LogDefaultFileName[ MAX_PATH*2 ];
char g_LogRegistryFileName[ MAX_PATH*2 ];
char *g_LogFileName = NULL;
char g_LogBuffer[512];
UINT64 g_LogSlots = ( DEFAULT_LOG_SIZE * 1000000 ) / g_LogLineSize;
DWORD g_LogSequence = 0;
UINT64 g_LogCurrentSlot = 1;
LOG_LINE_TYPE *g_LogFileBase = NULL;
// Allow access to system, administrators, and the creator/owner
const char g_LogSecurityString[] = "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;CO)";
void OpenLogFile()
{
bool NewFile = false;
{
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
g_LogSecurityString,
SDDL_REVISION_1,
&SecurityDescriptor,
NULL ) )
return;
SECURITY_ATTRIBUTES SecurityAttributes =
{
sizeof( SECURITY_ATTRIBUTES ),
SecurityDescriptor,
FALSE
};
g_LogFile =
CreateFile(
g_LogFileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
&SecurityAttributes,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL );
LocalFree( (HLOCAL)SecurityDescriptor );
if ( INVALID_HANDLE_VALUE == g_LogFile )
return;
}
SetFilePointer( g_LogFile, 0, NULL, FILE_BEGIN );
LOG_LINE_TYPE FirstLine;
DWORD dwBytesRead = 0;
ReadFile( g_LogFile,
FirstLine,
g_LogLineSize,
&dwBytesRead,
NULL );
DWORD LineSize;
UINT64 LogSlots;
if ( dwBytesRead != g_LogLineSize ||
4 != sscanf( FirstLine, "# %u %I64u %u %I64u", &LineSize, &LogSlots, &g_LogSequence, &g_LogCurrentSlot ) ||
LineSize != g_LogLineSize ||
LogSlots != g_LogSlots )
{
NewFile = true;
g_LogSequence = 0;
g_LogCurrentSlot = 1;
if ( INVALID_SET_FILE_POINTER == SetFilePointer( g_LogFile, (DWORD)g_LogSlots * g_LogLineSize, NULL, FILE_BEGIN ) )
goto fatalerror;
if ( !SetEndOfFile( g_LogFile ) )
goto fatalerror;
SetFilePointer( g_LogFile, 0, NULL, FILE_BEGIN );
}
g_LogFileMapping =
CreateFileMapping(
g_LogFile,
NULL,
PAGE_READWRITE,
0,
0,
NULL );
if ( !g_LogFileMapping )
goto fatalerror;
g_LogFileBase = (LOG_LINE_TYPE *)
MapViewOfFile(
g_LogFileMapping, // handle to file-mapping object
FILE_MAP_WRITE | FILE_MAP_READ,// access mode
0, // high-order DWORD of offset
0, // low-order DWORD of offset
0 // number of bytes to map
);
if ( !g_LogFileBase )
goto fatalerror;
if ( NewFile )
{
LOG_LINE_TYPE FillTemplate;
memset( FillTemplate, ' ', sizeof( FillTemplate ) );
StringCchPrintfA(
FillTemplate,
g_LogLineSize,
"# %u %I64u %u %I64u",
g_LogLineSize,
g_LogSlots,
g_LogSequence,
g_LogCurrentSlot );
FillTemplate[ g_LogLineSize - 2 ] = '\r';
FillTemplate[ g_LogLineSize - 1 ] = '\n';
memcpy( g_LogFileBase, FillTemplate, sizeof( FillTemplate ) );
memset( FillTemplate, '9', sizeof( FillTemplate ) );
FillTemplate[ g_LogLineSize - 2 ] = '\r';
FillTemplate[ g_LogLineSize - 1 ] = '\n';
for( SIZE_T i=1; i < g_LogSlots; i++ )
memcpy( g_LogFileBase + i, FillTemplate, sizeof( FillTemplate ) );
}
g_LogFileEnabled = true;
return;
fatalerror:
if ( g_LogFileBase )
{
UnmapViewOfFile( (LPCVOID)g_LogFileBase );
g_LogFileBase = NULL;
}
if ( g_LogFileMapping )
{
CloseHandle( g_LogFileMapping );
g_LogFileMapping = NULL;
}
if ( INVALID_HANDLE_VALUE != g_LogFile )
{
CloseHandle( g_LogFile );
g_LogFile = INVALID_HANDLE_VALUE;
}
}
HRESULT LogInit()
{
if ( !InitializeCriticalSectionAndSpinCount( &g_LogCs, 0x80000000 ) )
return HRESULT_FROM_WIN32( GetLastError() );
if (!GetSystemDirectory( g_LogDefaultFileName, MAX_PATH ) )
{
HRESULT Hr = HRESULT_FROM_WIN32( GetLastError() );
DeleteCriticalSection( &g_LogCs );
return Hr;
}
StringCchCatA(
g_LogDefaultFileName,
MAX_PATH,
"\\bitsserver.log" );
g_LogFileName = g_LogDefaultFileName;
HKEY Key = NULL;
if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, LOG_SETTINGS_PATH, &Key ) )
{
DWORD Type;
DWORD DataSize = sizeof( g_LogRegistryFileName );
if ( ERROR_SUCCESS == RegQueryValueEx( Key,
LOG_FILENAME_VALUE,
NULL,
&Type,
(LPBYTE)g_LogRegistryFileName,
&DataSize ) &&
( ( REG_EXPAND_SZ == Type ) || ( REG_SZ == Type ) ) )
{
g_LogFileName = g_LogRegistryFileName;
}
DWORD LogRegistryFlags;
DataSize = sizeof( LogRegistryFlags );
if ( ERROR_SUCCESS == RegQueryValueEx( Key,
LOG_FLAGS_VALUE,
NULL,
&Type,
(LPBYTE)&LogRegistryFlags,
&DataSize ) &&
( REG_DWORD == Type ) )
{
g_LogFlags = LogRegistryFlags;
}
DWORD LogSize;
DataSize = sizeof( LogSize );
if ( ERROR_SUCCESS == RegQueryValueEx( Key,
LOG_SIZE_VALUE,
NULL,
&Type,
(LPBYTE)&LogSize,
&DataSize ) &&
( REG_DWORD == Type ) )
{
g_LogSlots = ( LogSize * 1000000 ) / g_LogLineSize;
}
RegCloseKey( Key );
Key = NULL;
}
if ( g_LogFlags && g_LogFileName && g_LogSlots )
{
OpenLogFile();
}
return S_OK;
}
void LogClose()
{
EnterCriticalSection( &g_LogCs );
if ( g_LogFileBase )
{
memset( g_LogFileBase[0], ' ', sizeof( g_LogLineSize ) );
StringCchPrintfA(
g_LogFileBase[0],
g_LogLineSize,
"# %u %I64u %u %I64u",
g_LogLineSize,
g_LogSlots,
g_LogSequence,
g_LogCurrentSlot );
g_LogFileBase[0][ g_LogLineSize - 2 ] = '\r';
g_LogFileBase[0][ g_LogLineSize - 1 ] = '\n';
UnmapViewOfFile( (LPCVOID)g_LogFileBase );
g_LogFileBase = NULL;
}
if ( g_LogFileMapping )
{
CloseHandle( g_LogFileMapping );
g_LogFileMapping = NULL;
}
if ( INVALID_HANDLE_VALUE != g_LogFile )
{
CloseHandle( g_LogFile );
g_LogFile = INVALID_HANDLE_VALUE;
}
DeleteCriticalSection( &g_LogCs );
}
void LogInternal( UINT32 LogFlags, char *Format, va_list arglist )
{
if ( !g_LogFileEnabled && !g_LogDebuggerEnabled )
return;
DWORD LastError = GetLastError();
EnterCriticalSection( &g_LogCs );
DWORD ThreadId = GetCurrentThreadId();
DWORD ProcessId = GetCurrentProcessId();
SYSTEMTIME Time;
GetLocalTime( &Time );
StringCchVPrintfA(
g_LogBuffer,
sizeof(g_LogBuffer) - 1,
Format, arglist );
int CharsWritten = strlen( g_LogBuffer );
char *BeginPointer = g_LogBuffer;
char *EndPointer = g_LogBuffer + CharsWritten;
DWORD MinorSequence = 0;
while ( BeginPointer < EndPointer )
{
static char StaticLineBuffer[ g_LogLineSize ];
char *LineBuffer = StaticLineBuffer;
if ( g_LogFileBase )
{
LineBuffer = g_LogFileBase[ g_LogCurrentSlot ];
g_LogCurrentSlot = ( g_LogCurrentSlot + 1 ) % g_LogSlots;
// leave the first line alone
if ( !g_LogCurrentSlot )
g_LogCurrentSlot = ( g_LogCurrentSlot + 1 ) % g_LogSlots;
}
char *CurrentOutput = LineBuffer;
StringCchPrintfA(
LineBuffer,
g_LogLineSize,
"%.8X.%.2X %.2u/%.2u/%.4u-%.2u:%.2u:%.2u.%.3u %.4X.%.4X %s|%s|%s|%s|%s ",
g_LogSequence,
MinorSequence++,
Time.wMonth,
Time.wDay,
Time.wYear,
Time.wHour,
Time.wMinute,
Time.wSecond,
Time.wMilliseconds,
ProcessId,
ThreadId,
( LogFlags & LOG_INFO ) ? "I" : "-",
( LogFlags & LOG_WARNING ) ? "W" : "-",
( LogFlags & LOG_ERROR ) ? "E" : "-",
( LogFlags & LOG_CALLBEGIN ) ? "CB" : "--",
( LogFlags & LOG_CALLEND ) ? "CE" : "--" );
int HeaderSize = strlen( LineBuffer );
int SpaceAvailable = g_LogLineSize - HeaderSize - 2; // 2 bytes for /r/n
int OutputChars = min( (int)( EndPointer - BeginPointer ), SpaceAvailable );
int PadChars = SpaceAvailable - OutputChars;
CurrentOutput += HeaderSize;
memcpy( CurrentOutput, BeginPointer, OutputChars );
CurrentOutput += OutputChars;
BeginPointer += OutputChars;
memset( CurrentOutput, ' ', PadChars );
CurrentOutput += PadChars;
*CurrentOutput++ = '\r';
*CurrentOutput++ = '\n';
ASSERT( CurrentOutput - LineBuffer == g_LogLineSize );
if ( g_LogDebuggerEnabled )
{
static char DebugLineBuffer[ g_LogLineSize + 1];
memcpy( DebugLineBuffer, LineBuffer, g_LogLineSize );
DebugLineBuffer[ g_LogLineSize ] = '\0';
OutputDebugString( DebugLineBuffer );
}
}
g_LogSequence++;
LeaveCriticalSection( &g_LogCs );
SetLastError( LastError );
}