/* finalize eventlog6 and free the handles */ int finalize_eventlog6(EVT_HANDLE *render_context, EVT_HANDLE *query) { const char *__function_name = "finalize_eventlog6"; int ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (NULL != *query) { EvtClose(*query); *query = NULL; } if (NULL != *render_context) { EvtClose(*render_context); *render_context = NULL; } ret = SUCCEED; zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
void close_eventlog_context(void *v) { zbx_eventlog_context *context = v; if (context == NULL || EvtClose == NULL) return; EvtClose(context->handle); EvtClose(context->context_handle); if (context->each_handle) EvtClose(context->each_handle); if (context->keyword_context_handle) EvtClose(context->keyword_context_handle); zbx_free(context); }
/* expand the string message from a specific event handler */ static char *expand_message6(const wchar_t *pname, EVT_HANDLE event) { const char *__function_name = "expand_message6"; wchar_t *pmessage = NULL; EVT_HANDLE provider = NULL; DWORD require = 0; char *out_message = NULL; char *tmp_pname = NULL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (NULL == (provider = EvtOpenPublisherMetadata(NULL, pname, NULL, 0, 0))) { tmp_pname = zbx_unicode_to_utf8(pname); zabbix_log(LOG_LEVEL_DEBUG, "provider '%s' could not be opened: %s", strerror_from_system(GetLastError()), tmp_pname); zbx_free(tmp_pname); goto out; } if (TRUE != EvtFormatMessage(provider, event, 0, 0, NULL, EvtFormatMessageEvent, 0, NULL, &require)) { if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { DWORD error = ERROR_SUCCESS; pmessage = zbx_malloc(pmessage, sizeof(WCHAR) * require); if (TRUE != EvtFormatMessage(provider, event, 0, 0, NULL, EvtFormatMessageEvent, require, pmessage, &require)) { error = GetLastError(); } if (ERROR_SUCCESS == error || ERROR_EVT_UNRESOLVED_VALUE_INSERT == error || ERROR_EVT_UNRESOLVED_PARAMETER_INSERT == error || ERROR_EVT_MAX_INSERTS_REACHED == error) { out_message = zbx_unicode_to_utf8(pmessage); } else { zabbix_log(LOG_LEVEL_DEBUG, "%s() cannot format message: %s", __function_name, strerror_from_system(error)); goto out; } } } out: if (NULL != provider) EvtClose(provider); zbx_free(pmessage); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, out_message); /* should be freed */ return out_message; }
/** * @brief Enumerate all the events in the result set. * @param results The handle to a query or subscription result set that * the EvtQuery function or the EvtSubscribe function returns. * * @return returns Status code. */ DWORD EventLogReader::PrintResults(EVT_HANDLE results) { DWORD status = ERROR_SUCCESS; static const int ArraySize = 10; DWORD returned = 0; EVT_HANDLE events[ArraySize] = { 0 }; bool run = true; while (run) { // Get a block of events from the result set. if (!EvtNext(results, ArraySize, events, INFINITE, 0, &returned)) break; // For each event, call the PrintEvent function which renders the // event for display. PrintEvent is shown in RenderingEvents. for (DWORD i = 0; i < returned; i++) { _position++; status = PrintEvent(events[i]); if (status == ERROR_SUCCESS) { EvtClose(events[i]); events[i] = nullptr; } else { run = false; break; } } } for (DWORD i = 0; i < returned; i++) { if (events[i] != nullptr) EvtClose(events[i]); } return status; }
/* Get specific values from an event */ PEVT_VARIANT GetEventInfo(EVT_HANDLE hEvent) { EVT_HANDLE hContext = NULL; PEVT_VARIANT pRenderedEvents = NULL; LPWSTR ppValues[] = {L"Event/System/Provider/@Name", L"Event/System/TimeCreated/@SystemTime", L"Event/System/EventID", L"Event/System/Level", L"Event/System/Keywords"}; DWORD count = COUNT_OF(ppValues); DWORD dwReturned = 0; DWORD dwBufferSize = (256*sizeof(LPWSTR)*count); DWORD dwValuesCount = 0; DWORD status = 0; /* Create the context to use for EvtRender */ hContext = EvtCreateRenderContext(count, (LPCWSTR*)ppValues, EvtRenderContextValues); if (NULL == hContext) { Log(LOG_ERROR|LOG_SYS, "EvtCreateRenderContext failed"); goto cleanup; } pRenderedEvents = (PEVT_VARIANT)malloc(dwBufferSize); /* Use EvtRender to capture the Publisher name from the Event */ /* Log Errors to the event log if things go wrong */ if (!EvtRender(hContext, hEvent, EvtRenderEventValues, dwBufferSize, pRenderedEvents, &dwReturned, &dwValuesCount)) { if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { dwBufferSize = dwReturned; realloc(pRenderedEvents, dwBufferSize); if (!EvtRender(hContext, hEvent, EvtRenderEventValues, dwBufferSize, pRenderedEvents, &dwReturned, &dwValuesCount)) { if (LogInteractive) Log(LOG_ERROR|LOG_SYS, "Error Rendering Event"); status = ERR_FAIL; } } else { status = ERR_FAIL; if (LogInteractive) Log(LOG_ERROR|LOG_SYS, "Error Rendering Event"); } } cleanup: if (hContext) EvtClose(hContext); if (status == ERR_FAIL) return NULL; else return pRenderedEvents; }
/* expand the string message from a specific event handler */ static char *expand_message6(const wchar_t *pname, EVT_HANDLE event) { const char *__function_name = "expand_message6"; wchar_t *pmessage = NULL; EVT_HANDLE provider = NULL; DWORD require = 0; char *out_message = NULL; char *tmp_pname = NULL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (NULL == (provider = EvtOpenPublisherMetadata(NULL, pname, NULL, 0, 0))) { tmp_pname = zbx_unicode_to_utf8(pname); zabbix_log(LOG_LEVEL_DEBUG, "provider '%s' could not be opened: %s", strerror_from_system(GetLastError()), tmp_pname); zbx_free(tmp_pname); goto finish; } if (TRUE != EvtFormatMessage(provider, event, 0, 0, NULL, EvtFormatMessageEvent, 0, NULL, &require) ) { if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { pmessage = zbx_malloc(pmessage, sizeof(WCHAR) * require); if (TRUE != EvtFormatMessage(provider, event, 0, 0, NULL, EvtFormatMessageEvent, require, pmessage, &require)) { zabbix_log(LOG_LEVEL_DEBUG, "formatting message failed: %s", strerror_from_system(GetLastError())); goto finish; } out_message = zbx_unicode_to_utf8(pmessage); } } finish: if (NULL != provider) EvtClose(provider); zbx_free(pmessage); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, out_message); /* should be freed*/ return out_message; }
/** * @brief Get the list of events. */ void EventLogReader::ReadEvents() { DWORD status = ERROR_SUCCESS; std::wstring buf = base::string_to_wstring(_query); EVT_HANDLE results = EvtQuery(nullptr, nullptr, buf.c_str(), EvtQueryChannelPath | EvtQueryTolerateQueryErrors); if (results == nullptr) return; if (!EvtSeek(results, _position, nullptr, 0, EvtSeekRelativeToFirst)) return; if (PrintQueryStatuses(results) == ERROR_SUCCESS) PrintResults(results); if (results) EvtClose(results); }
void win_start_event_channel(char *evt_log, char future, char *query) { wchar_t *wchannel = NULL; wchar_t *wquery = NULL; os_channel *channel = NULL; DWORD flags = EvtSubscribeToFutureEvents; EVT_HANDLE bookmark = NULL; EVT_HANDLE result = NULL; int status = 0; if ((channel = calloc(1, sizeof(os_channel))) == NULL) { log2file( "%s: ERROR: Could not calloc() memory for channel to start reading (%s) which returned [(%d)-(%s)]", ARGV0, evt_log, errno, strerror(errno)); goto cleanup; } channel->evt_log = evt_log; /* Create copy of event log string */ if ((channel->bookmark_name = strdup(channel->evt_log)) == NULL) { log2file( "%s: ERROR: Could not strdup() event log name to start reading (%s) which returned [(%d)-(%s)]", ARGV0, channel->evt_log, errno, strerror(errno)); goto cleanup; } /* Replace '/' with '_' */ if (strchr(channel->bookmark_name, '/')) { *(strrchr(channel->bookmark_name, '/')) = '_'; } /* Convert evt_log to Windows string */ if ((wchannel = convert_unix_string(channel->evt_log)) == NULL) { log2file( "%s: ERROR: Could not convert_unix_string() evt_log for (%s) which returned [(%d)-(%s)]", ARGV0, channel->evt_log, errno, strerror(errno)); goto cleanup; } /* Convert query to Windows string */ if (query) { if ((wquery = convert_unix_string(query)) == NULL) { log2file( "%s: ERROR: Could not convert_unix_string() query for (%s) which returned [(%d)-(%s)]", ARGV0, channel->evt_log, errno, strerror(errno)); goto cleanup; } } channel->bookmark_enabled = !future; if (channel->bookmark_enabled) { /* Create bookmark file name */ snprintf(channel->bookmark_filename, sizeof(channel->bookmark_filename), "%s/%s", BOOKMARKS_DIR, channel->bookmark_name); /* Try to read existing bookmark */ if ((bookmark = read_bookmark(channel)) != NULL) { flags = EvtSubscribeStartAfterBookmark; } } result = EvtSubscribe(NULL, NULL, wchannel, wquery, bookmark, channel, (EVT_SUBSCRIBE_CALLBACK)event_channel_callback, flags); if (result == NULL && flags == EvtSubscribeStartAfterBookmark) { result = EvtSubscribe(NULL, NULL, wchannel, wquery, NULL, channel, (EVT_SUBSCRIBE_CALLBACK)event_channel_callback, EvtSubscribeToFutureEvents); } if (result == NULL) { log2file( "%s: ERROR: Could not EvtSubscribe() for (%s) which returned (%lu)", ARGV0, channel->evt_log, GetLastError()); goto cleanup; } /* Success */ status = 1; cleanup: free(wchannel); free(wquery); if (status == 0) { free(channel->bookmark_name); free(channel); if (result != NULL) { EvtClose(result); } } if (bookmark != NULL) { EvtClose(bookmark); } return; }
DWORD GetEventRawDescriptions ( __in PCWSTR ProviderName, __in LCID Locale ) /*++ Routine Description: This function gets the raw event description strings. Parameters: ProviderName - Supplies the provider name. Locale - Supplies the LCID. Return Value: Win32 error code indicating the status of the function execution. --*/ { PWSTR Description; ULONG BufferLength; ULONG BufferLengthNeeded; ULONG BufferUsed; EVT_VARIANT EventId; EVT_VARIANT EventMessageId; EVT_HANDLE EventMeta; EVT_HANDLE EventMetaEnum; EVT_HANDLE ProviderMetadata; ULONG Status; // // Open the provider meta data. // ProviderMetadata = EvtOpenPublisherMetadata(NULL, ProviderName, NULL, Locale, 0); if (ProviderMetadata == NULL) { return GetLastError(); } // // Open the Event meta data associated with the provider. // EventMetaEnum = EvtOpenEventMetadataEnum(ProviderMetadata, 0); if (EventMetaEnum == NULL) { Status = GetLastError(); EvtClose(ProviderMetadata); return Status; } Description = NULL; BufferLength = 0; BufferLengthNeeded = 0; while ((EventMeta = EvtNextEventMetadata(EventMetaEnum, 0)) != NULL) { // // Get the event & message IDs. // if ((EvtGetEventMetadataProperty(EventMeta, EventMetadataEventMessageID, 0, sizeof(EVT_VARIANT), &EventMessageId, &BufferUsed) == FALSE) || (EvtGetEventMetadataProperty(EventMeta, EventMetadataEventID, 0, sizeof(EVT_VARIANT), &EventId, &BufferUsed) == FALSE)) { EvtClose(EventMeta); continue; } // // Get the description, reallocating the buffer if needed. // do { if (BufferLengthNeeded > BufferLength) { free(Description); BufferLength = BufferLengthNeeded; Description = (PWSTR)malloc(BufferLength * sizeof(WCHAR)); if (Description == NULL) { Status = ERROR_OUTOFMEMORY; BufferLength = 0; break; } } if (EvtFormatMessage(ProviderMetadata, NULL, EventMessageId.UInt32Val, 0, NULL, EvtFormatMessageId, BufferLength, Description, &BufferLengthNeeded) != FALSE) { Status = ERROR_SUCCESS; } else { Status = GetLastError(); } } while (Status == ERROR_INSUFFICIENT_BUFFER); // // Display either the event message or an error message. // switch (Status) { case ERROR_SUCCESS: case ERROR_EVT_UNRESOLVED_VALUE_INSERT: case ERROR_EVT_UNRESOLVED_PARAMETER_INSERT: case ERROR_EVT_MAX_INSERTS_REACHED: wprintf(L"Event %u raw description is: %s\n", EventId.UInt32Val, Description); break; default: wprintf(L"Get raw event description failed with error code %u\n", Status); } // // Close this event's metadata and go to the next one. // EvtClose(EventMeta); } Status = GetLastError(); if (Status == ERROR_NO_MORE_ITEMS) { Status = ERROR_SUCCESS; } free(Description); EvtClose(EventMetaEnum); EvtClose(ProviderMetadata); return Status; }
/* Update the log position of a bookmark */ int update_bookmark(EVT_HANDLE evt, os_channel *channel) { DWORD size = 0; DWORD count = 0; wchar_t *buffer = NULL; int result = 0; int status = 0; int clean_tmp = 0; EVT_HANDLE bookmark = NULL; FILE *fp = NULL; char tmp_file[OS_MAXSTR]; /* Create temporary bookmark file name */ snprintf(tmp_file, sizeof(tmp_file), "%s/%s-XXXXXX", TMP_DIR, channel->bookmark_name); if ((bookmark = EvtCreateBookmark(NULL)) == NULL) { log2file( "%s: ERROR: Could not EvtCreateBookmark() bookmark (%s) for (%s) which returned (%lu)", ARGV0, channel->bookmark_filename, channel->evt_log, GetLastError()); goto cleanup; } if (!EvtUpdateBookmark(bookmark, evt)) { log2file( "%s: ERROR: Could not EvtUpdateBookmark() bookmark (%s) for (%s) which returned (%lu)", ARGV0, channel->bookmark_filename, channel->evt_log, GetLastError()); goto cleanup; } /* Make initial call to determine buffer size */ result = EvtRender(NULL, bookmark, EvtRenderBookmark, 0, NULL, &size, &count); if (result != FALSE || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { log2file( "%s: ERROR: Could not EvtRender() to get buffer size to update bookmark (%s) for (%s) which returned (%lu)", ARGV0, channel->bookmark_filename, channel->evt_log, GetLastError()); goto cleanup; } if ((buffer = calloc(size, sizeof(char))) == NULL) { log2file( "%s: ERROR: Could not calloc() memory to save bookmark (%s) for (%s) which returned [(%d)-(%s)]", ARGV0, channel->bookmark_filename, channel->evt_log, errno, strerror(errno)); goto cleanup; } if (!EvtRender(NULL, bookmark, EvtRenderBookmark, size, buffer, &size, &count)) { log2file( "%s: ERROR: Could not EvtRender() bookmark (%s) for (%s) which returned (%lu)", ARGV0, channel->bookmark_filename, channel->evt_log, GetLastError()); goto cleanup; } if (mkstemp_ex(tmp_file)) { log2file( "%s: ERROR: Could not mkstemp_ex() temporary bookmark (%s) for (%s)", ARGV0, tmp_file, channel->evt_log); goto cleanup; } if ((fp = fopen(tmp_file, "w")) == NULL) { log2file( "%s: ERROR: Could not fopen() temporary bookmark (%s) for (%s) which returned [(%d)-(%s)]", ARGV0, tmp_file, channel->evt_log, errno, strerror(errno)); goto cleanup; } /* Help to determine whether or not temporary file needs to be removed when * function cleans up after itself */ clean_tmp = 1; if ((fwrite(buffer, 1, size, fp)) < size) { log2file( "%s: ERROR: Could not fwrite() to temporary bookmark (%s) for (%s) which returned [(%d)-(%s)]", ARGV0, tmp_file, channel->evt_log, errno, strerror(errno)); goto cleanup; } fclose(fp); if (rename_ex(tmp_file, channel->bookmark_filename)) { log2file( "%s: ERROR: Could not rename_ex() temporary bookmark (%s) to (%s) for (%s)", ARGV0, tmp_file, channel->bookmark_filename, channel->evt_log); goto cleanup; } /* Success */ status = 1; cleanup: free(buffer); if (bookmark != NULL) { EvtClose(bookmark); } if (fp) { fclose(fp); } if (status == 0 && clean_tmp == 1 && unlink(tmp_file)) { log2file(DELETE_ERROR, ARGV0, tmp_file, errno, strerror(errno)); } return (status); }
void send_channel_event(EVT_HANDLE evt, os_channel *channel) { DWORD buffer_length = 0; PEVT_VARIANT properties_values = NULL; DWORD count = 0; EVT_HANDLE context = NULL; os_event event = {0}; char final_msg[OS_MAXSTR]; int result = 0; if ((context = EvtCreateRenderContext(count, NULL, EvtRenderContextSystem)) == NULL) { log2file( "%s: ERROR: Could not EvtCreateRenderContext() for (%s) which returned (%lu)", ARGV0, channel->evt_log, GetLastError()); goto cleanup; } /* Make initial call to determine buffer size necessary */ result = EvtRender(context, evt, EvtRenderEventValues, 0, NULL, &buffer_length, &count); if (result != FALSE || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { log2file( "%s: ERROR: Could not EvtRender() to determine buffer size for (%s) which returned (%lu)", ARGV0, channel->evt_log, GetLastError()); goto cleanup; } if ((properties_values = malloc(buffer_length)) == NULL) { log2file( "%s: ERROR: Could not malloc() memory to process event (%s) which returned [(%d)-(%s)]", ARGV0, channel->evt_log, errno, strerror(errno)); goto cleanup; } if (!EvtRender(context, evt, EvtRenderEventValues, buffer_length, properties_values, &buffer_length, &count)) { log2file( "%s: ERROR: Could not EvtRender() for (%s) which returned (%lu)", ARGV0, channel->evt_log, GetLastError()); goto cleanup; } event.name = get_property_value(&properties_values[EvtSystemChannel]); event.id = properties_values[EvtSystemEventID].UInt16Val; event.source = get_property_value(&properties_values[EvtSystemProviderName]); event.uid = properties_values[EvtSystemUserID].Type == EvtVarTypeNull ? NULL : properties_values[EvtSystemUserID].SidVal; event.computer = get_property_value(&properties_values[EvtSystemComputer]); event.time_created = properties_values[EvtSystemTimeCreated].FileTimeVal; event.keywords = properties_values[EvtSystemKeywords].Type == EvtVarTypeNull ? 0 : properties_values[EvtSystemKeywords].UInt64Val; event.level = properties_values[EvtSystemLevel].Type == EvtVarTypeNull ? -1 : properties_values[EvtSystemLevel].ByteVal; switch (event.level) { case WINEVENT_CRITICAL: event.category = "CRITICAL"; break; case WINEVENT_ERROR: event.category = "ERROR"; break; case WINEVENT_WARNING: event.category = "WARNING"; break; case WINEVENT_INFORMATION: event.category = "INFORMATION"; break; case WINEVENT_VERBOSE: event.category = "DEBUG"; break; case WINEVENT_AUDIT: if (event.keywords & WINEVENT_AUDIT_FAILURE) { event.category = "AUDIT_FAILURE"; break; } else if (event.keywords & WINEVENT_AUDIT_SUCCESS) { event.category = "AUDIT_SUCCESS"; break; } default: event.category = "Unknown"; break; } if ((event.timestamp = WinEvtTimeToString(event.time_created)) == NULL) { log2file( "%s: ERROR: Could not convert timestamp for (%s)", ARGV0, channel->evt_log); goto cleanup; } /* Determine user and domain */ get_username_and_domain(&event); /* Get event log message */ if ((event.message = get_message(evt, properties_values[EvtSystemProviderName].StringVal, EvtFormatMessageEvent)) == NULL) { log2file( "%s: ERROR: Could not get message for (%s)", ARGV0, channel->evt_log); } else { /* Format message */ win_format_event_string(event.message); } snprintf( final_msg, sizeof(final_msg), "%s WinEvtLog: %s: %s(%d): %s: %s: %s: %s: %s", event.timestamp, event.name, event.category, event.id, event.source && strlen(event.source) ? event.source : "no source", event.user && strlen(event.user) ? event.user : "******", event.domain && strlen(event.domain) ? event.domain : "no domain", event.computer && strlen(event.computer) ? event.computer : "no computer", event.message && strlen(event.message) ? event.message : "(no message)" ); if (SendMSG(logr_queue, final_msg, "WinEvtLog", LOCALFILE_MQ) < 0) { merror(QUEUE_SEND, ARGV0); } if (channel->bookmark_enabled) { update_bookmark(evt, channel); } cleanup: free(properties_values); free_event(&event); if (context != NULL) { EvtClose(context); } return; }
ULONG EnumerateChannels ( VOID ) /*++ Routine Description: This function enumerates all the EventLog channels and prints their names to the standard output. Arguments: None. Return Value: Win32 error code indicating if enumeration was successful. --*/ { PWSTR Buffer; ULONG BufferLength; ULONG BufferLengthNeeded; EVT_HANDLE ChannelEnum; ULONG Status; // // Create the channel enumeration handle. // ChannelEnum = EvtOpenChannelEnum(NULL, 0); if (ChannelEnum == NULL) { return GetLastError(); } Buffer = NULL; BufferLength = 0; BufferLengthNeeded = 0; do { // // Expand the buffer size if needed. // if (BufferLengthNeeded > BufferLength) { free(Buffer); BufferLength = BufferLengthNeeded; Buffer = malloc(BufferLength * sizeof(WCHAR)); if (Buffer == NULL) { Status = ERROR_OUTOFMEMORY; break; } } // // Try to get the next channel name. // if (EvtNextChannelPath(ChannelEnum, BufferLength, Buffer, &BufferLengthNeeded) == FALSE) { Status = GetLastError(); } else { Status = ERROR_SUCCESS; wprintf(L"%s\n", Buffer); } } while ((Status == ERROR_SUCCESS) || (Status == ERROR_INSUFFICIENT_BUFFER)); // // Free all resources associated with channel enumeration. // free(Buffer); EvtClose(ChannelEnum); // // When EvtNextChannelPath returns ERROR_NO_MORE_ITEMS, we have actually // iterated through all the channels and thus succeeded. // if (Status == ERROR_NO_MORE_ITEMS) { Status = ERROR_SUCCESS; } return Status; }
char *get_message(EVT_HANDLE evt, LPCWSTR provider_name, DWORD flags) { char *message = NULL; EVT_HANDLE publisher = NULL; DWORD size = 0; wchar_t *buffer = NULL; int result = 0; publisher = EvtOpenPublisherMetadata(NULL, provider_name, NULL, 0, 0); if (publisher == NULL) { log2file( "%s: ERROR: Could not EvtOpenPublisherMetadata() with flags (%lu) which returned (%lu)", ARGV0, flags, GetLastError()); goto cleanup; } /* Make initial call to determine buffer size */ result = EvtFormatMessage(publisher, evt, 0, 0, NULL, flags, 0, NULL, &size); if (result != FALSE || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { log2file( "%s: ERROR: Could not EvtFormatMessage() to determine buffer size with flags (%lu) which returned (%lu)", ARGV0, flags, GetLastError()); goto cleanup; } if ((buffer = calloc(size, sizeof(wchar_t))) == NULL) { log2file( "%s: ERROR: Could not calloc() memory which returned [(%d)-(%s)]", ARGV0, errno, strerror(errno)); goto cleanup; } result = EvtFormatMessage(publisher, evt, 0, 0, NULL, flags, size, buffer, &size); if (result == FALSE) { log2file( "%s: ERROR: Could not EvtFormatMessage() with flags (%lu) which returned (%lu)", ARGV0, flags, GetLastError()); goto cleanup; } message = convert_windows_string(buffer); cleanup: free(buffer); if (publisher != NULL) { EvtClose(publisher); } return (message); }
/* Process a given event */ DWORD ProcessEvent(EVT_HANDLE hEvent) { EVT_HANDLE hProviderMetadata = NULL; PEVT_VARIANT eventInfo = NULL; LPWSTR pwsMessage = NULL; LPWSTR pwszPublisherName = NULL; ULONGLONG eventTime; ULONGLONG keyword; DWORD status = ERROR_SUCCESS; int event_id = 0; int winlevel = 0; int level = 0; WCHAR source[SOURCE_SZ]; WCHAR hostname[HOSTNAME_SZ]; WCHAR * formatted_string = NULL; WCHAR * tstamp = NULL; WCHAR * index = NULL; WCHAR defmsg[ERRMSG_SZ]; WCHAR tstamped_message[SYSLOG_DEF_SZ]; /* Get and store the publishers new Windows Events name */ eventInfo = GetEventInfo(hEvent); if (eventInfo) { pwszPublisherName = (LPWSTR)eventInfo[0].StringVal; } else { return ERR_CONTINUE; } eventTime = eventInfo[1].FileTimeVal; event_id = eventInfo[2].UInt16Val; /* Check for the "Microsoft-Windows-" prefix in the publisher name */ /* and remove it if found. Saves 18 characters in the message */ if(wcsncmp(pwszPublisherName, L"Microsoft-Windows-", 18) == 0) wcsncpy_s(source, COUNT_OF(source), pwszPublisherName+18, _TRUNCATE); else wcsncpy_s(source, COUNT_OF(source), pwszPublisherName, _TRUNCATE); /* Format Event Timestamp */ if ((tstamp = WinEventTimeToString(eventTime)) == NULL) tstamp = L"TIME_ERROR"; /* Add hostname for RFC compliance (RFC 3164) */ if (ProgramUseIPAddress == TRUE) { _snwprintf_s(hostname, HOSTNAME_SZ, _TRUNCATE, L"%S", ProgramHostName); } else { if (ExpandEnvironmentStringsW(L"%COMPUTERNAME%", hostname, COUNT_OF(hostname)) == 0) { wcscpy_s(hostname, COUNT_OF(hostname), L"HOSTNAME_ERR"); Log(LOG_ERROR|LOG_SYS, "Cannot expand %COMPUTERNAME%"); } } /* replace every space in source by underscores */ index = source; while( *index ) { if( *index == L' ' ) { *index = L'_'; } index++; } /* Add Timestamp and hostname then format source & event ID for consistency with Event Viewer */ if(SyslogIncludeTag) { _snwprintf_s(tstamped_message, COUNT_OF(tstamped_message), _TRUNCATE, L"%s %s %S: %s: %i: ", tstamp, hostname, SyslogTag, source, event_id ); } else { _snwprintf_s(tstamped_message, COUNT_OF(tstamped_message), _TRUNCATE, L"%s %s %s: %i: ", tstamp, hostname, source, event_id ); } /* Get the handle to the provider's metadata that contains the message strings. */ hProviderMetadata = EvtOpenPublisherMetadata(NULL, pwszPublisherName, NULL, 0, 0); if (NULL == hProviderMetadata) { if (LogInteractive) Log(LOG_ERROR|LOG_SYS, "OpenPublisherMetadata failed for Publisher: \"%S\"", source); return ERR_CONTINUE; } /* Get the message string from the event */ pwsMessage = GetMessageString(hProviderMetadata, hEvent); if (pwsMessage == NULL) { Log(LOG_ERROR|LOG_SYS, "Error getting message string for event DETAILS: Publisher: %S EventID: %i", source, event_id); return ERR_CONTINUE; } /* Get string and strip whitespace */ formatted_string = CollapseExpandMessageW(pwsMessage); /* Create a default message if resources or formatting didn't work */ if (formatted_string == NULL) { if(SyslogIncludeTag) { _snwprintf_s(defmsg, COUNT_OF(defmsg), _TRUNCATE, L"%S: (Facility: %u, Status: %s)", SyslogTag, HRESULT_FACILITY(event_id), FAILED(event_id) ? L"Failure" : L"Success" ); } else { _snwprintf_s(defmsg, COUNT_OF(defmsg), _TRUNCATE, L"(Facility: %u, Status: %s)", HRESULT_FACILITY(event_id), FAILED(event_id) ? L"Failure" : L"Success" ); } formatted_string = defmsg; } /* Get Event Error Level. In the case of Security Events, * set Failures to Error instead of notice using the * keyword attribute */ keyword = (EvtVarTypeNull == eventInfo[4].Type) ? 0 : eventInfo[4].UInt64Val; if ((keyword & WINEVENT_KEYWORD_AUDIT_FAILURE) != 0) { // Add AUDIT_FAILURE message for better parsing wcsncat_s(tstamped_message, COUNT_OF(tstamped_message), L"AUDIT_FAILURE ", _TRUNCATE); winlevel = WINEVENT_ERROR_LEVEL; } else winlevel = (int)eventInfo[3].ByteVal; /* Select syslog level */ switch (winlevel) { case WINEVENT_CRITICAL_LEVEL: level = SYSLOG_BUILD(SyslogFacility, SYSLOG_CRIT); break; case WINEVENT_ERROR_LEVEL: level = SYSLOG_BUILD(SyslogFacility, SYSLOG_ERR); break; case WINEVENT_WARNING_LEVEL: level = SYSLOG_BUILD(SyslogFacility, SYSLOG_WARNING); break; case WINEVENT_INFORMATION_LEVEL: level = SYSLOG_BUILD(SyslogFacility, SYSLOG_NOTICE); break; case WINEVENT_AUDIT_LEVEL: wcsncat_s(tstamped_message, COUNT_OF(tstamped_message), L"AUDIT_SUCCESS ", _TRUNCATE); level = SYSLOG_BUILD(SyslogFacility, SYSLOG_NOTICE); break; case WINEVENT_VERBOSE_LEVEL: level = SYSLOG_BUILD(SyslogFacility, SYSLOG_DEBUG); break; /* Everything else */ default: level = SYSLOG_BUILD(SyslogFacility, SYSLOG_NOTICE); break; } /* Combine the message strings */ wcsncat_s(tstamped_message, COUNT_OF(tstamped_message), formatted_string, _TRUNCATE); /* Send the event to the Syslog Server */ /* Making sure it is severe enough to be logged */ if (SyslogLogLevel == 0 || (SyslogLogLevel >= (DWORD)winlevel && winlevel > 0)) if (SyslogSendW(tstamped_message, level)) status = ERR_FAIL; /* Cleanup memory and open handles */ if(pwsMessage) free(pwsMessage); if(eventInfo) free(eventInfo); if (hProviderMetadata) EvtClose(hProviderMetadata); if (hEvent) EvtClose(hEvent); return status; }
EVT_HANDLE CperOpenWheaLogQuery ( __in_opt PWSTR ComputerName, __in_opt PWSTR UserName, __in_opt PWSTR Domain, __in_opt PWSTR Password, __in_opt PWSTR FileName, __out EVT_HANDLE *Session ) /*++ Routine Description: This routine will initialize an event log query that may be used to enumerate any WHEA error records contained in the WHEA event log. Arguments: ComputerName - Supplies an optional computer name for remote queries. This should be NULL for the local event log query or if an exported event log is to be queried. UserName - Supplies the username to be used to authenticate to the remote computer. Domain - Supplies the username to be used to authenticate to the remote computer. Password - Supplies the password to be used to authenticate to the remote computer. FileName - Supplies an optional filename for an exported event log. This should be NULL for a live (local or remote) event log query. Session - Supplies a variable in which a handle to the session is returned, but only if the query is for events on a remote computer. Return Value: A handle to the ETW query if successful, NULL otherwise. --*/ { DWORD Error; DWORD Flags; EVT_RPC_LOGIN Login; PCWSTR Path; EVT_HANDLE QueryHandle; EVT_HANDLE SessionHandle; QueryHandle = NULL; SessionHandle = NULL; Error = ERROR_SUCCESS; // // If a computer name is specified, then an event log session to that // computer must be opened. It is invalid to specify a remote computer as // well as a filename. // if (ComputerName != NULL) { if (FileName != NULL) { Error = ERROR_INVALID_PARAMETER; goto OpenWheaLogQueryEnd; } RtlZeroMemory(&Login, sizeof(EVT_RPC_LOGIN)); Login.Server = ComputerName; Login.User = UserName; Login.Domain = Domain; Login.Password = Password; Login.Flags = EvtRpcLoginAuthDefault; SessionHandle = EvtOpenSession(EvtRpcLogin, &Login, 0, 0); if (SessionHandle == NULL) { Error = GetLastError(); goto OpenWheaLogQueryEnd; } } if (FileName == NULL) { Path = WHEA_CHANNEL; Flags = EvtQueryChannelPath | EvtQueryForwardDirection; } else { Path = (PCWSTR)FileName; Flags = EvtQueryFilePath | EvtQueryForwardDirection; } // // Open the query. If this is not a file query and the open fails, try the // legacy log name. // QueryHandle = EvtQuery(SessionHandle, Path, WHEA_LOG_QUERY, Flags); if (QueryHandle == NULL) { Error = GetLastError(); if (FileName == NULL) { Path = WHEA_CHANNEL_LEGACY; QueryHandle = EvtQuery(SessionHandle, Path, WHEA_LOG_QUERY, Flags); if (QueryHandle == NULL) { Error = GetLastError(); goto OpenWheaLogQueryEnd; } } } *Session = SessionHandle; OpenWheaLogQueryEnd: if (QueryHandle == NULL) { if (SessionHandle != NULL) { EvtClose(SessionHandle); } SetLastError(Error); } return QueryHandle; }
/** * @brief Enumerate all the events in the result set. * @param eventHandle A handle to an event. * * @return returns Print event status. */ DWORD EventLogReader::PrintEvent(EVT_HANDLE eventHandle) { EVT_HANDLE context = nullptr; PEVT_VARIANT renderedValues = nullptr; DWORD status = ERROR_SUCCESS; do { // Identify the components of the event that you want to render. In this case, // render the system section of the event. context = EvtCreateRenderContext(0, nullptr, EvtRenderContextSystem); if (context == nullptr) { status = GetLastError(); break; } // When you render the user data or system section of the event, you must specify // the EvtRenderEventValues flag. The function returns an array of variant values // for each element in the user data or system section of the event. For user data // or event data, the values are returned in the same order as the elements are // defined in the event. For system data, the values are returned in the order defined // in the EVT_SYSTEM_PROPERTY_ID enumeration. DWORD bufferSize = 0; DWORD bufferUsed = 0; DWORD propertyCount = 0; if (!EvtRender(context, eventHandle, EvtRenderEventValues, bufferSize, renderedValues, &bufferUsed, &propertyCount)) { status = GetLastError(); if (status == ERROR_INSUFFICIENT_BUFFER) { bufferSize = bufferUsed; renderedValues = (PEVT_VARIANT)malloc(bufferSize); if (renderedValues != nullptr) { EvtRender(context, eventHandle, EvtRenderEventValues, bufferSize, renderedValues, &bufferUsed, &propertyCount); status = GetLastError(); } else { status = ERROR_OUTOFMEMORY; break; } } if (status != ERROR_SUCCESS) break; } std::map<std::string, std::string> eventData; std::wstring tempBuf = (renderedValues[EvtSystemProviderName].StringVal) ? renderedValues[EvtSystemProviderName].StringVal : L""; eventData["providername"] = base::wstring_to_string(tempBuf); if (renderedValues[EvtSystemProviderGuid].GuidVal != nullptr) { WCHAR guid[50] = {0}; StringFromGUID2(*(renderedValues[EvtSystemProviderGuid].GuidVal), guid, sizeof(guid) / sizeof(WCHAR)); eventData["providerguid"] = base::wstring_to_string(guid); } DWORD eventId = renderedValues[EvtSystemEventID].UInt16Val; if (renderedValues[EvtSystemQualifiers].Type == EvtVarTypeNull) eventId = MAKELONG(renderedValues[EvtSystemEventID].UInt16Val, renderedValues[EvtSystemQualifiers].UInt16Val); char buf[1024] = { 0 }; snprintf(buf, sizeof(buf), "%lu", eventId); eventData["eventid"] = buf; snprintf(buf, sizeof(buf), "%u", (renderedValues[EvtSystemVersion].Type == EvtVarTypeNull) ? 0 : renderedValues[EvtSystemVersion].ByteVal); eventData["version"] = buf; snprintf(buf, sizeof(buf), "%u", (renderedValues[EvtSystemLevel].Type == EvtVarTypeNull) ? 0 : renderedValues[EvtSystemLevel].ByteVal); eventData["level"] = buf; snprintf(buf, sizeof(buf), "%hu", (renderedValues[EvtSystemTask].Type == EvtVarTypeNull) ? 0 : renderedValues[EvtSystemTask].ByteVal); eventData["task"] = buf; snprintf(buf, sizeof(buf), "%u", (renderedValues[EvtSystemOpcode].Type == EvtVarTypeNull) ? 0 : renderedValues[EvtSystemOpcode].UInt16Val); eventData["opcode"] = buf; snprintf(buf, sizeof(buf), "%0x%I64x", (renderedValues[EvtSystemKeywords].Type == EvtVarTypeNull) ? 0 : renderedValues[EvtSystemOpcode].UInt64Val); eventData["keywords"] = buf; ULONGLONG ullTimeStamp = renderedValues[EvtSystemTimeCreated].FileTimeVal; FILETIME ft; ft.dwHighDateTime = (DWORD)((ullTimeStamp >> 32) & 0xFFFFFFFF); ft.dwLowDateTime = (DWORD)(ullTimeStamp & 0xFFFFFFFF); SYSTEMTIME st; FileTimeToSystemTime(&ft, &st); ULONGLONG ullNanoseconds = (ullTimeStamp % 10000000) * 100; // Display nanoseconds instead of milliseconds for higher resolution snprintf(buf, sizeof(buf), "%02d/%02d/%02d %02d:%02d:%02d.%I64u", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond, ullNanoseconds); eventData["timecreated"] = buf; snprintf(buf, sizeof(buf), "%I64u", renderedValues[EvtSystemEventRecordId].UInt64Val); eventData["eventrecordid"] = buf; if (renderedValues[EvtSystemActivityID].Type != EvtVarTypeNull) { WCHAR guid[50] = { 0 }; StringFromGUID2(*(renderedValues[EvtSystemActivityID].GuidVal), guid, sizeof(guid) / sizeof(WCHAR));; eventData["activityid"] = base::wstring_to_string(guid); } if (renderedValues[EvtSystemRelatedActivityID].Type != EvtVarTypeNull) { WCHAR guid[50] = { 0 }; StringFromGUID2(*(renderedValues[EvtSystemRelatedActivityID].GuidVal), guid, sizeof(guid) / sizeof(WCHAR));; eventData["relatedactivityid"] = base::wstring_to_string(guid); } snprintf(buf, sizeof(buf), "%lu", renderedValues[EvtSystemProcessID].UInt32Val); eventData["processid"] = buf; snprintf(buf, sizeof(buf), "%lu", renderedValues[EvtSystemThreadID].UInt32Val); eventData["threadid"] = buf; tempBuf = (renderedValues[EvtSystemChannel].Type == EvtVarTypeNull) ? renderedValues[EvtSystemChannel].StringVal : L""; eventData["channel"] = base::wstring_to_string(tempBuf); eventData["computer"] = base::wstring_to_string(renderedValues[EvtSystemComputer].StringVal); if (renderedValues[EvtSystemUserID].Type != EvtVarTypeNull) { LPWSTR pwsSid = nullptr; if (ConvertSidToStringSid(renderedValues[EvtSystemUserID].SidVal, &pwsSid)) { eventData["secuserid"] = base::wstring_to_string(pwsSid); LocalFree(pwsSid); } } // Get the handle to the provider's metadata that contains the message strings. EVT_HANDLE providerMetadata = EvtOpenPublisherMetadata(nullptr, renderedValues[EvtSystemProviderName].StringVal, nullptr, 0, 0); if (providerMetadata == nullptr) break; eventData["message"] = GetMessageString(providerMetadata, eventHandle); _printResultsCallback(eventData); } while (false); if (context) EvtClose(context); if (renderedValues) free(renderedValues); return status; }
/* obtain a particular message from a desired eventlog */ static int zbx_get_eventlog_message6(const wchar_t *wsource, zbx_uint64_t *which, unsigned short *out_severity, unsigned long *out_timestamp, char **out_provider, char **out_source, char **out_message, unsigned long *out_eventid, EVT_HANDLE *render_context, EVT_HANDLE *query, zbx_uint64_t *keywords) { const char *__function_name = "zbx_get_eventlog_message6"; EVT_HANDLE event_bookmark = NULL; EVT_VARIANT* renderedContent = NULL; const wchar_t *pprovider = NULL; char *tmp_str = NULL; DWORD size = DEFAULT_EVENT_CONTENT_SIZE; DWORD bookmarkedCount = 0; DWORD require = 0; const zbx_uint64_t sec_1970 = 116444736000000000; const zbx_uint64_t success_audit = 0x20000000000000; const zbx_uint64_t failure_audit = 0x10000000000000; int ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s() EventRecordID:" ZBX_FS_UI64, __function_name, *which); if (NULL == *query) { zabbix_log(LOG_LEVEL_DEBUG, "%s() no EvtQuery handle", __function_name); goto out; } /* get the entries */ if (TRUE != EvtNext(*query, 1, &event_bookmark, INFINITE, 0, &require)) { /* The event reading query had less items than we calculated before. */ /* Either the eventlog was cleaned or our calculations were wrong. */ /* Either way we can safely abort the query by setting NULL value */ /* and returning success, which is interpreted as empty eventlog. */ if (ERROR_NO_MORE_ITEMS == GetLastError()) { ret = SUCCEED; } else { zabbix_log(LOG_LEVEL_WARNING, "EvtNext failed: %s, EventRecordID:" ZBX_FS_UI64, strerror_from_system(GetLastError()), *which); } goto out; } /* obtain the information from the selected events */ renderedContent = (EVT_VARIANT *)zbx_malloc((void *)renderedContent, size); if (TRUE != EvtRender(*render_context, event_bookmark, EvtRenderEventValues, size, renderedContent, &require, &bookmarkedCount)) { /* information exceeds the space allocated */ if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { zabbix_log(LOG_LEVEL_WARNING, "EvtRender failed: %s", strerror_from_system(GetLastError())); goto out; } renderedContent = (EVT_VARIANT *)zbx_realloc((void *)renderedContent, require); size = require; if (TRUE != EvtRender(*render_context, event_bookmark, EvtRenderEventValues, size, renderedContent, &require, &bookmarkedCount)) { zabbix_log(LOG_LEVEL_WARNING, "EvtRender failed: %s", strerror_from_system(GetLastError())); goto out; } } pprovider = VAR_PROVIDER_NAME(renderedContent); *out_provider = zbx_unicode_to_utf8(pprovider); if (NULL != VAR_SOURCE_NAME(renderedContent)) { *out_source = zbx_unicode_to_utf8(VAR_SOURCE_NAME(renderedContent)); } *keywords = VAR_KEYWORDS(renderedContent) & (success_audit | failure_audit); *out_severity = VAR_LEVEL(renderedContent); *out_timestamp = (unsigned long)((VAR_TIME_CREATED(renderedContent) - sec_1970) / 10000000); *out_eventid = VAR_EVENT_ID(renderedContent); *out_message = expand_message6(pprovider, event_bookmark); tmp_str = zbx_unicode_to_utf8(wsource); if (VAR_RECORD_NUMBER(renderedContent) != *which) { zabbix_log(LOG_LEVEL_DEBUG, "%s() Overwriting expected EventRecordID:" ZBX_FS_UI64 " with the real" " EventRecordID:" ZBX_FS_UI64 " in eventlog '%s'", __function_name, *which, VAR_RECORD_NUMBER(renderedContent), tmp_str); *which = VAR_RECORD_NUMBER(renderedContent); } /* some events don't have enough information for making event message */ if (NULL == *out_message) { *out_message = zbx_strdcatf(*out_message, "The description for Event ID:%lu in Source:'%s'" " cannot be found. Either the component that raises this event is not installed" " on your local computer or the installation is corrupted. You can install or repair" " the component on the local computer. If the event originated on another computer," " the display information had to be saved with the event.", *out_eventid, NULL == *out_provider ? "" : *out_provider); if (EvtVarTypeString == (VAR_EVENT_DATA_TYPE(renderedContent) & EVT_VARIANT_TYPE_MASK)) { unsigned int i; char *data = NULL; if (0 != (VAR_EVENT_DATA_TYPE(renderedContent) & EVT_VARIANT_TYPE_ARRAY) && 0 < VAR_EVENT_DATA_COUNT(renderedContent)) { *out_message = zbx_strdcatf(*out_message, " The following information was included" " with the event: "); for (i = 0; i < VAR_EVENT_DATA_COUNT(renderedContent); i++) { if (NULL != VAR_EVENT_DATA_STRING_ARRAY(renderedContent, i)) { if (0 < i) *out_message = zbx_strdcat(*out_message, "; "); data = zbx_unicode_to_utf8(VAR_EVENT_DATA_STRING_ARRAY(renderedContent, i)); *out_message = zbx_strdcatf(*out_message, "%s", data); zbx_free(data); } } } else if (NULL != VAR_EVENT_DATA_STRING(renderedContent)) { data = zbx_unicode_to_utf8(VAR_EVENT_DATA_STRING(renderedContent)); *out_message = zbx_strdcatf(*out_message, "The following information was included" " with the event: %s", data); zbx_free(data); } } } ret = SUCCEED; out: if (NULL != event_bookmark) EvtClose(event_bookmark); zbx_free(tmp_str); zbx_free(renderedContent); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/* open eventlog using API 6 and return the number of records */ static int zbx_open_eventlog6(const wchar_t *wsource, zbx_uint64_t *lastlogsize, EVT_HANDLE *render_context, zbx_uint64_t *FirstID, zbx_uint64_t *LastID) { const char *__function_name = "zbx_open_eventlog6"; EVT_HANDLE log = NULL; EVT_VARIANT var; EVT_HANDLE tmp_all_event_query = NULL; EVT_HANDLE event_bookmark = NULL; EVT_VARIANT* renderedContent = NULL; DWORD status = 0; DWORD size_required = 0; DWORD size = DEFAULT_EVENT_CONTENT_SIZE; DWORD bookmarkedCount = 0; zbx_uint64_t numIDs = 0; char *tmp_str = NULL; int ret = FAIL; *FirstID = 0; *LastID = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); /* try to open the desired log */ if (NULL == (log = EvtOpenLog(NULL, wsource, EvtOpenChannelPath))) { tmp_str = zbx_unicode_to_utf8(wsource); zabbix_log(LOG_LEVEL_WARNING, "cannot open eventlog '%s':%s", tmp_str, strerror_from_system(GetLastError())); goto out; } /* obtain the number of records in the log */ if (TRUE != EvtGetLogInfo(log, EvtLogNumberOfLogRecords, sizeof(var), &var, &size_required)) { zabbix_log(LOG_LEVEL_WARNING, "EvtGetLogInfo failed:%s", strerror_from_system(GetLastError())); goto out; } numIDs = var.UInt64Val; /* get the number of the oldest record in the log */ /* "EvtGetLogInfo()" does not work properly with "EvtLogOldestRecordNumber" */ /* we have to get it from the first EventRecordID */ /* create the system render */ if (NULL == (*render_context = EvtCreateRenderContext(RENDER_ITEMS_COUNT, RENDER_ITEMS, EvtRenderContextValues))) { zabbix_log(LOG_LEVEL_WARNING, "EvtCreateRenderContext failed:%s", strerror_from_system(GetLastError())); goto out; } /* get all eventlog */ tmp_all_event_query = EvtQuery(NULL, wsource, NULL, EvtQueryChannelPath); if (NULL == tmp_all_event_query) { if (ERROR_EVT_CHANNEL_NOT_FOUND == (status = GetLastError())) zabbix_log(LOG_LEVEL_WARNING, "EvtQuery channel missed:%s", strerror_from_system(status)); else zabbix_log(LOG_LEVEL_WARNING, "EvtQuery failed:%s", strerror_from_system(status)); goto out; } /* get the entries and allocate the required space */ renderedContent = zbx_malloc(renderedContent, size); if (TRUE != EvtNext(tmp_all_event_query, 1, &event_bookmark, INFINITE, 0, &size_required)) { /* no data in eventlog */ zabbix_log(LOG_LEVEL_DEBUG, "first EvtNext failed:%s", strerror_from_system(GetLastError())); *FirstID = 1; *LastID = 1; numIDs = 0; *lastlogsize = 0; ret = SUCCEED; goto out; } /* obtain the information from selected events */ if (TRUE != EvtRender(*render_context, event_bookmark, EvtRenderEventValues, size, renderedContent, &size_required, &bookmarkedCount)) { /* information exceeds the allocated space */ if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { zabbix_log(LOG_LEVEL_WARNING, "EvtRender failed:%s", strerror_from_system(GetLastError())); goto out; } renderedContent = (EVT_VARIANT*)zbx_realloc((void *)renderedContent, size_required); size = size_required; if (TRUE != EvtRender(*render_context, event_bookmark, EvtRenderEventValues, size, renderedContent, &size_required, &bookmarkedCount)) { zabbix_log(LOG_LEVEL_WARNING, "EvtRender failed:%s", strerror_from_system(GetLastError())); goto out; } } *FirstID = VAR_RECORD_NUMBER(renderedContent); *LastID = *FirstID + numIDs; if (*lastlogsize >= *LastID) { *lastlogsize = *FirstID - 1; zabbix_log(LOG_LEVEL_DEBUG, "lastlogsize is too big. It is set to:" ZBX_FS_UI64, *lastlogsize); } ret = SUCCEED; out: if (NULL != log) EvtClose(log); if (NULL != tmp_all_event_query) EvtClose(tmp_all_event_query); if (NULL != event_bookmark) EvtClose(event_bookmark); zbx_free(tmp_str); zbx_free(renderedContent); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s FirstID:" ZBX_FS_UI64 " LastID:" ZBX_FS_UI64 " numIDs:" ZBX_FS_UI64, __function_name, zbx_result_string(ret), *FirstID, *LastID, numIDs); return ret; }
/* Cancel the subscription */ void WinEventCancelSubscribes() { if (WinEventSub != NULL) EvtClose(WinEventSub); }
static int zbx_get_eventlog_message_xpath(LPCTSTR wsource, zbx_uint64_t *lastlogsize, char **out_source, char **out_message, unsigned short *out_severity, unsigned long *out_timestamp, unsigned long *out_eventid, unsigned char skip_old_data, void **pcontext) { const char *__function_name = "zbx_get_eventlog_message_xpath"; int ret = FAIL; LPSTR tmp_str = NULL; LPWSTR tmp_wstr = NULL; LPWSTR event_query = NULL; /* L"Event/System[EventRecordID=WHICH]" */ unsigned long status = ERROR_SUCCESS; PEVT_VARIANT eventlog_array = NULL; HANDLE providermetadata_handle = NULL; LPWSTR query_array[] = { L"/Event/System/Provider/@Name", L"/Event/System/EventID", L"/Event/System/Level", L"/Event/System/TimeCreated/@SystemTime", L"/Event/System/EventRecordID"}; DWORD array_count = 5; DWORD dwReturned = 0, dwValuesCount = 0, dwBufferSize = 0; const ULONGLONG sec_1970 = 116444736000000000; static HMODULE hmod_wevtapi = NULL; zbx_eventlog_context *context; assert(out_source); assert(out_message); assert(out_severity); assert(out_timestamp); assert(out_eventid); zabbix_log(LOG_LEVEL_DEBUG, "In %s() which:%lld", __function_name, *lastlogsize); *out_source = NULL; *out_message = NULL; *out_severity = 0; *out_timestamp = 0; *out_eventid = 0; /* We have to use LoadLibrary() to load wevtapi.dll to avoid it required even before Vista. */ /* load wevtapi.dll once */ if (NULL == hmod_wevtapi) { hmod_wevtapi = LoadLibrary(L"wevtapi.dll"); if (NULL == hmod_wevtapi) { zabbix_log(LOG_LEVEL_WARNING, "Can't load wevtapi.dll"); goto finish; } zabbix_log(LOG_LEVEL_DEBUG, "wevtapi.dll was loaded"); /* get function pointer from wevtapi.dll */ (FARPROC)EvtQuery = GetProcAddress(hmod_wevtapi, "EvtQuery"); (FARPROC)EvtCreateRenderContext = GetProcAddress(hmod_wevtapi, "EvtCreateRenderContext"); (FARPROC)EvtNext = GetProcAddress(hmod_wevtapi, "EvtNext"); (FARPROC)EvtRender = GetProcAddress(hmod_wevtapi, "EvtRender"); (FARPROC)EvtOpenPublisherMetadata = GetProcAddress(hmod_wevtapi, "EvtOpenPublisherMetadata"); (FARPROC)EvtFormatMessage = GetProcAddress(hmod_wevtapi, "EvtFormatMessage"); (FARPROC)EvtClose = GetProcAddress(hmod_wevtapi, "EvtClose"); if (NULL == EvtQuery || NULL == EvtCreateRenderContext || NULL == EvtNext || NULL == EvtRender || NULL == EvtOpenPublisherMetadata || NULL == EvtFormatMessage || NULL == EvtClose) { zabbix_log(LOG_LEVEL_WARNING, "Can't load wevtapi.dll functions"); goto finish; } zabbix_log(LOG_LEVEL_DEBUG, "wevtapi.dll functions were loaded"); } context = *pcontext; if (context == NULL) { context = zbx_malloc(NULL, sizeof(*context)); memset(context, 0, sizeof(*context)); tmp_str = zbx_dsprintf(NULL, "Event/System[EventRecordID>%lld]", *lastlogsize); event_query = zbx_utf8_to_unicode(tmp_str); zbx_free(tmp_str); context->handle = EvtQuery(NULL, wsource, event_query, skip_old_data? EvtQueryChannelPath|EvtQueryReverseDirection: EvtQueryChannelPath); if (NULL == context->handle) { status = GetLastError(); if (ERROR_EVT_CHANNEL_NOT_FOUND == status) { zabbix_log(LOG_LEVEL_WARNING, "Missed eventlog"); } else { zabbix_log(LOG_LEVEL_WARNING, "EvtQuery failed"); } goto finish; } context->context_handle = EvtCreateRenderContext(array_count, (LPCWSTR*)query_array, EvtRenderContextValues); if (NULL == context->context_handle) { zabbix_log(LOG_LEVEL_WARNING, "EvtCreateRenderContext failed"); goto finish; } *pcontext = context; } if (context->each_handle) { EvtClose(context->each_handle); context->each_handle = NULL; } if (!EvtNext(context->handle, 1, &context->each_handle, INFINITE, 0, &dwReturned)) { status = GetLastError(); if (ERROR_NO_MORE_ITEMS == status) { zabbix_log(LOG_LEVEL_DEBUG, "EvtNext no more items."); ret = SUCCEED; } else { zabbix_log(LOG_LEVEL_WARNING, "First EvtNext failed with %lu", status); } goto finish; } if (!EvtRender(context->context_handle, context->each_handle, EvtRenderEventValues, dwBufferSize, eventlog_array, &dwReturned, &dwValuesCount)) { if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError())) { dwBufferSize = dwReturned; if (NULL == (eventlog_array = (PEVT_VARIANT)zbx_malloc(eventlog_array, dwBufferSize))) { zabbix_log(LOG_LEVEL_WARNING, "EvtRender malloc failed"); goto finish; } if (!EvtRender(context->context_handle, context->each_handle, EvtRenderEventValues, dwBufferSize, eventlog_array, &dwReturned, &dwValuesCount)) { zabbix_log(LOG_LEVEL_WARNING, "EvtRender failed"); goto finish; } } if (ERROR_SUCCESS != (status = GetLastError())) { zabbix_log(LOG_LEVEL_WARNING, "EvtRender failed with %d", status); goto finish; } } *out_source = zbx_unicode_to_utf8(eventlog_array[0].StringVal); providermetadata_handle = EvtOpenPublisherMetadata(NULL, eventlog_array[0].StringVal, NULL, 0, 0); if (NULL != providermetadata_handle) { dwBufferSize = 0; dwReturned = 0; if (!EvtFormatMessage(providermetadata_handle, context->each_handle, 0, 0, NULL, EvtFormatMessageEvent, dwBufferSize, tmp_wstr, &dwReturned)) { if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError())) { dwBufferSize = dwReturned; if (NULL == (tmp_wstr = (LPWSTR)zbx_malloc(tmp_wstr, dwBufferSize * sizeof(WCHAR)))) { zabbix_log(LOG_LEVEL_WARNING, "EvtFormatMessage malloc failed"); goto finish; } if (!EvtFormatMessage(providermetadata_handle, context->each_handle, 0, 0, NULL, EvtFormatMessageEvent, dwBufferSize, tmp_wstr, &dwReturned)) { zabbix_log(LOG_LEVEL_WARNING, "EvtFormatMessage failed"); goto finish; } } if (ERROR_SUCCESS != (status = GetLastError())) { zabbix_log(LOG_LEVEL_WARNING, "EvtFormatMessage failed with %d", status); goto finish; } } *out_message= zbx_unicode_to_utf8(tmp_wstr); } else { zabbix_log(LOG_LEVEL_DEBUG, "EvtOpenPublisherMetadata failed with %d: no description availabel", GetLastError()); *out_message = zbx_strdup(NULL, ""); } *out_eventid = eventlog_array[1].UInt16Val; *out_severity = eventlog_array[2].ByteVal; *out_timestamp = (unsigned long)((eventlog_array[3].FileTimeVal - sec_1970) / 10000000); *lastlogsize = eventlog_array[4].UInt64Val; ret = SUCCEED; finish: zbx_free(tmp_str); zbx_free(tmp_wstr); zbx_free(event_query); zbx_free(eventlog_array); if (FAIL == ret) { zbx_free(*out_source); zbx_free(*out_message); } if (providermetadata_handle) EvtClose(providermetadata_handle); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/**** * ProcessResults * * DESC: * Creates a remote context * * ARGS: * hRemote - Remote session context * hResults - An open set of results * outputFormat - 0 for JSON, otherwise XML * mode - last record vs dump results * debug - set to 0 (none) 1 (basic) or 2 (verbose) */ DWORD64 ProcessResults(EVT_HANDLE hRemote, EVT_HANDLE hResults, int outputFormat, int mode, int debug) { DWORD64 status = ERROR_SUCCESS; EVT_HANDLE hEvents[CHUNK_SIZE + 1]; DWORD dwReturned = 0; BOOL completed = FALSE; BOOL firstRecordCompleted = FALSE; // Print header information for our events if( outputFormat == OUTPUT_FORMAT_JSON ) { // Note: Marc requested this to be removed //wprintf(L"["); } else { wprintf(L"%s||%s||%s||%s||%s||%s||%s||%s\n\n", L"RecordID", L"EventID", L"Channel", L"Provider", L"Computer", L"TimeCreated", L"Task", L"Level"); } // Begin an infinite loop, as we want to continue reading records as long as they are available. // The break-condition is a manual one at the bottom (i.e. no more records found) while (TRUE) { // Get a block of events from the result set. if (EvtNext(hResults, CHUNK_SIZE, hEvents, INFINITE, 0, &dwReturned)) { // Cycle through all the events that we received for (DWORD i = 0; i < dwReturned; i++) { // Only print the separator characters once the first record is completed if( firstRecordCompleted ) wprintf(L"||"); // Extract event details and output the screen DWORD64 result = DumpEventInfo(hRemote, hEvents[i], outputFormat, mode, debug); // Set flag indicating first record is completed so that // the top of our loop knows to begin printing the separator character firstRecordCompleted = TRUE; // Close the handle to the current event, as we are done EvtClose(hEvents[i]); // Clear the event handle so our cleanup routine does not attempt to re-close hEvents[i] = NULL; // If currently in "last record" mode if( mode == MODE_FETCH_LAST_RECORD ) { // We do not need to process anymore events // Recall that all we were looking for was the record ID of the most recent record // This should be stored in "status" as, this is the variable that's returned status = result; completed = true; break; } } } else { // Call to retrieve events failed. Get the error code status = GetLastError(); // If the error was the result of not having any more records if (status == ERROR_NO_MORE_ITEMS) { // Exit the loop. No more records to process completed = TRUE; } else { // Otherwise, notify user of the error fwprintf(stderr, L"Failed to fetch next batch with following error: %lu\n", status); } } // Cycle through all records that we received // Recall that dwReturned contains the number of records received for (DWORD i = 0; i < dwReturned; i++) { // If the event isn't already closed if (hEvents[i] != NULL) { // Close the event record EvtClose(hEvents[i]); } } // Exit the loop if required (i.e. we're done) if( completed ) break; } // Add closing tag if this is JSON if( outputFormat == OUTPUT_FORMAT_JSON ) { // Marc requested this to be removed // wprintf(L"]"); } return status; }
ULONG QueryEvents ( __in PCWSTR Channel, __in PCWSTR XPath ) /*++ Routine Description: This function queries events from the given channel and prints their description to the standard output. Arguments: Channel - Supplies the name of the channel whose events will be displayed. XPath - Supplies the XPath expression to filter events with. Return Value: Win32 error code indicating if querying was successful. --*/ { PWSTR Buffer; ULONG BufferSize; ULONG BufferSizeNeeded; ULONG Count; EVT_HANDLE Event; EVT_HANDLE Query; ULONG Status; // // Create the query. // Query = EvtQuery(NULL, Channel, XPath, EvtQueryChannelPath); if (Query == NULL) { return GetLastError(); } // // Read each event and render it as XML. // Buffer = NULL; BufferSize = 0; BufferSizeNeeded = 0; while (EvtNext(Query, 1, &Event, INFINITE, 0, &Count) != FALSE) { do { if (BufferSizeNeeded > BufferSize) { free(Buffer); BufferSize = BufferSizeNeeded; Buffer = malloc(BufferSize); if (Buffer == NULL) { Status = ERROR_OUTOFMEMORY; BufferSize = 0; break; } } if (EvtRender(NULL, Event, EvtRenderEventXml, BufferSize, Buffer, &BufferSizeNeeded, &Count) != FALSE) { Status = ERROR_SUCCESS; } else { Status = GetLastError(); } } while (Status == ERROR_INSUFFICIENT_BUFFER); // // Display either the event xml or an error message. // if (Status == ERROR_SUCCESS) { wprintf(L"%s\n", Buffer); } else { wprintf(L"Error rendering event.\n"); } EvtClose(Event); } // // When EvtNextChannelPath returns ERROR_NO_MORE_ITEMS, we have actually // iterated through all matching events and thus succeeded. // Status = GetLastError(); if (Status == ERROR_NO_MORE_ITEMS) { Status = ERROR_SUCCESS; } // // Free resources. // EvtClose(Query); free(Buffer); return Status; }
/**** * ParseEventLogInternal * * DESC: * Gets the most recent event log record * * ARGS: * server - IP or host to connect to * domain - domain within the host (empty string for none) * username - username within the domain * password - password for above user * logName - event log to open (default to "Application" if NULL) * query - XPath query to retrieve (see remarks) * outputFormat - set to 0 (JSON) otherwise XML * debug - set to 0 (none) 1 (basic) or 2 (verbose) * mode - mode to run the parser (see remarks) * * REMARKS: * XPath: * * The Windows Event log is structurally an XML document. You * may therefore use XPath queries to retrieve the information * you want. Pre-defined XPath queries have been built into the * supplementary Perl module. However, you are free to modify * that module to include newer queries, based on your requirements * * mode: * * Can be set to either MODE_FETCH_LAST_RECORD or MODE_DEFAULT. The * former will simply return the Event Log Record ID of the topmost * (i.e. the latest) event record. The latter will do the actual * processing of parsing an event log record to the screen. * * Note: As per previous discussions, output format is forced as * JSON here. To re-allow XML, simply replace OUTPUT_FORMAT_JSON * with outputFormat, in the line of code, below */ DWORD64 ParseEventLogInternal(LPWSTR server, LPWSTR domain, LPWSTR username, LPWSTR password, LPWSTR logName, LPWSTR query, INT outputFormat, INT debug, INT mode) { bool getLastRecord = false; DWORD64 result = 0; if( debug > DEBUG_L1 ) { wprintf(L"[ParseEventLogInternal]: Attempting to connect to '%s' on domain '%s' using %s:%s...\n", server, domain, username, password); } // If no domain was supplied if( wcslen(domain) == 0 ) { // Official MSDN specs request NULL instead of an empty string domain = NULL; if( debug >= DEBUG_L1 ) { wprintf(L"[ParseEventLogInternal]: Empty domain supplied. Default to NULL\n"); } } // If a blank query was supplied, assume no query (NULL) if( lstrlen(query) == 0 ) query = NULL; // If the supplied query is our special token that retrieves the last record if( lstrcmpW( query, L"LAST_RECORD") == 0 ) { if( debug >= DEBUG_L1 ) { wprintf(L"[ParseEventLogInternal]: Mode is last record fetch\n"); } // Flag the processing routine to only fetch the lastest record getLastRecord = true; // Force an empty query so that the last record is not affected by query filters // An empty query means it will get ALL records, in which case we are guaranteed // the latest record (i.e. the record ID we want) is the first to be retrieved query = NULL; } else { if( debug >= DEBUG_L1 ) { if( query == NULL ) { wprintf(L"[ParseEventLogInternal]: (no query specified)\n"); } else { wprintf(L"[ParseEventLogInternal]: Using query: %s\n", query); } } } // Create a remote context to the external server EVT_HANDLE hRemote = CreateRemoteSession(server, domain, username, password); if (hRemote != NULL) { // NOTE: Reaching here does not mean the connection succeeded. It merely // means that we successfully created the remote context if( debug >= DEBUG_L1 ) { wprintf(L"[ParseEventLogInternal]: Attempting to query the EventLog...\n\n", hRemote); } // Attempt to query event log in reverse chronological order (newest to oldest) EVT_HANDLE hResults = EvtQuery( hRemote, logName, query, EvtQueryChannelPath | EvtQueryReverseDirection); // If the query was successful if (hResults != NULL) { // Process the first event found DumpEventInfo(hRemote, hResults, outputFormat, getLastRecord ? MODE_FETCH_LAST_RECORD : 0, debug); // Process subsequent events result = ProcessResults(hRemote, hResults, outputFormat, getLastRecord ? MODE_FETCH_LAST_RECORD : 0, debug); } else { // Query was not successful. Get the error code DWORD dwError = GetLastError(); if (dwError == ERROR_EVT_CHANNEL_NOT_FOUND) { fwprintf(stderr, L"[Error][ParseEventLog]: Could not open the '%s' log on this machine.\n", logName); } else if (dwError == ERROR_EVT_INVALID_QUERY) { // You can call the EvtGetExtendedStatus function to try to get // additional information as to what is wrong with the query. fwprintf(stderr, L"[Error][ParseEventLog]: The specified search query is not valid.\n"); } else { fwprintf(stderr, L"[Error][ParseEventLog]: Could not read event logs due to the following Windows error: %lu.\n", dwError); } } // Close the handle to the query we opened EvtClose(hRemote); } else { fwprintf(stderr, L"[Error][ParseEventLog]: Failed to connect to remote computer. Error code is %d.\n", GetLastError()); } return result; }
/* obtain a particular message from a desired eventlog */ static int zbx_get_eventlog_message6(const wchar_t *wsource, zbx_uint64_t *which, unsigned short *out_severity, unsigned long *out_timestamp, char **out_provider, char **out_source, char **out_message, unsigned long *out_eventid, EVT_HANDLE *render_context, EVT_HANDLE *query, zbx_uint64_t *keywords) { const char *__function_name = "zbx_get_eventlog_message6"; EVT_HANDLE event_bookmark = NULL; EVT_VARIANT* renderedContent = NULL; const wchar_t *pprovider = NULL; char *tmp_str = NULL; DWORD size = DEFAULT_EVENT_CONTENT_SIZE; DWORD bookmarkedCount = 0; DWORD require = 0; const zbx_uint64_t sec_1970 = 116444736000000000; const zbx_uint64_t success_audit = 0x20000000000000; const zbx_uint64_t failure_audit = 0x10000000000000; int ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s() lastlogsize:" ZBX_FS_UI64, __function_name, *which); if (NULL == *query) { zabbix_log(LOG_LEVEL_DEBUG, "no EvtQuery handle"); goto finish; } /* get the entries and allocate required space */ renderedContent = zbx_malloc(renderedContent, size); if (TRUE != EvtNext(*query, 1, &event_bookmark, INFINITE, 0, &require)) { zabbix_log(LOG_LEVEL_WARNING, "EvtNext failed: %s, lastlogsize:" ZBX_FS_UI64, strerror_from_system(GetLastError()), *which); goto finish; } /* obtain the information from the selected events */ if (TRUE != EvtRender(*render_context, event_bookmark, EvtRenderEventValues, size, renderedContent, &require, &bookmarkedCount) ) { /* information exceeds the space allocated */ if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { zabbix_log(LOG_LEVEL_WARNING, "EvtRender failed: %s", strerror_from_system(GetLastError())); goto finish; } renderedContent = (EVT_VARIANT*)zbx_realloc((void *)renderedContent, require); size = require; if (TRUE != EvtRender(*render_context, event_bookmark, EvtRenderEventValues, size, renderedContent, &require, &bookmarkedCount)) { zabbix_log(LOG_LEVEL_WARNING, "EvtRender failed: %s", strerror_from_system(GetLastError())); goto finish; } } pprovider = VAR_PROVIDER_NAME(renderedContent); *out_provider = zbx_unicode_to_utf8(pprovider); if (NULL != VAR_SOURCE_NAME(renderedContent)) { *out_source = zbx_unicode_to_utf8(VAR_SOURCE_NAME(renderedContent)); } *keywords = VAR_KEYWORDS(renderedContent) & (success_audit | failure_audit); *out_severity = VAR_LEVEL(renderedContent); *out_timestamp = (unsigned long)((VAR_TIME_CREATED(renderedContent) - sec_1970) / 10000000); *out_eventid = VAR_EVENT_ID(renderedContent); *out_message = expand_message6(pprovider, event_bookmark); tmp_str = zbx_unicode_to_utf8(wsource); if (VAR_RECORD_NUMBER(renderedContent) != *which) { zabbix_log(LOG_LEVEL_DEBUG, "Overwriting expected EventRecordID:" ZBX_FS_UI64 " with the real" " EventRecordID:" ZBX_FS_UI64 " in eventlog '%s'", *which, VAR_RECORD_NUMBER(renderedContent), tmp_str); *which = VAR_RECORD_NUMBER(renderedContent); } /* some events dont have enough information for making event message */ if (NULL == *out_message) { *out_message = zbx_strdcatf(*out_message, "The description for Event ID:%lu in Source:'%s'" " cannot be found. Either the component that raises this event is not installed" " on your local computer or the installation is corrupted. You can install or repair" " the component on the local computer. If the event originated on another computer," " the display information had to be saved with the event.", *out_eventid, NULL == *out_provider ? "" : *out_provider); } ret = SUCCEED; finish: if (NULL != event_bookmark) EvtClose(event_bookmark); zbx_free(tmp_str); zbx_free(renderedContent); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }