CURRENT WORK ITEM - PREVIEW ONLY

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 more 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 and make it 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;
3.51 and higher  
0x10 0x18
ULARGE_INTEGER DueTime;
3.51 and higher  
0x18 0x20
LIST_ENTRY TimerListEntry;
3.51 and higher  
0x20 0x30
KDPC *Dpc;
3.51 and higher  
  0x38
ULONG Processor;
6.1 and higher  
0x24 0x38 (late 5.2 to 6.0);
0x3C
BOOLEAN Inserted;
3.51 only 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.

Dispatcher Header

Much of the new functionality in successive versions has been accommodated by finding space inside the Header. The DISPATCH_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
UCHAR Type;
3.51 to 6.3  
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, see below  */
    };
};
6.1 and higher  
0x02
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, see below  */
    };
};
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.

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.

TimerControlFlags

Mask Definition Versions
0x01
UCHAR Absolute : 1;
6.1 and higher
0x02
UCHAR Coalescable : 1;
6.1 only
UCHAR Wake : 1;
6.2 and higher
0x04 (6.1)
UCHAR KeepShifting : 1;
6.1 only
0xF8 (6.1);
0xFC
UCHAR EncodedTolerableDelay : 5;
6.1 only
UCHAR EncodedTolerableDelay : 6;
6.2 and higher

TimerMiscFlags

Mask (x86) Mask (x64) Definition Versions
0x01  
UCHAR Index: 1;
6.1 and higher
  0x3F
UCHAR Index: 6;
6.1 and higher
0x3E  
UCHAR Processor : 5;
6.1 and higher
0x40
UCHAR Inserted : 1;
6.1 and higher
0x80
UCHAR volatile Expired : 1;
6.1 and higher