-/* $Id: loader.c,v 1.112 2002/06/14 07:46:02 ekohl Exp $
- *
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ldr/loader.c
* PURPOSE: Loaders for PE executables
+ *
* PROGRAMMERS: Jean Michault
* Rex Jolliff (rex@lvcablemodem.com)
* Jason Filby (jasonfilby@yahoo.com)
* Casper S. Hornstrup (chorns@users.sourceforge.net)
- * UPDATE HISTORY:
- * DW 22/05/98 Created
- * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
- * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
- * RJJ 10/12/98 Rolled in David's code to load COFF drivers
- * JM 14/12/98 Built initial PE user module loader
- * RJJ 06/03/99 Moved user PE loader into NTDLL
- * JF 26/01/2000 Recoded some parts to retrieve export details correctly
- * DW 27/06/2000 Removed redundant header files
- * CSH 11/04/2001 Added automatic loading of module symbols if they exist
*/
/* INCLUDES *****************************************************************/
-#include <limits.h>
-#include <ddk/ntddk.h>
-#include <roscfg.h>
-#include <internal/module.h>
-#include <internal/ntoskrnl.h>
-#include <internal/kd.h>
-#include <internal/io.h>
-#include <internal/mm.h>
-#include <internal/ps.h>
-#include <internal/ldr.h>
-#include <internal/pool.h>
+#include <ntoskrnl.h>
#ifdef HALDBG
#include <internal/ntosdbg.h>
#else
+#ifdef __GNUC__
#define ps(args...)
+#else
+#define ps
+#endif /* __GNUC__ */
+#endif
+
+#if 0
+#undef ps
+#define ps(args...) DPRINT1(args)
#endif
#define NDEBUG
LIST_ENTRY ModuleListHead;
KSPIN_LOCK ModuleListLock;
+LDR_DATA_TABLE_ENTRY NtoskrnlModuleObject;
+LDR_DATA_TABLE_ENTRY HalModuleObject;
-LIST_ENTRY ModuleTextListHead;
-STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
-STATIC MODULE_TEXT_SECTION LdrHalTextSection;
ULONG_PTR LdrHalBase;
-#define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
-#define TAG_SYM_BUF TAG('S', 'Y', 'M', 'B')
-
/* FORWARD DECLARATIONS ******************************************************/
NTSTATUS
-LdrProcessModule(PVOID ModuleLoadBase,
- PUNICODE_STRING ModuleName,
- PMODULE_OBJECT *ModuleObject);
-
-PVOID
-LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
- char *Name,
- unsigned short Hint);
+LdrProcessModule (
+ PVOID ModuleLoadBase,
+ PUNICODE_STRING ModuleName,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject );
static VOID
-LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
- PUNICODE_STRING FullName);
+LdrpBuildModuleBaseName (
+ PUNICODE_STRING BaseName,
+ PUNICODE_STRING FullName );
static LONG
-LdrpCompareModuleNames(IN PUNICODE_STRING String1,
- IN PUNICODE_STRING String2);
+LdrpCompareModuleNames (
+ IN PUNICODE_STRING String1,
+ IN PUNICODE_STRING String2 );
/* PE Driver load support */
-static NTSTATUS LdrPEProcessModule(PVOID ModuleLoadBase,
- PUNICODE_STRING FileName,
- PMODULE_OBJECT *ModuleObject);
-static PVOID
-LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
- PCHAR Name,
- USHORT Hint);
+static NTSTATUS
+LdrPEProcessModule (
+ PVOID ModuleLoadBase,
+ PUNICODE_STRING FileName,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject );
static PVOID
-LdrSafePEGetExportAddress(PVOID ImportModuleBase,
- PCHAR Name,
- USHORT Hint);
+LdrPEGetExportByName (
+ PVOID BaseAddress,
+ PUCHAR SymbolName,
+ WORD Hint );
static PVOID
-LdrPEFixupForward(PCHAR ForwardName);
+LdrPEFixupForward ( PCHAR ForwardName );
+
+static NTSTATUS
+LdrPEPerformRelocations (
+ PVOID DriverBase,
+ ULONG DriverSize );
+static NTSTATUS
+LdrPEFixupImports ( PLDR_DATA_TABLE_ENTRY Module );
/* FUNCTIONS *****************************************************************/
VOID
-LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
+NTAPI
+LdrInitDebug ( PLOADER_MODULE Module, PWCH Name )
{
- PLIST_ENTRY current_entry;
- MODULE_TEXT_SECTION* current;
-
- current_entry = ModuleTextListHead.Flink;
- while (current_entry != &ModuleTextListHead)
- {
- current =
- CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
- if (wcscmp(current->Name, Name) == 0)
- {
- break;
- }
- current_entry = current_entry->Flink;
- }
-
- if (current_entry == &ModuleTextListHead)
- {
- return;
- }
-
- current->SymbolsBase = (PVOID)Module->ModStart;
- current->SymbolsLength = Module->ModEnd - Module->ModStart;
}
VOID
-LdrInit1(VOID)
+INIT_FUNCTION
+NTAPI
+LdrInit1 ( VOID )
{
- PIMAGE_DOS_HEADER DosHeader;
- PIMAGE_FILE_HEADER FileHeader;
- PIMAGE_OPTIONAL_HEADER OptionalHeader;
- PIMAGE_SECTION_HEADER SectionList;
-
- InitializeListHead(&ModuleTextListHead);
-
- /* Setup ntoskrnl.exe text section */
- DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
- FileHeader =
- (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE +
- DosHeader->e_lfanew + sizeof(ULONG));
- OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
- ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
- SectionList = (PIMAGE_SECTION_HEADER)
- ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
- NtoskrnlTextSection.Base = KERNEL_BASE;
- NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
- SectionList[0].VirtualAddress;
- NtoskrnlTextSection.Name = KERNEL_MODULE_NAME;
- NtoskrnlTextSection.SymbolsBase = NULL;
- NtoskrnlTextSection.SymbolsLength = 0;
- InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
-
- /* Setup hal.dll text section */
- DosHeader = (PIMAGE_DOS_HEADER)LdrHalBase;
- FileHeader =
- (PIMAGE_FILE_HEADER) ((DWORD)LdrHalBase +
- DosHeader->e_lfanew + sizeof(ULONG));
- OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
- ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
- SectionList = (PIMAGE_SECTION_HEADER)
- ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
- LdrHalTextSection.Base = LdrHalBase;
- LdrHalTextSection.Length = SectionList[0].Misc.VirtualSize +
- SectionList[0].VirtualAddress;
- LdrHalTextSection.Name = HAL_MODULE_NAME;
- LdrHalTextSection.SymbolsBase = NULL;
- LdrHalTextSection.SymbolsLength = 0;
- InsertTailList(&ModuleTextListHead, &LdrHalTextSection.ListEntry);
+ /* Hook for KDB on initialization of the loader. */
+ KDB_LOADERINIT_HOOK(&NtoskrnlModuleObject, &HalModuleObject);
}
-
VOID
-LdrInitModuleManagement(VOID)
+INIT_FUNCTION
+NTAPI
+LdrInitModuleManagement ( VOID )
{
- PIMAGE_DOS_HEADER DosHeader;
- PMODULE_OBJECT ModuleObject;
-
- /* Initialize the module list and spinlock */
- InitializeListHead(&ModuleListHead);
- KeInitializeSpinLock(&ModuleListLock);
-
- /* Create module object for NTOSKRNL */
- ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
- assert(ModuleObject != NULL);
- RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
-
- /* Initialize ModuleObject data */
- ModuleObject->Base = (PVOID) KERNEL_BASE;
- ModuleObject->Flags = MODULE_FLAG_PE;
- RtlCreateUnicodeString(&ModuleObject->FullName,
- KERNEL_MODULE_NAME);
- LdrpBuildModuleBaseName(&ModuleObject->BaseName,
- &ModuleObject->FullName);
-
- DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
- ModuleObject->Image.PE.FileHeader =
- (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
- DosHeader->e_lfanew + sizeof(ULONG));
- ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
- ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
- ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
- ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
- ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
- ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
- DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
- ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
- ModuleObject->TextSection = &NtoskrnlTextSection;
-
- InsertTailList(&ModuleListHead,
- &ModuleObject->ListEntry);
-
- /* Create module object for HAL */
- ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
- assert(ModuleObject != NULL);
- RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
-
- /* Initialize ModuleObject data */
- ModuleObject->Base = (PVOID) LdrHalBase;
- ModuleObject->Flags = MODULE_FLAG_PE;
-
- RtlCreateUnicodeString(&ModuleObject->FullName,
- HAL_MODULE_NAME);
- LdrpBuildModuleBaseName(&ModuleObject->BaseName,
- &ModuleObject->FullName);
-
- DosHeader = (PIMAGE_DOS_HEADER) LdrHalBase;
- ModuleObject->Image.PE.FileHeader =
- (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
- DosHeader->e_lfanew + sizeof(ULONG));
- ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
- ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
- ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
- ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
- ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
- ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
- DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
- ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
- ModuleObject->TextSection = &LdrHalTextSection;
-
- InsertTailList(&ModuleListHead,
- &ModuleObject->ListEntry);
-}
+ PIMAGE_NT_HEADERS NtHeader;
+ /* Initialize the module list and spinlock */
+ InitializeListHead(&ModuleListHead);
+ KeInitializeSpinLock(&ModuleListLock);
-/*
- * load the auto config drivers.
- */
-#if 0
-static VOID
-LdrLoadAutoConfigDriver(LPWSTR RelativeDriverName)
-{
- WCHAR TmpFileName [MAX_PATH];
- CHAR Buffer [256];
- UNICODE_STRING DriverName;
- ULONG x, y, cx, cy;
-
- HalQueryDisplayParameters(&x, &y, &cx, &cy);
- RtlFillMemory(Buffer, x, ' ');
- Buffer[x] = '\0';
- HalSetDisplayParameters(0, y-1);
- HalDisplayString(Buffer);
-
- sprintf(Buffer, "Loading %S...\n",RelativeDriverName);
- HalSetDisplayParameters(0, y-1);
- HalDisplayString(Buffer);
- HalSetDisplayParameters(cx, cy);
- //CPRINT("Loading %S\n",RelativeDriverName);
-
- wcscpy(TmpFileName, L"\\SystemRoot\\system32\\drivers\\");
- wcscat(TmpFileName, RelativeDriverName);
- RtlInitUnicodeString (&DriverName, TmpFileName);
-
- NtLoadDriver(&DriverName);
-}
-#endif
+ /* Initialize ModuleObject for NTOSKRNL */
+ RtlZeroMemory(&NtoskrnlModuleObject, sizeof(LDR_DATA_TABLE_ENTRY));
+ NtoskrnlModuleObject.DllBase = (PVOID) KERNEL_BASE;
+ RtlInitUnicodeString(&NtoskrnlModuleObject.FullDllName, KERNEL_MODULE_NAME);
+ LdrpBuildModuleBaseName(&NtoskrnlModuleObject.BaseDllName, &NtoskrnlModuleObject.FullDllName);
-#ifdef KDBG
+ NtHeader = RtlImageNtHeader((PVOID)KERNEL_BASE);
+ NtoskrnlModuleObject.EntryPoint = (PVOID) ((ULONG_PTR) NtoskrnlModuleObject.DllBase + NtHeader->OptionalHeader.AddressOfEntryPoint);
+ DPRINT("ModuleObject:%08x entrypoint at %x\n", &NtoskrnlModuleObject, NtoskrnlModuleObject.EntryPoint);
+ NtoskrnlModuleObject.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
-BOOLEAN LdrpReadLine(PCHAR Line,
- ULONG LineSize,
- PVOID *Buffer,
- PULONG Size)
-{
- CHAR ch;
- PCHAR Block;
- ULONG Count;
+ InsertTailList(&ModuleListHead, &NtoskrnlModuleObject.InLoadOrderModuleList);
- if (*Size == 0)
- return FALSE;
+ /* Initialize ModuleObject for HAL */
+ RtlZeroMemory(&HalModuleObject, sizeof(LDR_DATA_TABLE_ENTRY));
+ HalModuleObject.DllBase = (PVOID) LdrHalBase;
- ch = ' ';
- Count = 0;
- Block = *Buffer;
- while ((*Size > 0) && (Count < LineSize) && ((ch = *Block) != (CHAR)13))
- {
- *Line = ch;
- Line++;
- Block++;
- Count++;
- *Size -= 1;
- }
- *Line = (CHAR)0;
+ RtlInitUnicodeString(&HalModuleObject.FullDllName, HAL_MODULE_NAME);
+ LdrpBuildModuleBaseName(&HalModuleObject.BaseDllName, &HalModuleObject.FullDllName);
- if (ch == (CHAR)13)
- {
- Block++;
- *Size -= 1;
- }
-
- if ((*Size > 0) && (*Block == (CHAR)10))
- {
- Block++;
- *Size -= 1;
- }
-
- *Buffer = Block;
-
- return TRUE;
-}
+ NtHeader = RtlImageNtHeader((PVOID)LdrHalBase);
+ HalModuleObject.EntryPoint = (PVOID) ((ULONG_PTR) HalModuleObject.DllBase + NtHeader->OptionalHeader.AddressOfEntryPoint);
+ DPRINT("ModuleObject:%08x entrypoint at %x\n", &HalModuleObject, HalModuleObject.EntryPoint);
+ HalModuleObject.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
-ULONG HexL(PCHAR Buffer)
-{
- CHAR ch;
- UINT i, j;
- ULONG Value;
-
- j = 32;
- i = 0;
- Value = 0;
- while ((j > 0) && ((ch = Buffer[i]) != ' '))
- {
- j -= 4;
- if ((ch >= '0') && (ch <= '9'))
- Value |= ((ch - '0') << j);
- if ((ch >= 'A') && (ch <= 'F'))
- Value |= ((10 + (ch - 'A')) << j);
- else
- if ((ch >= 'a') && (ch <= 'f'))
- Value |= ((10 + (ch - 'a')) << j);
- i++;
- }
- return Value;
+ InsertTailList(&ModuleListHead, &HalModuleObject.InLoadOrderModuleList);
}
-PSYMBOL LdrpParseLine(PCHAR Line,
- PULONG TextBase,
- PBOOLEAN TextBaseValid,
- PULONG Alignment)
-/*
- Line format: [ADDRESS] <TYPE> <NAME>
- TYPE:
- U = ?
- A = Image information
- t = Symbol in text segment
- T = Symbol in text segment
- d = Symbol in data segment
- D = Symbol in data segment
- b = Symbol in BSS segment
- B = Symbol in BSS segment
- ? = Unknown segment or symbol in unknown segment
-*/
+NTSTATUS
+NTAPI
+LdrpLoadImage (
+ PUNICODE_STRING DriverName,
+ PVOID *ModuleBase,
+ PVOID *SectionPointer,
+ PVOID *EntryPoint,
+ PVOID *ExportSectionPointer )
{
- ANSI_STRING AnsiString;
- CHAR Buffer[128];
- PSYMBOL Symbol;
- ULONG Address;
- PCHAR Str;
- CHAR Type;
-
- if ((Line[0] == (CHAR)0) || (Line[0] == ' '))
- return NULL;
+ PLDR_DATA_TABLE_ENTRY ModuleObject;
+ NTSTATUS Status;
- Address = HexL(Line);
-
- Line = strchr(Line, ' ');
- if (Line == NULL)
- return NULL;
-
- Line++;
- Type = *Line;
-
- Line = strchr(Line, ' ');
- if (Line == NULL)
- return NULL;
-
- Line++;
- Str = strchr(Line, ' ');
- if (Str == NULL)
- strcpy((char*)&Buffer, Line);
- else
- strncpy((char*)&Buffer, Line, Str - Line);
-
- if ((Type == 'A') && (strcmp((char*)&Buffer, "__section_alignment__")) == 0)
+ ModuleObject = LdrGetModuleObject(DriverName);
+ if (ModuleObject == NULL)
{
- *Alignment = Address;
- return NULL;
+ Status = LdrLoadModule(DriverName, &ModuleObject);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
}
- /* We only want symbols in the .text segment */
- if ((Type != 't') && (Type != 'T'))
- return NULL;
+ if (ModuleBase)
+ *ModuleBase = ModuleObject->DllBase;
- /* Discard other symbols we can't use */
- if ((Buffer[0] != '_') || ((Buffer[0] == '_') && (Buffer[1] == '_')))
- return NULL;
+ if (SectionPointer)
+ *SectionPointer = ModuleObject;
- Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
- if (!Symbol)
- return NULL;
+ if (EntryPoint)
+ *EntryPoint = ModuleObject->EntryPoint;
- Symbol->Next = NULL;
+ //if (ExportSectionPointer)
+ // *ExportSectionPointer = ModuleObject->
- Symbol->RelativeAddress = Address;
-
- RtlInitAnsiString(&AnsiString, (PCSZ)&Buffer);
- RtlAnsiStringToUnicodeString(&Symbol->Name, &AnsiString, TRUE);
+ return(STATUS_SUCCESS);
+}
- if (!(*TextBaseValid))
- {
- *TextBase = Address - *Alignment;
- *TextBaseValid = TRUE;
- }
- return Symbol;
+NTSTATUS
+NTAPI
+LdrpUnloadImage ( PVOID ModuleBase )
+{
+ return(STATUS_NOT_IMPLEMENTED);
}
-VOID LdrpLoadModuleSymbolsFromBuffer(
- PMODULE_OBJECT ModuleObject,
- PVOID Buffer,
- ULONG Length)
-/*
- Symbols must be sorted by address, e.g.
- "nm --numeric-sort module.sys > module.sym"
- */
-{
- PSYMBOL Symbol, CurrentSymbol = NULL;
- BOOLEAN TextBaseValid;
- BOOLEAN Valid;
- ULONG TextBase = 0;
- ULONG Alignment = 0;
- CHAR Line[256];
- ULONG Tmp;
- assert(ModuleObject);
+NTSTATUS
+NTAPI
+LdrpLoadAndCallImage ( PUNICODE_STRING ModuleName )
+{
+ PDRIVER_INITIALIZE DriverEntry;
+ PLDR_DATA_TABLE_ENTRY ModuleObject;
+ DRIVER_OBJECT DriverObject;
+ NTSTATUS Status;
- if (ModuleObject->TextSection == NULL)
+ ModuleObject = LdrGetModuleObject(ModuleName);
+ if (ModuleObject != NULL)
{
- ModuleObject->TextSection = &NtoskrnlTextSection;
+ return(STATUS_IMAGE_ALREADY_LOADED);
}
- if (ModuleObject->TextSection->Symbols.SymbolCount > 0)
+ Status = LdrLoadModule(ModuleName, &ModuleObject);
+ if (!NT_SUCCESS(Status))
{
- CPRINT("Symbols are already loaded for %wZ\n", &ModuleObject->BaseName);
- return;
+ return(Status);
}
- ModuleObject->TextSection->Symbols.SymbolCount = 0;
- ModuleObject->TextSection->Symbols.Symbols = NULL;
- TextBaseValid = FALSE;
- Valid = FALSE;
- while (LdrpReadLine((PCHAR)&Line, 256, &Buffer, &Length))
- {
- Symbol = LdrpParseLine((PCHAR)&Line, &Tmp, &Valid, &Alignment);
+ DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
- if ((Valid) && (!TextBaseValid))
- {
- TextBase = Tmp;
- TextBaseValid = TRUE;
- }
+ RtlZeroMemory(&DriverObject, sizeof(DriverObject));
+// DriverObject.DriverStart = ModuleObject->DllBase;
- if (Symbol != NULL)
- {
- Symbol->RelativeAddress -= TextBase;
+ Status = DriverEntry(&DriverObject, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ LdrUnloadModule(ModuleObject);
+ }
- if (ModuleObject->TextSection->Symbols.Symbols == NULL)
- ModuleObject->TextSection->Symbols.Symbols = Symbol;
- else
- CurrentSymbol->Next = Symbol;
+ return(Status);
+}
- CurrentSymbol = Symbol;
- ModuleObject->TextSection->Symbols.SymbolCount++;
- }
- }
+NTSTATUS
+NTAPI
+LdrLoadModule(
+ PUNICODE_STRING Filename,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject )
+{
+ PVOID ModuleLoadBase;
+ NTSTATUS Status;
+ HANDLE FileHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PLDR_DATA_TABLE_ENTRY Module;
+ FILE_STANDARD_INFORMATION FileStdInfo;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ *ModuleObject = NULL;
+
+ DPRINT("Loading Module %wZ...\n", Filename);
+
+ /* Open the Module */
+ InitializeObjectAttributes(&ObjectAttributes,
+ Filename,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ CHECKPOINT;
+ Status = ZwOpenFile(&FileHandle,
+ GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ CHECKPOINT;
+ if (!NT_SUCCESS(Status))
+ {
+ CPRINT("Could not open module file: %wZ (Status 0x%08lx)\n", Filename, Status);
+ return(Status);
+ }
+ CHECKPOINT;
+
+ /* Get the size of the file */
+ Status = ZwQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileStdInfo,
+ sizeof(FileStdInfo),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ CPRINT("Could not get file size\n");
+ NtClose(FileHandle);
+ return(Status);
+ }
+ CHECKPOINT;
+
+ /* Allocate nonpageable memory for driver */
+ ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
+ FileStdInfo.EndOfFile.u.LowPart,
+ TAG_DRIVER_MEM);
+ if (ModuleLoadBase == NULL)
+ {
+ CPRINT("Could not allocate memory for module");
+ NtClose(FileHandle);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+ CHECKPOINT;
+
+ /* Load driver into memory chunk */
+ Status = ZwReadFile(FileHandle,
+ 0, 0, 0,
+ &IoStatusBlock,
+ ModuleLoadBase,
+ FileStdInfo.EndOfFile.u.LowPart,
+ 0, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ CPRINT("Could not read module file into memory");
+ ExFreePool(ModuleLoadBase);
+ NtClose(FileHandle);
+ return(Status);
+ }
+ CHECKPOINT;
+
+ ZwClose(FileHandle);
+
+ Status = LdrProcessModule(ModuleLoadBase,
+ Filename,
+ &Module);
+ if (!NT_SUCCESS(Status))
+ {
+ CPRINT("Could not process module\n");
+ ExFreePool(ModuleLoadBase);
+ return(Status);
+ }
+
+ /* Cleanup */
+ ExFreePool(ModuleLoadBase);
+
+ *ModuleObject = Module;
+
+ /* Hook for KDB on loading a driver. */
+ KDB_LOADDRIVER_HOOK(Filename, Module);
+
+ return(STATUS_SUCCESS);
}
-VOID LdrpLoadUserModuleSymbolsFromBuffer(
- PLDR_MODULE ModuleObject,
- PVOID Buffer,
- ULONG Length)
-/*
- Symbols must be sorted by address, e.g.
- "nm --numeric-sort module.dll > module.sym"
- */
-{
- PSYMBOL Symbol, CurrentSymbol = NULL;
- BOOLEAN TextBaseValid;
- BOOLEAN Valid;
- ULONG TextBase = 0;
- ULONG Alignment = 0;
- CHAR Line[256];
- ULONG Tmp;
-
- if (ModuleObject->Symbols.SymbolCount > 0)
- {
- DPRINT("Symbols are already loaded for %wZ\n", &ModuleObject->BaseDllName);
- return;
- }
- ModuleObject->Symbols.SymbolCount = 0;
- ModuleObject->Symbols.Symbols = NULL;
- TextBaseValid = FALSE;
- Valid = FALSE;
- while (LdrpReadLine((PCHAR)&Line, 256, &Buffer, &Length))
- {
- Symbol = LdrpParseLine((PCHAR)&Line, &Tmp, &Valid, &Alignment);
+NTSTATUS
+NTAPI
+LdrUnloadModule ( PLDR_DATA_TABLE_ENTRY ModuleObject )
+{
+ KIRQL Irql;
- if ((Valid) && (!TextBaseValid))
- {
- TextBase = Tmp;
- TextBaseValid = TRUE;
- }
+ /* Remove the module from the module list */
+ KeAcquireSpinLock(&ModuleListLock,&Irql);
+ RemoveEntryList(&ModuleObject->InLoadOrderModuleList);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
- if (Symbol != NULL)
- {
- Symbol->RelativeAddress -= TextBase;
+ /* Hook for KDB on unloading a driver. */
+ KDB_UNLOADDRIVER_HOOK(ModuleObject);
- if (ModuleObject->Symbols.Symbols == NULL)
- ModuleObject->Symbols.Symbols = Symbol;
- else
- CurrentSymbol->Next = Symbol;
+ /* Free module section */
+ // MmFreeSection(ModuleObject->DllBase);
- CurrentSymbol = Symbol;
+ ExFreePool(ModuleObject->FullDllName.Buffer);
+ ExFreePool(ModuleObject);
- ModuleObject->Symbols.SymbolCount++;
- }
- }
+ return(STATUS_SUCCESS);
}
-VOID
-LdrpLoadModuleSymbols(PMODULE_OBJECT ModuleObject)
-{
- FILE_STANDARD_INFORMATION FileStdInfo;
- OBJECT_ATTRIBUTES ObjectAttributes;
- WCHAR TmpFileName[MAX_PATH];
- UNICODE_STRING Filename;
- LPWSTR Start, Ext;
- HANDLE FileHandle;
- PVOID FileBuffer;
- NTSTATUS Status;
- ULONG Length;
- IO_STATUS_BLOCK IoStatusBlock;
-
- ModuleObject->TextSection->Symbols.SymbolCount = 0;
- ModuleObject->TextSection->Symbols.Symbols = NULL;
-
- /* Get the path to the symbol store */
- wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
-
- /* Get the symbol filename from the module name */
- Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
- if (Start == NULL)
- Start = ModuleObject->BaseName.Buffer;
- else
- Start++;
-
- Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
- if (Ext != NULL)
- Length = Ext - Start;
- else
- Length = wcslen(Start);
-
- wcsncat(TmpFileName, Start, Length);
- wcscat(TmpFileName, L".sym");
- RtlInitUnicodeString(&Filename, TmpFileName);
-
- /* Open the file */
- InitializeObjectAttributes(&ObjectAttributes,
- &Filename,
- 0,
- NULL,
- NULL);
-
- Status = ZwOpenFile(&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Could not open symbol file: %wZ\n", &Filename);
- return;
- }
-
- CPRINT("Loading symbols from %wZ...\n", &Filename);
- /* Get the size of the file */
- Status = ZwQueryInformationFile(FileHandle,
- &IoStatusBlock,
- &FileStdInfo,
- sizeof(FileStdInfo),
- FileStandardInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Could not get file size\n");
- return;
- }
-
- /* Allocate nonpageable memory for symbol file */
- FileBuffer = ExAllocatePool(NonPagedPool,
- FileStdInfo.EndOfFile.u.LowPart);
+NTSTATUS
+LdrProcessModule(
+ PVOID ModuleLoadBase,
+ PUNICODE_STRING ModuleName,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject )
+{
+ PIMAGE_DOS_HEADER PEDosHeader;
- if (FileBuffer == NULL)
+ /* If MZ header exists */
+ PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
+ if (PEDosHeader->e_magic == IMAGE_DOS_SIGNATURE && PEDosHeader->e_lfanew != 0L)
{
- DPRINT("Could not allocate memory for symbol file\n");
- return;
+ return LdrPEProcessModule(ModuleLoadBase,
+ ModuleName,
+ ModuleObject);
}
-
- /* Load file into memory chunk */
- Status = ZwReadFile(FileHandle,
- 0, 0, 0,
- &IoStatusBlock,
- FileBuffer,
- FileStdInfo.EndOfFile.u.LowPart,
- 0, 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Could not read symbol file into memory\n");
- ExFreePool(FileBuffer);
- return;
- }
-
- ZwClose(FileHandle);
-
- LdrpLoadModuleSymbolsFromBuffer(ModuleObject,
- FileBuffer,
- FileStdInfo.EndOfFile.u.LowPart);
- ExFreePool(FileBuffer);
+ CPRINT("Module wasn't PE\n");
+ return STATUS_UNSUCCESSFUL;
}
-VOID LdrLoadUserModuleSymbols(PLDR_MODULE ModuleObject)
+NTSTATUS
+NTAPI
+LdrpQueryModuleInformation (
+ PVOID Buffer,
+ ULONG Size,
+ PULONG ReqSize )
{
- FILE_STANDARD_INFORMATION FileStdInfo;
- OBJECT_ATTRIBUTES ObjectAttributes;
- WCHAR TmpFileName[MAX_PATH];
- UNICODE_STRING Filename;
- LPWSTR Start, Ext;
- HANDLE FileHandle;
- PVOID FileBuffer;
- NTSTATUS Status;
- ULONG Length;
- IO_STATUS_BLOCK IoStatusBlock;
-
- ModuleObject->Symbols.SymbolCount = 0;
- ModuleObject->Symbols.Symbols = NULL;
-
- /* Get the path to the symbol store */
- wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
-
- /* Get the symbol filename from the module name */
- Start = wcsrchr(ModuleObject->BaseDllName.Buffer, L'\\');
- if (Start == NULL)
- Start = ModuleObject->BaseDllName.Buffer;
- else
- Start++;
-
- Ext = wcsrchr(ModuleObject->BaseDllName.Buffer, L'.');
- if (Ext != NULL)
- Length = Ext - Start;
- else
- Length = wcslen(Start);
-
- wcsncat(TmpFileName, Start, Length);
- wcscat(TmpFileName, L".sym");
- RtlInitUnicodeString(&Filename, TmpFileName);
-
- /* Open the file */
- InitializeObjectAttributes(&ObjectAttributes,
- &Filename,
- 0,
- NULL,
- NULL);
-
- Status = ZwOpenFile(&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Could not open symbol file: %wZ\n", &Filename);
- return;
- }
+ PLIST_ENTRY current_entry;
+ PLDR_DATA_TABLE_ENTRY current;
+ ULONG ModuleCount = 0;
+ PSYSTEM_MODULE_INFORMATION Smi;
+ ANSI_STRING AnsiName;
+ PCHAR p;
+ KIRQL Irql;
- CPRINT("Loading symbols from %wZ...\n", &Filename);
+ KeAcquireSpinLock(&ModuleListLock,&Irql);
- /* Get the size of the file */
- Status = ZwQueryInformationFile(FileHandle,
- &IoStatusBlock,
- &FileStdInfo,
- sizeof(FileStdInfo),
- FileStandardInformation);
- if (!NT_SUCCESS(Status))
+ /* calculate required size */
+ current_entry = ModuleListHead.Flink;
+ while (current_entry != (&ModuleListHead))
{
- DPRINT("Could not get file size\n");
- return;
+ ModuleCount++;
+ current_entry = current_entry->Flink;
}
- /* Allocate nonpageable memory for symbol file */
- FileBuffer = ExAllocatePool(NonPagedPool,
- FileStdInfo.EndOfFile.u.LowPart);
+ *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
+ (ModuleCount - 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY);
- if (FileBuffer == NULL)
+ if (Size < *ReqSize)
{
- DPRINT("Could not allocate memory for symbol file\n");
- return;
- }
-
- /* Load file into memory chunk */
- Status = ZwReadFile(FileHandle,
- 0, 0, 0,
- &IoStatusBlock,
- FileBuffer,
- FileStdInfo.EndOfFile.u.LowPart,
- 0, 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Could not read symbol file into memory\n");
- ExFreePool(FileBuffer);
- return;
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+ return(STATUS_INFO_LENGTH_MISMATCH);
}
- ZwClose(FileHandle);
+ /* fill the buffer */
+ memset(Buffer, '=', Size);
- LdrpLoadUserModuleSymbolsFromBuffer(ModuleObject,
- FileBuffer,
- FileStdInfo.EndOfFile.u.LowPart);
+ Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
+ Smi->Count = ModuleCount;
- ExFreePool(FileBuffer);
-}
-#endif /* KDBG */
+ ModuleCount = 0;
+ current_entry = ModuleListHead.Flink;
+ while (current_entry != (&ModuleListHead))
+ {
+ current = CONTAINING_RECORD(current_entry,LDR_DATA_TABLE_ENTRY,InLoadOrderModuleList);
+ Smi->Module[ModuleCount].Unknown1 = 0; /* Always 0 */
+ Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
+ Smi->Module[ModuleCount].Base = current->DllBase;
+ Smi->Module[ModuleCount].Size = current->SizeOfImage;
+ Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
+ Smi->Module[ModuleCount].Index = (USHORT)ModuleCount;
+ Smi->Module[ModuleCount].NameLength = 0;
+ Smi->Module[ModuleCount].LoadCount = 0; /* FIXME */
-#if 0
-VOID LdrLoadAutoConfigDrivers (VOID)
-{
+ AnsiName.Length = 0;
+ AnsiName.MaximumLength = 256;
+ AnsiName.Buffer = Smi->Module[ModuleCount].ImageName;
+ RtlUnicodeStringToAnsiString(&AnsiName,
+ ¤t->FullDllName,
+ FALSE);
-#ifdef KDBG
- NTSTATUS Status;
- UNICODE_STRING ModuleName;
- PMODULE_OBJECT ModuleObject;
+ p = strrchr(AnsiName.Buffer, '\\');
+ if (p == NULL)
+ {
+ Smi->Module[ModuleCount].PathLength = 0;
+ }
+ else
+ {
+ p++;
+ Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
+ }
- /* Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot
- is created after their module entries */
+ ModuleCount++;
+ current_entry = current_entry->Flink;
+ }
- RtlInitUnicodeString(&ModuleName, KERNEL_MODULE_NAME);
- Status = LdrFindModuleObject(&ModuleName, &ModuleObject);
- if (NT_SUCCESS(Status))
- {
- LdrpLoadModuleSymbols(ModuleObject);
- }
+ KeReleaseSpinLock(&ModuleListLock, Irql);
- RtlInitUnicodeString(&ModuleName, HAL_MODULE_NAME);
- Status = LdrFindModuleObject(&ModuleName, &ModuleObject);
- if (NT_SUCCESS(Status))
- {
- LdrpLoadModuleSymbols(ModuleObject);
- }
+ return(STATUS_SUCCESS);
+}
-#endif /* KDBG */
- /*
- * PCI bus driver
- */
- //LdrLoadAutoConfigDriver( L"pci.sys" );
+static VOID
+LdrpBuildModuleBaseName (
+ PUNICODE_STRING BaseName,
+ PUNICODE_STRING FullName )
+{
+ PWCHAR p;
- /*
- * Keyboard driver
- */
- LdrLoadAutoConfigDriver( L"keyboard.sys" );
-
- if ((KdDebuggerEnabled) && (KdDebugState & KD_DEBUG_PICE))
- {
- /*
- * Private ICE debugger
- */
- LdrLoadAutoConfigDriver( L"pice.sys" );
- }
-
- /*
- * Raw console driver
- */
- LdrLoadAutoConfigDriver( L"blue.sys" );
-
- /*
- *
- */
- LdrLoadAutoConfigDriver(L"vidport.sys");
-
-#if 0
- /*
- * Minix filesystem driver
- */
- LdrLoadAutoConfigDriver(L"minixfs.sys");
+ DPRINT("LdrpBuildModuleBaseName()\n");
+ DPRINT("FullName %wZ\n", FullName);
- /*
- * Mailslot filesystem driver
- */
- LdrLoadAutoConfigDriver(L"msfs.sys");
-#endif
- /*
- * Named pipe filesystem driver
- */
- LdrLoadAutoConfigDriver(L"npfs.sys");
+ p = wcsrchr(FullName->Buffer, L'\\');
+ if (p == NULL)
+ {
+ p = FullName->Buffer;
+ }
+ else
+ {
+ p++;
+ }
- /*
- * Mouse drivers
- */
-// LdrLoadAutoConfigDriver(L"l8042prt.sys");
- LdrLoadAutoConfigDriver(L"psaux.sys");
- LdrLoadAutoConfigDriver(L"mouclass.sys");
+ DPRINT("p %S\n", p);
- /*
- * Networking
- */
-#if 1
- /*
- * NDIS library
- */
- LdrLoadAutoConfigDriver(L"ndis.sys");
-#endif
+ RtlInitUnicodeString(BaseName, p);
}
-#endif
-NTSTATUS
-LdrpLoadImage(PUNICODE_STRING DriverName,
- PVOID *ModuleBase,
- PVOID *SectionPointer,
- PVOID *EntryPoint,
- PVOID *ExportSectionPointer)
+static LONG
+LdrpCompareModuleNames (
+ IN PUNICODE_STRING String1,
+ IN PUNICODE_STRING String2 )
{
- PMODULE_OBJECT ModuleObject;
- NTSTATUS Status;
+ ULONG len1, len2, i;
+ PWCHAR s1, s2, p;
+ WCHAR c1, c2;
- Status = LdrLoadModule(DriverName, &ModuleObject);
- if (!NT_SUCCESS(Status))
+ if (String1 && String2)
{
- return(Status);
- }
-
- if (ModuleBase)
- *ModuleBase = ModuleObject->Base;
-
-// if (SectionPointer)
-// *SectionPointer = ModuleObject->
+ /* Search String1 for last path component */
+ len1 = String1->Length / sizeof(WCHAR);
+ s1 = String1->Buffer;
+ for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
+ {
+ if (*p == L'\\')
+ {
+ if (i == String1->Length - sizeof(WCHAR))
+ {
+ s1 = NULL;
+ len1 = 0;
+ }
+ else
+ {
+ s1 = p + 1;
+ len1 = (String1->Length - i) / sizeof(WCHAR);
+ }
+ }
+ }
- if (EntryPoint)
- *EntryPoint = ModuleObject->EntryPoint;
+ /* Search String2 for last path component */
+ len2 = String2->Length / sizeof(WCHAR);
+ s2 = String2->Buffer;
+ for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
+ {
+ if (*p == L'\\')
+ {
+ if (i == String2->Length - sizeof(WCHAR))
+ {
+ s2 = NULL;
+ len2 = 0;
+ }
+ else
+ {
+ s2 = p + 1;
+ len2 = (String2->Length - i) / sizeof(WCHAR);
+ }
+ }
+ }
-// if (ExportSectionPointer)
-// *ExportSectionPointer = ModuleObject->
+ /* Compare last path components */
+ if (s1 && s2)
+ {
+ while (1)
+ {
+ c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
+ c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
+ if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
+ return(0);
+ if (!c1 || !c2 || c1 != c2)
+ return(c1 - c2);
+ }
+ }
+ }
- return(STATUS_SUCCESS);
+ return(0);
}
-
-NTSTATUS
-LdrpUnloadImage(PVOID ModuleBase)
+PLDR_DATA_TABLE_ENTRY
+NTAPI
+LdrGetModuleObject ( PUNICODE_STRING ModuleName )
{
- return(STATUS_NOT_IMPLEMENTED);
-}
+ PLDR_DATA_TABLE_ENTRY Module;
+ PLIST_ENTRY Entry;
+ KIRQL Irql;
+ DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName);
-NTSTATUS
-LdrpLoadAndCallImage(PUNICODE_STRING ModuleName)
-{
- PDRIVER_INITIALIZE DriverEntry;
- PMODULE_OBJECT ModuleObject;
- NTSTATUS Status;
+ KeAcquireSpinLock(&ModuleListLock,&Irql);
- Status = LdrLoadModule(ModuleName, &ModuleObject);
- if (!NT_SUCCESS(Status))
+ Entry = ModuleListHead.Flink;
+ while (Entry != &ModuleListHead)
{
- return(Status);
- }
+ Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
- DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
+ DPRINT("Comparing %wZ and %wZ\n",
+ &Module->BaseDllName,
+ ModuleName);
- Status = DriverEntry(NULL, NULL);
- if (!NT_SUCCESS(Status))
- {
- LdrUnloadModule(ModuleObject);
+ if (!LdrpCompareModuleNames(&Module->BaseDllName, ModuleName))
+ {
+ DPRINT("Module %wZ\n", &Module->BaseDllName);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+ return(Module);
+ }
+
+ Entry = Entry->Flink;
}
- return(Status);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+
+ DPRINT("Could not find module '%wZ'\n", ModuleName);
+
+ return(NULL);
}
-NTSTATUS
-LdrLoadModule(PUNICODE_STRING Filename,
- PMODULE_OBJECT *ModuleObject)
+/* ---------------------------------------------- PE Module support */
+
+static ULONG
+LdrLookupPageProtection (
+ PVOID PageStart,
+ PVOID DriverBase,
+ PIMAGE_FILE_HEADER PEFileHeader,
+ PIMAGE_SECTION_HEADER PESectionHeaders )
{
- PVOID ModuleLoadBase;
- NTSTATUS Status;
- HANDLE FileHandle;
- OBJECT_ATTRIBUTES ObjectAttributes;
- PMODULE_OBJECT Module;
- FILE_STANDARD_INFORMATION FileStdInfo;
- IO_STATUS_BLOCK IoStatusBlock;
-
- *ModuleObject = NULL;
-
- /* Check for module already loaded */
- Module = LdrGetModuleObject(Filename);
- if (Module != NULL)
- {
- *ModuleObject = Module;
- return(STATUS_SUCCESS);
- }
+ BOOLEAN Write = FALSE;
+ BOOLEAN Execute = FALSE;
+ ULONG Characteristics;
+ ULONG Idx;
+ ULONG Length;
+ PVOID BaseAddress;
- DPRINT("Loading Module %wZ...\n", Filename);
-
- /* Open the Module */
- InitializeObjectAttributes(&ObjectAttributes,
- Filename,
- 0,
- NULL,
- NULL);
- CHECKPOINT;
- Status = NtOpenFile(&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- 0);
- CHECKPOINT;
- if (!NT_SUCCESS(Status))
+ for (Idx = 0; Idx < PEFileHeader->NumberOfSections && (!Write || !Execute); Idx++)
{
- CPRINT("Could not open module file: %wZ\n", Filename);
- return(Status);
+ Characteristics = PESectionHeaders[Idx].Characteristics;
+ if (!(Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+ {
+ Length = max(PESectionHeaders[Idx].Misc.VirtualSize, PESectionHeaders[Idx].SizeOfRawData);
+ BaseAddress = PESectionHeaders[Idx].VirtualAddress + (char*)DriverBase;
+ if (BaseAddress < (PVOID)((ULONG_PTR)PageStart + PAGE_SIZE) &&
+ PageStart < (PVOID)((ULONG_PTR)BaseAddress + Length))
+ {
+ if (Characteristics & IMAGE_SCN_CNT_CODE)
+ {
+ Execute = TRUE;
+ }
+ if (Characteristics & (IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_UNINITIALIZED_DATA))
+ {
+ Write = TRUE;
+ }
+ }
+ }
}
- CHECKPOINT;
-
- /* Get the size of the file */
- Status = NtQueryInformationFile(FileHandle,
- &IoStatusBlock,
- &FileStdInfo,
- sizeof(FileStdInfo),
- FileStandardInformation);
- if (!NT_SUCCESS(Status))
+ if (Write && Execute)
{
- CPRINT("Could not get file size\n");
- NtClose(FileHandle);
- return(Status);
+ return PAGE_EXECUTE_READWRITE;
}
- CHECKPOINT;
-
- /* Allocate nonpageable memory for driver */
- ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
- FileStdInfo.EndOfFile.u.LowPart,
- TAG_DRIVER_MEM);
- if (ModuleLoadBase == NULL)
+ else if (Execute)
{
- CPRINT("Could not allocate memory for module");
- NtClose(FileHandle);
- return(STATUS_INSUFFICIENT_RESOURCES);
+ return PAGE_EXECUTE_READ;
}
- CHECKPOINT;
-
- /* Load driver into memory chunk */
- Status = NtReadFile(FileHandle,
- 0, 0, 0,
- &IoStatusBlock,
- ModuleLoadBase,
- FileStdInfo.EndOfFile.u.LowPart,
- 0, 0);
- if (!NT_SUCCESS(Status))
+ else if (Write)
{
- CPRINT("Could not read module file into memory");
- ExFreePool(ModuleLoadBase);
- NtClose(FileHandle);
- return(Status);
+ return PAGE_READWRITE;
}
- CHECKPOINT;
-
- NtClose(FileHandle);
-
- Status = LdrProcessModule(ModuleLoadBase,
- Filename,
- &Module);
- if (!NT_SUCCESS(Status))
+ else
{
- CPRINT("Could not process module");
- ExFreePool(ModuleLoadBase);
- return(Status);
+ return PAGE_READONLY;
}
-
- /* Cleanup */
- ExFreePool(ModuleLoadBase);
-
-#ifdef KDBG
-
- /* Load symbols for module if available */
- LdrpLoadModuleSymbols(Module);
-
-#endif /* KDBG */
-
- *ModuleObject = Module;
-
- return(STATUS_SUCCESS);
}
-
-NTSTATUS
-LdrUnloadModule(PMODULE_OBJECT ModuleObject)
+static NTSTATUS
+LdrPEProcessModule(
+ PVOID ModuleLoadBase,
+ PUNICODE_STRING FileName,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject )
{
- KIRQL Irql;
-
- /* Remove the module from the module list */
- KeAcquireSpinLock(&ModuleListLock,&Irql);
- RemoveEntryList(&ModuleObject->ListEntry);
- KeReleaseSpinLock(&ModuleListLock, Irql);
-
-#ifdef KDBG
- /* Unload symbols for module if available */
-// LdrpUnloadModuleSymbols(Module);
-#endif /* KDBG */
-
- /* Free text section */
- if (ModuleObject->TextSection != NULL)
- {
- ExFreePool(ModuleObject->TextSection->Name);
- RemoveEntryList(&ModuleObject->TextSection->ListEntry);
- ExFreePool(ModuleObject->TextSection);
- ModuleObject->TextSection = NULL;
- }
+ unsigned int DriverSize, Idx;
+ DWORD CurrentSize;
+ PVOID DriverBase;
+ PIMAGE_DOS_HEADER PEDosHeader;
+ PIMAGE_NT_HEADERS PENtHeaders;
+ PIMAGE_SECTION_HEADER PESectionHeaders;
+ PLDR_DATA_TABLE_ENTRY CreatedModuleObject;
+ NTSTATUS Status;
+ KIRQL Irql;
- /* Free module section */
-// MmFreeSection(ModuleObject->Base);
+ DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
- ExFreePool(ModuleObject);
-
- return(STATUS_SUCCESS);
-}
-
-
-NTSTATUS
-LdrInitializeBootStartDriver(PVOID ModuleLoadBase,
- PCHAR FileName,
- ULONG ModuleLength)
-{
- PMODULE_OBJECT ModuleObject;
- UNICODE_STRING ModuleName;
- PDEVICE_NODE DeviceNode;
- NTSTATUS Status;
-
- WCHAR Buffer[MAX_PATH];
- ULONG Length;
- LPWSTR Start;
- LPWSTR Ext;
-
- CHAR TextBuffer [256];
- ULONG x, y, cx, cy;
-
-#ifdef KDBG
- CHAR TmpBaseName[MAX_PATH];
- CHAR TmpFileName[MAX_PATH];
- ANSI_STRING AnsiString;
- ULONG Length;
- PCHAR Ext;
-#endif
+ /* Get header pointers */
+ PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
+ PENtHeaders = RtlImageNtHeader(ModuleLoadBase);
+ PESectionHeaders = IMAGE_FIRST_SECTION(PENtHeaders);
+ CHECKPOINT;
- HalQueryDisplayParameters(&x, &y, &cx, &cy);
- RtlFillMemory(TextBuffer, x, ' ');
- TextBuffer[x] = '\0';
- HalSetDisplayParameters(0, y-1);
- HalDisplayString(TextBuffer);
-
- sprintf(TextBuffer, "Initializing %s...\n", FileName);
- HalSetDisplayParameters(0, y-1);
- HalDisplayString(TextBuffer);
- HalSetDisplayParameters(cx, cy);
-
-#ifdef KDBG
- /* Split the filename into base name and extension */
- Ext = strrchr(FileName, '.');
- if (Ext != NULL)
- Length = Ext - FileName;
- else
- Length = strlen(FileName);
-
- if ((Ext != NULL) && (strcmp(Ext, ".sym") == 0))
+ /* Check file magic numbers */
+ if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
- DPRINT("Module %s is a symbol file\n", FileName);
-
- strncpy(TmpBaseName, FileName, Length);
- TmpBaseName[Length] = '\0';
-
- DPRINT("base: %s (Length %d)\n", TmpBaseName, Length);
-
- strcpy(TmpFileName, TmpBaseName);
- strcat(TmpFileName, ".sys");
- RtlInitAnsiString(&AnsiString, TmpFileName);
-
- DPRINT("dasdsad: %s\n", TmpFileName);
-
- RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
- Status = LdrFindModuleObject(&ModuleName, &ModuleObject);
- RtlFreeUnicodeString(&ModuleName);
- if (!NT_SUCCESS(Status))
- {
- strcpy(TmpFileName, TmpBaseName);
- strcat(TmpFileName, ".exe");
- RtlInitAnsiString(&AnsiString, TmpFileName);
- RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
- Status = LdrFindModuleObject(&ModuleName, &ModuleObject);
- RtlFreeUnicodeString(&ModuleName);
- }
- if (NT_SUCCESS(Status))
- {
- LdrpLoadModuleSymbolsFromBuffer(ModuleObject,
- ModuleLoadBase,
- ModuleLength);
- }
- return(STATUS_SUCCESS);
+ CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
+ return STATUS_UNSUCCESSFUL;
}
- else
+ if (PEDosHeader->e_lfanew == 0)
{
- DPRINT("Module %s is executable\n", FileName);
+ CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
+ return STATUS_UNSUCCESSFUL;
}
-#endif /* KDBG */
-
- /* Use IopRootDeviceNode for now */
- Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
- if (!NT_SUCCESS(Status))
+ if (PENtHeaders->Signature != IMAGE_NT_SIGNATURE)
{
- CPRINT("Driver load failed, status (%x)\n", Status);
- return(Status);
+ CPRINT("Incorrect PE magic: %08x\n", PENtHeaders->Signature);
+ return STATUS_UNSUCCESSFUL;
}
-
- RtlCreateUnicodeStringFromAsciiz(&ModuleName,
- FileName);
- Status = LdrProcessModule(ModuleLoadBase,
- &ModuleName,
- &ModuleObject);
- RtlFreeUnicodeString(&ModuleName);
- if (ModuleObject == NULL)
+ if (PENtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
{
- IopFreeDeviceNode(DeviceNode);
- CPRINT("Driver load failed, status (%x)\n", Status);
- return(STATUS_UNSUCCESSFUL);
+ CPRINT("Incorrect Architechture: %04x\n", PENtHeaders->FileHeader.Machine);
+ return STATUS_UNSUCCESSFUL;
}
+ CHECKPOINT;
+ /* FIXME: if image is fixed-address load, then fail */
- /* Get the service name from the module name */
- Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
- if (Start == NULL)
- Start = ModuleObject->BaseName.Buffer;
- else
- Start++;
+ /* FIXME: check/verify OS version number */
- Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
- if (Ext != NULL)
- Length = Ext - Start;
- else
- Length = wcslen(Start);
+ DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
+ PENtHeaders->OptionalHeader.Magic,
+ PENtHeaders->OptionalHeader.MajorLinkerVersion,
+ PENtHeaders->OptionalHeader.MinorLinkerVersion);
+ DPRINT("Entry Point:%08lx\n", PENtHeaders->OptionalHeader.AddressOfEntryPoint);
- wcsncpy(Buffer, Start, Length);
- RtlCreateUnicodeString(&DeviceNode->ServiceName, Buffer);
-
- Status = IopInitializeDriver(ModuleObject->EntryPoint,
- DeviceNode, FALSE);
- if (!NT_SUCCESS(Status))
+ /* Determine the size of the module */
+ DriverSize = 0;
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
{
- IopFreeDeviceNode(DeviceNode);
- CPRINT("Driver load failed, status (%x)\n", Status);
+ if (!(PESectionHeaders[Idx].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+ {
+ CurrentSize = PESectionHeaders[Idx].VirtualAddress + PESectionHeaders[Idx].Misc.VirtualSize;
+ DriverSize = max(DriverSize, CurrentSize);
+ }
}
+ DriverSize = ROUND_UP(DriverSize, PENtHeaders->OptionalHeader.SectionAlignment);
+ DPRINT("DriverSize %x, SizeOfImage %x\n",DriverSize, PENtHeaders->OptionalHeader.SizeOfImage);
- return(Status);
-}
-
-
-NTSTATUS
-LdrProcessModule(PVOID ModuleLoadBase,
- PUNICODE_STRING ModuleName,
- PMODULE_OBJECT *ModuleObject)
-{
- PIMAGE_DOS_HEADER PEDosHeader;
-
- /* If MZ header exists */
- PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
- if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
+ /* Allocate a virtual section for the module */
+ DriverBase = NULL;
+ DriverBase = MmAllocateSection(DriverSize, DriverBase);
+ if (DriverBase == 0)
{
- return LdrPEProcessModule(ModuleLoadBase,
- ModuleName,
- ModuleObject);
+ CPRINT("Failed to allocate a virtual section for driver\n");
+ return STATUS_UNSUCCESSFUL;
}
+ DPRINT("DriverBase for %wZ: %x\n", FileName, DriverBase);
- CPRINT("Module wasn't PE\n");
- return STATUS_UNSUCCESSFUL;
-}
-
+ /* Copy headers over */
+ memcpy(DriverBase, ModuleLoadBase, PENtHeaders->OptionalHeader.SizeOfHeaders);
-PVOID
-LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
- char *Name,
- unsigned short Hint)
-{
- if (ModuleObject->Flags & MODULE_FLAG_PE)
+ /* Copy image sections into virtual section */
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
{
- return LdrPEGetExportAddress(ModuleObject, Name, Hint);
- }
- else
- {
- return 0;
+ CurrentSize = PESectionHeaders[Idx].VirtualAddress + PESectionHeaders[Idx].Misc.VirtualSize;
+ /* Copy current section into current offset of virtual section */
+ if (CurrentSize <= DriverSize &&
+ PESectionHeaders[Idx].SizeOfRawData)
+ {
+ DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
+ PESectionHeaders[Idx].VirtualAddress + (ULONG_PTR)DriverBase);
+ memcpy((PVOID)((ULONG_PTR)DriverBase + PESectionHeaders[Idx].VirtualAddress),
+ (PVOID)((ULONG_PTR)ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
+ PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
+ ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
+ }
}
-}
-
-NTSTATUS
-LdrpQueryModuleInformation(PVOID Buffer,
- ULONG Size,
- PULONG ReqSize)
-{
- PLIST_ENTRY current_entry;
- PMODULE_OBJECT current;
- ULONG ModuleCount = 0;
- PSYSTEM_MODULE_INFORMATION Smi;
- ANSI_STRING AnsiName;
- PCHAR p;
- KIRQL Irql;
-
- KeAcquireSpinLock(&ModuleListLock,&Irql);
-
- /* calculate required size */
- current_entry = ModuleListHead.Flink;
- while (current_entry != (&ModuleListHead))
+ /* Perform relocation fixups */
+ Status = LdrPEPerformRelocations(DriverBase, DriverSize);
+ if (!NT_SUCCESS(Status))
{
- ModuleCount++;
- current_entry = current_entry->Flink;
+ // MmFreeSection(DriverBase);
+ return Status;
}
- *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
- (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY);
-
- if (Size < *ReqSize)
+ /* Create the module */
+ CreatedModuleObject = ExAllocatePoolWithTag (
+ NonPagedPool, sizeof(LDR_DATA_TABLE_ENTRY), TAG_MODULE_OBJECT );
+ if (CreatedModuleObject == NULL)
{
- KeReleaseSpinLock(&ModuleListLock, Irql);
- return(STATUS_INFO_LENGTH_MISMATCH);
+ // MmFreeSection(DriverBase);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
- /* fill the buffer */
- memset(Buffer, '=', Size);
+ RtlZeroMemory(CreatedModuleObject, sizeof(LDR_DATA_TABLE_ENTRY));
- Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
- Smi->Count = ModuleCount;
+ /* Initialize ModuleObject data */
+ CreatedModuleObject->DllBase = DriverBase;
- ModuleCount = 0;
- current_entry = ModuleListHead.Flink;
- while (current_entry != (&ModuleListHead))
+ CreatedModuleObject->FullDllName.Length = 0;
+ CreatedModuleObject->FullDllName.MaximumLength = FileName->Length + sizeof(UNICODE_NULL);
+ CreatedModuleObject->FullDllName.Buffer =
+ ExAllocatePoolWithTag(PagedPool, CreatedModuleObject->FullDllName.MaximumLength, TAG_LDR_WSTR);
+ if (CreatedModuleObject->FullDllName.Buffer == NULL)
{
- current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
-
- Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
- Smi->Module[ModuleCount].BaseAddress = current->Base;
- Smi->Module[ModuleCount].Size = current->Length;
- Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
- Smi->Module[ModuleCount].EntryIndex = ModuleCount;
-
- AnsiName.Length = 0;
- AnsiName.MaximumLength = 256;
- AnsiName.Buffer = Smi->Module[ModuleCount].Name;
- RtlUnicodeStringToAnsiString(&AnsiName,
- ¤t->FullName,
- FALSE);
-
- p = strrchr(AnsiName.Buffer, '\\');
- if (p == NULL)
- {
- Smi->Module[ModuleCount].PathLength = 0;
- Smi->Module[ModuleCount].NameLength = strlen(AnsiName.Buffer);
- }
- else
- {
- p++;
- Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
- Smi->Module[ModuleCount].NameLength = strlen(p);
- }
-
- ModuleCount++;
- current_entry = current_entry->Flink;
+ ExFreePool(CreatedModuleObject);
+ // MmFreeSection(DriverBase);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
- KeReleaseSpinLock(&ModuleListLock, Irql);
-
- return(STATUS_SUCCESS);
-}
-
-
-static VOID
-LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
- PUNICODE_STRING FullName)
-{
- UNICODE_STRING Name;
- PWCHAR p;
- PWCHAR q;
-
- DPRINT("LdrpBuildModuleBaseName()\n");
- DPRINT("FullName %wZ\n", FullName);
-
- p = wcsrchr(FullName->Buffer, L'\\');
- if (p == NULL)
- {
- p = FullName->Buffer;
- }
- else
- {
- p++;
- }
-
- DPRINT("p %S\n", p);
-
- RtlCreateUnicodeString(&Name, p);
+ RtlCopyUnicodeString(&CreatedModuleObject->FullDllName, FileName);
+ CreatedModuleObject->FullDllName.Buffer[FileName->Length / sizeof(WCHAR)] = 0;
+ LdrpBuildModuleBaseName(&CreatedModuleObject->BaseDllName,
+ &CreatedModuleObject->FullDllName);
- q = wcschr(Name.Buffer, L'.');
- if (q != NULL)
- {
- *q = (WCHAR)0;
- }
+ CreatedModuleObject->EntryPoint =
+ (PVOID)((ULONG_PTR)DriverBase +
+ PENtHeaders->OptionalHeader.AddressOfEntryPoint);
+ CreatedModuleObject->SizeOfImage = DriverSize;
+ DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
- DPRINT("p %S\n", p);
-
- RtlCreateUnicodeString(BaseName, Name.Buffer);
- RtlFreeUnicodeString(&Name);
-}
-
-
-static LONG
-LdrpCompareModuleNames(IN PUNICODE_STRING String1,
- IN PUNICODE_STRING String2)
-{
- ULONG len1, len2, i;
- PWCHAR s1, s2, p;
- WCHAR c1, c2;
-
- if (String1 && String2)
+ /* Perform import fixups */
+ Status = LdrPEFixupImports(CreatedModuleObject);
+ if (!NT_SUCCESS(Status))
{
- /* Search String1 for last path component */
- len1 = String1->Length / sizeof(WCHAR);
- s1 = String1->Buffer;
- for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
- {
- if (*p == L'\\')
- {
- if (i == String1->Length - sizeof(WCHAR))
- {
- s1 = NULL;
- len1 = 0;
- }
- else
- {
- s1 = p + 1;
- len1 = (String1->Length - i) / sizeof(WCHAR);
- }
- }
- }
-
- /* Search String2 for last path component */
- len2 = String2->Length / sizeof(WCHAR);
- s2 = String2->Buffer;
- for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
- {
- if (*p == L'\\')
- {
- if (i == String2->Length - sizeof(WCHAR))
- {
- s2 = NULL;
- len2 = 0;
- }
- else
- {
- s2 = p + 1;
- len2 = (String2->Length - i) / sizeof(WCHAR);
- }
- }
- }
-
- /* Compare last path components */
- if (s1 && s2)
- {
- while (1)
- {
- c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
- c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
- if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
- return(0);
- if (!c1 || !c2 || c1 != c2)
- return(c1 - c2);
- }
- }
+ // MmFreeSection(DriverBase);
+ ExFreePool(CreatedModuleObject->FullDllName.Buffer);
+ ExFreePool(CreatedModuleObject);
+ return Status;
}
- return(0);
-}
-
-
-PMODULE_OBJECT
-LdrGetModuleObject(PUNICODE_STRING ModuleName)
-{
- PMODULE_OBJECT Module;
- PLIST_ENTRY Entry;
- KIRQL Irql;
+ MmSetPageProtect(NULL, DriverBase, PAGE_READONLY);
+ /* Set the protections for the various parts of the driver */
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
+ {
+ ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
+ ULONG Length;
+ PVOID BaseAddress;
+ PVOID PageAddress;
+ ULONG Protect;
+ Length = PESectionHeaders[Idx].Misc.VirtualSize;
+ BaseAddress = PESectionHeaders[Idx].VirtualAddress + (char*)DriverBase;
+ PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
- DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName);
+ Protect = LdrLookupPageProtection(PageAddress, DriverBase, &PENtHeaders->FileHeader, PESectionHeaders);
+#if 1
+ /*
+ * FIXME:
+ * This driver modifies a string in the first page of the text section while initialising.
+ */
+ if (0 == _wcsicmp(L"fireport.sys", FileName->Buffer))
+ {
+ Protect = PAGE_EXECUTE_READWRITE;
+ }
+#endif
+ if (PageAddress < RVA(DriverBase, DriverSize))
+ {
+ MmSetPageProtect(NULL, PageAddress, Protect);
+ }
- KeAcquireSpinLock(&ModuleListLock,&Irql);
+ if (Characteristics & IMAGE_SCN_CNT_CODE)
+ {
+ if (Characteristics & IMAGE_SCN_MEM_WRITE)
+ {
+ Protect = PAGE_EXECUTE_READWRITE;
+ }
+ else
+ {
+ Protect = PAGE_EXECUTE_READ;
+ }
+ }
+ else if (Characteristics & (IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_UNINITIALIZED_DATA))
+ {
+ Protect = PAGE_READWRITE;
+ }
+ else
+ {
+ Protect = PAGE_READONLY;
+ }
+ PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE);
+ while ((ULONG_PTR)PageAddress + PAGE_SIZE < (ULONG_PTR)BaseAddress + Length)
+ {
+ if (PageAddress < RVA(DriverBase, DriverSize))
+ {
+ MmSetPageProtect(NULL, PageAddress, Protect);
+ }
+ PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE);
+ }
+ if (PageAddress < (PVOID)((ULONG_PTR)BaseAddress + Length) &&
+ PageAddress < RVA(DriverBase, DriverSize))
+ {
+ Protect = LdrLookupPageProtection(PageAddress, DriverBase, &PENtHeaders->FileHeader, PESectionHeaders);
+ MmSetPageProtect(NULL, PageAddress, Protect);
+ }
+ }
- Entry = ModuleListHead.Flink;
- while (Entry != &ModuleListHead)
- {
- Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
+ /* Insert module */
+ KeAcquireSpinLock(&ModuleListLock, &Irql);
+ InsertTailList(&ModuleListHead,
+ &CreatedModuleObject->InLoadOrderModuleList);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
- DPRINT("Comparing %wZ and %wZ\n",
- &Module->BaseName,
- ModuleName);
+ *ModuleObject = CreatedModuleObject;
- if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName))
- {
- DPRINT("Module %wZ\n", &Module->BaseName);
- KeReleaseSpinLock(&ModuleListLock, Irql);
- return(Module);
- }
+ DPRINT("Loading Module %wZ...\n", FileName);
- Entry = Entry->Flink;
- }
+ DPRINT("Module %wZ loaded at 0x%.08x.\n",
+ FileName, CreatedModuleObject->DllBase);
- KeReleaseSpinLock(&ModuleListLock, Irql);
+ return STATUS_SUCCESS;
+}
- CPRINT("LdrpGetModuleObject: Failed to find module %wZ\n", ModuleName);
- return(NULL);
-}
+PVOID
+INIT_FUNCTION
+NTAPI
+LdrSafePEProcessModule (
+ PVOID ModuleLoadBase,
+ PVOID DriverBase,
+ PVOID ImportModuleBase,
+ PULONG DriverSize)
+{
+ unsigned int Idx;
+ ULONG CurrentSize;
+ PIMAGE_DOS_HEADER PEDosHeader;
+ PIMAGE_NT_HEADERS PENtHeaders;
+ PIMAGE_SECTION_HEADER PESectionHeaders;
+ NTSTATUS Status;
+ ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
-/* ---------------------------------------------- PE Module support */
+ /* Get header pointers */
+ PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
+ PENtHeaders = RtlImageNtHeader(ModuleLoadBase);
+ PESectionHeaders = IMAGE_FIRST_SECTION(PENtHeaders);
+ CHECKPOINT;
-static NTSTATUS
-LdrPEProcessModule(PVOID ModuleLoadBase,
- PUNICODE_STRING FileName,
- PMODULE_OBJECT *ModuleObject)
-{
- unsigned int DriverSize, Idx;
- ULONG RelocDelta, NumRelocs;
- DWORD CurrentSize, TotalRelocs;
- PVOID DriverBase;
- PULONG PEMagic;
- PIMAGE_DOS_HEADER PEDosHeader;
- PIMAGE_FILE_HEADER PEFileHeader;
- PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
- PIMAGE_SECTION_HEADER PESectionHeaders;
- PRELOCATION_DIRECTORY RelocDir;
- PRELOCATION_ENTRY RelocEntry;
- PMODULE_OBJECT LibraryModuleObject;
- PMODULE_OBJECT CreatedModuleObject;
- PVOID *ImportAddressList;
- PULONG FunctionNameList;
- PCHAR pName;
- WORD Hint;
- UNICODE_STRING ModuleName;
- UNICODE_STRING NameString;
- WCHAR NameBuffer[60];
- MODULE_TEXT_SECTION* ModuleTextSection;
- NTSTATUS Status;
- KIRQL Irql;
-
- DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
-
- /* Get header pointers */
- PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
- PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew);
- PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG));
- PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
- PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
- sizeof(IMAGE_OPTIONAL_HEADER));
- CHECKPOINT;
-
- /* Check file magic numbers */
- if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
+ /* Check file magic numbers */
+ if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
- CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
- return STATUS_UNSUCCESSFUL;
+ return NULL;
}
- if (PEDosHeader->e_lfanew == 0)
+ if (PEDosHeader->e_lfanew == 0)
{
- CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
- return STATUS_UNSUCCESSFUL;
+ return NULL;
}
- if (*PEMagic != IMAGE_PE_MAGIC)
+ if (PENtHeaders->Signature != IMAGE_NT_SIGNATURE)
{
- CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
- return STATUS_UNSUCCESSFUL;
+ return NULL;
}
- if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
+ if (PENtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
{
- CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
- return STATUS_UNSUCCESSFUL;
+ return NULL;
}
- CHECKPOINT;
-
- /* FIXME: if image is fixed-address load, then fail */
- /* FIXME: check/verify OS version number */
+ ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
+ PENtHeaders->OptionalHeader.Magic,
+ PENtHeaders->OptionalHeader.MajorLinkerVersion,
+ PENtHeaders->OptionalHeader.MinorLinkerVersion);
+ ps("Entry Point:%08lx\n", PENtHeaders->OptionalHeader.AddressOfEntryPoint);
- DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
- PEOptionalHeader->Magic,
- PEOptionalHeader->MajorLinkerVersion,
- PEOptionalHeader->MinorLinkerVersion);
- DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
- CHECKPOINT;
+ /* Determine the size of the module */
+ *DriverSize = PENtHeaders->OptionalHeader.SizeOfImage;
+ ps("DriverSize %x\n",*DriverSize);
- /* Determine the size of the module */
- DriverSize = PEOptionalHeader->SizeOfImage;
- DPRINT("DriverSize %x\n",DriverSize);
-
- /* Allocate a virtual section for the module */
- DriverBase = MmAllocateSection(DriverSize);
- if (DriverBase == 0)
+ /* Copy headers over */
+ if (DriverBase != ModuleLoadBase)
{
- CPRINT("Failed to allocate a virtual section for driver\n");
- return STATUS_UNSUCCESSFUL;
+ memcpy(DriverBase, ModuleLoadBase, PENtHeaders->OptionalHeader.SizeOfHeaders);
}
- CPRINT("DriverBase: %x\n", DriverBase);
- CHECKPOINT;
- /* Copy headers over */
- memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
- CurrentSize = 0;
- /* Copy image sections into virtual section */
- for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
+
+ ps("Hdr: 0x%X\n", PENtHeaders);
+ ps("Hdr->SizeOfHeaders: 0x%X\n", PENtHeaders->OptionalHeader.SizeOfHeaders);
+ ps("FileHdr->NumberOfSections: 0x%X\n", PENtHeaders->FileHeader.NumberOfSections);
+
+ /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
+ address as it is mapped */
+ if (DriverBase != ModuleLoadBase)
{
- // Copy current section into current offset of virtual section
- if (PESectionHeaders[Idx].Characteristics &
- (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
+ CurrentSize = 0;
+
+ /* Copy image sections into virtual section */
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
{
- DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
- PESectionHeaders[Idx].VirtualAddress + DriverBase);
- memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
- (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
- PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
+ PIMAGE_SECTION_HEADER Section = &PESectionHeaders[Idx];
+ // Copy current section into current offset of virtual section
+ if (Section->SizeOfRawData)
+ {
+ // ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
+ // PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
+ memcpy(Section->VirtualAddress + (char*)DriverBase,
+ Section->PointerToRawData + (char*)ModuleLoadBase,
+ Section->Misc.VirtualSize > Section->SizeOfRawData ? Section->SizeOfRawData : Section->Misc.VirtualSize);
+ }
+ if (Section->SizeOfRawData < Section->Misc.VirtualSize)
+ {
+ memset(Section->VirtualAddress + Section->SizeOfRawData + (char*)DriverBase,
+ 0,
+ Section->Misc.VirtualSize - Section->SizeOfRawData);
+ }
+ CurrentSize += ROUND_UP(Section->Misc.VirtualSize,
+ PENtHeaders->OptionalHeader.SectionAlignment);
}
- else
- {
- DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
- PESectionHeaders[Idx].VirtualAddress + DriverBase);
- memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
- '\0', PESectionHeaders[Idx].Misc.VirtualSize);
+ /* Perform relocation fixups */
+ Status = LdrPEPerformRelocations(DriverBase, *DriverSize);
+ if (!NT_SUCCESS(Status))
+ {
+ return NULL;
}
- CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
- PEOptionalHeader->SectionAlignment);
-
-
-// CurrentBase = (PVOID)((DWORD)CurrentBase +
- // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
- // PEOptionalHeader->SectionAlignment));
}
- /* Perform relocation fixups */
- RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
- RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
- IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
- DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
- DriverBase,
- PEOptionalHeader->ImageBase,
- RelocDelta);
- DPRINT("RelocDir %x\n",RelocDir);
-#if 1
- for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
+ /* Perform import fixups */
+ Status = LdrPEFixupImports(DriverBase == ModuleLoadBase ? &NtoskrnlModuleObject : &HalModuleObject);
+ if (!NT_SUCCESS(Status))
{
- if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
- {
- DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
- PESectionHeaders[Idx].Name,
- PESectionHeaders[Idx].PointerToRawData);
- RelocDir = PESectionHeaders[Idx].PointerToRawData +
- ModuleLoadBase;
- CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
- break;
- }
+ return NULL;
}
-#else
- RelocDir = RelocDir + (ULONG)DriverBase;
- CurrentSize = PEOptionalHeader->DataDirectory
- [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
-#endif
- DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
- TotalRelocs = 0;
- while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
+
+ /* Set the page protection for the virtual sections */
+ MmSetPageProtect(NULL, DriverBase, PAGE_READONLY);
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
{
- NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
- sizeof(WORD);
-/* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
- RelocDir,
- RelocDir->VirtualAddress,
- NumRelocs);*/
- RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
- sizeof(RELOCATION_DIRECTORY));
- for (Idx = 0; Idx < NumRelocs; Idx++)
+ ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
+ ULONG Length;
+ PVOID BaseAddress;
+ PVOID PageAddress;
+ ULONG Protect;
+ Length = PESectionHeaders[Idx].Misc.VirtualSize;
+ BaseAddress = PESectionHeaders[Idx].VirtualAddress + (char*)DriverBase;
+ PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
+
+ if (Characteristics & IMAGE_SCN_MEM_EXECUTE)
{
- ULONG Offset;
- ULONG Type;
- PDWORD RelocItem;
-
- Offset = RelocEntry[Idx].TypeOffset & 0xfff;
- Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
- RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
- Offset);
-/* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
- RelocItem,
- Type,
- Type ? "HIGHLOW" : "ABS",
- *RelocItem,
- (*RelocItem) + RelocDelta); */
- if (Type == 3)
+ if (Characteristics & IMAGE_SCN_MEM_WRITE)
{
- (*RelocItem) += RelocDelta;
+ Protect = PAGE_EXECUTE_READWRITE;
}
- else if (Type != 0)
+ else
{
- CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
- return STATUS_UNSUCCESSFUL;
+ Protect = PAGE_EXECUTE_READ;
}
}
- TotalRelocs += RelocDir->SizeOfBlock;
- RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
- RelocDir->SizeOfBlock);
-// DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
- }
-
- DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
- PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
- .VirtualAddress);
- /* Perform import fixups */
- if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
- {
- PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
-
- /* Process each import module */
- ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
- ((DWORD)DriverBase + PEOptionalHeader->
- DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
- DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
- while (ImportModuleDirectory->dwRVAModuleName)
+ else if (Characteristics & IMAGE_SCN_MEM_WRITE)
+ {
+ Protect = PAGE_READWRITE;
+ }
+ else
{
- /* Check to make sure that import lib is kernel */
- pName = (PCHAR) DriverBase +
- ImportModuleDirectory->dwRVAModuleName;
+ Protect = PAGE_READONLY;
+ }
+ while ((ULONG_PTR)PageAddress < (ULONG_PTR)BaseAddress + Length)
+ {
+ MmSetPageProtect(NULL, PageAddress, Protect);
+ PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE);
+ }
+ if (DriverBase == ModuleLoadBase &&
+ Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ {
+ /* For ntoskrnl, we must stop after the bss section */
+ break;
+ }
- RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName);
- DPRINT("Import module: %wZ\n", &ModuleName);
+ }
- LibraryModuleObject = LdrGetModuleObject(&ModuleName);
- if (LibraryModuleObject == NULL)
- {
- DPRINT("Module '%wZ' not loaded\n", &ModuleName);
- wcscpy(NameBuffer, L"\\SystemRoot\\system32\\drivers\\");
- wcscat(NameBuffer, ModuleName.Buffer);
- RtlInitUnicodeString(&NameString, NameBuffer);
- Status = LdrLoadModule(&NameString, &LibraryModuleObject);
- if (!NT_SUCCESS(Status))
- {
- CPRINT("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
- return(Status);
- }
- }
- /* Get the import address list */
- ImportAddressList = (PVOID *) ((DWORD)DriverBase +
- ImportModuleDirectory->dwRVAFunctionAddressList);
+ return DriverBase;
+}
- /* Get the list of functions to import */
- if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
- {
- FunctionNameList = (PULONG) ((DWORD)DriverBase +
- ImportModuleDirectory->dwRVAFunctionNameList);
- }
- else
- {
- FunctionNameList = (PULONG) ((DWORD)DriverBase +
- ImportModuleDirectory->dwRVAFunctionAddressList);
- }
- /* Walk through function list and fixup addresses */
- while (*FunctionNameList != 0L)
- {
- if ((*FunctionNameList) & 0x80000000) // hint
- {
- pName = NULL;
+static PVOID
+LdrPEFixupForward ( PCHAR ForwardName )
+{
+ CHAR NameBuffer[128];
+ UNICODE_STRING ModuleName;
+ PCHAR p;
+ PLDR_DATA_TABLE_ENTRY ModuleObject;
+ DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
- Hint = (*FunctionNameList) & 0xffff;
- }
- else // hint-name
- {
- pName = (PCHAR)((DWORD)DriverBase +
- *FunctionNameList + 2);
- Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
- }
- DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
+ strcpy(NameBuffer, ForwardName);
+ p = strchr(NameBuffer, '.');
+ if (p == NULL)
+ {
+ return NULL;
+ }
- /* Fixup the current import symbol */
- if (LibraryModuleObject != NULL)
- {
- *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
- pName,
- Hint);
- }
- else
- {
- CPRINT("Unresolved kernel symbol: %s\n", pName);
- return STATUS_UNSUCCESSFUL;
- }
- ImportAddressList++;
- FunctionNameList++;
- }
+ *p = 0;
- RtlFreeUnicodeString(&ModuleName);
+ DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
- ImportModuleDirectory++;
- }
- }
+ RtlCreateUnicodeStringFromAsciiz(&ModuleName,
+ NameBuffer);
+ ModuleObject = LdrGetModuleObject(&ModuleName);
+ RtlFreeUnicodeString(&ModuleName);
- /* Create the module */
- CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
- if (CreatedModuleObject == NULL)
- {
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
+ DPRINT("ModuleObject: %p\n", ModuleObject);
- RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT));
-
- /* Initialize ModuleObject data */
- CreatedModuleObject->Base = DriverBase;
- CreatedModuleObject->Flags = MODULE_FLAG_PE;
-
- RtlCreateUnicodeString(&CreatedModuleObject->FullName,
- FileName->Buffer);
- LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
- &CreatedModuleObject->FullName);
-
- CreatedModuleObject->EntryPoint = (PVOID)((DWORD)DriverBase +
- PEOptionalHeader->AddressOfEntryPoint);
- CreatedModuleObject->Length = DriverSize;
- DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
-
- CreatedModuleObject->Image.PE.FileHeader =
- (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
-
- DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
- CreatedModuleObject->Image.PE.OptionalHeader =
- (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
- sizeof(IMAGE_FILE_HEADER));
- DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
- CreatedModuleObject->Image.PE.SectionList =
- (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
- sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
- DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
-
- /* Insert module */
- KeAcquireSpinLock(&ModuleListLock, &Irql);
- InsertTailList(&ModuleListHead,
- &CreatedModuleObject->ListEntry);
- KeReleaseSpinLock(&ModuleListLock, Irql);
-
-
- ModuleTextSection = ExAllocatePool(NonPagedPool,
- sizeof(MODULE_TEXT_SECTION));
- ModuleTextSection->Base = (ULONG)DriverBase;
- ModuleTextSection->Length = DriverSize;
- ModuleTextSection->SymbolsBase = NULL;
- ModuleTextSection->SymbolsLength = 0;
- ModuleTextSection->Name =
- ExAllocatePool(NonPagedPool,
- (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
- wcscpy(ModuleTextSection->Name, NameBuffer);
- InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
-
- CreatedModuleObject->TextSection = ModuleTextSection;
-
- *ModuleObject = CreatedModuleObject;
-
- DPRINT("Loading Module %wZ...\n", FileName);
-
- if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
+ if (ModuleObject == NULL)
{
- DbgPrint("Module %wZ loaded at 0x%.08x.\n",
- FileName, CreatedModuleObject->Base);
+ CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
+ return NULL;
}
-
- return STATUS_SUCCESS;
+ return LdrPEGetExportByName(ModuleObject->DllBase, (PUCHAR)(p+1), 0xffff);
}
-
-PVOID
-LdrSafePEProcessModule(PVOID ModuleLoadBase,
- PVOID DriverBase,
- PVOID ImportModuleBase,
- PULONG DriverSize)
+static NTSTATUS
+LdrPEPerformRelocations (
+ PVOID DriverBase,
+ ULONG DriverSize)
{
- unsigned int Idx;
- ULONG RelocDelta, NumRelocs;
- ULONG CurrentSize, TotalRelocs;
- PULONG PEMagic;
- PIMAGE_DOS_HEADER PEDosHeader;
- PIMAGE_FILE_HEADER PEFileHeader;
- PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
- PIMAGE_SECTION_HEADER PESectionHeaders;
- PRELOCATION_DIRECTORY RelocDir;
- PRELOCATION_ENTRY RelocEntry;
- PVOID *ImportAddressList;
- PULONG FunctionNameList;
- PCHAR pName;
- USHORT Hint;
-
- ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
-
- /* Get header pointers */
- PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
- PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew);
- PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG));
- PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
- PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
- PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
- sizeof(IMAGE_OPTIONAL_HEADER));
- CHECKPOINT;
-
- /* Check file magic numbers */
- if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
- {
- return 0;
- }
- if (PEDosHeader->e_lfanew == 0)
+ PIMAGE_NT_HEADERS NtHeaders;
+ PIMAGE_DATA_DIRECTORY RelocationDDir;
+ PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
+ ULONG Count, i;
+ PVOID Address, MaxAddress;
+ PUSHORT TypeOffset;
+ ULONG_PTR Delta;
+ SHORT Offset;
+ USHORT Type;
+ PUSHORT ShortPtr;
+ PULONG LongPtr;
+
+ NtHeaders = RtlImageNtHeader(DriverBase);
+
+ if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
{
- return 0;
+ return STATUS_UNSUCCESSFUL;
}
- if (*PEMagic != IMAGE_PE_MAGIC)
+
+ RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+
+ if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0)
{
- return 0;
+ return STATUS_SUCCESS;
}
- if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
+
+ Delta = (ULONG_PTR)DriverBase - NtHeaders->OptionalHeader.ImageBase;
+ RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)DriverBase + RelocationDDir->VirtualAddress);
+ RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size);
+ MaxAddress = RVA(DriverBase, DriverSize);
+
+ while (RelocationDir < RelocationEnd &&
+ RelocationDir->SizeOfBlock > 0)
{
- return 0;
- }
+ Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
+ Address = RVA(DriverBase, RelocationDir->VirtualAddress);
+ TypeOffset = (PUSHORT)(RelocationDir + 1);
- ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
- PEOptionalHeader->Magic,
- PEOptionalHeader->MajorLinkerVersion,
- PEOptionalHeader->MinorLinkerVersion);
- ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
+ for (i = 0; i < Count; i++)
+ {
+ Offset = *TypeOffset & 0xFFF;
+ Type = *TypeOffset >> 12;
+ ShortPtr = (PUSHORT)(RVA(Address, Offset));
- /* Determine the size of the module */
- *DriverSize = PEOptionalHeader->SizeOfImage;
- ps("DriverSize %x\n",*DriverSize);
+ /* Don't relocate after the end of the loaded driver */
+ if ((PVOID)ShortPtr >= MaxAddress)
+ {
+ break;
+ }
- /* Copy headers over */
- if (DriverBase != ModuleLoadBase)
- {
- memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
+ /*
+ * Don't relocate within the relocation section itself.
+ * GCC/LD generates sometimes relocation records for the relocation section.
+ * This is a bug in GCC/LD.
+ */
+ if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
+ (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
+ {
+ switch (Type)
+ {
+ case IMAGE_REL_BASED_ABSOLUTE:
+ break;
+
+ case IMAGE_REL_BASED_HIGH:
+ *ShortPtr += HIWORD(Delta);
+ break;
+
+ case IMAGE_REL_BASED_LOW:
+ *ShortPtr += LOWORD(Delta);
+ break;
+
+ case IMAGE_REL_BASED_HIGHLOW:
+ LongPtr = (PULONG)ShortPtr;
+ *LongPtr += Delta;
+ break;
+
+ case IMAGE_REL_BASED_HIGHADJ:
+ case IMAGE_REL_BASED_MIPS_JMPADDR:
+ default:
+ DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
+ DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ TypeOffset++;
+ }
+ RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock);
}
- ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
- ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
- ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
+ return STATUS_SUCCESS;
+}
+#ifndef PATH_MAX
+#define PATH_MAX 260
+#endif
- /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
- address as it is mapped */
- if (DriverBase != ModuleLoadBase)
- {
- CurrentSize = 0;
+static NTSTATUS
+LdrPEGetOrLoadModule (
+ PLDR_DATA_TABLE_ENTRY Module,
+ PCHAR ImportedName,
+ PLDR_DATA_TABLE_ENTRY* ImportedModule)
+{
+ UNICODE_STRING DriverName;
+ UNICODE_STRING NameString;
+ WCHAR NameBuffer[PATH_MAX];
+ NTSTATUS Status = STATUS_SUCCESS;
- /* Copy image sections into virtual section */
- for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
+ if (0 == _stricmp(ImportedName, "ntoskrnl") ||
+ 0 == _stricmp(ImportedName, "ntoskrnl.exe"))
{
- // Copy current section into current offset of virtual section
- if (PESectionHeaders[Idx].Characteristics &
- (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
- {
- //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
- //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
- memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
- (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
- PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
- PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
- }
- else
- {
- ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
- PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
- memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
- '\0',
- PESectionHeaders[Idx].Misc.VirtualSize);
- }
- CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
- PEOptionalHeader->SectionAlignment);
+ *ImportedModule = &NtoskrnlModuleObject;
+ return STATUS_SUCCESS;
}
- /* Perform relocation fixups */
- RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase;
- RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
- IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
- ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
- DriverBase,
- PEOptionalHeader->ImageBase,
- RelocDelta);
- ps("RelocDir %x\n",RelocDir);
-
- for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
+ if (0 == _stricmp(ImportedName, "hal") ||
+ 0 == _stricmp(ImportedName, "hal.dll"))
{
- if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir)
- {
- DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
- PESectionHeaders[Idx].Name,
- PESectionHeaders[Idx].PointerToRawData);
- RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
- CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
- break;
- }
+ *ImportedModule = &HalModuleObject;
+ return STATUS_SUCCESS;
}
- ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
+ RtlCreateUnicodeStringFromAsciiz (&DriverName, ImportedName);
+ DPRINT("Import module: %wZ\n", &DriverName);
- TotalRelocs = 0;
- while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
+ *ImportedModule = LdrGetModuleObject(&DriverName);
+ if (*ImportedModule == NULL)
{
- NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
- sizeof(USHORT);
- RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir +
- sizeof(RELOCATION_DIRECTORY));
- for (Idx = 0; Idx < NumRelocs; Idx++)
+ PWCHAR PathEnd;
+ ULONG PathLength;
+
+ PathEnd = wcsrchr(Module->FullDllName.Buffer, L'\\');
+ if (NULL != PathEnd)
+ {
+ PathLength = (PathEnd - Module->FullDllName.Buffer + 1) * sizeof(WCHAR);
+ RtlCopyMemory(NameBuffer, Module->FullDllName.Buffer, PathLength);
+ RtlCopyMemory(NameBuffer + (PathLength / sizeof(WCHAR)), DriverName.Buffer, DriverName.Length);
+ NameString.Buffer = NameBuffer;
+ NameString.MaximumLength = NameString.Length = PathLength + DriverName.Length;
+
+ /* NULL-terminate */
+ NameString.MaximumLength++;
+ NameBuffer[NameString.Length / sizeof(WCHAR)] = 0;
+
+ Status = LdrLoadModule(&NameString, ImportedModule);
+ }
+ else
+ {
+ DPRINT("Module '%wZ' not loaded yet\n", &DriverName);
+ wcscpy(NameBuffer, L"\\SystemRoot\\system32\\drivers\\");
+ wcsncat(NameBuffer, DriverName.Buffer, DriverName.Length / sizeof(WCHAR));
+ RtlInitUnicodeString(&NameString, NameBuffer);
+ Status = LdrLoadModule(&NameString, ImportedModule);
+ }
+ if (!NT_SUCCESS(Status))
{
- ULONG Offset;
- ULONG Type;
- PDWORD RelocItem;
-
- Offset = RelocEntry[Idx].TypeOffset & 0xfff;
- Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
- RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset);
- if (Type == 3)
- {
- (*RelocItem) += RelocDelta;
- }
- else if (Type != 0)
- {
- CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
- return(0);
- }
- }
- TotalRelocs += RelocDir->SizeOfBlock;
- RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir +
- RelocDir->SizeOfBlock);
+ wcscpy(NameBuffer, L"\\SystemRoot\\system32\\");
+ wcsncat(NameBuffer, DriverName.Buffer, DriverName.Length / sizeof(WCHAR));
+ RtlInitUnicodeString(&NameString, NameBuffer);
+ Status = LdrLoadModule(&NameString, ImportedModule);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unknown import module: %wZ (Status %lx)\n", &DriverName, Status);
+ }
+ }
}
+ RtlFreeUnicodeString(&DriverName);
+ return Status;
+}
+
+static PVOID
+LdrPEGetExportByName (
+ PVOID BaseAddress,
+ PUCHAR SymbolName,
+ WORD Hint )
+{
+ PIMAGE_EXPORT_DIRECTORY ExportDir;
+ PDWORD * ExFunctions;
+ PDWORD * ExNames;
+ USHORT * ExOrdinals;
+ PVOID ExName;
+ ULONG Ordinal;
+ PVOID Function;
+ LONG minn, maxn, mid, res;
+ ULONG ExportDirSize;
- ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
- PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
- .VirtualAddress);
- }
+ DPRINT("LdrPEGetExportByName %x %s %hu\n", BaseAddress, SymbolName, Hint);
- /* Perform import fixups */
- if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
+ ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(BaseAddress,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &ExportDirSize);
+ if (ExportDir == NULL)
{
- PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
-
- /* Process each import module */
- ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
- ((ULONG)DriverBase + PEOptionalHeader->
- DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
-
- ps("Processeing import directory at %p\n", ImportModuleDirectory);
-
- /* Check to make sure that import lib is kernel */
- pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName;
-
- ps("Import module: %s\n", pName);
-
- /* Get the import address list */
- ImportAddressList = (PVOID *)((ULONG)DriverBase +
- ImportModuleDirectory->dwRVAFunctionAddressList);
-
- ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
- ImportModuleDirectory->dwRVAFunctionAddressList);
- ps(" ImportAddressList: 0x%X\n", ImportAddressList);
-
- /* Get the list of functions to import */
- if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
- {
- ps("Using function name list.\n");
-
- FunctionNameList = (PULONG)((ULONG)DriverBase +
- ImportModuleDirectory->dwRVAFunctionNameList);
- }
- else
- {
- ps("Using function address list.\n");
-
- FunctionNameList = (PULONG)((ULONG)DriverBase +
- ImportModuleDirectory->dwRVAFunctionAddressList);
- }
-
- /* Walk through function list and fixup addresses */
- while (*FunctionNameList != 0L)
- {
- if ((*FunctionNameList) & 0x80000000)
- {
- /* Hint */
- pName = NULL;
- Hint = (*FunctionNameList) & 0xffff;
- }
- else
- {
- /* Hint name */
- pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2);
- Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList);
- }
- //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
-
- *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase,
- pName,
- Hint);
-
- ImportAddressList++;
- FunctionNameList++;
- }
+ DPRINT1("LdrPEGetExportByName(): no export directory!\n");
+ return NULL;
}
- ps("Finished importing.\n");
- return(0);
-}
+ /* The symbol names may be missing entirely */
+ if (ExportDir->AddressOfNames == 0)
+ {
+ DPRINT("LdrPEGetExportByName(): symbol names missing entirely\n");
+ return NULL;
+ }
+ /*
+ * Get header pointers
+ */
+ ExNames = (PDWORD *)RVA(BaseAddress, ExportDir->AddressOfNames);
+ ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
+ ExFunctions = (PDWORD *)RVA(BaseAddress, ExportDir->AddressOfFunctions);
-static PVOID
-LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
- PCHAR Name,
- USHORT Hint)
-{
- PIMAGE_EXPORT_DIRECTORY ExportDir;
- ULONG ExportDirSize;
- USHORT Idx;
- PVOID ExportAddress;
- PWORD OrdinalList;
- PDWORD FunctionList, NameList;
-
- ExportDir = (PIMAGE_EXPORT_DIRECTORY)
- RtlImageDirectoryEntryToData(ModuleObject->Base,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_EXPORT,
- &ExportDirSize);
- DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
- if (ExportDir == NULL)
- {
- return NULL;
- }
-
- FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
- NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
- OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
-
- ExportAddress = 0;
-
- if (Name != NULL)
+ /*
+ * Check the hint first
+ */
+ if (Hint < ExportDir->NumberOfNames)
{
- for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
+ ExName = RVA(BaseAddress, ExNames[Hint]);
+ if (strcmp(ExName, (PCHAR)SymbolName) == 0)
{
-#if 0
- DPRINT(" Name:%s NameList[%d]:%s\n",
- Name,
- Idx,
- (DWORD) ModuleObject->Base + NameList[Idx]);
-
-#endif
- if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
+ Ordinal = ExOrdinals[Hint];
+ Function = RVA(BaseAddress, ExFunctions[Ordinal]);
+ if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
+ (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
{
- ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
- FunctionList[OrdinalList[Idx]]);
- if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
- ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
- {
- DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
- ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
- DPRINT("ExportAddress: %p\n", ExportAddress);
- }
-
- break;
+ DPRINT("Forward: %s\n", (PCHAR)Function);
+ Function = LdrPEFixupForward((PCHAR)Function);
+ if (Function == NULL)
+ {
+ DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName);
+ }
+ return Function;
+ }
+ if (Function != NULL)
+ {
+ return Function;
}
}
}
- else /* use hint */
- {
- ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
- FunctionList[Hint - ExportDir->Base]);
- }
- if (ExportAddress == 0)
+ /*
+ * Binary search
+ */
+ minn = 0;
+ maxn = ExportDir->NumberOfNames - 1;
+ while (minn <= maxn)
{
- CPRINT("Export not found for %d:%s\n",
- Hint,
- Name != NULL ? Name : "(Ordinal)");
- KeBugCheck(0);
+ mid = (minn + maxn) / 2;
+
+ ExName = RVA(BaseAddress, ExNames[mid]);
+ res = strcmp(ExName, (PCHAR)SymbolName);
+ if (res == 0)
+ {
+ Ordinal = ExOrdinals[mid];
+ Function = RVA(BaseAddress, ExFunctions[Ordinal]);
+ if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
+ (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
+ {
+ DPRINT("Forward: %s\n", (PCHAR)Function);
+ Function = LdrPEFixupForward((PCHAR)Function);
+ if (Function == NULL)
+ {
+ DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName);
+ }
+ return Function;
+ }
+ if (Function != NULL)
+ {
+ return Function;
+ }
+ }
+ else if (res > 0)
+ {
+ maxn = mid - 1;
+ }
+ else
+ {
+ minn = mid + 1;
+ }
}
- return(ExportAddress);
+ ExName = RVA(BaseAddress, ExNames[mid]);
+ DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName);
+ return (PVOID)NULL;
}
-
static PVOID
-LdrSafePEGetExportAddress(PVOID ImportModuleBase,
- PCHAR Name,
- USHORT Hint)
+LdrPEGetExportByOrdinal (
+ PVOID BaseAddress,
+ ULONG Ordinal )
{
- USHORT Idx;
- PVOID ExportAddress;
- PWORD OrdinalList;
- PDWORD FunctionList, NameList;
- PIMAGE_EXPORT_DIRECTORY ExportDir;
- ULONG ExportDirSize;
+ PIMAGE_EXPORT_DIRECTORY ExportDir;
+ ULONG ExportDirSize;
+ PDWORD * ExFunctions;
+ PVOID Function;
+
+ ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData (
+ BaseAddress,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &ExportDirSize);
- static BOOLEAN EP = FALSE;
+ ExFunctions = (PDWORD *)RVA(BaseAddress,
+ ExportDir->AddressOfFunctions);
+ DPRINT("LdrPEGetExportByOrdinal(Ordinal %d) = %x\n",
+ Ordinal,
+ RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base]));
- ExportDir = (PIMAGE_EXPORT_DIRECTORY)
- RtlImageDirectoryEntryToData(ImportModuleBase,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_EXPORT,
- &ExportDirSize);
+ Function = 0 != ExFunctions[Ordinal - ExportDir->Base]
+ ? RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] )
+ : NULL;
- if (!EP) {
- EP = TRUE;
- ps("ExportDir %x\n", ExportDir);
- }
+ if (((ULONG_PTR)Function >= (ULONG_PTR)ExportDir) &&
+ ((ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize))
+ {
+ DPRINT("Forward: %s\n", (PCHAR)Function);
+ Function = LdrPEFixupForward((PCHAR)Function);
+ }
- FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
- NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
- OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
+ return Function;
+}
- ExportAddress = 0;
+static NTSTATUS
+LdrPEProcessImportDirectoryEntry(
+ PVOID DriverBase,
+ PLDR_DATA_TABLE_ENTRY ImportedModule,
+ PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory )
+{
+ PVOID* ImportAddressList;
+ PULONG FunctionNameList;
+ ULONG Ordinal;
- if (Name != NULL)
+ if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
{
- for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
- {
- if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
- {
- ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
- FunctionList[OrdinalList[Idx]]);
- break;
- }
- }
+ return STATUS_UNSUCCESSFUL;
}
- else /* use hint */
- {
- ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
- FunctionList[Hint - ExportDir->Base]);
+ /* Get the import address list. */
+ ImportAddressList = (PVOID*)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
+
+ /* Get the list of functions to import. */
+ if (ImportModuleDirectory->OriginalFirstThunk != 0)
+ {
+ FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->OriginalFirstThunk);
+ }
+ else
+ {
+ FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
}
- if (ExportAddress == 0)
+ /* Walk through function list and fixup addresses. */
+ while (*FunctionNameList != 0L)
{
- ps("Export not found for %d:%s\n",
- Hint,
- Name != NULL ? Name : "(Ordinal)");
- KeBugCheck(0);
+ if ((*FunctionNameList) & 0x80000000)
+ {
+ Ordinal = (*FunctionNameList) & 0x7fffffff;
+ *ImportAddressList = LdrPEGetExportByOrdinal(ImportedModule->DllBase, Ordinal);
+ if ((*ImportAddressList) == NULL)
+ {
+ DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ else
+ {
+ IMAGE_IMPORT_BY_NAME *pe_name;
+ pe_name = RVA(DriverBase, *FunctionNameList);
+ *ImportAddressList = LdrPEGetExportByName(ImportedModule->DllBase, pe_name->Name, pe_name->Hint);
+ if ((*ImportAddressList) == NULL)
+ {
+ DPRINT1("Failed to import %s from %wZ\n", pe_name->Name, &ImportedModule->FullDllName);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ ImportAddressList++;
+ FunctionNameList++;
}
- return ExportAddress;
+ return STATUS_SUCCESS;
}
-
-static PVOID
-LdrPEFixupForward(PCHAR ForwardName)
+static NTSTATUS
+LdrPEFixupImports ( PLDR_DATA_TABLE_ENTRY Module )
{
- CHAR NameBuffer[128];
- UNICODE_STRING ModuleName;
- PCHAR p;
- PMODULE_OBJECT ModuleObject;
-
- DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
-
- strcpy(NameBuffer, ForwardName);
- p = strchr(NameBuffer, '.');
- if (p == NULL)
- {
- return NULL;
- }
-
- *p = 0;
-
- DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
+ PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
+ PCHAR ImportedName;
+ PLDR_DATA_TABLE_ENTRY ImportedModule;
+ NTSTATUS Status;
+ ULONG Size;
+
+ /* Process each import module */
+ ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
+ RtlImageDirectoryEntryToData(Module->DllBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_IMPORT,
+ &Size);
+ DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
+ while (ImportModuleDirectory->Name)
+ {
+ if (Module->SizeOfImage <= ImportModuleDirectory->Name)
+ {
+ DPRINT1("Invalid import directory in %wZ\n", &Module->FullDllName);
+ return STATUS_SECTION_NOT_IMAGE;
+ }
- RtlCreateUnicodeStringFromAsciiz(&ModuleName,
- NameBuffer);
- ModuleObject = LdrGetModuleObject(&ModuleName);
- RtlFreeUnicodeString(&ModuleName);
+ /* Check to make sure that import lib is kernel */
+ ImportedName = (PCHAR) Module->DllBase + ImportModuleDirectory->Name;
- DPRINT("ModuleObject: %p\n", ModuleObject);
+ Status = LdrPEGetOrLoadModule(Module, ImportedName, &ImportedModule);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
- if (ModuleObject == NULL)
- {
- CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
- return NULL;
- }
+ Status = LdrPEProcessImportDirectoryEntry(Module->DllBase, ImportedModule, ImportModuleDirectory);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
- return(LdrPEGetExportAddress(ModuleObject, p+1, 0));
+ ImportModuleDirectory++;
+ }
+ return STATUS_SUCCESS;
}
/* EOF */