MMPFN Union 3

The MMPFN (Memory Manager Page Frame Number) structure is the key to pretty much everything that the Memory Manager knows about a page of physical memory that is in general use. Since an array of these structures for all physical memory needs to be kept in physical memory, the MMPFN is its own substantial overhead. Presumably to keep this down, ever more gets packed in to the MMPFN ever more intricately.

Perhaps as early as version 4.0, a u3 member combines 16 bits of flags and a 16-bit reference count. It’s certainly not original to the MMPFN, but its existence is established by type information in symbol files for version 5.0 (strictly speaking, for the version 5.0 from Windows 2000 SP3). What’s in its place in versions 3.10 and 3.50 are two 16-bit counts: at offset 0x0C, one that survives as ReferenceCount; at offset 0x0E, one whose name may be lost to history. Version 3.51 dropped the second and widened the ReferenceCount to the whole 32 bits. It didn’t last.

Space in the MMPFN is tight. These early versions have 12 bits of flags at offset 0x14 in combination with a Page Frame Number (PFN) in something like the style of a Page Table Entry (PTE). Version 4.0 seems at least to have anticipated more. Space for 16 instead of 12 had been made by dropping the second of the original counts. Version 4.0 moves the flags

The whole dword there is thought to be defined as the original MMPFNENTRY.

For version 4.0

Originally, the e1 and e2 branches each lay out the whole four bytes: e1 as bit fields, leaving the reference count as a 16-bit DontUse field; e2 as 16-bit integers, collecting the flags as ShortFlags. Version 5.2 from Windows Server 2003 SP1 switched the flags and reference count, and changed many details of the construction.

Offset (x86) Offset (x64) Definition Versions
0x0C (4.0 to 6.3);
0x14
0x18 (late 5.2 to 6.3);
0x20
MMPFNENTRY e1;
4.0 to early 5.2
struct {
    /*  see below: Structure with Entry 1  */
};
late 5.2 and higher
struct {
    /*  see below: Entry 2 Structure  */
} e2;
4.0 and higher
struct {
    USHORT ReferenceCount;
    UCHAR ByteFlags;
    UCHAR InterlockedByteFlags;
} e3;
6.0 only
struct {
    ULONG EntireField;
} e4;
1607 and higher

The u3 union is almost certainly not original. The only known use that the earliest versions make of this space is for two 16-bit counts. The flags were instead in union with the PteFrame, which is here thought to be the origin of the name MMPFNENTRY for the flags as a structure.

Structure with Entry 1

When the version 5.2 from Windows Server 2003 SP1 brought the 16-bit ReferenceCount to the front of u3, the MMPFNENTRY of ULONG bit fields lost its high 16 bits that were labelled as DontUse, and was narrowed to USHORT bit fields. Version 6.0 rearranged further into two sets of UCHAR bit fields, which the 1607 release of Windows 10 formalises as separate structures MMPFNENTRY1 and MMPFNENTRY3.

Offset (x86) Offset (x64) Definition Versions
0x0C (late 5.2 to 6.3);
0x14
0x18 (late 5.2 to 6.3);
0x20
USHORT ReferenceCount;
late 5.2 and higher
0x0E (late 5.2 to 6.3);
0x16
0x1A (late 5.2 to 6.3);
0x22
MMPFNENTRY e1;
late 5.2 to 1511
MMPFNENTRY1 e1;
1607 and higher
0x17 0x23
MMPFNENTRY3 e3;
1607 and higher

Entry 2 Structure

The e2 member is in essence a pair of 16-bit integers: the 16 bits of flags that e1 defines as bit fields; and a 16-bit reference count. The order changes and different versions put either or both of the 16-bit integers in union with another that is volatile. Starting with the 1607 release of Windows 10, the flags are lost, which leaves the e2 member as just the ReferenceCount.

Offset (x86) Offset (x64) Definition Versions
0x0C (4.0 to 6.3);
0x14
0x18 (late 5.2 to 6.3);
0x20
USHORT ShortFlags;
4.0 to early 5.2
USHORT ReferenceCount;
late 5.2 only
union {
    USHORT ReferenceCount;
    SHORT volatile VolatileReferenceCount;
};
6.0 to 6.3
USHORT ReferenceCount;
10.0 and higher
0x0E (4.0 to 6.3);
0x16
0x1A (late 5.2 to 6.3);
0x22
USHORT ReferenceCount;
4.0 to early 5.2
USHORT ShortFlags;
late 5.2 to 6.1
union {
    USHORT ShortFlags;
    USHORT volatile VolatileShortFlags;
};
6.2 to 1511