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:
Though the KTHREAD does seem to have settled down since its last large-scale rearrangement for Windows 8, it still varies between versions, especially between successive half-yearly updates of Windows 10. Some sense of this variability can be gained just from the structure’s changing size.
Version | Size (x86) | Size (x64) |
---|---|---|
6.2 | 0x01E8 | 0x0348 |
6.3 | 0x0338 | 0x05D0 |
10.0 to 1511 | 0x0348 | 0x05D8 |
1607 | 0x0348 | 0x05E0 |
1703 | 0x0350 | 0x05E8 |
1709 to 1809 | 0x0350 | 0x05F0 |
1903 | 0x0358 | 0x0600 |
2004 | 0x0280 | 0x0430 |
Even with attention narrowed just to recent Windows versions, description of the KTHREAD is unusually complicated. Specially notable is the packing of small members into spare fields in other members. Some such reused fields are explicitly spare, as with several members of the KAPC structure. WDM.H even defines macros to ease the reference to these fields by their offsets. Other reuse is available only because of alignment padding, as with the last byte of the KAPC_STATE for 32-bit Windows. As if this weren’t messy enough by itself, the greater opportunity for this reuse in the 64-bit builds, whose wider pointers tend to create more alignment padding as a side-effect, allows that more than a few members are placed very differently in the 32-bit and 64-bit builds.
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 (6) in the KOBJECTS enumeration. Ever since version 5.2, some other members of this DISPATCHER_HEADER are specific to the KTHREAD.
Offset (x86) | Offset (x64) | Definition | Versions | History |
---|---|---|---|---|
0x00 | 0x00 |
DISPATCHER_HEADER Header; |
6.2 and higher | previously at 0x00 |
0x10 | 0x18 |
PVOID SListFaultAddress; |
6.2 and higher | previously at 0x01F0 and 0x0318 |
0x18 | 0x20 |
ULONGLONG QuantumTarget; |
6.2 and higher | previously at 0x20 (both) |
0x20 | 0x28 |
PVOID InitialStack; |
6.2 and higher | previously at 0x28 (both) |
0x24 | 0x30 |
PVOID volatile StackLimit; |
6.2 and higher | previously at 0x2C and 0x30 |
0x28 | 0x38 |
PVOID StackBase; |
6.2 and higher | previously at 0x0190 and 0x0278 |
0x2C | 0x40 |
KSPIN_LOCK ThreadLock; |
6.2 and higher | previously at 0x34 and 0x40 |
0x30 | 0x48 |
ULONGLONG volatile CycleTime; |
6.2 and higher | previously at 0x10 and 0x18 |
0x38 |
ULONG volatile HighCycleTime; |
6.2 and higher | previously at 0x18 | |
0x3C |
PVOID ServiceTable; |
6.2 and higher | previously at 0xBC | |
0x40 | 0x50 |
ULONG CurrentRunTime; |
6.2 and higher | |
0x44 | 0x54 |
ULONG ExpectedRunTime; |
6.2 and higher | |
0x48 | 0x58 |
PVOID KernelStack; |
6.2 and higher | previously at 0x30 and x038 |
0x4C | 0x60 |
XSAVE_FORMAT *StateSaveArea; |
6.2 and higher | |
0x50 | 0x68 |
KSCHEDULING_GROUP *SchedulingGroup; |
6.2 and higher | |
0x54 | 0x70 |
KWAIT_STATUS_REGISTER WaitRegister; |
6.2 and higher | previously at 0x38 and 0x48 |
0x55 | 0x71 |
BOOLEAN volatile Running; |
6.2 and higher | previously at 0x39 and 0x49 |
0x56 | 0x72 |
BOOLEAN Alerted [2]; |
6.2 and higher | previously at 0x3A and 0x4A |
0x58 | 0x74 |
union { struct { /* bit fields, follow link */ }; LONG MiscFlags; }; |
6.2 and higher | previously at 0x3C and 0x4C |
0x5C | 0x78 |
union { struct { /* bit fields, follow link */ }; LONG volatile ThreadFlags; }; |
6.2 and higher | previously at 0xB8 and 0x0100 |
0x60 | 0x7C |
UCHAR volatile Tag; |
10.0 and higher | |
0x61 | 0x7D |
UCHAR SystemHeteroCpuPolicy; |
10.0 and higher | |
0x62 | 0x7E |
UCHAR UserHeteroCpuPolicy : 7; UCHAR ExplicitSystemHeteroCpuPolicy : 1; |
10.0 and higher | |
0x60 (6.2 to 6.3); 0x63 |
0x7C (6.2 to 6.3); 0x7F |
UCHAR Spare0; |
6.2 and higher (x86); 6.2 to 1803 (x64) |
|
union { struct { UCHAR RunningNonRetpolineCode : 1; UCHAR SpecCtrlSpare : 7; }; UCHAR SpecCtrl; }; |
1809 and higher (x64) | |||
0x64 | 0x80 |
ULONG SystemCallNumber; |
6.2 and higher | previously at 0x013C and 0x01F8 |
0x84 |
ULONG Spare1; |
6.2 to 1607 | ||
ULONG ReadyTime; |
1703 and higher | |||
0x68 | 0x88 |
PVOID FirstArgument; |
6.2 and higher | previously at 0x012C and 0x01E0 |
0x6C | 0x90 |
KTRAP_FRAME *TrapFrame; |
6.2 and higher | previously at 0x0128 and 0x01D8 |
0x70 | 0x98 |
union { KAPC_STATE ApcState; /* overlay, see below */ }; |
6.2 and higher | previously at 0x40 and 0x50 |
Overlaying the ApcState is first some padding to get past the defined members of the KAPC_STATE to the space that’s left for alignment:
struct { UCHAR ApcStateFill [KAPC_STATE_ACTUAL_LENGTH]; /* 5 bytes, see below */ };
With this construction, the 64-bit builds squeeze five bytes into the end of the 0x30-byte ApcState. In 32-bit builds, only the first fits the 0x18-byte ApcState: the remaining four just follow as if they had been declared outside the union. Disregard the construction, and the members that are packed with the ApcState are:
Offset (x86) | Offset (x64) | Definition | Versions | History |
---|---|---|---|---|
0x87 | 0xC3 |
CHAR Priority; |
6.2 and higher | previously at 0x57 and 0x7B |
0x88 | 0xC4 |
ULONG UserIdealProcessor; |
6.2 and higher | previously at 0x0164 and 0x022C |
The structures used for larger members of the KTHREAD tend to have more spare space in the 64-bit builds, whose wider pointers have a wider alignment requirement. There follow a few members that the 32-bit builds don’t treat to this packing game. The 64-bit builds pack them with the WaitBlock member (further into the structure).
Offset (x86) | Offset (x64) | Definition | Versions | Remarks | History |
---|---|---|---|---|---|
0x8C |
ULONG ContextSwitches; |
6.2 and higher | x64 at 0x0154 | previously at 0x64 | |
0x90 |
UCHAR volatile State; |
6.2 and higher | x64 at 0x0184 | previously at 0x68 | |
0x91 |
CHAR NpxState; |
6.2 to 6.3 | x64 at 0x0185; next as LONGLONG at 0x0340 |
previously as UCHAR at 0x69 | |
CHAR Spare12; |
10.0 and higher | ||||
0x92 |
KIRQL WaitIrql; |
6.2 and higher | x64 at 0x0186 | previously at 0x6A | |
0x93 |
KPROCESSOR_MODE WaitMode; |
6.2 and higher | x64 at 0x0187 | previously at 0x6B | |
0x94 | 0xC8 |
LONG_PTR volatile WaitStatus; |
6.2 and higher | previously at 0x6C and 0x90 | |
0x98 | 0xD0 |
KWAIT_BLOCK *WaitBlockList; |
6.2 and higher | previously at 0x70 and 0x98 | |
0x9C | 0xD8 |
union { LIST_ENTRY WaitListEntry; SINGLE_LIST_ENTRY SwapListEntry; }; |
6.2 and higher | previously at 0x74 and 0xA0 | |
0xA4 | 0xE8 |
KQUEUE * volatile Queue; |
6.2 only | previously at 0x7C and 0xB0 | |
DISPATCHER_HEADER * volatile Queue; |
6.3 and higher |
Version 6.3 introduced a new type of queue object, and so Queue can point to either a KQUEUE (as for earlier versions) or to a KPRIQUEUE. Both can be waited on and therefore both begin with a DISPATCHER_HEADER.
Offset (x86) | Offset (x64) | Definition | Versions | History |
---|---|---|---|---|
0xA8 | 0xF0 |
PVOID Teb; |
6.2 and higher | previously at 0x88 and 0xB8 |
0xB0 | 0xF8 |
ULONGLONG RelativeTimerBias; |
6.2 and higher | |
0xB8 | 0x0100 |
KTIMER Timer; |
6.2 and higher | previously as union at 0x90 and 0xC0 |
0xE0 | 0x0140 |
union { KWAIT_BLOCK WaitBlock [4]; /* overlay, see below */ }; |
6.2 and higher | previously without union at 0xC0 (x86);
previously as changed union at 0x0108 (x64) |
Overlaying the long-standing WaitBlock array are a succession of structures that each pad from the start of the array to spare or resuable members:
#ifdef _AMD64_ // SpareLong exists only for x64 struct { UCHAR WaitBlockFill4 [FIELD_OFFSET (KWAIT_BLOCK, SpareLong)]; /* reclaimed 4 bytes, see below */ }; struct { UCHAR WaitBlockFill5 [sizeof (KWAIT_BLOCK) + FIELD_OFFSET (KWAIT_BLOCK, SpareLong)]; /* reclaimed 4 bytes, see below */ }; struct { UCHAR WaitBlockFill6 [2 * sizeof (KWAIT_BLOCK) + FIELD_OFFSET (KWAIT_BLOCK, SpareLong)]; /* reclaimed 4 bytes, see below */ }; struct { UCHAR WaitBlockFill7 [3 * sizeof (KWAIT_BLOCK) + FIELD_OFFSET (KWAIT_BLOCK, SpareLong)]; /* reclaimed 4 bytes, see below */ }; #endif struct { UCHAR WaitBlockFill8 [FIELD_OFFSET (KWAIT_BLOCK, SparePtr)]; /* reclaimed 4 or 8 bytes, see below */ }; struct { UCHAR WaitBlockFill9 [sizeof (KWAIT_BLOCK) + FIELD_OFFSET (KWAIT_BLOCK, SparePtr)]; /* reclaimed 4 or 8 bytes, see below */ }; struct { UCHAR WaitBlockFill10 [2 * sizeof (KWAIT_BLOCK) + FIELD_OFFSET (KWAIT_BLOCK, SparePtr)]; /* reclaimed 4 or 8 bytes, see below */ }; struct { UCHAR WaitBlockFill11 [3 * sizeof (KWAIT_BLOCK) + FIELD_OFFSET (KWAIT_BLOCK, Object)]; /* reclaimed 8 or 16 bytes, see below */ ;
The KWAIT_BLOCK structure changed for version 6.2. The x86 builds had an explicitly spare byte and the x64 builds had both this and an explicitly spare long. In version 6.2 and higher, both have an explicitly spare pointer and the x64 builds still have the spare long too. With the KTHREAD having four of these structures, packing members into these spares is certainly worthwhile, even if it’s beyond messy. Moroever, for the particular use that the KTHREAD makes of the last KWAIT_BLOCK in the array, the Object member is known to be irrelevant and is therefore also available for reuse.
Disregard all this scaffolding and here are the members that get squeezed in with the WaitBlock array:
Offset (x86) | Offset (x64) | Definition | Versions | Remarks | History |
---|---|---|---|---|---|
0x0154 |
ULONG ContextSwitches; |
6.2 and higher | x86 at 0x8C | previously at 0x0134 | |
0xF4 | 0x0168 |
KTHREAD_COUNTERS *ThreadCounters; |
6.2 and higher | previously at 0x01F4 and 0x0350 | |
0x0184 |
UCHAR volatile State; |
6.2 and higher | x86 at 0x90 | previously at 0x0164 | |
0x0185 |
CHAR NpxState; |
6.2 to 6.3 | x86 at 0x91; next as LONGLONG at 0x0250 |
previously as UCHAR at 0x0165 | |
CHAR Spare13; |
10.0 and higher | ||||
0x0186 |
KIRQL WaitIrql; |
6.2 and higher | x86 at 0x92 | previously at 0x0166 | |
0x0187 |
KPROCESSOR_MODE WaitMode; |
6.2 and higher | x86 at 0x93 | previously at 0x0167 | |
0x010C | 0x0198 |
XSTATE_SAVE *XStateSave; |
6.2 and higher | previously at 0x01F8 and 0x0358 | |
0x01B4 |
ULONG WaitTime; |
6.2 and higher | x86 at 0x0138 | previously at 0x0194 | |
0x0124 | 0x01C8 |
PVOID volatile Win32Thread; |
6.2 and higher | previously at 0x018C and 0x0270 | |
0x01E4 |
union { struct { SHORT KernelApcDisable; SHORT SpecialApcDisable; }; ULONG CombinedApcDisable; }; |
6.2 and higher | x86 at 0x013C | previously at 0x01C4 | |
0x0138 |
ULONG WaitTime; |
6.2 and higher | x64 at 0x01B4 | previously at 0x7C | |
0x01F0 |
UMS_CONTROL_BLOCK *Ucb; |
6.2 and higher | previously at 0x01B8 | ||
0x01F8 |
KUMS_CONTEXT_HEADER *Uch; |
6.2 and higher |
Note that WaitTime is listed twice above. Because it is packed with the spare Object in 32-bit builds but the SpareLong in 64-bit builds, it is ordered differently with respect to Win32Thread. The union of members that count the depth of requests to disable APC delivery is another example that is packed into spare space in the x64 builds (above) but not in the x86 builds (immediately below):
Offset (x86) | Offset (x64) | Definition | Versions | Remarks | History |
---|---|---|---|---|---|
0x013C |
union { struct { SHORT KernelApcDisable; SHORT SpecialApcDisable; }; ULONG CombinedApcDisable; }; |
6.2 and higher | x64 at 0x01E4 | previously at 0x84 | |
0x0200 |
union { LONG volatile ThreadFlags2; struct { /* bit fields, follow link */ }; }; |
2004 and higher | |||
0x0200 (6.2 to 1903); 0x0204 |
PVOID TebMappedLowVa; |
6.2 to 1607 | previously at 0x01B0 | ||
PVOID Spare21; |
1703 to 1903 | ||||
ULONG Spare21; |
2004 and higher | ||||
0x0140 | 0x0208 |
LIST_ENTRY QueueListEntry; |
6.2 and higher | previously at 0x0120 and 0x01C8 | |
0x0148 | 0x0218 |
ULONG volatile NextProcessor; |
6.2 only | previously at 0x58 and 0x7C | |
union { ULONG volatile NextProcessor; struct { ULONG NextProcessorNumber : 31; ULONG SharedReadyQueue : 1; }; }; |
6.3 and higher | ||||
0x014C | 0x021C |
ULONG volatile DeferredProcessor; |
6.2 only | previously at 0x5C and 0x80 | |
LONG QueuePriority; |
6.3 and higher | ||||
0x0150 | 0x0220 |
KPROCESS *Process; |
6.2 and higher | previously at 0x0150 and 0x0210 | |
0x0154 | 0x0228 |
union { GROUP_AFFINITY volatile UserAffinity; /* overlay, see below */ }; |
6.2 and higher | previously without union at 0x0144 and 0x0200 |
Version 6.1, with its support for potentially many more processors, changed UserAffinity and Affinity from KAFFINITY to GROUP_AFFINITY. The latter has six bytes explicitly labelled as Reserved. Version 6.1 doesn’t pack anything into them, but version 6.2 goes all the way. Overlaying UserAffinity is:
struct { UCHAR UserAffinityFill [FIELD_OFFSET (GROUP_AFFINITY, Reserved)]; /* reclaimed 6 bytes, see below */ };
Reclaimed from UserAffinity:
Offset (x86) | Offset (x64) | Definition | Versions | History |
---|---|---|---|---|
0x015A | 0x0232 |
KPROCESSOR_MODE PreviousMode; |
6.2 and higher | previously at 0x013A and 0x01F6 |
0x015B | 0x0233 |
CHAR BasePriority; |
6.2 and higher | previously at 0x0135 and 0x01F1 |
0x015C | 0x0234 |
union { CHAR PriorityDecrement; struct { UCHAR ForegroundBoost : 4; UCHAR UnusualBoost : 4; }; }; |
6.2 and higher | previously at 0x0136 and 0x01F2 |
0x015D | 0x0235 |
BOOLEAN Preempted; |
6.2 and higher | previously at 0x0137 and 0x01F3 |
0x015E | 0x0236 |
UCHAR AdjustReason; |
6.2 and higher | previously at 0x0138 and 0x01F4 |
0x015F | 0x0237 |
CHAR AdjustIncrement; |
6.2 and higher | previously at 0x0139 and 0x01F5 |
Insertion of the AffinityVersion for Windows 10 produces the first change of offset for any KTHREAD member since Windows 8.
Offset (x86) | Offset (x64) | Definition | Versions | History |
---|---|---|---|---|
0x0160 | 0x0238 |
ULONG_PTR AffinityVersion; |
10.0 and higher | |
0x0160 (6.2 to 6.3); 0x0164 |
0x0238 (6.2 to 6.3); 0x0240 |
union { GROUP_AFFINITY volatile Affinity; /* overlay, see below */ }; |
6.2 and higher | previously at 0x0154 and 0x0218 |
Overlaying Affinity:
struct { UCHAR AffinityFill [FIELD_OFFSET (GROUP_AFFINITY, Reserved)]; /* reclaimed 6 bytes, see below */ };
Reclaimed from Affinity:
Offset (x86) | Offset (x64) | Definition | Versions | History |
---|---|---|---|---|
0x0166 (6.2 to 6.3); 0x016A |
0x0242 (6.2 to 6.3); 0x024A |
UCHAR ApcStateIndex; |
6.2 and higher | previously at 0x0134 and 0x01F0 |
0x0167 (6.2 to 6.3); 0x016B |
0x0243 (6.2 to 6.3); 0x024B |
UCHAR WaitBlockCount; |
6.2 and higher | |
0x0168 (6.2 to 6.3); 0x016C |
0x0244 (6.2 to 6.3); 0x024C |
ULONG IdealProcessor; |
6.2 and higher | previously at 0x0160 and 0x0228 |
The KTHREAD keeps two KAPC_STATE structures, the second to support the KeStackAttachProcess function. From as far back as version 3.51, the KTHREAD has initialised its ApcStatePointer array with the addresses of these two structures and then left them there, unchanging, with the (8-bit) ApcStateIndex to select which pointer to use. This always was an extravagance for an implementation that’s supposedly so concerned about space that it fits small members into otherwise unused space in larger members. Windows 10 does away with it.
Offset (x86) | Offset (x64) | Definition | Versions | Remarks | History |
---|---|---|---|---|---|
0x016C (6.2 to 6.3) | 0x0248 (6.2 to 6.3) |
KAPC_STATE *ApcStatePointer [2]; |
6.2 to 6.3 | previously at 0x0168 and 0x0230 | |
0x0250 |
ULONGLONG NpxState; |
10.0 and higher | x86 at 0x0340; previously as CHAR at 0x0185 |
||
0x0170 |
ULONG Spare15 [1]; |
10.0 and higher |
See that Windows 10 inserts members with the effect, if not the intention, of restoring continuity of offsets for the second KAPC_STATE structure and beyond.
Offset (x86) | Offset (x64) | Definition | Versions | History |
---|---|---|---|---|
0x0174 | 0x0258 |
union { KAPC_STATE SavedApcState; /* overlay, see below */ }; |
6.2 and higher | previously at 0x0170 and 0x0240 |
Overlaying the SavedApcState:
struct { UCHAR SavedApcStateFill [KAPC_STATE_ACTUAL_LENGTH]; /* reclaimed, see below */ };
Reclaimed from the SavedApcState:
Offset (x86) | Offset (x64) | Definition | Versions | History |
---|---|---|---|---|
0x018B | 0x0283 |
UCHAR WaitReason; |
6.2 and higher | previously at 0x0187 and 0x026B |
0x018C | 0x0284 |
CHAR SuspendCount; |
6.2 and higher | previously at 0x0188 and 0x026C |
0x018D | 0x0285 |
CHAR Saturation; |
6.2 and higher | previously at 0x013B and 0x01F7 |
0x018E | 0x0286 |
USHORT SListFaultCount; |
6.2 and higher | previously as ULONG at 0x01DC and 0x02D4 |
What had been the SuspendApc (previously at offsets 0x0194 and 0x0280) is renamed to SchedulerApc.
Offset (x86) | Offset (x64) | Definition | Versions |
---|---|---|---|
0x0190 | 0x0288 |
union { KAPC SchedulerApc; /* overlay, see below */ }; |
6.2 and higher |
Overlaying the SchedulerApc:
struct { UCHAR SchedulerApcFill0 [KAPC_OFFSET_TO_SPARE_BYTE0]; /* reclaimed byte, see below */ }; struct { UCHAR SchedulerApcFill1 [KAPC_OFFSET_TO_SPARE_BYTE1]; /* reclaimed byte, see below */ }; struct { UCHAR SchedulerApcFill2 [KAPC_OFFSET_TO_SPARE_LONG]; /* reclaimed four bytes, see below */ }; struct { UCHAR SchedulerApcFill3 [KAPC_OFFSET_TO_SYSTEMARGUMENT1]; /* reclaimed 4 or 8 bytes, see below */ }; struct { UCHAR SchedulerApcFill4 [KAPC_OFFSET_TO_SYSTEMARGUMENT2]; /* reclaimed 4 or 8 bytes, see below */ }; struct { UCHAR SchedulerApcFill5 [KAPC_ACTUAL_LENGTH]; /* reclaimed 1 or 5 bytes, see below) */ };
Whatever its name, its sprinkling of other members in spare space barely changes:
Offset (x86) | Offset (x64) | Definition | Versions | History |
---|---|---|---|---|
0x0191 | 0x0289 |
UCHAR ResourceIndex; |
6.2 and higher | previously at 0x0195 and 0x0281 |
0x0193 | 0x028B |
UCHAR QuantumReset; |
6.2 and higher | previously at 0x0197 and 0x0283 |
0x0194 | 0x028C |
ULONG KernelTime; |
6.2 and higher | previously at 0x0198 and 0x0284 |
0x01B4 | 0x02C8 |
KPRCB * volatile WaitPrcb; |
6.2 and higher | previously at 0x01B8 and 0x02C0 |
0x01B8 | 0x02D0 |
PVOID LegoData; |
6.2 and higher | previously at 0x01BC and 0x02C8 |
0x01BF | 0x02DB |
UCHAR CallbackNestingLevel; |
6.2 and higher | |
0x01C0 | 0x02DC |
ULONG UserTime; |
6.2 and higher | previously at 0x01C4 and 0x02DC |
That’s the end of the contrivances over packing members into space that’s left unused in other members.
Offset (x86) | Offset (x64) | Definition | Versions | Remarks | History |
---|---|---|---|---|---|
0x01C4 | 0x02E0 |
KEVENT SuspendEvent; |
6.2 and higher | ||
0x01D4 | 0x02F8 |
LIST_ENTRY ThreadListEntry; |
6.2 and higher | previously at 0x01E0 and 0x02F8 | |
0x01DC | 0x0308 |
LIST_ENTRY MutantListHead; |
6.2 and higher | last member in 6.2 (x86) | previously at 0x01E8 and 0x0308 |
0x01E4 (6.3) | 0x0318 (6.3) |
SINGLE_LIST_ENTRY LockEntriesFreeList; |
6.3 only | ||
0x01E4 | 0x0318 |
UCHAR AbEntrySummary; |
10.0 and higher | ||
0x01E5 | 0x0319 |
UCHAR AbWaitEntryCount; |
10.0 and higher | previously at 0x032B and 0x058B | |
0x01E6 | 0x031A |
UCHAR AbAllocationRegionCount; |
1703 and higher | ||
0x01E6 (10.0 to 1607); 0x01E7 |
0x031A (10.0 to 1607); 0x031B |
USHORT Spare20; |
10.0 to 1607 | ||
UCHAR Spare20; |
1703 to 1709 | ||||
CHAR SystemPriority; |
1803 and higher | ||||
0x031C |
ULONG SecureThreadCookie; |
10.0 and higher | |||
0x01E8 | 0x0320 |
KLOCK_ENTRY LockEntries [6]; |
6.3 to 1903 | ||
KLOCK_ENTRY *LockEntries; |
2004 and higher | ||||
0x0308 (6.3 to 1903); 0x01EC |
0x0560 (6.3 to 1903); 0x0328 |
SINGLE_LIST_ENTRY PropagateBoostsEntry; |
6.3 and higher | ||
0x030C (6.3 to 1903); 0x01F0 |
0x0568 (6.3 to 1903); 0x0330 |
SINGLE_LIST_ENTRY IoSelfBoostsEntry; |
6.3 and higher | ||
0x0310 (6.3 to 1903); 0x01F4 |
0x0570 (6.3 to 1903); 0x0338 |
UCHAR PriorityFloorCounts [0x10]; |
6.3 and higher | ||
0x0204 | 0x0348 |
UCHAR PriorityFloorCountsReserved [0x10]; |
2004 and higher | ||
0x0320 (6.3 to 1903); 0x0214 |
0x0580 (6.3 to 1903); 0x0358 |
ULONG PriorityFloorSummary; |
6.3 and higher | ||
0x0324 (6.3 to 1903); 0x0218 |
0x0584 (6.3 to 1903); 0x035C |
LONG volatile AbCompletedIoBoostCount; |
6.3 and higher | ||
0x0328 (1607 to 1903); 0x021C |
0x0588 (6.3 to 1903); 0x0360 |
LONG volatile AbCompletedIoQosBoostCount; |
1607 and higher | ||
0x0328 (6.3 to 1511); 0x032C (1607 to 1903); 0x0220 |
0x0588 (6.3 to 1511); 0x058C (1607 to 1903); 0x0364 |
SHORT volatile AbReferenceCount; |
6.3 only | ||
SHORT volatile KeReferenceCount; |
10.0 and higher | ||||
0x032A (6.3 to 1511); 0x032E (1607 to 1903); 0x0222 |
0x058A (6.3 to 1511); 0x058E (1607 to 1903); 0x0366 |
UCHAR AbFreeEntryCount; |
6.3 only | ||
UCHAR AbOrphanedEntrySummary; |
10.0 and higher | ||||
0x032B (6.3 to 1511); 0x032F (1607 to 1903); 0x0223 |
0x058B (6.3 to 1511); 0x058F (1607 to 1903); 0x0367 |
UCHAR AbWaitEntryCount; |
6.3 only | next at 0x01E5 and 0x0319 | |
UCHAR AbOwnedEntryCount; |
10.0 and higher | ||||
0x032C (6.3 to 1511); 0x0330 (1607 to 1903); 0x0224 |
0x058C (6.3 to 1511); 0x0590 (1607 to 1903); 0x0368 |
ULONG ForegroundLossTime; |
6.3 and higher | ||
0x0330 (6.3 to 1511); 0x0334 (1607 to 1903); 0x0228 |
0x0590 (6.3 to 1511); 0x0598 (1607 to 1903); 0x0370 |
union { LIST_ENTRY GlobalForegroundListEntry; struct { SINGLE_LIST_ENTRY ForegroundDpcStackListEntry; ULONG InGlobalForegroundList; }; }; |
6.3 and higher | last member in 6.3 (x86) | |
0x0318 (6.2); 0x05A0 (6.3 to 1511); 0x05A8 (1607 to 1903); 0x0380 |
LONGLONG ReadOperationCount; |
6.2 and higher | previously at 0x0320 | ||
0x0320 (6.2); 0x05A8 (6.3 to 1511); 0x05B0 (1607 to 1903); 0x0388 |
LONGLONG WriteOperationCount; |
6.2 and higher | previously at 0x0328 | ||
0x0328 (6.2); 0x05B0 (6.3 to 1511); 0x05B8 (1607 to 1903); 0x0390 |
LONGLONG OtherOperationCount; |
6.2 and higher | previously at 0x0330 | ||
0x0330 (6.2); 0x05B8 (6.3 to 1511); 0x05C0 (1607 to 1903); 0x0398 |
LONGLONG ReadTransferCount; |
6.2 and higher | previously at 0x0338 | ||
0x0338 (6.2); 0x05C0 (6.3 to 1511); 0x05C8 (1607 to 1903); 0x03A0 |
LONGLONG WriteTransferCount; |
6.2 and higher | previously at 0x0340 | ||
0x0340 (6.2); 0x05C8 (6.3 to 1511); 0x05D0 (1607 to 1903); 0x03A8 |
LONGLONG OtherTransferCount; |
6.2 and higher | last member in 6.2 to 6.3 (x64) | previously at 0x0348 |
Offset (x86) | Offset (x64) | Definition | Versions | Remarks |
---|---|---|---|---|
0x0338 (10.0 to 1511); 0x033C (1607 to 1903); 0x0230 |
0x05D0 (10.0 to 1511); 0x05D8 (1607 to 1903); 0x03B0 |
KSCB *QueuedScb; |
10.0 and higher | last member in 10.0 to 1607 (x64) |
0x0340 (10.0 to 1903); 0x0238 |
ULONGLONG NpxState; |
10.0 and higher | x64 at 0x0250; previously as CHAR at 0x91; last member in 10.0 to 1607 (x86) |
|
0x0348 (1703 to 1903); 0x0240 |
0x05E0 (1703 to 1903); 0x03B8 |
ULONG volatile ThreadTimerDelay; |
1703 and higher | last member in 1703 (x86) |
0x05E4 (1703) |
LONG Spare22; |
1703 only | last member in 1703 (x64) | |
0x034C (1709 to 1903); 0x0244 |
0x05E4 (1709 to 1903); 0x03BC |
union { LONG volatile ThreadFlags2; struct { /* bit fields, follow link */ }; }; |
1709 to 1903 | last member in 1709 to 1809 (x86) |
union { LONG volatile ThreadFlags3; struct { /* bit fields, follow link */ }; }; |
2004 and higher | |||
0x05E8 (1903); 0x03C0 |
ULONGLONG TracingPrivate [1]; |
1903 and higher | ||
0x05E8 (1709 to 1809); 0x05F0 (1903); 0x03C8 |
PVOID SchedulerAssist; |
1709 and higher | last member in 1709 to 1809 (x64) | |
0x0350 (1903); 0x0248 |
0x05F8 (1903); 0x03D0 |
PVOID volatile AbWaitObject; |
1903 and higher | last member in 1903 |
0x024C | 0x03D8 |
ULONG ReservedPreviouslyReadyTimeValue; |
2004 and higher | |
0x0250 | 0x03E0 |
ULONGLONG KernelWaitTime; |
2004 and higher | |
0x0258 | 0x03E8 |
ULONGLONG UserWaitTime; |
2004 and higher | |
0x03F0 |
union { LIST_ENTRY GlobalUpdateVpThreadPriorityListEntry; struct { SINGLE_LIST_ENTRY UpdateVpThreadPriorityDpcStackListEntry; ULONGLONG InGlobalUpdateVpThreadPriorityList; }; }; |
2004 and higher | ||
0x0400 |
LONG SchedulerAssistPriorityFloor; |
2004 and higher | ||
0x0404 |
ULONG Spare28; |
2004 and higher | ||
0x0260 |
ULONG Spare29 [3]; |
2004 and higher | ||
0x026C | 0x0408 |
ULONG_PTR EndPadding [5]; |
2004 and higher | last member in 2004 |