ReactOS  r76032
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 {
25  SECTION_MAP_EXECUTE | SECTION_MAP_READ,
28  SECTION_MAP_EXECUTE | SECTION_MAP_WRITE,
29  SECTION_MAP_EXECUTE | SECTION_MAP_READ
30 };
31 
33 {
37  FILE_EXECUTE | FILE_READ_DATA,
40  FILE_EXECUTE | FILE_WRITE_DATA | FILE_READ_DATA,
41  FILE_EXECUTE | FILE_READ_DATA
42 };
43 
45 {
46  0,
52  (CHAR)MM_INVALID_PROTECTION,
55  (CHAR)MM_INVALID_PROTECTION,
57  (CHAR)MM_INVALID_PROTECTION,
59  (CHAR)MM_INVALID_PROTECTION,
61  (CHAR)MM_INVALID_PROTECTION
62 };
63 
65 {
66  0,
67  MM_EXECUTE,
69  (CHAR)MM_INVALID_PROTECTION,
72  (CHAR)MM_INVALID_PROTECTION,
75  (CHAR)MM_INVALID_PROTECTION,
77  (CHAR)MM_INVALID_PROTECTION,
79  (CHAR)MM_INVALID_PROTECTION,
81  (CHAR)MM_INVALID_PROTECTION
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 */
123  ProtectionMask = MiMakeProtectionMask(SectionPageProtection);
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 */
145  ProtectionMask = MiMakeProtectionMask(SectionPageProtection);
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) ||
194  (Protect & (PAGE_NOCACHE | PAGE_WRITECOMBINE)))
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 */
222  if (Protect & PAGE_WRITECOMBINE)
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;
252  Size = MmSessionViewSize;
253  }
254  else
255  {
256  /* Use the system space "session" */
257  Session = &MmSession;
258  ViewStart = MiSystemViewStart;
259  Size = MmSystemViewSize;
260  }
261 
262  /* Initialize the system space lock */
263  Session->SystemSpaceViewLockPointer = &Session->SystemSpaceViewLock;
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);
274  ASSERT(Session->SystemSpaceBitMap);
276  (PULONG)(Session->SystemSpaceBitMap + 1),
278 
279  /* Set system space fully empty to begin with */
281 
282  /* Set default hash flags */
283  Session->SystemSpaceHashSize = 31;
284  Session->SystemSpaceHashKey = Session->SystemSpaceHashSize - 1;
285  Session->SystemSpaceHashEntries = 0;
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 */
292  Session->SystemSpaceViewTable = ExAllocatePoolWithTag(Session == &MmSession ?
293  NonPagedPool :
294  PagedPool,
295  AllocSize,
296  TAG_MM);
297  ASSERT(Session->SystemSpaceViewTable != NULL);
298  RtlZeroMemory(Session->SystemSpaceViewTable, AllocSize);
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 */
319  KeAcquireGuardedMutex(Session->SystemSpaceViewLockPointer);
320 
321  /* Check if we're going to exhaust hash entries */
322  if ((Session->SystemSpaceHashEntries + 8) > Session->SystemSpaceHashSize)
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;
329  Session->SystemSpaceViewTable = ExAllocatePoolWithTag(Session ==
330  &MmSession ?
331  NonPagedPool :
332  PagedPool,
333  HashSize *
334  sizeof(MMVIEW),
335  TAG_MM);
336  if (!Session->SystemSpaceViewTable)
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;
346  Session->SystemSpaceHashKey = Session->SystemSpaceHashSize - 1;
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;
356  while (Session->SystemSpaceViewTable[Hash].Entry)
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 */
373  if (Session->SystemSpaceHashEntries == Session->SystemSpaceHashSize)
374  {
375  DPRINT1("Ran out of system view hash entries\n");
376  KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
377  return NULL;
378  }
379 
380  /* Find space where to map this view */
381  i = RtlFindClearBitsAndSet(Session->SystemSpaceBitMap, Buckets, 0);
382  if (i == 0xFFFFFFFF)
383  {
384  /* Out of space, fail */
385  Session->BitmapFailures++;
386  DPRINT1("Out of system view space\n");
387  KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
388  return NULL;
389  }
390 
391  /* Compute the base address */
392  Base = (PVOID)((ULONG_PTR)Session->SystemSpaceViewStart + (i * MI_SYSTEM_VIEW_BUCKET_SIZE));
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 */
399  while (Session->SystemSpaceViewTable[Hash].Entry)
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 */
406  Session->SystemSpaceViewTable[Hash].Entry = Entry;
407  Session->SystemSpaceViewTable[Hash].ControlArea = ControlArea;
408 
409  /* Hash entry found, increment total and return the base address */
410  Session->SystemSpaceHashEntries++;
411  KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
412  return Base;
413 }
414 
415 NTSTATUS
416 NTAPI
418  IN PFN_NUMBER PteCount,
419  IN PCONTROL_AREA ControlArea)
420 {
421  MMPTE TempPte;
422  PMMPTE PointerPte, ProtoPte, LastProtoPte, LastPte;
423  PSUBSECTION Subsection;
424 
425  /* ARM3 doesn't support this yet */
426  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
427  ASSERT(ControlArea->u.Flags.Rom == 0);
428  ASSERT(ControlArea->FilePointer == NULL);
429 
430  /* Sanity checks */
431  ASSERT(PteCount != 0);
432  ASSERT(ControlArea->NumberOfMappedViews >= 1);
433  ASSERT(ControlArea->NumberOfUserReferences >= 1);
434  ASSERT(ControlArea->NumberOfSectionReferences != 0);
435  ASSERT(ControlArea->u.Flags.BeingCreated == 0);
436  ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
437  ASSERT(ControlArea->u.Flags.BeingPurged == 0);
438 
439  /* Get the PTEs for the actual mapping */
440  PointerPte = FirstPte;
441  LastPte = FirstPte + PteCount;
442 
443  /* Get the prototype PTEs that desribe the section mapping in the subsection */
444  Subsection = (PSUBSECTION)(ControlArea + 1);
445  ProtoPte = Subsection->SubsectionBase;
446  LastProtoPte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
447 
448  /* Loop the PTEs for the mapping */
449  while (PointerPte < LastPte)
450  {
451  /* We may have run out of prototype PTEs in this subsection */
452  if (ProtoPte >= LastProtoPte)
453  {
454  /* But we don't handle this yet */
455  ASSERT(FALSE);
456  }
457 
458  /* The PTE should be completely clear */
459  ASSERT(PointerPte->u.Long == 0);
460 
461  /* Build the prototype PTE and write it */
462  MI_MAKE_PROTOTYPE_PTE(&TempPte, ProtoPte);
463  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
464 
465  /* Keep going */
466  PointerPte++;
467  ProtoPte++;
468  }
469 
470  /* No failure path */
471  return STATUS_SUCCESS;
472 }
473 
474 VOID
475 NTAPI
478 {
479  PMMPDE PointerPde, LastPde, SystemMapPde;
480  MMPDE TempPde;
481  PFN_NUMBER PageFrameIndex, ParentPage;
482  KIRQL OldIrql;
483  PAGED_CODE();
484 
485  /* Find the PDEs needed for this mapping */
486  PointerPde = MiAddressToPde(Base);
487  LastPde = MiAddressToPde((PVOID)((ULONG_PTR)Base + NumberOfBytes - 1));
488 
489 #if (_MI_PAGING_LEVELS == 2)
490  /* Find the system double-mapped PDE that describes this mapping */
491  SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
492 #else
493  /* We don't have a double mapping */
494  SystemMapPde = PointerPde;
495 #endif
496 
497  /* Use the PDE template and loop the PDEs */
498  TempPde = ValidKernelPde;
499  while (PointerPde <= LastPde)
500  {
501  /* Lock the PFN database */
503 
504  /* Check if we don't already have this PDE mapped */
505  if (SystemMapPde->u.Hard.Valid == 0)
506  {
507  /* Grab a page for it */
509  MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
510  PageFrameIndex = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
511  ASSERT(PageFrameIndex);
512  TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
513 
514 #if (_MI_PAGING_LEVELS == 2)
515  ParentPage = MmSystemPageDirectory[(PointerPde - MiAddressToPde(NULL)) / PDE_COUNT];
516 #else
517  ParentPage = MiPdeToPpe(PointerPde)->u.Hard.PageFrameNumber;
518 #endif
519  /* Initialize its PFN entry, with the parent system page directory page table */
520  MiInitializePfnForOtherProcess(PageFrameIndex,
521  (PMMPTE)PointerPde,
522  ParentPage);
523 
524  /* Make the system PDE entry valid */
525  MI_WRITE_VALID_PDE(SystemMapPde, TempPde);
526 
527  /* The system PDE entry might be the PDE itself, so check for this */
528  if (PointerPde->u.Hard.Valid == 0)
529  {
530  /* It's different, so make the real PDE valid too */
531  MI_WRITE_VALID_PDE(PointerPde, TempPde);
532  }
533  }
534 
535  /* Release the lock and keep going with the next PDE */
537  SystemMapPde++;
538  PointerPde++;
539  }
540 }
541 
542 NTSTATUS
543 NTAPI
545  IN BOOLEAN FailIfSystemViews)
546 {
547  KIRQL OldIrql;
548 
549  /* Flag not yet supported */
550  ASSERT(FailIfSystemViews == FALSE);
551 
552  /* Lock the PFN database */
554 
555  /* State not yet supported */
556  ASSERT(ControlArea->u.Flags.BeingPurged == 0);
557 
558  /* Increase the reference counts */
559  ControlArea->NumberOfMappedViews++;
560  ControlArea->NumberOfUserReferences++;
561  ASSERT(ControlArea->NumberOfSectionReferences != 0);
562 
563  /* Release the PFN lock and return success */
565  return STATUS_SUCCESS;
566 }
567 
569 NTAPI
571  IN ULONG_PTR Vpn)
572 {
573  PSUBSECTION Subsection;
574  PCONTROL_AREA ControlArea;
575  ULONG_PTR PteOffset;
576 
577  /* Get the control area */
578  ControlArea = Vad->ControlArea;
579  ASSERT(ControlArea->u.Flags.Rom == 0);
580  ASSERT(ControlArea->u.Flags.Image == 0);
581  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
582 
583  /* Get the subsection */
584  Subsection = (PSUBSECTION)(ControlArea + 1);
585 
586  /* We only support single-subsection segments */
587  ASSERT(Subsection->SubsectionBase != NULL);
588  ASSERT(Vad->FirstPrototypePte >= Subsection->SubsectionBase);
589  ASSERT(Vad->FirstPrototypePte < &Subsection->SubsectionBase[Subsection->PtesInSubsection]);
590 
591  /* Compute the PTE offset */
592  PteOffset = Vpn - Vad->StartingVpn;
593  PteOffset += Vad->FirstPrototypePte - Subsection->SubsectionBase;
594 
595  /* Again, we only support single-subsection segments */
596  ASSERT(PteOffset < 0xF0000000);
597  ASSERT(PteOffset < Subsection->PtesInSubsection);
598 
599  /* Return the subsection */
600  return Subsection;
601 }
602 
603 VOID
604 NTAPI
606 {
607  PCONTROL_AREA ControlArea;
608  SEGMENT_FLAGS SegmentFlags;
609  PSUBSECTION Subsection;
610  PMMPTE PointerPte, LastPte, PteForProto;
611  PMMPFN Pfn1;
612  PFN_NUMBER PageFrameIndex;
613  MMPTE TempPte;
614  KIRQL OldIrql;
615 
616  /* Capture data */
617  SegmentFlags = Segment->SegmentFlags;
618  ControlArea = Segment->ControlArea;
619 
620  /* Make sure control area is on the right delete path */
621  ASSERT(ControlArea->u.Flags.BeingDeleted == 1);
622  ASSERT(ControlArea->WritableUserReferences == 0);
623 
624  /* These things are not supported yet */
625  ASSERT(ControlArea->DereferenceList.Flink == NULL);
626  ASSERT(!(ControlArea->u.Flags.Image) && !(ControlArea->u.Flags.File));
627  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
628  ASSERT(ControlArea->u.Flags.Rom == 0);
629 
630  /* Get the subsection and PTEs for this segment */
631  Subsection = (PSUBSECTION)(ControlArea + 1);
632  PointerPte = Subsection->SubsectionBase;
633  LastPte = PointerPte + Segment->NonExtendedPtes;
634 
635  /* Lock the PFN database */
637 
638  /* Check if the master PTE is invalid */
639  PteForProto = MiAddressToPte(PointerPte);
640  if (!PteForProto->u.Hard.Valid)
641  {
642  /* Fault it in */
643  MiMakeSystemAddressValidPfn(PointerPte, OldIrql);
644  }
645 
646  /* Loop all the segment PTEs */
647  while (PointerPte < LastPte)
648  {
649  /* Check if it's time to switch master PTEs if we passed a PDE boundary */
650  if (!((ULONG_PTR)PointerPte & (PD_SIZE - 1)) &&
651  (PointerPte != Subsection->SubsectionBase))
652  {
653  /* Check if the master PTE is invalid */
654  PteForProto = MiAddressToPte(PointerPte);
655  if (!PteForProto->u.Hard.Valid)
656  {
657  /* Fault it in */
658  MiMakeSystemAddressValidPfn(PointerPte, OldIrql);
659  }
660  }
661 
662  /* This should be a prototype PTE */
663  TempPte = *PointerPte;
664  ASSERT(SegmentFlags.LargePages == 0);
665  ASSERT(TempPte.u.Hard.Valid == 0);
666 
667  /* See if we should clean things up */
668  if (!(ControlArea->u.Flags.Image) && !(ControlArea->u.Flags.File))
669  {
670  /*
671  * This is a section backed by the pagefile. Now that it doesn't exist anymore,
672  * we can give everything back to the system.
673  */
674  ASSERT(TempPte.u.Soft.Prototype == 0);
675 
676  if (TempPte.u.Soft.Transition == 1)
677  {
678  /* We can give the page back for other use */
679  DPRINT("Releasing page for transition PTE %p\n", PointerPte);
680  PageFrameIndex = PFN_FROM_PTE(&TempPte);
681  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
682 
683  /* As this is a paged-backed section, nobody should reference it anymore (no cache or whatever) */
684  ASSERT(Pfn1->u3.ReferenceCount == 0);
685 
686  /* And it should be in standby or modified list */
688 
689  /* Unlink it and put it back in free list */
690  MiUnlinkPageFromList(Pfn1);
691 
692  /* Temporarily mark this as active and make it free again */
694  MI_SET_PFN_DELETED(Pfn1);
695 
696  MiInsertPageInFreeList(PageFrameIndex);
697  }
698  else if (TempPte.u.Soft.PageFileHigh != 0)
699  {
700  /* Should not happen for now */
701  ASSERT(FALSE);
702  }
703  }
704  else
705  {
706  /* unsupported for now */
707  ASSERT(FALSE);
708 
709  /* File-backed section must have prototype PTEs */
710  ASSERT(TempPte.u.Soft.Prototype == 1);
711  }
712 
713  /* Zero the PTE and keep going */
714  PointerPte->u.Long = 0;
715  PointerPte++;
716  }
717 
718  /* Release the PFN lock */
720 
721  /* Free the structures */
722  ExFreePool(ControlArea);
723  ExFreePool(Segment);
724 }
725 
726 VOID
727 NTAPI
729  IN KIRQL OldIrql)
730 {
731  BOOLEAN DeleteSegment = FALSE;
733 
734  /* Check if this is the last reference or view */
735  if (!(ControlArea->NumberOfMappedViews) &&
736  !(ControlArea->NumberOfSectionReferences))
737  {
738  /* There should be no more user references either */
739  ASSERT(ControlArea->NumberOfUserReferences == 0);
740 
741  /* Not yet supported */
742  ASSERT(ControlArea->FilePointer == NULL);
743 
744  /* The control area is being destroyed */
745  ControlArea->u.Flags.BeingDeleted = TRUE;
746  DeleteSegment = TRUE;
747  }
748 
749  /* Release the PFN lock */
751 
752  /* Delete the segment if needed */
753  if (DeleteSegment)
754  {
755  /* No more user write references at all */
756  ASSERT(ControlArea->WritableUserReferences == 0);
757  MiSegmentDelete(ControlArea->Segment);
758  }
759 }
760 
761 VOID
762 NTAPI
764 {
765  KIRQL OldIrql;
766 
767  /* Lock the PFN database */
769 
770  /* Drop reference counts */
771  ControlArea->NumberOfMappedViews--;
772  ControlArea->NumberOfUserReferences--;
773 
774  /* Check if it's time to delete the CA. This releases the lock */
775  MiCheckControlArea(ControlArea, OldIrql);
776 }
777 
778 VOID
779 NTAPI
781  IN PMMVAD Vad)
782 {
783  KIRQL OldIrql;
784  PCONTROL_AREA ControlArea;
785  PETHREAD CurrentThread = PsGetCurrentThread();
786 
787  /* Get the control area */
788  ControlArea = Vad->ControlArea;
789 
790  /* We only support non-extendable, non-image, pagefile-backed regular sections */
791  ASSERT(Vad->u.VadFlags.VadType == VadNone);
792  ASSERT(Vad->u2.VadFlags2.ExtendableFile == FALSE);
793  ASSERT(ControlArea);
794  ASSERT(ControlArea->FilePointer == NULL);
795 
796  /* Delete the actual virtual memory pages */
797  MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
798  (Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
799  Vad);
800 
801  /* Release the working set */
802  MiUnlockProcessWorkingSetUnsafe(CurrentProcess, CurrentThread);
803 
804  /* Lock the PFN database */
806 
807  /* Remove references */
808  ControlArea->NumberOfMappedViews--;
809  ControlArea->NumberOfUserReferences--;
810 
811  /* Check if it should be destroyed */
812  MiCheckControlArea(ControlArea, OldIrql);
813 }
814 
815 NTSTATUS
816 NTAPI
819  IN ULONG Flags)
820 {
824  PMMVAD Vad;
825  PVOID DbgBase = NULL;
828  PETHREAD CurrentThread = PsGetCurrentThread();
830  PAGED_CODE();
831 
832  /* Check for Mm Region */
833  MemoryArea = MmLocateMemoryAreaByAddress(&Process->Vm, BaseAddress);
834  if ((MemoryArea) && (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3))
835  {
836  /* Call Mm API */
837  return MiRosUnmapViewOfSection(Process, BaseAddress, Process->ProcessExiting);
838  }
839 
840  /* Check if we should attach to the process */
841  if (CurrentProcess != Process)
842  {
843  /* The process is different, do an attach */
844  KeStackAttachProcess(&Process->Pcb, &ApcState);
845  Attached = TRUE;
846  }
847 
848  /* Check if we need to lock the address space */
849  if (!Flags) MmLockAddressSpace(&Process->Vm);
850 
851  /* Check if the process is already daed */
852  if (Process->VmDeleted)
853  {
854  /* Fail the call */
855  DPRINT1("Process died!\n");
856  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
858  goto Quickie;
859  }
860 
861  /* Find the VAD for the address and make sure it's a section VAD */
862  Vad = MiLocateAddress(BaseAddress);
863  if (!(Vad) || (Vad->u.VadFlags.PrivateMemory))
864  {
865  /* Couldn't find it, or invalid VAD, fail */
866  DPRINT1("No VAD or invalid VAD\n");
867  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
868  Status = STATUS_NOT_MAPPED_VIEW;
869  goto Quickie;
870  }
871 
872  /* We should be attached */
873  ASSERT(Process == PsGetCurrentProcess());
874 
875  /* We need the base address for the debugger message on image-backed VADs */
876  if (Vad->u.VadFlags.VadType == VadImageMap)
877  {
878  DbgBase = (PVOID)(Vad->StartingVpn >> PAGE_SHIFT);
879  }
880 
881  /* Compute the size of the VAD region */
882  RegionSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
883 
884  /* For SEC_NO_CHANGE sections, we need some extra checks */
885  if (Vad->u.VadFlags.NoChange == 1)
886  {
887  /* Are we allowed to mess with this VAD? */
888  Status = MiCheckSecuredVad(Vad,
889  (PVOID)(Vad->StartingVpn >> PAGE_SHIFT),
890  RegionSize,
892  if (!NT_SUCCESS(Status))
893  {
894  /* We failed */
895  DPRINT1("Trying to unmap protected VAD!\n");
896  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
897  goto Quickie;
898  }
899  }
900 
901  /* Not currently supported */
903 
904  /* FIXME: Remove VAD charges */
905 
906  /* Lock the working set */
907  MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
908 
909  /* Remove the VAD */
910  ASSERT(Process->VadRoot.NumberGenericTableElements >= 1);
911  MiRemoveNode((PMMADDRESS_NODE)Vad, &Process->VadRoot);
912 
913  /* Remove the PTEs for this view, which also releases the working set lock */
914  MiRemoveMappedView(Process, Vad);
915 
916  /* FIXME: Remove commitment */
917 
918  /* Update performance counter and release the lock */
919  Process->VirtualSize -= RegionSize;
920  if (!Flags) MmUnlockAddressSpace(&Process->Vm);
921 
922  /* Destroy the VAD and return success */
923  ExFreePool(Vad);
924  Status = STATUS_SUCCESS;
925 
926  /* Failure and success case -- send debugger message, detach, and return */
927 Quickie:
928  if (DbgBase) DbgkUnMapViewOfSection(DbgBase);
929  if (Attached) KeUnstackDetachProcess(&ApcState);
930  return Status;
931 }
932 
933 NTSTATUS
934 NTAPI
936  IN PVOID EndVa)
937 {
938  KIRQL OldIrql;
939  ULONG Color, Index;
940  PMMPDE StartPde, EndPde;
942  PMMPFN Pfn1;
943  PFN_NUMBER PageCount = 0, ActualPages = 0, PageFrameNumber;
944 
945  /* Windows sanity checks */
946  ASSERT(StartVa >= (PVOID)MmSessionBase);
947  ASSERT(EndVa < (PVOID)MiSessionSpaceEnd);
948  ASSERT(PAGE_ALIGN(EndVa) == EndVa);
949 
950  /* Get the start and end PDE, then loop each one */
951  StartPde = MiAddressToPde(StartVa);
952  EndPde = MiAddressToPde((PVOID)((ULONG_PTR)EndVa - 1));
953  Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
954  while (StartPde <= EndPde)
955  {
956 #ifndef _M_AMD64
957  /* If we don't already have a page table for it, increment count */
958  if (MmSessionSpace->PageTables[Index].u.Long == 0) PageCount++;
959 #endif
960  /* Move to the next one */
961  StartPde++;
962  Index++;
963  }
964 
965  /* If there's no page tables to create, bail out */
966  if (PageCount == 0) return STATUS_SUCCESS;
967 
968  /* Reset the start PDE and index */
969  StartPde = MiAddressToPde(StartVa);
970  Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
971 
972  /* Loop each PDE while holding the working set lock */
973 // MiLockWorkingSet(PsGetCurrentThread(),
974 // &MmSessionSpace->GlobalVirtualAddress->Vm);
975 #ifdef _M_AMD64
976 _WARN("MiSessionCommitPageTables halfplemented for amd64")
981  DBG_UNREFERENCED_LOCAL_VARIABLE(PageFrameNumber);
982  ASSERT(FALSE);
983 #else
984  while (StartPde <= EndPde)
985  {
986  /* Check if we already have a page table */
987  if (MmSessionSpace->PageTables[Index].u.Long == 0)
988  {
989  /* We don't, so the PDE shouldn't be ready yet */
990  ASSERT(StartPde->u.Hard.Valid == 0);
991 
992  /* ReactOS check to avoid MiEnsureAvailablePageOrWait */
993  ASSERT(MmAvailablePages >= 32);
994 
995  /* Acquire the PFN lock and grab a zero page */
998  MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
1000  PageFrameNumber = MiRemoveZeroPage(Color);
1001  TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
1002  MI_WRITE_VALID_PDE(StartPde, TempPde);
1003 
1004  /* Write the page table in session space structure */
1005  ASSERT(MmSessionSpace->PageTables[Index].u.Long == 0);
1007 
1008  /* Initialize the PFN */
1009  MiInitializePfnForOtherProcess(PageFrameNumber,
1010  StartPde,
1012 
1013  /* And now release the lock */
1015 
1016  /* Get the PFN entry and make sure there's no event for it */
1017  Pfn1 = MI_PFN_ELEMENT(PageFrameNumber);
1018  ASSERT(Pfn1->u1.Event == NULL);
1019 
1020  /* Increment the number of pages */
1021  ActualPages++;
1022  }
1023 
1024  /* Move to the next PDE */
1025  StartPde++;
1026  Index++;
1027  }
1028 #endif
1029 
1030  /* Make sure we didn't do more pages than expected */
1031  ASSERT(ActualPages <= PageCount);
1032 
1033  /* Release the working set lock */
1034 // MiUnlockWorkingSet(PsGetCurrentThread(),
1035 // &MmSessionSpace->GlobalVirtualAddress->Vm);
1036 
1037 
1038  /* If we did at least one page... */
1039  if (ActualPages)
1040  {
1041  /* Update the performance counters! */
1044  }
1045 
1046  /* Return status */
1047  return STATUS_SUCCESS;
1048 }
1049 
1050 NTSTATUS
1051 NTAPI
1054  OUT PVOID *MappedBase,
1056 {
1057  PVOID Base;
1058  PCONTROL_AREA ControlArea;
1059  ULONG Buckets, SectionSize;
1060  NTSTATUS Status;
1061  PAGED_CODE();
1062 
1063  /* Get the control area, check for any flags ARM3 doesn't yet support */
1064  ControlArea = ((PSECTION)Section)->Segment->ControlArea;
1065  ASSERT(ControlArea->u.Flags.Image == 0);
1066  ASSERT(ControlArea->FilePointer == NULL);
1067  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
1068  ASSERT(ControlArea->u.Flags.Rom == 0);
1069  ASSERT(ControlArea->u.Flags.WasPurged == 0);
1070 
1071  /* Increase the reference and map count on the control area, no purges yet */
1072  Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
1073  ASSERT(NT_SUCCESS(Status));
1074 
1075  /* Get the section size at creation time */
1076  SectionSize = ((PSECTION)Section)->SizeOfSection.LowPart;
1077 
1078  /* If the caller didn't specify a view size, assume the whole section */
1079  if (!(*ViewSize)) *ViewSize = SectionSize;
1080 
1081  /* Check if the caller wanted a larger section than the view */
1082  if (*ViewSize > SectionSize)
1083  {
1084  /* Fail */
1085  DPRINT1("View is too large\n");
1086  MiDereferenceControlArea(ControlArea);
1087  return STATUS_INVALID_VIEW_SIZE;
1088  }
1089 
1090  /* Get the number of 64K buckets required for this mapping */
1091  Buckets = (ULONG)(*ViewSize / MI_SYSTEM_VIEW_BUCKET_SIZE);
1092  if (*ViewSize & (MI_SYSTEM_VIEW_BUCKET_SIZE - 1)) Buckets++;
1093 
1094  /* Check if the view is more than 4GB large */
1095  if (Buckets >= MI_SYSTEM_VIEW_BUCKET_SIZE)
1096  {
1097  /* Fail */
1098  DPRINT1("View is too large\n");
1099  MiDereferenceControlArea(ControlArea);
1100  return STATUS_INVALID_VIEW_SIZE;
1101  }
1102 
1103  /* Insert this view into system space and get a base address for it */
1104  Base = MiInsertInSystemSpace(Session, Buckets, ControlArea);
1105  if (!Base)
1106  {
1107  /* Fail */
1108  DPRINT1("Out of system space\n");
1109  MiDereferenceControlArea(ControlArea);
1110  return STATUS_NO_MEMORY;
1111  }
1112 
1113  /* What's the underlying session? */
1114  if (Session == &MmSession)
1115  {
1116  /* Create the PDEs needed for this mapping, and double-map them if needed */
1118  Status = STATUS_SUCCESS;
1119  }
1120  else
1121  {
1122  /* Create the PDEs needed for this mapping */
1123  Status = MiSessionCommitPageTables(Base,
1124  (PVOID)((ULONG_PTR)Base +
1125  Buckets * MI_SYSTEM_VIEW_BUCKET_SIZE));
1126  ASSERT(NT_SUCCESS(Status));
1127  }
1128 
1129  /* Create the actual prototype PTEs for this mapping */
1130  Status = MiAddMappedPtes(MiAddressToPte(Base),
1131  BYTES_TO_PAGES(*ViewSize),
1132  ControlArea);
1133  ASSERT(NT_SUCCESS(Status));
1134 
1135  /* Return the base adress of the mapping and success */
1136  *MappedBase = Base;
1137  return STATUS_SUCCESS;
1138 }
1139 
1140 VOID
1141 NTAPI
1143 {
1144  KIRQL OldIrql;
1145 
1147 
1149  ControlArea->u.Flags.DebugSymbolsLoaded |= 1;
1150 
1151  ASSERT(OldIrql <= APC_LEVEL);
1154 }
1155 
1156 VOID
1157 NTAPI
1161 {
1162  NTSTATUS Status;
1164  PLIST_ENTRY NextEntry;
1166  PIMAGE_NT_HEADERS NtHeaders;
1167  PLDR_DATA_TABLE_ENTRY LdrEntry;
1168 
1169  FileName = &ControlArea->FilePointer->FileName;
1170  if (FileName->Length == 0)
1171  {
1172  return;
1173  }
1174 
1175  /* Acquire module list lock */
1178 
1179  /* Browse list to try to find current module */
1180  for (NextEntry = MmLoadedUserImageList.Flink;
1181  NextEntry != &MmLoadedUserImageList;
1182  NextEntry = NextEntry->Flink)
1183  {
1184  /* Get the entry */
1185  LdrEntry = CONTAINING_RECORD(NextEntry,
1187  InLoadOrderLinks);
1188 
1189  /* If already in the list, increase load count */
1190  if (LdrEntry->DllBase == BaseAddress)
1191  {
1192  ++LdrEntry->LoadCount;
1193  break;
1194  }
1195  }
1196 
1197  /* Not in the list, we'll add it */
1198  if (NextEntry == &MmLoadedUserImageList)
1199  {
1200  /* Allocate our element, taking to the name string and its null char */
1201  LdrEntry = ExAllocatePoolWithTag(NonPagedPool, FileName->Length + sizeof(UNICODE_NULL) + sizeof(*LdrEntry), 'bDmM');
1202  if (LdrEntry)
1203  {
1204  memset(LdrEntry, 0, FileName->Length + sizeof(UNICODE_NULL) + sizeof(*LdrEntry));
1205 
1206  _SEH2_TRY
1207  {
1208  /* Get image checksum and size */
1209  NtHeaders = RtlImageNtHeader(BaseAddress);
1210  if (NtHeaders)
1211  {
1212  LdrEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage;
1213  LdrEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum;
1214  }
1215  }
1217  {
1218  ExFreePoolWithTag(LdrEntry, 'bDmM');
1219  _SEH2_YIELD(return);
1220  }
1221  _SEH2_END;
1222 
1223  /* Fill all the details */
1224  LdrEntry->DllBase = BaseAddress;
1225  LdrEntry->FullDllName.Buffer = (PVOID)((ULONG_PTR)LdrEntry + sizeof(*LdrEntry));
1226  LdrEntry->FullDllName.Length = FileName->Length;
1227  LdrEntry->FullDllName.MaximumLength = FileName->Length + sizeof(UNICODE_NULL);
1228  memcpy(LdrEntry->FullDllName.Buffer, FileName->Buffer, FileName->Length);
1229  LdrEntry->FullDllName.Buffer[LdrEntry->FullDllName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1230  LdrEntry->LoadCount = 1;
1231 
1232  /* Insert! */
1234  }
1235  }
1236 
1237  /* Release locks */
1240 
1241  /* Load symbols */
1242  Status = RtlUnicodeStringToAnsiString(&FileNameA, FileName, TRUE);
1243  if (NT_SUCCESS(Status))
1244  {
1245  DbgLoadImageSymbols(&FileNameA, BaseAddress, (ULONG_PTR)Process->UniqueProcessId);
1246  RtlFreeAnsiString(&FileNameA);
1247  }
1248 }
1249 
1250 NTSTATUS
1251 NTAPI
1254  IN PVOID *BaseAddress,
1257  IN PSECTION Section,
1259  IN ULONG ProtectionMask,
1263 {
1264  PMMVAD_LONG Vad;
1265  ULONG_PTR StartAddress;
1266  ULONG_PTR ViewSizeInPages;
1267  PSUBSECTION Subsection;
1268  PSEGMENT Segment;
1269  PFN_NUMBER PteOffset;
1270  NTSTATUS Status;
1271  ULONG QuotaCharge = 0, QuotaExcess = 0;
1272  PMMPTE PointerPte, LastPte;
1273  MMPTE TempPte;
1274  ULONG Granularity = MM_VIRTMEM_GRANULARITY;
1275 
1276  DPRINT("Mapping ARM3 data section\n");
1277 
1278  /* Get the segment for this section */
1279  Segment = ControlArea->Segment;
1280 
1281 #ifdef _M_IX86
1282  /* ALlow being less restrictive on x86. */
1283  if (AllocationType & MEM_DOS_LIM)
1284  Granularity = PAGE_SIZE;
1285 #endif
1286 
1287  /* One can only reserve a file-based mapping, not shared memory! */
1288  if ((AllocationType & MEM_RESERVE) && !(ControlArea->FilePointer))
1289  {
1291  }
1292 
1293  /* First, increase the map count. No purging is supported yet */
1294  Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
1295  if (!NT_SUCCESS(Status)) return Status;
1296 
1297  /* Check if the caller specified the view size */
1298  if (!(*ViewSize))
1299  {
1300  /* The caller did not, so pick a 64K aligned view size based on the offset */
1301  SectionOffset->LowPart &= ~(_64K - 1);
1302  *ViewSize = (SIZE_T)(Section->SizeOfSection.QuadPart - SectionOffset->QuadPart);
1303  }
1304  else
1305  {
1306  /* A size was specified, align it to a 64K boundary */
1307  *ViewSize += SectionOffset->LowPart & (_64K - 1);
1308 
1309  /* Align the offset as well to make this an aligned map */
1310  SectionOffset->LowPart &= ~((ULONG)_64K - 1);
1311  }
1312 
1313  /* We must be dealing with a 64KB aligned offset. This is a Windows ASSERT */
1314  ASSERT((SectionOffset->LowPart & ((ULONG)_64K - 1)) == 0);
1315 
1316  /* It's illegal to try to map more than overflows a LONG_PTR */
1317  if (*ViewSize >= MAXLONG_PTR)
1318  {
1319  MiDereferenceControlArea(ControlArea);
1320  return STATUS_INVALID_VIEW_SIZE;
1321  }
1322 
1323  /* Windows ASSERTs for this flag */
1324  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
1325 
1326  /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
1327  ASSERT(ControlArea->u.Flags.Rom == 0);
1328  Subsection = (PSUBSECTION)(ControlArea + 1);
1329 
1330  /* Sections with extended segments are not supported in ARM3 */
1331  ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0);
1332 
1333  /* Within this section, figure out which PTEs will describe the view */
1334  PteOffset = (PFN_NUMBER)(SectionOffset->QuadPart >> PAGE_SHIFT);
1335 
1336  /* The offset must be in this segment's PTE chunk and it must be valid. Windows ASSERTs */
1337  ASSERT(PteOffset < Segment->TotalNumberOfPtes);
1338  ASSERT(((SectionOffset->QuadPart + *ViewSize + PAGE_SIZE - 1) >> PAGE_SHIFT) >= PteOffset);
1339 
1340  /* In ARM3, only one subsection is used for now. It must contain these PTEs */
1341  ASSERT(PteOffset < Subsection->PtesInSubsection);
1342 
1343  /* In ARM3, only page-file backed sections (shared memory) are supported now */
1344  ASSERT(ControlArea->FilePointer == NULL);
1345 
1346  /* Windows ASSERTs for this too -- there must be a subsection base address */
1347  ASSERT(Subsection->SubsectionBase != NULL);
1348 
1349  /* Compute how much commit space the segment will take */
1350  if ((CommitSize) && (Segment->NumberOfCommittedPages < Segment->TotalNumberOfPtes))
1351  {
1352  /* Charge for the maximum pages */
1353  QuotaCharge = BYTES_TO_PAGES(CommitSize);
1354  }
1355 
1356  /* ARM3 does not currently support large pages */
1357  ASSERT(Segment->SegmentFlags.LargePages == 0);
1358 
1359  /* Calculate how many pages the region spans */
1360  ViewSizeInPages = BYTES_TO_PAGES(*ViewSize);
1361 
1362  /* A VAD can now be allocated. Do so and zero it out */
1363  /* FIXME: we are allocating a LONG VAD for ReactOS compatibility only */
1364  ASSERT((AllocationType & MEM_RESERVE) == 0); /* ARM3 does not support this */
1365  Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
1366  if (!Vad)
1367  {
1368  MiDereferenceControlArea(ControlArea);
1370  }
1371 
1372  RtlZeroMemory(Vad, sizeof(MMVAD_LONG));
1373  Vad->u4.Banked = (PVOID)0xDEADBABE;
1374 
1375  /* Write all the data required in the VAD for handling a fault */
1376  Vad->ControlArea = ControlArea;
1377  Vad->u.VadFlags.CommitCharge = 0;
1378  Vad->u.VadFlags.Protection = ProtectionMask;
1379  Vad->u2.VadFlags2.FileOffset = (ULONG)(SectionOffset->QuadPart >> 16);
1380  Vad->u2.VadFlags2.Inherit = (InheritDisposition == ViewShare);
1381  if ((AllocationType & SEC_NO_CHANGE) || (Section->u.Flags.NoChange))
1382  {
1383  /* This isn't really implemented yet, but handle setting the flag */
1384  Vad->u.VadFlags.NoChange = 1;
1385  Vad->u2.VadFlags2.SecNoChange = 1;
1386  }
1387 
1388  /* Finally, write down the first and last prototype PTE */
1389  Vad->FirstPrototypePte = &Subsection->SubsectionBase[PteOffset];
1390  PteOffset += ViewSizeInPages - 1;
1391  ASSERT(PteOffset < Subsection->PtesInSubsection);
1392  Vad->LastContiguousPte = &Subsection->SubsectionBase[PteOffset];
1393 
1394  /* Make sure the prototype PTE ranges make sense, this is a Windows ASSERT */
1396 
1397  /* FIXME: Should setup VAD bitmap */
1398  Status = STATUS_SUCCESS;
1399 
1400  /* Check if anything was committed */
1401  if (QuotaCharge)
1402  {
1403  /* Set the start and end PTE addresses, and pick the template PTE */
1404  PointerPte = Vad->FirstPrototypePte;
1405  LastPte = PointerPte + BYTES_TO_PAGES(CommitSize);
1406  TempPte = Segment->SegmentPteTemplate;
1407 
1408  /* Acquire the commit lock and loop all prototype PTEs to be committed */
1409  KeAcquireGuardedMutex(&MmSectionCommitMutex);
1410  while (PointerPte < LastPte)
1411  {
1412  /* Make sure the PTE is already invalid */
1413  if (PointerPte->u.Long == 0)
1414  {
1415  /* And write the invalid PTE */
1416  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
1417  }
1418  else
1419  {
1420  /* The PTE is valid, so skip it */
1421  QuotaExcess++;
1422  }
1423 
1424  /* Move to the next PTE */
1425  PointerPte++;
1426  }
1427 
1428  /* Now check how many pages exactly we committed, and update accounting */
1429  ASSERT(QuotaCharge >= QuotaExcess);
1430  QuotaCharge -= QuotaExcess;
1431  Segment->NumberOfCommittedPages += QuotaCharge;
1432  ASSERT(Segment->NumberOfCommittedPages <= Segment->TotalNumberOfPtes);
1433 
1434  /* Now that we're done, release the lock */
1435  KeReleaseGuardedMutex(&MmSectionCommitMutex);
1436  }
1437 
1438  /* Is it SEC_BASED, or did the caller manually specify an address? */
1439  if (*BaseAddress != NULL)
1440  {
1441  /* Just align what the caller gave us */
1442  StartAddress = ALIGN_DOWN_BY((ULONG_PTR)*BaseAddress, Granularity);
1443  }
1444  else if (Section->Address.StartingVpn != 0)
1445  {
1446  /* It is a SEC_BASED mapping, use the address that was generated */
1447  StartAddress = Section->Address.StartingVpn + SectionOffset->LowPart;
1448  }
1449  else
1450  {
1451  StartAddress = 0;
1452  }
1453 
1454  /* Insert the VAD */
1455  Status = MiInsertVadEx((PMMVAD)Vad,
1456  &StartAddress,
1457  ViewSizeInPages * PAGE_SIZE,
1458  MAXULONG_PTR >> ZeroBits,
1459  Granularity,
1460  AllocationType);
1461  if (!NT_SUCCESS(Status))
1462  {
1463  return Status;
1464  }
1465 
1466  /* Windows stores this for accounting purposes, do so as well */
1467  if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
1468 
1469  /* Finally, let the caller know where, and for what size, the view was mapped */
1470  *ViewSize = ViewSizeInPages * PAGE_SIZE;
1471  *BaseAddress = (PVOID)StartAddress;
1472  DPRINT("Start and region: 0x%p, 0x%p\n", *BaseAddress, *ViewSize);
1473  return STATUS_SUCCESS;
1474 }
1475 
1476 VOID
1477 NTAPI
1479 {
1480  /* ReactOS only supports systems with 4K pages and 4K sectors */
1481  ASSERT(Subsection->u.SubsectionFlags.SectorEndOffset == 0);
1482 
1483  /* Therefore, then number of PTEs should be equal to the number of sectors */
1484  if (Subsection->NumberOfFullSectors != Subsection->PtesInSubsection)
1485  {
1486  /* Break and warn if this is inconsistent */
1487  DPRINT1("Mm: Subsection inconsistent (%x vs %x)\n",
1488  Subsection->NumberOfFullSectors, Subsection->PtesInSubsection);
1489  DbgBreakPoint();
1490  }
1491 }
1492 
1493 NTSTATUS
1494 NTAPI
1496  OUT PSEGMENT *Segment,
1500  IN ULONG IgnoreFileSizing)
1501 {
1502  /* Not yet implemented */
1503  ASSERT(FALSE);
1504  *Segment = NULL;
1505  return STATUS_NOT_IMPLEMENTED;
1506 }
1507 
1508 NTSTATUS
1509 NTAPI
1512  IN ULONG ProtectionMask,
1514 {
1515  SIZE_T SizeLimit;
1516  PFN_COUNT PteCount;
1517  PMMPTE PointerPte;
1518  MMPTE TempPte;
1519  PCONTROL_AREA ControlArea;
1520  PSEGMENT NewSegment;
1521  PSUBSECTION Subsection;
1522  PAGED_CODE();
1523 
1524  /* No large pages in ARM3 yet */
1525  ASSERT((AllocationAttributes & SEC_LARGE_PAGES) == 0);
1526 
1527  /* Pagefile-backed sections need a known size */
1528  if (!(*MaximumSize)) return STATUS_INVALID_PARAMETER_4;
1529 
1530  /* Calculate the maximum size possible, given the Prototype PTEs we'll need */
1531  SizeLimit = MAXULONG_PTR - sizeof(SEGMENT);
1532  SizeLimit /= sizeof(MMPTE);
1533  SizeLimit <<= PAGE_SHIFT;
1534 
1535  /* Fail if this size is too big */
1536  if (*MaximumSize > SizeLimit) return STATUS_SECTION_TOO_BIG;
1537 
1538  /* Calculate how many Prototype PTEs will be needed */
1539  PteCount = (PFN_COUNT)((*MaximumSize + PAGE_SIZE - 1) >> PAGE_SHIFT);
1540 
1541  /* For commited memory, we must have a valid protection mask */
1542  if (AllocationAttributes & SEC_COMMIT) ASSERT(ProtectionMask != 0);
1543 
1544  /* The segment contains all the Prototype PTEs, allocate it in paged pool */
1545  NewSegment = ExAllocatePoolWithTag(PagedPool,
1546  sizeof(SEGMENT) +
1547  sizeof(MMPTE) * (PteCount - 1),
1548  'tSmM');
1549  ASSERT(NewSegment);
1550  *Segment = NewSegment;
1551 
1552  /* Now allocate the control area, which has the subsection structure */
1553  ControlArea = ExAllocatePoolWithTag(NonPagedPool,
1554  sizeof(CONTROL_AREA) + sizeof(SUBSECTION),
1555  'tCmM');
1556  ASSERT(ControlArea);
1557 
1558  /* And zero it out, filling the basic segmnet pointer and reference fields */
1559  RtlZeroMemory(ControlArea, sizeof(CONTROL_AREA) + sizeof(SUBSECTION));
1560  ControlArea->Segment = NewSegment;
1561  ControlArea->NumberOfSectionReferences = 1;
1562  ControlArea->NumberOfUserReferences = 1;
1563 
1564  /* Convert allocation attributes to control area flags */
1565  if (AllocationAttributes & SEC_BASED) ControlArea->u.Flags.Based = 1;
1566  if (AllocationAttributes & SEC_RESERVE) ControlArea->u.Flags.Reserve = 1;
1567  if (AllocationAttributes & SEC_COMMIT) ControlArea->u.Flags.Commit = 1;
1568 
1569  /* We just allocated it */
1570  ControlArea->u.Flags.BeingCreated = 1;
1571 
1572  /* The subsection follows, write the mask, PTE count and point back to the CA */
1573  Subsection = (PSUBSECTION)(ControlArea + 1);
1574  Subsection->ControlArea = ControlArea;
1575  Subsection->PtesInSubsection = PteCount;
1576  Subsection->u.SubsectionFlags.Protection = ProtectionMask;
1577 
1578  /* Zero out the segment's prototype PTEs, and link it with the control area */
1579  PointerPte = &NewSegment->ThePtes[0];
1580  RtlZeroMemory(NewSegment, sizeof(SEGMENT));
1581  NewSegment->PrototypePte = PointerPte;
1582  NewSegment->ControlArea = ControlArea;
1583 
1584  /* Save some extra accounting data for the segment as well */
1585  NewSegment->u1.CreatingProcess = PsGetCurrentProcess();
1586  NewSegment->SizeOfSegment = PteCount * PAGE_SIZE;
1587  NewSegment->TotalNumberOfPtes = PteCount;
1588  NewSegment->NonExtendedPtes = PteCount;
1589 
1590  /* The subsection's base address is the first Prototype PTE in the segment */
1591  Subsection->SubsectionBase = PointerPte;
1592 
1593  /* Start with an empty PTE, unless this is a commit operation */
1594  TempPte.u.Long = 0;
1595  if (AllocationAttributes & SEC_COMMIT)
1596  {
1597  /* In which case, write down the protection mask in the Prototype PTEs */
1598  TempPte.u.Soft.Protection = ProtectionMask;
1599 
1600  /* For accounting, also mark these pages as being committed */
1601  NewSegment->NumberOfCommittedPages = PteCount;
1602  }
1603 
1604  /* The template PTE itself for the segment should also have the mask set */
1605  NewSegment->SegmentPteTemplate.u.Soft.Protection = ProtectionMask;
1606 
1607  /* Write out the prototype PTEs, for now they're simply demand zero */
1608 #ifdef _WIN64
1609  RtlFillMemoryUlonglong(PointerPte, PteCount * sizeof(MMPTE), TempPte.u.Long);
1610 #else
1611  RtlFillMemoryUlong(PointerPte, PteCount * sizeof(MMPTE), TempPte.u.Long);
1612 #endif
1613  return STATUS_SUCCESS;
1614 }
1615 
1616 NTSTATUS
1617 NTAPI
1619  IN PVOID Address,
1621 {
1622  PMMVAD Vad;
1623  PCONTROL_AREA ControlArea;
1624 
1625  /* Get the VAD */
1626  Vad = MiLocateAddress(Address);
1627  if (Vad == NULL)
1628  {
1629  /* Fail, the address does not exist */
1630  DPRINT1("Invalid address\n");
1631  return STATUS_INVALID_ADDRESS;
1632  }
1633 
1634  /* Check if this is a RosMm memory area */
1635  if (Vad->u.VadFlags.Spare != 0)
1636  {
1638  PROS_SECTION_OBJECT Section;
1639 
1640  /* Check if it's a section view (RosMm section) */
1641  if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
1642  {
1643  /* Get the section pointer to the SECTION_OBJECT */
1644  Section = MemoryArea->Data.SectionData.Section;
1645  *FileObject = Section->FileObject;
1646  }
1647  else
1648  {
1649  ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
1650  DPRINT1("Address is a cache section!\n");
1651  return STATUS_SECTION_NOT_IMAGE;
1652  }
1653  }
1654  else
1655  {
1656  /* Make sure it's not a VM VAD */
1657  if (Vad->u.VadFlags.PrivateMemory == 1)
1658  {
1659  DPRINT1("Address is not a section\n");
1660  return STATUS_SECTION_NOT_IMAGE;
1661  }
1662 
1663  /* Get the control area */
1664  ControlArea = Vad->ControlArea;
1665  if (!(ControlArea) || !(ControlArea->u.Flags.Image))
1666  {
1667  DPRINT1("Address is not a section\n");
1668  return STATUS_SECTION_NOT_IMAGE;
1669  }
1670 
1671  /* Get the file object */
1672  *FileObject = ControlArea->FilePointer;
1673  }
1674 
1675  /* Return success */
1676  return STATUS_SUCCESS;
1677 }
1678 
1680 NTAPI
1682 {
1683  PSECTION_OBJECT Section;
1685  ASSERT(SectionObject != NULL);
1686 
1687  /* Check if it's an ARM3, or ReactOS section */
1688  if (MiIsRosSectionObject(SectionObject) == FALSE)
1689  {
1690  /* Return the file pointer stored in the control area */
1691  Section = SectionObject;
1692  return Section->Segment->ControlArea->FilePointer;
1693  }
1694 
1695  /* Return the file object */
1696  return ((PROS_SECTION_OBJECT)SectionObject)->FileObject;
1697 }
1698 
1699 static
1702  _In_ PMMVAD Vad)
1703 {
1704  PCONTROL_AREA ControlArea;
1706 
1707  /* Check if this is a RosMm memory area */
1708  if (Vad->u.VadFlags.Spare != 0)
1709  {
1711  PROS_SECTION_OBJECT Section;
1712 
1713  /* Check if it's a section view (RosMm section) */
1714  if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
1715  {
1716  /* Get the section pointer to the SECTION_OBJECT */
1717  Section = MemoryArea->Data.SectionData.Section;
1718  FileObject = Section->FileObject;
1719  }
1720  else
1721  {
1722  ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
1723  DPRINT1("VAD is a cache section!\n");
1724  return NULL;
1725  }
1726  }
1727  else
1728  {
1729  /* Make sure it's not a VM VAD */
1730  if (Vad->u.VadFlags.PrivateMemory == 1)
1731  {
1732  DPRINT1("VAD is not a section\n");
1733  return NULL;
1734  }
1735 
1736  /* Get the control area */
1737  ControlArea = Vad->ControlArea;
1738  if ((ControlArea == NULL) || !ControlArea->u.Flags.Image)
1739  {
1740  DPRINT1("Address is not a section\n");
1741  return NULL;
1742  }
1743 
1744  /* Get the file object */
1745  FileObject = ControlArea->FilePointer;
1746  }
1747 
1748  /* Return the file object */
1749  return FileObject;
1750 }
1751 
1752 VOID
1753 NTAPI
1755 {
1757 
1758  /* Get the section object of this process*/
1759  SectionObject = PsGetCurrentProcess()->SectionObject;
1760  ASSERT(SectionObject != NULL);
1761  ASSERT(MiIsRosSectionObject(SectionObject) == TRUE);
1762 
1763  /* Return the image information */
1764  *ImageInformation = ((PROS_SECTION_OBJECT)SectionObject)->ImageSection->ImageInformation;
1765 }
1766 
1767 NTSTATUS
1768 NTAPI
1771 {
1772  POBJECT_NAME_INFORMATION ObjectNameInfo;
1773  NTSTATUS Status;
1775 
1776  /* Allocate memory for our structure */
1777  ObjectNameInfo = ExAllocatePoolWithTag(PagedPool, 1024, TAG_MM);
1778  if (!ObjectNameInfo) return STATUS_NO_MEMORY;
1779 
1780  /* Query the name */
1781  Status = ObQueryNameString(FileObject,
1782  ObjectNameInfo,
1783  1024,
1784  &ReturnLength);
1785  if (!NT_SUCCESS(Status))
1786  {
1787  /* Failed, free memory */
1788  DPRINT1("Name query failed\n");
1789  ExFreePoolWithTag(ObjectNameInfo, TAG_MM);
1790  *ModuleName = NULL;
1791  return Status;
1792  }
1793 
1794  /* Success */
1795  *ModuleName = ObjectNameInfo;
1796  return STATUS_SUCCESS;
1797 }
1798 
1799 NTSTATUS
1800 NTAPI
1803 {
1805 
1806  /* Make sure it's an image section */
1807  if (MiIsRosSectionObject(Section) == FALSE)
1808  {
1809  /* Check ARM3 Section flag */
1810  if (((PSECTION)Section)->u.Flags.Image == 0)
1811  {
1812  /* It's not, fail */
1813  DPRINT1("Not an image section\n");
1814  return STATUS_SECTION_NOT_IMAGE;
1815  }
1816  }
1817  else if (!(((PROS_SECTION_OBJECT)Section)->AllocationAttributes & SEC_IMAGE))
1818  {
1819  /* It's not, fail */
1820  DPRINT1("Not an image section\n");
1821  return STATUS_SECTION_NOT_IMAGE;
1822  }
1823 
1824  /* Get the file object */
1825  FileObject = MmGetFileObjectForSection(Section);
1826  return MmGetFileNameForFileObject(FileObject, ModuleName);
1827 }
1828 
1829 NTSTATUS
1830 NTAPI
1833 {
1834  POBJECT_NAME_INFORMATION ModuleNameInformation;
1836  NTSTATUS Status;
1837  PMMVAD Vad;
1839 
1840  /* Lock address space */
1841  AddressSpace = MmGetCurrentAddressSpace();
1842  MmLockAddressSpace(AddressSpace);
1843 
1844  /* Get the VAD */
1845  Vad = MiLocateAddress(Address);
1846  if (Vad == NULL)
1847  {
1848  /* Fail, the address does not exist */
1849  DPRINT1("No VAD at address %p\n", Address);
1850  MmUnlockAddressSpace(AddressSpace);
1851  return STATUS_INVALID_ADDRESS;
1852  }
1853 
1854  /* Get the file object pointer for the VAD */
1855  FileObject = MiGetFileObjectForVad(Vad);
1856  if (FileObject == NULL)
1857  {
1858  DPRINT1("Failed to get file object for Address %p\n", Address);
1859  MmUnlockAddressSpace(AddressSpace);
1860  return STATUS_SECTION_NOT_IMAGE;
1861  }
1862 
1863  /* Reference the file object */
1864  ObReferenceObject(FileObject);
1865 
1866  /* Unlock address space */
1867  MmUnlockAddressSpace(AddressSpace);
1868 
1869  /* Get the filename of the file object */
1870  Status = MmGetFileNameForFileObject(FileObject, &ModuleNameInformation);
1871 
1872  /* Dereference the file object */
1873  ObDereferenceObject(FileObject);
1874 
1875  /* Check if we were able to get the file object name */
1876  if (NT_SUCCESS(Status))
1877  {
1878  /* Init modulename */
1879  RtlCreateUnicodeString(ModuleName, ModuleNameInformation->Name.Buffer);
1880 
1881  /* Free temp taged buffer from MmGetFileNameForFileObject() */
1882  ExFreePoolWithTag(ModuleNameInformation, TAG_MM);
1883  DPRINT("Found ModuleName %S by address %p\n", ModuleName->Buffer, Address);
1884  }
1885 
1886  /* Return status */
1887  return Status;
1888 }
1889 
1890 NTSTATUS
1891 NTAPI
1894  OUT PVOID MemoryInformation,
1895  IN SIZE_T MemoryInformationLength,
1897 {
1899  NTSTATUS Status;
1900  WCHAR ModuleFileNameBuffer[MAX_PATH] = {0};
1902  PMEMORY_SECTION_NAME SectionName = NULL;
1904 
1905  Status = ObReferenceObjectByHandle(ProcessHandle,
1907  NULL,
1908  PreviousMode,
1909  (PVOID*)(&Process),
1910  NULL);
1911 
1912  if (!NT_SUCCESS(Status))
1913  {
1914  DPRINT("MiQueryMemorySectionName: ObReferenceObjectByHandle returned %x\n",Status);
1915  return Status;
1916  }
1917 
1918  RtlInitEmptyUnicodeString(&ModuleFileName, ModuleFileNameBuffer, sizeof(ModuleFileNameBuffer));
1919  Status = MmGetFileNameForAddress(BaseAddress, &ModuleFileName);
1920 
1921  if (NT_SUCCESS(Status))
1922  {
1923  SectionName = MemoryInformation;
1924  if (PreviousMode != KernelMode)
1925  {
1926  _SEH2_TRY
1927  {
1928  RtlInitUnicodeString(&SectionName->SectionFileName, SectionName->NameBuffer);
1929  SectionName->SectionFileName.MaximumLength = (USHORT)MemoryInformationLength;
1930  RtlCopyUnicodeString(&SectionName->SectionFileName, &ModuleFileName);
1931 
1932  if (ReturnLength) *ReturnLength = ModuleFileName.Length;
1933 
1934  }
1936  {
1937  Status = _SEH2_GetExceptionCode();
1938  }
1939  _SEH2_END;
1940  }
1941  else
1942  {
1943  RtlInitUnicodeString(&SectionName->SectionFileName, SectionName->NameBuffer);
1944  SectionName->SectionFileName.MaximumLength = (USHORT)MemoryInformationLength;
1945  RtlCopyUnicodeString(&SectionName->SectionFileName, &ModuleFileName);
1946 
1947  if (ReturnLength) *ReturnLength = ModuleFileName.Length;
1948 
1949  }
1950  }
1951  ObDereferenceObject(Process);
1952  return Status;
1953 }
1954 
1955 VOID
1956 NTAPI
1958  IN PMMPTE PointerPte,
1959  IN ULONG ProtectionMask,
1960  IN PMMPFN Pfn1,
1961  IN BOOLEAN UpdateDirty)
1962 {
1963  MMPTE TempPte, PreviousPte;
1964  KIRQL OldIrql;
1965  BOOLEAN RebuildPte = FALSE;
1966 
1967  //
1968  // User for sanity checking later on
1969  //
1970  PreviousPte = *PointerPte;
1971 
1972  //
1973  // Build the PTE and acquire the PFN lock
1974  //
1975  MI_MAKE_HARDWARE_PTE_USER(&TempPte,
1976  PointerPte,
1977  ProtectionMask,
1978  PreviousPte.u.Hard.PageFrameNumber);
1980 
1981  //
1982  // We don't support I/O mappings in this path yet
1983  //
1984  ASSERT(Pfn1 != NULL);
1985  ASSERT(Pfn1->u3.e1.CacheAttribute != MiWriteCombined);
1986 
1987  //
1988  // Make sure new protection mask doesn't get in conflict and fix it if it does
1989  //
1990  if (Pfn1->u3.e1.CacheAttribute == MiCached)
1991  {
1992  //
1993  // This is a cached PFN
1994  //
1995  if (ProtectionMask & (MM_NOCACHE | MM_NOACCESS))
1996  {
1997  RebuildPte = TRUE;
1998  ProtectionMask &= ~(MM_NOCACHE | MM_NOACCESS);
1999  }
2000  }
2001  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
2002  {
2003  //
2004  // This is a non-cached PFN
2005  //
2006  if ((ProtectionMask & (MM_NOCACHE | MM_NOACCESS)) != MM_NOCACHE)
2007  {
2008  RebuildPte = TRUE;
2009  ProtectionMask &= ~MM_NOACCESS;
2010  ProtectionMask |= MM_NOCACHE;
2011  }
2012  }
2013 
2014  if (RebuildPte)
2015  {
2016  MI_MAKE_HARDWARE_PTE_USER(&TempPte,
2017  PointerPte,
2018  ProtectionMask,
2019  PreviousPte.u.Hard.PageFrameNumber);
2020  }
2021 
2022  //
2023  // Write the new PTE, making sure we are only changing the bits
2024  //
2025  MI_UPDATE_VALID_PTE(PointerPte, TempPte);
2026 
2027  //
2028  // Flush the TLB
2029  //
2030  ASSERT(PreviousPte.u.Hard.Valid == 1);
2031  KeFlushCurrentTb();
2032  ASSERT(PreviousPte.u.Hard.Valid == 1);
2033 
2034  //
2035  // Windows updates the relevant PFN1 information, we currently don't.
2036  //
2037  if (UpdateDirty && PreviousPte.u.Hard.Dirty)
2038  {
2039  if (!Pfn1->u3.e1.Modified)
2040  {
2041  DPRINT1("FIXME: Mark PFN as dirty\n");
2042  }
2043  }
2044 
2045  //
2046  // Not supported in ARM3
2047  //
2048  ASSERT(FoundVad->u.VadFlags.VadType != VadWriteWatch);
2049 
2050  //
2051  // Release the PFN lock, we are done
2052  //
2054 }
2055 
2056 //
2057 // NOTE: This function gets a lot more complicated if we want Copy-on-Write support
2058 //
2059 NTSTATUS
2060 NTAPI
2062  IN PMMVAD FoundVad,
2063  IN PVOID StartingAddress,
2064  IN PVOID EndingAddress,
2066  OUT PULONG CapturedOldProtect,
2067  IN ULONG DontCharge,
2068  OUT PULONG Locked)
2069 {
2070  PMMPTE PointerPte, LastPte;
2071  MMPTE TempPte, PteContents;
2072  PMMPDE PointerPde;
2073  PMMPFN Pfn1;
2074  ULONG ProtectionMask, QuotaCharge = 0;
2076  PAGED_CODE();
2077 
2078  //
2079  // Tell caller nothing is being locked
2080  //
2081  *Locked = FALSE;
2082 
2083  //
2084  // This function should only be used for section VADs. Windows ASSERT */
2085  //
2086  ASSERT(FoundVad->u.VadFlags.PrivateMemory == 0);
2087 
2088  //
2089  // We don't support these features in ARM3
2090  //
2091  ASSERT(FoundVad->u.VadFlags.VadType != VadImageMap);
2092  ASSERT(FoundVad->u2.VadFlags2.CopyOnWrite == 0);
2093 
2094  //
2095  // Convert and validate the protection mask
2096  //
2097  ProtectionMask = MiMakeProtectionMask(NewProtect);
2098  if (ProtectionMask == MM_INVALID_PROTECTION)
2099  {
2100  DPRINT1("Invalid section protect\n");
2102  }
2103 
2104  //
2105  // Get the PTE and PDE for the address, as well as the final PTE
2106  //
2107  MiLockProcessWorkingSetUnsafe(Process, Thread);
2108  PointerPde = MiAddressToPde(StartingAddress);
2109  PointerPte = MiAddressToPte(StartingAddress);
2110  LastPte = MiAddressToPte(EndingAddress);
2111 
2112  //
2113  // Make the PDE valid, and check the status of the first PTE
2114  //
2115  MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
2116  if (PointerPte->u.Long)
2117  {
2118  //
2119  // Not supported in ARM3
2120  //
2121  ASSERT(FoundVad->u.VadFlags.VadType != VadRotatePhysical);
2122 
2123  //
2124  // Capture the page protection and make the PDE valid
2125  //
2126  *CapturedOldProtect = MiGetPageProtection(PointerPte);
2127  MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
2128  }
2129  else
2130  {
2131  //
2132  // Only pagefile-backed section VADs are supported for now
2133  //
2134  ASSERT(FoundVad->u.VadFlags.VadType != VadImageMap);
2135 
2136  //
2137  // Grab the old protection from the VAD itself
2138  //
2139  *CapturedOldProtect = MmProtectToValue[FoundVad->u.VadFlags.Protection];
2140  }
2141 
2142  //
2143  // Loop all the PTEs now
2144  //
2145  MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
2146  while (PointerPte <= LastPte)
2147  {
2148  //
2149  // Check if we've crossed a PDE boundary and make the new PDE valid too
2150  //
2151  if ((((ULONG_PTR)PointerPte) & (SYSTEM_PD_SIZE - 1)) == 0)
2152  {
2153  PointerPde = MiPteToPde(PointerPte);
2154  MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
2155  }
2156 
2157  //
2158  // Capture the PTE and see what we're dealing with
2159  //
2160  PteContents = *PointerPte;
2161  if (PteContents.u.Long == 0)
2162  {
2163  //
2164  // This used to be a zero PTE and it no longer is, so we must add a
2165  // reference to the pagetable.
2166  //
2168 
2169  //
2170  // Create the demand-zero prototype PTE
2171  //
2172  TempPte = PrototypePte;
2173  TempPte.u.Soft.Protection = ProtectionMask;
2174  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2175  }
2176  else if (PteContents.u.Hard.Valid == 1)
2177  {
2178  //
2179  // Get the PFN entry
2180  //
2181  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2182 
2183  //
2184  // We don't support these yet
2185  //
2186  ASSERT((NewProtect & (PAGE_NOACCESS | PAGE_GUARD)) == 0);
2187  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
2188 
2189  //
2190  // Write the protection mask and write it with a TLB flush
2191  //
2192  Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
2193  MiFlushTbAndCapture(FoundVad,
2194  PointerPte,
2195  ProtectionMask,
2196  Pfn1,
2197  TRUE);
2198  }
2199  else
2200  {
2201  //
2202  // We don't support these cases yet
2203  //
2204  ASSERT(PteContents.u.Soft.Prototype == 0);
2205  ASSERT(PteContents.u.Soft.Transition == 0);
2206 
2207  //
2208  // The PTE is already demand-zero, just update the protection mask
2209  //
2210  PointerPte->u.Soft.Protection = ProtectionMask;
2211  }
2212 
2213  PointerPte++;
2214  }
2215 
2216  //
2217  // Unlock the working set and update quota charges if needed, then return
2218  //
2219  MiUnlockProcessWorkingSetUnsafe(Process, Thread);
2220  if ((QuotaCharge > 0) && (!DontCharge))
2221  {
2222  FoundVad->u.VadFlags.CommitCharge -= QuotaCharge;
2223  Process->CommitCharge -= QuotaCharge;
2224  }
2225  return STATUS_SUCCESS;
2226 }
2227 
2228 VOID
2229 NTAPI
2231  IN ULONG NumberOfPtes,
2232  IN PCONTROL_AREA ControlArea,
2233  IN PMMSUPPORT Ws)
2234 {
2235  PMMPTE PointerPte, ProtoPte;//, FirstPte;
2236  PMMPDE PointerPde, SystemMapPde;
2237  PMMPFN Pfn1, Pfn2;
2238  MMPTE PteContents;
2239  KIRQL OldIrql;
2240  DPRINT("Removing mapped view at: 0x%p\n", BaseAddress);
2241 
2242  ASSERT(Ws == NULL);
2243 
2244  /* Get the PTE and loop each one */
2245  PointerPte = MiAddressToPte(BaseAddress);
2246  //FirstPte = PointerPte;
2247  while (NumberOfPtes)
2248  {
2249  /* Check if the PTE is already valid */
2250  PteContents = *PointerPte;
2251  if (PteContents.u.Hard.Valid == 1)
2252  {
2253  /* Get the PFN entry */
2254  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2255 
2256  /* Get the PTE */
2257  PointerPde = MiPteToPde(PointerPte);
2258 
2259  /* Lock the PFN database and make sure this isn't a mapped file */
2261  ASSERT(((Pfn1->u3.e1.PrototypePte) && (Pfn1->OriginalPte.u.Soft.Prototype)) == 0);
2262 
2263  /* Mark the page as modified accordingly */
2264  if (MI_IS_PAGE_DIRTY(&PteContents))
2265  Pfn1->u3.e1.Modified = 1;
2266 
2267  /* Was the PDE invalid */
2268  if (PointerPde->u.Long == 0)
2269  {
2270 #if (_MI_PAGING_LEVELS == 2)
2271  /* Find the system double-mapped PDE that describes this mapping */
2272  SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
2273 
2274  /* Make it valid */
2275  ASSERT(SystemMapPde->u.Hard.Valid == 1);
2276  MI_WRITE_VALID_PDE(PointerPde, *SystemMapPde);
2277 #else
2278  DBG_UNREFERENCED_LOCAL_VARIABLE(SystemMapPde);
2279  ASSERT(FALSE);
2280 #endif
2281  }
2282 
2283  /* Dereference the PDE and the PTE */
2284  Pfn2 = MiGetPfnEntry(PFN_FROM_PTE(PointerPde));
2285  MiDecrementShareCount(Pfn2, PFN_FROM_PTE(PointerPde));
2287  MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
2288 
2289  /* Release the PFN lock */
2291  }
2292  else
2293  {
2294  /* Windows ASSERT */
2295  ASSERT((PteContents.u.Long == 0) || (PteContents.u.Soft.Prototype == 1));
2296 
2297  /* Check if this is a prototype pointer PTE */
2298  if (PteContents.u.Soft.Prototype == 1)
2299  {
2300  /* Get the prototype PTE */
2301  ProtoPte = MiProtoPteToPte(&PteContents);
2302 
2303  /* We don't support anything else atm */
2304  ASSERT(ProtoPte->u.Long == 0);
2305  }
2306  }
2307 
2308  /* Make the PTE into a zero PTE */
2309  PointerPte->u.Long = 0;
2310 
2311  /* Move to the next PTE */
2312  PointerPte++;
2313  NumberOfPtes--;
2314  }
2315 
2316  /* Flush the TLB */
2317  KeFlushCurrentTb();
2318 
2319  /* Acquire the PFN lock */
2321 
2322  /* Decrement the accounting counters */
2323  ControlArea->NumberOfUserReferences--;
2324  ControlArea->NumberOfMappedViews--;
2325 
2326  /* Check if we should destroy the CA and release the lock */
2327  MiCheckControlArea(ControlArea, OldIrql);
2328 }
2329 
2330 ULONG
2331 NTAPI
2333  IN PVOID Base,
2334  OUT PCONTROL_AREA *ControlArea)
2335 {
2336  ULONG Hash, Size, Count = 0;
2337  ULONG_PTR Entry;
2338  PAGED_CODE();
2339 
2340  /* Compute the hash for this entry and loop trying to find it */
2341  Entry = (ULONG_PTR)Base >> 16;
2342  Hash = Entry % Session->SystemSpaceHashKey;
2343  while ((Session->SystemSpaceViewTable[Hash].Entry >> 16) != Entry)
2344  {
2345  /* Check if we overflew past the end of the hash table */
2346  if (++Hash >= Session->SystemSpaceHashSize)
2347  {
2348  /* Reset the hash to zero and keep searching from the bottom */
2349  Hash = 0;
2350  if (++Count == 2)
2351  {
2352  /* But if we overflew twice, then this is not a real mapping */
2353  KeBugCheckEx(DRIVER_UNMAPPING_INVALID_VIEW,
2354  (ULONG_PTR)Base,
2355  1,
2356  0,
2357  0);
2358  }
2359  }
2360  }
2361 
2362  /* One less entry */
2363  Session->SystemSpaceHashEntries--;
2364 
2365  /* Extract the size and clear the entry */
2366  Size = Session->SystemSpaceViewTable[Hash].Entry & 0xFFFF;
2367  Session->SystemSpaceViewTable[Hash].Entry = 0;
2368 
2369  /* Return the control area and the size */
2370  *ControlArea = Session->SystemSpaceViewTable[Hash].ControlArea;
2371  return Size;
2372 }
2373 
2374 NTSTATUS
2375 NTAPI
2378 {
2379  ULONG Size;
2380  PCONTROL_AREA ControlArea;
2381  PAGED_CODE();
2382 
2383  /* Remove this mapping */
2384  KeAcquireGuardedMutex(Session->SystemSpaceViewLockPointer);
2385  Size = MiRemoveFromSystemSpace(Session, MappedBase, &ControlArea);
2386 
2387  /* Clear the bits for this mapping */
2388  RtlClearBits(Session->SystemSpaceBitMap,
2389  (ULONG)(((ULONG_PTR)MappedBase - (ULONG_PTR)Session->SystemSpaceViewStart) >> 16),
2390  Size);
2391 
2392  /* Convert the size from a bit size into the actual size */
2393  Size = Size * (_64K >> PAGE_SHIFT);
2394 
2395  /* Remove the PTEs now */
2396  MiRemoveMappedPtes(MappedBase, Size, ControlArea, NULL);
2397  KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
2398 
2399  /* Return success */
2400  return STATUS_SUCCESS;
2401 }
2402 
2403 /* PUBLIC FUNCTIONS ***********************************************************/
2404 
2405 /*
2406  * @implemented
2407  */
2408 NTSTATUS
2409 NTAPI
2413  IN PLARGE_INTEGER InputMaximumSize,
2416  IN HANDLE FileHandle OPTIONAL,
2417  IN PFILE_OBJECT FileObject OPTIONAL)
2418 {
2419  SECTION Section;
2420  PSECTION NewSection;
2421  PSUBSECTION Subsection;
2422  PSEGMENT NewSegment, Segment;
2423  NTSTATUS Status;
2424  PCONTROL_AREA ControlArea;
2425  ULONG ProtectionMask, ControlAreaSize, Size, NonPagedCharge, PagedCharge;
2427  BOOLEAN FileLock = FALSE, KernelCall = FALSE;
2428  KIRQL OldIrql;
2430  BOOLEAN UserRefIncremented = FALSE;
2431  PVOID PreviousSectionPointer;
2432 
2433  /* Make the same sanity checks that the Nt interface should've validated */
2434  ASSERT((AllocationAttributes & ~(SEC_COMMIT | SEC_RESERVE | SEC_BASED |
2436  SEC_NO_CHANGE)) == 0);
2437  ASSERT((AllocationAttributes & (SEC_COMMIT | SEC_RESERVE | SEC_IMAGE)) != 0);
2438  ASSERT(!((AllocationAttributes & SEC_IMAGE) &&
2439  (AllocationAttributes & (SEC_COMMIT | SEC_RESERVE |
2440  SEC_NOCACHE | SEC_NO_CHANGE))));
2441  ASSERT(!((AllocationAttributes & SEC_COMMIT) && (AllocationAttributes & SEC_RESERVE)));
2442  ASSERT(!((SectionPageProtection & PAGE_NOCACHE) ||
2443  (SectionPageProtection & PAGE_WRITECOMBINE) ||
2444  (SectionPageProtection & PAGE_GUARD) ||
2445  (SectionPageProtection & PAGE_NOACCESS)));
2446 
2447  /* Convert section flag to page flag */
2448  if (AllocationAttributes & SEC_NOCACHE) SectionPageProtection |= PAGE_NOCACHE;
2449 
2450  /* Check to make sure the protection is correct. Nt* does this already */
2451  ProtectionMask = MiMakeProtectionMask(SectionPageProtection);
2452  if (ProtectionMask == MM_INVALID_PROTECTION) return STATUS_INVALID_PAGE_PROTECTION;
2453 
2454  /* Check if this is going to be a data or image backed file section */
2455  if ((FileHandle) || (FileObject))
2456  {
2457  /* These cannot be mapped with large pages */
2458  if (AllocationAttributes & SEC_LARGE_PAGES) return STATUS_INVALID_PARAMETER_6;
2459 
2460  /* For now, only support the mechanism through a file handle */
2461  ASSERT(FileObject == NULL);
2462 
2463  /* Reference the file handle to get the object */
2465  MmMakeFileAccess[ProtectionMask],
2467  PreviousMode,
2468  (PVOID*)&File,
2469  NULL);
2470  if (!NT_SUCCESS(Status)) return Status;
2471 
2472  /* Make sure Cc has been doing its job */
2473  if (!File->SectionObjectPointer)
2474  {
2475  /* This is not a valid file system-based file, fail */
2476  ObDereferenceObject(File);
2478  }
2479 
2480  /* Image-file backed sections are not yet supported */
2481  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2482 
2483  /* Compute the size of the control area, and allocate it */
2484  ControlAreaSize = sizeof(CONTROL_AREA) + sizeof(MSUBSECTION);
2485  ControlArea = ExAllocatePoolWithTag(NonPagedPool, ControlAreaSize, 'aCmM');
2486  if (!ControlArea)
2487  {
2488  ObDereferenceObject(File);
2490  }
2491 
2492  /* Zero it out */
2493  RtlZeroMemory(ControlArea, ControlAreaSize);
2494 
2495  /* Did we get a handle, or an object? */
2496  if (FileHandle)
2497  {
2498  /* We got a file handle so we have to lock down the file */
2499 #if 0
2500  Status = FsRtlAcquireToCreateMappedSection(File, SectionPageProtection);
2501  if (!NT_SUCCESS(Status))
2502  {
2503  ExFreePool(ControlArea);
2504  ObDereferenceObject(File);
2505  return Status;
2506  }
2507 #else
2508  /* ReactOS doesn't support this API yet, so do nothing */
2509  Status = STATUS_SUCCESS;
2510 #endif
2511  /* Update the top-level IRP so that drivers know what's happening */
2513  FileLock = TRUE;
2514  }
2515 
2516  /* Lock the PFN database while we play with the section pointers */
2518 
2519  /* Image-file backed sections are not yet supported */
2520  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2521 
2522  /* There should not already be a control area for this file */
2523  ASSERT(File->SectionObjectPointer->DataSectionObject == NULL);
2524  NewSegment = NULL;
2525 
2526  /* Write down that this CA is being created, and set it */
2527  ControlArea->u.Flags.BeingCreated = TRUE;
2528  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2529  PreviousSectionPointer = File->SectionObjectPointer;
2530  File->SectionObjectPointer->DataSectionObject = ControlArea;
2531 
2532  /* We can release the PFN lock now */
2534 
2535  /* We don't support previously-mapped file */
2536  ASSERT(NewSegment == NULL);
2537 
2538  /* Image-file backed sections are not yet supported */
2539  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2540 
2541  /* So we always create a data file map */
2542  Status = MiCreateDataFileMap(File,
2543  &Segment,
2544  (PSIZE_T)InputMaximumSize,
2545  SectionPageProtection,
2546  AllocationAttributes,
2547  KernelCall);
2548  if (!NT_SUCCESS(Status))
2549  {
2550  /* Lock the PFN database while we play with the section pointers */
2552 
2553  /* Reset the waiting-for-deletion event */
2554  ASSERT(ControlArea->WaitingForDeletion == NULL);
2555  ControlArea->WaitingForDeletion = NULL;
2556 
2557  /* Set the file pointer NULL flag */
2558  ASSERT(ControlArea->u.Flags.FilePointerNull == 0);
2559  ControlArea->u.Flags.FilePointerNull = TRUE;
2560 
2561  /* Delete the data section object */
2562  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2563  File->SectionObjectPointer->DataSectionObject = NULL;
2564 
2565  /* No longer being created */
2566  ControlArea->u.Flags.BeingCreated = FALSE;
2567 
2568  /* We can release the PFN lock now */
2570 
2571  /* Check if we locked and set the IRP */
2572  if (FileLock)
2573  {
2574  /* Undo */
2576  //FsRtlReleaseFile(File);
2577  }
2578 
2579  /* Free the control area and de-ref the file object */
2580  ExFreePool(ControlArea);
2581  ObDereferenceObject(File);
2582 
2583  /* All done */
2584  return Status;
2585  }
2586 
2587  /* On success, we expect this */
2588  ASSERT(PreviousSectionPointer == File->SectionObjectPointer);
2589 
2590  /* Check if a maximum size was specified */
2591  if (!InputMaximumSize->QuadPart)
2592  {
2593  /* Nope, use the segment size */
2594  Section.SizeOfSection.QuadPart = (LONGLONG)Segment->SizeOfSegment;
2595  }
2596  else
2597  {
2598  /* Yep, use the entered size */
2599  Section.SizeOfSection.QuadPart = InputMaximumSize->QuadPart;
2600  }
2601  }
2602  else
2603  {
2604  /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
2605  if (AllocationAttributes & SEC_IMAGE) return STATUS_INVALID_FILE_FOR_SECTION;
2606 
2607  /* Not yet supported */
2608  ASSERT((AllocationAttributes & SEC_LARGE_PAGES) == 0);
2609 
2610  /* So this must be a pagefile-backed section, create the mappings needed */
2611  Status = MiCreatePagingFileMap(&NewSegment,
2612  (PSIZE_T)InputMaximumSize,
2613  ProtectionMask,
2614  AllocationAttributes);
2615  if (!NT_SUCCESS(Status)) return Status;
2616 
2617  /* Set the size here, and read the control area */
2618  Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
2619  ControlArea = NewSegment->ControlArea;
2620 
2621  /* MiCreatePagingFileMap increments user references */
2622  UserRefIncremented = TRUE;
2623  }
2624 
2625  /* Did we already have a segment? */
2626  if (!NewSegment)
2627  {
2628  /* This must be the file path and we created a segment */
2629  NewSegment = Segment;
2630  ASSERT(File != NULL);
2631 
2632  /* Acquire the PFN lock while we set control area flags */
2634 
2635  /* We don't support this race condition yet, so assume no waiters */
2636  ASSERT(ControlArea->WaitingForDeletion == NULL);
2637  ControlArea->WaitingForDeletion = NULL;
2638 
2639  /* Image-file backed sections are not yet supported, nor ROM images */
2640  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2641  ASSERT(Segment->ControlArea->u.Flags.Rom == 0);
2642 
2643  /* Take off the being created flag, and then release the lock */
2644  ControlArea->u.Flags.BeingCreated = FALSE;
2646  }
2647 
2648  /* Check if we locked the file earlier */
2649  if (FileLock)
2650  {
2651  /* Reset the top-level IRP and release the lock */
2653  //FsRtlReleaseFile(File);
2654  FileLock = FALSE;
2655  }
2656 
2657  /* Set the initial section object data */
2658  Section.InitialPageProtection = SectionPageProtection;
2659 
2660  /* The mapping created a control area and segment, save the flags */
2661  Section.Segment = NewSegment;
2662  Section.u.LongFlags = ControlArea->u.LongFlags;
2663 
2664  /* Check if this is a user-mode read-write non-image file mapping */
2665  if (!(FileObject) &&
2666  (SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)) &&
2667  !(ControlArea->u.Flags.Image) &&
2668  (ControlArea->FilePointer))
2669  {
2670  /* Add a reference and set the flag */
2671  Section.u.Flags.UserWritable = TRUE;
2672  InterlockedIncrement((volatile LONG*)&ControlArea->WritableUserReferences);
2673  }
2674 
2675  /* Check for image mappings or page file mappings */
2676  if ((ControlArea->u.Flags.Image) || !(ControlArea->FilePointer))
2677  {
2678  /* Charge the segment size, and allocate a subsection */
2679  PagedCharge = sizeof(SECTION) + NewSegment->TotalNumberOfPtes * sizeof(MMPTE);
2680  Size = sizeof(SUBSECTION);
2681  }
2682  else
2683  {
2684  /* Charge nothing, and allocate a mapped subsection */
2685  PagedCharge = 0;
2686  Size = sizeof(MSUBSECTION);
2687  }
2688 
2689  /* Check if this is a normal CA */
2690  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
2691  ASSERT(ControlArea->u.Flags.Rom == 0);
2692 
2693  /* Charge only a CA, and the subsection is right after */
2694  NonPagedCharge = sizeof(CONTROL_AREA);
2695  Subsection = (PSUBSECTION)(ControlArea + 1);
2696 
2697  /* We only support single-subsection mappings */
2698  NonPagedCharge += Size;
2699  ASSERT(Subsection->NextSubsection == NULL);
2700 
2701  /* Create the actual section object, with enough space for the prototype PTEs */
2702  Status = ObCreateObject(PreviousMode,
2705  PreviousMode,
2706  NULL,
2707  sizeof(SECTION),
2708  PagedCharge,
2709  NonPagedCharge,
2710  (PVOID*)&NewSection);
2711  if (!NT_SUCCESS(Status))
2712  {
2713  /* Check if this is a user-mode read-write non-image file mapping */
2714  if (!(FileObject) &&
2715  (SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)) &&
2716  !(ControlArea->u.Flags.Image) &&
2717  (ControlArea->FilePointer))
2718  {
2719  /* Remove a reference and check the flag */
2720  ASSERT(Section.u.Flags.UserWritable == 1);
2721  InterlockedDecrement((volatile LONG*)&ControlArea->WritableUserReferences);
2722  }
2723 
2724  /* Check if a user reference was added */
2725  if (UserRefIncremented)
2726  {
2727  /* Acquire the PFN lock while we change counters */
2729 
2730  /* Decrement the accounting counters */
2731  ControlArea->NumberOfSectionReferences--;
2732  ASSERT((LONG)ControlArea->NumberOfUserReferences > 0);
2733  ControlArea->NumberOfUserReferences--;
2734 
2735  /* Check if we should destroy the CA and release the lock */
2736  MiCheckControlArea(ControlArea, OldIrql);
2737  }
2738 
2739  /* Return the failure code */
2740  return Status;
2741  }
2742 
2743  /* NOTE: Past this point, all failures will be handled by Ob upon ref->0 */
2744 
2745  /* Now copy the local section object from the stack into this new object */
2746  RtlCopyMemory(NewSection, &Section, sizeof(SECTION));
2747  NewSection->Address.StartingVpn = 0;
2748 
2749  /* For now, only user calls are supported */
2750  ASSERT(KernelCall == FALSE);
2751  NewSection->u.Flags.UserReference = TRUE;
2752 
2753  /* Is this a "based" allocation, in which all mappings are identical? */
2754  if (AllocationAttributes & SEC_BASED)
2755  {
2756  /* Lock the VAD tree during the search */
2757  KeAcquireGuardedMutex(&MmSectionBasedMutex);
2758 
2759  /* Is it a brand new ControArea ? */
2760  if (ControlArea->u.Flags.BeingCreated == 1)
2761  {
2762  ASSERT(ControlArea->u.Flags.Based == 1);
2763  /* Then we must find a global address, top-down */
2765  (ULONG_PTR)MmHighSectionBase,
2766  _64K,
2767  &MmSectionBasedRoot,
2768  (ULONG_PTR*)&ControlArea->Segment->BasedAddress);
2769 
2770  if (!NT_SUCCESS(Status))
2771  {
2772  /* No way to find a valid range. */
2773  KeReleaseGuardedMutex(&MmSectionBasedMutex);
2774  ControlArea->u.Flags.Based = 0;
2775  NewSection->u.Flags.Based = 0;
2776  ObDereferenceObject(NewSection);
2777  return Status;
2778  }
2779 
2780  /* Compute the ending address and insert it into the VAD tree */
2781  NewSection->Address.StartingVpn = (ULONG_PTR)ControlArea->Segment->BasedAddress;
2782  NewSection->Address.EndingVpn = NewSection->Address.StartingVpn + NewSection->SizeOfSection.LowPart - 1;
2783  MiInsertBasedSection(NewSection);
2784  }
2785  else
2786  {
2787  /* 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 !*/
2788  ASSERT(FALSE);
2789  }
2790 
2791  KeReleaseGuardedMutex(&MmSectionBasedMutex);
2792  }
2793 
2794  /* The control area is not being created anymore */
2795  if (ControlArea->u.Flags.BeingCreated == 1)
2796  {
2797  /* Acquire the PFN lock while we set control area flags */
2799 
2800  /* Take off the being created flag, and then release the lock */
2801  ControlArea->u.Flags.BeingCreated = 0;
2802  NewSection->u.Flags.BeingCreated = 0;
2803 
2805  }
2806 
2807  /* Migrate the attribute into a flag */
2808  if (AllocationAttributes & SEC_NO_CHANGE) NewSection->u.Flags.NoChange = TRUE;
2809 
2810  /* If R/W access is not requested, this might eventually become a CoW mapping */
2811  if (!(SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)))
2812  {
2813  NewSection->u.Flags.CopyOnWrite = TRUE;
2814  }
2815 
2816  /* Write down if this was a kernel call */
2817  ControlArea->u.Flags.WasPurged |= KernelCall;
2818  ASSERT(ControlArea->u.Flags.WasPurged == FALSE);
2819 
2820  /* Make sure the segment and the section are the same size, or the section is smaller */
2821  ASSERT((ULONG64)NewSection->SizeOfSection.QuadPart <= NewSection->Segment->SizeOfSegment);
2822 
2823  /* Return the object and the creation status */
2824  *SectionObject = (PVOID)NewSection;
2825  return Status;
2826 }
2827 
2828 /*
2829  * @implemented
2830  */
2831 NTSTATUS
2832 NTAPI
2842  IN ULONG Protect)
2843 {
2846  PSECTION Section;
2847  PCONTROL_AREA ControlArea;
2848  ULONG ProtectionMask;
2849  NTSTATUS Status;
2850  PAGED_CODE();
2851 
2852  /* Get the segment and control area */
2853  Section = (PSECTION)SectionObject;
2854  ControlArea = Section->Segment->ControlArea;
2855 
2856  /* These flags/states are not yet supported by ARM3 */
2857  ASSERT(Section->u.Flags.Image == 0);
2858  ASSERT(Section->u.Flags.NoCache == 0);
2859  ASSERT(Section->u.Flags.WriteCombined == 0);
2860  ASSERT(ControlArea->u.Flags.PhysicalMemory == 0);
2861 
2862  /* FIXME */
2863  if ((AllocationType & MEM_RESERVE) != 0)
2864  {
2865  DPRINT1("MmMapViewOfArm3Section called with MEM_RESERVE, this is not implemented yet!!!\n");
2866  return STATUS_NOT_IMPLEMENTED;
2867  }
2868 
2869  /* Check if the mapping protection is compatible with the create */
2870  if (!MiIsProtectionCompatible(Section->InitialPageProtection, Protect))
2871  {
2872  DPRINT1("Mapping protection is incompatible\n");
2874  }
2875 
2876  /* Check if the offset and size would cause an overflow */
2877  if (((ULONG64)SectionOffset->QuadPart + *ViewSize) <
2879  {
2880  DPRINT1("Section offset overflows\n");
2881  return STATUS_INVALID_VIEW_SIZE;
2882  }
2883 
2884  /* Check if the offset and size are bigger than the section itself */
2885  if (((ULONG64)SectionOffset->QuadPart + *ViewSize) >
2886  (ULONG64)Section->SizeOfSection.QuadPart)
2887  {
2888  DPRINT1("Section offset is larger than section\n");
2889  return STATUS_INVALID_VIEW_SIZE;
2890  }
2891 
2892  /* Check if the caller did not specify a view size */
2893  if (!(*ViewSize))
2894  {
2895  /* Compute it for the caller */
2896  *ViewSize = (SIZE_T)(Section->SizeOfSection.QuadPart - SectionOffset->QuadPart);
2897 
2898  /* Check if it's larger than 4GB or overflows into kernel-mode */
2899  if ((*ViewSize > 0xFFFFFFFF) ||
2901  {
2902  DPRINT1("Section view won't fit\n");
2903  return STATUS_INVALID_VIEW_SIZE;
2904  }
2905  }
2906 
2907  /* Check if the commit size is larger than the view size */
2908  if (CommitSize > *ViewSize)
2909  {
2910  DPRINT1("Attempting to commit more than the view itself\n");
2912  }
2913 
2914  /* Check if the view size is larger than the section */
2915  if (*ViewSize > (ULONG64)Section->SizeOfSection.QuadPart)
2916  {
2917  DPRINT1("The view is larger than the section\n");
2918  return STATUS_INVALID_VIEW_SIZE;
2919  }
2920 
2921  /* Compute and validate the protection mask */
2922  ProtectionMask = MiMakeProtectionMask(Protect);
2923  if (ProtectionMask == MM_INVALID_PROTECTION)
2924  {
2925  DPRINT1("The protection is invalid\n");
2927  }
2928 
2929  /* We only handle pagefile-backed sections, which cannot be writecombined */
2930  if (Protect & PAGE_WRITECOMBINE)
2931  {
2932  DPRINT1("Cannot write combine a pagefile-backed section\n");
2934  }
2935 
2936  /* Start by attaching to the current process if needed */
2937  if (PsGetCurrentProcess() != Process)
2938  {
2939  KeStackAttachProcess(&Process->Pcb, &ApcState);
2940  Attached = TRUE;
2941  }
2942 
2943  /* Do the actual mapping */
2944  Status = MiMapViewOfDataSection(ControlArea,
2945  Process,
2946  BaseAddress,
2947  SectionOffset,
2948  ViewSize,
2949  Section,
2950  InheritDisposition,
2951  ProtectionMask,
2952  CommitSize,
2953  ZeroBits,
2954  AllocationType);
2955 
2956  /* Detach if needed, then return status */
2957  if (Attached) KeUnstackDetachProcess(&ApcState);
2958  return Status;
2959 }
2960 
2961 /*
2962  * @unimplemented
2963  */
2964 BOOLEAN
2965 NTAPI
2967 {
2968  UNIMPLEMENTED;
2969  return FALSE;
2970 }
2971 
2972 /*
2973  * @unimplemented
2974  */
2975 BOOLEAN
2976 NTAPI
2979 {
2980  UNIMPLEMENTED;
2981  return FALSE;
2982 }
2983 
2984 /*
2985  * @implemented
2986  */
2987 NTSTATUS
2988 NTAPI
2990  OUT PVOID *MappedBase,
2992 {
2993  PAGED_CODE();
2994 
2995  // HACK
2996  if (MiIsRosSectionObject(Section))
2997  {
2998  return MmMapViewInSystemSpace(Section, MappedBase, ViewSize);
2999  }
3000 
3001  /* Process must be in a session */
3002  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3003  {
3004  DPRINT1("Process is not in session\n");
3005  return STATUS_NOT_MAPPED_VIEW;
3006  }
3007 
3008  /* Use the system space API, but with the session view instead */
3010  return MiMapViewInSystemSpace(Section,
3012  MappedBase,
3013  ViewSize);
3014 }
3015 
3016 /*
3017  * @implemented
3018  */
3019 NTSTATUS
3020 NTAPI
3022 {
3023  PAGED_CODE();
3024 
3025  // HACK
3026  if (!MI_IS_SESSION_ADDRESS(MappedBase))
3027  {
3028  return MmUnmapViewInSystemSpace(MappedBase);
3029  }
3030 
3031  /* Process must be in a session */
3032  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3033  {
3034  DPRINT1("Proess is not in session\n");
3035  return STATUS_NOT_MAPPED_VIEW;
3036  }
3037 
3038  /* Use the system space API, but with the session view instead */
3041  MappedBase);
3042 }
3043 
3044 /*
3045  * @implemented
3046  */
3047 NTSTATUS
3048 NTAPI
3051 {
3052  return MiUnmapViewOfSection(Process, BaseAddress, 0);
3053 }
3054 
3055 /*
3056  * @implemented
3057  */
3058 NTSTATUS
3059 NTAPI
3061 {
3063  PAGED_CODE();
3064 
3065  /* Was this mapped by RosMm? */
3066  MemoryArea = MmLocateMemoryAreaByAddress(MmGetKernelAddressSpace(), MappedBase);
3067  if ((MemoryArea) && (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3))
3068  {
3069  return MiRosUnmapViewInSystemSpace(MappedBase);
3070  }
3071 
3072  /* It was not, call the ARM3 routine */
3073  return MiUnmapViewInSystemSpace(&MmSession, MappedBase);
3074 }
3075 
3076 /*
3077  * @implemented
3078  */
3079 NTSTATUS
3080 NTAPI
3082  IN SIZE_T ViewSize)
3083 {
3084  ULONG_PTR StartAddress, EndingAddress, Base;
3085  ULONG Hash, Count = 0, Size, QuotaCharge;
3087  PMMPTE LastProtoPte, PointerPte, ProtoPte;
3088  PCONTROL_AREA ControlArea;
3089  PSEGMENT Segment;
3090  PSUBSECTION Subsection;
3091  MMPTE TempPte;
3092  PAGED_CODE();
3093 
3094  /* Make sure the base isn't past the session view range */
3095  if ((MappedBase < MiSessionViewStart) ||
3096  (MappedBase >= (PVOID)((ULONG_PTR)MiSessionViewStart + MmSessionViewSize)))
3097  {
3098  DPRINT1("Base outside of valid range\n");
3100  }
3101 
3102  /* Make sure the size isn't past the session view range */
3104  (ULONG_PTR)MappedBase) < ViewSize)
3105  {
3106  DPRINT1("Size outside of valid range\n");
3108  }
3109 
3110  /* Sanity check */
3111  ASSERT(ViewSize != 0);
3112 
3113  /* Process must be in a session */
3114  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3115  {
3116  DPRINT1("Process is not in session\n");
3117  return STATUS_NOT_MAPPED_VIEW;
3118  }
3119 
3120  /* Compute the correctly aligned base and end addresses */
3121  StartAddress = (ULONG_PTR)PAGE_ALIGN(MappedBase);
3122  EndingAddress = ((ULONG_PTR)MappedBase + ViewSize - 1) | (PAGE_SIZE - 1);
3123 
3124  /* Sanity check and grab the session */
3126  Session = &MmSessionSpace->Session;
3127 
3128  /* Get the hash entry for this allocation */
3129  Hash = (StartAddress >> 16) % Session->SystemSpaceHashKey;
3130 
3131  /* Lock system space */
3133 
3134  /* Loop twice so we can try rolling over if needed */
3135  while (TRUE)
3136  {
3137  /* Extract the size and base addresses from the entry */
3138  Base = Session->SystemSpaceViewTable[Hash].Entry & ~0xFFFF;
3139  Size = Session->SystemSpaceViewTable[Hash].Entry & 0xFFFF;
3140 
3141  /* Convert the size to bucket chunks */
3143 
3144  /* Bail out if this entry fits in here */
3145  if ((StartAddress >= Base) && (EndingAddress < (Base + Size))) break;
3146 
3147  /* Check if we overflew past the end of the hash table */
3148  if (++Hash >= Session->SystemSpaceHashSize)
3149  {
3150  /* Reset the hash to zero and keep searching from the bottom */
3151  Hash = 0;
3152  if (++Count == 2)
3153  {
3154  /* But if we overflew twice, then this is not a real mapping */
3155  KeBugCheckEx(DRIVER_UNMAPPING_INVALID_VIEW,
3156  Base,
3157  2,
3158  0,
3159  0);
3160  }
3161  }
3162  }
3163 
3164  /* Make sure the view being mapped is not file-based */
3165  ControlArea = Session->SystemSpaceViewTable[Hash].ControlArea;
3166  if (ControlArea->FilePointer != NULL)
3167  {
3168  /* It is, so we have to bail out */
3169  DPRINT1("Only page-filed backed sections can be commited\n");
3171  return STATUS_ALREADY_COMMITTED;
3172  }
3173 
3174  /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
3175  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
3176  ASSERT(ControlArea->u.Flags.Rom == 0);
3177  Subsection = (PSUBSECTION)(ControlArea + 1);
3178 
3179  /* Get the start and end PTEs -- make sure the end PTE isn't past the end */
3180  ProtoPte = Subsection->SubsectionBase + ((StartAddress - Base) >> PAGE_SHIFT);
3181  QuotaCharge = MiAddressToPte(EndingAddress) - MiAddressToPte(StartAddress) + 1;
3182  LastProtoPte = ProtoPte + QuotaCharge;
3183  if (LastProtoPte >= Subsection->SubsectionBase + Subsection->PtesInSubsection)
3184  {
3185  DPRINT1("PTE is out of bounds\n");
3188  }
3189 
3190  /* Acquire the commit lock and count all the non-committed PTEs */
3191  KeAcquireGuardedMutexUnsafe(&MmSectionCommitMutex);
3192  PointerPte = ProtoPte;
3193  while (PointerPte < LastProtoPte)
3194  {
3195  if (PointerPte->u.Long) QuotaCharge--;
3196  PointerPte++;
3197  }
3198 
3199  /* Was everything committed already? */
3200  if (!QuotaCharge)
3201  {
3202  /* Nothing to do! */
3203  KeReleaseGuardedMutexUnsafe(&MmSectionCommitMutex);
3205  return STATUS_SUCCESS;
3206  }
3207 
3208  /* Pick the segment and template PTE */
3209  Segment = ControlArea->Segment;
3210  TempPte = Segment->SegmentPteTemplate;
3211  ASSERT(TempPte.u.Long != 0);
3212 
3213  /* Loop all prototype PTEs to be committed */
3214  PointerPte = ProtoPte;
3215  while (PointerPte < LastProtoPte)
3216  {
3217  /* Make sure the PTE is already invalid */
3218  if (PointerPte->u.Long == 0)
3219  {
3220  /* And write the invalid PTE */
3221  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
3222  }
3223 
3224  /* Move to the next PTE */
3225  PointerPte++;
3226  }
3227 
3228  /* Check if we had at least one page charged */
3229  if (QuotaCharge)
3230  {
3231  /* Update the accounting data */
3232  Segment->NumberOfCommittedPages += QuotaCharge;
3234  }
3235 
3236  /* Release all */
3237  KeReleaseGuardedMutexUnsafe(&MmSectionCommitMutex);
3239  return STATUS_SUCCESS;
3240 }
3241 
3242 VOID
3243 NTAPI
3245 {
3247  PCONTROL_AREA ControlArea;
3248  KIRQL OldIrql;
3249 
3250  SectionObject = (PSECTION)ObjectBody;
3251 
3252  if (SectionObject->u.Flags.Based == 1)
3253  {
3254  /* Remove the node from the global section address tree */
3255  KeAcquireGuardedMutex(&MmSectionBasedMutex);
3256  MiRemoveNode(&SectionObject->Address, &MmSectionBasedRoot);
3257  KeReleaseGuardedMutex(&MmSectionBasedMutex);
3258  }
3259 
3260  /* Lock the PFN database */
3262 
3263  ASSERT(SectionObject->Segment);
3264  ASSERT(SectionObject->Segment->ControlArea);
3265 
3266  ControlArea = SectionObject->Segment->ControlArea;
3267 
3268  /* Dereference */
3269  ControlArea->NumberOfSectionReferences--;
3270  ControlArea->NumberOfUserReferences--;
3271 
3272  ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
3273 
3274  /* Check it. It will delete it if there is no more reference to it */
3275  MiCheckControlArea(ControlArea, OldIrql);
3276 }
3277 
3278 ULONG
3279 NTAPI
3281 {
3282  UNIMPLEMENTED;
3283  return 0;
3284 }
3285 
3286 /* SYSTEM CALLS ***************************************************************/
3287 
3288 NTSTATUS
3289 NTAPI
3290 NtAreMappedFilesTheSame(IN PVOID File1MappedAsAnImage,
3291  IN PVOID File2MappedAsFile)
3292 {
3294  PMMVAD Vad1, Vad2;
3295  PFILE_OBJECT FileObject1, FileObject2;
3296  NTSTATUS Status;
3297 
3298  /* Lock address space */
3299  AddressSpace = MmGetCurrentAddressSpace();
3300  MmLockAddressSpace(AddressSpace);
3301 
3302  /* Get the VAD for Address 1 */
3303  Vad1 = MiLocateAddress(File1MappedAsAnImage);
3304  if (Vad1 == NULL)
3305  {
3306  /* Fail, the address does not exist */
3307  DPRINT1("No VAD at address 1 %p\n", File1MappedAsAnImage);
3308  Status = STATUS_INVALID_ADDRESS;
3309  goto Exit;
3310  }
3311 
3312  /* Get the VAD for Address 2 */
3313  Vad2 = MiLocateAddress(File2MappedAsFile);
3314  if (Vad2 == NULL)
3315  {
3316  /* Fail, the address does not exist */
3317  DPRINT1("No VAD at address 2 %p\n", File2MappedAsFile);
3318  Status = STATUS_INVALID_ADDRESS;
3319  goto Exit;
3320  }
3321 
3322  /* Get the file object pointer for VAD 1 */
3323  FileObject1 = MiGetFileObjectForVad(Vad1);
3324  if (FileObject1 == NULL)
3325  {
3326  DPRINT1("Failed to get file object for Address 1 %p\n", File1MappedAsAnImage);
3328  goto Exit;
3329  }
3330 
3331  /* Get the file object pointer for VAD 2 */
3332  FileObject2 = MiGetFileObjectForVad(Vad2);
3333  if (FileObject2 == NULL)
3334  {
3335  DPRINT1("Failed to get file object for Address 2 %p\n", File2MappedAsFile);
3337  goto Exit;
3338  }
3339 
3340  /* Make sure Vad1 is an image mapping */
3341  if (Vad1->u.VadFlags.VadType != VadImageMap)
3342  {
3343  DPRINT1("Address 1 (%p) is not an image mapping\n", File1MappedAsAnImage);
3344  Status = STATUS_NOT_SAME_DEVICE;
3345  goto Exit;
3346  }
3347 
3348  /* SectionObjectPointer is equal if the files are equal */
3349  if (FileObject1->SectionObjectPointer == FileObject2->SectionObjectPointer)
3350  {
3351  Status = STATUS_SUCCESS;
3352  }
3353  else
3354  {
3355  Status = STATUS_NOT_SAME_DEVICE;
3356  }
3357 
3358 Exit:
3359  /* Unlock address space */
3360  MmUnlockAddressSpace(AddressSpace);
3361  return Status;
3362 }
3363 
3364 /*
3365  * @implemented
3366  */
3367 NTSTATUS
3368 NTAPI
3372  IN PLARGE_INTEGER MaximumSize OPTIONAL,
3373  IN ULONG SectionPageProtection OPTIONAL,
3375  IN HANDLE FileHandle OPTIONAL)
3376 {
3377  LARGE_INTEGER SafeMaximumSize;
3379  HANDLE Handle;
3381  NTSTATUS Status;
3382  PAGED_CODE();
3383 
3384  /* Check for non-existing flags */
3385  if ((AllocationAttributes & ~(SEC_COMMIT | SEC_RESERVE | SEC_BASED |
3387  SEC_NO_CHANGE)))
3388  {
3389  if (!(AllocationAttributes & 1))
3390  {
3391  DPRINT1("Bogus allocation attribute: %lx\n", AllocationAttributes);
3393  }
3394  }
3395 
3396  /* Check for no allocation type */
3397  if (!(AllocationAttributes & (SEC_COMMIT | SEC_RESERVE | SEC_IMAGE)))
3398  {
3399  DPRINT1("Missing allocation type in allocation attributes\n");
3401  }
3402 
3403  /* Check for image allocation with invalid attributes */
3404  if ((AllocationAttributes & SEC_IMAGE) &&
3405  (AllocationAttributes & (SEC_COMMIT | SEC_RESERVE | SEC_LARGE_PAGES |
3407  {
3408  DPRINT1("Image allocation with invalid attributes\n");
3410  }
3411 
3412  /* Check for allocation type is both commit and reserve */
3413  if ((AllocationAttributes & SEC_COMMIT) && (AllocationAttributes & SEC_RESERVE))
3414  {
3415  DPRINT1("Commit and reserve in the same time\n");
3417  }
3418 
3419  /* Now check for valid protection */
3424  {
3425  DPRINT1("Sections don't support these protections\n");
3427  }
3428 
3429  /* Use a maximum size of zero, if none was specified */
3430  SafeMaximumSize.QuadPart = 0;
3431 
3432  /* Check for user-mode caller */
3433  if (PreviousMode != KernelMode)
3434  {
3435  /* Enter SEH */
3436  _SEH2_TRY
3437  {
3438  /* Safely check user-mode parameters */
3439  if (MaximumSize) SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
3440  MaximumSize = &SafeMaximumSize;
3441  ProbeForWriteHandle(SectionHandle);
3442  }
3444  {
3445  /* Return the exception code */
3447  }
3448  _SEH2_END;
3449  }
3450  else if (!MaximumSize) MaximumSize = &SafeMaximumSize;
3451 
3452  /* Check that MaximumSize is valid if backed by paging file */
3453  if ((!FileHandle) && (!MaximumSize->QuadPart))
3455 
3456  /* Create the section */
3457  Status = MmCreateSection(&SectionObject,
3458  DesiredAccess,
3460  MaximumSize,
3462  AllocationAttributes,
3463  FileHandle,
3464  NULL);
3465  if (!NT_SUCCESS(Status)) return Status;
3466 
3467  /* FIXME: Should zero last page for a file mapping */
3468 
3469  /* Now insert the object */
3470  Status = ObInsertObject(SectionObject,
3471  NULL,
3472  DesiredAccess,
3473  0,
3474  NULL,
3475  &Handle);
3476  if (NT_SUCCESS(Status))
3477  {
3478  /* Enter SEH */
3479  _SEH2_TRY
3480  {
3481  /* Return the handle safely */
3482  *SectionHandle = Handle;
3483  }
3485  {
3486  /* Nothing here */
3487  }
3488  _SEH2_END;
3489  }
3490 
3491  /* Return the status */
3492  return Status;
3493 }
3494 
3495 NTSTATUS
3496 NTAPI
3497 NtOpenSection(OUT PHANDLE SectionHandle,
3500 {
3501  HANDLE Handle;
3502  NTSTATUS Status;
3504  PAGED_CODE();
3505 
3506  /* Check for user-mode caller */
3507  if (PreviousMode != KernelMode)
3508  {
3509  /* Enter SEH */
3510  _SEH2_TRY
3511  {
3512  /* Safely check user-mode parameters */
3513  ProbeForWriteHandle(SectionHandle);
3514  }
3516  {
3517  /* Return the exception code */
3519  }
3520  _SEH2_END;
3521  }
3522 
3523  /* Try opening the object */
3524  Status = ObOpenObjectByName(ObjectAttributes,
3526  PreviousMode,
3527  NULL,
3528  DesiredAccess,
3529  NULL,
3530  &Handle);
3531 
3532  /* Enter SEH */
3533  _SEH2_TRY
3534  {
3535  /* Return the handle safely */
3536  *SectionHandle = Handle;
3537  }
3539  {
3540  /* Nothing here */
3541  }
3542  _SEH2_END;
3543 
3544  /* Return the status */
3545  return Status;
3546 }
3547 
3548 NTSTATUS
3549 NTAPI
3559  IN ULONG Protect)
3560 {
3561  PVOID SafeBaseAddress;
3562  LARGE_INTEGER SafeSectionOffset;
3563  SIZE_T SafeViewSize;
3564  PROS_SECTION_OBJECT Section;
3566  NTSTATUS Status;
3568  ULONG ProtectionMask;
3570 #ifdef _M_IX86
3571  static const ULONG ValidAllocationType = (MEM_TOP_DOWN | MEM_LARGE_PAGES |
3573 #else
3574  static const ULONG ValidAllocationType = (MEM_TOP_DOWN | MEM_LARGE_PAGES |
3576 #endif
3577 
3578  /* Check for invalid inherit disposition */
3579  if ((InheritDisposition > ViewUnmap) || (InheritDisposition < ViewShare))
3580  {
3581  DPRINT1("Invalid inherit disposition\n");
3583  }
3584 
3585  /* Allow only valid allocation types */
3586  if (AllocationType & ~ValidAllocationType)
3587  {
3588  DPRINT1("Invalid allocation type\n");
3590  }
3591 
3592  /* Convert the protection mask, and validate it */
3593  ProtectionMask = MiMakeProtectionMask(Protect);
3594  if (ProtectionMask == MM_INVALID_PROTECTION)
3595  {
3596  DPRINT1("Invalid page protection\n");
3598  }
3599 
3600  /* Now convert the protection mask into desired section access mask */
3601  DesiredAccess = MmMakeSectionAccess[ProtectionMask & 0x7];
3602 
3603  /* Assume no section offset */
3604  SafeSectionOffset.QuadPart = 0;
3605 
3606  /* Enter SEH */
3607  _SEH2_TRY
3608  {
3609  /* Check for unsafe parameters */
3610  if (PreviousMode != KernelMode)
3611  {
3612  /* Probe the parameters */
3613  ProbeForWritePointer(BaseAddress);
3614  ProbeForWriteSize_t(ViewSize);
3615  }
3616 
3617  /* Check if a section offset was given */
3618  if (SectionOffset)
3619  {
3620  /* Check for unsafe parameters and capture section offset */
3621  if (PreviousMode != KernelMode) ProbeForWriteLargeInteger(SectionOffset);
3622  SafeSectionOffset = *SectionOffset;
3623  }
3624 
3625  /* Capture the other parameters */
3626  SafeBaseAddress = *BaseAddress;
3627  SafeViewSize = *ViewSize;
3628  }
3630  {
3631  /* Return the exception code */
3633  }
3634  _SEH2_END;
3635 
3636  /* Check for kernel-mode address */
3637  if (SafeBaseAddress > MM_HIGHEST_VAD_ADDRESS)
3638  {
3639  DPRINT1("Kernel base not allowed\n");
3641  }
3642 
3643  /* Check for range entering kernel-mode */
3644  if (((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)SafeBaseAddress) < SafeViewSize)
3645  {
3646  DPRINT1("Overflowing into kernel base not allowed\n");
3648  }
3649 
3650  /* Check for invalid zero bits */
3651  if (ZeroBits)
3652  {
3653  if (ZeroBits > MI_MAX_ZERO_BITS)
3654  {
3655  DPRINT1("Invalid zero bits\n");
3657  }
3658 
3659  if ((((ULONG_PTR)SafeBaseAddress << ZeroBits) >> ZeroBits) != (ULONG_PTR)SafeBaseAddress)
3660  {
3661  DPRINT1("Invalid zero bits\n");
3663  }
3664 
3665  if (((((ULONG_PTR)SafeBaseAddress + SafeViewSize) << ZeroBits) >> ZeroBits) != ((ULONG_PTR)SafeBaseAddress + SafeViewSize))
3666  {
3667  DPRINT1("Invalid zero bits\n");
3669  }
3670  }
3671 
3672  /* Reference the process */
3673  Status = ObReferenceObjectByHandle(ProcessHandle,
3675  PsProcessType,
3676  PreviousMode,
3677  (PVOID*)&Process,
3678  NULL);
3679  if (!NT_SUCCESS(Status)) return Status;
3680 
3681  /* Reference the section */
3682  Status = ObReferenceObjectByHandle(SectionHandle,
3683  DesiredAccess,
3685  PreviousMode,
3686  (PVOID*)&Section,
3687  NULL);
3688  if (!NT_SUCCESS(Status))
3689  {
3690  ObDereferenceObject(Process);
3691  return Status;
3692  }
3693 
3694  if (MiIsRosSectionObject(Section) &&
3696  {
3697  if (PreviousMode == UserMode &&
3698  SafeSectionOffset.QuadPart + SafeViewSize > MmHighestPhysicalPage << PAGE_SHIFT)
3699  {
3700  DPRINT1("Denying map past highest physical page.\n");
3701  ObDereferenceObject(Section);
3702  ObDereferenceObject(Process);
3704  }
3705  }
3706  else if (!(AllocationType & MEM_DOS_LIM))
3707  {
3708  /* Check for non-allocation-granularity-aligned BaseAddress */
3709  if (SafeBaseAddress != ALIGN_DOWN_POINTER_BY(SafeBaseAddress, MM_VIRTMEM_GRANULARITY))
3710  {
3711  DPRINT("BaseAddress is not at 64-kilobyte address boundary.\n");
3712  ObDereferenceObject(Section);
3713  ObDereferenceObject(Process);
3714  return STATUS_MAPPED_ALIGNMENT;
3715  }
3716 
3717  /* Do the same for the section offset */
3718  if (SafeSectionOffset.LowPart != ALIGN_DOWN_BY(SafeSectionOffset.LowPart, MM_VIRTMEM_GRANULARITY))
3719  {
3720  DPRINT("SectionOffset is not at 64-kilobyte address boundary.\n");
3721  ObDereferenceObject(Section);
3722  ObDereferenceObject(Process);
3723  return STATUS_MAPPED_ALIGNMENT;
3724  }
3725  }
3726 
3727  /* Now do the actual mapping */
3728  Status = MmMapViewOfSection(Section,
3729  Process,
3730  &SafeBaseAddress,
3731  ZeroBits,
3732  CommitSize,
3733  &SafeSectionOffset,
3734  &SafeViewSize,
3735  InheritDisposition,
3736  AllocationType,
3737  Protect);
3738 
3739  /* Return data only on success */
3740  if (NT_SUCCESS(Status))
3741  {
3742  /* Check if this is an image for the current process */
3743  if (MiIsRosSectionObject(Section) &&
3744  (Section->AllocationAttributes & SEC_IMAGE) &&
3745  (Process == PsGetCurrentProcess()) &&
3746  (Status != STATUS_IMAGE_NOT_AT_BASE))
3747  {
3748  /* Notify the debugger */
3749  DbgkMapViewOfSection(Section,
3750  SafeBaseAddress,
3751  SafeSectionOffset.LowPart,
3752  SafeViewSize);
3753  }
3754 
3755  /* Enter SEH */
3756  _SEH2_TRY
3757  {
3758  /* Return parameters to user */
3759  *BaseAddress = SafeBaseAddress;
3760  *ViewSize = SafeViewSize;
3761  if (SectionOffset) *SectionOffset = SafeSectionOffset;
3762  }
3764  {
3765  /* Nothing to do */
3766  }
3767  _SEH2_END;
3768  }
3769 
3770  /* Dereference all objects and return status */
3771  ObDereferenceObject(Section);
3772  ObDereferenceObject(Process);
3773  return Status;
3774 }
3775 
3776 NTSTATUS
3777 NTAPI
3780 {
3782  NTSTATUS Status;
3784 
3785  /* Don't allowing mapping kernel views */
3786  if ((PreviousMode == UserMode) && (BaseAddress > MM_HIGHEST_USER_ADDRESS))
3787  {
3788  DPRINT1("Trying to unmap a kernel view\n");
3789  return STATUS_NOT_MAPPED_VIEW;
3790  }
3791 
3792  /* Reference the process */
3793  Status = ObReferenceObjectByHandle(ProcessHandle,
3795  PsProcessType,
3796  PreviousMode,
3797  (PVOID*)&Process,
3798  NULL);
3799  if (!NT_SUCCESS(Status)) return Status;
3800 
3801  /* Unmap the view */
3802  Status = MiUnmapViewOfSection(Process, BaseAddress, 0);
3803 
3804  /* Dereference the process and return status */
3805  ObDereferenceObject(Process);
3806  return Status;
3807 }
3808 
3809 NTSTATUS
3810 NTAPI
3811 NtExtendSection(IN HANDLE SectionHandle,
3812  IN OUT PLARGE_INTEGER NewMaximumSize)
3813 {
3814  LARGE_INTEGER SafeNewMaximumSize;
3815  PROS_SECTION_OBJECT Section;
3816  NTSTATUS Status;
3818 
3819  /* Check for user-mode parameters */
3820  if (PreviousMode != KernelMode)
3821  {
3822  /* Enter SEH */
3823  _SEH2_TRY
3824  {
3825  /* Probe and capture the maximum size, it's both read and write */
3826  ProbeForWriteLargeInteger(NewMaximumSize);
3827  SafeNewMaximumSize = *NewMaximumSize;
3828  }
3830  {
3831  /* Return the exception code */
3833  }
3834  _SEH2_END;
3835  }
3836  else
3837  {
3838  /* Just read the size directly */
3839  SafeNewMaximumSize = *NewMaximumSize;
3840  }
3841 
3842  /* Reference the section */
3843  Status = ObReferenceObjectByHandle(SectionHandle,
3846  PreviousMode,
3847  (PVOID*)&Section,
3848  NULL);
3849  if (!NT_SUCCESS(Status)) return Status;
3850 
3851  /* Really this should go in MmExtendSection */
3852  if (!(Section->AllocationAttributes & SEC_FILE))
3853  {
3854  DPRINT1("Not extending a file\n");
3855  ObDereferenceObject(Section);
3857  }
3858 
3859  /* FIXME: Do the work */
3860 
3861  /* Dereference the section */
3862  ObDereferenceObject(Section);
3863 
3864  /* Enter SEH */
3865  _SEH2_TRY
3866  {
3867  /* Write back the new size */
3868  *NewMaximumSize = SafeNewMaximumSize;
3869  }
3871  {
3872  /* Nothing to do */
3873  }
3874  _SEH2_END;
3875 
3876  /* Return the status */
3877  return STATUS_NOT_IMPLEMENTED;
3878 }
3879 
3880 /* EOF */
ULONG NoChange
Definition: mmtypes.h:478
_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:2522
DWORD *typedef PVOID
Definition: winlogon.h:52
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define PAGE_NOCACHE
Definition: nt_native.h:1311
union _MMVAD_LONG::@2315 u2
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 const char UINT32 const char const char * ModuleName
Definition: acpixf.h:1256
static int Hash(const char *)
Definition: reader.c:2247
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
union _MMVAD_LONG::@2317 u4
_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:38
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
#define MM_VIRTMEM_GRANULARITY
Definition: mm.h:76
#define MM_INVALID_PROTECTION
Definition: miarm.h:69
MMPTE PrototypePte
Definition: init.c:42
ULONG NumberOfCommittedPages
Definition: mmtypes.h:407
PEVENT_COUNTER WaitingForDeletion
Definition: mmtypes.h:526
NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN PVOID BaseAddress)
Definition: section.c:3778
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define ALIGN_DOWN_POINTER_BY(ptr, align)
KAPC_STATE
Definition: ketypes.h:1258
PFILE_OBJECT FilePointer
Definition: mmtypes.h:525
PVOID ULONG Address
Definition: oprghdlr.h:14
SIZE_T NonPageablePages
Definition: miarm.h:458
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
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:1892
ULONG NTAPI MiMakeSystemAddressValidPfn(IN PVOID VirtualAddress, IN KIRQL OldIrql)
Definition: virtual.c:257
union _MEMORY_AREA::@1561 Data
#define SEC_LARGE_PAGES
Definition: mmtypes.h:102
struct _RTL_BITMAP RTL_BITMAP
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:604
ULONG Type
Definition: mm.h:210
struct _MEMORY_AREA * PMEMORY_AREA
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1177
NTSTATUS NTAPI NtAreMappedFilesTheSame(IN PVOID File1MappedAsAnImage, IN PVOID File2MappedAsFile)
Definition: section.c:3290
NTSTATUS NTAPI MmGetFileNameForAddress(IN PVOID Address, OUT PUNICODE_STRING ModuleName)
Definition: section.c:1831
ULONGLONG SizeOfSegment
Definition: mmtypes.h:405
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ ULONG AllocationAttributes
Definition: mmfuncs.h:360
ULONG UserReference
Definition: mmtypes.h:471
#define MiAddressToPde(x)
Definition: mmx86.c:20
ULONG NumberOfSectionReferences
Definition: mmtypes.h:515
#define STATUS_NOT_SAME_DEVICE
Definition: ntstatus.h:434
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:3369
struct _Entry Entry
Definition: kefuncs.h:640
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:264
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
PSEGMENT Segment
Definition: mmtypes.h:813
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
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:1495
USHORT MaximumLength
Definition: env_spec_w32.h:370
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
ULONG NonExtendedPtes
Definition: mmtypes.h:403
PMMPDE PageTables
Definition: miarm.h:484
BOOLEAN NTAPI MmDisableModifiedWriteOfSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer)
Definition: section.c:2966
ULONG PhysicalMemory
Definition: mmtypes.h:465
ULONG PFN_COUNT
Definition: mmtypes.h:102
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define MI_IS_SESSION_ADDRESS(Address)
Definition: miarm.h:138
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
return STATUS_SUCCESS
Definition: btrfs.c:2664
CHAR MmUserProtectionToMask1[16]
Definition: section.c:44
#define PAGE_GUARD
Definition: nt_native.h:1310
PMMPTE LastContiguousPte
Definition: mmtypes.h:768
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2268
VOID NTAPI MiRemoveMappedPtes(IN PVOID BaseAddress, IN ULONG NumberOfPtes, IN PCONTROL_AREA ControlArea, IN PMMSUPPORT Ws)
Definition: section.c:2230
char CHAR
Definition: xmlstorage.h:175
#define PROCESS_VM_OPERATION
Definition: pstypes.h:153
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1350
ULONG InitialPageProtection
Definition: mmtypes.h:820
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:764
KGUARDED_MUTEX MmSectionBasedMutex
Definition: section.c:110
ULONG_PTR CommitCharge
Definition: mmtypes.h:692
PCONTROL_AREA ControlArea
Definition: mmtypes.h:563
MMPTE ThePtes[1]
Definition: mmtypes.h:422
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2327
NTSTATUS NTAPI MmGetFileNameForSection(IN PVOID Section, OUT POBJECT_NAME_INFORMATION *ModuleName)
Definition: section.c:1801
BOOLEAN NTAPI MiInitializeSystemSpaceMap(IN PMMSESSION InputSession OPTIONAL)
Definition: section.c:240
#define ProbeForWriteSize_t(Ptr)
Definition: probe.h:45
#define MM_READWRITE
Definition: miarm.h:49
#define STATUS_INVALID_PARAMETER_9
Definition: ntstatus.h:469
SIZE_T MmSharedCommit
Definition: freelist.c:31
ULONG LargePages
Definition: mmtypes.h:395
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:209
#define STATUS_INVALID_PARAMETER_8
Definition: ntstatus.h:468
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:141
#define MM_NOACCESS
Definition: miarm.h:67
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:77
union _CONTROL_AREA::@2304 u
ACCESS_MASK MmMakeFileAccess[8]
Definition: section.c:32
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
union _SECTION::@2320 u
#define MAXULONG_PTR
Definition: basetsd.h:102
USHORT Modified
Definition: mm.h:288
VOID NTAPI MiRemoveMappedView(IN PEPROCESS CurrentProcess, IN PMMVAD Vad)
Definition: section.c:780
NTSTATUS NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
Definition: obname.c:1066
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
SEGMENT_FLAGS SegmentFlags
Definition: mmtypes.h:409
PCHAR SystemSpaceViewStart
Definition: miarm.h:429
ULONG SecNoChange
Definition: mmtypes.h:708
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:2740
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1280
PCONTROL_AREA ControlArea
Definition: mmtypes.h:766
ULONG_PTR Protection
Definition: mmtypes.h:697
VOID NTAPI MiSubsectionConsistent(IN PSUBSECTION Subsection)
Definition: section.c:1478
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint 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 GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble * u
Definition: glfuncs.h:88
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:267
IN SIZE_T IN PVOID File
Definition: exeformat.h:53
VOID NTAPI MiLoadUserSymbols(IN PCONTROL_AREA ControlArea, IN PVOID BaseAddress, IN PEPROCESS Process)
Definition: section.c:1158
ULONG SystemSpaceHashEntries
Definition: miarm.h:432
#define SEC_NOCACHE
Definition: mmtypes.h:100
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:707
ULONG TotalNumberOfPtes
Definition: mmtypes.h:402
UNICODE_STRING Name
Definition: nt_native.h:1270
IN POBJECT_ATTRIBUTES PortAttributes IN ACCESS_MASK DesiredAccess
Definition: creport.c:28
union _MMPFN::@1564 u1
_Must_inspect_result_ _In_ ULONG Index
Definition: fltkernel.h:1824
PVOID FirstMappedVa
Definition: mmtypes.h:419
struct _SUBSECTION SUBSECTION
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
#define WCHAR
Definition: msvc.h:43
void DbgBreakPoint()
Definition: mach.c:558
NTSTATUS NTAPI MiCreatePagingFileMap(OUT PSEGMENT *Segment, IN PSIZE_T MaximumSize, IN ULONG ProtectionMask, IN ULONG AllocationAttributes)
Definition: section.c:1510
USHORT ReferenceCount
Definition: mm.h:324
ULONG_PTR NoChange
Definition: mmtypes.h:694
PSEGMENT_OBJECT Segment
Definition: mmtypes.h:627
VOID NTAPI MiInsertBasedSection(IN PSECTION Section)
Definition: vadnode.c:345
#define MM_NOCACHE
Definition: miarm.h:58
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:735
NTSTATUS NTAPI MiSessionCommitPageTables(IN PVOID StartVa, IN PVOID EndVa)
Definition: section.c:935
#define MEMORY_AREA_CACHE
Definition: mm.h:70
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
USHORT PageLocation
Definition: mm.h:293
struct Color Color
KGUARDED_MUTEX SystemSpaceViewLock
Definition: miarm.h:427
_Must_inspect_result_ _In_ PDEVICE_OBJECT _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer
Definition: fsrtlfuncs.h:1368
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define MM_DELETE_CHECK
Definition: miarm.h:233
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:531
struct _CONTROL_AREA * ControlArea
Definition: mmtypes.h:401
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define STATUS_ALREADY_COMMITTED
Definition: ntstatus.h:256
NTSTATUS NTAPI MiCheckPurgeAndUpMapCount(IN PCONTROL_AREA ControlArea, IN BOOLEAN FailIfSystemViews)
Definition: section.c:544
#define SEC_BASED
PEPROCESS CreatingProcess
Definition: mmtypes.h:414
ERESOURCE PsLoadedModuleResource
Definition: sysldr.c:37
VOID NTAPI MiDereferenceControlArea(IN PCONTROL_AREA ControlArea)
Definition: section.c:763
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define MM_EXECUTE_WRITECOPY
Definition: miarm.h:52
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:2410
USHORT PrototypePte
Definition: mm.h:291
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG SectionPageProtection
Definition: mmfuncs.h:360
PVOID DllBase
Definition: btrfs_drv.h:1714
ULONG64 Dirty
Definition: mmtypes.h:164
NTSTATUS NTAPI MiAddMappedPtes(IN PMMPTE FirstPte, IN PFN_NUMBER PteCount, IN PCONTROL_AREA ControlArea)
Definition: section.c:417
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:325
PVOID MmSessionBase
Definition: init.c:33
ULONG_PTR EndingVpn
Definition: mmtypes.h:731
union _MMPFN::@1566 u3
while(1)
Definition: macro.lex.yy.c:730
#define MM_WRITECOPY
Definition: miarm.h:50
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:159
#define PDE_COUNT
Definition: miarm.h:30
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#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:388
VOID NTAPI MiDeleteARM3Section(PVOID ObjectBody)
Definition: section.c:3244
ULONG PFN_NUMBER
Definition: ke.h:8
static BOOL Attached
Definition: vidbios.c:3904
#define STATUS_INVALID_PARAMETER_3
Definition: ntstatus.h:463
ULONG NTAPI MiRemoveFromSystemSpace(IN PMMSESSION Session, IN PVOID Base, OUT PCONTROL_AREA *ControlArea)
Definition: section.c:2332
#define SEC_COMMIT
Definition: mmtypes.h:99
ULONG_PTR * PSIZE_T
Definition: typedefs.h:78
#define TAG_MM
Definition: tag.h:136
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:71
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
ULONG MmSystemViewSize
Definition: init.c:39
struct _SUBSECTION * NextSubsection
Definition: mmtypes.h:574
static PFILE_OBJECT MiGetFileObjectForVad(_In_ PMMVAD Vad)
Definition: section.c:1701
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:649
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:2833
_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 _WARN(msg)
Definition: debug.h:262
long LONG
Definition: pedump.c:60
NTSTATUS NTAPI MmUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:3060
LARGE_INTEGER SizeOfSection
Definition: mmtypes.h:814
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:260
ULONG MmSessionViewSize
Definition: init.c:35
#define SEC_RESERVE
Definition: nt_native.h:1323
#define FILE_READ_DATA
Definition: nt_native.h:628
#define _SEH2_END
Definition: pseh2_64.h:7
PKEVENT Event
Definition: mm.h:307
uint64_t ULONG64
Definition: typedefs.h:65
#define MI_SET_PROCESS2(x)
Definition: mm.h:250
#define MEM_RESERVE
Definition: nt_native.h:1314
struct _MSUBSECTION MSUBSECTION
#define STATUS_MAPPED_ALIGNMENT
Definition: ntstatus.h:662
PVOID MiSystemViewStart
Definition: init.c:38
NTSTATUS NTAPI MmUnmapViewInSessionSpace(IN PVOID MappedBase)
Definition: section.c:3021
union _SEGMENT::@2302 u1
NTSTATUS NTAPI MiRosUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress, IN BOOLEAN SkipDebuggerNotify)
Definition: section.c:4126
TCHAR ModuleFileName[MAX_PATH+1]
Definition: rundll32.c:55
PCONTROL_AREA ControlArea
Definition: mmtypes.h:737
#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:3550
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_In_ BOOLEAN DelayClose
Definition: mmfuncs.h:593
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:2061
NTSTATUS NTAPI NtOpenSection(OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: section.c:3497
#define PAGE_NOACCESS
Definition: nt_native.h:1302
#define STATUS_SECTION_TOO_BIG
Definition: ntstatus.h:286
VOID NTAPI MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
Definition: virtual.c:2371
NTSTATUS NTAPI NtExtendSection(IN HANDLE SectionHandle, IN OUT PLARGE_INTEGER NewMaximumSize)
Definition: section.c:3811
smooth NULL
Definition: ftsmooth.c:557
PVOID FORCEINLINE MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:185
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:48
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:462
#define MiProtoPteToPte(x)
Definition: mm.h:234
_In_ PFILE_OBJECT FileObject
Definition: classpnp.h:1229
#define MM_EXECUTE_READ
Definition: miarm.h:48
#define PAGE_EXECUTE
Definition: nt_native.h:1306
PVOID Banked
Definition: mmtypes.h:781
ULONG MmSecondaryColorMask
Definition: mminit.c:256
void DPRINT(...)
Definition: polytest.cpp:61
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1133
struct _SECTION * PSECTION
ULONG LongFlags
Definition: mmtypes.h:522
struct _SECTION SECTION
struct _FileName FileName
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:969
#define MI_SET_USAGE(x)
Definition: mm.h:249
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:4491
ULONG_PTR StartingVpn
Definition: mmtypes.h:730
ULONG_PTR StartingVpn
Definition: mmtypes.h:654
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:69
union _MMVAD_LONG::@2314 u
PMMVIEW SystemSpaceViewTable
Definition: miarm.h:430
PVOID NTAPI MiInsertInSystemSpace(IN PMMSESSION Session, IN ULONG Buckets, IN PCONTROL_AREA ControlArea)
Definition: section.c:306
ULONG SystemSpaceHashKey
Definition: miarm.h:433
#define FILE_WRITE_DATA
Definition: nt_native.h:631
_Inout_ PVOID Segment
Definition: exfuncs.h:893
CHAR MmUserProtectionToMask2[16]
Definition: section.c:64
LIST_ENTRY DereferenceList
Definition: mmtypes.h:514
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:938
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER SectionOffset
Definition: mmfuncs.h:404
#define SECTION_MAP_WRITE
Definition: nt_native.h:1288
UINTN Size
Definition: acefiex.h:555
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:49
ULONG FileOffset
Definition: mmtypes.h:707
PMMPDE MmSystemPagePtes
Definition: init.c:41
#define PD_SIZE
Definition: miarm.h:26
#define STATUS_INVALID_PARAMETER_5
Definition: ntstatus.h:465
ULONG_PTR EndingVpn
Definition: mmtypes.h:655
#define MEM_DOS_LIM
Definition: mmtypes.h:89
NTSTATUS NTAPI MmGetFileNameForFileObject(IN PFILE_OBJECT FileObject, OUT POBJECT_NAME_INFORMATION *ModuleName)
Definition: section.c:1769
NTSTATUS NTAPI MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:4890
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:318
NTSYSAPI void WINAPI RtlClearAllBits(PRTL_BITMAP)
NTSTATUS NTAPI MiCheckSecuredVad(IN PMMVAD Vad, IN PVOID Base, IN SIZE_T Size, IN ULONG ProtectionMask)
Definition: vadnode.c:809
int64_t LONGLONG
Definition: typedefs.h:66
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1107
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ HANDLE Handle
Definition: extypes.h:390
NTSTATUS NTAPI MmUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress)
Definition: section.c:3049
unsigned char BOOLEAN
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG CurrentProcess
Definition: shell.c:125
ULONG_PTR PrivateMemory
Definition: mmtypes.h:699
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
union _MMVAD::@2311 u
PFILE_OBJECT FileObject
Definition: mm.h:195
PCONTROL_AREA ControlArea
Definition: mmtypes.h:610
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define MM_EXECUTE
Definition: miarm.h:47
SIZE_T CommittedPages
Definition: miarm.h:459
NTSTATUS NTAPI MiUnmapViewInSystemSpace(IN PMMSESSION Session, IN PVOID MappedBase)
Definition: section.c:2376
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
#define MiPdeToPpe(_Pde)
Definition: mm.h:221
MMSESSION Session
Definition: miarm.h:474
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:4964
static void Exit(void)
Definition: sock.c:1272
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:605
ULONG CheckSum
Definition: btrfs_drv.h:1720
#define MAX_PATH
Definition: compat.h:26
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:488
struct _ROS_SECTION_OBJECT * PROS_SECTION_OBJECT
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
PVOID MiSessionSpaceEnd
Definition: init.c:27
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
#define PAGE_ALIGN(Va)
#define STATUS_SECTION_PROTECTION
Definition: ntstatus.h:300
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID NTAPI MiFillSystemPageDirectory(IN PVOID Base, IN SIZE_T NumberOfBytes)
Definition: section.c:476
MMVAD_FLAGS2 VadFlags2
Definition: mmtypes.h:772
#define SECTION_EXTEND_SIZE
Definition: nt_native.h:1291
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:75
ULONG NTAPI MmDoesFileHaveUserWritableReferences(IN PSECTION_OBJECT_POINTERS SectionPointer)
Definition: section.c:3280
#define STATUS_INVALID_FILE_FOR_SECTION
Definition: ntstatus.h:255
#define PAGED_CODE()
Definition: video.h:57
#define ProbeForReadLargeInteger(Ptr)
Definition: probe.h:75
POBJECT_TYPE MmSectionObjectType
Definition: section.c:136
#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:1949
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
union _SUBSECTION::@2306 u
NTSTATUS NTAPI MmMapViewInSystemSpace(IN PVOID SectionObject, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:4836
#define BYTES_TO_PAGES(Size)
VOID NTAPI DbgkUnMapViewOfSection(IN PVOID BaseAddress)
Definition: dbgkutil.c:436
UNICODE_STRING SectionFileName
Definition: mmtypes.h:317
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define STATUS_SECTION_NOT_IMAGE
Definition: ntstatus.h:295
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:1923
#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:1391
PKGUARDED_MUTEX SystemSpaceViewLockPointer
Definition: miarm.h:428
MMSECTION_FLAGS Flags
Definition: mmtypes.h:818
#define InterlockedDecrement
Definition: armddk.h:52
#define SEC_PHYSICALMEMORY
Definition: mm.h:86
PCONTROL_AREA ControlArea
Definition: miarm.h:422
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
ULONG TotalNumberOfPtes4132
Definition: mmtypes.h:393
ULONG64 PageFileHigh
Definition: mmtypes.h:93
#define MM_NOIRQL
Definition: miarm.h:203
IN SIZE_T NumberOfBytes
Definition: ndis.h:3914
NTSTATUS NTAPI MmCommitSessionMappedView(IN PVOID MappedBase, IN SIZE_T ViewSize)
Definition: section.c:3081
struct _SEGMENT SEGMENT
#define MM_GUARDPAGE
Definition: miarm.h:59
#define ProbeForWritePointer(Ptr)
Definition: probe.h:42
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:411
#define MI_MAX_ZERO_BITS
Definition: mm.h:73
#define FILE_EXECUTE
Definition: nt_native.h:642
#define SECTION_MAP_READ
Definition: compat.h:128
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:461
#define KeEnterCriticalRegion()
Definition: ke_x.h:83
Definition: mm.h:301
ULONG GlobalOnlyPerSession
Definition: mmtypes.h:483
Definition: btrfs_drv.h:1710
ULONG LowPart
Definition: typedefs.h:104
BOOLEAN NTAPI MmForceSectionClosed(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN BOOLEAN DelayClose)
Definition: section.c:2977
#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
PFN_NUMBER MmSystemPageDirectory[PD_COUNT]
Definition: init.c:40
Definition: typedefs.h:117
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:291
ULONG CopyOnWrite
Definition: mmtypes.h:466
ULONG NumberOfMappedViews
Definition: mmtypes.h:517
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
VOID NTAPI MmGetImageInformation(OUT PSECTION_IMAGE_INFORMATION ImageInformation)
Definition: section.c:1754
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
const ULONG MmProtectToValue[32]
Definition: page.c:81
_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:17
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:873
struct _MEMORY_AREA::@1561::@1562 SectionData
VOID NTAPI MiRemoveNode(IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table)
Definition: vadnode.c:360
MMPTE ValidKernelPdeLocal
Definition: init.c:34
NTSTATUS NTAPI MiMapViewInSystemSpace(IN PVOID Section, IN PMMSESSION Session, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:1052
KGUARDED_MUTEX MmSectionCommitMutex
Definition: section.c:108
ULONG Inherit
Definition: mmtypes.h:714
MMPTE ValidKernelPde
Definition: init.c:30
Status
Definition: gdiplustypes.h:24
ULONG_PTR Long
Definition: mmtypes.h:215
#define MM_EXECUTE_READWRITE
Definition: miarm.h:51
LIST_ENTRY InLoadOrderLinks
Definition: ldrtypes.h:136
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:785
#define ALIGN_DOWN_BY(size, align)
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define _In_
Definition: no_sal2.h:204
VOID NTAPI MiDeleteVirtualAddresses(IN ULONG_PTR Va, IN ULONG_PTR EndingAddress, IN PMMVAD Vad)
Definition: virtual.c:540
static HANDLE FileHandle
Definition: cabinet.c:47
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define STATUS_IMAGE_NOT_AT_BASE
Definition: ntstatus.h:117
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define SYSTEM_PD_SIZE
Definition: miarm.h:34
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:161
#define MiPteToPde(_Pte)
Definition: mm.h:220
MMSUBSECTION_FLAGS SubsectionFlags
Definition: mmtypes.h:567
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:943
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1372
DWORD *typedef HANDLE
Definition: winlogon.h:52
#define PAGE_WRITECOMBINE
Definition: mmtypes.h:78
#define STATUS_INVALID_VIEW_SIZE
Definition: ntstatus.h:254
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:2925
LONG NTSTATUS
Definition: DriverTester.h:11
#define KeLeaveCriticalRegion()
Definition: ke_x.h:114
PRTL_BITMAP SystemSpaceBitMap
Definition: miarm.h:435
#define InterlockedIncrement
Definition: armddk.h:53
PVOID MiSessionViewStart
Definition: init.c:30
unsigned short USHORT
Definition: pedump.c:61
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
PSUBSECTION NTAPI MiLocateSubsection(IN PMMVAD Vad, IN ULONG_PTR Vpn)
Definition: section.c:570
#define STATUS_INVALID_ADDRESS
Definition: ntstatus.h:543
ULONG FilePointerNull
Definition: mmtypes.h:474
NTSTATUS NTAPI MiGetFileObjectForSectionAddress(IN PVOID Address, OUT PFILE_OBJECT *FileObject)
Definition: section.c:1618
ULONG64 Transition
Definition: mmtypes.h:90
FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, IN PMMPTE PointerPte)
Definition: mm.h:253
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:701
#define MI_SYSTEM_VIEW_BUCKET_SIZE
Definition: miarm.h:238
ULONG NTAPI MiGetPageProtection(IN PMMPTE PointerPte)
Definition: virtual.c:1329
ULONG BeingDeleted
Definition: mmtypes.h:455
#define STATUS_INVALID_PARAMETER_10
Definition: ntstatus.h:470
Definition: miarm.h:419
ULONG WritableUserReferences
Definition: mmtypes.h:529
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
PSEGMENT Segment
Definition: mmtypes.h:513
#define _SEH2_TRY
Definition: pseh2_64.h:5
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1411
_Must_inspect_result_ _In_ ULONG NewProtect
Definition: mmfuncs.h:683
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1716
MMADDRESS_NODE Address
Definition: mmtypes.h:812
#define STATUS_INVALID_PARAMETER_6
Definition: ntstatus.h:466
ULONG NumberOfUserReferences
Definition: mmtypes.h:519
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
unsigned int * PULONG
Definition: retypes.h:1
struct _MMPTE MMPTE
MMPTE OriginalPte
Definition: mm.h:335
VOID NTAPI MiCheckControlArea(IN PCONTROL_AREA ControlArea, IN KIRQL OldIrql)
Definition: section.c:728
#define STATUS_SECTION_NOT_EXTENDED
Definition: ntstatus.h:357
#define PAGE_READONLY
Definition: compat.h:127
#define PAGE_WRITECOPY
Definition: nt_native.h:1305
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER MaximumSize
Definition: mmfuncs.h:360
VOID NTAPI DbgLoadImageSymbols(_In_ PSTRING Name, _In_ PVOID Base, _In_ ULONG_PTR ProcessId)
#define DPRINT1
Definition: precomp.h:8
#define RtlImageNtHeader
Definition: compat.h:457
_Must_inspect_result_ _Outptr_result_bytebuffer_ ViewSize PVOID * MappedBase
Definition: mmfuncs.h:493
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:36
#define SEC_FILE
Definition: mmtypes.h:95
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
PVOID BasedAddress
Definition: mmtypes.h:410
union _SEGMENT::@2303 u2
MMPTE SegmentPteTemplate
Definition: mmtypes.h:406
#define MI_IS_PAGE_DIRTY(x)
Definition: mm.h:101
#define OUT
Definition: typedefs.h:39
#define ObReferenceObject
Definition: obfuncs.h:204
ULONG_PTR Spare
Definition: mmtypes.h:698
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:404
PVOID MmHighSectionBase
Definition: section.c:111
VOID FASTCALL KeAcquireGuardedMutexUnsafe(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:64
FORCEINLINE VOID MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:1635
ULONG WasPurged
Definition: mmtypes.h:470
PVOID PIRP
Definition: usb.h:38
MMSECTION_FLAGS Flags
Definition: mmtypes.h:523
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_NOT_MAPPED_VIEW
Definition: ntstatus.h:248
#define SECTION_MAP_EXECUTE
Definition: nt_native.h:1290
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:259
PMMPTE FirstPrototypePte
Definition: mmtypes.h:767
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define UNIMPLEMENTED
Definition: debug.h:114
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
#define SEC_IMAGE
Definition: mmtypes.h:96
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
ULONG AllocationAttributes
Definition: mm.h:194
NTSTATUS NTAPI MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea, IN PEPROCESS Process, IN PVOID *BaseAddress, IN PLARGE_INTEGER SectionOffset, IN PSIZE_T ViewSize, IN PSECTION Section, IN SECTION_INHERIT InheritDisposition, IN ULONG ProtectionMask, IN SIZE_T CommitSize, IN ULONG_PTR ZeroBits, IN ULONG AllocationType)
Definition: section.c:1252
ULONG_PTR Entry
Definition: miarm.h:421
#define MM_READONLY
Definition: miarm.h:46
#define PAGE_EXECUTE_READ
Definition: nt_native.h:1307
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
Definition: File.h:15
VOID NTAPI MiSetControlAreaSymbolsLoaded(IN PCONTROL_AREA ControlArea)
Definition: section.c:1142
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1097
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
union _MMPTE::@2072 u
VOID NTAPI MiFlushTbAndCapture(IN PMMVAD FoundVad, IN PMMPTE PointerPte, IN ULONG ProtectionMask, IN PMMPFN Pfn1, IN BOOLEAN UpdateDirty)
Definition: section.c:1957
#define STATUS_INVALID_PARAMETER_4
Definition: ntstatus.h:464
NTSTATUS NTAPI MmMapViewInSessionSpace(IN PVOID Section, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:2989
ULONG SystemSpaceHashSize
Definition: miarm.h:431
#define MEM_TOP_DOWN
Definition: nt_native.h:1321
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:247
FORCEINLINE VOID MI_UPDATE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:928
WCHAR NameBuffer[ANYSIZE_ARRAY]
Definition: mmtypes.h:318
#define memset(x, y, z)
Definition: compat.h:39
#define CHAR(Char)
enum _SECTION_INHERIT SECTION_INHERIT
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:65
static const CHAR FileNameA[]
PMMPTE PrototypePte
Definition: mmtypes.h:421
#define SEC_NO_CHANGE
Definition: mmtypes.h:94
#define APC_LEVEL
Definition: env_spec_w32.h:695
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1343
POBJECT_TYPE PsProcessType
Definition: process.c:20
#define PFN_FROM_PTE(v)
Definition: mm.h:82
PMMPTE SubsectionBase
Definition: mmtypes.h:571
ULONG WriteCombined
Definition: mmtypes.h:485
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define MAXLONG_PTR
Definition: basetsd.h:103
ULONG_PTR VadType
Definition: mmtypes.h:695
#define ProbeForWriteLargeInteger(Ptr)
Definition: probe.h:46
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:90
FORCEINLINE PMMSUPPORT MmGetCurrentAddressSpace(VOID)
Definition: mm.h:1365
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ULONG BeingCreated
Definition: mmtypes.h:456
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:332
USHORT LoadCount
Definition: ntddk_ex.h:212
PFILE_OBJECT NTAPI MmGetFileObjectForSection(IN PVOID SectionObject)
Definition: section.c:1681
LONGLONG QuadPart
Definition: typedefs.h:112
NTSTATUS NTAPI MiUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress, IN ULONG Flags)
Definition: section.c:817
#define PAGE_READWRITE
Definition: nt_native.h:1304
NTSYSAPI VOID NTAPI RtlFillMemoryUlonglong(_Out_writes_bytes_all_(Length) PVOID Destination, _In_ SIZE_T Length, _In_ ULONGLONG Pattern)
PFN_NUMBER SessionPageDirectoryIndex
Definition: miarm.h:457
FORCEINLINE BOOLEAN MiIsRosSectionObject(IN PVOID Section)
Definition: miarm.h:1034
MMSESSION MmSession
Definition: section.c:107
ULONG PtesInSubsection
Definition: mmtypes.h:573