[CMAKE] Use modules instead of shared libraries
[reactos.git] / dll / ntdll / ldr / ldrpe.c
index 183c86e..ecba954 100644 (file)
@@ -9,27 +9,17 @@
 /* INCLUDES *****************************************************************/
 
 #include <ntdll.h>
+
 #define NDEBUG
 #include <debug.h>
 
 /* GLOBALS *******************************************************************/
 
-PVOID LdrpManifestProberRoutine;
+PLDR_MANIFEST_PROBER_ROUTINE LdrpManifestProberRoutine;
 ULONG LdrpNormalSnap;
 
 /* FUNCTIONS *****************************************************************/
 
-VOID
-NTAPI
-AVrfPageHeapDllNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
-{
-    /* Check if page heap dll notification is turned on */
-    if (!(RtlpDphGlobalFlags & DPH_FLAG_DLL_NOTIFY))
-        return;
-
-    /* We don't support this flag currently */
-    UNIMPLEMENTED;
-}
 
 NTSTATUS
 NTAPI
@@ -47,7 +37,7 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
     LPSTR ImportName;
     ULONG ForwarderChain, i, Rva, OldProtect, IatSize, ExportSize;
     SIZE_T ImportSize;
-    DPRINT("LdrpSnapIAT(%wZ %wZ %p %d)\n", &ExportLdrEntry->BaseDllName, &ImportLdrEntry->BaseDllName, IatEntry, EntriesValid);
+    DPRINT("LdrpSnapIAT(%wZ %wZ %p %u)\n", &ExportLdrEntry->BaseDllName, &ImportLdrEntry->BaseDllName, IatEntry, EntriesValid);
 
     /* Get export directory */
     ExportDirectory = RtlImageDirectoryEntryToData(ExportLdrEntry->DllBase,
@@ -147,7 +137,7 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
         /* We'll only do forwarders. Get the import name */
         ImportName = (LPSTR)((ULONG_PTR)ImportLdrEntry->DllBase + IatEntry->Name);
 
-        /* Get the list of forwaders */
+        /* Get the list of forwarders */
         ForwarderChain = IatEntry->ForwarderChain;
 
         /* Loop them */
@@ -287,7 +277,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     /* Get the name's VA */
     BoundImportName = (LPSTR)FirstEntry + BoundEntry->OffsetModuleName;
 
-    /* Show debug mesage */
+    /* Show debug message */
     if (ShowSnaps)
     {
         DPRINT1("LDR: %wZ bound to %s\n", &LdrEntry->BaseDllName, BoundImportName);
@@ -296,7 +286,6 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     /* Load the module for this entry */
     Status = LdrpLoadImportModule(DllPath,
                                   BoundImportName,
-                                  LdrEntry->DllBase,
                                   &DllLdrEntry,
                                   &AlreadyLoaded);
     if (!NT_SUCCESS(Status))
@@ -317,7 +306,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     {
         /* Add it to our list */
         InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
-                       &DllLdrEntry->InInitializationOrderModuleList);
+                       &DllLdrEntry->InInitializationOrderLinks);
     }
 
     /* Check if the Bound Entry is now invalid */
@@ -370,7 +359,6 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
         /* Load the module */
         Status = LdrpLoadImportModule(DllPath,
                                       ForwarderName,
-                                      LdrEntry->DllBase,
                                       &ForwarderLdrEntry,
                                       &AlreadyLoaded);
         if (NT_SUCCESS(Status))
@@ -380,7 +368,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
             {
                 /* Add it to our list */
                 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
-                               &ForwarderLdrEntry->InInitializationOrderModuleList);
+                               &ForwarderLdrEntry->InInitializationOrderLinks);
             }
         }
 
@@ -557,7 +545,6 @@ LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     /* Load the module associated to it */
     Status = LdrpLoadImportModule(DllPath,
                                   ImportName,
-                                  LdrEntry->DllBase,
                                   &DllLdrEntry,
                                   &AlreadyLoaded);
     if (!NT_SUCCESS(Status))
@@ -589,7 +576,7 @@ LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     {
         /* Add the DLL to our list */
         InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
-                       &DllLdrEntry->InInitializationOrderModuleList);
+                       &DllLdrEntry->InInitializationOrderLinks);
     }
 
     /* Now snap the IAT Entry */
@@ -685,11 +672,12 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
 {
     RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
     PPEB Peb = NtCurrentPeb();
-    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status = STATUS_SUCCESS, Status2;
     PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry = NULL;
     PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
     ULONG BoundSize, IatSize;
-    DPRINT("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry);
+
+    DPRINT("LdrpWalkImportDescriptor - BEGIN (%wZ %p '%S')\n", &LdrEntry->BaseDllName, LdrEntry, DllPath);
 
     /* Set up the Act Ctx */
     RtlZeroMemory(&ActCtx, sizeof(ActCtx));
@@ -699,23 +687,44 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     /* Check if we have a manifest prober routine */
     if (LdrpManifestProberRoutine)
     {
-        DPRINT1("We don't support manifests yet, much less prober routines\n");
+        /* Probe the DLL for its manifest. Some details are omitted */
+        Status2 = LdrpManifestProberRoutine(LdrEntry->DllBase, LdrEntry->FullDllName.Buffer, &LdrEntry->EntryPointActivationContext);
+
+        if (!NT_SUCCESS(Status2) &&
+            Status2 != STATUS_NO_SUCH_FILE &&
+            Status2 != STATUS_RESOURCE_DATA_NOT_FOUND &&
+            Status2 != STATUS_RESOURCE_TYPE_NOT_FOUND &&
+            Status2 != STATUS_RESOURCE_NAME_NOT_FOUND &&
+            Status2 != STATUS_RESOURCE_LANG_NOT_FOUND)
+        {
+            /* Some serious issue */
+            //Status = Status2; // FIXME: Ignore that error for now
+            DbgPrintEx(DPFLTR_SXS_ID,
+                DPFLTR_WARNING_LEVEL,
+                "LDR: LdrpWalkImportDescriptor() failed to probe %wZ for its "
+                "manifest, ntstatus = 0x%08lx\n",
+                &LdrEntry->FullDllName, Status);
+        }
     }
 
     /* Check if we failed above */
     if (!NT_SUCCESS(Status)) return Status;
 
     /* Get the Active ActCtx */
-    Status = RtlGetActiveActivationContext(&LdrEntry->EntryPointActivationContext);
-    if (!NT_SUCCESS(Status))
+    if (!LdrEntry->EntryPointActivationContext)
     {
-        /* Exit */
-        DbgPrintEx(51, // DPFLTR_SXS_ID
-                   DPFLTR_WARNING_LEVEL,
-                   "LDR: RtlGetActiveActivationContext() failed; ntstatus = "
-                   "0x%08lx\n",
-                   Status);
-        return Status;
+        Status = RtlGetActiveActivationContext(&LdrEntry->EntryPointActivationContext);
+
+        if (!NT_SUCCESS(Status))
+        {
+            /* Exit */
+            DbgPrintEx(DPFLTR_SXS_ID,
+                DPFLTR_WARNING_LEVEL,
+                "LDR: RtlGetActiveActivationContext() failed; ntstatus = "
+                "0x%08lx\n",
+                Status);
+            return Status;
+        }
     }
 
     /* Activate the ActCtx */
@@ -775,10 +784,9 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
             }
 
             /* Check if Application Verifier was enabled */
-            if (Peb->NtGlobalFlag & FLG_HEAP_ENABLE_TAIL_CHECK)
+            if (Peb->NtGlobalFlag & FLG_APPLICATION_VERIFIER)
             {
-                /* FIXME */
-                DPRINT1("We don't support Application Verifier yet!\n");
+                AVrfDllLoadNotification(LdrEntry);
             }
 
             /* Just to be safe */
@@ -789,26 +797,34 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     /* Release the activation context */
     RtlDeactivateActivationContextUnsafeFast(&ActCtx);
 
+    DPRINT("LdrpWalkImportDescriptor - END (%wZ %p)\n", &LdrEntry->BaseDllName, LdrEntry);
+
     /* Return status */
     return Status;
 }
 
-/* FIXME: This function is missing SxS support and has wrong prototype */
 NTSTATUS
 NTAPI
 LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,
                      IN LPSTR ImportName,
-                     IN PVOID DllBase,
                      OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry,
                      OUT PBOOLEAN Existing)
 {
     ANSI_STRING AnsiString;
     PUNICODE_STRING ImpDescName;
+    const WCHAR *p;
+    BOOLEAN GotExtension;
+    WCHAR c;
     NTSTATUS Status;
     PPEB Peb = RtlGetCurrentPeb();
     PTEB Teb = NtCurrentTeb();
+    UNICODE_STRING RedirectedImpDescName;
+    BOOLEAN RedirectedDll;
+
+    DPRINT("LdrpLoadImportModule('%S' '%s' %p %p)\n", DllPath, ImportName, DataTableEntry, Existing);
 
-    DPRINT("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBase, DataTableEntry, Existing);
+    RedirectedDll = FALSE;
+    RtlInitEmptyUnicodeString(&RedirectedImpDescName, NULL, 0);
 
     /* Convert import descriptor name to unicode string */
     ImpDescName = &Teb->StaticUnicodeString;
@@ -816,16 +832,84 @@ LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,
     Status = RtlAnsiStringToUnicodeString(ImpDescName, &AnsiString, FALSE);
     if (!NT_SUCCESS(Status)) return Status;
 
+    /* Find the extension, if present */
+    p = ImpDescName->Buffer + ImpDescName->Length / sizeof(WCHAR) - 1;
+    GotExtension = FALSE;
+    while (p >= ImpDescName->Buffer)
+    {
+        c = *p--;
+        if (c == L'.')
+        {
+            GotExtension = TRUE;
+            break;
+        }
+        else if (c == L'\\')
+        {
+            break;
+        }
+    }
+
+    /* If no extension was found, add the default extension */
+    if (!GotExtension)
+    {
+        /* Check that we have space to add one */
+        if ((ImpDescName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL)) >=
+            sizeof(Teb->StaticUnicodeBuffer))
+        {
+            /* No space to add the extension */
+            DbgPrintEx(DPFLTR_LDR_ID,
+                       DPFLTR_ERROR_LEVEL,
+                       "LDR: %s - Dll name missing extension; with extension "
+                       "added the name is too long\n"
+                       "   ImpDescName: (@ %p) \"%wZ\"\n"
+                       "   ImpDescName->Length: %u\n",
+                       __FUNCTION__,
+                       ImpDescName,
+                       ImpDescName,
+                       ImpDescName->Length);
+            return STATUS_NAME_TOO_LONG;
+        }
+
+        /* Add it. Needs to be null terminated, thus the length check above */
+        (VOID)RtlAppendUnicodeStringToString(ImpDescName,
+                                             &LdrApiDefaultExtension);
+    }
+
+    /* Check if the SxS Assemblies specify another file */
+    Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
+                                                      ImpDescName,
+                                                      &LdrApiDefaultExtension,
+                                                      NULL,
+                                                      &RedirectedImpDescName,
+                                                      &ImpDescName,
+                                                      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 */
+        DPRINT1("LDR: RtlDosApplyFileIsolationRedirection_Ustr failed  with status %x for dll %wZ\n", Status, ImpDescName);
+        goto done;
+    }
+
     /* Check if it's loaded */
     if (LdrpCheckForLoadedDll(DllPath,
                               ImpDescName,
                               TRUE,
-                              FALSE,
+                              RedirectedDll,
                               DataTableEntry))
     {
         /* It's already existing in the list */
         *Existing = TRUE;
-        return STATUS_SUCCESS;
+        Status = STATUS_SUCCESS;
+        goto done;
     }
 
     /* We're loading it for the first time */
@@ -837,10 +921,13 @@ LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,
                         ImpDescName->Buffer,
                         NULL,
                         TRUE,
-                        FALSE,
+                        RedirectedDll,
                         DataTableEntry);
-
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("LDR: LdrpMapDll failed  with status %x for dll %wZ\n", Status, ImpDescName);
+        goto done;
+    }
 
     /* Walk its import descriptor table */
     Status = LdrpWalkImportDescriptor(DllPath,
@@ -849,9 +936,12 @@ LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,
     {
         /* Add it to the in-init-order list in case of failure */
         InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
-                       &(*DataTableEntry)->InInitializationOrderModuleList);
+                       &(*DataTableEntry)->InInitializationOrderLinks);
     }
 
+done:
+    RtlFreeUnicodeString(&RedirectedImpDescName);
+
     return Status;
 }
 
@@ -872,7 +962,7 @@ LdrpSnapThunk(IN PVOID ExportBase,
     PIMAGE_IMPORT_BY_NAME AddressOfData;
     PULONG NameTable;
     PUSHORT OrdinalTable;
-    LPSTR ImportName = NULL;
+    LPSTR ImportName = NULL, DotPosition;
     USHORT Hint;
     NTSTATUS Status;
     ULONG_PTR HardErrorParameters[3];
@@ -938,14 +1028,14 @@ FailurePath:
         /* Is this a static snap? */
         if (Static)
         {
+            RtlInitAnsiString(&TempString, DllName ? DllName : "Unknown");
             /* Inform the debug log */
             if (IsOrdinal)
-                DPRINT1("Failed to snap ordinal 0x%x\n", OriginalOrdinal);
+                DPRINT1("Failed to snap ordinal %Z!0x%x\n", &TempString, OriginalOrdinal);
             else
-                DPRINT1("Failed to snap %s\n", ImportName);
+                DPRINT1("Failed to snap %Z!%s\n", &TempString, ImportName);
 
             /* These are critical errors. Setup a string for the DLL name */
-            RtlInitAnsiString(&TempString, DllName ? DllName : "Unknown");
             RtlAnsiStringToUnicodeString(&HardErrorDllName, &TempString, TRUE);
 
             /* Set it as the parameter */
@@ -1027,8 +1117,14 @@ FailurePath:
         {
             /* Get the Import and Forwarder Names */
             ImportName = (LPSTR)Thunk->u1.Function;
+
+            DotPosition = strchr(ImportName, '.');
+            ASSERT(DotPosition != NULL);
+            if (!DotPosition)
+                goto FailurePath;
+
             ForwarderName.Buffer = ImportName;
-            ForwarderName.Length = (USHORT)(strchr(ImportName, '.') - ImportName);
+            ForwarderName.Length = (USHORT)(DotPosition - ImportName);
             ForwarderName.MaximumLength = ForwarderName.Length;
             Status = RtlAnsiStringToUnicodeString(&TempUString,
                                                   &ForwarderName,
@@ -1037,13 +1133,44 @@ FailurePath:
             /* Make sure the conversion was OK */
             if (NT_SUCCESS(Status))
             {
-                /* Load the forwarder, free the temp string */
-                Status = LdrpLoadDll(FALSE,
+                WCHAR StringBuffer[MAX_PATH];
+                UNICODE_STRING StaticString, *RedirectedImportName;
+                BOOLEAN Redirected = FALSE;
+
+                RtlInitEmptyUnicodeString(&StaticString, StringBuffer, sizeof(StringBuffer));
+
+                /* Check if the SxS Assemblies specify another file */
+                Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
+                                                                  &TempUString,
+                                                                  &LdrApiDefaultExtension,
+                                                                  &StaticString,
+                                                                  NULL,
+                                                                  &RedirectedImportName,
+                                                                  NULL,
+                                                                  NULL,
+                                                                  NULL);
+                if (NT_SUCCESS(Status))
+                {
+                    if (ShowSnaps)
+                    {
+                        DPRINT1("LDR: %Z got redirected to %wZ\n", &ForwarderName, RedirectedImportName);
+                    }
+                    /* Let Ldrp know */
+                    Redirected = TRUE;
+                }
+                else
+                {
+                    RedirectedImportName = &TempUString;
+                }
+
+                /* Load the forwarder */
+                Status = LdrpLoadDll(Redirected,
                                      NULL,
                                      NULL,
-                                     &TempUString,
+                                     RedirectedImportName,
                                      &ForwarderHandle,
                                      FALSE);
+
                 RtlFreeUnicodeString(&TempUString);
             }
 
@@ -1072,6 +1199,7 @@ FailurePath:
             {
                 /* Import by name */
                 ForwardName = &ForwarderName;
+                ForwardOrdinal = 0;
             }
 
             /* Get the pointer */