1 #pragma once 2 #include <plog/Appenders/IAppender.h> 3 #include <plog/WinApi.h> 4 5 namespace plog 6 { 7 template <class Formatter> 8 class EventLogAppender : public IAppender 9 { 10 public: EventLogAppender(const wchar_t * sourceName)11 EventLogAppender(const wchar_t* sourceName) : m_eventSource(RegisterEventSourceW(NULL, sourceName)) 12 { 13 } 14 ~EventLogAppender()15 ~EventLogAppender() 16 { 17 DeregisterEventSource(m_eventSource); 18 } 19 write(const Record & record)20 virtual void write(const Record& record) 21 { 22 std::wstring str = Formatter::format(record); 23 const wchar_t* logMessagePtr[] = { str.c_str() }; 24 25 ReportEventW(m_eventSource, logSeverityToType(record.getSeverity()), static_cast<WORD>(record.getSeverity()), 0, NULL, 1, 0, logMessagePtr, NULL); 26 } 27 28 private: logSeverityToType(plog::Severity severity)29 static WORD logSeverityToType(plog::Severity severity) 30 { 31 switch (severity) 32 { 33 case plog::fatal: 34 case plog::error: 35 return eventLog::kErrorType; 36 37 case plog::warning: 38 return eventLog::kWarningType; 39 40 case plog::info: 41 case plog::debug: 42 case plog::verbose: 43 default: 44 return eventLog::kInformationType; 45 } 46 } 47 48 private: 49 HANDLE m_eventSource; 50 }; 51 52 class EventLogAppenderRegistry 53 { 54 public: 55 static bool add(const wchar_t* sourceName, const wchar_t* logName = L"Application") 56 { 57 std::wstring logKeyName; 58 std::wstring sourceKeyName; 59 getKeyNames(sourceName, logName, sourceKeyName, logKeyName); 60 61 HKEY sourceKey; 62 if (0 != RegCreateKeyExW(hkey::kLocalMachine, sourceKeyName.c_str(), 0, NULL, 0, regSam::kSetValue, NULL, &sourceKey, NULL)) 63 { 64 return false; 65 } 66 67 const DWORD kTypesSupported = eventLog::kErrorType | eventLog::kWarningType | eventLog::kInformationType; 68 RegSetValueExW(sourceKey, L"TypesSupported", 0, regType::kDword, reinterpret_cast<const BYTE*>(&kTypesSupported), sizeof(kTypesSupported)); 69 70 const wchar_t kEventMessageFile[] = L"%windir%\\Microsoft.NET\\Framework\\v4.0.30319\\EventLogMessages.dll;%windir%\\Microsoft.NET\\Framework\\v2.0.50727\\EventLogMessages.dll"; 71 RegSetValueExW(sourceKey, L"EventMessageFile", 0, regType::kExpandSz, reinterpret_cast<const BYTE*>(kEventMessageFile), sizeof(kEventMessageFile) - sizeof(*kEventMessageFile)); 72 73 RegCloseKey(sourceKey); 74 return true; 75 } 76 77 static bool exists(const wchar_t* sourceName, const wchar_t* logName = L"Application") 78 { 79 std::wstring logKeyName; 80 std::wstring sourceKeyName; 81 getKeyNames(sourceName, logName, sourceKeyName, logKeyName); 82 83 HKEY sourceKey; 84 if (0 != RegOpenKeyExW(hkey::kLocalMachine, sourceKeyName.c_str(), 0, regSam::kQueryValue, &sourceKey)) 85 { 86 return false; 87 } 88 89 RegCloseKey(sourceKey); 90 return true; 91 } 92 93 static void remove(const wchar_t* sourceName, const wchar_t* logName = L"Application") 94 { 95 std::wstring logKeyName; 96 std::wstring sourceKeyName; 97 getKeyNames(sourceName, logName, sourceKeyName, logKeyName); 98 99 RegDeleteKeyW(hkey::kLocalMachine, sourceKeyName.c_str()); 100 RegDeleteKeyW(hkey::kLocalMachine, logKeyName.c_str()); 101 } 102 103 private: getKeyNames(const wchar_t * sourceName,const wchar_t * logName,std::wstring & sourceKeyName,std::wstring & logKeyName)104 static void getKeyNames(const wchar_t* sourceName, const wchar_t* logName, std::wstring& sourceKeyName, std::wstring& logKeyName) 105 { 106 const std::wstring kPrefix = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\"; 107 logKeyName = kPrefix + logName; 108 sourceKeyName = logKeyName + L"\\" + sourceName; 109 } 110 }; 111 } 112