diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 01dfc79fed4..cac7c7468f8 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -191,6 +191,7 @@ typedef struct _MM_IMAGE_SECTION_OBJECT USHORT Machine; BOOLEAN Executable; ULONG NrSegments; + ULONG ImageSize; PMM_SECTION_SEGMENT Segments; } MM_IMAGE_SECTION_OBJECT, *PMM_IMAGE_SECTION_OBJECT; diff --git a/reactos/ntoskrnl/mm/section.c b/reactos/ntoskrnl/mm/section.c index 821dc058446..a1157fc4ffa 100644 --- a/reactos/ntoskrnl/mm/section.c +++ b/reactos/ntoskrnl/mm/section.c @@ -4560,6 +4560,8 @@ MmMapViewOfSection(IN PVOID SectionObject, } } + ImageSectionObject->ImageSize = ImageSize; + /* Check there is enough space to map the section at that point. */ if (MmLocateMemoryAreaByRegion(AddressSpace, (PVOID)ImageBase, PAGE_ROUND_UP(ImageSize)) != NULL) diff --git a/reactos/ntoskrnl/mm/sysldr.c b/reactos/ntoskrnl/mm/sysldr.c index cb4660e4bad..c6b3d966787 100644 --- a/reactos/ntoskrnl/mm/sysldr.c +++ b/reactos/ntoskrnl/mm/sysldr.c @@ -18,9 +18,102 @@ LIST_ENTRY PsLoadedModuleList; KSPIN_LOCK PsLoadedModuleSpinLock; PVOID PsNtosImageBase; KMUTANT MmSystemLoadLock; +extern ULONG NtGlobalFlag; /* FUNCTIONS *****************************************************************/ +NTSTATUS +NTAPI +MiLoadImageSection(IN OUT PVOID *SectionPtr, + OUT PVOID *ImageBase, + IN PUNICODE_STRING FileName, + IN BOOLEAN SessionLoad, + IN PLDR_DATA_TABLE_ENTRY LdrEntry) +{ + PROS_SECTION_OBJECT Section = *SectionPtr; + NTSTATUS Status; + PEPROCESS Process; + PVOID Base = NULL; + SIZE_T ViewSize = 0; + KAPC_STATE ApcState; + LARGE_INTEGER SectionOffset = {{0}}; + BOOLEAN LoadSymbols = FALSE; + ULONG DriverSize; + PVOID DriverBase; + PAGED_CODE(); + + /* Detect session load */ + if (SessionLoad) + { + /* Fail */ + DPRINT1("Session loading not yet supported!\n"); + while (TRUE); + } + + /* Not session load, shouldn't have an entry */ + ASSERT(LdrEntry == NULL); + + /* Attach to the system process */ + KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState); + + /* Check if we need to load symbols */ + if (NtGlobalFlag & FLG_ENABLE_KDEBUG_SYMBOL_LOAD) + { + /* Yes we do */ + LoadSymbols = TRUE; + NtGlobalFlag &= ~FLG_ENABLE_KDEBUG_SYMBOL_LOAD; + } + + /* Map the driver */ + Process = PsGetCurrentProcess(); + Status = MmMapViewOfSection(Section, + Process, + &Base, + 0, + 0, + &SectionOffset, + &ViewSize, + ViewUnmap, + 0, + PAGE_EXECUTE); + + /* Re-enable the flag */ + if (LoadSymbols) NtGlobalFlag |= FLG_ENABLE_KDEBUG_SYMBOL_LOAD; + + /* Check if we failed with distinguished status code */ + if (Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) + { + /* Change it to something more generic */ + Status = STATUS_INVALID_IMAGE_FORMAT; + } + + /* Now check if we failed */ + if (!NT_SUCCESS(Status)) + { + /* Detach and return */ + KeUnstackDetachProcess(&ApcState); + return Status; + } + + /* Get the driver size */ + DriverSize = Section->ImageSection->ImageSize; + + /* Allocate a virtual section for the module */ + DriverBase = MmAllocateSection(DriverSize, NULL); + *ImageBase = DriverBase; + + /* Copy the image */ + RtlCopyMemory(DriverBase, Base, DriverSize); + + /* Now unmap the view */ + Status = MmUnmapViewOfSection(Process, Base); + ASSERT(NT_SUCCESS(Status)); + + /* Detach and return status */ + KeUnstackDetachProcess(&ApcState); + return Status; +} + NTSTATUS NTAPI MiDereferenceImports(IN PLOAD_IMPORTS ImportList) @@ -1331,11 +1424,7 @@ MmLoadSystemImage(IN PUNICODE_STRING FileName, NTSTATUS Status; HANDLE FileHandle = NULL; OBJECT_ATTRIBUTES ObjectAttributes; - FILE_STANDARD_INFORMATION FileStdInfo; IO_STATUS_BLOCK IoStatusBlock; - ULONG DriverSize = 0, Size, i; - PVOID DriverBase; - PIMAGE_SECTION_HEADER SectionHeaders; PIMAGE_NT_HEADERS NtHeader; UNICODE_STRING BaseName, BaseDirectory, PrefixName; PLDR_DATA_TABLE_ENTRY LdrEntry = NULL; @@ -1510,31 +1599,6 @@ LoaderScan: goto Quickie; } - /* Get image size */ - Status = ZwQueryInformationFile(FileHandle, - &IoStatusBlock, - &FileStdInfo, - sizeof(FileStdInfo), - FileStandardInformation); - if (!NT_SUCCESS(Status)) goto Quickie; - - /* Allocate memory for image */ - ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool, - FileStdInfo.EndOfFile.u.LowPart, - TAG_DRIVER_MEM); - - /* Read the image */ - Status = ZwReadFile(FileHandle, - 0, - 0, - 0, - &IoStatusBlock, - ModuleLoadBase, - FileStdInfo.EndOfFile.u.LowPart, - 0, - 0); - if (!NT_SUCCESS(Status)) goto Quickie; - /* Check if this is a session-load */ if (Flags) { @@ -1591,61 +1655,19 @@ LoaderScan: LdrEntry = NULL; } - /* We should have a valid module base */ - ASSERT(ModuleLoadBase != NULL); + /* Load the image */ + Status = MiLoadImageSection(&Section, + &ModuleLoadBase, + FileName, + FALSE, + NULL); + ASSERT(Status != STATUS_ALREADY_COMMITTED); - /* Get header pointers */ + /* Get the NT Header */ NtHeader = RtlImageNtHeader(ModuleLoadBase); - /* Get header pointers */ - SectionHeaders = 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 (!(SectionHeaders[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD)) - { - /* Add the size of this section into the total size */ - Size = SectionHeaders[i].VirtualAddress + - SectionHeaders[i].Misc.VirtualSize; - DriverSize = max(DriverSize, Size); - } - } - - /* Round up the driver size to section alignment */ - DriverSize = ROUND_UP(DriverSize, NtHeader->OptionalHeader.SectionAlignment); - - /* Allocate a virtual section for the module */ - DriverBase = MmAllocateSection(DriverSize, NULL); - - /* Copy headers over */ - RtlCopyMemory(DriverBase, - ModuleLoadBase, - 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 = SectionHeaders[i].VirtualAddress + - SectionHeaders[i].Misc.VirtualSize; - if ((Size <= DriverSize) && (SectionHeaders[i].SizeOfRawData)) - { - /* Copy the data from the disk to the image */ - RtlCopyMemory((PVOID)((ULONG_PTR)DriverBase + - SectionHeaders[i].VirtualAddress), - (PVOID)((ULONG_PTR)ModuleLoadBase + - SectionHeaders[i].PointerToRawData), - SectionHeaders[i].Misc.VirtualSize > - SectionHeaders[i].SizeOfRawData ? - SectionHeaders[i].SizeOfRawData : - SectionHeaders[i].Misc.VirtualSize); - } - } - /* Relocate the driver */ - Status = LdrRelocateImageWithBias(DriverBase, + Status = LdrRelocateImageWithBias(ModuleLoadBase, 0, "SYSLDR", STATUS_SUCCESS, @@ -1682,10 +1704,10 @@ LoaderScan: } /* Setup the rest of the entry */ - LdrEntry->DllBase = DriverBase; - LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)DriverBase + + LdrEntry->DllBase = ModuleLoadBase; + LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)ModuleLoadBase + NtHeader->OptionalHeader.AddressOfEntryPoint); - LdrEntry->SizeOfImage = DriverSize; + LdrEntry->SizeOfImage = ((PROS_SECTION_OBJECT)Section)->ImageSection->ImageSize; LdrEntry->CheckSum = NtHeader->OptionalHeader.CheckSum; LdrEntry->SectionPointer = LdrEntry; @@ -1729,7 +1751,7 @@ LoaderScan: /* Resolve imports */ MissingApiName = Buffer; - Status = MiResolveImageReferences(DriverBase, + Status = MiResolveImageReferences(ModuleLoadBase, &BaseDirectory, NULL, &MissingApiName, @@ -1763,9 +1785,6 @@ Quickie: /* If we have a file handle, close it */ if (FileHandle) ZwClose(FileHandle); - /* Cleanup */ - if (ModuleLoadBase) ExFreePool(ModuleLoadBase); - /* Check if we have the lock acquired */ if (LockOwned) {