- 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.

svn path=/trunk/; revision=25874
This commit is contained in:
Alex Ionescu
2007-02-22 18:02:53 +00:00
parent 40e1082e3d
commit 31446c8a3b
9 changed files with 611 additions and 315 deletions

View File

@@ -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,

View File

@@ -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);

View File

@@ -20,6 +20,7 @@ extern BOOLEAN ExpIsWinPEMode;
ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
ULONG ExpUnicodeCaseTableDataOffset;
PVOID ExpNlsSectionPointer;
extern ULONG ExpInitializationPhase;
typedef struct _EXHANDLE
{

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -18,13 +18,6 @@
#define NDEBUG
#include <debug.h>
/* 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);
}

View File

@@ -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;

View File

@@ -12,8 +12,78 @@
#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
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;
}