[AVIFIL32]
[reactos.git] / reactos / dll / ntdll / ldr / ldrinit.c
index a7a196f..8aa9e74 100644 (file)
 /* INCLUDES *****************************************************************/
 
 #include <ntdll.h>
+#include <callback.h>
+
 #define NDEBUG
 #include <debug.h>
 
+
 /* GLOBALS *******************************************************************/
 
-HKEY ImageExecOptionsKey;
-HKEY Wow64ExecOptionsKey;
+HANDLE ImageExecOptionsKey;
+HANDLE Wow64ExecOptionsKey;
 UNICODE_STRING ImageExecOptionsString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options");
 UNICODE_STRING Wow64OptionsString = RTL_CONSTANT_STRING(L"");
 UNICODE_STRING NtDllString = RTL_CONSTANT_STRING(L"ntdll.dll");
@@ -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;
@@ -42,7 +48,7 @@ LIST_ENTRY LdrpTlsList;
 ULONG LdrpNumberOfTlsEntries;
 ULONG LdrpNumberOfProcessors;
 PVOID NtDllBase;
-LARGE_INTEGER RtlpTimeout;
+extern LARGE_INTEGER RtlpTimeout;
 BOOLEAN RtlpTimeoutDisable;
 LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
 LIST_ENTRY LdrpDllNotificationList;
@@ -68,20 +74,26 @@ RTL_CRITICAL_SECTION FastPebLock;
 BOOLEAN ShowSnaps;
 
 ULONG LdrpFatalHardErrorCount;
+ULONG LdrpActiveUnloadCount;
 
 //extern LIST_ENTRY RtlCriticalSectionList;
 
 VOID RtlpInitializeVectoredExceptionHandling(VOID);
 VOID NTAPI RtlpInitDeferedCriticalSection(VOID);
-VOID RtlInitializeHeapManager(VOID);
+VOID NTAPI RtlInitializeHeapManager(VOID);
 extern BOOLEAN RtlpPageHeapEnabled;
-extern ULONG RtlpDphGlobalFlags;
+
+ULONG RtlpDisableHeapLookaside; // TODO: Move to heap.c
+ULONG RtlpShutdownProcessFlags; // TODO: Use it
 
 NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase);
-NTSTATUS NTAPI
-LdrpInitializeProcess_(PCONTEXT Context,
-                      PVOID SystemArgument1);
+void actctx_init(void);
 
+#ifdef _WIN64
+#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
+#else
+#define DEFAULT_SECURITY_COOKIE 0xBB40E64E
+#endif
 
 /* FUNCTIONS *****************************************************************/
 
@@ -92,9 +104,9 @@ NTSTATUS
 NTAPI
 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey,
                            IN BOOLEAN Wow64,
-                           OUT PHKEY NewKeyHandle)
+                           OUT PHANDLE NewKeyHandle)
 {
-    PHKEY RootKeyLocation;
+    PHANDLE RootKeyLocation;
     HANDLE RootKey;
     UNICODE_STRING SubKeyString;
     OBJECT_ATTRIBUTES ObjectAttributes;
@@ -112,7 +124,7 @@ LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey,
 
     /* Setup the object attributes */
     InitializeObjectAttributes(&ObjectAttributes,
-                               Wow64 ? 
+                               Wow64 ?
                                &Wow64OptionsString : &ImageExecOptionsString,
                                OBJ_CASE_INSENSITIVE,
                                NULL,
@@ -133,14 +145,14 @@ LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey,
         /* Extract the name */
         SubKeyString = *SubKey;
         p1 = (PWCHAR)((ULONG_PTR)SubKeyString.Buffer + SubKeyString.Length);
-        while (SubKey->Length)
+        while (SubKeyString.Length)
         {
             if (p1[-1] == L'\\') break;
             p1--;
             SubKeyString.Length -= sizeof(*p1);
         }
         SubKeyString.Buffer = p1;
-        SubKeyString.Length = SubKeyString.MaximumLength - SubKeyString.Length - sizeof(WCHAR);
+        SubKeyString.Length = SubKey->Length - SubKeyString.Length;
 
         /* Setup the object attributes */
         InitializeObjectAttributes(&ObjectAttributes,
@@ -162,7 +174,7 @@ LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey,
  */
 NTSTATUS
 NTAPI
-LdrQueryImageFileKeyOption(IN HKEY KeyHandle,
+LdrQueryImageFileKeyOption(IN HANDLE KeyHandle,
                            IN PCWSTR ValueName,
                            IN ULONG Type,
                            OUT PVOID Buffer,
@@ -181,7 +193,7 @@ LdrQueryImageFileKeyOption(IN HKEY KeyHandle,
     if (!NT_SUCCESS(Status)) return Status;
 
     /* Query the value */
-    Status = NtQueryValueKey(KeyHandle,
+    Status = ZwQueryValueKey(KeyHandle,
                              &ValueNameString,
                              KeyValuePartialInformation,
                              KeyValueInformation,
@@ -195,20 +207,22 @@ LdrQueryImageFileKeyOption(IN HKEY KeyHandle,
         KeyValueInformation = RtlAllocateHeap(RtlGetProcessHeap(),
                                               0,
                                               KeyInfoSize);
-        if (KeyInfo == NULL)
+        if (KeyValueInformation != NULL)
+        {
+            /* Try again */
+            Status = ZwQueryValueKey(KeyHandle,
+                                     &ValueNameString,
+                                     KeyValuePartialInformation,
+                                     KeyValueInformation,
+                                     KeyInfoSize,
+                                     &ResultSize);
+            FreeHeap = TRUE;
+        }
+        else
         {
             /* Give up this time */
             Status = STATUS_NO_MEMORY;
         }
-
-        /* Try again */
-        Status = NtQueryValueKey(KeyHandle,
-                                 &ValueNameString,
-                                 KeyValuePartialInformation,
-                                 KeyValueInformation,
-                                 KeyInfoSize,
-                                 &ResultSize);
-        FreeHeap = TRUE;
     }
 
     /* Check for success */
@@ -283,9 +297,9 @@ LdrQueryImageFileKeyOption(IN HKEY KeyHandle,
                 {
                     /* OK, we know what you want... */
                     IntegerString.Buffer = (PWSTR)KeyValueInformation->Data;
-                    IntegerString.Length = KeyValueInformation->DataLength -
+                    IntegerString.Length = (USHORT)KeyValueInformation->DataLength -
                                            sizeof(WCHAR);
-                    IntegerString.MaximumLength = KeyValueInformation->DataLength;
+                    IntegerString.MaximumLength = (USHORT)KeyValueInformation->DataLength;
                     Status = RtlUnicodeStringToInteger(&IntegerString, 0, (PULONG)Buffer);
                 }
             }
@@ -315,8 +329,7 @@ LdrQueryImageFileKeyOption(IN HKEY KeyHandle,
     /* Check if buffer was in heap */
     if (FreeHeap) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation);
 
-    /* Close key and return */
-    NtClose(KeyHandle);
+    /* Return status */
     return Status;
 }
 
@@ -334,7 +347,7 @@ LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey,
                                     IN BOOLEAN Wow64)
 {
     NTSTATUS Status;
-    HKEY KeyHandle;
+    HANDLE KeyHandle;
 
     /* Open a handle to the key */
     Status = LdrOpenImageFileOptionsKey(SubKey, Wow64, &KeyHandle);
@@ -414,8 +427,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 +441,173 @@ PVOID
 NTAPI
 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry)
 {
-    PVOID Cookie;
+    PULONG_PTR Cookie;
+    LARGE_INTEGER Counter;
+    ULONG_PTR 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))
+        {
+            /* Make up a cookie from a bunch of values which may uniquely represent
+               current moment of time, environment, etc */
+            NtQueryPerformanceCounter(&Counter, NULL);
+
+            NewCookie = Counter.LowPart ^ Counter.HighPart;
+            NewCookie ^= (ULONG)NtCurrentTeb()->ClientId.UniqueProcess;
+            NewCookie ^= (ULONG)NtCurrentTeb()->ClientId.UniqueThread;
+
+            /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */
+            while (SharedUserData->SystemTime.High1Time != SharedUserData->SystemTime.High2Time)
+            {
+                YieldProcessor();
+            };
+
+            /* Calculate the milliseconds value and xor it to the cookie */
+            NewCookie ^= Int64ShrlMod32(UInt32x32To64(SharedUserData->TickCountMultiplier, SharedUserData->TickCount.LowPart), 24) +
+                (SharedUserData->TickCountMultiplier * (SharedUserData->TickCount.High1Time << 8));
+
+            /* Make the cookie 16bit if necessary */
+            if (*Cookie == 0xBB40) NewCookie &= 0xFFFF;
+
+            /* If the result is 0 or the same as we got, just subtract one from the existing value
+               and that's it */
+            if ((NewCookie == 0) || (NewCookie == *Cookie))
+            {
+                NewCookie = *Cookie - 1;
+            }
+
+            /* Set the new cookie value */
+            *Cookie = NewCookie;
+        }
     }
 
     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 (%p/%p)\n",
+            &LdrpImageEntry->BaseDllName,
+            NtCurrentTeb()->RealClientId.UniqueProcess,
+            NtCurrentTeb()->RealClientId.UniqueThread);
+
+    /* Allocate an Activation Context Stack */
+    DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer);
+    Status = RtlAllocateActivationContextStack(&NtCurrentTeb()->ActivationContextStackPointer);
+    if (!NT_SUCCESS(Status))
+    {
+        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 */
+                            LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_THREAD_ATTACH);
+                        }
+                    }
+
+                    /* Make sure we're not shutting down */
+                    if (!LdrpShutdownInProgress)
+                    {
+                        /* Call the Entrypoint */
+                        DPRINT("%wZ - Calling entry point at %p for thread attaching, %p/%p\n",
+                                &LdrEntry->BaseDllName, LdrEntry->EntryPoint,
+                                NtCurrentTeb()->RealClientId.UniqueProcess,
+                                NtCurrentTeb()->RealClientId.UniqueThread);
+                        LdrpCallInitRoutine(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 */
+        LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_THREAD_ATTACH);
+
+        /* Deactivate the ActCtx */
+        RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+    }
+
+    DPRINT("LdrpInitializeThread() done\n");
+}
+
 NTSTATUS
 NTAPI
 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
@@ -461,7 +626,10 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
     PTEB OldTldTeb;
     BOOLEAN DllStatus;
 
-    DPRINT("LdrpRunInitializeRoutines() called for %wZ\n", &LdrpImageEntry->BaseDllName);
+    DPRINT("LdrpRunInitializeRoutines() called for %wZ (%p/%p)\n",
+        &LdrpImageEntry->BaseDllName,
+        NtCurrentTeb()->RealClientId.UniqueProcess,
+        NtCurrentTeb()->RealClientId.UniqueThread);
 
     /* Check the Loader Lock */
     LdrpEnsureLoaderLockIsHeld();
@@ -475,7 +643,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
             /* Allocate space for all the entries */
             LdrRootEntry = RtlAllocateHeap(RtlGetProcessHeap(),
                                            0,
-                                           Count * sizeof(LdrRootEntry));
+                                           Count * sizeof(*LdrRootEntry));
             if (!LdrRootEntry) return STATUS_NO_MEMORY;
         }
         else
@@ -493,7 +661,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
     /* Show debug message */
     if (ShowSnaps)
     {
-        DPRINT1("[%x,%x] LDR: Real INIT LIST for Process %wZ\n",
+        DPRINT1("[%p,%p] LDR: Real INIT LIST for Process %wZ\n",
                 NtCurrentTeb()->RealClientId.UniqueThread,
                 NtCurrentTeb()->RealClientId.UniqueProcess,
                 &Peb->ProcessParameters->ImagePathName);
@@ -521,12 +689,13 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
                 if (LdrEntry->EntryPoint)
                 {
                     /* Write in array */
+                    ASSERT(i < Count);
                     LdrRootEntry[i] = LdrEntry;
 
                     /* Display debug message */
                     if (ShowSnaps)
                     {
-                        DPRINT1("[%x,%x] LDR: %wZ init routine %p\n",
+                        DPRINT1("[%p,%p] LDR: %wZ init routine %p\n",
                                 NtCurrentTeb()->RealClientId.UniqueThread,
                                 NtCurrentTeb()->RealClientId.UniqueProcess,
                                 &LdrEntry->FullDllName,
@@ -554,7 +723,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
 
         /* Clear it */
         //Kernel32ProcessInitPostImportfunction = NULL;
-        UNIMPLEMENTED;
+        //UNIMPLEMENTED;
     }
 
     /* No root entry? return */
@@ -591,6 +760,9 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
                                                        sizeof(ULONG),
                                                        NULL);
             if (!NT_SUCCESS(Status)) BreakOnDllLoad = 0;
+
+            /* Reset status back to STATUS_SUCCESS */
+            Status = STATUS_SUCCESS;
         }
 
         /* Break if aksed */
@@ -627,7 +799,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
             if (LdrEntry->TlsIndex && Context)
             {
                 /* Call TLS */
-                LdrpTlsCallback(LdrEntry->DllBase, DLL_PROCESS_ATTACH);
+                LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_PROCESS_ATTACH);
             }
 
             /* Call the Entrypoint */
@@ -636,7 +808,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
                 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n",
                         &LdrEntry->BaseDllName, EntryPoint);
             }
-            DllStatus = LdrpCallDllEntry(EntryPoint,
+            DllStatus = LdrpCallInitRoutine(EntryPoint,
                                          LdrEntry->DllBase,
                                          DLL_PROCESS_ATTACH,
                                          Context);
@@ -690,7 +862,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
                                                LdrpImageEntry->EntryPointActivationContext);
 
         /* Do TLS callbacks */
-        LdrpTlsCallback(Peb->ImageBaseAddress, DLL_PROCESS_ATTACH);
+        LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_PROCESS_ATTACH);
 
         /* Deactivate the ActCtx */
         RtlDeactivateActivationContextUnsafeFast(&ActCtx);
@@ -712,6 +884,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 */
+                    LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_PROCESS_DETACH);
+                }
+
+                /* Call the Entrypoint */
+                DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
+                        &LdrEntry->BaseDllName, LdrEntry->EntryPoint);
+                LdrpCallInitRoutine(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 */
+        LdrpCallTlsInitializers(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 */
+                            LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_THREAD_DETACH);
+                        }
+                    }
+
+                    /* Make sure we're not shutting down */
+                    if (!LdrpShutdownInProgress)
+                    {
+                        /* Call the Entrypoint */
+                        DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
+                                &LdrEntry->BaseDllName, LdrEntry->EntryPoint);
+                        LdrpCallInitRoutine(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 */
+        LdrpCallTlsInitializers(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)
@@ -782,7 +1215,7 @@ LdrpAllocateTls(VOID)
     PTEB Teb = NtCurrentTeb();
     PLIST_ENTRY NextEntry, ListHead;
     PLDRP_TLS_DATA TlsData;
-    ULONG TlsDataSize;
+    SIZE_T TlsDataSize;
     PVOID *TlsVector;
 
     /* Check if we have any entries */
@@ -806,7 +1239,7 @@ LdrpAllocateTls(VOID)
         NextEntry = NextEntry->Flink;
 
         /* Allocate this vector */
-        TlsDataSize = TlsData->TlsDirectory.EndAddressOfRawData - 
+        TlsDataSize = TlsData->TlsDirectory.EndAddressOfRawData -
                       TlsData->TlsDirectory.StartAddressOfRawData;
         TlsVector[TlsData->TlsDirectory.Characteristics] = RtlAllocateHeap(RtlGetProcessHeap(),
                                                                            0,
@@ -820,7 +1253,7 @@ LdrpAllocateTls(VOID)
         /* Show debug message */
         if (ShowSnaps)
         {
-            DPRINT1("LDR: TlsVector %x Index %d = %x copied from %x to %x\n",
+            DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n",
                     TlsVector,
                     TlsData->TlsDirectory.Characteristics,
                     &TlsVector[TlsData->TlsDirectory.Characteristics],
@@ -876,10 +1309,140 @@ LdrpFreeTls(VOID)
 
 NTSTATUS
 NTAPI
-LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PULONG Options)
+LdrpInitializeApplicationVerifierPackage(PUNICODE_STRING ImagePathName, PPEB Peb, BOOLEAN SystemWide, BOOLEAN ReadAdvancedOptions)
 {
-    UNIMPLEMENTED;
-    *Options = 0;
+    /* If global flags request DPH, perform some additional actions */
+    if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS)
+    {
+        // TODO: Read advanced DPH flags from the registry if requested
+        if (ReadAdvancedOptions)
+        {
+            UNIMPLEMENTED;
+        }
+
+        /* Enable page heap */
+        RtlpPageHeapEnabled = TRUE;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHANDLE OptionsKey)
+{
+    NTSTATUS Status;
+    HANDLE KeyHandle;
+    ULONG ExecuteOptions, MinimumStackCommit = 0, GlobalFlag;
+
+    /* Return error if we were not provided a pointer where to save the options key handle */
+    if (!OptionsKey) return STATUS_INVALID_HANDLE;
+
+    /* Zero initialize the optinos key pointer */
+    *OptionsKey = NULL;
+
+    /* Open the options key */
+    Status = LdrOpenImageFileOptionsKey(ImagePathName, 0, &KeyHandle);
+
+    /* Save it if it was opened successfully */
+    if (NT_SUCCESS(Status))
+        *OptionsKey = KeyHandle;
+
+    if (KeyHandle)
+    {
+        /* There are image specific options, read them starting with NXCOMPAT */
+        Status = LdrQueryImageFileKeyOption(KeyHandle,
+                                            L"ExecuteOptions",
+                                            4,
+                                            &ExecuteOptions,
+                                            sizeof(ExecuteOptions),
+                                            0);
+
+        if (NT_SUCCESS(Status))
+        {
+            /* TODO: Set execution options for the process */
+            /*
+            if (ExecuteOptions == 0)
+                ExecuteOptions = 1;
+            else
+                ExecuteOptions = 2;
+            ZwSetInformationProcess(NtCurrentProcess(),
+                                    ProcessExecuteFlags,
+                                    &ExecuteOptions,
+                                    sizeof(ULONG));*/
+
+        }
+
+        /* Check if this image uses large pages */
+        if (Peb->ImageUsesLargePages)
+        {
+            /* TODO: If it does, open large page key */
+            UNIMPLEMENTED;
+        }
+
+        /* Get various option values */
+        LdrQueryImageFileKeyOption(KeyHandle,
+                                   L"DisableHeapLookaside",
+                                   REG_DWORD,
+                                   &RtlpDisableHeapLookaside,
+                                   sizeof(RtlpDisableHeapLookaside),
+                                   NULL);
+
+        LdrQueryImageFileKeyOption(KeyHandle,
+                                   L"ShutdownFlags",
+                                   REG_DWORD,
+                                   &RtlpShutdownProcessFlags,
+                                   sizeof(RtlpShutdownProcessFlags),
+                                   NULL);
+
+        LdrQueryImageFileKeyOption(KeyHandle,
+                                   L"MinimumStackCommitInBytes",
+                                   REG_DWORD,
+                                   &MinimumStackCommit,
+                                   sizeof(MinimumStackCommit),
+                                   NULL);
+
+        /* Update PEB's minimum stack commit if it's lower */
+        if (Peb->MinimumStackCommit < MinimumStackCommit)
+            Peb->MinimumStackCommit = MinimumStackCommit;
+
+        /* Set the global flag */
+        Status = LdrQueryImageFileKeyOption(KeyHandle,
+                                            L"GlobalFlag",
+                                            REG_DWORD,
+                                            &GlobalFlag,
+                                            sizeof(GlobalFlag),
+                                            NULL);
+
+        if (NT_SUCCESS(Status))
+            Peb->NtGlobalFlag = GlobalFlag;
+        else
+            GlobalFlag = 0;
+
+        /* Call AVRF if necessary */
+        if (Peb->NtGlobalFlag & (FLG_POOL_ENABLE_TAIL_CHECK | FLG_HEAP_PAGE_ALLOCS))
+        {
+            Status = LdrpInitializeApplicationVerifierPackage(ImagePathName, Peb, TRUE, FALSE);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status);
+            }
+        }
+    }
+    else
+    {
+        /* There are no image-specific options, so perform global initialization */
+        if (Peb->NtGlobalFlag & (FLG_POOL_ENABLE_TAIL_CHECK | FLG_HEAP_PAGE_ALLOCS))
+        {
+            /* Initialize app verifier package */
+            Status = LdrpInitializeApplicationVerifierPackage(ImagePathName, Peb, TRUE, FALSE);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status);
+            }
+        }
+    }
+
     return STATUS_SUCCESS;
 }
 
@@ -907,16 +1470,16 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     PPEB Peb = NtCurrentPeb();
     BOOLEAN IsDotNetImage = FALSE;
     BOOLEAN FreeCurDir = FALSE;
-    //HKEY CompatKey;
+    //HANDLE CompatKey;
     PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
     //LPWSTR ImagePathBuffer;
     ULONG ConfigSize;
     UNICODE_STRING CurrentDirectory;
-    ULONG ExecuteOptions;
+    HANDLE OptionsKey;
     ULONG HeapFlags;
     PIMAGE_NT_HEADERS NtHeader;
     LPWSTR NtDllName = NULL;
-    NTSTATUS Status;
+    NTSTATUS Status, ImportStatus;
     NLSTABLEINFO NlsTable;
     PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig;
     PTEB Teb = NtCurrentTeb();
@@ -925,9 +1488,10 @@ 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;
+    PVOID ViewBase;
 
     /* Set a NULL SEH Filter */
     RtlSetUnhandledExceptionFilter(NULL);
@@ -935,8 +1499,8 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     /* Get the image path */
     ImagePath = Peb->ProcessParameters->ImagePathName.Buffer;
 
-    /* Check if it's normalized */
-    if (Peb->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_NORMALIZED)
+    /* Check if it's not normalized */
+    if (!(Peb->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_NORMALIZED))
     {
         /* Normalize it*/
         ImagePath = (PWSTR)((ULONG_PTR)ImagePath + (ULONG_PTR)Peb->ProcessParameters);
@@ -951,7 +1515,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,
@@ -985,7 +1549,6 @@ LdrpInitializeProcess(IN PCONTEXT Context,
 
     /* Normalize the parameters */
     ProcessParameters = RtlNormalizeProcessParams(Peb->ProcessParameters);
-    ProcessParameters = Peb->ProcessParameters;
     if (ProcessParameters)
     {
         /* Save the Image and Command Line Names */
@@ -1037,12 +1600,12 @@ 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)
     {
-        DPRINT1("LDR: PID: 0x%x started - '%wZ'\n",
+        DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
                 Teb->ClientId.UniqueProcess,
                 &CommandLine);
     }
@@ -1088,9 +1651,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 */
@@ -1132,18 +1697,17 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     }
 
     /* Allocate an Activation Context Stack */
-    Status = RtlAllocateActivationContextStack((PVOID *)&Teb->ActivationContextStackPointer);
+    Status = RtlAllocateActivationContextStack(&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,
@@ -1155,16 +1719,16 @@ LdrpInitializeProcess(IN PCONTEXT Context,
             /* Reset DPH if requested */
             if (RtlpPageHeapEnabled && DebugProcessHeapOnly)
             {
-                RtlpDphGlobalFlags &= ~0x40;
+                RtlpDphGlobalFlags &= ~DPH_FLAG_DLL_NOTIFY;
                 RtlpPageHeapEnabled = FALSE;
             }
         }
     }
 
     /* 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\\");
@@ -1181,16 +1745,10 @@ LdrpInitializeProcess(IN PCONTEXT Context,
                                    &ObjectAttributes);
 
     /* Check if it exists */
-    if (!NT_SUCCESS(Status))
-    {
-        /* It doesn't, so assume System32 */
-        LdrpKnownDllObjectDirectory = NULL;
-        RtlInitUnicodeString(&LdrpKnownDllPath, FullPath.Buffer);
-        LdrpKnownDllPath.Length -= sizeof(WCHAR);
-    }
-    else
+    if (NT_SUCCESS(Status))
     {
         /* Open the Known DLLs Path */
+        RtlInitUnicodeString(&KnownDllString, L"KnownDllPath");
         InitializeObjectAttributes(&ObjectAttributes,
                                    &KnownDllString,
                                    OBJ_CASE_INSENSITIVE,
@@ -1215,6 +1773,15 @@ LdrpInitializeProcess(IN PCONTEXT Context,
         }
     }
 
+    /* Check if we failed */
+    if (!NT_SUCCESS(Status))
+    {
+        /* Aassume System32 */
+        LdrpKnownDllObjectDirectory = NULL;
+        RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer);
+        LdrpKnownDllPath.Length -= sizeof(WCHAR);
+    }
+
     /* If we have process parameters, get the default path and current path */
     if (ProcessParameters)
     {
@@ -1227,6 +1794,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
         else
         {
             /* We need a valid path */
+            DPRINT1("No valid DllPath was given!\n");
             LdrpInitFailure(STATUS_INVALID_PARAMETER);
         }
 
@@ -1243,6 +1811,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,
@@ -1253,12 +1826,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");
         }
     }
 
@@ -1277,8 +1850,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
@@ -1288,7 +1861,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     if (!ImageFileName.Buffer[0])
     {
         /* Use the same Base name */
-        NtLdrEntry->BaseDllName = NtLdrEntry->BaseDllName;
+        NtLdrEntry->BaseDllName = NtLdrEntry->FullDllName;
     }
     else
     {
@@ -1329,14 +1902,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);
@@ -1354,6 +1929,9 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList,
                    &LdrpNtDllDataTableEntry->InInitializationOrderModuleList);
 
+    /* Initialize Wine's active context implementation for the current process */
+    actctx_init();
+
     /* Set the current directory */
     Status = RtlSetCurrentDirectory_U(&CurrentDirectory);
     if (!NT_SUCCESS(Status))
@@ -1395,22 +1973,46 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
     {
         /* Load kernel32 and call BasePostImportInit... */
-        DPRINT1("Unimplemented codepath!\n");
+        DPRINT("Unimplemented codepath!\n");
     }
 
     /* Walk the IAT and load all the DLLs */
-    LdrpWalkImportDescriptor(LdrpDefaultPath.Buffer, LdrpImageEntry);
+    ImportStatus = LdrpWalkImportDescriptor(LdrpDefaultPath.Buffer, LdrpImageEntry);
 
     /* Check if relocation is needed */
     if (Peb->ImageBaseAddress != (PVOID)NtHeader->OptionalHeader.ImageBase)
     {
-        DPRINT("LDR: Performing relocations\n");
-        Status = LdrPerformRelocations(NtHeader, Peb->ImageBaseAddress);
+        DPRINT1("LDR: Performing EXE relocation\n");
+
+        /* Change the protection to prepare for relocation */
+        ViewBase = Peb->ImageBaseAddress;
+        Status = LdrpSetProtection(ViewBase, FALSE);
+        if (!NT_SUCCESS(Status)) return Status;
+
+        /* Do the relocation */
+        Status = LdrRelocateImageWithBias(ViewBase,
+                                          0LL,
+                                          NULL,
+                                          STATUS_SUCCESS,
+                                          STATUS_CONFLICTING_ADDRESSES,
+                                          STATUS_INVALID_IMAGE_FORMAT);
         if (!NT_SUCCESS(Status))
         {
-            DPRINT1("LdrPerformRelocations() failed\n");
+            DPRINT1("LdrRelocateImageWithBias() failed\n");
+            return Status;
+        }
+
+        /* Check if a start context was provided */
+        if (Context)
+        {
+            DPRINT1("WARNING: Relocated EXE Context");
+            UNIMPLEMENTED; // We should support this
             return STATUS_INVALID_IMAGE_FORMAT;
         }
+
+        /* Restore the protection */
+        Status = LdrpSetProtection(ViewBase, TRUE);
+        if (!NT_SUCCESS(Status)) return Status;
     }
 
     /* Lock the DLLs */
@@ -1426,6 +2028,9 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     /* Phase 0 is done */
     LdrpLdrDatabaseIsSetup = TRUE;
 
+    /* Check whether all static imports were properly loaded and return here */
+    if (!NT_SUCCESS(ImportStatus)) return ImportStatus;
+
     /* Initialize TLS */
     Status = LdrpInitializeTls();
     if (!NT_SUCCESS(Status))
@@ -1478,7 +2083,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     {
         /* Check for Application Compatibility Goo */
         //LdrQueryApplicationCompatibilityGoo(hKey);
-        DPRINT1("Querying app compat hacks is missing!\n");
+        DPRINT("Querying app compat hacks is missing!\n");
     }
 
     /*
@@ -1500,14 +2105,13 @@ LdrpInitializeProcess(IN PCONTEXT Context,
     /* Check if we have a user-defined Post Process Routine */
     if (NT_SUCCESS(Status) && Peb->PostProcessInitRoutine)
     {
-        DPRINT1("CP\n");
         /* Call it */
         Peb->PostProcessInitRoutine();
     }
 
-    ///* Close the key if we have one opened */
-    //if (hKey) NtClose(hKey);
-DbgBreakPoint();
+    /* Close the key if we have one opened */
+    if (OptionsKey) NtClose(OptionsKey);
+
     /* Return status */
     return Status;
 }
@@ -1517,9 +2121,11 @@ NTAPI
 LdrpInitFailure(NTSTATUS Status)
 {
     ULONG Response;
+    PPEB Peb = NtCurrentPeb();
 
     /* Print a debug message */
-    DPRINT1("LDR: Process initialization failure; NTSTATUS = %08lx\n", Status);
+    DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
+            &Peb->ProcessParameters->ImagePathName, Status);
 
     /* Raise a hard error */
     if (!LdrpFatalHardErrorCount)
@@ -1540,7 +2146,9 @@ LdrpInit(PCONTEXT Context,
     MEMORY_BASIC_INFORMATION MemoryBasicInfo;
     PPEB Peb = NtCurrentPeb();
 
-    DPRINT("LdrpInit()\n");
+    DPRINT("LdrpInit() %p/%p\n",
+        NtCurrentTeb()->RealClientId.UniqueProcess,
+        NtCurrentTeb()->RealClientId.UniqueThread);
 
     /* Check if we have a deallocation stack */
     if (!Teb->DeallocationStack)
@@ -1593,7 +2201,7 @@ LdrpInit(PCONTEXT Context,
         _SEH2_TRY
         {
             /* Initialize the Process */
-            LoaderStatus = LdrpInitializeProcess_(Context,
+            LoaderStatus = LdrpInitializeProcess(Context,
                                                  SystemArgument1);
 
             /* Check for success and if MinimumStackCommit was requested */