MMPAGING_FILE

The MMPAGING_FILE structure either holds or points the way to pretty much everything that the kernel’s Memory Manager tracks about a paging file.

Variability

As an internal structure, the MMPAGING_FILE varies between versions, but far less than do many others and apparently never between builds of the one version. The changing size gives a rough guide to the variability:

Version Size (x86) Size (x64)
3.51 to 5.0 0x40  
5.1 0x44  
5.2 0x3C 0x78
6.0 0x50 0xA0
6.1 0x50 0x90
6.2 0x64 0xA8
6.3 0x80 0xE0
10.0 0x90 0x0100

Layout

These sizes, and the offsets, types and names in the tables that follow, are from Microsoft’s symbol files for the kernel starting with Windows 2000 SP3. Since symbol files for earlier versions do not contain type information for the MMPAGING_FILE, what’s known for them is instead inferred from what use the kernel is seen to make of the MMPAGING_FILE. Sizes are relatively straightforward, even without symbol files, but Microsoft’s names and types for all the members in these early versions can be something of a guess.

Offset (x86) Offset (x64) Definition Versions Remarks
0x00 0x00
ULONG_PTR Size;
3.51 and higher  
0x04 0x08
ULONG_PTR MaximumSize;
3.51 and higher  
0x08 0x10
ULONG_PTR MinimumSize;
3.51 and higher  
0x0C 0x18
ULONG_PTR FreeSpace;
3.51 and higher  
0x10 (3.51 to 5.2) 0x20 (5.2)
ULONG CurrentUsage;
3.51 to 5.2  
0x14 (3.51 to 5.2);
0x10
0x28 (5.2);
0x20
ULONG_PTR PeakUsage;
3.51 and higher  
0x18 (3.51 to 5.1)  
ULONG Hint;
3.51 to 5.1  
0x1C (3.51 to 5.1);
0x18 (5.2);
0x14
0x30 (5.2);
0x28
ULONG_PTR HighestPage;
3.51 and higher  
0x18 0x30
ULONG_PTR FreeReservationSpace;
6.2 and higher  
0x1C 0x38
ULONG_PTR LargestReserveCluster;
6.2 and higher  
0x1C (5.2);
0x18 (6.0 to 6.1);
0x20
0x38 (5.2);
0x30 (6.0 to 6.1);
0x40
FILE_OBJECT *File;
5.2 and higher previously at 0x2C
0x20 (3.51 to 5.2);
0x1C (6.0 to 6.1);
0x24
0x40 (5.2);
0x38 (6.0 to 6.1);
0x48
MMMOD_WRITER_MDL_ENTRY *Entry [2];
3.51 and higher  
0x28 (3.51 to 5.1)  
RTL_BITMAP *Bitmap;
3.51 to 5.1 next at 0x30
0x2C (3.51 to 5.1)  
FILE_OBJECT *File;
3.51 to 5.1 next at 0x1C
0x30 (3.51 to 4.0)  
ULONG PageFileNumber;
3.51 to 4.0 next at 0x38
0x30 0x60
SLIST_HEADER PfnsToFree;
6.3 and higher  
0x34 (3.51 to 4.0);
0x30 (5.0 to 5.1);
0x28 (5.2);
0x24 (6.0 to 6.1);
0x2C (6.2);
0x38
0x50 (5.2);
0x48 (6.0 to 6.1);
0x58 (6.2);
0x70
UNICODE_STRING PageFileName;
5.0 and higher  
0x30 (5.2);
0x2C (6.0 to 6.1)
0x60 (5.2);
0x58 (6.0 to 6.1)
RTL_BITMAP *Bitmap;
5.2 to 6.1 previously at 0x28
0x30 (6.1) 0x60 (6.1)
RTL_BITMAP *EvictStoreBitmap;
6.1 only  
0x34 (6.2);
0x40
0x68 (6.2);
0x80
MI_PAGING_FILE_SPACE_BITMAPS *Bitmaps;
6.2 and higher  
0x30 (6.0);
0x34 (6.1);
0x38 (6.2);
0x44
0x60 (6.0);
0x68 (6.1);
0x70 (6.2);
0x88
ULONG BitmapHint;
6.0 to 6.1  
ULONG AllocationBitmapHint;
6.2 and higher  
0x3C (6.2);
0x48
0x74 (6.2);
0x8C
ULONG ReservationBitmapHint;
6.2 and higher  
0x34 (6.0);
0x38 (6.1)
0x64 (6.0);
0x6C (6.1)
ULONG LastAllocationSize;
6.0 to 6.1  
0x40 (6.2);
0x4C
0x78 (6.2);
0x90
ULONG LargestNonReservedClusterSize;
6.2 and higher  
0x44 (6.2);
0x50
0x7C (6.2);
0x94
ULONG RefreshClusterSize;
6.2 and higher  
0x48 (6.2);
0x54
0x80 (6.2);
0x98
ULONG LastRefreshClusterSize;
6.2 and higher  
0x4C (6.2);
0x58
0x84 (6.2);
0x9C
ULONG ReservedClusterSizeAggregate;
6.2 and higher  
0x3C (6.1);
0x50 (6.2);
0x5C
0x70 (6.1);
0x88 (6.2);
0xA0
ULONG ToBeEvictedCount;
6.1 to 6.3  
union {
    ULONG ToBeEvictedCount;
    ULONG HybridPriority;
};
10.0 and higher  
0x60 (6.3) 0xA4 (6.3)
ULONG HybridPriority;
6.3 only  
0x38 (5.0 to 5.1);
0x34 (5.2);
0x38 (6.0);
0x40 (6.1);
0x54 (6.2);
0x64 (6.3);
0x60
 
ULONG PageFileNumber;
5.0 to 5.1 previously at 0x30;
next as bit field
0x68 (5.2);
0x68 (6.0);
0x74 (6.1);
0x8C (6.2);
0xA8 (6.3);
0xA4
/*  ULONG bit fields, see below  */
5.2 only  
/*  USHORT bit fields, see below  */
6.0 and higher  
0x3A (6.0);
0x42 (6.1);
0x56 (6.2);
0x66 (6.3);
0x62
0x6A (6.0);
0x76 (6.1);
0x8E (6.2);
0xAA (6.3);
0xA6
 struct {
    USHORT AdriftMdls : 1;
    USHORT Spare1 : 15;
};
6.0 to 6.1  
struct {
    UCHAR AdriftMdls : 1;
    UCHAR Spare1 : 7;
};
6.2 and higher  
0x57 (6.2);
0x67 (6.3);
0x63
0x8F (6.2);
0xAB (6.3);
0xA7
UCHAR Spare2 : 8;
6.2 and higher  
0x3C (3.51 to 5.1)  
UCHAR Extended;
3.51 to 5.1  
0x3D (3.51 to 5.1)  
UCHAR HintSetToZero;
3.51 to 5.1  
0x3E (5.1)  
BOOLEAN BootPartition;
5.1 only next as bit field at 0x34
0x68 (6.3);
0x64
0xAC (6.3);
0xA8
ULONG PageHashPages;
6.3 and higher  
0x6C (6.3);
0x68
0xB0 (6.3);
0xAC
ULONG PageHashPagesPeak;
6.3 and higher  
0x70 (6.3);
0x6C
0xB8 (6.3);
0xB0
ULONG *PageHash;
6.3 and higher  
0x40 (5.1);
0x38 (5.2);
0x3C (6.0);
0x44 (6.1);
0x58 (6.2);
0x74 (6.3);
0x70
0x70 (5.2 to 6.0);
0x78 (6.1);
0x90 (6.2);
0xC0 (6.3);
0xB8
HANDLE FileHandle;
5.1 and higher  
0x40 (6.0) 0x80 (6.0)
SLIST_HEADER AvailableList;
6.0 only  
0x48 (6.0) 0x90 (6.0)
SLIST_HEADER NeedProcessingList;
6.0 only  
0x48 (6.1);
0x5C (6.2);
0x78 (6.3);
0x74
0x80 (6.1);
0x98 (6.2);
0xC8 (6.3);
0xC0
KSPIN_LOCK Lock;
6.1 and higher  
0x4C (6.1);
0x60 (6.2);
0x7C (6.3);
0x78
0x88 (6.1);
0xA0 (6.2);
0xD0 (6.3);
0xC8
ETHREAD *LockOwner;
6.1 and higher  
0x7C 0xD0
RTL_AVL_TREE FlowThroughReadRoot;
10.0 and higher  
0x80 0xD8
MI_PARTITION *Partition;
10.0 and higher  
0x84 0xE0
RTL_BALANCED_NODE FileObjectNode;
10.0 and higher  

The MMPAGING_FILE is in non-paged pool, of course—and, starting with version 6.2, in non-paged no-execute pool. So too are various helper structures, e.g., those for the Entry array and the various bitmaps. The paging file’s name, however, is not accessed during paging I/O. It is kept just for information. The Buffer in PageFileName is in paged pool. Moreover, it just records what filename was given to the NtCreatePagingFile that created this MMPAGING_FILE. This filename need not still be valid when inspected later.

Bit Fields

Even now that Windows 10 has an array of MMPAGING_FILE pointers for each memory partition, each array still has the age-old capacity of 0x10. To allow 32 bits for the PageFileNumber, which indexes the array, always was excessive and the opportunity was eventually taken to make bit fields of both it and the boolean BootPartition.

Mask Definition Versions Remarks
0x000F
ULONG PageFileNumber : 4;
5.2 only previously ULONG at 0x38
USHORT PageFileNumber : 4;
6.0 and higher  
0x00F0
ULONG ReferenceCount : 4;
5.2 only  
0x0100 (5.2);
0x0010 (6.0 to 6.3)
ULONG BootPartition : 1;
5.2 only previously BOOLEAN at 0x3E
USHORT BootPartition : 1;
6.0 to 6.3  
0x0020 (6.2 to 6.3);
0x0010
USHORT WsSwapPagefile : 1;
6.2 and higher  
0x0040 (6.2 to 6.3);
0x0020
USHORT NoReservations : 1;
6.2 and higher  
0x0040
USHORT VirtualStorePagefile : 1;
10.0 and higher  
0x0080
USHORT SwapSupported : 1;
10.0 and higher  
0x0100
USHORT NodeInserted : 1;
10.0 and higher  
0x0200
USHORT StackNotified : 1;
10.0 and higher  
 
ULONG Reserved : 23;
5.2 only  
USHORT Spare0 : 11;
6.0 to 6.1  
USHORT Spare0 : 9;
6.2 to 6.3  
USHORT Spare0 : 5;
10.0 and higher