| 1 | #pragma once
|
|---|
| 2 |
|
|---|
| 3 | #include "simple_registry.hpp"
|
|---|
| 4 | #include <config.h>
|
|---|
| 5 |
|
|---|
| 6 | class EventLogRecord {
|
|---|
| 7 | const EVENTLOGRECORD *pevlr_;
|
|---|
| 8 | __int64 currentTime_;
|
|---|
| 9 | std::wstring file_;
|
|---|
| 10 | public:
|
|---|
| 11 | EventLogRecord(std::wstring file, const EVENTLOGRECORD *pevlr, __int64 currentTime) : file_(file), pevlr_(pevlr), currentTime_(currentTime) {
|
|---|
| 12 | }
|
|---|
| 13 | inline __int64 timeGenerated() const {
|
|---|
| 14 | return (currentTime_-pevlr_->TimeGenerated)*1000;
|
|---|
| 15 | }
|
|---|
| 16 | inline __int64 timeWritten() const {
|
|---|
| 17 | return (currentTime_-pevlr_->TimeWritten)*1000;
|
|---|
| 18 | }
|
|---|
| 19 | inline __int64 generated() const {
|
|---|
| 20 | return pevlr_->TimeGenerated;
|
|---|
| 21 | }
|
|---|
| 22 | inline __int64 written() const {
|
|---|
| 23 | return pevlr_->TimeWritten;
|
|---|
| 24 | }
|
|---|
| 25 | inline std::wstring eventSource() const {
|
|---|
| 26 | return reinterpret_cast<const WCHAR*>(reinterpret_cast<const BYTE*>(pevlr_) + sizeof(EVENTLOGRECORD));
|
|---|
| 27 | }
|
|---|
| 28 | inline DWORD eventID() const {
|
|---|
| 29 | return (pevlr_->EventID&0xffff);
|
|---|
| 30 | }
|
|---|
| 31 | inline DWORD severity() const {
|
|---|
| 32 | return (pevlr_->EventID>>30);
|
|---|
| 33 | }
|
|---|
| 34 |
|
|---|
| 35 | inline DWORD eventType() const {
|
|---|
| 36 | return pevlr_->EventType;
|
|---|
| 37 | }
|
|---|
| 38 |
|
|---|
| 39 | std::wstring userSID() const {
|
|---|
| 40 | if (pevlr_->UserSidOffset == 0)
|
|---|
| 41 | return _T("");
|
|---|
| 42 | PSID p = NULL; // = reinterpret_cast<const void*>(reinterpret_cast<const BYTE*>(pevlr_) + + pevlr_->UserSidOffset);
|
|---|
| 43 | DWORD userLen = 0;
|
|---|
| 44 | DWORD domainLen = 0;
|
|---|
| 45 | SID_NAME_USE sidName;
|
|---|
| 46 |
|
|---|
| 47 | LookupAccountSid(NULL, p, NULL, &userLen, NULL, &domainLen, &sidName);
|
|---|
| 48 | LPTSTR user = new TCHAR[userLen+10];
|
|---|
| 49 | LPTSTR domain = new TCHAR[domainLen+10];
|
|---|
| 50 |
|
|---|
| 51 | LookupAccountSid(NULL, p, user, &userLen, domain, &domainLen, &sidName);
|
|---|
| 52 | user[userLen] = 0;
|
|---|
| 53 | domain[domainLen] = 0;
|
|---|
| 54 | std::wstring ustr = user;
|
|---|
| 55 | std::wstring dstr = domain;
|
|---|
| 56 | delete [] user;
|
|---|
| 57 | delete [] domain;
|
|---|
| 58 | if (!dstr.empty())
|
|---|
| 59 | dstr = dstr + _T("\\");
|
|---|
| 60 | if (ustr.empty() && dstr.empty())
|
|---|
| 61 | return _T("missing");
|
|---|
| 62 |
|
|---|
| 63 | return dstr + ustr;
|
|---|
| 64 | }
|
|---|
| 65 |
|
|---|
| 66 | std::wstring enumStrings() const {
|
|---|
| 67 | std::wstring ret;
|
|---|
| 68 | const TCHAR* p = reinterpret_cast<const TCHAR*>(reinterpret_cast<const BYTE*>(pevlr_) + pevlr_->StringOffset);
|
|---|
| 69 | for (unsigned int i =0;i<pevlr_->NumStrings;i++) {
|
|---|
| 70 | std::wstring s = p;
|
|---|
| 71 | if (!s.empty())
|
|---|
| 72 | s += _T(", ");
|
|---|
| 73 | ret += s;
|
|---|
| 74 | p = &p[wcslen(p) + 1];
|
|---|
| 75 | }
|
|---|
| 76 | return ret;
|
|---|
| 77 | }
|
|---|
| 78 |
|
|---|
| 79 | static DWORD appendType(DWORD dwType, std::wstring sType) {
|
|---|
| 80 | return dwType | translateType(sType);
|
|---|
| 81 | }
|
|---|
| 82 | static DWORD subtractType(DWORD dwType, std::wstring sType) {
|
|---|
| 83 | return dwType & (!translateType(sType));
|
|---|
| 84 | }
|
|---|
| 85 | static DWORD translateType(std::wstring sType) {
|
|---|
| 86 | if (sType.empty())
|
|---|
| 87 | return EVENTLOG_ERROR_TYPE;
|
|---|
| 88 | if (sType == _T("error"))
|
|---|
| 89 | return EVENTLOG_ERROR_TYPE;
|
|---|
| 90 | if (sType == _T("warning"))
|
|---|
| 91 | return EVENTLOG_WARNING_TYPE;
|
|---|
| 92 | if (sType == _T("success"))
|
|---|
| 93 | return EVENTLOG_SUCCESS;
|
|---|
| 94 | if (sType == _T("info"))
|
|---|
| 95 | return EVENTLOG_INFORMATION_TYPE;
|
|---|
| 96 | if (sType == _T("auditSuccess"))
|
|---|
| 97 | return EVENTLOG_AUDIT_SUCCESS;
|
|---|
| 98 | if (sType == _T("auditFailure"))
|
|---|
| 99 | return EVENTLOG_AUDIT_FAILURE;
|
|---|
| 100 | return strEx::stoi(sType);
|
|---|
| 101 | }
|
|---|
| 102 | static std::wstring translateType(DWORD dwType) {
|
|---|
| 103 | if (dwType == EVENTLOG_ERROR_TYPE)
|
|---|
| 104 | return _T("error");
|
|---|
| 105 | if (dwType == EVENTLOG_WARNING_TYPE)
|
|---|
| 106 | return _T("warning");
|
|---|
| 107 | if (dwType == EVENTLOG_SUCCESS)
|
|---|
| 108 | return _T("success");
|
|---|
| 109 | if (dwType == EVENTLOG_INFORMATION_TYPE)
|
|---|
| 110 | return _T("info");
|
|---|
| 111 | if (dwType == EVENTLOG_AUDIT_SUCCESS)
|
|---|
| 112 | return _T("auditSuccess");
|
|---|
| 113 | if (dwType == EVENTLOG_AUDIT_FAILURE)
|
|---|
| 114 | return _T("auditFailure");
|
|---|
| 115 | return strEx::itos(dwType);
|
|---|
| 116 | }
|
|---|
| 117 | static DWORD translateSeverity(std::wstring sType) {
|
|---|
| 118 | if (sType.empty())
|
|---|
| 119 | return 0;
|
|---|
| 120 | if (sType == _T("success"))
|
|---|
| 121 | return 0;
|
|---|
| 122 | if (sType == _T("informational"))
|
|---|
| 123 | return 1;
|
|---|
| 124 | if (sType == _T("warning"))
|
|---|
| 125 | return 2;
|
|---|
| 126 | if (sType == _T("error"))
|
|---|
| 127 | return 3;
|
|---|
| 128 | return strEx::stoi(sType);
|
|---|
| 129 | }
|
|---|
| 130 | static std::wstring translateSeverity(DWORD dwType) {
|
|---|
| 131 | if (dwType == 0)
|
|---|
| 132 | return _T("success");
|
|---|
| 133 | if (dwType == 1)
|
|---|
| 134 | return _T("informational");
|
|---|
| 135 | if (dwType == 2)
|
|---|
| 136 | return _T("warning");
|
|---|
| 137 | if (dwType == 3)
|
|---|
| 138 | return _T("error");
|
|---|
| 139 | return strEx::itos(dwType);
|
|---|
| 140 | }
|
|---|
| 141 | std::wstring get_dll() const {
|
|---|
| 142 | try {
|
|---|
| 143 | return simple_registry::registry_key::get_string(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\") + file_ + (std::wstring)_T("\\") + eventSource(), _T("EventMessageFile"));
|
|---|
| 144 | } catch (simple_registry::registry_exception &e) {
|
|---|
| 145 | NSC_LOG_ERROR_STD(_T("Could not extract DLL for eventsource: ") + eventSource() + _T(": ") + e.what());
|
|---|
| 146 | return _T("");
|
|---|
| 147 | }
|
|---|
| 148 | }
|
|---|
| 149 |
|
|---|
| 150 | struct tchar_array {
|
|---|
| 151 | TCHAR **buffer;
|
|---|
| 152 | unsigned int size;
|
|---|
| 153 | tchar_array(unsigned int size) : buffer(NULL), size(size) {
|
|---|
| 154 | buffer = new TCHAR*[size];
|
|---|
| 155 | for (int i=0;i<size;i++)
|
|---|
| 156 | buffer[i] = NULL;
|
|---|
| 157 | }
|
|---|
| 158 | ~tchar_array() {
|
|---|
| 159 | for (int i=0;i<size;i++)
|
|---|
| 160 | delete [] buffer[i];
|
|---|
| 161 | delete [] buffer;
|
|---|
| 162 | }
|
|---|
| 163 | unsigned int set(int i, const TCHAR* str) {
|
|---|
| 164 | unsigned int len = wcslen(str);
|
|---|
| 165 | buffer[i] = new TCHAR[len+2];
|
|---|
| 166 | wcsncpy(buffer[i], str, len+1);
|
|---|
| 167 | return len;
|
|---|
| 168 | }
|
|---|
| 169 | TCHAR** get_buffer_unsafe() { return buffer; }
|
|---|
| 170 |
|
|---|
| 171 | };
|
|---|
| 172 | std::wstring render_message(DWORD dwLang = 0) const {
|
|---|
| 173 | std::vector<std::wstring> args;
|
|---|
| 174 | const TCHAR* p = reinterpret_cast<const TCHAR*>(reinterpret_cast<const BYTE*>(pevlr_) + pevlr_->StringOffset);
|
|---|
| 175 |
|
|---|
| 176 | tchar_array buffer(pevlr_->NumStrings);
|
|---|
| 177 | for (unsigned int i =0;i<pevlr_->NumStrings;i++) {
|
|---|
| 178 | unsigned int len = buffer.set(i, p);
|
|---|
| 179 | p = &(p[len+1]);
|
|---|
| 180 | }
|
|---|
| 181 | std::wstring ret;
|
|---|
| 182 | strEx::splitList dlls = strEx::splitEx(get_dll(), _T(";"));
|
|---|
| 183 | for (strEx::splitList::const_iterator cit = dlls.begin(); cit != dlls.end(); ++cit) {
|
|---|
| 184 | //std::wstring msg = error::format::message::from_module((*cit), eventID(), _sz);
|
|---|
| 185 | std::wstring msg;
|
|---|
| 186 | try {
|
|---|
| 187 | HMODULE hDLL = LoadLibraryEx((*cit).c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES);
|
|---|
| 188 | if (hDLL == NULL) {
|
|---|
| 189 | msg = _T("failed to load: ") + (*cit) + _T(", reason: ") + strEx::itos(GetLastError());
|
|---|
| 190 | continue;
|
|---|
| 191 | }
|
|---|
| 192 | LPVOID lpMsgBuf;
|
|---|
| 193 | if (dwLang == 0)
|
|---|
| 194 | dwLang = MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT);
|
|---|
| 195 | unsigned long dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_ARGUMENT_ARRAY,hDLL,
|
|---|
| 196 | eventID(),dwLang,(LPTSTR)&lpMsgBuf,0,reinterpret_cast<va_list*>(buffer.get_buffer_unsafe()));
|
|---|
| 197 | if (dwRet == 0) {
|
|---|
| 198 | DWORD err = GetLastError();
|
|---|
| 199 | FreeLibrary(hDLL);
|
|---|
| 200 | if (err == 317) {
|
|---|
| 201 | msg = _T("");
|
|---|
| 202 | continue;
|
|---|
| 203 | }
|
|---|
| 204 | msg = _T("failed to lookup error code: ") + strEx::itos(eventID()) + _T(" from DLL: ") + (*cit) + _T("( reson: ") + strEx::itos(err) + _T(")");
|
|---|
| 205 | continue;
|
|---|
| 206 | }
|
|---|
| 207 | msg = reinterpret_cast<wchar_t*>(lpMsgBuf);
|
|---|
| 208 | LocalFree(lpMsgBuf);
|
|---|
| 209 | FreeLibrary(hDLL);
|
|---|
| 210 | } catch (...) {
|
|---|
| 211 | msg = _T("Unknown exception getting message");
|
|---|
| 212 | }
|
|---|
| 213 | strEx::replace(msg, _T("\n"), _T(" "));
|
|---|
| 214 | strEx::replace(msg, _T("\t"), _T(" "));
|
|---|
| 215 | std::string::size_type pos = msg.find_last_not_of(_T("\n\t "));
|
|---|
| 216 | if (pos != std::string::npos) {
|
|---|
| 217 | msg = msg.substr(0,pos);
|
|---|
| 218 | }
|
|---|
| 219 | if (!msg.empty()) {
|
|---|
| 220 | if (!ret.empty())
|
|---|
| 221 | ret += _T(", ");
|
|---|
| 222 | ret += msg;
|
|---|
| 223 | }
|
|---|
| 224 | }
|
|---|
| 225 | return ret;
|
|---|
| 226 | }
|
|---|
| 227 | SYSTEMTIME get_time(DWORD time) const {
|
|---|
| 228 | FILETIME FileTime, LocalFileTime;
|
|---|
| 229 | SYSTEMTIME SysTime;
|
|---|
| 230 | __int64 lgTemp;
|
|---|
| 231 | __int64 SecsTo1970 = 116444736000000000;
|
|---|
| 232 |
|
|---|
| 233 | lgTemp = Int32x32To64(time,10000000) + SecsTo1970;
|
|---|
| 234 |
|
|---|
| 235 | FileTime.dwLowDateTime = (DWORD) lgTemp;
|
|---|
| 236 | FileTime.dwHighDateTime = (DWORD)(lgTemp >> 32);
|
|---|
| 237 |
|
|---|
| 238 | FileTimeToLocalFileTime(&FileTime, &LocalFileTime);
|
|---|
| 239 | FileTimeToSystemTime(&LocalFileTime, &SysTime);
|
|---|
| 240 | return SysTime;
|
|---|
| 241 | }
|
|---|
| 242 |
|
|---|
| 243 | SYSTEMTIME get_time_generated() const {
|
|---|
| 244 | return get_time(pevlr_->TimeGenerated);
|
|---|
| 245 | }
|
|---|
| 246 | SYSTEMTIME get_time_written() const {
|
|---|
| 247 | return get_time(pevlr_->TimeWritten);
|
|---|
| 248 | }
|
|---|
| 249 |
|
|---|
| 250 | std::wstring render(bool propper, std::wstring syntax, std::wstring date_format = DATE_FORMAT, DWORD langId = 0) const {
|
|---|
| 251 | if (propper) {
|
|---|
| 252 | // To obtain the appropriate message string from the message file, load the message file with the LoadLibrary function and use the FormatMessage function
|
|---|
| 253 | strEx::replace(syntax, _T("%message%"), render_message(langId));
|
|---|
| 254 | } else {
|
|---|
| 255 | strEx::replace(syntax, _T("%message%"), _T("%message% needs the descriptions flag set!"));
|
|---|
| 256 | }
|
|---|
| 257 |
|
|---|
| 258 | strEx::replace(syntax, _T("%source%"), eventSource());
|
|---|
| 259 | strEx::replace(syntax, _T("%generated%"), strEx::format_date(get_time_generated(), date_format));
|
|---|
| 260 | strEx::replace(syntax, _T("%written%"), strEx::format_date(get_time_written(), date_format));
|
|---|
| 261 | strEx::replace(syntax, _T("%generated-raw%"), strEx::itos(pevlr_->TimeGenerated));
|
|---|
| 262 | strEx::replace(syntax, _T("%written-raw%"), strEx::itos(pevlr_->TimeWritten));
|
|---|
| 263 | strEx::replace(syntax, _T("%type%"), translateType(eventType()));
|
|---|
| 264 | strEx::replace(syntax, _T("%severity%"), translateSeverity(severity()));
|
|---|
| 265 | strEx::replace(syntax, _T("%strings%"), enumStrings());
|
|---|
| 266 | strEx::replace(syntax, _T("%id%"), strEx::itos(eventID()));
|
|---|
| 267 | strEx::replace(syntax, _T("%user%"), userSID());
|
|---|
| 268 | return syntax;
|
|---|
| 269 | }
|
|---|
| 270 | }; |
|---|