[LDR] Silence some debug logs when images overlap
[reactos.git] / dll / ntdll / ldr / ldrutils.c
index 5459d4a..1011a85 100644 (file)
@@ -50,9 +50,9 @@ LdrpAllocateUnicodeString(IN OUT PUNICODE_STRING StringOut,
     }
 
     /* Allocate the string*/
-    StringOut->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+    StringOut->Buffer = RtlAllocateHeap(LdrpHeap,
                                         0,
-                                        StringOut->Length + sizeof(WCHAR));
+                                        Length + sizeof(WCHAR));
     if (!StringOut->Buffer)
     {
         /* Fail */
@@ -61,13 +61,13 @@ LdrpAllocateUnicodeString(IN OUT PUNICODE_STRING StringOut,
     }
 
     /* Null-terminate it */
-    StringOut->Buffer[StringOut->Length / sizeof(WCHAR)] = UNICODE_NULL;
+    StringOut->Buffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
 
     /* Check if this is a maximum-sized string */
-    if (StringOut->Length != UNICODE_STRING_MAX_BYTES)
+    if (Length != UNICODE_STRING_MAX_BYTES)
     {
         /* It's not, so set the maximum length to be one char more */
-        StringOut->MaximumLength = StringOut->Length + sizeof(UNICODE_NULL);
+        StringOut->MaximumLength = Length + sizeof(UNICODE_NULL);
     }
     else
     {
@@ -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 */
@@ -470,7 +470,7 @@ LdrpUpdateLoadCount2(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
 
 VOID
 NTAPI
-LdrpCallTlsInitializers(IN PVOID BaseAddress,
+LdrpCallTlsInitializers(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
                         IN ULONG Reason)
 {
     PIMAGE_TLS_DIRECTORY TlsDirectory;
@@ -478,7 +478,7 @@ LdrpCallTlsInitializers(IN PVOID BaseAddress,
     ULONG Size;
 
     /* Get the TLS Directory */
-    TlsDirectory = RtlImageDirectoryEntryToData(BaseAddress,
+    TlsDirectory = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
                                                 TRUE,
                                                 IMAGE_DIRECTORY_ENTRY_TLS,
                                                 &Size);
@@ -497,7 +497,7 @@ LdrpCallTlsInitializers(IN PVOID BaseAddress,
                 if (ShowSnaps)
                 {
                     DPRINT1("LDR: Tls Callbacks Found. Imagebase %p Tls %p CallBacks %p\n",
-                            BaseAddress, TlsDirectory, Array);
+                            LdrEntry->DllBase, TlsDirectory, Array);
                 }
 
                 /* Loop the array */
@@ -510,12 +510,12 @@ LdrpCallTlsInitializers(IN PVOID BaseAddress,
                     if (ShowSnaps)
                     {
                         DPRINT1("LDR: Calling Tls Callback Imagebase %p Function %p\n",
-                                BaseAddress, Callback);
+                                LdrEntry->DllBase, Callback);
                     }
 
                     /* Call it */
                     LdrpCallInitRoutine((PDLL_INIT_ROUTINE)Callback,
-                                        BaseAddress,
+                                        LdrEntry->DllBase,
                                         Reason,
                                         NULL);
                 }
@@ -524,7 +524,8 @@ LdrpCallTlsInitializers(IN PVOID BaseAddress,
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
-        /* Do nothing */
+        DPRINT1("LDR: Exception 0x%x during Tls Callback(%u) for %wZ\n",
+                _SEH2_GetExceptionCode(), Reason, &LdrEntry->BaseDllName);
     }
     _SEH2_END;
 }
@@ -702,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,
@@ -720,7 +721,7 @@ LdrpResolveDllName(PWSTR DllPath,
             DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer);
         }
 
-        RtlFreeUnicodeString(FullDllName);
+        LdrpFreeUnicodeString(FullDllName);
         return FALSE;
     }
 
@@ -729,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 */
@@ -765,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;
     }
 
@@ -866,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)
@@ -881,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;
@@ -931,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;
@@ -1136,8 +1137,8 @@ SkipCheck:
             if (!NT_SUCCESS(Status))
             {
                 /* Free the name strings and return */
-                RtlFreeUnicodeString(&FullDllName);
-                RtlFreeUnicodeString(&BaseDllName);
+                LdrpFreeUnicodeString(&FullDllName);
+                LdrpFreeUnicodeString(&BaseDllName);
                 return Status;
             }
         }
@@ -1285,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);
@@ -1331,7 +1332,7 @@ SkipCheck:
         ImageBase = (ULONG_PTR)NtHeaders->OptionalHeader.ImageBase;
         ImageEnd = ImageBase + ViewSize;
 
-        DPRINT1("LDR: LdrpMapDll Relocating Image Name %ws (%p-%p -> %p)\n", DllName, (PVOID)ImageBase, (PVOID)ImageEnd, ViewBase);
+        DPRINT("LDR: LdrpMapDll Relocating Image Name %ws (%p-%p -> %p)\n", DllName, (PVOID)ImageBase, (PVOID)ImageEnd, ViewBase);
 
         /* Scan all the modules */
         ListHead = &Peb->Ldr->InLoadOrderModuleList;
@@ -1370,7 +1371,7 @@ SkipCheck:
             RtlInitUnicodeString(&OverlapDll, L"Dynamically Allocated Memory");
         }
 
-        DPRINT1("Overlapping DLL: %wZ\n", &OverlapDll);
+        DPRINT("Overlapping DLL: %wZ\n", &OverlapDll);
 
         /* Are we dealing with a DLL? */
         if (LdrEntry->Flags & LDRP_IMAGE_DLL)
@@ -1552,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));
 
@@ -1607,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
@@ -1850,6 +1851,7 @@ LdrpSearchPath(IN PWCHAR *SearchPath,
 
     /* FIXME: Setup TestName here */
     Status = STATUS_NOT_FOUND;
+    BufEnd = Buffer;
 
     /* Start loop */
     do
@@ -2487,146 +2489,153 @@ LdrpLoadDll(IN BOOLEAN Redirected,
     /* Check for init flag and acquire lock */
     if (!InInit) RtlEnterCriticalSection(&LdrpLoaderLock);
 
-    /* Show debug message */
-    if (ShowSnaps)
+    _SEH2_TRY
     {
-        DPRINT1("LDR: LdrLoadDll, loading %wZ from %ws\n",
-                 &RawDllName,
-                 DllPath ? DllPath : L"");
-    }
-
-    /* Check if the DLL is already loaded */
-    if (!LdrpCheckForLoadedDll(DllPath,
-                               &RawDllName,
-                               FALSE,
-                               Redirected,
-                               &LdrEntry))
-    {
-        /* Map it */
-        Status = LdrpMapDll(DllPath,
-                            DllPath,
-                            NameBuffer,
-                            DllCharacteristics,
-                            FALSE,
-                            Redirected,
-                            &LdrEntry);
-        if (!NT_SUCCESS(Status)) goto Quickie;
-
-        /* FIXME: Need to mark the DLL range for the stack DB */
-        //RtlpStkMarkDllRange(LdrEntry);
-
-        /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
-        if ((DllCharacteristics) &&
-            (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
+        /* Show debug message */
+        if (ShowSnaps)
         {
-            /* This is not a DLL, so remove such data */
-            LdrEntry->EntryPoint = NULL;
-            LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
+            DPRINT1("LDR: LdrLoadDll, loading %wZ from %ws\n",
+                     &RawDllName,
+                     DllPath ? DllPath : L"");
         }
 
-        /* Make sure it's a DLL */
-        if (LdrEntry->Flags & LDRP_IMAGE_DLL)
+        /* Check if the DLL is already loaded */
+        if (!LdrpCheckForLoadedDll(DllPath,
+                                   &RawDllName,
+                                   FALSE,
+                                   Redirected,
+                                   &LdrEntry))
         {
-            /* Check if this is a .NET Image */
-            if (!(LdrEntry->Flags & LDRP_COR_IMAGE))
-            {
-                /* Walk the Import Descriptor */
-                Status = LdrpWalkImportDescriptor(DllPath, LdrEntry);
-            }
+            /* Map it */
+            Status = LdrpMapDll(DllPath,
+                                DllPath,
+                                NameBuffer,
+                                DllCharacteristics,
+                                FALSE,
+                                Redirected,
+                                &LdrEntry);
+            if (!NT_SUCCESS(Status))
+                _SEH2_LEAVE;
 
-            /* Update load count, unless it's locked */
-            if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
-            LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
+            /* FIXME: Need to mark the DLL range for the stack DB */
+            //RtlpStkMarkDllRange(LdrEntry);
 
-            /* Check if we failed */
-            if (!NT_SUCCESS(Status))
+            /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
+            if ((DllCharacteristics) &&
+                (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
             {
-                /* Clear entrypoint, and insert into list */
+                /* This is not a DLL, so remove such data */
                 LdrEntry->EntryPoint = NULL;
-                InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
-                               &LdrEntry->InInitializationOrderLinks);
-
-                /* Cancel the load */
-                LdrpClearLoadInProgress();
+                LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
+            }
 
-                /* Unload the DLL */
-                if (ShowSnaps)
+            /* Make sure it's a DLL */
+            if (LdrEntry->Flags & LDRP_IMAGE_DLL)
+            {
+                /* Check if this is a .NET Image */
+                if (!(LdrEntry->Flags & LDRP_COR_IMAGE))
                 {
-                    DbgPrint("LDR: Unloading %wZ due to error %x walking "
-                             "import descriptors\n",
-                             DllName,
-                             Status);
+                    /* Walk the Import Descriptor */
+                    Status = LdrpWalkImportDescriptor(DllPath, LdrEntry);
                 }
-                LdrUnloadDll(LdrEntry->DllBase);
 
-                /* Return the error */
-                goto Quickie;
-            }
-        }
-        else if (LdrEntry->LoadCount != 0xFFFF)
-        {
-            /* Increase load count */
-            LdrEntry->LoadCount++;
-        }
+                /* Update load count, unless it's locked */
+                if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
+                LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
+
+                /* Check if we failed */
+                if (!NT_SUCCESS(Status))
+                {
+                    /* Clear entrypoint, and insert into list */
+                    LdrEntry->EntryPoint = NULL;
+                    InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
+                                   &LdrEntry->InInitializationOrderLinks);
 
-        /* Insert it into the list */
-        InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
-                       &LdrEntry->InInitializationOrderLinks);
+                    /* Cancel the load */
+                    LdrpClearLoadInProgress();
 
-        /* If we have to run the entrypoint, make sure the DB is ready */
-        if (CallInit && LdrpLdrDatabaseIsSetup)
-        {
-            /* Notify Shim Engine */
-            if (g_ShimsEnabled)
+                    /* Unload the DLL */
+                    if (ShowSnaps)
+                    {
+                        DbgPrint("LDR: Unloading %wZ due to error %x walking "
+                                 "import descriptors\n",
+                                 DllName,
+                                 Status);
+                    }
+                    LdrUnloadDll(LdrEntry->DllBase);
+
+                    /* Return the error */
+                    _SEH2_LEAVE;
+                }
+            }
+            else if (LdrEntry->LoadCount != 0xFFFF)
             {
-                VOID (NTAPI* SE_DllLoaded)(PLDR_DATA_TABLE_ENTRY) = RtlDecodeSystemPointer(g_pfnSE_DllLoaded);
-                SE_DllLoaded(LdrEntry);
+                /* Increase load count */
+                LdrEntry->LoadCount++;
             }
 
-            /* Run the init routine */
-            Status = LdrpRunInitializeRoutines(NULL);
-            if (!NT_SUCCESS(Status))
+            /* Insert it into the list */
+            InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
+                           &LdrEntry->InInitializationOrderLinks);
+
+            /* If we have to run the entrypoint, make sure the DB is ready */
+            if (CallInit && LdrpLdrDatabaseIsSetup)
             {
-                /* Failed, unload the DLL */
-                if (ShowSnaps)
+                /* Notify Shim Engine */
+                if (g_ShimsEnabled)
                 {
-                    DbgPrint("LDR: Unloading %wZ because either its init "
-                             "routine or one of its static imports failed; "
-                             "status = 0x%08lx\n",
-                             DllName,
-                             Status);
+                    VOID (NTAPI* SE_DllLoaded)(PLDR_DATA_TABLE_ENTRY) = RtlDecodeSystemPointer(g_pfnSE_DllLoaded);
+                    SE_DllLoaded(LdrEntry);
                 }
-                LdrUnloadDll(LdrEntry->DllBase);
+
+                /* Run the init routine */
+                Status = LdrpRunInitializeRoutines(NULL);
+                if (!NT_SUCCESS(Status))
+                {
+                    /* Failed, unload the DLL */
+                    if (ShowSnaps)
+                    {
+                        DbgPrint("LDR: Unloading %wZ because either its init "
+                                 "routine or one of its static imports failed; "
+                                 "status = 0x%08lx\n",
+                                 DllName,
+                                 Status);
+                    }
+                    LdrUnloadDll(LdrEntry->DllBase);
+                }
+            }
+            else
+            {
+                /* The DB isn't ready, which means we were loaded because of a forwarder */
+                Status = STATUS_SUCCESS;
             }
         }
         else
         {
-            /* The DB isn't ready, which means we were loaded because of a forwarder */
-            Status = STATUS_SUCCESS;
+            /* We were already loaded. Are we a DLL? */
+            if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF))
+            {
+                /* Increase load count */
+                LdrEntry->LoadCount++;
+                LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
+
+                /* Clear the load in progress */
+                LdrpClearLoadInProgress();
+            }
+            else
+            {
+                /* Not a DLL, just increase the load count */
+                if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
+            }
         }
+
     }
-    else
+    _SEH2_FINALLY
     {
-        /* We were already loaded. Are we a DLL? */
-        if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF))
-        {
-            /* Increase load count */
-            LdrEntry->LoadCount++;
-            LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
-
-            /* Clear the load in progress */
-            LdrpClearLoadInProgress();
-        }
-        else
-        {
-            /* Not a DLL, just increase the load count */
-            if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
-        }
+        /* Release the lock */
+        if (!InInit) RtlLeaveCriticalSection(&LdrpLoaderLock);
     }
-
-Quickie:
-    /* Release the lock */
-    if (!InInit) RtlLeaveCriticalSection(&LdrpLoaderLock);
+    _SEH2_END;
 
     /* Check for success */
     if (NT_SUCCESS(Status))
@@ -2687,7 +2696,8 @@ PVOID LdrpGetShimEngineFunction(PCSZ FunctionName)
     NTSTATUS Status;
     PVOID Address;
     RtlInitAnsiString(&Function, FunctionName);
-    Status = LdrGetProcedureAddress(g_pShimEngineModule, &Function, 0, &Address);
+    /* Skip Dll init */
+    Status = LdrpGetProcedureAddress(g_pShimEngineModule, &Function, 0, &Address, FALSE);
     return NT_SUCCESS(Status) ? Address : NULL;
 }
 
@@ -2716,6 +2726,40 @@ LdrpGetShimEngineInterface()
     }
 }
 
+VOID
+NTAPI
+LdrpRunShimEngineInitRoutine(IN ULONG Reason)
+{
+    PLIST_ENTRY ListHead, Next;
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+
+    ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
+    Next = ListHead->Flink;
+    while (Next != ListHead)
+    {
+        LdrEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+
+        if (g_pShimEngineModule == LdrEntry->DllBase)
+        {
+            if (LdrEntry->EntryPoint)
+            {
+                _SEH2_TRY
+                {
+                    LdrpCallInitRoutine(LdrEntry->EntryPoint, LdrEntry->DllBase, Reason, NULL);
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    DPRINT1("WARNING: Exception 0x%x during LdrpRunShimEngineInitRoutine(%u)\n",
+                            _SEH2_GetExceptionCode(), Reason);
+                }
+                _SEH2_END;
+            }
+            return;
+        }
+
+        Next = Next->Flink;
+    }
+}
 
 VOID
 NTAPI
@@ -2725,10 +2769,13 @@ LdrpLoadShimEngine(IN PWSTR ImageName, IN PUNICODE_STRING ProcessImage, IN PVOID
     PVOID ShimLibrary;
     NTSTATUS Status;
     RtlInitUnicodeString(&ShimLibraryName, ImageName);
-    Status = LdrpLoadDll(FALSE, NULL, NULL, &ShimLibraryName, &ShimLibrary, TRUE);
+    /* We should NOT pass CallInit = TRUE!
+       If we do this, other init routines will be called before we get a chance to shim stuff.. */
+    Status = LdrpLoadDll(FALSE, NULL, NULL, &ShimLibraryName, &ShimLibrary, FALSE);
     if (NT_SUCCESS(Status))
     {
         g_pShimEngineModule = ShimLibrary;
+        LdrpRunShimEngineInitRoutine(DLL_PROCESS_ATTACH);
         LdrpGetShimEngineInterface();
         if (g_ShimsEnabled)
         {
@@ -2745,6 +2792,7 @@ LdrpUnloadShimEngine()
 {
     /* Make sure we do not call into the shim engine anymore */
     g_ShimsEnabled = FALSE;
+    LdrpRunShimEngineInitRoutine(DLL_PROCESS_DETACH);
     LdrUnloadDll(g_pShimEngineModule);
     g_pShimEngineModule = NULL;
 }