MEMORY_ALLOCATION_DESCRIPTOR

The MEMORY_ALLOCATION_DESCRIPTOR structure is how the loader describes to the kernel what memory has been found and which of it is already in use for what purpose.

There is one structure for each memory block. The structures are provided as a double-linked list, linked through the ListEntry member. The head is the MemoryDescriptorListHead member of the LOADER_PARAMETER_BLOCK structure whose address the loader passes to the kernel as the latter’s one argument for initialisation. Until the kernel completes its initialisation, it keeps the address in the exported KeLoaderBlock variable, which means the whole list of memory blocks can be easily inspected not just with a debugger but by device drivers.

Though the MEMORY_ALLOCATION_DESCRIPTOR structure is undocumented, it is stable up to and including Windows Vista. In 32-bit builds, it is stable even to Windows 10. In 64-bit builds, however, Windows 7 supports physical memory above 16TB, i.e., physical page numbers that are too wide for 32 bits, and therefore widens two members. Names, types and offsets given below are from Microsoft’s symbol files for Windows Vista and higher. Symbol files for earlier versions do not have type information for this structure.

Offset (x86) Offset (x64) Definition Versions
0x00 0x00
LIST_ENTRY ListEntry;
all
0x08 0x10
TYPE_OF_MEMORY MemoryType;
all
0x0C 0x14
ULONG BasePage;
before 6.1
0x18
ULONG_PTR BasePage;
6.1 and higher
0x10 0x18
ULONG PageCount;
before 6.1
0x20
ULONG_PTR PageCount;
6.1 and higher

The size of a MEMORY_ALLOCATION_DESCRIPTOR is 0x14 bytes in 32-bit builds and either 0x20 or 0x28 bytes in 64-bit builds depending on the version.

Memory Types

What use a memory block has already been put to, if any, is indicated by the TYPE_OF_MEMORY enumeration, which allows more possibilities in later versions. Nearly two dozen types look to be ancient: the kernel in version 3.50 (only) has plain-text descriptions which all match the names that are known from later symbol files.

Numerical Value Symbolic Name Versions
0x00000000
LoaderExceptionBlock
all
0x00000001
LoaderSystemBlock
all
0x00000002
LoaderFree
all
0x00000003
LoaderBad
all
0x00000004
LoaderLoadedProgram
all
0x00000005
LoaderFirmwareTemporary
all
0x00000006
LoaderFirmwarePermanent
all
0x00000007
LoaderOsloaderHeap
all
0x00000008
LoaderOsloaderStack
all
0x00000009
LoaderSystemCode
all
0x0000000A
LoaderHalCode
all
0x0000000B
LoaderBootDriver
all
0x0000000C
LoaderConsoleInDriver
all
0x0000000D
LoaderConsoleOutDriver
all
0x0000000E
LoaderStartupDpcStack
all
0x0000000F
LoaderStartupKernelStack
all
0x00000010
LoaderStartupPanicStack
all
0x00000011
LoaderStartupPcrPage
all
0x00000012
LoaderStartupPdrPage
all
0x00000013
LoaderRegistryData
all
0x00000014
LoaderMemoryData
all
0x00000015
LoaderNlsData
all
0x00000016
LoaderSpecialMemory
all
0x00000017
LoaderBBTMemory
5.0 and higher
0x00000018
LoaderReserve
5.0 to 6.3
LoaderZero
10.0 and higher
0x00000019
LoaderXIPRom
5.1 and higher
0x0000001A
LoaderHalCachedMemory
5.1 and higher
0x0000001B
LoaderLargePageFiller
5.1 and higher
0x0000001C
LoaderErrorLogMemory
6.1 and higher
0x0000001D
LoaderVsmMemory
10.0 and higher
0x0000001E
LoaderFirmwareCode
10.0 and higher
0x0000001F
LoaderFirmwareData
10.0 and higher
0x00000020
LoaderFirmwareReserved
10.0 and higher
0x00000021
LoaderEnclaveMemory
1511 and higher
0x00000022
LoaderFirmwareKsr
1607 and higher
0x00000023
LoaderEnclaveKsr
1703 and higher

Whatever the verson, the formal enumeration continues one value further to a LoaderMaximum.