/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
-#ifdef NEWCC
+#include "../cache/newcc.h"
#include "../cache/section/newmm.h"
-#endif
#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 SECTION_INHERIT InheritDisposition,
IN ULONG AllocationType,
IN ULONG Protect);
-
+
//
// PeFmtCreateSection depends on the following:
//
{
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_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 */
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)
+ 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)
{
NTSTATUS nStatus;
ULONG cbFileHeaderOffsetSize = 0;
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;
PMM_SECTION_SEGMENT pssSegments;
LARGE_INTEGER lnOffset;
PVOID pBuffer;
- ULONG nPrevVirtualEndOfSegment = 0;
+ SIZE_T nPrevVirtualEndOfSegment = 0;
ULONG nFileSizeOfHeaders = 0;
ULONG i;
/* 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));
+ 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));
+ 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));
+ 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));
+ DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
if(FileHeaderSize < cbFileHeaderOffsetSize)
- pinhNtHeader = NULL;
+ 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);
+ /*
+ * 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);
}
/*
if(FileHeaderSize < cbFileHeaderOffsetSize ||
(UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
{
- ULONG cbNtHeaderSize;
- ULONG cbReadSize;
- PVOID pData;
+ ULONG cbNtHeaderSize;
+ ULONG cbReadSize;
+ PVOID pData;
l_ReadHeaderFromFile:
- cbNtHeaderSize = 0;
- lnOffset.QuadPart = pidhDosHeader->e_lfanew;
+ cbNtHeaderSize = 0;
+ lnOffset.QuadPart = pidhDosHeader->e_lfanew;
+
+ /* read the header from the file */
+ nStatus = ReadFileCb(File, &lnOffset, sizeof(IMAGE_NT_HEADERS64), &pData, &pBuffer, &cbReadSize);
- /* read the header from the file */
- nStatus = ReadFileCb(File, &lnOffset, sizeof(IMAGE_NT_HEADERS64), &pData, &pBuffer, &cbReadSize);
+ if(!NT_SUCCESS(nStatus))
+ {
+ NTSTATUS ReturnedStatus = nStatus;
- if(!NT_SUCCESS(nStatus))
- DIE(("ReadFile failed, status %08X\n", nStatus));
+ /* If it attempted to read past the end of the file, it means e_lfanew is invalid */
+ if (ReturnedStatus == STATUS_END_OF_FILE) nStatus = STATUS_ROS_EXEFMT_UNKNOWN_FORMAT;
- ASSERT(pData);
- ASSERT(pBuffer);
- ASSERT(cbReadSize > 0);
+ DIE(("ReadFile failed, status %08X\n", ReturnedStatus));
+ }
- nStatus = STATUS_INVALID_IMAGE_FORMAT;
+ ASSERT(pData);
+ ASSERT(pBuffer);
+ ASSERT(cbReadSize > 0);
- /* 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"));
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
- pinhNtHeader = pData;
+ /* 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"));
- /* 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;
- }
+ pinhNtHeader = pData;
- /* invalid NT header */
- nStatus = STATUS_INVALID_IMAGE_PROTECT;
+ /* 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;
+ }
- if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
- DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
+ /* invalid NT header */
+ nStatus = STATUS_INVALID_IMAGE_PROTECT;
- nStatus = STATUS_INVALID_IMAGE_FORMAT;
+ if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
+ DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
- if(!Intsafe_AddULong32(&cbNtHeaderSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
- DIE(("The full NT header is too large\n"));
+ nStatus = STATUS_INVALID_IMAGE_FORMAT;
- /* the buffer doesn't contain the whole NT header */
- if(cbReadSize < cbNtHeaderSize)
- DIE(("The file doesn't contain the full NT header\n"));
+ 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
{
- ULONG cbOptHeaderOffsetSize = 0;
+ ULONG cbOptHeaderOffsetSize = 0;
- nStatus = STATUS_INVALID_IMAGE_FORMAT;
+ 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));
+ /* 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, 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));
+ 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;
+ /* the buffer doesn't contain the whole NT header: read it from the file */
+ if(cbOptHeaderOffsetSize > FileHeaderSize)
+ goto l_ReadHeaderFromFile;
}
/* read information from the NT header */
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));
+ DIE(("The optional header doesn't contain the Magic field, SizeOfOptionalHeader is %X\n", cbOptHeaderSize));
/* ASSUME: RtlZeroMemory(ImageSectionObject, sizeof(*ImageSectionObject)); */
switch(piohOptHeader->Magic)
{
- case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
- case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
- break;
+ case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+ break;
- default:
- DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
+ default:
+ DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
}
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));
+ /* 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;
+ nSectionAlignment = PAGE_SIZE;
+ nFileAlignment = PAGE_SIZE;
}
ASSERT(IsPowerOf2(nSectionAlignment));
switch(piohOptHeader->Magic)
{
- /* PE32 */
- case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
- {
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, ImageBase))
- ImageSectionObject->ImageBase = piohOptHeader->ImageBase;
+ /* PE32 */
+ case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+ {
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, ImageBase))
+ ImageBase = piohOptHeader->ImageBase;
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfImage))
- ImageSectionObject->ImageSize = piohOptHeader->SizeOfImage;
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfImage))
+ ImageSectionObject->ImageInformation.ImageFileSize = piohOptHeader->SizeOfImage;
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackReserve))
- ImageSectionObject->StackReserve = piohOptHeader->SizeOfStackReserve;
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackReserve))
+ ImageSectionObject->ImageInformation.MaximumStackSize = piohOptHeader->SizeOfStackReserve;
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackCommit))
- ImageSectionObject->StackCommit = piohOptHeader->SizeOfStackCommit;
+ if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackCommit))
+ ImageSectionObject->ImageInformation.CommittedStackSize = piohOptHeader->SizeOfStackCommit;
- break;
- }
+ 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;
+ }
+ }
- /* PE32+ */
- case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
- {
- const IMAGE_OPTIONAL_HEADER64 * pioh64OptHeader;
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
+ {
+ ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
+ piohOptHeader->AddressOfEntryPoint);
+ }
- pioh64OptHeader = (const IMAGE_OPTIONAL_HEADER64 *)piohOptHeader;
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfCode))
+ ImageSectionObject->ImageInformation.ImageContainsCode = piohOptHeader->SizeOfCode != 0;
+ else
+ ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
- if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, ImageBase))
- {
- if(pioh64OptHeader->ImageBase > MAXULONG_PTR)
- DIE(("ImageBase exceeds the address space\n"));
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
+ {
+ if (piohOptHeader->AddressOfEntryPoint == 0)
+ {
+ ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
+ }
+ }
- ImageSectionObject->ImageBase = (ULONG_PTR)pioh64OptHeader->ImageBase;
- }
+ if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, LoaderFlags))
+ ImageSectionObject->ImageInformation.LoaderFlags = piohOptHeader->LoaderFlags;
- if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfImage))
- {
- if(pioh64OptHeader->SizeOfImage > MAXULONG_PTR)
- DIE(("SizeOfImage exceeds the address space\n"));
+ 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;
+ }
- ImageSectionObject->ImageSize = pioh64OptHeader->SizeOfImage;
- }
+ break;
+ }
+#ifdef _WIN64
+ /* PE64 */
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+ {
+ const IMAGE_OPTIONAL_HEADER64 * pioh64OptHeader;
- if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackReserve))
- {
- if(pioh64OptHeader->SizeOfStackReserve > MAXULONG_PTR)
- DIE(("SizeOfStackReserve exceeds the address space\n"));
+ pioh64OptHeader = (const IMAGE_OPTIONAL_HEADER64 *)piohOptHeader;
- ImageSectionObject->StackReserve = pioh64OptHeader->SizeOfStackReserve;
- }
+ 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, SizeOfStackCommit))
- {
- if(pioh64OptHeader->SizeOfStackCommit > MAXULONG_PTR)
- DIE(("SizeOfStackCommit 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->StackCommit = pioh64OptHeader->SizeOfStackCommit;
- }
+ ImageSectionObject->ImageInformation.ImageFileSize = pioh64OptHeader->SizeOfImage;
+ }
- break;
- }
- }
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackReserve))
+ {
+ if(pioh64OptHeader->SizeOfStackReserve > MAXULONG_PTR)
+ DIE(("SizeOfStackReserve exceeds the address space\n"));
- /* [1], section 3.4.2 */
- if((ULONG_PTR)ImageSectionObject->ImageBase % 0x10000)
- DIE(("ImageBase is not aligned on a 64KB boundary"));
+ ImageSectionObject->ImageInformation.MaximumStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackReserve;
+ }
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Subsystem))
- {
- ImageSectionObject->Subsystem = piohOptHeader->Subsystem;
-
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
- RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MajorSubsystemVersion))
- {
- ImageSectionObject->MinorSubsystemVersion = piohOptHeader->MinorSubsystemVersion;
- ImageSectionObject->MajorSubsystemVersion = piohOptHeader->MajorSubsystemVersion;
- }
- }
+ if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackCommit))
+ {
+ if(pioh64OptHeader->SizeOfStackCommit > MAXULONG_PTR)
+ DIE(("SizeOfStackCommit exceeds the address space\n"));
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
- {
- ImageSectionObject->EntryPoint = piohOptHeader->ImageBase +
- piohOptHeader->AddressOfEntryPoint;
+ 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;
+
+ 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
}
- if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfCode))
- ImageSectionObject->Executable = piohOptHeader->SizeOfCode != 0;
- else
- ImageSectionObject->Executable = TRUE;
+ /* [1], section 3.4.2 */
+ if((ULONG_PTR)ImageBase % 0x10000)
+ DIE(("ImageBase is not aligned on a 64KB boundary"));
- ImageSectionObject->ImageCharacteristics = pinhNtHeader->FileHeader.Characteristics;
- ImageSectionObject->Machine = pinhNtHeader->FileHeader.Machine;
+ 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));
+ 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
/* file offset for the section headers */
if(!Intsafe_AddULong32(&cbSectionHeadersOffset, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
- DIE(("Offset overflow\n"));
+ DIE(("Offset overflow\n"));
if(!Intsafe_AddULong32(&cbSectionHeadersOffset, cbSectionHeadersOffset, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
- DIE(("Offset overflow\n"));
+ 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"));
+ 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(!IsAligned(piohOptHeader->SizeOfHeaders, nFileAlignment))
+// DIE(("SizeOfHeaders is not aligned\n"));
- if(cbSectionHeadersSize > piohOptHeader->SizeOfHeaders)
- DIE(("The section headers overflow SizeOfHeaders\n"));
+ if(cbSectionHeadersSize > piohOptHeader->SizeOfHeaders)
+ DIE(("The section headers overflow SizeOfHeaders\n"));
- cbHeadersSize = piohOptHeader->SizeOfHeaders;
+ cbHeadersSize = piohOptHeader->SizeOfHeaders;
}
else if(!AlignUp(&cbHeadersSize, cbSectionHeadersOffsetSize, nFileAlignment))
- DIE(("Overflow aligning the size of headers\n"));
+ DIE(("Overflow aligning the size of headers\n"));
if(pBuffer)
{
- ExFreePool(pBuffer);
- pBuffer = NULL;
+ 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;
+ 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);
+ /*
+ * 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);
}
/*
if(FileHeaderSize < cbSectionHeadersOffsetSize ||
(UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
{
- PVOID pData;
- ULONG cbReadSize;
+ PVOID pData;
+ ULONG cbReadSize;
- lnOffset.QuadPart = cbSectionHeadersOffset;
+ lnOffset.QuadPart = cbSectionHeadersOffset;
- /* read the header from the file */
- nStatus = ReadFileCb(File, &lnOffset, cbSectionHeadersSize, &pData, &pBuffer, &cbReadSize);
+ /* 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));
+ if(!NT_SUCCESS(nStatus))
+ DIE(("ReadFile failed with status %08X\n", nStatus));
- ASSERT(pData);
- ASSERT(pBuffer);
- ASSERT(cbReadSize > 0);
+ ASSERT(pData);
+ ASSERT(pBuffer);
+ ASSERT(cbReadSize > 0);
- nStatus = STATUS_INVALID_IMAGE_FORMAT;
+ 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"));
+ /* 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;
+ 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;
- }
+ /* 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 */
ImageSectionObject->Segments = AllocateSegmentsCb(ImageSectionObject->NrSegments);
if(ImageSectionObject->Segments == NULL)
- DIE(("AllocateSegments failed\n"));
+ DIE(("AllocateSegments failed\n"));
/* initialize the headers segment */
- pssSegments = ImageSectionObject->Segments;
+ pssSegments = ImageSectionObject->Segments;
// ASSERT(IsAligned(cbHeadersSize, nFileAlignment));
if(!AlignUp(&nFileSizeOfHeaders, cbHeadersSize, nFileAlignment))
- DIE(("Cannot align the size of the section headers\n"));
+ DIE(("Cannot align the size of the section headers\n"));
- if(!AlignUp(&nPrevVirtualEndOfSegment, cbHeadersSize, nSectionAlignment))
- DIE(("Cannot align the size of the section headers\n"));
+ nPrevVirtualEndOfSegment = ALIGN_UP_BY(cbHeadersSize, nSectionAlignment);
+ if (nPrevVirtualEndOfSegment < cbHeadersSize)
+ DIE(("Cannot align the size of the section headers\n"));
- pssSegments[0].FileOffset = 0;
+ pssSegments[0].Image.FileOffset = 0;
pssSegments[0].Protection = PAGE_READONLY;
- pssSegments[0].Length = nPrevVirtualEndOfSegment;
- pssSegments[0].RawLength = nFileSizeOfHeaders;
- pssSegments[0].VirtualAddress = 0;
- pssSegments[0].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA;
+ pssSegments[0].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 */
/* convert the executable sections into segments. See also [1], section 4 */
for(i = 0; i < ImageSectionObject->NrSegments - 1; ++ i)
{
- ULONG nCharacteristics;
+ ULONG nCharacteristics;
- /* validate the alignment */
- if(!IsAligned(pishSectionHeaders[i].VirtualAddress, nSectionAlignment))
- DIE(("VirtualAddress[%u] is not aligned\n", i));
+ /* 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));
+ /* 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 */
+ /* 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));
+ /* Yes, this should be a multiple of FileAlignment, but there's
+ * stuff out there that isn't. We can cope with that
+ */
+ if(!IsAligned(pishSectionHeaders[i].SizeOfRawData, nFileAlignment))
+ DIE(("SizeOfRawData[%u] is not aligned\n", i));
#endif
-// if(!IsAligned(pishSectionHeaders[i].PointerToRawData, nFileAlignment))
-// DIE(("PointerToRawData[%u] is not aligned\n", i));
+// if(!IsAligned(pishSectionHeaders[i].PointerToRawData, nFileAlignment))
+// DIE(("PointerToRawData[%u] is not aligned\n", i));
- /* conversion */
- pssSegments[i].FileOffset = pishSectionHeaders[i].PointerToRawData;
- pssSegments[i].RawLength = pishSectionHeaders[i].SizeOfRawData;
- }
- else
- {
- ASSERT(pssSegments[i].FileOffset == 0);
- ASSERT(pssSegments[i].RawLength == 0);
- }
+ /* 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);
+ }
- ASSERT(Intsafe_CanAddLong64(pssSegments[i].FileOffset, pssSegments[i].RawLength));
+ ASSERT(Intsafe_CanAddLong64(pssSegments[i].Image.FileOffset, pssSegments[i].RawLength.QuadPart));
- nCharacteristics = pishSectionHeaders[i].Characteristics;
+ 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;
+ /* 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_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;
- }
+ 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);
+ /* see table above */
+ pssSegments[i].Protection = SectionCharacteristicsToProtect[nCharacteristics >> 28];
+ pssSegments[i].WriteCopy = !(nCharacteristics & IMAGE_SCN_MEM_SHARED);
- if(pishSectionHeaders[i].Misc.VirtualSize == 0 || pishSectionHeaders[i].Misc.VirtualSize < pishSectionHeaders[i].SizeOfRawData)
- pssSegments[i].Length = pishSectionHeaders[i].SizeOfRawData;
- else
- pssSegments[i].Length = pishSectionHeaders[i].Misc.VirtualSize;
+ 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;
- if(!AlignUp(&pssSegments[i].Length, pssSegments[i].Length, nSectionAlignment))
- DIE(("Cannot align the virtual size of section %u\n", i));
+ 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));
- ASSERT(IsAligned(pssSegments[i].Length, nSectionAlignment));
+ if(pssSegments[i].Length.QuadPart == 0)
+ DIE(("Virtual size of section %u is null\n", i));
- if(pssSegments[i].Length == 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;
- pssSegments[i].VirtualAddress = pishSectionHeaders[i].VirtualAddress;
- pssSegments[i].Characteristics = pishSectionHeaders[i].Characteristics;
-
- /* ensure the memory image is no larger than 4GB */
- if(!Intsafe_AddULong32(&nPrevVirtualEndOfSegment, pssSegments[i].VirtualAddress, pssSegments[i].Length))
- DIE(("The image is larger than 4GB\n"));
+ /* 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"));
}
- /* spare our caller some work in validating the segments */
- *Flags = EXEFMT_LOAD_ASSUME_SEGMENTS_SORTED | EXEFMT_LOAD_ASSUME_SEGMENTS_NO_OVERLAP;
-
if(nSectionAlignment >= PAGE_SIZE)
- *Flags |= EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED;
+ *Flags |= EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED;
/* Success */
- nStatus = STATUS_ROS_EXEFMT_LOADED_FORMAT | EXEFMT_LOADED_PE32;
+ nStatus = STATUS_SUCCESS;// STATUS_ROS_EXEFMT_LOADED_FORMAT | EXEFMT_LOADED_PE32;
l_Return:
if(pBuffer)
- ExFreePool(pBuffer);
+ ExFreePool(pBuffer);
return nStatus;
}
-/* Note: Mmsp prefix denotes "Memory Manager Section Private". */
-
-/*
- * 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? */
-
- Timeout.QuadPart = -100000000LL; // 10 sec
-#else
-
- Timeout.QuadPart = -100000000; // 10 sec
-#endif
-
- return KeWaitForSingleObject(&PageOp->CompletionEvent, 0, KernelMode, FALSE, &Timeout);
-}
-
-
-/*
- * 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);
-}
-
-
/*
* FUNCTION: Waits in kernel mode indefinitely for a file object lock.
* ARGUMENTS: PFILE_OBJECT to wait for.
//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;
- PBCB Bcb;
+#ifndef NEWCC
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+#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;
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
IsDirectMapped = TRUE;
#ifndef NEWCC
- Status = CcRosUnmapCacheSegment(Bcb, FileOffset, Dirty);
+ Status = CcRosUnmapVacb(SharedCacheMap, FileOffset.LowPart, Dirty);
#else
- Status = STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
#endif
if (!NT_SUCCESS(Status))
{
- DPRINT1("CcRosUnmapCacheSegment failed, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
+ DPRINT1("CcRosUnmapVacb failed, status = %x\n", Status);
+ 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);
}
ULONG SegOffset)
{
#ifndef NEWCC
- if (!(MemoryArea->Data.SectionData.Segment->Characteristics & IMAGE_SCN_MEM_SHARED))
+ 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);
- if (CacheSeg)
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+ PROS_VACB Vacb;
+ SharedCacheMap = MemoryArea->Data.SectionData.Section->FileObject->SectionObjectPointer->SharedCacheMap;
+ Vacb = CcRosLookupVacb(SharedCacheMap, (ULONG)(SegOffset + MemoryArea->Data.SectionData.Segment->Image.FileOffset));
+ if (Vacb)
{
- CcRosReleaseCacheSegment(Bcb, CacheSeg, CacheSeg->Valid, FALSE, TRUE);
+ CcRosReleaseVacb(SharedCacheMap, Vacb, Vacb->Valid, FALSE, TRUE);
return TRUE;
}
}
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);
}
NTSTATUS
NTAPI
MiReadPage(PMEMORY_AREA MemoryArea,
- ULONG SegOffset,
+ ULONG_PTR SegOffset,
PPFN_NUMBER Page)
/*
* FUNCTION: Read a page for a section backed memory area.
* Page - Variable that receives a page contains the read data.
*/
{
- ULONG BaseOffset;
- ULONG FileOffset;
+ ULONGLONG BaseOffset;
+ ULONGLONG FileOffset;
PVOID BaseAddress;
BOOLEAN UptoDate;
- PCACHE_SEGMENT CacheSeg;
+ PROS_VACB Vacb;
PFILE_OBJECT FileObject;
NTSTATUS Status;
- ULONG RawLength;
- PBCB Bcb;
+ ULONG_PTR RawLength;
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
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;
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+ 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);
+ ASSERT(SharedCacheMap);
- 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.
+ * then get the related VACB.
*/
- 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))
{
/*
- * Get the related cache segment; we use a lower level interface than
- * filesystems do because it is safe for us to use an offset with a
+ * Get the related VACB; we use a lower level interface than
+ * filesystems do because it is safe for us to use an offset with an
* alignment less than the file system block size.
*/
- Status = CcRosGetCacheSegment(Bcb,
- FileOffset,
- &BaseOffset,
- &BaseAddress,
- &UptoDate,
- &CacheSeg);
+ Status = CcRosGetVacb(SharedCacheMap,
+ (ULONG)FileOffset,
+ &BaseOffset,
+ &BaseAddress,
+ &UptoDate,
+ &Vacb);
if (!NT_SUCCESS(Status))
{
return(Status);
if (!UptoDate)
{
/*
- * If the cache segment isn't up to date then call the file
+ * If the VACB isn't up to date then call the file
* system to read in the data.
*/
- Status = ReadCacheSegment(CacheSeg);
+ Status = CcReadVirtualAddress(Vacb);
if (!NT_SUCCESS(Status))
{
- CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
+ CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
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.
+ * Retrieve the page from the view that we actually want.
*/
(*Page) = MmGetPhysicalAddress((char*)BaseAddress +
FileOffset - BaseOffset).LowPart >> PAGE_SHIFT;
- CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, TRUE);
+ CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, TRUE);
}
else
{
PEPROCESS Process;
KIRQL Irql;
PVOID PageAddr;
- ULONG CacheSegOffset;
+ ULONG_PTR VacbOffset;
/*
* Allocate a page, this is rather complicated by the possibility
{
return(Status);
}
- Status = CcRosGetCacheSegment(Bcb,
- FileOffset,
- &BaseOffset,
- &BaseAddress,
- &UptoDate,
- &CacheSeg);
+ Status = CcRosGetVacb(SharedCacheMap,
+ (ULONG)FileOffset,
+ &BaseOffset,
+ &BaseAddress,
+ &UptoDate,
+ &Vacb);
if (!NT_SUCCESS(Status))
{
return(Status);
if (!UptoDate)
{
/*
- * If the cache segment isn't up to date then call the file
+ * If the VACB isn't up to date then call the file
* system to read in the data.
*/
- Status = ReadCacheSegment(CacheSeg);
+ Status = CcReadVirtualAddress(Vacb);
if (!NT_SUCCESS(Status))
{
- CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
+ CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
return Status;
}
}
Process = PsGetCurrentProcess();
PageAddr = MiMapPageInHyperSpace(Process, *Page, &Irql);
- CacheSegOffset = BaseOffset + CacheSeg->Bcb->CacheSegmentSize - FileOffset;
+ VacbOffset = (ULONG_PTR)(BaseOffset + VACB_MAPPING_GRANULARITY - FileOffset);
Length = RawLength - SegOffset;
- if (Length <= CacheSegOffset && Length <= PAGE_SIZE)
+ if (Length <= VacbOffset && Length <= PAGE_SIZE)
{
memcpy(PageAddr, (char*)BaseAddress + FileOffset - BaseOffset, Length);
}
- else if (CacheSegOffset >= PAGE_SIZE)
+ else if (VacbOffset >= PAGE_SIZE)
{
memcpy(PageAddr, (char*)BaseAddress + FileOffset - BaseOffset, PAGE_SIZE);
}
else
{
- memcpy(PageAddr, (char*)BaseAddress + FileOffset - BaseOffset, CacheSegOffset);
+ memcpy(PageAddr, (char*)BaseAddress + FileOffset - BaseOffset, VacbOffset);
MiUnmapPageInHyperSpace(Process, PageAddr, Irql);
- CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
- Status = CcRosGetCacheSegment(Bcb,
- FileOffset + CacheSegOffset,
- &BaseOffset,
- &BaseAddress,
- &UptoDate,
- &CacheSeg);
+ CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
+ Status = CcRosGetVacb(SharedCacheMap,
+ (ULONG)(FileOffset + VacbOffset),
+ &BaseOffset,
+ &BaseAddress,
+ &UptoDate,
+ &Vacb);
if (!NT_SUCCESS(Status))
{
return(Status);
if (!UptoDate)
{
/*
- * If the cache segment isn't up to date then call the file
+ * If the VACB isn't up to date then call the file
* system to read in the data.
*/
- Status = ReadCacheSegment(CacheSeg);
+ Status = CcReadVirtualAddress(Vacb);
if (!NT_SUCCESS(Status))
{
- CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
+ CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
return Status;
}
}
PageAddr = MiMapPageInHyperSpace(Process, *Page, &Irql);
if (Length < PAGE_SIZE)
{
- memcpy((char*)PageAddr + CacheSegOffset, BaseAddress, Length - CacheSegOffset);
+ memcpy((char*)PageAddr + VacbOffset, BaseAddress, Length - VacbOffset);
}
else
{
- memcpy((char*)PageAddr + CacheSegOffset, BaseAddress, PAGE_SIZE - CacheSegOffset);
+ memcpy((char*)PageAddr + VacbOffset, BaseAddress, PAGE_SIZE - VacbOffset);
}
}
MiUnmapPageInHyperSpace(Process, PageAddr, Irql);
- CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
+ CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
}
return(STATUS_SUCCESS);
}
NTSTATUS
NTAPI
MiReadPage(PMEMORY_AREA MemoryArea,
- ULONG SegOffset,
+ ULONG_PTR SegOffset,
PPFN_NUMBER Page)
/*
* FUNCTION: Read a page for a section backed memory area.
* Page - Variable that receives a page contains the read data.
*/
{
- MM_REQUIRED_RESOURCES Resources = { };
-
+ 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->FileOffset;
+ Resources.FileOffset.QuadPart = SegOffset +
+ MemoryArea->Data.SectionData.Segment->Image.FileOffset;
Resources.Consumer = MC_USER;
Resources.Amount = PAGE_SIZE;
- DPRINT1("%S, offset %x, len %d, page %x\n", ((PFILE_OBJECT)Resources.Context)->FileName.Buffer, Resources.FileOffset.LowPart, Resources.Amount, Resources.Page[0]);
+ 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]);
- NTSTATUS Status = MiReadFilePage(NULL, NULL, &Resources);
+ Status = MiReadFilePage(MmGetKernelAddressSpace(), MemoryArea, &Resources);
*Page = Resources.Page[0];
return Status;
}
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
*/
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);
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);
- MI_SET_USAGE(MI_USAGE_SECTION);
- if (Process) MI_SET_PROCESS2(Process->ImageFileName);
- if (!Process) MI_SET_PROCESS2("Kernel Section");
- Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
- if (!NT_SUCCESS(Status))
- {
- 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);
{
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))
* 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);
(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);
/*
/*
* 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;
- PBCB Bcb = NULL;
+#ifndef NEWCC
+ PROS_SHARED_CACHE_MAP SharedCacheMap = 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;
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
/*
* If the file system is letting us go directly to the cache and the
* 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)
{
}
/*
- * Take an additional reference to the page or the cache segment.
+ * Take an additional reference to the page or the VACB.
*/
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);
}
#ifndef NEWCC
- Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
+ Status = CcRosUnmapVacb(SharedCacheMap, (ULONG)FileOffset, FALSE);
#else
- Status = STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
#endif
+#ifndef NEWCC
if (!NT_SUCCESS(Status))
{
- DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
+ DPRINT1("CcRosUnmapVacb failed, status = %x\n", Status);
+ KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)SharedCacheMap, (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;
- PBCB Bcb = NULL;
+ PROS_SHARED_CACHE_MAP SharedCacheMap = NULL;
BOOLEAN DirectMapped;
BOOLEAN IsImageSection;
PEPROCESS Process = MmGetAddressSpaceOwner(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;
/*
* 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;
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
/*
* 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 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);
+ //SOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset;
#ifndef NEWCC
- CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
+ CcRosMarkDirtyVacb(SharedCacheMap, Offset.LowPart);
#endif
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ 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) &&
(NewProtect == PAGE_READWRITE || NewProtect == PAGE_EXECUTE_READWRITE))
{
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;
}
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);
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;
-
- /*
- * 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;
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);
{
PMEMORY_AREA MArea;
NTSTATUS Status;
- PHYSICAL_ADDRESS BoundaryAddressMultiple;
-
- BoundaryAddressMultiple.QuadPart = 0;
+ 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
+ Granularity = PAGE_SIZE;
+#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__);
+ }
+#endif
Status = MmCreateMemoryArea(AddressSpace,
MEMORY_AREA_SECTION_VIEW,
BaseAddress,
&MArea,
FALSE,
AllocationType,
- BoundaryAddressMultiple);
+ Granularity);
if (!NT_SUCCESS(Status))
{
- DPRINT1("Mapping between 0x%.8X and 0x%.8X failed (%X).\n",
+ DPRINT1("Mapping between 0x%p and 0x%p failed (%X).\n",
(*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status);
return(Status);
}
MArea->Data.SectionData.Segment = Segment;
MArea->Data.SectionData.Section = Section;
- MArea->Data.SectionData.ViewOffset = ViewOffset;
+ MArea->Data.SectionData.ViewOffset.QuadPart = ViewOffset;
MmInitializeRegion(&MArea->Data.SectionData.RegionListHead,
ViewSize, 0, Protect);
}
-
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;
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+ 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.
if (Page == PFN_FROM_SSE(Entry) && Dirty)
{
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
#ifndef NEWCC
- CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset);
+ CcRosMarkDirtyVacb(SharedCacheMap, (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);
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);
}
-
+
/**********************************************************************
* NAME EXPORTED
* MmMapViewOfSection
PMMSUPPORT AddressSpace;
ULONG ViewOffset;
NTSTATUS Status = STATUS_SUCCESS;
+ BOOLEAN NotAtBase = FALSE;
- if ((ULONG_PTR)SectionObject & 1)
+ if (MiIsRosSectionObject(SectionObject) == FALSE)
{
- return MmMapViewOfArm3Section((PVOID)((ULONG_PTR)SectionObject & ~1),
+ DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
+ return MmMapViewOfArm3Section(SectionObject,
Process,
BaseAddress,
ZeroBits,
AllocationType,
Protect);
}
-
+
ASSERT(Process);
if (!Protect || Protect & ~PAGE_FLAGS_VALID_FOR_SECTION)
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)
{
- PBCB Bcb = SectionObjectPointer->SharedCacheMap;
- if (NewFileSize->QuadPart <= Bcb->FileSize.QuadPart)
+ PROS_SHARED_CACHE_MAP SharedCacheMap = SectionObjectPointer->SharedCacheMap;
+ if (NewFileSize->QuadPart <= SharedCacheMap->FileSize.QuadPart)
{
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");
}
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);
+ CcRosRemoveIfClosed(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;
}
PMMSUPPORT AddressSpace;
NTSTATUS Status;
PAGED_CODE();
-
- if ((ULONG_PTR)SectionObject & 1)
+
+ if (MiIsRosSectionObject(SectionObject) == FALSE)
{
- extern PVOID MmSession;
- return MiMapViewInSystemSpace((PVOID)((ULONG_PTR)SectionObject & ~1),
+ return MiMapViewInSystemSpace(SectionObject,
&MmSession,
MappedBase,
ViewSize);
return Status;
}
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-MmUnmapViewInSystemSpace (IN PVOID MappedBase)
+NTSTATUS
+NTAPI
+MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
{
PMMSUPPORT AddressSpace;
NTSTATUS Status;
AddressSpace = MmGetKernelAddressSpace();
+ MmLockAddressSpace(AddressSpace);
+
Status = MmUnmapViewOfSegment(AddressSpace, MappedBase);
+ MmUnlockAddressSpace(AddressSpace);
+
return Status;
}
-
/**********************************************************************
* NAME EXPORTED
* MmCreateSection@
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 if an ARM3 section is being created instead */
- if (AllocationAttributes & 1)
+ if (!(AllocationAttributes & (SEC_IMAGE | SEC_PHYSICALMEMORY)))
{
- DPRINT1("arm 3 path\n");
- return MmCreateArm3Section(Section,
- DesiredAccess,
- ObjectAttributes,
- MaximumSize,
- SectionPageProtection,
- AllocationAttributes &~ 1,
- FileHandle,
- File);
+ if (!(FileObject) && !(FileHandle))
+ {
+ return MmCreateArm3Section(Section,
+ DesiredAccess,
+ ObjectAttributes,
+ MaximumSize,
+ SectionPageProtection,
+ AllocationAttributes &~ 1,
+ FileHandle,
+ FileObject);
+ }
}
- /*
- * 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));
-}
+ /* 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 */