The PEB_LDR_DATA structure is the main record of what modules are loaded in a process.
It is essentially the head of three double-linked lists of LDR_DATA_TABLE_ENTRY structures which each represent one loaded module.
Microsoft documentation of this is incomplete, the fields here are taken from various resources including:
Length: ULONGThe size in bytes of the structure
Initialized: BOOLEANTRUE if the structure is prepared.
SsHandle: PVOIDInLoadOrderModuleList: LIST_ENTRYInMemoryOrderModuleList: LIST_ENTRYInInitializationOrderModuleList: LIST_ENTRYEntryInProgress: PVOIDNo known use of this field is known in Windows 8 and higher.
ShutdownInProgress: BOOLEANShutdownThreadId: HANDLEThough ShutdownThreadId is declared as a HANDLE, it is indeed the thread ID as suggested by its name. It is picked up from the UniqueThread member of the CLIENT_ID in the TEB of the thread that asks to terminate the process.
pub const PEB_LDR_DATA = extern struct {
// Versions: 3.51 and higher
/// The size in bytes of the structure
Length: ULONG,
/// TRUE if the structure is prepared.
Initialized: BOOLEAN,
SsHandle: PVOID,
InLoadOrderModuleList: LIST_ENTRY,
InMemoryOrderModuleList: LIST_ENTRY,
InInitializationOrderModuleList: LIST_ENTRY,
// Versions: 5.1 and higher
/// No known use of this field is known in Windows 8 and higher.
EntryInProgress: PVOID,
// Versions: 6.0 from Windows Vista SP1, and higher
ShutdownInProgress: BOOLEAN,
/// Though ShutdownThreadId is declared as a HANDLE,
/// it is indeed the thread ID as suggested by its name.
/// It is picked up from the UniqueThread member of the CLIENT_ID in the
/// TEB of the thread that asks to terminate the process.
ShutdownThreadId: HANDLE,
}