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