/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
+#include "../cache/newcc.h"
+#include "../cache/section/newmm.h"
#define NDEBUG
#include <debug.h>
#include <reactos/exeformat.h>
#pragma alloc_text(INIT, MmInitSectionImplementation)
#endif
+#include "ARM3/miarm.h"
+
+#undef MmSetPageEntrySectionSegment
+#define MmSetPageEntrySectionSegment(S,O,E) do { \
+ DPRINT("SetPageEntrySectionSegment(old,%p,%x,%x)\n",(S),(O)->LowPart,E); \
+ _MmSetPageEntrySectionSegment((S),(O),(E),__FILE__,__LINE__); \
+ } while (0)
+
+extern MMSESSION MmSession;
+
+NTSTATUS
+NTAPI
+MiMapViewInSystemSpace(IN PVOID Section,
+IN PVOID Session,
+OUT PVOID *MappedBase,
+IN OUT PSIZE_T ViewSize);
+
+NTSTATUS
+NTAPI
+MmCreateArm3Section(OUT PVOID *SectionObject,
+IN ACCESS_MASK DesiredAccess,
+IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+IN PLARGE_INTEGER InputMaximumSize,
+IN ULONG SectionPageProtection,
+IN ULONG AllocationAttributes,
+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 *********************************************************************/
{
PROS_SECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
- ULONG Offset;
+ LARGE_INTEGER Offset;
BOOLEAN WasDirty;
BOOLEAN Private;
+ PEPROCESS CallingProcess;
+ ULONG_PTR SectionEntry;
}
MM_SECTION_PAGEOUT_CONTEXT;
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 */
+};
+
+extern ULONG MmMakeFileAccess [];
+ACCESS_MASK NTAPI MiArm3GetCorrectFileAccessMask(IN ACCESS_MASK SectionPageProtection);
static GENERIC_MAPPING MmpSectionMapping = {
STANDARD_RIGHTS_READ | SECTION_MAP_READ | SECTION_QUERY,
STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE,
STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE,
SECTION_ALL_ACCESS};
-#define PAGE_FROM_SSE(E) ((E) & 0xFFFFF000)
-#define PFN_FROM_SSE(E) ((E) >> PAGE_SHIFT)
-#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 SWAPENTRY_FROM_SSE(E) ((E) >> 1)
-#define MAKE_SWAP_SSE(S) (((S) << 1) | 0x1)
-
static const INFORMATION_CLASS_INFO ExSectionInfoClass[] =
{
ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionBasicInformation */
/* 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;
+ ULONG_PTR ImageBase;
+ 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));
- /* Make sure it's an image section */
- *ModuleName = NULL;
- if (!(Section->AllocationAttributes & SEC_IMAGE))
+ 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;
+
+ /* 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))
+ ImageBase = piohOptHeader->ImageBase;
- /* Lock address space */
- MmLockAddressSpace(AddressSpace);
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfImage))
+ ImageSectionObject->ImageInformation.ImageFileSize = piohOptHeader->SizeOfImage;
- /* Locate the memory area for the process by address */
- MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackReserve))
+ ImageSectionObject->ImageInformation.MaximumStackSize = 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->ImageInformation.CommittedStackSize = piohOptHeader->SizeOfStackCommit;
- /* Unlock address space */
- MmUnlockAddressSpace(AddressSpace);
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Subsystem))
+ {
+ ImageSectionObject->ImageInformation.SubSystemType = piohOptHeader->Subsystem;
+
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
+ RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MajorSubsystemVersion))
+ {
+ ImageSectionObject->ImageInformation.SubSystemMinorVersion = piohOptHeader->MinorSubsystemVersion;
+ ImageSectionObject->ImageInformation.SubSystemMajorVersion = piohOptHeader->MajorSubsystemVersion;
+ }
+ }
- /* Get the filename of the section */
- Status = MmGetFileNameForSection(Section,&ModuleNameInformation);
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
+ {
+ ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
+ piohOptHeader->AddressOfEntryPoint);
+ }
- 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);
- }
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfCode))
+ ImageSectionObject->ImageInformation.ImageContainsCode = piohOptHeader->SizeOfCode != 0;
+ else
+ ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
- return Status;
-}
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
+ {
+ if (piohOptHeader->AddressOfEntryPoint == 0)
+ {
+ ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
+ }
+ }
-/* Note: Mmsp prefix denotes "Memory Manager Section Private". */
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, LoaderFlags))
+ ImageSectionObject->ImageInformation.LoaderFlags = piohOptHeader->LoaderFlags;
-/*
- * FUNCTION: Waits in kernel mode up to ten seconds for an MM_PAGEOP event.
- * ARGUMENTS: PMM_PAGEOP which event we should wait for.
- * RETURNS: Status of the wait.
- */
-static NTSTATUS
-MmspWaitForPageOpCompletionEvent(PMM_PAGEOP PageOp)
-{
- LARGE_INTEGER Timeout;
-#ifdef __GNUC__ /* TODO: Use other macro to check for suffix to use? */
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, DllCharacteristics))
+ {
+ ImageSectionObject->ImageInformation.DllCharacteristics = piohOptHeader->DllCharacteristics;
+
+ /*
+ * Since we don't really implement SxS yet and LD doesn't supoprt /ALLOWISOLATION:NO, hard-code
+ * this flag here, which will prevent the loader and other code from doing any .manifest or SxS
+ * magic to any binary.
+ *
+ * This will break applications that depend on SxS when running with real Windows Kernel32/SxS/etc
+ * but honestly that's not tested. It will also break them when running no ReactOS once we implement
+ * the SxS support -- at which point, duh, this should be removed.
+ *
+ * But right now, any app depending on SxS is already broken anyway, so this flag only helps.
+ */
+ ImageSectionObject->ImageInformation.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NO_ISOLATION;
+ }
- Timeout.QuadPart = -100000000LL; // 10 sec
-#else
+ break;
+ }
+#ifdef _WIN64
+ /* PE64 */
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+ {
+ const IMAGE_OPTIONAL_HEADER64 * pioh64OptHeader;
+
+ pioh64OptHeader = (const IMAGE_OPTIONAL_HEADER64 *)piohOptHeader;
+
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, ImageBase))
+ {
+ ImageBase = pioh64OptHeader->ImageBase;
+ if(pioh64OptHeader->ImageBase > MAXULONG_PTR)
+ DIE(("ImageBase exceeds the address space\n"));
+ }
+
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfImage))
+ {
+ if(pioh64OptHeader->SizeOfImage > MAXULONG_PTR)
+ DIE(("SizeOfImage exceeds the address space\n"));
+
+ ImageSectionObject->ImageInformation.ImageFileSize = pioh64OptHeader->SizeOfImage;
+ }
+
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackReserve))
+ {
+ if(pioh64OptHeader->SizeOfStackReserve > MAXULONG_PTR)
+ DIE(("SizeOfStackReserve exceeds the address space\n"));
+
+ ImageSectionObject->ImageInformation.MaximumStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackReserve;
+ }
+
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackCommit))
+ {
+ if(pioh64OptHeader->SizeOfStackCommit > MAXULONG_PTR)
+ DIE(("SizeOfStackCommit exceeds the address space\n"));
+
+ ImageSectionObject->ImageInformation.CommittedStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackCommit;
+ }
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, Subsystem))
+ {
+ ImageSectionObject->ImageInformation.SubSystemType = pioh64OptHeader->Subsystem;
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
+ RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MajorSubsystemVersion))
+ {
+ ImageSectionObject->ImageInformation.SubSystemMinorVersion = pioh64OptHeader->MinorSubsystemVersion;
+ ImageSectionObject->ImageInformation.SubSystemMajorVersion = pioh64OptHeader->MajorSubsystemVersion;
+ }
+ }
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
+ {
+ ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
+ pioh64OptHeader->AddressOfEntryPoint);
+ }
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfCode))
+ ImageSectionObject->ImageInformation.ImageContainsCode = pioh64OptHeader->SizeOfCode != 0;
+ else
+ ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
- Timeout.QuadPart = -100000000; // 10 sec
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
+ {
+ if (pioh64OptHeader->AddressOfEntryPoint == 0)
+ {
+ ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
+ }
+ }
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, LoaderFlags))
+ ImageSectionObject->ImageInformation.LoaderFlags = pioh64OptHeader->LoaderFlags;
+
+ if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, DllCharacteristics))
+ ImageSectionObject->ImageInformation.DllCharacteristics = pioh64OptHeader->DllCharacteristics;
+
+ break;
+ }
+#endif // _WIN64
+ }
+
+ /* [1], section 3.4.2 */
+ if((ULONG_PTR)ImageBase % 0x10000)
+ DIE(("ImageBase is not aligned on a 64KB boundary"));
+
+ ImageSectionObject->ImageInformation.ImageCharacteristics = pinhNtHeader->FileHeader.Characteristics;
+ ImageSectionObject->ImageInformation.Machine = pinhNtHeader->FileHeader.Machine;
+ ImageSectionObject->ImageInformation.GpValue = 0;
+ ImageSectionObject->ImageInformation.ZeroBits = 0;
+ ImageSectionObject->BasedAddress = (PVOID)ImageBase;
+
+ /* 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].Image.FileOffset = 0;
+ pssSegments[0].Protection = PAGE_READONLY;
+ pssSegments[0].Length.QuadPart = nPrevVirtualEndOfSegment;
+ pssSegments[0].RawLength.QuadPart = nFileSizeOfHeaders;
+ pssSegments[0].Image.VirtualAddress = 0;
+ pssSegments[0].Image.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(("Image.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
- return KeWaitForSingleObject(&PageOp->CompletionEvent, 0, KernelMode, FALSE, &Timeout);
-}
+// if(!IsAligned(pishSectionHeaders[i].PointerToRawData, nFileAlignment))
+// DIE(("PointerToRawData[%u] is not aligned\n", i));
+ /* conversion */
+ pssSegments[i].Image.FileOffset = pishSectionHeaders[i].PointerToRawData;
+ pssSegments[i].RawLength.QuadPart = pishSectionHeaders[i].SizeOfRawData;
+ }
+ else
+ {
+ ASSERT(pssSegments[i].Image.FileOffset == 0);
+ ASSERT(pssSegments[i].RawLength.QuadPart == 0);
+ }
-/*
- * FUNCTION: Sets the page op completion event and releases the page op.
- * ARGUMENTS: PMM_PAGEOP.
- * RETURNS: In shorter time than it takes you to even read this
- * description, so don't even think about geting a mug of coffee.
- */
-static void
-MmspCompleteAndReleasePageOp(PMM_PAGEOP PageOp)
-{
- KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
- MmReleasePageOp(PageOp);
-}
+ ASSERT(Intsafe_CanAddLong64(pssSegments[i].Image.FileOffset, pssSegments[i].RawLength.QuadPart));
+
+ 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.QuadPart = pishSectionHeaders[i].SizeOfRawData;
+ else
+ pssSegments[i].Length.QuadPart = pishSectionHeaders[i].Misc.VirtualSize;
+
+ pssSegments[i].Length.LowPart = ALIGN_UP_BY(pssSegments[i].Length.LowPart, nSectionAlignment);
+ /* FIXME: always false */
+ if (pssSegments[i].Length.QuadPart < pssSegments[i].Length.QuadPart)
+ DIE(("Cannot align the virtual size of section %u\n", i));
+
+ if(pssSegments[i].Length.QuadPart == 0)
+ DIE(("Virtual size of section %u is null\n", i));
+
+ pssSegments[i].Image.VirtualAddress = pishSectionHeaders[i].VirtualAddress;
+ pssSegments[i].Image.Characteristics = pishSectionHeaders[i].Characteristics;
+
+ /* ensure the memory image is no larger than 4GB */
+ nPrevVirtualEndOfSegment = (ULONG_PTR)(pssSegments[i].Image.VirtualAddress + pssSegments[i].Length.QuadPart);
+ if (nPrevVirtualEndOfSegment < pssSegments[i].Image.VirtualAddress)
+ DIE(("The image is too large\n"));
+ }
+
+ if(nSectionAlignment >= PAGE_SIZE)
+ *Flags |= EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED;
+
+ /* Success */
+ nStatus = STATUS_SUCCESS;// STATUS_ROS_EXEFMT_LOADED_FORMAT | EXEFMT_LOADED_PE32;
+
+l_Return:
+ if(pBuffer)
+ ExFreePool(pBuffer);
+
+ return nStatus;
+}
/*
* FUNCTION: Waits in kernel mode indefinitely for a file object lock.
* ARGUMENTS: PFILE_OBJECT to wait for.
* RETURNS: Status of the wait.
*/
-static NTSTATUS
+NTSTATUS
MmspWaitForFileLock(PFILE_OBJECT File)
{
return STATUS_SUCCESS;
//return KeWaitForSingleObject(&File->Lock, 0, KernelMode, FALSE, NULL);
}
-
-VOID
-MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment)
-{
- ULONG i;
- if (Segment->Length > NR_SECTION_PAGE_TABLES * PAGE_SIZE)
- {
- for (i = 0; i < NR_SECTION_PAGE_TABLES; i++)
- {
- if (Segment->PageDirectory.PageTables[i] != NULL)
- {
- ExFreePool(Segment->PageDirectory.PageTables[i]);
- }
- }
- }
-}
-
VOID
NTAPI
MmFreeSectionSegments(PFILE_OBJECT FileObject)
{
if (SectionSegments[i].ReferenceCount != 0)
{
- DPRINT1("Image segment %d still referenced (was %d)\n", i,
+ DPRINT1("Image segment %lu still referenced (was %lu)\n", i,
SectionSegments[i].ReferenceCount);
KeBugCheck(MEMORY_MANAGEMENT);
}
- MmFreePageTablesSectionSegment(&SectionSegments[i]);
+ MmFreePageTablesSectionSegment(&SectionSegments[i], NULL);
}
ExFreePool(ImageSectionObject->Segments);
ExFreePool(ImageSectionObject);
DPRINT1("Data segment still referenced\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
- MmFreePageTablesSectionSegment(Segment);
+ MmFreePageTablesSectionSegment(Segment, NULL);
ExFreePool(Segment);
FileObject->SectionObjectPointer->DataSectionObject = NULL;
}
}
-VOID
-NTAPI
-MmLockSectionSegment(PMM_SECTION_SEGMENT Segment)
-{
- ExAcquireFastMutex(&Segment->Lock);
-}
-
-VOID
-NTAPI
-MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment)
-{
- ExReleaseFastMutex(&Segment->Lock);
-}
-
-VOID
-NTAPI
-MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
- ULONG Offset,
- ULONG Entry)
-{
- PSECTION_PAGE_TABLE Table;
- ULONG DirectoryOffset;
- ULONG TableOffset;
-
- if (Segment->Length <= NR_SECTION_PAGE_TABLES * PAGE_SIZE)
- {
- Table = (PSECTION_PAGE_TABLE)&Segment->PageDirectory;
- }
- else
- {
- DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
- Table = Segment->PageDirectory.PageTables[DirectoryOffset];
- if (Table == NULL)
- {
- Table =
- Segment->PageDirectory.PageTables[DirectoryOffset] =
- ExAllocatePoolWithTag(NonPagedPool, sizeof(SECTION_PAGE_TABLE),
- TAG_SECTION_PAGE_TABLE);
- if (Table == NULL)
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- memset(Table, 0, sizeof(SECTION_PAGE_TABLE));
- DPRINT("Table %x\n", Table);
- }
- }
- TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
- Table->Entry[TableOffset] = Entry;
-}
-
-
-ULONG
-NTAPI
-MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
- ULONG Offset)
-{
- PSECTION_PAGE_TABLE Table;
- ULONG Entry;
- ULONG DirectoryOffset;
- ULONG TableOffset;
-
- DPRINT("MmGetPageEntrySection(Segment %x, Offset %x)\n", Segment, Offset);
-
- if (Segment->Length <= NR_SECTION_PAGE_TABLES * PAGE_SIZE)
- {
- Table = (PSECTION_PAGE_TABLE)&Segment->PageDirectory;
- }
- else
- {
- DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
- Table = Segment->PageDirectory.PageTables[DirectoryOffset];
- DPRINT("Table %x\n", Table);
- if (Table == NULL)
- {
- return(0);
- }
- }
- TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
- Entry = Table->Entry[TableOffset];
- return(Entry);
-}
-
VOID
NTAPI
MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
- ULONG Offset)
+ PLARGE_INTEGER Offset)
{
- ULONG Entry;
+ ULONG_PTR Entry;
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
if (Entry == 0)
NTAPI
MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
PMM_SECTION_SEGMENT Segment,
- ULONG Offset,
+ PLARGE_INTEGER Offset,
BOOLEAN Dirty,
- BOOLEAN PageOut)
+ BOOLEAN PageOut,
+ ULONG_PTR *InEntry)
{
- ULONG Entry;
+ ULONG_PTR Entry = InEntry ? *InEntry : MmGetPageEntrySectionSegment(Segment, Offset);
BOOLEAN IsDirectMapped = FALSE;
- Entry = MmGetPageEntrySectionSegment(Segment, Offset);
if (Entry == 0)
{
DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
}
if (SHARE_COUNT_FROM_SSE(Entry) == 0)
{
- DPRINT1("Zero share count for unshare\n");
+ DPRINT1("Zero share count for unshare (Seg %p Offset %x Page %x)\n", Segment, Offset->LowPart, PFN_FROM_SSE(Entry));
KeBugCheck(MEMORY_MANAGEMENT);
}
if (IS_SWAP_FROM_SSE(Entry))
if (SHARE_COUNT_FROM_SSE(Entry) == 0)
{
PFILE_OBJECT FileObject;
+#ifndef NEWCC
PBCB Bcb;
+#endif
SWAPENTRY SavedSwapEntry;
PFN_NUMBER Page;
BOOLEAN IsImageSection;
- ULONG FileOffset;
+ LARGE_INTEGER FileOffset;
- FileOffset = Offset + Segment->FileOffset;
+ FileOffset.QuadPart = Offset->QuadPart + Segment->Image.FileOffset;
IsImageSection = Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
Page = PFN_FROM_SSE(Entry);
FileObject = Section->FileObject;
if (FileObject != NULL &&
- !(Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
+ !(Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
{
- if ((FileOffset % PAGE_SIZE) == 0 &&
- (Offset + PAGE_SIZE <= Segment->RawLength || !IsImageSection))
+#ifndef NEWCC
+ if ((FileOffset.QuadPart % PAGE_SIZE) == 0 &&
+ (Offset->QuadPart + PAGE_SIZE <= Segment->RawLength.QuadPart || !IsImageSection))
{
NTSTATUS Status;
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
IsDirectMapped = TRUE;
- Status = CcRosUnmapCacheSegment(Bcb, FileOffset, Dirty);
+#ifndef NEWCC
+ Status = CcRosUnmapCacheSegment(Bcb, FileOffset.LowPart, Dirty);
+#else
+ Status = STATUS_SUCCESS;
+#endif
if (!NT_SUCCESS(Status))
{
DPRINT1("CcRosUnmapCacheSegment failed, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
+ KeBugCheck(MEMORY_MANAGEMENT);
}
}
+#endif
}
SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
{
if (!PageOut &&
((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
- (Segment->Characteristics & IMAGE_SCN_MEM_SHARED)))
+ (Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)))
{
/*
* FIXME:
* page without a rmap entry.
*/
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ if (InEntry) *InEntry = Entry;
+ MiSetPageEvent(NULL, NULL);
}
else
{
MmSetPageEntrySectionSegment(Segment, Offset, 0);
+ if (InEntry) *InEntry = 0;
+ MiSetPageEvent(NULL, NULL);
if (!IsDirectMapped)
{
MmReleasePageMemoryConsumer(MC_USER, Page);
else
{
if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
- (Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
+ (Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
{
if (!PageOut)
{
}
}
MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
+ if (InEntry) *InEntry = MAKE_SWAP_SSE(SavedSwapEntry);
MmSetSavedSwapEntryPage(Page, 0);
+ MiSetPageEvent(NULL, NULL);
}
MmReleasePageMemoryConsumer(MC_USER, Page);
}
}
else
{
- MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ if (InEntry)
+ *InEntry = Entry;
+ else
+ MmSetPageEntrySectionSegment(Segment, Offset, Entry);
}
return(SHARE_COUNT_FROM_SSE(Entry) > 0);
}
BOOLEAN MiIsPageFromCache(PMEMORY_AREA MemoryArea,
ULONG SegOffset)
{
- if (!(MemoryArea->Data.SectionData.Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
+#ifndef NEWCC
+ if (!(MemoryArea->Data.SectionData.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
{
PBCB Bcb;
PCACHE_SEGMENT CacheSeg;
Bcb = MemoryArea->Data.SectionData.Section->FileObject->SectionObjectPointer->SharedCacheMap;
- CacheSeg = CcRosLookupCacheSegment(Bcb, SegOffset + MemoryArea->Data.SectionData.Segment->FileOffset);
+ CacheSeg = CcRosLookupCacheSegment(Bcb, (ULONG)(SegOffset + MemoryArea->Data.SectionData.Segment->Image.FileOffset));
if (CacheSeg)
{
CcRosReleaseCacheSegment(Bcb, CacheSeg, CacheSeg->Valid, FALSE, TRUE);
return TRUE;
}
}
+#endif
return FALSE;
}
NTSTATUS
NTAPI
-MiCopyFromUserPage(PFN_NUMBER DestPage, PVOID SourceAddress)
+MiCopyFromUserPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage)
{
PEPROCESS Process;
- KIRQL Irql;
- PVOID TempAddress;
-
+ KIRQL Irql, Irql2;
+ PVOID DestAddress, SrcAddress;
+
Process = PsGetCurrentProcess();
- TempAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
- if (TempAddress == NULL)
+ DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
+ SrcAddress = MiMapPageInHyperSpace(Process, SrcPage, &Irql2);
+ if (DestAddress == NULL || SrcAddress == NULL)
{
return(STATUS_NO_MEMORY);
}
- memcpy(TempAddress, SourceAddress, PAGE_SIZE);
- MiUnmapPageInHyperSpace(Process, TempAddress, Irql);
+ ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
+ ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
+ RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
+ MiUnmapPageInHyperSpace(Process, SrcAddress, Irql2);
+ MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
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;
+ ULONGLONG 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;
- RawLength = MemoryArea->Data.SectionData.Segment->RawLength;
- FileOffset = SegOffset + MemoryArea->Data.SectionData.Segment->FileOffset;
+ RawLength = (ULONG_PTR)(MemoryArea->Data.SectionData.Segment->RawLength.QuadPart);
+ FileOffset = SegOffset + MemoryArea->Data.SectionData.Segment->Image.FileOffset;
IsImageSection = MemoryArea->Data.SectionData.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
ASSERT(Bcb);
- DPRINT("%S %x\n", FileObject->FileName.Buffer, FileOffset);
+ DPRINT("%S %I64x\n", FileObject->FileName.Buffer, FileOffset);
/*
* If the file system is letting us go directly to the cache and the
* memory area was mapped at an offset in the file which is page aligned
* then get the related cache segment.
*/
- if ((FileOffset % PAGE_SIZE) == 0 &&
- (SegOffset + PAGE_SIZE <= RawLength || !IsImageSection) &&
- !(MemoryArea->Data.SectionData.Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
+ if (((FileOffset % PAGE_SIZE) == 0) &&
+ ((SegOffset + PAGE_SIZE <= RawLength) || !IsImageSection) &&
+ !(MemoryArea->Data.SectionData.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
{
/*
* alignment less than the file system block size.
*/
Status = CcRosGetCacheSegment(Bcb,
- FileOffset,
+ (ULONG)FileOffset,
&BaseOffset,
&BaseAddress,
&UptoDate,
return Status;
}
}
+
+ /* Probe the page, since it's PDE might not be synced */
+ (void)*((volatile char*)BaseAddress + FileOffset - BaseOffset);
+
/*
* Retrieve the page from the cache segment that we actually want.
*/
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,
Process = PsGetCurrentProcess();
PageAddr = MiMapPageInHyperSpace(Process, *Page, &Irql);
- CacheSegOffset = BaseOffset + CacheSeg->Bcb->CacheSegmentSize - FileOffset;
+ CacheSegOffset = (ULONG_PTR)(BaseOffset + VACB_MAPPING_GRANULARITY - FileOffset);
Length = RawLength - SegOffset;
if (Length <= CacheSegOffset && Length <= PAGE_SIZE)
{
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_PTR 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;
+ NTSTATUS Status;
+
+ RtlZeroMemory(&Resources, sizeof(MM_REQUIRED_RESOURCES));
+
+ Resources.Context = MemoryArea->Data.SectionData.Section->FileObject;
+ Resources.FileOffset.QuadPart = SegOffset +
+ MemoryArea->Data.SectionData.Segment->Image.FileOffset;
+ Resources.Consumer = MC_USER;
+ Resources.Amount = PAGE_SIZE;
+
+ DPRINT("%S, offset 0x%x, len 0x%x, page 0x%x\n", ((PFILE_OBJECT)Resources.Context)->FileName.Buffer, Resources.FileOffset.LowPart, Resources.Amount, Resources.Page[0]);
+
+ Status = MiReadFilePage(MmGetKernelAddressSpace(), MemoryArea, &Resources);
+ *Page = Resources.Page[0];
+ return Status;
+}
+#endif
NTSTATUS
NTAPI
PVOID Address,
BOOLEAN Locked)
{
- ULONG Offset;
+ LARGE_INTEGER 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;
+ PVOID PAddress;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-
+ SWAPENTRY SwapEntry;
+
/*
* 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);
}
+ if (MmIsDisabledPage(Process, Address))
+ {
+ return(STATUS_ACCESS_VIOLATION);
+ }
+
+ /*
+ * 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;
+ Offset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
Segment = MemoryArea->Data.SectionData.Segment;
Section = MemoryArea->Data.SectionData.Section;
Region = MmFindRegion(MemoryArea->StartingAddress,
&MemoryArea->Data.SectionData.RegionListHead,
Address, NULL);
+ ASSERT(Region != NULL);
/*
* Lock the segment
*/
MmLockSectionSegment(Segment);
-
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
/*
* 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))
{
Attributes = Region->Protect;
}
- /*
- * Get or create a page operation descriptor
- */
- PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset, MM_PAGEOP_PAGEIN, FALSE);
- if (PageOp == NULL)
- {
- DPRINT1("MmGetPageOp failed\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
/*
* Check if someone else is already handling this fault, if so wait
* for them
*/
- if (PageOp->Thread != PsGetCurrentThread())
+ if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
{
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
- Status = MmspWaitForPageOpCompletionEvent(PageOp);
- /*
- * Check for various strange conditions
- */
- if (Status != STATUS_SUCCESS)
- {
- DPRINT1("Failed to wait for page op, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- if (PageOp->Status == STATUS_PENDING)
- {
- DPRINT1("Woke for page op before completion\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
+ MiWaitForPageEvent(NULL, NULL);
MmLockAddressSpace(AddressSpace);
- /*
- * If this wasn't a pagein then restart the operation
- */
- if (PageOp->OpType != MM_PAGEOP_PAGEIN)
- {
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_MM_RESTART_OPERATION);
- }
-
- /*
- * If the thread handling this fault has failed then we don't retry
- */
- if (!NT_SUCCESS(PageOp->Status))
- {
- Status = PageOp->Status;
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
- return(Status);
- }
- MmLockSectionSegment(Segment);
- /*
- * If the completed fault was for another address space then set the
- * page in this one.
- */
- if (!MmIsPagePresent(Process, Address))
- {
- Entry = MmGetPageEntrySectionSegment(Segment, Offset);
- HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress);
+ DPRINT("Address 0x%p\n", Address);
+ return(STATUS_MM_RESTART_OPERATION);
+ }
- if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry)
- {
- /*
- * The page was a private page in another or in our address space
- */
- MmUnlockSectionSegment(Segment);
- MmspCompleteAndReleasePageOp(PageOp);
- return(STATUS_MM_RESTART_OPERATION);
- }
+ HasSwapEntry = MmIsPageSwapEntry(Process, Address);
- Page = PFN_FROM_SSE(Entry);
+ if (HasSwapEntry)
+ {
+ SWAPENTRY DummyEntry;
- MmSharePageEntrySectionSegment(Segment, Offset);
+ /*
+ * Is it a wait entry?
+ */
+ MmGetPageFileMapping(Process, Address, &SwapEntry);
- /* FIXME: Should we call MmCreateVirtualMappingUnsafe if
- * (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true?
- */
- Status = MmCreateVirtualMapping(Process,
- Address,
- Attributes,
- &Page,
- 1);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to create virtual mapping\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- MmInsertRmap(Page, Process, (PVOID)PAddress);
+ if (SwapEntry == MM_WAIT_ENTRY)
+ {
+ MmUnlockSectionSegment(Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ MiWaitForPageEvent(NULL, NULL);
+ MmLockAddressSpace(AddressSpace);
+ return STATUS_MM_RESTART_OPERATION;
}
- MmUnlockSectionSegment(Segment);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_SUCCESS);
- }
- HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress);
- if (HasSwapEntry)
- {
/*
* Must be private page we have swapped out.
*/
- SWAPENTRY SwapEntry;
/*
* Sanity check
}
MmUnlockSectionSegment(Segment);
- MmDeletePageFileMapping(Process, (PVOID)PAddress, &SwapEntry);
+ MmDeletePageFileMapping(Process, Address, &SwapEntry);
+ MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
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))
{
KeBugCheck(MEMORY_MANAGEMENT);
}
MmLockAddressSpace(AddressSpace);
+ MmDeletePageFileMapping(Process, PAddress, &DummyEntry);
Status = MmCreateVirtualMapping(Process,
- Address,
+ PAddress,
Region->Protect,
&Page,
1);
/*
* Add the page to the process's working set
*/
- MmInsertRmap(Page, Process, (PVOID)PAddress);
-
+ MmInsertRmap(Page, Process, Address);
/*
* Finish the operation
*/
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
return(STATUS_SUCCESS);
}
/*
* Just map the desired physical page
*/
- Page = Offset >> PAGE_SHIFT;
+ Page = (PFN_NUMBER)(Offset.QuadPart >> PAGE_SHIFT);
Status = MmCreateVirtualMappingUnsafe(Process,
- Address,
+ PAddress,
Region->Protect,
&Page,
1);
/*
* Cleanup and release locks
*/
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_SUCCESS);
- }
-
- /*
- * Map anonymous memory for BSS sections
- */
- if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
- {
- MmUnlockSectionSegment(Segment);
- Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
- if (!NT_SUCCESS(Status))
- {
- MmUnlockAddressSpace(AddressSpace);
- Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
- MmLockAddressSpace(AddressSpace);
- }
- if (!NT_SUCCESS(Status))
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- Status = MmCreateVirtualMapping(Process,
- Address,
- Region->Protect,
- &Page,
- 1);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- return(Status);
- }
- MmInsertRmap(Page, Process, (PVOID)PAddress);
-
- /*
- * Cleanup and release locks
- */
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
return(STATUS_SUCCESS);
}
/*
* Get the entry corresponding to the offset within the section
*/
- Entry = MmGetPageEntrySectionSegment(Segment, Offset);
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
if (Entry == 0)
{
+ SWAPENTRY FakeSwapEntry;
+
/*
* If the entry is zero (and it can't change because we have
* locked the segment) then we need to load the page.
/*
* Release all our locks and read in the page from disk
*/
+ MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
MmUnlockSectionSegment(Segment);
+ MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
MmUnlockAddressSpace(AddressSpace);
if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
- (Offset >= PAGE_ROUND_UP(Segment->RawLength) && Section->AllocationAttributes & SEC_IMAGE))
+ ((Offset.QuadPart >= (LONGLONG)PAGE_ROUND_UP(Segment->RawLength.QuadPart) &&
+ (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
{
- Status = MiReadPage(MemoryArea, Offset, &Page);
+ Status = MiReadPage(MemoryArea, (ULONG_PTR)Offset.QuadPart, &Page);
if (!NT_SUCCESS(Status))
{
DPRINT1("MiReadPage failed (Status %x)\n", Status);
* Cleanup and release locks
*/
MmLockAddressSpace(AddressSpace);
- PageOp->Status = Status;
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
return(Status);
}
- /*
- * Relock the address space and segment
- */
- MmLockAddressSpace(AddressSpace);
- MmLockSectionSegment(Segment);
-
- /*
- * Check the entry. No one should change the status of a page
- * that has a pending page-in.
- */
- Entry1 = MmGetPageEntrySectionSegment(Segment, Offset);
- if (Entry != Entry1)
- {
- DPRINT1("Someone changed ppte entry while we slept\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
/*
* Mark the offset within the section as having valid, in-memory
* data
*/
+ MmLockAddressSpace(AddressSpace);
+ MmLockSectionSegment(Segment);
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
MmUnlockSectionSegment(Segment);
+ MmDeletePageFileMapping(Process, PAddress, &FakeSwapEntry);
+ DPRINT("CreateVirtualMapping Page %x Process %p PAddress %p Attributes %x\n",
+ Page, Process, PAddress, Attributes);
Status = MmCreateVirtualMapping(Process,
- Address,
+ PAddress,
Attributes,
&Page,
1);
DPRINT1("Unable to create virtual mapping\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
- MmInsertRmap(Page, Process, (PVOID)PAddress);
+ ASSERT(MmIsPagePresent(Process, PAddress));
+ MmInsertRmap(Page, Process, Address);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
return(STATUS_SUCCESS);
}
else if (IS_SWAP_FROM_SSE(Entry))
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))
{
* Check the entry. No one should change the status of a page
* that has a pending page-in.
*/
- Entry1 = MmGetPageEntrySectionSegment(Segment, Offset);
+ Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
if (Entry != Entry1)
{
- DPRINT1("Someone changed ppte entry while we slept\n");
+ DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
KeBugCheck(MEMORY_MANAGEMENT);
}
* data
*/
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
MmUnlockSectionSegment(Segment);
/*
*/
MmSetSavedSwapEntryPage(Page, SwapEntry);
Status = MmCreateVirtualMapping(Process,
- Address,
+ PAddress,
Region->Protect,
&Page,
1);
DPRINT1("Unable to create virtual mapping\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
- MmInsertRmap(Page, Process, (PVOID)PAddress);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
+ MmInsertRmap(Page, Process, Address);
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
return(STATUS_SUCCESS);
}
else
Page = PFN_FROM_SSE(Entry);
- MmSharePageEntrySectionSegment(Segment, Offset);
+ MmSharePageEntrySectionSegment(Segment, &Offset);
MmUnlockSectionSegment(Segment);
Status = MmCreateVirtualMapping(Process,
- Address,
+ PAddress,
Attributes,
&Page,
1);
DPRINT1("Unable to create virtual mapping\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
- MmInsertRmap(Page, Process, (PVOID)PAddress);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
+ MmInsertRmap(Page, Process, Address);
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
return(STATUS_SUCCESS);
}
}
NTAPI
MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
- PVOID Address,
- BOOLEAN Locked)
+ PVOID Address)
{
PMM_SECTION_SEGMENT Segment;
PROS_SECTION_OBJECT Section;
PFN_NUMBER NewPage;
NTSTATUS Status;
PVOID PAddress;
- ULONG Offset;
- PMM_PAGEOP PageOp;
+ LARGE_INTEGER Offset;
PMM_REGION Region;
- ULONG Entry;
+ ULONG_PTR Entry;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-
- DPRINT("MmAccessFaultSectionView(%x, %x, %x, %x)\n", AddressSpace, MemoryArea, Address, Locked);
+ SWAPENTRY SwapEntry;
+
+ DPRINT("MmAccessFaultSectionView(%p, %p, %p)\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);
+ DPRINT("Address 0x%p\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;
+ Offset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
Segment = MemoryArea->Data.SectionData.Segment;
Section = MemoryArea->Data.SectionData.Section;
Region = MmFindRegion(MemoryArea->StartingAddress,
&MemoryArea->Data.SectionData.RegionListHead,
Address, NULL);
+ ASSERT(Region != NULL);
/*
* Lock the segment
*/
MmLockSectionSegment(Segment);
- OldPage = MmGetPfnForProcess(NULL, Address);
- Entry = MmGetPageEntrySectionSegment(Segment, Offset);
+ 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)))
{
- DPRINT("Address 0x%.8X\n", Address);
+ DPRINT("Address 0x%p\n", Address);
return(STATUS_ACCESS_VIOLATION);
}
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);
}
+ if(OldPage == 0)
+ DPRINT("OldPage == 0!\n");
+
/*
* Get or create a pageop
*/
- PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset,
- MM_PAGEOP_ACCESSFAULT, FALSE);
- if (PageOp == NULL)
- {
- DPRINT1("MmGetPageOp failed\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
+ MmLockSectionSegment(Segment);
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
/*
* Wait for any other operations to complete
*/
- if (PageOp->Thread != PsGetCurrentThread())
+ if (Entry == SWAPENTRY_FROM_SSE(MM_WAIT_ENTRY))
{
- MmUnlockAddressSpace(AddressSpace);
- Status = MmspWaitForPageOpCompletionEvent(PageOp);
- /*
- * Check for various strange conditions
- */
- if (Status == STATUS_TIMEOUT)
- {
- DPRINT1("Failed to wait for page op, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- if (PageOp->Status == STATUS_PENDING)
- {
- DPRINT1("Woke for page op before completion\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- /*
- * Restart the operation
- */
- MmLockAddressSpace(AddressSpace);
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_MM_RESTART_OPERATION);
+ MmUnlockSectionSegment(Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ MiWaitForPageEvent(NULL, NULL);
+ /*
+ * Restart the operation
+ */
+ MmLockAddressSpace(AddressSpace);
+ DPRINT("Address 0x%p\n", Address);
+ return(STATUS_MM_RESTART_OPERATION);
}
+ MmDeleteRmap(OldPage, Process, PAddress);
+ MmDeleteVirtualMapping(Process, PAddress, FALSE, NULL, NULL);
+ MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
+
/*
* Release locks now we have the pageop
*/
+ MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
/*
* 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, OldPage);
MmLockAddressSpace(AddressSpace);
- /*
- * Delete the old entry.
- */
- MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL);
/*
* Set the PTE to point to the new page
*/
+ MmDeletePageFileMapping(Process, PAddress, &SwapEntry);
Status = MmCreateVirtualMapping(Process,
- Address,
+ PAddress,
Region->Protect,
&NewPage,
1);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- return(Status);
- }
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to create virtual mapping\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ return(Status);
+ }
/*
* Unshare the old page.
*/
- MmDeleteRmap(OldPage, Process, PAddress);
+ DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
MmInsertRmap(NewPage, Process, PAddress);
MmLockSectionSegment(Segment);
- MmUnsharePageEntrySectionSegment(Section, Segment, Offset, FALSE, FALSE);
+ MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
MmUnlockSectionSegment(Segment);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
+ MiSetPageEvent(Process, Address);
+ DPRINT("Address 0x%p\n", Address);
return(STATUS_SUCCESS);
}
{
MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
BOOLEAN WasDirty;
- PFN_NUMBER Page;
+ PFN_NUMBER Page = 0;
PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
if (Process)
MmLockSectionSegment(PageOutContext->Segment);
MmUnsharePageEntrySectionSegment((PROS_SECTION_OBJECT)PageOutContext->Section,
PageOutContext->Segment,
- PageOutContext->Offset,
+ &PageOutContext->Offset,
PageOutContext->WasDirty,
- TRUE);
+ TRUE,
+ &PageOutContext->SectionEntry);
MmUnlockSectionSegment(PageOutContext->Segment);
}
if (Process)
{
MmReleasePageMemoryConsumer(MC_USER, Page);
}
-
- DPRINT("PhysicalAddress %x, Address %x\n", Page << PAGE_SHIFT, Address);
}
NTSTATUS
NTAPI
MmPageOutSectionView(PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
- PVOID Address,
- PMM_PAGEOP PageOp)
+ PVOID Address, ULONG_PTR Entry)
{
PFN_NUMBER Page;
MM_SECTION_PAGEOUT_CONTEXT Context;
SWAPENTRY SwapEntry;
- ULONG Entry;
- ULONG FileOffset;
+ ULONGLONG 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.SectionEntry = Entry;
+ Context.CallingProcess = Process;
- Context.Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
- + MemoryArea->Data.SectionData.ViewOffset;
- FileOffset = Context.Offset + Context.Segment->FileOffset;
+ Context.Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
+ FileOffset = Context.Offset.QuadPart + Context.Segment->Image.FileOffset;
IsImageSection = Context.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
FileObject = Context.Section->FileObject;
DirectMapped = FALSE;
+
+ MmLockSectionSegment(Context.Segment);
+
+#ifndef NEWCC
if (FileObject != NULL &&
- !(Context.Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
+ !(Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
{
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
* then note this is a direct mapped page.
*/
if ((FileOffset % PAGE_SIZE) == 0 &&
- (Context.Offset + PAGE_SIZE <= Context.Segment->RawLength || !IsImageSection))
+ (Context.Offset.QuadPart + PAGE_SIZE <= Context.Segment->RawLength.QuadPart || !IsImageSection))
{
DirectMapped = TRUE;
}
}
+#endif
/*
*/
if (Context.Section->AllocationAttributes & SEC_PHYSICALMEMORY)
{
- DPRINT1("Trying to page out from physical memory section address 0x%X "
- "process %d\n", Address,
+ DPRINT1("Trying to page out from physical memory section address 0x%p "
+ "process %p\n", Address,
Process ? Process->UniqueProcessId : 0);
KeBugCheck(MEMORY_MANAGEMENT);
}
/*
* Get the section segment entry and the physical address.
*/
- Entry = MmGetPageEntrySectionSegment(Context.Segment, Context.Offset);
if (!MmIsPagePresent(Process, Address))
{
- DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
+ DPRINT1("Trying to page out not-present page at (%p,0x%p).\n",
Process ? Process->UniqueProcessId : 0, Address);
KeBugCheck(MEMORY_MANAGEMENT);
}
Page = MmGetPfnForProcess(Process, Address);
SwapEntry = MmGetSavedSwapEntryPage(Page);
+ /*
+ * Check the reference count to ensure this page can be paged out
+ */
+ if (MmGetReferenceCountPage(Page) != 1)
+ {
+ DPRINT("Cannot page out locked section page: 0x%lu (RefCount: %lu)\n",
+ Page, MmGetReferenceCountPage(Page));
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+ MmUnlockSectionSegment(Context.Segment);
+ return STATUS_UNSUCCESSFUL;
+ }
+
/*
* Prepare the context structure for the rmap delete call.
*/
+ MmUnlockSectionSegment(Context.Segment);
Context.WasDirty = FALSE;
- if (Context.Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
+ if (Context.Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
IS_SWAP_FROM_SSE(Entry) ||
PFN_FROM_SSE(Entry) != Page)
{
*/
if (DirectMapped && !Context.Private)
{
- if(!MiIsPageFromCache(MemoryArea, Context.Offset))
+ if(!MiIsPageFromCache(MemoryArea, Context.Offset.LowPart))
{
DPRINT1("Direct mapped non private page is not associated with the cache.\n");
KeBugCheck(MEMORY_MANAGEMENT);
MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping);
+ /* Since we passed in a surrogate, we'll get back the page entry
+ * state in our context. This is intended to make intermediate
+ * decrements of share count not release the wait entry.
+ */
+ Entry = Context.SectionEntry;
+
/*
* If this wasn't a private page then we should have reduced the entry to
* zero by deleting all the rmaps.
*/
- if (!Context.Private && MmGetPageEntrySectionSegment(Context.Segment, Context.Offset) != 0)
+ if (!Context.Private && Entry != 0)
{
if (!(Context.Segment->Flags & MM_PAGEFILE_SEGMENT) &&
- !(Context.Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
+ !(Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
{
- KeBugCheck(MEMORY_MANAGEMENT);
+ KeBugCheckEx(MEMORY_MANAGEMENT, Entry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
}
}
{
if (Context.Private)
{
- DPRINT1("Found a %s private page (address %x) in a pagefile segment.\n",
+ DPRINT1("Found a %s private page (address %p) in a pagefile segment.\n",
Context.WasDirty ? "dirty" : "clean", Address);
- KeBugCheck(MEMORY_MANAGEMENT);
+ KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
}
if (!Context.WasDirty && SwapEntry != 0)
{
MmSetSavedSwapEntryPage(Page, 0);
- MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, MAKE_SWAP_SSE(SwapEntry));
+ MmLockSectionSegment(Context.Segment);
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
+ MmUnlockSectionSegment(Context.Segment);
MmReleasePageMemoryConsumer(MC_USER, Page);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
}
- else if (Context.Segment->Characteristics & IMAGE_SCN_MEM_SHARED)
+ else if (Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
{
if (Context.Private)
{
- DPRINT1("Found a %s private page (address %x) in a shared section segment.\n",
+ DPRINT1("Found a %s private page (address %p) in a shared section segment.\n",
Context.WasDirty ? "dirty" : "clean", Address);
- KeBugCheck(MEMORY_MANAGEMENT);
+ KeBugCheckEx(MEMORY_MANAGEMENT, Page, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
}
if (!Context.WasDirty || SwapEntry != 0)
{
MmSetSavedSwapEntryPage(Page, 0);
if (SwapEntry != 0)
{
- MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, MAKE_SWAP_SSE(SwapEntry));
+ MmLockSectionSegment(Context.Segment);
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
+ MmUnlockSectionSegment(Context.Segment);
}
MmReleasePageMemoryConsumer(MC_USER, Page);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
}
{
if (SwapEntry != 0)
{
- DPRINT1("Found a swapentry for a non private and direct mapped page (address %x)\n",
+ DPRINT1("Found a swapentry for a non private and direct mapped page (address %p)\n",
Address);
- KeBugCheck(MEMORY_MANAGEMENT);
+ KeBugCheckEx(MEMORY_MANAGEMENT, STATUS_UNSUCCESSFUL, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address);
}
- Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
+#ifndef NEWCC
+ Status = CcRosUnmapCacheSegment(Bcb, (ULONG)FileOffset, FALSE);
+#else
+ Status = STATUS_SUCCESS;
+#endif
+#ifndef NEWCC
if (!NT_SUCCESS(Status))
{
DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
+ KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Bcb, (ULONG_PTR)FileOffset, (ULONG_PTR)Address);
}
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+#endif
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
else if (!Context.WasDirty && !DirectMapped && !Context.Private)
{
if (SwapEntry != 0)
{
- DPRINT1("Found a swap entry for a non dirty, non private and not direct mapped page (address %x)\n",
+ DPRINT1("Found a swap entry for a non dirty, non private and not direct mapped page (address %p)\n",
Address);
- KeBugCheck(MEMORY_MANAGEMENT);
+ KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, Page, (ULONG_PTR)Process, (ULONG_PTR)Address);
}
MmReleasePageMemoryConsumer(MC_USER, Page);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
{
+ DPRINT("Not dirty and private and not swapped (%p:%p)\n", Process, Address);
MmSetSavedSwapEntryPage(Page, 0);
MmLockAddressSpace(AddressSpace);
Status = MmCreatePageFileMapping(Process,
MmUnlockAddressSpace(AddressSpace);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(MEMORY_MANAGEMENT);
+ DPRINT1("Status %x Swapping out %p:%p\n", Status, Process, Address);
+ KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
}
MmReleasePageMemoryConsumer(MC_USER, Page);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
}
else
{
+ ULONG_PTR OldEntry;
/*
* For non-private pages if the page wasn't direct mapped then
* set it back into the section segment entry so we don't loose
MmInsertRmap(Page,
Process,
Address);
+ // If we got here, the previous entry should have been a wait
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
+ MmLockSectionSegment(Context.Segment);
+ OldEntry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
+ ASSERT(OldEntry == 0 || OldEntry == MAKE_SWAP_SSE(MM_WAIT_ENTRY));
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+ MmUnlockSectionSegment(Context.Segment);
}
MmUnlockAddressSpace(AddressSpace);
- PageOp->Status = STATUS_UNSUCCESSFUL;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_PAGEFILE_QUOTA);
}
}
Process,
Address);
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
}
MmUnlockAddressSpace(AddressSpace);
- PageOp->Status = STATUS_UNSUCCESSFUL;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_UNSUCCESSFUL);
}
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
MmSetSavedSwapEntryPage(Page, 0);
if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
- Context.Segment->Characteristics & IMAGE_SCN_MEM_SHARED)
+ Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
{
- MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, MAKE_SWAP_SSE(SwapEntry));
+ MmLockSectionSegment(Context.Segment);
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
+ MmUnlockSectionSegment(Context.Segment);
}
else
{
if (Context.Private)
{
MmLockAddressSpace(AddressSpace);
+ MmLockSectionSegment(Context.Segment);
Status = MmCreatePageFileMapping(Process,
Address,
SwapEntry);
+ /* We had placed a wait entry upon entry ... replace it before leaving */
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+ MmUnlockSectionSegment(Context.Segment);
MmUnlockAddressSpace(AddressSpace);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(MEMORY_MANAGEMENT);
+ DPRINT1("Status %x Creating page file mapping for %p:%p\n", Status, Process, Address);
+ KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
}
}
else
{
+ MmLockAddressSpace(AddressSpace);
+ MmLockSectionSegment(Context.Segment);
Entry = MAKE_SWAP_SSE(SwapEntry);
- MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
+ /* We had placed a wait entry upon entry ... replace it before leaving */
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+ MmUnlockSectionSegment(Context.Segment);
+ MmUnlockAddressSpace(AddressSpace);
}
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
MmWritePageSectionView(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
- PMM_PAGEOP PageOp)
+ ULONG PageEntry)
{
- ULONG Offset;
+ LARGE_INTEGER Offset;
PROS_SECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
PFN_NUMBER Page;
SWAPENTRY SwapEntry;
- ULONG Entry;
+ ULONG_PTR Entry;
BOOLEAN Private;
NTSTATUS Status;
PFILE_OBJECT FileObject;
Address = (PVOID)PAGE_ROUND_DOWN(Address);
- Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
- + MemoryArea->Data.SectionData.ViewOffset;
+ Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
/*
* Get the segment and section.
FileObject = Section->FileObject;
DirectMapped = FALSE;
if (FileObject != NULL &&
- !(Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
+ !(Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
{
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
* memory area was mapped at an offset in the file which is page aligned
* then note this is a direct mapped page.
*/
- if (((Offset + Segment->FileOffset) % PAGE_SIZE) == 0 &&
- (Offset + PAGE_SIZE <= Segment->RawLength || !IsImageSection))
+ if (((Offset.QuadPart + Segment->Image.FileOffset) % PAGE_SIZE) == 0 &&
+ (Offset.QuadPart + PAGE_SIZE <= Segment->RawLength.QuadPart || !IsImageSection))
{
DirectMapped = TRUE;
}
*/
if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
{
- DPRINT1("Trying to write back page from physical memory mapped at %X "
- "process %d\n", Address,
+ DPRINT1("Trying to write back page from physical memory mapped at %p "
+ "process %p\n", Address,
Process ? Process->UniqueProcessId : 0);
KeBugCheck(MEMORY_MANAGEMENT);
}
/*
* Get the section segment entry and the physical address.
*/
- Entry = MmGetPageEntrySectionSegment(Segment, Offset);
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
if (!MmIsPagePresent(Process, Address))
{
- DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
+ DPRINT1("Trying to page out not-present page at (%p,0x%p).\n",
Process ? Process->UniqueProcessId : 0, Address);
KeBugCheck(MEMORY_MANAGEMENT);
}
/*
* Check for a private (COWed) page.
*/
- if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
+ if (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
IS_SWAP_FROM_SSE(Entry) ||
PFN_FROM_SSE(Entry) != Page)
{
*/
if (DirectMapped && !Private)
{
+ //LARGE_INTEGER SOffset;
ASSERT(SwapEntry == 0);
- CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ //SOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset;
+#ifndef NEWCC
+ CcRosMarkDirtyCacheSegment(Bcb, Offset.LowPart);
+#endif
+ MmLockSectionSegment(Segment);
+ MmSetPageEntrySectionSegment(Segment, &Offset, PageEntry);
+ MmUnlockSectionSegment(Segment);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
if (SwapEntry == 0)
{
MmSetDirtyAllRmaps(Page);
- PageOp->Status = STATUS_UNSUCCESSFUL;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_PAGEFILE_QUOTA);
}
MmSetSavedSwapEntryPage(Page, SwapEntry);
DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
Status);
MmSetDirtyAllRmaps(Page);
- PageOp->Status = STATUS_UNSUCCESSFUL;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_UNSUCCESSFUL);
}
* Otherwise we have succeeded.
*/
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
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 != NULL);
Segment = MemoryArea->Data.SectionData.Segment;
+ MmLockSectionSegment(Segment);
- if ((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) &&
+ if ((Segment->WriteCopy) &&
(NewProtect == PAGE_READWRITE || NewProtect == PAGE_EXECUTE_READWRITE))
{
DoCOW = TRUE;
{
for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
{
+ SWAPENTRY SwapEntry;
PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
ULONG Protect = NewProtect;
+ /* Wait for a wait entry to disappear */
+ do {
+ MmGetPageFileMapping(Process, Address, &SwapEntry);
+ if (SwapEntry != MM_WAIT_ENTRY)
+ break;
+ MiWaitForPageEvent(Process, Address);
+ } while (TRUE);
+
/*
* If we doing COW for this segment then check if the page is
* already private.
*/
if (DoCOW && MmIsPagePresent(Process, Address))
{
- ULONG Offset;
- ULONG Entry;
+ LARGE_INTEGER Offset;
+ ULONG_PTR Entry;
PFN_NUMBER Page;
- Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
- + MemoryArea->Data.SectionData.ViewOffset;
- Entry = MmGetPageEntrySectionSegment(Segment, Offset);
+ Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
+ + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+ /*
+ * An MM_WAIT_ENTRY is ok in this case... It'll just count as
+ * IS_SWAP_FROM_SSE and we'll do the right thing.
+ */
Page = MmGetPfnForProcess(Process, Address);
Protect = PAGE_READONLY;
- if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
+ if (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
IS_SWAP_FROM_SSE(Entry) ||
PFN_FROM_SSE(Entry) != Page)
{
}
}
- if (MmIsPagePresent(Process, Address))
+ if (MmIsPagePresent(Process, Address) || MmIsDisabledPage(Process, Address))
{
MmSetPageProtect(Process, Address,
Protect);
}
}
}
+
+ MmUnlockSectionSegment(Segment);
}
NTSTATUS
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,
BaseAddress, NULL);
+ ASSERT(Region != NULL);
+
if ((MemoryArea->Flags & SEC_NO_CHANGE) &&
Region->Protect != Protect)
{
if (Section->AllocationAttributes & SEC_IMAGE)
{
Segment = MemoryArea->Data.SectionData.Segment;
- Info->AllocationBase = (PUCHAR)MemoryArea->StartingAddress - Segment->VirtualAddress;
+ Info->AllocationBase = (PUCHAR)MemoryArea->StartingAddress - Segment->Image.VirtualAddress;
Info->Type = MEM_IMAGE;
}
else
MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
{
ULONG Length;
- ULONG Offset;
- ULONG Entry;
- ULONG SavedSwapEntry;
+ LARGE_INTEGER Offset;
+ ULONG_PTR Entry;
+ SWAPENTRY SavedSwapEntry;
PFN_NUMBER Page;
Page = 0;
- Length = PAGE_ROUND_UP(Segment->Length);
- for (Offset = 0; Offset < Length; Offset += PAGE_SIZE)
+ MmLockSectionSegment(Segment);
+
+ Length = PAGE_ROUND_UP(Segment->Length.QuadPart);
+ for (Offset.QuadPart = 0; Offset.QuadPart < Length; Offset.QuadPart += PAGE_SIZE)
{
- Entry = MmGetPageEntrySectionSegment(Segment, Offset);
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
if (Entry)
{
+ MmSetPageEntrySectionSegment(Segment, &Offset, 0);
if (IS_SWAP_FROM_SSE(Entry))
{
MmFreeSwapPage(SWAPENTRY_FROM_SSE(Entry));
}
MmReleasePageMemoryConsumer(MC_USER, Page);
}
- MmSetPageEntrySectionSegment(Segment, Offset, 0);
}
}
+
+ MmUnlockSectionSegment(Segment);
}
VOID NTAPI
{
PROS_SECTION_OBJECT Section = (PROS_SECTION_OBJECT)ObjectBody;
- DPRINT("MmpDeleteSection(ObjectBody %x)\n", ObjectBody);
+ DPRINT("MmpDeleteSection(ObjectBody %p)\n", ObjectBody);
if (Section->AllocationAttributes & SEC_IMAGE)
{
ULONG i;
for (i = 0; i < NrSegments; i++)
{
- if (SectionSegments[i].Characteristics & IMAGE_SCN_MEM_SHARED)
+ if (SectionSegments[i].Image.Characteristics & IMAGE_SCN_MEM_SHARED)
{
MmLockSectionSegment(&SectionSegments[i]);
}
RefCount = InterlockedDecrementUL(&SectionSegments[i].ReferenceCount);
- if (SectionSegments[i].Characteristics & IMAGE_SCN_MEM_SHARED)
+ if (SectionSegments[i].Image.Characteristics & IMAGE_SCN_MEM_SHARED)
{
+ MmUnlockSectionSegment(&SectionSegments[i]);
if (RefCount == 0)
{
MmpFreePageFileSegment(&SectionSegments[i]);
}
- MmUnlockSectionSegment(&SectionSegments[i]);
}
}
}
+#ifdef NEWCC
+ else if (Section->Segment && Section->Segment->Flags & MM_DATAFILE_SEGMENT)
+ {
+ ULONG RefCount = 0;
+ PMM_SECTION_SEGMENT Segment = Section->Segment;
+
+ if (Segment &&
+ (RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0)
+ {
+ DPRINT("Freeing section segment\n");
+ Section->Segment = NULL;
+ MmFinalizeSegment(Segment);
+ }
+ else
+ {
+ DPRINT("RefCount %d\n", RefCount);
+ }
+ }
+#endif
else
{
/*
if (Section->Segment->Flags & MM_PAGEFILE_SEGMENT)
{
MmpFreePageFileSegment(Section->Segment);
- MmFreePageTablesSectionSegment(Section->Segment);
+ MmFreePageTablesSectionSegment(Section->Segment, NULL);
ExFreePool(Section->Segment);
Section->Segment = NULL;
}
}
if (Section->FileObject != NULL)
{
+#ifndef NEWCC
CcRosDereferenceCache(Section->FileObject);
+#endif
ObDereferenceObject(Section->FileObject);
Section->FileObject = NULL;
}
IN ULONG ProcessHandleCount,
IN ULONG SystemHandleCount)
{
- DPRINT("MmpCloseSection(OB %x, HC %d)\n",
- Object, ProcessHandleCount);
+ DPRINT("MmpCloseSection(OB %p, HC %lu)\n", Object, ProcessHandleCount);
}
NTSTATUS
&Obj,
&SectionSize,
PAGE_EXECUTE_READWRITE,
- 0,
+ SEC_PHYSICALMEMORY,
NULL,
NULL);
if (!NT_SUCCESS(Status))
DPRINT("Creating Section Object Type\n");
+ /* Initialize the section based root */
+ ASSERT(MmSectionBasedRoot.NumberGenericTableElements == 0);
+ MmSectionBasedRoot.BalancedRoot.u1.Parent = &MmSectionBasedRoot.BalancedRoot;
+
/* Initialize the Section object type */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
RtlInitUnicodeString(&Name, L"Section");
ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
ObjectTypeInitializer.ValidAccessMask = SECTION_ALL_ACCESS;
+ ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &MmSectionObjectType);
-
+
MmCreatePhysicalMemorySection();
return(STATUS_SUCCESS);
if (UMaximumSize == NULL)
{
- return(STATUS_UNSUCCESSFUL);
+ DPRINT1("MmCreatePageFileSection: (UMaximumSize == NULL)\n");
+ return(STATUS_INVALID_PARAMETER);
}
MaximumSize = *UMaximumSize;
(PVOID*)(PVOID)&Section);
if (!NT_SUCCESS(Status))
{
+ DPRINT1("MmCreatePageFileSection: failed to create object (0x%lx)\n", Status);
return(Status);
}
* Initialize it
*/
RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
+ Section->Type = 'SC';
+ Section->Size = 'TN';
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
Section->MaximumSize = MaximumSize;
ObDereferenceObject(Section);
return(STATUS_NO_MEMORY);
}
+ RtlZeroMemory(Segment, sizeof(MM_SECTION_SEGMENT));
Section->Segment = Segment;
Segment->ReferenceCount = 1;
ExInitializeFastMutex(&Segment->Lock);
- Segment->FileOffset = 0;
+ Segment->Image.FileOffset = 0;
Segment->Protection = SectionPageProtection;
- Segment->RawLength = MaximumSize.u.LowPart;
- Segment->Length = PAGE_ROUND_UP(MaximumSize.u.LowPart);
+ Segment->RawLength.QuadPart = MaximumSize.u.LowPart;
+ Segment->Length.QuadPart = PAGE_ROUND_UP(MaximumSize.u.LowPart);
Segment->Flags = MM_PAGEFILE_SEGMENT;
Segment->WriteCopy = FALSE;
- RtlZeroMemory(&Segment->PageDirectory, sizeof(SECTION_PAGE_DIRECTORY));
- Segment->VirtualAddress = 0;
- Segment->Characteristics = 0;
+ Segment->Image.VirtualAddress = 0;
+ Segment->Image.Characteristics = 0;
*SectionObject = Section;
+ MiInitializeSectionPageTable(Segment);
return(STATUS_SUCCESS);
}
-
NTSTATUS
NTAPI
MmCreateDataFileSection(PROS_SECTION_OBJECT *SectionObject,
sizeof(ROS_SECTION_OBJECT),
0,
0,
- (PVOID*)(PVOID)&Section);
+ (PVOID*)&Section);
if (!NT_SUCCESS(Status))
{
return(Status);
* Initialize it
*/
RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
+ Section->Type = 'SC';
+ Section->Size = 'TN';
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
- /*
- * Check file access required
- */
- if (SectionPageProtection & PAGE_READWRITE ||
- SectionPageProtection & PAGE_EXECUTE_READWRITE)
- {
- FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
- }
- else
- {
- FileAccess = FILE_READ_DATA;
- }
-
/*
* Reference the file handle
*/
- Status = ObReferenceObjectByHandle(FileHandle,
+ FileAccess = MiArm3GetCorrectFileAccessMask(SectionPageProtection);
+ Status = ObReferenceObjectByHandle(FileHandle,
FileAccess,
IoFileObjectType,
ExGetPreviousMode(),
ExAcquireFastMutex(&Segment->Lock);
FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment;
- Segment->FileOffset = 0;
+ Segment->Image.FileOffset = 0;
Segment->Protection = SectionPageProtection;
Segment->Flags = MM_DATAFILE_SEGMENT;
- Segment->Characteristics = 0;
- Segment->WriteCopy = FALSE;
+ Segment->Image.Characteristics = 0;
+ Segment->WriteCopy = (SectionPageProtection & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY));
if (AllocationAttributes & SEC_RESERVE)
{
- Segment->Length = Segment->RawLength = 0;
+ Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0;
}
else
{
- Segment->RawLength = MaximumSize.u.LowPart;
- Segment->Length = PAGE_ROUND_UP(Segment->RawLength);
+ Segment->RawLength.QuadPart = MaximumSize.QuadPart;
+ Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
}
- Segment->VirtualAddress = 0;
- RtlZeroMemory(&Segment->PageDirectory, sizeof(SECTION_PAGE_DIRECTORY));
+ Segment->Image.VirtualAddress = 0;
+ Segment->Locked = TRUE;
+ MiInitializeSectionPageTable(Segment);
}
else
{
(void)InterlockedIncrementUL(&Segment->ReferenceCount);
MmLockSectionSegment(Segment);
- if (MaximumSize.u.LowPart > Segment->RawLength &&
+ if (MaximumSize.QuadPart > Segment->RawLength.QuadPart &&
!(AllocationAttributes & SEC_RESERVE))
{
- Segment->RawLength = MaximumSize.u.LowPart;
- Segment->Length = PAGE_ROUND_UP(Segment->RawLength);
+ Segment->RawLength.QuadPart = MaximumSize.QuadPart;
+ Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
}
}
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);
ULONG BufferSize;
ULONG UsedSize;
PVOID Buffer;
+ PFILE_OBJECT FileObject = File;
+ IO_STATUS_BLOCK Iosb;
ASSERT_IRQL_LESS(DISPATCH_LEVEL);
UsedSize = 0;
-#if 0
- Status = MmspPageRead(File,
- Buffer,
- BufferSize,
- &FileOffset,
- &UsedSize);
-#else
-/*
- * FIXME: if we don't use ZwReadFile, caching is not enabled for the file and
- * nothing will work. But using ZwReadFile is wrong, and using its side effects
- * to initialize internal state is even worse. Our cache manager is in need of
- * professional help
- */
- {
- IO_STATUS_BLOCK Iosb;
-
- Status = ZwReadFile(File,
- NULL,
- NULL,
- NULL,
- &Iosb,
- Buffer,
- BufferSize,
- &FileOffset,
- NULL);
+ Status = MiSimpleRead(FileObject, &FileOffset, Buffer, BufferSize, TRUE, &Iosb);
- if(NT_SUCCESS(Status))
- {
- UsedSize = Iosb.Information;
- }
- }
-#endif
+ UsedSize = (ULONG)Iosb.Information;
if(NT_SUCCESS(Status) && UsedSize < OffsetAdjustment)
{
for( i = 1; i < ImageSectionObject->NrSegments; ++ i )
{
- ASSERT(ImageSectionObject->Segments[i].VirtualAddress >=
- ImageSectionObject->Segments[i - 1].VirtualAddress);
+ ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
+ ImageSectionObject->Segments[i - 1].Image.VirtualAddress);
}
}
for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
{
- ASSERT(ImageSectionObject->Segments[i].Length > 0);
+ ASSERT(ImageSectionObject->Segments[i].Length.QuadPart > 0);
if(i > 0)
{
- ASSERT(ImageSectionObject->Segments[i].VirtualAddress >=
- (ImageSectionObject->Segments[i - 1].VirtualAddress +
- ImageSectionObject->Segments[i - 1].Length));
+ ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
+ (ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
+ ImageSectionObject->Segments[i - 1].Length.QuadPart));
}
}
}
for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
{
- ASSERT((ImageSectionObject->Segments[i].VirtualAddress % PAGE_SIZE) == 0);
- ASSERT((ImageSectionObject->Segments[i].Length % PAGE_SIZE) == 0);
+ ASSERT((ImageSectionObject->Segments[i].Image.VirtualAddress % PAGE_SIZE) == 0);
+ ASSERT((ImageSectionObject->Segments[i].Length.QuadPart % PAGE_SIZE) == 0);
}
}
#endif
const MM_SECTION_SEGMENT *Segment2 = (const MM_SECTION_SEGMENT *)y;
return
- (Segment1->VirtualAddress - Segment2->VirtualAddress) >>
+ (Segment1->Image.VirtualAddress - Segment2->Image.VirtualAddress) >>
((sizeof(ULONG_PTR) - sizeof(int)) * 8);
}
for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
{
- if(ImageSectionObject->Segments[i].Length == 0)
+ if(ImageSectionObject->Segments[i].Length.QuadPart == 0)
{
return FALSE;
}
* (NtMapViewOfSection could then refuse to map them, and they could
* e.g. only be allowed as parameters to NtCreateProcess, like on UNIX)
*/
- if ((ImageSectionObject->Segments[i - 1].VirtualAddress +
- ImageSectionObject->Segments[i - 1].Length) !=
- ImageSectionObject->Segments[i].VirtualAddress)
+ if ((ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
+ ImageSectionObject->Segments[i - 1].Length.QuadPart) !=
+ ImageSectionObject->Segments[i].Image.VirtualAddress)
{
return FALSE;
}
ULONG_PTR VirtualAddress;
ULONG_PTR VirtualOffset;
- VirtualAddress = EffectiveSegment->VirtualAddress;
+ VirtualAddress = EffectiveSegment->Image.VirtualAddress;
/* Round down the virtual address to the nearest page */
- EffectiveSegment->VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
+ EffectiveSegment->Image.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.QuadPart = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length.QuadPart) -
+ EffectiveSegment->Image.VirtualAddress;
/* Adjust the raw address and size */
- VirtualOffset = VirtualAddress - EffectiveSegment->VirtualAddress;
+ VirtualOffset = VirtualAddress - EffectiveSegment->Image.VirtualAddress;
- if (EffectiveSegment->FileOffset < VirtualOffset)
+ if (EffectiveSegment->Image.FileOffset < 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->Image.FileOffset -= VirtualOffset;
+ EffectiveSegment->RawLength.QuadPart += VirtualOffset;
}
else
{
PMM_SECTION_SEGMENT Segment = &ImageSectionObject->Segments[i];
ULONG_PTR EndOfEffectiveSegment;
- EndOfEffectiveSegment = EffectiveSegment->VirtualAddress + EffectiveSegment->Length;
+ EndOfEffectiveSegment = (ULONG_PTR)(EffectiveSegment->Image.VirtualAddress + EffectiveSegment->Length.QuadPart);
ASSERT((EndOfEffectiveSegment % PAGE_SIZE) == 0);
/*
* The current segment begins exactly where the current effective
* segment ended, therefore beginning a new effective segment
*/
- if (EndOfEffectiveSegment == Segment->VirtualAddress)
+ if (EndOfEffectiveSegment == Segment->Image.VirtualAddress)
{
LastSegment ++;
ASSERT(LastSegment <= i);
* Page-align the virtual size. We know for sure the virtual address
* already is
*/
- ASSERT((EffectiveSegment->VirtualAddress % PAGE_SIZE) == 0);
- EffectiveSegment->Length = PAGE_ROUND_UP(EffectiveSegment->Length);
+ ASSERT((EffectiveSegment->Image.VirtualAddress % PAGE_SIZE) == 0);
+ EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(EffectiveSegment->Length.QuadPart);
}
/*
* The current segment is still part of the current effective segment:
* extend the effective segment to reflect this
*/
- else if (EndOfEffectiveSegment > Segment->VirtualAddress)
+ else if (EndOfEffectiveSegment > Segment->Image.VirtualAddress)
{
static const ULONG FlagsToProtection[16] =
{
*/
/* Unaligned segments must be contiguous within the file */
- if (Segment->FileOffset != (EffectiveSegment->FileOffset +
- EffectiveSegment->RawLength))
+ if (Segment->Image.FileOffset != (EffectiveSegment->Image.FileOffset +
+ EffectiveSegment->RawLength.QuadPart))
{
return FALSE;
}
- EffectiveSegment->RawLength += Segment->RawLength;
+ EffectiveSegment->RawLength.QuadPart += Segment->RawLength.QuadPart;
/*
* Extend the virtual size
*/
- ASSERT(PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) >= EndOfEffectiveSegment);
+ ASSERT(PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) >= EndOfEffectiveSegment);
- EffectiveSegment->Length = PAGE_ROUND_UP(Segment->VirtualAddress + Segment->Length) -
- EffectiveSegment->VirtualAddress;
+ EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) -
+ EffectiveSegment->Image.VirtualAddress;
/*
* Merge the protection
* Some defaults
*/
/* FIXME? are these values platform-dependent? */
- if(ImageSectionObject->StackReserve == 0)
- ImageSectionObject->StackReserve = 0x40000;
+ if (ImageSectionObject->ImageInformation.MaximumStackSize == 0)
+ ImageSectionObject->ImageInformation.MaximumStackSize = 0x40000;
- if(ImageSectionObject->StackCommit == 0)
- ImageSectionObject->StackCommit = 0x1000;
+ if(ImageSectionObject->ImageInformation.CommittedStackSize == 0)
+ ImageSectionObject->ImageInformation.CommittedStackSize = 0x1000;
- if(ImageSectionObject->ImageBase == 0)
+ if(ImageSectionObject->BasedAddress == NULL)
{
- if(ImageSectionObject->ImageCharacteristics & IMAGE_FILE_DLL)
- ImageSectionObject->ImageBase = 0x10000000;
+ if(ImageSectionObject->ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL)
+ ImageSectionObject->BasedAddress = (PVOID)0x10000000;
else
- ImageSectionObject->ImageBase = 0x00400000;
+ ImageSectionObject->BasedAddress = (PVOID)0x00400000;
}
/*
{
ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock);
ImageSectionObject->Segments[i].ReferenceCount = 1;
-
- RtlZeroMemory(&ImageSectionObject->Segments[i].PageDirectory,
- sizeof(ImageSectionObject->Segments[i].PageDirectory));
+ MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]);
}
ASSERT(NT_SUCCESS(Status));
PLARGE_INTEGER UMaximumSize,
ULONG SectionPageProtection,
ULONG AllocationAttributes,
- HANDLE FileHandle)
+ PFILE_OBJECT FileObject)
{
PROS_SECTION_OBJECT Section;
NTSTATUS Status;
- PFILE_OBJECT FileObject;
PMM_SECTION_SEGMENT SectionSegments;
PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
ULONG i;
- ULONG FileAccess = 0;
-
- /*
- * Specifying a maximum size is meaningless for an image section
- */
- if (UMaximumSize != NULL)
- {
- return(STATUS_INVALID_PARAMETER_4);
- }
-
- /*
- * Check file access required
- */
- if (SectionPageProtection & PAGE_READWRITE ||
- SectionPageProtection & PAGE_EXECUTE_READWRITE)
- {
- FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
- }
- else
- {
- FileAccess = FILE_READ_DATA;
- }
-
- /*
- * Reference the file handle
- */
- Status = ObReferenceObjectByHandle(FileHandle,
- FileAccess,
- IoFileObjectType,
- ExGetPreviousMode(),
- (PVOID*)(PVOID)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+ if (FileObject == NULL)
+ return STATUS_INVALID_FILE_FOR_SECTION;
/*
* Create the section
* Initialize it
*/
RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
+ Section->Type = 'SC';
+ Section->Size = 'TN';
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)
{
RtlZeroMemory(ImageSectionObject, sizeof(MM_IMAGE_SECTION_OBJECT));
- StatusExeFmt = ExeFmtpCreateImageSection(FileHandle, ImageSectionObject);
+ StatusExeFmt = ExeFmtpCreateImageSection(FileObject, ImageSectionObject);
if (!NT_SUCCESS(StatusExeFmt))
{
if(ImageSectionObject->Segments != NULL)
ExFreePool(ImageSectionObject->Segments);
- ExFreePool(ImageSectionObject);
+ ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
ObDereferenceObject(Section);
ObDereferenceObject(FileObject);
return(StatusExeFmt);
Status = STATUS_SUCCESS;
}
Section->FileObject = FileObject;
+#ifndef NEWCC
CcRosReferenceCache(FileObject);
+#endif
//KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
*SectionObject = Section;
return(Status);
}
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-NtCreateSection (OUT PHANDLE SectionHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
- IN PLARGE_INTEGER MaximumSize OPTIONAL,
- IN ULONG SectionPageProtection OPTIONAL,
- IN ULONG AllocationAttributes,
- IN HANDLE FileHandle OPTIONAL)
-{
- LARGE_INTEGER SafeMaximumSize;
- PVOID SectionObject;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousMode != KernelMode)
- {
- _SEH2_TRY
- {
- if (MaximumSize != NULL)
- {
- /* make a copy on the stack */
- SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
- MaximumSize = &SafeMaximumSize;
- }
- ProbeForWriteHandle(SectionHandle);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
- }
-
- Status = MmCreateSection(&SectionObject,
- DesiredAccess,
- ObjectAttributes,
- MaximumSize,
- SectionPageProtection,
- AllocationAttributes,
- FileHandle,
- NULL);
- if (NT_SUCCESS(Status))
- {
- Status = ObInsertObject ((PVOID)SectionObject,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- SectionHandle);
- }
-
- return Status;
-}
-
-
-/**********************************************************************
- * NAME
- * NtOpenSection
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- * SectionHandle
- *
- * DesiredAccess
- *
- * ObjectAttributes
- *
- * RETURN VALUE
- *
- * REVISIONS
- */
-NTSTATUS NTAPI
-NtOpenSection(PHANDLE SectionHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes)
-{
- HANDLE hSection;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousMode != KernelMode)
- {
- _SEH2_TRY
- {
- ProbeForWriteHandle(SectionHandle);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
- }
-
- Status = ObOpenObjectByName(ObjectAttributes,
- MmSectionObjectType,
- PreviousMode,
- NULL,
- DesiredAccess,
- NULL,
- &hSection);
-
- if(NT_SUCCESS(Status))
- {
- _SEH2_TRY
- {
- *SectionHandle = hSection;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
- }
- return(Status);
-}
static NTSTATUS
MmMapViewOfSegment(PMMSUPPORT AddressSpace,
{
PMEMORY_AREA MArea;
NTSTATUS Status;
- PHYSICAL_ADDRESS BoundaryAddressMultiple;
-
- BoundaryAddressMultiple.QuadPart = 0;
-
- Status = MmCreateMemoryArea(AddressSpace,
- MEMORY_AREA_SECTION_VIEW,
- BaseAddress,
- ViewSize,
- Protect,
- &MArea,
- FALSE,
- AllocationType,
- BoundaryAddressMultiple);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Mapping between 0x%.8X and 0x%.8X failed (%X).\n",
- (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status);
- return(Status);
- }
-
- ObReferenceObject((PVOID)Section);
-
- 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);
-
- return(STATUS_SUCCESS);
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * NtMapViewOfSection
- *
- * DESCRIPTION
- * Maps a view of a section into the virtual address space of a
- * process.
- *
- * ARGUMENTS
- * SectionHandle
- * Handle of the section.
- *
- * ProcessHandle
- * Handle of the process.
- *
- * BaseAddress
- * Desired base address (or NULL) on entry;
- * Actual base address of the view on exit.
- *
- * ZeroBits
- * Number of high order address bits that must be zero.
- *
- * CommitSize
- * Size in bytes of the initially committed section of
- * the view.
- *
- * SectionOffset
- * Offset in bytes from the beginning of the section
- * to the beginning of the view.
- *
- * ViewSize
- * Desired length of map (or zero to map all) on entry
- * Actual length mapped on exit.
- *
- * InheritDisposition
- * Specified how the view is to be shared with
- * child processes.
- *
- * AllocateType
- * Type of allocation for the pages.
- *
- * Protect
- * Protection for the committed region of the view.
- *
- * RETURN VALUE
- * Status.
- *
- * @implemented
- */
-NTSTATUS NTAPI
-NtMapViewOfSection(IN HANDLE SectionHandle,
- IN HANDLE ProcessHandle,
- IN OUT PVOID* BaseAddress OPTIONAL,
- IN ULONG_PTR ZeroBits OPTIONAL,
- IN SIZE_T CommitSize,
- IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
- IN OUT PSIZE_T ViewSize,
- IN SECTION_INHERIT InheritDisposition,
- IN ULONG AllocationType OPTIONAL,
- IN ULONG Protect)
-{
- PVOID SafeBaseAddress;
- LARGE_INTEGER SafeSectionOffset;
- SIZE_T SafeViewSize;
- PROS_SECTION_OBJECT Section;
- PEPROCESS Process;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
- ULONG tmpProtect;
- ACCESS_MASK DesiredAccess;
-
- /*
- * Check the protection
- */
- if (Protect & ~PAGE_FLAGS_VALID_FROM_USER_MODE)
- {
- return STATUS_INVALID_PARAMETER_10;
- }
-
- tmpProtect = Protect & ~(PAGE_GUARD|PAGE_NOCACHE);
- if (tmpProtect != PAGE_NOACCESS &&
- tmpProtect != PAGE_READONLY &&
- tmpProtect != PAGE_READWRITE &&
- tmpProtect != PAGE_WRITECOPY &&
- tmpProtect != PAGE_EXECUTE &&
- tmpProtect != PAGE_EXECUTE_READ &&
- tmpProtect != PAGE_EXECUTE_READWRITE &&
- tmpProtect != PAGE_EXECUTE_WRITECOPY)
- {
- return STATUS_INVALID_PAGE_PROTECTION;
- }
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousMode != KernelMode)
- {
- SafeBaseAddress = NULL;
- SafeSectionOffset.QuadPart = 0;
- SafeViewSize = 0;
-
- _SEH2_TRY
- {
- if(BaseAddress != NULL)
- {
- ProbeForWritePointer(BaseAddress);
- SafeBaseAddress = *BaseAddress;
- }
- if(SectionOffset != NULL)
- {
- ProbeForWriteLargeInteger(SectionOffset);
- SafeSectionOffset = *SectionOffset;
- }
- ProbeForWriteSize_t(ViewSize);
- SafeViewSize = *ViewSize;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
- }
- else
- {
- SafeBaseAddress = (BaseAddress != NULL ? *BaseAddress : NULL);
- SafeSectionOffset.QuadPart = (SectionOffset != NULL ? SectionOffset->QuadPart : 0);
- SafeViewSize = (ViewSize != NULL ? *ViewSize : 0);
- }
-
- SafeSectionOffset.LowPart = PAGE_ROUND_DOWN(SafeSectionOffset.LowPart);
-
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_VM_OPERATION,
- PsProcessType,
- PreviousMode,
- (PVOID*)(PVOID)&Process,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- /* Convert NT Protection Attr to Access Mask */
- if (Protect == PAGE_READONLY)
- {
- DesiredAccess = SECTION_MAP_READ;
- }
- else if (Protect == PAGE_READWRITE)
- {
- DesiredAccess = SECTION_MAP_WRITE;
- }
- else if (Protect == PAGE_WRITECOPY)
- {
- DesiredAccess = SECTION_QUERY;
- }
- /* FIXME: Handle other Protection Attributes. For now keep previous behavior */
+ ULONG Granularity;
+
+ if (Segment->WriteCopy)
+ {
+ /* We have to do this because the not present fault
+ * and access fault handlers depend on the protection
+ * that should be granted AFTER the COW fault takes
+ * place to be in Region->Protect. The not present fault
+ * handler changes this to the correct protection for COW when
+ * mapping the pages into the process's address space. If a COW
+ * fault takes place, the access fault handler sets the page protection
+ * to these values for the newly copied pages
+ */
+ if (Protect == PAGE_WRITECOPY)
+ Protect = PAGE_READWRITE;
+ else if (Protect == PAGE_EXECUTE_WRITECOPY)
+ Protect = PAGE_EXECUTE_READWRITE;
+ }
+
+ if (*BaseAddress == NULL)
+ Granularity = MM_ALLOCATION_GRANULARITY;
else
- {
- DesiredAccess = SECTION_MAP_READ;
- }
+ Granularity = PAGE_SIZE;
- Status = ObReferenceObjectByHandle(SectionHandle,
- DesiredAccess,
- MmSectionObjectType,
- PreviousMode,
- (PVOID*)(PVOID)&Section,
- NULL);
- if (!(NT_SUCCESS(Status)))
- {
- DPRINT("ObReference failed rc=%x\n",Status);
- ObDereferenceObject(Process);
- return(Status);
+#ifdef NEWCC
+ if (Segment->Flags & MM_DATAFILE_SEGMENT) {
+ LARGE_INTEGER FileOffset;
+ FileOffset.QuadPart = ViewOffset;
+ ObReferenceObject(Section);
+ return _MiMapViewOfSegment(AddressSpace, Segment, BaseAddress, ViewSize, Protect, &FileOffset, AllocationType, __FILE__, __LINE__);
}
-
- Status = MmMapViewOfSection(Section,
- (PEPROCESS)Process,
- (BaseAddress != NULL ? &SafeBaseAddress : NULL),
- ZeroBits,
- CommitSize,
- (SectionOffset != NULL ? &SafeSectionOffset : NULL),
- (ViewSize != NULL ? &SafeViewSize : NULL),
- InheritDisposition,
+#endif
+ Status = MmCreateMemoryArea(AddressSpace,
+ MEMORY_AREA_SECTION_VIEW,
+ BaseAddress,
+ ViewSize,
+ Protect,
+ &MArea,
+ FALSE,
AllocationType,
- Protect);
-
- /* Check if this is an image for the current process */
- if ((Section->AllocationAttributes & SEC_IMAGE) &&
- (Process == PsGetCurrentProcess()) &&
- (Status != STATUS_IMAGE_NOT_AT_BASE))
+ Granularity);
+ if (!NT_SUCCESS(Status))
{
- /* Notify the debugger */
- DbgkMapViewOfSection(Section,
- SafeBaseAddress,
- SafeSectionOffset.LowPart,
- SafeViewSize);
+ DPRINT1("Mapping between 0x%p and 0x%p failed (%X).\n",
+ (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status);
+ return(Status);
}
- ObDereferenceObject(Section);
- ObDereferenceObject(Process);
+ ObReferenceObject((PVOID)Section);
- if(NT_SUCCESS(Status))
- {
- /* copy parameters back to the caller */
- _SEH2_TRY
- {
- if(BaseAddress != NULL)
- {
- *BaseAddress = SafeBaseAddress;
- }
- if(SectionOffset != NULL)
- {
- *SectionOffset = SafeSectionOffset;
- }
- if(ViewSize != NULL)
- {
- *ViewSize = SafeViewSize;
- }
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
- }
+ MArea->Data.SectionData.Segment = Segment;
+ MArea->Data.SectionData.Section = Section;
+ MArea->Data.SectionData.ViewOffset.QuadPart = ViewOffset;
+ MmInitializeRegion(&MArea->Data.SectionData.RegionListHead,
+ ViewSize, 0, Protect);
- return(Status);
+ return(STATUS_SUCCESS);
}
+
static VOID
MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
{
- ULONG Entry;
+ ULONG_PTR Entry;
PFILE_OBJECT FileObject;
PBCB Bcb;
- ULONG Offset;
+ LARGE_INTEGER Offset;
SWAPENTRY SavedSwapEntry;
- PMM_PAGEOP PageOp;
- NTSTATUS Status;
PROS_SECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
PMMSUPPORT AddressSpace;
Address = (PVOID)PAGE_ROUND_DOWN(Address);
- Offset = ((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress) +
- MemoryArea->Data.SectionData.ViewOffset;
+ Offset.QuadPart = ((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress) +
+ MemoryArea->Data.SectionData.ViewOffset.QuadPart;
Section = MemoryArea->Data.SectionData.Section;
Segment = MemoryArea->Data.SectionData.Segment;
- PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset);
-
- while (PageOp)
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+ while (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
{
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
- Status = MmspWaitForPageOpCompletionEvent(PageOp);
- if (Status != STATUS_SUCCESS)
- {
- DPRINT1("Failed to wait for page op, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
+ MiWaitForPageEvent(NULL, NULL);
MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Segment);
- MmspCompleteAndReleasePageOp(PageOp);
- PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset);
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
}
- Entry = MmGetPageEntrySectionSegment(Segment, Offset);
-
/*
* For a dirty, datafile, non-private page mark it as dirty in the
* cache manager.
{
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
- CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
+#ifndef NEWCC
+ CcRosMarkDirtyCacheSegment(Bcb, (ULONG)(Offset.QuadPart + Segment->Image.FileOffset));
+#endif
ASSERT(SwapEntry == 0);
}
}
else
{
MmDeleteRmap(Page, Process, Address);
- MmUnsharePageEntrySectionSegment(Section, Segment, Offset, Dirty, FALSE);
+ MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE, NULL);
}
}
}
Section = MemoryArea->Data.SectionData.Section;
Segment = MemoryArea->Data.SectionData.Segment;
+#ifdef NEWCC
+ if (Segment->Flags & MM_DATAFILE_SEGMENT)
+ return MmUnmapViewOfCacheSegment(AddressSpace, BaseAddress);
+#endif
+
MmLockSectionSegment(Segment);
RegionListHead = &MemoryArea->Data.SectionData.RegionListHead;
return(Status);
}
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-MmUnmapViewOfSection(PEPROCESS Process,
- PVOID BaseAddress)
+NTSTATUS
+NTAPI
+MiRosUnmapViewOfSection(IN PEPROCESS Process,
+ IN PVOID BaseAddress,
+ IN ULONG Flags)
{
NTSTATUS Status;
PMEMORY_AREA MemoryArea;
PMMSUPPORT AddressSpace;
PROS_SECTION_OBJECT Section;
- PMM_PAGEOP PageOp;
- ULONG_PTR Offset;
- PVOID ImageBaseAddress = 0;
+ PVOID ImageBaseAddress = 0;
- DPRINT("Opening memory area Process %x BaseAddress %x\n",
+ DPRINT("Opening memory area Process %p BaseAddress %p\n",
Process, BaseAddress);
ASSERT(Process);
- AddressSpace = &Process->Vm;
+ AddressSpace = Process ? &Process->Vm : MmGetKernelAddressSpace();
MmLockAddressSpace(AddressSpace);
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
MemoryArea->Type != MEMORY_AREA_SECTION_VIEW ||
MemoryArea->DeleteInProgress)
{
+ if (MemoryArea) NT_ASSERT(MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3);
MmUnlockAddressSpace(AddressSpace);
return STATUS_NOT_MAPPED_VIEW;
}
MemoryArea->DeleteInProgress = TRUE;
- while (MemoryArea->PageOpCount)
- {
- Offset = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)MemoryArea->StartingAddress);
-
- while (Offset)
- {
- Offset -= PAGE_SIZE;
- PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL,
- MemoryArea->Data.SectionData.Segment,
- Offset + MemoryArea->Data.SectionData.ViewOffset);
- if (PageOp)
- {
- MmUnlockAddressSpace(AddressSpace);
- Status = MmspWaitForPageOpCompletionEvent(PageOp);
- if (Status != STATUS_SUCCESS)
- {
- DPRINT1("Failed to wait for page op, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- MmLockAddressSpace(AddressSpace);
- MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
- BaseAddress);
- if (MemoryArea == NULL ||
- MemoryArea->Type != MEMORY_AREA_SECTION_VIEW)
- {
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_NOT_MAPPED_VIEW;
- }
- break;
- }
- }
- }
-
Section = MemoryArea->Data.SectionData.Section;
if (Section->AllocationAttributes & SEC_IMAGE)
* and calculate the image base address */
for (i = 0; i < NrSegments; i++)
{
- if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+ if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
{
if (Segment == &SectionSegments[i])
{
- ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].VirtualAddress;
+ ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
break;
}
}
for (i = 0; i < NrSegments; i++)
{
- if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+ if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
{
PVOID SBaseAddress = (PVOID)
- ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].VirtualAddress);
+ ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
+ NT_ASSERT(NT_SUCCESS(Status));
}
}
}
else
{
Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress);
+ NT_ASSERT(NT_SUCCESS(Status));
}
MmUnlockAddressSpace(AddressSpace);
return(STATUS_SUCCESS);
}
-/**********************************************************************
- * NAME EXPORTED
- * NtUnmapViewOfSection
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- * ProcessHandle
- *
- * BaseAddress
- *
- * RETURN VALUE
- * Status.
- *
- * REVISIONS
- */
-NTSTATUS NTAPI
-NtUnmapViewOfSection (HANDLE ProcessHandle,
- PVOID BaseAddress)
-{
- PEPROCESS Process;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
-
- DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n",
- ProcessHandle, BaseAddress);
-
- PreviousMode = ExGetPreviousMode();
-
- DPRINT("Referencing process\n");
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_VM_OPERATION,
- PsProcessType,
- PreviousMode,
- (PVOID*)(PVOID)&Process,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("ObReferenceObjectByHandle failed (Status %x)\n", Status);
- return(Status);
- }
- Status = MmUnmapViewOfSection(Process, BaseAddress);
-
- ObDereferenceObject(Process);
-
- return Status;
-}
/**
ExSectionInfoClass,
sizeof(ExSectionInfoClass) / sizeof(ExSectionInfoClass[0]),
SectionInformation,
- SectionInformationLength,
+ (ULONG)SectionInformationLength,
NULL,
ResultLength,
PreviousMode);
}
else
{
- Sbi->BaseAddress = (PVOID)Section->Segment->VirtualAddress;
- Sbi->Size.QuadPart = Section->Segment->Length;
+ Sbi->BaseAddress = (PVOID)Section->Segment->Image.VirtualAddress;
+ Sbi->Size.QuadPart = Section->Segment->Length.QuadPart;
}
if (ResultLength != NULL)
_SEH2_TRY
{
- memset(Sii, 0, sizeof(SECTION_IMAGE_INFORMATION));
if (Section->AllocationAttributes & SEC_IMAGE)
{
PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
ImageSectionObject = Section->ImageSection;
- Sii->TransferAddress = (PVOID)ImageSectionObject->EntryPoint;
- Sii->MaximumStackSize = ImageSectionObject->StackReserve;
- Sii->CommittedStackSize = ImageSectionObject->StackCommit;
- Sii->SubSystemType = ImageSectionObject->Subsystem;
- Sii->SubSystemMinorVersion = ImageSectionObject->MinorSubsystemVersion;
- Sii->SubSystemMajorVersion = ImageSectionObject->MajorSubsystemVersion;
- Sii->ImageCharacteristics = ImageSectionObject->ImageCharacteristics;
- Sii->Machine = ImageSectionObject->Machine;
- Sii->ImageContainsCode = ImageSectionObject->Executable;
+ *Sii = ImageSectionObject->ImageInformation;
}
if (ResultLength != NULL)
return(Status);
}
-
-/**
- * Extends size of file backed section.
- *
- * @param SectionHandle
- * Handle to the section object. It must be opened with
- * SECTION_EXTEND_SIZE access.
- * @param NewMaximumSize
- * New maximum size of the section in bytes.
- *
- * @return Status.
- *
- * @todo Move the actual code to internal function MmExtendSection.
- * @unimplemented
- */
-NTSTATUS NTAPI
-NtExtendSection(IN HANDLE SectionHandle,
- IN PLARGE_INTEGER NewMaximumSize)
-{
- LARGE_INTEGER SafeNewMaximumSize;
- PROS_SECTION_OBJECT Section;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousMode != KernelMode)
- {
- _SEH2_TRY
- {
- /* make a copy on the stack */
- SafeNewMaximumSize = ProbeForReadLargeInteger(NewMaximumSize);
- NewMaximumSize = &SafeNewMaximumSize;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
- }
-
- Status = ObReferenceObjectByHandle(SectionHandle,
- SECTION_EXTEND_SIZE,
- MmSectionObjectType,
- PreviousMode,
- (PVOID*)&Section,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- if (!(Section->AllocationAttributes & SEC_FILE))
- {
- ObDereferenceObject(Section);
- return STATUS_INVALID_PARAMETER;
- }
-
- /*
- * - Acquire file extneding resource.
- * - Check if we're not resizing the section below it's actual size!
- * - Extend segments if needed.
- * - Set file information (FileAllocationInformation) to the new size.
- * - Release file extending resource.
- */
-
- ObDereferenceObject(Section);
-
- return STATUS_NOT_IMPLEMENTED;
-}
-
/**********************************************************************
* NAME EXPORTED
* MmMapViewOfSection
PMMSUPPORT AddressSpace;
ULONG ViewOffset;
NTSTATUS Status = STATUS_SUCCESS;
+ BOOLEAN NotAtBase = FALSE;
+
+ if (MiIsRosSectionObject(SectionObject) == FALSE)
+ {
+ DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
+ return MmMapViewOfArm3Section(SectionObject,
+ 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;
SectionSegments = ImageSectionObject->Segments;
NrSegments = ImageSectionObject->NrSegments;
-
ImageBase = (ULONG_PTR)*BaseAddress;
if (ImageBase == 0)
{
- ImageBase = ImageSectionObject->ImageBase;
+ ImageBase = (ULONG_PTR)ImageSectionObject->BasedAddress;
}
ImageSize = 0;
for (i = 0; i < NrSegments; i++)
{
- if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+ if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
{
ULONG_PTR MaxExtent;
- MaxExtent = (ULONG_PTR)SectionSegments[i].VirtualAddress +
- SectionSegments[i].Length;
+ MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
+ SectionSegments[i].Length.QuadPart);
ImageSize = max(ImageSize, MaxExtent);
}
}
- ImageSectionObject->ImageSize = ImageSize;
+ ImageSectionObject->ImageInformation.ImageFileSize = (ULONG)ImageSize;
+
+ /* Check for an illegal base address */
+ if (((ImageBase + ImageSize) > (ULONG_PTR)MmHighestUserAddress) ||
+ ((ImageBase + ImageSize) < ImageSize))
+ {
+ NT_ASSERT(*BaseAddress == NULL);
+ ImageBase = ALIGN_DOWN_BY((ULONG_PTR)MmHighestUserAddress - ImageSize,
+ MM_VIRTMEM_GRANULARITY);
+ NotAtBase = TRUE;
+ }
+ else if (ImageBase != ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY))
+ {
+ NT_ASSERT(*BaseAddress == NULL);
+ ImageBase = ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY);
+ NotAtBase = TRUE;
+ }
/* Check there is enough space to map the section at that point. */
if (MmLocateMemoryAreaByRegion(AddressSpace, (PVOID)ImageBase,
if ((*BaseAddress) != NULL)
{
MmUnlockAddressSpace(AddressSpace);
- return(STATUS_UNSUCCESSFUL);
+ return(STATUS_CONFLICTING_ADDRESSES);
}
/* Otherwise find a gap to map the image. */
- ImageBase = (ULONG_PTR)MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), PAGE_SIZE, FALSE);
+ ImageBase = (ULONG_PTR)MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), MM_VIRTMEM_GRANULARITY, FALSE);
if (ImageBase == 0)
{
MmUnlockAddressSpace(AddressSpace);
- return(STATUS_UNSUCCESSFUL);
+ return(STATUS_CONFLICTING_ADDRESSES);
}
+ /* 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))
+ if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
{
PVOID SBaseAddress = (PVOID)
- ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].VirtualAddress);
+ ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
MmLockSectionSegment(&SectionSegments[i]);
Status = MmMapViewOfSegment(AddressSpace,
Section,
&SectionSegments[i],
&SBaseAddress,
- SectionSegments[i].Length,
+ SectionSegments[i].Length.LowPart,
SectionSegments[i].Protection,
0,
0);
}
*BaseAddress = (PVOID)ImageBase;
+ *ViewSize = ImageSize;
}
else
{
}
MmUnlockAddressSpace(AddressSpace);
+ NT_ASSERT(*BaseAddress == ALIGN_DOWN_POINTER_BY(*BaseAddress, MM_VIRTMEM_GRANULARITY));
- return(STATUS_SUCCESS);
+ if (NotAtBase)
+ Status = STATUS_IMAGE_NOT_AT_BASE;
+ else
+ Status = STATUS_SUCCESS;
+
+ return Status;
}
/*
if (Segment->ReferenceCount != 0)
{
+#ifdef NEWCC
+ CC_FILE_SIZES FileSizes;
+ CcpLock();
+ if (SectionObjectPointer->SharedCacheMap && (Segment->ReferenceCount > CcpCountCacheSections((PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap)))
+ {
+ CcpUnlock();
+ /* Check size of file */
+ if (SectionObjectPointer->SharedCacheMap)
+ {
+ if (!CcGetFileSizes(Segment->FileObject, &FileSizes))
+ {
+ return FALSE;
+ }
+
+ if (NewFileSize->QuadPart <= FileSizes.FileSize.QuadPart)
+ {
+ return FALSE;
+ }
+ }
+ }
+ else
+ CcpUnlock();
+#else
/* Check size of file */
if (SectionObjectPointer->SharedCacheMap)
{
return FALSE;
}
}
+#endif
}
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");
}
}
-/*
- * @unimplemented
- */
-BOOLEAN NTAPI
-MmDisableModifiedWriteOfSection (ULONG Unknown0)
-{
- UNIMPLEMENTED;
- return (FALSE);
-}
+
/*
* @implemented
MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
IN MMFLUSH_TYPE FlushType)
{
+ BOOLEAN Result = TRUE;
+#ifdef NEWCC
+ PMM_SECTION_SEGMENT Segment;
+#endif
+
switch(FlushType)
{
case MmFlushForDelete:
{
return FALSE;
}
+#ifndef NEWCC
CcRosSetRemoveOnClose(SectionObjectPointer);
+#endif
return TRUE;
case MmFlushForWrite:
- break;
+ {
+ DPRINT("MmFlushImageSection(%d)\n", FlushType);
+#ifdef NEWCC
+ Segment = (PMM_SECTION_SEGMENT)SectionObjectPointer->DataSectionObject;
+#endif
+
+ if (SectionObjectPointer->ImageSectionObject) {
+ DPRINT1("SectionObject has ImageSection\n");
+ return FALSE;
+ }
+
+#ifdef NEWCC
+ CcpLock();
+ Result = !SectionObjectPointer->SharedCacheMap || (Segment->ReferenceCount == CcpCountCacheSections((PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap));
+ CcpUnlock();
+ DPRINT("Result %d\n", Result);
+#endif
+ return Result;
+ }
}
return FALSE;
}
-/*
- * @unimplemented
- */
-BOOLEAN NTAPI
-MmForceSectionClosed (
- IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
- IN BOOLEAN DelayClose)
-{
- UNIMPLEMENTED;
- return (FALSE);
-}
-
-
/*
* @implemented
*/
PROS_SECTION_OBJECT Section;
PMMSUPPORT AddressSpace;
NTSTATUS Status;
+ PAGED_CODE();
+
+ if (MiIsRosSectionObject(SectionObject) == FALSE)
+ {
+ return MiMapViewInSystemSpace(SectionObject,
+ &MmSession,
+ MappedBase,
+ ViewSize);
+ }
DPRINT("MmMapViewInSystemSpace() called\n");
return Status;
}
-/*
- * @unimplemented
- */
NTSTATUS
NTAPI
-MmMapViewInSessionSpace (
- IN PVOID Section,
- OUT PVOID *MappedBase,
- IN OUT PSIZE_T ViewSize
- )
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-MmUnmapViewInSystemSpace (IN PVOID MappedBase)
+MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
{
PMMSUPPORT AddressSpace;
NTSTATUS Status;
AddressSpace = MmGetKernelAddressSpace();
+ MmLockAddressSpace(AddressSpace);
+
Status = MmUnmapViewOfSegment(AddressSpace, MappedBase);
- return Status;
-}
+ MmUnlockAddressSpace(AddressSpace);
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-MmUnmapViewInSessionSpace (
- IN PVOID MappedBase
- )
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ return Status;
}
/**********************************************************************
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL,
- IN PFILE_OBJECT File OPTIONAL)
+ IN PFILE_OBJECT FileObject OPTIONAL)
{
- ULONG Protection;
- PROS_SECTION_OBJECT *SectionObject = (PROS_SECTION_OBJECT *)Section;
+ NTSTATUS Status;
+ ULONG Protection;
+ PROS_SECTION_OBJECT *SectionObject = (PROS_SECTION_OBJECT *)Section;
- /*
- * Check the protection
- */
- Protection = SectionPageProtection & ~(PAGE_GUARD|PAGE_NOCACHE);
- if (Protection != PAGE_READONLY &&
- Protection != PAGE_READWRITE &&
- Protection != PAGE_WRITECOPY &&
- Protection != PAGE_EXECUTE &&
- Protection != PAGE_EXECUTE_READ &&
- Protection != PAGE_EXECUTE_READWRITE &&
- Protection != PAGE_EXECUTE_WRITECOPY)
- {
- return STATUS_INVALID_PAGE_PROTECTION;
- }
-
- if (AllocationAttributes & SEC_IMAGE)
- {
- return(MmCreateImageSection(SectionObject,
- DesiredAccess,
- ObjectAttributes,
- MaximumSize,
- SectionPageProtection,
- AllocationAttributes,
- FileHandle));
- }
-
- if (FileHandle != NULL)
- {
- return(MmCreateDataFileSection(SectionObject,
- DesiredAccess,
- ObjectAttributes,
- MaximumSize,
- SectionPageProtection,
- AllocationAttributes,
- FileHandle));
- }
-
- return(MmCreatePageFileSection(SectionObject,
- DesiredAccess,
- ObjectAttributes,
- MaximumSize,
- SectionPageProtection,
- AllocationAttributes));
-}
+ /* Check if an ARM3 section is being created instead */
+ if (!(AllocationAttributes & (SEC_IMAGE | SEC_PHYSICALMEMORY)))
+ {
+ if (!(FileObject) && !(FileHandle))
+ {
+ return MmCreateArm3Section(Section,
+ DesiredAccess,
+ ObjectAttributes,
+ MaximumSize,
+ SectionPageProtection,
+ AllocationAttributes &~ 1,
+ FileHandle,
+ FileObject);
+ }
+ }
-NTSTATUS
-NTAPI
-NtAreMappedFilesTheSame(IN PVOID File1MappedAsAnImage,
- IN PVOID File2MappedAsFile)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
+ /* Convert section flag to page flag */
+ if (AllocationAttributes & SEC_NOCACHE) SectionPageProtection |= PAGE_NOCACHE;
+
+ /* Check to make sure the protection is correct. Nt* does this already */
+ Protection = MiMakeProtectionMask(SectionPageProtection);
+ if (Protection == MM_INVALID_PROTECTION)
+ {
+ DPRINT1("Page protection is invalid\n");
+ return STATUS_INVALID_PAGE_PROTECTION;
+ }
+
+ /* Check if this is going to be a data or image backed file section */
+ if ((FileHandle) || (FileObject))
+ {
+ /* These cannot be mapped with large pages */
+ if (AllocationAttributes & SEC_LARGE_PAGES)
+ {
+ DPRINT1("Large pages cannot be used with an image mapping\n");
+ return STATUS_INVALID_PARAMETER_6;
+ }
+
+ /* Did the caller pass an object? */
+ if (FileObject)
+ {
+ /* Reference the object directly */
+ ObReferenceObject(FileObject);
+ }
+ else
+ {
+ /* Reference the file handle to get the object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ MmMakeFileAccess[Protection],
+ IoFileObjectType,
+ ExGetPreviousMode(),
+ (PVOID*)&FileObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to get a handle to the FO: %lx\n", Status);
+ return Status;
+ }
+ }
+ }
+ else
+ {
+ /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
+ if (AllocationAttributes & SEC_IMAGE) return STATUS_INVALID_FILE_FOR_SECTION;
+ }
+
+#ifndef NEWCC // A hack for initializing caching.
+ // This is needed only in the old case.
+ if (FileHandle)
+ {
+ IO_STATUS_BLOCK Iosb;
+ NTSTATUS Status;
+ CHAR Buffer;
+ LARGE_INTEGER ByteOffset;
+ ByteOffset.QuadPart = 0;
+ Status = ZwReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ &Buffer,
+ sizeof(Buffer),
+ &ByteOffset,
+ NULL);
+ if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
+ {
+ DPRINT1("CC failure: %lx\n", Status);
+ return Status;
+ }
+ // Caching is initialized...
+ }
+#endif
+
+ if (AllocationAttributes & SEC_IMAGE)
+ {
+ Status = MmCreateImageSection(SectionObject,
+ DesiredAccess,
+ ObjectAttributes,
+ MaximumSize,
+ SectionPageProtection,
+ AllocationAttributes,
+ FileObject);
+ }
+#ifndef NEWCC
+ else if (FileHandle != NULL)
+ {
+ Status = MmCreateDataFileSection(SectionObject,
+ DesiredAccess,
+ ObjectAttributes,
+ MaximumSize,
+ SectionPageProtection,
+ AllocationAttributes,
+ FileHandle);
+ if (FileObject)
+ ObDereferenceObject(FileObject);
+ }
+#else
+ else if (FileHandle != NULL || FileObject != NULL)
+ {
+ Status = MmCreateCacheSection(SectionObject,
+ DesiredAccess,
+ ObjectAttributes,
+ MaximumSize,
+ SectionPageProtection,
+ AllocationAttributes,
+ FileObject);
+ }
+#endif
+ else
+ {
+ if ((AllocationAttributes & SEC_PHYSICALMEMORY) == 0)
+ {
+ DPRINT1("Invalid path: %lx %p %p\n", AllocationAttributes, FileObject, FileHandle);
+ }
+// ASSERT(AllocationAttributes & SEC_PHYSICALMEMORY);
+ Status = MmCreatePageFileSection(SectionObject,
+ DesiredAccess,
+ ObjectAttributes,
+ MaximumSize,
+ SectionPageProtection,
+ AllocationAttributes);
+ }
+ return Status;
+}
/* EOF */