[CMAKE] Use modules instead of shared libraries
[reactos.git] / dll / ntdll / ldr / ldrutils.c
index 12d487c..4c1adbf 100644 (file)
 /* GLOBALS *******************************************************************/
 
 PLDR_DATA_TABLE_ENTRY LdrpLoadedDllHandleCache, LdrpGetModuleHandleCache;
+
 BOOLEAN g_ShimsEnabled;
+PVOID g_pShimEngineModule;
+PVOID g_pfnSE_DllLoaded;
+PVOID g_pfnSE_DllUnloaded;
+PVOID g_pfnSE_InstallBeforeInit;
+PVOID g_pfnSE_InstallAfterInit;
+PVOID g_pfnSE_ProcessDying;
 
 /* FUNCTIONS *****************************************************************/
 
-/* NOTE: Remove those two once our actctx support becomes better */
-NTSTATUS create_module_activation_context( LDR_DATA_TABLE_ENTRY *module )
-{
-    NTSTATUS status;
-    LDR_RESOURCE_INFO info;
-    IMAGE_RESOURCE_DATA_ENTRY *entry;
-
-    info.Type = (ULONG)RT_MANIFEST;
-    info.Name = (ULONG)ISOLATIONAWARE_MANIFEST_RESOURCE_ID;
-    info.Language = 0;
-    if (!(status = LdrFindResource_U( module->DllBase, &info, 3, &entry )))
-    {
-        ACTCTXW ctx;
-        ctx.cbSize   = sizeof(ctx);
-        ctx.lpSource = NULL;
-        ctx.dwFlags  = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
-        ctx.hModule  = module->DllBase;
-        ctx.lpResourceName = (LPCWSTR)ISOLATIONAWARE_MANIFEST_RESOURCE_ID;
-        status = RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &module->EntryPointActivationContext);
-    }
-    return status;
-}
-
-NTSTATUS find_actctx_dll( LPCWSTR libname, WCHAR *fullname )
-{
-    static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'};
-    static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
-
-    ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info;
-    ACTCTX_SECTION_KEYED_DATA data;
-    UNICODE_STRING nameW;
-    NTSTATUS status;
-    SIZE_T needed, size = 1024;
-    WCHAR *p;
-
-    RtlInitUnicodeString( &nameW, libname );
-    data.cbSize = sizeof(data);
-    status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
-                                                    ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
-                                                    &nameW, &data );
-    if (status != STATUS_SUCCESS) return status;
-
-    for (;;)
-    {
-        if (!(info = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
-        {
-            status = STATUS_NO_MEMORY;
-            goto done;
-        }
-        status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex,
-                                                       AssemblyDetailedInformationInActivationContext,
-                                                       info, size, &needed );
-        if (status == STATUS_SUCCESS) break;
-        if (status != STATUS_BUFFER_TOO_SMALL) goto done;
-        RtlFreeHeap( RtlGetProcessHeap(), 0, info );
-        size = needed;
-    }
-
-    DPRINT("manifestpath === %S\n", info->lpAssemblyManifestPath);
-    DPRINT("DirectoryName === %S\n", info->lpAssemblyDirectoryName);
-    if (!info->lpAssemblyManifestPath || !info->lpAssemblyDirectoryName)
-    {
-        status = STATUS_SXS_KEY_NOT_FOUND;
-        goto done;
-    }
-
-    if ((p = wcsrchr( info->lpAssemblyManifestPath, '\\' )))
-    {
-        DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
-
-        p++;
-        if (_wcsnicmp( p, info->lpAssemblyDirectoryName, dirlen ) || wcsicmp( p + dirlen, dotManifestW ))
-        {
-            /* manifest name does not match directory name, so it's not a global
-             * windows/winsxs manifest; use the manifest directory name instead */
-            dirlen = p - info->lpAssemblyManifestPath;
-            needed = (dirlen + 1) * sizeof(WCHAR) + nameW.Length;
-
-            p = fullname;
-            /*if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
-            {
-                status = STATUS_NO_MEMORY;
-                goto done;
-            }*/
-            memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) );
-            p += dirlen;
-            wcscpy( p, libname );
-            goto done;
-        }
-    }
-
-    needed = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR) +
-              sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + nameW.Length + 2*sizeof(WCHAR));
-
-    p = fullname;
-    //if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
-    //{
-        //status = STATUS_NO_MEMORY;
-        //goto done;
-    //}
-    wcscpy( p, SharedUserData->NtSystemRoot );
-    p += wcslen(p);
-    memcpy( p, winsxsW, sizeof(winsxsW) );
-    p += sizeof(winsxsW) / sizeof(WCHAR);
-    memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength );
-    p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
-    *p++ = '\\';
-    wcscpy( p, libname );
-
-done:
-    RtlFreeHeap( RtlGetProcessHeap(), 0, info );
-    RtlReleaseActivationContext( data.hActCtx );
-    DPRINT("%S\n", fullname);
-    return status;
-}
-
-
 NTSTATUS
 NTAPI
 LdrpAllocateUnicodeString(IN OUT PUNICODE_STRING StringOut,
@@ -160,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 */
@@ -171,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 = (USHORT)Length + sizeof(UNICODE_NULL);
     }
     else
     {
@@ -198,12 +88,13 @@ 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 */
     RtlInitEmptyUnicodeString(StringIn, NULL, 0);
 }
+
 BOOLEAN
 NTAPI
 LdrpCallInitRoutine(IN PDLL_INIT_ROUTINE EntryPoint,
@@ -223,23 +114,35 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
                      OUT PUNICODE_STRING UpdateString)
 {
     PIMAGE_BOUND_FORWARDER_REF NewImportForwarder;
+    PIMAGE_BOUND_IMPORT_DESCRIPTOR FirstEntry;
     PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry;
     PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
     PIMAGE_THUNK_DATA FirstThunk;
     PLDR_DATA_TABLE_ENTRY Entry;
-    PUNICODE_STRING ImportNameUnic;
+    PUNICODE_STRING ImportNameUnic, RedirectedImportName;
     ANSI_STRING ImportNameAnsi;
     LPSTR ImportName;
     ULONG ImportSize;
     NTSTATUS Status;
     ULONG i;
+    BOOLEAN RedirectedDll;
+    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
+
+    /* Set up the Act Ctx */
+    ActCtx.Size = sizeof(ActCtx);
+    ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER;
+    RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
+
+    /* Activate the ActCtx */
+    RtlActivateActivationContextUnsafeFast(&ActCtx,
+                                           LdrEntry->EntryPointActivationContext);
 
     /* Check the action we need to perform */
-    if (Flags == LDRP_UPDATE_REFCOUNT)
+    if ((Flags == LDRP_UPDATE_REFCOUNT) || (Flags == LDRP_UPDATE_PIN))
     {
         /* Make sure entry is not being loaded already */
         if (LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS)
-            return;
+            goto done;
 
         LdrEntry->Flags |= LDRP_LOAD_IN_PROGRESS;
     }
@@ -247,7 +150,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
     {
         /* Make sure the entry is not being unloaded already */
         if (LdrEntry->Flags & LDRP_UNLOAD_IN_PROGRESS)
-            return;
+            goto done;
 
         LdrEntry->Flags |= LDRP_UNLOAD_IN_PROGRESS;
     }
@@ -256,12 +159,12 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
     ImportNameUnic = &NtCurrentTeb()->StaticUnicodeString;
 
     /* Try to get the new import entry */
-    BoundEntry = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(LdrEntry->DllBase,
-                                                                              TRUE,
-                                                                              IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
-                                                                              &ImportSize);
+    FirstEntry = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
+                                              TRUE,
+                                              IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
+                                              &ImportSize);
 
-    if (BoundEntry)
+    if (FirstEntry)
     {
         /* Set entry flags if refing/derefing */
         if (Flags == LDRP_UPDATE_REFCOUNT)
@@ -269,64 +172,49 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
         else if (Flags == LDRP_UPDATE_DEREFCOUNT)
             LdrEntry->Flags |= LDRP_UNLOAD_IN_PROGRESS;
 
+        BoundEntry = FirstEntry;
         while (BoundEntry->OffsetModuleName)
         {
             /* Get pointer to the current import name */
-            ImportName = (PCHAR)BoundEntry + BoundEntry->OffsetModuleName;
+            ImportName = (LPSTR)FirstEntry + BoundEntry->OffsetModuleName;
 
             RtlInitAnsiString(&ImportNameAnsi, ImportName);
             Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
 
             if (NT_SUCCESS(Status))
             {
-                if (LdrpCheckForLoadedDll(NULL,
-                                          ImportNameUnic,
-                                          TRUE,
-                                          FALSE,
-                                          &Entry))
+                RedirectedDll = FALSE;
+                RedirectedImportName = ImportNameUnic;
+
+                /* Check if the SxS Assemblies specify another file */
+                Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
+                                                                  ImportNameUnic,
+                                                                  &LdrApiDefaultExtension,
+                                                                  UpdateString,
+                                                                  NULL,
+                                                                  &RedirectedImportName,
+                                                                  NULL,
+                                                                  NULL,
+                                                                  NULL);
+
+                /* Check success */
+                if (NT_SUCCESS(Status))
                 {
-                    if (Entry->LoadCount != 0xFFFF)
+                    /* Let Ldrp know */
+                    if (ShowSnaps)
                     {
-                        /* Perform the required action */
-                        switch (Flags)
-                        {
-                        case LDRP_UPDATE_REFCOUNT:
-                            Entry->LoadCount++;
-                            break;
-                        case LDRP_UPDATE_DEREFCOUNT:
-                            Entry->LoadCount--;
-                            break;
-                        case LDRP_UPDATE_PIN:
-                            Entry->LoadCount = 0xFFFF;
-                            break;
-                        }
-
-                        /* Show snaps */
-                        if (ShowSnaps)
-                        {
-                            DPRINT1("LDR: Flags %lu  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
-                        }
+                        DPRINT1("LDR: %Z got redirected to %wZ\n", &ImportNameAnsi, RedirectedImportName);
                     }
 
-                    /* Recurse into this entry */
-                    LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
+                    RedirectedDll = TRUE;
                 }
-            }
 
-            /* Go through forwarders */
-            NewImportForwarder = (PIMAGE_BOUND_FORWARDER_REF)(BoundEntry + 1);
-            for (i=0; i<BoundEntry->NumberOfModuleForwarderRefs; i++)
-            {
-                ImportName = (PCHAR)BoundEntry + NewImportForwarder->OffsetModuleName;
-
-                RtlInitAnsiString(&ImportNameAnsi, ImportName);
-                Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
-                if (NT_SUCCESS(Status))
+                if (RedirectedDll || Status == STATUS_SXS_KEY_NOT_FOUND)
                 {
                     if (LdrpCheckForLoadedDll(NULL,
-                                              ImportNameUnic,
+                                              RedirectedImportName,
                                               TRUE,
-                                              FALSE,
+                                              RedirectedDll,
                                               &Entry))
                     {
                         if (Entry->LoadCount != 0xFFFF)
@@ -348,13 +236,105 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
                             /* Show snaps */
                             if (ShowSnaps)
                             {
-                                DPRINT1("LDR: Flags %lu  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
+                                DPRINT1("LDR: Flags %lu  %wZ (%lx)\n", Flags, RedirectedImportName, Entry->LoadCount);
                             }
                         }
 
                         /* Recurse into this entry */
                         LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
                     }
+                    else if (RedirectedDll)
+                    {
+                        DPRINT1("LDR: LdrpCheckForLoadedDll failed for redirected dll %wZ\n", RedirectedImportName);
+                    }
+                }
+                else
+                {
+                    /* Unrecoverable SxS failure */
+                    DPRINT1("LDR: RtlDosApplyFileIsolationRedirection_Ustr failed with status %x for dll %wZ\n", Status, ImportNameUnic);
+                }
+
+            }
+
+            /* Go through forwarders */
+            NewImportForwarder = (PIMAGE_BOUND_FORWARDER_REF)(BoundEntry + 1);
+            for (i = 0; i < BoundEntry->NumberOfModuleForwarderRefs; i++)
+            {
+                ImportName = (LPSTR)FirstEntry + NewImportForwarder->OffsetModuleName;
+
+                RtlInitAnsiString(&ImportNameAnsi, ImportName);
+                Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
+                if (NT_SUCCESS(Status))
+                {
+                    RedirectedDll = FALSE;
+                    RedirectedImportName = ImportNameUnic;
+
+                    /* Check if the SxS Assemblies specify another file */
+                    Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
+                                                                      ImportNameUnic,
+                                                                      &LdrApiDefaultExtension,
+                                                                      UpdateString,
+                                                                      NULL,
+                                                                      &RedirectedImportName,
+                                                                      NULL,
+                                                                      NULL,
+                                                                      NULL);
+                    /* Check success */
+                    if (NT_SUCCESS(Status))
+                    {
+                        if (ShowSnaps)
+                        {
+                            DPRINT1("LDR: %Z got redirected to %wZ\n", &ImportNameAnsi, RedirectedImportName);
+                        }
+                        /* Let Ldrp know */
+                        RedirectedDll = TRUE;
+                    }
+
+                    if (RedirectedDll || Status == STATUS_SXS_KEY_NOT_FOUND)
+                    {
+                        if (LdrpCheckForLoadedDll(NULL,
+                                                  RedirectedImportName,
+                                                  TRUE,
+                                                  RedirectedDll,
+                                                  &Entry))
+                        {
+                            if (Entry->LoadCount != 0xFFFF)
+                            {
+                                /* Perform the required action */
+                                switch (Flags)
+                                {
+                                case LDRP_UPDATE_REFCOUNT:
+                                    Entry->LoadCount++;
+                                    break;
+                                case LDRP_UPDATE_DEREFCOUNT:
+                                    Entry->LoadCount--;
+                                    break;
+                                case LDRP_UPDATE_PIN:
+                                    Entry->LoadCount = 0xFFFF;
+                                    break;
+                                }
+
+                                /* Show snaps */
+                                if (ShowSnaps)
+                                {
+                                    DPRINT1("LDR: Flags %lu  %wZ (%lx)\n", Flags, RedirectedImportName, Entry->LoadCount);
+                                }
+                            }
+
+                            /* Recurse into this entry */
+                            LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
+                        }
+                        else if (RedirectedDll)
+                        {
+                            DPRINT1("LDR: LdrpCheckForLoadedDll failed with status %x for redirected dll %wZ\n", Status, RedirectedImportName);
+                        }
+                    }
+                    else
+                    {
+                        /* Unrecoverable SxS failure */
+                        DPRINT1("LDR: RtlDosApplyFileIsolationRedirection_Ustr failed  with status %x for dll %wZ\n", Status, ImportNameUnic);
+                    }
+
                 }
 
                 NewImportForwarder++;
@@ -364,7 +344,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
         }
 
         /* We're done */
-        return;
+        goto done;
     }
 
     /* Check oldstyle import descriptor */
@@ -392,44 +372,87 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
             Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
             if (NT_SUCCESS(Status))
             {
-                if (LdrpCheckForLoadedDll(NULL,
-                                          ImportNameUnic,
-                                          TRUE,
-                                          FALSE,
-                                          &Entry))
+                RedirectedDll = FALSE;
+                RedirectedImportName = ImportNameUnic;
+
+                /* Check if the SxS Assemblies specify another file */
+                Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
+                                                                  ImportNameUnic,
+                                                                  &LdrApiDefaultExtension,
+                                                                  UpdateString,
+                                                                  NULL,
+                                                                  &RedirectedImportName,
+                                                                  NULL,
+                                                                  NULL,
+                                                                  NULL);
+                /* Check success */
+                if (NT_SUCCESS(Status))
                 {
-                    if (Entry->LoadCount != 0xFFFF)
+                    if (ShowSnaps)
                     {
-                        /* Perform the required action */
-                        switch (Flags)
-                        {
-                        case LDRP_UPDATE_REFCOUNT:
-                            Entry->LoadCount++;
-                            break;
-                        case LDRP_UPDATE_DEREFCOUNT:
-                            Entry->LoadCount--;
-                            break;
-                        case LDRP_UPDATE_PIN:
-                            Entry->LoadCount = 0xFFFF;
-                            break;
-                        }
+                        DPRINT1("LDR: %Z got redirected to %wZ\n", &ImportNameAnsi, RedirectedImportName);
+                    }
 
-                        /* Show snaps */
-                        if (ShowSnaps)
+                    /* Let Ldrp know */
+                    RedirectedDll = TRUE;
+                }
+
+                if (RedirectedDll || Status == STATUS_SXS_KEY_NOT_FOUND)
+                {
+                    if (LdrpCheckForLoadedDll(NULL,
+                                              RedirectedImportName,
+                                              TRUE,
+                                              RedirectedDll,
+                                              &Entry))
+                    {
+                        if (Entry->LoadCount != 0xFFFF)
                         {
-                            DPRINT1("LDR: Flags %lu  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
+                            /* Perform the required action */
+                            switch (Flags)
+                            {
+                            case LDRP_UPDATE_REFCOUNT:
+                                Entry->LoadCount++;
+                                break;
+                            case LDRP_UPDATE_DEREFCOUNT:
+                                Entry->LoadCount--;
+                                break;
+                            case LDRP_UPDATE_PIN:
+                                Entry->LoadCount = 0xFFFF;
+                                break;
+                            }
+
+                            /* Show snaps */
+                            if (ShowSnaps)
+                            {
+                                DPRINT1("LDR: Flags %lu  %wZ (%lx)\n", Flags, RedirectedImportName, Entry->LoadCount);
+                            }
                         }
+
+                        /* Recurse */
+                        LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
+                    }
+                    else if (RedirectedDll)
+                    {
+                        DPRINT1("LDR: LdrpCheckForLoadedDll failed for redirected dll %wZ\n", RedirectedImportName);
                     }
 
-                    /* Recurse */
-                    LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
                 }
+                else
+                {
+                    /* Unrecoverable SxS failure */
+                    DPRINT1("LDR: RtlDosApplyFileIsolationRedirection_Ustr failed for dll %wZ\n", ImportNameUnic);
+                }
+
             }
 
             /* Go to the next entry */
             ImportEntry++;
         }
     }
+
+done:
+    /* Release the context */
+    RtlDeactivateActivationContextUnsafeFast(&ActCtx);    
 }
 
 VOID
@@ -447,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;
@@ -455,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);
@@ -474,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 */
@@ -487,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);
                 }
@@ -501,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;
 }
@@ -677,10 +701,9 @@ LdrpResolveDllName(PWSTR DllPath,
     PWCHAR NameBuffer, p1, p2 = 0;
     ULONG Length;
     ULONG BufSize = 500;
-    NTSTATUS Status;
 
     /* 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,
@@ -692,25 +715,14 @@ LdrpResolveDllName(PWSTR DllPath,
 
     if (!Length || Length > BufSize)
     {
-        /* HACK: Try to find active context dll */
-        Status = find_actctx_dll(DllName, FullDllName->Buffer);
-        if(Status == STATUS_SUCCESS)
+        if (ShowSnaps)
         {
-            Length = wcslen(FullDllName->Buffer) * sizeof(WCHAR);
-            DPRINT1("found %S for %S\n", FullDllName->Buffer, DllName);
+            DPRINT1("LDR: LdrResolveDllName - Unable to find ");
+            DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer);
         }
-        else
-        {
-            /* NOTE: This code should remain after removing the hack */
-            if (ShowSnaps)
-            {
-                DPRINT1("LDR: LdrResolveDllName - Unable to find ");
-                DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer);
-            }
 
-            RtlFreeUnicodeString(FullDllName);
-            return FALSE;
-        }
+        LdrpFreeUnicodeString(FullDllName);
+        return FALSE;
     }
 
     /* Construct full DLL name */
@@ -718,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 */
@@ -754,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;
     }
 
@@ -855,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)
@@ -870,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;
@@ -920,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;
@@ -1050,7 +1062,7 @@ LdrpMapDll(IN PWSTR SearchPath OPTIONAL,
     }
 
     /* Check if we have a known dll directory */
-    if (LdrpKnownDllObjectDirectory)
+    if (LdrpKnownDllObjectDirectory && Redirect == FALSE)
     {
         /* Check if the path is full */
         while (*p1)
@@ -1072,8 +1084,8 @@ LdrpMapDll(IN PWSTR SearchPath OPTIONAL,
         if (!NT_SUCCESS(Status) && (Status != STATUS_DLL_NOT_FOUND))
         {
             /* Failure */
-            DbgPrintEx(81, //DPFLTR_LDR_ID,
-                       0,
+            DbgPrintEx(DPFLTR_LDR_ID,
+                       DPFLTR_ERROR_LEVEL,
                        "LDR: %s - call to LdrpCheckForKnownDll(\"%ws\", ...) failed with status %x\n",
                         __FUNCTION__,
                         DllName,
@@ -1125,8 +1137,8 @@ SkipCheck:
             if (!NT_SUCCESS(Status))
             {
                 /* Free the name strings and return */
-                RtlFreeUnicodeString(&FullDllName);
-                RtlFreeUnicodeString(&BaseDllName);
+                LdrpFreeUnicodeString(&FullDllName);
+                LdrpFreeUnicodeString(&BaseDllName);
                 return Status;
             }
         }
@@ -1270,11 +1282,11 @@ SkipCheck:
         {
             /* Remove the DLL from the lists */
             RemoveEntryList(&LdrEntry->InLoadOrderLinks);
-            RemoveEntryList(&LdrEntry->InMemoryOrderModuleList);
+            RemoveEntryList(&LdrEntry->InMemoryOrderLinks);
             RemoveEntryList(&LdrEntry->HashLinks);
 
             /* Remove the LDR Entry */
-            RtlFreeHeap(RtlGetProcessHeap(), 0, LdrEntry );
+            RtlFreeHeap(LdrpHeap, 0, LdrEntry );
 
             /* Unmap and close section */
             NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
@@ -1320,7 +1332,7 @@ SkipCheck:
         ImageBase = (ULONG_PTR)NtHeaders->OptionalHeader.ImageBase;
         ImageEnd = ImageBase + ViewSize;
 
-        DPRINT1("LDR: LdrpMapDll Relocating Image Name %ws (%lu -> %p)\n", DllName, ImageBase, 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;
@@ -1338,7 +1350,7 @@ SkipCheck:
             CandidateEnd = CandidateBase + CandidateEntry->SizeOfImage;
 
             /* Make sure this entry isn't unloading */
-            if (!CandidateEntry->InMemoryOrderModuleList.Flink) continue;
+            if (!CandidateEntry->InMemoryOrderLinks.Flink) continue;
 
             /* Check if our regions are colliding */
             if ((ImageBase >= CandidateBase && ImageBase <= CandidateEnd) ||
@@ -1359,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)
@@ -1418,7 +1430,7 @@ SkipCheck:
 
                 /* Don't do relocation */
                 Status = STATUS_CONFLICTING_ADDRESSES;
-                goto NoRelocNeeded;
+                goto FailRelocate;
             }
 
             /* Change the protection to prepare for relocation */
@@ -1456,13 +1468,13 @@ SkipCheck:
                     Status = LdrpSetProtection(ViewBase, TRUE);
                 }
             }
-//FailRelocate:
+FailRelocate:
             /* Handle any kind of failure */
             if (!NT_SUCCESS(Status))
             {
                 /* Remove it from the lists */
                 RemoveEntryList(&LdrEntry->InLoadOrderLinks);
-                RemoveEntryList(&LdrEntry->InMemoryOrderModuleList);
+                RemoveEntryList(&LdrEntry->InMemoryOrderLinks);
                 RemoveEntryList(&LdrEntry->HashLinks);
 
                 /* Unmap it, clear the entry */
@@ -1541,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));
 
@@ -1573,7 +1585,7 @@ LdrpInsertMemoryTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
 
     /* Insert into other lists */
     InsertTailList(&PebData->InLoadOrderModuleList, &LdrEntry->InLoadOrderLinks);
-    InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderModuleList);
+    InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderLinks);
 }
 
 VOID
@@ -1596,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
@@ -1627,7 +1639,7 @@ LdrpCheckForLoadedDllHandle(IN PVOID Base,
                                     InLoadOrderLinks);
 
         /* Make sure it's not unloading and check for a match */
-        if ((Current->InMemoryOrderModuleList.Flink) && (Base == Current->DllBase))
+        if ((Current->InMemoryOrderLinks.Flink) && (Base == Current->DllBase))
         {
             /* Save in cache */
             LdrpLoadedDllHandleCache = Current;
@@ -1660,8 +1672,8 @@ LdrpResolveFullName(IN PUNICODE_STRING OriginalName,
     /* Display debug output if snaps are on */
     if (ShowSnaps)
     {
-        DbgPrintEx(81, //DPFLTR_LDR_ID,
-                   0,
+        DbgPrintEx(DPFLTR_LDR_ID,
+                   DPFLTR_ERROR_LEVEL,
                    "LDR: %s - Expanding full name of %wZ\n",
                    __FUNCTION__,
                    OriginalName);
@@ -1737,16 +1749,16 @@ Quickie:
         /* Check which output to use -- failure or success */
         if (NT_SUCCESS(Status))
         {
-            DbgPrintEx(81, //DPFLTR_LDR_ID,
-                       0,
+            DbgPrintEx(DPFLTR_LDR_ID,
+                       DPFLTR_ERROR_LEVEL,
                        "LDR: %s - Expanded to %wZ\n",
                        __FUNCTION__,
                        *ExpandedName);
         }
         else
         {
-            DbgPrintEx(81, //DPFLTR_LDR_ID,
-                       0,
+            DbgPrintEx(DPFLTR_LDR_ID,
+                       DPFLTR_ERROR_LEVEL,
                        "LDR: %s - Failed to expand %wZ; 0x%08x\n",
                        __FUNCTION__,
                        OriginalName,
@@ -1784,8 +1796,8 @@ LdrpSearchPath(IN PWCHAR *SearchPath,
     /* Display debug output if snaps are on */
     if (ShowSnaps)
     {
-        DbgPrintEx(81, //DPFLTR_LDR_ID,
-                   0,
+        DbgPrintEx(DPFLTR_LDR_ID,
+                   DPFLTR_ERROR_LEVEL,
                    "LDR: %s - Looking for %ws in %ws\n",
                    __FUNCTION__,
                    DllName,
@@ -1820,7 +1832,7 @@ LdrpSearchPath(IN PWCHAR *SearchPath,
     /* FIXME: Handle relative case semicolon-lookup here */
 
     /* Calculate length */
-    Length += (ULONG)wcslen(DllName) + sizeof(UNICODE_NULL);
+    Length += (ULONG)wcslen(DllName) + 1;
     if (Length > UNICODE_STRING_MAX_CHARS)
     {
         /* Too long, fail */
@@ -1839,6 +1851,7 @@ LdrpSearchPath(IN PWCHAR *SearchPath,
 
     /* FIXME: Setup TestName here */
     Status = STATUS_NOT_FOUND;
+    BufEnd = Buffer;
 
     /* Start loop */
     do
@@ -1852,8 +1865,8 @@ LdrpSearchPath(IN PWCHAR *SearchPath,
             /* Display debug output if snaps are on */
             if (ShowSnaps)
             {
-                DbgPrintEx(81, //DPFLTR_LDR_ID,
-                           0,
+                DbgPrintEx(DPFLTR_LDR_ID,
+                           DPFLTR_ERROR_LEVEL,
                            "LDR: %s - Looking for %ws\n",
                            __FUNCTION__,
                            Buffer);
@@ -1932,16 +1945,16 @@ Quickie:
         /* Check which output to use -- failure or success */
         if (NT_SUCCESS(Status))
         {
-            DbgPrintEx(81, //DPFLTR_LDR_ID,
-                       0,
+            DbgPrintEx(DPFLTR_LDR_ID,
+                       DPFLTR_ERROR_LEVEL,
                        "LDR: %s - Returning %wZ\n",
                        __FUNCTION__,
                        *ExpandedName);
         }
         else
         {
-            DbgPrintEx(81, //DPFLTR_LDR_ID,
-                       0,
+            DbgPrintEx(DPFLTR_LDR_ID,
+                       DPFLTR_ERROR_LEVEL,
                        "LDR: %s -  Unable to locate %ws in %ws: 0x%08x\n",
                        __FUNCTION__,
                        DllName,
@@ -1989,8 +2002,10 @@ LdrpCheckForLoadedDll(IN PWSTR DllPath,
 
     /* Look in the hash table if flag was set */
 lookinhash:
-    if (Flag)
+    if (Flag  /* the second check is a hack */ && !RedirectedDll)
     {
+        /* FIXME: if we get redirected dll it means that we also get a full path so we need to find its filename for the hash lookup */
+
         /* Get hash index */
         HashIndex = LDR_GET_HASH_ENTRY(DllName->Buffer[0]);
 
@@ -2018,58 +2033,54 @@ lookinhash:
         return FALSE;
     }
 
-    /* Check if there is a full path in this DLL */
-    wc = DllName->Buffer;
-    while (*wc)
+    /* Check if this is a redirected DLL */
+    if (RedirectedDll)
+    {
+        /* Redirected dlls already have a full path */
+        FullPath = TRUE;
+        FullDllName = *DllName;
+    }
+    else
     {
-        /* Check for a slash in the current position*/
-        if ((*wc == L'\\') || (*wc == L'/'))
+        /* Check if there is a full path in this DLL */
+        wc = DllName->Buffer;
+        while (*wc)
         {
-            /* Found the slash, so dll name contains path */
-            FullPath = TRUE;
-
-            /* Setup full dll name string */
-            FullDllName.Buffer = NameBuf;
-
-            /* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */
-            Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer,
-                                        DllName->Buffer,
-                                        NULL,
-                                        sizeof(NameBuf) - sizeof(UNICODE_NULL),
-                                        FullDllName.Buffer,
-                                        NULL);
-
-            /* Check if that was successful */
-            if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL))))
+            /* Check for a slash in the current position*/
+            if ((*wc == L'\\') || (*wc == L'/'))
             {
-                /* HACK: Try to find active context dll */
-                Status = find_actctx_dll(DllName->Buffer, FullDllName.Buffer);
-                if(Status == STATUS_SUCCESS)
-                {
-                    Length = wcslen(FullDllName.Buffer) * sizeof(WCHAR);
-                    DPRINT1("found %S for %S\n", FullDllName.Buffer, DllName->Buffer);
-                }
-                else
-                {
-
-                if (ShowSnaps)
+                /* Found the slash, so dll name contains path */
+                FullPath = TRUE;
+
+                /* Setup full dll name string */
+                FullDllName.Buffer = NameBuf;
+
+                /* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */
+                Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer,
+                                            DllName->Buffer,
+                                            NULL,
+                                            sizeof(NameBuf) - sizeof(UNICODE_NULL),
+                                            FullDllName.Buffer,
+                                            NULL);
+
+                /* Check if that was successful */
+                if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL))))
                 {
-                    DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %ws: 0x%08x\n",
-                        DllName->Buffer, Length);
+                    if (ShowSnaps)
+                    {
+                        DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %wZ: 0x%08x\n",
+                            &DllName, Length);
+                    }
                 }
 
-                /* Return failure */
-                return FALSE;
-                }
+                /* Full dll name is found */
+                FullDllName.Length = Length;
+                FullDllName.MaximumLength = FullDllName.Length + sizeof(UNICODE_NULL);
+                break;
             }
 
-            /* Full dll name is found */
-            FullDllName.Length = Length;
-            FullDllName.MaximumLength = FullDllName.Length + sizeof(UNICODE_NULL);
-            break;
+            wc++;
         }
-
-        wc++;
     }
 
     /* Go check the hash table */
@@ -2080,6 +2091,8 @@ lookinhash:
     }
 
     /* FIXME: Warning, activation context missing */
+    DPRINT("Warning, activation context missing\n");
+
     /* NOTE: From here on down, everything looks good */
 
     /* Loop the module list */
@@ -2094,7 +2107,7 @@ lookinhash:
         ListEntry = ListEntry->Flink;
 
         /* Check if it's being unloaded */
-        if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
+        if (!CurEntry->InMemoryOrderLinks.Flink) continue;
 
         /* Check if name matches */
         if (RtlEqualUnicodeString(&FullDllName,
@@ -2192,7 +2205,7 @@ lookinhash:
         ListEntry = ListEntry->Flink;
 
         /* Check if it's in the process of being unloaded */
-        if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
+        if (!CurEntry->InMemoryOrderLinks.Flink) continue;
 
         /* The header is untrusted, use SEH */
         _SEH2_TRY
@@ -2267,7 +2280,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress,
         }
 
         /* Check if our buffer is large enough */
-        if (Name->Length > sizeof(ImportBuffer))
+        if (Length > sizeof(ImportBuffer))
         {
             /* Allocate from heap, plus 2 bytes for the Hint */
             ImportName = RtlAllocateHeap(RtlGetProcessHeap(),
@@ -2307,7 +2320,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress,
             return STATUS_INVALID_PARAMETER;
         }
 
-        /* Set the orginal flag in the thunk */
+        /* Set the original flag in the thunk */
         Thunk.u1.Ordinal = Ordinal | IMAGE_ORDINAL_FLAG;
     }
 
@@ -2333,7 +2346,8 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress,
 
         if (!ExportDir)
         {
-            DPRINT1("Image %wZ has no exports, but were trying to get procedure %s. BaseAddress asked %p, got entry BA %p\n", &LdrEntry->BaseDllName, Name ? Name->Buffer : NULL, BaseAddress, LdrEntry->DllBase);
+            DPRINT1("Image %wZ has no exports, but were trying to get procedure %Z. BaseAddress asked 0x%p, got entry BA 0x%p\n",
+                    &LdrEntry->BaseDllName, Name, BaseAddress, LdrEntry->DllBase);
             Status = STATUS_PROCEDURE_NOT_FOUND;
             _SEH2_YIELD(goto Quickie;)
         }
@@ -2358,7 +2372,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress,
             Entry = NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Blink;
             LdrEntry = CONTAINING_RECORD(Entry,
                                          LDR_DATA_TABLE_ENTRY,
-                                         InInitializationOrderModuleList);
+                                         InInitializationOrderLinks);
 
             /* Make sure we didn't process it yet*/
             if (!(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
@@ -2454,8 +2468,8 @@ LdrpLoadDll(IN BOOLEAN Redirected,
             sizeof(NameBuffer))
         {
             /* No space to add the extension */
-            DbgPrintEx(81, //DPFLTR_LDR_ID,
-                       0,
+            DbgPrintEx(DPFLTR_LDR_ID,
+                       DPFLTR_ERROR_LEVEL,
                        "LDR: %s - Dll name missing extension; with extension "
                        "added the name is too long\n"
                        "   DllName: (@ %p) \"%wZ\"\n"
@@ -2475,147 +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->InInitializationOrderModuleList);
-
-                /* 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",
-                             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);
 
-        /* Insert it into the list */
-        InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
-                       &LdrEntry->InInitializationOrderModuleList);
+                /* Check if we failed */
+                if (!NT_SUCCESS(Status))
+                {
+                    /* Clear entrypoint, and insert into list */
+                    LdrEntry->EntryPoint = NULL;
+                    InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
+                                   &LdrEntry->InInitializationOrderLinks);
 
-        /* If we have to run the entrypoint, make sure the DB is ready */
-        if (CallInit && LdrpLdrDatabaseIsSetup)
-        {
-            /* FIXME: Notify Shim Engine */
-            if (g_ShimsEnabled)
+                    /* Cancel the load */
+                    LdrpClearLoadInProgress();
+
+                    /* 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)
             {
-                /* Call it */
-                //ShimLoadCallback = RtlDecodeSystemPointer(g_pfnSE_DllLoaded);
-                //ShimLoadCallback(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);
+                }
+
+                /* 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);
                 }
-                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(Peb->LoaderLock);
+    _SEH2_END;
 
     /* Check for success */
     if (NT_SUCCESS(Status))
@@ -2649,7 +2669,7 @@ LdrpClearLoadInProgress(VOID)
         /* Get the loader entry */
         LdrEntry = CONTAINING_RECORD(Entry,
                                      LDR_DATA_TABLE_ENTRY,
-                                     InInitializationOrderModuleList);
+                                     InInitializationOrderLinks);
 
         /* Clear load in progress flag */
         LdrEntry->Flags &= ~LDRP_LOAD_IN_PROGRESS;
@@ -2670,4 +2690,111 @@ LdrpClearLoadInProgress(VOID)
     return ModulesCount;
 }
 
+PVOID LdrpGetShimEngineFunction(PCSZ FunctionName)
+{
+    ANSI_STRING Function;
+    NTSTATUS Status;
+    PVOID Address;
+    RtlInitAnsiString(&Function, FunctionName);
+    /* Skip Dll init */
+    Status = LdrpGetProcedureAddress(g_pShimEngineModule, &Function, 0, &Address, FALSE);
+    return NT_SUCCESS(Status) ? Address : NULL;
+}
+
+VOID
+NTAPI
+LdrpGetShimEngineInterface()
+{
+    PVOID SE_DllLoaded = LdrpGetShimEngineFunction("SE_DllLoaded");
+    PVOID SE_DllUnloaded = LdrpGetShimEngineFunction("SE_DllUnloaded");
+    PVOID SE_InstallBeforeInit = LdrpGetShimEngineFunction("SE_InstallBeforeInit");
+    PVOID SE_InstallAfterInit = LdrpGetShimEngineFunction("SE_InstallAfterInit");
+    PVOID SE_ProcessDying = LdrpGetShimEngineFunction("SE_ProcessDying");
+
+    if (SE_DllLoaded && SE_DllUnloaded && SE_InstallBeforeInit && SE_InstallAfterInit && SE_ProcessDying)
+    {
+        g_pfnSE_DllLoaded = RtlEncodeSystemPointer(SE_DllLoaded);
+        g_pfnSE_DllUnloaded = RtlEncodeSystemPointer(SE_DllUnloaded);
+        g_pfnSE_InstallBeforeInit = RtlEncodeSystemPointer(SE_InstallBeforeInit);
+        g_pfnSE_InstallAfterInit = RtlEncodeSystemPointer(SE_InstallAfterInit);
+        g_pfnSE_ProcessDying = RtlEncodeSystemPointer(SE_ProcessDying);
+        g_ShimsEnabled = TRUE;
+    }
+    else
+    {
+        LdrpUnloadShimEngine();
+    }
+}
+
+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
+LdrpLoadShimEngine(IN PWSTR ImageName, IN PUNICODE_STRING ProcessImage, IN PVOID pShimData)
+{
+    UNICODE_STRING ShimLibraryName;
+    PVOID ShimLibrary;
+    NTSTATUS Status;
+    RtlInitUnicodeString(&ShimLibraryName, ImageName);
+    /* 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)
+        {
+            VOID(NTAPI *SE_InstallBeforeInit)(PUNICODE_STRING, PVOID);
+            SE_InstallBeforeInit = RtlDecodeSystemPointer(g_pfnSE_InstallBeforeInit);
+            SE_InstallBeforeInit(ProcessImage, pShimData);
+        }
+    }
+}
+
+VOID
+NTAPI
+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;
+}
+
 /* EOF */