X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fntoskrnl%2Fldr%2Floader.c;h=0f47e691a711167514c9af2a9f78e7ad1474c763;hp=9c58c5aaec64f0b1df6a82efe6d630ae8a18f54e;hb=fa63ad2beed5aad8c6cf541bda983e02ea20fd34;hpb=2ee2dcfd7ef7dfeb67e8b4795d14294b06cd5ef6 diff --git a/reactos/ntoskrnl/ldr/loader.c b/reactos/ntoskrnl/ldr/loader.c index 9c58c5aaec6..0f47e691a71 100644 --- a/reactos/ntoskrnl/ldr/loader.c +++ b/reactos/ntoskrnl/ldr/loader.c @@ -1,24 +1,14 @@ /* $Id$ - * + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ldr/loader.c * PURPOSE: Loaders for PE executables + * * PROGRAMMERS: Jean Michault * Rex Jolliff (rex@lvcablemodem.com) * Jason Filby (jasonfilby@yahoo.com) * Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * DW 22/05/98 Created - * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE - * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF - * RJJ 10/12/98 Rolled in David's code to load COFF drivers - * JM 14/12/98 Built initial PE user module loader - * RJJ 06/03/99 Moved user PE loader into NTDLL - * JF 26/01/2000 Recoded some parts to retrieve export details correctly - * DW 27/06/2000 Removed redundant header files - * CSH 11/04/2001 Added automatic loading of module symbols if they exist - * KJK 02/04/2003 Nebbet-ized a couple of type names */ @@ -36,1575 +26,1508 @@ #endif /* __GNUC__ */ #endif +#if 0 +#undef ps +#define ps(args...) DPRINT1(args) +#endif + #define NDEBUG #include +#if defined (ALLOC_PRAGMA) +#pragma alloc_text(INIT, LdrInit1) +#pragma alloc_text(INIT, LdrInitModuleManagement) +#pragma alloc_text(INIT, LdrSafePEProcessModule) +#endif + /* GLOBALS *******************************************************************/ LIST_ENTRY ModuleListHead; KSPIN_LOCK ModuleListLock; -MODULE_OBJECT NtoskrnlModuleObject; -MODULE_OBJECT HalModuleObject; +LDR_DATA_TABLE_ENTRY NtoskrnlModuleObject; +LDR_DATA_TABLE_ENTRY HalModuleObject; -LIST_ENTRY ModuleTextListHead; -STATIC MODULE_TEXT_SECTION NtoskrnlTextSection; -STATIC MODULE_TEXT_SECTION LdrHalTextSection; ULONG_PTR LdrHalBase; -#define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M') - -#ifndef HIWORD -#define HIWORD(X) ((WORD) (((DWORD) (X) >> 16) & 0xFFFF)) -#endif -#ifndef LOWORD -#define LOWORD(X) ((WORD) (X)) -#endif - /* FORWARD DECLARATIONS ******************************************************/ NTSTATUS -LdrProcessModule(PVOID ModuleLoadBase, - PUNICODE_STRING ModuleName, - PMODULE_OBJECT *ModuleObject); +LdrProcessModule ( + PVOID ModuleLoadBase, + PUNICODE_STRING ModuleName, + PLDR_DATA_TABLE_ENTRY *ModuleObject ); static VOID -LdrpBuildModuleBaseName(PUNICODE_STRING BaseName, - PUNICODE_STRING FullName); +LdrpBuildModuleBaseName ( + PUNICODE_STRING BaseName, + PUNICODE_STRING FullName ); static LONG -LdrpCompareModuleNames(IN PUNICODE_STRING String1, - IN PUNICODE_STRING String2); +LdrpCompareModuleNames ( + IN PUNICODE_STRING String1, + IN PUNICODE_STRING String2 ); /* PE Driver load support */ -static NTSTATUS LdrPEProcessModule(PVOID ModuleLoadBase, - PUNICODE_STRING FileName, - PMODULE_OBJECT *ModuleObject); +static NTSTATUS +LdrPEProcessModule ( + PVOID ModuleLoadBase, + PUNICODE_STRING FileName, + PLDR_DATA_TABLE_ENTRY *ModuleObject ); + static PVOID -LdrPEGetExportByName(PVOID BaseAddress, - PUCHAR SymbolName, - WORD Hint); +LdrPEGetExportByName ( + PVOID BaseAddress, + PUCHAR SymbolName, + WORD Hint ); static PVOID -LdrPEFixupForward(PCHAR ForwardName); +LdrPEFixupForward ( PCHAR ForwardName ); static NTSTATUS -LdrPEPerformRelocations(PVOID DriverBase, - ULONG DriverSize); +LdrPEPerformRelocations ( + PVOID DriverBase, + ULONG DriverSize ); static NTSTATUS -LdrPEFixupImports(PMODULE_OBJECT Module); +LdrPEFixupImports ( PLDR_DATA_TABLE_ENTRY Module ); /* FUNCTIONS *****************************************************************/ VOID -LdrInitDebug(PLOADER_MODULE Module, PWCH Name) +NTAPI +LdrInitDebug ( PLOADER_MODULE Module, PWCH Name ) { - PLIST_ENTRY current_entry; - MODULE_TEXT_SECTION* current; - - current_entry = ModuleTextListHead.Flink; - while (current_entry != &ModuleTextListHead) - { - current = - CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry); - if (wcscmp(current->Name, Name) == 0) - { - break; - } - current_entry = current_entry->Flink; - } - - if (current_entry == &ModuleTextListHead) - { - return; - } } -VOID INIT_FUNCTION -LdrInit1(VOID) +VOID +INIT_FUNCTION +NTAPI +LdrInit1 ( VOID ) { - PIMAGE_NT_HEADERS NtHeader; - PIMAGE_SECTION_HEADER SectionList; - - InitializeListHead(&ModuleTextListHead); - - /* Setup ntoskrnl.exe text section */ - /* - * This isn't the base of the text segment, but the start of the - * full image (in memory) - * Also, the Length field isn't set to the length of the segment, - * but is more like the offset, from the image base, to the end - * of the segment. - */ - NtHeader = RtlImageNtHeader((PVOID)KERNEL_BASE); - SectionList = IMAGE_FIRST_SECTION(NtHeader); - NtoskrnlTextSection.Base = KERNEL_BASE; - NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize + - SectionList[0].VirtualAddress; - NtoskrnlTextSection.Name = KERNEL_MODULE_NAME; - NtoskrnlTextSection.OptionalHeader = OPTHDROFFSET(KERNEL_BASE); - InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry); - - /* Setup hal.dll text section */ - /* Same comment as above applies */ - NtHeader = RtlImageNtHeader((PVOID)LdrHalBase); - SectionList = IMAGE_FIRST_SECTION(NtHeader); - LdrHalTextSection.Base = LdrHalBase; - LdrHalTextSection.Length = SectionList[0].Misc.VirtualSize + - SectionList[0].VirtualAddress; - LdrHalTextSection.Name = HAL_MODULE_NAME; - LdrHalTextSection.OptionalHeader = OPTHDROFFSET(LdrHalBase); - InsertTailList(&ModuleTextListHead, &LdrHalTextSection.ListEntry); - - /* Hook for KDB on initialization of the loader. */ - KDB_LOADERINIT_HOOK(&NtoskrnlTextSection, &LdrHalTextSection); + /* Hook for KDB on initialization of the loader. */ + KDB_LOADERINIT_HOOK(&NtoskrnlModuleObject, &HalModuleObject); } -VOID INIT_FUNCTION -LdrInitModuleManagement(VOID) +VOID +INIT_FUNCTION +NTAPI +LdrInitModuleManagement ( VOID ) { - PIMAGE_NT_HEADERS NtHeader; - - /* Initialize the module list and spinlock */ - InitializeListHead(&ModuleListHead); - KeInitializeSpinLock(&ModuleListLock); - - /* Initialize ModuleObject for NTOSKRNL */ - RtlZeroMemory(&NtoskrnlModuleObject, sizeof(MODULE_OBJECT)); - NtoskrnlModuleObject.Base = (PVOID) KERNEL_BASE; - NtoskrnlModuleObject.Flags = MODULE_FLAG_PE; - RtlInitUnicodeString(&NtoskrnlModuleObject.FullName, KERNEL_MODULE_NAME); - LdrpBuildModuleBaseName(&NtoskrnlModuleObject.BaseName, &NtoskrnlModuleObject.FullName); - - NtHeader = RtlImageNtHeader((PVOID)KERNEL_BASE); - NtoskrnlModuleObject.Image.PE.FileHeader = &NtHeader->FileHeader; - NtoskrnlModuleObject.Image.PE.OptionalHeader = &NtHeader->OptionalHeader; - NtoskrnlModuleObject.Image.PE.SectionList = IMAGE_FIRST_SECTION(NtHeader); - NtoskrnlModuleObject.EntryPoint = (PVOID) ((ULONG_PTR) NtoskrnlModuleObject.Base + NtHeader->OptionalHeader.AddressOfEntryPoint); - DPRINT("ModuleObject:%08x entrypoint at %x\n", &NtoskrnlModuleObject, NtoskrnlModuleObject.EntryPoint); - NtoskrnlModuleObject.Length = NtoskrnlModuleObject.Image.PE.OptionalHeader->SizeOfImage; - NtoskrnlModuleObject.TextSection = &NtoskrnlTextSection; - - InsertTailList(&ModuleListHead, - &NtoskrnlModuleObject.ListEntry); - - /* Initialize ModuleObject for HAL */ - RtlZeroMemory(&HalModuleObject, sizeof(MODULE_OBJECT)); - HalModuleObject.Base = (PVOID) LdrHalBase; - HalModuleObject.Flags = MODULE_FLAG_PE; - - RtlInitUnicodeString(&HalModuleObject.FullName, HAL_MODULE_NAME); - LdrpBuildModuleBaseName(&HalModuleObject.BaseName, &HalModuleObject.FullName); - - NtHeader = RtlImageNtHeader((PVOID)LdrHalBase); - HalModuleObject.Image.PE.FileHeader = &NtHeader->FileHeader; - HalModuleObject.Image.PE.OptionalHeader = &NtHeader->OptionalHeader; - HalModuleObject.Image.PE.SectionList = IMAGE_FIRST_SECTION(NtHeader); - HalModuleObject.EntryPoint = (PVOID) ((ULONG_PTR) HalModuleObject.Base + NtHeader->OptionalHeader.AddressOfEntryPoint); - DPRINT("ModuleObject:%08x entrypoint at %x\n", &HalModuleObject, HalModuleObject.EntryPoint); - HalModuleObject.Length = HalModuleObject.Image.PE.OptionalHeader->SizeOfImage; - HalModuleObject.TextSection = &LdrHalTextSection; - - InsertTailList(&ModuleListHead, - &HalModuleObject.ListEntry); + PIMAGE_NT_HEADERS NtHeader; + + /* Initialize the module list and spinlock */ + InitializeListHead(&ModuleListHead); + KeInitializeSpinLock(&ModuleListLock); + + /* Initialize ModuleObject for NTOSKRNL */ + RtlZeroMemory(&NtoskrnlModuleObject, sizeof(LDR_DATA_TABLE_ENTRY)); + NtoskrnlModuleObject.DllBase = (PVOID) KERNEL_BASE; + RtlInitUnicodeString(&NtoskrnlModuleObject.FullDllName, KERNEL_MODULE_NAME); + LdrpBuildModuleBaseName(&NtoskrnlModuleObject.BaseDllName, &NtoskrnlModuleObject.FullDllName); + + NtHeader = RtlImageNtHeader((PVOID)KERNEL_BASE); + NtoskrnlModuleObject.EntryPoint = (PVOID) ((ULONG_PTR) NtoskrnlModuleObject.DllBase + NtHeader->OptionalHeader.AddressOfEntryPoint); + DPRINT("ModuleObject:%08x entrypoint at %x\n", &NtoskrnlModuleObject, NtoskrnlModuleObject.EntryPoint); + NtoskrnlModuleObject.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage; + + InsertTailList(&ModuleListHead, &NtoskrnlModuleObject.InLoadOrderModuleList); + + /* Initialize ModuleObject for HAL */ + RtlZeroMemory(&HalModuleObject, sizeof(LDR_DATA_TABLE_ENTRY)); + HalModuleObject.DllBase = (PVOID) LdrHalBase; + + RtlInitUnicodeString(&HalModuleObject.FullDllName, HAL_MODULE_NAME); + LdrpBuildModuleBaseName(&HalModuleObject.BaseDllName, &HalModuleObject.FullDllName); + + NtHeader = RtlImageNtHeader((PVOID)LdrHalBase); + HalModuleObject.EntryPoint = (PVOID) ((ULONG_PTR) HalModuleObject.DllBase + NtHeader->OptionalHeader.AddressOfEntryPoint); + DPRINT("ModuleObject:%08x entrypoint at %x\n", &HalModuleObject, HalModuleObject.EntryPoint); + HalModuleObject.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage; + + InsertTailList(&ModuleListHead, &HalModuleObject.InLoadOrderModuleList); } NTSTATUS -LdrpLoadImage(PUNICODE_STRING DriverName, - PVOID *ModuleBase, - PVOID *SectionPointer, - PVOID *EntryPoint, - PVOID *ExportSectionPointer) +NTAPI +LdrpLoadImage ( + PUNICODE_STRING DriverName, + PVOID *ModuleBase, + PVOID *SectionPointer, + PVOID *EntryPoint, + PVOID *ExportSectionPointer ) { - PMODULE_OBJECT ModuleObject; - NTSTATUS Status; + PLDR_DATA_TABLE_ENTRY ModuleObject; + NTSTATUS Status; - ModuleObject = LdrGetModuleObject(DriverName); - if (ModuleObject == NULL) + ModuleObject = LdrGetModuleObject(DriverName); + if (ModuleObject == NULL) { - Status = LdrLoadModule(DriverName, &ModuleObject); - if (!NT_SUCCESS(Status)) - { - return(Status); - } + Status = LdrLoadModule(DriverName, &ModuleObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } } - if (ModuleBase) - *ModuleBase = ModuleObject->Base; + if (ModuleBase) + *ModuleBase = ModuleObject->DllBase; -// if (SectionPointer) -// *SectionPointer = ModuleObject-> + if (SectionPointer) + *SectionPointer = ModuleObject; - if (EntryPoint) - *EntryPoint = ModuleObject->EntryPoint; + if (EntryPoint) + *EntryPoint = ModuleObject->EntryPoint; -// if (ExportSectionPointer) -// *ExportSectionPointer = ModuleObject-> + //if (ExportSectionPointer) + // *ExportSectionPointer = ModuleObject-> - return(STATUS_SUCCESS); + return(STATUS_SUCCESS); } NTSTATUS -LdrpUnloadImage(PVOID ModuleBase) +NTAPI +LdrpUnloadImage ( PVOID ModuleBase ) { - return(STATUS_NOT_IMPLEMENTED); + return(STATUS_NOT_IMPLEMENTED); } NTSTATUS -LdrpLoadAndCallImage(PUNICODE_STRING ModuleName) +NTAPI +LdrpLoadAndCallImage ( PUNICODE_STRING ModuleName ) { - PDRIVER_INITIALIZE DriverEntry; - PMODULE_OBJECT ModuleObject; - NTSTATUS Status; + PDRIVER_INITIALIZE DriverEntry; + PLDR_DATA_TABLE_ENTRY ModuleObject; + DRIVER_OBJECT DriverObject; + NTSTATUS Status; - ModuleObject = LdrGetModuleObject(ModuleName); - if (ModuleObject != NULL) + ModuleObject = LdrGetModuleObject(ModuleName); + if (ModuleObject != NULL) { - return(STATUS_IMAGE_ALREADY_LOADED); + return(STATUS_IMAGE_ALREADY_LOADED); } - Status = LdrLoadModule(ModuleName, &ModuleObject); - if (!NT_SUCCESS(Status)) + Status = LdrLoadModule(ModuleName, &ModuleObject); + if (!NT_SUCCESS(Status)) { - return(Status); + return(Status); } - DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint; + DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint; + + RtlZeroMemory(&DriverObject, sizeof(DriverObject)); +// DriverObject.DriverStart = ModuleObject->DllBase; - Status = DriverEntry(NULL, NULL); - if (!NT_SUCCESS(Status)) + Status = DriverEntry(&DriverObject, NULL); + if (!NT_SUCCESS(Status)) { - LdrUnloadModule(ModuleObject); + LdrUnloadModule(ModuleObject); } - return(Status); + return(Status); } NTSTATUS -LdrLoadModule(PUNICODE_STRING Filename, - PMODULE_OBJECT *ModuleObject) +NTAPI +LdrLoadModule( + PUNICODE_STRING Filename, + PLDR_DATA_TABLE_ENTRY *ModuleObject ) { - PVOID ModuleLoadBase; - NTSTATUS Status; - HANDLE FileHandle; - OBJECT_ATTRIBUTES ObjectAttributes; - PMODULE_OBJECT 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 = NtOpenFile(&FileHandle, - FILE_ALL_ACCESS, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - CHECKPOINT; - if (!NT_SUCCESS(Status)) + 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\n", Filename); - return(Status); + CPRINT("Could not open module file: %wZ (Status 0x%08lx)\n", Filename, Status); + return(Status); } - CHECKPOINT; - - /* Get the size of the file */ - Status = NtQueryInformationFile(FileHandle, - &IoStatusBlock, - &FileStdInfo, - sizeof(FileStdInfo), - FileStandardInformation); - if (!NT_SUCCESS(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); + CPRINT("Could not get file size\n"); + NtClose(FileHandle); + return(Status); } - CHECKPOINT; + CHECKPOINT; - /* Allocate nonpageable memory for driver */ - ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool, - FileStdInfo.EndOfFile.u.LowPart, - TAG_DRIVER_MEM); - if (ModuleLoadBase == NULL) + /* 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); + CPRINT("Could not allocate memory for module"); + NtClose(FileHandle); + return(STATUS_INSUFFICIENT_RESOURCES); } - CHECKPOINT; - - /* Load driver into memory chunk */ - Status = NtReadFile(FileHandle, - 0, 0, 0, - &IoStatusBlock, - ModuleLoadBase, - FileStdInfo.EndOfFile.u.LowPart, - 0, 0); - if (!NT_SUCCESS(Status)) + 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); + CPRINT("Could not read module file into memory"); + ExFreePool(ModuleLoadBase); + NtClose(FileHandle); + return(Status); } - CHECKPOINT; + CHECKPOINT; - NtClose(FileHandle); + ZwClose(FileHandle); - Status = LdrProcessModule(ModuleLoadBase, - Filename, - &Module); - if (!NT_SUCCESS(Status)) + Status = LdrProcessModule(ModuleLoadBase, + Filename, + &Module); + if (!NT_SUCCESS(Status)) { - CPRINT("Could not process module\n"); - ExFreePool(ModuleLoadBase); - return(Status); + CPRINT("Could not process module\n"); + ExFreePool(ModuleLoadBase); + return(Status); } - /* Cleanup */ - ExFreePool(ModuleLoadBase); + /* Cleanup */ + ExFreePool(ModuleLoadBase); - *ModuleObject = Module; + *ModuleObject = Module; - /* Hook for KDB on loading a driver. */ - KDB_LOADDRIVER_HOOK(Filename, Module); + /* Hook for KDB on loading a driver. */ + KDB_LOADDRIVER_HOOK(Filename, Module); - return(STATUS_SUCCESS); + return(STATUS_SUCCESS); } NTSTATUS -LdrUnloadModule(PMODULE_OBJECT ModuleObject) +NTAPI +LdrUnloadModule ( PLDR_DATA_TABLE_ENTRY ModuleObject ) { - KIRQL Irql; + KIRQL Irql; - /* Remove the module from the module list */ - KeAcquireSpinLock(&ModuleListLock,&Irql); - RemoveEntryList(&ModuleObject->ListEntry); - KeReleaseSpinLock(&ModuleListLock, Irql); + /* Remove the module from the module list */ + KeAcquireSpinLock(&ModuleListLock,&Irql); + RemoveEntryList(&ModuleObject->InLoadOrderModuleList); + KeReleaseSpinLock(&ModuleListLock, Irql); - /* Hook for KDB on unloading a driver. */ - KDB_UNLOADDRIVER_HOOK(ModuleObject); + /* Hook for KDB on unloading a driver. */ + KDB_UNLOADDRIVER_HOOK(ModuleObject); - /* Free text section */ - if (ModuleObject->TextSection != NULL) - { - ExFreePool(ModuleObject->TextSection->Name); - RemoveEntryList(&ModuleObject->TextSection->ListEntry); - ExFreePool(ModuleObject->TextSection); - ModuleObject->TextSection = NULL; - } + /* Free module section */ + // MmFreeSection(ModuleObject->DllBase); - /* Free module section */ -// MmFreeSection(ModuleObject->Base); + ExFreePool(ModuleObject->FullDllName.Buffer); + ExFreePool(ModuleObject); - ExFreePool(ModuleObject->FullName.Buffer); - ExFreePool(ModuleObject); - - return(STATUS_SUCCESS); + return(STATUS_SUCCESS); } NTSTATUS -LdrProcessModule(PVOID ModuleLoadBase, - PUNICODE_STRING ModuleName, - PMODULE_OBJECT *ModuleObject) +LdrProcessModule( + PVOID ModuleLoadBase, + PUNICODE_STRING ModuleName, + PLDR_DATA_TABLE_ENTRY *ModuleObject ) { - PIMAGE_DOS_HEADER PEDosHeader; + PIMAGE_DOS_HEADER PEDosHeader; - /* If MZ header exists */ - PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase; - if (PEDosHeader->e_magic == IMAGE_DOS_SIGNATURE && PEDosHeader->e_lfanew != 0L) + /* 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); + return LdrPEProcessModule(ModuleLoadBase, + ModuleName, + ModuleObject); } - CPRINT("Module wasn't PE\n"); - return STATUS_UNSUCCESSFUL; + CPRINT("Module wasn't PE\n"); + return STATUS_UNSUCCESSFUL; } NTSTATUS -LdrpQueryModuleInformation(PVOID Buffer, - ULONG Size, - PULONG ReqSize) +NTAPI +LdrpQueryModuleInformation ( + PVOID Buffer, + ULONG Size, + PULONG ReqSize ) { - PLIST_ENTRY current_entry; - PMODULE_OBJECT current; - ULONG ModuleCount = 0; - PSYSTEM_MODULE_INFORMATION Smi; - ANSI_STRING AnsiName; - PCHAR p; - KIRQL Irql; - - KeAcquireSpinLock(&ModuleListLock,&Irql); - - /* calculate required size */ - current_entry = ModuleListHead.Flink; - while (current_entry != (&ModuleListHead)) + PLIST_ENTRY current_entry; + PLDR_DATA_TABLE_ENTRY current; + ULONG ModuleCount = 0; + PSYSTEM_MODULE_INFORMATION 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_entry = current_entry->Flink; + ModuleCount++; + current = CONTAINING_RECORD(current_entry,LDR_DATA_TABLE_ENTRY,InLoadOrderModuleList); + tmpBufferSize += current->FullDllName.Length + sizeof(WCHAR) + sizeof(UNICODE_STRING); + current_entry = current_entry->Flink; } - *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+ - (ModuleCount - 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY); + *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+ + (ModuleCount - 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY); + + if (Size < *ReqSize) + { + KeReleaseSpinLock(&ModuleListLock, Irql); + return(STATUS_INFO_LENGTH_MISMATCH); + } - if (Size < *ReqSize) + /* allocate a temp buffer to store the module names */ + UnicodeName = ExAllocatePool(NonPagedPool, tmpBufferSize); + if (UnicodeName == NULL) { - KeReleaseSpinLock(&ModuleListLock, Irql); - return(STATUS_INFO_LENGTH_MISMATCH); + KeReleaseSpinLock(&ModuleListLock, Irql); + return STATUS_INSUFFICIENT_RESOURCES; } + tmpNameBuffer = (PWCHAR)((ULONG_PTR)UnicodeName + ModuleCount * sizeof(UNICODE_STRING)); - /* fill the buffer */ - memset(Buffer, '=', Size); + /* fill the buffer */ + memset(Buffer, '=', Size); - Smi = (PSYSTEM_MODULE_INFORMATION)Buffer; - Smi->Count = ModuleCount; + Smi = (PSYSTEM_MODULE_INFORMATION)Buffer; + Smi->Count = ModuleCount; - ModuleCount = 0; - current_entry = ModuleListHead.Flink; - while (current_entry != (&ModuleListHead)) + ModuleCount = 0; + current_entry = ModuleListHead.Flink; + while (current_entry != (&ModuleListHead)) { - current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry); - - Smi->Module[ModuleCount].Unknown1 = 0; /* Always 0 */ - Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */ - Smi->Module[ModuleCount].Base = current->Base; - Smi->Module[ModuleCount].Size = current->Length; - Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */ - Smi->Module[ModuleCount].Index = (USHORT)ModuleCount; - Smi->Module[ModuleCount].NameLength = 0; - Smi->Module[ModuleCount].LoadCount = 0; /* FIXME */ - - AnsiName.Length = 0; - AnsiName.MaximumLength = 256; - AnsiName.Buffer = Smi->Module[ModuleCount].ImageName; - RtlUnicodeStringToAnsiString(&AnsiName, - ¤t->FullName, - FALSE); - - p = strrchr(AnsiName.Buffer, '\\'); - if (p == NULL) - { - Smi->Module[ModuleCount].PathLength = 0; - } - else - { - p++; - Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer; - } - - ModuleCount++; - current_entry = current_entry->Flink; + current = CONTAINING_RECORD(current_entry,LDR_DATA_TABLE_ENTRY,InLoadOrderModuleList); + + Smi->Module[ModuleCount].Unknown1 = 0; /* Always 0 */ + Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */ + Smi->Module[ModuleCount].Base = current->DllBase; + Smi->Module[ModuleCount].Size = current->SizeOfImage; + Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */ + Smi->Module[ModuleCount].Index = (USHORT)ModuleCount; + Smi->Module[ModuleCount].NameLength = 0; + Smi->Module[ModuleCount].LoadCount = 0; /* FIXME */ + 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); + KeReleaseSpinLock(&ModuleListLock, Irql); + + for (ModuleCount = 0; ModuleCount < Smi->Count; ModuleCount++) + { + AnsiName.Length = 0; + AnsiName.MaximumLength = 255; + AnsiName.Buffer = Smi->Module[ModuleCount].ImageName; + RtlUnicodeStringToAnsiString(&AnsiName, &UnicodeName[ModuleCount], FALSE); + AnsiName.Buffer[AnsiName.Length] = 0; + Smi->Module[ModuleCount].NameLength = AnsiName.Length; + + p = strrchr(AnsiName.Buffer, '\\'); + if (p == NULL) + { + Smi->Module[ModuleCount].PathLength = 0; + } + else + { + p++; + Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer; + } + } - return(STATUS_SUCCESS); + ExFreePool(UnicodeName); + + return(STATUS_SUCCESS); } static VOID -LdrpBuildModuleBaseName(PUNICODE_STRING BaseName, - PUNICODE_STRING FullName) +LdrpBuildModuleBaseName ( + PUNICODE_STRING BaseName, + PUNICODE_STRING FullName ) { - PWCHAR p; + PWCHAR p; - DPRINT("LdrpBuildModuleBaseName()\n"); - DPRINT("FullName %wZ\n", FullName); + DPRINT("LdrpBuildModuleBaseName()\n"); + DPRINT("FullName %wZ\n", FullName); - p = wcsrchr(FullName->Buffer, L'\\'); - if (p == NULL) - { - p = FullName->Buffer; - } - else - { - p++; - } + p = wcsrchr(FullName->Buffer, L'\\'); + if (p == NULL) + { + p = FullName->Buffer; + } + else + { + p++; + } - DPRINT("p %S\n", p); + DPRINT("p %S\n", p); - RtlInitUnicodeString(BaseName, p); + RtlInitUnicodeString(BaseName, p); } static LONG -LdrpCompareModuleNames(IN PUNICODE_STRING String1, - IN PUNICODE_STRING String2) +LdrpCompareModuleNames ( + IN PUNICODE_STRING String1, + IN PUNICODE_STRING String2 ) { - ULONG len1, len2, i; - PWCHAR s1, s2, p; - WCHAR c1, c2; + ULONG len1, len2, i; + PWCHAR s1, s2, p; + WCHAR c1, c2; - if (String1 && String2) + if (String1 && String2) { - /* Search String1 for last path component */ - len1 = String1->Length / sizeof(WCHAR); - s1 = String1->Buffer; - for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++) - { - if (*p == L'\\') - { - if (i == String1->Length - sizeof(WCHAR)) - { - s1 = NULL; - len1 = 0; - } - else - { - s1 = p + 1; - len1 = (String1->Length - i) / sizeof(WCHAR); - } - } - } - - /* Search String2 for last path component */ - len2 = String2->Length / sizeof(WCHAR); - s2 = String2->Buffer; - for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++) - { - if (*p == L'\\') - { - if (i == String2->Length - sizeof(WCHAR)) - { - s2 = NULL; - len2 = 0; - } - else - { - s2 = p + 1; - len2 = (String2->Length - i) / sizeof(WCHAR); - } - } - } - - /* Compare last path components */ - if (s1 && s2) - { - while (1) - { - c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0; - c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0; - if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0)) - return(0); - if (!c1 || !c2 || c1 != c2) - return(c1 - c2); - } - } + /* Search String1 for last path component */ + len1 = String1->Length / sizeof(WCHAR); + s1 = String1->Buffer; + for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++) + { + if (*p == L'\\') + { + if (i == String1->Length - sizeof(WCHAR)) + { + s1 = NULL; + len1 = 0; + } + else + { + s1 = p + 1; + len1 = (String1->Length - i) / sizeof(WCHAR); + } + } + } + + /* Search String2 for last path component */ + len2 = String2->Length / sizeof(WCHAR); + s2 = String2->Buffer; + for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++) + { + if (*p == L'\\') + { + if (i == String2->Length - sizeof(WCHAR)) + { + s2 = NULL; + len2 = 0; + } + else + { + s2 = p + 1; + len2 = (String2->Length - i) / sizeof(WCHAR); + } + } + } + + /* Compare last path components */ + if (s1 && s2) + { + while (1) + { + c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0; + c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0; + if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0)) + return(0); + if (!c1 || !c2 || c1 != c2) + return(c1 - c2); + } + } } - return(0); + return(0); } -PMODULE_OBJECT -LdrGetModuleObject(PUNICODE_STRING ModuleName) +PLDR_DATA_TABLE_ENTRY +NTAPI +LdrGetModuleObject ( PUNICODE_STRING ModuleName ) { - PMODULE_OBJECT Module; - PLIST_ENTRY Entry; - KIRQL Irql; + PLDR_DATA_TABLE_ENTRY Module; + PLIST_ENTRY Entry; + KIRQL Irql; - DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName); + DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName); - KeAcquireSpinLock(&ModuleListLock,&Irql); + KeAcquireSpinLock(&ModuleListLock,&Irql); - Entry = ModuleListHead.Flink; - while (Entry != &ModuleListHead) + Entry = ModuleListHead.Flink; + while (Entry != &ModuleListHead) { - Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry); + Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList); - DPRINT("Comparing %wZ and %wZ\n", - &Module->BaseName, - ModuleName); + DPRINT("Comparing %wZ and %wZ\n", + &Module->BaseDllName, + ModuleName); - if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName)) - { - DPRINT("Module %wZ\n", &Module->BaseName); - KeReleaseSpinLock(&ModuleListLock, Irql); - return(Module); - } + if (!LdrpCompareModuleNames(&Module->BaseDllName, ModuleName)) + { + DPRINT("Module %wZ\n", &Module->BaseDllName); + KeReleaseSpinLock(&ModuleListLock, Irql); + return(Module); + } - Entry = Entry->Flink; + Entry = Entry->Flink; } - KeReleaseSpinLock(&ModuleListLock, Irql); + KeReleaseSpinLock(&ModuleListLock, Irql); - DPRINT("Could not find module '%wZ'\n", ModuleName); + DPRINT("Could not find module '%wZ'\n", ModuleName); - return(NULL); + return(NULL); } /* ---------------------------------------------- PE Module support */ static ULONG -LdrLookupPageProtection(PVOID PageStart, - PVOID DriverBase, - PIMAGE_FILE_HEADER PEFileHeader, - PIMAGE_SECTION_HEADER PESectionHeaders) +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_LNK_OTHER)) - { - 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; - } + 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, - PMODULE_OBJECT *ModuleObject) +LdrPEProcessModule( + PVOID ModuleLoadBase, + PUNICODE_STRING FileName, + PLDR_DATA_TABLE_ENTRY *ModuleObject ) { - unsigned int DriverSize, Idx; - DWORD CurrentSize; - PVOID DriverBase; - PIMAGE_DOS_HEADER PEDosHeader; - PIMAGE_NT_HEADERS PENtHeaders; - PIMAGE_SECTION_HEADER PESectionHeaders; - PMODULE_OBJECT CreatedModuleObject; - MODULE_TEXT_SECTION* ModuleTextSection; - NTSTATUS Status; - KIRQL Irql; - - DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase); - - /* Get header pointers */ - PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase; - PENtHeaders = RtlImageNtHeader(ModuleLoadBase); - PESectionHeaders = IMAGE_FIRST_SECTION(PENtHeaders); - CHECKPOINT; - - /* Check file magic numbers */ - if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE) + unsigned int DriverSize, Idx; + DWORD CurrentSize; + PVOID DriverBase; + PIMAGE_DOS_HEADER PEDosHeader; + PIMAGE_NT_HEADERS PENtHeaders; + PIMAGE_SECTION_HEADER PESectionHeaders; + PLDR_DATA_TABLE_ENTRY CreatedModuleObject; + NTSTATUS Status; + KIRQL Irql; + + 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; + CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic); + return STATUS_UNSUCCESSFUL; } - if (PEDosHeader->e_lfanew == 0) + if (PEDosHeader->e_lfanew == 0) { - CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew); - return STATUS_UNSUCCESSFUL; + CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew); + return STATUS_UNSUCCESSFUL; } - if (PENtHeaders->Signature != IMAGE_NT_SIGNATURE) + if (PENtHeaders->Signature != IMAGE_NT_SIGNATURE) { - CPRINT("Incorrect PE magic: %08x\n", PENtHeaders->Signature); - return STATUS_UNSUCCESSFUL; + CPRINT("Incorrect PE magic: %08x\n", PENtHeaders->Signature); + return STATUS_UNSUCCESSFUL; } - if (PENtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) + if (PENtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) { - CPRINT("Incorrect Architechture: %04x\n", PENtHeaders->FileHeader.Machine); - return STATUS_UNSUCCESSFUL; + CPRINT("Incorrect Architechture: %04x\n", PENtHeaders->FileHeader.Machine); + return STATUS_UNSUCCESSFUL; } - CHECKPOINT; + 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); - /* FIXME: if image is fixed-address load, then fail */ + /* 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); - /* FIXME: check/verify OS version number */ + /* 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); - DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n", - PENtHeaders->OptionalHeader.Magic, - PENtHeaders->OptionalHeader.MajorLinkerVersion, - PENtHeaders->OptionalHeader.MinorLinkerVersion); - DPRINT("Entry Point:%08lx\n", PENtHeaders->OptionalHeader.AddressOfEntryPoint); + /* Copy headers over */ + memcpy(DriverBase, ModuleLoadBase, PENtHeaders->OptionalHeader.SizeOfHeaders); - /* Determine the size of the module */ - DriverSize = 0; - for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++) - { - if (!(PESectionHeaders[Idx].Characteristics & IMAGE_SCN_TYPE_NOLOAD)) - { + /* Copy image sections into virtual section */ + for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++) + { 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) + /* 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 = LdrPEPerformRelocations(DriverBase, DriverSize); + if (!NT_SUCCESS(Status)) { - CPRINT("Failed to allocate a virtual section for driver\n"); - return STATUS_UNSUCCESSFUL; + // MmFreeSection(DriverBase); + return Status; } - DbgPrint("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 = LdrPEPerformRelocations(DriverBase, DriverSize); - if (!NT_SUCCESS(Status)) - { -// MmFreeSection(DriverBase); - return Status; - } - - /* Create the module */ - CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT)); - if (CreatedModuleObject == NULL) - { -// MmFreeSection(DriverBase); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT)); - - /* Initialize ModuleObject data */ - CreatedModuleObject->Base = DriverBase; - CreatedModuleObject->Flags = MODULE_FLAG_PE; - - CreatedModuleObject->FullName.Length = 0; - CreatedModuleObject->FullName.MaximumLength = FileName->Length + sizeof(UNICODE_NULL); - CreatedModuleObject->FullName.Buffer = ExAllocatePool(PagedPool, CreatedModuleObject->FullName.MaximumLength); - if (CreatedModuleObject->FullName.Buffer == NULL) - { - ExFreePool(CreatedModuleObject); -// MmFreeSection(DriverBase); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlCopyUnicodeString(&CreatedModuleObject->FullName, FileName); - LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName, - &CreatedModuleObject->FullName); - - CreatedModuleObject->EntryPoint = - (PVOID)((ULONG_PTR)DriverBase + - PENtHeaders->OptionalHeader.AddressOfEntryPoint); - CreatedModuleObject->Length = DriverSize; - DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint); - - CreatedModuleObject->Image.PE.FileHeader = - (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG)); - - DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader); - CreatedModuleObject->Image.PE.OptionalHeader = - (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) + - sizeof(IMAGE_FILE_HEADER)); - DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader); - CreatedModuleObject->Image.PE.SectionList = - (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) + - sizeof(IMAGE_FILE_HEADER) + CreatedModuleObject->Image.PE.FileHeader->SizeOfOptionalHeader); - DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList); - - /* Perform import fixups */ - Status = LdrPEFixupImports(CreatedModuleObject); - if (!NT_SUCCESS(Status)) - { -// MmFreeSection(DriverBase); - ExFreePool(CreatedModuleObject->FullName.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); + + /* 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); + 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 1 - /* - * FIXME: - * This driver modifies a string in the first page of the text section while initialising. - */ - if (0 == _wcsicmp(L"fireport.sys", FileName->Buffer)) - { - Protect = PAGE_EXECUTE_READWRITE; - } + /* + * FIXME: + * This driver modifies a string in the first page of the text section while initialising. + */ + if (0 == _wcsicmp(L"fireport.sys", FileName->Buffer)) + { + Protect = PAGE_EXECUTE_READWRITE; + } #endif - if (PageAddress < 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_LNK_OTHER)) - { - 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 < DriverBase + DriverSize) - { - MmSetPageProtect(NULL, PageAddress, Protect); - } - PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE); - } - if (PageAddress < (PVOID)((ULONG_PTR)BaseAddress + Length) && - PageAddress < DriverBase + DriverSize) - { - Protect = LdrLookupPageProtection(PageAddress, DriverBase, &PENtHeaders->FileHeader, PESectionHeaders); - MmSetPageProtect(NULL, PageAddress, Protect); - } - } - - /* Insert module */ - KeAcquireSpinLock(&ModuleListLock, &Irql); - InsertTailList(&ModuleListHead, - &CreatedModuleObject->ListEntry); - KeReleaseSpinLock(&ModuleListLock, Irql); - - - ModuleTextSection = ExAllocatePool(NonPagedPool, - sizeof(MODULE_TEXT_SECTION)); - ASSERT(ModuleTextSection); - RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION)); - ModuleTextSection->Base = (ULONG)DriverBase; - ModuleTextSection->Length = DriverSize; - ModuleTextSection->Name = ExAllocatePool(NonPagedPool, - (CreatedModuleObject->BaseName.Length + 1) * sizeof(WCHAR)); - RtlCopyMemory(ModuleTextSection->Name, - CreatedModuleObject->BaseName.Buffer, - CreatedModuleObject->BaseName.Length); - ModuleTextSection->Name[CreatedModuleObject->BaseName.Length / sizeof(WCHAR)] = 0; - ModuleTextSection->OptionalHeader = - CreatedModuleObject->Image.PE.OptionalHeader; - InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry); - - CreatedModuleObject->TextSection = ModuleTextSection; - - *ModuleObject = CreatedModuleObject; - - DPRINT("Loading Module %wZ...\n", FileName); - - if (KdDebuggerEnabled && (KdDebugState & KD_DEBUG_GDB)) - { - DPRINT("Module %wZ loaded at 0x%.08x.\n", - FileName, CreatedModuleObject->Base); + 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); + } } - return STATUS_SUCCESS; + /* Insert module */ + KeAcquireSpinLock(&ModuleListLock, &Irql); + InsertTailList(&ModuleListHead, + &CreatedModuleObject->InLoadOrderModuleList); + 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; } -PVOID INIT_FUNCTION -LdrSafePEProcessModule(PVOID ModuleLoadBase, - PVOID DriverBase, - PVOID ImportModuleBase, - PULONG DriverSize) +PVOID +INIT_FUNCTION +NTAPI +LdrSafePEProcessModule ( + PVOID ModuleLoadBase, + PVOID DriverBase, + PVOID ImportModuleBase, + PULONG DriverSize) { - unsigned int Idx; - ULONG CurrentSize; - PIMAGE_DOS_HEADER PEDosHeader; - PIMAGE_NT_HEADERS PENtHeaders; - PIMAGE_SECTION_HEADER PESectionHeaders; - NTSTATUS Status; - - ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase); - - /* 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) + unsigned int Idx; + ULONG CurrentSize; + PIMAGE_DOS_HEADER PEDosHeader; + PIMAGE_NT_HEADERS PENtHeaders; + PIMAGE_SECTION_HEADER PESectionHeaders; + NTSTATUS Status; + + ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase); + + /* 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) { - return NULL; + return NULL; } - if (PEDosHeader->e_lfanew == 0) + if (PEDosHeader->e_lfanew == 0) { - return NULL; + return NULL; } - if (PENtHeaders->Signature != IMAGE_NT_SIGNATURE) + if (PENtHeaders->Signature != IMAGE_NT_SIGNATURE) { - return NULL; + return NULL; } - if (PENtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) + if (PENtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) { - return NULL; + return NULL; } - ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n", - PENtHeaders->OptionalHeader.Magic, - PENtHeaders->OptionalHeader.MajorLinkerVersion, - PENtHeaders->OptionalHeader.MinorLinkerVersion); - ps("Entry Point:%08lx\n", PENtHeaders->OptionalHeader.AddressOfEntryPoint); + ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n", + PENtHeaders->OptionalHeader.Magic, + PENtHeaders->OptionalHeader.MajorLinkerVersion, + PENtHeaders->OptionalHeader.MinorLinkerVersion); + ps("Entry Point:%08lx\n", PENtHeaders->OptionalHeader.AddressOfEntryPoint); - /* Determine the size of the module */ - *DriverSize = PENtHeaders->OptionalHeader.SizeOfImage; - ps("DriverSize %x\n",*DriverSize); + /* Determine the size of the module */ + *DriverSize = PENtHeaders->OptionalHeader.SizeOfImage; + ps("DriverSize %x\n",*DriverSize); - /* Copy headers over */ - if (DriverBase != ModuleLoadBase) + /* Copy headers over */ + if (DriverBase != ModuleLoadBase) { - memcpy(DriverBase, ModuleLoadBase, PENtHeaders->OptionalHeader.SizeOfHeaders); + memcpy(DriverBase, ModuleLoadBase, PENtHeaders->OptionalHeader.SizeOfHeaders); } - ps("Hdr: 0x%X\n", PENtHeaders); - ps("Hdr->SizeOfHeaders: 0x%X\n", PENtHeaders->OptionalHeader.SizeOfHeaders); - ps("FileHdr->NumberOfSections: 0x%X\n", PENtHeaders->FileHeader.NumberOfSections); + ps("Hdr: 0x%X\n", PENtHeaders); + ps("Hdr->SizeOfHeaders: 0x%X\n", PENtHeaders->OptionalHeader.SizeOfHeaders); + ps("FileHdr->NumberOfSections: 0x%X\n", PENtHeaders->FileHeader.NumberOfSections); - /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same - address as it is mapped */ - if (DriverBase != ModuleLoadBase) + /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same + address as it is mapped */ + if (DriverBase != ModuleLoadBase) { - CurrentSize = 0; + CurrentSize = 0; - /* Copy image sections into virtual section */ - for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++) + /* Copy image sections into virtual section */ + for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++) + { + PIMAGE_SECTION_HEADER Section = &PESectionHeaders[Idx]; + // Copy current section into current offset of virtual section + if (Section->SizeOfRawData) + { + // ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n", + // PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase); + memcpy(Section->VirtualAddress + (char*)DriverBase, + Section->PointerToRawData + (char*)ModuleLoadBase, + Section->Misc.VirtualSize > Section->SizeOfRawData ? Section->SizeOfRawData : Section->Misc.VirtualSize); + } + if (Section->SizeOfRawData < Section->Misc.VirtualSize) + { + memset(Section->VirtualAddress + Section->SizeOfRawData + (char*)DriverBase, + 0, + Section->Misc.VirtualSize - Section->SizeOfRawData); + } + CurrentSize += ROUND_UP(Section->Misc.VirtualSize, + PENtHeaders->OptionalHeader.SectionAlignment); + } + + /* Perform relocation fixups */ + Status = LdrPEPerformRelocations(DriverBase, *DriverSize); + if (!NT_SUCCESS(Status)) + { + return NULL; + } + } + + /* Perform import fixups */ + Status = LdrPEFixupImports(DriverBase == ModuleLoadBase ? &NtoskrnlModuleObject : &HalModuleObject); + if (!NT_SUCCESS(Status)) + { + return NULL; + } + + /* Set the page protection for the virtual sections */ + MmSetPageProtect(NULL, DriverBase, PAGE_READONLY); + 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); + + if (Characteristics & IMAGE_SCN_MEM_EXECUTE) { - PIMAGE_SECTION_HEADER Section = &PESectionHeaders[Idx]; - // Copy current section into current offset of virtual section - if (Section->SizeOfRawData) + if (Characteristics & IMAGE_SCN_MEM_WRITE) { -// ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n", -// PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase); - memcpy(Section->VirtualAddress + (char*)DriverBase, - Section->PointerToRawData + (char*)ModuleLoadBase, - Section->Misc.VirtualSize > Section->SizeOfRawData ? Section->SizeOfRawData : Section->Misc.VirtualSize); + Protect = PAGE_EXECUTE_READWRITE; } - if (Section->SizeOfRawData < Section->Misc.VirtualSize) + else { - memset(Section->VirtualAddress + Section->SizeOfRawData + (char*)DriverBase, - 0, - Section->Misc.VirtualSize - Section->SizeOfRawData); + Protect = PAGE_EXECUTE_READ; } - CurrentSize += ROUND_UP(Section->Misc.VirtualSize, - PENtHeaders->OptionalHeader.SectionAlignment); + } + else if (Characteristics & IMAGE_SCN_MEM_WRITE) + { + Protect = PAGE_READWRITE; + } + else + { + Protect = PAGE_READONLY; + } + while ((ULONG_PTR)PageAddress < (ULONG_PTR)BaseAddress + Length) + { + MmSetPageProtect(NULL, PageAddress, Protect); + PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE); + } + if (DriverBase == ModuleLoadBase && + Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) + { + /* For ntoskrnl, we must stop after the bss section */ + break; } - /* Perform relocation fixups */ - Status = LdrPEPerformRelocations(DriverBase, *DriverSize); - if (!NT_SUCCESS(Status)) - { - return NULL; - } - } - - /* Perform import fixups */ - Status = LdrPEFixupImports(DriverBase == ModuleLoadBase ? &NtoskrnlModuleObject : &HalModuleObject); - if (!NT_SUCCESS(Status)) - { - return NULL; - } - - /* Set the page protection for the virtual sections */ - MmSetPageProtect(NULL, DriverBase, PAGE_READONLY); - 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); - - if (Characteristics & IMAGE_SCN_MEM_EXECUTE) - { - if (Characteristics & IMAGE_SCN_MEM_WRITE) - { - Protect = PAGE_EXECUTE_READWRITE; - } - else - { - Protect = PAGE_EXECUTE_READ; - } - } - else if (Characteristics & IMAGE_SCN_MEM_WRITE) - { - Protect = PAGE_READWRITE; - } - else - { - Protect = PAGE_READONLY; - } - while ((ULONG_PTR)PageAddress < (ULONG_PTR)BaseAddress + Length) - { - MmSetPageProtect(NULL, PageAddress, Protect); - PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE); - } - if (DriverBase == ModuleLoadBase && - Characteristics & IMAGE_SCN_LNK_OTHER) - { - /* For ntoskrnl, we must stop after the bss section */ - break; - } - - } - - return DriverBase; + } + + return DriverBase; } static PVOID -LdrPEFixupForward(PCHAR ForwardName) +LdrPEFixupForward ( PCHAR ForwardName ) { - CHAR NameBuffer[128]; - UNICODE_STRING ModuleName; - PCHAR p; - PMODULE_OBJECT ModuleObject; + CHAR NameBuffer[128]; + UNICODE_STRING ModuleName; + PCHAR p; + PLDR_DATA_TABLE_ENTRY ModuleObject; - DPRINT("LdrPEFixupForward (%s)\n", ForwardName); + DPRINT("LdrPEFixupForward (%s)\n", ForwardName); - strcpy(NameBuffer, ForwardName); - p = strchr(NameBuffer, '.'); - if (p == NULL) - { - return NULL; - } + strcpy(NameBuffer, ForwardName); + p = strchr(NameBuffer, '.'); + if (p == NULL) + { + return NULL; + } - *p = 0; + *p = 0; - DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1); + DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1); - RtlCreateUnicodeStringFromAsciiz(&ModuleName, - NameBuffer); - ModuleObject = LdrGetModuleObject(&ModuleName); - RtlFreeUnicodeString(&ModuleName); + RtlCreateUnicodeStringFromAsciiz(&ModuleName, + NameBuffer); + ModuleObject = LdrGetModuleObject(&ModuleName); + RtlFreeUnicodeString(&ModuleName); - DPRINT("ModuleObject: %p\n", ModuleObject); + DPRINT("ModuleObject: %p\n", ModuleObject); - if (ModuleObject == NULL) - { - CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer); - return NULL; - } - return LdrPEGetExportByName(ModuleObject->Base, (PUCHAR)(p+1), 0xffff); + if (ModuleObject == NULL) + { + CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer); + return NULL; + } + return LdrPEGetExportByName(ModuleObject->DllBase, (PUCHAR)(p+1), 0xffff); } static NTSTATUS -LdrPEPerformRelocations(PVOID DriverBase, - ULONG DriverSize) +LdrPEPerformRelocations ( + PVOID DriverBase, + ULONG DriverSize) { - PIMAGE_NT_HEADERS NtHeaders; - PIMAGE_DATA_DIRECTORY RelocationDDir; - PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd; - ULONG Count, i; - PVOID Address, MaxAddress; - PUSHORT TypeOffset; - ULONG_PTR Delta; - SHORT Offset; - USHORT Type; - PUSHORT ShortPtr; - PULONG LongPtr; - - NtHeaders = RtlImageNtHeader(DriverBase); - - if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) - { - return STATUS_UNSUCCESSFUL; - } - - RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; - - if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0) - { - return STATUS_SUCCESS; - } - - Delta = (ULONG_PTR)DriverBase - NtHeaders->OptionalHeader.ImageBase; - RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)DriverBase + RelocationDDir->VirtualAddress); - RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size); - MaxAddress = DriverBase + DriverSize; - - while (RelocationDir < RelocationEnd && - RelocationDir->SizeOfBlock > 0) - { - Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT); - Address = DriverBase + RelocationDir->VirtualAddress; - TypeOffset = (PUSHORT)(RelocationDir + 1); - - for (i = 0; i < Count; i++) - { - Offset = *TypeOffset & 0xFFF; - Type = *TypeOffset >> 12; - ShortPtr = (PUSHORT)(Address + Offset); - - /* Don't relocate after the end of the loaded driver */ - if ((PVOID)ShortPtr >= MaxAddress) - { - break; - } - - /* - * Don't relocate within the relocation section itself. - * GCC/LD generates sometimes relocation records for the relecotion section. - * This is a bug in GCC/LD. - */ - if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir || - (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd) - { - switch (Type) + PIMAGE_NT_HEADERS NtHeaders; + PIMAGE_DATA_DIRECTORY RelocationDDir; + PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd; + ULONG Count, i; + PVOID Address, MaxAddress; + PUSHORT TypeOffset; + ULONG_PTR Delta; + SHORT Offset; + USHORT Type; + PUSHORT ShortPtr; + PULONG LongPtr; + + NtHeaders = RtlImageNtHeader(DriverBase); + + if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) + { + return STATUS_UNSUCCESSFUL; + } + + RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + + if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0) + { + return STATUS_SUCCESS; + } + + Delta = (ULONG_PTR)DriverBase - NtHeaders->OptionalHeader.ImageBase; + RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)DriverBase + RelocationDDir->VirtualAddress); + RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size); + MaxAddress = RVA(DriverBase, DriverSize); + + while (RelocationDir < RelocationEnd && + RelocationDir->SizeOfBlock > 0) + { + Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT); + Address = RVA(DriverBase, RelocationDir->VirtualAddress); + TypeOffset = (PUSHORT)(RelocationDir + 1); + + for (i = 0; i < Count; i++) + { + Offset = *TypeOffset & 0xFFF; + Type = *TypeOffset >> 12; + ShortPtr = (PUSHORT)(RVA(Address, Offset)); + + /* Don't relocate after the end of the loaded driver */ + if ((PVOID)ShortPtr >= MaxAddress) + { + break; + } + + /* + * Don't relocate within the relocation section itself. + * GCC/LD generates sometimes relocation records for the relocation section. + * This is a bug in GCC/LD. + */ + if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir || + (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd) { - case IMAGE_REL_BASED_ABSOLUTE: - break; - - case IMAGE_REL_BASED_HIGH: - *ShortPtr += HIWORD(Delta); - break; - - case IMAGE_REL_BASED_LOW: - *ShortPtr += LOWORD(Delta); - break; - - case IMAGE_REL_BASED_HIGHLOW: - LongPtr = (PULONG)ShortPtr; - *LongPtr += Delta; - break; - - case IMAGE_REL_BASED_HIGHADJ: - case IMAGE_REL_BASED_MIPS_JMPADDR: - default: - DPRINT1("Unknown/unsupported fixup type %hu.\n", Type); - DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset); - return STATUS_UNSUCCESSFUL; + switch (Type) + { + case IMAGE_REL_BASED_ABSOLUTE: + break; + + case IMAGE_REL_BASED_HIGH: + *ShortPtr += HIWORD(Delta); + break; + + case IMAGE_REL_BASED_LOW: + *ShortPtr += LOWORD(Delta); + break; + + case IMAGE_REL_BASED_HIGHLOW: + LongPtr = (PULONG)ShortPtr; + *LongPtr += Delta; + break; + + case IMAGE_REL_BASED_HIGHADJ: + case IMAGE_REL_BASED_MIPS_JMPADDR: + default: + DPRINT1("Unknown/unsupported fixup type %hu.\n", Type); + DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset); + return STATUS_UNSUCCESSFUL; + } } - } - TypeOffset++; - } - RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock); - } + TypeOffset++; + } + RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock); + } - return STATUS_SUCCESS; + return STATUS_SUCCESS; } +#ifndef PATH_MAX +#define PATH_MAX 260 +#endif static NTSTATUS -LdrPEGetOrLoadModule(PMODULE_OBJECT Module, - PCHAR ImportedName, - PMODULE_OBJECT* ImportedModule) +LdrPEGetOrLoadModule ( + PLDR_DATA_TABLE_ENTRY Module, + PCHAR ImportedName, + PLDR_DATA_TABLE_ENTRY* ImportedModule) { - UNICODE_STRING DriverName; - UNICODE_STRING NameString; - WCHAR NameBuffer[PATH_MAX]; - NTSTATUS Status = STATUS_SUCCESS; - - if (0 == _stricmp(ImportedName, "ntoskrnl") || - 0 == _stricmp(ImportedName, "ntoskrnl.exe")) - { - *ImportedModule = &NtoskrnlModuleObject; - return STATUS_SUCCESS; - } - - if (0 == _stricmp(ImportedName, "hal") || - 0 == _stricmp(ImportedName, "hal.dll")) - { - *ImportedModule = &HalModuleObject; - return STATUS_SUCCESS; - } - - RtlCreateUnicodeStringFromAsciiz (&DriverName, ImportedName); - DPRINT("Import module: %wZ\n", &DriverName); - - *ImportedModule = LdrGetModuleObject(&DriverName); - if (*ImportedModule == NULL) - { - PWCHAR PathEnd; - ULONG PathLength; - - PathEnd = wcsrchr(Module->FullName.Buffer, L'\\'); - if (NULL != PathEnd) - { - PathLength = (PathEnd - Module->FullName.Buffer + 1) * sizeof(WCHAR); - RtlCopyMemory(NameBuffer, Module->FullName.Buffer, PathLength); - RtlCopyMemory(NameBuffer + (PathLength / sizeof(WCHAR)), DriverName.Buffer, DriverName.Length); - NameString.Buffer = NameBuffer; - NameString.MaximumLength = NameString.Length = PathLength + DriverName.Length; - - /* NULL-terminate */ - NameString.MaximumLength++; - NameBuffer[NameString.Length / sizeof(WCHAR)] = 0; - - Status = LdrLoadModule(&NameString, ImportedModule); - } - else - { - DPRINT("Module '%wZ' not loaded yet\n", &DriverName); - wcscpy(NameBuffer, L"\\SystemRoot\\system32\\drivers\\"); - wcsncat(NameBuffer, DriverName.Buffer, DriverName.Length / sizeof(WCHAR)); - RtlInitUnicodeString(&NameString, NameBuffer); - Status = LdrLoadModule(&NameString, ImportedModule); - } - if (!NT_SUCCESS(Status)) - { - wcscpy(NameBuffer, L"\\SystemRoot\\system32\\"); - wcsncat(NameBuffer, DriverName.Buffer, DriverName.Length / sizeof(WCHAR)); - RtlInitUnicodeString(&NameString, NameBuffer); - Status = LdrLoadModule(&NameString, ImportedModule); + UNICODE_STRING DriverName; + UNICODE_STRING NameString; + WCHAR NameBuffer[PATH_MAX]; + NTSTATUS Status = STATUS_SUCCESS; + + if (0 == _stricmp(ImportedName, "ntoskrnl") || + 0 == _stricmp(ImportedName, "ntoskrnl.exe")) + { + *ImportedModule = &NtoskrnlModuleObject; + return STATUS_SUCCESS; + } + + if (0 == _stricmp(ImportedName, "hal") || + 0 == _stricmp(ImportedName, "hal.dll")) + { + *ImportedModule = &HalModuleObject; + return STATUS_SUCCESS; + } + + RtlCreateUnicodeStringFromAsciiz (&DriverName, ImportedName); + DPRINT("Import module: %wZ\n", &DriverName); + + *ImportedModule = LdrGetModuleObject(&DriverName); + if (*ImportedModule == NULL) + { + PWCHAR PathEnd; + ULONG PathLength; + + PathEnd = wcsrchr(Module->FullDllName.Buffer, L'\\'); + if (NULL != PathEnd) + { + PathLength = (PathEnd - Module->FullDllName.Buffer + 1) * sizeof(WCHAR); + RtlCopyMemory(NameBuffer, Module->FullDllName.Buffer, PathLength); + RtlCopyMemory(NameBuffer + (PathLength / sizeof(WCHAR)), DriverName.Buffer, DriverName.Length); + NameString.Buffer = NameBuffer; + NameString.MaximumLength = NameString.Length = PathLength + DriverName.Length; + + /* NULL-terminate */ + NameString.MaximumLength++; + NameBuffer[NameString.Length / sizeof(WCHAR)] = 0; + + Status = LdrLoadModule(&NameString, ImportedModule); + } + else + { + DPRINT("Module '%wZ' not loaded yet\n", &DriverName); + wcscpy(NameBuffer, L"\\SystemRoot\\system32\\drivers\\"); + wcsncat(NameBuffer, DriverName.Buffer, DriverName.Length / sizeof(WCHAR)); + RtlInitUnicodeString(&NameString, NameBuffer); + Status = LdrLoadModule(&NameString, ImportedModule); + } if (!NT_SUCCESS(Status)) { - DPRINT1("Unknown import module: %wZ (Status %lx)\n", &DriverName, Status); + wcscpy(NameBuffer, L"\\SystemRoot\\system32\\"); + wcsncat(NameBuffer, DriverName.Buffer, DriverName.Length / sizeof(WCHAR)); + RtlInitUnicodeString(&NameString, NameBuffer); + Status = LdrLoadModule(&NameString, ImportedModule); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Unknown import module: %wZ (Status %lx)\n", &DriverName, Status); + } } - } - } - RtlFreeUnicodeString(&DriverName); - return Status; + } + RtlFreeUnicodeString(&DriverName); + return Status; } static PVOID -LdrPEGetExportByName(PVOID BaseAddress, - PUCHAR SymbolName, - WORD Hint) +LdrPEGetExportByName ( + PVOID BaseAddress, + PUCHAR SymbolName, + WORD Hint ) { - PIMAGE_EXPORT_DIRECTORY ExportDir; - PDWORD * ExFunctions; - PDWORD * ExNames; - USHORT * ExOrdinals; - ULONG i; - PVOID ExName; - ULONG Ordinal; - PVOID Function; - LONG minn, maxn; - ULONG ExportDirSize; - - DPRINT("LdrPEGetExportByName %x %s %hu\n", BaseAddress, SymbolName, Hint); - - ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(BaseAddress, - TRUE, - IMAGE_DIRECTORY_ENTRY_EXPORT, - &ExportDirSize); - if (ExportDir == NULL) - { - DPRINT1("LdrPEGetExportByName(): no export directory!\n"); - return NULL; - } - - - /* The symbol names may be missing entirely */ - if (ExportDir->AddressOfNames == 0) - { - DPRINT("LdrPEGetExportByName(): symbol names missing entirely\n"); - return NULL; - } - - /* + PIMAGE_EXPORT_DIRECTORY ExportDir; + PDWORD * ExFunctions; + PDWORD * ExNames; + USHORT * ExOrdinals; + PVOID ExName; + ULONG Ordinal; + PVOID Function; + LONG minn, maxn, mid, res; + ULONG ExportDirSize; + + DPRINT("LdrPEGetExportByName %x %s %hu\n", BaseAddress, SymbolName, Hint); + + ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(BaseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportDirSize); + if (ExportDir == NULL) + { + DPRINT1("LdrPEGetExportByName(): no export directory!\n"); + return NULL; + } + + + /* The symbol names may be missing entirely */ + if (ExportDir->AddressOfNames == 0) + { + DPRINT("LdrPEGetExportByName(): symbol names missing entirely\n"); + return NULL; + } + + /* * Get header pointers */ - ExNames = (PDWORD *)RVA(BaseAddress, ExportDir->AddressOfNames); - ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals); - ExFunctions = (PDWORD *)RVA(BaseAddress, ExportDir->AddressOfFunctions); + ExNames = (PDWORD *)RVA(BaseAddress, ExportDir->AddressOfNames); + ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals); + ExFunctions = (PDWORD *)RVA(BaseAddress, ExportDir->AddressOfFunctions); - /* + /* * Check the hint first */ - if (Hint < ExportDir->NumberOfNames) - { - ExName = RVA(BaseAddress, ExNames[Hint]); - if (strcmp(ExName, (PCHAR)SymbolName) == 0) - { - Ordinal = ExOrdinals[Hint]; - Function = RVA(BaseAddress, ExFunctions[Ordinal]); - if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && - (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) - { - DPRINT("Forward: %s\n", (PCHAR)Function); - Function = LdrPEFixupForward((PCHAR)Function); - if (Function == NULL) + if (Hint < ExportDir->NumberOfNames) + { + ExName = RVA(BaseAddress, ExNames[Hint]); + if (strcmp(ExName, (PCHAR)SymbolName) == 0) + { + Ordinal = ExOrdinals[Hint]; + Function = RVA(BaseAddress, ExFunctions[Ordinal]); + if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && + (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) { - DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName); + DPRINT("Forward: %s\n", (PCHAR)Function); + Function = LdrPEFixupForward((PCHAR)Function); + if (Function == NULL) + { + DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName); + } + return Function; } - return Function; - } - if (Function != NULL) - { - return Function; - } - } - } - - /* - * Try a binary search first - */ - minn = 0; - maxn = ExportDir->NumberOfNames - 1; - while (minn <= maxn) - { - LONG mid; - LONG res; - - mid = (minn + maxn) / 2; - - ExName = RVA(BaseAddress, ExNames[mid]); - res = strcmp(ExName, (PCHAR)SymbolName); - if (res == 0) - { - Ordinal = ExOrdinals[mid]; - Function = RVA(BaseAddress, ExFunctions[Ordinal]); - if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && - (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) - { - DPRINT("Forward: %s\n", (PCHAR)Function); - Function = LdrPEFixupForward((PCHAR)Function); - if (Function == NULL) + if (Function != NULL) { - DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName); + return Function; } - return Function; - } - if (Function != NULL) - { - return Function; - } - } - else if (minn == maxn) - { - DPRINT("LdrPEGetExportByName(): binary search failed\n"); - break; - } - else if (res > 0) - { - maxn = mid - 1; - } - else - { - minn = mid + 1; - } - } - - /* - * Fall back on a linear search + } + } + + /* + * Binary search */ - DPRINT("LdrPEGetExportByName(): Falling back on a linear search of export table\n"); - for (i = 0; i < ExportDir->NumberOfNames; i++) - { - ExName = RVA(BaseAddress, ExNames[i]); - if (strcmp(ExName, (PCHAR)SymbolName) == 0) - { - Ordinal = ExOrdinals[i]; - Function = RVA(BaseAddress, ExFunctions[Ordinal]); - DPRINT("%x %x %x\n", Function, ExportDir, ExportDir + ExportDirSize); - if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && - (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) - { - DPRINT("Forward: %s\n", (PCHAR)Function); - Function = LdrPEFixupForward((PCHAR)Function); - } - if (Function == NULL) - { - break; - } - return Function; - } - } - DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName); - return (PVOID)NULL; + minn = 0; + maxn = ExportDir->NumberOfNames - 1; + while (minn <= maxn) + { + mid = (minn + maxn) / 2; + + ExName = RVA(BaseAddress, ExNames[mid]); + res = strcmp(ExName, (PCHAR)SymbolName); + if (res == 0) + { + Ordinal = ExOrdinals[mid]; + Function = RVA(BaseAddress, ExFunctions[Ordinal]); + if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && + (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) + { + DPRINT("Forward: %s\n", (PCHAR)Function); + Function = LdrPEFixupForward((PCHAR)Function); + if (Function == NULL) + { + DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName); + } + return Function; + } + if (Function != NULL) + { + return Function; + } + } + else if (res > 0) + { + maxn = mid - 1; + } + else + { + minn = mid + 1; + } + } + + ExName = RVA(BaseAddress, ExNames[mid]); + DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName); + return (PVOID)NULL; } static PVOID -LdrPEGetExportByOrdinal (PVOID BaseAddress, - ULONG Ordinal) +LdrPEGetExportByOrdinal ( + PVOID BaseAddress, + ULONG Ordinal ) { - PIMAGE_EXPORT_DIRECTORY ExportDir; - ULONG ExportDirSize; - PDWORD * ExFunctions; - PVOID Function; - - ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData (BaseAddress, - TRUE, - IMAGE_DIRECTORY_ENTRY_EXPORT, - &ExportDirSize); - - ExFunctions = (PDWORD *)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)Function >= (ULONG)ExportDir) && - ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize)) - { - DPRINT("Forward: %s\n", (PCHAR)Function); - Function = LdrPEFixupForward((PCHAR)Function); - } - - return Function; + PIMAGE_EXPORT_DIRECTORY ExportDir; + ULONG ExportDirSize; + PDWORD * ExFunctions; + PVOID Function; + + ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData ( + BaseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportDirSize); + + ExFunctions = (PDWORD *)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, - PMODULE_OBJECT ImportedModule, - PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory) +LdrPEProcessImportDirectoryEntry( + PVOID DriverBase, + PLDR_DATA_TABLE_ENTRY ImportedModule, + PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory ) { - PVOID* ImportAddressList; - PULONG FunctionNameList; - ULONG Ordinal; - - if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0) - { - return STATUS_UNSUCCESSFUL; - } - - /* Get the import address list. */ - ImportAddressList = (PVOID*)(DriverBase + (ULONG_PTR)ImportModuleDirectory->FirstThunk); - - /* Get the list of functions to import. */ - if (ImportModuleDirectory->OriginalFirstThunk != 0) - { - FunctionNameList = (PULONG) (DriverBase + (ULONG_PTR)ImportModuleDirectory->OriginalFirstThunk); - } - else - { - FunctionNameList = (PULONG)(DriverBase + (ULONG_PTR)ImportModuleDirectory->FirstThunk); - } - - /* Walk through function list and fixup addresses. */ - while (*FunctionNameList != 0L) - { - if ((*FunctionNameList) & 0x80000000) - { - Ordinal = (*FunctionNameList) & 0x7fffffff; - *ImportAddressList = LdrPEGetExportByOrdinal(ImportedModule->Base, Ordinal); - if ((*ImportAddressList) == NULL) - { - DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullName); - return STATUS_UNSUCCESSFUL; - } - } - else - { - IMAGE_IMPORT_BY_NAME *pe_name; - pe_name = RVA(DriverBase, *FunctionNameList); - *ImportAddressList = LdrPEGetExportByName(ImportedModule->Base, pe_name->Name, pe_name->Hint); - if ((*ImportAddressList) == NULL) - { - DPRINT1("Failed to import %s from %wZ\n", pe_name->Name, &ImportedModule->FullName); - return STATUS_UNSUCCESSFUL; - } - } - ImportAddressList++; - FunctionNameList++; - } - return STATUS_SUCCESS; + PVOID* ImportAddressList; + PULONG FunctionNameList; + ULONG Ordinal; + + if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0) + { + return STATUS_UNSUCCESSFUL; + } + + /* Get the import address list. */ + ImportAddressList = (PVOID*)RVA(DriverBase, ImportModuleDirectory->FirstThunk); + + /* Get the list of functions to import. */ + if (ImportModuleDirectory->OriginalFirstThunk != 0) + { + FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->OriginalFirstThunk); + } + else + { + FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->FirstThunk); + } + + /* Walk through function list and fixup addresses. */ + while (*FunctionNameList != 0L) + { + if ((*FunctionNameList) & 0x80000000) + { + Ordinal = (*FunctionNameList) & 0x7fffffff; + *ImportAddressList = LdrPEGetExportByOrdinal(ImportedModule->DllBase, Ordinal); + if ((*ImportAddressList) == NULL) + { + DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName); + return STATUS_UNSUCCESSFUL; + } + } + else + { + IMAGE_IMPORT_BY_NAME *pe_name; + pe_name = RVA(DriverBase, *FunctionNameList); + *ImportAddressList = LdrPEGetExportByName(ImportedModule->DllBase, pe_name->Name, pe_name->Hint); + if ((*ImportAddressList) == NULL) + { + DPRINT1("Failed to import %s from %wZ\n", pe_name->Name, &ImportedModule->FullDllName); + return STATUS_UNSUCCESSFUL; + } + } + ImportAddressList++; + FunctionNameList++; + } + return STATUS_SUCCESS; } static NTSTATUS -LdrPEFixupImports(PMODULE_OBJECT Module) +LdrPEFixupImports ( PLDR_DATA_TABLE_ENTRY Module ) { - PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory; - PCHAR ImportedName; - PMODULE_OBJECT ImportedModule; - NTSTATUS Status; - - /* Process each import module */ - ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR) - RtlImageDirectoryEntryToData(Module->Base, - TRUE, - IMAGE_DIRECTORY_ENTRY_IMPORT, - NULL); - DPRINT("Processeing import directory at %p\n", ImportModuleDirectory); - while (ImportModuleDirectory->Name) - { - /* Check to make sure that import lib is kernel */ - ImportedName = (PCHAR) Module->Base + ImportModuleDirectory->Name; - - Status = LdrPEGetOrLoadModule(Module, ImportedName, &ImportedModule); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - Status = LdrPEProcessImportDirectoryEntry(Module->Base, ImportedModule, ImportModuleDirectory); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - ImportModuleDirectory++; - } - return STATUS_SUCCESS; + PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory; + PCHAR ImportedName; + PLDR_DATA_TABLE_ENTRY ImportedModule; + NTSTATUS Status; + ULONG Size; + + /* Process each import module */ + ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR) + RtlImageDirectoryEntryToData(Module->DllBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_IMPORT, + &Size); + DPRINT("Processeing import directory at %p\n", ImportModuleDirectory); + while (ImportModuleDirectory->Name) + { + if (Module->SizeOfImage <= ImportModuleDirectory->Name) + { + DPRINT1("Invalid import directory in %wZ\n", &Module->FullDllName); + return STATUS_SECTION_NOT_IMAGE; + } + + /* Check to make sure that import lib is kernel */ + ImportedName = (PCHAR) Module->DllBase + ImportModuleDirectory->Name; + + Status = LdrPEGetOrLoadModule(Module, ImportedName, &ImportedModule); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Status = LdrPEProcessImportDirectoryEntry(Module->DllBase, ImportedModule, ImportModuleDirectory); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + ImportModuleDirectory++; + } + return STATUS_SUCCESS; } /* EOF */