[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:
Sir Richard 2010-04-22 08:13:56 +00:00
parent 0e419c8771
commit 2c0c247cc7

View file

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