これを行うための文書化された方法はありませんが、文書化されていない土地に足を踏み入れても、実際には難しくありません。(プログラムの機能には実際には影響しないため、これで問題ないはずです。)
最初に行う必要があるのは、指定されたハンドルがイベントかどうかを判断することです。これには 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 );
ここで、info の EventType フィールドを調べるだけで完了です。「NotificationEvent」は手動リセットを意味し、「SynchronizationEvent」は自動リセットを意味します。
私がその 2 番目の部分をどのように考え出したか疑問に思っているなら、私は知りませんでした。情報はhttp://undocumented.ntinternals.net/から得られます。責任を持って使用してください!