2005-01-26 20:31:05 +00:00
|
|
|
|
/*
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
|
|
|
* PURPOSE: Paging file functions
|
|
|
|
|
* COPYRIGHT: Copyright 1998-2003 David Welch <welch@mcmail.com>
|
|
|
|
|
* Copyright 2010-2018 Pierre Schweitzer <pierre@reactos.org>
|
1999-12-10 17:04:37 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
|
#include <ntoskrnl.h>
|
2002-02-08 02:57:10 +00:00
|
|
|
|
#define NDEBUG
|
2008-08-30 16:31:06 +00:00
|
|
|
|
#include <debug.h>
|
1999-12-10 17:04:37 +00:00
|
|
|
|
|
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
|
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
/* Minimum pagefile size is 256 pages (1 MB) */
|
|
|
|
|
#define MINIMUM_PAGEFILE_SIZE (256ULL * PAGE_SIZE)
|
|
|
|
|
|
|
|
|
|
/* Maximum pagefile sizes for different architectures */
|
|
|
|
|
#if defined(_M_IX86) && !defined(_X86PAE_)
|
|
|
|
|
/* Around 4 GB */
|
|
|
|
|
#define MAXIMUM_PAGEFILE_SIZE ((1ULL * 1024 * 1024 - 1) * PAGE_SIZE)
|
|
|
|
|
// PAGE_ROUND_DOWN(4ULL * GIGABYTE - 1)
|
|
|
|
|
/* PAE uses the same size as x64 */
|
|
|
|
|
#elif (defined(_M_IX86) && defined(_X86PAE_)) || defined (_M_AMD64) || defined(_M_ARM64)
|
|
|
|
|
/* Around 16 TB */
|
|
|
|
|
#if (NTDDI_VERSION >= NTDDI_WIN10)
|
|
|
|
|
#define MAXIMUM_PAGEFILE_SIZE ((4ULL * 1024 * 1024 * 1024 - 2) * PAGE_SIZE)
|
|
|
|
|
// PAGE_ROUND_DOWN(16ULL * TERABYTE - PAGE_SIZE - 1)
|
|
|
|
|
#else
|
|
|
|
|
#define MAXIMUM_PAGEFILE_SIZE ((4ULL * 1024 * 1024 * 1024 - 1) * PAGE_SIZE)
|
|
|
|
|
// PAGE_ROUND_DOWN(16ULL * TERABYTE - 1)
|
|
|
|
|
#endif
|
|
|
|
|
#elif defined (_M_IA64)
|
|
|
|
|
/* Around 32 TB */
|
|
|
|
|
#define MAXIMUM_PAGEFILE_SIZE ((8ULL * 1024 * 1024 * 1024 - 1) * PAGE_SIZE)
|
|
|
|
|
// PAGE_ROUND_DOWN(32ULL * TERABYTE - 1)
|
|
|
|
|
#elif defined(_M_ARM)
|
|
|
|
|
/* Around 2 GB */
|
|
|
|
|
#if (NTDDI_VERSION >= NTDDI_WIN10)
|
|
|
|
|
#define MAXIMUM_PAGEFILE_SIZE ((512ULL * 1024 - 2) * PAGE_SIZE)
|
|
|
|
|
// PAGE_ROUND_DOWN(2ULL * GIGABYTE - PAGE_SIZE - 1)
|
|
|
|
|
#elif (NTDDI_VERSION >= NTDDI_WINBLUE) // NTDDI_WIN81
|
|
|
|
|
#define MAXIMUM_PAGEFILE_SIZE ((512ULL * 1024 - 1) * PAGE_SIZE)
|
|
|
|
|
// PAGE_ROUND_DOWN(2ULL * GIGABYTE - 1)
|
|
|
|
|
#else
|
|
|
|
|
/* Around 4 GB */
|
|
|
|
|
#define MAXIMUM_PAGEFILE_SIZE ((1ULL * 1024 * 1024 - 1) * PAGE_SIZE)
|
|
|
|
|
// PAGE_ROUND_DOWN(4ULL * GIGABYTE - 1)
|
|
|
|
|
#endif
|
|
|
|
|
#else
|
|
|
|
|
#error Unknown architecture
|
|
|
|
|
#endif
|
2003-11-30 17:19:28 +00:00
|
|
|
|
|
2001-02-06 00:11:20 +00:00
|
|
|
|
/* List of paging files, both used and free */
|
2018-08-13 05:52:05 +00:00
|
|
|
|
PMMPAGING_FILE MmPagingFile[MAX_PAGING_FILES];
|
2001-03-25 03:34:30 +00:00
|
|
|
|
|
2001-02-06 00:11:20 +00:00
|
|
|
|
/* Lock for examining the list of paging files */
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KGUARDED_MUTEX MmPageFileCreationLock;
|
1999-12-10 17:04:37 +00:00
|
|
|
|
|
2002-03-18 16:16:47 +00:00
|
|
|
|
/* Number of paging files */
|
2009-10-31 01:02:35 +00:00
|
|
|
|
ULONG MmNumberOfPagingFiles;
|
2002-03-18 16:16:47 +00:00
|
|
|
|
|
2001-02-06 00:11:20 +00:00
|
|
|
|
/* Number of pages that are available for swapping */
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
|
PFN_COUNT MiFreeSwapPages;
|
2001-03-25 03:34:30 +00:00
|
|
|
|
|
2001-02-06 00:11:20 +00:00
|
|
|
|
/* Number of pages that have been allocated for swapping */
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
|
PFN_COUNT MiUsedSwapPages;
|
2001-03-25 03:34:30 +00:00
|
|
|
|
|
2010-04-20 22:47:51 +00:00
|
|
|
|
BOOLEAN MmZeroPageFile;
|
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
|
/*
|
2005-05-09 01:38:29 +00:00
|
|
|
|
* Number of pages that have been reserved for swapping but not yet allocated
|
2001-02-06 00:11:20 +00:00
|
|
|
|
*/
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
|
static PFN_COUNT MiReservedSwapPages;
|
1999-12-10 17:04:37 +00:00
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
|
/*
|
2001-02-06 00:11:20 +00:00
|
|
|
|
* Ratio between reserved and available swap pages, e.g. setting this to five
|
|
|
|
|
* forces one swap page to be available for every five swap pages that are
|
|
|
|
|
* reserved. Setting this to zero turns off commit checking altogether.
|
|
|
|
|
*/
|
2000-07-04 08:52:47 +00:00
|
|
|
|
#define MM_PAGEFILE_COMMIT_RATIO (1)
|
2001-03-25 03:34:30 +00:00
|
|
|
|
|
2001-02-06 00:11:20 +00:00
|
|
|
|
/*
|
|
|
|
|
* Number of pages that can be used for potentially swapable memory without
|
2002-01-08 00:49:02 +00:00
|
|
|
|
* pagefile space being reserved. The intention is that this allows smss
|
2001-02-06 00:11:20 +00:00
|
|
|
|
* to start up and create page files while ordinarily having a commit
|
|
|
|
|
* ratio of one.
|
|
|
|
|
*/
|
2000-07-04 08:52:47 +00:00
|
|
|
|
#define MM_PAGEFILE_COMMIT_GRACE (256)
|
|
|
|
|
|
2001-02-06 00:11:20 +00:00
|
|
|
|
/*
|
|
|
|
|
* Translate between a swap entry and a file and offset pair.
|
|
|
|
|
*/
|
2009-02-19 11:47:34 +00:00
|
|
|
|
#define FILE_FROM_ENTRY(i) ((i) & 0x0f)
|
|
|
|
|
#define OFFSET_FROM_ENTRY(i) ((i) >> 11)
|
2011-11-15 18:36:26 +00:00
|
|
|
|
#define ENTRY_FROM_FILE_OFFSET(i, j) ((i) | ((j) << 11) | 0x400)
|
2000-07-07 10:30:57 +00:00
|
|
|
|
|
2013-10-07 12:33:03 +00:00
|
|
|
|
/* Make sure there can be only 16 paging files */
|
|
|
|
|
C_ASSERT(FILE_FROM_ENTRY(0xffffffff) < MAX_PAGING_FILES);
|
|
|
|
|
|
2002-08-17 01:42:03 +00:00
|
|
|
|
static BOOLEAN MmSwapSpaceMessage = FALSE;
|
|
|
|
|
|
2018-09-18 19:42:01 +00:00
|
|
|
|
static BOOLEAN MmSystemPageFileLocated = FALSE;
|
|
|
|
|
|
1999-12-10 17:04:37 +00:00
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
|
2008-04-25 07:55:12 +00:00
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
2010-07-15 22:50:12 +00:00
|
|
|
|
MmBuildMdlFromPages(PMDL Mdl, PPFN_NUMBER Pages)
|
2008-04-25 07:55:12 +00:00
|
|
|
|
{
|
2010-07-15 22:50:12 +00:00
|
|
|
|
memcpy(Mdl + 1, Pages, sizeof(PFN_NUMBER) * (PAGE_ROUND_UP(Mdl->ByteOffset+Mdl->ByteCount)/PAGE_SIZE));
|
2008-04-25 07:55:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-05-07 17:44:54 +00:00
|
|
|
|
BOOLEAN
|
2008-11-29 20:47:48 +00:00
|
|
|
|
NTAPI
|
2010-11-22 22:18:02 +00:00
|
|
|
|
MmIsFileObjectAPagingFile(PFILE_OBJECT FileObject)
|
2005-05-07 17:44:54 +00:00
|
|
|
|
{
|
|
|
|
|
ULONG i;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2005-05-07 17:44:54 +00:00
|
|
|
|
/* Loop through all the paging files */
|
2014-08-06 21:53:09 +00:00
|
|
|
|
for (i = 0; i < MmNumberOfPagingFiles; i++)
|
2005-05-07 17:44:54 +00:00
|
|
|
|
{
|
|
|
|
|
/* Check if this is one of them */
|
2018-08-11 21:19:58 +00:00
|
|
|
|
if (MmPagingFile[i]->FileObject == FileObject) return TRUE;
|
2005-05-07 17:44:54 +00:00
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2005-05-07 17:44:54 +00:00
|
|
|
|
/* Nothing found */
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-17 01:42:03 +00:00
|
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
|
NTAPI
|
2002-08-17 01:42:03 +00:00
|
|
|
|
MmShowOutOfSpaceMessagePagingFile(VOID)
|
|
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
|
if (!MmSwapSpaceMessage)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("MM: Out of swap space.\n");
|
|
|
|
|
MmSwapSpaceMessage = TRUE;
|
|
|
|
|
}
|
2002-08-17 01:42:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
NTAPI
|
2010-07-15 22:50:12 +00:00
|
|
|
|
MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
|
2000-07-07 10:30:57 +00:00
|
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
|
ULONG i;
|
|
|
|
|
ULONG_PTR offset;
|
|
|
|
|
LARGE_INTEGER file_offset;
|
|
|
|
|
IO_STATUS_BLOCK Iosb;
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
KEVENT Event;
|
2023-04-14 07:34:21 +00:00
|
|
|
|
UCHAR MdlBase[sizeof(MDL) + sizeof(PFN_NUMBER)];
|
2014-10-05 06:33:34 +00:00
|
|
|
|
PMDL Mdl = (PMDL)MdlBase;
|
|
|
|
|
|
|
|
|
|
DPRINT("MmWriteToSwapPage\n");
|
|
|
|
|
|
|
|
|
|
if (SwapEntry == 0)
|
|
|
|
|
{
|
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = FILE_FROM_ENTRY(SwapEntry);
|
2016-10-23 18:59:42 +00:00
|
|
|
|
offset = OFFSET_FROM_ENTRY(SwapEntry) - 1;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
2018-08-11 21:19:58 +00:00
|
|
|
|
if (MmPagingFile[i]->FileObject == NULL ||
|
|
|
|
|
MmPagingFile[i]->FileObject->DeviceObject == NULL)
|
2014-10-05 06:33:34 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Bad paging file 0x%.8X\n", SwapEntry);
|
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
|
|
|
|
|
MmBuildMdlFromPages(Mdl, &Page);
|
|
|
|
|
Mdl->MdlFlags |= MDL_PAGES_LOCKED;
|
|
|
|
|
|
|
|
|
|
file_offset.QuadPart = offset * PAGE_SIZE;
|
|
|
|
|
|
|
|
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
2018-08-11 21:19:58 +00:00
|
|
|
|
Status = IoSynchronousPageWrite(MmPagingFile[i]->FileObject,
|
2014-10-05 06:33:34 +00:00
|
|
|
|
Mdl,
|
|
|
|
|
&file_offset,
|
|
|
|
|
&Event,
|
|
|
|
|
&Iosb);
|
|
|
|
|
if (Status == STATUS_PENDING)
|
|
|
|
|
{
|
|
|
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
|
Status = Iosb.Status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
|
|
|
|
|
{
|
|
|
|
|
MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
|
|
|
|
|
}
|
|
|
|
|
return(Status);
|
2000-07-07 10:30:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-08-06 21:53:09 +00:00
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
NTAPI
|
2010-07-15 22:50:12 +00:00
|
|
|
|
MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
|
2000-07-07 10:30:57 +00:00
|
|
|
|
{
|
2020-12-07 09:22:28 +00:00
|
|
|
|
return MiReadPageFile(Page, FILE_FROM_ENTRY(SwapEntry), OFFSET_FROM_ENTRY(SwapEntry));
|
2014-08-06 21:53:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
|
NTAPI
|
|
|
|
|
MiReadPageFile(
|
2014-10-05 06:33:34 +00:00
|
|
|
|
_In_ PFN_NUMBER Page,
|
|
|
|
|
_In_ ULONG PageFileIndex,
|
|
|
|
|
_In_ ULONG_PTR PageFileOffset)
|
2014-08-06 21:53:09 +00:00
|
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
|
LARGE_INTEGER file_offset;
|
|
|
|
|
IO_STATUS_BLOCK Iosb;
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
KEVENT Event;
|
2023-04-14 07:34:21 +00:00
|
|
|
|
UCHAR MdlBase[sizeof(MDL) + sizeof(PFN_NUMBER)];
|
2014-10-05 06:33:34 +00:00
|
|
|
|
PMDL Mdl = (PMDL)MdlBase;
|
2018-08-11 21:34:08 +00:00
|
|
|
|
PMMPAGING_FILE PagingFile;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
|
|
|
|
DPRINT("MiReadSwapFile\n");
|
|
|
|
|
|
|
|
|
|
if (PageFileOffset == 0)
|
|
|
|
|
{
|
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-07 09:22:28 +00:00
|
|
|
|
/* Normalize offset. */
|
|
|
|
|
PageFileOffset--;
|
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
|
ASSERT(PageFileIndex < MAX_PAGING_FILES);
|
|
|
|
|
|
2018-08-11 21:19:58 +00:00
|
|
|
|
PagingFile = MmPagingFile[PageFileIndex];
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
|
|
|
|
if (PagingFile->FileObject == NULL || PagingFile->FileObject->DeviceObject == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Bad paging file %u\n", PageFileIndex);
|
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
|
|
|
|
|
MmBuildMdlFromPages(Mdl, &Page);
|
2020-11-06 08:39:31 +00:00
|
|
|
|
Mdl->MdlFlags |= MDL_PAGES_LOCKED | MDL_IO_PAGE_READ;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
|
|
|
|
file_offset.QuadPart = PageFileOffset * PAGE_SIZE;
|
|
|
|
|
|
|
|
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
|
|
|
Status = IoPageRead(PagingFile->FileObject,
|
|
|
|
|
Mdl,
|
|
|
|
|
&file_offset,
|
|
|
|
|
&Event,
|
|
|
|
|
&Iosb);
|
|
|
|
|
if (Status == STATUS_PENDING)
|
|
|
|
|
{
|
|
|
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
|
Status = Iosb.Status;
|
|
|
|
|
}
|
|
|
|
|
if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
|
|
|
|
|
{
|
|
|
|
|
MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
|
|
|
|
|
}
|
|
|
|
|
return(Status);
|
2000-07-07 10:30:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
|
CODE_SEG("INIT")
|
2020-05-23 13:56:10 +00:00
|
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
|
NTAPI
|
2001-02-06 00:11:20 +00:00
|
|
|
|
MmInitPagingFile(VOID)
|
1999-12-10 17:04:37 +00:00
|
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
|
ULONG i;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeInitializeGuardedMutex(&MmPageFileCreationLock);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
|
MiFreeSwapPages = 0;
|
|
|
|
|
MiUsedSwapPages = 0;
|
|
|
|
|
MiReservedSwapPages = 0;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
|
for (i = 0; i < MAX_PAGING_FILES; i++)
|
|
|
|
|
{
|
2018-08-11 21:19:58 +00:00
|
|
|
|
MmPagingFile[i] = NULL;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
MmNumberOfPagingFiles = 0;
|
1999-12-10 17:04:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
|
NTAPI
|
2001-02-06 00:11:20 +00:00
|
|
|
|
MmFreeSwapPage(SWAPENTRY Entry)
|
1999-12-10 17:04:37 +00:00
|
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
|
ULONG i;
|
|
|
|
|
ULONG_PTR off;
|
2018-08-11 21:34:08 +00:00
|
|
|
|
PMMPAGING_FILE PagingFile;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
|
i = FILE_FROM_ENTRY(Entry);
|
2016-10-23 18:59:42 +00:00
|
|
|
|
off = OFFSET_FROM_ENTRY(Entry) - 1;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeAcquireGuardedMutex(&MmPageFileCreationLock);
|
2018-08-11 21:19:58 +00:00
|
|
|
|
|
|
|
|
|
PagingFile = MmPagingFile[i];
|
|
|
|
|
if (PagingFile == NULL)
|
2014-10-05 06:33:34 +00:00
|
|
|
|
{
|
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2018-08-16 12:04:27 +00:00
|
|
|
|
RtlClearBit(PagingFile->Bitmap, off >> 5);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2018-08-16 12:04:27 +00:00
|
|
|
|
PagingFile->FreeSpace++;
|
|
|
|
|
PagingFile->CurrentUsage--;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
|
MiFreeSwapPages++;
|
|
|
|
|
MiUsedSwapPages--;
|
2022-09-12 12:22:52 +00:00
|
|
|
|
UpdateTotalCommittedPages(-1);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeReleaseGuardedMutex(&MmPageFileCreationLock);
|
1999-12-10 17:04:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
|
SWAPENTRY
|
2005-09-14 01:05:50 +00:00
|
|
|
|
NTAPI
|
2001-02-06 00:11:20 +00:00
|
|
|
|
MmAllocSwapPage(VOID)
|
1999-12-10 17:04:37 +00:00
|
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
|
ULONG i;
|
|
|
|
|
ULONG off;
|
|
|
|
|
SWAPENTRY entry;
|
|
|
|
|
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeAcquireGuardedMutex(&MmPageFileCreationLock);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
|
|
|
|
if (MiFreeSwapPages == 0)
|
|
|
|
|
{
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeReleaseGuardedMutex(&MmPageFileCreationLock);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_PAGING_FILES; i++)
|
|
|
|
|
{
|
2018-08-11 21:19:58 +00:00
|
|
|
|
if (MmPagingFile[i] != NULL &&
|
2018-08-16 12:04:27 +00:00
|
|
|
|
MmPagingFile[i]->FreeSpace >= 1)
|
2014-10-05 06:33:34 +00:00
|
|
|
|
{
|
2018-08-16 12:04:27 +00:00
|
|
|
|
off = RtlFindClearBitsAndSet(MmPagingFile[i]->Bitmap, 1, 0);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
if (off == 0xFFFFFFFF)
|
|
|
|
|
{
|
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeReleaseGuardedMutex(&MmPageFileCreationLock);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
|
}
|
|
|
|
|
MiUsedSwapPages++;
|
|
|
|
|
MiFreeSwapPages--;
|
2022-09-12 12:22:52 +00:00
|
|
|
|
UpdateTotalCommittedPages(1);
|
|
|
|
|
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeReleaseGuardedMutex(&MmPageFileCreationLock);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
2016-10-18 19:55:22 +00:00
|
|
|
|
entry = ENTRY_FROM_FILE_OFFSET(i, off + 1);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
return(entry);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeReleaseGuardedMutex(&MmPageFileCreationLock);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
|
return(0);
|
1999-12-10 17:04:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-01 21:07:36 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
NTAPI
|
|
|
|
|
NtCreatePagingFile(
|
|
|
|
|
_In_ PUNICODE_STRING FileName,
|
|
|
|
|
_In_ PLARGE_INTEGER MinimumSize,
|
|
|
|
|
_In_ PLARGE_INTEGER MaximumSize,
|
|
|
|
|
_In_ ULONG Reserved)
|
1999-12-10 17:04:37 +00:00
|
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
|
HANDLE FileHandle;
|
|
|
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
|
PFILE_OBJECT FileObject;
|
2018-08-11 21:34:08 +00:00
|
|
|
|
PMMPAGING_FILE PagingFile;
|
2019-05-26 13:00:21 +00:00
|
|
|
|
SIZE_T AllocMapSize;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
ULONG Count;
|
|
|
|
|
KPROCESSOR_MODE PreviousMode;
|
2018-08-13 06:24:39 +00:00
|
|
|
|
UNICODE_STRING PageFileName;
|
2018-08-16 10:42:34 +00:00
|
|
|
|
LARGE_INTEGER SafeMinimumSize, SafeMaximumSize, AllocationSize;
|
2018-08-10 06:01:31 +00:00
|
|
|
|
FILE_FS_DEVICE_INFORMATION FsDeviceInfo;
|
2018-08-10 06:40:02 +00:00
|
|
|
|
SECURITY_DESCRIPTOR SecurityDescriptor;
|
|
|
|
|
PACL Dacl;
|
2018-08-13 06:24:39 +00:00
|
|
|
|
PWSTR Buffer;
|
2018-08-16 17:00:22 +00:00
|
|
|
|
DEVICE_TYPE DeviceType;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
2018-08-16 10:39:24 +00:00
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
2019-01-27 21:49:50 +00:00
|
|
|
|
DPRINT("NtCreatePagingFile(FileName: '%wZ', MinimumSize: %I64d, MaximumSize: %I64d)\n",
|
|
|
|
|
FileName, MinimumSize->QuadPart, MaximumSize->QuadPart);
|
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
|
if (MmNumberOfPagingFiles >= MAX_PAGING_FILES)
|
|
|
|
|
{
|
2018-08-09 19:13:08 +00:00
|
|
|
|
return STATUS_TOO_MANY_PAGING_FILES;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PreviousMode = ExGetPreviousMode();
|
|
|
|
|
|
|
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
|
{
|
2018-08-09 19:13:08 +00:00
|
|
|
|
if (SeSinglePrivilegeCheck(SeCreatePagefilePrivilege, PreviousMode) != TRUE)
|
|
|
|
|
{
|
|
|
|
|
return STATUS_PRIVILEGE_NOT_HELD;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
|
_SEH2_TRY
|
|
|
|
|
{
|
2018-08-16 10:42:34 +00:00
|
|
|
|
SafeMinimumSize = ProbeForReadLargeInteger(MinimumSize);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
|
2019-01-27 21:49:50 +00:00
|
|
|
|
PageFileName = ProbeForReadUnicodeString(FileName);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
|
{
|
|
|
|
|
/* Return the exception code */
|
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
|
|
|
|
}
|
|
|
|
|
_SEH2_END;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-08-16 10:42:34 +00:00
|
|
|
|
SafeMinimumSize = *MinimumSize;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
SafeMaximumSize = *MaximumSize;
|
2019-01-27 21:49:50 +00:00
|
|
|
|
PageFileName = *FileName;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 21:49:50 +00:00
|
|
|
|
/*
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
* Pagefiles cannot be larger than the platform-specific memory addressable
|
|
|
|
|
* limits, and of course the minimum should be smaller than the maximum.
|
2019-01-27 21:49:50 +00:00
|
|
|
|
*/
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
if (SafeMinimumSize.QuadPart < MINIMUM_PAGEFILE_SIZE ||
|
|
|
|
|
SafeMinimumSize.QuadPart > MAXIMUM_PAGEFILE_SIZE)
|
2014-10-05 06:33:34 +00:00
|
|
|
|
{
|
|
|
|
|
return STATUS_INVALID_PARAMETER_2;
|
|
|
|
|
}
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
if (SafeMaximumSize.QuadPart < SafeMinimumSize.QuadPart ||
|
|
|
|
|
SafeMaximumSize.QuadPart > MAXIMUM_PAGEFILE_SIZE)
|
2014-10-05 06:33:34 +00:00
|
|
|
|
{
|
|
|
|
|
return STATUS_INVALID_PARAMETER_3;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 21:49:50 +00:00
|
|
|
|
/* Validate the name length */
|
|
|
|
|
if ((PageFileName.Length == 0) ||
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
(PageFileName.Length > MAXIMUM_FILENAME_LENGTH))
|
2018-08-13 06:24:39 +00:00
|
|
|
|
{
|
|
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
|
}
|
|
|
|
|
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
/* Allocate a buffer to keep the name copy. Note that it is kept only
|
|
|
|
|
* for information purposes, so it gets allocated in the paged pool,
|
|
|
|
|
* even if it will be stored in the PagingFile structure, that is
|
|
|
|
|
* allocated from non-paged pool (see below). */
|
2018-08-13 06:24:39 +00:00
|
|
|
|
PageFileName.MaximumLength = PageFileName.Length;
|
|
|
|
|
Buffer = ExAllocatePoolWithTag(PagedPool, PageFileName.Length, TAG_MM);
|
|
|
|
|
if (Buffer == NULL)
|
2014-10-05 06:33:34 +00:00
|
|
|
|
{
|
2018-08-13 06:24:39 +00:00
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 21:49:50 +00:00
|
|
|
|
/* Copy the name */
|
2018-08-13 06:24:39 +00:00
|
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
|
{
|
|
|
|
|
_SEH2_TRY
|
|
|
|
|
{
|
2019-01-27 21:49:50 +00:00
|
|
|
|
ProbeForRead(PageFileName.Buffer, PageFileName.Length, sizeof(WCHAR));
|
2018-08-13 06:24:39 +00:00
|
|
|
|
RtlCopyMemory(Buffer, PageFileName.Buffer, PageFileName.Length);
|
|
|
|
|
}
|
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
|
{
|
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
|
|
|
|
|
|
|
|
|
/* Return the exception code */
|
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
|
|
|
|
}
|
|
|
|
|
_SEH2_END;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RtlCopyMemory(Buffer, PageFileName.Buffer, PageFileName.Length);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-27 21:49:50 +00:00
|
|
|
|
/* Replace caller's buffer with ours */
|
2018-08-13 06:24:39 +00:00
|
|
|
|
PageFileName.Buffer = Buffer;
|
|
|
|
|
|
2018-08-10 06:40:02 +00:00
|
|
|
|
/* Create the security descriptor for the page file */
|
|
|
|
|
Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2018-08-13 06:24:39 +00:00
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
2018-08-10 06:40:02 +00:00
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create the DACL: we will only allow two SIDs */
|
|
|
|
|
Count = sizeof(ACL) + (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) +
|
|
|
|
|
(sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid));
|
2022-11-01 21:06:12 +00:00
|
|
|
|
Dacl = ExAllocatePoolWithTag(PagedPool, Count, TAG_DACL);
|
2018-08-10 06:40:02 +00:00
|
|
|
|
if (Dacl == NULL)
|
|
|
|
|
{
|
2018-08-13 06:24:39 +00:00
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
2018-08-10 06:40:02 +00:00
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Initialize the DACL */
|
|
|
|
|
Status = RtlCreateAcl(Dacl, Count, ACL_REVISION);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
goto EarlyQuit;
|
2018-08-10 06:40:02 +00:00
|
|
|
|
|
|
|
|
|
/* Grant full access to admins */
|
|
|
|
|
Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, FILE_ALL_ACCESS, SeAliasAdminsSid);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
goto EarlyQuit;
|
2018-08-10 06:40:02 +00:00
|
|
|
|
|
|
|
|
|
/* Grant full access to SYSTEM */
|
|
|
|
|
Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, FILE_ALL_ACCESS, SeLocalSystemSid);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
goto EarlyQuit;
|
2018-08-10 06:40:02 +00:00
|
|
|
|
|
|
|
|
|
/* Attach the DACL to the security descriptor */
|
|
|
|
|
Status = RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl, FALSE);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
goto EarlyQuit;
|
2018-08-10 06:40:02 +00:00
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
2018-08-13 06:24:39 +00:00
|
|
|
|
&PageFileName,
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
2014-10-05 06:33:34 +00:00
|
|
|
|
NULL,
|
2018-08-10 06:40:02 +00:00
|
|
|
|
&SecurityDescriptor);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
2018-08-10 05:50:16 +00:00
|
|
|
|
/* Make sure we can at least store a complete page:
|
|
|
|
|
* If we have 2048 BytesPerAllocationUnit (FAT16 < 128MB) there is
|
|
|
|
|
* a problem if the paging file is fragmented. Suppose the first cluster
|
|
|
|
|
* of the paging file is cluster 3042 but cluster 3043 is NOT part of the
|
|
|
|
|
* paging file but of another file. We can't write a complete page (4096
|
|
|
|
|
* bytes) to the physical location of cluster 3042 then. */
|
2018-08-16 10:42:34 +00:00
|
|
|
|
AllocationSize.QuadPart = SafeMinimumSize.QuadPart + PAGE_SIZE;
|
2018-08-10 05:50:16 +00:00
|
|
|
|
|
|
|
|
|
/* First, attempt to replace the page file, if existing */
|
2014-10-05 06:33:34 +00:00
|
|
|
|
Status = IoCreateFile(&FileHandle,
|
2018-08-10 05:50:16 +00:00
|
|
|
|
SYNCHRONIZE | WRITE_DAC | FILE_READ_DATA | FILE_WRITE_DATA,
|
2014-10-05 06:33:34 +00:00
|
|
|
|
&ObjectAttributes,
|
|
|
|
|
&IoStatus,
|
2018-08-10 05:50:16 +00:00
|
|
|
|
&AllocationSize,
|
|
|
|
|
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
|
|
|
|
|
FILE_SHARE_WRITE,
|
|
|
|
|
FILE_SUPERSEDE,
|
|
|
|
|
FILE_DELETE_ON_CLOSE | FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING,
|
2014-10-05 06:33:34 +00:00
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
CreateFileTypeNone,
|
|
|
|
|
NULL,
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
IO_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING);
|
2018-08-10 05:50:16 +00:00
|
|
|
|
/* If we failed, relax a bit constraints, someone may be already holding the
|
|
|
|
|
* the file, so share write, don't attempt to replace and don't delete on close
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
* (basically, don't do anything conflicting).
|
2018-08-16 09:58:58 +00:00
|
|
|
|
* This can happen if the caller attempts to extend a page file.
|
2018-08-10 05:50:16 +00:00
|
|
|
|
*/
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2018-08-16 09:58:58 +00:00
|
|
|
|
ULONG i;
|
|
|
|
|
|
2018-08-10 05:50:16 +00:00
|
|
|
|
Status = IoCreateFile(&FileHandle,
|
|
|
|
|
SYNCHRONIZE | FILE_WRITE_DATA,
|
|
|
|
|
&ObjectAttributes,
|
|
|
|
|
&IoStatus,
|
|
|
|
|
&AllocationSize,
|
|
|
|
|
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
|
|
|
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
|
|
|
FILE_OPEN,
|
|
|
|
|
FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
CreateFileTypeNone,
|
|
|
|
|
NULL,
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
IO_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING);
|
2018-08-16 09:58:58 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
goto EarlyQuit;
|
2018-08-16 09:58:58 +00:00
|
|
|
|
|
|
|
|
|
/* We opened it! Check we are that "someone" ;-)
|
|
|
|
|
* First, get the opened file object.
|
|
|
|
|
*/
|
|
|
|
|
Status = ObReferenceObjectByHandle(FileHandle,
|
|
|
|
|
FILE_READ_DATA | FILE_WRITE_DATA,
|
|
|
|
|
IoFileObjectType,
|
|
|
|
|
KernelMode,
|
|
|
|
|
(PVOID*)&FileObject,
|
|
|
|
|
NULL);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
ZwClose(FileHandle);
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
goto EarlyQuit;
|
2018-08-16 09:58:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find if it matches a previous page file */
|
|
|
|
|
PagingFile = NULL;
|
2018-08-16 10:39:24 +00:00
|
|
|
|
|
|
|
|
|
KeAcquireGuardedMutex(&MmPageFileCreationLock);
|
2018-08-16 09:58:58 +00:00
|
|
|
|
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
for (i = 0; i < MmNumberOfPagingFiles; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (MmPagingFile[i]->FileObject->SectionObjectPointer == FileObject->SectionObjectPointer)
|
2018-08-16 09:58:58 +00:00
|
|
|
|
{
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
/* Same object pointer: this is the matching page file */
|
|
|
|
|
PagingFile = MmPagingFile[i];
|
|
|
|
|
break;
|
2018-08-16 09:58:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we didn't find the page file, fail */
|
|
|
|
|
if (PagingFile == NULL)
|
|
|
|
|
{
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeReleaseGuardedMutex(&MmPageFileCreationLock);
|
2018-08-16 09:58:58 +00:00
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
|
ZwClose(FileHandle);
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
Status = STATUS_NOT_FOUND;
|
|
|
|
|
goto EarlyQuit;
|
2018-08-16 09:58:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-16 11:41:16 +00:00
|
|
|
|
/* Don't allow page file shrinking */
|
2018-08-16 11:50:16 +00:00
|
|
|
|
if (PagingFile->MinimumSize > (SafeMinimumSize.QuadPart >> PAGE_SHIFT))
|
2018-08-16 11:41:16 +00:00
|
|
|
|
{
|
|
|
|
|
KeReleaseGuardedMutex(&MmPageFileCreationLock);
|
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
|
ZwClose(FileHandle);
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
Status = STATUS_INVALID_PARAMETER_2;
|
|
|
|
|
goto EarlyQuit;
|
2018-08-16 11:41:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-16 11:50:16 +00:00
|
|
|
|
if ((SafeMaximumSize.QuadPart >> PAGE_SHIFT) < PagingFile->MaximumSize)
|
2018-08-16 11:41:16 +00:00
|
|
|
|
{
|
|
|
|
|
KeReleaseGuardedMutex(&MmPageFileCreationLock);
|
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
|
ZwClose(FileHandle);
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
Status = STATUS_INVALID_PARAMETER_3;
|
|
|
|
|
goto EarlyQuit;
|
2018-08-16 11:41:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-16 09:58:58 +00:00
|
|
|
|
/* FIXME: implement parameters checking and page file extension */
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeReleaseGuardedMutex(&MmPageFileCreationLock);
|
2018-08-16 09:58:58 +00:00
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
|
ZwClose(FileHandle);
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
|
goto EarlyQuit;
|
2018-08-10 05:50:16 +00:00
|
|
|
|
}
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
EarlyQuit:
|
2018-08-10 05:50:16 +00:00
|
|
|
|
DPRINT1("Failed creating page file: %lx\n", Status);
|
2022-11-01 21:06:12 +00:00
|
|
|
|
ExFreePoolWithTag(Dacl, TAG_DACL);
|
2018-08-13 06:24:39 +00:00
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
|
|
|
|
return Status;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-10 06:40:02 +00:00
|
|
|
|
/* Set the security descriptor */
|
|
|
|
|
if (NT_SUCCESS(IoStatus.Status))
|
|
|
|
|
{
|
|
|
|
|
Status = ZwSetSecurityObject(FileHandle, DACL_SECURITY_INFORMATION, &SecurityDescriptor);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
ZwClose(FileHandle);
|
2022-11-01 21:06:12 +00:00
|
|
|
|
ExFreePoolWithTag(Dacl, TAG_DACL);
|
2018-08-13 06:24:39 +00:00
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
2018-08-10 06:40:02 +00:00
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* DACL is no longer needed, free it */
|
2022-11-01 21:06:12 +00:00
|
|
|
|
ExFreePoolWithTag(Dacl, TAG_DACL);
|
2018-08-10 06:40:02 +00:00
|
|
|
|
|
2022-11-01 21:06:12 +00:00
|
|
|
|
/* FIXME: To enable once page file management is moved to ARM3 */
|
2018-08-16 16:49:55 +00:00
|
|
|
|
#if 0
|
|
|
|
|
/* Check we won't overflow commit limit with the page file */
|
|
|
|
|
if (MmTotalCommitLimitMaximum + (SafeMaximumSize.QuadPart >> PAGE_SHIFT) <= MmTotalCommitLimitMaximum)
|
|
|
|
|
{
|
|
|
|
|
ZwClose(FileHandle);
|
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
|
|
|
|
return STATUS_INVALID_PARAMETER_3;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-08-16 10:42:34 +00:00
|
|
|
|
/* Set its end of file to minimal size */
|
2014-10-05 06:33:34 +00:00
|
|
|
|
Status = ZwSetInformationFile(FileHandle,
|
|
|
|
|
&IoStatus,
|
2018-08-16 10:42:34 +00:00
|
|
|
|
&SafeMinimumSize,
|
2014-10-05 06:33:34 +00:00
|
|
|
|
sizeof(LARGE_INTEGER),
|
2018-08-10 05:50:16 +00:00
|
|
|
|
FileEndOfFileInformation);
|
|
|
|
|
if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStatus.Status))
|
2014-10-05 06:33:34 +00:00
|
|
|
|
{
|
|
|
|
|
ZwClose(FileHandle);
|
2018-08-13 06:24:39 +00:00
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
|
|
|
|
return Status;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Status = ObReferenceObjectByHandle(FileHandle,
|
2018-08-16 16:54:23 +00:00
|
|
|
|
FILE_READ_DATA | FILE_WRITE_DATA,
|
2014-10-05 06:33:34 +00:00
|
|
|
|
IoFileObjectType,
|
2015-09-18 14:22:12 +00:00
|
|
|
|
KernelMode,
|
2014-10-05 06:33:34 +00:00
|
|
|
|
(PVOID*)&FileObject,
|
|
|
|
|
NULL);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
ZwClose(FileHandle);
|
2018-08-13 06:24:39 +00:00
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
|
|
|
|
return Status;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-16 17:00:22 +00:00
|
|
|
|
/* Only allow page file on a few device types */
|
|
|
|
|
DeviceType = IoGetRelatedDeviceObject(FileObject)->DeviceType;
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
if (DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM &&
|
|
|
|
|
DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM &&
|
|
|
|
|
DeviceType != FILE_DEVICE_DFS_VOLUME &&
|
|
|
|
|
DeviceType != FILE_DEVICE_DFS_FILE_SYSTEM)
|
2018-08-16 17:00:22 +00:00
|
|
|
|
{
|
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
|
ZwClose(FileHandle);
|
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-10 06:01:31 +00:00
|
|
|
|
/* Deny page file creation on a floppy disk */
|
|
|
|
|
FsDeviceInfo.Characteristics = 0;
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
IoQueryVolumeInformation(FileObject, FileFsDeviceInformation,
|
|
|
|
|
sizeof(FsDeviceInfo), &FsDeviceInfo, &Count);
|
2018-08-10 06:01:31 +00:00
|
|
|
|
if (BooleanFlagOn(FsDeviceInfo.Characteristics, FILE_FLOPPY_DISKETTE))
|
|
|
|
|
{
|
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
|
ZwClose(FileHandle);
|
2018-08-13 06:24:39 +00:00
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
2018-08-10 06:01:31 +00:00
|
|
|
|
return STATUS_FLOPPY_VOLUME;
|
|
|
|
|
}
|
|
|
|
|
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
/*
|
|
|
|
|
* Missing validation steps TODO:
|
|
|
|
|
* (see https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm )
|
|
|
|
|
*
|
|
|
|
|
* - Verify that no file system driver or any filter driver has done file
|
|
|
|
|
* I/O while opening the file.
|
|
|
|
|
* Verify that nothing of the paging file is yet in memory. Specifically,
|
|
|
|
|
* the file object must either have no SectionObjectPointer or the latter
|
|
|
|
|
* must have neither a DataSectionObject nor an ImageSectionObject.
|
|
|
|
|
* Otherwise, we should fail, returning STATUS_INCOMPATIBLE_FILE_MAP.
|
|
|
|
|
*
|
|
|
|
|
* - Inform all the applicable drivers to prepare for the possibility of
|
|
|
|
|
* paging I/O. Much of the point to paging I/O is to resolve page faults.
|
|
|
|
|
* Especially important is that drivers that handle paging I/O do not
|
|
|
|
|
* cause more page faults. All the code and data that each driver might
|
|
|
|
|
* ever use for access to the paging file must be locked into physical
|
|
|
|
|
* memory. This can’t be left until paging I/O actually occurs.
|
|
|
|
|
* It must be done in advance.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
PagingFile = ExAllocatePoolZero(NonPagedPool, sizeof(*PagingFile), TAG_MM);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
if (PagingFile == NULL)
|
|
|
|
|
{
|
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
|
ZwClose(FileHandle);
|
2018-08-13 06:24:39 +00:00
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
2018-08-13 06:29:17 +00:00
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-10 05:50:16 +00:00
|
|
|
|
PagingFile->FileHandle = FileHandle;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
PagingFile->FileObject = FileObject;
|
2018-08-16 12:04:27 +00:00
|
|
|
|
PagingFile->Size = (SafeMinimumSize.QuadPart >> PAGE_SHIFT);
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
PagingFile->MinimumSize = PagingFile->Size;
|
|
|
|
|
PagingFile->MaximumSize = (SafeMaximumSize.QuadPart >> PAGE_SHIFT);
|
2018-08-16 12:04:27 +00:00
|
|
|
|
/* First page is never used: it's the header
|
|
|
|
|
* TODO: write it
|
|
|
|
|
*/
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
PagingFile->FreeSpace = PagingFile->Size - 1;
|
2018-08-16 12:04:27 +00:00
|
|
|
|
PagingFile->CurrentUsage = 0;
|
2018-08-13 06:24:39 +00:00
|
|
|
|
PagingFile->PageFileName = PageFileName;
|
2018-08-16 12:04:27 +00:00
|
|
|
|
ASSERT(PagingFile->Size == PagingFile->FreeSpace + PagingFile->CurrentUsage + 1);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
2018-08-16 12:04:27 +00:00
|
|
|
|
AllocMapSize = sizeof(RTL_BITMAP) + (((PagingFile->MaximumSize + 31) / 32) * sizeof(ULONG));
|
|
|
|
|
PagingFile->Bitmap = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
AllocMapSize,
|
|
|
|
|
TAG_MM);
|
|
|
|
|
if (PagingFile->Bitmap == NULL)
|
2014-10-05 06:33:34 +00:00
|
|
|
|
{
|
2018-08-13 06:29:17 +00:00
|
|
|
|
ExFreePoolWithTag(PagingFile, TAG_MM);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
|
ZwClose(FileHandle);
|
2018-08-13 06:24:39 +00:00
|
|
|
|
ExFreePoolWithTag(Buffer, TAG_MM);
|
2018-08-13 06:29:17 +00:00
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-16 12:04:27 +00:00
|
|
|
|
RtlInitializeBitMap(PagingFile->Bitmap,
|
|
|
|
|
(PULONG)(PagingFile->Bitmap + 1),
|
|
|
|
|
(ULONG)(PagingFile->MaximumSize));
|
|
|
|
|
RtlClearAllBits(PagingFile->Bitmap);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
/* Insert the new paging file information into the list */
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeAcquireGuardedMutex(&MmPageFileCreationLock);
|
[SMSS][NTOS:MM] Implement the architecture-specific pagefile size limits + code review. (#4843)
What we have:
- Maximum number of pagefiles: 16
- Minimum pagefile size: 256 pages (1 MB when page size = 4096 bytes)
- Maximum pagefile size:
* 32-bit platforms: (1024 * 1024 - 1) pages (~ 4095 MB)
* x86 with PAE support: same size as for AMD x64
* x64 platform: (4 * 1024 * 1024 * 1024 - 1) pages (~ 16 TB)
* IA64 platform: (8 * 1024 * 1024 * 1024 - 1) pages (~ 32 TB)
Those are the values as supported and verified by the NT kernel.
Now, user-mode programs (including SMSS.EXE) have different opinions
on these, namely, they consider estimates directly in MB, respectively:
4095 MB, (16 * 1024 * 1024) MB, and (32 * 1024 * 1024) MB
(verified on Win2k3 and Win7 32 and 64 bits).
Also here, the minimum pagefile size is set to 2 MB.
Starting Windows 8+ (and 10), those values change slightly, and are
still not fully synchronized between NTOS:MM and SMSS. Finally, while
(x86 PAE and) AMD64 and ARM64 seem to share the maximum pagefile
size limit, 32-bit ARMv7 appears to use different limits than regular
x86 (2 GB instead of 4).
Please keep those values as they are for NT compatibility!
See the following references:
https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
https://techcommunity.microsoft.com/t5/ask-the-performance-team/what-is-the-page-file-for-anyway/ba-p/372608
+ Manual extraction of the values from different NT 6.2,6.3,10 builds.
[SMSS] Fill out in particular the x86-specific case for PAE.
[NTOS:MM] Some cleanup in the NtCreatePagingFile() code, namely:
- Clarify some comments;
- Validate the lower and upper bounds of the Minimum and Maximum sizes
(based on Windows behaviour as explained by Geoff + manual tests).
- Open the pagefile in case-insensitive;
- Simplify the loop that finds an existing matching pagefile;
- Simplify some failure exit paths;
- Add a "Missing validation steps TODO" comment block explaining the
existing code-hole.
2022-11-02 23:12:09 +00:00
|
|
|
|
/* Ensure the corresponding slot is empty yet */
|
2018-08-11 21:34:08 +00:00
|
|
|
|
ASSERT(MmPagingFile[MmNumberOfPagingFiles] == NULL);
|
2018-08-11 21:19:58 +00:00
|
|
|
|
MmPagingFile[MmNumberOfPagingFiles] = PagingFile;
|
2018-08-11 21:34:08 +00:00
|
|
|
|
MmNumberOfPagingFiles++;
|
2018-08-16 12:04:27 +00:00
|
|
|
|
MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreeSpace;
|
2018-08-16 10:39:24 +00:00
|
|
|
|
KeReleaseGuardedMutex(&MmPageFileCreationLock);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
|
|
|
|
MmSwapSpaceMessage = FALSE;
|
|
|
|
|
|
2018-09-18 19:42:01 +00:00
|
|
|
|
if (!MmSystemPageFileLocated && BooleanFlagOn(FileObject->DeviceObject->Flags, DO_SYSTEM_BOOT_PARTITION))
|
|
|
|
|
{
|
|
|
|
|
MmSystemPageFileLocated = IoInitializeCrashDump(FileHandle);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-13 06:29:17 +00:00
|
|
|
|
return STATUS_SUCCESS;
|
1999-12-10 17:04:37 +00:00
|
|
|
|
}
|
2000-03-26 19:38:32 +00:00
|
|
|
|
|
|
|
|
|
/* EOF */
|