KTIMER

The KTIMER is the kernel’s representation of a timer object. Like all dispatcher objects, timers can be waited on until they get signalled. As an elaboration that is not supported for all dispatcher objects, a timer’s usefulness comes not just from being waitable. It can also be configured so that signalling causes a Deferred Procedure Call (DPC) to be scheduled. For timers, signalling is done by the kernel on noticing that a specified time has been reached. This specified time can be absolute or relative, the former being a system time, the latter being a difference from the current interrupt time.

Kernel-mode code allocates space for a KTIMER and gets it ready for use by calling either KeInitializeTimer or the newer, more capable, KeInitializeTimerEx. Thereafter, conditions for the timer’s expiration can be specified through the progressively newer and more capable functions KeSetTimer, KeSetTimerEx and KeSetCoalescableTimer. These functions each reset the timer to be non-signalled.

The kernel itself exposes timer objects to the Object Manager. Code in both kernel mode and user mode can call NtCreateTimer or ZwCreateTimer, as appropriate, to get the kernel to create a KTIMER within an ETIMER, which is then made accessible through a handle. A timer that is created this way can have a name, such that another handle can be obtained, most usefully in another process, by calling NtOpenTimer or ZwOpenTimer. Of course, well-behaved user-mode code doesn’t call these native API functions directly but instead goes through such higher-level functions as CreateWaitableTimerEx and OpenWaitableTimer which are exported from KERNEL32.

Layout

In all versions, the KTIMER is 0x28 and 0x40 bytes in 32-bit and 64-bit Windows respectively.

Offset (x86) Offset (x64) Definition Versions Remarks
0x00 0x00
DISPATCHER_HEADER Header;
all    
0x10 0x18
ULARGE_INTEGER DueTime;
all  
0x18 0x20
LIST_ENTRY TimerListEntry;
all  
0x20 0x30
KDPC *Dpc;
all  
  0x38
ULONG Processor;
6.1 to 1903 x86 in Header
USHORT Processor;
2004 and higher  
  0x3A
USHORT TimerType;
2004 and higher  
0x24 0x38 (late 5.2 to 6.0);
0x3C
BOOLEAN Inserted;
3.10 to 3.51 moves to Header
LONG Period;
4.0 to 6.0  
ULONG Period;
6.1 and higher  

The DueTime is the interrupt time at which the timer is set to expire.

Of several expansions of functionality that Windows NT 4.0 brought to timers, automatically restarting the timer at repeating intervals required more storage in the KTIMER. Three bytes had been left undefined as a side-effect of alignment after the Inserted member. To find four bytes for saving the whole Period that could be given to the new KeSetTimerEx function, the Inserted member was moved into the DISPATCHER_HEADER, taking space from the Size.

Dispatcher Header

Much of the new functionality in successive versions has been accommodated by finding space inside the Header. The DISPATCHER_HEADER is a complex structure that begins all kernel objects that can be waited on. The following tables simplify by disregarding the nested unions, extracting only the branches that apply to timers.

Offset Definition Versions Remarks
0x00
SHORT Type;
3.10 to 3.50  
UCHAR Type;
3.51 and higher  
UCHAR TimerType;
10.0 and higher  
0x01
UCHAR Spare;
3.51 only  
UCHAR Absolute;
4.0 to 6.0 becomes bit in TimerControlFlags
union {
    UCHAR TimerControlFlags;
    struct {
        /*  bit fields, follow link  */
    };
};
6.1 and higher  
0x02
SHORT Size;
3.10 to 3.50  
USHORT Size;
3.51 only  
UCHAR Size;
4.0 to early 5.2  
UCHAR Hand;
late 5.2 and higher  
0x03
UCHAR Inserted;
4.0 to 6.0 becomes bit in TimerMiscFlags
union {
    UCHAR TimerMiscFlags;
    struct {
        /*  bit fields, follow link  */
    };
};
6.1 and higher  
0x04
LONG SignalState;
3.51 and higher  
0x08
LIST_ENTRY WaitListHead;
3.51 and higher  

As for all dispatchable objects, the low 7 bits of the Type—or all 8 bits in version 3.51—are from the KOBJECTS enumeration. For the KTIMER specifically, these bits are 0x08 (TimerNotificationObject) or 0x09 (TimerSynchronizationObject) according to whether NotificationTimer or SynchronizationTimer is given as the Type argument when initialising the timer through the KeInitializeTimerEx function.