651 lines
15 KiB
C++
651 lines
15 KiB
C++
/*++
|
||
|
||
Copyright (c) 1996-1997 Microsoft Corporation
|
||
|
||
Module Name:
|
||
eventlog.cxx
|
||
|
||
Abstract:
|
||
|
||
This module defines the generic class for logging events.
|
||
|
||
|
||
Author:
|
||
|
||
Murali R. Krishnan (MuraliK) 28-Sept-1994
|
||
|
||
Depends Upon:
|
||
Internet Services Platform Library (isplat.lib)
|
||
Internet Services Debugging Library (isdebug.lib)
|
||
|
||
--*/
|
||
|
||
#include "precomp.hxx"
|
||
|
||
//
|
||
// Include Headers
|
||
//
|
||
|
||
#define DLL_IMPLEMENTATION
|
||
#define IMPLEMENTATION_EXPORT
|
||
|
||
# include <isplat.h>
|
||
# include <dbgutil.h>
|
||
# include <eventlog.hxx>
|
||
# include <string.hxx>
|
||
|
||
|
||
#define EVENTLOG_KEY \
|
||
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\System\\"
|
||
|
||
#define EVENTLOG_VALUE_KEY "EventMessageFile"
|
||
|
||
|
||
EVENT_LOG::EVENT_LOG(
|
||
IN LPCTSTR lpszSource
|
||
)
|
||
/*++
|
||
|
||
Description
|
||
Constructor function for given event log object.
|
||
Initializes event logging services.
|
||
|
||
Arguments:
|
||
|
||
lpszSource: Source string for the Event.
|
||
|
||
Note:
|
||
|
||
This is intended to be executed once only.
|
||
This is not to be used for creating multiple event
|
||
log handles for same given source name.
|
||
But can be used for creating EVENT_LOG objects for
|
||
different source names.
|
||
|
||
--*/
|
||
:
|
||
m_ErrorCode (NO_ERROR),
|
||
m_pDateTimeCache (NULL),
|
||
m_hLogFile (INVALID_HANDLE_VALUE)
|
||
{
|
||
|
||
(VOID)IISGetPlatformType();
|
||
|
||
IF_DEBUG( INIT_CLEAN) {
|
||
DBGPRINTF( ( DBG_CONTEXT,
|
||
" Initializing Event Log for %s[%p] fLogFile[%x]\n",
|
||
lpszSource, this, TsIsWindows95()));
|
||
}
|
||
|
||
//
|
||
// Register as an event source.
|
||
//
|
||
|
||
if ( TsIsWindows95() ) {
|
||
|
||
m_hEventSource = RegisterEventSourceChicagoStyle(
|
||
lpszSource,
|
||
&m_hLogFile
|
||
);
|
||
} else {
|
||
|
||
m_hEventSource = RegisterEventSource( NULL, lpszSource);
|
||
}
|
||
|
||
if ( m_hEventSource != NULL ) {
|
||
|
||
//
|
||
// Success!
|
||
//
|
||
|
||
IF_DEBUG( ERROR) {
|
||
DBGPRINTF( ( DBG_CONTEXT,
|
||
" Event Log for %s initialized (hEventSource=%p)\n",
|
||
lpszSource,
|
||
m_hEventSource));
|
||
}
|
||
} else {
|
||
|
||
DBG_ASSERT(m_hLogFile == INVALID_HANDLE_VALUE);
|
||
|
||
//
|
||
// An Error in initializing the event log.
|
||
//
|
||
|
||
m_ErrorCode = GetLastError();
|
||
DBGPRINTF( ( DBG_CONTEXT,
|
||
"Could not register event source (%s) ( Error %lu)\n",
|
||
lpszSource,
|
||
m_ErrorCode));
|
||
}
|
||
|
||
return;
|
||
|
||
} // EVENT_LOG::EVENT_LOG()
|
||
|
||
|
||
|
||
EVENT_LOG::~EVENT_LOG(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Description:
|
||
Destructor function for given EVENT_LOG object.
|
||
Terminates event logging functions and closes
|
||
event log handle
|
||
|
||
--*/
|
||
{
|
||
|
||
IF_DEBUG( INIT_CLEAN) {
|
||
DBGPRINTF( ( DBG_CONTEXT,
|
||
"Terminating events logging[%p] fFile[%x]\n",
|
||
this, TsIsWindows95() ));
|
||
}
|
||
|
||
if ( TsIsWindows95() ) {
|
||
|
||
if ( m_hLogFile != INVALID_HANDLE_VALUE ) {
|
||
FlushFileBuffers(m_hLogFile);
|
||
DBG_REQUIRE(CloseHandle( m_hLogFile ));
|
||
m_hLogFile = INVALID_HANDLE_VALUE;
|
||
}
|
||
|
||
if ( m_pDateTimeCache != NULL ) {
|
||
delete m_pDateTimeCache;
|
||
m_pDateTimeCache = NULL;
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// If there is a valid Events handle, deregister it
|
||
//
|
||
|
||
if ( m_hEventSource != NULL) {
|
||
|
||
BOOL fSuccess;
|
||
|
||
fSuccess = DeregisterEventSource( m_hEventSource);
|
||
|
||
if ( !fSuccess) {
|
||
|
||
//
|
||
// An Error in DeRegistering
|
||
//
|
||
|
||
m_ErrorCode = GetLastError();
|
||
|
||
IF_DEBUG( INIT_CLEAN) {
|
||
|
||
DBGPRINTF( ( DBG_CONTEXT,
|
||
"Termination of EventLog[%p] failed."
|
||
" error %lu\n",
|
||
this,
|
||
m_ErrorCode));
|
||
}
|
||
}
|
||
|
||
//
|
||
// Reset the handle's value. Just as a precaution
|
||
//
|
||
m_hEventSource = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
IF_DEBUG( API_EXIT) {
|
||
DBGPRINTF( ( DBG_CONTEXT, "Terminated events log[%p]\n",this));
|
||
}
|
||
|
||
} /* EVENT_LOG::~EVENT_LOG() */
|
||
|
||
|
||
|
||
VOID
|
||
EVENT_LOG::LogEvent(
|
||
IN DWORD idMessage,
|
||
IN WORD nSubStrings,
|
||
IN const CHAR * rgpszSubStrings[],
|
||
IN DWORD errCode)
|
||
/*++
|
||
|
||
Description:
|
||
Log an event to the event logger
|
||
|
||
Arguments:
|
||
|
||
idMessage Identifies the event message
|
||
|
||
nSubStrings Number of substrings to include in
|
||
this message. (Maybe 0)
|
||
|
||
rgpszSubStrings array of substrings included in the message
|
||
(Maybe NULL if nSubStrings == 0)
|
||
|
||
errCode An error code from Win32 or WinSock or NT_STATUS.
|
||
If this is not Zero, it is considered as
|
||
"raw" data to be included in message
|
||
|
||
Returns:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
|
||
WORD wType; // Type of Event to be logged
|
||
|
||
//
|
||
// Find type of message for the event log
|
||
//
|
||
|
||
IF_DEBUG( API_ENTRY) {
|
||
|
||
DWORD i;
|
||
|
||
DBGPRINTF( ( DBG_CONTEXT,
|
||
"reporting event %08lX, Error Code = %lu\n",
|
||
idMessage,
|
||
errCode ));
|
||
|
||
for( i = 0 ; i < nSubStrings ; i++ ) {
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
" substring[%lu] = %s\n",
|
||
i,
|
||
rgpszSubStrings[i] ));
|
||
}
|
||
}
|
||
|
||
if ( NT_INFORMATION( idMessage)) {
|
||
|
||
wType = EVENTLOG_INFORMATION_TYPE;
|
||
|
||
} else {
|
||
|
||
if ( NT_WARNING( idMessage)) {
|
||
|
||
wType = EVENTLOG_WARNING_TYPE;
|
||
|
||
} else {
|
||
|
||
wType = EVENTLOG_ERROR_TYPE;
|
||
|
||
DBG_ASSERT(NT_ERROR( idMessage));
|
||
}
|
||
}
|
||
|
||
//
|
||
// Log the event
|
||
//
|
||
|
||
EVENT_LOG::LogEventPrivate( idMessage,
|
||
wType,
|
||
nSubStrings,
|
||
rgpszSubStrings,
|
||
errCode);
|
||
|
||
|
||
return;
|
||
|
||
} /* EVENT_LOG::LogEvent() */
|
||
|
||
|
||
//
|
||
// Private functions.
|
||
//
|
||
|
||
VOID
|
||
EVENT_LOG::LogEventPrivate(
|
||
IN DWORD idMessage,
|
||
IN WORD wEventType,
|
||
IN WORD nSubStrings,
|
||
IN const CHAR * apszSubStrings[],
|
||
IN DWORD errCode
|
||
)
|
||
/*++
|
||
|
||
Description:
|
||
Log an event to the event logger.
|
||
( Private version, includes EventType)
|
||
|
||
Arguments:
|
||
|
||
idMessage Identifies the event message
|
||
|
||
wEventType Specifies the severety of the event
|
||
(error, warning, or informational).
|
||
|
||
nSubStrings Number of substrings to include in
|
||
this message. (Maybe 0)
|
||
|
||
apszSubStrings array of substrings included in the message
|
||
(Maybe NULL if nSubStrings == 0)
|
||
|
||
errCode An error code from Win32 or WinSock or NT_STATUS.
|
||
If this is not Zero, it is considered as
|
||
"raw" data to be included in message
|
||
|
||
Returns:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
VOID * pRawData = NULL;
|
||
DWORD cbRawData = 0;
|
||
BOOL fReport;
|
||
DWORD dwErr;
|
||
|
||
if ( m_hEventSource == NULL ) {
|
||
|
||
IF_DEBUG(ERROR) {
|
||
DBGPRINTF((DBG_CONTEXT,"Attempt to log with no event source\n"));
|
||
}
|
||
return;
|
||
}
|
||
|
||
ASSERT( (nSubStrings == 0) || (apszSubStrings != NULL));
|
||
|
||
if( errCode != 0 ) {
|
||
pRawData = &errCode;
|
||
cbRawData = sizeof(errCode);
|
||
}
|
||
|
||
m_ErrorCode = NO_ERROR;
|
||
dwErr = GetLastError();
|
||
|
||
if ( TsIsWindows95() ) {
|
||
fReport = ReportEventChicagoStyle(
|
||
m_hEventSource,
|
||
m_hLogFile,
|
||
idMessage,
|
||
apszSubStrings,
|
||
errCode
|
||
);
|
||
|
||
} else {
|
||
|
||
fReport = ReportEvent(
|
||
m_hEventSource, // hEventSource
|
||
wEventType, // fwEventType
|
||
0, // fwCategory
|
||
idMessage, // IDEvent
|
||
NULL, // pUserSid,
|
||
nSubStrings, // cStrings
|
||
cbRawData, // cbData
|
||
(LPCTSTR *) apszSubStrings, // plpszStrings
|
||
pRawData ); // lpvData
|
||
|
||
#ifdef DBG
|
||
|
||
//
|
||
// Output the event log to the debugger
|
||
//
|
||
|
||
CHAR buffer[MAX_PATH+1];
|
||
PCHAR pBuffer = buffer;
|
||
|
||
::FormatMessageA(FORMAT_MESSAGE_MAX_WIDTH_MASK |
|
||
FORMAT_MESSAGE_FROM_HMODULE |
|
||
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||
m_hEventSource,
|
||
idMessage,
|
||
0,
|
||
(LPSTR)pBuffer,
|
||
(DWORD)sizeof(buffer),
|
||
(va_list*)apszSubStrings
|
||
);
|
||
|
||
DBGPRINTF((DBG_CONTEXT,"Reporting EVENT_LOG Event - %s\n", buffer));
|
||
|
||
#endif
|
||
}
|
||
|
||
if ( !fReport ) {
|
||
|
||
IF_DEBUG( ERROR) {
|
||
|
||
m_ErrorCode = GetLastError();
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"Cannot report event for %p, error %lu\n",
|
||
this,
|
||
m_ErrorCode));
|
||
}
|
||
}
|
||
else {
|
||
SetLastError( dwErr );
|
||
}
|
||
|
||
} // EVENT_LOG::LogEventPrivate()
|
||
|
||
|
||
|
||
HANDLE
|
||
EVENT_LOG::RegisterEventSourceChicagoStyle(
|
||
IN LPCSTR lpszSource,
|
||
IN PHANDLE hFile
|
||
)
|
||
/*++
|
||
|
||
Description:
|
||
Register event source in win95
|
||
|
||
Arguments:
|
||
|
||
lpszSource - name of event source
|
||
hFile - on return, contains handle to log file
|
||
|
||
Returns:
|
||
|
||
if successful, Handle to event source
|
||
NULL, otherwise
|
||
--*/
|
||
{
|
||
HANDLE hSource = NULL;
|
||
CHAR szPath[MAX_PATH+1];
|
||
STR regKey;
|
||
DWORD len;
|
||
DWORD err = NO_ERROR;
|
||
HKEY hKey;
|
||
HANDLE hEventFile = INVALID_HANDLE_VALUE;
|
||
|
||
//
|
||
// Initialize the cache
|
||
//
|
||
|
||
m_pDateTimeCache = new ASCLOG_DATETIME_CACHE(); //log format
|
||
if ( m_pDateTimeCache == NULL ) {
|
||
err = GetLastError();
|
||
|
||
DBGPRINTF((DBG_CONTEXT,
|
||
"Cannot allocate datetime cache[%d]\n", err));
|
||
goto exit;
|
||
}
|
||
|
||
//
|
||
// Contruct the log file name
|
||
//
|
||
|
||
len = GetWindowsDirectory(szPath, sizeof(szPath));
|
||
|
||
if ( len == 0 ) {
|
||
DBGPRINTF((DBG_CONTEXT,"GetWindowsDirectory returns 0\n"));
|
||
goto exit;
|
||
}
|
||
|
||
DBG_ASSERT(len <= MAX_PATH);
|
||
|
||
strcat(szPath, "\\");
|
||
strcat(szPath, lpszSource);
|
||
strcat(szPath, ".event.log");
|
||
|
||
IF_DEBUG( INIT_CLEAN) {
|
||
DBGPRINTF((DBG_CONTEXT,"Event log file set to %s\n", szPath));
|
||
}
|
||
|
||
//
|
||
// Open the file
|
||
//
|
||
|
||
hEventFile = CreateFile(
|
||
szPath,
|
||
GENERIC_WRITE,
|
||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||
NULL,
|
||
OPEN_ALWAYS,
|
||
FILE_ATTRIBUTE_NORMAL,
|
||
NULL
|
||
);
|
||
|
||
if ( hEventFile == INVALID_HANDLE_VALUE ) {
|
||
err = GetLastError();
|
||
goto exit;
|
||
}
|
||
|
||
//
|
||
// Move to end of file
|
||
//
|
||
|
||
if ( SetFilePointer( hEventFile, 0, NULL, FILE_END ) == (DWORD)-1 ) {
|
||
err = GetLastError();
|
||
goto exit;
|
||
}
|
||
|
||
//
|
||
// If log file successfully opened - register event message source file.
|
||
// On Win9x registration simply means locating module handle for DLL,
|
||
// where we will load messages from.
|
||
//
|
||
|
||
regKey.Copy(EVENTLOG_KEY);
|
||
regKey.Append(lpszSource);
|
||
|
||
err = RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE,
|
||
regKey.QueryStr(),
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
&hKey);
|
||
|
||
if ( err == NO_ERROR) {
|
||
|
||
DWORD cbBuffer;
|
||
|
||
cbBuffer = sizeof(szPath);
|
||
szPath[0] = '\0';
|
||
|
||
err = RegQueryValueEx( hKey,
|
||
EVENTLOG_VALUE_KEY,
|
||
NULL,
|
||
NULL,
|
||
(LPBYTE) szPath,
|
||
&cbBuffer);
|
||
|
||
RegCloseKey( hKey);
|
||
|
||
if ( err == NO_ERROR ) {
|
||
|
||
hSource = GetModuleHandle(szPath);
|
||
if ( hSource == NULL ) {
|
||
err = GetLastError();
|
||
|
||
DBGPRINTF((DBG_CONTEXT,"GetModuleHandle[%s] returns %d\n",
|
||
szPath, err));
|
||
}
|
||
} else {
|
||
|
||
DBGPRINTF((DBG_CONTEXT,
|
||
"Cannot find value %s. Err = %d\n",
|
||
EVENTLOG_VALUE_KEY, err ));
|
||
}
|
||
} else {
|
||
|
||
DBGPRINTF((DBG_CONTEXT,
|
||
"Cannot open key %s. Err = %d\n",
|
||
regKey.QueryStr(), err ));
|
||
}
|
||
|
||
exit:
|
||
|
||
if ( (err != NO_ERROR) || (hSource == NULL) ) {
|
||
|
||
if ( hEventFile != INVALID_HANDLE_VALUE ) {
|
||
CloseHandle( hEventFile );
|
||
hEventFile = INVALID_HANDLE_VALUE;
|
||
}
|
||
hSource = NULL;
|
||
SetLastError(err);
|
||
}
|
||
|
||
*hFile = hEventFile;
|
||
return(hSource);
|
||
|
||
} // RegisterEventSourceChicagoStyle()
|
||
|
||
|
||
|
||
BOOL
|
||
EVENT_LOG::ReportEventChicagoStyle(
|
||
IN HANDLE hEventSource,
|
||
IN HANDLE hLogFile,
|
||
IN DWORD idMessage,
|
||
IN LPCSTR * apszSubStrings,
|
||
IN DWORD dwErrorCode
|
||
)
|
||
{
|
||
SYSTEMTIME st;
|
||
DWORD cch;
|
||
DWORD nDate;
|
||
CHAR buffer[MAX_PATH+1];
|
||
PCHAR pBuffer = buffer;
|
||
BOOL fReturn = FALSE;
|
||
|
||
GetLocalTime( &st );
|
||
nDate = m_pDateTimeCache->GetFormattedDateTime(&st, pBuffer);
|
||
pBuffer += nDate;
|
||
|
||
//
|
||
// Read message and add inserts
|
||
//
|
||
|
||
cch = ::FormatMessageA(FORMAT_MESSAGE_MAX_WIDTH_MASK |
|
||
FORMAT_MESSAGE_FROM_HMODULE |
|
||
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||
hEventSource,
|
||
idMessage,
|
||
0,
|
||
(LPSTR)pBuffer,
|
||
(DWORD)(sizeof(buffer) - nDate),
|
||
(va_list*)apszSubStrings
|
||
);
|
||
|
||
if (cch != 0) {
|
||
|
||
DWORD nBytes = 0;
|
||
|
||
DBGPRINTF((DBG_CONTEXT,"Reporting EVENT_LOG Event - %s\n", buffer));
|
||
|
||
cch += nDate;
|
||
fReturn = WriteFile(
|
||
hLogFile,
|
||
buffer,
|
||
cch,
|
||
&nBytes,
|
||
NULL);
|
||
|
||
if (nBytes != 0) {
|
||
|
||
DBG_ASSERT(cch == nBytes);
|
||
|
||
cch = wsprintf(buffer,"[%x]\r\n",dwErrorCode);
|
||
fReturn = WriteFile(hLogFile,buffer,cch,&nBytes,NULL);
|
||
}
|
||
}
|
||
|
||
return(fReturn);
|
||
|
||
} // ReportEventChicagoStyle()
|
||
|