| 1 | /************************************************************************** |
|---|
| 2 | * Copyright (C) 2004-2007 by Michael Medin <michael@medin.name> * |
|---|
| 3 | * * |
|---|
| 4 | * This code is part of NSClient++ - http://trac.nakednuns.org/nscp * |
|---|
| 5 | * * |
|---|
| 6 | * This program is free software; you can redistribute it and/or modify * |
|---|
| 7 | * it under the terms of the GNU General Public License as published by * |
|---|
| 8 | * the Free Software Foundation; either version 2 of the License, or * |
|---|
| 9 | * (at your option) any later version. * |
|---|
| 10 | * * |
|---|
| 11 | * This program is distributed in the hope that it will be useful, * |
|---|
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|---|
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
|---|
| 14 | * GNU General Public License for more details. * |
|---|
| 15 | * * |
|---|
| 16 | * You should have received a copy of the GNU General Public License * |
|---|
| 17 | * along with this program; if not, write to the * |
|---|
| 18 | * Free Software Foundation, Inc., * |
|---|
| 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
|---|
| 20 | ***************************************************************************/ |
|---|
| 21 | |
|---|
| 22 | #include "stdafx.h" |
|---|
| 23 | #include "CheckEventLog.h" |
|---|
| 24 | #include <filter_framework.hpp> |
|---|
| 25 | #include <boost/foreach.hpp> |
|---|
| 26 | |
|---|
| 27 | #include <strEx.h> |
|---|
| 28 | #include <time.h> |
|---|
| 29 | #include <utils.h> |
|---|
| 30 | #include <error.hpp> |
|---|
| 31 | #include <map> |
|---|
| 32 | #include <vector> |
|---|
| 33 | #include <config.h> |
|---|
| 34 | |
|---|
| 35 | #include <boost/bind.hpp> |
|---|
| 36 | #include <boost/assign.hpp> |
|---|
| 37 | |
|---|
| 38 | #include <parsers/where.hpp> |
|---|
| 39 | #include <simple_timer.hpp> |
|---|
| 40 | |
|---|
| 41 | #include "simple_registry.hpp" |
|---|
| 42 | #include "eventlog_record.hpp" |
|---|
| 43 | #include "eventlog_filter.hpp" |
|---|
| 44 | |
|---|
| 45 | CheckEventLog gCheckEventLog; |
|---|
| 46 | |
|---|
| 47 | CheckEventLog::CheckEventLog() { |
|---|
| 48 | } |
|---|
| 49 | CheckEventLog::~CheckEventLog() { |
|---|
| 50 | } |
|---|
| 51 | struct parse_exception { |
|---|
| 52 | parse_exception(std::wstring) {} |
|---|
| 53 | }; |
|---|
| 54 | |
|---|
| 55 | #include <parsers/where.cpp> |
|---|
| 56 | #include <parsers/grammar.cpp> |
|---|
| 57 | #include <parsers/ast.cpp> |
|---|
| 58 | |
|---|
| 59 | namespace sh = nscapi::settings_helper; |
|---|
| 60 | |
|---|
| 61 | |
|---|
| 62 | bool CheckEventLog::loadModule() { |
|---|
| 63 | return false; |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | |
|---|
| 67 | bool CheckEventLog::loadModuleEx(std::wstring alias, NSCAPI::moduleLoadMode mode) { |
|---|
| 68 | try { |
|---|
| 69 | get_core()->registerCommand(_T("CheckEventLog"), _T("Check for errors in the event logger!")); |
|---|
| 70 | |
|---|
| 71 | sh::settings_registry settings(nscapi::plugin_singleton->get_core()); |
|---|
| 72 | settings.set_alias(_T("CheckEventlog"), alias); |
|---|
| 73 | |
|---|
| 74 | settings.alias().add_path_to_settings() |
|---|
| 75 | (_T("EVENT LOG SECTION"), _T("Section for the EventLog Checker (CHeckEventLog.dll).")) |
|---|
| 76 | ; |
|---|
| 77 | |
|---|
| 78 | settings.alias().add_key_to_settings() |
|---|
| 79 | (_T("debug"), sh::bool_key(&debug_, false), |
|---|
| 80 | _T("DEBUG"), _T("Log all \"hits\" and \"misses\" on the eventlog filter chain, useful for debugging eventlog checks but very very very noisy so you don't want to accidentally set this on a real machine.")) |
|---|
| 81 | |
|---|
| 82 | (_T("lookup names"), sh::bool_key(&lookup_names_, false), |
|---|
| 83 | _T("LOOKUP NAMES"), _T("")) |
|---|
| 84 | |
|---|
| 85 | (_T("syntax"), sh::wstring_key(&syntax_), |
|---|
| 86 | _T("SYNTAX"), _T("Set this to use a specific syntax string for all commands (that don't specify one).")) |
|---|
| 87 | |
|---|
| 88 | (_T("buffer size"), sh::int_key(&buffer_length_, 128*1024), |
|---|
| 89 | _T("BUFFER_SIZE"), _T("The size of the buffer to use when getting messages this affects the speed and maximum size of messages you can recieve.")) |
|---|
| 90 | ; |
|---|
| 91 | |
|---|
| 92 | settings.register_all(); |
|---|
| 93 | settings.notify(); |
|---|
| 94 | |
|---|
| 95 | } catch (std::exception &e) { |
|---|
| 96 | NSC_LOG_ERROR_STD(_T("Exception caught: ") + to_wstring(e.what())); |
|---|
| 97 | return false; |
|---|
| 98 | } catch (nscapi::nscapi_exception &e) { |
|---|
| 99 | NSC_LOG_ERROR_STD(_T("Failed to register command: ") + e.msg_); |
|---|
| 100 | return false; |
|---|
| 101 | } catch (...) { |
|---|
| 102 | NSC_LOG_ERROR_STD(_T("Failed to register command.")); |
|---|
| 103 | return false; |
|---|
| 104 | } |
|---|
| 105 | /* |
|---|
| 106 | parse(_T("321 = 123")); |
|---|
| 107 | parse(_T("123 = 123")); |
|---|
| 108 | parse(_T("id = 123")); |
|---|
| 109 | parse(_T("id = 321")); |
|---|
| 110 | |
|---|
| 111 | parse(_T("id = '123'")); |
|---|
| 112 | parse(_T("id = '321'")); |
|---|
| 113 | |
|---|
| 114 | parse(_T("id = convert(123)")); |
|---|
| 115 | parse(_T("id = convert(321)")); |
|---|
| 116 | |
|---|
| 117 | parse(_T("id = 123 AND 123 = 123 AND id = 123x")); |
|---|
| 118 | parse(_T("id = 123 AND 123 = 321 OR 123 = 456 OR 123 = 123")); |
|---|
| 119 | |
|---|
| 120 | parse(_T("foo")); |
|---|
| 121 | parse(_T("1")); |
|---|
| 122 | parse(_T("foo = ")); |
|---|
| 123 | parse(_T("foo = 1")); |
|---|
| 124 | parse(_T("'foo' = 1")); |
|---|
| 125 | parse(_T("foo = '1'")); |
|---|
| 126 | parse(_T("'hello'='world'")); |
|---|
| 127 | |
|---|
| 128 | parse(_T("foo = bar")); |
|---|
| 129 | parse(_T("foo = bar AND bar = foo")); |
|---|
| 130 | parse(_T("foo = bar AND bar = 1")); |
|---|
| 131 | parse(_T("foo = bar AND bar = foo OR foo = bar")); |
|---|
| 132 | parse(_T("foo = bar AND bar = 1 OR foo = 1")); |
|---|
| 133 | parse(_T(" foo = bar AND ( test > 120 OR foo < 123) OR ugh IN (123, 456, 789)")); |
|---|
| 134 | |
|---|
| 135 | parse(_T("aaa = 111 OR bbb = 222 OR ccc = 333")); |
|---|
| 136 | parse(_T("(aaa = 111) OR bbb = 222 OR ccc = 333")); |
|---|
| 137 | parse(_T("(aaa = 111 OR bbb = 222) OR ccc = 333")); |
|---|
| 138 | parse(_T("(aaa = 111 OR bbb = 222 OR ccc = 333)")); |
|---|
| 139 | parse(_T("aaa = 111 OR (bbb = 222 OR ccc = 333)")); |
|---|
| 140 | parse(_T("aaa = 111 OR bbb = 222 OR (ccc = 333)")); |
|---|
| 141 | parse(_T("ccc = -333")); |
|---|
| 142 | parse(_T("ccc = -333 AND ccc = to_date('AABBCC', 1234)")); |
|---|
| 143 | parse(_T("aaa = 111 OR bbb = 222 OR (ccc = -333)")); |
|---|
| 144 | parse(_T("ccc = -333 AND ccc = to_date('AABBCC', 1234) OR aaa = 123x")); |
|---|
| 145 | parse(_T("ccc = -333 AND ccc = to_date('AABBCC', 1234) OR aaa = 123x OR 123r = foo123")); |
|---|
| 146 | */ |
|---|
| 147 | return true; |
|---|
| 148 | } |
|---|
| 149 | bool CheckEventLog::unloadModule() { |
|---|
| 150 | return true; |
|---|
| 151 | } |
|---|
| 152 | |
|---|
| 153 | bool CheckEventLog::hasCommandHandler() { |
|---|
| 154 | return true; |
|---|
| 155 | } |
|---|
| 156 | bool CheckEventLog::hasMessageHandler() { |
|---|
| 157 | return false; |
|---|
| 158 | } |
|---|
| 159 | namespace filter { |
|---|
| 160 | namespace where { |
|---|
| 161 | struct type_obj : public parsers::where::varible_handler<type_obj> { |
|---|
| 162 | typedef parsers::where::varible_handler<type_obj> handler; |
|---|
| 163 | typedef std::list<std::wstring> error_type; |
|---|
| 164 | typedef std::map<std::wstring,parsers::where::value_type> types_type; |
|---|
| 165 | types_type types; |
|---|
| 166 | error_type errors; |
|---|
| 167 | static const parsers::where::value_type type_custom_severity = parsers::where::type_custom_int_1; |
|---|
| 168 | static const parsers::where::value_type type_custom_type = parsers::where::type_custom_int_2; |
|---|
| 169 | EventLogRecord *record; |
|---|
| 170 | type_obj() : record(NULL) { |
|---|
| 171 | using namespace boost::assign; |
|---|
| 172 | using namespace parsers::where; |
|---|
| 173 | insert(types) |
|---|
| 174 | (_T("id"), (type_int)) |
|---|
| 175 | (_T("source"), (type_string)) |
|---|
| 176 | (_T("type"), (type_custom_type)) |
|---|
| 177 | (_T("severity"), (type_custom_severity)) |
|---|
| 178 | (_T("message"), (type_string)) |
|---|
| 179 | (_T("strings"), (type_string)) |
|---|
| 180 | (_T("written"), (type_date)) |
|---|
| 181 | (_T("generated"), (type_date)); |
|---|
| 182 | } |
|---|
| 183 | type_obj(EventLogRecord *record) : record(record) {} |
|---|
| 184 | bool has_variable(std::wstring key) { |
|---|
| 185 | return types.find(key) != types.end(); |
|---|
| 186 | } |
|---|
| 187 | parsers::where::value_type get_type(std::wstring key) { |
|---|
| 188 | types_type::const_iterator cit = types.find(key); |
|---|
| 189 | if (cit == types.end()) |
|---|
| 190 | return parsers::where::type_invalid; |
|---|
| 191 | return cit->second; |
|---|
| 192 | } |
|---|
| 193 | bool can_convert(parsers::where::value_type from, parsers::where::value_type to) { |
|---|
| 194 | if ((from == parsers::where::type_string)&&(to == type_custom_severity)) |
|---|
| 195 | return true; |
|---|
| 196 | if ((from == parsers::where::type_string)&&(to == type_custom_type)) |
|---|
| 197 | return true; |
|---|
| 198 | return false; |
|---|
| 199 | } |
|---|
| 200 | void error(std::wstring err) { |
|---|
| 201 | errors.push_back(err); |
|---|
| 202 | } |
|---|
| 203 | bool has_error() { |
|---|
| 204 | return !errors.empty(); |
|---|
| 205 | } |
|---|
| 206 | long long get_id() { |
|---|
| 207 | if (record == NULL) throw _T("Whoops"); return record->eventID(); |
|---|
| 208 | } |
|---|
| 209 | std::wstring get_source() { |
|---|
| 210 | if (record == NULL) throw _T("Whoops"); return record->eventSource(); |
|---|
| 211 | } |
|---|
| 212 | long long get_el_type() { |
|---|
| 213 | if (record == NULL) throw _T("Whoops"); return record->eventType(); |
|---|
| 214 | } |
|---|
| 215 | long long get_severity() { |
|---|
| 216 | if (record == NULL) throw _T("Whoops"); |
|---|
| 217 | //NSC_DEBUG_MSG_STD(_T("Severity: ") + strEx::itos(record->severity())); |
|---|
| 218 | return record->severity(); |
|---|
| 219 | } |
|---|
| 220 | std::wstring get_message() { |
|---|
| 221 | if (record == NULL) throw _T("Whoops"); return record->render_message(); |
|---|
| 222 | } |
|---|
| 223 | std::wstring get_strings() { |
|---|
| 224 | if (record == NULL) throw _T("Whoops"); return record->enumStrings(); |
|---|
| 225 | } |
|---|
| 226 | long long get_written() { |
|---|
| 227 | if (record == NULL) throw _T("Whoops"); return record->written(); |
|---|
| 228 | } |
|---|
| 229 | long long get_generated() { |
|---|
| 230 | if (record == NULL) throw _T("Whoops"); return record->generated(); |
|---|
| 231 | } |
|---|
| 232 | |
|---|
| 233 | handler::bound_string_type bind_string(std::wstring key) { |
|---|
| 234 | handler::bound_string_type ret; |
|---|
| 235 | if (key == _T("source")) |
|---|
| 236 | ret = &type_obj::get_source; |
|---|
| 237 | else if (key == _T("message")) |
|---|
| 238 | ret = &type_obj::get_message; |
|---|
| 239 | else if (key == _T("strings")) |
|---|
| 240 | ret = &type_obj::get_strings; |
|---|
| 241 | else |
|---|
| 242 | NSC_DEBUG_MSG_STD(_T("Failed to bind (string): ") + key); |
|---|
| 243 | return ret; |
|---|
| 244 | } |
|---|
| 245 | handler::bound_int_type bind_int(std::wstring key) { |
|---|
| 246 | handler::bound_int_type ret; |
|---|
| 247 | if (key == _T("id")) |
|---|
| 248 | ret = &type_obj::get_id; |
|---|
| 249 | else if (key == _T("type")) |
|---|
| 250 | ret = &type_obj::get_el_type; |
|---|
| 251 | else if (key == _T("severity")) |
|---|
| 252 | ret = &type_obj::get_severity; |
|---|
| 253 | else if (key == _T("generated")) |
|---|
| 254 | ret = &type_obj::get_generated; |
|---|
| 255 | else if (key == _T("written")) |
|---|
| 256 | ret = &type_obj::get_written; |
|---|
| 257 | else |
|---|
| 258 | NSC_DEBUG_MSG_STD(_T("Failed to bind (int): ") + key); |
|---|
| 259 | return ret; |
|---|
| 260 | } |
|---|
| 261 | |
|---|
| 262 | bool has_function(parsers::where::value_type to, std::wstring name, parsers::where::expression_ast<type_obj> subject) { |
|---|
| 263 | if (to == type_custom_severity) |
|---|
| 264 | return true; |
|---|
| 265 | if (to == type_custom_type) |
|---|
| 266 | return true; |
|---|
| 267 | return false; |
|---|
| 268 | } |
|---|
| 269 | handler::bound_function_type bind_function(parsers::where::value_type to, std::wstring name, parsers::where::expression_ast<type_obj> subject) { |
|---|
| 270 | handler::bound_function_type ret; |
|---|
| 271 | if (to == type_custom_severity) |
|---|
| 272 | ret = &type_obj::fun_convert_severity; |
|---|
| 273 | if (to == type_custom_type) |
|---|
| 274 | ret = &type_obj::fun_convert_type; |
|---|
| 275 | return ret; |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | parsers::where::expression_ast<type_obj> fun_convert_severity(parsers::where::value_type target_type, parsers::where::expression_ast<type_obj> const& subject) { |
|---|
| 279 | return parsers::where::expression_ast<type_obj>(parsers::where::int_value(convert_severity(subject.get_string(*this)))); |
|---|
| 280 | } |
|---|
| 281 | parsers::where::expression_ast<type_obj> fun_convert_type(parsers::where::value_type target_type, parsers::where::expression_ast<type_obj> const& subject) { |
|---|
| 282 | return parsers::where::expression_ast<type_obj>(parsers::where::int_value(convert_type(subject.get_string(*this)))); |
|---|
| 283 | } |
|---|
| 284 | int convert_severity(std::wstring str) { |
|---|
| 285 | if (str == _T("success") || str == _T("ok")) |
|---|
| 286 | return 0; |
|---|
| 287 | if (str == _T("informational") || str == _T("info")) |
|---|
| 288 | return 1; |
|---|
| 289 | if (str == _T("warning") || str == _T("warn")) |
|---|
| 290 | return 2; |
|---|
| 291 | if (str == _T("error") || str == _T("err")) |
|---|
| 292 | return 3; |
|---|
| 293 | error(_T("Invalid severity: ") + str); |
|---|
| 294 | return strEx::stoi(str); |
|---|
| 295 | } |
|---|
| 296 | int convert_type(std::wstring str) { |
|---|
| 297 | if (str == _T("error")) |
|---|
| 298 | return EVENTLOG_ERROR_TYPE; |
|---|
| 299 | if (str == _T("warning")) |
|---|
| 300 | return EVENTLOG_WARNING_TYPE; |
|---|
| 301 | if (str == _T("info")) |
|---|
| 302 | return EVENTLOG_INFORMATION_TYPE; |
|---|
| 303 | if (str == _T("auditSuccess")) |
|---|
| 304 | return EVENTLOG_AUDIT_SUCCESS; |
|---|
| 305 | if (str == _T("auditFailure")) |
|---|
| 306 | return EVENTLOG_AUDIT_FAILURE; |
|---|
| 307 | return strEx::stoi(str); |
|---|
| 308 | } |
|---|
| 309 | |
|---|
| 310 | std::wstring get_error() { |
|---|
| 311 | std::wstring ret; |
|---|
| 312 | BOOST_FOREACH(std::wstring s, errors) { |
|---|
| 313 | if (!ret.empty()) ret += _T(", "); |
|---|
| 314 | ret += s; |
|---|
| 315 | } |
|---|
| 316 | return ret; |
|---|
| 317 | } |
|---|
| 318 | }; |
|---|
| 319 | } |
|---|
| 320 | } |
|---|
| 321 | |
|---|
| 322 | |
|---|
| 323 | |
|---|
| 324 | |
|---|
| 325 | struct filter_container { |
|---|
| 326 | enum filter_types { |
|---|
| 327 | filter_plus = 1, |
|---|
| 328 | filter_minus = 2, |
|---|
| 329 | filter_normal = 3 |
|---|
| 330 | }; |
|---|
| 331 | typedef std::pair<int,eventlog_filter> filteritem_type; |
|---|
| 332 | typedef std::list<filteritem_type > filterlist_type; |
|---|
| 333 | |
|---|
| 334 | filterlist_type filters; |
|---|
| 335 | |
|---|
| 336 | bool bFilterAll; |
|---|
| 337 | bool bFilterIn; |
|---|
| 338 | |
|---|
| 339 | bool bDebug; |
|---|
| 340 | int debugThreshold; |
|---|
| 341 | |
|---|
| 342 | bool bShowDescriptions; |
|---|
| 343 | std::wstring syntax; |
|---|
| 344 | |
|---|
| 345 | std::wstring filter; |
|---|
| 346 | |
|---|
| 347 | filter_container(std::wstring syntax, bool debug) : bDebug(debug), debugThreshold(0), bFilterIn(true), bFilterAll(false), bShowDescriptions(false), syntax(syntax) {} |
|---|
| 348 | |
|---|
| 349 | }; |
|---|
| 350 | |
|---|
| 351 | struct any_mode_filter { |
|---|
| 352 | virtual bool boot() = 0; |
|---|
| 353 | virtual bool validate(std::wstring &message) = 0; |
|---|
| 354 | virtual bool match(EventLogRecord &record) = 0; |
|---|
| 355 | virtual std::wstring get_name() = 0; |
|---|
| 356 | virtual std::wstring get_subject() = 0; |
|---|
| 357 | }; |
|---|
| 358 | |
|---|
| 359 | struct first_mode_filter : public any_mode_filter { |
|---|
| 360 | typedef filter_container::filterlist_type::const_iterator filter_iterator; |
|---|
| 361 | filter_container &data; |
|---|
| 362 | first_mode_filter(filter_container &data) : data(data) {} |
|---|
| 363 | bool boot() {return true;} |
|---|
| 364 | bool validate(std::wstring &message) { |
|---|
| 365 | if (data.filters.empty()) { |
|---|
| 366 | message = _T("No filters specified try adding: filter+generated=>2d"); |
|---|
| 367 | return false; |
|---|
| 368 | } |
|---|
| 369 | return true; |
|---|
| 370 | } |
|---|
| 371 | |
|---|
| 372 | virtual bool match(EventLogRecord &record) { |
|---|
| 373 | bool bMatch = !data.bFilterIn; |
|---|
| 374 | for (filter_iterator cit3 = data.filters.begin(); cit3 != data.filters.end(); ++cit3) { |
|---|
| 375 | std::wstring reason; |
|---|
| 376 | int mode = (*cit3).first; |
|---|
| 377 | bool bTmpMatched = (*cit3).second.matchFilter(record); |
|---|
| 378 | if (data.bFilterAll) { |
|---|
| 379 | if (!bTmpMatched) { |
|---|
| 380 | bMatch = false; |
|---|
| 381 | break; |
|---|
| 382 | } |
|---|
| 383 | } else { |
|---|
| 384 | if (bTmpMatched) { |
|---|
| 385 | bMatch = true; |
|---|
| 386 | break; |
|---|
| 387 | } |
|---|
| 388 | } |
|---|
| 389 | } |
|---|
| 390 | if ((data.bFilterIn&&bMatch)||(!data.bFilterIn&&!bMatch)) { |
|---|
| 391 | return true; |
|---|
| 392 | } |
|---|
| 393 | return false; |
|---|
| 394 | |
|---|
| 395 | } |
|---|
| 396 | std::wstring get_name() { |
|---|
| 397 | return _T("deprecated"); |
|---|
| 398 | } |
|---|
| 399 | std::wstring get_subject() { return _T("TODO"); } |
|---|
| 400 | |
|---|
| 401 | }; |
|---|
| 402 | struct second_mode_filter : public any_mode_filter { |
|---|
| 403 | typedef filter_container::filterlist_type::const_iterator filter_iterator; |
|---|
| 404 | |
|---|
| 405 | filter_container &data; |
|---|
| 406 | second_mode_filter(filter_container &data) : data(data) {} |
|---|
| 407 | bool boot() {return true;} |
|---|
| 408 | bool validate(std::wstring &message) { |
|---|
| 409 | if (data.filters.empty()) { |
|---|
| 410 | message = _T("No filters specified try adding: filter+generated=>2d"); |
|---|
| 411 | return false; |
|---|
| 412 | } |
|---|
| 413 | return true; |
|---|
| 414 | } |
|---|
| 415 | |
|---|
| 416 | virtual bool match(EventLogRecord &record) { |
|---|
| 417 | bool bMatch = !data.bFilterIn; |
|---|
| 418 | int i=0; |
|---|
| 419 | for (filter_iterator cit3 = data.filters.begin(); cit3 != data.filters.end(); ++cit3, i++ ) { |
|---|
| 420 | std::wstring reason; |
|---|
| 421 | int mode = (*cit3).first; |
|---|
| 422 | bool bTmpMatched = (*cit3).second.matchFilter(record); |
|---|
| 423 | if ((mode == filter_container::filter_minus)&&(bTmpMatched)) { |
|---|
| 424 | // a -<filter> hit so thrash item and bail out! |
|---|
| 425 | if (data.bDebug && (i>data.debugThreshold)) |
|---|
| 426 | NSC_DEBUG_MSG_STD(_T("[") + strEx::itos(i) + _T("] Matched: - ") + (*cit3).second.to_string() + _T(" for: ") + record.render(data.bShowDescriptions, data.syntax)); |
|---|
| 427 | return false; |
|---|
| 428 | } else if ((mode == filter_container::filter_plus)&&(!bTmpMatched)) { |
|---|
| 429 | // a +<filter> hit so keep item and bail out! |
|---|
| 430 | if (data.bDebug && (i>data.debugThreshold)) |
|---|
| 431 | NSC_DEBUG_MSG_STD(_T("[") + strEx::itos(i) + _T("] Matched: + ") + (*cit3).second.to_string() + _T(" for: ") + record.render(data.bShowDescriptions, data.syntax)); |
|---|
| 432 | return false; |
|---|
| 433 | } else if (bTmpMatched) { |
|---|
| 434 | if (data.bDebug && (i>data.debugThreshold)) |
|---|
| 435 | NSC_DEBUG_MSG_STD(_T("[") + strEx::itos(i) + _T("] Matched: . ") + (*cit3).second.to_string() + _T(" for: ") + record.render(data.bShowDescriptions, data.syntax)); |
|---|
| 436 | bMatch = true; |
|---|
| 437 | } |
|---|
| 438 | } |
|---|
| 439 | return bMatch; |
|---|
| 440 | } |
|---|
| 441 | std::wstring get_name() { |
|---|
| 442 | return _T("old"); |
|---|
| 443 | } |
|---|
| 444 | std::wstring get_subject() { return _T("TODO"); } |
|---|
| 445 | }; |
|---|
| 446 | |
|---|
| 447 | struct where_mode_filter : public any_mode_filter { |
|---|
| 448 | filter_container &data; |
|---|
| 449 | std::string message; |
|---|
| 450 | parsers::where::parser<filter::where::type_obj> ast_parser; |
|---|
| 451 | filter::where::type_obj dummy; |
|---|
| 452 | |
|---|
| 453 | where_mode_filter(filter_container &data) : data(data) {} |
|---|
| 454 | bool boot() {return true; } |
|---|
| 455 | |
|---|
| 456 | bool validate(std::wstring &message) { |
|---|
| 457 | if (data.bDebug) |
|---|
| 458 | NSC_DEBUG_MSG_STD(_T("Parsing: ") + data.filter); |
|---|
| 459 | |
|---|
| 460 | if (!ast_parser.parse(data.filter)) { |
|---|
| 461 | NSC_LOG_ERROR_STD(_T("Parsing failed of '") + data.filter + _T("' at: ") + ast_parser.rest); |
|---|
| 462 | message = _T("Parsing failed: ") + ast_parser.rest; |
|---|
| 463 | return false; |
|---|
| 464 | } |
|---|
| 465 | if (data.bDebug) |
|---|
| 466 | NSC_DEBUG_MSG_STD(_T("Parsing succeeded: ") + ast_parser.result_as_tree()); |
|---|
| 467 | |
|---|
| 468 | if (!ast_parser.derive_types(dummy) || dummy.has_error()) { |
|---|
| 469 | message = _T("Invalid types: ") + dummy.get_error(); |
|---|
| 470 | return false; |
|---|
| 471 | } |
|---|
| 472 | if (data.bDebug) |
|---|
| 473 | NSC_DEBUG_MSG_STD(_T("Type resolution succeeded: ") + ast_parser.result_as_tree()); |
|---|
| 474 | |
|---|
| 475 | if (!ast_parser.bind(dummy) || dummy.has_error()) { |
|---|
| 476 | message = _T("Variable and function binding failed: ") + dummy.get_error(); |
|---|
| 477 | return false; |
|---|
| 478 | } |
|---|
| 479 | if (data.bDebug) |
|---|
| 480 | NSC_DEBUG_MSG_STD(_T("Binding succeeded: ") + ast_parser.result_as_tree()); |
|---|
| 481 | |
|---|
| 482 | if (!ast_parser.static_eval(dummy) || dummy.has_error()) { |
|---|
| 483 | message = _T("Static evaluation failed: ") + dummy.get_error(); |
|---|
| 484 | return false; |
|---|
| 485 | } |
|---|
| 486 | if (data.bDebug) |
|---|
| 487 | NSC_DEBUG_MSG_STD(_T("Static evaluation succeeded: ") + ast_parser.result_as_tree()); |
|---|
| 488 | |
|---|
| 489 | return true; |
|---|
| 490 | } |
|---|
| 491 | virtual bool match(EventLogRecord &record) { |
|---|
| 492 | filter::where::type_obj obj(&record); |
|---|
| 493 | //NSC_DEBUG_MSG_STD(_T("Evaluating: ") + ast_parser.result_as_tree() + _T(": ") + strEx::itos(record.severity()) + _T(" >> ") + strEx::itos(ast_parser.evaluate(obj))); |
|---|
| 494 | bool ret = ast_parser.evaluate(obj); |
|---|
| 495 | if (obj.has_error()) { |
|---|
| 496 | NSC_LOG_ERROR_STD(_T("Error: ") + obj.get_error()); |
|---|
| 497 | } |
|---|
| 498 | return ret; |
|---|
| 499 | } |
|---|
| 500 | std::wstring get_name() { |
|---|
| 501 | return _T("where"); |
|---|
| 502 | } |
|---|
| 503 | std::wstring get_subject() { return data.filter; } |
|---|
| 504 | }; |
|---|
| 505 | |
|---|
| 506 | |
|---|
| 507 | |
|---|
| 508 | void CheckEventLog::parse(std::wstring expr) { |
|---|
| 509 | //return false; |
|---|
| 510 | /* |
|---|
| 511 | my_type_obj obj1(123); |
|---|
| 512 | std::wcout << _T("Result (001): ") << ast_parser.evaluate(obj1) << std::endl; |
|---|
| 513 | my_type_obj obj2(321); |
|---|
| 514 | std::wcout << _T("Result (002): ") << ast_parser.evaluate(obj2) << std::endl; |
|---|
| 515 | */ |
|---|
| 516 | } |
|---|
| 517 | |
|---|
| 518 | |
|---|
| 519 | |
|---|
| 520 | std::wstring find_eventlog_name(std::wstring name) { |
|---|
| 521 | try { |
|---|
| 522 | simple_registry::registry_key key(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog")); |
|---|
| 523 | std::list<std::wstring> list = key.get_keys(); |
|---|
| 524 | for (std::list<std::wstring>::const_iterator cit = list.begin(); cit != list.end(); ++cit) { |
|---|
| 525 | try { |
|---|
| 526 | simple_registry::registry_key sub_key(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\") + *cit); |
|---|
| 527 | std::wstring file = sub_key.get_string(_T("DisplayNameFile")); |
|---|
| 528 | int id = sub_key.get_int(_T("DisplayNameID")); |
|---|
| 529 | std::wstring real_name = error::format::message::from_module(file, id); |
|---|
| 530 | strEx::replace(real_name, _T("\n"), _T("")); |
|---|
| 531 | strEx::replace(real_name, _T("\r"), _T("")); |
|---|
| 532 | NSC_DEBUG_MSG(_T("Attempting to match: ") + real_name + _T(" with ") + name); |
|---|
| 533 | if (real_name == name) |
|---|
| 534 | return *cit; |
|---|
| 535 | } catch (simple_registry::registry_exception &e) { e;} |
|---|
| 536 | } |
|---|
| 537 | return name; |
|---|
| 538 | } catch (simple_registry::registry_exception &e) { |
|---|
| 539 | NSC_DEBUG_MSG(_T("Failed to get eventlog name (assuming shorthand): ") + e.what()); |
|---|
| 540 | return name; |
|---|
| 541 | } catch (...) { |
|---|
| 542 | NSC_DEBUG_MSG(_T("Failed to get eventlog name (assuming shorthand)")); |
|---|
| 543 | return name; |
|---|
| 544 | } |
|---|
| 545 | } |
|---|
| 546 | |
|---|
| 547 | |
|---|
| 548 | |
|---|
| 549 | class uniq_eventlog_record { |
|---|
| 550 | DWORD ID; |
|---|
| 551 | WORD type; |
|---|
| 552 | WORD category; |
|---|
| 553 | public: |
|---|
| 554 | std::wstring message; |
|---|
| 555 | uniq_eventlog_record(EVENTLOGRECORD *pevlr) : ID(pevlr->EventID&0xffff), type(pevlr->EventType), category(pevlr->EventCategory) {} |
|---|
| 556 | bool operator< (const uniq_eventlog_record &other) const { |
|---|
| 557 | return (ID < other.ID) || ((ID==other.ID)&&(type < other.type)) || (ID==other.ID&&type==other.type)&&(category < other.category); |
|---|
| 558 | } |
|---|
| 559 | std::wstring to_string() const { |
|---|
| 560 | return _T("id=") + strEx::itos(ID) + _T("type=") + strEx::itos(type) + _T("category=") + strEx::itos(category); |
|---|
| 561 | } |
|---|
| 562 | }; |
|---|
| 563 | typedef std::map<uniq_eventlog_record,unsigned int> uniq_eventlog_map; |
|---|
| 564 | |
|---|
| 565 | |
|---|
| 566 | |
|---|
| 567 | |
|---|
| 568 | |
|---|
| 569 | #define MAP_FILTER(value, obj, filtermode) \ |
|---|
| 570 | else if (p__.first == value) { filter.obj = p__.second; if (bPush) { data.filters.push_back(filter_container::filteritem_type(filtermode, filter)); filter = eventlog_filter(); } } |
|---|
| 571 | #define MAP_FILTER_LAST(value, obj) \ |
|---|
| 572 | else if (p__.first == value) { data.filters.front().second.obj = p__.second; } |
|---|
| 573 | |
|---|
| 574 | struct event_log_buffer { |
|---|
| 575 | BYTE *bBuffer; |
|---|
| 576 | DWORD bufferSize_; |
|---|
| 577 | event_log_buffer(DWORD bufferSize) : bufferSize_(bufferSize) { |
|---|
| 578 | bBuffer = new BYTE[bufferSize+10]; |
|---|
| 579 | } |
|---|
| 580 | ~event_log_buffer() { |
|---|
| 581 | delete [] bBuffer; |
|---|
| 582 | } |
|---|
| 583 | EVENTLOGRECORD* getBufferUnsafe() { |
|---|
| 584 | return reinterpret_cast<EVENTLOGRECORD*>(bBuffer); |
|---|
| 585 | } |
|---|
| 586 | DWORD getBufferSize() { |
|---|
| 587 | return bufferSize_; |
|---|
| 588 | } |
|---|
| 589 | }; |
|---|
| 590 | |
|---|
| 591 | NSCAPI::nagiosReturn CheckEventLog::handleCommand(const strEx::wci_string command, std::list<std::wstring> arguments, std::wstring &message, std::wstring &perf) { |
|---|
| 592 | if (command != _T("CheckEventLog")) |
|---|
| 593 | return NSCAPI::returnIgnored; |
|---|
| 594 | simple_timer time; |
|---|
| 595 | typedef checkHolders::CheckContainer<checkHolders::MaxMinBoundsULongInteger> EventLogQuery1Container; |
|---|
| 596 | typedef checkHolders::CheckContainer<checkHolders::ExactBoundsULongInteger> EventLogQuery2Container; |
|---|
| 597 | |
|---|
| 598 | NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK; |
|---|
| 599 | |
|---|
| 600 | std::list<std::wstring> files; |
|---|
| 601 | EventLogQuery1Container query1; |
|---|
| 602 | EventLogQuery2Container query2; |
|---|
| 603 | |
|---|
| 604 | |
|---|
| 605 | filter_container data(syntax_, debug_); |
|---|
| 606 | |
|---|
| 607 | bool bPerfData = true; |
|---|
| 608 | bool bFilterNew = true; |
|---|
| 609 | bool unique = false; |
|---|
| 610 | unsigned int truncate = 0; |
|---|
| 611 | event_log_buffer buffer(buffer_length_); |
|---|
| 612 | bool bPush = true; |
|---|
| 613 | eventlog_filter filter; |
|---|
| 614 | /* |
|---|
| 615 | try { |
|---|
| 616 | event_log_buffer buffer(buffer_length_); |
|---|
| 617 | } catch (std::exception e) { |
|---|
| 618 | message = std::wstring(_T("Failed to allocate memory: ")) + strEx::string_to_wstring(e.what()); |
|---|
| 619 | return NSCAPI::returnUNKNOWN; |
|---|
| 620 | } |
|---|
| 621 | */ |
|---|
| 622 | |
|---|
| 623 | try { |
|---|
| 624 | MAP_OPTIONS_BEGIN(arguments) |
|---|
| 625 | MAP_OPTIONS_NUMERIC_ALL(query1, _T("")) |
|---|
| 626 | MAP_OPTIONS_EXACT_NUMERIC_ALL(query2, _T("")) |
|---|
| 627 | MAP_OPTIONS_STR2INT(_T("truncate"), truncate) |
|---|
| 628 | MAP_OPTIONS_BOOL_TRUE(_T("unique"), unique) |
|---|
| 629 | MAP_OPTIONS_BOOL_TRUE(_T("descriptions"), data.bShowDescriptions) |
|---|
| 630 | MAP_OPTIONS_PUSH(_T("file"), files) |
|---|
| 631 | MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData) |
|---|
| 632 | MAP_OPTIONS_BOOL_EX(_T("filter"), bFilterNew, _T("new"), _T("old")) |
|---|
| 633 | MAP_OPTIONS_BOOL_EX(_T("filter"), data.bFilterIn, _T("in"), _T("out")) |
|---|
| 634 | MAP_OPTIONS_BOOL_EX(_T("filter"), data.bFilterAll, _T("all"), _T("any")) |
|---|
| 635 | MAP_OPTIONS_BOOL_EX(_T("debug"), data.bDebug, _T("true"), _T("false")) |
|---|
| 636 | MAP_OPTIONS_STR2INT(_T("debug-threshold"), data.debugThreshold) |
|---|
| 637 | MAP_OPTIONS_STR(_T("syntax"), data.syntax) |
|---|
| 638 | /* |
|---|
| 639 | MAP_FILTER_OLD("filter-eventType", eventType) |
|---|
| 640 | MAP_FILTER_OLD("filter-severity", eventSeverity) |
|---|
| 641 | MAP_FILTER_OLD("filter-eventID", eventID) |
|---|
| 642 | MAP_FILTER_OLD("filter-eventSource", eventSource) |
|---|
| 643 | MAP_FILTER_OLD("filter-generated", timeGenerated) |
|---|
| 644 | MAP_FILTER_OLD("filter-written", timeWritten) |
|---|
| 645 | MAP_FILTER_OLD("filter-message", message) |
|---|
| 646 | */ |
|---|
| 647 | MAP_FILTER(_T("filter+eventType"), eventType, filter_container::filter_plus) |
|---|
| 648 | MAP_FILTER(_T("filter+severity"), eventSeverity, filter_container::filter_plus) |
|---|
| 649 | MAP_FILTER(_T("filter+eventID"), eventID, filter_container::filter_plus) |
|---|
| 650 | MAP_FILTER(_T("filter+eventSource"), eventSource, filter_container::filter_plus) |
|---|
| 651 | MAP_FILTER(_T("filter+generated"), timeGenerated, filter_container::filter_plus) |
|---|
| 652 | MAP_FILTER(_T("filter+written"), timeWritten, filter_container::filter_plus) |
|---|
| 653 | MAP_FILTER(_T("filter+message"), message, filter_container::filter_plus) |
|---|
| 654 | |
|---|
| 655 | MAP_FILTER(_T("filter.eventType"), eventType, filter_container::filter_normal) |
|---|
| 656 | MAP_FILTER(_T("filter.severity"), eventSeverity, filter_container::filter_normal) |
|---|
| 657 | MAP_FILTER(_T("filter.eventID"), eventID, filter_container::filter_normal) |
|---|
| 658 | MAP_FILTER(_T("filter.eventSource"), eventSource, filter_container::filter_normal) |
|---|
| 659 | MAP_FILTER(_T("filter.generated"), timeGenerated, filter_container::filter_normal) |
|---|
| 660 | MAP_FILTER(_T("filter.written"), timeWritten, filter_container::filter_normal) |
|---|
| 661 | MAP_FILTER(_T("filter.message"), message, filter_container::filter_normal) |
|---|
| 662 | |
|---|
| 663 | MAP_FILTER(_T("filter-eventType"), eventType, filter_container::filter_minus) |
|---|
| 664 | MAP_FILTER(_T("filter-severity"), eventSeverity, filter_container::filter_minus) |
|---|
| 665 | MAP_FILTER(_T("filter-eventID"), eventID, filter_container::filter_minus) |
|---|
| 666 | MAP_FILTER(_T("filter-eventSource"), eventSource, filter_container::filter_minus) |
|---|
| 667 | MAP_FILTER(_T("filter-generated"), timeGenerated, filter_container::filter_minus) |
|---|
| 668 | MAP_FILTER(_T("filter-written"), timeWritten, filter_container::filter_minus) |
|---|
| 669 | MAP_FILTER(_T("filter-message"), message, filter_container::filter_minus) |
|---|
| 670 | |
|---|
| 671 | MAP_FILTER_LAST(_T("append-filter-eventType"), eventType) |
|---|
| 672 | MAP_FILTER_LAST(_T("append-filter-severity"), eventSeverity) |
|---|
| 673 | MAP_FILTER_LAST(_T("append-filter-eventID"), eventID) |
|---|
| 674 | MAP_FILTER_LAST(_T("append-filter-eventSource"), eventSource) |
|---|
| 675 | MAP_FILTER_LAST(_T("append-filter-generated"), timeGenerated) |
|---|
| 676 | MAP_FILTER_LAST(_T("append-filter-written"), timeWritten) |
|---|
| 677 | MAP_FILTER_LAST(_T("append-filter-message"), message) |
|---|
| 678 | |
|---|
| 679 | MAP_OPTIONS_STR(_T("filter"), data.filter) |
|---|
| 680 | |
|---|
| 681 | MAP_OPTIONS_MISSING(message, _T("Unknown argument: ")) |
|---|
| 682 | MAP_OPTIONS_END() |
|---|
| 683 | } catch (filters::parse_exception e) { |
|---|
| 684 | message = e.getMessage(); |
|---|
| 685 | return NSCAPI::returnUNKNOWN; |
|---|
| 686 | } catch (filters::filter_exception e) { |
|---|
| 687 | message = e.getMessage(); |
|---|
| 688 | return NSCAPI::returnUNKNOWN; |
|---|
| 689 | } catch (checkHolders::parse_exception e) { |
|---|
| 690 | message = e.getMessage(); |
|---|
| 691 | return NSCAPI::returnUNKNOWN; |
|---|
| 692 | } catch (...) { |
|---|
| 693 | message = _T("Invalid command line!"); |
|---|
| 694 | return NSCAPI::returnUNKNOWN; |
|---|
| 695 | } |
|---|
| 696 | |
|---|
| 697 | unsigned long int hit_count = 0; |
|---|
| 698 | if (files.empty()) { |
|---|
| 699 | message = _T("No file specified try adding: file=Application"); |
|---|
| 700 | return NSCAPI::returnUNKNOWN; |
|---|
| 701 | } |
|---|
| 702 | bool buffer_error_reported = false; |
|---|
| 703 | |
|---|
| 704 | if (data.bDebug) { |
|---|
| 705 | std::wstring str; |
|---|
| 706 | BOOST_FOREACH(filter_container::filteritem_type item, data.filters) { |
|---|
| 707 | if (item.first == filter_container::filter_normal) |
|---|
| 708 | str += _T(". {"); |
|---|
| 709 | else if (item.first == filter_container::filter_plus) |
|---|
| 710 | str += _T("+ {"); |
|---|
| 711 | else if (item.first == filter_container::filter_minus) |
|---|
| 712 | str += _T("- {"); |
|---|
| 713 | else |
|---|
| 714 | str += _T("? {"); |
|---|
| 715 | |
|---|
| 716 | str += item.second.to_string() + _T(" }"); |
|---|
| 717 | } |
|---|
| 718 | NSC_DEBUG_MSG_STD(_T("Filter: ") + str); |
|---|
| 719 | } |
|---|
| 720 | |
|---|
| 721 | boost::shared_ptr<any_mode_filter> filter_impl; |
|---|
| 722 | if (bFilterNew) { |
|---|
| 723 | filter_impl = boost::shared_ptr<any_mode_filter>(new second_mode_filter(data)); |
|---|
| 724 | } else { |
|---|
| 725 | filter_impl = boost::shared_ptr<any_mode_filter>(new second_mode_filter(data)); |
|---|
| 726 | } if (!data.filter.empty()) { |
|---|
| 727 | filter_impl = boost::shared_ptr<any_mode_filter>(new where_mode_filter(data)); |
|---|
| 728 | } |
|---|
| 729 | |
|---|
| 730 | if (!filter_impl) { |
|---|
| 731 | message = _T("Failed to initialize filter subsystem."); |
|---|
| 732 | return NSCAPI::returnUNKNOWN; |
|---|
| 733 | } |
|---|
| 734 | |
|---|
| 735 | filter_impl->boot(); |
|---|
| 736 | |
|---|
| 737 | __time64_t ltime; |
|---|
| 738 | _time64(<ime); |
|---|
| 739 | |
|---|
| 740 | NSC_DEBUG_MSG_STD(_T("Using: ") + filter_impl->get_name() + _T(" ") + filter_impl->get_subject()); |
|---|
| 741 | |
|---|
| 742 | if (!filter_impl->validate(message)) { |
|---|
| 743 | return NSCAPI::returnUNKNOWN; |
|---|
| 744 | } |
|---|
| 745 | |
|---|
| 746 | |
|---|
| 747 | NSC_DEBUG_MSG_STD(_T("Boot time: ") + strEx::itos(time.stop())); |
|---|
| 748 | |
|---|
| 749 | for (std::list<std::wstring>::const_iterator cit2 = files.begin(); cit2 != files.end(); ++cit2) { |
|---|
| 750 | std::wstring name = *cit2; |
|---|
| 751 | if (lookup_names_) { |
|---|
| 752 | name = find_eventlog_name(*cit2); |
|---|
| 753 | if ((*cit2) != name) { |
|---|
| 754 | NSC_DEBUG_MSG_STD(_T("Opening alternative log: ") + name); |
|---|
| 755 | } |
|---|
| 756 | } |
|---|
| 757 | HANDLE hLog = OpenEventLog(NULL, name.c_str()); |
|---|
| 758 | if (hLog == NULL) { |
|---|
| 759 | message = _T("Could not open the '") + (*cit2) + _T("' event log: ") + error::lookup::last_error(); |
|---|
| 760 | return NSCAPI::returnUNKNOWN; |
|---|
| 761 | } |
|---|
| 762 | uniq_eventlog_map uniq_records; |
|---|
| 763 | |
|---|
| 764 | //DWORD dwThisRecord; |
|---|
| 765 | DWORD dwRead, dwNeeded; |
|---|
| 766 | |
|---|
| 767 | |
|---|
| 768 | //GetOldestEventLogRecord(hLog, &dwThisRecord); |
|---|
| 769 | |
|---|
| 770 | while (true) { |
|---|
| 771 | BOOL bStatus = ReadEventLog(hLog, EVENTLOG_FORWARDS_READ|EVENTLOG_SEQUENTIAL_READ, |
|---|
| 772 | 0, buffer.getBufferUnsafe(), buffer.getBufferSize(), &dwRead, &dwNeeded); |
|---|
| 773 | if (bStatus == FALSE) { |
|---|
| 774 | DWORD err = GetLastError(); |
|---|
| 775 | if (err == ERROR_INSUFFICIENT_BUFFER) { |
|---|
| 776 | if (!buffer_error_reported) { |
|---|
| 777 | NSC_LOG_ERROR_STD(_T("EvenlogBuffer is too small change the value of ") + setting_keys::event_log::BUFFER_SIZE_PATH + _T("=") + strEx::itos(dwNeeded+1) + _T(": ") + error::lookup::last_error(err)); |
|---|
| 778 | buffer_error_reported = true; |
|---|
| 779 | } |
|---|
| 780 | } else if (err == ERROR_HANDLE_EOF) { |
|---|
| 781 | break; |
|---|
| 782 | } else { |
|---|
| 783 | NSC_LOG_ERROR_STD(_T("Failed to read from eventlog: ") + error::lookup::last_error(err)); |
|---|
| 784 | message = _T("Failed to read from eventlog: ") + error::lookup::last_error(err); |
|---|
| 785 | CloseEventLog(hLog); |
|---|
| 786 | return NSCAPI::returnUNKNOWN; |
|---|
| 787 | } |
|---|
| 788 | } |
|---|
| 789 | EVENTLOGRECORD *pevlr = buffer.getBufferUnsafe(); |
|---|
| 790 | while (dwRead > 0) { |
|---|
| 791 | EventLogRecord record((*cit2), pevlr, ltime); |
|---|
| 792 | bool match = filter_impl->match(record); |
|---|
| 793 | if (match&&unique) { |
|---|
| 794 | match = false; |
|---|
| 795 | uniq_eventlog_record uniq_record = pevlr; |
|---|
| 796 | uniq_eventlog_map::iterator it = uniq_records.find(uniq_record); |
|---|
| 797 | if (it != uniq_records.end()) { |
|---|
| 798 | (*it).second ++; |
|---|
| 799 | //match = false; |
|---|
| 800 | } |
|---|
| 801 | else { |
|---|
| 802 | if (!data.syntax.empty()) { |
|---|
| 803 | uniq_record.message = record.render(data.bShowDescriptions, data.syntax); |
|---|
| 804 | } else if (!data.bShowDescriptions) { |
|---|
| 805 | uniq_record.message = record.eventSource(); |
|---|
| 806 | } else { |
|---|
| 807 | uniq_record.message = record.eventSource(); |
|---|
| 808 | uniq_record.message += _T("(") + EventLogRecord::translateType(record.eventType()) + _T(", ") + |
|---|
| 809 | strEx::itos(record.eventID()) + _T(", ") + EventLogRecord::translateSeverity(record.severity()) + _T(")"); |
|---|
| 810 | uniq_record.message += _T("[") + record.enumStrings() + _T("]"); |
|---|
| 811 | uniq_record.message += _T("{%count%}"); |
|---|
| 812 | } |
|---|
| 813 | uniq_records[uniq_record] = 1; |
|---|
| 814 | } |
|---|
| 815 | hit_count++; |
|---|
| 816 | } else if (match) { |
|---|
| 817 | if (!data.syntax.empty()) { |
|---|
| 818 | strEx::append_list(message, record.render(data.bShowDescriptions, data.syntax)); |
|---|
| 819 | } else if (!data.bShowDescriptions) { |
|---|
| 820 | strEx::append_list(message, record.eventSource()); |
|---|
| 821 | } else { |
|---|
| 822 | strEx::append_list(message, record.eventSource()); |
|---|
| 823 | message += _T("(") + EventLogRecord::translateType(record.eventType()) + _T(", ") + |
|---|
| 824 | strEx::itos(record.eventID()) + _T(", ") + EventLogRecord::translateSeverity(record.severity()) + _T(")"); |
|---|
| 825 | message += _T("[") + record.enumStrings() + _T("]"); |
|---|
| 826 | } |
|---|
| 827 | hit_count++; |
|---|
| 828 | } |
|---|
| 829 | dwRead -= pevlr->Length; |
|---|
| 830 | pevlr = reinterpret_cast<EVENTLOGRECORD*>((LPBYTE)pevlr + pevlr->Length); |
|---|
| 831 | } |
|---|
| 832 | } |
|---|
| 833 | CloseEventLog(hLog); |
|---|
| 834 | for (uniq_eventlog_map::const_iterator cit = uniq_records.begin(); cit != uniq_records.end(); ++cit) { |
|---|
| 835 | std::wstring msg = (*cit).first.message; |
|---|
| 836 | strEx::replace(msg, _T("%count%"), strEx::itos((*cit).second)); |
|---|
| 837 | strEx::append_list(message, msg); |
|---|
| 838 | } |
|---|
| 839 | } |
|---|
| 840 | NSC_DEBUG_MSG_STD(_T("Evaluation time: ") + strEx::itos(time.stop())); |
|---|
| 841 | |
|---|
| 842 | if (!bPerfData) { |
|---|
| 843 | query1.perfData = false; |
|---|
| 844 | query2.perfData = false; |
|---|
| 845 | } |
|---|
| 846 | if (query1.alias.empty()) |
|---|
| 847 | query1.alias = _T("eventlog"); |
|---|
| 848 | if (query2.alias.empty()) |
|---|
| 849 | query2.alias = _T("eventlog"); |
|---|
| 850 | if (query1.hasBounds()) |
|---|
| 851 | query1.runCheck(hit_count, returnCode, message, perf); |
|---|
| 852 | else if (query2.hasBounds()) |
|---|
| 853 | query2.runCheck(hit_count, returnCode, message, perf); |
|---|
| 854 | else { |
|---|
| 855 | message = _T("No bounds specified!"); |
|---|
| 856 | return NSCAPI::returnUNKNOWN; |
|---|
| 857 | } |
|---|
| 858 | if ((truncate > 0) && (message.length() > (truncate-4))) |
|---|
| 859 | message = message.substr(0, truncate-4) + _T("..."); |
|---|
| 860 | if (message.empty()) |
|---|
| 861 | message = _T("Eventlog check ok"); |
|---|
| 862 | return returnCode; |
|---|
| 863 | } |
|---|
| 864 | |
|---|
| 865 | |
|---|
| 866 | NSC_WRAP_DLL(); |
|---|
| 867 | NSC_WRAPPERS_MAIN_DEF(gCheckEventLog); |
|---|
| 868 | NSC_WRAPPERS_IGNORE_MSG_DEF(); |
|---|
| 869 | NSC_WRAPPERS_HANDLE_CMD_DEF(gCheckEventLog); |
|---|