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