gremlin/libs/log4cplus/src/nteventlogappender.cxx

349 lines
8.5 KiB
C++

// Module: LOG4CPLUS
// File: nteventlogappender.cxx
// Created: 4/2003
// Author: Michael CATANZARITI
//
// Copyright 2003-2010 Michael CATANZARITI
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <log4cplus/nteventlogappender.h>
#include <log4cplus/loglevel.h>
#include <log4cplus/streams.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/spi/loggingevent.h>
#if defined (LOG4CPLUS_HAVE_NT_EVENT_LOG)
using namespace log4cplus;
using namespace log4cplus::spi;
using namespace log4cplus::helpers;
//////////////////////////////////////////////////////////////////////////////
// File LOCAL methods
//////////////////////////////////////////////////////////////////////////////
namespace {
bool
FreeSid(SID* pSid)
{
return ::HeapFree(GetProcessHeap(), 0, (LPVOID)pSid) != 0;
}
bool
CopySid(SID** ppDstSid, SID* pSrcSid)
{
bool bSuccess = false;
DWORD dwLength = ::GetLengthSid(pSrcSid);
*ppDstSid = (SID *) ::HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, dwLength);
if(::CopySid(dwLength, *ppDstSid, pSrcSid)) {
bSuccess = true;
}
else {
FreeSid(*ppDstSid);
}
return bSuccess;
}
bool
GetCurrentUserSID(SID** ppSid)
{
bool bSuccess = false;
// Pseudohandle so don't need to close it
HANDLE hProcess = ::GetCurrentProcess();
HANDLE hToken = NULL;
if(::OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
// Get the required size
DWORD tusize = 0;
GetTokenInformation(hToken, TokenUser, NULL, 0, &tusize);
TOKEN_USER* ptu = (TOKEN_USER*)new BYTE[tusize];
if(GetTokenInformation(hToken, TokenUser, (LPVOID)ptu, tusize, &tusize)) {
bSuccess = CopySid(ppSid, (SID *)ptu->User.Sid);
}
CloseHandle(hToken);
delete [] ptu;
}
return bSuccess;
}
HKEY
regGetKey(const log4cplus::tstring& subkey, DWORD* disposition)
{
HKEY hkey = 0;
RegCreateKeyEx(HKEY_LOCAL_MACHINE,
subkey.c_str(),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE,
NULL,
&hkey,
disposition);
return hkey;
}
void
regSetString(HKEY hkey, const log4cplus::tstring& name, const log4cplus::tstring& value)
{
RegSetValueEx(hkey,
name.c_str(),
0,
REG_SZ,
(LPBYTE)value.c_str(),
static_cast<DWORD>(value.length() * sizeof(tchar)));
}
void
regSetDword(HKEY hkey, const log4cplus::tstring& name, DWORD value)
{
RegSetValueEx(hkey,
name.c_str(),
0,
REG_DWORD,
(LPBYTE)&value,
sizeof(DWORD));
}
}
//////////////////////////////////////////////////////////////////////////////
// log4cplus::NTEventLogAppender ctor and dtor
//////////////////////////////////////////////////////////////////////////////
NTEventLogAppender::NTEventLogAppender(const log4cplus::tstring& server,
const log4cplus::tstring& log,
const log4cplus::tstring& source)
: server(server),
log(log),
source(source),
hEventLog(NULL),
pCurrentUserSID(NULL)
{
init();
}
NTEventLogAppender::NTEventLogAppender(const Properties properties)
: Appender(properties),
hEventLog(NULL),
pCurrentUserSID(NULL)
{
server = properties.getProperty( LOG4CPLUS_TEXT("server") );
log = properties.getProperty( LOG4CPLUS_TEXT("log") );
source = properties.getProperty( LOG4CPLUS_TEXT("source") );
init();
}
void
NTEventLogAppender::init()
{
if(source.empty()) {
getLogLog().warn( LOG4CPLUS_TEXT("Source option not set for appender [")
+ name
+ LOG4CPLUS_TEXT("]."));
return;
}
if(log.empty ()) {
log = LOG4CPLUS_TEXT("Application");
}
// current user security identifier
GetCurrentUserSID(&pCurrentUserSID);
addRegistryInfo();
hEventLog = ::RegisterEventSource(server.empty () ? 0 : server.c_str(),
source.c_str());
if (! hEventLog || hEventLog == HANDLE(ERROR_INVALID_HANDLE))
getLogLog().warn (LOG4CPLUS_TEXT("Event source registration failed."));
}
NTEventLogAppender::~NTEventLogAppender()
{
destructorImpl();
if(pCurrentUserSID != NULL) {
FreeSid(pCurrentUserSID);
pCurrentUserSID = NULL;
}
}
//////////////////////////////////////////////////////////////////////////////
// log4cplus::NTEventLogAppender public methods
//////////////////////////////////////////////////////////////////////////////
void
NTEventLogAppender::close()
{
if(hEventLog != NULL) {
::DeregisterEventSource(hEventLog);
hEventLog = NULL;
}
closed = true;
}
//////////////////////////////////////////////////////////////////////////////
// log4cplus::NTEventLogAppender protected methods
//////////////////////////////////////////////////////////////////////////////
void
NTEventLogAppender::append(const InternalLoggingEvent& event)
{
if(hEventLog == NULL) {
getLogLog().warn(LOG4CPLUS_TEXT("NT EventLog not opened."));
return;
}
tostringstream buf;
layout->formatAndAppend(buf, event);
tstring sz = buf.str();
const tchar * s = sz.c_str();
BOOL bSuccess = ::ReportEvent(hEventLog,
getEventType(event),
getEventCategory(event),
0x1000,
pCurrentUserSID,
1,
0,
&s,
NULL);
if(!bSuccess) {
getLogLog().error(LOG4CPLUS_TEXT("Cannot report event in NT EventLog."));
}
}
WORD
NTEventLogAppender::getEventType(const InternalLoggingEvent& event)
{
WORD ret_val;
switch ((int)event.getLogLevel())
{
case FATAL_LOG_LEVEL:
case ERROR_LOG_LEVEL:
ret_val = EVENTLOG_ERROR_TYPE;
break;
case WARN_LOG_LEVEL:
ret_val = EVENTLOG_WARNING_TYPE;
break;
case INFO_LOG_LEVEL:
case DEBUG_LOG_LEVEL:
default:
ret_val = EVENTLOG_INFORMATION_TYPE;
break;
}
return ret_val;
}
WORD
NTEventLogAppender::getEventCategory(const InternalLoggingEvent& event)
{
WORD ret_val;
switch (event.getLogLevel())
{
case FATAL_LOG_LEVEL:
ret_val = 1;
break;
case ERROR_LOG_LEVEL:
ret_val = 2;
break;
case WARN_LOG_LEVEL:
ret_val = 3;
break;
case INFO_LOG_LEVEL:
ret_val = 4;
break;
case DEBUG_LOG_LEVEL:
default:
ret_val = 5;
break;
}
return ret_val;
}
// Add this source with appropriate configuration keys to the registry.
void
NTEventLogAppender::addRegistryInfo()
{
DWORD disposition;
HKEY hkey = 0;
tstring subkey = LOG4CPLUS_TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\")
+ log
+ LOG4CPLUS_TEXT("\\")
+ source;
hkey = regGetKey(subkey, &disposition);
if(disposition == REG_CREATED_NEW_KEY) {
regSetString(hkey,
LOG4CPLUS_TEXT("EventMessageFile"),
LOG4CPLUS_TEXT("NTEventLogAppender.dll"));
regSetString(hkey,
LOG4CPLUS_TEXT("CategoryMessageFile"),
LOG4CPLUS_TEXT("NTEventLogAppender.dll"));
regSetDword(hkey, LOG4CPLUS_TEXT("TypesSupported"), (DWORD)7);
regSetDword(hkey, LOG4CPLUS_TEXT("CategoryCount"), (DWORD)5);
}
RegCloseKey(hkey);
return;
}
#endif