ReactOS  0.4.15-dev-5618-g8866b9d
section.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <mm/ARM3/miarm.h>
Include dependency graph for section.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 

Functions

BOOLEAN NTAPI MiIsProtectionCompatible (IN ULONG SectionPageProtection, IN ULONG NewSectionPageProtection)
 
ULONG NTAPI MiMakeProtectionMask (IN ULONG Protect)
 
BOOLEAN NTAPI MiInitializeSystemSpaceMap (IN PMMSESSION InputSession OPTIONAL)
 
PVOID NTAPI MiInsertInSystemSpace (IN PMMSESSION Session, IN ULONG Buckets, IN PCONTROL_AREA ControlArea)
 
static NTSTATUS MiAddMappedPtes (IN PMMPTE FirstPte, IN PFN_NUMBER PteCount, IN PCONTROL_AREA ControlArea, IN LONGLONG SectionOffset)
 
VOID NTAPI MiFillSystemPageDirectory (IN PVOID Base, IN SIZE_T NumberOfBytes)
 
NTSTATUS NTAPI MiCheckPurgeAndUpMapCount (IN PCONTROL_AREA ControlArea, IN BOOLEAN FailIfSystemViews)
 
PSUBSECTION NTAPI MiLocateSubsection (IN PMMVAD Vad, IN ULONG_PTR Vpn)
 
VOID NTAPI MiSegmentDelete (IN PSEGMENT Segment)
 
VOID NTAPI MiCheckControlArea (IN PCONTROL_AREA ControlArea, IN KIRQL OldIrql)
 
VOID NTAPI MiDereferenceControlArea (IN PCONTROL_AREA ControlArea)
 
VOID NTAPI MiRemoveMappedView (IN PEPROCESS CurrentProcess, IN PMMVAD Vad)
 
NTSTATUS NTAPI MiUnmapViewOfSection (IN PEPROCESS Process, IN PVOID BaseAddress, IN ULONG Flags)
 
NTSTATUS NTAPI MiSessionCommitPageTables (IN PVOID StartVa, IN PVOID EndVa)
 
NTSTATUS MiMapViewInSystemSpace (_In_ PVOID Section, _In_ PMMSESSION Session, _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, _Inout_ PSIZE_T ViewSize, _Inout_ PLARGE_INTEGER SectionOffset)
 
VOID NTAPI MiSetControlAreaSymbolsLoaded (IN PCONTROL_AREA ControlArea)
 
VOID NTAPI MiLoadUserSymbols (IN PCONTROL_AREA ControlArea, IN PVOID BaseAddress, IN PEPROCESS Process)
 
NTSTATUS NTAPI MiMapViewOfDataSection (IN PCONTROL_AREA ControlArea, IN PEPROCESS Process, IN PVOID *BaseAddress, IN PLARGE_INTEGER SectionOffset, IN PSIZE_T ViewSize, IN PSECTION Section, IN SECTION_INHERIT InheritDisposition, IN ULONG ProtectionMask, IN SIZE_T CommitSize, IN ULONG_PTR ZeroBits, IN ULONG AllocationType)
 
VOID NTAPI MiSubsectionConsistent (IN PSUBSECTION Subsection)
 
NTSTATUS NTAPI MiCreateDataFileMap (IN PFILE_OBJECT File, OUT PSEGMENT *Segment, IN PSIZE_T MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN ULONG IgnoreFileSizing)
 
static NTSTATUS NTAPI MiCreatePagingFileMap (OUT PSEGMENT *Segment, IN PLARGE_INTEGER MaximumSize, IN ULONG ProtectionMask, IN ULONG AllocationAttributes)
 
NTSTATUS NTAPI MiGetFileObjectForSectionAddress (IN PVOID Address, OUT PFILE_OBJECT *FileObject)
 
PFILE_OBJECT NTAPI MmGetFileObjectForSection (IN PVOID SectionObject)
 
static PFILE_OBJECT MiGetFileObjectForVad (_In_ PMMVAD Vad)
 
VOID NTAPI MmGetImageInformation (OUT PSECTION_IMAGE_INFORMATION ImageInformation)
 
NTSTATUS NTAPI MmGetFileNameForFileObject (IN PFILE_OBJECT FileObject, OUT POBJECT_NAME_INFORMATION *ModuleName)
 
NTSTATUS NTAPI MmGetFileNameForSection (IN PVOID Section, OUT POBJECT_NAME_INFORMATION *ModuleName)
 
NTSTATUS NTAPI MmGetFileNameForAddress (IN PVOID Address, OUT PUNICODE_STRING ModuleName)
 
NTSTATUS NTAPI MiQueryMemorySectionName (IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID MemoryInformation, IN SIZE_T MemoryInformationLength, OUT PSIZE_T ReturnLength)
 
VOID NTAPI MiFlushTbAndCapture (IN PMMVAD FoundVad, IN PMMPTE PointerPte, IN ULONG ProtectionMask, IN PMMPFN Pfn1, IN BOOLEAN UpdateDirty)
 
NTSTATUS NTAPI MiSetProtectionOnSection (IN PEPROCESS Process, IN PMMVAD FoundVad, IN PVOID StartingAddress, IN PVOID EndingAddress, IN ULONG NewProtect, OUT PULONG CapturedOldProtect, IN ULONG DontCharge, OUT PULONG Locked)
 
VOID NTAPI MiRemoveMappedPtes (IN PVOID BaseAddress, IN ULONG NumberOfPtes, IN PCONTROL_AREA ControlArea, IN PMMSUPPORT Ws)
 
ULONG NTAPI MiRemoveFromSystemSpace (IN PMMSESSION Session, IN PVOID Base, OUT PCONTROL_AREA *ControlArea)
 
NTSTATUS NTAPI MiUnmapViewInSystemSpace (IN PMMSESSION Session, IN PVOID MappedBase)
 
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)
 
BOOLEAN NTAPI MmDisableModifiedWriteOfSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer)
 
BOOLEAN NTAPI MmForceSectionClosed (IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN BOOLEAN DelayClose)
 
NTSTATUS NTAPI MmMapViewInSessionSpace (IN PVOID Section, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
 
NTSTATUS NTAPI MmUnmapViewInSessionSpace (IN PVOID MappedBase)
 
NTSTATUS NTAPI MmUnmapViewOfSection (IN PEPROCESS Process, IN PVOID BaseAddress)
 
NTSTATUS NTAPI MmUnmapViewInSystemSpace (IN PVOID MappedBase)
 
NTSTATUS NTAPI MmCommitSessionMappedView (IN PVOID MappedBase, IN SIZE_T ViewSize)
 
VOID NTAPI MiDeleteARM3Section (PVOID ObjectBody)
 
ULONG NTAPI MmDoesFileHaveUserWritableReferences (IN PSECTION_OBJECT_POINTERS SectionPointer)
 
NTSTATUS NTAPI NtAreMappedFilesTheSame (IN PVOID File1MappedAsAnImage, IN PVOID File2MappedAsFile)
 
NTSTATUS NTAPI NtCreateSection (OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize OPTIONAL, IN ULONG SectionPageProtection OPTIONAL, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL)
 
NTSTATUS NTAPI NtOpenSection (OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
 
NTSTATUS NTAPI NtMapViewOfSection (IN HANDLE SectionHandle, IN HANDLE ProcessHandle, 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)
 
NTSTATUS NTAPI NtUnmapViewOfSection (IN HANDLE ProcessHandle, IN PVOID BaseAddress)
 
NTSTATUS NTAPI NtExtendSection (IN HANDLE SectionHandle, IN OUT PLARGE_INTEGER NewMaximumSize)
 

Variables

ACCESS_MASK MmMakeSectionAccess [8]
 
ACCESS_MASK MmMakeFileAccess [8]
 
CHAR MmUserProtectionToMask1 [16]
 
CHAR MmUserProtectionToMask2 [16]
 
ULONG MmCompatibleProtectionMask [8]
 
MMSESSION MmSession
 
KGUARDED_MUTEX MmSectionCommitMutex
 
MM_AVL_TABLE MmSectionBasedRoot
 
KGUARDED_MUTEX MmSectionBasedMutex
 
PVOID MmHighSectionBase
 

Macro Definition Documentation

◆ MODULE_INVOLVED_IN_ARM3

#define MODULE_INVOLVED_IN_ARM3

Definition at line 15 of file section.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file section.c.

Function Documentation

◆ MiAddMappedPtes()

static NTSTATUS MiAddMappedPtes ( IN PMMPTE  FirstPte,
IN PFN_NUMBER  PteCount,
IN PCONTROL_AREA  ControlArea,
IN LONGLONG  SectionOffset 
)
static

Definition at line 399 of file section.c.

403 {
404  MMPTE TempPte;
405  PMMPTE PointerPte, ProtoPte, LastProtoPte, LastPte;
406  PSUBSECTION Subsection;
407 
408  /* Mapping at offset not supported yet */
409  ASSERT(SectionOffset == 0);
410 
411  /* ARM3 doesn't support this yet */
412  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
413  ASSERT(ControlArea->u.Flags.Rom == 0);
414  ASSERT(ControlArea->FilePointer == NULL);
415 
416  /* Sanity checks */
417  ASSERT(PteCount != 0);
418  ASSERT(ControlArea->NumberOfMappedViews >= 1);
419  ASSERT(ControlArea->NumberOfUserReferences >= 1);
420  ASSERT(ControlArea->NumberOfSectionReferences != 0);
421  ASSERT(ControlArea->u.Flags.BeingCreated == 0);
422  ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
423  ASSERT(ControlArea->u.Flags.BeingPurged == 0);
424 
425  /* Get the PTEs for the actual mapping */
426  PointerPte = FirstPte;
427  LastPte = FirstPte + PteCount;
428 
429  /* Get the prototype PTEs that desribe the section mapping in the subsection */
430  Subsection = (PSUBSECTION)(ControlArea + 1);
431  ProtoPte = Subsection->SubsectionBase;
432  LastProtoPte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
433 
434  /* Loop the PTEs for the mapping */
435  while (PointerPte < LastPte)
436  {
437  /* We may have run out of prototype PTEs in this subsection */
438  if (ProtoPte >= LastProtoPte)
439  {
440  /* But we don't handle this yet */
441  ASSERT(FALSE);
442  }
443 
444  /* The PTE should be completely clear */
445  ASSERT(PointerPte->u.Long == 0);
446 
447  /* Build the prototype PTE and write it */
448  MI_MAKE_PROTOTYPE_PTE(&TempPte, ProtoPte);
449  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
450 
451  /* Keep going */
452  PointerPte++;
453  ProtoPte++;
454  }
455 
456  /* No failure path */
457  return STATUS_SUCCESS;
458 }
union _MMPTE::@2288 u
ASSERT(Segment->Locked)
return FALSE
Definition: section.c:5098
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER SectionOffset
Definition: mmfuncs.h:404
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
struct _SUBSECTION * PSUBSECTION
ULONG_PTR Long
Definition: mmtypes.h:215
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:997
FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, IN PMMPTE PointerPte)
Definition: mm.h:342
#define NULL
Definition: types.h:112
#define STATUS_SUCCESS
Definition: shellext.h:65
PMMPTE SubsectionBase
Definition: mmtypes.h:578
ULONG PtesInSubsection
Definition: mmtypes.h:580

Referenced by MiMapViewInSystemSpace().

◆ MiCheckControlArea()

VOID NTAPI MiCheckControlArea ( IN PCONTROL_AREA  ControlArea,
IN KIRQL  OldIrql 
)

Definition at line 714 of file section.c.

716 {
717  BOOLEAN DeleteSegment = FALSE;
719 
720  /* Check if this is the last reference or view */
721  if (!(ControlArea->NumberOfMappedViews) &&
722  !(ControlArea->NumberOfSectionReferences))
723  {
724  /* There should be no more user references either */
725  ASSERT(ControlArea->NumberOfUserReferences == 0);
726 
727  /* Not yet supported */
728  ASSERT(ControlArea->FilePointer == NULL);
729 
730  /* The control area is being destroyed */
731  ControlArea->u.Flags.BeingDeleted = TRUE;
732  DeleteSegment = TRUE;
733  }
734 
735  /* Release the PFN lock */
736  MiReleasePfnLock(OldIrql);
737 
738  /* Delete the segment if needed */
739  if (DeleteSegment)
740  {
741  /* No more user write references at all */
742  ASSERT(ControlArea->WritableUserReferences == 0);
743  MiSegmentDelete(ControlArea->Segment);
744  }
745 }
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1043
#define TRUE
Definition: types.h:120
ASSERT(Segment->Locked)
unsigned char BOOLEAN
return FALSE
Definition: section.c:5098
VOID NTAPI MiSegmentDelete(IN PSEGMENT Segment)
Definition: section.c:591
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
#define NULL
Definition: types.h:112

Referenced by MiDeleteARM3Section(), MiDereferenceControlArea(), MiRemoveMappedPtes(), MiRemoveMappedView(), and MmCreateArm3Section().

◆ MiCheckPurgeAndUpMapCount()

NTSTATUS NTAPI MiCheckPurgeAndUpMapCount ( IN PCONTROL_AREA  ControlArea,
IN BOOLEAN  FailIfSystemViews 
)

Definition at line 530 of file section.c.

532 {
533  KIRQL OldIrql;
534 
535  /* Flag not yet supported */
536  ASSERT(FailIfSystemViews == FALSE);
537 
538  /* Lock the PFN database */
539  OldIrql = MiAcquirePfnLock();
540 
541  /* State not yet supported */
542  ASSERT(ControlArea->u.Flags.BeingPurged == 0);
543 
544  /* Increase the reference counts */
545  ControlArea->NumberOfMappedViews++;
546  ControlArea->NumberOfUserReferences++;
547  ASSERT(ControlArea->NumberOfSectionReferences != 0);
548 
549  /* Release the PFN lock and return success */
550  MiReleasePfnLock(OldIrql);
551  return STATUS_SUCCESS;
552 }
UCHAR KIRQL
Definition: env_spec_w32.h:591
ASSERT(Segment->Locked)
return FALSE
Definition: section.c:5098
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by MiMapViewInSystemSpace(), and MiMapViewOfDataSection().

◆ MiCreateDataFileMap()

NTSTATUS NTAPI MiCreateDataFileMap ( IN PFILE_OBJECT  File,
OUT PSEGMENT Segment,
IN PSIZE_T  MaximumSize,
IN ULONG  SectionPageProtection,
IN ULONG  AllocationAttributes,
IN ULONG  IgnoreFileSizing 
)

Definition at line 1536 of file section.c.

1542 {
1543  /* Not yet implemented */
1544  ASSERT(FALSE);
1545  *Segment = NULL;
1546  return STATUS_NOT_IMPLEMENTED;
1547 }
return STATUS_NOT_IMPLEMENTED
ASSERT(Segment->Locked)
return FALSE
Definition: section.c:5098
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NULL
Definition: types.h:112

Referenced by MmCreateArm3Section().

◆ MiCreatePagingFileMap()

static NTSTATUS NTAPI MiCreatePagingFileMap ( OUT PSEGMENT Segment,
IN PLARGE_INTEGER  MaximumSize,
IN ULONG  ProtectionMask,
IN ULONG  AllocationAttributes 
)
static

Definition at line 1552 of file section.c.

1556 {
1557  ULONGLONG SizeLimit;
1558  PFN_COUNT PteCount;
1559  PMMPTE PointerPte;
1560  MMPTE TempPte;
1561  PCONTROL_AREA ControlArea;
1562  PSEGMENT NewSegment;
1563  PSUBSECTION Subsection;
1564  PAGED_CODE();
1565 
1566  /* No large pages in ARM3 yet */
1568 
1569  /* Pagefile-backed sections need a known size */
1570  if (!MaximumSize || !MaximumSize->QuadPart || MaximumSize->QuadPart < 0)
1572 
1573  /* Calculate the maximum size possible, given the Prototype PTEs we'll need */
1574  SizeLimit = MmSizeOfPagedPoolInBytes - sizeof(SEGMENT);
1575  SizeLimit /= sizeof(MMPTE);
1576  SizeLimit <<= PAGE_SHIFT;
1577 
1578  /* Fail if this size is too big */
1579  if (MaximumSize->QuadPart > SizeLimit)
1580  {
1581  return STATUS_SECTION_TOO_BIG;
1582  }
1583 
1584  /* Calculate how many Prototype PTEs will be needed */
1585  PteCount = (PFN_COUNT)((MaximumSize->QuadPart + PAGE_SIZE - 1) >> PAGE_SHIFT);
1586 
1587  /* For commited memory, we must have a valid protection mask */
1588  if (AllocationAttributes & SEC_COMMIT) ASSERT(ProtectionMask != 0);
1589 
1590  /* The segment contains all the Prototype PTEs, allocate it in paged pool */
1591  NewSegment = ExAllocatePoolWithTag(PagedPool,
1592  sizeof(SEGMENT) +
1593  sizeof(MMPTE) * (PteCount - 1),
1594  'tSmM');
1595  if (!NewSegment)
1596  {
1598  }
1599  *Segment = NewSegment;
1600 
1601  /* Now allocate the control area, which has the subsection structure */
1602  ControlArea = ExAllocatePoolWithTag(NonPagedPool,
1603  sizeof(CONTROL_AREA) + sizeof(SUBSECTION),
1604  'tCmM');
1605  if (!ControlArea)
1606  {
1607  ExFreePoolWithTag(Segment, 'tSmM');
1609  }
1610 
1611  /* And zero it out, filling the basic segmnet pointer and reference fields */
1612  RtlZeroMemory(ControlArea, sizeof(CONTROL_AREA) + sizeof(SUBSECTION));
1613  ControlArea->Segment = NewSegment;
1614  ControlArea->NumberOfSectionReferences = 1;
1615  ControlArea->NumberOfUserReferences = 1;
1616 
1617  /* Convert allocation attributes to control area flags */
1618  if (AllocationAttributes & SEC_BASED) ControlArea->u.Flags.Based = 1;
1619  if (AllocationAttributes & SEC_RESERVE) ControlArea->u.Flags.Reserve = 1;
1620  if (AllocationAttributes & SEC_COMMIT) ControlArea->u.Flags.Commit = 1;
1621 
1622  /* We just allocated it */
1623  ControlArea->u.Flags.BeingCreated = 1;
1624 
1625  /* The subsection follows, write the mask, PTE count and point back to the CA */
1626  Subsection = (PSUBSECTION)(ControlArea + 1);
1627  Subsection->ControlArea = ControlArea;
1628  Subsection->PtesInSubsection = PteCount;
1629  Subsection->u.SubsectionFlags.Protection = ProtectionMask;
1630 
1631  /* Zero out the segment's prototype PTEs, and link it with the control area */
1632  PointerPte = &NewSegment->ThePtes[0];
1633  RtlZeroMemory(NewSegment, sizeof(SEGMENT));
1634  NewSegment->PrototypePte = PointerPte;
1635  NewSegment->ControlArea = ControlArea;
1636 
1637  /* Save some extra accounting data for the segment as well */
1638  NewSegment->u1.CreatingProcess = PsGetCurrentProcess();
1639  NewSegment->SizeOfSegment = ((ULONGLONG)PteCount) * PAGE_SIZE;
1640  NewSegment->TotalNumberOfPtes = PteCount;
1641  NewSegment->NonExtendedPtes = PteCount;
1642 
1643  /* The subsection's base address is the first Prototype PTE in the segment */
1644  Subsection->SubsectionBase = PointerPte;
1645 
1646  /* Start with an empty PTE, unless this is a commit operation */
1647  TempPte.u.Long = 0;
1649  {
1650  /* In which case, write down the protection mask in the Prototype PTEs */
1651  TempPte.u.Soft.Protection = ProtectionMask;
1652 
1653  /* For accounting, also mark these pages as being committed */
1654  NewSegment->NumberOfCommittedPages = PteCount;
1655  }
1656 
1657  /* The template PTE itself for the segment should also have the mask set */
1658  NewSegment->SegmentPteTemplate.u.Soft.Protection = ProtectionMask;
1659 
1660  /* Write out the prototype PTEs, for now they're simply demand zero */
1661 #ifdef _WIN64
1662  RtlFillMemoryUlonglong(PointerPte, PteCount * sizeof(MMPTE), TempPte.u.Long);
1663 #else
1664  RtlFillMemoryUlong(PointerPte, PteCount * sizeof(MMPTE), TempPte.u.Long);
1665 #endif
1666  return STATUS_SUCCESS;
1667 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
ULONG NumberOfCommittedPages
Definition: mmtypes.h:412
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define SEC_LARGE_PAGES
Definition: mmtypes.h:102
union _SEGMENT::@2560 u1
ULONGLONG SizeOfSegment
Definition: mmtypes.h:410
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ ULONG AllocationAttributes
Definition: mmfuncs.h:360
ULONG NumberOfSectionReferences
Definition: mmtypes.h:520
ULONG NonExtendedPtes
Definition: mmtypes.h:408
union _MMPTE::@2288 u
ULONG PFN_COUNT
Definition: mmtypes.h:102
PCONTROL_AREA ControlArea
Definition: mmtypes.h:570
MMPTE ThePtes[1]
Definition: mmtypes.h:427
ULONG TotalNumberOfPtes
Definition: mmtypes.h:407
SIZE_T MmSizeOfPagedPoolInBytes
Definition: miarm.h:590
struct _CONTROL_AREA * ControlArea
Definition: mmtypes.h:406
#define SEC_BASED
PEPROCESS CreatingProcess
Definition: mmtypes.h:419
ASSERT(Segment->Locked)
#define SEC_COMMIT
Definition: mmtypes.h:99
#define SEC_RESERVE
Definition: nt_native.h:1323
#define PsGetCurrentProcess
Definition: psfuncs.h:17
union _CONTROL_AREA::@2562 u
#define STATUS_SECTION_TOO_BIG
Definition: ntstatus.h:300
ULONG64 Protection
Definition: mmtypes.h:88
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
uint64_t ULONGLONG
Definition: typedefs.h:67
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
struct _SUBSECTION * PSUBSECTION
struct _SEGMENT SEGMENT
#define PAGE_SIZE
Definition: env_spec_w32.h:49
MMSUBSECTION_FLAGS SubsectionFlags
Definition: mmtypes.h:574
PSEGMENT Segment
Definition: mmtypes.h:518
ULONG NumberOfUserReferences
Definition: mmtypes.h:524
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
struct _MMPTE MMPTE
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER MaximumSize
Definition: mmfuncs.h:360
MMPTE SegmentPteTemplate
Definition: mmtypes.h:411
MMSECTION_FLAGS Flags
Definition: mmtypes.h:528
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_SUCCESS
Definition: shellext.h:65
union _SUBSECTION::@2564 u
#define STATUS_INVALID_PARAMETER_4
Definition: ntstatus.h:478
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
PMMPTE PrototypePte
Definition: mmtypes.h:426
PMMPTE SubsectionBase
Definition: mmtypes.h:578
ULONG BeingCreated
Definition: mmtypes.h:461
NTSYSAPI VOID NTAPI RtlFillMemoryUlonglong(_Out_writes_bytes_all_(Length) PVOID Destination, _In_ SIZE_T Length, _In_ ULONGLONG Pattern)
#define PAGED_CODE()
ULONG PtesInSubsection
Definition: mmtypes.h:580

Referenced by MmCreateArm3Section().

◆ MiDeleteARM3Section()

VOID NTAPI MiDeleteARM3Section ( PVOID  ObjectBody)

Definition at line 3316 of file section.c.

3317 {
3319  PCONTROL_AREA ControlArea;
3320  KIRQL OldIrql;
3321 
3322  SectionObject = (PSECTION)ObjectBody;
3323 
3324  if (SectionObject->u.Flags.Based == 1)
3325  {
3326  /* Remove the node from the global section address tree */
3330  }
3331 
3332  /* Lock the PFN database */
3333  OldIrql = MiAcquirePfnLock();
3334 
3335  ASSERT(SectionObject->Segment);
3336  ASSERT(SectionObject->Segment->ControlArea);
3337 
3338  ControlArea = SectionObject->Segment->ControlArea;
3339 
3340  /* Dereference */
3341  ControlArea->NumberOfSectionReferences--;
3342  ControlArea->NumberOfUserReferences--;
3343 
3344  ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
3345 
3346  /* Check it. It will delete it if there is no more reference to it */
3347  MiCheckControlArea(ControlArea, OldIrql);
3348 }
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
ULONG NumberOfSectionReferences
Definition: mmtypes.h:520
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
KGUARDED_MUTEX MmSectionBasedMutex
Definition: section.c:110
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
UCHAR KIRQL
Definition: env_spec_w32.h:591
ASSERT(Segment->Locked)
union _CONTROL_AREA::@2562 u
struct _SECTION * PSECTION
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
VOID NTAPI MiRemoveNode(IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table)
Definition: vadnode.c:360
ULONG BeingDeleted
Definition: mmtypes.h:460
ULONG NumberOfUserReferences
Definition: mmtypes.h:524
VOID NTAPI MiCheckControlArea(IN PCONTROL_AREA ControlArea, IN KIRQL OldIrql)
Definition: section.c:714
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
MMSECTION_FLAGS Flags
Definition: mmtypes.h:528

Referenced by MmpDeleteSection().

◆ MiDereferenceControlArea()

VOID NTAPI MiDereferenceControlArea ( IN PCONTROL_AREA  ControlArea)

Definition at line 749 of file section.c.

750 {
751  KIRQL OldIrql;
752 
753  /* Lock the PFN database */
754  OldIrql = MiAcquirePfnLock();
755 
756  /* Drop reference counts */
757  ControlArea->NumberOfMappedViews--;
758  ControlArea->NumberOfUserReferences--;
759 
760  /* Check if it's time to delete the CA. This releases the lock */
761  MiCheckControlArea(ControlArea, OldIrql);
762 }
UCHAR KIRQL
Definition: env_spec_w32.h:591
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
VOID NTAPI MiCheckControlArea(IN PCONTROL_AREA ControlArea, IN KIRQL OldIrql)
Definition: section.c:714

Referenced by MiMapViewInSystemSpace(), and MiMapViewOfDataSection().

◆ MiFillSystemPageDirectory()

VOID NTAPI MiFillSystemPageDirectory ( IN PVOID  Base,
IN SIZE_T  NumberOfBytes 
)

Definition at line 462 of file section.c.

464 {
465  PMMPDE PointerPde, LastPde, SystemMapPde;
466  MMPDE TempPde;
467  PFN_NUMBER PageFrameIndex, ParentPage;
468  KIRQL OldIrql;
469  PAGED_CODE();
470 
471  /* Find the PDEs needed for this mapping */
472  PointerPde = MiAddressToPde(Base);
473  LastPde = MiAddressToPde((PVOID)((ULONG_PTR)Base + NumberOfBytes - 1));
474 
475 #if (_MI_PAGING_LEVELS == 2)
476  /* Find the system double-mapped PDE that describes this mapping */
477  SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
478 #else
479  /* We don't have a double mapping */
480  SystemMapPde = PointerPde;
481 #endif
482 
483  /* Use the PDE template and loop the PDEs */
485  while (PointerPde <= LastPde)
486  {
487  /* Lock the PFN database */
488  OldIrql = MiAcquirePfnLock();
489 
490  /* Check if we don't already have this PDE mapped */
491  if (SystemMapPde->u.Hard.Valid == 0)
492  {
493  /* Grab a page for it */
495  MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
496  PageFrameIndex = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
497  ASSERT(PageFrameIndex);
498  TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
499 
500 #if (_MI_PAGING_LEVELS == 2)
501  ParentPage = MmSystemPageDirectory[(PointerPde - MiAddressToPde(NULL)) / PDE_PER_PAGE];
502 #else
503  ParentPage = MiPdeToPpe(PointerPde)->u.Hard.PageFrameNumber;
504 #endif
505  /* Initialize its PFN entry, with the parent system page directory page table */
506  MiInitializePfnForOtherProcess(PageFrameIndex,
507  (PMMPTE)PointerPde,
508  ParentPage);
509 
510  /* Make the system PDE entry valid */
511  MI_WRITE_VALID_PDE(SystemMapPde, TempPde);
512 
513  /* The system PDE entry might be the PDE itself, so check for this */
514  if (PointerPde->u.Hard.Valid == 0)
515  {
516  /* It's different, so make the real PDE valid too */
517  MI_WRITE_VALID_PDE(PointerPde, TempPde);
518  }
519  }
520 
521  /* Release the lock and keep going with the next PDE */
522  MiReleasePfnLock(OldIrql);
523  SystemMapPde++;
524  PointerPde++;
525  }
526 }
#define PDE_PER_PAGE
Definition: mm.h:21
#define MiAddressToPde(x)
Definition: mmx86.c:20
union _MMPTE::@2288 u
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2427
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:237
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1282
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:533
uint32_t ULONG_PTR
Definition: typedefs.h:65
UCHAR KIRQL
Definition: env_spec_w32.h:591
ASSERT(Segment->Locked)
ULONG PFN_NUMBER
Definition: ke.h:9
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
#define PsGetCurrentProcess
Definition: psfuncs.h:17
PFN_NUMBER MmSystemPageDirectory[PPE_PER_PAGE]
Definition: init.c:40
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:1023
#define MI_SET_USAGE(x)
Definition: mm.h:317
PMMPDE MmSystemPagePtes
Definition: init.c:41
ULONG PageFrameNumber
Definition: mmtypes.h:74
ULONG64 Valid
Definition: mmtypes.h:150
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
MMPTE ValidKernelPde
Definition: init.c:28
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define SYSTEM_PD_SIZE
Definition: miarm.h:32
FORCEINLINE PMMPDE MiPdeToPpe(PMMPDE PointerPde)
Definition: mm.h:292
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:1035
#define NULL
Definition: types.h:112
#define ULONG_PTR
Definition: config.h:101
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
#define PAGED_CODE()

Referenced by MiMapViewInSystemSpace(), and MmCreateVirtualMappingUnsafe().

◆ MiFlushTbAndCapture()

VOID NTAPI MiFlushTbAndCapture ( IN PMMVAD  FoundVad,
IN PMMPTE  PointerPte,
IN ULONG  ProtectionMask,
IN PMMPFN  Pfn1,
IN BOOLEAN  UpdateDirty 
)

Definition at line 2015 of file section.c.

2020 {
2021  MMPTE TempPte, PreviousPte;
2022  KIRQL OldIrql;
2023  BOOLEAN RebuildPte = FALSE;
2024 
2025  //
2026  // User for sanity checking later on
2027  //
2028  PreviousPte = *PointerPte;
2029 
2030  //
2031  // Build the PTE and acquire the PFN lock
2032  //
2034  PointerPte,
2035  ProtectionMask,
2036  PreviousPte.u.Hard.PageFrameNumber);
2037  OldIrql = MiAcquirePfnLock();
2038 
2039  //
2040  // We don't support I/O mappings in this path yet
2041  //
2042  ASSERT(Pfn1 != NULL);
2043  ASSERT(Pfn1->u3.e1.CacheAttribute != MiWriteCombined);
2044 
2045  //
2046  // Make sure new protection mask doesn't get in conflict and fix it if it does
2047  //
2048  if (Pfn1->u3.e1.CacheAttribute == MiCached)
2049  {
2050  //
2051  // This is a cached PFN
2052  //
2053  if (ProtectionMask & (MM_NOCACHE | MM_NOACCESS))
2054  {
2055  RebuildPte = TRUE;
2056  ProtectionMask &= ~(MM_NOCACHE | MM_NOACCESS);
2057  }
2058  }
2059  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
2060  {
2061  //
2062  // This is a non-cached PFN
2063  //
2064  if ((ProtectionMask & (MM_NOCACHE | MM_NOACCESS)) != MM_NOCACHE)
2065  {
2066  RebuildPte = TRUE;
2067  ProtectionMask &= ~MM_NOACCESS;
2068  ProtectionMask |= MM_NOCACHE;
2069  }
2070  }
2071 
2072  if (RebuildPte)
2073  {
2075  PointerPte,
2076  ProtectionMask,
2077  PreviousPte.u.Hard.PageFrameNumber);
2078  }
2079 
2080  //
2081  // Write the new PTE, making sure we are only changing the bits
2082  //
2083  MI_UPDATE_VALID_PTE(PointerPte, TempPte);
2084 
2085  //
2086  // Flush the TLB
2087  //
2088  ASSERT(PreviousPte.u.Hard.Valid == 1);
2089  KeFlushCurrentTb();
2090  ASSERT(PreviousPte.u.Hard.Valid == 1);
2091 
2092  //
2093  // Windows updates the relevant PFN1 information, we currently don't.
2094  //
2095  if (UpdateDirty && PreviousPte.u.Hard.Dirty)
2096  {
2097  if (!Pfn1->u3.e1.Modified)
2098  {
2099  DPRINT1("FIXME: Mark PFN as dirty\n");
2100  }
2101  }
2102 
2103  //
2104  // Not supported in ARM3
2105  //
2106  ASSERT(FoundVad->u.VadFlags.VadType != VadWriteWatch);
2107 
2108  //
2109  // Release the PFN lock, we are done
2110  //
2111  MiReleasePfnLock(OldIrql);
2112 }
union _MMPTE::@2288 u
#define TRUE
Definition: types.h:120
#define MM_NOACCESS
Definition: miarm.h:65
#define MM_NOCACHE
Definition: miarm.h:56
ULONG64 Dirty
Definition: mmtypes.h:164
UCHAR KIRQL
Definition: env_spec_w32.h:591
ASSERT(Segment->Locked)
unsigned char BOOLEAN
return FALSE
Definition: section.c:5098
ULONG64 Valid
Definition: mmtypes.h:150
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:832
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
FORCEINLINE VOID MI_UPDATE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:982
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:347

Referenced by MiProtectVirtualMemory(), and MiSetProtectionOnSection().

◆ MiGetFileObjectForSectionAddress()

NTSTATUS NTAPI MiGetFileObjectForSectionAddress ( IN PVOID  Address,
OUT PFILE_OBJECT FileObject 
)

Definition at line 1671 of file section.c.

1674 {
1675  PMMVAD Vad;
1676  PCONTROL_AREA ControlArea;
1677 
1678  /* Get the VAD */
1679  Vad = MiLocateAddress(Address);
1680  if (Vad == NULL)
1681  {
1682  /* Fail, the address does not exist */
1683  DPRINT1("Invalid address\n");
1684  return STATUS_INVALID_ADDRESS;
1685  }
1686 
1687  /* Check if this is a RosMm memory area */
1688  if (Vad->u.VadFlags.Spare != 0)
1689  {
1691 
1692  /* Check if it's a section view (RosMm section) */
1694  {
1695  /* Get the section pointer to the SECTION_OBJECT */
1696  *FileObject = MemoryArea->SectionData.Segment->FileObject;
1697  }
1698  else
1699  {
1700 #ifdef NEWCC
1701  ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
1702  DPRINT1("Address is a cache section!\n");
1703  return STATUS_SECTION_NOT_IMAGE;
1704 #else
1705  ASSERT(FALSE);
1706  return STATUS_SECTION_NOT_IMAGE;
1707 #endif
1708  }
1709  }
1710  else
1711  {
1712  /* Make sure it's not a VM VAD */
1713  if (Vad->u.VadFlags.PrivateMemory == 1)
1714  {
1715  DPRINT1("Address is not a section\n");
1716  return STATUS_SECTION_NOT_IMAGE;
1717  }
1718 
1719  /* Get the control area */
1720  ControlArea = Vad->ControlArea;
1721  if (!(ControlArea) || !(ControlArea->u.Flags.Image))
1722  {
1723  DPRINT1("Address is not a section\n");
1724  return STATUS_SECTION_NOT_IMAGE;
1725  }
1726 
1727  /* Get the file object */
1728  *FileObject = ControlArea->FilePointer;
1729  }
1730 
1731  /* Return success */
1732  return STATUS_SUCCESS;
1733 }
PFILE_OBJECT FilePointer
Definition: mmtypes.h:530
ULONG Type
Definition: mm.h:251
struct _MEMORY_AREA * PMEMORY_AREA
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
ASSERT(Segment->Locked)
PCONTROL_AREA ControlArea
Definition: mmtypes.h:733
union _CONTROL_AREA::@2562 u
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:48
static WCHAR Address[46]
Definition: ping.c:68
return FALSE
Definition: section.c:5098
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:93
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
union _MMVAD::@2569 u
ULONG_PTR PrivateMemory
Definition: mmtypes.h:695
#define STATUS_SECTION_NOT_IMAGE
Definition: ntstatus.h:309
struct _MEMORY_AREA::@1754 SectionData
#define STATUS_INVALID_ADDRESS
Definition: ntstatus.h:557
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
ULONG_PTR Spare
Definition: mmtypes.h:694
MMSECTION_FLAGS Flags
Definition: mmtypes.h:528
#define STATUS_SUCCESS
Definition: shellext.h:65

◆ MiGetFileObjectForVad()

static PFILE_OBJECT MiGetFileObjectForVad ( _In_ PMMVAD  Vad)
static

Definition at line 1756 of file section.c.

1758 {
1759  PCONTROL_AREA ControlArea;
1761 
1762  /* Check if this is a RosMm memory area */
1763  if (Vad->u.VadFlags.Spare != 0)
1764  {
1766 
1767  /* Check if it's a section view (RosMm section) */
1769  {
1770  /* Get the section pointer to the SECTION_OBJECT */
1771  FileObject = MemoryArea->SectionData.Segment->FileObject;
1772  }
1773  else
1774  {
1775 #ifdef NEWCC
1776  ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
1777  DPRINT1("VAD is a cache section!\n");
1778 #else
1779  ASSERT(FALSE);
1780 #endif
1781  return NULL;
1782  }
1783  }
1784  else
1785  {
1786  /* Make sure it's not a VM VAD */
1787  if (Vad->u.VadFlags.PrivateMemory == 1)
1788  {
1789  DPRINT1("VAD is not a section\n");
1790  return NULL;
1791  }
1792 
1793  /* Get the control area */
1794  ControlArea = Vad->ControlArea;
1795  if ((ControlArea == NULL) || !ControlArea->u.Flags.Image)
1796  {
1797  DPRINT1("Address is not a section\n");
1798  return NULL;
1799  }
1800 
1801  /* Get the file object */
1802  FileObject = ControlArea->FilePointer;
1803  }
1804 
1805  /* Return the file object */
1806  return FileObject;
1807 }
PFILE_OBJECT FilePointer
Definition: mmtypes.h:530
ULONG Type
Definition: mm.h:251
struct _MEMORY_AREA * PMEMORY_AREA
ASSERT(Segment->Locked)
union _CONTROL_AREA::@2562 u
return FALSE
Definition: section.c:5098
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:93
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
* PFILE_OBJECT
Definition: iotypes.h:1998
struct _MEMORY_AREA::@1754 SectionData
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
MMSECTION_FLAGS Flags
Definition: mmtypes.h:528

Referenced by MmGetFileNameForAddress(), and NtAreMappedFilesTheSame().

◆ MiInitializeSystemSpaceMap()

BOOLEAN NTAPI MiInitializeSystemSpaceMap ( IN PMMSESSION InputSession  OPTIONAL)

Definition at line 222 of file section.c.

223 {
224  SIZE_T AllocSize, BitmapSize, Size;
225  PVOID ViewStart;
226  PMMSESSION Session;
227 
228  /* Check if this a session or system space */
229  if (InputSession)
230  {
231  /* Use the input session */
232  Session = InputSession;
233  ViewStart = MiSessionViewStart;
235  }
236  else
237  {
238  /* Use the system space "session" */
239  Session = &MmSession;
240  ViewStart = MiSystemViewStart;
242  }
243 
244  /* Initialize the system space lock */
245  Session->SystemSpaceViewLockPointer = &Session->SystemSpaceViewLock;
247 
248  /* Set the start address */
249  Session->SystemSpaceViewStart = ViewStart;
250 
251  /* Create a bitmap to describe system space */
252  BitmapSize = sizeof(RTL_BITMAP) + ((((Size / MI_SYSTEM_VIEW_BUCKET_SIZE) + 31) / 32) * sizeof(ULONG));
254  BitmapSize,
255  TAG_MM);
256  ASSERT(Session->SystemSpaceBitMap);
258  (PULONG)(Session->SystemSpaceBitMap + 1),
260 
261  /* Set system space fully empty to begin with */
263 
264  /* Set default hash flags */
265  Session->SystemSpaceHashSize = 31;
266  Session->SystemSpaceHashKey = Session->SystemSpaceHashSize - 1;
267  Session->SystemSpaceHashEntries = 0;
268 
269  /* Calculate how much space for the hash views we'll need */
270  AllocSize = sizeof(MMVIEW) * Session->SystemSpaceHashSize;
271  ASSERT(AllocSize < PAGE_SIZE);
272 
273  /* Allocate and zero the view table */
274  Session->SystemSpaceViewTable = ExAllocatePoolWithTag(Session == &MmSession ?
275  NonPagedPool :
276  PagedPool,
277  AllocSize,
278  TAG_MM);
279  ASSERT(Session->SystemSpaceViewTable != NULL);
280  RtlZeroMemory(Session->SystemSpaceViewTable, AllocSize);
281 
282  /* Success */
283  return TRUE;
284 }
struct _RTL_BITMAP RTL_BITMAP
#define TRUE
Definition: types.h:120
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
PCHAR SystemSpaceViewStart
Definition: miarm.h:457
ULONG SystemSpaceHashEntries
Definition: miarm.h:460
KGUARDED_MUTEX SystemSpaceViewLock
Definition: miarm.h:455
ASSERT(Segment->Locked)
#define TAG_MM
Definition: tag.h:113
ULONG MmSystemViewSize
Definition: init.c:39
ULONG MmSessionViewSize
Definition: init.c:35
PVOID MiSystemViewStart
Definition: init.c:38
PMMVIEW SystemSpaceViewTable
Definition: miarm.h:458
ULONG SystemSpaceHashKey
Definition: miarm.h:461
struct _MMVIEW MMVIEW
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
PKGUARDED_MUTEX SystemSpaceViewLockPointer
Definition: miarm.h:456
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG_PTR SIZE_T
Definition: typedefs.h:80
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
PRTL_BITMAP SystemSpaceBitMap
Definition: miarm.h:463
PVOID MiSessionViewStart
Definition: init.c:30
#define MI_SYSTEM_VIEW_BUCKET_SIZE
Definition: miarm.h:266
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
NTSYSAPI void WINAPI RtlClearAllBits(PRTL_BITMAP)
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
ULONG SystemSpaceHashSize
Definition: miarm.h:459
MMSESSION MmSession
Definition: section.c:107

Referenced by MiBuildPagedPool(), and MiSessionCreateInternal().

◆ MiInsertInSystemSpace()

PVOID NTAPI MiInsertInSystemSpace ( IN PMMSESSION  Session,
IN ULONG  Buckets,
IN PCONTROL_AREA  ControlArea 
)

Definition at line 288 of file section.c.

291 {
292  PVOID Base;
293  ULONG Entry, Hash, i, HashSize;
294  PMMVIEW OldTable;
295  PAGED_CODE();
296 
297  /* Stay within 4GB */
299 
300  /* Lock system space */
301  KeAcquireGuardedMutex(Session->SystemSpaceViewLockPointer);
302 
303  /* Check if we're going to exhaust hash entries */
304  if ((Session->SystemSpaceHashEntries + 8) > Session->SystemSpaceHashSize)
305  {
306  /* Double the hash size */
307  HashSize = Session->SystemSpaceHashSize * 2;
308 
309  /* Save the old table and allocate a new one */
310  OldTable = Session->SystemSpaceViewTable;
311  Session->SystemSpaceViewTable = ExAllocatePoolWithTag(Session ==
312  &MmSession ?
313  NonPagedPool :
314  PagedPool,
315  HashSize *
316  sizeof(MMVIEW),
317  TAG_MM);
318  if (!Session->SystemSpaceViewTable)
319  {
320  /* Failed to allocate a new table, keep the old one for now */
321  Session->SystemSpaceViewTable = OldTable;
322  }
323  else
324  {
325  /* Clear the new table and set the new ahsh and key */
326  RtlZeroMemory(Session->SystemSpaceViewTable, HashSize * sizeof(MMVIEW));
327  Session->SystemSpaceHashSize = HashSize;
328  Session->SystemSpaceHashKey = Session->SystemSpaceHashSize - 1;
329 
330  /* Loop the old table */
331  for (i = 0; i < Session->SystemSpaceHashSize / 2; i++)
332  {
333  /* Check if the entry was valid */
334  if (OldTable[i].Entry)
335  {
336  /* Re-hash the old entry and search for space in the new table */
337  Hash = (OldTable[i].Entry >> 16) % Session->SystemSpaceHashKey;
338  while (Session->SystemSpaceViewTable[Hash].Entry)
339  {
340  /* Loop back at the beginning if we had an overflow */
341  if (++Hash >= Session->SystemSpaceHashSize) Hash = 0;
342  }
343 
344  /* Write the old entry in the new table */
345  Session->SystemSpaceViewTable[Hash] = OldTable[i];
346  }
347  }
348 
349  /* Free the old table */
350  ExFreePool(OldTable);
351  }
352  }
353 
354  /* Check if we ran out */
355  if (Session->SystemSpaceHashEntries == Session->SystemSpaceHashSize)
356  {
357  DPRINT1("Ran out of system view hash entries\n");
358  KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
359  return NULL;
360  }
361 
362  /* Find space where to map this view */
363  i = RtlFindClearBitsAndSet(Session->SystemSpaceBitMap, Buckets, 0);
364  if (i == 0xFFFFFFFF)
365  {
366  /* Out of space, fail */
367  Session->BitmapFailures++;
368  DPRINT1("Out of system view space\n");
369  KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
370  return NULL;
371  }
372 
373  /* Compute the base address */
374  Base = (PVOID)((ULONG_PTR)Session->SystemSpaceViewStart + (i * MI_SYSTEM_VIEW_BUCKET_SIZE));
375 
376  /* Get the hash entry for this allocation */
377  Entry = ((ULONG_PTR)Base & ~(MI_SYSTEM_VIEW_BUCKET_SIZE - 1)) + Buckets;
378  Hash = (Entry >> 16) % Session->SystemSpaceHashKey;
379 
380  /* Loop hash entries until a free one is found */
381  while (Session->SystemSpaceViewTable[Hash].Entry)
382  {
383  /* Unless we overflow, in which case loop back at hash o */
384  if (++Hash >= Session->SystemSpaceHashSize) Hash = 0;
385  }
386 
387  /* Add this entry into the hash table */
388  Session->SystemSpaceViewTable[Hash].Entry = Entry;
389  Session->SystemSpaceViewTable[Hash].ControlArea = ControlArea;
390 
391  /* Hash entry found, increment total and return the base address */
392  Session->SystemSpaceHashEntries++;
393  KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
394  return Base;
395 }
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
static int Hash(const char *)
Definition: reader.c:2257
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2427
uint32_t ULONG_PTR
Definition: typedefs.h:65
ASSERT(Segment->Locked)
#define TAG_MM
Definition: tag.h:113
Entry
Definition: section.c:4943
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
void * PVOID
Definition: retypes.h:9
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
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 MI_SYSTEM_VIEW_BUCKET_SIZE
Definition: miarm.h:266
Definition: miarm.h:447
#define NULL
Definition: types.h:112
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
ULONG_PTR Entry
Definition: miarm.h:449
base of all file and directory entries
Definition: entries.h:82
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define PAGED_CODE()
MMSESSION MmSession
Definition: section.c:107

Referenced by MiMapViewInSystemSpace().

◆ MiIsProtectionCompatible()

BOOLEAN NTAPI MiIsProtectionCompatible ( IN ULONG  SectionPageProtection,
IN ULONG  NewSectionPageProtection 
)

Definition at line 117 of file section.c.

119 {
120  ULONG ProtectionMask, CompatibleMask;
121 
122  /* Calculate the protection mask and make sure it's valid */
124  if (ProtectionMask == MM_INVALID_PROTECTION)
125  {
126  DPRINT1("Invalid protection mask\n");
127  return FALSE;
128  }
129 
130  /* Calculate the compatible mask */
131  CompatibleMask = MmCompatibleProtectionMask[ProtectionMask & 0x7] |
133 
134  /* See if the mapping protection is compatible with the create protection */
135  return ((CompatibleMask | NewSectionPageProtection) == CompatibleMask);
136 }
#define PAGE_NOCACHE
Definition: nt_native.h:1311
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
#define PAGE_GUARD
Definition: nt_native.h:1310
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG SectionPageProtection
Definition: mmfuncs.h:360
return FALSE
Definition: section.c:5098
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:140
ULONG MmCompatibleProtectionMask[8]
Definition: section.c:84
#define PAGE_WRITECOMBINE
Definition: mmtypes.h:78
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1

Referenced by MmMapViewOfArm3Section().

◆ MiLoadUserSymbols()

VOID NTAPI MiLoadUserSymbols ( IN PCONTROL_AREA  ControlArea,
IN PVOID  BaseAddress,
IN PEPROCESS  Process 
)

Definition at line 1168 of file section.c.

1171 {
1172  NTSTATUS Status;
1174  PLIST_ENTRY NextEntry;
1176  PIMAGE_NT_HEADERS NtHeaders;
1177  PLDR_DATA_TABLE_ENTRY LdrEntry;
1178 
1179  FileName = &ControlArea->FilePointer->FileName;
1180  if (FileName->Length == 0)
1181  {
1182  return;
1183  }
1184 
1185  /* Acquire module list lock */
1188 
1189  /* Browse list to try to find current module */
1190  for (NextEntry = MmLoadedUserImageList.Flink;
1191  NextEntry != &MmLoadedUserImageList;
1192  NextEntry = NextEntry->Flink)
1193  {
1194  /* Get the entry */
1195  LdrEntry = CONTAINING_RECORD(NextEntry,
1197  InLoadOrderLinks);
1198 
1199  /* If already in the list, increase load count */
1200  if (LdrEntry->DllBase == BaseAddress)
1201  {
1202  ++LdrEntry->LoadCount;
1203  break;
1204  }
1205  }
1206 
1207  /* Not in the list, we'll add it */
1208  if (NextEntry == &MmLoadedUserImageList)
1209  {
1210  /* Allocate our element, taking to the name string and its null char */
1211  LdrEntry = ExAllocatePoolWithTag(NonPagedPool, FileName->Length + sizeof(UNICODE_NULL) + sizeof(*LdrEntry), 'bDmM');
1212  if (LdrEntry)
1213  {
1214  memset(LdrEntry, 0, FileName->Length + sizeof(UNICODE_NULL) + sizeof(*LdrEntry));
1215 
1216  _SEH2_TRY
1217  {
1218  /* Get image checksum and size */
1219  NtHeaders = RtlImageNtHeader(BaseAddress);
1220  if (NtHeaders)
1221  {
1222  LdrEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage;
1223  LdrEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum;
1224  }
1225  }
1227  {
1228  ExFreePoolWithTag(LdrEntry, 'bDmM');
1231  _SEH2_YIELD(return);
1232  }
1233  _SEH2_END;
1234 
1235  /* Fill all the details */
1236  LdrEntry->DllBase = BaseAddress;
1237  LdrEntry->FullDllName.Buffer = (PVOID)((ULONG_PTR)LdrEntry + sizeof(*LdrEntry));
1238  LdrEntry->FullDllName.Length = FileName->Length;
1239  LdrEntry->FullDllName.MaximumLength = FileName->Length + sizeof(UNICODE_NULL);
1240  memcpy(LdrEntry->FullDllName.Buffer, FileName->Buffer, FileName->Length);
1241  LdrEntry->FullDllName.Buffer[LdrEntry->FullDllName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1242  LdrEntry->LoadCount = 1;
1243 
1244  /* Insert! */
1246  }
1247  }
1248 
1249  /* Release locks */
1252 
1253  /* Load symbols */
1255  if (NT_SUCCESS(Status))
1256  {
1259  }
1260 }
_SEH2_TRY
Definition: create.c:4226
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define TRUE
Definition: types.h:120
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
LONG NTSTATUS
Definition: precomp.h:26
ULONG SizeOfImage
Definition: ldrtypes.h:143
_SEH2_END
Definition: create.c:4400
uint32_t ULONG_PTR
Definition: typedefs.h:65
ERESOURCE PsLoadedModuleResource
Definition: sysldr.c:24
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
PVOID DllBase
Definition: btrfs_drv.h:1880
#define UNICODE_NULL
NTSTATUS Status
Definition: section.c:4934
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
void * PVOID
Definition: retypes.h:9
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
ULONG CheckSum
Definition: btrfs_drv.h:1886
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
LIST_ENTRY MmLoadedUserImageList
Definition: sysldr.c:22
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
Definition: btrfs_drv.h:1876
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
Definition: typedefs.h:119
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
LIST_ENTRY InLoadOrderLinks
Definition: ldrtypes.h:138
struct _FileName FileName
Definition: fatprocs.h:893
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1882
VOID NTAPI DbgLoadImageSymbols(_In_ PSTRING Name, _In_ PVOID Base, _In_ ULONG_PTR ProcessId)
#define RtlImageNtHeader
Definition: compat.h:806
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define memset(x, y, z)
Definition: compat.h:39
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
static const CHAR FileNameA[]
USHORT LoadCount
Definition: ntddk_ex.h:208

◆ MiLocateSubsection()

PSUBSECTION NTAPI MiLocateSubsection ( IN PMMVAD  Vad,
IN ULONG_PTR  Vpn 
)

Definition at line 556 of file section.c.

558 {
559  PSUBSECTION Subsection;
560  PCONTROL_AREA ControlArea;
561  ULONG_PTR PteOffset;
562 
563  /* Get the control area */
564  ControlArea = Vad->ControlArea;
565  ASSERT(ControlArea->u.Flags.Rom == 0);
566  ASSERT(ControlArea->u.Flags.Image == 0);
567  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
568 
569  /* Get the subsection */
570  Subsection = (PSUBSECTION)(ControlArea + 1);
571 
572  /* We only support single-subsection segments */
573  ASSERT(Subsection->SubsectionBase != NULL);
574  ASSERT(Vad->FirstPrototypePte >= Subsection->SubsectionBase);
575  ASSERT(Vad->FirstPrototypePte < &Subsection->SubsectionBase[Subsection->PtesInSubsection]);
576 
577  /* Compute the PTE offset */
578  PteOffset = Vpn - Vad->StartingVpn;
579  PteOffset += Vad->FirstPrototypePte - Subsection->SubsectionBase;
580 
581  /* Again, we only support single-subsection segments */
582  ASSERT(PteOffset < 0xF0000000);
583  ASSERT(PteOffset < Subsection->PtesInSubsection);
584 
585  /* Return the subsection */
586  return Subsection;
587 }
uint32_t ULONG_PTR
Definition: typedefs.h:65
ASSERT(Segment->Locked)
union _CONTROL_AREA::@2562 u
struct _SUBSECTION * PSUBSECTION
ULONG GlobalOnlyPerSession
Definition: mmtypes.h:488
#define NULL
Definition: types.h:112
MMSECTION_FLAGS Flags
Definition: mmtypes.h:528
PMMPTE SubsectionBase
Definition: mmtypes.h:578
ULONG PtesInSubsection
Definition: mmtypes.h:580

Referenced by MiDeleteVirtualAddresses().

◆ MiMakeProtectionMask()

ULONG NTAPI MiMakeProtectionMask ( IN ULONG  Protect)

Definition at line 140 of file section.c.

141 {
142  ULONG Mask1, Mask2, ProtectMask;
143 
144  /* PAGE_EXECUTE_WRITECOMBINE is theoretically the maximum */
145  if (Protect >= (PAGE_WRITECOMBINE * 2)) return MM_INVALID_PROTECTION;
146 
147  /*
148  * Windows API protection mask can be understood as two bitfields, differing
149  * by whether or not execute rights are being requested
150  */
151  Mask1 = Protect & 0xF;
152  Mask2 = (Protect >> 4) & 0xF;
153 
154  /* Check which field is there */
155  if (!Mask1)
156  {
157  /* Mask2 must be there, use it to determine the PTE protection */
158  if (!Mask2) return MM_INVALID_PROTECTION;
159  ProtectMask = MmUserProtectionToMask2[Mask2];
160  }
161  else
162  {
163  /* Mask2 should not be there, use Mask1 to determine the PTE mask */
164  if (Mask2) return MM_INVALID_PROTECTION;
165  ProtectMask = MmUserProtectionToMask1[Mask1];
166  }
167 
168  /* Make sure the final mask is a valid one */
169  if (ProtectMask == MM_INVALID_PROTECTION) return MM_INVALID_PROTECTION;
170 
171  /* Check for PAGE_GUARD option */
172  if (Protect & PAGE_GUARD)
173  {
174  /* It's not valid on no-access, nocache, or writecombine pages */
175  if ((ProtectMask == MM_NOACCESS) ||
177  {
178  /* Fail such requests */
179  return MM_INVALID_PROTECTION;
180  }
181 
182  /* This actually turns on guard page in this scenario! */
183  ProtectMask |= MM_GUARDPAGE;
184  }
185 
186  /* Check for nocache option */
187  if (Protect & PAGE_NOCACHE)
188  {
189  /* The earlier check should've eliminated this possibility */
190  ASSERT((Protect & PAGE_GUARD) == 0);
191 
192  /* Check for no-access page or write combine page */
193  if ((ProtectMask == MM_NOACCESS) || (Protect & PAGE_WRITECOMBINE))
194  {
195  /* Such a request is invalid */
196  return MM_INVALID_PROTECTION;
197  }
198 
199  /* Add the PTE flag */
200  ProtectMask |= MM_NOCACHE;
201  }
202 
203  /* Check for write combine option */
205  {
206  /* The two earlier scenarios should've caught this */
207  ASSERT((Protect & (PAGE_GUARD | PAGE_NOACCESS)) == 0);
208 
209  /* Don't allow on no-access pages */
210  if (ProtectMask == MM_NOACCESS) return MM_INVALID_PROTECTION;
211 
212  /* This actually turns on write-combine in this scenario! */
213  ProtectMask |= MM_NOACCESS;
214  }
215 
216  /* Return the final MM PTE protection mask */
217  return ProtectMask;
218 }
#define PAGE_NOCACHE
Definition: nt_native.h:1311
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
_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:214
CHAR MmUserProtectionToMask1[16]
Definition: section.c:44
#define PAGE_GUARD
Definition: nt_native.h:1310
#define MM_NOACCESS
Definition: miarm.h:65
#define MM_NOCACHE
Definition: miarm.h:56
ASSERT(Segment->Locked)
#define PAGE_NOACCESS
Definition: nt_native.h:1302
CHAR MmUserProtectionToMask2[16]
Definition: section.c:64
#define MM_GUARDPAGE
Definition: miarm.h:57
#define PAGE_WRITECOMBINE
Definition: mmtypes.h:78
unsigned int ULONG
Definition: retypes.h:1

Referenced by MiIsProtectionCompatible(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), MmCreateArm3Section(), MmCreateSection(), MmCreateVirtualMappingUnsafe(), MmInsertMemoryArea(), MmMapViewOfArm3Section(), MmSetPageProtect(), NtAllocateVirtualMemory(), and NtMapViewOfSection().

◆ MiMapViewInSystemSpace()

NTSTATUS MiMapViewInSystemSpace ( _In_ PVOID  Section,
_In_ PMMSESSION  Session,
_Outptr_result_bytebuffer_ *ViewSize PVOID MappedBase,
_Inout_ PSIZE_T  ViewSize,
_Inout_ PLARGE_INTEGER  SectionOffset 
)

Definition at line 1040 of file section.c.

1046 {
1047  PVOID Base;
1048  PCONTROL_AREA ControlArea;
1049  ULONG Buckets;
1050  LONGLONG SectionSize;
1051  NTSTATUS Status;
1052  PAGED_CODE();
1053 
1054  /* Get the control area, check for any flags ARM3 doesn't yet support */
1055  ControlArea = ((PSECTION)Section)->Segment->ControlArea;
1056  ASSERT(ControlArea->u.Flags.Image == 0);
1057  ASSERT(ControlArea->FilePointer == NULL);
1058  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
1059  ASSERT(ControlArea->u.Flags.Rom == 0);
1060  ASSERT(ControlArea->u.Flags.WasPurged == 0);
1061 
1062  /* Increase the reference and map count on the control area, no purges yet */
1063  Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
1065 
1066  /* Get the section size at creation time */
1067  SectionSize = ((PSECTION)Section)->SizeOfSection.QuadPart;
1068 
1069  /* If the caller didn't specify a view size, assume until the end of the section */
1070  if (!(*ViewSize))
1071  {
1072  /* Check for overflow first */
1073  if ((SectionSize - SectionOffset->QuadPart) > SIZE_T_MAX)
1074  {
1075  DPRINT1("Section end is too far away from the specified offset.\n");
1076  MiDereferenceControlArea(ControlArea);
1077  return STATUS_INVALID_VIEW_SIZE;
1078  }
1079  *ViewSize = SectionSize - SectionOffset->QuadPart;
1080  }
1081 
1082  /* Check overflow */
1083  if ((SectionOffset->QuadPart + *ViewSize) < SectionOffset->QuadPart)
1084  {
1085  DPRINT1("Integer overflow between size & offset!\n");
1086  MiDereferenceControlArea(ControlArea);
1087  return STATUS_INVALID_VIEW_SIZE;
1088  }
1089 
1090  /* Check if the caller wanted a larger section than the view */
1091  if (SectionOffset->QuadPart + *ViewSize > SectionSize)
1092  {
1093  /* Fail */
1094  DPRINT1("View is too large\n");
1095  MiDereferenceControlArea(ControlArea);
1096  return STATUS_INVALID_VIEW_SIZE;
1097  }
1098 
1099  /* Get the number of 64K buckets required for this mapping */
1100  Buckets = (ULONG)(*ViewSize / MI_SYSTEM_VIEW_BUCKET_SIZE);
1101  if (*ViewSize & (MI_SYSTEM_VIEW_BUCKET_SIZE - 1)) Buckets++;
1102 
1103  /* Check if the view is more than 4GB large */
1104  if (Buckets >= MI_SYSTEM_VIEW_BUCKET_SIZE)
1105  {
1106  /* Fail */
1107  DPRINT1("View is too large\n");
1108  MiDereferenceControlArea(ControlArea);
1109  return STATUS_INVALID_VIEW_SIZE;
1110  }
1111 
1112  /* Insert this view into system space and get a base address for it */
1113  Base = MiInsertInSystemSpace(Session, Buckets, ControlArea);
1114  if (!Base)
1115  {
1116  /* Fail */
1117  DPRINT1("Out of system space\n");
1118  MiDereferenceControlArea(ControlArea);
1119  return STATUS_NO_MEMORY;
1120  }
1121 
1122  /* What's the underlying session? */
1123  if (Session == &MmSession)
1124  {
1125  /* Create the PDEs needed for this mapping, and double-map them if needed */
1128  }
1129  else
1130  {
1131  /* Create the PDEs needed for this mapping */
1133  (PVOID)((ULONG_PTR)Base +
1134  Buckets * MI_SYSTEM_VIEW_BUCKET_SIZE));
1136  }
1137 
1138  /* Create the actual prototype PTEs for this mapping */
1141  ControlArea,
1142  SectionOffset->QuadPart);
1144 
1145  /* Return the base adress of the mapping and success */
1146  *MappedBase = Base;
1147  return STATUS_SUCCESS;
1148 }
PFILE_OBJECT FilePointer
Definition: mmtypes.h:530
#define SIZE_T_MAX
Definition: dhcpd.h:91
LONG NTSTATUS
Definition: precomp.h:26
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2427
NTSTATUS NTAPI MiSessionCommitPageTables(IN PVOID StartVa, IN PVOID EndVa)
Definition: section.c:924
struct _CONTROL_AREA * ControlArea
Definition: mmtypes.h:406
uint32_t ULONG_PTR
Definition: typedefs.h:65
NTSTATUS NTAPI MiCheckPurgeAndUpMapCount(IN PCONTROL_AREA ControlArea, IN BOOLEAN FailIfSystemViews)
Definition: section.c:530
VOID NTAPI MiDereferenceControlArea(IN PCONTROL_AREA ControlArea)
Definition: section.c:749
ASSERT(Segment->Locked)
#define MiAddressToPte(x)
Definition: mmx86.c:19
static NTSTATUS MiAddMappedPtes(IN PMMPTE FirstPte, IN PFN_NUMBER PteCount, IN PCONTROL_AREA ControlArea, IN LONGLONG SectionOffset)
Definition: section.c:399
NTSTATUS Status
Definition: section.c:4934
union _CONTROL_AREA::@2562 u
return FALSE
Definition: section.c:5098
struct _SECTION * PSECTION
PVOID NTAPI MiInsertInSystemSpace(IN PMMSESSION Session, IN ULONG Buckets, IN PCONTROL_AREA ControlArea)
Definition: section.c:288
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER SectionOffset
Definition: mmfuncs.h:404
Status
Definition: gdiplustypes.h:24
int64_t LONGLONG
Definition: typedefs.h:68
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID NTAPI MiFillSystemPageDirectory(IN PVOID Base, IN SIZE_T NumberOfBytes)
Definition: section.c:462
#define BYTES_TO_PAGES(Size)
ULONG GlobalOnlyPerSession
Definition: mmtypes.h:488
#define STATUS_INVALID_VIEW_SIZE
Definition: ntstatus.h:268
#define MI_SYSTEM_VIEW_BUCKET_SIZE
Definition: miarm.h:266
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
PSEGMENT Segment
Definition: mmtypes.h:518
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ _Outptr_result_bytebuffer_ ViewSize PVOID * MappedBase
Definition: mmfuncs.h:492
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:404
ULONG WasPurged
Definition: mmtypes.h:475
MMSECTION_FLAGS Flags
Definition: mmtypes.h:528
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
#define PAGED_CODE()
MMSESSION MmSession
Definition: section.c:107

Referenced by MmMapViewInSessionSpace(), and MmMapViewInSystemSpaceEx().

◆ MiMapViewOfDataSection()

NTSTATUS NTAPI MiMapViewOfDataSection ( IN PCONTROL_AREA  ControlArea,
IN PEPROCESS  Process,
IN PVOID BaseAddress,
IN PLARGE_INTEGER  SectionOffset,
IN PSIZE_T  ViewSize,
IN PSECTION  Section,
IN SECTION_INHERIT  InheritDisposition,
IN ULONG  ProtectionMask,
IN SIZE_T  CommitSize,
IN ULONG_PTR  ZeroBits,
IN ULONG  AllocationType 
)

Definition at line 1264 of file section.c.

1275 {
1276  PMMVAD_LONG Vad;
1277  ULONG_PTR StartAddress;
1278  ULONG_PTR ViewSizeInPages;
1279  PSUBSECTION Subsection;
1280  PSEGMENT Segment;
1281  PFN_NUMBER PteOffset;
1282  NTSTATUS Status;
1283  ULONG QuotaCharge = 0, QuotaExcess = 0;
1284  PMMPTE PointerPte, LastPte;
1285  MMPTE TempPte;
1286  ULONG Granularity = MM_VIRTMEM_GRANULARITY;
1287 
1288  DPRINT("Mapping ARM3 data section\n");
1289 
1290  /* Get the segment for this section */
1291  Segment = ControlArea->Segment;
1292 
1293 #ifdef _M_IX86
1294  /* ALlow being less restrictive on x86. */
1296  Granularity = PAGE_SIZE;
1297 #endif
1298 
1299  /* One can only reserve a file-based mapping, not shared memory! */
1300  if ((AllocationType & MEM_RESERVE) && !(ControlArea->FilePointer))
1301  {
1303  }
1304 
1305  /* First, increase the map count. No purging is supported yet */
1306  Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
1307  if (!NT_SUCCESS(Status)) return Status;
1308 
1309  /* Check if the caller specified the view size */
1310  if (!(*ViewSize))
1311  {
1312  LONGLONG ViewSizeLL;
1313 
1314  /* The caller did not, so pick a 64K aligned view size based on the offset */
1315  SectionOffset->LowPart &= ~(_64K - 1);
1316 
1317  /* Calculate size and make sure this fits */
1318  if (!NT_SUCCESS(RtlLongLongSub(Section->SizeOfSection.QuadPart, SectionOffset->QuadPart, &ViewSizeLL))
1319  || !NT_SUCCESS(RtlLongLongToSIZET(ViewSizeLL, ViewSize))
1320  || (*ViewSize > MAXLONG_PTR))
1321  {
1322  MiDereferenceControlArea(ControlArea);
1323  return STATUS_INVALID_VIEW_SIZE;
1324  }
1325  }
1326  else
1327  {
1328  /* A size was specified, align it to a 64K boundary
1329  * and check for overflow or huge value. */
1330  if (!NT_SUCCESS(RtlSIZETAdd(*ViewSize, SectionOffset->LowPart & (_64K - 1), ViewSize))
1331  || (*ViewSize > MAXLONG_PTR))
1332  {
1333  MiDereferenceControlArea(ControlArea);
1334  return STATUS_INVALID_VIEW_SIZE;
1335  }
1336 
1337  /* Align the offset as well to make this an aligned map */
1338  SectionOffset->LowPart &= ~((ULONG)_64K - 1);
1339  }
1340 
1341  /* We must be dealing with a 64KB aligned offset. This is a Windows ASSERT */
1342  ASSERT((SectionOffset->LowPart & ((ULONG)_64K - 1)) == 0);
1343 
1344  /* Windows ASSERTs for this flag */
1345  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
1346 
1347  /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
1348  ASSERT(ControlArea->u.Flags.Rom == 0);
1349  Subsection = (PSUBSECTION)(ControlArea + 1);
1350 
1351  /* Sections with extended segments are not supported in ARM3 */
1352  ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0);
1353 
1354  /* Within this section, figure out which PTEs will describe the view */
1355  PteOffset = (PFN_NUMBER)(SectionOffset->QuadPart >> PAGE_SHIFT);
1356 
1357  /* The offset must be in this segment's PTE chunk and it must be valid. Windows ASSERTs */
1358  ASSERT(PteOffset < Segment->TotalNumberOfPtes);
1359  ASSERT(((SectionOffset->QuadPart + *ViewSize + PAGE_SIZE - 1) >> PAGE_SHIFT) >= PteOffset);
1360 
1361  /* In ARM3, only one subsection is used for now. It must contain these PTEs */
1362  ASSERT(PteOffset < Subsection->PtesInSubsection);
1363 
1364  /* In ARM3, only page-file backed sections (shared memory) are supported now */
1365  ASSERT(ControlArea->FilePointer == NULL);
1366 
1367  /* Windows ASSERTs for this too -- there must be a subsection base address */
1368  ASSERT(Subsection->SubsectionBase != NULL);
1369 
1370  /* Compute how much commit space the segment will take */
1371  if ((CommitSize) && (Segment->NumberOfCommittedPages < Segment->TotalNumberOfPtes))
1372  {
1373  /* Charge for the maximum pages */
1374  QuotaCharge = BYTES_TO_PAGES(CommitSize);
1375  }
1376 
1377  /* ARM3 does not currently support large pages */
1378  ASSERT(Segment->SegmentFlags.LargePages == 0);
1379 
1380  /* Calculate how many pages the region spans */
1381  ViewSizeInPages = BYTES_TO_PAGES(*ViewSize);
1382 
1383  /* A VAD can now be allocated. Do so and zero it out */
1384  /* FIXME: we are allocating a LONG VAD for ReactOS compatibility only */
1385  ASSERT((AllocationType & MEM_RESERVE) == 0); /* ARM3 does not support this */
1386  Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
1387  if (!Vad)
1388  {
1389  MiDereferenceControlArea(ControlArea);
1391  }
1392 
1393  RtlZeroMemory(Vad, sizeof(MMVAD_LONG));
1394  Vad->u4.Banked = (PVOID)(ULONG_PTR)0xDEADBABEDEADBABEULL;
1395 
1396  /* Write all the data required in the VAD for handling a fault */
1397  Vad->ControlArea = ControlArea;
1398  Vad->u.VadFlags.CommitCharge = 0;
1399  Vad->u.VadFlags.Protection = ProtectionMask;
1400  Vad->u2.VadFlags2.FileOffset = (ULONG)(SectionOffset->QuadPart >> 16);
1402  if ((AllocationType & SEC_NO_CHANGE) || (Section->u.Flags.NoChange))
1403  {
1404  /* This isn't really implemented yet, but handle setting the flag */
1405  Vad->u.VadFlags.NoChange = 1;
1406  Vad->u2.VadFlags2.SecNoChange = 1;
1407  }
1408 
1409  /* Finally, write down the first and last prototype PTE */
1410  Vad->FirstPrototypePte = &Subsection->SubsectionBase[PteOffset];
1411  PteOffset += ViewSizeInPages - 1;
1412  ASSERT(PteOffset < Subsection->PtesInSubsection);
1413  Vad->LastContiguousPte = &Subsection->SubsectionBase[PteOffset];
1414 
1415  /* Make sure the prototype PTE ranges make sense, this is a Windows ASSERT */
1417 
1418  /* FIXME: Should setup VAD bitmap */
1420 
1421  /* Check if anything was committed */
1422  if (QuotaCharge)
1423  {
1424  /* Set the start and end PTE addresses, and pick the template PTE */
1425  PointerPte = Vad->FirstPrototypePte;
1426  LastPte = PointerPte + BYTES_TO_PAGES(CommitSize);
1427  TempPte = Segment->SegmentPteTemplate;
1428 
1429  /* Acquire the commit lock and loop all prototype PTEs to be committed */
1431  while (PointerPte < LastPte)
1432  {
1433  /* Make sure the PTE is already invalid */
1434  if (PointerPte->u.Long == 0)
1435  {
1436  /* And write the invalid PTE */
1437  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
1438  }
1439  else
1440  {
1441  /* The PTE is valid, so skip it */
1442  QuotaExcess++;
1443  }
1444 
1445  /* Move to the next PTE */
1446  PointerPte++;
1447  }
1448 
1449  /* Now check how many pages exactly we committed, and update accounting */
1450  ASSERT(QuotaCharge >= QuotaExcess);
1451  QuotaCharge -= QuotaExcess;
1452  Segment->NumberOfCommittedPages += QuotaCharge;
1453  ASSERT(Segment->NumberOfCommittedPages <= Segment->TotalNumberOfPtes);
1454 
1455  /* Now that we're done, release the lock */
1457  }
1458 
1459  /* Is it SEC_BASED, or did the caller manually specify an address? */
1460  if (*BaseAddress != NULL)
1461  {
1462  /* Just align what the caller gave us */
1463  StartAddress = ALIGN_DOWN_BY((ULONG_PTR)*BaseAddress, Granularity);
1464  }
1465  else if (Section->Address.StartingVpn != 0)
1466  {
1467  /* It is a SEC_BASED mapping, use the address that was generated */
1468  StartAddress = Section->Address.StartingVpn + SectionOffset->LowPart;
1469  }
1470  else
1471  {
1472  StartAddress = 0;
1473  }
1474 
1476  if (!NT_SUCCESS(Status))
1477  {
1478  ExFreePoolWithTag(Vad, 'ldaV');
1479  MiDereferenceControlArea(ControlArea);
1480 
1482  Segment->NumberOfCommittedPages -= QuotaCharge;
1484  return Status;
1485  }
1486 
1487  /* Insert the VAD */
1488  Status = MiInsertVadEx((PMMVAD)Vad,
1489  &StartAddress,
1490  ViewSizeInPages * PAGE_SIZE,
1492  Granularity,
1493  AllocationType);
1494  if (!NT_SUCCESS(Status))
1495  {
1496  ExFreePoolWithTag(Vad, 'ldaV');
1497  MiDereferenceControlArea(ControlArea);
1498 
1500  Segment->NumberOfCommittedPages -= QuotaCharge;
1502 
1504  return Status;
1505  }
1506 
1507  /* Windows stores this for accounting purposes, do so as well */
1508  if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
1509 
1510  /* Finally, let the caller know where, and for what size, the view was mapped */
1511  *ViewSize = ViewSizeInPages * PAGE_SIZE;
1512  *BaseAddress = (PVOID)StartAddress;
1513  DPRINT("Start and region: 0x%p, 0x%p\n", *BaseAddress, *ViewSize);
1514  return STATUS_SUCCESS;
1515 }
_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:404
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR ZeroBits
Definition: mmfuncs.h:404
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define MM_VIRTMEM_GRANULARITY
Definition: mm.h:102
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS NTAPI PsChargeProcessNonPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Charges the non paged pool quota of a given process.
Definition: quota.c:811
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
union _MMPTE::@2288 u
PMMPTE LastContiguousPte
Definition: mmtypes.h:764
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:760
ULONG_PTR CommitCharge
Definition: mmtypes.h:688
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_PARAMETER_9
Definition: ntstatus.h:483
#define MAXULONG_PTR
Definition: basetsd.h:103
ULONG SecNoChange
Definition: mmtypes.h:704
PCONTROL_AREA ControlArea
Definition: mmtypes.h:762
ULONG_PTR Protection
Definition: mmtypes.h:693
ULONG_PTR NoChange
Definition: mmtypes.h:690
uint32_t ULONG_PTR
Definition: typedefs.h:65
NTSTATUS NTAPI MiCheckPurgeAndUpMapCount(IN PCONTROL_AREA ControlArea, IN BOOLEAN FailIfSystemViews)
Definition: section.c:530
VOID NTAPI MiDereferenceControlArea(IN PCONTROL_AREA ControlArea)
Definition: section.c:749
ASSERT(Segment->Locked)
ULONG PFN_NUMBER
Definition: ke.h:9
#define MEM_RESERVE
Definition: nt_native.h:1314
NTSTATUS Status
Definition: section.c:4934
#define PsGetCurrentProcess
Definition: psfuncs.h:17
PVOID Banked
Definition: mmtypes.h:777
return FALSE
Definition: section.c:5098
void * PVOID
Definition: retypes.h:9
#define ULL(a, b)
Definition: format_msg.c:27
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER SectionOffset
Definition: mmfuncs.h:404
ULONG FileOffset
Definition: mmtypes.h:703
#define MEM_DOS_LIM
Definition: mmtypes.h:89
Status
Definition: gdiplustypes.h:24
int64_t LONGLONG
Definition: typedefs.h:68
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
NTSTATUS NTAPI MiInsertVadEx(_Inout_ PMMVAD Vad, _In_ ULONG_PTR *BaseAddress, _In_ SIZE_T ViewSize, _In_ ULONG_PTR HighestAddress, _In_ ULONG_PTR Alignment, _In_ ULONG AllocationType)
Definition: vadnode.c:204
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:404
MMVAD_FLAGS2 VadFlags2
Definition: mmtypes.h:768
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
struct _SUBSECTION * PSUBSECTION
#define BYTES_TO_PAGES(Size)
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_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:404
#define _64K
Definition: miarm.h:23
KGUARDED_MUTEX MmSectionCommitMutex
Definition: section.c:108
ULONG Inherit
Definition: mmtypes.h:710
ULONG_PTR Long
Definition: mmtypes.h:215
#define ALIGN_DOWN_BY(size, align)
union _MMVAD_LONG::@2573 u2
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:997
#define STATUS_INVALID_VIEW_SIZE
Definition: ntstatus.h:268
DPRINT("Checking segment for file %wZ at offset 0x%I64X.\n", &Segment->FileObject->FileName, Offset->QuadPart)
#define NULL
Definition: types.h:112
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
union _MMVAD_LONG::@2575 u4
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:404
unsigned int ULONG
Definition: retypes.h:1
PMMPTE FirstPrototypePte
Definition: mmtypes.h:763
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_SUCCESS
Definition: shellext.h:65
VOID NTAPI PsReturnProcessNonPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the non paged quota pool that the process was taking up.
Definition: quota.c:938
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define SEC_NO_CHANGE
Definition: mmtypes.h:94
PMMPTE SubsectionBase
Definition: mmtypes.h:578
#define MAXLONG_PTR
Definition: basetsd.h:104
union _MMVAD_LONG::@2572 u

Referenced by MmMapViewOfArm3Section().

◆ MiQueryMemorySectionName()

NTSTATUS NTAPI MiQueryMemorySectionName ( IN HANDLE  ProcessHandle,
IN PVOID  BaseAddress,
OUT PVOID  MemoryInformation,
IN SIZE_T  MemoryInformationLength,
OUT PSIZE_T  ReturnLength 
)

Definition at line 1948 of file section.c.

1953 {
1955  NTSTATUS Status;
1957  PMEMORY_SECTION_NAME SectionName = NULL;
1959 
1962  NULL,
1963  PreviousMode,
1964  (PVOID*)(&Process),
1965  NULL);
1966 
1967  if (!NT_SUCCESS(Status))
1968  {
1969  DPRINT("MiQueryMemorySectionName: ObReferenceObjectByHandle returned %x\n",Status);
1970  return Status;
1971  }
1972 
1974 
1975  if (NT_SUCCESS(Status))
1976  {
1977  SectionName = MemoryInformation;
1978  if (PreviousMode != KernelMode)
1979  {
1980  _SEH2_TRY
1981  {
1982  RtlInitEmptyUnicodeString(&SectionName->SectionFileName,
1983  (PWSTR)(SectionName + 1),
1984  MemoryInformationLength - sizeof(MEMORY_SECTION_NAME));
1986 
1988 
1989  }
1991  {
1993  }
1994  _SEH2_END;
1995  }
1996  else
1997  {
1998  RtlInitEmptyUnicodeString(&SectionName->SectionFileName,
1999  (PWSTR)(SectionName + 1),
2000  MemoryInformationLength - sizeof(MEMORY_SECTION_NAME));
2002 
2004 
2005  }
2006 
2008  }
2010  return Status;
2011 }
_SEH2_TRY
Definition: create.c:4226
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
NTSTATUS NTAPI MmGetFileNameForAddress(IN PVOID Address, OUT PUNICODE_STRING ModuleName)
Definition: section.c:1885
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:166
uint16_t * PWSTR
Definition: typedefs.h:56
LONG NTSTATUS
Definition: precomp.h:26
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3062
_SEH2_END
Definition: create.c:4400
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
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
NTSTATUS Status
Definition: section.c:4934
TCHAR ModuleFileName[MAX_PATH+1]
Definition: rundll32.c:55
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ObDereferenceObject
Definition: obfuncs.h:203
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
UNICODE_STRING SectionFileName
Definition: mmtypes.h:323
struct _MEMORY_SECTION_NAME MEMORY_SECTION_NAME
DPRINT("Checking segment for file %wZ at offset 0x%I64X.\n", &Segment->FileObject->FileName, Offset->QuadPart)
#define NULL
Definition: types.h:112
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403

Referenced by NtQueryVirtualMemory().

◆ MiRemoveFromSystemSpace()

ULONG NTAPI MiRemoveFromSystemSpace ( IN PMMSESSION  Session,
IN PVOID  Base,
OUT PCONTROL_AREA ControlArea 
)

Definition at line 2390 of file section.c.

2393 {
2394  ULONG Hash, Size, Count = 0;
2395  ULONG_PTR Entry;
2396  PAGED_CODE();
2397 
2398  /* Compute the hash for this entry and loop trying to find it */
2399  Entry = (ULONG_PTR)Base >> 16;
2400  Hash = Entry % Session->SystemSpaceHashKey;
2401  while ((Session->SystemSpaceViewTable[Hash].Entry >> 16) != Entry)
2402  {
2403  /* Check if we overflew past the end of the hash table */
2404  if (++Hash >= Session->SystemSpaceHashSize)
2405  {
2406  /* Reset the hash to zero and keep searching from the bottom */
2407  Hash = 0;
2408  if (++Count == 2)
2409  {
2410  /* But if we overflew twice, then this is not a real mapping */
2411  KeBugCheckEx(DRIVER_UNMAPPING_INVALID_VIEW,
2412  (ULONG_PTR)Base,
2413  1,
2414  0,
2415  0);
2416  }
2417  }
2418  }
2419 
2420  /* One less entry */
2421  Session->SystemSpaceHashEntries--;
2422 
2423  /* Extract the size and clear the entry */
2424  Size = Session->SystemSpaceViewTable[Hash].Entry & 0xFFFF;
2425  Session->SystemSpaceViewTable[Hash].Entry = 0;
2426 
2427  /* Return the control area and the size */
2428  *ControlArea = Session->SystemSpaceViewTable[Hash].ControlArea;
2429  return Size;
2430 }
static int Hash(const char *)
Definition: reader.c:2257
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2427
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
uint32_t ULONG_PTR
Definition: typedefs.h:65
Entry
Definition: section.c:4943
int Count
Definition: noreturn.cpp:7
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
base of all file and directory entries
Definition: entries.h:82
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
#define PAGED_CODE()

Referenced by MiUnmapViewInSystemSpace().

◆ MiRemoveMappedPtes()

VOID NTAPI MiRemoveMappedPtes ( IN PVOID  BaseAddress,
IN ULONG  NumberOfPtes,
IN PCONTROL_AREA  ControlArea,
IN PMMSUPPORT  Ws 
)

Definition at line 2288 of file section.c.

2292 {
2293  PMMPTE PointerPte, ProtoPte;//, FirstPte;
2294  PMMPDE PointerPde, SystemMapPde;
2295  PMMPFN Pfn1, Pfn2;
2296  MMPTE PteContents;
2297  KIRQL OldIrql;
2298  DPRINT("Removing mapped view at: 0x%p\n", BaseAddress);
2299 
2300  ASSERT(Ws == NULL);
2301 
2302  /* Get the PTE and loop each one */
2303  PointerPte = MiAddressToPte(BaseAddress);
2304  //FirstPte = PointerPte;
2305  while (NumberOfPtes)
2306  {
2307  /* Check if the PTE is already valid */
2308  PteContents = *PointerPte;
2309  if (PteContents.u.Hard.Valid == 1)
2310  {
2311  /* Get the PFN entry */
2312  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2313 
2314  /* Get the PTE */
2315  PointerPde = MiPteToPde(PointerPte);
2316 
2317  /* Lock the PFN database and make sure this isn't a mapped file */
2318  OldIrql = MiAcquirePfnLock();
2319  ASSERT(((Pfn1->u3.e1.PrototypePte) && (Pfn1->OriginalPte.u.Soft.Prototype)) == 0);
2320 
2321  /* Mark the page as modified accordingly */
2322  if (MI_IS_PAGE_DIRTY(&PteContents))
2323  Pfn1->u3.e1.Modified = 1;
2324 
2325  /* Was the PDE invalid */
2326  if (PointerPde->u.Long == 0)
2327  {
2328 #if (_MI_PAGING_LEVELS == 2)
2329  /* Find the system double-mapped PDE that describes this mapping */
2330  SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
2331 
2332  /* Make it valid */
2333  ASSERT(SystemMapPde->u.Hard.Valid == 1);
2334  MI_WRITE_VALID_PDE(PointerPde, *SystemMapPde);
2335 #else
2336  DBG_UNREFERENCED_LOCAL_VARIABLE(SystemMapPde);
2337  ASSERT(FALSE);
2338 #endif
2339  }
2340 
2341  /* Dereference the PDE and the PTE */
2342  Pfn2 = MiGetPfnEntry(PFN_FROM_PTE(PointerPde));
2343  MiDecrementShareCount(Pfn2, PFN_FROM_PTE(PointerPde));
2345  MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
2346 
2347  /* Release the PFN lock */
2348  MiReleasePfnLock(OldIrql);
2349  }
2350  else
2351  {
2352  /* Windows ASSERT */
2353  ASSERT((PteContents.u.Long == 0) || (PteContents.u.Soft.Prototype == 1));
2354 
2355  /* Check if this is a prototype pointer PTE */
2356  if (PteContents.u.Soft.Prototype == 1)
2357  {
2358  /* Get the prototype PTE */
2359  ProtoPte = MiProtoPteToPte(&PteContents);
2360 
2361  /* We don't support anything else atm */
2362  ASSERT(ProtoPte->u.Long == 0);
2363  }
2364  }
2365 
2366  /* Make the PTE into a zero PTE */
2367  PointerPte->u.Long = 0;
2368 
2369  /* Move to the next PTE */
2370  PointerPte++;
2371  NumberOfPtes--;
2372  }
2373 
2374  /* Flush the TLB */
2375  KeFlushCurrentTb();
2376 
2377  /* Acquire the PFN lock */
2378  OldIrql = MiAcquirePfnLock();
2379 
2380  /* Decrement the accounting counters */
2381  ControlArea->NumberOfUserReferences--;
2382  ControlArea->NumberOfMappedViews--;
2383 
2384  /* Check if we should destroy the CA and release the lock */
2385  MiCheckControlArea(ControlArea, OldIrql);
2386 }
union _MMPTE::@2288 u
union _MMPFN::@1757 u3
USHORT Modified
Definition: mm.h:360
FORCEINLINE PMMPDE MiPteToPde(PMMPTE PointerPte)
Definition: mm.h:268
USHORT PrototypePte
Definition: mm.h:363
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:397
ASSERT(Segment->Locked)
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define MiProtoPteToPte(x)
Definition: mm.h:316
return FALSE
Definition: section.c:5098
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1133
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:1023
PMMPDE MmSystemPagePtes
Definition: init.c:41
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:319
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG64 Valid
Definition: mmtypes.h:150
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
Definition: mm.h:373
ULONG64 Prototype
Definition: mmtypes.h:89
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define SYSTEM_PD_SIZE
Definition: miarm.h:32
DPRINT("Checking segment for file %wZ at offset 0x%I64X.\n", &Segment->FileObject->FileName, Offset->QuadPart)
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
#define NULL
Definition: types.h:112
MMPTE OriginalPte
Definition: mm.h:407
VOID NTAPI MiCheckControlArea(IN PCONTROL_AREA ControlArea, IN KIRQL OldIrql)
Definition: section.c:714
#define MI_IS_PAGE_DIRTY(x)
Definition: mm.h:112
#define ULONG_PTR
Definition: config.h:101
#define PFN_FROM_PTE(v)
Definition: mm.h:92
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:347

Referenced by MiUnmapViewInSystemSpace().

◆ MiRemoveMappedView()

VOID NTAPI MiRemoveMappedView ( IN PEPROCESS  CurrentProcess,
IN PMMVAD  Vad 
)

Definition at line 766 of file section.c.

768 {
769  KIRQL OldIrql;
770  PCONTROL_AREA ControlArea;
771  PETHREAD CurrentThread = PsGetCurrentThread();
772 
773  /* Get the control area */
774  ControlArea = Vad->ControlArea;
775 
776  /* We only support non-extendable, non-image, pagefile-backed regular sections */
777  ASSERT(Vad->u.VadFlags.VadType == VadNone);
778  ASSERT(Vad->u2.VadFlags2.ExtendableFile == FALSE);
779  ASSERT(ControlArea);
780  ASSERT(ControlArea->FilePointer == NULL);
781 
782  /* Delete the actual virtual memory pages */
783  MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
784  (Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
785  Vad);
786 
787  /* Release the working set */
789 
790  /* Lock the PFN database */
791  OldIrql = MiAcquirePfnLock();
792 
793  /* Remove references */
794  ControlArea->NumberOfMappedViews--;
795  ControlArea->NumberOfUserReferences--;
796 
797  /* Check if it should be destroyed */
798  MiCheckControlArea(ControlArea, OldIrql);
799 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
PFILE_OBJECT FilePointer
Definition: mmtypes.h:530
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1244
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
UCHAR KIRQL
Definition: env_spec_w32.h:591
ASSERT(Segment->Locked)
return FALSE
Definition: section.c:5098
ULONG CurrentProcess
Definition: shell.c:125
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG NumberOfMappedViews
Definition: mmtypes.h:522
VOID NTAPI MiDeleteVirtualAddresses(IN ULONG_PTR Va, IN ULONG_PTR EndingAddress, IN PMMVAD Vad)
Definition: virtual.c:530
ULONG NumberOfUserReferences
Definition: mmtypes.h:524
#define NULL
Definition: types.h:112
VOID NTAPI MiCheckControlArea(IN PCONTROL_AREA ControlArea, IN KIRQL OldIrql)
Definition: section.c:714

Referenced by MiUnmapViewOfSection(), and MmCleanProcessAddressSpace().

◆ MiSegmentDelete()

VOID NTAPI MiSegmentDelete ( IN PSEGMENT  Segment)

Definition at line 591 of file section.c.

592 {
593  PCONTROL_AREA ControlArea;
594  SEGMENT_FLAGS SegmentFlags;
595  PSUBSECTION Subsection;
596  PMMPTE PointerPte, LastPte, PteForProto;
597  PMMPFN Pfn1;
598  PFN_NUMBER PageFrameIndex;
599  MMPTE TempPte;
600  KIRQL OldIrql;
601 
602  /* Capture data */
603  SegmentFlags = Segment->SegmentFlags;
604  ControlArea = Segment->ControlArea;
605 
606  /* Make sure control area is on the right delete path */
607  ASSERT(ControlArea->u.Flags.BeingDeleted == 1);
608  ASSERT(ControlArea->WritableUserReferences == 0);
609 
610  /* These things are not supported yet */
611  ASSERT(ControlArea->DereferenceList.Flink == NULL);
612  ASSERT(!(ControlArea->u.Flags.Image) && !(ControlArea->u.Flags.File));
613  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
614  ASSERT(ControlArea->u.Flags.Rom == 0);
615 
616  /* Get the subsection and PTEs for this segment */
617  Subsection = (PSUBSECTION)(ControlArea + 1);
618  PointerPte = Subsection->SubsectionBase;
619  LastPte = PointerPte + Segment->NonExtendedPtes;
620 
621  /* Lock the PFN database */
622  OldIrql = MiAcquirePfnLock();
623 
624  /* Check if the master PTE is invalid */
625  PteForProto = MiAddressToPte(PointerPte);
626  if (!PteForProto->u.Hard.Valid)
627  {
628  /* Fault it in */
630  }
631 
632  /* Loop all the segment PTEs */
633  while (PointerPte < LastPte)
634  {
635  /* Check if it's time to switch master PTEs if we passed a PDE boundary */
636  if (MiIsPteOnPdeBoundary(PointerPte) &&
637  (PointerPte != Subsection->SubsectionBase))
638  {
639  /* Check if the master PTE is invalid */
640  PteForProto = MiAddressToPte(PointerPte);
641  if (!PteForProto->u.Hard.Valid)
642  {
643  /* Fault it in */
645  }
646  }
647 
648  /* This should be a prototype PTE */
649  TempPte = *PointerPte;
650  ASSERT(SegmentFlags.LargePages == 0);
651  ASSERT(TempPte.u.Hard.Valid == 0);
652 
653  /* See if we should clean things up */
654  if (!(ControlArea->u.Flags.Image) && !(ControlArea->u.Flags.File))
655  {
656  /*
657  * This is a section backed by the pagefile. Now that it doesn't exist anymore,
658  * we can give everything back to the system.
659  */
660  ASSERT(TempPte.u.Soft.Prototype == 0);
661 
662  if (TempPte.u.Soft.Transition == 1)
663  {
664  /* We can give the page back for other use */
665  DPRINT("Releasing page for transition PTE %p\n", PointerPte);
666  PageFrameIndex = PFN_FROM_PTE(&TempPte);
667  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
668 
669  /* As this is a paged-backed section, nobody should reference it anymore (no cache or whatever) */
670  ASSERT(Pfn1->u3.ReferenceCount == 0);
671 
672  /* And it should be in standby or modified list */
674 
675  /* Unlink it and put it back in free list */
676  MiUnlinkPageFromList(Pfn1);
677 
678  /* Temporarily mark this as active and make it free again */
680  MI_SET_PFN_DELETED(Pfn1);
681 
682  MiInsertPageInFreeList(PageFrameIndex);
683  }
684  else if (TempPte.u.Soft.PageFileHigh != 0)
685  {
686  /* Should not happen for now */
687  ASSERT(FALSE);
688  }
689  }
690  else
691  {
692  /* unsupported for now */
693  ASSERT(FALSE);
694 
695  /* File-backed section must have prototype PTEs */
696  ASSERT(TempPte.u.Soft.Prototype == 1);
697  }
698 
699  /* Zero the PTE and keep going */
700  PointerPte->u.Long = 0;
701  PointerPte++;
702  }
703 
704  /* Release the PFN lock */
705  MiReleasePfnLock(OldIrql);
706 
707  /* Free the structures */
708  ExFreePool(ControlArea);
710 }
ULONG NTAPI MiMakeSystemAddressValidPfn(IN PVOID VirtualAddress, IN KIRQL OldIrql)
Definition: virtual.c:235
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:603
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:265
union _MMPTE::@2288 u
union _MMPFN::@1757 u3
ULONG LargePages
Definition: mmtypes.h:400
USHORT ReferenceCount
Definition: mm.h:396
USHORT PageLocation
Definition: mm.h:365
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:397
ASSERT(Segment->Locked)
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG PFN_NUMBER
Definition: ke.h:9
union _CONTROL_AREA::@2562 u
return FALSE
Definition: section.c:5098
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
LIST_ENTRY DereferenceList
Definition: mmtypes.h:519
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
ULONG64 Valid
Definition: mmtypes.h:150
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
struct _SUBSECTION * PSUBSECTION
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
Definition: mm.h:373
ULONG GlobalOnlyPerSession
Definition: mmtypes.h:488
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:194
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:306
ULONG BeingDeleted
Definition: mmtypes.h:460
ULONG WritableUserReferences
Definition: mmtypes.h:534
DPRINT("Checking segment for file %wZ at offset 0x%I64X.\n", &Segment->FileObject->FileName, Offset->QuadPart)
#define NULL
Definition: types.h:112
MMSECTION_FLAGS Flags
Definition: mmtypes.h:528
#define PFN_FROM_PTE(v)
Definition: mm.h:92
PMMPTE SubsectionBase
Definition: mmtypes.h:578
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by MiCheckControlArea().

◆ MiSessionCommitPageTables()

NTSTATUS NTAPI MiSessionCommitPageTables ( IN PVOID  StartVa,
IN PVOID  EndVa 
)

Definition at line 924 of file section.c.

926 {
927  KIRQL OldIrql;
928  ULONG Color, Index;
929  PMMPDE StartPde, EndPde;
931  PMMPFN Pfn1;
932  PFN_NUMBER PageCount = 0, ActualPages = 0, PageFrameNumber;
933 
934  /* Windows sanity checks */
935  ASSERT(StartVa >= (PVOID)MmSessionBase);
936  ASSERT(EndVa < (PVOID)MiSessionSpaceEnd);
937  ASSERT(PAGE_ALIGN(EndVa) == EndVa);
938 
939  /* Get the start and end PDE, then loop each one */
940  StartPde = MiAddressToPde(StartVa);
941  EndPde = MiAddressToPde((PVOID)((ULONG_PTR)EndVa - 1));
942  Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
943  while (StartPde <= EndPde)
944  {
945 #ifndef _M_AMD64
946  /* If we don't already have a page table for it, increment count */
947  if (MmSessionSpace->PageTables[Index].u.Long == 0) PageCount++;
948 #endif
949  /* Move to the next one */
950  StartPde++;
951  Index++;
952  }
953 
954  /* If there's no page tables to create, bail out */
955  if (PageCount == 0) return STATUS_SUCCESS;
956 
957  /* Reset the start PDE and index */
958  StartPde = MiAddressToPde(StartVa);
959  Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
960 
961  /* Loop each PDE while holding the working set lock */
962 // MiLockWorkingSet(PsGetCurrentThread(),
963 // &MmSessionSpace->GlobalVirtualAddress->Vm);
964 #ifdef _M_AMD64
965 _WARN("MiSessionCommitPageTables halfplemented for amd64")
970  DBG_UNREFERENCED_LOCAL_VARIABLE(PageFrameNumber);
971  ASSERT(FALSE);
972 #else
973  while (StartPde <= EndPde)
974  {
975  /* Check if we already have a page table */
976  if (MmSessionSpace->PageTables[Index].u.Long == 0)
977  {
978  /* We don't, so the PDE shouldn't be ready yet */
979  ASSERT(StartPde->u.Hard.Valid == 0);
980 
981  /* ReactOS check to avoid MiEnsureAvailablePageOrWait */
982  ASSERT(MmAvailablePages >= 32);
983 
984  /* Acquire the PFN lock and grab a zero page */
985  OldIrql = MiAcquirePfnLock();
987  MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
989  PageFrameNumber = MiRemoveZeroPage(Color);
990  TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
991  MI_WRITE_VALID_PDE(StartPde, TempPde);
992 
993  /* Write the page table in session space structure */
996 
997  /* Initialize the PFN */
998  MiInitializePfnForOtherProcess(PageFrameNumber,
999  StartPde,
1001 
1002  /* And now release the lock */
1003  MiReleasePfnLock(OldIrql);
1004 
1005  /* Get the PFN entry and make sure there's no event for it */
1006  Pfn1 = MI_PFN_ELEMENT(PageFrameNumber);
1007  ASSERT(Pfn1->u1.Event == NULL);
1008 
1009  /* Increment the number of pages */
1010  ActualPages++;
1011  }
1012 
1013  /* Move to the next PDE */
1014  StartPde++;
1015  Index++;
1016  }
1017 #endif
1018 
1019  /* Make sure we didn't do more pages than expected */
1020  ASSERT(ActualPages <= PageCount);
1021 
1022  /* Release the working set lock */
1023 // MiUnlockWorkingSet(PsGetCurrentThread(),
1024 // &MmSessionSpace->GlobalVirtualAddress->Vm);
1025 
1026 
1027  /* If we did at least one page... */
1028  if (ActualPages)
1029  {
1030  /* Update the performance counters! */
1033  }
1034 
1035  /* Return status */
1036  return STATUS_SUCCESS;
1037 }
SIZE_T NonPageablePages
Definition: miarm.h:486
#define MiAddressToPde(x)
Definition: mmx86.c:20
PMMPDE PageTables
Definition: miarm.h:512
union _MMPTE::@2288 u
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1282
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
struct Color Color
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:533
uint32_t ULONG_PTR
Definition: typedefs.h:65
UCHAR KIRQL
Definition: env_spec_w32.h:591
PVOID MmSessionBase
Definition: init.c:33
ASSERT(Segment->Locked)
ULONG PFN_NUMBER
Definition: ke.h:9
#define _WARN(msg)
Definition: debug.h:263
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
#define PsGetCurrentProcess
Definition: psfuncs.h:17
ULONG MmSecondaryColorMask
Definition: mminit.c:257
return FALSE
Definition: section.c:5098
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:1023
#define MI_SET_USAGE(x)
Definition: mm.h:317
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:319
ULONG PageFrameNumber
Definition: mmtypes.h:74
SIZE_T CommittedPages
Definition: miarm.h:487
_In_ WDFCOLLECTION _In_ ULONG Index
ULONG64 Valid
Definition: mmtypes.h:150
PVOID MiSessionSpaceEnd
Definition: init.c:27
#define PAGE_ALIGN(Va)
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
Definition: mm.h:373
MMPTE ValidKernelPdeLocal
Definition: init.c:32
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
#define STATUS_SUCCESS
Definition: shellext.h:65
PFN_NUMBER SessionPageDirectoryIndex
Definition: miarm.h:485

Referenced by MiMapViewInSystemSpace().

◆ MiSetControlAreaSymbolsLoaded()

VOID NTAPI MiSetControlAreaSymbolsLoaded ( IN PCONTROL_AREA  ControlArea)

Definition at line 1152 of file section.c.

1153 {
1154  KIRQL OldIrql;
1155 
1157 
1158  OldIrql = MiAcquirePfnLock();
1159  ControlArea->u.Flags.DebugSymbolsLoaded |= 1;
1160 
1161  ASSERT(OldIrql <= APC_LEVEL);
1162  MiReleasePfnLock(OldIrql);
1164 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
UCHAR KIRQL
Definition: env_spec_w32.h:591
ASSERT(Segment->Locked)
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
#define APC_LEVEL
Definition: env_spec_w32.h:695

◆ MiSetProtectionOnSection()

NTSTATUS NTAPI MiSetProtectionOnSection ( IN PEPROCESS  Process,
IN PMMVAD  FoundVad,
IN PVOID  StartingAddress,
IN PVOID  EndingAddress,
IN ULONG  NewProtect,
OUT PULONG  CapturedOldProtect,
IN ULONG  DontCharge,
OUT PULONG  Locked 
)

Definition at line 2119 of file section.c.

2127 {
2128  PMMPTE PointerPte, LastPte;
2129  MMPTE TempPte, PteContents;
2130  PMMPDE PointerPde;
2131  PMMPFN Pfn1;
2132  ULONG ProtectionMask, QuotaCharge = 0;
2134  PAGED_CODE();
2135 
2136  //
2137  // Tell caller nothing is being locked
2138  //
2139  *Locked = FALSE;
2140 
2141  //
2142  // This function should only be used for section VADs. Windows ASSERT */
2143  //
2144  ASSERT(FoundVad->u.VadFlags.PrivateMemory == 0);
2145 
2146  //
2147  // We don't support these features in ARM3
2148  //
2149  ASSERT(FoundVad->u.VadFlags.VadType != VadImageMap);
2150  ASSERT(FoundVad->u2.VadFlags2.CopyOnWrite == 0);
2151 
2152  //
2153  // Convert and validate the protection mask
2154  //
2155  ProtectionMask = MiMakeProtectionMask(NewProtect);
2156  if (ProtectionMask == MM_INVALID_PROTECTION)
2157  {
2158  DPRINT1("Invalid section protect\n");
2160  }
2161 
2162  //
2163  // Get the PTE and PDE for the address, as well as the final PTE
2164  //
2166  PointerPde = MiAddressToPde(StartingAddress);
2167  PointerPte = MiAddressToPte(StartingAddress);
2168  LastPte = MiAddressToPte(EndingAddress);
2169 
2170  //
2171  // Make the PDE valid, and check the status of the first PTE
2172  //
2174  if (PointerPte->u.Long)
2175  {
2176  //
2177  // Not supported in ARM3
2178  //
2179  ASSERT(FoundVad->u.VadFlags.VadType != VadRotatePhysical);
2180 
2181  //
2182  // Capture the page protection and make the PDE valid
2183  //
2184  *CapturedOldProtect = MiGetPageProtection(PointerPte);
2186  }
2187  else
2188  {
2189  //
2190  // Only pagefile-backed section VADs are supported for now
2191  //
2192  ASSERT(FoundVad->u.VadFlags.VadType != VadImageMap);
2193 
2194  //
2195  // Grab the old protection from the VAD itself
2196  //
2197  *CapturedOldProtect = MmProtectToValue[FoundVad->u.VadFlags.Protection];
2198  }
2199 
2200  //
2201  // Loop all the PTEs now
2202  //
2204  while (PointerPte <= LastPte)
2205  {
2206  //
2207  // Check if we've crossed a PDE boundary and make the new PDE valid too
2208  //
2209  if (MiIsPteOnPdeBoundary(PointerPte))
2210  {
2211  PointerPde = MiPteToPde(PointerPte);
2213  }
2214 
2215  //
2216  // Capture the PTE and see what we're dealing with
2217  //
2218  PteContents = *PointerPte;
2219  if (PteContents.u.Long == 0)
2220  {
2221  //
2222  // This used to be a zero PTE and it no longer is, so we must add a
2223  // reference to the pagetable.
2224  //
2226 
2227  //
2228  // Create the demand-zero prototype PTE
2229  //
2231  TempPte.u.Soft.Protection = ProtectionMask;
2232  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2233  }
2234  else if (PteContents.u.Hard.Valid == 1)
2235  {
2236  //
2237  // Get the PFN entry
2238  //
2239  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2240 
2241  //
2242  // We don't support these yet
2243  //
2244  ASSERT((NewProtect & (PAGE_NOACCESS | PAGE_GUARD)) == 0);
2245  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
2246 
2247  //
2248  // Write the protection mask and write it with a TLB flush
2249  //
2250  Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
2251  MiFlushTbAndCapture(FoundVad,
2252  PointerPte,
2253  ProtectionMask,
2254  Pfn1,
2255  TRUE);
2256  }
2257  else
2258  {
2259  //
2260  // We don't support these cases yet
2261  //
2262  ASSERT(PteContents.u.Soft.Prototype == 0);
2263  ASSERT(PteContents.u.Soft.Transition == 0);
2264 
2265  //
2266  // The PTE is already demand-zero, just update the protection mask
2267  //
2268  PointerPte->u.Soft.Protection = ProtectionMask;
2269  }
2270 
2271  PointerPte++;
2272  }
2273 
2274  //
2275  // Unlock the working set and update quota charges if needed, then return
2276  //
2278  if ((QuotaCharge > 0) && (!DontCharge))
2279  {
2280  FoundVad->u.VadFlags.CommitCharge -= QuotaCharge;
2281  Process->CommitCharge -= QuotaCharge;
2282  }
2283  return STATUS_SUCCESS;
2284 }
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
MMPTE PrototypePte
Definition: init.c:40
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1244
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
union _MMPTE::@2288 u
#define TRUE
Definition: types.h:120
#define PAGE_GUARD
Definition: nt_native.h:1310
union _MMPFN::@1757 u3
FORCEINLINE PMMPDE MiPteToPde(PMMPTE PointerPte)
Definition: mm.h:268
USHORT PrototypePte
Definition: mm.h:363
MMPFNENTRY e1
Definition: mm.h:397
const ULONG MmProtectToValue[32]
Definition: page.c:71
ASSERT(Segment->Locked)
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define MM_NOIRQL
Definition: mm.h:70
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:207
#define PAGE_NOACCESS
Definition: nt_native.h:1302
VOID NTAPI MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
Definition: virtual.c:2475
return FALSE
Definition: section.c:5098
ULONG64 Protection
Definition: mmtypes.h:88
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1174
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:140
ULONG64 Valid
Definition: mmtypes.h:150
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2652
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE USHORT MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2486
Definition: mm.h:373
ULONG64 Prototype
Definition: mmtypes.h:89
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:305
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:997
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:306
ULONG64 Transition
Definition: mmtypes.h:90
ULONG NTAPI MiGetPageProtection(IN PMMPTE PointerPte)
Definition: virtual.c:1353
_Must_inspect_result_ _In_ ULONG NewProtect
Definition: mmfuncs.h:682
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
MMPTE OriginalPte
Definition: mm.h:407
#define DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
VOID NTAPI MiFlushTbAndCapture(IN PMMVAD FoundVad, IN PMMPTE PointerPte, IN ULONG ProtectionMask, IN PMMPFN Pfn1, IN BOOLEAN UpdateDirty)
Definition: section.c:2015
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:208
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define PAGED_CODE()

◆ MiSubsectionConsistent()

VOID NTAPI MiSubsectionConsistent ( IN PSUBSECTION  Subsection)

Definition at line 1519 of file section.c.

1520 {
1521  /* ReactOS only supports systems with 4K pages and 4K sectors */
1522  ASSERT(Subsection->u.SubsectionFlags.SectorEndOffset == 0);
1523 
1524  /* Therefore, then number of PTEs should be equal to the number of sectors */
1525  if (Subsection->NumberOfFullSectors != Subsection->PtesInSubsection)
1526  {
1527  /* Break and warn if this is inconsistent */
1528  DPRINT1("Mm: Subsection inconsistent (%x vs %x)\n",
1529  Subsection->NumberOfFullSectors, Subsection->PtesInSubsection);
1530  DbgBreakPoint();
1531  }
1532 }
ASSERT(Segment->Locked)
VOID NTAPI DbgBreakPoint(VOID)
#define DPRINT1
Definition: precomp.h:8

◆ MiUnmapViewInSystemSpace()

NTSTATUS NTAPI MiUnmapViewInSystemSpace ( IN PMMSESSION  Session,
IN PVOID  MappedBase 
)

Definition at line 2434 of file section.c.

2436 {
2437  ULONG Size;
2438  PCONTROL_AREA ControlArea;
2439  PAGED_CODE();
2440 
2441  /* Remove this mapping */
2442  KeAcquireGuardedMutex(Session->SystemSpaceViewLockPointer);
2443  Size = MiRemoveFromSystemSpace(Session, MappedBase, &ControlArea);
2444 
2445  /* Clear the bits for this mapping */
2446  RtlClearBits(Session->SystemSpaceBitMap,
2447  (ULONG)(((ULONG_PTR)MappedBase - (ULONG_PTR)Session->SystemSpaceViewStart) >> 16),
2448  Size);
2449 
2450  /* Convert the size from a bit size into the actual size */
2451  Size = Size * (_64K >> PAGE_SHIFT);
2452 
2453  /* Remove the PTEs now */
2454  MiRemoveMappedPtes(MappedBase, Size, ControlArea, NULL);
2455  KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
2456 
2457  /* Return success */
2458  return STATUS_SUCCESS;
2459 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
VOID NTAPI MiRemoveMappedPtes(IN PVOID BaseAddress, IN ULONG NumberOfPtes, IN PCONTROL_AREA ControlArea, IN PMMSUPPORT Ws)
Definition: section.c:2288
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG NTAPI MiRemoveFromSystemSpace(IN PMMSESSION Session, IN PVOID Base, OUT PCONTROL_AREA *ControlArea)
Definition: section.c:2390
#define _64K
Definition: miarm.h:23
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
#define NULL
Definition: types.h:112
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
_Must_inspect_result_ _Outptr_result_bytebuffer_ ViewSize PVOID * MappedBase
Definition: mmfuncs.h:492
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
#define PAGED_CODE()

Referenced by MmUnmapViewInSessionSpace(), and MmUnmapViewInSystemSpace().

◆ MiUnmapViewOfSection()

NTSTATUS NTAPI MiUnmapViewOfSection ( IN PEPROCESS  Process,
IN PVOID  BaseAddress,
IN ULONG  Flags 
)

Definition at line 803 of file section.c.

806 {
810  PMMVAD Vad;
811  PVOID DbgBase = NULL;
814  PETHREAD CurrentThread = PsGetCurrentThread();
816  PAGED_CODE();
817 
818  /* Check if we need to lock the address space */
819  if (!Flags) MmLockAddressSpace(&Process->Vm);
820 
821  /* Check for Mm Region */
824  {
825  /* Call Mm API */
827  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
828  return Status;
829  }
830 
831  /* Check if we should attach to the process */
832  if (CurrentProcess != Process)
833  {
834  /* The process is different, do an attach */
836  Attached = TRUE;
837  }
838 
839  /* Check if the process is already dead */
840  if (Process->VmDeleted)
841  {
842  /* Fail the call */
843  DPRINT1("Process died!\n");
844  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
846  goto Quickie;
847  }
848 
849  /* Find the VAD for the address and make sure it's a section VAD */
851  if (!(Vad) || (Vad->u.VadFlags.PrivateMemory))
852  {
853  /* Couldn't find it, or invalid VAD, fail */
854  DPRINT1("No VAD or invalid VAD\n");
855  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
857  goto Quickie;
858  }
859 
860  /* We should be attached */
862 
863  /* We need the base address for the debugger message on image-backed VADs */
864  if (Vad->u.VadFlags.VadType == VadImageMap)
865  {
866  DbgBase = (PVOID)(Vad->StartingVpn >> PAGE_SHIFT);
867  }
868 
869  /* Compute the size of the VAD region */
870  RegionSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
871 
872  /* For SEC_NO_CHANGE sections, we need some extra checks */
873  if (Vad->u.VadFlags.NoChange == 1)
874  {
875  /* Are we allowed to mess with this VAD? */
877  (PVOID)(Vad->StartingVpn >> PAGE_SHIFT),
878  RegionSize,
880  if (!NT_SUCCESS(Status))
881  {
882  /* We failed */
883  DPRINT1("Trying to unmap protected VAD!\n");
884  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
885  goto Quickie;
886  }
887  }
888 
889  /* Not currently supported */
891 
892  /* FIXME: Remove VAD charges */
893 
894  /* Lock the working set */
895  MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
896 
897  /* Remove the VAD */
898  ASSERT(Process->VadRoot.NumberGenericTableElements >= 1);
899  MiRemoveNode((PMMADDRESS_NODE)Vad, &Process->VadRoot);
901 
902  /* Remove the PTEs for this view, which also releases the working set lock */
904 
905  /* FIXME: Remove commitment */
906 
907  /* Update performance counter and release the lock */
908  Process->VirtualSize -= RegionSize;
909  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
910 
911  /* Destroy the VAD and return success */
912  ExFreePool(Vad);
914 
915  /* Failure and success case -- send debugger message, detach, and return */
916 Quickie:
917  if (DbgBase) DbgkUnMapViewOfSection(DbgBase);
919  return Status;
920 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
KAPC_STATE
Definition: ketypes.h:1285
ULONG Type
Definition: mm.h:251
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define TRUE
Definition: types.h:120
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1666
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI MiRemoveMappedView(IN PEPROCESS CurrentProcess, IN PMMVAD Vad)
Definition: section.c:766
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
ULONG_PTR NoChange
Definition: mmtypes.h:690
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
#define MM_DELETE_CHECK
Definition: miarm.h:261
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
ASSERT(Segment->Locked)
static BOOL Attached
Definition: vidbios.c:3905
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:97
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
NTSTATUS NTAPI MiRosUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress, IN BOOLEAN SkipDebuggerNotify)
Definition: section.c:3567
NTSTATUS Status
Definition: section.c:4934
#define PsGetCurrentProcess
Definition: psfuncs.h:17
unsigned char BOOLEAN
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:48
return FALSE
Definition: section.c:5098
void * PVOID
Definition: retypes.h:9
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
union _MMVAD::@2569 u
Status
Definition: gdiplustypes.h:24
NTSTATUS NTAPI MiCheckSecuredVad(IN PMMVAD Vad, IN PVOID Base, IN SIZE_T Size, IN ULONG ProtectionMask)
Definition: vadnode.c:815
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1174
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG CurrentProcess
Definition: shell.c:125
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
ULONG_PTR PrivateMemory
Definition: mmtypes.h:695
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:502
VOID NTAPI DbgkUnMapViewOfSection(IN PVOID BaseAddress)
Definition: dbgkutil.c:436
#define PAGE_SIZE
Definition: env_spec_w32.h:49
VOID NTAPI MiRemoveNode(IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table)
Definition: vadnode.c:360
ULONG_PTR SIZE_T
Definition: typedefs.h:80
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1727
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define STATUS_NOT_MAPPED_VIEW
Definition: ntstatus.h:262
#define STATUS_SUCCESS
Definition: shellext.h:65
VOID NTAPI PsReturnProcessNonPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the non paged quota pool that the process was taking up.
Definition: quota.c:938
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:37
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1659
ULONG_PTR VadType
Definition: mmtypes.h:691
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define PAGED_CODE()

Referenced by MmUnmapViewOfSection(), and NtUnmapViewOfSection().

◆ MmCommitSessionMappedView()

NTSTATUS NTAPI MmCommitSessionMappedView ( IN PVOID  MappedBase,
IN SIZE_T  ViewSize 
)

Definition at line 3153 of file section.c.

3155 {
3156  ULONG_PTR StartAddress, EndingAddress, Base;
3157  ULONG Hash, Count = 0, Size, QuotaCharge;
3158  PMMSESSION Session;
3159  PMMPTE LastProtoPte, PointerPte, ProtoPte;
3160  PCONTROL_AREA ControlArea;
3161  PSEGMENT Segment;
3162  PSUBSECTION Subsection;
3163  MMPTE TempPte;
3164  PAGED_CODE();
3165 
3166  /* Make sure the base isn't past the session view range */
3167  if ((MappedBase < MiSessionViewStart) ||
3169  {
3170  DPRINT1("Base outside of valid range\n");
3172  }
3173 
3174  /* Make sure the size isn't past the session view range */
3177  {
3178  DPRINT1("Size outside of valid range\n");
3180  }
3181 
3182  /* Sanity check */
3183  ASSERT(ViewSize != 0);
3184 
3185  /* Process must be in a session */
3186  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3187  {
3188  DPRINT1("Process is not in session\n");
3189  return STATUS_NOT_MAPPED_VIEW;
3190  }
3191 
3192  /* Compute the correctly aligned base and end addresses */
3193  StartAddress = (ULONG_PTR)PAGE_ALIGN(MappedBase);
3194  EndingAddress = ((ULONG_PTR)MappedBase + ViewSize - 1) | (PAGE_SIZE - 1);
3195 
3196  /* Sanity check and grab the session */
3198  Session = &MmSessionSpace->Session;
3199 
3200  /* Get the hash entry for this allocation */
3201  Hash = (StartAddress >> 16) % Session->SystemSpaceHashKey;
3202 
3203  /* Lock system space */
3205 
3206  /* Loop twice so we can try rolling over if needed */
3207  while (TRUE)
3208  {
3209  /* Extract the size and base addresses from the entry */
3210  Base = Session->SystemSpaceViewTable[Hash].Entry & ~0xFFFF;
3211  Size = Session->SystemSpaceViewTable[Hash].Entry & 0xFFFF;
3212 
3213  /* Convert the size to bucket chunks */
3215 
3216  /* Bail out if this entry fits in here */
3217  if ((StartAddress >= Base) && (EndingAddress < (Base + Size))) break;
3218 
3219  /* Check if we overflew past the end of the hash table */
3220  if (++Hash >= Session->SystemSpaceHashSize)
3221  {
3222  /* Reset the hash to zero and keep searching from the bottom */
3223  Hash = 0;
3224  if (++Count == 2)
3225  {
3226  /* But if we overflew twice, then this is not a real mapping */
3227  KeBugCheckEx(DRIVER_UNMAPPING_INVALID_VIEW,
3228  Base,
3229  2,
3230  0,
3231  0);
3232  }
3233  }
3234  }
3235 
3236  /* Make sure the view being mapped is not file-based */
3237  ControlArea = Session->SystemSpaceViewTable[Hash].ControlArea;
3238  if (ControlArea->FilePointer != NULL)
3239  {
3240  /* It is, so we have to bail out */
3241  DPRINT1("Only page-filed backed sections can be commited\n");
3243  return STATUS_ALREADY_COMMITTED;
3244  }
3245 
3246  /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
3247  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
3248  ASSERT(ControlArea->u.Flags.Rom == 0);
3249  Subsection = (PSUBSECTION)(ControlArea + 1);
3250 
3251  /* Get the start and end PTEs -- make sure the end PTE isn't past the end */
3252  ProtoPte = Subsection->SubsectionBase + ((StartAddress - Base) >> PAGE_SHIFT);
3253  QuotaCharge = MiAddressToPte(EndingAddress) - MiAddressToPte(StartAddress) + 1;
3254  LastProtoPte = ProtoPte + QuotaCharge;
3255  if (LastProtoPte >= Subsection->SubsectionBase + Subsection->PtesInSubsection)
3256  {
3257  DPRINT1("PTE is out of bounds\n");
3260  }
3261 
3262  /* Acquire the commit lock and count all the non-committed PTEs */
3264  PointerPte = ProtoPte;
3265  while (PointerPte < LastProtoPte)
3266  {
3267  if (PointerPte->u.Long) QuotaCharge--;
3268  PointerPte++;
3269  }
3270 
3271  /* Was everything committed already? */
3272  if (!QuotaCharge)
3273  {
3274  /* Nothing to do! */
3277  return STATUS_SUCCESS;
3278  }
3279 
3280  /* Pick the segment and template PTE */
3281  Segment = ControlArea->Segment;
3282  TempPte = Segment->SegmentPteTemplate;
3283  ASSERT(TempPte.u.Long != 0);
3284 
3285  /* Loop all prototype PTEs to be committed */
3286  PointerPte = ProtoPte;
3287  while (PointerPte < LastProtoPte)
3288  {
3289  /* Make sure the PTE is already invalid */
3290  if (PointerPte->u.Long == 0)
3291  {
3292  /* And write the invalid PTE */
3293  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
3294  }
3295 
3296  /* Move to the next PTE */
3297  PointerPte++;
3298  }
3299 
3300  /* Check if we had at least one page charged */
3301  if (QuotaCharge)
3302  {
3303  /* Update the accounting data */
3304  Segment->NumberOfCommittedPages += QuotaCharge;
3306  }
3307 
3308  /* Release all */
3311  return STATUS_SUCCESS;
3312 }
static int Hash(const char *)
Definition: reader.c:2257
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
PFILE_OBJECT FilePointer
Definition: mmtypes.h:530
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
union _MMPTE::@2288 u
#define TRUE
Definition: types.h:120
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2427
SIZE_T MmSharedCommit
Definition: freelist.c:31
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define STATUS_ALREADY_COMMITTED
Definition: ntstatus.h:270
ASSERT(Segment->Locked)
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG MmSessionViewSize
Definition: init.c:35
#define PsGetCurrentProcess
Definition: psfuncs.h:17
union _CONTROL_AREA::@2562 u
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:476
return FALSE
Definition: section.c:5098
PMMVIEW SystemSpaceViewTable
Definition: miarm.h:458
ULONG SystemSpaceHashKey
Definition: miarm.h:461
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
int Count
Definition: noreturn.cpp:7
MMSESSION Session
Definition: miarm.h:502
#define PAGE_ALIGN(Va)
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
BOOLEAN NTAPI MmIsAddressValid(IN PVOID VirtualAddress)
Definition: mmsup.c:174
struct _SUBSECTION * PSUBSECTION
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
VOID FASTCALL KeReleaseGuardedMutexUnsafe(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:75
PKGUARDED_MUTEX SystemSpaceViewLockPointer
Definition: miarm.h:456
PCONTROL_AREA ControlArea
Definition: miarm.h:450
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
ULONG GlobalOnlyPerSession
Definition: mmtypes.h:488
#define PAGE_SIZE
Definition: env_spec_w32.h:49
KGUARDED_MUTEX MmSectionCommitMutex
Definition: section.c:108
ULONG_PTR Long
Definition: mmtypes.h:215
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:997
PVOID MiSessionViewStart
Definition: init.c:30
#define MI_SYSTEM_VIEW_BUCKET_SIZE
Definition: miarm.h:266
PSEGMENT Segment
Definition: mmtypes.h:518
#define NULL
Definition: types.h:112
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
#define DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ _Outptr_result_bytebuffer_ ViewSize PVOID * MappedBase
Definition: mmfuncs.h:492
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:404
VOID FASTCALL KeAcquireGuardedMutexUnsafe(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:64
MMSECTION_FLAGS Flags
Definition: mmtypes.h:528
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_NOT_MAPPED_VIEW
Definition: ntstatus.h:262
#define ULONG_PTR
Definition: config.h:101
ULONG_PTR Entry
Definition: miarm.h:449
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG SystemSpaceHashSize
Definition: miarm.h:459
PMMPTE SubsectionBase
Definition: mmtypes.h:578
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
#define PAGED_CODE()
ULONG PtesInSubsection
Definition: mmtypes.h:580

◆ MmCreateArm3Section()

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

Definition at line 2468 of file section.c.

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