#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <winevt.h>
#include <vld.h>
#pragma comment(lib, "wevtapi.lib")

DWORD WINAPI SubscriptionCallback(EVT_SUBSCRIBE_NOTIFY_ACTION action, PVOID pContext, EVT_HANDLE hEvent);
DWORD PrintEvent(EVT_HANDLE hEvent);
wchar_t wcsXmlQuery[260];
int ncnt = 1;
void PrepareEventQuery()
{
try
{
char szSendString[253]="";
SYSTEMTIME lpSystemTime;
GetSystemTime(&lpSystemTime);
_snprintf_s(szSendString,_countof(szSendString),_TRUNCATE,"<QueryList><Query Id=\"0\" Path=\"Security\"><Select Path=\"Security\">*[System[TimeCreated[@SystemTime&gt;='%02d-%02d-%02dT%02d:%02d:%02d.000000000Z']]] </Select> </Query> </QueryList>",lpSystemTime.wYear, lpSystemTime.wMonth, lpSystemTime.wDay, lpSystemTime.wHour, lpSystemTime.wMinute, lpSystemTime.wSecond,lpSystemTime.wMilliseconds);

size_t origsize = strlen(szSendString) + 1;
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, wcsXmlQuery, origsize, szSendString, _TRUNCATE);
}
catch(...)
{
//WriteEventLogEntry(L"Failed in PrepareEventQuery",EVENTLOG_ERROR_TYPE);
}
}

void main(void)
{
DWORD status = ERROR_SUCCESS;
EVT_HANDLE hSubscription = NULL;
LPWSTR pwsPath = L"<channel name goes here>";
LPWSTR pwsQuery = L"<xpath query goes here>";
PrepareEventQuery();
// Subscribe to events beginning with the oldest event in the channel. The subscription
// will return all current events in the channel and any future events that are raised
// while the application is active.
hSubscription = EvtSubscribe(NULL, NULL, NULL, wcsXmlQuery, NULL, NULL,
(EVT_SUBSCRIBE_CALLBACK)SubscriptionCallback, EvtSubscribeStartAtOldestRecord);
if (NULL == hSubscription)
{
status = GetLastError();

if (ERROR_EVT_CHANNEL_NOT_FOUND == status)
wprintf(L"Channel %s was not found.\n", pwsPath);
else if (ERROR_EVT_INVALID_QUERY == status)
// You can call EvtGetExtendedStatus to get information as to why the query is not valid.
wprintf(L"The query \"%s\" is not valid.\n", pwsQuery);
else
wprintf(L"EvtSubscribe failed with %lu.\n", status);

goto cleanup;
}

wprintf(L"Hit any key to quit\n\n");
while (!_kbhit())
Sleep(10);

cleanup:

if (hSubscription)
EvtClose(hSubscription);
}

// The callback that receives the events that match the query criteria.
DWORD WINAPI SubscriptionCallback(EVT_SUBSCRIBE_NOTIFY_ACTION action, PVOID pContext, EVT_HANDLE hEvent)
{
UNREFERENCED_PARAMETER(pContext);

DWORD status = ERROR_SUCCESS;

switch(action)
{
// You should only get the EvtSubscribeActionError action if your subscription flags
// includes EvtSubscribeStrict and the channel contains missing event records.
case EvtSubscribeActionError:
if (ERROR_EVT_QUERY_RESULT_STALE == (DWORD)hEvent)
{
wprintf(L"The subscription callback was notified that event records are missing.\n");
// Handle if this is an issue for your application.
}
else
{
wprintf(L"The subscription callback received the following Win32 error: %lu\n", (DWORD)hEvent);
}
break;

case EvtSubscribeActionDeliver:
if (ERROR_SUCCESS != (status = PrintEvent(hEvent)))
{
goto cleanup;
}
break;

default:
wprintf(L"SubscriptionCallback: Unknown action.\n");
}

cleanup:

if (ERROR_SUCCESS != status)
{
// End subscription - Use some kind of IPC mechanism to signal
// your application to close the subscription handle.
}

return status; // The service ignores the returned status.
}

// Render the event as an XML string and print it.
DWORD PrintEvent(EVT_HANDLE hEvent)
{
DWORD status = ERROR_SUCCESS;
DWORD dwBufferSize = 0;
DWORD dwBufferUsed = 0;
DWORD dwPropertyCount = 0;
LPWSTR pRenderedContent = NULL;

if (!EvtRender(NULL, hEvent, EvtRenderEventXml, dwBufferSize, pRenderedContent, &dwBufferUsed, &dwPropertyCount))
{
if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError()))
{
dwBufferSize = dwBufferUsed;
pRenderedContent = (LPWSTR)malloc(dwBufferSize);
if (pRenderedContent)
{
EvtRender(NULL, hEvent, EvtRenderEventXml, dwBufferSize, pRenderedContent, &dwBufferUsed, &dwPropertyCount);
}
else
{
wprintf(L"malloc failed\n");
status = ERROR_OUTOFMEMORY;
goto cleanup;
}
}

if (ERROR_SUCCESS != (status = GetLastError()))
{
wprintf(L"EvtRender failed with %d\n", status);
goto cleanup;
}
}

// wprintf(L"%s\n\n", pRenderedContent);
printf("%d\n",ncnt);
ncnt++;
cleanup:

if (pRenderedContent)
free(pRenderedContent);

EvtClose(hEvent);

return status;
}