ReactOS  0.4.15-dev-1623-g66cf1d2
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 3192 of file virtual.c.

3195 {
3196  // HACK until we have proper WSLIST support
3197  PMMWSLE Wsle = &Pfn1->Wsle;
3198 
3199  if ((LockType & MAP_PROCESS) && (Wsle->u1.e1.LockedInWs))
3200  return TRUE;
3201  if ((LockType & MAP_SYSTEM) && (Wsle->u1.e1.LockedInMemory))
3202  return TRUE;
3203 
3204  return FALSE;
3205 }
#define TRUE
Definition: types.h:120
MMWSLENTRY e1
Definition: mmtypes.h:853
MMWSLE Wsle
Definition: mm.h:370
union _MMWSLE::@2589 u1
#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:839
ULONG_PTR LockedInWs
Definition: mmtypes.h:838
#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 3209 of file virtual.c.

3212 {
3213  // HACK until we have proper WSLIST support
3214  PMMWSLE Wsle = &Pfn1->Wsle;
3215 
3216  if (!Wsle->u1.e1.LockedInWs &&
3217  !Wsle->u1.e1.LockedInMemory)
3218  {
3220  }
3221 
3222  if (LockType & MAP_PROCESS)
3223  Wsle->u1.e1.LockedInWs = 1;
3224  if (LockType & MAP_SYSTEM)
3225  Wsle->u1.e1.LockedInMemory = 1;
3226 }
MMWSLENTRY e1
Definition: mmtypes.h:853
MMWSLE Wsle
Definition: mm.h:370
union _MMWSLE::@2589 u1
_In_ WDFREQUEST _In_ MEDIA_LOCK_TYPE LockType
Definition: cdrom.h:1334
#define MAP_PROCESS
Definition: mmtypes.h:67
ULONG_PTR LockedInMemory
Definition: mmtypes.h:839
FORCEINLINE VOID MiReferenceProbedPageAndBumpLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1542
ULONG_PTR LockedInWs
Definition: mmtypes.h:838
#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 3230 of file virtual.c.

3233 {
3234  // HACK until we have proper WSLIST support
3235  PMMWSLE Wsle = &Pfn1->Wsle;
3236 
3237  if (LockType & MAP_PROCESS)
3238  Wsle->u1.e1.LockedInWs = 0;
3239  if (LockType & MAP_SYSTEM)
3240  Wsle->u1.e1.LockedInMemory = 0;
3241 
3242  if (!Wsle->u1.e1.LockedInWs &&
3243  !Wsle->u1.e1.LockedInMemory)
3244  {
3246  }
3247 }
FORCEINLINE VOID MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1470
MMWSLENTRY e1
Definition: mmtypes.h:853
MMWSLE Wsle
Definition: mm.h:370
union _MMWSLE::@2589 u1
_In_ WDFREQUEST _In_ MEDIA_LOCK_TYPE LockType
Definition: cdrom.h:1334
#define MAP_PROCESS
Definition: mmtypes.h:67
ULONG_PTR LockedInMemory
Definition: mmtypes.h:839
ULONG_PTR LockedInWs
Definition: mmtypes.h:838
#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  ULONG CommittedPages;
50 
51  /* Compute starting and ending PTE and PDE addresses */
52  PointerPde = MiAddressToPde(StartingAddress);
53  PointerPte = MiAddressToPte(StartingAddress);
54  LastPte = MiAddressToPte(EndingAddress);
55 
56  /* Handle commited pages first */
57  if (Vad->u.VadFlags.MemCommit == 1)
58  {
59  /* This is a committed VAD, so Assume the whole range is committed */
60  CommittedPages = (ULONG)BYTES_TO_PAGES(EndingAddress - StartingAddress);
61 
62  /* Is the PDE demand-zero? */
63  PointerPde = MiPteToPde(PointerPte);
64  if (PointerPde->u.Long != 0)
65  {
66  /* It is not. Is it valid? */
67  if (PointerPde->u.Hard.Valid == 0)
68  {
69  /* Fault it in */
70  PointerPte = MiPteToAddress(PointerPde);
71  MiMakeSystemAddressValid(PointerPte, Process);
72  }
73  }
74  else
75  {
76  /* It is, skip it and move to the next PDE, unless we're done */
77  PointerPde++;
78  PointerPte = MiPteToAddress(PointerPde);
79  if (PointerPte > LastPte) return CommittedPages;
80  }
81 
82  /* Now loop all the PTEs in the range */
83  while (PointerPte <= LastPte)
84  {
85  /* Have we crossed a PDE boundary? */
86  if (MiIsPteOnPdeBoundary(PointerPte))
87  {
88  /* Is this PDE demand zero? */
89  PointerPde = MiPteToPde(PointerPte);
90  if (PointerPde->u.Long != 0)
91  {
92  /* It isn't -- is it valid? */
93  if (PointerPde->u.Hard.Valid == 0)
94  {
95  /* Nope, fault it in */
96  PointerPte = MiPteToAddress(PointerPde);
97  MiMakeSystemAddressValid(PointerPte, Process);
98  }
99  }
100  else
101  {
102  /* It is, skip it and move to the next PDE */
103  PointerPde++;
104  PointerPte = MiPteToAddress(PointerPde);
105  continue;
106  }
107  }
108 
109  /* Is this PTE demand zero? */
110  if (PointerPte->u.Long != 0)
111  {
112  /* It isn't -- is it a decommited, invalid, or faulted PTE? */
113  if ((PointerPte->u.Soft.Protection == MM_DECOMMIT) &&
114  (PointerPte->u.Hard.Valid == 0) &&
115  ((PointerPte->u.Soft.Prototype == 0) ||
116  (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)))
117  {
118  /* It is, so remove it from the count of commited pages */
119  CommittedPages--;
120  }
121  }
122 
123  /* Move to the next PTE */
124  PointerPte++;
125  }
126 
127  /* Return how many committed pages there still are */
128  return CommittedPages;
129  }
130 
131  /* This is a non-commited VAD, so assume none of it is committed */
132  CommittedPages = 0;
133 
134  /* Is the PDE demand-zero? */
135  PointerPde = MiPteToPde(PointerPte);
136  if (PointerPde->u.Long != 0)
137  {
138  /* It isn't -- is it invalid? */
139  if (PointerPde->u.Hard.Valid == 0)
140  {
141  /* It is, so page it in */
142  PointerPte = MiPteToAddress(PointerPde);
143  MiMakeSystemAddressValid(PointerPte, Process);
144  }
145  }
146  else
147  {
148  /* It is, so skip it and move to the next PDE */
149  PointerPde++;
150  PointerPte = MiPteToAddress(PointerPde);
151  if (PointerPte > LastPte) return CommittedPages;
152  }
153 
154  /* Loop all the PTEs in this PDE */
155  while (PointerPte <= LastPte)
156  {
157  /* Have we crossed a PDE boundary? */
158  if (MiIsPteOnPdeBoundary(PointerPte))
159  {
160  /* Is this new PDE demand-zero? */
161  PointerPde = MiPteToPde(PointerPte);
162  if (PointerPde->u.Long != 0)
163  {
164  /* It isn't. Is it valid? */
165  if (PointerPde->u.Hard.Valid == 0)
166  {
167  /* It isn't, so make it valid */
168  PointerPte = MiPteToAddress(PointerPde);
169  MiMakeSystemAddressValid(PointerPte, Process);
170  }
171  }
172  else
173  {
174  /* It is, so skip it and move to the next one */
175  PointerPde++;
176  PointerPte = MiPteToAddress(PointerPde);
177  continue;
178  }
179  }
180 
181  /* Is this PTE demand-zero? */
182  if (PointerPte->u.Long != 0)
183  {
184  /* Nope. Is it a valid, non-decommited, non-paged out PTE? */
185  if ((PointerPte->u.Soft.Protection != MM_DECOMMIT) ||
186  (PointerPte->u.Hard.Valid == 1) ||
187  ((PointerPte->u.Soft.Prototype == 1) &&
188  (PointerPte->u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED)))
189  {
190  /* It is! So we'll treat this as a committed page */
191  CommittedPages++;
192  }
193  }
194 
195  /* Move to the next PTE */
196  PointerPte++;
197  }
198 
199  /* Return how many committed pages we found in this VAD */
200  return CommittedPages;
201 }
ULONG NTAPI MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
Definition: virtual.c:205
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define MM_DECOMMIT
Definition: miarm.h:60
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:247
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG64 Protection
Definition: mmtypes.h:88
static const OBJECT_ATTRIBUTES const LARGE_INTEGER ULONG
Definition: virtual.c:34
ULONG64 Valid
Definition: mmtypes.h:150
#define BYTES_TO_PAGES(Size)
ULONG64 PageFileHigh
Definition: mmtypes.h:93
ULONG64 Prototype
Definition: mmtypes.h:89
union _MMPTE::@2319 u
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MiPteToPde(_Pte)
Definition: mm.h:236
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:240
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
_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
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201

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

3256 {
3257  PMMVAD Vad;
3258  PVOID CurrentVa;
3259 
3260  /* Get the base address and align the start address */
3261  *EndAddress = (PUCHAR)*BaseAddress + *RegionSize;
3262  *EndAddress = ALIGN_UP_POINTER_BY(*EndAddress, PAGE_SIZE);
3264 
3265  /* First loop and check all VADs */
3266  CurrentVa = *BaseAddress;
3267  while (CurrentVa < *EndAddress)
3268  {
3269  /* Get VAD */
3270  Vad = MiLocateAddress(CurrentVa);
3271  if (Vad == NULL)
3272  {
3274  return STATUS_ACCESS_VIOLATION;
3275  }
3276 
3277  /* Check VAD type */
3278  if ((Vad->u.VadFlags.VadType != VadNone) &&
3279  (Vad->u.VadFlags.VadType != VadImageMap) &&
3280  (Vad->u.VadFlags.VadType != VadWriteWatch))
3281  {
3282  *EndAddress = CurrentVa;
3283  *RegionSize = (PUCHAR)*EndAddress - (PUCHAR)*BaseAddress;
3285  }
3286 
3287  CurrentVa = (PVOID)((Vad->EndingVpn + 1) << PAGE_SHIFT);
3288  }
3289 
3290  *RegionSize = (PUCHAR)*EndAddress - (PUCHAR)*BaseAddress;
3291  return STATUS_SUCCESS;
3292 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
unsigned char * PUCHAR
Definition: retypes.h:3
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:744
ULONG_PTR EndingVpn
Definition: mmtypes.h:740
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:48
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define ALIGN_UP_POINTER_BY(ptr, align)
Definition: umtypes.h:85
static PVOID
Definition: virtual.c:33
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
#define NULL
Definition: types.h:112
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ALIGN_DOWN_POINTER_BY(ptr, align)
Definition: umtypes.h:82
#define STATUS_INCOMPATIBLE_FILE_MAP
Definition: ntstatus.h:313
ULONG_PTR VadType
Definition: mmtypes.h:704
union _MMVAD::@2579 u

Referenced by MiLockVirtualMemory(), and MiUnlockVirtualMemory().

◆ MiDecommitPages()

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

Definition at line 2542 of file virtual.c.

2546 {
2547  PMMPTE PointerPte, CommitPte = NULL;
2548  PMMPDE PointerPde;
2549  ULONG CommitReduction = 0;
2550  PMMPTE ValidPteList[256];
2551  ULONG PteCount = 0;
2552  PMMPFN Pfn1;
2553  MMPTE PteContents;
2554  PETHREAD CurrentThread = PsGetCurrentThread();
2555 
2556  //
2557  // Get the PTE and PTE for the address, and lock the working set
2558  // If this was a VAD for a MEM_COMMIT allocation, also figure out where the
2559  // commited range ends so that we can do the right accounting.
2560  //
2561  PointerPde = MiAddressToPde(StartingAddress);
2562  PointerPte = MiAddressToPte(StartingAddress);
2563  if (Vad->u.VadFlags.MemCommit) CommitPte = MiAddressToPte(Vad->EndingVpn << PAGE_SHIFT);
2564  MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
2565 
2566  //
2567  // Make the PDE valid, and now loop through each page's worth of data
2568  //
2570  while (PointerPte <= EndingPte)
2571  {
2572  //
2573  // Check if we've crossed a PDE boundary
2574  //
2575  if (MiIsPteOnPdeBoundary(PointerPte))
2576  {
2577  //
2578  // Get the new PDE and flush the valid PTEs we had built up until
2579  // now. This helps reduce the amount of TLB flushing we have to do.
2580  // Note that Windows does a much better job using timestamps and
2581  // such, and does not flush the entire TLB all the time, but right
2582  // now we have bigger problems to worry about than TLB flushing.
2583  //
2584  PointerPde = MiAddressToPde(StartingAddress);
2585  if (PteCount)
2586  {
2587  MiProcessValidPteList(ValidPteList, PteCount);
2588  PteCount = 0;
2589  }
2590 
2591  //
2592  // Make this PDE valid
2593  //
2595  }
2596 
2597  //
2598  // Read this PTE. It might be active or still demand-zero.
2599  //
2600  PteContents = *PointerPte;
2601  if (PteContents.u.Long)
2602  {
2603  //
2604  // The PTE is active. It might be valid and in a working set, or
2605  // it might be a prototype PTE or paged out or even in transition.
2606  //
2607  if (PointerPte->u.Long == MmDecommittedPte.u.Long)
2608  {
2609  //
2610  // It's already decommited, so there's nothing for us to do here
2611  //
2612  CommitReduction++;
2613  }
2614  else
2615  {
2616  //
2617  // Remove it from the counters, and check if it was valid or not
2618  //
2619  //Process->NumberOfPrivatePages--;
2620  if (PteContents.u.Hard.Valid)
2621  {
2622  //
2623  // It's valid. At this point make sure that it is not a ROS
2624  // PFN. Also, we don't support ProtoPTEs in this code path.
2625  //
2626  Pfn1 = MiGetPfnEntry(PteContents.u.Hard.PageFrameNumber);
2627  ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
2628  ASSERT(Pfn1->u3.e1.PrototypePte == FALSE);
2629 
2630  //
2631  // Flush any pending PTEs that we had not yet flushed, if our
2632  // list has gotten too big, then add this PTE to the flush list.
2633  //
2634  if (PteCount == 256)
2635  {
2636  MiProcessValidPteList(ValidPteList, PteCount);
2637  PteCount = 0;
2638  }
2639  ValidPteList[PteCount++] = PointerPte;
2640  }
2641  else
2642  {
2643  //
2644  // We do not support any of these other scenarios at the moment
2645  //
2646  ASSERT(PteContents.u.Soft.Prototype == 0);
2647  ASSERT(PteContents.u.Soft.Transition == 0);
2648  ASSERT(PteContents.u.Soft.PageFileHigh == 0);
2649 
2650  //
2651  // So the only other possibility is that it is still a demand
2652  // zero PTE, in which case we undo the accounting we did
2653  // earlier and simply make the page decommitted.
2654  //
2655  //Process->NumberOfPrivatePages++;
2657  }
2658  }
2659  }
2660  else
2661  {
2662  //
2663  // This used to be a zero PTE and it no longer is, so we must add a
2664  // reference to the pagetable.
2665  //
2666  MiIncrementPageTableReferences(StartingAddress);
2667 
2668  //
2669  // Next, we account for decommitted PTEs and make the PTE as such
2670  //
2671  if (PointerPte > CommitPte) CommitReduction++;
2673  }
2674 
2675  //
2676  // Move to the next PTE and the next address
2677  //
2678  PointerPte++;
2679  StartingAddress = (PVOID)((ULONG_PTR)StartingAddress + PAGE_SIZE);
2680  }
2681 
2682  //
2683  // Flush any dangling PTEs from the loop in the last page table, and then
2684  // release the working set and return the commit reduction accounting.
2685  //
2686  if (PteCount) MiProcessValidPteList(ValidPteList, PteCount);
2687  MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
2688  return CommitReduction;
2689 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1215
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
VOID NTAPI MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
Definition: virtual.c:2411
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:301
MMPFNENTRY e1
Definition: mm.h:335
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
VOID NTAPI MiProcessValidPteList(IN PMMPTE *ValidPteList, IN ULONG Count)
Definition: virtual.c:2490
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1145
#define ASSERT(a)
Definition: mode.c:45
ULONG64 Valid
Definition: mmtypes.h:150
union _MMPFN::@1793 u3
ULONG64 PageFileHigh
Definition: mmtypes.h:93
#define MM_NOIRQL
Definition: miarm.h:232
Definition: mm.h:311
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:939
union _MMPTE::@2319 u
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:975
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:240
ULONG64 Transition
Definition: mmtypes.h:90
#define MI_IS_ROS_PFN(x)
Definition: miarm.h:1079
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
FORCEINLINE VOID MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:1673
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 391 of file virtual.c.

395 {
396  PMMPFN Pfn1;
397  MMPTE TempPte;
398  PFN_NUMBER PageFrameIndex;
399  PMMPDE PointerPde;
400 
401  /* PFN lock must be held */
403 
404  /* Capture the PTE */
405  TempPte = *PointerPte;
406 
407  /* See if the PTE is valid */
408  if (TempPte.u.Hard.Valid == 0)
409  {
410  /* Prototype and paged out PTEs not supported yet */
411  ASSERT(TempPte.u.Soft.Prototype == 0);
412  ASSERT((TempPte.u.Soft.PageFileHigh == 0) || (TempPte.u.Soft.Transition == 1));
413 
414  if (TempPte.u.Soft.Transition)
415  {
416  /* Get the PFN entry */
417  PageFrameIndex = PFN_FROM_PTE(&TempPte);
418  Pfn1 = MiGetPfnEntry(PageFrameIndex);
419 
420  DPRINT("Pte %p is transitional!\n", PointerPte);
421 
422  /* Make sure the saved PTE address is valid */
423  ASSERT((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) == PointerPte);
424 
425  /* Destroy the PTE */
426  MI_ERASE_PTE(PointerPte);
427 
428  /* Drop the reference on the page table. */
430 
431  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
432 
433  /* Make the page free. For prototypes, it will be made free when deleting the section object */
434  if (Pfn1->u3.e2.ReferenceCount == 0)
435  {
436  /* And it should be in standby or modified list */
438 
439  /* Unlink it and set its reference count to one */
440  MiUnlinkPageFromList(Pfn1);
441  Pfn1->u3.e2.ReferenceCount++;
442 
443  /* This will put it back in free list and clean properly up */
444  MI_SET_PFN_DELETED(Pfn1);
445  MiDecrementReferenceCount(Pfn1, PageFrameIndex);
446  }
447  return;
448  }
449  }
450 
451  /* Get the PFN entry */
452  PageFrameIndex = PFN_FROM_PTE(&TempPte);
453  Pfn1 = MiGetPfnEntry(PageFrameIndex);
454 
455  /* Check if this is a valid, prototype PTE */
456  if (Pfn1->u3.e1.PrototypePte == 1)
457  {
458  /* Get the PDE and make sure it's faulted in */
459  PointerPde = MiPteToPde(PointerPte);
460  if (PointerPde->u.Hard.Valid == 0)
461  {
462 #if (_MI_PAGING_LEVELS == 2)
463  /* Could be paged pool access from a new process -- synchronize the page directories */
465  {
466 #endif
467  /* The PDE must be valid at this point */
468  KeBugCheckEx(MEMORY_MANAGEMENT,
469  0x61940,
470  (ULONG_PTR)PointerPte,
471  PointerPte->u.Long,
473  }
474 #if (_MI_PAGING_LEVELS == 2)
475  }
476 #endif
477  /* Drop the share count on the page table */
478  PointerPde = MiPteToPde(PointerPte);
480  PointerPde->u.Hard.PageFrameNumber);
481 
482  /* Drop the share count */
483  MiDecrementShareCount(Pfn1, PageFrameIndex);
484 
485  /* Either a fork, or this is the shared user data page */
486  if ((PointerPte <= MiHighestUserPte) && (PrototypePte != Pfn1->PteAddress))
487  {
488  /* If it's not the shared user page, then crash, since there's no fork() yet */
491  {
492  /* Must be some sort of memory corruption */
493  KeBugCheckEx(MEMORY_MANAGEMENT,
494  0x400,
495  (ULONG_PTR)PointerPte,
497  (ULONG_PTR)Pfn1->PteAddress);
498  }
499  }
500 
501  /* Erase it */
502  MI_ERASE_PTE(PointerPte);
503  }
504  else
505  {
506  /* Make sure the saved PTE address is valid */
507  if ((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) != PointerPte)
508  {
509  /* The PFN entry is illegal, or invalid */
510  KeBugCheckEx(MEMORY_MANAGEMENT,
511  0x401,
512  (ULONG_PTR)PointerPte,
513  PointerPte->u.Long,
514  (ULONG_PTR)Pfn1->PteAddress);
515  }
516 
517  /* Erase the PTE */
518  MI_ERASE_PTE(PointerPte);
519 
520  /* There should only be 1 shared reference count */
521  ASSERT(Pfn1->u2.ShareCount == 1);
522 
523  /* Drop the reference on the page table. */
525 
526  /* Mark the PFN for deletion and dereference what should be the last ref */
527  MI_SET_PFN_DELETED(Pfn1);
528  MiDecrementShareCount(Pfn1, PageFrameIndex);
529 
530  /* We should eventually do this */
531  //CurrentProcess->NumberOfPrivatePages--;
532  }
533 
534  /* Flush the TLB */
536 }
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:989
MMPTE PrototypePte
Definition: init.c:40
union _MMPFN::@1792 u2
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:935
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:264
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:475
USHORT PageLocation
Definition: mm.h:303
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:301
MMPFNENTRY e1
Definition: mm.h:335
ULONG PFN_NUMBER
Definition: ke.h:9
union _MMPFN::@1796 u4
ULONG_PTR ShareCount
Definition: mm.h:328
#define USER_SHARED_DATA
Definition: pstypes.h:51
void DPRINT(...)
Definition: polytest.cpp:61
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
#define ASSERT(a)
Definition: mode.c:45
#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:1222
union _MMPFN::@1793 u3
Definition: mm.h:311
struct _MMPFN::@1793::@1799 e2
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:939
union _MMPTE::@2319 u
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:190
#define MiPteToPde(_Pte)
Definition: mm.h:236
ULONG_PTR PteFrame
Definition: mm.h:356
PMMPTE PteAddress
Definition: mm.h:324
PVOID MmHighestUserAddress
Definition: rtlcompat.c:29
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
PMMPTE MiHighestUserPte
Definition: mminit.c:233
#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:325

Referenced by MiBalancerThread(), MiDeleteVirtualAddresses(), MiResolveProtoPteFault(), MiUnmapLockedPagesInUserSpace(), MmArmAccessFault(), MmDeleteProcessAddressSpace(), and MmFreeMemoryArea().

◆ MiDeleteSystemPageableVm()

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

Definition at line 297 of file virtual.c.

301 {
302  PFN_COUNT ActualPages = 0;
303  PETHREAD CurrentThread = PsGetCurrentThread();
304  PMMPFN Pfn1, Pfn2;
305  PFN_NUMBER PageFrameIndex, PageTableIndex;
306  KIRQL OldIrql;
308 
309  /* Lock the system working set */
310  MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
311 
312  /* Loop all pages */
313  while (PageCount)
314  {
315  /* Make sure there's some data about the page */
316  if (PointerPte->u.Long)
317  {
318  /* As always, only handle current ARM3 scenarios */
319  ASSERT(PointerPte->u.Soft.Prototype == 0);
320  ASSERT(PointerPte->u.Soft.Transition == 0);
321 
322  /* Normally this is one possibility -- freeing a valid page */
323  if (PointerPte->u.Hard.Valid)
324  {
325  /* Get the page PFN */
326  PageFrameIndex = PFN_FROM_PTE(PointerPte);
327  Pfn1 = MiGetPfnEntry(PageFrameIndex);
328 
329  /* Should not have any working set data yet */
330  ASSERT(Pfn1->u1.WsIndex == 0);
331 
332  /* Actual valid, legitimate, pages */
333  if (ValidPages) (*ValidPages)++;
334 
335  /* Get the page table entry */
336  PageTableIndex = Pfn1->u4.PteFrame;
337  Pfn2 = MiGetPfnEntry(PageTableIndex);
338 
339  /* Lock the PFN database */
341 
342  /* Delete it the page */
343  MI_SET_PFN_DELETED(Pfn1);
344  MiDecrementShareCount(Pfn1, PageFrameIndex);
345 
346  /* Decrement the page table too */
347  MiDecrementShareCount(Pfn2, PageTableIndex);
348 
349  /* Release the PFN database */
351 
352  /* Destroy the PTE */
353  MI_ERASE_PTE(PointerPte);
354  }
355  else
356  {
357  /*
358  * The only other ARM3 possibility is a demand zero page, which would
359  * mean freeing some of the paged pool pages that haven't even been
360  * touched yet, as part of a larger allocation.
361  *
362  * Right now, we shouldn't expect any page file information in the PTE
363  */
364  ASSERT(PointerPte->u.Soft.PageFileHigh == 0);
365 
366  /* Destroy the PTE */
367  MI_ERASE_PTE(PointerPte);
368  }
369 
370  /* Actual legitimate pages */
371  ActualPages++;
372  }
373 
374  /* Keep going */
375  PointerPte++;
376  PageCount--;
377  }
378 
379  /* Release the working set */
380  MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
381 
382  /* Flush the entire TLB */
384 
385  /* Done */
386  return ActualPages;
387 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:989
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ULONG PFN_COUNT
Definition: mmtypes.h:102
#define TRUE
Definition: types.h:120
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:900
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:907
union _MMPFN::@1791 u1
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG PFN_NUMBER
Definition: ke.h:9
union _MMPFN::@1796 u4
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:1285
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:416
#define ASSERT(a)
Definition: mode.c:45
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
Definition: mm.h:311
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:939
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:190
ULONG_PTR PteFrame
Definition: mm.h:356
ULONG WsIndex
Definition: mm.h:316
FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1241
#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 540 of file virtual.c.

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

813 {
814  PFN_NUMBER MdlBuffer[(sizeof(MDL) / sizeof(PFN_NUMBER)) + MI_MAPPED_COPY_PAGES + 1];
815  PMDL Mdl = (PMDL)MdlBuffer;
816  SIZE_T TotalSize, CurrentSize, RemainingSize;
817  volatile BOOLEAN FailedInProbe = FALSE;
818  volatile BOOLEAN PagesLocked = FALSE;
819  PVOID CurrentAddress = SourceAddress, CurrentTargetAddress = TargetAddress;
820  volatile PVOID MdlAddress = NULL;
822  BOOLEAN HaveBadAddress;
823  ULONG_PTR BadAddress;
825  PAGED_CODE();
826 
827  //
828  // Calculate the maximum amount of data to move
829  //
830  TotalSize = MI_MAPPED_COPY_PAGES * PAGE_SIZE;
831  if (BufferSize <= TotalSize) TotalSize = BufferSize;
832  CurrentSize = TotalSize;
833  RemainingSize = BufferSize;
834 
835  //
836  // Loop as long as there is still data
837  //
838  while (RemainingSize > 0)
839  {
840  //
841  // Check if this transfer will finish everything off
842  //
843  if (RemainingSize < CurrentSize) CurrentSize = RemainingSize;
844 
845  //
846  // Attach to the source address space
847  //
848  KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
849 
850  //
851  // Check state for this pass
852  //
853  ASSERT(MdlAddress == NULL);
854  ASSERT(PagesLocked == FALSE);
855  ASSERT(FailedInProbe == FALSE);
856 
857  //
858  // Protect user-mode copy
859  //
860  _SEH2_TRY
861  {
862  //
863  // If this is our first time, probe the buffer
864  //
865  if ((CurrentAddress == SourceAddress) && (PreviousMode != KernelMode))
866  {
867  //
868  // Catch a failure here
869  //
870  FailedInProbe = TRUE;
871 
872  //
873  // Do the probe
874  //
876 
877  //
878  // Passed
879  //
880  FailedInProbe = FALSE;
881  }
882 
883  //
884  // Initialize and probe and lock the MDL
885  //
886  MmInitializeMdl(Mdl, CurrentAddress, CurrentSize);
888  PagesLocked = TRUE;
889  }
891  {
893  }
894  _SEH2_END
895 
896  /* Detach from source process */
898 
899  if (Status != STATUS_SUCCESS)
900  {
901  goto Exit;
902  }
903 
904  //
905  // Now map the pages
906  //
907  MdlAddress = MmMapLockedPagesSpecifyCache(Mdl,
908  KernelMode,
909  MmCached,
910  NULL,
911  FALSE,
913  if (!MdlAddress)
914  {
916  goto Exit;
917  }
918 
919  //
920  // Grab to the target process
921  //
922  KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
923 
924  _SEH2_TRY
925  {
926  //
927  // Check if this is our first time through
928  //
929  if ((CurrentTargetAddress == TargetAddress) && (PreviousMode != KernelMode))
930  {
931  //
932  // Catch a failure here
933  //
934  FailedInProbe = TRUE;
935 
936  //
937  // Do the probe
938  //
940 
941  //
942  // Passed
943  //
944  FailedInProbe = FALSE;
945  }
946 
947  //
948  // Now do the actual move
949  //
950  RtlCopyMemory(CurrentTargetAddress, MdlAddress, CurrentSize);
951  }
953  &HaveBadAddress,
954  &BadAddress))
955  {
956  *ReturnSize = BufferSize - RemainingSize;
957  //
958  // Check if we failed during the probe
959  //
960  if (FailedInProbe)
961  {
962  //
963  // Exit
964  //
966  }
967  else
968  {
969  //
970  // Othewise we failed during the move.
971  // Check if we know exactly where we stopped copying
972  //
973  if (HaveBadAddress)
974  {
975  //
976  // Return the exact number of bytes copied
977  //
978  *ReturnSize = BadAddress - (ULONG_PTR)SourceAddress;
979  }
980  //
981  // Return partial copy
982  //
984  }
985  }
986  _SEH2_END;
987 
988  /* Detach from target process */
990 
991  //
992  // Check for SEH status
993  //
994  if (Status != STATUS_SUCCESS)
995  {
996  goto Exit;
997  }
998 
999  //
1000  // Unmap and unlock
1001  //
1002  MmUnmapLockedPages(MdlAddress, Mdl);
1003  MdlAddress = NULL;
1004  MmUnlockPages(Mdl);
1005  PagesLocked = FALSE;
1006 
1007  //
1008  // Update location and size
1009  //
1010  RemainingSize -= CurrentSize;
1011  CurrentAddress = (PVOID)((ULONG_PTR)CurrentAddress + CurrentSize);
1012  CurrentTargetAddress = (PVOID)((ULONG_PTR)CurrentTargetAddress + CurrentSize);
1013  }
1014 
1015 Exit:
1016  if (MdlAddress != NULL)
1017  MmUnmapLockedPages(MdlAddress, Mdl);
1018  if (PagesLocked)
1019  MmUnlockPages(Mdl);
1020 
1021  //
1022  // All bytes read
1023  //
1024  if (Status == STATUS_SUCCESS)
1025  *ReturnSize = BufferSize;
1026  return Status;
1027 }
KAPC_STATE
Definition: ketypes.h:1280
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define MmInitializeMdl(_MemoryDescriptorList, _BaseVa, _Length)
#define TRUE
Definition: types.h:120
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1439
#define MI_MAPPED_COPY_PAGES
Definition: virtual.c:18
PVOID PMDL
Definition: usb.h:39
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
PVOID NTAPI MmMapLockedPagesSpecifyCache(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN MEMORY_CACHING_TYPE CacheType, IN PVOID BaseAddress, IN ULONG BugCheckOnFailure, IN ULONG Priority)
Definition: mdlsup.c:664
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:701
VOID NTAPI MmUnmapLockedPages(IN PVOID BaseAddress, IN PMDL Mdl)
Definition: mdlsup.c:841
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER _Outptr_ PVOID * TargetAddress
Definition: iotypes.h:1035
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define ASSERT(a)
Definition: mode.c:45
static void Exit(void)
Definition: sock.c:1331
MDL
Definition: mmtypes.h:117
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
static PVOID
Definition: virtual.c:33
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_SEH2_END
Definition: create.c:4400
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:935
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:753
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1488
#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:6
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
_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:761

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

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

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

1984 {
1985  MMPTE TempPte, PreviousPte;
1986  KIRQL OldIrql;
1987  BOOLEAN RebuildPte = FALSE;
1988 
1989  //
1990  // User for sanity checking later on
1991  //
1992  PreviousPte = *PointerPte;
1993 
1994  //
1995  // Build the PTE and acquire the PFN lock
1996  //
1998  PointerPte,
1999  ProtectionMask,
2000  PreviousPte.u.Hard.PageFrameNumber);
2002 
2003  //
2004  // We don't support I/O mappings in this path yet
2005  //
2006  ASSERT(Pfn1 != NULL);
2007  ASSERT(Pfn1->u3.e1.CacheAttribute != MiWriteCombined);
2008 
2009  //
2010  // Make sure new protection mask doesn't get in conflict and fix it if it does
2011  //
2012  if (Pfn1->u3.e1.CacheAttribute == MiCached)
2013  {
2014  //
2015  // This is a cached PFN
2016  //
2017  if (ProtectionMask & (MM_NOCACHE | MM_NOACCESS))
2018  {
2019  RebuildPte = TRUE;
2020  ProtectionMask &= ~(MM_NOCACHE | MM_NOACCESS);
2021  }
2022  }
2023  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
2024  {
2025  //
2026  // This is a non-cached PFN
2027  //
2028  if ((ProtectionMask & (MM_NOCACHE | MM_NOACCESS)) != MM_NOCACHE)
2029  {
2030  RebuildPte = TRUE;
2031  ProtectionMask &= ~MM_NOACCESS;
2032  ProtectionMask |= MM_NOCACHE;
2033  }
2034  }
2035 
2036  if (RebuildPte)
2037  {
2039  PointerPte,
2040  ProtectionMask,
2041  PreviousPte.u.Hard.PageFrameNumber);
2042  }
2043 
2044  //
2045  // Write the new PTE, making sure we are only changing the bits
2046  //
2047  MI_UPDATE_VALID_PTE(PointerPte, TempPte);
2048 
2049  //
2050  // Flush the TLB
2051  //
2052  ASSERT(PreviousPte.u.Hard.Valid == 1);
2053  KeFlushCurrentTb();
2054  ASSERT(PreviousPte.u.Hard.Valid == 1);
2055 
2056  //
2057  // Windows updates the relevant PFN1 information, we currently don't.
2058  //
2059  if (UpdateDirty && PreviousPte.u.Hard.Dirty)
2060  {
2061  if (!Pfn1->u3.e1.Modified)
2062  {
2063  DPRINT1("FIXME: Mark PFN as dirty\n");
2064  }
2065  }
2066 
2067  //
2068  // Not supported in ARM3
2069  //
2070  ASSERT(FoundVad->u.VadFlags.VadType != VadWriteWatch);
2071 
2072  //
2073  // Release the PFN lock, we are done
2074  //
2076 }
#define TRUE
Definition: types.h:120
#define MM_NOACCESS
Definition: miarm.h:61
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:900
#define MM_NOCACHE
Definition: miarm.h:52
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:907
ULONG64 Dirty
Definition: mmtypes.h:164
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
#define ASSERT(a)
Definition: mode.c:45
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:790
union _MMPTE::@2319 u
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:813
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:960
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:325

Referenced by MiProtectVirtualMemory(), and MiSetProtectionOnSection().

◆ MiGetExceptionInfo()

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

Definition at line 761 of file virtual.c.

764 {
765  PEXCEPTION_RECORD ExceptionRecord;
766  PAGED_CODE();
767 
768  //
769  // Assume default
770  //
771  *HaveBadAddress = FALSE;
772 
773  //
774  // Get the exception record
775  //
776  ExceptionRecord = ExceptionInfo->ExceptionRecord;
777 
778  //
779  // Look at the exception code
780  //
781  if ((ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) ||
782  (ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) ||
783  (ExceptionRecord->ExceptionCode == STATUS_IN_PAGE_ERROR))
784  {
785  //
786  // We can tell the address if we have more than one parameter
787  //
788  if (ExceptionRecord->NumberParameters > 1)
789  {
790  //
791  // Return the address
792  //
793  *HaveBadAddress = TRUE;
794  *BadAddress = ExceptionRecord->ExceptionInformation[1];
795  }
796  }
797 
798  //
799  // Continue executing the next handler
800  //
802 }
#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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
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 1369 of file virtual.c.

1370 {
1371  MMPTE TempPte;
1372  PMMPFN Pfn;
1374  PETHREAD CurrentThread;
1375  BOOLEAN WsSafe, WsShared;
1376  ULONG Protect;
1377  KIRQL OldIrql;
1378  PAGED_CODE();
1379 
1380  /* Copy this PTE's contents */
1381  TempPte = *PointerPte;
1382 
1383  /* Assure it's not totally zero */
1384  ASSERT(TempPte.u.Long);
1385 
1386  /* Check for a special prototype format */
1387  if ((TempPte.u.Soft.Valid == 0) &&
1388  (TempPte.u.Soft.Prototype == 1))
1389  {
1390  /* Check if the prototype PTE is not yet pointing to a PTE */
1391  if (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
1392  {
1393  /* The prototype PTE contains the protection */
1394  return MmProtectToValue[TempPte.u.Soft.Protection];
1395  }
1396 
1397  /* Get a pointer to the underlying shared PTE */
1398  PointerPte = MiProtoPteToPte(&TempPte);
1399 
1400  /* Since the PTE we want to read can be paged out at any time, we need
1401  to release the working set lock first, so that it can be paged in */
1402  CurrentThread = PsGetCurrentThread();
1405  CurrentThread,
1406  &WsSafe,
1407  &WsShared);
1408 
1409  /* Now read the PTE value */
1410  TempPte = *PointerPte;
1411 
1412  /* Check if that one is invalid */
1413  if (!TempPte.u.Hard.Valid)
1414  {
1415  /* We get the protection directly from this PTE */
1416  Protect = MmProtectToValue[TempPte.u.Soft.Protection];
1417  }
1418  else
1419  {
1420  /* The PTE is valid, so we might need to get the protection from
1421  the PFN. Lock the PFN database */
1423 
1424  /* Check if the PDE is still valid */
1425  if (MiAddressToPte(PointerPte)->u.Hard.Valid == 0)
1426  {
1427  /* It's not, make it valid */
1428  MiMakeSystemAddressValidPfn(PointerPte, OldIrql);
1429  }
1430 
1431  /* Now it's safe to read the PTE value again */
1432  TempPte = *PointerPte;
1433  ASSERT(TempPte.u.Long != 0);
1434 
1435  /* Check again if the PTE is invalid */
1436  if (!TempPte.u.Hard.Valid)
1437  {
1438  /* The PTE is not valid, so we can use it's protection field */
1439  Protect = MmProtectToValue[TempPte.u.Soft.Protection];
1440  }
1441  else
1442  {
1443  /* The PTE is valid, so we can find the protection in the
1444  OriginalPte field of the PFN */
1445  Pfn = MI_PFN_ELEMENT(TempPte.u.Hard.PageFrameNumber);
1447  }
1448 
1449  /* Release the PFN database */
1451  }
1452 
1453  /* Lock the working set again */
1455  CurrentThread,
1456  WsSafe,
1457  WsShared);
1458 
1459  return Protect;
1460  }
1461 
1462  /* In the easy case of transition or demand zero PTE just return its protection */
1463  if (!TempPte.u.Hard.Valid) return MmProtectToValue[TempPte.u.Soft.Protection];
1464 
1465  /* If we get here, the PTE is valid, so look up the page in PFN database */
1466  Pfn = MiGetPfnEntry(TempPte.u.Hard.PageFrameNumber);
1467  if (!Pfn->u3.e1.PrototypePte)
1468  {
1469  /* Return protection of the original pte */
1470  ASSERT(Pfn->u4.AweAllocation == 0);
1472  }
1473 
1474  /* This is software PTE */
1475  DPRINT("Prototype PTE: %lx %p\n", TempPte.u.Hard.PageFrameNumber, Pfn);
1476  DPRINT("VA: %p\n", MiPteToAddress(&TempPte));
1477  DPRINT("Mask: %lx\n", TempPte.u.Soft.Protection);
1478  DPRINT("Mask2: %lx\n", Pfn->OriginalPte.u.Soft.Protection);
1479  return MmProtectToValue[TempPte.u.Soft.Protection];
1480 }
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG _In_ ULONG Protect
Definition: zwfuncs.h:214
ULONG_PTR AweAllocation
Definition: mm.h:359
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:247
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:900
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:907
USHORT PrototypePte
Definition: mm.h:301
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:335
#define MiAddressToPte(x)
Definition: mmx86.c:19
union _MMPFN::@1796 u4
#define PsGetCurrentProcess
Definition: psfuncs.h:17
unsigned char BOOLEAN
#define MiProtoPteToPte(x)
Definition: mm.h:250
void DPRINT(...)
Definition: polytest.cpp:61
ULONG64 Protection
Definition: mmtypes.h:88
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:45
FORCEINLINE VOID MiUnlockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, OUT PBOOLEAN Safe, OUT PBOOLEAN Shared)
Definition: miarm.h:1323
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
union _MMPFN::@1793 u3
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1429
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
Definition: mm.h:311
const ULONG MmProtectToValue[32]
Definition: page.c:81
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:939
union _MMPTE::@2319 u
FORCEINLINE VOID MiLockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, IN BOOLEAN Safe, IN BOOLEAN Shared)
Definition: miarm.h:1356
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
MMPTE OriginalPte
Definition: mm.h:345
unsigned int ULONG
Definition: retypes.h:1
ULONG NTAPI MiMakeSystemAddressValidPfn(IN PVOID VirtualAddress, IN KIRQL OldIrql)
Definition: virtual.c:257
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
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 2016 of file virtual.c.

2020 {
2021  PMMPTE PointerPte, LastPte;
2022  PMMPDE PointerPde;
2023  BOOLEAN OnBoundary = TRUE;
2024  PAGED_CODE();
2025 
2026  /* Get the PDE and PTE addresses */
2027  PointerPde = MiAddressToPde(StartingAddress);
2028  PointerPte = MiAddressToPte(StartingAddress);
2029  LastPte = MiAddressToPte(EndingAddress);
2030 
2031  /* Loop all the PTEs */
2032  while (PointerPte <= LastPte)
2033  {
2034  /* Check if we've hit an new PDE boundary */
2035  if (OnBoundary)
2036  {
2037  /* Is this PDE demand zero? */
2038  PointerPde = MiPteToPde(PointerPte);
2039  if (PointerPde->u.Long != 0)
2040  {
2041  /* It isn't -- is it valid? */
2042  if (PointerPde->u.Hard.Valid == 0)
2043  {
2044  /* Nope, fault it in */
2045  MiMakeSystemAddressValid(PointerPte, Process);
2046  }
2047  }
2048  else
2049  {
2050  /* The PTE was already valid, so move to the next one */
2051  PointerPde++;
2052  PointerPte = MiPdeToPte(PointerPde);
2053 
2054  /* Is the entire VAD committed? If not, fail */
2055  if (!Vad->u.VadFlags.MemCommit) return FALSE;
2056 
2057  /* New loop iteration with our new, on-boundary PTE. */
2058  continue;
2059  }
2060  }
2061 
2062  /* Is the PTE demand zero? */
2063  if (PointerPte->u.Long == 0)
2064  {
2065  /* Is the entire VAD committed? If not, fail */
2066  if (!Vad->u.VadFlags.MemCommit) return FALSE;
2067  }
2068  else
2069  {
2070  /* It isn't -- is it a decommited, invalid, or faulted PTE? */
2071  if ((PointerPte->u.Soft.Protection == MM_DECOMMIT) &&
2072  (PointerPte->u.Hard.Valid == 0) &&
2073  ((PointerPte->u.Soft.Prototype == 0) ||
2074  (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)))
2075  {
2076  /* Then part of the range is decommitted, so fail */
2077  return FALSE;
2078  }
2079  }
2080 
2081  /* Move to the next PTE */
2082  PointerPte++;
2083  OnBoundary = MiIsPteOnPdeBoundary(PointerPte);
2084  }
2085 
2086  /* All PTEs seem valid, and no VAD checks failed, the range is okay */
2087  return TRUE;
2088 }
ULONG NTAPI MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
Definition: virtual.c:205
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define TRUE
Definition: types.h:120
#define MM_DECOMMIT
Definition: miarm.h:60
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:247
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
ULONG64 Protection
Definition: mmtypes.h:88
ULONG64 Valid
Definition: mmtypes.h:150
ULONG64 PageFileHigh
Definition: mmtypes.h:93
ULONG64 Prototype
Definition: mmtypes.h:89
union _MMPTE::@2319 u
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MiPteToPde(_Pte)
Definition: mm.h:236
#define MiPdeToPte(_Pde)
Definition: mm.h:235
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:240
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#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 3296 of file virtual.c.

3300 {
3303  PVOID CurrentVa, EndAddress;
3304  PMMPTE PointerPte, LastPte;
3305  PMMPDE PointerPde;
3306 #if (_MI_PAGING_LEVELS >= 3)
3307  PMMPDE PointerPpe;
3308 #endif
3309 #if (_MI_PAGING_LEVELS == 4)
3310  PMMPDE PointerPxe;
3311 #endif
3312  PMMPFN Pfn1;
3313  NTSTATUS Status, TempStatus;
3314 
3315  /* Lock the address space */
3318 
3319  /* Make sure we still have an address space */
3321  if (CurrentProcess->VmDeleted)
3322  {
3324  goto Cleanup;
3325  }
3326 
3327  /* Check the VADs in the requested range */
3329  if (!NT_SUCCESS(Status))
3330  {
3331  goto Cleanup;
3332  }
3333 
3334  /* Enter SEH for probing */
3335  _SEH2_TRY
3336  {
3337  /* Loop all pages and probe them */
3338  CurrentVa = *BaseAddress;
3339  while (CurrentVa < EndAddress)
3340  {
3341  (void)(*(volatile CHAR*)CurrentVa);
3342  CurrentVa = (PUCHAR)CurrentVa + PAGE_SIZE;
3343  }
3344  }
3346  {
3348  goto Cleanup;
3349  }
3350  _SEH2_END;
3351 
3352  /* All pages were accessible, since we hold the address space lock, nothing
3353  can be de-committed. Assume success for now. */
3355 
3356  /* Get the PTE and PDE */
3357  PointerPte = MiAddressToPte(*BaseAddress);
3358  PointerPde = MiAddressToPde(*BaseAddress);
3359 #if (_MI_PAGING_LEVELS >= 3)
3360  PointerPpe = MiAddressToPpe(*BaseAddress);
3361 #endif
3362 #if (_MI_PAGING_LEVELS == 4)
3363  PointerPxe = MiAddressToPxe(*BaseAddress);
3364 #endif
3365 
3366  /* Get the last PTE */
3367  LastPte = MiAddressToPte((PVOID)((ULONG_PTR)EndAddress - 1));
3368 
3369  /* Lock the process working set */
3371 
3372  /* Loop the pages */
3373  do
3374  {
3375  /* Check for a page that is not accessible */
3376  while (
3377 #if (_MI_PAGING_LEVELS == 4)
3378  (PointerPxe->u.Hard.Valid == 0) ||
3379 #endif
3380 #if (_MI_PAGING_LEVELS >= 3)
3381  (PointerPpe->u.Hard.Valid == 0) ||
3382 #endif
3383  (PointerPde->u.Hard.Valid == 0) ||
3384  (PointerPte->u.Hard.Valid == 0))
3385  {
3386  /* Release process working set */
3388 
3389  /* Access the page */
3390  CurrentVa = MiPteToAddress(PointerPte);
3391 
3392  //HACK: Pass a placeholder TrapInformation so the fault handler knows we're unlocked
3393  TempStatus = MmAccessFault(TRUE, CurrentVa, KernelMode, (PVOID)(ULONG_PTR)0xBADBADA3BADBADA3ULL);
3394  if (!NT_SUCCESS(TempStatus))
3395  {
3396  // This should only happen, when remote backing storage is not accessible
3397  ASSERT(FALSE);
3398  Status = TempStatus;
3399  goto Cleanup;
3400  }
3401 
3402  /* Lock the process working set */
3404  }
3405 
3406  /* Get the PFN */
3407  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
3408  ASSERT(Pfn1 != NULL);
3409 
3410  /* Check the previous lock status */
3411  if (MI_IS_LOCKED_VA(Pfn1, MapType))
3412  {
3414  }
3415 
3416  /* Lock it */
3417  MI_LOCK_VA(Pfn1, MapType);
3418 
3419  /* Go to the next PTE */
3420  PointerPte++;
3421 
3422  /* Check if we're on a PDE boundary */
3423  if (MiIsPteOnPdeBoundary(PointerPte)) PointerPde++;
3424 #if (_MI_PAGING_LEVELS >= 3)
3425  if (MiIsPteOnPpeBoundary(PointerPte)) PointerPpe++;
3426 #endif
3427 #if (_MI_PAGING_LEVELS == 4)
3428  if (MiIsPteOnPxeBoundary(PointerPte)) PointerPxe++;
3429 #endif
3430  } while (PointerPte <= LastPte);
3431 
3432  /* Release process working set */
3434 
3435 Cleanup:
3436  /* Unlock address space */
3438 
3439  return Status;
3440 }
#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:204
#define TRUE
Definition: types.h:120
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2268
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1427
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:154
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1100
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
Status
Definition: gdiplustypes.h:24
FORCEINLINE PMMPTE MiAddressToPxe(PVOID Address)
Definition: mm.h:164
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG CurrentProcess
Definition: shell.c:125
static NTSTATUS MiCheckVadsForLockOperation(_Inout_ PVOID *BaseAddress, _Inout_ PSIZE_T RegionSize, _Inout_ PVOID *EndAddress)
Definition: virtual.c:3251
#define ASSERT(a)
Definition: mode.c:45
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG64 Valid
Definition: mmtypes.h:150
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:502
#define MiIsPteOnPpeBoundary(PointerPte)
Definition: mm.h:242
Definition: mm.h:311
#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:939
union _MMPTE::@2319 u
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
_SEH2_END
Definition: create.c:4400
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:240
#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:3192
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1420
#define PFN_FROM_PTE(v)
Definition: mm.h:92
FORCEINLINE VOID MI_LOCK_VA(PMMPFN Pfn1, ULONG LockType)
Definition: virtual.c:3209
FORCEINLINE PMMSUPPORT MmGetCurrentAddressSpace(VOID)
Definition: mm.h:1442
#define MiIsPteOnPxeBoundary(PointerPte)
Definition: mm.h:244
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1170

Referenced by NtLockVirtualMemory(), and RunTest().

◆ MiMakePdeExistAndMakeValid()

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

Definition at line 2411 of file virtual.c.

2414 {
2415  PMMPTE PointerPte, PointerPpe, PointerPxe;
2416 
2417  //
2418  // Sanity checks. The latter is because we only use this function with the
2419  // PFN lock not held, so it may go away in the future.
2420  //
2422  ASSERT(OldIrql == MM_NOIRQL);
2423 
2424  //
2425  // Also get the PPE and PXE. This is okay not to #ifdef because they will
2426  // return the same address as the PDE on 2-level page table systems.
2427  //
2428  // If everything is already valid, there is nothing to do.
2429  //
2430  PointerPpe = MiAddressToPte(PointerPde);
2431  PointerPxe = MiAddressToPde(PointerPde);
2432  if ((PointerPxe->u.Hard.Valid) &&
2433  (PointerPpe->u.Hard.Valid) &&
2434  (PointerPde->u.Hard.Valid))
2435  {
2436  return;
2437  }
2438 
2439  //
2440  // At least something is invalid, so begin by getting the PTE for the PDE itself
2441  // and then lookup each additional level. We must do it in this precise order
2442  // because the pagfault.c code (as well as in Windows) depends that the next
2443  // level up (higher) must be valid when faulting a lower level
2444  //
2445  PointerPte = MiPteToAddress(PointerPde);
2446  do
2447  {
2448  //
2449  // Make sure APCs continued to be disabled
2450  //
2452 
2453  //
2454  // First, make the PXE valid if needed
2455  //
2456  if (!PointerPxe->u.Hard.Valid)
2457  {
2458  MiMakeSystemAddressValid(PointerPpe, TargetProcess);
2459  ASSERT(PointerPxe->u.Hard.Valid == 1);
2460  }
2461 
2462  //
2463  // Next, the PPE
2464  //
2465  if (!PointerPpe->u.Hard.Valid)
2466  {
2467  MiMakeSystemAddressValid(PointerPde, TargetProcess);
2468  ASSERT(PointerPpe->u.Hard.Valid == 1);
2469  }
2470 
2471  //
2472  // And finally, make the PDE itself valid.
2473  //
2474  MiMakeSystemAddressValid(PointerPte, TargetProcess);
2475 
2476  //
2477  // This should've worked the first time so the loop is really just for
2478  // show -- ASSERT that we're actually NOT going to be looping.
2479  //
2480  ASSERT(PointerPxe->u.Hard.Valid == 1);
2481  ASSERT(PointerPpe->u.Hard.Valid == 1);
2482  ASSERT(PointerPde->u.Hard.Valid == 1);
2483  } while (!(PointerPxe->u.Hard.Valid) ||
2484  !(PointerPpe->u.Hard.Valid) ||
2485  !(PointerPde->u.Hard.Valid));
2486 }
ULONG NTAPI MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
Definition: virtual.c:205
#define MiAddressToPde(x)
Definition: mmx86.c:20
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
#define TRUE
Definition: types.h:120
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define ASSERT(a)
Definition: mode.c:45
ULONG64 Valid
Definition: mmtypes.h:150
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define MM_NOIRQL
Definition: miarm.h:232
union _MMPTE::@2319 u
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201

Referenced by MiDecommitPages(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), and NtAllocateVirtualMemory().

◆ MiMakeSystemAddressValid()

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

Definition at line 205 of file virtual.c.

207 {
209  BOOLEAN WsShared = FALSE, WsSafe = FALSE, LockChange = FALSE;
210  PETHREAD CurrentThread = PsGetCurrentThread();
211 
212  /* Must be a non-pool page table, since those are double-mapped already */
213  ASSERT(PageTableVirtualAddress > MM_HIGHEST_USER_ADDRESS);
214  ASSERT((PageTableVirtualAddress < MmPagedPoolStart) ||
215  (PageTableVirtualAddress > MmPagedPoolEnd));
216 
217  /* Working set lock or PFN lock should be held */
219 
220  /* Check if the page table is valid */
221  while (!MmIsAddressValid(PageTableVirtualAddress))
222  {
223  /* Release the working set lock */
225  CurrentThread,
226  &WsSafe,
227  &WsShared);
228 
229  /* Fault it in */
230  Status = MmAccessFault(FALSE, PageTableVirtualAddress, KernelMode, NULL);
231  if (!NT_SUCCESS(Status))
232  {
233  /* This should not fail */
234  KeBugCheckEx(KERNEL_DATA_INPAGE_ERROR,
235  1,
236  Status,
238  (ULONG_PTR)PageTableVirtualAddress);
239  }
240 
241  /* Lock the working set again */
243  CurrentThread,
244  WsSafe,
245  WsShared);
246 
247  /* This flag will be useful later when we do better locking */
248  LockChange = TRUE;
249  }
250 
251  /* Let caller know what the lock state is */
252  return LockChange;
253 }
#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:204
#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:45
FORCEINLINE VOID MiUnlockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, OUT PBOOLEAN Safe, OUT PBOOLEAN Shared)
Definition: miarm.h:1323
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOLEAN NTAPI MmIsAddressValid(IN PVOID VirtualAddress)
Definition: mmsup.c:174
PVOID MmPagedPoolStart
Definition: miarm.h:581
FORCEINLINE VOID MiLockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, IN BOOLEAN Safe, IN BOOLEAN Shared)
Definition: miarm.h:1356
#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(), MiMakePdeExistAndMakeValid(), and MiQueryAddressState().

◆ MiMakeSystemAddressValidPfn()

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

Definition at line 257 of file virtual.c.

259 {
261  BOOLEAN LockChange = FALSE;
262 
263  /* Must be e kernel address */
265 
266  /* Check if the page is valid */
268  {
269  /* Release the PFN database */
271 
272  /* Fault it in */
274  if (!NT_SUCCESS(Status))
275  {
276  /* This should not fail */
277  KeBugCheckEx(KERNEL_DATA_INPAGE_ERROR,
278  3,
279  Status,
280  0,
282  }
283 
284  /* This flag will be useful later when we do better locking */
285  LockChange = TRUE;
286 
287  /* Lock the PFN database */
289  }
290 
291  /* Let caller know what the lock state is */
292  return LockChange;
293 }
#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:204
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:900
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:907
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:45
#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:790
#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 2490 of file virtual.c.

2492 {
2493  KIRQL OldIrql;
2494  ULONG i;
2495  MMPTE TempPte;
2496  PFN_NUMBER PageFrameIndex;
2497  PMMPFN Pfn1, Pfn2;
2498 
2499  //
2500  // Acquire the PFN lock and loop all the PTEs in the list
2501  //
2503  for (i = 0; i != Count; i++)
2504  {
2505  //
2506  // The PTE must currently be valid
2507  //
2508  TempPte = *ValidPteList[i];
2509  ASSERT(TempPte.u.Hard.Valid == 1);
2510 
2511  //
2512  // Get the PFN entry for the page itself, and then for its page table
2513  //
2514  PageFrameIndex = PFN_FROM_PTE(&TempPte);
2515  Pfn1 = MiGetPfnEntry(PageFrameIndex);
2516  Pfn2 = MiGetPfnEntry(Pfn1->u4.PteFrame);
2517 
2518  //
2519  // Decrement the share count on the page table, and then on the page
2520  // itself
2521  //
2522  MiDecrementShareCount(Pfn2, Pfn1->u4.PteFrame);
2523  MI_SET_PFN_DELETED(Pfn1);
2524  MiDecrementShareCount(Pfn1, PageFrameIndex);
2525 
2526  //
2527  // Make the page decommitted
2528  //
2529  MI_WRITE_INVALID_PTE(ValidPteList[i], MmDecommittedPte);
2530  }
2531 
2532  //
2533  // All the PTEs have been dereferenced and made invalid, flush the TLB now
2534  // and then release the PFN lock
2535  //
2536  KeFlushCurrentTb();
2538 }
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:900
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:907
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG PFN_NUMBER
Definition: ke.h:9
union _MMPFN::@1796 u4
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:45
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
Definition: mm.h:311
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:939
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:190
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:975
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:356
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:325

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

2137 {
2139  PMMVAD Vad;
2141  ULONG_PTR StartingAddress, EndingAddress;
2142  PMMPTE PointerPte, LastPte;
2143  PMMPDE PointerPde;
2144  MMPTE PteContents;
2145  PMMPFN Pfn1;
2146  ULONG ProtectionMask, OldProtect;
2147  BOOLEAN Committed;
2151 
2152  /* Calculate base address for the VAD */
2153  StartingAddress = (ULONG_PTR)PAGE_ALIGN((*BaseAddress));
2154  EndingAddress = (((ULONG_PTR)*BaseAddress + *NumberOfBytesToProtect - 1) | (PAGE_SIZE - 1));
2155 
2156  /* Calculate the protection mask and make sure it's valid */
2157  ProtectionMask = MiMakeProtectionMask(NewAccessProtection);
2158  if (ProtectionMask == MM_INVALID_PROTECTION)
2159  {
2160  DPRINT1("Invalid protection mask\n");
2162  }
2163 
2164  /* Check for ROS specific memory area */
2167  {
2168  /* Evil hack */
2170  BaseAddress,
2171  NumberOfBytesToProtect,
2172  NewAccessProtection,
2173  OldAccessProtection);
2174  }
2175 
2176  /* Lock the address space and make sure the process isn't already dead */
2179  if (Process->VmDeleted)
2180  {
2181  DPRINT1("Process is dying\n");
2183  goto FailPath;
2184  }
2185 
2186  /* Get the VAD for this address range, and make sure it exists */
2187  Result = MiCheckForConflictingNode(StartingAddress >> PAGE_SHIFT,
2188  EndingAddress >> PAGE_SHIFT,
2189  &Process->VadRoot,
2190  (PMMADDRESS_NODE*)&Vad);
2191  if (Result != TableFoundNode)
2192  {
2193  DPRINT("Could not find a VAD for this allocation\n");
2195  goto FailPath;
2196  }
2197 
2198  /* Make sure the address is within this VAD's boundaries */
2199  if ((((ULONG_PTR)StartingAddress >> PAGE_SHIFT) < Vad->StartingVpn) ||
2200  (((ULONG_PTR)EndingAddress >> PAGE_SHIFT) > Vad->EndingVpn))
2201  {
2203  goto FailPath;
2204  }
2205 
2206  /* These kinds of VADs are not supported atm */
2207  if ((Vad->u.VadFlags.VadType == VadAwe) ||
2209  (Vad->u.VadFlags.VadType == VadLargePages))
2210  {
2211  DPRINT1("Illegal VAD for attempting to set protection\n");
2213  goto FailPath;
2214  }
2215 
2216  /* Check for a VAD whose protection can't be changed */
2217  if (Vad->u.VadFlags.NoChange == 1)
2218  {
2219  DPRINT1("Trying to change protection of a NoChange VAD\n");
2221  goto FailPath;
2222  }
2223 
2224  /* Is this section, or private memory? */
2225  if (Vad->u.VadFlags.PrivateMemory == 0)
2226  {
2227  /* Not yet supported */
2228  if (Vad->u.VadFlags.VadType == VadLargePageSection)
2229  {
2230  DPRINT1("Illegal VAD for attempting to set protection\n");
2232  goto FailPath;
2233  }
2234 
2235  /* Rotate VADs are not yet supported */
2236  if (Vad->u.VadFlags.VadType == VadRotatePhysical)
2237  {
2238  DPRINT1("Illegal VAD for attempting to set protection\n");
2240  goto FailPath;
2241  }
2242 
2243  /* Not valid on section files */
2244  if (NewAccessProtection & (PAGE_NOCACHE | PAGE_WRITECOMBINE))
2245  {
2246  /* Fail */
2247  DPRINT1("Invalid protection flags for section\n");
2249  goto FailPath;
2250  }
2251 
2252  /* Check if data or page file mapping protection PTE is compatible */
2253  if (!Vad->ControlArea->u.Flags.Image)
2254  {
2255  /* Not yet */
2256  DPRINT1("Fixme: Not checking for valid protection\n");
2257  }
2258 
2259  /* This is a section, and this is not yet supported */
2260  DPRINT1("Section protection not yet supported\n");
2261  OldProtect = 0;
2262  }
2263  else
2264  {
2265  /* Private memory, check protection flags */
2266  if ((NewAccessProtection & PAGE_WRITECOPY) ||
2267  (NewAccessProtection & PAGE_EXECUTE_WRITECOPY))
2268  {
2269  DPRINT1("Invalid protection flags for private memory\n");
2271  goto FailPath;
2272  }
2273 
2274  /* Lock the working set */
2276 
2277  /* Check if all pages in this range are committed */
2278  Committed = MiIsEntireRangeCommitted(StartingAddress,
2279  EndingAddress,
2280  Vad,
2281  Process);
2282  if (!Committed)
2283  {
2284  /* Fail */
2285  DPRINT1("The entire range is not committed\n");
2288  goto FailPath;
2289  }
2290 
2291  /* Compute starting and ending PTE and PDE addresses */
2292  PointerPde = MiAddressToPde(StartingAddress);
2293  PointerPte = MiAddressToPte(StartingAddress);
2294  LastPte = MiAddressToPte(EndingAddress);
2295 
2296  /* Make this PDE valid */
2298 
2299  /* Save protection of the first page */
2300  if (PointerPte->u.Long != 0)
2301  {
2302  /* Capture the page protection and make the PDE valid */
2303  OldProtect = MiGetPageProtection(PointerPte);
2305  }
2306  else
2307  {
2308  /* Grab the old protection from the VAD itself */
2309  OldProtect = MmProtectToValue[Vad->u.VadFlags.Protection];
2310  }
2311 
2312  /* Loop all the PTEs now */
2313  while (PointerPte <= LastPte)
2314  {
2315  /* Check if we've crossed a PDE boundary and make the new PDE valid too */
2316  if (MiIsPteOnPdeBoundary(PointerPte))
2317  {
2318  PointerPde = MiPteToPde(PointerPte);
2320  }
2321 
2322  /* Capture the PTE and check if it was empty */
2323  PteContents = *PointerPte;
2324  if (PteContents.u.Long == 0)
2325  {
2326  /* This used to be a zero PTE and it no longer is, so we must add a
2327  reference to the pagetable. */
2329  }
2330 
2331  /* Check what kind of PTE we are dealing with */
2332  if (PteContents.u.Hard.Valid == 1)
2333  {
2334  /* Get the PFN entry */
2335  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2336 
2337  /* We don't support this yet */
2338  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
2339 
2340  /* Check if the page should not be accessible at all */
2341  if ((NewAccessProtection & PAGE_NOACCESS) ||
2342  (NewAccessProtection & PAGE_GUARD))
2343  {
2345 
2346  /* Mark the PTE as transition and change its protection */
2347  PteContents.u.Hard.Valid = 0;
2348  PteContents.u.Soft.Transition = 1;
2349  PteContents.u.Trans.Protection = ProtectionMask;
2350  /* Decrease PFN share count and write the PTE */
2351  MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
2352  // FIXME: remove the page from the WS
2353  MI_WRITE_INVALID_PTE(PointerPte, PteContents);
2354 #ifdef CONFIG_SMP
2355  // FIXME: Should invalidate entry in every CPU TLB
2356  ASSERT(FALSE);
2357 #endif
2358  KeInvalidateTlbEntry(MiPteToAddress(PointerPte));
2359 
2360  /* We are done for this PTE */
2362  }
2363  else
2364  {
2365  /* Write the protection mask and write it with a TLB flush */
2366  Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
2367  MiFlushTbAndCapture(Vad,
2368  PointerPte,
2369  ProtectionMask,
2370  Pfn1,
2371  TRUE);
2372  }
2373  }
2374  else
2375  {
2376  /* We don't support these cases yet */
2377  ASSERT(PteContents.u.Soft.Prototype == 0);
2378  //ASSERT(PteContents.u.Soft.Transition == 0);
2379 
2380  /* The PTE is already demand-zero, just update the protection mask */
2381  PteContents.u.Soft.Protection = ProtectionMask;
2382  MI_WRITE_INVALID_PTE(PointerPte, PteContents);
2383  ASSERT(PointerPte->u.Long != 0);
2384  }
2385 
2386  /* Move to the next PTE */
2387  PointerPte++;
2388  }
2389 
2390  /* Unlock the working set */
2392  }
2393 
2394  /* Unlock the address space */
2396 
2397  /* Return parameters and success */
2398  *NumberOfBytesToProtect = EndingAddress - StartingAddress + 1;
2399  *BaseAddress = (PVOID)StartingAddress;
2400  *OldAccessProtection = OldProtect;
2401  return STATUS_SUCCESS;
2402 
2403 FailPath:
2404  /* Unlock the address space and return the failure code */
2406  return Status;
2407 }
#define PAGE_NOCACHE
Definition: nt_native.h:1311
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define MM_INVALID_PROTECTION
Definition: miarm.h:63
ULONG Type
Definition: mm.h:220
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1215
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define TRUE
Definition: types.h:120
#define PAGE_GUARD
Definition: nt_native.h:1310
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2268
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1427
enum _TABLE_SEARCH_RESULT TABLE_SEARCH_RESULT
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:900
ULONG_PTR Protection
Definition: mmtypes.h:706
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
ULONG NTAPI MiGetPageProtection(IN PMMPTE PointerPte)
Definition: virtual.c:1369
ULONG_PTR NoChange
Definition: mmtypes.h:703
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:744
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:907
VOID NTAPI MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
Definition: virtual.c:2411
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:301
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:335
ULONG_PTR EndingVpn
Definition: mmtypes.h:740
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define PAGE_EXECUTE_WRITECOPY
Definition: nt_native.h:1309
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:73
#define FALSE
Definition: types.h:117
union _CONTROL_AREA::@2572 u
PCONTROL_AREA ControlArea
Definition: mmtypes.h:746
#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 DPRINT(...)
Definition: polytest.cpp:61
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:739
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:2016
Status
Definition: gdiplustypes.h:24
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1145
FORCEINLINE VOID KeInvalidateTlbEntry(IN PVOID Address)
Definition: ke.h:201
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG_PTR PrivateMemory
Definition: mmtypes.h:708
#define ASSERT(a)
Definition: mode.c:45
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:2653
union _MMPFN::@1793 u3
VOID NTAPI MiFlushTbAndCapture(IN PMMVAD FoundVad, IN PMMPTE PointerPte, IN ULONG ProtectionMask, IN PMMPFN Pfn1, IN BOOLEAN CaptureDirtyBit)
Definition: section.c:1979
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define MM_NOIRQL
Definition: miarm.h:232
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:158
Definition: mm.h:311
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
const ULONG MmProtectToValue[32]
Definition: page.c:81
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:939
union _MMPTE::@2319 u
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MiPteToPde(_Pte)
Definition: mm.h:236
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:975
#define PAGE_WRITECOMBINE
Definition: mmtypes.h:78
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:240
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:2092
ULONG64 Transition
Definition: mmtypes.h:90
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
MMPTE OriginalPte
Definition: mm.h:345
#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
FORCEINLINE VOID MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:1673
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
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
#define STATUS_INVALID_PARAMETER_4
Definition: ntstatus.h:478
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:261
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:65
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1420
#define PFN_FROM_PTE(v)
Definition: mm.h:92
ULONG64 Protection
Definition: mmtypes.h:103
ULONG_PTR VadType
Definition: mmtypes.h:704
FORCEINLINE PMMSUPPORT MmGetCurrentAddressSpace(VOID)
Definition: mm.h:1442
union _MMVAD::@2579 u

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

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

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

1680 {
1681  PEPROCESS TargetProcess;
1683  PMMVAD Vad = NULL;
1684  PVOID Address, NextAddress;
1685  BOOLEAN Found = FALSE;
1686  ULONG NewProtect, NewState;
1687  ULONG_PTR BaseVpn;
1688  MEMORY_BASIC_INFORMATION MemoryInfo;
1693 
1694  /* Check for illegal addresses in user-space, or the shared memory area */
1697  {
1699 
1700  /* Make up an info structure describing this range */
1701  MemoryInfo.BaseAddress = Address;
1702  MemoryInfo.AllocationProtect = PAGE_READONLY;
1703  MemoryInfo.Type = MEM_PRIVATE;
1704 
1705  /* Special case for shared data */
1707  {
1709  MemoryInfo.State = MEM_COMMIT;
1710  MemoryInfo.Protect = PAGE_READONLY;
1711  MemoryInfo.RegionSize = PAGE_SIZE;
1712  }
1713  else
1714  {
1715  MemoryInfo.AllocationBase = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1;
1716  MemoryInfo.State = MEM_RESERVE;
1717  MemoryInfo.Protect = PAGE_NOACCESS;
1719  }
1720 
1721  /* Return the data, NtQueryInformation already probed it*/
1722  if (PreviousMode != KernelMode)
1723  {
1724  _SEH2_TRY
1725  {
1726  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1728  }
1730  {
1732  }
1733  _SEH2_END;
1734  }
1735  else
1736  {
1737  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1739  }
1740 
1741  return Status;
1742  }
1743 
1744  /* Check if this is for a local or remote process */
1746  {
1747  TargetProcess = PsGetCurrentProcess();
1748  }
1749  else
1750  {
1751  /* Reference the target process */
1754  PsProcessType,
1756  (PVOID*)&TargetProcess,
1757  NULL);
1758  if (!NT_SUCCESS(Status)) return Status;
1759 
1760  /* Attach to it now */
1761  KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
1762  }
1763 
1764  /* Lock the address space and make sure the process isn't already dead */
1765  MmLockAddressSpace(&TargetProcess->Vm);
1766  if (TargetProcess->VmDeleted)
1767  {
1768  /* Unlock the address space of the process */
1769  MmUnlockAddressSpace(&TargetProcess->Vm);
1770 
1771  /* Check if we were attached */
1773  {
1774  /* Detach and dereference the process */
1776  ObDereferenceObject(TargetProcess);
1777  }
1778 
1779  /* Bail out */
1780  DPRINT1("Process is dying\n");
1782  }
1783 
1784  /* Loop the VADs */
1785  ASSERT(TargetProcess->VadRoot.NumberGenericTableElements);
1786  if (TargetProcess->VadRoot.NumberGenericTableElements)
1787  {
1788  /* Scan on the right */
1789  Vad = (PMMVAD)TargetProcess->VadRoot.BalancedRoot.RightChild;
1790  BaseVpn = (ULONG_PTR)BaseAddress >> PAGE_SHIFT;
1791  while (Vad)
1792  {
1793  /* Check if this VAD covers the allocation range */
1794  if ((BaseVpn >= Vad->StartingVpn) &&
1795  (BaseVpn <= Vad->EndingVpn))
1796  {
1797  /* We're done */
1798  Found = TRUE;
1799  break;
1800  }
1801 
1802  /* Check if this VAD is too high */
1803  if (BaseVpn < Vad->StartingVpn)
1804  {
1805  /* Stop if there is no left child */
1806  if (!Vad->LeftChild) break;
1807 
1808  /* Search on the left next */
1809  Vad = Vad->LeftChild;
1810  }
1811  else
1812  {
1813  /* Then this VAD is too low, keep searching on the right */
1814  ASSERT(BaseVpn > Vad->EndingVpn);
1815 
1816  /* Stop if there is no right child */
1817  if (!Vad->RightChild) break;
1818 
1819  /* Search on the right next */
1820  Vad = Vad->RightChild;
1821  }
1822  }
1823  }
1824 
1825  /* Was a VAD found? */
1826  if (!Found)
1827  {
1829 
1830  /* Calculate region size */
1831  if (Vad)
1832  {
1833  if (Vad->StartingVpn >= BaseVpn)
1834  {
1835  /* Region size is the free space till the start of that VAD */
1836  MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
1837  }
1838  else
1839  {
1840  /* Get the next VAD */
1841  Vad = (PMMVAD)MiGetNextNode((PMMADDRESS_NODE)Vad);
1842  if (Vad)
1843  {
1844  /* Region size is the free space till the start of that VAD */
1845  MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
1846  }
1847  else
1848  {
1849  /* Maximum possible region size with that base address */
1850  MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
1851  }
1852  }
1853  }
1854  else
1855  {
1856  /* Maximum possible region size with that base address */
1857  MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
1858  }
1859 
1860  /* Unlock the address space of the process */
1861  MmUnlockAddressSpace(&TargetProcess->Vm);
1862 
1863  /* Check if we were attached */
1865  {
1866  /* Detach and derefernece the process */
1868  ObDereferenceObject(TargetProcess);
1869  }
1870 
1871  /* Build the rest of the initial information block */
1872  MemoryInfo.BaseAddress = Address;
1873  MemoryInfo.AllocationBase = NULL;
1874  MemoryInfo.AllocationProtect = 0;
1875  MemoryInfo.State = MEM_FREE;
1876  MemoryInfo.Protect = PAGE_NOACCESS;
1877  MemoryInfo.Type = 0;
1878 
1879  /* Return the data, NtQueryInformation already probed it*/
1880  if (PreviousMode != KernelMode)
1881  {
1882  _SEH2_TRY
1883  {
1884  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1886  }
1888  {
1890  }
1891  _SEH2_END;
1892  }
1893  else
1894  {
1895  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1897  }
1898 
1899  return Status;
1900  }
1901 
1902  /* Set the correct memory type based on what kind of VAD this is */
1903  if ((Vad->u.VadFlags.PrivateMemory) ||
1904  (Vad->u.VadFlags.VadType == VadRotatePhysical))
1905  {
1906  MemoryInfo.Type = MEM_PRIVATE;
1907  }
1908  else if (Vad->u.VadFlags.VadType == VadImageMap)
1909  {
1910  MemoryInfo.Type = MEM_IMAGE;
1911  }
1912  else
1913  {
1914  MemoryInfo.Type = MEM_MAPPED;
1915  }
1916 
1917  /* Find the memory area the specified address belongs to */
1919  ASSERT(MemoryArea != NULL);
1920 
1921  /* Determine information dependent on the memory area type */
1923  {
1925  if (!NT_SUCCESS(Status))
1926  {
1927  DPRINT1("MmQuerySectionView failed. MemoryArea=%p (%p-%p), BaseAddress=%p\n",
1930  }
1931  }
1932  else
1933  {
1934  /* Build the initial information block */
1936  MemoryInfo.BaseAddress = Address;
1937  MemoryInfo.AllocationBase = (PVOID)(Vad->StartingVpn << PAGE_SHIFT);
1939  MemoryInfo.Type = MEM_PRIVATE;
1940 
1941  /* Acquire the working set lock (shared is enough) */
1943 
1944  /* Find the largest chunk of memory which has the same state and protection mask */
1945  MemoryInfo.State = MiQueryAddressState(Address,
1946  Vad,
1947  TargetProcess,
1948  &MemoryInfo.Protect,
1949  &NextAddress);
1950  Address = NextAddress;
1951  while (((ULONG_PTR)Address >> PAGE_SHIFT) <= Vad->EndingVpn)
1952  {
1953  /* Keep going unless the state or protection mask changed */
1954  NewState = MiQueryAddressState(Address, Vad, TargetProcess, &NewProtect, &NextAddress);
1955  if ((NewState != MemoryInfo.State) || (NewProtect != MemoryInfo.Protect)) break;
1956  Address = NextAddress;
1957  }
1958 
1959  /* Release the working set lock */
1961 
1962  /* Check if we went outside of the VAD */
1963  if (((ULONG_PTR)Address >> PAGE_SHIFT) > Vad->EndingVpn)
1964  {
1965  /* Set the end of the VAD as the end address */
1966  Address = (PVOID)((Vad->EndingVpn + 1) << PAGE_SHIFT);
1967  }
1968 
1969  /* Now that we know the last VA address, calculate the region size */
1970  MemoryInfo.RegionSize = ((ULONG_PTR)Address - (ULONG_PTR)MemoryInfo.BaseAddress);
1971  }
1972 
1973  /* Unlock the address space of the process */
1974  MmUnlockAddressSpace(&TargetProcess->Vm);
1975 
1976  /* Check if we were attached */
1978  {
1979  /* Detach and derefernece the process */
1981  ObDereferenceObject(TargetProcess);
1982  }
1983 
1984  /* Return the data, NtQueryInformation already probed it */
1985  if (PreviousMode != KernelMode)
1986  {
1987  _SEH2_TRY
1988  {
1989  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1991  }
1993  {
1995  }
1996  _SEH2_END;
1997  }
1998  else
1999  {
2000  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
2002  }
2003 
2004  /* All went well */
2005  DPRINT("Base: %p AllocBase: %p AllocProtect: %lx Protect: %lx "
2006  "State: %lx Type: %lx Size: %lx\n",
2007  MemoryInfo.BaseAddress, MemoryInfo.AllocationBase,
2008  MemoryInfo.AllocationProtect, MemoryInfo.Protect,
2009  MemoryInfo.State, MemoryInfo.Type, MemoryInfo.RegionSize);
2010 
2011  return Status;
2012 }
signed char * PCHAR
Definition: retypes.h:7
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define MEM_IMAGE
Definition: mmtypes.h:88
KAPC_STATE
Definition: ketypes.h:1280
ULONG Type
Definition: mm.h:220
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:158
struct _MEMORY_BASIC_INFORMATION MEMORY_BASIC_INFORMATION
FORCEINLINE VOID MiUnlockProcessWorkingSetShared(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1191
#define TRUE
Definition: types.h:120
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1427
LONG NTSTATUS
Definition: precomp.h:26
ULONG_PTR NumberGenericTableElements
Definition: mmtypes.h:678
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3070
ULONG_PTR Protection
Definition: mmtypes.h:706
#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:744
MMADDRESS_NODE BalancedRoot
Definition: mmtypes.h:672
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG_PTR EndingVpn
Definition: mmtypes.h:740
NTSTATUS NTAPI MmQuerySectionView(PMEMORY_AREA MemoryArea, PVOID Address, PMEMORY_BASIC_INFORMATION Info, PSIZE_T ResultLength)
Definition: section.c:2559
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:496
#define FALSE
Definition: types.h:117
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:701
struct _MMVAD * LeftChild
Definition: mmtypes.h:737
#define MEM_RESERVE
Definition: nt_native.h:1314
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define PAGE_NOACCESS
Definition: nt_native.h:1302
unsigned char BOOLEAN
static WCHAR Address[46]
Definition: ping.c:68
void DPRINT(...)
Definition: polytest.cpp:61
return Found
Definition: dirsup.c:1270
ULONG_PTR StartingVpn
Definition: mmtypes.h:739
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:71
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define PCHAR
Definition: match.c:90
Status
Definition: gdiplustypes.h:24
#define MEM_FREE
Definition: nt_native.h:1317
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG VmDeleted
Definition: pstypes.h:1340
ULONG_PTR PrivateMemory
Definition: mmtypes.h:708
#define ASSERT(a)
Definition: mode.c:45
#define MEM_PRIVATE
Definition: nt_native.h:1318
struct _MEMORY_BASIC_INFORMATION * PMEMORY_BASIC_INFORMATION
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#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:214
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:662
FORCEINLINE VOID MiLockProcessWorkingSetShared(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1122
struct _MMVAD * RightChild
Definition: mmtypes.h:738
static PVOID
Definition: virtual.c:33
#define PAGE_SIZE
Definition: env_spec_w32.h:49
KPROCESS Pcb
Definition: pstypes.h:1204
const ULONG MmProtectToValue[32]
Definition: page.c:81
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:213
MMSUPPORT Vm
Definition: pstypes.h:1298
ULONG NTAPI MiQueryAddressState(IN PVOID Va, IN PMMVAD Vad, IN PEPROCESS TargetProcess, OUT PULONG ReturnedProtect, OUT PVOID *NextVa)
Definition: virtual.c:1484
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_SEH2_END
Definition: create.c:4400
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:753
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1488
_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:6
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
MM_AVL_TABLE VadRoot
Definition: pstypes.h:1395
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:65
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1420
struct _MMVAD * PMMVAD
POBJECT_TYPE PsProcessType
Definition: process.c:20
ULONG_PTR VadType
Definition: mmtypes.h:704
union _MMVAD::@2579 u

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

2097 {
2100  ULONG OldAccessProtection_;
2101  NTSTATUS Status;
2102 
2103  *NumberOfBytesToProtect = PAGE_ROUND_UP((ULONG_PTR)(*BaseAddress) + (*NumberOfBytesToProtect)) - PAGE_ROUND_DOWN(*BaseAddress);
2105 
2106  AddressSpace = &Process->Vm;
2110  {
2112  return STATUS_UNSUCCESSFUL;
2113  }
2114 
2115  if (OldAccessProtection == NULL) OldAccessProtection = &OldAccessProtection_;
2116 
2119  MemoryArea,
2120  *BaseAddress,
2121  *NumberOfBytesToProtect,
2122  NewAccessProtection,
2123  OldAccessProtection);
2124 
2126 
2127  return Status;
2128 }
ULONG Type
Definition: mm.h:220
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2268
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1427
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:71
Status
Definition: gdiplustypes.h:24
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define ASSERT(a)
Definition: mode.c:45
BOOLEAN DeleteInProgress
Definition: mm.h:223
#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:2523
unsigned int ULONG
Definition: retypes.h:1
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:65
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1420

Referenced by MiProtectVirtualMemory().

◆ MiUnlockVirtualMemory()

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

Definition at line 3615 of file virtual.c.

3619 {
3622  PVOID EndAddress;
3623  PMMPTE PointerPte, LastPte;
3624  PMMPDE PointerPde;
3625 #if (_MI_PAGING_LEVELS >= 3)
3626  PMMPDE PointerPpe;
3627 #endif
3628 #if (_MI_PAGING_LEVELS == 4)
3629  PMMPDE PointerPxe;
3630 #endif
3631  PMMPFN Pfn1;
3632  NTSTATUS Status;
3633 
3634  /* Lock the address space */
3637 
3638  /* Make sure we still have an address space */
3640  if (CurrentProcess->VmDeleted)
3641  {
3643  goto Cleanup;
3644  }
3645 
3646  /* Check the VADs in the requested range */
3648 
3649  /* Note: only bail out, if we hit an area without a VAD. If we hit an
3650  incompatible VAD we continue, like Windows does */
3652  {
3654  goto Cleanup;
3655  }
3656 
3657  /* Get the PTE and PDE */
3658  PointerPte = MiAddressToPte(*BaseAddress);
3659  PointerPde = MiAddressToPde(*BaseAddress);
3660 #if (_MI_PAGING_LEVELS >= 3)
3661  PointerPpe = MiAddressToPpe(*BaseAddress);
3662 #endif
3663 #if (_MI_PAGING_LEVELS == 4)
3664  PointerPxe = MiAddressToPxe(*BaseAddress);
3665 #endif
3666 
3667  /* Get the last PTE */
3668  LastPte = MiAddressToPte((PVOID)((ULONG_PTR)EndAddress - 1));
3669 
3670  /* Lock the process working set */
3672 
3673  /* Loop the pages */
3674  do
3675  {
3676  /* Check for a page that is not present */
3677  if (
3678 #if (_MI_PAGING_LEVELS == 4)
3679  (PointerPxe->u.Hard.Valid == 0) ||
3680 #endif
3681 #if (_MI_PAGING_LEVELS >= 3)
3682  (PointerPpe->u.Hard.Valid == 0) ||
3683 #endif
3684  (PointerPde->u.Hard.Valid == 0) ||
3685  (PointerPte->u.Hard.Valid == 0))
3686  {
3687  /* Remember it, but keep going */
3689  }
3690  else
3691  {
3692  /* Get the PFN */
3693  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
3694  ASSERT(Pfn1 != NULL);
3695 
3696  /* Check if all of the requested locks are present */
3697  if (((MapType & MAP_SYSTEM) && !MI_IS_LOCKED_VA(Pfn1, MAP_SYSTEM)) ||
3698  ((MapType & MAP_PROCESS) && !MI_IS_LOCKED_VA(Pfn1, MAP_PROCESS)))
3699  {
3700  /* Remember it, but keep going */
3702 
3703  /* Check if no lock is present */
3704  if (!MI_IS_LOCKED_VA(Pfn1, MAP_PROCESS | MAP_SYSTEM))
3705  {
3706  DPRINT1("FIXME: Should remove the page from WS\n");
3707  }
3708  }
3709  }
3710 
3711  /* Go to the next PTE */
3712  PointerPte++;
3713 
3714  /* Check if we're on a PDE boundary */
3715  if (MiIsPteOnPdeBoundary(PointerPte)) PointerPde++;
3716 #if (_MI_PAGING_LEVELS >= 3)
3717  if (MiIsPteOnPpeBoundary(PointerPte)) PointerPpe++;
3718 #endif
3719 #if (_MI_PAGING_LEVELS == 4)
3720  if (MiIsPteOnPxeBoundary(PointerPte)) PointerPxe++;
3721 #endif
3722  } while (PointerPte <= LastPte);
3723 
3724  /* Check if we hit a page that was not locked */
3725  if (Status == STATUS_NOT_LOCKED)
3726  {
3727  goto CleanupWithWsLock;
3728  }
3729 
3730  /* All pages in the region were locked, so unlock them all */
3731 
3732  /* Get the PTE and PDE */
3733  PointerPte = MiAddressToPte(*BaseAddress);
3734  PointerPde = MiAddressToPde(*BaseAddress);
3735 #if (_MI_PAGING_LEVELS >= 3)
3736  PointerPpe = MiAddressToPpe(*BaseAddress);
3737 #endif
3738 #if (_MI_PAGING_LEVELS == 4)
3739  PointerPxe = MiAddressToPxe(*BaseAddress);
3740 #endif
3741 
3742  /* Loop the pages */
3743  do
3744  {
3745  /* Unlock it */
3746  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
3747  MI_UNLOCK_VA(Pfn1, MapType);
3748 
3749  /* Go to the next PTE */
3750  PointerPte++;
3751 
3752  /* Check if we're on a PDE boundary */
3753  if (MiIsPteOnPdeBoundary(PointerPte)) PointerPde++;
3754 #if (_MI_PAGING_LEVELS >= 3)
3755  if (MiIsPteOnPpeBoundary(PointerPte)) PointerPpe++;
3756 #endif