Author: sir_richard Date: Thu Apr 22 10:13:56 2010 New Revision: 46989
URL: http://svn.reactos.org/svn/reactos?rev=46989&view=rev Log: [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.
Modified: trunk/reactos/ntoskrnl/mm/sysldr.c
Modified: trunk/reactos/ntoskrnl/mm/sysldr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/sysldr.c?rev=46... ============================================================================== --- trunk/reactos/ntoskrnl/mm/sysldr.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/sysldr.c [iso-8859-1] Thu Apr 22 10:13:56 2010 @@ -46,6 +46,10 @@
BOOLEAN MmMakeLowMemory; BOOLEAN MmEnforceWriteProtection = TRUE; + +PMMPTE MiKernelResourceStartPte, MiKernelResourceEndPte; +ULONG_PTR ExPoolCodeStart, ExPoolCodeEnd, MmPoolCodeStart, MmPoolCodeEnd; +ULONG_PTR MmPteCodeStart, MmPteCodeEnd;
/* FUNCTIONS ******************************************************************/
@@ -1508,6 +1512,331 @@ } }
+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 @@ 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 @@ if (!RtlImageNtHeader(LdrEntry->DllBase)) { /* Skip this entry */ - NextEntry= NextEntry->Flink; + NextEntry = NextEntry->Flink; continue; }
@@ -1584,7 +1916,7 @@ }
/* Build the import lists for the boot drivers */ - //MiBuildImportsForBootDrivers(); + MiBuildImportsForBootDrivers();
/* We're done */ return TRUE;