-/* $Id: loader.c,v 1.32 1999/10/07 23:36:24 ekohl Exp $
+/* $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
* 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
+ * 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 <internal/i386/segment.h>
-#include <internal/linkage.h>
+#include <internal/config.h>
#include <internal/module.h>
#include <internal/ntoskrnl.h>
-#include <internal/mmhal.h>
+#include <internal/mm.h>
#include <internal/ob.h>
#include <internal/ps.h>
-#include <string.h>
-#include <internal/string.h>
-#include <internal/symbol.h>
+#include <internal/ldr.h>
+#include <internal/pool.h>
#define NDEBUG
#include <internal/debug.h>
-#include "syspath.h"
-
/* FIXME: this should appear in a kernel header file */
NTSTATUS IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry);
/* GLOBALS *******************************************************************/
-POBJECT_TYPE ObModuleType = NULL;
+LIST_ENTRY ModuleListHead;
+POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;
+LIST_ENTRY ModuleTextListHead;
+STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
+/* STATIC MODULE_TEXT_SECTION HalTextSection; */
-/* FORWARD DECLARATIONS ******************************************************/
+#define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
+#define TAG_SYM_BUF TAG('S', 'Y', 'M', 'B')
-NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename);
-NTSTATUS LdrProcessDriver(PVOID ModuleLoadBase);
+/* FORWARD DECLARATIONS ******************************************************/
PMODULE_OBJECT LdrLoadModule(PUNICODE_STRING Filename);
-PMODULE_OBJECT LdrProcessModule(PVOID ModuleLoadBase);
+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 PIMAGE_SECTION_HEADER LdrPEGetEnclosingSectionHeader(DWORD RVA,
- PMODULE_OBJECT ModuleObject);
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);
-static PVOID LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
- char *Name,
+static PMODULE_OBJECT LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING FileName);
+static PVOID LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
+ char *Name,
unsigned short Hint);
-static unsigned int LdrGetKernelSymbolAddr(char *Name);
+static PMODULE_OBJECT LdrPEGetModuleObject(PUNICODE_STRING ModuleName);
+static PVOID LdrPEFixupForward(PCHAR ForwardName);
/* FUNCTIONS *****************************************************************/
+VOID
+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)
+{
+ 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];
- ANSI_STRING AnsiString;
UNICODE_STRING ModuleName;
OBJECT_ATTRIBUTES ObjectAttributes;
PIMAGE_DOS_HEADER DosHeader;
PMODULE_OBJECT ModuleObject;
- /* Register the process object type */
- ObModuleType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
- ObModuleType->TotalObjects = 0;
- ObModuleType->TotalHandles = 0;
- ObModuleType->MaxObjects = ULONG_MAX;
- ObModuleType->MaxHandles = ULONG_MAX;
- ObModuleType->PagedPoolCharge = 0;
- ObModuleType->NonpagedPoolCharge = sizeof(MODULE);
- ObModuleType->Dump = NULL;
- ObModuleType->Open = NULL;
- ObModuleType->Close = NULL;
- ObModuleType->Delete = NULL;
- ObModuleType->Parse = NULL;
- ObModuleType->Security = NULL;
- ObModuleType->QueryName = NULL;
- ObModuleType->OkayToClose = NULL;
- ObModuleType->Create = LdrCreateModule;
- RtlInitAnsiString(&AnsiString, "Module");
- RtlAnsiStringToUnicodeString(&ObModuleType->TypeName, &AnsiString, TRUE);
+ /* 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;
- ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
- ModuleName.Buffer = NameBuffer;
- InitializeObjectAttributes(&ObjectAttributes,
- &ModuleName,
- 0,
- NULL,
+ RtlInitUnicodeString (&ModuleName, NameBuffer);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ModuleName,
+ 0,
+ NULL,
NULL);
- DPRINT("Create dir: %W\n", &ModuleName);
- Status = ZwCreateDirectoryObject(&DirHandle, 0, &ObjectAttributes);
+ 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");
- ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
- ModuleName.Buffer = NameBuffer;
- DPRINT("Kernel's Module name is: %W\n", &ModuleName);
-
+ RtlInitUnicodeString (&ModuleName, NameBuffer);
+ DPRINT("Kernel's Module name is: %wZ\n", &ModuleName);
+
/* Initialize ObjectAttributes for ModuleObject */
- InitializeObjectAttributes(&ObjectAttributes,
- &ModuleName,
- 0,
- NULL,
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ModuleName,
+ 0,
+ NULL,
NULL);
/* Create module object */
ModuleObject = ObCreateObject(&ModuleHandle,
STANDARD_RIGHTS_REQUIRED,
&ObjectAttributes,
- ObModuleType);
+ IoDriverObjectType);
assert(ModuleObject != NULL);
- /* Initialize ModuleObject data */
- ModuleObject->Base = (PVOID) KERNEL_BASE;
- ModuleObject->Flags = MODULE_FLAG_PE;
+ 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 +
+ ModuleObject->Image.PE.FileHeader =
+ (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
DosHeader->e_lfanew + sizeof(ULONG));
- ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
+ ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
- ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
+ ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
- ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
+ 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
- )
+static VOID LdrLoadAutoConfigDriver (LPWSTR RelativeDriverName)
{
- WCHAR TmpFileName [MAX_PATH];
- NTSTATUS Status;
- UNICODE_STRING DriverName;
-
- GetSystemDirectory(
- TmpFileName,
- (MAX_PATH * sizeof(WCHAR))
- );
- wcscat(
- TmpFileName,
- L"\\drivers\\"
- );
- wcscat(
- TmpFileName,
- RelativeDriverName
- );
-
- DriverName.Buffer =
- TmpFileName;
- DriverName.Length =
- wcslen(TmpFileName)
- * sizeof (WCHAR);
- DriverName.MaximumLength =
- DriverName.Length
- + sizeof(WCHAR);
-
- Status = LdrLoadDriver(&DriverName);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint(
- "driver load failed, status;%d(%x)\n",
- Status,
- Status
- );
- DbgPrintErrorMessage(Status);
- }
+ 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
-VOID
-LdrLoadAutoConfigDrivers (VOID)
+BOOLEAN LdrReadLine(PCHAR Line,
+ PVOID *Buffer,
+ PULONG Size)
{
- /*
- * Keyboard driver
- */
- LdrLoadAutoConfigDriver( L"keyboard.sys" );
- /*
- * Raw console driver
- */
- LdrLoadAutoConfigDriver( L"blue.sys" );
+ CHAR ch;
+ PCHAR Block;
+
+ if (*Size == 0)
+ return FALSE;
+
+ Block = *Buffer;
+ while ((*Size > 0) && ((ch = *Block) != (CHAR)13))
+ {
+ *Line = ch;
+ Line++;
+ Block++;
+ *Size -= 1;
+ }
+ *Line = (CHAR)0;
+
+ Block++;
+ *Size -= 1;
+
+ if ((*Size > 0) && (*Block == (CHAR)10))
+ {
+ Block++;
+ *Size -= 1;
+ }
+
+ *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]) != ' '))
+ {
+ 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;
+}
+
+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;
+
+ 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)
+ {
+ *ImageBase = Address;
+ *ImageBaseValid = TRUE;
+ return NULL;
+ }
+
+ /* 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))
+ {
+ DPRINT("Could not open symbol file: %wZ\n", &Filename);
+ return;
+ }
+
+ 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))
+ {
+ DPRINT("Could not get file size\n");
+ return;
+ }
+
+ /* Allocate nonpageable memory for symbol file */
+ FileBuffer = ExAllocatePool(NonPagedPool,
+ FileStdInfo.EndOfFile.u.LowPart);
+
+ if (FileBuffer == NULL)
+ {
+ DPRINT("Could not allocate memory for symbol file\n");
+ return;
+ }
+
+ /* 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;
+ }
+
+ ZwClose(FileHandle);
+
+ ModuleTextSection->Symbols.SymbolCount = 0;
+ ModuleTextSection->Symbols.Symbols = NULL;
+
+ FilePtr = FileBuffer;
+ Length = FileStdInfo.EndOfFile.u.LowPart;
+
+ while (LdrReadLine((PCHAR)&Line, &FilePtr, &Length))
+ {
+ Symbol = LdrParseLine((PCHAR)&Line, &Tmp, &ImageBaseValid);
+
+ if (ImageBaseValid)
+ ImageBase = Tmp;
+
+ if (Symbol != NULL)
+ {
+ Symbol->RelativeAddress -= ImageBase;
+
+ if (ModuleTextSection->Symbols.Symbols == NULL)
+ ModuleTextSection->Symbols.Symbols = Symbol;
+ else
+ CurrentSymbol->Next = Symbol;
+
+ CurrentSymbol = Symbol;
+
+ ModuleTextSection->Symbols.SymbolCount++;
+ }
+ }
+
+ ExFreePool(FileBuffer);
+}
+
+#endif /* KDBG */
+
+VOID LdrLoadAutoConfigDrivers (VOID)
+{
+
+#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" );
+
+ /*
+ * Raw console driver
+ */
+ LdrLoadAutoConfigDriver( L"blue.sys" );
+
+ /*
+ *
+ */
+ 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
}
PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes)
{
- DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %w)\n",
- ObjectBody,
- Parent,
+ DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+ ObjectBody,
+ Parent,
RemainingPath);
if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
{
* RETURNS: Status
*/
-NTSTATUS
-LdrLoadDriver(PUNICODE_STRING Filename)
+NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename)
{
PMODULE_OBJECT ModuleObject;
/* FIXME: should we dereference the ModuleObject here? */
- return IoInitializeDriver(ModuleObject->EntryPoint);
+ return IoInitializeDriver(ModuleObject->EntryPoint);
}
-
-PMODULE_OBJECT
+
+NTSTATUS LdrLoadGdiDriver (PUNICODE_STRING DriverName,
+ PVOID *ImageAddress,
+ PVOID *SectionPointer,
+ PVOID *EntryPoint,
+ PVOID *ExportSectionPointer)
+{
+ PMODULE_OBJECT ModuleObject;
+
+ ModuleObject = LdrLoadModule(DriverName);
+ if (ModuleObject == 0)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (ImageAddress)
+ *ImageAddress = ModuleObject->Base;
+
+// if (SectionPointer)
+// *SectionPointer = ModuleObject->
+
+ if (EntryPoint)
+ *EntryPoint = ModuleObject->EntryPoint;
+
+// if (ExportSectionPointer)
+// *ExportSectionPointer = ModuleObject->
+
+ return STATUS_SUCCESS;
+}
+
+
+PMODULE_OBJECT
LdrLoadModule(PUNICODE_STRING Filename)
{
PVOID ModuleLoadBase;
OBJECT_ATTRIBUTES ObjectAttributes;
PMODULE_OBJECT ModuleObject;
FILE_STANDARD_INFORMATION FileStdInfo;
- WCHAR NameBuffer[60];
- PWSTR RemainingPath;
- UNICODE_STRING ModuleName;
/* Check for module already loaded */
if ((ModuleObject = LdrOpenModule(Filename)) != NULL)
return ModuleObject;
}
- DPRINT("Loading Module %W...\n", Filename);
+ DPRINT("Loading Module %wZ...\n", Filename);
/* Open the Module */
InitializeObjectAttributes(&ObjectAttributes,
- Filename,
+ Filename,
0,
NULL,
NULL);
CHECKPOINT;
- Status = ZwOpenFile(&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
+ Status = NtOpenFile(&FileHandle,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
NULL, 0, 0);
CHECKPOINT;
if (!NT_SUCCESS(Status))
{
- DbgPrint("Could not open module file: %W\n", Filename);
+ DbgPrint("Could not open module file: %wZ\n", Filename);
return 0;
}
CHECKPOINT;
/* Get the size of the file */
- Status = ZwQueryInformationFile(FileHandle,
+ Status = NtQueryInformationFile(FileHandle,
NULL,
&FileStdInfo,
sizeof(FileStdInfo),
CHECKPOINT;
/* Allocate nonpageable memory for driver */
- ModuleLoadBase = ExAllocatePool(NonPagedPool,
- FileStdInfo.EndOfFile.u.LowPart);
+ ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
+ FileStdInfo.EndOfFile.u.LowPart,
+ TAG_DRIVER_MEM);
+
if (ModuleLoadBase == NULL)
{
DbgPrint("could not allocate memory for module");
return 0;
}
CHECKPOINT;
-
+
/* Load driver into memory chunk */
- Status = ZwReadFile(FileHandle,
+ Status = NtReadFile(FileHandle,
0, 0, 0, 0,
ModuleLoadBase,
FileStdInfo.EndOfFile.u.LowPart,
}
CHECKPOINT;
- ZwClose(FileHandle);
+ NtClose(FileHandle);
- ModuleObject = LdrProcessModule(ModuleLoadBase);
+ ModuleObject = LdrProcessModule(ModuleLoadBase, Filename);
/* Cleanup */
ExFreePool(ModuleLoadBase);
}
NTSTATUS
-LdrProcessDriver(PVOID ModuleLoadBase)
+LdrProcessDriver(PVOID ModuleLoadBase, PCHAR FileName)
{
- PMODULE_OBJECT ModuleObject;
-
- ModuleObject = LdrProcessModule(ModuleLoadBase);
- if (ModuleObject == 0)
- {
- return STATUS_UNSUCCESSFUL;
- }
-
- /* FIXME: should we dereference the ModuleObject here? */
-
- return IoInitializeDriver(ModuleObject->EntryPoint);
+ 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));
}
PMODULE_OBJECT
-LdrProcessModule(PVOID ModuleLoadBase)
+LdrProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING ModuleName)
{
PIMAGE_DOS_HEADER PEDosHeader;
PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
{
- return LdrPEProcessModule(ModuleLoadBase);
+ return LdrPEProcessModule(ModuleLoadBase, ModuleName);
}
-#if 0
- if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC)
- {
- return 0;
- }
- else /* Assume COFF format and load */
- {
- return LdrCOFFProcessModule(ModuleLoadBase);
- }
-#endif
+ DPRINT1("Module wasn't PE\n");
return 0;
}
UNICODE_STRING ModuleName;
OBJECT_ATTRIBUTES ObjectAttributes;
PMODULE_OBJECT ModuleObject;
- PWSTR RemainingPath;
+ UNICODE_STRING RemainingPath;
wcscpy(NameBuffer, MODULE_ROOT_NAME);
if (wcsrchr(Filename->Buffer, '\\') != 0)
{
wcscat(NameBuffer, Filename->Buffer);
}
- ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
- ModuleName.Buffer = NameBuffer;
+ RtlInitUnicodeString (&ModuleName, NameBuffer);
InitializeObjectAttributes(&ObjectAttributes,
&ModuleName,
0,
NULL,
NULL);
+
Status = ObFindObject(&ObjectAttributes,
(PVOID *) &ModuleObject,
- &RemainingPath);
+ &RemainingPath,
+ NULL);
CHECKPOINT;
- if (NT_SUCCESS(Status) && (RemainingPath == NULL || *RemainingPath == 0))
+ if (NT_SUCCESS(Status) && (RemainingPath.Buffer == NULL || *(RemainingPath.Buffer) == 0))
{
- DPRINT("Module %W at %p\n", Filename, ModuleObject);
+ DPRINT("Module %wZ at %p\n", Filename, ModuleObject);
+ RtlFreeUnicodeString (&RemainingPath);
return ModuleObject;
}
+ RtlFreeUnicodeString (&RemainingPath);
+
return NULL;
}
-PVOID
-LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
- char *Name,
+PVOID
+LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
+ char *Name,
unsigned short Hint)
{
if (ModuleObject->Flags & MODULE_FLAG_PE)
}
}
+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 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, '\\');
+ 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);
+}
+
+
/* ---------------------------------------------- PE Module support */
PMODULE_OBJECT
-LdrPEProcessModule(PVOID ModuleLoadBase)
+LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING FileName)
{
unsigned int DriverSize, Idx, Idx2;
ULONG RelocDelta, NumRelocs;
DWORD CurrentSize, TotalRelocs;
- PVOID DriverBase, CurrentBase;
+ PVOID DriverBase;
PULONG PEMagic;
PIMAGE_DOS_HEADER PEDosHeader;
PIMAGE_FILE_HEADER PEFileHeader;
PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
PIMAGE_SECTION_HEADER PESectionHeaders;
- PIMAGE_EXPORT_DIRECTORY ExportDirectory;
PRELOCATION_DIRECTORY RelocDir;
PRELOCATION_ENTRY RelocEntry;
PMODULE_OBJECT LibraryModuleObject;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ModuleName;
WCHAR NameBuffer[60];
-
+ MODULE_TEXT_SECTION* ModuleTextSection;
+
DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
/* Get header pointers */
CHECKPOINT;
/* Determine the size of the module */
-
- DriverSize = PEOptionalHeader->SizeOfImage;
- DPRINT("DriverSize %x\n",DriverSize);
-
- /* Allocate a virtual section for 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;
- DPRINT("Module is at base %x\n",DriverBase);
-
- /* Copy image sections into virtual section */
- memcpy(DriverBase, ModuleLoadBase, PESectionHeaders[0].PointerToRawData);
- CurrentBase = (PVOID) ((DWORD)DriverBase + PESectionHeaders[0].PointerToRawData);
+ /* Copy headers over */
+ memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
CurrentSize = 0;
+ /* Copy image sections into virtual section */
for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
{
- /* Copy current section into current offset of virtual section */
+ // Copy current section into current offset of virtual section
if (PESectionHeaders[Idx].Characteristics &
(IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
{
DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
PESectionHeaders[Idx].VirtualAddress + DriverBase);
- memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
- (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
- PESectionHeaders[Idx].SizeOfRawData);
+ 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].SizeOfRawData);
+ '\0', PESectionHeaders[Idx].Misc.VirtualSize);
+
}
- CurrentSize += ROUND_UP(PESectionHeaders[Idx].SizeOfRawData,
+ CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
PEOptionalHeader->SectionAlignment);
- CurrentBase = (PVOID)((DWORD)CurrentBase +
- ROUND_UP(PESectionHeaders[Idx].SizeOfRawData,
- PEOptionalHeader->SectionAlignment));
+
+
+// CurrentBase = (PVOID)((DWORD)CurrentBase +
+ // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
+ // PEOptionalHeader->SectionAlignment));
}
/* Perform relocation fixups */
DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
DriverBase,
PEOptionalHeader->ImageBase,
- RelocDelta);
+ RelocDelta);
DPRINT("RelocDir %x\n",RelocDir);
+#if 1
for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
{
if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
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)
}
else if (Type != 0)
{
- DbgPrint("Unknown relocation type %x\n",Type);
+ DbgPrint("Unknown relocation type %x at %x\n",Type, &Type);
return 0;
}
}
PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
.VirtualAddress);
/* Perform import fixups */
- if (PEOptionalHeader->DataDirectory[
- IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
+ if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
{
PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
- SymbolNameBuf = ExAllocatePool(NonPagedPool, 512);
+ SymbolNameBuf = ExAllocatePoolWithTag(NonPagedPool, 512, TAG_SYM_BUF);
/* Process each import module */
ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
NameBuffer[Idx + Idx2] = (WCHAR) pName[Idx2];
}
NameBuffer[Idx + Idx2] = 0;
- ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
- ModuleName.Buffer = NameBuffer;
- DPRINT("Import module: %W\n", &ModuleName);
+ RtlInitUnicodeString (&ModuleName, NameBuffer);
+ DPRINT("Import module: %wZ\n", &ModuleName);
+
LibraryModuleObject = LdrLoadModule(&ModuleName);
if (LibraryModuleObject == 0)
{
- DbgPrint("Unknown import module: %W\n", &ModuleName);
+ DbgPrint("Unknown import module: %wZ\n", &ModuleName);
}
/* Get the import address list */
ImportAddressList = (PVOID *) ((DWORD)DriverBase +
if ((*FunctionNameList) & 0x80000000) // hint
{
pName = NULL;
+
+
Hint = (*FunctionNameList) & 0xffff;
}
else // hint-name
}
else
{
- DbgPrint("Unresolved kernel symbol: %s\n", pName);
+ DbgPrint("Unresolved kernel symbol: %s\n", pName);
+ return(NULL);
}
ImportAddressList++;
FunctionNameList++;
/* Create ModuleName string */
wcscpy(NameBuffer, MODULE_ROOT_NAME);
- if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
- .VirtualAddress != 0)
+ if (wcsrchr(FileName->Buffer, '\\') != 0)
{
- ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) (DriverBase +
- PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
- .VirtualAddress);
- wcscat(NameBuffer, DriverBase + ExportDirectory->Name);
+ wcscat(NameBuffer, wcsrchr(FileName->Buffer, '\\') + 1);
}
else
{
- char buf[12];
-
- sprintf(buf, "%08X", (DWORD) DriverBase);
- for (Idx = 0; NameBuffer[Idx] != 0; Idx++)
- ;
- Idx2 = 0;
- while ((NameBuffer[Idx + Idx2] = (WCHAR) buf[Idx2]) != 0)
- Idx2++;
+ wcscat(NameBuffer, FileName->Buffer);
}
- ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
- ModuleName.Buffer = NameBuffer;
- DPRINT("Module name is: %W\n", &ModuleName);
-
+ RtlInitUnicodeString (&ModuleName, NameBuffer);
+ DbgPrint("Module name is: %wZ\n", &ModuleName);
+
/* Initialize ObjectAttributes for ModuleObject */
- InitializeObjectAttributes(&ObjectAttributes,
- &ModuleName,
- 0,
- NULL,
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ModuleName,
+ 0,
+ NULL,
NULL);
/* Create module object */
ModuleObject = ObCreateObject(&ModuleHandle,
STANDARD_RIGHTS_REQUIRED,
&ObjectAttributes,
- ObModuleType);
+ 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);
- /* Initialize ModuleObject data */
- ModuleObject->Base = DriverBase;
- ModuleObject->Flags = MODULE_FLAG_PE;
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));
+
+ 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));
+ (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));
+ (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,
+static PVOID
+LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
+ char *Name,
unsigned short Hint)
{
WORD Idx;
- DWORD ExportsStartRVA, ExportsEndRVA, Delta;
PVOID ExportAddress;
PWORD OrdinalList;
PDWORD FunctionList, NameList;
- PIMAGE_SECTION_HEADER SectionHeader;
- PIMAGE_EXPORT_DIRECTORY ExportDirectory;
-
- ExportsStartRVA = ModuleObject->Image.PE.OptionalHeader->DataDirectory
- [IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- ExportsEndRVA = ExportsStartRVA +
- ModuleObject->Image.PE.OptionalHeader->DataDirectory
- [IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
- /* Get the IMAGE_SECTION_HEADER that contains the exports. This is
- usually the .edata section, but doesn't have to be. */
- SectionHeader = LdrPEGetEnclosingSectionHeader(ExportsStartRVA, ModuleObject);
- if (!SectionHeader)
- {
- return 0;
- }
- Delta = (DWORD)(SectionHeader->VirtualAddress -
- SectionHeader->PointerToRawData);
- ExportDirectory = MakePtr(PIMAGE_EXPORT_DIRECTORY,
- ModuleObject->Base,
- ExportsStartRVA - Delta);
-
- FunctionList = (PDWORD)((DWORD)ExportDirectory->AddressOfFunctions -
- Delta + ModuleObject->Base);
- NameList = (PDWORD)((DWORD)ExportDirectory->AddressOfNames -
- Delta + ModuleObject->Base);
- OrdinalList = (PWORD)((DWORD)ExportDirectory->AddressOfNameOrdinals -
- Delta + ModuleObject->Base);
- DPRINT("Delta:%08x\n", Delta);
- DPRINT("Func:%08x RVA:%08x Name:%08x RVA:%08x\nOrd:%08x RVA:%08x ",
- FunctionList, ExportDirectory->AddressOfFunctions,
- NameList, ExportDirectory->AddressOfNames,
- OrdinalList, ExportDirectory->AddressOfNameOrdinals);
- DPRINT("NumNames:%d NumFuncs:%d\n", ExportDirectory->NumberOfNames,
- ExportDirectory->NumberOfFunctions);
+ 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 < ExportDirectory->NumberOfNames; Idx++)
+ 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;
}
}
else /* use hint */
{
ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
- FunctionList[Hint - ExportDirectory->Base]);
- }
- if (ExportAddress == 0)
- {
- DbgPrint("Export not found for %d:%s\n", Hint, Name != NULL ? Name : "(Ordinal)");
+ FunctionList[Hint - ExportDir->Base]);
}
- return ExportAddress;
+ if (ExportAddress == 0)
+ {
+ DbgPrint("Export not found for %d:%s\n",
+ Hint,
+ Name != NULL ? Name : "(Ordinal)");
+ KeBugCheck(0);
+ }
+
+ return ExportAddress;
}
-static PIMAGE_SECTION_HEADER
-LdrPEGetEnclosingSectionHeader(DWORD RVA,
- PMODULE_OBJECT ModuleObject)
+
+static PMODULE_OBJECT
+LdrPEGetModuleObject(PUNICODE_STRING ModuleName)
{
- PIMAGE_SECTION_HEADER SectionHeader = SECHDROFFSET(ModuleObject->Base);
- unsigned i;
-
- for (i = 0; i < ModuleObject->Image.PE.FileHeader->NumberOfSections;
- i++, SectionHeader++)
- {
- /* Is the RVA within this section? */
- if ((RVA >= SectionHeader->VirtualAddress) &&
- (RVA < (SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize)))
- {
- return SectionHeader;
- }
- }
-
- return 0;
+ 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 */