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

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 
#define HYDRA_PROCESS   (PEPROCESS)1
 
#define _BYTE_MASK(Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7)
 

Functions

static NTSTATUS NTAPI MiCheckForUserStackOverflow (IN PVOID Address, IN PVOID TrapInformation)
 
FORCEINLINE BOOLEAN MiIsAccessAllowed (_In_ ULONG ProtectionMask, _In_ BOOLEAN Write, _In_ BOOLEAN Execute)
 
static NTSTATUS NTAPI MiAccessCheck (IN PMMPTE PointerPte, IN BOOLEAN StoreInstruction, IN KPROCESSOR_MODE PreviousMode, IN ULONG_PTR ProtectionMask, IN PVOID TrapFrame, IN BOOLEAN LockHeld)
 
static PMMPTE NTAPI MiCheckVirtualAddress (IN PVOID VirtualAddress, OUT PULONG ProtectCode, OUT PMMVAD *ProtoVad)
 
NTSTATUS FASTCALL MiCheckPdeForPagedPool (IN PVOID Address)
 
VOID NTAPI MiZeroPfn (IN PFN_NUMBER PageFrameNumber)
 
VOID NTAPI MiCopyPfn (_In_ PFN_NUMBER DestPage, _In_ PFN_NUMBER SrcPage)
 
static NTSTATUS NTAPI MiResolveDemandZeroFault (IN PVOID Address, IN PMMPTE PointerPte, IN ULONG Protection, IN PEPROCESS Process, IN KIRQL OldIrql)
 
static NTSTATUS NTAPI MiCompleteProtoPteFault (IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN KIRQL OldIrql, IN PMMPFN *LockedProtoPfn)
 
static NTSTATUS NTAPI MiResolvePageFileFault (_In_ BOOLEAN StoreInstruction, _In_ PVOID FaultingAddress, _In_ PMMPTE PointerPte, _In_ PEPROCESS CurrentProcess, _Inout_ KIRQL *OldIrql)
 
static NTSTATUS NTAPI MiResolveTransitionFault (IN BOOLEAN StoreInstruction, IN PVOID FaultingAddress, IN PMMPTE PointerPte, IN PEPROCESS CurrentProcess, IN KIRQL OldIrql, OUT PKEVENT **InPageBlock)
 
static NTSTATUS NTAPI MiResolveProtoPteFault (IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN OUT PMMPFN *OutPfn, OUT PVOID *PageFileData, OUT PMMPTE PteValue, IN PEPROCESS Process, IN KIRQL OldIrql, IN PVOID TrapInformation)
 
NTSTATUS NTAPI MiDispatchFault (IN ULONG FaultCode, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN BOOLEAN Recursive, IN PEPROCESS Process, IN PVOID TrapInformation, IN PMMVAD Vad)
 
NTSTATUS NTAPI MmArmAccessFault (IN ULONG FaultCode, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
 
NTSTATUS NTAPI MmGetExecuteOptions (IN PULONG ExecuteOptions)
 
NTSTATUS NTAPI MmSetExecuteOptions (IN ULONG ExecuteOptions)
 

Macro Definition Documentation

◆ _BYTE_MASK

#define _BYTE_MASK (   Bit0,
  Bit1,
  Bit2,
  Bit3,
  Bit4,
  Bit5,
  Bit6,
  Bit7 
)
Value:
(Bit0) | ((Bit1) << 1) | ((Bit2) << 2) | ((Bit3) << 3) | \
((Bit4) << 4) | ((Bit5) << 5) | ((Bit6) << 6) | ((Bit7) << 7)

◆ HYDRA_PROCESS

#define HYDRA_PROCESS   (PEPROCESS)1

Definition at line 20 of file pagfault.c.

◆ MODULE_INVOLVED_IN_ARM3

#define MODULE_INVOLVED_IN_ARM3

Definition at line 15 of file pagfault.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file pagfault.c.

Function Documentation

◆ MiAccessCheck()

static NTSTATUS NTAPI MiAccessCheck ( IN PMMPTE  PointerPte,
IN BOOLEAN  StoreInstruction,
IN KPROCESSOR_MODE  PreviousMode,
IN ULONG_PTR  ProtectionMask,
IN PVOID  TrapFrame,
IN BOOLEAN  LockHeld 
)
static

Definition at line 168 of file pagfault.c.

174 {
175  MMPTE TempPte;
176 
177  /* Check for invalid user-mode access */
178  if ((PreviousMode == UserMode) && (PointerPte > MiHighestUserPte))
179  {
181  }
182 
183  /* Capture the PTE -- is it valid? */
184  TempPte = *PointerPte;
185  if (TempPte.u.Hard.Valid)
186  {
187  /* Was someone trying to write to it? */
188  if (StoreInstruction)
189  {
190  /* Is it writable?*/
193  {
194  /* Then there's nothing to worry about */
195  return STATUS_SUCCESS;
196  }
197 
198  /* Oops! This isn't allowed */
200  }
201 
202  /* Someone was trying to read from a valid PTE, that's fine too */
203  return STATUS_SUCCESS;
204  }
205 
206  /* Check if the protection on the page allows what is being attempted */
207  if (!MiIsAccessAllowed(ProtectionMask, StoreInstruction, FALSE))
208  {
210  }
211 
212  /* Check if this is a guard page */
213  if ((ProtectionMask & MM_PROTECT_SPECIAL) == MM_GUARDPAGE)
214  {
215  ASSERT(ProtectionMask != MM_DECOMMIT);
216 
217  /* Attached processes can't expand their stack */
219 
220  /* No support for prototype PTEs yet */
221  ASSERT(TempPte.u.Soft.Prototype == 0);
222 
223  /* Remove the guard page bit, and return a guard page violation */
224  TempPte.u.Soft.Protection = ProtectionMask & ~MM_GUARDPAGE;
225  ASSERT(TempPte.u.Long != 0);
226  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
228  }
229 
230  /* Nothing to do */
231  return STATUS_SUCCESS;
232 }
#define MM_DECOMMIT
Definition: miarm.h:64
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:182
#define MI_IS_PAGE_COPY_ON_WRITE(x)
Definition: mm.h:110
#define FALSE
Definition: types.h:117
BOOLEAN NTAPI KeIsAttachedProcess(VOID)
Definition: procobj.c:690
FORCEINLINE BOOLEAN MiIsAccessAllowed(_In_ ULONG ProtectionMask, _In_ BOOLEAN Write, _In_ BOOLEAN Execute)
Definition: pagfault.c:138
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define ASSERT(a)
Definition: mode.c:45
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define MM_GUARDPAGE
Definition: miarm.h:57
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:984
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define MM_PROTECT_SPECIAL
Definition: miarm.h:59
#define STATUS_SUCCESS
Definition: shellext.h:65
PMMPTE MiHighestUserPte
Definition: mminit.c:233

Referenced by MiResolveProtoPteFault(), and MmArmAccessFault().

◆ MiCheckForUserStackOverflow()

static NTSTATUS NTAPI MiCheckForUserStackOverflow ( IN PVOID  Address,
IN PVOID  TrapInformation 
)
static

Definition at line 30 of file pagfault.c.

32 {
33  PETHREAD CurrentThread = PsGetCurrentThread();
34  PTEB Teb = CurrentThread->Tcb.Teb;
35  PVOID StackBase, DeallocationStack, NextStackAddress;
36  SIZE_T GuaranteedSize;
38 
39  /* Do we own the address space lock? */
40  if (CurrentThread->AddressSpaceOwner == 1)
41  {
42  /* This isn't valid */
43  DPRINT1("Process owns address space lock\n");
46  }
47 
48  /* Are we attached? */
49  if (KeIsAttachedProcess())
50  {
51  /* This isn't valid */
52  DPRINT1("Process is attached\n");
54  }
55 
56  /* Read the current settings */
57  StackBase = Teb->NtTib.StackBase;
58  DeallocationStack = Teb->DeallocationStack;
59  GuaranteedSize = Teb->GuaranteedStackBytes;
60  DPRINT("Handling guard page fault with Stacks Addresses 0x%p and 0x%p, guarantee: %lx\n",
61  StackBase, DeallocationStack, GuaranteedSize);
62 
63  /* Guarantees make this code harder, for now, assume there aren't any */
64  ASSERT(GuaranteedSize == 0);
65 
66  /* So allocate only the minimum guard page size */
67  GuaranteedSize = PAGE_SIZE;
68 
69  /* Does this faulting stack address actually exist in the stack? */
70  if ((Address >= StackBase) || (Address < DeallocationStack))
71  {
72  /* That's odd... */
73  DPRINT1("Faulting address outside of stack bounds. Address=%p, StackBase=%p, DeallocationStack=%p\n",
74  Address, StackBase, DeallocationStack);
76  }
77 
78  /* This is where the stack will start now */
79  NextStackAddress = (PVOID)((ULONG_PTR)PAGE_ALIGN(Address) - GuaranteedSize);
80 
81  /* Do we have at least one page between here and the end of the stack? */
82  if (((ULONG_PTR)NextStackAddress - PAGE_SIZE) <= (ULONG_PTR)DeallocationStack)
83  {
84  /* We don't -- Trying to make this guard page valid now */
85  DPRINT1("Close to our death...\n");
86 
87  /* Calculate the next memory address */
88  NextStackAddress = (PVOID)((ULONG_PTR)PAGE_ALIGN(DeallocationStack) + GuaranteedSize);
89 
90  /* Allocate the memory */
91  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
92  &NextStackAddress,
93  0,
94  &GuaranteedSize,
95  MEM_COMMIT,
97  if (NT_SUCCESS(Status))
98  {
99  /* Success! */
100  Teb->NtTib.StackLimit = NextStackAddress;
101  }
102  else
103  {
104  DPRINT1("Failed to allocate memory\n");
105  }
106 
107  return STATUS_STACK_OVERFLOW;
108  }
109 
110  /* Don't handle this flag yet */
112 
113  /* Update the stack limit */
114  Teb->NtTib.StackLimit = (PVOID)((ULONG_PTR)NextStackAddress + GuaranteedSize);
115 
116  /* Now move the guard page to the next page */
117  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
118  &NextStackAddress,
119  0,
120  &GuaranteedSize,
121  MEM_COMMIT,
124  {
125  /* We did it! */
126  DPRINT("Guard page handled successfully for %p\n", Address);
128  }
129 
130  /* Fail, we couldn't move the guard page */
131  DPRINT1("Guard page failure: %lx\n", Status);
132  ASSERT(FALSE);
133  return STATUS_STACK_OVERFLOW;
134 }
PPEB Peb
Definition: dllmain.c:27
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define TRUE
Definition: types.h:120
#define PAGE_GUARD
Definition: nt_native.h:1310
LONG NTSTATUS
Definition: precomp.h:26
KTHREAD Tcb
Definition: pstypes.h:1103
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:182
#define MEM_COMMIT
Definition: nt_native.h:1313
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define STATUS_ALREADY_COMMITTED
Definition: ntstatus.h:270
ULONG NtGlobalFlag
Definition: ntddk_ex.h:270
#define STATUS_PAGE_FAULT_GUARD_PAGE
Definition: ntstatus.h:97
#define FALSE
Definition: types.h:117
BOOLEAN NTAPI KeIsAttachedProcess(VOID)
Definition: procobj.c:690
#define PsGetCurrentProcess
Definition: psfuncs.h:17
static WCHAR Address[46]
Definition: ping.c:68
void * PVOID
Definition: retypes.h:9
#define NtCurrentProcess()
Definition: nt_native.h:1657
Status
Definition: gdiplustypes.h:24
ULONG GuaranteedStackBytes
Definition: winternl.h:279
#define ASSERT(a)
Definition: mode.c:45
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
PVOID DeallocationStack
Definition: compat.h:737
#define PAGE_ALIGN(Va)
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define FLG_DISABLE_STACK_EXTENSION
Definition: pstypes.h:71
ULONG_PTR SIZE_T
Definition: typedefs.h:80
Definition: compat.h:694
PVOID StackBase
Definition: compat.h:571
#define STATUS_STACK_OVERFLOW
Definition: ntstatus.h:489
PVOID Teb
Definition: ketypes.h:1739
#define DPRINT1
Definition: precomp.h:8
#define ULONG_PTR
Definition: config.h:101
PVOID StackLimit
Definition: compat.h:572
#define DPRINT
Definition: sndvol32.h:71
NT_TIB NtTib
Definition: ntddk_ex.h:332
#define PAGE_READWRITE
Definition: nt_native.h:1304

Referenced by MmArmAccessFault().

◆ MiCheckPdeForPagedPool()

NTSTATUS FASTCALL MiCheckPdeForPagedPool ( IN PVOID  Address)

Definition at line 475 of file pagfault.c.

476 {
478 }
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242

Referenced by MiDeletePte(), MiInitializePfn(), MiInitializePfnAndMakePteValid(), and MmArmAccessFault().

◆ MiCheckVirtualAddress()

static PMMPTE NTAPI MiCheckVirtualAddress ( IN PVOID  VirtualAddress,
OUT PULONG  ProtectCode,
OUT PMMVAD ProtoVad 
)
static

Definition at line 237 of file pagfault.c.

240 {
241  PMMVAD Vad;
242  PMMPTE PointerPte;
243 
244  /* No prototype/section support for now */
245  *ProtoVad = NULL;
246 
247  /* User or kernel fault? */
249  {
250  /* Special case for shared data */
252  {
253  /* It's a read-only page */
254  *ProtectCode = MM_READONLY;
255  return MmSharedUserDataPte;
256  }
257 
258  /* Find the VAD, it might not exist if the address is bogus */
260  if (!Vad)
261  {
262  /* Bogus virtual address */
263  *ProtectCode = MM_NOACCESS;
264  return NULL;
265  }
266 
267  /* ReactOS does not handle physical memory VADs yet */
269 
270  /* Check if it's a section, or just an allocation */
271  if (Vad->u.VadFlags.PrivateMemory)
272  {
273  /* ReactOS does not handle AWE VADs yet */
274  ASSERT(Vad->u.VadFlags.VadType != VadAwe);
275 
276  /* This must be a TEB/PEB VAD */
277  if (Vad->u.VadFlags.MemCommit)
278  {
279  /* It's committed, so return the VAD protection */
280  *ProtectCode = (ULONG)Vad->u.VadFlags.Protection;
281  }
282  else
283  {
284  /* It has not yet been committed, so return no access */
285  *ProtectCode = MM_NOACCESS;
286  }
287 
288  /* In both cases, return no PTE */
289  return NULL;
290  }
291  else
292  {
293  /* ReactOS does not supoprt these VADs yet */
295  ASSERT(Vad->u2.VadFlags2.ExtendableFile == 0);
296 
297  /* Return the proto VAD */
298  *ProtoVad = Vad;
299 
300  /* Get the prototype PTE for this page */
301  PointerPte = (((ULONG_PTR)VirtualAddress >> PAGE_SHIFT) - Vad->StartingVpn) + Vad->FirstPrototypePte;
302  ASSERT(PointerPte != NULL);
303  ASSERT(PointerPte <= Vad->LastContiguousPte);
304 
305  /* Return the Prototype PTE and the protection for the page mapping */
306  *ProtectCode = (ULONG)Vad->u.VadFlags.Protection;
307  return PointerPte;
308  }
309  }
311  {
312  /* This should never happen, as these addresses are handled by the double-maping */
315  {
316  /* Fail such access */
317  *ProtectCode = MM_NOACCESS;
318  return NULL;
319  }
320 
321  /* Return full access rights */
322  *ProtectCode = MM_EXECUTE_READWRITE;
323  return NULL;
324  }
326  {
327  /* ReactOS does not have an image list yet, so bail out to failure case */
329  }
330 
331  /* Default case -- failure */
332  *ProtectCode = MM_NOACCESS;
333  return NULL;
334 }
#define MI_IS_PAGE_TABLE_ADDRESS(Address)
Definition: miarm.h:177
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define MI_IS_SESSION_ADDRESS(Address)
Definition: miarm.h:171
#define MM_NOACCESS
Definition: miarm.h:65
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
ULONG_PTR Protection
Definition: mmtypes.h:693
#define MM_SHARED_USER_DATA_VA
Definition: mmtypes.h:48
union _MMVAD::@2565 u2
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
#define MiAddressToPte(x)
Definition: mmx86.c:19
PMMPTE LastPteForPagedPool
Definition: mm.h:460
MM_PAGED_POOL_INFO MmPagedPoolInfo
Definition: pool.c:25
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:48
ULONG ExtendableFile
Definition: mmtypes.h:709
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
PMMPTE MmSharedUserDataPte
Definition: mminit.c:26
MMVAD_FLAGS2 VadFlags2
Definition: mmtypes.h:739
ULONG_PTR MemCommit
Definition: mmtypes.h:692
#define MM_READONLY
Definition: inbv.c:11
ULONG_PTR PrivateMemory
Definition: mmtypes.h:695
#define ASSERT(a)
Definition: mode.c:45
struct _MMPTE * PMMPTE
#define PAGE_ALIGN(Va)
LIST_ENTRY ImageList
Definition: miarm.h:499
PVOID MmPagedPoolStart
Definition: miarm.h:584
#define MM_EXECUTE_READWRITE
Definition: miarm.h:49
union _MMVAD::@2564 u
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
PMMPTE FirstPrototypePte
Definition: mmtypes.h:734
ULONG_PTR VadType
Definition: mmtypes.h:691

Referenced by MmArmAccessFault().

◆ MiCompleteProtoPteFault()

static NTSTATUS NTAPI MiCompleteProtoPteFault ( IN BOOLEAN  StoreInstruction,
IN PVOID  Address,
IN PMMPTE  PointerPte,
IN PMMPTE  PointerProtoPte,
IN KIRQL  OldIrql,
IN PMMPFN LockedProtoPfn 
)
static

Definition at line 758 of file pagfault.c.

764 {
765  MMPTE TempPte;
766  PMMPTE OriginalPte, PageTablePte;
767  ULONG_PTR Protection;
768  PFN_NUMBER PageFrameIndex;
769  PMMPFN Pfn1, Pfn2;
770  BOOLEAN OriginalProtection, DirtyPage;
771 
772  /* Must be called with an valid prototype PTE, with the PFN lock held */
774  ASSERT(PointerProtoPte->u.Hard.Valid == 1);
775 
776  /* Get the page */
777  PageFrameIndex = PFN_FROM_PTE(PointerProtoPte);
778 
779  /* Get the PFN entry and set it as a prototype PTE */
780  Pfn1 = MiGetPfnEntry(PageFrameIndex);
781  Pfn1->u3.e1.PrototypePte = 1;
782 
783  /* Increment the share count for the page table */
784  PageTablePte = MiAddressToPte(PointerPte);
785  Pfn2 = MiGetPfnEntry(PageTablePte->u.Hard.PageFrameNumber);
786  Pfn2->u2.ShareCount++;
787 
788  /* Check where we should be getting the protection information from */
789  if (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
790  {
791  /* Get the protection from the PTE, there's no real Proto PTE data */
792  Protection = PointerPte->u.Soft.Protection;
793 
794  /* Remember that we did not use the proto protection */
795  OriginalProtection = FALSE;
796  }
797  else
798  {
799  /* Get the protection from the original PTE link */
800  OriginalPte = &Pfn1->OriginalPte;
801  Protection = OriginalPte->u.Soft.Protection;
802 
803  /* Remember that we used the original protection */
804  OriginalProtection = TRUE;
805 
806  /* Check if this was a write on a read only proto */
807  if ((StoreInstruction) && !(Protection & MM_READWRITE))
808  {
809  /* Clear the flag */
810  StoreInstruction = 0;
811  }
812  }
813 
814  /* Check if this was a write on a non-COW page */
815  DirtyPage = FALSE;
816  if ((StoreInstruction) && ((Protection & MM_WRITECOPY) != MM_WRITECOPY))
817  {
818  /* Then the page should be marked dirty */
819  DirtyPage = TRUE;
820 
821  /* ReactOS check */
822  ASSERT(Pfn1->OriginalPte.u.Soft.Prototype != 0);
823  }
824 
825  /* Did we get a locked incoming PFN? */
826  if (*LockedProtoPfn)
827  {
828  /* Drop a reference */
829  ASSERT((*LockedProtoPfn)->u3.e2.ReferenceCount >= 1);
830  MiDereferencePfnAndDropLockCount(*LockedProtoPfn);
831  *LockedProtoPfn = NULL;
832  }
833 
834  /* Release the PFN lock */
836 
837  /* Remove special/caching bits */
838  Protection &= ~MM_PROTECT_SPECIAL;
839 
840  /* Setup caching */
841  if (Pfn1->u3.e1.CacheAttribute == MiWriteCombined)
842  {
843  /* Write combining, no caching */
846  }
847  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
848  {
849  /* Write through, no caching */
852  }
853 
854  /* Check if this is a kernel or user address */
856  {
857  /* Build the user PTE */
858  MI_MAKE_HARDWARE_PTE_USER(&TempPte, PointerPte, Protection, PageFrameIndex);
859  }
860  else
861  {
862  /* Build the kernel PTE */
863  MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, PageFrameIndex);
864  }
865 
866  /* Set the dirty flag if needed */
867  if (DirtyPage) MI_MAKE_DIRTY_PAGE(&TempPte);
868 
869  /* Write the PTE */
870  MI_WRITE_VALID_PTE(PointerPte, TempPte);
871 
872  /* Reset the protection if needed */
873  if (OriginalProtection) Protection = MM_ZERO_ACCESS;
874 
875  /* Return success */
876  ASSERT(PointerPte == MiAddressToPte(Address));
877  return STATUS_SUCCESS;
878 }
#define MI_PAGE_WRITE_COMBINED(x)
Definition: mm.h:103
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:965
FORCEINLINE VOID MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1598
union _MMPTE::@2304 u
#define TRUE
Definition: types.h:120
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:251
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:937
union _MMPFN::@1778 u3
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:335
MMPFNENTRY e1
Definition: mm.h:369
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
#define MM_WRITECOPY
Definition: miarm.h:48
USHORT CacheAttribute
Definition: mm.h:339
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:951
ULONG_PTR ShareCount
Definition: mm.h:362
unsigned char BOOLEAN
static WCHAR Address[46]
Definition: ping.c:68
ULONG64 Protection
Definition: mmtypes.h:88
#define MM_ZERO_ACCESS
Definition: miarm.h:43
#define ASSERT(a)
Definition: mode.c:45
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define MI_PAGE_WRITE_THROUGH(x)
Definition: mm.h:102
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define MM_READWRITE
Definition: inbv.c:12
Definition: mm.h:345
ULONG64 Prototype
Definition: mmtypes.h:89
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:969
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:822
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MI_PAGE_DISABLE_CACHE(x)
Definition: mm.h:101
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
#define NULL
Definition: types.h:112
MMPTE OriginalPte
Definition: mm.h:379
union _MMPFN::@1777 u2
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
#define MM_PROTECT_SPECIAL
Definition: miarm.h:59
#define STATUS_SUCCESS
Definition: shellext.h:65
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define MmSystemRangeStart
Definition: mm.h:32
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:806

Referenced by MiDispatchFault(), and MiResolveProtoPteFault().

◆ MiCopyPfn()

VOID NTAPI MiCopyPfn ( _In_ PFN_NUMBER  DestPage,
_In_ PFN_NUMBER  SrcPage 
)

Definition at line 529 of file pagfault.c.

532 {
533  PMMPTE SysPtes;
534  MMPTE TempPte;
535  PMMPFN DestPfn, SrcPfn;
536  PVOID DestAddress;
537  const VOID* SrcAddress;
538 
539  /* Get the PFNs */
540  DestPfn = MiGetPfnEntry(DestPage);
541  ASSERT(DestPfn);
542  SrcPfn = MiGetPfnEntry(SrcPage);
543  ASSERT(SrcPfn);
544 
545  /* Grab 2 system PTEs */
546  SysPtes = MiReserveSystemPtes(2, SystemPteSpace);
547  ASSERT(SysPtes);
548 
549  /* Initialize the destination PTE */
551  TempPte.u.Hard.PageFrameNumber = DestPage;
552 
553  /* Setup caching */
554  if (DestPfn->u3.e1.CacheAttribute == MiWriteCombined)
555  {
556  /* Write combining, no caching */
559  }
560  else if (DestPfn->u3.e1.CacheAttribute == MiNonCached)
561  {
562  /* Write through, no caching */
565  }
566 
567  /* Make the system PTE valid with our PFN */
568  MI_WRITE_VALID_PTE(&SysPtes[0], TempPte);
569 
570  /* Initialize the source PTE */
572  TempPte.u.Hard.PageFrameNumber = SrcPage;
573 
574  /* Setup caching */
575  if (SrcPfn->u3.e1.CacheAttribute == MiNonCached)
576  {
578  }
579 
580  /* Make the system PTE valid with our PFN */
581  MI_WRITE_VALID_PTE(&SysPtes[1], TempPte);
582 
583  /* Get the addresses and perform the copy */
584  DestAddress = MiPteToAddress(&SysPtes[0]);
585  SrcAddress = MiPteToAddress(&SysPtes[1]);
586  RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
587 
588  /* Now get rid of it */
589  MiReleaseSystemPtes(SysPtes, 2, SystemPteSpace);
590 }
#define MI_PAGE_WRITE_COMBINED(x)
Definition: mm.h:103
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246
union _MMPFN::@1778 u3
MMPFNENTRY e1
Definition: mm.h:369
USHORT CacheAttribute
Definition: mm.h:339
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:951
VOID NTAPI MiReleaseSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:264
#define ASSERT(a)
Definition: mode.c:45
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
MMPTE ValidKernelPte
Definition: init.c:29
#define MI_PAGE_WRITE_THROUGH(x)
Definition: mm.h:102
Definition: mm.h:345
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:969
#define MI_PAGE_DISABLE_CACHE(x)
Definition: mm.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MiResolveProtoPteFault(), and MmArmAccessFault().

◆ MiDispatchFault()

NTSTATUS NTAPI MiDispatchFault ( IN ULONG  FaultCode,
IN PVOID  Address,
IN PMMPTE  PointerPte,
IN PMMPTE  PointerProtoPte,
IN BOOLEAN  Recursive,
IN PEPROCESS  Process,
IN PVOID  TrapInformation,
IN PMMVAD  Vad 
)

Definition at line 1304 of file pagfault.c.

1312 {
1313  MMPTE TempPte;
1314  KIRQL OldIrql, LockIrql;
1315  NTSTATUS Status;
1316  PMMPTE SuperProtoPte;
1317  PMMPFN Pfn1, OutPfn = NULL;
1318  PFN_NUMBER PageFrameIndex;
1319  PFN_COUNT PteCount, ProcessedPtes;
1320  DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n",
1321  Address,
1322  Process);
1323 
1324  /* Make sure the addresses are ok */
1325  ASSERT(PointerPte == MiAddressToPte(Address));
1326 
1327  //
1328  // Make sure APCs are off and we're not at dispatch
1329  //
1331  ASSERT(OldIrql <= APC_LEVEL);
1333 
1334  //
1335  // Grab a copy of the PTE
1336  //
1337  TempPte = *PointerPte;
1338 
1339  /* Do we have a prototype PTE? */
1340  if (PointerProtoPte)
1341  {
1342  /* This should never happen */
1343  ASSERT(!MI_IS_PHYSICAL_ADDRESS(PointerProtoPte));
1344 
1345  /* Check if this is a kernel-mode address */
1346  SuperProtoPte = MiAddressToPte(PointerProtoPte);
1347  if (Address >= MmSystemRangeStart)
1348  {
1349  /* Lock the PFN database */
1350  LockIrql = MiAcquirePfnLock();
1351 
1352  /* Has the PTE been made valid yet? */
1353  if (!SuperProtoPte->u.Hard.Valid)
1354  {
1355  ASSERT(FALSE);
1356  }
1357  else if (PointerPte->u.Hard.Valid == 1)
1358  {
1359  ASSERT(FALSE);
1360  }
1361 
1362  /* Resolve the fault -- this will release the PFN lock */
1364  Address,
1365  PointerPte,
1366  PointerProtoPte,
1367  &OutPfn,
1368  NULL,
1369  NULL,
1370  Process,
1371  LockIrql,
1372  TrapInformation);
1374 
1375  /* Complete this as a transition fault */
1377  ASSERT(OldIrql <= APC_LEVEL);
1379  return Status;
1380  }
1381  else
1382  {
1383  /* We only handle the lookup path */
1384  ASSERT(PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED);
1385 
1386  /* Is there a non-image VAD? */
1387  if ((Vad) &&
1388  (Vad->u.VadFlags.VadType != VadImageMap) &&
1389  !(Vad->u2.VadFlags2.ExtendableFile))
1390  {
1391  /* One day, ReactOS will cluster faults */
1393  DPRINT("Should cluster fault, but won't\n");
1394  }
1395 
1396  /* Only one PTE to handle for now */
1397  PteCount = 1;
1398  ProcessedPtes = 0;
1399 
1400  /* Lock the PFN database */
1401  LockIrql = MiAcquirePfnLock();
1402 
1403  /* We only handle the valid path */
1404  ASSERT(SuperProtoPte->u.Hard.Valid == 1);
1405 
1406  /* Capture the PTE */
1407  TempPte = *PointerProtoPte;
1408 
1409  /* Loop to handle future case of clustered faults */
1410  while (TRUE)
1411  {
1412  /* For our current usage, this should be true */
1413  if (TempPte.u.Hard.Valid == 1)
1414  {
1415  /* Bump the share count on the PTE */
1416  PageFrameIndex = PFN_FROM_PTE(&TempPte);
1417  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1418  Pfn1->u2.ShareCount++;
1419  }
1420  else if ((TempPte.u.Soft.Prototype == 0) &&
1421  (TempPte.u.Soft.Transition == 1))
1422  {
1423  /* This is a standby page, bring it back from the cache */
1424  PageFrameIndex = TempPte.u.Trans.PageFrameNumber;
1425  DPRINT("oooh, shiny, a soft fault! 0x%lx\n", PageFrameIndex);
1426  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1428 
1429  /* Should not yet happen in ReactOS */
1430  ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
1431  ASSERT(Pfn1->u4.InPageError == 0);
1432 
1433  /* Get the page */
1434  MiUnlinkPageFromList(Pfn1);
1435 
1436  /* Bump its reference count */
1437  ASSERT(Pfn1->u2.ShareCount == 0);
1438  InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1439  Pfn1->u2.ShareCount++;
1440 
1441  /* Make it valid again */
1442  /* This looks like another macro.... */
1443  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1444  ASSERT(PointerProtoPte->u.Hard.Valid == 0);
1445  ASSERT(PointerProtoPte->u.Trans.Prototype == 0);
1446  ASSERT(PointerProtoPte->u.Trans.Transition == 1);
1447  TempPte.u.Long = (PointerProtoPte->u.Long & ~0xFFF) |
1448  MmProtectToPteMask[PointerProtoPte->u.Trans.Protection];
1449  TempPte.u.Hard.Valid = 1;
1451 
1452  /* Is the PTE writeable? */
1453  if ((Pfn1->u3.e1.Modified) &&
1456  {
1457  /* Make it dirty */
1459  }
1460  else
1461  {
1462  /* Make it clean */
1464  }
1465 
1466  /* Write the valid PTE */
1467  MI_WRITE_VALID_PTE(PointerProtoPte, TempPte);
1468  ASSERT(PointerPte->u.Hard.Valid == 0);
1469  }
1470  else
1471  {
1472  /* Page is invalid, get out of the loop */
1473  break;
1474  }
1475 
1476  /* One more done, was it the last? */
1477  if (++ProcessedPtes == PteCount)
1478  {
1479  /* Complete the fault */
1481  Address,
1482  PointerPte,
1483  PointerProtoPte,
1484  LockIrql,
1485  &OutPfn);
1486 
1487  /* THIS RELEASES THE PFN LOCK! */
1488  break;
1489  }
1490 
1491  /* No clustered faults yet */
1492  ASSERT(FALSE);
1493  }
1494 
1495  /* Did we resolve the fault? */
1496  if (ProcessedPtes)
1497  {
1498  /* Bump the transition count */
1499  InterlockedExchangeAddSizeT(&KeGetCurrentPrcb()->MmTransitionCount, ProcessedPtes);
1500  ProcessedPtes--;
1501 
1502  /* Loop all the processing we did */
1503  ASSERT(ProcessedPtes == 0);
1504 
1505  /* Complete this as a transition fault */
1507  ASSERT(OldIrql <= APC_LEVEL);
1510  }
1511 
1512  /* We did not -- PFN lock is still held, prepare to resolve prototype PTE fault */
1513  OutPfn = MI_PFN_ELEMENT(SuperProtoPte->u.Hard.PageFrameNumber);
1515  ASSERT(OutPfn->u3.e2.ReferenceCount > 1);
1516  ASSERT(PointerPte->u.Hard.Valid == 0);
1517 
1518  /* Resolve the fault -- this will release the PFN lock */
1520  Address,
1521  PointerPte,
1522  PointerProtoPte,
1523  &OutPfn,
1524  NULL,
1525  NULL,
1526  Process,
1527  LockIrql,
1528  TrapInformation);
1529  //ASSERT(Status != STATUS_ISSUE_PAGING_IO);
1530  //ASSERT(Status != STATUS_REFAULT);
1531  //ASSERT(Status != STATUS_PTE_CHANGED);
1532 
1533  /* Did the routine clean out the PFN or should we? */
1534  if (OutPfn)
1535  {
1536  /* We had a locked PFN, so acquire the PFN lock to dereference it */
1537  ASSERT(PointerProtoPte != NULL);
1539 
1540  /* Dereference the locked PFN */
1542  ASSERT(OutPfn->u3.e2.ReferenceCount >= 1);
1543 
1544  /* And now release the lock */
1546  }
1547 
1548  /* Complete this as a transition fault */
1550  ASSERT(OldIrql <= APC_LEVEL);
1552  return Status;
1553  }
1554  }
1555 
1556  /* Is this a transition PTE */
1557  if (TempPte.u.Soft.Transition)
1558  {
1559  PKEVENT* InPageBlock = NULL;
1560  PKEVENT PreviousPageEvent;
1561  KEVENT CurrentPageEvent;
1562 
1563  /* Lock the PFN database */
1564  LockIrql = MiAcquirePfnLock();
1565 
1566  /* Resolve */
1567  Status = MiResolveTransitionFault(!MI_IS_NOT_PRESENT_FAULT(FaultCode), Address, PointerPte, Process, LockIrql, &InPageBlock);
1568 
1570 
1571  if (InPageBlock != NULL)
1572  {
1573  /* Another thread is reading or writing this page. Put us into the waiting queue. */
1574  KeInitializeEvent(&CurrentPageEvent, NotificationEvent, FALSE);
1575  PreviousPageEvent = *InPageBlock;
1576  *InPageBlock = &CurrentPageEvent;
1577  }
1578 
1579  /* And now release the lock and leave*/
1580  MiReleasePfnLock(LockIrql);
1581 
1582  if (InPageBlock != NULL)
1583  {
1584  KeWaitForSingleObject(&CurrentPageEvent, WrPageIn, KernelMode, FALSE, NULL);
1585 
1586  /* Let's the chain go on */
1587  if (PreviousPageEvent)
1588  {
1589  KeSetEvent(PreviousPageEvent, IO_NO_INCREMENT, FALSE);
1590  }
1591  }
1592 
1594  ASSERT(OldIrql <= APC_LEVEL);
1596  return Status;
1597  }
1598 
1599  /* Should we page the data back in ? */
1600  if (TempPte.u.Soft.PageFileHigh != 0)
1601  {
1602  /* Lock the PFN database */
1603  LockIrql = MiAcquirePfnLock();
1604 
1605  /* Resolve */
1606  Status = MiResolvePageFileFault(!MI_IS_NOT_PRESENT_FAULT(FaultCode), Address, PointerPte, Process, &LockIrql);
1607 
1608  /* And now release the lock and leave*/
1609  MiReleasePfnLock(LockIrql);
1610 
1612  ASSERT(OldIrql <= APC_LEVEL);
1614  return Status;
1615  }
1616 
1617  //
1618  // The PTE must be invalid but not completely empty. It must also not be a
1619  // prototype a transition or a paged-out PTE as those scenarii should've been handled above.
1620  // These are all Windows checks
1621  //
1622  ASSERT(TempPte.u.Hard.Valid == 0);
1623  ASSERT(TempPte.u.Soft.Prototype == 0);
1624  ASSERT(TempPte.u.Soft.Transition == 0);
1625  ASSERT(TempPte.u.Soft.PageFileHigh == 0);
1626  ASSERT(TempPte.u.Long != 0);
1627 
1628  //
1629  // If we got this far, the PTE can only be a demand zero PTE, which is what
1630  // we want. Go handle it!
1631  //
1633  PointerPte,
1634  (ULONG)TempPte.u.Soft.Protection,
1635  Process,
1636  MM_NOIRQL);
1638  if (NT_SUCCESS(Status))
1639  {
1640  //
1641  // Make sure we're returning in a sane state and pass the status down
1642  //
1645  return Status;
1646  }
1647 
1648  //
1649  // Generate an access fault
1650  //
1651  return STATUS_ACCESS_VIOLATION;
1652 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
#define MI_IS_NOT_PRESENT_FAULT(FaultCode)
Definition: mm.h:121
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:264
FORCEINLINE VOID MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1598
union _MMPTE::@2304 u
#define MI_MAKE_ACCESSED_PAGE(x)
Definition: mm.h:100
signed short * PSHORT
Definition: retypes.h:6
ULONG PFN_COUNT
Definition: mmtypes.h:102
#define TRUE
Definition: types.h:120
static NTSTATUS NTAPI MiResolvePageFileFault(_In_ BOOLEAN StoreInstruction, _In_ PVOID FaultingAddress, _In_ PMMPTE PointerPte, _In_ PEPROCESS CurrentProcess, _Inout_ KIRQL *OldIrql)
Definition: pagfault.c:883
USHORT ReadInProgress
Definition: mm.h:333
struct _MMPFN::@1778::@1784 e2
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:251
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:930
USHORT Modified
Definition: mm.h:332
#define MI_IS_PAGE_COPY_ON_WRITE(x)
Definition: mm.h:110
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
union _MMPFN::@1781 u4
FORCEINLINE VOID MiReferenceUsedPageAndBumpLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1725
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:937
union _MMPFN::@1778 u3
USHORT PageLocation
Definition: mm.h:337
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:369
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG PFN_NUMBER
Definition: ke.h:9
const ULONG MmProtectToPteMask[32]
Definition: page.c:22
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:951
#define MI_MAKE_CLEAN_PAGE(x)
Definition: mm.h:99
ULONG_PTR ShareCount
Definition: mm.h:362
#define STATUS_PAGE_FAULT_TRANSITION
Definition: ntstatus.h:94
static WCHAR Address[46]
Definition: ping.c:68
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:45
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG64 Valid
Definition: mmtypes.h:150
#define InterlockedIncrement16
Definition: interlocked.h:206
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1557
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define MM_NOIRQL
Definition: miarm.h:236
Definition: mm.h:345
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
static NTSTATUS NTAPI MiResolveTransitionFault(IN BOOLEAN StoreInstruction, IN PVOID FaultingAddress, IN PMMPTE PointerPte, IN PEPROCESS CurrentProcess, IN KIRQL OldIrql, OUT PKEVENT **InPageBlock)
Definition: pagfault.c:971
static NTSTATUS NTAPI MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN KIRQL OldIrql, IN PMMPFN *LockedProtoPfn)
Definition: pagfault.c:758
#define NULL
Definition: types.h:112
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
union _MMPFN::@1777 u2
static NTSTATUS NTAPI MiResolveProtoPteFault(IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN OUT PMMPFN *OutPfn, OUT PVOID *PageFileData, OUT PMMPTE PteValue, IN PEPROCESS Process, IN KIRQL OldIrql, IN PVOID TrapInformation)
Definition: pagfault.c:1103
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
ULONG_PTR InPageError
Definition: mm.h:391
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
static NTSTATUS NTAPI MiResolveDemandZeroFault(IN PVOID Address, IN PMMPTE PointerPte, IN ULONG Protection, IN PEPROCESS Process, IN KIRQL OldIrql)
Definition: pagfault.c:595
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:937
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define MmSystemRangeStart
Definition: mm.h:32
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MmArmAccessFault().

◆ MiIsAccessAllowed()

FORCEINLINE BOOLEAN MiIsAccessAllowed ( _In_ ULONG  ProtectionMask,
_In_ BOOLEAN  Write,
_In_ BOOLEAN  Execute 
)

Definition at line 138 of file pagfault.c.

142 {
143  #define _BYTE_MASK(Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7) \
144  (Bit0) | ((Bit1) << 1) | ((Bit2) << 2) | ((Bit3) << 3) | \
145  ((Bit4) << 4) | ((Bit5) << 5) | ((Bit6) << 6) | ((Bit7) << 7)
146  static const UCHAR AccessAllowedMask[2][2] =
147  {
148  { // Protect 0 1 2 3 4 5 6 7
149  _BYTE_MASK(0, 1, 1, 1, 1, 1, 1, 1), // READ
150  _BYTE_MASK(0, 0, 1, 1, 0, 0, 1, 1), // EXECUTE READ
151  },
152  {
153  _BYTE_MASK(0, 0, 0, 0, 1, 1, 1, 1), // WRITE
154  _BYTE_MASK(0, 0, 0, 0, 0, 0, 1, 1), // EXECUTE WRITE
155  }
156  };
157 
158  /* We want only the lower access bits */
159  ProtectionMask &= MM_PROTECT_ACCESS;
160 
161  /* Look it up in the table */
162  return (AccessAllowedMask[Write != 0][Execute != 0] >> ProtectionMask) & 1;
163 }
#define _BYTE_MASK(Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7)
static BOOL Write(PBYTE Address, PBYTE Data, SIZE_T Size)
Definition: vmhorizon.c:15
#define MM_PROTECT_ACCESS
Definition: miarm.h:51
unsigned char UCHAR
Definition: xmlstorage.h:181
static INT Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
Definition: cmd.c:347

Referenced by MiAccessCheck().

◆ MiResolveDemandZeroFault()

static NTSTATUS NTAPI MiResolveDemandZeroFault ( IN PVOID  Address,
IN PMMPTE  PointerPte,
IN ULONG  Protection,
IN PEPROCESS  Process,
IN KIRQL  OldIrql 
)
static

Definition at line 595 of file pagfault.c.

600 {
601  PFN_NUMBER PageFrameNumber = 0;
602  MMPTE TempPte;
603  BOOLEAN NeedZero = FALSE, HaveLock = FALSE;
604  ULONG Color;
605  PMMPFN Pfn1;
606  DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
607  Address,
608  Process);
609 
610  /* Must currently only be called by paging path */
611  if ((Process > HYDRA_PROCESS) && (OldIrql == MM_NOIRQL))
612  {
613  /* Sanity check */
614  ASSERT(MI_IS_PAGE_TABLE_ADDRESS(PointerPte));
615 
616  /* No forking yet */
617  ASSERT(Process->ForkInProgress == NULL);
618 
619  /* Get process color */
621  ASSERT(Color != 0xFFFFFFFF);
622 
623  /* We'll need a zero page */
624  NeedZero = TRUE;
625  }
626  else
627  {
628  /* Check if we need a zero page */
629  NeedZero = (OldIrql != MM_NOIRQL);
630 
631  /* Session-backed image views must be zeroed */
632  if ((Process == HYDRA_PROCESS) &&
635  {
636  NeedZero = TRUE;
637  }
638 
639  /* Hardcode unknown color */
640  Color = 0xFFFFFFFF;
641  }
642 
643  /* Check if the PFN database should be acquired */
644  if (OldIrql == MM_NOIRQL)
645  {
646  /* Acquire it and remember we should release it after */
648  HaveLock = TRUE;
649  }
650 
651  /* We either manually locked the PFN DB, or already came with it locked */
653  ASSERT(PointerPte->u.Hard.Valid == 0);
654 
655  /* Assert we have enough pages */
656  ASSERT(MmAvailablePages >= 32);
657 
658 #if MI_TRACE_PFNS
659  if (UserPdeFault) MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
660  if (!UserPdeFault) MI_SET_USAGE(MI_USAGE_DEMAND_ZERO);
661 #endif
662  if (Process == HYDRA_PROCESS) MI_SET_PROCESS2("Hydra");
663  else if (Process) MI_SET_PROCESS2(Process->ImageFileName);
664  else MI_SET_PROCESS2("Kernel Demand 0");
665 
666  /* Do we need a zero page? */
667  if (Color != 0xFFFFFFFF)
668  {
669  /* Try to get one, if we couldn't grab a free page and zero it */
670  PageFrameNumber = MiRemoveZeroPageSafe(Color);
671  if (!PageFrameNumber)
672  {
673  /* We'll need a free page and zero it manually */
674  PageFrameNumber = MiRemoveAnyPage(Color);
675  NeedZero = TRUE;
676  }
677  }
678  else
679  {
680  /* Get a color, and see if we should grab a zero or non-zero page */
682  if (!NeedZero)
683  {
684  /* Process or system doesn't want a zero page, grab anything */
685  PageFrameNumber = MiRemoveAnyPage(Color);
686  }
687  else
688  {
689  /* System wants a zero page, obtain one */
690  PageFrameNumber = MiRemoveZeroPage(Color);
691  }
692  }
693 
694  /* Initialize it */
695  MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
696 
697  /* Increment demand zero faults */
698  KeGetCurrentPrcb()->MmDemandZeroCount++;
699 
700  /* Do we have the lock? */
701  if (HaveLock)
702  {
703  /* Release it */
705 
706  /* Update performance counters */
707  if (Process > HYDRA_PROCESS) Process->NumberOfPrivatePages++;
708  }
709 
710  /* Zero the page if need be */
711  if (NeedZero) MiZeroPfn(PageFrameNumber);
712 
713  /* Fault on user PDE, or fault on user PTE? */
714  if (PointerPte <= MiHighestUserPte)
715  {
716  /* User fault, build a user PTE */
718  PointerPte,
719  Protection,
720  PageFrameNumber);
721  }
722  else
723  {
724  /* This is a user-mode PDE, create a kernel PTE for it */
726  PointerPte,
727  Protection,
728  PageFrameNumber);
729  }
730 
731  /* Set it dirty if it's a writable page */
733 
734  /* Write it */
735  MI_WRITE_VALID_PTE(PointerPte, TempPte);
736 
737  /* Did we manually acquire the lock */
738  if (HaveLock)
739  {
740  /* Get the PFN entry */
741  Pfn1 = MI_PFN_ELEMENT(PageFrameNumber);
742 
743  /* Windows does these sanity checks */
744  ASSERT(Pfn1->u1.Event == 0);
745  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
746  }
747 
748  //
749  // It's all good now
750  //
751  DPRINT("Demand zero page has now been paged in\n");
753 }
#define MI_IS_PAGE_TABLE_ADDRESS(Address)
Definition: miarm.h:177
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:968
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:965
#define TRUE
Definition: types.h:120
#define HYDRA_PROCESS
Definition: pagfault.c:20
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:242
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:930
PVOID MiSessionSpaceWs
Definition: mminit.c:130
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:937
union _MMPFN::@1778 u3
struct Color Color
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:531
USHORT PrototypePte
Definition: mm.h:335
MMPFNENTRY e1
Definition: mm.h:369
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
union _MMPFN::@1776 u1
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:951
PKEVENT Event
Definition: mm.h:351
#define MI_SET_PROCESS2(x)
Definition: mm.h:291
FORCEINLINE PFN_NUMBER MiRemoveZeroPageSafe(IN ULONG Color)
Definition: miarm.h:2431
unsigned char BOOLEAN
static WCHAR Address[46]
Definition: ping.c:68
#define MI_SET_USAGE(x)
Definition: mm.h:289
#define ASSERT(a)
Definition: mode.c:45
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:243
VOID NTAPI MiZeroPfn(IN PFN_NUMBER PageFrameNumber)
Definition: pagfault.c:483
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1557
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define MM_NOIRQL
Definition: miarm.h:236
Definition: mm.h:345
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:822
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:475
PVOID MiSessionViewStart
Definition: init.c:30
#define NULL
Definition: types.h:112
#define MI_IS_SESSION_IMAGE_ADDRESS(Address)
Definition: miarm.h:168
_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
PMMPTE MiHighestUserPte
Definition: mminit.c:233
#define DPRINT
Definition: sndvol32.h:71
#define STATUS_PAGE_FAULT_DEMAND_ZERO
Definition: ntstatus.h:95
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:806

Referenced by MiDispatchFault(), MiResolveProtoPteFault(), and MmArmAccessFault().

◆ MiResolvePageFileFault()

static NTSTATUS NTAPI MiResolvePageFileFault ( _In_ BOOLEAN  StoreInstruction,
_In_ PVOID  FaultingAddress,
_In_ PMMPTE  PointerPte,
_In_ PEPROCESS  CurrentProcess,
_Inout_ KIRQL OldIrql 
)
static

Definition at line 883 of file pagfault.c.

888 {
889  ULONG Color;
892  MMPTE TempPte = *PointerPte;
893  PMMPFN Pfn1;
894  ULONG PageFileIndex = TempPte.u.Soft.PageFileLow;
895  ULONG_PTR PageFileOffset = TempPte.u.Soft.PageFileHigh;
896  ULONG Protection = TempPte.u.Soft.Protection;
897 
898  /* Things we don't support yet */
900  ASSERT(*OldIrql != MM_NOIRQL);
901 
904 
905  /* We must hold the PFN lock */
907 
908  /* Some sanity checks */
909  ASSERT(TempPte.u.Hard.Valid == 0);
910  ASSERT(TempPte.u.Soft.PageFileHigh != 0);
911  ASSERT(TempPte.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED);
912 
913  /* Get any page, it will be overwritten */
916 
917  /* Initialize this PFN */
918  MiInitializePfn(Page, PointerPte, StoreInstruction);
919 
920  /* Sets the PFN as being in IO operation */
921  Pfn1 = MI_PFN_ELEMENT(Page);
922  ASSERT(Pfn1->u1.Event == NULL);
923  ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
924  ASSERT(Pfn1->u3.e1.WriteInProgress == 0);
925  Pfn1->u3.e1.ReadInProgress = 1;
926 
927  /* We must write the PTE now as the PFN lock will be released while performing the IO operation */
928  MI_MAKE_TRANSITION_PTE(&TempPte, Page, Protection);
929 
930  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
931 
932  /* Release the PFN lock while we proceed */
934 
935  /* Do the paging IO */
936  Status = MiReadPageFile(Page, PageFileIndex, PageFileOffset);
937 
938  /* Lock the PFN database again */
940 
941  /* Nobody should have changed that while we were not looking */
942  ASSERT(Pfn1->u3.e1.ReadInProgress == 1);
943  ASSERT(Pfn1->u3.e1.WriteInProgress == 0);
944 
945  if (!NT_SUCCESS(Status))
946  {
947  /* Malheur! */
948  ASSERT(FALSE);
949  Pfn1->u4.InPageError = 1;
950  Pfn1->u1.ReadStatus = Status;
951  }
952 
953  /* And the PTE can finally be valid */
954  MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, Page);
955  MI_WRITE_VALID_PTE(PointerPte, TempPte);
956 
957  Pfn1->u3.e1.ReadInProgress = 0;
958  /* Did someone start to wait on us while we proceeded ? */
959  if (Pfn1->u1.Event)
960  {
961  /* Tell them we're done */
963  }
964 
965  return Status;
966 }
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:968
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:965
USHORT ReadInProgress
Definition: mm.h:333
#define HYDRA_PROCESS
Definition: pagfault.c:20
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI MiReadPageFile(_In_ PFN_NUMBER Page, _In_ ULONG PageFileIndex, _In_ ULONG_PTR PageFileOffset)
Definition: pagefile.c:194
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:251
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:930
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
union _MMPFN::@1781 u4
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:937
union _MMPFN::@1778 u3
struct Color Color
uint32_t ULONG_PTR
Definition: typedefs.h:65
MMPFNENTRY e1
Definition: mm.h:369
union _MMPFN::@1776 u1
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:951
#define MI_SET_PROCESS(x)
Definition: mm.h:290
PKEVENT Event
Definition: mm.h:351
FORCEINLINE VOID MI_MAKE_TRANSITION_PTE(_Out_ PMMPTE NewPte, _In_ PFN_NUMBER Page, _In_ ULONG Protection)
Definition: miarm.h:921
PFN_NUMBER Page
Definition: section.c:4757
#define MI_SET_USAGE(x)
Definition: mm.h:289
USHORT WriteInProgress
Definition: mm.h:334
Status
Definition: gdiplustypes.h:24
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:45
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:243
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1557
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define MM_NOIRQL
Definition: miarm.h:236
Definition: mm.h:345
NTSTATUS ReadStatus
Definition: mm.h:352
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:475
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:984
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
ULONG_PTR InPageError
Definition: mm.h:391
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:806

Referenced by MiDispatchFault().

◆ MiResolveProtoPteFault()

static NTSTATUS NTAPI MiResolveProtoPteFault ( IN BOOLEAN  StoreInstruction,
IN PVOID  Address,
IN PMMPTE  PointerPte,
IN PMMPTE  PointerProtoPte,
IN OUT PMMPFN OutPfn,
OUT PVOID PageFileData,
OUT PMMPTE  PteValue,
IN PEPROCESS  Process,
IN KIRQL  OldIrql,
IN PVOID  TrapInformation 
)
static

Definition at line 1103 of file pagfault.c.

1113 {
1114  MMPTE TempPte, PteContents;
1115  PMMPFN Pfn1;
1116  PFN_NUMBER PageFrameIndex;
1117  NTSTATUS Status;
1118  PKEVENT* InPageBlock = NULL;
1119  ULONG Protection;
1120 
1121  /* Must be called with an invalid, prototype PTE, with the PFN lock held */
1123  ASSERT(PointerPte->u.Hard.Valid == 0);
1124  ASSERT(PointerPte->u.Soft.Prototype == 1);
1125 
1126  /* Read the prototype PTE and check if it's valid */
1127  TempPte = *PointerProtoPte;
1128  if (TempPte.u.Hard.Valid == 1)
1129  {
1130  /* One more user of this mapped page */
1131  PageFrameIndex = PFN_FROM_PTE(&TempPte);
1132  Pfn1 = MiGetPfnEntry(PageFrameIndex);
1133  Pfn1->u2.ShareCount++;
1134 
1135  /* Call it a transition */
1136  InterlockedIncrement(&KeGetCurrentPrcb()->MmTransitionCount);
1137 
1138  /* Complete the prototype PTE fault -- this will release the PFN lock */
1139  return MiCompleteProtoPteFault(StoreInstruction,
1140  Address,
1141  PointerPte,
1142  PointerProtoPte,
1143  OldIrql,
1144  OutPfn);
1145  }
1146 
1147  /* Make sure there's some protection mask */
1148  if (TempPte.u.Long == 0)
1149  {
1150  /* Release the lock */
1151  DPRINT1("Access on reserved section?\n");
1153  return STATUS_ACCESS_VIOLATION;
1154  }
1155 
1156  /* There is no such thing as a decommitted prototype PTE */
1157  ASSERT(TempPte.u.Long != MmDecommittedPte.u.Long);
1158 
1159  /* Check for access rights on the PTE proper */
1160  PteContents = *PointerPte;
1161  if (PteContents.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED)
1162  {
1163  if (!PteContents.u.Proto.ReadOnly)
1164  {
1165  Protection = TempPte.u.Soft.Protection;
1166  }
1167  else
1168  {
1169  Protection = MM_READONLY;
1170  }
1171  /* Check for page acess in software */
1172  Status = MiAccessCheck(PointerProtoPte,
1173  StoreInstruction,
1174  KernelMode,
1175  TempPte.u.Soft.Protection,
1176  TrapInformation,
1177  TRUE);
1179  }
1180  else
1181  {
1182  Protection = PteContents.u.Soft.Protection;
1183  }
1184 
1185  /* Check for writing copy on write page */
1186  if (((Protection & MM_WRITECOPY) == MM_WRITECOPY) && StoreInstruction)
1187  {
1188  PFN_NUMBER PageFrameIndex, ProtoPageFrameIndex;
1189  ULONG Color;
1190 
1191  /* Resolve the proto fault as if it was a read operation */
1193  Address,
1194  PointerPte,
1195  PointerProtoPte,
1196  OutPfn,
1197  PageFileData,
1198  PteValue,
1199  Process,
1200  OldIrql,
1201  TrapInformation);
1202 
1203  if (!NT_SUCCESS(Status))
1204  {
1205  return Status;
1206  }
1207 
1208  /* Lock again the PFN lock, MiResolveProtoPteFault unlocked it */
1210 
1211  /* And re-read the proto PTE */
1212  TempPte = *PointerProtoPte;
1213  ASSERT(TempPte.u.Hard.Valid == 1);
1214  ProtoPageFrameIndex = PFN_FROM_PTE(&TempPte);
1215 
1218 
1219  /* Get a new page for the private copy */
1220  if (Process > HYDRA_PROCESS)
1222  else
1224 
1225  PageFrameIndex = MiRemoveAnyPage(Color);
1226 
1227  /* Perform the copy */
1228  MiCopyPfn(PageFrameIndex, ProtoPageFrameIndex);
1229 
1230  /* This will drop everything MiResolveProtoPteFault referenced */
1231  MiDeletePte(PointerPte, Address, Process, PointerProtoPte);
1232 
1233  /* Because now we use this */
1234  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1235  MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
1236 
1237  /* Fix the protection */
1238  Protection &= ~MM_WRITECOPY;
1239  Protection |= MM_READWRITE;
1241  {
1242  /* Build the user PTE */
1243  MI_MAKE_HARDWARE_PTE_USER(&PteContents, PointerPte, Protection, PageFrameIndex);
1244  }
1245  else
1246  {
1247  /* Build the kernel PTE */
1248  MI_MAKE_HARDWARE_PTE(&PteContents, PointerPte, Protection, PageFrameIndex);
1249  }
1250 
1251  /* And finally, write the valid PTE */
1252  MI_WRITE_VALID_PTE(PointerPte, PteContents);
1253 
1254  /* The caller expects us to release the PFN lock */
1256  return Status;
1257  }
1258 
1259  /* Check for clone PTEs */
1260  if (PointerPte <= MiHighestUserPte) ASSERT(Process->CloneRoot == NULL);
1261 
1262  /* We don't support mapped files yet */
1263  ASSERT(TempPte.u.Soft.Prototype == 0);
1264 
1265  /* We might however have transition PTEs */
1266  if (TempPte.u.Soft.Transition == 1)
1267  {
1268  /* Resolve the transition fault */
1269  ASSERT(OldIrql != MM_NOIRQL);
1270  Status = MiResolveTransitionFault(StoreInstruction,
1271  Address,
1272  PointerProtoPte,
1273  Process,
1274  OldIrql,
1275  &InPageBlock);
1277  }
1278  else
1279  {
1280  /* We also don't support paged out pages */
1281  ASSERT(TempPte.u.Soft.PageFileHigh == 0);
1282 
1283  /* Resolve the demand zero fault */
1285  PointerProtoPte,
1286  (ULONG)TempPte.u.Soft.Protection,
1287  Process,
1288  OldIrql);
1290  }
1291 
1292  /* Complete the prototype PTE fault -- this will release the PFN lock */
1293  ASSERT(PointerPte->u.Hard.Valid == 0);
1294  return MiCompleteProtoPteFault(StoreInstruction,
1295  Address,
1296  PointerPte,
1297  PointerProtoPte,
1298  OldIrql,
1299  OutPfn);
1300 }
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:968
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:965
union _MMPTE::@2304 u
#define TRUE
Definition: types.h:120
#define HYDRA_PROCESS
Definition: pagfault.c:20
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
static NTSTATUS NTAPI MiAccessCheck(IN PMMPTE PointerPte, IN BOOLEAN StoreInstruction, IN KPROCESSOR_MODE PreviousMode, IN ULONG_PTR ProtectionMask, IN PVOID TrapFrame, IN BOOLEAN LockHeld)
Definition: pagfault.c:168
VOID NTAPI MiCopyPfn(_In_ PFN_NUMBER DestPage, _In_ PFN_NUMBER SrcPage)
Definition: pagfault.c:529
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:242
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:251
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:930
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:937
struct Color Color
VOID NTAPI MiDeletePte(IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
Definition: virtual.c:391
#define MM_WRITECOPY
Definition: miarm.h:48
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:951
#define MI_SET_PROCESS(x)
Definition: mm.h:290
ULONG_PTR ShareCount
Definition: mm.h:362
static WCHAR Address[46]
Definition: ping.c:68
#define MI_SET_USAGE(x)
Definition: mm.h:289
ULONG64 Protection
Definition: mmtypes.h:88
Status
Definition: gdiplustypes.h:24
#define MM_READONLY
Definition: inbv.c:11
#define ASSERT(a)
Definition: mode.c:45
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:243
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1557
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define MM_READWRITE
Definition: inbv.c:12
ULONG64 PageFileHigh
Definition: mmtypes.h:93
#define MM_NOIRQL
Definition: miarm.h:236
Definition: mm.h:345
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:969
ULONG_PTR Long
Definition: mmtypes.h:215
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:822
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:475
#define InterlockedIncrement
Definition: armddk.h:53
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
static NTSTATUS NTAPI MiResolveTransitionFault(IN BOOLEAN StoreInstruction, IN PVOID FaultingAddress, IN PMMPTE PointerPte, IN PEPROCESS CurrentProcess, IN KIRQL OldIrql, OUT PKEVENT **InPageBlock)
Definition: pagfault.c:971
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
static NTSTATUS NTAPI MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN KIRQL OldIrql, IN PMMPFN *LockedProtoPfn)
Definition: pagfault.c:758
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
ULONG64 ReadOnly
Definition: mmtypes.h:119
unsigned int ULONG
Definition: retypes.h:1
union _MMPFN::@1777 u2
static NTSTATUS NTAPI MiResolveProtoPteFault(IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN OUT PMMPFN *OutPfn, OUT PVOID *PageFileData, OUT PMMPTE PteValue, IN PEPROCESS Process, IN KIRQL OldIrql, IN PVOID TrapInformation)
Definition: pagfault.c:1103
#define STATUS_SUCCESS
Definition: shellext.h:65
MMPTE MmDecommittedPte
Definition: init.c:44
PMMPTE MiHighestUserPte
Definition: mminit.c:233
static NTSTATUS NTAPI MiResolveDemandZeroFault(IN PVOID Address, IN PMMPTE PointerPte, IN ULONG Protection, IN PEPROCESS Process, IN KIRQL OldIrql)
Definition: pagfault.c:595
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define MmSystemRangeStart
Definition: mm.h:32
MMPTE_PROTOTYPE Proto
Definition: mmtypes.h:218
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:806

Referenced by MiDispatchFault().

◆ MiResolveTransitionFault()

static NTSTATUS NTAPI MiResolveTransitionFault ( IN BOOLEAN  StoreInstruction,
IN PVOID  FaultingAddress,
IN PMMPTE  PointerPte,
IN PEPROCESS  CurrentProcess,
IN KIRQL  OldIrql,
OUT PKEVENT **  InPageBlock 
)
static

Definition at line 971 of file pagfault.c.

977 {
978  PFN_NUMBER PageFrameIndex;
979  PMMPFN Pfn1;
980  MMPTE TempPte;
981  PMMPTE PointerToPteForProtoPage;
982  DPRINT("Transition fault on 0x%p with PTE 0x%p in process %s\n",
983  FaultingAddress, PointerPte, CurrentProcess->ImageFileName);
984 
985  /* Windowss does this check */
986  ASSERT(*InPageBlock == NULL);
987 
988  /* ARM3 doesn't support this path */
990 
991  /* Capture the PTE and make sure it's in transition format */
992  TempPte = *PointerPte;
993  ASSERT((TempPte.u.Soft.Valid == 0) &&
994  (TempPte.u.Soft.Prototype == 0) &&
995  (TempPte.u.Soft.Transition == 1));
996 
997  /* Get the PFN and the PFN entry */
998  PageFrameIndex = TempPte.u.Trans.PageFrameNumber;
999  DPRINT("Transition PFN: %lx\n", PageFrameIndex);
1000  Pfn1 = MiGetPfnEntry(PageFrameIndex);
1001 
1002  /* One more transition fault! */
1003  InterlockedIncrement(&KeGetCurrentPrcb()->MmTransitionCount);
1004 
1005  /* This is from ARM3 -- Windows normally handles this here */
1006  ASSERT(Pfn1->u4.InPageError == 0);
1007 
1008  /* See if we should wait before terminating the fault */
1009  if ((Pfn1->u3.e1.ReadInProgress == 1)
1010  || ((Pfn1->u3.e1.WriteInProgress == 1) && StoreInstruction))
1011  {
1012  DPRINT1("The page is currently in a page transition !\n");
1013  *InPageBlock = &Pfn1->u1.Event;
1014  if (PointerPte == Pfn1->PteAddress)
1015  {
1016  DPRINT1("And this if for this particular PTE.\n");
1017  /* The PTE will be made valid by the thread serving the fault */
1018  return STATUS_SUCCESS; // FIXME: Maybe something more descriptive
1019  }
1020  }
1021 
1022  /* Windows checks there's some free pages and this isn't an in-page error */
1023  ASSERT(MmAvailablePages > 0);
1024  ASSERT(Pfn1->u4.InPageError == 0);
1025 
1026  /* ReactOS checks for this */
1027  ASSERT(MmAvailablePages > 32);
1028 
1029  /* Was this a transition page in the valid list, or free/zero list? */
1030  if (Pfn1->u3.e1.PageLocation == ActiveAndValid)
1031  {
1032  /* All Windows does here is a bunch of sanity checks */
1033  DPRINT("Transition in active list\n");
1036  ASSERT(Pfn1->u2.ShareCount != 0);
1037  ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1038  }
1039  else
1040  {
1041  /* Otherwise, the page is removed from its list */
1042  DPRINT("Transition page in free/zero list\n");
1043  MiUnlinkPageFromList(Pfn1);
1045  }
1046 
1047  /* At this point, there should no longer be any in-page errors */
1048  ASSERT(Pfn1->u4.InPageError == 0);
1049 
1050  /* Check if this was a PFN with no more share references */
1051  if (Pfn1->u2.ShareCount == 0) MiDropLockCount(Pfn1);
1052 
1053  /* Bump the share count and make the page valid */
1054  Pfn1->u2.ShareCount++;
1055  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1056 
1057  /* Prototype PTEs are in paged pool, which itself might be in transition */
1058  if (FaultingAddress >= MmSystemRangeStart)
1059  {
1060  /* Check if this is a paged pool PTE in transition state */
1061  PointerToPteForProtoPage = MiAddressToPte(PointerPte);
1062  TempPte = *PointerToPteForProtoPage;
1063  if ((TempPte.u.Hard.Valid == 0) && (TempPte.u.Soft.Transition == 1))
1064  {
1065  /* This isn't yet supported */
1066  DPRINT1("Double transition fault not yet supported\n");
1067  ASSERT(FALSE);
1068  }
1069  }
1070 
1071  /* Build the final PTE */
1072  ASSERT(PointerPte->u.Hard.Valid == 0);
1073  ASSERT(PointerPte->u.Trans.Prototype == 0);
1074  ASSERT(PointerPte->u.Trans.Transition == 1);
1075  TempPte.u.Long = (PointerPte->u.Long & ~0xFFF) |
1076  (MmProtectToPteMask[PointerPte->u.Trans.Protection]) |
1077  MiDetermineUserGlobalPteMask(PointerPte);
1078 
1079  /* Is the PTE writeable? */
1080  if ((Pfn1->u3.e1.Modified) &&
1083  {
1084  /* Make it dirty */
1086  }
1087  else
1088  {
1089  /* Make it clean */
1091  }
1092 
1093  /* Write the valid PTE */
1094  MI_WRITE_VALID_PTE(PointerPte, TempPte);
1095 
1096  /* Return success */
1098 }
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:264
USHORT ReadInProgress
Definition: mm.h:333
struct _MMPFN::@1778::@1784 e2
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
FORCEINLINE VOID MiReferenceUnusedPageAndBumpLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1770
USHORT Modified
Definition: mm.h:332
PVOID MmPagedPoolEnd
Definition: init.c:26
#define MI_IS_PAGE_COPY_ON_WRITE(x)
Definition: mm.h:110
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
union _MMPFN::@1781 u4
union _MMPFN::@1778 u3
USHORT PageLocation
Definition: mm.h:337
MMPFNENTRY e1
Definition: mm.h:369
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
#define MiAddressToPte(x)
Definition: mmx86.c:19
union _MMPFN::@1776 u1
ULONG PFN_NUMBER
Definition: ke.h:9
const ULONG MmProtectToPteMask[32]
Definition: page.c:22
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:951
#define MI_MAKE_CLEAN_PAGE(x)
Definition: mm.h:99
ULONG_PTR ShareCount
Definition: mm.h:362
PKEVENT Event
Definition: mm.h:351
#define STATUS_PAGE_FAULT_TRANSITION
Definition: ntstatus.h:94
FORCEINLINE ULONG_PTR MiDetermineUserGlobalPteMask(IN PVOID PointerPte)
Definition: miarm.h:746
USHORT WriteInProgress
Definition: mm.h:334
ULONG CurrentProcess
Definition: shell.c:125
#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
#define MM_NOIRQL
Definition: miarm.h:236
FORCEINLINE VOID MiDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1568
Definition: mm.h:345
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:969
PVOID MmPagedPoolStart
Definition: miarm.h:584
#define InterlockedIncrement
Definition: armddk.h:53
PMMPTE PteAddress
Definition: mm.h:358
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
union _MMPFN::@1777 u2
ULONG_PTR InPageError
Definition: mm.h:391
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
#define MmSystemRangeStart
Definition: mm.h:32
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MiDispatchFault(), and MiResolveProtoPteFault().

◆ MiZeroPfn()

VOID NTAPI MiZeroPfn ( IN PFN_NUMBER  PageFrameNumber)

Definition at line 483 of file pagfault.c.

484 {
485  PMMPTE ZeroPte;
486  MMPTE TempPte;
487  PMMPFN Pfn1;
488  PVOID ZeroAddress;
489 
490  /* Get the PFN for this page */
491  Pfn1 = MiGetPfnEntry(PageFrameNumber);
492  ASSERT(Pfn1);
493 
494  /* Grab a system PTE we can use to zero the page */
495  ZeroPte = MiReserveSystemPtes(1, SystemPteSpace);
496  ASSERT(ZeroPte);
497 
498  /* Initialize the PTE for it */
500  TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
501 
502  /* Setup caching */
503  if (Pfn1->u3.e1.CacheAttribute == MiWriteCombined)
504  {
505  /* Write combining, no caching */
508  }
509  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
510  {
511  /* Write through, no caching */
514  }
515 
516  /* Make the system PTE valid with our PFN */
517  MI_WRITE_VALID_PTE(ZeroPte, TempPte);
518 
519  /* Get the address it maps to, and zero it out */
520  ZeroAddress = MiPteToAddress(ZeroPte);
521  KeZeroPages(ZeroAddress, PAGE_SIZE);
522 
523  /* Now get rid of it */
524  MiReleaseSystemPtes(ZeroPte, 1, SystemPteSpace);
525 }
#define MI_PAGE_WRITE_COMBINED(x)
Definition: mm.h:103
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246
union _MMPFN::@1778 u3
MMPFNENTRY e1
Definition: mm.h:369
USHORT CacheAttribute
Definition: mm.h:339
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:951
VOID NTAPI MiReleaseSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:264
VOID FASTCALL KeZeroPages(IN PVOID Address, IN ULONG Size)
Definition: stubs.c:91
#define ASSERT(a)
Definition: mode.c:45
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
MMPTE ValidKernelPte
Definition: init.c:29
#define MI_PAGE_WRITE_THROUGH(x)
Definition: mm.h:102
Definition: mm.h:345
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:969
#define MI_PAGE_DISABLE_CACHE(x)
Definition: mm.h:101
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MiResolveDemandZeroFault(), and MmArmAccessFault().

◆ MmArmAccessFault()

NTSTATUS NTAPI MmArmAccessFault ( IN ULONG  FaultCode,
IN PVOID  Address,
IN KPROCESSOR_MODE  Mode,
IN PVOID  TrapInformation 
)

Definition at line 1656 of file pagfault.c.

1660 {
1661  KIRQL OldIrql = KeGetCurrentIrql(), LockIrql;
1662  PMMPTE ProtoPte = NULL;
1663  PMMPTE PointerPte = MiAddressToPte(Address);
1664  PMMPDE PointerPde = MiAddressToPde(Address);
1665 #if (_MI_PAGING_LEVELS >= 3)
1666  PMMPDE PointerPpe = MiAddressToPpe(Address);
1667 #if (_MI_PAGING_LEVELS == 4)
1668  PMMPDE PointerPxe = MiAddressToPxe(Address);
1669 #endif
1670 #endif
1671  MMPTE TempPte;
1672  PETHREAD CurrentThread;
1674  NTSTATUS Status;
1675  PMMSUPPORT WorkingSet;
1676  ULONG ProtectionCode;
1677  PMMVAD Vad = NULL;
1678  PFN_NUMBER PageFrameIndex;
1679  ULONG Color;
1680  BOOLEAN IsSessionAddress;
1681  PMMPFN Pfn1;
1682  DPRINT("ARM3 FAULT AT: %p\n", Address);
1683 
1684  /* Check for page fault on high IRQL */
1685  if (OldIrql > APC_LEVEL)
1686  {
1687 #if (_MI_PAGING_LEVELS < 3)
1688  /* Could be a page table for paged pool, which we'll allow */
1689  if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)) MiSynchronizeSystemPde((PMMPDE)PointerPte);
1691 #endif
1692  /* Check if any of the top-level pages are invalid */
1693  if (
1694 #if (_MI_PAGING_LEVELS == 4)
1695  (PointerPxe->u.Hard.Valid == 0) ||
1696 #endif
1697 #if (_MI_PAGING_LEVELS >= 3)
1698  (PointerPpe->u.Hard.Valid == 0) ||
1699 #endif
1700  (PointerPde->u.Hard.Valid == 0) ||
1701  (PointerPte->u.Hard.Valid == 0))
1702  {
1703  /* This fault is not valid, print out some debugging help */
1704  DbgPrint("MM:***PAGE FAULT AT IRQL > 1 Va %p, IRQL %lx\n",
1705  Address,
1706  OldIrql);
1707  if (TrapInformation)
1708  {
1709  PKTRAP_FRAME TrapFrame = TrapInformation;
1710 #ifdef _M_IX86
1711  DbgPrint("MM:***EIP %p, EFL %p\n", TrapFrame->Eip, TrapFrame->EFlags);
1712  DbgPrint("MM:***EAX %p, ECX %p EDX %p\n", TrapFrame->Eax, TrapFrame->Ecx, TrapFrame->Edx);
1713  DbgPrint("MM:***EBX %p, ESI %p EDI %p\n", TrapFrame->Ebx, TrapFrame->Esi, TrapFrame->Edi);
1714 #elif defined(_M_AMD64)
1715  DbgPrint("MM:***RIP %p, EFL %p\n", TrapFrame->Rip, TrapFrame->EFlags);
1716  DbgPrint("MM:***RAX %p, RCX %p RDX %p\n", TrapFrame->Rax, TrapFrame->Rcx, TrapFrame->Rdx);
1717  DbgPrint("MM:***RBX %p, RSI %p RDI %p\n", TrapFrame->Rbx, TrapFrame->Rsi, TrapFrame->Rdi);
1718 #elif defined(_M_ARM)
1719  DbgPrint("MM:***PC %p\n", TrapFrame->Pc);
1720  DbgPrint("MM:***R0 %p, R1 %p R2 %p, R3 %p\n", TrapFrame->R0, TrapFrame->R1, TrapFrame->R2, TrapFrame->R3);
1721  DbgPrint("MM:***R11 %p, R12 %p SP %p, LR %p\n", TrapFrame->R11, TrapFrame->R12, TrapFrame->Sp, TrapFrame->Lr);
1722 #endif
1723  }
1724 
1725  /* Tell the trap handler to fail */
1726  return STATUS_IN_PAGE_ERROR | 0x10000000;
1727  }
1728 
1729  /* Not yet implemented in ReactOS */
1730  ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
1731  ASSERT((!MI_IS_NOT_PRESENT_FAULT(FaultCode) && MI_IS_PAGE_COPY_ON_WRITE(PointerPte)) == FALSE);
1732 
1733  /* Check if this was a write */
1734  if (MI_IS_WRITE_ACCESS(FaultCode))
1735  {
1736  /* Was it to a read-only page? */
1737  Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1738  if (!(PointerPte->u.Long & PTE_READWRITE) &&
1740  {
1741  /* Crash with distinguished bugcheck code */
1742  KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1743  (ULONG_PTR)Address,
1744  PointerPte->u.Long,
1745  (ULONG_PTR)TrapInformation,
1746  10);
1747  }
1748  }
1749 
1750  /* Nothing is actually wrong */
1751  DPRINT1("Fault at IRQL %u is ok (%p)\n", OldIrql, Address);
1752  return STATUS_SUCCESS;
1753  }
1754 
1755  /* Check for kernel fault address */
1756  if (Address >= MmSystemRangeStart)
1757  {
1758  /* Bail out, if the fault came from user mode */
1759  if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
1760 
1761 #if (_MI_PAGING_LEVELS == 2)
1762  if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)) MiSynchronizeSystemPde((PMMPDE)PointerPte);
1764 #endif
1765 
1766  /* Check if the higher page table entries are invalid */
1767  if (
1768 #if (_MI_PAGING_LEVELS == 4)
1769  /* AMD64 system, check if PXE is invalid */
1770  (PointerPxe->u.Hard.Valid == 0) ||
1771 #endif
1772 #if (_MI_PAGING_LEVELS >= 3)
1773  /* PAE/AMD64 system, check if PPE is invalid */
1774  (PointerPpe->u.Hard.Valid == 0) ||
1775 #endif
1776  /* Always check if the PDE is valid */
1777  (PointerPde->u.Hard.Valid == 0))
1778  {
1779  /* PXE/PPE/PDE (still) not valid, kill the system */
1780  KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
1781  (ULONG_PTR)Address,
1782  FaultCode,
1783  (ULONG_PTR)TrapInformation,
1784  2);
1785  }
1786 
1787  /* Not handling session faults yet */
1788  IsSessionAddress = MI_IS_SESSION_ADDRESS(Address);
1789 
1790  /* The PDE is valid, so read the PTE */
1791  TempPte = *PointerPte;
1792  if (TempPte.u.Hard.Valid == 1)
1793  {
1794  /* Check if this was system space or session space */
1795  if (!IsSessionAddress)
1796  {
1797  /* Check if the PTE is still valid under PFN lock */
1799  TempPte = *PointerPte;
1800  if (TempPte.u.Hard.Valid)
1801  {
1802  /* Check if this was a write */
1803  if (MI_IS_WRITE_ACCESS(FaultCode))
1804  {
1805  /* Was it to a read-only page? */
1806  Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1807  if (!(PointerPte->u.Long & PTE_READWRITE) &&
1809  {
1810  /* Crash with distinguished bugcheck code */
1811  KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1812  (ULONG_PTR)Address,
1813  PointerPte->u.Long,
1814  (ULONG_PTR)TrapInformation,
1815  11);
1816  }
1817  }
1818 
1819  /* Check for execution of non-executable memory */
1820  if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
1822  {
1823  KeBugCheckEx(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY,
1824  (ULONG_PTR)Address,
1825  (ULONG_PTR)TempPte.u.Long,
1826  (ULONG_PTR)TrapInformation,
1827  1);
1828  }
1829  }
1830 
1831  /* Release PFN lock and return all good */
1833  return STATUS_SUCCESS;
1834  }
1835  }
1836 #if (_MI_PAGING_LEVELS == 2)
1837  /* Check if this was a session PTE that needs to remap the session PDE */
1839  {
1840  /* Do the remapping */
1841  Status = MiCheckPdeForSessionSpace(Address);
1842  if (!NT_SUCCESS(Status))
1843  {
1844  /* It failed, this address is invalid */
1845  KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
1846  (ULONG_PTR)Address,
1847  FaultCode,
1848  (ULONG_PTR)TrapInformation,
1849  6);
1850  }
1851  }
1852 #else
1853 
1854 _WARN("Session space stuff is not implemented yet!")
1855 
1856 #endif
1857 
1858  /* Check for a fault on the page table or hyperspace */
1860  {
1861 #if (_MI_PAGING_LEVELS < 3)
1862  /* Windows does this check but I don't understand why -- it's done above! */
1864 #endif
1865  /* Handle this as a user mode fault */
1866  goto UserFault;
1867  }
1868 
1869  /* Get the current thread */
1870  CurrentThread = PsGetCurrentThread();
1871 
1872  /* What kind of address is this */
1873  if (!IsSessionAddress)
1874  {
1875  /* Use the system working set */
1876  WorkingSet = &MmSystemCacheWs;
1877  CurrentProcess = NULL;
1878 
1879  /* Make sure we don't have a recursive working set lock */
1880  if ((CurrentThread->OwnsProcessWorkingSetExclusive) ||
1881  (CurrentThread->OwnsProcessWorkingSetShared) ||
1882  (CurrentThread->OwnsSystemWorkingSetExclusive) ||
1883  (CurrentThread->OwnsSystemWorkingSetShared) ||
1884  (CurrentThread->OwnsSessionWorkingSetExclusive) ||
1885  (CurrentThread->OwnsSessionWorkingSetShared))
1886  {
1887  /* Fail */
1888  return STATUS_IN_PAGE_ERROR | 0x10000000;
1889  }
1890  }
1891  else
1892  {
1893  /* Use the session process and working set */
1895  WorkingSet = &MmSessionSpace->GlobalVirtualAddress->Vm;
1896 
1897  /* Make sure we don't have a recursive working set lock */
1898  if ((CurrentThread->OwnsSessionWorkingSetExclusive) ||
1899  (CurrentThread->OwnsSessionWorkingSetShared))
1900  {
1901  /* Fail */
1902  return STATUS_IN_PAGE_ERROR | 0x10000000;
1903  }
1904  }
1905 
1906  /* Acquire the working set lock */
1907  KeRaiseIrql(APC_LEVEL, &LockIrql);
1908  MiLockWorkingSet(CurrentThread, WorkingSet);
1909 
1910  /* Re-read PTE now that we own the lock */
1911  TempPte = *PointerPte;
1912  if (TempPte.u.Hard.Valid == 1)
1913  {
1914  /* Check if this was a write */
1915  if (MI_IS_WRITE_ACCESS(FaultCode))
1916  {
1917  /* Was it to a read-only page that is not copy on write? */
1918  Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1919  if (!(TempPte.u.Long & PTE_READWRITE) &&
1920  !(Pfn1->OriginalPte.u.Soft.Protection & MM_READWRITE) &&
1922  {
1923  /* Case not yet handled */
1924  ASSERT(!IsSessionAddress);
1925 
1926  /* Crash with distinguished bugcheck code */
1927  KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1928  (ULONG_PTR)Address,
1929  TempPte.u.Long,
1930  (ULONG_PTR)TrapInformation,
1931  12);
1932  }
1933  }
1934 
1935  /* Check for execution of non-executable memory */
1936  if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
1938  {
1939  KeBugCheckEx(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY,
1940  (ULONG_PTR)Address,
1941  (ULONG_PTR)TempPte.u.Long,
1942  (ULONG_PTR)TrapInformation,
1943  2);
1944  }
1945 
1946  /* Check for read-only write in session space */
1947  if ((IsSessionAddress) &&
1948  MI_IS_WRITE_ACCESS(FaultCode) &&
1950  {
1951  /* Sanity check */
1953 
1954  /* Was this COW? */
1956  {
1957  /* Then this is not allowed */
1958  KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1959  (ULONG_PTR)Address,
1960  (ULONG_PTR)TempPte.u.Long,
1961  (ULONG_PTR)TrapInformation,
1962  13);
1963  }
1964 
1965  /* Otherwise, handle COW */
1966  ASSERT(FALSE);
1967  }
1968 
1969  /* Release the working set */
1970  MiUnlockWorkingSet(CurrentThread, WorkingSet);
1971  KeLowerIrql(LockIrql);
1972 
1973  /* Otherwise, the PDE was probably invalid, and all is good now */
1974  return STATUS_SUCCESS;
1975  }
1976 
1977  /* Check one kind of prototype PTE */
1978  if (TempPte.u.Soft.Prototype)
1979  {
1980  /* Make sure protected pool is on, and that this is a pool address */
1982  (((Address >= MmNonPagedPoolStart) &&
1986  (Address < MmNonPagedPoolEnd))))
1987  {
1988  /* Bad boy, bad boy, whatcha gonna do, whatcha gonna do when ARM3 comes for you! */
1989  KeBugCheckEx(DRIVER_CAUGHT_MODIFYING_FREED_POOL,
1990  (ULONG_PTR)Address,
1991  FaultCode,
1992  Mode,
1993  4);
1994  }
1995 
1996  /* Get the prototype PTE! */
1997  ProtoPte = MiProtoPteToPte(&TempPte);
1998 
1999  /* Do we need to locate the prototype PTE in session space? */
2000  if ((IsSessionAddress) &&
2001  (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED))
2002  {
2003  /* Yep, go find it as well as the VAD for it */
2004  ProtoPte = MiCheckVirtualAddress(Address,
2005  &ProtectionCode,
2006  &Vad);
2007  ASSERT(ProtoPte != NULL);
2008  }
2009  }
2010  else
2011  {
2012  /* We don't implement transition PTEs */
2013  ASSERT(TempPte.u.Soft.Transition == 0);
2014 
2015  /* Check for no-access PTE */
2016  if (TempPte.u.Soft.Protection == MM_NOACCESS)
2017  {
2018  /* Bugcheck the system! */
2019  KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
2020  (ULONG_PTR)Address,
2021  FaultCode,
2022  (ULONG_PTR)TrapInformation,
2023  1);
2024  }
2025 
2026  /* Check for no protecton at all */
2027  if (TempPte.u.Soft.Protection == MM_ZERO_ACCESS)
2028  {
2029  /* Bugcheck the system! */
2030  KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
2031  (ULONG_PTR)Address,
2032  FaultCode,
2033  (ULONG_PTR)TrapInformation,
2034  0);
2035  }
2036  }
2037 
2038  /* Check for demand page */
2039  if (MI_IS_WRITE_ACCESS(FaultCode) &&
2040  !(ProtoPte) &&
2041  !(IsSessionAddress) &&
2042  !(TempPte.u.Hard.Valid))
2043  {
2044  /* Get the protection code */
2045  ASSERT(TempPte.u.Soft.Transition == 0);
2046  if (!(TempPte.u.Soft.Protection & MM_READWRITE))
2047  {
2048  /* Bugcheck the system! */
2049  KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
2050  (ULONG_PTR)Address,
2051  TempPte.u.Long,
2052  (ULONG_PTR)TrapInformation,
2053  14);
2054  }
2055  }
2056 
2057  /* Now do the real fault handling */
2058  Status = MiDispatchFault(FaultCode,
2059  Address,
2060  PointerPte,
2061  ProtoPte,
2062  FALSE,
2064  TrapInformation,
2065  NULL);
2066 
2067  /* Release the working set */
2069  MiUnlockWorkingSet(CurrentThread, WorkingSet);
2070  KeLowerIrql(LockIrql);
2071 
2072  /* We are done! */
2073  DPRINT("Fault resolved with status: %lx\n", Status);
2074  return Status;
2075  }
2076 
2077  /* This is a user fault */
2078 UserFault:
2079  CurrentThread = PsGetCurrentThread();
2080  CurrentProcess = (PEPROCESS)CurrentThread->Tcb.ApcState.Process;
2081 
2082  /* Lock the working set */
2083  MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
2084 
2085  ProtectionCode = MM_INVALID_PROTECTION;
2086 
2087 #if (_MI_PAGING_LEVELS == 4)
2088  /* Check if the PXE is valid */
2089  if (PointerPxe->u.Hard.Valid == 0)
2090  {
2091  /* Right now, we only handle scenarios where the PXE is totally empty */
2092  ASSERT(PointerPxe->u.Long == 0);
2093 
2094  /* This is only possible for user mode addresses! */
2095  ASSERT(PointerPte <= MiHighestUserPte);
2096 
2097  /* Check if we have a VAD */
2098  MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2099  if (ProtectionCode == MM_NOACCESS)
2100  {
2101  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2102  return STATUS_ACCESS_VIOLATION;
2103  }
2104 
2105  /* Resolve a demand zero fault */
2106  MiResolveDemandZeroFault(PointerPpe,
2107  PointerPxe,
2110  MM_NOIRQL);
2111 
2112  /* We should come back with a valid PXE */
2113  ASSERT(PointerPxe->u.Hard.Valid == 1);
2114  }
2115 #endif
2116 
2117 #if (_MI_PAGING_LEVELS >= 3)
2118  /* Check if the PPE is valid */
2119  if (PointerPpe->u.Hard.Valid == 0)
2120  {
2121  /* Right now, we only handle scenarios where the PPE is totally empty */
2122  ASSERT(PointerPpe->u.Long == 0);
2123 
2124  /* This is only possible for user mode addresses! */
2125  ASSERT(PointerPte <= MiHighestUserPte);
2126 
2127  /* Check if we have a VAD, unless we did this already */
2128  if (ProtectionCode == MM_INVALID_PROTECTION)
2129  {
2130  MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2131  }
2132 
2133  if (ProtectionCode == MM_NOACCESS)
2134  {
2135  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2136  return STATUS_ACCESS_VIOLATION;
2137  }
2138 
2139  /* Resolve a demand zero fault */
2140  MiResolveDemandZeroFault(PointerPde,
2141  PointerPpe,
2144  MM_NOIRQL);
2145 
2146  /* We should come back with a valid PPE */
2147  ASSERT(PointerPpe->u.Hard.Valid == 1);
2148  }
2149 #endif
2150 
2151  /* Check if the PDE is invalid */
2152  if (PointerPde->u.Hard.Valid == 0)
2153  {
2154  /* Right now, we only handle scenarios where the PDE is totally empty */
2155  ASSERT(PointerPde->u.Long == 0);
2156 
2157  /* And go dispatch the fault on the PDE. This should handle the demand-zero */
2158 #if MI_TRACE_PFNS
2159  UserPdeFault = TRUE;
2160 #endif
2161  /* Check if we have a VAD, unless we did this already */
2162  if (ProtectionCode == MM_INVALID_PROTECTION)
2163  {
2164  MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2165  }
2166 
2167  if (ProtectionCode == MM_NOACCESS)
2168  {
2169 #if (_MI_PAGING_LEVELS == 2)
2170  /* Could be a page table for paged pool */
2172 #endif
2173  /* Has the code above changed anything -- is this now a valid PTE? */
2174  Status = (PointerPde->u.Hard.Valid == 1) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
2175 
2176  /* Either this was a bogus VA or we've fixed up a paged pool PDE */
2177  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2178  return Status;
2179  }
2180 
2181  /* Resolve a demand zero fault */
2182  MiResolveDemandZeroFault(PointerPte,
2183  PointerPde,
2186  MM_NOIRQL);
2187 #if MI_TRACE_PFNS
2188  UserPdeFault = FALSE;
2189 #endif
2190  /* We should come back with APCs enabled, and with a valid PDE */
2192  ASSERT(PointerPde->u.Hard.Valid == 1);
2193  }
2194  else
2195  {
2196  /* Not yet implemented in ReactOS */
2197  ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
2198  }
2199 
2200  /* Now capture the PTE. */
2201  TempPte = *PointerPte;
2202 
2203  /* Check if the PTE is valid */
2204  if (TempPte.u.Hard.Valid)
2205  {
2206  /* Check if this is a write on a readonly PTE */
2207  if (MI_IS_WRITE_ACCESS(FaultCode))
2208  {
2209  /* Is this a copy on write PTE? */
2211  {
2212  PFN_NUMBER PageFrameIndex, OldPageFrameIndex;
2213  PMMPFN Pfn1;
2214 
2215  LockIrql = MiAcquirePfnLock();
2216 
2217  ASSERT(MmAvailablePages > 0);
2218 
2221 
2222  /* Allocate a new page and copy it */
2224  OldPageFrameIndex = PFN_FROM_PTE(&TempPte);
2225 
2226  MiCopyPfn(PageFrameIndex, OldPageFrameIndex);
2227 
2228  /* Dereference whatever this PTE is referencing */
2229  Pfn1 = MI_PFN_ELEMENT(OldPageFrameIndex);
2230  ASSERT(Pfn1->u3.e1.PrototypePte == 1);
2231  ASSERT(!MI_IS_PFN_DELETED(Pfn1));
2232  ProtoPte = Pfn1->PteAddress;
2233  MiDeletePte(PointerPte, Address, CurrentProcess, ProtoPte);
2234 
2235  /* And make a new shiny one with our page */
2236  MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
2237  TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
2238  TempPte.u.Hard.Write = 1;
2239  TempPte.u.Hard.CopyOnWrite = 0;
2240 
2241  MI_WRITE_VALID_PTE(PointerPte, TempPte);
2242 
2243  MiReleasePfnLock(LockIrql);
2244 
2245  /* Return the status */
2246  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2248  }
2249 
2250  /* Is this a read-only PTE? */
2252  {
2253  /* Return the status */
2254  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2255  return STATUS_ACCESS_VIOLATION;
2256  }
2257  }
2258 
2259  /* Check for execution of non-executable memory */
2260  if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
2262  {
2263  /* Return the status */
2264  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2265  return STATUS_ACCESS_VIOLATION;
2266  }
2267 
2268  /* The fault has already been resolved by a different thread */
2269  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2270  return STATUS_SUCCESS;
2271  }
2272 
2273  /* Quick check for demand-zero */
2274  if ((TempPte.u.Long == (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS)) ||
2276  {
2277  /* Resolve the fault */
2279  PointerPte,
2280  TempPte.u.Soft.Protection,
2282  MM_NOIRQL);
2283 
2284  /* Return the status */
2285  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2287  }
2288 
2289  /* Check for zero PTE */
2290  if (TempPte.u.Long == 0)
2291  {
2292  /* Check if this address range belongs to a valid allocation (VAD) */
2293  ProtoPte = MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2294  if (ProtectionCode == MM_NOACCESS)
2295  {
2296 #if (_MI_PAGING_LEVELS == 2)
2297  /* Could be a page table for paged pool */
2299 #endif
2300  /* Has the code above changed anything -- is this now a valid PTE? */
2301  Status = (PointerPte->u.Hard.Valid == 1) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
2302 
2303  /* Either this was a bogus VA or we've fixed up a paged pool PDE */
2304  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2305  return Status;
2306  }
2307 
2308  /*
2309  * Check if this is a real user-mode address or actually a kernel-mode
2310  * page table for a user mode address
2311  */
2313  {
2314  /* Add an additional page table reference */
2316  }
2317 
2318  /* Is this a guard page? */
2319  if ((ProtectionCode & MM_PROTECT_SPECIAL) == MM_GUARDPAGE)
2320  {
2321  /* The VAD protection cannot be MM_DECOMMIT! */
2322  ASSERT(ProtectionCode != MM_DECOMMIT);
2323 
2324  /* Remove the bit */
2325  TempPte.u.Soft.Protection = ProtectionCode & ~MM_GUARDPAGE;
2326  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2327 
2328  /* Not supported */
2329  ASSERT(ProtoPte == NULL);
2330  ASSERT(CurrentThread->ApcNeeded == 0);
2331 
2332  /* Drop the working set lock */
2333  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2335 
2336  /* Handle stack expansion */
2337  return MiCheckForUserStackOverflow(Address, TrapInformation);
2338  }
2339 
2340  /* Did we get a prototype PTE back? */
2341  if (!ProtoPte)
2342  {
2343  /* Is this PTE actually part of the PDE-PTE self-mapping directory? */
2344  if (PointerPde == MiAddressToPde(PTE_BASE))
2345  {
2346  /* Then it's really a demand-zero PDE (on behalf of user-mode) */
2347 #ifdef _M_ARM
2348  _WARN("This is probably completely broken!");
2350 #else
2351  MI_WRITE_INVALID_PDE(PointerPte, DemandZeroPde);
2352 #endif
2353  }
2354  else
2355  {
2356  /* No, create a new PTE. First, write the protection */
2357  TempPte.u.Soft.Protection = ProtectionCode;
2358  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2359  }
2360 
2361  /* Lock the PFN database since we're going to grab a page */
2363 
2364  /* Make sure we have enough pages */
2365  ASSERT(MmAvailablePages >= 32);
2366 
2367  /* Try to get a zero page */
2369  MI_SET_PROCESS2(CurrentProcess->ImageFileName);
2371  PageFrameIndex = MiRemoveZeroPageSafe(Color);
2372  if (!PageFrameIndex)
2373  {
2374  /* Grab a page out of there. Later we should grab a colored zero page */
2375  PageFrameIndex = MiRemoveAnyPage(Color);
2376  ASSERT(PageFrameIndex);
2377 
2378  /* Release the lock since we need to do some zeroing */
2380 
2381  /* Zero out the page, since it's for user-mode */
2382  MiZeroPfn(PageFrameIndex);
2383 
2384  /* Grab the lock again so we can initialize the PFN entry */
2386  }
2387 
2388  /* Initialize the PFN entry now */
2389  MiInitializePfn(PageFrameIndex, PointerPte, 1);
2390 
2391  /* Increment the count of pages in the process */
2392  CurrentProcess->NumberOfPrivatePages++;
2393 
2394  /* One more demand-zero fault */
2395  KeGetCurrentPrcb()->MmDemandZeroCount++;
2396 
2397  /* And we're done with the lock */
2399 
2400  /* Fault on user PDE, or fault on user PTE? */
2401  if (PointerPte <= MiHighestUserPte)
2402  {
2403  /* User fault, build a user PTE */
2405  PointerPte,
2406  PointerPte->u.Soft.Protection,
2407  PageFrameIndex);
2408  }
2409  else
2410  {
2411  /* This is a user-mode PDE, create a kernel PTE for it */
2413  PointerPte,
2414  PointerPte->u.Soft.Protection,
2415  PageFrameIndex);
2416  }
2417 
2418  /* Write the dirty bit for writeable pages */
2420 
2421  /* And now write down the PTE, making the address valid */
2422  MI_WRITE_VALID_PTE(PointerPte, TempPte);
2423  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
2424  ASSERT(Pfn1->u1.Event == NULL);
2425 
2426  /* Demand zero */
2428  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2430  }
2431 
2432  /* We should have a valid protection here */
2433  ASSERT(ProtectionCode != 0x100);
2434 
2435  /* Write the prototype PTE */
2437  TempPte.u.Soft.Protection = ProtectionCode;
2438  ASSERT(TempPte.u.Long != 0);
2439  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2440  }
2441  else
2442  {
2443  /* Get the protection code and check if this is a proto PTE */
2444  ProtectionCode = (ULONG)TempPte.u.Soft.Protection;
2445  if (TempPte.u.Soft.Prototype)
2446  {
2447  /* Do we need to go find the real PTE? */
2448  if (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
2449  {
2450  /* Get the prototype pte and VAD for it */
2451  ProtoPte = MiCheckVirtualAddress(Address,
2452  &ProtectionCode,
2453  &Vad);
2454  if (!ProtoPte)
2455  {
2457  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2458  return STATUS_ACCESS_VIOLATION;
2459  }
2460  }
2461  else
2462  {
2463  /* Get the prototype PTE! */
2464  ProtoPte = MiProtoPteToPte(&TempPte);
2465 
2466  /* Is it read-only */
2467  if (TempPte.u.Proto.ReadOnly)
2468  {
2469  /* Set read-only code */
2470  ProtectionCode = MM_READONLY;
2471  }
2472  else
2473  {
2474  /* Set unknown protection */
2475  ProtectionCode = 0x100;
2476  ASSERT(CurrentProcess->CloneRoot != NULL);
2477  }
2478  }
2479  }
2480  }
2481 
2482  /* Do we have a valid protection code? */
2483  if (ProtectionCode != 0x100)
2484  {
2485  /* Run a software access check first, including to detect guard pages */
2486  Status = MiAccessCheck(PointerPte,
2487  !MI_IS_NOT_PRESENT_FAULT(FaultCode),
2488  Mode,
2489  ProtectionCode,
2490  TrapInformation,
2491  FALSE);
2492  if (Status != STATUS_SUCCESS)
2493  {
2494  /* Not supported */
2495  ASSERT(CurrentThread->ApcNeeded == 0);
2496 
2497  /* Drop the working set lock */
2498  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2500 
2501  /* Did we hit a guard page? */
2503  {
2504  /* Handle stack expansion */
2505  return MiCheckForUserStackOverflow(Address, TrapInformation);
2506  }
2507 
2508  /* Otherwise, fail back to the caller directly */
2509  return Status;
2510  }
2511  }
2512 
2513  /* Dispatch the fault */
2514  Status = MiDispatchFault(FaultCode,
2515  Address,
2516  PointerPte,
2517  ProtoPte,
2518  FALSE,
2520  TrapInformation,
2521  Vad);
2522 
2523  /* Return the status */
2525  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2526  return Status;
2527 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
ULONG R12
Definition: ketypes.h:363
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:968
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
MMPTE PrototypePte
Definition: init.c:40
#define _MI_PAGING_LEVELS
Definition: mm.h:6
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
UINT64 Rbx
Definition: ketypes.h:373
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define MI_IS_NOT_PRESENT_FAULT(FaultCode)
Definition: mm.h:121
#define MiAddressToPde(x)
Definition: mmx86.c:20
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
_In_ ULONG Mode
Definition: hubbusif.h:303
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
union _MMPTE::@2304 u
#define DbgPrint
Definition: loader.c:25
ULONG OwnsSystemWorkingSetShared
Definition: pstypes.h:1224
NTSTATUS NTAPI MiDispatchFault(IN ULONG FaultCode, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN BOOLEAN Recursive, IN PEPROCESS Process, IN PVOID TrapInformation, IN PMMVAD Vad)
Definition: pagfault.c:1304
#define TRUE
Definition: types.h:120
#define MI_IS_SESSION_ADDRESS(Address)
Definition: miarm.h:171
#define HYDRA_PROCESS
Definition: pagfault.c:20
#define MM_DECOMMIT
Definition: miarm.h:64
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:154
KTHREAD Tcb
Definition: pstypes.h:1103
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
#define MI_IS_PAGE_EXECUTABLE(x)
Definition: mm.h:111
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
static NTSTATUS NTAPI MiAccessCheck(IN PMMPTE PointerPte, IN BOOLEAN StoreInstruction, IN KPROCESSOR_MODE PreviousMode, IN ULONG_PTR ProtectionMask, IN PVOID TrapFrame, IN BOOLEAN LockHeld)
Definition: pagfault.c:168
VOID NTAPI MiCopyPfn(_In_ PFN_NUMBER DestPage, _In_ PFN_NUMBER SrcPage)
Definition: pagfault.c:529
PVOID MmNonPagedPoolExpansionStart
Definition: init.c:25
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:182
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:251
#define MM_NOACCESS
Definition: miarm.h:65
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:930
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1107
#define MM_PTE_SOFTWARE_PROTECTION_BITS
Definition: mm.h:75
#define MI_IS_PAGE_COPY_ON_WRITE(x)
Definition: mm.h:110
#define MI_IS_WRITE_ACCESS(FaultCode)
Definition: mm.h:122
ULONG R3
Definition: ketypes.h:362
ULONG Esi
Definition: ketypes.h:263
if(dx==0 &&dy==0)
Definition: linetemp.h:174
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
ULONG Pc
Definition: ketypes.h:367
ULONG Lr
Definition: ketypes.h:365
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:937
union _MMPFN::@1778 u3
struct Color Color
ULONG R2
Definition: ketypes.h:361
ULONG Edi
Definition: ketypes.h:262
VOID NTAPI MiDeletePte(IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
Definition: virtual.c:391
PVOID MmNonPagedPoolEnd
Definition: mminit.c:99
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG R0
Definition: ketypes.h:359
USHORT PrototypePte
Definition: mm.h:335
static PMMPTE NTAPI MiCheckVirtualAddress(IN PVOID VirtualAddress, OUT PULONG ProtectCode, OUT PMMVAD *ProtoVad)
Definition: pagfault.c:237
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:369
#define STATUS_WAIT_1
Definition: ntstatus.h:71
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
ULONG OwnsSessionWorkingSetShared
Definition: pstypes.h:1226
#define MiAddressToPte(x)
Definition: mmx86.c:19
union _MMPFN::@1776 u1
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG Eax
Definition: ketypes.h:258
UINT64 Rsi
Definition: ketypes.h:375
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:951
#define MI_SET_PROCESS(x)
Definition: mm.h:290
FORCEINLINE VOID MI_WRITE_INVALID_PDE(IN PMMPDE PointerPde, IN MMPDE InvalidPde)
Definition: miarm.h:1027
#define _WARN(msg)
Definition: debug.h:263
UINT64 Rax
Definition: ketypes.h:322
KAPC_STATE ApcState
Definition: ketypes.h:1710
PKEVENT Event
Definition: mm.h:351
#define MI_SET_PROCESS2(x)
Definition: mm.h:291
ULONG OwnsSessionWorkingSetExclusive
Definition: pstypes.h:1225
FORCEINLINE PFN_NUMBER MiRemoveZeroPageSafe(IN ULONG Color)
Definition: miarm.h:2431
unsigned char BOOLEAN
MMSUPPORT MmSystemCacheWs
Definition: init.c:55
static WCHAR Address[46]
Definition: ping.c:68
#define MiProtoPteToPte(x)
Definition: mm.h:250
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1334
#define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)
Definition: miarm.h:180
#define MI_SET_USAGE(x)
Definition: mm.h:289
ULONG64 Protection
Definition: mmtypes.h:88
#define MM_ZERO_ACCESS
Definition: miarm.h:43
Status
Definition: gdiplustypes.h:24
#define MM_READONLY
Definition: inbv.c:11
FORCEINLINE PMMPTE MiAddressToPxe(PVOID Address)
Definition: mm.h:164
struct _MM_SESSION_SPACE * GlobalVirtualAddress
Definition: miarm.h:480
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:45
#define MI_IS_SESSION_PTE(Pte)
Definition: miarm.h:174
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:243
ULONG64 Valid
Definition: mmtypes.h:150
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:195
#define STATUS_PAGE_FAULT_COPY_ON_WRITE
Definition: ntstatus.h:96
VOID NTAPI MiZeroPfn(IN PFN_NUMBER PageFrameNumber)
Definition: pagfault.c:483
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define MI_IS_PAGE_LARGE(x)
Definition: mm.h:104
UINT64 Rdx
Definition: ketypes.h:324
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1557
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define MM_READWRITE
Definition: inbv.c:12
#define MM_NOIRQL
Definition: miarm.h:236
#define MM_GUARDPAGE
Definition: miarm.h:57
Definition: mm.h:345
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
#define PTE_BASE
Definition: mmx86.c:14
ULONG OwnsSystemWorkingSetExclusive
Definition: pstypes.h:1223
ULONG Ecx
Definition: ketypes.h:257
BOOLEAN MmProtectFreedNonPagedPool
Definition: pool.c:29
ULONG Eip
Definition: ketypes.h:267
UINT64 R11
Definition: ketypes.h:328
#define MI_IS_INSTRUCTION_FETCH(FaultCode)
Definition: mm.h:123
#define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address)
Definition: miarm.h:183
ULONG_PTR Long
Definition: mmtypes.h:215
PVOID MmNonPagedPoolStart
Definition: init.c:24
#define MM_EXECUTE_READWRITE
Definition: miarm.h:49
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:822
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:475
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:475
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:984
ULONG Ebx
Definition: ketypes.h:264
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
ULONG Sp
Definition: ketypes.h:364
static NTSTATUS NTAPI MiCheckForUserStackOverflow(IN PVOID Address, IN PVOID TrapInformation)
Definition: pagfault.c:30
PMMPTE PteAddress
Definition: mm.h:358
ULONG OwnsProcessWorkingSetShared
Definition: pstypes.h:1222
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
#define NULL
Definition: types.h:112
MMPTE OriginalPte
Definition: mm.h:379
UINT64 Rdi
Definition: ketypes.h:374
MMPDE DemandZeroPde
Definition: init.c:36
ULONG R1
Definition: ketypes.h:360
#define DPRINT1
Definition: precomp.h:8
#define MI_IS_SESSION_IMAGE_ADDRESS(Address)
Definition: miarm.h:168
UINT64 Rip
Definition: ketypes.h:383
FORCEINLINE VOID MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:1801
unsigned int ULONG
Definition: retypes.h:1
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
#define MM_PROTECT_SPECIAL
Definition: miarm.h:59
ULONG OwnsProcessWorkingSetExclusive
Definition: pstypes.h:1221
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:243
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG MmSizeOfNonPagedPoolInBytes
Definition: init.c:21
FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1248
PMMPTE MiHighestUserPte
Definition: mminit.c:233
#define DPRINT
Definition: sndvol32.h:71
static NTSTATUS NTAPI MiResolveDemandZeroFault(IN PVOID Address, IN PMMPTE PointerPte, IN ULONG Protection, IN PEPROCESS Process, IN KIRQL OldIrql)
Definition: pagfault.c:595
UINT64 Rcx
Definition: ketypes.h:323
#define STATUS_PAGE_FAULT_DEMAND_ZERO
Definition: ntstatus.h:95
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define MmSystemRangeStart
Definition: mm.h:32
ULONG EFlags
Definition: ketypes.h:388
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
ULONG Edx
Definition: ketypes.h:256
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:806
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1177
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MmAccessFault().

◆ MmGetExecuteOptions()

NTSTATUS NTAPI MmGetExecuteOptions ( IN PULONG  ExecuteOptions)

Definition at line 2531 of file pagfault.c.

2532 {
2535 
2536  *ExecuteOptions = 0;
2537 
2538  if (CurrentProcess->Flags.ExecuteDisable)
2539  {
2540  *ExecuteOptions |= MEM_EXECUTE_OPTION_DISABLE;
2541  }
2542 
2543  if (CurrentProcess->Flags.ExecuteEnable)
2544  {
2545  *ExecuteOptions |= MEM_EXECUTE_OPTION_ENABLE;
2546  }
2547 
2548  if (CurrentProcess->Flags.DisableThunkEmulation)
2549  {
2550  *ExecuteOptions |= MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION;
2551  }
2552 
2553  if (CurrentProcess->Flags.Permanent)
2554  {
2555  *ExecuteOptions |= MEM_EXECUTE_OPTION_PERMANENT;
2556  }
2557 
2558  if (CurrentProcess->Flags.ExecuteDispatchEnable)
2559  {
2560  *ExecuteOptions |= MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE;
2561  }
2562 
2563  if (CurrentProcess->Flags.ImageDispatchEnable)
2564  {
2565  *ExecuteOptions |= MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE;
2566  }
2567 
2568  return STATUS_SUCCESS;
2569 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE
Definition: mmtypes.h:78
#define MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE
Definition: mmtypes.h:77
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define MEM_EXECUTE_OPTION_ENABLE
Definition: mmtypes.h:74
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:45
#define MEM_EXECUTE_OPTION_DISABLE
Definition: mmtypes.h:73
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
Definition: mmtypes.h:75
#define MEM_EXECUTE_OPTION_PERMANENT
Definition: mmtypes.h:76
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by NtQueryInformationProcess().

◆ MmSetExecuteOptions()

NTSTATUS NTAPI MmSetExecuteOptions ( IN ULONG  ExecuteOptions)

Definition at line 2573 of file pagfault.c.

2574 {
2576  KLOCK_QUEUE_HANDLE ProcessLock;
2579 
2580  /* Only accept valid flags */
2581  if (ExecuteOptions & ~MEM_EXECUTE_OPTION_VALID_FLAGS)
2582  {
2583  /* Fail */
2584  DPRINT1("Invalid no-execute options\n");
2585  return STATUS_INVALID_PARAMETER;
2586  }
2587 
2588  /* Change the NX state in the process lock */
2590 
2591  /* Don't change anything if the permanent flag was set */
2592  if (!CurrentProcess->Flags.Permanent)
2593  {
2594  /* Start by assuming it's not disabled */
2595  CurrentProcess->Flags.ExecuteDisable = FALSE;
2596 
2597  /* Now process each flag and turn the equivalent bit on */
2598  if (ExecuteOptions & MEM_EXECUTE_OPTION_DISABLE)
2599  {
2600  CurrentProcess->Flags.ExecuteDisable = TRUE;
2601  }
2602  if (ExecuteOptions & MEM_EXECUTE_OPTION_ENABLE)
2603  {
2604  CurrentProcess->Flags.ExecuteEnable = TRUE;
2605  }
2606  if (ExecuteOptions & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)
2607  {
2608  CurrentProcess->Flags.DisableThunkEmulation = TRUE;
2609  }
2610  if (ExecuteOptions & MEM_EXECUTE_OPTION_PERMANENT)
2611  {
2612  CurrentProcess->Flags.Permanent = TRUE;
2613  }
2614  if (ExecuteOptions & MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE)
2615  {
2616  CurrentProcess->Flags.ExecuteDispatchEnable = TRUE;
2617  }
2618  if (ExecuteOptions & MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE)
2619  {
2620  CurrentProcess->Flags.ImageDispatchEnable = TRUE;
2621  }
2622 
2623  /* These are turned on by default if no-execution is also eanbled */
2624  if (CurrentProcess->Flags.ExecuteEnable)
2625  {
2626  CurrentProcess->Flags.ExecuteDispatchEnable = TRUE;
2627  CurrentProcess->Flags.ImageDispatchEnable = TRUE;
2628  }
2629 
2630  /* All good */
2632  }
2633 
2634  /* Release the lock and return status */
2635  KiReleaseProcessLock(&ProcessLock);
2636  return Status;
2637 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE
Definition: mmtypes.h:78
FORCEINLINE VOID KiAcquireProcessLockRaiseToSynch(IN PKPROCESS Process, IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:651
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE
Definition: mmtypes.h:77
LONG NTSTATUS
Definition: precomp.h:26
#define MEM_EXECUTE_OPTION_VALID_FLAGS
Definition: mmtypes.h:79
#define FALSE
Definition: types.h:117
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define MEM_EXECUTE_OPTION_ENABLE
Definition: mmtypes.h:74
Status
Definition: gdiplustypes.h:24
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:45
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
FORCEINLINE VOID KiReleaseProcessLock(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:660
#define MEM_EXECUTE_OPTION_DISABLE
Definition: mmtypes.h:73
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
Definition: mmtypes.h:75
#define MEM_EXECUTE_OPTION_PERMANENT
Definition: mmtypes.h:76
#define DPRINT1
Definition: precomp.h:8
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by NtSetInformationProcess().