LOADER_PARAMETER_EXTENSION

The LOADER_PARAMETER_EXTENSION structure is part of the mechanism through which the kernel and HAL learn the initialisation data that was gathered by the loader. It exists only as data that is pointed to from the LOADER_PARAMETER_BLOCK whose address the loader passes to the kernel for the latter’s initialisation.

Variability

The architectural point to having two structures is that the LOADER_PARAMETER_BLOCK should be relatively stable across Windows versions, which indeed it was before Windows 7, but the LOADER_PARAMETER_EXTENSION can vary significantly and often has.

This is not just theoretical. Before version 6.0, the LOADER_PARAMETER_BLOCK really did need to be stable enough that the one NTLDR in the root directory of the bootable partition might load a kernel from a different Windows version, certainly any earlier version if not also any later one. Variability between versions was more for things that the LOADER_PARAMETER_BLOCK points to from its stable offsets. The LOADER_PARAMETER_EXTENSION is one such thing. It was a far-sighted allowance. An Extension pointer seems to have been allowed for, if not formally defined, right from the start, but not until version 5.0 does the loader create a LOADER_PARAMETER_EXTENSION to point to.

Version 6.0 separated NTLDR into a boot manager, e.g., BOOTMGR, and boot loader, e.g., WINLOAD, such that the latter should always match the kernel of whatever Windows version is being booted. Since the boot loader prepares the LOADER_PARAMETER_EXTENSION, considerations for backwards compatibility have essentially disappared. Subsequent changes are not just from growth at the end: members are removed, changed and inserted without regard for continuity. Especially notable among the changes is that Windows 7 does away with the MajorVersion and MinorVersion—or, if you prefer, moves them to the LOADER_PARAMETER_BLOCK. The Size at the start of the LOADER_PARAMETER_EXTENSION is then the only means of identifying which version did the preparation.

It cannot be stressed enough that the LOADER_PARAMETER_EXTENSION, however vital as shared data between the loader, kernel and HAL, is highly variable. Though early versions change organically, i.e., by adding only to the end so that the Size at the start differentiates the layouts, they change even between builds. The structure is greatly expanded in later versions and successive releases of Windows 10 vary the structure more than ever before.

Version Size (x86) Size (x64)
5.0 0x28  
original 5.1 0x3C  
late 5.1, starting with SP1 0x40  
early 5.2 0x50  
late 5.2, starting with SP1 0x58 0x88
6.0 0x7C 0xB8
6.1 0xE8 0x0148
6.2 0x0870 0x0920
6.3 0x08E0 0x0988
10.0 0x0920 0x09E0
1511 0x0930 0x09F0
1607 0x0950 0x0A28
1703 and 1709 0x0B60 0x0C38
1803 0x0B68 0x0C40

Beware that the change within version 5.1 starts with Windows XP Service Pack 1. On numerous other pages at this website, the abbreviation “late 5.1” means version 5.1 starting with Windows XP SP2. Many advances and fixes that came with the introduction of the amd64 architecture for the version 5.2 from Windows Server 2003 SP1 found their way into the roughly contemporaneous Windows XP SP2, but none affected the LOADER_PARAMETER_EXTENSION.

Layout

Until recently, Microsoft’s names for the LOADER_PARAMETER_EXTENSION members and types were known only from type information in the symbol files for occasional Windows versions: first for Windows 2000 SP3 and SP4, and then for all releases of Windows Vista and Windows 7. How the type information gets into symbol files for some versions but not others is not known. Windows 10, however, brought something new…

A header file, ARC.H, in an Enterprise edition of the Windows Driver Kit (WDK) for Windows 10 supplies a C-language definition of the LOADER_PARAMETER_EXTENSION. This appears to be Microsoft’s first formal disclosure of the structure’s layout. It comes with no conditional compilation blocks for accommodating earlier versions. As supplied, it is immediately useful only for programming that targets not just Windows 10 specifically but one particular update of Windows 10, yet doesn’t say so. Add that the header is beneath a subdirectory named “um”, presumably to mean user-mode, but that the LOADER_PARAMETER_EXTENSION is long gone by the time any user-mode software gets to execute, and one might wonder if this structure’s definition was published by mistake.

Still, published it is. Then, just as that seemed to be the end of disclosure, perhaps forever, Microsoft’s names and types returned to the public symbol files for the 1803 release of Windows 10.

The following table presents the layout of the LOADER_PARAMETER_EXTENSION for the 1803 release of Windows 10, as given by the public symbol files, and for the 1511 release of Windows 10, as given by Microsoft’s ARC.H. For earlier versions, the layout is directly from type information in symbol files, if available. Names, types and offsets for all other versions are something of a guess from assuming continuity except where inspection of the loader or kernel shows that members have come and gone.

Offset (x86) Offset (x64) Definition Versions Remarks
0x00 0x00
ULONG Size;
5.0 and higher  
0x04 0x04
PROFILE_PARAMETER_BLOCK Profile;
5.0 and higher  
0x14 (5.0 to 6.0) 0x14 (5.2 to 6.0)
ULONG MajorVersion;
5.0 to 6.0  
0x18 (5.0 to 6.0) 0x18 (5.2 to 6.0)
ULONG MinorVersion;
5.0 to 6.0  
0x1C (5.0 to 6.0);
0x14
0x20 (5.2 to 6.0);
0x18
PVOID EmInfFileImage;
5.0 and higher  
0x20 (5.0 to 6.0);
0x18
0x28 (5.2 to 6.0);
0x20
ULONG EmInfFileSize;
5.0 and higher  
0x24 (5.0 to 6.0);
0x1C
0x30 (5.2 to 6.0);
0x28
PVOID TriageDumpBlock;
5.0 and higher last member in 5.0

Appended for Windows XP

Offset (x86) Offset (x64) Definition Versions Remarks
0x28 (5.1 to 6.0);
0x20 (6.1)
0x38 (5.2 to 6.0);
0x30 (6.1)
ULONG_PTR LoaderPagesSpanned;
5.1 to 6.1  
0x2C (5.1 to 6.0);
0x24 (6.1);
0x20
0x40 (5.2 to 6.0);
0x38 (6.1);
0x30
HEADLESS_LOADER_BLOCK *HeadlessLoaderBlock;
5.1 and higher  
0x30 (5.1 to 6.0);
0x28 (6.1);
0x24
0x48 (5.2 to 6.0);
0x40 (6.1);
0x38
SMBIOS_TABLE_HEADER *SMBiosEPSHeader;
5.1 and higher  
0x34 (5.1 to 6.0);
0x2C (6.1);
0x28
0x50 (5.2 to 6.0);
0x48 (6.1);
0x40
PVOID DrvDBImage;
5.1 and higher  
0x38 (5.1 to 6.0);
0x30 (6.1);
0x2C
0x58 (5.2 to 6.0);
0x50 (6.1);
0x48
ULONG DrvDBSize;
5.1 and higher last member in original 5.1
0x3C (late 5.1 to 6.0);
0x34 (6.1);
0x30
0x60 (5.2 to 6.0);
0x58 (6.1);
0x50
NETWORK_LOADER_BLOCK *NetworkLoaderBlock;
late 5.1 and higher last member in late 5.1

Appended for Windows Server 2003

Offset (x86) Offset (x64) Definition Versions Remarks
0x40 (5.2 to 6.0);
0x38 (6.1);
0x34
 
PUCHAR HalpIRQLToTPR;
5.2 and higher  
0x44 (5.2 to 6.0);
0x3C (6.1);
0x38
 
PUCHAR HalpVectorToIRQL;
5.2 and higher  
0x48 (5.2 to 6.0);
0x40 (6.1);
0x3C
0x68 (5.2 to 6.0);
0x60 (6.1);
0x58
LIST_ENTRY FirmwareDescriptorListHead;
5.2 and higher last member in early 5.2
0x50 (late 5.2 to 6.0);
0x48 (6.1);
0x44
0x78 (5.2 to 6.0);
0x70 (6.1);
0x68
PVOID AcpiTable;
late 5.2 and higher  
0x54 (late 5.2 to 6.0);
0x4C (6.1);
0x48
0x80 (5.2 to 6.0);
0x78 (6.1);
0x70
ULONG AcpiTableSize;
late 5.2 and higher last member in late 5.2

Appended for Windows Vista

Offset (x86) Offset (x64) Definition Versions Remarks
0x58 (6.0);
0x50 (6.1);
0x4C
0x84 (6.0);
0x7C (6.1);
0x74
/*  bit fields, see below  */
6.0 and higher  
0x5C (6.0);
0x54 (6.1);
0x50
0x88 (6.0);
0x80 (6.1);
0x78
LOADER_PERFORMANCE_DATA *LoaderPerformanceData;
6.0 and higher  
0x60 (6.0);
0x58 (6.1);
0x54
0x90 (6.0);
0x88 (6.1);
0x80
LIST_ENTRY BootApplicationPersistentData;
6.0 and higher  
0x68 (6.0);
0x60 (6.1);
0x5C
0xA0 (6.0);
0x98 (6.1);
0x90
PVOID WmdTestResult;
6.0 and higher  
0x6C (6.0);
0x64 (6.1);
0x60
0xA8 (6.0);
0xA0 (6.1);
0x98
GUID BootIdentifier;
6.0 and higher last member in 6.0

Appended for Windows 7

Offset (x86) Offset (x64) Definition Versions Remarks
0x74 (6.1);
0x70
0xB0 (6.1);
0xA8
ULONG ResumePages;
6.1 and higher  
0x78 (6.1);
0x74
0xB8 (6.1);
0xB0
PVOID DumpHeader;
6.1 and higher  
0x7C (6.1);
0x78
0xC0 (6.1);
0xB8
PVOID BgContext;
6.1 and higher  
0x80 (6.1);
0x7C
0xC8 (6.1);
0xC0
PVOID NumaLocalityInfo;
6.1 and higher  
0x84 (6.1);
0x80
0xD0 (6.1);
0xC8
PVOID NumaGroupAssignment;
6.1 and higher  
0x88 (6.1);
0x84
0xD8 (6.1);
0xD0
LIST_ENTRY AttachedHives;
6.1 and higher  
0x90 (6.1);
0x8C
0xE8 (6.1);
0xE0
ULONG MemoryCachingRequirementsCount;
6.1 and higher  
0x94 (6.1);
0x90
0xF0 (6.1);
0xE8
PVOID MemoryCachingRequirements;
6.1 and higher  
0x98 0xF8 (6.1);
0xF0
TPM_BOOT_ENTROPY_LDR_RESULT TpmBootEntropyResult;
6.1 only  
BOOT_ENTROPY_LDR_RESULT BootEntropyResult;
6.2 and higher  
0xE0 (6.1);
0x07A8 (6.2);
0x0810 (6.3 to 1607);
0x0830
0x0140 (6.1);
0x0800 (6.2);
0x0868 (6.3 to 1607);
0x0888
ULONGLONG ProcessorCounterFrequency;
6.1 and higher last member in 6.1

Appended for Windows 8

Offset (x86) Offset (x64) Definition Versions Remarks
0x07B0 (6.2);
0x0818 (6.3 to 1607);
0x0838
0x0808 (6.2);
0x0870 (6.3 to 1607);
0x0890
LOADER_PARAMETER_HYPERVISOR_EXTENSION HypervisorExtension;
6.2 and higher  
0x07E8 (6.2);
0x0850 (6.3 to 1607);
0x0870
0x0840 (6.2);
0x08A8 (6.3 to 1607);
0x08C8
GUID HardwareConfigurationId;
6.2 and higher  
0x07F8 (6.2);
0x0860 (6.3 to 1607);
0x0880
0x0850 (6.2);
0x08B8 (6.3 to 1607);
0x08D8
LIST_ENTRY HalExtensionModuleList;
6.2 and higher  
0x0800 (6.2);
0x0868 (6.3 to 1607);
0x0888
0x0860 (6.2);
0x08C8 (6.3 to 1607);
0x08E8
LARGE_INTEGER SystemTime;
6.2 and higher  
0x0808 (6.2);
0x0870 (6.3 to 1607);
0x0890
0x0868 (6.2);
0x08D0 (6.3 to 1607);
0x08F0
ULONGLONG TimeStampAtSystemTimeRead;
6.2 and higher  
0x0810 (6.2);
0x0878 (6.3 to 1607);
0x0898
0x0870 (6.2);
0x08D8 (6.3 to 1607);
0x08F8
ULONGLONG BootFlags;
6.2 to some 10.0  
union {
    ULONGLONG BootFlags;
    struct {
        ULONGLONG DbgMenuOsSelection : ;
        ULONGLONG DbgHiberBoot : ;
        ULONGLONG DbgSoftRestart : ;
    };
};
some 10.0 and higher  
0x0818 (6.2);
0x0880 (6.3 to 1607);
0x08A0
0x0878 (6.2);
0x08E0 (6.3 to 1607);
0x0900
ULONGLONG InternalBootFlags;
6.2 to some 10.0  
union {
    ULONGLONG InternalBootFlags;
    struct {
        ULONGLONG DbgUtcBootTime : 1;
        ULONGLONG DbgRtcBootTime : 1;
        ULONGLONG DbgNoLegacyServices : 1;
    };
};
some 10.0 and higher  
0x0820 (6.2);
0x0888 (6.3 to 1607);
0x08A8
0x0880 (6.2);
0x08E8 (6.3 to 1607);
0x0908
PVOID WfsFPData;
6.2 and higher  
0x0824 (6.2);
0x088C (6.3 to 1607);
0x08AC
0x0888 (6.2);
0x08F0 (6.3 to 1607);
0x0910
ULONG WfsFPDataSize;
6.2 and higher  
0x0828 (6.2);
0x0890 (6.3 to 1607);
0x08B0
0x0890 (6.2);
0x08F8 (6.3 to 1607);
0x0918
array of 6 unknown structures 6.2 only  
LOADER_BUGCHECK_PARAMETERS BugcheckParameters;
6.3 and higher  
0x08A4 (6.3 to 1607);
0x08C4
0x0920 (6.3 to 1607);
0x0940
PVOID ApiSetSchema;
6.3 and higher  
0x08A8 (6.3 to 1607);
0x08C8
0x0928 (6.3 to 1607);
0x0948
ULONG ApiSetSchemaSize;
6.3 and higher  
0x08AC (6.3 to 1607);
0x08CC
0x0930 (6.3 to 1607);
0x0950
LIST_ENTRY ApiSetSchemaExtensions;
6.3 and higher  
0x0858 (6.2);
0x08B4 (6.3 to 1607);
0x08D4
0x08F0 (6.2);
0x0940 (6.3 to 1607);
0x0960
UNICODE_STRING AcpiBiosVersion;
6.2 and higher  
0x0860 (6.2);
0x08BC (6.3 to 1607);
0x08DC
0x0900 (6.2);
0x0950 (6.3 to 1607);
0x0970
UNICODE_STRING SmbiosVersion;
6.2 and higher  
0x0868 (6.2);
0x08C4 (6.3 to 1607);
0x08E4
0x0910 (6.2);
0x0960 (6.3 to 1607);
0x0980
UNICODE_STRING EfiVersion;
6.2 and higher last member in 6.2

It is not known which Windows 10 release is the one for which Microsoft formally defined bit flags in union with BootFlags and InternalBootFlags.

Appended for Windows 8.1

Offset (x86) Offset (x64) Definition Versions Remarks
0x08CC (6.3 to 1607);
0x08EC
0x0970 (6.3 to 1607);
0x0990
DEBUG_DEVICE_DESCRIPTOR *KdDebugDevice;
6.3 and higher  
0x08D0 (6.3 to 1607);
0x08F0
0x0978 (6.3 to 1607);
0x0998
OFFLINE_CRASHDUMP_CONFIGURATION_TABLE OfflineCrashdumpConfigurationTable;
6.3 and higher last member in 6.3

Appended for Windows 10

Offset (x86) Offset (x64) Definition Versions Remarks
0x08F0 (10.0 to 1607);
0x0910
0x0998 (10.0 to 1607);
0x09B8
UNICODE_STRING ManufacturingProfile;
10.0 and higher  
0x08F8 (10.0 to 1607);
0x0918
0x09A8 (10.0 to 1607);
0x09C8
PVOID BbtBuffer;
10.0 and higher  
0x0900 (10.0 to 1607);
0x0920
0x09B0 (10.0 to 1607);
0x09D0
ULONG64 XsaveAllowedFeatures;
10.0 and higher  
0x0908 (10.0 to 1607);
0x0928
0x09B8 (10.0 to 1607);
0x09D8
ULONG XsaveFlags;
10.0 and higher  
0x090C (10.0 to 1607);
0x092C
0x09C0 (10.0 to 1607);
0x09E0
PVOID BootOptions;
10.0 and higher  
0x0910 (1607);
0x0930
0x09C8 (1607);
0x09E8
ULONG IumEnablement;
1607 and higher  
0x914 (1607);
0x0934
0x09CC (1607);
0x09EC
ULONG IumPolicy;
1607 and higher  
0x918 (1607);
0x0938
0x09D0 (1607);
0x09F0
NTSTATUS IumStatus;
1607 and higher  
0x0910 (10.0 to 1511);
0x091C (1607);
0x093C
0x09C8 (10.0 to 1511);
0x09D4 (1607);
0x09F4
ULONG BootId;
10.0 and higher  
0x0914 (10.0 to 1511);
0x0920 (1607);
0x0940
0x09D0 (10.0 to 1511);
0x09D8 (1607);
0x09F8
LOADER_PARAMETER_CI_EXTENSION *CodeIntegrityData;
10.0 and higher  
0x0918 (10.0 to 1511);
0x0924 (1607);
0x0944
0x09D8 (10.0 to 1511);
0x09E0 (1607);
0x0A00
ULONG CodeIntegrityDataSize;
10.0 and higher last member in original 10.0
0x091C (1511);
0x0928 (1607);
0x0948
0x09E0 (1511);
0x09E4 (1607);
0x0A04
LOADER_HIVE_RECOVER_INFO SystemHiveRecoveryInfo;
1511 and higher last member in 1511
0x093C (1607);
0x095C
0x09F8 (1607);
0x0A18
ULONG SoftRestartCount;
1607 and higher  
0x0940 (1607);
0x0960
0x0A00 (1607);
0x0A20
LONGLONG SoftRestartTime;
1607 and higher  
  0x0A08 (1607);
0x0A28
PVOID HypercallCodeVa;
1607 and higher  
  0x0A10 (1607);
0x0A30
PVOID HalVirtualAddress;
1607 and higher  
  0x0A18 (1607);
0x0A38
ULONGLONG HalNumberOfBytes;
1607 and higher  
0x0948 (1607);
0x0968
0x0A20 (1607);
0x0A40
ULONG MajorRelease;
1607 and higher  
0x094C (1607);
0x096C
0x0A24 (1607);
0x0A44
ULONG Reserved1;
1607 and higher last member in 1607
0x0970 0x0A48
CHAR NtBuildLab [0xE0];
1703 and higher  
0x0A50 0x0B28
CHAR NtBuildLabEx [0xE0];
1703 and higher  
0x0B30 0x0C08
LOADER_RESET_REASON ResetReason;
1703 and higher last member in 1703;
last member in 1709
0x0B60 0x0C38
ULONG MaxPciBusNumber;
1803 and higher last member in 1803

The MajorRelease is an NTDDI version number as defined in the SDKDDKVER.H header. It adds to the kernel’s validation of the LOADER_PARAMETER_EXTENSION for the LOADER_BLOCK_MISMATCH bugcheck. Do not miss the irony that the version numbering that was removed from the extension for Windows 7 is brought back, with elaboration, now that Windows 10 makes the extension more variable than ever before.

Bit Fields

Version 6.0 introduced a single bit-wide flag at offsets 0x58 and 0x84, plausibly anticipating that there would soon be more.

Mask Definition Versions
0x00000001
ULONG BootViaWinload : 1;
6.0 only
ULONG LastBootSucceeded : 1;
6.1 and higher
0x00000002
ULONG LastBootShutdown : 1;
6.1 and higher
0x00000004
ULONG IoPortAccessSupported : 1;
6.1 and higher
0x00000008
ULONG BootDebuggerActive : 1;
6.2 and higher
0x00000010
ULONG StrongCodeGuarantees : 1;
10.0 and higher
0x00000020
ULONG HardStrongCodeGuarantees : 1;
10.0 and higher
0x00000040
ULONG SidSharingDisabled : 1;
10.0 and higher
0x00000080
ULONG TpmInitialized : 1;
10.0 and higher
0x00000100
ULONG VsmConfigured : 1;
10.0 and higher
0x00000200
ULONG IumEnabled : 1;
10.0 and higher
0x00000400
ULONG IsSmbboot : 1;
10.0 and higher
0x00000800
ULONG BootLogEnabled : 1;
1607 and higher
0x0007F000
ULONG FeatureSettings : 7;
1803 and higher
0x01F80000
ULONG FeatureSimulations : 6;
1803 and higher
0x02000000
ULONG MicrocodeOptedOut : 1;
1803 and higher
0x04000000
ULONG XhciLegacyHandoffSkip : 1;
1803 and higher
 
ULONG Reserved : 31;
6.0 only
ULONG Reserved : 29;
6.1 only
ULONG Reserved : 28;
6.2 to 6.3
ULONG Reserved : 21;
10.0 to 1511
ULONG Reserved : 20;
1607 to 1709
ULONG Reserved : 5;
1803 and higher

Which version from 6.2 to 10.0 inclusive introduced StrongCodeGuarantees and HardStrongCodeGuarantees is not known: I don’t yet know where either is used in any version.