xref: /reactos/ntoskrnl/include/internal/mm.h (revision ba3f0743)
1 #pragma once
2 
3 #include <internal/arch/mm.h>
4 
5 /* TYPES *********************************************************************/
6 
7 struct _EPROCESS;
8 
9 extern PMMSUPPORT MmKernelAddressSpace;
10 extern PFN_COUNT MiFreeSwapPages;
11 extern PFN_COUNT MiUsedSwapPages;
12 extern PFN_COUNT MmNumberOfPhysicalPages;
13 extern UCHAR MmDisablePagingExecutive;
14 extern PFN_NUMBER MmLowestPhysicalPage;
15 extern PFN_NUMBER MmHighestPhysicalPage;
16 extern PFN_NUMBER MmAvailablePages;
17 extern PFN_NUMBER MmResidentAvailablePages;
18 
19 extern LIST_ENTRY MmLoadedUserImageList;
20 
21 extern KMUTANT MmSystemLoadLock;
22 
23 extern ULONG MmNumberOfPagingFiles;
24 
25 extern PVOID MmUnloadedDrivers;
26 extern PVOID MmLastUnloadedDrivers;
27 extern PVOID MmTriageActionTaken;
28 extern PVOID KernelVerifier;
29 extern MM_DRIVER_VERIFIER_DATA MmVerifierData;
30 
31 extern SIZE_T MmTotalCommitLimit;
32 extern SIZE_T MmTotalCommittedPages;
33 extern SIZE_T MmSharedCommit;
34 extern SIZE_T MmDriverCommit;
35 extern SIZE_T MmProcessCommit;
36 extern SIZE_T MmPagedPoolCommit;
37 extern SIZE_T MmPeakCommitment;
38 extern SIZE_T MmtotalCommitLimitMaximum;
39 
40 extern PVOID MiDebugMapping; // internal
41 extern PMMPTE MmDebugPte; // internal
42 
43 struct _KTRAP_FRAME;
44 struct _EPROCESS;
45 struct _MM_RMAP_ENTRY;
46 typedef ULONG_PTR SWAPENTRY;
47 
48 //
49 // MmDbgCopyMemory Flags
50 //
51 #define MMDBG_COPY_WRITE            0x00000001
52 #define MMDBG_COPY_PHYSICAL         0x00000002
53 #define MMDBG_COPY_UNSAFE           0x00000004
54 #define MMDBG_COPY_CACHED           0x00000008
55 #define MMDBG_COPY_UNCACHED         0x00000010
56 #define MMDBG_COPY_WRITE_COMBINED   0x00000020
57 
58 //
59 // Maximum chunk size per copy
60 //
61 #define MMDBG_COPY_MAX_SIZE         0x8
62 
63 #if defined(_X86_) // intenal for marea.c
64 #define MI_STATIC_MEMORY_AREAS              (14)
65 #else
66 #define MI_STATIC_MEMORY_AREAS              (13)
67 #endif
68 
69 #define MEMORY_AREA_SECTION_VIEW            (1)
70 #define MEMORY_AREA_CACHE                   (2)
71 #define MEMORY_AREA_OWNED_BY_ARM3           (15)
72 #define MEMORY_AREA_STATIC                  (0x80000000)
73 
74 /* Although Microsoft says this isn't hardcoded anymore,
75    they won't be able to change it. Stuff depends on it */
76 #define MM_VIRTMEM_GRANULARITY              (64 * 1024)
77 
78 #define STATUS_MM_RESTART_OPERATION         ((NTSTATUS)0xD0000001)
79 
80 /*
81  * Additional flags for protection attributes
82  */
83 #define PAGE_WRITETHROUGH                   (1024)
84 #define PAGE_SYSTEM                         (2048)
85 
86 #define SEC_PHYSICALMEMORY                  (0x80000000)
87 
88 #define MM_PAGEFILE_SEGMENT                 (0x1)
89 #define MM_DATAFILE_SEGMENT                 (0x2)
90 
91 #define MC_CACHE                            (0)
92 #define MC_USER                             (1)
93 #define MC_SYSTEM                           (2)
94 #define MC_MAXIMUM                          (3)
95 
96 #define PAGED_POOL_MASK                     1
97 #define MUST_SUCCEED_POOL_MASK              2
98 #define CACHE_ALIGNED_POOL_MASK             4
99 #define QUOTA_POOL_MASK                     8
100 #define SESSION_POOL_MASK                   32
101 #define VERIFIER_POOL_MASK                  64
102 
103 // FIXME: use ALIGN_UP_BY
104 #define MM_ROUND_UP(x,s)                    \
105     ((PVOID)(((ULONG_PTR)(x)+(s)-1) & ~((ULONG_PTR)(s)-1)))
106 
107 #define MM_ROUND_DOWN(x,s)                  \
108     ((PVOID)(((ULONG_PTR)(x)) & ~((ULONG_PTR)(s)-1)))
109 
110 #define PAGE_FLAGS_VALID_FOR_SECTION \
111     (PAGE_READONLY | \
112      PAGE_READWRITE | \
113      PAGE_WRITECOPY | \
114      PAGE_EXECUTE | \
115      PAGE_EXECUTE_READ | \
116      PAGE_EXECUTE_READWRITE | \
117      PAGE_EXECUTE_WRITECOPY | \
118      PAGE_NOACCESS | \
119      PAGE_NOCACHE)
120 
121 #define PAGE_IS_READABLE                    \
122     (PAGE_READONLY | \
123     PAGE_READWRITE | \
124     PAGE_WRITECOPY | \
125     PAGE_EXECUTE_READ | \
126     PAGE_EXECUTE_READWRITE | \
127     PAGE_EXECUTE_WRITECOPY)
128 
129 #define PAGE_IS_WRITABLE                    \
130     (PAGE_READWRITE | \
131     PAGE_WRITECOPY | \
132     PAGE_EXECUTE_READWRITE | \
133     PAGE_EXECUTE_WRITECOPY)
134 
135 #define PAGE_IS_EXECUTABLE                  \
136     (PAGE_EXECUTE | \
137     PAGE_EXECUTE_READ | \
138     PAGE_EXECUTE_READWRITE | \
139     PAGE_EXECUTE_WRITECOPY)
140 
141 #define PAGE_IS_WRITECOPY                   \
142     (PAGE_WRITECOPY | \
143     PAGE_EXECUTE_WRITECOPY)
144 
145 //
146 // Wait entry for marking pages that are being serviced
147 //
148 #define MM_WAIT_ENTRY            0x7ffffc00
149 
150 #define InterlockedCompareExchangePte(PointerPte, Exchange, Comperand) \
151     InterlockedCompareExchange((PLONG)(PointerPte), Exchange, Comperand)
152 
153 #define InterlockedExchangePte(PointerPte, Value) \
154     InterlockedExchange((PLONG)(PointerPte), Value)
155 
156 typedef struct _MM_SECTION_SEGMENT
157 {
158     FAST_MUTEX Lock;		/* lock which protects the page directory */
159 	PFILE_OBJECT FileObject;
160     LARGE_INTEGER RawLength;		/* length of the segment which is part of the mapped file */
161     LARGE_INTEGER Length;			/* absolute length of the segment */
162     ULONG ReferenceCount;
163 	ULONG CacheCount;
164     ULONG Protection;
165     ULONG Flags;
166     BOOLEAN WriteCopy;
167 	BOOLEAN Locked;
168 
169 	struct
170 	{
171 		ULONGLONG FileOffset;		/* start offset into the file for image sections */
172 		ULONG_PTR VirtualAddress;	/* start offset into the address range for image sections */
173 		ULONG Characteristics;
174 	} Image;
175 
176 	LIST_ENTRY ListOfSegments;
177 	RTL_GENERIC_TABLE PageTable;
178 } MM_SECTION_SEGMENT, *PMM_SECTION_SEGMENT;
179 
180 typedef struct _MM_IMAGE_SECTION_OBJECT
181 {
182     SECTION_IMAGE_INFORMATION ImageInformation;
183     PVOID BasedAddress;
184     ULONG NrSegments;
185     PMM_SECTION_SEGMENT Segments;
186 } MM_IMAGE_SECTION_OBJECT, *PMM_IMAGE_SECTION_OBJECT;
187 
188 typedef struct _ROS_SECTION_OBJECT
189 {
190     CSHORT Type;
191     CSHORT Size;
192     LARGE_INTEGER MaximumSize;
193     ULONG SectionPageProtection;
194     ULONG AllocationAttributes;
195     PFILE_OBJECT FileObject;
196     union
197     {
198         PMM_IMAGE_SECTION_OBJECT ImageSection;
199         PMM_SECTION_SEGMENT Segment;
200     };
201 } ROS_SECTION_OBJECT, *PROS_SECTION_OBJECT;
202 
203 #define MA_GetStartingAddress(_MemoryArea) ((_MemoryArea)->VadNode.StartingVpn << PAGE_SHIFT)
204 #define MA_GetEndingAddress(_MemoryArea) (((_MemoryArea)->VadNode.EndingVpn + 1) << PAGE_SHIFT)
205 
206 typedef struct _MEMORY_AREA
207 {
208     MMVAD VadNode;
209 
210     ULONG Type;
211     ULONG Protect;
212     ULONG Flags;
213     BOOLEAN DeleteInProgress;
214     ULONG Magic;
215     PVOID Vad;
216     union
217     {
218         struct
219         {
220             ROS_SECTION_OBJECT* Section;
221             LARGE_INTEGER ViewOffset;
222             PMM_SECTION_SEGMENT Segment;
223             LIST_ENTRY RegionListHead;
224         } SectionData;
225         struct
226         {
227             LIST_ENTRY RegionListHead;
228         } VirtualMemoryData;
229     } Data;
230 } MEMORY_AREA, *PMEMORY_AREA;
231 
232 typedef struct _MM_RMAP_ENTRY
233 {
234    struct _MM_RMAP_ENTRY* Next;
235    PEPROCESS Process;
236    PVOID Address;
237 #if DBG
238    PVOID Caller;
239 #endif
240 }
241 MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
242 
243 #if MI_TRACE_PFNS
244 extern ULONG MI_PFN_CURRENT_USAGE;
245 extern CHAR MI_PFN_CURRENT_PROCESS_NAME[16];
246 #define MI_SET_USAGE(x)     MI_PFN_CURRENT_USAGE = x
247 #define MI_SET_PROCESS2(x)  memcpy(MI_PFN_CURRENT_PROCESS_NAME, x, 16)
248 #else
249 #define MI_SET_USAGE(x)
250 #define MI_SET_PROCESS2(x)
251 #endif
252 
253 typedef enum _MI_PFN_USAGES
254 {
255     MI_USAGE_NOT_SET = 0,
256     MI_USAGE_PAGED_POOL,
257     MI_USAGE_NONPAGED_POOL,
258     MI_USAGE_NONPAGED_POOL_EXPANSION,
259     MI_USAGE_KERNEL_STACK,
260     MI_USAGE_KERNEL_STACK_EXPANSION,
261     MI_USAGE_SYSTEM_PTE,
262     MI_USAGE_VAD,
263     MI_USAGE_PEB_TEB,
264     MI_USAGE_SECTION,
265     MI_USAGE_PAGE_TABLE,
266     MI_USAGE_PAGE_DIRECTORY,
267     MI_USAGE_LEGACY_PAGE_DIRECTORY,
268     MI_USAGE_DRIVER_PAGE,
269     MI_USAGE_CONTINOUS_ALLOCATION,
270     MI_USAGE_MDL,
271     MI_USAGE_DEMAND_ZERO,
272     MI_USAGE_ZERO_LOOP,
273     MI_USAGE_CACHE,
274     MI_USAGE_PFN_DATABASE,
275     MI_USAGE_BOOT_DRIVER,
276     MI_USAGE_INIT_MEMORY,
277     MI_USAGE_FREE_PAGE
278 } MI_PFN_USAGES;
279 
280 //
281 // These two mappings are actually used by Windows itself, based on the ASSERTS
282 //
283 #define StartOfAllocation ReadInProgress
284 #define EndOfAllocation WriteInProgress
285 
286 typedef struct _MMPFNENTRY
287 {
288     USHORT Modified:1;
289     USHORT ReadInProgress:1;                 // StartOfAllocation
290     USHORT WriteInProgress:1;                // EndOfAllocation
291     USHORT PrototypePte:1;
292     USHORT PageColor:4;
293     USHORT PageLocation:3;
294     USHORT RemovalRequested:1;
295     USHORT CacheAttribute:2;
296     USHORT Rom:1;
297     USHORT ParityError:1;
298 } MMPFNENTRY;
299 
300 // Mm internal
301 typedef struct _MMPFN
302 {
303     union
304     {
305         PFN_NUMBER Flink;
306         ULONG WsIndex;
307         PKEVENT Event;
308         NTSTATUS ReadStatus;
309         SINGLE_LIST_ENTRY NextStackPfn;
310 
311         // HACK for ROSPFN
312         SWAPENTRY SwapEntry;
313     } u1;
314     PMMPTE PteAddress;
315     union
316     {
317         PFN_NUMBER Blink;
318         ULONG_PTR ShareCount;
319     } u2;
320     union
321     {
322         struct
323         {
324             USHORT ReferenceCount;
325             MMPFNENTRY e1;
326         };
327         struct
328         {
329             USHORT ReferenceCount;
330             USHORT ShortFlags;
331         } e2;
332     } u3;
333     union
334     {
335         MMPTE OriginalPte;
336         LONG AweReferenceCount;
337 
338         // HACK for ROSPFN
339         PMM_RMAP_ENTRY RmapListHead;
340     };
341     union
342     {
343         ULONG_PTR EntireFrame;
344         struct
345         {
346             ULONG_PTR PteFrame:25;
347             ULONG_PTR InPageError:1;
348             ULONG_PTR VerifierAllocation:1;
349             ULONG_PTR AweAllocation:1;
350             ULONG_PTR Priority:3;
351             ULONG_PTR MustBeCached:1;
352         };
353     } u4;
354 #if MI_TRACE_PFNS
355     MI_PFN_USAGES PfnUsage;
356     CHAR ProcessName[16];
357 #endif
358 
359     // HACK until WS lists are supported
360     MMWSLE Wsle;
361 } MMPFN, *PMMPFN;
362 
363 extern PMMPFN MmPfnDatabase;
364 
365 typedef struct _MMPFNLIST
366 {
367     PFN_NUMBER Total;
368     MMLISTS ListName;
369     PFN_NUMBER Flink;
370     PFN_NUMBER Blink;
371 } MMPFNLIST, *PMMPFNLIST;
372 
373 extern MMPFNLIST MmZeroedPageListHead;
374 extern MMPFNLIST MmFreePageListHead;
375 extern MMPFNLIST MmStandbyPageListHead;
376 extern MMPFNLIST MmModifiedPageListHead;
377 extern MMPFNLIST MmModifiedNoWritePageListHead;
378 
379 typedef struct _MM_MEMORY_CONSUMER
380 {
381     ULONG PagesUsed;
382     ULONG PagesTarget;
383     NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed);
384 } MM_MEMORY_CONSUMER, *PMM_MEMORY_CONSUMER;
385 
386 typedef struct _MM_REGION
387 {
388     ULONG Type;
389     ULONG Protect;
390     SIZE_T Length;
391     LIST_ENTRY RegionListEntry;
392 } MM_REGION, *PMM_REGION;
393 
394 // Mm internal
395 /* Entry describing free pool memory */
396 typedef struct _MMFREE_POOL_ENTRY
397 {
398     LIST_ENTRY List;
399     PFN_COUNT Size;
400     ULONG Signature;
401     struct _MMFREE_POOL_ENTRY *Owner;
402 } MMFREE_POOL_ENTRY, *PMMFREE_POOL_ENTRY;
403 
404 /* Signature of a freed block */
405 #define MM_FREE_POOL_SIGNATURE 'ARM3'
406 
407 /* Paged pool information */
408 typedef struct _MM_PAGED_POOL_INFO
409 {
410     PRTL_BITMAP PagedPoolAllocationMap;
411     PRTL_BITMAP EndOfPagedPoolBitmap;
412     PMMPTE FirstPteForPagedPool;
413     PMMPTE LastPteForPagedPool;
414     PMMPDE NextPdeForPagedPoolExpansion;
415     ULONG PagedPoolHint;
416     SIZE_T PagedPoolCommit;
417     SIZE_T AllocatedPagedPool;
418 } MM_PAGED_POOL_INFO, *PMM_PAGED_POOL_INFO;
419 
420 extern MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM];
421 
422 typedef VOID
423 (*PMM_ALTER_REGION_FUNC)(
424     PMMSUPPORT AddressSpace,
425     PVOID BaseAddress,
426     SIZE_T Length,
427     ULONG OldType,
428     ULONG OldProtect,
429     ULONG NewType,
430     ULONG NewProtect
431 );
432 
433 typedef VOID
434 (*PMM_FREE_PAGE_FUNC)(
435     PVOID Context,
436     PMEMORY_AREA MemoryArea,
437     PVOID Address,
438     PFN_NUMBER Page,
439     SWAPENTRY SwapEntry,
440     BOOLEAN Dirty
441 );
442 
443 //
444 // Mm copy support for Kd
445 //
446 NTSTATUS
447 NTAPI
448 MmDbgCopyMemory(
449     IN ULONG64 Address,
450     IN PVOID Buffer,
451     IN ULONG Size,
452     IN ULONG Flags
453 );
454 
455 //
456 // Determines if a given address is a session address
457 //
458 BOOLEAN
459 NTAPI
460 MmIsSessionAddress(
461     IN PVOID Address
462 );
463 
464 ULONG
465 NTAPI
466 MmGetSessionId(
467     IN PEPROCESS Process
468 );
469 
470 ULONG
471 NTAPI
472 MmGetSessionIdEx(
473     IN PEPROCESS Process
474 );
475 
476 /* marea.c *******************************************************************/
477 
478 NTSTATUS
479 NTAPI
480 MmCreateMemoryArea(
481     PMMSUPPORT AddressSpace,
482     ULONG Type,
483     PVOID *BaseAddress,
484     SIZE_T Length,
485     ULONG Protection,
486     PMEMORY_AREA *Result,
487     ULONG AllocationFlags,
488     ULONG AllocationGranularity
489 );
490 
491 PMEMORY_AREA
492 NTAPI
493 MmLocateMemoryAreaByAddress(
494     PMMSUPPORT AddressSpace,
495     PVOID Address
496 );
497 
498 NTSTATUS
499 NTAPI
500 MmFreeMemoryArea(
501     PMMSUPPORT AddressSpace,
502     PMEMORY_AREA MemoryArea,
503     PMM_FREE_PAGE_FUNC FreePage,
504     PVOID FreePageContext
505 );
506 
507 VOID
508 NTAPI
509 MiRosCleanupMemoryArea(
510     PEPROCESS Process,
511     PMMVAD Vad);
512 
513 PMEMORY_AREA
514 NTAPI
515 MmLocateMemoryAreaByRegion(
516     PMMSUPPORT AddressSpace,
517     PVOID Address,
518     SIZE_T Length
519 );
520 
521 PVOID
522 NTAPI
523 MmFindGap(
524     PMMSUPPORT AddressSpace,
525     SIZE_T Length,
526     ULONG_PTR Granularity,
527     BOOLEAN TopDown
528 );
529 
530 VOID
531 NTAPI
532 MiRosCheckMemoryAreas(
533    PMMSUPPORT AddressSpace);
534 
535 VOID
536 NTAPI
537 MiCheckAllProcessMemoryAreas(VOID);
538 
539 /* npool.c *******************************************************************/
540 
541 VOID
542 NTAPI
543 MiInitializeNonPagedPool(VOID);
544 
545 PVOID
546 NTAPI
547 MiAllocatePoolPages(
548     IN POOL_TYPE PoolType,
549     IN SIZE_T SizeInBytes
550 );
551 
552 POOL_TYPE
553 NTAPI
554 MmDeterminePoolType(
555     IN PVOID VirtualAddress
556 );
557 
558 ULONG
559 NTAPI
560 MiFreePoolPages(
561     IN PVOID StartingAddress
562 );
563 
564 /* pool.c *******************************************************************/
565 
566 BOOLEAN
567 NTAPI
568 MiRaisePoolQuota(
569     IN POOL_TYPE PoolType,
570     IN ULONG CurrentMaxQuota,
571     OUT PULONG NewMaxQuota
572 );
573 
574 /* mdl.c *********************************************************************/
575 
576 VOID
577 NTAPI
578 MmBuildMdlFromPages(
579     PMDL Mdl,
580     PPFN_NUMBER Pages
581 );
582 
583 /* mminit.c ******************************************************************/
584 
585 VOID
586 NTAPI
587 MmInit1(
588     VOID
589 );
590 
591 BOOLEAN
592 NTAPI
593 MmInitSystem(IN ULONG Phase,
594              IN PLOADER_PARAMETER_BLOCK LoaderBlock);
595 
596 
597 /* pagefile.c ****************************************************************/
598 
599 SWAPENTRY
600 NTAPI
601 MmAllocSwapPage(VOID);
602 
603 VOID
604 NTAPI
605 MmFreeSwapPage(SWAPENTRY Entry);
606 
607 VOID
608 NTAPI
609 MmInitPagingFile(VOID);
610 
611 BOOLEAN
612 NTAPI
613 MmIsFileObjectAPagingFile(PFILE_OBJECT FileObject);
614 
615 NTSTATUS
616 NTAPI
617 MmReadFromSwapPage(
618     SWAPENTRY SwapEntry,
619     PFN_NUMBER Page
620 );
621 
622 NTSTATUS
623 NTAPI
624 MmWriteToSwapPage(
625     SWAPENTRY SwapEntry,
626     PFN_NUMBER Page
627 );
628 
629 VOID
630 NTAPI
631 MmShowOutOfSpaceMessagePagingFile(VOID);
632 
633 NTSTATUS
634 NTAPI
635 MiReadPageFile(
636     _In_ PFN_NUMBER Page,
637     _In_ ULONG PageFileIndex,
638     _In_ ULONG_PTR PageFileOffset);
639 
640 /* process.c ****************************************************************/
641 
642 NTSTATUS
643 NTAPI
644 MmInitializeProcessAddressSpace(
645     IN PEPROCESS Process,
646     IN PEPROCESS Clone OPTIONAL,
647     IN PVOID Section OPTIONAL,
648     IN OUT PULONG Flags,
649     IN POBJECT_NAME_INFORMATION *AuditName OPTIONAL
650 );
651 
652 NTSTATUS
653 NTAPI
654 MmCreatePeb(
655     IN PEPROCESS Process,
656     IN PINITIAL_PEB InitialPeb,
657     OUT PPEB *BasePeb
658 );
659 
660 NTSTATUS
661 NTAPI
662 MmCreateTeb(
663     IN PEPROCESS Process,
664     IN PCLIENT_ID ClientId,
665     IN PINITIAL_TEB InitialTeb,
666     OUT PTEB* BaseTeb
667 );
668 
669 VOID
670 NTAPI
671 MmDeleteTeb(
672     struct _EPROCESS *Process,
673     PTEB Teb
674 );
675 
676 VOID
677 NTAPI
678 MmCleanProcessAddressSpace(IN PEPROCESS Process);
679 
680 NTSTATUS
681 NTAPI
682 MmDeleteProcessAddressSpace(IN PEPROCESS Process);
683 
684 ULONG
685 NTAPI
686 MmGetSessionLocaleId(VOID);
687 
688 NTSTATUS
689 NTAPI
690 MmSetMemoryPriorityProcess(
691     IN PEPROCESS Process,
692     IN UCHAR MemoryPriority
693 );
694 
695 /* i386/pfault.c *************************************************************/
696 
697 NTSTATUS
698 NTAPI
699 MmPageFault(
700     ULONG Cs,
701     PULONG Eip,
702     PULONG Eax,
703     ULONG Cr2,
704     ULONG ErrorCode
705 );
706 
707 /* special.c *****************************************************************/
708 
709 VOID
710 NTAPI
711 MiInitializeSpecialPool(VOID);
712 
713 BOOLEAN
714 NTAPI
715 MmUseSpecialPool(
716     IN SIZE_T NumberOfBytes,
717     IN ULONG Tag);
718 
719 BOOLEAN
720 NTAPI
721 MmIsSpecialPoolAddress(
722     IN PVOID P);
723 
724 BOOLEAN
725 NTAPI
726 MmIsSpecialPoolAddressFree(
727     IN PVOID P);
728 
729 PVOID
730 NTAPI
731 MmAllocateSpecialPool(
732     IN SIZE_T NumberOfBytes,
733     IN ULONG Tag,
734     IN POOL_TYPE PoolType,
735     IN ULONG SpecialType);
736 
737 VOID
738 NTAPI
739 MmFreeSpecialPool(
740     IN PVOID P);
741 
742 /* mm.c **********************************************************************/
743 
744 NTSTATUS
745 NTAPI
746 MmAccessFault(
747     IN ULONG FaultCode,
748     IN PVOID Address,
749     IN KPROCESSOR_MODE Mode,
750     IN PVOID TrapInformation
751 );
752 
753 /* kmap.c ********************************************************************/
754 
755 NTSTATUS
756 NTAPI
757 MiCopyFromUserPage(
758     PFN_NUMBER NewPage,
759     PFN_NUMBER OldPage
760 );
761 
762 /* process.c *****************************************************************/
763 
764 PVOID
765 NTAPI
766 MmCreateKernelStack(BOOLEAN GuiStack, UCHAR Node);
767 
768 VOID
769 NTAPI
770 MmDeleteKernelStack(PVOID Stack,
771                     BOOLEAN GuiStack);
772 
773 /* balace.c ******************************************************************/
774 
775 VOID
776 NTAPI
777 MmInitializeMemoryConsumer(
778     ULONG Consumer,
779     NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed)
780 );
781 
782 VOID
783 NTAPI
784 MmInitializeBalancer(
785     ULONG NrAvailablePages,
786     ULONG NrSystemPages
787 );
788 
789 NTSTATUS
790 NTAPI
791 MmReleasePageMemoryConsumer(
792     ULONG Consumer,
793     PFN_NUMBER Page
794 );
795 
796 NTSTATUS
797 NTAPI
798 MmRequestPageMemoryConsumer(
799     ULONG Consumer,
800     BOOLEAN MyWait,
801     PPFN_NUMBER AllocatedPage
802 );
803 
804 VOID
805 NTAPI
806 MiInitBalancerThread(VOID);
807 
808 VOID
809 NTAPI
810 MmRebalanceMemoryConsumers(VOID);
811 
812 /* rmap.c **************************************************************/
813 
814 VOID
815 NTAPI
816 MmSetRmapListHeadPage(
817     PFN_NUMBER Page,
818     struct _MM_RMAP_ENTRY* ListHead
819 );
820 
821 struct _MM_RMAP_ENTRY*
822 NTAPI
823 MmGetRmapListHeadPage(PFN_NUMBER Page);
824 
825 VOID
826 NTAPI
827 MmInsertRmap(
828     PFN_NUMBER Page,
829     struct _EPROCESS *Process,
830     PVOID Address
831 );
832 
833 VOID
834 NTAPI
835 MmDeleteAllRmaps(
836     PFN_NUMBER Page,
837     PVOID Context,
838     VOID (*DeleteMapping)(PVOID Context, struct _EPROCESS *Process, PVOID Address)
839 );
840 
841 VOID
842 NTAPI
843 MmDeleteRmap(
844     PFN_NUMBER Page,
845     struct _EPROCESS *Process,
846     PVOID Address
847 );
848 
849 VOID
850 NTAPI
851 MmInitializeRmapList(VOID);
852 
853 VOID
854 NTAPI
855 MmSetCleanAllRmaps(PFN_NUMBER Page);
856 
857 VOID
858 NTAPI
859 MmSetDirtyAllRmaps(PFN_NUMBER Page);
860 
861 BOOLEAN
862 NTAPI
863 MmIsDirtyPageRmap(PFN_NUMBER Page);
864 
865 NTSTATUS
866 NTAPI
867 MmPageOutPhysicalAddress(PFN_NUMBER Page);
868 
869 /* freelist.c **********************************************************/
870 
871 FORCEINLINE
872 KIRQL
873 MiAcquirePfnLock(VOID)
874 {
875     return KeAcquireQueuedSpinLock(LockQueuePfnLock);
876 }
877 
878 FORCEINLINE
879 VOID
880 MiReleasePfnLock(
881     _In_ KIRQL OldIrql)
882 {
883     KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
884 }
885 
886 FORCEINLINE
887 VOID
888 MiAcquirePfnLockAtDpcLevel(VOID)
889 {
890     PKSPIN_LOCK_QUEUE LockQueue;
891 
892     ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
893     LockQueue = &KeGetCurrentPrcb()->LockQueue[LockQueuePfnLock];
894     KeAcquireQueuedSpinLockAtDpcLevel(LockQueue);
895 }
896 
897 FORCEINLINE
898 VOID
899 MiReleasePfnLockFromDpcLevel(VOID)
900 {
901     PKSPIN_LOCK_QUEUE LockQueue;
902 
903     LockQueue = &KeGetCurrentPrcb()->LockQueue[LockQueuePfnLock];
904     KeReleaseQueuedSpinLockFromDpcLevel(LockQueue);
905     ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
906 }
907 
908 #define MI_ASSERT_PFN_LOCK_HELD() ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL)
909 
910 FORCEINLINE
911 PMMPFN
912 MiGetPfnEntry(IN PFN_NUMBER Pfn)
913 {
914     PMMPFN Page;
915     extern RTL_BITMAP MiPfnBitMap;
916 
917     /* Make sure the PFN number is valid */
918     if (Pfn > MmHighestPhysicalPage) return NULL;
919 
920     /* Make sure this page actually has a PFN entry */
921     if ((MiPfnBitMap.Buffer) && !(RtlTestBit(&MiPfnBitMap, (ULONG)Pfn))) return NULL;
922 
923     /* Get the entry */
924     Page = &MmPfnDatabase[Pfn];
925 
926     /* Return it */
927     return Page;
928 };
929 
930 FORCEINLINE
931 PFN_NUMBER
932 MiGetPfnEntryIndex(IN PMMPFN Pfn1)
933 {
934     //
935     // This will return the Page Frame Number (PFN) from the MMPFN
936     //
937     return Pfn1 - MmPfnDatabase;
938 }
939 
940 PFN_NUMBER
941 NTAPI
942 MmGetLRUNextUserPage(PFN_NUMBER PreviousPage);
943 
944 PFN_NUMBER
945 NTAPI
946 MmGetLRUFirstUserPage(VOID);
947 
948 VOID
949 NTAPI
950 MmInsertLRULastUserPage(PFN_NUMBER Page);
951 
952 VOID
953 NTAPI
954 MmRemoveLRUUserPage(PFN_NUMBER Page);
955 
956 VOID
957 NTAPI
958 MmDumpArmPfnDatabase(
959    IN BOOLEAN StatusOnly
960 );
961 
962 VOID
963 NTAPI
964 MmZeroPageThread(
965     VOID
966 );
967 
968 /* hypermap.c *****************************************************************/
969 
970 extern PEPROCESS HyperProcess;
971 extern KIRQL HyperIrql;
972 
973 PVOID
974 NTAPI
975 MiMapPageInHyperSpace(IN PEPROCESS Process,
976                       IN PFN_NUMBER Page,
977                       IN PKIRQL OldIrql);
978 
979 VOID
980 NTAPI
981 MiUnmapPageInHyperSpace(IN PEPROCESS Process,
982                         IN PVOID Address,
983                         IN KIRQL OldIrql);
984 
985 PVOID
986 NTAPI
987 MiMapPagesInZeroSpace(IN PMMPFN Pfn1,
988                       IN PFN_NUMBER NumberOfPages);
989 
990 VOID
991 NTAPI
992 MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress,
993                         IN PFN_NUMBER NumberOfPages);
994 
995 //
996 // ReactOS Compatibility Layer
997 //
998 FORCEINLINE
999 PVOID
1000 MmCreateHyperspaceMapping(IN PFN_NUMBER Page)
1001 {
1002     HyperProcess = (PEPROCESS)KeGetCurrentThread()->ApcState.Process;
1003     return MiMapPageInHyperSpace(HyperProcess, Page, &HyperIrql);
1004 }
1005 
1006 #define MmDeleteHyperspaceMapping(x) MiUnmapPageInHyperSpace(HyperProcess, x, HyperIrql);
1007 
1008 /* i386/page.c *********************************************************/
1009 
1010 NTSTATUS
1011 NTAPI
1012 MmCreateVirtualMapping(
1013     struct _EPROCESS* Process,
1014     PVOID Address,
1015     ULONG flProtect,
1016     PPFN_NUMBER Pages,
1017     ULONG PageCount
1018 );
1019 
1020 NTSTATUS
1021 NTAPI
1022 MmCreateVirtualMappingUnsafe(
1023     struct _EPROCESS* Process,
1024     PVOID Address,
1025     ULONG flProtect,
1026     PPFN_NUMBER Pages,
1027     ULONG PageCount
1028 );
1029 
1030 ULONG
1031 NTAPI
1032 MmGetPageProtect(
1033     struct _EPROCESS* Process,
1034     PVOID Address);
1035 
1036 VOID
1037 NTAPI
1038 MmSetPageProtect(
1039     struct _EPROCESS* Process,
1040     PVOID Address,
1041     ULONG flProtect
1042 );
1043 
1044 BOOLEAN
1045 NTAPI
1046 MmIsPagePresent(
1047     struct _EPROCESS* Process,
1048     PVOID Address
1049 );
1050 
1051 BOOLEAN
1052 NTAPI
1053 MmIsDisabledPage(
1054     struct _EPROCESS* Process,
1055     PVOID Address
1056 );
1057 
1058 VOID
1059 NTAPI
1060 MmInitGlobalKernelPageDirectory(VOID);
1061 
1062 VOID
1063 NTAPI
1064 MmGetPageFileMapping(
1065 	struct _EPROCESS *Process,
1066 	PVOID Address,
1067 	SWAPENTRY* SwapEntry);
1068 
1069 VOID
1070 NTAPI
1071 MmDeletePageFileMapping(
1072     struct _EPROCESS *Process,
1073     PVOID Address,
1074     SWAPENTRY* SwapEntry
1075 );
1076 
1077 NTSTATUS
1078 NTAPI
1079 MmCreatePageFileMapping(
1080     struct _EPROCESS *Process,
1081     PVOID Address,
1082     SWAPENTRY SwapEntry
1083 );
1084 
1085 BOOLEAN
1086 NTAPI
1087 MmIsPageSwapEntry(
1088     struct _EPROCESS *Process,
1089     PVOID Address
1090 );
1091 
1092 VOID
1093 NTAPI
1094 MmSetDirtyPage(
1095     struct _EPROCESS *Process,
1096     PVOID Address
1097 );
1098 
1099 PFN_NUMBER
1100 NTAPI
1101 MmAllocPage(
1102     ULONG Consumer
1103 );
1104 
1105 VOID
1106 NTAPI
1107 MmDereferencePage(PFN_NUMBER Page);
1108 
1109 VOID
1110 NTAPI
1111 MmReferencePage(PFN_NUMBER Page);
1112 
1113 ULONG
1114 NTAPI
1115 MmGetReferenceCountPage(PFN_NUMBER Page);
1116 
1117 BOOLEAN
1118 NTAPI
1119 MmIsPageInUse(PFN_NUMBER Page);
1120 
1121 VOID
1122 NTAPI
1123 MmSetSavedSwapEntryPage(
1124     PFN_NUMBER Page,
1125     SWAPENTRY SavedSwapEntry);
1126 
1127 SWAPENTRY
1128 NTAPI
1129 MmGetSavedSwapEntryPage(PFN_NUMBER Page);
1130 
1131 VOID
1132 NTAPI
1133 MmSetCleanPage(
1134     struct _EPROCESS *Process,
1135     PVOID Address
1136 );
1137 
1138 VOID
1139 NTAPI
1140 MmDeletePageTable(
1141     struct _EPROCESS *Process,
1142     PVOID Address
1143 );
1144 
1145 PFN_NUMBER
1146 NTAPI
1147 MmGetPfnForProcess(
1148     struct _EPROCESS *Process,
1149     PVOID Address
1150 );
1151 
1152 BOOLEAN
1153 NTAPI
1154 MmCreateProcessAddressSpace(
1155     IN ULONG MinWs,
1156     IN PEPROCESS Dest,
1157     IN PULONG_PTR DirectoryTableBase
1158 );
1159 
1160 NTSTATUS
1161 NTAPI
1162 MmInitializeHandBuiltProcess(
1163     IN PEPROCESS Process,
1164     IN PULONG_PTR DirectoryTableBase
1165 );
1166 
1167 
1168 NTSTATUS
1169 NTAPI
1170 MmInitializeHandBuiltProcess2(
1171     IN PEPROCESS Process
1172 );
1173 
1174 NTSTATUS
1175 NTAPI
1176 MmSetExecuteOptions(IN ULONG ExecuteOptions);
1177 
1178 NTSTATUS
1179 NTAPI
1180 MmGetExecuteOptions(IN PULONG ExecuteOptions);
1181 
1182 VOID
1183 NTAPI
1184 MmDeleteVirtualMapping(
1185     struct _EPROCESS *Process,
1186     PVOID Address,
1187     BOOLEAN* WasDirty,
1188     PPFN_NUMBER Page
1189 );
1190 
1191 BOOLEAN
1192 NTAPI
1193 MmIsDirtyPage(
1194     struct _EPROCESS *Process,
1195     PVOID Address
1196 );
1197 
1198 /* wset.c ********************************************************************/
1199 
1200 NTSTATUS
1201 MmTrimUserMemory(
1202     ULONG Target,
1203     ULONG Priority,
1204     PULONG NrFreedPages
1205 );
1206 
1207 /* region.c ************************************************************/
1208 
1209 NTSTATUS
1210 NTAPI
1211 MmAlterRegion(
1212     PMMSUPPORT AddressSpace,
1213     PVOID BaseAddress,
1214     PLIST_ENTRY RegionListHead,
1215     PVOID StartAddress,
1216     SIZE_T Length,
1217     ULONG NewType,
1218     ULONG NewProtect,
1219     PMM_ALTER_REGION_FUNC AlterFunc
1220 );
1221 
1222 VOID
1223 NTAPI
1224 MmInitializeRegion(
1225     PLIST_ENTRY RegionListHead,
1226     SIZE_T Length,
1227     ULONG Type,
1228     ULONG Protect
1229 );
1230 
1231 PMM_REGION
1232 NTAPI
1233 MmFindRegion(
1234     PVOID BaseAddress,
1235     PLIST_ENTRY RegionListHead,
1236     PVOID Address,
1237     PVOID* RegionBaseAddress
1238 );
1239 
1240 /* section.c *****************************************************************/
1241 
1242 VOID
1243 NTAPI
1244 MmGetImageInformation(
1245     OUT PSECTION_IMAGE_INFORMATION ImageInformation
1246 );
1247 
1248 PFILE_OBJECT
1249 NTAPI
1250 MmGetFileObjectForSection(
1251     IN PVOID Section
1252 );
1253 NTSTATUS
1254 NTAPI
1255 MmGetFileNameForAddress(
1256     IN PVOID Address,
1257     OUT PUNICODE_STRING ModuleName
1258 );
1259 
1260 NTSTATUS
1261 NTAPI
1262 MmGetFileNameForSection(
1263     IN PVOID Section,
1264     OUT POBJECT_NAME_INFORMATION *ModuleName
1265 );
1266 
1267 NTSTATUS
1268 NTAPI
1269 MmQuerySectionView(
1270     PMEMORY_AREA MemoryArea,
1271     PVOID Address,
1272     PMEMORY_BASIC_INFORMATION Info,
1273     PSIZE_T ResultLength
1274 );
1275 
1276 NTSTATUS
1277 NTAPI
1278 MmProtectSectionView(
1279     PMMSUPPORT AddressSpace,
1280     PMEMORY_AREA MemoryArea,
1281     PVOID BaseAddress,
1282     SIZE_T Length,
1283     ULONG Protect,
1284     PULONG OldProtect
1285 );
1286 
1287 NTSTATUS
1288 NTAPI
1289 MmInitSectionImplementation(VOID);
1290 
1291 NTSTATUS
1292 NTAPI
1293 MmNotPresentFaultSectionView(
1294     PMMSUPPORT AddressSpace,
1295     MEMORY_AREA* MemoryArea,
1296     PVOID Address,
1297     BOOLEAN Locked
1298 );
1299 
1300 NTSTATUS
1301 NTAPI
1302 MmPageOutSectionView(
1303     PMMSUPPORT AddressSpace,
1304     PMEMORY_AREA MemoryArea,
1305     PVOID Address,
1306     ULONG_PTR Entry
1307 );
1308 
1309 NTSTATUS
1310 NTAPI
1311 MmCreatePhysicalMemorySection(VOID);
1312 
1313 NTSTATUS
1314 NTAPI
1315 MmAccessFaultSectionView(
1316     PMMSUPPORT AddressSpace,
1317     MEMORY_AREA* MemoryArea,
1318     PVOID Address
1319 );
1320 
1321 VOID
1322 NTAPI
1323 MmFreeSectionSegments(PFILE_OBJECT FileObject);
1324 
1325 /* sysldr.c ******************************************************************/
1326 
1327 VOID
1328 NTAPI
1329 MiReloadBootLoadedDrivers(
1330     IN PLOADER_PARAMETER_BLOCK LoaderBlock
1331 );
1332 
1333 BOOLEAN
1334 NTAPI
1335 MiInitializeLoadedModuleList(
1336     IN PLOADER_PARAMETER_BLOCK LoaderBlock
1337 );
1338 
1339 NTSTATUS
1340 NTAPI
1341 MmLoadSystemImage(
1342     IN PUNICODE_STRING FileName,
1343     IN PUNICODE_STRING NamePrefix OPTIONAL,
1344     IN PUNICODE_STRING LoadedName OPTIONAL,
1345     IN ULONG Flags,
1346     OUT PVOID *ModuleObject,
1347     OUT PVOID *ImageBaseAddress
1348 );
1349 
1350 NTSTATUS
1351 NTAPI
1352 MmUnloadSystemImage(
1353     IN PVOID ImageHandle
1354 );
1355 
1356 NTSTATUS
1357 NTAPI
1358 MmCheckSystemImage(
1359     IN HANDLE ImageHandle,
1360     IN BOOLEAN PurgeSection
1361 );
1362 
1363 NTSTATUS
1364 NTAPI
1365 MmCallDllInitialize(
1366     IN PLDR_DATA_TABLE_ENTRY LdrEntry,
1367     IN PLIST_ENTRY ListHead
1368 );
1369 
1370 
1371 /* procsup.c *****************************************************************/
1372 
1373 NTSTATUS
1374 NTAPI
1375 MmGrowKernelStack(
1376     IN PVOID StackPointer
1377 );
1378 
1379 
1380 FORCEINLINE
1381 VOID
1382 MmLockAddressSpace(PMMSUPPORT AddressSpace)
1383 {
1384     KeAcquireGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
1385 }
1386 
1387 FORCEINLINE
1388 VOID
1389 MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
1390 {
1391     KeReleaseGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
1392 }
1393 
1394 FORCEINLINE
1395 PEPROCESS
1396 MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
1397 {
1398     if (AddressSpace == MmKernelAddressSpace) return NULL;
1399     return CONTAINING_RECORD(AddressSpace, EPROCESS, Vm);
1400 }
1401 
1402 FORCEINLINE
1403 PMMSUPPORT
1404 MmGetCurrentAddressSpace(VOID)
1405 {
1406     return &((PEPROCESS)KeGetCurrentThread()->ApcState.Process)->Vm;
1407 }
1408 
1409 FORCEINLINE
1410 PMMSUPPORT
1411 MmGetKernelAddressSpace(VOID)
1412 {
1413     return MmKernelAddressSpace;
1414 }
1415 
1416 
1417 /* expool.c ******************************************************************/
1418 
1419 VOID
1420 NTAPI
1421 ExpCheckPoolAllocation(
1422     PVOID P,
1423     POOL_TYPE PoolType,
1424     ULONG Tag);
1425 
1426 VOID
1427 NTAPI
1428 ExReturnPoolQuota(
1429     IN PVOID P);
1430 
1431 
1432 /* mmsup.c *****************************************************************/
1433 
1434 NTSTATUS
1435 NTAPI
1436 MmAdjustWorkingSetSize(
1437     IN SIZE_T WorkingSetMinimumInBytes,
1438     IN SIZE_T WorkingSetMaximumInBytes,
1439     IN ULONG SystemCache,
1440     IN BOOLEAN IncreaseOkay);
1441 
1442 
1443 /* session.c *****************************************************************/
1444 
1445 _IRQL_requires_max_(APC_LEVEL)
1446 NTSTATUS
1447 NTAPI
1448 MmAttachSession(
1449     _Inout_ PVOID SessionEntry,
1450     _Out_ PKAPC_STATE ApcState);
1451 
1452 _IRQL_requires_max_(APC_LEVEL)
1453 VOID
1454 NTAPI
1455 MmDetachSession(
1456     _Inout_ PVOID SessionEntry,
1457     _Out_ PKAPC_STATE ApcState);
1458 
1459 VOID
1460 NTAPI
1461 MmQuitNextSession(
1462     _Inout_ PVOID SessionEntry);
1463 
1464 PVOID
1465 NTAPI
1466 MmGetSessionById(
1467     _In_ ULONG SessionId);
1468 
1469 _IRQL_requires_max_(APC_LEVEL)
1470 VOID
1471 NTAPI
1472 MmSetSessionLocaleId(
1473     _In_ LCID LocaleId);
1474 
1475 
1476 /* virtual.c *****************************************************************/
1477 
1478 NTSTATUS
1479 NTAPI
1480 MmCopyVirtualMemory(IN PEPROCESS SourceProcess,
1481                     IN PVOID SourceAddress,
1482                     IN PEPROCESS TargetProcess,
1483                     OUT PVOID TargetAddress,
1484                     IN SIZE_T BufferSize,
1485                     IN KPROCESSOR_MODE PreviousMode,
1486                     OUT PSIZE_T ReturnSize);
1487 
1488