KTHREAD (Early 5.2)

The KTHREAD structure is the Kernel Core’s portion of the ETHREAD structure. The latter is the thread object as exposed through the Object Manager. The KTHREAD is the core of it.

Variability

The KTHREAD structure is plainly internal to the kernel and its layout varies greatly between Windows versions and even between builds. Indeed, it is the most highly variable of all significant kernel-mode structures—so much so that tracking its history looks to be imposisble on one page and is therefore spread over several:

Through versions 3.51 to 5.1, the KTHREAD was relatively stable. Windows Server 2003, however, brought so many rearrangements, especially of small members, that tracking them from the earlier versions gets very messy—and then the very first service pack rearranged the structure at least as much all over again. This page lays out the KTHREAD just for the original build of version 5.2. Its size in this build is 0x01C8 bytes.

For each member that survives to the next build of version 5.2—only NpxIrql does not—the History column points the way to that member’s continuations (for 32-bit and 64-bit builds, respectively) on the separate page for late builds of version 5.2.

Layout

Offsets, types and names in the table that follows, are from Microsoft’s symbol files for the kernel.

It is well known that the KTHREAD is a kernel object that can be waited on until it gets signalled, as happens when the thread ends its execution. In the DISPATCHER_HEADER at the beginning of a KTHREAD, the Type is ThreadObject in the KOBJECTS enumeration. Version 5.2 started specialising this Header for thread objects, the DebugActive member having moved there (from offset 0x2C in version 5.1).

Offset (x86) Definition History
0x00
DISPATCHER_HEADER Header;
previously at same;
next at 0x00
0x10
LIST_ENTRY MutantListHead;
previously at same;
next at 0x10 and 0x18
0x18
PVOID InitialStack;
previously at same;
next at 0x18 and 0x28
0x1C
PVOID StackLimit;
previously at same;
next at 0x1C and 0x30
0x20
PVOID KernelStack;
previously at 0x28
next at 0x20 and 0x38
0x24
KSPIN_LOCK ThreadLock;
next at 0x24 and 0x40
0x28
ULONG ContextSwitches;
previously at 0x4C;
next at 0x48 and 0x0124
0x2C
UCHAR volatile State;
previously as UCHAR at 0x2D;
next at 0x4C and 0x0154
0x2D
UCHAR NpxState;
previously at 0x31;
next at 0x4D and 0x0155
0x2E
KIRQL WaitIrql;
previously at 0x58;
next at 0x4E and 0x0156
0x2F
KPROCESSOR_MODE WaitMode;
previously at 0x59;
next at 0x4F and 0x0157
0x30
PVOID Teb;
previously at 0x20;
next at 0x74 and 0xB0
0x34
KAPC_STATE ApcState;
previously at 0x34;
next as union at 0x28 and 0x48
0x4C
KSPIN_LOCK ApcQueueLock;
previously at 0xE8;
next at 0x44 and 0x78
0x50
LONG WaitStatus;
previously at 0x54;
next at 0x50 and 0x80
0x54
KWAIT_BLOCK *WaitBlockList;
previously at 0x5C;
next as union at 0x54 and 0x88
0x58
BOOLEAN Alertable;
previously at 0x0164;
next at 0x58 and 0x90
0x59
BOOLEAN WaitNext;
previously at 0x5A;
next at 0x59 and 0x91
0x5A
UCHAR WaitReason;
previously at 0x5B;
next at 0x5A and 0x92
0x5B
CHAR Priority;
previously at 0x33;
next at 0x5B and 0x93
0x5C
BOOLEAN EnableStackSwap;
previously at 0x0141;
next at 0x5C and 0x94
0x5D
UCHAR volatile SwapBusy;
next at 0x5D and 0x95
0x5E
BOOLEAN Alerted [2];
previously at 0x2E;
next at 0x5E and 0x96
0x60
union {
    LIST_ENTRY WaitListEntry;
    SINGLE_LIST_ENTRY SwapListEntry;
};
previously at 0x60;
next at 0x60 and 0x98
0x68
KQUEUE *Queue;
previously at 0xE4;
next at 0x68 and 0xA8
0x6C
ULONG WaitTime;
previously at 0x68;
next at 0x6C and 0x0184
0x70
union {
    struct {
        SHORT KernelApcDisable;
        SHORT SpecialApcDisable;
    };
    ULONG CombinedApcDisable;
};
previously as ULONG at 0xD4;
next at 0x70 and 0x01B4
0x78
KTIMER Timer;
previously at 0xF0;
next as union at 0x78 and 0xB8
0xA0
KWAIT_BLOCK WaitBlock [4];
previously at 0x70;
next as union at 0xA8 and 0xF8
0x0100
LIST_ENTRY QueueListEntry;
previously at 0x0118;
next at 0x0108 and 0x01B8
0x0108
UCHAR ApcStateIndex;
previously at 0x0165;
next at 0x011C and 0x01E4
0x0109
BOOLEAN ApcQueueable;
previously at 0x0166;
next at 0x3F and 0x73
0x010A
BOOLEAN Preempted;
previously at 0x0128;
next at 0x011E and 0x01E6
0x010B
BOOLEAN ProcessReadyQueue;
previously at 0x0129;
next at 0x011F and 0x01E7
0x010C
BOOLEAN KernelStackResident;
previously at 0x012A;
next at 0x0120 and 0x01F4
0x010D
CHAR Saturation;
previously at 0x32;
next at 0x0123 and 0x01F7
0x010E
UCHAR IdealProcessor;
previously at 0x01BB;
next at 0x011D and 0x01E5
0x010F
UCHAR NextProcessor;
previously at 0x012B;
next as UCHAR volatile at 0x40 and 0x74
0x0110
CHAR BasePriority;
previously at 0x6C;
next at 0x0121 and 0x01F5
0x0111
UCHAR Spare4;
 
0x0112
CHAR PriorityDecrement;
previously at 0x6E;
next at 0x0122 and 0x01F6
0x0113
CHAR Quantum;
previously at 0x6F;
next at 0x015D and 0x0261
0x0114
BOOLEAN SystemAffinityActive;
previously at 0xDC;
next at 0xBF and 0x0123
0x0115
KPROCESSOR_MODE PreviousMode;
previously at 0x0140;
next at 0xD7 and 0x0153
0x0116
UCHAR ResourceIndex;
previously at 0x0143;
next at 0xEF and 0x0183
0x0117
BOOLEAN DisableBoost;
previously at 0x01BB;
next as bit in ThreadFlags
0x0118
KAFFINITY UserAffinity;
previously at 0xD8;
next at 0x0124 and 0x01F8
0x011C
KPROCESS *Process;
next at 0x0128 and 0x0200
0x0120
KAFFINITY Affinity;
previously at 0x0124;
next at 0x012C and 0x0208
0x0124
PVOID ServiceTable;
previously at 0xE0;
next at 0x0118 and 0x01D8
0x0128
KAPC_STATE *ApcStatePointer [2];
previously at 0x0138;
next at 0x0130 and 0x0210
0x0130
KAPC_STATE SavedApcState;
previously at 0x014C;
next as union at 0x0138 and 0x0220
0x0148
PVOID CallbackStack;
previously at 0x012C;
next at 0x0114 and 0x01D0
0x014C
PVOID Win32Thread;
previously at 0x0130;
next at 0x0154 and 0x0250
0x0150
KTRAP_FRAME *TrapFrame;
previously at 0x0134;
next at 0x0110 and 0x01C8
0x0154
ULONG KernelTime;
previously at 0x0144;
next at 0x0160 and 0x0264
0x0158
ULONG UserTime;
previously at 0x0148;
next at 0x018C and 0x02B4
0x015C
PVOID StackBase;
previously at 0x0168;
next at 0x0158 and 0x0258
0x0160
KAPC SuspendApc;
previously at 0x016C;
next as union at 0x015C and 0x0260
0x0190
KSEMAPHORE SuspendSemaphore;
previously at 0x019C;
next as union at 0x0190 and 0x02B8
0x01A4
PVOID TlsArray;
previously at 0x24;
next at 0x0180 and 0x02A0
0x01A8
PVOID LegoData;
previously at 0xD0;
next at 0x0184 and 0x02A8
0x01AC
LIST_ENTRY ThreadListEntry;
previously at 0x01B0;
next at 0x01A8 and 0x02D8
0x01B4
BOOLEAN LargeStack;
previously at 0x0142;
next at 0x0107 and 0x01B3
0x01B5
UCHAR PowerState;
previously at 0xDD;
next at 0x01B8 and 0x02B3
0x01B6
KIRQL NpxIrql;
previously at 0xDE
0x01B7
UCHAR Spare5;
 
0x01B8
UCHAR AutoAlignment;
previously at 0x0167;
next as bit in ThreadFlags
0x01B9
UCHAR Iopl;
previously at 0x30;
next at 0x0153 (x86)
0x01BA
CHAR FreezeCount;
previously at 0x01B8;
next at 0x014F and 0x024B
0x01BB
CHAR SuspendCount;
previously at 0x01B9;
next at 0x0150 and 0x024C
0x01BC
UCHAR Spare0 [1];
 
0x01BD
UCHAR UserIdealProcessor;
next at 0x0151 and 0x024D
0x01BE
UCHAR volatile DeferredProcessor;
next at 0x41 and 0x75
0x01BF
UCHAR AdjustReason;
next at 0x42 and 0x76
0x01C0
CHAR AdjustIncrement;
next at 0x43 and 0x77
0x01C1
UCHAR Spare2 [3];