ReactOS  0.4.15-dev-5142-g967f5b9
section.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/section.c
5  * PURPOSE: ARM Memory Manager Section Support
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 
18 /* GLOBALS ********************************************************************/
19 
21 {
30 };
31 
33 {
42 };
43 
45 {
46  0,
62 };
63 
65 {
66  0,
67  MM_EXECUTE,
82 };
83 
85 {
87 
89 
91 
94 
96 
98 
102 
105 };
106 
112 
113 /* PRIVATE FUNCTIONS **********************************************************/
114 
115 BOOLEAN
116 NTAPI
118  IN ULONG NewSectionPageProtection)
119 {
120  ULONG ProtectionMask, CompatibleMask;
121 
122  /* Calculate the protection mask and make sure it's valid */
124  if (ProtectionMask == MM_INVALID_PROTECTION)
125  {
126  DPRINT1("Invalid protection mask\n");
127  return FALSE;
128  }
129 
130  /* Calculate the compatible mask */
131  CompatibleMask = MmCompatibleProtectionMask[ProtectionMask & 0x7] |
133 
134  /* See if the mapping protection is compatible with the create protection */
135  return ((CompatibleMask | NewSectionPageProtection) == CompatibleMask);
136 }
137 
139 NTAPI
141 {
142  ULONG ProtectionMask;
143 
144  /* Calculate the protection mask and make sure it's valid */
146  if (ProtectionMask == MM_INVALID_PROTECTION)
147  {
148  DPRINT1("Invalid protection mask\n");
150  }
151 
152  /* Now convert it to the required file access */
153  return MmMakeFileAccess[ProtectionMask & 0x7];
154 }
155 
156 ULONG
157 NTAPI
159 {
160  ULONG Mask1, Mask2, ProtectMask;
161 
162  /* PAGE_EXECUTE_WRITECOMBINE is theoretically the maximum */
163  if (Protect >= (PAGE_WRITECOMBINE * 2)) return MM_INVALID_PROTECTION;
164 
165  /*
166  * Windows API protection mask can be understood as two bitfields, differing
167  * by whether or not execute rights are being requested
168  */
169  Mask1 = Protect & 0xF;
170  Mask2 = (Protect >> 4) & 0xF;
171 
172  /* Check which field is there */
173  if (!Mask1)
174  {
175  /* Mask2 must be there, use it to determine the PTE protection */
176  if (!Mask2) return MM_INVALID_PROTECTION;
177  ProtectMask = MmUserProtectionToMask2[Mask2];
178  }
179  else
180  {
181  /* Mask2 should not be there, use Mask1 to determine the PTE mask */
182  if (Mask2) return MM_INVALID_PROTECTION;
183  ProtectMask = MmUserProtectionToMask1[Mask1];
184  }
185 
186  /* Make sure the final mask is a valid one */
187  if (ProtectMask == MM_INVALID_PROTECTION) return MM_INVALID_PROTECTION;
188 
189  /* Check for PAGE_GUARD option */
190  if (Protect & PAGE_GUARD)
191  {
192  /* It's not valid on no-access, nocache, or writecombine pages */
193  if ((ProtectMask == MM_NOACCESS) ||
195  {
196  /* Fail such requests */
197  return MM_INVALID_PROTECTION;
198  }
199 
200  /* This actually turns on guard page in this scenario! */
201  ProtectMask |= MM_GUARDPAGE;
202  }
203 
204  /* Check for nocache option */
205  if (Protect & PAGE_NOCACHE)
206  {
207  /* The earlier check should've eliminated this possibility */
208  ASSERT((Protect & PAGE_GUARD) == 0);
209 
210  /* Check for no-access page or write combine page */
211  if ((ProtectMask == MM_NOACCESS) || (Protect & PAGE_WRITECOMBINE))
212  {
213  /* Such a request is invalid */
214  return MM_INVALID_PROTECTION;
215  }
216 
217  /* Add the PTE flag */
218  ProtectMask |= MM_NOCACHE;
219  }
220 
221  /* Check for write combine option */
223  {
224  /* The two earlier scenarios should've caught this */
225  ASSERT((Protect & (PAGE_GUARD | PAGE_NOACCESS)) == 0);
226 
227  /* Don't allow on no-access pages */
228  if (ProtectMask == MM_NOACCESS) return MM_INVALID_PROTECTION;
229 
230  /* This actually turns on write-combine in this scenario! */
231  ProtectMask |= MM_NOACCESS;
232  }
233 
234  /* Return the final MM PTE protection mask */
235  return ProtectMask;
236 }
237 
238 BOOLEAN
239 NTAPI
241 {
242  SIZE_T AllocSize, BitmapSize, Size;
243  PVOID ViewStart;
245 
246  /* Check if this a session or system space */
247  if (InputSession)
248  {
249  /* Use the input session */
250  Session = InputSession;
251  ViewStart = MiSessionViewStart;
253  }
254  else
255  {
256  /* Use the system space "session" */
257  Session = &MmSession;
258  ViewStart = MiSystemViewStart;
260  }
261 
262  /* Initialize the system space lock */
265 
266  /* Set the start address */
267  Session->SystemSpaceViewStart = ViewStart;
268 
269  /* Create a bitmap to describe system space */
270  BitmapSize = sizeof(RTL_BITMAP) + ((((Size / MI_SYSTEM_VIEW_BUCKET_SIZE) + 31) / 32) * sizeof(ULONG));
272  BitmapSize,
273  TAG_MM);
278 
279  /* Set system space fully empty to begin with */
281 
282  /* Set default hash flags */
286 
287  /* Calculate how much space for the hash views we'll need */
288  AllocSize = sizeof(MMVIEW) * Session->SystemSpaceHashSize;
289  ASSERT(AllocSize < PAGE_SIZE);
290 
291  /* Allocate and zero the view table */
293  NonPagedPool :
294  PagedPool,
295  AllocSize,
296  TAG_MM);
299 
300  /* Success */
301  return TRUE;
302 }
303 
304 PVOID
305 NTAPI
307  IN ULONG Buckets,
308  IN PCONTROL_AREA ControlArea)
309 {
310  PVOID Base;
311  ULONG Entry, Hash, i, HashSize;
312  PMMVIEW OldTable;
313  PAGED_CODE();
314 
315  /* Stay within 4GB */
317 
318  /* Lock system space */
320 
321  /* Check if we're going to exhaust hash entries */
323  {
324  /* Double the hash size */
325  HashSize = Session->SystemSpaceHashSize * 2;
326 
327  /* Save the old table and allocate a new one */
328  OldTable = Session->SystemSpaceViewTable;
330  &MmSession ?
331  NonPagedPool :
332  PagedPool,
333  HashSize *
334  sizeof(MMVIEW),
335  TAG_MM);
337  {
338  /* Failed to allocate a new table, keep the old one for now */
339  Session->SystemSpaceViewTable = OldTable;
340  }
341  else
342  {
343  /* Clear the new table and set the new ahsh and key */
344  RtlZeroMemory(Session->SystemSpaceViewTable, HashSize * sizeof(MMVIEW));
345  Session->SystemSpaceHashSize = HashSize;
347 
348  /* Loop the old table */
349  for (i = 0; i < Session->SystemSpaceHashSize / 2; i++)
350  {
351  /* Check if the entry was valid */
352  if (OldTable[i].Entry)
353  {
354  /* Re-hash the old entry and search for space in the new table */
355  Hash = (OldTable[i].Entry >> 16) % Session->SystemSpaceHashKey;
357  {
358  /* Loop back at the beginning if we had an overflow */
359  if (++Hash >= Session->SystemSpaceHashSize) Hash = 0;
360  }
361 
362  /* Write the old entry in the new table */
363  Session->SystemSpaceViewTable[Hash] = OldTable[i];
364  }
365  }
366 
367  /* Free the old table */
368  ExFreePool(OldTable);
369  }
370  }
371 
372  /* Check if we ran out */
374  {
375  DPRINT1("Ran out of system view hash entries\n");
377  return NULL;
378  }
379 
380  /* Find space where to map this view */
382  if (i == 0xFFFFFFFF)
383  {
384  /* Out of space, fail */
386  DPRINT1("Out of system view space\n");
388  return NULL;
389  }
390 
391  /* Compute the base address */
393 
394  /* Get the hash entry for this allocation */
395  Entry = ((ULONG_PTR)Base & ~(MI_SYSTEM_VIEW_BUCKET_SIZE - 1)) + Buckets;
396  Hash = (Entry >> 16) % Session->SystemSpaceHashKey;
397 
398  /* Loop hash entries until a free one is found */
400  {
401  /* Unless we overflow, in which case loop back at hash o */
402  if (++Hash >= Session->SystemSpaceHashSize) Hash = 0;
403  }
404 
405  /* Add this entry into the hash table */
408 
409  /* Hash entry found, increment total and return the base address */
412  return Base;
413 }
414 
415 static
416 NTSTATUS
418  IN PFN_NUMBER PteCount,
419  IN PCONTROL_AREA ControlArea,
421 {
422  MMPTE TempPte;
423  PMMPTE PointerPte, ProtoPte, LastProtoPte, LastPte;
424  PSUBSECTION Subsection;
425 
426  /* Mapping at offset not supported yet */
427  ASSERT(SectionOffset == 0);
428 
429  /* ARM3 doesn't support this yet */
430  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
431  ASSERT(ControlArea->u.Flags.Rom == 0);
432  ASSERT(ControlArea->FilePointer == NULL);
433 
434  /* Sanity checks */
435  ASSERT(PteCount != 0);
436  ASSERT(ControlArea->NumberOfMappedViews >= 1);
437  ASSERT(ControlArea->NumberOfUserReferences >= 1);
438  ASSERT(ControlArea->NumberOfSectionReferences != 0);
439  ASSERT(ControlArea->u.Flags.BeingCreated == 0);
440  ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
441  ASSERT(ControlArea->u.Flags.BeingPurged == 0);
442 
443  /* Get the PTEs for the actual mapping */
444  PointerPte = FirstPte;
445  LastPte = FirstPte + PteCount;
446 
447  /* Get the prototype PTEs that desribe the section mapping in the subsection */
448  Subsection = (PSUBSECTION)(ControlArea + 1);
449  ProtoPte = Subsection->SubsectionBase;
450  LastProtoPte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
451 
452  /* Loop the PTEs for the mapping */
453  while (PointerPte < LastPte)
454  {
455  /* We may have run out of prototype PTEs in this subsection */
456  if (ProtoPte >= LastProtoPte)
457  {
458  /* But we don't handle this yet */
459  ASSERT(FALSE);
460  }
461 
462  /* The PTE should be completely clear */
463  ASSERT(PointerPte->u.Long == 0);
464 
465  /* Build the prototype PTE and write it */
466  MI_MAKE_PROTOTYPE_PTE(&TempPte, ProtoPte);
467  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
468 
469  /* Keep going */
470  PointerPte++;
471  ProtoPte++;
472  }
473 
474  /* No failure path */
475  return STATUS_SUCCESS;
476 }
477 
478 VOID
479 NTAPI
482 {
483  PMMPDE PointerPde, LastPde, SystemMapPde;
484  MMPDE TempPde;
485  PFN_NUMBER PageFrameIndex, ParentPage;
486  KIRQL OldIrql;
487  PAGED_CODE();
488 
489  /* Find the PDEs needed for this mapping */
490  PointerPde = MiAddressToPde(Base);
491  LastPde = MiAddressToPde((PVOID)((ULONG_PTR)Base + NumberOfBytes - 1));
492 
493 #if (_MI_PAGING_LEVELS == 2)
494  /* Find the system double-mapped PDE that describes this mapping */
495  SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
496 #else
497  /* We don't have a double mapping */
498  SystemMapPde = PointerPde;
499 #endif
500 
501  /* Use the PDE template and loop the PDEs */
503  while (PointerPde <= LastPde)
504  {
505  /* Lock the PFN database */
506  OldIrql = MiAcquirePfnLock();
507 
508  /* Check if we don't already have this PDE mapped */
509  if (SystemMapPde->u.Hard.Valid == 0)
510  {
511  /* Grab a page for it */
513  MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
514  PageFrameIndex = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
515  ASSERT(PageFrameIndex);
516  TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
517 
518 #if (_MI_PAGING_LEVELS == 2)
519  ParentPage = MmSystemPageDirectory[(PointerPde - MiAddressToPde(NULL)) / PDE_PER_PAGE];
520 #else
521  ParentPage = MiPdeToPpe(PointerPde)->u.Hard.PageFrameNumber;
522 #endif
523  /* Initialize its PFN entry, with the parent system page directory page table */
524  MiInitializePfnForOtherProcess(PageFrameIndex,
525  (PMMPTE)PointerPde,
526  ParentPage);
527 
528  /* Make the system PDE entry valid */
529  MI_WRITE_VALID_PDE(SystemMapPde, TempPde);
530 
531  /* The system PDE entry might be the PDE itself, so check for this */
532  if (PointerPde->u.Hard.Valid == 0)
533  {
534  /* It's different, so make the real PDE valid too */
535  MI_WRITE_VALID_PDE(PointerPde, TempPde);
536  }
537  }
538 
539  /* Release the lock and keep going with the next PDE */
540  MiReleasePfnLock(OldIrql);
541  SystemMapPde++;
542  PointerPde++;
543  }
544 }
545 
546 NTSTATUS
547 NTAPI
549  IN BOOLEAN FailIfSystemViews)
550 {
551  KIRQL OldIrql;
552 
553  /* Flag not yet supported */
554  ASSERT(FailIfSystemViews == FALSE);
555 
556  /* Lock the PFN database */
557  OldIrql = MiAcquirePfnLock();
558 
559  /* State not yet supported */
560  ASSERT(ControlArea->u.Flags.BeingPurged == 0);
561 
562  /* Increase the reference counts */
563  ControlArea->NumberOfMappedViews++;
564  ControlArea->NumberOfUserReferences++;
565  ASSERT(ControlArea->NumberOfSectionReferences != 0);
566 
567  /* Release the PFN lock and return success */
568  MiReleasePfnLock(OldIrql);
569  return STATUS_SUCCESS;
570 }
571 
573 NTAPI
575  IN ULONG_PTR Vpn)
576 {
577  PSUBSECTION Subsection;
578  PCONTROL_AREA ControlArea;
579  ULONG_PTR PteOffset;
580 
581  /* Get the control area */
582  ControlArea = Vad->ControlArea;
583  ASSERT(ControlArea->u.Flags.Rom == 0);
584  ASSERT(ControlArea->u.Flags.Image == 0);
585  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
586 
587  /* Get the subsection */
588  Subsection = (PSUBSECTION)(ControlArea + 1);
589 
590  /* We only support single-subsection segments */
591  ASSERT(Subsection->SubsectionBase != NULL);
592  ASSERT(Vad->FirstPrototypePte >= Subsection->SubsectionBase);
593  ASSERT(Vad->FirstPrototypePte < &Subsection->SubsectionBase[Subsection->PtesInSubsection]);
594 
595  /* Compute the PTE offset */
596  PteOffset = Vpn - Vad->StartingVpn;
597  PteOffset += Vad->FirstPrototypePte - Subsection->SubsectionBase;
598 
599  /* Again, we only support single-subsection segments */
600  ASSERT(PteOffset < 0xF0000000);
601  ASSERT(PteOffset < Subsection->PtesInSubsection);
602 
603  /* Return the subsection */
604  return Subsection;
605 }
606 
607 VOID
608 NTAPI
610 {
611  PCONTROL_AREA ControlArea;
612  SEGMENT_FLAGS SegmentFlags;
613  PSUBSECTION Subsection;
614  PMMPTE PointerPte, LastPte, PteForProto;
615  PMMPFN Pfn1;
616  PFN_NUMBER PageFrameIndex;
617  MMPTE TempPte;
618  KIRQL OldIrql;
619 
620  /* Capture data */
621  SegmentFlags = Segment->SegmentFlags;
622  ControlArea = Segment->ControlArea;
623 
624  /* Make sure control area is on the right delete path */
625  ASSERT(ControlArea->u.Flags.BeingDeleted == 1);
626  ASSERT(ControlArea->WritableUserReferences == 0);
627 
628  /* These things are not supported yet */
629  ASSERT(ControlArea->DereferenceList.Flink == NULL);
630  ASSERT(!(ControlArea->u.Flags.Image) && !(ControlArea->u.Flags.File));
631  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
632  ASSERT(ControlArea->u.Flags.Rom == 0);
633 
634  /* Get the subsection and PTEs for this segment */
635  Subsection = (PSUBSECTION)(ControlArea + 1);
636  PointerPte = Subsection->SubsectionBase;
637  LastPte = PointerPte + Segment->NonExtendedPtes;
638 
639  /* Lock the PFN database */
640  OldIrql = MiAcquirePfnLock();
641 
642  /* Check if the master PTE is invalid */
643  PteForProto = MiAddressToPte(PointerPte);
644  if (!PteForProto->u.Hard.Valid)
645  {
646  /* Fault it in */
648  }
649 
650  /* Loop all the segment PTEs */
651  while (PointerPte < LastPte)
652  {
653  /* Check if it's time to switch master PTEs if we passed a PDE boundary */
654  if (MiIsPteOnPdeBoundary(PointerPte) &&
655  (PointerPte != Subsection->SubsectionBase))
656  {
657  /* Check if the master PTE is invalid */
658  PteForProto = MiAddressToPte(PointerPte);
659  if (!PteForProto->u.Hard.Valid)
660  {
661  /* Fault it in */
663  }
664  }
665 
666  /* This should be a prototype PTE */
667  TempPte = *PointerPte;
668  ASSERT(SegmentFlags.LargePages == 0);
669  ASSERT(TempPte.u.Hard.Valid == 0);
670 
671  /* See if we should clean things up */
672  if (!(ControlArea->u.Flags.Image) && !(ControlArea->u.Flags.File))
673  {
674  /*
675  * This is a section backed by the pagefile. Now that it doesn't exist anymore,
676  * we can give everything back to the system.
677  */
678  ASSERT(TempPte.u.Soft.Prototype == 0);
679 
680  if (TempPte.u.Soft.Transition == 1)
681  {
682  /* We can give the page back for other use */
683  DPRINT("Releasing page for transition PTE %p\n", PointerPte);
684  PageFrameIndex = PFN_FROM_PTE(&TempPte);
685  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
686 
687  /* As this is a paged-backed section, nobody should reference it anymore (no cache or whatever) */
688  ASSERT(Pfn1->u3.ReferenceCount == 0);
689 
690  /* And it should be in standby or modified list */
692 
693  /* Unlink it and put it back in free list */
694  MiUnlinkPageFromList(Pfn1);
695 
696  /* Temporarily mark this as active and make it free again */
698  MI_SET_PFN_DELETED(Pfn1);
699 
700  MiInsertPageInFreeList(PageFrameIndex);
701  }
702  else if (TempPte.u.Soft.PageFileHigh != 0)
703  {
704  /* Should not happen for now */
705  ASSERT(FALSE);
706  }
707  }
708  else
709  {
710  /* unsupported for now */
711  ASSERT(FALSE);
712 
713  /* File-backed section must have prototype PTEs */
714  ASSERT(TempPte.u.Soft.Prototype == 1);
715  }
716 
717  /* Zero the PTE and keep going */
718  PointerPte->u.Long = 0;
719  PointerPte++;
720  }
721 
722  /* Release the PFN lock */
723  MiReleasePfnLock(OldIrql);
724 
725  /* Free the structures */
726  ExFreePool(ControlArea);
728 }
729 
730 VOID
731 NTAPI
733  IN KIRQL OldIrql)
734 {
735  BOOLEAN DeleteSegment = FALSE;
737 
738  /* Check if this is the last reference or view */
739  if (!(ControlArea->NumberOfMappedViews) &&
740  !(ControlArea->NumberOfSectionReferences))
741  {
742  /* There should be no more user references either */
743  ASSERT(ControlArea->NumberOfUserReferences == 0);
744 
745  /* Not yet supported */
746  ASSERT(ControlArea->FilePointer == NULL);
747 
748  /* The control area is being destroyed */
749  ControlArea->u.Flags.BeingDeleted = TRUE;
750  DeleteSegment = TRUE;
751  }
752 
753  /* Release the PFN lock */
754  MiReleasePfnLock(OldIrql);
755 
756  /* Delete the segment if needed */
757  if (DeleteSegment)
758  {
759  /* No more user write references at all */
760  ASSERT(ControlArea->WritableUserReferences == 0);
761  MiSegmentDelete(ControlArea->Segment);
762  }
763 }
764 
765 VOID
766 NTAPI
768 {
769  KIRQL OldIrql;
770 
771  /* Lock the PFN database */
772  OldIrql = MiAcquirePfnLock();
773 
774  /* Drop reference counts */
775  ControlArea->NumberOfMappedViews--;
776  ControlArea->NumberOfUserReferences--;
777 
778  /* Check if it's time to delete the CA. This releases the lock */
779  MiCheckControlArea(ControlArea, OldIrql);
780 }
781 
782 VOID
783 NTAPI
785  IN PMMVAD Vad)
786 {
787  KIRQL OldIrql;
788  PCONTROL_AREA ControlArea;
789  PETHREAD CurrentThread = PsGetCurrentThread();
790 
791  /* Get the control area */
792  ControlArea = Vad->ControlArea;
793 
794  /* We only support non-extendable, non-image, pagefile-backed regular sections */
795  ASSERT(Vad->u.VadFlags.VadType == VadNone);
796  ASSERT(Vad->u2.VadFlags2.ExtendableFile == FALSE);
797  ASSERT(ControlArea);
798  ASSERT(ControlArea->FilePointer == NULL);
799 
800  /* Delete the actual virtual memory pages */
801  MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
802  (Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
803  Vad);
804 
805  /* Release the working set */
807 
808  /* Lock the PFN database */
809  OldIrql = MiAcquirePfnLock();
810 
811  /* Remove references */
812  ControlArea->NumberOfMappedViews--;
813  ControlArea->NumberOfUserReferences--;
814 
815  /* Check if it should be destroyed */
816  MiCheckControlArea(ControlArea, OldIrql);
817 }
818 
819 NTSTATUS
820 NTAPI
823  IN ULONG Flags)
824 {
828  PMMVAD Vad;
829  PVOID DbgBase = NULL;
832  PETHREAD CurrentThread = PsGetCurrentThread();
834  PAGED_CODE();
835 
836  /* Check if we need to lock the address space */
837  if (!Flags) MmLockAddressSpace(&Process->Vm);
838 
839  /* Check for Mm Region */
842  {
843  /* Call Mm API */
845  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
846  return Status;
847  }
848 
849  /* Check if we should attach to the process */
850  if (CurrentProcess != Process)
851  {
852  /* The process is different, do an attach */
854  Attached = TRUE;
855  }
856 
857  /* Check if the process is already dead */
858  if (Process->VmDeleted)
859  {
860  /* Fail the call */
861  DPRINT1("Process died!\n");
862  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
864  goto Quickie;
865  }
866 
867  /* Find the VAD for the address and make sure it's a section VAD */
869  if (!(Vad) || (Vad->u.VadFlags.PrivateMemory))
870  {
871  /* Couldn't find it, or invalid VAD, fail */
872  DPRINT1("No VAD or invalid VAD\n");
873  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
875  goto Quickie;
876  }
877 
878  /* We should be attached */
880 
881  /* We need the base address for the debugger message on image-backed VADs */
882  if (Vad->u.VadFlags.VadType == VadImageMap)
883  {
884  DbgBase = (PVOID)(Vad->StartingVpn >> PAGE_SHIFT);
885  }
886 
887  /* Compute the size of the VAD region */
888  RegionSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
889 
890  /* For SEC_NO_CHANGE sections, we need some extra checks */
891  if (Vad->u.VadFlags.NoChange == 1)
892  {
893  /* Are we allowed to mess with this VAD? */
895  (PVOID)(Vad->StartingVpn >> PAGE_SHIFT),
896  RegionSize,
898  if (!NT_SUCCESS(Status))
899  {
900  /* We failed */
901  DPRINT1("Trying to unmap protected VAD!\n");
902  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
903  goto Quickie;
904  }
905  }
906 
907  /* Not currently supported */
909 
910  /* FIXME: Remove VAD charges */
911 
912  /* Lock the working set */
913  MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
914 
915  /* Remove the VAD */
916  ASSERT(Process->VadRoot.NumberGenericTableElements >= 1);
917  MiRemoveNode((PMMADDRESS_NODE)Vad, &Process->VadRoot);
919 
920  /* Remove the PTEs for this view, which also releases the working set lock */
922 
923  /* FIXME: Remove commitment */
924 
925  /* Update performance counter and release the lock */
926  Process->VirtualSize -= RegionSize;
927  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
928 
929  /* Destroy the VAD and return success */
930  ExFreePool(Vad);
932 
933  /* Failure and success case -- send debugger message, detach, and return */
934 Quickie:
935  if (DbgBase) DbgkUnMapViewOfSection(DbgBase);
937  return Status;
938 }
939 
940 NTSTATUS
941 NTAPI
943  IN PVOID EndVa)
944 {
945  KIRQL OldIrql;
946  ULONG Color, Index;
947  PMMPDE StartPde, EndPde;
949  PMMPFN Pfn1;
950  PFN_NUMBER PageCount = 0, ActualPages = 0, PageFrameNumber;
951 
952  /* Windows sanity checks */
953  ASSERT(StartVa >= (PVOID)MmSessionBase);
954  ASSERT(EndVa < (PVOID)MiSessionSpaceEnd);
955  ASSERT(PAGE_ALIGN(EndVa) == EndVa);
956 
957  /* Get the start and end PDE, then loop each one */
958  StartPde = MiAddressToPde(StartVa);
959  EndPde = MiAddressToPde((PVOID)((ULONG_PTR)EndVa - 1));
960  Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
961  while (StartPde <= EndPde)
962  {
963 #ifndef _M_AMD64
964  /* If we don't already have a page table for it, increment count */
965  if (MmSessionSpace->PageTables[Index].u.Long == 0) PageCount++;
966 #endif
967  /* Move to the next one */
968  StartPde++;
969  Index++;
970  }
971 
972  /* If there's no page tables to create, bail out */
973  if (PageCount == 0) return STATUS_SUCCESS;
974 
975  /* Reset the start PDE and index */
976  StartPde = MiAddressToPde(StartVa);
977  Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
978 
979  /* Loop each PDE while holding the working set lock */
980 // MiLockWorkingSet(PsGetCurrentThread(),
981 // &MmSessionSpace->GlobalVirtualAddress->Vm);
982 #ifdef _M_AMD64
983 _WARN("MiSessionCommitPageTables halfplemented for amd64")
988  DBG_UNREFERENCED_LOCAL_VARIABLE(PageFrameNumber);
989  ASSERT(FALSE);
990 #else
991  while (StartPde <= EndPde)
992  {
993  /* Check if we already have a page table */
994  if (MmSessionSpace->PageTables[Index].u.Long == 0)
995  {
996  /* We don't, so the PDE shouldn't be ready yet */
997  ASSERT(StartPde->u.Hard.Valid == 0);
998 
999  /* ReactOS check to avoid MiEnsureAvailablePageOrWait */
1000  ASSERT(MmAvailablePages >= 32);
1001 
1002  /* Acquire the PFN lock and grab a zero page */
1003  OldIrql = MiAcquirePfnLock();
1005  MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
1007  PageFrameNumber = MiRemoveZeroPage(Color);
1008  TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
1009  MI_WRITE_VALID_PDE(StartPde, TempPde);
1010 
1011  /* Write the page table in session space structure */
1014 
1015  /* Initialize the PFN */
1016  MiInitializePfnForOtherProcess(PageFrameNumber,
1017  StartPde,
1019 
1020  /* And now release the lock */
1021  MiReleasePfnLock(OldIrql);
1022 
1023  /* Get the PFN entry and make sure there's no event for it */
1024  Pfn1 = MI_PFN_ELEMENT(PageFrameNumber);
1025  ASSERT(Pfn1->u1.Event == NULL);
1026 
1027  /* Increment the number of pages */
1028  ActualPages++;
1029  }
1030 
1031  /* Move to the next PDE */
1032  StartPde++;
1033  Index++;
1034  }
1035 #endif
1036 
1037  /* Make sure we didn't do more pages than expected */
1038  ASSERT(ActualPages <= PageCount);
1039 
1040  /* Release the working set lock */
1041 // MiUnlockWorkingSet(PsGetCurrentThread(),
1042 // &MmSessionSpace->GlobalVirtualAddress->Vm);
1043 
1044 
1045  /* If we did at least one page... */
1046  if (ActualPages)
1047  {
1048  /* Update the performance counters! */
1051  }
1052 
1053  /* Return status */
1054  return STATUS_SUCCESS;
1055 }
1056 
1057 NTSTATUS
1059  _In_ PVOID Section,
1064 {
1065  PVOID Base;
1066  PCONTROL_AREA ControlArea;
1067  ULONG Buckets;
1068  LONGLONG SectionSize;
1069  NTSTATUS Status;
1070  PAGED_CODE();
1071 
1072  /* Get the control area, check for any flags ARM3 doesn't yet support */
1073  ControlArea = ((PSECTION)Section)->Segment->ControlArea;
1074  ASSERT(ControlArea->u.Flags.Image == 0);
1075  ASSERT(ControlArea->FilePointer == NULL);
1076  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
1077  ASSERT(ControlArea->u.Flags.Rom == 0);
1078  ASSERT(ControlArea->u.Flags.WasPurged == 0);
1079 
1080  /* Increase the reference and map count on the control area, no purges yet */
1081  Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
1083 
1084  /* Get the section size at creation time */
1085  SectionSize = ((PSECTION)Section)->SizeOfSection.QuadPart;
1086 
1087  /* If the caller didn't specify a view size, assume until the end of the section */
1088  if (!(*ViewSize))
1089  {
1090  /* Check for overflow first */
1091  if ((SectionSize - SectionOffset->QuadPart) > SIZE_T_MAX)
1092  {
1093  DPRINT1("Section end is too far away from the specified offset.\n");
1094  MiDereferenceControlArea(ControlArea);
1095  return STATUS_INVALID_VIEW_SIZE;
1096  }
1097  *ViewSize = SectionSize - SectionOffset->QuadPart;
1098  }
1099 
1100  /* Check overflow */
1101  if ((SectionOffset->QuadPart + *ViewSize) < SectionOffset->QuadPart)
1102  {
1103  DPRINT1("Integer overflow between size & offset!\n");
1104  MiDereferenceControlArea(ControlArea);
1105  return STATUS_INVALID_VIEW_SIZE;
1106  }
1107 
1108  /* Check if the caller wanted a larger section than the view */
1109  if (SectionOffset->QuadPart + *ViewSize > SectionSize)
1110  {
1111  /* Fail */
1112  DPRINT1("View is too large\n");
1113  MiDereferenceControlArea(ControlArea);
1114  return STATUS_INVALID_VIEW_SIZE;
1115  }
1116 
1117  /* Get the number of 64K buckets required for this mapping */
1118  Buckets = (ULONG)(*ViewSize / MI_SYSTEM_VIEW_BUCKET_SIZE);
1119  if (*ViewSize & (MI_SYSTEM_VIEW_BUCKET_SIZE - 1)) Buckets++;
1120 
1121  /* Check if the view is more than 4GB large */
1122  if (Buckets >= MI_SYSTEM_VIEW_BUCKET_SIZE)
1123  {
1124  /* Fail */
1125  DPRINT1("View is too large\n");
1126  MiDereferenceControlArea(ControlArea);
1127  return STATUS_INVALID_VIEW_SIZE;
1128  }
1129 
1130  /* Insert this view into system space and get a base address for it */
1131  Base = MiInsertInSystemSpace(Session, Buckets, ControlArea);
1132  if (!Base)
1133  {
1134  /* Fail */
1135  DPRINT1("Out of system space\n");
1136  MiDereferenceControlArea(ControlArea);
1137  return STATUS_NO_MEMORY;
1138  }
1139 
1140  /* What's the underlying session? */
1141  if (Session == &MmSession)
1142  {
1143  /* Create the PDEs needed for this mapping, and double-map them if needed */
1146  }
1147  else
1148  {
1149  /* Create the PDEs needed for this mapping */
1151  (PVOID)((ULONG_PTR)Base +
1152  Buckets * MI_SYSTEM_VIEW_BUCKET_SIZE));
1154  }
1155 
1156  /* Create the actual prototype PTEs for this mapping */
1159  ControlArea,
1160  SectionOffset->QuadPart);
1162 
1163  /* Return the base adress of the mapping and success */
1164  *MappedBase = Base;
1165  return STATUS_SUCCESS;
1166 }
1167 
1168 VOID
1169 NTAPI
1171 {
1172  KIRQL OldIrql;
1173 
1175 
1176  OldIrql = MiAcquirePfnLock();
1177  ControlArea->u.Flags.DebugSymbolsLoaded |= 1;
1178 
1179  ASSERT(OldIrql <= APC_LEVEL);
1180  MiReleasePfnLock(OldIrql);
1182 }
1183 
1184 VOID
1185 NTAPI
1189 {
1190  NTSTATUS Status;
1192  PLIST_ENTRY NextEntry;
1194  PIMAGE_NT_HEADERS NtHeaders;
1195  PLDR_DATA_TABLE_ENTRY LdrEntry;
1196 
1197  FileName = &ControlArea->FilePointer->FileName;
1198  if (FileName->Length == 0)
1199  {
1200  return;
1201  }
1202 
1203  /* Acquire module list lock */
1206 
1207  /* Browse list to try to find current module */
1208  for (NextEntry = MmLoadedUserImageList.Flink;
1209  NextEntry != &MmLoadedUserImageList;
1210  NextEntry = NextEntry->Flink)
1211  {
1212  /* Get the entry */
1213  LdrEntry = CONTAINING_RECORD(NextEntry,
1215  InLoadOrderLinks);
1216 
1217  /* If already in the list, increase load count */
1218  if (LdrEntry->DllBase == BaseAddress)
1219  {
1220  ++LdrEntry->LoadCount;
1221  break;
1222  }
1223  }
1224 
1225  /* Not in the list, we'll add it */
1226  if (NextEntry == &MmLoadedUserImageList)
1227  {
1228  /* Allocate our element, taking to the name string and its null char */
1229  LdrEntry = ExAllocatePoolWithTag(NonPagedPool, FileName->Length + sizeof(UNICODE_NULL) + sizeof(*LdrEntry), 'bDmM');
1230  if (LdrEntry)
1231  {
1232  memset(LdrEntry, 0, FileName->Length + sizeof(UNICODE_NULL) + sizeof(*LdrEntry));
1233 
1234  _SEH2_TRY
1235  {
1236  /* Get image checksum and size */
1237  NtHeaders = RtlImageNtHeader(BaseAddress);
1238  if (NtHeaders)
1239  {
1240  LdrEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage;
1241  LdrEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum;
1242  }
1243  }
1245  {
1246  ExFreePoolWithTag(LdrEntry, 'bDmM');
1249  _SEH2_YIELD(return);
1250  }
1251  _SEH2_END;
1252 
1253  /* Fill all the details */
1254  LdrEntry->DllBase = BaseAddress;
1255  LdrEntry->FullDllName.Buffer = (PVOID)((ULONG_PTR)LdrEntry + sizeof(*LdrEntry));
1256  LdrEntry->FullDllName.Length = FileName->Length;
1257  LdrEntry->FullDllName.MaximumLength = FileName->Length + sizeof(UNICODE_NULL);
1258  memcpy(LdrEntry->FullDllName.Buffer, FileName->Buffer, FileName->Length);
1259  LdrEntry->FullDllName.Buffer[LdrEntry->FullDllName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1260  LdrEntry->LoadCount = 1;
1261 
1262  /* Insert! */
1264  }
1265  }
1266 
1267  /* Release locks */
1270 
1271  /* Load symbols */
1273  if (NT_SUCCESS(Status))
1274  {
1277  }
1278 }
1279 
1280 NTSTATUS
1281 NTAPI
1284  IN PVOID *BaseAddress,
1287  IN PSECTION Section,
1289  IN ULONG ProtectionMask,
1293 {
1294  PMMVAD_LONG Vad;
1295  ULONG_PTR StartAddress;
1296  ULONG_PTR ViewSizeInPages;
1297  PSUBSECTION Subsection;
1298  PSEGMENT Segment;
1299  PFN_NUMBER PteOffset;
1300  NTSTATUS Status;
1301  ULONG QuotaCharge = 0, QuotaExcess = 0;
1302  PMMPTE PointerPte, LastPte;
1303  MMPTE TempPte;
1304  ULONG Granularity = MM_VIRTMEM_GRANULARITY;
1305 
1306  DPRINT("Mapping ARM3 data section\n");
1307 
1308  /* Get the segment for this section */
1309  Segment = ControlArea->Segment;
1310 
1311 #ifdef _M_IX86
1312  /* ALlow being less restrictive on x86. */
1314  Granularity = PAGE_SIZE;
1315 #endif
1316 
1317  /* One can only reserve a file-based mapping, not shared memory! */
1318  if ((AllocationType & MEM_RESERVE) && !(ControlArea->FilePointer))
1319  {
1321  }
1322 
1323  /* First, increase the map count. No purging is supported yet */
1324  Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
1325  if (!NT_SUCCESS(Status)) return Status;
1326 
1327  /* Check if the caller specified the view size */
1328  if (!(*ViewSize))
1329  {
1330  LONGLONG ViewSizeLL;
1331 
1332  /* The caller did not, so pick a 64K aligned view size based on the offset */
1333  SectionOffset->LowPart &= ~(_64K - 1);
1334 
1335  /* Calculate size and make sure this fits */
1336  if (!NT_SUCCESS(RtlLongLongSub(Section->SizeOfSection.QuadPart, SectionOffset->QuadPart, &ViewSizeLL))
1337  || !NT_SUCCESS(RtlLongLongToSIZET(ViewSizeLL, ViewSize))
1338  || (*ViewSize > MAXLONG_PTR))
1339  {
1340  MiDereferenceControlArea(ControlArea);
1341  return STATUS_INVALID_VIEW_SIZE;
1342  }
1343  }
1344  else
1345  {
1346  /* A size was specified, align it to a 64K boundary
1347  * and check for overflow or huge value. */
1348  if (!NT_SUCCESS(RtlSIZETAdd(*ViewSize, SectionOffset->LowPart & (_64K - 1), ViewSize))
1349  || (*ViewSize > MAXLONG_PTR))
1350  {
1351  MiDereferenceControlArea(ControlArea);
1352  return STATUS_INVALID_VIEW_SIZE;
1353  }
1354 
1355  /* Align the offset as well to make this an aligned map */
1356  SectionOffset->LowPart &= ~((ULONG)_64K - 1);
1357  }
1358 
1359  /* We must be dealing with a 64KB aligned offset. This is a Windows ASSERT */
1360  ASSERT((SectionOffset->LowPart & ((ULONG)_64K - 1)) == 0);
1361 
1362  /* Windows ASSERTs for this flag */
1363  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
1364 
1365  /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
1366  ASSERT(ControlArea->u.Flags.Rom == 0);
1367  Subsection = (PSUBSECTION)(ControlArea + 1);
1368 
1369  /* Sections with extended segments are not supported in ARM3 */
1370  ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0);
1371 
1372  /* Within this section, figure out which PTEs will describe the view */
1373  PteOffset = (PFN_NUMBER)(SectionOffset->QuadPart >> PAGE_SHIFT);
1374 
1375  /* The offset must be in this segment's PTE chunk and it must be valid. Windows ASSERTs */
1376  ASSERT(PteOffset < Segment->TotalNumberOfPtes);
1377  ASSERT(((SectionOffset->QuadPart + *ViewSize + PAGE_SIZE - 1) >> PAGE_SHIFT) >= PteOffset);
1378 
1379  /* In ARM3, only one subsection is used for now. It must contain these PTEs */
1380  ASSERT(PteOffset < Subsection->PtesInSubsection);
1381 
1382  /* In ARM3, only page-file backed sections (shared memory) are supported now */
1383  ASSERT(ControlArea->FilePointer == NULL);
1384 
1385  /* Windows ASSERTs for this too -- there must be a subsection base address */
1386  ASSERT(Subsection->SubsectionBase != NULL);
1387 
1388  /* Compute how much commit space the segment will take */
1389  if ((CommitSize) && (Segment->NumberOfCommittedPages < Segment->TotalNumberOfPtes))
1390  {
1391  /* Charge for the maximum pages */
1392  QuotaCharge = BYTES_TO_PAGES(CommitSize);
1393  }
1394 
1395  /* ARM3 does not currently support large pages */
1396  ASSERT(Segment->SegmentFlags.LargePages == 0);
1397 
1398  /* Calculate how many pages the region spans */
1399  ViewSizeInPages = BYTES_TO_PAGES(*ViewSize);
1400 
1401  /* A VAD can now be allocated. Do so and zero it out */
1402  /* FIXME: we are allocating a LONG VAD for ReactOS compatibility only */
1403  ASSERT((AllocationType & MEM_RESERVE) == 0); /* ARM3 does not support this */
1404  Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
1405  if (!Vad)
1406  {
1407  MiDereferenceControlArea(ControlArea);
1409  }
1410 
1411  RtlZeroMemory(Vad, sizeof(MMVAD_LONG));
1412  Vad->u4.Banked = (PVOID)(ULONG_PTR)0xDEADBABEDEADBABEULL;
1413 
1414  /* Write all the data required in the VAD for handling a fault */
1415  Vad->ControlArea = ControlArea;
1416  Vad->u.VadFlags.CommitCharge = 0;
1417  Vad->u.VadFlags.Protection = ProtectionMask;
1418  Vad->u2.VadFlags2.FileOffset = (ULONG)(SectionOffset->QuadPart >> 16);
1420  if ((AllocationType & SEC_NO_CHANGE) || (Section->u.Flags.NoChange))
1421  {
1422  /* This isn't really implemented yet, but handle setting the flag */
1423  Vad->u.VadFlags.NoChange = 1;
1424  Vad->u2.VadFlags2.SecNoChange = 1;
1425  }
1426 
1427  /* Finally, write down the first and last prototype PTE */
1428  Vad->FirstPrototypePte = &Subsection->SubsectionBase[PteOffset];
1429  PteOffset += ViewSizeInPages - 1;
1430  ASSERT(PteOffset < Subsection->PtesInSubsection);
1431  Vad->LastContiguousPte = &Subsection->SubsectionBase[PteOffset];
1432 
1433  /* Make sure the prototype PTE ranges make sense, this is a Windows ASSERT */
1435 
1436  /* FIXME: Should setup VAD bitmap */
1438 
1439  /* Check if anything was committed */
1440  if (QuotaCharge)
1441  {
1442  /* Set the start and end PTE addresses, and pick the template PTE */
1443  PointerPte = Vad->FirstPrototypePte;
1444  LastPte = PointerPte + BYTES_TO_PAGES(CommitSize);
1445  TempPte = Segment->SegmentPteTemplate;
1446 
1447  /* Acquire the commit lock and loop all prototype PTEs to be committed */
1449  while (PointerPte < LastPte)
1450  {
1451  /* Make sure the PTE is already invalid */
1452  if (PointerPte->u.Long == 0)
1453  {
1454  /* And write the invalid PTE */
1455  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
1456  }
1457  else
1458  {
1459  /* The PTE is valid, so skip it */
1460  QuotaExcess++;
1461  }
1462 
1463  /* Move to the next PTE */
1464  PointerPte++;
1465  }
1466 
1467  /* Now check how many pages exactly we committed, and update accounting */
1468  ASSERT(QuotaCharge >= QuotaExcess);
1469  QuotaCharge -= QuotaExcess;
1470  Segment->NumberOfCommittedPages += QuotaCharge;
1471  ASSERT(Segment->NumberOfCommittedPages <= Segment->TotalNumberOfPtes);
1472 
1473  /* Now that we're done, release the lock */
1475  }
1476 
1477  /* Is it SEC_BASED, or did the caller manually specify an address? */
1478  if (*BaseAddress != NULL)
1479  {
1480  /* Just align what the caller gave us */
1481  StartAddress = ALIGN_DOWN_BY((ULONG_PTR)*BaseAddress, Granularity);
1482  }
1483  else if (Section->Address.StartingVpn != 0)
1484  {
1485  /* It is a SEC_BASED mapping, use the address that was generated */
1486  StartAddress = Section->Address.StartingVpn + SectionOffset->LowPart;
1487  }
1488  else
1489  {
1490  StartAddress = 0;
1491  }
1492 
1494  if (!NT_SUCCESS(Status))
1495  {
1496  ExFreePoolWithTag(Vad, 'ldaV');
1497  MiDereferenceControlArea(ControlArea);
1498 
1500  Segment->NumberOfCommittedPages -= QuotaCharge;
1502  return Status;
1503  }
1504 
1505  /* Insert the VAD */
1506  Status = MiInsertVadEx((PMMVAD)Vad,
1507  &StartAddress,
1508  ViewSizeInPages * PAGE_SIZE,
1510  Granularity,
1511  AllocationType);
1512  if (!NT_SUCCESS(Status))
1513  {
1514  ExFreePoolWithTag(Vad, 'ldaV');
1515  MiDereferenceControlArea(ControlArea);
1516 
1518  Segment->NumberOfCommittedPages -= QuotaCharge;
1520 
1522  return Status;
1523  }
1524 
1525  /* Windows stores this for accounting purposes, do so as well */
1526  if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
1527 
1528  /* Finally, let the caller know where, and for what size, the view was mapped */
1529  *ViewSize = ViewSizeInPages * PAGE_SIZE;
1530  *BaseAddress = (PVOID)StartAddress;
1531  DPRINT("Start and region: 0x%p, 0x%p\n", *BaseAddress, *ViewSize);
1532  return STATUS_SUCCESS;
1533 }
1534 
1535 VOID
1536 NTAPI
1538 {
1539  /* ReactOS only supports systems with 4K pages and 4K sectors */
1540  ASSERT(Subsection->u.SubsectionFlags.SectorEndOffset == 0);
1541 
1542  /* Therefore, then number of PTEs should be equal to the number of sectors */
1543  if (Subsection->NumberOfFullSectors != Subsection->PtesInSubsection)
1544  {
1545  /* Break and warn if this is inconsistent */
1546  DPRINT1("Mm: Subsection inconsistent (%x vs %x)\n",
1547  Subsection->NumberOfFullSectors, Subsection->PtesInSubsection);
1548  DbgBreakPoint();
1549  }
1550 }
1551 
1552 NTSTATUS
1553 NTAPI
1555  OUT PSEGMENT *Segment,
1559  IN ULONG IgnoreFileSizing)
1560 {
1561  /* Not yet implemented */
1562  ASSERT(FALSE);
1563  *Segment = NULL;
1564  return STATUS_NOT_IMPLEMENTED;
1565 }
1566 
1567 static
1568 NTSTATUS
1569 NTAPI
1572  IN ULONG ProtectionMask,
1574 {
1575  ULONGLONG SizeLimit;
1576  PFN_COUNT PteCount;
1577  PMMPTE PointerPte;
1578  MMPTE TempPte;
1579  PCONTROL_AREA ControlArea;
1580  PSEGMENT NewSegment;
1581  PSUBSECTION Subsection;
1582  PAGED_CODE();
1583 
1584  /* No large pages in ARM3 yet */
1586 
1587  /* Pagefile-backed sections need a known size */
1588  if (!MaximumSize || !MaximumSize->QuadPart || MaximumSize->QuadPart < 0)
1590 
1591  /* Calculate the maximum size possible, given the Prototype PTEs we'll need */
1592  SizeLimit = MmSizeOfPagedPoolInBytes - sizeof(SEGMENT);
1593  SizeLimit /= sizeof(MMPTE);
1594  SizeLimit <<= PAGE_SHIFT;
1595 
1596  /* Fail if this size is too big */
1597  if (MaximumSize->QuadPart > SizeLimit)
1598  {
1599  return STATUS_SECTION_TOO_BIG;
1600  }
1601 
1602  /* Calculate how many Prototype PTEs will be needed */
1603  PteCount = (PFN_COUNT)((MaximumSize->QuadPart + PAGE_SIZE - 1) >> PAGE_SHIFT);
1604 
1605  /* For commited memory, we must have a valid protection mask */
1606  if (AllocationAttributes & SEC_COMMIT) ASSERT(ProtectionMask != 0);
1607 
1608  /* The segment contains all the Prototype PTEs, allocate it in paged pool */
1609  NewSegment = ExAllocatePoolWithTag(PagedPool,
1610  sizeof(SEGMENT) +
1611  sizeof(MMPTE) * (PteCount - 1),
1612  'tSmM');
1613  if (!NewSegment)
1614  {
1616  }
1617  *Segment = NewSegment;
1618 
1619  /* Now allocate the control area, which has the subsection structure */
1620  ControlArea = ExAllocatePoolWithTag(NonPagedPool,
1621  sizeof(CONTROL_AREA) + sizeof(SUBSECTION),
1622  'tCmM');
1623  if (!ControlArea)
1624  {
1625  ExFreePoolWithTag(Segment, 'tSmM');
1627  }
1628 
1629  /* And zero it out, filling the basic segmnet pointer and reference fields */
1630  RtlZeroMemory(ControlArea, sizeof(CONTROL_AREA) + sizeof(SUBSECTION));
1631  ControlArea->Segment = NewSegment;
1632  ControlArea->NumberOfSectionReferences = 1;
1633  ControlArea->NumberOfUserReferences = 1;
1634 
1635  /* Convert allocation attributes to control area flags */
1636  if (AllocationAttributes & SEC_BASED) ControlArea->u.Flags.Based = 1;
1637  if (AllocationAttributes & SEC_RESERVE) ControlArea->u.Flags.Reserve = 1;
1638  if (AllocationAttributes & SEC_COMMIT) ControlArea->u.Flags.Commit = 1;
1639 
1640  /* We just allocated it */
1641  ControlArea->u.Flags.BeingCreated = 1;
1642 
1643  /* The subsection follows, write the mask, PTE count and point back to the CA */
1644  Subsection = (PSUBSECTION)(ControlArea + 1);
1645  Subsection->ControlArea = ControlArea;
1646  Subsection->PtesInSubsection = PteCount;
1647  Subsection->u.SubsectionFlags.Protection = ProtectionMask;
1648 
1649  /* Zero out the segment's prototype PTEs, and link it with the control area */
1650  PointerPte = &NewSegment->ThePtes[0];
1651  RtlZeroMemory(NewSegment, sizeof(SEGMENT));
1652  NewSegment->PrototypePte = PointerPte;
1653  NewSegment->ControlArea = ControlArea;
1654 
1655  /* Save some extra accounting data for the segment as well */
1656  NewSegment->u1.CreatingProcess = PsGetCurrentProcess();
1657  NewSegment->SizeOfSegment = ((ULONGLONG)PteCount) * PAGE_SIZE;
1658  NewSegment->TotalNumberOfPtes = PteCount;
1659  NewSegment->NonExtendedPtes = PteCount;
1660 
1661  /* The subsection's base address is the first Prototype PTE in the segment */
1662  Subsection->SubsectionBase = PointerPte;
1663 
1664  /* Start with an empty PTE, unless this is a commit operation */
1665  TempPte.u.Long = 0;
1667  {
1668  /* In which case, write down the protection mask in the Prototype PTEs */
1669  TempPte.u.Soft.Protection = ProtectionMask;
1670 
1671  /* For accounting, also mark these pages as being committed */
1672  NewSegment->NumberOfCommittedPages = PteCount;
1673  }
1674 
1675  /* The template PTE itself for the segment should also have the mask set */
1676  NewSegment->SegmentPteTemplate.u.Soft.Protection = ProtectionMask;
1677 
1678  /* Write out the prototype PTEs, for now they're simply demand zero */
1679 #ifdef _WIN64
1680  RtlFillMemoryUlonglong(PointerPte, PteCount * sizeof(MMPTE), TempPte.u.Long);
1681 #else
1682  RtlFillMemoryUlong(PointerPte, PteCount * sizeof(MMPTE), TempPte.u.Long);
1683 #endif
1684  return STATUS_SUCCESS;
1685 }
1686 
1687 NTSTATUS
1688 NTAPI
1690  IN PVOID Address,
1692 {
1693  PMMVAD Vad;
1694  PCONTROL_AREA ControlArea;
1695 
1696  /* Get the VAD */
1697  Vad = MiLocateAddress(Address);
1698  if (Vad == NULL)
1699  {
1700  /* Fail, the address does not exist */
1701  DPRINT1("Invalid address\n");
1702  return STATUS_INVALID_ADDRESS;
1703  }
1704 
1705  /* Check if this is a RosMm memory area */
1706  if (Vad->u.VadFlags.Spare != 0)
1707  {
1709 
1710  /* Check if it's a section view (RosMm section) */
1712  {
1713  /* Get the section pointer to the SECTION_OBJECT */
1714  *FileObject = MemoryArea->SectionData.Segment->FileObject;
1715  }
1716  else
1717  {
1718 #ifdef NEWCC
1719  ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
1720  DPRINT1("Address is a cache section!\n");
1721  return STATUS_SECTION_NOT_IMAGE;
1722 #else
1723  ASSERT(FALSE);
1724  return STATUS_SECTION_NOT_IMAGE;
1725 #endif
1726  }
1727  }
1728  else
1729  {
1730  /* Make sure it's not a VM VAD */
1731  if (Vad->u.VadFlags.PrivateMemory == 1)
1732  {
1733  DPRINT1("Address is not a section\n");
1734  return STATUS_SECTION_NOT_IMAGE;
1735  }
1736 
1737  /* Get the control area */
1738  ControlArea = Vad->ControlArea;
1739  if (!(ControlArea) || !(ControlArea->u.Flags.Image))
1740  {
1741  DPRINT1("Address is not a section\n");
1742  return STATUS_SECTION_NOT_IMAGE;
1743  }
1744 
1745  /* Get the file object */
1746  *FileObject = ControlArea->FilePointer;
1747  }
1748 
1749  /* Return success */
1750  return STATUS_SUCCESS;
1751 }
1752 
1754 NTAPI
1756 {
1757  PSECTION Section = SectionObject;
1760 
1761  /* Check if it's an ARM3, or ReactOS section */
1763  {
1764  /* Return the file pointer stored in the control area */
1765  return Section->Segment->ControlArea->FilePointer;
1766  }
1767 
1768  /* Return the file object */
1769  return ((PMM_SECTION_SEGMENT)Section->Segment)->FileObject;
1770 }
1771 
1772 static
1775  _In_ PMMVAD Vad)
1776 {
1777  PCONTROL_AREA ControlArea;
1779 
1780  /* Check if this is a RosMm memory area */
1781  if (Vad->u.VadFlags.Spare != 0)
1782  {
1784 
1785  /* Check if it's a section view (RosMm section) */
1787  {
1788  /* Get the section pointer to the SECTION_OBJECT */
1789  FileObject = MemoryArea->SectionData.Segment->FileObject;
1790  }
1791  else
1792  {
1793 #ifdef NEWCC
1794  ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
1795  DPRINT1("VAD is a cache section!\n");
1796 #else
1797  ASSERT(FALSE);
1798 #endif
1799  return NULL;
1800  }
1801  }
1802  else
1803  {
1804  /* Make sure it's not a VM VAD */
1805  if (Vad->u.VadFlags.PrivateMemory == 1)
1806  {
1807  DPRINT1("VAD is not a section\n");
1808  return NULL;
1809  }
1810 
1811  /* Get the control area */
1812  ControlArea = Vad->ControlArea;
1813  if ((ControlArea == NULL) || !ControlArea->u.Flags.Image)
1814  {
1815  DPRINT1("Address is not a section\n");
1816  return NULL;
1817  }
1818 
1819  /* Get the file object */
1820  FileObject = ControlArea->FilePointer;
1821  }
1822 
1823  /* Return the file object */
1824  return FileObject;
1825 }
1826 
1827 VOID
1828 NTAPI
1830 {
1832 
1833  /* Get the section object of this process*/
1834  SectionObject = PsGetCurrentProcess()->SectionObject;
1837 
1838  if (SectionObject->u.Flags.Image == 0)
1839  {
1840  RtlZeroMemory(ImageInformation, sizeof(*ImageInformation));
1841  return;
1842  }
1843 
1844  /* Return the image information */
1845  *ImageInformation = ((PMM_IMAGE_SECTION_OBJECT)SectionObject->Segment)->ImageInformation;
1846 }
1847 
1848 NTSTATUS
1849 NTAPI
1852 {
1853  POBJECT_NAME_INFORMATION ObjectNameInfo;
1854  NTSTATUS Status;
1856 
1857  /* Allocate memory for our structure */
1858  ObjectNameInfo = ExAllocatePoolWithTag(PagedPool, 1024, TAG_MM);
1859  if (!ObjectNameInfo) return STATUS_NO_MEMORY;
1860 
1861  /* Query the name */
1863  ObjectNameInfo,
1864  1024,
1865  &ReturnLength);
1866  if (!NT_SUCCESS(Status))
1867  {
1868  /* Failed, free memory */
1869  DPRINT1("Name query failed\n");
1870  ExFreePoolWithTag(ObjectNameInfo, TAG_MM);
1871  *ModuleName = NULL;
1872  return Status;
1873  }
1874 
1875  /* Success */
1876  *ModuleName = ObjectNameInfo;
1877  return STATUS_SUCCESS;
1878 }
1879 
1880 NTSTATUS
1881 NTAPI
1884 {
1886  PSECTION SectionObject = Section;
1887 
1888  /* Make sure it's an image section */
1889  if (SectionObject->u.Flags.Image == 0)
1890  {
1891  /* It's not, fail */
1892  DPRINT1("Not an image section\n");
1893  return STATUS_SECTION_NOT_IMAGE;
1894  }
1895 
1896  /* Get the file object */
1899 }
1900 
1901 NTSTATUS
1902 NTAPI
1905 {
1906  POBJECT_NAME_INFORMATION ModuleNameInformation;
1908  NTSTATUS Status;
1909  PMMVAD Vad;
1911 
1912  /* Lock address space */
1915 
1916  /* Get the VAD */
1917  Vad = MiLocateAddress(Address);
1918  if (Vad == NULL)
1919  {
1920  /* Fail, the address does not exist */
1921  DPRINT1("No VAD at address %p\n", Address);
1923  return STATUS_INVALID_ADDRESS;
1924  }
1925 
1926  /* Get the file object pointer for the VAD */
1928  if (FileObject == NULL)
1929  {
1930  DPRINT1("Failed to get file object for Address %p\n", Address);
1932  return STATUS_SECTION_NOT_IMAGE;
1933  }
1934 
1935  /* Reference the file object */
1937 
1938  /* Unlock address space */
1940 
1941  /* Get the filename of the file object */
1942  Status = MmGetFileNameForFileObject(FileObject, &ModuleNameInformation);
1943 
1944  /* Dereference the file object */
1946 
1947  /* Check if we were able to get the file object name */
1948  if (NT_SUCCESS(Status))
1949  {
1950  /* Init modulename */
1951  if (!RtlCreateUnicodeString(ModuleName, ModuleNameInformation->Name.Buffer))
1953 
1954  /* Free temp taged buffer from MmGetFileNameForFileObject() */
1955  ExFreePoolWithTag(ModuleNameInformation, TAG_MM);
1956 
1957  DPRINT("Found ModuleName %wZ by address %p\n", ModuleName, Address);
1958  }
1959 
1960  /* Return status */
1961  return Status;
1962 }
1963 
1964 NTSTATUS
1965 NTAPI
1968  OUT PVOID MemoryInformation,
1969  IN SIZE_T MemoryInformationLength,
1971 {
1973  NTSTATUS Status;
1975  PMEMORY_SECTION_NAME SectionName = NULL;
1977 
1980  NULL,
1981  PreviousMode,
1982  (PVOID*)(&Process),
1983  NULL);
1984 
1985  if (!NT_SUCCESS(Status))
1986  {
1987  DPRINT("MiQueryMemorySectionName: ObReferenceObjectByHandle returned %x\n",Status);
1988  return Status;
1989  }
1990 
1992 
1993  if (NT_SUCCESS(Status))
1994  {
1995  SectionName = MemoryInformation;
1996  if (PreviousMode != KernelMode)
1997  {
1998  _SEH2_TRY
1999  {
2000  RtlInitEmptyUnicodeString(&SectionName->SectionFileName,
2001  (PWSTR)(SectionName + 1),
2002  MemoryInformationLength - sizeof(MEMORY_SECTION_NAME));
2004 
2006 
2007  }
2009  {
2011  }
2012  _SEH2_END;
2013  }
2014  else
2015  {
2016  RtlInitEmptyUnicodeString(&SectionName->SectionFileName,
2017  (PWSTR)(SectionName + 1),
2018  MemoryInformationLength - sizeof(MEMORY_SECTION_NAME));
2020 
2022 
2023  }
2024 
2026  }
2028  return Status;
2029 }
2030 
2031 VOID
2032 NTAPI
2034  IN PMMPTE PointerPte,
2035  IN ULONG ProtectionMask,
2036  IN PMMPFN Pfn1,
2037  IN BOOLEAN UpdateDirty)
2038 {
2039  MMPTE TempPte, PreviousPte;
2040  KIRQL OldIrql;
2041  BOOLEAN RebuildPte = FALSE;
2042 
2043  //
2044  // User for sanity checking later on
2045  //
2046  PreviousPte = *PointerPte;
2047 
2048  //
2049  // Build the PTE and acquire the PFN lock
2050  //
2052  PointerPte,
2053  ProtectionMask,
2054  PreviousPte.u.Hard.PageFrameNumber);
2055  OldIrql = MiAcquirePfnLock();
2056 
2057  //
2058  // We don't support I/O mappings in this path yet
2059  //
2060  ASSERT(Pfn1 != NULL);
2061  ASSERT(Pfn1->u3.e1.CacheAttribute != MiWriteCombined);
2062 
2063  //
2064  // Make sure new protection mask doesn't get in conflict and fix it if it does
2065  //
2066  if (Pfn1->u3.e1.CacheAttribute == MiCached)
2067  {
2068  //
2069  // This is a cached PFN
2070  //
2071  if (ProtectionMask & (MM_NOCACHE | MM_NOACCESS))
2072  {
2073  RebuildPte = TRUE;
2074  ProtectionMask &= ~(MM_NOCACHE | MM_NOACCESS);
2075  }
2076  }
2077  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
2078  {
2079  //
2080  // This is a non-cached PFN
2081  //
2082  if ((ProtectionMask & (MM_NOCACHE | MM_NOACCESS)) != MM_NOCACHE)
2083  {
2084  RebuildPte = TRUE;
2085  ProtectionMask &= ~MM_NOACCESS;
2086  ProtectionMask |= MM_NOCACHE;
2087  }
2088  }
2089 
2090  if (RebuildPte)
2091  {
2093  PointerPte,
2094  ProtectionMask,
2095  PreviousPte.u.Hard.PageFrameNumber);
2096  }
2097 
2098  //
2099  // Write the new PTE, making sure we are only changing the bits
2100  //
2101  MI_UPDATE_VALID_PTE(PointerPte, TempPte);
2102 
2103  //
2104  // Flush the TLB
2105  //
2106  ASSERT(PreviousPte.u.Hard.Valid == 1);
2107  KeFlushCurrentTb();
2108  ASSERT(PreviousPte.u.Hard.Valid == 1);
2109 
2110  //
2111  // Windows updates the relevant PFN1 information, we currently don't.
2112  //
2113  if (UpdateDirty && PreviousPte.u.Hard.Dirty)
2114  {
2115  if (!Pfn1->u3.e1.Modified)
2116  {
2117  DPRINT1("FIXME: Mark PFN as dirty\n");
2118  }
2119  }
2120 
2121  //
2122  // Not supported in ARM3
2123  //
2124  ASSERT(FoundVad->u.VadFlags.VadType != VadWriteWatch);
2125 
2126  //
2127  // Release the PFN lock, we are done
2128  //
2129  MiReleasePfnLock(OldIrql);
2130 }
2131 
2132 //
2133 // NOTE: This function gets a lot more complicated if we want Copy-on-Write support
2134 //
2135 NTSTATUS
2136 NTAPI
2138  IN PMMVAD FoundVad,
2139  IN PVOID StartingAddress,
2140  IN PVOID EndingAddress,
2142  OUT PULONG CapturedOldProtect,
2143  IN ULONG DontCharge,
2144  OUT PULONG Locked)
2145 {
2146  PMMPTE PointerPte, LastPte;
2147  MMPTE TempPte, PteContents;
2148  PMMPDE PointerPde;
2149  PMMPFN Pfn1;
2150  ULONG ProtectionMask, QuotaCharge = 0;
2152  PAGED_CODE();
2153 
2154  //
2155  // Tell caller nothing is being locked
2156  //
2157  *Locked = FALSE;
2158 
2159  //
2160  // This function should only be used for section VADs. Windows ASSERT */
2161  //
2162  ASSERT(FoundVad->u.VadFlags.PrivateMemory == 0);
2163 
2164  //
2165  // We don't support these features in ARM3
2166  //
2167  ASSERT(FoundVad->u.VadFlags.VadType != VadImageMap);
2168  ASSERT(FoundVad->u2.VadFlags2.CopyOnWrite == 0);
2169 
2170  //
2171  // Convert and validate the protection mask
2172  //
2173  ProtectionMask = MiMakeProtectionMask(NewProtect);
2174  if (ProtectionMask == MM_INVALID_PROTECTION)
2175  {
2176  DPRINT1("Invalid section protect\n");
2178  }
2179 
2180  //
2181  // Get the PTE and PDE for the address, as well as the final PTE
2182  //
2184  PointerPde = MiAddressToPde(StartingAddress);
2185  PointerPte = MiAddressToPte(StartingAddress);
2186  LastPte = MiAddressToPte(EndingAddress);
2187 
2188  //
2189  // Make the PDE valid, and check the status of the first PTE
2190  //
2192  if (PointerPte->u.Long)
2193  {
2194  //
2195  // Not supported in ARM3
2196  //
2197  ASSERT(FoundVad->u.VadFlags.VadType != VadRotatePhysical);
2198 
2199  //
2200  // Capture the page protection and make the PDE valid
2201  //
2202  *CapturedOldProtect = MiGetPageProtection(PointerPte);
2204  }
2205  else
2206  {
2207  //
2208  // Only pagefile-backed section VADs are supported for now
2209  //
2210  ASSERT(FoundVad->u.VadFlags.VadType != VadImageMap);
2211 
2212  //
2213  // Grab the old protection from the VAD itself
2214  //
2215  *CapturedOldProtect = MmProtectToValue[FoundVad->u.VadFlags.Protection];
2216  }
2217 
2218  //
2219  // Loop all the PTEs now
2220  //
2222  while (PointerPte <= LastPte)
2223  {
2224  //
2225  // Check if we've crossed a PDE boundary and make the new PDE valid too
2226  //
2227  if (MiIsPteOnPdeBoundary(PointerPte))
2228  {
2229  PointerPde = MiPteToPde(PointerPte);
2231  }
2232 
2233  //
2234  // Capture the PTE and see what we're dealing with
2235  //
2236  PteContents = *PointerPte;
2237  if (PteContents.u.Long == 0)
2238  {
2239  //
2240  // This used to be a zero PTE and it no longer is, so we must add a
2241  // reference to the pagetable.
2242  //
2244 
2245  //
2246  // Create the demand-zero prototype PTE
2247  //
2249  TempPte.u.Soft.Protection = ProtectionMask;
2250  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2251  }
2252  else if (PteContents.u.Hard.Valid == 1)
2253  {
2254  //
2255  // Get the PFN entry
2256  //
2257  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2258 
2259  //
2260  // We don't support these yet
2261  //
2262  ASSERT((NewProtect & (PAGE_NOACCESS | PAGE_GUARD)) == 0);
2263  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
2264 
2265  //
2266  // Write the protection mask and write it with a TLB flush
2267  //
2268  Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
2269  MiFlushTbAndCapture(FoundVad,
2270  PointerPte,
2271  ProtectionMask,
2272  Pfn1,
2273  TRUE);
2274  }
2275  else
2276  {
2277  //
2278  // We don't support these cases yet
2279  //
2280  ASSERT(PteContents.u.Soft.Prototype == 0);
2281  ASSERT(PteContents.u.Soft.Transition == 0);
2282 
2283  //
2284  // The PTE is already demand-zero, just update the protection mask
2285  //
2286  PointerPte->u.Soft.Protection = ProtectionMask;
2287  }
2288 
2289  PointerPte++;
2290  }
2291 
2292  //
2293  // Unlock the working set and update quota charges if needed, then return
2294  //
2296  if ((QuotaCharge > 0) && (!DontCharge))
2297  {
2298  FoundVad->u.VadFlags.CommitCharge -= QuotaCharge;
2299  Process->CommitCharge -= QuotaCharge;
2300  }
2301  return STATUS_SUCCESS;
2302 }
2303 
2304 VOID
2305 NTAPI
2307  IN ULONG NumberOfPtes,
2308  IN PCONTROL_AREA ControlArea,
2309  IN PMMSUPPORT Ws)
2310 {
2311  PMMPTE PointerPte, ProtoPte;//, FirstPte;
2312  PMMPDE PointerPde, SystemMapPde;
2313  PMMPFN Pfn1, Pfn2;
2314  MMPTE PteContents;
2315  KIRQL OldIrql;
2316  DPRINT("Removing mapped view at: 0x%p\n", BaseAddress);
2317 
2318  ASSERT(Ws == NULL);
2319 
2320  /* Get the PTE and loop each one */
2321  PointerPte = MiAddressToPte(BaseAddress);
2322  //FirstPte = PointerPte;
2323  while (NumberOfPtes)
2324  {
2325  /* Check if the PTE is already valid */
2326  PteContents = *PointerPte;
2327  if (PteContents.u.Hard.Valid == 1)
2328  {
2329  /* Get the PFN entry */
2330  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2331 
2332  /* Get the PTE */
2333  PointerPde = MiPteToPde(PointerPte);
2334 
2335  /* Lock the PFN database and make sure this isn't a mapped file */
2336  OldIrql = MiAcquirePfnLock();
2337  ASSERT(((Pfn1->u3.e1.PrototypePte) && (Pfn1->OriginalPte.u.Soft.Prototype)) == 0);
2338 
2339  /* Mark the page as modified accordingly */
2340  if (MI_IS_PAGE_DIRTY(&PteContents))
2341  Pfn1->u3.e1.Modified = 1;
2342 
2343  /* Was the PDE invalid */
2344  if (PointerPde->u.Long == 0)
2345  {
2346 #if (_MI_PAGING_LEVELS == 2)
2347  /* Find the system double-mapped PDE that describes this mapping */
2348  SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
2349 
2350  /* Make it valid */
2351  ASSERT(SystemMapPde->u.Hard.Valid == 1);
2352  MI_WRITE_VALID_PDE(PointerPde, *SystemMapPde);
2353 #else
2354  DBG_UNREFERENCED_LOCAL_VARIABLE(SystemMapPde);
2355  ASSERT(FALSE);
2356 #endif
2357  }
2358 
2359  /* Dereference the PDE and the PTE */
2360  Pfn2 = MiGetPfnEntry(PFN_FROM_PTE(PointerPde));
2361  MiDecrementShareCount(Pfn2, PFN_FROM_PTE(PointerPde));
2363  MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
2364 
2365  /* Release the PFN lock */
2366  MiReleasePfnLock(OldIrql);
2367  }
2368  else
2369  {
2370  /* Windows ASSERT */
2371  ASSERT((PteContents.u.Long == 0) || (PteContents.u.Soft.Prototype == 1));
2372 
2373  /* Check if this is a prototype pointer PTE */
2374  if (PteContents.u.Soft.Prototype == 1)
2375  {
2376  /* Get the prototype PTE */
2377  ProtoPte = MiProtoPteToPte(&PteContents);
2378 
2379  /* We don't support anything else atm */
2380  ASSERT(ProtoPte->u.Long == 0);
2381  }
2382  }
2383 
2384  /* Make the PTE into a zero PTE */
2385  PointerPte->u.Long = 0;
2386 
2387  /* Move to the next PTE */
2388  PointerPte++;
2389  NumberOfPtes--;
2390  }
2391 
2392  /* Flush the TLB */
2393  KeFlushCurrentTb();
2394 
2395  /* Acquire the PFN lock */
2396  OldIrql = MiAcquirePfnLock();
2397 
2398  /* Decrement the accounting counters */
2399  ControlArea->NumberOfUserReferences--;
2400  ControlArea->NumberOfMappedViews--;
2401 
2402  /* Check if we should destroy the CA and release the lock */
2403  MiCheckControlArea(ControlArea, OldIrql);
2404 }
2405 
2406 ULONG
2407 NTAPI
2409  IN PVOID Base,
2410  OUT PCONTROL_AREA *ControlArea)
2411 {
2412  ULONG Hash, Size, Count = 0;
2413  ULONG_PTR Entry;
2414  PAGED_CODE();
2415 
2416  /* Compute the hash for this entry and loop trying to find it */
2417  Entry = (ULONG_PTR)Base >> 16;
2419  while ((Session->SystemSpaceViewTable[Hash].Entry >> 16) != Entry)
2420  {
2421  /* Check if we overflew past the end of the hash table */
2422  if (++Hash >= Session->SystemSpaceHashSize)
2423  {
2424  /* Reset the hash to zero and keep searching from the bottom */
2425  Hash = 0;
2426  if (++Count == 2)
2427  {
2428  /* But if we overflew twice, then this is not a real mapping */
2429  KeBugCheckEx(DRIVER_UNMAPPING_INVALID_VIEW,
2430  (ULONG_PTR)Base,
2431  1,
2432  0,
2433  0);
2434  }
2435  }
2436  }
2437 
2438  /* One less entry */
2440 
2441  /* Extract the size and clear the entry */
2444 
2445  /* Return the control area and the size */
2446  *ControlArea = Session->SystemSpaceViewTable[Hash].ControlArea;
2447  return Size;
2448 }
2449 
2450 NTSTATUS
2451 NTAPI
2454 {
2455  ULONG Size;
2456  PCONTROL_AREA ControlArea;
2457  PAGED_CODE();
2458 
2459  /* Remove this mapping */
2461  Size = MiRemoveFromSystemSpace(Session, MappedBase, &ControlArea);
2462 
2463  /* Clear the bits for this mapping */
2466  Size);
2467 
2468  /* Convert the size from a bit size into the actual size */
2469  Size = Size * (_64K >> PAGE_SHIFT);
2470 
2471  /* Remove the PTEs now */
2472  MiRemoveMappedPtes(MappedBase, Size, ControlArea, NULL);
2474 
2475  /* Return success */
2476  return STATUS_SUCCESS;
2477 }
2478 
2479 /* PUBLIC FUNCTIONS ***********************************************************/
2480 
2481 /*
2482  * @implemented
2483  */
2484 NTSTATUS
2485 NTAPI
2489  IN PLARGE_INTEGER InputMaximumSize,
2494 {
2495  SECTION Section;
2496  PSECTION NewSection;
2497  PSUBSECTION Subsection;
2498  PSEGMENT NewSegment, Segment;
2499  NTSTATUS Status;
2500  PCONTROL_AREA ControlArea;
2501  ULONG ProtectionMask, ControlAreaSize, Size, NonPagedCharge, PagedCharge;
2503  BOOLEAN FileLock = FALSE, KernelCall = FALSE;
2504  KIRQL OldIrql;
2506  BOOLEAN UserRefIncremented = FALSE;
2507  PVOID PreviousSectionPointer;
2508 
2509  /* Make the same sanity checks that the Nt interface should've validated */
2512  SEC_NO_CHANGE)) == 0);
2516  SEC_NOCACHE | SEC_NO_CHANGE))));
2522 
2523  /* Convert section flag to page flag */
2525 
2526  /* Check to make sure the protection is correct. Nt* does this already */
2527  ProtectionMask = MiMakeProtectionMask(SectionPageProtection);
2528  if (ProtectionMask == MM_INVALID_PROTECTION) return STATUS_INVALID_PAGE_PROTECTION;
2529 
2530  /* Check if this is going to be a data or image backed file section */
2531  if ((FileHandle) || (FileObject))
2532  {
2533  /* These cannot be mapped with large pages */
2535 
2536  /* For now, only support the mechanism through a file handle */
2537  ASSERT(FileObject == NULL);
2538 
2539  /* Reference the file handle to get the object */
2541  MmMakeFileAccess[ProtectionMask],
2543  PreviousMode,
2544  (PVOID*)&File,
2545  NULL);
2546  if (!NT_SUCCESS(Status)) return Status;
2547 
2548  /* Make sure Cc has been doing its job */
2549  if (!File->SectionObjectPointer)
2550  {
2551  /* This is not a valid file system-based file, fail */
2554  }
2555 
2556  /* Image-file backed sections are not yet supported */
2558 
2559  /* Compute the size of the control area, and allocate it */
2560  ControlAreaSize = sizeof(CONTROL_AREA) + sizeof(MSUBSECTION);
2561  ControlArea = ExAllocatePoolWithTag(NonPagedPool, ControlAreaSize, 'aCmM');
2562  if (!ControlArea)
2563  {
2566  }
2567 
2568  /* Zero it out */
2569  RtlZeroMemory(ControlArea, ControlAreaSize);
2570 
2571  /* Did we get a handle, or an object? */
2572  if (FileHandle)
2573  {
2574  /* We got a file handle so we have to lock down the file */
2575 #if 0
2577  if (!NT_SUCCESS(Status))
2578  {
2579  ExFreePool(ControlArea);
2581  return Status;
2582  }
2583 #else
2584  /* ReactOS doesn't support this API yet, so do nothing */
2586 #endif
2587  /* Update the top-level IRP so that drivers know what's happening */
2589  FileLock = TRUE;
2590  }
2591 
2592  /* Lock the PFN database while we play with the section pointers */
2593  OldIrql = MiAcquirePfnLock();
2594 
2595  /* Image-file backed sections are not yet supported */
2597 
2598  /* There should not already be a control area for this file */
2599  ASSERT(File->SectionObjectPointer->DataSectionObject == NULL);
2600  NewSegment = NULL;
2601 
2602  /* Write down that this CA is being created, and set it */
2603  ControlArea->u.Flags.BeingCreated = TRUE;
2605  PreviousSectionPointer = File->SectionObjectPointer;
2606  File->SectionObjectPointer->DataSectionObject = ControlArea;
2607 
2608  /* We can release the PFN lock now */
2609  MiReleasePfnLock(OldIrql);
2610 
2611  /* We don't support previously-mapped file */
2612  ASSERT(NewSegment == NULL);
2613 
2614  /* Image-file backed sections are not yet supported */
2616 
2617  /* So we always create a data file map */
2619  &Segment,
2620  (PSIZE_T)InputMaximumSize,
2623  KernelCall);
2624  if (!NT_SUCCESS(Status))
2625  {
2626  /* Lock the PFN database while we play with the section pointers */
2627  OldIrql = MiAcquirePfnLock();
2628 
2629  /* Reset the waiting-for-deletion event */
2630  ASSERT(ControlArea->WaitingForDeletion == NULL);
2631  ControlArea->WaitingForDeletion = NULL;
2632 
2633  /* Set the file pointer NULL flag */
2634  ASSERT(ControlArea->u.Flags.FilePointerNull == 0);
2635  ControlArea->u.Flags.FilePointerNull = TRUE;
2636 
2637  /* Delete the data section object */
2639  File->SectionObjectPointer->DataSectionObject = NULL;
2640 
2641  /* No longer being created */
2642  ControlArea->u.Flags.BeingCreated = FALSE;
2643 
2644  /* We can release the PFN lock now */
2645  MiReleasePfnLock(OldIrql);
2646 
2647  /* Check if we locked and set the IRP */
2648  if (FileLock)
2649  {
2650  /* Undo */
2652  //FsRtlReleaseFile(File);
2653  }
2654 
2655  /* Free the control area and de-ref the file object */
2656  ExFreePool(ControlArea);
2658 
2659  /* All done */
2660  return Status;
2661  }
2662 
2663  /* On success, we expect this */
2664  ASSERT(PreviousSectionPointer == File->SectionObjectPointer);
2665 
2666  /* Check if a maximum size was specified */
2667  if (!InputMaximumSize->QuadPart)
2668  {
2669  /* Nope, use the segment size */
2670  Section.SizeOfSection.QuadPart = (LONGLONG)Segment->SizeOfSegment;
2671  }
2672  else
2673  {
2674  /* Yep, use the entered size */
2675  Section.SizeOfSection.QuadPart = InputMaximumSize->QuadPart;
2676  }
2677  }
2678  else
2679  {
2680  /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
2682 
2683  /* Not yet supported */
2685 
2686  /* So this must be a pagefile-backed section, create the mappings needed */
2687  Status = MiCreatePagingFileMap(&NewSegment,
2688  InputMaximumSize,
2689  ProtectionMask,
2691  if (!NT_SUCCESS(Status)) return Status;
2692 
2693  /* Set the size here, and read the control area */
2694  Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
2695  ControlArea = NewSegment->ControlArea;
2696 
2697  /* MiCreatePagingFileMap increments user references */
2698  UserRefIncremented = TRUE;
2699  }
2700 
2701  /* Did we already have a segment? */
2702  if (!NewSegment)
2703  {
2704  /* This must be the file path and we created a segment */
2705  NewSegment = Segment;
2706  ASSERT(File != NULL);
2707 
2708  /* Acquire the PFN lock while we set control area flags */
2709  OldIrql = MiAcquirePfnLock();
2710 
2711  /* We don't support this race condition yet, so assume no waiters */
2712  ASSERT(ControlArea->WaitingForDeletion == NULL);
2713  ControlArea->WaitingForDeletion = NULL;
2714 
2715  /* Image-file backed sections are not yet supported, nor ROM images */
2717  ASSERT(Segment->ControlArea->u.Flags.Rom == 0);
2718 
2719  /* Take off the being created flag, and then release the lock */
2720  ControlArea->u.Flags.BeingCreated = FALSE;
2721  MiReleasePfnLock(OldIrql);
2722  }
2723 
2724  /* Check if we locked the file earlier */
2725  if (FileLock)
2726  {
2727  /* Reset the top-level IRP and release the lock */
2729  //FsRtlReleaseFile(File);
2730  FileLock = FALSE;
2731  }
2732 
2733  /* Set the initial section object data */
2734  Section.InitialPageProtection = SectionPageProtection;
2735 
2736  /* The mapping created a control area and segment, save the flags */
2737  Section.Segment = NewSegment;
2738  Section.u.LongFlags = ControlArea->u.LongFlags;
2739 
2740  /* Check if this is a user-mode read-write non-image file mapping */
2741  if (!(FileObject) &&
2743  !(ControlArea->u.Flags.Image) &&
2744  (ControlArea->FilePointer))
2745  {
2746  /* Add a reference and set the flag */
2747  Section.u.Flags.UserWritable = TRUE;
2748  InterlockedIncrement((volatile LONG*)&ControlArea->WritableUserReferences);
2749  }
2750 
2751  /* Check for image mappings or page file mappings */
2752  if ((ControlArea->u.Flags.Image) || !(ControlArea->FilePointer))
2753  {
2754  /* Charge the segment size, and allocate a subsection */
2755  PagedCharge = sizeof(SECTION) + NewSegment->TotalNumberOfPtes * sizeof(MMPTE);
2756  Size = sizeof(SUBSECTION);
2757  }
2758  else
2759  {
2760  /* Charge nothing, and allocate a mapped subsection */
2761  PagedCharge = 0;
2762  Size = sizeof(MSUBSECTION);
2763  }
2764 
2765  /* Check if this is a normal CA */
2766  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
2767  ASSERT(ControlArea->u.Flags.Rom == 0);
2768 
2769  /* Charge only a CA, and the subsection is right after */
2770  NonPagedCharge = sizeof(CONTROL_AREA);
2771  Subsection = (PSUBSECTION)(ControlArea + 1);
2772 
2773  /* We only support single-subsection mappings */
2774  NonPagedCharge += Size;
2775  ASSERT(Subsection->NextSubsection == NULL);
2776 
2777  /* Create the actual section object, with enough space for the prototype PTEs */
2781  PreviousMode,
2782  NULL,
2783  sizeof(SECTION),
2784  PagedCharge,
2785  NonPagedCharge,
2786  (PVOID*)&NewSection);
2787  if (!NT_SUCCESS(Status))
2788  {
2789  /* Check if this is a user-mode read-write non-image file mapping */
2790  if (!(FileObject) &&
2792  !(ControlArea->u.Flags.Image) &&
2793  (ControlArea->FilePointer))
2794  {
2795  /* Remove a reference and check the flag */
2796  ASSERT(Section.u.Flags.UserWritable == 1);
2797  InterlockedDecrement((volatile LONG*)&ControlArea->WritableUserReferences);
2798  }
2799 
2800  /* Check if a user reference was added */
2801  if (UserRefIncremented)
2802  {
2803  /* Acquire the PFN lock while we change counters */
2804  OldIrql = MiAcquirePfnLock();
2805 
2806  /* Decrement the accounting counters */
2807  ControlArea->NumberOfSectionReferences--;
2808  ASSERT((LONG)ControlArea->NumberOfUserReferences > 0);
2809  ControlArea->NumberOfUserReferences--;
2810 
2811  /* Check if we should destroy the CA and release the lock */
2812  MiCheckControlArea(ControlArea, OldIrql);
2813  }
2814 
2815  /* Return the failure code */
2816  return Status;
2817  }
2818 
2819  /* NOTE: Past this point, all failures will be handled by Ob upon ref->0 */
2820 
2821  /* Now copy the local section object from the stack into this new object */
2822  RtlCopyMemory(NewSection, &Section, sizeof(SECTION));
2823  NewSection->Address.StartingVpn = 0;
2824 
2825  /* For now, only user calls are supported */
2826  ASSERT(KernelCall == FALSE);
2827  NewSection->u.Flags.UserReference = TRUE;
2828 
2829  /* Is this a "based" allocation, in which all mappings are identical? */
2831  {
2832  /* Lock the VAD tree during the search */
2834 
2835  /* Is it a brand new ControArea ? */
2836  if (ControlArea->u.Flags.BeingCreated == 1)
2837  {
2838  ASSERT(ControlArea->u.Flags.Based == 1);
2839  /* Then we must find a global address, top-down */
2842  _64K,
2844  (ULONG_PTR*)&ControlArea->Segment->BasedAddress);
2845 
2846  if (!NT_SUCCESS(Status))
2847  {
2848  /* No way to find a valid range. */
2850  ControlArea->u.Flags.Based = 0;
2851  NewSection->u.Flags.Based = 0;
2852  ObDereferenceObject(NewSection);
2853  return Status;
2854  }
2855 
2856  /* Compute the ending address and insert it into the VAD tree */
2857  NewSection->Address.StartingVpn = (ULONG_PTR)ControlArea->Segment->BasedAddress;
2858  NewSection->Address.EndingVpn = NewSection->Address.StartingVpn + NewSection->SizeOfSection.LowPart - 1;
2859  MiInsertBasedSection(NewSection);
2860  }
2861  else
2862  {
2863  /* FIXME : Should we deny section creation if SEC_BASED is not set ? Can we have two different section objects on the same based address ? Investigate !*/
2864  ASSERT(FALSE);
2865  }
2866 
2868  }
2869 
2870  /* The control area is not being created anymore */
2871  if (ControlArea->u.Flags.BeingCreated == 1)
2872  {
2873  /* Acquire the PFN lock while we set control area flags */
2874  OldIrql = MiAcquirePfnLock();
2875 
2876  /* Take off the being created flag, and then release the lock */
2877  ControlArea->u.Flags.BeingCreated = 0;
2878  NewSection->u.Flags.BeingCreated = 0;
2879 
2880  MiReleasePfnLock(OldIrql);
2881  }
2882 
2883  /* Migrate the attribute into a flag */
2884  if (AllocationAttributes & SEC_NO_CHANGE) NewSection->u.Flags.NoChange = TRUE;
2885 
2886  /* If R/W access is not requested, this might eventually become a CoW mapping */
2888  {
2889  NewSection->u.Flags.CopyOnWrite = TRUE;
2890  }
2891 
2892  /* Write down if this was a kernel call */
2893  ControlArea->u.Flags.WasPurged |= KernelCall;
2894  ASSERT(ControlArea->u.Flags.WasPurged == FALSE);
2895 
2896  /* Make sure the segment and the section are the same size, or the section is smaller */
2897  ASSERT((ULONG64)NewSection->SizeOfSection.QuadPart <= NewSection->Segment->SizeOfSegment);
2898 
2899  /* Return the object and the creation status */
2900  *SectionObject = (PVOID)NewSection;
2901  return Status;
2902 }
2903 
2904 /*
2905  * @implemented
2906  */
2907 NTSTATUS
2908 NTAPI
2918  IN ULONG Protect)
2919 {
2922  PSECTION Section;
2923  PCONTROL_AREA ControlArea;
2924  ULONG ProtectionMask;
2925  NTSTATUS Status;
2926  ULONG64 CalculatedViewSize;
2927  PAGED_CODE();
2928 
2929  /* Get the segment and control area */
2930  Section = (PSECTION)SectionObject;
2931  ControlArea = Section->Segment->ControlArea;
2932 
2933  /* These flags/states are not yet supported by ARM3 */
2934  ASSERT(Section->u.Flags.Image == 0);
2935  ASSERT(Section->u.Flags.NoCache == 0);
2936  ASSERT(Section->u.Flags.WriteCombined == 0);
2937  ASSERT(ControlArea->u.Flags.PhysicalMemory == 0);
2938 
2939  /* FIXME */
2940  if ((AllocationType & MEM_RESERVE) != 0)
2941  {
2942  DPRINT1("MmMapViewOfArm3Section called with MEM_RESERVE, this is not implemented yet!!!\n");
2943  return STATUS_NOT_IMPLEMENTED;
2944  }
2945 
2946  /* Check if the mapping protection is compatible with the create */
2948  {
2949  DPRINT1("Mapping protection is incompatible\n");
2951  }
2952 
2953  /* Check if the offset and size would cause an overflow */
2954  if (((ULONG64)SectionOffset->QuadPart + *ViewSize) <
2955  (ULONG64)SectionOffset->QuadPart)
2956  {
2957  DPRINT1("Section offset overflows\n");
2958  return STATUS_INVALID_VIEW_SIZE;
2959  }
2960 
2961  /* Check if the offset and size are bigger than the section itself */
2962  if (((ULONG64)SectionOffset->QuadPart + *ViewSize) >
2963  (ULONG64)Section->SizeOfSection.QuadPart)
2964  {
2965  DPRINT1("Section offset is larger than section\n");
2966  return STATUS_INVALID_VIEW_SIZE;
2967  }
2968 
2969  /* Check if the caller did not specify a view size */
2970  if (!(*ViewSize))
2971  {
2972  /* Compute it for the caller */
2973  CalculatedViewSize = Section->SizeOfSection.QuadPart -
2974  SectionOffset->QuadPart;
2975 
2976  /* Check if it's larger than 4GB or overflows into kernel-mode */
2977  if (!NT_SUCCESS(RtlULongLongToSIZET(CalculatedViewSize, ViewSize)) ||
2978  (((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)*BaseAddress) < CalculatedViewSize))
2979  {
2980  DPRINT1("Section view won't fit\n");
2981  return STATUS_INVALID_VIEW_SIZE;
2982  }
2983  }
2984 
2985  /* Check if the commit size is larger than the view size */
2986  if (CommitSize > *ViewSize)
2987  {
2988  DPRINT1("Attempting to commit more than the view itself\n");
2990  }
2991 
2992  /* Check if the view size is larger than the section */
2993  if (*ViewSize > (ULONG64)Section->SizeOfSection.QuadPart)
2994  {
2995  DPRINT1("The view is larger than the section\n");
2996  return STATUS_INVALID_VIEW_SIZE;
2997  }
2998 
2999  /* Compute and validate the protection mask */
3000  ProtectionMask = MiMakeProtectionMask(Protect);
3001  if (ProtectionMask == MM_INVALID_PROTECTION)
3002  {
3003  DPRINT1("The protection is invalid\n");
3005  }
3006 
3007  /* We only handle pagefile-backed sections, which cannot be writecombined */
3008  if (Protect & PAGE_WRITECOMBINE)
3009  {
3010  DPRINT1("Cannot write combine a pagefile-backed section\n");
3012  }
3013 
3014  /* Start by attaching to the current process if needed */
3015  if (PsGetCurrentProcess() != Process)
3016  {
3018  Attached = TRUE;
3019  }
3020 
3021  /* Do the actual mapping */
3022  Status = MiMapViewOfDataSection(ControlArea,
3023  Process,
3024  BaseAddress,
3025  SectionOffset,
3026  ViewSize,
3027  Section,
3029  ProtectionMask,
3030  CommitSize,
3031  ZeroBits,
3032  AllocationType);
3033 
3034  /* Detach if needed, then return status */
3036  return Status;
3037 }
3038 
3039 /*
3040  * @unimplemented
3041  */
3042 BOOLEAN
3043 NTAPI
3045 {
3046  UNIMPLEMENTED;
3047  return FALSE;
3048 }
3049 
3050 /*
3051  * @unimplemented
3052  */
3053 BOOLEAN
3054 NTAPI
3057 {
3058  UNIMPLEMENTED;
3059  return FALSE;
3060 }
3061 
3062 /*
3063  * @implemented
3064  */
3065 NTSTATUS
3066 NTAPI
3068  OUT PVOID *MappedBase,
3070 {
3071  PAGED_CODE();
3073 
3074  // HACK
3075  if (MiIsRosSectionObject(Section))
3076  {
3077  return MmMapViewInSystemSpace(Section, MappedBase, ViewSize);
3078  }
3079 
3080  /* Process must be in a session */
3081  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3082  {
3083  DPRINT1("Process is not in session\n");
3084  return STATUS_NOT_MAPPED_VIEW;
3085  }
3086 
3087  /* Use the system space API, but with the session view instead */
3089  SectionOffset.QuadPart = 0;
3090  return MiMapViewInSystemSpace(Section,
3092  MappedBase,
3093  ViewSize,
3094  &SectionOffset);
3095 }
3096 
3097 /*
3098  * @implemented
3099  */
3100 NTSTATUS
3101 NTAPI
3103 {
3104  PAGED_CODE();
3105 
3106  // HACK
3108  {
3110  }
3111 
3112  /* Process must be in a session */
3113  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3114  {
3115  DPRINT1("Proess is not in session\n");
3116  return STATUS_NOT_MAPPED_VIEW;
3117  }
3118 
3119  /* Use the system space API, but with the session view instead */
3122  MappedBase);
3123 }
3124 
3125 /*
3126  * @implemented
3127  */
3128 NTSTATUS
3129 NTAPI
3132 {
3134 }
3135 
3136 /*
3137  * @implemented
3138  */
3139 NTSTATUS
3140 NTAPI
3142 {
3144  PAGED_CODE();
3145 
3146  /* Was this mapped by RosMm? */
3150  {
3153  return Status;
3154  }
3156 
3157  /* It was not, call the ARM3 routine */
3159 }
3160 
3161 /*
3162  * @implemented
3163  */
3164 NTSTATUS
3165 NTAPI
3167  IN SIZE_T ViewSize)
3168 {
3169  ULONG_PTR StartAddress, EndingAddress, Base;
3170  ULONG Hash, Count = 0, Size, QuotaCharge;
3172  PMMPTE LastProtoPte, PointerPte, ProtoPte;
3173  PCONTROL_AREA ControlArea;
3174  PSEGMENT Segment;
3175  PSUBSECTION Subsection;
3176  MMPTE TempPte;
3177  PAGED_CODE();
3178 
3179  /* Make sure the base isn't past the session view range */
3180  if ((MappedBase < MiSessionViewStart) ||
3182  {
3183  DPRINT1("Base outside of valid range\n");
3185  }
3186 
3187  /* Make sure the size isn't past the session view range */
3190  {
3191  DPRINT1("Size outside of valid range\n");
3193  }
3194 
3195  /* Sanity check */
3196  ASSERT(ViewSize != 0);
3197 
3198  /* Process must be in a session */
3199  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3200  {
3201  DPRINT1("Process is not in session\n");
3202  return STATUS_NOT_MAPPED_VIEW;
3203  }
3204 
3205  /* Compute the correctly aligned base and end addresses */
3206  StartAddress = (ULONG_PTR)PAGE_ALIGN(MappedBase);
3207  EndingAddress = ((ULONG_PTR)MappedBase + ViewSize - 1) | (PAGE_SIZE - 1);
3208 
3209  /* Sanity check and grab the session */
3212 
3213  /* Get the hash entry for this allocation */
3214  Hash = (StartAddress >> 16) % Session->SystemSpaceHashKey;
3215 
3216  /* Lock system space */
3218 
3219  /* Loop twice so we can try rolling over if needed */
3220  while (TRUE)
3221  {
3222  /* Extract the size and base addresses from the entry */
3223  Base = Session->SystemSpaceViewTable[Hash].Entry & ~0xFFFF;
3225 
3226  /* Convert the size to bucket chunks */
3228 
3229  /* Bail out if this entry fits in here */
3230  if ((StartAddress >= Base) && (EndingAddress < (Base + Size))) break;
3231 
3232  /* Check if we overflew past the end of the hash table */
3233  if (++Hash >= Session->SystemSpaceHashSize)
3234  {
3235  /* Reset the hash to zero and keep searching from the bottom */
3236  Hash = 0;
3237  if (++Count == 2)
3238  {
3239  /* But if we overflew twice, then this is not a real mapping */
3240  KeBugCheckEx(DRIVER_UNMAPPING_INVALID_VIEW,
3241  Base,
3242  2,
3243  0,
3244  0);
3245  }
3246  }
3247  }
3248 
3249  /* Make sure the view being mapped is not file-based */
3250  ControlArea = Session->SystemSpaceViewTable[Hash].ControlArea;
3251  if (ControlArea->FilePointer != NULL)
3252  {
3253  /* It is, so we have to bail out */
3254  DPRINT1("Only page-filed backed sections can be commited\n");
3256  return STATUS_ALREADY_COMMITTED;
3257  }
3258 
3259  /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
3260  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
3261  ASSERT(ControlArea->u.Flags.Rom == 0);
3262  Subsection = (PSUBSECTION)(ControlArea + 1);
3263 
3264  /* Get the start and end PTEs -- make sure the end PTE isn't past the end */
3265  ProtoPte = Subsection->SubsectionBase + ((StartAddress - Base) >> PAGE_SHIFT);
3266  QuotaCharge = MiAddressToPte(EndingAddress) - MiAddressToPte(StartAddress) + 1;
3267  LastProtoPte = ProtoPte + QuotaCharge;
3268  if (LastProtoPte >= Subsection->SubsectionBase + Subsection->PtesInSubsection)
3269  {
3270  DPRINT1("PTE is out of bounds\n");
3273  }
3274 
3275  /* Acquire the commit lock and count all the non-committed PTEs */
3277  PointerPte = ProtoPte;
3278  while (PointerPte < LastProtoPte)
3279  {
3280  if (PointerPte->u.Long) QuotaCharge--;
3281  PointerPte++;
3282  }
3283 
3284  /* Was everything committed already? */
3285  if (!QuotaCharge)
3286  {
3287  /* Nothing to do! */
3290  return STATUS_SUCCESS;
3291  }
3292 
3293  /* Pick the segment and template PTE */
3294  Segment = ControlArea->Segment;
3295  TempPte = Segment->SegmentPteTemplate;
3296  ASSERT(TempPte.u.Long != 0);
3297 
3298  /* Loop all prototype PTEs to be committed */
3299  PointerPte = ProtoPte;
3300  while (PointerPte < LastProtoPte)
3301  {
3302  /* Make sure the PTE is already invalid */
3303  if (PointerPte->u.Long == 0)
3304  {
3305  /* And write the invalid PTE */
3306  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
3307  }
3308 
3309  /* Move to the next PTE */
3310  PointerPte++;
3311  }
3312 
3313  /* Check if we had at least one page charged */
3314  if (QuotaCharge)
3315  {
3316  /* Update the accounting data */
3317  Segment->NumberOfCommittedPages += QuotaCharge;
3319  }
3320 
3321  /* Release all */
3324  return STATUS_SUCCESS;
3325 }
3326 
3327 VOID
3328 NTAPI
3330 {
3332  PCONTROL_AREA ControlArea;
3333  KIRQL OldIrql;
3334 
3335  SectionObject = (PSECTION)ObjectBody;
3336 
3337  if (SectionObject->u.Flags.Based == 1)
3338  {
3339  /* Remove the node from the global section address tree */
3343  }
3344 
3345  /* Lock the PFN database */
3346  OldIrql = MiAcquirePfnLock();
3347 
3348  ASSERT(SectionObject->Segment);
3349  ASSERT(SectionObject->Segment->ControlArea);
3350 
3351  ControlArea = SectionObject->Segment->ControlArea;
3352 
3353  /* Dereference */
3354  ControlArea->NumberOfSectionReferences--;
3355  ControlArea->NumberOfUserReferences--;
3356 
3357  ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
3358 
3359  /* Check it. It will delete it if there is no more reference to it */
3360  MiCheckControlArea(ControlArea, OldIrql);
3361 }
3362 
3363 ULONG
3364 NTAPI
3366 {
3368  return 0;
3369 }
3370 
3371 /* SYSTEM CALLS ***************************************************************/
3372 
3373 NTSTATUS
3374 NTAPI
3375 NtAreMappedFilesTheSame(IN PVOID File1MappedAsAnImage,
3376  IN PVOID File2MappedAsFile)
3377 {
3379  PMMVAD Vad1, Vad2;
3380  PFILE_OBJECT FileObject1, FileObject2;
3381  NTSTATUS Status;
3382 
3383  /* Lock address space */
3386 
3387  /* Get the VAD for Address 1 */
3388  Vad1 = MiLocateAddress(File1MappedAsAnImage);
3389  if (Vad1 == NULL)
3390  {
3391  /* Fail, the address does not exist */
3392  DPRINT1("No VAD at address 1 %p\n", File1MappedAsAnImage);
3394  goto Exit;
3395  }
3396 
3397  /* Get the VAD for Address 2 */
3398  Vad2 = MiLocateAddress(File2MappedAsFile);
3399  if (Vad2 == NULL)
3400  {
3401  /* Fail, the address does not exist */
3402  DPRINT1("No VAD at address 2 %p\n", File2MappedAsFile);
3404  goto Exit;
3405  }
3406 
3407  /* Get the file object pointer for VAD 1 */
3408  FileObject1 = MiGetFileObjectForVad(Vad1);
3409  if (FileObject1 == NULL)
3410  {
3411  DPRINT1("Failed to get file object for Address 1 %p\n", File1MappedAsAnImage);
3413  goto Exit;
3414  }
3415 
3416  /* Get the file object pointer for VAD 2 */
3417  FileObject2 = MiGetFileObjectForVad(Vad2);
3418  if (FileObject2 == NULL)
3419  {
3420  DPRINT1("Failed to get file object for Address 2 %p\n", File2MappedAsFile);
3422  goto Exit;
3423  }
3424 
3425  /* Make sure Vad1 is an image mapping */
3426  if (Vad1->u.VadFlags.VadType != VadImageMap)
3427  {
3428  DPRINT1("Address 1 (%p) is not an image mapping\n", File1MappedAsAnImage);
3430  goto Exit;
3431  }
3432 
3433  /* SectionObjectPointer is equal if the files are equal */
3434  if (FileObject1->SectionObjectPointer == FileObject2->SectionObjectPointer)
3435  {
3437  }
3438  else
3439  {
3441  }
3442 
3443 Exit:
3444  /* Unlock address space */
3446  return Status;
3447 }
3448 
3449 /*
3450  * @implemented
3451  */
3452 NTSTATUS
3453 NTAPI
3461 {
3462  LARGE_INTEGER SafeMaximumSize;
3464  HANDLE Handle;
3466  NTSTATUS Status;
3467  PAGED_CODE();
3468 
3469  /* Check for non-existing flags */
3472  SEC_NO_CHANGE)))
3473  {
3474  if (!(AllocationAttributes & 1))
3475  {
3476  DPRINT1("Bogus allocation attribute: %lx\n", AllocationAttributes);
3478  }
3479  }
3480 
3481  /* Check for no allocation type */
3483  {
3484  DPRINT1("Missing allocation type in allocation attributes\n");
3486  }
3487 
3488  /* Check for image allocation with invalid attributes */
3489  if ((AllocationAttributes & SEC_IMAGE) &&
3492  {
3493  DPRINT1("Image allocation with invalid attributes\n");
3495  }
3496 
3497  /* Check for allocation type is both commit and reserve */
3499  {
3500  DPRINT1("Commit and reserve in the same time\n");
3502  }
3503 
3504  /* Now check for valid protection */
3509  {
3510  DPRINT1("Sections don't support these protections\n");
3512  }
3513 
3514  /* Use a maximum size of zero, if none was specified */
3515  SafeMaximumSize.QuadPart = 0;
3516 
3517  /* Check for user-mode caller */
3518  if (PreviousMode != KernelMode)
3519  {
3520  /* Enter SEH */
3521  _SEH2_TRY
3522  {
3523  /* Safely check user-mode parameters */
3524  if (MaximumSize) SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
3525  MaximumSize = &SafeMaximumSize;
3526  ProbeForWriteHandle(SectionHandle);
3527  }
3529  {
3530  /* Return the exception code */
3532  }
3533  _SEH2_END;
3534  }
3535  else if (!MaximumSize) MaximumSize = &SafeMaximumSize;
3536 
3537  /* Check that MaximumSize is valid if backed by paging file */
3538  if ((!FileHandle) && (!MaximumSize->QuadPart))
3540 
3541  /* Create the section */
3543  DesiredAccess,
3545  MaximumSize,
3548  FileHandle,
3549  NULL);
3550  if (!NT_SUCCESS(Status)) return Status;
3551 
3552  /* FIXME: Should zero last page for a file mapping */
3553 
3554  /* Now insert the object */
3556  NULL,
3557  DesiredAccess,
3558  0,
3559  NULL,
3560  &Handle);
3561  if (NT_SUCCESS(Status))
3562  {
3563  /* Enter SEH */
3564  _SEH2_TRY
3565  {
3566  /* Return the handle safely */
3567  *SectionHandle = Handle;
3568  }
3570  {
3571  /* Nothing here */
3572  }
3573  _SEH2_END;
3574  }
3575 
3576  /* Return the status */
3577  return Status;
3578 }
3579 
3580 NTSTATUS
3581 NTAPI
3582 NtOpenSection(OUT PHANDLE SectionHandle,
3585 {
3586  HANDLE Handle;
3587  NTSTATUS Status;
3589  PAGED_CODE();
3590 
3591  /* Check for user-mode caller */
3592  if (PreviousMode != KernelMode)
3593  {
3594  /* Enter SEH */
3595  _SEH2_TRY
3596  {
3597  /* Safely check user-mode parameters */
3598  ProbeForWriteHandle(SectionHandle);
3599  }
3601  {
3602  /* Return the exception code */
3604  }
3605  _SEH2_END;
3606  }
3607 
3608  /* Try opening the object */
3611  PreviousMode,
3612  NULL,
3613  DesiredAccess,
3614  NULL,
3615  &Handle);
3616 
3617  /* Enter SEH */
3618  _SEH2_TRY
3619  {
3620  /* Return the handle safely */
3621  *SectionHandle = Handle;
3622  }
3624  {
3625  /* Nothing here */
3626  }
3627  _SEH2_END;
3628 
3629  /* Return the status */
3630  return Status;
3631 }
3632 
3633 NTSTATUS
3634 NTAPI
3644  IN ULONG Protect)
3645 {
3646  PVOID SafeBaseAddress;
3647  LARGE_INTEGER SafeSectionOffset;
3648  SIZE_T SafeViewSize;
3649  PSECTION Section;
3651  NTSTATUS Status;
3653  ULONG ProtectionMask;
3655 #if defined(_M_IX86) || defined(_M_AMD64)
3656  static const ULONG ValidAllocationType = (MEM_TOP_DOWN | MEM_LARGE_PAGES |
3658 #else
3659  static const ULONG ValidAllocationType = (MEM_TOP_DOWN | MEM_LARGE_PAGES |
3661 #endif
3662 
3663  /* Check for invalid inherit disposition */
3665  {
3666  DPRINT1("Invalid inherit disposition\n");
3668  }
3669 
3670  /* Allow only valid allocation types */
3671  if (AllocationType & ~ValidAllocationType)
3672  {
3673  DPRINT1("Invalid allocation type\n");
3675  }
3676 
3677  /* Convert the protection mask, and validate it */
3678  ProtectionMask = MiMakeProtectionMask(Protect);
3679  if (ProtectionMask == MM_INVALID_PROTECTION)
3680  {
3681  DPRINT1("Invalid page protection\n");
3683  }
3684 
3685  /* Now convert the protection mask into desired section access mask */
3686  DesiredAccess = MmMakeSectionAccess[ProtectionMask & 0x7];
3687 
3688  /* Assume no section offset */
3689  SafeSectionOffset.QuadPart = 0;
3690 
3691  /* Enter SEH */
3692  _SEH2_TRY
3693  {
3694  /* Check for unsafe parameters */
3695  if (PreviousMode != KernelMode)
3696  {
3697  /* Probe the parameters */
3700  }
3701 
3702  /* Check if a section offset was given */
3703  if (SectionOffset)
3704  {
3705  /* Check for unsafe parameters and capture section offset */
3707  SafeSectionOffset = *SectionOffset;
3708  }
3709 
3710  /* Capture the other parameters */
3711  SafeBaseAddress = *BaseAddress;
3712  SafeViewSize = *ViewSize;
3713  }
3715  {
3716  /* Return the exception code */
3718  }
3719  _SEH2_END;
3720 
3721  /* Check for kernel-mode address */
3722  if (SafeBaseAddress > MM_HIGHEST_VAD_ADDRESS)
3723  {
3724  DPRINT1("Kernel base not allowed\n");
3726  }
3727 
3728  /* Check for range entering kernel-mode */
3729  if (((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)SafeBaseAddress) < SafeViewSize)
3730  {
3731  DPRINT1("Overflowing into kernel base not allowed\n");
3733  }
3734 
3735  /* Check for invalid zero bits */
3736  if (ZeroBits)
3737  {
3738  if (ZeroBits > MI_MAX_ZERO_BITS)
3739  {
3740  DPRINT1("Invalid zero bits\n");
3742  }
3743 
3744  if ((((ULONG_PTR)SafeBaseAddress << ZeroBits) >> ZeroBits) != (ULONG_PTR)SafeBaseAddress)
3745  {
3746  DPRINT1("Invalid zero bits\n");
3748  }
3749 
3750  if (((((ULONG_PTR)SafeBaseAddress + SafeViewSize) << ZeroBits) >> ZeroBits) != ((ULONG_PTR)SafeBaseAddress + SafeViewSize))
3751  {
3752  DPRINT1("Invalid zero bits\n");
3754  }
3755  }
3756 
3757  /* Reference the process */
3760  PsProcessType,
3761  PreviousMode,
3762  (PVOID*)&Process,
3763  NULL);
3764  if (!NT_SUCCESS(Status)) return Status;
3765 
3766  /* Reference the section */
3767  Status = ObReferenceObjectByHandle(SectionHandle,
3768  DesiredAccess,
3770  PreviousMode,
3771  (PVOID*)&Section,
3772  NULL);
3773  if (!NT_SUCCESS(Status))
3774  {
3776  return Status;
3777  }
3778 
3779  if (Section->u.Flags.PhysicalMemory)
3780  {
3781  if (PreviousMode == UserMode &&
3782  SafeSectionOffset.QuadPart + SafeViewSize > MmHighestPhysicalPage << PAGE_SHIFT)
3783  {
3784  DPRINT1("Denying map past highest physical page.\n");
3785  ObDereferenceObject(Section);
3788  }
3789  }
3790  else if (!(AllocationType & MEM_DOS_LIM))
3791  {
3792  /* Check for non-allocation-granularity-aligned BaseAddress */
3793  if (SafeBaseAddress != ALIGN_DOWN_POINTER_BY(SafeBaseAddress, MM_VIRTMEM_GRANULARITY))
3794  {
3795  DPRINT("BaseAddress is not at 64-kilobyte address boundary.\n");
3796  ObDereferenceObject(Section);
3798  return STATUS_MAPPED_ALIGNMENT;
3799  }
3800 
3801  /* Do the same for the section offset */
3802  if (SafeSectionOffset.LowPart != ALIGN_DOWN_BY(SafeSectionOffset.LowPart, MM_VIRTMEM_GRANULARITY))
3803  {
3804  DPRINT("SectionOffset is not at 64-kilobyte address boundary.\n");
3805  ObDereferenceObject(Section);
3807  return STATUS_MAPPED_ALIGNMENT;
3808  }
3809  }
3810 
3811  /* Now do the actual mapping */
3812  Status = MmMapViewOfSection(Section,
3813  Process,
3814  &SafeBaseAddress,
3815  ZeroBits,
3816  CommitSize,
3817  &SafeSectionOffset,
3818  &SafeViewSize,
3821  Protect);
3822 
3823  /* Return data only on success */
3824  if (NT_SUCCESS(Status))
3825  {
3826  /* Check if this is an image for the current process */
3827  if ((Section->u.Flags.Image) &&
3828  (Process == PsGetCurrentProcess()) &&
3830  {
3831  /* Notify the debugger */
3832  DbgkMapViewOfSection(Section,
3833  SafeBaseAddress,
3834  SafeSectionOffset.LowPart,
3835  SafeViewSize);
3836  }
3837 
3838  /* Enter SEH */
3839  _SEH2_TRY
3840  {
3841  /* Return parameters to user */
3842  *BaseAddress = SafeBaseAddress;
3843  *ViewSize = SafeViewSize;
3844  if (SectionOffset) *SectionOffset = SafeSectionOffset;
3845  }
3847  {
3848  /* Nothing to do */
3849  }
3850  _SEH2_END;
3851  }
3852 
3853  /* Dereference all objects and return status */
3854  ObDereferenceObject(Section);
3856  return Status;
3857 }
3858 
3859 NTSTATUS
3860 NTAPI
3863 {
3865  NTSTATUS Status;
3867 
3868  /* Don't allowing mapping kernel views */
3870  {
3871  DPRINT1("Trying to unmap a kernel view\n");
3872  return STATUS_NOT_MAPPED_VIEW;
3873  }
3874 
3875  /* Reference the process */
3878  PsProcessType,
3879  PreviousMode,
3880  (PVOID*)&Process,
3881  NULL);
3882  if (!NT_SUCCESS(Status)) return Status;
3883 
3884  /* Unmap the view */
3886 
3887  /* Dereference the process and return status */
3889  return Status;
3890 }
3891 
3892 NTSTATUS
3893 NTAPI
3894 NtExtendSection(IN HANDLE SectionHandle,
3895  IN OUT PLARGE_INTEGER NewMaximumSize)
3896 {
3897  LARGE_INTEGER SafeNewMaximumSize;
3898  PSECTION Section;
3899  NTSTATUS Status;
3901 
3902  /* Check for user-mode parameters */
3903  if (PreviousMode != KernelMode)
3904  {
3905  /* Enter SEH */
3906  _SEH2_TRY
3907  {
3908  /* Probe and capture the maximum size, it's both read and write */
3909  ProbeForWriteLargeInteger(NewMaximumSize);
3910  SafeNewMaximumSize = *NewMaximumSize;
3911  }
3913  {
3914  /* Return the exception code */
3916  }
3917  _SEH2_END;
3918  }
3919  else
3920  {
3921  /* Just read the size directly */
3922  SafeNewMaximumSize = *NewMaximumSize;
3923  }
3924 
3925  /* Reference the section */
3926  Status = ObReferenceObjectByHandle(SectionHandle,
3929  PreviousMode,
3930  (PVOID*)&Section,
3931  NULL);
3932  if (!NT_SUCCESS(Status)) return Status;
3933 
3934  Status = MmExtendSection(Section, &SafeNewMaximumSize);
3935 
3936  /* Dereference the section */
3937  ObDereferenceObject(Section);
3938 
3939  if (NT_SUCCESS(Status))
3940  {
3941  _SEH2_TRY
3942  {
3943  /* Write back the new size */
3944  *NewMaximumSize = SafeNewMaximumSize;
3945  }
3947  {
3949  }
3950  _SEH2_END;
3951  }
3952 
3953  /* Return the status */
3954  return STATUS_NOT_IMPLEMENTED;
3955 }
3956 
3957 /* EOF */
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT InheritDisposition
Definition: mmfuncs.h:404
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
NTSTATUS NTAPI ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN OUT PVOID ParseContext, OUT PHANDLE Handle)
Definition: obhandle.c:2532
_SEH2_TRY
Definition: create.c:4226
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define PAGE_NOCACHE
Definition: nt_native.h:1311
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
static int Hash(const char *)
Definition: reader.c:2257
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define MEM_LARGE_PAGES
Definition: nt_native.h:1322
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
#define PDE_PER_PAGE
Definition: mm.h:21
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR ZeroBits
Definition: mmfuncs.h:404
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:39
#define MM_VIRTMEM_GRANULARITY
Definition: mm.h:102
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
MMPTE PrototypePte
Definition: init.c:40
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
ULONG NumberOfCommittedPages
Definition: mmtypes.h:412
PEVENT_COUNTER WaitingForDeletion
Definition: mmtypes.h:531
NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN PVOID BaseAddress)
Definition: section.c:3861
union _MMPTE::@2285 u
KAPC_STATE
Definition: ketypes.h:1285
PFILE_OBJECT FilePointer
Definition: mmtypes.h:530
SIZE_T NonPageablePages
Definition: miarm.h:486
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
BOOLEAN NTAPI MiIsProtectionCompatible(IN ULONG SectionPageProtection, IN ULONG NewSectionPageProtection)
Definition: section.c:117
NTSTATUS NTAPI MiQueryMemorySectionName(IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID MemoryInformation, IN SIZE_T MemoryInformationLength, OUT PSIZE_T ReturnLength)
Definition: section.c:1966
ULONG NTAPI MiMakeSystemAddressValidPfn(IN PVOID VirtualAddress, IN KIRQL OldIrql)
Definition: virtual.c:235
#define SEC_LARGE_PAGES
Definition: mmtypes.h:102
struct _RTL_BITMAP RTL_BITMAP
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:603
ULONG Type
Definition: mm.h:251
struct _MEMORY_AREA * PMEMORY_AREA
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1244
NTSTATUS NTAPI PsChargeProcessNonPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Charges the non paged pool quota of a given process.
Definition: quota.c:811
#define _Inout_
Definition: ms_sal.h:378
NTSTATUS NTAPI NtAreMappedFilesTheSame(IN PVOID File1MappedAsAnImage, IN PVOID File2MappedAsFile)
Definition: section.c:3375
NTSTATUS NTAPI MmGetFileNameForAddress(IN PVOID Address, OUT PUNICODE_STRING ModuleName)
Definition: section.c:1903
ULONGLONG SizeOfSegment
Definition: mmtypes.h:410
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ ULONG AllocationAttributes
Definition: mmfuncs.h:360
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1043
#define MiAddressToPde(x)
Definition: mmx86.c:20
ULONG NumberOfSectionReferences
Definition: mmtypes.h:520
#define STATUS_NOT_SAME_DEVICE
Definition: ntstatus.h:448
NTSTATUS NTAPI NtCreateSection(OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize OPTIONAL, IN ULONG SectionPageProtection OPTIONAL, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL)
Definition: section.c:3454
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:265
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
PSEGMENT Segment
Definition: mmtypes.h:809
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:166
NTSTATUS NTAPI MiCreateDataFileMap(IN PFILE_OBJECT File, OUT PSEGMENT *Segment, IN PSIZE_T MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN ULONG IgnoreFileSizing)
Definition: section.c:1554
USHORT MaximumLength
Definition: env_spec_w32.h:370
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
ULONG NonExtendedPtes
Definition: mmtypes.h:408
PMMPDE PageTables
Definition: miarm.h:512
BOOLEAN NTAPI MmDisableModifiedWriteOfSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer)
Definition: section.c:3044
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG _In_ ULONG Protect
Definition: zwfuncs.h:214
#define SIZE_T_MAX
Definition: dhcpd.h:91
ULONG PhysicalMemory
Definition: mmtypes.h:470
ULONG PFN_COUNT
Definition: mmtypes.h:102
#define TRUE
Definition: types.h:120
#define MI_IS_SESSION_ADDRESS(Address)
Definition: miarm.h:171
uint16_t * PWSTR
Definition: typedefs.h:56
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
CHAR MmUserProtectionToMask1[16]
Definition: section.c:44
#define PAGE_GUARD
Definition: nt_native.h:1310
PMMPTE LastContiguousPte
Definition: mmtypes.h:764
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2272
VOID NTAPI MiRemoveMappedPtes(IN PVOID BaseAddress, IN ULONG NumberOfPtes, IN PCONTROL_AREA ControlArea, IN PMMSUPPORT Ws)
Definition: section.c:2306
char CHAR
Definition: xmlstorage.h:175
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1666
ULONG InitialPageProtection
Definition: mmtypes.h:816
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:760
KGUARDED_MUTEX MmSectionBasedMutex
Definition: section.c:110
ULONG_PTR CommitCharge
Definition: mmtypes.h:688
PCONTROL_AREA ControlArea
Definition: mmtypes.h:570
LONG NTSTATUS
Definition: precomp.h:26
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
MMPTE ThePtes[1]
Definition: mmtypes.h:427
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2413
NTSTATUS NTAPI MmGetFileNameForSection(IN PVOID Section, OUT POBJECT_NAME_INFORMATION *ModuleName)
Definition: section.c:1882
BOOLEAN NTAPI MiInitializeSystemSpaceMap(IN PMMSESSION InputSession OPTIONAL)
Definition: section.c:240
#define ProbeForWriteSize_t(Ptr)
Definition: probe.h:45
#define STATUS_INVALID_PARAMETER_9
Definition: ntstatus.h:483
SIZE_T MmSharedCommit
Definition: freelist.c:31
ULONG LargePages
Definition: mmtypes.h:400
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:237
#define STATUS_INVALID_PARAMETER_8
Definition: ntstatus.h:482
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
VOID NTAPI DbgkMapViewOfSection(IN PVOID Section, IN PVOID BaseAddress, IN ULONG SectionOffset, IN ULONG_PTR ViewSize)
Definition: dbgkutil.c:380
ULONG SizeOfImage
Definition: ldrtypes.h:143
#define MM_READWRITE
Definition: bootanim.c:19
#define MM_NOACCESS
Definition: miarm.h:65
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
ACCESS_MASK MmMakeFileAccess[8]
Definition: section.c:32
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
union _MMPFN::@1752 u1
#define MAXULONG_PTR
Definition: basetsd.h:103
USHORT Modified
Definition: mm.h:360
VOID NTAPI MiRemoveMappedView(IN PEPROCESS CurrentProcess, IN PMMVAD Vad)
Definition: section.c:784
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
NTSTATUS NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
Definition: obname.c:1207
PCHAR SystemSpaceViewStart
Definition: miarm.h:457
ULONG SecNoChange
Definition: mmtypes.h:704
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3062
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1282
PCONTROL_AREA ControlArea
Definition: mmtypes.h:762
ULONG_PTR Protection
Definition: mmtypes.h:693
VOID NTAPI MiSubsectionConsistent(IN PSUBSECTION Subsection)
Definition: section.c:1537
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char const char * ModuleName
Definition: acpixf.h:1274
VOID NTAPI MiLoadUserSymbols(IN PCONTROL_AREA ControlArea, IN PVOID BaseAddress, IN PEPROCESS Process)
Definition: section.c:1186
ULONG SystemSpaceHashEntries
Definition: miarm.h:460
ULONG BitmapFailures
Definition: miarm.h:462
#define SEC_NOCACHE
Definition: mmtypes.h:100
static NTSTATUS NTAPI MiCreatePagingFileMap(OUT PSEGMENT *Segment, IN PLARGE_INTEGER MaximumSize, IN ULONG ProtectionMask, IN ULONG AllocationAttributes)
Definition: section.c:1570
NTSTATUS NTAPI MiFindEmptyAddressRangeDownBasedTree(IN SIZE_T Length, IN ULONG_PTR BoundaryAddress, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PULONG_PTR Base)
Definition: vadnode.c:713
_SEH2_END
Definition: create.c:4400
ULONG TotalNumberOfPtes
Definition: mmtypes.h:407
UNICODE_STRING Name
Definition: nt_native.h:1270
union _MMVAD_LONG::@2570 u2
struct _SUBSECTION SUBSECTION
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
FORCEINLINE PMMPDE MiPteToPde(PMMPTE PointerPte)
Definition: mm.h:268
USHORT ReferenceCount
Definition: mm.h:396
ULONG_PTR NoChange
Definition: mmtypes.h:690
VOID NTAPI MiInsertBasedSection(IN PSECTION Section)
Definition: vadnode.c:345
#define MM_NOCACHE
Definition: miarm.h:56
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
NTSTATUS NTAPI MiSessionCommitPageTables(IN PVOID StartVa, IN PVOID EndVa)
Definition: section.c:942
union _CONTROL_AREA::@2559 u
USHORT PageLocation
Definition: mm.h:365
struct Color Color
KGUARDED_MUTEX SystemSpaceViewLock
Definition: miarm.h:455
_Must_inspect_result_ _In_ PDEVICE_OBJECT _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer
Definition: fsrtlfuncs.h:1368
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define MM_DELETE_CHECK
Definition: miarm.h:261
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:533
SIZE_T MmSizeOfPagedPoolInBytes
Definition: miarm.h:590
struct _CONTROL_AREA * ControlArea
Definition: mmtypes.h:406
uint32_t ULONG_PTR
Definition: typedefs.h:65
union _MMVAD_LONG::@2572 u4
#define STATUS_ALREADY_COMMITTED
Definition: ntstatus.h:270
NTSTATUS NTAPI MiCheckPurgeAndUpMapCount(IN PCONTROL_AREA ControlArea, IN BOOLEAN FailIfSystemViews)
Definition: section.c:548
#define SEC_BASED
PEPROCESS CreatingProcess
Definition: mmtypes.h:419
ERESOURCE PsLoadedModuleResource
Definition: sysldr.c:37
VOID NTAPI MiDereferenceControlArea(IN PCONTROL_AREA ControlArea)
Definition: section.c:767
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define MM_EXECUTE_WRITECOPY
Definition: miarm.h:50
NTSTATUS NTAPI MmCreateArm3Section(OUT PVOID *SectionObject, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER InputMaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: section.c:2486
USHORT PrototypePte
Definition: mm.h:363
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG SectionPageProtection
Definition: mmfuncs.h:360
PVOID DllBase
Definition: btrfs_drv.h:1880
ULONG64 Dirty
Definition: mmtypes.h:164
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:397
PVOID MmSessionBase
Definition: init.c:33
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
return STATUS_NOT_IMPLEMENTED
#define MM_WRITECOPY
Definition: miarm.h:48
const ULONG MmProtectToValue[32]
Definition: page.c:71
ASSERT(Segment->Locked)
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define PAGE_EXECUTE_WRITECOPY
Definition: nt_native.h:1309
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define MM_NOIRQL
Definition: mm.h:70
VOID NTAPI MiDeleteARM3Section(PVOID ObjectBody)
Definition: section.c:3329
ULONG PFN_NUMBER
Definition: ke.h:9
static BOOL Attached
Definition: vidbios.c:3905
#define STATUS_INVALID_PARAMETER_3
Definition: ntstatus.h:477
ULONG NTAPI MiRemoveFromSystemSpace(IN PMMSESSION Session, IN PVOID Base, OUT PCONTROL_AREA *ControlArea)
Definition: section.c:2408
#define SEC_COMMIT
Definition: mmtypes.h:99
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
#define TAG_MM
Definition: tag.h:110
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:97
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define UNICODE_NULL
ULONG MmSystemViewSize
Definition: init.c:39
struct _SUBSECTION * NextSubsection
Definition: mmtypes.h:581
static PFILE_OBJECT MiGetFileObjectForVad(_In_ PMMVAD Vad)
Definition: section.c:1774
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI DbgBreakPoint(VOID)
NTSTATUS NTAPI MmMapViewOfArm3Section(IN PVOID SectionObject, IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:2909
#define _Outptr_result_bytebuffer_(size)
Definition: ms_sal.h:472
#define _WARN(msg)
Definition: debug.h:263
long LONG
Definition: pedump.c:60
NTSTATUS NTAPI MmUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:3141
LARGE_INTEGER SizeOfSection
Definition: mmtypes.h:810
static NTSTATUS MiAddMappedPtes(IN PMMPTE FirstPte, IN PFN_NUMBER PteCount, IN PCONTROL_AREA ControlArea, IN LONGLONG SectionOffset)
Definition: section.c:417
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:207
ULONG MmSessionViewSize
Definition: init.c:35
#define SEC_RESERVE
Definition: nt_native.h:1323
#define FILE_READ_DATA
Definition: nt_native.h:628
PKEVENT Event
Definition: mm.h:379
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
#define MEM_RESERVE
Definition: nt_native.h:1314
struct _MSUBSECTION MSUBSECTION
#define STATUS_MAPPED_ALIGNMENT
Definition: ntstatus.h:676
PVOID MiSystemViewStart
Definition: init.c:38
NTSTATUS NTAPI MmUnmapViewInSessionSpace(IN PVOID MappedBase)
Definition: section.c:3102
NTSTATUS NTAPI FsRtlAcquireToCreateMappedSection(_In_ PFILE_OBJECT FileObject, _In_ ULONG SectionPageProtection)
Definition: fastio.c:1647
NTSTATUS NTAPI MiRosUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress, IN BOOLEAN SkipDebuggerNotify)
Definition: section.c:3568
NTSTATUS Status
Definition: section.c:4935
TCHAR ModuleFileName[MAX_PATH+1]
Definition: rundll32.c:55
PCONTROL_AREA ControlArea
Definition: mmtypes.h:733
#define PsGetCurrentProcess
Definition: psfuncs.h:17
NTSTATUS NTAPI NtMapViewOfSection(IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:3635
_In_ BOOLEAN DelayClose
Definition: mmfuncs.h:592
NTSTATUS NTAPI MiSetProtectionOnSection(IN PEPROCESS Process, IN PMMVAD FoundVad, IN PVOID StartingAddress, IN PVOID EndingAddress, IN ULONG NewProtect, OUT PULONG CapturedOldProtect, IN ULONG DontCharge, OUT PULONG Locked)
Definition: section.c:2137
NTSTATUS NTAPI NtOpenSection(OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: section.c:3582
PFN_NUMBER MmSystemPageDirectory[PPE_PER_PAGE]
Definition: init.c:40
#define PAGE_NOACCESS
Definition: nt_native.h:1302
unsigned char BOOLEAN
FORCEINLINE BOOLEAN MiIsRosSectionObject(IN PSECTION Section)
Definition: miarm.h:1103
#define STATUS_SECTION_TOO_BIG
Definition: ntstatus.h:300
VOID NTAPI MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
Definition: virtual.c:2475
NTSTATUS NTAPI NtExtendSection(IN HANDLE SectionHandle, IN OUT PLARGE_INTEGER NewMaximumSize)
Definition: section.c:3894
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:48
static WCHAR Address[46]
Definition: ping.c:68
Entry
Definition: section.c:4944
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:476
#define MiProtoPteToPte(x)
Definition: mm.h:316
#define _In_
Definition: ms_sal.h:308
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
#define MM_EXECUTE_READ
Definition: miarm.h:46
#define PAGE_EXECUTE
Definition: nt_native.h:1306
PVOID Banked
Definition: mmtypes.h:777
ULONG MmSecondaryColorMask
Definition: mminit.c:257
union _MMVAD::@2566 u
union _SUBSECTION::@2561 u
return FALSE
Definition: section.c:5060
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1133
struct _SECTION * PSECTION
ULONG LongFlags
Definition: mmtypes.h:527
struct _SECTION SECTION
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:1023
#define MI_SET_USAGE(x)
Definition: mm.h:317
ULONG64 Protection
Definition: mmtypes.h:88
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSTATUS NTAPI MmMapViewOfSection(IN PVOID SectionObject, IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:3919
void * PVOID
Definition: retypes.h:9
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:93
PMMVIEW SystemSpaceViewTable
Definition: miarm.h:458
PVOID NTAPI MiInsertInSystemSpace(IN PMMSESSION Session, IN ULONG Buckets, IN PCONTROL_AREA ControlArea)
Definition: section.c:306
ULONG SystemSpaceHashKey
Definition: miarm.h:461
#define FILE_WRITE_DATA
Definition: nt_native.h:631
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
#define ULL(a, b)
Definition: format_msg.c:27
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
CHAR MmUserProtectionToMask2[16]
Definition: section.c:64
LIST_ENTRY DereferenceList
Definition: mmtypes.h:519
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:951
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER SectionOffset
Definition: mmfuncs.h:404
struct _MM_IMAGE_SECTION_OBJECT * PMM_IMAGE_SECTION_OBJECT
#define SECTION_MAP_WRITE
Definition: nt_native.h:1288
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
ULONG FileOffset
Definition: mmtypes.h:703
PMMPDE MmSystemPagePtes
Definition: init.c:41
#define STATUS_INVALID_PARAMETER_5
Definition: ntstatus.h:479
#define MEM_DOS_LIM
Definition: mmtypes.h:89
Status
Definition: gdiplustypes.h:24
NTSTATUS NTAPI MmGetFileNameForFileObject(IN PFILE_OBJECT FileObject, OUT POBJECT_NAME_INFORMATION *ModuleName)
Definition: section.c:1850
NTSTATUS NTAPI MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:4459
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:319
NTSTATUS NTAPI MiCheckSecuredVad(IN PMMVAD Vad, IN PVOID Base, IN SIZE_T Size, IN ULONG ProtectionMask)
Definition: vadnode.c:815
ULONG PageFrameNumber
Definition: mmtypes.h:74
int64_t LONGLONG
Definition: typedefs.h:68
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1174
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
NTSTATUS NTAPI MmUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress)
Definition: section.c:3130
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
int Count
Definition: noreturn.cpp:7
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG CurrentProcess
Definition: shell.c:125
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
ULONG_PTR PrivateMemory
Definition: mmtypes.h:695
NTSTATUS NTAPI MiInsertVadEx(_Inout_ PMMVAD Vad, _In_ ULONG_PTR *BaseAddress, _In_ SIZE_T ViewSize, _In_ ULONG_PTR HighestAddress, _In_ ULONG_PTR Alignment, _In_ ULONG AllocationType)
Definition: vadnode.c:204
ACCESS_MASK MmMakeSectionAccess[8]
Definition: section.c:20
NTSTATUS MiMapViewInSystemSpace(_In_ PVOID Section, _In_ PMMSESSION Session, _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, _Inout_ PSIZE_T ViewSize, _Inout_ PLARGE_INTEGER SectionOffset)
Definition: section.c:1058
#define MM_EXECUTE
Definition: miarm.h:45
SIZE_T CommittedPages
Definition: miarm.h:487
__wchar_t WCHAR
Definition: xmlstorage.h:180
NTSTATUS NTAPI MiUnmapViewInSystemSpace(IN PMMSESSION Session, IN PVOID MappedBase)
Definition: section.c:2452
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ WDFCOLLECTION _In_ ULONG Index
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
uint64_t ULONGLONG
Definition: typedefs.h:67
MMSESSION Session
Definition: miarm.h:502
NTSTATUS NTAPI MmCreateSection(OUT PVOID *Section, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: section.c:4522
static void Exit(void)
Definition: sock.c:1331
ACCESS_MASK NTAPI MiArm3GetCorrectFileAccessMask(IN ACCESS_MASK SectionPageProtection)
Definition: section.c:140
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:158
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:404
ULONG64 Valid
Definition: mmtypes.h:150
VOID NTAPI MiSegmentDelete(IN PSEGMENT Segment)
Definition: section.c:609
ULONG CheckSum
Definition: btrfs_drv.h:1886
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:502
#define ObDereferenceObject
Definition: obfuncs.h:203
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
PVOID MiSessionSpaceEnd
Definition: init.c:27
#define PAGE_ALIGN(Va)
#define STATUS_SECTION_PROTECTION
Definition: ntstatus.h:314
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2652
VOID NTAPI MiFillSystemPageDirectory(IN PVOID Base, IN SIZE_T NumberOfBytes)
Definition: section.c:480
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
MMVAD_FLAGS2 VadFlags2
Definition: mmtypes.h:768
#define SECTION_EXTEND_SIZE
Definition: nt_native.h:1291
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
ULONG NTAPI MmDoesFileHaveUserWritableReferences(IN PSECTION_OBJECT_POINTERS SectionPointer)
Definition: section.c:3365
#define STATUS_INVALID_FILE_FOR_SECTION
Definition: ntstatus.h:269
#define ProbeForReadLargeInteger(Ptr)
Definition: probe.h:75
POBJECT_TYPE MmSectionObjectType
Definition: section.c:195
#define FSRTL_FSP_TOP_LEVEL_IRP
Definition: fsrtltypes.h:59
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
struct _MMVIEW MMVIEW
* PFILE_OBJECT
Definition: iotypes.h:1998
BOOLEAN NTAPI MmIsAddressValid(IN PVOID VirtualAddress)
Definition: mmsup.c:174
LIST_ENTRY MmLoadedUserImageList
Definition: sysldr.c:35
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
struct _CONTROL_AREA CONTROL_AREA
struct _SUBSECTION * PSUBSECTION
NTSTATUS NTAPI MmMapViewInSystemSpace(IN PVOID SectionObject, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:4349
NTSTATUS NTAPI MmExtendSection(_In_ PVOID _Section, _Inout_ PLARGE_INTEGER NewSize)
Definition: section.c:5136
unsigned __int64 ULONG64
Definition: imports.h:198
#define BYTES_TO_PAGES(Size)
VOID NTAPI DbgkUnMapViewOfSection(IN PVOID BaseAddress)
Definition: dbgkutil.c:436
UNICODE_STRING SectionFileName
Definition: mmtypes.h:323
FORCEINLINE USHORT MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2486
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define STATUS_SECTION_NOT_IMAGE
Definition: ntstatus.h:309
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
VOID FASTCALL KeReleaseGuardedMutexUnsafe(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:75
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
PKGUARDED_MUTEX SystemSpaceViewLockPointer
Definition: miarm.h:456
MMSECTION_FLAGS Flags
Definition: mmtypes.h:814
#define InterlockedDecrement
Definition: armddk.h:52
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
PCONTROL_AREA ControlArea
Definition: miarm.h:450
NTSTATUS NTAPI MmCommitSessionMappedView(IN PVOID MappedBase, IN SIZE_T ViewSize)
Definition: section.c:3166
struct _SEGMENT SEGMENT
#define MM_GUARDPAGE
Definition: miarm.h:57
#define ProbeForWritePointer(Ptr)
Definition: probe.h:42
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
#define MI_MAX_ZERO_BITS
Definition: mm.h:83
#define FILE_EXECUTE
Definition: nt_native.h:642
#define SECTION_MAP_READ
Definition: compat.h:139
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
Definition: mm.h:373
ULONG GlobalOnlyPerSession
Definition: mmtypes.h:488
Definition: btrfs_drv.h:1876
ULONG LowPart
Definition: typedefs.h:106
BOOLEAN NTAPI MmForceSectionClosed(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN BOOLEAN DelayClose)
Definition: section.c:3055
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
ULONG64 Prototype
Definition: mmtypes.h:89
union _MMPFN::@1754 u3
ULONG MmCompatibleProtectionMask[8]
Definition: section.c:84
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:305
ULONG NumberOfMappedViews
Definition: mmtypes.h:522
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
VOID NTAPI MmGetImageInformation(OUT PSECTION_IMAGE_INFORMATION ImageInformation)
Definition: section.c:1829
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG AllocationType
Definition: mmfuncs.h:404
#define _64K
Definition: miarm.h:23
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
VOID NTAPI MiRemoveNode(IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table)
Definition: vadnode.c:360
MMPTE ValidKernelPdeLocal
Definition: init.c:32
KGUARDED_MUTEX MmSectionCommitMutex
Definition: section.c:108
ULONG Inherit
Definition: mmtypes.h:710
MMPTE ValidKernelPde
Definition: init.c:28
ULONG_PTR Long
Definition: mmtypes.h:215
#define MM_EXECUTE_READWRITE
Definition: miarm.h:49
LIST_ENTRY InLoadOrderLinks
Definition: ldrtypes.h:138
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:832
#define ALIGN_DOWN_BY(size, align)
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
VOID NTAPI MiDeleteVirtualAddresses(IN ULONG_PTR Va, IN ULONG_PTR EndingAddress, IN PMMVAD Vad)
Definition: virtual.c:530
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define STATUS_IMAGE_NOT_AT_BASE
Definition: ntstatus.h:117
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define SYSTEM_PD_SIZE
Definition: miarm.h:32
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1230
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:194
struct _FileName FileName
Definition: fatprocs.h:893
MMSUBSECTION_FLAGS SubsectionFlags
Definition: mmtypes.h:574
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:997
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1688
#define PAGE_WRITECOMBINE
Definition: mmtypes.h:78
#define STATUS_INVALID_VIEW_SIZE
Definition: ntstatus.h:268
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
PRTL_BITMAP SystemSpaceBitMap
Definition: miarm.h:463
#define InterlockedIncrement
Definition: armddk.h:53
FORCEINLINE PMMPDE MiPdeToPpe(PMMPDE PointerPde)
Definition: mm.h:292
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:306
PVOID MiSessionViewStart
Definition: init.c:30
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
PSUBSECTION NTAPI MiLocateSubsection(IN PMMVAD Vad, IN ULONG_PTR Vpn)
Definition: section.c:574
#define STATUS_INVALID_ADDRESS
Definition: ntstatus.h:557
ULONG FilePointerNull
Definition: mmtypes.h:479
NTSTATUS NTAPI MiGetFileObjectForSectionAddress(IN PVOID Address, OUT PFILE_OBJECT *FileObject)
Definition: section.c:1689
ULONG64 Transition
Definition: mmtypes.h:90
struct _MEMORY_AREA::@1751 SectionData
FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, IN PMMPTE PointerPte)
Definition: mm.h:342
union _SECTION::@2575 u
struct _MEMORY_SECTION_NAME MEMORY_SECTION_NAME