ReactOS  0.4.15-dev-5463-g138eb58
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 3271 of file virtual.c.

3274 {
3275  // HACK until we have proper WSLIST support
3276  PMMWSLE Wsle = &Pfn1->Wsle;
3277 
3278  if ((LockType & MAP_PROCESS) && (Wsle->u1.e1.LockedInWs))
3279  return TRUE;
3280  if ((LockType & MAP_SYSTEM) && (Wsle->u1.e1.LockedInMemory))
3281  return TRUE;
3282 
3283  return FALSE;
3284 }
#define TRUE
Definition: types.h:120
MMWSLENTRY e1
Definition: mmtypes.h:855
MMWSLE Wsle
Definition: mm.h:434
#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
union _MMWSLE::@2579 u1
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 3288 of file virtual.c.

3291 {
3292  // HACK until we have proper WSLIST support
3293  PMMWSLE Wsle = &Pfn1->Wsle;
3294 
3295  if (!Wsle->u1.e1.LockedInWs &&
3296  !Wsle->u1.e1.LockedInMemory)
3297  {
3299  }
3300 
3301  if (LockType & MAP_PROCESS)
3302  Wsle->u1.e1.LockedInWs = 1;
3303  if (LockType & MAP_SYSTEM)
3304  Wsle->u1.e1.LockedInMemory = 1;
3305 }
MMWSLENTRY e1
Definition: mmtypes.h:855
MMWSLE Wsle
Definition: mm.h:434
_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
union _MMWSLE::@2579 u1
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 3309 of file virtual.c.

3312 {
3313  // HACK until we have proper WSLIST support
3314  PMMWSLE Wsle = &Pfn1->Wsle;
3315 
3316  if (LockType & MAP_PROCESS)
3317  Wsle->u1.e1.LockedInWs = 0;
3318  if (LockType & MAP_SYSTEM)
3319  Wsle->u1.e1.LockedInMemory = 0;
3320 
3321  if (!Wsle->u1.e1.LockedInWs &&
3322  !Wsle->u1.e1.LockedInMemory)
3323  {
3325  }
3326 }
FORCEINLINE VOID MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1620
MMWSLENTRY e1
Definition: mmtypes.h:855
MMWSLE Wsle
Definition: mm.h:434
_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
union _MMWSLE::@2579 u1
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
union _MMPTE::@2288 u
#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:268
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MiAddressToPte(x)
Definition: mmx86.c:19
FORCEINLINE PMMPPE MiPteToPpe(PMMPTE PointerPte)
Definition: mm.h:276
unsigned char BOOLEAN
FORCEINLINE PMMPTE MiPdeToPte(PMMPDE PointerPde)
Definition: mm.h:244
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:308
#define BYTES_TO_PAGES(Size)
FORCEINLINE PMMPTE MiPxeToPte(PMMPXE PointerPxe)
Definition: mm.h:260
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:306
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
FORCEINLINE PMMPTE MiPpeToPte(PMMPPE PointerPpe)
Definition: mm.h:252
FORCEINLINE PMMPXE MiPteToPxe(PMMPTE PointerPte)
Definition: mm.h:284
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define MiIsPteOnPxeBoundary(PointerPte)
Definition: mm.h:310

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 3330 of file virtual.c.

3335 {
3336  PMMVAD Vad;
3337  PVOID CurrentVa;
3338 
3339  /* Get the base address and align the start address */
3340  *EndAddress = (PUCHAR)*BaseAddress + *RegionSize;
3341  *EndAddress = ALIGN_UP_POINTER_BY(*EndAddress, PAGE_SIZE);
3343 
3344  /* First loop and check all VADs */
3345  CurrentVa = *BaseAddress;
3346  while (CurrentVa < *EndAddress)
3347  {
3348  /* Get VAD */
3349  Vad = MiLocateAddress(CurrentVa);
3350  if (Vad == NULL)
3351  {
3353  return STATUS_ACCESS_VIOLATION;
3354  }
3355 
3356  /* Check VAD type */
3357  if ((Vad->u.VadFlags.VadType != VadNone) &&
3358  (Vad->u.VadFlags.VadType != VadImageMap) &&
3359  (Vad->u.VadFlags.VadType != VadWriteWatch))
3360  {
3361  *EndAddress = CurrentVa;
3362  *RegionSize = (PUCHAR)*EndAddress - (PUCHAR)*BaseAddress;
3364  }
3365 
3366  CurrentVa = (PVOID)((Vad->EndingVpn + 1) << PAGE_SHIFT);
3367  }
3368 
3369  *RegionSize = (PUCHAR)*EndAddress - (PUCHAR)*BaseAddress;
3370  return STATUS_SUCCESS;
3371 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
unsigned char * PUCHAR
Definition: retypes.h:3
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:48
union _MMVAD::@2569 u
_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 2621 of file virtual.c.

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

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:1043
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:265
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
union _MMPTE::@2288 u
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
union _MMPFN::@1757 u3
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:475
FORCEINLINE PMMPDE MiPteToPde(PMMPTE PointerPte)
Definition: mm.h:268
USHORT PageLocation
Definition: mm.h:365
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:363
MMPFNENTRY e1
Definition: mm.h:397
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG_PTR ShareCount
Definition: mm.h:390
#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:1133
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
USHORT WriteInProgress
Definition: mm.h:362
ULONG CurrentProcess
Definition: shell.c:125
struct _MMPFN::@1757::@1763 e2
#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:1224
union _MMPFN::@1756 u2
Definition: mm.h:373
union _MMPFN::@1760 u4
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:194
ULONG_PTR PteFrame
Definition: mm.h:418
PMMPTE PteAddress
Definition: mm.h:386
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
#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:347

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:1133
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:438
#define ASSERT(a)
Definition: mode.c:44
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
Definition: mm.h:373
union _MMPFN::@1760 u4
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
union _MMPFN::@1755 u1
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:194
ULONG_PTR PteFrame
Definition: mm.h:418
ULONG WsIndex
Definition: mm.h:378
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

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 
718  /* Delete the PDE proper */
719  MiDeletePde(PointerPde, CurrentProcess);
720 
721  /* Continue with the next PDE */
722  Va = (ULONG_PTR)MiPdeToAddress(PointerPde + 1);
723 
724  /* Use this to detect address gaps */
725  PointerPte++;
726  break;
727  }
728  }
729 
730  /* Update the address and PTE for it */
731  Va += PAGE_SIZE;
732  PointerPte++;
733  PrototypePte++;
734  } while ((Va & (PDE_MAPPED_VA - 1)) && (Va <= EndingAddress));
735 
736  /* Release the lock */
737  MiReleasePfnLock(OldIrql);
738 
739  if (Va > EndingAddress) return;
740 
741  /* Check if we exited the loop regularly */
742  AddressGap = (PointerPte != MiAddressToPte(Va));
743  }
744 }
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
union _MMPTE::@2288 u
#define TRUE
Definition: types.h:120
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:161
FORCEINLINE USHORT MiDecrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2512
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
FORCEINLINE PMMPTE MiAddressToPxe(PVOID Address)
Definition: mm.h:171
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
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
FORCEINLINE PVOID MiPxeToAddress(PMMPTE PointerPxe)
Definition: mm.h:235
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE VOID MiDeletePde(_In_ PMMPDE PointerPde, _In_ PEPROCESS CurrentProcess)
Definition: miarm.h:2546
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:556
FORCEINLINE PVOID MiPdeToAddress(PMMPTE PointerPde)
Definition: mm.h:217
#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:226
FORCEINLINE BOOLEAN MI_IS_MAPPED_PTE(PMMPTE PointerPte)
Definition: mm.h:356
#define PDE_MAPPED_VA
Definition: mm.h:39
#define ULONG_PTR
Definition: config.h:101
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:208
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 792 of file virtual.c.

799 {
800  PFN_NUMBER MdlBuffer[(sizeof(MDL) / sizeof(PFN_NUMBER)) + MI_MAPPED_COPY_PAGES + 1];
801  PMDL Mdl = (PMDL)MdlBuffer;
802  SIZE_T TotalSize, CurrentSize, RemainingSize;
803  volatile BOOLEAN FailedInProbe = FALSE;
804  volatile BOOLEAN PagesLocked = FALSE;
805  PVOID CurrentAddress = SourceAddress, CurrentTargetAddress = TargetAddress;
806  volatile PVOID MdlAddress = NULL;
808  BOOLEAN HaveBadAddress;
809  ULONG_PTR BadAddress;
811  PAGED_CODE();
812 
813  //
814  // Calculate the maximum amount of data to move
815  //
816  TotalSize = MI_MAPPED_COPY_PAGES * PAGE_SIZE;
817  if (BufferSize <= TotalSize) TotalSize = BufferSize;
818  CurrentSize = TotalSize;
819  RemainingSize = BufferSize;
820 
821  //
822  // Loop as long as there is still data
823  //
824  while (RemainingSize > 0)
825  {
826  //
827  // Check if this transfer will finish everything off
828  //
829  if (RemainingSize < CurrentSize) CurrentSize = RemainingSize;
830 
831  //
832  // Attach to the source address space
833  //
834  KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
835 
836  //
837  // Check state for this pass
838  //
839  ASSERT(MdlAddress == NULL);
840  ASSERT(PagesLocked == FALSE);
841  ASSERT(FailedInProbe == FALSE);
842 
843  //
844  // Protect user-mode copy
845  //
846  _SEH2_TRY
847  {
848  //
849  // If this is our first time, probe the buffer
850  //
851  if ((CurrentAddress == SourceAddress) && (PreviousMode != KernelMode))
852  {
853  //
854  // Catch a failure here
855  //
856  FailedInProbe = TRUE;
857 
858  //
859  // Do the probe
860  //
862 
863  //
864  // Passed
865  //
866  FailedInProbe = FALSE;
867  }
868 
869  //
870  // Initialize and probe and lock the MDL
871  //
872  MmInitializeMdl(Mdl, CurrentAddress, CurrentSize);
874  PagesLocked = TRUE;
875  }
877  {
879  }
880  _SEH2_END
881 
882  /* Detach from source process */
884 
885  if (Status != STATUS_SUCCESS)
886  {
887  goto Exit;
888  }
889 
890  //
891  // Now map the pages
892  //
893  MdlAddress = MmMapLockedPagesSpecifyCache(Mdl,
894  KernelMode,
895  MmCached,
896  NULL,
897  FALSE,
899  if (!MdlAddress)
900  {
902  goto Exit;
903  }
904 
905  //
906  // Grab to the target process
907  //
908  KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
909 
910  _SEH2_TRY
911  {
912  //
913  // Check if this is our first time through
914  //
915  if ((CurrentTargetAddress == TargetAddress) && (PreviousMode != KernelMode))
916  {
917  //
918  // Catch a failure here
919  //
920  FailedInProbe = TRUE;
921 
922  //
923  // Do the probe
924  //
926 
927  //
928  // Passed
929  //
930  FailedInProbe = FALSE;
931  }
932 
933  //
934  // Now do the actual move
935  //
936  RtlCopyMemory(CurrentTargetAddress, MdlAddress, CurrentSize);
937  }
939  &HaveBadAddress,
940  &BadAddress))
941  {
942  *ReturnSize = BufferSize - RemainingSize;
943  //
944  // Check if we failed during the probe
945  //
946  if (FailedInProbe)
947  {
948  //
949  // Exit
950  //
952  }
953  else
954  {
955  //
956  // Othewise we failed during the move.
957  // Check if we know exactly where we stopped copying
958  //
959  if (HaveBadAddress)
960  {
961  //
962  // Return the exact number of bytes copied
963  //
964  *ReturnSize = BadAddress - (ULONG_PTR)SourceAddress;
965  }
966  //
967  // Return partial copy
968  //
970  }
971  }
972  _SEH2_END;
973 
974  /* Detach from target process */
976 
977  //
978  // Check for SEH status
979  //
980  if (Status != STATUS_SUCCESS)
981  {
982  goto Exit;
983  }
984 
985  //
986  // Unmap and unlock
987  //
988  MmUnmapLockedPages(MdlAddress, Mdl);
989  MdlAddress = NULL;
991  PagesLocked = FALSE;
992 
993  //
994  // Update location and size
995  //
996  RemainingSize -= CurrentSize;
997  CurrentAddress = (PVOID)((ULONG_PTR)CurrentAddress + CurrentSize);
998  CurrentTargetAddress = (PVOID)((ULONG_PTR)CurrentTargetAddress + CurrentSize);
999  }
1000 
1001 Exit:
1002  if (MdlAddress != NULL)
1003  MmUnmapLockedPages(MdlAddress, Mdl);
1004  if (PagesLocked)
1005  MmUnlockPages(Mdl);
1006 
1007  //
1008  // All bytes read
1009  //
1010  if (Status == STATUS_SUCCESS)
1011  *ReturnSize = BufferSize;
1012  return Status;
1013 }
_SEH2_TRY
Definition: create.c:4226
KAPC_STATE
Definition: ketypes.h:1285
#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:1435
_SEH2_END
Definition: create.c:4400
#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
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:660
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:837
#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
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1727
#define NULL
Definition: types.h:112
_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:747

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 1017 of file virtual.c.

1024 {
1025  UCHAR StackBuffer[MI_POOL_COPY_BYTES];
1026  SIZE_T TotalSize, CurrentSize, RemainingSize;
1027  volatile BOOLEAN FailedInProbe = FALSE, HavePoolAddress = FALSE;
1028  PVOID CurrentAddress = SourceAddress, CurrentTargetAddress = TargetAddress;
1029  PVOID PoolAddress;
1031  BOOLEAN HaveBadAddress;
1032  ULONG_PTR BadAddress;
1034  PAGED_CODE();
1035 
1036  DPRINT("Copying %Iu bytes from process %p (address %p) to process %p (Address %p)\n",
1037  BufferSize, SourceProcess, SourceAddress, TargetProcess, TargetAddress);
1038 
1039  //
1040  // Calculate the maximum amount of data to move
1041  //
1042  TotalSize = MI_MAX_TRANSFER_SIZE;
1043  if (BufferSize <= MI_MAX_TRANSFER_SIZE) TotalSize = BufferSize;
1044  CurrentSize = TotalSize;
1045  RemainingSize = BufferSize;
1046 
1047  //
1048  // Check if we can use the stack
1049  //
1051  {
1052  //
1053  // Use it
1054  //
1055  PoolAddress = (PVOID)StackBuffer;
1056  }
1057  else
1058  {
1059  //
1060  // Allocate pool
1061  //
1062  PoolAddress = ExAllocatePoolWithTag(NonPagedPool, TotalSize, 'VmRw');
1063  if (!PoolAddress) ASSERT(FALSE);
1064  HavePoolAddress = TRUE;
1065  }
1066 
1067  //
1068  // Loop as long as there is still data
1069  //
1070  while (RemainingSize > 0)
1071  {
1072  //
1073  // Check if this transfer will finish everything off
1074  //
1075  if (RemainingSize < CurrentSize) CurrentSize = RemainingSize;
1076 
1077  //
1078  // Attach to the source address space
1079  //
1080  KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
1081 
1082  /* Check that state is sane */
1083  ASSERT(FailedInProbe == FALSE);
1085 
1086  //
1087  // Protect user-mode copy
1088  //
1089  _SEH2_TRY
1090  {
1091  //
1092  // If this is our first time, probe the buffer
1093  //
1094  if ((CurrentAddress == SourceAddress) && (PreviousMode != KernelMode))
1095  {
1096  //
1097  // Catch a failure here
1098  //
1099  FailedInProbe = TRUE;
1100 
1101  //
1102  // Do the probe
1103  //
1105 
1106  //
1107  // Passed
1108  //
1109  FailedInProbe = FALSE;
1110  }
1111 
1112  //
1113  // Do the copy
1114  //
1115  RtlCopyMemory(PoolAddress, CurrentAddress, CurrentSize);
1116  }
1118  &HaveBadAddress,
1119  &BadAddress))
1120  {
1121  *ReturnSize = BufferSize - RemainingSize;
1122 
1123  //
1124  // Check if we failed during the probe
1125  //
1126  if (FailedInProbe)
1127  {
1128  //
1129  // Exit
1130  //
1132  }
1133  else
1134  {
1135  //
1136  // We failed during the move.
1137  // Check if we know exactly where we stopped copying
1138  //
1139  if (HaveBadAddress)
1140  {
1141  //
1142  // Return the exact number of bytes copied
1143  //
1144  *ReturnSize = BadAddress - (ULONG_PTR)SourceAddress;
1145  }
1146  //
1147  // Return partial copy
1148  //
1150  }
1151  }
1152  _SEH2_END
1153 
1154  /* Let go of the source */
1156 
1157  if (Status != STATUS_SUCCESS)
1158  {
1159  goto Exit;
1160  }
1161 
1162  /* Grab the target process */
1163  KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
1164 
1165  _SEH2_TRY
1166  {
1167  //
1168  // Check if this is our first time through
1169  //
1170  if ((CurrentTargetAddress == TargetAddress) && (PreviousMode != KernelMode))
1171  {
1172  //
1173  // Catch a failure here
1174  //
1175  FailedInProbe = TRUE;
1176 
1177  //
1178  // Do the probe
1179  //
1181 
1182  //
1183  // Passed
1184  //
1185  FailedInProbe = FALSE;
1186  }
1187 
1188  //
1189  // Now do the actual move
1190  //
1191  RtlCopyMemory(CurrentTargetAddress, PoolAddress, CurrentSize);
1192  }
1194  &HaveBadAddress,
1195  &BadAddress))
1196  {
1197  *ReturnSize = BufferSize - RemainingSize;
1198  //
1199  // Check if we failed during the probe
1200  //
1201  if (FailedInProbe)
1202  {
1203  //
1204  // Exit
1205  //
1207  }
1208  else
1209  {
1210  //
1211  // Otherwise we failed during the move.
1212  // Check if we know exactly where we stopped copying
1213  //
1214  if (HaveBadAddress)
1215  {
1216  //
1217  // Return the exact number of bytes copied
1218  //
1219  *ReturnSize = BadAddress - (ULONG_PTR)SourceAddress;
1220  }
1221  //
1222  // Return partial copy
1223  //
1225  }
1226  }
1227  _SEH2_END;
1228 
1229  //
1230  // Detach from target
1231  //
1233 
1234  //
1235  // Check for SEH status
1236  //
1237  if (Status != STATUS_SUCCESS)
1238  {
1239  goto Exit;
1240  }
1241 
1242  //
1243  // Update location and size
1244  //
1245  RemainingSize -= CurrentSize;
1246  CurrentAddress = (PVOID)((ULONG_PTR)CurrentAddress + CurrentSize);
1247  CurrentTargetAddress = (PVOID)((ULONG_PTR)CurrentTargetAddress +
1248  CurrentSize);
1249  }
1250 
1251 Exit:
1252  //
1253  // Check if we had allocated pool
1254  //
1255  if (HavePoolAddress)
1256  ExFreePoolWithTag(PoolAddress, 'VmRw');
1257 
1258  //
1259  // All bytes read
1260  //
1261  if (Status == STATUS_SUCCESS)
1262  *ReturnSize = BufferSize;
1263  return Status;
1264 }
_SEH2_TRY
Definition: create.c:4226
#define MI_POOL_COPY_BYTES
Definition: virtual.c:19
KAPC_STATE
Definition: ketypes.h:1285
#define TRUE
Definition: types.h:120
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
_SEH2_END
Definition: create.c:4400
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
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
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1727
#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:747

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

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

Referenced by MiProtectVirtualMemory(), and MiSetProtectionOnSection().

◆ MiGetExceptionInfo()

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

Definition at line 747 of file virtual.c.

750 {
751  PEXCEPTION_RECORD ExceptionRecord;
752  PAGED_CODE();
753 
754  //
755  // Assume default
756  //
757  *HaveBadAddress = FALSE;
758 
759  //
760  // Get the exception record
761  //
762  ExceptionRecord = ExceptionInfo->ExceptionRecord;
763 
764  //
765  // Look at the exception code
766  //
767  if ((ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) ||
768  (ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) ||
769  (ExceptionRecord->ExceptionCode == STATUS_IN_PAGE_ERROR))
770  {
771  //
772  // We can tell the address if we have more than one parameter
773  //
774  if (ExceptionRecord->NumberParameters > 1)
775  {
776  //
777  // Return the address
778  //
779  *HaveBadAddress = TRUE;
780  *BadAddress = ExceptionRecord->ExceptionInformation[1];
781  }
782  }
783 
784  //
785  // Continue executing the next handler
786  //
788 }
#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 1353 of file virtual.c.

1354 {
1355  MMPTE TempPte;
1356  PMMPFN Pfn;
1358  PETHREAD CurrentThread;
1359  BOOLEAN WsSafe, WsShared;
1360  ULONG Protect;
1361  KIRQL OldIrql;
1362  PAGED_CODE();
1363 
1364  /* Copy this PTE's contents */
1365  TempPte = *PointerPte;
1366 
1367  /* Assure it's not totally zero */
1368  ASSERT(TempPte.u.Long);
1369 
1370  /* Check for a special prototype format */
1371  if ((TempPte.u.Soft.Valid == 0) &&
1372  (TempPte.u.Soft.Prototype == 1))
1373  {
1374  /* Check if the prototype PTE is not yet pointing to a PTE */
1375  if (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
1376  {
1377  /* The prototype PTE contains the protection */
1378  return MmProtectToValue[TempPte.u.Soft.Protection];
1379  }
1380 
1381  /* Get a pointer to the underlying shared PTE */
1382  PointerPte = MiProtoPteToPte(&TempPte);
1383 
1384  /* Since the PTE we want to read can be paged out at any time, we need
1385  to release the working set lock first, so that it can be paged in */
1386  CurrentThread = PsGetCurrentThread();
1389  CurrentThread,
1390  &WsSafe,
1391  &WsShared);
1392 
1393  /* Now read the PTE value */
1394  TempPte = *PointerPte;
1395 
1396  /* Check if that one is invalid */
1397  if (!TempPte.u.Hard.Valid)
1398  {
1399  /* We get the protection directly from this PTE */
1400  Protect = MmProtectToValue[TempPte.u.Soft.Protection];
1401  }
1402  else
1403  {
1404  /* The PTE is valid, so we might need to get the protection from
1405  the PFN. Lock the PFN database */
1406  OldIrql = MiAcquirePfnLock();
1407 
1408  /* Check if the PDE is still valid */
1409  if (MiAddressToPte(PointerPte)->u.Hard.Valid == 0)
1410  {
1411  /* It's not, make it valid */
1412  MiMakeSystemAddressValidPfn(PointerPte, OldIrql);
1413  }
1414 
1415  /* Now it's safe to read the PTE value again */
1416  TempPte = *PointerPte;
1417  ASSERT(TempPte.u.Long != 0);
1418 
1419  /* Check again if the PTE is invalid */
1420  if (!TempPte.u.Hard.Valid)
1421  {
1422  /* The PTE is not valid, so we can use it's protection field */
1423  Protect = MmProtectToValue[TempPte.u.Soft.Protection];
1424  }
1425  else
1426  {
1427  /* The PTE is valid, so we can find the protection in the
1428  OriginalPte field of the PFN */
1429  Pfn = MI_PFN_ELEMENT(TempPte.u.Hard.PageFrameNumber);
1431  }
1432 
1433  /* Release the PFN database */
1434  MiReleasePfnLock(OldIrql);
1435  }
1436 
1437  /* Lock the working set again */
1439  CurrentThread,
1440  WsSafe,
1441  WsShared);
1442 
1443  return Protect;
1444  }
1445 
1446  /* In the easy case of transition or demand zero PTE just return its protection */
1447  if (!TempPte.u.Hard.Valid) return MmProtectToValue[TempPte.u.Soft.Protection];
1448 
1449  /* If we get here, the PTE is valid, so look up the page in PFN database */
1450  Pfn = MiGetPfnEntry(TempPte.u.Hard.PageFrameNumber);
1451  if (!Pfn->u3.e1.PrototypePte)
1452  {
1453  /* Return protection of the original pte */
1454  ASSERT(Pfn->u4.AweAllocation == 0);
1456  }
1457 
1458  /* This is software PTE */
1459  DPRINT("Prototype PTE: %lx %p\n", TempPte.u.Hard.PageFrameNumber, Pfn);
1460  DPRINT("VA: %p\n", MiPteToAddress(&TempPte));
1461  DPRINT("Mask: %lx\n", TempPte.u.Soft.Protection);
1462  DPRINT("Mask2: %lx\n", Pfn->OriginalPte.u.Soft.Protection);
1463  return MmProtectToValue[TempPte.u.Soft.Protection];
1464 }
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
union _MMPTE::@2288 u
_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:421
union _MMPFN::@1757 u3
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
USHORT PrototypePte
Definition: mm.h:363
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:397
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:316
ULONG64 Protection
Definition: mmtypes.h:88
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
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
Definition: mm.h:373
union _MMPFN::@1760 u4
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
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:407
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:208
ULONG PageFrameNumber
Definition: mmtypes.h:109
#define PAGED_CODE()

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 2000 of file virtual.c.

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

3379 {
3382  PVOID CurrentVa, EndAddress;
3383  PMMPTE PointerPte, LastPte;
3384  PMMPDE PointerPde;
3385 #if (_MI_PAGING_LEVELS >= 3)
3386  PMMPDE PointerPpe;
3387 #endif
3388 #if (_MI_PAGING_LEVELS == 4)
3389  PMMPDE PointerPxe;
3390 #endif
3391  PMMPFN Pfn1;
3392  NTSTATUS Status, TempStatus;
3393 
3394  /* Lock the address space */
3397 
3398  /* Make sure we still have an address space */
3400  if (CurrentProcess->VmDeleted)
3401  {
3403  goto Cleanup;
3404  }
3405 
3406  /* Check the VADs in the requested range */
3408  if (!NT_SUCCESS(Status))
3409  {
3410  goto Cleanup;
3411  }
3412 
3413  /* Enter SEH for probing */
3414  _SEH2_TRY
3415  {
3416  /* Loop all pages and probe them */
3417  CurrentVa = *BaseAddress;
3418  while (CurrentVa < EndAddress)
3419  {
3420  (void)(*(volatile CHAR*)CurrentVa);
3421  CurrentVa = (PUCHAR)CurrentVa + PAGE_SIZE;
3422  }
3423  }
3425  {
3427  goto Cleanup;
3428  }
3429  _SEH2_END;
3430 
3431  /* All pages were accessible, since we hold the address space lock, nothing
3432  can be de-committed. Assume success for now. */
3434 
3435  /* Get the PTE and PDE */
3436  PointerPte = MiAddressToPte(*BaseAddress);
3437  PointerPde = MiAddressToPde(*BaseAddress);
3438 #if (_MI_PAGING_LEVELS >= 3)
3439  PointerPpe = MiAddressToPpe(*BaseAddress);
3440 #endif
3441 #if (_MI_PAGING_LEVELS == 4)
3442  PointerPxe = MiAddressToPxe(*BaseAddress);
3443 #endif
3444 
3445  /* Get the last PTE */
3446  LastPte = MiAddressToPte((PVOID)((ULONG_PTR)EndAddress - 1));
3447 
3448  /* Lock the process working set */
3450 
3451  /* Loop the pages */
3452  do
3453  {
3454  /* Check for a page that is not accessible */
3455  while (
3456 #if (_MI_PAGING_LEVELS == 4)
3457  (PointerPxe->u.Hard.Valid == 0) ||
3458 #endif
3459 #if (_MI_PAGING_LEVELS >= 3)
3460  (PointerPpe->u.Hard.Valid == 0) ||
3461 #endif
3462  (PointerPde->u.Hard.Valid == 0) ||
3463  (PointerPte->u.Hard.Valid == 0))
3464  {
3465  /* Release process working set */
3467 
3468  /* Access the page */
3469  CurrentVa = MiPteToAddress(PointerPte);
3470 
3471  //HACK: Pass a placeholder TrapInformation so the fault handler knows we're unlocked
3472  TempStatus = MmAccessFault(TRUE, CurrentVa, KernelMode, (PVOID)(ULONG_PTR)0xBADBADA3BADBADA3ULL);
3473  if (!NT_SUCCESS(TempStatus))
3474  {
3475  // This should only happen, when remote backing storage is not accessible
3476  ASSERT(FALSE);
3477  Status = TempStatus;
3478  goto Cleanup;
3479  }
3480 
3481  /* Lock the process working set */
3483  }
3484 
3485  /* Get the PFN */
3486  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
3487  ASSERT(Pfn1 != NULL);
3488 
3489  /* Check the previous lock status */
3490  if (MI_IS_LOCKED_VA(Pfn1, MapType))
3491  {
3493  }
3494 
3495  /* Lock it */
3496  MI_LOCK_VA(Pfn1, MapType);
3497 
3498  /* Go to the next PTE */
3499  PointerPte++;
3500 
3501  /* Check if we're on a PDE boundary */
3502  if (MiIsPteOnPdeBoundary(PointerPte)) PointerPde++;
3503 #if (_MI_PAGING_LEVELS >= 3)
3504  if (MiIsPteOnPpeBoundary(PointerPte)) PointerPpe++;
3505 #endif
3506 #if (_MI_PAGING_LEVELS == 4)
3507  if (MiIsPteOnPxeBoundary(PointerPte)) PointerPxe++;
3508 #endif
3509  } while (PointerPte <= LastPte);
3510 
3511  /* Release process working set */
3513 
3514 Cleanup:
3515  /* Unlock address space */
3517 
3518  return Status;
3519 }
_SEH2_TRY
Definition: create.c:4226
#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
union _MMPTE::@2288 u
#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:1666
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:161
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1129
_SEH2_END
Definition: create.c:4400
if(dx==0 &&dy==0)
Definition: linetemp.h:174
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:171
_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:3330
#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:308
Definition: mm.h:373
#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:1047
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:306
#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:3271
#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:208
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1659
#define PFN_FROM_PTE(v)
Definition: mm.h:92
FORCEINLINE VOID MI_LOCK_VA(PMMPFN Pfn1, ULONG LockType)
Definition: virtual.c:3288
FORCEINLINE PMMSUPPORT MmGetCurrentAddressSpace(VOID)
Definition: mm.h:1681
#define MiIsPteOnPxeBoundary(PointerPte)
Definition: mm.h:310
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 2475 of file virtual.c.

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

Referenced by _Success_(), MiDecommitPages(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), MmCreatePageFileMapping(), MmCreateVirtualMappingUnsafe(), MmDeletePageFileMapping(), 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
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
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
#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 2569 of file virtual.c.

2571 {
2572  KIRQL OldIrql;
2573  ULONG i;
2574  MMPTE TempPte;
2575  PFN_NUMBER PageFrameIndex;
2576  PMMPFN Pfn1, Pfn2;
2577 
2578  //
2579  // Acquire the PFN lock and loop all the PTEs in the list
2580  //
2581  OldIrql = MiAcquirePfnLock();
2582  for (i = 0; i != Count; i++)
2583  {
2584  //
2585  // The PTE must currently be valid
2586  //
2587  TempPte = *ValidPteList[i];
2588  ASSERT(TempPte.u.Hard.Valid == 1);
2589 
2590  //
2591  // Get the PFN entry for the page itself, and then for its page table
2592  //
2593  PageFrameIndex = PFN_FROM_PTE(&TempPte);
2594  Pfn1 = MiGetPfnEntry(PageFrameIndex);
2595  Pfn2 = MiGetPfnEntry(Pfn1->u4.PteFrame);
2596 
2597  //
2598  // Decrement the share count on the page table, and then on the page
2599  // itself
2600  //
2601  MiDecrementShareCount(Pfn2, Pfn1->u4.PteFrame);
2602  MI_SET_PFN_DELETED(Pfn1);
2603  MiDecrementShareCount(Pfn1, PageFrameIndex);
2604 
2605  //
2606  // Make the page decommitted
2607  //
2608  MI_WRITE_INVALID_PTE(ValidPteList[i], MmDecommittedPte);
2609  }
2610 
2611  //
2612  // All the PTEs have been dereferenced and made invalid, flush the TLB now
2613  // and then release the PFN lock
2614  //
2615  KeFlushCurrentTb();
2616  MiReleasePfnLock(OldIrql);
2617 }
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:1133
int Count
Definition: noreturn.cpp:7
#define ASSERT(a)
Definition: mode.c:44
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
Definition: mm.h:373
union _MMPFN::@1760 u4
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
#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:418
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:347

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 2196 of file virtual.c.

2201 {
2203  PMMVAD Vad;
2205  ULONG_PTR StartingAddress, EndingAddress;
2206  PMMPTE PointerPte, LastPte;
2207  PMMPDE PointerPde;
2208  MMPTE PteContents;
2209  PMMPFN Pfn1;
2210  ULONG ProtectionMask, OldProtect;
2211  BOOLEAN Committed;
2215 
2216  /* Calculate base address for the VAD */
2217  StartingAddress = (ULONG_PTR)PAGE_ALIGN((*BaseAddress));
2218  EndingAddress = (((ULONG_PTR)*BaseAddress + *NumberOfBytesToProtect - 1) | (PAGE_SIZE - 1));
2219 
2220  /* Calculate the protection mask and make sure it's valid */
2221  ProtectionMask = MiMakeProtectionMask(NewAccessProtection);
2222  if (ProtectionMask == MM_INVALID_PROTECTION)
2223  {
2224  DPRINT1("Invalid protection mask\n");
2226  }
2227 
2228  /* Check for ROS specific memory area */
2231  {
2232  /* Evil hack */
2234  BaseAddress,
2235  NumberOfBytesToProtect,
2236  NewAccessProtection,
2237  OldAccessProtection);
2238  }
2239 
2240  /* Lock the address space and make sure the process isn't already dead */
2243  if (Process->VmDeleted)
2244  {
2245  DPRINT1("Process is dying\n");
2247  goto FailPath;
2248  }
2249 
2250  /* Get the VAD for this address range, and make sure it exists */
2251  Result = MiCheckForConflictingNode(StartingAddress >> PAGE_SHIFT,
2252  EndingAddress >> PAGE_SHIFT,
2253  &Process->VadRoot,
2254  (PMMADDRESS_NODE*)&Vad);
2255  if (Result != TableFoundNode)
2256  {
2257  DPRINT("Could not find a VAD for this allocation\n");
2259  goto FailPath;
2260  }
2261 
2262  /* Make sure the address is within this VAD's boundaries */
2263  if ((((ULONG_PTR)StartingAddress >> PAGE_SHIFT) < Vad->StartingVpn) ||
2264  (((ULONG_PTR)EndingAddress >> PAGE_SHIFT) > Vad->EndingVpn))
2265  {
2267  goto FailPath;
2268  }
2269 
2270  /* These kinds of VADs are not supported atm */
2271  if ((Vad->u.VadFlags.VadType == VadAwe) ||
2273  (Vad->u.VadFlags.VadType == VadLargePages))
2274  {
2275  DPRINT1("Illegal VAD for attempting to set protection\n");
2277  goto FailPath;
2278  }
2279 
2280  /* Check for a VAD whose protection can't be changed */
2281  if (Vad->u.VadFlags.NoChange == 1)
2282  {
2283  DPRINT1("Trying to change protection of a NoChange VAD\n");
2285  goto FailPath;
2286  }
2287 
2288  /* Is this section, or private memory? */
2289  if (Vad->u.VadFlags.PrivateMemory == 0)
2290  {
2291  /* Not yet supported */
2292  if (Vad->u.VadFlags.VadType == VadLargePageSection)
2293  {
2294  DPRINT1("Illegal VAD for attempting to set protection\n");
2296  goto FailPath;
2297  }
2298 
2299  /* Rotate VADs are not yet supported */
2300  if (Vad->u.VadFlags.VadType == VadRotatePhysical)
2301  {
2302  DPRINT1("Illegal VAD for attempting to set protection\n");
2304  goto FailPath;
2305  }
2306 
2307  /* Not valid on section files */
2308  if (NewAccessProtection & (PAGE_NOCACHE | PAGE_WRITECOMBINE))
2309  {
2310  /* Fail */
2311  DPRINT1("Invalid protection flags for section\n");
2313  goto FailPath;
2314  }
2315 
2316  /* Check if data or page file mapping protection PTE is compatible */
2317  if (!Vad->ControlArea->u.Flags.Image)
2318  {
2319  /* Not yet */
2320  DPRINT1("Fixme: Not checking for valid protection\n");
2321  }
2322 
2323  /* This is a section, and this is not yet supported */
2324  DPRINT1("Section protection not yet supported\n");
2325  OldProtect = 0;
2326  }
2327  else
2328  {
2329  /* Private memory, check protection flags */
2330  if ((NewAccessProtection & PAGE_WRITECOPY) ||
2331  (NewAccessProtection & PAGE_EXECUTE_WRITECOPY))
2332  {
2333  DPRINT1("Invalid protection flags for private memory\n");
2335  goto FailPath;
2336  }
2337 
2338  /* Lock the working set */
2340 
2341  /* Check if all pages in this range are committed */
2342  Committed = MiIsEntireRangeCommitted(StartingAddress,
2343  EndingAddress,
2344  Vad,
2345  Process);
2346  if (!Committed)
2347  {
2348  /* Fail */
2349  DPRINT1("The entire range is not committed\n");
2352  goto FailPath;
2353  }
2354 
2355  /* Compute starting and ending PTE and PDE addresses */
2356  PointerPde = MiAddressToPde(StartingAddress);
2357  PointerPte = MiAddressToPte(StartingAddress);
2358  LastPte = MiAddressToPte(EndingAddress);
2359 
2360  /* Make this PDE valid */
2362 
2363  /* Save protection of the first page */
2364  if (PointerPte->u.Long != 0)
2365  {
2366  /* Capture the page protection and make the PDE valid */
2367  OldProtect = MiGetPageProtection(PointerPte);
2369  }
2370  else
2371  {
2372  /* Grab the old protection from the VAD itself */
2373  OldProtect = MmProtectToValue[Vad->u.VadFlags.Protection];
2374  }
2375 
2376  /* Loop all the PTEs now */
2377  while (PointerPte <= LastPte)
2378  {
2379  /* Check if we've crossed a PDE boundary and make the new PDE valid too */
2380  if (MiIsPteOnPdeBoundary(PointerPte))
2381  {
2382  PointerPde = MiPteToPde(PointerPte);
2384  }
2385 
2386  /* Capture the PTE and check if it was empty */
2387  PteContents = *PointerPte;
2388  if (PteContents.u.Long == 0)
2389  {
2390  /* This used to be a zero PTE and it no longer is, so we must add a
2391  reference to the pagetable. */
2393  }
2394 
2395  /* Check what kind of PTE we are dealing with */
2396  if (PteContents.u.Hard.Valid == 1)
2397  {
2398  /* Get the PFN entry */
2399  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2400 
2401  /* We don't support this yet */
2402  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
2403 
2404  /* Check if the page should not be accessible at all */
2405  if ((NewAccessProtection & PAGE_NOACCESS) ||
2406  (NewAccessProtection & PAGE_GUARD))
2407  {
2408  KIRQL OldIrql = MiAcquirePfnLock();
2409 
2410  /* Mark the PTE as transition and change its protection */
2411  PteContents.u.Hard.Valid = 0;
2412  PteContents.u.Soft.Transition = 1;
2413  PteContents.u.Trans.Protection = ProtectionMask;
2414  /* Decrease PFN share count and write the PTE */
2415  MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
2416  // FIXME: remove the page from the WS
2417  MI_WRITE_INVALID_PTE(PointerPte, PteContents);
2418 #ifdef CONFIG_SMP
2419  // FIXME: Should invalidate entry in every CPU TLB
2420  ASSERT(KeNumberProcessors == 1);
2421 #endif
2422  KeInvalidateTlbEntry(MiPteToAddress(PointerPte));
2423 
2424  /* We are done for this PTE */
2425  MiReleasePfnLock(OldIrql);
2426  }
2427  else
2428  {
2429  /* Write the protection mask and write it with a TLB flush */
2430  Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
2431  MiFlushTbAndCapture(Vad,
2432  PointerPte,
2433  ProtectionMask,
2434  Pfn1,
2435  TRUE);
2436  }
2437  }
2438  else
2439  {
2440  /* We don't support these cases yet */
2441  ASSERT(PteContents.u.Soft.Prototype == 0);
2442  //ASSERT(PteContents.u.Soft.Transition == 0);
2443 
2444  /* The PTE is already demand-zero, just update the protection mask */
2445  PteContents.u.Soft.Protection = ProtectionMask;
2446  MI_WRITE_INVALID_PTE(PointerPte, PteContents);
2447  ASSERT(PointerPte->u.Long != 0);
2448  }
2449 
2450  /* Move to the next PTE */
2451  PointerPte++;
2452  }
2453 
2454  /* Unlock the working set */
2456  }
2457 
2458  /* Unlock the address space */
2460 
2461  /* Return parameters and success */
2462  *NumberOfBytesToProtect = EndingAddress - StartingAddress + 1;
2463  *BaseAddress = (PVOID)StartingAddress;
2464  *OldAccessProtection = OldProtect;
2465  return STATUS_SUCCESS;
2466 
2467 FailPath:
2468  /* Unlock the address space and return the failure code */
2470  return Status;
2471 }
#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:251
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1244
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
union _MMPTE::@2288 u
#define TRUE
Definition: types.h:120
#define PAGE_GUARD
Definition: nt_native.h:1310
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2272
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1666
enum _TABLE_SEARCH_RESULT TABLE_SEARCH_RESULT
LONG NTSTATUS
Definition: precomp.h:26
union _MMPFN::@1757 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:1353
FORCEINLINE PMMPDE MiPteToPde(PMMPTE PointerPte)
Definition: mm.h:268
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:2475
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:363
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:397
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:70
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:97
PCONTROL_AREA ControlArea
Definition: mmtypes.h:733
union _CONTROL_AREA::@2562 u
#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:1133
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:2000
union _MMVAD::@2569 u
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:264
_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:2486
VOID NTAPI MiFlushTbAndCapture(IN PMMVAD FoundVad, IN PMMPTE PointerPte, IN ULONG ProtectionMask, IN PMMPFN Pfn1, IN BOOLEAN CaptureDirtyBit)
Definition: section.c:2015
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:140
Definition: mm.h:373
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:1047
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:306
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:2156
ULONG64 Transition
Definition: mmtypes.h:90
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
MMPTE OriginalPte
Definition: mm.h:407
#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:208
#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
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1659
#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:1681

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 1468 of file virtual.c.

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

1664 {
1665  PEPROCESS TargetProcess;
1667  PMMVAD Vad = NULL;
1668  PVOID Address, NextAddress;
1669  BOOLEAN Found = FALSE;
1670  ULONG NewProtect, NewState;
1671  ULONG_PTR BaseVpn;
1672  MEMORY_BASIC_INFORMATION MemoryInfo;
1677 
1678  /* Check for illegal addresses in user-space, or the shared memory area */
1681  {
1683 
1684  /* Make up an info structure describing this range */
1685  MemoryInfo.BaseAddress = Address;
1686  MemoryInfo.AllocationProtect = PAGE_READONLY;
1687  MemoryInfo.Type = MEM_PRIVATE;
1688 
1689  /* Special case for shared data */
1691  {
1693  MemoryInfo.State = MEM_COMMIT;
1694  MemoryInfo.Protect = PAGE_READONLY;
1695  MemoryInfo.RegionSize = PAGE_SIZE;
1696  }
1697  else
1698  {
1699  MemoryInfo.AllocationBase = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1;
1700  MemoryInfo.State = MEM_RESERVE;
1701  MemoryInfo.Protect = PAGE_NOACCESS;
1703  }
1704 
1705  /* Return the data, NtQueryInformation already probed it*/
1706  if (PreviousMode != KernelMode)
1707  {
1708  _SEH2_TRY
1709  {
1710  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1712  }
1714  {
1716  }
1717  _SEH2_END;
1718  }
1719  else
1720  {
1721  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1723  }
1724 
1725  return Status;
1726  }
1727 
1728  /* Check if this is for a local or remote process */
1730  {
1731  TargetProcess = PsGetCurrentProcess();
1732  }
1733  else
1734  {
1735  /* Reference the target process */
1738  PsProcessType,
1740  (PVOID*)&TargetProcess,
1741  NULL);
1742  if (!NT_SUCCESS(Status)) return Status;
1743 
1744  /* Attach to it now */
1745  KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
1746  }
1747 
1748  /* Lock the address space and make sure the process isn't already dead */
1749  MmLockAddressSpace(&TargetProcess->Vm);
1750  if (TargetProcess->VmDeleted)
1751  {
1752  /* Unlock the address space of the process */
1753  MmUnlockAddressSpace(&TargetProcess->Vm);
1754 
1755  /* Check if we were attached */
1757  {
1758  /* Detach and dereference the process */
1760  ObDereferenceObject(TargetProcess);
1761  }
1762 
1763  /* Bail out */
1764  DPRINT1("Process is dying\n");
1766  }
1767 
1768  /* Loop the VADs */
1769  ASSERT(TargetProcess->VadRoot.NumberGenericTableElements);
1770  if (TargetProcess->VadRoot.NumberGenericTableElements)
1771  {
1772  /* Scan on the right */
1773  Vad = (PMMVAD)TargetProcess->VadRoot.BalancedRoot.RightChild;
1774  BaseVpn = (ULONG_PTR)BaseAddress >> PAGE_SHIFT;
1775  while (Vad)
1776  {
1777  /* Check if this VAD covers the allocation range */
1778  if ((BaseVpn >= Vad->StartingVpn) &&
1779  (BaseVpn <= Vad->EndingVpn))
1780  {
1781  /* We're done */
1782  Found = TRUE;
1783  break;
1784  }
1785 
1786  /* Check if this VAD is too high */
1787  if (BaseVpn < Vad->StartingVpn)
1788  {
1789  /* Stop if there is no left child */
1790  if (!Vad->LeftChild) break;
1791 
1792  /* Search on the left next */
1793  Vad = Vad->LeftChild;
1794  }
1795  else
1796  {
1797  /* Then this VAD is too low, keep searching on the right */
1798  ASSERT(BaseVpn > Vad->EndingVpn);
1799 
1800  /* Stop if there is no right child */
1801  if (!Vad->RightChild) break;
1802 
1803  /* Search on the right next */
1804  Vad = Vad->RightChild;
1805  }
1806  }
1807  }
1808 
1809  /* Was a VAD found? */
1810  if (!Found)
1811  {
1813 
1814  /* Calculate region size */
1815  if (Vad)
1816  {
1817  if (Vad->StartingVpn >= BaseVpn)
1818  {
1819  /* Region size is the free space till the start of that VAD */
1820  MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
1821  }
1822  else
1823  {
1824  /* Get the next VAD */
1825  Vad = (PMMVAD)MiGetNextNode((PMMADDRESS_NODE)Vad);
1826  if (Vad)
1827  {
1828  /* Region size is the free space till the start of that VAD */
1829  MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
1830  }
1831  else
1832  {
1833  /* Maximum possible region size with that base address */
1834  MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
1835  }
1836  }
1837  }
1838  else
1839  {
1840  /* Maximum possible region size with that base address */
1841  MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
1842  }
1843 
1844  /* Unlock the address space of the process */
1845  MmUnlockAddressSpace(&TargetProcess->Vm);
1846 
1847  /* Check if we were attached */
1849  {
1850  /* Detach and dereference the process */
1852  ObDereferenceObject(TargetProcess);
1853  }
1854 
1855  /* Build the rest of the initial information block */
1856  MemoryInfo.BaseAddress = Address;
1857  MemoryInfo.AllocationBase = NULL;
1858  MemoryInfo.AllocationProtect = 0;
1859  MemoryInfo.State = MEM_FREE;
1860  MemoryInfo.Protect = PAGE_NOACCESS;
1861  MemoryInfo.Type = 0;
1862 
1863  /* Return the data, NtQueryInformation already probed it*/
1864  if (PreviousMode != KernelMode)
1865  {
1866  _SEH2_TRY
1867  {
1868  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1870  }
1872  {
1874  }
1875  _SEH2_END;
1876  }
1877  else
1878  {
1879  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1881  }
1882 
1883  return Status;
1884  }
1885 
1886  /* Set the correct memory type based on what kind of VAD this is */
1887  if ((Vad->u.VadFlags.PrivateMemory) ||
1888  (Vad->u.VadFlags.VadType == VadRotatePhysical))
1889  {
1890  MemoryInfo.Type = MEM_PRIVATE;
1891  }
1892  else if (Vad->u.VadFlags.VadType == VadImageMap)
1893  {
1894  MemoryInfo.Type = MEM_IMAGE;
1895  }
1896  else
1897  {
1898  MemoryInfo.Type = MEM_MAPPED;
1899  }
1900 
1901  /* Find the memory area the specified address belongs to */
1903  ASSERT(MemoryArea != NULL);
1904 
1905  /* Determine information dependent on the memory area type */
1907  {
1909  if (!NT_SUCCESS(Status))
1910  {
1911  DPRINT1("MmQuerySectionView failed. MemoryArea=%p (%p-%p), BaseAddress=%p\n",
1914  }
1915  }
1916  else
1917  {
1918  /* Build the initial information block */
1920  MemoryInfo.BaseAddress = Address;
1921  MemoryInfo.AllocationBase = (PVOID)(Vad->StartingVpn << PAGE_SHIFT);
1923  MemoryInfo.Type = MEM_PRIVATE;
1924 
1925  /* Acquire the working set lock (shared is enough) */
1927 
1928  /* Find the largest chunk of memory which has the same state and protection mask */
1929  MemoryInfo.State = MiQueryAddressState(Address,
1930  Vad,
1931  TargetProcess,
1932  &MemoryInfo.Protect,
1933  &NextAddress);
1934  Address = NextAddress;
1935  while (((ULONG_PTR)Address >> PAGE_SHIFT) <= Vad->EndingVpn)
1936  {
1937  /* Keep going unless the state or protection mask changed */
1938  NewState = MiQueryAddressState(Address, Vad, TargetProcess, &NewProtect, &NextAddress);
1939  if ((NewState != MemoryInfo.State) || (NewProtect != MemoryInfo.Protect)) break;
1940  Address = NextAddress;
1941  }
1942 
1943  /* Release the working set lock */
1945 
1946  /* Check if we went outside of the VAD */
1947  if (((ULONG_PTR)Address >> PAGE_SHIFT) > Vad->EndingVpn)
1948  {
1949  /* Set the end of the VAD as the end address */
1950  Address = (PVOID)((Vad->EndingVpn + 1) << PAGE_SHIFT);
1951  }
1952 
1953  /* Now that we know the last VA address, calculate the region size */
1954  MemoryInfo.RegionSize = ((ULONG_PTR)Address - (ULONG_PTR)MemoryInfo.BaseAddress);
1955  }
1956 
1957  /* Unlock the address space of the process */
1958  MmUnlockAddressSpace(&TargetProcess->Vm);
1959 
1960  /* Check if we were attached */
1962  {
1963  /* Detach and dereference the process */
1965  ObDereferenceObject(TargetProcess);
1966  }
1967 
1968  /* Return the data, NtQueryInformation already probed it */
1969  if (PreviousMode != KernelMode)
1970  {
1971  _SEH2_TRY
1972  {
1973  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1975  }
1977  {
1979  }
1980  _SEH2_END;
1981  }
1982  else
1983  {
1984  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1986  }
1987 
1988  /* All went well */
1989  DPRINT("Base: %p AllocBase: %p AllocProtect: %lx Protect: %lx "
1990  "State: %lx Type: %lx Size: %lx\n",
1991  MemoryInfo.BaseAddress, MemoryInfo.AllocationBase,
1992  MemoryInfo.AllocationProtect, MemoryInfo.Protect,
1993  MemoryInfo.State, MemoryInfo.Type, MemoryInfo.RegionSize);
1994 
1995  return Status;
1996 }
_SEH2_TRY
Definition: create.c:4226
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:1285
ULONG Type
Definition: mm.h:251
#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:1666
LONG NTSTATUS
Definition: precomp.h:26
ULONG_PTR NumberGenericTableElements
Definition: mmtypes.h:665
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3062
ULONG_PTR Protection
Definition: mmtypes.h:693
_SEH2_END
Definition: create.c:4400
#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
uint32_t ULONG_PTR
Definition: typedefs.h:65
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:2077
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:93
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define PCHAR
Definition: match.c:90
union _MMVAD::@2569 u
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:245
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:244
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:1468
ULONG_PTR SIZE_T
Definition: typedefs.h:80
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1727
_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:1659
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 2156 of file virtual.c.

2161 {
2164  ULONG OldAccessProtection_;
2165  NTSTATUS Status;
2166 
2167  *NumberOfBytesToProtect = PAGE_ROUND_UP((ULONG_PTR)(*BaseAddress) + (*NumberOfBytesToProtect)) - PAGE_ROUND_DOWN(*BaseAddress);
2169 
2170  AddressSpace = &Process->Vm;
2174  {
2176  return STATUS_UNSUCCESSFUL;
2177  }
2178 
2179  if (OldAccessProtection == NULL) OldAccessProtection = &OldAccessProtection_;
2180 
2183  MemoryArea,
2184  *BaseAddress,
2185  *NumberOfBytesToProtect,
2186  NewAccessProtection,
2187  OldAccessProtection);
2188 
2190 
2191  return Status;
2192 }
ULONG Type
Definition: mm.h:251
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2272
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1666
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:93
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:253
#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:2041
unsigned int ULONG
Definition: retypes.h:1
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:37
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1659

Referenced by MiProtectVirtualMemory().

◆ MiUnlockVirtualMemory()

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

Definition at line 3694 of file virtual.c.

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