mirror of
https://github.com/reactos/reactos.git
synced 2026-07-05 12:44:22 +08:00
- 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:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ extern BOOLEAN ExpIsWinPEMode;
|
||||
ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
|
||||
ULONG ExpUnicodeCaseTableDataOffset;
|
||||
PVOID ExpNlsSectionPointer;
|
||||
extern ULONG ExpInitializationPhase;
|
||||
|
||||
typedef struct _EXHANDLE
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user