ReactOS 0.4.15-dev-6054-gbddd8b0
section.c File Reference
#include <ntoskrnl.h>
#include <cache/newcc.h>
#include <cache/section/newmm.h>
#include <debug.h>
#include <reactos/exeformat.h>
#include "ARM3/miarm.h"
Include dependency graph for section.c:

Go to the source code of this file.

Classes

struct  MM_SECTION_PAGEOUT_CONTEXT
 

Macros

#define NDEBUG
 
#define MmSetPageEntrySectionSegment(S, O, E)
 
#define DIE(ARGS_)   { DPRINT ARGS_; goto l_Return; }
 

Functions

VOID NTAPI _MmLockSectionSegment (PMM_SECTION_SEGMENT Segment, const char *file, int line)
 
VOID NTAPI _MmUnlockSectionSegment (PMM_SECTION_SEGMENT Segment, const char *file, int line)
 
static PMM_SECTION_SEGMENT MiGrabDataSection (PSECTION_OBJECT_POINTERS SectionObjectPointer)
 
PMM_IMAGE_SECTION_OBJECT ImageSectionObjectFromSegment (PMM_SECTION_SEGMENT Segment)
 
NTSTATUS MiMapViewInSystemSpace (IN PVOID Section, IN PVOID Session, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize, IN PLARGE_INTEGER SectionOffset)
 
NTSTATUS NTAPI MmCreateArm3Section (OUT PVOID *SectionObject, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER InputMaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
 
NTSTATUS NTAPI MmMapViewOfArm3Section (IN PVOID SectionObject, IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
 
 C_ASSERT (EXEFMT_LOAD_HEADER_SIZE >=sizeof(IMAGE_DOS_HEADER))
 
 C_ASSERT (sizeof(IMAGE_NT_HEADERS32)<=sizeof(IMAGE_NT_HEADERS64))
 
 C_ASSERT (TYPE_ALIGNMENT(IMAGE_NT_HEADERS32)==TYPE_ALIGNMENT(IMAGE_NT_HEADERS64))
 
 C_ASSERT (RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader)==RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS64, FileHeader))
 
 C_ASSERT (FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)==FIELD_OFFSET(IMAGE_NT_HEADERS64, OptionalHeader))
 
 C_ASSERT (PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, Magic))
 
 C_ASSERT (PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, SectionAlignment))
 
 C_ASSERT (PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, FileAlignment))
 
 C_ASSERT (PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, Subsystem))
 
 C_ASSERT (PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, MinorSubsystemVersion))
 
 C_ASSERT (PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, MajorSubsystemVersion))
 
 C_ASSERT (PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, AddressOfEntryPoint))
 
 C_ASSERT (PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, SizeOfCode))
 
 C_ASSERT (PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, SizeOfHeaders))
 
NTSTATUS NTAPI MiWritePage (PMM_SECTION_SEGMENT Segment, LONGLONG SegOffset, PFN_NUMBER Page)
 
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)
 
NTSTATUS MmspWaitForFileLock (PFILE_OBJECT File)
 
VOID NTAPI MmpFreePageFileSegment (PMM_SECTION_SEGMENT Segment)
 
static VOID NTAPI FreeSegmentPage (PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
 
 _When_ (OldIrql==MM_NOIRQL, _IRQL_requires_max_(DISPATCH_LEVEL))
 
VOID NTAPI MmSharePageEntrySectionSegment (PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
 
BOOLEAN NTAPI MmUnsharePageEntrySectionSegment (PMEMORY_AREA MemoryArea, PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, BOOLEAN Dirty, BOOLEAN PageOut, ULONG_PTR *InEntry)
 
static NTSTATUS MiCopyFromUserPage (PFN_NUMBER DestPage, const VOID *SrcAddress)
 
static NTSTATUS NTAPI MmMakeSegmentResident (_In_ PMM_SECTION_SEGMENT Segment, _In_ LONGLONG Offset, _In_ ULONG Length, _In_opt_ PLARGE_INTEGER ValidDataLength, _In_ BOOLEAN SetDirty)
 
static VOID MmAlterViewAttributes (PMMSUPPORT AddressSpace, PVOID BaseAddress, SIZE_T RegionSize, ULONG OldType, ULONG OldProtect, ULONG NewType, ULONG NewProtect)
 
NTSTATUS NTAPI MmNotPresentFaultSectionView (PMMSUPPORT AddressSpace, MEMORY_AREA *MemoryArea, PVOID Address, BOOLEAN Locked)
 
NTSTATUS NTAPI MmAccessFaultSectionView (PMMSUPPORT AddressSpace, MEMORY_AREA *MemoryArea, PVOID Address, BOOLEAN Locked)
 
NTSTATUS NTAPI MmProtectSectionView (PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PVOID BaseAddress, SIZE_T Length, ULONG Protect, PULONG OldProtect)
 
NTSTATUS NTAPI MmQuerySectionView (PMEMORY_AREA MemoryArea, PVOID Address, PMEMORY_BASIC_INFORMATION Info, PSIZE_T ResultLength)
 
VOID NTAPI MmpDeleteSection (PVOID ObjectBody)
 
VOID NTAPI MmpCloseSection (IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG ProcessHandleCount, IN ULONG SystemHandleCount)
 
NTSTATUS NTAPI MmCreatePhysicalMemorySection (VOID)
 
NTSTATUS NTAPI MmInitSectionImplementation (VOID)
 
static NTSTATUS NTAPI MmCreateDataFileSection (PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject, BOOLEAN GotFileHandle)
 
NTSTATUS NTAPI ElfFmtCreateSection (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)
 
static PMM_SECTION_SEGMENT NTAPI ExeFmtpAllocateSegments (IN ULONG NrSegments)
 
static NTSTATUS NTAPI ExeFmtpReadFile (IN PVOID File, IN PLARGE_INTEGER Offset, IN ULONG Length, OUT PVOID *Data, OUT PVOID *AllocBase, OUT PULONG ReadSize)
 
static VOID NTAPI MmspAssertSegmentsSorted (IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
 
static VOID NTAPI MmspAssertSegmentsNoOverlap (IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
 
static VOID NTAPI MmspAssertSegmentsPageAligned (IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
 
static int __cdecl MmspCompareSegments (const void *x, const void *y)
 
static VOID NTAPI MmspSortSegments (IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
 
static BOOLEAN NTAPI MmspCheckSegmentBounds (IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
 
static BOOLEAN NTAPI MmspPageAlignSegments (IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
 
NTSTATUS ExeFmtpCreateImageSection (PFILE_OBJECT FileObject, PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
 
NTSTATUS MmCreateImageSection (PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
 
static NTSTATUS MmMapViewOfSegment (PMMSUPPORT AddressSpace, BOOLEAN AsImage, PMM_SECTION_SEGMENT Segment, PVOID *BaseAddress, SIZE_T ViewSize, ULONG Protect, LONGLONG ViewOffset, ULONG AllocationType)
 
static VOID MmFreeSectionPage (PVOID Context, MEMORY_AREA *MemoryArea, PVOID Address, PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
 
static NTSTATUS MmUnmapViewOfSegment (PMMSUPPORT AddressSpace, PVOID BaseAddress)
 
NTSTATUS NTAPI MiRosUnmapViewOfSection (IN PEPROCESS Process, IN PVOID BaseAddress, IN BOOLEAN SkipDebuggerNotify)
 
NTSTATUS NTAPI NtQuerySection (_In_ HANDLE SectionHandle, _In_ SECTION_INFORMATION_CLASS SectionInformationClass, _Out_ PVOID SectionInformation, _In_ SIZE_T SectionInformationLength, _Out_opt_ PSIZE_T ResultLength)
 
NTSTATUS NTAPI MmMapViewOfSection (IN PVOID SectionObject, IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
 
BOOLEAN NTAPI MmCanFileBeTruncated (_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
 
static BOOLEAN MiPurgeImageSegment (PMM_SECTION_SEGMENT Segment)
 
BOOLEAN NTAPI MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
 
NTSTATUS NTAPI MmMapViewInSystemSpace (IN PVOID SectionObject, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
 
NTSTATUS NTAPI MmMapViewInSystemSpaceEx (_In_ PVOID SectionObject, _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, _Inout_ PSIZE_T ViewSize, _Inout_ PLARGE_INTEGER SectionOffset, _In_ ULONG_PTR Flags)
 
NTSTATUS NTAPI MiRosUnmapViewInSystemSpace (IN PVOID MappedBase)
 
NTSTATUS NTAPI MmCreateSection (OUT PVOID *Section, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
 
BOOLEAN NTAPI MmArePagesResident (_In_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG Length)
 
BOOLEAN NTAPI MmPurgeSegment (_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length)
 
NTSTATUS NTAPI MmMakeDataSectionResident (_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length, _In_ PLARGE_INTEGER ValidDataLength)
 
NTSTATUS NTAPI MmFlushSegment (_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length, _Out_opt_ PIO_STATUS_BLOCK Iosb)
 
 _Requires_exclusive_lock_held_ (Segment->Lock) BOOLEAN NTAPI MmCheckDirtySegment(PMM_SECTION_SEGMENT Segment
 
 ASSERT (Segment->Locked)
 
 ASSERT ((Offset->QuadPart % PAGE_SIZE)==0)
 
 DPRINT ("Checking segment for file %wZ at offset 0x%I64X.\n", &Segment->FileObject->FileName, Offset->QuadPart)
 
 if (Entry==0)
 
 if (!IS_DIRTY_SSE(Entry) &&(SHARE_COUNT_FROM_SSE(Entry)==0) &&PageOut)
 
NTSTATUS NTAPI MmMakePagesDirty (_In_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG Length)
 
NTSTATUS NTAPI MmExtendSection (_In_ PVOID _Section, _Inout_ PLARGE_INTEGER NewSize)
 

Variables

MMSESSION MmSession
 
static LARGE_INTEGER TinyTime = {{-1L, -1L}}
 
KEVENT MmWaitPageEvent
 
POBJECT_TYPE MmSectionObjectType = NULL
 
ULONG_PTR MmSubsectionBase
 
static ULONG SectionCharacteristicsToProtect [16]
 
ACCESS_MASK MmMakeFileAccess [8]
 
static GENERIC_MAPPING MmpSectionMapping
 
static PEXEFMT_LOADER ExeFmtpLoaders []
 
PLARGE_INTEGER Offset
 
PLARGE_INTEGER BOOLEAN ForceDirty
 
PLARGE_INTEGER BOOLEAN BOOLEAN PageOut
 
NTSTATUS Status
 
PFN_NUMBER Page
 
 Entry = MmGetPageEntrySectionSegment(Segment, Offset)
 
return FALSE
 

Macro Definition Documentation

◆ DIE

#define DIE (   ARGS_)    { DPRINT ARGS_; goto l_Return; }

◆ MmSetPageEntrySectionSegment

#define MmSetPageEntrySectionSegment (   S,
  O,
  E 
)
Value:
do { \
DPRINT("SetPageEntrySectionSegment(old,%p,%x,%x)\n",(S),(O)->LowPart,E); \
_MmSetPageEntrySectionSegment((S),(O),(E),__FILE__,__LINE__); \
} while (0)
static const WCHAR E[]
Definition: oid.c:1253
static const WCHAR O[]
Definition: oid.c:1251
Definition: movable.cpp:9

Definition at line 57 of file section.c.

◆ NDEBUG

#define NDEBUG

Definition at line 50 of file section.c.

Function Documentation

◆ _MmLockSectionSegment()

VOID NTAPI _MmLockSectionSegment ( PMM_SECTION_SEGMENT  Segment,
const char file,
int  line 
)

Definition at line 71 of file section.c.

72{
73 //DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line);
75 Segment->Locked = TRUE;
76}
#define TRUE
Definition: types.h:120
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
_Inout_ PVOID Segment
Definition: exfuncs.h:1101

◆ _MmUnlockSectionSegment()

VOID NTAPI _MmUnlockSectionSegment ( PMM_SECTION_SEGMENT  Segment,
const char file,
int  line 
)

Definition at line 80 of file section.c.

81{
82 ASSERT(Segment->Locked);
83 Segment->Locked = FALSE;
85 //DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line);
86}
#define FALSE
Definition: types.h:117
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define ASSERT(a)
Definition: mode.c:44

◆ _Requires_exclusive_lock_held_()

_Requires_exclusive_lock_held_ ( Segment->  Lock)

◆ _When_()

Definition at line 989 of file section.c.

999{
1000 /* Lock the PFN lock because we mess around with SectionObjectPointers */
1001 if (OldIrql == MM_NOIRQL)
1002 {
1003 OldIrql = MiAcquirePfnLock();
1004 }
1005
1006 if (InterlockedDecrement64(Segment->ReferenceCount) > 0)
1007 {
1008 /* Nothing to do yet */
1009 MiReleasePfnLock(OldIrql);
1010 return;
1011 }
1012
1013 *Segment->Flags |= MM_SEGMENT_INDELETE;
1014
1015 /* Flush the segment */
1016 if (*Segment->Flags & MM_DATAFILE_SEGMENT)
1017 {
1018 MiReleasePfnLock(OldIrql);
1019 /* Free the page table. This will flush any remaining dirty data */
1021
1022 OldIrql = MiAcquirePfnLock();
1023 /* Delete the pointer on the file */
1024 ASSERT(Segment->FileObject->SectionObjectPointer->DataSectionObject == Segment);
1025 Segment->FileObject->SectionObjectPointer->DataSectionObject = NULL;
1026 MiReleasePfnLock(OldIrql);
1027 ObDereferenceObject(Segment->FileObject);
1028
1030 }
1031 else
1032 {
1033 /* Most grotesque thing ever */
1034 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = CONTAINING_RECORD(Segment->ReferenceCount, MM_IMAGE_SECTION_OBJECT, RefCount);
1035 PMM_SECTION_SEGMENT SectionSegments;
1036 ULONG NrSegments;
1037 ULONG i;
1038
1039 /* Delete the pointer on the file */
1040 ASSERT(ImageSectionObject->FileObject->SectionObjectPointer->ImageSectionObject == ImageSectionObject);
1041 ImageSectionObject->FileObject->SectionObjectPointer->ImageSectionObject = NULL;
1042 MiReleasePfnLock(OldIrql);
1043
1044 ObDereferenceObject(ImageSectionObject->FileObject);
1045
1046 NrSegments = ImageSectionObject->NrSegments;
1047 SectionSegments = ImageSectionObject->Segments;
1048 for (i = 0; i < NrSegments; i++)
1049 {
1050 if (SectionSegments[i].Image.Characteristics & IMAGE_SCN_MEM_SHARED)
1051 {
1052 MmpFreePageFileSegment(&SectionSegments[i]);
1053 }
1054
1055 MmFreePageTablesSectionSegment(&SectionSegments[i], NULL);
1056 }
1057
1059 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
1060 }
1061}
#define NULL
Definition: types.h:112
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define InterlockedDecrement64
Definition: interlocked.h:144
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
VOID NTAPI MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage)
Definition: sptab.c:307
#define IMAGE_SCN_MEM_SHARED
Definition: ntimage.h:238
#define MM_NOIRQL
Definition: mm.h:70
#define MM_SEGMENT_INDELETE
Definition: mm.h:239
#define MM_DATAFILE_SEGMENT
Definition: mm.h:238
static VOID NTAPI FreeSegmentPage(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
Definition: section.c:961
VOID NTAPI MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:918
PMM_SECTION_SEGMENT Segments
Definition: mm.h:234
PFILE_OBJECT FileObject
Definition: mm.h:226
#define TAG_MM_SECTION_SEGMENT
Definition: tag.h:114
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
#define ObDereferenceObject
Definition: obfuncs.h:203

◆ ASSERT() [1/2]

ASSERT ( (Offset->QuadPart % PAGE_SIZE = =0)

◆ ASSERT() [2/2]

ASSERT ( Segment->  Locked)

◆ C_ASSERT() [1/14]

C_ASSERT ( EXEFMT_LOAD_HEADER_SIZE >=  sizeofIMAGE_DOS_HEADER)

◆ C_ASSERT() [2/14]

C_ASSERT ( FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)  = =FIELD_OFFSET(IMAGE_NT_HEADERS64, OptionalHeader))

◆ C_ASSERT() [3/14]

◆ C_ASSERT() [4/14]

◆ C_ASSERT() [5/14]

◆ C_ASSERT() [6/14]

C_ASSERT ( PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, MajorSubsystemVersion)  )

◆ C_ASSERT() [7/14]

C_ASSERT ( PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, MinorSubsystemVersion)  )

◆ C_ASSERT() [8/14]

◆ C_ASSERT() [9/14]

◆ C_ASSERT() [10/14]

◆ C_ASSERT() [11/14]

◆ C_ASSERT() [12/14]

◆ C_ASSERT() [13/14]

◆ C_ASSERT() [14/14]

◆ DPRINT()

DPRINT ( "Checking segment for file %wZ at offset 0x%I64X.\n"  ,
&Segment->FileObject->  FileName,
Offset->  QuadPart 
)

◆ ElfFmtCreateSection()

NTSTATUS NTAPI ElfFmtCreateSection ( 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 
)

◆ ExeFmtpAllocateSegments()

static PMM_SECTION_SEGMENT NTAPI ExeFmtpAllocateSegments ( IN ULONG  NrSegments)
static

Definition at line 2568 of file section.c.

2569{
2570 SIZE_T SizeOfSegments;
2571 PMM_SECTION_SEGMENT Segments;
2572
2573 /* TODO: check for integer overflow */
2574 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * NrSegments;
2575
2577 SizeOfSegments,
2579
2580 if(Segments)
2581 RtlZeroMemory(Segments, SizeOfSegments);
2582
2583 return Segments;
2584}
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
struct _MM_SECTION_SEGMENT MM_SECTION_SEGMENT
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by ExeFmtpCreateImageSection().

◆ ExeFmtpCreateImageSection()

NTSTATUS ExeFmtpCreateImageSection ( PFILE_OBJECT  FileObject,
PMM_IMAGE_SECTION_OBJECT  ImageSectionObject 
)

Definition at line 3002 of file section.c.

3004{
3006 PVOID FileHeader;
3007 PVOID FileHeaderBuffer;
3008 ULONG FileHeaderSize;
3009 ULONG Flags;
3010 ULONG OldNrSegments;
3012 ULONG i;
3013
3014 /*
3015 * Read the beginning of the file (2 pages). Should be enough to contain
3016 * all (or most) of the headers
3017 */
3018 Offset.QuadPart = 0;
3019
3021 &Offset,
3022 PAGE_SIZE * 2,
3023 &FileHeader,
3024 &FileHeaderBuffer,
3025 &FileHeaderSize);
3026
3027 if (!NT_SUCCESS(Status))
3028 return Status;
3029
3030 if (FileHeaderSize == 0)
3031 {
3032 ExFreePool(FileHeaderBuffer);
3033 return STATUS_UNSUCCESSFUL;
3034 }
3035
3036 /*
3037 * Look for a loader that can handle this executable
3038 */
3039 for (i = 0; i < RTL_NUMBER_OF(ExeFmtpLoaders); ++ i)
3040 {
3041 Flags = 0;
3042
3043 Status = ExeFmtpLoaders[i](FileHeader,
3044 FileHeaderSize,
3045 FileObject,
3046 ImageSectionObject,
3047 &Flags,
3050
3051 if (!NT_SUCCESS(Status))
3052 {
3053 if (ImageSectionObject->Segments)
3054 {
3055 ExFreePool(ImageSectionObject->Segments);
3056 ImageSectionObject->Segments = NULL;
3057 }
3058 }
3059
3061 break;
3062 }
3063
3064 ExFreePoolWithTag(FileHeaderBuffer, 'rXmM');
3065
3066 /*
3067 * No loader handled the format
3068 */
3070 {
3073 }
3074
3075 if (!NT_SUCCESS(Status))
3076 return Status;
3077
3078 ASSERT(ImageSectionObject->Segments != NULL);
3079 ASSERT(ImageSectionObject->RefCount > 0);
3080
3081 /*
3082 * Some defaults
3083 */
3084 /* FIXME? are these values platform-dependent? */
3085 if (ImageSectionObject->ImageInformation.MaximumStackSize == 0)
3086 ImageSectionObject->ImageInformation.MaximumStackSize = 0x40000;
3087
3088 if(ImageSectionObject->ImageInformation.CommittedStackSize == 0)
3089 ImageSectionObject->ImageInformation.CommittedStackSize = 0x1000;
3090
3091 if(ImageSectionObject->BasedAddress == NULL)
3092 {
3093 if(ImageSectionObject->ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL)
3094 ImageSectionObject->BasedAddress = (PVOID)0x10000000;
3095 else
3096 ImageSectionObject->BasedAddress = (PVOID)0x00400000;
3097 }
3098
3099 /*
3100 * And now the fun part: fixing the segments
3101 */
3102
3103 /* Sort them by virtual address */
3104 MmspSortSegments(ImageSectionObject, Flags);
3105
3106 /* Ensure they don't overlap in memory */
3107 if (!MmspCheckSegmentBounds(ImageSectionObject, Flags))
3109
3110 /* Ensure they are aligned */
3111 OldNrSegments = ImageSectionObject->NrSegments;
3112
3113 if (!MmspPageAlignSegments(ImageSectionObject, Flags))
3115
3116 /* Trim them if the alignment phase merged some of them */
3117 if (ImageSectionObject->NrSegments < OldNrSegments)
3118 {
3119 PMM_SECTION_SEGMENT Segments;
3120 SIZE_T SizeOfSegments;
3121
3122 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
3123
3125 SizeOfSegments,
3127
3128 if (Segments == NULL)
3130
3131 RtlCopyMemory(Segments, ImageSectionObject->Segments, SizeOfSegments);
3132 ExFreePool(ImageSectionObject->Segments);
3133 ImageSectionObject->Segments = Segments;
3134 }
3135
3136 /* And finish their initialization */
3137 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
3138 {
3139 ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock);
3140 ImageSectionObject->Segments[i].ReferenceCount = &ImageSectionObject->RefCount;
3141 ImageSectionObject->Segments[i].Flags = &ImageSectionObject->SegFlags;
3142 MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]);
3143 ImageSectionObject->Segments[i].FileObject = FileObject;
3144 }
3145
3146 ASSERT(ImageSectionObject->RefCount > 0);
3147
3148 ImageSectionObject->FileObject = FileObject;
3149
3151 return Status;
3152}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define PagedPool
Definition: env_spec_w32.h:308
#define STATUS_ROS_EXEFMT_UNKNOWN_FORMAT
Definition: exeformat.h:72
Status
Definition: gdiplustypes.h:25
VOID NTAPI MiInitializeSectionPageTable(PMM_SECTION_SEGMENT Segment)
Definition: sptab.c:165
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define STATUS_INVALID_IMAGE_FORMAT
Definition: ntstatus.h:359
#define STATUS_INVALID_IMAGE_NOT_MZ
Definition: ntstatus.h:539
#define IMAGE_FILE_DLL
Definition: pedump.c:169
static PMM_SECTION_SEGMENT NTAPI ExeFmtpAllocateSegments(IN ULONG NrSegments)
Definition: section.c:2568
static BOOLEAN NTAPI MmspPageAlignSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2819
static BOOLEAN NTAPI MmspCheckSegmentBounds(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2768
static VOID NTAPI MmspSortSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2742
static NTSTATUS NTAPI ExeFmtpReadFile(IN PVOID File, IN PLARGE_INTEGER Offset, IN ULONG Length, OUT PVOID *Data, OUT PVOID *AllocBase, OUT PULONG ReadSize)
Definition: section.c:2588
static PEXEFMT_LOADER ExeFmtpLoaders[]
Definition: section.c:2557
PLARGE_INTEGER Offset
Definition: section.c:4987
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274

Referenced by MmCreateImageSection().

◆ ExeFmtpReadFile()

static NTSTATUS NTAPI ExeFmtpReadFile ( IN PVOID  File,
IN PLARGE_INTEGER  Offset,
IN ULONG  Length,
OUT PVOID Data,
OUT PVOID AllocBase,
OUT PULONG  ReadSize 
)
static

Definition at line 2588 of file section.c.

2594{
2597 ULONG AdjustOffset;
2598 ULONG OffsetAdjustment;
2600 ULONG UsedSize;
2601 PVOID Buffer;
2604
2606
2607 if(Length == 0)
2608 {
2609 KeBugCheck(MEMORY_MANAGEMENT);
2610 }
2611
2612 FileOffset = *Offset;
2613
2614 /* Negative/special offset: it cannot be used in this context */
2615 if(FileOffset.u.HighPart < 0)
2616 {
2617 KeBugCheck(MEMORY_MANAGEMENT);
2618 }
2619
2620 AdjustOffset = PAGE_ROUND_DOWN(FileOffset.u.LowPart);
2621 OffsetAdjustment = FileOffset.u.LowPart - AdjustOffset;
2622 FileOffset.u.LowPart = AdjustOffset;
2623
2624 BufferSize = Length + OffsetAdjustment;
2626
2627 /*
2628 * It's ok to use paged pool, because this is a temporary buffer only used in
2629 * the loading of executables. The assumption is that MmCreateSection is
2630 * always called at low IRQLs and that these buffers don't survive a brief
2631 * initialization phase
2632 */
2634 if (!Buffer)
2635 {
2637 }
2638
2640
2641 UsedSize = (ULONG)Iosb.Information;
2642
2643 if(NT_SUCCESS(Status) && UsedSize < OffsetAdjustment)
2644 {
2647 }
2648
2649 if(NT_SUCCESS(Status))
2650 {
2651 *Data = (PVOID)((ULONG_PTR)Buffer + OffsetAdjustment);
2652 *AllocBase = Buffer;
2653 *ReadSize = UsedSize - OffsetAdjustment;
2654 }
2655 else
2656 {
2657 ExFreePoolWithTag(Buffer, 'rXmM');
2658 }
2659
2660 return Status;
2661}
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1431
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
Definition: bufpool.h:45
Definition: File.h:16
#define BufferSize
Definition: mmc.h:75
return Iosb
Definition: create.c:4402
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSTATUS NTAPI MiSimpleRead(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PVOID Buffer, ULONG Length, BOOLEAN Paging, PIO_STATUS_BLOCK ReadStatus)
Definition: io.c:109
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:243
#define ASSERT_IRQL_LESS(x)
Definition: debug.h:253
uint32_t ULONG_PTR
Definition: typedefs.h:65
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
* PFILE_OBJECT
Definition: iotypes.h:1998

Referenced by ExeFmtpCreateImageSection().

◆ FreeSegmentPage()

static VOID NTAPI FreeSegmentPage ( PMM_SECTION_SEGMENT  Segment,
PLARGE_INTEGER  Offset 
)
static

Definition at line 961 of file section.c.

962{
965
967
969
971
972 /* This must be either a valid entry or nothing */
974
975 /* There should be no reference anymore */
977
979 /* If there is a page, this must be because it's still dirty */
980 ASSERT(Page != 0);
981
982 /* Write the page */
983 if (IS_DIRTY_SSE(Entry))
984 MiWritePage(Segment, Offset->QuadPart, Page);
985
987}
#define MmGetPageEntrySectionSegment(S, O)
Definition: mm.h:1586
#define MmLockSectionSegment(x)
Definition: mm.h:1380
#define SHARE_COUNT_FROM_SSE(E)
Definition: mm.h:1368
#define MC_USER
Definition: mm.h:114
#define MmUnlockSectionSegment(x)
Definition: mm.h:1388
#define IS_DIRTY_SSE(E)
Definition: mm.h:1360
#define PFN_FROM_SSE(E)
Definition: mm.h:1351
#define IS_SWAP_FROM_SSE(E)
Definition: mm.h:1352
NTSTATUS NTAPI MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
Definition: balance.c:73
ULONG PFN_NUMBER
Definition: ke.h:9
PFN_NUMBER Page
Definition: section.c:4993
NTSTATUS NTAPI MiWritePage(PMM_SECTION_SEGMENT Segment, LONGLONG SegOffset, PFN_NUMBER Page)
Definition: section.c:239
base of all file and directory entries
Definition: entries.h:83

Referenced by _When_().

◆ if() [1/2]

if ( !IS_DIRTY_SSE(Entry) &&(SHARE_COUNT_FROM_SSE(Entry)==0) &&  PageOut)

Definition at line 5138 of file section.c.

5139 {
5140 ULONG_PTR NewEntry = 0;
5141 /* Restore the swap entry here */
5142 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5143 {
5145 if (SwapEntry)
5146 NewEntry = MAKE_SWAP_SSE(SwapEntry);
5147 }
5148
5149 /* Yes. Release it */
5152 /* Tell the caller we released the page */
5153 return TRUE;
5154 }
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define MAKE_SWAP_SSE(S)
Definition: mm.h:1357
ULONG_PTR SWAPENTRY
Definition: mm.h:57
SWAPENTRY NTAPI MmGetSavedSwapEntryPage(PFN_NUMBER Page)
Definition: freelist.c:499
#define MmSetPageEntrySectionSegment(S, O, E)
Definition: section.c:57

◆ if() [2/2]

if ( Entry  = = 0)

Definition at line 5002 of file section.c.

5007 {
5008 BOOLEAN DirtyAgain;
5009
5010 /*
5011 * We got a dirty entry. This path is for the shared data,
5012 * be-it regular file maps or shared sections of DLLs
5013 */
5015 FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5016
5017 /* Insert the cleaned entry back. Mark it as write in progress, and clear the dirty bit. */
5021
5023
5024 if (FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5025 {
5027 KIRQL OldIrql;
5028
5029 /* We have to write it back to the file. Tell the FS driver who we are */
5030 if (PageOut)
5031 {
5032 LARGE_INTEGER EndOffset = *Offset;
5033
5035
5036 /* We need to disable all APCs */
5038
5039 EndOffset.QuadPart += PAGE_SIZE;
5041 &EndOffset,
5043 if (NT_SUCCESS(Status))
5044 {
5046 }
5047 else
5048 {
5049 /* Make sure we will not try to release anything */
5051 }
5052 }
5053 else
5054 {
5055 /* We don't have to lock. Say this is success */
5057 }
5058
5059 /* Go ahead and write the page, if previous locking succeeded */
5060 if (NT_SUCCESS(Status))
5061 {
5062 DPRINT("Writing page at offset %I64d for file %wZ, Pageout: %s\n",
5063 Offset->QuadPart, &Segment->FileObject->FileName, PageOut ? "TRUE" : "FALSE");
5064 Status = MiWritePage(Segment, Offset->QuadPart, Page);
5065 }
5066
5067 if (PageOut)
5068 {
5070 if (ResourceToRelease != NULL)
5071 {
5073 }
5075 }
5076 }
5077 else
5078 {
5079 /* This must only be called by the page-out path */
5080 ASSERT(PageOut);
5081
5082 /* And this must be for a shared section in a DLL */
5083 ASSERT(FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5084
5086 if (!SwapEntry)
5087 {
5088 SwapEntry = MmAllocSwapPage();
5089 }
5090
5091 if (SwapEntry)
5092 {
5093 Status = MmWriteToSwapPage(SwapEntry, Page);
5094 if (NT_SUCCESS(Status))
5095 {
5096 MmSetSavedSwapEntryPage(Page, SwapEntry);
5097 }
5098 else
5099 {
5100 MmFreeSwapPage(SwapEntry);
5101 }
5102 }
5103 else
5104 {
5105 DPRINT1("Failed to allocate a swap page!\n");
5107 }
5108 }
5109
5111
5112 /* Get the entry again */
5115
5116 if (!NT_SUCCESS(Status))
5117 {
5118 /* Damn, this failed. Consider this page as still dirty */
5119 DPRINT1("MiWritePage FAILED: Status 0x%08x!\n", Status);
5120 DirtyAgain = TRUE;
5121 }
5122 else
5123 {
5124 /* Check if someone dirtified this page while we were not looking */
5125 DirtyAgain = IS_DIRTY_SSE(Entry);
5126 }
5127
5128 /* Drop the reference we got, deleting the write altogether. */
5130 if (DirtyAgain)
5131 {
5133 }
5135 }
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define FSRTL_MOD_WRITE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:61
_Check_return_ NTSTATUS NTAPI FsRtlAcquireFileForModWriteEx(_In_ PFILE_OBJECT FileObject, _In_ PLARGE_INTEGER EndingOffset, _Outptr_result_maybenull_ PERESOURCE *ResourceToRelease)
Lock a file object before flushing pages to disk. To be called by the Modified Page Writer (MPW)
Definition: fastio.c:1852
VOID NTAPI FsRtlReleaseFileForModWrite(_In_ PFILE_OBJECT FileObject, _In_ PERESOURCE ResourceToRelease)
Unlock a file object after flushing pages to disk. To be called by the Modified Page Writer (MPW) aft...
Definition: fastio.c:1959
#define DIRTY_SSE(E)
Definition: mm.h:1358
#define MAKE_SSE(P, C)
Definition: mm.h:1370
SWAPENTRY NTAPI MmAllocSwapPage(VOID)
Definition: pagefile.c:322
NTSTATUS NTAPI MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
Definition: pagefile.c:147
#define PAGE_FROM_SSE(E)
Definition: mm.h:1366
VOID NTAPI MmFreeSwapPage(SWAPENTRY Entry)
Definition: pagefile.c:291
VOID NTAPI MmSetSavedSwapEntryPage(PFN_NUMBER Page, SWAPENTRY SavedSwapEntry)
Definition: freelist.c:483
#define WRITE_SSE(E)
Definition: mm.h:1361
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
PLARGE_INTEGER BOOLEAN BOOLEAN PageOut
Definition: section.c:4990
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PLARGE_INTEGER _Out_ struct _ERESOURCE ** ResourceToRelease
Definition: iotypes.h:1598

◆ ImageSectionObjectFromSegment()

PMM_IMAGE_SECTION_OBJECT ImageSectionObjectFromSegment ( PMM_SECTION_SEGMENT  Segment)

Definition at line 121 of file section.c.

122{
123 ASSERT((Segment->SegFlags & MM_DATAFILE_SEGMENT) == 0);
124
125 return CONTAINING_RECORD(Segment->ReferenceCount, MM_IMAGE_SECTION_OBJECT, RefCount);
126}

Referenced by MiRosUnmapViewOfSection().

◆ MiCopyFromUserPage()

static NTSTATUS MiCopyFromUserPage ( PFN_NUMBER  DestPage,
const VOID SrcAddress 
)
static

Definition at line 1171 of file section.c.

1172{
1174 KIRQL Irql;
1175 PVOID DestAddress;
1176
1178 DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
1179 if (DestAddress == NULL)
1180 {
1181 return STATUS_NO_MEMORY;
1182 }
1183 ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
1184 ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
1185 RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
1186 MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
1187 return STATUS_SUCCESS;
1188}
_Out_ PKIRQL Irql
Definition: csq.h:179
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
VOID NTAPI MiUnmapPageInHyperSpace(IN PEPROCESS Process, IN PVOID Address, IN KIRQL OldIrql)
Definition: hypermap.c:91
PVOID NTAPI MiMapPageInHyperSpace(IN PEPROCESS Process, IN PFN_NUMBER Page, IN PKIRQL OldIrql)
Definition: hypermap.c:28
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define PsGetCurrentProcess
Definition: psfuncs.h:17

Referenced by MmAccessFaultSectionView().

◆ MiGrabDataSection()

static PMM_SECTION_SEGMENT MiGrabDataSection ( PSECTION_OBJECT_POINTERS  SectionObjectPointer)
static

Definition at line 91 of file section.c.

92{
93 KIRQL OldIrql = MiAcquirePfnLock();
95
96 while (TRUE)
97 {
98 Segment = SectionObjectPointer->DataSectionObject;
99 if (!Segment)
100 break;
101
103 {
104 MiReleasePfnLock(OldIrql);
106 OldIrql = MiAcquirePfnLock();
107 continue;
108 }
109
112 break;
113 }
114
115 MiReleasePfnLock(OldIrql);
116
117 return Segment;
118}
#define InterlockedIncrement64(a)
Definition: btrfs_drv.h:143
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
_Must_inspect_result_ _In_ PDEVICE_OBJECT _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer
Definition: fsrtlfuncs.h:1369
#define KernelMode
Definition: asm.h:34
#define MM_SEGMENT_INCREATE
Definition: mm.h:240
static LARGE_INTEGER TinyTime
Definition: section.c:64

Referenced by MmCanFileBeTruncated(), MmFlushSegment(), MmMakeDataSectionResident(), and MmPurgeSegment().

◆ MiMapViewInSystemSpace()

NTSTATUS MiMapViewInSystemSpace ( IN PVOID  Section,
IN PVOID  Session,
OUT PVOID MappedBase,
IN OUT PSIZE_T  ViewSize,
IN PLARGE_INTEGER  SectionOffset 
)

◆ MiPurgeImageSegment()

static BOOLEAN MiPurgeImageSegment ( PMM_SECTION_SEGMENT  Segment)
static

Definition at line 4269 of file section.c.

4270{
4272
4274
4275 /* Loop over all entries */
4276 for (PageTable = RtlEnumerateGenericTable(&Segment->PageTable, TRUE);
4277 PageTable != NULL;
4279 {
4280 for (ULONG i = 0; i < _countof(PageTable->PageEntries); i++)
4281 {
4282 ULONG_PTR Entry = PageTable->PageEntries[i];
4284
4285 if (!Entry)
4286 continue;
4287
4289 {
4290 /* I/O ongoing or swap entry. Someone mapped this file as we were not looking */
4292 return FALSE;
4293 }
4294
4295 /* Regular entry */
4298
4299 /* Properly remove using the used API */
4300 Offset.QuadPart = PageTable->FileOffset.QuadPart + (i << PAGE_SHIFT);
4303 }
4304 }
4305
4307
4308 return TRUE;
4309}
#define IS_WRITE_SSE(E)
Definition: mm.h:1362
#define _countof(array)
Definition: sndvol32.h:68
static PMEM_HOOK PageTable[TOTAL_PAGES]
Definition: memory.c:43
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ BOOLEAN Restart)

Referenced by MmFlushImageSection().

◆ MiRosUnmapViewInSystemSpace()

NTSTATUS NTAPI MiRosUnmapViewInSystemSpace ( IN PVOID  MappedBase)

Definition at line 4516 of file section.c.

4517{
4518 DPRINT("MmUnmapViewInSystemSpace() called\n");
4519
4521}
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1688
static NTSTATUS MmUnmapViewOfSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
Definition: section.c:3503
_Must_inspect_result_ _Outptr_result_bytebuffer_ ViewSize PVOID * MappedBase
Definition: mmfuncs.h:492

Referenced by MmUnmapViewInSystemSpace().

◆ MiRosUnmapViewOfSection()

NTSTATUS NTAPI MiRosUnmapViewOfSection ( IN PEPROCESS  Process,
IN PVOID  BaseAddress,
IN BOOLEAN  SkipDebuggerNotify 
)

Definition at line 3567 of file section.c.

3570{
3574 PVOID ImageBaseAddress = 0;
3575
3576 DPRINT("Opening memory area Process %p BaseAddress %p\n",
3578
3579 ASSERT(Process);
3580
3581 AddressSpace = &Process->Vm;
3582
3584 BaseAddress);
3585 if (MemoryArea == NULL ||
3586#ifdef NEWCC
3587 ((MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) && (MemoryArea->Type != MEMORY_AREA_CACHE)) ||
3588#else
3590#endif
3592
3593 {
3595
3596 DPRINT1("Unable to find memory area at address %p.\n", BaseAddress);
3598 }
3599
3601 {
3602 ULONG i;
3603 ULONG NrSegments;
3604 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3605 PMM_SECTION_SEGMENT SectionSegments;
3607
3608 Segment = MemoryArea->SectionData.Segment;
3609 ImageSectionObject = ImageSectionObjectFromSegment(Segment);
3610 SectionSegments = ImageSectionObject->Segments;
3611 NrSegments = ImageSectionObject->NrSegments;
3612
3614
3615 /* Search for the current segment within the section segments
3616 * and calculate the image base address */
3617 for (i = 0; i < NrSegments; i++)
3618 {
3619 if (Segment == &SectionSegments[i])
3620 {
3621 ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
3622 break;
3623 }
3624 }
3625 if (i >= NrSegments)
3626 {
3627 KeBugCheck(MEMORY_MANAGEMENT);
3628 }
3629
3630 for (i = 0; i < NrSegments; i++)
3631 {
3632 PVOID SBaseAddress = (PVOID)
3633 ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
3634
3635 Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
3636 if (!NT_SUCCESS(Status))
3637 {
3638 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3639 SBaseAddress, Process, Status);
3641 }
3642 }
3643 DPRINT("One mapping less for %p\n", ImageSectionObject->FileObject->SectionObjectPointer);
3644 InterlockedDecrement(&ImageSectionObject->MapCount);
3645 }
3646 else
3647 {
3649 PMMVAD Vad = &MemoryArea->VadNode;
3652 LARGE_INTEGER ViewOffset;
3653 ViewOffset.QuadPart = MemoryArea->SectionData.ViewOffset;
3654
3655 InterlockedIncrement64(Segment->ReferenceCount);
3656
3658 if (!NT_SUCCESS(Status))
3659 {
3660 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3663 }
3664
3666 {
3667 /* Don't bother */
3668 MmDereferenceSegment(Segment);
3669 return STATUS_SUCCESS;
3670 }
3672
3673 FileObject = Segment->FileObject;
3675
3676 /* Don't bother for auto-delete closed file. */
3678 {
3680 MmDereferenceSegment(Segment);
3681 return STATUS_SUCCESS;
3682 }
3683
3684 /*
3685 * Flush only when last mapping is deleted.
3686 * FIXME: Why Vad->ControlArea == NULL?
3687 */
3688 if (Vad->ControlArea == NULL || Vad->ControlArea->NumberOfMappedViews == 1)
3689 {
3690 ViewSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
3691 while (ViewSize > 0)
3692 {
3693 ULONG FlushSize = min(ViewSize, PAGE_ROUND_DOWN(MAXULONG));
3694 MmFlushSegment(FileObject->SectionObjectPointer,
3695 &ViewOffset,
3696 FlushSize,
3697 NULL);
3698 ViewSize -= FlushSize;
3699 ViewOffset.QuadPart += FlushSize;
3700 }
3701 }
3702
3704 MmDereferenceSegment(Segment);
3705 }
3706
3707 /* Notify debugger */
3708 if (ImageBaseAddress && !SkipDebuggerNotify) DbgkUnMapViewOfSection(ImageBaseAddress);
3709
3710 return STATUS_SUCCESS;
3711}
#define InterlockedDecrement
Definition: armddk.h:52
VOID NTAPI DbgkUnMapViewOfSection(IN PVOID BaseAddress)
Definition: dbgkutil.c:436
#define ULONG_PTR
Definition: config.h:101
#define min(a, b)
Definition: monoChain.cc:55
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:408
@ VadImageMap
Definition: mmtypes.h:202
_In_ PMEMORY_AREA MemoryArea
Definition: newmm.h:207
VOID NTAPI FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1659
VOID NTAPI FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1634
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:97
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:93
#define MM_PHYSICALMEMORY_SEGMENT
Definition: mm.h:237
#define STATUS_NOT_MAPPED_VIEW
Definition: ntstatus.h:262
PMM_IMAGE_SECTION_OBJECT ImageSectionObjectFromSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:121
NTSTATUS NTAPI MmFlushSegment(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: section.c:4899
ULONG NumberOfMappedViews
Definition: mmtypes.h:522
BOOLEAN DeleteInProgress
Definition: mm.h:253
ULONG Type
Definition: mm.h:251
struct _MEMORY_AREA::@1769 SectionData
MMVAD VadNode
Definition: mm.h:249
ULONG_PTR VadType
Definition: mmtypes.h:691
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
PCONTROL_AREA ControlArea
Definition: mmtypes.h:733
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
union _MMVAD::@2588 u
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
struct _MM_SECTION_SEGMENT::@1768 Image
else
Definition: tritemp.h:161
#define MAXULONG
Definition: typedefs.h:251
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2274
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
#define FO_DELETE_ON_CLOSE
Definition: iotypes.h:1792

Referenced by MiRosCleanupMemoryArea(), and MiUnmapViewOfSection().

◆ MiWritePage()

NTSTATUS NTAPI MiWritePage ( PMM_SECTION_SEGMENT  Segment,
LONGLONG  SegOffset,
PFN_NUMBER  Page 
)

Definition at line 239 of file section.c.

249{
253 UCHAR MdlBase[sizeof(MDL) + sizeof(PFN_NUMBER)];
254 PMDL Mdl = (PMDL)MdlBase;
255 PFILE_OBJECT FileObject = Segment->FileObject;
257
258 FileOffset.QuadPart = Segment->Image.FileOffset + SegOffset;
259
260 RtlZeroMemory(MdlBase, sizeof(MdlBase));
263 Mdl->MdlFlags |= MDL_PAGES_LOCKED;
264
267 if (Status == STATUS_PENDING)
268 {
270 Status = IoStatus.Status;
271 }
272 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
273 {
274 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
275 }
276
277 return Status;
278}
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
NTSTATUS NTAPI IoSynchronousPageWrite(IN PFILE_OBJECT FileObject, IN PMDL Mdl, IN PLARGE_INTEGER Offset, IN PKEVENT Event, IN PIO_STATUS_BLOCK StatusBlock)
Definition: iofunc.c:1146
VOID NTAPI MmUnmapLockedPages(IN PVOID BaseAddress, IN PMDL Mdl)
Definition: mdlsup.c:837
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
@ NotificationEvent
#define STATUS_PENDING
Definition: ntstatus.h:82
VOID NTAPI MmBuildMdlFromPages(PMDL Mdl, PPFN_NUMBER Pages)
Definition: pagefile.c:111
PVOID PMDL
Definition: usb.h:39
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
@ Executive
Definition: ketypes.h:403
#define MmInitializeMdl(_MemoryDescriptorList, _BaseVa, _Length)
MDL
Definition: mmtypes.h:117
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define MDL_MAPPED_TO_SYSTEM_VA
Definition: mmtypes.h:18
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by FreeSegmentPage().

◆ MmAccessFaultSectionView()

NTSTATUS NTAPI MmAccessFaultSectionView ( PMMSUPPORT  AddressSpace,
MEMORY_AREA MemoryArea,
PVOID  Address,
BOOLEAN  Locked 
)

Definition at line 1891 of file section.c.

1895{
1897 PFN_NUMBER OldPage;
1898 PFN_NUMBER NewPage;
1899 PFN_NUMBER UnmappedPage;
1900 PVOID PAddress;
1905 BOOLEAN Cow = FALSE;
1907 BOOLEAN Unmapped;
1908
1909 DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
1910
1911 /* Get the region for this address */
1913 &MemoryArea->SectionData.RegionListHead,
1914 Address, NULL);
1915 ASSERT(Region != NULL);
1916 if (!(Region->Protect & PAGE_IS_WRITABLE))
1918
1919 /* Make sure we have a page mapping for this address. */
1921 {
1923 if (!NT_SUCCESS(Status))
1924 {
1925 /* This is invalid access ! */
1926 return Status;
1927 }
1928 }
1929
1930 /*
1931 * Check if the page has already been set readwrite
1932 */
1934 {
1935 DPRINT("Address 0x%p\n", Address);
1936 return STATUS_SUCCESS;
1937 }
1938
1939 /* Check if we are doing Copy-On-Write */
1940 Segment = MemoryArea->SectionData.Segment;
1941 Cow = Segment->WriteCopy || (Region->Protect & PAGE_IS_WRITECOPY);
1942
1943 if (!Cow)
1944 {
1945 /* Simply update page protection and we're done */
1947 return STATUS_SUCCESS;
1948 }
1949
1950 /* Calculate the new protection & check if we should update the region */
1951 NewProtect = Region->Protect;
1953 {
1954 NewProtect &= ~PAGE_IS_WRITECOPY;
1955 if (Region->Protect & PAGE_IS_EXECUTABLE)
1957 else
1960 &MemoryArea->SectionData.RegionListHead,
1963 }
1964
1965 /*
1966 * Find the offset of the page
1967 */
1968 PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
1969 Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
1970 + MemoryArea->SectionData.ViewOffset;
1971
1972 /* Get the page mapping this section offset. */
1975
1976 /* Get the current page mapping for the process */
1977 ASSERT(MmIsPagePresent(Process, PAddress));
1978 OldPage = MmGetPfnForProcess(Process, PAddress);
1979 ASSERT(OldPage != 0);
1980
1981 if (IS_SWAP_FROM_SSE(Entry) ||
1982 PFN_FROM_SSE(Entry) != OldPage)
1983 {
1985 /* This is a private page. We must only change the page protection. */
1987 return STATUS_SUCCESS;
1988 }
1989
1990 /*
1991 * Allocate a page
1992 */
1994 {
1995 KeBugCheck(MEMORY_MANAGEMENT);
1996 }
1997
1998 /*
1999 * Copy the old page
2000 */
2001 NT_VERIFY(NT_SUCCESS(MiCopyFromUserPage(NewPage, PAddress)));
2002
2003 /*
2004 * Unshare the old page.
2005 */
2006 DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
2007 Unmapped = MmDeleteVirtualMapping(Process, PAddress, NULL, &UnmappedPage);
2008 if (!Unmapped || (UnmappedPage != OldPage))
2009 {
2010 /* Uh , we had a page just before, but suddenly it changes. Someone corrupted us. */
2011 KeBugCheckEx(MEMORY_MANAGEMENT,
2013 (ULONG_PTR)PAddress,
2014 (ULONG_PTR)__FILE__,
2015 __LINE__);
2016 }
2017
2018 if (Process)
2019 MmDeleteRmap(OldPage, Process, PAddress);
2022
2023 /*
2024 * Set the PTE to point to the new page
2025 */
2026 if (!NT_SUCCESS(MmCreateVirtualMapping(Process, PAddress, NewProtect, NewPage)))
2027 {
2028 DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
2029 KeBugCheck(MEMORY_MANAGEMENT);
2030 }
2031
2032 if (Process)
2033 MmInsertRmap(NewPage, Process, PAddress);
2034
2035 DPRINT("Address 0x%p\n", Address);
2036 return STATUS_SUCCESS;
2037}
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:209
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
ULONG NTAPI MmGetPageProtect(struct _EPROCESS *Process, PVOID Address)
PMM_REGION NTAPI MmFindRegion(PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID Address, PVOID *RegionBaseAddress)
Definition: region.c:257
PFN_NUMBER NTAPI MmGetPfnForProcess(struct _EPROCESS *Process, PVOID Address)
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:244
#define PAGE_IS_WRITABLE
Definition: mm.h:153
FORCEINLINE PEPROCESS MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
Definition: mm.h:1673
BOOLEAN NTAPI MmIsPagePresent(struct _EPROCESS *Process, PVOID Address)
NTSTATUS NTAPI MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID StartAddress, SIZE_T Length, ULONG NewType, ULONG NewProtect, PMM_ALTER_REGION_FUNC AlterFunc)
Definition: region.c:108
#define PAGE_IS_EXECUTABLE
Definition: mm.h:159
NTSTATUS NTAPI MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN MyWait, PPFN_NUMBER AllocatedPage)
Definition: balance.c:281
NTSTATUS NTAPI MmCreateVirtualMapping(struct _EPROCESS *Process, PVOID Address, ULONG flProtect, PFN_NUMBER Page)
VOID NTAPI MmDeleteRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
#define MM_ROUND_DOWN(x, s)
Definition: mm.h:131
VOID NTAPI MmInsertRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
#define PAGE_IS_WRITECOPY
Definition: mm.h:165
VOID NTAPI MmDeleteVirtualMapping(IN PEPROCESS Process, IN PVOID Address, OUT PBOOLEAN WasDirty, OUT PPFN_NUMBER Page)
Definition: page.c:177
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
static WCHAR Address[46]
Definition: ping.c:68
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
NTSTATUS NTAPI MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, MEMORY_AREA *MemoryArea, PVOID Address, BOOLEAN Locked)
Definition: section.c:1525
BOOLEAN NTAPI MmUnsharePageEntrySectionSegment(PMEMORY_AREA MemoryArea, PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, BOOLEAN Dirty, BOOLEAN PageOut, ULONG_PTR *InEntry)
Definition: section.c:1090
static NTSTATUS MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
Definition: section.c:1171
static VOID MmAlterViewAttributes(PMMSUPPORT AddressSpace, PVOID BaseAddress, SIZE_T RegionSize, ULONG OldType, ULONG OldProtect, ULONG NewType, ULONG NewProtect)
Definition: section.c:1439
Definition: mm.h:463
_Must_inspect_result_ _In_ ULONG NewProtect
Definition: mmfuncs.h:682
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3287

Referenced by MmpAccessFault().

◆ MmAlterViewAttributes()

static VOID MmAlterViewAttributes ( PMMSUPPORT  AddressSpace,
PVOID  BaseAddress,
SIZE_T  RegionSize,
ULONG  OldType,
ULONG  OldProtect,
ULONG  NewType,
ULONG  NewProtect 
)
static

Definition at line 1439 of file section.c.

1446{
1449 BOOLEAN DoCOW = FALSE;
1450 ULONG i;
1452
1455 Segment = MemoryArea->SectionData.Segment;
1457
1458 if ((Segment->WriteCopy) &&
1460 {
1461 DoCOW = TRUE;
1462 }
1463
1464 if (OldProtect != NewProtect)
1465 {
1466 for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
1467 {
1468 SWAPENTRY SwapEntry;
1469 PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
1471
1472 /* Wait for a wait entry to disappear */
1473 do
1474 {
1475 MmGetPageFileMapping(Process, Address, &SwapEntry);
1476 if (SwapEntry != MM_WAIT_ENTRY)
1477 break;
1483 }
1484 while (TRUE);
1485
1486 /*
1487 * If we doing COW for this segment then check if the page is
1488 * already private.
1489 */
1491 {
1495
1497 + MemoryArea->SectionData.ViewOffset;
1499 /*
1500 * An MM_WAIT_ENTRY is ok in this case... It'll just count as
1501 * IS_SWAP_FROM_SSE and we'll do the right thing.
1502 */
1504
1507 {
1509 }
1510 }
1511
1513 {
1515 Protect);
1516 }
1517 }
1518 }
1519
1521}
#define PAGE_READONLY
Definition: compat.h:138
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1659
VOID NTAPI MmGetPageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY *SwapEntry)
Definition: page.c:299
BOOLEAN NTAPI MmIsDisabledPage(struct _EPROCESS *Process, PVOID Address)
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1666
#define YieldProcessor
Definition: ke.h:48
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG _In_ ULONG Protect
Definition: zwfuncs.h:221

Referenced by MmAccessFaultSectionView(), MmNotPresentFaultSectionView(), and MmProtectSectionView().

◆ MmArePagesResident()

BOOLEAN NTAPI MmArePagesResident ( _In_ PEPROCESS  Process,
_In_ PVOID  Address,
_In_ ULONG  Length 
)

Definition at line 4734 of file section.c.

4738{
4740 BOOLEAN Ret = TRUE;
4742 LARGE_INTEGER SegmentOffset, RangeEnd;
4744
4746
4748 if (MemoryArea == NULL)
4749 {
4751 return FALSE;
4752 }
4753
4754 /* Only supported in old Mm for now */
4756 /* For file mappings */
4758
4759 Segment = MemoryArea->SectionData.Segment;
4761
4763 + MemoryArea->SectionData.ViewOffset;
4765 + MemoryArea->SectionData.ViewOffset;
4766
4767 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
4768 {
4770 if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
4771 {
4772 Ret = FALSE;
4773 break;
4774 }
4775 SegmentOffset.QuadPart += PAGE_SIZE;
4776 }
4777
4779
4781 return Ret;
4782}

Referenced by CcRosEnsureVacbResident().

◆ MmCanFileBeTruncated()

BOOLEAN NTAPI MmCanFileBeTruncated ( _In_ PSECTION_OBJECT_POINTERS  SectionObjectPointer,
_In_opt_ PLARGE_INTEGER  NewFileSize 
)

Definition at line 4214 of file section.c.

4217{
4218 BOOLEAN Ret;
4220
4221 /* Check whether an ImageSectionObject exists */
4222 if (SectionObjectPointer->ImageSectionObject != NULL)
4223 {
4224 DPRINT1("ERROR: File can't be truncated because it has an image section\n");
4225 return FALSE;
4226 }
4227
4229 if (!Segment)
4230 {
4231 /* There is no data section. It's fine to do anything. */
4232 return TRUE;
4233 }
4234
4236 if ((Segment->SectionCount == 0) ||
4237 ((Segment->SectionCount == 1) && (SectionObjectPointer->SharedCacheMap != NULL)))
4238 {
4239 /* If the cache is the only one holding a reference to the segment, then it's fine to resize */
4240 Ret = TRUE;
4241 }
4242 else if (NewFileSize != NULL)
4243 {
4244 /* We can't shrink, but we can extend */
4245 Ret = NewFileSize->QuadPart >= Segment->RawLength.QuadPart;
4246#if DBG
4247 if (!Ret)
4248 {
4249 DPRINT1("Cannot truncate data: New Size %I64d, Segment Size %I64d\n", NewFileSize->QuadPart, Segment->RawLength.QuadPart);
4250 }
4251#endif
4252 }
4253 else
4254 {
4255 DPRINT1("ERROR: File can't be truncated because it has references held to its data section\n");
4256 Ret = FALSE;
4257 }
4258
4260 MmDereferenceSegment(Segment);
4261
4262 DPRINT("FIXME: didn't check for outstanding write probes\n");
4263
4264 return Ret;
4265}
static PMM_SECTION_SEGMENT MiGrabDataSection(PSECTION_OBJECT_POINTERS SectionObjectPointer)
Definition: section.c:91
_In_opt_ PLARGE_INTEGER NewFileSize
Definition: mmfuncs.h:608

Referenced by Ext2SetFileInformation(), Ext2SupersedeOrOverWriteFile(), NtfsSetEndOfFile(), open_file2(), RxCommonSetInformation(), set_end_of_file_information(), SetAttributeDataLength(), UDFCommonCreate(), UDFSetAllocationInformation(), UDFSetEOF(), VfatSetAllocationSizeInformation(), and VfatSetInformation().

◆ MmCreateArm3Section()

NTSTATUS NTAPI MmCreateArm3Section ( OUT PVOID SectionObject,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
IN PLARGE_INTEGER  InputMaximumSize,
IN ULONG  SectionPageProtection,
IN ULONG  AllocationAttributes,
IN HANDLE FileHandle  OPTIONAL,
IN PFILE_OBJECT FileObject  OPTIONAL 
)

Definition at line 2468 of file section.c.

2476{
2477 SECTION Section;
2478 PSECTION NewSection;
2479 PSUBSECTION Subsection;
2480 PSEGMENT NewSegment, Segment;
2482 PCONTROL_AREA ControlArea;
2483 ULONG ProtectionMask, ControlAreaSize, Size, NonPagedCharge, PagedCharge;
2485 BOOLEAN FileLock = FALSE, KernelCall = FALSE;
2486 KIRQL OldIrql;
2488 BOOLEAN UserRefIncremented = FALSE;
2489 PVOID PreviousSectionPointer;
2490
2491 /* Make the same sanity checks that the Nt interface should've validated */
2494 SEC_NO_CHANGE)) == 0);
2504
2505 /* Convert section flag to page flag */
2508
2509 /* Check to make sure the protection is correct. Nt* does this already */
2511 if (ProtectionMask == MM_INVALID_PROTECTION)
2512 {
2513 DPRINT1("Invalid protection mask\n");
2515 }
2516
2517 /* Check if this is going to be a data or image backed file section */
2518 if ((FileHandle) || (FileObject))
2519 {
2520 /* These cannot be mapped with large pages */
2522
2523 /* For now, only support the mechanism through a file handle */
2525
2526 /* Reference the file handle to get the object */
2528 MmMakeFileAccess[ProtectionMask],
2531 (PVOID*)&File,
2532 NULL);
2533 if (!NT_SUCCESS(Status)) return Status;
2534
2535 /* Make sure Cc has been doing its job */
2536 if (!File->SectionObjectPointer)
2537 {
2538 /* This is not a valid file system-based file, fail */
2541 }
2542
2543 /* Image-file backed sections are not yet supported */
2545
2546 /* Compute the size of the control area, and allocate it */
2547 ControlAreaSize = sizeof(CONTROL_AREA) + sizeof(MSUBSECTION);
2548 ControlArea = ExAllocatePoolWithTag(NonPagedPool, ControlAreaSize, 'aCmM');
2549 if (!ControlArea)
2550 {
2553 }
2554
2555 /* Zero it out */
2556 RtlZeroMemory(ControlArea, ControlAreaSize);
2557
2558 /* Did we get a handle, or an object? */
2559 if (FileHandle)
2560 {
2561 /* We got a file handle so we have to lock down the file */
2562#if 0
2564 if (!NT_SUCCESS(Status))
2565 {
2566 ExFreePool(ControlArea);
2568 return Status;
2569 }
2570#else
2571 /* ReactOS doesn't support this API yet, so do nothing */
2573#endif
2574 /* Update the top-level IRP so that drivers know what's happening */
2576 FileLock = TRUE;
2577 }
2578
2579 /* Lock the PFN database while we play with the section pointers */
2580 OldIrql = MiAcquirePfnLock();
2581
2582 /* Image-file backed sections are not yet supported */
2584
2585 /* There should not already be a control area for this file */
2586 ASSERT(File->SectionObjectPointer->DataSectionObject == NULL);
2587 NewSegment = NULL;
2588
2589 /* Write down that this CA is being created, and set it */
2590 ControlArea->u.Flags.BeingCreated = TRUE;
2592 PreviousSectionPointer = File->SectionObjectPointer;
2593 File->SectionObjectPointer->DataSectionObject = ControlArea;
2594
2595 /* We can release the PFN lock now */
2596 MiReleasePfnLock(OldIrql);
2597
2598 /* We don't support previously-mapped file */
2599 ASSERT(NewSegment == NULL);
2600
2601 /* Image-file backed sections are not yet supported */
2603
2604 /* So we always create a data file map */
2606 &Segment,
2607 (PSIZE_T)InputMaximumSize,
2610 KernelCall);
2611 if (!NT_SUCCESS(Status))
2612 {
2613 /* Lock the PFN database while we play with the section pointers */
2614 OldIrql = MiAcquirePfnLock();
2615
2616 /* Reset the waiting-for-deletion event */
2617 ASSERT(ControlArea->WaitingForDeletion == NULL);
2618 ControlArea->WaitingForDeletion = NULL;
2619
2620 /* Set the file pointer NULL flag */
2621 ASSERT(ControlArea->u.Flags.FilePointerNull == 0);
2622 ControlArea->u.Flags.FilePointerNull = TRUE;
2623
2624 /* Delete the data section object */
2626 File->SectionObjectPointer->DataSectionObject = NULL;
2627
2628 /* No longer being created */
2629 ControlArea->u.Flags.BeingCreated = FALSE;
2630
2631 /* We can release the PFN lock now */
2632 MiReleasePfnLock(OldIrql);
2633
2634 /* Check if we locked and set the IRP */
2635 if (FileLock)
2636 {
2637 /* Undo */
2639 //FsRtlReleaseFile(File);
2640 }
2641
2642 /* Free the control area and de-ref the file object */
2643 ExFreePool(ControlArea);
2645
2646 /* All done */
2647 return Status;
2648 }
2649
2650 /* On success, we expect this */
2651 ASSERT(PreviousSectionPointer == File->SectionObjectPointer);
2652
2653 /* Check if a maximum size was specified */
2654 if (!InputMaximumSize->QuadPart)
2655 {
2656 /* Nope, use the segment size */
2657 Section.SizeOfSection.QuadPart = (LONGLONG)Segment->SizeOfSegment;
2658 }
2659 else
2660 {
2661 /* Yep, use the entered size */
2662 Section.SizeOfSection.QuadPart = InputMaximumSize->QuadPart;
2663 }
2664 }
2665 else
2666 {
2667 /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
2669
2670 /* Not yet supported */
2672
2673 /* So this must be a pagefile-backed section, create the mappings needed */
2674 Status = MiCreatePagingFileMap(&NewSegment,
2675 InputMaximumSize,
2676 ProtectionMask,
2678 if (!NT_SUCCESS(Status)) return Status;
2679
2680 /* Set the size here, and read the control area */
2681 Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
2682 ControlArea = NewSegment->ControlArea;
2683
2684 /* MiCreatePagingFileMap increments user references */
2685 UserRefIncremented = TRUE;
2686 }
2687
2688 /* Did we already have a segment? */
2689 if (!NewSegment)
2690 {
2691 /* This must be the file path and we created a segment */
2692 NewSegment = Segment;
2693 ASSERT(File != NULL);
2694
2695 /* Acquire the PFN lock while we set control area flags */
2696 OldIrql = MiAcquirePfnLock();
2697
2698 /* We don't support this race condition yet, so assume no waiters */
2699 ASSERT(ControlArea->WaitingForDeletion == NULL);
2700 ControlArea->WaitingForDeletion = NULL;
2701
2702 /* Image-file backed sections are not yet supported, nor ROM images */
2704 ASSERT(Segment->ControlArea->u.Flags.Rom == 0);
2705
2706 /* Take off the being created flag, and then release the lock */
2707 ControlArea->u.Flags.BeingCreated = FALSE;
2708 MiReleasePfnLock(OldIrql);
2709 }
2710
2711 /* Check if we locked the file earlier */
2712 if (FileLock)
2713 {
2714 /* Reset the top-level IRP and release the lock */
2716 //FsRtlReleaseFile(File);
2717 FileLock = FALSE;
2718 }
2719
2720 /* Set the initial section object data */
2721 Section.InitialPageProtection = SectionPageProtection;
2722
2723 /* The mapping created a control area and segment, save the flags */
2724 Section.Segment = NewSegment;
2725 Section.u.LongFlags = ControlArea->u.LongFlags;
2726
2727 /* Check if this is a user-mode read-write non-image file mapping */
2728 if (!(FileObject) &&
2730 !(ControlArea->u.Flags.Image) &&
2731 (ControlArea->FilePointer))
2732 {
2733 /* Add a reference and set the flag */
2734 Section.u.Flags.UserWritable = TRUE;
2735 InterlockedIncrement((volatile LONG*)&ControlArea->WritableUserReferences);
2736 }
2737
2738 /* Check for image mappings or page file mappings */
2739 if ((ControlArea->u.Flags.Image) || !(ControlArea->FilePointer))
2740 {
2741 /* Charge the segment size, and allocate a subsection */
2742 PagedCharge = sizeof(SECTION) + NewSegment->TotalNumberOfPtes * sizeof(MMPTE);
2743 Size = sizeof(SUBSECTION);
2744 }
2745 else
2746 {
2747 /* Charge nothing, and allocate a mapped subsection */
2748 PagedCharge = 0;
2749 Size = sizeof(MSUBSECTION);
2750 }
2751
2752 /* Check if this is a normal CA */
2753 ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
2754 ASSERT(ControlArea->u.Flags.Rom == 0);
2755
2756 /* Charge only a CA, and the subsection is right after */
2757 NonPagedCharge = sizeof(CONTROL_AREA);
2758 Subsection = (PSUBSECTION)(ControlArea + 1);
2759
2760 /* We only support single-subsection mappings */
2761 NonPagedCharge += Size;
2762 ASSERT(Subsection->NextSubsection == NULL);
2763
2764 /* Create the actual section object, with enough space for the prototype PTEs */
2769 NULL,
2770 sizeof(SECTION),
2771 PagedCharge,
2772 NonPagedCharge,
2773 (PVOID*)&NewSection);
2774 if (!NT_SUCCESS(Status))
2775 {
2776 /* Check if this is a user-mode read-write non-image file mapping */
2777 if (!(FileObject) &&
2779 !(ControlArea->u.Flags.Image) &&
2780 (ControlArea->FilePointer))
2781 {
2782 /* Remove a reference and check the flag */
2783 ASSERT(Section.u.Flags.UserWritable == 1);
2784 InterlockedDecrement((volatile LONG*)&ControlArea->WritableUserReferences);
2785 }
2786
2787 /* Check if a user reference was added */
2788 if (UserRefIncremented)
2789 {
2790 /* Acquire the PFN lock while we change counters */
2791 OldIrql = MiAcquirePfnLock();
2792
2793 /* Decrement the accounting counters */
2794 ControlArea->NumberOfSectionReferences--;
2795 ASSERT((LONG)ControlArea->NumberOfUserReferences > 0);
2796 ControlArea->NumberOfUserReferences--;
2797
2798 /* Check if we should destroy the CA and release the lock */
2799 MiCheckControlArea(ControlArea, OldIrql);
2800 }
2801
2802 /* Return the failure code */
2803 return Status;
2804 }
2805
2806 /* NOTE: Past this point, all failures will be handled by Ob upon ref->0 */
2807
2808 /* Now copy the local section object from the stack into this new object */
2809 RtlCopyMemory(NewSection, &Section, sizeof(SECTION));
2810 NewSection->Address.StartingVpn = 0;
2811
2812 /* For now, only user calls are supported */
2813 ASSERT(KernelCall == FALSE);
2814 NewSection->u.Flags.UserReference = TRUE;
2815
2816 /* Is this a "based" allocation, in which all mappings are identical? */
2818 {
2819 /* Lock the VAD tree during the search */
2821
2822 /* Is it a brand new ControArea ? */
2823 if (ControlArea->u.Flags.BeingCreated == 1)
2824 {
2825 ASSERT(ControlArea->u.Flags.Based == 1);
2826 /* Then we must find a global address, top-down */
2829 _64K,
2831 (ULONG_PTR*)&ControlArea->Segment->BasedAddress);
2832
2833 if (!NT_SUCCESS(Status))
2834 {
2835 /* No way to find a valid range. */
2837 ControlArea->u.Flags.Based = 0;
2838 NewSection->u.Flags.Based = 0;
2839 ObDereferenceObject(NewSection);
2840 return Status;
2841 }
2842
2843 /* Compute the ending address and insert it into the VAD tree */
2844 NewSection->Address.StartingVpn = (ULONG_PTR)ControlArea->Segment->BasedAddress;
2845 NewSection->Address.EndingVpn = NewSection->Address.StartingVpn + NewSection->SizeOfSection.LowPart - 1;
2846 MiInsertBasedSection(NewSection);
2847 }
2848 else
2849 {
2850 /* FIXME : Should we deny section creation if SEC_BASED is not set ? Can we have two different section objects on the same based address ? Investigate !*/
2851 ASSERT(FALSE);
2852 }
2853
2855 }
2856
2857 /* The control area is not being created anymore */
2858 if (ControlArea->u.Flags.BeingCreated == 1)
2859 {
2860 /* Acquire the PFN lock while we set control area flags */
2861 OldIrql = MiAcquirePfnLock();
2862
2863 /* Take off the being created flag, and then release the lock */
2864 ControlArea->u.Flags.BeingCreated = 0;
2865 NewSection->u.Flags.BeingCreated = 0;
2866
2867 MiReleasePfnLock(OldIrql);
2868 }
2869
2870 /* Migrate the attribute into a flag */
2872
2873 /* If R/W access is not requested, this might eventually become a CoW mapping */
2875 {
2876 NewSection->u.Flags.CopyOnWrite = TRUE;
2877 }
2878
2879 /* Write down if this was a kernel call */
2880 ControlArea->u.Flags.WasPurged |= KernelCall;
2881 ASSERT(ControlArea->u.Flags.WasPurged == FALSE);
2882
2883 /* Make sure the segment and the section are the same size, or the section is smaller */
2884 ASSERT((ULONG64)NewSection->SizeOfSection.QuadPart <= NewSection->Segment->SizeOfSegment);
2885
2886 /* Return the object and the creation status */
2887 *SectionObject = (PVOID)NewSection;
2888 return Status;
2889}
KGUARDED_MUTEX MmSectionBasedMutex
Definition: section.c:110
static NTSTATUS NTAPI MiCreatePagingFileMap(OUT PSEGMENT *Segment, IN PLARGE_INTEGER MaximumSize, IN ULONG ProtectionMask, IN ULONG AllocationAttributes)
Definition: section.c:1552
NTSTATUS NTAPI MiCreateDataFileMap(IN PFILE_OBJECT File, OUT PSEGMENT *Segment, IN PSIZE_T MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN ULONG IgnoreFileSizing)
Definition: section.c:1536
PVOID MmHighSectionBase
Definition: section.c:111
VOID NTAPI MiCheckControlArea(IN PCONTROL_AREA ControlArea, IN KIRQL OldIrql)
Definition: section.c:714
ACCESS_MASK MmMakeFileAccess[8]
Definition: section.c:32
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:140
#define InterlockedIncrement
Definition: armddk.h:53
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define ExGetPreviousMode
Definition: ex.h:139
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
#define FSRTL_FSP_TOP_LEVEL_IRP
Definition: fsrtltypes.h:59
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
VOID NTAPI MiInsertBasedSection(IN PSECTION Section)
Definition: vadnode.c:345
NTSTATUS NTAPI MiFindEmptyAddressRangeDownBasedTree(IN SIZE_T Length, IN ULONG_PTR BoundaryAddress, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PULONG_PTR Base)
Definition: vadnode.c:713
#define _64K
Definition: miarm.h:23
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
unsigned __int64 ULONG64
Definition: imports.h:198
#define SECTION
Definition: profile.c:31
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG SectionPageProtection
Definition: mmfuncs.h:363
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ ULONG AllocationAttributes
Definition: mmfuncs.h:364
struct _SUBSECTION * PSUBSECTION
struct _SUBSECTION SUBSECTION
#define SEC_NOCACHE
Definition: mmtypes.h:100
#define SEC_COMMIT
Definition: mmtypes.h:99
#define SEC_IMAGE
Definition: mmtypes.h:96
struct _MSUBSECTION MSUBSECTION
#define SEC_LARGE_PAGES
Definition: mmtypes.h:102
#define SEC_NO_CHANGE
Definition: mmtypes.h:94
struct _CONTROL_AREA CONTROL_AREA
#define PAGE_NOCACHE
Definition: nt_native.h:1311
#define SEC_RESERVE
Definition: nt_native.h:1323
#define PAGE_NOACCESS
Definition: nt_native.h:1302
#define PAGE_GUARD
Definition: nt_native.h:1310
#define SEC_BASED
NTSTATUS NTAPI FsRtlAcquireToCreateMappedSection(_In_ PFILE_OBJECT FileObject, _In_ ULONG SectionPageProtection)
Definition: fastio.c:1647
#define STATUS_INVALID_FILE_FOR_SECTION
Definition: ntstatus.h:269
#define STATUS_INVALID_PARAMETER_6
Definition: ntstatus.h:480
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:305
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1039
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
long LONG
Definition: pedump.c:60
POBJECT_TYPE MmSectionObjectType
Definition: section.c:195
PSEGMENT Segment
Definition: mmtypes.h:518
ULONG NumberOfSectionReferences
Definition: mmtypes.h:520
PEVENT_COUNTER WaitingForDeletion
Definition: mmtypes.h:531
ULONG NumberOfUserReferences
Definition: mmtypes.h:524
ULONG LongFlags
Definition: mmtypes.h:527
ULONG WritableUserReferences
Definition: mmtypes.h:534
MMSECTION_FLAGS Flags
Definition: mmtypes.h:528
PFILE_OBJECT FilePointer
Definition: mmtypes.h:530
union _CONTROL_AREA::@2581 u
ULONG_PTR StartingVpn
Definition: mmtypes.h:650
ULONG_PTR EndingVpn
Definition: mmtypes.h:651
ULONG NoChange
Definition: mmtypes.h:483
ULONG UserReference
Definition: mmtypes.h:476
ULONG CopyOnWrite
Definition: mmtypes.h:471
ULONG FilePointerNull
Definition: mmtypes.h:479
ULONG BeingCreated
Definition: mmtypes.h:461
ULONG GlobalOnlyPerSession
Definition: mmtypes.h:488
ULONG WasPurged
Definition: mmtypes.h:475
MMSECTION_FLAGS Flags
Definition: mmtypes.h:814
union _SECTION::@2597 u
PSEGMENT Segment
Definition: mmtypes.h:809
MMADDRESS_NODE Address
Definition: mmtypes.h:808
LARGE_INTEGER SizeOfSection
Definition: mmtypes.h:810
struct _CONTROL_AREA * ControlArea
Definition: mmtypes.h:406
ULONG TotalNumberOfPtes
Definition: mmtypes.h:407
PVOID BasedAddress
Definition: mmtypes.h:415
ULONGLONG SizeOfSegment
Definition: mmtypes.h:410
struct _SUBSECTION * NextSubsection
Definition: mmtypes.h:581
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
int64_t LONGLONG
Definition: typedefs.h:68
ULONG LowPart
Definition: typedefs.h:106
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define PAGE_WRITECOMBINE
Definition: mmtypes.h:78
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103

Referenced by MmCreateSection().

◆ MmCreateDataFileSection()

static NTSTATUS NTAPI MmCreateDataFileSection ( PSECTION SectionObject,
ACCESS_MASK  DesiredAccess,
POBJECT_ATTRIBUTES  ObjectAttributes,
PLARGE_INTEGER  UMaximumSize,
ULONG  SectionPageProtection,
ULONG  AllocationAttributes,
PFILE_OBJECT  FileObject,
BOOLEAN  GotFileHandle 
)
static

Definition at line 2305 of file section.c.

2316{
2317 PSECTION Section;
2321 KIRQL OldIrql;
2322
2323 /*
2324 * Create the section
2325 */
2330 NULL,
2331 sizeof(*Section),
2332 0,
2333 0,
2334 (PVOID*)&Section);
2335 if (!NT_SUCCESS(Status))
2336 {
2337 return Status;
2338 }
2339 /*
2340 * Initialize it
2341 */
2342 RtlZeroMemory(Section, sizeof(*Section));
2343
2344 /* Mark this as a "ROS" section */
2345 Section->u.Flags.filler = 1;
2347 Section->u.Flags.File = 1;
2348
2350 Section->u.Flags.NoChange = 1;
2352 Section->u.Flags.Reserve = 1;
2353
2354 if (!GotFileHandle)
2355 {
2356 ASSERT(UMaximumSize != NULL);
2357 // ASSERT(UMaximumSize->QuadPart != 0);
2358 MaximumSize = *UMaximumSize;
2359 }
2360 else
2361 {
2364 if (!NT_SUCCESS(Status))
2365 {
2366 ObDereferenceObject(Section);
2367 return Status;
2368 }
2369
2370 /*
2371 * FIXME: Revise this once a locking order for file size changes is
2372 * decided
2373 */
2374 if ((UMaximumSize != NULL) && (UMaximumSize->QuadPart != 0))
2375 {
2376 MaximumSize = *UMaximumSize;
2377 }
2378 else
2379 {
2381 /* Mapping zero-sized files isn't allowed. */
2382 if (MaximumSize.QuadPart == 0)
2383 {
2384 ObDereferenceObject(Section);
2386 }
2387 }
2388
2389 if (MaximumSize.QuadPart > FileSize.QuadPart)
2390 {
2393 sizeof(LARGE_INTEGER),
2394 &MaximumSize);
2395 if (!NT_SUCCESS(Status))
2396 {
2397 ObDereferenceObject(Section);
2399 }
2400 }
2401 }
2402
2403 if (FileObject->SectionObjectPointer == NULL)
2404 {
2405 ObDereferenceObject(Section);
2407 }
2408
2409 /*
2410 * Lock the file
2411 */
2413 if (Status != STATUS_SUCCESS)
2414 {
2415 ObDereferenceObject(Section);
2416 return Status;
2417 }
2418
2419 /* Lock the PFN lock while messing with Section Object pointers */
2420grab_segment:
2421 OldIrql = MiAcquirePfnLock();
2422 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2423
2424 while (Segment && (Segment->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
2425 {
2426 MiReleasePfnLock(OldIrql);
2428 OldIrql = MiAcquirePfnLock();
2429 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2430 }
2431
2432 /*
2433 * If this file hasn't been mapped as a data file before then allocate a
2434 * section segment to describe the data file mapping
2435 */
2436 if (Segment == NULL)
2437 {
2438 /* Release the lock. ExAllocatePoolWithTag might acquire it */
2439 MiReleasePfnLock(OldIrql);
2440
2443 if (Segment == NULL)
2444 {
2445 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2446 ObDereferenceObject(Section);
2447 return STATUS_NO_MEMORY;
2448 }
2449
2450 /* We are creating it */
2451 RtlZeroMemory(Segment, sizeof(*Segment));
2453 Segment->RefCount = 1;
2454
2455 /* Acquire lock again */
2456 OldIrql = MiAcquirePfnLock();
2457
2458 if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
2459 {
2460 /* Well that's bad luck. Restart it all over */
2461 MiReleasePfnLock(OldIrql);
2463 goto grab_segment;
2464 }
2465
2466 FileObject->SectionObjectPointer->DataSectionObject = Segment;
2467
2468 /* We're safe to release the lock now */
2469 MiReleasePfnLock(OldIrql);
2470
2471 Section->Segment = (PSEGMENT)Segment;
2472
2473 /* Self-referencing segment */
2474 Segment->Flags = &Segment->SegFlags;
2475 Segment->ReferenceCount = &Segment->RefCount;
2476
2477 Segment->SectionCount = 1;
2478
2480 Segment->FileObject = FileObject;
2482
2483 Segment->Image.FileOffset = 0;
2484 Segment->Protection = SectionPageProtection;
2485
2486 Segment->Image.Characteristics = 0;
2489 {
2490 Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0;
2491 }
2492 else
2493 {
2494 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2495 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2496 }
2497 Segment->Image.VirtualAddress = 0;
2499
2500 /* We're good to use it now */
2501 OldIrql = MiAcquirePfnLock();
2502 Segment->SegFlags &= ~MM_SEGMENT_INCREATE;
2503 MiReleasePfnLock(OldIrql);
2504 }
2505 else
2506 {
2507 Section->Segment = (PSEGMENT)Segment;
2508 InterlockedIncrement64(&Segment->RefCount);
2509 InterlockedIncrementUL(&Segment->SectionCount);
2510
2511 MiReleasePfnLock(OldIrql);
2512
2514
2515 if (MaximumSize.QuadPart > Segment->RawLength.QuadPart &&
2517 {
2518 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2519 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2520 }
2521
2523 }
2524 Section->SizeOfSection = MaximumSize;
2525
2526 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2527 *SectionObject = Section;
2528 return STATUS_SUCCESS;
2529}
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1526
@ FileEndOfFileInformation
Definition: from_kernel.h:81
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
NTSTATUS NTAPI IoSetInformation(IN PFILE_OBJECT FileObject, IN FILE_INFORMATION_CLASS FileInformationClass, IN ULONG Length, IN PVOID FileInformation)
Definition: iofunc.c:1314
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER MaximumSize
Definition: mmfuncs.h:362
struct _SEGMENT * PSEGMENT
#define PAGE_WRITECOPY
Definition: nt_native.h:1305
#define PAGE_EXECUTE_WRITECOPY
Definition: nt_native.h:1309
NTSTATUS NTAPI FsRtlGetFileSize(IN PFILE_OBJECT FileObject, IN OUT PLARGE_INTEGER FileSize)
Definition: fastio.c:815
#define STATUS_MAPPED_FILE_SIZE_ZERO
Definition: ntstatus.h:522
#define STATUS_SECTION_NOT_EXTENDED
Definition: ntstatus.h:371
NTSTATUS MmspWaitForFileLock(PFILE_OBJECT File)
Definition: section.c:908
ULONG InitialPageProtection
Definition: mmtypes.h:816
#define ObReferenceObject
Definition: obfuncs.h:204

Referenced by MmCreateSection().

◆ MmCreateImageSection()

NTSTATUS MmCreateImageSection ( PSECTION SectionObject,
ACCESS_MASK  DesiredAccess,
POBJECT_ATTRIBUTES  ObjectAttributes,
PLARGE_INTEGER  UMaximumSize,
ULONG  SectionPageProtection,
ULONG  AllocationAttributes,
PFILE_OBJECT  FileObject 
)

Definition at line 3155 of file section.c.

3162{
3163 PSECTION Section;
3165 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3166 KIRQL OldIrql;
3167
3168
3169 if (FileObject == NULL)
3171
3172 if (FileObject->SectionObjectPointer == NULL)
3173 {
3174 DPRINT1("Denying section creation due to missing cache initialization\n");
3176 }
3177
3178 /*
3179 * Create the section
3180 */
3185 NULL,
3186 sizeof(*Section),
3187 0,
3188 0,
3189 (PVOID*)(PVOID)&Section);
3190 if (!NT_SUCCESS(Status))
3191 {
3192 return Status;
3193 }
3194
3195 /*
3196 * Initialize it
3197 */
3198 RtlZeroMemory(Section, sizeof(*Section));
3199
3200 /* Mark this as a "ROS" Section */
3201 Section->u.Flags.filler = 1;
3202
3204 Section->u.Flags.File = 1;
3205 Section->u.Flags.Image = 1;
3207 Section->u.Flags.NoChange = 1;
3208
3209grab_image_section_object:
3210 OldIrql = MiAcquirePfnLock();
3211
3212 /* Wait for it to be properly created or deleted */
3213 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3214 while(ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
3215 {
3216 MiReleasePfnLock(OldIrql);
3217
3219
3220 OldIrql = MiAcquirePfnLock();
3221 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3222 }
3223
3224 if (ImageSectionObject == NULL)
3225 {
3226 NTSTATUS StatusExeFmt;
3227
3228 /* Release the lock because ExAllocatePoolWithTag could need to acquire it */
3229 MiReleasePfnLock(OldIrql);
3230
3231 ImageSectionObject = ExAllocatePoolZero(NonPagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT);
3232 if (ImageSectionObject == NULL)
3233 {
3234 ObDereferenceObject(Section);
3235 return STATUS_NO_MEMORY;
3236 }
3237
3238 ImageSectionObject->SegFlags = MM_SEGMENT_INCREATE;
3239 ImageSectionObject->RefCount = 1;
3240 ImageSectionObject->SectionCount = 1;
3241
3242 OldIrql = MiAcquirePfnLock();
3243 if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
3244 {
3245 MiReleasePfnLock(OldIrql);
3246 /* Bad luck. Start over */
3247 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3248 goto grab_image_section_object;
3249 }
3250
3251 FileObject->SectionObjectPointer->ImageSectionObject = ImageSectionObject;
3252
3253 MiReleasePfnLock(OldIrql);
3254
3255 /* Purge the cache */
3256 CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, NULL);
3257
3258 StatusExeFmt = ExeFmtpCreateImageSection(FileObject, ImageSectionObject);
3259
3260 if (!NT_SUCCESS(StatusExeFmt))
3261 {
3262 /* Unset */
3263 OldIrql = MiAcquirePfnLock();
3264 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3265 MiReleasePfnLock(OldIrql);
3266
3267 if(ImageSectionObject->Segments != NULL)
3268 ExFreePool(ImageSectionObject->Segments);
3269
3270 /*
3271 * If image file is empty, then return that the file is invalid for section
3272 */
3273 Status = StatusExeFmt;
3274 if (StatusExeFmt == STATUS_END_OF_FILE)
3275 {
3277 }
3278
3279 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3280 ObDereferenceObject(Section);
3281 return Status;
3282 }
3283
3284 Section->Segment = (PSEGMENT)ImageSectionObject;
3285 ASSERT(ImageSectionObject->Segments);
3286 ASSERT(ImageSectionObject->RefCount > 0);
3287
3288 /*
3289 * Lock the file
3290 */
3292 if (!NT_SUCCESS(Status))
3293 {
3294 /* Unset */
3295 OldIrql = MiAcquirePfnLock();
3296 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3297 MiReleasePfnLock(OldIrql);
3298
3299 ExFreePool(ImageSectionObject->Segments);
3300 ExFreePool(ImageSectionObject);
3301 ObDereferenceObject(Section);
3302 return Status;
3303 }
3304
3305 OldIrql = MiAcquirePfnLock();
3306 ImageSectionObject->SegFlags &= ~MM_SEGMENT_INCREATE;
3307
3308 /* Take a ref on the file on behalf of the newly created structure */
3310
3311 MiReleasePfnLock(OldIrql);
3312
3313 Status = StatusExeFmt;
3314 }
3315 else
3316 {
3317 /* If FS driver called for delete, tell them it's not possible anymore. */
3318 ImageSectionObject->SegFlags &= ~MM_IMAGE_SECTION_FLUSH_DELETE;
3319
3320 /* Take one ref */
3321 InterlockedIncrement64(&ImageSectionObject->RefCount);
3322 ImageSectionObject->SectionCount++;
3323
3324 MiReleasePfnLock(OldIrql);
3325
3326 Section->Segment = (PSEGMENT)ImageSectionObject;
3327
3329 }
3330 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
3331 *SectionObject = Section;
3332 ASSERT(ImageSectionObject->RefCount > 0);
3333
3334 return Status;
3335}
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
NTSTATUS ExeFmtpCreateImageSection(PFILE_OBJECT FileObject, PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:3002
#define STATUS_END_OF_FILE
Definition: shellext.h:67

Referenced by MmCreateSection().

◆ MmCreatePhysicalMemorySection()

NTSTATUS NTAPI MmCreatePhysicalMemorySection ( VOID  )

Definition at line 2181 of file section.c.

2182{
2183 PSECTION PhysSection;
2186 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
2187 LARGE_INTEGER SectionSize;
2188 HANDLE Handle;
2190
2191 /*
2192 * Create the section mapping physical memory
2193 */
2196 &Name,
2198 NULL,
2199 NULL);
2200 /*
2201 * Create the Object
2202 */
2205 &Obj,
2207 NULL,
2208 sizeof(*PhysSection),
2209 0,
2210 0,
2211 (PVOID*)&PhysSection);
2212 if (!NT_SUCCESS(Status))
2213 {
2214 DPRINT1("MmCreatePhysicalMemorySection: failed to create object (0x%lx)\n", Status);
2215 return Status;
2216 }
2217
2218 /*
2219 * Initialize it
2220 */
2221 RtlZeroMemory(PhysSection, sizeof(*PhysSection));
2222
2223 /* Mark this as a "ROS Section" */
2224 PhysSection->u.Flags.filler = 1;
2226 PhysSection->u.Flags.PhysicalMemory = 1;
2227 PhysSection->SizeOfSection = SectionSize;
2230 if (Segment == NULL)
2231 {
2232 ObDereferenceObject(PhysSection);
2233 return STATUS_NO_MEMORY;
2234 }
2236 PhysSection->Segment = (PSEGMENT)Segment;
2237 Segment->RefCount = 1;
2238
2239 Segment->ReferenceCount = &Segment->RefCount;
2240 Segment->Flags = &Segment->SegFlags;
2241
2243 Segment->Image.FileOffset = 0;
2244 Segment->Protection = PAGE_EXECUTE_READWRITE;
2245 Segment->RawLength = SectionSize;
2246 Segment->Length = SectionSize;
2248 Segment->WriteCopy = FALSE;
2249 Segment->Image.VirtualAddress = 0;
2250 Segment->Image.Characteristics = 0;
2252
2253 Status = ObInsertObject(PhysSection,
2254 NULL,
2256 0,
2257 NULL,
2258 &Handle);
2259 if (!NT_SUCCESS(Status))
2260 {
2261 ObDereferenceObject(PhysSection);
2262 return Status;
2263 }
2265
2266 return STATUS_SUCCESS;
2267}
ULONG Handle
Definition: gdb_input.c:15
#define OBJ_PERMANENT
Definition: winternl.h:226
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define OBJ_KERNEL_EXCLUSIVE
Definition: obtypes.h:91
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
ULONG PhysicalMemory
Definition: mmtypes.h:470
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14

Referenced by MmInitSectionImplementation().

◆ MmCreateSection()

NTSTATUS NTAPI MmCreateSection ( OUT PVOID Section,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
IN PLARGE_INTEGER  MaximumSize,
IN ULONG  SectionPageProtection,
IN ULONG  AllocationAttributes,
IN HANDLE FileHandle  OPTIONAL,
IN PFILE_OBJECT FileObject  OPTIONAL 
)

Definition at line 4579 of file section.c.

4587{
4589 ULONG Protection;
4590 PSECTION *SectionObject = (PSECTION *)Section;
4591 BOOLEAN FileLock = FALSE;
4592
4593 /* Check if an ARM3 section is being created instead */
4595 {
4596 if (!(FileObject) && !(FileHandle))
4597 {
4598 return MmCreateArm3Section(Section,
4604 FileHandle,
4605 FileObject);
4606 }
4607 }
4608
4609 /* Convert section flag to page flag */
4611
4612 /* Check to make sure the protection is correct. Nt* does this already */
4614 if (Protection == MM_INVALID_PROTECTION)
4615 {
4616 DPRINT1("Page protection is invalid\n");
4618 }
4619
4620 /* Check if this is going to be a data or image backed file section */
4621 if ((FileHandle) || (FileObject))
4622 {
4623 /* These cannot be mapped with large pages */
4625 {
4626 DPRINT1("Large pages cannot be used with an image mapping\n");
4628 }
4629
4630 /* Did the caller pass a file object ? */
4631 if (FileObject)
4632 {
4633 /* Reference the object directly */
4635
4636 /* We don't create image mappings with file objects */
4637 AllocationAttributes &= ~SEC_IMAGE;
4638 }
4639 else
4640 {
4641 /* Reference the file handle to get the object */
4643 MmMakeFileAccess[Protection],
4646 (PVOID*)&FileObject,
4647 NULL);
4648 if (!NT_SUCCESS(Status))
4649 {
4650 DPRINT1("Failed to get a handle to the FO: %lx\n", Status);
4651 return Status;
4652 }
4653
4654 /* Lock the file */
4656 if (!NT_SUCCESS(Status))
4657 {
4659 return Status;
4660 }
4661
4662 FileLock = TRUE;
4663
4664 /* Deny access if there are writes on the file */
4665#if 0
4667 {
4668 DPRINT1("Cannot create image maps with writers open on the file!\n");
4670 goto Quit;
4671 }
4672#else
4674 DPRINT1("Creating image map with writers open on the file!\n");
4675#endif
4676 }
4677 }
4678 else
4679 {
4680 /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
4682 }
4683
4685 {
4692 FileObject);
4693 }
4694#ifndef NEWCC
4695 else if (FileObject != NULL)
4696 {
4703 FileObject,
4704 FileHandle != NULL);
4705 }
4706#else
4707 else if (FileHandle != NULL || FileObject != NULL)
4708 {
4715 FileObject);
4716 }
4717#endif
4718 else
4719 {
4720 /* All cases should be handled above */
4722 }
4723
4724 if (FileLock)
4726 if (FileObject)
4728
4729 return Status;
4730}
NTSTATUS NTAPI MmCreateCacheSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
#define SEC_PHYSICALMEMORY
Definition: mm.h:112
#define STATUS_FILE_LOCKED_WITH_WRITERS
Definition: ntstatus.h:112
static NTSTATUS NTAPI MmCreateDataFileSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject, BOOLEAN GotFileHandle)
Definition: section.c:2305
NTSTATUS NTAPI MmCreateArm3Section(OUT PVOID *SectionObject, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER InputMaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: section.c:2468
NTSTATUS MmCreateImageSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
Definition: section.c:3155
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658

Referenced by CcpAllocateSection(), CcRosInitializeFileCache(), EngCreateSection(), EngCreateSectionHack(), EngLoadModuleEx(), InitGdiHandleTable(), IntGdiAddFontResourceEx(), NtCreateSection(), TestCreateSection(), TestPhysicalMemorySection(), and UserCreateHeap().

◆ MmExtendSection()

NTSTATUS NTAPI MmExtendSection ( _In_ PVOID  _Section,
_Inout_ PLARGE_INTEGER  NewSize 
)

Definition at line 5232 of file section.c.

5235{
5236 PSECTION Section = _Section;
5237
5238 /* It makes no sense to extend an image mapping */
5239 if (Section->u.Flags.Image)
5241
5242 /* Nor is it possible to extend a page file mapping */
5243 if (!Section->u.Flags.File)
5245
5246 if (!MiIsRosSectionObject(Section))
5248
5249 /* We just extend the sizes. Shrinking is a no-op ? */
5250 if (NewSize->QuadPart > Section->SizeOfSection.QuadPart)
5251 {
5253 Section->SizeOfSection = *NewSize;
5254
5255 if (!Section->u.Flags.Reserve)
5256 {
5258 if (Segment->RawLength.QuadPart < NewSize->QuadPart)
5259 {
5260 Segment->RawLength = *NewSize;
5261 Segment->Length.QuadPart = (NewSize->QuadPart + PAGE_SIZE - 1) & ~((LONGLONG)PAGE_SIZE);
5262 }
5264 }
5265 }
5266
5267 return STATUS_SUCCESS;
5268}
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
if(dx< 0)
Definition: linetemp.h:194
FORCEINLINE BOOLEAN MiIsRosSectionObject(IN PSECTION Section)
Definition: miarm.h:1098
struct _MM_SECTION_SEGMENT * PMM_SECTION_SEGMENT
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239

Referenced by CcSetFileSizes(), and NtExtendSection().

◆ MmFlushImageSection()

BOOLEAN NTAPI MmFlushImageSection ( IN PSECTION_OBJECT_POINTERS  SectionObjectPointer,
IN MMFLUSH_TYPE  FlushType 
)

Definition at line 4315 of file section.c.

4317{
4318 switch(FlushType)
4319 {
4320 case MmFlushForDelete:
4321 {
4322 /*
4323 * FIXME: Check for outstanding write probes on Data section.
4324 * How do we do that ?
4325 */
4326 }
4327 /* Fall-through */
4328 case MmFlushForWrite:
4329 {
4330 KIRQL OldIrql = MiAcquirePfnLock();
4331 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4332
4333 DPRINT("Deleting or modifying %p\n", SectionObjectPointer);
4334
4335 /* Wait for concurrent creation or deletion of image to be done */
4336 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4337 while (ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INCREATE | MM_SEGMENT_INDELETE)))
4338 {
4339 MiReleasePfnLock(OldIrql);
4341 OldIrql = MiAcquirePfnLock();
4342 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4343 }
4344
4345 if (!ImageSectionObject)
4346 {
4347 DPRINT("No image section object. Accepting\n");
4348 /* Nothing to do */
4349 MiReleasePfnLock(OldIrql);
4350 return TRUE;
4351 }
4352
4353 /* Do we have open sections or mappings on it ? */
4354 if ((ImageSectionObject->SectionCount) || (ImageSectionObject->MapCount))
4355 {
4356 /* We do. No way to delete it */
4357 MiReleasePfnLock(OldIrql);
4358 DPRINT("Denying. There are mappings open\n");
4359 return FALSE;
4360 }
4361
4362 /* There are no sections open on it, but we must still have pages around. Discard everything */
4363 ImageSectionObject->SegFlags |= MM_IMAGE_SECTION_FLUSH_DELETE;
4364 InterlockedIncrement64(&ImageSectionObject->RefCount);
4365 MiReleasePfnLock(OldIrql);
4366
4367 DPRINT("Purging\n");
4368
4369 for (ULONG i = 0; i < ImageSectionObject->NrSegments; i++)
4370 {
4371 if (!MiPurgeImageSegment(&ImageSectionObject->Segments[i]))
4372 break;
4373 }
4374
4375 /* Grab lock again */
4376 OldIrql = MiAcquirePfnLock();
4377
4378 if (!(ImageSectionObject->SegFlags & MM_IMAGE_SECTION_FLUSH_DELETE))
4379 {
4380 /*
4381 * Someone actually created a section while we were not looking.
4382 * Drop our ref and deny.
4383 * MmDereferenceSegmentWithLock releases Pfn lock
4384 */
4385 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4386 return FALSE;
4387 }
4388
4389 /* We should be the last one holding a ref here. */
4390 ASSERT(ImageSectionObject->RefCount == 1);
4391 ASSERT(ImageSectionObject->SectionCount == 0);
4392
4393 /* Dereference the first segment, this will free everything & release the lock */
4394 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4395 return TRUE;
4396 }
4397 }
4398 return FALSE;
4399}
IN PFCB IN FAT_FLUSH_TYPE FlushType
Definition: fatprocs.h:1082
#define MM_IMAGE_SECTION_FLUSH_DELETE
Definition: mm.h:241
static BOOLEAN MiPurgeImageSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:4269

Referenced by _Requires_lock_held_(), Ext2CreateFile(), Ext2IsFileRemovable(), Ext2PurgeFile(), Ext2PurgeVolume(), FatSetRenameInfo(), open_file3(), RxCommonSetInformation(), RxPurgeFcbInSystemCache(), RxPurgeFobx(), RxPurgeNetFcb(), set_disposition_information(), UDFCloseAllXXXDelayedInDir(), UDFCommonCreate(), UDFMarkStreamsForDeletion(), UDFSetDispositionInformation(), VfatCreateFile(), vfatPrepareTargetForRename(), and VfatSetDispositionInformation().

◆ MmFlushSegment()

NTSTATUS NTAPI MmFlushSegment ( _In_ PSECTION_OBJECT_POINTERS  SectionObjectPointer,
_In_opt_ PLARGE_INTEGER  Offset,
_In_ ULONG  Length,
_Out_opt_ PIO_STATUS_BLOCK  Iosb 
)

Definition at line 4899 of file section.c.

4904{
4905 LARGE_INTEGER FlushStart, FlushEnd;
4907
4908 if (Offset)
4909 {
4910 FlushStart = *Offset;
4911 Status = RtlLongLongAdd(FlushStart.QuadPart, Length, &FlushEnd.QuadPart);
4912 if (!NT_SUCCESS(Status))
4913 return Status;
4914 }
4915
4916 if (Iosb)
4917 Iosb->Information = 0;
4918
4920 if (!Segment)
4921 {
4922 /* Nothing to flush */
4923 if (Iosb)
4924 Iosb->Status = STATUS_SUCCESS;
4925 return STATUS_SUCCESS;
4926 }
4927
4929
4931
4932 if (!Offset)
4933 {
4934 FlushStart.QuadPart = 0;
4935
4936 /* FIXME: All of this is suboptimal */
4937 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
4938 /* No page. Nothing to flush */
4939 if (!ElemCount)
4940 {
4942 MmDereferenceSegment(Segment);
4943 if (Iosb)
4944 {
4945 Iosb->Status = STATUS_SUCCESS;
4946 Iosb->Information = 0;
4947 }
4948 return STATUS_SUCCESS;
4949 }
4950
4952 FlushEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
4953 }
4954
4955 FlushStart.QuadPart >>= PAGE_SHIFT;
4956 FlushStart.QuadPart <<= PAGE_SHIFT;
4957
4958 while (FlushStart.QuadPart < FlushEnd.QuadPart)
4959 {
4961
4962 if (IS_DIRTY_SSE(Entry))
4963 {
4964 MmCheckDirtySegment(Segment, &FlushStart, FALSE, FALSE);
4965
4966 if (Iosb)
4967 Iosb->Information += PAGE_SIZE;
4968 }
4969
4970 FlushStart.QuadPart += PAGE_SIZE;
4971 }
4972
4974 MmDereferenceSegment(Segment);
4975
4976 if (Iosb)
4977 Iosb->Status = STATUS_SUCCESS;
4978
4979 return STATUS_SUCCESS;
4980}
BOOLEAN NTAPI MmCheckDirtySegment(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, BOOLEAN ForceDirty, BOOLEAN PageOut)
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlGetElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ ULONG I)
NTSYSAPI ULONG NTAPI RtlNumberGenericTableElements(_In_ PRTL_GENERIC_TABLE Table)

Referenced by CcFlushCache(), CcRosDeleteFileCache(), CcRosFlushVacb(), and MiRosUnmapViewOfSection().

◆ MmFreeSectionPage()

static VOID MmFreeSectionPage ( PVOID  Context,
MEMORY_AREA MemoryArea,
PVOID  Address,
PFN_NUMBER  Page,
SWAPENTRY  SwapEntry,
BOOLEAN  Dirty 
)
static

Definition at line 3419 of file section.c.

3421{
3424 SWAPENTRY SavedSwapEntry;
3428
3431
3433
3435 MemoryArea->SectionData.ViewOffset;
3436
3437 Segment = MemoryArea->SectionData.Segment;
3438
3440 while (Entry && MM_IS_WAIT_PTE(Entry))
3441 {
3444
3446
3450 }
3451
3452 /*
3453 * For a dirty, datafile, non-private page, there shoulkd be no swap entry
3454 */
3455 if (*Segment->Flags & MM_DATAFILE_SEGMENT)
3456 {
3457 if (Page == PFN_FROM_SSE(Entry) && Dirty)
3458 {
3459 ASSERT(SwapEntry == 0);
3460 }
3461 }
3462
3463 if (SwapEntry != 0)
3464 {
3465 /*
3466 * Sanity check
3467 */
3468 MmFreeSwapPage(SwapEntry);
3469 }
3470 else if (Page != 0)
3471 {
3472 if (IS_SWAP_FROM_SSE(Entry) ||
3474 {
3475 ASSERT(Process != NULL);
3476
3477 /*
3478 * Just dereference private pages
3479 */
3480 SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
3481 if (SavedSwapEntry != 0)
3482 {
3483 MmFreeSwapPage(SavedSwapEntry);
3485 }
3488 }
3489 else
3490 {
3491 if (Process)
3492 {
3494 }
3495
3496 /* We don't dirtify for System Space Maps. We let Cc manage that */
3498 }
3499 }
3500}
struct _MMSUPPORT * PMMSUPPORT
#define MM_IS_WAIT_PTE(E)
Definition: mm.h:1353

Referenced by MmUnmapViewOfSegment().

◆ MmInitSectionImplementation()

NTSTATUS NTAPI MmInitSectionImplementation ( VOID  )

Definition at line 2272 of file section.c.

2273{
2274 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
2276
2277 DPRINT("Creating Section Object Type\n");
2278
2279 /* Initialize the section based root */
2282
2283 /* Initialize the Section object type */
2284 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
2285 RtlInitUnicodeString(&Name, L"Section");
2286 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
2287 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(SECTION);
2288 ObjectTypeInitializer.PoolType = PagedPool;
2289 ObjectTypeInitializer.UseDefaultObject = TRUE;
2290 ObjectTypeInitializer.GenericMapping = MmpSectionMapping;
2291 ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
2292 ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
2293 ObjectTypeInitializer.ValidAccessMask = SECTION_ALL_ACCESS;
2294 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
2295 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &MmSectionObjectType);
2296
2298
2299 return STATUS_SUCCESS;
2300}
struct NameRec_ * Name
Definition: cdprocs.h:460
#define OBJ_OPENLINK
Definition: winternl.h:230
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1136
static GENERIC_MAPPING MmpSectionMapping
Definition: section.c:224
VOID NTAPI MmpDeleteSection(PVOID ObjectBody)
Definition: section.c:2116
VOID NTAPI MmpCloseSection(IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG ProcessHandleCount, IN ULONG SystemHandleCount)
Definition: section.c:2169
NTSTATUS NTAPI MmCreatePhysicalMemorySection(VOID)
Definition: section.c:2181
union _MMADDRESS_NODE::@2586 u1
struct _MMADDRESS_NODE * Parent
Definition: mmtypes.h:646
ULONG_PTR NumberGenericTableElements
Definition: mmtypes.h:665
MMADDRESS_NODE BalancedRoot
Definition: mmtypes.h:659
OB_CLOSE_METHOD CloseProcedure
Definition: obtypes.h:368
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
OB_DELETE_METHOD DeleteProcedure
Definition: obtypes.h:369

Referenced by MmInitSystem().

◆ MmMakeDataSectionResident()

NTSTATUS NTAPI MmMakeDataSectionResident ( _In_ PSECTION_OBJECT_POINTERS  SectionObjectPointer,
_In_ LONGLONG  Offset,
_In_ ULONG  Length,
_In_ PLARGE_INTEGER  ValidDataLength 
)

Definition at line 4879 of file section.c.

4884{
4886
4887 /* There must be a segment for this call */
4888 ASSERT(Segment);
4889
4891
4892 MmDereferenceSegment(Segment);
4893
4894 return Status;
4895}
static NTSTATUS NTAPI MmMakeSegmentResident(_In_ PMM_SECTION_SEGMENT Segment, _In_ LONGLONG Offset, _In_ ULONG Length, _In_opt_ PLARGE_INTEGER ValidDataLength, _In_ BOOLEAN SetDirty)
Definition: section.c:1193

Referenced by CcRosEnsureVacbResident().

◆ MmMakePagesDirty()

NTSTATUS NTAPI MmMakePagesDirty ( _In_ PEPROCESS  Process,
_In_ PVOID  Address,
_In_ ULONG  Length 
)

Definition at line 5161 of file section.c.

5165{
5168 LARGE_INTEGER SegmentOffset, RangeEnd;
5170
5172
5174 if (MemoryArea == NULL)
5175 {
5176 DPRINT1("Unable to find memory area at address %p.\n", Address);
5179 }
5180
5181 /* Only supported in old Mm for now */
5183 /* For file mappings */
5185
5186 Segment = MemoryArea->SectionData.Segment;
5188
5190 + MemoryArea->SectionData.ViewOffset;
5192 + MemoryArea->SectionData.ViewOffset;
5193
5194 DPRINT("MmMakePagesResident: Segment %p, 0x%I64x -> 0x%I64x\n", Segment, SegmentOffset.QuadPart, RangeEnd.QuadPart);
5195
5196 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
5197 {
5199
5200 /* Let any pending read proceed */
5201 while (MM_IS_WAIT_PTE(Entry))
5202 {
5208 Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset);
5209 }
5210
5211 /* We are called from Cc, this can't be backed by the page files */
5213
5214 /* If there is no page there, there is nothing to make dirty */
5215 if (Entry != 0)
5216 {
5217 /* Dirtify the entry */
5219 }
5220
5221 SegmentOffset.QuadPart += PAGE_SIZE;
5222 }
5223
5225
5227 return STATUS_SUCCESS;
5228}

Referenced by CcCopyWrite(), CcSetDirtyPinnedData(), and CcZeroData().

◆ MmMakeSegmentResident()

static NTSTATUS NTAPI MmMakeSegmentResident ( _In_ PMM_SECTION_SEGMENT  Segment,
_In_ LONGLONG  Offset,
_In_ ULONG  Length,
_In_opt_ PLARGE_INTEGER  ValidDataLength,
_In_ BOOLEAN  SetDirty 
)
static

Definition at line 1193 of file section.c.

1199{
1200 /* Let's use a 64K granularity. */
1201 LONGLONG RangeStart, RangeEnd;
1203 PFILE_OBJECT FileObject = Segment->FileObject;
1204
1205 /* Calculate our range, aligned on 64K if possible. */
1206 Status = RtlLongLongAdd(Offset, Length, &RangeEnd);
1208 if (!NT_SUCCESS(Status))
1209 return Status;
1210
1211 /* If the file is not random access and we are not the page out thread
1212 * read a 64K Chunk. */
1214 && !FlagOn(FileObject->Flags, FO_RANDOM_ACCESS))
1215 {
1216 RangeStart = Offset - (Offset % _64K);
1217 if (RangeEnd % _64K)
1218 RangeEnd += _64K - (RangeEnd % _64K);
1219 }
1220 else
1221 {
1222 RangeStart = Offset - (Offset % PAGE_SIZE);
1223 if (RangeEnd % PAGE_SIZE)
1224 RangeEnd += PAGE_SIZE - (RangeEnd % PAGE_SIZE);
1225 }
1226
1227 /* Clamp if needed */
1228 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
1229 {
1230 if (RangeEnd > Segment->RawLength.QuadPart)
1231 RangeEnd = Segment->RawLength.QuadPart;
1232 }
1233
1234 /* Let's gooooooooo */
1235 for ( ; RangeStart < RangeEnd; RangeStart += _64K)
1236 {
1237 /* First take a look at where we miss pages */
1238 ULONG ToReadPageBits = 0;
1239 LONGLONG ChunkEnd = RangeStart + _64K;
1240
1241 if (ChunkEnd > RangeEnd)
1242 ChunkEnd = RangeEnd;
1243
1245 for (LONGLONG ChunkOffset = RangeStart; ChunkOffset < ChunkEnd; ChunkOffset += PAGE_SIZE)
1246 {
1247 LARGE_INTEGER CurrentOffset;
1248
1249 CurrentOffset.QuadPart = ChunkOffset;
1251
1252 /* Let any pending read proceed */
1253 while (MM_IS_WAIT_PTE(Entry))
1254 {
1256
1258
1260 Entry = MmGetPageEntrySectionSegment(Segment, &CurrentOffset);
1261 }
1262
1263 if (Entry != 0)
1264 {
1265 /* Dirtify it if it's a resident page and we're asked to */
1266 if (SetDirty && !IS_SWAP_FROM_SSE(Entry))
1268 continue;
1269 }
1270
1271 ToReadPageBits |= 1UL << ((ChunkOffset - RangeStart) >> PAGE_SHIFT);
1272
1273 /* Put a wait entry here */
1274 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
1275 }
1277
1278 if (ToReadPageBits == 0)
1279 {
1280 /* Nothing to do for this chunk */
1281 continue;
1282 }
1283
1284 /* Now perform the actual read */
1285 LONGLONG ChunkOffset = RangeStart;
1286 while (ChunkOffset < ChunkEnd)
1287 {
1288 /* Move forward if there is a hole */
1289 ULONG BitSet;
1290 if (!_BitScanForward(&BitSet, ToReadPageBits))
1291 {
1292 /* Nothing more to read */
1293 break;
1294 }
1295 ToReadPageBits >>= BitSet;
1296 ChunkOffset += BitSet * PAGE_SIZE;
1297 ASSERT(ChunkOffset < ChunkEnd);
1298
1299 /* Get the range we have to read */
1300 _BitScanForward(&BitSet, ~ToReadPageBits);
1301 ULONG ReadLength = BitSet * PAGE_SIZE;
1302
1304
1305 /* Clamp (This is for image mappings */
1306 if ((ChunkOffset + ReadLength) > ChunkEnd)
1307 ReadLength = ChunkEnd - ChunkOffset;
1308
1309 ASSERT(ReadLength != 0);
1310
1311 /* Allocate a MDL */
1313 if (!Mdl)
1314 {
1315 /* Damn. Roll-back. */
1317 while (ChunkOffset < ChunkEnd)
1318 {
1319 if (ToReadPageBits & 1)
1320 {
1321 LARGE_INTEGER CurrentOffset;
1322 CurrentOffset.QuadPart = ChunkOffset;
1324 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, 0);
1325 }
1326 ToReadPageBits >>= 1;
1327 ChunkOffset += PAGE_SIZE;
1328 }
1331 }
1332
1333 /* Get our pages */
1336 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1337 {
1338 /* MmRequestPageMemoryConsumer succeeds or bugchecks */
1340 }
1341 Mdl->MdlFlags |= MDL_PAGES_LOCKED | MDL_IO_PAGE_READ;
1342
1344 FileOffset.QuadPart = Segment->Image.FileOffset + ChunkOffset;
1345
1346 /* Clamp to VDL */
1347 if (ValidDataLength && ((FileOffset.QuadPart + ReadLength) > ValidDataLength->QuadPart))
1348 {
1349 if (FileOffset.QuadPart > ValidDataLength->QuadPart)
1350 {
1351 /* Great, nothing to read. */
1352 goto AssignPagesToSegment;
1353 }
1354
1355 Mdl->Size = (FileOffset.QuadPart + ReadLength) - ValidDataLength->QuadPart;
1356 }
1357
1358 KEVENT Event;
1360
1361 /* Disable APCs */
1362 KIRQL OldIrql;
1364
1367 if (Status == STATUS_PENDING)
1368 {
1370 Status = Iosb.Status;
1371 }
1372
1373 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
1374 {
1375 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
1376 }
1377
1379
1381 {
1382 DPRINT1("Got STATUS_END_OF_FILE at offset %I64d for file %wZ.\n", FileOffset.QuadPart, &FileObject->FileName);
1384 }
1385
1386 if (!NT_SUCCESS(Status))
1387 {
1388 /* Damn. Roll back. */
1389 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1391
1393 while (ChunkOffset < ChunkEnd)
1394 {
1395 if (ToReadPageBits & 1)
1396 {
1397 LARGE_INTEGER CurrentOffset;
1398 CurrentOffset.QuadPart = ChunkOffset;
1400 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, 0);
1401 }
1402 ToReadPageBits >>= 1;
1403 ChunkOffset += PAGE_SIZE;
1404 }
1406 IoFreeMdl(Mdl);;
1407 return Status;
1408 }
1409
1410AssignPagesToSegment:
1412
1413 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1414 {
1415 ULONG_PTR Entry = MAKE_SSE(Pages[i] << PAGE_SHIFT, 0);
1416 LARGE_INTEGER CurrentOffset;
1417 CurrentOffset.QuadPart = ChunkOffset + (i * PAGE_SIZE);
1418
1420
1421 if (SetDirty)
1423
1424 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, Entry);
1425 }
1426
1428
1429 IoFreeMdl(Mdl);
1430 ToReadPageBits >>= BitSet;
1431 ChunkOffset += BitSet * PAGE_SIZE;
1432 }
1433 }
1434
1435 return STATUS_SUCCESS;
1436}
ULONG ReadLength
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask)
Definition: intrin_arm.h:57
NTSTATUS NTAPI IoPageRead(IN PFILE_OBJECT FileObject, IN PMDL Mdl, IN PLARGE_INTEGER Offset, IN PKEVENT Event, IN PIO_STATUS_BLOCK StatusBlock)
Definition: iofunc.c:1201
unsigned int UINT
Definition: ndis.h:50
ULONG * PPFN_NUMBER
Definition: ke.h:9
#define FO_RANDOM_ACCESS
Definition: iotypes.h:1796
@ WrPageIn
Definition: ketypes.h:412
#define BYTES_TO_PAGES(Size)
#define MmGetMdlPfnArray(_Mdl)
#define MDL_IO_PAGE_READ
Definition: mmtypes.h:24

Referenced by MmMakeDataSectionResident(), and MmNotPresentFaultSectionView().

◆ MmMapViewInSystemSpace()

NTSTATUS NTAPI MmMapViewInSystemSpace ( IN PVOID  SectionObject,
OUT PVOID MappedBase,
IN OUT PSIZE_T  ViewSize 
)

Definition at line 4406 of file section.c.

4409{
4411
4412 SectionOffset.QuadPart = 0;
4413
4415}
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER SectionOffset
Definition: mmfuncs.h:407
NTSTATUS NTAPI MmMapViewInSystemSpaceEx(_In_ PVOID SectionObject, _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, _Inout_ PSIZE_T ViewSize, _Inout_ PLARGE_INTEGER SectionOffset, _In_ ULONG_PTR Flags)
Definition: section.c:4419

Referenced by ExpInitNls(), IntGdiAddFontResourceEx(), and MmMapViewInSessionSpace().

◆ MmMapViewInSystemSpaceEx()

NTSTATUS NTAPI MmMapViewInSystemSpaceEx ( _In_ PVOID  SectionObject,
_Outptr_result_bytebuffer_ *ViewSize PVOID MappedBase,
_Inout_ PSIZE_T  ViewSize,
_Inout_ PLARGE_INTEGER  SectionOffset,
_In_ ULONG_PTR  Flags 
)

Definition at line 4419 of file section.c.

4426{
4427 PSECTION Section = SectionObject;
4431
4433
4434 PAGED_CODE();
4435
4437 {
4439 &MmSession,
4440 MappedBase,
4441 ViewSize,
4443 }
4444
4445 DPRINT("MmMapViewInSystemSpaceEx() called\n");
4446
4447 /* unsupported for now */
4448 ASSERT(Section->u.Flags.Image == 0);
4449
4450 Section = SectionObject;
4452
4453 if (*ViewSize == 0)
4454 {
4455 LONGLONG MapSizeLL;
4456
4457 /* Page-align the mapping */
4458 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4459
4460 if (!NT_SUCCESS(RtlLongLongSub(Section->SizeOfSection.QuadPart, SectionOffset->QuadPart, &MapSizeLL)))
4462
4463 if (!NT_SUCCESS(RtlLongLongToSIZET(MapSizeLL, ViewSize)))
4465 }
4466 else
4467 {
4468 LONGLONG HelperLL;
4469
4470 /* Get the map end */
4471 if (!NT_SUCCESS(RtlLongLongAdd(SectionOffset->QuadPart, *ViewSize, &HelperLL)))
4473
4474 /* Round it up, if needed */
4475 if (HelperLL % PAGE_SIZE)
4476 {
4477 if (!NT_SUCCESS(RtlLongLongAdd(HelperLL, PAGE_SIZE - (HelperLL % PAGE_SIZE), &HelperLL)))
4479 }
4480
4481 /* Now that we have the mapping end, we can align down its start */
4482 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4483
4484 /* Get the new size */
4485 if (!NT_SUCCESS(RtlLongLongSub(HelperLL, SectionOffset->QuadPart, &HelperLL)))
4487
4488 if (!NT_SUCCESS(RtlLongLongToSIZET(HelperLL, ViewSize)))
4490 }
4491
4493
4495
4497
4499 Section->u.Flags.Image,
4500 Segment,
4501 MappedBase,
4502 *ViewSize,
4504 SectionOffset->QuadPart,
4505 SEC_RESERVE);
4506
4509
4510 return Status;
4511}
NTSTATUS MiMapViewInSystemSpace(_In_ PVOID Section, _In_ PMMSESSION Session, _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, _Inout_ PSIZE_T ViewSize, _Inout_ PLARGE_INTEGER SectionOffset)
Definition: section.c:1040
MMSESSION MmSession
Definition: section.c:107
#define PAGED_CODE()
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_INVALID_VIEW_SIZE
Definition: ntstatus.h:268
static NTSTATUS MmMapViewOfSegment(PMMSUPPORT AddressSpace, BOOLEAN AsImage, PMM_SECTION_SEGMENT Segment, PVOID *BaseAddress, SIZE_T ViewSize, ULONG Protect, LONGLONG ViewOffset, ULONG AllocationType)
Definition: section.c:3340

Referenced by CcRosCreateVacb(), and MmMapViewInSystemSpace().

◆ MmMapViewOfArm3Section()

NTSTATUS NTAPI MmMapViewOfArm3Section ( IN PVOID  SectionObject,
IN PEPROCESS  Process,
IN OUT PVOID BaseAddress,
IN ULONG_PTR  ZeroBits,
IN SIZE_T  CommitSize,
IN OUT PLARGE_INTEGER SectionOffset  OPTIONAL,
IN OUT PSIZE_T  ViewSize,
IN SECTION_INHERIT  InheritDisposition,
IN ULONG  AllocationType,
IN ULONG  Protect 
)

Definition at line 2896 of file section.c.

2906{
2909 PSECTION Section;
2910 PCONTROL_AREA ControlArea;
2911 ULONG ProtectionMask;
2913 ULONG64 CalculatedViewSize;
2914 PAGED_CODE();
2915
2916 /* Get the segment and control area */
2917 Section = (PSECTION)SectionObject;
2918 ControlArea = Section->Segment->ControlArea;
2919
2920 /* These flags/states are not yet supported by ARM3 */
2921 ASSERT(Section->u.Flags.Image == 0);
2922 ASSERT(Section->u.Flags.NoCache == 0);
2923 ASSERT(Section->u.Flags.WriteCombined == 0);
2924 ASSERT(ControlArea->u.Flags.PhysicalMemory == 0);
2925
2926 /* FIXME */
2927 if ((AllocationType & MEM_RESERVE) != 0)
2928 {
2929 DPRINT1("MmMapViewOfArm3Section called with MEM_RESERVE, this is not implemented yet!!!\n");
2931 }
2932
2933 /* Check if the mapping protection is compatible with the create */
2935 {
2936 DPRINT1("Mapping protection is incompatible\n");
2938 }
2939
2940 /* Check if the offset and size would cause an overflow */
2941 if (((ULONG64)SectionOffset->QuadPart + *ViewSize) <
2942 (ULONG64)SectionOffset->QuadPart)
2943 {
2944 DPRINT1("Section offset overflows\n");
2946 }
2947
2948 /* Check if the offset and size are bigger than the section itself */
2949 if (((ULONG64)SectionOffset->QuadPart + *ViewSize) >
2950 (ULONG64)Section->SizeOfSection.QuadPart)
2951 {
2952 DPRINT1("Section offset is larger than section\n");
2954 }
2955
2956 /* Check if the caller did not specify a view size */
2957 if (!(*ViewSize))
2958 {
2959 /* Compute it for the caller */
2960 CalculatedViewSize = Section->SizeOfSection.QuadPart -
2961 SectionOffset->QuadPart;
2962
2963 /* Check if it's larger than 4GB or overflows into kernel-mode */
2964 if (!NT_SUCCESS(RtlULongLongToSIZET(CalculatedViewSize, ViewSize)) ||
2965 (((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)*BaseAddress) < CalculatedViewSize))
2966 {
2967 DPRINT1("Section view won't fit\n");
2969 }
2970 }
2971
2972 /* Check if the commit size is larger than the view size */
2973 if (CommitSize > *ViewSize)
2974 {
2975 DPRINT1("Attempting to commit more than the view itself\n");
2977 }
2978
2979 /* Check if the view size is larger than the section */
2980 if (*ViewSize > (ULONG64)Section->SizeOfSection.QuadPart)
2981 {
2982 DPRINT1("The view is larger than the section\n");
2984 }
2985
2986 /* Compute and validate the protection mask */
2987 ProtectionMask = MiMakeProtectionMask(Protect);
2988 if (ProtectionMask == MM_INVALID_PROTECTION)
2989 {
2990 DPRINT1("The protection is invalid\n");
2992 }
2993
2994 /* We only handle pagefile-backed sections, which cannot be writecombined */
2996 {
2997 DPRINT1("Cannot write combine a pagefile-backed section\n");
2999 }
3000
3001 /* Start by attaching to the current process if needed */
3003 {
3005 Attached = TRUE;
3006 }
3007
3008 /* Do the actual mapping */
3009 Status = MiMapViewOfDataSection(ControlArea,
3010 Process,
3013 ViewSize,
3014 Section,
3016 ProtectionMask,
3017 CommitSize,
3018 ZeroBits,
3020
3021 /* Detach if needed, then return status */
3023 return Status;
3024}
BOOLEAN NTAPI MiIsProtectionCompatible(IN ULONG SectionPageProtection, IN ULONG NewSectionPageProtection)
Definition: section.c:117
NTSTATUS NTAPI MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea, IN PEPROCESS Process, IN PVOID *BaseAddress, IN PLARGE_INTEGER SectionOffset, IN PSIZE_T ViewSize, IN PSECTION Section, IN SECTION_INHERIT InheritDisposition, IN ULONG ProtectionMask, IN SIZE_T CommitSize, IN ULONG_PTR ZeroBits, IN ULONG AllocationType)
Definition: section.c:1264
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT InheritDisposition
Definition: mmfuncs.h:409
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR ZeroBits
Definition: mmfuncs.h:405
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG AllocationType
Definition: mmfuncs.h:410
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:406
struct _SECTION * PSECTION
#define MEM_RESERVE
Definition: nt_native.h:1314
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:46
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1727
#define STATUS_SECTION_PROTECTION
Definition: ntstatus.h:314
#define STATUS_INVALID_PARAMETER_10
Definition: ntstatus.h:484
#define STATUS_INVALID_PARAMETER_5
Definition: ntstatus.h:479
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
ULONG WriteCombined
Definition: mmtypes.h:490
static BOOL Attached
Definition: vidbios.c:3905
KAPC_STATE
Definition: ketypes.h:1285

Referenced by MmMapViewOfSection().

◆ MmMapViewOfSection()

NTSTATUS NTAPI MmMapViewOfSection ( IN PVOID  SectionObject,
IN PEPROCESS  Process,
IN OUT PVOID BaseAddress,
IN ULONG_PTR  ZeroBits,
IN SIZE_T  CommitSize,
IN OUT PLARGE_INTEGER SectionOffset  OPTIONAL,
IN OUT PSIZE_T  ViewSize,
IN SECTION_INHERIT  InheritDisposition,
IN ULONG  AllocationType,
IN ULONG  Protect 
)

Definition at line 3968 of file section.c.

3978{
3979 PSECTION Section;
3982 BOOLEAN NotAtBase = FALSE;
3983
3985 {
3986 DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
3988 Process,
3990 ZeroBits,
3991 CommitSize,
3993 ViewSize,
3996 Protect);
3997 }
3998
3999 ASSERT(Process);
4000
4002 {
4004 }
4005
4006 /* FIXME: We should keep this, but it would break code checking equality */
4007 Protect &= ~PAGE_NOCACHE;
4008
4009 Section = SectionObject;
4010 AddressSpace = &Process->Vm;
4011
4012 if (Section->u.Flags.NoChange)
4014
4016
4017 if (Section->u.Flags.Image)
4018 {
4019 ULONG i;
4020 ULONG NrSegments;
4021 ULONG_PTR ImageBase;
4022 SIZE_T ImageSize;
4023 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
4024 PMM_SECTION_SEGMENT SectionSegments;
4025
4026 ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
4027 SectionSegments = ImageSectionObject->Segments;
4028 NrSegments = ImageSectionObject->NrSegments;
4029
4030 ASSERT(ImageSectionObject->RefCount > 0);
4031
4032 ImageBase = (ULONG_PTR)*BaseAddress;
4033 if (ImageBase == 0)
4034 {
4035 ImageBase = (ULONG_PTR)ImageSectionObject->BasedAddress;
4036 }
4037
4038 ImageSize = 0;
4039 for (i = 0; i < NrSegments; i++)
4040 {
4041 ULONG_PTR MaxExtent;
4042