2025-11-27 16:46:48 +09:00

700 lines
16 KiB
C++

// ==========================================================================
// Class Implementation : COXEventLog
// ==========================================================================
// Source file : evntlog.cpp
// Version: 9.3
// This software along with its related components, documentation and files ("The Libraries")
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office. For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h" // standard MFC include
#include "evntlog.h" // class specification
#include "OXIteratorRegistryItem.h"
#include "UTB64Bit.h"
#if defined( _DEBUG )
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC( COXEventLog, CObject );
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// Definition of static members
// Data members -------------------------------------------------------------
// protected:
// private:
// Member functions ---------------------------------------------------------
// public:
COXEventLog::COXEventLog()
{
Initialize();
}
COXEventLog::COXEventLog(LPCTSTR pszSourceName)
{
Initialize();
RegisterSource(pszSourceName);
}
COXEventLog::~COXEventLog()
{
if (m_EventSourceHandle != INVALID_HANDLE_VALUE)
{
DeregisterSource();
}
if (m_LogHandle != INVALID_HANDLE_VALUE)
{
Close();
}
Initialize();
}
void COXEventLog::Initialize()
{
ASSERT_VALID( this );
m_sComputerName.Empty();
m_sLogName.Empty();
m_LogHandle = INVALID_HANDLE_VALUE;
m_EventSourceHandle = INVALID_HANDLE_VALUE;
m_ErrorCode = 0;
m_NumberOfBytesRead = 0;
m_NumberOfBytesInNextRecord = 0;
}
BOOL COXEventLog::Backup(LPCTSTR pszNameOfBackupFile)
{
ASSERT_VALID(this);
ASSERT(m_LogHandle != INVALID_HANDLE_VALUE);
ASSERT(pszNameOfBackupFile != NULL);
if (m_LogHandle == INVALID_HANDLE_VALUE)
{
m_ErrorCode = ERROR_INVALID_HANDLE;
return(FALSE);
}
if (pszNameOfBackupFile == NULL)
{
m_ErrorCode = ERROR_INVALID_PARAMETER;
return(FALSE);
}
BOOL return_value = ::BackupEventLog(m_LogHandle, pszNameOfBackupFile);
if (return_value != TRUE)
{
m_ErrorCode = ::GetLastError();
}
return(return_value);
}
BOOL COXEventLog::Clear(LPCTSTR pszNameOfBackupFile)
{
ASSERT_VALID( this );
ASSERT(m_LogHandle != INVALID_HANDLE_VALUE);
if (m_LogHandle == INVALID_HANDLE_VALUE)
{
m_ErrorCode = ERROR_INVALID_HANDLE;
return(FALSE);
}
/*
** pszNameOfBackupFile can be NULL
*/
BOOL return_value = ::ClearEventLog(m_LogHandle, pszNameOfBackupFile);
if (return_value != TRUE)
{
m_ErrorCode = ::GetLastError();
}
return(return_value);
}
BOOL COXEventLog::Close()
{
ASSERT_VALID(this);
if (m_LogHandle == INVALID_HANDLE_VALUE)
{
TRACE0("COXEventLog::In Close : handle Invalid");
return(FALSE);
}
BOOL return_value = ::CloseEventLog(m_LogHandle);
if (return_value != TRUE)
{
m_ErrorCode = ::GetLastError();
}
m_LogHandle = INVALID_HANDLE_VALUE;
return(return_value);
}
BOOL COXEventLog::CreateApplicationLog(LPCTSTR pszApplicationName,
LPCTSTR pszFileContainingMessageTableResource,
DWORD dwSupportedTypes)
{
ASSERT_VALID(this);
ASSERT(pszApplicationName != NULL);
ASSERT(pszFileContainingMessageTableResource != NULL);
if (pszApplicationName == NULL ||
lstrlen(pszApplicationName) <= 0 ||
pszFileContainingMessageTableResource == NULL ||
lstrlen(pszFileContainingMessageTableResource) <= 0)
{
m_ErrorCode = ERROR_INVALID_PARAMETER;
return(FALSE);
}
COXRegistryItem regItem;
CString log_key_name(_T("\\LocalMachine\\SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"));
log_key_name += pszApplicationName;
log_key_name += _T("\\");
regItem.SetFullRegistryItem(log_key_name);
if (regItem.Open() == FALSE)
{
m_ErrorCode = regItem.GetLastError();
return FALSE;
}
if (regItem.SetStringValue(pszFileContainingMessageTableResource,
_T("EventMessageFile"),
TRUE) == FALSE)
{
m_ErrorCode = regItem.GetLastError();
return FALSE;
}
if (regItem.SetNumberValue(dwSupportedTypes,
_T("TypesSupported")) == FALSE)
{
m_ErrorCode = regItem.GetLastError();
return FALSE;
}
return TRUE;
}
BOOL COXEventLog::DeleteApplicationLog(LPCTSTR pszApplicationName)
{
ASSERT_VALID(this);
ASSERT(pszApplicationName != NULL);
if (pszApplicationName == NULL ||
lstrlen(pszApplicationName) <= 0)
{
m_ErrorCode = ERROR_INVALID_PARAMETER;
return(FALSE);
}
COXRegistryItem regItem;
CString log_key_name(_T("\\LocalMachine\\SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"));
log_key_name += pszApplicationName;
log_key_name += _T("\\");
regItem.SetFullRegistryItem(log_key_name);
if (regItem.Delete() == FALSE)
{
m_ErrorCode = regItem.GetLastError();
return FALSE;
}
/*
** Microsoft has a bug in this area. Even though we deleted the application from the
** HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\
** registry area, they don't provide a way to delete the application from the
** HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\Sources
** value. The application name is one of the strings in this REG_MULTI_SZ value. We
** still need to delete it from there. The names listed in this value appear in the
** "Source" combobox of the Event Viewer application View->Filter Events... menu selection.
*/
log_key_name = _T("\\LocalMachine\\SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");
regItem.SetFullRegistryItem(log_key_name);
CStringArray sources;
if (regItem.Open(FALSE) == FALSE ||
regItem.GetMultiStringValue(sources, _T("Sources")) == FALSE)
{
m_ErrorCode = regItem.GetLastError();
return FALSE;
}
int index = 0;
int number_of_sources = PtrToInt(sources.GetSize());
BOOL application_was_found = FALSE;
while(index < number_of_sources)
{
if (sources[index] == pszApplicationName)
{
application_was_found = TRUE;
sources.RemoveAt(index);
index = number_of_sources;
}
index++;
}
if (application_was_found != FALSE)
{
regItem.SetMultiStringValue(sources, _T("Sources"));
}
return TRUE;
}
BOOL COXEventLog::DeregisterSource()
{
ASSERT_VALID(this);
BOOL return_value = TRUE;
if (m_EventSourceHandle != INVALID_HANDLE_VALUE)
{
return_value = ::DeregisterEventSource(m_EventSourceHandle);
if (return_value != TRUE)
{
m_ErrorCode = ::GetLastError();
}
m_EventSourceHandle = INVALID_HANDLE_VALUE;
}
return(return_value);
}
#if defined(_DEBUG)
void COXEventLog::Dump(CDumpContext& dump_context) const
{
CObject::Dump(dump_context);
dump_context << _T("m_LogHandle = ") << m_LogHandle << _T("\n");
dump_context << _T("m_EventSourceHandle = ") << m_EventSourceHandle << _T("\n");
dump_context << _T("m_ErrorCode = ") << m_ErrorCode << _T("\n");
dump_context << _T("m_NumberOfBytesRead = ") << m_NumberOfBytesRead << _T("\n");
dump_context << _T("m_NumberOfBytesInNextRecord = ") << m_NumberOfBytesInNextRecord << _T("\n");
dump_context << _T("m_sComputerName = \"") << m_sComputerName << _T("\"\n");
dump_context << _T("m_sLogName = \"") << m_sLogName << _T("\"\n");
}
void COXEventLog::AssertValid() const
{
CObject::AssertValid();
}
#endif // _DEBUG
DWORD COXEventLog::GetErrorCode() const
{
ASSERT_VALID(this);
return(m_ErrorCode);
}
BOOL COXEventLog::GetNumberOfRecords(DWORD& dwNumberOfRecords)
{
ASSERT_VALID(this);
ASSERT(m_LogHandle != INVALID_HANDLE_VALUE);
if (m_LogHandle == INVALID_HANDLE_VALUE)
{
m_ErrorCode = ERROR_INVALID_HANDLE;
return(FALSE);
}
BOOL return_value = ::GetNumberOfEventLogRecords(m_LogHandle, &dwNumberOfRecords);
if (return_value != TRUE)
{
m_ErrorCode = ::GetLastError();
}
return(return_value);
}
BOOL COXEventLog::GetNumberOfBytesInNextRecord(DWORD& dwNumberOfBytesInNextRecord)
{
dwNumberOfBytesInNextRecord = m_NumberOfBytesInNextRecord;
return TRUE;
}
BOOL COXEventLog::NotifyChange(HANDLE hEventHandle, HANDLE hLogHandle /* = NULL */)
{
ASSERT_VALID(this);
ASSERT(hEventHandle != INVALID_HANDLE_VALUE);
if (hEventHandle == INVALID_HANDLE_VALUE)
{
m_ErrorCode = ERROR_INVALID_PARAMETER;
return( FALSE );
}
if (hLogHandle == INVALID_HANDLE_VALUE || hLogHandle == NULL)
{
hLogHandle = m_LogHandle;
}
ASSERT(hLogHandle != INVALID_HANDLE_VALUE);
if (hLogHandle == INVALID_HANDLE_VALUE)
{
m_ErrorCode = ERROR_INVALID_HANDLE;
return(FALSE);
}
BOOL return_value = ::NotifyChangeEventLog(hLogHandle, hEventHandle);
if (return_value != TRUE)
{
m_ErrorCode = ::GetLastError();
}
return(return_value);
}
BOOL COXEventLog::Open(LPCTSTR pszLogName, LPCTSTR pszNameOfComputer /* = NULL */)
{
ASSERT_VALID(this);
ASSERT(pszLogName != NULL);
/*
** name_of_computer can be NULL
*/
if (pszLogName == NULL)
{
m_ErrorCode = ERROR_INVALID_PARAMETER;
return(FALSE);
}
if (m_LogHandle != INVALID_HANDLE_VALUE && m_LogHandle != NULL)
{
// We do not return FALSE here, should this fail, because the old handle could be invalid
// but that is not our concern anymore
Close();
}
BOOL return_value = TRUE;
m_LogHandle = ::OpenEventLog(pszNameOfComputer, pszLogName);
if (m_LogHandle == NULL)
{
m_LogHandle = INVALID_HANDLE_VALUE;
m_ErrorCode = ::GetLastError();
return_value = FALSE;
}
else
{
if (pszNameOfComputer == NULL)
{
TCHAR computer_name[MAX_PATH] = _T("");
DWORD size = sizeof(computer_name);
if (::GetComputerName(computer_name, &size) == TRUE)
{
m_sComputerName = computer_name;
}
else
{
m_sComputerName.Empty();
}
}
else
{
m_sComputerName = pszNameOfComputer;
}
}
return(return_value);
}
BOOL COXEventLog::OpenBackup(LPCTSTR pszNameOfBackupFile, LPCTSTR pszNameOfComputer /* = NULL */)
{
ASSERT_VALID(this);
ASSERT(pszNameOfBackupFile != NULL);
if (m_LogHandle != INVALID_HANDLE_VALUE && m_LogHandle != NULL)
{
// We do not return FALSE here, should this fail, because the old handle could be invalid
// but that is not our concern anymore
Close();
}
/*
** pszNameOfComputer can be NULL
*/
if (pszNameOfBackupFile == NULL)
{
m_ErrorCode = ERROR_INVALID_PARAMETER;
return(FALSE);
}
BOOL return_value = TRUE;
m_LogHandle = ::OpenBackupEventLog(pszNameOfComputer, pszNameOfBackupFile);
if (m_LogHandle == NULL)
{
m_LogHandle = INVALID_HANDLE_VALUE;
m_ErrorCode = ::GetLastError();
return_value = FALSE;
}
else
{
if (pszNameOfComputer == NULL)
{
TCHAR computer_name[ MAX_PATH ] = _T("");
DWORD size = sizeof(computer_name);
if (::GetComputerName(computer_name, &size) == TRUE)
{
m_sComputerName = computer_name;
}
else
{
m_sComputerName.Empty();
}
}
else
{
m_sComputerName = pszNameOfComputer;
}
}
return(return_value);
}
BOOL COXEventLog::Read(DWORD dwRecordNumber, LPVOID pBuffer, DWORD& dwNumberOfBytesToRead,
DWORD dwHowToRead /* = EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ */)
{
ASSERT_VALID(this);
ASSERT(pBuffer != NULL);
ASSERT(m_LogHandle != INVALID_HANDLE_VALUE);
if (m_LogHandle == INVALID_HANDLE_VALUE)
{
m_ErrorCode = ERROR_INVALID_HANDLE;
return(FALSE);
}
if (pBuffer == NULL)
{
m_ErrorCode = ERROR_INVALID_PARAMETER;
return( FALSE );
}
BOOL return_value = ::ReadEventLog(m_LogHandle,
dwHowToRead,
dwRecordNumber,
pBuffer,
dwNumberOfBytesToRead,
&dwNumberOfBytesToRead,
&m_NumberOfBytesInNextRecord);
if (return_value != TRUE)
{
m_ErrorCode = ::GetLastError();
}
return(return_value);
}
BOOL COXEventLog::RegisterSource(LPCTSTR pszSourceName, LPCTSTR pszNameOfComputer /* = NULL */)
{
ASSERT_VALID(this);
ASSERT(pszSourceName != NULL);
/*
** pszNameOfComputer can be NULL
*/
if (pszSourceName == NULL)
{
m_ErrorCode = ERROR_INVALID_PARAMETER;
return(FALSE);
}
BOOL return_value = TRUE;
if (m_EventSourceHandle != INVALID_HANDLE_VALUE)
{
DeregisterSource();
}
m_EventSourceHandle = ::RegisterEventSource(pszNameOfComputer, pszSourceName);
if (m_EventSourceHandle == NULL)
{
TRACE0("RegisterEventSource returned NULL\n");
m_EventSourceHandle = INVALID_HANDLE_VALUE;
m_ErrorCode = ::GetLastError();
return_value = FALSE;
}
return(return_value);
}
BOOL COXEventLog::Report(EventType eEventType,
DWORD dwEventIdentifier,
WORD wCategory /* = 0 */,
WORD wNumberOfStrings /* = 0 */,
LPCTSTR* pszStringArray /* = NULL */,
DWORD dwNumberOfRawDataBytes /* = 0 */,
LPVOID pRawDataBuffer /* = NULL */,
PSID pUserSecurityIdentifier /* = NULL */)
{
ASSERT_VALID(this);
BYTE security_identifier_buffer[4096];
DWORD size_of_security_identifier_buffer = sizeof(security_identifier_buffer);
if (pUserSecurityIdentifier == NULL)
{
TCHAR user_name[256];
DWORD size_of_user_name = sizeof(user_name);
TCHAR domain_name[256];
DWORD size_of_domain_name = sizeof(domain_name);
SID_NAME_USE type_of_security_identifier;
::ZeroMemory(user_name, size_of_user_name);
::ZeroMemory(domain_name, size_of_domain_name);
::ZeroMemory(security_identifier_buffer, size_of_security_identifier_buffer);
::GetUserName(user_name, &size_of_user_name);
if (::LookupAccountName(NULL,
user_name,
&security_identifier_buffer,
&size_of_security_identifier_buffer,
domain_name,
&size_of_domain_name,
&type_of_security_identifier) == TRUE)
{
pUserSecurityIdentifier = security_identifier_buffer;
}
}
BOOL return_value = FALSE;
if (m_EventSourceHandle != INVALID_HANDLE_VALUE)
{
return_value = ::ReportEvent(m_EventSourceHandle,
(WORD)eEventType,
wCategory,
dwEventIdentifier,
pUserSecurityIdentifier,
wNumberOfStrings,
dwNumberOfRawDataBytes,
pszStringArray,
pRawDataBuffer);
TRACE0("COXEventLog::Report(), Calling ReportEvent() went OK\n");
if (return_value != TRUE)
{
m_ErrorCode = ::GetLastError();
}
}
else
{
m_ErrorCode = ERROR_INVALID_HANDLE;
}
return(return_value);
}
BOOL COXEventLog::Report(LPCTSTR pszLogName, DWORD dwMessageStringResourceID,
WORD wNumberOfStrings /* = 0 */, LPCTSTR* pszStringArray /* = NULL */)
{
ASSERT_VALID(this);
ASSERT(pszLogName != NULL);
if (pszLogName == NULL)
{
m_ErrorCode = ERROR_INVALID_PARAMETER;
return(FALSE);
}
if (pszStringArray == (LPCTSTR*)NULL)
{
m_ErrorCode = ERROR_INVALID_HANDLE;
return(FALSE);
}
if (RegisterSource(pszLogName) == TRUE)
{
if (Report(eventError, dwMessageStringResourceID, 0, wNumberOfStrings, pszStringArray) != TRUE)
{
DeregisterSource();
return(FALSE);
}
DeregisterSource();
}
else
{
return(FALSE);
}
return(TRUE);
}
void COXEventLog::ReportError(LPCTSTR pszStringToReport)
{
LPCTSTR string_array[1];
if (pszStringToReport == (LPCTSTR)NULL)
{
string_array[0] = _T("COXEventLog::ReportError(NULL)");
}
else
{
string_array[0] = pszStringToReport;
}
TRACE0("COXEventLog::ReportError()\n");
Report(eventError, 0, 0, 1, string_array);
}
void COXEventLog::ReportInformation(LPCTSTR pszStringToReport)
{
LPCTSTR string_array[1];
if (pszStringToReport == (LPCTSTR)NULL)
{
string_array[0] = _T("COXEventLog::ReportInformation(NULL)");
}
else
{
string_array[0] = pszStringToReport;
}
Report(eventInformation, 0, 0, 1, string_array);
}