|
|
/******************************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name: Logging.cpp
Abstract: This file contains the implementation of a set of logging classes.
Revision History: Davide Massarenti (Dmassare) 05/27/99 created
******************************************************************************/
#include "stdafx.h"
#define BUFFER_LINE_LENGTH (1024)
static WCHAR l_EndOfLine[] = L"\n";
/////////////////////////////////////////////////////////////////////////////
static DATE GetMidnight( /*[in]*/ SYSTEMTIME stTime ) { DATE dTime;
stTime.wHour = 0; stTime.wMinute = 0; stTime.wSecond = 0; stTime.wMilliseconds = 0;
::SystemTimeToVariantTime( &stTime, &dTime );
return dTime; }
/////////////////////////////////////////////////////////////////////////////
MPC::FileLog::FileLog( /*[in]*/ bool fCacheHandle, /*[in]*/ bool fUseUnicode ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::FileLog" );
// MPC::wstring m_szLogFile;
m_hFile = INVALID_HANDLE_VALUE; // HANDLE m_hFile;
m_fCacheHandle = fCacheHandle; // bool m_fCacheHandle;
m_fUseUnicode = fUseUnicode; // bool m_fUseUnicode;
}
MPC::FileLog::FileLog( /*[in]*/ const FileLog& fl ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::FileLog" );
m_szLogFile = fl.m_szLogFile; // MPC::wstring m_szLogFile;
m_hFile = INVALID_HANDLE_VALUE; // HANDLE m_hFile;
m_fCacheHandle = fl.m_fCacheHandle; // bool m_fCacheHandle;
m_fUseUnicode = fl.m_fUseUnicode; // bool m_fUseUnicode;
}
MPC::FileLog::~FileLog() { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::~FileLog" );
Close(); }
MPC::FileLog& MPC::FileLog::operator=( /*[in]*/ const FileLog& fl ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::operator=" );
Close();
m_szLogFile = fl.m_szLogFile; // MPC::wstring m_szLogFile;
m_hFile = INVALID_HANDLE_VALUE; // HANDLE m_hFile;
m_fCacheHandle = fl.m_fCacheHandle; // bool m_fCacheHandle;
m_fUseUnicode = fl.m_fUseUnicode; // bool m_fUseUnicode;
return *this; }
/////////////////////////////////////////////////////////////////////////////
HRESULT MPC::FileLog::Open() { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::Open" );
HRESULT hr;
Lock();
if(m_hFile == INVALID_HANDLE_VALUE) { // Ensure the directory exists.
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( m_szLogFile ));
__MPC_EXIT_IF_INVALID_HANDLE(hr, m_hFile, ::CreateFileW( m_szLogFile.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL ));
::SetFilePointer( m_hFile, 0, NULL, FILE_END ); }
hr = S_OK;
__MPC_FUNC_CLEANUP;
Unlock();
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::FileLog::Close() { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::Close" );
HRESULT hr;
Lock();
if(m_hFile != INVALID_HANDLE_VALUE) { ::CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE; }
hr = S_OK;
Unlock();
__MPC_FUNC_EXIT(hr); }
/////////////////////////////////////////////////////////////////////////////
HRESULT MPC::FileLog::Rotate( /*[in]*/ DWORD dwDays ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::Rotate" );
HRESULT hr; SYSTEMTIME st; WCHAR rgTime[BUFFER_LINE_LENGTH]; MPC::wstring szLogFileNew;
Lock();
//
// Before rotating, check if it's time to do it.
//
if(dwDays) { FILETIME ftCreation; SYSTEMTIME stCreation; SYSTEMTIME stNow; DATE dCreation; DATE dNow;
__MPC_EXIT_IF_METHOD_FAILS(hr, Open());
if(::GetFileTime( m_hFile, &ftCreation, NULL, NULL )) { ::FileTimeToSystemTime( &ftCreation, &stCreation ); ::GetSystemTime ( &stNow );
dCreation = GetMidnight( stCreation ); dNow = GetMidnight( stNow );
//
// If it's not been 'dwDays' since the creation of the log, don't rotate.
//
if(dCreation + (DATE)dwDays > dNow) { __MPC_SET_ERROR_AND_EXIT(hr, S_OK); } } }
__MPC_EXIT_IF_METHOD_FAILS(hr, Close());
//
// Append current time.
//
// <FileName>__<Year>_<Month>_<Day>_<hour>-<minute>-<second>
//
::GetLocalTime( &st ); StringCchPrintfW( rgTime, ARRAYSIZE(rgTime), L"__%04u-%02u-%02u_%02u-%02u-%02u", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond );
szLogFileNew = m_szLogFile; szLogFileNew.append( rgTime );
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::MoveFileExW( m_szLogFile.c_str(), szLogFileNew.c_str(), MOVEFILE_REPLACE_EXISTING ));
//
// After rotation, SET the date of creation. There's a BUG in NTFS that caches the date from the previous file...
//
if(dwDays) { FILETIME ftNow; SYSTEMTIME stNow;
__MPC_EXIT_IF_METHOD_FAILS(hr, Open());
::GetSystemTime ( &stNow ); ::SystemTimeToFileTime( &stNow, &ftNow );
::SetFileTime( m_hFile, &ftNow, NULL, NULL );
__MPC_EXIT_IF_METHOD_FAILS(hr, Close()); }
hr = S_OK;
__MPC_FUNC_CLEANUP;
Unlock();
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::FileLog::SetLocation( /*[in]*/ LPCWSTR szLogFile ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::SetLocation" );
HRESULT hr;
Lock();
__MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_STRING_NOT_EMPTY(szLogFile); __MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, Close());
m_szLogFile = szLogFile; hr = S_OK;
__MPC_FUNC_CLEANUP;
Unlock();
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::FileLog::Terminate() { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::Terminate" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, Close());
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
/////////////////////////////////////////////////////////////////////////////
HRESULT MPC::FileLog::AppendString( /*[in]*/ LPCWSTR szLine ) { _ASSERT(m_hFile != INVALID_HANDLE_VALUE);
USES_CONVERSION;
HRESULT hr; DWORD dwWritten; LPCVOID lpData; DWORD dwSize;
if(m_fUseUnicode) { lpData = szLine; dwSize = wcslen( szLine ) * sizeof(WCHAR); } else { LPCSTR szLineASCII = W2A( szLine );
lpData = szLineASCII; dwSize = strlen( szLineASCII ) * sizeof(CHAR); }
if(::WriteFile( m_hFile, lpData, dwSize, &dwWritten, NULL ) == FALSE) { hr = HRESULT_FROM_WIN32( ::GetLastError() ); } else { hr = S_OK; }
return hr; }
HRESULT MPC::FileLog::WriteEntry( /*[in]*/ LPWSTR szLine ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::WriteEntry" );
HRESULT hr; WCHAR rgTime[BUFFER_LINE_LENGTH]; SYSTEMTIME st;
Lock();
__MPC_EXIT_IF_METHOD_FAILS(hr, Open());
//
// Prepend current time.
//
::GetLocalTime( &st ); StringCchPrintfW( rgTime, ARRAYSIZE(rgTime), L"%04u/%02u/%02u %02u:%02u:%02u ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond );
while(1) { LPWSTR szEndOfLine = wcschr( szLine, '\n' );
if(szEndOfLine) *szEndOfLine++ = 0;
__MPC_EXIT_IF_METHOD_FAILS(hr, AppendString( rgTime )); __MPC_EXIT_IF_METHOD_FAILS(hr, AppendString( szLine )); __MPC_EXIT_IF_METHOD_FAILS(hr, AppendString( L"\n" ));
//
// Two cases to stop: end of string or NewLine at the end of it.
//
if(!szEndOfLine || !szEndOfLine[0]) break;
szLine = szEndOfLine; }
hr = S_OK;
__MPC_FUNC_CLEANUP;
if(m_fCacheHandle == false) (void)Close();
Unlock();
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::FileLog::LogRecordV( /*[in]*/ LPCWSTR szFormat , /*[in]*/ va_list arglist ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::WriteEntry" );
HRESULT hr; WCHAR rgLine[BUFFER_LINE_LENGTH];
__MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_STRING_NOT_EMPTY(szFormat); __MPC_PARAMCHECK_END();
StringCchVPrintfW( rgLine, ARRAYSIZE(rgLine), szFormat, arglist );
__MPC_EXIT_IF_METHOD_FAILS(hr, WriteEntry( rgLine ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::FileLog::LogRecordV( /*[in]*/ LPCSTR szFormat , /*[in]*/ va_list arglist ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::WriteEntry" );
USES_CONVERSION;
HRESULT hr; CHAR rgLine[BUFFER_LINE_LENGTH];
__MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_STRING_NOT_EMPTY(szFormat); __MPC_PARAMCHECK_END();
StringCchVPrintfA( rgLine, ARRAYSIZE(rgLine), szFormat, arglist );
__MPC_EXIT_IF_METHOD_FAILS(hr, WriteEntry( A2W(rgLine) ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::FileLog::LogRecord( /*[in]*/ LPCWSTR szFormat, /*[in]*/ ... ) { va_list arglist;
va_start( arglist, szFormat );
return LogRecordV( szFormat, arglist ); }
HRESULT MPC::FileLog::LogRecord( /*[in]*/ LPCSTR szFormat, /*[in]*/ ... ) { va_list arglist;
va_start( arglist, szFormat );
return LogRecordV( szFormat, arglist ); }
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
MPC::NTEvent::NTEvent() { __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::NTEvent" );
m_hEventSource = INVALID_HANDLE_VALUE; }
MPC::NTEvent::NTEvent( /*[in]*/ const NTEvent& ne ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::NTEvent" );
m_hEventSource = INVALID_HANDLE_VALUE; }
MPC::NTEvent::~NTEvent() { __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::~NTEvent" );
Terminate(); }
MPC::NTEvent& MPC::NTEvent::operator=( /*[in]*/ const NTEvent& fl ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::operator=" );
m_hEventSource = INVALID_HANDLE_VALUE;
return *this; }
/////////////////////////////////////////////////////////////////////////////
HRESULT MPC::NTEvent::Init( /*[in]*/ LPCWSTR szEventSourceName ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::Init" );
HRESULT hr;
Lock();
//
// Validate params.
//
if(szEventSourceName == NULL) { return E_INVALIDARG; }
if(m_hEventSource != INVALID_HANDLE_VALUE) { // only allow one init per lifetime of the object...
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_ALREADY_ASSIGNED); }
__MPC_EXIT_IF_INVALID_HANDLE(hr, m_hEventSource, ::RegisterEventSourceW( NULL, szEventSourceName ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
Unlock();
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::NTEvent::Terminate() { __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::Terminate" );
HRESULT hr;
Lock();
if(m_hEventSource != INVALID_HANDLE_VALUE) { __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::DeregisterEventSource( m_hEventSource ));
m_hEventSource = NULL; }
hr = S_OK;
__MPC_FUNC_CLEANUP;
Unlock();
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::NTEvent::LogEvent( /*[in]*/ WORD wEventType , /*[in]*/ DWORD dwEventID , /*[in]*/ ... ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::LogEvent" );
HRESULT hr; va_list arglist; LPCWSTR szParams; LPCWSTR* pParams = NULL; DWORD dwParams = 0; int i;
Lock();
if(m_hEventSource == INVALID_HANDLE_VALUE) { __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL); }
//
// Walk through the parameters twice, the first time to count them, the second time to collect them.
//
for(i=0;i<2;i++) { va_start( arglist, dwEventID );
dwParams = 0; while((szParams = va_arg( arglist, LPCWSTR )) != NULL) { if(pParams) pParams[dwParams] = szParams;
dwParams++; }
va_end( arglist );
if(i == 0 && dwParams) { pParams = (LPCWSTR*)_alloca( sizeof(*pParams) * dwParams ); } }
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ReportEventW( m_hEventSource, wEventType, 0, dwEventID, NULL, dwParams, 0, pParams, NULL ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
Unlock();
__MPC_FUNC_EXIT(hr); }
|