GrabBag/VrUtils/log4cpp/src/NTEventLogAppender.cpp
2025-07-23 01:35:14 +08:00

166 lines
5.1 KiB
C++

/*
* NTEventLogAppender.cpp
*
* Copyright 2002, Log4cpp Project. All rights reserved.
*
* See the COPYING file for the terms of usage and distribution.
*/
#ifdef WIN32 // only available on Win32
#include <log4cpp/NTEventLogAppender.hh>
#include <log4cpp/FactoryParams.hh>
#include <memory>
namespace log4cpp {
NTEventLogAppender::NTEventLogAppender(const std::string& name, const std::string& sourceName) :
AppenderSkeleton(name),
_strSourceName(sourceName),
_hEventSource(NULL)
{
open();
}
NTEventLogAppender::~NTEventLogAppender()
{
close();
}
void NTEventLogAppender::open()
{
addRegistryInfo(_strSourceName.c_str());
#ifdef __WIN_ROS__
_hEventSource = ::RegisterEventSource(NULL, (LPCSTR)_strSourceName.c_str());
#else
_hEventSource = ::RegisterEventSource(NULL, (LPCWSTR)_strSourceName.c_str());
#endif
}
void NTEventLogAppender::close()
{
if (_hEventSource) {
::DeregisterEventSource(_hEventSource);
}
}
bool NTEventLogAppender::reopen() {
close();
open();
return true;
}
bool NTEventLogAppender::requiresLayout() const {
return false;
}
void NTEventLogAppender::setLayout(Layout* layout) {
return;
}
void NTEventLogAppender::_append(const LoggingEvent& event) {
const char* ps[1];
ps[0] = event.message.c_str();
const DWORD messageID = 0x1000;
#ifdef __WIN_ROS__
::ReportEvent(_hEventSource, getType(event.priority), getCategory(event.priority), messageID, NULL, 1, 0, (LPCSTR *)ps, NULL);
#else
::ReportEvent(_hEventSource, getType(event.priority), getCategory(event.priority), messageID, NULL, 1, 0, (LPCWSTR *)ps, NULL);
#endif
}
/**
* Convert log4cpp Priority to an EventLog category. Each category is
* backed by a message resource so that proper category names will
* be displayed in the NT Event Viewer.
*/
WORD NTEventLogAppender::getCategory(Priority::Value priority) {
// Priority values map directly to EventLog category values
return (WORD)((priority / 100) + 1);
}
/**
* Convert log4cpp Priority to an EventLog type. The log4cpp package
* supports 8 defined priorites, but the NT EventLog only knows
* 3 event types of interest to us: ERROR, WARNING, and INFO.
*/
WORD NTEventLogAppender::getType(Priority::Value priority) {
WORD ret_val;
switch (priority) {
case Priority::EMERG:
// FATAL is the same value as EMERG
// case Priority::FATAL:
case Priority::ALERT:
case Priority::CRIT:
case Priority::ERROR:
ret_val = EVENTLOG_ERROR_TYPE;
break;
case Priority::WARN:
ret_val = EVENTLOG_WARNING_TYPE;
break;
case Priority::NOTICE:
case Priority::INFO:
case Priority::DEBUG:
default:
ret_val = EVENTLOG_INFORMATION_TYPE;
break;
}
return ret_val;
}
HKEY NTEventLogAppender::regGetKey(TCHAR *subkey, DWORD *disposition) {
HKEY hkey = 0;
RegCreateKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL,
&hkey, disposition);
return hkey;
}
void NTEventLogAppender::regSetString(HKEY hkey, TCHAR *name, TCHAR *value) {
RegSetValueEx(hkey, name, 0, REG_SZ, (LPBYTE)value, lstrlen(value));
}
void NTEventLogAppender::regSetDword(HKEY hkey, TCHAR *name, DWORD value) {
RegSetValueEx(hkey, name, 0, REG_DWORD, (LPBYTE)&value, sizeof(DWORD));
}
/*
* Add this source with appropriate configuration keys to the registry.
*/
void NTEventLogAppender::addRegistryInfo(const char *source) {
const TCHAR *prefix = (TCHAR *)("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");
DWORD disposition;
HKEY hkey = 0;
TCHAR subkey[256];
lstrcpy(subkey, prefix);
#ifdef __WIN_ROS__
lstrcat(subkey, (LPCSTR)source);
#else
lstrcat(subkey, (LPCWSTR)source);
#endif
hkey = regGetKey(subkey, &disposition);
if (disposition == REG_CREATED_NEW_KEY) {
regSetString(hkey, (TCHAR*)("EventMessageFile"), (TCHAR*)("NTEventLogAppender.dll"));
regSetString(hkey, (TCHAR*)("CategoryMessageFile"), (TCHAR*)("NTEventLogAppender.dll"));
regSetDword(hkey, (TCHAR*)("TypesSupported"), (DWORD)7);
regSetDword(hkey, (TCHAR*)("CategoryCount"), (DWORD)8);
}
RegCloseKey(hkey);
return;
}
std::auto_ptr<Appender> create_nt_event_log_appender(const FactoryParams& params)
{
std::string name, source_name;
params.get_for("nt event log appender").required("name", name)("source_name", source_name);
return std::auto_ptr<Appender>(new NTEventLogAppender(name, source_name));
}
}
#endif // WIN32