[BASESRV-CONSRV-WINSRV]
[reactos.git] / dll / ntdll / ldr / ldrpe.c
index 41694d3..183c86e 100644 (file)
 #include <debug.h>
 
 /* GLOBALS *******************************************************************/
-ULONG LdrpFatalHardErrorCount;
-PVOID LdrpManifestProberRoutine;
 
-/* PROTOTYPES ****************************************************************/
+PVOID LdrpManifestProberRoutine;
+ULONG LdrpNormalSnap;
 
-#define IMAGE_REL_BASED_HIGH3ADJ 11
+/* FUNCTIONS *****************************************************************/
 
-NTSTATUS
+VOID
 NTAPI
-LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,
-                     IN LPSTR ImportName,
-                     IN PVOID DllBase,
-                     OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry,
-                     OUT PBOOLEAN Existing);
+AVrfPageHeapDllNotification(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
+{
+    /* Check if page heap dll notification is turned on */
+    if (!(RtlpDphGlobalFlags & DPH_FLAG_DLL_NOTIFY))
+        return;
 
-/* FUNCTIONS *****************************************************************/
+    /* We don't support this flag currently */
+    UNIMPLEMENTED;
+}
 
 NTSTATUS
 NTAPI
@@ -37,21 +38,15 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
             IN PIMAGE_IMPORT_DESCRIPTOR IatEntry,
             IN BOOLEAN EntriesValid)
 {
-    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
-    ULONG ExportSize;
     PVOID Iat;
-    SIZE_T ImportSize;
-    ULONG IatSize;
-    //PPEB Peb = NtCurrentPeb();
     NTSTATUS Status;
     PIMAGE_THUNK_DATA OriginalThunk, FirstThunk;
-    LPSTR ImportName;
-    ULONG ForwarderChain;
     PIMAGE_NT_HEADERS NtHeader;
     PIMAGE_SECTION_HEADER SectionHeader;
-    ULONG i, Rva;
-    ULONG OldProtect;
-
+    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
+    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);
 
     /* Get export directory */
@@ -61,7 +56,13 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
                                                    &ExportSize);
 
     /* Make sure it has one */
-    if (!ExportDirectory) return STATUS_INVALID_IMAGE_FORMAT;
+    if (!ExportDirectory)
+    {
+        /* Fail */
+        DbgPrint("LDR: %wZ doesn't contain an EXPORT table\n",
+                 &ExportLdrEntry->BaseDllName);
+        return STATUS_INVALID_IMAGE_FORMAT;
+    }
 
     /* Get the IAT */
     Iat = RtlImageDirectoryEntryToData(ImportLdrEntry->DllBase,
@@ -75,6 +76,7 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
     {
         /* Get the NT Header and the first section */
         NtHeader = RtlImageNtHeader(ImportLdrEntry->DllBase);
+        if (!NtHeader) return STATUS_INVALID_IMAGE_FORMAT;
         SectionHeader = IMAGE_FIRST_SECTION(NtHeader);
 
         /* Get the RVA of the import directory */
@@ -99,8 +101,7 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
                     IatSize = SectionHeader->Misc.VirtualSize;
 
                     /* Deal with Watcom and other retarded compilers */
-                    if (!IatSize)
-                        IatSize = SectionHeader->SizeOfRawData;
+                    if (!IatSize) IatSize = SectionHeader->SizeOfRawData;
 
                     /* Found it, get out */
                     break;
@@ -112,7 +113,14 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
         }
 
         /* If we still don't have an IAT, that's bad */
-        if (!Iat) return STATUS_INVALID_IMAGE_FORMAT;
+        if (!Iat)
+        {
+            /* Fail */
+            DbgPrint("LDR: Unable to unprotect IAT for %wZ (Image Base %p)\n",
+                     &ImportLdrEntry->BaseDllName,
+                     ImportLdrEntry->DllBase);
+            return STATUS_INVALID_IMAGE_FORMAT;
+        }
 
         /* Set the right size */
         ImportSize = IatSize;
@@ -124,7 +132,14 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
                                     &ImportSize,
                                     PAGE_READWRITE,
                                     &OldProtect);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        DbgPrint("LDR: Unable to unprotect IAT for %wZ (Status %x)\n",
+                 &ImportLdrEntry->BaseDllName,
+                 Status);
+        return Status;
+    }
 
     /* Check if the Thunks are already valid */
     if (EntriesValid)
@@ -410,6 +425,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     if (Stale)
     {
         /* It was, so find the IAT entry for it */
+        ++LdrpNormalSnap;
         ImportEntry = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
                                                    TRUE,
                                                    IMAGE_DIRECTORY_ENTRY_IMPORT,
@@ -511,22 +527,21 @@ NTSTATUS
 NTAPI
 LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
                                        IN PLDR_DATA_TABLE_ENTRY LdrEntry,
-                                       IN PIMAGE_IMPORT_DESCRIPTOR ImportEntry)
+                                       IN PIMAGE_IMPORT_DESCRIPTOR *ImportEntry)
 {
-    //ULONG IatSize, i;
     LPSTR ImportName;
     NTSTATUS Status;
-    BOOLEAN AlreadyLoaded = FALSE, StaticEntriesValid = FALSE, SkipSnap = FALSE;
+    BOOLEAN AlreadyLoaded = FALSE;
     PLDR_DATA_TABLE_ENTRY DllLdrEntry;
     PIMAGE_THUNK_DATA FirstThunk;
     PPEB Peb = NtCurrentPeb();
 
     /* Get the import name's VA */
-    ImportName = (LPSTR)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->Name);
+    ImportName = (LPSTR)((ULONG_PTR)LdrEntry->DllBase + (*ImportEntry)->Name);
 
     /* Get the first thunk */
     FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)LdrEntry->DllBase +
-                                     ImportEntry->FirstThunk);
+                                     (*ImportEntry)->FirstThunk);
 
     /* Make sure it's valid */
     if (!FirstThunk->u1.Function) goto SkipEntry;
@@ -545,7 +560,20 @@ LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
                                   LdrEntry->DllBase,
                                   &DllLdrEntry,
                                   &AlreadyLoaded);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        if (ShowSnaps)
+        {
+            DbgPrint("LDR: LdrpWalkImportTable - LdrpLoadImportModule failed "
+                     "on import %s with status %x\n",
+                     ImportName,
+                     Status);
+        }
+
+        /* Return */
+        return Status;
+    }
 
     /* Show debug message */
     if (ShowSnaps)
@@ -555,41 +583,8 @@ LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
                 ImportName);
     }
 
-    /* Check if the image was bound when compiled */
-    if (ImportEntry->OriginalFirstThunk)
-    {
-        /* It was, so check if the static IAT entries are still valid */
-        if ((ImportEntry->TimeDateStamp) &&
-            (ImportEntry->TimeDateStamp == DllLdrEntry->TimeDateStamp) &&
-            (!(DllLdrEntry->Flags & LDRP_IMAGE_NOT_AT_BASE)))
-        {
-            /* Show debug message */
-            if (ShowSnaps)
-            {
-                DPRINT1("LDR: Snap bypass %s from %wZ\n",
-                        ImportName,
-                        &LdrEntry->BaseDllName);
-            }
-
-            /*
-             * They are still valid, so we can skip snapping them.
-             * Additionally, if we have no forwarders, we are totally
-             * done.
-             */
-            if (ImportEntry->ForwarderChain == -1)
-            {
-                /* Totally skip LdrpSnapIAT */
-                SkipSnap = TRUE;
-            }
-            else
-            {
-                /* Set this so LdrpSnapIAT will only do forwarders */
-                StaticEntriesValid = TRUE;
-            }
-        }
-    }
-
     /* Check if it wasn't already loaded */
+    ++LdrpNormalSnap;
     if (!AlreadyLoaded)
     {
         /* Add the DLL to our list */
@@ -597,18 +592,25 @@ LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
                        &DllLdrEntry->InInitializationOrderModuleList);
     }
 
-    /* Check if we should snap at all */
-    if (!SkipSnap)
+    /* Now snap the IAT Entry */
+    Status = LdrpSnapIAT(DllLdrEntry, LdrEntry, *ImportEntry, FALSE);
+    if (!NT_SUCCESS(Status))
     {
-        /* Now snap the IAT Entry */
-        Status = LdrpSnapIAT(DllLdrEntry,
-                             LdrEntry,
-                             ImportEntry,
-                             StaticEntriesValid);
-        if (!NT_SUCCESS(Status)) return Status;
+        /* Fail */
+        if (ShowSnaps)
+        {
+            DbgPrint("LDR: LdrpWalkImportTable - LdrpSnapIAT #2 failed with "
+                     "status %x\n",
+                     Status);
+        }
+
+        /* Return */
+        return Status;
     }
 
 SkipEntry:
+    /* Move on */
+    (*ImportEntry)++;
     return STATUS_SUCCESS;
 }
 
@@ -621,34 +623,31 @@ LdrpHandleOldFormatImportDescriptors(IN LPWSTR DllPath OPTIONAL,
     NTSTATUS Status;
 
     /* Check for Name and Thunk */
-    while (ImportEntry->Name && ImportEntry->FirstThunk)
+    while ((ImportEntry->Name) && (ImportEntry->FirstThunk))
     {
         /* Parse this descriptor */
         Status = LdrpHandleOneOldFormatImportDescriptor(DllPath,
                                                         LdrEntry,
-                                                        ImportEntry);
+                                                        &ImportEntry);
         if (!NT_SUCCESS(Status)) return Status;
-
-        /* Move to the next entry */
-        ImportEntry++;
     }
 
     /* Done */
     return STATUS_SUCCESS;
 }
 
-USHORT NTAPI
-LdrpNameToOrdinal(LPSTR ImportName,
-                  ULONG NumberOfNames,
-                  PVOID ExportBase,
-                  PULONG NameTable,
-                  PUSHORT OrdinalTable)
+USHORT
+NTAPI
+LdrpNameToOrdinal(IN LPSTR ImportName,
+                  IN ULONG NumberOfNames,
+                  IN PVOID ExportBase,
+                  IN PULONG NameTable,
+                  IN PUSHORT OrdinalTable)
 {
-    ULONG Start, End, Next;
-    LONG CmpResult;
+    LONG Start, End, Next, CmpResult;
 
     /* Use classical binary search to find the ordinal */
-    Start = 0;
+    Start = Next = 0;
     End = NumberOfNames - 1;
     while (End >= Start)
     {
@@ -663,9 +662,13 @@ LdrpNameToOrdinal(LPSTR ImportName,
 
         /* We didn't find, update our range then */
         if (CmpResult < 0)
+        {
             End = Next - 1;
+        }
         else if (CmpResult > 0)
+        {
             Start = Next + 1;
+        }
     }
 
     /* If end is before start, then the search failed */
@@ -686,13 +689,12 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry = NULL;
     PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
     ULONG BoundSize, IatSize;
-
     DPRINT("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry);
 
     /* Set up the Act Ctx */
+    RtlZeroMemory(&ActCtx, sizeof(ActCtx));
     ActCtx.Size = sizeof(ActCtx);
-    ActCtx.Format = 1;
-    RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
+    ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER;
 
     /* Check if we have a manifest prober routine */
     if (LdrpManifestProberRoutine)
@@ -705,7 +707,16 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
 
     /* Get the Active ActCtx */
     Status = RtlGetActiveActivationContext(&LdrEntry->EntryPointActivationContext);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+    {
+        /* Exit */
+        DbgPrintEx(51, // DPFLTR_SXS_ID
+                   DPFLTR_WARNING_LEVEL,
+                   "LDR: RtlGetActiveActivationContext() failed; ntstatus = "
+                   "0x%08lx\n",
+                   Status);
+        return Status;
+    }
 
     /* Activate the ActCtx */
     RtlActivateActivationContextUnsafeFast(&ActCtx,
@@ -728,7 +739,7 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
                                                &IatSize);
 
     /* Check if we got at least one */
-    if (BoundEntry || ImportEntry)
+    if ((BoundEntry) || (ImportEntry))
     {
         /* Do we have a Bound IAT */
         if (BoundEntry)
@@ -759,8 +770,8 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
             /* Check if Page Heap was enabled */
             if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS)
             {
-                /* FIXME */
-                DPRINT1("We don't support Page Heaps yet!\n");
+                /* Initialize target DLL */
+                AVrfPageHeapDllNotification(LdrEntry);
             }
 
             /* Check if Application Verifier was enabled */
@@ -782,6 +793,7 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
     return Status;
 }
 
+/* FIXME: This function is missing SxS support and has wrong prototype */
 NTSTATUS
 NTAPI
 LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,