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

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 
#define MI_MAPPED_COPY_PAGES   14
 
#define MI_POOL_COPY_BYTES   512
 
#define MI_MAX_TRANSFER_SIZE   64 * 1024
 

Functions

NTSTATUS NTAPI MiProtectVirtualMemory (IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection OPTIONAL)
 
VOID NTAPI MiFlushTbAndCapture (IN PMMVAD FoundVad, IN PMMPTE PointerPte, IN ULONG ProtectionMask, IN PMMPFN Pfn1, IN BOOLEAN CaptureDirtyBit)
 
ULONG NTAPI MiCalculatePageCommitment (IN ULONG_PTR StartingAddress, IN ULONG_PTR EndingAddress, IN PMMVAD Vad, IN PEPROCESS Process)
 
ULONG NTAPI MiMakeSystemAddressValid (IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
 
ULONG NTAPI MiMakeSystemAddressValidPfn (IN PVOID VirtualAddress, IN KIRQL OldIrql)
 
PFN_COUNT NTAPI MiDeleteSystemPageableVm (IN PMMPTE PointerPte, IN PFN_NUMBER PageCount, IN ULONG Flags, OUT PPFN_NUMBER ValidPages)
 
VOID NTAPI MiDeletePte (IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
 
VOID NTAPI MiDeleteVirtualAddresses (IN ULONG_PTR Va, IN ULONG_PTR EndingAddress, IN PMMVAD Vad)
 
LONG MiGetExceptionInfo (IN PEXCEPTION_POINTERS ExceptionInfo, OUT PBOOLEAN HaveBadAddress, OUT PULONG_PTR BadAddress)
 
NTSTATUS NTAPI MiDoMappedCopy (IN PEPROCESS SourceProcess, IN PVOID SourceAddress, IN PEPROCESS TargetProcess, OUT PVOID TargetAddress, IN SIZE_T BufferSize, IN KPROCESSOR_MODE PreviousMode, OUT PSIZE_T ReturnSize)
 
NTSTATUS NTAPI MiDoPoolCopy (IN PEPROCESS SourceProcess, IN PVOID SourceAddress, IN PEPROCESS TargetProcess, OUT PVOID TargetAddress, IN SIZE_T BufferSize, IN KPROCESSOR_MODE PreviousMode, OUT PSIZE_T ReturnSize)
 
NTSTATUS NTAPI MmCopyVirtualMemory (IN PEPROCESS SourceProcess, IN PVOID SourceAddress, IN PEPROCESS TargetProcess, OUT PVOID TargetAddress, IN SIZE_T BufferSize, IN KPROCESSOR_MODE PreviousMode, OUT PSIZE_T ReturnSize)
 
NTSTATUS NTAPI MmFlushVirtualMemory (IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T RegionSize, OUT PIO_STATUS_BLOCK IoStatusBlock)
 
ULONG NTAPI MiGetPageProtection (IN PMMPTE PointerPte)
 
ULONG NTAPI MiQueryAddressState (IN PVOID Va, IN PMMVAD Vad, IN PEPROCESS TargetProcess, OUT PULONG ReturnedProtect, OUT PVOID *NextVa)
 
NTSTATUS NTAPI MiQueryMemoryBasicInformation (IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID MemoryInformation, IN SIZE_T MemoryInformationLength, OUT PSIZE_T ReturnLength)
 
BOOLEAN NTAPI MiIsEntireRangeCommitted (IN ULONG_PTR StartingAddress, IN ULONG_PTR EndingAddress, IN PMMVAD Vad, IN PEPROCESS Process)
 
NTSTATUS NTAPI MiRosProtectVirtualMemory (IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection OPTIONAL)
 
VOID NTAPI MiMakePdeExistAndMakeValid (IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
 
VOID NTAPI MiProcessValidPteList (IN PMMPTE *ValidPteList, IN ULONG Count)
 
ULONG NTAPI MiDecommitPages (IN PVOID StartingAddress, IN PMMPTE EndingPte, IN PEPROCESS Process, IN PMMVAD Vad)
 
PVOID NTAPI MmGetVirtualForPhysical (IN PHYSICAL_ADDRESS PhysicalAddress)
 
PVOID NTAPI MmSecureVirtualMemory (IN PVOID Address, IN SIZE_T Length, IN ULONG Mode)
 
VOID NTAPI MmUnsecureVirtualMemory (IN PVOID SecureMem)
 
NTSTATUS NTAPI NtReadVirtualMemory (IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN SIZE_T NumberOfBytesToRead, OUT PSIZE_T NumberOfBytesRead OPTIONAL)
 
NTSTATUS NTAPI NtWriteVirtualMemory (IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, IN SIZE_T NumberOfBytesToWrite, OUT PSIZE_T NumberOfBytesWritten OPTIONAL)
 
NTSTATUS NTAPI NtFlushInstructionCache (_In_ HANDLE ProcessHandle, _In_opt_ PVOID BaseAddress, _In_ SIZE_T FlushSize)
 
NTSTATUS NTAPI NtProtectVirtualMemory (IN HANDLE ProcessHandle, IN OUT PVOID *UnsafeBaseAddress, IN OUT SIZE_T *UnsafeNumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG UnsafeOldAccessProtection)
 
FORCEINLINE BOOLEAN MI_IS_LOCKED_VA (PMMPFN Pfn1, ULONG LockType)
 
FORCEINLINE VOID MI_LOCK_VA (PMMPFN Pfn1, ULONG LockType)
 
FORCEINLINE VOID MI_UNLOCK_VA (PMMPFN Pfn1, ULONG LockType)
 
static NTSTATUS MiCheckVadsForLockOperation (_Inout_ PVOID *BaseAddress, _Inout_ PSIZE_T RegionSize, _Inout_ PVOID *EndAddress)
 
static NTSTATUS MiLockVirtualMemory (IN OUT PVOID *BaseAddress, IN OUT PSIZE_T RegionSize, IN ULONG MapType)
 
NTSTATUS NTAPI NtLockVirtualMemory (IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T NumberOfBytesToLock, IN ULONG MapType)
 
static NTSTATUS MiUnlockVirtualMemory (IN OUT PVOID *BaseAddress, IN OUT PSIZE_T RegionSize, IN ULONG MapType)
 
NTSTATUS NTAPI NtUnlockVirtualMemory (IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T NumberOfBytesToUnlock, IN ULONG MapType)
 
NTSTATUS NTAPI NtFlushVirtualMemory (IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T NumberOfBytesToFlush, OUT PIO_STATUS_BLOCK IoStatusBlock)
 
NTSTATUS NTAPI NtGetWriteWatch (IN HANDLE ProcessHandle, IN ULONG Flags, IN PVOID BaseAddress, IN SIZE_T RegionSize, IN PVOID *UserAddressArray, OUT PULONG_PTR EntriesInUserAddressArray, OUT PULONG Granularity)
 
NTSTATUS NTAPI NtResetWriteWatch (IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN SIZE_T RegionSize)
 
NTSTATUS NTAPI NtQueryVirtualMemory (IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN MEMORY_INFORMATION_CLASS MemoryInformationClass, OUT PVOID MemoryInformation, IN SIZE_T MemoryInformationLength, OUT PSIZE_T ReturnLength)
 
NTSTATUS NTAPI NtAllocateVirtualMemory (IN HANDLE ProcessHandle, IN OUT PVOID *UBaseAddress, IN ULONG_PTR ZeroBits, IN OUT PSIZE_T URegionSize, IN ULONG AllocationType, IN ULONG Protect)
 
NTSTATUS NTAPI NtFreeVirtualMemory (IN HANDLE ProcessHandle, IN PVOID *UBaseAddress, IN PSIZE_T URegionSize, IN ULONG FreeType)
 
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress (PVOID Address)
 

Macro Definition Documentation

◆ MI_MAPPED_COPY_PAGES

#define MI_MAPPED_COPY_PAGES   14

Definition at line 18 of file virtual.c.

◆ MI_MAX_TRANSFER_SIZE

#define MI_MAX_TRANSFER_SIZE   64 * 1024

Definition at line 20 of file virtual.c.

◆ MI_POOL_COPY_BYTES

#define MI_POOL_COPY_BYTES   512

Definition at line 19 of file virtual.c.

◆ MODULE_INVOLVED_IN_ARM3

#define MODULE_INVOLVED_IN_ARM3

Definition at line 15 of file virtual.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file virtual.c.

Function Documentation

◆ MI_IS_LOCKED_VA()

FORCEINLINE BOOLEAN MI_IS_LOCKED_VA ( PMMPFN  Pfn1,
ULONG  LockType 
)

Definition at line 3266 of file virtual.c.

3269 {
3270  // HACK until we have proper WSLIST support
3271  PMMWSLE Wsle = &Pfn1->Wsle;
3272 
3273  if ((LockType & MAP_PROCESS) && (Wsle->u1.e1.LockedInWs))
3274  return TRUE;
3275  if ((LockType & MAP_SYSTEM) && (Wsle->u1.e1.LockedInMemory))
3276  return TRUE;
3277 
3278  return FALSE;
3279 }
#define TRUE
Definition: types.h:120
MMWSLENTRY e1
Definition: mmtypes.h:855
union _MMWSLE::@2557 u1
MMWSLE Wsle
Definition: mm.h:423
#define FALSE
Definition: types.h:117
_In_ WDFREQUEST _In_ MEDIA_LOCK_TYPE LockType
Definition: cdrom.h:1334
#define MAP_PROCESS
Definition: mmtypes.h:67
ULONG_PTR LockedInMemory
Definition: mmtypes.h:826
ULONG_PTR LockedInWs
Definition: mmtypes.h:825
#define MAP_SYSTEM
Definition: mmtypes.h:68

Referenced by MiLockVirtualMemory(), and MiUnlockVirtualMemory().

◆ MI_LOCK_VA()

FORCEINLINE VOID MI_LOCK_VA ( PMMPFN  Pfn1,
ULONG  LockType 
)

Definition at line 3283 of file virtual.c.

3286 {
3287  // HACK until we have proper WSLIST support
3288  PMMWSLE Wsle = &Pfn1->Wsle;
3289 
3290  if (!Wsle->u1.e1.LockedInWs &&
3291  !Wsle->u1.e1.LockedInMemory)
3292  {
3294  }
3295 
3296  if (LockType & MAP_PROCESS)
3297  Wsle->u1.e1.LockedInWs = 1;
3298  if (LockType & MAP_SYSTEM)
3299  Wsle->u1.e1.LockedInMemory = 1;
3300 }
MMWSLENTRY e1
Definition: mmtypes.h:855
union _MMWSLE::@2557 u1
MMWSLE Wsle
Definition: mm.h:423
_In_ WDFREQUEST _In_ MEDIA_LOCK_TYPE LockType
Definition: cdrom.h:1334
#define MAP_PROCESS
Definition: mmtypes.h:67
ULONG_PTR LockedInMemory
Definition: mmtypes.h:826
FORCEINLINE VOID MiReferenceProbedPageAndBumpLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1692
ULONG_PTR LockedInWs
Definition: mmtypes.h:825
#define MAP_SYSTEM
Definition: mmtypes.h:68

Referenced by MiLockVirtualMemory().

◆ MI_UNLOCK_VA()

FORCEINLINE VOID MI_UNLOCK_VA ( PMMPFN  Pfn1,
ULONG  LockType 
)

Definition at line 3304 of file virtual.c.

3307 {
3308  // HACK until we have proper WSLIST support
3309  PMMWSLE Wsle = &Pfn1->Wsle;
3310 
3311  if (LockType & MAP_PROCESS)
3312  Wsle->u1.e1.LockedInWs = 0;
3313  if (LockType & MAP_SYSTEM)
3314  Wsle->u1.e1.LockedInMemory = 0;
3315 
3316  if (!Wsle->u1.e1.LockedInWs &&
3317  !Wsle->u1.e1.LockedInMemory)
3318  {
3320  }
3321 }
FORCEINLINE VOID MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1620
MMWSLENTRY e1
Definition: mmtypes.h:855
union _MMWSLE::@2557 u1
MMWSLE Wsle
Definition: mm.h:423
_In_ WDFREQUEST _In_ MEDIA_LOCK_TYPE LockType
Definition: cdrom.h:1334
#define MAP_PROCESS
Definition: mmtypes.h:67
ULONG_PTR LockedInMemory
Definition: mmtypes.h:826
ULONG_PTR LockedInWs
Definition: mmtypes.h:825
#define MAP_SYSTEM
Definition: mmtypes.h:68

Referenced by MiUnlockVirtualMemory().

◆ MiCalculatePageCommitment()

ULONG NTAPI MiCalculatePageCommitment ( IN ULONG_PTR  StartingAddress,
IN ULONG_PTR  EndingAddress,
IN PMMVAD  Vad,
IN PEPROCESS  Process 
)

Definition at line 42 of file virtual.c.

46 {
47  PMMPTE PointerPte, LastPte;
48  PMMPDE PointerPde;
49  BOOLEAN OnPdeBoundary = TRUE;
50 #if _MI_PAGING_LEVELS >= 3
51  PMMPPE PointerPpe;
52  BOOLEAN OnPpeBoundary = TRUE;
53 #if _MI_PAGING_LEVELS == 4
54  PMMPXE PointerPxe;
55  BOOLEAN OnPxeBoundary = TRUE;
56 #endif
57 #endif
58 
59  /* Make sure this all makes sense */
60  ASSERT(PsGetCurrentThread()->OwnsProcessWorkingSetExclusive || PsGetCurrentThread()->OwnsProcessWorkingSetShared);
61  ASSERT(EndingAddress >= StartingAddress);
62  PointerPte = MiAddressToPte(StartingAddress);
63  LastPte = MiAddressToPte(EndingAddress);
64 
65  /*
66  * In case this is a committed VAD, assume the whole range is committed
67  * and count the individually decommitted pages.
68  * In case it is not, assume the range is not committed and count the individually committed pages.
69  */
70  ULONG_PTR CommittedPages = Vad->u.VadFlags.MemCommit ? BYTES_TO_PAGES(EndingAddress - StartingAddress) : 0;
71 
72  while (PointerPte <= LastPte)
73  {
74 #if _MI_PAGING_LEVELS == 4
75  /* Check if PXE was ever paged in. */
76  if (OnPxeBoundary)
77  {
78  PointerPxe = MiPteToPxe(PointerPte);
79 
80  /* Check that this loop is sane */
81  ASSERT(OnPpeBoundary);
82  ASSERT(OnPdeBoundary);
83 
84  if (PointerPxe->u.Long == 0)
85  {
86  PointerPxe++;
87  PointerPte = MiPxeToPte(PointerPde);
88  continue;
89  }
90 
91  if (PointerPxe->u.Hard.Valid == 0)
93  }
94  ASSERT(PointerPxe->u.Hard.Valid == 1);
95 #endif
96 
97 #if _MI_PAGING_LEVELS >= 3
98  /* Now PPE */
99  if (OnPpeBoundary)
100  {
101  PointerPpe = MiPteToPpe(PointerPte);
102 
103  /* Sanity again */
104  ASSERT(OnPdeBoundary);
105 
106  if (PointerPpe->u.Long == 0)
107  {
108  PointerPpe++;
109  PointerPte = MiPpeToPte(PointerPpe);
110 #if _MI_PAGING_LEVELS == 4
111  OnPxeBoundary = MiIsPteOnPxeBoundary(PointerPte);
112 #endif
113  continue;
114  }
115 
116  if (PointerPpe->u.Hard.Valid == 0)
118  }
119  ASSERT(PointerPpe->u.Hard.Valid == 1);
120 #endif
121 
122  /* Last level is the PDE */
123  if (OnPdeBoundary)
124  {
125  PointerPde = MiPteToPde(PointerPte);
126  if (PointerPde->u.Long == 0)
127  {
128  PointerPde++;
129  PointerPte = MiPdeToPte(PointerPde);
130 #if _MI_PAGING_LEVELS >= 3
131  OnPpeBoundary = MiIsPteOnPpeBoundary(PointerPte);
132 #if _MI_PAGING_LEVELS == 4
133  OnPxeBoundary = MiIsPteOnPxeBoundary(PointerPte);
134 #endif
135 #endif
136  continue;
137  }
138 
139  if (PointerPde->u.Hard.Valid == 0)
140  MiMakeSystemAddressValid(PointerPte, Process);
141  }
142  ASSERT(PointerPde->u.Hard.Valid == 1);
143 
144  /* Is this PTE demand zero? */
145  if (PointerPte->u.Long != 0)
146  {
147  /* It isn't -- is it a decommited, invalid, or faulted PTE? */
148  if ((PointerPte->u.Hard.Valid == 0) &&
149  (PointerPte->u.Soft.Protection == MM_DECOMMIT) &&
150  ((PointerPte->u.Soft.Prototype == 0) ||
151  (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)))
152  {
153  /* It is, so remove it from the count of committed pages if we have to */
154  if (Vad->u.VadFlags.MemCommit)
155  CommittedPages--;
156  }
157  else if (!Vad->u.VadFlags.MemCommit)
158  {
159  /* It is a valid, non-decommited, non-paged out PTE. Count it in. */
160  CommittedPages++;
161  }
162  }
163 
164  /* Move to the next PTE */
165  PointerPte++;
166  /* Manage page tables */
167  OnPdeBoundary = MiIsPteOnPdeBoundary(PointerPte);
168 #if _MI_PAGING_LEVELS >= 3
169  OnPpeBoundary = MiIsPteOnPpeBoundary(PointerPte);
170 #if _MI_PAGING_LEVELS == 4
171  OnPxeBoundary = MiIsPteOnPxeBoundary(PointerPte);
172 #endif
173 #endif
174  }
175 
176  /* Make sure we didn't mess this up */
177  ASSERT(CommittedPages <= BYTES_TO_PAGES(EndingAddress - StartingAddress));
178  return CommittedPages;
179 }
ULONG NTAPI MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
Definition: virtual.c:183
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define TRUE
Definition: types.h:120
#define MM_DECOMMIT
Definition: miarm.h:64
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
FORCEINLINE PMMPDE MiPteToPde(PMMPTE PointerPte)
Definition: mm.h:261
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MiAddressToPte(x)
Definition: mmx86.c:19
FORCEINLINE PMMPPE MiPteToPpe(PMMPTE PointerPte)
Definition: mm.h:269
unsigned char BOOLEAN
FORCEINLINE PMMPTE MiPdeToPte(PMMPDE PointerPde)
Definition: mm.h:237
ULONG64 Protection
Definition: mmtypes.h:88
#define ASSERT(a)
Definition: mode.c:44
ULONG64 Valid
Definition: mmtypes.h:150
#define MiIsPteOnPpeBoundary(PointerPte)
Definition: mm.h:301
#define BYTES_TO_PAGES(Size)
FORCEINLINE PMMPTE MiPxeToPte(PMMPXE PointerPxe)
Definition: mm.h:253
ULONG64 PageFileHigh
Definition: mmtypes.h:93
ULONG64 Prototype
Definition: mmtypes.h:89
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:299
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
FORCEINLINE PMMPTE MiPpeToPte(PMMPPE PointerPpe)
Definition: mm.h:245
FORCEINLINE PMMPXE MiPteToPxe(PMMPTE PointerPte)
Definition: mm.h:277
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
union _MMPTE::@2287 u
#define MiIsPteOnPxeBoundary(PointerPte)
Definition: mm.h:303

Referenced by NtFreeVirtualMemory().

◆ MiCheckVadsForLockOperation()

static NTSTATUS MiCheckVadsForLockOperation ( _Inout_ PVOID BaseAddress,
_Inout_ PSIZE_T  RegionSize,
_Inout_ PVOID EndAddress 
)
static

FIXME: this might be a memory area for a section view...

Definition at line 3325 of file virtual.c.

3330 {
3331  PMMVAD Vad;
3332  PVOID CurrentVa;
3333 
3334  /* Get the base address and align the start address */
3335  *EndAddress = (PUCHAR)*BaseAddress + *RegionSize;
3336  *EndAddress = ALIGN_UP_POINTER_BY(*EndAddress, PAGE_SIZE);
3338 
3339  /* First loop and check all VADs */
3340  CurrentVa = *BaseAddress;
3341  while (CurrentVa < *EndAddress)
3342  {
3343  /* Get VAD */
3344  Vad = MiLocateAddress(CurrentVa);
3345  if (Vad == NULL)
3346  {
3348  return STATUS_ACCESS_VIOLATION;
3349  }
3350 
3351  /* Check VAD type */
3352  if ((Vad->u.VadFlags.VadType != VadNone) &&
3353  (Vad->u.VadFlags.VadType != VadImageMap) &&
3354  (Vad->u.VadFlags.VadType != VadWriteWatch))
3355  {
3356  *EndAddress = CurrentVa;
3357  *RegionSize = (PUCHAR)*EndAddress - (PUCHAR)*BaseAddress;
3359  }
3360 
3361  CurrentVa = (PVOID)((Vad->EndingVpn + 1) << PAGE_SHIFT);
3362  }
3363 
3364  *RegionSize = (PUCHAR)*EndAddress - (PUCHAR)*BaseAddress;
3365  return STATUS_SUCCESS;
3366 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
unsigned char * PUCHAR
Definition: retypes.h:3
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
union _MMVAD::@2547 u
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:48
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define ALIGN_UP_POINTER_BY(ptr, align)
Definition: umtypes.h:85
static PVOID
Definition: virtual.c:33
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
#define NULL
Definition: types.h:112
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ALIGN_DOWN_POINTER_BY(ptr, align)
Definition: umtypes.h:82
#define STATUS_INCOMPATIBLE_FILE_MAP
Definition: ntstatus.h:313
ULONG_PTR VadType
Definition: mmtypes.h:691

Referenced by MiLockVirtualMemory(), and MiUnlockVirtualMemory().

◆ MiDecommitPages()

ULONG NTAPI MiDecommitPages ( IN PVOID  StartingAddress,
IN PMMPTE  EndingPte,
IN PEPROCESS  Process,
IN PMMVAD  Vad 
)

Definition at line 2616 of file virtual.c.

2620 {
2621  PMMPTE PointerPte, CommitPte = NULL;
2622  PMMPDE PointerPde;
2623  ULONG CommitReduction = 0;
2624  PMMPTE ValidPteList[256];
2625  ULONG PteCount = 0;
2626  PMMPFN Pfn1;
2627  MMPTE PteContents;
2628  PETHREAD CurrentThread = PsGetCurrentThread();
2629 
2630  //
2631  // Get the PTE and PTE for the address, and lock the working set
2632  // If this was a VAD for a MEM_COMMIT allocation, also figure out where the
2633  // commited range ends so that we can do the right accounting.
2634  //
2635  PointerPde = MiAddressToPde(StartingAddress);
2636  PointerPte = MiAddressToPte(StartingAddress);
2637  if (Vad->u.VadFlags.MemCommit) CommitPte = MiAddressToPte(Vad->EndingVpn << PAGE_SHIFT);
2638  MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
2639 
2640  //
2641  // Make the PDE valid, and now loop through each page's worth of data
2642  //
2644  while (PointerPte <= EndingPte)
2645  {
2646  //
2647  // Check if we've crossed a PDE boundary
2648  //
2649  if (MiIsPteOnPdeBoundary(PointerPte))
2650  {
2651  //
2652  // Get the new PDE and flush the valid PTEs we had built up until
2653  // now. This helps reduce the amount of TLB flushing we have to do.
2654  // Note that Windows does a much better job using timestamps and
2655  // such, and does not flush the entire TLB all the time, but right
2656  // now we have bigger problems to worry about than TLB flushing.
2657  //
2658  PointerPde = MiAddressToPde(StartingAddress);
2659  if (PteCount)
2660  {
2661  MiProcessValidPteList(ValidPteList, PteCount);
2662  PteCount = 0;
2663  }
2664 
2665  //
2666  // Make this PDE valid
2667  //
2669  }
2670 
2671  //
2672  // Read this PTE. It might be active or still demand-zero.
2673  //
2674  PteContents = *PointerPte;
2675  if (PteContents.u.Long)
2676  {
2677  //
2678  // The PTE is active. It might be valid and in a working set, or
2679  // it might be a prototype PTE or paged out or even in transition.
2680  //
2681  if (PointerPte->u.Long == MmDecommittedPte.u.Long)
2682  {
2683  //
2684  // It's already decommited, so there's nothing for us to do here
2685  //
2686  CommitReduction++;
2687  }
2688  else
2689  {
2690  //
2691  // Remove it from the counters, and check if it was valid or not
2692  //
2693  //Process->NumberOfPrivatePages--;
2694  if (PteContents.u.Hard.Valid)
2695  {
2696  //
2697  // It's valid. At this point make sure that it is not a ROS
2698  // PFN. Also, we don't support ProtoPTEs in this code path.
2699  //
2700  Pfn1 = MiGetPfnEntry(PteContents.u.Hard.PageFrameNumber);
2701  ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
2702  ASSERT(Pfn1->u3.e1.PrototypePte == FALSE);
2703 
2704  //
2705  // Flush any pending PTEs that we had not yet flushed, if our
2706  // list has gotten too big, then add this PTE to the flush list.
2707  //
2708  if (PteCount == 256)
2709  {
2710  MiProcessValidPteList(ValidPteList, PteCount);
2711  PteCount = 0;
2712  }
2713  ValidPteList[PteCount++] = PointerPte;
2714  }
2715  else
2716  {
2717  //
2718  // We do not support any of these other scenarios at the moment
2719  //
2720  ASSERT(PteContents.u.Soft.Prototype == 0);
2721  ASSERT(PteContents.u.Soft.Transition == 0);
2722  ASSERT(PteContents.u.Soft.PageFileHigh == 0);
2723 
2724  //
2725  // So the only other possibility is that it is still a demand
2726  // zero PTE, in which case we undo the accounting we did
2727  // earlier and simply make the page decommitted.
2728  //
2729  //Process->NumberOfPrivatePages++;
2731  }
2732  }
2733  }
2734  else
2735  {
2736  //
2737  // This used to be a zero PTE and it no longer is, so we must add a
2738  // reference to the pagetable.
2739  //
2740  MiIncrementPageTableReferences(StartingAddress);
2741 
2742  //
2743  // Next, we account for decommitted PTEs and make the PTE as such
2744  //
2745  if (PointerPte > CommitPte) CommitReduction++;
2747  }
2748 
2749  //
2750  // Move to the next PTE and the next address
2751  //
2752  PointerPte++;
2753  StartingAddress = (PVOID)((ULONG_PTR)StartingAddress + PAGE_SIZE);
2754  }
2755 
2756  //
2757  // Flush any dangling PTEs from the loop in the last page table, and then
2758  // release the working set and return the commit reduction accounting.
2759  //
2760  if (PteCount) MiProcessValidPteList(ValidPteList, PteCount);
2761  MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
2762  return CommitReduction;
2763 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
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 _MMPFN::@1761 u3
VOID NTAPI MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
Definition: virtual.c:2470
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:352
MMPFNENTRY e1
Definition: mm.h:386
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define MM_NOIRQL
Definition: mm.h:59
#define FALSE
Definition: types.h:117
VOID NTAPI MiProcessValidPteList(IN PMMPTE *ValidPteList, IN ULONG Count)
Definition: virtual.c:2564
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1174
#define ASSERT(a)
Definition: mode.c:44
ULONG64 Valid
Definition: mmtypes.h:150
FORCEINLINE USHORT MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2478
ULONG64 PageFileHigh
Definition: mmtypes.h:93
Definition: mm.h:362
static PVOID
Definition: virtual.c:33
ULONG64 Prototype
Definition: mmtypes.h:89
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
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:299
ULONG64 Transition
Definition: mmtypes.h:90
#define MI_IS_ROS_PFN(x)
Definition: miarm.h:1108
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
#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
unsigned int ULONG
Definition: retypes.h:1
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
MMPTE MmDecommittedPte
Definition: init.c:44
union _MMPTE::@2287 u

Referenced by NtFreeVirtualMemory().

◆ MiDeletePte()

VOID NTAPI MiDeletePte ( IN PMMPTE  PointerPte,
IN PVOID  VirtualAddress,
IN PEPROCESS  CurrentProcess,
IN PMMPTE  PrototypePte 
)

Definition at line 369 of file virtual.c.

373 {
374  PMMPFN Pfn1;
375  MMPTE TempPte;
376  PFN_NUMBER PageFrameIndex;
377  PMMPDE PointerPde;
378 
379  /* PFN lock must be held */
381 
382  /* WorkingSet must be exclusively locked */
384 
385  /* This must be current process. */
387 
388  /* Capture the PTE */
389  TempPte = *PointerPte;
390 
391  /* See if the PTE is valid */
392  if (TempPte.u.Hard.Valid == 0)
393  {
394  /* Prototype and paged out PTEs not supported yet */
395  ASSERT(TempPte.u.Soft.Prototype == 0);
396  ASSERT((TempPte.u.Soft.PageFileHigh == 0) || (TempPte.u.Soft.Transition == 1));
397 
398  if (TempPte.u.Soft.Transition)
399  {
400  /* Get the PFN entry */
401  PageFrameIndex = PFN_FROM_PTE(&TempPte);
402  Pfn1 = MiGetPfnEntry(PageFrameIndex);
403 
404  DPRINT("Pte %p is transitional!\n", PointerPte);
405 
406  /* Make sure the saved PTE address is valid */
407  ASSERT((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) == PointerPte);
408 
409  /* Destroy the PTE */
410  MI_ERASE_PTE(PointerPte);
411 
412  /* Drop the reference on the page table. */
414 
415  /* In case of shared page, the prototype PTE must be in transition, not the process one */
416  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
417 
418  /* Delete the PFN */
419  MI_SET_PFN_DELETED(Pfn1);
420 
421  /* It must be either free (refcount == 0) or being written (refcount == 1) */
422  ASSERT(Pfn1->u3.e2.ReferenceCount == Pfn1->u3.e1.WriteInProgress);
423 
424  /* See if we must free it ourselves, or if it will be freed once I/O is over */
425  if (Pfn1->u3.e2.ReferenceCount == 0)
426  {
427  /* And it should be in standby or modified list */
429 
430  /* Unlink it and set its reference count to one */
431  MiUnlinkPageFromList(Pfn1);
432  Pfn1->u3.e2.ReferenceCount++;
433 
434  /* This will put it back in free list and clean properly up */
435  MiDecrementReferenceCount(Pfn1, PageFrameIndex);
436  }
437  return;
438  }
439  }
440 
441  /* Get the PFN entry */
442  PageFrameIndex = PFN_FROM_PTE(&TempPte);
443  Pfn1 = MiGetPfnEntry(PageFrameIndex);
444 
445  /* Check if this is a valid, prototype PTE */
446  if (Pfn1->u3.e1.PrototypePte == 1)
447  {
448  /* Get the PDE and make sure it's faulted in */
449  PointerPde = MiPteToPde(PointerPte);
450  if (PointerPde->u.Hard.Valid == 0)
451  {
452 #if (_MI_PAGING_LEVELS == 2)
453  /* Could be paged pool access from a new process -- synchronize the page directories */
455  {
456 #endif
457  /* The PDE must be valid at this point */
458  KeBugCheckEx(MEMORY_MANAGEMENT,
459  0x61940,
460  (ULONG_PTR)PointerPte,
461  PointerPte->u.Long,
463  }
464 #if (_MI_PAGING_LEVELS == 2)
465  }
466 #endif
467  /* Drop the share count on the page table */
468  PointerPde = MiPteToPde(PointerPte);
470  PointerPde->u.Hard.PageFrameNumber);
471 
472  /* Drop the share count */
473  MiDecrementShareCount(Pfn1, PageFrameIndex);
474 
475  /* Either a fork, or this is the shared user data page */
476  if ((PointerPte <= MiHighestUserPte) && (PrototypePte != Pfn1->PteAddress))
477  {
478  /* If it's not the shared user page, then crash, since there's no fork() yet */
481  {
482  /* Must be some sort of memory corruption */
483  KeBugCheckEx(MEMORY_MANAGEMENT,
484  0x400,
485  (ULONG_PTR)PointerPte,
487  (ULONG_PTR)Pfn1->PteAddress);
488  }
489  }
490 
491  /* Erase it */
492  MI_ERASE_PTE(PointerPte);
493  }
494  else
495  {
496  /* Make sure the saved PTE address is valid */
497  if ((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) != PointerPte)
498  {
499  /* The PFN entry is illegal, or invalid */
500  KeBugCheckEx(MEMORY_MANAGEMENT,
501  0x401,
502  (ULONG_PTR)PointerPte,
503  PointerPte->u.Long,
504  (ULONG_PTR)Pfn1->PteAddress);
505  }
506 
507  /* Erase the PTE */
508  MI_ERASE_PTE(PointerPte);
509 
510  /* There should only be 1 shared reference count */
511  ASSERT(Pfn1->u2.ShareCount == 1);
512 
513  /* Drop the reference on the page table. */
515 
516  /* Mark the PFN for deletion and dereference what should be the last ref */
517  MI_SET_PFN_DELETED(Pfn1);
518  MiDecrementShareCount(Pfn1, PageFrameIndex);
519 
520  /* We should eventually do this */
521  //CurrentProcess->NumberOfPrivatePages--;
522  }
523 
524  /* Flush the TLB */
526 }
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:1011
MMPTE PrototypePte
Definition: init.c:40
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:265
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
union _MMPFN::@1761 u3
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:475
FORCEINLINE PMMPDE MiPteToPde(PMMPTE PointerPte)
Definition: mm.h:261
USHORT PageLocation
Definition: mm.h:354
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:352
MMPFNENTRY e1
Definition: mm.h:386
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG_PTR ShareCount
Definition: mm.h:379
#define USER_SHARED_DATA
Definition: pstypes.h:51
#define PsGetCurrentProcess
Definition: psfuncs.h:17
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1143
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
union _MMPFN::@1760 u2
USHORT WriteInProgress
Definition: mm.h:351
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG64 Valid
Definition: mmtypes.h:150
#define PAGE_ALIGN(Va)
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
VOID NTAPI MiDecrementReferenceCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1234
Definition: mm.h:362
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:194
ULONG_PTR PteFrame
Definition: mm.h:407
struct _MMPFN::@1761::@1767 e2
PMMPTE PteAddress
Definition: mm.h:375
PVOID MmHighestUserAddress
Definition: rtlcompat.c:29
FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD_EXCLUSIVE(_In_ PETHREAD Thread)
Definition: miarm.h:1070
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
PMMPTE MiHighestUserPte
Definition: mminit.c:233
#define DPRINT
Definition: sndvol32.h:71
union _MMPTE::@2287 u
#define PFN_FROM_PTE(v)
Definition: mm.h:92
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
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:312
union _MMPFN::@1764 u4

Referenced by MiDeletePde(), MiDeleteVirtualAddresses(), MiResolveProtoPteFault(), and MmArmAccessFault().

◆ MiDeleteSystemPageableVm()

PFN_COUNT NTAPI MiDeleteSystemPageableVm ( IN PMMPTE  PointerPte,
IN PFN_NUMBER  PageCount,
IN ULONG  Flags,
OUT PPFN_NUMBER  ValidPages 
)

Definition at line 275 of file virtual.c.

279 {
280  PFN_COUNT ActualPages = 0;
281  PETHREAD CurrentThread = PsGetCurrentThread();
282  PMMPFN Pfn1, Pfn2;
283  PFN_NUMBER PageFrameIndex, PageTableIndex;
284  KIRQL OldIrql;
286 
287  /* Lock the system working set */
288  MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
289 
290  /* Loop all pages */
291  while (PageCount)
292  {
293  /* Make sure there's some data about the page */
294  if (PointerPte->u.Long)
295  {
296  /* Normally this is one possibility -- freeing a valid page */
297  if (PointerPte->u.Hard.Valid)
298  {
299  /* Get the page PFN */
300  PageFrameIndex = PFN_FROM_PTE(PointerPte);
301  Pfn1 = MiGetPfnEntry(PageFrameIndex);
302 
303  /* Should not have any working set data yet */
304  ASSERT(Pfn1->u1.WsIndex == 0);
305 
306  /* Actual valid, legitimate, pages */
307  if (ValidPages) (*ValidPages)++;
308 
309  /* Get the page table entry */
310  PageTableIndex = Pfn1->u4.PteFrame;
311  Pfn2 = MiGetPfnEntry(PageTableIndex);
312 
313  /* Lock the PFN database */
314  OldIrql = MiAcquirePfnLock();
315 
316  /* Delete it the page */
317  MI_SET_PFN_DELETED(Pfn1);
318  MiDecrementShareCount(Pfn1, PageFrameIndex);
319 
320  /* Decrement the page table too */
321  MiDecrementShareCount(Pfn2, PageTableIndex);
322 
323  /* Release the PFN database */
324  MiReleasePfnLock(OldIrql);
325 
326  /* Destroy the PTE */
327  MI_ERASE_PTE(PointerPte);
328  }
329  else
330  {
331  /* As always, only handle current ARM3 scenarios */
332  ASSERT(PointerPte->u.Soft.Prototype == 0);
333  ASSERT(PointerPte->u.Soft.Transition == 0);
334 
335  /*
336  * The only other ARM3 possibility is a demand zero page, which would
337  * mean freeing some of the paged pool pages that haven't even been
338  * touched yet, as part of a larger allocation.
339  *
340  * Right now, we shouldn't expect any page file information in the PTE
341  */
342  ASSERT(PointerPte->u.Soft.PageFileHigh == 0);
343 
344  /* Destroy the PTE */
345  MI_ERASE_PTE(PointerPte);
346  }
347 
348  /* Actual legitimate pages */
349  ActualPages++;
350  }
351 
352  /* Keep going */
353  PointerPte++;
354  PageCount--;
355  }
356 
357  /* Release the working set */
358  MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
359 
360  /* Flush the entire TLB */
362 
363  /* Done */
364  return ActualPages;
365 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:1011
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ULONG PFN_COUNT
Definition: mmtypes.h:102
#define TRUE
Definition: types.h:120
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG PFN_NUMBER
Definition: ke.h:9
MMSUPPORT MmSystemCacheWs
Definition: init.c:55
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1143
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1356
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:403
KIRQL OldIrql
Definition: mm.h:1502
#define ASSERT(a)
Definition: mode.c:44
Definition: mm.h:362
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:194
ULONG_PTR PteFrame
Definition: mm.h:407
ULONG WsIndex
Definition: mm.h:367
union _MMPFN::@1759 u1
FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1270
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PFN_FROM_PTE(v)
Definition: mm.h:92
union _MMPFN::@1764 u4

Referenced by MiFreeInitializationCode(), MiFreePoolPages(), MmFreeDriverInitialization(), and MmFreeSpecialPool().

◆ MiDeleteVirtualAddresses()

VOID NTAPI MiDeleteVirtualAddresses ( IN ULONG_PTR  Va,
IN ULONG_PTR  EndingAddress,
IN PMMVAD  Vad 
)

Definition at line 530 of file virtual.c.

533 {
534  PMMPTE PointerPte, PrototypePte, LastPrototypePte;
535  PMMPDE PointerPde;
536 #if (_MI_PAGING_LEVELS >= 3)
537  PMMPPE PointerPpe;
538 #endif
539 #if (_MI_PAGING_LEVELS >= 4)
540  PMMPPE PointerPxe;
541 #endif
542  MMPTE TempPte;
544  KIRQL OldIrql;
545  BOOLEAN AddressGap = FALSE;
546  PSUBSECTION Subsection;
547 
548  /* Get out if this is a fake VAD, RosMm will free the marea pages */
549  if ((Vad) && (Vad->u.VadFlags.Spare == 1)) return;
550 
551  /* Get the current process */
553 
554  /* Check if this is a section VAD or a VM VAD */
555  if (!(Vad) || (Vad->u.VadFlags.PrivateMemory) || !(Vad->FirstPrototypePte))
556  {
557  /* Don't worry about prototypes */
558  PrototypePte = LastPrototypePte = NULL;
559  }
560  else
561  {
562  /* Get the prototype PTE */
563  PrototypePte = Vad->FirstPrototypePte;
564  LastPrototypePte = Vad->FirstPrototypePte + 1;
565  }
566 
567  /* In all cases, we don't support fork() yet */
568  ASSERT(CurrentProcess->CloneRoot == NULL);
569 
570  /* Loop the PTE for each VA (EndingAddress is inclusive!) */
571  while (Va <= EndingAddress)
572  {
573 #if (_MI_PAGING_LEVELS >= 4)
574  /* Get the PXE and check if it's valid */
575  PointerPxe = MiAddressToPxe((PVOID)Va);
576  if (!PointerPxe->u.Hard.Valid)
577  {
578  /* Check for unmapped range and skip it */
579  if (!PointerPxe->u.Long)
580  {
581  /* There are gaps in the address space */
582  AddressGap = TRUE;
583 
584  /* Update Va and continue looping */
585  Va = (ULONG_PTR)MiPxeToAddress(PointerPxe + 1);
586  continue;
587  }
588 
589  /* Make the PXE valid */
591  }
592 #endif
593 #if (_MI_PAGING_LEVELS >= 3)
594  /* Get the PPE and check if it's valid */
595  PointerPpe = MiAddressToPpe((PVOID)Va);
596  if (!PointerPpe->u.Hard.Valid)
597  {
598  /* Check for unmapped range and skip it */
599  if (!PointerPpe->u.Long)
600  {
601  /* There are gaps in the address space */
602  AddressGap = TRUE;
603 
604  /* Update Va and continue looping */
605  Va = (ULONG_PTR)MiPpeToAddress(PointerPpe + 1);
606  continue;
607  }
608 
609  /* Make the PPE valid */
611  }
612 #endif
613  /* Skip invalid PDEs */
614  PointerPde = MiAddressToPde((PVOID)Va);
615  if (!PointerPde->u.Long)
616  {
617  /* There are gaps in the address space */
618  AddressGap = TRUE;
619 
620  /* Check if all the PDEs are invalid, so there's nothing to free */
621  Va = (ULONG_PTR)MiPdeToAddress(PointerPde + 1);
622  continue;
623  }
624 
625  /* Now check if the PDE is mapped in */
626  if (!PointerPde->u.Hard.Valid)
627  {
628  /* It isn't, so map it in */
629  PointerPte = MiPteToAddress(PointerPde);
631  }
632 
633  /* Now we should have a valid PDE, mapped in, and still have some VA */
634  ASSERT(PointerPde->u.Hard.Valid == 1);
635  ASSERT(Va <= EndingAddress);
636 
637  /* Check if this is a section VAD with gaps in it */
638  if ((AddressGap) && (LastPrototypePte))
639  {
640  /* We need to skip to the next correct prototype PTE */
642 
643  /* And we need the subsection to skip to the next last prototype PTE */
644  Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
645  if (Subsection)
646  {
647  /* Found it! */
648  LastPrototypePte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
649  }
650  else
651  {
652  /* No more subsections, we are done with prototype PTEs */
653  PrototypePte = NULL;
654  }
655  }
656 
657  /* Lock the PFN Database while we delete the PTEs */
658  OldIrql = MiAcquirePfnLock();
659  PointerPte = MiAddressToPte(Va);
660  do
661  {
662  /* Making sure the PDE is still valid */
663  ASSERT(PointerPde->u.Hard.Valid == 1);
664 
665  /* Capture the PDE and make sure it exists */
666  TempPte = *PointerPte;
667  if (TempPte.u.Long)
668  {
669  /* Check if the PTE is actually mapped in */
671  {
672  /* Are we dealing with section VAD? */
673  if ((LastPrototypePte) && (PrototypePte > LastPrototypePte))
674  {
675  /* We need to skip to the next correct prototype PTE */
677 
678  /* And we need the subsection to skip to the next last prototype PTE */
679  Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
680  if (Subsection)
681  {
682  /* Found it! */
683  LastPrototypePte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
684  }
685  else
686  {
687  /* No more subsections, we are done with prototype PTEs */
688  PrototypePte = NULL;
689  }
690  }
691 
692  /* Check for prototype PTE */
693  if ((TempPte.u.Hard.Valid == 0) &&
694  (TempPte.u.Soft.Prototype == 1))
695  {
696  /* Just nuke it */
697  MI_ERASE_PTE(PointerPte);
698  }
699  else
700  {
701  /* Delete the PTE proper */
702  MiDeletePte(PointerPte,
703  (PVOID)Va,
705  PrototypePte);
706  }
707  }
708  else
709  {
710  /* The PTE was never mapped, just nuke it here */
711  MI_ERASE_PTE(PointerPte);
712  }
713 
715  {
716  ASSERT(PointerPde->u.Long != 0);
717  /* Delete the PDE proper */
718  MiDeletePde(PointerPde, CurrentProcess);
719  /* Jump */
720  Va = (ULONG_PTR)MiPdeToAddress(PointerPde + 1);
721  break;
722  }
723  }
724 
725  /* Update the address and PTE for it */
726  Va += PAGE_SIZE;
727  PointerPte++;
728  PrototypePte++;
729  } while ((Va & (PDE_MAPPED_VA - 1)) && (Va <= EndingAddress));
730 
731  /* Release the lock */
732  MiReleasePfnLock(OldIrql);
733 
734  if (Va > EndingAddress) return;
735 
736  /* Otherwise, we exited because we hit a new PDE boundary, so start over */
737  AddressGap = FALSE;
738  }
739 }
ULONG NTAPI MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
Definition: virtual.c:183
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:1011
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
MMPTE PrototypePte
Definition: init.c:40
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define TRUE
Definition: types.h:120
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:154
FORCEINLINE USHORT MiDecrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2504
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
#define PsGetCurrentProcess
Definition: psfuncs.h:17
unsigned char BOOLEAN
KIRQL OldIrql
Definition: mm.h:1502
FORCEINLINE PMMPTE MiAddressToPxe(PVOID Address)
Definition: mm.h:164
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:44
ULONG64 Valid
Definition: mmtypes.h:150
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE PVOID MiPxeToAddress(PMMPTE PointerPxe)
Definition: mm.h:228
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE VOID MiDeletePde(_In_ PMMPDE PointerPde, _In_ PEPROCESS CurrentProcess)
Definition: miarm.h:2538
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
PSUBSECTION NTAPI MiLocateSubsection(IN PMMVAD Vad, IN ULONG_PTR Vpn)
Definition: section.c:574
FORCEINLINE PVOID MiPdeToAddress(PMMPTE PointerPde)
Definition: mm.h:210
#define NULL
Definition: types.h:112
VOID NTAPI MiDeletePte(IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
Definition: virtual.c:369
FORCEINLINE PVOID MiPpeToAddress(PMMPTE PointerPpe)
Definition: mm.h:219
FORCEINLINE BOOLEAN MI_IS_MAPPED_PTE(PMMPTE PointerPte)
Definition: mm.h:349
#define PDE_MAPPED_VA
Definition: mm.h:39
#define ULONG_PTR
Definition: config.h:101
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
union _MMPTE::@2287 u
PMMPTE SubsectionBase
Definition: mmtypes.h:578
FORCEINLINE PMMPTE MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad, IN ULONG_PTR Vpn)
Definition: miarm.h:1562
ULONG PtesInSubsection
Definition: mmtypes.h:580

Referenced by MiRemoveMappedView(), MmCleanProcessAddressSpace(), MmDeleteTeb(), and NtFreeVirtualMemory().

◆ MiDoMappedCopy()

NTSTATUS NTAPI MiDoMappedCopy ( IN PEPROCESS  SourceProcess,
IN PVOID  SourceAddress,
IN PEPROCESS  TargetProcess,
OUT PVOID  TargetAddress,
IN SIZE_T  BufferSize,
IN KPROCESSOR_MODE  PreviousMode,
OUT PSIZE_T  ReturnSize 
)

Definition at line 787 of file virtual.c.

794 {
795  PFN_NUMBER MdlBuffer[(sizeof(MDL) / sizeof(PFN_NUMBER)) + MI_MAPPED_COPY_PAGES + 1];
796  PMDL Mdl = (PMDL)MdlBuffer;
797  SIZE_T TotalSize, CurrentSize, RemainingSize;
798  volatile BOOLEAN FailedInProbe = FALSE;
799  volatile BOOLEAN PagesLocked = FALSE;
800  PVOID CurrentAddress = SourceAddress, CurrentTargetAddress = TargetAddress;
801  volatile PVOID MdlAddress = NULL;
803  BOOLEAN HaveBadAddress;
804  ULONG_PTR BadAddress;
806  PAGED_CODE();
807 
808  //
809  // Calculate the maximum amount of data to move
810  //
811  TotalSize = MI_MAPPED_COPY_PAGES * PAGE_SIZE;
812  if (BufferSize <= TotalSize) TotalSize = BufferSize;
813  CurrentSize = TotalSize;
814  RemainingSize = BufferSize;
815 
816  //
817  // Loop as long as there is still data
818  //
819  while (RemainingSize > 0)
820  {
821  //
822  // Check if this transfer will finish everything off
823  //
824  if (RemainingSize < CurrentSize) CurrentSize = RemainingSize;
825 
826  //
827  // Attach to the source address space
828  //
829  KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
830 
831  //
832  // Check state for this pass
833  //
834  ASSERT(MdlAddress == NULL);
835  ASSERT(PagesLocked == FALSE);
836  ASSERT(FailedInProbe == FALSE);
837 
838  //
839  // Protect user-mode copy
840  //
841  _SEH2_TRY
842  {
843  //
844  // If this is our first time, probe the buffer
845  //
846  if ((CurrentAddress == SourceAddress) && (PreviousMode != KernelMode))
847  {
848  //
849  // Catch a failure here
850  //
851  FailedInProbe = TRUE;
852 
853  //
854  // Do the probe
855  //
857 
858  //
859  // Passed
860  //
861  FailedInProbe = FALSE;
862  }
863 
864  //
865  // Initialize and probe and lock the MDL
866  //
867  MmInitializeMdl(Mdl, CurrentAddress, CurrentSize);
869  PagesLocked = TRUE;
870  }
872  {
874  }
875  _SEH2_END
876 
877  /* Detach from source process */
879 
880  if (Status != STATUS_SUCCESS)
881  {
882  goto Exit;
883  }
884 
885  //
886  // Now map the pages
887  //
888  MdlAddress = MmMapLockedPagesSpecifyCache(Mdl,
889  KernelMode,
890  MmCached,
891  NULL,
892  FALSE,
894  if (!MdlAddress)
895  {
897  goto Exit;
898  }
899 
900  //
901  // Grab to the target process
902  //
903  KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
904 
905  _SEH2_TRY
906  {
907  //
908  // Check if this is our first time through
909  //
910  if ((CurrentTargetAddress == TargetAddress) && (PreviousMode != KernelMode))
911  {
912  //
913  // Catch a failure here
914  //
915  FailedInProbe = TRUE;
916 
917  //
918  // Do the probe
919  //
921 
922  //
923  // Passed
924  //
925  FailedInProbe = FALSE;
926  }
927 
928  //
929  // Now do the actual move
930  //
931  RtlCopyMemory(CurrentTargetAddress, MdlAddress, CurrentSize);
932  }
934  &HaveBadAddress,
935  &BadAddress))
936  {
937  *ReturnSize = BufferSize - RemainingSize;
938  //
939  // Check if we failed during the probe
940  //
941  if (FailedInProbe)
942  {
943  //
944  // Exit
945  //
947  }
948  else
949  {
950  //
951  // Othewise we failed during the move.
952  // Check if we know exactly where we stopped copying
953  //
954  if (HaveBadAddress)
955  {
956  //
957  // Return the exact number of bytes copied
958  //
959  *ReturnSize = BadAddress - (ULONG_PTR)SourceAddress;
960  }
961  //
962  // Return partial copy
963  //
965  }
966  }
967  _SEH2_END;
968 
969  /* Detach from target process */
971 
972  //
973  // Check for SEH status
974  //
975  if (Status != STATUS_SUCCESS)
976  {
977  goto Exit;
978  }
979 
980  //
981  // Unmap and unlock
982  //
983  MmUnmapLockedPages(MdlAddress, Mdl);
984  MdlAddress = NULL;
986  PagesLocked = FALSE;
987 
988  //
989  // Update location and size
990  //
991  RemainingSize -= CurrentSize;
992  CurrentAddress = (PVOID)((ULONG_PTR)CurrentAddress + CurrentSize);
993  CurrentTargetAddress = (PVOID)((ULONG_PTR)CurrentTargetAddress + CurrentSize);
994  }
995 
996 Exit:
997  if (MdlAddress != NULL)
998  MmUnmapLockedPages(MdlAddress, Mdl);
999  if (PagesLocked)
1000  MmUnlockPages(Mdl);
1001 
1002  //
1003  // All bytes read
1004  //
1005  if (Status == STATUS_SUCCESS)
1006  *ReturnSize = BufferSize;
1007  return Status;
1008 }
KAPC_STATE
Definition: ketypes.h:1280
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define MmInitializeMdl(_MemoryDescriptorList, _BaseVa, _Length)
#define TRUE
Definition: types.h:120
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1426
#define MI_MAPPED_COPY_PAGES
Definition: virtual.c:18
PVOID PMDL
Definition: usb.h:39
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
PVOID NTAPI MmMapLockedPagesSpecifyCache(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN MEMORY_CACHING_TYPE CacheType, IN PVOID BaseAddress, IN ULONG BugCheckOnFailure, IN ULONG Priority)
Definition: mdlsup.c:651
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI MmUnmapLockedPages(IN PVOID BaseAddress, IN PMDL Mdl)
Definition: mdlsup.c:828
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER _Outptr_ PVOID * TargetAddress
Definition: iotypes.h:1035
unsigned char BOOLEAN
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define ASSERT(a)
Definition: mode.c:44
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
static void Exit(void)
Definition: sock.c:1331
MDL
Definition: mmtypes.h:117
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
static PVOID
Definition: virtual.c:33
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_SEH2_END
Definition: create.c:4400
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:922
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1679
#define NULL
Definition: types.h:112
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
#define STATUS_PARTIAL_COPY
Definition: ntstatus.h:193
#define ULONG_PTR
Definition: config.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS SourceAddress
Definition: iotypes.h:1127
#define BufferSize
Definition: mmc.h:75
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:251
#define PAGED_CODE()
LONG MiGetExceptionInfo(IN PEXCEPTION_POINTERS ExceptionInfo, OUT PBOOLEAN HaveBadAddress, OUT PULONG_PTR BadAddress)
Definition: virtual.c:742

Referenced by MmCopyVirtualMemory().

◆ MiDoPoolCopy()

NTSTATUS NTAPI MiDoPoolCopy ( IN PEPROCESS  SourceProcess,
IN PVOID  SourceAddress,
IN PEPROCESS  TargetProcess,
OUT PVOID  TargetAddress,
IN SIZE_T  BufferSize,
IN KPROCESSOR_MODE  PreviousMode,
OUT PSIZE_T  ReturnSize 
)

Definition at line 1012 of file virtual.c.

1019 {
1020  UCHAR StackBuffer[MI_POOL_COPY_BYTES];
1021  SIZE_T TotalSize, CurrentSize, RemainingSize;
1022  volatile BOOLEAN FailedInProbe = FALSE, HavePoolAddress = FALSE;
1023  PVOID CurrentAddress = SourceAddress, CurrentTargetAddress = TargetAddress;
1024  PVOID PoolAddress;
1026  BOOLEAN HaveBadAddress;
1027  ULONG_PTR BadAddress;
1029  PAGED_CODE();
1030 
1031  DPRINT("Copying %Iu bytes from process %p (address %p) to process %p (Address %p)\n",
1032  BufferSize, SourceProcess, SourceAddress, TargetProcess, TargetAddress);
1033 
1034  //
1035  // Calculate the maximum amount of data to move
1036  //
1037  TotalSize = MI_MAX_TRANSFER_SIZE;
1038  if (BufferSize <= MI_MAX_TRANSFER_SIZE) TotalSize = BufferSize;
1039  CurrentSize = TotalSize;
1040  RemainingSize = BufferSize;
1041 
1042  //
1043  // Check if we can use the stack
1044  //
1046  {
1047  //
1048  // Use it
1049  //
1050  PoolAddress = (PVOID)StackBuffer;
1051  }
1052  else
1053  {
1054  //
1055  // Allocate pool
1056  //
1057  PoolAddress = ExAllocatePoolWithTag(NonPagedPool, TotalSize, 'VmRw');
1058  if (!PoolAddress) ASSERT(FALSE);
1059  HavePoolAddress = TRUE;
1060  }
1061 
1062  //
1063  // Loop as long as there is still data
1064  //
1065  while (RemainingSize > 0)
1066  {
1067  //
1068  // Check if this transfer will finish everything off
1069  //
1070  if (RemainingSize < CurrentSize) CurrentSize = RemainingSize;
1071 
1072  //
1073  // Attach to the source address space
1074  //
1075  KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
1076 
1077  /* Check that state is sane */
1078  ASSERT(FailedInProbe == FALSE);
1080 
1081  //
1082  // Protect user-mode copy
1083  //
1084  _SEH2_TRY
1085  {
1086  //
1087  // If this is our first time, probe the buffer
1088  //
1089  if ((CurrentAddress == SourceAddress) && (PreviousMode != KernelMode))
1090  {
1091  //
1092  // Catch a failure here
1093  //
1094  FailedInProbe = TRUE;
1095 
1096  //
1097  // Do the probe
1098  //
1100 
1101  //
1102  // Passed
1103  //
1104  FailedInProbe = FALSE;
1105  }
1106 
1107  //
1108  // Do the copy
1109  //
1110  RtlCopyMemory(PoolAddress, CurrentAddress, CurrentSize);
1111  }
1113  &HaveBadAddress,
1114  &BadAddress))
1115  {
1116  *ReturnSize = BufferSize - RemainingSize;
1117 
1118  //
1119  // Check if we failed during the probe
1120  //
1121  if (FailedInProbe)
1122  {
1123  //
1124  // Exit
1125  //
1127  }
1128  else
1129  {
1130  //
1131  // We failed during the move.
1132  // Check if we know exactly where we stopped copying
1133  //
1134  if (HaveBadAddress)
1135  {
1136  //
1137  // Return the exact number of bytes copied
1138  //
1139  *ReturnSize = BadAddress - (ULONG_PTR)SourceAddress;
1140  }
1141  //
1142  // Return partial copy
1143  //
1145  }
1146  }
1147  _SEH2_END
1148 
1149  /* Let go of the source */
1151 
1152  if (Status != STATUS_SUCCESS)
1153  {
1154  goto Exit;
1155  }
1156 
1157  /* Grab the target process */
1158  KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
1159 
1160  _SEH2_TRY
1161  {
1162  //
1163  // Check if this is our first time through
1164  //
1165  if ((CurrentTargetAddress == TargetAddress) && (PreviousMode != KernelMode))
1166  {
1167  //
1168  // Catch a failure here
1169  //
1170  FailedInProbe = TRUE;
1171 
1172  //
1173  // Do the probe
1174  //
1176 
1177  //
1178  // Passed
1179  //
1180  FailedInProbe = FALSE;
1181  }
1182 
1183  //
1184  // Now do the actual move
1185  //
1186  RtlCopyMemory(CurrentTargetAddress, PoolAddress, CurrentSize);
1187  }
1189  &HaveBadAddress,
1190  &BadAddress))
1191  {
1192  *ReturnSize = BufferSize - RemainingSize;
1193  //
1194  // Check if we failed during the probe
1195  //
1196  if (FailedInProbe)
1197  {
1198  //
1199  // Exit
1200  //
1202  }
1203  else
1204  {
1205  //
1206  // Otherwise we failed during the move.
1207  // Check if we know exactly where we stopped copying
1208  //
1209  if (HaveBadAddress)
1210  {
1211  //
1212  // Return the exact number of bytes copied
1213  //
1214  *ReturnSize = BadAddress - (ULONG_PTR)SourceAddress;
1215  }
1216  //
1217  // Return partial copy
1218  //
1220  }
1221  }
1222  _SEH2_END;
1223 
1224  //
1225  // Detach from target
1226  //
1228 
1229  //
1230  // Check for SEH status
1231  //
1232  if (Status != STATUS_SUCCESS)
1233  {
1234  goto Exit;
1235  }
1236 
1237  //
1238  // Update location and size
1239  //
1240  RemainingSize -= CurrentSize;
1241  CurrentAddress = (PVOID)((ULONG_PTR)CurrentAddress + CurrentSize);
1242  CurrentTargetAddress = (PVOID)((ULONG_PTR)CurrentTargetAddress +
1243  CurrentSize);
1244  }
1245 
1246 Exit:
1247  //
1248  // Check if we had allocated pool
1249  //
1250  if (HavePoolAddress)
1251  ExFreePoolWithTag(PoolAddress, 'VmRw');
1252 
1253  //
1254  // All bytes read
1255  //
1256  if (Status == STATUS_SUCCESS)
1257  *ReturnSize = BufferSize;
1258  return Status;
1259 }
#define MI_POOL_COPY_BYTES
Definition: virtual.c:19
KAPC_STATE
Definition: ketypes.h:1280
#define TRUE
Definition: types.h:120
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define FALSE
Definition: types.h:117
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER _Outptr_ PVOID * TargetAddress
Definition: iotypes.h:1035
unsigned char BOOLEAN
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define ASSERT(a)
Definition: mode.c:44
static void Exit(void)
Definition: sock.c:1331
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
static PVOID
Definition: virtual.c:33
#define MI_MAX_TRANSFER_SIZE
Definition: virtual.c:20
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_SEH2_END
Definition: create.c:4400
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1679
#define STATUS_PARTIAL_COPY
Definition: ntstatus.h:193
#define ULONG_PTR
Definition: config.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define DPRINT
Definition: sndvol32.h:71
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS SourceAddress
Definition: iotypes.h:1127
#define BufferSize
Definition: mmc.h:75
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:251
#define PAGED_CODE()
LONG MiGetExceptionInfo(IN PEXCEPTION_POINTERS ExceptionInfo, OUT PBOOLEAN HaveBadAddress, OUT PULONG_PTR BadAddress)
Definition: virtual.c:742

Referenced by MmCopyVirtualMemory().

◆ MiFlushTbAndCapture()

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

Definition at line 2012 of file section.c.

2017 {
2018  MMPTE TempPte, PreviousPte;
2019  KIRQL OldIrql;
2020  BOOLEAN RebuildPte = FALSE;
2021 
2022  //
2023  // User for sanity checking later on
2024  //
2025  PreviousPte = *PointerPte;
2026 
2027  //
2028  // Build the PTE and acquire the PFN lock
2029  //
2031  PointerPte,
2032  ProtectionMask,
2033  PreviousPte.u.Hard.PageFrameNumber);
2034  OldIrql = MiAcquirePfnLock();
2035 
2036  //
2037  // We don't support I/O mappings in this path yet
2038  //
2039  ASSERT(Pfn1 != NULL);
2040  ASSERT(Pfn1->u3.e1.CacheAttribute != MiWriteCombined);
2041 
2042  //
2043  // Make sure new protection mask doesn't get in conflict and fix it if it does
2044  //
2045  if (Pfn1->u3.e1.CacheAttribute == MiCached)
2046  {
2047  //
2048  // This is a cached PFN
2049  //
2050  if (ProtectionMask & (MM_NOCACHE | MM_NOACCESS))
2051  {
2052  RebuildPte = TRUE;
2053  ProtectionMask &= ~(MM_NOCACHE | MM_NOACCESS);
2054  }
2055  }
2056  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
2057  {
2058  //
2059  // This is a non-cached PFN
2060  //
2061  if ((ProtectionMask & (MM_NOCACHE | MM_NOACCESS)) != MM_NOCACHE)
2062  {
2063  RebuildPte = TRUE;
2064  ProtectionMask &= ~MM_NOACCESS;
2065  ProtectionMask |= MM_NOCACHE;
2066  }
2067  }
2068 
2069  if (RebuildPte)
2070  {
2072  PointerPte,
2073  ProtectionMask,
2074  PreviousPte.u.Hard.PageFrameNumber);
2075  }
2076 
2077  //
2078  // Write the new PTE, making sure we are only changing the bits
2079  //
2080  MI_UPDATE_VALID_PTE(PointerPte, TempPte);
2081 
2082  //
2083  // Flush the TLB
2084  //
2085  ASSERT(PreviousPte.u.Hard.Valid == 1);
2086  KeFlushCurrentTb();
2087  ASSERT(PreviousPte.u.Hard.Valid == 1);
2088 
2089  //
2090  // Windows updates the relevant PFN1 information, we currently don't.
2091  //
2092  if (UpdateDirty && PreviousPte.u.Hard.Dirty)
2093  {
2094  if (!Pfn1->u3.e1.Modified)
2095  {
2096  DPRINT1("FIXME: Mark PFN as dirty\n");
2097  }
2098  }
2099 
2100  //
2101  // Not supported in ARM3
2102  //
2103  ASSERT(FoundVad->u.VadFlags.VadType != VadWriteWatch);
2104 
2105  //
2106  // Release the PFN lock, we are done
2107  //
2108  MiReleasePfnLock(OldIrql);
2109 }
#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:5012
KIRQL OldIrql
Definition: mm.h:1502
ULONG64 Valid
Definition: mmtypes.h:150
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
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
union _MMPTE::@2287 u
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:312

Referenced by MiProtectVirtualMemory(), and MiSetProtectionOnSection().

◆ MiGetExceptionInfo()

LONG MiGetExceptionInfo ( IN PEXCEPTION_POINTERS  ExceptionInfo,
OUT PBOOLEAN  HaveBadAddress,
OUT PULONG_PTR  BadAddress 
)

Definition at line 742 of file virtual.c.

745 {
746  PEXCEPTION_RECORD ExceptionRecord;
747  PAGED_CODE();
748 
749  //
750  // Assume default
751  //
752  *HaveBadAddress = FALSE;
753 
754  //
755  // Get the exception record
756  //
757  ExceptionRecord = ExceptionInfo->ExceptionRecord;
758 
759  //
760  // Look at the exception code
761  //
762  if ((ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) ||
763  (ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) ||
764  (ExceptionRecord->ExceptionCode == STATUS_IN_PAGE_ERROR))
765  {
766  //
767  // We can tell the address if we have more than one parameter
768  //
769  if (ExceptionRecord->NumberParameters > 1)
770  {
771  //
772  // Return the address
773  //
774  *HaveBadAddress = TRUE;
775  *BadAddress = ExceptionRecord->ExceptionInformation[1];
776  }
777  }
778 
779  //
780  // Continue executing the next handler
781  //
783 }
#define TRUE
Definition: types.h:120
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:182
DWORD ExceptionCode
Definition: compat.h:208
#define FALSE
Definition: types.h:117
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:243
DWORD NumberParameters
Definition: compat.h:212
#define PAGED_CODE()

Referenced by MiDoMappedCopy(), and MiDoPoolCopy().

◆ MiGetPageProtection()

ULONG NTAPI MiGetPageProtection ( IN PMMPTE  PointerPte)

Definition at line 1348 of file virtual.c.

1349 {
1350  MMPTE TempPte;
1351  PMMPFN Pfn;
1353  PETHREAD CurrentThread;
1354  BOOLEAN WsSafe, WsShared;
1355  ULONG Protect;
1356  KIRQL OldIrql;
1357  PAGED_CODE();
1358 
1359  /* Copy this PTE's contents */
1360  TempPte = *PointerPte;
1361 
1362  /* Assure it's not totally zero */
1363  ASSERT(TempPte.u.Long);
1364 
1365  /* Check for a special prototype format */
1366  if ((TempPte.u.Soft.Valid == 0) &&
1367  (TempPte.u.Soft.Prototype == 1))
1368  {
1369  /* Check if the prototype PTE is not yet pointing to a PTE */
1370  if (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
1371  {
1372  /* The prototype PTE contains the protection */
1373  return MmProtectToValue[TempPte.u.Soft.Protection];
1374  }
1375 
1376  /* Get a pointer to the underlying shared PTE */
1377  PointerPte = MiProtoPteToPte(&TempPte);
1378 
1379  /* Since the PTE we want to read can be paged out at any time, we need
1380  to release the working set lock first, so that it can be paged in */
1381  CurrentThread = PsGetCurrentThread();
1384  CurrentThread,
1385  &WsSafe,
1386  &WsShared);
1387 
1388  /* Now read the PTE value */
1389  TempPte = *PointerPte;
1390 
1391  /* Check if that one is invalid */
1392  if (!TempPte.u.Hard.Valid)
1393  {
1394  /* We get the protection directly from this PTE */
1395  Protect = MmProtectToValue[TempPte.u.Soft.Protection];
1396  }
1397  else
1398  {
1399  /* The PTE is valid, so we might need to get the protection from
1400  the PFN. Lock the PFN database */
1401  OldIrql = MiAcquirePfnLock();
1402 
1403  /* Check if the PDE is still valid */
1404  if (MiAddressToPte(PointerPte)->u.Hard.Valid == 0)
1405  {
1406  /* It's not, make it valid */
1407  MiMakeSystemAddressValidPfn(PointerPte, OldIrql);
1408  }
1409 
1410  /* Now it's safe to read the PTE value again */
1411  TempPte = *PointerPte;
1412  ASSERT(TempPte.u.Long != 0);
1413 
1414  /* Check again if the PTE is invalid */
1415  if (!TempPte.u.Hard.Valid)
1416  {
1417  /* The PTE is not valid, so we can use it's protection field */
1418  Protect = MmProtectToValue[TempPte.u.Soft.Protection];
1419  }
1420  else
1421  {
1422  /* The PTE is valid, so we can find the protection in the
1423  OriginalPte field of the PFN */
1424  Pfn = MI_PFN_ELEMENT(TempPte.u.Hard.PageFrameNumber);
1426  }
1427 
1428  /* Release the PFN database */
1429  MiReleasePfnLock(OldIrql);
1430  }
1431 
1432  /* Lock the working set again */
1434  CurrentThread,
1435  WsSafe,
1436  WsShared);
1437 
1438  return Protect;
1439  }
1440 
1441  /* In the easy case of transition or demand zero PTE just return its protection */
1442  if (!TempPte.u.Hard.Valid) return MmProtectToValue[TempPte.u.Soft.Protection];
1443 
1444  /* If we get here, the PTE is valid, so look up the page in PFN database */
1445  Pfn = MiGetPfnEntry(TempPte.u.Hard.PageFrameNumber);
1446  if (!Pfn->u3.e1.PrototypePte)
1447  {
1448  /* Return protection of the original pte */
1449  ASSERT(Pfn->u4.AweAllocation == 0);
1451  }
1452 
1453  /* This is software PTE */
1454  DPRINT("Prototype PTE: %lx %p\n", TempPte.u.Hard.PageFrameNumber, Pfn);
1455  DPRINT("VA: %p\n", MiPteToAddress(&TempPte));
1456  DPRINT("Mask: %lx\n", TempPte.u.Soft.Protection);
1457  DPRINT("Mask2: %lx\n", Pfn->OriginalPte.u.Soft.Protection);
1458  return MmProtectToValue[TempPte.u.Soft.Protection];
1459 }
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 * u
Definition: glfuncs.h:240
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
_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
ULONG_PTR AweAllocation
Definition: mm.h:410
union _MMPFN::@1761 u3
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
USHORT PrototypePte
Definition: mm.h:352
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:386
const ULONG MmProtectToValue[32]
Definition: page.c:71
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define PsGetCurrentProcess
Definition: psfuncs.h:17
unsigned char BOOLEAN
#define MiProtoPteToPte(x)
Definition: mm.h:309
ULONG64 Protection
Definition: mmtypes.h:88
KIRQL OldIrql
Definition: mm.h:1502
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE VOID MiUnlockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, OUT PBOOLEAN Safe, OUT PBOOLEAN Shared)
Definition: miarm.h:1473
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
Definition: mm.h:362
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
FORCEINLINE VOID MiLockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, IN BOOLEAN Safe, IN BOOLEAN Shared)
Definition: miarm.h:1506
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
MMPTE OriginalPte
Definition: mm.h:396
unsigned int ULONG
Definition: retypes.h:1
ULONG NTAPI MiMakeSystemAddressValidPfn(IN PVOID VirtualAddress, IN KIRQL OldIrql)
Definition: virtual.c:235
#define DPRINT
Definition: sndvol32.h:71
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
union _MMPTE::@2287 u
ULONG PageFrameNumber
Definition: mmtypes.h:109
#define PAGED_CODE()
union _MMPFN::@1764 u4

Referenced by MiProtectVirtualMemory(), MiQueryAddressState(), MiSetProtectionOnSection(), and NtAllocateVirtualMemory().

◆ MiIsEntireRangeCommitted()

BOOLEAN NTAPI MiIsEntireRangeCommitted ( IN ULONG_PTR  StartingAddress,
IN ULONG_PTR  EndingAddress,
IN PMMVAD  Vad,
IN PEPROCESS  Process 
)

Definition at line 1995 of file virtual.c.

1999 {
2000  PMMPTE PointerPte, LastPte;
2001  PMMPDE PointerPde;
2002  BOOLEAN OnPdeBoundary = TRUE;
2003 #if _MI_PAGING_LEVELS >= 3
2004  PMMPPE PointerPpe;
2005  BOOLEAN OnPpeBoundary = TRUE;
2006 #if _MI_PAGING_LEVELS == 4
2007  PMMPXE PointerPxe;
2008  BOOLEAN OnPxeBoundary = TRUE;
2009 #endif
2010 #endif
2011 
2012  PAGED_CODE();
2013 
2014  /* Check that we hols the right locks */
2015  ASSERT(PsGetCurrentThread()->OwnsProcessWorkingSetExclusive || PsGetCurrentThread()->OwnsProcessWorkingSetShared);
2016 
2017  /* Get the PTE addresses */
2018  PointerPte = MiAddressToPte(StartingAddress);
2019  LastPte = MiAddressToPte(EndingAddress);
2020 
2021  /* Loop all the PTEs */
2022  while (PointerPte <= LastPte)
2023  {
2024 #if _MI_PAGING_LEVELS == 4
2025  /* Check for new PXE boundary */
2026  if (OnPxeBoundary)
2027  {
2028  PointerPxe = MiPteToPxe(PointerPte);
2029 
2030  /* Check that this loop is sane */
2031  ASSERT(OnPpeBoundary);
2032  ASSERT(OnPdeBoundary);
2033 
2034  if (PointerPxe->u.Long != 0)
2035  {
2036  /* Make it valid if needed */
2037  if (PointerPxe->u.Hard.Valid == 0)
2039  }
2040  else
2041  {
2042  /* Is the entire VAD committed? If not, fail */
2043  if (!Vad->u.VadFlags.MemCommit) return FALSE;
2044 
2045  PointerPxe++;
2046  PointerPte = MiPxeToPte(PointerPte);
2047  continue;
2048  }
2049  }
2050 #endif
2051 
2052 #if _MI_PAGING_LEVELS >= 3
2053  /* Check for new PPE boundary */
2054  if (OnPpeBoundary)
2055  {
2056  PointerPpe = MiPteToPpe(PointerPte);
2057 
2058  /* Check that this loop is sane */
2059  ASSERT(OnPdeBoundary);
2060 
2061  if (PointerPpe->u.Long != 0)
2062  {
2063  /* Make it valid if needed */
2064  if (PointerPpe->u.Hard.Valid == 0)
2066  }
2067  else
2068  {
2069  /* Is the entire VAD committed? If not, fail */
2070  if (!Vad->u.VadFlags.MemCommit) return FALSE;
2071 
2072  PointerPpe++;
2073  PointerPte = MiPpeToPte(PointerPpe);
2074 #if _MI_PAGING_LEVELS == 4
2075  OnPxeBoundary = MiIsPteOnPxeBoundary(PointerPte);
2076 #endif
2077  continue;
2078  }
2079  }
2080 #endif
2081  /* Check if we've hit a new PDE boundary */
2082  if (OnPdeBoundary)
2083  {
2084  /* Is this PDE demand zero? */
2085  PointerPde = MiPteToPde(PointerPte);
2086  if (PointerPde->u.Long != 0)
2087  {
2088  /* It isn't -- is it valid? */
2089  if (PointerPde->u.Hard.Valid == 0)
2090  {
2091  /* Nope, fault it in */
2092  MiMakeSystemAddressValid(PointerPte, Process);
2093  }
2094  }
2095  else
2096  {
2097  /* Is the entire VAD committed? If not, fail */
2098  if (!Vad->u.VadFlags.MemCommit) return FALSE;
2099 
2100  /* The PTE was already valid, so move to the next one */
2101  PointerPde++;
2102  PointerPte = MiPdeToPte(PointerPde);
2103 #if _MI_PAGING_LEVELS >= 3
2104  OnPpeBoundary = MiIsPteOnPpeBoundary(PointerPte);
2105 #if _MI_PAGING_LEVELS == 4
2106  OnPxeBoundary = MiIsPteOnPxeBoundary(PointerPte);
2107 #endif
2108 #endif
2109 
2110  /* New loop iteration with our new, on-boundary PTE. */
2111  continue;
2112  }
2113  }
2114 
2115  /* Is the PTE demand zero? */
2116  if (PointerPte->u.Long == 0)
2117  {
2118  /* Is the entire VAD committed? If not, fail */
2119  if (!Vad->u.VadFlags.MemCommit) return FALSE;
2120  }
2121  else
2122  {
2123  /* It isn't -- is it a decommited, invalid, or faulted PTE? */
2124  if ((PointerPte->u.Soft.Protection == MM_DECOMMIT) &&
2125  (PointerPte->u.Hard.Valid == 0) &&
2126  ((PointerPte->u.Soft.Prototype == 0) ||
2127  (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)))
2128  {
2129  /* Then part of the range is decommitted, so fail */
2130  return FALSE;
2131  }
2132  }
2133 
2134  /* Move to the next PTE */
2135  PointerPte++;
2136  OnPdeBoundary = MiIsPteOnPdeBoundary(PointerPte);
2137 #if _MI_PAGING_LEVELS >= 3
2138  OnPpeBoundary = MiIsPteOnPpeBoundary(PointerPte);
2139 #if _MI_PAGING_LEVELS == 4
2140  OnPxeBoundary = MiIsPteOnPxeBoundary(PointerPte);
2141 #endif
2142 #endif
2143  }
2144 
2145  /* All PTEs seem valid, and no VAD checks failed, the range is okay */
2146  return TRUE;
2147 }
ULONG NTAPI MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
Definition: virtual.c:183
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define TRUE
Definition: types.h:120
#define MM_DECOMMIT
Definition: miarm.h:64
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
FORCEINLINE PMMPDE MiPteToPde(PMMPTE PointerPte)
Definition: mm.h:261
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
FORCEINLINE PMMPPE MiPteToPpe(PMMPTE PointerPte)
Definition: mm.h:269
unsigned char BOOLEAN
FORCEINLINE PMMPTE MiPdeToPte(PMMPDE PointerPde)
Definition: mm.h:237
ULONG64 Protection
Definition: mmtypes.h:88
#define ASSERT(a)
Definition: mode.c:44
ULONG64 Valid
Definition: mmtypes.h:150
#define MiIsPteOnPpeBoundary(PointerPte)
Definition: mm.h:301
FORCEINLINE PMMPTE MiPxeToPte(PMMPXE PointerPxe)
Definition: mm.h:253
ULONG64 PageFileHigh
Definition: mmtypes.h:93
ULONG64 Prototype
Definition: mmtypes.h:89
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:299
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
FORCEINLINE PMMPTE MiPpeToPte(PMMPPE PointerPpe)
Definition: mm.h:245
FORCEINLINE PMMPXE MiPteToPxe(PMMPTE PointerPte)
Definition: mm.h:277
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
union _MMPTE::@2287 u
#define MiIsPteOnPxeBoundary(PointerPte)
Definition: mm.h:303
#define PAGED_CODE()

Referenced by MiProtectVirtualMemory().

◆ MiLockVirtualMemory()

static NTSTATUS MiLockVirtualMemory ( IN OUT PVOID BaseAddress,
IN OUT PSIZE_T  RegionSize,
IN ULONG  MapType 
)
static

Definition at line 3370 of file virtual.c.

3374 {
3377  PVOID CurrentVa, EndAddress;
3378  PMMPTE PointerPte, LastPte;
3379  PMMPDE PointerPde;
3380 #if (_MI_PAGING_LEVELS >= 3)
3381  PMMPDE PointerPpe;
3382 #endif
3383 #if (_MI_PAGING_LEVELS == 4)
3384  PMMPDE PointerPxe;
3385 #endif
3386  PMMPFN Pfn1;
3387  NTSTATUS Status, TempStatus;
3388 
3389  /* Lock the address space */
3392 
3393  /* Make sure we still have an address space */
3395  if (CurrentProcess->VmDeleted)
3396  {
3398  goto Cleanup;
3399  }
3400 
3401  /* Check the VADs in the requested range */
3403  if (!NT_SUCCESS(Status))
3404  {
3405  goto Cleanup;
3406  }
3407 
3408  /* Enter SEH for probing */
3409  _SEH2_TRY
3410  {
3411  /* Loop all pages and probe them */
3412  CurrentVa = *BaseAddress;
3413  while (CurrentVa < EndAddress)
3414  {
3415  (void)(*(volatile CHAR*)CurrentVa);
3416  CurrentVa = (PUCHAR)CurrentVa + PAGE_SIZE;
3417  }
3418  }
3420  {
3422  goto Cleanup;
3423  }
3424  _SEH2_END;
3425 
3426  /* All pages were accessible, since we hold the address space lock, nothing
3427  can be de-committed. Assume success for now. */
3429 
3430  /* Get the PTE and PDE */
3431  PointerPte = MiAddressToPte(*BaseAddress);
3432  PointerPde = MiAddressToPde(*BaseAddress);
3433 #if (_MI_PAGING_LEVELS >= 3)
3434  PointerPpe = MiAddressToPpe(*BaseAddress);
3435 #endif
3436 #if (_MI_PAGING_LEVELS == 4)
3437  PointerPxe = MiAddressToPxe(*BaseAddress);
3438 #endif
3439 
3440  /* Get the last PTE */
3441  LastPte = MiAddressToPte((PVOID)((ULONG_PTR)EndAddress - 1));
3442 
3443  /* Lock the process working set */
3445 
3446  /* Loop the pages */
3447  do
3448  {
3449  /* Check for a page that is not accessible */
3450  while (
3451 #if (_MI_PAGING_LEVELS == 4)
3452  (PointerPxe->u.Hard.Valid == 0) ||
3453 #endif
3454 #if (_MI_PAGING_LEVELS >= 3)
3455  (PointerPpe->u.Hard.Valid == 0) ||
3456 #endif
3457  (PointerPde->u.Hard.Valid == 0) ||
3458  (PointerPte->u.Hard.Valid == 0))
3459  {
3460  /* Release process working set */
3462 
3463  /* Access the page */
3464  CurrentVa = MiPteToAddress(PointerPte);
3465 
3466  //HACK: Pass a placeholder TrapInformation so the fault handler knows we're unlocked
3467  TempStatus = MmAccessFault(TRUE, CurrentVa, KernelMode, (PVOID)(ULONG_PTR)0xBADBADA3BADBADA3ULL);
3468  if (!NT_SUCCESS(TempStatus))
3469  {
3470  // This should only happen, when remote backing storage is not accessible
3471  ASSERT(FALSE);
3472  Status = TempStatus;
3473  goto Cleanup;
3474  }
3475 
3476  /* Lock the process working set */
3478  }
3479 
3480  /* Get the PFN */
3481  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
3482  ASSERT(Pfn1 != NULL);
3483 
3484  /* Check the previous lock status */
3485  if (MI_IS_LOCKED_VA(Pfn1, MapType))
3486  {
3488  }
3489 
3490  /* Lock it */
3491  MI_LOCK_VA(Pfn1, MapType);
3492 
3493  /* Go to the next PTE */
3494  PointerPte++;
3495 
3496  /* Check if we're on a PDE boundary */
3497  if (MiIsPteOnPdeBoundary(PointerPte)) PointerPde++;
3498 #if (_MI_PAGING_LEVELS >= 3)
3499  if (MiIsPteOnPpeBoundary(PointerPte)) PointerPpe++;
3500 #endif
3501 #if (_MI_PAGING_LEVELS == 4)
3502  if (MiIsPteOnPxeBoundary(PointerPte)) PointerPxe++;
3503 #endif
3504  } while (PointerPte <= LastPte);
3505 
3506  /* Release process working set */
3508 
3509 Cleanup:
3510  /* Unlock address space */
3512 
3513  return Status;
3514 }
#define _MI_PAGING_LEVELS
Definition: mm.h:6
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
NTSTATUS NTAPI MmAccessFault(IN ULONG FaultCode, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
Definition: mmfault.c:205
#define TRUE
Definition: types.h:120
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2272
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1618
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:154
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1129
if(dx==0 &&dy==0)
Definition: linetemp.h:174
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
#define PsGetCurrentProcess
Definition: psfuncs.h:17
Status
Definition: gdiplustypes.h:24
FORCEINLINE PMMPTE MiAddressToPxe(PVOID Address)
Definition: mm.h:164
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG CurrentProcess
Definition: shell.c:125
static NTSTATUS MiCheckVadsForLockOperation(_Inout_ PVOID *BaseAddress, _Inout_ PSIZE_T RegionSize, _Inout_ PVOID *EndAddress)
Definition: virtual.c:3325
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
ULONG64 Valid
Definition: mmtypes.h:150
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:502
#define MiIsPteOnPpeBoundary(PointerPte)
Definition: mm.h:301
Definition: mm.h:362
#define PAGE_SIZE
Definition: env_spec_w32.h:49
static const WCHAR Cleanup[]
Definition: register.c:80
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
_SEH2_END
Definition: create.c:4400
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:299
#define STATUS_WAS_LOCKED
Definition: ntstatus.h:139
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
#define NULL
Definition: types.h:112
FORCEINLINE BOOLEAN MI_IS_LOCKED_VA(PMMPFN Pfn1, ULONG LockType)
Definition: virtual.c:3266
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
union _MMPTE::@2287 u
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1611
#define PFN_FROM_PTE(v)
Definition: mm.h:92
FORCEINLINE VOID MI_LOCK_VA(PMMPFN Pfn1, ULONG LockType)
Definition: virtual.c:3283
FORCEINLINE PMMSUPPORT MmGetCurrentAddressSpace(VOID)
Definition: mm.h:1633
#define MiIsPteOnPxeBoundary(PointerPte)
Definition: mm.h:303
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1199

Referenced by NtLockVirtualMemory(), and RunTest().

◆ MiMakePdeExistAndMakeValid()

VOID NTAPI MiMakePdeExistAndMakeValid ( IN PMMPDE  PointerPde,
IN PEPROCESS  TargetProcess,
IN KIRQL  OldIrql 
)

Definition at line 2470 of file virtual.c.

2473 {
2474  PMMPTE PointerPte;
2475 #if _MI_PAGING_LEVELS >= 3
2476  PMMPPE PointerPpe = MiPdeToPpe(PointerPde);
2477 #if _MI_PAGING_LEVELS == 4
2478  PMMPXE PointerPxe = MiPdeToPxe(PointerPde);
2479 #endif
2480 #endif
2481 
2482  //
2483  // Sanity checks. The latter is because we only use this function with the
2484  // PFN lock not held, so it may go away in the future.
2485  //
2487  ASSERT(OldIrql == MM_NOIRQL);
2488 
2489  //
2490  // If everything is already valid, there is nothing to do.
2491  //
2492  if (
2493 #if _MI_PAGING_LEVELS == 4
2494  (PointerPxe->u.Hard.Valid) &&
2495 #endif
2496 #if _MI_PAGING_LEVELS >= 3
2497  (PointerPpe->u.Hard.Valid) &&
2498 #endif
2499  (PointerPde->u.Hard.Valid))
2500  {
2501  return;
2502  }
2503 
2504  //
2505  // At least something is invalid, so begin by getting the PTE for the PDE itself
2506  // and then lookup each additional level. We must do it in this precise order
2507  // because the pagfault.c code (as well as in Windows) depends that the next
2508  // level up (higher) must be valid when faulting a lower level
2509  //
2510  PointerPte = MiPteToAddress(PointerPde);
2511  do
2512  {
2513  //
2514  // Make sure APCs continued to be disabled
2515  //
2517 
2518 #if _MI_PAGING_LEVELS == 4
2519  //
2520  // First, make the PXE valid if needed
2521  //
2522  if (!PointerPxe->u.Hard.Valid)
2523  {
2524  MiMakeSystemAddressValid(PointerPpe, TargetProcess);
2525  ASSERT(PointerPxe->u.Hard.Valid == 1);
2526  }
2527 #endif
2528 
2529 #if _MI_PAGING_LEVELS >= 3
2530  //
2531  // Next, the PPE
2532  //
2533  if (!PointerPpe->u.Hard.Valid)
2534  {
2535  MiMakeSystemAddressValid(PointerPde, TargetProcess);
2536  ASSERT(PointerPpe->u.Hard.Valid == 1);
2537  }
2538 #endif
2539 
2540  //
2541  // And finally, make the PDE itself valid.
2542  //
2543  MiMakeSystemAddressValid(PointerPte, TargetProcess);
2544 
2545  /* Do not increment Page table refcount here for the PDE, this must be managed by caller */
2546 
2547  //
2548  // This should've worked the first time so the loop is really just for
2549  // show -- ASSERT that we're actually NOT going to be looping.
2550  //
2551  ASSERT(PointerPde->u.Hard.Valid == 1);
2552  } while (
2553 #if _MI_PAGING_LEVELS == 4
2554  !PointerPxe->u.Hard.Valid ||
2555 #endif
2556 #if _MI_PAGING_LEVELS >= 3
2557  !PointerPpe->u.Hard.Valid ||
2558 #endif
2559  !PointerPde->u.Hard.Valid);
2560 }
ULONG NTAPI MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
Definition: virtual.c:183
#define _MI_PAGING_LEVELS
Definition: mm.h:6
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
#define TRUE
Definition: types.h:120
#define MM_NOIRQL
Definition: mm.h:59
KIRQL OldIrql
Definition: mm.h:1502
#define ASSERT(a)
Definition: mode.c:44
ULONG64 Valid
Definition: mmtypes.h:150
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
FORCEINLINE PMMPDE MiPdeToPpe(PMMPDE PointerPde)
Definition: mm.h:285
FORCEINLINE PMMPXE MiPdeToPxe(PMMPDE PointerPde)
Definition: mm.h:293
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
union _MMPTE::@2287 u

Referenced by MiDecommitPages(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), MmCreatePageFileMapping(), MmCreateVirtualMappingUnsafe(), MmDeletePageFileMapping(), MmDeleteVirtualMapping(), MmGetPageFileMapping(), MmGetPageProtect(), MmGetPfnForProcess(), MmIsDisabledPage(), MmIsPagePresent(), MmIsPageSwapEntry(), MmSetDirtyBit(), MmSetPageProtect(), and NtAllocateVirtualMemory().

◆ MiMakeSystemAddressValid()

ULONG NTAPI MiMakeSystemAddressValid ( IN PVOID  PageTableVirtualAddress,
IN PEPROCESS  CurrentProcess 
)

Definition at line 183 of file virtual.c.

185 {
187  BOOLEAN WsShared = FALSE, WsSafe = FALSE, LockChange = FALSE;
188  PETHREAD CurrentThread = PsGetCurrentThread();
189 
190  /* Must be a non-pool page table, since those are double-mapped already */
191  ASSERT(PageTableVirtualAddress > MM_HIGHEST_USER_ADDRESS);
192  ASSERT((PageTableVirtualAddress < MmPagedPoolStart) ||
193  (PageTableVirtualAddress > MmPagedPoolEnd));
194 
195  /* Working set lock or PFN lock should be held */
197 
198  /* Check if the page table is valid */
199  while (!MmIsAddressValid(PageTableVirtualAddress))
200  {
201  /* Release the working set lock */
203  CurrentThread,
204  &WsSafe,
205  &WsShared);
206 
207  /* Fault it in */
208  Status = MmAccessFault(FALSE, PageTableVirtualAddress, KernelMode, NULL);
209  if (!NT_SUCCESS(Status))
210  {
211  /* This should not fail */
212  KeBugCheckEx(KERNEL_DATA_INPAGE_ERROR,
213  1,
214  Status,
216  (ULONG_PTR)PageTableVirtualAddress);
217  }
218 
219  /* Lock the working set again */
221  CurrentThread,
222  WsSafe,
223  WsShared);
224 
225  /* This flag will be useful later when we do better locking */
226  LockChange = TRUE;
227  }
228 
229  /* Let caller know what the lock state is */
230  return LockChange;
231 }
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
NTSTATUS NTAPI MmAccessFault(IN ULONG FaultCode, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
Definition: mmfault.c:205
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
PVOID MmPagedPoolEnd
Definition: init.c:26
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
Status
Definition: gdiplustypes.h:24
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE VOID MiUnlockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, OUT PBOOLEAN Safe, OUT PBOOLEAN Shared)
Definition: miarm.h:1473
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOLEAN NTAPI MmIsAddressValid(IN PVOID VirtualAddress)
Definition: mmsup.c:174
PVOID MmPagedPoolStart
Definition: miarm.h:579
FORCEINLINE VOID MiLockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, IN BOOLEAN Safe, IN BOOLEAN Shared)
Definition: miarm.h:1506
#define NULL
Definition: types.h:112
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

Referenced by MiCalculatePageCommitment(), MiDeleteVirtualAddresses(), MiIsEntireRangeCommitted(), MiIsPageTablePresent(), MiMakePdeExistAndMakeValid(), and MiQueryAddressState().

◆ MiMakeSystemAddressValidPfn()

ULONG NTAPI MiMakeSystemAddressValidPfn ( IN PVOID  VirtualAddress,
IN KIRQL  OldIrql 
)

Definition at line 235 of file virtual.c.

237 {
239  BOOLEAN LockChange = FALSE;
240 
241  /* Must be e kernel address */
243 
244  /* Check if the page is valid */
246  {
247  /* Release the PFN database */
248  MiReleasePfnLock(OldIrql);
249 
250  /* Fault it in */
252  if (!NT_SUCCESS(Status))
253  {
254  /* This should not fail */
255  KeBugCheckEx(KERNEL_DATA_INPAGE_ERROR,
256  3,
257  Status,
258  0,
260  }
261 
262  /* This flag will be useful later when we do better locking */
263  LockChange = TRUE;
264 
265  /* Lock the PFN database */
266  OldIrql = MiAcquirePfnLock();
267  }
268 
269  /* Let caller know what the lock state is */
270  return LockChange;
271 }
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
NTSTATUS NTAPI MmAccessFault(IN ULONG FaultCode, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
Definition: mmfault.c:205
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
KIRQL OldIrql
Definition: mm.h:1502
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOLEAN NTAPI MmIsAddressValid(IN PVOID VirtualAddress)
Definition: mmsup.c:174
#define NULL
Definition: types.h:112
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

Referenced by MiGetPageProtection(), and MiSegmentDelete().

◆ MiProcessValidPteList()

VOID NTAPI MiProcessValidPteList ( IN PMMPTE ValidPteList,
IN ULONG  Count 
)

Definition at line 2564 of file virtual.c.

2566 {
2567  KIRQL OldIrql;
2568  ULONG i;
2569  MMPTE TempPte;
2570  PFN_NUMBER PageFrameIndex;
2571  PMMPFN Pfn1, Pfn2;
2572 
2573  //
2574  // Acquire the PFN lock and loop all the PTEs in the list
2575  //
2576  OldIrql = MiAcquirePfnLock();
2577  for (i = 0; i != Count; i++)
2578  {
2579  //
2580  // The PTE must currently be valid
2581  //
2582  TempPte = *ValidPteList[i];
2583  ASSERT(TempPte.u.Hard.Valid == 1);
2584 
2585  //
2586  // Get the PFN entry for the page itself, and then for its page table
2587  //
2588  PageFrameIndex = PFN_FROM_PTE(&TempPte);
2589  Pfn1 = MiGetPfnEntry(PageFrameIndex);
2590  Pfn2 = MiGetPfnEntry(Pfn1->u4.PteFrame);
2591 
2592  //
2593  // Decrement the share count on the page table, and then on the page
2594  // itself
2595  //
2596  MiDecrementShareCount(Pfn2, Pfn1->u4.PteFrame);
2597  MI_SET_PFN_DELETED(Pfn1);
2598  MiDecrementShareCount(Pfn1, PageFrameIndex);
2599 
2600  //
2601  // Make the page decommitted
2602  //
2603  MI_WRITE_INVALID_PTE(ValidPteList[i], MmDecommittedPte);
2604  }
2605 
2606  //
2607  // All the PTEs have been dereferenced and made invalid, flush the TLB now
2608  // and then release the PFN lock
2609  //
2610  KeFlushCurrentTb();
2611  MiReleasePfnLock(OldIrql);
2612 }
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG PFN_NUMBER
Definition: ke.h:9
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1143
KIRQL OldIrql
Definition: mm.h:1502
int Count
Definition: noreturn.cpp:7
#define ASSERT(a)
Definition: mode.c:44
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
Definition: mm.h:362
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:194
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:997
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
ULONG_PTR PteFrame
Definition: mm.h:407
unsigned int ULONG
Definition: retypes.h:1
MMPTE MmDecommittedPte
Definition: init.c:44
#define PFN_FROM_PTE(v)
Definition: mm.h:92
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:312
union _MMPFN::@1764 u4

Referenced by MiDecommitPages().

◆ MiProtectVirtualMemory()

NTSTATUS NTAPI MiProtectVirtualMemory ( IN PEPROCESS  Process,
IN OUT PVOID BaseAddress,
IN OUT PSIZE_T  NumberOfBytesToProtect,
IN ULONG  NewAccessProtection,
OUT PULONG OldAccessProtection  OPTIONAL 
)

Definition at line 2191 of file virtual.c.

2196 {
2198  PMMVAD Vad;
2200  ULONG_PTR StartingAddress, EndingAddress;
2201  PMMPTE PointerPte, LastPte;
2202  PMMPDE PointerPde;
2203  MMPTE PteContents;
2204  PMMPFN Pfn1;
2205  ULONG ProtectionMask, OldProtect;
2206  BOOLEAN Committed;
2210 
2211  /* Calculate base address for the VAD */
2212  StartingAddress = (ULONG_PTR)PAGE_ALIGN((*BaseAddress));
2213  EndingAddress = (((ULONG_PTR)*BaseAddress + *NumberOfBytesToProtect - 1) | (PAGE_SIZE - 1));
2214 
2215  /* Calculate the protection mask and make sure it's valid */
2216  ProtectionMask = MiMakeProtectionMask(NewAccessProtection);
2217  if (ProtectionMask == MM_INVALID_PROTECTION)
2218  {
2219  DPRINT1("Invalid protection mask\n");
2221  }
2222 
2223  /* Check for ROS specific memory area */
2226  {
2227  /* Evil hack */
2229  BaseAddress,
2230  NumberOfBytesToProtect,
2231  NewAccessProtection,
2232  OldAccessProtection);
2233  }
2234 
2235  /* Lock the address space and make sure the process isn't already dead */
2238  if (Process->VmDeleted)
2239  {
2240  DPRINT1("Process is dying\n");
2242  goto FailPath;
2243  }
2244 
2245  /* Get the VAD for this address range, and make sure it exists */
2246  Result = MiCheckForConflictingNode(StartingAddress >> PAGE_SHIFT,
2247  EndingAddress >> PAGE_SHIFT,
2248  &Process->VadRoot,
2249  (PMMADDRESS_NODE*)&Vad);
2250  if (Result != TableFoundNode)
2251  {
2252  DPRINT("Could not find a VAD for this allocation\n");
2254  goto FailPath;
2255  }
2256 
2257  /* Make sure the address is within this VAD's boundaries */
2258  if ((((ULONG_PTR)StartingAddress >> PAGE_SHIFT) < Vad->StartingVpn) ||
2259  (((ULONG_PTR)EndingAddress >> PAGE_SHIFT) > Vad->EndingVpn))
2260  {
2262  goto FailPath;
2263  }
2264 
2265  /* These kinds of VADs are not supported atm */
2266  if ((Vad->u.VadFlags.VadType == VadAwe) ||
2268  (Vad->u.VadFlags.VadType == VadLargePages))
2269  {
2270  DPRINT1("Illegal VAD for attempting to set protection\n");
2272  goto FailPath;
2273  }
2274 
2275  /* Check for a VAD whose protection can't be changed */
2276  if (Vad->u.VadFlags.NoChange == 1)
2277  {
2278  DPRINT1("Trying to change protection of a NoChange VAD\n");
2280  goto FailPath;
2281  }
2282 
2283  /* Is this section, or private memory? */
2284  if (Vad->u.VadFlags.PrivateMemory == 0)
2285  {
2286  /* Not yet supported */
2287  if (Vad->u.VadFlags.VadType == VadLargePageSection)
2288  {
2289  DPRINT1("Illegal VAD for attempting to set protection\n");
2291  goto FailPath;
2292  }
2293 
2294  /* Rotate VADs are not yet supported */
2295  if (Vad->u.VadFlags.VadType == VadRotatePhysical)
2296  {
2297  DPRINT1("Illegal VAD for attempting to set protection\n");
2299  goto FailPath;
2300  }
2301 
2302  /* Not valid on section files */
2303  if (NewAccessProtection & (PAGE_NOCACHE | PAGE_WRITECOMBINE))
2304  {
2305  /* Fail */
2306  DPRINT1("Invalid protection flags for section\n");
2308  goto FailPath;
2309  }
2310 
2311  /* Check if data or page file mapping protection PTE is compatible */
2312  if (!Vad->ControlArea->u.Flags.Image)
2313  {
2314  /* Not yet */
2315  DPRINT1("Fixme: Not checking for valid protection\n");
2316  }
2317 
2318  /* This is a section, and this is not yet supported */
2319  DPRINT1("Section protection not yet supported\n");
2320  OldProtect = 0;
2321  }
2322  else
2323  {
2324  /* Private memory, check protection flags */
2325  if ((NewAccessProtection & PAGE_WRITECOPY) ||
2326  (NewAccessProtection & PAGE_EXECUTE_WRITECOPY))
2327  {
2328  DPRINT1("Invalid protection flags for private memory\n");
2330  goto FailPath;
2331  }
2332 
2333  /* Lock the working set */
2335 
2336  /* Check if all pages in this range are committed */
2337  Committed = MiIsEntireRangeCommitted(StartingAddress,
2338  EndingAddress,
2339  Vad,
2340  Process);
2341  if (!Committed)
2342  {
2343  /* Fail */
2344  DPRINT1("The entire range is not committed\n");
2347  goto FailPath;
2348  }
2349 
2350  /* Compute starting and ending PTE and PDE addresses */
2351  PointerPde = MiAddressToPde(StartingAddress);
2352  PointerPte = MiAddressToPte(StartingAddress);
2353  LastPte = MiAddressToPte(EndingAddress);
2354 
2355  /* Make this PDE valid */
2357 
2358  /* Save protection of the first page */
2359  if (PointerPte->u.Long != 0)
2360  {
2361  /* Capture the page protection and make the PDE valid */
2362  OldProtect = MiGetPageProtection(PointerPte);
2364  }
2365  else
2366  {
2367  /* Grab the old protection from the VAD itself */
2368  OldProtect = MmProtectToValue[Vad->u.VadFlags.Protection];
2369  }
2370 
2371  /* Loop all the PTEs now */
2372  while (PointerPte <= LastPte)
2373  {
2374  /* Check if we've crossed a PDE boundary and make the new PDE valid too */
2375  if (MiIsPteOnPdeBoundary(PointerPte))
2376  {
2377  PointerPde = MiPteToPde(PointerPte);
2379  }
2380 
2381  /* Capture the PTE and check if it was empty */
2382  PteContents = *PointerPte;
2383  if (PteContents.u.Long == 0)
2384  {
2385  /* This used to be a zero PTE and it no longer is, so we must add a
2386  reference to the pagetable. */
2388  }
2389 
2390  /* Check what kind of PTE we are dealing with */
2391  if (PteContents.u.Hard.Valid == 1)
2392  {
2393  /* Get the PFN entry */
2394  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2395 
2396  /* We don't support this yet */
2397  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
2398 
2399  /* Check if the page should not be accessible at all */
2400  if ((NewAccessProtection & PAGE_NOACCESS) ||
2401  (NewAccessProtection & PAGE_GUARD))
2402  {
2403  KIRQL OldIrql = MiAcquirePfnLock();
2404 
2405  /* Mark the PTE as transition and change its protection */
2406  PteContents.u.Hard.Valid = 0;
2407  PteContents.u.Soft.Transition = 1;
2408  PteContents.u.Trans.Protection = ProtectionMask;
2409  /* Decrease PFN share count and write the PTE */
2410  MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
2411  // FIXME: remove the page from the WS
2412  MI_WRITE_INVALID_PTE(PointerPte, PteContents);
2413 #ifdef CONFIG_SMP
2414  // FIXME: Should invalidate entry in every CPU TLB
2415  ASSERT(KeNumberProcessors == 1);
2416 #endif
2417  KeInvalidateTlbEntry(MiPteToAddress(PointerPte));
2418 
2419  /* We are done for this PTE */
2420  MiReleasePfnLock(OldIrql);
2421  }
2422  else
2423  {
2424  /* Write the protection mask and write it with a TLB flush */
2425  Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
2426  MiFlushTbAndCapture(Vad,
2427  PointerPte,
2428  ProtectionMask,
2429  Pfn1,
2430  TRUE);
2431  }
2432  }
2433  else
2434  {
2435  /* We don't support these cases yet */
2436  ASSERT(PteContents.u.Soft.Prototype == 0);
2437  //ASSERT(PteContents.u.Soft.Transition == 0);
2438 
2439  /* The PTE is already demand-zero, just update the protection mask */
2440  PteContents.u.Soft.Protection = ProtectionMask;
2441  MI_WRITE_INVALID_PTE(PointerPte, PteContents);
2442  ASSERT(PointerPte->u.Long != 0);
2443  }
2444 
2445  /* Move to the next PTE */
2446  PointerPte++;
2447  }
2448 
2449  /* Unlock the working set */
2451  }
2452 
2453  /* Unlock the address space */
2455 
2456  /* Return parameters and success */
2457  *NumberOfBytesToProtect = EndingAddress - StartingAddress + 1;
2458  *BaseAddress = (PVOID)StartingAddress;
2459  *OldAccessProtection = OldProtect;
2460  return STATUS_SUCCESS;
2461 
2462 FailPath:
2463  /* Unlock the address space and return the failure code */
2465  return Status;
2466 }
#define PAGE_NOCACHE
Definition: nt_native.h:1311
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
ULONG Type
Definition: mm.h:240
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
#define TRUE
Definition: types.h:120
#define PAGE_GUARD
Definition: nt_native.h:1310
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2272
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1618
enum _TABLE_SEARCH_RESULT TABLE_SEARCH_RESULT
LONG NTSTATUS
Definition: precomp.h:26
union _MMPFN::@1761 u3
ULONG_PTR Protection
Definition: mmtypes.h:693
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
ULONG NTAPI MiGetPageProtection(IN PMMPTE PointerPte)
Definition: virtual.c:1348
FORCEINLINE PMMPDE MiPteToPde(PMMPTE PointerPte)
Definition: mm.h:261
ULONG_PTR NoChange
Definition: mmtypes.h:690
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
VOID NTAPI MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
Definition: virtual.c:2470
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:352
union _MMVAD::@2547 u
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:386
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
const ULONG MmProtectToValue[32]
Definition: page.c:71
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define PAGE_EXECUTE_WRITECOPY
Definition: nt_native.h:1309
#define MM_NOIRQL
Definition: mm.h:59
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:86
PCONTROL_AREA ControlArea
Definition: mmtypes.h:733
#define PAGE_NOACCESS
Definition: nt_native.h:1302
unsigned char BOOLEAN
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1143
ULONG64 Protection
Definition: mmtypes.h:88
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
TABLE_SEARCH_RESULT NTAPI MiCheckForConflictingNode(IN ULONG_PTR StartVpn, IN ULONG_PTR EndVpn, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *NodeOrParent)
Definition: vadnode.c:78
BOOLEAN NTAPI MiIsEntireRangeCommitted(IN ULONG_PTR StartingAddress, IN ULONG_PTR EndingAddress, IN PMMVAD Vad, IN PEPROCESS Process)
Definition: virtual.c:1995
union _CONTROL_AREA::@2540 u
KIRQL OldIrql
Definition: mm.h:1502
Status
Definition: gdiplustypes.h:24
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1174
FORCEINLINE VOID KeInvalidateTlbEntry(IN PVOID Address)
Definition: ke.h:260
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG_PTR PrivateMemory
Definition: mmtypes.h:695
#define ASSERT(a)
Definition: mode.c:44
MMPTE_TRANSITION Trans
Definition: mmtypes.h:220
ULONG64 Valid
Definition: mmtypes.h:150
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:502
#define PAGE_ALIGN(Va)
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2652
FORCEINLINE USHORT MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2478
VOID NTAPI MiFlushTbAndCapture(IN PMMVAD FoundVad, IN PMMPTE PointerPte, IN ULONG ProtectionMask, IN PMMPFN Pfn1, IN BOOLEAN CaptureDirtyBit)
Definition: section.c:2012
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:158
Definition: mm.h:362
static PVOID
Definition: virtual.c:33
ULONG64 Prototype
Definition: mmtypes.h:89
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:305
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
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 PAGE_WRITECOMBINE
Definition: mmtypes.h:78
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:299
NTSTATUS NTAPI MiRosProtectVirtualMemory(IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection OPTIONAL)
Definition: virtual.c:2151
ULONG64 Transition
Definition: mmtypes.h:90
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
MMPTE OriginalPte
Definition: mm.h:396
#define PAGE_WRITECOPY
Definition: nt_native.h:1305
#define STATUS_NOT_COMMITTED
Definition: ntstatus.h:282
#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
MMSECTION_FLAGS Flags
Definition: mmtypes.h:528
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
#define STATUS_INVALID_PARAMETER_4
Definition: ntstatus.h:478
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:261
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:37
union _MMPTE::@2287 u
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1611
#define PFN_FROM_PTE(v)
Definition: mm.h:92
ULONG64 Protection
Definition: mmtypes.h:103
ULONG_PTR VadType
Definition: mmtypes.h:691
FORCEINLINE PMMSUPPORT MmGetCurrentAddressSpace(VOID)
Definition: mm.h:1633

Referenced by CcPreparePinWrite(), CcpUnpinData(), NtAllocateVirtualMemory(), and NtProtectVirtualMemory().

◆ MiQueryAddressState()

ULONG NTAPI MiQueryAddressState ( IN PVOID  Va,
IN PMMVAD  Vad,
IN PEPROCESS  TargetProcess,
OUT PULONG  ReturnedProtect,
OUT PVOID NextVa 
)

Definition at line 1463 of file virtual.c.

1468 {
1469 
1470  PMMPTE PointerPte, ProtoPte;
1471  PMMPDE PointerPde;
1472 #if (_MI_PAGING_LEVELS >= 3)
1473  PMMPPE PointerPpe;
1474 #endif
1475 #if (_MI_PAGING_LEVELS >= 4)
1476  PMMPXE PointerPxe;
1477 #endif
1478  MMPTE TempPte, TempProtoPte;
1479  BOOLEAN DemandZeroPte = TRUE, ValidPte = FALSE;
1480  ULONG State = MEM_RESERVE, Protect = 0;
1481  ASSERT((Vad->StartingVpn <= ((ULONG_PTR)Va >> PAGE_SHIFT)) &&
1482  (Vad->EndingVpn >= ((ULONG_PTR)Va >> PAGE_SHIFT)));
1483 
1484  /* Only normal VADs supported */
1485  ASSERT(Vad->u.VadFlags.VadType == VadNone);
1486 
1487  /* Get the PDE and PTE for the address */
1488  PointerPde = MiAddressToPde(Va);
1489  PointerPte = MiAddressToPte(Va);
1490 #if (_MI_PAGING_LEVELS >= 3)
1491  PointerPpe = MiAddressToPpe(Va);
1492 #endif
1493 #if (_MI_PAGING_LEVELS >= 4)
1494  PointerPxe = MiAddressToPxe(Va);
1495 #endif
1496 
1497  /* Return the next range */
1498  *NextVa = (PVOID)((ULONG_PTR)Va + PAGE_SIZE);
1499 
1500  do
1501  {
1502 #if (_MI_PAGING_LEVELS >= 4)
1503  /* Does the PXE exist? */
1504  if (PointerPxe->u.Long == 0)
1505  {
1506  /* It does not, next range starts at the next PXE */
1507  *NextVa = MiPxeToAddress(PointerPxe + 1);
1508  break;
1509  }
1510 
1511  /* Is the PXE valid? */
1512  if (PointerPxe->u.Hard.Valid == 0)
1513  {
1514  /* Is isn't, fault it in (make the PPE accessible) */
1515  MiMakeSystemAddressValid(PointerPpe, TargetProcess);
1516  }
1517 #endif
1518 #if (_MI_PAGING_LEVELS >= 3)
1519  /* Does the PPE exist? */
1520  if (PointerPpe->u.Long == 0)
1521  {
1522  /* It does not, next range starts at the next PPE */
1523  *NextVa = MiPpeToAddress(PointerPpe + 1);
1524  break;
1525  }
1526 
1527  /* Is the PPE valid? */
1528  if (PointerPpe->u.Hard.Valid == 0)
1529  {
1530  /* Is isn't, fault it in (make the PDE accessible) */
1531  MiMakeSystemAddressValid(PointerPde, TargetProcess);
1532  }
1533 #endif
1534 
1535  /* Does the PDE exist? */
1536  if (PointerPde->u.Long == 0)
1537  {
1538  /* It does not, next range starts at the next PDE */
1539  *NextVa = MiPdeToAddress(PointerPde + 1);
1540  break;
1541  }
1542 
1543  /* Is the PDE valid? */
1544  if (PointerPde->u.Hard.Valid == 0)
1545  {
1546  /* Is isn't, fault it in (make the PTE accessible) */
1547  MiMakeSystemAddressValid(PointerPte, TargetProcess);
1548  }
1549 
1550  /* We have a PTE that we can access now! */
1551  ValidPte = TRUE;
1552 
1553  } while (FALSE);
1554 
1555  /* Is it safe to try reading the PTE? */
1556  if (ValidPte)
1557  {
1558  /* FIXME: watch out for large pages */
1559  ASSERT(PointerPde->u.Hard.LargePage == FALSE);
1560 
1561  /* Capture the PTE */
1562  TempPte = *PointerPte;
1563  if (TempPte.u.Long != 0)
1564  {
1565  /* The PTE is valid, so it's not zeroed out */
1566  DemandZeroPte = FALSE;
1567 
1568  /* Is it a decommited, invalid, or faulted PTE? */
1569  if ((TempPte.u.Soft.Protection == MM_DECOMMIT) &&
1570  (TempPte.u.Hard.Valid == 0) &&
1571  ((TempPte.u.Soft.Prototype == 0) ||
1572  (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)))
1573  {
1574  /* Otherwise our defaults should hold */
1575  ASSERT(Protect == 0);
1576  ASSERT(State == MEM_RESERVE);
1577  }
1578  else
1579  {
1580  /* This means it's committed */
1581  State = MEM_COMMIT;
1582 
1583  /* We don't support these */
1584  ASSERT(Vad->u.VadFlags.VadType != VadDevicePhysicalMemory);
1585  ASSERT(Vad->u.VadFlags.VadType != VadRotatePhysical);
1586  ASSERT(Vad->u.VadFlags.VadType != VadAwe);
1587 
1588  /* Get protection state of this page */
1589  Protect = MiGetPageProtection(PointerPte);
1590 
1591  /* Check if this is an image-backed VAD */
1592  if ((TempPte.u.Soft.Valid == 0) &&
1593  (TempPte.u.Soft.Prototype == 1) &&
1594  (Vad->u.VadFlags.PrivateMemory == 0) &&
1595  (Vad->ControlArea))
1596  {
1597  DPRINT1("Not supported\n");
1598  ASSERT(FALSE);
1599  }
1600  }
1601  }
1602  }
1603 
1604  /* Check if this was a demand-zero PTE, since we need to find the state */
1605  if (DemandZeroPte)
1606  {
1607  /* Not yet handled */
1608  ASSERT(Vad->u.VadFlags.VadType != VadDevicePhysicalMemory);
1609  ASSERT(Vad->u.VadFlags.VadType != VadAwe);
1610 
1611  /* Check if this is private commited memory, or an section-backed VAD */
1612  if ((Vad->u.VadFlags.PrivateMemory == 0) && (Vad->ControlArea))
1613  {
1614  /* Tell caller about the next range */
1615  *NextVa = (PVOID)((ULONG_PTR)Va + PAGE_SIZE);
1616 
1617  /* Get the prototype PTE for this VAD */
1618  ProtoPte = MI_GET_PROTOTYPE_PTE_FOR_VPN(Vad,
1619  (ULONG_PTR)Va >> PAGE_SHIFT);
1620  if (ProtoPte)
1621  {
1622  /* We should unlock the working set, but it's not being held! */
1623 
1624  /* Is the prototype PTE actually valid (committed)? */
1625  TempProtoPte = *ProtoPte;
1626  if (TempProtoPte.u.Long)
1627  {
1628  /* Unless this is a memory-mapped file, handle it like private VAD */
1629  State = MEM_COMMIT;
1630  ASSERT(Vad->u.VadFlags.VadType != VadImageMap);
1631  Protect = MmProtectToValue[Vad->u.VadFlags.Protection];
1632  }
1633 
1634  /* We should re-lock the working set */
1635  }
1636  }
1637  else if (Vad->u.VadFlags.MemCommit)
1638  {
1639  /* This is committed memory */
1640  State = MEM_COMMIT;
1641 
1642  /* Convert the protection */
1643  Protect = MmProtectToValue[Vad->u.VadFlags.Protection];
1644  }
1645  }
1646 
1647  /* Return the protection code */
1648  *ReturnedProtect = Protect;
1649  return State;
1650 }
ULONG NTAPI MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
Definition: virtual.c:183
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define MiAddressToPde(x)
Definition: mmx86.c:20
_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
#define TRUE
Definition: types.h:120
#define MM_DECOMMIT
Definition: miarm.h:64
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:154
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
_In_ ULONG _In_ ULONG State
Definition: potypes.h:516
ULONG NTAPI MiGetPageProtection(IN PMMPTE PointerPte)
Definition: virtual.c:1348
#define MEM_COMMIT
Definition: nt_native.h:1313
uint32_t ULONG_PTR
Definition: typedefs.h:65
const ULONG MmProtectToValue[32]
Definition: page.c:71
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
#define MEM_RESERVE
Definition: nt_native.h:1314
unsigned char BOOLEAN
FORCEINLINE PMMPTE MiAddressToPxe(PVOID Address)
Definition: mm.h:164
#define ASSERT(a)
Definition: mode.c:44
ULONG64 Valid
Definition: mmtypes.h:150
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
static PVOID
Definition: virtual.c:33
FORCEINLINE PVOID MiPxeToAddress(PMMPTE PointerPxe)
Definition: mm.h:228
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
FORCEINLINE PVOID MiPdeToAddress(PMMPTE PointerPde)
Definition: mm.h:210
#define DPRINT1
Definition: precomp.h:8
FORCEINLINE PVOID MiPpeToAddress(PMMPTE PointerPpe)
Definition: mm.h:219
unsigned int ULONG
Definition: retypes.h:1
ULONG64 LargePage
Definition: mmtypes.h:165
MMPTE DemandZeroPte
Definition: init.c:37
union _MMPTE::@2287 u
FORCEINLINE PMMPTE MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad, IN ULONG_PTR Vpn)
Definition: miarm.h:1562

Referenced by MiQueryMemoryBasicInformation().

◆ MiQueryMemoryBasicInformation()

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

Definition at line 1654 of file virtual.c.

1659 {
1660  PEPROCESS TargetProcess;
1662  PMMVAD Vad = NULL;
1663  PVOID Address, NextAddress;
1664  BOOLEAN Found = FALSE;
1665  ULONG NewProtect, NewState;
1666  ULONG_PTR BaseVpn;
1667  MEMORY_BASIC_INFORMATION MemoryInfo;
1672 
1673  /* Check for illegal addresses in user-space, or the shared memory area */
1676  {
1678 
1679  /* Make up an info structure describing this range */
1680  MemoryInfo.BaseAddress = Address;
1681  MemoryInfo.AllocationProtect = PAGE_READONLY;
1682  MemoryInfo.Type = MEM_PRIVATE;
1683 
1684  /* Special case for shared data */
1686  {
1688  MemoryInfo.State = MEM_COMMIT;
1689  MemoryInfo.Protect = PAGE_READONLY;
1690  MemoryInfo.RegionSize = PAGE_SIZE;
1691  }
1692  else
1693  {
1694  MemoryInfo.AllocationBase = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1;
1695  MemoryInfo.State = MEM_RESERVE;
1696  MemoryInfo.Protect = PAGE_NOACCESS;
1698  }
1699 
1700  /* Return the data, NtQueryInformation already probed it*/
1701  if (PreviousMode != KernelMode)
1702  {
1703  _SEH2_TRY
1704  {
1705  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1707  }
1709  {
1711  }
1712  _SEH2_END;
1713  }
1714  else
1715  {
1716  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1718  }
1719 
1720  return Status;
1721  }
1722 
1723  /* Check if this is for a local or remote process */
1725  {
1726  TargetProcess = PsGetCurrentProcess();
1727  }
1728  else
1729  {
1730  /* Reference the target process */
1733  PsProcessType,
1735  (PVOID*)&TargetProcess,
1736  NULL);
1737  if (!NT_SUCCESS(Status)) return Status;
1738 
1739  /* Attach to it now */
1740  KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
1741  }
1742 
1743  /* Lock the address space and make sure the process isn't already dead */
1744  MmLockAddressSpace(&TargetProcess->Vm);
1745  if (TargetProcess->VmDeleted)
1746  {
1747  /* Unlock the address space of the process */
1748  MmUnlockAddressSpace(&TargetProcess->Vm);
1749 
1750  /* Check if we were attached */
1752  {
1753  /* Detach and dereference the process */
1755  ObDereferenceObject(TargetProcess);
1756  }
1757 
1758  /* Bail out */
1759  DPRINT1("Process is dying\n");
1761  }
1762 
1763  /* Loop the VADs */
1764  ASSERT(TargetProcess->VadRoot.NumberGenericTableElements);
1765  if (TargetProcess->VadRoot.NumberGenericTableElements)
1766  {
1767  /* Scan on the right */
1768  Vad = (PMMVAD)TargetProcess->VadRoot.BalancedRoot.RightChild;
1769  BaseVpn = (ULONG_PTR)BaseAddress >> PAGE_SHIFT;
1770  while (Vad)
1771  {
1772  /* Check if this VAD covers the allocation range */
1773  if ((BaseVpn >= Vad->StartingVpn) &&
1774  (BaseVpn <= Vad->EndingVpn))
1775  {
1776  /* We're done */
1777  Found = TRUE;
1778  break;
1779  }
1780 
1781  /* Check if this VAD is too high */
1782  if (BaseVpn < Vad->StartingVpn)
1783  {
1784  /* Stop if there is no left child */
1785  if (!Vad->LeftChild) break;
1786 
1787  /* Search on the left next */
1788  Vad = Vad->LeftChild;
1789  }
1790  else
1791  {
1792  /* Then this VAD is too low, keep searching on the right */
1793  ASSERT(BaseVpn > Vad->EndingVpn);
1794 
1795  /* Stop if there is no right child */
1796  if (!Vad->RightChild) break;
1797 
1798  /* Search on the right next */
1799  Vad = Vad->RightChild;
1800  }
1801  }
1802  }
1803 
1804  /* Was a VAD found? */
1805  if (!Found)
1806  {
1808 
1809  /* Calculate region size */
1810  if (Vad)
1811  {
1812  if (Vad->StartingVpn >= BaseVpn)
1813  {
1814  /* Region size is the free space till the start of that VAD */
1815  MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
1816  }
1817  else
1818  {
1819  /* Get the next VAD */
1820  Vad = (PMMVAD)MiGetNextNode((PMMADDRESS_NODE)Vad);
1821  if (Vad)
1822  {
1823  /* Region size is the free space till the start of that VAD */
1824  MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
1825  }
1826  else
1827  {
1828  /* Maximum possible region size with that base address */
1829  MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
1830  }
1831  }
1832  }
1833  else
1834  {
1835  /* Maximum possible region size with that base address */
1836  MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
1837  }
1838 
1839  /* Unlock the address space of the process */
1840  MmUnlockAddressSpace(&TargetProcess->Vm);
1841 
1842  /* Check if we were attached */
1844  {
1845  /* Detach and derefernece the process */
1847  ObDereferenceObject(TargetProcess);
1848  }
1849 
1850  /* Build the rest of the initial information block */
1851  MemoryInfo.BaseAddress = Address;
1852  MemoryInfo.AllocationBase = NULL;
1853  MemoryInfo.AllocationProtect = 0;
1854  MemoryInfo.State = MEM_FREE;
1855  MemoryInfo.Protect = PAGE_NOACCESS;
1856  MemoryInfo.Type = 0;
1857 
1858  /* Return the data, NtQueryInformation already probed it*/
1859  if (PreviousMode != KernelMode)
1860  {
1861  _SEH2_TRY
1862  {
1863  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1865  }
1867  {
1869  }
1870  _SEH2_END;
1871  }
1872  else
1873  {
1874  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1876  }
1877 
1878  return Status;
1879  }
1880 
1881  /* Set the correct memory type based on what kind of VAD this is */
1882  if ((Vad->u.VadFlags.PrivateMemory) ||
1883  (Vad->u.VadFlags.VadType == VadRotatePhysical))
1884  {
1885  MemoryInfo.Type = MEM_PRIVATE;
1886  }
1887  else if (Vad->u.VadFlags.VadType == VadImageMap)
1888  {
1889  MemoryInfo.Type = MEM_IMAGE;
1890  }
1891  else
1892  {
1893  MemoryInfo.Type = MEM_MAPPED;
1894  }
1895 
1896  /* Find the memory area the specified address belongs to */
1898  ASSERT(MemoryArea != NULL);
1899 
1900  /* Determine information dependent on the memory area type */
1902  {
1904  if (!NT_SUCCESS(Status))
1905  {
1906  DPRINT1("MmQuerySectionView failed. MemoryArea=%p (%p-%p), BaseAddress=%p\n",
1909  }
1910  }
1911  else
1912  {
1913  /* Build the initial information block */
1915  MemoryInfo.BaseAddress = Address;
1916  MemoryInfo.AllocationBase = (PVOID)(Vad->StartingVpn << PAGE_SHIFT);
1918  MemoryInfo.Type = MEM_PRIVATE;
1919 
1920  /* Acquire the working set lock (shared is enough) */
1922 
1923  /* Find the largest chunk of memory which has the same state and protection mask */
1924  MemoryInfo.State = MiQueryAddressState(Address,
1925  Vad,
1926  TargetProcess,
1927  &MemoryInfo.Protect,
1928  &NextAddress);
1929  Address = NextAddress;
1930  while (((ULONG_PTR)Address >> PAGE_SHIFT) <= Vad->EndingVpn)
1931  {
1932  /* Keep going unless the state or protection mask changed */
1933  NewState = MiQueryAddressState(Address, Vad, TargetProcess, &NewProtect, &NextAddress);
1934  if ((NewState != MemoryInfo.State) || (NewProtect != MemoryInfo.Protect)) break;
1935  Address = NextAddress;
1936  }
1937 
1938  /* Release the working set lock */
1940 
1941  /* Check if we went outside of the VAD */
1942  if (((ULONG_PTR)Address >> PAGE_SHIFT) > Vad->EndingVpn)
1943  {
1944  /* Set the end of the VAD as the end address */
1945  Address = (PVOID)((Vad->EndingVpn + 1) << PAGE_SHIFT);
1946  }
1947 
1948  /* Now that we know the last VA address, calculate the region size */
1949  MemoryInfo.RegionSize = ((ULONG_PTR)Address - (ULONG_PTR)MemoryInfo.BaseAddress);
1950  }
1951 
1952  /* Unlock the address space of the process */
1953  MmUnlockAddressSpace(&TargetProcess->Vm);
1954 
1955  /* Check if we were attached */
1957  {
1958  /* Detach and derefernece the process */
1960  ObDereferenceObject(TargetProcess);
1961  }
1962 
1963  /* Return the data, NtQueryInformation already probed it */
1964  if (PreviousMode != KernelMode)
1965  {
1966  _SEH2_TRY
1967  {
1968  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1970  }
1972  {
1974  }
1975  _SEH2_END;
1976  }
1977  else
1978  {
1979  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1981  }
1982 
1983  /* All went well */
1984  DPRINT("Base: %p AllocBase: %p AllocProtect: %lx Protect: %lx "
1985  "State: %lx Type: %lx Size: %lx\n",
1986  MemoryInfo.BaseAddress, MemoryInfo.AllocationBase,
1987  MemoryInfo.AllocationProtect, MemoryInfo.Protect,
1988  MemoryInfo.State, MemoryInfo.Type, MemoryInfo.RegionSize);
1989 
1990  return Status;
1991 }
signed char * PCHAR
Definition: retypes.h:7
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define MEM_IMAGE
Definition: mmtypes.h:88
KAPC_STATE
Definition: ketypes.h:1280
ULONG Type
Definition: mm.h:240
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:166
struct _MEMORY_BASIC_INFORMATION MEMORY_BASIC_INFORMATION
FORCEINLINE VOID MiUnlockProcessWorkingSetShared(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1220
#define TRUE
Definition: types.h:120
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1618
LONG NTSTATUS
Definition: precomp.h:26
ULONG_PTR NumberGenericTableElements
Definition: mmtypes.h:665
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3070
ULONG_PTR Protection
Definition: mmtypes.h:693
#define MM_SHARED_USER_DATA_VA
Definition: mmtypes.h:48
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
#define MEM_COMMIT
Definition: nt_native.h:1313
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
MMADDRESS_NODE BalancedRoot
Definition: mmtypes.h:659
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
union _MMVAD::@2547 u
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
NTSTATUS NTAPI MmQuerySectionView(PMEMORY_AREA MemoryArea, PVOID Address, PMEMORY_BASIC_INFORMATION Info, PSIZE_T ResultLength)
Definition: section.c:2058
const ULONG MmProtectToValue[32]
Definition: page.c:71
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
#define FALSE
Definition: types.h:117
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
struct _MMVAD * LeftChild
Definition: mmtypes.h:724
#define MEM_RESERVE
Definition: nt_native.h:1314
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define PAGE_NOACCESS
Definition: nt_native.h:1302
unsigned char BOOLEAN
static WCHAR Address[46]
Definition: ping.c:68
return Found
Definition: dirsup.c:1270
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:82
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define PCHAR
Definition: match.c:90
Status
Definition: gdiplustypes.h:24
#define MEM_FREE
Definition: nt_native.h:1317
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG VmDeleted
Definition: pstypes.h:1398
ULONG_PTR PrivateMemory
Definition: mmtypes.h:695
#define ASSERT(a)
Definition: mode.c:44
#define MEM_PRIVATE
Definition: nt_native.h:1318
struct _MEMORY_BASIC_INFORMATION * PMEMORY_BASIC_INFORMATION
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:502
#define ObDereferenceObject
Definition: obfuncs.h:203
#define PAGE_ALIGN(Va)
#define MA_GetEndingAddress(_MemoryArea)
Definition: mm.h:234
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
PMMADDRESS_NODE NTAPI MiGetNextNode(IN PMMADDRESS_NODE Node)
Definition: vadnode.c:467
struct _MMADDRESS_NODE * RightChild
Definition: mmtypes.h:649
FORCEINLINE VOID MiLockProcessWorkingSetShared(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1151
struct _MMVAD * RightChild
Definition: mmtypes.h:725
static PVOID
Definition: virtual.c:33
#define PAGE_SIZE
Definition: env_spec_w32.h:49
KPROCESS Pcb
Definition: pstypes.h:1262
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:233
MMSUPPORT Vm
Definition: pstypes.h:1356
ULONG NTAPI MiQueryAddressState(IN PVOID Va, IN PMMVAD Vad, IN PEPROCESS TargetProcess, OUT PULONG ReturnedProtect, OUT PVOID *NextVa)
Definition: virtual.c:1463
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_SEH2_END
Definition: create.c:4400
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1679
_Must_inspect_result_ _In_ ULONG NewProtect
Definition: mmfuncs.h:682
#define NULL
Definition: types.h:112
#define PAGE_READONLY
Definition: compat.h:138
#define MEM_MAPPED
Definition: nt_native.h:1319
#define DPRINT1
Definition: precomp.h:8
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:46
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define DPRINT
Definition: sndvol32.h:71
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
MM_AVL_TABLE VadRoot
Definition: pstypes.h:1453
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:37
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1611
struct _MMVAD * PMMVAD
POBJECT_TYPE PsProcessType
Definition: process.c:20
ULONG_PTR VadType
Definition: mmtypes.h:691

Referenced by NtQueryVirtualMemory().

◆ MiRosProtectVirtualMemory()

NTSTATUS NTAPI MiRosProtectVirtualMemory ( IN PEPROCESS  Process,
IN OUT PVOID BaseAddress,
IN OUT PSIZE_T  NumberOfBytesToProtect,
IN ULONG  NewAccessProtection,
OUT PULONG OldAccessProtection  OPTIONAL 
)

Definition at line 2151 of file virtual.c.

2156 {
2159  ULONG OldAccessProtection_;
2160  NTSTATUS Status;
2161 
2162  *NumberOfBytesToProtect = PAGE_ROUND_UP((ULONG_PTR)(*BaseAddress) + (*NumberOfBytesToProtect)) - PAGE_ROUND_DOWN(*BaseAddress);
2164 
2165  AddressSpace = &Process->Vm;
2169  {
2171  return STATUS_UNSUCCESSFUL;
2172  }
2173 
2174  if (OldAccessProtection == NULL) OldAccessProtection = &OldAccessProtection_;
2175 
2178  MemoryArea,
2179  *BaseAddress,
2180  *NumberOfBytesToProtect,
2181  NewAccessProtection,
2182  OldAccessProtection);
2183 
2185 
2186  return Status;
2187 }
ULONG Type
Definition: mm.h:240
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2272
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1618
LONG NTSTATUS
Definition: precomp.h:26
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:82
Status
Definition: gdiplustypes.h:24
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define ASSERT(a)
Definition: mode.c:44
BOOLEAN DeleteInProgress
Definition: mm.h:242
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
static PVOID
Definition: virtual.c:33
#define NULL
Definition: types.h:112
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
NTSTATUS NTAPI MmProtectSectionView(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PVOID BaseAddress, SIZE_T Length, ULONG Protect, PULONG OldProtect)
Definition: section.c:2022
unsigned int ULONG
Definition: retypes.h:1
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:37
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1611

Referenced by MiProtectVirtualMemory().

◆ MiUnlockVirtualMemory()

static NTSTATUS MiUnlockVirtualMemory ( IN OUT PVOID BaseAddress,
IN OUT PSIZE_T  RegionSize,
IN ULONG  MapType 
)
static

Definition at line 3689 of file virtual.c.

3693 {
3696  PVOID EndAddress;
3697  PMMPTE PointerPte, LastPte;
3698  PMMPDE PointerPde;
3699 #if (_MI_PAGING_LEVELS >= 3)
3700  PMMPDE PointerPpe;
3701 #endif
3702 #if (_MI_PAGING_LEVELS == 4)
3703  PMMPDE PointerPxe;
3704 #endif
3705  PMMPFN Pfn1;
3706  NTSTATUS Status;
3707 
3708  /* Lock the address space */
3711 
3712  /* Make sure we still have an address space */
3714  if (CurrentProcess->VmDeleted)
3715  {
3717  goto Cleanup;
3718  }
3719 
3720  /* Check the VADs in the requested range */
3722 
3723  /* Note: only bail out, if we hit an area without a VAD. If we hit an
3724  incompatible VAD we continue, like Windows does */
3726  {
3728  goto Cleanup;
3729  }
3730 
3731  /* Get the PTE and PDE */
3732  PointerPte = MiAddressToPte(*BaseAddress);
3733  PointerPde = MiAddressToPde(*BaseAddress);
3734 #if (_MI_PAGING_LEVELS >= 3)
3735  PointerPpe = MiAddressToPpe(*BaseAddress);
3736 #endif
3737 #if (_MI_PAGING_LEVELS == 4)
3738  PointerPxe = MiAddressToPxe(*BaseAddress);
3739 #endif
3740 
3741  /* Get the l