ReactOS  0.4.15-dev-2355-gaf9df93
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 3190 of file virtual.c.

3193 {
3194  // HACK until we have proper WSLIST support
3195  PMMWSLE Wsle = &Pfn1->Wsle;
3196 
3197  if ((LockType & MAP_PROCESS) && (Wsle->u1.e1.LockedInWs))
3198  return TRUE;
3199  if ((LockType & MAP_SYSTEM) && (Wsle->u1.e1.LockedInMemory))
3200  return TRUE;
3201 
3202  return FALSE;
3203 }
#define TRUE
Definition: types.h:120
MMWSLENTRY e1
Definition: mmtypes.h:840
MMWSLE Wsle
Definition: mm.h:401
#define FALSE
Definition: types.h:117
union _MMWSLE::@2574 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:826
ULONG_PTR LockedInWs
Definition: mmtypes.h:825
#define MAP_SYSTEM
Definition: mmtypes.h:68

Referenced by MiLockVirtualMemory(), and MiUnlockVirtualMemory().

◆ MI_LOCK_VA()

FORCEINLINE VOID MI_LOCK_VA ( PMMPFN  Pfn1,
ULONG  LockType 
)

Definition at line 3207 of file virtual.c.

3210 {
3211  // HACK until we have proper WSLIST support
3212  PMMWSLE Wsle = &Pfn1->Wsle;
3213 
3214  if (!Wsle->u1.e1.LockedInWs &&
3215  !Wsle->u1.e1.LockedInMemory)
3216  {
3218  }
3219 
3220  if (LockType & MAP_PROCESS)
3221  Wsle->u1.e1.LockedInWs = 1;
3222  if (LockType & MAP_SYSTEM)
3223  Wsle->u1.e1.LockedInMemory = 1;
3224 }
MMWSLENTRY e1
Definition: mmtypes.h:840
MMWSLE Wsle
Definition: mm.h:401
union _MMWSLE::@2574 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:826
FORCEINLINE VOID MiReferenceProbedPageAndBumpLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1541
ULONG_PTR LockedInWs
Definition: mmtypes.h:825
#define MAP_SYSTEM
Definition: mmtypes.h:68

Referenced by MiLockVirtualMemory().

◆ MI_UNLOCK_VA()

FORCEINLINE VOID MI_UNLOCK_VA ( PMMPFN  Pfn1,
ULONG  LockType 
)

Definition at line 3228 of file virtual.c.

3231 {
3232  // HACK until we have proper WSLIST support
3233  PMMWSLE Wsle = &Pfn1->Wsle;
3234 
3235  if (LockType & MAP_PROCESS)
3236  Wsle->u1.e1.LockedInWs = 0;
3237  if (LockType & MAP_SYSTEM)
3238  Wsle->u1.e1.LockedInMemory = 0;
3239 
3240  if (!Wsle->u1.e1.LockedInWs &&
3241  !Wsle->u1.e1.LockedInMemory)
3242  {
3244  }
3245 }
FORCEINLINE VOID MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1469
MMWSLENTRY e1
Definition: mmtypes.h:840
MMWSLE Wsle
Definition: mm.h:401
union _MMWSLE::@2574 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:826
ULONG_PTR LockedInWs
Definition: mmtypes.h:825
#define MAP_SYSTEM
Definition: mmtypes.h:68

Referenced by MiUnlockVirtualMemory().

◆ MiCalculatePageCommitment()

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

Definition at line 42 of file virtual.c.

46 {
47  PMMPTE PointerPte, LastPte;
48  PMMPDE PointerPde;
49  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
union _MMPTE::@2304 u
#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
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 3249 of file virtual.c.

3254 {
3255  PMMVAD Vad;
3256  PVOID CurrentVa;
3257 
3258  /* Get the base address and align the start address */
3259  *EndAddress = (PUCHAR)*BaseAddress + *RegionSize;
3260  *EndAddress = ALIGN_UP_POINTER_BY(*EndAddress, PAGE_SIZE);
3262 
3263  /* First loop and check all VADs */
3264  CurrentVa = *BaseAddress;
3265  while (CurrentVa < *EndAddress)
3266  {
3267  /* Get VAD */
3268  Vad = MiLocateAddress(CurrentVa);
3269  if (Vad == NULL)
3270  {
3272  return STATUS_ACCESS_VIOLATION;
3273  }
3274 
3275  /* Check VAD type */
3276  if ((Vad->u.VadFlags.VadType != VadNone) &&
3277  (Vad->u.VadFlags.VadType != VadImageMap) &&
3278  (Vad->u.VadFlags.VadType != VadWriteWatch))
3279  {
3280  *EndAddress = CurrentVa;
3281  *RegionSize = (PUCHAR)*EndAddress - (PUCHAR)*BaseAddress;
3283  }
3284 
3285  CurrentVa = (PVOID)((Vad->EndingVpn + 1) << PAGE_SHIFT);
3286  }
3287 
3288  *RegionSize = (PUCHAR)*EndAddress - (PUCHAR)*BaseAddress;
3289  return STATUS_SUCCESS;
3290 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
unsigned char * PUCHAR
Definition: retypes.h:3
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:48
_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
union _MMVAD::@2564 u
#define NULL
Definition: types.h:112
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ALIGN_DOWN_POINTER_BY(ptr, align)
Definition: umtypes.h:82
#define STATUS_INCOMPATIBLE_FILE_MAP
Definition: ntstatus.h:313
ULONG_PTR VadType
Definition: mmtypes.h:691

Referenced by MiLockVirtualMemory(), and MiUnlockVirtualMemory().

◆ MiDecommitPages()

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

Definition at line 2540 of file virtual.c.

2544 {
2545  PMMPTE PointerPte, CommitPte = NULL;
2546  PMMPDE PointerPde;
2547  ULONG CommitReduction = 0;
2548  PMMPTE ValidPteList[256];
2549  ULONG PteCount = 0;
2550  PMMPFN Pfn1;
2551  MMPTE PteContents;
2552  PETHREAD CurrentThread = PsGetCurrentThread();
2553 
2554  //
2555  // Get the PTE and PTE for the address, and lock the working set
2556  // If this was a VAD for a MEM_COMMIT allocation, also figure out where the
2557  // commited range ends so that we can do the right accounting.
2558  //
2559  PointerPde = MiAddressToPde(StartingAddress);
2560  PointerPte = MiAddressToPte(StartingAddress);
2561  if (Vad->u.VadFlags.MemCommit) CommitPte = MiAddressToPte(Vad->EndingVpn << PAGE_SHIFT);
2562  MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
2563 
2564  //
2565  // Make the PDE valid, and now loop through each page's worth of data
2566  //
2568  while (PointerPte <= EndingPte)
2569  {
2570  //
2571  // Check if we've crossed a PDE boundary
2572  //
2573  if (MiIsPteOnPdeBoundary(PointerPte))
2574  {
2575  //
2576  // Get the new PDE and flush the valid PTEs we had built up until
2577  // now. This helps reduce the amount of TLB flushing we have to do.
2578  // Note that Windows does a much better job using timestamps and
2579  // such, and does not flush the entire TLB all the time, but right
2580  // now we have bigger problems to worry about than TLB flushing.
2581  //
2582  PointerPde = MiAddressToPde(StartingAddress);
2583  if (PteCount)
2584  {
2585  MiProcessValidPteList(ValidPteList, PteCount);
2586  PteCount = 0;
2587  }
2588 
2589  //
2590  // Make this PDE valid
2591  //
2593  }
2594 
2595  //
2596  // Read this PTE. It might be active or still demand-zero.
2597  //
2598  PteContents = *PointerPte;
2599  if (PteContents.u.Long)
2600  {
2601  //
2602  // The PTE is active. It might be valid and in a working set, or
2603  // it might be a prototype PTE or paged out or even in transition.
2604  //
2605  if (PointerPte->u.Long == MmDecommittedPte.u.Long)
2606  {
2607  //
2608  // It's already decommited, so there's nothing for us to do here
2609  //
2610  CommitReduction++;
2611  }
2612  else
2613  {
2614  //
2615  // Remove it from the counters, and check if it was valid or not
2616  //
2617  //Process->NumberOfPrivatePages--;
2618  if (PteContents.u.Hard.Valid)
2619  {
2620  //
2621  // It's valid. At this point make sure that it is not a ROS
2622  // PFN. Also, we don't support ProtoPTEs in this code path.
2623  //
2624  Pfn1 = MiGetPfnEntry(PteContents.u.Hard.PageFrameNumber);
2625  ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
2626  ASSERT(Pfn1->u3.e1.PrototypePte == FALSE);
2627 
2628  //
2629  // Flush any pending PTEs that we had not yet flushed, if our
2630  // list has gotten too big, then add this PTE to the flush list.
2631  //
2632  if (PteCount == 256)
2633  {
2634  MiProcessValidPteList(ValidPteList, PteCount);
2635  PteCount = 0;
2636  }
2637  ValidPteList[PteCount++] = PointerPte;
2638  }
2639  else
2640  {
2641  //
2642  // We do not support any of these other scenarios at the moment
2643  //
2644  ASSERT(PteContents.u.Soft.Prototype == 0);
2645  ASSERT(PteContents.u.Soft.Transition == 0);
2646  ASSERT(PteContents.u.Soft.PageFileHigh == 0);
2647 
2648  //
2649  // So the only other possibility is that it is still a demand
2650  // zero PTE, in which case we undo the accounting we did
2651  // earlier and simply make the page decommitted.
2652  //
2653  //Process->NumberOfPrivatePages++;
2655  }
2656  }
2657  }
2658  else
2659  {
2660  //
2661  // This used to be a zero PTE and it no longer is, so we must add a
2662  // reference to the pagetable.
2663  //
2664  MiIncrementPageTableReferences(StartingAddress);
2665 
2666  //
2667  // Next, we account for decommitted PTEs and make the PTE as such
2668  //
2669  if (PointerPte > CommitPte) CommitReduction++;
2671  }
2672 
2673  //
2674  // Move to the next PTE and the next address
2675  //
2676  PointerPte++;
2677  StartingAddress = (PVOID)((ULONG_PTR)StartingAddress + PAGE_SIZE);
2678  }
2679 
2680  //
2681  // Flush any dangling PTEs from the loop in the last page table, and then
2682  // release the working set and return the commit reduction accounting.
2683  //
2684  if (PteCount) MiProcessValidPteList(ValidPteList, PteCount);
2685  MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
2686  return CommitReduction;
2687 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1214
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
union _MMPTE::@2304 u
union _MMPFN::@1778 u3
VOID NTAPI MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
Definition: virtual.c:2409
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:331
MMPFNENTRY e1
Definition: mm.h:365
#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:2488
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1144
#define ASSERT(a)
Definition: mode.c:45
ULONG64 Valid
Definition: mmtypes.h:150
ULONG64 PageFileHigh
Definition: mmtypes.h:93
#define MM_NOIRQL
Definition: miarm.h:232
Definition: mm.h:341
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:958
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:1078
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:1672
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
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:954
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:264
union _MMPTE::@2304 u
struct _MMPFN::@1778::@1784 e2
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:475
union _MMPFN::@1781 u4
union _MMPFN::@1778 u3
USHORT PageLocation
Definition: mm.h:333
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:331
MMPFNENTRY e1
Definition: mm.h:365
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG_PTR ShareCount
Definition: mm.h:358
#define USER_SHARED_DATA
Definition: pstypes.h:51
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1132
_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:1221
Definition: mm.h:341
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:958
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:386
PMMPTE PteAddress
Definition: mm.h:354
PVOID MmHighestUserAddress
Definition: rtlcompat.c:29
union _MMPFN::@1777 u2
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
PMMPTE MiHighestUserPte
Definition: mminit.c:233
#define DPRINT
Definition: sndvol32.h:71
#define PFN_FROM_PTE(v)
Definition: mm.h:92
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:325

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

◆ 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:919
union _MMPFN::@1781 u4
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:926
UCHAR KIRQL
Definition: env_spec_w32.h:591
union _MMPFN::@1776 u1
ULONG PFN_NUMBER
Definition: ke.h:9
MMSUPPORT MmSystemCacheWs
Definition: init.c:55
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1132
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1284
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:341
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:958
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:190
ULONG_PTR PteFrame
Definition: mm.h:386
ULONG WsIndex
Definition: mm.h:346
FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1240
#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
union _MMPTE::@2304 u
#define TRUE
Definition: types.h:120
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:154
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:919
FORCEINLINE USHORT MiQueryPageTableReferences(IN PVOID Address)
Definition: miarm.h:1696
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:926
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:1684
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
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
PSUBSECTION NTAPI MiLocateSubsection(IN PMMVAD Vad, IN ULONG_PTR Vpn)
Definition: section.c:574
FORCEINLINE PVOID MiPdeToAddress(PMMPTE PointerPde)
Definition: mm.h:210
#define NULL
Definition: types.h:112
VOID NTAPI MiDeletePte(IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
Definition: virtual.c: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:1411
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:1602
#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
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:1602
#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
#define DPRINT
Definition: sndvol32.h:71
_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 2010 of file section.c.

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

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

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

3298 {
3301  PVOID CurrentVa, EndAddress;
3302  PMMPTE PointerPte, LastPte;
3303  PMMPDE PointerPde;
3304 #if (_MI_PAGING_LEVELS >= 3)
3305  PMMPDE PointerPpe;
3306 #endif
3307 #if (_MI_PAGING_LEVELS == 4)
3308  PMMPDE PointerPxe;
3309 #endif
3310  PMMPFN Pfn1;
3311  NTSTATUS Status, TempStatus;
3312 
3313  /* Lock the address space */
3316 
3317  /* Make sure we still have an address space */
3319  if (CurrentProcess->VmDeleted)
3320  {
3322  goto Cleanup;
3323  }
3324 
3325  /* Check the VADs in the requested range */
3327  if (!NT_SUCCESS(Status))
3328  {
3329  goto Cleanup;
3330  }
3331 
3332  /* Enter SEH for probing */
3333  _SEH2_TRY
3334  {
3335  /* Loop all pages and probe them */
3336  CurrentVa = *BaseAddress;
3337  while (CurrentVa < EndAddress)
3338  {
3339  (void)(*(volatile CHAR*)CurrentVa);
3340  CurrentVa = (PUCHAR)CurrentVa + PAGE_SIZE;
3341  }
3342  }
3344  {
3346  goto Cleanup;
3347  }
3348  _SEH2_END;
3349 
3350  /* All pages were accessible, since we hold the address space lock, nothing
3351  can be de-committed. Assume success for now. */
3353 
3354  /* Get the PTE and PDE */
3355  PointerPte = MiAddressToPte(*BaseAddress);
3356  PointerPde = MiAddressToPde(*BaseAddress);
3357 #if (_MI_PAGING_LEVELS >= 3)
3358  PointerPpe = MiAddressToPpe(*BaseAddress);
3359 #endif
3360 #if (_MI_PAGING_LEVELS == 4)
3361  PointerPxe = MiAddressToPxe(*BaseAddress);
3362 #endif
3363 
3364  /* Get the last PTE */
3365  LastPte = MiAddressToPte((PVOID)((ULONG_PTR)EndAddress - 1));
3366 
3367  /* Lock the process working set */
3369 
3370  /* Loop the pages */
3371  do
3372  {
3373  /* Check for a page that is not accessible */
3374  while (
3375 #if (_MI_PAGING_LEVELS == 4)
3376  (PointerPxe->u.Hard.Valid == 0) ||
3377 #endif
3378 #if (_MI_PAGING_LEVELS >= 3)
3379  (PointerPpe->u.Hard.Valid == 0) ||
3380 #endif
3381  (PointerPde->u.Hard.Valid == 0) ||
3382  (PointerPte->u.Hard.Valid == 0))
3383  {
3384  /* Release process working set */
3386 
3387  /* Access the page */
3388  CurrentVa = MiPteToAddress(PointerPte);
3389 
3390  //HACK: Pass a placeholder TrapInformation so the fault handler knows we're unlocked
3391  TempStatus = MmAccessFault(TRUE, CurrentVa, KernelMode, (PVOID)(ULONG_PTR)0xBADBADA3BADBADA3ULL);
3392  if (!NT_SUCCESS(TempStatus))
3393  {
3394  // This should only happen, when remote backing storage is not accessible
3395  ASSERT(FALSE);
3396  Status = TempStatus;
3397  goto Cleanup;
3398  }
3399 
3400  /* Lock the process working set */
3402  }
3403 
3404  /* Get the PFN */
3405  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
3406  ASSERT(Pfn1 != NULL);
3407 
3408  /* Check the previous lock status */
3409  if (MI_IS_LOCKED_VA(Pfn1, MapType))
3410  {
3412  }
3413 
3414  /* Lock it */
3415  MI_LOCK_VA(Pfn1, MapType);
3416 
3417  /* Go to the next PTE */
3418  PointerPte++;
3419 
3420  /* Check if we're on a PDE boundary */
3421  if (MiIsPteOnPdeBoundary(PointerPte)) PointerPde++;
3422 #if (_MI_PAGING_LEVELS >= 3)
3423  if (MiIsPteOnPpeBoundary(PointerPte)) PointerPpe++;
3424 #endif
3425 #if (_MI_PAGING_LEVELS == 4)
3426  if (MiIsPteOnPxeBoundary(PointerPte)) PointerPxe++;
3427 #endif
3428  } while (PointerPte <= LastPte);
3429 
3430  /* Release process working set */
3432 
3433 Cleanup:
3434  /* Unlock address space */
3436 
3437  return Status;
3438 }
#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
union _MMPTE::@2304 u
NTSTATUS NTAPI MmAccessFault(IN ULONG FaultCode, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
Definition: mmfault.c:205
#define TRUE
Definition: types.h:120
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2268
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1541
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:1099
if(dx==0 &&dy==0)
Definition: linetemp.h:174
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#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:3249
#define ASSERT(a)
Definition: mode.c:45
#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:341
#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:958
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:3190
#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:1534
#define PFN_FROM_PTE(v)
Definition: mm.h:92
FORCEINLINE VOID MI_LOCK_VA(PMMPFN Pfn1, ULONG LockType)
Definition: virtual.c:3207
FORCEINLINE PMMSUPPORT MmGetCurrentAddressSpace(VOID)
Definition: mm.h:1556
#define MiIsPteOnPxeBoundary(PointerPte)
Definition: mm.h:244
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1169

Referenced by NtLockVirtualMemory(), and RunTest().

◆ MiMakePdeExistAndMakeValid()

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

Definition at line 2409 of file virtual.c.

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

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

◆ MiMakeSystemAddressValid()

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

Definition at line 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:205
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
PVOID MmPagedPoolEnd
Definition: init.c:26
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
Status
Definition: gdiplustypes.h:24
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:45
FORCEINLINE VOID MiUnlockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, OUT PBOOLEAN Safe, OUT PBOOLEAN Shared)
Definition: miarm.h:1322
#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:1355
#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:205
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:919
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:926
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 2488 of file virtual.c.

2490 {
2491  KIRQL OldIrql;
2492  ULONG i;
2493  MMPTE TempPte;
2494  PFN_NUMBER PageFrameIndex;
2495  PMMPFN Pfn1, Pfn2;
2496 
2497  //
2498  // Acquire the PFN lock and loop all the PTEs in the list
2499  //
2501  for (i = 0; i != Count; i++)
2502  {
2503  //
2504  // The PTE must currently be valid
2505  //
2506  TempPte = *ValidPteList[i];
2507  ASSERT(TempPte.u.Hard.Valid == 1);
2508 
2509  //
2510  // Get the PFN entry for the page itself, and then for its page table
2511  //
2512  PageFrameIndex = PFN_FROM_PTE(&TempPte);
2513  Pfn1 = MiGetPfnEntry(PageFrameIndex);
2514  Pfn2 = MiGetPfnEntry(Pfn1->u4.PteFrame);
2515 
2516  //
2517  // Decrement the share count on the page table, and then on the page
2518  // itself
2519  //
2520  MiDecrementShareCount(Pfn2, Pfn1->u4.PteFrame);
2521  MI_SET_PFN_DELETED(Pfn1);
2522  MiDecrementShareCount(Pfn1, PageFrameIndex);
2523 
2524  //
2525  // Make the page decommitted
2526  //
2527  MI_WRITE_INVALID_PTE(ValidPteList[i], MmDecommittedPte);
2528  }
2529 
2530  //
2531  // All the PTEs have been dereferenced and made invalid, flush the TLB now
2532  // and then release the PFN lock
2533  //
2534  KeFlushCurrentTb();
2536 }
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:919
union _MMPFN::@1781 u4
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:926
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG PFN_NUMBER
Definition: ke.h:9
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1132
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:341
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:958
#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:386
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 2130 of file virtual.c.

2135 {
2137  PMMVAD Vad;
2139  ULONG_PTR StartingAddress, EndingAddress;
2140  PMMPTE PointerPte, LastPte;
2141  PMMPDE PointerPde;
2142  MMPTE PteContents;
2143  PMMPFN Pfn1;
2144  ULONG ProtectionMask, OldProtect;
2145  BOOLEAN Committed;
2149 
2150  /* Calculate base address for the VAD */
2151  StartingAddress = (ULONG_PTR)PAGE_ALIGN((*BaseAddress));
2152  EndingAddress = (((ULONG_PTR)*BaseAddress + *NumberOfBytesToProtect - 1) | (PAGE_SIZE - 1));
2153 
2154  /* Calculate the protection mask and make sure it's valid */
2155  ProtectionMask = MiMakeProtectionMask(NewAccessProtection);
2156  if (ProtectionMask == MM_INVALID_PROTECTION)
2157  {
2158  DPRINT1("Invalid protection mask\n");
2160  }
2161 
2162  /* Check for ROS specific memory area */
2165  {
2166  /* Evil hack */
2168  BaseAddress,
2169  NumberOfBytesToProtect,
2170  NewAccessProtection,
2171  OldAccessProtection);
2172  }
2173 
2174  /* Lock the address space and make sure the process isn't already dead */
2177  if (Process->VmDeleted)
2178  {
2179  DPRINT1("Process is dying\n");
2181  goto FailPath;
2182  }
2183 
2184  /* Get the VAD for this address range, and make sure it exists */
2185  Result = MiCheckForConflictingNode(StartingAddress >> PAGE_SHIFT,
2186  EndingAddress >> PAGE_SHIFT,
2187  &Process->VadRoot,
2188  (PMMADDRESS_NODE*)&Vad);
2189  if (Result != TableFoundNode)
2190  {
2191  DPRINT("Could not find a VAD for this allocation\n");
2193  goto FailPath;
2194  }
2195 
2196  /* Make sure the address is within this VAD's boundaries */
2197  if ((((ULONG_PTR)StartingAddress >> PAGE_SHIFT) < Vad->StartingVpn) ||
2198  (((ULONG_PTR)EndingAddress >> PAGE_SHIFT) > Vad->EndingVpn))
2199  {
2201  goto FailPath;
2202  }
2203 
2204  /* These kinds of VADs are not supported atm */
2205  if ((Vad->u.VadFlags.VadType == VadAwe) ||
2207  (Vad->u.VadFlags.VadType == VadLargePages))
2208  {
2209  DPRINT1("Illegal VAD for attempting to set protection\n");
2211  goto FailPath;
2212  }
2213 
2214  /* Check for a VAD whose protection can't be changed */
2215  if (Vad->u.VadFlags.NoChange == 1)
2216  {
2217  DPRINT1("Trying to change protection of a NoChange VAD\n");
2219  goto FailPath;
2220  }
2221 
2222  /* Is this section, or private memory? */
2223  if (Vad->u.VadFlags.PrivateMemory == 0)
2224  {
2225  /* Not yet supported */
2226  if (Vad->u.VadFlags.VadType == VadLargePageSection)
2227  {
2228  DPRINT1("Illegal VAD for attempting to set protection\n");
2230  goto FailPath;
2231  }
2232 
2233  /* Rotate VADs are not yet supported */
2234  if (Vad->u.VadFlags.VadType == VadRotatePhysical)
2235  {
2236  DPRINT1("Illegal VAD for attempting to set protection\n");
2238  goto FailPath;
2239  }
2240 
2241  /* Not valid on section files */
2242  if (NewAccessProtection & (PAGE_NOCACHE | PAGE_WRITECOMBINE))
2243  {
2244  /* Fail */
2245  DPRINT1("Invalid protection flags for section\n");
2247  goto FailPath;
2248  }
2249 
2250  /* Check if data or page file mapping protection PTE is compatible */
2251  if (!Vad->ControlArea->u.Flags.Image)
2252  {
2253  /* Not yet */
2254  DPRINT1("Fixme: Not checking for valid protection\n");
2255  }
2256 
2257  /* This is a section, and this is not yet supported */
2258  DPRINT1("Section protection not yet supported\n");
2259  OldProtect = 0;
2260  }
2261  else
2262  {
2263  /* Private memory, check protection flags */
2264  if ((NewAccessProtection & PAGE_WRITECOPY) ||
2265  (NewAccessProtection & PAGE_EXECUTE_WRITECOPY))
2266  {
2267  DPRINT1("Invalid protection flags for private memory\n");
2269  goto FailPath;
2270  }
2271 
2272  /* Lock the working set */
2274 
2275  /* Check if all pages in this range are committed */
2276  Committed = MiIsEntireRangeCommitted(StartingAddress,
2277  EndingAddress,
2278  Vad,
2279  Process);
2280  if (!Committed)
2281  {
2282  /* Fail */
2283  DPRINT1("The entire range is not committed\n");
2286  goto FailPath;
2287  }
2288 
2289  /* Compute starting and ending PTE and PDE addresses */
2290  PointerPde = MiAddressToPde(StartingAddress);
2291  PointerPte = MiAddressToPte(StartingAddress);
2292  LastPte = MiAddressToPte(EndingAddress);
2293 
2294  /* Make this PDE valid */
2296 
2297  /* Save protection of the first page */
2298  if (PointerPte->u.Long != 0)
2299  {
2300  /* Capture the page protection and make the PDE valid */
2301  OldProtect = MiGetPageProtection(PointerPte);
2303  }
2304  else
2305  {
2306  /* Grab the old protection from the VAD itself */
2307  OldProtect = MmProtectToValue[Vad->u.VadFlags.Protection];
2308  }
2309 
2310  /* Loop all the PTEs now */
2311  while (PointerPte <= LastPte)
2312  {
2313  /* Check if we've crossed a PDE boundary and make the new PDE valid too */
2314  if (MiIsPteOnPdeBoundary(PointerPte))
2315  {
2316  PointerPde = MiPteToPde(PointerPte);
2318  }
2319 
2320  /* Capture the PTE and check if it was empty */
2321  PteContents = *PointerPte;
2322  if (PteContents.u.Long == 0)
2323  {
2324  /* This used to be a zero PTE and it no longer is, so we must add a
2325  reference to the pagetable. */
2327  }
2328 
2329  /* Check what kind of PTE we are dealing with */
2330  if (PteContents.u.Hard.Valid == 1)
2331  {
2332  /* Get the PFN entry */
2333  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2334 
2335  /* We don't support this yet */
2336  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
2337 
2338  /* Check if the page should not be accessible at all */
2339  if ((NewAccessProtection & PAGE_NOACCESS) ||
2340  (NewAccessProtection & PAGE_GUARD))
2341  {
2343 
2344  /* Mark the PTE as transition and change its protection */
2345  PteContents.u.Hard.Valid = 0;
2346  PteContents.u.Soft.Transition = 1;
2347  PteContents.u.Trans.Protection = ProtectionMask;
2348  /* Decrease PFN share count and write the PTE */
2349  MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
2350  // FIXME: remove the page from the WS
2351  MI_WRITE_INVALID_PTE(PointerPte, PteContents);
2352 #ifdef CONFIG_SMP
2353  // FIXME: Should invalidate entry in every CPU TLB
2354  ASSERT(FALSE);
2355 #endif
2356  KeInvalidateTlbEntry(MiPteToAddress(PointerPte));
2357 
2358  /* We are done for this PTE */
2360  }
2361  else
2362  {
2363  /* Write the protection mask and write it with a TLB flush */
2364  Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
2365  MiFlushTbAndCapture(Vad,
2366  PointerPte,
2367  ProtectionMask,
2368  Pfn1,
2369  TRUE);
2370  }
2371  }
2372  else
2373  {
2374  /* We don't support these cases yet */
2375  ASSERT(PteContents.u.Soft.Prototype == 0);
2376  //ASSERT(PteContents.u.Soft.Transition == 0);
2377 
2378  /* The PTE is already demand-zero, just update the protection mask */
2379  PteContents.u.Soft.Protection = ProtectionMask;
2380  MI_WRITE_INVALID_PTE(PointerPte, PteContents);
2381  ASSERT(PointerPte->u.Long != 0);
2382  }
2383 
2384  /* Move to the next PTE */
2385  PointerPte++;
2386  }
2387 
2388  /* Unlock the working set */
2390  }
2391 
2392  /* Unlock the address space */
2394 
2395  /* Return parameters and success */
2396  *NumberOfBytesToProtect = EndingAddress - StartingAddress + 1;
2397  *BaseAddress = (PVOID)StartingAddress;
2398  *OldAccessProtection = OldProtect;
2399  return STATUS_SUCCESS;
2400 
2401 FailPath:
2402  /* Unlock the address space and return the failure code */
2404  return Status;
2405 }
#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:219
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1214
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
union _MMPTE::@2304 u
#define TRUE
Definition: types.h:120
#define PAGE_GUARD
Definition: nt_native.h:1310
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2268
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1541
enum _TABLE_SEARCH_RESULT TABLE_SEARCH_RESULT
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:919
ULONG_PTR Protection
Definition: mmtypes.h:693
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
ULONG NTAPI MiGetPageProtection(IN PMMPTE PointerPte)
Definition: virtual.c:1367
ULONG_PTR NoChange
Definition: mmtypes.h:690
union _CONTROL_AREA::@2557 u
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:926
union _MMPFN::@1778 u3
VOID NTAPI MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
Definition: virtual.c:2409
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:331
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:365
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
const ULONG MmProtectToValue[32]
Definition: page.c:71
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define PAGE_EXECUTE_WRITECOPY
Definition: nt_native.h:1309
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:75
#define FALSE
Definition: types.h:117
PCONTROL_AREA ControlArea
Definition: mmtypes.h:733
#define PAGE_NOACCESS
Definition: nt_native.h:1302
unsigned char BOOLEAN
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1132
ULONG64 Protection
Definition: mmtypes.h:88
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
TABLE_SEARCH_RESULT NTAPI MiCheckForConflictingNode(IN ULONG_PTR StartVpn, IN ULONG_PTR EndVpn, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *NodeOrParent)
Definition: vadnode.c:78
BOOLEAN NTAPI MiIsEntireRangeCommitted(IN ULONG_PTR StartingAddress, IN ULONG_PTR EndingAddress, IN PMMVAD Vad, IN PEPROCESS Process)
Definition: virtual.c:2014
Status
Definition: gdiplustypes.h:24
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1144
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:695
#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
VOID NTAPI MiFlushTbAndCapture(IN PMMVAD FoundVad, IN PMMPTE PointerPte, IN ULONG ProtectionMask, IN PMMPFN Pfn1, IN BOOLEAN CaptureDirtyBit)
Definition: section.c:2010
_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:341
static PVOID
Definition: virtual.c:33
ULONG64 Prototype
Definition: mmtypes.h:89
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:305
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:958
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:2090
ULONG64 Transition
Definition: mmtypes.h:90
union _MMVAD::@2564 u
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
MMPTE OriginalPte
Definition: mm.h:375
#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:1672
MMSECTION_FLAGS Flags
Definition: mmtypes.h:528
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
#define STATUS_INVALID_PARAMETER_4
Definition: ntstatus.h:478
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:261
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:37
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1534
#define PFN_FROM_PTE(v)
Definition: mm.h:92
ULONG64 Protection
Definition: mmtypes.h:103
ULONG_PTR VadType
Definition: mmtypes.h:691
FORCEINLINE PMMSUPPORT MmGetCurrentAddressSpace(VOID)
Definition: mm.h:1556

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

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

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

1678 {
1679  PEPROCESS TargetProcess;
1681  PMMVAD Vad = NULL;
1682  PVOID Address, NextAddress;
1683  BOOLEAN Found = FALSE;
1684  ULONG NewProtect, NewState;
1685  ULONG_PTR BaseVpn;
1686  MEMORY_BASIC_INFORMATION MemoryInfo;
1691 
1692  /* Check for illegal addresses in user-space, or the shared memory area */
1695  {
1697 
1698  /* Make up an info structure describing this range */
1699  MemoryInfo.BaseAddress = Address;
1700  MemoryInfo.AllocationProtect = PAGE_READONLY;
1701  MemoryInfo.Type = MEM_PRIVATE;
1702 
1703  /* Special case for shared data */
1705  {
1707  MemoryInfo.State = MEM_COMMIT;
1708  MemoryInfo.Protect = PAGE_READONLY;
1709  MemoryInfo.RegionSize = PAGE_SIZE;
1710  }
1711  else
1712  {
1713  MemoryInfo.AllocationBase = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1;
1714  MemoryInfo.State = MEM_RESERVE;
1715  MemoryInfo.Protect = PAGE_NOACCESS;
1717  }
1718 
1719  /* Return the data, NtQueryInformation already probed it*/
1720  if (PreviousMode != KernelMode)
1721  {
1722  _SEH2_TRY
1723  {
1724  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1726  }
1728  {
1730  }
1731  _SEH2_END;
1732  }
1733  else
1734  {
1735  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1737  }
1738 
1739  return Status;
1740  }
1741 
1742  /* Check if this is for a local or remote process */
1744  {
1745  TargetProcess = PsGetCurrentProcess();
1746  }
1747  else
1748  {
1749  /* Reference the target process */
1752  PsProcessType,
1754  (PVOID*)&TargetProcess,
1755  NULL);
1756  if (!NT_SUCCESS(Status)) return Status;
1757 
1758  /* Attach to it now */
1759  KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
1760  }
1761 
1762  /* Lock the address space and make sure the process isn't already dead */
1763  MmLockAddressSpace(&TargetProcess->Vm);
1764  if (TargetProcess->VmDeleted)
1765  {
1766  /* Unlock the address space of the process */
1767  MmUnlockAddressSpace(&TargetProcess->Vm);
1768 
1769  /* Check if we were attached */
1771  {
1772  /* Detach and dereference the process */
1774  ObDereferenceObject(TargetProcess);
1775  }
1776 
1777  /* Bail out */
1778  DPRINT1("Process is dying\n");
1780  }
1781 
1782  /* Loop the VADs */
1783  ASSERT(TargetProcess->VadRoot.NumberGenericTableElements);
1784  if (TargetProcess->VadRoot.NumberGenericTableElements)
1785  {
1786  /* Scan on the right */
1787  Vad = (PMMVAD)TargetProcess->VadRoot.BalancedRoot.RightChild;
1788  BaseVpn = (ULONG_PTR)BaseAddress >> PAGE_SHIFT;
1789  while (Vad)
1790  {
1791  /* Check if this VAD covers the allocation range */
1792  if ((BaseVpn >= Vad->StartingVpn) &&
1793  (BaseVpn <= Vad->EndingVpn))
1794  {
1795  /* We're done */
1796  Found = TRUE;
1797  break;
1798  }
1799 
1800  /* Check if this VAD is too high */
1801  if (BaseVpn < Vad->StartingVpn)
1802  {
1803  /* Stop if there is no left child */
1804  if (!Vad->LeftChild) break;
1805 
1806  /* Search on the left next */
1807  Vad = Vad->LeftChild;
1808  }
1809  else
1810  {
1811  /* Then this VAD is too low, keep searching on the right */
1812  ASSERT(BaseVpn > Vad->EndingVpn);
1813 
1814  /* Stop if there is no right child */
1815  if (!Vad->RightChild) break;
1816 
1817  /* Search on the right next */
1818  Vad = Vad->RightChild;
1819  }
1820  }
1821  }
1822 
1823  /* Was a VAD found? */
1824  if (!Found)
1825  {
1827 
1828  /* Calculate region size */
1829  if (Vad)
1830  {
1831  if (Vad->StartingVpn >= BaseVpn)
1832  {
1833  /* Region size is the free space till the start of that VAD */
1834  MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
1835  }
1836  else
1837  {
1838  /* Get the next VAD */
1839  Vad = (PMMVAD)MiGetNextNode((PMMADDRESS_NODE)Vad);
1840  if (Vad)
1841  {
1842  /* Region size is the free space till the start of that VAD */
1843  MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
1844  }
1845  else
1846  {
1847  /* Maximum possible region size with that base address */
1848  MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
1849  }
1850  }
1851  }
1852  else
1853  {
1854  /* Maximum possible region size with that base address */
1855  MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
1856  }
1857 
1858  /* Unlock the address space of the process */
1859  MmUnlockAddressSpace(&TargetProcess->Vm);
1860 
1861  /* Check if we were attached */
1863  {
1864  /* Detach and derefernece the process */
1866  ObDereferenceObject(TargetProcess);
1867  }
1868 
1869  /* Build the rest of the initial information block */
1870  MemoryInfo.BaseAddress = Address;
1871  MemoryInfo.AllocationBase = NULL;
1872  MemoryInfo.AllocationProtect = 0;
1873  MemoryInfo.State = MEM_FREE;
1874  MemoryInfo.Protect = PAGE_NOACCESS;
1875  MemoryInfo.Type = 0;
1876 
1877  /* Return the data, NtQueryInformation already probed it*/
1878  if (PreviousMode != KernelMode)
1879  {
1880  _SEH2_TRY
1881  {
1882  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1884  }
1886  {
1888  }
1889  _SEH2_END;
1890  }
1891  else
1892  {
1893  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1895  }
1896 
1897  return Status;
1898  }
1899 
1900  /* Set the correct memory type based on what kind of VAD this is */
1901  if ((Vad->u.VadFlags.PrivateMemory) ||
1902  (Vad->u.VadFlags.VadType == VadRotatePhysical))
1903  {
1904  MemoryInfo.Type = MEM_PRIVATE;
1905  }
1906  else if (Vad->u.VadFlags.VadType == VadImageMap)
1907  {
1908  MemoryInfo.Type = MEM_IMAGE;
1909  }
1910  else
1911  {
1912  MemoryInfo.Type = MEM_MAPPED;
1913  }
1914 
1915  /* Find the memory area the specified address belongs to */
1917  ASSERT(MemoryArea != NULL);
1918 
1919  /* Determine information dependent on the memory area type */
1921  {
1923  if (!NT_SUCCESS(Status))
1924  {
1925  DPRINT1("MmQuerySectionView failed. MemoryArea=%p (%p-%p), BaseAddress=%p\n",
1928  }
1929  }
1930  else
1931  {
1932  /* Build the initial information block */
1934  MemoryInfo.BaseAddress = Address;
1935  MemoryInfo.AllocationBase = (PVOID)(Vad->StartingVpn << PAGE_SHIFT);
1937  MemoryInfo.Type = MEM_PRIVATE;
1938 
1939  /* Acquire the working set lock (shared is enough) */
1941 
1942  /* Find the largest chunk of memory which has the same state and protection mask */
1943  MemoryInfo.State = MiQueryAddressState(Address,
1944  Vad,
1945  TargetProcess,
1946  &MemoryInfo.Protect,
1947  &NextAddress);
1948  Address = NextAddress;
1949  while (((ULONG_PTR)Address >> PAGE_SHIFT) <= Vad->EndingVpn)
1950  {
1951  /* Keep going unless the state or protection mask changed */
1952  NewState = MiQueryAddressState(Address, Vad, TargetProcess, &NewProtect, &NextAddress);
1953  if ((NewState != MemoryInfo.State) || (NewProtect != MemoryInfo.Protect)) break;
1954  Address = NextAddress;
1955  }
1956 
1957  /* Release the working set lock */
1959 
1960  /* Check if we went outside of the VAD */
1961  if (((ULONG_PTR)Address >> PAGE_SHIFT) > Vad->EndingVpn)
1962  {
1963  /* Set the end of the VAD as the end address */
1964  Address = (PVOID)((Vad->EndingVpn + 1) << PAGE_SHIFT);
1965  }
1966 
1967  /* Now that we know the last VA address, calculate the region size */
1968  MemoryInfo.RegionSize = ((ULONG_PTR)Address - (ULONG_PTR)MemoryInfo.BaseAddress);
1969  }
1970 
1971  /* Unlock the address space of the process */
1972  MmUnlockAddressSpace(&TargetProcess->Vm);
1973 
1974  /* Check if we were attached */
1976  {
1977  /* Detach and derefernece the process */
1979  ObDereferenceObject(TargetProcess);
1980  }
1981 
1982  /* Return the data, NtQueryInformation already probed it */
1983  if (PreviousMode != KernelMode)
1984  {
1985  _SEH2_TRY
1986  {
1987  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
1989  }
1991  {
1993  }
1994  _SEH2_END;
1995  }
1996  else
1997  {
1998  *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
2000  }
2001 
2002  /* All went well */
2003  DPRINT("Base: %p AllocBase: %p AllocProtect: %lx Protect: %lx "
2004  "State: %lx Type: %lx Size: %lx\n",
2005  MemoryInfo.BaseAddress, MemoryInfo.AllocationBase,
2006  MemoryInfo.AllocationProtect, MemoryInfo.Protect,
2007  MemoryInfo.State, MemoryInfo.Type, MemoryInfo.RegionSize);
2008 
2009  return Status;
2010 }
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:219
#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:1190
#define TRUE
Definition: types.h:120
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1541
LONG NTSTATUS
Definition: precomp.h:26
ULONG_PTR NumberGenericTableElements
Definition: mmtypes.h:665
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3066
ULONG_PTR Protection
Definition: mmtypes.h:693
#define MM_SHARED_USER_DATA_VA
Definition: mmtypes.h:48
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
#define MEM_COMMIT
Definition: nt_native.h:1313
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
MMADDRESS_NODE BalancedRoot
Definition: mmtypes.h:659
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
NTSTATUS NTAPI MmQuerySectionView(PMEMORY_AREA MemoryArea, PVOID Address, PMEMORY_BASIC_INFORMATION Info, PSIZE_T ResultLength)
Definition: section.c:2051
const ULONG MmProtectToValue[32]
Definition: page.c:71
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c: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:724
#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
return Found
Definition: dirsup.c:1270
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
#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:1357
ULONG_PTR PrivateMemory
Definition: mmtypes.h:695
#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:213
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
PMMADDRESS_NODE NTAPI MiGetNextNode(IN PMMADDRESS_NODE Node)
Definition: vadnode.c:467
struct _MMADDRESS_NODE * RightChild
Definition: mmtypes.h:649
FORCEINLINE VOID MiLockProcessWorkingSetShared(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1121
struct _MMVAD * RightChild
Definition: mmtypes.h:725
static PVOID
Definition: virtual.c:33
#define PAGE_SIZE
Definition: env_spec_w32.h:49
KPROCESS Pcb
Definition: pstypes.h:1221
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:212
MMSUPPORT Vm
Definition: pstypes.h:1315
ULONG NTAPI MiQueryAddressState(IN PVOID Va, IN PMMVAD Vad, IN PEPROCESS TargetProcess, OUT PULONG ReturnedProtect, OUT PVOID *NextVa)
Definition: virtual.c:1482
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
union _MMVAD::@2564 u
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1602
_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
#define DPRINT
Definition: sndvol32.h:71
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
MM_AVL_TABLE VadRoot
Definition: pstypes.h:1412
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:37
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1534
struct _MMVAD * PMMVAD
POBJECT_TYPE PsProcessType
Definition: process.c:20
ULONG_PTR VadType
Definition: mmtypes.h:691

Referenced by NtQueryVirtualMemory().

◆ MiRosProtectVirtualMemory()

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

Definition at line 2090 of file virtual.c.

2095 {
2098  ULONG OldAccessProtection_;
2099  NTSTATUS Status;
2100 
2101  *NumberOfBytesToProtect = PAGE_ROUND_UP((ULONG_PTR)(*BaseAddress) + (*NumberOfBytesToProtect)) - PAGE_ROUND_DOWN(*BaseAddress);
2103 
2104  AddressSpace = &Process->Vm;
2108  {
2110  return STATUS_UNSUCCESSFUL;
2111  }
2112 
2113  if (OldAccessProtection == NULL) OldAccessProtection = &OldAccessProtection_;
2114 
2117  MemoryArea,
2118  *BaseAddress,
2119  *NumberOfBytesToProtect,
2120  NewAccessProtection,
2121  OldAccessProtection);
2122 
2124 
2125  return Status;
2126 }
ULONG Type
Definition: mm.h:219
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2268
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1541
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:221
#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:2015
unsigned int ULONG
Definition: retypes.h:1
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:37
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1534

Referenced by MiProtectVirtualMemory().

◆ MiUnlockVirtualMemory()

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

Definition at line 3613 of file virtual.c.

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