Geoff Chappell - Software Analyst
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.
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.
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]; |