Author: ion
Date: Wed Feb 21 04:57:02 2007
New Revision: 25861
URL:
http://svn.reactos.org/svn/reactos?rev=25861&view=rev
Log:
- Cleanup loader.c and comment some public routines (no code change).
- Temporarily remove routines to set per-page protection (this doesn't really break
anything, just makes the OS less secure).
Modified:
trunk/reactos/ntoskrnl/ldr/loader.c
Modified: trunk/reactos/ntoskrnl/ldr/loader.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ldr/loader.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ldr/loader.c (original)
+++ trunk/reactos/ntoskrnl/ldr/loader.c Wed Feb 21 04:57:02 2007
@@ -15,30 +15,8 @@
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
-
-#ifdef HALDBG
-#include <internal/ntosdbg.h>
-#else
-#ifdef __GNUC__
-#define ps(args...)
-#else
-#define ps
-#endif /* __GNUC__ */
-#endif
-
-#if 0
-#undef ps
-#define ps(args...) DPRINT1(args)
-#endif
-
#define NDEBUG
-#include <internal/debug.h>
-
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, LdrInit1)
-#pragma alloc_text(INIT, LdrInitModuleManagement)
-#pragma alloc_text(INIT, LdrSafePEProcessModule)
-#endif
+#include <debug.h>
/* GLOBALS *******************************************************************/
@@ -47,467 +25,44 @@
LDR_DATA_TABLE_ENTRY NtoskrnlModuleObject;
LDR_DATA_TABLE_ENTRY HalModuleObject;
-/* FORWARD DECLARATIONS ******************************************************/
-
-NTSTATUS
-LdrProcessModule (
- PVOID ModuleLoadBase,
- PUNICODE_STRING ModuleName,
- PLDR_DATA_TABLE_ENTRY *ModuleObject );
+/* FUNCTIONS *****************************************************************/
+
+static PVOID
+LdrPEGetExportByName (
+ PVOID BaseAddress,
+ PUCHAR SymbolName,
+ USHORT Hint );
static VOID
LdrpBuildModuleBaseName (
- PUNICODE_STRING BaseName,
- PUNICODE_STRING FullName );
+ PUNICODE_STRING BaseName,
+ PUNICODE_STRING FullName )
+{
+ PWCHAR p;
+
+ DPRINT("LdrpBuildModuleBaseName()\n");
+ DPRINT("FullName %wZ\n", FullName);
+
+ p = wcsrchr(FullName->Buffer, L'\\');
+ if (p == NULL)
+ {
+ p = FullName->Buffer;
+ }
+ else
+ {
+ p++;
+ }
+
+ DPRINT("p %S\n", p);
+
+ RtlInitUnicodeString(BaseName, p);
+}
+
static LONG
LdrpCompareModuleNames (
- IN PUNICODE_STRING String1,
- IN PUNICODE_STRING String2 );
-
-
-/* PE Driver load support */
-static NTSTATUS
-LdrPEProcessModule (
- PVOID ModuleLoadBase,
- PUNICODE_STRING FileName,
- PLDR_DATA_TABLE_ENTRY *ModuleObject );
-
-static PVOID
-LdrPEGetExportByName (
- PVOID BaseAddress,
- PUCHAR SymbolName,
- USHORT Hint );
-
-static PVOID
-LdrPEFixupForward ( PCHAR ForwardName );
-
-static NTSTATUS
-LdrPEFixupImports ( IN PVOID DllBase, IN PWCHAR DllName);
-
-/* FUNCTIONS *****************************************************************/
-
-VOID
-NTAPI
-LdrInitDebug ( PLOADER_MODULE Module, PWCH Name )
-{
-}
-
-VOID
-INIT_FUNCTION
-NTAPI
-LdrInit1(VOID)
-{
- PLDR_DATA_TABLE_ENTRY HalModuleObject, NtoskrnlModuleObject, LdrEntry;
-
- /* Initialize the module list and spinlock */
- InitializeListHead(&ModuleListHead);
- KeInitializeSpinLock(&ModuleListLock);
-
- /* Get the NTOSKRNL Entry from the loader */
- LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink,
LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-
- /* Initialize ModuleObject for NTOSKRNL */
- NtoskrnlModuleObject = ExAllocatePoolWithTag(PagedPool,
- sizeof(LDR_DATA_TABLE_ENTRY),
- TAG('M', 'm',
'L', 'd'));
- NtoskrnlModuleObject->DllBase = LdrEntry->DllBase;
- RtlInitUnicodeString(&NtoskrnlModuleObject->FullDllName, KERNEL_MODULE_NAME);
- LdrpBuildModuleBaseName(&NtoskrnlModuleObject->BaseDllName,
&NtoskrnlModuleObject->FullDllName);
- NtoskrnlModuleObject->EntryPoint = LdrEntry->EntryPoint;
- NtoskrnlModuleObject->SizeOfImage = LdrEntry->SizeOfImage;
-
- /* Insert it into the list */
- InsertTailList(&ModuleListHead, &NtoskrnlModuleObject->InLoadOrderLinks);
-
- /* Get the HAL Entry from the loader */
- LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink->Flink,
LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-
- /* Initialize ModuleObject for HAL */
- HalModuleObject = ExAllocatePoolWithTag(PagedPool,
- sizeof(LDR_DATA_TABLE_ENTRY),
- TAG('M', 'm',
'L', 'd'));
- HalModuleObject->DllBase = LdrEntry->DllBase;
- RtlInitUnicodeString(&HalModuleObject->FullDllName, HAL_MODULE_NAME);
- LdrpBuildModuleBaseName(&HalModuleObject->BaseDllName,
&HalModuleObject->FullDllName);
- HalModuleObject->EntryPoint = LdrEntry->EntryPoint;
- HalModuleObject->SizeOfImage = LdrEntry->SizeOfImage;
-
- /* Insert it into the list */
- InsertTailList(&ModuleListHead, &HalModuleObject->InLoadOrderLinks);
-
- /* Hook for KDB on initialization of the loader. */
- KDB_LOADERINIT_HOOK(NtoskrnlModuleObject, HalModuleObject);
-}
-
-NTSTATUS
-NTAPI
-LdrpLoadImage (
- PUNICODE_STRING DriverName,
- PVOID *ModuleBase,
- PVOID *SectionPointer,
- PVOID *EntryPoint,
- PVOID *ExportSectionPointer )
-{
- PLDR_DATA_TABLE_ENTRY ModuleObject;
- NTSTATUS Status;
-
- ModuleObject = LdrGetModuleObject(DriverName);
- if (ModuleObject == NULL)
- {
- Status = LdrLoadModule(DriverName, &ModuleObject);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- }
-
- if (ModuleBase)
- *ModuleBase = ModuleObject->DllBase;
-
- if (SectionPointer)
- *SectionPointer = ModuleObject;
-
- if (EntryPoint)
- *EntryPoint = ModuleObject->EntryPoint;
-
- //if (ExportSectionPointer)
- // *ExportSectionPointer = ModuleObject->
-
- return(STATUS_SUCCESS);
-}
-
-
-NTSTATUS
-NTAPI
-LdrpUnloadImage ( PVOID ModuleBase )
-{
- return(STATUS_NOT_IMPLEMENTED);
-}
-
-
-NTSTATUS
-NTAPI
-LdrpLoadAndCallImage ( PUNICODE_STRING ModuleName )
-{
- PDRIVER_INITIALIZE DriverEntry;
- PLDR_DATA_TABLE_ENTRY ModuleObject;
- DRIVER_OBJECT DriverObject;
- NTSTATUS Status;
-
- ModuleObject = LdrGetModuleObject(ModuleName);
- if (ModuleObject != NULL)
- {
- return(STATUS_IMAGE_ALREADY_LOADED);
- }
-
- Status = LdrLoadModule(ModuleName, &ModuleObject);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
-
- RtlZeroMemory(&DriverObject, sizeof(DriverObject));
-// DriverObject.DriverStart = ModuleObject->DllBase;
-
- Status = DriverEntry(&DriverObject, NULL);
- if (!NT_SUCCESS(Status))
- {
- LdrUnloadModule(ModuleObject);
- }
-
- return(Status);
-}
-
-
-NTSTATUS
-NTAPI
-LdrLoadModule(
- PUNICODE_STRING Filename,
- PLDR_DATA_TABLE_ENTRY *ModuleObject )
-{
- PVOID ModuleLoadBase;
- NTSTATUS Status;
- HANDLE FileHandle;
- OBJECT_ATTRIBUTES ObjectAttributes;
- PLDR_DATA_TABLE_ENTRY Module;
- FILE_STANDARD_INFORMATION FileStdInfo;
- IO_STATUS_BLOCK IoStatusBlock;
-
- *ModuleObject = NULL;
-
- DPRINT("Loading Module %wZ...\n", Filename);
-
- /* Open the Module */
- InitializeObjectAttributes(&ObjectAttributes,
- Filename,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
- CHECKPOINT;
- Status = ZwOpenFile(&FileHandle,
- GENERIC_READ,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ,
- FILE_SYNCHRONOUS_IO_NONALERT);
- CHECKPOINT;
- if (!NT_SUCCESS(Status))
- {
- CPRINT("Could not open module file: %wZ (Status 0x%08lx)\n", Filename,
Status);
- return(Status);
- }
- CHECKPOINT;
-
- /* Get the size of the file */
- Status = ZwQueryInformationFile(FileHandle,
- &IoStatusBlock,
- &FileStdInfo,
- sizeof(FileStdInfo),
- FileStandardInformation);
- if (!NT_SUCCESS(Status))
- {
- CPRINT("Could not get file size\n");
- NtClose(FileHandle);
- return(Status);
- }
- CHECKPOINT;
-
- /* Allocate nonpageable memory for driver */
- ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
- FileStdInfo.EndOfFile.u.LowPart,
- TAG_DRIVER_MEM);
- if (ModuleLoadBase == NULL)
- {
- CPRINT("Could not allocate memory for module");
- NtClose(FileHandle);
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
- CHECKPOINT;
-
- /* Load driver into memory chunk */
- Status = ZwReadFile(FileHandle,
- 0, 0, 0,
- &IoStatusBlock,
- ModuleLoadBase,
- FileStdInfo.EndOfFile.u.LowPart,
- 0, 0);
- if (!NT_SUCCESS(Status))
- {
- CPRINT("Could not read module file into memory");
- ExFreePool(ModuleLoadBase);
- NtClose(FileHandle);
- return(Status);
- }
- CHECKPOINT;
-
- ZwClose(FileHandle);
-
- Status = LdrProcessModule(ModuleLoadBase,
- Filename,
- &Module);
- if (!NT_SUCCESS(Status))
- {
- CPRINT("Could not process module\n");
- ExFreePool(ModuleLoadBase);
- return(Status);
- }
-
- /* Cleanup */
- ExFreePool(ModuleLoadBase);
-
- *ModuleObject = Module;
-
- /* Hook for KDB on loading a driver. */
- KDB_LOADDRIVER_HOOK(Filename, Module);
-
- return(STATUS_SUCCESS);
-}
-
-
-NTSTATUS
-NTAPI
-LdrUnloadModule ( PLDR_DATA_TABLE_ENTRY ModuleObject )
-{
- KIRQL Irql;
-
- /* Remove the module from the module list */
- KeAcquireSpinLock(&ModuleListLock,&Irql);
- RemoveEntryList(&ModuleObject->InLoadOrderLinks);
- KeReleaseSpinLock(&ModuleListLock, Irql);
-
- /* Hook for KDB on unloading a driver. */
- KDB_UNLOADDRIVER_HOOK(ModuleObject);
-
- /* Free module section */
- // MmFreeSection(ModuleObject->DllBase);
-
- ExFreePool(ModuleObject->FullDllName.Buffer);
- ExFreePool(ModuleObject);
-
- return(STATUS_SUCCESS);
-}
-
-
-NTSTATUS
-LdrProcessModule(
- PVOID ModuleLoadBase,
- PUNICODE_STRING ModuleName,
- PLDR_DATA_TABLE_ENTRY *ModuleObject )
-{
- PIMAGE_DOS_HEADER PEDosHeader;
-
- /* If MZ header exists */
- PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
- if (PEDosHeader->e_magic == IMAGE_DOS_SIGNATURE &&
PEDosHeader->e_lfanew != 0L)
- {
- return LdrPEProcessModule(ModuleLoadBase,
- ModuleName,
- ModuleObject);
- }
-
- CPRINT("Module wasn't PE\n");
- return STATUS_UNSUCCESSFUL;
-}
-
-NTSTATUS
-NTAPI
-LdrpQueryModuleInformation (
- PVOID Buffer,
- ULONG Size,
- PULONG ReqSize )
-{
- PLIST_ENTRY current_entry;
- PLDR_DATA_TABLE_ENTRY current;
- ULONG ModuleCount = 0;
- PRTL_PROCESS_MODULES Smi;
- ANSI_STRING AnsiName;
- PCHAR p;
- KIRQL Irql;
- PUNICODE_STRING UnicodeName;
- ULONG tmpBufferSize = 0;
- PWCHAR tmpNameBuffer;
-
- KeAcquireSpinLock(&ModuleListLock,&Irql);
-
- /* calculate required size */
- current_entry = ModuleListHead.Flink;
- while (current_entry != (&ModuleListHead))
- {
- ModuleCount++;
- current =
CONTAINING_RECORD(current_entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
- tmpBufferSize += current->FullDllName.Length + sizeof(WCHAR) +
sizeof(UNICODE_STRING);
- current_entry = current_entry->Flink;
- }
-
- *ReqSize = sizeof(RTL_PROCESS_MODULES)+
- (ModuleCount - 1) * sizeof(RTL_PROCESS_MODULE_INFORMATION);
-
- if (Size < *ReqSize)
- {
- KeReleaseSpinLock(&ModuleListLock, Irql);
- return(STATUS_INFO_LENGTH_MISMATCH);
- }
-
- /* allocate a temp buffer to store the module names */
- UnicodeName = ExAllocatePool(NonPagedPool, tmpBufferSize);
- if (UnicodeName == NULL)
- {
- KeReleaseSpinLock(&ModuleListLock, Irql);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- tmpNameBuffer = (PWCHAR)((ULONG_PTR)UnicodeName + ModuleCount *
sizeof(UNICODE_STRING));
-
- /* fill the buffer */
- memset(Buffer, '=', Size);
-
- Smi = (PRTL_PROCESS_MODULES)Buffer;
- Smi->NumberOfModules = ModuleCount;
-
- ModuleCount = 0;
- current_entry = ModuleListHead.Flink;
- while (current_entry != (&ModuleListHead))
- {
- current =
CONTAINING_RECORD(current_entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
-
- Smi->Modules[ModuleCount].Section = 0; /* Always 0 */
- Smi->Modules[ModuleCount].MappedBase = 0; /* Always 0 */
- Smi->Modules[ModuleCount].ImageBase = current->DllBase;
- Smi->Modules[ModuleCount].ImageSize = current->SizeOfImage;
- Smi->Modules[ModuleCount].Flags = 0; /* Flags ??? (GN) */
- Smi->Modules[ModuleCount].LoadOrderIndex = (USHORT)ModuleCount;
- Smi->Modules[ModuleCount].InitOrderIndex = 0;
- Smi->Modules[ModuleCount].LoadCount = 0; /* FIXME */
- UnicodeName[ModuleCount].Buffer = tmpNameBuffer;
- UnicodeName[ModuleCount].MaximumLength = current->FullDllName.Length +
sizeof(WCHAR);
- tmpNameBuffer += UnicodeName[ModuleCount].MaximumLength / sizeof(WCHAR);
- RtlCopyUnicodeString(&UnicodeName[ModuleCount],
¤t->FullDllName);
-
- ModuleCount++;
- current_entry = current_entry->Flink;
- }
-
- KeReleaseSpinLock(&ModuleListLock, Irql);
-
- for (ModuleCount = 0; ModuleCount < Smi->NumberOfModules; ModuleCount++)
- {
- AnsiName.Length = 0;
- AnsiName.MaximumLength = 255;
- AnsiName.Buffer = Smi->Modules[ModuleCount].FullPathName;
- RtlUnicodeStringToAnsiString(&AnsiName, &UnicodeName[ModuleCount],
FALSE);
- AnsiName.Buffer[AnsiName.Length] = 0;
- Smi->Modules[ModuleCount].InitOrderIndex = AnsiName.Length;
-
- p = strrchr(AnsiName.Buffer, '\\');
- if (p == NULL)
- {
- Smi->Modules[ModuleCount].OffsetToFileName = 0;
- }
- else
- {
- p++;
- Smi->Modules[ModuleCount].OffsetToFileName = p - AnsiName.Buffer;
- }
- }
-
- ExFreePool(UnicodeName);
-
- return(STATUS_SUCCESS);
-}
-
-
-static VOID
-LdrpBuildModuleBaseName (
- PUNICODE_STRING BaseName,
- PUNICODE_STRING FullName )
-{
- PWCHAR p;
-
- DPRINT("LdrpBuildModuleBaseName()\n");
- DPRINT("FullName %wZ\n", FullName);
-
- p = wcsrchr(FullName->Buffer, L'\\');
- if (p == NULL)
- {
- p = FullName->Buffer;
- }
- else
- {
- p++;
- }
-
- DPRINT("p %S\n", p);
-
- RtlInitUnicodeString(BaseName, p);
-}
-
-
-static LONG
-LdrpCompareModuleNames (
- IN PUNICODE_STRING String1,
- IN PUNICODE_STRING String2 )
+ IN PUNICODE_STRING String1,
+ IN PUNICODE_STRING String2 )
{
ULONG len1, len2, i;
PWCHAR s1, s2, p;
@@ -573,372 +128,15 @@
return(0);
}
-PLDR_DATA_TABLE_ENTRY
-NTAPI
-LdrGetModuleObject ( PUNICODE_STRING ModuleName )
-{
- PLDR_DATA_TABLE_ENTRY Module;
- PLIST_ENTRY Entry;
- KIRQL Irql;
-
- DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName);
-
- KeAcquireSpinLock(&ModuleListLock,&Irql);
-
- Entry = ModuleListHead.Flink;
- while (Entry != &ModuleListHead)
- {
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-
- DPRINT("Comparing %wZ and %wZ\n",
- &Module->BaseDllName,
- ModuleName);
-
- if (!LdrpCompareModuleNames(&Module->BaseDllName, ModuleName))
- {
- DPRINT("Module %wZ\n", &Module->BaseDllName);
- KeReleaseSpinLock(&ModuleListLock, Irql);
- return(Module);
- }
-
- Entry = Entry->Flink;
- }
-
- KeReleaseSpinLock(&ModuleListLock, Irql);
-
- DPRINT("Could not find module '%wZ'\n", ModuleName);
-
- return(NULL);
-}
-
-
-/* ---------------------------------------------- PE Module support */
-
-static ULONG
-LdrLookupPageProtection (
- PVOID PageStart,
- PVOID DriverBase,
- PIMAGE_FILE_HEADER PEFileHeader,
- PIMAGE_SECTION_HEADER PESectionHeaders )
-{
- BOOLEAN Write = FALSE;
- BOOLEAN Execute = FALSE;
- ULONG Characteristics;
- ULONG Idx;
- ULONG Length;
- PVOID BaseAddress;
-
- for (Idx = 0; Idx < PEFileHeader->NumberOfSections && (!Write ||
!Execute); Idx++)
- {
- Characteristics = PESectionHeaders[Idx].Characteristics;
- if (!(Characteristics & IMAGE_SCN_TYPE_NOLOAD))
- {
- Length = max(PESectionHeaders[Idx].Misc.VirtualSize,
PESectionHeaders[Idx].SizeOfRawData);
- BaseAddress = PESectionHeaders[Idx].VirtualAddress + (char*)DriverBase;
- if (BaseAddress < (PVOID)((ULONG_PTR)PageStart + PAGE_SIZE) &&
- PageStart < (PVOID)((ULONG_PTR)BaseAddress + Length))
- {
- if (Characteristics & IMAGE_SCN_CNT_CODE)
- {
- Execute = TRUE;
- }
- if (Characteristics &
(IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_UNINITIALIZED_DATA))
- {
- Write = TRUE;
- }
- }
- }
- }
- if (Write && Execute)
- {
- return PAGE_EXECUTE_READWRITE;
- }
- else if (Execute)
- {
- return PAGE_EXECUTE_READ;
- }
- else if (Write)
- {
- return PAGE_READWRITE;
- }
- else
- {
- return PAGE_READONLY;
- }
-}
-
-static NTSTATUS
-LdrPEProcessModule(
- PVOID ModuleLoadBase,
- PUNICODE_STRING FileName,
- PLDR_DATA_TABLE_ENTRY *ModuleObject )
-{
- unsigned int DriverSize, Idx;
- ULONG CurrentSize;
- PVOID DriverBase;
- PIMAGE_DOS_HEADER PEDosHeader;
- PIMAGE_NT_HEADERS PENtHeaders;
- PIMAGE_SECTION_HEADER PESectionHeaders;
- PLDR_DATA_TABLE_ENTRY CreatedModuleObject;
- NTSTATUS Status;
- KIRQL Irql;
-
- DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
-
- /* Get header pointers */
- PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
- PENtHeaders = RtlImageNtHeader(ModuleLoadBase);
- PESectionHeaders = IMAGE_FIRST_SECTION(PENtHeaders);
- CHECKPOINT;
-
- /* Check file magic numbers */
- if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
- {
- CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
- return STATUS_UNSUCCESSFUL;
- }
- if (PEDosHeader->e_lfanew == 0)
- {
- CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
- return STATUS_UNSUCCESSFUL;
- }
- if (PENtHeaders->Signature != IMAGE_NT_SIGNATURE)
- {
- CPRINT("Incorrect PE magic: %08x\n", PENtHeaders->Signature);
- return STATUS_UNSUCCESSFUL;
- }
- if (PENtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
- {
- CPRINT("Incorrect Architechture: %04x\n",
PENtHeaders->FileHeader.Machine);
- return STATUS_UNSUCCESSFUL;
- }
- CHECKPOINT;
-
- /* FIXME: if image is fixed-address load, then fail */
-
- /* FIXME: check/verify OS version number */
-
- DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
- PENtHeaders->OptionalHeader.Magic,
- PENtHeaders->OptionalHeader.MajorLinkerVersion,
- PENtHeaders->OptionalHeader.MinorLinkerVersion);
- DPRINT("Entry Point:%08lx\n",
PENtHeaders->OptionalHeader.AddressOfEntryPoint);
-
- /* Determine the size of the module */
- DriverSize = 0;
- for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
- {
- if (!(PESectionHeaders[Idx].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
- {
- CurrentSize = PESectionHeaders[Idx].VirtualAddress +
PESectionHeaders[Idx].Misc.VirtualSize;
- DriverSize = max(DriverSize, CurrentSize);
- }
- }
- DriverSize = ROUND_UP(DriverSize, PENtHeaders->OptionalHeader.SectionAlignment);
- DPRINT("DriverSize %x, SizeOfImage %x\n",DriverSize,
PENtHeaders->OptionalHeader.SizeOfImage);
-
- /* Allocate a virtual section for the module */
- DriverBase = NULL;
- DriverBase = MmAllocateSection(DriverSize, DriverBase);
- if (DriverBase == 0)
- {
- CPRINT("Failed to allocate a virtual section for driver\n");
- return STATUS_UNSUCCESSFUL;
- }
- DPRINT("DriverBase for %wZ: %x\n", FileName, DriverBase);
-
- /* Copy headers over */
- memcpy(DriverBase, ModuleLoadBase, PENtHeaders->OptionalHeader.SizeOfHeaders);
-
- /* Copy image sections into virtual section */
- for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
- {
- CurrentSize = PESectionHeaders[Idx].VirtualAddress +
PESectionHeaders[Idx].Misc.VirtualSize;
- /* Copy current section into current offset of virtual section */
- if (CurrentSize <= DriverSize &&
- PESectionHeaders[Idx].SizeOfRawData)
- {
- DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
- PESectionHeaders[Idx].VirtualAddress + (ULONG_PTR)DriverBase);
- memcpy((PVOID)((ULONG_PTR)DriverBase +
PESectionHeaders[Idx].VirtualAddress),
- (PVOID)((ULONG_PTR)ModuleLoadBase +
PESectionHeaders[Idx].PointerToRawData),
- PESectionHeaders[Idx].Misc.VirtualSize >
PESectionHeaders[Idx].SizeOfRawData
- ? PESectionHeaders[Idx].SizeOfRawData :
PESectionHeaders[Idx].Misc.VirtualSize );
- }
- }
-
- /* Perform relocation fixups */
- Status = LdrRelocateImageWithBias(DriverBase, 0, "", STATUS_SUCCESS,
- STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
- if (!NT_SUCCESS(Status))
- {
- // MmFreeSection(DriverBase);
- return Status;
- }
-
- /* Create the module */
- CreatedModuleObject = ExAllocatePoolWithTag (
- NonPagedPool, sizeof(LDR_DATA_TABLE_ENTRY), TAG_MODULE_OBJECT );
- if (CreatedModuleObject == NULL)
- {
- // MmFreeSection(DriverBase);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- RtlZeroMemory(CreatedModuleObject, sizeof(LDR_DATA_TABLE_ENTRY));
-
- /* Initialize ModuleObject data */
- CreatedModuleObject->DllBase = DriverBase;
-
- CreatedModuleObject->FullDllName.Length = 0;
- CreatedModuleObject->FullDllName.MaximumLength = FileName->Length +
sizeof(UNICODE_NULL);
- CreatedModuleObject->FullDllName.Buffer =
- ExAllocatePoolWithTag(PagedPool,
CreatedModuleObject->FullDllName.MaximumLength, TAG_LDR_WSTR);
- if (CreatedModuleObject->FullDllName.Buffer == NULL)
- {
- ExFreePool(CreatedModuleObject);
- // MmFreeSection(DriverBase);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- RtlCopyUnicodeString(&CreatedModuleObject->FullDllName, FileName);
- CreatedModuleObject->FullDllName.Buffer[FileName->Length / sizeof(WCHAR)] = 0;
- LdrpBuildModuleBaseName(&CreatedModuleObject->BaseDllName,
- &CreatedModuleObject->FullDllName);
-
- CreatedModuleObject->EntryPoint =
- (PVOID)((ULONG_PTR)DriverBase +
- PENtHeaders->OptionalHeader.AddressOfEntryPoint);
- CreatedModuleObject->SizeOfImage = DriverSize;
- DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
-
- /* Perform import fixups */
- Status = LdrPEFixupImports(CreatedModuleObject->DllBase,
- CreatedModuleObject->FullDllName.Buffer);
- if (!NT_SUCCESS(Status))
- {
- // MmFreeSection(DriverBase);
- ExFreePool(CreatedModuleObject->FullDllName.Buffer);
- ExFreePool(CreatedModuleObject);
- return Status;
- }
-
- MmSetPageProtect(NULL, DriverBase, PAGE_READONLY);
- /* Set the protections for the various parts of the driver */
- for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
- {
- ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
- ULONG Length;
- PVOID BaseAddress;
- PVOID PageAddress;
- ULONG Protect;
- Length = PESectionHeaders[Idx].Misc.VirtualSize;
- BaseAddress = PESectionHeaders[Idx].VirtualAddress + (char*)DriverBase;
- PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
-
- Protect = LdrLookupPageProtection(PageAddress, DriverBase,
&PENtHeaders->FileHeader, PESectionHeaders);
- if (PageAddress < RVA(DriverBase, DriverSize))
- {
- MmSetPageProtect(NULL, PageAddress, Protect);
- }
-
- if (Characteristics & IMAGE_SCN_CNT_CODE)
- {
- if (Characteristics & IMAGE_SCN_MEM_WRITE)
- {
- Protect = PAGE_EXECUTE_READWRITE;
- }
- else
- {
- Protect = PAGE_EXECUTE_READ;
- }
- }
- else if (Characteristics &
(IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_UNINITIALIZED_DATA))
- {
- Protect = PAGE_READWRITE;
- }
- else
- {
- Protect = PAGE_READONLY;
- }
- PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE);
- while ((ULONG_PTR)PageAddress + PAGE_SIZE < (ULONG_PTR)BaseAddress + Length)
- {
- if (PageAddress < RVA(DriverBase, DriverSize))
- {
- MmSetPageProtect(NULL, PageAddress, Protect);
- }
- PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE);
- }
- if (PageAddress < (PVOID)((ULONG_PTR)BaseAddress + Length) &&
- PageAddress < RVA(DriverBase, DriverSize))
- {
- Protect = LdrLookupPageProtection(PageAddress, DriverBase,
&PENtHeaders->FileHeader, PESectionHeaders);
- MmSetPageProtect(NULL, PageAddress, Protect);
- }
- }
-
- /* Insert module */
- KeAcquireSpinLock(&ModuleListLock, &Irql);
- InsertTailList(&ModuleListHead,
- &CreatedModuleObject->InLoadOrderLinks);
- KeReleaseSpinLock(&ModuleListLock, Irql);
-
- *ModuleObject = CreatedModuleObject;
-
- DPRINT("Loading Module %wZ...\n", FileName);
-
- DPRINT("Module %wZ loaded at 0x%.08x.\n",
- FileName, CreatedModuleObject->DllBase);
-
- return STATUS_SUCCESS;
-}
-
-static PVOID
-LdrPEFixupForward ( PCHAR ForwardName )
-{
- CHAR NameBuffer[128];
- UNICODE_STRING ModuleName;
- PCHAR p;
- PLDR_DATA_TABLE_ENTRY 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 = LdrGetModuleObject(&ModuleName);
- RtlFreeUnicodeString(&ModuleName);
-
- DPRINT("ModuleObject: %p\n", ModuleObject);
-
- if (ModuleObject == NULL)
- {
- CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
- return NULL;
- }
- return LdrPEGetExportByName(ModuleObject->DllBase, (PUCHAR)(p+1), 0xffff);
-}
-
#ifndef PATH_MAX
#define PATH_MAX 260
#endif
static NTSTATUS
LdrPEGetOrLoadModule (
- PWCHAR ModuleName,
- PCHAR ImportedName,
- PLDR_DATA_TABLE_ENTRY* ImportedModule)
+ PWCHAR ModuleName,
+ PCHAR ImportedName,
+ PLDR_DATA_TABLE_ENTRY* ImportedModule)
{
UNICODE_STRING DriverName;
UNICODE_STRING NameString;
@@ -994,10 +192,82 @@
}
static PVOID
+LdrPEFixupForward ( PCHAR ForwardName )
+{
+ CHAR NameBuffer[128];
+ UNICODE_STRING ModuleName;
+ PCHAR p;
+ PLDR_DATA_TABLE_ENTRY 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 = LdrGetModuleObject(&ModuleName);
+ RtlFreeUnicodeString(&ModuleName);
+
+ DPRINT("ModuleObject: %p\n", ModuleObject);
+
+ if (ModuleObject == NULL)
+ {
+ DPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
+ return NULL;
+ }
+ return LdrPEGetExportByName(ModuleObject->DllBase, (PUCHAR)(p+1), 0xffff);
+}
+
+static PVOID
+LdrPEGetExportByOrdinal (
+ PVOID BaseAddress,
+ ULONG Ordinal )
+{
+ PIMAGE_EXPORT_DIRECTORY ExportDir;
+ ULONG ExportDirSize;
+ PULONG * ExFunctions;
+ PVOID Function;
+
+ ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData (
+ BaseAddress,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &ExportDirSize);
+
+ ExFunctions = (PULONG *)RVA(BaseAddress,
+ ExportDir->AddressOfFunctions);
+ DPRINT("LdrPEGetExportByOrdinal(Ordinal %d) = %x\n",
+ Ordinal,
+ RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base]));
+
+ Function = 0 != ExFunctions[Ordinal - ExportDir->Base]
+ ? RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] )
+ : NULL;
+
+ if (((ULONG_PTR)Function >= (ULONG_PTR)ExportDir) &&
+ ((ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize))
+ {
+ DPRINT("Forward: %s\n", (PCHAR)Function);
+ Function = LdrPEFixupForward((PCHAR)Function);
+ }
+
+ return Function;
+}
+
+static PVOID
LdrPEGetExportByName (
- PVOID BaseAddress,
- PUCHAR SymbolName,
- USHORT Hint )
+ PVOID BaseAddress,
+ PUCHAR SymbolName,
+ USHORT Hint )
{
PIMAGE_EXPORT_DIRECTORY ExportDir;
PULONG * ExFunctions;
@@ -1110,47 +380,11 @@
return (PVOID)NULL;
}
-static PVOID
-LdrPEGetExportByOrdinal (
- PVOID BaseAddress,
- ULONG Ordinal )
-{
- PIMAGE_EXPORT_DIRECTORY ExportDir;
- ULONG ExportDirSize;
- PULONG * ExFunctions;
- PVOID Function;
-
- ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData (
- BaseAddress,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_EXPORT,
- &ExportDirSize);
-
- ExFunctions = (PULONG *)RVA(BaseAddress,
- ExportDir->AddressOfFunctions);
- DPRINT("LdrPEGetExportByOrdinal(Ordinal %d) = %x\n",
- Ordinal,
- RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base]));
-
- Function = 0 != ExFunctions[Ordinal - ExportDir->Base]
- ? RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] )
- : NULL;
-
- if (((ULONG_PTR)Function >= (ULONG_PTR)ExportDir) &&
- ((ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize))
- {
- DPRINT("Forward: %s\n", (PCHAR)Function);
- Function = LdrPEFixupForward((PCHAR)Function);
- }
-
- return Function;
-}
-
static NTSTATUS
LdrPEProcessImportDirectoryEntry(
- PVOID DriverBase,
- PLDR_DATA_TABLE_ENTRY ImportedModule,
- PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory )
+ PVOID DriverBase,
+ PLDR_DATA_TABLE_ENTRY ImportedModule,
+ PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory )
{
PVOID* ImportAddressList;
PULONG FunctionNameList;
@@ -1244,4 +478,621 @@
return STATUS_SUCCESS;
}
+static NTSTATUS
+LdrPEProcessModule(
+ PVOID ModuleLoadBase,
+ PUNICODE_STRING FileName,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject )
+{
+ unsigned int DriverSize, Idx;
+ ULONG CurrentSize;
+ PVOID DriverBase;
+ PIMAGE_DOS_HEADER PEDosHeader;
+ PIMAGE_NT_HEADERS PENtHeaders;
+ PIMAGE_SECTION_HEADER PESectionHeaders;
+ PLDR_DATA_TABLE_ENTRY CreatedModuleObject;
+ NTSTATUS Status;
+ KIRQL Irql;
+
+ DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
+
+ /* Get header pointers */
+ PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
+ PENtHeaders = RtlImageNtHeader(ModuleLoadBase);
+ PESectionHeaders = IMAGE_FIRST_SECTION(PENtHeaders);
+
+
+ /* Check file magic numbers */
+ if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+ {
+ DPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
+ return STATUS_UNSUCCESSFUL;
+ }
+ if (PEDosHeader->e_lfanew == 0)
+ {
+ DPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
+ return STATUS_UNSUCCESSFUL;
+ }
+ if (PENtHeaders->Signature != IMAGE_NT_SIGNATURE)
+ {
+ DPRINT("Incorrect PE magic: %08x\n", PENtHeaders->Signature);
+ return STATUS_UNSUCCESSFUL;
+ }
+ if (PENtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
+ {
+ DPRINT("Incorrect Architechture: %04x\n",
PENtHeaders->FileHeader.Machine);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+
+ /* FIXME: if image is fixed-address load, then fail */
+
+ /* FIXME: check/verify OS version number */
+
+ DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
+ PENtHeaders->OptionalHeader.Magic,
+ PENtHeaders->OptionalHeader.MajorLinkerVersion,
+ PENtHeaders->OptionalHeader.MinorLinkerVersion);
+ DPRINT("Entry Point:%08lx\n",
PENtHeaders->OptionalHeader.AddressOfEntryPoint);
+
+ /* Determine the size of the module */
+ DriverSize = 0;
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
+ {
+ if (!(PESectionHeaders[Idx].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+ {
+ CurrentSize = PESectionHeaders[Idx].VirtualAddress +
PESectionHeaders[Idx].Misc.VirtualSize;
+ DriverSize = max(DriverSize, CurrentSize);
+ }
+ }
+ DriverSize = ROUND_UP(DriverSize, PENtHeaders->OptionalHeader.SectionAlignment);
+ DPRINT("DriverSize %x, SizeOfImage %x\n",DriverSize,
PENtHeaders->OptionalHeader.SizeOfImage);
+
+ /* Allocate a virtual section for the module */
+ DriverBase = NULL;
+ DriverBase = MmAllocateSection(DriverSize, DriverBase);
+ if (DriverBase == 0)
+ {
+ DPRINT("Failed to allocate a virtual section for driver\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+ DPRINT1("DriverBase for %wZ: %x\n", FileName, DriverBase);
+
+ /* Copy headers over */
+ memcpy(DriverBase, ModuleLoadBase, PENtHeaders->OptionalHeader.SizeOfHeaders);
+
+ /* Copy image sections into virtual section */
+ for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
+ {
+ CurrentSize = PESectionHeaders[Idx].VirtualAddress +
PESectionHeaders[Idx].Misc.VirtualSize;
+ /* Copy current section into current offset of virtual section */
+ if (CurrentSize <= DriverSize &&
+ PESectionHeaders[Idx].SizeOfRawData)
+ {
+ DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
+ PESectionHeaders[Idx].VirtualAddress + (ULONG_PTR)DriverBase);
+ memcpy((PVOID)((ULONG_PTR)DriverBase +
PESectionHeaders[Idx].VirtualAddress),
+ (PVOID)((ULONG_PTR)ModuleLoadBase +
PESectionHeaders[Idx].PointerToRawData),
+ PESectionHeaders[Idx].Misc.VirtualSize >
PESectionHeaders[Idx].SizeOfRawData
+ ? PESectionHeaders[Idx].SizeOfRawData :
PESectionHeaders[Idx].Misc.VirtualSize );
+ }
+ }
+
+ /* Perform relocation fixups */
+ Status = LdrRelocateImageWithBias(DriverBase, 0, "", STATUS_SUCCESS,
+ STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
+ if (!NT_SUCCESS(Status))
+ {
+ // MmFreeSection(DriverBase);
+ return Status;
+ }
+
+ /* Create the module */
+ CreatedModuleObject = ExAllocatePoolWithTag (
+ NonPagedPool, sizeof(LDR_DATA_TABLE_ENTRY), TAG_MODULE_OBJECT );
+ if (CreatedModuleObject == NULL)
+ {
+ // MmFreeSection(DriverBase);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(CreatedModuleObject, sizeof(LDR_DATA_TABLE_ENTRY));
+
+ /* Initialize ModuleObject data */
+ CreatedModuleObject->DllBase = DriverBase;
+
+ CreatedModuleObject->FullDllName.Length = 0;
+ CreatedModuleObject->FullDllName.MaximumLength = FileName->Length +
sizeof(UNICODE_NULL);
+ CreatedModuleObject->FullDllName.Buffer =
+ ExAllocatePoolWithTag(PagedPool,
CreatedModuleObject->FullDllName.MaximumLength, TAG_LDR_WSTR);
+ if (CreatedModuleObject->FullDllName.Buffer == NULL)
+ {
+ ExFreePool(CreatedModuleObject);
+ // MmFreeSection(DriverBase);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlCopyUnicodeString(&CreatedModuleObject->FullDllName, FileName);
+ CreatedModuleObject->FullDllName.Buffer[FileName->Length / sizeof(WCHAR)] = 0;
+ LdrpBuildModuleBaseName(&CreatedModuleObject->BaseDllName,
+ &CreatedModuleObject->FullDllName);
+
+ CreatedModuleObject->EntryPoint =
+ (PVOID)((ULONG_PTR)DriverBase +
+ PENtHeaders->OptionalHeader.AddressOfEntryPoint);
+ CreatedModuleObject->SizeOfImage = DriverSize;
+ DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
+
+ /* Perform import fixups */
+ Status = LdrPEFixupImports(CreatedModuleObject->DllBase,
+ CreatedModuleObject->FullDllName.Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ // MmFreeSection(DriverBase);
+ ExFreePool(CreatedModuleObject->FullDllName.Buffer);
+ ExFreePool(CreatedModuleObject);
+ return Status;
+ }
+
+ /* Insert module */
+ KeAcquireSpinLock(&ModuleListLock, &Irql);
+ InsertTailList(&ModuleListHead,
+ &CreatedModuleObject->InLoadOrderLinks);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+
+ *ModuleObject = CreatedModuleObject;
+
+ DPRINT("Loading Module %wZ...\n", FileName);
+
+ DPRINT("Module %wZ loaded at 0x%.08x.\n",
+ FileName, CreatedModuleObject->DllBase);
+
+ return STATUS_SUCCESS;
+}
+
+
+VOID
+INIT_FUNCTION
+NTAPI
+LdrInit1(VOID)
+{
+ PLDR_DATA_TABLE_ENTRY HalModuleObject, NtoskrnlModuleObject, LdrEntry;
+
+ /* Initialize the module list and spinlock */
+ InitializeListHead(&ModuleListHead);
+ KeInitializeSpinLock(&ModuleListLock);
+
+ /* Get the NTOSKRNL Entry from the loader */
+ LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink,
LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+
+ /* Initialize ModuleObject for NTOSKRNL */
+ NtoskrnlModuleObject = ExAllocatePoolWithTag(PagedPool,
+ sizeof(LDR_DATA_TABLE_ENTRY),
+ TAG('M', 'm',
'L', 'd'));
+ NtoskrnlModuleObject->DllBase = LdrEntry->DllBase;
+ RtlInitUnicodeString(&NtoskrnlModuleObject->FullDllName, KERNEL_MODULE_NAME);
+ LdrpBuildModuleBaseName(&NtoskrnlModuleObject->BaseDllName,
&NtoskrnlModuleObject->FullDllName);
+ NtoskrnlModuleObject->EntryPoint = LdrEntry->EntryPoint;
+ NtoskrnlModuleObject->SizeOfImage = LdrEntry->SizeOfImage;
+
+ /* Insert it into the list */
+ InsertTailList(&ModuleListHead, &NtoskrnlModuleObject->InLoadOrderLinks);
+
+ /* Get the HAL Entry from the loader */
+ LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink->Flink,
LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+
+ /* Initialize ModuleObject for HAL */
+ HalModuleObject = ExAllocatePoolWithTag(PagedPool,
+ sizeof(LDR_DATA_TABLE_ENTRY),
+ TAG('M', 'm',
'L', 'd'));
+ HalModuleObject->DllBase = LdrEntry->DllBase;
+ RtlInitUnicodeString(&HalModuleObject->FullDllName, HAL_MODULE_NAME);
+ LdrpBuildModuleBaseName(&HalModuleObject->BaseDllName,
&HalModuleObject->FullDllName);
+ HalModuleObject->EntryPoint = LdrEntry->EntryPoint;
+ HalModuleObject->SizeOfImage = LdrEntry->SizeOfImage;
+
+ /* Insert it into the list */
+ InsertTailList(&ModuleListHead, &HalModuleObject->InLoadOrderLinks);
+
+ /* Hook for KDB on initialization of the loader. */
+ KDB_LOADERINIT_HOOK(NtoskrnlModuleObject, HalModuleObject);
+}
+
+//
+// Used for checking if a module is already in the module list.
+// Used during loading/unloading drivers.
+//
+PLDR_DATA_TABLE_ENTRY
+NTAPI
+LdrGetModuleObject ( PUNICODE_STRING ModuleName )
+{
+ PLDR_DATA_TABLE_ENTRY Module;
+ PLIST_ENTRY Entry;
+ KIRQL Irql;
+
+ DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName);
+
+ KeAcquireSpinLock(&ModuleListLock,&Irql);
+
+ Entry = ModuleListHead.Flink;
+ while (Entry != &ModuleListHead)
+ {
+ Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+
+ DPRINT("Comparing %wZ and %wZ\n",
+ &Module->BaseDllName,
+ ModuleName);
+
+ if (!LdrpCompareModuleNames(&Module->BaseDllName, ModuleName))
+ {
+ DPRINT("Module %wZ\n", &Module->BaseDllName);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+ return(Module);
+ }
+
+ Entry = Entry->Flink;
+ }
+
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+
+ DPRINT("Could not find module '%wZ'\n", ModuleName);
+
+ return(NULL);
+}
+
+//
+// Used by NtSetSystemInformation
+//
+NTSTATUS
+NTAPI
+LdrpLoadImage (
+ PUNICODE_STRING DriverName,
+ PVOID *ModuleBase,
+ PVOID *SectionPointer,
+ PVOID *EntryPoint,
+ PVOID *ExportSectionPointer )
+{
+ PLDR_DATA_TABLE_ENTRY ModuleObject;
+ NTSTATUS Status;
+
+ ModuleObject = LdrGetModuleObject(DriverName);
+ if (ModuleObject == NULL)
+ {
+ Status = LdrLoadModule(DriverName, &ModuleObject);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+ }
+
+ if (ModuleBase)
+ *ModuleBase = ModuleObject->DllBase;
+
+ if (SectionPointer)
+ *SectionPointer = ModuleObject;
+
+ if (EntryPoint)
+ *EntryPoint = ModuleObject->EntryPoint;
+
+ //if (ExportSectionPointer)
+ // *ExportSectionPointer = ModuleObject->
+
+ return(STATUS_SUCCESS);
+}
+
+//
+// Used by NtSetSystemInformation
+//
+NTSTATUS
+NTAPI
+LdrpUnloadImage ( PVOID ModuleBase )
+{
+ return(STATUS_NOT_IMPLEMENTED);
+}
+
+//
+// Used by NtSetSystemInformation
+//
+NTSTATUS
+NTAPI
+LdrpLoadAndCallImage ( PUNICODE_STRING ModuleName )
+{
+ PDRIVER_INITIALIZE DriverEntry;
+ PLDR_DATA_TABLE_ENTRY ModuleObject;
+ DRIVER_OBJECT DriverObject;
+ NTSTATUS Status;
+
+ ModuleObject = LdrGetModuleObject(ModuleName);
+ if (ModuleObject != NULL)
+ {
+ return(STATUS_IMAGE_ALREADY_LOADED);
+ }
+
+ Status = LdrLoadModule(ModuleName, &ModuleObject);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
+
+ RtlZeroMemory(&DriverObject, sizeof(DriverObject));
+// DriverObject.DriverStart = ModuleObject->DllBase;
+
+ Status = DriverEntry(&DriverObject, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ LdrUnloadModule(ModuleObject);
+ }
+
+ return(Status);
+}
+
+//
+// Used when unloading drivers
+//
+NTSTATUS
+NTAPI
+LdrUnloadModule ( PLDR_DATA_TABLE_ENTRY ModuleObject )
+{
+ KIRQL Irql;
+
+ /* Remove the module from the module list */
+ KeAcquireSpinLock(&ModuleListLock,&Irql);
+ RemoveEntryList(&ModuleObject->InLoadOrderLinks);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+
+ /* Hook for KDB on unloading a driver. */
+ KDB_UNLOADDRIVER_HOOK(ModuleObject);
+
+ /* Free module section */
+ // MmFreeSection(ModuleObject->DllBase);
+
+ ExFreePool(ModuleObject->FullDllName.Buffer);
+ ExFreePool(ModuleObject);
+
+ return(STATUS_SUCCESS);
+}
+
+//
+// Used for images already loaded (boot drivers)
+//
+NTSTATUS
+LdrProcessModule(
+ PVOID ModuleLoadBase,
+ PUNICODE_STRING ModuleName,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject )
+{
+ PIMAGE_DOS_HEADER PEDosHeader;
+
+ /* If MZ header exists */
+ PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
+ if (PEDosHeader->e_magic == IMAGE_DOS_SIGNATURE &&
PEDosHeader->e_lfanew != 0L)
+ {
+ return LdrPEProcessModule(ModuleLoadBase,
+ ModuleName,
+ ModuleObject);
+ }
+
+ DPRINT("Module wasn't PE\n");
+ return STATUS_UNSUCCESSFUL;
+}
+
+//
+// Used by NtLoadDriver/IoMgr
+//
+NTSTATUS
+NTAPI
+LdrLoadModule(
+ PUNICODE_STRING Filename,
+ PLDR_DATA_TABLE_ENTRY *ModuleObject )
+{
+ PVOID ModuleLoadBase;
+ NTSTATUS Status;
+ HANDLE FileHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PLDR_DATA_TABLE_ENTRY Module;
+ FILE_STANDARD_INFORMATION FileStdInfo;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ *ModuleObject = NULL;
+
+ DPRINT("Loading Module %wZ...\n", Filename);
+
+ /* Open the Module */
+ InitializeObjectAttributes(&ObjectAttributes,
+ Filename,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = ZwOpenFile(&FileHandle,
+ GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Could not open module file: %wZ (Status 0x%08lx)\n", Filename,
Status);
+ return(Status);
+ }
+
+
+ /* Get the size of the file */
+ Status = ZwQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileStdInfo,
+ sizeof(FileStdInfo),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Could not get file size\n");
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+
+ /* Allocate nonpageable memory for driver */
+ ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
+ FileStdInfo.EndOfFile.u.LowPart,
+ TAG_DRIVER_MEM);
+ if (ModuleLoadBase == NULL)
+ {
+ DPRINT("Could not allocate memory for module");
+ NtClose(FileHandle);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+
+ /* Load driver into memory chunk */
+ Status = ZwReadFile(FileHandle,
+ 0, 0, 0,
+ &IoStatusBlock,
+ ModuleLoadBase,
+ FileStdInfo.EndOfFile.u.LowPart,
+ 0, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Could not read module file into memory");
+ ExFreePool(ModuleLoadBase);
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+
+ ZwClose(FileHandle);
+
+ Status = LdrProcessModule(ModuleLoadBase,
+ Filename,
+ &Module);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Could not process module\n");
+ ExFreePool(ModuleLoadBase);
+ return(Status);
+ }
+
+ /* Cleanup */
+ ExFreePool(ModuleLoadBase);
+
+ *ModuleObject = Module;
+
+ /* Hook for KDB on loading a driver. */
+ KDB_LOADDRIVER_HOOK(Filename, Module);
+
+ return(STATUS_SUCCESS);
+}
+
+//
+// Used by NtSetSystemInformation
+//
+NTSTATUS
+NTAPI
+LdrpQueryModuleInformation (
+ PVOID Buffer,
+ ULONG Size,
+ PULONG ReqSize )
+{
+ PLIST_ENTRY current_entry;
+ PLDR_DATA_TABLE_ENTRY current;
+ ULONG ModuleCount = 0;
+ PRTL_PROCESS_MODULES Smi;
+ ANSI_STRING AnsiName;
+ PCHAR p;
+ KIRQL Irql;
+ PUNICODE_STRING UnicodeName;
+ ULONG tmpBufferSize = 0;
+ PWCHAR tmpNameBuffer;
+
+ KeAcquireSpinLock(&ModuleListLock,&Irql);
+
+ /* calculate required size */
+ current_entry = ModuleListHead.Flink;
+ while (current_entry != (&ModuleListHead))
+ {
+ ModuleCount++;
+ current =
CONTAINING_RECORD(current_entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
+ tmpBufferSize += current->FullDllName.Length + sizeof(WCHAR) +
sizeof(UNICODE_STRING);
+ current_entry = current_entry->Flink;
+ }
+
+ *ReqSize = sizeof(RTL_PROCESS_MODULES)+
+ (ModuleCount - 1) * sizeof(RTL_PROCESS_MODULE_INFORMATION);
+
+ if (Size < *ReqSize)
+ {
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+ return(STATUS_INFO_LENGTH_MISMATCH);
+ }
+
+ /* allocate a temp buffer to store the module names */
+ UnicodeName = ExAllocatePool(NonPagedPool, tmpBufferSize);
+ if (UnicodeName == NULL)
+ {
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ tmpNameBuffer = (PWCHAR)((ULONG_PTR)UnicodeName + ModuleCount *
sizeof(UNICODE_STRING));
+
+ /* fill the buffer */
+ memset(Buffer, '=', Size);
+
+ Smi = (PRTL_PROCESS_MODULES)Buffer;
+ Smi->NumberOfModules = ModuleCount;
+
+ ModuleCount = 0;
+ current_entry = ModuleListHead.Flink;
+ while (current_entry != (&ModuleListHead))
+ {
+ current =
CONTAINING_RECORD(current_entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
+
+ Smi->Modules[ModuleCount].Section = 0; /* Always 0 */
+ Smi->Modules[ModuleCount].MappedBase = 0; /* Always 0 */
+ Smi->Modules[ModuleCount].ImageBase = current->DllBase;
+ Smi->Modules[ModuleCount].ImageSize = current->SizeOfImage;
+ Smi->Modules[ModuleCount].Flags = 0; /* Flags ??? (GN) */
+ Smi->Modules[ModuleCount].LoadOrderIndex = (USHORT)ModuleCount;
+ Smi->Modules[ModuleCount].InitOrderIndex = 0;
+ Smi->Modules[ModuleCount].LoadCount = 0; /* FIXME */
+ UnicodeName[ModuleCount].Buffer = tmpNameBuffer;
+ UnicodeName[ModuleCount].MaximumLength = current->FullDllName.Length +
sizeof(WCHAR);
+ tmpNameBuffer += UnicodeName[ModuleCount].MaximumLength / sizeof(WCHAR);
+ RtlCopyUnicodeString(&UnicodeName[ModuleCount],
¤t->FullDllName);
+
+ ModuleCount++;
+ current_entry = current_entry->Flink;
+ }
+
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+
+ for (ModuleCount = 0; ModuleCount < Smi->NumberOfModules; ModuleCount++)
+ {
+ AnsiName.Length = 0;
+ AnsiName.MaximumLength = 255;
+ AnsiName.Buffer = Smi->Modules[ModuleCount].FullPathName;
+ RtlUnicodeStringToAnsiString(&AnsiName, &UnicodeName[ModuleCount],
FALSE);
+ AnsiName.Buffer[AnsiName.Length] = 0;
+ Smi->Modules[ModuleCount].InitOrderIndex = AnsiName.Length;
+
+ p = strrchr(AnsiName.Buffer, '\\');
+ if (p == NULL)
+ {
+ Smi->Modules[ModuleCount].OffsetToFileName = 0;
+ }
+ else
+ {
+ p++;
+ Smi->Modules[ModuleCount].OffsetToFileName = p - AnsiName.Buffer;
+ }
+ }
+
+ ExFreePool(UnicodeName);
+
+ return(STATUS_SUCCESS);
+}
+
+
+
/* EOF */