Esempio n. 1
0
/* get handles of eventlog */
static int	zbx_get_handle_eventlog6(const wchar_t *wsource, zbx_uint64_t *lastlogsize, EVT_HANDLE *query)
{
	const char	*__function_name = "zbx_get_handle_eventlog6";
	wchar_t		*event_query = NULL;
	DWORD		status = 0;
	char		*tmp_str = NULL;
	int		ret = FAIL;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s(), previous lastlogsize:" ZBX_FS_UI64, __function_name, *lastlogsize);

	/* start building the query */
	tmp_str = zbx_dsprintf(NULL, "Event/System[EventRecordID>" ZBX_FS_UI64 "]", *lastlogsize);
	event_query = zbx_utf8_to_unicode(tmp_str);

	/* create massive query for an event on a local computer*/
	*query = EvtQuery(NULL, wsource, event_query, EvtQueryChannelPath);
	if (NULL == *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;
	}

	ret = SUCCEED;
out:
	zbx_free(tmp_str);
	zbx_free(event_query);
	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

	return ret;
}
Esempio n. 2
0
/**
* @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);
}
Esempio n. 3
0
/****
 * 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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
/* 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;
}
Esempio n. 6
0
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;
}
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;
}