https://git.reactos.org/?p=reactos.git;a=commitdiff;h=04ff7481b1da008b4e493…
commit 04ff7481b1da008b4e49354dda548ff8aa4853de
Author:     Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Sun Oct 14 23:16:36 2018 +0200
Commit:     Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Tue Jan 1 16:20:13 2019 +0100
    [LDR] Introduce a private heap for the loader.
    This ensures we can still do stuff when the process heap is corrupted.
---
 dll/ntdll/include/ntdllp.h |  1 +
 dll/ntdll/ldr/ldrinit.c    | 20 ++++++++++++++------
 dll/ntdll/ldr/ldrutils.c   | 36 ++++++++++++++++++------------------
 3 files changed, 33 insertions(+), 24 deletions(-)
diff --git a/dll/ntdll/include/ntdllp.h b/dll/ntdll/include/ntdllp.h
index 934a4b2205..11f1e826f3 100644
--- a/dll/ntdll/include/ntdllp.h
+++ b/dll/ntdll/include/ntdllp.h
@@ -32,6 +32,7 @@ typedef struct _LDRP_TLS_DATA
 /* Global data */
 extern RTL_CRITICAL_SECTION LdrpLoaderLock;
 extern BOOLEAN LdrpInLdrInit;
+extern PVOID LdrpHeap;
 extern LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
 extern BOOLEAN ShowSnaps;
 extern UNICODE_STRING LdrpDefaultPath;
diff --git a/dll/ntdll/ldr/ldrinit.c b/dll/ntdll/ldr/ldrinit.c
index e40db1717a..bc72c952cd 100644
--- a/dll/ntdll/ldr/ldrinit.c
+++ b/dll/ntdll/ldr/ldrinit.c
@@ -55,6 +55,7 @@ ULONG LdrpNumberOfProcessors;
 PVOID NtDllBase;
 extern LARGE_INTEGER RtlpTimeout;
 BOOLEAN RtlpTimeoutDisable;
+PVOID LdrpHeap;
 LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
 LIST_ENTRY LdrpDllNotificationList;
 HANDLE LdrpKnownDllObjectDirectory;
@@ -663,7 +664,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
         if (Count > 16)
         {
             /* Allocate space for all the entries */
-            LdrRootEntry = RtlAllocateHeap(RtlGetProcessHeap(),
+            LdrRootEntry = RtlAllocateHeap(LdrpHeap,
                                            0,
                                            Count * sizeof(*LdrRootEntry));
             if (!LdrRootEntry) return STATUS_NO_MEMORY;
@@ -921,7 +922,7 @@ Quickie:
     if (LdrRootEntry != LocalArray)
     {
         /* Free the array */
-        RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry);
+        RtlFreeHeap(LdrpHeap, 0, LdrRootEntry);
     }
     /* Return to caller */
@@ -1752,9 +1753,9 @@ LdrpInitializeProcess(IN PCONTEXT Context,
                                               &ConfigSize);
     /* Setup the Heap Parameters */
-    RtlZeroMemory(&HeapParameters, sizeof(RTL_HEAP_PARAMETERS));
+    RtlZeroMemory(&HeapParameters, sizeof(HeapParameters));
     HeapFlags = HEAP_GROWABLE;
-    HeapParameters.Length = sizeof(RTL_HEAP_PARAMETERS);
+    HeapParameters.Length = sizeof(HeapParameters);
     /* Check if we have Configuration Data */
     if ((LoadConfig) && (ConfigSize == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY)))
@@ -1875,8 +1876,15 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     Status =
RtlAllocateActivationContextStack(&Teb->ActivationContextStackPointer);
     if (!NT_SUCCESS(Status)) return Status;
-    // FIXME: Loader private heap is missing
-    //DPRINT1("Loader private heap is missing\n");
+    RtlZeroMemory(&HeapParameters, sizeof(HeapParameters));
+    HeapFlags = HEAP_GROWABLE | HEAP_CLASS_1;
+    HeapParameters.Length = sizeof(HeapParameters);
+    LdrpHeap = RtlCreateHeap(HeapFlags, 0, 0x10000, 0x6000, 0, &HeapParameters);
+    if (!LdrpHeap)
+    {
+        DPRINT1("Failed to create loader private heap\n");
+        return STATUS_NO_MEMORY;
+    }
     /* Check for Debug Heap */
     if (OptionsKey)
diff --git a/dll/ntdll/ldr/ldrutils.c b/dll/ntdll/ldr/ldrutils.c
index aa18d0384f..5b6e26abd9 100644
--- a/dll/ntdll/ldr/ldrutils.c
+++ b/dll/ntdll/ldr/ldrutils.c
@@ -50,7 +50,7 @@ LdrpAllocateUnicodeString(IN OUT PUNICODE_STRING StringOut,
     }
     /* Allocate the string*/
-    StringOut->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+    StringOut->Buffer = RtlAllocateHeap(LdrpHeap,
                                         0,
                                         StringOut->Length + sizeof(WCHAR));
     if (!StringOut->Buffer)
@@ -88,7 +88,7 @@ LdrpFreeUnicodeString(IN PUNICODE_STRING StringIn)
     /* If Buffer is not NULL - free it */
     if (StringIn->Buffer)
     {
-        RtlFreeHeap(RtlGetProcessHeap(), 0, StringIn->Buffer);
+        RtlFreeHeap(LdrpHeap, 0, StringIn->Buffer);
     }
     /* Zero it out */
@@ -703,7 +703,7 @@ LdrpResolveDllName(PWSTR DllPath,
     ULONG BufSize = 500;
     /* Allocate space for full DLL name */
-    FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufSize +
sizeof(UNICODE_NULL));
+    FullDllName->Buffer = RtlAllocateHeap(LdrpHeap, 0, BufSize +
sizeof(UNICODE_NULL));
     if (!FullDllName->Buffer) return FALSE;
     Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer,
@@ -721,7 +721,7 @@ LdrpResolveDllName(PWSTR DllPath,
             DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath :
LdrpDefaultPath.Buffer);
         }
-        RtlFreeUnicodeString(FullDllName);
+        LdrpFreeUnicodeString(FullDllName);
         return FALSE;
     }
@@ -730,16 +730,16 @@ LdrpResolveDllName(PWSTR DllPath,
     FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL);
     /* Allocate a new buffer */
-    NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullDllName->MaximumLength);
+    NameBuffer = RtlAllocateHeap(LdrpHeap, 0, FullDllName->MaximumLength);
     if (!NameBuffer)
     {
-        RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer);
+        RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
         return FALSE;
     }
     /* Copy over the contents from the previous one and free it */
     RtlCopyMemory(NameBuffer, FullDllName->Buffer, FullDllName->MaximumLength);
-    RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer);
+    RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
     FullDllName->Buffer = NameBuffer;
     /* Find last backslash */
@@ -766,11 +766,11 @@ LdrpResolveDllName(PWSTR DllPath,
     /* Construct base DLL name */
     BaseDllName->Length = (ULONG_PTR)p1 - (ULONG_PTR)p2;
     BaseDllName->MaximumLength = BaseDllName->Length + sizeof(UNICODE_NULL);
-    BaseDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
BaseDllName->MaximumLength);
+    BaseDllName->Buffer = RtlAllocateHeap(LdrpHeap, 0, BaseDllName->MaximumLength);
     if (!BaseDllName->Buffer)
     {
-        RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
+        RtlFreeHeap(LdrpHeap, 0, NameBuffer);
         return FALSE;
     }
@@ -867,7 +867,7 @@ LdrpCheckForKnownDll(PWSTR DllName,
         /* Set up BaseDllName */
         BaseDllName->Length = DllNameUnic.Length;
         BaseDllName->MaximumLength = DllNameUnic.MaximumLength;
-        BaseDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+        BaseDllName->Buffer = RtlAllocateHeap(LdrpHeap,
                                               0,
                                               DllNameUnic.MaximumLength);
         if (!BaseDllName->Buffer)
@@ -882,7 +882,7 @@ LdrpCheckForKnownDll(PWSTR DllName,
         /* Set up FullDllName */
         FullDllName->Length = LdrpKnownDllPath.Length + BaseDllName->Length +
sizeof(WCHAR);
         FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL);
-        FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
FullDllName->MaximumLength);
+        FullDllName->Buffer = RtlAllocateHeap(LdrpHeap, 0,
FullDllName->MaximumLength);
         if (!FullDllName->Buffer)
         {
             Status = STATUS_NO_MEMORY;
@@ -932,8 +932,8 @@ Failure:
     if (Section) NtClose(Section);
     /* Free string resources */
-    if (BaseDllName->Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0,
BaseDllName->Buffer);
-    if (FullDllName->Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0,
FullDllName->Buffer);
+    if (BaseDllName->Buffer) RtlFreeHeap(LdrpHeap, 0, BaseDllName->Buffer);
+    if (FullDllName->Buffer) RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
     /* Return status */
     return Status;
@@ -1137,8 +1137,8 @@ SkipCheck:
             if (!NT_SUCCESS(Status))
             {
                 /* Free the name strings and return */
-                RtlFreeUnicodeString(&FullDllName);
-                RtlFreeUnicodeString(&BaseDllName);
+                LdrpFreeUnicodeString(&FullDllName);
+                LdrpFreeUnicodeString(&BaseDllName);
                 return Status;
             }
         }
@@ -1286,7 +1286,7 @@ SkipCheck:
             RemoveEntryList(&LdrEntry->HashLinks);
             /* Remove the LDR Entry */
-            RtlFreeHeap(RtlGetProcessHeap(), 0, LdrEntry );
+            RtlFreeHeap(LdrpHeap, 0, LdrEntry );
             /* Unmap and close section */
             NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
@@ -1553,7 +1553,7 @@ LdrpAllocateDataTableEntry(IN PVOID BaseAddress)
     if (NtHeader)
     {
         /* Allocate an entry */
-        LdrEntry = RtlAllocateHeap(RtlGetProcessHeap(),
+        LdrEntry = RtlAllocateHeap(LdrpHeap,
                                    HEAP_ZERO_MEMORY,
                                    sizeof(LDR_DATA_TABLE_ENTRY));
@@ -1608,7 +1608,7 @@ LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY
Entry)
     if (Entry->FullDllName.Buffer) LdrpFreeUnicodeString(&Entry->FullDllName);
     /* Finally free the entry's memory */
-    RtlFreeHeap(RtlGetProcessHeap(), 0, Entry);
+    RtlFreeHeap(LdrpHeap, 0, Entry);
 }
 BOOLEAN