#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
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;
-
- DPRINT("LdrpSnapIAT(%wZ %wZ %p %d)\n", &ExportLdrEntry->BaseDllName, &ImportLdrEntry->BaseDllName, IatEntry, EntriesValid);
+ PIMAGE_EXPORT_DIRECTORY ExportDirectory;
+ LPSTR ImportName;
+ ULONG ForwarderChain, i, Rva, OldProtect, IatSize, ExportSize;
+ SIZE_T ImportSize;
+ DPRINT("LdrpSnapIAT(%wZ %wZ %p %u)\n", &ExportLdrEntry->BaseDllName, &ImportLdrEntry->BaseDllName, IatEntry, EntriesValid);
/* Get export directory */
ExportDirectory = RtlImageDirectoryEntryToData(ExportLdrEntry->DllBase,
&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,
{
/* 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 */
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;
}
/* 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;
&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)
NTAPI
LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
IN PLDR_DATA_TABLE_ENTRY LdrEntry,
- IN PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry,
+ IN PIMAGE_BOUND_IMPORT_DESCRIPTOR *BoundEntryPtr,
IN PIMAGE_BOUND_IMPORT_DESCRIPTOR FirstEntry)
{
LPSTR ImportName = NULL, BoundImportName, ForwarderName;
PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
PLDR_DATA_TABLE_ENTRY DllLdrEntry, ForwarderLdrEntry;
PIMAGE_BOUND_FORWARDER_REF ForwarderEntry;
+ PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry;
PPEB Peb = NtCurrentPeb();
ULONG i, IatSize;
+ /* Get the pointer to the bound entry */
+ BoundEntry = *BoundEntryPtr;
+
/* Get the name's VA */
- BoundImportName = (LPSTR)(BoundEntry + BoundEntry->OffsetModuleName);
+ BoundImportName = (LPSTR)FirstEntry + BoundEntry->OffsetModuleName;
/* Show debug mesage */
if (ShowSnaps)
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has stale binding to %s\n",
- &DllLdrEntry->BaseDllName,
+ &LdrEntry->BaseDllName,
BoundImportName);
}
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has correct binding to %s\n",
- &DllLdrEntry->BaseDllName,
+ &LdrEntry->BaseDllName,
BoundImportName);
}
for (i = 0; i < BoundEntry->NumberOfModuleForwarderRefs; i++)
{
/* Get the name */
- ForwarderName = (LPSTR)(FirstEntry + ForwarderEntry->OffsetModuleName);
+ ForwarderName = (LPSTR)FirstEntry + ForwarderEntry->OffsetModuleName;
/* Show debug message */
if (ShowSnaps)
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has stale binding to %s\n",
- &ForwarderLdrEntry->BaseDllName,
+ &LdrEntry->BaseDllName,
ForwarderName);
}
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has correct binding to %s\n",
- &ForwarderLdrEntry->BaseDllName,
+ &LdrEntry->BaseDllName,
ForwarderName);
}
if (Stale)
{
/* It was, so find the IAT entry for it */
+ ++LdrpNormalSnap;
ImportEntry = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
if (!_stricmp(ImportName, BoundImportName)) break;
/* Move to next entry */
- ImportEntry += 1;
+ ImportEntry++;
}
/* If we didn't find a name, fail */
Quickie:
/* Write where we are now and return */
- *BoundEntry = *FirstEntry;
+ *BoundEntryPtr = FirstEntry;
return Status;
}
/* Parse this descriptor */
Status = LdrpHandleOneNewFormatImportDescriptor(DllPath,
LdrEntry,
- BoundEntry,
+ &BoundEntry,
FirstEntry);
if (!NT_SUCCESS(Status)) return Status;
}
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;
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)
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 */
&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;
}
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)
{
- UNIMPLEMENTED;
- return 0;
+ LONG Start, End, Next, CmpResult;
+
+ /* Use classical binary search to find the ordinal */
+ Start = Next = 0;
+ End = NumberOfNames - 1;
+ while (End >= Start)
+ {
+ /* Next will be exactly between Start and End */
+ Next = (Start + End) >> 1;
+
+ /* Compare this name with the one we need to find */
+ CmpResult = strcmp(ImportName, (PCHAR)((ULONG_PTR)ExportBase + NameTable[Next]));
+
+ /* We found our entry if result is 0 */
+ if (!CmpResult) break;
+
+ /* We didn't find, update our range then */
+ if (CmpResult < 0)
+ {
+ End = Next - 1;
+ }
+ else if (CmpResult > 0)
+ {
+ Start = Next + 1;
+ }
+ }
+
+ /* If end is before start, then the search failed */
+ if (End < Start) return -1;
+
+ /* Return found name */
+ return OrdinalTable[Next];
}
NTSTATUS
PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry = NULL;
PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
ULONG BoundSize, IatSize;
-DPRINT1("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry);
+ DPRINT("LdrpWalkImportDescriptor('%S' %p)\n", DllPath, LdrEntry);
+
/* Set up the Act Ctx */
+ RtlZeroMemory(&ActCtx, sizeof(ActCtx));
ActCtx.Size = sizeof(ActCtx);
- ActCtx.Frame.Flags = 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)
/* 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,
LdrEntry->EntryPointActivationContext);
- /* Check if we were directed */
+ /* Check if we were redirected */
if (!(LdrEntry->Flags & LDRP_REDIRECTED))
{
/* Get the Bound IAT */
&IatSize);
/* Check if we got at least one */
- if (BoundEntry || ImportEntry)
+ if ((BoundEntry) || (ImportEntry))
{
/* Do we have a Bound IAT */
if (BoundEntry)
/* 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 */
return Status;
}
+/* FIXME: This function is missing SxS support and has wrong prototype */
NTSTATUS
NTAPI
LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,
NTSTATUS Status;
PPEB Peb = RtlGetCurrentPeb();
PTEB Teb = NtCurrentTeb();
-DPRINT1("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBase, DataTableEntry, Existing);
+
+ DPRINT("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBase, DataTableEntry, Existing);
+
/* Convert import descriptor name to unicode string */
ImpDescName = &Teb->StaticUnicodeString;
RtlInitAnsiString(&AnsiString, ImportName);
/* Map it */
Status = LdrpMapDll(DllPath,
- ImpDescName->Buffer,
NULL,
+ ImpDescName->Buffer,
NULL,
TRUE,
FALSE,
/* Is this a static snap? */
if (Static)
{
+ /* Inform the debug log */
+ if (IsOrdinal)
+ DPRINT1("Failed to snap ordinal 0x%x\n", OriginalOrdinal);
+ else
+ DPRINT1("Failed to snap %s\n", ImportName);
+
/* These are critical errors. Setup a string for the DLL name */
RtlInitAnsiString(&TempString, DllName ? DllName : "Unknown");
RtlAnsiStringToUnicodeString(&HardErrorDllName, &TempString, TRUE);
/* Return ordinal error */
RtlRaiseStatus(STATUS_ORDINAL_NOT_FOUND);
}
+ else
+ {
+ /* Inform the debug log */
+ if (IsOrdinal)
+ DPRINT("Non-fatal: Failed to snap ordinal 0x%x\n", OriginalOrdinal);
+ else
+ DPRINT("Non-fatal: Failed to snap %s\n", ImportName);
+ }
/* Set this as a bad DLL */
Thunk->u1.Function = (ULONG_PTR)0xffbadd11;