KTHREAD

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. Some sense of the variability can be gained just from the structure’s changing size. In the following table, different builds of the same version are distinguished as early, late and even very late because they are known to vary the structure even if they don’t change the size. These descriptions are then used as a shorthand throughout this article and its companions.

Version Size (x86) Size (x64)
3.10 0x01D8  
3.50 to 5.0 0x01B0  
5.1 0x01C0  
early 5.2 (before Windows Server 2003 SP1) 0x01C8  
late 5.2 (Windows Server 2003 SP1) 0x01B8 0x0320
very late 5.2 (Windows Server 2003 SP2) 0x01B8 0x0308
early 6.0 (before Windows Vista SP1);
late 6.0 (Windows Vista SP1 and higher)
0x01E0 0x0330
6.1 0x0200 0x0360
6.2 0x01E8 0x0348
6.3 0x0338 0x05D0
10.0 0x0348 0x05D8

Unfortunately for the editorial matter of tracking changes within the structure, these changes of size don’t begin to convey the changes inside the structure. Among undocumented kernel-mode structures, and certainly the most important ones, the KTHREAD stands out for having been treated multiple times to large-scale rearrangements in which members are brought together from opposite ends of the structure only to have the next build scatter them again. These notes track the earlier versions separately:

The rest of this article is specific to versions 6.2 and higher.

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 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.

Layout

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 Remarks 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 x86 only previously at 0x18
0x3C  
PVOID ServiceTable;
6.2 and higher x86 only 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
ULONG Spare0;
6.2 to 6.3    
UCHAR volatile Tag;
10.0 and higher    
0x61 0x7D
UCHAR SystemHeteroCpuPolicy;
10.0 and higher    
0x62 0x7E
union {
    UCHAR UserHeteroCpuPolicy : 7;
    UCHAR ExplicitSystemHeteroCpuPolicy : 1;
};
10.0 and higher    
0x63 0x7F
UCHAR Spare0;
10.0 and higher    
0x64 0x80
ULONG SystemCallNumber;
6.2 and higher   previously at 0x013C and 0x01F8
  0x84
ULONG Spare1;
6.2 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 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 *Queue;
6.2 and higher   previously at 0x7C and 0xB0
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 are a succession of structures that pad 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 [FIELD_OFFSET (KWAIT_BLOCK, SpareLong) + sizeof (KWAIT_BLOCK)];
    /*  reclaimed 4 bytes, see below  */
};
struct {
    UCHAR WaitBlockFill6 [FIELD_OFFSET (KWAIT_BLOCK, SpareLong) + 2 * sizeof (KWAIT_BLOCK)];
    /*  reclaimed 4 bytes, see below  */
};
struct {
    UCHAR WaitBlockFill7 [FIELD_OFFSET (KWAIT_BLOCK, SpareLong) + 3 * sizeof (KWAIT_BLOCK)];
    /*  reclaimed 4 bytes, see below  */
};
#endif
struct {
    UCHAR WaitBlockFill8 [FIELD_OFFSET (KWAIT_BLOCK, SparePtr)];
    /*  reclaimed 4 or 8 bytes, see below  */
};
struct {
    UCHAR WaitBlockFill9 [FIELD_OFFSET (KWAIT_BLOCK, SparePtr) + sizeof (KWAIT_BLOCK)];
    /*  reclaimed 4 or 8 bytes, see below  */
};
struct {
    UCHAR WaitBlockFill10 [FIELD_OFFSET (KWAIT_BLOCK, SparePtr) + 2 * sizeof (KWAIT_BLOCK)];
    /*  reclaimed 4 or 8 bytes, see below  */
};
struct {
    UCHAR WaitBlockFill11 [FIELD_OFFSET (KWAIT_BLOCK, Object) + 3 * sizeof (KWAIT_BLOCK)];
    /*  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 x64 only previously at 0x01B8
  0x01F8
KUMS_CONTEXT_HEADER *Uch;
6.2 and higher x64 only  

Note that WaitTime is listed twice above. Because it is packed with the spare object in 32-bit builds but the spare long 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 but not in the x86 builds:

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
PVOID TebMappedLowVa;
6.2 and higher x64 only previously at 0x01B0
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 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
0x0170  
ULONG Spare15 [1];
10.0 and higher    
  0x0250
LONGLONG NpxState;
10.0 and higher x86 at 0x0340;
previously as CHAR at 0x0185
 

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
PVOID 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
USHORT Spare20;
10.0 and higher    
  0x031C
ULONG SecureThreadCookie;
10.0 and higher    
0x01E8 0x0320
KLOCK_ENTRY LockEntries [6];
6.3 and higher    
0x0308 0x0560
SINGLE_LIST_ENTRY PropagateBoostsEntry;
6.3 and higher    
0x030C 0x0568
SINGLE_LIST_ENTRY IoSelfBoostsEntry;
6.3 and higher    
0x0310 0x0570
UCHAR PriorityFloorCounts [0x10];
6.3 and higher    
0x0320 0x0580
ULONG PriorityFloorSummary;
6.3 and higher    
0x0324 0x0584
LONG volatile AbCompletedIoBoostCount;
6.3 and higher    
0x0328 0x0588
SHORT volatile AbReferenceCount;
6.3 only    
SHORT volatile KeReferenceCount;
10.0 and higher    
0x032A 0x058A
UCHAR AbFreeEntryCount;
6.3 only    
UCHAR AbOrphanedEntrySummary;
10.0 and higher    
0x032B 0x058B
UCHAR AbWaitEntryCount;
6.3 only next at 0x01E5 and 0x0319  
UCHAR AbOwnedEntryCount;
10.0 and higher    
0x032C 0x058C
ULONG ForegroundLossTime;
6.3 and higher    
0x0330 0x0590
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
LONGLONG ReadOperationCount;
6.2 and higher x64 only previously at 0x0320
  0x0320 (6.2);
0x05A8
LONGLONG WriteOperationCount;
6.2 and higher x64 only previously at 0x0328
  0x0328 (6.2);
0x05B0
LONGLONG OtherOperationCount;
6.2 and higher x64 only previously at 0x0330
  0x0330 (6.2);
0x05B8
LONGLONG ReadTransferCount;
6.2 and higher x64 only previously at 0x0338
  0x0338 (6.2);
0x05C0
LONGLONG WriteTransferCount;
6.2 and higher x64 only previously at 0x0340
  0x0340 (6.2);
0x05C8
LONGLONG OtherTransferCount;
6.2 and higher x64 only;
last member in 6.2 (x64);
last member in 6.3 (x64)
previously at 0x0348
0x0338  
KSCB *QueuedScb;
10.0 and higher last member in 10.0 (x64)  
0x0340  
LONGLONG NpxState;
10.0 and higher x64 at 0x0250;
previously as CHAR at 0x91;
last member in 10.0 (x86)