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/…
==============================================================================
--- 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=258…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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?…
==============================================================================
--- 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=…
==============================================================================
--- 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=2…
==============================================================================
--- 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=2…
==============================================================================
--- 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;
+}