xref: /reactos/ntoskrnl/include/internal/mm.h (revision f308c6a2)
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 / pagefile.c******************************************************/
870 
871 inline VOID UpdateTotalCommittedPages(LONG Delta)
872 {
873     /*
874      * Add up all the used "Committed" memory + pagefile.
875      * Not sure this is right. 8^\
876      * MmTotalCommittedPages should be adjusted consistently with
877      * other counters at different places.
878      *
879        MmTotalCommittedPages = MiMemoryConsumers[MC_SYSTEM].PagesUsed +
880                                MiMemoryConsumers[MC_USER].PagesUsed +
881                                MiUsedSwapPages;
882      */
883 
884     /* Update Commitment */
885     SIZE_T TotalCommittedPages = InterlockedExchangeAddSizeT(&MmTotalCommittedPages, Delta) + Delta;
886 
887     /* Update Peak = max(Peak, Total) in a lockless way */
888     SIZE_T PeakCommitment = MmPeakCommitment;
889     while (TotalCommittedPages > PeakCommitment &&
890            InterlockedCompareExchangeSizeT(&MmPeakCommitment, TotalCommittedPages, PeakCommitment) != PeakCommitment)
891     {
892         PeakCommitment = MmPeakCommitment;
893     }
894 }
895 
896 /* balance.c *****************************************************************/
897 
898 CODE_SEG("INIT")
899 VOID
900 NTAPI
901 MmInitializeMemoryConsumer(
902     ULONG Consumer,
903     NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed)
904 );
905 
906 CODE_SEG("INIT")
907 VOID
908 NTAPI
909 MmInitializeBalancer(
910     ULONG NrAvailablePages,
911     ULONG NrSystemPages
912 );
913 
914 NTSTATUS
915 NTAPI
916 MmReleasePageMemoryConsumer(
917     ULONG Consumer,
918     PFN_NUMBER Page
919 );
920 
921 NTSTATUS
922 NTAPI
923 MmRequestPageMemoryConsumer(
924     ULONG Consumer,
925     BOOLEAN MyWait,
926     PPFN_NUMBER AllocatedPage
927 );
928 
929 CODE_SEG("INIT")
930 VOID
931 NTAPI
932 MiInitBalancerThread(VOID);
933 
934 VOID
935 NTAPI
936 MmRebalanceMemoryConsumers(VOID);
937 
938 /* rmap.c **************************************************************/
939 #define RMAP_SEGMENT_MASK ~((ULONG_PTR)0xff)
940 #define RMAP_IS_SEGMENT(x) (((ULONG_PTR)(x) & RMAP_SEGMENT_MASK) == RMAP_SEGMENT_MASK)
941 
942 VOID
943 NTAPI
944 MmSetRmapListHeadPage(
945     PFN_NUMBER Page,
946     struct _MM_RMAP_ENTRY* ListHead
947 );
948 
949 struct _MM_RMAP_ENTRY*
950 NTAPI
951 MmGetRmapListHeadPage(PFN_NUMBER Page);
952 
953 VOID
954 NTAPI
955 MmInsertRmap(
956     PFN_NUMBER Page,
957     struct _EPROCESS *Process,
958     PVOID Address
959 );
960 
961 VOID
962 NTAPI
963 MmDeleteAllRmaps(
964     PFN_NUMBER Page,
965     PVOID Context,
966     VOID (*DeleteMapping)(PVOID Context, struct _EPROCESS *Process, PVOID Address)
967 );
968 
969 VOID
970 NTAPI
971 MmDeleteRmap(
972     PFN_NUMBER Page,
973     struct _EPROCESS *Process,
974     PVOID Address
975 );
976 
977 CODE_SEG("INIT")
978 VOID
979 NTAPI
980 MmInitializeRmapList(VOID);
981 
982 NTSTATUS
983 NTAPI
984 MmPageOutPhysicalAddress(PFN_NUMBER Page);
985 
986 PMM_SECTION_SEGMENT
987 NTAPI
988 MmGetSectionAssociation(PFN_NUMBER Page,
989                         PLARGE_INTEGER Offset);
990 
991 /* freelist.c **********************************************************/
992 _IRQL_raises_(DISPATCH_LEVEL)
993 _IRQL_requires_max_(DISPATCH_LEVEL)
994 _Requires_lock_not_held_(MmPfnLock)
995 _Acquires_lock_(MmPfnLock)
996 _IRQL_saves_
997 FORCEINLINE
998 KIRQL
999 MiAcquirePfnLock(VOID)
1000 {
1001     return KeAcquireQueuedSpinLock(LockQueuePfnLock);
1002 }
1003 
1004 _Requires_lock_held_(MmPfnLock)
1005 _Releases_lock_(MmPfnLock)
1006 _IRQL_requires_(DISPATCH_LEVEL)
1007 FORCEINLINE
1008 VOID
1009 MiReleasePfnLock(
1010     _In_ _IRQL_restores_ KIRQL OldIrql)
1011 {
1012     KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
1013 }
1014 
1015 _IRQL_requires_min_(DISPATCH_LEVEL)
1016 _Requires_lock_not_held_(MmPfnLock)
1017 _Acquires_lock_(MmPfnLock)
1018 FORCEINLINE
1019 VOID
1020 MiAcquirePfnLockAtDpcLevel(VOID)
1021 {
1022     PKSPIN_LOCK_QUEUE LockQueue;
1023 
1024     ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
1025     LockQueue = &KeGetCurrentPrcb()->LockQueue[LockQueuePfnLock];
1026     KeAcquireQueuedSpinLockAtDpcLevel(LockQueue);
1027 }
1028 
1029 _Requires_lock_held_(MmPfnLock)
1030 _Releases_lock_(MmPfnLock)
1031 _IRQL_requires_min_(DISPATCH_LEVEL)
1032 FORCEINLINE
1033 VOID
1034 MiReleasePfnLockFromDpcLevel(VOID)
1035 {
1036     PKSPIN_LOCK_QUEUE LockQueue;
1037 
1038     LockQueue = &KeGetCurrentPrcb()->LockQueue[LockQueuePfnLock];
1039     KeReleaseQueuedSpinLockFromDpcLevel(LockQueue);
1040     ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
1041 }
1042 
1043 #define MI_ASSERT_PFN_LOCK_HELD() NT_ASSERT((KeGetCurrentIrql() >= DISPATCH_LEVEL) && (MmPfnLock != 0))
1044 
1045 FORCEINLINE
1046 PMMPFN
1047 MiGetPfnEntry(IN PFN_NUMBER Pfn)
1048 {
1049     PMMPFN Page;
1050     extern RTL_BITMAP MiPfnBitMap;
1051 
1052     /* Make sure the PFN number is valid */
1053     if (Pfn > MmHighestPhysicalPage) return NULL;
1054 
1055     /* Make sure this page actually has a PFN entry */
1056     if ((MiPfnBitMap.Buffer) && !(RtlTestBit(&MiPfnBitMap, (ULONG)Pfn))) return NULL;
1057 
1058     /* Get the entry */
1059     Page = &MmPfnDatabase[Pfn];
1060 
1061     /* Return it */
1062     return Page;
1063 };
1064 
1065 FORCEINLINE
1066 PFN_NUMBER
1067 MiGetPfnEntryIndex(IN PMMPFN Pfn1)
1068 {
1069     //
1070     // This will return the Page Frame Number (PFN) from the MMPFN
1071     //
1072     return Pfn1 - MmPfnDatabase;
1073 }
1074 
1075 PFN_NUMBER
1076 NTAPI
1077 MmGetLRUNextUserPage(PFN_NUMBER PreviousPage, BOOLEAN MoveToLast);
1078 
1079 PFN_NUMBER
1080 NTAPI
1081 MmGetLRUFirstUserPage(VOID);
1082 
1083 VOID
1084 NTAPI
1085 MmDumpArmPfnDatabase(
1086    IN BOOLEAN StatusOnly
1087 );
1088 
1089 VOID
1090 NTAPI
1091 MmZeroPageThread(
1092     VOID
1093 );
1094 
1095 /* hypermap.c *****************************************************************/
1096 PVOID
1097 NTAPI
1098 MiMapPageInHyperSpace(IN PEPROCESS Process,
1099                       IN PFN_NUMBER Page,
1100                       IN PKIRQL OldIrql);
1101 
1102 VOID
1103 NTAPI
1104 MiUnmapPageInHyperSpace(IN PEPROCESS Process,
1105                         IN PVOID Address,
1106                         IN KIRQL OldIrql);
1107 
1108 PVOID
1109 NTAPI
1110 MiMapPagesInZeroSpace(IN PMMPFN Pfn1,
1111                       IN PFN_NUMBER NumberOfPages);
1112 
1113 VOID
1114 NTAPI
1115 MiUnmapPagesInZeroSpace(IN PVOID VirtualAddress,
1116                         IN PFN_NUMBER NumberOfPages);
1117 
1118 /* i386/page.c *********************************************************/
1119 
1120 NTSTATUS
1121 NTAPI
1122 MmCreateVirtualMapping(
1123     struct _EPROCESS* Process,
1124     PVOID Address,
1125     ULONG flProtect,
1126     PFN_NUMBER Page
1127 );
1128 
1129 NTSTATUS
1130 NTAPI
1131 MmCreateVirtualMappingUnsafe(
1132     struct _EPROCESS* Process,
1133     PVOID Address,
1134     ULONG flProtect,
1135     PFN_NUMBER Page
1136 );
1137 
1138 ULONG
1139 NTAPI
1140 MmGetPageProtect(
1141     struct _EPROCESS* Process,
1142     PVOID Address);
1143 
1144 VOID
1145 NTAPI
1146 MmSetPageProtect(
1147     struct _EPROCESS* Process,
1148     PVOID Address,
1149     ULONG flProtect
1150 );
1151 
1152 BOOLEAN
1153 NTAPI
1154 MmIsPagePresent(
1155     struct _EPROCESS* Process,
1156     PVOID Address
1157 );
1158 
1159 BOOLEAN
1160 NTAPI
1161 MmIsDisabledPage(
1162     struct _EPROCESS* Process,
1163     PVOID Address
1164 );
1165 
1166 CODE_SEG("INIT")
1167 VOID
1168 NTAPI
1169 MmInitGlobalKernelPageDirectory(VOID);
1170 
1171 VOID
1172 NTAPI
1173 MmDeletePageFileMapping(
1174     struct _EPROCESS *Process,
1175     PVOID Address,
1176     SWAPENTRY* SwapEntry
1177 );
1178 
1179 NTSTATUS
1180 NTAPI
1181 MmCreatePageFileMapping(
1182     struct _EPROCESS *Process,
1183     PVOID Address,
1184     SWAPENTRY SwapEntry
1185 );
1186 
1187 VOID
1188 NTAPI
1189 MmGetPageFileMapping(
1190     PEPROCESS Process,
1191     PVOID Address,
1192     SWAPENTRY *SwapEntry);
1193 
1194 BOOLEAN
1195 NTAPI
1196 MmIsPageSwapEntry(
1197     struct _EPROCESS *Process,
1198     PVOID Address
1199 );
1200 
1201 PFN_NUMBER
1202 NTAPI
1203 MmAllocPage(
1204     ULONG Consumer
1205 );
1206 
1207 VOID
1208 NTAPI
1209 MmDereferencePage(PFN_NUMBER Page);
1210 
1211 VOID
1212 NTAPI
1213 MmReferencePage(PFN_NUMBER Page);
1214 
1215 ULONG
1216 NTAPI
1217 MmGetReferenceCountPage(PFN_NUMBER Page);
1218 
1219 BOOLEAN
1220 NTAPI
1221 MmIsPageInUse(PFN_NUMBER Page);
1222 
1223 VOID
1224 NTAPI
1225 MmSetSavedSwapEntryPage(
1226     PFN_NUMBER Page,
1227     SWAPENTRY SavedSwapEntry);
1228 
1229 SWAPENTRY
1230 NTAPI
1231 MmGetSavedSwapEntryPage(PFN_NUMBER Page);
1232 
1233 VOID
1234 NTAPI
1235 MmSetCleanPage(
1236     struct _EPROCESS *Process,
1237     PVOID Address
1238 );
1239 
1240 VOID
1241 NTAPI
1242 MmSetDirtyBit(PEPROCESS Process, PVOID Address, BOOLEAN Bit);
1243 #define MmSetCleanPage(__P, __A) MmSetDirtyBit(__P, __A, FALSE)
1244 #define MmSetDirtyPage(__P, __A) MmSetDirtyBit(__P, __A, TRUE)
1245 
1246 VOID
1247 NTAPI
1248 MmDeletePageTable(
1249     struct _EPROCESS *Process,
1250     PVOID Address
1251 );
1252 
1253 PFN_NUMBER
1254 NTAPI
1255 MmGetPfnForProcess(
1256     struct _EPROCESS *Process,
1257     PVOID Address
1258 );
1259 
1260 BOOLEAN
1261 NTAPI
1262 MmCreateProcessAddressSpace(
1263     IN ULONG MinWs,
1264     IN PEPROCESS Dest,
1265     IN PULONG_PTR DirectoryTableBase
1266 );
1267 
1268 CODE_SEG("INIT")
1269 NTSTATUS
1270 NTAPI
1271 MmInitializeHandBuiltProcess(
1272     IN PEPROCESS Process,
1273     IN PULONG_PTR DirectoryTableBase
1274 );
1275 
1276 CODE_SEG("INIT")
1277 NTSTATUS
1278 NTAPI
1279 MmInitializeHandBuiltProcess2(
1280     IN PEPROCESS Process
1281 );
1282 
1283 NTSTATUS
1284 NTAPI
1285 MmSetExecuteOptions(IN ULONG ExecuteOptions);
1286 
1287 NTSTATUS
1288 NTAPI
1289 MmGetExecuteOptions(IN PULONG ExecuteOptions);
1290 
1291 VOID
1292 NTAPI
1293 MmDeleteVirtualMapping(
1294     struct _EPROCESS *Process,
1295     PVOID Address,
1296     BOOLEAN* WasDirty,
1297     PPFN_NUMBER Page
1298 );
1299 
1300 /* arch/procsup.c ************************************************************/
1301 
1302 BOOLEAN
1303 MiArchCreateProcessAddressSpace(
1304     _In_ PEPROCESS Process,
1305     _In_ PULONG_PTR DirectoryTableBase);
1306 
1307 /* wset.c ********************************************************************/
1308 
1309 NTSTATUS
1310 MmTrimUserMemory(
1311     ULONG Target,
1312     ULONG Priority,
1313     PULONG NrFreedPages
1314 );
1315 
1316 /* region.c ************************************************************/
1317 
1318 NTSTATUS
1319 NTAPI
1320 MmAlterRegion(
1321     PMMSUPPORT AddressSpace,
1322     PVOID BaseAddress,
1323     PLIST_ENTRY RegionListHead,
1324     PVOID StartAddress,
1325     SIZE_T Length,
1326     ULONG NewType,
1327     ULONG NewProtect,
1328     PMM_ALTER_REGION_FUNC AlterFunc
1329 );
1330 
1331 VOID
1332 NTAPI
1333 MmInitializeRegion(
1334     PLIST_ENTRY RegionListHead,
1335     SIZE_T Length,
1336     ULONG Type,
1337     ULONG Protect
1338 );
1339 
1340 PMM_REGION
1341 NTAPI
1342 MmFindRegion(
1343     PVOID BaseAddress,
1344     PLIST_ENTRY RegionListHead,
1345     PVOID Address,
1346     PVOID* RegionBaseAddress
1347 );
1348 
1349 /* section.c *****************************************************************/
1350 
1351 #define PFN_FROM_SSE(E)          ((PFN_NUMBER)((E) >> PAGE_SHIFT))
1352 #define IS_SWAP_FROM_SSE(E)      ((E) & 0x00000001)
1353 #define MM_IS_WAIT_PTE(E)        \
1354     (IS_SWAP_FROM_SSE(E) && SWAPENTRY_FROM_SSE(E) == MM_WAIT_ENTRY)
1355 #define MAKE_PFN_SSE(P)          ((ULONG_PTR)((P) << PAGE_SHIFT))
1356 #define SWAPENTRY_FROM_SSE(E)    ((E) >> 1)
1357 #define MAKE_SWAP_SSE(S)         (((ULONG_PTR)(S) << 1) | 0x1)
1358 #define DIRTY_SSE(E)             ((E) | 2)
1359 #define CLEAN_SSE(E)             ((E) & ~2)
1360 #define IS_DIRTY_SSE(E)          ((E) & 2)
1361 #define WRITE_SSE(E)             ((E) | 4)
1362 #define IS_WRITE_SSE(E)          ((E) & 4)
1363 #ifdef _WIN64
1364 #define PAGE_FROM_SSE(E)         ((E) & 0xFFFFFFF000ULL)
1365 #else
1366 #define PAGE_FROM_SSE(E)         ((E) & 0xFFFFF000)
1367 #endif
1368 #define SHARE_COUNT_FROM_SSE(E)  (((E) & 0x00000FFC) >> 3)
1369 #define MAX_SHARE_COUNT          0x1FF
1370 #define MAKE_SSE(P, C)           ((ULONG_PTR)((P) | ((C) << 3)))
1371 #define BUMPREF_SSE(E)           (PAGE_FROM_SSE(E) | ((SHARE_COUNT_FROM_SSE(E) + 1) << 3) | ((E) & 0x7))
1372 #define DECREF_SSE(E)            (PAGE_FROM_SSE(E) | ((SHARE_COUNT_FROM_SSE(E) - 1) << 3) | ((E) & 0x7))
1373 
1374 VOID
1375 NTAPI
1376 _MmLockSectionSegment(PMM_SECTION_SEGMENT Segment,
1377                       const char *file,
1378                       int line);
1379 
1380 #define MmLockSectionSegment(x) _MmLockSectionSegment(x,__FILE__,__LINE__)
1381 
1382 VOID
1383 NTAPI
1384 _MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment,
1385                         const char *file,
1386                         int line);
1387 
1388 #define MmUnlockSectionSegment(x) _MmUnlockSectionSegment(x,__FILE__,__LINE__)
1389 
1390 VOID
1391 NTAPI
1392 MmGetImageInformation(
1393     OUT PSECTION_IMAGE_INFORMATION ImageInformation
1394 );
1395 
1396 PFILE_OBJECT
1397 NTAPI
1398 MmGetFileObjectForSection(
1399     IN PVOID Section
1400 );
1401 NTSTATUS
1402 NTAPI
1403 MmGetFileNameForAddress(
1404     IN PVOID Address,
1405     OUT PUNICODE_STRING ModuleName
1406 );
1407 
1408 NTSTATUS
1409 NTAPI
1410 MmGetFileNameForSection(
1411     IN PVOID Section,
1412     OUT POBJECT_NAME_INFORMATION *ModuleName
1413 );
1414 
1415 NTSTATUS
1416 NTAPI
1417 MmQuerySectionView(
1418     PMEMORY_AREA MemoryArea,
1419     PVOID Address,
1420     PMEMORY_BASIC_INFORMATION Info,
1421     PSIZE_T ResultLength
1422 );
1423 
1424 NTSTATUS
1425 NTAPI
1426 MmProtectSectionView(
1427     PMMSUPPORT AddressSpace,
1428     PMEMORY_AREA MemoryArea,
1429     PVOID BaseAddress,
1430     SIZE_T Length,
1431     ULONG Protect,
1432     PULONG OldProtect
1433 );
1434 
1435 CODE_SEG("INIT")
1436 NTSTATUS
1437 NTAPI
1438 MmInitSectionImplementation(VOID);
1439 
1440 NTSTATUS
1441 NTAPI
1442 MmNotPresentFaultSectionView(
1443     PMMSUPPORT AddressSpace,
1444     MEMORY_AREA* MemoryArea,
1445     PVOID Address,
1446     BOOLEAN Locked
1447 );
1448 
1449 NTSTATUS
1450 NTAPI
1451 MmPageOutSectionView(
1452     PMMSUPPORT AddressSpace,
1453     PMEMORY_AREA MemoryArea,
1454     PVOID Address,
1455     ULONG_PTR Entry
1456 );
1457 
1458 CODE_SEG("INIT")
1459 NTSTATUS
1460 NTAPI
1461 MmCreatePhysicalMemorySection(VOID);
1462 
1463 NTSTATUS
1464 NTAPI
1465 MmAccessFaultSectionView(
1466     PMMSUPPORT AddressSpace,
1467     MEMORY_AREA* MemoryArea,
1468     PVOID Address,
1469     BOOLEAN Locked
1470 );
1471 
1472 VOID
1473 NTAPI
1474 MmFreeSectionSegments(PFILE_OBJECT FileObject);
1475 
1476 /* Exported from NT 6.2 Onward. We keep it internal. */
1477 NTSTATUS
1478 NTAPI
1479 MmMapViewInSystemSpaceEx (
1480     _In_ PVOID Section,
1481     _Outptr_result_bytebuffer_ (*ViewSize) PVOID *MappedBase,
1482     _Inout_ PSIZE_T ViewSize,
1483     _Inout_ PLARGE_INTEGER SectionOffset,
1484     _In_ ULONG_PTR Flags
1485     );
1486 
1487 BOOLEAN
1488 NTAPI
1489 MmArePagesResident(
1490     _In_ PEPROCESS Process,
1491     _In_ PVOID BaseAddress,
1492     _In_ ULONG Length);
1493 
1494 NTSTATUS
1495 NTAPI
1496 MmMakePagesDirty(
1497     _In_ PEPROCESS Process,
1498     _In_ PVOID Address,
1499     _In_ ULONG Length);
1500 
1501 NTSTATUS
1502 NTAPI
1503 MmFlushSegment(
1504     _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer,
1505     _In_opt_ PLARGE_INTEGER Offset,
1506     _In_ ULONG Length,
1507     _Out_opt_ PIO_STATUS_BLOCK Iosb);
1508 
1509 NTSTATUS
1510 NTAPI
1511 MmMakeDataSectionResident(
1512     _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer,
1513     _In_ LONGLONG Offset,
1514     _In_ ULONG Length,
1515     _In_ PLARGE_INTEGER ValidDataLength);
1516 
1517 BOOLEAN
1518 NTAPI
1519 MmPurgeSegment(
1520     _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer,
1521     _In_opt_ PLARGE_INTEGER Offset,
1522     _In_ ULONG Length);
1523 
1524 BOOLEAN
1525 NTAPI
1526 MmCheckDirtySegment(
1527     PMM_SECTION_SEGMENT Segment,
1528     PLARGE_INTEGER Offset,
1529     BOOLEAN ForceDirty,
1530     BOOLEAN PageOut);
1531 
1532 BOOLEAN
1533 NTAPI
1534 MmUnsharePageEntrySectionSegment(PMEMORY_AREA MemoryArea,
1535                                  PMM_SECTION_SEGMENT Segment,
1536                                  PLARGE_INTEGER Offset,
1537                                  BOOLEAN Dirty,
1538                                  BOOLEAN PageOut,
1539                                  ULONG_PTR *InEntry);
1540 
1541 _When_(OldIrql == MM_NOIRQL, _IRQL_requires_max_(DISPATCH_LEVEL))
1542 _When_(OldIrql == MM_NOIRQL, _Requires_lock_not_held_(MmPfnLock))
1543 _When_(OldIrql != MM_NOIRQL, _Requires_lock_held_(MmPfnLock))
1544 _When_(OldIrql != MM_NOIRQL, _Releases_lock_(MmPfnLock))
1545 _When_(OldIrql != MM_NOIRQL, _IRQL_requires_(DISPATCH_LEVEL))
1546 VOID
1547 NTAPI
1548 MmDereferenceSegmentWithLock(
1549     _In_ PMM_SECTION_SEGMENT Segment,
1550     _In_ _When_(OldIrql != MM_NOIRQL, _IRQL_restores_) KIRQL OldIrql);
1551 
1552 _IRQL_requires_max_(DISPATCH_LEVEL)
1553 _Requires_lock_not_held_(MmPfnLock)
1554 FORCEINLINE
1555 VOID
1556 MmDereferenceSegment(PMM_SECTION_SEGMENT Segment)
1557 {
1558     MmDereferenceSegmentWithLock(Segment, MM_NOIRQL);
1559 }
1560 
1561 NTSTATUS
1562 NTAPI
1563 MmExtendSection(
1564     _In_ PVOID Section,
1565     _Inout_ PLARGE_INTEGER NewSize);
1566 
1567 /* sptab.c *******************************************************************/
1568 
1569 NTSTATUS
1570 NTAPI
1571 _MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
1572                               PLARGE_INTEGER Offset,
1573                               ULONG_PTR Entry,
1574                               const char *file,
1575                               int line);
1576 
1577 ULONG_PTR
1578 NTAPI
1579 _MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
1580                               PLARGE_INTEGER Offset,
1581                               const char *file,
1582                               int line);
1583 
1584 #define MmSetPageEntrySectionSegment(S,O,E) _MmSetPageEntrySectionSegment(S,O,E,__FILE__,__LINE__)
1585 
1586 #define MmGetPageEntrySectionSegment(S,O) _MmGetPageEntrySectionSegment(S,O,__FILE__,__LINE__)
1587 
1588 /* sysldr.c ******************************************************************/
1589 
1590 CODE_SEG("INIT")
1591 VOID
1592 NTAPI
1593 MiReloadBootLoadedDrivers(
1594     IN PLOADER_PARAMETER_BLOCK LoaderBlock
1595 );
1596 
1597 CODE_SEG("INIT")
1598 BOOLEAN
1599 NTAPI
1600 MiInitializeLoadedModuleList(
1601     IN PLOADER_PARAMETER_BLOCK LoaderBlock
1602 );
1603 
1604 BOOLEAN
1605 NTAPI
1606 MmChangeKernelResourceSectionProtection(IN ULONG_PTR ProtectionMask);
1607 
1608 VOID
1609 NTAPI
1610 MmMakeKernelResourceSectionWritable(VOID);
1611 
1612 NTSTATUS
1613 NTAPI
1614 MmLoadSystemImage(
1615     IN PUNICODE_STRING FileName,
1616     IN PUNICODE_STRING NamePrefix OPTIONAL,
1617     IN PUNICODE_STRING LoadedName OPTIONAL,
1618     IN ULONG Flags,
1619     OUT PVOID *ModuleObject,
1620     OUT PVOID *ImageBaseAddress
1621 );
1622 
1623 NTSTATUS
1624 NTAPI
1625 MmUnloadSystemImage(
1626     IN PVOID ImageHandle
1627 );
1628 
1629 NTSTATUS
1630 NTAPI
1631 MmCheckSystemImage(
1632     IN HANDLE ImageHandle,
1633     IN BOOLEAN PurgeSection
1634 );
1635 
1636 NTSTATUS
1637 NTAPI
1638 MmCallDllInitialize(
1639     IN PLDR_DATA_TABLE_ENTRY LdrEntry,
1640     IN PLIST_ENTRY ListHead
1641 );
1642 
1643 VOID
1644 NTAPI
1645 MmFreeDriverInitialization(
1646     IN PLDR_DATA_TABLE_ENTRY LdrEntry);
1647 
1648 /* procsup.c *****************************************************************/
1649 
1650 NTSTATUS
1651 NTAPI
1652 MmGrowKernelStack(
1653     IN PVOID StackPointer
1654 );
1655 
1656 
1657 FORCEINLINE
1658 VOID
1659 MmLockAddressSpace(PMMSUPPORT AddressSpace)
1660 {
1661     KeAcquireGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
1662 }
1663 
1664 FORCEINLINE
1665 VOID
1666 MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
1667 {
1668     KeReleaseGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
1669 }
1670 
1671 FORCEINLINE
1672 PEPROCESS
1673 MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
1674 {
1675     if (AddressSpace == MmKernelAddressSpace) return NULL;
1676     return CONTAINING_RECORD(AddressSpace, EPROCESS, Vm);
1677 }
1678 
1679 FORCEINLINE
1680 PMMSUPPORT
1681 MmGetCurrentAddressSpace(VOID)
1682 {
1683     return &((PEPROCESS)KeGetCurrentThread()->ApcState.Process)->Vm;
1684 }
1685 
1686 FORCEINLINE
1687 PMMSUPPORT
1688 MmGetKernelAddressSpace(VOID)
1689 {
1690     return MmKernelAddressSpace;
1691 }
1692 
1693 
1694 /* expool.c ******************************************************************/
1695 
1696 VOID
1697 NTAPI
1698 ExpCheckPoolAllocation(
1699     PVOID P,
1700     POOL_TYPE PoolType,
1701     ULONG Tag);
1702 
1703 VOID
1704 NTAPI
1705 ExReturnPoolQuota(
1706     IN PVOID P);
1707 
1708 
1709 /* mmsup.c *****************************************************************/
1710 
1711 NTSTATUS
1712 NTAPI
1713 MmAdjustWorkingSetSize(
1714     IN SIZE_T WorkingSetMinimumInBytes,
1715     IN SIZE_T WorkingSetMaximumInBytes,
1716     IN ULONG SystemCache,
1717     IN BOOLEAN IncreaseOkay);
1718 
1719 
1720 /* session.c *****************************************************************/
1721 
1722 _IRQL_requires_max_(APC_LEVEL)
1723 NTSTATUS
1724 NTAPI
1725 MmAttachSession(
1726     _Inout_ PVOID SessionEntry,
1727     _Out_ PKAPC_STATE ApcState);
1728 
1729 _IRQL_requires_max_(APC_LEVEL)
1730 VOID
1731 NTAPI
1732 MmDetachSession(
1733     _Inout_ PVOID SessionEntry,
1734     _Out_ PKAPC_STATE ApcState);
1735 
1736 VOID
1737 NTAPI
1738 MmQuitNextSession(
1739     _Inout_ PVOID SessionEntry);
1740 
1741 PVOID
1742 NTAPI
1743 MmGetSessionById(
1744     _In_ ULONG SessionId);
1745 
1746 _IRQL_requires_max_(APC_LEVEL)
1747 VOID
1748 NTAPI
1749 MmSetSessionLocaleId(
1750     _In_ LCID LocaleId);
1751 
1752 /* shutdown.c *****************************************************************/
1753 
1754 VOID
1755 MmShutdownSystem(IN ULONG Phase);
1756 
1757 /* virtual.c *****************************************************************/
1758 
1759 NTSTATUS
1760 NTAPI
1761 MmCopyVirtualMemory(IN PEPROCESS SourceProcess,
1762                     IN PVOID SourceAddress,
1763                     IN PEPROCESS TargetProcess,
1764                     OUT PVOID TargetAddress,
1765                     IN SIZE_T BufferSize,
1766                     IN KPROCESSOR_MODE PreviousMode,
1767                     OUT PSIZE_T ReturnSize);
1768 
1769 /* wslist.cpp ****************************************************************/
1770 _Requires_exclusive_lock_held_(WorkingSet->WorkingSetMutex)
1771 VOID
1772 NTAPI
1773 MiInitializeWorkingSetList(_Inout_ PMMSUPPORT WorkingSet);
1774 
1775 #ifdef __cplusplus
1776 } // extern "C"
1777 
1778 namespace ntoskrnl
1779 {
1780 using MiPfnLockGuard = const KiQueuedSpinLockGuard<LockQueuePfnLock>;
1781 } // namespace ntoskrnl
1782 
1783 #endif
1784