没有记录在案的方法可以做到这一点,但如果你冒险进入无证土地实际上并不难。(出于您的目的,这应该没问题,因为它不会真正影响您程序的功能。)
你需要做的第一件事是弄清楚给你的句柄是否是一个事件。为此,您使用 NtQueryObject。该函数记录在这里:http: //msdn.microsoft.com/en-us/library/bb432383 (v=vs.85).aspx 。它带有本机 API 的通常条款,它可能会消失或更改,恕不另行通知。部分示例:
#include <winternl.h>
typedef NTSTATUS (NTAPI * PFN_NtQueryObject)(
HANDLE Handle,
OBJECT_INFORMATION_CLASS ObjectInformationClass,
PVOID ObjectInformation,
ULONG ObjectInformationLength,
PULONG ReturnLength );
HMODULE ntdll = GetModuleHandle( L"ntdll.dll" );
auto NtQueryObject = (PFN_NtQueryObject)GetProcAddress( ntdll, "NtQueryObject" );
NTSTATUS result = NtQueryObject(
eventHandle,
ObjectTypeInformation,
buffer,
length,
&length );
这将为您提供一个 PUBLIC_OBJECT_TYPE_INFORMATION 结构。如果对象实际上是一个事件,则 TypeName 字段将为“Event”。
接下来,您调用 NtQueryEvent 来获取事件的类型。所有这些都是完全没有记录的。
typedef enum _EVENT_INFORMATION_CLASS {
EventBasicInformation
} EVENT_INFORMATION_CLASS, *PEVENT_INFORMATION_CLASS;
typedef enum _EVENT_TYPE {
NotificationEvent,
SynchronizationEvent
} EVENT_TYPE, *PEVENT_TYPE;
typedef struct _EVENT_BASIC_INFORMATION {
EVENT_TYPE EventType;
LONG EventState;
} EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION;
typedef NTSTATUS (NTAPI * PFN_NtQueryEvent)(
HANDLE EventHandle,
EVENT_INFORMATION_CLASS EventInformationClass,
PVOID EventInformation,
ULONG EventInformationLength,
PULONG ReturnLength );
auto NtQueryEvent = (PFN_NtQueryEvent)GetProcAddress( ntdll, "NtQueryEvent" );
EVENT_BASIC_INFORMATION info;
ULONG length = sizeof( info );
NTSTATUS result = NtQueryEvent(
eventHandle,
EventBasicInformation,
&info,
length,
&length );
现在,只需检查信息中的 EventType 字段即可。“NotificationEvent”表示手动重置,“SynchronizationEvent”表示自动重置。
如果你想知道我是如何计算出第二部分的,我没有。信息来自这里:http ://undocumented.ntinternals.net/ 。请负责任地使用!