Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

898 lines
22 KiB

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997-2000 Microsoft Corporation
//
// Module Name:
// LogSrc.cpp
//
// Description:
// Logging utilities.
//
// Documentation:
// Spec\Admin\Debugging.ppt
//
// Maintained By:
// Galen Barbee (GalenB) 05-DEC-2000
//
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <tchar.h>
#include "Common.h"
//****************************************************************************
//****************************************************************************
//
// Logging Functions
//
// These are in both DEBUG and RETAIL.
//
//****************************************************************************
//****************************************************************************
//
// Constants
//
static const int LOG_OUTPUT_BUFFER_SIZE = 512;
//
// Globals
//
CRITICAL_SECTION * g_pcsLogging = NULL;
HANDLE g_hLogFile = INVALID_HANDLE_VALUE;
//////////////////////////////////////////////////////////////////////////////
//++
//
// HRESULT
// HrLogOpen( void )
//
// Description:
// This function:
// - initializes the log critical section
// - enters the log critical section assuring only one thread is
// writing to the log at a time
// - creates the directory tree to the log file (if needed)
// - initializes the log file by:
// - creating a new log file if one doesn't exist.
// - opens an existing log file (for append)
// - appends a time/date stamp that the log was (re)opened.
//
// Use LogClose() to exit the log critical section.
//
// If there is a failure inside this function, the log critical
// section will be released before returning.
//
// Arguments:
// None.
//
// Return Values:
// S_OK - log critical section held and log open successfully
// Otherwize HRESULT error code.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrLogOpen( void )
{
TCHAR szFilePath[ MAX_PATH ];
TCHAR szModulePath[ MAX_PATH ];
CHAR szBuffer[ LOG_OUTPUT_BUFFER_SIZE ];
DWORD dwWritten;
HANDLE hTemp;
BOOL fReturn;
HRESULT hr;
SYSTEMTIME SystemTime;
//
// Create a critical section to prevent lines from being fragmented.
//
if ( g_pcsLogging == NULL )
{
PCRITICAL_SECTION pNewCritSect =
(PCRITICAL_SECTION) HeapAlloc( GetProcessHeap(), 0, sizeof( CRITICAL_SECTION ) );
if ( pNewCritSect == NULL )
{
DebugMsg( "DEBUG: Out of Memory. Logging disabled." );
hr = E_OUTOFMEMORY;
goto Cleanup;
} // if: creation failed
InitializeCriticalSection( pNewCritSect );
// Make sure we only have one log critical section
InterlockedCompareExchangePointer( (PVOID *) &g_pcsLogging, pNewCritSect, 0 );
if ( g_pcsLogging != pNewCritSect )
{
DebugMsg( "DEBUG: Another thread already created the CS. Deleting this one." );
DeleteCriticalSection( pNewCritSect );
HeapFree( GetProcessHeap(), 0, pNewCritSect );
} // if: already have another critical section
} // if: no critical section created yet
Assert( g_pcsLogging != NULL );
EnterCriticalSection( g_pcsLogging );
//
// Make sure the log file is open
//
if ( g_hLogFile == INVALID_HANDLE_VALUE )
{
DWORD dwLen;
LPTSTR psz;
//
// Create the directory tree
//
// TODO: 12-DEC-2000 DavidP
// Change this to be more generic. This shouldn't be specific
// to clustering.
//
ExpandEnvironmentStrings( TEXT("%windir%\\system32\\LogFiles\\Cluster"), szFilePath, MAX_PATH );
hr = HrCreateDirectoryPath( szFilePath );
if ( FAILED( hr ) )
{
#if defined( DEBUG )
if ( !( g_tfModule & mtfOUTPUTTODISK ) )
{
DebugMsg( "*ERROR* Failed to create directory tree %s", szFilePath );
} // if: not logging to disk
#endif
goto Error;
} // if: failed
//
// Add filename
//
dwLen = GetModuleFileName( g_hInstance, szModulePath, sizeof( szModulePath ) / sizeof( szModulePath[ 0 ] ) );
Assert( dwLen != 0 );
_tcscpy( &szModulePath[ dwLen - 3 ], TEXT("log") );
psz = _tcsrchr( szModulePath, TEXT('\\') );
Assert( psz != NULL );
if ( psz == NULL )
{
hr = E_POINTER;
goto Error;
}
_tcscat( szFilePath, psz );
//
// Create it
//
g_hLogFile = CreateFile( szFilePath,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_FLAG_WRITE_THROUGH,
NULL
);
if ( g_hLogFile == INVALID_HANDLE_VALUE )
{
#if defined( DEBUG )
if ( !( g_tfModule & mtfOUTPUTTODISK ) )
{
DebugMsg( "*ERROR* Failed to create log at %s", szFilePath );
} // if: not logging to disk
#endif
hr = THR( HRESULT_FROM_WIN32( GetLastError() ) );
goto Error;
} // if: failed
// Seek to the end
SetFilePointer( g_hLogFile, 0, NULL, FILE_END );
//
// Write the time/date the log was (re)openned.
//
GetLocalTime( &SystemTime );
_snprintf( szBuffer,
sizeof( szBuffer ),
"*" ASZ_NEWLINE
"* %04u-%02u-%02u %02u:%02u:%02u.%03u" ASZ_NEWLINE
"*" ASZ_NEWLINE,
SystemTime.wYear,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond,
SystemTime.wMilliseconds
);
fReturn = WriteFile( g_hLogFile, szBuffer, strlen(szBuffer), &dwWritten, NULL );
if ( ! fReturn )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError() ) );
goto Error;
} // if: failed
DebugMsg( "DEBUG: Created log at %s", szFilePath );
} // if: file not already openned
hr = S_OK;
Cleanup:
return hr;
Error:
DebugMsg( "LogOpen: Failed hr = 0x%08x", hr );
if ( g_hLogFile != INVALID_HANDLE_VALUE )
{
CloseHandle( g_hLogFile );
g_hLogFile = INVALID_HANDLE_VALUE;
} // if: handle was open
LeaveCriticalSection( g_pcsLogging );
goto Cleanup;
} //*** HrLogOpen()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HRESULT
// HrLogRelease( void )
//
// Description:
// This actually just leaves the log critical section.
//
// Arguments:
// None.
//
// Return Values:
// S_OK always.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrLogRelease( void )
{
Assert( g_pcsLogging != NULL );
LeaveCriticalSection( g_pcsLogging );
return S_OK;
} //*** HrLogRelease()
//////////////////////////////////////////////////////////////////////////////
//++
//
// HRESULT
// HrLogClose( void )
//
// Description:
// Close the file. This function expects the critical section to have
// already been released.
//
// Arguments:
// None.
//
// Return Values:
// S_OK always.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
HrLogClose( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
if ( g_hLogFile != INVALID_HANDLE_VALUE )
{
CloseHandle( g_hLogFile );
g_hLogFile = INVALID_HANDLE_VALUE;
} // if: handle was open
return hr;
} //*** HrLogClose()
//////////////////////////////////////////////////////////////////////////////
//++
//
// ASCII
//
// void
// LogMsgNoNewline(
// LPCSTR pszFormat,
// ...
// )
//
// Description:
// Logs a message to the log file without adding a newline.
//
// Arguments:
// pszFormat - A printf format string to be printed.
// ,,, - Arguments for the printf string.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
__cdecl
LogMsgNoNewline(
LPCSTR pszFormat,
...
)
{
va_list valist;
CHAR szBuf[ LOG_OUTPUT_BUFFER_SIZE ];
DWORD dwWritten;
HRESULT hr;
#ifdef UNICODE
WCHAR szFormat[ LOG_OUTPUT_BUFFER_SIZE ];
WCHAR szTmpBuf[ LOG_OUTPUT_BUFFER_SIZE ];
mbstowcs( szFormat, pszFormat, strlen( pszFormat ) + 1 );
va_start( valist, pszFormat );
wvsprintf( szTmpBuf, szFormat, valist );
va_end( valist );
dwWritten = wcstombs( szBuf, szTmpBuf, wcslen( szTmpBuf ) + 1 );
if ( dwWritten == - 1 )
{
dwWritten = strlen( szBuf );
} // if: bad character found
#else
va_start( valist, pszFormat );
dwWritten = wvsprintf( szBuf, pszFormat, valist );
va_end( valist );
#endif // UNICODE
hr = HrLogOpen();
if ( hr != S_OK )
{
return;
} // if: failed
// LogDateTime();
WriteFile( g_hLogFile, szBuf, dwWritten, &dwWritten, NULL );
HrLogRelease();
} //*** LogMsgNoNewline() ASCII
//////////////////////////////////////////////////////////////////////////////
//++
//
// UNICODE
//
// void
// LogMsgNoNewline(
// LPCWSTR pszFormat,
// ...
// )
//
// Description:
// Logs a message to the log file without adding a newline.
//
// Arguments:
// pszFormat - A printf format string to be printed.
// ,,, - Arguments for the printf string.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
__cdecl
LogMsgNoNewline(
LPCWSTR pszFormat,
...
)
{
va_list valist;
CHAR szBuf[ LOG_OUTPUT_BUFFER_SIZE ];
DWORD dwWritten;
HRESULT hr;
#ifdef UNICODE
WCHAR szTmpBuf[ LOG_OUTPUT_BUFFER_SIZE ];
va_start( valist, pszFormat );
wvsprintf( szTmpBuf, pszFormat, valist);
va_end( valist );
dwWritten = wcstombs( szBuf, szTmpBuf, wcslen( szTmpBuf ) + 1 );
if ( dwWritten == -1 )
{
dwWritten = strlen( szBuf );
} // if: bad character found
#else
CHAR szFormat[ LOG_OUTPUT_BUFFER_SIZE ];
wcstombs( szFormat, pszFormat, wcslen( pszFormat ) + 1 );
va_start( valist, pszFormat );
dwWritten = wvsprintf( szBuf, szFormat, valist);
va_end( valist );
#endif // UNICODE
hr = HrLogOpen();
if ( hr != S_OK )
{
return;
} // if: failed
// LogDateTime();
WriteFile( g_hLogFile, szBuf, dwWritten, &dwWritten, NULL );
HrLogRelease();
} //*** LogMsgNoNewline() UNICODE
//////////////////////////////////////////////////////////////////////////////
//++
//
// void
// LogFormatStatusReport(
// CHAR ** ppaszBuffer,
// int iFirstArg,
// ...
// )
//
// Description:
// Formats a status report for writing to the log file.
//
// Arugments:
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
DWORD
LogFormatStatusReport(
CHAR ** ppaszBuffer,
int iFirstArg,
...
)
{
va_list valist;
va_start( valist, iFirstArg );
DWORD dw;
dw = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
"%2!02u!/%3!02u!/%4!04u!-%5!02u!:%6!02u!:%7!02u!.%8!02u! - %9!02u!/%10!02u!/%11!04u!-%12!02u!:%13!02u!:%14!02u!.%15!02u! {%16!08X!-%17!04X!-%18!04X!-%19!02X!%20!02X!-%21!02X!%22!02X!%23!02X!%24!02X!%25!02X!%26!02X!}, {%27!08X!-%28!04X!-%29!04X!-%30!02X!%31!02X!-%32!02X!%33!02X!%34!02X!%35!02X!%36!02X!%37!02X!} (%38!2d! / %39!2d! .. %40!2d! ) <%41!ws!> hr=%42!08X! %43!ws! %44!ws!" ASZ_NEWLINE,
0,
0,
(LPSTR) ppaszBuffer,
256,
&valist
);
return dw;
} //*** LogFormatStatusReport()
//////////////////////////////////////////////////////////////////////////////
//++
//
// void
// LogDateTime( void )
//
// Description:
// Adds date/time stamp to the log without a CR. This should be done
// while holding the Logging critical section which is done by calling
// HrLogOpen().
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
LogDateTime( void )
{
static CHAR szBuffer[ 25 ];
static SYSTEMTIME OldSystemTime = { 0 };
static DWORD dwWritten;
SYSTEMTIME SystemTime;
DWORD dwWhoCares;
int iCmp;
GetLocalTime( &SystemTime );
//
// Avoid expensive printf by comparing times
//
iCmp = memcmp( (PVOID) &SystemTime, (PVOID) &OldSystemTime, sizeof( SYSTEMTIME ) );
if ( iCmp != 0 )
{
dwWritten = _snprintf( szBuffer,
sizeof( szBuffer ),
"%04u-%02u-%02u %02u:%02u:%02u.%03u ",
SystemTime.wYear,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond,
SystemTime.wMilliseconds
);
Assert( dwWritten < 25 && dwWritten != -1 );
CopyMemory( (PVOID) &OldSystemTime, (PVOID) &SystemTime, sizeof( SYSTEMTIME ) );
} // if: time last different from this time
WriteFile( g_hLogFile, szBuffer, dwWritten, &dwWhoCares, NULL );
} //*** LogDateTime()
//////////////////////////////////////////////////////////////////////////////
//++
//
// void
// LogSystemTime( SYSTEMTIME stSystemTimeIn )
//
// Description:
// Adds date/time stamp to the log without a CR. This should be done
// while holding the Logging critical section which is done by calling
// HrLogOpen().
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
LogSystemTime( SYSTEMTIME * stSystemTimeIn )
{
static CHAR szBuffer[ 25 ];
DWORD dwWhoCares;
DWORD dwWritten;
dwWritten = _snprintf( szBuffer,
sizeof( szBuffer ),
"%04u-%02u-%02u %02u:%02u:%02u.%03u ",
stSystemTimeIn->wYear,
stSystemTimeIn->wMonth,
stSystemTimeIn->wDay,
stSystemTimeIn->wHour,
stSystemTimeIn->wMinute,
stSystemTimeIn->wSecond,
stSystemTimeIn->wMilliseconds
);
Assert( dwWritten < 25 && dwWritten != -1 );
WriteFile( g_hLogFile, szBuffer, dwWritten, &dwWhoCares, NULL );
} //*** LogSystemTime()
//////////////////////////////////////////////////////////////////////////////
//++
//
// ASCII
//
// void
// LogMsg(
// LPCSTR pszFormat,
// ...
// )
//
// Description:
// Logs a message to the log file and adds a newline.
//
// Arguments:
// pszFormat - A printf format string to be printed.
// ,,, - Arguments for the printf string.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
__cdecl
LogMsg(
LPCSTR pszFormat,
...
)
{
va_list valist;
CHAR szBuf[ LOG_OUTPUT_BUFFER_SIZE ];
DWORD dwWritten;
HRESULT hr;
#ifdef UNICODE
WCHAR szFormat[ LOG_OUTPUT_BUFFER_SIZE ];
WCHAR szTmpBuf[ LOG_OUTPUT_BUFFER_SIZE ];
mbstowcs( szFormat, pszFormat, strlen( pszFormat ) + 1 );
va_start( valist, pszFormat );
wvsprintf( szTmpBuf, szFormat, valist);
va_end( valist );
dwWritten = wcstombs( szBuf, szTmpBuf, wcslen( szTmpBuf ) + 1 );
if ( dwWritten == - 1 )
{
dwWritten = strlen( szBuf );
} // if: bad character found
#else
va_start( valist, pszFormat );
dwWritten = wvsprintf( szBuf, pszFormat, valist);
va_end( valist );
#endif // UNICODE
hr = HrLogOpen();
if ( FAILED( hr ) )
goto Cleanup;
LogDateTime();
WriteFile( g_hLogFile, szBuf, dwWritten, &dwWritten, NULL );
WriteFile( g_hLogFile, ASZ_NEWLINE, SIZEOF_ASZ_NEWLINE, &dwWritten, NULL );
HrLogRelease();
Cleanup:
return;
} //*** LogMsg() ASCII
//////////////////////////////////////////////////////////////////////////////
//++
//
// UNICODE
//
// void
// LogMsg(
// LPCWSTR pszFormat,
// ...
// )
//
// Description:
// Logs a message to the log file and adds a newline.
//
// Arguments:
// pszFormat - A printf format string to be printed.
// ,,, - Arguments for the printf string.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
__cdecl
LogMsg(
LPCWSTR pszFormat,
...
)
{
va_list valist;
CHAR szBuf[ LOG_OUTPUT_BUFFER_SIZE ];
DWORD dwWritten;
HRESULT hr;
#ifdef UNICODE
WCHAR szTmpBuf[ LOG_OUTPUT_BUFFER_SIZE ];
va_start( valist, pszFormat );
wvsprintf( szTmpBuf, pszFormat, valist);
va_end( valist );
dwWritten = wcstombs( szBuf, szTmpBuf, wcslen( szTmpBuf ) + 1 );
if ( dwWritten == -1 )
{
dwWritten = strlen( szBuf );
} // if: bad character found
#else
CHAR szFormat[ LOG_OUTPUT_BUFFER_SIZE ];
wcstombs( szFormat, pszFormat, wcslen( pszFormat ) + 1 );
va_start( valist, pszFormat );
dwWritten = wvsprintf( szBuf, szFormat, valist);
va_end( valist );
#endif // UNICODE
hr = HrLogOpen();
if ( FAILED( hr ) )
goto Cleanup;
LogDateTime();
WriteFile( g_hLogFile, szBuf, dwWritten, &dwWritten, NULL );
WriteFile( g_hLogFile, ASZ_NEWLINE, SIZEOF_ASZ_NEWLINE, &dwWritten, NULL );
HrLogRelease();
Cleanup:
return;
} //*** LogMsg() UNICODE
//////////////////////////////////////////////////////////////////////////////
//++
//
// void
// LogStatusReport(
// SYSTEMTIME * pstTimeIn,
// const WCHAR * pcszNodeNameIn,
// CLSID clsidTaskMajorIn,
// CLSID clsidTaskMinorIn,
// ULONG ulMinIn,
// ULONG ulMaxIn,
// ULONG ulCurrentIn,
// HRESULT hrStatusIn,
// const WCHAR * pcszDescriptionIn,
// const WCHAR * pcszUrlIn
// )
//
// Description:
// Writes a status report to the log file.
//
// Arugments:
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
LogStatusReport(
SYSTEMTIME * pstTimeIn,
const WCHAR * pcszNodeNameIn,
CLSID clsidTaskMajorIn,
CLSID clsidTaskMinorIn,
ULONG ulMinIn,
ULONG ulMaxIn,
ULONG ulCurrentIn,
HRESULT hrStatusIn,
const WCHAR * pcszDescriptionIn,
const WCHAR * pcszUrlIn
)
{
HRESULT hr;
DWORD dw;
DWORD dwWritten;
unsigned long dwArray[50];
CHAR * paszBuffer = NULL;
SYSTEMTIME SystemTime;
SYSTEMTIME SystemTime2;
GetLocalTime( &SystemTime );
if ( pstTimeIn )
{
memcpy( &SystemTime2, pstTimeIn, sizeof( SYSTEMTIME ) );
}
else
{
memset( &SystemTime2, 0, sizeof( SYSTEMTIME) );
}
dw = LogFormatStatusReport(
&paszBuffer,
0, 0,
// Time One.
SystemTime.wMonth, //1
SystemTime.wDay, //2
SystemTime.wYear, //3
SystemTime.wHour, //4
SystemTime.wMinute, //5
SystemTime.wSecond, //6
SystemTime.wMilliseconds, //7
// Time Two
SystemTime2.wMonth,
SystemTime2.wDay,
SystemTime2.wYear,
SystemTime2.wHour,
SystemTime2.wMinute,
SystemTime2.wSecond,
SystemTime2.wMilliseconds,
// GUID One
clsidTaskMajorIn.Data1,
clsidTaskMajorIn.Data2,
clsidTaskMajorIn.Data3,
clsidTaskMajorIn.Data4[0],
clsidTaskMajorIn.Data4[1],
clsidTaskMajorIn.Data4[2],
clsidTaskMajorIn.Data4[3],
clsidTaskMajorIn.Data4[4],
clsidTaskMajorIn.Data4[5],
clsidTaskMajorIn.Data4[6],
clsidTaskMajorIn.Data4[7],
// GUID Two
clsidTaskMinorIn.Data1,
clsidTaskMinorIn.Data2,
clsidTaskMinorIn.Data3,
clsidTaskMinorIn.Data4[0],
clsidTaskMinorIn.Data4[1],
clsidTaskMinorIn.Data4[2],
clsidTaskMinorIn.Data4[3],
clsidTaskMinorIn.Data4[4],
clsidTaskMinorIn.Data4[5],
clsidTaskMinorIn.Data4[6],
clsidTaskMinorIn.Data4[7],
// Other...
ulCurrentIn,
ulMinIn,
ulMaxIn,
pcszNodeNameIn,
hrStatusIn,
pcszDescriptionIn,
pcszUrlIn,
0,
0
);
// Open the log file.
hr = HrLogOpen();
if ( hr != S_OK )
{
return;
} // if: failed
// Write the initial output.
WriteFile( g_hLogFile, paszBuffer, dw, &dwWritten, NULL );
HrLogRelease();
LocalFree( paszBuffer );
} //*** LogStatusReport
//////////////////////////////////////////////////////////////////////////////
//++
//
// void
// LogTerminateProcess( void )
//
// Description:
// Cleans up anything the logging routines may have created or
// initialized. Typical called from the TraceTerminateProcess() macro.
//
// Arugments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
LogTerminateProcess( void )
{
} //*** LogTerminateProcess()