/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
+#ifdef NEWCC
+#include "../cache/section/newmm.h"
+#endif
#define NDEBUG
#include <debug.h>
#include <reactos/exeformat.h>
IN HANDLE FileHandle OPTIONAL,
IN PFILE_OBJECT FileObject OPTIONAL);
+NTSTATUS
+NTAPI
+MmMapViewOfArm3Section(IN PVOID SectionObject,
+ IN PEPROCESS Process,
+ IN OUT PVOID *BaseAddress,
+ IN ULONG_PTR ZeroBits,
+ IN SIZE_T CommitSize,
+ IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
+ IN OUT PSIZE_T ViewSize,
+ IN SECTION_INHERIT InheritDisposition,
+ IN ULONG AllocationType,
+ IN ULONG Protect);
+
+//
+// PeFmtCreateSection depends on the following:
+//
+C_ASSERT(EXEFMT_LOAD_HEADER_SIZE >= sizeof(IMAGE_DOS_HEADER));
+C_ASSERT(sizeof(IMAGE_NT_HEADERS32) <= sizeof(IMAGE_NT_HEADERS64));
+
+C_ASSERT(TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) == TYPE_ALIGNMENT(IMAGE_NT_HEADERS64));
+C_ASSERT(RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader) == RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS64, FileHeader));
+C_ASSERT(FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader) == FIELD_OFFSET(IMAGE_NT_HEADERS64, OptionalHeader));
+
+C_ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, Magic));
+C_ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, SectionAlignment));
+C_ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, FileAlignment));
+C_ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, Subsystem));
+C_ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, MinorSubsystemVersion));
+C_ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, MajorSubsystemVersion));
+C_ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, AddressOfEntryPoint));
+C_ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, SizeOfCode));
+C_ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, SizeOfHeaders));
+
/* TYPES *********************************************************************/
typedef struct
POBJECT_TYPE MmSectionObjectType = NULL;
-SIZE_T MmAllocationFragment;
-
ULONG_PTR MmSubsectionBase;
+static ULONG SectionCharacteristicsToProtect[16] =
+{
+ PAGE_NOACCESS, /* 0 = NONE */
+ PAGE_NOACCESS, /* 1 = SHARED */
+ PAGE_EXECUTE, /* 2 = EXECUTABLE */
+ PAGE_EXECUTE, /* 3 = EXECUTABLE, SHARED */
+ PAGE_READONLY, /* 4 = READABLE */
+ PAGE_READONLY, /* 5 = READABLE, SHARED */
+ PAGE_EXECUTE_READ, /* 6 = READABLE, EXECUTABLE */
+ PAGE_EXECUTE_READ, /* 7 = READABLE, EXECUTABLE, SHARED */
+ /*
+ * FIXME? do we really need the WriteCopy field in segments? can't we use
+ * PAGE_WRITECOPY here?
+ */
+ PAGE_READWRITE, /* 8 = WRITABLE */
+ PAGE_READWRITE, /* 9 = WRITABLE, SHARED */
+ PAGE_EXECUTE_READWRITE, /* 10 = WRITABLE, EXECUTABLE */
+ PAGE_EXECUTE_READWRITE, /* 11 = WRITABLE, EXECUTABLE, SHARED */
+ PAGE_READWRITE, /* 12 = WRITABLE, READABLE */
+ PAGE_READWRITE, /* 13 = WRITABLE, READABLE, SHARED */
+ PAGE_EXECUTE_READWRITE, /* 14 = WRITABLE, READABLE, EXECUTABLE */
+ PAGE_EXECUTE_READWRITE, /* 15 = WRITABLE, READABLE, EXECUTABLE, SHARED */
+};
+
static GENERIC_MAPPING MmpSectionMapping = {
STANDARD_RIGHTS_READ | SECTION_MAP_READ | SECTION_QUERY,
STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE,
#define SHARE_COUNT_FROM_SSE(E) (((E) & 0x00000FFE) >> 1)
#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
#define MAX_SHARE_COUNT 0x7FF
-#define MAKE_SSE(P, C) ((P) | ((C) << 1))
+#define MAKE_SSE(P, C) ((ULONG)(P) | ((C) << 1))
#define SWAPENTRY_FROM_SSE(E) ((E) >> 1)
-#define MAKE_SWAP_SSE(S) (((S) << 1) | 0x1)
+#define MAKE_SWAP_SSE(S) (((ULONG)(S) << 1) | 0x1)
static const INFORMATION_CLASS_INFO ExSectionInfoClass[] =
{
/* FUNCTIONS *****************************************************************/
-PFILE_OBJECT
-NTAPI
-MmGetFileObjectForSection(IN PROS_SECTION_OBJECT Section)
+
+/*
+ References:
+ [1] Microsoft Corporation, "Microsoft Portable Executable and Common Object
+ File Format Specification", revision 6.0 (February 1999)
+*/
+NTSTATUS NTAPI PeFmtCreateSection(IN CONST VOID * FileHeader,
+ IN SIZE_T FileHeaderSize,
+ IN PVOID File,
+ OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
+ OUT PULONG Flags,
+ IN PEXEFMT_CB_READ_FILE ReadFileCb,
+ IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb)
{
- PAGED_CODE();
- ASSERT(Section);
+ NTSTATUS nStatus;
+ ULONG cbFileHeaderOffsetSize = 0;
+ ULONG cbSectionHeadersOffset = 0;
+ ULONG cbSectionHeadersSize;
+ ULONG cbSectionHeadersOffsetSize = 0;
+ ULONG cbOptHeaderSize;
+ ULONG cbHeadersSize = 0;
+ ULONG nSectionAlignment;
+ ULONG nFileAlignment;
+ const IMAGE_DOS_HEADER * pidhDosHeader;
+ const IMAGE_NT_HEADERS32 * pinhNtHeader;
+ const IMAGE_OPTIONAL_HEADER32 * piohOptHeader;
+ const IMAGE_SECTION_HEADER * pishSectionHeaders;
+ PMM_SECTION_SEGMENT pssSegments;
+ LARGE_INTEGER lnOffset;
+ PVOID pBuffer;
+ SIZE_T nPrevVirtualEndOfSegment = 0;
+ ULONG nFileSizeOfHeaders = 0;
+ ULONG i;
+
+ ASSERT(FileHeader);
+ ASSERT(FileHeaderSize > 0);
+ ASSERT(File);
+ ASSERT(ImageSectionObject);
+ ASSERT(ReadFileCb);
+ ASSERT(AllocateSegmentsCb);
+
+ ASSERT(Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize));
+
+ ASSERT(((UINT_PTR)FileHeader % TYPE_ALIGNMENT(IMAGE_DOS_HEADER)) == 0);
+
+#define DIE(ARGS_) { DPRINT ARGS_; goto l_Return; }
+
+ pBuffer = NULL;
+ pidhDosHeader = FileHeader;
+
+ /* DOS HEADER */
+ nStatus = STATUS_ROS_EXEFMT_UNKNOWN_FORMAT;
+
+ /* image too small to be an MZ executable */
+ if(FileHeaderSize < sizeof(IMAGE_DOS_HEADER))
+ DIE(("Too small to be an MZ executable, size is %lu\n", FileHeaderSize));
+
+ /* no MZ signature */
+ if(pidhDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+ DIE(("No MZ signature found, e_magic is %hX\n", pidhDosHeader->e_magic));
+
+ /* not a Windows executable */
+ if(pidhDosHeader->e_lfanew <= 0)
+ DIE(("Not a Windows executable, e_lfanew is %d\n", pidhDosHeader->e_lfanew));
+
+ /* NT HEADER */
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
+
+ if(!Intsafe_AddULong32(&cbFileHeaderOffsetSize, pidhDosHeader->e_lfanew, RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader)))
+ DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
+
+ if(FileHeaderSize < cbFileHeaderOffsetSize)
+ pinhNtHeader = NULL;
+ else
+ {
+ /*
+ * we already know that Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize),
+ * and FileHeaderSize >= cbFileHeaderOffsetSize, so this holds true too
+ */
+ ASSERT(Intsafe_CanOffsetPointer(FileHeader, pidhDosHeader->e_lfanew));
+ pinhNtHeader = (PVOID)((UINT_PTR)FileHeader + pidhDosHeader->e_lfanew);
+ }
- /* Return the file object */
- return Section->FileObject; // Section->ControlArea->FileObject on NT
-}
+ /*
+ * the buffer doesn't contain the NT file header, or the alignment is wrong: we
+ * need to read the header from the file
+ */
+ if(FileHeaderSize < cbFileHeaderOffsetSize ||
+ (UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
+ {
+ ULONG cbNtHeaderSize;
+ ULONG cbReadSize;
+ PVOID pData;
-NTSTATUS
-NTAPI
-MmGetFileNameForSection(IN PROS_SECTION_OBJECT Section,
- OUT POBJECT_NAME_INFORMATION *ModuleName)
-{
- POBJECT_NAME_INFORMATION ObjectNameInfo;
- NTSTATUS Status;
- ULONG ReturnLength;
+l_ReadHeaderFromFile:
+ cbNtHeaderSize = 0;
+ lnOffset.QuadPart = pidhDosHeader->e_lfanew;
+
+ /* read the header from the file */
+ nStatus = ReadFileCb(File, &lnOffset, sizeof(IMAGE_NT_HEADERS64), &pData, &pBuffer, &cbReadSize);
+
+ if(!NT_SUCCESS(nStatus))
+ DIE(("ReadFile failed, status %08X\n", nStatus));
+
+ ASSERT(pData);
+ ASSERT(pBuffer);
+ ASSERT(cbReadSize > 0);
+
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
+
+ /* the buffer doesn't contain the file header */
+ if(cbReadSize < RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader))
+ DIE(("The file doesn't contain the PE file header\n"));
+
+ pinhNtHeader = pData;
- /* Make sure it's an image section */
- *ModuleName = NULL;
- if (!(Section->AllocationAttributes & SEC_IMAGE))
+ /* object still not aligned: copy it to the beginning of the buffer */
+ if((UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
+ {
+ ASSERT((UINT_PTR)pBuffer % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) == 0);
+ RtlMoveMemory(pBuffer, pData, cbReadSize);
+ pinhNtHeader = pBuffer;
+ }
+
+ /* invalid NT header */
+ nStatus = STATUS_INVALID_IMAGE_PROTECT;
+
+ if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
+ DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
+
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
+
+ if(!Intsafe_AddULong32(&cbNtHeaderSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
+ DIE(("The full NT header is too large\n"));
+
+ /* the buffer doesn't contain the whole NT header */
+ if(cbReadSize < cbNtHeaderSize)
+ DIE(("The file doesn't contain the full NT header\n"));
+ }
+ else
{
- /* It's not, fail */
- return STATUS_SECTION_NOT_IMAGE;
+ ULONG cbOptHeaderOffsetSize = 0;
+
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
+
+ /* don't trust an invalid NT header */
+ if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
+ DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
+
+ if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
+ DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
+
+ if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, cbOptHeaderOffsetSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
+ DIE(("The NT header is too large, SizeOfOptionalHeader is %X\n", pinhNtHeader->FileHeader.SizeOfOptionalHeader));
+
+ /* the buffer doesn't contain the whole NT header: read it from the file */
+ if(cbOptHeaderOffsetSize > FileHeaderSize)
+ goto l_ReadHeaderFromFile;
}
- /* Allocate memory for our structure */
- ObjectNameInfo = ExAllocatePoolWithTag(PagedPool,
- 1024,
- ' mM');
- if (!ObjectNameInfo) return STATUS_NO_MEMORY;
-
- /* Query the name */
- Status = ObQueryNameString(Section->FileObject,
- ObjectNameInfo,
- 1024,
- &ReturnLength);
- if (!NT_SUCCESS(Status))
+ /* read information from the NT header */
+ piohOptHeader = &pinhNtHeader->OptionalHeader;
+ cbOptHeaderSize = pinhNtHeader->FileHeader.SizeOfOptionalHeader;
+
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
+
+ if(!RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Magic))
+ DIE(("The optional header doesn't contain the Magic field, SizeOfOptionalHeader is %X\n", cbOptHeaderSize));
+
+ /* ASSUME: RtlZeroMemory(ImageSectionObject, sizeof(*ImageSectionObject)); */
+
+ switch(piohOptHeader->Magic)
{
- /* Failed, free memory */
- ExFreePoolWithTag(ObjectNameInfo, ' mM');
- return Status;
+ case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+ break;
+
+ default:
+ DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
}
- /* Success */
- *ModuleName = ObjectNameInfo;
- return STATUS_SUCCESS;
-}
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SectionAlignment) &&
+ RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, FileAlignment))
+ {
+ /* See [1], section 3.4.2 */
+ if(piohOptHeader->SectionAlignment < PAGE_SIZE)
+ {
+ if(piohOptHeader->FileAlignment != piohOptHeader->SectionAlignment)
+ DIE(("Sections aren't page-aligned and the file alignment isn't the same\n"));
+ }
+ else if(piohOptHeader->SectionAlignment < piohOptHeader->FileAlignment)
+ DIE(("The section alignment is smaller than the file alignment\n"));
+
+ nSectionAlignment = piohOptHeader->SectionAlignment;
+ nFileAlignment = piohOptHeader->FileAlignment;
+
+ if(!IsPowerOf2(nSectionAlignment) || !IsPowerOf2(nFileAlignment))
+ DIE(("The section alignment (%u) and file alignment (%u) aren't both powers of 2\n", nSectionAlignment, nFileAlignment));
+ }
+ else
+ {
+ nSectionAlignment = PAGE_SIZE;
+ nFileAlignment = PAGE_SIZE;
+ }
-NTSTATUS
-NTAPI
-MmGetFileNameForAddress(IN PVOID Address,
- OUT PUNICODE_STRING ModuleName)
-{
- PROS_SECTION_OBJECT Section;
- PMEMORY_AREA MemoryArea;
- PMMSUPPORT AddressSpace;
- POBJECT_NAME_INFORMATION ModuleNameInformation;
- NTSTATUS Status = STATUS_ADDRESS_NOT_ASSOCIATED;
+ ASSERT(IsPowerOf2(nSectionAlignment));
+ ASSERT(IsPowerOf2(nFileAlignment));
- /* Get the MM_AVL_TABLE from EPROCESS */
- if (Address >= MmSystemRangeStart)
- {
- AddressSpace = MmGetKernelAddressSpace();
- }
- else
- {
- AddressSpace = &PsGetCurrentProcess()->Vm;
- }
+ switch(piohOptHeader->Magic)
+ {
+ /* PE32 */
+ case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+ {
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, ImageBase))
+ ImageSectionObject->ImageBase = piohOptHeader->ImageBase;
- /* Lock address space */
- MmLockAddressSpace(AddressSpace);
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfImage))
+ ImageSectionObject->ImageSize = piohOptHeader->SizeOfImage;
- /* Locate the memory area for the process by address */
- MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackReserve))
+ ImageSectionObject->StackReserve = piohOptHeader->SizeOfStackReserve;
- /* Make sure it's a section view type */
- if ((MemoryArea != NULL) && (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW))
- {
- /* Get the section pointer to the SECTION_OBJECT */
- Section = MemoryArea->Data.SectionData.Section;
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackCommit))
+ ImageSectionObject->StackCommit = piohOptHeader->SizeOfStackCommit;
- /* Unlock address space */
- MmUnlockAddressSpace(AddressSpace);
+ break;
+ }
- /* Get the filename of the section */
- Status = MmGetFileNameForSection(Section,&ModuleNameInformation);
+ /* PE32+ */
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+ {
+ const IMAGE_OPTIONAL_HEADER64 * pioh64OptHeader;
- if (NT_SUCCESS(Status))
- {
- /* Init modulename */
- RtlCreateUnicodeString(ModuleName,
- ModuleNameInformation->Name.Buffer);
-
- /* Free temp taged buffer from MmGetFileNameForSection() */
- ExFreePoolWithTag(ModuleNameInformation, ' mM');
- DPRINT("Found ModuleName %S by address %p\n",
- ModuleName->Buffer,Address);
- }
- }
- else
- {
- /* Unlock address space */
- MmUnlockAddressSpace(AddressSpace);
- }
+ pioh64OptHeader = (const IMAGE_OPTIONAL_HEADER64 *)piohOptHeader;
- return Status;
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, ImageBase))
+ {
+ if(pioh64OptHeader->ImageBase > MAXULONG_PTR)
+ DIE(("ImageBase exceeds the address space\n"));
+
+ ImageSectionObject->ImageBase = (ULONG_PTR)pioh64OptHeader->ImageBase;
+ }
+
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfImage))
+ {
+ if(pioh64OptHeader->SizeOfImage > MAXULONG_PTR)
+ DIE(("SizeOfImage exceeds the address space\n"));
+
+ ImageSectionObject->ImageSize = pioh64OptHeader->SizeOfImage;
+ }
+
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackReserve))
+ {
+ if(pioh64OptHeader->SizeOfStackReserve > MAXULONG_PTR)
+ DIE(("SizeOfStackReserve exceeds the address space\n"));
+
+ ImageSectionObject->StackReserve = (ULONG_PTR)pioh64OptHeader->SizeOfStackReserve;
+ }
+
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackCommit))
+ {
+ if(pioh64OptHeader->SizeOfStackCommit > MAXULONG_PTR)
+ DIE(("SizeOfStackCommit exceeds the address space\n"));
+
+ ImageSectionObject->StackCommit = (ULONG_PTR)pioh64OptHeader->SizeOfStackCommit;
+ }
+
+ break;
+ }
+ }
+
+ /* [1], section 3.4.2 */
+ if((ULONG_PTR)ImageSectionObject->ImageBase % 0x10000)
+ DIE(("ImageBase is not aligned on a 64KB boundary"));
+
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Subsystem))
+ {
+ ImageSectionObject->Subsystem = piohOptHeader->Subsystem;
+
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
+ RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MajorSubsystemVersion))
+ {
+ ImageSectionObject->MinorSubsystemVersion = piohOptHeader->MinorSubsystemVersion;
+ ImageSectionObject->MajorSubsystemVersion = piohOptHeader->MajorSubsystemVersion;
+ }
+ }
+
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
+ {
+ ImageSectionObject->EntryPoint = piohOptHeader->ImageBase +
+ piohOptHeader->AddressOfEntryPoint;
+ }
+
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfCode))
+ ImageSectionObject->Executable = piohOptHeader->SizeOfCode != 0;
+ else
+ ImageSectionObject->Executable = TRUE;
+
+ ImageSectionObject->ImageCharacteristics = pinhNtHeader->FileHeader.Characteristics;
+ ImageSectionObject->Machine = pinhNtHeader->FileHeader.Machine;
+
+ /* SECTION HEADERS */
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
+
+ /* see [1], section 3.3 */
+ if(pinhNtHeader->FileHeader.NumberOfSections > 96)
+ DIE(("Too many sections, NumberOfSections is %u\n", pinhNtHeader->FileHeader.NumberOfSections));
+
+ /*
+ * the additional segment is for the file's headers. They need to be present for
+ * the benefit of the dynamic loader (to locate exports, defaults for thread
+ * parameters, resources, etc.)
+ */
+ ImageSectionObject->NrSegments = pinhNtHeader->FileHeader.NumberOfSections + 1;
+
+ /* file offset for the section headers */
+ if(!Intsafe_AddULong32(&cbSectionHeadersOffset, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
+ DIE(("Offset overflow\n"));
+
+ if(!Intsafe_AddULong32(&cbSectionHeadersOffset, cbSectionHeadersOffset, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
+ DIE(("Offset overflow\n"));
+
+ /* size of the section headers */
+ ASSERT(Intsafe_CanMulULong32(pinhNtHeader->FileHeader.NumberOfSections, sizeof(IMAGE_SECTION_HEADER)));
+ cbSectionHeadersSize = pinhNtHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
+
+ if(!Intsafe_AddULong32(&cbSectionHeadersOffsetSize, cbSectionHeadersOffset, cbSectionHeadersSize))
+ DIE(("Section headers too large\n"));
+
+ /* size of the executable's headers */
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfHeaders))
+ {
+// if(!IsAligned(piohOptHeader->SizeOfHeaders, nFileAlignment))
+// DIE(("SizeOfHeaders is not aligned\n"));
+
+ if(cbSectionHeadersSize > piohOptHeader->SizeOfHeaders)
+ DIE(("The section headers overflow SizeOfHeaders\n"));
+
+ cbHeadersSize = piohOptHeader->SizeOfHeaders;
+ }
+ else if(!AlignUp(&cbHeadersSize, cbSectionHeadersOffsetSize, nFileAlignment))
+ DIE(("Overflow aligning the size of headers\n"));
+
+ if(pBuffer)
+ {
+ ExFreePool(pBuffer);
+ pBuffer = NULL;
+ }
+ /* WARNING: pinhNtHeader IS NO LONGER USABLE */
+ /* WARNING: piohOptHeader IS NO LONGER USABLE */
+ /* WARNING: pioh64OptHeader IS NO LONGER USABLE */
+
+ if(FileHeaderSize < cbSectionHeadersOffsetSize)
+ pishSectionHeaders = NULL;
+ else
+ {
+ /*
+ * we already know that Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize),
+ * and FileHeaderSize >= cbSectionHeadersOffsetSize, so this holds true too
+ */
+ ASSERT(Intsafe_CanOffsetPointer(FileHeader, cbSectionHeadersOffset));
+ pishSectionHeaders = (PVOID)((UINT_PTR)FileHeader + cbSectionHeadersOffset);
+ }
+
+ /*
+ * the buffer doesn't contain the section headers, or the alignment is wrong:
+ * read the headers from the file
+ */
+ if(FileHeaderSize < cbSectionHeadersOffsetSize ||
+ (UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
+ {
+ PVOID pData;
+ ULONG cbReadSize;
+
+ lnOffset.QuadPart = cbSectionHeadersOffset;
+
+ /* read the header from the file */
+ nStatus = ReadFileCb(File, &lnOffset, cbSectionHeadersSize, &pData, &pBuffer, &cbReadSize);
+
+ if(!NT_SUCCESS(nStatus))
+ DIE(("ReadFile failed with status %08X\n", nStatus));
+
+ ASSERT(pData);
+ ASSERT(pBuffer);
+ ASSERT(cbReadSize > 0);
+
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
+
+ /* the buffer doesn't contain all the section headers */
+ if(cbReadSize < cbSectionHeadersSize)
+ DIE(("The file doesn't contain all of the section headers\n"));
+
+ pishSectionHeaders = pData;
+
+ /* object still not aligned: copy it to the beginning of the buffer */
+ if((UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
+ {
+ ASSERT((UINT_PTR)pBuffer % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) == 0);
+ RtlMoveMemory(pBuffer, pData, cbReadSize);
+ pishSectionHeaders = pBuffer;
+ }
+ }
+
+ /* SEGMENTS */
+ /* allocate the segments */
+ nStatus = STATUS_INSUFFICIENT_RESOURCES;
+ ImageSectionObject->Segments = AllocateSegmentsCb(ImageSectionObject->NrSegments);
+
+ if(ImageSectionObject->Segments == NULL)
+ DIE(("AllocateSegments failed\n"));
+
+ /* initialize the headers segment */
+ pssSegments = ImageSectionObject->Segments;
+
+// ASSERT(IsAligned(cbHeadersSize, nFileAlignment));
+
+ if(!AlignUp(&nFileSizeOfHeaders, cbHeadersSize, nFileAlignment))
+ DIE(("Cannot align the size of the section headers\n"));
+
+ nPrevVirtualEndOfSegment = ALIGN_UP_BY(cbHeadersSize, nSectionAlignment);
+ if (nPrevVirtualEndOfSegment < cbHeadersSize)
+ DIE(("Cannot align the size of the section headers\n"));
+
+ pssSegments[0].FileOffset = 0;
+ pssSegments[0].Protection = PAGE_READONLY;
+ pssSegments[0].Length = nPrevVirtualEndOfSegment;
+ pssSegments[0].RawLength = nFileSizeOfHeaders;
+ pssSegments[0].VirtualAddress = 0;
+ pssSegments[0].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA;
+ pssSegments[0].WriteCopy = TRUE;
+
+ /* skip the headers segment */
+ ++ pssSegments;
+
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
+
+ /* convert the executable sections into segments. See also [1], section 4 */
+ for(i = 0; i < ImageSectionObject->NrSegments - 1; ++ i)
+ {
+ ULONG nCharacteristics;
+
+ /* validate the alignment */
+ if(!IsAligned(pishSectionHeaders[i].VirtualAddress, nSectionAlignment))
+ DIE(("VirtualAddress[%u] is not aligned\n", i));
+
+ /* sections must be contiguous, ordered by base address and non-overlapping */
+ if(pishSectionHeaders[i].VirtualAddress != nPrevVirtualEndOfSegment)
+ DIE(("Memory gap between section %u and the previous\n", i));
+
+ /* ignore explicit BSS sections */
+ if(pishSectionHeaders[i].SizeOfRawData != 0)
+ {
+ /* validate the alignment */
+#if 0
+ /* Yes, this should be a multiple of FileAlignment, but there's
+ * stuff out there that isn't. We can cope with that
+ */
+ if(!IsAligned(pishSectionHeaders[i].SizeOfRawData, nFileAlignment))
+ DIE(("SizeOfRawData[%u] is not aligned\n", i));
+#endif
+
+// if(!IsAligned(pishSectionHeaders[i].PointerToRawData, nFileAlignment))
+// DIE(("PointerToRawData[%u] is not aligned\n", i));
+
+ /* conversion */
+ pssSegments[i].FileOffset = pishSectionHeaders[i].PointerToRawData;
+ pssSegments[i].RawLength = pishSectionHeaders[i].SizeOfRawData;
+ }
+ else
+ {
+ ASSERT(pssSegments[i].FileOffset == 0);
+ ASSERT(pssSegments[i].RawLength == 0);
+ }
+
+ ASSERT(Intsafe_CanAddLong64(pssSegments[i].FileOffset, pssSegments[i].RawLength));
+
+ nCharacteristics = pishSectionHeaders[i].Characteristics;
+
+ /* no explicit protection */
+ if((nCharacteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)) == 0)
+ {
+ if(nCharacteristics & IMAGE_SCN_CNT_CODE)
+ nCharacteristics |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;
+
+ if(nCharacteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
+ nCharacteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
+
+ if(nCharacteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ nCharacteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
+ }
+
+ /* see table above */
+ pssSegments[i].Protection = SectionCharacteristicsToProtect[nCharacteristics >> 28];
+ pssSegments[i].WriteCopy = !(nCharacteristics & IMAGE_SCN_MEM_SHARED);
+
+ if(pishSectionHeaders[i].Misc.VirtualSize == 0 || pishSectionHeaders[i].Misc.VirtualSize < pishSectionHeaders[i].SizeOfRawData)
+ pssSegments[i].Length = pishSectionHeaders[i].SizeOfRawData;
+ else
+ pssSegments[i].Length = pishSectionHeaders[i].Misc.VirtualSize;
+
+ pssSegments[i].Length = ALIGN_UP_BY(pssSegments[i].Length, nSectionAlignment);
+ if (pssSegments[i].Length < pssSegments[i].Length)
+ DIE(("Cannot align the virtual size of section %u\n", i));
+
+ if(pssSegments[i].Length == 0)
+ DIE(("Virtual size of section %u is null\n", i));
+
+ pssSegments[i].VirtualAddress = pishSectionHeaders[i].VirtualAddress;
+ pssSegments[i].Characteristics = pishSectionHeaders[i].Characteristics;
+
+ /* ensure the memory image is no larger than 4GB */
+ nPrevVirtualEndOfSegment = pssSegments[i].VirtualAddress + pssSegments[i].Length;
+ if (nPrevVirtualEndOfSegment < pssSegments[i].VirtualAddress)
+ DIE(("The image is too large\n"));
+ }
+
+ if(nSectionAlignment >= PAGE_SIZE)
+ *Flags |= EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED;
+
+ /* Success */
+ nStatus = STATUS_ROS_EXEFMT_LOADED_FORMAT | EXEFMT_LOADED_PE32;
+
+l_Return:
+ if(pBuffer)
+ ExFreePool(pBuffer);
+
+ return nStatus;
}
/* Note: Mmsp prefix denotes "Memory Manager Section Private". */
* ARGUMENTS: PFILE_OBJECT to wait for.
* RETURNS: Status of the wait.
*/
-static NTSTATUS
+NTSTATUS
MmspWaitForFileLock(PFILE_OBJECT File)
{
return STATUS_SUCCESS;
VOID
NTAPI
MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
- ULONG Offset,
- ULONG Entry)
+ ULONG_PTR Offset,
+ ULONG_PTR Entry)
{
PSECTION_PAGE_TABLE Table;
- ULONG DirectoryOffset;
- ULONG TableOffset;
+ ULONG_PTR DirectoryOffset;
+ ULONG_PTR TableOffset;
if (Segment->Length <= NR_SECTION_PAGE_TABLES * PAGE_SIZE)
{
}
}
TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
- Table->Entry[TableOffset] = Entry;
+ Table->Entry[TableOffset] = (ULONG)Entry;
}
ULONG
NTAPI
MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
- ULONG Offset)
+ ULONG_PTR Offset)
{
PSECTION_PAGE_TABLE Table;
ULONG Entry;
- ULONG DirectoryOffset;
- ULONG TableOffset;
+ ULONG_PTR DirectoryOffset;
+ ULONG_PTR TableOffset;
DPRINT("MmGetPageEntrySection(Segment %x, Offset %x)\n", Segment, Offset);
VOID
NTAPI
MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
- ULONG Offset)
+ ULONG_PTR Offset)
{
ULONG Entry;
NTSTATUS Status;
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
IsDirectMapped = TRUE;
+#ifndef NEWCC
Status = CcRosUnmapCacheSegment(Bcb, FileOffset, Dirty);
+#else
+ Status = STATUS_SUCCESS;
+#endif
if (!NT_SUCCESS(Status))
{
DPRINT1("CcRosUnmapCacheSegment failed, status = %x\n", Status);
BOOLEAN MiIsPageFromCache(PMEMORY_AREA MemoryArea,
ULONG SegOffset)
{
+#ifndef NEWCC
if (!(MemoryArea->Data.SectionData.Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
{
PBCB Bcb;
return TRUE;
}
}
+#endif
return FALSE;
}
PEPROCESS Process;
KIRQL Irql;
PVOID TempAddress;
-
+
Process = PsGetCurrentProcess();
TempAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
if (TempAddress == NULL)
return(STATUS_SUCCESS);
}
+#ifndef NEWCC
NTSTATUS
NTAPI
MiReadPage(PMEMORY_AREA MemoryArea,
- ULONG SegOffset,
+ ULONG_PTR SegOffset,
PPFN_NUMBER Page)
/*
* FUNCTION: Read a page for a section backed memory area.
*/
{
ULONG BaseOffset;
- ULONG FileOffset;
+ ULONG_PTR FileOffset;
PVOID BaseAddress;
BOOLEAN UptoDate;
PCACHE_SEGMENT CacheSeg;
PFILE_OBJECT FileObject;
NTSTATUS Status;
- ULONG RawLength;
+ ULONG_PTR RawLength;
PBCB Bcb;
BOOLEAN IsImageSection;
- ULONG Length;
+ ULONG_PTR Length;
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
* alignment less than the file system block size.
*/
Status = CcRosGetCacheSegment(Bcb,
- FileOffset,
+ (ULONG)FileOffset,
&BaseOffset,
&BaseAddress,
&UptoDate,
PEPROCESS Process;
KIRQL Irql;
PVOID PageAddr;
- ULONG CacheSegOffset;
+ ULONG_PTR CacheSegOffset;
/*
* Allocate a page, this is rather complicated by the possibility
* we might have to move other things out of memory
*/
+ MI_SET_USAGE(MI_USAGE_SECTION);
+ MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, Page);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = CcRosGetCacheSegment(Bcb,
- FileOffset,
+ (ULONG)FileOffset,
&BaseOffset,
&BaseAddress,
&UptoDate,
MiUnmapPageInHyperSpace(Process, PageAddr, Irql);
CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
Status = CcRosGetCacheSegment(Bcb,
- FileOffset + CacheSegOffset,
+ (ULONG)(FileOffset + CacheSegOffset),
&BaseOffset,
&BaseAddress,
&UptoDate,
}
return(STATUS_SUCCESS);
}
+#else
+NTSTATUS
+NTAPI
+MiReadPage(PMEMORY_AREA MemoryArea,
+ ULONG SegOffset,
+ PPFN_NUMBER Page)
+/*
+ * FUNCTION: Read a page for a section backed memory area.
+ * PARAMETERS:
+ * MemoryArea - Memory area to read the page for.
+ * Offset - Offset of the page to read.
+ * Page - Variable that receives a page contains the read data.
+ */
+{
+ MM_REQUIRED_RESOURCES Resources = { };
+
+ Resources.Context = MemoryArea->Data.SectionData.Section->FileObject;
+ Resources.FileOffset.QuadPart = SegOffset +
+ MemoryArea->Data.SectionData.Segment->FileOffset;
+ Resources.Consumer = MC_USER;
+ Resources.Amount = PAGE_SIZE;
+
+ DPRINT1("%S, offset %x, len %d, page %x\n", ((PFILE_OBJECT)Resources.Context)->FileName.Buffer, Resources.FileOffset.LowPart, Resources.Amount, Resources.Page[0]);
+
+ NTSTATUS Status = MiReadFilePage(NULL, NULL, &Resources);
+ *Page = Resources.Page[0];
+ return Status;
+}
+#endif
NTSTATUS
NTAPI
MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
- PVOID Address,
- BOOLEAN Locked)
+ PVOID Address)
{
ULONG Offset;
PFN_NUMBER Page;
NTSTATUS Status;
- PVOID PAddress;
PROS_SECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
- ULONG Entry;
- ULONG Entry1;
+ ULONG_PTR Entry;
+ ULONG_PTR Entry1;
ULONG Attributes;
PMM_PAGEOP PageOp;
PMM_REGION Region;
BOOLEAN HasSwapEntry;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-
+
/*
* There is a window between taking the page fault and locking the
* address space when another thread could load the page so we check
{
return(STATUS_SUCCESS);
}
+
+ /*
+ * Check for the virtual memory area being deleted.
+ */
+ if (MemoryArea->DeleteInProgress)
+ {
+ return(STATUS_UNSUCCESSFUL);
+ }
- PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
- Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress
- + MemoryArea->Data.SectionData.ViewOffset;
+ Address = MM_ROUND_DOWN(Address, PAGE_SIZE);
+ Offset = (ULONG)((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset);
Segment = MemoryArea->Data.SectionData.Segment;
Section = MemoryArea->Data.SectionData.Section;
/*
* Check if this page needs to be mapped COW
*/
- if ((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) &&
+ if ((Segment->WriteCopy) &&
(Region->Protect == PAGE_READWRITE ||
Region->Protect == PAGE_EXECUTE_READWRITE))
{
if (!MmIsPagePresent(Process, Address))
{
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
- HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress);
+ HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)Address);
if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry)
{
DPRINT1("Unable to create virtual mapping\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
- MmInsertRmap(Page, Process, (PVOID)PAddress);
+ MmInsertRmap(Page, Process, Address);
}
MmUnlockSectionSegment(Segment);
PageOp->Status = STATUS_SUCCESS;
return(STATUS_SUCCESS);
}
- HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress);
+ HasSwapEntry = MmIsPageSwapEntry(Process, Address);
if (HasSwapEntry)
{
/*
}
MmUnlockSectionSegment(Segment);
- MmDeletePageFileMapping(Process, (PVOID)PAddress, &SwapEntry);
+ MmDeletePageFileMapping(Process, Address, &SwapEntry);
MmUnlockAddressSpace(AddressSpace);
+ MI_SET_USAGE(MI_USAGE_SECTION);
+ if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+ if (!Process) MI_SET_PROCESS2("Kernel Section");
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
if (!NT_SUCCESS(Status))
{
/*
* Add the page to the process's working set
*/
- MmInsertRmap(Page, Process, (PVOID)PAddress);
-
+ MmInsertRmap(Page, Process, Address);
/*
* Finish the operation
*/
if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
{
MmUnlockSectionSegment(Segment);
+ MI_SET_USAGE(MI_USAGE_SECTION);
+ if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+ if (!Process) MI_SET_PROCESS2("Kernel Section");
Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
if (!NT_SUCCESS(Status))
{
KeBugCheck(MEMORY_MANAGEMENT);
return(Status);
}
- MmInsertRmap(Page, Process, (PVOID)PAddress);
+ MmInsertRmap(Page, Process, Address);
/*
* Cleanup and release locks
if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
(Offset >= PAGE_ROUND_UP(Segment->RawLength) && Section->AllocationAttributes & SEC_IMAGE))
{
+ MI_SET_USAGE(MI_USAGE_SECTION);
+ if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+ if (!Process) MI_SET_PROCESS2("Kernel Section");
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
if (!NT_SUCCESS(Status))
{
DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status);
}
+
}
else
{
if (Entry != Entry1)
{
DPRINT1("Someone changed ppte entry while we slept\n");
- KeBugCheck(MEMORY_MANAGEMENT);
+ KeBugCheck(MEMORY_MANAGEMENT);
}
/*
DPRINT1("Unable to create virtual mapping\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
- MmInsertRmap(Page, Process, (PVOID)PAddress);
+ MmInsertRmap(Page, Process, Address);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
-
+ MI_SET_USAGE(MI_USAGE_SECTION);
+ if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+ if (!Process) MI_SET_PROCESS2("Kernel Section");
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
if (!NT_SUCCESS(Status))
{
DPRINT1("Unable to create virtual mapping\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
- MmInsertRmap(Page, Process, (PVOID)PAddress);
+ MmInsertRmap(Page, Process, Address);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address);
DPRINT1("Unable to create virtual mapping\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
- MmInsertRmap(Page, Process, (PVOID)PAddress);
+ MmInsertRmap(Page, Process, Address);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address);
NTAPI
MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
- PVOID Address,
- BOOLEAN Locked)
+ PVOID Address)
{
PMM_SECTION_SEGMENT Segment;
PROS_SECTION_OBJECT Section;
PFN_NUMBER OldPage;
PFN_NUMBER NewPage;
NTSTATUS Status;
- PVOID PAddress;
ULONG Offset;
PMM_PAGEOP PageOp;
PMM_REGION Region;
ULONG Entry;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-
- DPRINT("MmAccessFaultSectionView(%x, %x, %x, %x)\n", AddressSpace, MemoryArea, Address, Locked);
+
+ DPRINT("MmAccessFaultSectionView(%x, %x, %x, %x)\n", AddressSpace, MemoryArea, Address);
/*
- * Check if the page has been paged out or has already been set readwrite
+ * Check if the page has already been set readwrite
*/
- if (!MmIsPagePresent(Process, Address) ||
- MmGetPageProtect(Process, Address) & PAGE_READWRITE)
+ if (MmGetPageProtect(Process, Address) & PAGE_READWRITE)
{
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
/*
* Find the offset of the page
*/
- PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
- Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress
- + MemoryArea->Data.SectionData.ViewOffset;
+ Address = MM_ROUND_DOWN(Address, PAGE_SIZE);
+ Offset = (ULONG)((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset);
Segment = MemoryArea->Data.SectionData.Segment;
Section = MemoryArea->Data.SectionData.Section;
*/
MmLockSectionSegment(Segment);
- OldPage = MmGetPfnForProcess(NULL, Address);
+ OldPage = MmGetPfnForProcess(Process, Address);
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
MmUnlockSectionSegment(Segment);
/*
* Check if we are doing COW
*/
- if (!((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) &&
+ if (!((Segment->WriteCopy) &&
(Region->Protect == PAGE_READWRITE ||
Region->Protect == PAGE_EXECUTE_READWRITE)))
{
PFN_FROM_SSE(Entry) != OldPage)
{
/* This is a private page. We must only change the page protection. */
- MmSetPageProtect(Process, PAddress, Region->Protect);
+ MmSetPageProtect(Process, Address, Region->Protect);
return(STATUS_SUCCESS);
}
/*
* Allocate a page
*/
+ MI_SET_USAGE(MI_USAGE_SECTION);
+ if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+ if (!Process) MI_SET_PROCESS2("Kernel Section");
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage);
if (!NT_SUCCESS(Status))
{
/*
* Copy the old page
*/
- MiCopyFromUserPage(NewPage, PAddress);
+ MiCopyFromUserPage(NewPage, Address);
MmLockAddressSpace(AddressSpace);
/*
/*
* Unshare the old page.
*/
- MmDeleteRmap(OldPage, Process, PAddress);
- MmInsertRmap(NewPage, Process, PAddress);
+ MmDeleteRmap(OldPage, Process, Address);
+ MmInsertRmap(NewPage, Process, Address);
MmLockSectionSegment(Segment);
MmUnsharePageEntrySectionSegment(Section, Segment, Offset, FALSE, FALSE);
MmUnlockSectionSegment(Segment);
ULONG FileOffset;
NTSTATUS Status;
PFILE_OBJECT FileObject;
+#ifndef NEWCC
PBCB Bcb = NULL;
+#endif
BOOLEAN DirectMapped;
BOOLEAN IsImageSection;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
KIRQL OldIrql;
-
+
Address = (PVOID)PAGE_ROUND_DOWN(Address);
/*
Context.Segment = MemoryArea->Data.SectionData.Segment;
Context.Section = MemoryArea->Data.SectionData.Section;
- Context.Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
- + MemoryArea->Data.SectionData.ViewOffset;
+ Context.Offset = (ULONG)((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset);
FileOffset = Context.Offset + Context.Segment->FileOffset;
IsImageSection = Context.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
FileObject = Context.Section->FileObject;
DirectMapped = FALSE;
+#ifndef NEWCC
if (FileObject != NULL &&
!(Context.Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
{
DirectMapped = TRUE;
}
}
+#endif
/*
Page = MmGetPfnForProcess(Process, Address);
SwapEntry = MmGetSavedSwapEntryPage(Page);
+ /*
+ * Check the reference count to ensure this page can be paged out
+ */
+ if (MmGetReferenceCountPage(Page) != 1)
+ {
+ DPRINT1("Cannot page out locked section page: 0x%p (RefCount: %d)\n",
+ Page, MmGetReferenceCountPage(Page));
+ PageOp->Status = STATUS_UNSUCCESSFUL;
+ MmspCompleteAndReleasePageOp(PageOp);
+ return STATUS_UNSUCCESSFUL;
+ }
+
/*
* Prepare the context structure for the rmap delete call.
*/
Address);
KeBugCheck(MEMORY_MANAGEMENT);
}
+#ifndef NEWCC
Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
+#else
+ Status = STATUS_SUCCESS;
+#endif
if (!NT_SUCCESS(Status))
{
DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status);
PVOID Address,
PMM_PAGEOP PageOp)
{
- ULONG Offset;
+ ULONG_PTR Offset;
PROS_SECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
PFN_NUMBER Page;
if (DirectMapped && !Private)
{
ASSERT(SwapEntry == 0);
- CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
+#ifndef NEWCC
+ CcRosMarkDirtyCacheSegment(Bcb, (ULONG)Offset + Segment->FileOffset);
+#endif
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_SUCCESS);
static VOID
MmAlterViewAttributes(PMMSUPPORT AddressSpace,
PVOID BaseAddress,
- ULONG RegionSize,
+ SIZE_T RegionSize,
ULONG OldType,
ULONG OldProtect,
ULONG NewType,
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
+ ASSERT(MemoryArea);
Segment = MemoryArea->Data.SectionData.Segment;
- if ((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) &&
+ if ((Segment->WriteCopy) &&
(NewProtect == PAGE_READWRITE || NewProtect == PAGE_EXECUTE_READWRITE))
{
DoCOW = TRUE;
*/
if (DoCOW && MmIsPagePresent(Process, Address))
{
- ULONG Offset;
+ ULONG_PTR Offset;
ULONG Entry;
PFN_NUMBER Page;
MmProtectSectionView(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID BaseAddress,
- ULONG Length,
+ SIZE_T Length,
ULONG Protect,
PULONG OldProtect)
{
MaxLength = (ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)BaseAddress;
if (Length > MaxLength)
- Length = MaxLength;
+ Length = (ULONG)MaxLength;
Region = MmFindRegion(MemoryArea->StartingAddress,
&MemoryArea->Data.SectionData.RegionListHead,
ULONG Length;
ULONG Offset;
ULONG Entry;
- ULONG SavedSwapEntry;
+ SWAPENTRY SavedSwapEntry;
PFN_NUMBER Page;
Page = 0;
}
if (Section->FileObject != NULL)
{
+#ifndef NEWCC
CcRosDereferenceCache(Section->FileObject);
+#endif
ObDereferenceObject(Section->FileObject);
Section->FileObject = NULL;
}
ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
ObjectTypeInitializer.ValidAccessMask = SECTION_ALL_ACCESS;
ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &MmSectionObjectType);
-
+
MmCreatePhysicalMemorySection();
return(STATUS_SUCCESS);
MmUnlockSectionSegment(Segment);
Section->FileObject = FileObject;
Section->MaximumSize = MaximumSize;
+#ifndef NEWCC
CcRosReferenceCache(FileObject);
+#endif
//KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
*SectionObject = Section;
return(STATUS_SUCCESS);
if(NT_SUCCESS(Status))
{
- UsedSize = Iosb.Information;
+ UsedSize = (ULONG)Iosb.Information;
}
}
#endif
EffectiveSegment->VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
/* Round up the virtual size to the nearest page */
- EffectiveSegment->Length = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length) -
- EffectiveSegment->VirtualAddress;
+ EffectiveSegment->Length = (ULONG)(PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length) -
+ EffectiveSegment->VirtualAddress);
/* Adjust the raw address and size */
VirtualOffset = VirtualAddress - EffectiveSegment->VirtualAddress;
- if (EffectiveSegment->FileOffset < VirtualOffset)
+ if (EffectiveSegment->FileOffset < (LONG_PTR)VirtualOffset)
{
return FALSE;
}
* offset point in curious and odd places, but that's what we were
* asked for
*/
- EffectiveSegment->FileOffset -= VirtualOffset;
- EffectiveSegment->RawLength += VirtualOffset;
+ EffectiveSegment->FileOffset -= (ULONG)VirtualOffset;
+ EffectiveSegment->RawLength += (ULONG)VirtualOffset;
}
else
{
*/
ASSERT(PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) >= EndOfEffectiveSegment);
- EffectiveSegment->Length = PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) -
- EffectiveSegment->VirtualAddress;
+ EffectiveSegment->Length = (ULONG)(PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) -
+ EffectiveSegment->VirtualAddress);
/*
* Merge the protection
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
+#ifndef NEWCC
/*
* Initialized caching for this file object if previously caching
* was initialized for the same on disk file
*/
Status = CcTryToInitializeFileCache(FileObject);
+#else
+ Status = STATUS_SUCCESS;
+#endif
if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL)
{
Status = STATUS_SUCCESS;
}
Section->FileObject = FileObject;
+#ifndef NEWCC
CcRosReferenceCache(FileObject);
+#endif
//KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
*SectionObject = Section;
return(Status);
MArea->Data.SectionData.Segment = Segment;
MArea->Data.SectionData.Section = Section;
MArea->Data.SectionData.ViewOffset = ViewOffset;
- MArea->Data.SectionData.WriteCopyView = FALSE;
MmInitializeRegion(&MArea->Data.SectionData.RegionListHead,
ViewSize, 0, Protect);
Address = (PVOID)PAGE_ROUND_DOWN(Address);
- Offset = ((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress) +
- MemoryArea->Data.SectionData.ViewOffset;
+ Offset = (ULONG)(((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress) +
+ MemoryArea->Data.SectionData.ViewOffset);
Section = MemoryArea->Data.SectionData.Section;
Segment = MemoryArea->Data.SectionData.Segment;
{
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+#ifndef NEWCC
CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
+#endif
ASSERT(SwapEntry == 0);
}
}
Offset -= PAGE_SIZE;
PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL,
MemoryArea->Data.SectionData.Segment,
- Offset + MemoryArea->Data.SectionData.ViewOffset);
+ (ULONG)Offset + MemoryArea->Data.SectionData.ViewOffset);
if (PageOp)
{
MmUnlockAddressSpace(AddressSpace);
* and calculate the image base address */
for (i = 0; i < NrSegments; i++)
{
- if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
- {
- if (Segment == &SectionSegments[i])
- {
- ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].VirtualAddress;
- break;
- }
- }
+ if (Segment == &SectionSegments[i])
+ {
+ ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].VirtualAddress;
+ break;
+ }
}
if (i >= NrSegments)
{
for (i = 0; i < NrSegments; i++)
{
- if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
- {
- PVOID SBaseAddress = (PVOID)
- ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].VirtualAddress);
+ PVOID SBaseAddress = (PVOID)
+ ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].VirtualAddress);
- Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
- }
+ Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
}
}
else
ExSectionInfoClass,
sizeof(ExSectionInfoClass) / sizeof(ExSectionInfoClass[0]),
SectionInformation,
- SectionInformationLength,
+ (ULONG)SectionInformationLength,
NULL,
ResultLength,
PreviousMode);
return(Status);
}
-
-
-
/**********************************************************************
* NAME EXPORTED
* MmMapViewOfSection
PMMSUPPORT AddressSpace;
ULONG ViewOffset;
NTSTATUS Status = STATUS_SUCCESS;
+ BOOLEAN NotAtBase = FALSE;
+
+ if ((ULONG_PTR)SectionObject & 1)
+ {
+ return MmMapViewOfArm3Section((PVOID)((ULONG_PTR)SectionObject & ~1),
+ Process,
+ BaseAddress,
+ ZeroBits,
+ CommitSize,
+ SectionOffset,
+ ViewSize,
+ InheritDisposition,
+ AllocationType,
+ Protect);
+ }
ASSERT(Process);
ULONG i;
ULONG NrSegments;
ULONG_PTR ImageBase;
- ULONG ImageSize;
+ SIZE_T ImageSize;
PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
PMM_SECTION_SEGMENT SectionSegments;
ImageSize = 0;
for (i = 0; i < NrSegments; i++)
{
- if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
- {
- ULONG_PTR MaxExtent;
- MaxExtent = (ULONG_PTR)SectionSegments[i].VirtualAddress +
- SectionSegments[i].Length;
- ImageSize = max(ImageSize, MaxExtent);
- }
+ ULONG_PTR MaxExtent;
+ MaxExtent = (ULONG_PTR)SectionSegments[i].VirtualAddress +
+ SectionSegments[i].Length;
+ ImageSize = max(ImageSize, MaxExtent);
}
- ImageSectionObject->ImageSize = ImageSize;
+ ImageSectionObject->ImageSize = (ULONG)ImageSize;
+
+ /* Check for an illegal base address */
+ if ((ImageBase + ImageSize) > (ULONG_PTR)MmHighestUserAddress)
+ {
+ ImageBase = PAGE_ROUND_DOWN((ULONG_PTR)MmHighestUserAddress - ImageSize);
+ }
/* Check there is enough space to map the section at that point. */
if (MmLocateMemoryAreaByRegion(AddressSpace, (PVOID)ImageBase,
MmUnlockAddressSpace(AddressSpace);
return(STATUS_UNSUCCESSFUL);
}
+ /* Remember that we loaded image at a different base address */
+ NotAtBase = TRUE;
}
for (i = 0; i < NrSegments; i++)
{
- if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
- {
- PVOID SBaseAddress = (PVOID)
- ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].VirtualAddress);
- MmLockSectionSegment(&SectionSegments[i]);
- Status = MmMapViewOfSegment(AddressSpace,
- Section,
- &SectionSegments[i],
- &SBaseAddress,
- SectionSegments[i].Length,
- SectionSegments[i].Protection,
- 0,
- 0);
- MmUnlockSectionSegment(&SectionSegments[i]);
- if (!NT_SUCCESS(Status))
- {
- MmUnlockAddressSpace(AddressSpace);
- return(Status);
- }
- }
+ PVOID SBaseAddress = (PVOID)
+ ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].VirtualAddress);
+ MmLockSectionSegment(&SectionSegments[i]);
+ Status = MmMapViewOfSegment(AddressSpace,
+ Section,
+ &SectionSegments[i],
+ &SBaseAddress,
+ SectionSegments[i].Length,
+ SectionSegments[i].Protection,
+ 0,
+ 0);
+ MmUnlockSectionSegment(&SectionSegments[i]);
+ if (!NT_SUCCESS(Status))
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ return(Status);
+ }
}
*BaseAddress = (PVOID)ImageBase;
+ *ViewSize = ImageSize;
}
else
{
MmUnlockAddressSpace(AddressSpace);
- return(STATUS_SUCCESS);
+ if (NotAtBase)
+ Status = STATUS_IMAGE_NOT_AT_BASE;
+ else
+ Status = STATUS_SUCCESS;
+
+ return Status;
}
/*
else
{
/* Something must gone wrong
- * how can we have a Section but no
+ * how can we have a Section but no
* reference? */
DPRINT("ERROR: DataSectionObject without reference!\n");
}
{
return FALSE;
}
+#ifndef NEWCC
CcRosSetRemoveOnClose(SectionObjectPointer);
+#endif
return TRUE;
case MmFlushForWrite:
break;
PROS_SECTION_OBJECT Section;
PMMSUPPORT AddressSpace;
NTSTATUS Status;
+ PAGED_CODE();
if ((ULONG_PTR)SectionObject & 1)
{
- PAGED_CODE();
extern PVOID MmSession;
return MiMapViewInSystemSpace((PVOID)((ULONG_PTR)SectionObject & ~1),
&MmSession,
DPRINT("MmUnmapViewInSystemSpace() called\n");
AddressSpace = MmGetKernelAddressSpace();
+
+ MmLockAddressSpace(AddressSpace);
Status = MmUnmapViewOfSegment(AddressSpace, MappedBase);
+
+ MmUnlockAddressSpace(AddressSpace);
return Status;
}
{
ULONG Protection;
PROS_SECTION_OBJECT *SectionObject = (PROS_SECTION_OBJECT *)Section;
-
+
/* Check if an ARM3 section is being created instead */
- if (AllocationAttributes & 0xC0000000)
+ if (AllocationAttributes & 1)
{
DPRINT1("arm 3 path\n");
return MmCreateArm3Section(Section,
ObjectAttributes,
MaximumSize,
SectionPageProtection,
- AllocationAttributes &~ 0xC0000000,
+ AllocationAttributes &~ 1,
FileHandle,
File);
}