1c2c66affSColin Finck /* 2c2c66affSColin Finck * ReactOS kernel 3c2c66affSColin Finck * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team 4c2c66affSColin Finck * 5c2c66affSColin Finck * This program is free software; you can redistribute it and/or modify 6c2c66affSColin Finck * it under the terms of the GNU General Public License as published by 7c2c66affSColin Finck * the Free Software Foundation; either version 2 of the License, or 8c2c66affSColin Finck * (at your option) any later version. 9c2c66affSColin Finck * 10c2c66affSColin Finck * This program is distributed in the hope that it will be useful, 11c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 12c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13c2c66affSColin Finck * GNU General Public License for more details. 14c2c66affSColin Finck * 15c2c66affSColin Finck * You should have received a copy of the GNU General Public License along 16c2c66affSColin Finck * with this program; if not, write to the Free Software Foundation, Inc., 17c2c66affSColin Finck * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18c2c66affSColin Finck */ 19c2c66affSColin Finck /* 20c2c66affSColin Finck * PROJECT: ReactOS kernel 21c2c66affSColin Finck * FILE: ntoskrnl/mm/pagefile.c 22c2c66affSColin Finck * PURPOSE: Paging file functions 23c2c66affSColin Finck * PROGRAMMER: David Welch (welch@mcmail.com) 2402b0ca08SPierre Schweitzer * Pierre Schweitzer 25c2c66affSColin Finck * UPDATE HISTORY: 26c2c66affSColin Finck * Created 22/05/98 27c2c66affSColin Finck */ 28c2c66affSColin Finck 29c2c66affSColin Finck /* INCLUDES *****************************************************************/ 30c2c66affSColin Finck 31c2c66affSColin Finck #include <ntoskrnl.h> 32c2c66affSColin Finck #define NDEBUG 33c2c66affSColin Finck #include <debug.h> 34c2c66affSColin Finck 35c2c66affSColin Finck #if defined (ALLOC_PRAGMA) 36c2c66affSColin Finck #pragma alloc_text(INIT, MmInitPagingFile) 37c2c66affSColin Finck #endif 38c2c66affSColin Finck 39c2c66affSColin Finck /* GLOBALS *******************************************************************/ 40c2c66affSColin Finck 41c2c66affSColin Finck #define PAIRS_PER_RUN (1024) 42c2c66affSColin Finck 43c2c66affSColin Finck /* List of paging files, both used and free */ 443814a822SPierre Schweitzer PMMPAGING_FILE MmPagingFile[MAX_PAGING_FILES]; 45c2c66affSColin Finck 46c2c66affSColin Finck /* Lock for examining the list of paging files */ 47315867d4SPierre Schweitzer KGUARDED_MUTEX MmPageFileCreationLock; 48c2c66affSColin Finck 49c2c66affSColin Finck /* Number of paging files */ 50c2c66affSColin Finck ULONG MmNumberOfPagingFiles; 51c2c66affSColin Finck 52c2c66affSColin Finck /* Number of pages that are available for swapping */ 53c2c66affSColin Finck PFN_COUNT MiFreeSwapPages; 54c2c66affSColin Finck 55c2c66affSColin Finck /* Number of pages that have been allocated for swapping */ 56c2c66affSColin Finck PFN_COUNT MiUsedSwapPages; 57c2c66affSColin Finck 58c2c66affSColin Finck BOOLEAN MmZeroPageFile; 59c2c66affSColin Finck 60c2c66affSColin Finck /* 61c2c66affSColin Finck * Number of pages that have been reserved for swapping but not yet allocated 62c2c66affSColin Finck */ 63c2c66affSColin Finck static PFN_COUNT MiReservedSwapPages; 64c2c66affSColin Finck 65c2c66affSColin Finck /* 66c2c66affSColin Finck * Ratio between reserved and available swap pages, e.g. setting this to five 67c2c66affSColin Finck * forces one swap page to be available for every five swap pages that are 68c2c66affSColin Finck * reserved. Setting this to zero turns off commit checking altogether. 69c2c66affSColin Finck */ 70c2c66affSColin Finck #define MM_PAGEFILE_COMMIT_RATIO (1) 71c2c66affSColin Finck 72c2c66affSColin Finck /* 73c2c66affSColin Finck * Number of pages that can be used for potentially swapable memory without 74c2c66affSColin Finck * pagefile space being reserved. The intention is that this allows smss 75c2c66affSColin Finck * to start up and create page files while ordinarily having a commit 76c2c66affSColin Finck * ratio of one. 77c2c66affSColin Finck */ 78c2c66affSColin Finck #define MM_PAGEFILE_COMMIT_GRACE (256) 79c2c66affSColin Finck 80c2c66affSColin Finck /* 81c2c66affSColin Finck * Translate between a swap entry and a file and offset pair. 82c2c66affSColin Finck */ 83c2c66affSColin Finck #define FILE_FROM_ENTRY(i) ((i) & 0x0f) 84c2c66affSColin Finck #define OFFSET_FROM_ENTRY(i) ((i) >> 11) 85c2c66affSColin Finck #define ENTRY_FROM_FILE_OFFSET(i, j) ((i) | ((j) << 11) | 0x400) 86c2c66affSColin Finck 87c2c66affSColin Finck /* Make sure there can be only 16 paging files */ 88c2c66affSColin Finck C_ASSERT(FILE_FROM_ENTRY(0xffffffff) < MAX_PAGING_FILES); 89c2c66affSColin Finck 90c2c66affSColin Finck static BOOLEAN MmSwapSpaceMessage = FALSE; 91c2c66affSColin Finck 92c2c66affSColin Finck /* FUNCTIONS *****************************************************************/ 93c2c66affSColin Finck 94c2c66affSColin Finck VOID 95c2c66affSColin Finck NTAPI 96c2c66affSColin Finck MmBuildMdlFromPages(PMDL Mdl, PPFN_NUMBER Pages) 97c2c66affSColin Finck { 98c2c66affSColin Finck memcpy(Mdl + 1, Pages, sizeof(PFN_NUMBER) * (PAGE_ROUND_UP(Mdl->ByteOffset+Mdl->ByteCount)/PAGE_SIZE)); 99c2c66affSColin Finck 100c2c66affSColin Finck /* FIXME: this flag should be set by the caller perhaps? */ 101c2c66affSColin Finck Mdl->MdlFlags |= MDL_IO_PAGE_READ; 102c2c66affSColin Finck } 103c2c66affSColin Finck 104c2c66affSColin Finck 105c2c66affSColin Finck BOOLEAN 106c2c66affSColin Finck NTAPI 107c2c66affSColin Finck MmIsFileObjectAPagingFile(PFILE_OBJECT FileObject) 108c2c66affSColin Finck { 109c2c66affSColin Finck ULONG i; 110c2c66affSColin Finck 111c2c66affSColin Finck /* Loop through all the paging files */ 112c2c66affSColin Finck for (i = 0; i < MmNumberOfPagingFiles; i++) 113c2c66affSColin Finck { 114c2c66affSColin Finck /* Check if this is one of them */ 115f106c297SPierre Schweitzer if (MmPagingFile[i]->FileObject == FileObject) return TRUE; 116c2c66affSColin Finck } 117c2c66affSColin Finck 118c2c66affSColin Finck /* Nothing found */ 119c2c66affSColin Finck return FALSE; 120c2c66affSColin Finck } 121c2c66affSColin Finck 122c2c66affSColin Finck VOID 123c2c66affSColin Finck NTAPI 124c2c66affSColin Finck MmShowOutOfSpaceMessagePagingFile(VOID) 125c2c66affSColin Finck { 126c2c66affSColin Finck if (!MmSwapSpaceMessage) 127c2c66affSColin Finck { 128c2c66affSColin Finck DPRINT1("MM: Out of swap space.\n"); 129c2c66affSColin Finck MmSwapSpaceMessage = TRUE; 130c2c66affSColin Finck } 131c2c66affSColin Finck } 132c2c66affSColin Finck 133c2c66affSColin Finck NTSTATUS 134c2c66affSColin Finck NTAPI 135c2c66affSColin Finck MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page) 136c2c66affSColin Finck { 137c2c66affSColin Finck ULONG i; 138c2c66affSColin Finck ULONG_PTR offset; 139c2c66affSColin Finck LARGE_INTEGER file_offset; 140c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 141c2c66affSColin Finck NTSTATUS Status; 142c2c66affSColin Finck KEVENT Event; 143c2c66affSColin Finck UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)]; 144c2c66affSColin Finck PMDL Mdl = (PMDL)MdlBase; 145c2c66affSColin Finck 146c2c66affSColin Finck DPRINT("MmWriteToSwapPage\n"); 147c2c66affSColin Finck 148c2c66affSColin Finck if (SwapEntry == 0) 149c2c66affSColin Finck { 150c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 151c2c66affSColin Finck return(STATUS_UNSUCCESSFUL); 152c2c66affSColin Finck } 153c2c66affSColin Finck 154c2c66affSColin Finck i = FILE_FROM_ENTRY(SwapEntry); 155c2c66affSColin Finck offset = OFFSET_FROM_ENTRY(SwapEntry) - 1; 156c2c66affSColin Finck 157f106c297SPierre Schweitzer if (MmPagingFile[i]->FileObject == NULL || 158f106c297SPierre Schweitzer MmPagingFile[i]->FileObject->DeviceObject == NULL) 159c2c66affSColin Finck { 160c2c66affSColin Finck DPRINT1("Bad paging file 0x%.8X\n", SwapEntry); 161c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 162c2c66affSColin Finck } 163c2c66affSColin Finck 164c2c66affSColin Finck MmInitializeMdl(Mdl, NULL, PAGE_SIZE); 165c2c66affSColin Finck MmBuildMdlFromPages(Mdl, &Page); 166c2c66affSColin Finck Mdl->MdlFlags |= MDL_PAGES_LOCKED; 167c2c66affSColin Finck 168c2c66affSColin Finck file_offset.QuadPart = offset * PAGE_SIZE; 169c2c66affSColin Finck 170c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE); 171f106c297SPierre Schweitzer Status = IoSynchronousPageWrite(MmPagingFile[i]->FileObject, 172c2c66affSColin Finck Mdl, 173c2c66affSColin Finck &file_offset, 174c2c66affSColin Finck &Event, 175c2c66affSColin Finck &Iosb); 176c2c66affSColin Finck if (Status == STATUS_PENDING) 177c2c66affSColin Finck { 178c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 179c2c66affSColin Finck Status = Iosb.Status; 180c2c66affSColin Finck } 181c2c66affSColin Finck 182c2c66affSColin Finck if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) 183c2c66affSColin Finck { 184c2c66affSColin Finck MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); 185c2c66affSColin Finck } 186c2c66affSColin Finck return(Status); 187c2c66affSColin Finck } 188c2c66affSColin Finck 189c2c66affSColin Finck 190c2c66affSColin Finck NTSTATUS 191c2c66affSColin Finck NTAPI 192c2c66affSColin Finck MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page) 193c2c66affSColin Finck { 194c2c66affSColin Finck return MiReadPageFile(Page, FILE_FROM_ENTRY(SwapEntry), OFFSET_FROM_ENTRY(SwapEntry) - 1); 195c2c66affSColin Finck } 196c2c66affSColin Finck 197c2c66affSColin Finck NTSTATUS 198c2c66affSColin Finck NTAPI 199c2c66affSColin Finck MiReadPageFile( 200c2c66affSColin Finck _In_ PFN_NUMBER Page, 201c2c66affSColin Finck _In_ ULONG PageFileIndex, 202c2c66affSColin Finck _In_ ULONG_PTR PageFileOffset) 203c2c66affSColin Finck { 204c2c66affSColin Finck LARGE_INTEGER file_offset; 205c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 206c2c66affSColin Finck NTSTATUS Status; 207c2c66affSColin Finck KEVENT Event; 208c2c66affSColin Finck UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)]; 209c2c66affSColin Finck PMDL Mdl = (PMDL)MdlBase; 21002b0ca08SPierre Schweitzer PMMPAGING_FILE PagingFile; 211c2c66affSColin Finck 212c2c66affSColin Finck DPRINT("MiReadSwapFile\n"); 213c2c66affSColin Finck 214c2c66affSColin Finck if (PageFileOffset == 0) 215c2c66affSColin Finck { 216c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 217c2c66affSColin Finck return(STATUS_UNSUCCESSFUL); 218c2c66affSColin Finck } 219c2c66affSColin Finck 220c2c66affSColin Finck ASSERT(PageFileIndex < MAX_PAGING_FILES); 221c2c66affSColin Finck 222f106c297SPierre Schweitzer PagingFile = MmPagingFile[PageFileIndex]; 223c2c66affSColin Finck 224c2c66affSColin Finck if (PagingFile->FileObject == NULL || PagingFile->FileObject->DeviceObject == NULL) 225c2c66affSColin Finck { 226c2c66affSColin Finck DPRINT1("Bad paging file %u\n", PageFileIndex); 227c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 228c2c66affSColin Finck } 229c2c66affSColin Finck 230c2c66affSColin Finck MmInitializeMdl(Mdl, NULL, PAGE_SIZE); 231c2c66affSColin Finck MmBuildMdlFromPages(Mdl, &Page); 232c2c66affSColin Finck Mdl->MdlFlags |= MDL_PAGES_LOCKED; 233c2c66affSColin Finck 234c2c66affSColin Finck file_offset.QuadPart = PageFileOffset * PAGE_SIZE; 235c2c66affSColin Finck 236c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE); 237c2c66affSColin Finck Status = IoPageRead(PagingFile->FileObject, 238c2c66affSColin Finck Mdl, 239c2c66affSColin Finck &file_offset, 240c2c66affSColin Finck &Event, 241c2c66affSColin Finck &Iosb); 242c2c66affSColin Finck if (Status == STATUS_PENDING) 243c2c66affSColin Finck { 244c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 245c2c66affSColin Finck Status = Iosb.Status; 246c2c66affSColin Finck } 247c2c66affSColin Finck if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) 248c2c66affSColin Finck { 249c2c66affSColin Finck MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); 250c2c66affSColin Finck } 251c2c66affSColin Finck return(Status); 252c2c66affSColin Finck } 253c2c66affSColin Finck 254c2c66affSColin Finck VOID 255c2c66affSColin Finck INIT_FUNCTION 256c2c66affSColin Finck NTAPI 257c2c66affSColin Finck MmInitPagingFile(VOID) 258c2c66affSColin Finck { 259c2c66affSColin Finck ULONG i; 260c2c66affSColin Finck 261315867d4SPierre Schweitzer KeInitializeGuardedMutex(&MmPageFileCreationLock); 262c2c66affSColin Finck 263c2c66affSColin Finck MiFreeSwapPages = 0; 264c2c66affSColin Finck MiUsedSwapPages = 0; 265c2c66affSColin Finck MiReservedSwapPages = 0; 266c2c66affSColin Finck 267c2c66affSColin Finck for (i = 0; i < MAX_PAGING_FILES; i++) 268c2c66affSColin Finck { 269f106c297SPierre Schweitzer MmPagingFile[i] = NULL; 270c2c66affSColin Finck } 271c2c66affSColin Finck MmNumberOfPagingFiles = 0; 272c2c66affSColin Finck } 273c2c66affSColin Finck 274c2c66affSColin Finck VOID 275c2c66affSColin Finck NTAPI 276c2c66affSColin Finck MmFreeSwapPage(SWAPENTRY Entry) 277c2c66affSColin Finck { 278c2c66affSColin Finck ULONG i; 279c2c66affSColin Finck ULONG_PTR off; 28002b0ca08SPierre Schweitzer PMMPAGING_FILE PagingFile; 281c2c66affSColin Finck 282c2c66affSColin Finck i = FILE_FROM_ENTRY(Entry); 283c2c66affSColin Finck off = OFFSET_FROM_ENTRY(Entry) - 1; 284c2c66affSColin Finck 285315867d4SPierre Schweitzer KeAcquireGuardedMutex(&MmPageFileCreationLock); 286f106c297SPierre Schweitzer 287f106c297SPierre Schweitzer PagingFile = MmPagingFile[i]; 288f106c297SPierre Schweitzer if (PagingFile == NULL) 289c2c66affSColin Finck { 290c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 291c2c66affSColin Finck } 292c2c66affSColin Finck 293f106c297SPierre Schweitzer RtlClearBit(PagingFile->AllocMap, off >> 5); 294c2c66affSColin Finck 295f106c297SPierre Schweitzer PagingFile->FreePages++; 296f106c297SPierre Schweitzer PagingFile->UsedPages--; 297c2c66affSColin Finck 298c2c66affSColin Finck MiFreeSwapPages++; 299c2c66affSColin Finck MiUsedSwapPages--; 300c2c66affSColin Finck 301315867d4SPierre Schweitzer KeReleaseGuardedMutex(&MmPageFileCreationLock); 302c2c66affSColin Finck } 303c2c66affSColin Finck 304c2c66affSColin Finck SWAPENTRY 305c2c66affSColin Finck NTAPI 306c2c66affSColin Finck MmAllocSwapPage(VOID) 307c2c66affSColin Finck { 308c2c66affSColin Finck ULONG i; 309c2c66affSColin Finck ULONG off; 310c2c66affSColin Finck SWAPENTRY entry; 311c2c66affSColin Finck 312315867d4SPierre Schweitzer KeAcquireGuardedMutex(&MmPageFileCreationLock); 313c2c66affSColin Finck 314c2c66affSColin Finck if (MiFreeSwapPages == 0) 315c2c66affSColin Finck { 316315867d4SPierre Schweitzer KeReleaseGuardedMutex(&MmPageFileCreationLock); 317c2c66affSColin Finck return(0); 318c2c66affSColin Finck } 319c2c66affSColin Finck 320c2c66affSColin Finck for (i = 0; i < MAX_PAGING_FILES; i++) 321c2c66affSColin Finck { 322f106c297SPierre Schweitzer if (MmPagingFile[i] != NULL && 323f106c297SPierre Schweitzer MmPagingFile[i]->FreePages >= 1) 324c2c66affSColin Finck { 325891a6eeeSPierre Schweitzer off = RtlFindClearBitsAndSet(MmPagingFile[i]->AllocMap, 1, 0); 326c2c66affSColin Finck if (off == 0xFFFFFFFF) 327c2c66affSColin Finck { 328c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 329315867d4SPierre Schweitzer KeReleaseGuardedMutex(&MmPageFileCreationLock); 330c2c66affSColin Finck return(STATUS_UNSUCCESSFUL); 331c2c66affSColin Finck } 332c2c66affSColin Finck MiUsedSwapPages++; 333c2c66affSColin Finck MiFreeSwapPages--; 334315867d4SPierre Schweitzer KeReleaseGuardedMutex(&MmPageFileCreationLock); 335c2c66affSColin Finck 336c2c66affSColin Finck entry = ENTRY_FROM_FILE_OFFSET(i, off + 1); 337c2c66affSColin Finck return(entry); 338c2c66affSColin Finck } 339c2c66affSColin Finck } 340c2c66affSColin Finck 341315867d4SPierre Schweitzer KeReleaseGuardedMutex(&MmPageFileCreationLock); 342c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 343c2c66affSColin Finck return(0); 344c2c66affSColin Finck } 345c2c66affSColin Finck 346c2c66affSColin Finck NTSTATUS NTAPI 347c2c66affSColin Finck NtCreatePagingFile(IN PUNICODE_STRING FileName, 348bfc6a795SPierre Schweitzer IN PLARGE_INTEGER MinimumSize, 349c2c66affSColin Finck IN PLARGE_INTEGER MaximumSize, 350c2c66affSColin Finck IN ULONG Reserved) 351c2c66affSColin Finck { 352c2c66affSColin Finck NTSTATUS Status; 353c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 354c2c66affSColin Finck HANDLE FileHandle; 355c2c66affSColin Finck IO_STATUS_BLOCK IoStatus; 356c2c66affSColin Finck PFILE_OBJECT FileObject; 35702b0ca08SPierre Schweitzer PMMPAGING_FILE PagingFile; 358c2c66affSColin Finck ULONG AllocMapSize; 359c2c66affSColin Finck ULONG Count; 360c2c66affSColin Finck KPROCESSOR_MODE PreviousMode; 36134e8f451SPierre Schweitzer UNICODE_STRING PageFileName; 362bfc6a795SPierre Schweitzer LARGE_INTEGER SafeMinimumSize, SafeMaximumSize, AllocationSize; 36336c20dc5SPierre Schweitzer FILE_FS_DEVICE_INFORMATION FsDeviceInfo; 36428b4b419SPierre Schweitzer SECURITY_DESCRIPTOR SecurityDescriptor; 36528b4b419SPierre Schweitzer PACL Dacl; 36634e8f451SPierre Schweitzer PWSTR Buffer; 367c2c66affSColin Finck 368bfc6a795SPierre Schweitzer DPRINT("NtCreatePagingFile(FileName %wZ, MinimumSize %I64d)\n", 369bfc6a795SPierre Schweitzer FileName, MinimumSize->QuadPart); 370c2c66affSColin Finck 371315867d4SPierre Schweitzer PAGED_CODE(); 372315867d4SPierre Schweitzer 373c2c66affSColin Finck if (MmNumberOfPagingFiles >= MAX_PAGING_FILES) 374c2c66affSColin Finck { 3750ad4ef60SPierre Schweitzer return STATUS_TOO_MANY_PAGING_FILES; 376c2c66affSColin Finck } 377c2c66affSColin Finck 378c2c66affSColin Finck PreviousMode = ExGetPreviousMode(); 379c2c66affSColin Finck 380c2c66affSColin Finck if (PreviousMode != KernelMode) 381c2c66affSColin Finck { 3820ad4ef60SPierre Schweitzer if (SeSinglePrivilegeCheck(SeCreatePagefilePrivilege, PreviousMode) != TRUE) 3830ad4ef60SPierre Schweitzer { 3840ad4ef60SPierre Schweitzer return STATUS_PRIVILEGE_NOT_HELD; 3850ad4ef60SPierre Schweitzer } 3860ad4ef60SPierre Schweitzer 387c2c66affSColin Finck _SEH2_TRY 388c2c66affSColin Finck { 389bfc6a795SPierre Schweitzer SafeMinimumSize = ProbeForReadLargeInteger(MinimumSize); 390c2c66affSColin Finck SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize); 39134e8f451SPierre Schweitzer 39234e8f451SPierre Schweitzer PageFileName.Length = FileName->Length; 39334e8f451SPierre Schweitzer PageFileName.MaximumLength = FileName->MaximumLength; 39434e8f451SPierre Schweitzer PageFileName.Buffer = FileName->Buffer; 395c2c66affSColin Finck } 396c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 397c2c66affSColin Finck { 398c2c66affSColin Finck /* Return the exception code */ 399c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 400c2c66affSColin Finck } 401c2c66affSColin Finck _SEH2_END; 402c2c66affSColin Finck } 403c2c66affSColin Finck else 404c2c66affSColin Finck { 405bfc6a795SPierre Schweitzer SafeMinimumSize = *MinimumSize; 406c2c66affSColin Finck SafeMaximumSize = *MaximumSize; 40734e8f451SPierre Schweitzer 40834e8f451SPierre Schweitzer PageFileName.Length = FileName->Length; 40934e8f451SPierre Schweitzer PageFileName.MaximumLength = FileName->MaximumLength; 41034e8f451SPierre Schweitzer PageFileName.Buffer = FileName->Buffer; 411c2c66affSColin Finck } 412c2c66affSColin Finck 413c2c66affSColin Finck /* Pagefiles can't be larger than 4GB and ofcourse the minimum should be 414c2c66affSColin Finck smaller than the maximum */ 415bfc6a795SPierre Schweitzer if (0 != SafeMinimumSize.u.HighPart) 416c2c66affSColin Finck { 417c2c66affSColin Finck return STATUS_INVALID_PARAMETER_2; 418c2c66affSColin Finck } 419c2c66affSColin Finck if (0 != SafeMaximumSize.u.HighPart) 420c2c66affSColin Finck { 421c2c66affSColin Finck return STATUS_INVALID_PARAMETER_3; 422c2c66affSColin Finck } 423bfc6a795SPierre Schweitzer if (SafeMaximumSize.u.LowPart < SafeMinimumSize.u.LowPart) 424c2c66affSColin Finck { 425c2c66affSColin Finck return STATUS_INVALID_PARAMETER_MIX; 426c2c66affSColin Finck } 427c2c66affSColin Finck 42834e8f451SPierre Schweitzer /* Validate name length */ 42934e8f451SPierre Schweitzer if (PageFileName.Length > 128 * sizeof(WCHAR)) 430c2c66affSColin Finck { 43134e8f451SPierre Schweitzer return STATUS_OBJECT_NAME_INVALID; 432c2c66affSColin Finck } 433c2c66affSColin Finck 43434e8f451SPierre Schweitzer /* We won't care about any potential UNICODE_NULL */ 43534e8f451SPierre Schweitzer PageFileName.MaximumLength = PageFileName.Length; 43634e8f451SPierre Schweitzer /* Allocate a buffer to keep name copy */ 43734e8f451SPierre Schweitzer Buffer = ExAllocatePoolWithTag(PagedPool, PageFileName.Length, TAG_MM); 43834e8f451SPierre Schweitzer if (Buffer == NULL) 43934e8f451SPierre Schweitzer { 44034e8f451SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES; 44134e8f451SPierre Schweitzer } 44234e8f451SPierre Schweitzer 44334e8f451SPierre Schweitzer /* Copy name */ 44434e8f451SPierre Schweitzer if (PreviousMode != KernelMode) 44534e8f451SPierre Schweitzer { 44634e8f451SPierre Schweitzer _SEH2_TRY 44734e8f451SPierre Schweitzer { 44834e8f451SPierre Schweitzer if (PageFileName.Length != 0) 44934e8f451SPierre Schweitzer { 45034e8f451SPierre Schweitzer ProbeForRead(PageFileName.Buffer, PageFileName.Length, sizeof(WCHAR)); 45134e8f451SPierre Schweitzer } 45234e8f451SPierre Schweitzer 45334e8f451SPierre Schweitzer RtlCopyMemory(Buffer, PageFileName.Buffer, PageFileName.Length); 45434e8f451SPierre Schweitzer } 45534e8f451SPierre Schweitzer _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 45634e8f451SPierre Schweitzer { 45734e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 45834e8f451SPierre Schweitzer 45934e8f451SPierre Schweitzer /* Return the exception code */ 46034e8f451SPierre Schweitzer _SEH2_YIELD(return _SEH2_GetExceptionCode()); 46134e8f451SPierre Schweitzer } 46234e8f451SPierre Schweitzer _SEH2_END; 46334e8f451SPierre Schweitzer } 46434e8f451SPierre Schweitzer else 46534e8f451SPierre Schweitzer { 46634e8f451SPierre Schweitzer RtlCopyMemory(Buffer, PageFileName.Buffer, PageFileName.Length); 46734e8f451SPierre Schweitzer } 46834e8f451SPierre Schweitzer 46934e8f451SPierre Schweitzer /* Erase caller's buffer with ours */ 47034e8f451SPierre Schweitzer PageFileName.Buffer = Buffer; 47134e8f451SPierre Schweitzer 47228b4b419SPierre Schweitzer /* Create the security descriptor for the page file */ 47328b4b419SPierre Schweitzer Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); 47428b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 47528b4b419SPierre Schweitzer { 47634e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 47728b4b419SPierre Schweitzer return Status; 47828b4b419SPierre Schweitzer } 47928b4b419SPierre Schweitzer 48028b4b419SPierre Schweitzer /* Create the DACL: we will only allow two SIDs */ 48128b4b419SPierre Schweitzer Count = sizeof(ACL) + (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) + 48228b4b419SPierre Schweitzer (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid)); 48328b4b419SPierre Schweitzer Dacl = ExAllocatePoolWithTag(PagedPool, Count, 'lcaD'); 48428b4b419SPierre Schweitzer if (Dacl == NULL) 48528b4b419SPierre Schweitzer { 48634e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 48728b4b419SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES; 48828b4b419SPierre Schweitzer } 48928b4b419SPierre Schweitzer 49028b4b419SPierre Schweitzer /* Initialize the DACL */ 49128b4b419SPierre Schweitzer Status = RtlCreateAcl(Dacl, Count, ACL_REVISION); 49228b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 49328b4b419SPierre Schweitzer { 49428b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 49534e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 49628b4b419SPierre Schweitzer return Status; 49728b4b419SPierre Schweitzer } 49828b4b419SPierre Schweitzer 49928b4b419SPierre Schweitzer /* Grant full access to admins */ 50028b4b419SPierre Schweitzer Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, FILE_ALL_ACCESS, SeAliasAdminsSid); 50128b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 50228b4b419SPierre Schweitzer { 50328b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 50434e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 50528b4b419SPierre Schweitzer return Status; 50628b4b419SPierre Schweitzer } 50728b4b419SPierre Schweitzer 50828b4b419SPierre Schweitzer /* Grant full access to SYSTEM */ 50928b4b419SPierre Schweitzer Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, FILE_ALL_ACCESS, SeLocalSystemSid); 51028b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 51128b4b419SPierre Schweitzer { 51228b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 51334e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 51428b4b419SPierre Schweitzer return Status; 51528b4b419SPierre Schweitzer } 51628b4b419SPierre Schweitzer 51728b4b419SPierre Schweitzer /* Attach the DACL to the security descriptor */ 51828b4b419SPierre Schweitzer Status = RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl, FALSE); 51928b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 52028b4b419SPierre Schweitzer { 52128b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 52234e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 52328b4b419SPierre Schweitzer return Status; 52428b4b419SPierre Schweitzer } 52528b4b419SPierre Schweitzer 526c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 52734e8f451SPierre Schweitzer &PageFileName, 528c2c66affSColin Finck OBJ_KERNEL_HANDLE, 529c2c66affSColin Finck NULL, 53028b4b419SPierre Schweitzer &SecurityDescriptor); 531c2c66affSColin Finck 5322969c28aSPierre Schweitzer /* Make sure we can at least store a complete page: 5332969c28aSPierre Schweitzer * If we have 2048 BytesPerAllocationUnit (FAT16 < 128MB) there is 5342969c28aSPierre Schweitzer * a problem if the paging file is fragmented. Suppose the first cluster 5352969c28aSPierre Schweitzer * of the paging file is cluster 3042 but cluster 3043 is NOT part of the 5362969c28aSPierre Schweitzer * paging file but of another file. We can't write a complete page (4096 5372969c28aSPierre Schweitzer * bytes) to the physical location of cluster 3042 then. */ 538bfc6a795SPierre Schweitzer AllocationSize.QuadPart = SafeMinimumSize.QuadPart + PAGE_SIZE; 5392969c28aSPierre Schweitzer 5402969c28aSPierre Schweitzer /* First, attempt to replace the page file, if existing */ 541c2c66affSColin Finck Status = IoCreateFile(&FileHandle, 5422969c28aSPierre Schweitzer SYNCHRONIZE | WRITE_DAC | FILE_READ_DATA | FILE_WRITE_DATA, 543c2c66affSColin Finck &ObjectAttributes, 544c2c66affSColin Finck &IoStatus, 5452969c28aSPierre Schweitzer &AllocationSize, 5462969c28aSPierre Schweitzer FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 5472969c28aSPierre Schweitzer FILE_SHARE_WRITE, 5482969c28aSPierre Schweitzer FILE_SUPERSEDE, 5492969c28aSPierre Schweitzer FILE_DELETE_ON_CLOSE | FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING, 550c2c66affSColin Finck NULL, 551c2c66affSColin Finck 0, 552c2c66affSColin Finck CreateFileTypeNone, 553c2c66affSColin Finck NULL, 554c2c66affSColin Finck SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING); 5552969c28aSPierre Schweitzer /* If we failed, relax a bit constraints, someone may be already holding the 5562969c28aSPierre Schweitzer * the file, so share write, don't attempt to replace and don't delete on close 5572969c28aSPierre Schweitzer * (basically, don't do anything conflicting) 5585bd938bdSPierre Schweitzer * This can happen if the caller attempts to extend a page file. 5592969c28aSPierre Schweitzer */ 5602969c28aSPierre Schweitzer if (!NT_SUCCESS(Status)) 5612969c28aSPierre Schweitzer { 5625bd938bdSPierre Schweitzer ULONG i; 5635bd938bdSPierre Schweitzer 5642969c28aSPierre Schweitzer Status = IoCreateFile(&FileHandle, 5652969c28aSPierre Schweitzer SYNCHRONIZE | FILE_WRITE_DATA, 5662969c28aSPierre Schweitzer &ObjectAttributes, 5672969c28aSPierre Schweitzer &IoStatus, 5682969c28aSPierre Schweitzer &AllocationSize, 5692969c28aSPierre Schweitzer FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 5702969c28aSPierre Schweitzer FILE_SHARE_WRITE | FILE_SHARE_READ, 5712969c28aSPierre Schweitzer FILE_OPEN, 5722969c28aSPierre Schweitzer FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING, 5732969c28aSPierre Schweitzer NULL, 5742969c28aSPierre Schweitzer 0, 5752969c28aSPierre Schweitzer CreateFileTypeNone, 5762969c28aSPierre Schweitzer NULL, 5772969c28aSPierre Schweitzer SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING); 5785bd938bdSPierre Schweitzer if (!NT_SUCCESS(Status)) 5795bd938bdSPierre Schweitzer { 5805bd938bdSPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 5815bd938bdSPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 5825bd938bdSPierre Schweitzer return Status; 5835bd938bdSPierre Schweitzer } 5845bd938bdSPierre Schweitzer 5855bd938bdSPierre Schweitzer /* We opened it! Check we are that "someone" ;-) 5865bd938bdSPierre Schweitzer * First, get the opened file object. 5875bd938bdSPierre Schweitzer */ 5885bd938bdSPierre Schweitzer Status = ObReferenceObjectByHandle(FileHandle, 5895bd938bdSPierre Schweitzer FILE_READ_DATA | FILE_WRITE_DATA, 5905bd938bdSPierre Schweitzer IoFileObjectType, 5915bd938bdSPierre Schweitzer KernelMode, 5925bd938bdSPierre Schweitzer (PVOID*)&FileObject, 5935bd938bdSPierre Schweitzer NULL); 5945bd938bdSPierre Schweitzer if (!NT_SUCCESS(Status)) 5955bd938bdSPierre Schweitzer { 5965bd938bdSPierre Schweitzer ZwClose(FileHandle); 5975bd938bdSPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 5985bd938bdSPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 5995bd938bdSPierre Schweitzer return Status; 6005bd938bdSPierre Schweitzer } 6015bd938bdSPierre Schweitzer 6025bd938bdSPierre Schweitzer /* Find if it matches a previous page file */ 6035bd938bdSPierre Schweitzer PagingFile = NULL; 604315867d4SPierre Schweitzer 605315867d4SPierre Schweitzer /* FIXME: should be calling unsafe instead, 606315867d4SPierre Schweitzer * we should already be in a guarded region 607315867d4SPierre Schweitzer */ 608315867d4SPierre Schweitzer KeAcquireGuardedMutex(&MmPageFileCreationLock); 6095bd938bdSPierre Schweitzer if (MmNumberOfPagingFiles > 0) 6105bd938bdSPierre Schweitzer { 6115bd938bdSPierre Schweitzer i = 0; 6125bd938bdSPierre Schweitzer 6135bd938bdSPierre Schweitzer while (MmPagingFile[i]->FileObject->SectionObjectPointer != FileObject->SectionObjectPointer) 6145bd938bdSPierre Schweitzer { 6155bd938bdSPierre Schweitzer ++i; 6165bd938bdSPierre Schweitzer if (i >= MmNumberOfPagingFiles) 6175bd938bdSPierre Schweitzer { 6185bd938bdSPierre Schweitzer break; 6195bd938bdSPierre Schweitzer } 6205bd938bdSPierre Schweitzer } 6215bd938bdSPierre Schweitzer 6225bd938bdSPierre Schweitzer /* This is the matching page file */ 6235bd938bdSPierre Schweitzer PagingFile = MmPagingFile[i]; 6245bd938bdSPierre Schweitzer } 6255bd938bdSPierre Schweitzer 6265bd938bdSPierre Schweitzer /* If we didn't find the page file, fail */ 6275bd938bdSPierre Schweitzer if (PagingFile == NULL) 6285bd938bdSPierre Schweitzer { 629315867d4SPierre Schweitzer KeReleaseGuardedMutex(&MmPageFileCreationLock); 6305bd938bdSPierre Schweitzer ObDereferenceObject(FileObject); 6315bd938bdSPierre Schweitzer ZwClose(FileHandle); 6325bd938bdSPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 6335bd938bdSPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 6345bd938bdSPierre Schweitzer return STATUS_NOT_FOUND; 6355bd938bdSPierre Schweitzer } 6365bd938bdSPierre Schweitzer 6372fe4e713SPierre Schweitzer /* Don't allow page file shrinking */ 638*e392bdf9SPierre Schweitzer if (PagingFile->MinimumSize > (SafeMinimumSize.QuadPart >> PAGE_SHIFT)) 6392fe4e713SPierre Schweitzer { 6402fe4e713SPierre Schweitzer KeReleaseGuardedMutex(&MmPageFileCreationLock); 6412fe4e713SPierre Schweitzer ObDereferenceObject(FileObject); 6422fe4e713SPierre Schweitzer ZwClose(FileHandle); 6432fe4e713SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 6442fe4e713SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 6452fe4e713SPierre Schweitzer return STATUS_INVALID_PARAMETER_2; 6462fe4e713SPierre Schweitzer } 6472fe4e713SPierre Schweitzer 648*e392bdf9SPierre Schweitzer if ((SafeMaximumSize.QuadPart >> PAGE_SHIFT) < PagingFile->MaximumSize) 6492fe4e713SPierre Schweitzer { 6502fe4e713SPierre Schweitzer KeReleaseGuardedMutex(&MmPageFileCreationLock); 6512fe4e713SPierre Schweitzer ObDereferenceObject(FileObject); 6522fe4e713SPierre Schweitzer ZwClose(FileHandle); 6532fe4e713SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 6542fe4e713SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 6552fe4e713SPierre Schweitzer return STATUS_INVALID_PARAMETER_3; 6562fe4e713SPierre Schweitzer } 6572fe4e713SPierre Schweitzer 6585bd938bdSPierre Schweitzer /* FIXME: implement parameters checking and page file extension */ 6595bd938bdSPierre Schweitzer UNIMPLEMENTED; 6605bd938bdSPierre Schweitzer 661315867d4SPierre Schweitzer KeReleaseGuardedMutex(&MmPageFileCreationLock); 6625bd938bdSPierre Schweitzer ObDereferenceObject(FileObject); 6635bd938bdSPierre Schweitzer ZwClose(FileHandle); 6645bd938bdSPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 6655bd938bdSPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 6665bd938bdSPierre Schweitzer return STATUS_NOT_IMPLEMENTED; 6672969c28aSPierre Schweitzer } 668c2c66affSColin Finck 669c2c66affSColin Finck if (!NT_SUCCESS(Status)) 670c2c66affSColin Finck { 6712969c28aSPierre Schweitzer DPRINT1("Failed creating page file: %lx\n", Status); 67228b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 67334e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 67434e8f451SPierre Schweitzer return Status; 675c2c66affSColin Finck } 676c2c66affSColin Finck 67728b4b419SPierre Schweitzer /* Set the security descriptor */ 67828b4b419SPierre Schweitzer if (NT_SUCCESS(IoStatus.Status)) 67928b4b419SPierre Schweitzer { 68028b4b419SPierre Schweitzer Status = ZwSetSecurityObject(FileHandle, DACL_SECURITY_INFORMATION, &SecurityDescriptor); 68128b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 68228b4b419SPierre Schweitzer { 68328b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 68428b4b419SPierre Schweitzer ZwClose(FileHandle); 68534e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 68628b4b419SPierre Schweitzer return Status; 68728b4b419SPierre Schweitzer } 68828b4b419SPierre Schweitzer } 68928b4b419SPierre Schweitzer 69028b4b419SPierre Schweitzer /* DACL is no longer needed, free it */ 69128b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 69228b4b419SPierre Schweitzer 693bfc6a795SPierre Schweitzer /* Set its end of file to minimal size */ 694c2c66affSColin Finck Status = ZwSetInformationFile(FileHandle, 695c2c66affSColin Finck &IoStatus, 696bfc6a795SPierre Schweitzer &SafeMinimumSize, 697c2c66affSColin Finck sizeof(LARGE_INTEGER), 6982969c28aSPierre Schweitzer FileEndOfFileInformation); 6992969c28aSPierre Schweitzer if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStatus.Status)) 700c2c66affSColin Finck { 701c2c66affSColin Finck ZwClose(FileHandle); 70234e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 70334e8f451SPierre Schweitzer return Status; 704c2c66affSColin Finck } 705c2c66affSColin Finck 706c2c66affSColin Finck Status = ObReferenceObjectByHandle(FileHandle, 707c2c66affSColin Finck FILE_ALL_ACCESS, 708c2c66affSColin Finck IoFileObjectType, 709c2c66affSColin Finck KernelMode, 710c2c66affSColin Finck (PVOID*)&FileObject, 711c2c66affSColin Finck NULL); 712c2c66affSColin Finck if (!NT_SUCCESS(Status)) 713c2c66affSColin Finck { 714c2c66affSColin Finck ZwClose(FileHandle); 71534e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 71634e8f451SPierre Schweitzer return Status; 717c2c66affSColin Finck } 718c2c66affSColin Finck 71936c20dc5SPierre Schweitzer /* Deny page file creation on a floppy disk */ 72036c20dc5SPierre Schweitzer FsDeviceInfo.Characteristics = 0; 72136c20dc5SPierre Schweitzer IoQueryVolumeInformation(FileObject, FileFsDeviceInformation, sizeof(FsDeviceInfo), &FsDeviceInfo, &Count); 72236c20dc5SPierre Schweitzer if (BooleanFlagOn(FsDeviceInfo.Characteristics, FILE_FLOPPY_DISKETTE)) 72336c20dc5SPierre Schweitzer { 72436c20dc5SPierre Schweitzer ObDereferenceObject(FileObject); 72536c20dc5SPierre Schweitzer ZwClose(FileHandle); 72634e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 72736c20dc5SPierre Schweitzer return STATUS_FLOPPY_VOLUME; 72836c20dc5SPierre Schweitzer } 72936c20dc5SPierre Schweitzer 7301ea68d05SPierre Schweitzer PagingFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(*PagingFile), TAG_MM); 731c2c66affSColin Finck if (PagingFile == NULL) 732c2c66affSColin Finck { 733c2c66affSColin Finck ObDereferenceObject(FileObject); 734c2c66affSColin Finck ZwClose(FileHandle); 73534e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 7361ea68d05SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES; 737c2c66affSColin Finck } 738c2c66affSColin Finck 739c2c66affSColin Finck RtlZeroMemory(PagingFile, sizeof(*PagingFile)); 740c2c66affSColin Finck 7412969c28aSPierre Schweitzer PagingFile->FileHandle = FileHandle; 742c2c66affSColin Finck PagingFile->FileObject = FileObject; 743*e392bdf9SPierre Schweitzer PagingFile->MaximumSize = (SafeMaximumSize.QuadPart >> PAGE_SHIFT); 744*e392bdf9SPierre Schweitzer PagingFile->CurrentSize = (SafeMinimumSize.QuadPart >> PAGE_SHIFT); 745*e392bdf9SPierre Schweitzer PagingFile->MinimumSize = (SafeMinimumSize.QuadPart >> PAGE_SHIFT); 746bfc6a795SPierre Schweitzer PagingFile->FreePages = (ULONG)(SafeMinimumSize.QuadPart / PAGE_SIZE); 747c2c66affSColin Finck PagingFile->UsedPages = 0; 74834e8f451SPierre Schweitzer PagingFile->PageFileName = PageFileName; 749c2c66affSColin Finck 750f080ee13SPierre Schweitzer AllocMapSize = sizeof(RTL_BITMAP) + (((PagingFile->FreePages + 31) / 32) * sizeof(ULONG)); 751f080ee13SPierre Schweitzer PagingFile->AllocMap = ExAllocatePoolWithTag(NonPagedPool, 752f080ee13SPierre Schweitzer AllocMapSize, 753f080ee13SPierre Schweitzer TAG_MM); 754c2c66affSColin Finck if (PagingFile->AllocMap == NULL) 755c2c66affSColin Finck { 7561ea68d05SPierre Schweitzer ExFreePoolWithTag(PagingFile, TAG_MM); 757c2c66affSColin Finck ObDereferenceObject(FileObject); 758c2c66affSColin Finck ZwClose(FileHandle); 75934e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 7601ea68d05SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES; 761c2c66affSColin Finck } 762c2c66affSColin Finck 763f080ee13SPierre Schweitzer RtlInitializeBitMap(PagingFile->AllocMap, 764f080ee13SPierre Schweitzer (PULONG)(PagingFile->AllocMap + 1), 765f080ee13SPierre Schweitzer (ULONG)(PagingFile->FreePages)); 766f080ee13SPierre Schweitzer RtlClearAllBits(PagingFile->AllocMap); 767c2c66affSColin Finck 768315867d4SPierre Schweitzer /* FIXME: should be calling unsafe instead, 769315867d4SPierre Schweitzer * we should already be in a guarded region 770315867d4SPierre Schweitzer */ 771315867d4SPierre Schweitzer KeAcquireGuardedMutex(&MmPageFileCreationLock); 77202b0ca08SPierre Schweitzer ASSERT(MmPagingFile[MmNumberOfPagingFiles] == NULL); 773f106c297SPierre Schweitzer MmPagingFile[MmNumberOfPagingFiles] = PagingFile; 77402b0ca08SPierre Schweitzer MmNumberOfPagingFiles++; 775f106c297SPierre Schweitzer MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages; 776315867d4SPierre Schweitzer KeReleaseGuardedMutex(&MmPageFileCreationLock); 777c2c66affSColin Finck 778c2c66affSColin Finck MmSwapSpaceMessage = FALSE; 779c2c66affSColin Finck 7801ea68d05SPierre Schweitzer return STATUS_SUCCESS; 781c2c66affSColin Finck } 782c2c66affSColin Finck 783c2c66affSColin Finck /* EOF */ 784