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