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