// GetEventLog.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <strsafe.h>
#include <locale.h>
#define MAX_RECORD_BUFFER_SIZE 0x10000
#define MAX_TIMESTAMP_LEN 23 + 1
void GetTimestamp(const DWORD Time , WCHAR DisplayString[])
{
ULONGLONG ullTimeStamp = 0;
ULONGLONG SecsTo1970 = 116444736000000000;
SYSTEMTIME st;
FILETIME ft , ftLocal;
ullTimeStamp = Int32x32To64(Time , 10000000) + SecsTo1970;
ft.dwHighDateTime = (DWORD)((ullTimeStamp >> 32) & 0xFFFFFFFF);
ft.dwLowDateTime = (DWORD)(ullTimeStamp & 0xFFFFFFFF);
FileTimeToLocalFileTime(&ft , &ftLocal);
FileTimeToSystemTime(&ftLocal , &st);
StringCchPrintf(DisplayString , MAX_TIMESTAMP_LEN , L"%d/%d/%d %.2d:%.2d:%.2d" ,
st.wMonth , st.wDay , st.wYear , st.wHour , st.wMinute , st.wSecond);
}
int main()
{
// 创建事件对象
HANDLE hEvent = CreateEventW(0 , 1 , 0 , 0);
HANDLE hEventLog = OpenEventLogW(0 , L"Applicattion Error");
DWORD OldestRecord;
DWORD NumberOfRecords;
// 使一个应用程序在事件写入指定的事件日志时接收通知。当事件写入日志时,指定的事件对象被设置为信号状态。
// 将事件对象和产生日志"绑定"在一起
NotifyChangeEventLog(hEventLog , hEvent);
DWORD newLog;
PEVENTLOGRECORD pBuf = (PEVENTLOGRECORD)malloc(MAX_RECORD_BUFFER_SIZE);
DWORD pnBytesRead;
DWORD pnMinNumberOfBytesNeeded;
while (1)
{
// 捕获日志[通过事件对象获取捕获信号]
while (1)
{
// 等待日志事件
WaitForSingleObject(hEvent , -1);
OldestRecord = 0;
NumberOfRecords = 0;
if(GetOldestEventLogRecord(hEventLog , &OldestRecord))
{
if(GetNumberOfEventLogRecords(hEventLog , &NumberOfRecords))
break;
}
ResetEvent(hEvent);
}
newLog = NumberOfRecords - 1 + OldestRecord;
// 读取日志
if(!ReadEventLogW(hEventLog , 6 , newLog , pBuf , 0x38 , &pnBytesRead , &pnMinNumberOfBytesNeeded) && GetLastError() == 122)
{
// 如果读取错误,可能是之前申请的内存小了,这里重新申请
pBuf = (PEVENTLOGRECORD)realloc(pBuf , pnMinNumberOfBytesNeeded);
if(!pBuf)
{
printf("内存错误");
TerminateProcess(NULL , 0);
}
// 重新申请完之后,继续读取
if(!ReadEventLogW(hEventLog , 6 , newLog , pBuf , pnMinNumberOfBytesNeeded , &pnBytesRead , &pnMinNumberOfBytesNeeded))
{
printf("内存错误");
TerminateProcess(NULL , 0);
}
}
if (pBuf->EventType == 1)
{
CHAR ppColumn[ 8 ][ 25 ] = {
"应用程序名: ",
"应用程序版本: ",
"应用程序时间戳:",
"故障模块名称: ",
"故障模块版本: ",
"故障模块时间戳:",
"异常代码: ",
"异常偏移: "
};
// WCHAR SourceName []
// WCHAR Computername []
// SID UserSid
// WCHAR Strings []
// BYTE Data []
// CHAR Pad []
// DWORD Length;
WCHAR *pDataBuf;
PWCHAR lpString[ 8 ];// 字符串指针数组.用于保存各信息的首地址
DWORD dwDataStrLength;
DWORD RecordBuf
= (DWORD)pBuf + pBuf->StringOffset;
NumberOfRecords = 0;
if (pBuf->NumStrings > 0)
{
for (int i = 0; i < 8; i++)
{
// 定位到该条数据的首地址[注意是宽字符]
pDataBuf = (WCHAR *)(RecordBuf + 2 * NumberOfRecords);
lpString[ i ] = pDataBuf;
// 计算字符串长度
dwDataStrLength = lstrlenW(pDataBuf) + 1;
// 计算下条数据的偏移
NumberOfRecords = dwDataStrLength + NumberOfRecords;
}
}
// 打印标题
setlocale(LC_CTYPE , "");
wprintf(L"%s\n", L"**************** 15PB Event Catcher ^-^ by 树梢之上****************");
// 转化时间
WCHAR TimeStamp[ MAX_TIMESTAMP_LEN ];
GetTimestamp(pBuf->TimeGenerated , TimeStamp);
wprintf(L"%s\n", TimeStamp);
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole , 7);
for (int i = 0; i < 8; i++)
{
SetConsoleTextAttribute(hConsole , 7);
// 打印标题
printf("%-20s" , ppColumn[ i ]);
CHAR MultiByteStr[ 1040 ];
memset(MultiByteStr , 0 , 1040);
// 求长度
DWORD v17 = lstrlenW((LPCWSTR)lpString[ i ]);
// 宽字符转窄
WideCharToMultiByte(0 , 0 , (LPCWSTR)lpString[ i ] , v17 , MultiByteStr , 1040 , 0 , 0);
// 设置字符颜色
if(i >= 6 || i == 3)
{
SetConsoleTextAttribute(hConsole , 0xA);
}
// 打印数据
printf("%s\n" , MultiByteStr);
}
}
}
}