MI_USER_VA_INFO

The MI_USER_VA_INFO structure (formally _MI_USER_VA_INFO) is a vital part of the implementation of the Working Set List (WSL) in Windows 8 and higher. Indeed, it’s the largest and most complex of all the implementation’s structures. Some measure of its importance as an implementation detail—or its deserved obscurity, depending on perspective—is that the MI_USER_VA_INFO disappears entirely from Microsoft’s public symbol files for the 1607 release of Windows 10, and is not known in any since.

History

From all the way back at Windows NT 3.1, the Working Set List is modelled by the MMWSL structure. Each process has one, pointed to by the VmWorkingSetList member of the MMSUPPORT that’s nested in the EPROCESS as the latter’s Vm member.

The MI_USER_VA_INFO looks to have been introduced to tidy the implementation of the Working Set List in Windows 8. An assortment of MMWSL members, some long-standing and some very large, were collected into the new structure as a new member named UserVaInfo at the end of the MMWSL. The splitting of the MMWSL for the 1607 release of Windows 10, into an MMWSL_INSTANCE and MMWSL_SHARED, also split off the MI_USER_VA_INFO: it is not nested in either. Better, perhaps, would be to say the MMWSL was split in three.

In the 1607 release itself, the MI_USER_VA_INFO precedes the MMWSL_FULL (which in turn has the Instance and Shared parts). All these parts of the Working Set List are in hyperspace, as for earlier versions. For 32-bit Windows, hyperspace continues to have the fixed address 0xC0800000 and the MI_USER_VA_INFO has the fixed address 0xC0802000. For 64-bit Windows, however, the 1607 release allows that hyperspace can vary. What can be said in common about the positioning of the MI_USER_VA_INFO is that it has a fixed offset into hyperspace: 0x2000 and 0x10804000 bytes in 32-bit and 64-bit Windows, respectively.

The 1703 release reverses the order: the MI_USER_VA_INFO begins immediately where the MMWSL_INSTANCE ends. Neither is in hyperspace. Both are instead in one allocation of non-paged pool. The MMWSL_INSTANCE at its start is pointed to from the VmWorkingSetList member of the MMSUPPORT_FULL structure that is embedded in the EPROCESS as its Vm member.

Variability

As an internal structure with little, if any, visibility outside the kernel, the MI_USER_VA_INFO varies greatly between versions and even between builds. The following changes of size give a rough measure of this variability so far:

Version Size (x86) Size (x64)
6.2 0x0CFC 0x0478
6.3 0x0D1C 0x0128
10.0 0x0D20 0x0108
1511 0x0D48 0x0158
1607 0x0D50 0x0168
1703 to 1709 0x0D58 0x0178
1803 0x0F68 0x01E8
1809 0x0F78 0x0208
1903 to 2004 0x0F80 0x0248

The size for the 1607 release of 64-bit Windows is uncertain. The kernel’s own use that is yet known reaches up to but not including offset 0x0164. With 8-byte alignment the structure then is 0x0168 bytes. But the MMWSL_FULL that follows the structure is at offset 0x0170. In the difference may be use that is not yet accounted for. What is here thought more likely is that the MMWSL_FULL has 16-byte alignment, apparently picked up from its nesting of MMWSL_SHARED.

Layout

These sizes, and the offsets, names and types in the tables that follow, are from Microsoft’s symbol files for the kernel from version 6.2 up to and includng the 1511 release of Windows 10. What’s known for later versions is something of a guess, or at least a work in progress, pending discovery of type information in public symbol files (or some similarly authoritative but public disclosure).

Offset (x86) Offset (x64) Definition Versions Remarks
0x00 (6.2 to 1607) 0x00 (6.2 to 1607)
ULONG NumberOfCommittedPageTables;
6.2 to 1607 previously at 0x20 and 0x28 in MMWSL
0x04 (6.2 to 6.3) 0x04 (6.2 to 6.3)
ULONG PhysicalMappingCount;
6.2 to 6.3 next at 0x24 and 0x28
0x08 (6.2 to 6.3);
0x04 (10.0)
0x08 (6.2 to 6.3);
0x04 (10.0)
ULONG VadBitMapHint;
6.2 to 10.0 previously at 0x24 and 0x2C in MMWSL
0x0C (6.2 to 6.3);
0x08 (10.0)
0x0C (6.2 to 6.3);
0x08 (10.0)
ULONG LastAllocationSizeHint;
6.2 to 10.0 previously at 0x34 and 0x3C in MMWSL
0x10 (6.2 to 6.3);
0x0C (10.0)
0x10 (6.2 to 6.3);
0x0C (10.0)
ULONG LastAllocationSize;
6.2 to 10.0 previously at 0x38 and 0x40 in MMWSL
0x14 (6.2 to 6.3);
0x10 (10.0)
0x14 (6.2 to 6.3);
0x10 (10.0)
ULONG LowestBottomUpVadBit;
6.2 to 10.0  
0x18 (6.2 to 6.3);
0x14 (10.0)
0x18 (6.2 to 6.3);
0x14 (10.0)
ULONG VadBitMapSize;
6.2 to 10.0  
0x04 (1511 to 1607);
0x00 (1703 to 1709)
0x08 (1511 to 1607);
0x00 (1703 to 1709)
PVOID HighestTopDownAllocationAddress;
1511 to 1709 previously at 0x34 and 0x48
  0x00 unaccounted eight bytes 1803 and higher  
0x08 (1511 to 1607);
0x04 (1703 to 1709);
0x00
0x10 (1511 to 1607);
0x08
MI_VAD_ALLOCATION_CELL VadCell [MiVadAllocationCellMaximum];
1511 and higher  
0x48 0xB0 (1803 to 1809);
0xE0
unknown ULONG 1803 to 1809  
unknown ULONG_PTR 1903 and higher
0x1C (6.3);
0x18 (10.0);
0x40 (1511 to 1607);
0x3C (1703 to 1709);
0x4C
0x1C (6.3);
0x18 (10.0);
0x60 (1511 to 1607);
0x58 (1703 to 1709);
0xB4 (1803 to 1809);
0xE8
ULONG VadBitMapCommitment;
6.3 to 1809  
ULONG_PTR VadBitMapCommitment;
1903 and higher
0x1C (6.2);
0x20 (6.3);
0x1C (10.0);
0x44 (1511 to 1607);
0x40 (1703 to 1709)
0x1C (6.2);
0x20 (6.3);
0x1C (10.0);
0x64 (1511 to 1607);
0x5C (1703 to 1709)
ULONG MaximumLastVadBit;
6.2 to 1709 previously at 0x30 and 0x38 in MMWSL
0x20 (6.2);
0x24 (6.3);
0x20 (10.0);
0x48 (1511 to 1607);
0x44 (1703 to 1709);
0x50
0x20 (6.2);
0x24 (6.3);
0x20 (10.0);
0x68 (1511 to 1607);
0x60 (1703 to 1709);
0xB8 (1803 to 1809);
0xF0
LONG VadsBeingDeleted;
6.2 and higher  
0x48 (1703 to 1709);
0x54
0x64 (1703 to 1709);
0xBC (1803 to 1809);
0xF4
unaccounted four bytes 1703 and higher  
  0xF8 unaccounted eight bytes 1903 and higher  
0x4C (1511 to 1709);
0x58
0x6C (1511 to 1607);
0x68 (1703 to 1709);
0xC0 (1803 to 1809);
0x0100
LONG NumberOfDebugEnclaves;
1511 and higher  
0x24 (10.0);
0x50 (1511 to 1709);
0x5C
0x28 (10.0);
0x70 (1511 to 1709);
0xC8 (1803 to 1809);
0x0108
ULONG_PTR PhysicalMappingCount;
10.0 and higher previously at 0x04
0x24 (6.2);
0x28 (6.3 to 10.0);
0x54 (1511 to 1709);
0x60
0x28 (6.2 to 6.3);
0x30 (10.0);
0x78 (1511 to 1709);
0xD0 (1803 to 1809);
0x0110
KEVENT *LastVadDeletionEvent;
6.2 and higher  
0x28 (6.2);
0x2C (6.3 to 10.0)
0x30 (6.2 to 6.3);
0x38 (10.0)
ULONG *VadBitBuffer;
6.2 to 10.0  
0x2C (6.2);
0x30 (6.3 to 10.0)
0x38 (6.2 to 6.3);
0x40 (10.0)
PVOID LowestBottomUpAllocationAddress;
6.2 to 10.0  
0x30 (6.2);
0x34 (6.3 to 10.0)
0x40 (6.2 to 6.3);
0x48 (10.0)
PVOID HighestTopDownAllocationAddress;
6.2 to 10.0 next at 0x04 and 0x08
0x34 (6.2);
0x38 (6.3 to 10.0)
0x48 (6.2 to 6.3);
0x50 (10.0)
PVOID FreeTebHint;
6.2 to 10.0  
0x58 (1511 to 1709);
0x64
0x80 (1511 to 1709);
0xD8 (1803 to 1809);
0x0118
LIST_ENTRY SubVadRanges [1];
1511 to 1607 (x86)  
LIST_ENTRY SubVadRanges [2];
1703 to 1803 (x86)  
LIST_ENTRY SubVadRanges [1];
1809 and higher (x86)  
LIST_ENTRY SubVadRanges [3];
1511 to 1607 (x64)  
LIST_ENTRY SubVadRanges [4];
1703 to 1803 (x64)  
LIST_ENTRY SubVadRanges [2];
1809 and higher (x64)  
0x3C (6.3 to 10.0);
0x60 (1511 to 1607);
0x68 (1703 to 1709);
0x74 (1803);
0x6C
0x50 (6.3);
0x58 (10.0);
0xB0 (1511 to 1607);
0xC0 (1703 to 1709);
0x0118 (1803);
0x0108 (1809);
0x0138
BOOLEAN NumaAware;
6.3 and higher  
0x40 (10.0);
0x68 (1511 to 1607);
0x70 (1703 to 1709);
0x78 (1803);
0x70
0x60 (10.0);
0xB8 (1511 to 1607);
0xC8 (1703 to 1709);
0x0120 (1803);
0x0110 (1809);
0x0140
ULONGLONG CloneNestingLevel;
10.0 and higher  
0x80 (1803);
0x78
0x0128 (1803);
0x0118 (1809);
0x0148
unknown SLIST_HEADER 1803 and higher  
0x38 (6.2);
0x40 (6.3);
0x48 (10.0);
0x70 (1511 to 1607);
0x78 (1703 to 1709);
0x88 (1803);
0x80
0x50 (6.2);
0x58 (6.3);
0x68 (10.0);
0xC0 (1511 to 1607);
0xD0 (1703 to 1709);
0x0138 (1803);
0x0128 (1809);
0x0158
ULONG_PTR PrivateFixupVadCount;
6.2 and higher  
  0x58 (6.2)
PVOID FreeUmsTebHint;
6.2 only next at 0x0120
0x84 0x0130 (1809);
0x0160
unknown pointer-sized integer 1809 and higher nd higher  
0x88 0x0138 (1809);
0x0168
unknown pointer 1809 and higher  
0x8C 0x0170 unknown EX_PUSH_LOCK_AUTO_EXPAND 1809 and higher  
0x74 (1607);
0x7C (1703 to 1709);
0x8C (1803);
0x98
0xC8 (1607);
0xD8 (1703 to 1709);
0x0140 (1803);
0x0150 (1809);
0x0180
unknown ULONG_PTR count 1607 and higher  
0x78 (1607);
0x80 (1703 to 1709);
0x90 (1803);
0x9C
0xD0 (1607);
0xE0 (1703 to 1709);
0x0148 (1803);
0x0158 (1809);
0x0188
unknown ULONG_PTR count 1607 and higher  
0x44 (6.3);
0x4C (10.0);
0x74 (1511);
0x7C (1607);
0x84 (1703 to 1709);
0x94 (1803);
0xA0
0x60 (6.3);
0x70 (10.0);
0xC8 (1511);
0xD8 (1607);
0xE8 0x0150 (1803);
0x0160 (1809);
0x0190
MI_CFG_BITMAP_INFO CfgBitMap [CfgBitMapMax - 1];
6.3 and higher  
0x54 (6.3);
0x58 (10.0);
0x80 (1511);
0x88 (1607);
0x90 (1703 to 1709);
0xA0 (1803);
0xB0
0xC0 (6.3);
0xA0 (10.0);
0xF8 (1511);
0x0108 (1607);
0x0118 (1703 to 1709);
0x0180 (1803);
0x01A0 (1809);
0x01D0
ULONG CommittedPageTableBufferForTopLevel [0x30];
6.3 and higher (x86)  
ULONG CommittedPageTableBufferForTopLevel [8];
6.3 and higher (x64)  
0x0114 (6.3);
0x0118 (10.0);
0x0140 (1511);
0x0148 (1607);
0x0150 (1703 to 1709);
0x0160 (1803);
0x0170
0xE0 (6.3);
0xC0 (10.0);
0x0118 (1511);
0x0128 (1607);
0x0138 (1703 to 1709);
0x01A0 (1803);
0x01C0 (1809);
0x01F0
RTL_BITMAP CommittedPageTableBitmaps [1];
6.3 and higher (x86)  
RTL_BITMAP CommittedPageTableBitmaps [3];
6.3 to 1809 (x64)  
RTL_BITMAP_EX CommittedPageTableBitmaps [3];
1903 and higher  
0x3C (6.2);
0x011C (6.3);
0x0120 (10.0);
0x0148 (1511);
0x0150 (1607);
0x0158 1703 to 1709);
0x0168 (1803);
0x0178
 
USHORT UsedPageTableEntries [0x0600]; [0x0600];
6.2 to 1703 previously at 0x48 in MMWSL
0x0C3C (6.2) 0x60 (6.2)
ULONG CommittedPageTables [0x30];
6.2 only (x86) previously at 0x0C48 in MMWSL
ULONG *CommittedPageTables;
6.2 only (x64) previously at 0x68 in MMWSL
  0x68 (6.2);
0x0110 (6.3);
0xF0 (10.0);
0x0148 (1511);
0x0158 (1607);
0x0168 (1703 to 1709);
0x01D0 (1803);
0x01F0 (1809);
0x0224
ULONG PageTableBitmapPages;
6.2 only  
ULONG PageTableBitmapPages [3];
10.0 and higher  
  0x70
ULONGLONG CommitedPageDirectories [0x80];
6.2 only previously at 0x78 in MMWSL
  0x0470
ULONGLONG CommitedPageDirectoryParents [1];
6.2 only previously at 0x0480 in MMWSL
  0x0120 (6.3);
0x0100
PVOID FreeUmsTebHint;
6.3 to 10.0 previously at 0x58
  0x01E0 (1803);
0x0200 (1809);
0x0230
unaccounted eight bytes 1803 and higher  
  0x0238 unknown pointer 1903 and higher  
0x0F78 0x0240 unknown 64-bit count 1903 and higher  

The CfgBitMap member is indexed by the MI_CFG_BITMAP_TYPE enumeration. Its first element is for native addressing. This is the only element in 32-bit Windows but 64-bit Windows has a second for the 32-bit address space of WOW64 processes.