[NTDLL]: Fix 2 DPRINTs.
[reactos.git] / reactos / dll / ntdll / ldr / ldrutils.c
index 59c653e..3cc7608 100644 (file)
 /* INCLUDES *****************************************************************/
 
 #include <ntdll.h>
+
 #define NDEBUG
 #include <debug.h>
 
 /* GLOBALS *******************************************************************/
 
 PLDR_DATA_TABLE_ENTRY LdrpLoadedDllHandleCache, LdrpGetModuleHandleCache;
+BOOLEAN g_ShimsEnabled;
 
 /* 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,
+                          IN ULONG Length)
+{
+    /* Sanity checks */
+    ASSERT(StringOut);
+    ASSERT(Length <= UNICODE_STRING_MAX_BYTES);
+
+    /* Assume failure */
+    StringOut->Length = 0;
+
+    /* Make sure it's not mis-aligned */
+    if (Length & 1)
+    {
+        /* Fail */
+        StringOut->Buffer = NULL;
+        StringOut->MaximumLength = 0;
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Allocate the string*/
+    StringOut->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+                                        0,
+                                        StringOut->Length + sizeof(WCHAR));
+    if (!StringOut->Buffer)
+    {
+        /* Fail */
+        StringOut->MaximumLength = 0;
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Null-terminate it */
+    StringOut->Buffer[StringOut->Length / sizeof(WCHAR)] = UNICODE_NULL;
+
+    /* Check if this is a maximum-sized string */
+    if (StringOut->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);
+    }
+    else
+    {
+        /* The length is already the maximum possible */
+        StringOut->MaximumLength = UNICODE_STRING_MAX_BYTES;
+    }
+
+    /* Return success */
+    return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+LdrpFreeUnicodeString(IN PUNICODE_STRING StringIn)
+{
+    ASSERT(StringIn != NULL);
+
+    /* If Buffer is not NULL - free it */
+    if (StringIn->Buffer)
+    {
+        RtlFreeHeap(RtlGetProcessHeap(), 0, StringIn->Buffer);
+    }
+
+    /* Zero it out */
+    RtlInitEmptyUnicodeString(StringIn, NULL, 0);
+}
 BOOLEAN
 NTAPI
 LdrpCallInitRoutine(IN PDLL_INIT_ROUTINE EntryPoint,
@@ -119,7 +304,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
                         /* Show snaps */
                         if (ShowSnaps)
                         {
-                            DPRINT1("LDR: Flags %d  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
+                            DPRINT1("LDR: Flags %lu  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
                         }
                     }
 
@@ -163,7 +348,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
                             /* Show snaps */
                             if (ShowSnaps)
                             {
-                                DPRINT1("LDR: Flags %d  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
+                                DPRINT1("LDR: Flags %lu  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
                             }
                         }
 
@@ -232,7 +417,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
                         /* Show snaps */
                         if (ShowSnaps)
                         {
-                            DPRINT1("LDR: Flags %d  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
+                            DPRINT1("LDR: Flags %lu  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
                         }
                     }
 
@@ -492,6 +677,7 @@ 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));
@@ -506,14 +692,25 @@ LdrpResolveDllName(PWSTR DllPath,
 
     if (!Length || Length > BufSize)
     {
-        if (ShowSnaps)
+        /* HACK: Try to find active context dll */
+        Status = find_actctx_dll(DllName, FullDllName->Buffer);
+        if(Status == STATUS_SUCCESS)
         {
-            DPRINT1("LDR: LdrResolveDllName - Unable to find ");
-            DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer);
+            Length = wcslen(FullDllName->Buffer) * sizeof(WCHAR);
+            DPRINT1("found %S for %S\n", FullDllName->Buffer, DllName);
         }
+        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;
+            RtlFreeUnicodeString(FullDllName);
+            return FALSE;
+        }
     }
 
     /* Construct full DLL name */
@@ -596,12 +793,13 @@ LdrpFetchAddressOfEntryPoint(IN PVOID ImageBase)
     return (PVOID)EntryPoint;
 }
 
-/* NOTE: This function is broken, wrong number of parameters, no SxS, etc */
-HANDLE
+/* NOTE: This function is partially missing SxS */
+NTSTATUS
 NTAPI
 LdrpCheckForKnownDll(PWSTR DllName,
                      PUNICODE_STRING FullDllName,
-                     PUNICODE_STRING BaseDllName)
+                     PUNICODE_STRING BaseDllName,
+                     HANDLE *SectionHandle)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     HANDLE Section = NULL;
@@ -610,9 +808,35 @@ LdrpCheckForKnownDll(PWSTR DllName,
     PCHAR p1;
     PWCHAR p2;
 
+    /* Zero initialize provided parameters */
+    if (SectionHandle) *SectionHandle = 0;
+
+    if (FullDllName)
+    {
+        FullDllName->Length = 0;
+        FullDllName->MaximumLength = 0;
+        FullDllName->Buffer = NULL;
+    }
+
+    if (BaseDllName)
+    {
+        BaseDllName->Length = 0;
+        BaseDllName->MaximumLength = 0;
+        BaseDllName->Buffer = NULL;
+    }
+
+    /* If any of these three params are missing then fail */
+    if (!SectionHandle || !FullDllName || !BaseDllName)
+        return STATUS_INVALID_PARAMETER;
+
+    /* Check the Loader Lock */
+    LdrpEnsureLoaderLockIsHeld();
+
     /* Upgrade DllName to a unicode string */
     RtlInitUnicodeString(&DllNameUnic, DllName);
 
+    /* FIXME: Missing RtlComputePrivatizedDllName_U related functionality */
+
     /* Get the activation context */
     Status = RtlFindActivationContextSectionString(0,
                                                    NULL,
@@ -624,13 +848,21 @@ LdrpCheckForKnownDll(PWSTR DllName,
     if (Status == STATUS_SXS_SECTION_NOT_FOUND ||
         Status == STATUS_SXS_KEY_NOT_FOUND)
     {
+        /* NOTE: Here it's beneficial to allocate one big unicode string
+                 using LdrpAllocateUnicodeString instead of fragmenting the heap
+                 with two allocations as it's done now. */
+
         /* Set up BaseDllName */
         BaseDllName->Length = DllNameUnic.Length;
         BaseDllName->MaximumLength = DllNameUnic.MaximumLength;
         BaseDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
                                               0,
                                               DllNameUnic.MaximumLength);
-        if (!BaseDllName->Buffer) return NULL;
+        if (!BaseDllName->Buffer)
+        {
+            Status = STATUS_NO_MEMORY;
+            goto Failure;
+        }
 
         /* Copy the contents there */
         RtlMoveMemory(BaseDllName->Buffer, DllNameUnic.Buffer, DllNameUnic.MaximumLength);
@@ -641,9 +873,8 @@ LdrpCheckForKnownDll(PWSTR DllName,
         FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullDllName->MaximumLength);
         if (!FullDllName->Buffer)
         {
-            /* Free base name and fail */
-            RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer);
-            return NULL;
+            Status = STATUS_NO_MEMORY;
+            goto Failure;
         }
 
         RtlMoveMemory(FullDllName->Buffer, LdrpKnownDllPath.Buffer, LdrpKnownDllPath.Length);
@@ -674,19 +905,26 @@ LdrpCheckForKnownDll(PWSTR DllName,
                                &ObjectAttributes);
         if (!NT_SUCCESS(Status))
         {
-            /* Opening failed, free resources */
-            Section = NULL;
-            RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer);
+            /* Clear status in case it was just not found */
+            if (Status == STATUS_OBJECT_NAME_NOT_FOUND) Status = STATUS_SUCCESS;
+            goto Failure;
         }
+
+        /* Pass section handle to the caller and return success */
+        *SectionHandle = Section;
+        return STATUS_SUCCESS;
     }
-    else
-    {
-        if (!NT_SUCCESS(Status)) Section = NULL;
-    }
 
-    /* Return section handle */
-    return Section;
+Failure:
+    /* Close section object if it was opened */
+    if (Section) NtClose(Section);
+
+    /* Free string resources */
+    if (BaseDllName->Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer);
+    if (FullDllName->Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer);
+
+    /* Return status */
+    return Status;
 }
 
 NTSTATUS
@@ -826,9 +1064,23 @@ LdrpMapDll(IN PWSTR SearchPath OPTIONAL,
         }
 
         /* Try to find a Known DLL */
-        SectionHandle = LdrpCheckForKnownDll(DllName,
-                                             &FullDllName,
-                                             &BaseDllName);
+        Status = LdrpCheckForKnownDll(DllName,
+                                      &FullDllName,
+                                      &BaseDllName,
+                                      &SectionHandle);
+
+        if (!NT_SUCCESS(Status) && (Status != STATUS_DLL_NOT_FOUND))
+        {
+            /* Failure */
+            DbgPrintEx(81, //DPFLTR_LDR_ID,
+                       0,
+                       "LDR: %s - call to LdrpCheckForKnownDll(\"%ws\", ...) failed with status %x\n",
+                        __FUNCTION__,
+                        DllName,
+                        Status);
+
+            return Status;
+        }
     }
 
 SkipCheck:
@@ -1068,7 +1320,7 @@ SkipCheck:
         ImageBase = (ULONG_PTR)NtHeaders->OptionalHeader.ImageBase;
         ImageEnd = ImageBase + ViewSize;
 
-        DPRINT1("LDR: LdrpMapDll Relocating Image Name %ws (%p -> %p)\n", DllName, ImageBase, ViewBase);
+        DPRINT1("LDR: LdrpMapDll Relocating Image Name %ws (%p -> %p)\n", DllName, (PVOID)ImageBase, ViewBase);
 
         /* Scan all the modules */
         ListHead = &Peb->Ldr->InLoadOrderModuleList;
@@ -1146,8 +1398,8 @@ SkipCheck:
                 }
             }
 
-            /* Check if this was a non-relocatable DLL or a known dll */
-            if (!RelocatableDll && KnownDll)
+            /* Known DLLs are not allowed to be relocated */
+            if (KnownDll && !RelocatableDll)
             {
                 /* Setup for hard error */
                 HardErrorParameters[0] = (ULONG_PTR)&IllegalDll;
@@ -1184,7 +1436,7 @@ SkipCheck:
                     /* Stuff the image name in the TIB, for the debugger */
                     ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
                     Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
-
+#if 0
                     /* Map the DLL */
                     Status = NtMapViewOfSection(SectionHandle,
                                                 NtCurrentProcess(),
@@ -1196,7 +1448,7 @@ SkipCheck:
                                                 ViewShare,
                                                 0,
                                                 PAGE_READWRITE);
-
+#endif
                     /* Restore */
                     Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
 
@@ -1234,7 +1486,7 @@ NoRelocNeeded:
             /* Stuff the image name in the TIB, for the debugger */
             ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
             Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
-
+#if 0
             /* Map the DLL */
             Status = NtMapViewOfSection(SectionHandle,
                                         NtCurrentProcess(),
@@ -1246,7 +1498,7 @@ NoRelocNeeded:
                                         ViewShare,
                                         0,
                                         PAGE_READWRITE);
-
+#endif
             /* Restore */
             Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
 
@@ -1393,6 +1645,317 @@ LdrpCheckForLoadedDllHandle(IN PVOID Base,
     return FALSE;
 }
 
+NTSTATUS
+NTAPI
+LdrpResolveFullName(IN PUNICODE_STRING OriginalName,
+                    IN PUNICODE_STRING PathName,
+                    IN PUNICODE_STRING FullPathName,
+                    IN PUNICODE_STRING *ExpandedName)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+//    RTL_PATH_TYPE PathType;
+//    BOOLEAN InvalidName;
+    ULONG Length;
+
+    /* Display debug output if snaps are on */
+    if (ShowSnaps)
+    {
+        DbgPrintEx(81, //DPFLTR_LDR_ID,
+                   0,
+                   "LDR: %s - Expanding full name of %wZ\n",
+                   __FUNCTION__,
+                   OriginalName);
+    }
+
+    /* FIXME: Lock the PEB */
+    //RtlEnterCriticalSection(&FastPebLock);
+#if 0
+    /* Get the path name */
+    Length = RtlGetFullPathName_Ustr(OriginalName,
+                                     PathName->Length,
+                                     PathName->Buffer,
+                                     NULL,
+                                     &InvalidName,
+                                     &PathType);
+#else
+    Length = 0;
+#endif
+    if (!(Length) || (Length > UNICODE_STRING_MAX_BYTES))
+    {
+        /* Fail */
+        Status = STATUS_NAME_TOO_LONG;
+        goto Quickie;
+    }
+
+    /* Check if the length hasn't changed */
+    if (Length <= PathName->Length)
+    {
+        /* Return the same thing */
+        *ExpandedName = PathName;
+        PathName->Length = (USHORT)Length;
+        goto Quickie;
+    }
+
+    /* Sanity check */
+    ASSERT(Length >= sizeof(WCHAR));
+
+    /* Allocate a string */
+    Status = LdrpAllocateUnicodeString(FullPathName, Length - sizeof(WCHAR));
+    if (!NT_SUCCESS(Status)) goto Quickie;
+
+    /* Now get the full path again */
+#if 0
+    Length = RtlGetFullPathName_Ustr(OriginalName,
+                                     FullPathName->Length,
+                                     FullPathName->Buffer,
+                                     NULL,
+                                     &InvalidName,
+                                     &PathType);
+#else
+    Length = 0;
+#endif
+    if (!(Length) || (Length > FullPathName->Length))
+    {
+        /* Fail */
+        LdrpFreeUnicodeString(FullPathName);
+        Status = STATUS_NAME_TOO_LONG;
+    }
+    else
+    {
+        /* Return the expanded name */
+        *ExpandedName = FullPathName;
+        FullPathName->Length = (USHORT)Length;
+    }
+
+Quickie:
+    /* FIXME: Unlock the PEB */
+    //RtlLeaveCriticalSection(&FastPebLock);
+
+    /* Display debug output if snaps are on */
+    if (ShowSnaps)
+    {
+        /* Check which output to use -- failure or success */
+        if (NT_SUCCESS(Status))
+        {
+            DbgPrintEx(81, //DPFLTR_LDR_ID,
+                       0,
+                       "LDR: %s - Expanded to %wZ\n",
+                       __FUNCTION__,
+                       *ExpandedName);
+        }
+        else
+        {
+            DbgPrintEx(81, //DPFLTR_LDR_ID,
+                       0,
+                       "LDR: %s - Failed to expand %wZ; 0x%08x\n",
+                       __FUNCTION__,
+                       OriginalName,
+                       Status);
+        }
+    }
+
+    /* If we failed, return NULL */
+    if (!NT_SUCCESS(Status)) *ExpandedName = NULL;
+
+    /* Return status */
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+LdrpSearchPath(IN PWCHAR *SearchPath,
+               IN PWCHAR DllName,
+               IN PUNICODE_STRING PathName,
+               IN PUNICODE_STRING FullPathName,
+               IN PUNICODE_STRING *ExpandedName)
+{
+    BOOLEAN TryAgain = FALSE;
+    PWCHAR ActualSearchPath = *SearchPath;
+    UNICODE_STRING TestName;
+    NTSTATUS Status;
+    PWCHAR Buffer, BufEnd = NULL;
+    ULONG Length = 0;
+    WCHAR p;
+    //PWCHAR pp;
+
+    /* Check if we don't have a search path */
+    if (!ActualSearchPath) *SearchPath = LdrpDefaultPath.Buffer;
+
+    /* Display debug output if snaps are on */
+    if (ShowSnaps)
+    {
+        DbgPrintEx(81, //DPFLTR_LDR_ID,
+                   0,
+                   "LDR: %s - Looking for %ws in %ws\n",
+                   __FUNCTION__,
+                   DllName,
+                   *SearchPath);
+    }
+
+    /* Check if we're dealing with a relative path */
+    if (RtlDetermineDosPathNameType_U(DllName) != RtlPathTypeRelative)
+    {
+        /* Good, we're not. Create the name string */
+        Status = RtlInitUnicodeStringEx(&TestName, DllName);
+        if (!NT_SUCCESS(Status)) goto Quickie;
+
+        /* Make sure it exists */
+        #if 0
+        if (!RtlDoesFileExists_UstrEx(&TestName, TRUE))
+        {
+            /* It doesn't, fail */
+            Status = STATUS_DLL_NOT_FOUND;
+            goto Quickie;
+        }
+        #endif
+
+        /* Resolve the full name */
+        Status = LdrpResolveFullName(&TestName,
+                                     PathName,
+                                     FullPathName,
+                                     ExpandedName);
+        goto Quickie;
+    }
+
+    /* FIXME: Handle relative case semicolon-lookup here */
+
+    /* Calculate length */
+    Length += (ULONG)wcslen(DllName) + sizeof(UNICODE_NULL);
+    if (Length > UNICODE_STRING_MAX_CHARS)
+    {
+        /* Too long, fail */
+        Status = STATUS_NAME_TOO_LONG;
+        goto Quickie;
+    }
+
+    /* Allocate buffer */
+    Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
+    if (!Buffer)
+    {
+        /* Fail */
+        Status = STATUS_NO_MEMORY;
+        goto Quickie;
+    }
+
+    /* FIXME: Setup TestName here */
+    Status = STATUS_NOT_FOUND;
+
+    /* Start loop */
+    do
+    {
+        /* Get character */
+        p = *ActualSearchPath;
+        if (!(p) || (p == ';'))
+        {
+            /* FIXME: We don't have a character, or is a semicolon.*/
+
+            /* Display debug output if snaps are on */
+            if (ShowSnaps)
+            {
+                DbgPrintEx(81, //DPFLTR_LDR_ID,
+                           0,
+                           "LDR: %s - Looking for %ws\n",
+                           __FUNCTION__,
+                           Buffer);
+            }
+
+            /* Sanity check */
+            TestName.Length = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR);
+#if 0
+            ASSERT(TestName.Length < TestName.MaximumLength);
+#endif
+
+            /* Check if the file exists */
+            #if 0
+            if (RtlDoesFileExists_UstrEx(&TestName, FALSE))
+            #endif
+            {
+                /* It does. Reallocate the buffer */
+                TestName.MaximumLength = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR) + sizeof(WCHAR);
+                TestName.Buffer = RtlReAllocateHeap(RtlGetProcessHeap(),
+                                                    0,
+                                                    Buffer,
+                                                    TestName.MaximumLength);
+                if (!TestName.Buffer)
+                {
+                    /* Keep the old one */
+                    TestName.Buffer = Buffer;
+                }
+                else
+                {
+                    /* Update buffer */
+                    Buffer = TestName.Buffer;
+                }
+
+                /* Make sure we have a buffer at least */
+                ASSERT(TestName.Buffer);
+
+                /* Resolve the name */
+                *SearchPath = ActualSearchPath++;
+                Status = LdrpResolveFullName(&TestName,
+                                             PathName,
+                                             FullPathName,
+                                             ExpandedName);
+                break;
+            }
+
+            /* Update buffer end */
+            BufEnd = Buffer;
+
+            /* Update string position */
+            //pp = ActualSearchPath++;
+        }
+        else
+        {
+            /* Otherwise, write the character */
+            *BufEnd = p;
+            BufEnd++;
+        }
+
+        /* Check if the string is empty, meaning we're done */
+        if (!(*ActualSearchPath)) TryAgain = TRUE;
+
+        /* Advance in the string */
+        ActualSearchPath++;
+    } while (!TryAgain);
+
+    /* Check if we had a buffer and free it */
+    if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+
+Quickie:
+    /* Check if we got here through failure */
+    if (!NT_SUCCESS(Status)) *ExpandedName = NULL;
+
+    /* Display debug output if snaps are on */
+    if (ShowSnaps)
+    {
+        /* Check which output to use -- failure or success */
+        if (NT_SUCCESS(Status))
+        {
+            DbgPrintEx(81, //DPFLTR_LDR_ID,
+                       0,
+                       "LDR: %s - Returning %wZ\n",
+                       __FUNCTION__,
+                       *ExpandedName);
+        }
+        else
+        {
+            DbgPrintEx(81, //DPFLTR_LDR_ID,
+                       0,
+                       "LDR: %s -  Unable to locate %ws in %ws: 0x%08x\n",
+                       __FUNCTION__,
+                       DllName,
+                       ActualSearchPath,
+                       Status);
+        }
+    }
+
+    /* Return status */
+    return Status;
+}
+
+
+/* NOTE: This function is b0rked and in the process of being slowly unf*cked */
 BOOLEAN
 NTAPI
 LdrpCheckForLoadedDll(IN PWSTR DllPath,
@@ -1416,11 +1979,13 @@ LdrpCheckForLoadedDll(IN PWSTR DllPath,
     PVOID ViewBase = NULL;
     SIZE_T ViewSize = 0;
     PIMAGE_NT_HEADERS NtHeader, NtHeader2;
-
-    DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath, DllName, Flag, RedirectedDll, LdrEntry);
+    DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %u %u %p)\n", DllPath ? ((ULONG_PTR)DllPath == 1 ? L"" : DllPath) : L"", DllName, Flag, RedirectedDll, LdrEntry);
 
     /* Check if a dll name was provided */
-    if (!DllName->Buffer || !DllName->Buffer[0]) return FALSE;
+    if (!(DllName->Buffer) || !(DllName->Buffer[0])) return FALSE;
+
+    /* FIXME: Warning, "Flag" is used as magic instead of "Static" */
+    /* FIXME: Warning, code does not support redirection at all */
 
     /* Look in the hash table if flag was set */
 lookinhash:
@@ -1458,7 +2023,7 @@ lookinhash:
     while (*wc)
     {
         /* Check for a slash in the current position*/
-        if (*wc == L'\\' || *wc == L'/')
+        if ((*wc == L'\\') || (*wc == L'/'))
         {
             /* Found the slash, so dll name contains path */
             FullPath = TRUE;
@@ -1466,6 +2031,7 @@ lookinhash:
             /* 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,
@@ -1474,16 +2040,27 @@ lookinhash:
                                         NULL);
 
             /* Check if that was successful */
-            if (!Length || Length > sizeof(NameBuf) - sizeof(UNICODE_NULL))
+            if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL))))
             {
+                /* 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)
                 {
-                    DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %ws: 0x%08x\n",
-                        DllName->Buffer, Length);
+                    DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %wZ: 0x%08x\n",
+                        &DllName, Length);
                 }
 
                 /* Return failure */
                 return FALSE;
+                }
             }
 
             /* Full dll name is found */
@@ -1502,17 +2079,21 @@ lookinhash:
         goto lookinhash;
     }
 
-    /* Now go through the InLoadOrder module list */
+    /* FIXME: Warning, activation context missing */
+    /* NOTE: From here on down, everything looks good */
+
+    /* Loop the module list */
     ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
     ListEntry = ListHead->Flink;
-
     while (ListEntry != ListHead)
     {
-        /* Get the containing record of the current entry and advance to the next one */
-        CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+        /* Get the current entry and advance to the next one */
+        CurEntry = CONTAINING_RECORD(ListEntry,
+                                     LDR_DATA_TABLE_ENTRY,
+                                     InLoadOrderLinks);
         ListEntry = ListEntry->Flink;
 
-        /* Check if it's already being unloaded */
+        /* Check if it's being unloaded */
         if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
 
         /* Check if name matches */
@@ -1522,18 +2103,10 @@ lookinhash:
         {
             /* Found it */
             *LdrEntry = CurEntry;
-
-            /* Find activation context */
-            //Status = RtlFindActivationContextSectionString(0, NULL, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, DllName, NULL);
-            //if (!NT_SUCCESS(Status))
-            //    return FALSE;
-            //else
             return TRUE;
         }
     }
 
-    /* The DLL was not found in the load order modules list. Perform a complex check */
-
     /* Convert given path to NT path */
     if (!RtlDosPathNameToNtPathName_U(FullDllName.Buffer,
                                       &NtPathName,
@@ -1550,7 +2123,6 @@ lookinhash:
                                OBJ_CASE_INSENSITIVE,
                                NULL,
                                NULL);
-
     Status = NtOpenFile(&FileHandle,
                         SYNCHRONIZE | FILE_EXECUTE,
                         &ObjectAttributes,
@@ -1566,7 +2138,9 @@ lookinhash:
 
     /* Create a section for this file */
     Status = NtCreateSection(&SectionHandle,
-                             SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_WRITE,
+                             SECTION_MAP_READ |
+                             SECTION_MAP_EXECUTE |
+                             SECTION_MAP_WRITE,
                              NULL,
                              NULL,
                              PAGE_EXECUTE,
@@ -1590,6 +2164,7 @@ lookinhash:
                                 ViewShare,
                                 0,
                                 PAGE_EXECUTE);
+
     /* Close section handle */
     NtClose(SectionHandle);
 
@@ -1597,52 +2172,46 @@ lookinhash:
     if (!NT_SUCCESS(Status)) return FALSE;
 
     /* Get pointer to the NT header of this section */
-    NtHeader = RtlImageNtHeader(ViewBase);
-    if (!NtHeader)
+    Status = RtlImageNtHeaderEx(0, ViewBase, ViewSize, &NtHeader);
+    if (!(NT_SUCCESS(Status)) || !(NtHeader))
     {
         /* Unmap the section and fail */
         NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
         return FALSE;
     }
 
-    /* Go through the list of modules */
+    /* Go through the list of modules again */
     ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
     ListEntry = ListHead->Flink;
-
     while (ListEntry != ListHead)
     {
-        CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+        /* Get the current entry and advance to the next one */
+        CurEntry = CONTAINING_RECORD(ListEntry,
+                                     LDR_DATA_TABLE_ENTRY,
+                                     InLoadOrderLinks);
         ListEntry = ListEntry->Flink;
 
-        /* Check if it's already being unloaded */
+        /* Check if it's in the process of being unloaded */
         if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
 
+        /* The header is untrusted, use SEH */
         _SEH2_TRY
         {
             /* Check if timedate stamp and sizes match */
-            if (CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp &&
-                CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage)
+            if ((CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp) &&
+                (CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage))
             {
                 /* Time, date and size match. Let's compare their headers */
                 NtHeader2 = RtlImageNtHeader(CurEntry->DllBase);
-
                 if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS)))
                 {
                     /* Headers match too! Finally ask the kernel to compare mapped files */
                     Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase);
-
-                    if (!NT_SUCCESS(Status))
-                    {
-                        _SEH2_YIELD(continue;)
-                    }
-                    else
+                    if (NT_SUCCESS(Status))
                     {
-                        /* This is our entry! */
+                        /* This is our entry!, unmap and return success */
                         *LdrEntry = CurEntry;
-
-                        /* Unmap the section */
                         NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
-
                         _SEH2_YIELD(return TRUE;)
                     }
                 }
@@ -1655,9 +2224,8 @@ lookinhash:
         _SEH2_END;
     }
 
-    /* Unmap the section */
+    /* Unmap the section and fail */
     NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
-
     return FALSE;
 }
 
@@ -1699,7 +2267,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(),
@@ -1765,7 +2333,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;)
         }
@@ -1848,71 +2417,61 @@ LdrpLoadDll(IN BOOLEAN Redirected,
 {
     PPEB Peb = NtCurrentPeb();
     NTSTATUS Status = STATUS_SUCCESS;
-    PWCHAR p1, p2;
-    WCHAR NameBuffer[266];
-    LPWSTR RawDllName;
-    UNICODE_STRING RawDllNameString;
+    const WCHAR *p;
+    BOOLEAN GotExtension;
+    WCHAR c;
+    WCHAR NameBuffer[MAX_PATH + 6];
+    UNICODE_STRING RawDllName;
     PLDR_DATA_TABLE_ENTRY LdrEntry;
     BOOLEAN InInit = LdrpInLdrInit;
 
-    /* Find the name without the extension */
-    p1 = DllName->Buffer;
-StartLoop:
-    p2 = NULL;
-    while (*p1)
+    /* Save the Raw DLL Name */
+    if (DllName->Length >= sizeof(NameBuffer)) return STATUS_NAME_TOO_LONG;
+    RtlInitEmptyUnicodeString(&RawDllName, NameBuffer, sizeof(NameBuffer));
+    RtlCopyUnicodeString(&RawDllName, DllName);
+
+    /* Find the extension, if present */
+    p = DllName->Buffer + DllName->Length / sizeof(WCHAR) - 1;
+    GotExtension = FALSE;
+    while (p >= DllName->Buffer)
     {
-        if (*p1++ == L'.')
+        c = *p--;
+        if (c == L'.')
         {
-            p2 = p1;
+            GotExtension = TRUE;
+            break;
         }
-        else if (*p1 == L'\\')
+        else if (c == L'\\')
         {
-            goto StartLoop;
+            break;
         }
     }
 
-    /* Save the Raw DLL Name */
-    RawDllName = NameBuffer;
-    if (DllName->Length >= sizeof(NameBuffer))
-    {
-        /* The DLL's name is too long */
-        return STATUS_NAME_TOO_LONG;
-    }
-    RtlMoveMemory(RawDllName, DllName->Buffer, DllName->Length);
-
-    /* Check if no extension was found or if we got a slash */
-    if (!p2 || *p2 == '\\')
+    /* If no extension was found, add the default extension */
+    if (!GotExtension)
     {
         /* Check that we have space to add one */
-        if (DllName->Length + LdrApiDefaultExtension.Length >= sizeof(NameBuffer))
+        if ((DllName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL)) >=
+            sizeof(NameBuffer))
         {
             /* No space to add the extension */
+            DbgPrintEx(81, //DPFLTR_LDR_ID,
+                       0,
+                       "LDR: %s - Dll name missing extension; with extension "
+                       "added the name is too long\n"
+                       "   DllName: (@ %p) \"%wZ\"\n"
+                       "   DllName->Length: %u\n",
+                       __FUNCTION__,
+                       DllName,
+                       DllName,
+                       DllName->Length);
             return STATUS_NAME_TOO_LONG;
         }
 
-        /* Add it */
-        RtlMoveMemory((PVOID)((ULONG_PTR)RawDllName + DllName->Length),
-                      LdrApiDefaultExtension.Buffer,
-                      LdrApiDefaultExtension.Length);
-
-        /* Save the length to a unicode string */
-        RawDllNameString.Length = DllName->Length + LdrApiDefaultExtension.Length;
-
-        /* Null terminate it */
-        RawDllName[RawDllNameString.Length / sizeof(WCHAR)] = 0;
+        /* Add it. Needs to be null terminated, thus the length check above */
+        (VOID)RtlAppendUnicodeStringToString(&RawDllName,
+                                             &LdrApiDefaultExtension);
     }
-    else
-    {
-        /* Null terminate it */
-        RawDllName[DllName->Length / sizeof(WCHAR)] = 0;
-
-        /* Save the length to a unicode string */
-        RawDllNameString.Length = DllName->Length;
-    }
-
-    /* Now create a unicode string for the DLL's name */
-    RawDllNameString.MaximumLength = sizeof(NameBuffer);
-    RawDllNameString.Buffer = NameBuffer;
 
     /* Check for init flag and acquire lock */
     if (!InInit) RtlEnterCriticalSection(&LdrpLoaderLock);
@@ -1920,14 +2479,14 @@ StartLoop:
     /* Show debug message */
     if (ShowSnaps)
     {
-        DPRINT1("LDR: LdrLoadDll, loading %ws from %ws\n",
-                 RawDllName,
+        DPRINT1("LDR: LdrLoadDll, loading %wZ from %ws\n",
+                 &RawDllName,
                  DllPath ? DllPath : L"");
     }
 
     /* Check if the DLL is already loaded */
     if (!LdrpCheckForLoadedDll(DllPath,
-                               &RawDllNameString,
+                               &RawDllName,
                                FALSE,
                                Redirected,
                                &LdrEntry))
@@ -1942,15 +2501,17 @@ StartLoop:
                             &LdrEntry);
         if (!NT_SUCCESS(Status)) goto Quickie;
 
-               /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
-               if (DllCharacteristics &&
-                       (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
-               {
-                       LdrEntry->EntryPoint = NULL;
-                       LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
-               }
+        /* FIXME: Need to mark the DLL range for the stack DB */
+        //RtlpStkMarkDllRange(LdrEntry);
 
-        /* FIXME Mark the DLL Ranges for Stack Traces later */
+        /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
+        if ((DllCharacteristics) &&
+            (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
+        {
+            /* This is not a DLL, so remove such data */
+            LdrEntry->EntryPoint = NULL;
+            LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
+        }
 
         /* Make sure it's a DLL */
         if (LdrEntry->Flags & LDRP_IMAGE_DLL)
@@ -1974,8 +2535,17 @@ StartLoop:
                 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
                                &LdrEntry->InInitializationOrderModuleList);
 
-                /* Cancel the load and unload the DLL */
+                /* Cancel the load */
                 LdrpClearLoadInProgress();
+
+                /* Unload the DLL */
+                if (ShowSnaps)
+                {
+                    DbgPrint("LDR: Unloading %wZ due to error %x walking "
+                             "import descriptors",
+                             DllName,
+                             Status);
+                }
                 LdrUnloadDll(LdrEntry->DllBase);
 
                 /* Return the error */
@@ -1996,12 +2566,26 @@ StartLoop:
         if (CallInit && LdrpLdrDatabaseIsSetup)
         {
             /* FIXME: Notify Shim Engine */
+            if (g_ShimsEnabled)
+            {
+                /* Call it */
+                //ShimLoadCallback = RtlDecodeSystemPointer(g_pfnSE_DllLoaded);
+                //ShimLoadCallback(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);
             }
         }
@@ -2087,20 +2671,4 @@ LdrpClearLoadInProgress(VOID)
     return ModulesCount;
 }
 
-VOID
-NTAPI
-LdrpFreeUnicodeString(IN PUNICODE_STRING StringIn)
-{
-    ASSERT(StringIn != NULL);
-
-    /* If Buffer is not NULL - free it */
-    if (StringIn->Buffer)
-    {
-        RtlFreeHeap(RtlGetProcessHeap(), 0, StringIn->Buffer);
-    }
-
-    /* Zero it out */
-    RtlInitEmptyUnicodeString(StringIn, NULL, 0);
-}
-
 /* EOF */