MMPFNLIST

For each physical page that’s in general use, the kernel keeps one MMPFN structure. For each physical page that’s not in active use (or at least in transition to or from active use), the MMPFN goes into one or another list. The MMPFNLIST structure (formally _MMPFNLIST) is the list head.

Before Windows 10, the list heads are internal variables in the kernel’s data. In Windows 10 and higher, with physical memory in separate partitions, the list heads are the PageLists and Vp members of an MI_PARTITION structure.

The MMPFNLIST structure is 0x14 or 0x28 bytes in 32-bit and 64-bit Windows 10, respectively, since its one change for Windows 7. In earlier versions it is 0x10 or 0x20 bytes.

Offset (x86) Offset (x64) Definition Versions
0x00 0x00
ULONG_PTR Total;
all
0x04 0x08
MMLISTS ListName;
all
0x08 0x10
PFN_NUMBER Flink;
all
0x0C 0x18
PFN_NUMBER Blink;
all
0x10 0x20
ULONG_PTR Lock;
6.1 and higher

The Total is of pages in the list. The ListName has long been only a rough classification of the list’s purpose. In early versions, the kernel has six lists among its internal variables, each with a unique ListName. Only in version 3.10 does each list have its own ListName. Version 5.0 added a second list that shares StandbyPageList for its ListName. Ever since, the ListName is arguably more a list type.

The kernel keeps all MMPFN structures in an array that is indexed by the Page Frame Number (PFN) of the corresponding pages of physical memory. For each page that’s in a list, the MMPFN has its Flink and Blink members set to the PFN of the next and previous page, respectively, or to a terminating value if the page is at the tail or head. The terminator varies with the version:

x86 x64 Version
0xFFFFFFFF 0xFFFFFFFF`FFFFFFFF 3.10 to 6.1
0x01FFFFFF 0x0000000F`FFFFFFFF 6.2 only
0x00FFFFFF 0x0000000F`FFFFFFFF 6.3 and higher

This interpretation applies also to the Flink and Blink in the MMPFNLIST. They are respectively the PFN of the first and last pages in the list, else they hold the terminating value.