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