- Revert r52573
authorCameron Gutman <aicommander@gmail.com>
Thu, 4 Aug 2011 17:16:20 +0000 (17:16 +0000)
committerCameron Gutman <aicommander@gmail.com>
Thu, 4 Aug 2011 17:16:20 +0000 (17:16 +0000)
- Branch repair (part 1 of x)

svn path=/branches/GSoC_2011/TcpIpDriver/; revision=53062

dll/ntdll/include/ntdllp.h
dll/ntdll/ldr/ldrapi.c
dll/ntdll/ldr/ldrinit.c
dll/ntdll/ldr/ldrpe.c
dll/ntdll/ldr/ldrutils.c
dll/ntdll/ldr/startup.c
dll/ntdll/ldr/utils.c
dll/win32/kernel32/misc/ldr.c
lib/rtl/actctx.c

index a01a960..dc4bf75 100644 (file)
 
 #define LDR_HASH_TABLE_ENTRIES 32
 
+/* LdrpUpdateLoadCount2 flags */
+#define LDRP_UPDATE_REFCOUNT   0x01
+#define LDRP_UPDATE_DEREFCOUNT 0x02
+#define LDRP_UPDATE_PIN        0x03
+
 typedef struct _LDRP_TLS_DATA
 {
     LIST_ENTRY TlsLinks;
@@ -27,10 +32,21 @@ extern BOOLEAN LdrpInLdrInit;
 extern LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
 extern BOOLEAN ShowSnaps;
 extern UNICODE_STRING LdrpDefaultPath;
+extern HANDLE LdrpKnownDllObjectDirectory;
+extern ULONG LdrpNumberOfProcessors;
+extern ULONG LdrpFatalHardErrorCount;
+extern PUNICODE_STRING LdrpTopLevelDllBeingLoaded;
+extern PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer;
+extern UNICODE_STRING LdrApiDefaultExtension;
+extern BOOLEAN LdrpLdrDatabaseIsSetup;
+extern ULONG LdrpActiveUnloadCount;
+extern BOOLEAN LdrpShutdownInProgress;
+extern UNICODE_STRING LdrpKnownDllPath;
+extern PLDR_DATA_TABLE_ENTRY LdrpGetModuleHandleCache;
 
 /* ldrinit.c */
 NTSTATUS NTAPI LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL);
-NTSTATUS NTAPI LdrpInitializeThread(IN PCONTEXT Context);
+VOID NTAPI LdrpInitializeThread(IN PCONTEXT Context);
 NTSTATUS NTAPI LdrpInitializeTls(VOID);
 NTSTATUS NTAPI LdrpAllocateTls(VOID);
 VOID NTAPI LdrpFreeTls(VOID);
@@ -38,7 +54,7 @@ VOID NTAPI LdrpTlsCallback(PVOID BaseAddress, ULONG Reason);
 BOOLEAN NTAPI LdrpCallDllEntry(PDLLMAIN_FUNC EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context);
 NTSTATUS NTAPI LdrpInitializeProcess(PCONTEXT Context, PVOID SystemArgument1);
 VOID NTAPI LdrpInitFailure(NTSTATUS Status);
-
+VOID NTAPI LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry);
 
 /* ldrpe.c */
 NTSTATUS
@@ -79,6 +95,10 @@ LdrpLoadDll(IN BOOLEAN Redirected,
             OUT PVOID *BaseAddress,
             IN BOOLEAN CallInit);
 
+VOID NTAPI
+LdrpUpdateLoadCount2(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+                     IN ULONG Flags);
+
 ULONG NTAPI
 LdrpClearLoadInProgress();
 
@@ -101,6 +121,9 @@ LdrpMapDll(IN PWSTR SearchPath OPTIONAL,
 PVOID NTAPI
 LdrpFetchAddressOfEntryPoint(PVOID ImageBase);
 
+BOOLEAN NTAPI
+LdrpFreeUnicodeString(PUNICODE_STRING String);
+
 
 /* FIXME: Cleanup this mess */
 typedef NTSTATUS (NTAPI *PEPFUNC)(PPEB);
@@ -110,13 +133,8 @@ NTSTATUS LdrMapSections(HANDLE ProcessHandle,
                        PIMAGE_NT_HEADERS NTHeaders);
 NTSTATUS LdrMapNTDllForProcess(HANDLE ProcessHandle,
                               PHANDLE NTDllSectionHandle);
-BOOLEAN LdrMappedAsDataFile(PVOID *BaseAddress);
 ULONG
 LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders);
-PEPFUNC LdrPEStartup (PVOID  ImageBase,
-                     HANDLE SectionHandle,
-                     PLDR_DATA_TABLE_ENTRY* Module,
-                     PWSTR FullDosName);
 
 extern HANDLE WindowsApiPort;
 
index e08f4ca..7ba8792 100644 (file)
@@ -16,6 +16,8 @@
 /* GLOBALS *******************************************************************/
 
 LONG LdrpLoaderLockAcquisitonCount;
+BOOLEAN LdrpShowRecursiveLoads;
+UNICODE_STRING LdrApiDefaultExtension = RTL_CONSTANT_STRING(L".DLL");
 
 /* FUNCTIONS *****************************************************************/
 
@@ -242,6 +244,480 @@ Quickie:
     return Status;
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+LdrLoadDll(IN PWSTR SearchPath OPTIONAL,
+           IN PULONG DllCharacteristics OPTIONAL,
+           IN PUNICODE_STRING DllName,
+           OUT PVOID *BaseAddress)
+{
+    WCHAR StringBuffer[MAX_PATH];
+    UNICODE_STRING DllString1, DllString2;
+    BOOLEAN RedirectedDll = FALSE;
+    NTSTATUS Status;
+    ULONG Cookie;
+    PUNICODE_STRING OldTldDll;
+    PTEB Teb = NtCurrentTeb();
+
+    /* Initialize the strings */
+    RtlInitUnicodeString(&DllString2, NULL);
+    DllString1.Buffer = StringBuffer;
+    DllString1.Length = 0;
+    DllString1.MaximumLength = sizeof(StringBuffer);
+
+    /* Check if the SxS Assemblies specify another file */
+    Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
+                                                      DllName,
+                                                      &LdrApiDefaultExtension,
+                                                      &DllString1,
+                                                      &DllString2,
+                                                      &DllName,
+                                                      NULL,
+                                                      NULL,
+                                                      NULL);
+
+    /* Check success */
+    if (NT_SUCCESS(Status))
+    {
+        /* Let Ldrp know */
+        RedirectedDll = TRUE;
+    }
+    else if (Status != STATUS_SXS_KEY_NOT_FOUND)
+    {
+        /* Unrecoverable SxS failure; did we get a string? */
+        if (DllString2.Buffer)
+        {
+            /* Free the string */
+            RtlFreeUnicodeString(&DllString2);
+        }
+        return Status;
+    }
+
+    /* Lock the loader lock */
+    LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &Cookie);
+
+    /* Check if there's a TLD DLL being loaded */
+    if ((OldTldDll = LdrpTopLevelDllBeingLoaded))
+    {
+        /* This is a recursive load, do something about it? */
+        if (ShowSnaps || LdrpShowRecursiveLoads)
+        {
+            /* Print out debug messages */
+            DPRINT1("[%lx, %lx] LDR: Recursive DLL Load\n",
+                    Teb->RealClientId.UniqueProcess,
+                    Teb->RealClientId.UniqueThread);
+            DPRINT1("[%lx, %lx]      Previous DLL being loaded \"%wZ\"\n",
+                    Teb->RealClientId.UniqueProcess,
+                    Teb->RealClientId.UniqueThread,
+                    OldTldDll);
+            DPRINT1("[%lx, %lx]      DLL being requested \"%wZ\"\n",
+                    Teb->RealClientId.UniqueProcess,
+                    Teb->RealClientId.UniqueThread,
+                    DllName);
+
+            /* Was it initializing too? */
+            if (!LdrpCurrentDllInitializer)
+            {
+                DPRINT1("[%lx, %lx] LDR: No DLL Initializer was running\n",
+                        Teb->RealClientId.UniqueProcess,
+                        Teb->RealClientId.UniqueThread);
+            }
+            else
+            {
+                DPRINT1("[%lx, %lx]      DLL whose initializer was currently running \"%wZ\"\n",
+                        Teb->ClientId.UniqueProcess,
+                        Teb->ClientId.UniqueThread,
+                        &LdrpCurrentDllInitializer->BaseDllName);
+            }
+        }
+    }
+
+    /* Set this one as the TLD DLL being loaded*/
+    LdrpTopLevelDllBeingLoaded = DllName;
+
+    /* Load the DLL */
+    Status = LdrpLoadDll(RedirectedDll,
+                         SearchPath,
+                         DllCharacteristics,
+                         DllName,
+                         BaseAddress,
+                         TRUE);
+
+    /* Restore the old TLD DLL */
+    LdrpTopLevelDllBeingLoaded = OldTldDll;
+
+    /* Release the lock */
+    LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
+
+    /* Do we have a redirect string? */
+    if (DllString2.Buffer) RtlFreeUnicodeString(&DllString2);
+
+    /* Return */
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+LdrFindEntryForAddress(PVOID Address,
+                       PLDR_DATA_TABLE_ENTRY *Module)
+{
+    PLIST_ENTRY ListHead, NextEntry;
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    PIMAGE_NT_HEADERS NtHeader;
+    PPEB_LDR_DATA Ldr = NtCurrentPeb()->Ldr;
+    ULONG_PTR DllBase, DllEnd;
+
+    DPRINT("LdrFindEntryForAddress(Address %p)\n", Address);
+
+    /* Nothing to do */
+    if (!Ldr) return STATUS_NO_MORE_ENTRIES;
+
+    /* Loop the module list */
+    ListHead = &Ldr->InMemoryOrderModuleList;
+    NextEntry = ListHead->Flink;
+    while (NextEntry != ListHead)
+    {
+        /* Get the entry and NT Headers */
+        LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList);
+        if ((NtHeader = RtlImageNtHeader(LdrEntry->DllBase)))
+        {
+            /* Get the Image Base */
+            DllBase = (ULONG_PTR)LdrEntry->DllBase;
+            DllEnd = DllBase + NtHeader->OptionalHeader.SizeOfImage;
+
+            /* Check if they match */
+            if (((ULONG_PTR)Address >= DllBase) &&
+                ((ULONG_PTR)Address < DllEnd))
+            {
+                /* Return it */
+                *Module = LdrEntry;
+                return STATUS_SUCCESS;
+            }
+
+            /* Next Entry */
+            NextEntry = NextEntry->Flink;
+        }
+    }
+
+    /* Nothing found */
+    return STATUS_NO_MORE_ENTRIES;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+LdrGetDllHandleEx(IN ULONG Flags,
+                  IN PWSTR DllPath OPTIONAL,
+                  IN PULONG DllCharacteristics OPTIONAL,
+                  IN PUNICODE_STRING DllName,
+                  OUT PVOID *DllHandle OPTIONAL)
+{
+    NTSTATUS Status = STATUS_DLL_NOT_FOUND;
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    UNICODE_STRING RedirectName, DllString1;
+    UNICODE_STRING RawDllName;
+    PUNICODE_STRING pRedirectName = &RedirectName;
+    PUNICODE_STRING CompareName;
+    PWCHAR p1, p2, p3;
+    BOOLEAN Locked = FALSE;
+    BOOLEAN RedirectedDll = FALSE;
+    ULONG Cookie;
+    ULONG LoadFlag;
+
+    /* Initialize the strings */
+    RtlInitUnicodeString(&DllString1, NULL);
+    RtlInitUnicodeString(&RawDllName, NULL);
+    RedirectName = *DllName;
+
+    /* Clear the handle */
+    if (DllHandle) *DllHandle = NULL;
+
+    /* Check for a valid flag */
+    if ((Flags & ~3) || (!DllHandle && !(Flags & 2)))
+    {
+        DPRINT1("Flags are invalid or no DllHandle given\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* If not initializing */
+    if (!LdrpInLdrInit)
+    {
+        /* Acquire the lock */
+        Status = LdrLockLoaderLock(0, NULL, &Cookie);
+        Locked = TRUE;
+    }
+
+    /* Check if the SxS Assemblies specify another file */
+    Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
+                                                      pRedirectName,
+                                                      &LdrApiDefaultExtension,
+                                                      NULL,
+                                                      &DllString1,
+                                                      &pRedirectName,
+                                                      NULL,
+                                                      NULL,
+                                                      NULL);
+
+    /* Check success */
+    if (NT_SUCCESS(Status))
+    {
+        /* Let Ldrp know */
+        RedirectedDll = TRUE;
+    }
+    else if (Status != STATUS_SXS_KEY_NOT_FOUND)
+    {
+        /* Unrecoverable SxS failure; */
+        goto Quickie;
+    }
+
+    /* Use the cache if we can */
+    if (LdrpGetModuleHandleCache)
+    {
+        /* Check if we were redirected */
+        if (RedirectedDll)
+        {
+            /* Check the flag */
+            if (LdrpGetModuleHandleCache->Flags & LDRP_REDIRECTED)
+            {
+                /* Use the right name */
+                CompareName = &LdrpGetModuleHandleCache->FullDllName;
+            }
+            else
+            {
+                goto DontCompare;
+            }
+        }
+        else
+        {
+            /* Check the flag */
+            if (!(LdrpGetModuleHandleCache->Flags & LDRP_REDIRECTED))
+            {
+                /* Use the right name */
+                CompareName = &LdrpGetModuleHandleCache->BaseDllName;
+            }
+            else
+            {
+                goto DontCompare;
+            }
+        }
+
+        /* Check if the name matches */
+        if (RtlEqualUnicodeString(pRedirectName,
+                                  CompareName,
+                                  TRUE))
+        {
+            /* Skip the rest */
+            LdrEntry = LdrpGetModuleHandleCache;
+
+            /* Return success */
+            Status = STATUS_SUCCESS;
+
+            goto FoundEntry;
+        }
+    }
+
+DontCompare:
+    /* Find the name without the extension */
+    p1 = pRedirectName->Buffer;
+    p3 = &p1[pRedirectName->Length / sizeof(WCHAR)];
+StartLoop:
+    p2 = NULL;
+    while (p1 != p3)
+    {
+        if (*p1++ == L'.')
+        {
+            p2 = p1;
+        }
+        else if (*p1 == L'\\')
+        {
+            goto StartLoop;
+        }
+    }
+
+    /* Check if no extension was found or if we got a slash */
+    if (!p2 || *p2 == L'\\' || *p2 == L'/')
+    {
+        /* Check that we have space to add one */
+        if (pRedirectName->Length + LdrApiDefaultExtension.Length >= MAXLONG)
+        {
+            /* No space to add the extension */
+            return STATUS_NAME_TOO_LONG;
+        }
+
+        /* Setup the string */
+        RawDllName.MaximumLength = pRedirectName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL);
+        RawDllName.Length = RawDllName.MaximumLength - sizeof(UNICODE_NULL);
+        RawDllName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+                                            0,
+                                            RawDllName.MaximumLength);
+
+        /* Copy the buffer */
+        RtlMoveMemory(RawDllName.Buffer,
+                      pRedirectName->Buffer,
+                      pRedirectName->Length);
+
+        /* Add extension */
+        RtlMoveMemory((PVOID)((ULONG_PTR)RawDllName.Buffer + pRedirectName->Length),
+                      LdrApiDefaultExtension.Buffer,
+                      LdrApiDefaultExtension.Length);
+
+        /* Null terminate */
+        RawDllName.Buffer[RawDllName.Length / sizeof(WCHAR)] = UNICODE_NULL;
+    }
+    else
+    {
+        /* Check if there's something in the name */
+        if (pRedirectName->Length)
+        {
+            /* Check and remove trailing period */
+            if (pRedirectName->Buffer[(pRedirectName->Length - 2) /
+                sizeof(WCHAR)] == '.')
+            {
+                /* Decrease the size */
+                pRedirectName->Length -= sizeof(WCHAR);
+            }
+        }
+
+        /* Setup the string */
+        RawDllName.MaximumLength = pRedirectName->Length + sizeof(WCHAR);
+        RawDllName.Length = pRedirectName->Length;
+        RawDllName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+                                            0,
+                                            RawDllName.MaximumLength);
+
+        /* Copy the buffer */
+        RtlMoveMemory(RawDllName.Buffer,
+                      pRedirectName->Buffer,
+                      pRedirectName->Length);
+
+        /* Null terminate */
+        RawDllName.Buffer[RawDllName.Length / sizeof(WCHAR)] = UNICODE_NULL;
+    }
+
+    /* Display debug string */
+    if (ShowSnaps)
+    {
+        DPRINT1("LDR: LdrGetDllHandle, searching for %wZ from %ws\n",
+                &RawDllName,
+                DllPath ? ((ULONG_PTR)DllPath == 1 ? L"" : DllPath) : L"");
+    }
+
+    /* Do the lookup */
+    if (LdrpCheckForLoadedDll(DllPath,
+                              &RawDllName,
+                              ((ULONG_PTR)DllPath == 1) ? TRUE : FALSE,
+                              RedirectedDll,
+                              &LdrEntry))
+    {
+        /* Update cached entry */
+        LdrpGetModuleHandleCache = LdrEntry;
+
+        /* Return success */
+        Status = STATUS_SUCCESS;
+    }
+    else
+    {
+        /* Make sure to NULL this */
+        LdrEntry = NULL;
+    }
+FoundEntry:
+    DPRINT("Got LdrEntry->BaseDllName %wZ\n", LdrEntry ? &LdrEntry->BaseDllName : NULL);
+
+    /* Check if we got an entry */
+    if (LdrEntry)
+    {
+        /* Check for success */
+        if (NT_SUCCESS(Status))
+        {
+            /* Check if the DLL is locked */
+            if (LdrEntry->LoadCount != -1)
+            {
+                /* Check what flag we got */
+                if (!(Flags & 1))
+                {
+                    /* Check what to do with the load count */
+                    if (Flags & 2)
+                    {
+                        /* Pin it */
+                        LdrEntry->LoadCount = -1;
+                        LoadFlag = LDRP_UPDATE_PIN;
+                    }
+                    else
+                    {
+                        /* Increase the load count */
+                        LdrEntry->LoadCount++;
+                        LoadFlag = LDRP_UPDATE_REFCOUNT;
+                    }
+
+                    /* Update the load count now */
+                    LdrpUpdateLoadCount2(LdrEntry, LoadFlag);
+                    LdrpClearLoadInProgress();
+                }
+            }
+
+            /* Check if the caller is requesting the handle */
+            if (DllHandle) *DllHandle = LdrEntry->DllBase;
+        }
+    }
+Quickie:
+    /* Free string if needed */
+    if (DllString1.Buffer) RtlFreeUnicodeString(&DllString1);
+
+    /* Free the raw DLL Name if needed */
+    if (RawDllName.Buffer)
+    {
+        /* Free the heap-allocated buffer */
+        RtlFreeHeap(RtlGetProcessHeap(), 0, RawDllName.Buffer);
+        RawDllName.Buffer = NULL;
+    }
+
+    /* Release lock */
+    if (Locked) LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
+
+    /* Return */
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+LdrGetDllHandle(IN PWSTR DllPath OPTIONAL,
+                IN PULONG DllCharacteristics OPTIONAL,
+                IN PUNICODE_STRING DllName,
+                OUT PVOID *DllHandle)
+{
+    /* Call the newer API */
+    return LdrGetDllHandleEx(TRUE,
+                             DllPath,
+                             DllCharacteristics,
+                             DllName,
+                             DllHandle);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+LdrGetProcedureAddress(IN PVOID BaseAddress,
+                       IN PANSI_STRING Name,
+                       IN ULONG Ordinal,
+                       OUT PVOID *ProcedureAddress)
+{
+    /* Call the internal routine and tell it to execute DllInit */
+    return LdrpGetProcedureAddress(BaseAddress, Name, Ordinal, ProcedureAddress, TRUE);
+}
+
 /*
  * @implemented
  */
@@ -374,21 +850,6 @@ LdrVerifyImageMatchesChecksum(IN HANDLE FileHandle,
     return !Result ? STATUS_IMAGE_CHECKSUM_MISMATCH : Status;
 }
 
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-LdrGetProcedureAddress_(IN PVOID BaseAddress,
-                       IN PANSI_STRING Name,
-                       IN ULONG Ordinal,
-                       OUT PVOID *ProcedureAddress)
-{
-    /* Call the internal routine and tell it to execute DllInit */
-    return LdrpGetProcedureAddress(BaseAddress, Name, Ordinal, ProcedureAddress, TRUE);
-}
-
-
 NTSTATUS
 NTAPI
 LdrQueryProcessModuleInformationEx(IN ULONG ProcessId,
index 6b08bed..fd0aa39 100644 (file)
 /* INCLUDES *****************************************************************/
 
 #include <ntdll.h>
+#include <win32k/callback.h>
+
 #define NDEBUG
 #include <debug.h>
 
+
 /* GLOBALS *******************************************************************/
 
 HKEY ImageExecOptionsKey;
@@ -25,11 +28,14 @@ BOOLEAN LdrpInLdrInit;
 LONG LdrpProcessInitialized;
 BOOLEAN LdrpLoaderLockInit;
 BOOLEAN LdrpLdrDatabaseIsSetup;
+BOOLEAN LdrpShutdownInProgress;
+HANDLE LdrpShutdownThreadId;
 
 BOOLEAN LdrpDllValidation;
 
 PLDR_DATA_TABLE_ENTRY LdrpImageEntry;
 PUNICODE_STRING LdrpTopLevelDllBeingLoaded;
+WCHAR StringBuffer[156];
 extern PTEB LdrpTopLevelDllBeingLoadedTeb; // defined in rtlsupp.c!
 PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer;
 PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry;
@@ -68,6 +74,7 @@ RTL_CRITICAL_SECTION FastPebLock;
 BOOLEAN ShowSnaps;
 
 ULONG LdrpFatalHardErrorCount;
+ULONG LdrpActiveUnloadCount;
 
 //extern LIST_ENTRY RtlCriticalSectionList;
 
@@ -78,10 +85,12 @@ extern BOOLEAN RtlpPageHeapEnabled;
 extern ULONG RtlpDphGlobalFlags;
 
 NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase);
-NTSTATUS NTAPI
-LdrpInitializeProcess_(PCONTEXT Context,
-                      PVOID SystemArgument1);
 
+#ifdef _WIN64
+#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
+#else
+#define DEFAULT_SECURITY_COOKIE 0xBB40E64E
+#endif
 
 /* FUNCTIONS *****************************************************************/
 
@@ -414,8 +423,7 @@ LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress, ULONG SizeOfImage)
     Cookie = (PVOID)ConfigDir->SecurityCookie;
 
     /* Check this cookie */
-    if (Cookie == NULL ||
-        (PCHAR)Cookie <= (PCHAR)BaseAddress ||
+    if ((PCHAR)Cookie <= (PCHAR)BaseAddress ||
         (PCHAR)Cookie >= (PCHAR)BaseAddress + SizeOfImage)
     {
         Cookie = NULL;
@@ -429,20 +437,178 @@ PVOID
 NTAPI
 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry)
 {
-    PVOID Cookie;
+    PULONG_PTR Cookie;
+    LARGE_INTEGER Counter;
+    //ULONG NewCookie;
 
     /* Fetch address of the cookie */
     Cookie = LdrpFetchAddressOfSecurityCookie(LdrEntry->DllBase, LdrEntry->SizeOfImage);
 
     if (Cookie)
     {
-        UNIMPLEMENTED;
-        Cookie = NULL;
+        /* Check if it's a default one */
+        if (*Cookie == DEFAULT_SECURITY_COOKIE ||
+            *Cookie == 0xBB40)
+        {
+            /* We need to initialize it */
+
+            NtQueryPerformanceCounter(&Counter, NULL);
+#if 0
+            GetSystemTimeAsFileTime (&systime.ft_struct);
+#ifdef _WIN64
+            cookie = systime.ft_scalar;
+#else
+            cookie = systime.ft_struct.dwLowDateTime;
+            cookie ^= systime.ft_struct.dwHighDateTime;
+#endif
+
+            cookie ^= GetCurrentProcessId ();
+            cookie ^= GetCurrentThreadId ();
+            cookie ^= GetTickCount ();
+
+            QueryPerformanceCounter (&perfctr);
+#ifdef _WIN64
+            cookie ^= perfctr.QuadPart;
+#else
+            cookie ^= perfctr.LowPart;
+            cookie ^= perfctr.HighPart;
+#endif
+
+#ifdef _WIN64
+            cookie &= 0x0000ffffffffffffll;
+#endif
+#endif
+            *Cookie = Counter.LowPart;
+
+            //Cookie = NULL;
+        }
     }
 
     return Cookie;
 }
 
+VOID
+NTAPI
+LdrpInitializeThread(IN PCONTEXT Context)
+{
+    PPEB Peb = NtCurrentPeb();
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    PLIST_ENTRY NextEntry, ListHead;
+    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
+    NTSTATUS Status;
+    PVOID EntryPoint;
+
+    DPRINT("LdrpInitializeThread() called for %wZ\n",
+            &LdrpImageEntry->BaseDllName);
+
+    /* Allocate an Activation Context Stack */
+    /* FIXME: This is a hack for Wine's actctx stuff */
+    DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer);
+    if (!(NtCurrentTeb()->ActivationContextStackPointer))
+    {
+        Status = RtlAllocateActivationContextStack((PVOID*)&NtCurrentTeb()->ActivationContextStackPointer);
+        if (NT_SUCCESS(Status))
+        {
+            DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer);
+            DPRINT("ActiveFrame %p\n", ((PACTIVATION_CONTEXT_STACK)NtCurrentTeb()->ActivationContextStackPointer)->ActiveFrame);
+            NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL;
+        }
+        else
+            DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
+    }
+
+    /* Make sure we are not shutting down */
+    if (LdrpShutdownInProgress) return;
+
+    /* Allocate TLS */
+    LdrpAllocateTls();
+
+    /* Start at the beginning */
+    ListHead = &Peb->Ldr->InMemoryOrderModuleList;
+    NextEntry = ListHead->Flink;
+    while (NextEntry != ListHead)
+    {
+        /* Get the current entry */
+        LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList);
+
+        /* Make sure it's not ourselves */
+        if (Peb->ImageBaseAddress != LdrEntry->DllBase)
+        {
+            /* Check if we should call */
+            if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS))
+            {
+                /* Get the entrypoint */
+                EntryPoint = LdrEntry->EntryPoint;
+
+                /* Check if we are ready to call it */
+                if ((EntryPoint) && 
+                    (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) &&
+                    (LdrEntry->Flags & LDRP_IMAGE_DLL))
+                {
+                    /* Set up the Act Ctx */
+                    ActCtx.Size = sizeof(ActCtx);
+                    ActCtx.Format = 1;
+                    RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
+
+                    /* Activate the ActCtx */
+                    RtlActivateActivationContextUnsafeFast(&ActCtx,
+                                                           LdrEntry->EntryPointActivationContext);
+
+                    /* Check if it has TLS */
+                    if (LdrEntry->TlsIndex)
+                    {
+                        /* Make sure we're not shutting down */
+                        if (!LdrpShutdownInProgress)
+                        {
+                            /* Call TLS */
+                            LdrpTlsCallback(LdrEntry->DllBase, DLL_THREAD_ATTACH);
+                        }
+                    }
+
+                    /* Make sure we're not shutting down */
+                    if (!LdrpShutdownInProgress)
+                    {
+                        /* Call the Entrypoint */
+                        DPRINT("%wZ - Calling entry point at %x for thread attaching\n",
+                                &LdrEntry->BaseDllName, LdrEntry->EntryPoint);
+                        LdrpCallDllEntry(LdrEntry->EntryPoint,
+                                         LdrEntry->DllBase,
+                                         DLL_THREAD_ATTACH,
+                                         NULL);
+                    }
+
+                    /* Deactivate the ActCtx */
+                    RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+                }
+            }
+        }
+
+        /* Next entry */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Check for TLS */
+    if (LdrpImageHasTls && !LdrpShutdownInProgress)
+    {
+        /* Set up the Act Ctx */
+        ActCtx.Size = sizeof(ActCtx);
+        ActCtx.Format = 1;
+        RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
+
+        /* Activate the ActCtx */
+        RtlActivateActivationContextUnsafeFast(&ActCtx,
+                                               LdrpImageEntry->EntryPointActivationContext);
+
+        /* Do TLS callbacks */
+        LdrpTlsCallback(Peb->ImageBaseAddress, DLL_THREAD_ATTACH);
+
+        /* Deactivate the ActCtx */
+        RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+    }
+
+    DPRINT("LdrpInitializeThread() done\n");
+}
+
 NTSTATUS
 NTAPI
 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
@@ -715,6 +881,267 @@ Quickie:
     return Status;
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+LdrShutdownProcess(VOID)
+{
+    PPEB Peb = NtCurrentPeb();
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    PLIST_ENTRY NextEntry, ListHead;
+    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
+    PVOID EntryPoint;
+
+    DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry->BaseDllName);
+    if (LdrpShutdownInProgress) return STATUS_SUCCESS;
+
+    /* Tell the Shim Engine */
+    //if (ShimsEnabled)
+    //{
+        /* FIXME */
+    //}
+
+    /* Tell the world */
+    if (ShowSnaps)
+    {
+        DPRINT1("\n");
+    }
+
+    /* Set the shutdown variables */
+    LdrpShutdownThreadId = NtCurrentTeb()->RealClientId.UniqueThread;
+    LdrpShutdownInProgress = TRUE;
+
+    /* Enter the Loader Lock */
+    RtlEnterCriticalSection(&LdrpLoaderLock);
+
+    /* Cleanup trace logging data (Etw) */
+    if (SharedUserData->TraceLogging)
+    {
+        /* FIXME */
+        DPRINT1("We don't support Etw yet.\n");
+    }
+
+    /* Start at the end */
+    ListHead = &Peb->Ldr->InInitializationOrderModuleList;
+    NextEntry = ListHead->Blink;
+    while (NextEntry != ListHead)
+    {
+        /* Get the current entry */
+        LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
+        NextEntry = NextEntry->Blink;
+
+        /* Make sure it's not ourselves */
+        if (Peb->ImageBaseAddress != LdrEntry->DllBase)
+        {
+            /* Get the entrypoint */
+            EntryPoint = LdrEntry->EntryPoint;
+
+            /* Check if we are ready to call it */
+            if (EntryPoint && 
+                (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) &&
+                LdrEntry->Flags)
+            {
+                /* Set up the Act Ctx */
+                ActCtx.Size = sizeof(ActCtx);
+                ActCtx.Format = 1;
+                RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
+
+                /* Activate the ActCtx */
+                RtlActivateActivationContextUnsafeFast(&ActCtx,
+                                                       LdrEntry->EntryPointActivationContext);
+
+                /* Check if it has TLS */
+                if (LdrEntry->TlsIndex)
+                {
+                    /* Call TLS */
+                    LdrpTlsCallback(LdrEntry->DllBase, DLL_PROCESS_DETACH);
+                }
+
+                /* Call the Entrypoint */
+                DPRINT("%wZ - Calling entry point at %x for thread detaching\n",
+                        &LdrEntry->BaseDllName, LdrEntry->EntryPoint);
+                LdrpCallDllEntry(EntryPoint,
+                                 LdrEntry->DllBase,
+                                 DLL_PROCESS_DETACH,
+                                 (PVOID)1);
+
+                /* Deactivate the ActCtx */
+                RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+            }
+        }
+    }
+
+    /* Check for TLS */
+    if (LdrpImageHasTls)
+    {
+        /* Set up the Act Ctx */
+        ActCtx.Size = sizeof(ActCtx);
+        ActCtx.Format = 1;
+        RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
+
+        /* Activate the ActCtx */
+        RtlActivateActivationContextUnsafeFast(&ActCtx,
+                                               LdrpImageEntry->EntryPointActivationContext);
+
+        /* Do TLS callbacks */
+        LdrpTlsCallback(Peb->ImageBaseAddress, DLL_PROCESS_DETACH);
+
+        /* Deactivate the ActCtx */
+        RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+    }
+
+    /* FIXME: Do Heap detection and Etw final shutdown */
+
+    /* Release the lock */
+    RtlLeaveCriticalSection(&LdrpLoaderLock);
+    DPRINT("LdrpShutdownProcess() done\n");
+
+    return STATUS_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+LdrShutdownThread(VOID)
+{
+    PPEB Peb = NtCurrentPeb();
+    PTEB Teb = NtCurrentTeb();
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    PLIST_ENTRY NextEntry, ListHead;
+    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
+    PVOID EntryPoint;
+
+    DPRINT("LdrShutdownThread() called for %wZ\n",
+            &LdrpImageEntry->BaseDllName);
+
+    /* Cleanup trace logging data (Etw) */
+    if (SharedUserData->TraceLogging)
+    {
+        /* FIXME */
+        DPRINT1("We don't support Etw yet.\n");
+    }
+
+    /* Get the Ldr Lock */
+    RtlEnterCriticalSection(&LdrpLoaderLock);
+
+    /* Start at the end */
+    ListHead = &Peb->Ldr->InInitializationOrderModuleList;
+    NextEntry = ListHead->Blink;
+    while (NextEntry != ListHead)
+    {
+        /* Get the current entry */
+        LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
+        NextEntry = NextEntry->Blink;
+
+        /* Make sure it's not ourselves */
+        if (Peb->ImageBaseAddress != LdrEntry->DllBase)
+        {
+            /* Check if we should call */
+            if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
+                (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) &&
+                (LdrEntry->Flags & LDRP_IMAGE_DLL))
+            {
+                /* Get the entrypoint */
+                EntryPoint = LdrEntry->EntryPoint;
+
+                /* Check if we are ready to call it */
+                if (EntryPoint)
+                {
+                    /* Set up the Act Ctx */
+                    ActCtx.Size = sizeof(ActCtx);
+                    ActCtx.Format = 1;
+                    RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
+
+                    /* Activate the ActCtx */
+                    RtlActivateActivationContextUnsafeFast(&ActCtx,
+                                                           LdrEntry->EntryPointActivationContext);
+
+                    /* Check if it has TLS */
+                    if (LdrEntry->TlsIndex)
+                    {
+                        /* Make sure we're not shutting down */
+                        if (!LdrpShutdownInProgress)
+                        {
+                            /* Call TLS */
+                            LdrpTlsCallback(LdrEntry->DllBase, DLL_THREAD_DETACH);
+                        }
+                    }
+
+                    /* Make sure we're not shutting down */
+                    if (!LdrpShutdownInProgress)
+                    {
+                        /* Call the Entrypoint */
+                        DPRINT("%wZ - Calling entry point at %x for thread detaching\n",
+                                &LdrEntry->BaseDllName, LdrEntry->EntryPoint);
+                        LdrpCallDllEntry(EntryPoint,
+                                         LdrEntry->DllBase,
+                                         DLL_THREAD_DETACH,
+                                         NULL);
+                    }
+
+                    /* Deactivate the ActCtx */
+                    RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+                }
+            }
+        }
+    }
+
+    /* Check for TLS */
+    if (LdrpImageHasTls)
+    {
+        /* Set up the Act Ctx */
+        ActCtx.Size = sizeof(ActCtx);
+        ActCtx.Format = 1;
+        RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
+
+        /* Activate the ActCtx */
+        RtlActivateActivationContextUnsafeFast(&ActCtx,
+                                               LdrpImageEntry->EntryPointActivationContext);
+
+        /* Do TLS callbacks */
+        LdrpTlsCallback(Peb->ImageBaseAddress, DLL_THREAD_DETACH);
+
+        /* Deactivate the ActCtx */
+        RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+    }
+
+    /* Free TLS */
+    LdrpFreeTls();
+    RtlLeaveCriticalSection(&LdrpLoaderLock);
+
+    /* Check for expansion slots */
+    if (Teb->TlsExpansionSlots)
+    {
+        /* Free expansion slots */
+        RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->TlsExpansionSlots);
+    }
+
+    /* Check for FLS Data */
+    if (Teb->FlsData)
+    {
+        /* FIXME */
+        DPRINT1("We don't support FLS Data yet\n");
+    }
+
+    /* Check for Fiber data */
+    if (Teb->HasFiberData)
+    {
+        /* Free Fiber data*/
+        RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->NtTib.FiberData);
+        Teb->NtTib.FiberData = NULL;
+    }
+
+    /* Free the activation context stack */
+    RtlFreeThreadActivationContextStack();
+    DPRINT("LdrShutdownThread() done\n");
+
+    return STATUS_SUCCESS;
+}
+
 NTSTATUS
 NTAPI
 LdrpInitializeTls(VOID)
@@ -879,10 +1306,10 @@ LdrpFreeTls(VOID)
 
 NTSTATUS
 NTAPI
-LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PULONG Options)
+LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHKEY OptionsKey)
 {
     UNIMPLEMENTED;
-    *Options = 0;
+    *OptionsKey = NULL;
     return STATUS_SUCCESS;
 }
 
@@ -915,7 +1342,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     //LPWSTR ImagePathBuffer;
     ULONG ConfigSize;
     UNICODE_STRING CurrentDirectory;
-    ULONG ExecuteOptions;
+    HKEY OptionsKey;
     ULONG HeapFlags;
     PIMAGE_NT_HEADERS NtHeader;
     LPWSTR NtDllName = NULL;
@@ -928,9 +1355,9 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     ULONG i;
     PWSTR ImagePath;
     ULONG DebugProcessHeapOnly = 0;
-    WCHAR FullNtDllPath[MAX_PATH];
     PLDR_DATA_TABLE_ENTRY NtLdrEntry;
     PWCHAR Current;
+    ULONG ExecuteOptions = 0;
 
     /* Set a NULL SEH Filter */
     RtlSetUnhandledExceptionFilter(NULL);
@@ -954,7 +1381,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     NtHeader = RtlImageNtHeader(Peb->ImageBaseAddress);
 
     /* Get the execution options */
-    Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &ExecuteOptions);
+    Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &OptionsKey);
 
     /* Check if this is a .NET executable */
     if (RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
@@ -1040,7 +1467,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     }
 
     /* Check if verbose debugging (ShowSnaps) was requested */
-    ShowSnaps = TRUE;//Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
+    ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
 
     /* Start verbose debugging messages right now if they were requested */
     if (ShowSnaps)
@@ -1091,9 +1518,11 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     }
 
     /* Initialize the Loader Lock */
+    // FIXME: What's the point of initing it manually, if two lines lower
+    //        a call to RtlInitializeCriticalSection() is being made anyway?
     //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
     //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
-    UNIMPLEMENTED;
+    RtlInitializeCriticalSection(&LdrpLoaderLock);
     LdrpLoaderLockInit = TRUE;
 
     /* Check if User Stack Trace Database support was requested */
@@ -1134,19 +1563,30 @@ LdrpInitializeProcess(IN PCONTEXT Context,
         return STATUS_NO_MEMORY;
     }
 
+    // FIXME: Is it located properly?
+    /* Initialize table of callbacks for the kernel. */
+    Peb->KernelCallbackTable = RtlAllocateHeap(RtlGetProcessHeap(),
+                                               0,
+                                               sizeof(PVOID) *
+                                                (USER32_CALLBACK_MAXIMUM + 1));
+    if (!Peb->KernelCallbackTable)
+    {
+        DPRINT1("Failed to create callback table\n");
+        ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
+    }
+
     /* Allocate an Activation Context Stack */
     Status = RtlAllocateActivationContextStack((PVOID *)&Teb->ActivationContextStackPointer);
     if (!NT_SUCCESS(Status)) return Status;
 
     // FIXME: Loader private heap is missing
-    DPRINT1("Loader private heap is missing\n");
+    //DPRINT1("Loader private heap is missing\n");
 
     /* Check for Debug Heap */
-    DPRINT1("Check for a debug heap is missing\n");
-    if (FALSE)
+    if (OptionsKey)
     {
         /* Query the setting */
-        Status = LdrQueryImageFileKeyOption(NULL,//hKey
+        Status = LdrQueryImageFileKeyOption(OptionsKey,
                                             L"DebugProcessHeapOnly",
                                             REG_DWORD,
                                             &DebugProcessHeapOnly,
@@ -1165,9 +1605,9 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     }
 
     /* Build the NTDLL Path */
-    FullPath.Buffer = FullNtDllPath;
+    FullPath.Buffer = StringBuffer;
     FullPath.Length = 0;
-    FullPath.MaximumLength = sizeof(FullNtDllPath);
+    FullPath.MaximumLength = sizeof(StringBuffer);
     RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot);
     RtlAppendUnicodeStringToString(&FullPath, &NtSystemRoot);
     RtlAppendUnicodeToString(&FullPath, L"\\System32\\");
@@ -1188,7 +1628,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     {
         /* It doesn't, so assume System32 */
         LdrpKnownDllObjectDirectory = NULL;
-        RtlInitUnicodeString(&LdrpKnownDllPath, FullPath.Buffer);
+        RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer);
         LdrpKnownDllPath.Length -= sizeof(WCHAR);
     }
     else
@@ -1230,6 +1670,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
         else
         {
             /* We need a valid path */
+            DPRINT1("No valid DllPath was given!\n");
             LdrpInitFailure(STATUS_INVALID_PARAMETER);
         }
 
@@ -1246,6 +1687,11 @@ LdrpInitializeProcess(IN PCONTEXT Context,
                                                       0,
                                                       3 * sizeof(WCHAR) +
                                                       sizeof(UNICODE_NULL));
+            if (!CurrentDirectory.Buffer)
+            {
+                DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
+                // FIXME: And what?
+            }
 
             /* Copy the drive of the system root */
             RtlMoveMemory(CurrentDirectory.Buffer,
@@ -1256,12 +1702,12 @@ LdrpInitializeProcess(IN PCONTEXT Context,
             CurrentDirectory.MaximumLength = CurrentDirectory.Length + sizeof(WCHAR);
 
             FreeCurDir = TRUE;
+            DPRINT("Using dynamically allocd curdir\n");
         }
         else
         {
             /* Use the local buffer */
-            CurrentDirectory.Length = NtSystemRoot.Length;
-            CurrentDirectory.Buffer = NtSystemRoot.Buffer;
+            DPRINT("Using local system root\n");
         }
     }
 
@@ -1280,8 +1726,8 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase);
     NtLdrEntry->LoadCount = -1;
     NtLdrEntry->EntryPointActivationContext = 0;
-    NtLdrEntry->FullDllName.Length = ImageFileName.Length;
-    NtLdrEntry->FullDllName.Buffer = ImageFileName.Buffer;
+    NtLdrEntry->FullDllName = ImageFileName;
+
     if (IsDotNetImage)
         NtLdrEntry->Flags = LDRP_COR_IMAGE;
     else
@@ -1291,7 +1737,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     if (!ImageFileName.Buffer[0])
     {
         /* Use the same Base name */
-        NtLdrEntry->BaseDllName = NtLdrEntry->BaseDllName;
+        NtLdrEntry->BaseDllName = NtLdrEntry->FullDllName;
     }
     else
     {
@@ -1332,14 +1778,16 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase);
     NtLdrEntry->LoadCount = -1;
     NtLdrEntry->EntryPointActivationContext = 0;
-    //NtLdrEntry->BaseDllName.Length = NtSystemRoot.Length;
-    //RtlAppendUnicodeStringToString(&NtSystemRoot, &NtDllString);
+
+    NtLdrEntry->FullDllName.Length = FullPath.Length;
+    NtLdrEntry->FullDllName.MaximumLength = FullPath.MaximumLength;
+    NtLdrEntry->FullDllName.Buffer = StringBuffer;
+    RtlAppendUnicodeStringToString(&NtLdrEntry->FullDllName, &NtDllString);
+
     NtLdrEntry->BaseDllName.Length = NtDllString.Length;
     NtLdrEntry->BaseDllName.MaximumLength = NtDllString.MaximumLength;
     NtLdrEntry->BaseDllName.Buffer = NtDllString.Buffer;
 
-    // FIXME: Full DLL name?!
-
     /* Processing done, insert it */
     LdrpNtDllDataTableEntry = NtLdrEntry;
     LdrpInsertMemoryTableEntry(NtLdrEntry);
@@ -1510,7 +1958,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
 
     ///* Close the key if we have one opened */
     //if (hKey) NtClose(hKey);
-DbgBreakPoint();
+
     /* Return status */
     return Status;
 }
@@ -1596,7 +2044,7 @@ LdrpInit(PCONTEXT Context,
         _SEH2_TRY
         {
             /* Initialize the Process */
-            LoaderStatus = LdrpInitializeProcess_(Context,
+            LoaderStatus = LdrpInitializeProcess(Context,
                                                  SystemArgument1);
 
             /* Check for success and if MinimumStackCommit was requested */
index 12e24fe..41694d3 100644 (file)
@@ -100,9 +100,7 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
 
                     /* Deal with Watcom and other retarded compilers */
                     if (!IatSize)
-                    {
                         IatSize = SectionHeader->SizeOfRawData;
-                    }
 
                     /* Found it, get out */
                     break;
@@ -255,7 +253,7 @@ NTSTATUS
 NTAPI
 LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
                                        IN PLDR_DATA_TABLE_ENTRY LdrEntry,
-                                       IN PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry,
+                                       IN PIMAGE_BOUND_IMPORT_DESCRIPTOR *BoundEntryPtr,
                                        IN PIMAGE_BOUND_IMPORT_DESCRIPTOR FirstEntry)
 {
     LPSTR ImportName = NULL, BoundImportName, ForwarderName;
@@ -264,11 +262,15 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
     PLDR_DATA_TABLE_ENTRY DllLdrEntry, ForwarderLdrEntry;
     PIMAGE_BOUND_FORWARDER_REF ForwarderEntry;
+    PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry;
     PPEB Peb = NtCurrentPeb();
     ULONG i, IatSize;
 
+    /* Get the pointer to the bound entry */
+    BoundEntry = *BoundEntryPtr;
+
     /* Get the name's VA */
-    BoundImportName = (LPSTR)(BoundEntry + BoundEntry->OffsetModuleName);
+    BoundImportName = (LPSTR)FirstEntry + BoundEntry->OffsetModuleName;
 
     /* Show debug mesage */
     if (ShowSnaps)
@@ -311,7 +313,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
         if (ShowSnaps)
         {
             DPRINT1("LDR: %wZ has stale binding to %s\n",
-                    &DllLdrEntry->BaseDllName,
+                    &LdrEntry->BaseDllName,
                     BoundImportName);
         }
 
@@ -324,7 +326,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
         if (ShowSnaps)
         {
             DPRINT1("LDR: %wZ has correct binding to %s\n",
-                    &DllLdrEntry->BaseDllName,
+                    &LdrEntry->BaseDllName,
                     BoundImportName);
         }
 
@@ -339,7 +341,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     for (i = 0; i < BoundEntry->NumberOfModuleForwarderRefs; i++)
     {
         /* Get the name */
-        ForwarderName = (LPSTR)(FirstEntry + ForwarderEntry->OffsetModuleName);
+        ForwarderName = (LPSTR)FirstEntry + ForwarderEntry->OffsetModuleName;
 
         /* Show debug message */
         if (ShowSnaps)
@@ -376,7 +378,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
             if (ShowSnaps)
             {
                 DPRINT1("LDR: %wZ has stale binding to %s\n",
-                        &ForwarderLdrEntry->BaseDllName,
+                        &LdrEntry->BaseDllName,
                         ForwarderName);
             }
 
@@ -389,7 +391,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
             if (ShowSnaps)
             {
                 DPRINT1("LDR: %wZ has correct binding to %s\n",
-                        &ForwarderLdrEntry->BaseDllName,
+                        &LdrEntry->BaseDllName,
                         ForwarderName);
             }
 
@@ -423,7 +425,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
             if (!_stricmp(ImportName, BoundImportName)) break;
 
             /* Move to next entry */
-            ImportEntry += 1;
+            ImportEntry++;
         }
 
         /* If we didn't find a name, fail */
@@ -477,7 +479,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
 
 Quickie:
     /* Write where we are now and return */
-    *BoundEntry = *FirstEntry;
+    *BoundEntryPtr = FirstEntry;
     return Status;
 }
 
@@ -496,7 +498,7 @@ LdrpHandleNewFormatImportDescriptors(IN LPWSTR DllPath OPTIONAL,
         /* Parse this descriptor */
         Status = LdrpHandleOneNewFormatImportDescriptor(DllPath,
                                                         LdrEntry,
-                                                        BoundEntry,
+                                                        &BoundEntry,
                                                         FirstEntry);
         if (!NT_SUCCESS(Status)) return Status;
     }
@@ -642,8 +644,35 @@ LdrpNameToOrdinal(LPSTR ImportName,
                   PULONG NameTable,
                   PUSHORT OrdinalTable)
 {
-    UNIMPLEMENTED;
-    return 0;
+    ULONG Start, End, Next;
+    LONG CmpResult;
+
+    /* Use classical binary search to find the ordinal */
+    Start = 0;
+    End = NumberOfNames - 1;
+    while (End >= Start)
+    {
+        /* Next will be exactly between Start and End */
+        Next = (Start + End) >> 1;
+
+        /* Compare this name with the one we need to find */
+        CmpResult = strcmp(ImportName, (PCHAR)((ULONG_PTR)ExportBase + NameTable[Next]));
+
+        /* We found our entry if result is 0 */
+        if (!CmpResult) break;
+
+        /* We didn't find, update our range then */
+        if (CmpResult < 0)
+            End = Next - 1;
+        else if (CmpResult > 0)
+            Start = Next + 1;
+    }
+
+    /* If end is before start, then the search failed */
+    if (End < Start) return -1;
+
+    /* Return found name */
+    return OrdinalTable[Next];
 }
 
 NTSTATUS
@@ -657,10 +686,12 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry = NULL;
     PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
     ULONG BoundSize, IatSize;
-DPRINT1("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry);
+
+    DPRINT("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry);
+
     /* Set up the Act Ctx */
     ActCtx.Size = sizeof(ActCtx);
-    ActCtx.Frame.Flags = 1;
+    ActCtx.Format = 1;
     RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
 
     /* Check if we have a manifest prober routine */
@@ -680,7 +711,7 @@ DPRINT1("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry);
     RtlActivateActivationContextUnsafeFast(&ActCtx,
                                            LdrEntry->EntryPointActivationContext);
 
-    /* Check if we were directed */
+    /* Check if we were redirected */
     if (!(LdrEntry->Flags & LDRP_REDIRECTED))
     {
         /* Get the Bound IAT */
@@ -764,7 +795,9 @@ LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,
     NTSTATUS Status;
     PPEB Peb = RtlGetCurrentPeb();
     PTEB Teb = NtCurrentTeb();
-DPRINT1("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBase, DataTableEntry, Existing);
+
+    DPRINT("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBase, DataTableEntry, Existing);
+
     /* Convert import descriptor name to unicode string */
     ImpDescName = &Teb->StaticUnicodeString;
     RtlInitAnsiString(&AnsiString, ImportName);
@@ -788,8 +821,8 @@ DPRINT1("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBa
 
     /* Map it */
     Status = LdrpMapDll(DllPath,
-                        ImpDescName->Buffer,
                         NULL,
+                        ImpDescName->Buffer,
                         NULL,
                         TRUE,
                         FALSE,
@@ -893,6 +926,12 @@ FailurePath:
         /* Is this a static snap? */
         if (Static)
         {
+            /* Inform the debug log */
+            if (IsOrdinal)
+                DPRINT1("Failed to snap ordinal 0x%x\n", OriginalOrdinal);
+            else
+                DPRINT1("Failed to snap %s\n", ImportName);
+
             /* These are critical errors. Setup a string for the DLL name */
             RtlInitAnsiString(&TempString, DllName ? DllName : "Unknown");
             RtlAnsiStringToUnicodeString(&HardErrorDllName, &TempString, TRUE);
@@ -944,6 +983,14 @@ FailurePath:
             /* Return ordinal error */
             RtlRaiseStatus(STATUS_ORDINAL_NOT_FOUND);
         }
+        else
+        {
+            /* Inform the debug log */
+            if (IsOrdinal)
+                DPRINT("Non-fatal: Failed to snap ordinal 0x%x\n", OriginalOrdinal);
+            else
+                DPRINT("Non-fatal: Failed to snap %s\n", ImportName);
+        }
 
         /* Set this as a bad DLL */
         Thunk->u1.Function = (ULONG_PTR)0xffbadd11;
index 8c27837..b3c4dce 100644 (file)
 #include <debug.h>
 
 /* GLOBALS *******************************************************************/
+#define IMAGE_DLLCHARACTERISTICS_WX86_DLL 0x1000
 
+LIST_ENTRY LdrpUnloadHead;
 PLDR_DATA_TABLE_ENTRY LdrpLoadedDllHandleCache;
+PLDR_DATA_TABLE_ENTRY LdrpGetModuleHandleCache;
 
 #define LDR_GET_HASH_ENTRY(x) (RtlUpcaseUnicodeChar((x)) & (LDR_HASH_TABLE_ENTRIES - 1))
 
@@ -32,6 +35,241 @@ LdrpCallDllEntry(PDLLMAIN_FUNC EntryPoint,
     return EntryPoint(BaseAddress, Reason, Context);
 }
 
+VOID
+NTAPI
+LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+                     IN ULONG Flags,
+                     OUT PUNICODE_STRING UpdateString)
+{
+    PIMAGE_BOUND_FORWARDER_REF NewImportForwarder;
+    
+
+    PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry;
+    PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
+    PIMAGE_THUNK_DATA FirstThunk;
+    PLDR_DATA_TABLE_ENTRY Entry;
+    PUNICODE_STRING ImportNameUnic;
+    ANSI_STRING ImportNameAnsi;
+    LPSTR ImportName;
+    ULONG ImportSize;
+    NTSTATUS Status;
+    ULONG i;
+
+    /* Check the action we need to perform */
+    if (Flags == LDRP_UPDATE_REFCOUNT)
+    {
+        /* Make sure entry is not being loaded already */
+        if (LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS)
+            return;
+
+        LdrEntry->Flags |= LDRP_LOAD_IN_PROGRESS;
+    }
+    else if (Flags == LDRP_UPDATE_DEREFCOUNT)
+    {
+        /* Make sure the entry is not being unloaded already */
+        if (LdrEntry->Flags & LDRP_UNLOAD_IN_PROGRESS)
+            return;
+
+        LdrEntry->Flags |= LDRP_UNLOAD_IN_PROGRESS;
+    }
+
+    /* Go through all bound DLLs and dereference them */
+    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);
+
+    if (BoundEntry)
+    {
+        /* Set entry flags if refing/derefing */
+        if (Flags == LDRP_UPDATE_REFCOUNT)
+            LdrEntry->Flags |= LDRP_LOAD_IN_PROGRESS;
+        else if (Flags == LDRP_UPDATE_DEREFCOUNT)
+            LdrEntry->Flags |= LDRP_UNLOAD_IN_PROGRESS;
+
+        while (BoundEntry->OffsetModuleName)
+        {
+            /* Get pointer to the current import name */
+            ImportName = (PCHAR)BoundEntry + BoundEntry->OffsetModuleName;
+
+            RtlInitAnsiString(&ImportNameAnsi, ImportName);
+            Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
+
+            if (NT_SUCCESS(Status))
+            {
+                if (LdrpCheckForLoadedDll(NULL,
+                                          ImportNameUnic,
+                                          TRUE,
+                                          FALSE,
+                                          &Entry))
+                {
+                    if (Entry->LoadCount != -1)
+                    {
+                        /* 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 = -1;
+                            break;
+                        }
+
+                        /* Show snaps */
+                        if (ShowSnaps)
+                        {
+                            DPRINT1("LDR: Flags %d  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
+                        }
+                    }
+
+                    /* Recurse into this entry */
+                    LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
+                }
+            }
+
+            /* 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 (LdrpCheckForLoadedDll(NULL,
+                                              ImportNameUnic,
+                                              TRUE,
+                                              FALSE,
+                                              &Entry))
+                    {
+                        if (Entry->LoadCount != -1)
+                        {
+                            /* 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 = -1;
+                                break;
+                            }
+
+                            /* Show snaps */
+                            if (ShowSnaps)
+                            {
+                                DPRINT1("LDR: Flags %d  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
+                            }
+                        }
+
+                        /* Recurse into this entry */
+                        LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
+                    }
+                }
+
+                NewImportForwarder++;
+            }
+
+            BoundEntry = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)NewImportForwarder;
+        }
+
+        /* We're done */
+        return;
+    }
+
+    /* Check oldstyle import descriptor */
+    ImportEntry = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(LdrEntry->DllBase,
+                                                                         TRUE,
+                                                                         IMAGE_DIRECTORY_ENTRY_IMPORT,
+                                                                         &ImportSize);
+    if (ImportEntry)
+    {
+        /* There is old one, so go through its entries */
+        while (ImportEntry->Name && ImportEntry->FirstThunk)
+        {
+            FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->FirstThunk);
+
+            /* Skip this entry if needed */
+            if (!FirstThunk->u1.Function)
+            {
+                ImportEntry++;
+                continue;
+            }
+
+            ImportName = (PSZ)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->Name);
+
+            RtlInitAnsiString(&ImportNameAnsi, ImportName);
+            Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
+            if (NT_SUCCESS(Status))
+            {
+                if (LdrpCheckForLoadedDll(NULL,
+                                          ImportNameUnic,
+                                          TRUE,
+                                          FALSE,
+                                          &Entry))
+                {
+                    if (Entry->LoadCount != -1)
+                    {
+                        /* 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 = -1;
+                            break;
+                        }
+
+                        /* Show snaps */
+                        if (ShowSnaps)
+                        {
+                            DPRINT1("LDR: Flags %d  %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
+                        }
+                    }
+
+                    /* Recurse */
+                    LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
+                }
+            }
+
+            /* Go to the next entry */
+            ImportEntry++;
+        }
+    }
+}
+
+VOID
+NTAPI
+LdrpUpdateLoadCount2(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+                     IN ULONG Flags)
+{
+    WCHAR Buffer[MAX_PATH];
+    UNICODE_STRING UpdateString;
+
+    /* Setup the string */
+    UpdateString.Buffer = Buffer;
+    UpdateString.Length = 0;
+    UpdateString.MaximumLength = sizeof(Buffer);
+
+    /* Call the extended API */
+    LdrpUpdateLoadCount3(LdrEntry, Flags, &UpdateString);
+}
+
 VOID
 NTAPI
 LdrpTlsCallback(PVOID BaseAddress, ULONG Reason)
@@ -77,46 +315,959 @@ LdrpTlsCallback(PVOID BaseAddress, ULONG Reason)
             }
         }
     }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        /* Do nothing */
-    }
-    _SEH2_END;
-}
-
-PVOID
-NTAPI
-LdrpFetchAddressOfEntryPoint(PVOID ImageBase)
-{
-    PIMAGE_NT_HEADERS NtHeaders;
-    ULONG_PTR EntryPoint;
-
-    /* Get entry point offset from NT headers */
-    NtHeaders = RtlImageNtHeader(ImageBase);
-    EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint;
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Do nothing */
+    }
+    _SEH2_END;
+}
+
+NTSTATUS
+NTAPI
+LdrpCodeAuthzCheckDllAllowed(PUNICODE_STRING FullName,
+                             HANDLE DllHandle)
+{
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+LdrpCreateDllSection(IN PUNICODE_STRING FullName,
+                     IN HANDLE DllHandle,
+                     IN PULONG DllCharacteristics OPTIONAL,
+                     OUT PHANDLE SectionHandle)
+{
+    HANDLE FileHandle;
+    NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+    ULONG_PTR HardErrorParameters[1];
+    ULONG Response;
+    SECTION_IMAGE_INFORMATION SectionImageInfo;
+
+    /* Check if we don't already have a handle */
+    if (!DllHandle)
+    {
+        /* Create the object attributes */
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   FullName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   NULL,
+                                   NULL);
+
+        /* Open the DLL */
+        Status = NtOpenFile(&FileHandle,
+                            SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,
+                            &ObjectAttributes,
+                            &IoStatusBlock,
+                            FILE_SHARE_READ | FILE_SHARE_DELETE,
+                            FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
+
+        /* Check if we failed */
+        if (!NT_SUCCESS(Status))
+        {
+            /* Attempt to open for execute only */
+            Status = NtOpenFile(&FileHandle,
+                                SYNCHRONIZE | FILE_EXECUTE,
+                                &ObjectAttributes,
+                                &IoStatusBlock,
+                                FILE_SHARE_READ | FILE_SHARE_DELETE,
+                                FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
+
+            /* Check if this failed too */
+            if (!NT_SUCCESS(Status))
+            {
+                /* Show debug message */
+                if (ShowSnaps)
+                {
+                    DPRINT1("LDR: LdrpCreateDllSection - NtOpenFile failed; status = %x\n",
+                            Status);
+                }
+
+                /* Make sure to return an expected status code */
+                if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+                {
+                    /* Callers expect this instead */
+                    Status = STATUS_DLL_NOT_FOUND;
+                }
+
+                /* Return an empty section handle */
+                *SectionHandle = NULL;
+                return Status;
+            }
+        }
+    }
+    else
+    {
+        /* Use the handle we already have */
+        FileHandle = DllHandle;
+    }
+
+    /* Create a section for the DLL */
+    Status = NtCreateSection(SectionHandle,
+                             SECTION_MAP_READ | SECTION_MAP_EXECUTE |
+                             SECTION_MAP_WRITE | SECTION_QUERY,
+                             NULL,
+                             NULL,
+                             PAGE_EXECUTE,
+                             SEC_IMAGE,
+                             FileHandle);
+
+    /* If mapping failed, raise a hard error */
+    if (!NT_SUCCESS(Status))
+    {
+        /* Forget the handle */
+        *SectionHandle = NULL;
+
+        /* Give the DLL name */
+        HardErrorParameters[0] = (ULONG_PTR)FullName;
+
+        /* Raise the error */
+        ZwRaiseHardError(STATUS_INVALID_IMAGE_FORMAT,
+                         1,
+                         1,
+                         HardErrorParameters,
+                         OptionOk,
+                         &Response);
+
+        /* Increment the error count */
+        if (LdrpInLdrInit) LdrpFatalHardErrorCount++;
+    }
+
+    /* Check for Safer restrictions */
+    if (DllCharacteristics &&
+        !(*DllCharacteristics & IMAGE_DLLCHARACTERISTICS_WX86_DLL))
+    {
+        /* Make sure it's executable */
+        Status = ZwQuerySection(*SectionHandle,
+                                SectionImageInformation,
+                                &SectionImageInfo,
+                                sizeof(SECTION_IMAGE_INFORMATION),
+                                NULL);
+        if (NT_SUCCESS(Status))
+        {
+            /* Check if it's executable */
+            if (SectionImageInfo.ImageContainsCode)
+            {
+                /* It is, check safer */
+                Status = LdrpCodeAuthzCheckDllAllowed(FullName, DllHandle);
+                if (!NT_SUCCESS(Status) && (Status != STATUS_NOT_FOUND))
+                {
+                    /* Show debug message */
+                    if (ShowSnaps)
+                    {
+                        DPRINT1("LDR: Loading of (%wZ) blocked by Winsafer\n",
+                                &FullName);
+                    }
+                }
+                else
+                {
+                    /* We're fine, return normally */
+                    goto Quickie;
+                }
+            }
+        }
+
+        /* Failure case, close section handle */
+        NtClose(*SectionHandle);
+        *SectionHandle = NULL;
+    }
+
+Quickie:
+    /* Close the file handle, we don't need it */
+    NtClose(FileHandle);
+
+    /* Return status */
+    return Status;
+}
+
+BOOLEAN
+NTAPI
+LdrpResolveDllName(PWSTR DllPath,
+                   PWSTR DllName,
+                   PUNICODE_STRING FullDllName,
+                   PUNICODE_STRING BaseDllName)
+{
+    PWCHAR NameBuffer, p1, p2 = 0;
+    ULONG Length;
+    ULONG BufSize = 500;
+
+    /* Allocate space for full DLL name */
+    FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufSize + sizeof(UNICODE_NULL));
+    if (!FullDllName->Buffer) return FALSE;
+
+    Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer,
+                                DllName,
+                                NULL,
+                                BufSize,
+                                FullDllName->Buffer,
+                                &BaseDllName->Buffer);
+
+    if (!Length || Length > BufSize)
+    {
+        if (ShowSnaps)
+        {
+            DPRINT1("LDR: LdrResolveDllName - Unable to find ");
+            DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer);
+        }
+
+        RtlFreeUnicodeString(FullDllName);
+        return FALSE;
+    }
+
+    /* Construct full DLL name */
+    FullDllName->Length = Length;
+    FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL);
+
+    /* Allocate a new buffer */
+    NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullDllName->MaximumLength);
+    if (!NameBuffer)
+    {
+        RtlFreeHeap(RtlGetProcessHeap(), 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);
+    FullDllName->Buffer = NameBuffer;
+
+    /* Find last backslash */
+    p1 = FullDllName->Buffer;
+    while (*p1)
+    {
+        if (*p1++ == L'\\')
+        {
+            p2 = p1;
+        }
+    }
+
+    /* If found, set p1 to it, otherwise p1 points to the beginning of DllName */
+    if (p2)
+        p1 = p2;
+    else
+        p1 = DllName;
+
+    p2 = p1;
+
+    /* Calculate remaining length */
+    while (*p1) ++p1;
+
+    /* 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);
+
+    if (!BaseDllName->Buffer)
+    {
+        RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
+        return FALSE;
+    }
+
+    /* Copy base dll name to the new buffer */
+    RtlMoveMemory(BaseDllName->Buffer,
+                  p2,
+                  BaseDllName->Length);
+
+    /* Null-terminate the string */
+    BaseDllName->Buffer[BaseDllName->Length / sizeof(WCHAR)] = 0;
+
+    return TRUE;
+}
+
+PVOID
+NTAPI
+LdrpFetchAddressOfEntryPoint(PVOID ImageBase)
+{
+    PIMAGE_NT_HEADERS NtHeaders;
+    ULONG_PTR EntryPoint;
+
+    /* Get entry point offset from NT headers */
+    NtHeaders = RtlImageNtHeader(ImageBase);
+    EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint;
+
+    /* If it's 0 - return so */
+    if (!EntryPoint) return NULL;
+
+    /* Add image base */
+    EntryPoint += (ULONG_PTR)ImageBase;
+
+    /* Return calculated pointer */
+    return (PVOID)EntryPoint;
+}
+
+HANDLE
+NTAPI
+LdrpCheckForKnownDll(PWSTR DllName,
+                     PUNICODE_STRING FullDllName,
+                     PUNICODE_STRING BaseDllName)
+{
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE Section = NULL;
+    UNICODE_STRING DllNameUnic;
+    NTSTATUS Status;
+    PCHAR p1;
+    PWCHAR p2;
+
+    /* Upgrade DllName to a unicode string */
+    RtlInitUnicodeString(&DllNameUnic, DllName);
+
+    /* Get the activation context */
+    Status = RtlFindActivationContextSectionString(0,
+                                                   NULL,
+                                                   ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
+                                                   &DllNameUnic,
+                                                   NULL);
+
+    /* Check if it's a SxS or not */
+    if (Status == STATUS_SXS_SECTION_NOT_FOUND ||
+        Status == STATUS_SXS_KEY_NOT_FOUND)
+    {
+        /* Set up BaseDllName */
+        BaseDllName->Length = DllNameUnic.Length;
+        BaseDllName->MaximumLength = DllNameUnic.MaximumLength;
+        BaseDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+                                              0,
+                                              DllNameUnic.MaximumLength);
+        if (!BaseDllName->Buffer) return NULL;
+
+        /* Copy the contents there */
+        RtlMoveMemory(BaseDllName->Buffer, DllNameUnic.Buffer, DllNameUnic.MaximumLength);
+
+        /* 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);
+        if (!FullDllName->Buffer)
+        {
+            /* Free base name and fail */
+            RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer);
+            return NULL;
+        }
+
+        RtlMoveMemory(FullDllName->Buffer, LdrpKnownDllPath.Buffer, LdrpKnownDllPath.Length);
+
+        /* Put a slash there */
+        p1 = (PCHAR)FullDllName->Buffer + LdrpKnownDllPath.Length;
+        p2 = (PWCHAR)p1;
+        *p2++ = (WCHAR)'\\';
+        p1 = (PCHAR)p2;
+
+        /* Set up DllNameUnic for a relative path */
+        DllNameUnic.Buffer = (PWSTR)p1;
+        DllNameUnic.Length = BaseDllName->Length;
+        DllNameUnic.MaximumLength = DllNameUnic.Length + sizeof(UNICODE_NULL);
+
+        /* Copy the contents */
+        RtlMoveMemory(p1, BaseDllName->Buffer, BaseDllName->MaximumLength);
+
+        /* There are all names, init attributes and open the section */
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &DllNameUnic,
+                                   OBJ_CASE_INSENSITIVE,
+                                   LdrpKnownDllObjectDirectory,
+                                   NULL);
+
+        Status = NtOpenSection(&Section,
+                               SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_WRITE,
+                               &ObjectAttributes);
+        if (!NT_SUCCESS(Status))
+        {
+            /* Opening failed, free resources */
+            Section = NULL;
+            RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer);
+        }
+    }
+    else
+    {
+        if (!NT_SUCCESS(Status)) Section = NULL;
+    }
+
+    /* Return section handle */
+    return Section;
+}
+
+NTSTATUS
+NTAPI
+LdrpSetProtection(PVOID ViewBase,
+                  BOOLEAN Restore)
+{
+    PIMAGE_NT_HEADERS NtHeaders;
+    PIMAGE_SECTION_HEADER Section;
+    NTSTATUS Status;
+    PVOID SectionBase;
+    SIZE_T SectionSize;
+    ULONG NewProtection, OldProtection, i;
+
+    /* Get the NT headers */
+    NtHeaders = RtlImageNtHeader(ViewBase);
+
+    /* Compute address of the first section header */
+    Section = (PIMAGE_SECTION_HEADER)(
+        (ULONG_PTR)NtHeaders + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
+        NtHeaders->FileHeader.SizeOfOptionalHeader);
+
+    /* Go through all sections */
+    for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++)
+    {
+        if (Section->SizeOfRawData &&
+            !(Section->Characteristics & IMAGE_SCN_MEM_WRITE))
+        {
+            /* This section is not writable and has some size, so we need to change
+               its protection */
+            if (Restore)
+            {
+                /* Set it to either EXECUTE or READONLY */
+                if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE)
+                    NewProtection = PAGE_EXECUTE;
+                else
+                    NewProtection = PAGE_READONLY;
+
+                /* Add PAGE_NOCACHE if needed */
+                if (Section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
+                    NewProtection |= PAGE_NOCACHE;
+            }
+            else
+            {
+                /* Enable write access */
+                NewProtection = PAGE_READWRITE;
+            }
+
+            SectionBase = (PVOID)((ULONG_PTR)ViewBase + Section->VirtualAddress);
+            SectionSize = Section->SizeOfRawData;
+
+            if (SectionSize)
+            {
+                /* Set protection */
+                Status = ZwProtectVirtualMemory(NtCurrentProcess(),
+                                                &SectionBase,
+                                                &SectionSize,
+                                                NewProtection,
+                                                &OldProtection);
+
+                if (!NT_SUCCESS(Status)) return Status;
+            }
+        }
+
+        /* Move to the next section */
+        Section++;
+    }
+
+    /* Flush instruction cache if necessary */
+    if (Restore) ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0);
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+LdrpMapDll(IN PWSTR SearchPath OPTIONAL,
+           IN PWSTR DllPath2,
+           IN PWSTR DllName OPTIONAL,
+           IN PULONG DllCharacteristics,
+           IN BOOLEAN Static,
+           IN BOOLEAN Redirect,
+           OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry)
+{
+    PTEB Teb = NtCurrentTeb();
+    PPEB Peb = NtCurrentPeb();
+    PWCHAR p1 = DllName;
+    WCHAR TempChar;
+    BOOLEAN KnownDll = FALSE;
+    UNICODE_STRING FullDllName, BaseDllName;
+    HANDLE SectionHandle = NULL, DllHandle = 0;
+    UNICODE_STRING NtPathDllName;
+    ULONG_PTR HardErrorParameters[2];
+    UNICODE_STRING HardErrorDllName, HardErrorDllPath;
+    ULONG Response;
+    SIZE_T ViewSize = 0;
+    PVOID ViewBase = NULL;
+    PVOID ArbitraryUserPointer;
+    PIMAGE_NT_HEADERS NtHeaders;
+    NTSTATUS HardErrorStatus, Status;
+    BOOLEAN OverlapDllFound = FALSE;
+    ULONG_PTR ImageBase, ImageEnd;
+    PLIST_ENTRY ListHead, NextEntry;
+    PLDR_DATA_TABLE_ENTRY CandidateEntry, LdrEntry;
+    ULONG_PTR CandidateBase, CandidateEnd;
+    UNICODE_STRING OverlapDll;
+    BOOLEAN RelocatableDll = TRUE;
+    UNICODE_STRING IllegalDll;
+    PVOID RelocData;
+    ULONG RelocDataSize = 0;
+
+    // FIXME: AppCompat stuff is missing
+
+    if (ShowSnaps)
+    {
+        DPRINT1("LDR: LdrpMapDll: Image Name %ws, Search Path %ws\n",
+                DllName,
+                SearchPath ? SearchPath : L"");
+    }
+
+    /* Check if we have a known dll directory */
+    if (LdrpKnownDllObjectDirectory)
+    {
+        /* Check if the path is full */
+        while (*p1)
+        {
+            TempChar = *p1++;
+            if (TempChar == '\\' || TempChar == '/' )
+            {
+                /* Complete path, don't do Known Dll lookup */
+                goto SkipCheck;
+            }
+        }
+
+        /* Try to find a Known DLL */
+        SectionHandle = LdrpCheckForKnownDll(DllName,
+                                             &FullDllName,
+                                             &BaseDllName);
+    }
+
+SkipCheck:
+
+    /* Check if the Known DLL Check returned something */
+    if (!SectionHandle)
+    {
+        /* It didn't, so try to resolve the name now */
+        if (LdrpResolveDllName(SearchPath,
+                               DllName,
+                               &FullDllName,
+                               &BaseDllName))
+        {
+            /* Got a name, display a message */
+            if (ShowSnaps)
+            {
+                DPRINT1("LDR: Loading (%s) %wZ\n",
+                        Static ? "STATIC" : "DYNAMIC",
+                        &FullDllName);
+            }
+
+            /* Convert to NT Name */
+            if (!RtlDosPathNameToNtPathName_U(FullDllName.Buffer,
+                                              &NtPathDllName,
+                                              NULL,
+                                              NULL))
+            {
+                /* Path was invalid */
+                return STATUS_OBJECT_PATH_SYNTAX_BAD;
+            }
+
+            /* Create a section for this dLL */
+            Status = LdrpCreateDllSection(&NtPathDllName,
+                                          DllHandle,
+                                          DllCharacteristics,
+                                          &SectionHandle);
+
+            /* Free the NT Name */
+            RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);
+
+            /* If we failed */
+            if (!NT_SUCCESS(Status))
+            {
+                /* Free the name strings and return */
+                RtlFreeUnicodeString(&FullDllName);
+                RtlFreeUnicodeString(&BaseDllName);
+                return Status;
+            }
+        }
+        else
+        {
+            /* We couldn't resolve the name, is this a static load? */
+            if (Static)
+            {
+                /* 
+                 * This is BAD! Static loads are CRITICAL. Bugcheck!
+                 * Initialize the strings for the error
+                 */
+                RtlInitUnicodeString(&HardErrorDllName, DllName);
+                RtlInitUnicodeString(&HardErrorDllPath,
+                                     DllPath2 ? DllPath2 : LdrpDefaultPath.Buffer);
+
+                /* Set them as error parameters */
+                HardErrorParameters[0] = (ULONG_PTR)&HardErrorDllName;
+                HardErrorParameters[1] = (ULONG_PTR)&HardErrorDllPath;
+
+                /* Raise the hard error */
+                NtRaiseHardError(STATUS_DLL_NOT_FOUND,
+                                 2,
+                                 0x00000003,
+                                 HardErrorParameters,
+                                 OptionOk,
+                                 &Response);
+
+                /* We're back, where we initializing? */
+                if (LdrpInLdrInit) LdrpFatalHardErrorCount++;
+            }
+
+            /* Return failure */
+            return STATUS_DLL_NOT_FOUND;
+        }
+    }
+    else
+    {
+        /* We have a section handle, so this is a known dll */
+        KnownDll = TRUE;
+    }
+
+    /* Stuff the image name in the TIB, for the debugger */
+    ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
+    Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
+
+    /* Map the DLL */
+    ViewBase = NULL;
+    ViewSize = 0;
+    Status = NtMapViewOfSection(SectionHandle,
+                                NtCurrentProcess(),
+                                &ViewBase,
+                                0,
+                                0,
+                                NULL,
+                                &ViewSize,
+                                ViewShare,
+                                0,
+                                PAGE_READWRITE);
+
+    /* Restore */
+    Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
+
+    /* Fail if we couldn't map it */
+    if (!NT_SUCCESS(Status))
+    {
+        /* Close and return */
+        NtClose(SectionHandle);
+        return Status;
+    }
+
+    /* Get the NT Header */
+    if (!(NtHeaders = RtlImageNtHeader(ViewBase)))
+    {
+        /* Invalid image, unmap, close handle and fail */
+        NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
+        NtClose(SectionHandle);
+        return STATUS_INVALID_IMAGE_FORMAT;
+    }
+
+    // FIXME: .NET support is missing
+
+    /* Allocate an entry */
+    if (!(LdrEntry = LdrpAllocateDataTableEntry(ViewBase)))
+    {
+        /* Invalid image, unmap, close handle and fail */
+        NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
+        NtClose(SectionHandle);
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Setup the entry */
+    LdrEntry->Flags = Static ? LDRP_STATIC_LINK : 0;
+    if (Redirect) LdrEntry->Flags |= LDRP_REDIRECTED;
+    LdrEntry->LoadCount = 0;
+    LdrEntry->FullDllName = FullDllName;
+    LdrEntry->BaseDllName = BaseDllName;
+    LdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrEntry->DllBase);
+
+    /* Show debug message */
+    if (ShowSnaps)
+    {
+        DPRINT1("LDR: LdrpMapDll: Full Name %wZ, Base Name %wZ\n",
+                &FullDllName,
+                &BaseDllName);
+    }
+
+    /* Insert this entry */
+    LdrpInsertMemoryTableEntry(LdrEntry);
+
+    // LdrpSendDllNotifications(LdrEntry, TRUE, Status == STATUS_IMAGE_NOT_AT_BASE)
+
+    /* Check for invalid CPU Image */
+    if (Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH)
+    {
+        /* Load our header */
+        PIMAGE_NT_HEADERS ImageNtHeader = RtlImageNtHeader(Peb->ImageBaseAddress);
+
+        /* Assume defaults if we don't have to run the Hard Error path */
+        HardErrorStatus = STATUS_SUCCESS;
+        Response = ResponseCancel;
+
+        /* Are we an NT 3.0 image? [Do these still exist? LOL -- IAI] */
+        if (ImageNtHeader->OptionalHeader.MajorSubsystemVersion <= 3)
+        {
+            /* Reset the entrypoint, save our Dll Name */
+            LdrEntry->EntryPoint = 0;
+            HardErrorParameters[0] = (ULONG_PTR)&FullDllName;
+
+            /* Raise the error */
+            HardErrorStatus = ZwRaiseHardError(STATUS_IMAGE_MACHINE_TYPE_MISMATCH,
+                                               1,
+                                               1,
+                                               HardErrorParameters,
+                                               OptionOkCancel,
+                                               &Response);
+        }
+
+        /* Check if the user pressed cancel */
+        if (NT_SUCCESS(HardErrorStatus) && Response == ResponseCancel)
+        {
+            /* Remove the DLL from the lists */
+            RemoveEntryList(&LdrEntry->InLoadOrderLinks);
+            RemoveEntryList(&LdrEntry->InMemoryOrderModuleList);
+            RemoveEntryList(&LdrEntry->HashLinks);
+
+            /* Remove the LDR Entry */
+            RtlFreeHeap(RtlGetProcessHeap(), 0, LdrEntry );
+
+            /* Unmap and close section */
+            NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
+            NtClose(SectionHandle);
+
+            /* Did we do a hard error? */
+            if (ImageNtHeader->OptionalHeader.MajorSubsystemVersion <= 3)
+            {
+                /* Yup, so increase fatal error count if we are initializing */
+                if (LdrpInLdrInit) LdrpFatalHardErrorCount++;
+            }
+
+            /* Return failure */
+            return STATUS_INVALID_IMAGE_FORMAT;
+        }
+    }
+    else
+    {
+        /* The image was valid. Is it a DLL? */
+        if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
+        {
+            /* Set the DLL Flag */
+            LdrEntry->Flags |= LDRP_IMAGE_DLL;
+        }
+
+        /* If we're not a DLL, clear the entrypoint */
+        if (!(LdrEntry->Flags & LDRP_IMAGE_DLL))
+        {
+            LdrEntry->EntryPoint = 0;
+        }
+    }
+
+    /* Return it for the caller */
+    *DataTableEntry = LdrEntry;
+
+    /* Check if we loaded somewhere else */
+    if (Status == STATUS_IMAGE_NOT_AT_BASE)
+    {
+        /* Write the flag */
+        LdrEntry->Flags |= LDRP_IMAGE_NOT_AT_BASE;
+
+        /* Find our region */
+        ImageBase = (ULONG_PTR)NtHeaders->OptionalHeader.ImageBase;
+        ImageEnd = ImageBase + ViewSize;
+
+        DPRINT1("LDR: LdrpMapDll Relocating Image Name %ws (%p -> %p)\n", DllName, ImageBase, ViewBase);
+
+        /* Scan all the modules */
+        ListHead = &Peb->Ldr->InLoadOrderModuleList;
+        NextEntry = ListHead->Flink;
+        while (NextEntry != ListHead)
+        {
+            /* Get the entry */
+            CandidateEntry = CONTAINING_RECORD(NextEntry,
+                                               LDR_DATA_TABLE_ENTRY,
+                                               InLoadOrderLinks);
+            NextEntry = NextEntry->Flink;
+
+            /* Get the entry's bounds */
+            CandidateBase = (ULONG_PTR)CandidateEntry->DllBase;
+            CandidateEnd = CandidateBase + CandidateEntry->SizeOfImage;
+
+            /* Make sure this entry isn't unloading */
+            if (!CandidateEntry->InMemoryOrderModuleList.Flink) continue;
+
+            /* Check if our regions are colliding */
+            if ((ImageBase >= CandidateBase && ImageBase <= CandidateEnd) ||
+                (ImageEnd >= CandidateBase && ImageEnd <= CandidateEnd) ||
+                (CandidateBase >= ImageBase && CandidateBase <= ImageEnd))
+            {
+                /* Found who is overlapping */
+                OverlapDllFound = TRUE;
+                OverlapDll = CandidateEntry->FullDllName;
+                break;
+            }
+        }
+
+        /* Check if we found the DLL overlapping with us */
+        if (!OverlapDllFound)
+        {
+            /* It's not another DLL, it's memory already here */
+            RtlInitUnicodeString(&OverlapDll, L"Dynamically Allocated Memory");
+        }
+
+        DPRINT1("Overlapping DLL: %wZ\n", &OverlapDll);
+
+        /* Are we dealing with a DLL? */
+        if (LdrEntry->Flags & LDRP_IMAGE_DLL)
+        {
+            /* Check if relocs were stripped */
+            if (!(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED))
+            {
+                /* Get the relocation data */
+                RelocData = RtlImageDirectoryEntryToData(ViewBase,
+                                                         TRUE,
+                                                         IMAGE_DIRECTORY_ENTRY_BASERELOC,
+                                                         &RelocDataSize);
+
+                /* Does the DLL not have any? */
+                if (!RelocData && !RelocDataSize)
+                {
+                    /* We'll allow this and simply continue */
+                    goto NoRelocNeeded;
+                }
+            }
+
+            /* See if this is an Illegal DLL - IE: user32 and kernel32 */
+            RtlInitUnicodeString(&IllegalDll,L"user32.dll");
+            if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE))
+            {
+                /* Can't relocate user32 */
+                RelocatableDll = FALSE;
+            }
+            else
+            {
+                RtlInitUnicodeString(&IllegalDll, L"kernel32.dll");
+                if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE))
+                {
+                    /* Can't relocate kernel32 */
+                    RelocatableDll = FALSE;
+                }
+            }
+
+            /* Check if this was a non-relocatable DLL or a known dll */
+            if (!RelocatableDll && KnownDll)
+            {
+                /* Setup for hard error */
+                HardErrorParameters[0] = (ULONG_PTR)&IllegalDll;
+                HardErrorParameters[1] = (ULONG_PTR)&OverlapDll;
+
+                /* Raise the error */
+                ZwRaiseHardError(STATUS_ILLEGAL_DLL_RELOCATION,
+                                 2,
+                                 3,
+                                 HardErrorParameters,
+                                 OptionOk,
+                                 &Response);
+
+                /* If initializing, increase the error count */
+                if (LdrpInLdrInit) LdrpFatalHardErrorCount++;
+
+                /* Don't do relocation */
+                Status = STATUS_CONFLICTING_ADDRESSES;
+                goto NoRelocNeeded;
+            }
+
+            /* Change the protection to prepare for relocation */
+            Status = LdrpSetProtection(ViewBase, FALSE);
+
+            /* Make sure we changed the protection */
+            if (NT_SUCCESS(Status))
+            {
+                /* Do the relocation */
+                Status = LdrRelocateImageWithBias(ViewBase, 0LL, NULL, STATUS_SUCCESS,
+                    STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
+
+                if (NT_SUCCESS(Status))
+                {
+                    /* Stuff the image name in the TIB, for the debugger */
+                    ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
+                    Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
+
+                    /* Map the DLL */
+                    Status = NtMapViewOfSection(SectionHandle,
+                                                NtCurrentProcess(),
+                                                &ViewBase,
+                                                0,
+                                                0,
+                                                NULL,
+                                                &ViewSize,
+                                                ViewShare,
+                                                0,
+                                                PAGE_READWRITE);
+
+                    /* Restore */
+                    Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
+
+                    /* Return the protection */
+                    Status = LdrpSetProtection(ViewBase, TRUE);
+                }
+            }
+//FailRelocate:
+            /* Handle any kind of failure */
+            if (!NT_SUCCESS(Status))
+            {
+                /* Remove it from the lists */
+                RemoveEntryList(&LdrEntry->InLoadOrderLinks);
+                RemoveEntryList(&LdrEntry->InMemoryOrderModuleList);
+                RemoveEntryList(&LdrEntry->HashLinks);
+
+                /* Unmap it, clear the entry */
+                NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
+                LdrEntry = NULL;
+            }
+
+            /* Show debug message */
+            if (ShowSnaps)
+            {
+                DPRINT1("LDR: Fixups %successfully re-applied @ %p\n",
+                        NT_SUCCESS(Status) ? "s" : "uns", ViewBase);
+            }
+        }
+        else
+        {
+NoRelocNeeded:
+            /* Not a DLL, or no relocation needed */
+            Status = STATUS_SUCCESS;
+
+            /* Stuff the image name in the TIB, for the debugger */
+            ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
+            Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
+
+            /* Map the DLL */
+            Status = NtMapViewOfSection(SectionHandle,
+                                        NtCurrentProcess(),
+                                        &ViewBase,
+                                        0,
+                                        0,
+                                        NULL,
+                                        &ViewSize,
+                                        ViewShare,
+                                        0,
+                                        PAGE_READWRITE);
+
+            /* Restore */
+            Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
+
+            /* Show debug message */
+            if (ShowSnaps)
+            {
+                DPRINT1("LDR: Fixups won't be re-applied to non-Dll @ %p\n", ViewBase);
+            }
+        }
+    }
 
-    /* If it's 0 - return so */
-    if (!EntryPoint) return NULL;
+    // FIXME: LdrpCheckCorImage() is missing
 
-    /* Add image base */
-    EntryPoint += (ULONG_PTR)ImageBase;
+    /* Check if this is an SMP Machine and a DLL */
+    if ((LdrpNumberOfProcessors > 1) &&
+        (LdrEntry && (LdrEntry->Flags & LDRP_IMAGE_DLL)))
+    {
+        /* Validate the image for MP */
+        LdrpValidateImageForMp(LdrEntry);
+    }
 
-    /* Return calculated pointer */
-    return (PVOID)EntryPoint;
-}
+    // FIXME: LdrpCorUnloadImage() is missing
 
-NTSTATUS
-NTAPI
-LdrpMapDll(IN PWSTR SearchPath OPTIONAL,
-           IN PWSTR DllPath2,
-           IN PWSTR DllName OPTIONAL,
-           IN PULONG DllCharacteristics,
-           IN BOOLEAN Static,
-           IN BOOLEAN Redirect,
-           OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry)
-{
-    UNIMPLEMENTED;
-    return STATUS_SUCCESS;
+    /* Close section and return status */
+    NtClose(SectionHandle);
+    return Status;
 }
 
 PLDR_DATA_TABLE_ENTRY
@@ -126,6 +1277,8 @@ LdrpAllocateDataTableEntry(IN PVOID BaseAddress)
     PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
     PIMAGE_NT_HEADERS NtHeader = RtlImageNtHeader(BaseAddress);
 
+    DPRINT("LdrpAllocateDataTableEntry(%p), NtHeader %p\n", BaseAddress, NtHeader);
+
     /* Make sure the header is valid */
     if (NtHeader)
     {
@@ -163,6 +1316,33 @@ LdrpInsertMemoryTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
     InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderModuleList);
 }
 
+VOID
+NTAPI
+LdrpFinalizeAndDeallocateDataTableEntry(PLDR_DATA_TABLE_ENTRY Entry)
+{
+    ASSERT(Entry != NULL);
+
+    /* Release the activation context if it exists */
+    if (Entry->EntryPointActivationContext)
+    {
+        /* Check if it wasn't already released */
+        if ((HANDLE)Entry->EntryPointActivationContext != INVALID_HANDLE_VALUE)
+        {
+            RtlReleaseActivationContext(Entry->EntryPointActivationContext);
+
+            /* Mark it as invalid */
+            Entry->EntryPointActivationContext = INVALID_HANDLE_VALUE;
+        }
+    }
+
+    /* Release the full dll name string */
+    if (Entry->FullDllName.Buffer)
+        LdrpFreeUnicodeString(&Entry->FullDllName);
+
+    /* Finally free the entry's memory */
+    RtlFreeHeap(RtlGetProcessHeap(), 0, Entry);
+}
+
 BOOLEAN
 NTAPI
 LdrpCheckForLoadedDllHandle(IN PVOID Base,
@@ -231,7 +1411,9 @@ LdrpCheckForLoadedDll(IN PWSTR DllPath,
     PVOID ViewBase = NULL;
     SIZE_T ViewSize = 0;
     PIMAGE_NT_HEADERS NtHeader, NtHeader2;
-DPRINT1("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath, DllName, Flag, RedirectedDll, LdrEntry);
+
+    DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath, DllName, Flag, RedirectedDll, LdrEntry);
+
     /* Check if a dll name was provided */
     if (!DllName->Buffer || !DllName->Buffer[0]) return FALSE;
 
@@ -499,7 +1681,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress,
     if (Name)
     {
         /* Show debug message */
-        if (ShowSnaps) DPRINT1("NAME - %s\n", Name->Buffer);
+        if (ShowSnaps) DbgPrint("NAME - %s\n", Name->Buffer);
 
         /* Make sure it's not too long */
         if ((Name->Length + sizeof(CHAR) + sizeof(USHORT)) > MAXLONG)
@@ -527,8 +1709,8 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress,
         ImportName->Hint = 0;
 
         /* Copy the name and null-terminate it */
-        RtlMoveMemory(&ImportName->Name, Name->Buffer, Name->Length);
-        ImportName->Name[Name->Length + 1] = 0;
+        RtlMoveMemory(ImportName->Name, Name->Buffer, Name->Length);
+        ImportName->Name[Name->Length] = 0;
 
         /* Clear the high bit */
         ImageBase = ImportName;
@@ -540,7 +1722,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress,
         ImageBase = NULL;
 
         /* Show debug message */
-        if (ShowSnaps) DPRINT1("ORDINAL - %lx\n", Ordinal);
+        if (ShowSnaps) DbgPrint("ORDINAL - %lx\n", Ordinal);
 
         if (Ordinal)
         {
@@ -563,7 +1745,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress,
         if (!LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry))
         {
             /* Invalid base */
-            DPRINT1("Invalid base address\n");
+            DPRINT1("Invalid base address %p\n", BaseAddress);
             Status = STATUS_DLL_NOT_FOUND;
             _SEH2_YIELD(goto Quickie;)
         }
@@ -576,7 +1758,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress,
 
         if (!ExportDir)
         {
-            DPRINT1("Image has no exports\n");
+            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);
             Status = STATUS_PROCEDURE_NOT_FOUND;
             _SEH2_YIELD(goto Quickie;)
         }
@@ -657,8 +1839,474 @@ LdrpLoadDll(IN BOOLEAN Redirected,
             OUT PVOID *BaseAddress,
             IN BOOLEAN CallInit)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PPEB Peb = NtCurrentPeb();
+    NTSTATUS Status = STATUS_SUCCESS;
+    PWCHAR p1, p2;
+    WCHAR NameBuffer[266];
+    LPWSTR RawDllName;
+    UNICODE_STRING RawDllNameString;
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    BOOLEAN InInit = LdrpInLdrInit;
+
+    /* Find the name without the extension */
+    p1 = DllName->Buffer;
+StartLoop:
+    p2 = NULL;
+    while (*p1)
+    {
+        if (*p1++ == L'.')
+        {
+            p2 = p1;
+        }
+        else if (*p1 == L'\\')
+        {
+            goto StartLoop;
+        }
+    }
+
+    /* 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 == '\\')
+    {
+        /* Check that we have space to add one */
+        if (DllName->Length + LdrApiDefaultExtension.Length >= sizeof(NameBuffer))
+        {
+            /* No space to add the extension */
+            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;
+    }
+    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);
+
+    /* Show debug message */
+    if (ShowSnaps)
+    {
+        DPRINT1("LDR: LdrLoadDll, loading %ws from %ws\n",
+                 RawDllName,
+                 DllPath ? DllPath : L"");
+    }
+
+    /* Check if the DLL is already loaded */
+    if (!LdrpCheckForLoadedDll(DllPath,
+                               &RawDllNameString,
+                               FALSE,
+                               Redirected,
+                               &LdrEntry))
+    {
+        /* Map it */
+        Status = LdrpMapDll(DllPath,
+                            DllPath,
+                            NameBuffer,
+                            DllCharacteristics,
+                            FALSE,
+                            Redirected,
+                            &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 Mark the DLL Ranges for Stack Traces later */
+
+        /* 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))
+            {
+                /* Walk the Import Descriptor */
+                Status = LdrpWalkImportDescriptor(DllPath, LdrEntry);
+            }
+
+            /* Update load count, unless it's locked */
+            if (LdrEntry->LoadCount != -1) LdrEntry->LoadCount++;
+            LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
+
+            /* Check if we failed */
+            if (!NT_SUCCESS(Status))
+            {
+                /* Clear entrypoint, and insert into list */
+                LdrEntry->EntryPoint = NULL;
+                InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
+                               &LdrEntry->InInitializationOrderModuleList);
+
+                /* Cancel the load and unload the DLL */
+                LdrpClearLoadInProgress();
+                LdrUnloadDll(LdrEntry->DllBase);
+
+                /* Return the error */
+                goto Quickie;
+            }
+        }
+        else if (LdrEntry->LoadCount != -1)
+        {
+            /* Increase load count */
+            LdrEntry->LoadCount++;
+        }
+
+        /* Insert it into the list */
+        InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
+                       &LdrEntry->InInitializationOrderModuleList);
+
+        /* If we have to run the entrypoint, make sure the DB is ready */
+        if (CallInit && LdrpLdrDatabaseIsSetup)
+        {
+            /* FIXME: Notify Shim Engine */
+
+            /* Run the init routine */
+            Status = LdrpRunInitializeRoutines(NULL);
+            if (!NT_SUCCESS(Status))
+            {
+                /* Failed, unload the DLL */
+                LdrUnloadDll(LdrEntry->DllBase);
+            }
+        }
+        else
+        {
+            /* The DB isn't ready, which means we were loaded because of a forwarder */
+            Status = STATUS_SUCCESS;
+        }
+    }
+    else
+    {
+        /* We were already loaded. Are we a DLL? */
+        if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != -1))
+        {
+            /* 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 != -1) LdrEntry->LoadCount++;
+        }
+    }
+
+Quickie:
+    /* Release the lock */
+    if (!InInit) RtlLeaveCriticalSection(Peb->LoaderLock);
+
+    /* Check for success */
+    if (NT_SUCCESS(Status))
+    {
+        /* Return the base address */
+        *BaseAddress = LdrEntry->DllBase;
+    }
+    else
+    {
+        /* Nothing found */
+        *BaseAddress = NULL;
+    }
+
+    /* Return status */
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+LdrUnloadDll(IN PVOID BaseAddress)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PPEB Peb = NtCurrentPeb();
+    PLDR_DATA_TABLE_ENTRY LdrEntry, CurrentEntry;
+    PVOID EntryPoint;
+    PLIST_ENTRY NextEntry;
+    LIST_ENTRY UnloadList;
+    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
+    PVOID CorImageData;
+    ULONG ComSectionSize;
+
+    /* Get the LDR Lock */
+    if (!LdrpInLdrInit) RtlEnterCriticalSection(Peb->LoaderLock);
+
+    /* Increase the unload count */
+    LdrpActiveUnloadCount++;
+
+    /* Skip unload */
+    if (LdrpShutdownInProgress) goto Quickie;
+
+    /* Make sure the DLL is valid and get its entry */
+    if (!LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry))
+    {
+        Status = STATUS_DLL_NOT_FOUND;
+        goto Quickie;
+    }
+
+    /* Check the current Load Count */
+    if (LdrEntry->LoadCount != -1)
+    {
+        /* Decrease it */
+        LdrEntry->LoadCount--;
+
+        /* If it's a dll */
+        if (LdrEntry->Flags & LDRP_IMAGE_DLL)
+        {
+            /* Set up the Act Ctx */
+            ActCtx.Size = sizeof(ActCtx);
+            ActCtx.Format = 1;
+            RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
+
+            /* Activate the ActCtx */
+            RtlActivateActivationContextUnsafeFast(&ActCtx,
+                                                   LdrEntry->EntryPointActivationContext);
+
+            /* Update the load count */
+            LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_DEREFCOUNT);
+
+            /* Release the context */
+            RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+        }
+    }
+    else
+    {
+        /* The DLL is locked */
+        goto Quickie;
+    }
+
+    /* Show debug message */
+    if (ShowSnaps) DPRINT1("LDR: UNINIT LIST\n");
+
+    /* Check if this is our only unload */
+    if (LdrpActiveUnloadCount == 1)
+    {
+        /* Initialize the unload list */
+        InitializeListHead(&LdrpUnloadHead);
+    }
+
+    /* Loop the modules to build the list */
+    NextEntry = Peb->Ldr->InInitializationOrderModuleList.Blink;
+    while (NextEntry != &Peb->Ldr->InInitializationOrderModuleList)
+    {
+        /* Get the entry */
+        LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
+        NextEntry = NextEntry->Blink;
+
+        /* Remove flag */
+        LdrEntry->Flags &= ~LDRP_UNLOAD_IN_PROGRESS;
+
+        /* If the load count is now 0 */
+        if (!LdrEntry->LoadCount)
+        {
+            /* Show message */
+            if (ShowSnaps)
+            {
+                DPRINT1("(%d) [%ws] %ws (%lx) deinit %lx\n",
+                        LdrpActiveUnloadCount,
+                        LdrEntry->BaseDllName.Buffer,
+                        LdrEntry->FullDllName.Buffer,
+                        (ULONG)LdrEntry->LoadCount,
+                        LdrEntry->EntryPoint);
+            }
+
+            /* FIXME: Call Shim Engine and notify */
+
+            /* Unlink it */
+            CurrentEntry = LdrEntry;
+            RemoveEntryList(&CurrentEntry->InInitializationOrderModuleList);
+            RemoveEntryList(&CurrentEntry->InMemoryOrderModuleList);
+            RemoveEntryList(&CurrentEntry->HashLinks);
+
+            /* If there's more then one active unload */
+            if (LdrpActiveUnloadCount > 1)
+            {
+                /* Flush the cached DLL handle and clear the list */
+                LdrpLoadedDllHandleCache = NULL;
+                CurrentEntry->InMemoryOrderModuleList.Flink = NULL;
+            }
+
+            /* Add the entry on the unload list */
+            InsertTailList(&LdrpUnloadHead, &CurrentEntry->HashLinks);
+        }
+    }
+
+    /* Only call the entrypoints once */
+    if (LdrpActiveUnloadCount > 1) goto Quickie;
+
+    /* Now loop the unload list and create our own */
+    InitializeListHead(&UnloadList);
+    CurrentEntry = NULL;
+    NextEntry = LdrpUnloadHead.Flink;
+    while (NextEntry != &LdrpUnloadHead)
+    {
+        /* If we have an active entry */
+        if (CurrentEntry)
+        {
+            /* Remove it */
+            RemoveEntryList(&CurrentEntry->InLoadOrderLinks);
+            CurrentEntry = NULL;
+
+            /* Reset list pointers */
+            NextEntry = LdrpUnloadHead.Flink;
+            if (NextEntry == &LdrpUnloadHead) break;
+        }
+
+        /* Get the current entry */
+        LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
+
+        /* Log the Unload Event */
+        //LdrpRecordUnloadEvent(LdrEntry);
+
+        /* Set the entry and clear it from the list */
+        CurrentEntry = LdrEntry;
+        LdrpLoadedDllHandleCache = NULL;
+        CurrentEntry->InMemoryOrderModuleList.Flink = NULL;
+
+        /* Move it from the global to the local list */
+        RemoveEntryList(&CurrentEntry->HashLinks);
+        InsertTailList(&UnloadList, &CurrentEntry->HashLinks);
+
+        /* Get the entrypoint */
+        EntryPoint = LdrEntry->EntryPoint;
+
+        /* Check if we should call it */
+        if (EntryPoint && (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED))
+        {
+            /* Show message */
+            if (ShowSnaps)
+            {
+                DPRINT1("LDR: Calling deinit %lx\n", EntryPoint);
+            }
+
+            /* Set up the Act Ctx */
+            ActCtx.Size = sizeof(ActCtx);
+            ActCtx.Format = 1;
+            RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
+
+            /* Activate the ActCtx */
+            RtlActivateActivationContextUnsafeFast(&ActCtx,
+                                                   LdrEntry->EntryPointActivationContext);
+
+            /* Call the entrypoint */
+            LdrpCallDllEntry(LdrEntry->EntryPoint,
+                             LdrEntry->DllBase,
+                             DLL_PROCESS_DETACH,
+                             NULL);
+
+            /* Release the context */
+            RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+        }
+
+        /* Remove it from the list */
+        RemoveEntryList(&CurrentEntry->InLoadOrderLinks);
+        CurrentEntry = NULL;
+        NextEntry = LdrpUnloadHead.Flink;
+    }
+
+    /* Now loop our local list */
+    NextEntry = UnloadList.Flink;
+    while (NextEntry != &UnloadList)
+    {
+        /* Get the entry */
+        LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
+        NextEntry = NextEntry->Flink;
+        CurrentEntry = LdrEntry;
+
+        /* Notify Application Verifier */
+        if (Peb->NtGlobalFlag & FLG_HEAP_ENABLE_TAIL_CHECK)
+        {
+            DPRINT1("We don't support Application Verifier yet\n");
+        }
+
+        /* Show message */
+        if (ShowSnaps)
+        {
+            DPRINT1("LDR: Unmapping [%ws]\n", LdrEntry->BaseDllName.Buffer);
+        }
+
+        /* Check if this is a .NET executable */
+        if ((CorImageData = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
+                                                         TRUE,
+                                                         IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
+                                                         &ComSectionSize)))
+        {
+            /* FIXME */
+            DPRINT1(".NET Images are not supported yet\n");
+        }
+
+        /* Check if we should unmap*/
+        if (!(CurrentEntry->Flags & LDR_COR_OWNS_UNMAP))
+        {
+            /* Unmap the DLL */
+            Status = NtUnmapViewOfSection(NtCurrentProcess(),
+                                          CurrentEntry->DllBase);
+        }
+
+        /* Unload the alternate resource module, if any */
+        LdrUnloadAlternateResourceModule(CurrentEntry->DllBase);
+
+        /* Send shutdown notification */
+        //LdrpSendDllNotifications(CurrentEntry, 2, LdrpShutdownInProgress);
+
+        /* Check if a Hotpatch is active */
+        if (LdrEntry->PatchInformation)
+        {
+            /* FIXME */
+            DPRINT1("We don't support Hotpatching yet\n");
+        }
+
+        /* Deallocate the Entry */
+        LdrpFinalizeAndDeallocateDataTableEntry(CurrentEntry);
+
+        /* If this is the cached entry, invalide it */
+        if (LdrpGetModuleHandleCache == CurrentEntry)
+        {
+            LdrpGetModuleHandleCache = NULL;
+        }
+    }
+
+Quickie:
+    /* Decrease unload count */
+    LdrpActiveUnloadCount--;
+    if (!LdrpInLdrInit) RtlLeaveCriticalSection(Peb->LoaderLock);
+
+    /* FIXME: Rundown the Hotpatch data, if present */
+
+    /* Return to caller */
+    return Status;
 }
 
 ULONG
@@ -692,4 +2340,110 @@ LdrpClearLoadInProgress()
     return ModulesCount;
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS NTAPI
+LdrAddRefDll(IN ULONG Flags,
+             IN PVOID BaseAddress)
+{
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    NTSTATUS Status = STATUS_SUCCESS;
+       ULONG Cookie;
+       BOOLEAN Locked = FALSE;
+
+       /* Check for invalid flags */
+    if (Flags & ~(LDR_PIN_MODULE))
+    {
+               /* Fail with invalid parameter status if so */
+               Status = STATUS_INVALID_PARAMETER;
+               goto quickie;
+    }
+
+       /* Acquire the loader lock if not in init phase */
+    if (!LdrpInLdrInit)
+    {
+        /* Acquire the lock */
+        Status = LdrLockLoaderLock(0, NULL, &Cookie);
+        if (!NT_SUCCESS(Status)) goto quickie;
+        Locked = TRUE;
+    }
+
+       /* Get this module's data table entry */
+       if (LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry))
+       {
+               if (!LdrEntry)
+               {
+                       /* Shouldn't happen */
+                       Status = STATUS_INTERNAL_ERROR;
+                       goto quickie;
+               }
+
+               /* If this is not a pinned module */
+               if (LdrEntry->LoadCount != -1)
+               {
+                       /* Update its load count */
+                       if (Flags & LDR_PIN_MODULE)
+                       {
+                               /* Pin it by setting load count to -1 */
+                               LdrEntry->LoadCount = -1;
+                               LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_PIN);
+                       }
+                       else
+                       {
+                               /* Increase its load count by one */
+                               LdrEntry->LoadCount++;
+                               LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
+                       }
+
+                       /* Clear load in progress */
+                       LdrpClearLoadInProgress();
+               }
+       }
+       else
+       {
+               /* There was an error getting this module's handle, return invalid param status */
+               Status = STATUS_INVALID_PARAMETER;
+               goto quickie;
+       }
+
+quickie:
+       if (!NT_SUCCESS(Status))
+       {
+               if (ShowSnaps ||
+                       (Status != STATUS_NO_SUCH_FILE &&
+                        Status != STATUS_DLL_NOT_FOUND &&
+                        Status != STATUS_OBJECT_NAME_NOT_FOUND))
+               {
+                       DPRINT1("LDR: LdrAddRefDll(%p) 0x%08lx\n", BaseAddress);
+               }
+       }
+
+       /* Release the lock if needed */
+       if (Locked) LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
+
+    return Status;
+}
+
+
+BOOLEAN
+NTAPI
+LdrpFreeUnicodeString(PUNICODE_STRING String)
+{
+    BOOLEAN Result = FALSE;
+
+    ASSERT(String != NULL);
+
+    /* If Buffer is not NULL - free it */
+    if (String->Buffer)
+        Result = RtlFreeHeap(RtlGetProcessHeap(), 0, String->Buffer);
+
+    /* Zero it out */
+    String->Length = 0;
+    String->MaximumLength = 0;
+    String->Buffer = NULL;
+
+    return Result;
+}
+
 /* EOF */
index f063aef..90c2ca8 100644 (file)
 /* INCLUDES *****************************************************************/
 
 #include <ntdll.h>
-#define NDEBUG
+//#define NDEBUG
 #include <debug.h>
 #include <win32k/callback.h>
 
 VOID RtlInitializeHeapManager(VOID);
-VOID LdrpInitLoader(VOID);
 extern PTEB LdrpTopLevelDllBeingLoadedTeb;
 VOID NTAPI RtlpInitDeferedCriticalSection(VOID);
 VOID RtlpInitializeVectoredExceptionHandling(VOID);
@@ -309,280 +308,4 @@ finish:
     return FALSE;
 }
 
-NTSTATUS
-NTAPI
-LdrpInitializeProcess_(PCONTEXT Context,
-                      PVOID SystemArgument1)
-{
-    PIMAGE_NT_HEADERS NTHeaders;
-    PEPFUNC EntryPoint;
-    PIMAGE_DOS_HEADER PEDosHeader;
-    PVOID ImageBase;
-    PPEB Peb = NtCurrentPeb();
-    PLDR_DATA_TABLE_ENTRY NtModule;     // ntdll
-    NLSTABLEINFO NlsTable;
-    WCHAR FullNtDllPath[MAX_PATH];
-    SYSTEM_BASIC_INFORMATION SystemInformation;
-    NTSTATUS Status;
-    PVOID BaseAddress = SystemArgument1;
-
-    DPRINT("LdrpInit()\n");
-    DPRINT("Peb %p\n", Peb);
-    ImageBase = Peb->ImageBaseAddress;
-    DPRINT("ImageBase %p\n", ImageBase);
-
-    if (ImageBase <= (PVOID) 0x1000)
-    {
-        DPRINT("ImageBase is null\n");
-        ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT);
-    }
-
-    /*  If MZ header exists  */
-    PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
-    NTHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)ImageBase + PEDosHeader->e_lfanew);
-    DPRINT("PEDosHeader %p\n", PEDosHeader);
-
-    if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
-        PEDosHeader->e_lfanew == 0L ||
-        NTHeaders->Signature != IMAGE_NT_SIGNATURE)
-    {
-        DPRINT1("Image has bad header\n");
-        ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT);
-    }
-
-    /* normalize process parameters */
-    RtlNormalizeProcessParams(Peb->ProcessParameters);
-
-    /* Initialize NLS data */
-    RtlInitNlsTables(Peb->AnsiCodePageData,
-                     Peb->OemCodePageData,
-                     Peb->UnicodeCaseTableData,
-                     &NlsTable);
-    RtlResetRtlTranslations(&NlsTable);
-
-    /* Get number of processors */
-    DPRINT("Here\n");
-    Status = ZwQuerySystemInformation(SystemBasicInformation,
-                                      &SystemInformation,
-                                      sizeof(SYSTEM_BASIC_INFORMATION),
-                                      NULL);
-    DPRINT("Here2\n");
-    if (!NT_SUCCESS(Status))
-    {
-        ZwTerminateProcess(NtCurrentProcess(), Status);
-    }
-
-    Peb->NumberOfProcessors = SystemInformation.NumberOfProcessors;
-
-    /* Initialize Critical Section Data */
-    RtlpInitDeferedCriticalSection();
-
-    /* Load execution options */
-    LoadImageFileExecutionOptions(Peb);
-
-    /* create process heap */
-    RtlInitializeHeapManager();
-    Peb->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE,
-                                     NULL,
-                                     NTHeaders->OptionalHeader.SizeOfHeapReserve,
-                                     NTHeaders->OptionalHeader.SizeOfHeapCommit,
-                                     NULL,
-                                     NULL);
-    if (Peb->ProcessHeap == 0)
-    {
-        DPRINT1("Failed to create process heap\n");
-        ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
-    }
-
-    /* Check for correct machine type */
-    if (NTHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_NATIVE)
-    {
-        ULONG_PTR HardErrorParameters[1];
-        UNICODE_STRING ImageNameU;
-        ANSI_STRING ImageNameA;
-        WCHAR *Ptr;
-        ULONG ErrorResponse;
-
-        DPRINT1("Image %wZ is for a foreign architecture (0x%x).\n",
-                &Peb->ProcessParameters->ImagePathName, NTHeaders->FileHeader.Machine);
-
-        /* Get the full image path name */
-        ImageNameU = Peb->ProcessParameters->ImagePathName;
-
-        /* Get the file name */
-        Ptr = Peb->ProcessParameters->ImagePathName.Buffer +
-              (Peb->ProcessParameters->ImagePathName.Length / sizeof(WCHAR)) -1;
-        while ((Ptr >= Peb->ProcessParameters->ImagePathName.Buffer) &&
-               (*Ptr != L'\\')) Ptr--;
-        ImageNameU.Buffer = Ptr + 1;
-        ImageNameU.Length = Peb->ProcessParameters->ImagePathName.Length -
-            (ImageNameU.Buffer - Peb->ProcessParameters->ImagePathName.Buffer) * sizeof(WCHAR);
-        ImageNameU.MaximumLength = ImageNameU.Length;
-
-        /*`Convert to ANSI, harderror message needs that */
-        RtlUnicodeStringToAnsiString(&ImageNameA, &ImageNameU, TRUE);
-
-        /* Raise harderror */
-        HardErrorParameters[0] = (ULONG_PTR)&ImageNameA;
-        NtRaiseHardError(STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE,
-                         1,
-                         1,
-                         HardErrorParameters,
-                         OptionOk,
-                         &ErrorResponse);
-
-        RtlFreeAnsiString(&ImageNameA);
-        ZwTerminateProcess(NtCurrentProcess(), STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE);
-    }
-
-    /* initialized vectored exception handling */
-    RtlpInitializeVectoredExceptionHandling();
-
-    /* initalize peb lock support */
-    RtlInitializeCriticalSection(&FastPebLock);
-    Peb->FastPebLock = &FastPebLock;
-
-    /* initialize tls bitmaps */
-    RtlInitializeBitMap(&TlsBitMap, Peb->TlsBitmapBits, TLS_MINIMUM_AVAILABLE);
-    RtlInitializeBitMap(&TlsExpansionBitMap, Peb->TlsExpansionBitmapBits, TLS_EXPANSION_SLOTS);
-
-    Peb->TlsBitmap = &TlsBitMap;
-    Peb->TlsExpansionBitmap = &TlsExpansionBitMap;
-    Peb->TlsExpansionCounter = TLS_MINIMUM_AVAILABLE;
-
-    /* Initialize table of callbacks for the kernel. */
-    Peb->KernelCallbackTable = RtlAllocateHeap(RtlGetProcessHeap(),
-                                               0,
-                                               sizeof(PVOID) *
-                                                (USER32_CALLBACK_MAXIMUM + 1));
-    if (Peb->KernelCallbackTable == NULL)
-    {
-        DPRINT1("Failed to create callback table\n");
-        ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
-    }
-
-    /* initalize loader lock */
-    RtlInitializeCriticalSection(&LdrpLoaderLock);
-    Peb->LoaderLock = &LdrpLoaderLock;
-
-    /* create loader information */
-    Peb->Ldr = (PPEB_LDR_DATA) RtlAllocateHeap(Peb->ProcessHeap,
-                                               0,
-                                               sizeof(PEB_LDR_DATA));
-    if (Peb->Ldr == NULL)
-    {
-        DPRINT1("Failed to create loader data\n");
-        ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
-    }
-
-    Peb->Ldr->Length = sizeof(PEB_LDR_DATA);
-    Peb->Ldr->Initialized = FALSE;
-    Peb->Ldr->SsHandle = NULL;
-    InitializeListHead(&Peb->Ldr->InLoadOrderModuleList);
-    InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList);
-    InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList);
-
-    /* Load compatibility settings */
-    LoadCompatibilitySettings(Peb);
-
-    /* build full ntdll path */
-    wcscpy(FullNtDllPath, SharedUserData->NtSystemRoot);
-    wcscat(FullNtDllPath, L"\\system32\\ntdll.dll");
-
-    /* add entry for ntdll */
-    NtModule = (PLDR_DATA_TABLE_ENTRY)
-                RtlAllocateHeap(Peb->ProcessHeap,
-                                0,
-                                sizeof(LDR_DATA_TABLE_ENTRY));
-    if (NtModule == NULL)
-    {
-        DPRINT1("Failed to create loader module entry (NTDLL)\n");
-        ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
-    }
-    memset(NtModule, 0, sizeof(LDR_DATA_TABLE_ENTRY));
-
-    NtModule->DllBase = BaseAddress;
-    NtModule->EntryPoint = 0;       /* no entry point */
-    RtlCreateUnicodeString(&NtModule->FullDllName, FullNtDllPath);
-    RtlCreateUnicodeString(&NtModule->BaseDllName, L"ntdll.dll");
-    NtModule->Flags = LDRP_IMAGE_DLL | LDRP_ENTRY_PROCESSED;
-
-    NtModule->LoadCount = -1;       /* don't unload */
-    NtModule->TlsIndex = -1;
-    NtModule->SectionPointer = NULL;
-    NtModule->CheckSum = 0;
-
-    NTHeaders = RtlImageNtHeader(NtModule->DllBase);
-    NtModule->SizeOfImage = LdrpGetResidentSize(NTHeaders);
-    NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
-
-    InsertTailList(&Peb->Ldr->InLoadOrderModuleList,
-                   &NtModule->InLoadOrderLinks);
-    InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
-                   &NtModule->InInitializationOrderModuleList);
-
-    /* add entry for executable (becomes first list entry) */
-    LdrpImageEntry = (PLDR_DATA_TABLE_ENTRY)
-                 RtlAllocateHeap(Peb->ProcessHeap,
-                                 HEAP_ZERO_MEMORY,
-                                 sizeof(LDR_DATA_TABLE_ENTRY));
-    if (LdrpImageEntry == NULL)
-    {
-        DPRINT1("Failed to create loader module infomation\n");
-        ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
-    }
-
-    LdrpImageEntry->DllBase = Peb->ImageBaseAddress;
-
-    if ((Peb->ProcessParameters == NULL) ||
-        (Peb->ProcessParameters->ImagePathName.Length == 0))
-    {
-        DPRINT1("Failed to access the process parameter block\n");
-        ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
-    }
-
-    RtlCreateUnicodeString(&LdrpImageEntry->FullDllName,
-                           Peb->ProcessParameters->ImagePathName.Buffer);
-    RtlCreateUnicodeString(&LdrpImageEntry->BaseDllName,
-                           wcsrchr(LdrpImageEntry->FullDllName.Buffer, L'\\') + 1);
-
-    DPRINT("BaseDllName '%wZ'  FullDllName '%wZ'\n", &LdrpImageEntry->BaseDllName, &LdrpImageEntry->FullDllName);
-
-    LdrpImageEntry->Flags = LDRP_ENTRY_PROCESSED;
-    LdrpImageEntry->LoadCount = -1;      /* don't unload */
-    LdrpImageEntry->TlsIndex = -1;
-    LdrpImageEntry->SectionPointer = NULL;
-    LdrpImageEntry->CheckSum = 0;
-
-    NTHeaders = RtlImageNtHeader(LdrpImageEntry->DllBase);
-    LdrpImageEntry->SizeOfImage = LdrpGetResidentSize(NTHeaders);
-    LdrpImageEntry->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
-
-    LdrpTopLevelDllBeingLoadedTeb = NtCurrentTeb();
-
-    InsertHeadList(&Peb->Ldr->InLoadOrderModuleList,
-                   &LdrpImageEntry->InLoadOrderLinks);
-
-    LdrpInitLoader();
-
-    EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL, NULL, NULL);
-    LdrpImageEntry->EntryPoint = EntryPoint;
-
-    /* all required dlls are loaded now */
-    Peb->Ldr->Initialized = TRUE;
-
-    /* Check before returning that we can run the image safely. */
-    if (EntryPoint == NULL)
-    {
-        DPRINT1("Failed to initialize image\n");
-        ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT);
-    }
-
-    /* Break into debugger */
-    if (Peb->BeingDebugged)
-        DbgBreakPoint();
-
-    return STATUS_SUCCESS;
-}
-
 /* EOF */
index 9ce0cbb..fe39e90 100644 (file)
@@ -42,31 +42,12 @@ extern PLDR_DATA_TABLE_ENTRY LdrpImageEntry;
 static NTSTATUS LdrFindEntryForName(PUNICODE_STRING Name, PLDR_DATA_TABLE_ENTRY *Module, BOOLEAN Ref);
 static PVOID LdrFixupForward(PCHAR ForwardName);
 static PVOID LdrGetExportByName(PVOID BaseAddress, PUCHAR SymbolName, USHORT Hint);
-static NTSTATUS LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
-                               IN ULONG LoadFlags,
-                               IN PUNICODE_STRING Name,
-                               OUT PLDR_DATA_TABLE_ENTRY *Module,
-                               OUT PVOID *BaseAddress OPTIONAL);
-static VOID LdrpDetachProcess(BOOLEAN UnloadAll);
-static NTSTATUS LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module, BOOLEAN Unload);
 
 NTSTATUS find_actctx_dll( LPCWSTR libname, WCHAR *fulldosname );
 NTSTATUS create_module_activation_context( LDR_DATA_TABLE_ENTRY *module );
 
 /* FUNCTIONS *****************************************************************/
 
-BOOLEAN
-LdrMappedAsDataFile(PVOID *BaseAddress)
-{
-    if (0 != ((DWORD_PTR) *BaseAddress & (PAGE_SIZE - 1)))
-    {
-        *BaseAddress = (PVOID)((DWORD_PTR)*BaseAddress & ~((DWORD_PTR) PAGE_SIZE - 1));
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
 static __inline LONG LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module, BOOLEAN Locked)
 {
     LONG LoadCount;
@@ -105,193 +86,6 @@ static __inline LONG LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module, BOOLEA
     return LoadCount;
 }
 
-static PWSTR
-LdrpQueryAppPaths(IN PCWSTR ImageName)
-{
-    PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    WCHAR SearchPathBuffer[5*MAX_PATH];
-    UNICODE_STRING ValueNameString;
-    UNICODE_STRING KeyName;
-    WCHAR NameBuffer[MAX_PATH];
-    ULONG KeyInfoSize;
-    ULONG ResultSize;
-    PWCHAR Backslash;
-    HANDLE KeyHandle;
-    NTSTATUS Status;
-    PWSTR Path = NULL;
-
-    _snwprintf(NameBuffer,
-               sizeof(NameBuffer) / sizeof(WCHAR),
-               L"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s",
-               ImageName);
-
-    RtlInitUnicodeString(&KeyName, NameBuffer);
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &KeyName,
-                               OBJ_CASE_INSENSITIVE,
-                               NULL,
-                               NULL);
-
-    Status = NtOpenKey(&KeyHandle,
-                       KEY_READ,
-                       &ObjectAttributes);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT ("NtOpenKey() failed (Status %lx)\n", Status);
-        return NULL;
-    }
-
-    KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 256 * sizeof(WCHAR);
-
-    KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize);
-    if (KeyInfo == NULL)
-    {
-        DPRINT("RtlAllocateHeap() failed\n");
-        NtClose(KeyHandle);
-        return NULL;
-    }
-
-    RtlInitUnicodeString(&ValueNameString,
-                         L"Path");
-
-    Status = NtQueryValueKey(KeyHandle,
-                             &ValueNameString,
-                             KeyValuePartialInformation,
-                             KeyInfo,
-                             KeyInfoSize,
-                             &ResultSize);
-
-    if (!NT_SUCCESS(Status))
-    {
-        NtClose(KeyHandle);
-        RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
-        return NULL;
-    }
-
-    RtlCopyMemory(SearchPathBuffer,
-                  &KeyInfo->Data,
-                  KeyInfo->DataLength);
-
-    /* Free KeyInfo memory, we won't need it anymore */
-    RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
-
-    /* Close the key handle */
-    NtClose(KeyHandle);
-
-    /* get application running path */
-    wcscat(SearchPathBuffer, L";");
-    wcscat(SearchPathBuffer, NtCurrentPeb()->ProcessParameters->ImagePathName.Buffer); // FIXME: Don't rely on it being NULL-terminated!!!
-
-    /* Remove trailing backslash */
-    Backslash = wcsrchr(SearchPathBuffer, L'\\');
-    if (Backslash) Backslash = L'\0';
-
-    wcscat(SearchPathBuffer, L";");
-
-    wcscat(SearchPathBuffer, SharedUserData->NtSystemRoot);
-    wcscat(SearchPathBuffer, L"\\system32;");
-    wcscat(SearchPathBuffer, SharedUserData->NtSystemRoot);
-    wcscat(SearchPathBuffer, L";.");
-
-    /* Copy it to the heap allocd memory */
-    Path = RtlAllocateHeap(RtlGetProcessHeap(),
-                           0,
-                           (wcslen(SearchPathBuffer) + 1) * sizeof(WCHAR));
-
-    if (!Path)
-    {
-        DPRINT1("RtlAllocateHeap() failed\n");
-        return NULL;
-    }
-
-    wcscpy(Path, SearchPathBuffer);
-
-    return Path;
-}
-
-VOID
-LdrpInitLoader(VOID)
-{
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    UNICODE_STRING LinkTarget;
-    UNICODE_STRING Name;
-    HANDLE LinkHandle;
-    ULONG Length;
-    NTSTATUS Status;
-
-    DPRINT("LdrpInitLoader() called for %wZ\n", &LdrpImageEntry->BaseDllName);
-
-    /* Get handle to the 'KnownDlls' directory */
-    RtlInitUnicodeString(&Name,
-                         L"\\KnownDlls");
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &Name,
-                               OBJ_CASE_INSENSITIVE,
-                               NULL,
-                               NULL);
-    Status = NtOpenDirectoryObject(&LdrpKnownDllObjectDirectory,
-                                   DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
-                                   &ObjectAttributes);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status);
-        LdrpKnownDllObjectDirectory = NULL;
-        return;
-    }
-
-    /* Allocate target name string */
-    LinkTarget.Length = 0;
-    LinkTarget.MaximumLength = MAX_PATH * sizeof(WCHAR);
-    LinkTarget.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
-                                        0,
-                                        MAX_PATH * sizeof(WCHAR));
-    if (LinkTarget.Buffer == NULL)
-    {
-        NtClose(LdrpKnownDllObjectDirectory);
-        LdrpKnownDllObjectDirectory = NULL;
-        return;
-    }
-
-    RtlInitUnicodeString(&Name,
-                         L"KnownDllPath");
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &Name,
-                               OBJ_CASE_INSENSITIVE,
-                               LdrpKnownDllObjectDirectory,
-                               NULL);
-    Status = NtOpenSymbolicLinkObject(&LinkHandle,
-                                      SYMBOLIC_LINK_ALL_ACCESS,
-                                      &ObjectAttributes);
-    if (!NT_SUCCESS(Status))
-    {
-        RtlFreeUnicodeString(&LinkTarget);
-        NtClose(LdrpKnownDllObjectDirectory);
-        LdrpKnownDllObjectDirectory = NULL;
-        return;
-    }
-
-    Status = NtQuerySymbolicLinkObject(LinkHandle,
-                                       &LinkTarget,
-                                       &Length);
-    NtClose(LinkHandle);
-    if (!NT_SUCCESS(Status))
-    {
-        RtlFreeUnicodeString(&LinkTarget);
-        NtClose(LdrpKnownDllObjectDirectory);
-        LdrpKnownDllObjectDirectory = NULL;
-    }
-
-    RtlCreateUnicodeString(&LdrpKnownDllPath,
-                           LinkTarget.Buffer);
-
-    RtlFreeUnicodeString(&LinkTarget);
-
-    DPRINT("LdrpInitLoader() done\n");
-}
-
-
 /***************************************************************************
  * NAME                                                         LOCAL
  *      LdrAdjustDllName
@@ -328,6 +122,8 @@ LdrAdjustDllName (PUNICODE_STRING FullDllName,
     PWCHAR Extension;
     PWCHAR Pointer;
 
+    DPRINT1("\n");
+
     Length = DllName->Length / sizeof(WCHAR);
 
     if (BaseName)
@@ -379,6 +175,8 @@ LdrAddModuleEntry(PVOID ImageBase,
 {
     PLDR_DATA_TABLE_ENTRY Module;
 
+    DPRINT1("\n");
+
     Module = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY));
     ASSERT(Module);
     memset(Module, 0, sizeof(LDR_DATA_TABLE_ENTRY));
@@ -420,407 +218,6 @@ LdrAddModuleEntry(PVOID ImageBase,
     return(Module);
 }
 
-
-static NTSTATUS
-LdrpMapKnownDll(IN PUNICODE_STRING DllName,
-                OUT PUNICODE_STRING FullDosName,
-                OUT PHANDLE SectionHandle)
-{
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    NTSTATUS Status;
-
-    DPRINT("LdrpMapKnownDll() called\n");
-
-    if (LdrpKnownDllObjectDirectory == NULL)
-    {
-        DPRINT("Invalid 'KnownDlls' directory\n");
-        return STATUS_UNSUCCESSFUL;
-    }
-
-    DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath);
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               DllName,
-                               OBJ_CASE_INSENSITIVE,
-                               LdrpKnownDllObjectDirectory,
-                               NULL);
-    Status = NtOpenSection(SectionHandle,
-                           SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE,
-                           &ObjectAttributes);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName, Status);
-        return Status;
-    }
-
-    FullDosName->Length = LdrpKnownDllPath.Length + DllName->Length + sizeof(WCHAR);
-    FullDosName->MaximumLength = FullDosName->Length + sizeof(WCHAR);
-    FullDosName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
-                                          0,
-                                          FullDosName->MaximumLength);
-    if (FullDosName->Buffer == NULL)
-    {
-        FullDosName->Length = 0;
-        FullDosName->MaximumLength = 0;
-        return STATUS_SUCCESS;
-    }
-
-    wcscpy(FullDosName->Buffer, LdrpKnownDllPath.Buffer);
-    wcscat(FullDosName->Buffer, L"\\");
-    wcscat(FullDosName->Buffer, DllName->Buffer);
-
-    DPRINT("FullDosName '%wZ'\n", FullDosName);
-
-    DPRINT("LdrpMapKnownDll() done\n");
-
-    return STATUS_SUCCESS;
-}
-
-
-static NTSTATUS
-LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL,
-                    IN PUNICODE_STRING DllName,
-                    OUT PUNICODE_STRING FullDosName,
-                    IN BOOLEAN MapAsDataFile,
-                    OUT PHANDLE SectionHandle)
-{
-    WCHAR                 *SearchPathBuffer = NULL;
-    WCHAR                 *ImagePathNameBufferPtr = NULL;
-    WCHAR                 DosName[MAX_PATH];
-    UNICODE_STRING        FullNtFileName;
-    UNICODE_STRING        PathEnvironmentVar_U;
-    UNICODE_STRING        PathName_U;
-    OBJECT_ATTRIBUTES     FileObjectAttributes;
-    HANDLE                FileHandle;
-    char                  BlockBuffer [1024];
-    PIMAGE_DOS_HEADER     DosHeader;
-    PIMAGE_NT_HEADERS     NTHeaders;
-    IO_STATUS_BLOCK       IoStatusBlock;
-    NTSTATUS              Status;
-    ULONG                 len;
-    ULONG                 ImagePathLen;
-
-    DPRINT("LdrpMapDllImageFile() called\n");
-
-    if (SearchPath == NULL)
-    {
-        /* get application running path */
-        ImagePathNameBufferPtr = NtCurrentPeb()->ProcessParameters->ImagePathName.Buffer;
-
-        /* Length of ImagePathName */
-        ImagePathLen = wcslen(ImagePathNameBufferPtr);
-
-        /* Subtract application name leaveing only the directory length */
-        while (ImagePathLen && ImagePathNameBufferPtr[ImagePathLen - 1] != L'\\')
-            ImagePathLen--;
-
-        /* Length of directory + semicolon */
-        len = ImagePathLen + 1;
-
-        /* Length of SystemRoot + "//system32"  + semicolon*/
-        len += wcslen(SharedUserData->NtSystemRoot) + 10;
-        /* Length of SystemRoot + semicolon */
-        len += wcslen(SharedUserData->NtSystemRoot) + 1;
-
-        RtlInitUnicodeString (&PathName_U, L"PATH");
-        PathEnvironmentVar_U.Length = 0;
-        PathEnvironmentVar_U.MaximumLength = 0;
-        PathEnvironmentVar_U.Buffer = NULL;
-
-        /* Get the path environment variable */
-        Status = RtlQueryEnvironmentVariable_U(NULL, &PathName_U, &PathEnvironmentVar_U);
-
-        /* Check that valid information was returned */
-        if ((Status == STATUS_BUFFER_TOO_SMALL) && (PathEnvironmentVar_U.Length > 0))
-        {
-            /* Allocate memory for the path env var */
-            PathEnvironmentVar_U.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, PathEnvironmentVar_U.Length + sizeof(WCHAR));
-            if (!PathEnvironmentVar_U.Buffer)
-            {
-                DPRINT1("Fatal! Out of Memory!!\n");
-                return STATUS_NO_MEMORY;
-            }
-            PathEnvironmentVar_U.MaximumLength = PathEnvironmentVar_U.Length + sizeof(WCHAR);
-
-            /* Retry */
-            Status = RtlQueryEnvironmentVariable_U(NULL, &PathName_U, &PathEnvironmentVar_U);
-
-            if (!NT_SUCCESS(Status))
-            {
-                DPRINT1("Unable to get path environment string!\n");
-                ASSERT(FALSE);
-            }
-            /* Length of path evn var + semicolon */
-            len += (PathEnvironmentVar_U.Length / sizeof(WCHAR)) + 1;
-        }
-
-        /* Allocate the size needed to hold all the above paths + period */
-        SearchPathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, (len + 2) * sizeof(WCHAR));
-        if (!SearchPathBuffer)
-        {
-            DPRINT1("Fatal! Out of Memory!!\n");
-            return STATUS_NO_MEMORY;
-        }
-
-        wcsncpy(SearchPathBuffer, ImagePathNameBufferPtr, ImagePathLen);
-        wcscat (SearchPathBuffer, L";");
-        wcscat (SearchPathBuffer, SharedUserData->NtSystemRoot);
-        wcscat (SearchPathBuffer, L"\\system32;");
-        wcscat (SearchPathBuffer, SharedUserData->NtSystemRoot);
-        wcscat (SearchPathBuffer, L";");
-
-        if (PathEnvironmentVar_U.Buffer)
-        {
-            wcscat (SearchPathBuffer, PathEnvironmentVar_U.Buffer);
-            wcscat (SearchPathBuffer, L";");
-            RtlFreeHeap(RtlGetProcessHeap(), 0, PathEnvironmentVar_U.Buffer);
-        }
-        wcscat (SearchPathBuffer, L".");
-
-        SearchPath = SearchPathBuffer;
-    }
-
-    if (RtlDosSearchPath_U (SearchPath,
-                            DllName->Buffer,
-                            NULL,
-                            MAX_PATH,
-                            DosName,
-                            NULL) == 0)
-    {
-        /* try to find active context dll */
-        Status = find_actctx_dll(DllName->Buffer, DosName);
-        if(Status == STATUS_SUCCESS)
-            DPRINT("found %S for %S\n", DosName,DllName->Buffer);
-        else
-            return STATUS_DLL_NOT_FOUND;
-    }
-
-    if (!RtlDosPathNameToNtPathName_U (DosName,
-                                       &FullNtFileName,
-                                       NULL,
-                                       NULL))
-    {
-        DPRINT("Dll %wZ not found!\n", DllName);
-        return STATUS_DLL_NOT_FOUND;
-    }
-
-    DPRINT("FullNtFileName %wZ\n", &FullNtFileName);
-
-    InitializeObjectAttributes(&FileObjectAttributes,
-                               &FullNtFileName,
-                               0,
-                               NULL,
-                               NULL);
-
-    DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName);
-
-    Status = NtOpenFile(&FileHandle,
-                        GENERIC_READ|SYNCHRONIZE,
-                        &FileObjectAttributes,
-                        &IoStatusBlock,
-                        FILE_SHARE_READ,
-                        FILE_SYNCHRONOUS_IO_NONALERT);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
-                &FullNtFileName, Status);
-        RtlFreeHeap (RtlGetProcessHeap (),
-                     0,
-                     FullNtFileName.Buffer);
-        return Status;
-    }
-    RtlFreeHeap (RtlGetProcessHeap (),
-                 0,
-                 FullNtFileName.Buffer);
-
-    if (!MapAsDataFile)
-    {
-
-        Status = NtReadFile(FileHandle,
-                            NULL,
-                            NULL,
-                            NULL,
-                            &IoStatusBlock,
-                            BlockBuffer,
-                            sizeof(BlockBuffer),
-                            NULL,
-                            NULL);
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT("Dll header read failed: Status = 0x%08lx\n", Status);
-            NtClose(FileHandle);
-            return Status;
-        }
-
-        /*
-         * Overlay DOS and NT headers structures to the
-         * buffer with DLL's header raw data.
-         */
-        DosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
-        NTHeaders = (PIMAGE_NT_HEADERS) (BlockBuffer + DosHeader->e_lfanew);
-        /*
-         * Check it is a PE image file.
-         */
-        if ((DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
-                || (DosHeader->e_lfanew == 0L)
-                || (*(PULONG)(NTHeaders) != IMAGE_NT_SIGNATURE))
-        {
-            DPRINT("NTDLL format invalid\n");
-            NtClose(FileHandle);
-
-            return STATUS_UNSUCCESSFUL;
-        }
-    }
-
-    /*
-     * Create a section for dll.
-     */
-    Status = NtCreateSection(SectionHandle,
-                             SECTION_ALL_ACCESS,
-                             NULL,
-                             NULL,
-                             PAGE_READONLY,
-                             MapAsDataFile ? SEC_COMMIT : SEC_IMAGE,
-                             FileHandle);
-    NtClose(FileHandle);
-
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status);
-        return Status;
-    }
-
-    RtlCreateUnicodeString(FullDosName,
-                           DosName);
-
-    return Status;
-}
-
-
-
-/***************************************************************************
- * NAME                                                         EXPORTED
- *      LdrLoadDll
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- *
- * @implemented
- */
-NTSTATUS NTAPI
-LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
-            IN PULONG LoadFlags OPTIONAL,
-            IN PUNICODE_STRING Name,
-            OUT PVOID *BaseAddress /* also known as HMODULE*, and PHANDLE 'DllHandle' */)
-{
-    NTSTATUS              Status;
-    PLDR_DATA_TABLE_ENTRY Module;
-    ULONG_PTR cookie;
-    PPEB Peb = NtCurrentPeb();
-
-    TRACE_LDR("LdrLoadDll loading %wZ%S%S with flags %d\n",
-              Name,
-              SearchPath ? L" from " : L"",
-              SearchPath ? SearchPath : L"",
-              LoadFlags ? *LoadFlags : 0);
-
-    Status = LdrpLoadModule(SearchPath, LoadFlags ? *LoadFlags : 0, Name, &Module, BaseAddress);
-
-    if (NT_SUCCESS(Status) &&
-            (!LoadFlags || 0 == (*LoadFlags & LOAD_LIBRARY_AS_DATAFILE)))
-    {
-        if (!create_module_activation_context( Module ))
-        {
-            RtlActivateActivationContext(0, Module->EntryPointActivationContext, &cookie);
-        }
-
-        if (!(Module->Flags & LDRP_PROCESS_ATTACH_CALLED))
-        {
-            RtlEnterCriticalSection(Peb->LoaderLock);
-            Status = LdrpRunInitializeRoutines(NULL);
-            RtlLeaveCriticalSection(Peb->LoaderLock);
-        }
-        if (Module->EntryPointActivationContext) RtlDeactivateActivationContext(0, cookie);
-    }
-
-    if ((!Module) && (NT_SUCCESS(Status)))
-        return Status;
-
-    *BaseAddress = NT_SUCCESS(Status) ? Module->DllBase : NULL;
-
-    return Status;
-}
-
-
-/***************************************************************************
- * NAME                                                         EXPORTED
- *      LdrFindEntryForAddress
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- *
- * @implemented
- */
-NTSTATUS NTAPI
-LdrFindEntryForAddress(PVOID Address,
-                       PLDR_DATA_TABLE_ENTRY *Module)
-{
-    PLIST_ENTRY ModuleListHead;
-    PLIST_ENTRY Entry;
-    PLDR_DATA_TABLE_ENTRY ModulePtr;
-
-    DPRINT("LdrFindEntryForAddress(Address %p)\n", Address);
-
-    if (NtCurrentPeb()->Ldr == NULL)
-        return(STATUS_NO_MORE_ENTRIES);
-
-    RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
-    ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
-    Entry = ModuleListHead->Flink;
-    if (Entry == ModuleListHead)
-    {
-        RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
-        return(STATUS_NO_MORE_ENTRIES);
-    }
-
-    while (Entry != ModuleListHead)
-    {
-        ModulePtr = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-
-        DPRINT("Scanning %wZ at %p\n", &ModulePtr->BaseDllName, ModulePtr->DllBase);
-
-        if ((Address >= ModulePtr->DllBase) &&
-            ((ULONG_PTR)Address <= ((ULONG_PTR)ModulePtr->DllBase + ModulePtr->SizeOfImage)))
-        {
-            *Module = ModulePtr;
-            RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
-            return(STATUS_SUCCESS);
-        }
-
-        Entry = Entry->Flink;
-    }
-
-    DPRINT("Failed to find module entry.\n");
-
-    RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
-    return(STATUS_NO_MORE_ENTRIES);
-}
-
-
 /***************************************************************************
  * NAME                                                         LOCAL
  *      LdrFindEntryForName
@@ -944,6 +341,8 @@ LdrFixupForward(PCHAR ForwardName)
     PLDR_DATA_TABLE_ENTRY Module;
     PVOID BaseAddress;
 
+    DPRINT1("\n");
+
     strcpy(NameBuffer, ForwardName);
     p = strchr(NameBuffer, '.');
     if (p != NULL)
@@ -984,7 +383,7 @@ LdrFixupForward(PCHAR ForwardName)
 
 /**********************************************************************
  * NAME                                                         LOCAL
- *      LdrGetExportByOrdinal
+ *      LdrGetExportByName
  *
  * DESCRIPTION
  *
@@ -995,66 +394,14 @@ LdrFixupForward(PCHAR ForwardName)
  * REVISIONS
  *
  * NOTE
+ *  AddressOfNames and AddressOfNameOrdinals are paralell tables,
+ *  both with NumberOfNames entries.
  *
  */
 static PVOID
-LdrGetExportByOrdinal (
-    PVOID   BaseAddress,
-    ULONG   Ordinal
-)
-{
-    PIMAGE_EXPORT_DIRECTORY ExportDir;
-    ULONG ExportDirSize;
-    PDWORD * ExFunctions;
-    PVOID Function;
-
-    ExportDir = (PIMAGE_EXPORT_DIRECTORY)
-                RtlImageDirectoryEntryToData (BaseAddress,
-                        TRUE,
-                        IMAGE_DIRECTORY_ENTRY_EXPORT,
-                        &ExportDirSize);
-
-
-    ExFunctions = (PDWORD*)RVA(BaseAddress, ExportDir->AddressOfFunctions);
-    DPRINT("LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
-           Ordinal, RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base]));
-
-    Function = (0 != ExFunctions[Ordinal - ExportDir->Base]
-                ? RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] )
-                : NULL);
-
-    if (((ULONG)Function >= (ULONG)ExportDir) &&
-        ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
-    {
-        DPRINT("Forward: %s\n", (PCHAR)Function);
-        Function = LdrFixupForward((PCHAR)Function);
-    }
-
-    return Function;
-}
-
-
-/**********************************************************************
- * NAME                                                         LOCAL
- *      LdrGetExportByName
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- *  AddressOfNames and AddressOfNameOrdinals are paralell tables,
- *  both with NumberOfNames entries.
- *
- */
-static PVOID
-LdrGetExportByName(PVOID BaseAddress,
-                   PUCHAR SymbolName,
-                   WORD Hint)
+LdrGetExportByName(PVOID BaseAddress,
+                   PUCHAR SymbolName,
+                   WORD Hint)
 {
     PIMAGE_EXPORT_DIRECTORY ExportDir;
     PDWORD *ExFunctions;
@@ -1201,6 +548,8 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
     LONG_PTR Delta;
     NTSTATUS Status;
 
+    DPRINT1("\n");
+
     if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
     {
         return STATUS_SUCCESS;
@@ -1294,56 +643,6 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
     return STATUS_SUCCESS;
 }
 
-static NTSTATUS
-LdrpGetOrLoadModule(PWCHAR SearchPath,
-                    PCHAR Name,
-                    PLDR_DATA_TABLE_ENTRY* Module,
-                    BOOLEAN Load)
-{
-    ANSI_STRING AnsiDllName;
-    UNICODE_STRING DllName;
-    NTSTATUS Status;
-
-    DPRINT("LdrpGetOrLoadModule() called for %s\n", Name);
-
-    RtlInitAnsiString(&AnsiDllName, Name);
-    Status = RtlAnsiStringToUnicodeString(&DllName, &AnsiDllName, TRUE);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    Status = LdrFindEntryForName (&DllName, Module, Load);
-    if (Load && !NT_SUCCESS(Status))
-    {
-        Status = LdrpLoadModule(SearchPath,
-                                0,
-                                &DllName,
-                                Module,
-                                NULL);
-        if (NT_SUCCESS(Status))
-        {
-            Status = LdrFindEntryForName (&DllName, Module, FALSE);
-        }
-        if (!NT_SUCCESS(Status))
-        {
-            ULONG ErrorResponse;
-            ULONG_PTR ErrorParameter = (ULONG_PTR)&AnsiDllName;
-
-            DPRINT1("failed to load %wZ\n", &DllName);
-
-            NtRaiseHardError(STATUS_DLL_NOT_FOUND,
-                             1,
-                             1,
-                             &ErrorParameter,
-                             OptionOk,
-                             &ErrorResponse);
-        }
-    }
-    RtlFreeUnicodeString (&DllName);
-    return Status;
-}
-
 void
 RtlpRaiseImportNotFound(CHAR *FuncName, ULONG Ordinal, PUNICODE_STRING DllName)
 {
@@ -1353,6 +652,8 @@ RtlpRaiseImportNotFound(CHAR *FuncName, ULONG Ordinal, PUNICODE_STRING DllName)
     ANSI_STRING DllNameAnsi;
     CHAR Buffer[8];
 
+    DPRINT1("\n");
+
     if (!FuncName)
     {
         _snprintf(Buffer, 8, "# %ld", Ordinal);
@@ -1372,1414 +673,66 @@ RtlpRaiseImportNotFound(CHAR *FuncName, ULONG Ordinal, PUNICODE_STRING DllName)
     RtlFreeAnsiString(&DllNameAnsi);
 }
 
-static NTSTATUS
-LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module,
-                                PLDR_DATA_TABLE_ENTRY ImportedModule,
-                                PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory)
+/*
+ * @implemented
+ */
+NTSTATUS NTAPI
+LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress)
 {
+    PLIST_ENTRY ModuleListHead;
+    PLIST_ENTRY Entry;
+    PLDR_DATA_TABLE_ENTRY Module;
     NTSTATUS Status;
-    PVOID* ImportAddressList;
-    PULONG FunctionNameList;
-    PVOID IATBase;
-    ULONG OldProtect;
-    ULONG Ordinal;
-    ULONG IATSize;
-
-    if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
-    {
-        return STATUS_UNSUCCESSFUL;
-    }
-
-    /* Get the import address list. */
-    ImportAddressList = (PVOID *)((ULONG_PTR)Module->DllBase +
-                                  (ULONG_PTR)ImportModuleDirectory->FirstThunk);
-
-    /* Get the list of functions to import. */
-    if (ImportModuleDirectory->OriginalFirstThunk != 0)
-    {
-        FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase +
-                                    (ULONG_PTR)ImportModuleDirectory->OriginalFirstThunk);
-    }
-    else
-    {
-        FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase +
-                                    (ULONG_PTR)ImportModuleDirectory->FirstThunk);
-    }
 
-    /* Get the size of IAT. */
-    IATSize = 0;
-    while (FunctionNameList[IATSize] != 0L)
-    {
-        IATSize++;
-    }
-
-    /* No need to fixup anything if IAT is empty */
-    if (IATSize == 0) return STATUS_SUCCESS;
-
-    /* Unprotect the region we are about to write into. */
-    IATBase = (PVOID)ImportAddressList;
-    IATSize *= sizeof(PVOID*);
-    Status = NtProtectVirtualMemory(NtCurrentProcess(),
-                                    &IATBase,
-                                    &IATSize,
-                                    PAGE_READWRITE,
-                                    &OldProtect);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("Failed to unprotect IAT.\n");
-        return(Status);
-    }
-
-    /* Walk through function list and fixup addresses. */
-    while (*FunctionNameList != 0L)
-    {
-        if ((*FunctionNameList) & 0x80000000)
-        {
-            Ordinal = (*FunctionNameList) & 0x7fffffff;
-            *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase,
-                                                       Ordinal);
-            if ((*ImportAddressList) == NULL)
-            {
-                DPRINT1("Failed to import #%ld from %wZ\n",
-                        Ordinal, &ImportedModule->FullDllName);
-                RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName);
-                return STATUS_ENTRYPOINT_NOT_FOUND;
-            }
-        }
-        else
-        {
-            IMAGE_IMPORT_BY_NAME *pe_name;
-            pe_name = RVA(Module->DllBase, *FunctionNameList);
-            *ImportAddressList = LdrGetExportByName(ImportedModule->DllBase,
-                                                    pe_name->Name,
-                                                    pe_name->Hint);
-            if ((*ImportAddressList) == NULL)
-            {
-                DPRINT1("Failed to import %s from %wZ\n",
-                        pe_name->Name, &ImportedModule->FullDllName);
-                RtlpRaiseImportNotFound((CHAR*)pe_name->Name,
-                                        0,
-                                        &ImportedModule->FullDllName);
-                return STATUS_ENTRYPOINT_NOT_FOUND;
-            }
-        }
-        ImportAddressList++;
-        FunctionNameList++;
-    }
+    DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress);
 
-    /* Protect the region we are about to write into. */
-    Status = NtProtectVirtualMemory(NtCurrentProcess(),
-                                    &IATBase,
-                                    &IATSize,
-                                    OldProtect,
-                                    &OldProtect);
-    if (!NT_SUCCESS(Status))
+    Status = STATUS_DLL_NOT_FOUND;
+    RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
+    ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
+    Entry = ModuleListHead->Flink;
+    while (Entry != ModuleListHead)
     {
-        DPRINT1("Failed to protect IAT.\n");
-        return(Status);
-    }
-
-    return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-LdrpProcessImportDirectory(
-    PLDR_DATA_TABLE_ENTRY Module,
-    PLDR_DATA_TABLE_ENTRY ImportedModule,
-    PCHAR ImportedName)
-{
-    NTSTATUS Status;
-    PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
-    PCHAR Name;
-    ULONG Size;
-
-    DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
-           Module, &Module->BaseDllName, ImportedName);
-
+        Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
 
-    ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
-                            RtlImageDirectoryEntryToData(Module->DllBase,
-                                    TRUE,
-                                    IMAGE_DIRECTORY_ENTRY_IMPORT,
-                                    &Size);
-    if (ImportModuleDirectory == NULL)
-    {
-        return STATUS_UNSUCCESSFUL;
-    }
+        DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module->BaseDllName, Module->DllBase);
 
-    while (ImportModuleDirectory->Name)
-    {
-        Name = (PCHAR)Module->DllBase + ImportModuleDirectory->Name;
-        if (0 == _stricmp(Name, ImportedName))
+        if (Module->DllBase == BaseAddress)
         {
-            Status = LdrpProcessImportDirectoryEntry(Module,
-                     ImportedModule,
-                     ImportModuleDirectory);
-            if (!NT_SUCCESS(Status))
+            if (Module->TlsIndex == 0xFFFF)
             {
-                return Status;
+                Module->Flags |= LDRP_DONT_CALL_FOR_THREADS;
+                Status = STATUS_SUCCESS;
             }
+            break;
         }
-        ImportModuleDirectory++;
+        Entry = Entry->Flink;
     }
-
-
-    return STATUS_SUCCESS;
+    RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
+    return Status;
 }
 
-
-static NTSTATUS
-LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module,
-                          PLDR_DATA_TABLE_ENTRY ImportedModule,
-                          PCHAR ImportedName)
+/*
+ * @implemented
+ */
+BOOLEAN NTAPI
+RtlDllShutdownInProgress (VOID)
 {
-    PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
-    NTSTATUS Status;
-    PVOID* ImportAddressList;
-    PVOID Start;
-    PVOID End;
-    PULONG FunctionNameList;
-    PVOID IATBase;
-    ULONG OldProtect;
-    ULONG Offset;
-    ULONG IATSize;
-    PIMAGE_NT_HEADERS NTHeaders;
-    PCHAR Name;
-    ULONG Size;
-
-    DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
-           Module, &Module->BaseDllName, ImportedModule, &ImportedModule->BaseDllName, ImportedName);
-
-    ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
-                            RtlImageDirectoryEntryToData(Module->DllBase,
-                                    TRUE,
-                                    IMAGE_DIRECTORY_ENTRY_IMPORT,
-                                    &Size);
-    if (ImportModuleDirectory == NULL)
-    {
-        return STATUS_UNSUCCESSFUL;
-    }
-
-    while (ImportModuleDirectory->Name)
-    {
-        Name = (PCHAR)Module->DllBase + ImportModuleDirectory->Name;
-        if (0 == _stricmp(Name, (PCHAR)ImportedName))
-        {
-
-            /* Get the import address list. */
-            ImportAddressList = (PVOID *)((ULONG_PTR)Module->DllBase +
-                                          (ULONG_PTR)ImportModuleDirectory->FirstThunk);
-
-            /* Get the list of functions to import. */
-            if (ImportModuleDirectory->OriginalFirstThunk != 0)
-            {
-                FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase +
-                                            (ULONG_PTR)ImportModuleDirectory->OriginalFirstThunk);
-            }
-            else
-            {
-                FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase +
-                                            (ULONG_PTR)ImportModuleDirectory->FirstThunk);
-            }
-
-            /* Get the size of IAT. */
-            IATSize = 0;
-            while (FunctionNameList[IATSize] != 0L)
-            {
-                IATSize++;
-            }
-
-            /* Unprotect the region we are about to write into. */
-            IATBase = (PVOID)ImportAddressList;
-            IATSize *= sizeof(PVOID*);
-            Status = NtProtectVirtualMemory(NtCurrentProcess(),
-                                            &IATBase,
-                                            &IATSize,
-                                            PAGE_READWRITE,
-                                            &OldProtect);
-            if (!NT_SUCCESS(Status))
-            {
-                DPRINT1("Failed to unprotect IAT.\n");
-                return(Status);
-            }
-
-            NTHeaders = RtlImageNtHeader (ImportedModule->DllBase);
-            Start = (PVOID)NTHeaders->OptionalHeader.ImageBase;
-            End = (PVOID)((ULONG_PTR)Start + ImportedModule->SizeOfImage);
-            Offset = (ULONG)((ULONG_PTR)ImportedModule->DllBase - (ULONG_PTR)Start);
-
-            /* Walk through function list and fixup addresses. */
-            while (*FunctionNameList != 0L)
-            {
-                if (*ImportAddressList >= Start && *ImportAddressList < End)
-                {
-                    (*ImportAddressList) = (PVOID)((ULONG_PTR)(*ImportAddressList) + Offset);
-                }
-                ImportAddressList++;
-                FunctionNameList++;
-            }
-
-            /* Protect the region we are about to write into. */
-            Status = NtProtectVirtualMemory(NtCurrentProcess(),
-                                            &IATBase,
-                                            &IATSize,
-                                            OldProtect,
-                                            &OldProtect);
-            if (!NT_SUCCESS(Status))
-            {
-                DPRINT1("Failed to protect IAT.\n");
-                return(Status);
-            }
-        }
-        ImportModuleDirectory++;
-    }
-    return STATUS_SUCCESS;
+    DPRINT1("\n");
+    return LdrpDllShutdownInProgress;
 }
 
-
-/**********************************************************************
- * NAME                                                         LOCAL
- *      LdrFixupImports
- *
- * DESCRIPTION
- *      Compute the entry point for every symbol the DLL imports
- *      from other modules.
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- *
+/*
+ * Compute size of an image as it is actually present in virt memory
+ * (i.e. excluding NEVER_LOAD sections)
  */
-static NTSTATUS
-LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
-                IN PLDR_DATA_TABLE_ENTRY Module)
+ULONG
+LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders)
 {
-    PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
-    PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent;
-    PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor;
-    PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent;
-    PIMAGE_TLS_DIRECTORY TlsDirectory;
-    ULONG TlsSize = 0;
-    NTSTATUS Status = STATUS_SUCCESS;
-    PLDR_DATA_TABLE_ENTRY ImportedModule;
-    PCHAR ImportedName;
-    PWSTR ModulePath;
-    ULONG Size;
-    ULONG_PTR cookie;
-
-    DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath, Module);
-
-    /* Check for tls data */
-    TlsDirectory = (PIMAGE_TLS_DIRECTORY)
-                   RtlImageDirectoryEntryToData(Module->DllBase,
-                           TRUE,
-                           IMAGE_DIRECTORY_ENTRY_TLS,
-                           &Size);
-    if (TlsDirectory)
-    {
-        TlsSize = TlsDirectory->EndAddressOfRawData
-                  - TlsDirectory->StartAddressOfRawData
-                  + TlsDirectory->SizeOfZeroFill;
-
-        if (TlsSize > 0 && NtCurrentPeb()->Ldr->Initialized)
-        {
-            TRACE_LDR("Trying to dynamically load %wZ which contains a TLS directory\n",
-                      &Module->BaseDllName);
-            TlsDirectory = NULL;
-        }
-    }
-
-    if (!create_module_activation_context( Module ))
-    {
-        if (Module->EntryPointActivationContext == NULL)
-        {
-            DPRINT("EntryPointActivationContext has not be allocated\n");
-            DPRINT("Module->DllBaseName %wZ\n", Module->BaseDllName);
-        }
-        RtlActivateActivationContext( 0, Module->EntryPointActivationContext, &cookie );
-    }
-
-    /*
-     * Process each import module.
-     */
-    ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
-                            RtlImageDirectoryEntryToData(Module->DllBase,
-                                    TRUE,
-                                    IMAGE_DIRECTORY_ENTRY_IMPORT,
-                                    &Size);
-
-    BoundImportDescriptor = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)
-                            RtlImageDirectoryEntryToData(Module->DllBase,
-                                    TRUE,
-                                    IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
-                                    &Size);
-
-    if (BoundImportDescriptor != NULL && ImportModuleDirectory == NULL)
-    {
-        DPRINT1("%wZ has only a bound import directory\n", &Module->BaseDllName);
-        return STATUS_UNSUCCESSFUL;
-    }
-    if (BoundImportDescriptor)
-    {
-        DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor);
-
-        BoundImportDescriptorCurrent = BoundImportDescriptor;
-        while (BoundImportDescriptorCurrent->OffsetModuleName)
-        {
-            ImportedName = (PCHAR)BoundImportDescriptor +
-                           BoundImportDescriptorCurrent->OffsetModuleName;
-            TRACE_LDR("%wZ bound to %s\n", &Module->BaseDllName, ImportedName);
-            Status = LdrpGetOrLoadModule(SearchPath, ImportedName, &ImportedModule, TRUE);
-            if (!NT_SUCCESS(Status))
-            {
-                DPRINT1("failed to load %s\n", ImportedName);
-                return Status;
-            }
-            if (Module == ImportedModule)
-            {
-                LdrpDecrementLoadCount(Module, FALSE);
-            }
-            if (ImportedModule->TimeDateStamp != BoundImportDescriptorCurrent->TimeDateStamp)
-            {
-                TRACE_LDR("%wZ has stale binding to %wZ\n",
-                          &Module->BaseDllName, &ImportedModule->BaseDllName);
-                Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName);
-                if (!NT_SUCCESS(Status))
-                {
-                    DPRINT1("failed to import %s\n", ImportedName);
-                    return Status;
-                }
-            }
-            else
-            {
-                BOOLEAN WrongForwarder;
-                WrongForwarder = FALSE;
-                if (ImportedModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
-                {
-                    TRACE_LDR("%wZ has stale binding to %s\n",
-                              &Module->BaseDllName, ImportedName);
-                }
-                else
-                {
-                    TRACE_LDR("%wZ has correct binding to %wZ\n",
-                              &Module->BaseDllName, &ImportedModule->BaseDllName);
-                }
-                if (BoundImportDescriptorCurrent->NumberOfModuleForwarderRefs)
-                {
-                    PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef;
-                    ULONG i;
-                    PLDR_DATA_TABLE_ENTRY ForwarderModule;
-                    PCHAR ForwarderName;
-
-                    BoundForwarderRef = (PIMAGE_BOUND_FORWARDER_REF)(BoundImportDescriptorCurrent + 1);
-                    for (i = 0;
-                         i < BoundImportDescriptorCurrent->NumberOfModuleForwarderRefs;
-                         i++, BoundForwarderRef++)
-                    {
-                        ForwarderName = (PCHAR)BoundImportDescriptor +
-                                        BoundForwarderRef->OffsetModuleName;
-                        TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
-                                  &Module->BaseDllName, ForwarderName, ImportedName);
-                        Status = LdrpGetOrLoadModule(SearchPath, ForwarderName, &ForwarderModule, TRUE);
-                        if (!NT_SUCCESS(Status))
-                        {
-                            DPRINT1("failed to load %s\n", ForwarderName);
-                            return Status;
-                        }
-                        if (Module == ImportedModule)
-                        {
-                            LdrpDecrementLoadCount(Module, FALSE);
-                        }
-                        if (ForwarderModule->TimeDateStamp != BoundForwarderRef->TimeDateStamp ||
-                                ForwarderModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
-                        {
-                            TRACE_LDR("%wZ has stale binding to %s\n",
-                                      &Module->BaseDllName, ForwarderName);
-                            WrongForwarder = TRUE;
-                        }
-                        else
-                        {
-                            TRACE_LDR("%wZ has correct binding to %s\n",
-                                      &Module->BaseDllName, ForwarderName);
-                        }
-                    }
-                }
-                if (WrongForwarder ||
-                        ImportedModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
-                {
-                    Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName);
-                    if (!NT_SUCCESS(Status))
-                    {
-                        DPRINT1("failed to import %s\n", ImportedName);
-                        return Status;
-                    }
-                }
-                else if (ImportedModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
-                {
-                    TRACE_LDR("Adjust imports for %s from %wZ\n",
-                              ImportedName, &Module->BaseDllName);
-                    Status = LdrpAdjustImportDirectory(Module, ImportedModule, ImportedName);
-                    if (!NT_SUCCESS(Status))
-                    {
-                        DPRINT1("failed to adjust import entries for %s\n", ImportedName);
-                        return Status;
-                    }
-                }
-                else if (WrongForwarder)
-                {
-                    /*
-                     * FIXME:
-                     *   Update only forwarders
-                     */
-                    TRACE_LDR("Stale BIND %s from %wZ\n",
-                              ImportedName, &Module->BaseDllName);
-                    Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName);
-                    if (!NT_SUCCESS(Status))
-                    {
-                        DPRINT1("faild to import %s\n", ImportedName);
-                        return Status;
-                    }
-                }
-                else
-                {
-                    /* nothing to do */
-                }
-            }
-            BoundImportDescriptorCurrent += BoundImportDescriptorCurrent->NumberOfModuleForwarderRefs + 1;
-        }
-    }
-    else if (ImportModuleDirectory)
-    {
-        DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory);
-
-        ImportModuleDirectoryCurrent = ImportModuleDirectory;
-        while (ImportModuleDirectoryCurrent->Name)
-        {
-            ImportedName = (PCHAR)Module->DllBase + ImportModuleDirectoryCurrent->Name;
-            TRACE_LDR("%wZ imports functions from %s\n", &Module->BaseDllName, ImportedName);
-
-            if (SearchPath == NULL)
-            {
-                ModulePath = LdrpQueryAppPaths(Module->BaseDllName.Buffer);
-
-                Status = LdrpGetOrLoadModule(ModulePath, ImportedName, &ImportedModule, TRUE);
-                if (ModulePath != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, ModulePath);
-                if (NT_SUCCESS(Status)) goto Success;
-            }
-
-            Status = LdrpGetOrLoadModule(SearchPath, ImportedName, &ImportedModule, TRUE);
-            if (!NT_SUCCESS(Status))
-            {
-                DPRINT1("failed to load %s\n", ImportedName);
-                break;
-            }
-Success:
-            if (Module == ImportedModule)
-            {
-                LdrpDecrementLoadCount(Module, FALSE);
-            }
+    PIMAGE_SECTION_HEADER SectionHeader;
+    unsigned SectionIndex;
+    ULONG ResidentSize;
 
-            TRACE_LDR("Initializing imports for %wZ from %s\n",
-                      &Module->BaseDllName, ImportedName);
-            Status = LdrpProcessImportDirectoryEntry(Module, ImportedModule, ImportModuleDirectoryCurrent);
-            if (!NT_SUCCESS(Status))
-            {
-                DPRINT1("failed to import %s\n", ImportedName);
-                break;
-            }
-            ImportModuleDirectoryCurrent++;
-        }
-
-        if (!NT_SUCCESS(Status))
-        {
-            NTSTATUS errorStatus = Status;
-
-            while (ImportModuleDirectoryCurrent >= ImportModuleDirectory)
-            {
-                ImportedName = (PCHAR)Module->DllBase + ImportModuleDirectoryCurrent->Name;
-
-                Status = LdrpGetOrLoadModule(NULL, ImportedName, &ImportedModule, FALSE);
-                if (NT_SUCCESS(Status) && Module != ImportedModule)
-                {
-                    Status = LdrpUnloadModule(ImportedModule, FALSE);
-                    if (!NT_SUCCESS(Status)) DPRINT1("unable to unload %s\n", ImportedName);
-                }
-                ImportModuleDirectoryCurrent--;
-            }
-            return errorStatus;
-        }
-    }
-
-    if (Module->EntryPointActivationContext) RtlDeactivateActivationContext( 0, cookie );
-
-    return STATUS_SUCCESS;
-}
-
-
-/**********************************************************************
- * NAME
- *      LdrPEStartup
- *
- * DESCRIPTION
- *      1. Relocate, if needed the EXE.
- *      2. Fixup any imported symbol.
- *      3. Compute the EXE's entry point.
- *
- * ARGUMENTS
- *      ImageBase
- *              Address at which the EXE's image
- *              is loaded.
- *
- *      SectionHandle
- *              Handle of the section that contains
- *              the EXE's image.
- *
- * RETURN VALUE
- *      NULL on error; otherwise the entry point
- *      to call for initializing the DLL.
- *
- * REVISIONS
- *
- * NOTE
- *      04.01.2004 hb Previous this function was used for all images (dll + exe).
- *                    Currently the function is only used for the exe.
- */
-PEPFUNC LdrPEStartup (PVOID  ImageBase,
-                      HANDLE SectionHandle,
-                      PLDR_DATA_TABLE_ENTRY* Module,
-                      PWSTR FullDosName)
-{
-    NTSTATUS             Status;
-    PEPFUNC              EntryPoint = NULL;
-    PIMAGE_DOS_HEADER    DosHeader;
-    PIMAGE_NT_HEADERS    NTHeaders;
-    PLDR_DATA_TABLE_ENTRY tmpModule;
-    PVOID ActivationContextStack;
-
-    DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
-           ImageBase, SectionHandle);
-
-    /*
-     * Overlay DOS and WNT headers structures
-     * to the DLL's image.
-     */
-    DosHeader = (PIMAGE_DOS_HEADER) ImageBase;
-    NTHeaders = (PIMAGE_NT_HEADERS) ((ULONG_PTR)ImageBase + DosHeader->e_lfanew);
-
-    /*
-     * If the base address is different from the
-     * one the DLL is actually loaded, perform any
-     * relocation.
-     */
-    if (ImageBase != (PVOID)NTHeaders->OptionalHeader.ImageBase)
-    {
-        DPRINT("LDR: Performing relocations\n");
-        Status = LdrPerformRelocations(NTHeaders, ImageBase);
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT1("LdrPerformRelocations() failed\n");
-            return NULL;
-        }
-    }
-
-    if (Module != NULL)
-    {
-        *Module = LdrAddModuleEntry(ImageBase, NTHeaders, FullDosName);
-        (*Module)->SectionPointer = SectionHandle;
-    }
-    else
-    {
-        Module = &tmpModule;
-        Status = LdrFindEntryForAddress(ImageBase, Module);
-        if (!NT_SUCCESS(Status))
-        {
-            return NULL;
-        }
-    }
-
-    if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase)
-    {
-        (*Module)->Flags |= LDRP_IMAGE_NOT_AT_BASE;
-    }
-
-    /* Allocate memory for the ActivationContextStack */
-    /* FIXME: Verify RtlAllocateActivationContextStack behavior */
-    Status = RtlAllocateActivationContextStack(&ActivationContextStack);
-    if (NT_SUCCESS(Status))
-    {
-        DPRINT("ActivationContextStack %x\n",ActivationContextStack);
-        DPRINT("ActiveFrame %x\n", ((PACTIVATION_CONTEXT_STACK)ActivationContextStack)->ActiveFrame);
-        NtCurrentTeb()->ActivationContextStackPointer = ActivationContextStack;
-        NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL;
-    }
-    else
-        DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
-
-    /*
-     * If the DLL's imports symbols from other
-     * modules, fixup the imported calls entry points.
-     */
-    DPRINT("About to fixup imports\n");
-    Status = LdrFixupImports(NULL, *Module);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module)->BaseDllName);
-        return NULL;
-    }
-    DPRINT("Fixup done\n");
-    RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
-    Status = LdrpInitializeTls();
-    if (NT_SUCCESS(Status))
-    {
-        Status = LdrpRunInitializeRoutines(NULL);
-    }
-    if (NT_SUCCESS(Status))
-    {
-        LdrpTlsCallback((*Module)->DllBase, DLL_PROCESS_ATTACH);
-    }
-
-
-    RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
-    if (!NT_SUCCESS(Status))
-    {
-        return NULL;
-    }
-
-    /*
-     * Compute the DLL's entry point's address.
-     */
-    DPRINT("ImageBase = %p\n", ImageBase);
-    DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG)NTHeaders->OptionalHeader.AddressOfEntryPoint);
-    if (NTHeaders->OptionalHeader.AddressOfEntryPoint != 0)
-    {
-        EntryPoint = (PEPFUNC) ((ULONG_PTR)ImageBase
-                                + NTHeaders->OptionalHeader.AddressOfEntryPoint);
-    }
-    DPRINT("LdrPEStartup() = %p\n",EntryPoint);
-    return EntryPoint;
-}
-
-static NTSTATUS
-LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
-               IN ULONG LoadFlags,
-               IN PUNICODE_STRING Name,
-               PLDR_DATA_TABLE_ENTRY *Module,
-               PVOID *BaseAddress OPTIONAL)
-{
-    UNICODE_STRING AdjustedName;
-    UNICODE_STRING FullDosName;
-    NTSTATUS Status;
-    PLDR_DATA_TABLE_ENTRY tmpModule;
-    HANDLE SectionHandle;
-    SIZE_T ViewSize;
-    PVOID ImageBase;
-    PIMAGE_NT_HEADERS NtHeaders;
-    BOOLEAN MappedAsDataFile;
-    PVOID ArbitraryUserPointer;
-
-    if (Module == NULL)
-    {
-        Module = &tmpModule;
-    }
-    /* adjust the full dll name */
-    LdrAdjustDllName(&AdjustedName, Name, FALSE);
-
-    DPRINT("%wZ\n", &AdjustedName);
-
-    MappedAsDataFile = FALSE;
-    /* Test if dll is already loaded */
-    Status = LdrFindEntryForName(&AdjustedName, Module, TRUE);
-    if (NT_SUCCESS(Status))
-    {
-        RtlFreeUnicodeString(&AdjustedName);
-        if (NULL != BaseAddress)
-        {
-            *BaseAddress = (*Module)->DllBase;
-        }
-    }
-    else
-    {
-        /* Open or create dll image section */
-        Status = LdrpMapKnownDll(&AdjustedName, &FullDosName, &SectionHandle);
-        if (!NT_SUCCESS(Status))
-        {
-            MappedAsDataFile = (0 != (LoadFlags & LOAD_LIBRARY_AS_DATAFILE));
-            Status = LdrpMapDllImageFile(SearchPath, &AdjustedName, &FullDosName,
-                                         MappedAsDataFile, &SectionHandle);
-        }
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n",
-                    &AdjustedName, Status);
-            RtlFreeUnicodeString(&AdjustedName);
-            return Status;
-        }
-        RtlFreeUnicodeString(&AdjustedName);
-        /* Map the dll into the process */
-        ViewSize = 0;
-        ImageBase = 0;
-        ArbitraryUserPointer = NtCurrentTeb()->NtTib.ArbitraryUserPointer;
-        NtCurrentTeb()->NtTib.ArbitraryUserPointer = FullDosName.Buffer;
-        Status = NtMapViewOfSection(SectionHandle,
-                                    NtCurrentProcess(),
-                                    &ImageBase,
-                                    0,
-                                    0,
-                                    NULL,
-                                    &ViewSize,
-                                    ViewShare,
-                                    0,
-                                    PAGE_READONLY);
-        NtCurrentTeb()->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT1("map view of section failed (Status 0x%08lx)\n", Status);
-            RtlFreeUnicodeString(&FullDosName);
-            NtClose(SectionHandle);
-            return(Status);
-        }
-        if (NULL != BaseAddress)
-        {
-            *BaseAddress = ImageBase;
-        }
-        if (!MappedAsDataFile)
-        {
-            /* Get and check the NT headers */
-            NtHeaders = RtlImageNtHeader(ImageBase);
-            if (NtHeaders == NULL)
-            {
-                DPRINT1("RtlImageNtHeaders() failed\n");
-                NtUnmapViewOfSection (NtCurrentProcess (), ImageBase);
-                NtClose (SectionHandle);
-                RtlFreeUnicodeString(&FullDosName);
-                return STATUS_UNSUCCESSFUL;
-            }
-        }
-        DPRINT("Mapped %wZ at %x\n", &FullDosName, ImageBase);
-        if (MappedAsDataFile)
-        {
-            ASSERT(NULL != BaseAddress);
-            if (NULL != BaseAddress)
-            {
-                *BaseAddress = (PVOID) ((char *) *BaseAddress + 1);
-            }
-            *Module = NULL;
-            RtlFreeUnicodeString(&FullDosName);
-            NtClose(SectionHandle);
-            return STATUS_SUCCESS;
-        }
-        /* If the base address is different from the
-         * one the DLL is actually loaded, perform any
-         * relocation. */
-        if (ImageBase != (PVOID) NtHeaders->OptionalHeader.ImageBase)
-        {
-            DPRINT1("Relocating (%lx -> %p) %wZ\n",
-                    NtHeaders->OptionalHeader.ImageBase, ImageBase, &FullDosName);
-            Status = LdrPerformRelocations(NtHeaders, ImageBase);
-            if (!NT_SUCCESS(Status))
-            {
-                DPRINT1("LdrPerformRelocations() failed\n");
-                NtUnmapViewOfSection (NtCurrentProcess (), ImageBase);
-                NtClose (SectionHandle);
-                RtlFreeUnicodeString(&FullDosName);
-                return STATUS_UNSUCCESSFUL;
-            }
-        }
-        *Module = LdrAddModuleEntry(ImageBase, NtHeaders, FullDosName.Buffer);
-        (*Module)->SectionPointer = SectionHandle;
-        if (ImageBase != (PVOID) NtHeaders->OptionalHeader.ImageBase)
-        {
-            (*Module)->Flags |= LDRP_IMAGE_NOT_AT_BASE;
-        }
-        if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
-        {
-            (*Module)->Flags |= LDRP_IMAGE_DLL;
-        }
-        /* fixup the imported calls entry points */
-        Status = LdrFixupImports(SearchPath, *Module);
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module)->BaseDllName, Status);
-            NtUnmapViewOfSection (NtCurrentProcess (), ImageBase);
-            NtClose (SectionHandle);
-            RtlFreeUnicodeString (&FullDosName);
-            RtlFreeUnicodeString (&(*Module)->FullDllName);
-            RtlFreeUnicodeString (&(*Module)->BaseDllName);
-            RemoveEntryList (&(*Module)->InLoadOrderLinks);
-            return Status;
-        }
-
-        RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
-        InsertTailList(&NtCurrentPeb()->Ldr->InInitializationOrderModuleList,
-                       &(*Module)->InInitializationOrderModuleList);
-        RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
-    }
-    return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module,
-                 BOOLEAN Unload)
-{
-    PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
-    PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor;
-    PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent;
-    PCHAR ImportedName;
-    PLDR_DATA_TABLE_ENTRY ImportedModule;
-    NTSTATUS Status = 0;
-    LONG LoadCount;
-    ULONG Size;
-
-    if (Unload)
-    {
-        RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
-    }
-
-    LoadCount = LdrpDecrementLoadCount(Module, Unload);
-
-    TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module->BaseDllName, LoadCount);
-
-    if (LoadCount == 0)
-    {
-        /* ?????????????????? */
-    }
-    else if (!(Module->Flags & LDRP_STATIC_LINK) && LoadCount == 1)
-    {
-        BoundImportDescriptor = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)
-                                RtlImageDirectoryEntryToData(Module->DllBase,
-                                        TRUE,
-                                        IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
-                                        &Size);
-        if (BoundImportDescriptor)
-        {
-            /* dereferencing all imported modules, use the bound import descriptor */
-            BoundImportDescriptorCurrent = BoundImportDescriptor;
-            while (BoundImportDescriptorCurrent->OffsetModuleName)
-            {
-                ImportedName = (PCHAR)BoundImportDescriptor + BoundImportDescriptorCurrent->OffsetModuleName;
-                TRACE_LDR("%wZ trys to unload %s\n", &Module->BaseDllName, ImportedName);
-                Status = LdrpGetOrLoadModule(NULL, ImportedName, &ImportedModule, FALSE);
-                if (!NT_SUCCESS(Status))
-                {
-                    DPRINT1("unable to found imported modul %s\n", ImportedName);
-                }
-                else
-                {
-                    if (Module != ImportedModule)
-                    {
-                        Status = LdrpUnloadModule(ImportedModule, FALSE);
-                        if (!NT_SUCCESS(Status))
-                        {
-                            DPRINT1("unable to unload %s\n", ImportedName);
-                        }
-                    }
-                }
-                BoundImportDescriptorCurrent++;
-            }
-        }
-        else
-        {
-            ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
-                                    RtlImageDirectoryEntryToData(Module->DllBase,
-                                            TRUE,
-                                            IMAGE_DIRECTORY_ENTRY_IMPORT,
-                                            &Size);
-            if (ImportModuleDirectory)
-            {
-                /* dereferencing all imported modules, use the import descriptor */
-                while (ImportModuleDirectory->Name)
-                {
-                    ImportedName = (PCHAR)Module->DllBase + ImportModuleDirectory->Name;
-                    TRACE_LDR("%wZ trys to unload %s\n", &Module->BaseDllName, ImportedName);
-                    Status = LdrpGetOrLoadModule(NULL, ImportedName, &ImportedModule, FALSE);
-                    if (!NT_SUCCESS(Status))
-                    {
-                        DPRINT1("unable to found imported modul %s\n", ImportedName);
-                    }
-                    else
-                    {
-                        if (Module != ImportedModule)
-                        {
-                            Status = LdrpUnloadModule(ImportedModule, FALSE);
-                            if (!NT_SUCCESS(Status))
-                            {
-                                DPRINT1("unable to unload %s\n", ImportedName);
-                            }
-                        }
-                    }
-                    ImportModuleDirectory++;
-                }
-            }
-        }
-    }
-
-    if (Unload)
-    {
-        if (!(Module->Flags & LDRP_STATIC_LINK))
-        {
-            LdrpDetachProcess(FALSE);
-        }
-
-        RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
-    }
-    return STATUS_SUCCESS;
-
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrUnloadDll (IN PVOID BaseAddress)
-{
-    PLDR_DATA_TABLE_ENTRY Module;
-    NTSTATUS Status;
-
-    if (BaseAddress == NULL)
-        return STATUS_SUCCESS;
-
-    if (LdrMappedAsDataFile(&BaseAddress))
-    {
-        Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
-    }
-    else
-    {
-        Status = LdrFindEntryForAddress(BaseAddress, &Module);
-        if (NT_SUCCESS(Status))
-        {
-            TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module->BaseDllName);
-            Status = LdrpUnloadModule(Module, TRUE);
-        }
-    }
-
-    return Status;
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress)
-{
-    PLIST_ENTRY ModuleListHead;
-    PLIST_ENTRY Entry;
-    PLDR_DATA_TABLE_ENTRY Module;
-    NTSTATUS Status;
-
-    DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress);
-
-    Status = STATUS_DLL_NOT_FOUND;
-    RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
-    ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
-    Entry = ModuleListHead->Flink;
-    while (Entry != ModuleListHead)
-    {
-        Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-
-        DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module->BaseDllName, Module->DllBase);
-
-        if (Module->DllBase == BaseAddress)
-        {
-            if (Module->TlsIndex == 0xFFFF)
-            {
-                Module->Flags |= LDRP_DONT_CALL_FOR_THREADS;
-                Status = STATUS_SUCCESS;
-            }
-            break;
-        }
-        Entry = Entry->Flink;
-    }
-    RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
-    return Status;
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrGetDllHandle(IN PWSTR DllPath OPTIONAL,
-                IN PULONG DllCharacteristics,
-                IN PUNICODE_STRING DllName,
-                OUT PVOID *DllHandle)
-{
-    PLDR_DATA_TABLE_ENTRY Module;
-    NTSTATUS Status;
-
-    TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
-              DllName, DllPath ? DllPath : L"");
-
-    /* NULL is the current executable */
-    if (DllName == NULL)
-    {
-        *DllHandle = LdrpImageEntry->DllBase;
-        DPRINT("BaseAddress 0x%lx\n", *DllHandle);
-        return STATUS_SUCCESS;
-    }
-
-    Status = LdrFindEntryForName(DllName, &Module, FALSE);
-    if (NT_SUCCESS(Status))
-    {
-        *DllHandle = Module->DllBase;
-        return STATUS_SUCCESS;
-    }
-
-    DPRINT("Failed to find dll %wZ\n", DllName);
-    *DllHandle = NULL;
-    return STATUS_DLL_NOT_FOUND;
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrAddRefDll(IN ULONG Flags,
-             IN PVOID BaseAddress)
-{
-    PLIST_ENTRY ModuleListHead;
-    PLIST_ENTRY Entry;
-    PLDR_DATA_TABLE_ENTRY Module;
-    NTSTATUS Status;
-
-    if (Flags & ~(LDR_PIN_MODULE))
-    {
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    Status = STATUS_DLL_NOT_FOUND;
-    RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
-    ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
-    Entry = ModuleListHead->Flink;
-    while (Entry != ModuleListHead)
-    {
-        Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-
-        if (Module->DllBase == BaseAddress)
-        {
-            if (Flags & LDR_PIN_MODULE)
-            {
-                Module->Flags |= LDRP_STATIC_LINK;
-            }
-            else
-            {
-                LdrpIncrementLoadCount(Module,
-                                       FALSE);
-            }
-            Status = STATUS_SUCCESS;
-            break;
-        }
-        Entry = Entry->Flink;
-    }
-    RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
-    return Status;
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrGetProcedureAddress (IN PVOID BaseAddress,
-                        IN PANSI_STRING Name,
-                        IN ULONG Ordinal,
-                        OUT PVOID *ProcedureAddress)
-{
-    NTSTATUS Status = STATUS_PROCEDURE_NOT_FOUND;
-    if (Name && Name->Length)
-    {
-        TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name);
-    }
-    else
-    {
-        TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal);
-    }
-
-    DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
-           BaseAddress, Name, Ordinal, ProcedureAddress);
-
-    _SEH2_TRY
-    {
-        if (Name && Name->Length)
-        {
-            /* by name */
-            *ProcedureAddress = LdrGetExportByName(BaseAddress, (PUCHAR)Name->Buffer, 0xffff);
-            if (*ProcedureAddress != NULL)
-            {
-                Status = STATUS_SUCCESS;
-            }
-            DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
-        }
-        else
-        {
-            /* by ordinal */
-            Ordinal &= 0x0000FFFF;
-            *ProcedureAddress = LdrGetExportByOrdinal(BaseAddress, (WORD)Ordinal);
-            if (*ProcedureAddress)
-            {
-                Status = STATUS_SUCCESS;
-            }
-            DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal);
-        }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        Status = STATUS_DLL_NOT_FOUND;
-    }
-    _SEH2_END;
-
-    return Status;
-}
-
-/**********************************************************************
- * NAME                                                         LOCAL
- *      LdrpDetachProcess
- *
- * DESCRIPTION
- *      Unload dll's which are no longer referenced from others dll's
- *
- * ARGUMENTS
- *      none
- *
- * RETURN VALUE
- *      none
- *
- * REVISIONS
- *
- * NOTE
- *      The loader lock must be held on enty.
- */
-static VOID
-LdrpDetachProcess(BOOLEAN UnloadAll)
-{
-    PLIST_ENTRY ModuleListHead;
-    PLIST_ENTRY Entry;
-    PLDR_DATA_TABLE_ENTRY Module;
-    static ULONG CallingCount = 0;
-
-    DPRINT("LdrpDetachProcess() called for %wZ\n",
-           &LdrpImageEntry->BaseDllName);
-
-    if (UnloadAll)
-        LdrpDllShutdownInProgress = TRUE;
-
-    CallingCount++;
-
-    ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
-    Entry = ModuleListHead->Blink;
-    while (Entry != ModuleListHead)
-    {
-        Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
-        if (((UnloadAll && Module->LoadCount == LDRP_PROCESS_CREATION_TIME) || Module->LoadCount == 0) &&
-                Module->Flags & LDRP_ENTRY_PROCESSED &&
-                !(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
-        {
-            Module->Flags |= LDRP_UNLOAD_IN_PROGRESS;
-            if (Module == LdrpLastModule)
-            {
-                LdrpLastModule = NULL;
-            }
-            if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED)
-            {
-                TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
-                          &Module->BaseDllName, Module->EntryPoint);
-
-                /* Check if it has TLS */
-                if (Module->TlsIndex)
-                {
-                    /* Call TLS */
-                    LdrpTlsCallback(Module->DllBase, DLL_PROCESS_ATTACH);
-                }
-
-               if ((Module->Flags & LDRP_IMAGE_DLL) && Module->EntryPoint)
-               {
-                    LdrpCallDllEntry(Module->EntryPoint,
-                                     Module->DllBase,
-                                     DLL_PROCESS_DETACH,
-                                     (PVOID)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
-               }
-            }
-            else
-            {
-                TRACE_LDR("Unload %wZ\n", &Module->BaseDllName);
-            }
-            Entry = ModuleListHead->Blink;
-        }
-        else
-        {
-            Entry = Entry->Blink;
-        }
-    }
-
-    if (CallingCount == 1)
-    {
-        Entry = ModuleListHead->Blink;
-        while (Entry != ModuleListHead)
-        {
-            Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
-            Entry = Entry->Blink;
-            if (Module->Flags & LDRP_UNLOAD_IN_PROGRESS &&
-                    ((UnloadAll && Module->LoadCount != LDRP_PROCESS_CREATION_TIME) || Module->LoadCount == 0))
-            {
-                /* remove the module entry from the list */
-                RemoveEntryList (&Module->InLoadOrderLinks);
-                RemoveEntryList (&Module->InInitializationOrderModuleList);
-
-                NtUnmapViewOfSection (NtCurrentProcess (), Module->DllBase);
-                NtClose (Module->SectionPointer);
-
-                TRACE_LDR("%wZ unloaded\n", &Module->BaseDllName);
-
-                RtlFreeUnicodeString (&Module->FullDllName);
-                RtlFreeUnicodeString (&Module->BaseDllName);
-
-                RtlFreeHeap (RtlGetProcessHeap (), 0, Module);
-            }
-        }
-    }
-    CallingCount--;
-    DPRINT("LdrpDetachProcess() done\n");
-}
-
-/*
- * @implemented
- */
-BOOLEAN NTAPI
-RtlDllShutdownInProgress (VOID)
-{
-    return LdrpDllShutdownInProgress;
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrShutdownProcess (VOID)
-{
-    LdrpDetachProcess(TRUE);
-    return STATUS_SUCCESS;
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-LdrpInitializeThread(IN PCONTEXT Context)
-{
-    PLIST_ENTRY ModuleListHead;
-    PLIST_ENTRY Entry;
-    PLDR_DATA_TABLE_ENTRY Module;
-    NTSTATUS Status;
-
-    DPRINT("LdrpAttachThread() called for %wZ\n",
-           &LdrpImageEntry->BaseDllName);
-
-    RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
-
-    Status = LdrpAllocateTls();
-
-    if (NT_SUCCESS(Status))
-    {
-        ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
-        Entry = ModuleListHead->Flink;
-
-        while (Entry != ModuleListHead)
-        {
-            Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
-            if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED &&
-                    !(Module->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
-                    !(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
-            {
-                TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
-                          &Module->BaseDllName, Module->EntryPoint);
-
-                /* Check if it has TLS */
-                if (Module->TlsIndex)
-                {
-                    /* Call TLS */
-                    LdrpTlsCallback(Module->DllBase, DLL_THREAD_ATTACH);
-                }
-
-               if ((Module->Flags & LDRP_IMAGE_DLL) && Module->EntryPoint)
-                   LdrpCallDllEntry(Module->EntryPoint, Module->DllBase, DLL_THREAD_ATTACH, NULL);
-            }
-            Entry = Entry->Flink;
-        }
-
-        Entry = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;
-        Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-        LdrpTlsCallback(Module->DllBase, DLL_THREAD_ATTACH);
-    }
-
-    RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
-
-    DPRINT("LdrpAttachThread() done\n");
-
-    return Status;
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrShutdownThread (VOID)
-{
-    PLIST_ENTRY ModuleListHead;
-    PLIST_ENTRY Entry;
-    PLDR_DATA_TABLE_ENTRY Module;
-
-    DPRINT("LdrShutdownThread() called for %wZ\n",
-           &LdrpImageEntry->BaseDllName);
-
-    RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
-
-    ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
-    Entry = ModuleListHead->Blink;
-    while (Entry != ModuleListHead)
-    {
-        Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
-
-        if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED &&
-                !(Module->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
-                !(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
-        {
-            TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
-                      &Module->BaseDllName, Module->EntryPoint);
-            /* Check if it has TLS */
-            if (Module->TlsIndex)
-            {
-                /* Call TLS */
-                LdrpTlsCallback(Module->DllBase, DLL_THREAD_DETACH);
-            }
-
-            if ((Module->Flags & LDRP_IMAGE_DLL) && Module->EntryPoint)
-                LdrpCallDllEntry(Module->EntryPoint, Module->DllBase, DLL_THREAD_DETACH, NULL);
-        }
-        Entry = Entry->Blink;
-    }
-
-    /* Free TLS */
-    LdrpFreeTls();
-    RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
-
-    DPRINT("LdrShutdownThread() done\n");
-
-    return STATUS_SUCCESS;
-}
-
-/*
- * Compute size of an image as it is actually present in virt memory
- * (i.e. excluding NEVER_LOAD sections)
- */
-ULONG
-LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders)
-{
-    PIMAGE_SECTION_HEADER SectionHeader;
-    unsigned SectionIndex;
-    ULONG ResidentSize;
+    DPRINT1("\n");
 
     SectionHeader = (PIMAGE_SECTION_HEADER)((char *) &NTHeaders->OptionalHeader
                                             + NTHeaders->FileHeader.SizeOfOptionalHeader);
@@ -2807,6 +760,7 @@ LdrProcessRelocationBlock(
     IN PUSHORT TypeOffset,
     IN LONG_PTR Delta)
 {
+    DPRINT1("\n");
     return LdrProcessRelocationBlockLongLong(Address, Count, TypeOffset, Delta);
 }
 
@@ -2814,6 +768,7 @@ BOOLEAN
 NTAPI
 LdrUnloadAlternateResourceModule(IN PVOID BaseAddress)
 {
-    UNIMPLEMENTED;
+    //FIXME: We don't implement alternate resources anyway, don't spam the log
+    //UNIMPLEMENTED;
     return FALSE;
 }
index b383f1d..b2874cf 100644 (file)
@@ -443,20 +443,11 @@ LoadLibraryExW(LPCWSTR lpLibFileName,
             }
         }
 
-        /* HACK!!! FIXME */
-        if (InWindows)
-        {
-            /* Call the API Properly */
-            Status = LdrLoadDll(SearchPath,
-                                &DllCharacteristics,
-                                &DllName,
-                                (PVOID*)&hInst);
-        }
-        else
-        {
-            /* Call the ROS API. NOTE: Don't fix this, I have a patch to merge later. */
-            Status = LdrLoadDll(SearchPath, &dwFlags, &DllName, (PVOID*)&hInst);
-        }
+        /* Call the API Properly */
+        Status = LdrLoadDll(SearchPath,
+                            &DllCharacteristics,
+                            &DllName,
+                            (PVOID*)&hInst);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
index 2abea6e..71a5459 100644 (file)
@@ -2736,6 +2736,10 @@ NTAPI
 RtlAllocateActivationContextStack(IN PVOID *Context)
 {
     PACTIVATION_CONTEXT_STACK ContextStack;
+
+    /* FIXME: Check if it's already allocated */
+    //if (*Context) return STATUS_SUCCESS;
+
     ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (ACTIVATION_CONTEXT_STACK) );
     if (!ContextStack)
     {
@@ -2798,7 +2802,16 @@ RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTE
     /* Return pointer to the activation frame */
     return &Frame->Frame;
 #else
-    return NULL;
+
+    RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame = &Frame->Frame;
+
+    frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
+    frame->ActivationContext = Context;
+    frame->Flags = 0;
+
+    NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame;
+
+    return STATUS_SUCCESS;
 #endif
 }
 
@@ -2806,7 +2819,6 @@ PRTL_ACTIVATION_CONTEXT_STACK_FRAME
 FASTCALL
 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
 {
-#if NEW_NTDLL_LOADER
     RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
 
     /* find the right frame */
@@ -2820,9 +2832,6 @@ RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CON
     NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
 
     return frame;
-#else
-    return NULL;
-#endif
 }