mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[NTOS]: Implement and call MiBuildImportsForBootDrivers. We now have full dependency tracking for correct unloading.
[NTOS]: Implement and call MiLocateKernelSections. Pool code and paging paths will require this information later. Loader work done for now. svn path=/trunk/; revision=46989
This commit is contained in:
parent
0e419c8771
commit
2c0c247cc7
1 changed files with 334 additions and 2 deletions
|
@ -47,6 +47,10 @@ PVOID MmLastUnloadedDrivers;
|
|||
BOOLEAN MmMakeLowMemory;
|
||||
BOOLEAN MmEnforceWriteProtection = TRUE;
|
||||
|
||||
PMMPTE MiKernelResourceStartPte, MiKernelResourceEndPte;
|
||||
ULONG_PTR ExPoolCodeStart, ExPoolCodeEnd, MmPoolCodeStart, MmPoolCodeEnd;
|
||||
ULONG_PTR MmPteCodeStart, MmPteCodeEnd;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
PVOID
|
||||
|
@ -1508,6 +1512,331 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiBuildImportsForBootDrivers(VOID)
|
||||
{
|
||||
PLIST_ENTRY NextEntry, NextEntry2;
|
||||
PLDR_DATA_TABLE_ENTRY LdrEntry, KernelEntry, HalEntry, LdrEntry2, LastEntry;
|
||||
PLDR_DATA_TABLE_ENTRY* EntryArray;
|
||||
UNICODE_STRING KernelName = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
|
||||
UNICODE_STRING HalName = RTL_CONSTANT_STRING(L"hal.dll");
|
||||
PLOAD_IMPORTS LoadedImports;
|
||||
ULONG LoadedImportsSize, ImportSize;
|
||||
PULONG_PTR ImageThunk;
|
||||
ULONG_PTR DllBase, DllEnd;
|
||||
ULONG Modules = 0, i, j = 0;
|
||||
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
|
||||
|
||||
/* Initialize variables */
|
||||
KernelEntry = HalEntry = LastEntry = NULL;
|
||||
|
||||
/* Loop the loaded module list... we are early enough that no lock is needed */
|
||||
NextEntry = PsLoadedModuleList.Flink;
|
||||
while (NextEntry != &PsLoadedModuleList)
|
||||
{
|
||||
/* Get the entry */
|
||||
LdrEntry = CONTAINING_RECORD(NextEntry,
|
||||
LDR_DATA_TABLE_ENTRY,
|
||||
InLoadOrderLinks);
|
||||
|
||||
/* Check if it's the kernel or HAL */
|
||||
if (RtlEqualUnicodeString(&KernelName, &LdrEntry->BaseDllName, TRUE))
|
||||
{
|
||||
/* Found it */
|
||||
KernelEntry = LdrEntry;
|
||||
}
|
||||
else if (RtlEqualUnicodeString(&HalName, &LdrEntry->BaseDllName, TRUE))
|
||||
{
|
||||
/* Found it */
|
||||
HalEntry = LdrEntry;
|
||||
}
|
||||
|
||||
/* Check if this is a driver DLL */
|
||||
if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
|
||||
{
|
||||
/* Check if this is the HAL or kernel */
|
||||
if ((LdrEntry == HalEntry) || (LdrEntry == KernelEntry))
|
||||
{
|
||||
/* Add a reference */
|
||||
LdrEntry->LoadCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No referencing needed */
|
||||
LdrEntry->LoadCount = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No referencing needed */
|
||||
LdrEntry->LoadCount = 0;
|
||||
}
|
||||
|
||||
/* Remember this came from the loader */
|
||||
LdrEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
|
||||
|
||||
/* Keep looping */
|
||||
NextEntry = NextEntry->Flink;
|
||||
Modules++;
|
||||
}
|
||||
|
||||
/* We must have at least found the kernel and HAL */
|
||||
if (!(HalEntry) || (!KernelEntry)) return STATUS_NOT_FOUND;
|
||||
|
||||
/* Allocate the list */
|
||||
EntryArray = ExAllocatePoolWithTag(PagedPool, Modules * sizeof(PVOID), 'TDmM');
|
||||
if (!EntryArray) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* Loop the loaded module list again */
|
||||
NextEntry = PsLoadedModuleList.Flink;
|
||||
while (NextEntry != &PsLoadedModuleList)
|
||||
{
|
||||
/* Get the entry */
|
||||
LdrEntry = CONTAINING_RECORD(NextEntry,
|
||||
LDR_DATA_TABLE_ENTRY,
|
||||
InLoadOrderLinks);
|
||||
#ifdef _WORKING_LOADER_
|
||||
/* Get its imports */
|
||||
ImageThunk = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_IAT,
|
||||
&ImportSize);
|
||||
if (!ImageThunk)
|
||||
#else
|
||||
/* Get its imports */
|
||||
ImportDescriptor = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT,
|
||||
&ImportSize);
|
||||
if (!ImportDescriptor)
|
||||
#endif
|
||||
{
|
||||
/* None present */
|
||||
LdrEntry->LoadedImports = MM_SYSLDR_NO_IMPORTS;
|
||||
NextEntry = NextEntry->Flink;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Clear the list and count the number of IAT thunks */
|
||||
RtlZeroMemory(EntryArray, Modules * sizeof(PVOID));
|
||||
#ifdef _WORKING_LOADER_
|
||||
ImportSize /= sizeof(ULONG_PTR);
|
||||
|
||||
/* Scan the thunks */
|
||||
for (i = 0, DllBase = 0, DllEnd = 0; i < ImportSize; i++, ImageThunk++)
|
||||
#else
|
||||
i = DllBase = DllEnd = 0;
|
||||
while ((ImportDescriptor->Name) &&
|
||||
(ImportDescriptor->OriginalFirstThunk))
|
||||
{
|
||||
/* Get the image thunk */
|
||||
ImageThunk = (PVOID)((ULONG_PTR)LdrEntry->DllBase +
|
||||
ImportDescriptor->FirstThunk);
|
||||
while (*ImageThunk)
|
||||
#endif
|
||||
{
|
||||
/* Do we already have an address? */
|
||||
if (DllBase)
|
||||
{
|
||||
/* Is the thunk in the same address? */
|
||||
if ((*ImageThunk >= DllBase) && (*ImageThunk < DllEnd))
|
||||
{
|
||||
/* Skip it, we already have a reference for it */
|
||||
ASSERT(EntryArray[j]);
|
||||
ImageThunk++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop the loaded module list to locate this address owner */
|
||||
j = 0;
|
||||
NextEntry2 = PsLoadedModuleList.Flink;
|
||||
while (NextEntry2 != &PsLoadedModuleList)
|
||||
{
|
||||
/* Get the entry */
|
||||
LdrEntry2 = CONTAINING_RECORD(NextEntry2,
|
||||
LDR_DATA_TABLE_ENTRY,
|
||||
InLoadOrderLinks);
|
||||
|
||||
/* Get the address range for this module */
|
||||
DllBase = (ULONG_PTR)LdrEntry2->DllBase;
|
||||
DllEnd = DllBase + LdrEntry2->SizeOfImage;
|
||||
|
||||
/* Check if this IAT entry matches it */
|
||||
if ((*ImageThunk >= DllBase) && (*ImageThunk < DllEnd))
|
||||
{
|
||||
/* Save it */
|
||||
//DPRINT1("Found imported dll: %wZ\n", &LdrEntry2->BaseDllName);
|
||||
EntryArray[j] = LdrEntry2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Keep searching */
|
||||
NextEntry2 = NextEntry2->Flink;
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Do we have a thunk outside the range? */
|
||||
if ((*ImageThunk < DllBase) || (*ImageThunk >= DllEnd))
|
||||
{
|
||||
/* Could be 0... */
|
||||
if (*ImageThunk)
|
||||
{
|
||||
/* Should not be happening */
|
||||
DPRINT1("Broken IAT entry for %p at %p (%lx)\n",
|
||||
LdrEntry, ImageThunk, *ImageThunk);
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Reset if we hit this */
|
||||
DllBase = 0;
|
||||
}
|
||||
#ifndef _WORKING_LOADER_
|
||||
ImageThunk++;
|
||||
}
|
||||
|
||||
i++;
|
||||
ImportDescriptor++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Now scan how many imports we really have */
|
||||
for (i = 0, ImportSize = 0; i < Modules; i++)
|
||||
{
|
||||
/* Skip HAL and kernel */
|
||||
if ((EntryArray[i]) &&
|
||||
(EntryArray[i] != HalEntry) &&
|
||||
(EntryArray[i] != KernelEntry))
|
||||
{
|
||||
/* A valid reference */
|
||||
LastEntry = EntryArray[i];
|
||||
ImportSize++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do we have any imports after all? */
|
||||
if (!ImportSize)
|
||||
{
|
||||
/* No */
|
||||
LdrEntry->LoadedImports = MM_SYSLDR_NO_IMPORTS;
|
||||
}
|
||||
else if (ImportSize == 1)
|
||||
{
|
||||
/* A single entry import */
|
||||
LdrEntry->LoadedImports = (PVOID)((ULONG_PTR)LastEntry | MM_SYSLDR_SINGLE_ENTRY);
|
||||
LastEntry->LoadCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We need an import table */
|
||||
LoadedImportsSize = ImportSize * sizeof(PVOID) + sizeof(SIZE_T);
|
||||
LoadedImports = ExAllocatePoolWithTag(PagedPool,
|
||||
LoadedImportsSize,
|
||||
'TDmM');
|
||||
ASSERT(LoadedImports);
|
||||
|
||||
/* Save the count */
|
||||
LoadedImports->Count = ImportSize;
|
||||
|
||||
/* Now copy all imports */
|
||||
for (i = 0, j = 0; i < Modules; i++)
|
||||
{
|
||||
/* Skip HAL and kernel */
|
||||
if ((EntryArray[i]) &&
|
||||
(EntryArray[i] != HalEntry) &&
|
||||
(EntryArray[i] != KernelEntry))
|
||||
{
|
||||
/* A valid reference */
|
||||
//DPRINT1("Found valid entry: %p\n", EntryArray[i]);
|
||||
LoadedImports->Entry[j] = EntryArray[i];
|
||||
EntryArray[i]->LoadCount++;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Should had as many entries as we expected */
|
||||
ASSERT(j == ImportSize);
|
||||
LdrEntry->LoadedImports = LoadedImports;
|
||||
}
|
||||
|
||||
/* Next */
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
/* Free the initial array */
|
||||
ExFreePool(EntryArray);
|
||||
|
||||
/* FIXME: Might not need to keep the HAL/Kernel imports around */
|
||||
|
||||
/* Kernel and HAL are loaded at boot */
|
||||
KernelEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
|
||||
HalEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
|
||||
|
||||
/* All worked well */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiLocateKernelSections(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
|
||||
{
|
||||
ULONG_PTR DllBase;
|
||||
PIMAGE_NT_HEADERS NtHeaders;
|
||||
PIMAGE_SECTION_HEADER SectionHeader;
|
||||
ULONG Sections, Size;
|
||||
|
||||
/* Get the kernel section header */
|
||||
DllBase = (ULONG_PTR)LdrEntry->DllBase;
|
||||
NtHeaders = RtlImageNtHeader((PVOID)DllBase);
|
||||
SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
|
||||
|
||||
/* Loop all the sections */
|
||||
Sections = NtHeaders->FileHeader.NumberOfSections;
|
||||
while (Sections)
|
||||
{
|
||||
/* Grab the size of the section */
|
||||
Size = max(SectionHeader->SizeOfRawData, SectionHeader->Misc.VirtualSize);
|
||||
|
||||
/* Check for .RSRC section */
|
||||
if (*(PULONG)SectionHeader->Name == 'rsr.')
|
||||
{
|
||||
/* Remember the PTEs so we can modify them later */
|
||||
MiKernelResourceStartPte = MiAddressToPte(DllBase +
|
||||
SectionHeader->VirtualAddress);
|
||||
MiKernelResourceEndPte = MiKernelResourceStartPte +
|
||||
BYTES_TO_PAGES(SectionHeader->VirtualAddress + Size);
|
||||
}
|
||||
else if (*(PULONG)SectionHeader->Name == 'LOOP')
|
||||
{
|
||||
/* POOLCODE vs. POOLMI */
|
||||
if (*(PULONG)&SectionHeader->Name[4] == 'EDOC')
|
||||
{
|
||||
/* Found Ex* Pool code */
|
||||
ExPoolCodeStart = DllBase + SectionHeader->VirtualAddress;
|
||||
ExPoolCodeEnd = ExPoolCodeStart + Size;
|
||||
}
|
||||
else if (*(PUSHORT)&SectionHeader->Name[4] == 'MI')
|
||||
{
|
||||
/* Found Mm* Pool code */
|
||||
MmPoolCodeStart = DllBase + SectionHeader->VirtualAddress;
|
||||
MmPoolCodeEnd = ExPoolCodeStart + Size;
|
||||
}
|
||||
}
|
||||
else if ((*(PULONG)SectionHeader->Name == 'YSIM') &&
|
||||
(*(PULONG)&SectionHeader->Name[4] == 'ETPS'))
|
||||
{
|
||||
/* Found MISYSPTE (Mm System PTE code)*/
|
||||
MmPteCodeStart = DllBase + SectionHeader->VirtualAddress;
|
||||
MmPteCodeEnd = ExPoolCodeStart + Size;
|
||||
}
|
||||
|
||||
/* Keep going */
|
||||
Sections--;
|
||||
SectionHeader++;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||
|
@ -1528,6 +1857,9 @@ MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
LDR_DATA_TABLE_ENTRY,
|
||||
InLoadOrderLinks);
|
||||
PsNtosImageBase = (ULONG_PTR)LdrEntry->DllBase;
|
||||
|
||||
/* Locate resource section, pool code, and system pte code */
|
||||
MiLocateKernelSections(LdrEntry);
|
||||
|
||||
/* Loop the loader block */
|
||||
while (NextEntry != ListHead)
|
||||
|
@ -1541,7 +1873,7 @@ MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
if (!RtlImageNtHeader(LdrEntry->DllBase))
|
||||
{
|
||||
/* Skip this entry */
|
||||
NextEntry= NextEntry->Flink;
|
||||
NextEntry = NextEntry->Flink;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1584,7 +1916,7 @@ MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
}
|
||||
|
||||
/* Build the import lists for the boot drivers */
|
||||
//MiBuildImportsForBootDrivers();
|
||||
MiBuildImportsForBootDrivers();
|
||||
|
||||
/* We're done */
|
||||
return TRUE;
|
||||
|
|
Loading…
Reference in a new issue