diff --git a/reactos/boot/freeldr/freeldr/arch/i386/loader.c b/reactos/boot/freeldr/freeldr/arch/i386/loader.c index ddab5492b79..4e29d9791ee 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/loader.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/loader.c @@ -127,6 +127,12 @@ FrLdrLoadImage(IN PCHAR szFileName, IN INT nPos, IN BOOLEAN IsKernel); +PVOID +NTAPI +LdrPEGetExportByName(PVOID BaseAddress, + PUCHAR SymbolName, + USHORT Hint); + /* FUNCTIONS *****************************************************************/ /*++ @@ -300,6 +306,46 @@ FrLdrSetupPageDirectory(VOID) 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 @@ LdrPEGetExportByName(PVOID BaseAddress, 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 @@ LdrPEGetExportByName(PVOID BaseAddress, 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 @@ LdrPEGetExportByName(PVOID BaseAddress, } ExName = RVA(BaseAddress, ExNames[mid]); - DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName); + DbgPrint("2: failed to find %s\n",SymbolName); return (PVOID)NULL; } @@ -474,23 +520,6 @@ LdrPEProcessImportDirectoryEntry(PVOID DriverBase, 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 NTAPI LdrPEGetOrLoadModule(IN PCHAR ModuleName, diff --git a/reactos/ntoskrnl/ex/init.c b/reactos/ntoskrnl/ex/init.c index d65b5354dff..b82aff94e58 100644 --- a/reactos/ntoskrnl/ex/init.c +++ b/reactos/ntoskrnl/ex/init.c @@ -896,6 +896,9 @@ ExpInitializeExecutive(IN ULONG Cpu, /* 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); diff --git a/reactos/ntoskrnl/include/internal/ex.h b/reactos/ntoskrnl/include/internal/ex.h index c65efce4d03..b1188b66bb8 100644 --- a/reactos/ntoskrnl/include/internal/ex.h +++ b/reactos/ntoskrnl/include/internal/ex.h @@ -20,6 +20,7 @@ extern BOOLEAN ExpIsWinPEMode; ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset; ULONG ExpUnicodeCaseTableDataOffset; PVOID ExpNlsSectionPointer; +extern ULONG ExpInitializationPhase; typedef struct _EXHANDLE { diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 2c5f3e7ae92..c15595b2d1c 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -1429,4 +1429,17 @@ MiQueryVirtualMemory( OUT PULONG ResultLength ); +VOID +NTAPI +MiReloadBootLoadedDrivers( + IN PLOADER_PARAMETER_BLOCK LoaderBlock +); + +BOOLEAN +NTAPI +MiInitializeLoadedModuleList( + IN PLOADER_PARAMETER_BLOCK LoaderBlock +); + + #endif diff --git a/reactos/ntoskrnl/io/iomgr/driver.c b/reactos/ntoskrnl/io/iomgr/driver.c index c87ecb98206..8d187f96fbc 100644 --- a/reactos/ntoskrnl/io/iomgr/driver.c +++ b/reactos/ntoskrnl/io/iomgr/driver.c @@ -34,10 +34,10 @@ extern BOOLEAN ExpInTextModeSetup; /* 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 @@ IopLoadServiceModule( /* 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 @@ IopAttachFilterDrivers( 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) +NTSTATUS +NTAPI +IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry) { - PLDR_DATA_TABLE_ENTRY ModuleObject; - PDEVICE_NODE DeviceNode; - PDRIVER_OBJECT DriverObject; - NTSTATUS Status; - PWCHAR FileNameWithoutPath; - LPWSTR FileExtension; + PDEVICE_NODE DeviceNode; + PDRIVER_OBJECT DriverObject; + NTSTATUS Status; + PWCHAR FileNameWithoutPath; + LPWSTR FileExtension; + PUNICODE_STRING ModuleName = &LdrEntry->BaseDllName; + PLDR_DATA_TABLE_ENTRY ModuleObject; - DPRINT("Initializing driver '%wZ' at %08lx, length 0x%08lx\n", - ModuleName, ModuleLoadBase, ModuleLength); /* * Display 'Loading XXX...' message @@ -836,9 +864,6 @@ IopInitializeBuiltinDriver( /* * 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 @@ IopInitializeBuiltinDriver( 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 @@ IopInitializeBuiltinDriver( } /* - * 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 @@ IopInitializeBuiltinDriver( /* * Strip the file extension from ServiceName */ - FileExtension = wcsrchr(DeviceNode->ServiceName.Buffer, '.'); if (FileExtension != NULL) { @@ -896,13 +914,11 @@ IopInitializeBuiltinDriver( /* * 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,10 +1021,7 @@ IopInitializeBootDrivers(VOID) if (!(LdrEntry->Flags & LDRP_ENTRY_INSERTED)) { /* Initialize it */ - IopInitializeBuiltinDriver(NULL, - LdrEntry->DllBase, - &LdrEntry->BaseDllName, - LdrEntry->SizeOfImage); + IopInitializeBuiltinDriver(LdrEntry); } } @@ -1016,25 +1029,6 @@ IopInitializeBootDrivers(VOID) 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; - } - /* In old ROS, the loader list became empty after this point. Simulate. */ InitializeListHead(&KeLoaderBlock->LoadOrderListHead); } diff --git a/reactos/ntoskrnl/ke/i386/kiinit.c b/reactos/ntoskrnl/ke/i386/kiinit.c index 032a6b3a882..3bc2597f711 100644 --- a/reactos/ntoskrnl/ke/i386/kiinit.c +++ b/reactos/ntoskrnl/ke/i386/kiinit.c @@ -533,9 +533,6 @@ KiInitializeKernel(IN PKPROCESS InitProcess, 0, 4096); - /* Sets up the Text Sections of the Kernel and HAL for debugging */ - LdrInit1(); - /* Set the NX Support policy */ SharedUserData->NXSupportPolicy = (UCHAR)NXSupportPolicy; diff --git a/reactos/ntoskrnl/ldr/loader.c b/reactos/ntoskrnl/ldr/loader.c index 5e505472273..5c1599ec833 100644 --- a/reactos/ntoskrnl/ldr/loader.c +++ b/reactos/ntoskrnl/ldr/loader.c @@ -18,13 +18,6 @@ #define NDEBUG #include -/* GLOBALS *******************************************************************/ - -LIST_ENTRY PsLoadedModuleList; -KSPIN_LOCK ModuleListLock; -LDR_DATA_TABLE_ENTRY NtoskrnlModuleObject; -LDR_DATA_TABLE_ENTRY HalModuleObject; - /* FUNCTIONS *****************************************************************/ NTSTATUS @@ -105,52 +98,7 @@ LdrpCompareModuleNames ( 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 @@ LdrGetModuleObject ( PUNICODE_STRING ModuleName ) DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName); - KeAcquireSpinLock(&ModuleListLock,&Irql); + KeAcquireSpinLock(&PsLoadedModuleSpinLock,&Irql); Entry = PsLoadedModuleList.Flink; while (Entry != &PsLoadedModuleList) @@ -180,14 +128,14 @@ LdrGetModuleObject ( PUNICODE_STRING ModuleName ) 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 @@ LdrUnloadModule ( PLDR_DATA_TABLE_ENTRY ModuleObject ) 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,30 +169,105 @@ LdrUnloadModule ( PLDR_DATA_TABLE_ENTRY ModuleObject ) } // -// 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); /* Get header pointers */ @@ -414,9 +437,6 @@ LdrProcessModule(PVOID ModuleLoadBase, 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 @@ LdrProcessModule(PVOID ModuleLoadBase, 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 @@ LdrProcessModule(PVOID ModuleLoadBase, } /* 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 @@ LdrProcessModule(PVOID ModuleLoadBase, } /* 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 @@ LdrLoadModule( *ModuleObject = Module; /* Hook for KDB on loading a driver. */ - KDB_LOADDRIVER_HOOK(Filename, Module); + KDB_LOADDRIVER_HOOK(FileName, Module); return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/mm/mminit.c b/reactos/ntoskrnl/mm/mminit.c index 72afb2499d4..ac42a1c1e0b 100644 --- a/reactos/ntoskrnl/mm/mminit.c +++ b/reactos/ntoskrnl/mm/mminit.c @@ -459,7 +459,18 @@ NTAPI 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; diff --git a/reactos/ntoskrnl/mm/sysldr.c b/reactos/ntoskrnl/mm/sysldr.c index f8febbae2b7..772c031aee7 100644 --- a/reactos/ntoskrnl/mm/sysldr.c +++ b/reactos/ntoskrnl/mm/sysldr.c @@ -12,8 +12,78 @@ #define NDEBUG #include +/* 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 MiSnapThunk(IN PVOID DllBase, @@ -584,3 +654,259 @@ CheckDllState: 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; +}