ReactOS 0.4.17-dev-1190-g4c812f4
pagfault.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/pagfault.c
5 * PURPOSE: ARM Memory Manager Page Fault Handling
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15#define MODULE_INVOLVED_IN_ARM3
16#include <mm/ARM3/miarm.h>
17
18VOID
21
22/* GLOBALS ********************************************************************/
23
24#define HYDRA_PROCESS (PEPROCESS)1
25#if MI_TRACE_PFNS
26BOOLEAN UserPdeFault = FALSE;
27#endif
28
29/* PRIVATE FUNCTIONS **********************************************************/
30
31static
35 IN PVOID TrapInformation)
36{
37 PETHREAD CurrentThread = PsGetCurrentThread();
38 PTEB Teb = CurrentThread->Tcb.Teb;
39 PVOID StackBase, DeallocationStack, NextStackAddress;
40 SIZE_T GuaranteedSize;
42
43 /* Do we own the address space lock? */
44 if (CurrentThread->AddressSpaceOwner == 1)
45 {
46 /* This isn't valid */
47 DPRINT1("Process owns address space lock\n");
50 }
51
52 /* Are we attached? */
54 {
55 /* This isn't valid */
56 DPRINT1("Process is attached\n");
58 }
59
60 /* Read the current settings */
61 StackBase = Teb->NtTib.StackBase;
62 DeallocationStack = Teb->DeallocationStack;
63 GuaranteedSize = Teb->GuaranteedStackBytes;
64 DPRINT("Handling guard page fault with Stacks Addresses 0x%p and 0x%p, guarantee: %lx\n",
65 StackBase, DeallocationStack, GuaranteedSize);
66
67 /* Guarantees make this code harder, for now, assume there aren't any */
68 ASSERT(GuaranteedSize == 0);
69
70 /* So allocate only the minimum guard page size */
71 GuaranteedSize = PAGE_SIZE;
72
73 /* Does this faulting stack address actually exist in the stack? */
74 if ((Address >= StackBase) || (Address < DeallocationStack))
75 {
76 /* That's odd... */
77 DPRINT1("Faulting address outside of stack bounds. Address=%p, StackBase=%p, DeallocationStack=%p\n",
78 Address, StackBase, DeallocationStack);
80 }
81
82 /* This is where the stack will start now */
83 NextStackAddress = (PVOID)((ULONG_PTR)PAGE_ALIGN(Address) - GuaranteedSize);
84
85 /* Do we have at least one page between here and the end of the stack? */
86 if (((ULONG_PTR)NextStackAddress - PAGE_SIZE) <= (ULONG_PTR)DeallocationStack)
87 {
88 /* We don't -- Trying to make this guard page valid now */
89 DPRINT1("Close to our death...\n");
90
91 /* Calculate the next memory address */
92 NextStackAddress = (PVOID)((ULONG_PTR)PAGE_ALIGN(DeallocationStack) + GuaranteedSize);
93
94 /* Allocate the memory */
95 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
96 &NextStackAddress,
97 0,
98 &GuaranteedSize,
101 if (NT_SUCCESS(Status))
102 {
103 /* Success! */
104 Teb->NtTib.StackLimit = NextStackAddress;
105
106#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
107 /* Update WOW64 32-bit TEB stack limit */
108 if (CurrentThread->ThreadsProcess->Wow64Process != NULL)
109 {
110 PS_GET_TEB32_FROM_TEB(Teb)->NtTib.StackLimit = PtrToUlong(Teb->NtTib.StackLimit);
111 }
112#endif
113 }
114 else
115 {
116 DPRINT1("Failed to allocate memory\n");
117 }
118
120 }
121
122 /* Don't handle this flag yet */
124
125 /* Update the stack limit */
126 Teb->NtTib.StackLimit = (PVOID)((ULONG_PTR)NextStackAddress + GuaranteedSize);
127
128#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
129 /* Update WOW64 32-bit TEB stack limit */
130 if (CurrentThread->ThreadsProcess->Wow64Process != NULL)
131 {
132 PS_GET_TEB32_FROM_TEB(Teb)->NtTib.StackLimit = PtrToUlong(Teb->NtTib.StackLimit);
133 }
134#endif
135
136 /* Now move the guard page to the next page */
137 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
138 &NextStackAddress,
139 0,
140 &GuaranteedSize,
144 {
145 /* We did it! */
146 DPRINT("Guard page handled successfully for %p\n", Address);
148 }
149
150 /* Fail, we couldn't move the guard page */
151 DPRINT1("Guard page failure: %lx\n", Status);
152 ASSERT(FALSE);
154}
155
159 _In_ ULONG ProtectionMask,
162{
163 #define _BYTE_MASK(Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7) \
164 (Bit0) | ((Bit1) << 1) | ((Bit2) << 2) | ((Bit3) << 3) | \
165 ((Bit4) << 4) | ((Bit5) << 5) | ((Bit6) << 6) | ((Bit7) << 7)
166 static const UCHAR AccessAllowedMask[2][2] =
167 {
168 { // Protect 0 1 2 3 4 5 6 7
169 _BYTE_MASK(0, 1, 1, 1, 1, 1, 1, 1), // READ
170 _BYTE_MASK(0, 0, 1, 1, 0, 0, 1, 1), // EXECUTE READ
171 },
172 {
173 _BYTE_MASK(0, 0, 0, 0, 1, 1, 1, 1), // WRITE
174 _BYTE_MASK(0, 0, 0, 0, 0, 0, 1, 1), // EXECUTE WRITE
175 }
176 };
177
178 /* We want only the lower access bits */
179 ProtectionMask &= MM_PROTECT_ACCESS;
180
181 /* Look it up in the table */
182 return (AccessAllowedMask[Write != 0][Execute != 0] >> ProtectionMask) & 1;
183}
184
185static
187NTAPI
189 IN BOOLEAN StoreInstruction,
191 IN ULONG_PTR ProtectionMask,
192 IN PVOID TrapFrame,
193 IN BOOLEAN LockHeld)
194{
196
197 /* Check for invalid user-mode access */
198 if ((PreviousMode == UserMode) && (PointerPte > MiHighestUserPte))
199 {
201 }
202
203 /* Capture the PTE -- is it valid? */
204 TempPte = *PointerPte;
205 if (TempPte.u.Hard.Valid)
206 {
207 /* Was someone trying to write to it? */
208 if (StoreInstruction)
209 {
210 /* Is it writable?*/
213 {
214 /* Then there's nothing to worry about */
215 return STATUS_SUCCESS;
216 }
217
218 /* Oops! This isn't allowed */
220 }
221
222 /* Someone was trying to read from a valid PTE, that's fine too */
223 return STATUS_SUCCESS;
224 }
225
226 /* Check if the protection on the page allows what is being attempted */
227 if (!MiIsAccessAllowed(ProtectionMask, StoreInstruction, FALSE))
228 {
230 }
231
232 /* Check if this is a guard page */
233 if ((ProtectionMask & MM_PROTECT_SPECIAL) == MM_GUARDPAGE)
234 {
235 ASSERT(ProtectionMask != MM_DECOMMIT);
236
237 /* Attached processes can't expand their stack */
239
240 /* No support for prototype PTEs yet */
241 ASSERT(TempPte.u.Soft.Prototype == 0);
242
243 /* Remove the guard page bit, and return a guard page violation */
244 TempPte.u.Soft.Protection = ProtectionMask & ~MM_GUARDPAGE;
245 ASSERT(TempPte.u.Long != 0);
246 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
248 }
249
250 /* Nothing to do */
251 return STATUS_SUCCESS;
252}
253
254static
255PMMPTE
256NTAPI
258 OUT PULONG ProtectCode,
259 OUT PMMVAD *ProtoVad)
260{
261 PMMVAD Vad;
262 PMMPTE PointerPte;
263
264 /* No prototype/section support for now */
265 *ProtoVad = NULL;
266
267 /* User or kernel fault? */
269 {
270 /* Special case for shared data */
272 {
273 /* It's a read-only page */
274 *ProtectCode = MM_READONLY;
275 return MmSharedUserDataPte;
276 }
277
278 /* Find the VAD, it might not exist if the address is bogus */
280 if (!Vad)
281 {
282 /* Bogus virtual address */
283 *ProtectCode = MM_NOACCESS;
284 return NULL;
285 }
286
287 /* ReactOS does not handle physical memory VADs yet */
289
290 /* Check if it's a section, or just an allocation */
291 if (Vad->u.VadFlags.PrivateMemory)
292 {
293 /* ReactOS does not handle AWE VADs yet */
294 ASSERT(Vad->u.VadFlags.VadType != VadAwe);
295
296 /* This must be a TEB/PEB VAD */
297 if (Vad->u.VadFlags.MemCommit)
298 {
299 /* It's committed, so return the VAD protection */
300 *ProtectCode = (ULONG)Vad->u.VadFlags.Protection;
301 }
302 else
303 {
304 /* It has not yet been committed, so return no access */
305 *ProtectCode = MM_NOACCESS;
306 }
307
308 /* In both cases, return no PTE */
309 return NULL;
310 }
311 else
312 {
313 /* ReactOS does not supoprt these VADs yet */
316
317 /* Return the proto VAD */
318 *ProtoVad = Vad;
319
320 /* Get the prototype PTE for this page */
321 PointerPte = (((ULONG_PTR)VirtualAddress >> PAGE_SHIFT) - Vad->StartingVpn) + Vad->FirstPrototypePte;
322 ASSERT(PointerPte != NULL);
323 ASSERT(PointerPte <= Vad->LastContiguousPte);
324
325 /* Return the Prototype PTE and the protection for the page mapping */
326 *ProtectCode = (ULONG)Vad->u.VadFlags.Protection;
327 return PointerPte;
328 }
329 }
331 {
332 /* This should never happen, as these addresses are handled by the double-maping */
335 {
336 /* Fail such access */
337 *ProtectCode = MM_NOACCESS;
338 return NULL;
339 }
340
341 /* Return full access rights */
342 *ProtectCode = MM_EXECUTE_READWRITE;
343 return NULL;
344 }
346 {
347 /* ReactOS does not have an image list yet, so bail out to failure case */
349 }
350
351 /* Default case -- failure */
352 *ProtectCode = MM_NOACCESS;
353 return NULL;
354}
355
356#if (_MI_PAGING_LEVELS == 2)
357static
360MiCheckPdeForSessionSpace(IN PVOID Address)
361{
363 PMMPDE PointerPde;
364 PVOID SessionAddress;
365 ULONG Index;
366
367 /* Is this a session PTE? */
369 {
370 /* Make sure the PDE for session space is valid */
371 PointerPde = MiAddressToPde(MmSessionSpace);
372 if (!PointerPde->u.Hard.Valid)
373 {
374 /* This means there's no valid session, bail out */
375 DbgPrint("MiCheckPdeForSessionSpace: No current session for PTE %p\n",
376 Address);
379 }
380
381 /* Now get the session-specific page table for this address */
382 SessionAddress = MiPteToAddress(Address);
383 PointerPde = MiAddressToPte(Address);
384 if (PointerPde->u.Hard.Valid) return STATUS_WAIT_1;
385
386 /* It's not valid, so find it in the page table array */
387 Index = ((ULONG_PTR)SessionAddress - (ULONG_PTR)MmSessionBase) >> 22;
389 if (TempPde.u.Hard.Valid)
390 {
391 /* The copy is valid, so swap it in */
392 InterlockedExchange((PLONG)PointerPde, TempPde.u.Long);
393 return STATUS_WAIT_1;
394 }
395
396 /* We don't seem to have allocated a page table for this address yet? */
397 DbgPrint("MiCheckPdeForSessionSpace: No Session PDE for PTE %p, %p\n",
398 PointerPde->u.Long, SessionAddress);
401 }
402
403 /* Is the address also a session address? If not, we're done */
405
406 /* It is, so again get the PDE for session space */
407 PointerPde = MiAddressToPde(MmSessionSpace);
408 if (!PointerPde->u.Hard.Valid)
409 {
410 /* This means there's no valid session, bail out */
411 DbgPrint("MiCheckPdeForSessionSpace: No current session for VA %p\n",
412 Address);
415 }
416
417 /* Now get the PDE for the address itself */
418 PointerPde = MiAddressToPde(Address);
419 if (!PointerPde->u.Hard.Valid)
420 {
421 /* Do the swap, we should be good to go */
423 PointerPde->u.Long = MmSessionSpace->PageTables[Index].u.Long;
424 if (PointerPde->u.Hard.Valid) return STATUS_WAIT_1;
425
426 /* We had not allocated a page table for this session address yet, fail! */
427 DbgPrint("MiCheckPdeForSessionSpace: No Session PDE for VA %p, %p\n",
428 PointerPde->u.Long, Address);
431 }
432
433 /* It's valid, so there's nothing to do */
434 return STATUS_SUCCESS;
435}
436
440{
441 PMMPDE PointerPde;
443
444 /* Check session PDE */
445 if (MI_IS_SESSION_ADDRESS(Address)) return MiCheckPdeForSessionSpace(Address);
446 if (MI_IS_SESSION_PTE(Address)) return MiCheckPdeForSessionSpace(Address);
447
448 //
449 // Check if this is a fault while trying to access the page table itself
450 //
452 {
453 //
454 // Send a hint to the page fault handler that this is only a valid fault
455 // if we already detected this was access within the page table range
456 //
457 PointerPde = (PMMPDE)MiAddressToPte(Address);
459 }
460 else if (Address < MmSystemRangeStart)
461 {
462 //
463 // This is totally illegal
464 //
466 }
467 else
468 {
469 //
470 // Get the PDE for the address
471 //
472 PointerPde = MiAddressToPde(Address);
473 }
474
475 //
476 // Check if it's not valid
477 //
478 if (PointerPde->u.Hard.Valid == 0)
479 {
480 //
481 // Copy it from our double-mapped system page directory
482 //
483 InterlockedExchangePte(PointerPde,
484 MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)].u.Long);
485 }
486
487 //
488 // Return status
489 //
490 return Status;
491}
492#else
496{
498}
499#endif
500
501VOID
502NTAPI
503MiZeroPfn(IN PFN_NUMBER PageFrameNumber)
504{
505 PMMPTE ZeroPte;
507 PMMPFN Pfn1;
508 PVOID ZeroAddress;
509
510 /* Get the PFN for this page */
511 Pfn1 = MiGetPfnEntry(PageFrameNumber);
512 ASSERT(Pfn1);
513
514 /* Grab a system PTE we can use to zero the page */
516 ASSERT(ZeroPte);
517
518 /* Initialize the PTE for it */
520 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
521
522 /* Setup caching */
523 if (Pfn1->u3.e1.CacheAttribute == MiWriteCombined)
524 {
525 /* Write combining, no caching */
527 }
528 else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
529 {
530 /* Disable caching */
532 }
533
534 /* Make the system PTE valid with our PFN */
535 MI_WRITE_VALID_PTE(ZeroPte, TempPte);
536
537 /* Get the address it maps to, and zero it out */
538 ZeroAddress = MiPteToAddress(ZeroPte);
539 KeZeroPages(ZeroAddress, PAGE_SIZE);
540
541 /* Now get rid of it */
543}
544
545VOID
546NTAPI
548 _In_ PFN_NUMBER DestPage,
549 _In_ PFN_NUMBER SrcPage)
550{
551 PMMPTE SysPtes;
553 PMMPFN DestPfn, SrcPfn;
554 PVOID DestAddress;
555 const VOID* SrcAddress;
556
557 /* Get the PFNs */
558 DestPfn = MiGetPfnEntry(DestPage);
559 ASSERT(DestPfn);
560 SrcPfn = MiGetPfnEntry(SrcPage);
561 ASSERT(SrcPfn);
562
563 /* Grab 2 system PTEs */
565 ASSERT(SysPtes);
566
567 /* Initialize the destination PTE */
569 TempPte.u.Hard.PageFrameNumber = DestPage;
570
571 /* Setup caching */
572 if (DestPfn->u3.e1.CacheAttribute == MiWriteCombined)
573 {
574 /* Write combining, no caching */
576 }
577 else if (DestPfn->u3.e1.CacheAttribute == MiNonCached)
578 {
579 /* Disable caching */
581 }
582
583 /* Make the system PTE valid with our PFN */
584 MI_WRITE_VALID_PTE(&SysPtes[0], TempPte);
585
586 /* Initialize the source PTE */
588 TempPte.u.Hard.PageFrameNumber = SrcPage;
589
590 /* Setup caching */
591 if (SrcPfn->u3.e1.CacheAttribute == MiNonCached)
592 {
594 }
595
596 /* Make the system PTE valid with our PFN */
597 MI_WRITE_VALID_PTE(&SysPtes[1], TempPte);
598
599 /* Get the addresses and perform the copy */
600 DestAddress = MiPteToAddress(&SysPtes[0]);
601 SrcAddress = MiPteToAddress(&SysPtes[1]);
602 RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
603
604 /* Now get rid of it */
606}
607
608static
610NTAPI
612 IN PMMPTE PointerPte,
613 IN ULONG Protection,
616{
617 PFN_NUMBER PageFrameNumber = 0;
619 BOOLEAN NeedZero = FALSE, HaveLock = FALSE;
620 ULONG Color;
621 PMMPFN Pfn1;
622 DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
623 Address,
624 Process);
625
626 /* Must currently only be called by paging path */
627 if ((Process > HYDRA_PROCESS) && (OldIrql == MM_NOIRQL))
628 {
629 /* Sanity check */
630 ASSERT(MI_IS_PAGE_TABLE_ADDRESS(PointerPte));
631
632 /* No forking yet */
633 ASSERT(Process->ForkInProgress == NULL);
634
635 /* Get process color */
637 ASSERT(Color != 0xFFFFFFFF);
638
639 /* We'll need a zero page */
640 NeedZero = TRUE;
641 }
642 else
643 {
644 /* Check if we need a zero page */
645 NeedZero = (OldIrql != MM_NOIRQL);
646
647 /* Session-backed image views must be zeroed */
648 if ((Process == HYDRA_PROCESS) &&
651 {
652 NeedZero = TRUE;
653 }
654
655 /* Hardcode unknown color */
656 Color = 0xFFFFFFFF;
657 }
658
659 /* Check if the PFN database should be acquired */
660 if (OldIrql == MM_NOIRQL)
661 {
662 /* Acquire it and remember we should release it after */
663 OldIrql = MiAcquirePfnLock();
664 HaveLock = TRUE;
665 }
666
667 /* We either manually locked the PFN DB, or already came with it locked */
669 ASSERT(PointerPte->u.Hard.Valid == 0);
670
671 /* Assert we have enough pages */
672 //ASSERT(MmAvailablePages >= 32);
673
674#if MI_TRACE_PFNS
675 if (UserPdeFault) MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
676 if (!UserPdeFault) MI_SET_USAGE(MI_USAGE_DEMAND_ZERO);
677#endif
678 if (Process == HYDRA_PROCESS) MI_SET_PROCESS2("Hydra");
679 else if (Process) MI_SET_PROCESS2(Process->ImageFileName);
680 else MI_SET_PROCESS2("Kernel Demand 0");
681
682 /* Do we need a zero page? */
683 if (Color != 0xFFFFFFFF)
684 {
685 /* Try to get one, if we couldn't grab a free page and zero it */
686 PageFrameNumber = MiRemoveZeroPageSafe(Color);
687 if (!PageFrameNumber)
688 {
689 /* We'll need a free page and zero it manually */
690 PageFrameNumber = MiRemoveAnyPage(Color);
691 NeedZero = TRUE;
692 }
693 else
694 {
695 /* Page guaranteed to be zero-filled */
696 NeedZero = FALSE;
697 }
698 }
699 else
700 {
701 /* Get a color, and see if we should grab a zero or non-zero page */
703 if (!NeedZero)
704 {
705 /* Process or system doesn't want a zero page, grab anything */
706 PageFrameNumber = MiRemoveAnyPage(Color);
707 }
708 else
709 {
710 /* System wants a zero page, obtain one */
711 PageFrameNumber = MiRemoveZeroPage(Color);
712 /* No need to zero-fill it */
713 NeedZero = FALSE;
714 }
715 }
716
717 if (PageFrameNumber == 0)
718 {
719 MiReleasePfnLock(OldIrql);
720 return STATUS_NO_MEMORY;
721 }
722
723 /* Initialize it */
724 MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
725
726 /* Increment demand zero faults */
727 KeGetCurrentPrcb()->MmDemandZeroCount++;
728
729 /* Do we have the lock? */
730 if (HaveLock)
731 {
732 /* Release it */
733 MiReleasePfnLock(OldIrql);
734
735 /* Update performance counters */
736 if (Process > HYDRA_PROCESS) Process->NumberOfPrivatePages++;
737 }
738
739 /* Zero the page if need be */
740 if (NeedZero) MiZeroPfn(PageFrameNumber);
741
742 /* Fault on user PDE, or fault on user PTE? */
743 if (PointerPte <= MiHighestUserPte)
744 {
745 /* User fault, build a user PTE */
747 PointerPte,
748 Protection,
749 PageFrameNumber);
750 }
751 else
752 {
753 /* This is a user-mode PDE, create a kernel PTE for it */
755 PointerPte,
756 Protection,
757 PageFrameNumber);
758 }
759
760 /* Set it dirty if it's a writable page */
762
763 /* Write it */
764 MI_WRITE_VALID_PTE(PointerPte, TempPte);
765
766 /* Did we manually acquire the lock */
767 if (HaveLock)
768 {
769 /* Get the PFN entry */
770 Pfn1 = MI_PFN_ELEMENT(PageFrameNumber);
771
772 /* Windows does these sanity checks */
773 ASSERT(Pfn1->u1.Event == 0);
774 ASSERT(Pfn1->u3.e1.PrototypePte == 0);
775 }
776
777 //
778 // It's all good now
779 //
780 DPRINT("Demand zero page has now been paged in\n");
782}
783
784static
786NTAPI
789 IN PMMPTE PointerPte,
790 IN PMMPTE PointerProtoPte,
792 IN PMMPFN* LockedProtoPfn)
793{
795 PMMPTE OriginalPte, PageTablePte;
796 ULONG_PTR Protection;
797 PFN_NUMBER PageFrameIndex;
798 PMMPFN Pfn1, Pfn2;
799 BOOLEAN OriginalProtection, DirtyPage;
800
801 /* Must be called with an valid prototype PTE, with the PFN lock held */
803 ASSERT(PointerProtoPte->u.Hard.Valid == 1);
804
805 /* Get the page */
806 PageFrameIndex = PFN_FROM_PTE(PointerProtoPte);
807
808 /* Get the PFN entry and set it as a prototype PTE */
809 Pfn1 = MiGetPfnEntry(PageFrameIndex);
810 Pfn1->u3.e1.PrototypePte = 1;
811
812 /* Increment the share count for the page table */
813 PageTablePte = MiAddressToPte(PointerPte);
814 Pfn2 = MiGetPfnEntry(PageTablePte->u.Hard.PageFrameNumber);
815 Pfn2->u2.ShareCount++;
816
817 /* Check where we should be getting the protection information from */
818 if (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
819 {
820 /* Get the protection from the PTE, there's no real Proto PTE data */
821 Protection = PointerPte->u.Soft.Protection;
822
823 /* Remember that we did not use the proto protection */
824 OriginalProtection = FALSE;
825 }
826 else
827 {
828 /* Get the protection from the original PTE link */
829 OriginalPte = &Pfn1->OriginalPte;
830 Protection = OriginalPte->u.Soft.Protection;
831
832 /* Remember that we used the original protection */
833 OriginalProtection = TRUE;
834
835 /* Check if this was a write on a read only proto */
836 if ((StoreInstruction) && !(Protection & MM_READWRITE))
837 {
838 /* Clear the flag */
839 StoreInstruction = 0;
840 }
841 }
842
843 /* Check if this was a write on a non-COW page */
844 DirtyPage = FALSE;
845 if ((StoreInstruction) && ((Protection & MM_WRITECOPY) != MM_WRITECOPY))
846 {
847 /* Then the page should be marked dirty */
848 DirtyPage = TRUE;
849
850 /* ReactOS check */
851 ASSERT(Pfn1->OriginalPte.u.Soft.Prototype != 0);
852 }
853
854 /* Did we get a locked incoming PFN? */
855 if (*LockedProtoPfn)
856 {
857 /* Drop a reference */
858 ASSERT((*LockedProtoPfn)->u3.e2.ReferenceCount >= 1);
859 MiDereferencePfnAndDropLockCount(*LockedProtoPfn);
860 *LockedProtoPfn = NULL;
861 }
862
863 /* Release the PFN lock */
864 MiReleasePfnLock(OldIrql);
865
866 /* Remove special/caching bits */
867 Protection &= ~MM_PROTECT_SPECIAL;
868
869 /* Setup caching */
870 if (Pfn1->u3.e1.CacheAttribute == MiWriteCombined)
871 {
872 /* Write combining, no caching */
874 }
875 else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
876 {
877 /* Disable caching */
879 }
880
881 /* Check if this is a kernel or user address */
883 {
884 /* Build the user PTE */
885 MI_MAKE_HARDWARE_PTE_USER(&TempPte, PointerPte, Protection, PageFrameIndex);
886 }
887 else
888 {
889 /* Build the kernel PTE */
890 MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, PageFrameIndex);
891 }
892
893 /* Set the dirty flag if needed */
894 if (DirtyPage) MI_MAKE_DIRTY_PAGE(&TempPte);
895
896 /* Write the PTE */
897 MI_WRITE_VALID_PTE(PointerPte, TempPte);
898
899 /* Reset the protection if needed */
900 if (OriginalProtection) Protection = MM_ZERO_ACCESS;
901
902 /* Return success */
903 ASSERT(PointerPte == MiAddressToPte(Address));
904 return STATUS_SUCCESS;
905}
906
907static
909NTAPI
911 _In_ PVOID FaultingAddress,
912 _In_ PMMPTE PointerPte,
913 _In_ PEPROCESS CurrentProcess,
915{
916 ULONG Color;
919 MMPTE TempPte = *PointerPte;
920 PMMPFN Pfn1;
921 ULONG PageFileIndex = TempPte.u.Soft.PageFileLow;
922 ULONG_PTR PageFileOffset = TempPte.u.Soft.PageFileHigh;
923 ULONG Protection = TempPte.u.Soft.Protection;
924
925 /* Things we don't support yet */
926 ASSERT(CurrentProcess > HYDRA_PROCESS);
928
930 MI_SET_PROCESS(CurrentProcess);
931
932 /* We must hold the PFN lock */
934
935 /* Some sanity checks */
936 ASSERT(TempPte.u.Hard.Valid == 0);
937 ASSERT(TempPte.u.Soft.PageFileHigh != 0);
938 ASSERT(TempPte.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED);
939
940 /* Get any page, it will be overwritten */
941 Color = MI_GET_NEXT_PROCESS_COLOR(CurrentProcess);
943 if (Page == 0)
944 {
945 return STATUS_NO_MEMORY;
946 }
947
948 /* Initialize this PFN */
949 MiInitializePfn(Page, PointerPte, StoreInstruction);
950
951 /* Sets the PFN as being in IO operation */
952 Pfn1 = MI_PFN_ELEMENT(Page);
953 ASSERT(Pfn1->u1.Event == NULL);
954 ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
955 ASSERT(Pfn1->u3.e1.WriteInProgress == 0);
956 Pfn1->u3.e1.ReadInProgress = 1;
957
958 /* We must write the PTE now as the PFN lock will be released while performing the IO operation */
959 MI_MAKE_TRANSITION_PTE(&TempPte, Page, Protection);
960
961 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
962
963 /* Release the PFN lock while we proceed */
964 MiReleasePfnLock(*OldIrql);
965
966 /* Do the paging IO */
967 Status = MiReadPageFile(Page, PageFileIndex, PageFileOffset);
968
969 /* Lock the PFN database again */
970 *OldIrql = MiAcquirePfnLock();
971
972 /* Nobody should have changed that while we were not looking */
973 ASSERT(Pfn1->u3.e1.ReadInProgress == 1);
974 ASSERT(Pfn1->u3.e1.WriteInProgress == 0);
975
976 if (!NT_SUCCESS(Status))
977 {
978 /* Malheur! */
979 ASSERT(FALSE);
980 Pfn1->u4.InPageError = 1;
981 Pfn1->u1.ReadStatus = Status;
982 }
983
984 /* And the PTE can finally be valid */
985 MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, Page);
986 MI_WRITE_VALID_PTE(PointerPte, TempPte);
987
988 Pfn1->u3.e1.ReadInProgress = 0;
989 /* Did someone start to wait on us while we proceeded ? */
990 if (Pfn1->u1.Event)
991 {
992 /* Tell them we're done */
994 }
995
996 return Status;
997}
998
999static
1001NTAPI
1003 IN PVOID FaultingAddress,
1004 IN PMMPTE PointerPte,
1005 IN PEPROCESS CurrentProcess,
1007 OUT PKEVENT **InPageBlock)
1008{
1009 PFN_NUMBER PageFrameIndex;
1010 PMMPFN Pfn1;
1011 MMPTE TempPte;
1012 PMMPTE PointerToPteForProtoPage;
1013 DPRINT("Transition fault on 0x%p with PTE 0x%p in process %s\n",
1014 FaultingAddress, PointerPte, CurrentProcess->ImageFileName);
1015
1016 /* Windowss does this check */
1017 ASSERT(*InPageBlock == NULL);
1018
1019 /* ARM3 doesn't support this path */
1021
1022 /* Capture the PTE and make sure it's in transition format */
1023 TempPte = *PointerPte;
1024 ASSERT((TempPte.u.Soft.Valid == 0) &&
1025 (TempPte.u.Soft.Prototype == 0) &&
1026 (TempPte.u.Soft.Transition == 1));
1027
1028 /* Get the PFN and the PFN entry */
1029 PageFrameIndex = TempPte.u.Trans.PageFrameNumber;
1030 DPRINT("Transition PFN: %lx\n", PageFrameIndex);
1031 Pfn1 = MiGetPfnEntry(PageFrameIndex);
1032
1033 /* One more transition fault! */
1034 InterlockedIncrement(&KeGetCurrentPrcb()->MmTransitionCount);
1035
1036 /* This is from ARM3 -- Windows normally handles this here */
1037 ASSERT(Pfn1->u4.InPageError == 0);
1038
1039 /* See if we should wait before terminating the fault */
1040 if ((Pfn1->u3.e1.ReadInProgress == 1)
1041 || ((Pfn1->u3.e1.WriteInProgress == 1) && StoreInstruction))
1042 {
1043 DPRINT1("The page is currently in a page transition !\n");
1044 *InPageBlock = &Pfn1->u1.Event;
1045 if (PointerPte == Pfn1->PteAddress)
1046 {
1047 DPRINT1("And this if for this particular PTE.\n");
1048 /* The PTE will be made valid by the thread serving the fault */
1049 return STATUS_SUCCESS; // FIXME: Maybe something more descriptive
1050 }
1051 }
1052
1053 /* Windows checks there's some free pages and this isn't an in-page error */
1055 ASSERT(Pfn1->u4.InPageError == 0);
1056
1057 /* ReactOS checks for this */
1059
1060 /* Was this a transition page in the valid list, or free/zero list? */
1061 if (Pfn1->u3.e1.PageLocation == ActiveAndValid)
1062 {
1063 /* All Windows does here is a bunch of sanity checks */
1064 DPRINT("Transition in active list\n");
1067 ASSERT(Pfn1->u2.ShareCount != 0);
1068 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1069 }
1070 else
1071 {
1072 /* Otherwise, the page is removed from its list */
1073 DPRINT("Transition page in free/zero list\n");
1076 }
1077
1078 /* At this point, there should no longer be any in-page errors */
1079 ASSERT(Pfn1->u4.InPageError == 0);
1080
1081 /* Check if this was a PFN with no more share references */
1082 if (Pfn1->u2.ShareCount == 0) MiDropLockCount(Pfn1);
1083
1084 /* Bump the share count and make the page valid */
1085 Pfn1->u2.ShareCount++;
1087
1088 /* Prototype PTEs are in paged pool, which itself might be in transition */
1089 if (FaultingAddress >= MmSystemRangeStart)
1090 {
1091 /* Check if this is a paged pool PTE in transition state */
1092 PointerToPteForProtoPage = MiAddressToPte(PointerPte);
1093 TempPte = *PointerToPteForProtoPage;
1094 if ((TempPte.u.Hard.Valid == 0) && (TempPte.u.Soft.Transition == 1))
1095 {
1096 /* This isn't yet supported */
1097 DPRINT1("Double transition fault not yet supported\n");
1098 ASSERT(FALSE);
1099 }
1100 }
1101
1102 /* Build the final PTE */
1103 ASSERT(PointerPte->u.Hard.Valid == 0);
1104 ASSERT(PointerPte->u.Trans.Prototype == 0);
1105 ASSERT(PointerPte->u.Trans.Transition == 1);
1106 TempPte.u.Long = (PointerPte->u.Long & ~0xFFF) |
1107 (MmProtectToPteMask[PointerPte->u.Trans.Protection]) |
1108 MiDetermineUserGlobalPteMask(PointerPte);
1109
1110 /* Is the PTE writeable? */
1111 if ((Pfn1->u3.e1.Modified) &&
1114 {
1115 /* Make it dirty */
1117 }
1118 else
1119 {
1120 /* Make it clean */
1122 }
1123
1124 /* Write the valid PTE */
1125 MI_WRITE_VALID_PTE(PointerPte, TempPte);
1126
1127 /* Return success */
1129}
1130
1131static
1133NTAPI
1136 IN PMMPTE PointerPte,
1137 IN PMMPTE PointerProtoPte,
1138 IN OUT PMMPFN *OutPfn,
1139 OUT PVOID *PageFileData,
1140 OUT PMMPTE PteValue,
1143 IN PVOID TrapInformation)
1144{
1145 MMPTE TempPte, PteContents;
1146 PMMPFN Pfn1;
1147 PFN_NUMBER PageFrameIndex;
1149 PKEVENT* InPageBlock = NULL;
1150 ULONG Protection;
1151
1152 /* Must be called with an invalid, prototype PTE, with the PFN lock held */
1154 ASSERT(PointerPte->u.Hard.Valid == 0);
1155 ASSERT(PointerPte->u.Soft.Prototype == 1);
1156
1157 /* Read the prototype PTE and check if it's valid */
1158 TempPte = *PointerProtoPte;
1159 if (TempPte.u.Hard.Valid == 1)
1160 {
1161 /* One more user of this mapped page */
1162 PageFrameIndex = PFN_FROM_PTE(&TempPte);
1163 Pfn1 = MiGetPfnEntry(PageFrameIndex);
1164 Pfn1->u2.ShareCount++;
1165
1166 /* Call it a transition */
1167 InterlockedIncrement(&KeGetCurrentPrcb()->MmTransitionCount);
1168
1169 /* Complete the prototype PTE fault -- this will release the PFN lock */
1170 return MiCompleteProtoPteFault(StoreInstruction,
1171 Address,
1172 PointerPte,
1173 PointerProtoPte,
1174 OldIrql,
1175 OutPfn);
1176 }
1177
1178 /* Make sure there's some protection mask */
1179 if (TempPte.u.Long == 0)
1180 {
1181 /* Release the lock */
1182 DPRINT1("Access on reserved section?\n");
1183 MiReleasePfnLock(OldIrql);
1185 }
1186
1187 /* There is no such thing as a decommitted prototype PTE */
1189
1190 /* Check for access rights on the PTE proper */
1191 PteContents = *PointerPte;
1192 if (PteContents.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED)
1193 {
1194 if (!PteContents.u.Proto.ReadOnly)
1195 {
1196 Protection = TempPte.u.Soft.Protection;
1197 }
1198 else
1199 {
1200 Protection = MM_READONLY;
1201 }
1202 /* Check for page acess in software */
1203 Status = MiAccessCheck(PointerProtoPte,
1204 StoreInstruction,
1205 KernelMode,
1206 TempPte.u.Soft.Protection,
1207 TrapInformation,
1208 TRUE);
1210 }
1211 else
1212 {
1213 Protection = PteContents.u.Soft.Protection;
1214 }
1215
1216 /* Check for writing copy on write page */
1217 if (((Protection & MM_WRITECOPY) == MM_WRITECOPY) && StoreInstruction)
1218 {
1219 PFN_NUMBER PageFrameIndex, ProtoPageFrameIndex;
1220 ULONG Color;
1221
1222 /* Resolve the proto fault as if it was a read operation */
1224 Address,
1225 PointerPte,
1226 PointerProtoPte,
1227 OutPfn,
1228 PageFileData,
1229 PteValue,
1230 Process,
1231 OldIrql,
1232 TrapInformation);
1233
1234 if (!NT_SUCCESS(Status))
1235 {
1236 return Status;
1237 }
1238
1239 /* Lock again the PFN lock, MiResolveProtoPteFault unlocked it */
1240 OldIrql = MiAcquirePfnLock();
1241
1242 /* And re-read the proto PTE */
1243 TempPte = *PointerProtoPte;
1244 ASSERT(TempPte.u.Hard.Valid == 1);
1245 ProtoPageFrameIndex = PFN_FROM_PTE(&TempPte);
1246
1249
1250 /* Get a new page for the private copy */
1251 if (Process > HYDRA_PROCESS)
1253 else
1255
1256 PageFrameIndex = MiRemoveAnyPage(Color);
1257 if (PageFrameIndex == 0)
1258 {
1259 MiReleasePfnLock(OldIrql);
1260 return STATUS_NO_MEMORY;
1261 }
1262
1263 /* Perform the copy */
1264 MiCopyPfn(PageFrameIndex, ProtoPageFrameIndex);
1265
1266 /* This will drop everything MiResolveProtoPteFault referenced */
1267 MiDeletePte(PointerPte, Address, Process, PointerProtoPte);
1268
1269 /* Because now we use this */
1270 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1271 MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
1272
1273 /* Fix the protection */
1274 Protection &= ~MM_WRITECOPY;
1275 Protection |= MM_READWRITE;
1277 {
1278 /* Build the user PTE */
1279 MI_MAKE_HARDWARE_PTE_USER(&PteContents, PointerPte, Protection, PageFrameIndex);
1280 }
1281 else
1282 {
1283 /* Build the kernel PTE */
1284 MI_MAKE_HARDWARE_PTE(&PteContents, PointerPte, Protection, PageFrameIndex);
1285 }
1286
1287 /* And finally, write the valid PTE */
1288 MI_WRITE_VALID_PTE(PointerPte, PteContents);
1289
1290 /* The caller expects us to release the PFN lock */
1291 MiReleasePfnLock(OldIrql);
1292 return Status;
1293 }
1294
1295 /* Check for clone PTEs */
1296 if (PointerPte <= MiHighestUserPte) ASSERT(Process->CloneRoot == NULL);
1297
1298 /* We don't support mapped files yet */
1299 ASSERT(TempPte.u.Soft.Prototype == 0);
1300
1301 /* We might however have transition PTEs */
1302 if (TempPte.u.Soft.Transition == 1)
1303 {
1304 /* Resolve the transition fault */
1306 Status = MiResolveTransitionFault(StoreInstruction,
1307 Address,
1308 PointerProtoPte,
1309 Process,
1310 OldIrql,
1311 &InPageBlock);
1313 }
1314 else
1315 {
1316 /* We also don't support paged out pages */
1317 ASSERT(TempPte.u.Soft.PageFileHigh == 0);
1318
1319 /* Resolve the demand zero fault */
1321 PointerProtoPte,
1322 (ULONG)TempPte.u.Soft.Protection,
1323 Process,
1324 OldIrql);
1325#if MI_TRACE_PFNS
1326 /* Update debug info */
1327 if (TrapInformation)
1328 MiGetPfnEntry(PointerProtoPte->u.Hard.PageFrameNumber)->CallSite = (PVOID)KeGetTrapFramePc(TrapInformation);
1329 else
1330 MiGetPfnEntry(PointerProtoPte->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
1331#endif
1332
1334 }
1335
1336 /* Complete the prototype PTE fault -- this will release the PFN lock */
1337 ASSERT(PointerPte->u.Hard.Valid == 0);
1338 return MiCompleteProtoPteFault(StoreInstruction,
1339 Address,
1340 PointerPte,
1341 PointerProtoPte,
1342 OldIrql,
1343 OutPfn);
1344}
1345
1347NTAPI
1350 IN PMMPTE PointerPte,
1351 IN PMMPTE PointerProtoPte,
1352 IN BOOLEAN Recursive,
1354 IN PVOID TrapInformation,
1355 IN PMMVAD Vad)
1356{
1357 MMPTE TempPte;
1358 KIRQL OldIrql, LockIrql;
1360 PMMPTE SuperProtoPte;
1361 PMMPFN Pfn1, OutPfn = NULL;
1362 PFN_NUMBER PageFrameIndex;
1363 PFN_COUNT PteCount, ProcessedPtes;
1364 DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n",
1365 Address,
1366 Process);
1367
1368 /* Make sure the addresses are ok */
1369 ASSERT(PointerPte == MiAddressToPte(Address));
1370
1371 //
1372 // Make sure APCs are off and we're not at dispatch
1373 //
1377
1378 //
1379 // Grab a copy of the PTE
1380 //
1381 TempPte = *PointerPte;
1382
1383 /* Do we have a prototype PTE? */
1384 if (PointerProtoPte)
1385 {
1386 /* This should never happen */
1387 ASSERT(!MI_IS_PHYSICAL_ADDRESS(PointerProtoPte));
1388
1389 /* Check if this is a kernel-mode address */
1390 SuperProtoPte = MiAddressToPte(PointerProtoPte);
1392 {
1393 /* Lock the PFN database */
1394 LockIrql = MiAcquirePfnLock();
1395
1396 /* Has the PTE been made valid yet? */
1397 if (!SuperProtoPte->u.Hard.Valid)
1398 {
1399 ASSERT(FALSE);
1400 }
1401 else if (PointerPte->u.Hard.Valid == 1)
1402 {
1403 ASSERT(FALSE);
1404 }
1405
1406 /* Resolve the fault -- this will release the PFN lock */
1408 Address,
1409 PointerPte,
1410 PointerProtoPte,
1411 &OutPfn,
1412 NULL,
1413 NULL,
1414 Process,
1415 LockIrql,
1416 TrapInformation);
1418
1419 /* Complete this as a transition fault */
1423 return Status;
1424 }
1425 else
1426 {
1427 /* We only handle the lookup path */
1428 ASSERT(PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED);
1429
1430 /* Is there a non-image VAD? */
1431 if ((Vad) &&
1432 (Vad->u.VadFlags.VadType != VadImageMap) &&
1433 !(Vad->u2.VadFlags2.ExtendableFile))
1434 {
1435 /* One day, ReactOS will cluster faults */
1437 DPRINT("Should cluster fault, but won't\n");
1438 }
1439
1440 /* Only one PTE to handle for now */
1441 PteCount = 1;
1442 ProcessedPtes = 0;
1443
1444 /* Lock the PFN database */
1445 LockIrql = MiAcquirePfnLock();
1446
1447 /* We only handle the valid path */
1448 ASSERT(SuperProtoPte->u.Hard.Valid == 1);
1449
1450 /* Capture the PTE */
1451 TempPte = *PointerProtoPte;
1452
1453 /* Loop to handle future case of clustered faults */
1454 while (TRUE)
1455 {
1456 /* For our current usage, this should be true */
1457 if (TempPte.u.Hard.Valid == 1)
1458 {
1459 /* Bump the share count on the PTE */
1460 PageFrameIndex = PFN_FROM_PTE(&TempPte);
1461 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1462 Pfn1->u2.ShareCount++;
1463 }
1464 else if ((TempPte.u.Soft.Prototype == 0) &&
1465 (TempPte.u.Soft.Transition == 1))
1466 {
1467 /* This is a standby page, bring it back from the cache */
1468 PageFrameIndex = TempPte.u.Trans.PageFrameNumber;
1469 DPRINT("oooh, shiny, a soft fault! 0x%lx\n", PageFrameIndex);
1470 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1472
1473 /* Should not yet happen in ReactOS */
1474 ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
1475 ASSERT(Pfn1->u4.InPageError == 0);
1476
1477 /* Get the page */
1479
1480 /* Bump its reference count */
1481 ASSERT(Pfn1->u2.ShareCount == 0);
1482 InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1483 Pfn1->u2.ShareCount++;
1484
1485 /* Make it valid again */
1486 /* This looks like another macro.... */
1488 ASSERT(PointerProtoPte->u.Hard.Valid == 0);
1489 ASSERT(PointerProtoPte->u.Trans.Prototype == 0);
1490 ASSERT(PointerProtoPte->u.Trans.Transition == 1);
1491 TempPte.u.Long = (PointerProtoPte->u.Long & ~0xFFF) |
1492 MmProtectToPteMask[PointerProtoPte->u.Trans.Protection];
1493 TempPte.u.Hard.Valid = 1;
1495
1496 /* Is the PTE writeable? */
1497 if ((Pfn1->u3.e1.Modified) &&
1500 {
1501 /* Make it dirty */
1503 }
1504 else
1505 {
1506 /* Make it clean */
1508 }
1509
1510 /* Write the valid PTE */
1511 MI_WRITE_VALID_PTE(PointerProtoPte, TempPte);
1512 ASSERT(PointerPte->u.Hard.Valid == 0);
1513 }
1514 else
1515 {
1516 /* Page is invalid, get out of the loop */
1517 break;
1518 }
1519
1520 /* One more done, was it the last? */
1521 if (++ProcessedPtes == PteCount)
1522 {
1523 /* Complete the fault */
1525 Address,
1526 PointerPte,
1527 PointerProtoPte,
1528 LockIrql,
1529 &OutPfn);
1530
1531 /* THIS RELEASES THE PFN LOCK! */
1532 break;
1533 }
1534
1535 /* No clustered faults yet */
1536 ASSERT(FALSE);
1537 }
1538
1539 /* Did we resolve the fault? */
1540 if (ProcessedPtes)
1541 {
1542 /* Bump the transition count */
1543 InterlockedExchangeAddSizeT(&KeGetCurrentPrcb()->MmTransitionCount, ProcessedPtes);
1544 ProcessedPtes--;
1545
1546 /* Loop all the processing we did */
1547 ASSERT(ProcessedPtes == 0);
1548
1549 /* Complete this as a transition fault */
1554 }
1555
1556 /* We did not -- PFN lock is still held, prepare to resolve prototype PTE fault */
1557 OutPfn = MI_PFN_ELEMENT(SuperProtoPte->u.Hard.PageFrameNumber);
1559 ASSERT(OutPfn->u3.e2.ReferenceCount > 1);
1560 ASSERT(PointerPte->u.Hard.Valid == 0);
1561
1562 /* Resolve the fault -- this will release the PFN lock */
1564 Address,
1565 PointerPte,
1566 PointerProtoPte,
1567 &OutPfn,
1568 NULL,
1569 NULL,
1570 Process,
1571 LockIrql,
1572 TrapInformation);
1573 //ASSERT(Status != STATUS_ISSUE_PAGING_IO);
1574 //ASSERT(Status != STATUS_REFAULT);
1575 //ASSERT(Status != STATUS_PTE_CHANGED);
1576
1577 /* Did the routine clean out the PFN or should we? */
1578 if (OutPfn)
1579 {
1580 /* We had a locked PFN, so acquire the PFN lock to dereference it */
1581 ASSERT(PointerProtoPte != NULL);
1582 OldIrql = MiAcquirePfnLock();
1583
1584 /* Dereference the locked PFN */
1586 ASSERT(OutPfn->u3.e2.ReferenceCount >= 1);
1587
1588 /* And now release the lock */
1589 MiReleasePfnLock(OldIrql);
1590 }
1591
1592 /* Complete this as a transition fault */
1596 return Status;
1597 }
1598 }
1599
1600 /* Is this a transition PTE */
1601 if (TempPte.u.Soft.Transition)
1602 {
1603 PKEVENT* InPageBlock = NULL;
1604 PKEVENT PreviousPageEvent;
1605 KEVENT CurrentPageEvent;
1606
1607 /* Lock the PFN database */
1608 LockIrql = MiAcquirePfnLock();
1609
1610 /* Resolve */
1611 Status = MiResolveTransitionFault(!MI_IS_NOT_PRESENT_FAULT(FaultCode), Address, PointerPte, Process, LockIrql, &InPageBlock);
1612
1614
1615 if (InPageBlock != NULL)
1616 {
1617 /* Another thread is reading or writing this page. Put us into the waiting queue. */
1618 KeInitializeEvent(&CurrentPageEvent, NotificationEvent, FALSE);
1619 PreviousPageEvent = *InPageBlock;
1620 *InPageBlock = &CurrentPageEvent;
1621 }
1622
1623 /* And now release the lock and leave*/
1624 MiReleasePfnLock(LockIrql);
1625
1626 if (InPageBlock != NULL)
1627 {
1628 KeWaitForSingleObject(&CurrentPageEvent, WrPageIn, KernelMode, FALSE, NULL);
1629
1630 /* Let's the chain go on */
1631 if (PreviousPageEvent)
1632 {
1633 KeSetEvent(PreviousPageEvent, IO_NO_INCREMENT, FALSE);
1634 }
1635 }
1636
1640 return Status;
1641 }
1642
1643 /* Should we page the data back in ? */
1644 if (TempPte.u.Soft.PageFileHigh != 0)
1645 {
1646 /* Lock the PFN database */
1647 LockIrql = MiAcquirePfnLock();
1648
1649 /* Resolve */
1650 Status = MiResolvePageFileFault(!MI_IS_NOT_PRESENT_FAULT(FaultCode), Address, PointerPte, Process, &LockIrql);
1651
1652 /* And now release the lock and leave*/
1653 MiReleasePfnLock(LockIrql);
1654
1658 return Status;
1659 }
1660
1661 //
1662 // The PTE must be invalid but not completely empty. It must also not be a
1663 // prototype a transition or a paged-out PTE as those scenarii should've been handled above.
1664 // These are all Windows checks
1665 //
1666 ASSERT(TempPte.u.Hard.Valid == 0);
1667 ASSERT(TempPte.u.Soft.Prototype == 0);
1668 ASSERT(TempPte.u.Soft.Transition == 0);
1669 ASSERT(TempPte.u.Soft.PageFileHigh == 0);
1670 ASSERT(TempPte.u.Long != 0);
1671
1672 //
1673 // If we got this far, the PTE can only be a demand zero PTE, which is what
1674 // we want. Go handle it!
1675 //
1677 PointerPte,
1678 (ULONG)TempPte.u.Soft.Protection,
1679 Process,
1680 MM_NOIRQL);
1682 if (NT_SUCCESS(Status))
1683 {
1684#if MI_TRACE_PFNS
1685 /* Update debug info */
1686 if (TrapInformation)
1687 MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = (PVOID)KeGetTrapFramePc(TrapInformation);
1688 else
1689 MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
1690#endif
1691
1692 //
1693 // Make sure we're returning in a sane state and pass the status down
1694 //
1697 return Status;
1698 }
1699
1700 //
1701 // Return status
1702 //
1703 return Status;
1704}
1705
1707NTAPI
1711 IN PVOID TrapInformation)
1712{
1713 KIRQL OldIrql = KeGetCurrentIrql(), LockIrql;
1714 PMMPTE ProtoPte = NULL;
1715 PMMPTE PointerPte = MiAddressToPte(Address);
1716 PMMPDE PointerPde = MiAddressToPde(Address);
1717#if (_MI_PAGING_LEVELS >= 3)
1718 PMMPDE PointerPpe = MiAddressToPpe(Address);
1719#if (_MI_PAGING_LEVELS == 4)
1720 PMMPDE PointerPxe = MiAddressToPxe(Address);
1721#endif
1722#endif
1723 MMPTE TempPte;
1724 PETHREAD CurrentThread;
1725 PEPROCESS CurrentProcess;
1727 PMMSUPPORT WorkingSet;
1728 ULONG ProtectionCode;
1729 PMMVAD Vad = NULL;
1730 PFN_NUMBER PageFrameIndex;
1731 ULONG Color;
1732 BOOLEAN IsSessionAddress;
1733 PMMPFN Pfn1;
1734 DPRINT("ARM3 FAULT AT: %p\n", Address);
1735
1736 /* Check for page fault on high IRQL */
1737 if (OldIrql > APC_LEVEL)
1738 {
1739#if (_MI_PAGING_LEVELS < 3)
1740 /* Could be a page table for paged pool, which we'll allow */
1741 if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)) MiSynchronizeSystemPde((PMMPDE)PointerPte);
1743#endif
1744 /* Check if any of the top-level pages are invalid */
1745 if (
1746#if (_MI_PAGING_LEVELS == 4)
1747 (PointerPxe->u.Hard.Valid == 0) ||
1748#endif
1749#if (_MI_PAGING_LEVELS >= 3)
1750 (PointerPpe->u.Hard.Valid == 0) ||
1751#endif
1752 (PointerPde->u.Hard.Valid == 0) ||
1753 (PointerPte->u.Hard.Valid == 0))
1754 {
1755 /* This fault is not valid, print out some debugging help */
1756 DbgPrint("MM:***PAGE FAULT AT IRQL > 1 Va %p, IRQL %lx\n",
1757 Address,
1758 OldIrql);
1759 if (TrapInformation)
1760 {
1761 PKTRAP_FRAME TrapFrame = TrapInformation;
1762#ifdef _M_IX86
1763 DbgPrint("MM:***EIP %p, EFL %p\n", TrapFrame->Eip, TrapFrame->EFlags);
1764 DbgPrint("MM:***EAX %p, ECX %p EDX %p\n", TrapFrame->Eax, TrapFrame->Ecx, TrapFrame->Edx);
1765 DbgPrint("MM:***EBX %p, ESI %p EDI %p\n", TrapFrame->Ebx, TrapFrame->Esi, TrapFrame->Edi);
1766#elif defined(_M_AMD64)
1767 DbgPrint("MM:***RIP %p, EFL %p\n", TrapFrame->Rip, TrapFrame->EFlags);
1768 DbgPrint("MM:***RAX %p, RCX %p RDX %p\n", TrapFrame->Rax, TrapFrame->Rcx, TrapFrame->Rdx);
1769 DbgPrint("MM:***RBX %p, RSI %p RDI %p\n", TrapFrame->Rbx, TrapFrame->Rsi, TrapFrame->Rdi);
1770#elif defined(_M_ARM)
1771 DbgPrint("MM:***PC %p\n", TrapFrame->Pc);
1772 DbgPrint("MM:***R0 %p, R1 %p R2 %p, R3 %p\n", TrapFrame->R0, TrapFrame->R1, TrapFrame->R2, TrapFrame->R3);
1773 DbgPrint("MM:***R11 %p, R12 %p SP %p, LR %p\n", TrapFrame->R11, TrapFrame->R12, TrapFrame->Sp, TrapFrame->Lr);
1774#endif
1775 }
1776
1777 /* Tell the trap handler to fail */
1778 return STATUS_IN_PAGE_ERROR | 0x10000000;
1779 }
1780
1781 /* Not yet implemented in ReactOS */
1782 ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
1783 ASSERT((!MI_IS_NOT_PRESENT_FAULT(FaultCode) && MI_IS_PAGE_COPY_ON_WRITE(PointerPte)) == FALSE);
1784
1785 /* Check if this was a write */
1786 if (MI_IS_WRITE_ACCESS(FaultCode))
1787 {
1788 /* Was it to a read-only page? */
1789 Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1790 if (!(PointerPte->u.Long & PTE_READWRITE) &&
1792 {
1793 /* Crash with distinguished bugcheck code */
1794 KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1796 PointerPte->u.Long,
1797 (ULONG_PTR)TrapInformation,
1798 10);
1799 }
1800 }
1801
1802 /* Nothing is actually wrong */
1803 DPRINT1("Fault at IRQL %u is ok (%p)\n", OldIrql, Address);
1804 return STATUS_SUCCESS;
1805 }
1806
1807 /* Check for kernel fault address */
1809 {
1810 /* Bail out, if the fault came from user mode */
1811 if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
1812
1813#if (_MI_PAGING_LEVELS == 2)
1814 if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)) MiSynchronizeSystemPde((PMMPDE)PointerPte);
1816#endif
1817
1818 /* Check if the higher page table entries are invalid */
1819 if (
1820#if (_MI_PAGING_LEVELS == 4)
1821 /* AMD64 system, check if PXE is invalid */
1822 (PointerPxe->u.Hard.Valid == 0) ||
1823#endif
1824#if (_MI_PAGING_LEVELS >= 3)
1825 /* PAE/AMD64 system, check if PPE is invalid */
1826 (PointerPpe->u.Hard.Valid == 0) ||
1827#endif
1828 /* Always check if the PDE is valid */
1829 (PointerPde->u.Hard.Valid == 0))
1830 {
1831 /* PXE/PPE/PDE (still) not valid, kill the system */
1832 KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
1834 FaultCode,
1835 (ULONG_PTR)TrapInformation,
1836 2);
1837 }
1838
1839 /* Not handling session faults yet */
1840 IsSessionAddress = MI_IS_SESSION_ADDRESS(Address);
1841
1842 /* The PDE is valid, so read the PTE */
1843 TempPte = *PointerPte;
1844 if (TempPte.u.Hard.Valid == 1)
1845 {
1846 /* Check if this was system space or session space */
1847 if (!IsSessionAddress)
1848 {
1849 /* Check if the PTE is still valid under PFN lock */
1850 OldIrql = MiAcquirePfnLock();
1851 TempPte = *PointerPte;
1852 if (TempPte.u.Hard.Valid)
1853 {
1854 /* Check if this was a write */
1855 if (MI_IS_WRITE_ACCESS(FaultCode))
1856 {
1857 /* Was it to a read-only page? */
1858 Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1859 if (!(PointerPte->u.Long & PTE_READWRITE) &&
1861 {
1862 /* Crash with distinguished bugcheck code */
1863 KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1865 PointerPte->u.Long,
1866 (ULONG_PTR)TrapInformation,
1867 11);
1868 }
1869 }
1870
1871 /* Check for execution of non-executable memory */
1872 if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
1874 {
1875 KeBugCheckEx(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY,
1877 (ULONG_PTR)TempPte.u.Long,
1878 (ULONG_PTR)TrapInformation,
1879 1);
1880 }
1881 }
1882
1883 /* Release PFN lock and return all good */
1884 MiReleasePfnLock(OldIrql);
1885 return STATUS_SUCCESS;
1886 }
1887 }
1888#if (_MI_PAGING_LEVELS == 2)
1889 /* Check if this was a session PTE that needs to remap the session PDE */
1891 {
1892 /* Do the remapping */
1893 Status = MiCheckPdeForSessionSpace(Address);
1894 if (!NT_SUCCESS(Status))
1895 {
1896 /* It failed, this address is invalid */
1897 KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
1899 FaultCode,
1900 (ULONG_PTR)TrapInformation,
1901 6);
1902 }
1903 }
1904#else
1905
1906_WARN("Session space stuff is not implemented yet!")
1907
1908#endif
1909
1910 /* Check for a fault on the page table or hyperspace */
1912 {
1913#if (_MI_PAGING_LEVELS < 3)
1914 /* Windows does this check but I don't understand why -- it's done above! */
1916#endif
1917 /* Handle this as a user mode fault */
1918 goto UserFault;
1919 }
1920
1921 /* Get the current thread */
1922 CurrentThread = PsGetCurrentThread();
1923
1924 /* What kind of address is this */
1925 if (!IsSessionAddress)
1926 {
1927 /* Use the system working set */
1928 WorkingSet = &MmSystemCacheWs;
1929 CurrentProcess = NULL;
1930
1931 /* Make sure we don't have a recursive working set lock */
1932 if ((CurrentThread->OwnsProcessWorkingSetExclusive) ||
1933 (CurrentThread->OwnsProcessWorkingSetShared) ||
1934 (CurrentThread->OwnsSystemWorkingSetExclusive) ||
1935 (CurrentThread->OwnsSystemWorkingSetShared) ||
1936 (CurrentThread->OwnsSessionWorkingSetExclusive) ||
1937 (CurrentThread->OwnsSessionWorkingSetShared))
1938 {
1939 /* Fail */
1940 return STATUS_IN_PAGE_ERROR | 0x10000000;
1941 }
1942 }
1943 else
1944 {
1945 /* Use the session process and working set */
1946 CurrentProcess = HYDRA_PROCESS;
1947 WorkingSet = &MmSessionSpace->GlobalVirtualAddress->Vm;
1948
1949 /* Make sure we don't have a recursive working set lock */
1950 if ((CurrentThread->OwnsSessionWorkingSetExclusive) ||
1951 (CurrentThread->OwnsSessionWorkingSetShared))
1952 {
1953 /* Fail */
1954 return STATUS_IN_PAGE_ERROR | 0x10000000;
1955 }
1956 }
1957RetryKernel:
1958 /* Acquire the working set lock */
1959 KeRaiseIrql(APC_LEVEL, &LockIrql);
1960 MiLockWorkingSet(CurrentThread, WorkingSet);
1961
1962 /* Re-read PTE now that we own the lock */
1963 TempPte = *PointerPte;
1964 if (TempPte.u.Hard.Valid == 1)
1965 {
1966 /* Check if this was a write */
1967 if (MI_IS_WRITE_ACCESS(FaultCode))
1968 {
1969 /* Was it to a read-only page that is not copy on write? */
1970 Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1971 if (!(TempPte.u.Long & PTE_READWRITE) &&
1974 {
1975 /* Case not yet handled */
1976 ASSERT(!IsSessionAddress);
1977
1978 /* Crash with distinguished bugcheck code */
1979 KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1981 TempPte.u.Long,
1982 (ULONG_PTR)TrapInformation,
1983 12);
1984 }
1985 }
1986
1987 /* Check for execution of non-executable memory */
1988 if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
1990 {
1991 KeBugCheckEx(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY,
1993 (ULONG_PTR)TempPte.u.Long,
1994 (ULONG_PTR)TrapInformation,
1995 2);
1996 }
1997
1998 /* Check for read-only write in session space */
1999 if ((IsSessionAddress) &&
2000 MI_IS_WRITE_ACCESS(FaultCode) &&
2002 {
2003 /* Sanity check */
2005
2006 /* Was this COW? */
2008 {
2009 /* Then this is not allowed */
2010 KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
2012 (ULONG_PTR)TempPte.u.Long,
2013 (ULONG_PTR)TrapInformation,
2014 13);
2015 }
2016
2017 /* Otherwise, handle COW */
2018 ASSERT(FALSE);
2019 }
2020
2021 /* Release the working set */
2022 MiUnlockWorkingSet(CurrentThread, WorkingSet);
2023 KeLowerIrql(LockIrql);
2024
2025 /* Otherwise, the PDE was probably invalid, and all is good now */
2026 return STATUS_SUCCESS;
2027 }
2028
2029 /* Check one kind of prototype PTE */
2030 if (TempPte.u.Soft.Prototype)
2031 {
2032 /* Make sure protected pool is on, and that this is a pool address */
2039 {
2040 /* Bad boy, bad boy, whatcha gonna do, whatcha gonna do when ARM3 comes for you! */
2041 KeBugCheckEx(DRIVER_CAUGHT_MODIFYING_FREED_POOL,
2043 FaultCode,
2044 Mode,
2045 4);
2046 }
2047
2048 /* Get the prototype PTE! */
2049 ProtoPte = MiProtoPteToPte(&TempPte);
2050
2051 /* Do we need to locate the prototype PTE in session space? */
2052 if ((IsSessionAddress) &&
2053 (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED))
2054 {
2055 /* Yep, go find it as well as the VAD for it */
2056 ProtoPte = MiCheckVirtualAddress(Address,
2057 &ProtectionCode,
2058 &Vad);
2059 ASSERT(ProtoPte != NULL);
2060 }
2061 }
2062 else
2063 {
2064 /* We don't implement transition PTEs */
2065 ASSERT(TempPte.u.Soft.Transition == 0);
2066
2067 /* Check for no-access PTE */
2068 if (TempPte.u.Soft.Protection == MM_NOACCESS)
2069 {
2070 /* Bugcheck the system! */
2071 KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
2073 FaultCode,
2074 (ULONG_PTR)TrapInformation,
2075 1);
2076 }
2077
2078 /* Check for no protecton at all */
2079 if (TempPte.u.Soft.Protection == MM_ZERO_ACCESS)
2080 {
2081 /* Bugcheck the system! */
2082 KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
2084 FaultCode,
2085 (ULONG_PTR)TrapInformation,
2086 0);
2087 }
2088 }
2089
2090 /* Check for demand page */
2091 if (MI_IS_WRITE_ACCESS(FaultCode) &&
2092 !(ProtoPte) &&
2093 !(IsSessionAddress) &&
2094 !(TempPte.u.Hard.Valid))
2095 {
2096 /* Get the protection code */
2097 ASSERT(TempPte.u.Soft.Transition == 0);
2098 if (!(TempPte.u.Soft.Protection & MM_READWRITE))
2099 {
2100 /* Bugcheck the system! */
2101 KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
2103 TempPte.u.Long,
2104 (ULONG_PTR)TrapInformation,
2105 14);
2106 }
2107 }
2108
2109 /* Now do the real fault handling */
2110 Status = MiDispatchFault(FaultCode,
2111 Address,
2112 PointerPte,
2113 ProtoPte,
2114 FALSE,
2115 CurrentProcess,
2116 TrapInformation,
2117 NULL);
2118
2119 /* Release the working set */
2121 MiUnlockWorkingSet(CurrentThread, WorkingSet);
2122 KeLowerIrql(LockIrql);
2123
2124 if (Status == STATUS_NO_MEMORY)
2125 {
2127 goto RetryKernel;
2128 }
2129
2130 /* We are done! */
2131 DPRINT("Fault resolved with status: %lx\n", Status);
2132 return Status;
2133 }
2134
2135 /* This is a user fault */
2136UserFault:
2137 CurrentThread = PsGetCurrentThread();
2138 CurrentProcess = (PEPROCESS)CurrentThread->Tcb.ApcState.Process;
2139
2140 /* Lock the working set */
2141 MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
2142
2143 ProtectionCode = MM_INVALID_PROTECTION;
2144
2145#if (_MI_PAGING_LEVELS == 4)
2146 /* Check if the PXE is valid */
2147 if (PointerPxe->u.Hard.Valid == 0)
2148 {
2149 /* Right now, we only handle scenarios where the PXE is totally empty */
2150 ASSERT(PointerPxe->u.Long == 0);
2151
2152 /* This is only possible for user mode addresses! */
2153 ASSERT(PointerPte <= MiHighestUserPte);
2154
2155 /* Check if we have a VAD */
2156 MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2157 if (ProtectionCode == MM_NOACCESS)
2158 {
2159 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2161 }
2162
2163 /* Resolve a demand zero fault */
2164 Status = MiResolveDemandZeroFault(PointerPpe,
2165 PointerPxe,
2167 CurrentProcess,
2168 MM_NOIRQL);
2169 if (!NT_SUCCESS(Status))
2170 {
2171 goto ExitUser;
2172 }
2173
2174 /* We should come back with a valid PXE */
2175 ASSERT(PointerPxe->u.Hard.Valid == 1);
2176 }
2177#endif
2178
2179#if (_MI_PAGING_LEVELS >= 3)
2180 /* Check if the PPE is valid */
2181 if (PointerPpe->u.Hard.Valid == 0)
2182 {
2183 /* Right now, we only handle scenarios where the PPE is totally empty */
2184 ASSERT(PointerPpe->u.Long == 0);
2185
2186 /* This is only possible for user mode addresses! */
2187 ASSERT(PointerPte <= MiHighestUserPte);
2188
2189 /* Check if we have a VAD, unless we did this already */
2190 if (ProtectionCode == MM_INVALID_PROTECTION)
2191 {
2192 MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2193 }
2194
2195 if (ProtectionCode == MM_NOACCESS)
2196 {
2197 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2199 }
2200
2201 /* Resolve a demand zero fault */
2202 Status = MiResolveDemandZeroFault(PointerPde,
2203 PointerPpe,
2205 CurrentProcess,
2206 MM_NOIRQL);
2207 if (!NT_SUCCESS(Status))
2208 {
2209 goto ExitUser;
2210 }
2211
2212 /* We should come back with a valid PPE */
2213 ASSERT(PointerPpe->u.Hard.Valid == 1);
2215 }
2216#endif
2217
2218 /* Check if the PDE is invalid */
2219 if (PointerPde->u.Hard.Valid == 0)
2220 {
2221 /* Right now, we only handle scenarios where the PDE is totally empty */
2222 ASSERT(PointerPde->u.Long == 0);
2223
2224 /* And go dispatch the fault on the PDE. This should handle the demand-zero */
2225#if MI_TRACE_PFNS
2226 UserPdeFault = TRUE;
2227#endif
2228 /* Check if we have a VAD, unless we did this already */
2229 if (ProtectionCode == MM_INVALID_PROTECTION)
2230 {
2231 MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2232 }
2233
2234 if (ProtectionCode == MM_NOACCESS)
2235 {
2236#if (_MI_PAGING_LEVELS == 2)
2237 /* Could be a page table for paged pool */
2239#endif
2240 /* Has the code above changed anything -- is this now a valid PTE? */
2241 Status = (PointerPde->u.Hard.Valid == 1) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
2242
2243 /* Either this was a bogus VA or we've fixed up a paged pool PDE */
2244 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2245 return Status;
2246 }
2247
2248 /* Resolve a demand zero fault */
2249 Status = MiResolveDemandZeroFault(PointerPte,
2250 PointerPde,
2252 CurrentProcess,
2253 MM_NOIRQL);
2254 if (!NT_SUCCESS(Status))
2255 {
2256 goto ExitUser;
2257 }
2258
2259#if _MI_PAGING_LEVELS >= 3
2261#endif
2262
2263#if MI_TRACE_PFNS
2264 UserPdeFault = FALSE;
2265 /* Update debug info */
2266 if (TrapInformation)
2267 MiGetPfnEntry(PointerPde->u.Hard.PageFrameNumber)->CallSite = (PVOID)KeGetTrapFramePc(TrapInformation);
2268 else
2269 MiGetPfnEntry(PointerPde->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
2270#endif
2271 /* We should come back with APCs enabled, and with a valid PDE */
2273 ASSERT(PointerPde->u.Hard.Valid == 1);
2274 }
2275 else
2276 {
2277 /* Not yet implemented in ReactOS */
2278 ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
2279 }
2280
2281 /* Now capture the PTE. */
2282 TempPte = *PointerPte;
2283
2284 /* Check if the PTE is valid */
2285 if (TempPte.u.Hard.Valid)
2286 {
2287 /* Check if this is a write on a readonly PTE */
2288 if (MI_IS_WRITE_ACCESS(FaultCode))
2289 {
2290 /* Is this a copy on write PTE? */
2292 {
2293 PFN_NUMBER PageFrameIndex, OldPageFrameIndex;
2294 PMMPFN Pfn1;
2295
2296 LockIrql = MiAcquirePfnLock();
2297
2299
2301 MI_SET_PROCESS(CurrentProcess);
2302
2303 /* Allocate a new page and copy it */
2304 PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(CurrentProcess));
2305 if (PageFrameIndex == 0)
2306 {
2307 MiReleasePfnLock(LockIrql);
2309 goto ExitUser;
2310 }
2311 OldPageFrameIndex = PFN_FROM_PTE(&TempPte);
2312
2313 MiCopyPfn(PageFrameIndex, OldPageFrameIndex);
2314
2315 /* Dereference whatever this PTE is referencing */
2316 Pfn1 = MI_PFN_ELEMENT(OldPageFrameIndex);
2317 ASSERT(Pfn1->u3.e1.PrototypePte == 1);
2318 ASSERT(!MI_IS_PFN_DELETED(Pfn1));
2319 ProtoPte = Pfn1->PteAddress;
2320 MiDeletePte(PointerPte, Address, CurrentProcess, ProtoPte);
2321
2322 /* And make a new shiny one with our page */
2323 MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
2324 TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
2325 TempPte.u.Hard.Write = 1;
2326 TempPte.u.Hard.CopyOnWrite = 0;
2327
2328 MI_WRITE_VALID_PTE(PointerPte, TempPte);
2329
2330 MiReleasePfnLock(LockIrql);
2331
2332 /* Return the status */
2333 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2335 }
2336
2337 /* Is this a read-only PTE? */
2339 {
2340 /* Return the status */
2341 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2343 }
2344 }
2345
2346#if _MI_HAS_NO_EXECUTE
2347 /* Check for execution of non-executable memory */
2348 if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
2350 {
2351 /* Check if execute enable was set */
2352 if (CurrentProcess->Pcb.Flags.ExecuteEnable)
2353 {
2354 /* Fix up the PTE to be executable */
2355 TempPte.u.Hard.NoExecute = 0;
2356 MI_UPDATE_VALID_PTE(PointerPte, TempPte);
2357 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2358 return STATUS_SUCCESS;
2359 }
2360
2361 /* Return the status */
2362 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2364 }
2365#endif
2366
2367 /* The fault has already been resolved by a different thread */
2368 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2369 return STATUS_SUCCESS;
2370 }
2371
2372 /* Quick check for demand-zero */
2375 {
2376 /* Resolve the fault */
2378 PointerPte,
2379 TempPte.u.Soft.Protection,
2380 CurrentProcess,
2381 MM_NOIRQL);
2382 if (!NT_SUCCESS(Status))
2383 {
2384 goto ExitUser;
2385 }
2386
2387#if MI_TRACE_PFNS
2388 /* Update debug info */
2389 if (TrapInformation)
2390 MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = (PVOID)KeGetTrapFramePc(TrapInformation);
2391 else
2392 MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
2393#endif
2394
2395 /* Return the status */
2396 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2398 }
2399
2400 /* Check for zero PTE */
2401 if (TempPte.u.Long == 0)
2402 {
2403 /* Check if this address range belongs to a valid allocation (VAD) */
2404 ProtoPte = MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2405 if (ProtectionCode == MM_NOACCESS)
2406 {
2407#if (_MI_PAGING_LEVELS == 2)
2408 /* Could be a page table for paged pool */
2410#endif
2411 /* Has the code above changed anything -- is this now a valid PTE? */
2412 Status = (PointerPte->u.Hard.Valid == 1) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
2413
2414 /* Either this was a bogus VA or we've fixed up a paged pool PDE */
2415 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2416 return Status;
2417 }
2418
2419 /*
2420 * Check if this is a real user-mode address or actually a kernel-mode
2421 * page table for a user mode address
2422 */
2424#if _MI_PAGING_LEVELS >= 3
2426#if _MI_PAGING_LEVELS == 4
2428#endif
2429#endif
2430 )
2431 {
2432 /* Add an additional page table reference */
2434 }
2435
2436 /* Is this a guard page? */
2437 if ((ProtectionCode & MM_PROTECT_SPECIAL) == MM_GUARDPAGE)
2438 {
2439 /* The VAD protection cannot be MM_DECOMMIT! */
2440 ASSERT(ProtectionCode != MM_DECOMMIT);
2441
2442 /* Remove the bit */
2443 TempPte.u.Soft.Protection = ProtectionCode & ~MM_GUARDPAGE;
2444 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2445
2446 /* Not supported */
2447 ASSERT(ProtoPte == NULL);
2448 ASSERT(CurrentThread->ApcNeeded == 0);
2449
2450 /* Drop the working set lock */
2451 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2453
2454 /* Handle stack expansion */
2455 return MiCheckForUserStackOverflow(Address, TrapInformation);
2456 }
2457
2458 /* Did we get a prototype PTE back? */
2459 if (!ProtoPte)
2460 {
2461 /* Is this PTE actually part of the PDE-PTE self-mapping directory? */
2462 if (PointerPde == MiAddressToPde(PTE_BASE))
2463 {
2464 /* Then it's really a demand-zero PDE (on behalf of user-mode) */
2465#ifdef _M_ARM
2466 _WARN("This is probably completely broken!");
2468#else
2470#endif
2471 }
2472 else
2473 {
2474 /* No, create a new PTE. First, write the protection */
2475 TempPte.u.Soft.Protection = ProtectionCode;
2476 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2477 }
2478
2479 /* Lock the PFN database since we're going to grab a page */
2480 OldIrql = MiAcquirePfnLock();
2481
2482 /* Make sure we have enough pages */
2483 //ASSERT(MmAvailablePages >= 32);
2484
2485 /* Try to get a zero page */
2487 MI_SET_PROCESS2(CurrentProcess->ImageFileName);
2488 Color = MI_GET_NEXT_PROCESS_COLOR(CurrentProcess);
2489 PageFrameIndex = MiRemoveZeroPageSafe(Color);
2490 if (!PageFrameIndex)
2491 {
2492 /* Grab a page out of there. Later we should grab a colored zero page */
2493 PageFrameIndex = MiRemoveAnyPage(Color);
2494
2495 /* Release the lock since we need to do some zeroing */
2496 MiReleasePfnLock(OldIrql);
2497
2498 if (PageFrameIndex == 0)
2499 {
2501 goto ExitUser;
2502 }
2503
2504 /* Zero out the page, since it's for user-mode */
2505 MiZeroPfn(PageFrameIndex);
2506
2507 /* Grab the lock again so we can initialize the PFN entry */
2508 OldIrql = MiAcquirePfnLock();
2509 }
2510
2511 /* Initialize the PFN entry now */
2512 MiInitializePfn(PageFrameIndex, PointerPte, 1);
2513
2514 /* Increment the count of pages in the process */
2515 CurrentProcess->NumberOfPrivatePages++;
2516
2517 /* One more demand-zero fault */
2518 KeGetCurrentPrcb()->MmDemandZeroCount++;
2519
2520 /* And we're done with the lock */
2521 MiReleasePfnLock(OldIrql);
2522
2523 /* Fault on user PDE, or fault on user PTE? */
2524 if (PointerPte <= MiHighestUserPte)
2525 {
2526 /* User fault, build a user PTE */
2528 PointerPte,
2529 PointerPte->u.Soft.Protection,
2530 PageFrameIndex);
2531 }
2532 else
2533 {
2534 /* This is a user-mode PDE, create a kernel PTE for it */
2536 PointerPte,
2537 PointerPte->u.Soft.Protection,
2538 PageFrameIndex);
2539 }
2540
2541 /* Write the dirty bit for writeable pages */
2543
2544 /* And now write down the PTE, making the address valid */
2545 MI_WRITE_VALID_PTE(PointerPte, TempPte);
2546 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
2547 ASSERT(Pfn1->u1.Event == NULL);
2548
2549 /* Demand zero */
2551 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2553 }
2554
2555 /* We should have a valid protection here */
2556 ASSERT(ProtectionCode != 0x100);
2557
2558 /* Write the prototype PTE */
2560 TempPte.u.Soft.Protection = ProtectionCode;
2561 ASSERT(TempPte.u.Long != 0);
2562 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2563 }
2564 else
2565 {
2566 /* Get the protection code and check if this is a proto PTE */
2567 ProtectionCode = (ULONG)TempPte.u.Soft.Protection;
2568 if (TempPte.u.Soft.Prototype)
2569 {
2570 /* Do we need to go find the real PTE? */
2571 if (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
2572 {
2573 /* Get the prototype pte and VAD for it */
2574 ProtoPte = MiCheckVirtualAddress(Address,
2575 &ProtectionCode,
2576 &Vad);
2577 if (!ProtoPte)
2578 {
2580 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2582 }
2583 }
2584 else
2585 {
2586 /* Get the prototype PTE! */
2587 ProtoPte = MiProtoPteToPte(&TempPte);
2588
2589 /* Is it read-only */
2590 if (TempPte.u.Proto.ReadOnly)
2591 {
2592 /* Set read-only code */
2593 ProtectionCode = MM_READONLY;
2594 }
2595 else
2596 {
2597 /* Set unknown protection */
2598 ProtectionCode = 0x100;
2599 ASSERT(CurrentProcess->CloneRoot != NULL);
2600 }
2601 }
2602 }
2603 }
2604
2605 /* Do we have a valid protection code? */
2606 if (ProtectionCode != 0x100)
2607 {
2608 /* Run a software access check first, including to detect guard pages */
2609 Status = MiAccessCheck(PointerPte,
2610 !MI_IS_NOT_PRESENT_FAULT(FaultCode),
2611 Mode,
2612 ProtectionCode,
2613 TrapInformation,
2614 FALSE);
2615 if (Status != STATUS_SUCCESS)
2616 {
2617 /* Not supported */
2618 ASSERT(CurrentThread->ApcNeeded == 0);
2619
2620 /* Drop the working set lock */
2621 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2623
2624 /* Did we hit a guard page? */
2626 {
2627 /* Handle stack expansion */
2628 return MiCheckForUserStackOverflow(Address, TrapInformation);
2629 }
2630
2631 /* Otherwise, fail back to the caller directly */
2632 return Status;
2633 }
2634 }
2635
2636 /* Dispatch the fault */
2637 Status = MiDispatchFault(FaultCode,
2638 Address,
2639 PointerPte,
2640 ProtoPte,
2641 FALSE,
2642 CurrentProcess,
2643 TrapInformation,
2644 Vad);
2645
2646ExitUser:
2647
2648 /* Return the status */
2650 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2651
2652 if (Status == STATUS_NO_MEMORY)
2653 {
2654 /* Don't wait on the balancer while holding AddressCreationLock (CORE-20761) */
2655 if (CurrentProcess->AddressCreationLock.Owner == KeGetCurrentThread())
2656 {
2657 static LARGE_INTEGER TinyTime = {{-1L, -1L}};
2660 }
2661 else
2662 {
2664 }
2665
2666 goto UserFault;
2667 }
2668
2669 return Status;
2670}
2671
2673NTAPI
2675{
2676 PKPROCESS CurrentProcess = &PsGetCurrentProcess()->Pcb;
2678
2679 *ExecuteOptions = 0;
2680
2681 if (CurrentProcess->Flags.ExecuteDisable)
2682 {
2683 *ExecuteOptions |= MEM_EXECUTE_OPTION_DISABLE;
2684 }
2685
2686 if (CurrentProcess->Flags.ExecuteEnable)
2687 {
2688 *ExecuteOptions |= MEM_EXECUTE_OPTION_ENABLE;
2689 }
2690
2691 if (CurrentProcess->Flags.DisableThunkEmulation)
2692 {
2694 }
2695
2696 if (CurrentProcess->Flags.Permanent)
2697 {
2698 *ExecuteOptions |= MEM_EXECUTE_OPTION_PERMANENT;
2699 }
2700
2701 if (CurrentProcess->Flags.ExecuteDispatchEnable)
2702 {
2704 }
2705
2706 if (CurrentProcess->Flags.ImageDispatchEnable)
2707 {
2709 }
2710
2711 return STATUS_SUCCESS;
2712}
2713
2715NTAPI
2717{
2718 PKPROCESS CurrentProcess = &PsGetCurrentProcess()->Pcb;
2719 KLOCK_QUEUE_HANDLE ProcessLock;
2722
2723 /* Only accept valid flags */
2724 if (ExecuteOptions & ~MEM_EXECUTE_OPTION_VALID_FLAGS)
2725 {
2726 /* Fail */
2727 DPRINT1("Invalid no-execute options\n");
2729 }
2730
2731 /* Change the NX state in the process lock */
2732 KiAcquireProcessLockRaiseToSynch(CurrentProcess, &ProcessLock);
2733
2734 /* Don't change anything if the permanent flag was set */
2735 if (!CurrentProcess->Flags.Permanent)
2736 {
2737 /* Start by assuming it's not disabled */
2738 CurrentProcess->Flags.ExecuteDisable = FALSE;
2739
2740 /* Now process each flag and turn the equivalent bit on */
2741 if (ExecuteOptions & MEM_EXECUTE_OPTION_DISABLE)
2742 {
2743 CurrentProcess->Flags.ExecuteDisable = TRUE;
2744 }
2745 if (ExecuteOptions & MEM_EXECUTE_OPTION_ENABLE)
2746 {
2747 CurrentProcess->Flags.ExecuteEnable = TRUE;
2748 }
2749 if (ExecuteOptions & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)
2750 {
2751 CurrentProcess->Flags.DisableThunkEmulation = TRUE;
2752 }
2753 if (ExecuteOptions & MEM_EXECUTE_OPTION_PERMANENT)
2754 {
2755 CurrentProcess->Flags.Permanent = TRUE;
2756 }
2757 if (ExecuteOptions & MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE)
2758 {
2759 CurrentProcess->Flags.ExecuteDispatchEnable = TRUE;
2760 }
2761 if (ExecuteOptions & MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE)
2762 {
2763 CurrentProcess->Flags.ImageDispatchEnable = TRUE;
2764 }
2765
2766 /* These are turned on by default if no-execution is also enabled */
2767 if (CurrentProcess->Flags.ExecuteEnable)
2768 {
2769 CurrentProcess->Flags.ExecuteDispatchEnable = TRUE;
2770 CurrentProcess->Flags.ImageDispatchEnable = TRUE;
2771 }
2772
2773 /* All good */
2775 }
2776
2777 /* Release the lock and return status */
2778 KiReleaseProcessLock(&ProcessLock);
2779 return Status;
2780}
2781
2782/* EOF */
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG _In_ KPROCESSOR_MODE PreviousMode
ULONG_PTR PFN_NUMBER
unsigned char BOOLEAN
Definition: actypes.h:127
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
#define PTE_BASE
Definition: winldr.c:20
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedExchange
Definition: armddk.h:54
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
static INT Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
Definition: cmd.c:345
#define _WARN(msg)
Definition: debug.h:135
DECLSPEC_NORETURN VOID NTAPI KeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
Definition: debug.c:485
#define MM_READWRITE
Definition: bootanim.c:19
#define MM_READONLY
Definition: bootanim.c:18
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
_In_ ULONG _In_ MEMORY_CACHING_TYPE _Out_ PPHYSICAL_ADDRESS _Out_ PVOID * VirtualAddress
Definition: dispmprt.h:716
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
PPEB Peb
Definition: dllmain.c:27
#define ULONG_PTR
Definition: config.h:101
#define PtrToUlong(u)
Definition: config.h:107
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define STATUS_ACCESS_VIOLATION
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:24
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define DbgPrint
Definition: hal.h:12
#define KeGetCurrentThread
Definition: hal.h:55
_In_ ULONG Mode
Definition: hubbusif.h:303
#define FLG_DISABLE_STACK_EXTENSION
Definition: pstypes.h:66
#define InterlockedIncrement16
Definition: interlocked.h:221
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:211
#define _ReturnAddress()
Definition: intrin_arm.h:35
FORCEINLINE VOID KiReleaseProcessLock(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:639
FORCEINLINE VOID KiAcquireProcessLockRaiseToSynch(IN PKPROCESS Process, IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:630
if(dx< 0)
Definition: linetemp.h:194
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
@ SystemPteSpace
Definition: miarm.h:407
PMMPTE MiHighestUserPte
Definition: mminit.c:234
PMMPTE MmSharedUserDataPte
Definition: mminit.c:26
#define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)
Definition: miarm.h:194
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:953
PVOID MmPagedPoolStart
Definition: miarm.h:579
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:537
FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1272
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:834
#define MI_IS_SESSION_IMAGE_ADDRESS(Address)
Definition: miarm.h:182
VOID NTAPI MiDeletePte(IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
Definition: virtual.c:369
#define MM_GUARDPAGE
Definition: miarm.h:57
PVOID MmNonPagedPoolEnd
Definition: mminit.c:100
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
FORCEINLINE VOID MiReferenceUsedPageAndBumpLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1749
#define MI_IS_SESSION_ADDRESS(Address)
Definition: miarm.h:185
BOOLEAN MmProtectFreedNonPagedPool
Definition: pool.c:31
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:236
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:477
VOID NTAPI MiReleaseSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:264
#define MM_EXECUTE_READWRITE
Definition: miarm.h:49
FORCEINLINE BOOLEAN MiIsUserPte(PVOID Address)
Definition: miarm.h:730
MM_PAGED_POOL_INFO MmPagedPoolInfo
Definition: pool.c:25
#define MI_IS_SESSION_PTE(Pte)
Definition: miarm.h:188
#define MI_IS_PAGE_TABLE_ADDRESS(Address)
Definition: miarm.h:191
#define MM_DECOMMIT
Definition: miarm.h:64
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1201
FORCEINLINE VOID MiReferenceUnusedPageAndBumpLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1794
@ MiWriteCombined
Definition: miarm.h:416
@ MiNonCached
Definition: miarm.h:414
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:1000
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1358
FORCEINLINE VOID MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1622
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:265
#define SYSTEM_PD_SIZE
Definition: miarm.h:32
#define MM_NOACCESS
Definition: miarm.h:65
#define MM_ZERO_ACCESS
Definition: miarm.h:43
FORCEINLINE VOID MI_WRITE_INVALID_PDE(IN PMMPDE PointerPde, IN MMPDE InvalidPde)
Definition: miarm.h:1042
#define MM_PROTECT_SPECIAL
Definition: miarm.h:59
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:813
FORCEINLINE BOOLEAN MiIsUserPde(PVOID Address)
Definition: miarm.h:722
FORCEINLINE VOID MI_UPDATE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:985
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:245
FORCEINLINE VOID MI_MAKE_TRANSITION_PTE(_Out_ PMMPTE NewPte, _In_ PFN_NUMBER Page, _In_ ULONG Protection)
Definition: miarm.h:937
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:967
FORCEINLINE VOID MiDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1592
FORCEINLINE ULONG_PTR MiDetermineUserGlobalPteMask(IN PVOID PointerPte)
Definition: miarm.h:741
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:209
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:970
#define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address)
Definition: miarm.h:197
FORCEINLINE USHORT MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2479
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:237
#define MM_PROTECT_ACCESS
Definition: miarm.h:51
PVOID MiSessionSpaceWs
Definition: mminit.c:131
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1581
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1131
FORCEINLINE PFN_NUMBER MiRemoveZeroPageSafe(IN ULONG Color)
Definition: miarm.h:2413
#define MM_WRITECOPY
Definition: miarm.h:48
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1197
struct _MMPTE * PMMPTE
#define MM_SHARED_USER_DATA_VA
Definition: mmtypes.h:48
struct _MMPTE * PMMPDE
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
#define MEM_EXECUTE_OPTION_DISABLE
Definition: mmtypes.h:73
#define MEM_EXECUTE_OPTION_PERMANENT
Definition: mmtypes.h:76
#define MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE
Definition: mmtypes.h:77
#define MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE
Definition: mmtypes.h:78
@ VadAwe
Definition: mmtypes.h:207
@ VadDevicePhysicalMemory
Definition: mmtypes.h:205
@ VadImageMap
Definition: mmtypes.h:206
#define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
Definition: mmtypes.h:75
#define MEM_EXECUTE_OPTION_ENABLE
Definition: mmtypes.h:74
#define MEM_EXECUTE_OPTION_VALID_FLAGS
Definition: mmtypes.h:79
@ ActiveAndValid
Definition: mmtypes.h:159
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#define PAGE_READWRITE
Definition: nt_native.h:1307
#define FASTCALL
Definition: nt_native.h:50
#define NtCurrentProcess()
Definition: nt_native.h:1660
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
#define MEM_COMMIT
Definition: nt_native.h:1316
#define PAGE_GUARD
Definition: nt_native.h:1313
@ NotificationEvent
#define MiAddressToPte(x)
Definition: mm.h:144
#define MI_IS_PAGE_EXECUTABLE(x)
Definition: mm.h:110
#define MI_IS_PAGE_COPY_ON_WRITE(x)
Definition: mm.h:109
#define MI_IS_WRITE_ACCESS(FaultCode)
Definition: mm.h:121
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:105
#define MM_PTE_SOFTWARE_PROTECTION_BITS
Definition: mm.h:77
#define MI_IS_INSTRUCTION_FETCH(FaultCode)
Definition: mm.h:124
#define MI_IS_NOT_PRESENT_FAULT(FaultCode)
Definition: mm.h:120
#define MI_MAKE_ACCESSED_PAGE(x)
Definition: mm.h:102
#define _MI_PAGING_LEVELS
Definition: mm.h:8
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:160
#define MiProtoPteToPte(x)
Definition: mm.h:315
FORCEINLINE PMMPTE MiAddressToPxe(PVOID Address)
Definition: mm.h:170
#define MI_IS_PAGE_LARGE(x)
Definition: mm.h:103
#define MmSystemRangeStart
Definition: mm.h:34
#define MiAddressToPde(x)
Definition: mm.h:155
#define MI_MAKE_CLEAN_PAGE(x)
Definition: mm.h:101
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:100
#define PFN_FROM_PTE(v)
Definition: mm.h:94
#define KeGetTrapFramePc(TrapFrame)
Definition: ke.h:37
#define MI_MAKE_PTE_WRITE_COMBINE(Pte)
Definition: mm.h:94
#define MiPteToAddress(_Pte)
Definition: mm.h:131
#define MI_MAKE_PTE_NON_CACHED(Pte)
Definition: mm.h:88
VOID FASTCALL KeZeroPages(IN PVOID Address, IN ULONG Size)
Definition: cpu.c:56
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1042
#define MI_SET_PROCESS2(x)
Definition: mm.h:325
#define MM_NOIRQL
Definition: mm.h:67
@ MI_USAGE_PAGE_FILE
Definition: mm.h:352
@ MI_USAGE_COW
Definition: mm.h:353
@ MI_USAGE_PEB_TEB
Definition: mm.h:338
@ MI_USAGE_PAGE_TABLE
Definition: mm.h:340
@ MI_USAGE_DEMAND_ZERO
Definition: mm.h:346
NTSTATUS NTAPI MiReadPageFile(_In_ PFN_NUMBER Page, _In_ ULONG PageFileIndex, _In_ ULONG_PTR PageFileOffset)
Definition: pagefile.c:211
VOID NTAPI MmRebalanceMemoryConsumers(VOID)
Definition: balance.c:290
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1038
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1287
#define MI_SET_USAGE(x)
Definition: mm.h:323
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
#define MI_SET_PROCESS(x)
Definition: mm.h:324
#define InterlockedExchangePte(PointerPte, Value)
Definition: mm.h:192
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
PMMPDE MmSystemPagePtes
Definition: init.c:41
PVOID MiSessionViewStart
Definition: init.c:30
ULONG MmSizeOfNonPagedPoolInBytes
Definition: init.c:21
PVOID MmNonPagedPoolExpansionStart
Definition: init.c:25
PVOID MmSessionBase
Definition: init.c:33
MMSUPPORT MmSystemCacheWs
Definition: init.c:55
PVOID MmNonPagedPoolStart
Definition: init.c:24
PVOID MmPagedPoolEnd
Definition: init.c:26
MMPTE ValidKernelPte
Definition: init.c:29
MMPDE DemandZeroPde
Definition: init.c:36
MMPTE MmDecommittedPte
Definition: init.c:44
MMPTE PrototypePte
Definition: init.c:40
const ULONG MmProtectToPteMask[32]
Definition: page.c:22
#define STATUS_PAGE_FAULT_GUARD_PAGE
Definition: ntstatus.h:150
#define STATUS_WAIT_1
Definition: ntstatus.h:123
#define STATUS_ALREADY_COMMITTED
Definition: ntstatus.h:363
#define STATUS_STACK_OVERFLOW
Definition: ntstatus.h:583
#define STATUS_PAGE_FAULT_COPY_ON_WRITE
Definition: ntstatus.h:149
#define STATUS_PAGE_FAULT_DEMAND_ZERO
Definition: ntstatus.h:148
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:336
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:262
#define STATUS_PAGE_FAULT_TRANSITION
Definition: ntstatus.h:147
VOID NTAPI MiCopyPfn(_In_ PFN_NUMBER DestPage, _In_ PFN_NUMBER SrcPage)
Definition: pagfault.c:547
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:188
static NTSTATUS NTAPI MiResolveDemandZeroFault(IN PVOID Address, IN PMMPTE PointerPte, IN ULONG Protection, IN PEPROCESS Process, IN KIRQL OldIrql)
Definition: pagfault.c:611
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:787
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:1002
static PMMPTE NTAPI MiCheckVirtualAddress(IN PVOID VirtualAddress, OUT PULONG ProtectCode, OUT PMMVAD *ProtoVad)
Definition: pagfault.c:257
NTSTATUS NTAPI MmArmAccessFault(IN ULONG FaultCode, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
Definition: pagfault.c:1708
NTSTATUS NTAPI MmSetExecuteOptions(IN ULONG ExecuteOptions)
Definition: pagfault.c:2716
VOID NTAPI MiZeroPfn(IN PFN_NUMBER PageFrameNumber)
Definition: pagfault.c:503
FORCEINLINE BOOLEAN MiIsAccessAllowed(_In_ ULONG ProtectionMask, _In_ BOOLEAN Write, _In_ BOOLEAN Execute)
Definition: pagfault.c:158
VOID NTAPI MmRebalanceMemoryConsumersAndWait(VOID)
Definition: balance.c:300
static NTSTATUS NTAPI MiResolvePageFileFault(_In_ BOOLEAN StoreInstruction, _In_ PVOID FaultingAddress, _In_ PMMPTE PointerPte, _In_ PEPROCESS CurrentProcess, _Inout_ KIRQL *OldIrql)
Definition: pagfault.c:910
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:1134
#define HYDRA_PROCESS
Definition: pagfault.c:24
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:495
NTSTATUS NTAPI MmGetExecuteOptions(IN PULONG ExecuteOptions)
Definition: pagfault.c:2674
#define _BYTE_MASK(Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7)
static NTSTATUS NTAPI MiCheckForUserStackOverflow(IN PVOID Address, IN PVOID TrapInformation)
Definition: pagfault.c:34
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:1348
static WCHAR Address[46]
Definition: ping.c:68
BOOLEAN NTAPI KeIsAttachedProcess(VOID)
Definition: procobj.c:693
static LARGE_INTEGER TinyTime
Definition: section.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
PFN_NUMBER NumberOfPrivatePages
Definition: pstypes.h:1505
KPROCESS Pcb
Definition: pstypes.h:1467
PVOID CloneRoot
Definition: pstypes.h:1504
EX_PUSH_LOCK AddressCreationLock
Definition: pstypes.h:1495
CHAR ImageFileName[16]
Definition: pstypes.h:1531
KTHREAD Tcb
Definition: pstypes.h:1296
ULONG OwnsSessionWorkingSetExclusive
Definition: pstypes.h:1418
ULONG OwnsSessionWorkingSetShared
Definition: pstypes.h:1419
ULONG OwnsSystemWorkingSetShared
Definition: pstypes.h:1417
ULONG OwnsProcessWorkingSetShared
Definition: pstypes.h:1415
ULONG OwnsProcessWorkingSetExclusive
Definition: pstypes.h:1414
ULONG OwnsSystemWorkingSetExclusive
Definition: pstypes.h:1416
ULONG PageFrameNumber
Definition: mmtypes.h:109
UCHAR DisableThunkEmulation
Definition: ketypes.h:1133
UCHAR ExecuteDisable
Definition: ketypes.h:1131
UCHAR ExecuteEnable
Definition: ketypes.h:1132
UCHAR ExecuteDispatchEnable
Definition: ketypes.h:1135
UCHAR ImageDispatchEnable
Definition: ketypes.h:1136
KEXECUTE_OPTIONS Flags
Definition: ketypes.h:2277
PVOID Teb
Definition: ketypes.h:1954
KAPC_STATE ApcState
Definition: ketypes.h:1925
ULONG R3
Definition: ketypes.h:370
UINT64 Rdi
Definition: ketypes.h:475
ULONG Sp
Definition: ketypes.h:372
ULONG Pc
Definition: ketypes.h:375
ULONG Edi
Definition: ketypes.h:327
UINT64 Rsi
Definition: ketypes.h:476
UINT64 Rdx
Definition: ketypes.h:425
ULONG Lr
Definition: ketypes.h:373
ULONG EFlags
Definition: ketypes.h:489
ULONG R0
Definition: ketypes.h:367
ULONG Ebx
Definition: ketypes.h:329
ULONG Ecx
Definition: ketypes.h:322
UINT64 Rbx
Definition: ketypes.h:474
ULONG Eip
Definition: ketypes.h:332
UINT64 Rax
Definition: ketypes.h:423
UINT64 Rip
Definition: ketypes.h:484
ULONG R2
Definition: ketypes.h:369
ULONG R1
Definition: ketypes.h:368
ULONG Eax
Definition: ketypes.h:323
UINT64 Rcx
Definition: ketypes.h:424
ULONG Esi
Definition: ketypes.h:328
ULONG Edx
Definition: ketypes.h:321
UINT64 R11
Definition: ketypes.h:429
ULONG R12
Definition: ketypes.h:371
USHORT CacheAttribute
Definition: mm.h:373
USHORT PrototypePte
Definition: mm.h:369
USHORT Modified
Definition: mm.h:366
USHORT ReadInProgress
Definition: mm.h:367
USHORT PageLocation
Definition: mm.h:371
USHORT WriteInProgress
Definition: mm.h:368
Definition: mm.h:386
MMPTE OriginalPte
Definition: mm.h:422
PMMPTE PteAddress
Definition: mm.h:398
NTSTATUS ReadStatus
Definition: mm.h:392
union _MMPFN::@2100 u2
MMPFNENTRY e1
Definition: mm.h:409
ULONG_PTR ShareCount
Definition: mm.h:402
union _MMPFN::@2099 u1
struct _MMPFN::@2101::@2107 e2
ULONG_PTR InPageError
Definition: mm.h:434
PKEVENT Event
Definition: mm.h:391
union _MMPFN::@2101 u3
union _MMPFN::@2104 u4
ULONG64 Valid
Definition: mmtypes.h:150
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
ULONG64 ReadOnly
Definition: mmtypes.h:119
ULONG64 Protection
Definition: mmtypes.h:88
ULONG64 Prototype
Definition: mmtypes.h:89
ULONG64 PageFileHigh
Definition: mmtypes.h:93
union _MMPTE::@2788 u
MMPTE_PROTOTYPE Proto
Definition: mmtypes.h:218
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG_PTR Long
Definition: mmtypes.h:215
ULONG ExtendableFile
Definition: mmtypes.h:712
ULONG_PTR MemCommit
Definition: mmtypes.h:695
ULONG_PTR Protection
Definition: mmtypes.h:696
ULONG_PTR VadType
Definition: mmtypes.h:694
ULONG_PTR PrivateMemory
Definition: mmtypes.h:698
union _MMVAD::@3114 u
ULONG_PTR StartingVpn
Definition: mmtypes.h:729
MMVAD_FLAGS2 VadFlags2
Definition: mmtypes.h:742
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:734
union _MMVAD::@3115 u2
PMMPTE FirstPrototypePte
Definition: mmtypes.h:737
PMMPTE LastPteForPagedPool
Definition: mm.h:504
PMMPDE PageTables
Definition: miarm.h:511
struct _MM_SESSION_SPACE * GlobalVirtualAddress
Definition: miarm.h:474
LIST_ENTRY ImageList
Definition: miarm.h:493
PVOID StackLimit
Definition: compat.h:713
PVOID StackBase
Definition: compat.h:712
ULONG NtGlobalFlag
Definition: ntddk_ex.h:270
Definition: compat.h:836
NT_TIB NtTib
Definition: ntddk_ex.h:332
ULONG GuaranteedStackBytes
Definition: winternl.h:668
PVOID DeallocationStack
Definition: compat.h:878
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
int16_t * PSHORT
Definition: typedefs.h:55
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
static BOOL Write(PBYTE Address, PBYTE Data, SIZE_T Size)
Definition: vmhorizon.c:15
_In_ WDFCOLLECTION _In_ ULONG Index
#define FORCEINLINE
Definition: wdftypes.h:67
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ WrPageIn
Definition: ketypes.h:476
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define PAGE_ALIGN(Va)
ULONG PFN_COUNT
Definition: mmtypes.h:102
#define PsGetCurrentProcess
Definition: psfuncs.h:17