Though obscure now—indeed, for decades—the event pair was once vital to the efficiency of windowing and other functionality in the Win32 subsystem. The KEVENT_PAIR structure (formally _KEVENT_PAIR) is the kernel’s internal packaging of a pair of events to operate as one object. It is in turn exposed through the Object Manager as an EEVENT_PAIR such that event pairs can be created, opened and otherwise worked with though handles.

Two user-mode threads—you might call them client and server—create or open a pair of synchronisation events as one object by calling the NTDLL functions NtCreateEventPair and NtOpenEventPair. The two events—call them low and high—each represent one thread’s work. When one thread completes work for the other, it signals its own of the events and waits on the other’s. They each do this as one call to the kernel, passing one handle to the NTDLL functions NtSetLowWaitHighEventPair and NtSetHighWaitLowEventPair.

In version 5.0 and higher, once this operation gets to the kernel and the handles are resolved to objects, the kernel actually does just call KeSetEvent for one event and KeWaitForSingleObject for the other. Earlier versions, however, look for efficiency from the certainty that setting the event is just the first operation in a pair. They even give each thread a built-in event pair which a client and server can operate through the NTDLL functions NtSetLowWaitHighThread and NtSetHighWaitLowThread without the overhead of interpreting a handle. The original Windows versions apparently regarded this as so important that these functions get to the kernel through their own interrupt numbers (0x2B and 0x2C), thus shaving away even the small overhead of having the kernel look up its service table.

All this special attention to synchronising with event pairs was arguably nothing but dim prehistory even before Windows 8.1 reduced all the relevant functions to trivial failure. For one vestige that remains to this day, see NTSTATUS.H where comments for STATUS_NO_EVENT_PAIR talk of a “thread specific client/server event pair object”.

Documentation Status

Neither the KEVENT_PAIR nor any of the relevant NTDLL functions were ever documented. No C-language definition is known to have been published in any header from a Device Driver Kit (DDK) or Windows Driver Kit (WDK) or any other of Microsoft’s programming kits. For no Windows version is the structure even known from type information in public symbol files for the kernel or NTDLL.

The first that KEVENT_PAIR is known as Microsoft’s name for the structure is from output of the !strct command as implemented by the KDEX2X86 debugging extension which Microsoft supplied with the Device Driver Kit (DDK) for Windows NT 4.0. This also provides offsets and names (but not types) of the members.

Type information, such as might be found in public symbols, has instead been published in a statically linked library named CLFSMGMT.LIB which Microsoft supplies with the Software Development Kit (SDK) for user-mode programming. The x86 build of this library has type information for versions 6.0 to 6.2 inclusive, the x64 build for version 6.2 only. These libraries for version 6.2 place the definition in an otherwise unpublished header named ke.h (at line 488) from which it is thought to have been deleted for version 6.3.


The KEVENT_PAIR is 0x24 and 0x38 bytes in 32-bit and 64-bit Windows, respectively, in all versions that have it.

Offset (x86) Offset (x64) Definition Versions
0x00 0x00
3.10 to 6.2  
0x02 0x02
3.10 to 6.2
0x04 0x08
KEVENT EventLow;
3.10 to 6.2
0x14 0x20
KEVENT EventHigh;
3.10 to 6.2