-/*
+/* $Id: loader.c,v 1.74 2001/04/23 22:00:28 ea Exp $
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ldr/loader.c
* PURPOSE: Loaders for PE executables
- * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com)
+ * 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 loader function and added hooks for MZ/PE
+ * 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 <internal/i386/segment.h>
-#include <internal/kernel.h>
-#include <internal/linkage.h>
+#include <limits.h>
+#include <ddk/ntddk.h>
+#include <internal/config.h>
#include <internal/module.h>
-#include <internal/string.h>
-#include <internal/symbol.h>
+#include <internal/ntoskrnl.h>
+#include <internal/mm.h>
+#include <internal/ob.h>
+#include <internal/ps.h>
+#include <internal/ldr.h>
+#include <internal/pool.h>
+
+#define NDEBUG
+#include <internal/debug.h>
-#include <ddk/ntddk.h>
-#include <ddk/li.h>
-//#define NDEBUG
-#include <internal/debug.h>
+/* FIXME: this should appear in a kernel header file */
+NTSTATUS IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry);
-#include "pe.h"
+/* MACROS ********************************************************************/
-/* FUNCTIONS *****************************************************************/
+#define MODULE_ROOT_NAME L"\\Modules\\"
-/* COFF Driver load support **************************************************/
-static BOOLEAN LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex);
-static BOOLEAN LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
-static BOOLEAN LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
-static void LdrCOFFGetSymbolName(module *Module, unsigned int Idx, char *Name);
-static unsigned int LdrCOFFGetSymbolValue(module *Module, unsigned int Idx);
-static unsigned int LdrCOFFGetKernelSymbolAddr(char *Name);
-static unsigned int LdrCOFFGetSymbolValueByName(module *Module, char *SymbolName, unsigned int Idx);
+/* GLOBALS *******************************************************************/
-static NTSTATUS
-LdrCOFFProcessDriver(HANDLE FileHandle)
+LIST_ENTRY ModuleListHead;
+POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;
+LIST_ENTRY ModuleTextListHead;
+STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
+/* STATIC MODULE_TEXT_SECTION HalTextSection; */
+
+#define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
+#define TAG_SYM_BUF TAG('S', 'Y', 'M', 'B')
+
+/* FORWARD DECLARATIONS ******************************************************/
+
+PMODULE_OBJECT LdrLoadModule(PUNICODE_STRING Filename);
+PMODULE_OBJECT LdrProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING ModuleName);
+PVOID LdrGetExportAddress(PMODULE_OBJECT ModuleObject, char *Name, unsigned short Hint);
+static PMODULE_OBJECT LdrOpenModule(PUNICODE_STRING Filename);
+static NTSTATUS LdrCreateModule(PVOID ObjectBody,
+ PVOID Parent,
+ PWSTR RemainingPath,
+ POBJECT_ATTRIBUTES ObjectAttributes);
+static VOID LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
+ PUNICODE_STRING FullName);
+
+/* PE Driver load support */
+static PMODULE_OBJECT LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING FileName);
+static PVOID LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
+ char *Name,
+ unsigned short Hint);
+static PMODULE_OBJECT LdrPEGetModuleObject(PUNICODE_STRING ModuleName);
+static PVOID LdrPEFixupForward(PCHAR ForwardName);
+
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
{
- BOOLEAN FoundEntry;
- char SymbolName[255];
- int i;
- NTSTATUS Status;
- PVOID ModuleLoadBase;
- ULONG EntryOffset;
- FILHDR *FileHeader;
- AOUTHDR *AOUTHeader;
- module *Module;
- FILE_STANDARD_INFORMATION FileStdInfo;
- PDRIVER_INITIALIZE EntryRoutine;
+ PLIST_ENTRY current_entry;
+ MODULE_TEXT_SECTION* current;
- /* Get the size of the file for the section */
- Status = ZwQueryInformationFile(FileHandle,
- NULL,
- &FileStdInfo,
- sizeof(FileStdInfo),
- FileStandardInformation);
- if (!NT_SUCCESS(Status))
+ current_entry = ModuleTextListHead.Flink;
+ while (current_entry != &ModuleTextListHead)
{
- return Status;
+ current =
+ CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
+ if (wcscmp(current->Name, Name) == 0)
+ {
+ break;
+ }
+ current_entry = current_entry->Flink;
}
- CHECKPOINT;
- /* Allocate nonpageable memory for driver */
- ModuleLoadBase = ExAllocatePool(NonPagedPool,
- GET_LARGE_INTEGER_LOW_PART(FileStdInfo.AllocationSize));
- if (ModuleLoadBase == NULL)
+ if (current_entry == &ModuleTextListHead)
{
- return STATUS_INSUFFICIENT_RESOURCES;
+ return;
}
- CHECKPOINT;
+
+ current->SymbolsBase = (PVOID)Module->ModStart;
+ current->SymbolsLength = Module->ModEnd - Module->ModStart;
+}
- /* Load driver into memory chunk */
- Status = ZwReadFile(FileHandle,
- 0, 0, 0, 0,
- ModuleLoadBase,
- GET_LARGE_INTEGER_LOW_PART(FileStdInfo.AllocationSize),
- 0, 0);
- if (!NT_SUCCESS(Status))
+VOID
+LdrInit1(VOID)
+{
+ PIMAGE_DOS_HEADER DosHeader;
+ PIMAGE_FILE_HEADER FileHeader;
+ PIMAGE_OPTIONAL_HEADER OptionalHeader;
+ PIMAGE_SECTION_HEADER SectionList;
+
+ InitializeListHead(&ModuleTextListHead);
+
+ 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 = L"ntoskrnl.exe";
+ NtoskrnlTextSection.SymbolsBase = NULL;
+ NtoskrnlTextSection.SymbolsLength = 0;
+ InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
+}
+
+VOID LdrInitModuleManagement(VOID)
+{
+ HANDLE DirHandle, ModuleHandle;
+ NTSTATUS Status;
+ WCHAR NameBuffer[60];
+ UNICODE_STRING ModuleName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PIMAGE_DOS_HEADER DosHeader;
+ PMODULE_OBJECT ModuleObject;
+
+ /* Register the process object type */
+ IoDriverObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
+ IoDriverObjectType->Tag = TAG('D', 'R', 'V', 'T');
+ IoDriverObjectType->TotalObjects = 0;
+ IoDriverObjectType->TotalHandles = 0;
+ IoDriverObjectType->MaxObjects = ULONG_MAX;
+ IoDriverObjectType->MaxHandles = ULONG_MAX;
+ IoDriverObjectType->PagedPoolCharge = 0;
+ IoDriverObjectType->NonpagedPoolCharge = sizeof(MODULE);
+ IoDriverObjectType->Dump = NULL;
+ IoDriverObjectType->Open = NULL;
+ IoDriverObjectType->Close = NULL;
+ IoDriverObjectType->Delete = NULL;
+ IoDriverObjectType->Parse = NULL;
+ IoDriverObjectType->Security = NULL;
+ IoDriverObjectType->QueryName = NULL;
+ IoDriverObjectType->OkayToClose = NULL;
+ IoDriverObjectType->Create = LdrCreateModule;
+ RtlInitUnicodeString(&IoDriverObjectType->TypeName, L"Driver");
+
+ /* Create Modules object directory */
+ wcscpy(NameBuffer, MODULE_ROOT_NAME);
+ *(wcsrchr(NameBuffer, L'\\')) = 0;
+ RtlInitUnicodeString (&ModuleName, NameBuffer);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ModuleName,
+ 0,
+ NULL,
+ NULL);
+ DPRINT("Create dir: %wZ\n", &ModuleName);
+ Status = NtCreateDirectoryObject(&DirHandle, 0, &ObjectAttributes);
+ assert(NT_SUCCESS(Status));
+
+ /* Add module entry for NTOSKRNL */
+ wcscpy(NameBuffer, MODULE_ROOT_NAME);
+ wcscat(NameBuffer, L"ntoskrnl.exe");
+ RtlInitUnicodeString (&ModuleName, NameBuffer);
+ DPRINT("Kernel's Module name is: %wZ\n", &ModuleName);
+
+ /* Initialize ObjectAttributes for ModuleObject */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ModuleName,
+ 0,
+ NULL,
+ NULL);
+
+ /* Create module object */
+ ModuleHandle = 0;
+ ModuleObject = ObCreateObject(&ModuleHandle,
+ STANDARD_RIGHTS_REQUIRED,
+ &ObjectAttributes,
+ IoDriverObjectType);
+ assert(ModuleObject != NULL);
+
+ InitializeListHead(&ModuleListHead);
+
+ /* Initialize ModuleObject data */
+ ModuleObject->Base = (PVOID) KERNEL_BASE;
+ ModuleObject->Flags = MODULE_FLAG_PE;
+ InsertTailList(&ModuleListHead,
+ &ModuleObject->ListEntry);
+ RtlCreateUnicodeString(&ModuleObject->FullName,
+ L"ntoskrnl.exe");
+ 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;
+
+ /* FIXME: Add fake module entry for HAL */
+
+}
+
+/*
+ * load the auto config drivers.
+ */
+static VOID LdrLoadAutoConfigDriver (LPWSTR RelativeDriverName)
+{
+ WCHAR TmpFileName [MAX_PATH];
+ NTSTATUS Status;
+ UNICODE_STRING DriverName;
+
+ DbgPrint("Loading %S\n",RelativeDriverName);
+
+ wcscpy(TmpFileName, L"\\SystemRoot\\system32\\drivers\\");
+ wcscat(TmpFileName, RelativeDriverName);
+ RtlInitUnicodeString (&DriverName, TmpFileName);
+
+ Status = LdrLoadDriver(&DriverName);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("driver load failed, status (%x)\n", Status);
+// KeBugCheck(0);
+ }
+}
+
+#ifdef KDBG
+
+BOOLEAN LdrReadLine(PCHAR Line,
+ PVOID *Buffer,
+ PULONG Size)
+{
+ CHAR ch;
+ PCHAR Block;
+
+ if (*Size == 0)
+ return FALSE;
+
+ Block = *Buffer;
+ while ((*Size > 0) && ((ch = *Block) != (CHAR)13))
{
- ExFreePool(ModuleLoadBase);
- return Status;
+ *Line = ch;
+ Line++;
+ Block++;
+ *Size -= 1;
}
- CHECKPOINT;
+ *Line = (CHAR)0;
- /* Get header pointers */
- FileHeader = ModuleLoadBase;
- AOUTHeader = ModuleLoadBase + FILHSZ;
- CHECKPOINT;
+ Block++;
+ *Size -= 1;
- /* Check COFF magic value */
- if (I386BADMAG(*FileHeader))
+ if ((*Size > 0) && (*Block == (CHAR)10))
{
- DbgPrint("Module has bad magic value (%x)\n",
- FileHeader->f_magic);
- ExFreePool(ModuleLoadBase);
- return STATUS_UNSUCCESSFUL;
+ Block++;
+ *Size -= 1;
}
- CHECKPOINT;
-
- /* Allocate and initialize a module definition structure */
- Module = (module *) ExAllocatePool(NonPagedPool, sizeof(module));
- if (Module == NULL)
- {
- ExFreePool(ModuleLoadBase);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- Module->sym_list = (SYMENT *)(ModuleLoadBase + FileHeader->f_symptr);
- Module->str_tab = (char *)(ModuleLoadBase + FileHeader->f_symptr +
- FileHeader->f_nsyms * SYMESZ);
- Module->scn_list = (SCNHDR *)(ModuleLoadBase + FILHSZ +
- FileHeader->f_opthdr);
- Module->size = 0;
- Module->raw_data_off = (ULONG) ModuleLoadBase;
- Module->nsyms = FileHeader->f_nsyms;
- CHECKPOINT;
- /* Determine the length of the module */
- for (i = 0; i < FileHeader->f_nscns; i++)
+ *Buffer = Block;
+
+ return TRUE;
+}
+
+ULONG HexL(PCHAR Buffer)
+{
+ CHAR ch;
+ UINT i, j;
+ ULONG Value;
+
+ j = 32;
+ i = 0;
+ Value = 0;
+ while ((j > 0) && ((ch = Buffer[i]) != ' '))
{
- DPRINT("Section name: %.8s\n", Module->scn_list[i].s_name);
- DPRINT("size %x vaddr %x size %x\n",
- Module->size,
- Module->scn_list[i].s_vaddr,
- Module->scn_list[i].s_size);
- if (Module->scn_list[i].s_flags & STYP_TEXT)
- {
- Module->text_base = Module->scn_list[i].s_vaddr;
- }
- if (Module->scn_list[i].s_flags & STYP_DATA)
- {
- Module->data_base = Module->scn_list[i].s_vaddr;
- }
- if (Module->scn_list[i].s_flags & STYP_BSS)
- {
- Module->bss_base = Module->scn_list[i].s_vaddr;
- }
- if (Module->size <
- (Module->scn_list[i].s_vaddr + Module->scn_list[i].s_size))
- {
- Module->size = Module->size + Module->scn_list[i].s_vaddr +
- Module->scn_list[i].s_size;
- }
+ 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++;
}
- CHECKPOINT;
+ return Value;
+}
+
+PSYMBOL LdrParseLine(PCHAR Line,
+ PULONG ImageBase,
+ PBOOLEAN ImageBaseValid)
+/*
+ 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
+*/
+{
+ ANSI_STRING AnsiString;
+ CHAR Buffer[128];
+ PSYMBOL Symbol;
+ ULONG Address;
+ PCHAR Str;
+ CHAR Type;
+
+ *ImageBaseValid = FALSE;
+
+ if ((Line[0] == (CHAR)0) || (Line[0] == ' '))
+ return NULL;
+
+ Address = HexL(Line);
+
+ Line = strchr(Line, ' ');
+ if (Line == NULL)
+ return NULL;
- /* Allocate a section for the module */
- Module->base = (unsigned int) MmAllocateSection(Module->size);
- if (Module->base == 0)
+ 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, "__image_base__")) == 0)
{
- DbgPrint("Failed to alloc section for module\n");
- ExFreePool(Module);
- ExFreePool(ModuleLoadBase);
- return STATUS_INSUFFICIENT_RESOURCES;
+ *ImageBase = Address;
+ *ImageBaseValid = TRUE;
+ return NULL;
}
- CHECKPOINT;
- /* Adjust section vaddrs for allocated area */
- Module->data_base = Module->data_base + Module->base;
- Module->text_base = Module->text_base + Module->base;
- Module->bss_base = Module->bss_base + Module->base;
-
- /* Relocate module and fixup imports */
- for (i = 0; i < FileHeader->f_nscns; i++)
+ /* We only want symbols in the .text segment */
+ if ((Type != 't') && (Type != 'T'))
+ return NULL;
+
+ /* Discard other symbols we can't use */
+ if ((Buffer[0] != '_') || ((Buffer[0] == '_') && (Buffer[1] == '_')))
+ return NULL;
+
+ Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
+ if (!Symbol)
+ return NULL;
+
+ Symbol->Next = NULL;
+
+ Symbol->RelativeAddress = Address;
+
+ RtlInitAnsiString(&AnsiString, (PCSZ)&Buffer);
+ RtlAnsiStringToUnicodeString(&Symbol->Name, &AnsiString, TRUE);
+
+ return Symbol;
+}
+
+VOID LdrLoadModuleSymbols(PMODULE_OBJECT ModuleObject,
+ MODULE_TEXT_SECTION* ModuleTextSection)
+/*
+ Symbols must be sorted by address, e.g.
+ "nm --numeric-sort module.sys > module.sym"
+ */
+{
+ WCHAR TmpFileName[MAX_PATH];
+ LPWSTR Start, Ext;
+ ULONG Length, Tmp;
+ UNICODE_STRING Filename;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ HANDLE FileHandle;
+ PVOID FileBuffer, FilePtr;
+ CHAR Line[256];
+ FILE_STANDARD_INFORMATION FileStdInfo;
+ BOOLEAN ImageBaseValid;
+ ULONG ImageBase = 0;
+ PSYMBOL Symbol, CurrentSymbol = 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,
+ NULL, 0, 0);
+ if (!NT_SUCCESS(Status))
{
- if (Module->scn_list[i].s_flags & STYP_TEXT ||
- Module->scn_list[i].s_flags & STYP_DATA)
- {
- memcpy((PVOID)(Module->base + Module->scn_list[i].s_vaddr),
- (PVOID)(ModuleLoadBase + Module->scn_list[i].s_scnptr),
- Module->scn_list[i].s_size);
- if (!LdrCOFFDoRelocations(Module, i))
- {
- DPRINT("Relocation failed for section %s\n",
- Module->scn_list[i].s_name);
- ExFreePool(Module);
- ExFreePool(ModuleLoadBase);
- return STATUS_UNSUCCESSFUL;
- }
- }
- if (Module->scn_list[i].s_flags & STYP_BSS)
- {
- memset((PVOID)(Module->base + Module->scn_list[i].s_vaddr),
- 0,
- Module->scn_list[i].s_size);
- }
+ DPRINT("Could not open symbol file: %wZ\n", &Filename);
+ return;
}
-
- DbgPrint("Module base: %x\n", Module->base);
-
- /* Find the entry point */
- EntryOffset = 0L;
- FoundEntry = FALSE;
- for (i = 0; i < FileHeader->f_nsyms; i++)
+
+ DbgPrint("Loading symbols from %wZ...\n", &Filename);
+
+ /* Get the size of the file */
+ Status = ZwQueryInformationFile(FileHandle,
+ NULL,
+ &FileStdInfo,
+ sizeof(FileStdInfo),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
{
- LdrCOFFGetSymbolName(Module, i, SymbolName);
- if (!strcmp(SymbolName, "_DriverEntry"))
- {
- EntryOffset = Module->sym_list[i].e_value;
- FoundEntry = TRUE;
- DPRINT("Found entry at %x\n", EntryOffset);
- }
+ DPRINT("Could not get file size\n");
+ return;
}
- if (!FoundEntry)
+
+ /* Allocate nonpageable memory for symbol file */
+ FileBuffer = ExAllocatePool(NonPagedPool,
+ FileStdInfo.EndOfFile.u.LowPart);
+
+ if (FileBuffer == NULL)
{
- DbgPrint("No module entry point defined\n");
- ExFreePool(Module);
- ExFreePool(ModuleLoadBase);
- return STATUS_UNSUCCESSFUL;
+ DPRINT("Could not allocate memory for symbol file\n");
+ return;
}
- /* Call the module initalization routine */
- EntryRoutine = (PDRIVER_INITIALIZE)(Module->base + EntryOffset);
+ /* Load file into memory chunk */
+ Status = ZwReadFile(FileHandle,
+ 0, 0, 0, 0,
+ FileBuffer,
+ FileStdInfo.EndOfFile.u.LowPart,
+ 0, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Could not read symbol file into memory\n");
+ ExFreePool(FileBuffer);
+ return;
+ }
- return InitalizeLoadedDriver(EntryRoutine);
-}
+ ZwClose(FileHandle);
-/* LdrCOFFDoRelocations
- * FUNCTION: Do the relocations for a module section
- * ARGUMENTS:
- * Module = Pointer to the module
- * SectionIndex = Index of the section to be relocated
- * RETURNS: Success or failure
- */
+ ModuleTextSection->Symbols.SymbolCount = 0;
+ ModuleTextSection->Symbols.Symbols = NULL;
-static BOOLEAN
-LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex)
-{
- SCNHDR *Section = &Module->scn_list[SectionIndex];
- RELOC *Relocation = (RELOC *)(Module->raw_data_off + Section->s_relptr);
- int j;
-
- DPRINT("SectionIndex %d Name %.8s Relocs %d\n",
- SectionIndex,
- Module->scn_list[SectionIndex].s_name,
- Section->s_nreloc);
+ FilePtr = FileBuffer;
+ Length = FileStdInfo.EndOfFile.u.LowPart;
- for (j = 0; j < Section->s_nreloc; j++)
+ while (LdrReadLine((PCHAR)&Line, &FilePtr, &Length))
{
- DbgPrint("vaddr %x ", Relocation->r_vaddr);
- DbgPrint("symndex %x ", Relocation->r_symndx);
+ Symbol = LdrParseLine((PCHAR)&Line, &Tmp, &ImageBaseValid);
+
+ if (ImageBaseValid)
+ ImageBase = Tmp;
- switch (Relocation->r_type)
+ if (Symbol != NULL)
{
- case RELOC_ADDR32:
- if (!LdrCOFFDoAddr32Reloc(Module, Section, Relocation))
- {
- return FALSE;
- }
- break;
-
- case RELOC_REL32:
- if (!LdrCOFFDoReloc32Reloc(Module, Section, Relocation))
- {
- return FALSE;
- }
- break;
-
- default:
- DbgPrint("%.8s: Unknown relocation type %x at %d in module\n",
- Module->scn_list[SectionIndex].s_name,
- Relocation->r_type,
- j);
- return FALSE;
+ Symbol->RelativeAddress -= ImageBase;
+
+ if (ModuleTextSection->Symbols.Symbols == NULL)
+ ModuleTextSection->Symbols.Symbols = Symbol;
+ else
+ CurrentSymbol->Next = Symbol;
+
+ CurrentSymbol = Symbol;
+
+ ModuleTextSection->Symbols.SymbolCount++;
}
- Relocation++;
}
- DPRINT("%.8s: relocations done\n", Module->scn_list[SectionIndex].s_name);
-
- return TRUE;
-}
-/*
- * FUNCTION: Performs a addr32 relocation on a loaded module
- * ARGUMENTS:
- * mod = module to perform the relocation on
- * scn = Section to perform the relocation in
- * reloc = Pointer to a data structure describing the relocation
- * RETURNS: Success or failure
- * NOTE: This fixes up a relocation needed when changing the base address of a
- * module
- */
+ ExFreePool(FileBuffer);
+}
+
+#endif /* KDBG */
-static BOOLEAN
-LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation)
+VOID LdrLoadAutoConfigDrivers (VOID)
{
- unsigned int Value;
- unsigned int *Location;
+
+#ifdef KDBG
+
+ NTSTATUS Status;
+ WCHAR NameBuffer[60];
+ UNICODE_STRING ModuleName;
+ PMODULE_OBJECT ModuleObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING RemainingPath;
+
+ /* Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot
+ is created after their module entries */
+
+ wcscpy(NameBuffer, MODULE_ROOT_NAME);
+ wcscat(NameBuffer, L"ntoskrnl.exe");
+ RtlInitUnicodeString(&ModuleName, NameBuffer);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ModuleName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = ObFindObject(&ObjectAttributes,
+ (PVOID*)&ModuleObject,
+ &RemainingPath,
+ NULL);
+ if (NT_SUCCESS(Status)) {
+ RtlFreeUnicodeString(&RemainingPath);
+
+ LdrLoadModuleSymbols(ModuleObject, &NtoskrnlTextSection);
+ }
+
+ /* FIXME: Load symbols for hal.dll */
+
+#endif /* KDBG */
+
+ /*
+ * Keyboard driver
+ */
+ LdrLoadAutoConfigDriver( L"keyboard.sys" );
- Value = LdrCOFFGetSymbolValue(Module, Relocation->r_symndx);
- Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
- DbgPrint("ADDR32 loc %x value %x *loc %x ", Location, Value, *Location);
- *Location = (*Location) + Module->base;
+ /*
+ * Raw console driver
+ */
+ LdrLoadAutoConfigDriver( L"blue.sys" );
- return TRUE;
+ /*
+ *
+ */
+ LdrLoadAutoConfigDriver(L"vidport.sys");
+
+ /*
+ *
+ */
+ LdrLoadAutoConfigDriver(L"vgamp.sys");
+
+ /*
+ * Minix filesystem driver
+ */
+ LdrLoadAutoConfigDriver(L"minixfs.sys");
+
+ /*
+ * Networking
+ */
+#if 0
+ /*
+ * NDIS library
+ */
+ LdrLoadAutoConfigDriver(L"ndis.sys");
+
+ /*
+ * Novell Eagle 2000 driver
+ */
+ LdrLoadAutoConfigDriver(L"ne2000.sys");
+
+ /*
+ * TCP/IP protocol driver
+ */
+ LdrLoadAutoConfigDriver(L"tcpip.sys");
+
+ /*
+ * TDI test driver
+ */
+ LdrLoadAutoConfigDriver(L"tditest.sys");
+
+ /*
+ * Ancillary Function Driver
+ */
+ LdrLoadAutoConfigDriver(L"afd.sys");
+#endif
}
-/*
- * FUNCTION: Performs a reloc32 relocation on a loaded module
- * ARGUMENTS:
- * mod = module to perform the relocation on
- * scn = Section to perform the relocation in
- * reloc = Pointer to a data structure describing the relocation
- * RETURNS: Success or failure
- * NOTE: This fixes up an undefined reference to a kernel function in a module
- */
-static BOOLEAN
-LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation)
+static NTSTATUS
+LdrCreateModule(PVOID ObjectBody,
+ PVOID Parent,
+ PWSTR RemainingPath,
+ POBJECT_ATTRIBUTES ObjectAttributes)
{
- char Name[255];
- unsigned int Value;
- unsigned int *Location;
-
- memset(Name, 0, 255);
- LdrCOFFGetSymbolName(Module, Relocation->r_symndx, Name);
- Value = (unsigned int) LdrCOFFGetKernelSymbolAddr(Name);
- if (Value == 0L)
+ DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+ ObjectBody,
+ Parent,
+ RemainingPath);
+ if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
{
- Value = LdrCOFFGetSymbolValueByName(Module, Name, Relocation->r_symndx);
- if (Value == 0L)
- {
- DbgPrint("Undefined symbol %s in module\n", Name);
- return FALSE;
- }
- Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
-// (*Location) = (*Location) + Value + Module->base - Section->s_vaddr;
- (*Location) = (*Location);
- DPRINT("Module->base %x Section->s_vaddr %x\n",
- Module->base,
- Section->s_vaddr);
+ return STATUS_UNSUCCESSFUL;
}
- else
+ if (Parent != NULL && RemainingPath != NULL)
{
- DPRINT("REL32 value %x name %s\n", Value, Name);
- Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
- DPRINT("old %x ", *Location);
- DPRINT("Module->base %x Section->s_vaddr %x\n",
- Module->base,
- Section->s_vaddr);
- (*Location) = (*Location) + Value - Module->base + Section->s_vaddr;
- DPRINT("new %x\n", *Location);
+ ObAddEntryDirectory(Parent, ObjectBody, RemainingPath + 1);
}
- return TRUE;
+ return STATUS_SUCCESS;
}
/*
- * FUNCTION: Get the name of a symbol from a loaded module by ordinal
+ * FUNCTION: Loads a kernel driver
* ARGUMENTS:
- * mod = module
- * i = index of symbol
- * name (OUT) = pointer to a string where the symbol name will be
- * stored
+ * FileName = Driver to load
+ * RETURNS: Status
*/
-static void
-LdrCOFFGetSymbolName(module *Module, unsigned int Idx, char *Name)
+NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename)
{
- if (Module->sym_list[Idx].e.e_name[0] != 0)
+ PMODULE_OBJECT ModuleObject;
+
+ ModuleObject = LdrLoadModule(Filename);
+ if (ModuleObject == 0)
{
- strncpy(Name, Module->sym_list[Idx].e.e_name, 8);
- Name[8] = '\0';
+ return STATUS_UNSUCCESSFUL;
}
- else
+
+ /* FIXME: should we dereference the ModuleObject here? */
+
+ return IoInitializeDriver(ModuleObject->EntryPoint);
+}
+
+NTSTATUS LdrLoadGdiDriver (PUNICODE_STRING DriverName,
+ PVOID *ImageAddress,
+ PVOID *SectionPointer,
+ PVOID *EntryPoint,
+ PVOID *ExportSectionPointer)
+{
+ PMODULE_OBJECT ModuleObject;
+
+ ModuleObject = LdrLoadModule(DriverName);
+ if (ModuleObject == 0)
{
- strcpy(Name, &Module->str_tab[Module->sym_list[Idx].e.e.e_offset]);
+ return STATUS_UNSUCCESSFUL;
}
+
+ if (ImageAddress)
+ *ImageAddress = ModuleObject->Base;
+
+// if (SectionPointer)
+// *SectionPointer = ModuleObject->
+
+ if (EntryPoint)
+ *EntryPoint = ModuleObject->EntryPoint;
+
+// if (ExportSectionPointer)
+// *ExportSectionPointer = ModuleObject->
+
+ return STATUS_SUCCESS;
}
-/*
- * FUNCTION: Get the value of a module defined symbol
- * ARGUMENTS:
- * mod = module
- * i = index of symbol
- * RETURNS: The value of the symbol
- * NOTE: This fixes up references to known sections
- */
-static unsigned int
-LdrCOFFGetSymbolValue(module *Module, unsigned int Idx)
+PMODULE_OBJECT
+LdrLoadModule(PUNICODE_STRING Filename)
{
- char Name[255];
+ PVOID ModuleLoadBase;
+ NTSTATUS Status;
+ HANDLE FileHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PMODULE_OBJECT ModuleObject;
+ FILE_STANDARD_INFORMATION FileStdInfo;
- LdrCOFFGetSymbolName(Module, Idx, Name);
- DbgPrint("name %s ", Name);
-
- /* Check if the symbol is a section we have relocated */
- if (strcmp(Name, ".text") == 0)
+ /* Check for module already loaded */
+ if ((ModuleObject = LdrOpenModule(Filename)) != NULL)
{
- return Module->text_base;
+ return ModuleObject;
}
- if (strcmp(Name, ".data") == 0)
+
+ DPRINT("Loading Module %wZ...\n", Filename);
+
+ /* Open the Module */
+ InitializeObjectAttributes(&ObjectAttributes,
+ Filename,
+ 0,
+ NULL,
+ NULL);
+ CHECKPOINT;
+ Status = NtOpenFile(&FileHandle,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ NULL, 0, 0);
+ CHECKPOINT;
+ if (!NT_SUCCESS(Status))
{
- return Module->data_base;
+ DbgPrint("Could not open module file: %wZ\n", Filename);
+ return 0;
}
- if (strcmp(Name, ".bss") == 0)
+ CHECKPOINT;
+
+ /* Get the size of the file */
+ Status = NtQueryInformationFile(FileHandle,
+ NULL,
+ &FileStdInfo,
+ sizeof(FileStdInfo),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
{
- return Module->bss_base;
+ DbgPrint("Could not get file size\n");
+ return 0;
}
+ CHECKPOINT;
- return Module->sym_list[Idx].e_value;
-}
-
-/*
- * FUNCTION: Get the address of a kernel symbol
- * ARGUMENTS:
- * name = symbol name
- * RETURNS: The address of the symbol on success
- * NULL on failure
- */
-
-static unsigned int
-LdrCOFFGetKernelSymbolAddr(char *Name)
-{
- int i = 0;
+ /* Allocate nonpageable memory for driver */
+ ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
+ FileStdInfo.EndOfFile.u.LowPart,
+ TAG_DRIVER_MEM);
- while (symbol_table[i].name != NULL)
+ if (ModuleLoadBase == NULL)
{
- if (strcmp(symbol_table[i].name, Name) == 0)
- {
- return symbol_table[i].value;
- }
- i++;
+ DbgPrint("could not allocate memory for module");
+ return 0;
}
-
- return 0L;
-}
-
-static unsigned int
-LdrCOFFGetSymbolValueByName(module *Module,
- char *SymbolName,
- unsigned int Idx)
-{
- unsigned int i;
- char Name[255];
-
- DPRINT("LdrCOFFGetSymbolValueByName(sname %s, idx %x)\n", SymbolName, Idx);
+ CHECKPOINT;
- for (i = 0; i < Module->nsyms; i++)
+ /* Load driver into memory chunk */
+ Status = NtReadFile(FileHandle,
+ 0, 0, 0, 0,
+ ModuleLoadBase,
+ FileStdInfo.EndOfFile.u.LowPart,
+ 0, 0);
+ if (!NT_SUCCESS(Status))
{
- LdrCOFFGetSymbolName(Module, i, Name);
- DPRINT("Scanning %s Value %x\n", Name, Module->sym_list[i].e_value);
- if (strcmp(Name, SymbolName) == 0)
- {
- DPRINT("Returning %x\n", Module->sym_list[i].e_value);
- return Module->sym_list[i].e_value;
- }
+ DbgPrint("could not read module file into memory");
+ ExFreePool(ModuleLoadBase);
+
+ return 0;
}
+ CHECKPOINT;
- return 0L;
-}
+ NtClose(FileHandle);
+ ModuleObject = LdrProcessModule(ModuleLoadBase, Filename);
+ /* Cleanup */
+ ExFreePool(ModuleLoadBase);
+ return ModuleObject;
+}
-static NTSTATUS
-LdrProcessPEDriver(HANDLE FileHandle, PIMAGE_DOS_HEADER DosHeader)
+NTSTATUS
+LdrProcessDriver(PVOID ModuleLoadBase, PCHAR FileName)
{
- return STATUS_NOT_IMPLEMENTED;
+ PMODULE_OBJECT ModuleObject;
+ UNICODE_STRING ModuleName;
+
+ RtlCreateUnicodeStringFromAsciiz(&ModuleName,
+ FileName);
+ ModuleObject = LdrProcessModule(ModuleLoadBase,
+ &ModuleName);
+ RtlFreeUnicodeString(&ModuleName);
+ if (ModuleObject == NULL)
+ {
+ DPRINT1("Driver load was unsuccessful\n");
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ /* FIXME: should we dereference the ModuleObject here? */
+
+ return(IoInitializeDriver(ModuleObject->EntryPoint));
}
-NTSTATUS
-LdrLoadDriver(PUNICODE_STRING Filename)
-/*
- * FUNCTION: Loads a kernel driver
- * ARGUMENTS:
- * FileName = Driver to load
- * RETURNS: Status
- */
+PMODULE_OBJECT
+LdrProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING ModuleName)
{
- char BlockBuffer[512];
- NTSTATUS Status;
- HANDLE FileHandle;
- OBJECT_ATTRIBUTES FileObjectAttributes;
PIMAGE_DOS_HEADER PEDosHeader;
- /* Open the Driver */
- InitializeObjectAttributes(&FileObjectAttributes,
- Filename,
- 0,
- NULL,
- NULL);
- Status = ZwOpenFile(&FileHandle, 0, &FileObjectAttributes, NULL, 0, 0);
- if (!NT_SUCCESS(Status))
+ /* If MZ header exists */
+ PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
+ if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
{
- return Status;
+ return LdrPEProcessModule(ModuleLoadBase, ModuleName);
}
- /* Read first block of image to determine type */
- Status = ZwReadFile(FileHandle, 0, 0, 0, 0, BlockBuffer, 512, 0, 0);
- if (!NT_SUCCESS(Status))
- {
- ZwClose(FileHandle);
- return Status;
- }
+ DPRINT1("Module wasn't PE\n");
+ return 0;
+}
- /* If MZ header exists */
- PEDosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
- if (PEDosHeader->e_magic == 0x54AD && PEDosHeader->e_lfanew != 0L)
+static PMODULE_OBJECT
+LdrOpenModule(PUNICODE_STRING Filename)
+{
+ NTSTATUS Status;
+ WCHAR NameBuffer[60];
+ UNICODE_STRING ModuleName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PMODULE_OBJECT ModuleObject;
+ UNICODE_STRING RemainingPath;
+
+ wcscpy(NameBuffer, MODULE_ROOT_NAME);
+ if (wcsrchr(Filename->Buffer, '\\') != 0)
{
- Status = LdrProcessPEDriver(FileHandle, PEDosHeader);
- if (!NT_SUCCESS(Status))
- {
- ZwClose(FileHandle);
- return Status;
- }
+ wcscat(NameBuffer, wcsrchr(Filename->Buffer, '\\') + 1);
}
- if (PEDosHeader->e_magic == 0x54AD)
+ else
{
- ZwClose(FileHandle);
- return STATUS_NOT_IMPLEMENTED;
+ wcscat(NameBuffer, Filename->Buffer);
}
- else /* Assume coff format and load */
+ RtlInitUnicodeString (&ModuleName, NameBuffer);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ModuleName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = ObFindObject(&ObjectAttributes,
+ (PVOID *) &ModuleObject,
+ &RemainingPath,
+ NULL);
+ CHECKPOINT;
+ if (NT_SUCCESS(Status) && (RemainingPath.Buffer == NULL || *(RemainingPath.Buffer) == 0))
{
- Status = LdrCOFFProcessDriver(FileHandle);
- if (!NT_SUCCESS(Status))
- {
- ZwClose(FileHandle);
- return Status;
- }
+ DPRINT("Module %wZ at %p\n", Filename, ModuleObject);
+ RtlFreeUnicodeString (&RemainingPath);
+
+ return ModuleObject;
}
- return STATUS_NOT_IMPLEMENTED;
+ RtlFreeUnicodeString (&RemainingPath);
+
+ return NULL;
}
-static NTSTATUS
-LdrProcessMZImage(HANDLE ProcessHandle,
- HANDLE FileHandle,
- PIMAGE_DOS_HEADER DosHeader)
+PVOID
+LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
+ char *Name,
+ unsigned short Hint)
{
+ if (ModuleObject->Flags & MODULE_FLAG_PE)
+ {
+ return LdrPEGetExportAddress(ModuleObject, Name, Hint);
+ }
+ else
+ {
+ return 0;
+ }
+}
- /* FIXME: map VDM into low memory */
- /* FIXME: Build/Load image sections */
-
- return STATUS_NOT_IMPLEMENTED;
+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;
+
+// KeAcquireSpinLock(&ModuleListLock,&oldlvl);
+
+ /* calculate required size */
+ current_entry = ModuleListHead.Flink;
+ while (current_entry != (&ModuleListHead))
+ {
+ ModuleCount++;
+ current_entry = current_entry->Flink;
+ }
+
+ *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
+ (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY);
+
+ if (Size < *ReqSize)
+ {
+// KeReleaseSpinLock(&ModuleListLock,oldlvl);
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* fill the buffer */
+ memset(Buffer, '=', Size);
+
+ Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
+ Smi->Count = ModuleCount;
+
+ ModuleCount = 0;
+ current_entry = ModuleListHead.Flink;
+ while (current_entry != (&ModuleListHead))
+ {
+ 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;
+ }
+
+// KeReleaseSpinLock(&ModuleListLock,oldlvl);
+
+ return STATUS_SUCCESS;
}
-static NTSTATUS
-LdrProcessPEImage(HANDLE ProcessHandle,
- HANDLE FileHandle,
- PIMAGE_DOS_HEADER DosHeader)
+
+static VOID
+LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
+ PUNICODE_STRING FullName)
{
-// PIMAGE_NT_HEADERS PEHeader;
-// PIMAGE_SECTION_HEADER Sections;
-
- // FIXME: Check architechture
- // FIXME: Build/Load image sections
- // FIXME: do relocations code sections
- // FIXME: resolve imports
- // FIXME: do fixups
-
- return STATUS_NOT_IMPLEMENTED;
+ UNICODE_STRING Name;
+ PWCHAR p;
+ PWCHAR q;
+
+ DPRINT("LdrpBuildModuleBaseName()\n");
+ DPRINT("FullName %wZ\n", FullName);
+
+ p = wcsrchr(FullName->Buffer, '\\');
+ if (p == NULL)
+ {
+ p = FullName->Buffer;
+ }
+ else
+ {
+ p++;
+ }
+
+ DPRINT("p %S\n", p);
+
+ RtlCreateUnicodeString(&Name, p);
+
+ q = wcschr(p, '.');
+ if (q != NULL)
+ {
+ *q = (WCHAR)0;
+ }
+
+ DPRINT("p %S\n", p);
+
+ RtlCreateUnicodeString(BaseName, p);
+ RtlFreeUnicodeString(&Name);
}
-/*
- * FUNCTION: Loads a PE executable into the specified process
- * ARGUMENTS:
- * Filename = File to load
- * ProcessHandle = handle
- * RETURNS: Status
- */
-NTSTATUS
-LdrLoadImage(PUNICODE_STRING Filename, HANDLE ProcessHandle)
+/* ---------------------------------------------- PE Module support */
+
+PMODULE_OBJECT
+LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING FileName)
{
- char BlockBuffer[512];
- NTSTATUS Status;
- ULONG SectionSize;
- HANDLE FileHandle;
- HANDLE ThreadHandle;
- OBJECT_ATTRIBUTES FileObjectAttributes;
+ unsigned int DriverSize, Idx, Idx2;
+ ULONG RelocDelta, NumRelocs;
+ DWORD CurrentSize, TotalRelocs;
+ PVOID DriverBase;
+ PULONG PEMagic;
PIMAGE_DOS_HEADER PEDosHeader;
- CONTEXT Context;
- HANDLE SectionHandle;
- PVOID BaseAddress;
+ PIMAGE_FILE_HEADER PEFileHeader;
+ PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
+ PIMAGE_SECTION_HEADER PESectionHeaders;
+ PRELOCATION_DIRECTORY RelocDir;
+ PRELOCATION_ENTRY RelocEntry;
+ PMODULE_OBJECT LibraryModuleObject;
+ HANDLE ModuleHandle;
+ PMODULE_OBJECT ModuleObject;
+ PVOID *ImportAddressList;
+ PULONG FunctionNameList;
+ PCHAR pName, SymbolNameBuf;
+ WORD Hint;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING ModuleName;
+ WCHAR NameBuffer[60];
+ MODULE_TEXT_SECTION* ModuleTextSection;
+
+ DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
- /* FIXME: should DLLs be named sections? */
+ /* 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;
- /* Open the image file */
- InitializeObjectAttributes(&FileObjectAttributes,
- Filename,
- 0,
- NULL,
- NULL);
- Status = ZwOpenFile(&FileHandle, 0, &FileObjectAttributes, NULL, 0, 0);
- if (!NT_SUCCESS(Status))
+ /* Check file magic numbers */
+ if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
{
- return Status;
+ DbgPrint("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
+ return 0;
}
-
- /* Read first block of image to determine type */
- Status = ZwReadFile(FileHandle, 0, 0, 0, 0, BlockBuffer, 512, 0, 0);
- if (!NT_SUCCESS(Status))
+ if (PEDosHeader->e_lfanew == 0)
+ {
+ DbgPrint("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
+ return 0;
+ }
+ if (*PEMagic != IMAGE_PE_MAGIC)
+ {
+ DbgPrint("Incorrect PE magic: %08x\n", *PEMagic);
+ return 0;
+ }
+ if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
{
- ZwClose(FileHandle);
- return Status;
- }
+ DbgPrint("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
+ return 0;
+ }
+ CHECKPOINT;
- /* If MZ header exists */
- PEDosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
- if (PEDosHeader->e_magic == 0x54AD && PEDosHeader->e_lfanew != 0L)
+ /* FIXME: if image is fixed-address load, then fail */
+
+ /* FIXME: check/verify OS version number */
+
+ 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 = PEOptionalHeader->SizeOfImage;
+ DPRINT("DriverSize %x\n",DriverSize);
+
+ /* Allocate a virtual section for the module */
+ DriverBase = MmAllocateSection(DriverSize);
+ if (DriverBase == 0)
+ {
+ DbgPrint("Failed to allocate a virtual section for driver\n");
+ return 0;
+ }
+ DbgPrint("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++)
{
- Status = LdrProcessPEImage(ProcessHandle,
- FileHandle,
- PEDosHeader);
- if (!NT_SUCCESS(Status))
+ // Copy current section into current offset of virtual section
+ if (PESectionHeaders[Idx].Characteristics &
+ (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
{
- return Status;
+ 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 );
}
+ else
+ {
+ DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
+ PESectionHeaders[Idx].VirtualAddress + DriverBase);
+ memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
+ '\0', PESectionHeaders[Idx].Misc.VirtualSize);
+
+ }
+ CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
+ PEOptionalHeader->SectionAlignment);
+
+
+// CurrentBase = (PVOID)((DWORD)CurrentBase +
+ // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
+ // PEOptionalHeader->SectionAlignment));
}
- else if (PEDosHeader->e_magic == 0x54AD)
+
+ /* 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++)
{
- Status = LdrProcessMZImage(ProcessHandle,
- FileHandle,
- PEDosHeader);
- 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;
+ }
+ }
+#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)
+ {
+ 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++)
{
- return Status;
+ 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)
+ {
+ (*RelocItem) += RelocDelta;
+ }
+ else if (Type != 0)
+ {
+ DbgPrint("Unknown relocation type %x at %x\n",Type, &Type);
+ return 0;
+ }
}
+ TotalRelocs += RelocDir->SizeOfBlock;
+ RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
+ RelocDir->SizeOfBlock);
+// DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
}
- else /* Assume bin format and load */
+
+ 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)
{
- FILE_STANDARD_INFORMATION FileStdInfo;
+ PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
- /* Get the size of the file for the section */
- Status = ZwQueryInformationFile(FileHandle,
- NULL,
- &FileStdInfo,
- sizeof(FileStdInfo),
- FileStandardInformation);
- if (!NT_SUCCESS(Status))
- {
- ZwClose(FileHandle);
- return Status;
- }
+ SymbolNameBuf = ExAllocatePoolWithTag(NonPagedPool, 512, TAG_SYM_BUF);
- /* Create the section for the code */
- Status = ZwCreateSection(&SectionHandle,
- SECTION_ALL_ACCESS,
- NULL,
- NULL,
- PAGE_READWRITE,
- MEM_COMMIT,
- FileHandle);
- ZwClose(FileHandle);
- if (!NT_SUCCESS(Status))
+ /* 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)
{
- return Status;
- }
+ /* Check to make sure that import lib is kernel */
+ pName = (PCHAR) DriverBase +
+ ImportModuleDirectory->dwRVAModuleName;
+ wcscpy(NameBuffer, MODULE_ROOT_NAME);
+ for (Idx = 0; NameBuffer[Idx] != 0; Idx++)
+ ;
+ for (Idx2 = 0; pName[Idx2] != '\0'; Idx2++)
+ {
+ NameBuffer[Idx + Idx2] = (WCHAR) pName[Idx2];
+ }
+ NameBuffer[Idx + Idx2] = 0;
+ RtlInitUnicodeString (&ModuleName, NameBuffer);
+ DPRINT("Import module: %wZ\n", &ModuleName);
- /* Map a view of the section into the desired process */
- BaseAddress = (PVOID)0x10000;
- SectionSize = GET_LARGE_INTEGER_LOW_PART(FileStdInfo.AllocationSize);
- Status = ZwMapViewOfSection(SectionHandle,
- ProcessHandle,
- &BaseAddress,
- 0,
- SectionSize,
- NULL,
- &SectionSize,
- 0,
- MEM_COMMIT,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- /* FIXME: destroy the section here */
+ LibraryModuleObject = LdrLoadModule(&ModuleName);
+ if (LibraryModuleObject == 0)
+ {
+ DbgPrint("Unknown import module: %wZ\n", &ModuleName);
+ }
+ /* Get the import address list */
+ ImportAddressList = (PVOID *) ((DWORD)DriverBase +
+ ImportModuleDirectory->dwRVAFunctionAddressList);
- return Status;
+ /* 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;
+
+
+ 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);
+
+ /* Fixup the current import symbol */
+ if (LibraryModuleObject != NULL)
+ {
+ *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
+ pName,
+ Hint);
+ }
+ else
+ {
+ DbgPrint("Unresolved kernel symbol: %s\n", pName);
+ return(NULL);
+ }
+ ImportAddressList++;
+ FunctionNameList++;
+ }
+ ImportModuleDirectory++;
}
-
- /* Setup the context for the initial thread */
- memset(&Context,0,sizeof(CONTEXT));
- Context.SegSs = USER_DS;
- Context.Esp = 0x2000;
- Context.EFlags = 0x202;
- Context.SegCs = USER_CS;
- Context.Eip = 0x10000;
- Context.SegDs = USER_DS;
- Context.SegEs = USER_DS;
- Context.SegFs = USER_DS;
- Context.SegGs = USER_DS;
-
- /* Create the stack for the process */
- BaseAddress = (PVOID) 0x1000;
- SectionSize = 0x1000;
- Status = ZwAllocateVirtualMemory(ProcessHandle,
- &BaseAddress,
- 0,
- &SectionSize,
- MEM_COMMIT,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- /* FIXME: unmap the section here */
- /* FIXME: destroy the section here */
- return Status;
- }
-
- /* Create the initial thread */
- Status = ZwCreateThread(&ThreadHandle,
- THREAD_ALL_ACCESS,
- NULL,
- ProcessHandle,
- NULL,
- &Context,
- NULL,
- FALSE);
- if (!NT_SUCCESS(Status))
- {
- /* FIXME: destroy the stack memory block here */
- /* FIXME: unmap the section here */
- /* FIXME: destroy the section here */
+ ExFreePool(SymbolNameBuf);
+ }
+
+ /* Create ModuleName string */
+ wcscpy(NameBuffer, MODULE_ROOT_NAME);
+ if (wcsrchr(FileName->Buffer, '\\') != 0)
+ {
+ wcscat(NameBuffer, wcsrchr(FileName->Buffer, '\\') + 1);
+ }
+ else
+ {
+ wcscat(NameBuffer, FileName->Buffer);
+ }
+ RtlInitUnicodeString (&ModuleName, NameBuffer);
+ DbgPrint("Module name is: %wZ\n", &ModuleName);
- return Status;
+ /* Initialize ObjectAttributes for ModuleObject */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ModuleName,
+ 0,
+ NULL,
+ NULL);
+
+ /* Create module object */
+ ModuleHandle = 0;
+ ModuleObject = ObCreateObject(&ModuleHandle,
+ STANDARD_RIGHTS_REQUIRED,
+ &ObjectAttributes,
+ IoDriverObjectType);
+
+ /* Initialize ModuleObject data */
+ ModuleObject->Base = DriverBase;
+ ModuleObject->Flags = MODULE_FLAG_PE;
+ InsertTailList(&ModuleListHead,
+ &ModuleObject->ListEntry);
+ RtlCreateUnicodeString(&ModuleObject->FullName,
+ FileName->Buffer);
+ LdrpBuildModuleBaseName(&ModuleObject->BaseName,
+ &ModuleObject->FullName);
+
+ ModuleObject->EntryPoint = (PVOID) ((DWORD)DriverBase +
+ PEOptionalHeader->AddressOfEntryPoint);
+ ModuleObject->Length = DriverSize;
+ DPRINT("entrypoint at %x\n", ModuleObject->EntryPoint);
+
+ ModuleObject->Image.PE.FileHeader =
+ (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
+
+ DPRINT("FileHeader at %x\n", ModuleObject->Image.PE.FileHeader);
+ ModuleObject->Image.PE.OptionalHeader =
+ (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
+ sizeof(IMAGE_FILE_HEADER));
+ DPRINT("OptionalHeader at %x\n", ModuleObject->Image.PE.OptionalHeader);
+ ModuleObject->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", ModuleObject->Image.PE.SectionList);
+
+ 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);
+
+#ifdef KDBG
+
+ /* Load symbols for module if available */
+ LdrLoadModuleSymbols(ModuleObject, ModuleTextSection);
+
+#endif /* KDBG */
+
+ return ModuleObject;
+}
+
+static PVOID
+LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
+ char *Name,
+ unsigned short Hint)
+{
+ WORD Idx;
+ PVOID ExportAddress;
+ PWORD OrdinalList;
+ PDWORD FunctionList, NameList;
+ PIMAGE_EXPORT_DIRECTORY ExportDir;
+ ULONG ExportDirSize;
+
+ 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)
+ {
+ for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
+ {
+#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])))
+ {
+ 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;
+ }
}
}
- /* FIXME: {else} could check for a.out, ELF, COFF, etc. images here... */
+ else /* use hint */
+ {
+ ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
+ FunctionList[Hint - ExportDir->Base]);
+ }
- return Status;
+ if (ExportAddress == 0)
+ {
+ DbgPrint("Export not found for %d:%s\n",
+ Hint,
+ Name != NULL ? Name : "(Ordinal)");
+ KeBugCheck(0);
+ }
+
+ return ExportAddress;
+}
+
+
+static PMODULE_OBJECT
+LdrPEGetModuleObject(PUNICODE_STRING ModuleName)
+{
+ PLIST_ENTRY Entry;
+ PMODULE_OBJECT Module;
+
+ DPRINT("LdrPEGetModuleObject (ModuleName %wZ)\n",
+ ModuleName);
+
+ Entry = ModuleListHead.Flink;
+
+ while (Entry != &ModuleListHead)
+ {
+ Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
+
+ DPRINT("Comparing %wZ and %wZ\n",
+ &Module->BaseName,
+ ModuleName);
+
+ if (!RtlCompareUnicodeString(&Module->BaseName, ModuleName, TRUE))
+ {
+ DPRINT("Module %x\n", Module);
+ return Module;
+ }
+
+ Entry = Entry->Flink;
+ }
+
+ DbgPrint("LdrPEGetModuleObject: Failed to find dll %wZ\n", ModuleName);
+
+ return NULL;
}
+
+static PVOID
+LdrPEFixupForward(PCHAR ForwardName)
+{
+ 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);
+
+ RtlCreateUnicodeStringFromAsciiz(&ModuleName,
+ NameBuffer);
+ ModuleObject = LdrPEGetModuleObject(&ModuleName);
+ RtlFreeUnicodeString(&ModuleName);
+
+ DPRINT("ModuleObject: %p\n", ModuleObject);
+
+ if (ModuleObject == NULL)
+ {
+ DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
+ return NULL;
+ }
+
+ return LdrPEGetExportAddress(ModuleObject, p+1, 0);
+}
+
+
+/* EOF */