如何在winevt.h Windows C++API中的EvtSubscribe中使用Context参数

How to use Context argument in EvtSubscribe in winevt.h Windows C++ API

本文关键字:EvtSubscribe 参数 Context 中的 C++API winevt Windows      更新时间:2023-10-16

我正在尝试使用Windows C++API中提供的winevt.h头中的EvtSubscribe函数。

目前,我对EvtSubscibe的呼叫如下:

EvtSubscribeData data;
hResults = EvtSubscribe(
NULL, NULL, L"Security", L"Event/System[EventID=4624]", NULL, reinterpret_cast<void *>(&data), (EVT_SUBSCRIBE_CALLBACK)callback, EvtSubscribeStartAtOldestRecord
);

EvtSubscribeData是一个类,它有一个名为subscribe的函数,我的回调函数如下所示:

DWORD callback(EVT_SUBSCRIBE_NOTIFY_ACTION Action, PVOID UserContext,EVT_HANDLE Event) {
return reinterpret_cast<EvtSubscribeData *>(UserContext)->subscribe(Action, Event);
}

正如您所知,我正在使用Context参数,该参数允许我使用回调中返回的数据来填充EvtSubscribeData类成员变量。

唯一的问题是返回一个数据点,然后程序停止。EVT_SUBSCRIBE_CALLBACK函数说subscribe函数正在阻塞,所以我的第一个想法是callback永远不会返回,但调试后,callback返回0,这是从EvtSubscribeData::subscribe正确返回的。

当我删除Context参数并使用EvtSubscribeData::subscribe作为函数而不是成员函数时(如这里所示的示例),打印数百个事件时,一切都会正常工作。

一个简单的EvtSubscribeData函数:

class EvtSubscribeData {
public:
EvtSubscribeData() {}
DWORD WINAPI subscribe(EVT_SUBSCRIBE_NOTIFY_ACTION action, EVT_HANDLE event) {
auto status = ERROR_SUCCESS;
switch (action) {
case EvtSubscribeActionError:
if (ERROR_EVT_QUERY_RESULT_STALE == (DWORD)event) {
std::cout << "event records are missing" << std::endl;
} else {
std::cout << "win32 Error" << (DWORD)event << std::endl;
}
break;
case EvtSubscribeActionDeliver:
status = PrintEvent(event);
break;
}
return status;
}
};

唯一的问题是返回一个数据点,然后程序停止。

将WINAPI添加到回调函数中,看看它是否有效。如果没有WINAPI关键字,它会导致您的"访问违规读取"异常(而不是"订阅功能被阻止"。)

回调如下:

DWORD WINAPI callback(EVT_SUBSCRIBE_NOTIFY_ACTION Action, PVOID UserContext, EVT_HANDLE Event) {
return reinterpret_cast<EvtSubscribeData *>(UserContext)->subscribe(Action, Event);
}

它对我有用。

更多参考:"主要功能中的"WINAPI"是什么意思?">