ReactOS 0.4.16-dev-1401-gf1332c7
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_ PMEMORY_AREA MemoryArea, _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 MmPurgeSegment (_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length)
 
BOOLEAN NTAPI MmIsDataSectionResident (_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
 
NTSTATUS NTAPI MmMakeDataSectionResident (_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length, _In_ PLARGE_INTEGER ValidDataLength)
 
NTSTATUS NTAPI MmMakeSegmentDirty (_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
 
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 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 56 of file section.c.

◆ NDEBUG

#define NDEBUG

Definition at line 49 of file section.c.

Function Documentation

◆ _MmLockSectionSegment()

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

Definition at line 70 of file section.c.

71{
72 //DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line);
74 Segment->Locked = TRUE;
75}
#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 79 of file section.c.

80{
81 ASSERT(Segment->Locked);
82 Segment->Locked = FALSE;
84 //DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line);
85}
#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 988 of file section.c.

998{
999 /* Lock the PFN lock because we mess around with SectionObjectPointers */
1000 if (OldIrql == MM_NOIRQL)
1001 {
1002 OldIrql = MiAcquirePfnLock();
1003 }
1004
1005 if (InterlockedDecrement64(Segment->ReferenceCount) > 0)
1006 {
1007 /* Nothing to do yet */
1008 MiReleasePfnLock(OldIrql);
1009 return;
1010 }
1011
1012 *Segment->Flags |= MM_SEGMENT_INDELETE;
1013
1014 /* Flush the segment */
1015 if (*Segment->Flags & MM_DATAFILE_SEGMENT)
1016 {
1017 MiReleasePfnLock(OldIrql);
1018 /* Free the page table. This will flush any remaining dirty data */
1020
1021 OldIrql = MiAcquirePfnLock();
1022 /* Delete the pointer on the file */
1023 ASSERT(Segment->FileObject->SectionObjectPointer->DataSectionObject == Segment);
1024 Segment->FileObject->SectionObjectPointer->DataSectionObject = NULL;
1025 MiReleasePfnLock(OldIrql);
1026 ObDereferenceObject(Segment->FileObject);
1027
1029 }
1030 else
1031 {
1032 /* Most grotesque thing ever */
1033 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = CONTAINING_RECORD(Segment->ReferenceCount, MM_IMAGE_SECTION_OBJECT, RefCount);
1034 PMM_SECTION_SEGMENT SectionSegments;
1035 ULONG NrSegments;
1036 ULONG i;
1037
1038 /* Delete the pointer on the file */
1039 ASSERT(ImageSectionObject->FileObject->SectionObjectPointer->ImageSectionObject == ImageSectionObject);
1040 ImageSectionObject->FileObject->SectionObjectPointer->ImageSectionObject = NULL;
1041 MiReleasePfnLock(OldIrql);
1042
1043 ObDereferenceObject(ImageSectionObject->FileObject);
1044
1045 NrSegments = ImageSectionObject->NrSegments;
1046 SectionSegments = ImageSectionObject->Segments;
1047 for (i = 0; i < NrSegments; i++)
1048 {
1049 if (SectionSegments[i].Image.Characteristics & IMAGE_SCN_MEM_SHARED)
1050 {
1051 MmpFreePageFileSegment(&SectionSegments[i]);
1052 }
1053
1054 MmFreePageTablesSectionSegment(&SectionSegments[i], NULL);
1055 }
1056
1058 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
1059 }
1060}
#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:159
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
VOID NTAPI MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage)
Definition: sptab.c:321
#define IMAGE_SCN_MEM_SHARED
Definition: ntimage.h:238
#define MM_NOIRQL
Definition: mm.h:70
#define MM_SEGMENT_INDELETE
Definition: mm.h:244
#define MM_DATAFILE_SEGMENT
Definition: mm.h:243
static VOID NTAPI FreeSegmentPage(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
Definition: section.c:960
VOID NTAPI MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:917
PMM_SECTION_SEGMENT Segments
Definition: mm.h:239
PFILE_OBJECT FileObject
Definition: mm.h:231
#define TAG_MM_SECTION_SEGMENT
Definition: tag.h:113
#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:778
#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 2601 of file section.c.

2602{
2603 SIZE_T SizeOfSegments;
2604 PMM_SECTION_SEGMENT Segments;
2605
2606 /* TODO: check for integer overflow */
2607 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * NrSegments;
2608
2610 SizeOfSegments,
2612
2613 if(Segments)
2614 RtlZeroMemory(Segments, SizeOfSegments);
2615
2616 return Segments;
2617}
#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 3035 of file section.c.

3037{
3039 PVOID FileHeader;
3040 PVOID FileHeaderBuffer;
3041 ULONG FileHeaderSize;
3042 ULONG Flags;
3043 ULONG OldNrSegments;
3045 ULONG i;
3046
3047 /*
3048 * Read the beginning of the file (2 pages). Should be enough to contain
3049 * all (or most) of the headers
3050 */
3051 Offset.QuadPart = 0;
3052
3054 &Offset,
3055 PAGE_SIZE * 2,
3056 &FileHeader,
3057 &FileHeaderBuffer,
3058 &FileHeaderSize);
3059
3060 if (!NT_SUCCESS(Status))
3061 return Status;
3062
3063 if (FileHeaderSize == 0)
3064 {
3065 ExFreePool(FileHeaderBuffer);
3066 return STATUS_UNSUCCESSFUL;
3067 }
3068
3069 /*
3070 * Look for a loader that can handle this executable
3071 */
3072 for (i = 0; i < RTL_NUMBER_OF(ExeFmtpLoaders); ++ i)
3073 {
3074 Flags = 0;
3075
3076 Status = ExeFmtpLoaders[i](FileHeader,
3077 FileHeaderSize,
3078 FileObject,
3079 ImageSectionObject,
3080 &Flags,
3083
3084 if (!NT_SUCCESS(Status))
3085 {
3086 if (ImageSectionObject->Segments)
3087 {
3088 ExFreePool(ImageSectionObject->Segments);
3089 ImageSectionObject->Segments = NULL;
3090 }
3091 }
3092
3094 break;
3095 }
3096
3097 ExFreePoolWithTag(FileHeaderBuffer, 'rXmM');
3098
3099 /*
3100 * No loader handled the format
3101 */
3103 {
3106 }
3107
3108 if (!NT_SUCCESS(Status))
3109 return Status;
3110
3111 ASSERT(ImageSectionObject->Segments != NULL);
3112 ASSERT(ImageSectionObject->RefCount > 0);
3113
3114 /*
3115 * Some defaults
3116 */
3117 /* FIXME? are these values platform-dependent? */
3118 if (ImageSectionObject->ImageInformation.MaximumStackSize == 0)
3119 ImageSectionObject->ImageInformation.MaximumStackSize = 0x40000;
3120
3121 if(ImageSectionObject->ImageInformation.CommittedStackSize == 0)
3122 ImageSectionObject->ImageInformation.CommittedStackSize = 0x1000;
3123
3124 if(ImageSectionObject->BasedAddress == NULL)
3125 {
3126 if(ImageSectionObject->ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL)
3127 ImageSectionObject->BasedAddress = (PVOID)0x10000000;
3128 else
3129 ImageSectionObject->BasedAddress = (PVOID)0x00400000;
3130 }
3131
3132 /*
3133 * And now the fun part: fixing the segments
3134 */
3135
3136 /* Sort them by virtual address */
3137 MmspSortSegments(ImageSectionObject, Flags);
3138
3139 /* Ensure they don't overlap in memory */
3140 if (!MmspCheckSegmentBounds(ImageSectionObject, Flags))
3142
3143 /* Ensure they are aligned */
3144 OldNrSegments = ImageSectionObject->NrSegments;
3145
3146 if (!MmspPageAlignSegments(ImageSectionObject, Flags))
3148
3149 /* Trim them if the alignment phase merged some of them */
3150 if (ImageSectionObject->NrSegments < OldNrSegments)
3151 {
3152 PMM_SECTION_SEGMENT Segments;
3153 SIZE_T SizeOfSegments;
3154
3155 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
3156
3158 SizeOfSegments,
3160
3161 if (Segments == NULL)
3163
3164 RtlCopyMemory(Segments, ImageSectionObject->Segments, SizeOfSegments);
3165 ExFreePool(ImageSectionObject->Segments);
3166 ImageSectionObject->Segments = Segments;
3167 }
3168
3169 /* And finish their initialization */
3170 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
3171 {
3172 ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock);
3173 ImageSectionObject->Segments[i].ReferenceCount = &ImageSectionObject->RefCount;
3174 ImageSectionObject->Segments[i].Flags = &ImageSectionObject->SegFlags;
3175 MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]);
3176 ImageSectionObject->Segments[i].FileObject = FileObject;
3177 }
3178
3179 ASSERT(ImageSectionObject->RefCount > 0);
3180
3181 ImageSectionObject->FileObject = FileObject;
3182
3184 return Status;
3185}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#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:2601
static BOOLEAN NTAPI MmspPageAlignSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2852
static BOOLEAN NTAPI MmspCheckSegmentBounds(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2801
static VOID NTAPI MmspSortSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2775
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:2621
static PEXEFMT_LOADER ExeFmtpLoaders[]
Definition: section.c:2590
PLARGE_INTEGER Offset
Definition: section.c:5177
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 2621 of file section.c.

2627{
2630 ULONG AdjustOffset;
2631 ULONG OffsetAdjustment;
2633 ULONG UsedSize;
2634 PVOID Buffer;
2637
2639
2640 if(Length == 0)
2641 {
2642 KeBugCheck(MEMORY_MANAGEMENT);
2643 }
2644
2645 FileOffset = *Offset;
2646
2647 /* Negative/special offset: it cannot be used in this context */
2648 if(FileOffset.u.HighPart < 0)
2649 {
2650 KeBugCheck(MEMORY_MANAGEMENT);
2651 }
2652
2653 AdjustOffset = PAGE_ROUND_DOWN(FileOffset.u.LowPart);
2654 OffsetAdjustment = FileOffset.u.LowPart - AdjustOffset;
2655 FileOffset.u.LowPart = AdjustOffset;
2656
2657 BufferSize = Length + OffsetAdjustment;
2659
2660 /*
2661 * It's ok to use paged pool, because this is a temporary buffer only used in
2662 * the loading of executables. The assumption is that MmCreateSection is
2663 * always called at low IRQLs and that these buffers don't survive a brief
2664 * initialization phase
2665 */
2667 if (!Buffer)
2668 {
2670 }
2671
2673
2674 UsedSize = (ULONG)Iosb.Information;
2675
2676 if(NT_SUCCESS(Status) && UsedSize < OffsetAdjustment)
2677 {
2680 }
2681
2682 if(NT_SUCCESS(Status))
2683 {
2684 *Data = (PVOID)((ULONG_PTR)Buffer + OffsetAdjustment);
2685 *AllocBase = Buffer;
2686 *ReadSize = UsedSize - OffsetAdjustment;
2687 }
2688 else
2689 {
2690 ExFreePoolWithTag(Buffer, 'rXmM');
2691 }
2692
2693 return Status;
2694}
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1434
_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:4403
#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 960 of file section.c.

961{
964
966
968
970
971 /* This must be either a valid entry or nothing */
973
974 /* There should be no reference anymore */
976
978 /* If there is a page, this must be because it's still dirty */
979 ASSERT(Page != 0);
980
981 /* Write the page */
982 if (IS_DIRTY_SSE(Entry))
983 MiWritePage(Segment, Offset->QuadPart, Page);
984
986}
ULONG_PTR PFN_NUMBER
#define MmGetPageEntrySectionSegment(S, O)
Definition: mm.h:1600
#define MmLockSectionSegment(x)
Definition: mm.h:1395
#define SHARE_COUNT_FROM_SSE(E)
Definition: mm.h:1383
#define MC_USER
Definition: mm.h:112
#define MmUnlockSectionSegment(x)
Definition: mm.h:1403
#define IS_DIRTY_SSE(E)
Definition: mm.h:1375
#define PFN_FROM_SSE(E)
Definition: mm.h:1366
#define IS_SWAP_FROM_SSE(E)
Definition: mm.h:1367
NTSTATUS NTAPI MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
Definition: balance.c:72
PFN_NUMBER Page
Definition: section.c:5183
NTSTATUS NTAPI MiWritePage(PMM_SECTION_SEGMENT Segment, LONGLONG SegOffset, PFN_NUMBER Page)
Definition: section.c:238
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 5328 of file section.c.

5329 {
5330 ULONG_PTR NewEntry = 0;
5331 /* Restore the swap entry here */
5332 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5333 {
5335 if (SwapEntry)
5336 NewEntry = MAKE_SWAP_SSE(SwapEntry);
5337 }
5338
5339 /* Yes. Release it */
5342 /* Tell the caller we released the page */
5343 return TRUE;
5344 }
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define MAKE_SWAP_SSE(S)
Definition: mm.h:1372
ULONG_PTR SWAPENTRY
Definition: mm.h:57
SWAPENTRY NTAPI MmGetSavedSwapEntryPage(PFN_NUMBER Page)
Definition: freelist.c:500
#define MmSetPageEntrySectionSegment(S, O, E)
Definition: section.c:56

◆ if() [2/2]

if ( Entry  = = 0)

Definition at line 5192 of file section.c.

5197 {
5198 BOOLEAN DirtyAgain;
5199
5200 /*
5201 * We got a dirty entry. This path is for the shared data,
5202 * be-it regular file maps or shared sections of DLLs
5203 */
5205 FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5206
5207 /* Insert the cleaned entry back. Mark it as write in progress, and clear the dirty bit. */
5211
5213
5214 if (FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5215 {
5217 KIRQL OldIrql;
5218
5219 /* We have to write it back to the file. Tell the FS driver who we are */
5220 if (PageOut)
5221 {
5222 LARGE_INTEGER EndOffset = *Offset;
5223
5225
5226 /* We need to disable all APCs */
5228
5229 EndOffset.QuadPart += PAGE_SIZE;
5231 &EndOffset,
5233 if (NT_SUCCESS(Status))
5234 {
5236 }
5237 else
5238 {
5239 /* Make sure we will not try to release anything */
5241 }
5242 }
5243 else
5244 {
5245 /* We don't have to lock. Say this is success */
5247 }
5248
5249 /* Go ahead and write the page, if previous locking succeeded */
5250 if (NT_SUCCESS(Status))
5251 {
5252 DPRINT("Writing page at offset %I64d for file %wZ, Pageout: %s\n",
5253 Offset->QuadPart, &Segment->FileObject->FileName, PageOut ? "TRUE" : "FALSE");
5254 Status = MiWritePage(Segment, Offset->QuadPart, Page);
5255 }
5256
5257 if (PageOut)
5258 {
5260 if (ResourceToRelease != NULL)
5261 {
5263 }
5265 }
5266 }
5267 else
5268 {
5269 /* This must only be called by the page-out path */
5270 ASSERT(PageOut);
5271
5272 /* And this must be for a shared section in a DLL */
5273 ASSERT(FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5274
5276 if (!SwapEntry)
5277 {
5278 SwapEntry = MmAllocSwapPage();
5279 }
5280
5281 if (SwapEntry)
5282 {
5283 Status = MmWriteToSwapPage(SwapEntry, Page);
5284 if (NT_SUCCESS(Status))
5285 {
5286 MmSetSavedSwapEntryPage(Page, SwapEntry);
5287 }
5288 else
5289 {
5290 MmFreeSwapPage(SwapEntry);
5291 }
5292 }
5293 else
5294 {
5295 DPRINT1("Failed to allocate a swap page!\n");
5297 }
5298 }
5299
5301
5302 /* Get the entry again */
5305
5306 if (!NT_SUCCESS(Status))
5307 {
5308 /* Damn, this failed. Consider this page as still dirty */
5309 DPRINT1("MiWritePage FAILED: Status 0x%08x!\n", Status);
5310 DirtyAgain = TRUE;
5311 }
5312 else
5313 {
5314 /* Check if someone dirtified this page while we were not looking */
5315 DirtyAgain = IS_DIRTY_SSE(Entry);
5316 }
5317
5318 /* Drop the reference we got, deleting the write altogether. */
5320 if (DirtyAgain)
5321 {
5323 }
5325 }
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:1858
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:1965
#define DIRTY_SSE(E)
Definition: mm.h:1373
#define MAKE_SSE(P, C)
Definition: mm.h:1385
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:1381
VOID NTAPI MmFreeSwapPage(SWAPENTRY Entry)
Definition: pagefile.c:291
VOID NTAPI MmSetSavedSwapEntryPage(PFN_NUMBER Page, SWAPENTRY SavedSwapEntry)
Definition: freelist.c:484
#define WRITE_SSE(E)
Definition: mm.h:1376
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:5180
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
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 120 of file section.c.

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

Referenced by MiRosUnmapViewOfSection().

◆ MiCopyFromUserPage()

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

Definition at line 1170 of file section.c.

1171{
1173 KIRQL Irql;
1174 PVOID DestAddress;
1175
1177 DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
1178 if (DestAddress == NULL)
1179 {
1180 return STATUS_NO_MEMORY;
1181 }
1182 ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
1183 ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
1184 RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
1185 MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
1186 return STATUS_SUCCESS;
1187}
_Out_ PKIRQL Irql
Definition: csq.h:179
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
_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 PsGetCurrentProcess
Definition: psfuncs.h:17

Referenced by MmAccessFaultSectionView().

◆ MiGrabDataSection()

static PMM_SECTION_SEGMENT MiGrabDataSection ( PSECTION_OBJECT_POINTERS  SectionObjectPointer)
static

Definition at line 90 of file section.c.

91{
92 KIRQL OldIrql = MiAcquirePfnLock();
94
95 while (TRUE)
96 {
97 Segment = SectionObjectPointer->DataSectionObject;
98 if (!Segment)
99 break;
100
102 {
103 MiReleasePfnLock(OldIrql);
105 OldIrql = MiAcquirePfnLock();
106 continue;
107 }
108
111 break;
112 }
113
114 MiReleasePfnLock(OldIrql);
115
116 return Segment;
117}
#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:38
#define MM_SEGMENT_INCREATE
Definition: mm.h:245
static LARGE_INTEGER TinyTime
Definition: section.c:63

Referenced by MmCanFileBeTruncated(), MmFlushSegment(), MmIsDataSectionResident(), MmMakeDataSectionResident(), MmMakeSegmentDirty(), 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 4342 of file section.c.

4343{
4345
4347
4348 /* Loop over all entries */
4349 for (PageTable = RtlEnumerateGenericTable(&Segment->PageTable, TRUE);
4350 PageTable != NULL;
4352 {
4353 for (ULONG i = 0; i < _countof(PageTable->PageEntries); i++)
4354 {
4355 ULONG_PTR Entry = PageTable->PageEntries[i];
4357
4358 if (!Entry)
4359 continue;
4360
4362 {
4363 /* I/O ongoing or swap entry. Someone mapped this file as we were not looking */
4365 return FALSE;
4366 }
4367
4368 /* Regular entry */
4371
4372 /* Properly remove using the used API */
4373 Offset.QuadPart = PageTable->FileOffset.QuadPart + (i << PAGE_SHIFT);
4376 }
4377 }
4378
4380
4381 return TRUE;
4382}
#define IS_WRITE_SSE(E)
Definition: mm.h:1377
#define _countof(array)
Definition: sndvol32.h:70
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 4589 of file section.c.

4590{
4591 DPRINT("MmUnmapViewInSystemSpace() called\n");
4592
4594}
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1729
static NTSTATUS MmUnmapViewOfSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
Definition: section.c:3543
_Must_inspect_result_ _Outptr_result_bytebuffer_ ViewSize PVOID * MappedBase
Definition: mmfuncs.h:492

Referenced by MmUnmapViewInSystemSpace().

◆ MiRosUnmapViewOfSection()

NTSTATUS NTAPI MiRosUnmapViewOfSection ( _In_ PEPROCESS  Process,
_In_ PMEMORY_AREA  MemoryArea,
_In_ PVOID  BaseAddress,
_In_ BOOLEAN  SkipDebuggerNotify 
)

Definition at line 3607 of file section.c.

3612{
3615 PVOID ImageBaseAddress = 0;
3616
3617 DPRINT("Opening memory area Process %p BaseAddress %p\n",
3619
3620 ASSERT(Process);
3622
3623 AddressSpace = &Process->Vm;
3624
3625 if (MemoryArea == NULL ||
3626#ifdef NEWCC
3627 ((MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) && (MemoryArea->Type != MEMORY_AREA_CACHE)) ||
3628#else
3630#endif
3632
3633 {
3635
3636 DPRINT1("Unable to find memory area at address %p.\n", BaseAddress);
3638 }
3639
3641 {
3642 ULONG i;
3643 ULONG NrSegments;
3644 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3645 PMM_SECTION_SEGMENT SectionSegments;
3647
3648 Segment = MemoryArea->SectionData.Segment;
3649 ImageSectionObject = ImageSectionObjectFromSegment(Segment);
3650 SectionSegments = ImageSectionObject->Segments;
3651 NrSegments = ImageSectionObject->NrSegments;
3652
3654
3655 /* Search for the current segment within the section segments
3656 * and calculate the image base address */
3657 for (i = 0; i < NrSegments; i++)
3658 {
3659 if (Segment == &SectionSegments[i])
3660 {
3661 ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
3662 break;
3663 }
3664 }
3665 if (i >= NrSegments)
3666 {
3667 KeBugCheck(MEMORY_MANAGEMENT);
3668 }
3669
3670 for (i = 0; i < NrSegments; i++)
3671 {
3672 PVOID SBaseAddress = (PVOID)
3673 ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
3674
3675 Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
3676 if (!NT_SUCCESS(Status))
3677 {
3678 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3679 SBaseAddress, Process, Status);
3681 }
3682 }
3683 DPRINT("One mapping less for %p\n", ImageSectionObject->FileObject->SectionObjectPointer);
3684 InterlockedDecrement(&ImageSectionObject->MapCount);
3685 }
3686 else
3687 {
3689 PMMVAD Vad = &MemoryArea->VadNode;
3690 PCONTROL_AREA ControlArea = Vad->ControlArea;
3693 LARGE_INTEGER ViewOffset;
3694 ViewOffset.QuadPart = MemoryArea->SectionData.ViewOffset;
3695
3696 InterlockedIncrement64(Segment->ReferenceCount);
3697
3698 ViewSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
3699
3701 if (!NT_SUCCESS(Status))
3702 {
3703 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3706 }
3707
3708 /* These might be deleted now */
3709 Vad = NULL;
3710 MemoryArea = NULL;
3711
3713 {
3714 /* Don't bother */
3715 MmDereferenceSegment(Segment);
3716 return STATUS_SUCCESS;
3717 }
3719
3720 FileObject = Segment->FileObject;
3722
3723 /* Don't bother for auto-delete closed file. */
3725 {
3727 MmDereferenceSegment(Segment);
3728 return STATUS_SUCCESS;
3729 }
3730
3731 /*
3732 * Flush only when last mapping is deleted.
3733 * FIXME: Why ControlArea == NULL? Or rather: is ControlArea ever not NULL here?
3734 */
3735 if (ControlArea == NULL || ControlArea->NumberOfMappedViews == 1)
3736 {
3737 while (ViewSize > 0)
3738 {
3739 ULONG FlushSize = min(ViewSize, PAGE_ROUND_DOWN(MAXULONG));
3740 MmFlushSegment(FileObject->SectionObjectPointer,
3741 &ViewOffset,
3742 FlushSize,
3743 NULL);
3744 ViewSize -= FlushSize;
3745 ViewOffset.QuadPart += FlushSize;
3746 }
3747 }
3748
3750 MmDereferenceSegment(Segment);
3751 }
3752
3753 /* Notify debugger */
3754 if (ImageBaseAddress && !SkipDebuggerNotify) DbgkUnMapViewOfSection(ImageBaseAddress);
3755
3756 return STATUS_SUCCESS;
3757}
#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:206
_In_ PMEMORY_AREA MemoryArea
Definition: newmm.h:207
VOID NTAPI FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1665
VOID NTAPI FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1640
#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:242
#define STATUS_NOT_MAPPED_VIEW
Definition: ntstatus.h:262
PMM_IMAGE_SECTION_OBJECT ImageSectionObjectFromSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:120
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:5094
struct _MEMORY_AREA::@1926 SectionData
BOOLEAN DeleteInProgress
Definition: mm.h:258
ULONG Type
Definition: mm.h:256
MMVAD VadNode
Definition: mm.h:254
ULONG_PTR VadType
Definition: mmtypes.h:694
ULONG_PTR EndingVpn
Definition: mmtypes.h:730
union _MMVAD::@2797 u
PCONTROL_AREA ControlArea
Definition: mmtypes.h:736
ULONG_PTR StartingVpn
Definition: mmtypes.h:729
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:734
struct _MM_SECTION_SEGMENT::@1925 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 238 of file section.c.

248{
252 UCHAR MdlBase[sizeof(MDL) + sizeof(PFN_NUMBER)];
253 PMDL Mdl = (PMDL)MdlBase;
254 PFILE_OBJECT FileObject = Segment->FileObject;
256
257 FileOffset.QuadPart = Segment->Image.FileOffset + SegOffset;
258
259 RtlZeroMemory(MdlBase, sizeof(MdlBase));
262 Mdl->MdlFlags |= MDL_PAGES_LOCKED;
263
266 if (Status == STATUS_PENDING)
267 {
269 Status = IoStatus.Status;
270 }
271 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
272 {
273 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
274 }
275
276 return Status;
277}
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#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
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:415
#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 1915 of file section.c.

1919{
1921 PFN_NUMBER OldPage;
1922 PFN_NUMBER NewPage;
1923 PFN_NUMBER UnmappedPage;
1924 PVOID PAddress;
1929 BOOLEAN Cow = FALSE;
1931 BOOLEAN Unmapped;
1933
1934 DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
1935
1936 /* Get the region for this address */
1938 &MemoryArea->SectionData.RegionListHead,
1939 Address, NULL);
1940 ASSERT(Region != NULL);
1941 if (!(Region->Protect & PAGE_IS_WRITABLE))
1943
1944 /* Make sure we have a page mapping for this address. */
1946 {
1948 if (!NT_SUCCESS(Status))
1949 {
1950 /* This is invalid access ! */
1951 return Status;
1952 }
1953 }
1954
1955 /*
1956 * Check if the page has already been set readwrite
1957 */
1959 {
1960 DPRINT("Address 0x%p\n", Address);
1961 return STATUS_SUCCESS;
1962 }
1963
1964 /* Check if we are doing Copy-On-Write */
1965 Segment = MemoryArea->SectionData.Segment;
1966 Cow = Segment->WriteCopy || (Region->Protect & PAGE_IS_WRITECOPY);
1967
1968 if (!Cow)
1969 {
1970 /* Simply update page protection and we're done */
1972 return STATUS_SUCCESS;
1973 }
1974
1975 /* Calculate the new protection & check if we should update the region */
1976 NewProtect = Region->Protect;
1978 {
1979 NewProtect &= ~PAGE_IS_WRITECOPY;
1980 if (Region->Protect & PAGE_IS_EXECUTABLE)
1982 else
1985 &MemoryArea->SectionData.RegionListHead,
1988 }
1989
1990 /*
1991 * Find the offset of the page
1992 */
1993 PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
1994 Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
1995 + MemoryArea->SectionData.ViewOffset;
1996
1997 /* Get the page mapping this section offset. */
2000
2001 /* Get the current page mapping for the process */
2002 ASSERT(MmIsPagePresent(Process, PAddress));
2003 OldPage = MmGetPfnForProcess(Process, PAddress);
2004 ASSERT(OldPage != 0);
2005
2006 if (IS_SWAP_FROM_SSE(Entry) ||
2007 PFN_FROM_SSE(Entry) != OldPage)
2008 {
2010 /* This is a private page. We must only change the page protection. */
2012 return STATUS_SUCCESS;
2013 }
2014
2015 /*
2016 * Allocate a page
2017 */
2019 if (!NT_SUCCESS(Status))
2020 {
2022 return STATUS_NO_MEMORY;
2023 }
2024
2025 /*
2026 * Copy the old page
2027 */
2028 NT_VERIFY(NT_SUCCESS(MiCopyFromUserPage(NewPage, PAddress)));
2029
2030 /*
2031 * Unshare the old page.
2032 */
2033 DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
2034 Unmapped = MmDeleteVirtualMapping(Process, PAddress, NULL, &UnmappedPage);
2035 if (!Unmapped || (UnmappedPage != OldPage))
2036 {
2037 /* Uh , we had a page just before, but suddenly it changes. Someone corrupted us. */
2038 KeBugCheckEx(MEMORY_MANAGEMENT,
2040 (ULONG_PTR)PAddress,
2041 (ULONG_PTR)__FILE__,
2042 __LINE__);
2043 }
2044
2045 if (Process)
2046 MmDeleteRmap(OldPage, Process, PAddress);
2049
2050 /*
2051 * Set the PTE to point to the new page
2052 */
2053 if (!NT_SUCCESS(MmCreateVirtualMapping(Process, PAddress, NewProtect, NewPage)))
2054 {
2055 DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
2056 KeBugCheck(MEMORY_MANAGEMENT);
2057 }
2058
2059 if (Process)
2060 MmInsertRmap(NewPage, Process, PAddress);
2061
2062 DPRINT("Address 0x%p\n", Address);
2063 return STATUS_SUCCESS;
2064}
_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:249
#define PAGE_IS_WRITABLE
Definition: mm.h:158
FORCEINLINE PEPROCESS MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
Definition: mm.h:1714
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:164
NTSTATUS NTAPI MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN MyWait, PPFN_NUMBER AllocatedPage)
Definition: balance.c:313
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:129
VOID NTAPI MmInsertRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
#define PAGE_IS_WRITECOPY
Definition: mm.h:170
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:1537
BOOLEAN NTAPI MmUnsharePageEntrySectionSegment(PMEMORY_AREA MemoryArea, PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, BOOLEAN Dirty, BOOLEAN PageOut, ULONG_PTR *InEntry)
Definition: section.c:1089
static NTSTATUS MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
Definition: section.c:1170
static VOID MmAlterViewAttributes(PMMSUPPORT AddressSpace, PVOID BaseAddress, SIZE_T RegionSize, ULONG OldType, ULONG OldProtect, ULONG NewType, ULONG NewProtect)
Definition: section.c:1446
Definition: mm.h:481
_Must_inspect_result_ _In_ ULONG NewProtect
Definition: mmfuncs.h:682
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304

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 1446 of file section.c.

1453{
1456 BOOLEAN DoCOW = FALSE;
1457 ULONG i;
1459
1462 Segment = MemoryArea->SectionData.Segment;
1464
1465 if ((Segment->WriteCopy) &&
1467 {
1468 DoCOW = TRUE;
1469 }
1470
1471 if (OldProtect != NewProtect)
1472 {
1473 for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
1474 {
1475 SWAPENTRY SwapEntry;
1476 PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
1478
1479 /* Wait for a wait entry to disappear */
1480 do
1481 {
1482 MmGetPageFileMapping(Process, Address, &SwapEntry);
1483 if (SwapEntry != MM_WAIT_ENTRY)
1484 break;
1490 }
1491 while (TRUE);
1492
1493 /*
1494 * If we doing COW for this segment then check if the page is
1495 * already private.
1496 */
1498 {
1502
1504 + MemoryArea->SectionData.ViewOffset;
1506 /*
1507 * An MM_WAIT_ENTRY is ok in this case... It'll just count as
1508 * IS_SWAP_FROM_SSE and we'll do the right thing.
1509 */
1511
1512 /* Choose protection based on what was requested */
1515 else
1517
1519 {
1521 }
1522 }
1523
1525 {
1527 Protect);
1528 }
1529 }
1530 }
1531
1533}
#define PAGE_READONLY
Definition: compat.h:138
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
#define PAGE_EXECUTE_READ
Definition: nt_native.h:1307
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1694
VOID NTAPI MmGetPageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY *SwapEntry)
Definition: page.c:299
BOOLEAN NTAPI MmIsDisabledPage(struct _EPROCESS *Process, PVOID Address)
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:61
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1707
_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().

◆ MmCanFileBeTruncated()

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

Definition at line 4287 of file section.c.

4290{
4291 BOOLEAN Ret;
4293
4294 /* Check whether an ImageSectionObject exists */
4295 if (SectionObjectPointer->ImageSectionObject != NULL)
4296 {
4297 DPRINT1("ERROR: File can't be truncated because it has an image section\n");
4298 return FALSE;
4299 }
4300
4302 if (!Segment)
4303 {
4304 /* There is no data section. It's fine to do anything. */
4305 return TRUE;
4306 }
4307
4309 if ((Segment->SectionCount == 0) ||
4310 ((Segment->SectionCount == 1) && (SectionObjectPointer->SharedCacheMap != NULL)))
4311 {
4312 /* If the cache is the only one holding a reference to the segment, then it's fine to resize */
4313 Ret = TRUE;
4314 }
4315 else if (NewFileSize != NULL)
4316 {
4317 /* We can't shrink, but we can extend */
4318 Ret = NewFileSize->QuadPart >= Segment->RawLength.QuadPart;
4319#if DBG
4320 if (!Ret)
4321 {
4322 DPRINT1("Cannot truncate data: New Size %I64d, Segment Size %I64d\n", NewFileSize->QuadPart, Segment->RawLength.QuadPart);
4323 }
4324#endif
4325 }
4326 else
4327 {
4328 DPRINT1("ERROR: File can't be truncated because it has references held to its data section\n");
4329 Ret = FALSE;
4330 }
4331
4333 MmDereferenceSegment(Segment);
4334
4335 DPRINT("FIXME: didn't check for outstanding write probes\n");
4336
4337 return Ret;
4338}
static PMM_SECTION_SEGMENT MiGrabDataSection(PSECTION_OBJECT_POINTERS SectionObjectPointer)
Definition: section.c:90
_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 2102 of file section.c.

2110{
2111 SECTION Section;
2112 PSECTION NewSection;
2113 PSUBSECTION Subsection;
2114 PSEGMENT NewSegment, Segment;
2116 PCONTROL_AREA ControlArea;
2117 ULONG ProtectionMask, ControlAreaSize, Size, NonPagedCharge, PagedCharge;
2119 BOOLEAN FileLock = FALSE, KernelCall = FALSE;
2120 KIRQL OldIrql;
2122 BOOLEAN UserRefIncremented = FALSE;
2123 PVOID PreviousSectionPointer;
2124
2125 /* Make the same sanity checks that the Nt interface should've validated */
2128 SEC_NO_CHANGE)) == 0);
2138
2139 /* Convert section flag to page flag */
2142
2143 /* Check to make sure the protection is correct. Nt* does this already */
2145 if (ProtectionMask == MM_INVALID_PROTECTION)
2146 {
2147 DPRINT1("Invalid protection mask\n");
2149 }
2150
2151 /* Check if this is going to be a data or image backed file section */
2152 if ((FileHandle) || (FileObject))
2153 {
2154 /* These cannot be mapped with large pages */
2156
2157 /* For now, only support the mechanism through a file handle */
2159
2160 /* Reference the file handle to get the object */
2162 MmMakeFileAccess[ProtectionMask],
2165 (PVOID*)&File,
2166 NULL);
2167 if (!NT_SUCCESS(Status)) return Status;
2168
2169 /* Make sure Cc has been doing its job */
2170 if (!File->SectionObjectPointer)
2171 {
2172 /* This is not a valid file system-based file, fail */
2175 }
2176
2177 /* Image-file backed sections are not yet supported */
2179
2180 /* Compute the size of the control area, and allocate it */
2181 ControlAreaSize = sizeof(CONTROL_AREA) + sizeof(MSUBSECTION);
2182 ControlArea = ExAllocatePoolWithTag(NonPagedPool, ControlAreaSize, 'aCmM');
2183 if (!ControlArea)
2184 {
2187 }
2188
2189 /* Zero it out */
2190 RtlZeroMemory(ControlArea, ControlAreaSize);
2191
2192 /* Did we get a handle, or an object? */
2193 if (FileHandle)
2194 {
2195 /* We got a file handle so we have to lock down the file */
2196#if 0
2198 if (!NT_SUCCESS(Status))
2199 {
2200 ExFreePool(ControlArea);
2202 return Status;
2203 }
2204#else
2205 /* ReactOS doesn't support this API yet, so do nothing */
2208#endif
2209 /* Update the top-level IRP so that drivers know what's happening */
2211 FileLock = TRUE;
2212 }
2213
2214 /* Lock the PFN database while we play with the section pointers */
2215 OldIrql = MiAcquirePfnLock();
2216
2217 /* Image-file backed sections are not yet supported */
2219
2220 /* There should not already be a control area for this file */
2221 ASSERT(File->SectionObjectPointer->DataSectionObject == NULL);
2222 NewSegment = NULL;
2223
2224 /* Write down that this CA is being created, and set it */
2225 ControlArea->u.Flags.BeingCreated = TRUE;
2227 PreviousSectionPointer = File->SectionObjectPointer;
2228 File->SectionObjectPointer->DataSectionObject = ControlArea;
2229
2230 /* We can release the PFN lock now */
2231 MiReleasePfnLock(OldIrql);
2232
2233 /* We don't support previously-mapped file */
2234 ASSERT(NewSegment == NULL);
2235
2236 /* Image-file backed sections are not yet supported */
2238
2239 /* So we always create a data file map */
2241 &Segment,
2242 InputMaximumSize,
2245 KernelCall);
2246 if (!NT_SUCCESS(Status))
2247 {
2248 /* Lock the PFN database while we play with the section pointers */
2249 OldIrql = MiAcquirePfnLock();
2250
2251 /* Reset the waiting-for-deletion event */
2252 ASSERT(ControlArea->WaitingForDeletion == NULL);
2253 ControlArea->WaitingForDeletion = NULL;
2254
2255 /* Set the file pointer NULL flag */
2256 ASSERT(ControlArea->u.Flags.FilePointerNull == 0);
2257 ControlArea->u.Flags.FilePointerNull = TRUE;
2258
2259 /* Delete the data section object */
2261 File->SectionObjectPointer->DataSectionObject = NULL;
2262
2263 /* No longer being created */
2264 ControlArea->u.Flags.BeingCreated = FALSE;
2265
2266 /* We can release the PFN lock now */
2267 MiReleasePfnLock(OldIrql);
2268
2269 /* Check if we locked and set the IRP */
2270 if (FileLock)
2271 {
2272 /* Undo */
2274 //FsRtlReleaseFile(File);
2275 }
2276
2277 /* Free the control area and de-ref the file object */
2278 ExFreePool(ControlArea);
2280
2281 /* All done */
2282 return Status;
2283 }
2284
2285 /* On success, we expect this */
2286 ASSERT(PreviousSectionPointer == File->SectionObjectPointer);
2287
2288 /* Check if a maximum size was specified */
2289 if (!InputMaximumSize->QuadPart)
2290 {
2291 /* Nope, use the segment size */
2292 Section.SizeOfSection.QuadPart = (LONGLONG)Segment->SizeOfSegment;
2293 }
2294 else
2295 {
2296 /* Yep, use the entered size */
2297 Section.SizeOfSection.QuadPart = InputMaximumSize->QuadPart;
2298 }
2299 }
2300 else
2301 {
2302 /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
2304
2305 /* Not yet supported */
2307
2308 /* So this must be a pagefile-backed section, create the mappings needed */
2309 Status = MiCreatePagingFileMap(&NewSegment,
2310 InputMaximumSize->QuadPart,
2311 ProtectionMask,
2313 if (!NT_SUCCESS(Status)) return Status;
2314
2315 /* Set the size here, and read the control area */
2316 Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
2317 ControlArea = NewSegment->ControlArea;
2318
2319 /* MiCreatePagingFileMap increments user references */
2320 UserRefIncremented = TRUE;
2321 }
2322
2323 /* Did we already have a segment? */
2324 if (!NewSegment)
2325 {
2326 /* This must be the file path and we created a segment */
2327 NewSegment = Segment;
2328 ASSERT(File != NULL);
2329
2330 /* Acquire the PFN lock while we set control area flags */
2331 OldIrql = MiAcquirePfnLock();
2332
2333 /* We don't support this race condition yet, so assume no waiters */
2334 ASSERT(ControlArea->WaitingForDeletion == NULL);
2335 ControlArea->WaitingForDeletion = NULL;
2336
2337 /* Image-file backed sections are not yet supported, nor ROM images */
2339 ASSERT(Segment->ControlArea->u.Flags.Rom == 0);
2340
2341 /* Take off the being created flag, and then release the lock */
2342 ControlArea->u.Flags.BeingCreated = FALSE;
2343 MiReleasePfnLock(OldIrql);
2344 }
2345
2346 /* Check if we locked the file earlier */
2347 if (FileLock)
2348 {
2349 /* Reset the top-level IRP and release the lock */
2351 //FsRtlReleaseFile(File);
2352 FileLock = FALSE;
2353 }
2354
2355 /* Set the initial section object data */
2357
2358 /* The mapping created a control area and segment, save the flags */
2359 Section.Segment = NewSegment;
2360 Section.u.LongFlags = ControlArea->u.LongFlags;
2361
2362 /* Check if this is a user-mode read-write non-image file mapping */
2363 if (!(FileObject) &&
2365 !(ControlArea->u.Flags.Image) &&
2366 (ControlArea->FilePointer))
2367 {
2368 /* Add a reference and set the flag */
2369 Section.u.Flags.UserWritable = TRUE;
2370 InterlockedIncrement((volatile LONG*)&ControlArea->WritableUserReferences);
2371 }
2372
2373 /* Check for image mappings or page file mappings */
2374 if ((ControlArea->u.Flags.Image) || !(ControlArea->FilePointer))
2375 {
2376 /* Charge the segment size, and allocate a subsection */
2377 PagedCharge = sizeof(SECTION) + NewSegment->TotalNumberOfPtes * sizeof(MMPTE);
2378 Size = sizeof(SUBSECTION);
2379 }
2380 else
2381 {
2382 /* Charge nothing, and allocate a mapped subsection */
2383 PagedCharge = 0;
2384 Size = sizeof(MSUBSECTION);
2385 }
2386
2387 /* Check if this is a normal CA */
2388 ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
2389 ASSERT(ControlArea->u.Flags.Rom == 0);
2390
2391 /* Charge only a CA, and the subsection is right after */
2392 NonPagedCharge = sizeof(CONTROL_AREA);
2393 Subsection = (PSUBSECTION)(ControlArea + 1);
2394
2395 /* We only support single-subsection mappings */
2396 NonPagedCharge += Size;
2397 ASSERT(Subsection->NextSubsection == NULL);
2398
2399 /* Create the actual section object, with enough space for the prototype PTEs */
2404 NULL,
2405 sizeof(SECTION),
2406 PagedCharge,
2407 NonPagedCharge,
2408 (PVOID*)&NewSection);
2409 if (!NT_SUCCESS(Status))
2410 {
2411 /* Check if this is a user-mode read-write non-image file mapping */
2412 if (!(FileObject) &&
2414 !(ControlArea->u.Flags.Image) &&
2415 (ControlArea->FilePointer))
2416 {
2417 /* Remove a reference and check the flag */
2418 ASSERT(Section.u.Flags.UserWritable == 1);
2419 InterlockedDecrement((volatile LONG*)&ControlArea->WritableUserReferences);
2420 }
2421
2422 /* Check if a user reference was added */
2423 if (UserRefIncremented)
2424 {
2425 /* Acquire the PFN lock while we change counters */
2426 OldIrql = MiAcquirePfnLock();
2427
2428 /* Decrement the accounting counters */
2429 ControlArea->NumberOfSectionReferences--;
2430 ASSERT((LONG)ControlArea->NumberOfUserReferences > 0);
2431 ControlArea->NumberOfUserReferences--;
2432
2433 /* Check if we should destroy the CA and release the lock */
2434 MiCheckControlArea(ControlArea, OldIrql);
2435 }
2436
2437 /* Return the failure code */
2438 return Status;
2439 }
2440
2441 /* NOTE: Past this point, all failures will be handled by Ob upon ref->0 */
2442
2443 /* Now copy the local section object from the stack into this new object */
2444 RtlCopyMemory(NewSection, &Section, sizeof(SECTION));
2445 NewSection->Address.StartingVpn = 0;
2446
2447 /* For now, only user calls are supported */
2448 ASSERT(KernelCall == FALSE);
2449 NewSection->u.Flags.UserReference = TRUE;
2450
2451 /* Is this a "based" allocation, in which all mappings are identical? */
2453 {
2454 /* Lock the VAD tree during the search */
2456
2457 /* Is it a brand new ControArea ? */
2458 if (ControlArea->u.Flags.BeingCreated == 1)
2459 {
2460 ASSERT(ControlArea->u.Flags.Based == 1);
2461 /* Then we must find a global address, top-down */
2464 _64K,
2466 (ULONG_PTR*)&ControlArea->Segment->BasedAddress);
2467
2468 if (!NT_SUCCESS(Status))
2469 {
2470 /* No way to find a valid range. */
2472 ControlArea->u.Flags.Based = 0;
2473 NewSection->u.Flags.Based = 0;
2474 ObDereferenceObject(NewSection);
2475 return Status;
2476 }
2477
2478 /* Compute the ending address and insert it into the VAD tree */
2479 NewSection->Address.StartingVpn = (ULONG_PTR)ControlArea->Segment->BasedAddress;
2480 NewSection->Address.EndingVpn = NewSection->Address.StartingVpn + NewSection->SizeOfSection.LowPart - 1;
2481 MiInsertBasedSection(NewSection);
2482 }
2483 else
2484 {
2485 /* 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 !*/
2486 ASSERT(FALSE);
2487 }
2488
2490 }
2491
2492 /* The control area is not being created anymore */
2493 if (ControlArea->u.Flags.BeingCreated == 1)
2494 {
2495 /* Acquire the PFN lock while we set control area flags */
2496 OldIrql = MiAcquirePfnLock();
2497
2498 /* Take off the being created flag, and then release the lock */
2499 ControlArea->u.Flags.BeingCreated = 0;
2500 NewSection->u.Flags.BeingCreated = 0;
2501
2502 MiReleasePfnLock(OldIrql);
2503 }
2504
2505 /* Migrate the attribute into a flag */
2507
2508 /* If R/W access is not requested, this might eventually become a CoW mapping */
2510 {
2511 NewSection->u.Flags.CopyOnWrite = TRUE;
2512 }
2513
2514 /* Write down if this was a kernel call */
2515 ControlArea->u.Flags.WasPurged |= KernelCall;
2516 ASSERT(ControlArea->u.Flags.WasPurged == FALSE);
2517
2518 /* Make sure the segment and the section are the same size, or the section is smaller */
2519 ASSERT((ULONG64)NewSection->SizeOfSection.QuadPart <= NewSection->Segment->SizeOfSegment);
2520
2521 /* Return the object and the creation status */
2522 *SectionObject = (PVOID)NewSection;
2523 return Status;
2524}
KGUARDED_MUTEX MmSectionBasedMutex
Definition: section.c:110
static NTSTATUS MiCreateDataFileMap(IN PFILE_OBJECT File, OUT PSEGMENT *Segment, IN PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN ULONG IgnoreFileSizing)
Definition: section.c:1406
static NTSTATUS MiCreatePagingFileMap(OUT PSEGMENT *Segment, IN ULONG64 MaximumSize, IN ULONG ProtectionMask, IN ULONG AllocationAttributes)
Definition: section.c:1421
PVOID MmHighSectionBase
Definition: section.c:111
ACCESS_MASK MmMakeFileAccess[8]
Definition: section.c:32
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
static VOID MiCheckControlArea(IN PCONTROL_AREA ControlArea, IN KIRQL OldIrql)
Definition: section.c:714
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:140
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG _In_ KPROCESSOR_MODE PreviousMode
#define InterlockedIncrement
Definition: armddk.h:53
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define ExGetPreviousMode
Definition: ex.h:143
_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:386
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:711
#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:101
#define SEC_COMMIT
Definition: mmtypes.h:100
#define SEC_IMAGE
Definition: mmtypes.h:97
struct _MSUBSECTION MSUBSECTION
#define SEC_LARGE_PAGES
Definition: mmtypes.h:103
#define SEC_NO_CHANGE
Definition: mmtypes.h:95
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:1653
#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:194
PSEGMENT Segment
Definition: mmtypes.h:521
ULONG NumberOfSectionReferences
Definition: mmtypes.h:523
PEVENT_COUNTER WaitingForDeletion
Definition: mmtypes.h:534
ULONG NumberOfUserReferences
Definition: mmtypes.h:527
ULONG LongFlags
Definition: mmtypes.h:530
ULONG WritableUserReferences
Definition: mmtypes.h:537
MMSECTION_FLAGS Flags
Definition: mmtypes.h:531
PFILE_OBJECT FilePointer
Definition: mmtypes.h:533
union _CONTROL_AREA::@2790 u
ULONG_PTR StartingVpn
Definition: mmtypes.h:653
ULONG_PTR EndingVpn
Definition: mmtypes.h:654
ULONG NoChange
Definition: mmtypes.h:486
ULONG UserReference
Definition: mmtypes.h:479
ULONG CopyOnWrite
Definition: mmtypes.h:474
ULONG FilePointerNull
Definition: mmtypes.h:482
ULONG BeingCreated
Definition: mmtypes.h:464
ULONG GlobalOnlyPerSession
Definition: mmtypes.h:491
ULONG WasPurged
Definition: mmtypes.h:478
ULONG UserWritable
Definition: mmtypes.h:489
MMSECTION_FLAGS Flags
Definition: mmtypes.h:817
ULONG LongFlags
Definition: mmtypes.h:816
PSEGMENT Segment
Definition: mmtypes.h:812
ULONG InitialPageProtection
Definition: mmtypes.h:819
union _SECTION::@2806 u
MMADDRESS_NODE Address
Definition: mmtypes.h:811
LARGE_INTEGER SizeOfSection
Definition: mmtypes.h:813
struct _CONTROL_AREA * ControlArea
Definition: mmtypes.h:409
ULONG TotalNumberOfPtes
Definition: mmtypes.h:410
PVOID BasedAddress
Definition: mmtypes.h:418
ULONGLONG SizeOfSegment
Definition: mmtypes.h:413
struct _SUBSECTION * NextSubsection
Definition: mmtypes.h:584
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

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 2340 of file section.c.

2351{
2352 PSECTION Section;
2356 KIRQL OldIrql;
2357
2358 /*
2359 * Create the section
2360 */
2365 NULL,
2366 sizeof(*Section),
2367 0,
2368 0,
2369 (PVOID*)&Section);
2370 if (!NT_SUCCESS(Status))
2371 {
2372 return Status;
2373 }
2374 /*
2375 * Initialize it
2376 */
2377 RtlZeroMemory(Section, sizeof(*Section));
2378
2379 /* Mark this as a "ROS" section */
2380 Section->u.Flags.filler = 1;
2382 Section->u.Flags.File = 1;
2383
2385 Section->u.Flags.NoChange = 1;
2386
2387 if (!GotFileHandle)
2388 {
2389 ASSERT(UMaximumSize != NULL);
2390 // ASSERT(UMaximumSize->QuadPart != 0);
2391 MaximumSize = *UMaximumSize;
2392 }
2393 else
2394 {
2397 if (!NT_SUCCESS(Status))
2398 {
2399 ObDereferenceObject(Section);
2400 return Status;
2401 }
2402
2403 /*
2404 * FIXME: Revise this once a locking order for file size changes is
2405 * decided
2406 */
2407 if ((UMaximumSize != NULL) && (UMaximumSize->QuadPart != 0))
2408 {
2409 MaximumSize = *UMaximumSize;
2410 }
2411 else
2412 {
2414 /* Mapping zero-sized files isn't allowed. */
2415 if (MaximumSize.QuadPart == 0)
2416 {
2417 ObDereferenceObject(Section);
2419 }
2420 }
2421
2422 if (MaximumSize.QuadPart > FileSize.QuadPart)
2423 {
2426 sizeof(LARGE_INTEGER),
2427 &MaximumSize);
2428 if (!NT_SUCCESS(Status))
2429 {
2430 ObDereferenceObject(Section);
2432 }
2433 }
2434 }
2435
2436 if (FileObject->SectionObjectPointer == NULL)
2437 {
2438 ObDereferenceObject(Section);
2440 }
2441
2442 /*
2443 * Lock the file
2444 */
2446 if (Status != STATUS_SUCCESS)
2447 {
2448 ObDereferenceObject(Section);
2449 return Status;
2450 }
2451
2452 /* Lock the PFN lock while messing with Section Object pointers */
2453grab_segment:
2454 OldIrql = MiAcquirePfnLock();
2455 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2456
2457 while (Segment && (Segment->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
2458 {
2459 MiReleasePfnLock(OldIrql);
2461 OldIrql = MiAcquirePfnLock();
2462 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2463 }
2464
2465 /*
2466 * If this file hasn't been mapped as a data file before then allocate a
2467 * section segment to describe the data file mapping
2468 */
2469 if (Segment == NULL)
2470 {
2471 /* Release the lock. ExAllocatePoolWithTag might acquire it */
2472 MiReleasePfnLock(OldIrql);
2473
2476 if (Segment == NULL)
2477 {
2478 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2479 ObDereferenceObject(Section);
2480 return STATUS_NO_MEMORY;
2481 }
2482
2483 /* We are creating it */
2484 RtlZeroMemory(Segment, sizeof(*Segment));
2486 Segment->RefCount = 1;
2487
2488 /* Acquire lock again */
2489 OldIrql = MiAcquirePfnLock();
2490
2491 if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
2492 {
2493 /* Well that's bad luck. Restart it all over */
2494 MiReleasePfnLock(OldIrql);
2496 goto grab_segment;
2497 }
2498
2499 FileObject->SectionObjectPointer->DataSectionObject = Segment;
2500
2501 /* We're safe to release the lock now */
2502 MiReleasePfnLock(OldIrql);
2503
2504 Section->Segment = (PSEGMENT)Segment;
2505
2506 /* Self-referencing segment */
2507 Segment->Flags = &Segment->SegFlags;
2508 Segment->ReferenceCount = &Segment->RefCount;
2509
2510 Segment->SectionCount = 1;
2511
2513 Segment->FileObject = FileObject;
2515
2516 Segment->Image.FileOffset = 0;
2517 Segment->Protection = SectionPageProtection;
2518
2519 Segment->Image.Characteristics = 0;
2522 {
2523 Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0;
2524 }
2525 else
2526 {
2527 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2528 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2529 }
2530 Segment->Image.VirtualAddress = 0;
2532
2533 /* We're good to use it now */
2534 OldIrql = MiAcquirePfnLock();
2535 Segment->SegFlags &= ~MM_SEGMENT_INCREATE;
2536 MiReleasePfnLock(OldIrql);
2537 }
2538 else
2539 {
2540 Section->Segment = (PSEGMENT)Segment;
2541 InterlockedIncrement64(&Segment->RefCount);
2542 InterlockedIncrementUL(&Segment->SectionCount);
2543
2544 MiReleasePfnLock(OldIrql);
2545
2547
2548 if (MaximumSize.QuadPart > Segment->RawLength.QuadPart &&
2550 {
2551 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2552 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2553 }
2554
2556 }
2557 Section->SizeOfSection = MaximumSize;
2558
2559 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2560 *SectionObject = Section;
2561 return STATUS_SUCCESS;
2562}
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1544
@ 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:907
#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 3188 of file section.c.

3195{
3196 PSECTION Section;
3198 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3199 KIRQL OldIrql;
3200
3201
3202 if (FileObject == NULL)
3204
3205 if (FileObject->SectionObjectPointer == NULL)
3206 {
3207 DPRINT1("Denying section creation due to missing cache initialization\n");
3209 }
3210
3211 /*
3212 * Create the section
3213 */
3218 NULL,
3219 sizeof(*Section),
3220 0,
3221 0,
3222 (PVOID*)(PVOID)&Section);
3223 if (!NT_SUCCESS(Status))
3224 {
3225 return Status;
3226 }
3227
3228 /*
3229 * Initialize it
3230 */
3231 RtlZeroMemory(Section, sizeof(*Section));
3232
3233 /* Mark this as a "ROS" Section */
3234 Section->u.Flags.filler = 1;
3235
3237 Section->SizeOfSection = *UMaximumSize;
3238 Section->u.Flags.File = 1;
3239 Section->u.Flags.Image = 1;
3241 Section->u.Flags.NoChange = 1;
3242
3243grab_image_section_object:
3244 OldIrql = MiAcquirePfnLock();
3245
3246 /* Wait for it to be properly created or deleted */
3247 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3248 while(ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
3249 {
3250 MiReleasePfnLock(OldIrql);
3251
3253
3254 OldIrql = MiAcquirePfnLock();
3255 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3256 }
3257
3258 if (ImageSectionObject == NULL)
3259 {
3260 NTSTATUS StatusExeFmt;
3261
3262 /* Release the lock because ExAllocatePoolWithTag could need to acquire it */
3263 MiReleasePfnLock(OldIrql);
3264
3266 if (ImageSectionObject == NULL)
3267 {
3268 ObDereferenceObject(Section);
3269 return STATUS_NO_MEMORY;
3270 }
3271
3272 ImageSectionObject->SegFlags = MM_SEGMENT_INCREATE;
3273 ImageSectionObject->RefCount = 1;
3274 ImageSectionObject->SectionCount = 1;
3275
3276 OldIrql = MiAcquirePfnLock();
3277 if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
3278 {
3279 MiReleasePfnLock(OldIrql);
3280 /* Bad luck. Start over */
3281 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3282 goto grab_image_section_object;
3283 }
3284
3285 FileObject->SectionObjectPointer->ImageSectionObject = ImageSectionObject;
3286
3287 MiReleasePfnLock(OldIrql);
3288
3289 /* Purge the cache */
3290 CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, NULL);
3291
3292 StatusExeFmt = ExeFmtpCreateImageSection(FileObject, ImageSectionObject);
3293
3294 if (!NT_SUCCESS(StatusExeFmt))
3295 {
3296 /* Unset */
3297 OldIrql = MiAcquirePfnLock();
3298 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3299 MiReleasePfnLock(OldIrql);
3300
3301 if(ImageSectionObject->Segments != NULL)
3302 ExFreePool(ImageSectionObject->Segments);
3303
3304 /*
3305 * If image file is empty, then return that the file is invalid for section
3306 */
3307 Status = StatusExeFmt;
3308 if (StatusExeFmt == STATUS_END_OF_FILE)
3309 {
3311 }
3312
3313 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3314 ObDereferenceObject(Section);
3315 return Status;
3316 }
3317
3318 Section->Segment = (PSEGMENT)ImageSectionObject;
3319 ASSERT(ImageSectionObject->Segments);
3320 ASSERT(ImageSectionObject->RefCount > 0);
3321
3322 /*
3323 * Lock the file
3324 */
3326 if (!NT_SUCCESS(Status))
3327 {
3328 /* Unset */
3329 OldIrql = MiAcquirePfnLock();
3330 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3331 MiReleasePfnLock(OldIrql);
3332
3333 ExFreePool(ImageSectionObject->Segments);
3334 ExFreePool(ImageSectionObject);
3335 ObDereferenceObject(Section);
3336 return Status;
3337 }
3338
3339 OldIrql = MiAcquirePfnLock();
3340 ImageSectionObject->SegFlags &= ~MM_SEGMENT_INCREATE;
3341
3342 /* Take a ref on the file on behalf of the newly created structure */
3344
3345 MiReleasePfnLock(OldIrql);
3346
3347 Status = StatusExeFmt;
3348 }
3349 else
3350 {
3351 /* If FS driver called for delete, tell them it's not possible anymore. */
3352 ImageSectionObject->SegFlags &= ~MM_IMAGE_SECTION_FLUSH_DELETE;
3353
3354 /* Take one ref */
3355 InterlockedIncrement64(&ImageSectionObject->RefCount);
3356 ImageSectionObject->SectionCount++;
3357
3358 MiReleasePfnLock(OldIrql);
3359
3360 Section->Segment = (PSEGMENT)ImageSectionObject;
3361
3363 }
3364
3365 if (Section->SizeOfSection.QuadPart == 0)
3366 {
3367 Section->SizeOfSection.QuadPart = ImageSectionObject->ImageInformation.ImageFileSize;
3368 }
3369
3370 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
3371 *SectionObject = Section;
3372 ASSERT(ImageSectionObject->RefCount > 0);
3373
3374 return Status;
3375}
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
FORCEINLINE PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
NTSTATUS ExeFmtpCreateImageSection(PFILE_OBJECT FileObject, PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:3035
#define STATUS_END_OF_FILE
Definition: shellext.h:67
SECTION_IMAGE_INFORMATION ImageInformation
Definition: mm.h:236

Referenced by MmCreateSection().

◆ MmCreatePhysicalMemorySection()

NTSTATUS NTAPI MmCreatePhysicalMemorySection ( VOID  )

Definition at line 2216 of file section.c.

2217{
2218 PSECTION PhysSection;
2221 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
2222 LARGE_INTEGER SectionSize;
2223 HANDLE Handle;
2225
2226 /*
2227 * Create the section mapping physical memory
2228 */
2231 &Name,
2233 NULL,
2234 NULL);
2235 /*
2236 * Create the Object
2237 */
2240 &Obj,
2242 NULL,
2243 sizeof(*PhysSection),
2244 0,
2245 0,
2246 (PVOID*)&PhysSection);
2247 if (!NT_SUCCESS(Status))
2248 {
2249 DPRINT1("MmCreatePhysicalMemorySection: failed to create object (0x%lx)\n", Status);
2250 return Status;
2251 }
2252
2253 /*
2254 * Initialize it
2255 */
2256 RtlZeroMemory(PhysSection, sizeof(*PhysSection));
2257
2258 /* Mark this as a "ROS Section" */
2259 PhysSection->u.Flags.filler = 1;
2261 PhysSection->u.Flags.PhysicalMemory = 1;
2262 PhysSection->SizeOfSection = SectionSize;
2265 if (Segment == NULL)
2266 {
2267 ObDereferenceObject(PhysSection);
2268 return STATUS_NO_MEMORY;
2269 }
2271 PhysSection->Segment = (PSEGMENT)Segment;
2272 Segment->RefCount = 1;
2273
2274 Segment->ReferenceCount = &Segment->RefCount;
2275 Segment->Flags = &Segment->SegFlags;
2276
2278 Segment->Image.FileOffset = 0;
2279 Segment->Protection = PAGE_EXECUTE_READWRITE;
2280 Segment->RawLength = SectionSize;
2281 Segment->Length = SectionSize;
2283 Segment->WriteCopy = FALSE;
2284 Segment->Image.VirtualAddress = 0;
2285 Segment->Image.Characteristics = 0;
2287
2288 Status = ObInsertObject(PhysSection,
2289 NULL,
2291 0,
2292 NULL,
2293 &Handle);
2294 if (!NT_SUCCESS(Status))
2295 {
2296 ObDereferenceObject(PhysSection);
2297 return Status;
2298 }
2300
2301 return STATUS_SUCCESS;
2302}
LPWSTR Name
Definition: desk.c:124
#define L(x)
Definition: resources.c:13
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
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:473
#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 4652 of file section.c.

4660{
4662 ULONG Protection;
4663 PSECTION *SectionObject = (PSECTION *)Section;
4664 BOOLEAN FileLock = FALSE;
4665 BOOLEAN HaveFileObject = FALSE;
4666
4667 // FIXME: Implement support for large pages
4669 {
4670 DPRINT1("SEC_LARGE_PAGES is not supported\n");
4672 }
4673
4674 /* Check if an ARM3 section is being created instead */
4676 {
4677 if (!(FileObject) && !(FileHandle))
4678 {
4679 return MmCreateArm3Section(Section,
4685 FileHandle,
4686 FileObject);
4687 }
4688 }
4689
4690 /* Convert section flag to page flag */
4692
4693 /* Check to make sure the protection is correct. Nt* does this already */
4695 if (Protection == MM_INVALID_PROTECTION)
4696 {
4697 DPRINT1("Page protection is invalid\n");
4699 }
4700
4701 /* Check if this is going to be a data or image backed file section */
4702 if ((FileHandle) || (FileObject))
4703 {
4704 /* These cannot be mapped with large pages */
4706 {
4707 DPRINT1("Large pages cannot be used with an image mapping\n");
4709 }
4710
4711 /* Did the caller pass a file object ? */
4712 if (FileObject)
4713 {
4714 /* Reference the object directly */
4716 HaveFileObject = TRUE;
4717 }
4718 else
4719 {
4720 /* Reference the file handle to get the object */
4722 MmMakeFileAccess[Protection],
4725 (PVOID*)&FileObject,
4726 NULL);
4727 if (!NT_SUCCESS(Status))
4728 {
4729 DPRINT1("Failed to get a handle to the FO: %lx\n", Status);
4730 return Status;
4731 }
4732
4733 /* Lock the file */
4735 if (!NT_SUCCESS(Status))
4736 {
4738 return Status;
4739 }
4740
4741 FileLock = TRUE;
4742
4743 /* Deny access if there are writes on the file */
4744#if 0
4746 {
4747 DPRINT1("Cannot create image maps with writers open on the file!\n");
4749 goto Quit;
4750 }
4751#else
4753 DPRINT1("Creating image map with writers open on the file!\n");
4754#endif
4755 }
4756 }
4757 else
4758 {
4759 /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
4761 }
4762
4763 if (FileObject == NULL)
4764 {
4766 goto Exit;
4767 }
4768
4770 {
4777 FileObject);
4778
4779 /* If the file was ivalid, and we got a FileObject passed, fall back to data section */
4780 if (!NT_SUCCESS(Status) && HaveFileObject)
4781 {
4782 AllocationAttributes &= ~SEC_IMAGE;
4783 }
4784 }
4785
4786#ifndef NEWCC
4788 {
4795 FileObject,
4796 FileHandle != NULL);
4797 }
4798#else
4799 else
4800 {
4807 FileObject);
4808 }
4809#endif
4810
4811Exit:
4812
4813 if (FileLock)
4815 if (FileObject)
4817
4818 return Status;
4819}
NTSTATUS NTAPI MmCreateCacheSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
#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:2340
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:2102
NTSTATUS MmCreateImageSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
Definition: section.c:3188
static void Exit(void)
Definition: sock.c:1330
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658

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

◆ MmExtendSection()

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

Definition at line 5426 of file section.c.

5429{
5430 PSECTION Section = _Section;
5431
5432 /* It makes no sense to extend an image mapping */
5433 if (Section->u.Flags.Image)
5435
5436 /* Nor is it possible to extend a page file mapping */
5437 if (!Section->u.Flags.File)
5439
5440 if (!MiIsRosSectionObject(Section))
5442
5443 /* We just extend the sizes. Shrinking is a no-op ? */
5444 if (NewSize->QuadPart > Section->SizeOfSection.QuadPart)
5445 {
5447 Section->SizeOfSection = *NewSize;
5448
5449 if (!Section->u.Flags.Reserve)
5450 {
5452 if (Segment->RawLength.QuadPart < NewSize->QuadPart)
5453 {
5454 Segment->RawLength = *NewSize;
5455 Segment->Length.QuadPart = (NewSize->QuadPart + PAGE_SIZE - 1) & ~((LONGLONG)PAGE_SIZE);
5456 }
5458 }
5459 }
5460
5461 return STATUS_SUCCESS;
5462}
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
_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:1101
struct _MM_SECTION_SEGMENT * PMM_SECTION_SEGMENT

Referenced by CcSetFileSizes(), and NtExtendSection().

◆ MmFlushImageSection()

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

Definition at line 4388 of file section.c.

4390{
4391 switch(FlushType)
4392 {
4393 case MmFlushForDelete:
4394 {
4395 /*
4396 * FIXME: Check for outstanding write probes on Data section.
4397 * How do we do that ?
4398 */
4399 }
4400 /* Fall-through */
4401 case MmFlushForWrite:
4402 {
4403 KIRQL OldIrql = MiAcquirePfnLock();
4404 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4405
4406 DPRINT("Deleting or modifying %p\n", SectionObjectPointer);
4407
4408 /* Wait for concurrent creation or deletion of image to be done */
4409 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4410 while (ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INCREATE | MM_SEGMENT_INDELETE)))
4411 {
4412 MiReleasePfnLock(OldIrql);
4414 OldIrql = MiAcquirePfnLock();
4415 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4416 }
4417
4418 if (!ImageSectionObject)
4419 {
4420 DPRINT("No image section object. Accepting\n");
4421 /* Nothing to do */
4422 MiReleasePfnLock(OldIrql);
4423 return TRUE;
4424 }
4425
4426 /* Do we have open sections or mappings on it ? */
4427 if ((ImageSectionObject->SectionCount) || (ImageSectionObject->MapCount))
4428 {
4429 /* We do. No way to delete it */
4430 MiReleasePfnLock(OldIrql);
4431 DPRINT("Denying. There are mappings open\n");
4432 return FALSE;
4433 }
4434
4435 /* There are no sections open on it, but we must still have pages around. Discard everything */
4436 ImageSectionObject->SegFlags |= MM_IMAGE_SECTION_FLUSH_DELETE;
4437 InterlockedIncrement64(&ImageSectionObject->RefCount);
4438 MiReleasePfnLock(OldIrql);
4439
4440 DPRINT("Purging\n");
4441
4442 for (ULONG i = 0; i < ImageSectionObject->NrSegments; i++)
4443 {
4444 if (!MiPurgeImageSegment(&ImageSectionObject->Segments[i]))
4445 break;
4446 }
4447
4448 /* Grab lock again */
4449 OldIrql = MiAcquirePfnLock();
4450
4451 if (!(ImageSectionObject->SegFlags & MM_IMAGE_SECTION_FLUSH_DELETE))
4452 {
4453 /*
4454 * Someone actually created a section while we were not looking.
4455 * Drop our ref and deny.
4456 * MmDereferenceSegmentWithLock releases Pfn lock
4457 */
4458 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4459 return FALSE;
4460 }
4461
4462 /* We should be the last one holding a ref here. */
4463 ASSERT(ImageSectionObject->RefCount == 1);
4464 ASSERT(ImageSectionObject->SectionCount == 0);
4465
4466 /* Dereference the first segment, this will free everything & release the lock */
4467 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4468 return TRUE;
4469 }
4470 }
4471 return FALSE;
4472}
IN PFCB IN FAT_FLUSH_TYPE FlushType
Definition: fatprocs.h:1083
#define MM_IMAGE_SECTION_FLUSH_DELETE
Definition: mm.h:246
static BOOLEAN MiPurgeImageSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:4342

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 5094 of file section.c.

5099{
5100 LARGE_INTEGER FlushStart, FlushEnd;
5102
5103 if (Offset)
5104 {
5105 FlushStart = *Offset;
5106 Status = RtlLongLongAdd(FlushStart.QuadPart, Length, &FlushEnd.QuadPart);
5107 if (!NT_SUCCESS(Status))
5108 return Status;
5109 }
5110
5111 if (Iosb)
5112 Iosb->Information = 0;
5113
5115 if (!Segment)
5116 {
5117 /* Nothing to flush */
5118 goto Quit;
5119 }
5120
5122
5124
5125 if (!Offset)
5126 {
5127 FlushStart.QuadPart = 0;
5128
5129 /* FIXME: All of this is suboptimal */
5130 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
5131 if (!ElemCount)
5132 {
5133 /* No page. Nothing to flush */
5135 MmDereferenceSegment(Segment);
5136 goto Quit;
5137 }
5138
5140 FlushEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
5141 }
5142
5143 /* Find byte offset of the page to start */
5144 FlushStart.QuadPart = PAGE_ROUND_DOWN_64(FlushStart.QuadPart);
5145
5146 while (FlushStart.QuadPart < FlushEnd.QuadPart)
5147 {
5149
5150 if (IS_DIRTY_SSE(Entry))
5151 {
5152 MmCheckDirtySegment(Segment, &FlushStart, FALSE, FALSE);
5153
5154 if (Iosb)
5155 Iosb->Information += PAGE_SIZE;
5156 }
5157
5158 FlushStart.QuadPart += PAGE_SIZE;
5159 }
5160
5162 MmDereferenceSegment(Segment);
5163
5164Quit:
5165 /* FIXME: Handle failures */
5166 if (Iosb)
5167 Iosb->Status = STATUS_SUCCESS;
5168
5169 return STATUS_SUCCESS;
5170}
BOOLEAN NTAPI MmCheckDirtySegment(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, BOOLEAN ForceDirty, BOOLEAN PageOut)
#define PAGE_ROUND_DOWN_64(x)
Definition: mm.h:136
_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 3459 of file section.c.

3461{
3464 SWAPENTRY SavedSwapEntry;
3468
3471
3473
3475 MemoryArea->SectionData.ViewOffset;
3476
3477 Segment = MemoryArea->SectionData.Segment;
3478
3480 while (Entry && MM_IS_WAIT_PTE(Entry))
3481 {
3484
3486
3490 }
3491
3492 /*
3493 * For a dirty, datafile, non-private page, there shoulkd be no swap entry
3494 */
3495 if (*Segment->Flags & MM_DATAFILE_SEGMENT)
3496 {
3497 if (Page == PFN_FROM_SSE(Entry) && Dirty)
3498 {
3499 ASSERT(SwapEntry == 0);
3500 }
3501 }
3502
3503 if (SwapEntry != 0)
3504 {
3505 /*
3506 * Sanity check
3507 */
3508 MmFreeSwapPage(SwapEntry);
3509 }
3510 else if (Page != 0)
3511 {
3512 if (IS_SWAP_FROM_SSE(Entry) ||
3514 {
3515 ASSERT(Process != NULL);
3516
3517 /*
3518 * Just dereference private pages
3519 */
3520 SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
3521 if (SavedSwapEntry != 0)
3522 {
3523 MmFreeSwapPage(SavedSwapEntry);
3525 }
3528 }
3529 else
3530 {
3531 if (Process)
3532 {
3534 }
3535
3536 /* We don't dirtify for System Space Maps. We let Cc manage that */
3538 }
3539 }
3540}
struct _MMSUPPORT * PMMSUPPORT
#define MM_IS_WAIT_PTE(E)
Definition: mm.h:1368

Referenced by MmUnmapViewOfSegment().

◆ MmInitSectionImplementation()

NTSTATUS NTAPI MmInitSectionImplementation ( VOID  )

Definition at line 2307 of file section.c.

2308{
2309 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
2311
2312 DPRINT("Creating Section Object Type\n");
2313
2314 /* Initialize the section based root */
2317
2318 /* Initialize the Section object type */
2319 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
2320 RtlInitUnicodeString(&Name, L"Section");
2321 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
2322 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(SECTION);
2323 ObjectTypeInitializer.PoolType = PagedPool;
2324 ObjectTypeInitializer.UseDefaultObject = TRUE;
2325 ObjectTypeInitializer.GenericMapping = MmpSectionMapping;
2326 ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
2327 ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
2328 ObjectTypeInitializer.ValidAccessMask = SECTION_ALL_ACCESS;
2329 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
2330 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &MmSectionObjectType);
2331
2333
2334 return STATUS_SUCCESS;
2335}
#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:223
VOID NTAPI MmpDeleteSection(PVOID ObjectBody)
Definition: section.c:2151
VOID NTAPI MmpCloseSection(IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG ProcessHandleCount, IN ULONG SystemHandleCount)
Definition: section.c:2204
NTSTATUS NTAPI MmCreatePhysicalMemorySection(VOID)
Definition: section.c:2216
union _MMADDRESS_NODE::@2795 u1
struct _MMADDRESS_NODE * Parent
Definition: mmtypes.h:649
ULONG_PTR NumberGenericTableElements
Definition: mmtypes.h:668
MMADDRESS_NODE BalancedRoot
Definition: mmtypes.h:662
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().

◆ MmIsDataSectionResident()

BOOLEAN NTAPI MmIsDataSectionResident ( _In_ PSECTION_OBJECT_POINTERS  SectionObjectPointer,
_In_ LONGLONG  Offset,
_In_ ULONG  Length 
)

Definition at line 4975 of file section.c.

4979{
4981 LARGE_INTEGER RangeStart, RangeEnd;
4982 BOOLEAN Ret = TRUE;
4983
4984 RangeStart.QuadPart = Offset;
4985 if (!NT_SUCCESS(RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart)))
4986 return FALSE;
4987
4989 if (!Segment)
4990 return FALSE;
4991
4992 /* Find byte offset of the page to start */
4993 RangeStart.QuadPart = PAGE_ROUND_DOWN_64(RangeStart.QuadPart);
4994
4996
4997 while (RangeStart.QuadPart < RangeEnd.QuadPart)
4998 {
5000 if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
5001 {
5002 Ret = FALSE;
5003 break;
5004 }
5005
5006 RangeStart.QuadPart += PAGE_SIZE;
5007 }
5008
5010 MmDereferenceSegment(Segment);
5011
5012 return Ret;
5013}

Referenced by CcRosEnsureVacbResident().

◆ MmMakeDataSectionResident()

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

Definition at line 5017 of file section.c.

5022{
5024
5025 /* There must be a segment for this call */
5026 ASSERT(Segment);
5027
5029
5030 MmDereferenceSegment(Segment);
5031
5032 return Status;
5033}
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:1192

Referenced by CcRosEnsureVacbResident().

◆ MmMakeSegmentDirty()

NTSTATUS NTAPI MmMakeSegmentDirty ( _In_ PSECTION_OBJECT_POINTERS  SectionObjectPointer,
_In_ LONGLONG  Offset,
_In_ ULONG  Length 
)

Definition at line 5037 of file section.c.

5041{
5043 LARGE_INTEGER RangeStart, RangeEnd;
5045
5046 RangeStart.QuadPart = Offset;
5047 Status = RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart);
5048 if (!NT_SUCCESS(Status))
5049 return Status;
5050
5052 if (!Segment)
5054
5055 /* Find byte offset of the page to start */
5056 RangeStart.QuadPart = PAGE_ROUND_DOWN_64(RangeStart.QuadPart);
5057
5059
5060 while (RangeStart.QuadPart < RangeEnd.QuadPart)
5061 {
5063
5064 /* Let any pending read proceed */
5065 while (MM_IS_WAIT_PTE(Entry))
5066 {
5071 }
5072
5073 /* We are called from Cc, this can't be backed by the page files */
5075
5076 /* If there is no page there, there is nothing to make dirty */
5077 if (Entry != 0)
5078 {
5079 /* Dirtify the entry */
5081 }
5082
5083 RangeStart.QuadPart += PAGE_SIZE;
5084 }
5085
5087 MmDereferenceSegment(Segment);
5088
5089 return STATUS_SUCCESS;
5090}

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 1192 of file section.c.

1198{
1199 /* Let's use a 64K granularity. */
1200 LONGLONG RangeStart, RangeEnd;
1202 PFILE_OBJECT FileObject = Segment->FileObject;
1203
1204 /* Calculate our range, aligned on 64K if possible. */
1205 Status = RtlLongLongAdd(Offset, Length, &RangeEnd);
1207 if (!NT_SUCCESS(Status))
1208 return Status;
1209
1210 /* If the file is not random access and we are not the page out thread
1211 * read a 64K Chunk. */
1213 && !FlagOn(FileObject->Flags, FO_RANDOM_ACCESS))
1214 {
1215 RangeStart = Offset - (Offset % _64K);
1216 if (RangeEnd % _64K)
1217 RangeEnd += _64K - (RangeEnd % _64K);
1218 }
1219 else
1220 {
1221 RangeStart = Offset - (Offset % PAGE_SIZE);
1222 if (RangeEnd % PAGE_SIZE)
1223 RangeEnd += PAGE_SIZE - (RangeEnd % PAGE_SIZE);
1224 }
1225
1226 /* Clamp if needed */
1227 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
1228 {
1229 if (RangeEnd > Segment->RawLength.QuadPart)
1230 RangeEnd = Segment->RawLength.QuadPart;
1231 }
1232
1233 /* Let's gooooooooo */
1234 for ( ; RangeStart < RangeEnd; RangeStart += _64K)
1235 {
1236 /* First take a look at where we miss pages */
1237 ULONG ToReadPageBits = 0;
1238 LONGLONG ChunkEnd = RangeStart + _64K;
1239
1240 if (ChunkEnd > RangeEnd)
1241 ChunkEnd = RangeEnd;
1242
1244 for (LONGLONG ChunkOffset = RangeStart; ChunkOffset < ChunkEnd; ChunkOffset += PAGE_SIZE)
1245 {
1246 LARGE_INTEGER CurrentOffset;
1247
1248 CurrentOffset.QuadPart = ChunkOffset;
1250
1251 /* Let any pending read proceed */
1252 while (MM_IS_WAIT_PTE(Entry))
1253 {
1255
1257
1259 Entry = MmGetPageEntrySectionSegment(Segment, &CurrentOffset);
1260 }
1261
1262 if (Entry != 0)
1263 {
1264 /* Dirtify it if it's a resident page and we're asked to */
1265 if (SetDirty && !IS_SWAP_FROM_SSE(Entry))
1267 continue;
1268 }
1269
1270 ToReadPageBits |= 1UL << ((ChunkOffset - RangeStart) >> PAGE_SHIFT);
1271
1272 /* Put a wait entry here */
1273 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
1274 }
1276
1277 if (ToReadPageBits == 0)
1278 {
1279 /* Nothing to do for this chunk */
1280 continue;
1281 }
1282
1283 /* Now perform the actual read */
1284 LONGLONG ChunkOffset = RangeStart;
1285 while (ChunkOffset < ChunkEnd)
1286 {
1287 /* Move forward if there is a hole */
1288 ULONG BitSet;
1289 if (!_BitScanForward(&BitSet, ToReadPageBits))
1290 {
1291 /* Nothing more to read */
1292 break;
1293 }
1294 ToReadPageBits >>= BitSet;
1295 ChunkOffset += BitSet * PAGE_SIZE;
1296 ASSERT(ChunkOffset < ChunkEnd);
1297
1298 /* Get the range we have to read */
1299 _BitScanForward(&BitSet, ~ToReadPageBits);
1300 ULONG ReadLength = BitSet * PAGE_SIZE;
1301
1303
1304 /* Clamp (This is for image mappings */
1305 if ((ChunkOffset + ReadLength) > ChunkEnd)
1306 ReadLength = ChunkEnd - ChunkOffset;
1307
1308 ASSERT(ReadLength != 0);
1309
1310 /* Allocate a MDL */
1312 if (!Mdl)
1313 {
1314 /* Damn. Roll-back. */
1316 while (ChunkOffset < ChunkEnd)
1317 {
1318 if (ToReadPageBits & 1)
1319 {
1320 LARGE_INTEGER CurrentOffset;
1321 CurrentOffset.QuadPart = ChunkOffset;
1323 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, 0);
1324 }
1325 ToReadPageBits >>= 1;
1326 ChunkOffset += PAGE_SIZE;
1327 }
1330 }
1331
1332 /* Get our pages */
1335 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1336 {
1338 if (!NT_SUCCESS(Status))
1339 {
1340 /* Damn. Roll-back. */
1341 for (UINT j = 0; j < i; j++)
1343 goto Failed;
1344 }
1345 }
1346
1347 Mdl->MdlFlags |= MDL_PAGES_LOCKED | MDL_IO_PAGE_READ;
1348
1350 FileOffset.QuadPart = Segment->Image.FileOffset + ChunkOffset;
1351
1352 /* Clamp to VDL */
1353 if (ValidDataLength && ((FileOffset.QuadPart + ReadLength) > ValidDataLength->QuadPart))
1354 {
1355 if (FileOffset.QuadPart > ValidDataLength->QuadPart)
1356 {
1357 /* Great, nothing to read. */
1358 goto AssignPagesToSegment;
1359 }
1360
1361 Mdl->Size = (FileOffset.QuadPart + ReadLength) - ValidDataLength->QuadPart;
1362 }
1363
1364 KEVENT Event;
1366
1367 /* Disable APCs */
1368 KIRQL OldIrql;
1370
1373 if (Status == STATUS_PENDING)
1374 {
1376 Status = Iosb.Status;
1377 }
1378
1379 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
1380 {
1381 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
1382 }
1383
1385
1387 {
1388 DPRINT1("Got STATUS_END_OF_FILE at offset %I64d for file %wZ.\n", FileOffset.QuadPart, &FileObject->FileName);
1390 }
1391
1392 if (!NT_SUCCESS(Status))
1393 {
1394 /* Damn. Roll back. */
1395 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1397
1398Failed:
1400 while (ChunkOffset < ChunkEnd)
1401 {
1402 if (ToReadPageBits & 1)
1403 {
1404 LARGE_INTEGER CurrentOffset;
1405 CurrentOffset.QuadPart = ChunkOffset;
1407 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, 0);
1408 }
1409 ToReadPageBits >>= 1;
1410 ChunkOffset += PAGE_SIZE;
1411 }
1413 IoFreeMdl(Mdl);;
1414 return Status;
1415 }
1416
1417AssignPagesToSegment:
1419
1420 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1421 {
1422 ULONG_PTR Entry = MAKE_SSE(Pages[i] << PAGE_SHIFT, 0);
1423 LARGE_INTEGER CurrentOffset;
1424 CurrentOffset.QuadPart = ChunkOffset + (i * PAGE_SIZE);
1425
1427
1428 if (SetDirty)
1430
1431 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, Entry);
1432 }
1433
1435
1436 IoFreeMdl(Mdl);
1437 ToReadPageBits >>= BitSet;
1438 ChunkOffset += BitSet * PAGE_SIZE;
1439 }
1440 }
1441
1442 return STATUS_SUCCESS;
1443}
ULONG ReadLength
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
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 GLint GLint j
Definition: glfuncs.h:250
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
@ Failed
Definition: arc.h:79
ULONG * PPFN_NUMBER
Definition: ke.h:9
#define FO_RANDOM_ACCESS
Definition: iotypes.h:1796
@ WrPageIn
Definition: ketypes.h:424
#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 4479 of file section.c.

4482{
4484
4485 SectionOffset.QuadPart = 0;
4486
4488}
_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:4492

Referenced by ExpInitNls(), IntGdiAddFontResourceSingle(), 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 4492 of file section.c.

4499{
4500 PSECTION Section = SectionObject;
4504
4506
4507 PAGED_CODE();
4508
4510 {
4512 &MmSession,
4513 MappedBase,
4514 ViewSize,
4516 }
4517
4518 DPRINT("MmMapViewInSystemSpaceEx() called\n");
4519
4520 /* unsupported for now */
4521 ASSERT(Section->u.Flags.Image == 0);
4522
4523 Section = SectionObject;
4525
4526 if (*ViewSize == 0)
4527 {
4528 LONGLONG MapSizeLL;
4529
4530 /* Page-align the mapping */
4531 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4532
4533 if (!NT_SUCCESS(RtlLongLongSub(Section->SizeOfSection.QuadPart, SectionOffset->QuadPart, &MapSizeLL)))
4535
4536 if (!NT_SUCCESS(RtlLongLongToSIZET(MapSizeLL, ViewSize)))
4538 }
4539 else
4540 {
4541 LONGLONG HelperLL;
4542
4543 /* Get the map end */
4544 if (!NT_SUCCESS(RtlLongLongAdd(SectionOffset->QuadPart, *ViewSize, &HelperLL)))
4546
4547 /* Round it up, if needed */
4548 if (HelperLL % PAGE_SIZE)
4549 {
4550 if (!NT_SUCCESS(RtlLongLongAdd(HelperLL, PAGE_SIZE - (HelperLL % PAGE_SIZE), &HelperLL)))
4552 }
4553
4554 /* Now that we have the mapping end, we can align down its start */
4555 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4556
4557 /* Get the new size */
4558 if (!NT_SUCCESS(RtlLongLongSub(HelperLL, SectionOffset->QuadPart, &HelperLL)))
4560
4561 if (!NT_SUCCESS(RtlLongLongToSIZET(HelperLL, ViewSize)))
4563 }
4564
4566
4568
4570
4572 Section->u.Flags.Image,
4573 Segment,
4574 MappedBase,
4575 *ViewSize,
4577 SectionOffset->QuadPart,
4578 SEC_RESERVE);
4579
4582
4583 return Status;
4584}
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:1039
MMSESSION MmSession
Definition: section.c:107
#define PAGED_CODE()
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#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:3380

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 2531 of file section.c.

2541{
2544 PSECTION Section;
2545 PCONTROL_AREA ControlArea;
2546 ULONG ProtectionMask;
2548 ULONG64 CalculatedViewSize;
2549 PAGED_CODE();
2550
2551 /* Get the segment and control area */
2552 Section = (PSECTION)SectionObject;
2553 ControlArea = Section->Segment->ControlArea;
2554
2555 /* These flags/states are not yet supported by ARM3 */
2556 ASSERT(Section->u.Flags.Image == 0);
2557 ASSERT(Section->u.Flags.NoCache == 0);
2558 ASSERT(Section->u.Flags.WriteCombined == 0);
2559 ASSERT(ControlArea->u.Flags.PhysicalMemory == 0);
2560
2561 /* FIXME */
2562 if ((AllocationType & MEM_RESERVE) != 0)
2563 {
2564 DPRINT1("MmMapViewOfArm3Section called with MEM_RESERVE, this is not implemented yet!!!\n");
2566 }
2567
2568 /* Check if the mapping protection is compatible with the create */
2570 {
2571 DPRINT1("Mapping protection is incompatible\n");
2573 }
2574
2575 /* Check if the offset and size would cause an overflow */
2576 if (((ULONG64)SectionOffset->QuadPart + *ViewSize) <
2577 (ULONG64)SectionOffset->QuadPart)
2578 {
2579 DPRINT1("Section offset overflows\n");
2581 }
2582
2583 /* Check if the offset and size are bigger than the section itself */
2584 if (((ULONG64)SectionOffset->QuadPart + *ViewSize) >
2585 (ULONG64)Section->SizeOfSection.QuadPart)
2586 {
2587 DPRINT1("Section offset is larger than section\n");
2589 }
2590
2591 /* Check if the caller did not specify a view size */
2592 if (!(*ViewSize))
2593 {
2594 /* Compute it for the caller */
2595 CalculatedViewSize = Section->SizeOfSection.QuadPart -
2596 SectionOffset->QuadPart;
2597
2598 /* Check if it's larger than 4GB or overflows into kernel-mode */
2599 if (!NT_SUCCESS(RtlULongLongToSIZET(CalculatedViewSize, ViewSize)) ||
2600 (((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)*BaseAddress) < CalculatedViewSize))
2601 {
2602 DPRINT1("Section view won't fit\n");
2604 }
2605 }
2606
2607 /* Check if the commit size is larger than the view size */
2608 if (CommitSize > *ViewSize)
2609 {
2610 DPRINT1("Attempting to commit more than the view itself\n");
2612 }
2613
2614 /* Check if the view size is larger than the section */
2615 if (*ViewSize > (ULONG64)Section->SizeOfSection.QuadPart)
2616 {
2617 DPRINT1("The view is larger than the section\n");
2619 }
2620
2621 /* Compute and validate the protection mask */
2622 ProtectionMask = MiMakeProtectionMask(Protect);
2623 if (ProtectionMask == MM_INVALID_PROTECTION)
2624 {
2625 DPRINT1("The protection is invalid\n");
2627 }
2628
2629 /* We only handle pagefile-backed sections, which cannot be writecombined */
2631 {
2632 DPRINT1("Cannot write combine a pagefile-backed section\n");
2634 }
2635
2636 /* Start by attaching to the current process if needed */
2638 {
2640 Attached = TRUE;
2641 }
2642
2643 /* Do the actual mapping */
2644 Status = MiMapViewOfDataSection(ControlArea,
2645 Process,
2648 ViewSize,
2649 Section,
2651 ProtectionMask,
2652 CommitSize,
2653 ZeroBits,
2655
2656 /* Detach if needed, then return status */
2658 return Status;
2659}
static NTSTATUS 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:1151
static BOOLEAN MiIsProtectionCompatible(IN ULONG SectionPageProtection, IN ULONG NewSectionPageProtection)
Definition: section.c:117
_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:1768
#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:493
static BOOL Attached
Definition: vidbios.c:3905
KAPC_STATE
Definition: ketypes.h:1588

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 4005 of file section.c.

4015{
4016 PSECTION Section;
4019 BOOLEAN NotAtBase = FALSE;
4020 BOOLEAN IsAttached = FALSE;
4022
4024 {
4025 DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
4027 Process,
4029 ZeroBits,
4030 CommitSize,
4032 ViewSize,
4035 Protect);
4036 }
4037
4038 ASSERT(Process);
4039
4041 {
4043 }
4044
4046 {
4048 IsAttached = TRUE;
4049 }
4050
4051 /* FIXME: We should keep this, but it would break code checking equality */
4052 Protect &= ~PAGE_NOCACHE;
4053
4054 Section = SectionObject;
4055 AddressSpace = &Process->Vm;
4056
4057 if (Section->u.Flags.NoChange)
4059
4061
4062 if (Section->u.Flags.Image)
4063 {
4064 ULONG i;
4065 ULONG NrSegments;
4066 ULONG_PTR ImageBase;
4067 SIZE_T ImageSize;
4068 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
4069 PMM_SECTION_SEGMENT SectionSegments;
4070
4071 ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
4072 SectionSegments = ImageSectionObject->Segments;
4073 NrSegments = ImageSectionObject->NrSegments;
4074
4075 ASSERT(ImageSectionObject->RefCount > 0);
4076
4077 ImageBase = (ULONG_PTR)*BaseAddress;
4078 if (ImageBase == 0)
4079 {
4080 ImageBase = (ULONG_PTR)ImageSectionObject->BasedAddress;
4081 }
4082
4083 ImageSize = 0;
4084 for (i = 0; i < NrSegments; i++)
4085 {
4086 ULONG_PTR MaxExtent;
4087 MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
4088 SectionSegments[i].Length.QuadPart);
4089 ImageSize = max(ImageSize, MaxExtent);
4090 }
4091
4092 ImageSectionObject->ImageInformation.ImageFileSize = (ULONG)ImageSize;
4093
4094 /* Check for an illegal base address */
4095 if (((ImageBase + ImageSize) > (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS) ||
4096 ((ImageBase + ImageSize) < ImageSize))
4097 {
4098 ASSERT(*BaseAddress == NULL);
4099 ImageBase = ALIGN_DOWN_BY((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - ImageSize,
4101 NotAtBase = TRUE;
4102 }
4103 else if (ImageBase != ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY))
4104 {
4105 ASSERT(*BaseAddress == NULL);
4106 ImageBase = ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY);
4107 NotAtBase = TRUE;
4108 }
4109
4110 /* Check there is enough space to map the section at that point. */
4111 if (!MmIsAddressRangeFree(AddressSpace, (PVOID)ImageBase, PAGE_ROUND_UP(ImageSize)))
4112 {
4113 /* Fail if the user requested a fixed base address. */
4114 if ((*BaseAddress) != NULL)
4115 {
4117 goto Exit;
4118 }
4119 /* Otherwise find a gap to map the image. */
4121 if (ImageBase == 0)
4122 {
4124 goto Exit;
4125 }
4126 /* Remember that we loaded image at a different base address */
4127 NotAtBase = TRUE;
4128 }
4129
4130 for (i = 0; i < NrSegments; i++)
4131 {
4132 PVOID SBaseAddress = (PVOID)
4133 ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4134 MmLockSectionSegment(&SectionSegments[i]);
4136 TRUE,
4137 &SectionSegments[i],
4138 &SBaseAddress,
4139 SectionSegments[i].Length.QuadPart,
4140 SectionSegments[i].Protection,
4141 0,
4142 0);
4143 MmUnlockSectionSegment(&SectionSegments[i]);
4144 if (!NT_SUCCESS(Status))
4145 {
4146 /* roll-back */
4147 while (i--)
4148 {
4149 SBaseAddress = ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4150 MmLockSectionSegment(&SectionSegments[i]);
4151 MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
4152 MmUnlockSectionSegment(&SectionSegments[i]);
4153 }
4154
4155 goto Exit;
4156 }
4157 }
4158
4159 *BaseAddress = (PVOID)ImageBase;
4160 *ViewSize = ImageSize;
4161
4162 DPRINT("Mapped %p for section pointer %p\n", ImageSectionObject, ImageSectionObject->FileObject->SectionObjectPointer);
4163
4164 /* One more map */
4165 InterlockedIncrement(&ImageSectionObject->MapCount);
4166 }
4167 else
4168 {
4170 LONGLONG ViewOffset;
4171
4172 ASSERT(Segment->RefCount > 0);
4173
4174 /* check for write access */
4177 {
4179 goto Exit;
4180 }
4181 /* check for read access */
4184 {
4186 goto Exit;
4187 }
4188 /* check for execute access */
4191 {
4193 goto Exit;
4194 }
4195
4196 if (SectionOffset == NULL)
4197 {
4198 ViewOffset = 0;
4199 }
4200 else
4201 {
4202 SectionOffset->QuadPart &= ~(PAGE_SIZE - 1);
4203 ViewOffset = SectionOffset->QuadPart;
4204 }
4205
4206 /* Check if the offset and size would cause an overflow */
4207 if (((ULONG64)ViewOffset + *ViewSize) < (ULONG64)ViewOffset)
4208 {
4209 DPRINT1("Section offset overflows\n");
4211 goto Exit;
4212 }
4213
4214 /* Check if the offset and size are bigger than the section itself */
4215 if (((ULONG64)ViewOffset + *ViewSize) > (ULONG64)Section->SizeOfSection.QuadPart)
4216 {
4217 /* This is allowed for physical memory sections and kernel mode callers */
4218 if (!Section->u.Flags.PhysicalMemory || (ExGetPreviousMode() == UserMode))
4219 {
4220 DPRINT1("Section offset and size are larger than section\n");
4222 goto Exit;
4223 }
4224 }
4225
4226 if ((*ViewSize) == 0)
4227 {
4228 /* Calculate a view size and make sure it doesn't overflow a SIZE_T */
4229 ULONG64 CalculatedSize = Section->SizeOfSection.QuadPart - ViewOffset;
4230 if (CalculatedSize > SIZE_T_MAX)
4231 {
4232 DPRINT1("ViewSize is larger than SIZE_T_MAX\n");
4234 goto Exit;
4235 }
4236
4237 *ViewSize = (SIZE_T)CalculatedSize;
4238 }
4239 else if ((ExGetPreviousMode() == UserMode) &&
4240 (((*ViewSize)+ViewOffset) > Section->SizeOfSection.QuadPart) &&
4241 (!Section->u.Flags.Reserve))
4242 {
4243 /* Dubious */
4244 (*ViewSize) = MIN(Section->SizeOfSection.QuadPart - ViewOffset, SIZE_T_MAX - PAGE_SIZE);
4245 }
4246
4248
4251 FALSE,
4252 Segment,
4254 *ViewSize,
4255 Protect,
4256 ViewOffset,
4259 if (!NT_SUCCESS(Status))
4260 {
4261 goto Exit;
4262 }
4263 }
4264
4265 if (NotAtBase)
4267 else
4269
4270Exit:
4271
4273
4274 if (IsAttached)
4275 {
4277 }
4278
4279 return Status;
4280}
#define ALIGN_DOWN_BY(size, align)
#define MIN(x, y)
Definition: rdesktop.h:171
#define SIZE_T_MAX
Definition: dhcpd.h:91
#define UserMode
Definition: asm.h:39
#define MEM_TOP_DOWN
Definition: nt_native.h:1321
#define PAGE_EXECUTE
Definition: nt_native.h:1306
#define MM_VIRTMEM_GRANULARITY
Definition: mm.h:102
struct _MM_IMAGE_SECTION_OBJECT * PMM_IMAGE_SECTION_OBJECT
#define PAGE_FLAGS_VALID_FOR_SECTION
Definition: mm.h:139
BOOLEAN NTAPI MmIsAddressRangeFree(_In_ PMMSUPPORT AddressSpace, _In_ PVOID Address, _In_ ULONG_PTR Length)
Definition: marea.c:111
PVOID NTAPI MmFindGap(PMMSUPPORT AddressSpace, SIZE_T Length, ULONG_PTR Granularity, BOOLEAN TopDown)
Definition: marea.c:190
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:261
#define STATUS_IMAGE_NOT_AT_BASE
Definition: ntstatus.h:117
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: section.c:2531
#define max(a, b)
Definition: svc.c:63

Referenced by _Function_class_(), _Success_(), ExpInitNls(), GDI_MapHandleTable(), IntMapDesktopView(), IntUserHeapCreate(), MapGlobalUserHeap(), MiLoadImageSection(), MmCreatePeb(), MmInitializeProcessAddressSpace(), NtMapViewOfSection(), NtSecureConnectPort(), and PspMapSystemDll().

◆ MmMapViewOfSegment()

static NTSTATUS MmMapViewOfSegment ( PMMSUPPORT  AddressSpace,
BOOLEAN  AsImage,
PMM_SECTION_SEGMENT  Segment,
PVOID BaseAddress,
SIZE_T  ViewSize,
ULONG  Protect,
LONGLONG  ViewOffset,
ULONG  AllocationType 
)
static

Definition at line 3380 of file section.c.

3389{
3390 PMEMORY_AREA MArea;
3392 ULONG Granularity;
3393
3394 ASSERT(ViewSize != 0);
3395
3396 if (Segment->WriteCopy)
3397 {
3398 /* We have to do this because the not present fault
3399 * and access fault handlers depend on the protection
3400 * that should be granted AFTER the COW fault takes
3401 * place to be in Region->Protect. The not present fault
3402 * handler changes this to the correct protection for COW when
3403 * mapping the pages into the process's address space. If a COW
3404 * fault takes place, the access fault handler sets the page protection
3405 * to these values for the newly copied pages
3406 */
3407 if (Protect == PAGE_WRITECOPY)
3409 else if (Protect == PAGE_EXECUTE_WRITECOPY)
3411 }
3412
3413 if (*BaseAddress == NULL)
3414 Granularity = MM_ALLOCATION_GRANULARITY;
3415 else
3416 Granularity = PAGE_SIZE;
3417
3418#ifdef NEWCC
3419 if (Segment->Flags & MM_DATAFILE_SEGMENT)
3420 {
3422 FileOffset.QuadPart = ViewOffset;
3423 ObReferenceObject(Section);
3425 }
3426#endif
3430 ViewSize,
3431 Protect,
3432 &MArea,
3434 Granularity);
3435 if (!NT_SUCCESS(Status))
3436 {
3437 DPRINT1("Mapping between 0x%p and 0x%p failed (%X).\n",
3438 (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status);
3439 return Status;
3440 }
3441
3442 InterlockedIncrement64(Segment->ReferenceCount);
3443
3444 MArea->SectionData.Segment = Segment;
3445 MArea->SectionData.ViewOffset = ViewOffset;
3446 if (AsImage)
3447 {
3449 }
3450
3451 MmInitializeRegion(&MArea->SectionData.RegionListHead,
3452 ViewSize, 0, Protect);
3453
3454 return STATUS_SUCCESS;
3455}
#define MM_ALLOCATION_GRANULARITY
Definition: mmtypes.h:36
NTSTATUS NTAPI _MiMapViewOfSegment(PMMSUPPORT AddressSpace, PMM_SECTION_SEGMENT Segment, PVOID *BaseAddress, SIZE_T ViewSize, ULONG Protect, PLARGE_INTEGER ViewOffset, ULONG AllocationType, const char *file, int line)
NTSTATUS NTAPI MmCreateMemoryArea(PMMSUPPORT AddressSpace, ULONG Type, PVOID *BaseAddress, SIZE_T Length, ULONG Protection, PMEMORY_AREA *Result, ULONG AllocationFlags, ULONG AllocationGranularity)
Definition: marea.c:379
VOID NTAPI MmInitializeRegion(PLIST_ENTRY RegionListHead, SIZE_T Length, ULONG Type, ULONG Protect)
Definition: region.c:239

Referenced by MmMapViewInSystemSpaceEx(), and MmMapViewOfSection().

◆ MmNotPresentFaultSectionView()

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

Definition at line 1537 of file section.c.

1541{
1547 ULONG_PTR Entry1;
1550 BOOLEAN HasSwapEntry;
1551 PVOID PAddress;
1553 SWAPENTRY SwapEntry;
1554
1555 ASSERT(Locked);
1556
1557 /*
1558 * There is a window between taking the page fault and locking the
1559 * address space when another thread could load the page so we check
1560 * that.
1561 */
1563 {
1564 return STATUS_SUCCESS;
1565 }
1566
1568 {
1570 }
1571
1572 /*
1573 * Check for the virtual memory area being deleted.
1574 */
1576 {
1577 return STATUS_UNSUCCESSFUL;
1578 }
1579
1580 PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
1581 Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
1582 + MemoryArea->SectionData.ViewOffset;
1583
1584 Segment = MemoryArea->SectionData.Segment;
1586 &MemoryArea->SectionData.RegionListHead,
1587 Address, NULL);
1588 ASSERT(Region != NULL);
1589
1590 /* Check for a NOACCESS mapping */
1591 if (Region->Protect & PAGE_NOACCESS)
1592 {
1594 }
1595
1596 if (Region->Protect & PAGE_GUARD)
1597 {
1598 /* Remove it */
1600 &MemoryArea->SectionData.RegionListHead,
1601 Address, PAGE_SIZE, Region->Type, Region->Protect & ~PAGE_GUARD,
1603
1604 if (!NT_SUCCESS(Status))
1605 {
1606 DPRINT1("Removing PAGE_GUARD protection failed : 0x%08x.\n", Status);
1607 }
1608
1610 }
1611
1612 HasSwapEntry = MmIsPageSwapEntry(Process, Address);
1613
1614 /* See if we should use a private page */
1615 if (HasSwapEntry)
1616 {
1617 SWAPENTRY DummyEntry;
1618
1619 MmGetPageFileMapping(Process, Address, &SwapEntry);
1620 if (SwapEntry == MM_WAIT_ENTRY)
1621 {
1626 }
1627
1629 if (Process) MI_SET_PROCESS2(Process->ImageFileName);
1630 if (!Process) MI_SET_PROCESS2("Kernel Section");
1632 if (!NT_SUCCESS(Status))
1633 {
1634 return STATUS_NO_MEMORY;
1635 }
1636
1637 /*
1638 * Must be private page we have swapped out.
1639 */
1640
1641 /*
1642 * Sanity check
1643 */
1645 ASSERT(DummyEntry == SwapEntry);
1646
1647 /* Tell everyone else we are serving the fault. */
1648 MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
1649
1651
1652 Status = MmReadFromSwapPage(SwapEntry, Page);
1653 if (!NT_SUCCESS(Status))
1654 {
1655 DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
1656 KeBugCheck(MEMORY_MANAGEMENT);
1657 }
1658
1660 MmDeletePageFileMapping(Process, PAddress, &DummyEntry);
1661 ASSERT(DummyEntry == MM_WAIT_ENTRY);
1662
1664 PAddress,
1665 Region->Protect,
1666 Page);
1667 if (!NT_SUCCESS(Status))
1668 {
1669 DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
1670 KeBugCheck(MEMORY_MANAGEMENT);
1671 return Status;
1672 }
1673
1674 /*
1675 * Store the swap entry for later use.
1676 */
1677 MmSetSavedSwapEntryPage(Page, SwapEntry);
1678
1679 /*
1680 * Add the page to the process's working set
1681 */
1683 /*
1684 * Finish the operation
1685 */
1686 DPRINT("Address 0x%p\n", Address);
1687 return STATUS_SUCCESS;
1688 }
1689
1690 /*
1691 * Lock the segment
1692 */
1694
1695 /*
1696 * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
1697 */
1698 if ((*Segment->Flags) & MM_PHYSICALMEMORY_SEGMENT)
1699 {
1701 /*
1702 * Just map the desired physical page
1703 */
1704 Page = (PFN_NUMBER)(Offset.QuadPart >> PAGE_SHIFT);
1706 PAddress,
1707 Region->Protect,
1708 Page);
1709 if (!NT_SUCCESS(Status))
1710 {
1711 DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
1712 KeBugCheck(MEMORY_MANAGEMENT);
1713 return Status;
1714 }
1715
1716 /*
1717 * Cleanup and release locks
1718 */
1719 DPRINT("Address 0x%p\n", Address);
1720 return STATUS_SUCCESS;
1721 }
1722
1723 /*
1724 * Check if this page needs to be mapped COW
1725 */
1726 if ((Segment->WriteCopy) &&
1727 (Region->Protect == PAGE_READWRITE || Region->Protect == PAGE_EXECUTE_READWRITE))
1728 {
1730 }
1731 else
1732 {
1733 Attributes = Region->Protect;
1734 }
1735
1736
1737 /*
1738 * Get the entry corresponding to the offset within the section
1739 */
1741 if (Entry == 0)
1742 {
1743 /*
1744 * If the entry is zero, then we need to load the page.
1745 */
1746 if ((Offset.QuadPart >= (LONGLONG)PAGE_ROUND_UP(Segment->RawLength.QuadPart)) && (MemoryArea->VadNode.u.VadFlags.VadType == VadImageMap))
1747 {
1748 /* We are beyond the data which is on file. Just get a new page. */
1750 if (Process) MI_SET_PROCESS2(Process->ImageFileName);
1751 if (!Process) MI_SET_PROCESS2("Kernel Section");
1753 if (!NT_SUCCESS(Status))
1754 {
1756 return STATUS_NO_MEMORY;
1757 }
1760
1762 if (!NT_SUCCESS(Status))
1763 {
1764 DPRINT1("Unable to create virtual mapping\n");
1765 KeBugCheck(MEMORY_MANAGEMENT);
1766 }
1767 ASSERT(MmIsPagePresent(Process, PAddress));
1768 if (Process)
1770
1771 DPRINT("Address 0x%p\n", Address);
1772 return STATUS_SUCCESS;
1773 }
1774
1777
1778 /* The data must be paged in. Lock the file, so that the VDL doesn't get updated behind us. */
1780
1781 PFSRTL_COMMON_FCB_HEADER FcbHeader = Segment->FileObject->FsContext;
1782
1784
1785 FsRtlReleaseFile(Segment->FileObject);
1786
1787 /* Lock address space again */
1789 if (!NT_SUCCESS(Status))
1790 {
1791 if (Status == STATUS_NO_MEMORY)
1792 {
1793 return Status;
1794 }
1795 /* Damn */
1796 DPRINT1("Failed to page data in!\n");
1797 return STATUS_IN_PAGE_ERROR;
1798 }
1799
1800 /* Everything went fine. Restart the operation */
1802 }
1803 else if (IS_SWAP_FROM_SSE(Entry))
1804 {
1805 SWAPENTRY SwapEntry;
1806
1807 SwapEntry = SWAPENTRY_FROM_SSE(Entry);
1808
1809 /* See if a page op is running on this segment. */
1810 if (SwapEntry == MM_WAIT_ENTRY)
1811 {
1817 }
1818
1820 if (!NT_SUCCESS(Status))
1821 {
1823 return STATUS_NO_MEMORY;
1824 }
1825
1826 /*
1827 * Release all our locks and read in the page from disk
1828 */
1831
1833
1834 Status = MmReadFromSwapPage(SwapEntry, Page);
1835 if (!NT_SUCCESS(Status))
1836 {
1837 KeBugCheck(MEMORY_MANAGEMENT);
1838 }
1839
1840 /*
1841 * Relock the address space and segment
1842 */
1845
1846 /*
1847 * Check the entry. No one should change the status of a page
1848 * that has a pending page-in.
1849 */
1851 if (Entry1 != MAKE_SWAP_SSE(MM_WAIT_ENTRY))
1852 {
1853 DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
1854 KeBugCheck(MEMORY_MANAGEMENT);
1855 }
1856
1857 /*
1858 * Save the swap entry.
1859 */
1860 MmSetSavedSwapEntryPage(Page, SwapEntry);
1861
1862 /* Map the page into the process address space */
1864 PAddress,
1865 Attributes,
1866 Page);
1867 if (!NT_SUCCESS(Status))
1868 {
1869 DPRINT1("Unable to create virtual mapping\n");
1870 KeBugCheck(MEMORY_MANAGEMENT);
1871 }
1872 if (Process)
1874
1875 /*
1876 * Mark the offset within the section as having valid, in-memory
1877 * data
1878 */
1879 Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
1882
1883 DPRINT("Address 0x%p\n", Address);
1884 return STATUS_SUCCESS;
1885 }
1886 else
1887 {
1888 /* We already have a page on this section offset. Map it into the process address space. */
1890
1892 PAddress,
1893 Attributes,
1894 Page);
1895 if (!NT_SUCCESS(Status))
1896 {
1897 DPRINT1("Unable to create virtual mapping\n");
1898 KeBugCheck(MEMORY_MANAGEMENT);
1899 }
1900
1901 if (Process)
1903
1904 /* Take a reference on it */
1907
1908 DPRINT("Address 0x%p\n", Address);
1909 return STATUS_SUCCESS;
1910 }
1911}
#define MI_SET_PROCESS2(x)
Definition: mm.h:328
@ MI_USAGE_SECTION
Definition: mm.h:342
BOOLEAN NTAPI MmIsPageSwapEntry(struct _EPROCESS *Process, PVOID Address)
#define SWAPENTRY_FROM_SSE(E)
Definition: mm.h:1371
NTSTATUS NTAPI MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
Definition: pagefile.c:204
VOID NTAPI MmDeletePageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY *SwapEntry)
#define MI_SET_USAGE(x)
Definition: mm.h:326
NTSTATUS NTAPI MmCreatePhysicalMapping(_Inout_opt_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG flProtect, _In_ PFN_NUMBER Page)
Definition: page.c:735
NTSTATUS NTAPI MmCreatePageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY SwapEntry)
#define STATUS_MM_RESTART_OPERATION
Definition: mm.h:104
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:182
VOID NTAPI MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
Definition: section.c:1064
LARGE_INTEGER ValidDataLength
Definition: env_spec_w32.h:757
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes

Referenced by MmAccessFaultSectionView(), and MmNotPresentFault().

◆ MmpCloseSection()

VOID NTAPI MmpCloseSection ( IN PEPROCESS Process  OPTIONAL,
IN PVOID  Object,
IN ACCESS_MASK  GrantedAccess,
IN ULONG  ProcessHandleCount,
IN ULONG  SystemHandleCount 
)

Definition at line 2204 of file section.c.

2209{
2210 DPRINT("MmpCloseSection(OB %p, HC %lu)\n", Object, ProcessHandleCount);
2211}
@ ProcessHandleCount
Definition: winternl.h:876
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object

Referenced by MmInitSectionImplementation().

◆ MmpDeleteSection()

VOID NTAPI MmpDeleteSection ( PVOID  ObjectBody)

Definition at line 2151 of file section.c.

2152{
2153 PSECTION Section = ObjectBody;
2154
2155 /* Check if it's an ARM3, or ReactOS section */
2156 if (!MiIsRosSectionObject(Section))
2157 {
2158 MiDeleteARM3Section(ObjectBody);
2159 return;
2160 }
2161
2162 DPRINT("MmpDeleteSection(ObjectBody %p)\n", ObjectBody);
2163 if (Section->u.Flags.Image)
2164 {
2165 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)Section->Segment;
2166
2167 /*
2168 * NOTE: Section->ImageSection can be NULL for short time
2169 * during the section creating. If we fail for some reason
2170 * until the image section is properly initialized we shouldn't
2171 * process further here.
2172 */
2173 if (Section->Segment == NULL)
2174 return;
2175
2176 KIRQL OldIrql = MiAcquirePfnLock();
2177 ImageSectionObject->SectionCount--;
2178
2179 /* We just dereference the first segment */
2180 ASSERT(ImageSectionObject->RefCount > 0);
2181 /* MmDereferenceSegmentWithLock releases PFN lock */
2182 MmDereferenceSegmentWithLock(ImageSectionObject->Segments, OldIrql);
2183 }
2184 else
2185 {
2187
2188 /*
2189 * NOTE: Section->Segment can be NULL for short time
2190 * during the section creating.
2191 */
2192 if (Segment == NULL)
2193 return;
2194
2195 KIRQL OldIrql = MiAcquirePfnLock();
2196 Segment->SectionCount--;
2197
2198 /* MmDereferenceSegmentWithLock releases PFN lock */
2199 MmDereferenceSegmentWithLock(Segment, OldIrql);
2200 }
2201}
VOID NTAPI MiDeleteARM3Section(PVOID ObjectBody)
Definition: section.c:2951

Referenced by MmInitSectionImplementation().

◆ MmpFreePageFileSegment()

VOID NTAPI MmpFreePageFileSegment ( PMM_SECTION_SEGMENT  Segment)

Definition at line 917 of file section.c.

918{
922 SWAPENTRY SavedSwapEntry;
924
925 Page = 0;
926
928
929 Length = PAGE_ROUND_UP(Segment->Length.QuadPart);
930 for (Offset.QuadPart = 0; Offset.QuadPart < Length; Offset.QuadPart += PAGE_SIZE)
931 {
933 if (Entry)
934 {
937 {
939 }
940 else
941 {
943 SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
944 if (SavedSwapEntry != 0)
945 {
947 MmFreeSwapPage(SavedSwapEntry);
948 }
950 }
951 }
952 }
953
955}

Referenced by _When_().

◆ MmProtectSectionView()

NTSTATUS NTAPI MmProtectSectionView ( PMMSUPPORT  AddressSpace,
PMEMORY_AREA  MemoryArea,
PVOID  BaseAddress,
SIZE_T  Length,
ULONG  Protect,
PULONG  OldProtect 
)

Definition at line 2068 of file section.c.

2074{
2077 ULONG_PTR MaxLength;
2078
2080
2082 {
2083 return STATUS_UNSUCCESSFUL;
2084 }
2085
2087 if (Length > MaxLength)
2088 Length = (ULONG)MaxLength;
2089
2091 &MemoryArea->SectionData.RegionListHead,
2092 BaseAddress, NULL);
2093 ASSERT(Region != NULL);
2094
2095 if ((MemoryArea->Flags & SEC_NO_CHANGE) &&
2096 Region->Protect != Protect)
2097 {
2099 }
2100
2101 if (OldProtect != NULL)
2102 *OldProtect = Region->Protect;
2104 &MemoryArea->SectionData.RegionListHead,
2107
2108 return Status;
2109}
#define MA_GetEndingAddress(_MemoryArea)
Definition: mm.h:250
ULONG Flags
Definition: mm.h:257

Referenced by MiProtectVirtualMemory().

◆ MmPurgeSegment()

BOOLEAN NTAPI MmPurgeSegment ( _In_ PSECTION_OBJECT_POINTERS  SectionObjectPointer,
_In_opt_ PLARGE_INTEGER  Offset,
_In_ ULONG  Length 
)

Definition at line 4880 of file section.c.

4884{
4885 LARGE_INTEGER PurgeStart, PurgeEnd;
4887
4888 PurgeStart.QuadPart = Offset ? Offset->QuadPart : 0LL;
4889 if (Length && Offset)
4890 {
4891 if (!NT_SUCCESS(RtlLongLongAdd(PurgeStart.QuadPart, Length, &PurgeEnd.QuadPart)))
4892 return FALSE;
4893 }
4894
4896 if (!Segment)
4897 {
4898 /* Nothing to purge */
4899 return TRUE;
4900 }
4901
4903
4904 if (!Length || !Offset)
4905 {
4906 /* We must calculate the length for ourselves */
4907 /* FIXME: All of this is suboptimal */
4908 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
4909 if (!ElemCount)
4910 {
4911 /* No page. Nothing to purge */
4913 MmDereferenceSegment(Segment);
4914 return TRUE;
4915 }
4916
4918 PurgeEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
4919 }
4920
4921 /* Find byte offset of the page to start */
4922 PurgeStart.QuadPart = PAGE_ROUND_DOWN_64(PurgeStart.QuadPart);
4923
4924 while (PurgeStart.QuadPart < PurgeEnd.QuadPart)
4925 {
4927
4928 if (Entry == 0)
4929 {
4930 PurgeStart.QuadPart += PAGE_SIZE;
4931 continue;
4932 }
4933
4935 {
4936 ASSERT(SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY);
4937 /* The page is currently being read. Meaning someone will need it soon. Bad luck */
4939 MmDereferenceSegment(Segment);
4940 return FALSE;
4941 }
4942
4943 if (IS_WRITE_SSE(Entry))
4944 {
4945 /* We're trying to purge an entry which is being written. Restart this loop iteration */
4949 continue;
4950 }
4951
4952 if (SHARE_COUNT_FROM_SSE(Entry) > 0)
4953 {
4954 /* This page is currently in use. Bad luck */
4956 MmDereferenceSegment(Segment);
4957 return FALSE;
4958 }
4959
4960 /* We can let this page go */
4961 MmSetPageEntrySectionSegment(Segment, &PurgeStart, 0);
4963
4964 PurgeStart.QuadPart += PAGE_SIZE;
4965 }
4966
4967 /* This page is currently in use. Bad luck */
4969 MmDereferenceSegment(Segment);
4970 return TRUE;
4971}
#define LL
Definition: tui.h:166

Referenced by CcPurgeCacheSection().

◆ MmQuerySectionView()

NTSTATUS NTAPI MmQuerySectionView ( PMEMORY_AREA  MemoryArea,
PVOID  Address,
PMEMORY_BASIC_INFORMATION  Info,
PSIZE_T  ResultLength 
)

Definition at line 2112 of file section.c.

2116{
2118 PVOID RegionBaseAddress;
2120
2122 &MemoryArea->SectionData.RegionListHead,
2123 Address, &RegionBaseAddress);
2124 if (Region == NULL)
2125 {
2126 return STATUS_UNSUCCESSFUL;
2127 }
2128
2130 {
2131 Segment = MemoryArea->SectionData.Segment;
2132 Info->AllocationBase = (PUCHAR)MA_GetStartingAddress(MemoryArea) - Segment->Image.VirtualAddress;
2133 Info->Type = MEM_IMAGE;
2134 }
2135 else
2136 {
2137 Info->AllocationBase = (PVOID)MA_GetStartingAddress(MemoryArea);
2138 Info->Type = MEM_MAPPED;
2139 }
2140 Info->BaseAddress = RegionBaseAddress;
2142 Info->RegionSize = Region->Length;
2143 Info->State = MEM_COMMIT;
2144 Info->Protect = Region->Protect;
2145
2147 return STATUS_SUCCESS;
2148}
#define MEM_IMAGE
Definition: mmtypes.h:89
struct _MEMORY_BASIC_INFORMATION MEMORY_BASIC_INFORMATION
#define MEM_MAPPED
Definition: nt_native.h:1319
#define MEM_COMMIT
Definition: nt_native.h:1313
const ULONG MmProtectToValue[32]
Definition: page.c:71
ULONG_PTR Protection
Definition: mmtypes.h:696
unsigned char * PUCHAR
Definition: typedefs.h:53
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776

Referenced by MiQueryMemoryBasicInformation().

◆ MmSharePageEntrySectionSegment()

VOID NTAPI MmSharePageEntrySectionSegment ( PMM_SECTION_SEGMENT  Segment,
PLARGE_INTEGER  Offset 
)

Definition at line 1064 of file section.c.

1066{
1068
1070 if (Entry == 0)
1071 {
1072 DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
1073 KeBugCheck(MEMORY_MANAGEMENT);
1074 }
1076 {
1077 DPRINT1("Maximum share count reached\n");
1078 KeBugCheck(MEMORY_MANAGEMENT);
1079 }
1081 {
1082 KeBugCheck(MEMORY_MANAGEMENT);
1083 }
1085}
#define MAX_SHARE_COUNT
Definition: mm.h:1384
#define BUMPREF_SSE(E)
Definition: mm.h:1386

Referenced by MmNotPresentFaultSectionView().

◆ MmspAssertSegmentsNoOverlap()

static VOID NTAPI MmspAssertSegmentsNoOverlap ( IN PMM_IMAGE_SECTION_OBJECT  ImageSectionObject)
static

Definition at line 2718 of file section.c.

2719{
2720 ULONG i;
2721
2722 MmspAssertSegmentsSorted(ImageSectionObject);
2723
2724 for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2725 {
2726 ASSERT(ImageSectionObject->Segments[i].Length.QuadPart > 0);
2727
2728 if(i > 0)
2729 {
2730 ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
2731 (ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
2732 ImageSectionObject->Segments[i - 1].Length.QuadPart));
2733 }
2734 }
2735}
static VOID NTAPI MmspAssertSegmentsSorted(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2704

Referenced by MmspCheckSegmentBounds().

◆ MmspAssertSegmentsPageAligned()

static VOID NTAPI MmspAssertSegmentsPageAligned ( IN PMM_IMAGE_SECTION_OBJECT  ImageSectionObject)
static

Definition at line 2740 of file section.c.

2741{
2742 ULONG i;
2743
2744 for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2745 {
2746 ASSERT((ImageSectionObject->Segments[i].Image.VirtualAddress % PAGE_SIZE) == 0);
2747 ASSERT((ImageSectionObject->Segments[i].Length.QuadPart % PAGE_SIZE) == 0);
2748 }
2749}

Referenced by MmspPageAlignSegments().

◆ MmspAssertSegmentsSorted()

static VOID NTAPI MmspAssertSegmentsSorted ( IN PMM_IMAGE_SECTION_OBJECT  ImageSectionObject)
static

Definition at line 2704 of file section.c.

2705{
2706 ULONG i;
2707
2708 for( i = 1; i < ImageSectionObject->NrSegments; ++ i )
2709 {
2710 ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
2711 ImageSectionObject->Segments[i - 1].Image.VirtualAddress);
2712 }
2713}

Referenced by MmspAssertSegmentsNoOverlap(), and MmspSortSegments().

◆ MmspCheckSegmentBounds()

static BOOLEAN NTAPI MmspCheckSegmentBounds ( IN OUT PMM_IMAGE_SECTION_OBJECT  ImageSectionObject,
IN ULONG  Flags 
)
static

Definition at line 2800 of file section.c.

2805{
2806 ULONG i;
2807
2809 {
2810 MmspAssertSegmentsNoOverlap(ImageSectionObject);
2811 return TRUE;
2812 }
2813
2814 ASSERT(ImageSectionObject->NrSegments >= 1);
2815
2816 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2817 {
2818 if(ImageSectionObject->Segments[i].Length.QuadPart == 0)
2819 {
2820 return FALSE;
2821 }
2822
2823 if(i > 0)
2824 {
2825 /*
2826 * TODO: relax the limitation on gaps. For example, gaps smaller than a
2827 * page could be OK (Windows seems to be OK with them), and larger gaps
2828 * could lead to image sections spanning several discontiguous regions
2829 * (NtMapViewOfSection could then refuse to map them, and they could
2830 * e.g. only be allowed as parameters to NtCreateProcess, like on UNIX)
2831 */
2832 if ((ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
2833 ImageSectionObject->Segments[i - 1].Length.QuadPart) !=
2834 ImageSectionObject->Segments[i].Image.VirtualAddress)
2835 {
2836 return FALSE;
2837 }
2838 }
2839 }
2840
2841 return TRUE;
2842}
#define EXEFMT_LOAD_ASSUME_SEGMENTS_NO_OVERLAP
Definition: exeformat.h:9
static VOID NTAPI MmspAssertSegmentsNoOverlap(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2718

Referenced by ExeFmtpCreateImageSection().

◆ MmspCompareSegments()

static int __cdecl MmspCompareSegments ( const void x,
const void y 
)
static

Definition at line 2755 of file section.c.

2757{
2758 const MM_SECTION_SEGMENT *Segment1 = (const MM_SECTION_SEGMENT *)x;
2759 const MM_SECTION_SEGMENT *Segment2 = (const MM_SECTION_SEGMENT *)y;
2760
2761 if (Segment1->Image.VirtualAddress > Segment2->Image.VirtualAddress)
2762 return 1;
2763 else if (Segment1->Image.VirtualAddress < Segment2->Image.VirtualAddress)
2764 return -1;
2765 else
2766 return 0;
2767}
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548

Referenced by MmspSortSegments().

◆ MmspPageAlignSegments()

static BOOLEAN NTAPI MmspPageAlignSegments ( IN OUT PMM_IMAGE_SECTION_OBJECT  ImageSectionObject,
IN ULONG  Flags 
)
static

Definition at line 2851 of file section.c.

2856{
2857 ULONG i;
2858 ULONG LastSegment;
2859 PMM_SECTION_SEGMENT EffectiveSegment;
2860
2862 {
2863 MmspAssertSegmentsPageAligned(ImageSectionObject);
2864 return TRUE;
2865 }
2866
2867 LastSegment = 0;
2868 EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
2869
2870 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2871 {
2872 /*
2873 * The first segment requires special handling
2874 */
2875 if (i == 0)
2876 {
2878 ULONG_PTR VirtualOffset;
2879
2880 VirtualAddress = EffectiveSegment->Image.VirtualAddress;
2881
2882 /* Round down the virtual address to the nearest page */
2883 EffectiveSegment->Image.VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
2884
2885 /* Round up the virtual size to the nearest page */
2886 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length.QuadPart) -
2887 EffectiveSegment->Image.VirtualAddress;
2888
2889 /* Adjust the raw address and size */
2890 VirtualOffset = VirtualAddress - EffectiveSegment->Image.VirtualAddress;
2891
2892 if (EffectiveSegment->Image.FileOffset < VirtualOffset)
2893 {
2894 return FALSE;
2895 }
2896
2897 /*
2898 * Garbage in, garbage out: unaligned base addresses make the file
2899 * offset point in curious and odd places, but that's what we were
2900 * asked for
2901 */
2902 EffectiveSegment->Image.FileOffset -= VirtualOffset;
2903 EffectiveSegment->RawLength.QuadPart += VirtualOffset;
2904 }
2905 else
2906 {
2907 PMM_SECTION_SEGMENT Segment = &ImageSectionObject->Segments[i];
2908 ULONG_PTR EndOfEffectiveSegment;
2909
2910 EndOfEffectiveSegment = (ULONG_PTR)(EffectiveSegment->Image.VirtualAddress + EffectiveSegment->Length.QuadPart);
2911 ASSERT((EndOfEffectiveSegment % PAGE_SIZE) == 0);
2912
2913 /*
2914 * The current segment begins exactly where the current effective
2915 * segment ended, therefore beginning a new effective segment
2916 */
2917 if (EndOfEffectiveSegment == Segment->Image.VirtualAddress)
2918 {
2919 LastSegment ++;
2920 ASSERT(LastSegment <= i);
2921 ASSERT(LastSegment < ImageSectionObject->NrSegments);
2922
2923 EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
2924
2925 if (LastSegment != i)
2926 {
2927 /*
2928 * Copy the current segment. If necessary, the effective segment
2929 * will be expanded later
2930 */
2931 *EffectiveSegment = *Segment;
2932 }
2933
2934 /*
2935 * Page-align the virtual size. We know for sure the virtual address
2936 * already is
2937 */
2938 ASSERT((EffectiveSegment->Image.VirtualAddress % PAGE_SIZE) == 0);
2939 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(EffectiveSegment->Length.QuadPart);
2940 }
2941 /*
2942 * The current segment is still part of the current effective segment:
2943 * extend the effective segment to reflect this
2944 */
2945 else if (EndOfEffectiveSegment > Segment->Image.VirtualAddress)
2946 {
2947 static const ULONG FlagsToProtection[16] =
2948 {
2965 };
2966
2967 unsigned ProtectionFlags;
2968
2969 /*
2970 * Extend the file size
2971 */
2972
2973 /* Unaligned segments must be contiguous within the file */
2974 if (Segment->Image.FileOffset != (EffectiveSegment->Image.FileOffset +
2975 EffectiveSegment->RawLength.QuadPart))
2976 {
2977 return FALSE;
2978 }
2979
2980 EffectiveSegment->RawLength.QuadPart += Segment->RawLength.QuadPart;
2981
2982 /*
2983 * Extend the virtual size
2984 */
2985 ASSERT(PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) >= EndOfEffectiveSegment);
2986
2987 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) -
2988 EffectiveSegment->Image.VirtualAddress;
2989
2990 /*
2991 * Merge the protection
2992 */
2993 EffectiveSegment->Protection |= Segment->Protection;
2994
2995 /* Clean up redundance */
2996 ProtectionFlags = 0;
2997
2998 if(EffectiveSegment->Protection & PAGE_IS_READABLE)
2999 ProtectionFlags |= 1 << 0;
3000
3001 if(EffectiveSegment->Protection & PAGE_IS_WRITABLE)
3002 ProtectionFlags |= 1 << 1;
3003
3004 if(EffectiveSegment->Protection & PAGE_IS_EXECUTABLE)
3005 ProtectionFlags |= 1 << 2;
3006
3007 if(EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
3008 ProtectionFlags |= 1 << 3;
3009
3010 ASSERT(ProtectionFlags < 16);
3011 EffectiveSegment->Protection = FlagsToProtection[ProtectionFlags];
3012
3013 /* If a segment was required to be shared and cannot, fail */
3014 if(!(Segment->Protection & PAGE_IS_WRITECOPY) &&
3015 EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
3016 {
3017 return FALSE;
3018 }
3019 }
3020 /*
3021 * We assume no holes between segments at this point
3022 */
3023 else
3024 {
3025 KeBugCheck(MEMORY_MANAGEMENT);
3026 }
3027 }
3028 }
3029 ImageSectionObject->NrSegments = LastSegment + 1;
3030
3031 return TRUE;
3032}
#define EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED
Definition: exeformat.h:10
#define PAGE_IS_READABLE
Definition: mm.h:150
static VOID NTAPI MmspAssertSegmentsPageAligned(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2740
LARGE_INTEGER RawLength
Definition: mm.h:205
ULONG Protection
Definition: mm.h:209
LARGE_INTEGER Length
Definition: mm.h:206
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress

Referenced by ExeFmtpCreateImageSection().

◆ MmspSortSegments()

static VOID NTAPI MmspSortSegments ( IN OUT PMM_IMAGE_SECTION_OBJECT  ImageSectionObject,
IN ULONG  Flags 
)
static

Definition at line 2775 of file section.c.

2777{
2779 {
2780 MmspAssertSegmentsSorted(ImageSectionObject);
2781 }
2782 else
2783 {
2784 qsort(ImageSectionObject->Segments,
2785 ImageSectionObject->NrSegments,
2786 sizeof(ImageSectionObject->Segments[0]),
2788 }
2789}
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))
#define EXEFMT_LOAD_ASSUME_SEGMENTS_SORTED
Definition: exeformat.h:8
static int __cdecl MmspCompareSegments(const void *x, const void *y)
Definition: section.c:2755

Referenced by ExeFmtpCreateImageSection().

◆ MmspWaitForFileLock()

NTSTATUS MmspWaitForFileLock ( PFILE_OBJECT  File)

Definition at line 907 of file section.c.

908{
909 return STATUS_SUCCESS;
910 //return KeWaitForSingleObject(&File->Lock, 0, KernelMode, FALSE, NULL);
911}

Referenced by MmCreateDataFileSection(), and MmCreateImageSection().

◆ MmUnmapViewOfSegment()

static NTSTATUS MmUnmapViewOfSegment ( PMMSUPPORT  AddressSpace,
PVOID  BaseAddress 
)
static

Definition at line 3543 of file section.c.

3545{
3549 PLIST_ENTRY CurrentEntry;
3550 PMM_REGION CurrentRegion;
3551 PLIST_ENTRY RegionListHead;
3552
3554 BaseAddress);
3555 if (MemoryArea == NULL)
3556 {
3557 return STATUS_UNSUCCESSFUL;
3558 }
3559
3560 Segment = MemoryArea->SectionData.Segment;
3561
3562#ifdef NEWCC
3563 if (Segment->Flags & MM_DATAFILE_SEGMENT)
3564 {
3568
3569 return Status;
3570 }
3571#endif
3572
3574
3576
3577 RegionListHead = &MemoryArea->SectionData.RegionListHead;
3578 while (!IsListEmpty(RegionListHead))
3579 {
3580 CurrentEntry = RemoveHeadList(RegionListHead);
3581 CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
3582 ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
3583 }
3584
3585 if ((*Segment->Flags) & MM_PHYSICALMEMORY_SEGMENT)
3586 {
3588 MemoryArea,
3589 NULL,
3590 NULL);
3591 }
3592 else
3593 {
3595 MemoryArea,
3597 AddressSpace);
3598 }
3600 MmDereferenceSegment(Segment);
3601 return Status;
3602}
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
NTSTATUS NTAPI MmUnmapViewOfCacheSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
NTSTATUS NTAPI MmFreeMemoryArea(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_FREE_PAGE_FUNC FreePage, PVOID FreePageContext)
Definition: marea.c:258
static VOID MmFreeSectionPage(PVOID Context, MEMORY_AREA *MemoryArea, PVOID Address, PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
Definition: section.c:3459
Definition: typedefs.h:120
#define TAG_MM_REGION
Definition: tag.h:110

Referenced by MiRosUnmapViewInSystemSpace(), MiRosUnmapViewOfSection(), and MmMapViewOfSection().

◆ MmUnsharePageEntrySectionSegment()

BOOLEAN NTAPI MmUnsharePageEntrySectionSegment ( PMEMORY_AREA  MemoryArea,
PMM_SECTION_SEGMENT  Segment,
PLARGE_INTEGER  Offset,
BOOLEAN  Dirty,
BOOLEAN  PageOut,
ULONG_PTR InEntry 
)

Definition at line 1089 of file section.c.

1095{
1098 BOOLEAN IsDataMap = BooleanFlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT);
1099 SWAPENTRY SwapEntry;
1100
1101 if (Entry == 0)
1102 {
1103 DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
1104 KeBugCheck(MEMORY_MANAGEMENT);
1105 }
1106 if (SHARE_COUNT_FROM_SSE(Entry) == 0)
1107 {
1108 DPRINT1("Zero share count for unshare (Seg %p Offset %x Page %x)\n", Segment, Offset->LowPart, PFN_FROM_SSE(Entry));
1109 KeBugCheck(MEMORY_MANAGEMENT);
1110 }
1112 {
1113 KeBugCheck(MEMORY_MANAGEMENT);
1114 }
1116 if (Dirty) Entry = DIRTY_SSE(Entry);
1117
1118 /* If we are paging-out, pruning the page for real will be taken care of in MmCheckDirtySegment */
1119 if ((SHARE_COUNT_FROM_SSE(Entry) > 0) || PageOut)
1120 {
1121 /* Update the page mapping in the segment and we're done */
1123 return FALSE;
1124 }
1125
1126 /* We are pruning the last mapping on this page. See if we can keep it a bit more. */
1127 ASSERT(!PageOut);
1128
1129 if (IsDataMap)
1130 {
1131 /* We can always keep memory in for data maps */
1133 return FALSE;
1134 }
1135
1136 if (!FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED))
1137 {
1138 ASSERT(Segment->WriteCopy);
1141 /* So this must have been a read-only page. Keep it ! */
1143 return FALSE;
1144 }
1145
1146 /*
1147 * So this is a page for a shared section of a DLL.
1148 * We can keep it if it is not dirty.
1149 */
1150 SwapEntry = MmGetSavedSwapEntryPage(Page);
1151 if ((SwapEntry == 0) && !IS_DIRTY_SSE(Entry))
1152 {
1154 return FALSE;
1155 }
1156
1157 /* No more processes are referencing this shared dirty page. Ditch it. */
1158 if (SwapEntry)
1159 {
1161 MmFreeSwapPage(SwapEntry);
1162 }
1165 return TRUE;
1166}
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define DECREF_SSE(E)
Definition: mm.h:1387

Referenced by MmAccessFaultSectionView(), MmFreeSectionPage(), and MmPageOutPhysicalAddress().

◆ NtQuerySection()

NTSTATUS NTAPI NtQuerySection ( _In_ HANDLE  SectionHandle,
_In_ SECTION_INFORMATION_CLASS  SectionInformationClass,
_Out_ PVOID  SectionInformation,
_In_ SIZE_T  SectionInformationLength,
_Out_opt_ PSIZE_T  ResultLength 
)

Queries the information of a section object.

Parameters
SectionHandleHandle to the section object. It must be opened with SECTION_QUERY access.
SectionInformationClassIndex to a certain information structure. Can be either SectionBasicInformation or SectionImageInformation. The latter is valid only for sections that were created with the SEC_IMAGE flag.
SectionInformationCaller supplies storage for resulting information.
LengthSize of the supplied storage.
ResultLengthData written.
Returns
Status.

@implemented

Definition at line 3786 of file section.c.

3792{
3793 PSECTION Section;
3796 PAGED_CODE();
3797
3799 if (PreviousMode != KernelMode)
3800 {
3801 _SEH2_TRY
3802 {
3803 ProbeForWrite(SectionInformation,
3804 SectionInformationLength,
3805 __alignof(ULONG));
3806 if (ResultLength != NULL)
3807 {
3809 sizeof(*ResultLength),
3810 __alignof(SIZE_T));
3811 }
3812 }
3814 {
3816 }
3817 _SEH2_END;
3818 }
3819
3820 if (SectionInformationClass == SectionBasicInformation)
3821 {
3822 if (SectionInformationLength < sizeof(SECTION_BASIC_INFORMATION))
3823 {
3825 }
3826 }
3827 else if (SectionInformationClass == SectionImageInformation)
3828 {
3829 if (SectionInformationLength < sizeof(SECTION_IMAGE_INFORMATION))
3830 {
3832 }
3833 }
3834 else
3835 {
3837 }
3838
3839 Status = ObReferenceObjectByHandle(SectionHandle,
3843 (PVOID*)(PVOID)&Section,
3844 NULL);
3845 if (!NT_SUCCESS(Status))
3846 {
3847 DPRINT1("Failed to reference section: 0x%lx\n", Status);
3848 return Status;
3849 }
3850
3851 switch(SectionInformationClass)
3852 {
3854 {
3855 SECTION_BASIC_INFORMATION Sbi = { 0 };
3856
3857 Sbi.Size = Section->SizeOfSection;
3858 Sbi.BaseAddress = NULL;
3859
3860 if (Section->u.Flags.File)
3861 Sbi.Attributes |= SEC_FILE;
3862 if (Section->u.Flags.Image)
3863 Sbi.Attributes |= SEC_IMAGE;
3864 if (Section->u.Flags.Commit)
3865 Sbi.Attributes |= SEC_COMMIT;
3866 if (Section->u.Flags.Reserve)
3867 Sbi.Attributes |= SEC_RESERVE;
3868 if (Section->u.Flags.Based)
3869 Sbi.Attributes |= SEC_BASED;
3870
3871 if (Section->u.Flags.Image)
3872 {
3873 if (!MiIsRosSectionObject(Section))
3874 {
3875 /* Not supported yet */
3876 ASSERT(FALSE);
3877 }
3878 }
3879 else if (MiIsRosSectionObject(Section))
3880 {
3881 Sbi.BaseAddress = (PVOID)((PMM_SECTION_SEGMENT)Section->Segment)->Image.VirtualAddress;
3882 }
3883 else
3884 {
3885 Sbi.BaseAddress = Section->Segment->BasedAddress;
3886 }
3887
3888 _SEH2_TRY
3889 {
3890 *((SECTION_BASIC_INFORMATION*)SectionInformation) = Sbi;
3891 if (ResultLength != NULL)
3892 {
3893 *ResultLength = sizeof(Sbi);
3894 }
3895 }
3897 {
3899 }
3900 _SEH2_END;
3901 break;
3902 }
3904 {
3905 if (!Section->u.Flags.Image)
3906 {
3908 }
3909 else if (MiIsRosSectionObject(Section))
3910 {
3911 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
3912
3913 _SEH2_TRY
3914 {
3916 *Sii = ImageSectionObject->ImageInformation;
3917 if (ResultLength != NULL)
3918 {
3919 *ResultLength = sizeof(*Sii);
3920 }
3921 }
3923 {
3925 }
3926 _SEH2_END;
3927 }
3928 else
3929 {
3930 _SEH2_TRY
3931 {
3933 *Sii = *Section->Segment->u2.ImageInformation;
3934 if (ResultLength != NULL)
3935 *ResultLength = sizeof(*Sii);
3936 }
3938 {
3940 }
3941 _SEH2_END;
3942 }
3943 break;
3944 }
3945 default:
3946 DPRINT1("Unknown SectionInformationClass: %d\n", SectionInformationClass);
3948 }
3949
3950 ObDereferenceObject(Section);
3951
3952 return Status;
3953}
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
struct _SECTION_IMAGE_INFORMATION * PSECTION_IMAGE_INFORMATION
#define SEC_FILE
Definition: mmtypes.h:96
@ SectionBasicInformation
Definition: mmtypes.h:195
@ SectionImageInformation
Definition: mmtypes.h:196
#define SECTION_QUERY
Definition: nt_native.h:1287
#define STATUS_SECTION_NOT_IMAGE
Definition: ntstatus.h:309
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:181
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:184
LARGE_INTEGER Size
Definition: mmtypes.h:336
union _SEGMENT::@2789 u2
PSECTION_IMAGE_INFORMATION ImageInformation
Definition: mmtypes.h:426
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133

Referenced by CreateProcessInternalW(), get_binary_type(), QuerySbi(), and Test_SectionBasicInformation().

◆ PeFmtCreateSection()

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 
)

Definition at line 285 of file section.c.

292{
293 NTSTATUS nStatus;
294 ULONG cbFileHeaderOffsetSize = 0;
295 ULONG cbSectionHeadersOffset = 0;
296 ULONG cbSectionHeadersSize;
297 ULONG cbSectionHeadersOffsetSize = 0;
298 ULONG cbOptHeaderSize;
299 ULONG cbHeadersSize = 0;
300 ULONG nSectionAlignment;
301 ULONG nFileAlignment;
302 ULONG_PTR ImageBase = 0;
303 const IMAGE_DOS_HEADER * pidhDosHeader;
304 const IMAGE_NT_HEADERS32 * pinhNtHeader;
305 const IMAGE_OPTIONAL_HEADER32 * piohOptHeader;
306 const IMAGE_SECTION_HEADER * pishSectionHeaders;
307 PMM_SECTION_SEGMENT pssSegments;
308 LARGE_INTEGER lnOffset;
310 SIZE_T nPrevVirtualEndOfSegment = 0;
311 ULONG nFileSizeOfHeaders = 0;
312 ULONG i;
313 ULONG AlignedLength;
314
315 ASSERT(FileHeader);
316 ASSERT(FileHeaderSize > 0);
317 ASSERT(File);
318 ASSERT(ImageSectionObject);
319 ASSERT(ReadFileCb);
320 ASSERT(AllocateSegmentsCb);
321
322 ASSERT(Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize));
323
324 ASSERT(((UINT_PTR)FileHeader % TYPE_ALIGNMENT(IMAGE_DOS_HEADER)) == 0);
325
326#define DIE(ARGS_) { DPRINT ARGS_; goto l_Return; }
327
328 pBuffer = NULL;
329 pidhDosHeader = FileHeader;
330
331 /* DOS HEADER */
333
334 /* image too small to be an MZ executable */
335 if(FileHeaderSize < sizeof(IMAGE_DOS_HEADER))
336 DIE(("Too small to be an MZ executable, size is %lu\n", FileHeaderSize));
337
338 /* no MZ signature */
339 if(pidhDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
340 DIE(("No MZ signature found, e_magic is %hX\n", pidhDosHeader->e_magic));
341
342 /* NT HEADER */
344
345 /* not a Windows executable */
346 if(pidhDosHeader->e_lfanew <= 0)
347 DIE(("Not a Windows executable, e_lfanew is %d\n", pidhDosHeader->e_lfanew));
348
349 if(!Intsafe_AddULong32(&cbFileHeaderOffsetSize, pidhDosHeader->e_lfanew, RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader)))
350 DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
351
352 if(FileHeaderSize < cbFileHeaderOffsetSize)
353 pinhNtHeader = NULL;
354 else
355 {
356 /*
357 * we already know that Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize),
358 * and FileHeaderSize >= cbFileHeaderOffsetSize, so this holds true too
359 */
360 ASSERT(Intsafe_CanOffsetPointer(FileHeader, pidhDosHeader->e_lfanew));
361 pinhNtHeader = (PVOID)((UINT_PTR)FileHeader + pidhDosHeader->e_lfanew);
362 }
363
364 /*
365 * the buffer doesn't contain the NT file header, or the alignment is wrong: we
366 * need to read the header from the file
367 */
368 if(FileHeaderSize < cbFileHeaderOffsetSize ||
369 (UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
370 {
371 ULONG cbNtHeaderSize;
372 ULONG cbReadSize;
373 PVOID pData;
374
375l_ReadHeaderFromFile:
376 cbNtHeaderSize = 0;
377 lnOffset.QuadPart = pidhDosHeader->e_lfanew;
378
379 /* read the header from the file */
380 nStatus = ReadFileCb(File, &lnOffset, sizeof(IMAGE_NT_HEADERS64), &pData, &pBuffer, &cbReadSize);
381
382 if(!NT_SUCCESS(nStatus))
383 {
384 NTSTATUS ReturnedStatus = nStatus;
385
386 /* If it attempted to read past the end of the file, it means e_lfanew is invalid */
387 if (ReturnedStatus == STATUS_END_OF_FILE) nStatus = STATUS_INVALID_IMAGE_PROTECT;
388
389 DIE(("ReadFile failed, status %08X\n", ReturnedStatus));
390 }
391
392 ASSERT(pData);
394 ASSERT(cbReadSize > 0);
395
397
398 /* the buffer doesn't contain the file header */
399 if(cbReadSize < RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader))
400 DIE(("The file doesn't contain the PE file header\n"));
401
402 pinhNtHeader = pData;
403
404 /* object still not aligned: copy it to the beginning of the buffer */
405 if((UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
406 {
408 RtlMoveMemory(pBuffer, pData, cbReadSize);
409 pinhNtHeader = pBuffer;
410 }
411
412 /* invalid NT header */
414
415 if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
416 DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
417
419
420 if(!Intsafe_AddULong32(&cbNtHeaderSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
421 DIE(("The full NT header is too large\n"));
422
423 /* the buffer doesn't contain the whole NT header */
424 if(cbReadSize < cbNtHeaderSize)
425 DIE(("The file doesn't contain the full NT header\n"));
426 }
427 else
428 {
429 ULONG cbOptHeaderOffsetSize = 0;
430
432
433 /* don't trust an invalid NT header */
434 if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
435 DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
436
437 if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
438 DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
439
441
442 if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, cbOptHeaderOffsetSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
443 DIE(("The NT header is too large, SizeOfOptionalHeader is %X\n", pinhNtHeader->FileHeader.SizeOfOptionalHeader));
444
445 /* the buffer doesn't contain the whole NT header: read it from the file */
446 if(cbOptHeaderOffsetSize > FileHeaderSize)
447 goto l_ReadHeaderFromFile;
448 }
449
450 /* read information from the NT header */
451 piohOptHeader = &pinhNtHeader->OptionalHeader;
452 cbOptHeaderSize = pinhNtHeader->FileHeader.SizeOfOptionalHeader;
453
455
456 if(!RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Magic))
457 DIE(("The optional header doesn't contain the Magic field, SizeOfOptionalHeader is %X\n", cbOptHeaderSize));
458
459 /* ASSUME: RtlZeroMemory(ImageSectionObject, sizeof(*ImageSectionObject)); */
460
461 switch(piohOptHeader->Magic)
462 {
464#ifndef _WIN64
466 DIE(("Win64 optional header, unsupported\n"));
467#else
468 // Fall through.
469#endif
471 break;
472 default:
473 DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
474 }
475
476 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SectionAlignment) &&
477 RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, FileAlignment))
478 {
479 /* See [1], section 3.4.2 */
480 if(piohOptHeader->SectionAlignment < PAGE_SIZE)
481 {
482 if(piohOptHeader->FileAlignment != piohOptHeader->SectionAlignment)
483 DIE(("Sections aren't page-aligned and the file alignment isn't the same\n"));
484 }
485 else if(piohOptHeader->SectionAlignment < piohOptHeader->FileAlignment)
486 DIE(("The section alignment is smaller than the file alignment\n"));
487
488 nSectionAlignment = piohOptHeader->SectionAlignment;
489 nFileAlignment = piohOptHeader->FileAlignment;
490
491 if(!IsPowerOf2(nSectionAlignment) || !IsPowerOf2(nFileAlignment))
492 DIE(("The section alignment (%u) and file alignment (%u) aren't both powers of 2\n", nSectionAlignment, nFileAlignment));
493 }
494 else
495 {
496 nSectionAlignment = PAGE_SIZE;
497 nFileAlignment = PAGE_SIZE;
498 }
499
500 ASSERT(IsPowerOf2(nSectionAlignment));
501 ASSERT(IsPowerOf2(nFileAlignment));
502
503 switch(piohOptHeader->Magic)
504 {
505 /* PE32 */
507 {
508 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, ImageBase))
509 ImageBase = piohOptHeader->ImageBase;
510
511 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfImage))
512 ImageSectionObject->ImageInformation.ImageFileSize = piohOptHeader->SizeOfImage;
513
514 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackReserve))
515 ImageSectionObject->ImageInformation.MaximumStackSize = piohOptHeader->SizeOfStackReserve;
516
517 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackCommit))
518 ImageSectionObject->ImageInformation.CommittedStackSize = piohOptHeader->SizeOfStackCommit;
519
520 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Subsystem))
521 {
522 ImageSectionObject->ImageInformation.SubSystemType = piohOptHeader->Subsystem;
523
524 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
525 RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MajorSubsystemVersion))
526 {
527 ImageSectionObject->ImageInformation.SubSystemMinorVersion = piohOptHeader->MinorSubsystemVersion;
528 ImageSectionObject->ImageInformation.SubSystemMajorVersion = piohOptHeader->MajorSubsystemVersion;
529 }
530 }
531
532 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
533 {
534 ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
535 piohOptHeader->AddressOfEntryPoint);
536 }
537
538 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfCode))
539 ImageSectionObject->ImageInformation.ImageContainsCode = piohOptHeader->SizeOfCode != 0;
540 else
541 ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
542
543 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
544 {
545 if (piohOptHeader->AddressOfEntryPoint == 0)
546 {
547 ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
548 }
549 }
550
551 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, LoaderFlags))
552 ImageSectionObject->ImageInformation.LoaderFlags = piohOptHeader->LoaderFlags;
553
554 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, DllCharacteristics))
555 {
556 ImageSectionObject->ImageInformation.DllCharacteristics = piohOptHeader->DllCharacteristics;
557
558 /*
559 * Since we don't really implement SxS yet and LD doesn't supoprt /ALLOWISOLATION:NO, hard-code
560 * this flag here, which will prevent the loader and other code from doing any .manifest or SxS
561 * magic to any binary.
562 *
563 * This will break applications that depend on SxS when running with real Windows Kernel32/SxS/etc
564 * but honestly that's not tested. It will also break them when running no ReactOS once we implement
565 * the SxS support -- at which point, duh, this should be removed.
566 *
567 * But right now, any app depending on SxS is already broken anyway, so this flag only helps.
568 */
569 ImageSectionObject->ImageInformation.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NO_ISOLATION;
570 }
571
572 break;
573 }
574#ifdef _WIN64
575 /* PE64 */
577 {
578 const IMAGE_OPTIONAL_HEADER64 * pioh64OptHeader;
579
580 pioh64OptHeader = (const IMAGE_OPTIONAL_HEADER64 *)piohOptHeader;
581
582 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, ImageBase))
583 {
584 ImageBase = pioh64OptHeader->ImageBase;
585 if(pioh64OptHeader->ImageBase > MAXULONG_PTR)
586 DIE(("ImageBase exceeds the address space\n"));
587 }
588
589 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfImage))
590 {
591 if(pioh64OptHeader->SizeOfImage > MAXULONG_PTR)
592 DIE(("SizeOfImage exceeds the address space\n"));
593
594 ImageSectionObject->ImageInformation.ImageFileSize = pioh64OptHeader->SizeOfImage;
595 }
596
597 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackReserve))
598 {
599 if(pioh64OptHeader->SizeOfStackReserve > MAXULONG_PTR)
600 DIE(("SizeOfStackReserve exceeds the address space\n"));
601
602 ImageSectionObject->ImageInformation.MaximumStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackReserve;
603 }
604
605 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackCommit))
606 {
607 if(pioh64OptHeader->SizeOfStackCommit > MAXULONG_PTR)
608 DIE(("SizeOfStackCommit exceeds the address space\n"));
609
610 ImageSectionObject->ImageInformation.CommittedStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackCommit;
611 }
612
613 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, Subsystem))
614 {
615 ImageSectionObject->ImageInformation.SubSystemType = pioh64OptHeader->Subsystem;
616
617 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
618 RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MajorSubsystemVersion))
619 {
620 ImageSectionObject->ImageInformation.SubSystemMinorVersion = pioh64OptHeader->MinorSubsystemVersion;
621 ImageSectionObject->ImageInformation.SubSystemMajorVersion = pioh64OptHeader->MajorSubsystemVersion;
622 }
623 }
624
625 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
626 {
627 ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
628 pioh64OptHeader->AddressOfEntryPoint);
629 }
630
631 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfCode))
632 ImageSectionObject->ImageInformation.ImageContainsCode = pioh64OptHeader->SizeOfCode != 0;
633 else
634 ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
635
636 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
637 {
638 if (pioh64OptHeader->AddressOfEntryPoint == 0)
639 {
640 ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
641 }
642 }
643
644 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, LoaderFlags))
645 ImageSectionObject->ImageInformation.LoaderFlags = pioh64OptHeader->LoaderFlags;
646
647 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, DllCharacteristics))
648 ImageSectionObject->ImageInformation.DllCharacteristics = pioh64OptHeader->DllCharacteristics;
649
650 break;
651 }
652#endif // _WIN64
653 }
654
655 /* [1], section 3.4.2 */
656 if((ULONG_PTR)ImageBase % 0x10000)
657 DIE(("ImageBase is not aligned on a 64KB boundary"));
658
659 ImageSectionObject->ImageInformation.ImageCharacteristics = pinhNtHeader->FileHeader.Characteristics;
660 ImageSectionObject->ImageInformation.Machine = pinhNtHeader->FileHeader.Machine;
661 ImageSectionObject->ImageInformation.GpValue = 0;
662 ImageSectionObject->ImageInformation.ZeroBits = 0;
663 ImageSectionObject->BasedAddress = (PVOID)ImageBase;
664
665 /* SECTION HEADERS */
667
668 /* see [1], section 3.3 */
669 if(pinhNtHeader->FileHeader.NumberOfSections > 96)
670 DIE(("Too many sections, NumberOfSections is %u\n", pinhNtHeader->FileHeader.NumberOfSections));
671
672 /*
673 * the additional segment is for the file's headers. They need to be present for
674 * the benefit of the dynamic loader (to locate exports, defaults for thread
675 * parameters, resources, etc.)
676 */
677 ImageSectionObject->NrSegments = pinhNtHeader->FileHeader.NumberOfSections + 1;
678
679 /* file offset for the section headers */
680 if(!Intsafe_AddULong32(&cbSectionHeadersOffset, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
681 DIE(("Offset overflow\n"));
682
683 if(!Intsafe_AddULong32(&cbSectionHeadersOffset, cbSectionHeadersOffset, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
684 DIE(("Offset overflow\n"));
685
686 /* size of the section headers */
688 cbSectionHeadersSize = pinhNtHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
689
690 if(!Intsafe_AddULong32(&cbSectionHeadersOffsetSize, cbSectionHeadersOffset, cbSectionHeadersSize))
691 DIE(("Section headers too large\n"));
692
693 /* size of the executable's headers */
694 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfHeaders))
695 {
696// if(!IsAligned(piohOptHeader->SizeOfHeaders, nFileAlignment))
697// DIE(("SizeOfHeaders is not aligned\n"));
698
699 if(cbSectionHeadersSize > piohOptHeader->SizeOfHeaders)
700 DIE(("The section headers overflow SizeOfHeaders\n"));
701
702 cbHeadersSize = piohOptHeader->SizeOfHeaders;
703 }
704 else if(!AlignUp(&cbHeadersSize, cbSectionHeadersOffsetSize, nFileAlignment))
705 DIE(("Overflow aligning the size of headers\n"));
706
707 if(pBuffer)
708 {
710 pBuffer = NULL;
711 }
712 /* WARNING: pinhNtHeader IS NO LONGER USABLE */
713 /* WARNING: piohOptHeader IS NO LONGER USABLE */
714 /* WARNING: pioh64OptHeader IS NO LONGER USABLE */
715
716 if(FileHeaderSize < cbSectionHeadersOffsetSize)
717 pishSectionHeaders = NULL;
718 else
719 {
720 /*
721 * we already know that Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize),
722 * and FileHeaderSize >= cbSectionHeadersOffsetSize, so this holds true too
723 */
724 ASSERT(Intsafe_CanOffsetPointer(FileHeader, cbSectionHeadersOffset));
725 pishSectionHeaders = (PVOID)((UINT_PTR)FileHeader + cbSectionHeadersOffset);
726 }
727
728 /*
729 * the buffer doesn't contain the section headers, or the alignment is wrong:
730 * read the headers from the file
731 */
732 if(FileHeaderSize < cbSectionHeadersOffsetSize ||
733 (UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
734 {
735 PVOID pData;
736 ULONG cbReadSize;
737
738 lnOffset.QuadPart = cbSectionHeadersOffset;
739
740 /* read the header from the file */
741 nStatus = ReadFileCb(File, &lnOffset, cbSectionHeadersSize, &pData, &pBuffer, &cbReadSize);
742
743 if(!NT_SUCCESS(nStatus))
744 DIE(("ReadFile failed with status %08X\n", nStatus));
745
746 ASSERT(pData);
748 ASSERT(cbReadSize > 0);
749
751
752 /* the buffer doesn't contain all the section headers */
753 if(cbReadSize < cbSectionHeadersSize)
754 DIE(("The file doesn't contain all of the section headers\n"));
755
756 pishSectionHeaders = pData;
757
758 /* object still not aligned: copy it to the beginning of the buffer */
759 if((UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
760 {
762 RtlMoveMemory(pBuffer, pData, cbReadSize);
763 pishSectionHeaders = pBuffer;
764 }
765 }
766
767 /* SEGMENTS */
768 /* allocate the segments */
770 ImageSectionObject->Segments = AllocateSegmentsCb(ImageSectionObject->NrSegments);
771
772 if(ImageSectionObject->Segments == NULL)
773 DIE(("AllocateSegments failed\n"));
774
775 /* initialize the headers segment */
776 pssSegments = ImageSectionObject->Segments;
777
778// ASSERT(IsAligned(cbHeadersSize, nFileAlignment));
779
780 if(!AlignUp(&nFileSizeOfHeaders, cbHeadersSize, nFileAlignment))
781 DIE(("Cannot align the size of the section headers\n"));
782
783 nPrevVirtualEndOfSegment = ALIGN_UP_BY(cbHeadersSize, nSectionAlignment);
784 if (nPrevVirtualEndOfSegment < cbHeadersSize)
785 DIE(("Cannot align the size of the section headers\n"));
786
787 pssSegments[0].Image.FileOffset = 0;
788 pssSegments[0].Protection = PAGE_READONLY;
789 pssSegments[0].Length.QuadPart = nPrevVirtualEndOfSegment;
790 pssSegments[0].RawLength.QuadPart = nFileSizeOfHeaders;
791 pssSegments[0].Image.VirtualAddress = 0;
792 pssSegments[0].Image.Characteristics = 0;
793 pssSegments[0].WriteCopy = TRUE;
794
795 /* skip the headers segment */
796 ++ pssSegments;
797
799
800 ASSERT(ImageSectionObject->RefCount > 0);
801
802 /* convert the executable sections into segments. See also [1], section 4 */
803 for(i = 0; i < ImageSectionObject->NrSegments - 1; ++ i)
804 {
805 ULONG nCharacteristics;
806
807 /* validate the alignment */
808 if(!IsAligned(pishSectionHeaders[i].VirtualAddress, nSectionAlignment))
809 DIE(("Image.VirtualAddress[%u] is not aligned\n", i));
810
811 /* sections must be contiguous, ordered by base address and non-overlapping */
812 if(pishSectionHeaders[i].VirtualAddress != nPrevVirtualEndOfSegment)
813 DIE(("Memory gap between section %u and the previous\n", i));
814
815 /* ignore explicit BSS sections */
816 if(pishSectionHeaders[i].PointerToRawData != 0 && pishSectionHeaders[i].SizeOfRawData != 0)
817 {
818 /* validate the alignment */
819#if 0
820 /* Yes, this should be a multiple of FileAlignment, but there's
821 * stuff out there that isn't. We can cope with that
822 */
823 if(!IsAligned(pishSectionHeaders[i].SizeOfRawData, nFileAlignment))
824 DIE(("SizeOfRawData[%u] is not aligned\n", i));
825#endif
826
827// if(!IsAligned(pishSectionHeaders[i].PointerToRawData, nFileAlignment))
828// DIE(("PointerToRawData[%u] is not aligned\n", i));
829
830 if(!Intsafe_CanAddULong32(pishSectionHeaders[i].PointerToRawData, pishSectionHeaders[i].SizeOfRawData))
831 DIE(("SizeOfRawData[%u] too large\n", i));
832
833 /* conversion */
834 pssSegments[i].Image.FileOffset = pishSectionHeaders[i].PointerToRawData;
835 pssSegments[i].RawLength.QuadPart = pishSectionHeaders[i].SizeOfRawData;
836 }
837 else
838 {
839 /* FIXME: Should reset PointerToRawData to 0 in the image mapping */
840 ASSERT(pssSegments[i].Image.FileOffset == 0);
841 ASSERT(pssSegments[i].RawLength.QuadPart == 0);
842 }
843
844 ASSERT(Intsafe_CanAddLong64(pssSegments[i].Image.FileOffset, pssSegments[i].RawLength.QuadPart));
845
846 nCharacteristics = pishSectionHeaders[i].Characteristics;
847
848 /* no explicit protection */
849 if((nCharacteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)) == 0)
850 {
851 if(nCharacteristics & IMAGE_SCN_CNT_CODE)
852 nCharacteristics |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;
853
854 if(nCharacteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
855 nCharacteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
856
857 if(nCharacteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
858 nCharacteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
859 }
860
861 /* see table above */
862 pssSegments[i].Protection = SectionCharacteristicsToProtect[nCharacteristics >> 28];
863 pssSegments[i].WriteCopy = !(nCharacteristics & IMAGE_SCN_MEM_SHARED);
864
865 if(pishSectionHeaders[i].Misc.VirtualSize == 0)
866 pssSegments[i].Length.QuadPart = pishSectionHeaders[i].SizeOfRawData;
867 else
868 pssSegments[i].Length.QuadPart = pishSectionHeaders[i].Misc.VirtualSize;
869
870 AlignedLength = ALIGN_UP_BY(pssSegments[i].Length.LowPart, nSectionAlignment);
871 if(AlignedLength < pssSegments[i].Length.LowPart)
872 DIE(("Cannot align the virtual size of section %u\n", i));
873
874 pssSegments[i].Length.LowPart = AlignedLength;
875
876 if(pssSegments[i].Length.QuadPart == 0)
877 DIE(("Virtual size of section %u is null\n", i));
878
879 pssSegments[i].Image.VirtualAddress = pishSectionHeaders[i].VirtualAddress;
880 pssSegments[i].Image.Characteristics = pishSectionHeaders[i].Characteristics;
881
882 /* ensure the memory image is no larger than 4GB */
883 nPrevVirtualEndOfSegment = (ULONG_PTR)(pssSegments[i].Image.VirtualAddress + pssSegments[i].Length.QuadPart);
884 if (nPrevVirtualEndOfSegment < pssSegments[i].Image.VirtualAddress)
885 DIE(("The image is too large\n"));
886 }
887
888 if(nSectionAlignment >= PAGE_SIZE)
890
891 /* Success */
892 nStatus = STATUS_SUCCESS;// STATUS_ROS_EXEFMT_LOADED_FORMAT | EXEFMT_LOADED_PE32;
893
894l_Return:
895 if(pBuffer)
897
898 return nStatus;
899}
#define ALIGN_UP_BY(size, align)
#define MAXULONG_PTR
Definition: basetsd.h:103
static __inline BOOLEAN IsPowerOf2(IN ULONG Number)
Definition: exeformat.h:134
static __inline BOOLEAN Intsafe_CanAddLong64(IN LONG64 Addend1, IN LONG64 Addend2)
Definition: exeformat.h:104
static __inline BOOLEAN Intsafe_CanMulULong32(IN ULONG Factor1, IN ULONG Factor2)
Definition: exeformat.h:123
static __inline BOOLEAN Intsafe_CanAddULong32(IN ULONG Addend1, IN ULONG Addend2)
Definition: exeformat.h:109
static __inline BOOLEAN IsAligned(IN ULONG Address, IN ULONG Alignment)
Definition: exeformat.h:147
static __inline BOOLEAN Intsafe_CanOffsetPointer(IN CONST VOID *Pointer, IN SIZE_T Offset)
Definition: exeformat.h:128
static __inline BOOLEAN Intsafe_AddULong32(OUT PULONG Result, IN ULONG Addend1, IN ULONG Addend2)
Definition: exeformat.h:114
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
#define TYPE_ALIGNMENT(t)
Definition: ntbasedef.h:117
#define RTL_CONTAINS_FIELD(Struct, Size, Field)
Definition: ntbasedef.h:687
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:684
#define IMAGE_SCN_MEM_WRITE
Definition: ntimage.h:241
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC
Definition: ntimage.h:376
#define IMAGE_SCN_CNT_INITIALIZED_DATA
Definition: ntimage.h:231
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC
Definition: ntimage.h:377
#define IMAGE_SCN_CNT_CODE
Definition: ntimage.h:230
#define IMAGE_SCN_MEM_EXECUTE
Definition: ntimage.h:239
#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION
Definition: ntimage.h:458
#define IMAGE_SCN_MEM_READ
Definition: ntimage.h:240
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA
Definition: ntimage.h:232
#define STATUS_INVALID_IMAGE_WIN_64
Definition: ntstatus.h:901
#define STATUS_INVALID_IMAGE_PROTECT
Definition: ntstatus.h:540
#define IMAGE_NT_SIGNATURE
Definition: pedump.c:93
#define IMAGE_DOS_SIGNATURE
Definition: pedump.c:89
struct _IMAGE_SECTION_HEADER IMAGE_SECTION_HEADER
PVOID pBuffer
static ULONG SectionCharacteristicsToProtect[16]
Definition: section.c:198
#define DIE(ARGS_)
ULONGLONG AlignUp(IN ULONGLONG Value, IN ULONG Alignment)
Definition: partlist.c:79
WORD SizeOfOptionalHeader
Definition: ntddk_ex.h:127
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
USHORT MajorSubsystemVersion
Definition: ntimage.h:356
ULONGLONG SizeOfStackReserve
Definition: ntimage.h:364
USHORT MinorSubsystemVersion
Definition: ntimage.h:357
ULONGLONG SizeOfStackCommit
Definition: ntimage.h:365
union _IMAGE_SECTION_HEADER::@1693 Misc
DWORD PointerToRawData
Definition: pedump.c:290
BOOLEAN WriteCopy
Definition: mm.h:211
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264

Variable Documentation

◆ Entry

◆ ExeFmtpLoaders

PEXEFMT_LOADER ExeFmtpLoaders[]
static
Initial value:
=
{
}
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)
Definition: section.c:285

Definition at line 2590 of file section.c.

Referenced by ExeFmtpCreateImageSection().

◆ FALSE

return FALSE

Definition at line 5346 of file section.c.

◆ ForceDirty

PLARGE_INTEGER BOOLEAN ForceDirty

Definition at line 5178 of file section.c.

◆ MmMakeFileAccess

ACCESS_MASK MmMakeFileAccess[8]
extern

Definition at line 32 of file section.c.

Referenced by MmCreateArm3Section(), and MmCreateSection().

◆ MmpSectionMapping

GENERIC_MAPPING MmpSectionMapping
static
Initial value:
=
{
}
#define SECTION_MAP_READ
Definition: compat.h:139
#define SECTION_MAP_EXECUTE
Definition: nt_native.h:1290
#define SECTION_MAP_WRITE
Definition: nt_native.h:1288
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67

Definition at line 223 of file section.c.

Referenced by MmInitSectionImplementation().

◆ MmSectionObjectType

◆ MmSession

◆ MmSubsectionBase

ULONG_PTR MmSubsectionBase

Definition at line 196 of file section.c.

Referenced by MI_MAKE_SUBSECTION_PTE(), and MiInitMachineDependent().

◆ MmWaitPageEvent

KEVENT MmWaitPageEvent

Definition at line 66 of file section.c.

Referenced by MmInitSystem().

◆ Offset

◆ Page

◆ PageOut

Initial value:

Definition at line 5179 of file section.c.

Referenced by MmUnsharePageEntrySectionSegment().

◆ SectionCharacteristicsToProtect

◆ Status

Definition at line 5182 of file section.c.

◆ TinyTime