ReactOS  r74431
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, Flags);
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  PageFrameNumber = MiRemoveZeroPage(Color);
999  TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
1000  MI_WRITE_VALID_PDE(StartPde, TempPde);
1001 
1002  /* Write the page table in session space structure */
1003  ASSERT(MmSessionSpace->PageTables[Index].u.Long == 0);
1005 
1006  /* Initialize the PFN */
1007  MiInitializePfnForOtherProcess(PageFrameNumber,
1008  StartPde,
1010 
1011  /* And now release the lock */
1013 
1014  /* Get the PFN entry and make sure there's no event for it */
1015  Pfn1 = MI_PFN_ELEMENT(PageFrameNumber);
1016  ASSERT(Pfn1->u1.Event == NULL);
1017 
1018  /* Increment the number of pages */
1019  ActualPages++;
1020  }
1021 
1022  /* Move to the next PDE */
1023  StartPde++;
1024  Index++;
1025  }
1026 #endif
1027 
1028  /* Make sure we didn't do more pages than expected */
1029  ASSERT(ActualPages <= PageCount);
1030 
1031  /* Release the working set lock */
1032 // MiUnlockWorkingSet(PsGetCurrentThread(),
1033 // &MmSessionSpace->GlobalVirtualAddress->Vm);
1034 
1035 
1036  /* If we did at least one page... */
1037  if (ActualPages)
1038  {
1039  /* Update the performance counters! */
1042  }
1043 
1044  /* Return status */
1045  return STATUS_SUCCESS;
1046 }
1047 
1048 NTSTATUS
1049 NTAPI
1052  OUT PVOID *MappedBase,
1054 {
1055  PVOID Base;
1056  PCONTROL_AREA ControlArea;
1057  ULONG Buckets, SectionSize;
1058  NTSTATUS Status;
1059  PAGED_CODE();
1060 
1061  /* Get the control area, check for any flags ARM3 doesn't yet support */
1062  ControlArea = ((PSECTION)Section)->Segment->ControlArea;
1063  ASSERT(ControlArea->u.Flags.Image == 0);
1064  ASSERT(ControlArea->FilePointer == NULL);
1065  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
1066  ASSERT(ControlArea->u.Flags.Rom == 0);
1067  ASSERT(ControlArea->u.Flags.WasPurged == 0);
1068 
1069  /* Increase the reference and map count on the control area, no purges yet */
1070  Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
1071  ASSERT(NT_SUCCESS(Status));
1072 
1073  /* Get the section size at creation time */
1074  SectionSize = ((PSECTION)Section)->SizeOfSection.LowPart;
1075 
1076  /* If the caller didn't specify a view size, assume the whole section */
1077  if (!(*ViewSize)) *ViewSize = SectionSize;
1078 
1079  /* Check if the caller wanted a larger section than the view */
1080  if (*ViewSize > SectionSize)
1081  {
1082  /* Fail */
1083  DPRINT1("View is too large\n");
1084  MiDereferenceControlArea(ControlArea);
1085  return STATUS_INVALID_VIEW_SIZE;
1086  }
1087 
1088  /* Get the number of 64K buckets required for this mapping */
1089  Buckets = (ULONG)(*ViewSize / MI_SYSTEM_VIEW_BUCKET_SIZE);
1090  if (*ViewSize & (MI_SYSTEM_VIEW_BUCKET_SIZE - 1)) Buckets++;
1091 
1092  /* Check if the view is more than 4GB large */
1093  if (Buckets >= MI_SYSTEM_VIEW_BUCKET_SIZE)
1094  {
1095  /* Fail */
1096  DPRINT1("View is too large\n");
1097  MiDereferenceControlArea(ControlArea);
1098  return STATUS_INVALID_VIEW_SIZE;
1099  }
1100 
1101  /* Insert this view into system space and get a base address for it */
1102  Base = MiInsertInSystemSpace(Session, Buckets, ControlArea);
1103  if (!Base)
1104  {
1105  /* Fail */
1106  DPRINT1("Out of system space\n");
1107  MiDereferenceControlArea(ControlArea);
1108  return STATUS_NO_MEMORY;
1109  }
1110 
1111  /* What's the underlying session? */
1112  if (Session == &MmSession)
1113  {
1114  /* Create the PDEs needed for this mapping, and double-map them if needed */
1116  Status = STATUS_SUCCESS;
1117  }
1118  else
1119  {
1120  /* Create the PDEs needed for this mapping */
1121  Status = MiSessionCommitPageTables(Base,
1122  (PVOID)((ULONG_PTR)Base +
1123  Buckets * MI_SYSTEM_VIEW_BUCKET_SIZE));
1124  ASSERT(NT_SUCCESS(Status));
1125  }
1126 
1127  /* Create the actual prototype PTEs for this mapping */
1128  Status = MiAddMappedPtes(MiAddressToPte(Base),
1129  BYTES_TO_PAGES(*ViewSize),
1130  ControlArea);
1131  ASSERT(NT_SUCCESS(Status));
1132 
1133  /* Return the base adress of the mapping and success */
1134  *MappedBase = Base;
1135  return STATUS_SUCCESS;
1136 }
1137 
1138 VOID
1139 NTAPI
1141 {
1142  KIRQL OldIrql;
1143 
1145 
1147  ControlArea->u.Flags.DebugSymbolsLoaded |= 1;
1148 
1149  ASSERT(OldIrql <= APC_LEVEL);
1152 }
1153 
1154 VOID
1155 NTAPI
1159 {
1160  NTSTATUS Status;
1162  PLIST_ENTRY NextEntry;
1164  PIMAGE_NT_HEADERS NtHeaders;
1165  PLDR_DATA_TABLE_ENTRY LdrEntry;
1166 
1167  FileName = &ControlArea->FilePointer->FileName;
1168  if (FileName->Length == 0)
1169  {
1170  return;
1171  }
1172 
1173  /* Acquire module list lock */
1176 
1177  /* Browse list to try to find current module */
1178  for (NextEntry = MmLoadedUserImageList.Flink;
1179  NextEntry != &MmLoadedUserImageList;
1180  NextEntry = NextEntry->Flink)
1181  {
1182  /* Get the entry */
1183  LdrEntry = CONTAINING_RECORD(NextEntry,
1185  InLoadOrderLinks);
1186 
1187  /* If already in the list, increase load count */
1188  if (LdrEntry->DllBase == BaseAddress)
1189  {
1190  ++LdrEntry->LoadCount;
1191  break;
1192  }
1193  }
1194 
1195  /* Not in the list, we'll add it */
1196  if (NextEntry == &MmLoadedUserImageList)
1197  {
1198  /* Allocate our element, taking to the name string and its null char */
1199  LdrEntry = ExAllocatePoolWithTag(NonPagedPool, FileName->Length + sizeof(UNICODE_NULL) + sizeof(*LdrEntry), 'bDmM');
1200  if (LdrEntry)
1201  {
1202  memset(LdrEntry, 0, FileName->Length + sizeof(UNICODE_NULL) + sizeof(*LdrEntry));
1203 
1204  _SEH2_TRY
1205  {
1206  /* Get image checksum and size */
1207  NtHeaders = RtlImageNtHeader(BaseAddress);
1208  if (NtHeaders)
1209  {
1210  LdrEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage;
1211  LdrEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum;
1212  }
1213  }
1215  {
1216  ExFreePoolWithTag(LdrEntry, 'bDmM');
1217  _SEH2_YIELD(return);
1218  }
1219  _SEH2_END;
1220 
1221  /* Fill all the details */
1222  LdrEntry->DllBase = BaseAddress;
1223  LdrEntry->FullDllName.Buffer = (PVOID)((ULONG_PTR)LdrEntry + sizeof(*LdrEntry));
1224  LdrEntry->FullDllName.Length = FileName->Length;
1225  LdrEntry->FullDllName.MaximumLength = FileName->Length + sizeof(UNICODE_NULL);
1226  memcpy(LdrEntry->FullDllName.Buffer, FileName->Buffer, FileName->Length);
1227  LdrEntry->FullDllName.Buffer[LdrEntry->FullDllName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1228  LdrEntry->LoadCount = 1;
1229 
1230  /* Insert! */
1232  }
1233  }
1234 
1235  /* Release locks */
1238 
1239  /* Load symbols */
1240  Status = RtlUnicodeStringToAnsiString(&FileNameA, FileName, TRUE);
1241  if (NT_SUCCESS(Status))
1242  {
1243  DbgLoadImageSymbols(&FileNameA, BaseAddress, (ULONG_PTR)Process->UniqueProcessId);
1244  RtlFreeAnsiString(&FileNameA);
1245  }
1246 }
1247 
1248 NTSTATUS
1249 NTAPI
1252  IN PVOID *BaseAddress,
1255  IN PSECTION Section,
1257  IN ULONG ProtectionMask,
1261 {
1262  PMMVAD_LONG Vad;
1263  ULONG_PTR StartAddress;
1264  ULONG_PTR ViewSizeInPages;
1265  PSUBSECTION Subsection;
1266  PSEGMENT Segment;
1267  PFN_NUMBER PteOffset;
1268  NTSTATUS Status;
1269  ULONG QuotaCharge = 0, QuotaExcess = 0;
1270  PMMPTE PointerPte, LastPte;
1271  MMPTE TempPte;
1272  ULONG Granularity = MM_VIRTMEM_GRANULARITY;
1273 
1274  DPRINT("Mapping ARM3 data section\n");
1275 
1276  /* Get the segment for this section */
1277  Segment = ControlArea->Segment;
1278 
1279 #ifdef _M_IX86
1280  /* ALlow being less restrictive on x86. */
1281  if (AllocationType & MEM_DOS_LIM)
1282  Granularity = PAGE_SIZE;
1283 #endif
1284 
1285  /* One can only reserve a file-based mapping, not shared memory! */
1286  if ((AllocationType & MEM_RESERVE) && !(ControlArea->FilePointer))
1287  {
1289  }
1290 
1291  /* First, increase the map count. No purging is supported yet */
1292  Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
1293  if (!NT_SUCCESS(Status)) return Status;
1294 
1295  /* Check if the caller specified the view size */
1296  if (!(*ViewSize))
1297  {
1298  /* The caller did not, so pick a 64K aligned view size based on the offset */
1299  SectionOffset->LowPart &= ~(_64K - 1);
1300  *ViewSize = (SIZE_T)(Section->SizeOfSection.QuadPart - SectionOffset->QuadPart);
1301  }
1302  else
1303  {
1304  /* A size was specified, align it to a 64K boundary */
1305  *ViewSize += SectionOffset->LowPart & (_64K - 1);
1306 
1307  /* Align the offset as well to make this an aligned map */
1308  SectionOffset->LowPart &= ~((ULONG)_64K - 1);
1309  }
1310 
1311  /* We must be dealing with a 64KB aligned offset. This is a Windows ASSERT */
1312  ASSERT((SectionOffset->LowPart & ((ULONG)_64K - 1)) == 0);
1313 
1314  /* It's illegal to try to map more than overflows a LONG_PTR */
1315  if (*ViewSize >= MAXLONG_PTR)
1316  {
1317  MiDereferenceControlArea(ControlArea);
1318  return STATUS_INVALID_VIEW_SIZE;
1319  }
1320 
1321  /* Windows ASSERTs for this flag */
1322  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
1323 
1324  /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
1325  ASSERT(ControlArea->u.Flags.Rom == 0);
1326  Subsection = (PSUBSECTION)(ControlArea + 1);
1327 
1328  /* Sections with extended segments are not supported in ARM3 */
1329  ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0);
1330 
1331  /* Within this section, figure out which PTEs will describe the view */
1332  PteOffset = (PFN_NUMBER)(SectionOffset->QuadPart >> PAGE_SHIFT);
1333 
1334  /* The offset must be in this segment's PTE chunk and it must be valid. Windows ASSERTs */
1335  ASSERT(PteOffset < Segment->TotalNumberOfPtes);
1336  ASSERT(((SectionOffset->QuadPart + *ViewSize + PAGE_SIZE - 1) >> PAGE_SHIFT) >= PteOffset);
1337 
1338  /* In ARM3, only one subsection is used for now. It must contain these PTEs */
1339  ASSERT(PteOffset < Subsection->PtesInSubsection);
1340 
1341  /* In ARM3, only page-file backed sections (shared memory) are supported now */
1342  ASSERT(ControlArea->FilePointer == NULL);
1343 
1344  /* Windows ASSERTs for this too -- there must be a subsection base address */
1345  ASSERT(Subsection->SubsectionBase != NULL);
1346 
1347  /* Compute how much commit space the segment will take */
1348  if ((CommitSize) && (Segment->NumberOfCommittedPages < Segment->TotalNumberOfPtes))
1349  {
1350  /* Charge for the maximum pages */
1351  QuotaCharge = BYTES_TO_PAGES(CommitSize);
1352  }
1353 
1354  /* ARM3 does not currently support large pages */
1355  ASSERT(Segment->SegmentFlags.LargePages == 0);
1356 
1357  /* Calculate how many pages the region spans */
1358  ViewSizeInPages = BYTES_TO_PAGES(*ViewSize);
1359 
1360  /* A VAD can now be allocated. Do so and zero it out */
1361  /* FIXME: we are allocating a LONG VAD for ReactOS compatibility only */
1362  ASSERT((AllocationType & MEM_RESERVE) == 0); /* ARM3 does not support this */
1363  Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
1364  if (!Vad)
1365  {
1366  MiDereferenceControlArea(ControlArea);
1368  }
1369 
1370  RtlZeroMemory(Vad, sizeof(MMVAD_LONG));
1371  Vad->u4.Banked = (PVOID)0xDEADBABE;
1372 
1373  /* Write all the data required in the VAD for handling a fault */
1374  Vad->ControlArea = ControlArea;
1375  Vad->u.VadFlags.CommitCharge = 0;
1376  Vad->u.VadFlags.Protection = ProtectionMask;
1377  Vad->u2.VadFlags2.FileOffset = (ULONG)(SectionOffset->QuadPart >> 16);
1378  Vad->u2.VadFlags2.Inherit = (InheritDisposition == ViewShare);
1379  if ((AllocationType & SEC_NO_CHANGE) || (Section->u.Flags.NoChange))
1380  {
1381  /* This isn't really implemented yet, but handle setting the flag */
1382  Vad->u.VadFlags.NoChange = 1;
1383  Vad->u2.VadFlags2.SecNoChange = 1;
1384  }
1385 
1386  /* Finally, write down the first and last prototype PTE */
1387  Vad->FirstPrototypePte = &Subsection->SubsectionBase[PteOffset];
1388  PteOffset += ViewSizeInPages - 1;
1389  ASSERT(PteOffset < Subsection->PtesInSubsection);
1390  Vad->LastContiguousPte = &Subsection->SubsectionBase[PteOffset];
1391 
1392  /* Make sure the prototype PTE ranges make sense, this is a Windows ASSERT */
1394 
1395  /* FIXME: Should setup VAD bitmap */
1396  Status = STATUS_SUCCESS;
1397 
1398  /* Check if anything was committed */
1399  if (QuotaCharge)
1400  {
1401  /* Set the start and end PTE addresses, and pick the template PTE */
1402  PointerPte = Vad->FirstPrototypePte;
1403  LastPte = PointerPte + BYTES_TO_PAGES(CommitSize);
1404  TempPte = Segment->SegmentPteTemplate;
1405 
1406  /* Acquire the commit lock and loop all prototype PTEs to be committed */
1407  KeAcquireGuardedMutex(&MmSectionCommitMutex);
1408  while (PointerPte < LastPte)
1409  {
1410  /* Make sure the PTE is already invalid */
1411  if (PointerPte->u.Long == 0)
1412  {
1413  /* And write the invalid PTE */
1414  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
1415  }
1416  else
1417  {
1418  /* The PTE is valid, so skip it */
1419  QuotaExcess++;
1420  }
1421 
1422  /* Move to the next PTE */
1423  PointerPte++;
1424  }
1425 
1426  /* Now check how many pages exactly we committed, and update accounting */
1427  ASSERT(QuotaCharge >= QuotaExcess);
1428  QuotaCharge -= QuotaExcess;
1429  Segment->NumberOfCommittedPages += QuotaCharge;
1430  ASSERT(Segment->NumberOfCommittedPages <= Segment->TotalNumberOfPtes);
1431 
1432  /* Now that we're done, release the lock */
1433  KeReleaseGuardedMutex(&MmSectionCommitMutex);
1434  }
1435 
1436  /* Is it SEC_BASED, or did the caller manually specify an address? */
1437  if (*BaseAddress != NULL)
1438  {
1439  /* Just align what the caller gave us */
1440  StartAddress = ALIGN_DOWN_BY((ULONG_PTR)*BaseAddress, Granularity);
1441  }
1442  else if (Section->Address.StartingVpn != 0)
1443  {
1444  /* It is a SEC_BASED mapping, use the address that was generated */
1445  StartAddress = Section->Address.StartingVpn + SectionOffset->LowPart;
1446  }
1447  else
1448  {
1449  StartAddress = 0;
1450  }
1451 
1452  /* Insert the VAD */
1453  Status = MiInsertVadEx((PMMVAD)Vad,
1454  &StartAddress,
1455  ViewSizeInPages * PAGE_SIZE,
1456  MAXULONG_PTR >> ZeroBits,
1457  Granularity,
1458  AllocationType);
1459  if (!NT_SUCCESS(Status))
1460  {
1461  return Status;
1462  }
1463 
1464  /* Windows stores this for accounting purposes, do so as well */
1465  if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
1466 
1467  /* Finally, let the caller know where, and for what size, the view was mapped */
1468  *ViewSize = ViewSizeInPages * PAGE_SIZE;
1469  *BaseAddress = (PVOID)StartAddress;
1470  DPRINT("Start and region: 0x%p, 0x%p\n", *BaseAddress, *ViewSize);
1471  return STATUS_SUCCESS;
1472 }
1473 
1474 VOID
1475 NTAPI
1477 {
1478  /* ReactOS only supports systems with 4K pages and 4K sectors */
1479  ASSERT(Subsection->u.SubsectionFlags.SectorEndOffset == 0);
1480 
1481  /* Therefore, then number of PTEs should be equal to the number of sectors */
1482  if (Subsection->NumberOfFullSectors != Subsection->PtesInSubsection)
1483  {
1484  /* Break and warn if this is inconsistent */
1485  DPRINT1("Mm: Subsection inconsistent (%x vs %x)\n",
1486  Subsection->NumberOfFullSectors, Subsection->PtesInSubsection);
1487  DbgBreakPoint();
1488  }
1489 }
1490 
1491 NTSTATUS
1492 NTAPI
1494  OUT PSEGMENT *Segment,
1498  IN ULONG IgnoreFileSizing)
1499 {
1500  /* Not yet implemented */
1501  ASSERT(FALSE);
1502  *Segment = NULL;
1503  return STATUS_NOT_IMPLEMENTED;
1504 }
1505 
1506 NTSTATUS
1507 NTAPI
1510  IN ULONG ProtectionMask,
1512 {
1513  SIZE_T SizeLimit;
1514  PFN_COUNT PteCount;
1515  PMMPTE PointerPte;
1516  MMPTE TempPte;
1517  PCONTROL_AREA ControlArea;
1518  PSEGMENT NewSegment;
1519  PSUBSECTION Subsection;
1520  PAGED_CODE();
1521 
1522  /* No large pages in ARM3 yet */
1523  ASSERT((AllocationAttributes & SEC_LARGE_PAGES) == 0);
1524 
1525  /* Pagefile-backed sections need a known size */
1526  if (!(*MaximumSize)) return STATUS_INVALID_PARAMETER_4;
1527 
1528  /* Calculate the maximum size possible, given the Prototype PTEs we'll need */
1529  SizeLimit = MAXULONG_PTR - sizeof(SEGMENT);
1530  SizeLimit /= sizeof(MMPTE);
1531  SizeLimit <<= PAGE_SHIFT;
1532 
1533  /* Fail if this size is too big */
1534  if (*MaximumSize > SizeLimit) return STATUS_SECTION_TOO_BIG;
1535 
1536  /* Calculate how many Prototype PTEs will be needed */
1537  PteCount = (PFN_COUNT)((*MaximumSize + PAGE_SIZE - 1) >> PAGE_SHIFT);
1538 
1539  /* For commited memory, we must have a valid protection mask */
1540  if (AllocationAttributes & SEC_COMMIT) ASSERT(ProtectionMask != 0);
1541 
1542  /* The segment contains all the Prototype PTEs, allocate it in paged pool */
1543  NewSegment = ExAllocatePoolWithTag(PagedPool,
1544  sizeof(SEGMENT) +
1545  sizeof(MMPTE) * (PteCount - 1),
1546  'tSmM');
1547  ASSERT(NewSegment);
1548  *Segment = NewSegment;
1549 
1550  /* Now allocate the control area, which has the subsection structure */
1551  ControlArea = ExAllocatePoolWithTag(NonPagedPool,
1552  sizeof(CONTROL_AREA) + sizeof(SUBSECTION),
1553  'tCmM');
1554  ASSERT(ControlArea);
1555 
1556  /* And zero it out, filling the basic segmnet pointer and reference fields */
1557  RtlZeroMemory(ControlArea, sizeof(CONTROL_AREA) + sizeof(SUBSECTION));
1558  ControlArea->Segment = NewSegment;
1559  ControlArea->NumberOfSectionReferences = 1;
1560  ControlArea->NumberOfUserReferences = 1;
1561 
1562  /* Convert allocation attributes to control area flags */
1563  if (AllocationAttributes & SEC_BASED) ControlArea->u.Flags.Based = 1;
1564  if (AllocationAttributes & SEC_RESERVE) ControlArea->u.Flags.Reserve = 1;
1565  if (AllocationAttributes & SEC_COMMIT) ControlArea->u.Flags.Commit = 1;
1566 
1567  /* We just allocated it */
1568  ControlArea->u.Flags.BeingCreated = 1;
1569 
1570  /* The subsection follows, write the mask, PTE count and point back to the CA */
1571  Subsection = (PSUBSECTION)(ControlArea + 1);
1572  Subsection->ControlArea = ControlArea;
1573  Subsection->PtesInSubsection = PteCount;
1574  Subsection->u.SubsectionFlags.Protection = ProtectionMask;
1575 
1576  /* Zero out the segment's prototype PTEs, and link it with the control area */
1577  PointerPte = &NewSegment->ThePtes[0];
1578  RtlZeroMemory(NewSegment, sizeof(SEGMENT));
1579  NewSegment->PrototypePte = PointerPte;
1580  NewSegment->ControlArea = ControlArea;
1581 
1582  /* Save some extra accounting data for the segment as well */
1583  NewSegment->u1.CreatingProcess = PsGetCurrentProcess();
1584  NewSegment->SizeOfSegment = PteCount * PAGE_SIZE;
1585  NewSegment->TotalNumberOfPtes = PteCount;
1586  NewSegment->NonExtendedPtes = PteCount;
1587 
1588  /* The subsection's base address is the first Prototype PTE in the segment */
1589  Subsection->SubsectionBase = PointerPte;
1590 
1591  /* Start with an empty PTE, unless this is a commit operation */
1592  TempPte.u.Long = 0;
1593  if (AllocationAttributes & SEC_COMMIT)
1594  {
1595  /* In which case, write down the protection mask in the Prototype PTEs */
1596  TempPte.u.Soft.Protection = ProtectionMask;
1597 
1598  /* For accounting, also mark these pages as being committed */
1599  NewSegment->NumberOfCommittedPages = PteCount;
1600  }
1601 
1602  /* The template PTE itself for the segment should also have the mask set */
1603  NewSegment->SegmentPteTemplate.u.Soft.Protection = ProtectionMask;
1604 
1605  /* Write out the prototype PTEs, for now they're simply demand zero */
1606 #ifdef _WIN64
1607  RtlFillMemoryUlonglong(PointerPte, PteCount * sizeof(MMPTE), TempPte.u.Long);
1608 #else
1609  RtlFillMemoryUlong(PointerPte, PteCount * sizeof(MMPTE), TempPte.u.Long);
1610 #endif
1611  return STATUS_SUCCESS;
1612 }
1613 
1614 NTSTATUS
1615 NTAPI
1617  IN PVOID Address,
1619 {
1620  PMMVAD Vad;
1621  PCONTROL_AREA ControlArea;
1622 
1623  /* Get the VAD */
1624  Vad = MiLocateAddress(Address);
1625  if (Vad == NULL)
1626  {
1627  /* Fail, the address does not exist */
1628  DPRINT1("Invalid address\n");
1629  return STATUS_INVALID_ADDRESS;
1630  }
1631 
1632  /* Check if this is a RosMm memory area */
1633  if (Vad->u.VadFlags.Spare != 0)
1634  {
1636  PROS_SECTION_OBJECT Section;
1637 
1638  /* Check if it's a section view (RosMm section) */
1639  if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
1640  {
1641  /* Get the section pointer to the SECTION_OBJECT */
1642  Section = MemoryArea->Data.SectionData.Section;
1643  *FileObject = Section->FileObject;
1644  }
1645  else
1646  {
1647  ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
1648  DPRINT1("Address is a cache section!\n");
1649  return STATUS_SECTION_NOT_IMAGE;
1650  }
1651  }
1652  else
1653  {
1654  /* Make sure it's not a VM VAD */
1655  if (Vad->u.VadFlags.PrivateMemory == 1)
1656  {
1657  DPRINT1("Address is not a section\n");
1658  return STATUS_SECTION_NOT_IMAGE;
1659  }
1660 
1661  /* Get the control area */
1662  ControlArea = Vad->ControlArea;
1663  if (!(ControlArea) || !(ControlArea->u.Flags.Image))
1664  {
1665  DPRINT1("Address is not a section\n");
1666  return STATUS_SECTION_NOT_IMAGE;
1667  }
1668 
1669  /* Get the file object */
1670  *FileObject = ControlArea->FilePointer;
1671  }
1672 
1673  /* Return success */
1674  return STATUS_SUCCESS;
1675 }
1676 
1678 NTAPI
1680 {
1681  PSECTION_OBJECT Section;
1683  ASSERT(SectionObject != NULL);
1684 
1685  /* Check if it's an ARM3, or ReactOS section */
1686  if (MiIsRosSectionObject(SectionObject) == FALSE)
1687  {
1688  /* Return the file pointer stored in the control area */
1689  Section = SectionObject;
1690  return Section->Segment->ControlArea->FilePointer;
1691  }
1692 
1693  /* Return the file object */
1694  return ((PROS_SECTION_OBJECT)SectionObject)->FileObject;
1695 }
1696 
1697 static
1700  _In_ PMMVAD Vad)
1701 {
1702  PCONTROL_AREA ControlArea;
1704 
1705  /* Check if this is a RosMm memory area */
1706  if (Vad->u.VadFlags.Spare != 0)
1707  {
1709  PROS_SECTION_OBJECT Section;
1710 
1711  /* Check if it's a section view (RosMm section) */
1712  if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
1713  {
1714  /* Get the section pointer to the SECTION_OBJECT */
1715  Section = MemoryArea->Data.SectionData.Section;
1716  FileObject = Section->FileObject;
1717  }
1718  else
1719  {
1720  ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE);
1721  DPRINT1("VAD is a cache section!\n");
1722  return NULL;
1723  }
1724  }
1725  else
1726  {
1727  /* Make sure it's not a VM VAD */
1728  if (Vad->u.VadFlags.PrivateMemory == 1)
1729  {
1730  DPRINT1("VAD is not a section\n");
1731  return NULL;
1732  }
1733 
1734  /* Get the control area */
1735  ControlArea = Vad->ControlArea;
1736  if ((ControlArea == NULL) || !ControlArea->u.Flags.Image)
1737  {
1738  DPRINT1("Address is not a section\n");
1739  return NULL;
1740  }
1741 
1742  /* Get the file object */
1743  FileObject = ControlArea->FilePointer;
1744  }
1745 
1746  /* Return the file object */
1747  return FileObject;
1748 }
1749 
1750 VOID
1751 NTAPI
1753 {
1755 
1756  /* Get the section object of this process*/
1757  SectionObject = PsGetCurrentProcess()->SectionObject;
1758  ASSERT(SectionObject != NULL);
1759  ASSERT(MiIsRosSectionObject(SectionObject) == TRUE);
1760 
1761  /* Return the image information */
1762  *ImageInformation = ((PROS_SECTION_OBJECT)SectionObject)->ImageSection->ImageInformation;
1763 }
1764 
1765 NTSTATUS
1766 NTAPI
1769 {
1770  POBJECT_NAME_INFORMATION ObjectNameInfo;
1771  NTSTATUS Status;
1773 
1774  /* Allocate memory for our structure */
1775  ObjectNameInfo = ExAllocatePoolWithTag(PagedPool, 1024, TAG_MM);
1776  if (!ObjectNameInfo) return STATUS_NO_MEMORY;
1777 
1778  /* Query the name */
1779  Status = ObQueryNameString(FileObject,
1780  ObjectNameInfo,
1781  1024,
1782  &ReturnLength);
1783  if (!NT_SUCCESS(Status))
1784  {
1785  /* Failed, free memory */
1786  DPRINT1("Name query failed\n");
1787  ExFreePoolWithTag(ObjectNameInfo, TAG_MM);
1788  *ModuleName = NULL;
1789  return Status;
1790  }
1791 
1792  /* Success */
1793  *ModuleName = ObjectNameInfo;
1794  return STATUS_SUCCESS;
1795 }
1796 
1797 NTSTATUS
1798 NTAPI
1801 {
1803 
1804  /* Make sure it's an image section */
1805  if (MiIsRosSectionObject(Section) == FALSE)
1806  {
1807  /* Check ARM3 Section flag */
1808  if (((PSECTION)Section)->u.Flags.Image == 0)
1809  {
1810  /* It's not, fail */
1811  DPRINT1("Not an image section\n");
1812  return STATUS_SECTION_NOT_IMAGE;
1813  }
1814  }
1815  else if (!(((PROS_SECTION_OBJECT)Section)->AllocationAttributes & SEC_IMAGE))
1816  {
1817  /* It's not, fail */
1818  DPRINT1("Not an image section\n");
1819  return STATUS_SECTION_NOT_IMAGE;
1820  }
1821 
1822  /* Get the file object */
1823  FileObject = MmGetFileObjectForSection(Section);
1824  return MmGetFileNameForFileObject(FileObject, ModuleName);
1825 }
1826 
1827 NTSTATUS
1828 NTAPI
1831 {
1832  POBJECT_NAME_INFORMATION ModuleNameInformation;
1834  NTSTATUS Status;
1835  PMMVAD Vad;
1837 
1838  /* Lock address space */
1839  AddressSpace = MmGetCurrentAddressSpace();
1840  MmLockAddressSpace(AddressSpace);
1841 
1842  /* Get the VAD */
1843  Vad = MiLocateAddress(Address);
1844  if (Vad == NULL)
1845  {
1846  /* Fail, the address does not exist */
1847  DPRINT1("No VAD at address %p\n", Address);
1848  MmUnlockAddressSpace(AddressSpace);
1849  return STATUS_INVALID_ADDRESS;
1850  }
1851 
1852  /* Get the file object pointer for the VAD */
1853  FileObject = MiGetFileObjectForVad(Vad);
1854  if (FileObject == NULL)
1855  {
1856  DPRINT1("Failed to get file object for Address %p\n", Address);
1857  MmUnlockAddressSpace(AddressSpace);
1858  return STATUS_SECTION_NOT_IMAGE;
1859  }
1860 
1861  /* Reference the file object */
1862  ObReferenceObject(FileObject);
1863 
1864  /* Unlock address space */
1865  MmUnlockAddressSpace(AddressSpace);
1866 
1867  /* Get the filename of the file object */
1868  Status = MmGetFileNameForFileObject(FileObject, &ModuleNameInformation);
1869 
1870  /* Dereference the file object */
1871  ObDereferenceObject(FileObject);
1872 
1873  /* Check if we were able to get the file object name */
1874  if (NT_SUCCESS(Status))
1875  {
1876  /* Init modulename */
1877  RtlCreateUnicodeString(ModuleName, ModuleNameInformation->Name.Buffer);
1878 
1879  /* Free temp taged buffer from MmGetFileNameForFileObject() */
1880  ExFreePoolWithTag(ModuleNameInformation, TAG_MM);
1881  DPRINT("Found ModuleName %S by address %p\n", ModuleName->Buffer, Address);
1882  }
1883 
1884  /* Return status */
1885  return Status;
1886 }
1887 
1888 NTSTATUS
1889 NTAPI
1892  OUT PVOID MemoryInformation,
1893  IN SIZE_T MemoryInformationLength,
1895 {
1897  NTSTATUS Status;
1898  WCHAR ModuleFileNameBuffer[MAX_PATH] = {0};
1900  PMEMORY_SECTION_NAME SectionName = NULL;
1902 
1903  Status = ObReferenceObjectByHandle(ProcessHandle,
1905  NULL,
1906  PreviousMode,
1907  (PVOID*)(&Process),
1908  NULL);
1909 
1910  if (!NT_SUCCESS(Status))
1911  {
1912  DPRINT("MiQueryMemorySectionName: ObReferenceObjectByHandle returned %x\n",Status);
1913  return Status;
1914  }
1915 
1916  RtlInitEmptyUnicodeString(&ModuleFileName, ModuleFileNameBuffer, sizeof(ModuleFileNameBuffer));
1917  Status = MmGetFileNameForAddress(BaseAddress, &ModuleFileName);
1918 
1919  if (NT_SUCCESS(Status))
1920  {
1921  SectionName = MemoryInformation;
1922  if (PreviousMode != KernelMode)
1923  {
1924  _SEH2_TRY
1925  {
1926  RtlInitUnicodeString(&SectionName->SectionFileName, SectionName->NameBuffer);
1927  SectionName->SectionFileName.MaximumLength = (USHORT)MemoryInformationLength;
1928  RtlCopyUnicodeString(&SectionName->SectionFileName, &ModuleFileName);
1929 
1930  if (ReturnLength) *ReturnLength = ModuleFileName.Length;
1931 
1932  }
1934  {
1935  Status = _SEH2_GetExceptionCode();
1936  }
1937  _SEH2_END;
1938  }
1939  else
1940  {
1941  RtlInitUnicodeString(&SectionName->SectionFileName, SectionName->NameBuffer);
1942  SectionName->SectionFileName.MaximumLength = (USHORT)MemoryInformationLength;
1943  RtlCopyUnicodeString(&SectionName->SectionFileName, &ModuleFileName);
1944 
1945  if (ReturnLength) *ReturnLength = ModuleFileName.Length;
1946 
1947  }
1948  }
1949  ObDereferenceObject(Process);
1950  return Status;
1951 }
1952 
1953 VOID
1954 NTAPI
1956  IN PMMPTE PointerPte,
1957  IN ULONG ProtectionMask,
1958  IN PMMPFN Pfn1,
1959  IN BOOLEAN UpdateDirty)
1960 {
1961  MMPTE TempPte, PreviousPte;
1962  KIRQL OldIrql;
1963  BOOLEAN RebuildPte = FALSE;
1964 
1965  //
1966  // User for sanity checking later on
1967  //
1968  PreviousPte = *PointerPte;
1969 
1970  //
1971  // Build the PTE and acquire the PFN lock
1972  //
1973  MI_MAKE_HARDWARE_PTE_USER(&TempPte,
1974  PointerPte,
1975  ProtectionMask,
1976  PreviousPte.u.Hard.PageFrameNumber);
1978 
1979  //
1980  // We don't support I/O mappings in this path yet
1981  //
1982  ASSERT(Pfn1 != NULL);
1983  ASSERT(Pfn1->u3.e1.CacheAttribute != MiWriteCombined);
1984 
1985  //
1986  // Make sure new protection mask doesn't get in conflict and fix it if it does
1987  //
1988  if (Pfn1->u3.e1.CacheAttribute == MiCached)
1989  {
1990  //
1991  // This is a cached PFN
1992  //
1993  if (ProtectionMask & (MM_NOCACHE | MM_NOACCESS))
1994  {
1995  RebuildPte = TRUE;
1996  ProtectionMask &= ~(MM_NOCACHE | MM_NOACCESS);
1997  }
1998  }
1999  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
2000  {
2001  //
2002  // This is a non-cached PFN
2003  //
2004  if ((ProtectionMask & (MM_NOCACHE | MM_NOACCESS)) != MM_NOCACHE)
2005  {
2006  RebuildPte = TRUE;
2007  ProtectionMask &= ~MM_NOACCESS;
2008  ProtectionMask |= MM_NOCACHE;
2009  }
2010  }
2011 
2012  if (RebuildPte)
2013  {
2014  MI_MAKE_HARDWARE_PTE_USER(&TempPte,
2015  PointerPte,
2016  ProtectionMask,
2017  PreviousPte.u.Hard.PageFrameNumber);
2018  }
2019 
2020  //
2021  // Write the new PTE, making sure we are only changing the bits
2022  //
2023  MI_UPDATE_VALID_PTE(PointerPte, TempPte);
2024 
2025  //
2026  // Flush the TLB
2027  //
2028  ASSERT(PreviousPte.u.Hard.Valid == 1);
2029  KeFlushCurrentTb();
2030  ASSERT(PreviousPte.u.Hard.Valid == 1);
2031 
2032  //
2033  // Windows updates the relevant PFN1 information, we currently don't.
2034  //
2035  if (UpdateDirty && PreviousPte.u.Hard.Dirty)
2036  {
2037  if (!Pfn1->u3.e1.Modified)
2038  {
2039  DPRINT1("FIXME: Mark PFN as dirty\n");
2040  }
2041  }
2042 
2043  //
2044  // Not supported in ARM3
2045  //
2046  ASSERT(FoundVad->u.VadFlags.VadType != VadWriteWatch);
2047 
2048  //
2049  // Release the PFN lock, we are done
2050  //
2052 }
2053 
2054 //
2055 // NOTE: This function gets a lot more complicated if we want Copy-on-Write support
2056 //
2057 NTSTATUS
2058 NTAPI
2060  IN PMMVAD FoundVad,
2061  IN PVOID StartingAddress,
2062  IN PVOID EndingAddress,
2064  OUT PULONG CapturedOldProtect,
2065  IN ULONG DontCharge,
2066  OUT PULONG Locked)
2067 {
2068  PMMPTE PointerPte, LastPte;
2069  MMPTE TempPte, PteContents;
2070  PMMPDE PointerPde;
2071  PMMPFN Pfn1;
2072  ULONG ProtectionMask, QuotaCharge = 0;
2074  PAGED_CODE();
2075 
2076  //
2077  // Tell caller nothing is being locked
2078  //
2079  *Locked = FALSE;
2080 
2081  //
2082  // This function should only be used for section VADs. Windows ASSERT */
2083  //
2084  ASSERT(FoundVad->u.VadFlags.PrivateMemory == 0);
2085 
2086  //
2087  // We don't support these features in ARM3
2088  //
2089  ASSERT(FoundVad->u.VadFlags.VadType != VadImageMap);
2090  ASSERT(FoundVad->u2.VadFlags2.CopyOnWrite == 0);
2091 
2092  //
2093  // Convert and validate the protection mask
2094  //
2095  ProtectionMask = MiMakeProtectionMask(NewProtect);
2096  if (ProtectionMask == MM_INVALID_PROTECTION)
2097  {
2098  DPRINT1("Invalid section protect\n");
2100  }
2101 
2102  //
2103  // Get the PTE and PDE for the address, as well as the final PTE
2104  //
2105  MiLockProcessWorkingSetUnsafe(Process, Thread);
2106  PointerPde = MiAddressToPde(StartingAddress);
2107  PointerPte = MiAddressToPte(StartingAddress);
2108  LastPte = MiAddressToPte(EndingAddress);
2109 
2110  //
2111  // Make the PDE valid, and check the status of the first PTE
2112  //
2113  MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
2114  if (PointerPte->u.Long)
2115  {
2116  //
2117  // Not supported in ARM3
2118  //
2119  ASSERT(FoundVad->u.VadFlags.VadType != VadRotatePhysical);
2120 
2121  //
2122  // Capture the page protection and make the PDE valid
2123  //
2124  *CapturedOldProtect = MiGetPageProtection(PointerPte);
2125  MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
2126  }
2127  else
2128  {
2129  //
2130  // Only pagefile-backed section VADs are supported for now
2131  //
2132  ASSERT(FoundVad->u.VadFlags.VadType != VadImageMap);
2133 
2134  //
2135  // Grab the old protection from the VAD itself
2136  //
2137  *CapturedOldProtect = MmProtectToValue[FoundVad->u.VadFlags.Protection];
2138  }
2139 
2140  //
2141  // Loop all the PTEs now
2142  //
2143  MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
2144  while (PointerPte <= LastPte)
2145  {
2146  //
2147  // Check if we've crossed a PDE boundary and make the new PDE valid too
2148  //
2149  if ((((ULONG_PTR)PointerPte) & (SYSTEM_PD_SIZE - 1)) == 0)
2150  {
2151  PointerPde = MiPteToPde(PointerPte);
2152  MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
2153  }
2154 
2155  //
2156  // Capture the PTE and see what we're dealing with
2157  //
2158  PteContents = *PointerPte;
2159  if (PteContents.u.Long == 0)
2160  {
2161  //
2162  // This used to be a zero PTE and it no longer is, so we must add a
2163  // reference to the pagetable.
2164  //
2166 
2167  //
2168  // Create the demand-zero prototype PTE
2169  //
2170  TempPte = PrototypePte;
2171  TempPte.u.Soft.Protection = ProtectionMask;
2172  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2173  }
2174  else if (PteContents.u.Hard.Valid == 1)
2175  {
2176  //
2177  // Get the PFN entry
2178  //
2179  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2180 
2181  //
2182  // We don't support these yet
2183  //
2184  ASSERT((NewProtect & (PAGE_NOACCESS | PAGE_GUARD)) == 0);
2185  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
2186 
2187  //
2188  // Write the protection mask and write it with a TLB flush
2189  //
2190  Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
2191  MiFlushTbAndCapture(FoundVad,
2192  PointerPte,
2193  ProtectionMask,
2194  Pfn1,
2195  TRUE);
2196  }
2197  else
2198  {
2199  //
2200  // We don't support these cases yet
2201  //
2202  ASSERT(PteContents.u.Soft.Prototype == 0);
2203  ASSERT(PteContents.u.Soft.Transition == 0);
2204 
2205  //
2206  // The PTE is already demand-zero, just update the protection mask
2207  //
2208  PointerPte->u.Soft.Protection = ProtectionMask;
2209  }
2210 
2211  PointerPte++;
2212  }
2213 
2214  //
2215  // Unlock the working set and update quota charges if needed, then return
2216  //
2217  MiUnlockProcessWorkingSetUnsafe(Process, Thread);
2218  if ((QuotaCharge > 0) && (!DontCharge))
2219  {
2220  FoundVad->u.VadFlags.CommitCharge -= QuotaCharge;
2221  Process->CommitCharge -= QuotaCharge;
2222  }
2223  return STATUS_SUCCESS;
2224 }
2225 
2226 VOID
2227 NTAPI
2229  IN ULONG NumberOfPtes,
2230  IN PCONTROL_AREA ControlArea,
2231  IN PMMSUPPORT Ws)
2232 {
2233  PMMPTE PointerPte, ProtoPte;//, FirstPte;
2234  PMMPDE PointerPde, SystemMapPde;
2235  PMMPFN Pfn1, Pfn2;
2236  MMPTE PteContents;
2237  KIRQL OldIrql;
2238  DPRINT("Removing mapped view at: 0x%p\n", BaseAddress);
2239 
2240  ASSERT(Ws == NULL);
2241 
2242  /* Get the PTE and loop each one */
2243  PointerPte = MiAddressToPte(BaseAddress);
2244  //FirstPte = PointerPte;
2245  while (NumberOfPtes)
2246  {
2247  /* Check if the PTE is already valid */
2248  PteContents = *PointerPte;
2249  if (PteContents.u.Hard.Valid == 1)
2250  {
2251  /* Get the PFN entry */
2252  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
2253 
2254  /* Get the PTE */
2255  PointerPde = MiPteToPde(PointerPte);
2256 
2257  /* Lock the PFN database and make sure this isn't a mapped file */
2259  ASSERT(((Pfn1->u3.e1.PrototypePte) && (Pfn1->OriginalPte.u.Soft.Prototype)) == 0);
2260 
2261  /* Mark the page as modified accordingly */
2262  if (MI_IS_PAGE_DIRTY(&PteContents))
2263  Pfn1->u3.e1.Modified = 1;
2264 
2265  /* Was the PDE invalid */
2266  if (PointerPde->u.Long == 0)
2267  {
2268 #if (_MI_PAGING_LEVELS == 2)
2269  /* Find the system double-mapped PDE that describes this mapping */
2270  SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
2271 
2272  /* Make it valid */
2273  ASSERT(SystemMapPde->u.Hard.Valid == 1);
2274  MI_WRITE_VALID_PDE(PointerPde, *SystemMapPde);
2275 #else
2276  DBG_UNREFERENCED_LOCAL_VARIABLE(SystemMapPde);
2277  ASSERT(FALSE);
2278 #endif
2279  }
2280 
2281  /* Dereference the PDE and the PTE */
2282  Pfn2 = MiGetPfnEntry(PFN_FROM_PTE(PointerPde));
2283  MiDecrementShareCount(Pfn2, PFN_FROM_PTE(PointerPde));
2285  MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
2286 
2287  /* Release the PFN lock */
2289  }
2290  else
2291  {
2292  /* Windows ASSERT */
2293  ASSERT((PteContents.u.Long == 0) || (PteContents.u.Soft.Prototype == 1));
2294 
2295  /* Check if this is a prototype pointer PTE */
2296  if (PteContents.u.Soft.Prototype == 1)
2297  {
2298  /* Get the prototype PTE */
2299  ProtoPte = MiProtoPteToPte(&PteContents);
2300 
2301  /* We don't support anything else atm */
2302  ASSERT(ProtoPte->u.Long == 0);
2303  }
2304  }
2305 
2306  /* Make the PTE into a zero PTE */
2307  PointerPte->u.Long = 0;
2308 
2309  /* Move to the next PTE */
2310  PointerPte++;
2311  NumberOfPtes--;
2312  }
2313 
2314  /* Flush the TLB */
2315  KeFlushCurrentTb();
2316 
2317  /* Acquire the PFN lock */
2319 
2320  /* Decrement the accounting counters */
2321  ControlArea->NumberOfUserReferences--;
2322  ControlArea->NumberOfMappedViews--;
2323 
2324  /* Check if we should destroy the CA and release the lock */
2325  MiCheckControlArea(ControlArea, OldIrql);
2326 }
2327 
2328 ULONG
2329 NTAPI
2331  IN PVOID Base,
2332  OUT PCONTROL_AREA *ControlArea)
2333 {
2334  ULONG Hash, Size, Count = 0;
2335  ULONG_PTR Entry;
2336  PAGED_CODE();
2337 
2338  /* Compute the hash for this entry and loop trying to find it */
2339  Entry = (ULONG_PTR)Base >> 16;
2340  Hash = Entry % Session->SystemSpaceHashKey;
2341  while ((Session->SystemSpaceViewTable[Hash].Entry >> 16) != Entry)
2342  {
2343  /* Check if we overflew past the end of the hash table */
2344  if (++Hash >= Session->SystemSpaceHashSize)
2345  {
2346  /* Reset the hash to zero and keep searching from the bottom */
2347  Hash = 0;
2348  if (++Count == 2)
2349  {
2350  /* But if we overflew twice, then this is not a real mapping */
2351  KeBugCheckEx(DRIVER_UNMAPPING_INVALID_VIEW,
2352  (ULONG_PTR)Base,
2353  1,
2354  0,
2355  0);
2356  }
2357  }
2358  }
2359 
2360  /* One less entry */
2361  Session->SystemSpaceHashEntries--;
2362 
2363  /* Extract the size and clear the entry */
2364  Size = Session->SystemSpaceViewTable[Hash].Entry & 0xFFFF;
2365  Session->SystemSpaceViewTable[Hash].Entry = 0;
2366 
2367  /* Return the control area and the size */
2368  *ControlArea = Session->SystemSpaceViewTable[Hash].ControlArea;
2369  return Size;
2370 }
2371 
2372 NTSTATUS
2373 NTAPI
2376 {
2377  ULONG Size;
2378  PCONTROL_AREA ControlArea;
2379  PAGED_CODE();
2380 
2381  /* Remove this mapping */
2382  KeAcquireGuardedMutex(Session->SystemSpaceViewLockPointer);
2383  Size = MiRemoveFromSystemSpace(Session, MappedBase, &ControlArea);
2384 
2385  /* Clear the bits for this mapping */
2386  RtlClearBits(Session->SystemSpaceBitMap,
2387  (ULONG)(((ULONG_PTR)MappedBase - (ULONG_PTR)Session->SystemSpaceViewStart) >> 16),
2388  Size);
2389 
2390  /* Convert the size from a bit size into the actual size */
2391  Size = Size * (_64K >> PAGE_SHIFT);
2392 
2393  /* Remove the PTEs now */
2394  MiRemoveMappedPtes(MappedBase, Size, ControlArea, NULL);
2395  KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
2396 
2397  /* Return success */
2398  return STATUS_SUCCESS;
2399 }
2400 
2401 /* PUBLIC FUNCTIONS ***********************************************************/
2402 
2403 /*
2404  * @implemented
2405  */
2406 NTSTATUS
2407 NTAPI
2411  IN PLARGE_INTEGER InputMaximumSize,
2414  IN HANDLE FileHandle OPTIONAL,
2415  IN PFILE_OBJECT FileObject OPTIONAL)
2416 {
2417  SECTION Section;
2418  PSECTION NewSection;
2419  PSUBSECTION Subsection;
2420  PSEGMENT NewSegment, Segment;
2421  NTSTATUS Status;
2422  PCONTROL_AREA ControlArea;
2423  ULONG ProtectionMask, ControlAreaSize, Size, NonPagedCharge, PagedCharge;
2425  BOOLEAN FileLock = FALSE, KernelCall = FALSE;
2426  KIRQL OldIrql;
2428  BOOLEAN UserRefIncremented = FALSE;
2429  PVOID PreviousSectionPointer;
2430 
2431  /* Make the same sanity checks that the Nt interface should've validated */
2432  ASSERT((AllocationAttributes & ~(SEC_COMMIT | SEC_RESERVE | SEC_BASED |
2434  SEC_NO_CHANGE)) == 0);
2435  ASSERT((AllocationAttributes & (SEC_COMMIT | SEC_RESERVE | SEC_IMAGE)) != 0);
2436  ASSERT(!((AllocationAttributes & SEC_IMAGE) &&
2437  (AllocationAttributes & (SEC_COMMIT | SEC_RESERVE |
2438  SEC_NOCACHE | SEC_NO_CHANGE))));
2439  ASSERT(!((AllocationAttributes & SEC_COMMIT) && (AllocationAttributes & SEC_RESERVE)));
2440  ASSERT(!((SectionPageProtection & PAGE_NOCACHE) ||
2441  (SectionPageProtection & PAGE_WRITECOMBINE) ||
2442  (SectionPageProtection & PAGE_GUARD) ||
2443  (SectionPageProtection & PAGE_NOACCESS)));
2444 
2445  /* Convert section flag to page flag */
2446  if (AllocationAttributes & SEC_NOCACHE) SectionPageProtection |= PAGE_NOCACHE;
2447 
2448  /* Check to make sure the protection is correct. Nt* does this already */
2449  ProtectionMask = MiMakeProtectionMask(SectionPageProtection);
2450  if (ProtectionMask == MM_INVALID_PROTECTION) return STATUS_INVALID_PAGE_PROTECTION;
2451 
2452  /* Check if this is going to be a data or image backed file section */
2453  if ((FileHandle) || (FileObject))
2454  {
2455  /* These cannot be mapped with large pages */
2456  if (AllocationAttributes & SEC_LARGE_PAGES) return STATUS_INVALID_PARAMETER_6;
2457 
2458  /* For now, only support the mechanism through a file handle */
2459  ASSERT(FileObject == NULL);
2460 
2461  /* Reference the file handle to get the object */
2463  MmMakeFileAccess[ProtectionMask],
2465  PreviousMode,
2466  (PVOID*)&File,
2467  NULL);
2468  if (!NT_SUCCESS(Status)) return Status;
2469 
2470  /* Make sure Cc has been doing its job */
2471  if (!File->SectionObjectPointer)
2472  {
2473  /* This is not a valid file system-based file, fail */
2474  ObDereferenceObject(File);
2476  }
2477 
2478  /* Image-file backed sections are not yet supported */
2479  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2480 
2481  /* Compute the size of the control area, and allocate it */
2482  ControlAreaSize = sizeof(CONTROL_AREA) + sizeof(MSUBSECTION);
2483  ControlArea = ExAllocatePoolWithTag(NonPagedPool, ControlAreaSize, 'aCmM');
2484  if (!ControlArea)
2485  {
2486  ObDereferenceObject(File);
2488  }
2489 
2490  /* Zero it out */
2491  RtlZeroMemory(ControlArea, ControlAreaSize);
2492 
2493  /* Did we get a handle, or an object? */
2494  if (FileHandle)
2495  {
2496  /* We got a file handle so we have to lock down the file */
2497 #if 0
2498  Status = FsRtlAcquireToCreateMappedSection(File, SectionPageProtection);
2499  if (!NT_SUCCESS(Status))
2500  {
2501  ExFreePool(ControlArea);
2502  ObDereferenceObject(File);
2503  return Status;
2504  }
2505 #else
2506  /* ReactOS doesn't support this API yet, so do nothing */
2507  Status = STATUS_SUCCESS;
2508 #endif
2509  /* Update the top-level IRP so that drivers know what's happening */
2511  FileLock = TRUE;
2512  }
2513 
2514  /* Lock the PFN database while we play with the section pointers */
2516 
2517  /* Image-file backed sections are not yet supported */
2518  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2519 
2520  /* There should not already be a control area for this file */
2521  ASSERT(File->SectionObjectPointer->DataSectionObject == NULL);
2522  NewSegment = NULL;
2523 
2524  /* Write down that this CA is being created, and set it */
2525  ControlArea->u.Flags.BeingCreated = TRUE;
2526  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2527  PreviousSectionPointer = File->SectionObjectPointer;
2528  File->SectionObjectPointer->DataSectionObject = ControlArea;
2529 
2530  /* We can release the PFN lock now */
2532 
2533  /* We don't support previously-mapped file */
2534  ASSERT(NewSegment == NULL);
2535 
2536  /* Image-file backed sections are not yet supported */
2537  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2538 
2539  /* So we always create a data file map */
2540  Status = MiCreateDataFileMap(File,
2541  &Segment,
2542  (PSIZE_T)InputMaximumSize,
2543  SectionPageProtection,
2544  AllocationAttributes,
2545  KernelCall);
2546  if (!NT_SUCCESS(Status))
2547  {
2548  /* Lock the PFN database while we play with the section pointers */
2550 
2551  /* Reset the waiting-for-deletion event */
2552  ASSERT(ControlArea->WaitingForDeletion == NULL);
2553  ControlArea->WaitingForDeletion = NULL;
2554 
2555  /* Set the file pointer NULL flag */
2556  ASSERT(ControlArea->u.Flags.FilePointerNull == 0);
2557  ControlArea->u.Flags.FilePointerNull = TRUE;
2558 
2559  /* Delete the data section object */
2560  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2561  File->SectionObjectPointer->DataSectionObject = NULL;
2562 
2563  /* No longer being created */
2564  ControlArea->u.Flags.BeingCreated = FALSE;
2565 
2566  /* We can release the PFN lock now */
2568 
2569  /* Check if we locked and set the IRP */
2570  if (FileLock)
2571  {
2572  /* Undo */
2574  //FsRtlReleaseFile(File);
2575  }
2576 
2577  /* Free the control area and de-ref the file object */
2578  ExFreePool(ControlArea);
2579  ObDereferenceObject(File);
2580 
2581  /* All done */
2582  return Status;
2583  }
2584 
2585  /* On success, we expect this */
2586  ASSERT(PreviousSectionPointer == File->SectionObjectPointer);
2587 
2588  /* Check if a maximum size was specified */
2589  if (!InputMaximumSize->QuadPart)
2590  {
2591  /* Nope, use the segment size */
2592  Section.SizeOfSection.QuadPart = (LONGLONG)Segment->SizeOfSegment;
2593  }
2594  else
2595  {
2596  /* Yep, use the entered size */
2597  Section.SizeOfSection.QuadPart = InputMaximumSize->QuadPart;
2598  }
2599  }
2600  else
2601  {
2602  /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
2603  if (AllocationAttributes & SEC_IMAGE) return STATUS_INVALID_FILE_FOR_SECTION;
2604 
2605  /* Not yet supported */
2606  ASSERT((AllocationAttributes & SEC_LARGE_PAGES) == 0);
2607 
2608  /* So this must be a pagefile-backed section, create the mappings needed */
2609  Status = MiCreatePagingFileMap(&NewSegment,
2610  (PSIZE_T)InputMaximumSize,
2611  ProtectionMask,
2612  AllocationAttributes);
2613  if (!NT_SUCCESS(Status)) return Status;
2614 
2615  /* Set the size here, and read the control area */
2616  Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
2617  ControlArea = NewSegment->ControlArea;
2618 
2619  /* MiCreatePagingFileMap increments user references */
2620  UserRefIncremented = TRUE;
2621  }
2622 
2623  /* Did we already have a segment? */
2624  if (!NewSegment)
2625  {
2626  /* This must be the file path and we created a segment */
2627  NewSegment = Segment;
2628  ASSERT(File != NULL);
2629 
2630  /* Acquire the PFN lock while we set control area flags */
2632 
2633  /* We don't support this race condition yet, so assume no waiters */
2634  ASSERT(ControlArea->WaitingForDeletion == NULL);
2635  ControlArea->WaitingForDeletion = NULL;
2636 
2637  /* Image-file backed sections are not yet supported, nor ROM images */
2638  ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
2639  ASSERT(Segment->ControlArea->u.Flags.Rom == 0);
2640 
2641  /* Take off the being created flag, and then release the lock */
2642  ControlArea->u.Flags.BeingCreated = FALSE;
2644  }
2645 
2646  /* Check if we locked the file earlier */
2647  if (FileLock)
2648  {
2649  /* Reset the top-level IRP and release the lock */
2651  //FsRtlReleaseFile(File);
2652  FileLock = FALSE;
2653  }
2654 
2655  /* Set the initial section object data */
2656  Section.InitialPageProtection = SectionPageProtection;
2657 
2658  /* The mapping created a control area and segment, save the flags */
2659  Section.Segment = NewSegment;
2660  Section.u.LongFlags = ControlArea->u.LongFlags;
2661 
2662  /* Check if this is a user-mode read-write non-image file mapping */
2663  if (!(FileObject) &&
2664  (SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)) &&
2665  !(ControlArea->u.Flags.Image) &&
2666  (ControlArea->FilePointer))
2667  {
2668  /* Add a reference and set the flag */
2669  Section.u.Flags.UserWritable = TRUE;
2670  InterlockedIncrement((volatile LONG*)&ControlArea->WritableUserReferences);
2671  }
2672 
2673  /* Check for image mappings or page file mappings */
2674  if ((ControlArea->u.Flags.Image) || !(ControlArea->FilePointer))
2675  {
2676  /* Charge the segment size, and allocate a subsection */
2677  PagedCharge = sizeof(SECTION) + NewSegment->TotalNumberOfPtes * sizeof(MMPTE);
2678  Size = sizeof(SUBSECTION);
2679  }
2680  else
2681  {
2682  /* Charge nothing, and allocate a mapped subsection */
2683  PagedCharge = 0;
2684  Size = sizeof(MSUBSECTION);
2685  }
2686 
2687  /* Check if this is a normal CA */
2688  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
2689  ASSERT(ControlArea->u.Flags.Rom == 0);
2690 
2691  /* Charge only a CA, and the subsection is right after */
2692  NonPagedCharge = sizeof(CONTROL_AREA);
2693  Subsection = (PSUBSECTION)(ControlArea + 1);
2694 
2695  /* We only support single-subsection mappings */
2696  NonPagedCharge += Size;
2697  ASSERT(Subsection->NextSubsection == NULL);
2698 
2699  /* Create the actual section object, with enough space for the prototype PTEs */
2700  Status = ObCreateObject(PreviousMode,
2703  PreviousMode,
2704  NULL,
2705  sizeof(SECTION),
2706  PagedCharge,
2707  NonPagedCharge,
2708  (PVOID*)&NewSection);
2709  if (!NT_SUCCESS(Status))
2710  {
2711  /* Check if this is a user-mode read-write non-image file mapping */
2712  if (!(FileObject) &&
2713  (SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)) &&
2714  !(ControlArea->u.Flags.Image) &&
2715  (ControlArea->FilePointer))
2716  {
2717  /* Remove a reference and check the flag */
2718  ASSERT(Section.u.Flags.UserWritable == 1);
2719  InterlockedDecrement((volatile LONG*)&ControlArea->WritableUserReferences);
2720  }
2721 
2722  /* Check if a user reference was added */
2723  if (UserRefIncremented)
2724  {
2725  /* Acquire the PFN lock while we change counters */
2727 
2728  /* Decrement the accounting counters */
2729  ControlArea->NumberOfSectionReferences--;
2730  ASSERT((LONG)ControlArea->NumberOfUserReferences > 0);
2731  ControlArea->NumberOfUserReferences--;
2732 
2733  /* Check if we should destroy the CA and release the lock */
2734  MiCheckControlArea(ControlArea, OldIrql);
2735  }
2736 
2737  /* Return the failure code */
2738  return Status;
2739  }
2740 
2741  /* NOTE: Past this point, all failures will be handled by Ob upon ref->0 */
2742 
2743  /* Now copy the local section object from the stack into this new object */
2744  RtlCopyMemory(NewSection, &Section, sizeof(SECTION));
2745  NewSection->Address.StartingVpn = 0;
2746 
2747  /* For now, only user calls are supported */
2748  ASSERT(KernelCall == FALSE);
2749  NewSection->u.Flags.UserReference = TRUE;
2750 
2751  /* Is this a "based" allocation, in which all mappings are identical? */
2752  if (AllocationAttributes & SEC_BASED)
2753  {
2754  /* Lock the VAD tree during the search */
2755  KeAcquireGuardedMutex(&MmSectionBasedMutex);
2756 
2757  /* Is it a brand new ControArea ? */
2758  if (ControlArea->u.Flags.BeingCreated == 1)
2759  {
2760  ASSERT(ControlArea->u.Flags.Based == 1);
2761  /* Then we must find a global address, top-down */
2763  (ULONG_PTR)MmHighSectionBase,
2764  _64K,
2765  &MmSectionBasedRoot,
2766  (ULONG_PTR*)&ControlArea->Segment->BasedAddress);
2767 
2768  if (!NT_SUCCESS(Status))
2769  {
2770  /* No way to find a valid range. */
2771  KeReleaseGuardedMutex(&MmSectionBasedMutex);
2772  ControlArea->u.Flags.Based = 0;
2773  NewSection->u.Flags.Based = 0;
2774  ObDereferenceObject(NewSection);
2775  return Status;
2776  }
2777 
2778  /* Compute the ending address and insert it into the VAD tree */
2779  NewSection->Address.StartingVpn = (ULONG_PTR)ControlArea->Segment->BasedAddress;
2780  NewSection->Address.EndingVpn = NewSection->Address.StartingVpn + NewSection->SizeOfSection.LowPart - 1;
2781  MiInsertBasedSection(NewSection);
2782  }
2783  else
2784  {
2785  /* 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 !*/
2786  ASSERT(FALSE);
2787  }
2788 
2789  KeReleaseGuardedMutex(&MmSectionBasedMutex);
2790  }
2791 
2792  /* The control area is not being created anymore */
2793  if (ControlArea->u.Flags.BeingCreated == 1)
2794  {
2795  /* Acquire the PFN lock while we set control area flags */
2797 
2798  /* Take off the being created flag, and then release the lock */
2799  ControlArea->u.Flags.BeingCreated = 0;
2800  NewSection->u.Flags.BeingCreated = 0;
2801 
2803  }
2804 
2805  /* Migrate the attribute into a flag */
2806  if (AllocationAttributes & SEC_NO_CHANGE) NewSection->u.Flags.NoChange = TRUE;
2807 
2808  /* If R/W access is not requested, this might eventually become a CoW mapping */
2809  if (!(SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)))
2810  {
2811  NewSection->u.Flags.CopyOnWrite = TRUE;
2812  }
2813 
2814  /* Write down if this was a kernel call */
2815  ControlArea->u.Flags.WasPurged |= KernelCall;
2816  ASSERT(ControlArea->u.Flags.WasPurged == FALSE);
2817 
2818  /* Make sure the segment and the section are the same size, or the section is smaller */
2819  ASSERT((ULONG64)NewSection->SizeOfSection.QuadPart <= NewSection->Segment->SizeOfSegment);
2820 
2821  /* Return the object and the creation status */
2822  *SectionObject = (PVOID)NewSection;
2823  return Status;
2824 }
2825 
2826 /*
2827  * @implemented
2828  */
2829 NTSTATUS
2830 NTAPI
2840  IN ULONG Protect)
2841 {
2844  PSECTION Section;
2845  PCONTROL_AREA ControlArea;
2846  ULONG ProtectionMask;
2847  NTSTATUS Status;
2848  PAGED_CODE();
2849 
2850  /* Get the segment and control area */
2851  Section = (PSECTION)SectionObject;
2852  ControlArea = Section->Segment->ControlArea;
2853 
2854  /* These flags/states are not yet supported by ARM3 */
2855  ASSERT(Section->u.Flags.Image == 0);
2856  ASSERT(Section->u.Flags.NoCache == 0);
2857  ASSERT(Section->u.Flags.WriteCombined == 0);
2858  ASSERT(ControlArea->u.Flags.PhysicalMemory == 0);
2859 
2860  /* FIXME */
2861  if ((AllocationType & MEM_RESERVE) != 0)
2862  {
2863  DPRINT1("MmMapViewOfArm3Section called with MEM_RESERVE, this is not implemented yet!!!\n");
2864  return STATUS_NOT_IMPLEMENTED;
2865  }
2866 
2867  /* Check if the mapping protection is compatible with the create */
2868  if (!MiIsProtectionCompatible(Section->InitialPageProtection, Protect))
2869  {
2870  DPRINT1("Mapping protection is incompatible\n");
2872  }
2873 
2874  /* Check if the offset and size would cause an overflow */
2875  if (((ULONG64)SectionOffset->QuadPart + *ViewSize) <
2877  {
2878  DPRINT1("Section offset overflows\n");
2879  return STATUS_INVALID_VIEW_SIZE;
2880  }
2881 
2882  /* Check if the offset and size are bigger than the section itself */
2883  if (((ULONG64)SectionOffset->QuadPart + *ViewSize) >
2884  (ULONG64)Section->SizeOfSection.QuadPart)
2885  {
2886  DPRINT1("Section offset is larger than section\n");
2887  return STATUS_INVALID_VIEW_SIZE;
2888  }
2889 
2890  /* Check if the caller did not specify a view size */
2891  if (!(*ViewSize))
2892  {
2893  /* Compute it for the caller */
2894  *ViewSize = (SIZE_T)(Section->SizeOfSection.QuadPart - SectionOffset->QuadPart);
2895 
2896  /* Check if it's larger than 4GB or overflows into kernel-mode */
2897  if ((*ViewSize > 0xFFFFFFFF) ||
2899  {
2900  DPRINT1("Section view won't fit\n");
2901  return STATUS_INVALID_VIEW_SIZE;
2902  }
2903  }
2904 
2905  /* Check if the commit size is larger than the view size */
2906  if (CommitSize > *ViewSize)
2907  {
2908  DPRINT1("Attempting to commit more than the view itself\n");
2910  }
2911 
2912  /* Check if the view size is larger than the section */
2913  if (*ViewSize > (ULONG64)Section->SizeOfSection.QuadPart)
2914  {
2915  DPRINT1("The view is larger than the section\n");
2916  return STATUS_INVALID_VIEW_SIZE;
2917  }
2918 
2919  /* Compute and validate the protection mask */
2920  ProtectionMask = MiMakeProtectionMask(Protect);
2921  if (ProtectionMask == MM_INVALID_PROTECTION)
2922  {
2923  DPRINT1("The protection is invalid\n");
2925  }
2926 
2927  /* We only handle pagefile-backed sections, which cannot be writecombined */
2928  if (Protect & PAGE_WRITECOMBINE)
2929  {
2930  DPRINT1("Cannot write combine a pagefile-backed section\n");
2932  }
2933 
2934  /* Start by attaching to the current process if needed */
2935  if (PsGetCurrentProcess() != Process)
2936  {
2937  KeStackAttachProcess(&Process->Pcb, &ApcState);
2938  Attached = TRUE;
2939  }
2940 
2941  /* Do the actual mapping */
2942  Status = MiMapViewOfDataSection(ControlArea,
2943  Process,
2944  BaseAddress,
2945  SectionOffset,
2946  ViewSize,
2947  Section,
2948  InheritDisposition,
2949  ProtectionMask,
2950  CommitSize,
2951  ZeroBits,
2952  AllocationType);
2953 
2954  /* Detach if needed, then return status */
2955  if (Attached) KeUnstackDetachProcess(&ApcState);
2956  return Status;
2957 }
2958 
2959 /*
2960  * @unimplemented
2961  */
2962 BOOLEAN
2963 NTAPI
2965 {
2966  UNIMPLEMENTED;
2967  return FALSE;
2968 }
2969 
2970 /*
2971  * @unimplemented
2972  */
2973 BOOLEAN
2974 NTAPI
2977 {
2978  UNIMPLEMENTED;
2979  return FALSE;
2980 }
2981 
2982 /*
2983  * @implemented
2984  */
2985 NTSTATUS
2986 NTAPI
2988  OUT PVOID *MappedBase,
2990 {
2991  PAGED_CODE();
2992 
2993  // HACK
2994  if (MiIsRosSectionObject(Section))
2995  {
2996  return MmMapViewInSystemSpace(Section, MappedBase, ViewSize);
2997  }
2998 
2999  /* Process must be in a session */
3000  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3001  {
3002  DPRINT1("Process is not in session\n");
3003  return STATUS_NOT_MAPPED_VIEW;
3004  }
3005 
3006  /* Use the system space API, but with the session view instead */
3008  return MiMapViewInSystemSpace(Section,
3010  MappedBase,
3011  ViewSize);
3012 }
3013 
3014 /*
3015  * @implemented
3016  */
3017 NTSTATUS
3018 NTAPI
3020 {
3021  PAGED_CODE();
3022 
3023  // HACK
3024  if (!MI_IS_SESSION_ADDRESS(MappedBase))
3025  {
3026  return MmUnmapViewInSystemSpace(MappedBase);
3027  }
3028 
3029  /* Process must be in a session */
3030  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3031  {
3032  DPRINT1("Proess is not in session\n");
3033  return STATUS_NOT_MAPPED_VIEW;
3034  }
3035 
3036  /* Use the system space API, but with the session view instead */
3039  MappedBase);
3040 }
3041 
3042 /*
3043  * @implemented
3044  */
3045 NTSTATUS
3046 NTAPI
3049 {
3050  return MiUnmapViewOfSection(Process, BaseAddress, 0);
3051 }
3052 
3053 /*
3054  * @implemented
3055  */
3056 NTSTATUS
3057 NTAPI
3059 {
3061  PAGED_CODE();
3062 
3063  /* Was this mapped by RosMm? */
3064  MemoryArea = MmLocateMemoryAreaByAddress(MmGetKernelAddressSpace(), MappedBase);
3065  if ((MemoryArea) && (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3))
3066  {
3067  return MiRosUnmapViewInSystemSpace(MappedBase);
3068  }
3069 
3070  /* It was not, call the ARM3 routine */
3071  return MiUnmapViewInSystemSpace(&MmSession, MappedBase);
3072 }
3073 
3074 /*
3075  * @implemented
3076  */
3077 NTSTATUS
3078 NTAPI
3080  IN SIZE_T ViewSize)
3081 {
3082  ULONG_PTR StartAddress, EndingAddress, Base;
3083  ULONG Hash, Count = 0, Size, QuotaCharge;
3085  PMMPTE LastProtoPte, PointerPte, ProtoPte;
3086  PCONTROL_AREA ControlArea;
3087  PSEGMENT Segment;
3088  PSUBSECTION Subsection;
3089  MMPTE TempPte;
3090  PAGED_CODE();
3091 
3092  /* Make sure the base isn't past the session view range */
3093  if ((MappedBase < MiSessionViewStart) ||
3094  (MappedBase >= (PVOID)((ULONG_PTR)MiSessionViewStart + MmSessionViewSize)))
3095  {
3096  DPRINT1("Base outside of valid range\n");
3098  }
3099 
3100  /* Make sure the size isn't past the session view range */
3102  (ULONG_PTR)MappedBase) < ViewSize)
3103  {
3104  DPRINT1("Size outside of valid range\n");
3106  }
3107 
3108  /* Sanity check */
3109  ASSERT(ViewSize != 0);
3110 
3111  /* Process must be in a session */
3112  if (PsGetCurrentProcess()->ProcessInSession == FALSE)
3113  {
3114  DPRINT1("Process is not in session\n");
3115  return STATUS_NOT_MAPPED_VIEW;
3116  }
3117 
3118  /* Compute the correctly aligned base and end addresses */
3119  StartAddress = (ULONG_PTR)PAGE_ALIGN(MappedBase);
3120  EndingAddress = ((ULONG_PTR)MappedBase + ViewSize - 1) | (PAGE_SIZE - 1);
3121 
3122  /* Sanity check and grab the session */
3124  Session = &MmSessionSpace->Session;
3125 
3126  /* Get the hash entry for this allocation */
3127  Hash = (StartAddress >> 16) % Session->SystemSpaceHashKey;
3128 
3129  /* Lock system space */
3131 
3132  /* Loop twice so we can try rolling over if needed */
3133  while (TRUE)
3134  {
3135  /* Extract the size and base addresses from the entry */
3136  Base = Session->SystemSpaceViewTable[Hash].Entry & ~0xFFFF;
3137  Size = Session->SystemSpaceViewTable[Hash].Entry & 0xFFFF;
3138 
3139  /* Convert the size to bucket chunks */
3141 
3142  /* Bail out if this entry fits in here */
3143  if ((StartAddress >= Base) && (EndingAddress < (Base + Size))) break;
3144 
3145  /* Check if we overflew past the end of the hash table */
3146  if (++Hash >= Session->SystemSpaceHashSize)
3147  {
3148  /* Reset the hash to zero and keep searching from the bottom */
3149  Hash = 0;
3150  if (++Count == 2)
3151  {
3152  /* But if we overflew twice, then this is not a real mapping */
3153  KeBugCheckEx(DRIVER_UNMAPPING_INVALID_VIEW,
3154  Base,
3155  2,
3156  0,
3157  0);
3158  }
3159  }
3160  }
3161 
3162  /* Make sure the view being mapped is not file-based */
3163  ControlArea = Session->SystemSpaceViewTable[Hash].ControlArea;
3164  if (ControlArea->FilePointer != NULL)
3165  {
3166  /* It is, so we have to bail out */
3167  DPRINT1("Only page-filed backed sections can be commited\n");
3169  return STATUS_ALREADY_COMMITTED;
3170  }
3171 
3172  /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
3173  ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
3174  ASSERT(ControlArea->u.Flags.Rom == 0);
3175  Subsection = (PSUBSECTION)(ControlArea + 1);
3176 
3177  /* Get the start and end PTEs -- make sure the end PTE isn't past the end */
3178  ProtoPte = Subsection->SubsectionBase + ((StartAddress - Base) >> PAGE_SHIFT);
3179  QuotaCharge = MiAddressToPte(EndingAddress) - MiAddressToPte(StartAddress) + 1;
3180  LastProtoPte = ProtoPte + QuotaCharge;
3181  if (LastProtoPte >= Subsection->SubsectionBase + Subsection->PtesInSubsection)
3182  {
3183  DPRINT1("PTE is out of bounds\n");
3186  }
3187 
3188  /* Acquire the commit lock and count all the non-committed PTEs */
3189  KeAcquireGuardedMutexUnsafe(&MmSectionCommitMutex);
3190  PointerPte = ProtoPte;
3191  while (PointerPte < LastProtoPte)
3192  {
3193  if (PointerPte->u.Long) QuotaCharge--;
3194  PointerPte++;
3195  }
3196 
3197  /* Was everything committed already? */
3198  if (!QuotaCharge)
3199  {
3200  /* Nothing to do! */
3201  KeReleaseGuardedMutexUnsafe(&MmSectionCommitMutex);
3203  return STATUS_SUCCESS;
3204  }
3205 
3206  /* Pick the segment and template PTE */
3207  Segment = ControlArea->Segment;
3208  TempPte = Segment->SegmentPteTemplate;
3209  ASSERT(TempPte.u.Long != 0);
3210 
3211  /* Loop all prototype PTEs to be committed */
3212  PointerPte = ProtoPte;
3213  while (PointerPte < LastProtoPte)
3214  {
3215  /* Make sure the PTE is already invalid */
3216  if (PointerPte->u.Long == 0)
3217  {
3218  /* And write the invalid PTE */
3219  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
3220  }
3221 
3222  /* Move to the next PTE */
3223  PointerPte++;
3224  }
3225 
3226  /* Check if we had at least one page charged */
3227  if (QuotaCharge)
3228  {
3229  /* Update the accounting data */
3230  Segment->NumberOfCommittedPages += QuotaCharge;
3232  }
3233 
3234  /* Release all */
3235  KeReleaseGuardedMutexUnsafe(&MmSectionCommitMutex);
3237  return STATUS_SUCCESS;
3238 }
3239 
3240 VOID
3241 NTAPI
3243 {
3245  PCONTROL_AREA ControlArea;
3246  KIRQL OldIrql;
3247 
3248  SectionObject = (PSECTION)ObjectBody;
3249 
3250  if (SectionObject->u.Flags.Based == 1)
3251  {
3252  /* Remove the node from the global section address tree */
3253  KeAcquireGuardedMutex(&MmSectionBasedMutex);
3254  MiRemoveNode(&SectionObject->Address, &MmSectionBasedRoot);
3255  KeReleaseGuardedMutex(&MmSectionBasedMutex);
3256  }
3257 
3258  /* Lock the PFN database */
3260 
3261  ASSERT(SectionObject->Segment);
3262  ASSERT(SectionObject->Segment->ControlArea);
3263 
3264  ControlArea = SectionObject->Segment->ControlArea;
3265 
3266  /* Dereference */
3267  ControlArea->NumberOfSectionReferences--;
3268  ControlArea->NumberOfUserReferences--;
3269 
3270  ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
3271 
3272  /* Check it. It will delete it if there is no more reference to it */
3273  MiCheckControlArea(ControlArea, OldIrql);
3274 }
3275 
3276 ULONG
3277 NTAPI
3279 {
3280  UNIMPLEMENTED;
3281  return 0;
3282 }
3283 
3284 /* SYSTEM CALLS ***************************************************************/
3285 
3286 NTSTATUS
3287 NTAPI
3288 NtAreMappedFilesTheSame(IN PVOID File1MappedAsAnImage,
3289  IN PVOID File2MappedAsFile)
3290 {
3292  PMMVAD Vad1, Vad2;
3293  PFILE_OBJECT FileObject1, FileObject2;
3294  NTSTATUS Status;
3295 
3296  /* Lock address space */
3297  AddressSpace = MmGetCurrentAddressSpace();
3298  MmLockAddressSpace(AddressSpace);
3299 
3300  /* Get the VAD for Address 1 */
3301  Vad1 = MiLocateAddress(File1MappedAsAnImage);
3302  if (Vad1 == NULL)
3303  {
3304  /* Fail, the address does not exist */
3305  DPRINT1("No VAD at address 1 %p\n", File1MappedAsAnImage);
3306  Status = STATUS_INVALID_ADDRESS;
3307  goto Exit;
3308  }
3309 
3310  /* Get the VAD for Address 2 */
3311  Vad2 = MiLocateAddress(File2MappedAsFile);
3312  if (Vad2 == NULL)
3313  {
3314  /* Fail, the address does not exist */
3315  DPRINT1("No VAD at address 2 %p\n", File2MappedAsFile);
3316  Status = STATUS_INVALID_ADDRESS;
3317  goto Exit;
3318  }
3319 
3320  /* Get the file object pointer for VAD 1 */
3321  FileObject1 = MiGetFileObjectForVad(Vad1);
3322  if (FileObject1 == NULL)
3323  {
3324  DPRINT1("Failed to get file object for Address 1 %p\n", File1MappedAsAnImage);
3326  goto Exit;
3327  }
3328 
3329  /* Get the file object pointer for VAD 2 */
3330  FileObject2 = MiGetFileObjectForVad(Vad2);
3331  if (FileObject2 == NULL)
3332  {
3333  DPRINT1("Failed to get file object for Address 2 %p\n", File2MappedAsFile);
3335  goto Exit;
3336  }
3337 
3338  /* Make sure Vad1 is an image mapping */
3339  if (Vad1->u.VadFlags.VadType != VadImageMap)
3340  {
3341  DPRINT1("Address 1 (%p) is not an image mapping\n", File1MappedAsAnImage);
3342  Status = STATUS_NOT_SAME_DEVICE;
3343  goto Exit;
3344  }
3345 
3346  /* SectionObjectPointer is equal if the files are equal */
3347  if (FileObject1->SectionObjectPointer == FileObject2->SectionObjectPointer)
3348  {
3349  Status = STATUS_SUCCESS;
3350  }
3351  else
3352  {
3353  Status = STATUS_NOT_SAME_DEVICE;
3354  }
3355 
3356 Exit:
3357  /* Unlock address space */
3358  MmUnlockAddressSpace(AddressSpace);
3359  return Status;
3360 }
3361 
3362 /*
3363  * @implemented
3364  */
3365 NTSTATUS
3366 NTAPI
3370  IN PLARGE_INTEGER MaximumSize OPTIONAL,
3371  IN ULONG SectionPageProtection OPTIONAL,
3373  IN HANDLE FileHandle OPTIONAL)
3374 {
3375  LARGE_INTEGER SafeMaximumSize;
3377  HANDLE Handle;
3379  NTSTATUS Status;
3380  PAGED_CODE();
3381 
3382  /* Check for non-existing flags */
3383  if ((AllocationAttributes & ~(SEC_COMMIT | SEC_RESERVE | SEC_BASED |
3385  SEC_NO_CHANGE)))
3386  {
3387  if (!(AllocationAttributes & 1))
3388  {
3389  DPRINT1("Bogus allocation attribute: %lx\n", AllocationAttributes);
3391  }
3392  }
3393 
3394  /* Check for no allocation type */
3395  if (!(AllocationAttributes & (SEC_COMMIT | SEC_RESERVE | SEC_IMAGE)))
3396  {
3397  DPRINT1("Missing allocation type in allocation attributes\n");
3399  }
3400 
3401  /* Check for image allocation with invalid attributes */
3402  if ((AllocationAttributes & SEC_IMAGE) &&
3403  (AllocationAttributes & (SEC_COMMIT | SEC_RESERVE | SEC_LARGE_PAGES |
3405  {
3406  DPRINT1("Image allocation with invalid attributes\n");
3408  }
3409 
3410  /* Check for allocation type is both commit and reserve */
3411  if ((AllocationAttributes & SEC_COMMIT) && (AllocationAttributes & SEC_RESERVE))
3412  {
3413  DPRINT1("Commit and reserve in the same time\n");
3415  }
3416 
3417  /* Now check for valid protection */
3422  {
3423  DPRINT1("Sections don't support these protections\n");
3425  }
3426 
3427  /* Use a maximum size of zero, if none was specified */
3428  SafeMaximumSize.QuadPart = 0;
3429 
3430  /* Check for user-mode caller */
3431  if (PreviousMode != KernelMode)
3432  {
3433  /* Enter SEH */
3434  _SEH2_TRY
3435  {
3436  /* Safely check user-mode parameters */
3437  if (MaximumSize) SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
3438  MaximumSize = &SafeMaximumSize;
3439  ProbeForWriteHandle(SectionHandle);
3440  }
3442  {
3443  /* Return the exception code */
3445  }
3446  _SEH2_END;
3447  }
3448  else if (!MaximumSize) MaximumSize = &SafeMaximumSize;
3449 
3450  /* Check that MaximumSize is valid if backed by paging file */
3451  if ((!FileHandle) && (!MaximumSize->QuadPart))
3453 
3454  /* Create the section */
3455  Status = MmCreateSection(&SectionObject,
3456  DesiredAccess,
3458  MaximumSize,
3460  AllocationAttributes,
3461  FileHandle,
3462  NULL);
3463  if (!NT_SUCCESS(Status)) return Status;
3464 
3465  /* FIXME: Should zero last page for a file mapping */
3466 
3467  /* Now insert the object */
3468  Status = ObInsertObject(SectionObject,
3469  NULL,
3470  DesiredAccess,
3471  0,
3472  NULL,
3473  &Handle);
3474  if (NT_SUCCESS(Status))
3475  {
3476  /* Enter SEH */
3477  _SEH2_TRY
3478  {
3479  /* Return the handle safely */
3480  *SectionHandle = Handle;
3481  }
3483  {
3484  /* Nothing here */
3485  }
3486  _SEH2_END;
3487  }
3488 
3489  /* Return the status */
3490  return Status;
3491 }
3492 
3493 NTSTATUS
3494 NTAPI
3495 NtOpenSection(OUT PHANDLE SectionHandle,
3498 {
3499  HANDLE Handle;
3500  NTSTATUS Status;
3502  PAGED_CODE();
3503 
3504  /* Check for user-mode caller */
3505  if (PreviousMode != KernelMode)
3506  {
3507  /* Enter SEH */
3508  _SEH2_TRY
3509  {
3510  /* Safely check user-mode parameters */
3511  ProbeForWriteHandle(SectionHandle);
3512  }
3514  {
3515  /* Return the exception code */
3517  }
3518  _SEH2_END;
3519  }
3520 
3521  /* Try opening the object */
3522  Status = ObOpenObjectByName(ObjectAttributes,
3524  PreviousMode,
3525  NULL,
3526  DesiredAccess,
3527  NULL,
3528  &Handle);
3529 
3530  /* Enter SEH */
3531  _SEH2_TRY
3532  {
3533  /* Return the handle safely */
3534  *SectionHandle = Handle;
3535  }
3537  {
3538  /* Nothing here */
3539  }
3540  _SEH2_END;
3541 
3542  /* Return the status */
3543  return Status;
3544 }
3545 
3546 NTSTATUS
3547 NTAPI
3557  IN ULONG Protect)
3558 {
3559  PVOID SafeBaseAddress;
3560  LARGE_INTEGER SafeSectionOffset;
3561  SIZE_T SafeViewSize;
3562  PROS_SECTION_OBJECT Section;
3564  NTSTATUS Status;
3566  ULONG ProtectionMask;
3568 #ifdef _M_IX86
3569  static const ULONG ValidAllocationType = (MEM_TOP_DOWN | MEM_LARGE_PAGES |
3571 #else
3572  static const ULONG ValidAllocationType = (MEM_TOP_DOWN | MEM_LARGE_PAGES |
3574 #endif
3575 
3576  /* Check for invalid inherit disposition */
3577  if ((InheritDisposition > ViewUnmap) || (InheritDisposition < ViewShare))
3578  {
3579  DPRINT1("Invalid inherit disposition\n");
3581  }
3582 
3583  /* Allow only valid allocation types */
3584  if (AllocationType & ~ValidAllocationType)
3585  {
3586  DPRINT1("Invalid allocation type\n");
3588  }
3589 
3590  /* Convert the protection mask, and validate it */
3591  ProtectionMask = MiMakeProtectionMask(Protect);
3592  if (ProtectionMask == MM_INVALID_PROTECTION)
3593  {
3594  DPRINT1("Invalid page protection\n");
3596  }
3597 
3598  /* Now convert the protection mask into desired section access mask */
3599  DesiredAccess = MmMakeSectionAccess[ProtectionMask & 0x7];
3600 
3601  /* Assume no section offset */
3602  SafeSectionOffset.QuadPart = 0;
3603 
3604  /* Enter SEH */
3605  _SEH2_TRY
3606  {
3607  /* Check for unsafe parameters */
3608  if (PreviousMode != KernelMode)
3609  {
3610  /* Probe the parameters */
3611  ProbeForWritePointer(BaseAddress);
3612  ProbeForWriteSize_t(ViewSize);
3613  }
3614 
3615  /* Check if a section offset was given */
3616  if (SectionOffset)
3617  {
3618  /* Check for unsafe parameters and capture section offset */
3619  if (PreviousMode != KernelMode) ProbeForWriteLargeInteger(SectionOffset);
3620  SafeSectionOffset = *SectionOffset;
3621  }
3622 
3623  /* Capture the other parameters */
3624  SafeBaseAddress = *BaseAddress;
3625  SafeViewSize = *ViewSize;
3626  }
3628  {
3629  /* Return the exception code */
3631  }
3632  _SEH2_END;
3633 
3634  /* Check for kernel-mode address */
3635  if (SafeBaseAddress > MM_HIGHEST_VAD_ADDRESS)
3636  {
3637  DPRINT1("Kernel base not allowed\n");
3639  }
3640 
3641  /* Check for range entering kernel-mode */
3642  if (((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - (ULONG_PTR)SafeBaseAddress) < SafeViewSize)
3643  {
3644  DPRINT1("Overflowing into kernel base not allowed\n");
3646  }
3647 
3648  /* Check for invalid zero bits */
3649  if (ZeroBits)
3650  {
3651  if (ZeroBits > MI_MAX_ZERO_BITS)
3652  {
3653  DPRINT1("Invalid zero bits\n");
3655  }
3656 
3657  if ((((ULONG_PTR)SafeBaseAddress << ZeroBits) >> ZeroBits) != (ULONG_PTR)SafeBaseAddress)
3658  {
3659  DPRINT1("Invalid zero bits\n");
3661  }
3662 
3663  if (((((ULONG_PTR)SafeBaseAddress + SafeViewSize) << ZeroBits) >> ZeroBits) != ((ULONG_PTR)SafeBaseAddress + SafeViewSize))
3664  {
3665  DPRINT1("Invalid zero bits\n");
3667  }
3668  }
3669 
3670  /* Reference the process */
3671  Status = ObReferenceObjectByHandle(ProcessHandle,
3673  PsProcessType,
3674  PreviousMode,
3675  (PVOID*)&Process,
3676  NULL);
3677  if (!NT_SUCCESS(Status)) return Status;
3678 
3679  /* Reference the section */
3680  Status = ObReferenceObjectByHandle(SectionHandle,
3681  DesiredAccess,
3683  PreviousMode,
3684  (PVOID*)&Section,
3685  NULL);
3686  if (!NT_SUCCESS(Status))
3687  {
3688  ObDereferenceObject(Process);
3689  return Status;
3690  }
3691 
3692  if (!(AllocationType & MEM_DOS_LIM))
3693  {
3694  /* Check for non-allocation-granularity-aligned BaseAddress */
3695  if (SafeBaseAddress != ALIGN_DOWN_POINTER_BY(SafeBaseAddress, MM_VIRTMEM_GRANULARITY))
3696  {
3697  DPRINT("BaseAddress is not at 64-kilobyte address boundary.");
3698  ObDereferenceObject(Section);
3699  ObDereferenceObject(Process);
3700  return STATUS_MAPPED_ALIGNMENT;
3701  }
3702 
3703  /* Do the same for the section offset */
3704  if (SafeSectionOffset.LowPart != ALIGN_DOWN_BY(SafeSectionOffset.LowPart, MM_VIRTMEM_GRANULARITY))
3705  {
3706  DPRINT("SectionOffset is not at 64-kilobyte address boundary.");
3707  ObDereferenceObject(Section);
3708  ObDereferenceObject(Process);
3709  return STATUS_MAPPED_ALIGNMENT;
3710  }
3711  }
3712 
3713  /* Now do the actual mapping */
3714  Status = MmMapViewOfSection(Section,
3715  Process,
3716  &SafeBaseAddress,
3717  ZeroBits,
3718  CommitSize,
3719  &SafeSectionOffset,
3720  &SafeViewSize,
3721  InheritDisposition,
3722  AllocationType,
3723  Protect);
3724 
3725  /* Return data only on success */
3726  if (NT_SUCCESS(Status))
3727  {
3728  /* Check if this is an image for the current process */
3729  if (MiIsRosSectionObject(Section) &&
3730  (Section->AllocationAttributes & SEC_IMAGE) &&
3731  (Process == PsGetCurrentProcess()) &&
3732  (Status != STATUS_IMAGE_NOT_AT_BASE))
3733  {
3734  /* Notify the debugger */
3735  DbgkMapViewOfSection(Section,
3736  SafeBaseAddress,
3737  SafeSectionOffset.LowPart,
3738  SafeViewSize);
3739  }
3740 
3741  /* Enter SEH */
3742  _SEH2_TRY
3743  {
3744  /* Return parameters to user */
3745  *BaseAddress = SafeBaseAddress;
3746  *ViewSize = SafeViewSize;
3747  if (SectionOffset) *SectionOffset = SafeSectionOffset;
3748  }
3750  {
3751  /* Nothing to do */
3752  }
3753  _SEH2_END;
3754  }
3755 
3756  /* Dereference all objects and return status */
3757  ObDereferenceObject(Section);
3758  ObDereferenceObject(Process);
3759  return Status;
3760 }
3761 
3762 NTSTATUS
3763 NTAPI
3766 {
3768  NTSTATUS Status;
3770 
3771  /* Don't allowing mapping kernel views */
3772  if ((PreviousMode == UserMode) && (BaseAddress > MM_HIGHEST_USER_ADDRESS))
3773  {
3774  DPRINT1("Trying to unmap a kernel view\n");
3775  return STATUS_NOT_MAPPED_VIEW;
3776  }
3777 
3778  /* Reference the process */
3779  Status = ObReferenceObjectByHandle(ProcessHandle,
3781  PsProcessType,
3782  PreviousMode,
3783  (PVOID*)&Process,
3784  NULL);
3785  if (!NT_SUCCESS(Status)) return Status;
3786 
3787  /* Unmap the view */
3788  Status = MiUnmapViewOfSection(Process, BaseAddress, 0);
3789 
3790  /* Dereference the process and return status */
3791  ObDereferenceObject(Process);
3792  return Status;
3793 }
3794 
3795 NTSTATUS
3796 NTAPI
3797 NtExtendSection(IN HANDLE SectionHandle,
3798  IN OUT PLARGE_INTEGER NewMaximumSize)
3799 {
3800  LARGE_INTEGER SafeNewMaximumSize;
3801  PROS_SECTION_OBJECT Section;
3802  NTSTATUS Status;
3804 
3805  /* Check for user-mode parameters */
3806  if (PreviousMode != KernelMode)
3807  {
3808  /* Enter SEH */
3809  _SEH2_TRY
3810  {
3811  /* Probe and capture the maximum size, it's both read and write */
3812  ProbeForWriteLargeInteger(NewMaximumSize);
3813  SafeNewMaximumSize = *NewMaximumSize;
3814  }
3816  {
3817  /* Return the exception code */
3819  }
3820  _SEH2_END;
3821  }
3822  else
3823  {
3824  /* Just read the size directly */
3825  SafeNewMaximumSize = *NewMaximumSize;
3826  }
3827 
3828  /* Reference the section */
3829  Status = ObReferenceObjectByHandle(SectionHandle,
3832  PreviousMode,
3833  (PVOID*)&Section,
3834  NULL);
3835  if (!NT_SUCCESS(Status)) return Status;
3836 
3837  /* Really this should go in MmExtendSection */
3838  if (!(Section->AllocationAttributes & SEC_FILE))
3839  {
3840  DPRINT1("Not extending a file\n");
3841  ObDereferenceObject(Section);
3843  }
3844 
3845  /* FIXME: Do the work */
3846 
3847  /* Dereference the section */
3848  ObDereferenceObject(Section);
3849 
3850  /* Enter SEH */
3851  _SEH2_TRY
3852  {
3853  /* Write back the new size */
3854  *NewMaximumSize = SafeNewMaximumSize;
3855  }
3857  {
3858  /* Nothing to do */
3859  }
3860  _SEH2_END;
3861 
3862  /* Return the status */
3863  return STATUS_NOT_IMPLEMENTED;
3864 }
3865 
3866 /* 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::@2132 u
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:1255
NTSYSAPI ULONG NTAPI RtlFindClearBitsAndSet(_In_ PRTL_BITMAP BitMapHeader, _In_ ULONG NumberToFind, _In_ ULONG HintIndex)
Definition: bitmap.c:645
#define STATUS_SUCCESS
Definition: contextmenu.cpp:55
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
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR ZeroBits
Definition: mmfuncs.h:404
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:39
#define MM_VIRTMEM_GRANULARITY
Definition: mm.h:76
#define MM_INVALID_PROTECTION
Definition: miarm.h:69
MMPTE PrototypePte
Definition: init.c:42
union _MEMORY_AREA::@1488 Data
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:3764
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
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:1890
ULONG NTAPI MiMakeSystemAddressValidPfn(IN PVOID VirtualAddress, IN KIRQL OldIrql)
Definition: virtual.c:257
#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:214
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:3288
NTSTATUS NTAPI MmGetFileNameForAddress(IN PVOID Address, OUT PUNICODE_STRING ModuleName)
Definition: section.c:1829
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:3367
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:1493
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:2964
ULONG PhysicalMemory
Definition: mmtypes.h:465
ULONG PFN_COUNT
Definition: mmtypes.h:102
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
union _SECTION::@2138 u
__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
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:2228
char CHAR
Definition: xmlstorage.h:175
#define PROCESS_VM_OPERATION
Definition: pstypes.h:153
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1354
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:1799
BOOLEAN NTAPI MiInitializeSystemSpaceMap(IN PMMSESSION InputSession OPTIONAL)
Definition: section.c:240
#define ProbeForWriteSize_t(Ptr)
Definition: probe.h:45
#define TRUE
Definition: numbers.c:17
#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
ACCESS_MASK MmMakeFileAccess[8]
Definition: section.c:32
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
#define MAXULONG_PTR
Definition: basetsd.h:102
USHORT Modified
Definition: mm.h:292
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:2603
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:1476
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:1156
ULONG SystemSpaceHashEntries
Definition: miarm.h:432
union _MMPTE::@1890 u
#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
_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:1508
USHORT ReferenceCount
Definition: mm.h:328
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:297
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:64
#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:2408
USHORT PrototypePte
Definition: mm.h:295
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG SectionPageProtection
Definition: mmfuncs.h:360
PVOID DllBase
Definition: ldrtypes.h:139
ULONG64 Dirty
Definition: mmtypes.h:164
NTSTATUS NTAPI MiAddMappedPtes(IN PMMPTE FirstPte, IN PFN_NUMBER PteCount, IN PCONTROL_AREA ControlArea)
Definition: section.c:417
NTSYSAPI VOID NTAPI RtlInitializeBitMap(_Out_ PRTL_BITMAP BitMapHeader, _In_opt_ __drv_aliasesMem PULONG BitMapBuffer, _In_opt_ ULONG SizeOfBitMap)
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:329
PVOID MmSessionBase
Definition: init.c:33
ULONG_PTR EndingVpn
Definition: mmtypes.h:731
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:3242
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:2330
#define SEC_COMMIT
Definition: mmtypes.h:99
ULONG_PTR * PSIZE_T
Definition: typedefs.h:79
#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 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:1699
union _MMVAD_LONG::@2133 u2
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:649
union _MMVAD_LONG::@2135 u4
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:2831
union _CONTROL_AREA::@2122 u
_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:3058
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:311
uint64_t ULONG64
Definition: typedefs.h:66
#define MI_SET_PROCESS2(x)
Definition: mm.h:254
#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:3019
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:3548
#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:2059
NTSTATUS NTAPI NtOpenSection(OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: section.c:3495
#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
NTSYSAPI VOID NTAPI RtlClearAllBits(_In_ PRTL_BITMAP BitMapHeader)
Definition: bitmap.c:272
NTSTATUS NTAPI NtExtendSection(IN HANDLE SectionHandle, IN OUT PLARGE_INTEGER NewMaximumSize)
Definition: section.c:3797
smooth NULL
Definition: ftsmooth.c:464
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 _MEMORY_AREA::@1488::@1489 SectionData
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:253
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:4508
ULONG_PTR StartingVpn
Definition: mmtypes.h:730
ULONG_PTR StartingVpn
Definition: mmtypes.h:654
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:69
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:926
_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:550
#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:1767
NTSTATUS NTAPI MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:4907
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:318
union _MMPFN::@1491 u1
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:67
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1107
union _SEGMENT::@2121 u2
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
_In_ HANDLE Handle
Definition: extypes.h:390
NTSTATUS NTAPI MmUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress)
Definition: section.c:3047
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
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:2374
#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:4981
static void Exit(void)
Definition: sock.c:1255
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: ntddk_ex.h:218
#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:3278
#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
NTSTATUS NTAPI MmMapViewInSystemSpace(IN PVOID SectionObject, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:4853
#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
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:3079
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:305
ULONG GlobalOnlyPerSession
Definition: mmtypes.h:483
Definition: ntddk_ex.h:202
ULONG LowPart
Definition: typedefs.h:105
BOOLEAN NTAPI MmForceSectionClosed(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN BOOLEAN DelayClose)
Definition: section.c:2975
#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:118
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:291
ULONG CopyOnWrite
Definition: mmtypes.h:466
ULONG NumberOfMappedViews
Definition: mmtypes.h:517
union _MMVAD::@2129 u
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
VOID NTAPI MmGetImageInformation(OUT PSECTION_IMAGE_INFORMATION ImageInformation)
Definition: section.c:1752
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:877
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:1050
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:79
#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
#define NT_SUCCESS(StatCode)
Definition: cmd.c:149
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:943
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1376
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:1616
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:1415
_Must_inspect_result_ _In_ ULONG NewProtect
Definition: mmfuncs.h:683
UNICODE_STRING FullDllName
Definition: ldrtypes.h:142
MMADDRESS_NODE Address
Definition: mmtypes.h:812
#define STATUS_INVALID_PARAMETER_6
Definition: ntstatus.h:466
ULONG NumberOfUserReferences
Definition: mmtypes.h:519
union _MMPFN::@1493 u3
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
unsigned int * PULONG
Definition: retypes.h:1
struct _MMPTE MMPTE
MMPTE OriginalPte
Definition: mm.h:339
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
MMPTE SegmentPteTemplate
Definition: mmtypes.h:406
#define MI_IS_PAGE_DIRTY(x)
Definition: mm.h:101
#define OUT
Definition: typedefs.h:40
#define ObReferenceObject
Definition: obfuncs.h:204
#define FALSE
Definition: numbers.c:16
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:260
NTSYSAPI VOID NTAPI RtlClearBits(_In_ PRTL_BITMAP BitMapHeader, _In_range_(0, BitMapHeader->SizeOfBitMap-NumberToClear) ULONG StartingIndex, _In_range_(0, BitMapHeader->SizeOfBitMap-StartingIndex) ULONG NumberToClear)
Definition: bitmap.c:314
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:262
#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
union _SUBSECTION::@2124 u
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:1250
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
Definition: File.h:15
VOID NTAPI MiSetControlAreaSymbolsLoaded(IN PCONTROL_AREA ControlArea)
Definition: section.c:1140
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1097
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
VOID NTAPI MiFlushTbAndCapture(IN PMMVAD FoundVad, IN PMMPTE PointerPte, IN ULONG ProtectionMask, IN PMMPFN Pfn1, IN BOOLEAN UpdateDirty)
Definition: section.c:1955
#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:2987
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:1347
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:1369
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ULONG BeingCreated
Definition: mmtypes.h:456
NTSTATUS NTAPI MiRosUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress, IN ULONG Flags)
Definition: section.c:4143
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:1679
LONGLONG QuadPart
Definition: typedefs.h:113
union _SEGMENT::@2120 u1
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