Sync to trunk head (r42241)
[reactos.git] / reactos / dll / ntdll / ldr / utils.c
index ce03c96..2753814 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            lib/ntdll/ldr/utils.c
 #define NDEBUG
 #include <debug.h>
 
-#define LDRP_PROCESS_CREATION_TIME 0x8000000
+#define LDRP_PROCESS_CREATION_TIME 0xffff
+#define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m)))
 
 /* GLOBALS *******************************************************************/
 
 #ifdef NDEBUG
-#if defined(__GNUC__)
-#define TRACE_LDR(args...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); }
-#else
-#endif /* __GNUC__ */
-#else
-#define TRACE_LDR(args...) do { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0)
+#define TRACE_LDR(...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(__VA_ARGS__); }
 #endif
 
 typedef struct _TLS_DATA
@@ -40,10 +35,11 @@ typedef struct _TLS_DATA
    PVOID StartAddressOfRawData;
    DWORD TlsDataSize;
    DWORD TlsZeroSize;
-   PIMAGE_TLS_CALLBACK TlsAddressOfCallBacks;
+   PIMAGE_TLS_CALLBACK *TlsAddressOfCallBacks;
    PLDR_DATA_TABLE_ENTRY Module;
 } TLS_DATA, *PTLS_DATA;
 
+static BOOLEAN LdrpDllShutdownInProgress = FALSE;
 static PTLS_DATA LdrpTlsArray = NULL;
 static ULONG LdrpTlsCount = 0;
 static ULONG LdrpTlsSize = 0;
@@ -67,7 +63,7 @@ static VOID LdrpDetachProcess(BOOLEAN UnloadAll);
 
 /* FUNCTIONS *****************************************************************/
 
-#if defined(DBG) || defined(KDBG)
+#if DBG || defined(KDBG)
 
 VOID
 LdrpLoadUserModuleSymbols(PLDR_DATA_TABLE_ENTRY LdrModule)
@@ -103,7 +99,7 @@ static __inline LONG LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module, BOOLEA
        RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
      }
    LoadCount = Module->LoadCount;
-   if (Module->LoadCount > 0 && Module->LoadCount != 0xFFFF)
+   if (Module->LoadCount > 0 && Module->LoadCount != LDRP_PROCESS_CREATION_TIME)
      {
        Module->LoadCount--;
      }
@@ -122,7 +118,7 @@ static __inline LONG LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module, BOOLEA
        RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
      }
    LoadCount = Module->LoadCount;
-   if (Module->LoadCount != 0xFFFF)
+   if (Module->LoadCount != LDRP_PROCESS_CREATION_TIME)
      {
        Module->LoadCount++;
      }
@@ -150,8 +146,8 @@ static __inline VOID LdrpAcquireTlsSlot(PLDR_DATA_TABLE_ENTRY Module, ULONG Size
 
 static __inline VOID LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module, ULONG dwReason)
 {
-   PIMAGE_TLS_CALLBACK TlsCallback;
-   if (Module->TlsIndex != 0xFFFF && Module->LoadCount == 0xFFFF)
+   PIMAGE_TLS_CALLBACK *TlsCallback;
+   if (Module->TlsIndex != 0xFFFF && Module->LoadCount == LDRP_PROCESS_CREATION_TIME)
      {
        TlsCallback = LdrpTlsArray[Module->TlsIndex].TlsAddressOfCallBacks;
        if (TlsCallback)
@@ -159,9 +155,9 @@ static __inline VOID LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module, ULONG dwReaso
            while (*TlsCallback)
              {
                TRACE_LDR("%wZ - Calling tls callback at %x\n",
-                         &Module->BaseDllName, TlsCallback);
-               TlsCallback(Module->DllBase, dwReason, NULL);
-               TlsCallback = (PIMAGE_TLS_CALLBACK)((ULONG_PTR)TlsCallback + sizeof(PVOID));
+                         &Module->BaseDllName, *TlsCallback);
+               (*TlsCallback)(Module->DllBase, dwReason, NULL);
+               TlsCallback++;
              }
          }
      }
@@ -178,6 +174,112 @@ static BOOLEAN LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module, DWORD dwReason, PV
    return  ((PDLLMAIN_FUNC)Module->EntryPoint)(Module->DllBase, dwReason, lpReserved);
 }
 
+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) * sizeof(WCHAR));
+
+    if (!Path)
+    {
+        DPRINT1("RtlAllocateHeap() failed\n");
+        return NULL;
+    }
+
+    wcscpy(Path, SearchPathBuffer);
+
+    return Path;
+}
+
 static NTSTATUS
 LdrpInitializeTlsForThread(VOID)
 {
@@ -224,6 +326,7 @@ LdrpInitializeTlsForThread(VOID)
              }
          }
      }
+
    DPRINT("LdrpInitializeTlsForThread() done\n");
    return STATUS_SUCCESS;
 }
@@ -256,7 +359,7 @@ LdrpInitializeTlsForProccess(VOID)
        while (Entry != ModuleListHead)
          {
            Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-           if (Module->LoadCount == 0xFFFF &&
+           if (Module->LoadCount == LDRP_PROCESS_CREATION_TIME &&
                Module->TlsIndex != 0xFFFF)
              {
                TlsDirectory = (PIMAGE_TLS_DIRECTORY)
@@ -270,7 +373,7 @@ LdrpInitializeTlsForProccess(VOID)
                TlsData->TlsDataSize = TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData;
                TlsData->TlsZeroSize = TlsDirectory->SizeOfZeroFill;
                if (TlsDirectory->AddressOfCallBacks)
-                 TlsData->TlsAddressOfCallBacks = *(PIMAGE_TLS_CALLBACK*)TlsDirectory->AddressOfCallBacks;
+                 TlsData->TlsAddressOfCallBacks = (PIMAGE_TLS_CALLBACK *)TlsDirectory->AddressOfCallBacks;
                else
                  TlsData->TlsAddressOfCallBacks = NULL;
                TlsData->Module = Module;
@@ -280,7 +383,7 @@ LdrpInitializeTlsForProccess(VOID)
                DbgPrint("EndAddressOfRawData:   %x\n", TlsDirectory->EndAddressOfRawData);
                DbgPrint("SizeOfRawData:         %d\n", TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData);
                DbgPrint("AddressOfIndex:        %x\n", TlsDirectory->AddressOfIndex);
-               DbgPrint("AddressOfCallBacks:    %x (%x)\n", TlsDirectory->AddressOfCallBacks, *TlsDirectory->AddressOfCallBacks);
+               DbgPrint("AddressOfCallBacks:    %x\n", TlsDirectory->AddressOfCallBacks);
                DbgPrint("SizeOfZeroFill:        %d\n", TlsDirectory->SizeOfZeroFill);
                DbgPrint("Characteristics:       %x\n", TlsDirectory->Characteristics);
 #endif
@@ -293,6 +396,7 @@ LdrpInitializeTlsForProccess(VOID)
            Entry = Entry->Flink;
         }
     }
+
   DPRINT("LdrpInitializeTlsForProccess() done\n");
   return STATUS_SUCCESS;
 }
@@ -344,7 +448,7 @@ LdrpInitLoader(VOID)
                        L"KnownDllPath");
   InitializeObjectAttributes(&ObjectAttributes,
                              &Name,
-                             OBJ_CASE_INSENSITIVE | OBJ_OPENLINK,
+                             OBJ_CASE_INSENSITIVE,
                              LdrpKnownDllsDirHandle,
                              NULL);
   Status = NtOpenSymbolicLinkObject(&LinkHandle,
@@ -469,7 +573,7 @@ LdrAddModuleEntry(PVOID ImageBase,
   ASSERT(Module);
   memset(Module, 0, sizeof(LDR_DATA_TABLE_ENTRY));
   Module->DllBase = (PVOID)ImageBase;
-  Module->EntryPoint = (PVOID)NTHeaders->OptionalHeader.AddressOfEntryPoint;
+  Module->EntryPoint = (PVOID)(ULONG_PTR)NTHeaders->OptionalHeader.AddressOfEntryPoint;
   if (Module->EntryPoint != 0)
     Module->EntryPoint = (PVOID)((ULONG_PTR)Module->EntryPoint + (ULONG_PTR)Module->DllBase);
   Module->SizeOfImage = LdrpGetResidentSize(NTHeaders);
@@ -482,7 +586,7 @@ LdrAddModuleEntry(PVOID ImageBase,
        * loading while app is initializing
        * dll must not be unloaded
        */
-      Module->LoadCount = 0xFFFF;
+      Module->LoadCount = LDRP_PROCESS_CREATION_TIME;
     }
 
   Module->Flags = 0;
@@ -613,7 +717,6 @@ LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL,
                           NULL) == 0)
     return STATUS_DLL_NOT_FOUND;
 
-
   if (!RtlDosPathNameToNtPathName_U (DosName,
                                      &FullNtFileName,
                                      NULL,
@@ -649,38 +752,43 @@ LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL,
                0,
                FullNtFileName.Buffer);
 
-  Status = NtReadFile(FileHandle,
-                      NULL,
-                      NULL,
-                      NULL,
-                      &IoStatusBlock,
-                      BlockBuffer,
-                      sizeof(BlockBuffer),
-                      NULL,
-                      NULL);
-  if (!NT_SUCCESS(Status))
+  if (!MapAsDataFile)
     {
-      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;
+      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;
+        }
     }
 
   /*
@@ -691,7 +799,7 @@ LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL,
                            NULL,
                            NULL,
                            PAGE_READONLY,
-                           SEC_COMMIT | (MapAsDataFile ? 0 : SEC_IMAGE),
+                           MapAsDataFile ? SEC_COMMIT : SEC_IMAGE,
                            FileHandle);
   NtClose(FileHandle);
 
@@ -729,38 +837,36 @@ NTSTATUS NTAPI
 LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
             IN PULONG LoadFlags OPTIONAL,
             IN PUNICODE_STRING Name,
-            OUT PVOID *BaseAddress OPTIONAL)
+            OUT PVOID *BaseAddress /* also known as HMODULE*, and PHANDLE 'DllHandle' */)
 {
   NTSTATUS              Status;
-  PLDR_DATA_TABLE_ENTRY           Module;
+  PLDR_DATA_TABLE_ENTRY Module;
+
+  PPEB Peb = NtCurrentPeb();
 
   TRACE_LDR("LdrLoadDll, loading %wZ%s%S\n",
             Name,
-            SearchPath ? " from " : "",
+            SearchPath ? L" from " : L"",
             SearchPath ? SearchPath : L"");
 
-  if (Name == NULL)
-    {
-      if (BaseAddress)
-        *BaseAddress = NtCurrentPeb()->ImageBaseAddress;
-      return STATUS_SUCCESS;
-    }
-
-  if (BaseAddress)
-    *BaseAddress = NULL;
-
   Status = LdrpLoadModule(SearchPath, LoadFlags ? *LoadFlags : 0, Name, &Module, BaseAddress);
-  if (NT_SUCCESS(Status)
-  && (!LoadFlags || 0 == (*LoadFlags & LOAD_LIBRARY_AS_DATAFILE)))
+
+  if (NT_SUCCESS(Status) &&
+      (!LoadFlags || 0 == (*LoadFlags & LOAD_LIBRARY_AS_DATAFILE)))
     {
-      RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
-      Status = LdrpAttachProcess();
-      RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
-      if (NT_SUCCESS(Status) && BaseAddress)
+      if (!(Module->Flags & LDRP_PROCESS_ATTACH_CALLED))
         {
-          *BaseAddress = Module->DllBase;
+          RtlEnterCriticalSection(Peb->LoaderLock);
+          Status = LdrpAttachProcess();
+          RtlLeaveCriticalSection(Peb->LoaderLock);
         }
-   }
+    }
+
+ if ((!Module) && (NT_SUCCESS(Status)))
+    return Status;
+
+  *BaseAddress = NT_SUCCESS(Status) ? Module->DllBase : NULL;
+
   return Status;
 }
 
@@ -852,7 +958,6 @@ LdrFindEntryForName(PUNICODE_STRING Name,
   PLDR_DATA_TABLE_ENTRY ModulePtr;
   BOOLEAN ContainsPath;
   UNICODE_STRING AdjustedName;
-  unsigned i;
 
   DPRINT("LdrFindEntryForName(Name %wZ)\n", Name);
 
@@ -876,14 +981,8 @@ LdrFindEntryForName(PUNICODE_STRING Name,
       return(STATUS_SUCCESS);
     }
 
-  LdrAdjustDllName (&AdjustedName, Name, FALSE);
-
-  ContainsPath = (AdjustedName.Length >= 2 * sizeof(WCHAR) && L':' == AdjustedName.Buffer[1]);
-  for (i = 0; ! ContainsPath && i < AdjustedName.Length / sizeof(WCHAR); i++)
-    {
-      ContainsPath = L'\\' == AdjustedName.Buffer[i] ||
-                     L'/' == AdjustedName.Buffer[i];
-    }
+  ContainsPath = (Name->Length >= 2 * sizeof(WCHAR) && L':' == Name->Buffer[1]);
+  LdrAdjustDllName (&AdjustedName, Name, !ContainsPath);
 
   if (LdrpLastModule)
     {
@@ -893,7 +992,7 @@ LdrFindEntryForName(PUNICODE_STRING Name,
            0 == RtlCompareUnicodeString(&LdrpLastModule->FullDllName, &AdjustedName, TRUE)))
         {
           *Module = LdrpLastModule;
-          if (Ref && (*Module)->LoadCount != 0xFFFF)
+          if (Ref && (*Module)->LoadCount != LDRP_PROCESS_CREATION_TIME)
             {
               (*Module)->LoadCount++;
             }
@@ -914,7 +1013,7 @@ LdrFindEntryForName(PUNICODE_STRING Name,
            0 == RtlCompareUnicodeString(&ModulePtr->FullDllName, &AdjustedName, TRUE)))
         {
           *Module = LdrpLastModule = ModulePtr;
-          if (Ref && ModulePtr->LoadCount != 0xFFFF)
+          if (Ref && ModulePtr->LoadCount != LDRP_PROCESS_CREATION_TIME)
             {
               ModulePtr->LoadCount++;
             }
@@ -973,9 +1072,8 @@ LdrFixupForward(PCHAR ForwardName)
          */
         if (!NT_SUCCESS(Status))
           {
-             ULONG Flags = LDRP_PROCESS_CREATION_TIME;
              Status = LdrLoadDll(NULL,
-                                 &Flags,
+                                                                NULL,
                                  &DllName,
                                  &BaseAddress);
              if (NT_SUCCESS(Status))
@@ -1047,8 +1145,8 @@ LdrGetExportByOrdinal (
                     ? RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] )
                     : NULL);
 
-        if (((ULONG)Function >= (ULONG)ExportDir) &&
-            ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
+        if (((ULONG_PTR)Function >= (ULONG_PTR)ExportDir) &&
+            ((ULONG_PTR)Function < (ULONG_PTR)ExportDir + (ULONG_PTR)ExportDirSize))
           {
              DPRINT("Forward: %s\n", (PCHAR)Function);
              Function = LdrFixupForward((PCHAR)Function);
@@ -1099,7 +1197,8 @@ LdrGetExportByName(PVOID BaseAddress,
                                   &ExportDirSize);
    if (ExportDir == NULL)
      {
-        DPRINT1("LdrGetExportByName(): no export directory!\n");
+        DPRINT1("LdrGetExportByName(): no export directory, "
+                "can't lookup %s/%hu!\n", SymbolName, Hint);
         return NULL;
      }
 
@@ -1131,8 +1230,8 @@ LdrGetExportByName(PVOID BaseAddress,
           {
              Ordinal = ExOrdinals[Hint];
              Function = RVA(BaseAddress, ExFunctions[Ordinal]);
-             if (((ULONG)Function >= (ULONG)ExportDir) &&
-                 ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
+             if (((ULONG_PTR)Function >= (ULONG_PTR)ExportDir) &&
+                 ((ULONG_PTR)Function < (ULONG_PTR)ExportDir + (ULONG_PTR)ExportDirSize))
                {
                   DPRINT("Forward: %s\n", (PCHAR)Function);
                   Function = LdrFixupForward((PCHAR)Function);
@@ -1165,8 +1264,8 @@ LdrGetExportByName(PVOID BaseAddress,
           {
              Ordinal = ExOrdinals[mid];
              Function = RVA(BaseAddress, ExFunctions[Ordinal]);
-             if (((ULONG)Function >= (ULONG)ExportDir) &&
-                 ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
+             if (((ULONG_PTR)Function >= (ULONG_PTR)ExportDir) &&
+                 ((ULONG_PTR)Function < (ULONG_PTR)ExportDir + (ULONG_PTR)ExportDirSize))
                {
                   DPRINT("Forward: %s\n", (PCHAR)Function);
                   Function = LdrFixupForward((PCHAR)Function);
@@ -1194,7 +1293,7 @@ LdrGetExportByName(PVOID BaseAddress,
           }
      }
 
-   DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName);
+   DPRINT("LdrGetExportByName(): failed to find %s\n",SymbolName);
    return (PVOID)NULL;
 }
 
@@ -1221,7 +1320,8 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
 {
   PIMAGE_DATA_DIRECTORY RelocationDDir;
   PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
-  ULONG Count, ProtectSize, OldProtect, OldProtect2;
+  ULONG Count, OldProtect, OldProtect2;
+  SIZE_T ProtectSize;
   PVOID Page, ProtectPage, ProtectPage2;
   PUSHORT TypeOffset;
   ULONG_PTR Delta;
@@ -1229,7 +1329,7 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
 
   if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
     {
-      return STATUS_UNSUCCESSFUL;
+      return STATUS_SUCCESS;
     }
 
   RelocationDDir =
@@ -1321,39 +1421,82 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
 }
 
 static NTSTATUS
-LdrpGetOrLoadModule(PWCHAR SerachPath,
+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);
 
-   RtlCreateUnicodeStringFromAsciiz (&DllName, 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(SerachPath,
-                               NtCurrentPeb()->Ldr->Initialized ? 0 : LDRP_PROCESS_CREATION_TIME,
+       Status = LdrpLoadModule(SearchPath,
+                                                          0,
                                &DllName,
                                Module,
-                               NULL);
+                                                          NULL);
        if (NT_SUCCESS(Status))
          {
            Status = LdrFindEntryForName (&DllName, Module, FALSE);
          }
        if (!NT_SUCCESS(Status))
          {
+           ULONG ErrorResponse;
+           ULONG_PTR ErrorParameter = (ULONG_PTR)&DllName;
+
            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)
+{
+    ULONG ErrorResponse;
+    ULONG_PTR ErrorParameters[2];
+    ANSI_STRING ProcNameAnsi;
+    UNICODE_STRING ProcName;
+    CHAR Buffer[8];
+
+    if (!FuncName)
+    {
+        _snprintf(Buffer, 8, "# %ld", Ordinal);
+        FuncName = Buffer;
+    }
+
+    RtlInitAnsiString(&ProcNameAnsi, FuncName);
+    RtlAnsiStringToUnicodeString(&ProcName, &ProcNameAnsi, TRUE);
+    ErrorParameters[0] = (ULONG_PTR)&ProcName;
+    ErrorParameters[1] = (ULONG_PTR)DllName;
+    NtRaiseHardError(STATUS_ENTRYPOINT_NOT_FOUND,
+                     2,
+                     3,
+                     ErrorParameters,
+                     OptionOk,
+                     &ErrorResponse);
+    RtlFreeUnicodeString(&ProcName);
+}
+
 static NTSTATUS
 LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module,
                                 PLDR_DATA_TABLE_ENTRY ImportedModule,
@@ -1365,7 +1508,7 @@ LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module,
    PVOID IATBase;
    ULONG OldProtect;
    ULONG Ordinal;
-   ULONG IATSize;
+   SIZE_T IATSize;
 
    if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
      {
@@ -1416,7 +1559,8 @@ LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module,
            if ((*ImportAddressList) == NULL)
              {
                DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName);
-               return STATUS_UNSUCCESSFUL;
+               RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName);
+               return STATUS_ENTRYPOINT_NOT_FOUND;
              }
          }
        else
@@ -1427,7 +1571,8 @@ LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module,
            if ((*ImportAddressList) == NULL)
              {
                DPRINT1("Failed to import %s from %wZ\n", pe_name->Name, &ImportedModule->FullDllName);
-               return STATUS_UNSUCCESSFUL;
+               RtlpRaiseImportNotFound((CHAR*)pe_name->Name, 0, &ImportedModule->FullDllName);
+               return STATUS_ENTRYPOINT_NOT_FOUND;
              }
          }
        ImportAddressList++;
@@ -1509,7 +1654,7 @@ LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module,
    PVOID IATBase;
    ULONG OldProtect;
    ULONG Offset;
-   ULONG IATSize;
+   SIZE_T IATSize;
    PIMAGE_NT_HEADERS NTHeaders;
    PCHAR Name;
    ULONG Size;
@@ -1631,6 +1776,7 @@ LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
    NTSTATUS Status;
    PLDR_DATA_TABLE_ENTRY ImportedModule;
    PCHAR ImportedName;
+   PWSTR ModulePath;
    ULONG Size;
 
    DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath, Module);
@@ -1646,14 +1792,15 @@ LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
        TlsSize = TlsDirectory->EndAddressOfRawData
                    - TlsDirectory->StartAddressOfRawData
                    + TlsDirectory->SizeOfZeroFill;
-       if (TlsSize > 0 &&
-           NtCurrentPeb()->Ldr->Initialized)
+
+       if (TlsSize > 0 && NtCurrentPeb()->Ldr->Initialized)
          {
-           TRACE_LDR("Trying to load dynamicly %wZ which contains a tls directory\n",
+           TRACE_LDR("Trying to dynamically load %wZ which contains a TLS directory\n",
                      &Module->BaseDllName);
-           return STATUS_UNSUCCESSFUL;
+           TlsDirectory = NULL;
          }
      }
+
    /*
     * Process each import module.
     */
@@ -1716,7 +1863,7 @@ LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
                else
                  {
                    TRACE_LDR("%wZ has correct binding to %wZ\n",
-                           &Module->BaseDllName, &ImportedModule->BaseDllName);
+                             &Module->BaseDllName, &ImportedModule->BaseDllName);
                  }
                if (BoundImportDescriptorCurrent->NumberOfModuleForwarderRefs)
                  {
@@ -1809,12 +1956,22 @@ LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
            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);
                return Status;
              }
+Success:
            if (Module == ImportedModule)
              {
                LdrpDecrementLoadCount(Module, FALSE);
@@ -1982,7 +2139,7 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
     NTSTATUS Status;
     PLDR_DATA_TABLE_ENTRY tmpModule;
     HANDLE SectionHandle;
-    ULONG ViewSize;
+    SIZE_T ViewSize;
     PVOID ImageBase;
     PIMAGE_NT_HEADERS NtHeaders;
     BOOLEAN MappedAsDataFile;
@@ -2030,7 +2187,6 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
         ImageBase = 0;
         ArbitraryUserPointer = NtCurrentTeb()->Tib.ArbitraryUserPointer;
         NtCurrentTeb()->Tib.ArbitraryUserPointer = FullDosName.Buffer;
-        DPRINT1("POI. DAT: %p %S\n", NtCurrentTeb()->Tib.ArbitraryUserPointer, FullDosName.Buffer);
         Status = NtMapViewOfSection(SectionHandle,
                                     NtCurrentProcess(),
                                     &ImageBase,
@@ -2038,11 +2194,10 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
                                     0,
                                     NULL,
                                     &ViewSize,
+                                    ViewShare,
                                     0,
-                                    MEM_COMMIT,
                                     PAGE_READONLY);
         NtCurrentTeb()->Tib.ArbitraryUserPointer = ArbitraryUserPointer;
-        DPRINT1("Poi gone!\n");
         if (!NT_SUCCESS(Status))
           {
             DPRINT1("map view of section failed (Status 0x%08lx)\n", Status);
@@ -2054,15 +2209,18 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
           {
             *BaseAddress = ImageBase;
           }
-        /* Get and check the NT headers */
-        NtHeaders = RtlImageNtHeader(ImageBase);
-        if (NtHeaders == NULL)
+        if (!MappedAsDataFile)
           {
-            DPRINT1("RtlImageNtHeaders() failed\n");
-            NtUnmapViewOfSection (NtCurrentProcess (), ImageBase);
-            NtClose (SectionHandle);
-            RtlFreeUnicodeString(&FullDosName);
-            return STATUS_UNSUCCESSFUL;
+            /* 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)
@@ -2111,12 +2269,12 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
             DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module)->BaseDllName, Status);
             return Status;
           }
-#if defined(DBG) || defined(KDBG)
+#if DBG || defined(KDBG)
         LdrpLoadUserModuleSymbols(*Module);
 #endif /* DBG || KDBG */
         RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
         InsertTailList(&NtCurrentPeb()->Ldr->InInitializationOrderModuleList,
-                       &(*Module)->InInitializationOrderModuleList);
+                       &(*Module)->InInitializationOrderLinks);
         RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
       }
     return STATUS_SUCCESS;
@@ -2420,6 +2578,7 @@ LdrGetProcedureAddress (IN PVOID BaseAddress,
                         IN ULONG Ordinal,
                         OUT PVOID *ProcedureAddress)
 {
+   NTSTATUS Status = STATUS_PROCEDURE_NOT_FOUND;
    if (Name && Name->Length)
      {
        TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name);
@@ -2432,28 +2591,37 @@ LdrGetProcedureAddress (IN PVOID BaseAddress,
    DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
           BaseAddress, Name, Ordinal, ProcedureAddress);
 
-   if (Name && Name->Length)
+   _SEH2_TRY
+   {
+     if (Name && Name->Length)
      {
        /* by name */
        *ProcedureAddress = LdrGetExportByName(BaseAddress, (PUCHAR)Name->Buffer, 0xffff);
        if (*ProcedureAddress != NULL)
          {
-           return STATUS_SUCCESS;
+           Status = STATUS_SUCCESS;
          }
        DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
      }
-   else
+     else
      {
        /* by ordinal */
        Ordinal &= 0x0000FFFF;
        *ProcedureAddress = LdrGetExportByOrdinal(BaseAddress, (WORD)Ordinal);
        if (*ProcedureAddress)
          {
-           return STATUS_SUCCESS;
+           Status = STATUS_SUCCESS;
          }
        DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal);
      }
-   return STATUS_PROCEDURE_NOT_FOUND;
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+       Status = STATUS_DLL_NOT_FOUND;
+   }
+   _SEH2_END;
+
+   return Status;
 }
 
 /**********************************************************************
@@ -2485,14 +2653,17 @@ LdrpDetachProcess(BOOLEAN UnloadAll)
    DPRINT("LdrpDetachProcess() called for %wZ\n",
            &ExeModule->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 == 0xFFFF) || Module->LoadCount == 0) &&
+       Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
+       if (((UnloadAll && Module->LoadCount == LDRP_PROCESS_CREATION_TIME) || Module->LoadCount == 0) &&
            Module->Flags & LDRP_ENTRY_PROCESSED &&
            !(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
          {
@@ -2505,7 +2676,7 @@ LdrpDetachProcess(BOOLEAN UnloadAll)
              {
                TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
                          &Module->BaseDllName, Module->EntryPoint);
-               LdrpCallDllEntry(Module, DLL_PROCESS_DETACH, (PVOID)(Module->LoadCount == 0xFFFF ? 1 : 0));
+               LdrpCallDllEntry(Module, DLL_PROCESS_DETACH, (PVOID)(INT_PTR)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
              }
            else
              {
@@ -2524,14 +2695,14 @@ LdrpDetachProcess(BOOLEAN UnloadAll)
        Entry = ModuleListHead->Blink;
        while (Entry != ModuleListHead)
          {
-           Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
+           Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
            Entry = Entry->Blink;
            if (Module->Flags & LDRP_UNLOAD_IN_PROGRESS &&
-               ((UnloadAll && Module->LoadCount != 0xFFFF) || Module->LoadCount == 0))
+               ((UnloadAll && Module->LoadCount != LDRP_PROCESS_CREATION_TIME) || Module->LoadCount == 0))
              {
                /* remove the module entry from the list */
                RemoveEntryList (&Module->InLoadOrderLinks);
-               RemoveEntryList (&Module->InInitializationOrderModuleList);
+               RemoveEntryList (&Module->InInitializationOrderLinks);
 
                NtUnmapViewOfSection (NtCurrentProcess (), Module->DllBase);
                NtClose (Module->SectionPointer);
@@ -2584,13 +2755,13 @@ LdrpAttachProcess(VOID)
    Entry = ModuleListHead->Flink;
    while (Entry != ModuleListHead)
      {
-       Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
+       Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
        if (!(Module->Flags & (LDRP_LOAD_IN_PROGRESS|LDRP_UNLOAD_IN_PROGRESS|LDRP_ENTRY_PROCESSED)))
          {
            Module->Flags |= LDRP_LOAD_IN_PROGRESS;
            TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
                      &Module->BaseDllName, Module->EntryPoint);
-           Result = LdrpCallDllEntry(Module, DLL_PROCESS_ATTACH, (PVOID)(Module->LoadCount == 0xFFFF ? 1 : 0));
+           Result = LdrpCallDllEntry(Module, DLL_PROCESS_ATTACH, (PVOID)(INT_PTR)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
            if (!Result)
              {
                Status = STATUS_DLL_INIT_FAILED;
@@ -2614,6 +2785,15 @@ LdrpAttachProcess(VOID)
    return Status;
 }
 
+/*
+ * @implemented
+ */
+BOOLEAN NTAPI
+RtlDllShutdownInProgress (VOID)
+{
+  return LdrpDllShutdownInProgress;
+}
+
 /*
  * @implemented
  */
@@ -2650,7 +2830,7 @@ LdrpAttachThread (VOID)
 
       while (Entry != ModuleListHead)
         {
-          Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
+          Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
           if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED &&
               !(Module->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
               !(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
@@ -2694,7 +2874,7 @@ LdrShutdownThread (VOID)
    Entry = ModuleListHead->Blink;
    while (Entry != ModuleListHead)
      {
-       Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
+       Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
 
        if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED &&
            !(Module->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
@@ -2944,7 +3124,7 @@ LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle,
   FILE_STANDARD_INFORMATION FileInfo;
   IO_STATUS_BLOCK IoStatusBlock;
   HANDLE SectionHandle;
-  ULONG ViewSize;
+  SIZE_T ViewSize;
   PVOID BaseAddress;
   BOOLEAN Result;
   NTSTATUS Status;
@@ -3201,6 +3381,12 @@ LdrProcessRelocationBlock(IN ULONG_PTR Address,
             LongPtr = (PULONG)((ULONG_PTR)Address + Offset);
             *LongPtr += Delta;
             break;
+#ifdef _WIN64
+          case IMAGE_REL_BASED_DIR64:
+            LongPtr = (PULONG)((ULONG_PTR)Address + Offset);
+            *LongPtr += Delta;
+            break;
+#endif
 
           case IMAGE_REL_BASED_HIGHADJ:
           case IMAGE_REL_BASED_MIPS_JMPADDR:
@@ -3215,4 +3401,29 @@ LdrProcessRelocationBlock(IN ULONG_PTR Address,
   return (PIMAGE_BASE_RELOCATION)TypeOffset;
 }
 
-/* EOF */
+NTSTATUS
+NTAPI
+LdrLockLoaderLock(IN ULONG Flags,
+                  OUT PULONG Disposition OPTIONAL,
+                  OUT PULONG Cookie OPTIONAL)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+LdrUnlockLoaderLock(IN ULONG Flags,
+                    IN ULONG Cookie OPTIONAL)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+BOOLEAN
+NTAPI
+LdrUnloadAlternateResourceModule(IN PVOID BaseAddress)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}