ReactOS  0.4.15-dev-2985-g54406bf
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);
918 
919  /* Remove the PTEs for this view, which also releases the working set lock */
921 
922  /* FIXME: Remove commitment */
923 
924  /* Update performance counter and release the lock */
925  Process->VirtualSize -= RegionSize;
926  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
927 
928  /* Destroy the VAD and return success */
929  ExFreePool(Vad);
931 
932  /* Failure and success case -- send debugger message, detach, and return */
933 Quickie:
934  if (DbgBase) DbgkUnMapViewOfSection(DbgBase);
936  return Status;
937 }
938 
939 NTSTATUS
940 NTAPI
942  IN PVOID EndVa)
943 {
944  KIRQL OldIrql;
945  ULONG Color, Index;
946  PMMPDE StartPde, EndPde;
948  PMMPFN Pfn1;
949  PFN_NUMBER PageCount = 0, ActualPages = 0, PageFrameNumber;
950 
951  /* Windows sanity checks */
952  ASSERT(StartVa >= (PVOID)MmSessionBase);
953  ASSERT(EndVa < (PVOID)MiSessionSpaceEnd);
954  ASSERT(PAGE_ALIGN(EndVa) == EndVa);
955 
956  /* Get the start and end PDE, then loop each one */
957  StartPde = MiAddressToPde(StartVa);
958  EndPde = MiAddressToPde((PVOID)((ULONG_PTR)EndVa - 1));
959  Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
960  while (StartPde <= EndPde)
961  {
962 #ifndef _M_AMD64
963  /* If we don't already have a page table for it, increment count */
964  if (MmSessionSpace->PageTables[Index].u.Long == 0) PageCount++;
965 #endif
966  /* Move to the next one */
967  StartPde++;
968  Index++;
969  }
970 
971  /* If there's no page tables to create, bail out */
972  if (PageCount == 0) return STATUS_SUCCESS;
973 
974  /* Reset the start PDE and index */
975  StartPde = MiAddressToPde(StartVa);
976  Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
977 
978  /* Loop each PDE while holding the working set lock */
979 // MiLockWorkingSet(PsGetCurrentThread(),
980 // &MmSessionSpace->GlobalVirtualAddress->Vm);
981 #ifdef _M_AMD64
982 _WARN("MiSessionCommitPageTables halfplemented for amd64")
987  DBG_UNREFERENCED_LOCAL_VARIABLE(PageFrameNumber);
988  ASSERT(FALSE);
989 #else
990  while (StartPde <= EndPde)
991  {
992  /* Check if we already have a page table */
993  if (MmSessionSpace->PageTables[Index].u.Long == 0)
994  {
995  /* We don't, so the PDE shouldn't be ready yet */
996  ASSERT(StartPde->u.Hard.Valid == 0);
997 
998  /* ReactOS check to avoid MiEnsureAvailablePageOrWait */
999  ASSERT(MmAvailablePages >= 32);
1000 
1001  /* Acquire the PFN lock and grab a zero page */
1002  OldIrql = MiAcquirePfnLock();
1004  MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
1006  PageFrameNumber = MiRemoveZeroPage(Color);
1007  TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
1008  MI_WRITE_VALID_PDE(StartPde, TempPde);
1009 
1010  /* Write the page table in session space structure */
1013 
1014  /* Initialize the PFN */
1015  MiInitializePfnForOtherProcess(PageFrameNumber,
1016  StartPde,
1018 
1019  /* And now release the lock */
1020  MiReleasePfnLock(OldIrql);
1021 
1022  /* Get the PFN entry and make sure there's no event for it */
1023  Pfn1 = MI_PFN_ELEMENT(PageFrameNumber);
1024  ASSERT(Pfn1->u1.Event == NULL);
1025 
1026  /* Increment the number of pages */
1027  ActualPages++;
1028  }
1029 
1030  /* Move to the next PDE */
1031  StartPde++;
1032  Index++;
1033  }
1034 #endif
1035 
1036  /* Make sure we didn't do more pages than expected */
1037  ASSERT(ActualPages <= PageCount);
1038 
1039  /* Release the working set lock */
1040 // MiUnlockWorkingSet(PsGetCurrentThread(),
1041 // &MmSessionSpace->GlobalVirtualAddress->Vm);
1042 
1043 
1044  /* If we did at least one page... */
1045  if (ActualPages)
1046  {
1047  /* Update the performance counters! */
1050  }
1051 
1052  /* Return status */
1053  return STATUS_SUCCESS;
1054 }
1055 
1056 NTSTATUS
1058  _In_ PVOID Section,
1063 {
1064  PVOID Base;
1065  PCONTROL_AREA ControlArea;
1066  ULONG Buckets;
1067  LONGLONG SectionSize;
1068  NTSTATUS Status;
1069  PAGED_CODE();
1070 
1071  /* Get the control area, check for any flags ARM3 doesn't yet support */
1072  ControlArea = ((PSECTION)Section)->Segment->ControlArea;
1073  ASSERT(ControlArea->u.Flags.Image == 0);
1074  ASSERT(ControlArea->FilePointer == NULL);
1075  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
1076  ASSERT(ControlArea->u.Flags.Rom == 0);
1077  ASSERT(ControlArea->u.Flags.WasPurged == 0);
1078 
1079  /* Increase the reference and map count on the control area, no purges yet */
1080  Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
1082 
1083  /* Get the section size at creation time */
1084  SectionSize = ((PSECTION)Section)->SizeOfSection.QuadPart;
1085 
1086  /* If the caller didn't specify a view size, assume until the end of the section */
1087  if (!(*ViewSize))
1088  {
1089  /* Check for overflow first */
1090  if ((SectionSize - SectionOffset->QuadPart) > SIZE_T_MAX)
1091  {
1092  DPRINT1("Section end is too far away from the specified offset.\n");
1093  MiDereferenceControlArea(ControlArea);
1094  return STATUS_INVALID_VIEW_SIZE;
1095  }
1096  *ViewSize = SectionSize - SectionOffset->QuadPart;
1097  }
1098 
1099  /* Check overflow */
1100  if ((SectionOffset->QuadPart + *ViewSize) < SectionOffset->QuadPart)
1101  {
1102  DPRINT1("Integer overflow between size & offset!\n");
1103  MiDereferenceControlArea(ControlArea);
1104  return STATUS_INVALID_VIEW_SIZE;
1105  }
1106 
1107  /* Check if the caller wanted a larger section than the view */
1108  if (SectionOffset->QuadPart + *ViewSize > SectionSize)
1109  {
1110  /* Fail */
1111  DPRINT1("View is too large\n");
1112  MiDereferenceControlArea(ControlArea);
1113  return STATUS_INVALID_VIEW_SIZE;
1114  }
1115 
1116  /* Get the number of 64K buckets required for this mapping */
1117  Buckets = (ULONG)(*ViewSize / MI_SYSTEM_VIEW_BUCKET_SIZE);
1118  if (*ViewSize & (MI_SYSTEM_VIEW_BUCKET_SIZE - 1)) Buckets++;
1119 
1120  /* Check if the view is more than 4GB large */
1121  if (Buckets >= MI_SYSTEM_VIEW_BUCKET_SIZE)
1122  {
1123  /* Fail */
1124  DPRINT1("View is too large\n");
1125  MiDereferenceControlArea(ControlArea);
1126  return STATUS_INVALID_VIEW_SIZE;
1127  }
1128 
1129  /* Insert this view into system space and get a base address for it */
1130  Base = MiInsertInSystemSpace(Session, Buckets, ControlArea);
1131  if (!Base)
1132  {
1133  /* Fail */
1134  DPRINT1("Out of system space\n");
1135  MiDereferenceControlArea(ControlArea);
1136  return STATUS_NO_MEMORY;
1137  }
1138 
1139  /* What's the underlying session? */
1140  if (Session == &MmSession)
1141  {
1142  /* Create the PDEs needed for this mapping, and double-map them if needed */
1145  }
1146  else
1147  {
1148  /* Create the PDEs needed for this mapping */
1150  (PVOID)((ULONG_PTR)Base +
1151  Buckets * MI_SYSTEM_VIEW_BUCKET_SIZE));
1153  }
1154 
1155  /* Create the actual prototype PTEs for this mapping */
1158  ControlArea,
1159  SectionOffset->QuadPart);
1161 
1162  /* Return the base adress of the mapping and success */
1163  *MappedBase = Base;
1164  return STATUS_SUCCESS;
1165 }
1166 
1167 VOID
1168 NTAPI
1170 {
1171  KIRQL OldIrql;
1172 
1174 
1175  OldIrql = MiAcquirePfnLock();
1176  ControlArea->u.Flags.DebugSymbolsLoaded |= 1;
1177 
1178  ASSERT(OldIrql <= APC_LEVEL);
1179  MiReleasePfnLock(OldIrql);
1181 }
1182 
1183 VOID
1184 NTAPI
1188 {
1189  NTSTATUS Status;
1191  PLIST_ENTRY NextEntry;
1193  PIMAGE_NT_HEADERS NtHeaders;
1194  PLDR_DATA_TABLE_ENTRY LdrEntry;
1195 
1196  FileName = &ControlArea->FilePointer->FileName;
1197  if (FileName->Length == 0)
1198  {
1199  return;
1200  }
1201 
1202  /* Acquire module list lock */
1205 
1206  /* Browse list to try to find current module */
1207  for (NextEntry = MmLoadedUserImageList.Flink;
1208  NextEntry != &MmLoadedUserImageList;
1209  NextEntry = NextEntry->Flink)
1210  {
1211  /* Get the entry */
1212  LdrEntry = CONTAINING_RECORD(NextEntry,
1214  InLoadOrderLinks);
1215 
1216  /* If already in the list, increase load count */
1217  if (LdrEntry->DllBase == BaseAddress)
1218  {
1219  ++LdrEntry->LoadCount;
1220  break;
1221  }
1222  }
1223 
1224  /* Not in the list, we'll add it */
1225  if (NextEntry == &MmLoadedUserImageList)
1226  {
1227  /* Allocate our element, taking to the name string and its null char */
1228  LdrEntry = ExAllocatePoolWithTag(NonPagedPool, FileName->Length + sizeof(UNICODE_NULL) + sizeof(*LdrEntry), 'bDmM');
1229  if (LdrEntry)
1230  {
1231  memset(LdrEntry, 0, FileName->Length + sizeof(UNICODE_NULL) + sizeof(*LdrEntry));
1232 
1233  _SEH2_TRY
1234  {
1235  /* Get image checksum and size */
1236  NtHeaders = RtlImageNtHeader(BaseAddress);
1237  if (NtHeaders)
1238  {
1239  LdrEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage;
1240  LdrEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum;
1241  }
1242  }
1244  {
1245  ExFreePoolWithTag(LdrEntry, 'bDmM');
1248  _SEH2_YIELD(return);
1249  }
1250  _SEH2_END;
1251 
1252  /* Fill all the details */
1253  LdrEntry->DllBase = BaseAddress;
1254  LdrEntry->FullDllName.Buffer = (PVOID)((ULONG_PTR)LdrEntry + sizeof(*LdrEntry));
1255  LdrEntry->FullDllName.Length = FileName->Length;
1256  LdrEntry->FullDllName.MaximumLength = FileName->Length + sizeof(UNICODE_NULL);
1257  memcpy(LdrEntry->FullDllName.Buffer, FileName->Buffer, FileName->Length);
1258  LdrEntry->FullDllName.Buffer[LdrEntry->FullDllName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1259  LdrEntry->LoadCount = 1;
1260 
1261  /* Insert! */
1263  }
1264  }
1265 
1266  /* Release locks */
1269 
1270  /* Load symbols */
1272  if (NT_SUCCESS(Status))
1273  {
1276  }
1277 }
1278 
1279 NTSTATUS
1280 NTAPI
1283  IN PVOID *BaseAddress,
1286  IN PSECTION Section,
1288  IN ULONG ProtectionMask,
1292 {
1293  PMMVAD_LONG Vad;
1294  ULONG_PTR StartAddress;
1295  ULONG_PTR ViewSizeInPages;
1296  PSUBSECTION Subsection;
1297  PSEGMENT Segment;
1298  PFN_NUMBER PteOffset;
1299  NTSTATUS Status;
1300  ULONG QuotaCharge = 0, QuotaExcess = 0;
1301  PMMPTE PointerPte, LastPte;
1302  MMPTE TempPte;
1303  ULONG Granularity = MM_VIRTMEM_GRANULARITY;
1304 
1305  DPRINT("Mapping ARM3 data section\n");
1306 
1307  /* Get the segment for this section */
1308  Segment = ControlArea->Segment;
1309 
1310 #ifdef _M_IX86
1311  /* ALlow being less restrictive on x86. */
1313  Granularity = PAGE_SIZE;
1314 #endif
1315 
1316  /* One can only reserve a file-based mapping, not shared memory! */
1317  if ((AllocationType & MEM_RESERVE) && !(ControlArea->FilePointer))
1318  {
1320  }
1321 
1322  /* First, increase the map count. No purging is supported yet */
1323  Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
1324  if (!NT_SUCCESS(Status)) return Status;
1325 
1326  /* Check if the caller specified the view size */
1327  if (!(*ViewSize))
1328  {
1329  LONGLONG ViewSizeLL;
1330 
1331  /* The caller did not, so pick a 64K aligned view size based on the offset */
1332  SectionOffset->LowPart &= ~(_64K - 1);
1333 
1334  /* Calculate size and make sure this fits */
1335  if (!NT_SUCCESS(RtlLongLongSub(Section->SizeOfSection.QuadPart, SectionOffset->QuadPart, &ViewSizeLL))
1336  || !NT_SUCCESS(RtlLongLongToSIZET(ViewSizeLL, ViewSize))
1337  || (*ViewSize > MAXLONG_PTR))
1338  {
1339  MiDereferenceControlArea(ControlArea);
1340  return STATUS_INVALID_VIEW_SIZE;
1341  }
1342  }
1343  else
1344  {
1345  /* A size was specified, align it to a 64K boundary
1346  * and check for overflow or huge value. */
1347  if (!NT_SUCCESS(RtlSIZETAdd(*ViewSize, SectionOffset->LowPart & (_64K - 1), ViewSize))
1348  || (*ViewSize > MAXLONG_PTR))
1349  {
1350  MiDereferenceControlArea(ControlArea);
1351  return STATUS_INVALID_VIEW_SIZE;
1352  }
1353 
1354  /* Align the offset as well to make this an aligned map */
1355  SectionOffset->LowPart &= ~((ULONG)_64K - 1);
1356  }
1357 
1358  /* We must be dealing with a 64KB aligned offset. This is a Windows ASSERT */
1359  ASSERT((SectionOffset->LowPart & ((ULONG)_64K - 1)) == 0);
1360 
1361  /* Windows ASSERTs for this flag */
1362  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
1363 
1364  /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
1365  ASSERT(ControlArea->u.Flags.Rom == 0);
1366  Subsection = (PSUBSECTION)(ControlArea + 1);
1367 
1368  /* Sections with extended segments are not supported in ARM3 */
1369  ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0);
1370 
1371  /* Within this section, figure out which PTEs will describe the view */
1372  PteOffset = (PFN_NUMBER)(SectionOffset->QuadPart >> PAGE_SHIFT);
1373 
1374  /* The offset must be in this segment's PTE chunk and it must be valid. Windows ASSERTs */
1375  ASSERT(PteOffset < Segment->TotalNumberOfPtes);
1376  ASSERT(((SectionOffset->QuadPart + *ViewSize + PAGE_SIZE - 1) >> PAGE_SHIFT) >= PteOffset);
1377 
1378  /* In ARM3, only one subsection is used for now. It must contain these PTEs */
1379  ASSERT(PteOffset < Subsection->PtesInSubsection);
1380 
1381  /* In ARM3, only page-file backed sections (shared memory) are supported now */
1382  ASSERT(ControlArea->FilePointer == NULL);
1383 
1384  /* Windows ASSERTs for this too -- there must be a subsection base address */
1385  ASSERT(Subsection->SubsectionBase != NULL);
1386 
1387  /* Compute how much commit space the segment will take */
1388  if ((CommitSize) && (Segment->NumberOfCommittedPages < Segment->TotalNumberOfPtes))
1389  {
1390  /* Charge for the maximum pages */
1391  QuotaCharge = BYTES_TO_PAGES(CommitSize);
1392  }
1393 
1394  /* ARM3 does not currently support large pages */
1395  ASSERT(Segment->SegmentFlags.LargePages == 0);
1396 
1397  /* Calculate how many pages the region spans */
1398  ViewSizeInPages = BYTES_TO_PAGES(*ViewSize);
1399 
1400  /* A VAD can now be allocated. Do so and zero it out */
1401  /* FIXME: we are allocating a LONG VAD for ReactOS compatibility only */
1402  ASSERT((AllocationType & MEM_RESERVE) == 0); /* ARM3 does not support this */
1403  Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
1404  if (!Vad)
1405  {
1406  MiDereferenceControlArea(ControlArea);
1408  }
1409 
1410  RtlZeroMemory(Vad, sizeof(MMVAD_LONG));
1411  Vad->u4.Banked = (PVOID)(ULONG_PTR)0xDEADBABEDEADBABEULL;
1412 
1413  /* Write all the data required in the VAD for handling a fault */
1414  Vad->ControlArea = ControlArea;
1415  Vad->u.VadFlags.CommitCharge = 0;
1416  Vad->u.VadFlags.Protection = ProtectionMask;
1417  Vad->u2.VadFlags2.FileOffset = (ULONG)(SectionOffset->QuadPart >> 16);
1419  if ((AllocationType & SEC_NO_CHANGE) || (Section->u.Flags.NoChange))
1420  {
1421  /* This isn't really implemented yet, but handle setting the flag */
1422  Vad->u.VadFlags.NoChange = 1;
1423  Vad->u2.VadFlags2.SecNoChange = 1;
1424  }
1425 
1426  /* Finally, write down the first and last prototype PTE */
1427  Vad->FirstPrototypePte = &Subsection->SubsectionBase[PteOffset];
1428  PteOffset += ViewSizeInPages - 1;
1429  ASSERT(PteOffset < Subsection->PtesInSubsection);
1430  Vad->LastContiguousPte = &Subsection->SubsectionBase[PteOffset];
1431 
1432  /* Make sure the prototype PTE ranges make sense, this is a Windows ASSERT */
1434 
1435  /* FIXME: Should setup VAD bitmap */
1437 
1438  /* Check if anything was committed */
1439  if (QuotaCharge)
1440  {
1441  /* Set the start and end PTE addresses, and pick the template PTE */
1442  PointerPte = Vad->FirstPrototypePte;
1443  LastPte = PointerPte + BYTES_TO_PAGES(CommitSize);
1444  TempPte = Segment->SegmentPteTemplate;
1445 
1446  /* Acquire the commit lock and loop all prototype PTEs to be committed */
1448  while (PointerPte < LastPte)
1449  {
1450  /* Make sure the PTE is already invalid */
1451  if (PointerPte->u.Long == 0)
1452  {
1453  /* And write the invalid PTE */
1454  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
1455  }
1456  else
1457  {
1458  /* The PTE is valid, so skip it */
1459  QuotaExcess++;
1460  }
1461 
1462  /* Move to the next PTE */
1463  PointerPte++;
1464  }
1465 
1466  /* Now check how many pages exactly we committed, and update accounting */
1467  ASSERT(QuotaCharge >= QuotaExcess);
1468  QuotaCharge -= QuotaExcess;
1469  Segment->NumberOfCommittedPages += QuotaCharge;
1470  ASSERT(Segment->NumberOfCommittedPages <= Segment->TotalNumberOfPtes);
1471 
1472  /* Now that we're done, release the lock */
1474  }
1475 
1476  /* Is it SEC_BASED, or did the caller manually specify an address? */
1477  if (*BaseAddress != NULL)
1478  {
1479  /* Just align what the caller gave us */
1480  StartAddress = ALIGN_DOWN_BY((ULONG_PTR)*BaseAddress, Granularity);
1481  }
1482  else if (Section->Address.StartingVpn != 0)
1483  {
1484  /* It is a SEC_BASED mapping, use the address that was generated */
1485  StartAddress = Section->Address.StartingVpn + SectionOffset->LowPart;
1486  }
1487  else
1488  {
1489  StartAddress = 0;
1490  }
1491 
1492  /* Insert the VAD */
1493  Status = MiInsertVadEx((PMMVAD)Vad,
1494  &StartAddress,
1495  ViewSizeInPages * PAGE_SIZE,
1497  Granularity,
1498  AllocationType);
1499  if (!NT_SUCCESS(Status))
1500  {
1501  return Status;
1502  }
1503 
1504  /* Windows stores this for accounting purposes, do so as well */
1505  if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
1506 
1507  /* Finally, let the caller know where, and for what size, the view was mapped */
1508  *ViewSize = ViewSizeInPages * PAGE_SIZE;
1509  *BaseAddress = (PVOID)StartAddress;
1510  DPRINT("Start and region: 0x%p, 0x%p\n", *BaseAddress, *ViewSize);
1511  return STATUS_SUCCESS;
1512 }
1513 
1514 VOID
1515 NTAPI
1517 {
1518  /* ReactOS only supports systems with 4K pages and 4K sectors */
1519  ASSERT(Subsection->u.SubsectionFlags.SectorEndOffset == 0);
1520 
1521  /* Therefore, then number of PTEs should be equal to the number of sectors */
1522  if (Subsection->NumberOfFullSectors != Subsection->PtesInSubsection)
1523  {
1524  /* Break and warn if this is inconsistent */
1525  DPRINT1("Mm: Subsection inconsistent (%x vs %x)\n",
1526  Subsection->NumberOfFullSectors, Subsection->PtesInSubsection);
1527  DbgBreakPoint();
1528  }
1529 }
1530 
1531 NTSTATUS
1532 NTAPI
1534  OUT PSEGMENT *Segment,
1538  IN ULONG IgnoreFileSizing)
1539 {
1540  /* Not yet implemented */
1541  ASSERT(FALSE);
1542  *Segment = NULL;
1543  return STATUS_NOT_IMPLEMENTED;
1544 }
1545 
1546 static
1547 NTSTATUS
1548 NTAPI
1551  IN ULONG ProtectionMask,
1553 {
1554  ULONGLONG SizeLimit;
1555  PFN_COUNT PteCount;
1556  PMMPTE PointerPte;
1557  MMPTE TempPte;
1558  PCONTROL_AREA ControlArea;
1559  PSEGMENT NewSegment;
1560  PSUBSECTION Subsection;
1561  PAGED_CODE();
1562 
1563  /* No large pages in ARM3 yet */
1565 
1566  /* Pagefile-backed sections need a known size */
1567  if (!MaximumSize || !MaximumSize->QuadPart || MaximumSize->QuadPart < 0)
1569 
1570  /* Calculate the maximum size possible, given the Prototype PTEs we'll need */
1571  SizeLimit = MmSizeOfPagedPoolInBytes - sizeof(SEGMENT);
1572  SizeLimit /= sizeof(MMPTE);
1573  SizeLimit <<= PAGE_SHIFT;
1574 
1575  /* Fail if this size is too big */
1576  if (MaximumSize->QuadPart > SizeLimit)
1577  {
1578  return STATUS_SECTION_TOO_BIG;
1579  }
1580 
1581  /* Calculate how many Prototype PTEs will be needed */
1582  PteCount = (PFN_COUNT)((MaximumSize->QuadPart + PAGE_SIZE - 1) >> PAGE_SHIFT);
1583 
1584  /* For commited memory, we must have a valid protection mask */
1585  if (AllocationAttributes & SEC_COMMIT) ASSERT(ProtectionMask != 0);
1586 
1587  /* The segment contains all the Prototype PTEs, allocate it in paged pool */
1588  NewSegment = ExAllocatePoolWithTag(PagedPool,
1589  sizeof(SEGMENT) +
1590  sizeof(MMPTE) * (PteCount - 1),
1591  'tSmM');
1592  if (!NewSegment)
1593  {
1595  }
1596  *Segment = NewSegment;
1597 
1598  /* Now allocate the control area, which has the subsection structure */
1599  ControlArea = ExAllocatePoolWithTag(NonPagedPool,
1600  sizeof(CONTROL_AREA) + sizeof(SUBSECTION),
1601  'tCmM');
1602  if (!ControlArea)
1603  {
1604  ExFreePoolWithTag(Segment, 'tSmM');
1606  }
1607 
1608  /* And zero it out, filling the basic segmnet pointer and reference fields */
1609  RtlZeroMemory(ControlArea, sizeof(CONTROL_AREA) + sizeof(SUBSECTION));
1610  ControlArea->Segment = NewSegment;
1611  ControlArea->NumberOfSectionReferences = 1;
1612  ControlArea->NumberOfUserReferences = 1;
1613 
1614  /* Convert allocation attributes to control area flags */
1615  if (AllocationAttributes & SEC_BASED) ControlArea->u.Flags.Based = 1;
1616  if (AllocationAttributes & SEC_RESERVE) ControlArea->u.Flags.Reserve = 1;
1617  if (AllocationAttributes & SEC_COMMIT) ControlArea->u.Flags.Commit = 1;
1618 
1619  /* We just allocated it */
1620  ControlArea->u.Flags.BeingCreated = 1;
1621 
1622  /* The subsection follows, write the mask, PTE count and point back to the CA */
1623  Subsection = (PSUBSECTION)(ControlArea + 1);
1624  Subsection->ControlArea = ControlArea;
1625  Subsection->PtesInSubsection = PteCount;
1626  Subsection->u.SubsectionFlags.Protection = ProtectionMask;
1627 
1628  /* Zero out the segment's prototype PTEs, and link it with the control area */
1629  PointerPte = &NewSegment->ThePtes[0];
1630  RtlZeroMemory(NewSegment, sizeof(SEGMENT));
1631  NewSegment->PrototypePte = PointerPte;
1632  NewSegment->ControlArea = ControlArea;
1633 
1634  /* Save some extra accounting data for the segment as well */
1635  NewSegment->u1.CreatingProcess = PsGetCurrentProcess();
1636  NewSegment->SizeOfSegment = ((ULONGLONG)PteCount) * PAGE_SIZE;
1637  NewSegment->TotalNumberOfPtes = PteCount;
1638  NewSegment->NonExtendedPtes = PteCount;
1639 
1640  /* The subsection's base address is the first Prototype PTE in the segment */
1641  Subsection->SubsectionBase = PointerPte;
1642 
1643  /* Start with an empty PTE, unless this is a commit operation */
1644  TempPte.u.Long = 0;
1646  {
1647  /* In which case, write down the protection mask in the Prototype PTEs */
1648  TempPte.u.Soft.Protection = ProtectionMask;
1649 
1650  /* For accounting, also mark these pages as being committed */
1651  NewSegment->NumberOfCommittedPages = PteCount;
1652  }
1653 
1654  /* The template PTE itself for the segment should also have the mask set */
1655  NewSegment->SegmentPteTemplate.u.Soft.Protection = ProtectionMask;
1656 
1657  /* Write out the prototype PTEs, for now they're simply demand zero */
1658 #ifdef _WIN64
1659  RtlFillMemoryUlonglong(PointerPte, PteCount * sizeof(MMPTE), TempPte.u.Long);
1660 #else
1661  RtlFillMemoryUlong(PointerPte, PteCount * sizeof(MMPTE), TempPte.u.Long);
1662 #endif
1663  return STATUS_SUCCESS;
1664 }
1665 
1666 NTSTATUS
1667 NTAPI
1669  IN PVOID Address,
1671 {
1672  PMMVAD Vad;
1673  PCONTROL_AREA ControlArea;
1674 
1675  /* Get the VAD */
1676  Vad = MiLocateAddress(Address);
1677  if (Vad == NULL)
1678  {
1679  /* Fail, the address does not exist */
1680  DPRINT1("Invalid address\n");
1681  return STATUS_INVALID_ADDRESS;
1682  }
1683 
1684  /* Check if this is a RosMm memory area */
1685  if (Vad->u.VadFlags.Spare != 0)
1686  {
1688 
1689  /* Check if it's a section view (RosMm section) */
1691  {
1692  /* Get the section pointer to the SECTION_OBJECT */
1693  *FileObject = MemoryArea->SectionData.Segment->FileObject;
1694  }
1695  else
1696  {
1697 #ifdef NEWCC
1698  ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
1699  DPRINT1("Address is a cache section!\n");
1700  return STATUS_SECTION_NOT_IMAGE;
1701 #else
1702  ASSERT(FALSE);
1703  return STATUS_SECTION_NOT_IMAGE;
1704 #endif
1705  }
1706  }
1707  else
1708  {
1709  /* Make sure it's not a VM VAD */
1710  if (Vad->u.VadFlags.PrivateMemory == 1)
1711  {
1712  DPRINT1("Address is not a section\n");
1713  return STATUS_SECTION_NOT_IMAGE;
1714  }
1715 
1716  /* Get the control area */
1717  ControlArea = Vad->ControlArea;
1718  if (!(ControlArea) || !(ControlArea->u.Flags.Image))
1719  {
1720  DPRINT1("Address is not a section\n");
1721  return STATUS_SECTION_NOT_IMAGE;
1722  }
1723 
1724  /* Get the file object */
1725  *FileObject = ControlArea->FilePointer;
1726  }
1727 
1728  /* Return success */
1729  return STATUS_SUCCESS;
1730 }
1731 
1733 NTAPI
1735 {
1736  PSECTION Section = SectionObject;
1739 
1740  /* Check if it's an ARM3, or ReactOS section */
1742  {
1743  /* Return the file pointer stored in the control area */
1744  return Section->Segment->ControlArea->FilePointer;
1745  }
1746 
1747  /* Return the file object */
1748  return ((PMM_SECTION_SEGMENT)Section->Segment)->FileObject;
1749 }
1750 
1751 static
1754  _In_ PMMVAD Vad)
1755 {
1756  PCONTROL_AREA ControlArea;
1758 
1759  /* Check if this is a RosMm memory area */
1760  if (Vad->u.VadFlags.Spare != 0)
1761  {
1763 
1764  /* Check if it's a section view (RosMm section) */
1766  {
1767  /* Get the section pointer to the SECTION_OBJECT */
1768  FileObject = MemoryArea->SectionData.Segment->FileObject;
1769  }
1770  else
1771  {
1772 #ifdef NEWCC
1773  ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
1774  DPRINT1("VAD is a cache section!\n");
1775 #else
1776  ASSERT(FALSE);
1777 #endif
1778  return NULL;
1779  }
1780  }
1781  else
1782  {
1783  /* Make sure it's not a VM VAD */
1784  if (Vad->u.VadFlags.PrivateMemory == 1)
1785  {
1786  DPRINT1("VAD is not a section\n");
1787  return NULL;
1788  }
1789 
1790  /* Get the control area */
1791  ControlArea = Vad->ControlArea;
1792  if ((ControlArea == NULL) || !ControlArea->u.Flags.Image)
1793  {
1794  DPRINT1("Address is not a section\n");
1795  return NULL;
1796  }
1797 
1798  /* Get the file object */
1799  FileObject = ControlArea->FilePointer;
1800  }
1801 
1802  /* Return the file object */
1803  return FileObject;
1804 }
1805 
1806 VOID
1807 NTAPI
1809 {
1811 
1812  /* Get the section object of this process*/
1813  SectionObject = PsGetCurrentProcess()->SectionObject;
1816 
1817  if (SectionObject->u.Flags.Image == 0)
1818  {
1819  RtlZeroMemory(ImageInformation, sizeof(*ImageInformation));
1820  return;
1821  }
1822 
1823  /* Return the image information */
1824  *ImageInformation = ((PMM_IMAGE_SECTION_OBJECT)SectionObject->Segment)->ImageInformation;
1825 }
1826 
1827 NTSTATUS
1828 NTAPI
1831 {
1832  POBJECT_NAME_INFORMATION ObjectNameInfo;
1833  NTSTATUS Status;
1835 
1836  /* Allocate memory for our structure */
1837  ObjectNameInfo = ExAllocatePoolWithTag(PagedPool, 1024, TAG_MM);
1838  if (!ObjectNameInfo) return STATUS_NO_MEMORY;
1839 
1840  /* Query the name */
1842  ObjectNameInfo,
1843  1024,
1844  &ReturnLength);
1845  if (!NT_SUCCESS(Status))
1846  {
1847  /* Failed, free memory */
1848  DPRINT1("Name query failed\n");
1849  ExFreePoolWithTag(ObjectNameInfo, TAG_MM);
1850  *ModuleName = NULL;
1851  return Status;
1852  }
1853 
1854  /* Success */
1855  *ModuleName = ObjectNameInfo;
1856  return STATUS_SUCCESS;
1857 }
1858 
1859 NTSTATUS
1860 NTAPI
1863 {
1865  PSECTION SectionObject = Section;
1866 
1867  /* Make sure it's an image section */
1868  if (SectionObject->u.Flags.Image == 0)
1869  {
1870  /* It's not, fail */
1871  DPRINT1("Not an image section\n");
1872  return STATUS_SECTION_NOT_IMAGE;
1873  }
1874 
1875  /* Get the file object */
1878 }
1879 
1880 NTSTATUS
1881 NTAPI
1884 {
1885  POBJECT_NAME_INFORMATION ModuleNameInformation;
1887  NTSTATUS Status;
1888  PMMVAD Vad;
1890 
1891  /* Lock address space */
1894 
1895  /* Get the VAD */
1896  Vad = MiLocateAddress(Address);
1897  if (Vad == NULL)
1898  {
1899  /* Fail, the address does not exist */
1900  DPRINT1("No VAD at address %p\n", Address);
1902  return STATUS_INVALID_ADDRESS;
1903  }
1904 
1905  /* Get the file object pointer for the VAD */
1907  if (FileObject == NULL)
1908  {
1909  DPRINT1("Failed to get file object for Address %p\n", Address);
1911  return STATUS_SECTION_NOT_IMAGE;
1912  }
1913 
1914  /* Reference the file object */
1916 
1917  /* Unlock address space */
1919 
1920  /* Get the filename of the file object */
1921  Status = MmGetFileNameForFileObject(FileObject, &ModuleNameInformation);
1922 
1923  /* Dereference the file object */
1925 
1926  /* Check if we were able to get the file object name */
1927  if (NT_SUCCESS(Status))
1928  {
1929  /* Init modulename */
1930  if (!RtlCreateUnicodeString(ModuleName, ModuleNameInformation->Name.Buffer))
1932 
1933  /* Free temp taged buffer from MmGetFileNameForFileObject() */
1934  ExFreePoolWithTag(ModuleNameInformation, TAG_MM);
1935 
1936  DPRINT("Found ModuleName %wZ by address %p\n", ModuleName, Address);
1937  }
1938 
1939  /* Return status */
1940  return Status;
1941 }
1942 
1943 NTSTATUS
1944 NTAPI
1947  OUT PVOID MemoryInformation,
1948  IN SIZE_T MemoryInformationLength,
1950 {
1952  NTSTATUS Status;
1954  PMEMORY_SECTION_NAME SectionName = NULL;
1956 
1959  NULL,
1960  PreviousMode,
1961  (PVOID*)(&Process),
1962  NULL);
1963 
1964  if (!NT_SUCCESS(Status))
1965  {
1966  DPRINT("MiQueryMemorySectionName: ObReferenceObjectByHandle returned %x\n",Status);
1967  return Status;
1968  }
1969 
1971 
1972  if (NT_SUCCESS(Status))
1973  {
1974  SectionName = MemoryInformation;
1975  if (PreviousMode != KernelMode)
1976  {
1977  _SEH2_TRY
1978  {
1979  RtlInitEmptyUnicodeString(&SectionName->SectionFileName,
1980  (PWSTR)(SectionName + 1),
1981  MemoryInformationLength - sizeof(MEMORY_SECTION_NAME));
1983 
1985 
1986  }
1988  {
1990  }
1991  _SEH2_END;
1992  }
1993  else
1994  {
1995  RtlInitEmptyUnicodeString(&SectionName->SectionFileName,
1996  (PWSTR)(SectionName + 1),
1997  MemoryInformationLength - sizeof(MEMORY_SECTION_NAME));
1999 
2001 
2002  }
2003 
2005  }
2007  return Status;
2008 }
2009 
2010 VOID
2011 NTAPI
2013  IN PMMPTE PointerPte,
2014  IN ULONG ProtectionMask,
2015  IN PMMPFN Pfn1,
2016  IN BOOLEAN UpdateDirty)
2017 {
2018  MMPTE TempPte, PreviousPte;
2019  KIRQL OldIrql;
2020  BOOLEAN RebuildPte = FALSE;
2021 
2022  //
2023  // User for sanity checking later on
2024  //
2025  PreviousPte = *PointerPte;
2026 
2027  //
2028  // Build the PTE and acquire the PFN lock
2029  //
2031  PointerPte,
2032  ProtectionMask,
2033  PreviousPte.u.Hard.PageFrameNumber);
2034  OldIrql = MiAcquirePfnLock();
2035 
2036  //
2037  // We don't support I/O mappings in this path yet
2038  //
2039  ASSERT(Pfn1 != NULL);
2040  ASSERT(Pfn1->u3.e1.CacheAttribute != MiWriteCombined);
2041 
2042  //
2043  // Make sure new protection mask doesn't get in conflict and fix it if it does
2044  //
2045  if (Pfn1->u3.e1.CacheAttribute == MiCached)
2046  {
2047  //
2048  // This is a cached PFN
2049  //
2050  if (ProtectionMask & (MM_NOCACHE | MM_NOACCESS))
2051  {
2052  RebuildPte = TRUE;
2053  ProtectionMask &= ~(MM_NOCACHE | MM_NOACCESS);
2054  }
2055  }
2056  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
2057  {
2058  //
2059  // This is a non-cached PFN
2060  //
2061  if ((ProtectionMask & (MM_NOCACHE | MM_NOACCESS)) != MM_NOCACHE)
2062  {
2063  RebuildPte = TRUE;
2064  ProtectionMask &= ~MM_NOACCESS;
2065  ProtectionMask |= MM_NOCACHE;
2066  }
2067  }
2068 
2069  if (RebuildPte)
2070  {
2072  PointerPte,
2073  ProtectionMask,
2074  PreviousPte.u.Hard.PageFrameNumber);
2075  }
2076 
2077  //
2078  // Write the new PTE, making sure we are only changing the bits
2079  //
2080  MI_UPDATE_VALID_PTE(PointerPte, TempPte);
2081 
2082  //
2083  // Flush the TLB
2084  //
2085  ASSERT(PreviousPte.u.Hard.Valid == 1);
2086  KeFlushCurrentTb();
2087  ASSERT(PreviousPte.u.Hard.Valid == 1);
2088 
2089  //
2090  // Windows updates the relevant PFN1 information, we currently don't.
2091  //
2092  if (UpdateDirty && PreviousPte.u.Hard.Dirty)
2093  {
2094  if (!Pfn1->u3.e1.Modified)
2095  {
2096  DPRINT1("FIXME: Mark PFN as dirty\n");
2097  }
2098  }
2099 
2100  //
2101  // Not supported in ARM3
2102  //
2103  ASSERT(FoundVad->u.VadFlags.VadType != VadWriteWatch);
2104 
2105  //
2106  // Release the PFN lock, we are done
2107  //
2108  MiReleasePfnLock(OldIrql);
2109 }
2110 
2111 //
2112 // NOTE: This function gets a lot more complicated if we want Copy-on-Write support
2113 //
2114 NTSTATUS
2115 NTAPI
2117  IN PMMVAD FoundVad,
2118  IN PVOID StartingAddress,
2119  IN PVOID EndingAddress,
2121  OUT PULONG CapturedOldProtect,
2122  IN ULONG DontCharge,
2123  OUT PULONG Locked)
2124 {
2125  PMMPTE PointerPte, LastPte;
2126  MMPTE TempPte, PteContents;
2127  PMMPDE PointerPde;
2128  PMMPFN Pfn1;
2129  ULONG ProtectionMask, QuotaCharge = 0;
2131  PAGED_CODE();
2132 
2133  //
2134  // Tell caller nothing is being locked
2135  //
2136  *Locked = FALSE;
2137 
2138  //
2139  // This function should only be used for section VADs. Windows ASSERT */
2140  //
2141  ASSERT(FoundVad->u.VadFlags.PrivateMemory == 0);
2142 
2143  //
2144  // We don't support these features in ARM3
2145  //
2146  ASSERT(FoundVad->u.VadFlags.VadType != VadImageMap);
2147  ASSERT(FoundVad->u2.VadFlags2.CopyOnWrite == 0);
2148 
2149  //
2150  // Convert and validate the protection mask
2151  //
2152  ProtectionMask = MiMakeProtectionMask(NewProtect);
2153  if (ProtectionMask == MM_INVALID_PROTECTION)
2154  {
2155  DPRINT1("Invalid section protect\n");
2157  }
2158 
2159  //
2160  // Get the PTE and PDE for the address, as well as the final PTE
2161  //
2163  PointerPde = MiAddressToPde(StartingAddress);
2164  PointerPte = MiAddressToPte(StartingAddress);
2165  LastPte = MiAddressToPte(EndingAddress);
2166 
2167  //
2168  // Make the PDE valid, and check the status of the first PTE
2169  //
2171  if (PointerPte->u.Long)
2172  {
2173  //
2174  // Not supported in ARM3
2175  //
2176  ASSERT(FoundVad->u.VadFlags.VadType != VadRotatePhysical);
2177 
2178  //
2179  // Capture the page protection and make the PDE valid
2180  //
2181  *CapturedOldProtect = MiGetPageProtection(PointerPte);
2183  }
2184  else
2185  {
2186  //
2187  // Only pagefile-backed section VADs are supported for now
2188  //
2189  ASSERT(FoundVad->u.VadFlags.VadType != VadImageMap);
2190 
2191  //
2192  // Grab the old protection from the VAD itself
2193  //
2194  *CapturedOldProtect = MmProtectToValue[FoundVad->u.VadFlags.Protection];
2195  }
2196 
2197  //
2198  // Loop all the PTEs now
2199  //
2201  while (PointerPte <= LastPte)
2202  {
2203  //
2204  // Check if we've crossed a PDE boundary and make the new PDE valid too
2205  //
2206  if (MiIsPteOnPdeBoundary(PointerPte))
2207  {
2208  PointerPde = MiPteToPde(PointerPte);
2210  }
2211 
2212  //
2213  // Capture the PTE and see what we're dealing with
2214  //
2215  PteContents = *PointerPte;
2216  if (PteContents.u.Long == 0)
2217  {
2218  //
2219  // This used to be a zero PTE and it no longer is, so we must add a
2220  // reference to the pagetable.
2221  //
2223 
2224  //
2225  // Create the demand-zero prototype PTE
2226  //
2228  TempPte.u.Soft.Protection = ProtectionMask;
2229  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2230  }
2231  else if (PteContents.u.Hard.Valid == 1)
2232  {
2233  //
2234  // Get the PFN entry
2235  //
2236  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2237 
2238  //
2239  // We don't support these yet
2240  //
2241  ASSERT((NewProtect & (PAGE_NOACCESS | PAGE_GUARD)) == 0);
2242  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
2243 
2244  //
2245  // Write the protection mask and write it with a TLB flush
2246  //
2247  Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
2248  MiFlushTbAndCapture(FoundVad,
2249  PointerPte,
2250  ProtectionMask,
2251  Pfn1,
2252  TRUE);
2253  }
2254  else
2255  {
2256  //
2257  // We don't support these cases yet
2258  //
2259  ASSERT(PteContents.u.Soft.Prototype == 0);
2260  ASSERT(PteContents.u.Soft.Transition == 0);
2261 
2262  //
2263  // The PTE is already demand-zero, just update the protection mask
2264  //
2265  PointerPte->u.Soft.Protection = ProtectionMask;
2266  }
2267 
2268  PointerPte++;
2269  }
2270 
2271  //
2272  // Unlock the working set and update quota charges if needed, then return
2273  //
2275  if ((QuotaCharge > 0) && (!DontCharge))
2276  {
2277  FoundVad->u.VadFlags.CommitCharge -= QuotaCharge;
2278  Process->CommitCharge -= QuotaCharge;
2279  }
2280  return STATUS_SUCCESS;
2281 }
2282 
2283 VOID
2284 NTAPI
2286  IN ULONG NumberOfPtes,
2287  IN PCONTROL_AREA ControlArea,
2288  IN PMMSUPPORT Ws)
2289 {
2290  PMMPTE PointerPte, ProtoPte;//, FirstPte;
2291  PMMPDE PointerPde, SystemMapPde;
2292  PMMPFN Pfn1, Pfn2;
2293  MMPTE PteContents;
2294  KIRQL OldIrql;
2295  DPRINT("Removing mapped view at: 0x%p\n", BaseAddress);
2296 
2297  ASSERT(Ws == NULL);
2298 
2299  /* Get the PTE and loop each one */
2300  PointerPte = MiAddressToPte(BaseAddress);
2301  //FirstPte = PointerPte;
2302  while (NumberOfPtes)
2303  {
2304  /* Check if the PTE is already valid */
2305  PteContents = *PointerPte;
2306  if (PteContents.u.Hard.Valid == 1)
2307  {
2308  /* Get the PFN entry */
2309  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2310 
2311  /* Get the PTE */
2312  PointerPde = MiPteToPde(PointerPte);
2313 
2314  /* Lock the PFN database and make sure this isn't a mapped file */
2315  OldIrql = MiAcquirePfnLock();
2316  ASSERT(((Pfn1->u3.e1.PrototypePte) && (Pfn1->OriginalPte.u.Soft.Prototype)) == 0);
2317 
2318  /* Mark the page as modified accordingly */
2319  if (MI_IS_PAGE_DIRTY(&PteContents))
2320  Pfn1->u3.e1.Modified = 1;
2321 
2322  /* Was the PDE invalid */
2323  if (PointerPde->u.Long == 0)
2324  {
2325 #if (_MI_PAGING_LEVELS == 2)
2326  /* Find the system double-mapped PDE that describes this mapping */
2327  SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
2328 
2329  /* Make it valid */
2330  ASSERT(SystemMapPde->u.Hard.Valid == 1);
2331  MI_WRITE_VALID_PDE(PointerPde, *SystemMapPde);
2332 #else
2333  DBG_UNREFERENCED_LOCAL_VARIABLE(SystemMapPde);
2334  ASSERT(FALSE);
2335 #endif
2336  }
2337 
2338  /* Dereference the PDE and the PTE */
2339  Pfn2 = MiGetPfnEntry(PFN_FROM_PTE(PointerPde));
2340  MiDecrementShareCount(Pfn2, PFN_FROM_PTE(PointerPde));
2342  MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
2343 
2344  /* Release the PFN lock */
2345  MiReleasePfnLock(OldIrql);
2346  }
2347  else
2348  {
2349  /* Windows ASSERT */
2350  ASSERT((PteContents.u.Long == 0) || (PteContents.u.Soft.Prototype == 1));
2351 
2352  /* Check if this is a prototype pointer PTE */
2353  if (PteContents.u.Soft.Prototype == 1)
2354  {
2355  /* Get the prototype PTE */
2356  ProtoPte = MiProtoPteToPte(&PteContents);
2357 
2358  /* We don't support anything else atm */
2359  ASSERT(ProtoPte->u.Long == 0);
2360  }
2361  }
2362 
2363  /* Make the PTE into a zero PTE */
2364  PointerPte->u.Long = 0;
2365 
2366  /* Move to the next PTE */
2367  PointerPte++;
2368  NumberOfPtes--;
2369  }
2370 
2371  /* Flush the TLB */
2372  KeFlushCurrentTb();
2373 
2374  /* Acquire the PFN lock */
2375  OldIrql = MiAcquirePfnLock();
2376 
2377  /* Decrement the accounting counters */
2378  ControlArea->NumberOfUserReferences--;
2379  ControlArea->NumberOfMappedViews--;
2380 
2381  /* Check if we should destroy the CA and release the lock */
2382  MiCheckControlArea(ControlArea, OldIrql);
2383 }
2384 
2385 ULONG
2386 NTAPI
2388  IN PVOID Base,
2389  OUT PCONTROL_AREA *ControlArea)
2390 {
2391  ULONG Hash, Size, Count = 0;
2392  ULONG_PTR Entry;
2393  PAGED_CODE();
2394 
2395  /* Compute the hash for this entry and loop trying to find it */
2396  Entry = (ULONG_PTR)Base >> 16;
2398  while ((Session->SystemSpaceViewTable[Hash].Entry >> 16) != Entry)
2399  {
2400  /* Check if we overflew past the end of the hash table */
2401  if (++Hash >= Session->SystemSpaceHashSize)
2402  {
2403  /* Reset the hash to zero and keep searching from the bottom */
2404  Hash = 0;
2405  if (++Count == 2)
2406  {
2407  /* But if we overflew twice, then this is not a real mapping */
2408  KeBugCheckEx(DRIVER_UNMAPPING_INVALID_VIEW,
2409  (ULONG_PTR)Base,
2410  1,
2411  0,
2412  0);
2413  }
2414  }
2415  }
2416 
2417  /* One less entry */
2419 
2420  /* Extract the size and clear the entry */
2423 
2424  /* Return the control area and the size */
2425  *ControlArea = Session->SystemSpaceViewTable[Hash].ControlArea;
2426  return Size;
2427 }
2428 
2429 NTSTATUS
2430 NTAPI
2433 {
2434  ULONG Size;
2435  PCONTROL_AREA ControlArea;
2436  PAGED_CODE();
2437 
2438  /* Remove this mapping */
2440  Size = MiRemoveFromSystemSpace(Session, MappedBase, &ControlArea);
2441 
2442  /* Clear the bits for this mapping */
2445  Size);
2446 
2447  /* Convert the size from a bit size into the actual size */
2448  Size = Size * (_64K >> PAGE_SHIFT);
2449 
2450  /* Remove the PTEs now */
2451  MiRemoveMappedPtes(MappedBase, Size, ControlArea, NULL);
2453 
2454  /* Return success */
2455  return STATUS_SUCCESS;
2456 }
2457 
2458 /* PUBLIC FUNCTIONS ***********************************************************/
2459 
2460 /*
2461  * @implemented
2462  */
2463 NTSTATUS
2464 NTAPI
2468  IN PLARGE_INTEGER InputMaximumSize,
2473 {
2474  SECTION Section;
2475  PSECTION NewSection;
2476  PSUBSECTION Subsection;
2477  PSEGMENT NewSegment, Segment;
2478  NTSTATUS Status;
2479  PCONTROL_AREA ControlArea;
2480  ULONG ProtectionMask, ControlAreaSize, Size, NonPagedCharge, PagedCharge;
2482  BOOLEAN FileLock = FALSE, KernelCall = FALSE;
2483  KIRQL OldIrql;
2485  BOOLEAN UserRefIncremented = FALSE;
2486  PVOID PreviousSectionPointer;
2487 
2488  /* Make the same sanity checks that the Nt interface should've validated */
2491  SEC_NO_CHANGE)) == 0);
2495  SEC_NOCACHE | SEC_NO_CHANGE))));
2501 
2502  /* Convert section flag to page flag */
2504 
2505  /* Check to make sure the protection is correct. Nt* does this already */
2506  ProtectionMask = MiMakeProtectionMask(SectionPageProtection);
2507  if (ProtectionMask == MM_INVALID_PROTECTION) return STATUS_INVALID_PAGE_PROTECTION;
2508 
2509  /* Check if this is going to be a data or image backed file section */
2510  if ((FileHandle) || (FileObject))
2511  {
2512  /* These cannot be mapped with large pages */
2514 
2515  /* For now, only support the mechanism through a file handle */
2516  ASSERT(FileObject == NULL);
2517 
2518  /* Reference the file handle to get the object */
2520  MmMakeFileAccess[ProtectionMask],
2522  PreviousMode,
2523  (PVOID*)&File,
2524  NULL);
2525  if (!NT_SUCCESS(Status)) return Status;
2526 
2527  /* Make sure Cc has been doing its job */
2528  if (!File->SectionObjectPointer)
2529  {
2530  /* This is not a valid file system-based file, fail */
2533  }
2534 
2535  /* Image-file backed sections are not yet supported */
2537 
2538  /* Compute the size of the control area, and allocate it */
2539  ControlAreaSize = sizeof(CONTROL_AREA) + sizeof(MSUBSECTION);
2540  ControlArea = ExAllocatePoolWithTag(NonPagedPool, ControlAreaSize, 'aCmM');
2541  if (!ControlArea)
2542  {
2545  }
2546 
2547  /* Zero it out */
2548  RtlZeroMemory(ControlArea, ControlAreaSize);
2549 
2550  /* Did we get a handle, or an object? */
2551  if (FileHandle)
2552  {
2553  /* We got a file handle so we have to lock down the file */
2554 #if 0
2556  if (!NT_SUCCESS(Status))
2557  {
2558  ExFreePool(ControlArea);
2560  return Status;
2561  }
2562 #else
2563  /* ReactOS doesn't support this API yet, so do nothing */
2565 #endif
2566  /* Update the top-level IRP so that drivers know what's happening */
2568  FileLock = TRUE;
2569  }
2570 
2571  /* Lock the PFN database while we play with the section pointers */
2572  OldIrql = MiAcquirePfnLock();
2573 
2574  /* Image-file backed sections are not yet supported */
2576 
2577  /* There should not already be a control area for this file */
2578  ASSERT(File->SectionObjectPointer->DataSectionObject == NULL);
2579  NewSegment = NULL;
2580 
2581  /* Write down that this CA is being created, and set it */
2582  ControlArea->u.Flags.BeingCreated = TRUE;
2584  PreviousSectionPointer = File->SectionObjectPointer;
2585  File->SectionObjectPointer->DataSectionObject = ControlArea;
2586 
2587  /* We can release the PFN lock now */
2588  MiReleasePfnLock(OldIrql);
2589 
2590  /* We don't support previously-mapped file */
2591  ASSERT(NewSegment == NULL);
2592 
2593  /* Image-file backed sections are not yet supported */
2595 
2596  /* So we always create a data file map */
2598  &Segment,
2599  (PSIZE_T)InputMaximumSize,
2602  KernelCall);
2603  if (!NT_SUCCESS(Status))
2604  {
2605  /* Lock the PFN database while we play with the section pointers */
2606  OldIrql = MiAcquirePfnLock();
2607 
2608  /* Reset the waiting-for-deletion event */
2609  ASSERT(ControlArea->WaitingForDeletion == NULL);
2610  ControlArea->WaitingForDeletion = NULL;
2611 
2612  /* Set the file pointer NULL flag */
2613  ASSERT(ControlArea->u.Flags.FilePointerNull == 0);
2614  ControlArea->u.Flags.FilePointerNull = TRUE;
2615 
2616  /* Delete the data section object */
2618  File->SectionObjectPointer->DataSectionObject = NULL;
2619 
2620  /* No longer being created */
2621  ControlArea->u.Flags.BeingCreated = FALSE;
2622 
2623  /* We can release the PFN lock now */
2624  MiReleasePfnLock(OldIrql);
2625 
2626  /* Check if we locked and set the IRP */
2627  if (FileLock)
2628  {
2629  /* Undo */
2631  //FsRtlReleaseFile(File);
2632  }
2633 
2634  /* Free the control area and de-ref the file object */
2635  ExFreePool(ControlArea);
2637 
2638  /* All done */
2639  return Status;
2640  }
2641 
2642  /* On success, we expect this */
2643  ASSERT(PreviousSectionPointer == File->SectionObjectPointer);
2644 
2645  /* Check if a maximum size was specified */
2646  if (!InputMaximumSize->QuadPart)
2647  {
2648  /* Nope, use the segment size */
2649  Section.SizeOfSection.QuadPart = (LONGLONG)Segment->SizeOfSegment;
2650  }
2651  else
2652  {
2653  /* Yep, use the entered size */
2654  Section.SizeOfSection.QuadPart = InputMaximumSize->QuadPart;
2655  }
2656  }
2657  else
2658  {
2659  /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
2661 
2662  /* Not yet supported */
2664 
2665  /* So this must be a pagefile-backed section, create the mappings needed */
2666  Status = MiCreatePagingFileMap(&NewSegment,
2667  InputMaximumSize,
2668  ProtectionMask,
2670  if (!NT_SUCCESS(Status)) return Status;
2671 
2672  /* Set the size here, and read the control area */
2673  Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
2674  ControlArea = NewSegment->ControlArea;
2675 
2676  /* MiCreatePagingFileMap increments user references */
2677  UserRefIncremented = TRUE;
2678  }
2679 
2680  /* Did we already have a segment? */
2681  if (!NewSegment)
2682  {
2683  /* This must be the file path and we created a segment */
2684  NewSegment = Segment;
2685  ASSERT(File != NULL);
2686 
2687  /* Acquire the PFN lock while we set control area flags */
2688  OldIrql = MiAcquirePfnLock();
2689 
2690  /* We don't support this race condition yet, so assume no waiters */
2691  ASSERT(ControlArea->WaitingForDeletion == NULL);
2692  ControlArea->WaitingForDeletion = NULL;
2693 
2694  /* Image-file backed sections are not yet supported, nor ROM images */
2696  ASSERT(Segment->ControlArea->u.Flags.Rom == 0);
2697 
2698  /* Take off the being created flag, and then release the lock */
2699  ControlArea->u.Flags.BeingCreated = FALSE;
2700  MiReleasePfnLock(OldIrql);
2701  }
2702 
2703  /* Check if we locked the file earlier */
2704  if (FileLock)
2705  {
2706  /* Reset the top-level IRP and release the lock */
2708  //FsRtlReleaseFile(File);
2709  FileLock = FALSE;
2710  }
2711 
2712  /* Set the initial section object data */
2713  Section.InitialPageProtection = SectionPageProtection;
2714 
2715  /* The mapping created a control area and segment, save the flags */
2716  Section.Segment = NewSegment;
2717  Section.u.LongFlags = ControlArea->u.LongFlags;
2718 
2719  /* Check if this is a user-mode read-write non-image file mapping */
2720  if (!(FileObject) &&
2722  !(ControlArea->u.Flags.Image) &&
2723  (ControlArea->FilePointer))
2724  {
2725  /* Add a reference and set the flag */
2726  Section.u.Flags.UserWritable = TRUE;
2727  InterlockedIncrement((volatile LONG*)&ControlArea->WritableUserReferences);
2728  }
2729 
2730  /* Check for image mappings or page file mappings */
2731  if ((ControlArea->u.Flags.Image) || !(ControlArea->FilePointer))
2732  {
2733  /* Charge the segment size, and allocate a subsection */
2734  PagedCharge = sizeof(SECTION) + NewSegment->TotalNumberOfPtes * sizeof(MMPTE);
2735  Size = sizeof(SUBSECTION);
2736  }
2737  else
2738  {
2739  /* Charge nothing, and allocate a mapped subsection */
2740  PagedCharge = 0;
2741  Size = sizeof(MSUBSECTION);
2742  }
2743 
2744  /* Check if this is a normal CA */
2745  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
2746  ASSERT(ControlArea->u.Flags.Rom == 0);
2747 
2748  /* Charge only a CA, and the subsection is right after */
2749  NonPagedCharge = sizeof(CONTROL_AREA);
2750  Subsection = (PSUBSECTION)(ControlArea + 1);
2751 
2752  /* We only support single-subsection mappings */
2753  NonPagedCharge += Size;
2754  ASSERT(Subsection->NextSubsection == NULL);
2755 
2756  /* Create the actual section object, with enough space for the prototype PTEs */
2760  PreviousMode,
2761  NULL,
2762  sizeof(SECTION),
2763  PagedCharge,
2764  NonPagedCharge,
2765  (PVOID*)&NewSection);
2766  if (!NT_SUCCESS(Status))
2767  {
2768  /* Check if this is a user-mode read-write non-image file mapping */
2769  if (!(FileObject) &&
2771  !(ControlArea->u.Flags.Image) &&
2772  (ControlArea->FilePointer))
2773  {
2774  /* Remove a reference and check the flag */
2775  ASSERT(Section.u.Flags.UserWritable == 1);
2776  InterlockedDecrement((volatile LONG*)&ControlArea->WritableUserReferences);
2777  }
2778 
2779  /* Check if a user reference was added */
2780  if (UserRefIncremented)
2781  {
2782  /* Acquire the PFN lock while we change counters */
2783  OldIrql = MiAcquirePfnLock();
2784 
2785  /* Decrement the accounting counters */
2786  ControlArea->NumberOfSectionReferences--;
2787  ASSERT((LONG)ControlArea->NumberOfUserReferences > 0);
2788  ControlArea->NumberOfUserReferences--;
2789 
2790  /* Check if we should destroy the CA and release the lock */
2791  MiCheckControlArea(ControlArea, OldIrql);
2792  }
2793 
2794  /* Return the failure code */
2795  return Status;
2796  }
2797 
2798  /* NOTE: Past this point, all failures will be handled by Ob upon ref->0 */
2799 
2800  /* Now copy the local section object from the stack into this new object */
2801  RtlCopyMemory(NewSection, &Section, sizeof(SECTION));
2802  NewSection->Address.StartingVpn = 0;
2803 
2804  /* For now, only user calls are supported */
2805  ASSERT(KernelCall == FALSE);
2806  NewSection->u.Flags.UserReference = TRUE;
2807 
2808  /* Is this a "based" allocation, in which all mappings are identical? */
2810  {
2811  /* Lock the VAD tree during the search */
2813 
2814  /* Is it a brand new ControArea ? */
2815  if (ControlArea->u.Flags.BeingCreated == 1)
2816  {
2817  ASSERT(ControlArea->u.Flags.Based == 1);
2818  /* Then we must find a global address, top-down */
2821  _64K,
2823  (ULONG_PTR*)&ControlArea->Segment->BasedAddress);
2824 
2825  if (!NT_SUCCESS(Status))
2826  {
2827  /* No way to find a valid range. */
2829  ControlArea->u.Flags.Based = 0;
2830  NewSection->u.Flags.Based = 0;
2831  ObDereferenceObject(NewSection);
2832  return Status;
2833  }
2834 
2835  /* Compute the ending address and insert it into the VAD tree */
2836  NewSection->Address.StartingVpn = (ULONG_PTR)ControlArea->Segment->BasedAddress;
2837  NewSection->Address.EndingVpn = NewSection->Address.StartingVpn + NewSection->SizeOfSection.LowPart - 1;
2838  MiInsertBasedSection(NewSection);
2839  }
2840  else
2841  {
2842  /* 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 !*/
2843  ASSERT(FALSE);
2844  }
2845 
2847  }
2848 
2849  /* The control area is not being created anymore */
2850  if (ControlArea->u.Flags.BeingCreated == 1)
2851  {
2852  /* Acquire the PFN lock while we set control area flags */
2853  OldIrql = MiAcquirePfnLock();
2854 
2855  /* Take off the being created flag, and then release the lock */
2856  ControlArea->u.Flags.BeingCreated = 0;
2857  NewSection->u.Flags.BeingCreated = 0;
2858 
2859  MiReleasePfnLock(OldIrql);
2860  }
2861 
2862  /* Migrate the attribute into a flag */
2863  if (AllocationAttributes & SEC_NO_CHANGE) NewSection->u.Flags.NoChange = TRUE;
2864 
2865  /* If R/W access is not requested, this might eventually become a CoW mapping */
2867  {
2868  NewSection->u.Flags.CopyOnWrite = TRUE;
2869  }
2870 
2871  /* Write down if this was a kernel call */
2872  ControlArea->u.Flags.WasPurged |= KernelCall;
2873  ASSERT(ControlArea->u.Flags.WasPurged == FALSE);
2874 
2875  /* Make sure the segment and the section are the same size, or the section is smaller */
2876  ASSERT((ULONG64)NewSection->SizeOfSection.QuadPart <= NewSection->Segment->SizeOfSegment);
2877 
2878  /* Return the object and the creation status */
2879  *SectionObject = (PVOID)NewSection;
2880  return Status;
2881 }
2882 
2883 /*
2884  * @implemented
2885  */
2886 NTSTATUS
2887 NTAPI
2897  IN ULONG Protect)
2898 {
2901  PSECTION Section;
2902  PCONTROL_AREA ControlArea;
2903  ULONG ProtectionMask;
2904  NTSTATUS Status;
2905  ULONG64 CalculatedViewSize;
2906  PAGED_CODE();
2907 
2908  /* Get the segment and control area */
2909  Section = (PSECTION)SectionObject;
2910  ControlArea = Section->Segment->ControlArea;
2911 
2912  /* These flags/states are not yet supported by ARM3 */
2913  ASSERT(Section->u.Flags.Image == 0);
2914  ASSERT(Section->u.Flags.NoCache == 0);
2915  ASSERT(Section->u.Flags.WriteCombined == 0);
2916  ASSERT(ControlArea->u.Flags.PhysicalMemory == 0);
2917 
2918  /* FIXME */
2919  if ((AllocationType & MEM_RESERVE) != 0)
2920  {
2921  DPRINT1("MmMapViewOfArm3Section called with MEM_RESERVE, this is not implemented yet!!!\n");
2922  return STATUS_NOT_IMPLEMENTED;
2923  }
2924 
2925  /* Check if the mapping protection is compatible with the create */
2927  {
2928  DPRINT1("Mapping protection is incompatible\n");
2930  }
2931 
2932  /* Check if the offset and size would cause an overflow */
2933  if (((ULONG64)SectionOffset->QuadPart + *ViewSize) <
2934  (ULONG64)SectionOffset->QuadPart)
2935  {
2936  DPRINT1("Section offset overflows\n");
2937  return STATUS_INVALID_VIEW_SIZE;
2938  }
2939 
2940  /* Check if the offset and size are bigger than the section itself */
2941  if (((ULONG64)SectionOffset->QuadPart + *ViewSize) >
2942  (ULONG64)Section->SizeOfSection.QuadPart)
2943  {
2944  DPRINT1("Section offset is larger than section\n");
2945  return STATUS_INVALID_VIEW_SIZE;
2946  }
2947 
2948  /* Check if the caller did not specify a view size */
2949  if (!(*ViewSize))
2950  {
2951  /* Compute it for the caller */
2952  CalculatedViewSize = Section->SizeOfSection.QuadPart -
2953  SectionOffset->QuadPart;
2954 
2955  /* Check if it's larger than 4GB or overflows into kernel-mode */
2956  if (!NT_SUCCESS(RtlULongLongToSIZET(CalculatedViewSize, ViewSize)) ||
2957  (((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)*BaseAddress) < CalculatedViewSize))
2958  {
2959  DPRINT1("Section view won't fit\n");
2960  return STATUS_INVALID_VIEW_SIZE;
2961  }
2962  }
2963 
2964  /* Check if the commit size is larger than the view size */
2965  if (CommitSize > *ViewSize)
2966  {
2967  DPRINT1("Attempting to commit more than the view itself\n");
2969  }
2970 
2971  /* Check if the view size is larger than the section */
2972  if (*ViewSize > (ULONG64)Section->SizeOfSection.QuadPart)
2973  {
2974  DPRINT1("The view is larger than the section\n");
2975  return STATUS_INVALID_VIEW_SIZE;
2976  }
2977 
2978  /* Compute and validate the protection mask */
2979  ProtectionMask = MiMakeProtectionMask(Protect);
2980  if (ProtectionMask == MM_INVALID_PROTECTION)
2981  {
2982  DPRINT1("The protection is invalid\n");
2984  }
2985 
2986  /* We only handle pagefile-backed sections, which cannot be writecombined */
2987  if (Protect & PAGE_WRITECOMBINE)
2988  {
2989  DPRINT1("Cannot write combine a pagefile-backed section\n");
2991  }
2992 
2993  /* Start by attaching to the current process if needed */
2994  if (PsGetCurrentProcess() != Process)
2995  {
2997  Attached = TRUE;
2998  }
2999 
3000  /* Do the actual mapping */
3001  Status = MiMapViewOfDataSection(ControlArea,
3002  Process,
3003  BaseAddress,
3004  SectionOffset,
3005  ViewSize,
3006  Section,
3008  ProtectionMask,
3009  CommitSize,
3010  ZeroBits,
3011  AllocationType);
3012 
3013  /* Detach if needed, then return status */
3015  return Status;
3016 }
3017 
3018 /*
3019  * @unimplemented
3020  */
3021 BOOLEAN
3022 NTAPI
3024 {
3025  UNIMPLEMENTED;
3026  return FALSE;
3027 }
3028 
3029 /*
3030  * @unimplemented
3031  */
3032 BOOLEAN
3033 NTAPI
3036 {
3037  UNIMPLEMENTED;
3038  return FALSE;
3039 }
3040 
3041 /*
3042  * @implemented
3043  */
3044 NTSTATUS
3045 NTAPI
3047  OUT PVOID *MappedBase,
3049 {
3050  PAGED_CODE();
3052 
3053  // HACK
3054  if (MiIsRosSectionObject(Section))
3055  {
3056  return MmMapViewInSystemSpace(Section, MappedBase, ViewSize);
3057  }
3058 
3059  /* Process must be in a session */
3060  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3061  {
3062  DPRINT1("Process is not in session\n");
3063  return STATUS_NOT_MAPPED_VIEW;
3064  }
3065 
3066  /* Use the system space API, but with the session view instead */
3068  SectionOffset.QuadPart = 0;
3069  return MiMapViewInSystemSpace(Section,
3071  MappedBase,
3072  ViewSize,
3073  &SectionOffset);
3074 }
3075 
3076 /*
3077  * @implemented
3078  */
3079 NTSTATUS
3080 NTAPI
3082 {
3083  PAGED_CODE();
3084 
3085  // HACK
3087  {
3089  }
3090 
3091  /* Process must be in a session */
3092  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3093  {
3094  DPRINT1("Proess is not in session\n");
3095  return STATUS_NOT_MAPPED_VIEW;
3096  }
3097 
3098  /* Use the system space API, but with the session view instead */
3101  MappedBase);
3102 }
3103 
3104 /*
3105  * @implemented
3106  */
3107 NTSTATUS
3108 NTAPI
3111 {
3113 }
3114 
3115 /*
3116  * @implemented
3117  */
3118 NTSTATUS
3119 NTAPI
3121 {
3123  PAGED_CODE();
3124 
3125  /* Was this mapped by RosMm? */
3129  {
3132  return Status;
3133  }
3135 
3136  /* It was not, call the ARM3 routine */
3138 }
3139 
3140 /*
3141  * @implemented
3142  */
3143 NTSTATUS
3144 NTAPI
3146  IN SIZE_T ViewSize)
3147 {
3148  ULONG_PTR StartAddress, EndingAddress, Base;
3149  ULONG Hash, Count = 0, Size, QuotaCharge;
3151  PMMPTE LastProtoPte, PointerPte, ProtoPte;
3152  PCONTROL_AREA ControlArea;
3153  PSEGMENT Segment;
3154  PSUBSECTION Subsection;
3155  MMPTE TempPte;
3156  PAGED_CODE();
3157 
3158  /* Make sure the base isn't past the session view range */
3159  if ((MappedBase < MiSessionViewStart) ||
3161  {
3162  DPRINT1("Base outside of valid range\n");
3164  }
3165 
3166  /* Make sure the size isn't past the session view range */
3169  {
3170  DPRINT1("Size outside of valid range\n");
3172  }
3173 
3174  /* Sanity check */
3175  ASSERT(ViewSize != 0);
3176 
3177  /* Process must be in a session */
3178  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3179  {
3180  DPRINT1("Process is not in session\n");
3181  return STATUS_NOT_MAPPED_VIEW;
3182  }
3183 
3184  /* Compute the correctly aligned base and end addresses */
3185  StartAddress = (ULONG_PTR)PAGE_ALIGN(MappedBase);
3186  EndingAddress = ((ULONG_PTR)MappedBase + ViewSize - 1) | (PAGE_SIZE - 1);
3187 
3188  /* Sanity check and grab the session */
3191 
3192  /* Get the hash entry for this allocation */
3193  Hash = (StartAddress >> 16) % Session->SystemSpaceHashKey;
3194 
3195  /* Lock system space */
3197 
3198  /* Loop twice so we can try rolling over if needed */
3199  while (TRUE)
3200  {
3201  /* Extract the size and base addresses from the entry */
3202  Base = Session->SystemSpaceViewTable[Hash].Entry & ~0xFFFF;
3204 
3205  /* Convert the size to bucket chunks */
3207 
3208  /* Bail out if this entry fits in here */
3209  if ((StartAddress >= Base) && (EndingAddress < (Base + Size))) break;
3210 
3211  /* Check if we overflew past the end of the hash table */
3212  if (++Hash >= Session->SystemSpaceHashSize)
3213  {
3214  /* Reset the hash to zero and keep searching from the bottom */
3215  Hash = 0;
3216  if (++Count == 2)
3217  {
3218  /* But if we overflew twice, then this is not a real mapping */
3219  KeBugCheckEx(DRIVER_UNMAPPING_INVALID_VIEW,
3220  Base,
3221  2,
3222  0,
3223  0);
3224  }
3225  }
3226  }
3227 
3228  /* Make sure the view being mapped is not file-based */
3229  ControlArea = Session->SystemSpaceViewTable[Hash].ControlArea;
3230  if (ControlArea->FilePointer != NULL)
3231  {
3232  /* It is, so we have to bail out */
3233  DPRINT1("Only page-filed backed sections can be commited\n");
3235  return STATUS_ALREADY_COMMITTED;
3236  }
3237 
3238  /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
3239  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
3240  ASSERT(ControlArea->u.Flags.Rom == 0);
3241  Subsection = (PSUBSECTION)(ControlArea + 1);
3242 
3243  /* Get the start and end PTEs -- make sure the end PTE isn't past the end */
3244  ProtoPte = Subsection->SubsectionBase + ((StartAddress - Base) >> PAGE_SHIFT);
3245  QuotaCharge = MiAddressToPte(EndingAddress) - MiAddressToPte(StartAddress) + 1;
3246  LastProtoPte = ProtoPte + QuotaCharge;
3247  if (LastProtoPte >= Subsection->SubsectionBase + Subsection->PtesInSubsection)
3248  {
3249  DPRINT1("PTE is out of bounds\n");
3252  }
3253 
3254  /* Acquire the commit lock and count all the non-committed PTEs */
3256  PointerPte = ProtoPte;
3257  while (PointerPte < LastProtoPte)
3258  {
3259  if (PointerPte->u.Long) QuotaCharge--;
3260  PointerPte++;
3261  }
3262 
3263  /* Was everything committed already? */
3264  if (!QuotaCharge)
3265  {
3266  /* Nothing to do! */
3269  return STATUS_SUCCESS;
3270  }
3271 
3272  /* Pick the segment and template PTE */
3273  Segment = ControlArea->Segment;
3274  TempPte = Segment->SegmentPteTemplate;
3275  ASSERT(TempPte.u.Long != 0);
3276 
3277  /* Loop all prototype PTEs to be committed */
3278  PointerPte = ProtoPte;
3279  while (PointerPte < LastProtoPte)
3280  {
3281  /* Make sure the PTE is already invalid */
3282  if (PointerPte->u.Long == 0)
3283  {
3284  /* And write the invalid PTE */
3285  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
3286  }
3287 
3288  /* Move to the next PTE */
3289  PointerPte++;
3290  }
3291 
3292  /* Check if we had at least one page charged */
3293  if (QuotaCharge)
3294  {
3295  /* Update the accounting data */
3296  Segment->NumberOfCommittedPages += QuotaCharge;
3298  }
3299 
3300  /* Release all */
3303  return STATUS_SUCCESS;
3304 }
3305 
3306 VOID
3307 NTAPI
3309 {
3311  PCONTROL_AREA ControlArea;
3312  KIRQL OldIrql;
3313 
3314  SectionObject = (PSECTION)ObjectBody;
3315 
3316  if (SectionObject->u.Flags.Based == 1)
3317  {
3318  /* Remove the node from the global section address tree */
3322  }
3323 
3324  /* Lock the PFN database */
3325  OldIrql = MiAcquirePfnLock();
3326 
3327  ASSERT(SectionObject->Segment);
3328  ASSERT(SectionObject->Segment->ControlArea);
3329 
3330  ControlArea = SectionObject->Segment->ControlArea;
3331 
3332  /* Dereference */
3333  ControlArea->NumberOfSectionReferences--;
3334  ControlArea->NumberOfUserReferences--;
3335 
3336  ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
3337 
3338  /* Check it. It will delete it if there is no more reference to it */
3339  MiCheckControlArea(ControlArea, OldIrql);
3340 }
3341 
3342 ULONG
3343 NTAPI
3345 {
3347  return 0;
3348 }
3349 
3350 /* SYSTEM CALLS ***************************************************************/
3351 
3352 NTSTATUS
3353 NTAPI
3354 NtAreMappedFilesTheSame(IN PVOID File1MappedAsAnImage,
3355  IN PVOID File2MappedAsFile)
3356 {
3358  PMMVAD Vad1, Vad2;
3359  PFILE_OBJECT FileObject1, FileObject2;
3360  NTSTATUS Status;
3361 
3362  /* Lock address space */
3365 
3366  /* Get the VAD for Address 1 */
3367  Vad1 = MiLocateAddress(File1MappedAsAnImage);
3368  if (Vad1 == NULL)
3369  {
3370  /* Fail, the address does not exist */
3371  DPRINT1("No VAD at address 1 %p\n", File1MappedAsAnImage);
3373  goto Exit;
3374  }
3375 
3376  /* Get the VAD for Address 2 */
3377  Vad2 = MiLocateAddress(File2MappedAsFile);
3378  if (Vad2 == NULL)
3379  {
3380  /* Fail, the address does not exist */
3381  DPRINT1("No VAD at address 2 %p\n", File2MappedAsFile);
3383  goto Exit;
3384  }
3385 
3386  /* Get the file object pointer for VAD 1 */
3387  FileObject1 = MiGetFileObjectForVad(Vad1);
3388  if (FileObject1 == NULL)
3389  {
3390  DPRINT1("Failed to get file object for Address 1 %p\n", File1MappedAsAnImage);
3392  goto Exit;
3393  }
3394 
3395  /* Get the file object pointer for VAD 2 */
3396  FileObject2 = MiGetFileObjectForVad(Vad2);
3397  if (FileObject2 == NULL)
3398  {
3399  DPRINT1("Failed to get file object for Address 2 %p\n", File2MappedAsFile);
3401  goto Exit;
3402  }
3403 
3404  /* Make sure Vad1 is an image mapping */
3405  if (Vad1->u.VadFlags.VadType != VadImageMap)
3406  {
3407  DPRINT1("Address 1 (%p) is not an image mapping\n", File1MappedAsAnImage);
3409  goto Exit;
3410  }
3411 
3412  /* SectionObjectPointer is equal if the files are equal */
3413  if (FileObject1->SectionObjectPointer == FileObject2->SectionObjectPointer)
3414  {
3416  }
3417  else
3418  {
3420  }
3421 
3422 Exit:
3423  /* Unlock address space */
3425  return Status;
3426 }
3427 
3428 /*
3429  * @implemented
3430  */
3431 NTSTATUS
3432 NTAPI
3440 {
3441  LARGE_INTEGER SafeMaximumSize;
3443  HANDLE Handle;
3445  NTSTATUS Status;
3446  PAGED_CODE();
3447 
3448  /* Check for non-existing flags */
3451  SEC_NO_CHANGE)))
3452  {
3453  if (!(AllocationAttributes & 1))
3454  {
3455  DPRINT1("Bogus allocation attribute: %lx\n", AllocationAttributes);
3457  }
3458  }
3459 
3460  /* Check for no allocation type */
3462  {
3463  DPRINT1("Missing allocation type in allocation attributes\n");
3465  }
3466 
3467  /* Check for image allocation with invalid attributes */
3468  if ((AllocationAttributes & SEC_IMAGE) &&
3471  {
3472  DPRINT1("Image allocation with invalid attributes\n");
3474  }
3475 
3476  /* Check for allocation type is both commit and reserve */
3478  {
3479  DPRINT1("Commit and reserve in the same time\n");
3481  }
3482 
3483  /* Now check for valid protection */
3488  {
3489  DPRINT1("Sections don't support these protections\n");
3491  }
3492 
3493  /* Use a maximum size of zero, if none was specified */
3494  SafeMaximumSize.QuadPart = 0;
3495 
3496  /* Check for user-mode caller */
3497  if (PreviousMode != KernelMode)
3498  {
3499  /* Enter SEH */
3500  _SEH2_TRY
3501  {
3502  /* Safely check user-mode parameters */
3503  if (MaximumSize) SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
3504  MaximumSize = &SafeMaximumSize;
3505  ProbeForWriteHandle(SectionHandle);
3506  }
3508  {
3509  /* Return the exception code */
3511  }
3512  _SEH2_END;
3513  }
3514  else if (!MaximumSize) MaximumSize = &SafeMaximumSize;
3515 
3516  /* Check that MaximumSize is valid if backed by paging file */
3517  if ((!FileHandle) && (!MaximumSize->QuadPart))
3519 
3520  /* Create the section */
3522  DesiredAccess,
3524  MaximumSize,
3527  FileHandle,
3528  NULL);
3529  if (!NT_SUCCESS(Status)) return Status;
3530 
3531  /* FIXME: Should zero last page for a file mapping */
3532 
3533  /* Now insert the object */
3535  NULL,
3536  DesiredAccess,
3537  0,
3538  NULL,
3539  &Handle);
3540  if (NT_SUCCESS(Status))
3541  {
3542  /* Enter SEH */
3543  _SEH2_TRY
3544  {
3545  /* Return the handle safely */
3546  *SectionHandle = Handle;
3547  }
3549  {
3550  /* Nothing here */
3551  }
3552  _SEH2_END;
3553  }
3554 
3555  /* Return the status */
3556  return Status;
3557 }
3558 
3559 NTSTATUS
3560 NTAPI
3561 NtOpenSection(OUT PHANDLE SectionHandle,
3564 {
3565  HANDLE Handle;
3566  NTSTATUS Status;
3568  PAGED_CODE();
3569 
3570  /* Check for user-mode caller */
3571  if (PreviousMode != KernelMode)
3572  {
3573  /* Enter SEH */
3574  _SEH2_TRY
3575  {
3576  /* Safely check user-mode parameters */
3577  ProbeForWriteHandle(SectionHandle);
3578  }
3580  {
3581  /* Return the exception code */
3583  }
3584  _SEH2_END;
3585  }
3586 
3587  /* Try opening the object */
3590  PreviousMode,
3591  NULL,
3592  DesiredAccess,
3593  NULL,
3594  &Handle);
3595 
3596  /* Enter SEH */
3597  _SEH2_TRY
3598  {
3599  /* Return the handle safely */
3600  *SectionHandle = Handle;
3601  }
3603  {
3604  /* Nothing here */
3605  }
3606  _SEH2_END;
3607 
3608  /* Return the status */
3609  return Status;
3610 }
3611 
3612 NTSTATUS
3613 NTAPI
3623  IN ULONG Protect)
3624 {
3625  PVOID SafeBaseAddress;
3626  LARGE_INTEGER SafeSectionOffset;
3627  SIZE_T SafeViewSize;
3628  PSECTION Section;
3630  NTSTATUS Status;
3632  ULONG ProtectionMask;
3634 #if defined(_M_IX86) || defined(_M_AMD64)
3635  static const ULONG ValidAllocationType = (MEM_TOP_DOWN | MEM_LARGE_PAGES |
3637 #else
3638  static const ULONG ValidAllocationType = (MEM_TOP_DOWN | MEM_LARGE_PAGES |
3640 #endif
3641 
3642  /* Check for invalid inherit disposition */
3644  {
3645  DPRINT1("Invalid inherit disposition\n");
3647  }
3648 
3649  /* Allow only valid allocation types */
3650  if (AllocationType & ~ValidAllocationType)
3651  {
3652  DPRINT1("Invalid allocation type\n");
3654  }
3655 
3656  /* Convert the protection mask, and validate it */
3657  ProtectionMask = MiMakeProtectionMask(Protect);
3658  if (ProtectionMask == MM_INVALID_PROTECTION)
3659  {
3660  DPRINT1("Invalid page protection\n");
3662  }
3663 
3664  /* Now convert the protection mask into desired section access mask */
3665  DesiredAccess = MmMakeSectionAccess[ProtectionMask & 0x7];
3666 
3667  /* Assume no section offset */
3668  SafeSectionOffset.QuadPart = 0;
3669 
3670  /* Enter SEH */
3671  _SEH2_TRY
3672  {
3673  /* Check for unsafe parameters */
3674  if (PreviousMode != KernelMode)
3675  {
3676  /* Probe the parameters */
3679  }
3680 
3681  /* Check if a section offset was given */
3682  if (SectionOffset)
3683  {
3684  /* Check for unsafe parameters and capture section offset */
3686  SafeSectionOffset = *SectionOffset;
3687  }
3688 
3689  /* Capture the other parameters */
3690  SafeBaseAddress = *BaseAddress;
3691  SafeViewSize = *ViewSize;
3692  }
3694  {
3695  /* Return the exception code */
3697  }
3698  _SEH2_END;
3699 
3700  /* Check for kernel-mode address */
3701  if (SafeBaseAddress > MM_HIGHEST_VAD_ADDRESS)
3702  {
3703  DPRINT1("Kernel base not allowed\n");
3705  }
3706 
3707  /* Check for range entering kernel-mode */
3708  if (((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)SafeBaseAddress) < SafeViewSize)
3709  {
3710  DPRINT1("Overflowing into kernel base not allowed\n");
3712  }
3713 
3714  /* Check for invalid zero bits */
3715  if (ZeroBits)
3716  {
3717  if (ZeroBits > MI_MAX_ZERO_BITS)
3718  {
3719  DPRINT1("Invalid zero bits\n");
3721  }
3722 
3723  if ((((ULONG_PTR)SafeBaseAddress << ZeroBits) >> ZeroBits) != (ULONG_PTR)SafeBaseAddress)
3724  {
3725  DPRINT1("Invalid zero bits\n");
3727  }
3728 
3729  if (((((ULONG_PTR)SafeBaseAddress + SafeViewSize) << ZeroBits) >> ZeroBits) != ((ULONG_PTR)SafeBaseAddress + SafeViewSize))
3730  {
3731  DPRINT1("Invalid zero bits\n");
3733  }
3734  }
3735 
3736  /* Reference the process */
3739  PsProcessType,
3740  PreviousMode,
3741  (PVOID*)&Process,
3742  NULL);
3743  if (!NT_SUCCESS(Status)) return Status;
3744 
3745  /* Reference the section */
3746  Status = ObReferenceObjectByHandle(SectionHandle,
3747  DesiredAccess,
3749  PreviousMode,
3750  (PVOID*)&Section,
3751  NULL);
3752  if (!NT_SUCCESS(Status))
3753  {
3755  return Status;
3756  }
3757 
3758  if (Section->u.Flags.PhysicalMemory)
3759  {
3760  if (PreviousMode == UserMode &&
3761  SafeSectionOffset.QuadPart + SafeViewSize > MmHighestPhysicalPage << PAGE_SHIFT)
3762  {
3763  DPRINT1("Denying map past highest physical page.\n");
3764  ObDereferenceObject(Section);
3767  }
3768  }
3769  else if (!(AllocationType & MEM_DOS_LIM))
3770  {
3771  /* Check for non-allocation-granularity-aligned BaseAddress */
3772  if (SafeBaseAddress != ALIGN_DOWN_POINTER_BY(SafeBaseAddress, MM_VIRTMEM_GRANULARITY))
3773  {
3774  DPRINT("BaseAddress is not at 64-kilobyte address boundary.\n");
3775  ObDereferenceObject(Section);
3777  return STATUS_MAPPED_ALIGNMENT;
3778  }
3779 
3780  /* Do the same for the section offset */
3781  if (SafeSectionOffset.LowPart != ALIGN_DOWN_BY(SafeSectionOffset.LowPart, MM_VIRTMEM_GRANULARITY))
3782  {
3783  DPRINT("SectionOffset is not at 64-kilobyte address boundary.\n");
3784  ObDereferenceObject(Section);
3786  return STATUS_MAPPED_ALIGNMENT;
3787  }
3788  }
3789 
3790  /* Now do the actual mapping */
3791  Status = MmMapViewOfSection(Section,
3792  Process,
3793  &SafeBaseAddress,
3794  ZeroBits,
3795  CommitSize,
3796  &SafeSectionOffset,
3797  &SafeViewSize,
3800  Protect);
3801 
3802  /* Return data only on success */
3803  if (NT_SUCCESS(Status))
3804  {
3805  /* Check if this is an image for the current process */
3806  if ((Section->u.Flags.Image) &&
3807  (Process == PsGetCurrentProcess()) &&
3809  {
3810  /* Notify the debugger */
3811  DbgkMapViewOfSection(Section,
3812  SafeBaseAddress,
3813  SafeSectionOffset.LowPart,
3814  SafeViewSize);
3815  }
3816 
3817  /* Enter SEH */
3818  _SEH2_TRY
3819  {
3820  /* Return parameters to user */
3821  *BaseAddress = SafeBaseAddress;
3822  *ViewSize = SafeViewSize;
3823  if (SectionOffset) *SectionOffset = SafeSectionOffset;
3824  }
3826  {
3827  /* Nothing to do */
3828  }
3829  _SEH2_END;
3830  }
3831 
3832  /* Dereference all objects and return status */
3833  ObDereferenceObject(Section);
3835  return Status;
3836 }
3837 
3838 NTSTATUS
3839 NTAPI
3842 {
3844  NTSTATUS Status;
3846 
3847  /* Don't allowing mapping kernel views */
3849  {
3850  DPRINT1("Trying to unmap a kernel view\n");
3851  return STATUS_NOT_MAPPED_VIEW;
3852  }
3853 
3854  /* Reference the process */
3857  PsProcessType,
3858  PreviousMode,
3859  (PVOID*)&Process,
3860  NULL);
3861  if (!NT_SUCCESS(Status)) return Status;
3862 
3863  /* Unmap the view */
3865 
3866  /* Dereference the process and return status */
3868  return Status;
3869 }
3870 
3871 NTSTATUS
3872 NTAPI
3873 NtExtendSection(IN HANDLE SectionHandle,
3874  IN OUT PLARGE_INTEGER NewMaximumSize)
3875 {
3876  LARGE_INTEGER SafeNewMaximumSize;
3877  PSECTION Section;
3878  NTSTATUS Status;
3880 
3881  /* Check for user-mode parameters */
3882  if (PreviousMode != KernelMode)
3883  {
3884  /* Enter SEH */
3885  _SEH2_TRY
3886  {
3887  /* Probe and capture the maximum size, it's both read and write */
3888  ProbeForWriteLargeInteger(NewMaximumSize);
3889  SafeNewMaximumSize = *NewMaximumSize;
3890  }
3892  {
3893  /* Return the exception code */
3895  }
3896  _SEH2_END;
3897  }
3898  else
3899  {
3900  /* Just read the size directly */
3901  SafeNewMaximumSize = *NewMaximumSize;
3902  }
3903 
3904  /* Reference the section */
3905  Status = ObReferenceObjectByHandle(SectionHandle,
3908  PreviousMode,
3909  (PVOID*)&Section,
3910  NULL);
3911  if (!NT_SUCCESS(Status)) return Status;
3912 
3913  Status = MmExtendSection(Section, &SafeNewMaximumSize);
3914 
3915  /* Dereference the section */
3916  ObDereferenceObject(Section);
3917 
3918  if (NT_SUCCESS(Status))
3919  {
3920  _SEH2_TRY
3921  {
3922  /* Write back the new size */
3923  *NewMaximumSize = SafeNewMaximumSize;
3924  }
3926  {
3928  }
3929  _SEH2_END;
3930  }
3931 
3932  /* Return the status */
3933  return STATUS_NOT_IMPLEMENTED;
3934 }
3935 
3936 /* 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:2528
#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:91
#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:3840
KAPC_STATE
Definition: ketypes.h:1280
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:1945
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:606
ULONG Type
Definition: mm.h:240
struct _MEMORY_AREA * PMEMORY_AREA
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1244
#define _Inout_
Definition: ms_sal.h:378
NTSTATUS NTAPI NtAreMappedFilesTheSame(IN PVOID File1MappedAsAnImage, IN PVOID File2MappedAsFile)
Definition: section.c:3354
NTSTATUS NTAPI MmGetFileNameForAddress(IN PVOID Address, OUT PUNICODE_STRING ModuleName)
Definition: section.c:1882
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:996
#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:3433
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:1533
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:3023
_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:2285
char CHAR
Definition: xmlstorage.h:175
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1618
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:2386
NTSTATUS NTAPI MmGetFileNameForSection(IN PVOID Section, OUT POBJECT_NAME_INFORMATION *ModuleName)
Definition: section.c:1861
BOOLEAN NTAPI MiInitializeSystemSpaceMap(IN PMMSESSION InputSession OPTIONAL)
Definition: section.c:240
union _MMPFN::@1761 u3
#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_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
#define MAXULONG_PTR
Definition: basetsd.h:103
USHORT Modified
Definition: mm.h:349
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:1209
PCHAR SystemSpaceViewStart
Definition: miarm.h:457
ULONG SecNoChange
Definition: mmtypes.h:704
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3070
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1292
PCONTROL_AREA ControlArea
Definition: mmtypes.h:762
ULONG_PTR Protection
Definition: mmtypes.h:693
VOID NTAPI MiSubsectionConsistent(IN PSUBSECTION Subsection)
Definition: section.c:1516
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:1185
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:1549
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
ULONG TotalNumberOfPtes
Definition: mmtypes.h:407
UNICODE_STRING Name
Definition: nt_native.h:1270
struct _SUBSECTION SUBSECTION
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
void DbgBreakPoint()
Definition: mach.c:553
FORCEINLINE PMMPDE MiPteToPde(PMMPTE PointerPte)
Definition: mm.h:261
USHORT ReferenceCount
Definition: mm.h:385
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:941
USHORT PageLocation
Definition: mm.h:354
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)
_SEH2_TRY
Definition: create.c:4226
#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
union _SUBSECTION::@2542 u
struct _CONTROL_AREA * ControlArea
Definition: mmtypes.h:406
uint32_t ULONG_PTR
Definition: typedefs.h:65
#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:2465
USHORT PrototypePte
Definition: mm.h:352
union _MMVAD::@2547 u
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG SectionPageProtection
Definition: mmfuncs.h:360
PVOID DllBase
Definition: btrfs_drv.h:1926
ULONG64 Dirty
Definition: mmtypes.h:164
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:386
HANDLE FileHandle
Definition: stats.c:38
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:59
VOID NTAPI MiDeleteARM3Section(PVOID ObjectBody)
Definition: section.c:3308
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:2387
#define SEC_COMMIT
Definition: mmtypes.h:99
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
#define TAG_MM
Definition: tag.h:136
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:86
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:1753
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
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:2888
#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:3120
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:368
#define MI_SET_PROCESS2(x)
Definition: mm.h:308
#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:3081
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:3548
NTSTATUS Status
Definition: section.c:4887
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:3614
_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:2116
NTSTATUS NTAPI NtOpenSection(OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: section.c:3561
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:2470
NTSTATUS NTAPI NtExtendSection(IN HANDLE SectionHandle, IN OUT PLARGE_INTEGER NewMaximumSize)
Definition: section.c:3873
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:48
static WCHAR Address[46]
Definition: ping.c:68
Entry
Definition: section.c:4896
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:476
#define MiProtoPteToPte(x)
Definition: mm.h:309
#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
return FALSE
Definition: section.c:5012
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1143
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:306
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:3898
union _SEGMENT::@2538 u1
void * PVOID
Definition: retypes.h:9
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:82
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
union _CONTROL_AREA::@2540 u
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:952
_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
KIRQL OldIrql
Definition: mm.h:1502
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:1829
NTSTATUS NTAPI MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:4411
#define MM_READONLY
Definition: inbv.c:11
#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:3109
_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:1057
#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:2431
#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:4474
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:1932
#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:3344
#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:4301
NTSTATUS NTAPI MmExtendSection(_In_ PVOID _Section, _Inout_ PLARGE_INTEGER NewSize)
Definition: section.c:5088
union _SECTION::@2556 u
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:2478
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
PCONTROL_AREA ControlArea
Definition: miarm.h:450
#define MM_READWRITE
Definition: inbv.c:12
NTSTATUS NTAPI MmCommitSessionMappedView(IN PVOID MappedBase, IN SIZE_T ViewSize)
Definition: section.c:3145
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:362
ULONG GlobalOnlyPerSession
Definition: mmtypes.h:488
Definition: btrfs_drv.h:1922
ULONG LowPart
Definition: typedefs.h:106
BOOLEAN NTAPI MmForceSectionClosed(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN BOOLEAN DelayClose)
Definition: section.c:3034
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
ULONG64 Prototype
Definition: mmtypes.h:89
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:1808
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:1000
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)
union _MMVAD_LONG::@2553 u4
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
#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:1640
#define PAGE_WRITECOMBINE
Definition: mmtypes.h:78
#define STATUS_INVALID_VIEW_SIZE
Definition: ntstatus.h:268
_SEH2_END
Definition: create.c:4400
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:2931
#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:285
#define MiIsPteOnPdeBoundary(PointerPte)
Definition: mm.h:299
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
union _MMVAD_LONG::@2551 u2
ULONG FilePointerNull
Definition: mmtypes.h:479
NTSTATUS NTAPI MiGetFileObjectForSectionAddress(IN PVOID Address, OUT PFILE_OBJECT *FileObject)
Definition: section.c:1668
ULONG64 Transition
Definition: mmtypes.h:90
FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, IN PMMPTE PointerPte)
Definition: mm.h:335
struct _MEMORY_SECTION_NAME MEMORY_SECTION_NAME
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
#define MI_SYSTEM_VIEW_BUCKET_SIZE
Definition: miarm.h:266
ULONG NTAPI MiGetPageProtection(IN PMMPTE PointerPte)
Definition: virtual.c:1348
ULONG BeingDeleted
Definition: mmtypes.h:460
#define STATUS_INVALID_PARAMETER_10
Definition: ntstatus.h:484
Definition: miarm.h:447
ULONG WritableUserReferences
Definition: mmtypes.h:534
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
PSEGMENT Segment
Definition: mmtypes.h:518
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1679
_Must_inspect_result_ _In_ ULONG NewProtect
Definition: mmfuncs.h:682
UNICODE_STRING FullDllName
Definition: