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=2... ============================================================================== --- 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 */