273 lines
6.9 KiB
C++
273 lines
6.9 KiB
C++
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* File: eventlog.cpp
|
||
|
|
||
|
Description: Implements a subset of the NT event log APIs as a C++ class.
|
||
|
CEventLog is intended only to provide a convenient method for writing
|
||
|
NT event log messages. No reading of event log entries is supported.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
02/14/98 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
#include "pch.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "eventlog.h"
|
||
|
#include "registry.h"
|
||
|
|
||
|
TCHAR CEventLog::m_szFmtDec[] = TEXT("%1!d!");
|
||
|
TCHAR CEventLog::m_szFmtHex[] = TEXT("0x%1!X!");
|
||
|
|
||
|
|
||
|
CEventLog::~CEventLog(
|
||
|
void
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_EVENTLOG, DL_MID, TEXT("CEventLog::~CEventLog")));
|
||
|
Close();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Register the specified event source.
|
||
|
// Note that the registry entries must already exist.
|
||
|
// HKLM\System\CurrentControlSet\Services\EventLog\Application\<pszEventSource>
|
||
|
// Requires values "EventMessageFile" and "TypesSupported".
|
||
|
//
|
||
|
HRESULT
|
||
|
CEventLog::Initialize(
|
||
|
LPCTSTR pszEventSource
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_EVENTLOG, DL_MID, TEXT("CEventLog::Initialize")));
|
||
|
if (NULL != m_hLog)
|
||
|
{
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
m_hLog = RegisterEventSource(NULL, pszEventSource);
|
||
|
if (NULL == m_hLog)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
DBGERROR((TEXT("Error 0x%08X registering event source \"%s\""), hr, pszEventSource));
|
||
|
DBGERROR((TEXT("Run regsvr32 on dskquota.dll")));
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Deregister the event source.
|
||
|
//
|
||
|
void
|
||
|
CEventLog::Close(
|
||
|
void
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_EVENTLOG, DL_MID, TEXT("CEventLog::Close")));
|
||
|
|
||
|
if (NULL != m_hLog)
|
||
|
{
|
||
|
DeregisterEventSource(m_hLog);
|
||
|
m_hLog = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Report an event. No replaceable parameters explicitly specified.
|
||
|
// If msg string contains replaceable parameters, use Push() to
|
||
|
// build list of replacement strings.
|
||
|
//
|
||
|
HRESULT
|
||
|
CEventLog::ReportEvent(
|
||
|
WORD wType,
|
||
|
WORD wCategory,
|
||
|
DWORD dwEventID,
|
||
|
PSID lpUserSid, // [optional]
|
||
|
LPVOID pvRawData, // [optional]
|
||
|
DWORD cbRawData // [optional]
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_EVENTLOG, DL_MID, TEXT("CEventLog::ReportEvent")));
|
||
|
|
||
|
if (NULL == m_hLog)
|
||
|
{
|
||
|
DBGERROR((TEXT("Event log not initialized")));
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
BOOL bResult = false;
|
||
|
HRESULT hr = NOERROR;
|
||
|
if (0 < m_rgstrText.Count())
|
||
|
{
|
||
|
bResult = ReportEvent(wType,
|
||
|
wCategory,
|
||
|
dwEventID,
|
||
|
m_rgstrText,
|
||
|
lpUserSid,
|
||
|
pvRawData,
|
||
|
cbRawData);
|
||
|
m_rgstrText.Clear();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bResult = ::ReportEvent(m_hLog,
|
||
|
wType,
|
||
|
wCategory,
|
||
|
dwEventID,
|
||
|
lpUserSid,
|
||
|
0,
|
||
|
cbRawData,
|
||
|
NULL,
|
||
|
pvRawData);
|
||
|
}
|
||
|
if (!bResult)
|
||
|
{
|
||
|
//
|
||
|
// Special-case ERROR_IO_PENDING. ::ReportEvent will fail with
|
||
|
// this error code even when it succeeds. Don't know exactly why
|
||
|
// but it does. Treat this as success so we don't get unnecessary
|
||
|
// debugger output.
|
||
|
//
|
||
|
DWORD dwError = GetLastError();
|
||
|
if (ERROR_IO_PENDING != dwError)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(dwError);
|
||
|
DBGERROR((TEXT("Error 0x%08X reporting event"), hr));
|
||
|
}
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Report an event. Replacement strings are explicitly specified
|
||
|
// through an array of CString objects.
|
||
|
//
|
||
|
HRESULT
|
||
|
CEventLog::ReportEvent(
|
||
|
WORD wType,
|
||
|
WORD wCategory,
|
||
|
DWORD dwEventID,
|
||
|
const CArray<CString>& rgstr,
|
||
|
PSID lpUserSid,
|
||
|
LPVOID pvRawData,
|
||
|
DWORD cbRawData
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_EVENTLOG, DL_MID, TEXT("CEventLog::ReportEvent [ with strings ]")));
|
||
|
|
||
|
if (NULL == m_hLog)
|
||
|
{
|
||
|
DBGERROR((TEXT("Event log not initialized")));
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
int cStrings = rgstr.Count();
|
||
|
array_autoptr<LPCTSTR> rgpsz;
|
||
|
if (0 < cStrings)
|
||
|
{
|
||
|
rgpsz = new LPCTSTR[cStrings];
|
||
|
for (int i = 0; i < cStrings; i++)
|
||
|
{
|
||
|
rgpsz[i] = rgstr[i].Cstr();
|
||
|
}
|
||
|
}
|
||
|
if (!::ReportEvent(m_hLog,
|
||
|
wType,
|
||
|
wCategory,
|
||
|
dwEventID,
|
||
|
lpUserSid,
|
||
|
(WORD)cStrings,
|
||
|
cbRawData,
|
||
|
rgpsz.get(),
|
||
|
pvRawData))
|
||
|
{
|
||
|
//
|
||
|
// Special-case ERROR_IO_PENDING. ::ReportEvent will fail with
|
||
|
// this error code even when it succeeds. Don't know exactly why
|
||
|
// but it does. Treat this as success so we don't get unnecessary
|
||
|
// debugger output.
|
||
|
//
|
||
|
DWORD dwError = GetLastError();
|
||
|
if (ERROR_IO_PENDING != dwError)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(dwError);
|
||
|
DBGERROR((TEXT("Error 0x%08X reporting event"), hr));
|
||
|
}
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Push an HRESULT value onto the stack of replacment strings.
|
||
|
//
|
||
|
void
|
||
|
CEventLog::Push(
|
||
|
HRESULT hr,
|
||
|
eFmt fmt
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_EVENTLOG, DL_LOW, TEXT("CEventLog::Push [ integer ]")));
|
||
|
|
||
|
LPTSTR pszBuffer = NULL;
|
||
|
CString s;
|
||
|
try
|
||
|
{
|
||
|
if (eFmtSysErr == fmt)
|
||
|
{
|
||
|
int cchLoaded = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||
|
NULL,
|
||
|
HRESULT_CODE(hr),
|
||
|
0,
|
||
|
(LPTSTR)&pszBuffer,
|
||
|
1,
|
||
|
NULL);
|
||
|
|
||
|
if (NULL != pszBuffer && 0 != cchLoaded)
|
||
|
{
|
||
|
s = pszBuffer;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s.Format(eFmtDec == fmt ? m_szFmtDec : m_szFmtHex, hr);
|
||
|
}
|
||
|
m_rgstrText.Append(s);
|
||
|
}
|
||
|
catch(CAllocException& e)
|
||
|
{
|
||
|
DBGERROR((TEXT("Out of memory error in CEventLog::Push")));
|
||
|
}
|
||
|
LocalFree(pszBuffer);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Push a string onto the stack of replacement strings.
|
||
|
//
|
||
|
void
|
||
|
CEventLog::Push(
|
||
|
LPCTSTR psz
|
||
|
)
|
||
|
{
|
||
|
DBGTRACE((DM_EVENTLOG, DL_LOW, TEXT("CEventLog::Push [ string ]")));
|
||
|
try
|
||
|
{
|
||
|
m_rgstrText.Append(CString(psz));
|
||
|
}
|
||
|
catch(CAllocException& e)
|
||
|
{
|
||
|
DBGERROR((TEXT("Out of memory error in CEventLog::Push")));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|