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