Author: ion Date: Thu Feb 22 21:02:53 2007 New Revision: 25874
URL: http://svn.reactos.org/svn/reactos?rev=25874&view=rev Log: - Improve LdrGetModuleObject (in FreeLDR) to handle partial names too, so NTOSKRNL will still match NTOSKRNL.EXE. This is needed for forwarder support. - Implement LdrPEFixupForward in FreeLDR and update LdrPEGetExportByName to use it, so that FreeLDR can now parse import tables with forwarders. - Add call to MmInitSystem for Phase 0 in ExpInitializeExecutive. - Completely redesign the way boot drivers are handled. They're now re-mapped during Phase 0 MmInit (part of the re-mapping is a hack until FreeLDR 2.5 is ready) and the IoMgr only does I/O stuff, not PE loading anymore (this is only half-true, we still process imports until FreeLDR 2.5 is done). - Also re-design the way the module list head is initialized and used. LdrInit1 is now gone, Phase 0 MmInit now handles initializing it and copying boot loader data to it. - Some code is still missing and functions still need to be improved. - When FreeLDR 2.5 is ready some of the hacks will go away, they're #ifed for now to make it easy to switch.
Modified: trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c trunk/reactos/ntoskrnl/ex/init.c trunk/reactos/ntoskrnl/include/internal/ex.h trunk/reactos/ntoskrnl/include/internal/mm.h trunk/reactos/ntoskrnl/io/iomgr/driver.c trunk/reactos/ntoskrnl/ke/i386/kiinit.c trunk/reactos/ntoskrnl/ldr/loader.c trunk/reactos/ntoskrnl/mm/mminit.c trunk/reactos/ntoskrnl/mm/sysldr.c
Modified: trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/arch/i... ============================================================================== --- trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c (original) +++ trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c Thu Feb 22 21:02:53 2007 @@ -127,6 +127,12 @@ IN INT nPos, IN BOOLEAN IsKernel);
+PVOID +NTAPI +LdrPEGetExportByName(PVOID BaseAddress, + PUCHAR SymbolName, + USHORT Hint); + /* FUNCTIONS *****************************************************************/
/*++ @@ -300,6 +306,46 @@ PageDir->Pde[0].PageFrameNumber = 1; }
+PLOADER_MODULE +NTAPI +LdrGetModuleObject(PCHAR ModuleName) +{ + ULONG i; + + for (i = 0; i < LoaderBlock.ModsCount; i++) + { + if (strstr(_strupr((PCHAR)reactos_modules[i].String), _strupr(ModuleName))) + { + return &reactos_modules[i]; + } + } + + return NULL; +} + +PVOID +NTAPI +LdrPEFixupForward(IN PCHAR ForwardName) +{ + CHAR NameBuffer[128]; + PCHAR p; + PLOADER_MODULE ModuleObject; + + strcpy(NameBuffer, ForwardName); + p = strchr(NameBuffer, '.'); + if (p == NULL) return NULL; + *p = 0; + + ModuleObject = LdrGetModuleObject(NameBuffer); + if (!ModuleObject) + { + DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer); + return NULL; + } + + return LdrPEGetExportByName((PVOID)ModuleObject->ModStart, (PUCHAR)(p + 1), 0xffff); +} + PVOID NTAPI LdrPEGetExportByName(PVOID BaseAddress, @@ -360,10 +406,10 @@ if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) { - Function = NULL; + Function = LdrPEFixupForward((PCHAR)Function); if (Function == NULL) { - DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName); + DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function); } return Function; } @@ -390,10 +436,10 @@ if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) { - Function = NULL; + Function = LdrPEFixupForward((PCHAR)Function); if (Function == NULL) { - DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName); + DbgPrint("1: failed to find %s\n", Function); } return Function; } @@ -413,7 +459,7 @@ }
ExName = RVA(BaseAddress, ExNames[mid]); - DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName); + DbgPrint("2: failed to find %s\n",SymbolName); return (PVOID)NULL; }
@@ -472,23 +518,6 @@ FunctionNameList++; } return STATUS_SUCCESS; -} - -PLOADER_MODULE -NTAPI -LdrGetModuleObject(PCHAR ModuleName) -{ - ULONG i; - - for (i = 0; i < LoaderBlock.ModsCount; i++) - { - if (!_stricmp((PCHAR)reactos_modules[i].String, ModuleName)) - { - return &reactos_modules[i]; - } - } - - return NULL; }
NTSTATUS
Modified: trunk/reactos/ntoskrnl/ex/init.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/init.c?rev=2587... ============================================================================== --- trunk/reactos/ntoskrnl/ex/init.c (original) +++ trunk/reactos/ntoskrnl/ex/init.c Thu Feb 22 21:02:53 2007 @@ -896,6 +896,9 @@ /* Initialize the executive at phase 0 */ if (!ExInitSystem()) KEBUGCHECK(PHASE0_INITIALIZATION_FAILED);
+ /* Initialize the memory manager at phase 0 */ + if (!MmInitSystem(0, LoaderBlock)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED); + /* Load boot symbols */ ExpLoadBootSymbols(LoaderBlock);
Modified: trunk/reactos/ntoskrnl/include/internal/ex.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/e... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ex.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ex.h Thu Feb 22 21:02:53 2007 @@ -20,6 +20,7 @@ ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset; ULONG ExpUnicodeCaseTableDataOffset; PVOID ExpNlsSectionPointer; +extern ULONG ExpInitializationPhase;
typedef struct _EXHANDLE {
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/m... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/mm.h (original) +++ trunk/reactos/ntoskrnl/include/internal/mm.h Thu Feb 22 21:02:53 2007 @@ -1429,4 +1429,17 @@ OUT PULONG ResultLength );
+VOID +NTAPI +MiReloadBootLoadedDrivers( + IN PLOADER_PARAMETER_BLOCK LoaderBlock +); + +BOOLEAN +NTAPI +MiInitializeLoadedModuleList( + IN PLOADER_PARAMETER_BLOCK LoaderBlock +); + + #endif
Modified: trunk/reactos/ntoskrnl/io/iomgr/driver.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/driver.c?... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/driver.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/driver.c Thu Feb 22 21:02:53 2007 @@ -34,10 +34,10 @@ /* DECLARATIONS ***************************************************************/
NTSTATUS -LdrProcessModule( - PVOID ModuleLoadBase, - PUNICODE_STRING ModuleName, - PLDR_DATA_TABLE_ENTRY *ModuleObject +NTAPI +LdrTemporaryDriverHack( + PLDR_DATA_TABLE_ENTRY ModuleObject, + PUNICODE_STRING ModuleName );
/* PRIVATE FUNCTIONS **********************************************************/ @@ -452,66 +452,6 @@ /* FIXME: Check if it is the right status code */ Status = STATUS_PLUGPLAY_NO_DEVICE; } - - /* - * Special case for boot modules that were loaded by boot loader. - */ - - else if (KeLoaderBlock) - { - WCHAR SearchNameBuffer[256]; - UNICODE_STRING SearchName; - PLIST_ENTRY ListHead, NextEntry; - PLDR_DATA_TABLE_ENTRY LdrEntry; - - Status = STATUS_UNSUCCESSFUL; - - /* - * FIXME: - * Improve this searching algorithm by using the image name - * stored in registry entry ImageName and use the whole path - * (requires change in FreeLoader). - */ - swprintf(SearchNameBuffer, L"%wZ.sys", ServiceName); - RtlInitUnicodeString(&SearchName, SearchNameBuffer); - - /* Loop the boot modules */ - ListHead = &KeLoaderBlock->LoadOrderListHead; - NextEntry = ListHead->Flink->Flink; - while (ListHead != NextEntry) - { - /* Get the entry */ - LdrEntry = CONTAINING_RECORD(NextEntry, - LDR_DATA_TABLE_ENTRY, - InLoadOrderLinks); - - /* Compare names */ - if (RtlEqualUnicodeString(&LdrEntry->BaseDllName, &SearchName, TRUE)) - { - /* Tell, that the module is already loaded */ - LdrEntry->Flags |= LDRP_ENTRY_INSERTED; - - Status = LdrProcessModule(LdrEntry->DllBase, - &ServiceImagePath, - ModuleObject); - - KDB_SYMBOLFILE_HOOK(&SearchName); - break; - } - - /* Go to the next driver */ - NextEntry = NextEntry->Flink; - } - - if (!NT_SUCCESS(Status)) - /* Try to load it. It may just have been installed by PnP manager */ - Status = LdrLoadModule(&ServiceImagePath, ModuleObject); - } - - /* - * Case for rest of the drivers - */ - else { DPRINT("Loading module\n"); @@ -805,28 +745,116 @@ return STATUS_SUCCESS; }
+NTSTATUS +NTAPI +MiResolveImageReferences(IN PVOID ImageBase, + IN PUNICODE_STRING ImageFileDirectory, + IN PUNICODE_STRING NamePrefix OPTIONAL, + OUT PCHAR *MissingApi, + OUT PWCHAR *MissingDriver, + OUT PLOAD_IMPORTS *LoadImports); + +extern KSPIN_LOCK PsLoadedModuleSpinLock; + +// +// Used for images already loaded (boot drivers) +// +NTSTATUS +NTAPI +LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry, + PUNICODE_STRING FileName, + PLDR_DATA_TABLE_ENTRY *ModuleObject) +{ + NTSTATUS Status; + PLDR_DATA_TABLE_ENTRY NewEntry; + UNICODE_STRING BaseName, BaseDirectory; + PLOAD_IMPORTS LoadedImports = (PVOID)-2; + PCHAR MissingApiName, Buffer; + PWCHAR MissingDriverName; + PVOID DriverBase = LdrEntry->DllBase; + + /* Allocate a buffer we'll use for names */ + Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG_LDR_WSTR); + if (!Buffer) + { + /* Fail */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Check for a separator */ + if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) + { + PWCHAR p; + ULONG BaseLength; + + /* Loop the path until we get to the base name */ + p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)]; + while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--; + + /* Get the length */ + BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p); + BaseLength *= sizeof(WCHAR); + + /* Setup the string */ + BaseName.Length = (USHORT)BaseLength; + BaseName.Buffer = p; + } + else + { + /* Otherwise, we already have a base name */ + BaseName.Length = FileName->Length; + BaseName.Buffer = FileName->Buffer; + } + + /* Setup the maximum length */ + BaseName.MaximumLength = BaseName.Length; + + /* Now compute the base directory */ + BaseDirectory = *FileName; + BaseDirectory.Length -= BaseName.Length; + BaseDirectory.MaximumLength = BaseDirectory.Length; + + NewEntry = LdrEntry; + + /* Resolve imports */ + MissingApiName = Buffer; + Status = MiResolveImageReferences(DriverBase, + &BaseDirectory, + NULL, + &MissingApiName, + &MissingDriverName, + &LoadedImports); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ExFreePool(LdrEntry->FullDllName.Buffer); + ExFreePool(LdrEntry); + return Status; + } + + /* Return */ + *ModuleObject = LdrEntry; + return STATUS_SUCCESS; +} + /* * IopInitializeBuiltinDriver * * Initialize a driver that is already loaded in memory. */
-NTSTATUS FASTCALL INIT_FUNCTION -IopInitializeBuiltinDriver( - PDEVICE_NODE ModuleDeviceNode, - PVOID ModuleLoadBase, - PUNICODE_STRING ModuleName, - ULONG ModuleLength) -{ - PLDR_DATA_TABLE_ENTRY ModuleObject; - PDEVICE_NODE DeviceNode; - PDRIVER_OBJECT DriverObject; - NTSTATUS Status; - PWCHAR FileNameWithoutPath; - LPWSTR FileExtension; - - DPRINT("Initializing driver '%wZ' at %08lx, length 0x%08lx\n", - ModuleName, ModuleLoadBase, ModuleLength); +NTSTATUS +NTAPI +IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry) +{ + PDEVICE_NODE DeviceNode; + PDRIVER_OBJECT DriverObject; + NTSTATUS Status; + PWCHAR FileNameWithoutPath; + LPWSTR FileExtension; + PUNICODE_STRING ModuleName = &LdrEntry->BaseDllName; + PLDR_DATA_TABLE_ENTRY ModuleObject; +
/* * Display 'Loading XXX...' message @@ -836,9 +864,6 @@ /* * Determine the right device object */ - - if (ModuleDeviceNode == NULL) - { /* Use IopRootDeviceNode for now */ Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode); if (!NT_SUCCESS(Status)) @@ -846,15 +871,11 @@ CPRINT("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status); return(Status); } - } else - { - DeviceNode = ModuleDeviceNode; - } +
/* * Generate filename without path (not needed by freeldr) */ - FileNameWithoutPath = wcsrchr(ModuleName->Buffer, L'\'); if (FileNameWithoutPath == NULL) { @@ -866,17 +887,15 @@ }
/* - * Load the module + * Load the module. Remove for FreeLDR 2.5. */ RtlCreateUnicodeString(&DeviceNode->ServiceName, FileNameWithoutPath); - Status = LdrProcessModule(ModuleLoadBase, &DeviceNode->ServiceName, - &ModuleObject); + Status = LdrProcessDriverModule(LdrEntry, &DeviceNode->ServiceName, &ModuleObject); if (!NT_SUCCESS(Status)) { - if (ModuleDeviceNode == NULL) - IopFreeDeviceNode(DeviceNode); - CPRINT("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status); - return Status; + IopFreeDeviceNode(DeviceNode); + CPRINT("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status); + return Status; }
/* Load symbols */ @@ -885,7 +904,6 @@ /* * Strip the file extension from ServiceName */ - FileExtension = wcsrchr(DeviceNode->ServiceName.Buffer, '.'); if (FileExtension != NULL) { @@ -896,13 +914,11 @@ /* * Initialize the driver */ - Status = IopInitializeDriverModule(DeviceNode, ModuleObject, &DeviceNode->ServiceName, FALSE, &DriverObject);
if (!NT_SUCCESS(Status)) { - if (ModuleDeviceNode == NULL) IopFreeDeviceNode(DeviceNode); CPRINT("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status); return Status; @@ -1005,31 +1021,9 @@ if (!(LdrEntry->Flags & LDRP_ENTRY_INSERTED)) { /* Initialize it */ - IopInitializeBuiltinDriver(NULL, - LdrEntry->DllBase, - &LdrEntry->BaseDllName, - LdrEntry->SizeOfImage); + IopInitializeBuiltinDriver(LdrEntry); } } - - /* Go to the next driver */ - NextEntry = NextEntry->Flink; - } - - /* Loop modules again */ - NextEntry = ListHead->Flink; - while (ListHead != NextEntry) - { - /* Get the entry */ - LdrEntry = CONTAINING_RECORD(NextEntry, - LDR_DATA_TABLE_ENTRY, - InLoadOrderLinks); - - /* Free memory */ - DPRINT("Driver at: %p ending at: %p for module: %wZ\n", - LdrEntry->DllBase, - (ULONG_PTR)LdrEntry->DllBase+ LdrEntry->SizeOfImage, - &LdrEntry->FullDllName);
/* Go to the next driver */ NextEntry = NextEntry->Flink;
Modified: trunk/reactos/ntoskrnl/ke/i386/kiinit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/kiinit.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/kiinit.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/kiinit.c Thu Feb 22 21:02:53 2007 @@ -533,9 +533,6 @@ 0, 4096);
- /* Sets up the Text Sections of the Kernel and HAL for debugging */ - LdrInit1(); - /* Set the NX Support policy */ SharedUserData->NXSupportPolicy = (UCHAR)NXSupportPolicy;
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 Thu Feb 22 21:02:53 2007 @@ -17,13 +17,6 @@ #include <ntoskrnl.h> #define NDEBUG #include <debug.h> - -/* GLOBALS *******************************************************************/ - -LIST_ENTRY PsLoadedModuleList; -KSPIN_LOCK ModuleListLock; -LDR_DATA_TABLE_ENTRY NtoskrnlModuleObject; -LDR_DATA_TABLE_ENTRY HalModuleObject;
/* FUNCTIONS *****************************************************************/
@@ -105,52 +98,7 @@ return(0); }
-VOID -INIT_FUNCTION -NTAPI -LdrInit1(VOID) -{ - PLDR_DATA_TABLE_ENTRY HalModuleObject, NtoskrnlModuleObject, LdrEntry; - - /* Initialize the module list and spinlock */ - InitializeListHead(&PsLoadedModuleList); - 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); - NtoskrnlModuleObject->BaseDllName = NtoskrnlModuleObject->FullDllName; - NtoskrnlModuleObject->EntryPoint = LdrEntry->EntryPoint; - NtoskrnlModuleObject->SizeOfImage = LdrEntry->SizeOfImage; - - /* Insert it into the list */ - InsertTailList(&PsLoadedModuleList, &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); - HalModuleObject->BaseDllName = HalModuleObject->FullDllName; - HalModuleObject->EntryPoint = LdrEntry->EntryPoint; - HalModuleObject->SizeOfImage = LdrEntry->SizeOfImage; - - /* Insert it into the list */ - InsertTailList(&PsLoadedModuleList, &HalModuleObject->InLoadOrderLinks); - - /* Hook for KDB on initialization of the loader. */ - KDB_LOADERINIT_HOOK(NtoskrnlModuleObject, HalModuleObject); -} +extern KSPIN_LOCK PsLoadedModuleSpinLock;
// // Used for checking if a module is already in the module list. @@ -166,7 +114,7 @@
DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName);
- KeAcquireSpinLock(&ModuleListLock,&Irql); + KeAcquireSpinLock(&PsLoadedModuleSpinLock,&Irql);
Entry = PsLoadedModuleList.Flink; while (Entry != &PsLoadedModuleList) @@ -180,14 +128,14 @@ if (!LdrpCompareModuleNames(&Module->BaseDllName, ModuleName)) { DPRINT("Module %wZ\n", &Module->BaseDllName); - KeReleaseSpinLock(&ModuleListLock, Irql); + KeReleaseSpinLock(&PsLoadedModuleSpinLock, Irql); return(Module); }
Entry = Entry->Flink; }
- KeReleaseSpinLock(&ModuleListLock, Irql); + KeReleaseSpinLock(&PsLoadedModuleSpinLock, Irql);
DPRINT("Could not find module '%wZ'\n", ModuleName);
@@ -204,9 +152,9 @@ KIRQL Irql;
/* Remove the module from the module list */ - KeAcquireSpinLock(&ModuleListLock,&Irql); + KeAcquireSpinLock(&PsLoadedModuleSpinLock,&Irql); RemoveEntryList(&ModuleObject->InLoadOrderLinks); - KeReleaseSpinLock(&ModuleListLock, Irql); + KeReleaseSpinLock(&PsLoadedModuleSpinLock, Irql);
/* Hook for KDB on unloading a driver. */ KDB_UNLOADDRIVER_HOOK(ModuleObject); @@ -221,29 +169,104 @@ }
// -// Used for images already loaded (boot drivers) +// Used by NtLoadDriver/IoMgr // NTSTATUS -LdrProcessModule(PVOID ModuleLoadBase, - PUNICODE_STRING FileName, - PLDR_DATA_TABLE_ENTRY *ModuleObject) +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; unsigned int DriverSize, Idx; ULONG CurrentSize; PVOID DriverBase; PIMAGE_DOS_HEADER PEDosHeader; PIMAGE_NT_HEADERS PENtHeaders; PIMAGE_SECTION_HEADER PESectionHeaders; - NTSTATUS Status; KIRQL Irql; PIMAGE_NT_HEADERS NtHeader; UNICODE_STRING BaseName, BaseDirectory, PrefixName; PLDR_DATA_TABLE_ENTRY LdrEntry; ULONG EntrySize; PLOAD_IMPORTS LoadedImports = (PVOID)-2; - PWSTR NameBuffer; PCHAR MissingApiName, Buffer; PWCHAR MissingDriverName; + + *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);
DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
@@ -414,9 +437,6 @@ LdrEntry->Flags |= 0x80000000; }
- /* We'll put the name after the entry */ - NameBuffer = (PVOID)(LdrEntry + 1); - /* Setup the rest of the entry */ LdrEntry->DllBase = DriverBase; LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)DriverBase + @@ -426,7 +446,7 @@ LdrEntry->SectionPointer = LdrEntry;
/* Now write the DLL name */ - LdrEntry->BaseDllName.Buffer = NameBuffer; + LdrEntry->BaseDllName.Buffer = (PVOID)(LdrEntry + 1); LdrEntry->BaseDllName.Length = BaseName.Length; LdrEntry->BaseDllName.MaximumLength = BaseName.Length;
@@ -461,9 +481,9 @@ }
/* Insert the entry */ - KeAcquireSpinLock(&ModuleListLock, &Irql); + KeAcquireSpinLock(&PsLoadedModuleSpinLock, &Irql); InsertTailList(&PsLoadedModuleList, &LdrEntry->InLoadOrderLinks); - KeReleaseSpinLock(&ModuleListLock, Irql); + KeReleaseSpinLock(&PsLoadedModuleSpinLock, Irql);
/* Resolve imports */ MissingApiName = Buffer; @@ -482,105 +502,7 @@ }
/* Return */ - *ModuleObject = LdrEntry; - return STATUS_SUCCESS; -} - -// -// 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); - } + Module = LdrEntry;
/* Cleanup */ ExFreePool(ModuleLoadBase); @@ -588,7 +510,7 @@ *ModuleObject = Module;
/* Hook for KDB on loading a driver. */ - KDB_LOADDRIVER_HOOK(Filename, Module); + KDB_LOADDRIVER_HOOK(FileName, Module);
return(STATUS_SUCCESS); }
Modified: trunk/reactos/ntoskrnl/mm/mminit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/mminit.c?rev=25... ============================================================================== --- trunk/reactos/ntoskrnl/mm/mminit.c (original) +++ trunk/reactos/ntoskrnl/mm/mminit.c Thu Feb 22 21:02:53 2007 @@ -459,7 +459,18 @@ MmInitSystem(IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock) { - if (Phase == 1) + if (Phase == 0) + { + /* Reload boot drivers */ + MiReloadBootLoadedDrivers(LoaderBlock); + + /* Initialize the loaded module list */ + MiInitializeLoadedModuleList(LoaderBlock); + + /* We're done, for now */ + DPRINT("Mm0: COMPLETE\n"); + } + else if (Phase == 1) { MmInitializeRmapList(); RmapReady = TRUE;
Modified: trunk/reactos/ntoskrnl/mm/sysldr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/sysldr.c?rev=25... ============================================================================== --- trunk/reactos/ntoskrnl/mm/sysldr.c (original) +++ trunk/reactos/ntoskrnl/mm/sysldr.c Thu Feb 22 21:02:53 2007 @@ -12,7 +12,77 @@ #define NDEBUG #include <debug.h>
+/* GLOBALS *******************************************************************/ + +LIST_ENTRY PsLoadedModuleList; +KSPIN_LOCK PsLoadedModuleSpinLock; +PVOID PsNtosImageBase; + /* FUNCTIONS *****************************************************************/ + +VOID +NTAPI +MiUpdateThunks(IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN PVOID OldBase, + IN PVOID NewBase, + IN ULONG Size) +{ + ULONG_PTR OldBaseTop, Delta; + PLDR_DATA_TABLE_ENTRY LdrEntry; + PLIST_ENTRY NextEntry; + ULONG ImportSize; + PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor; + PULONG ImageThunk; + + /* Calculate the top and delta */ + OldBaseTop = (ULONG_PTR)OldBase + Size - 1; + Delta = (ULONG_PTR)NewBase - (ULONG_PTR)OldBase; + + /* Loop the loader block */ + for (NextEntry = LoaderBlock->LoadOrderListHead.Flink; + NextEntry != &LoaderBlock->LoadOrderListHead; + NextEntry = NextEntry->Flink) + { + /* Get the loader entry */ + LdrEntry = CONTAINING_RECORD(NextEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + + /* Get the import table */ + ImportDescriptor = RtlImageDirectoryEntryToData(LdrEntry->DllBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_IMPORT, + &ImportSize); + if (!ImportDescriptor) continue; + + /* Make sure we have an IAT */ + DPRINT("[Mm0]: Updating thunks in: %wZ\n", &LdrEntry->BaseDllName); + while ((ImportDescriptor->Name) && + (ImportDescriptor->OriginalFirstThunk)) + { + /* Get the image thunk */ + ImageThunk = (PVOID)((ULONG_PTR)LdrEntry->DllBase + + ImportDescriptor->FirstThunk); + while (*ImageThunk) + { + /* Check if it's within this module */ + if ((*ImageThunk >= (ULONG_PTR)OldBase) && (*ImageThunk <= OldBaseTop)) + { + /* Relocate it */ + DPRINT("[Mm0]: Updating IAT at: %p. Old Entry: %p. New Entry: %p.\n", + ImageThunk, *ImageThunk, *ImageThunk + Delta); + *ImageThunk += Delta; + } + + /* Go to the next thunk */ + ImageThunk++; + } + + /* Go to the next import */ + ImportDescriptor++; + } + } +}
NTSTATUS NTAPI @@ -584,3 +654,259 @@ return STATUS_SUCCESS; }
+VOID +NTAPI +MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + PLIST_ENTRY NextEntry; + ULONG i = 0; + PIMAGE_NT_HEADERS NtHeader; + PLDR_DATA_TABLE_ENTRY LdrEntry; + PIMAGE_FILE_HEADER FileHeader; + BOOLEAN ValidRelocs; + PIMAGE_DATA_DIRECTORY DataDirectory; + PVOID DllBase, NewImageAddress; + NTSTATUS Status; + ULONG DriverSize = 0, Size; + PIMAGE_SECTION_HEADER Section; + + /* Loop driver list */ + for (NextEntry = LoaderBlock->LoadOrderListHead.Flink; + NextEntry != &LoaderBlock->LoadOrderListHead; + NextEntry = NextEntry->Flink) + { + /* Get the loader entry and NT header */ + LdrEntry = CONTAINING_RECORD(NextEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + NtHeader = RtlImageNtHeader(LdrEntry->DllBase); + + /* Debug info */ + DPRINT("[Mm0]: Driver at: %p ending at: %p for module: %wZ\n", + LdrEntry->DllBase, + (ULONG_PTR)LdrEntry->DllBase+ LdrEntry->SizeOfImage, + &LdrEntry->FullDllName); + + /* Skip kernel and HAL */ + /* ROS HACK: Skip BOOTVID/KDCOM too */ + i++; + if (i <= 4) continue; + + /* Skip non-drivers */ + if (!NtHeader) continue; + +#if 1 // Disable for FreeLDR 2.5 + /* Get header pointers */ + Section = IMAGE_FIRST_SECTION(NtHeader); + + /* Determine the size of the module */ + for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++) + { + /* Skip this section if we're not supposed to load it */ + if (!(Section[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD)) + { + /* Add the size of this section into the total size */ + Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize; + DriverSize = max(DriverSize, Size); + } + } + + /* Round up the driver size to section alignment */ + DriverSize = ROUND_UP(DriverSize, NtHeader->OptionalHeader.SectionAlignment); +#endif + + /* Get the file header and make sure we can relocate */ + FileHeader = &NtHeader->FileHeader; + if (FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) continue; + if (NtHeader->OptionalHeader.NumberOfRvaAndSizes < + IMAGE_DIRECTORY_ENTRY_BASERELOC) continue; + + /* Everything made sense until now, check the relocation section too */ + DataDirectory = &NtHeader->OptionalHeader. + DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + if (!DataDirectory->VirtualAddress) + { + /* We don't really have relocations */ + ValidRelocs = FALSE; + } + else + { + /* Make sure the size is valid */ + if ((DataDirectory->VirtualAddress + DataDirectory->Size) > + LdrEntry->SizeOfImage) + { + /* They're not, skip */ + continue; + } + + /* We have relocations */ + ValidRelocs = TRUE; + } + + /* Remember the original address */ + DllBase = LdrEntry->DllBase; + + /* Allocate a virtual section for the module */ + NewImageAddress = MmAllocateSection(DriverSize, NULL); + if (!NewImageAddress) + { + /* Shouldn't happen */ + DPRINT1("[Mm0]: Couldn't allocate driver section!\n"); + while (TRUE); + } + + /* Sanity check */ + DPRINT("[Mm0]: Copying from: %p to: %p\n", DllBase, NewImageAddress); + ASSERT(ExpInitializationPhase == 0); + +#if 0 // Enable for FreeLDR 2.5 + /* Now copy the entire driver over */ + RtlCopyMemory(NewImageAddress, DllBase, DriverSize); +#else + /* Copy headers over */ + RtlCopyMemory(NewImageAddress, + DllBase, + NtHeader->OptionalHeader.SizeOfHeaders); + + /* Copy image sections into virtual section */ + for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++) + { + /* Get the size of this section and check if it's valid and on-disk */ + Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize; + if ((Size <= DriverSize) && (Section[i].SizeOfRawData)) + { + /* Copy the data from the disk to the image */ + RtlCopyMemory((PVOID)((ULONG_PTR)NewImageAddress + + Section[i].VirtualAddress), + (PVOID)((ULONG_PTR)DllBase + + Section[i].PointerToRawData), + Section[i].Misc.VirtualSize > + Section[i].SizeOfRawData ? + Section[i].SizeOfRawData : + Section[i].Misc.VirtualSize); + } + } +#endif + + /* Sanity check */ + ASSERT(*(PULONG)NewImageAddress == *(PULONG)DllBase); + + /* Set the image base to the old address */ + NtHeader->OptionalHeader.ImageBase = (ULONG_PTR)DllBase; + + /* Check if we had relocations */ + if (ValidRelocs) + { + /* Relocate the image */ + Status = LdrRelocateImageWithBias(NewImageAddress, + 0, + "SYSLDR", + STATUS_SUCCESS, + STATUS_CONFLICTING_ADDRESSES, + STATUS_INVALID_IMAGE_FORMAT); + if (!NT_SUCCESS(Status)) + { + /* This shouldn't happen */ + DPRINT1("Relocations failed!\n"); + while (TRUE); + } + } + + /* Update the loader entry */ + LdrEntry->DllBase = NewImageAddress; + + /* Update the thunks */ + DPRINT("[Mm0]: Updating thunks to: %wZ\n", &LdrEntry->BaseDllName); + MiUpdateThunks(LoaderBlock, + DllBase, + NewImageAddress, + LdrEntry->SizeOfImage); + + /* Update the loader entry */ + LdrEntry->Flags |= 0x01000000; + LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)NewImageAddress + + NtHeader->OptionalHeader.AddressOfEntryPoint); + LdrEntry->SizeOfImage = DriverSize; + } +} + +BOOLEAN +NTAPI +MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + PLDR_DATA_TABLE_ENTRY LdrEntry, NewEntry; + PLIST_ENTRY ListHead, NextEntry; + ULONG EntrySize; + + /* Setup the loaded module list and lock */ + KeInitializeSpinLock(&PsLoadedModuleSpinLock); + InitializeListHead(&PsLoadedModuleList); + + /* Get loop variables and the kernel entry */ + ListHead = &LoaderBlock->LoadOrderListHead; + NextEntry = ListHead->Flink; + LdrEntry = CONTAINING_RECORD(NextEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + PsNtosImageBase = LdrEntry->DllBase; + + /* Loop the loader block */ + while (NextEntry != ListHead) + { + /* Get the loader entry */ + LdrEntry = CONTAINING_RECORD(NextEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + + /* FIXME: ROS HACK. Make sure this is a driver */ + if (!RtlImageNtHeader(LdrEntry->DllBase)) + { + /* Skip this entry */ + NextEntry= NextEntry->Flink; + continue; + } + + /* Calculate the size we'll need and allocate a copy */ + EntrySize = sizeof(LDR_DATA_TABLE_ENTRY) + + LdrEntry->BaseDllName.MaximumLength + + sizeof(UNICODE_NULL); + NewEntry = ExAllocatePoolWithTag(NonPagedPool, EntrySize, TAG_LDR_WSTR); + if (!NewEntry) return FALSE; + + /* Copy the entry over */ + *NewEntry = *LdrEntry; + + /* Allocate the name */ + NewEntry->FullDllName.Buffer = + ExAllocatePoolWithTag(PagedPool, + LdrEntry->FullDllName.MaximumLength + + sizeof(UNICODE_NULL), + TAG_LDR_WSTR); + if (!NewEntry->FullDllName.Buffer) return FALSE; + + /* Set the base name */ + NewEntry->BaseDllName.Buffer = (PVOID)(NewEntry + 1); + + /* Copy the full and base name */ + RtlCopyMemory(NewEntry->FullDllName.Buffer, + LdrEntry->FullDllName.Buffer, + LdrEntry->FullDllName.MaximumLength); + RtlCopyMemory(NewEntry->BaseDllName.Buffer, + LdrEntry->BaseDllName.Buffer, + LdrEntry->BaseDllName.MaximumLength); + + /* Null-terminate the base name */ + NewEntry->BaseDllName.Buffer[NewEntry->BaseDllName.Length / + sizeof(WCHAR)] = UNICODE_NULL; + + /* Insert the entry into the list */ + InsertTailList(&PsLoadedModuleList, &NewEntry->InLoadOrderLinks); + NextEntry = NextEntry->Flink; + } + + /* Build the import lists for the boot drivers */ + //MiBuildImportsForBootDrivers(); + + /* We're done */ + return TRUE; +}