Leaked source code of windows server 2003
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.
 
 
 
 
 
 

325 lines
10 KiB

//-----------------------------------------------------------------------------
// Util.cpp
//-----------------------------------------------------------------------------
#include <logutil.h>
#include <tchar.h>
#include <winerror.h>
#include <shlwapi.h>
#include <assert.h>
#include <stdio.h>
CLogging::CLogging( LPCTSTR ps ) :
m_psLogFile(NULL), m_psDefaultPath(NULL), m_bInitialized(false), m_hInstance(NULL), m_bSkipDefaultPath(false)
{
assert( ps );
if ( NULL != ps )
{
m_psLogFile = new TCHAR[ _tcslen( ps ) + 1 ];
if( NULL != m_psLogFile )
{
_tcscpy( m_psLogFile, ps );
}
}
}
CLogging::CLogging( LPCTSTR ps, LPCTSTR psPath ) :
m_psLogFile(NULL), m_psDefaultPath(NULL), m_bInitialized(false), m_hInstance(NULL), m_bSkipDefaultPath(false)
{
assert( ps );
if ( NULL != ps )
{
m_psLogFile = new TCHAR[ _tcslen( ps ) + 1 ];
if(NULL != m_psLogFile)
{
_tcscpy( m_psLogFile, ps );
}
}
assert( psPath );
if ( NULL != psPath )
{
//try to substitute any embedded environment variables
DWORD dwRC = 0;
DWORD dwSize = ExpandEnvironmentStrings( psPath, m_psDefaultPath, 0 );
if ( 0 != dwSize )
{
m_psDefaultPath = new TCHAR[dwSize + 1];
dwRC = ExpandEnvironmentStrings( psPath, m_psDefaultPath, dwSize );
}
if ( 0 == dwRC )
{
dwSize = _tcslen( psPath ) + 1;
m_psDefaultPath = new TCHAR[ dwSize ];
if(NULL != m_psDefaultPath)
{
_tcsncpy( m_psDefaultPath, psPath, dwSize );
}
}
}
}
CLogging::~CLogging ()
{
if ( NULL != m_psLogFile )
delete m_psLogFile;
if ( NULL != m_psDefaultPath )
delete m_psDefaultPath;
}
void CLogging::Init( HINSTANCE hinst )
{
m_hInstance = hinst;
}
void CLogging::LogPrivate( LPCTSTR szBuffer )
{
if (!m_bInitialized)
Initialize();
if (!m_bInitialized)
return;
// always create/open the log file and close it after each write
HANDLE hf = CreateFile( m_psLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if (hf != INVALID_HANDLE_VALUE)
{
// io
DWORD dwWritten = 0;
if (!SetFilePointer( hf, 0, NULL, FILE_END ))
{
#ifdef UNICODE
// write UNICODE signature (only first time)
unsigned char sig[2] = { 0xFF, 0xFE };
WriteFile (hf, (LPVOID)sig, 2, &dwWritten, NULL);
#endif
}
// write data
dwWritten = 0;
WriteFile( hf, (LPVOID)szBuffer, sizeof(TCHAR)*_tcslen( szBuffer ), &dwWritten, NULL );
assert( dwWritten != 0 );
// write crlf (if nec)
// add a new line if not present
int nLen = _tcslen( szBuffer );
if ( nLen >=2 )
{
if (szBuffer[nLen - 2] != _T('\r') || szBuffer[nLen - 1] != _T('\n'))
WriteFile( hf, (LPVOID)_T("\r\n"), 2 * sizeof(TCHAR), &dwWritten, NULL );
}
// close up (every time)
CloseHandle( hf );
}
}
void CLogging::Initialize()
{
HRESULT hr = S_OK;
// use default log file name if necessary
if ( NULL == m_psLogFile )
{
m_psLogFile = new TCHAR[32];
if ( NULL == m_psLogFile )
hr = E_OUTOFMEMORY;
else
_tcscpy( m_psLogFile, _T("LOGFILE.log"));
}
// skip default path for non-server running apps
if( !m_bSkipDefaultPath )
{
// create dir if not there already
if ( NULL == m_psDefaultPath )
{
DWORD dwSize = MAX_PATH;
m_psDefaultPath = new TCHAR[MAX_PATH];
if ( NULL == m_psDefaultPath )
hr = E_OUTOFMEMORY;
else
{
if ( 0 == GetModuleFileName( NULL, m_psDefaultPath, dwSize ) )
hr = HRESULT_FROM_WIN32( GetLastError() );
else
{
LPTSTR ps = _tcsrchr( m_psDefaultPath, _T( '\\' ));
if ( NULL != ps )
*ps = NULL;
}
}
}
else
{
if ( 0 == CreateDirectory( m_psDefaultPath, NULL ))
{
DWORD dwRC = GetLastError();
if ( ERROR_ALREADY_EXISTS == dwRC )
hr = S_OK;
else
hr = HRESULT_FROM_WIN32(hr);
}
if ( !PathAppend( m_psDefaultPath, m_psLogFile ))
hr = E_FAIL;
delete [] m_psLogFile;
//m_psLogFile = m_psDefaultPath; This causes double free in the destructor...
m_psLogFile = new TCHAR[ _tcslen( m_psDefaultPath ) + 1 ];
if( NULL != m_psLogFile )
{
_tcscpy( m_psLogFile, m_psDefaultPath );
}
}
}
if SUCCEEDED( hr )
{
m_bInitialized = TRUE;
// write initial messages to file
TCHAR szTime[50];
TCHAR szDate[50];
GetTimeFormat( LOCALE_USER_DEFAULT, TIME_NOSECONDS, NULL, NULL, szTime, 50 );
GetDateFormat( LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, szDate, 50 );
Log( _T("\r\n%s %s"), szDate, szTime );
}
}
void __cdecl CLogging::Log( int iMessageId, ... )
{
va_list ArgList; // to turn ellipses into va_list
va_start( ArgList, iMessageId );
LPTSTR lpBuffer = NULL;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE, m_hInstance, iMessageId, 0, (LPTSTR)&lpBuffer, 0, &ArgList );
assert( lpBuffer );
if( lpBuffer )
{
LogPrivate (lpBuffer);
LocalFree (lpBuffer);
}
va_end(ArgList);
}
void __cdecl CLogging::Log( LPCTSTR lpszFormat, ... )
{
// form the log string
va_list args;
va_start( args, lpszFormat );
TCHAR szBuffer[2048];
// 2KB max log string with room for new line and null termination
_vsntprintf( szBuffer, 2047, lpszFormat, args );
szBuffer[2047]=0;
va_end( args );
LogPrivate( szBuffer );
}
void CLogging::Size( DWORD _FileSizeLow )
{
if ( 0 != _FileSizeLow % 2 )
{
assert( false ); // Even numbers required in case this is a UNICODE file
return;
}
if ( 1 > static_cast<long>( _FileSizeLow ))
{
assert( false ); // Need a positive number
return;
}
if (m_bInitialized == FALSE)
Initialize();
if (!m_bInitialized)
return;
WIN32_FIND_DATA stWfd;
HANDLE hSearch;
DWORD dwRC;
PBYTE pbBuffer, pbBlankLine;
DWORD dwRead = 0, dwWrite, dwWritten;
BOOL bRC;
pbBuffer = new BYTE[_FileSizeLow];
if ( pbBuffer == NULL )
{
return;
}
ZeroMemory( pbBuffer, _FileSizeLow );
hSearch = FindFirstFile( m_psLogFile, &stWfd );
if ( hSearch != INVALID_HANDLE_VALUE )
{
FindClose( hSearch );
if ( 0 < stWfd.nFileSizeHigh || _FileSizeLow < stWfd.nFileSizeLow )
{ // Need to resize the file
HANDLE hf = CreateFile( m_psLogFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hf != INVALID_HANDLE_VALUE)
{ // Move the pointer to the end of the file - the size we want to truncate to
dwRC = SetFilePointer( hf, _FileSizeLow * -1, NULL, FILE_END );
if ( INVALID_SET_FILE_POINTER != dwRC )
{
bRC = ReadFile( hf, reinterpret_cast<LPVOID>( pbBuffer ), _FileSizeLow, &dwRead, NULL );
CloseHandle( hf );
if ( bRC && 0 < dwRead )
{ // Find the first blank line
pbBlankLine = reinterpret_cast<PBYTE>( _tcsstr( reinterpret_cast<LPTSTR>( pbBuffer ), _T( "\r\n\r\n" )));
if ( NULL != pbBlankLine )
pbBlankLine += 4 * sizeof( TCHAR );
else
{ // Let's just find the next crlf and write out the rest of the file
pbBlankLine = reinterpret_cast<PBYTE>( _tcsstr( reinterpret_cast<LPTSTR>( pbBuffer ), _T( "\r\n" )));
if ( NULL != pbBlankLine )
pbBlankLine += 2 * sizeof( TCHAR );
}
if ( NULL == pbBlankLine )
{ // I guess we should just write out the rest of the file
pbBlankLine = pbBuffer;
}
HANDLE hf1 = CreateFile( m_psLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if (hf1 != INVALID_HANDLE_VALUE)
{
#ifdef UNICODE
// write UNICODE signature (only first time)
unsigned char sig[2] = { 0xFF, 0xFE };
WriteFile (hf1, (LPVOID)sig, 2, &dwWritten, NULL);
#endif
// write data
dwWritten = 0;
dwWrite = dwRead - static_cast<DWORD>(pbBlankLine - pbBuffer);
WriteFile (hf1, pbBlankLine, dwWrite, &dwWritten, NULL);
assert (dwWritten != 0);
// close up (every time)
CloseHandle (hf1);
}
}
}
CloseHandle(hf);
}
}
}
delete [] pbBuffer;
}
void CLogging::SetFile( LPCTSTR psLogFile )
{
assert( !(NULL == psLogFile ));
if ( NULL == psLogFile )
return;
if ( NULL != m_psLogFile )
delete m_psLogFile;
m_psLogFile = new TCHAR[ _tcslen( psLogFile ) + 1 ];
if ( NULL == m_psLogFile )
return;
_tcscpy( m_psLogFile, psLogFile );
}
void CLogging::SkipDefaultPath( void )
{
m_bSkipDefaultPath = true;
}