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