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 */ 47c2c66affSColin Finck static KSPIN_LOCK PagingFileListLock; 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 261c2c66affSColin Finck KeInitializeSpinLock(&PagingFileListLock); 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 static ULONG 27502b0ca08SPierre Schweitzer MiAllocPageFromPagingFile(PMMPAGING_FILE PagingFile) 276c2c66affSColin Finck { 277c2c66affSColin Finck KIRQL oldIrql; 278f080ee13SPierre Schweitzer ULONG off; 279c2c66affSColin Finck 280c2c66affSColin Finck KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql); 281f080ee13SPierre Schweitzer off = RtlFindClearBitsAndSet(PagingFile->AllocMap, 1, 0); 282c2c66affSColin Finck KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql); 283c2c66affSColin Finck 284f080ee13SPierre Schweitzer return off; 285c2c66affSColin Finck } 286c2c66affSColin Finck 287c2c66affSColin Finck VOID 288c2c66affSColin Finck NTAPI 289c2c66affSColin Finck MmFreeSwapPage(SWAPENTRY Entry) 290c2c66affSColin Finck { 291c2c66affSColin Finck ULONG i; 292c2c66affSColin Finck ULONG_PTR off; 293c2c66affSColin Finck KIRQL oldIrql; 29402b0ca08SPierre Schweitzer PMMPAGING_FILE PagingFile; 295c2c66affSColin Finck 296c2c66affSColin Finck i = FILE_FROM_ENTRY(Entry); 297c2c66affSColin Finck off = OFFSET_FROM_ENTRY(Entry) - 1; 298c2c66affSColin Finck 299c2c66affSColin Finck KeAcquireSpinLock(&PagingFileListLock, &oldIrql); 300f106c297SPierre Schweitzer 301f106c297SPierre Schweitzer PagingFile = MmPagingFile[i]; 302f106c297SPierre Schweitzer if (PagingFile == NULL) 303c2c66affSColin Finck { 304c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 305c2c66affSColin Finck } 306f106c297SPierre Schweitzer KeAcquireSpinLockAtDpcLevel(&PagingFile->AllocMapLock); 307c2c66affSColin Finck 308f106c297SPierre Schweitzer RtlClearBit(PagingFile->AllocMap, off >> 5); 309c2c66affSColin Finck 310f106c297SPierre Schweitzer PagingFile->FreePages++; 311f106c297SPierre Schweitzer PagingFile->UsedPages--; 312c2c66affSColin Finck 313c2c66affSColin Finck MiFreeSwapPages++; 314c2c66affSColin Finck MiUsedSwapPages--; 315c2c66affSColin Finck 316f106c297SPierre Schweitzer KeReleaseSpinLockFromDpcLevel(&PagingFile->AllocMapLock); 317c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 318c2c66affSColin Finck } 319c2c66affSColin Finck 320c2c66affSColin Finck SWAPENTRY 321c2c66affSColin Finck NTAPI 322c2c66affSColin Finck MmAllocSwapPage(VOID) 323c2c66affSColin Finck { 324c2c66affSColin Finck KIRQL oldIrql; 325c2c66affSColin Finck ULONG i; 326c2c66affSColin Finck ULONG off; 327c2c66affSColin Finck SWAPENTRY entry; 328c2c66affSColin Finck 329c2c66affSColin Finck KeAcquireSpinLock(&PagingFileListLock, &oldIrql); 330c2c66affSColin Finck 331c2c66affSColin Finck if (MiFreeSwapPages == 0) 332c2c66affSColin Finck { 333c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 334c2c66affSColin Finck return(0); 335c2c66affSColin Finck } 336c2c66affSColin Finck 337c2c66affSColin Finck for (i = 0; i < MAX_PAGING_FILES; i++) 338c2c66affSColin Finck { 339f106c297SPierre Schweitzer if (MmPagingFile[i] != NULL && 340f106c297SPierre Schweitzer MmPagingFile[i]->FreePages >= 1) 341c2c66affSColin Finck { 342f106c297SPierre Schweitzer off = MiAllocPageFromPagingFile(MmPagingFile[i]); 343c2c66affSColin Finck if (off == 0xFFFFFFFF) 344c2c66affSColin Finck { 345c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 346c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 347c2c66affSColin Finck return(STATUS_UNSUCCESSFUL); 348c2c66affSColin Finck } 349c2c66affSColin Finck MiUsedSwapPages++; 350c2c66affSColin Finck MiFreeSwapPages--; 351c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 352c2c66affSColin Finck 353c2c66affSColin Finck entry = ENTRY_FROM_FILE_OFFSET(i, off + 1); 354c2c66affSColin Finck return(entry); 355c2c66affSColin Finck } 356c2c66affSColin Finck } 357c2c66affSColin Finck 358c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 359c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 360c2c66affSColin Finck return(0); 361c2c66affSColin Finck } 362c2c66affSColin Finck 363c2c66affSColin Finck NTSTATUS NTAPI 364c2c66affSColin Finck NtCreatePagingFile(IN PUNICODE_STRING FileName, 365c2c66affSColin Finck IN PLARGE_INTEGER InitialSize, 366c2c66affSColin Finck IN PLARGE_INTEGER MaximumSize, 367c2c66affSColin Finck IN ULONG Reserved) 368c2c66affSColin Finck { 369c2c66affSColin Finck NTSTATUS Status; 370c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 371c2c66affSColin Finck HANDLE FileHandle; 372c2c66affSColin Finck IO_STATUS_BLOCK IoStatus; 373c2c66affSColin Finck PFILE_OBJECT FileObject; 37402b0ca08SPierre Schweitzer PMMPAGING_FILE PagingFile; 375c2c66affSColin Finck KIRQL oldIrql; 376c2c66affSColin Finck ULONG AllocMapSize; 377c2c66affSColin Finck ULONG Count; 378c2c66affSColin Finck KPROCESSOR_MODE PreviousMode; 37934e8f451SPierre Schweitzer UNICODE_STRING PageFileName; 3802969c28aSPierre Schweitzer LARGE_INTEGER SafeInitialSize, SafeMaximumSize, AllocationSize; 38136c20dc5SPierre Schweitzer FILE_FS_DEVICE_INFORMATION FsDeviceInfo; 38228b4b419SPierre Schweitzer SECURITY_DESCRIPTOR SecurityDescriptor; 38328b4b419SPierre Schweitzer PACL Dacl; 38434e8f451SPierre Schweitzer PWSTR Buffer; 385c2c66affSColin Finck 386c2c66affSColin Finck DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n", 387c2c66affSColin Finck FileName, InitialSize->QuadPart); 388c2c66affSColin Finck 389c2c66affSColin Finck if (MmNumberOfPagingFiles >= MAX_PAGING_FILES) 390c2c66affSColin Finck { 3910ad4ef60SPierre Schweitzer return STATUS_TOO_MANY_PAGING_FILES; 392c2c66affSColin Finck } 393c2c66affSColin Finck 394c2c66affSColin Finck PreviousMode = ExGetPreviousMode(); 395c2c66affSColin Finck 396c2c66affSColin Finck if (PreviousMode != KernelMode) 397c2c66affSColin Finck { 3980ad4ef60SPierre Schweitzer if (SeSinglePrivilegeCheck(SeCreatePagefilePrivilege, PreviousMode) != TRUE) 3990ad4ef60SPierre Schweitzer { 4000ad4ef60SPierre Schweitzer return STATUS_PRIVILEGE_NOT_HELD; 4010ad4ef60SPierre Schweitzer } 4020ad4ef60SPierre Schweitzer 403c2c66affSColin Finck _SEH2_TRY 404c2c66affSColin Finck { 405c2c66affSColin Finck SafeInitialSize = ProbeForReadLargeInteger(InitialSize); 406c2c66affSColin Finck SafeMaximumSize = ProbeForReadLargeInteger(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 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 413c2c66affSColin Finck { 414c2c66affSColin Finck /* Return the exception code */ 415c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 416c2c66affSColin Finck } 417c2c66affSColin Finck _SEH2_END; 418c2c66affSColin Finck } 419c2c66affSColin Finck else 420c2c66affSColin Finck { 421c2c66affSColin Finck SafeInitialSize = *InitialSize; 422c2c66affSColin Finck SafeMaximumSize = *MaximumSize; 42334e8f451SPierre Schweitzer 42434e8f451SPierre Schweitzer PageFileName.Length = FileName->Length; 42534e8f451SPierre Schweitzer PageFileName.MaximumLength = FileName->MaximumLength; 42634e8f451SPierre Schweitzer PageFileName.Buffer = FileName->Buffer; 427c2c66affSColin Finck } 428c2c66affSColin Finck 429c2c66affSColin Finck /* Pagefiles can't be larger than 4GB and ofcourse the minimum should be 430c2c66affSColin Finck smaller than the maximum */ 431c2c66affSColin Finck if (0 != SafeInitialSize.u.HighPart) 432c2c66affSColin Finck { 433c2c66affSColin Finck return STATUS_INVALID_PARAMETER_2; 434c2c66affSColin Finck } 435c2c66affSColin Finck if (0 != SafeMaximumSize.u.HighPart) 436c2c66affSColin Finck { 437c2c66affSColin Finck return STATUS_INVALID_PARAMETER_3; 438c2c66affSColin Finck } 439c2c66affSColin Finck if (SafeMaximumSize.u.LowPart < SafeInitialSize.u.LowPart) 440c2c66affSColin Finck { 441c2c66affSColin Finck return STATUS_INVALID_PARAMETER_MIX; 442c2c66affSColin Finck } 443c2c66affSColin Finck 44434e8f451SPierre Schweitzer /* Validate name length */ 44534e8f451SPierre Schweitzer if (PageFileName.Length > 128 * sizeof(WCHAR)) 446c2c66affSColin Finck { 44734e8f451SPierre Schweitzer return STATUS_OBJECT_NAME_INVALID; 448c2c66affSColin Finck } 449c2c66affSColin Finck 45034e8f451SPierre Schweitzer /* We won't care about any potential UNICODE_NULL */ 45134e8f451SPierre Schweitzer PageFileName.MaximumLength = PageFileName.Length; 45234e8f451SPierre Schweitzer /* Allocate a buffer to keep name copy */ 45334e8f451SPierre Schweitzer Buffer = ExAllocatePoolWithTag(PagedPool, PageFileName.Length, TAG_MM); 45434e8f451SPierre Schweitzer if (Buffer == NULL) 45534e8f451SPierre Schweitzer { 45634e8f451SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES; 45734e8f451SPierre Schweitzer } 45834e8f451SPierre Schweitzer 45934e8f451SPierre Schweitzer /* Copy name */ 46034e8f451SPierre Schweitzer if (PreviousMode != KernelMode) 46134e8f451SPierre Schweitzer { 46234e8f451SPierre Schweitzer _SEH2_TRY 46334e8f451SPierre Schweitzer { 46434e8f451SPierre Schweitzer if (PageFileName.Length != 0) 46534e8f451SPierre Schweitzer { 46634e8f451SPierre Schweitzer ProbeForRead(PageFileName.Buffer, PageFileName.Length, sizeof(WCHAR)); 46734e8f451SPierre Schweitzer } 46834e8f451SPierre Schweitzer 46934e8f451SPierre Schweitzer RtlCopyMemory(Buffer, PageFileName.Buffer, PageFileName.Length); 47034e8f451SPierre Schweitzer } 47134e8f451SPierre Schweitzer _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 47234e8f451SPierre Schweitzer { 47334e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 47434e8f451SPierre Schweitzer 47534e8f451SPierre Schweitzer /* Return the exception code */ 47634e8f451SPierre Schweitzer _SEH2_YIELD(return _SEH2_GetExceptionCode()); 47734e8f451SPierre Schweitzer } 47834e8f451SPierre Schweitzer _SEH2_END; 47934e8f451SPierre Schweitzer } 48034e8f451SPierre Schweitzer else 48134e8f451SPierre Schweitzer { 48234e8f451SPierre Schweitzer RtlCopyMemory(Buffer, PageFileName.Buffer, PageFileName.Length); 48334e8f451SPierre Schweitzer } 48434e8f451SPierre Schweitzer 48534e8f451SPierre Schweitzer /* Erase caller's buffer with ours */ 48634e8f451SPierre Schweitzer PageFileName.Buffer = Buffer; 48734e8f451SPierre Schweitzer 48828b4b419SPierre Schweitzer /* Create the security descriptor for the page file */ 48928b4b419SPierre Schweitzer Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); 49028b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 49128b4b419SPierre Schweitzer { 49234e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 49328b4b419SPierre Schweitzer return Status; 49428b4b419SPierre Schweitzer } 49528b4b419SPierre Schweitzer 49628b4b419SPierre Schweitzer /* Create the DACL: we will only allow two SIDs */ 49728b4b419SPierre Schweitzer Count = sizeof(ACL) + (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) + 49828b4b419SPierre Schweitzer (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid)); 49928b4b419SPierre Schweitzer Dacl = ExAllocatePoolWithTag(PagedPool, Count, 'lcaD'); 50028b4b419SPierre Schweitzer if (Dacl == NULL) 50128b4b419SPierre Schweitzer { 50234e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 50328b4b419SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES; 50428b4b419SPierre Schweitzer } 50528b4b419SPierre Schweitzer 50628b4b419SPierre Schweitzer /* Initialize the DACL */ 50728b4b419SPierre Schweitzer Status = RtlCreateAcl(Dacl, Count, ACL_REVISION); 50828b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 50928b4b419SPierre Schweitzer { 51028b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 51134e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 51228b4b419SPierre Schweitzer return Status; 51328b4b419SPierre Schweitzer } 51428b4b419SPierre Schweitzer 51528b4b419SPierre Schweitzer /* Grant full access to admins */ 51628b4b419SPierre Schweitzer Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, FILE_ALL_ACCESS, SeAliasAdminsSid); 51728b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 51828b4b419SPierre Schweitzer { 51928b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 52034e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 52128b4b419SPierre Schweitzer return Status; 52228b4b419SPierre Schweitzer } 52328b4b419SPierre Schweitzer 52428b4b419SPierre Schweitzer /* Grant full access to SYSTEM */ 52528b4b419SPierre Schweitzer Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, FILE_ALL_ACCESS, SeLocalSystemSid); 52628b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 52728b4b419SPierre Schweitzer { 52828b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 52934e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 53028b4b419SPierre Schweitzer return Status; 53128b4b419SPierre Schweitzer } 53228b4b419SPierre Schweitzer 53328b4b419SPierre Schweitzer /* Attach the DACL to the security descriptor */ 53428b4b419SPierre Schweitzer Status = RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl, FALSE); 53528b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 53628b4b419SPierre Schweitzer { 53728b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 53834e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 53928b4b419SPierre Schweitzer return Status; 54028b4b419SPierre Schweitzer } 54128b4b419SPierre Schweitzer 542c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 54334e8f451SPierre Schweitzer &PageFileName, 544c2c66affSColin Finck OBJ_KERNEL_HANDLE, 545c2c66affSColin Finck NULL, 54628b4b419SPierre Schweitzer &SecurityDescriptor); 547c2c66affSColin Finck 5482969c28aSPierre Schweitzer /* Make sure we can at least store a complete page: 5492969c28aSPierre Schweitzer * If we have 2048 BytesPerAllocationUnit (FAT16 < 128MB) there is 5502969c28aSPierre Schweitzer * a problem if the paging file is fragmented. Suppose the first cluster 5512969c28aSPierre Schweitzer * of the paging file is cluster 3042 but cluster 3043 is NOT part of the 5522969c28aSPierre Schweitzer * paging file but of another file. We can't write a complete page (4096 5532969c28aSPierre Schweitzer * bytes) to the physical location of cluster 3042 then. */ 5542969c28aSPierre Schweitzer AllocationSize.QuadPart = SafeInitialSize.QuadPart + PAGE_SIZE; 5552969c28aSPierre Schweitzer 5562969c28aSPierre Schweitzer /* First, attempt to replace the page file, if existing */ 557c2c66affSColin Finck Status = IoCreateFile(&FileHandle, 5582969c28aSPierre Schweitzer SYNCHRONIZE | WRITE_DAC | FILE_READ_DATA | FILE_WRITE_DATA, 559c2c66affSColin Finck &ObjectAttributes, 560c2c66affSColin Finck &IoStatus, 5612969c28aSPierre Schweitzer &AllocationSize, 5622969c28aSPierre Schweitzer FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 5632969c28aSPierre Schweitzer FILE_SHARE_WRITE, 5642969c28aSPierre Schweitzer FILE_SUPERSEDE, 5652969c28aSPierre Schweitzer FILE_DELETE_ON_CLOSE | FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING, 566c2c66affSColin Finck NULL, 567c2c66affSColin Finck 0, 568c2c66affSColin Finck CreateFileTypeNone, 569c2c66affSColin Finck NULL, 570c2c66affSColin Finck SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING); 5712969c28aSPierre Schweitzer /* If we failed, relax a bit constraints, someone may be already holding the 5722969c28aSPierre Schweitzer * the file, so share write, don't attempt to replace and don't delete on close 5732969c28aSPierre Schweitzer * (basically, don't do anything conflicting) 574*5bd938bdSPierre Schweitzer * This can happen if the caller attempts to extend a page file. 5752969c28aSPierre Schweitzer */ 5762969c28aSPierre Schweitzer if (!NT_SUCCESS(Status)) 5772969c28aSPierre Schweitzer { 578*5bd938bdSPierre Schweitzer ULONG i; 579*5bd938bdSPierre Schweitzer 5802969c28aSPierre Schweitzer Status = IoCreateFile(&FileHandle, 5812969c28aSPierre Schweitzer SYNCHRONIZE | FILE_WRITE_DATA, 5822969c28aSPierre Schweitzer &ObjectAttributes, 5832969c28aSPierre Schweitzer &IoStatus, 5842969c28aSPierre Schweitzer &AllocationSize, 5852969c28aSPierre Schweitzer FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 5862969c28aSPierre Schweitzer FILE_SHARE_WRITE | FILE_SHARE_READ, 5872969c28aSPierre Schweitzer FILE_OPEN, 5882969c28aSPierre Schweitzer FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING, 5892969c28aSPierre Schweitzer NULL, 5902969c28aSPierre Schweitzer 0, 5912969c28aSPierre Schweitzer CreateFileTypeNone, 5922969c28aSPierre Schweitzer NULL, 5932969c28aSPierre Schweitzer SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING); 594*5bd938bdSPierre Schweitzer if (!NT_SUCCESS(Status)) 595*5bd938bdSPierre Schweitzer { 596*5bd938bdSPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 597*5bd938bdSPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 598*5bd938bdSPierre Schweitzer return Status; 599*5bd938bdSPierre Schweitzer } 600*5bd938bdSPierre Schweitzer 601*5bd938bdSPierre Schweitzer /* We opened it! Check we are that "someone" ;-) 602*5bd938bdSPierre Schweitzer * First, get the opened file object. 603*5bd938bdSPierre Schweitzer */ 604*5bd938bdSPierre Schweitzer Status = ObReferenceObjectByHandle(FileHandle, 605*5bd938bdSPierre Schweitzer FILE_READ_DATA | FILE_WRITE_DATA, 606*5bd938bdSPierre Schweitzer IoFileObjectType, 607*5bd938bdSPierre Schweitzer KernelMode, 608*5bd938bdSPierre Schweitzer (PVOID*)&FileObject, 609*5bd938bdSPierre Schweitzer NULL); 610*5bd938bdSPierre Schweitzer if (!NT_SUCCESS(Status)) 611*5bd938bdSPierre Schweitzer { 612*5bd938bdSPierre Schweitzer ZwClose(FileHandle); 613*5bd938bdSPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 614*5bd938bdSPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 615*5bd938bdSPierre Schweitzer return Status; 616*5bd938bdSPierre Schweitzer } 617*5bd938bdSPierre Schweitzer 618*5bd938bdSPierre Schweitzer /* Find if it matches a previous page file */ 619*5bd938bdSPierre Schweitzer PagingFile = NULL; 620*5bd938bdSPierre Schweitzer if (MmNumberOfPagingFiles > 0) 621*5bd938bdSPierre Schweitzer { 622*5bd938bdSPierre Schweitzer i = 0; 623*5bd938bdSPierre Schweitzer 624*5bd938bdSPierre Schweitzer while (MmPagingFile[i]->FileObject->SectionObjectPointer != FileObject->SectionObjectPointer) 625*5bd938bdSPierre Schweitzer { 626*5bd938bdSPierre Schweitzer ++i; 627*5bd938bdSPierre Schweitzer if (i >= MmNumberOfPagingFiles) 628*5bd938bdSPierre Schweitzer { 629*5bd938bdSPierre Schweitzer break; 630*5bd938bdSPierre Schweitzer } 631*5bd938bdSPierre Schweitzer } 632*5bd938bdSPierre Schweitzer 633*5bd938bdSPierre Schweitzer /* This is the matching page file */ 634*5bd938bdSPierre Schweitzer PagingFile = MmPagingFile[i]; 635*5bd938bdSPierre Schweitzer } 636*5bd938bdSPierre Schweitzer 637*5bd938bdSPierre Schweitzer /* If we didn't find the page file, fail */ 638*5bd938bdSPierre Schweitzer if (PagingFile == NULL) 639*5bd938bdSPierre Schweitzer { 640*5bd938bdSPierre Schweitzer ObDereferenceObject(FileObject); 641*5bd938bdSPierre Schweitzer ZwClose(FileHandle); 642*5bd938bdSPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 643*5bd938bdSPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 644*5bd938bdSPierre Schweitzer return STATUS_NOT_FOUND; 645*5bd938bdSPierre Schweitzer } 646*5bd938bdSPierre Schweitzer 647*5bd938bdSPierre Schweitzer /* FIXME: implement parameters checking and page file extension */ 648*5bd938bdSPierre Schweitzer UNIMPLEMENTED; 649*5bd938bdSPierre Schweitzer 650*5bd938bdSPierre Schweitzer ObDereferenceObject(FileObject); 651*5bd938bdSPierre Schweitzer ZwClose(FileHandle); 652*5bd938bdSPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 653*5bd938bdSPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 654*5bd938bdSPierre Schweitzer return STATUS_NOT_IMPLEMENTED; 6552969c28aSPierre Schweitzer } 656c2c66affSColin Finck 657c2c66affSColin Finck if (!NT_SUCCESS(Status)) 658c2c66affSColin Finck { 6592969c28aSPierre Schweitzer DPRINT1("Failed creating page file: %lx\n", Status); 66028b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 66134e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 66234e8f451SPierre Schweitzer return Status; 663c2c66affSColin Finck } 664c2c66affSColin Finck 66528b4b419SPierre Schweitzer /* Set the security descriptor */ 66628b4b419SPierre Schweitzer if (NT_SUCCESS(IoStatus.Status)) 66728b4b419SPierre Schweitzer { 66828b4b419SPierre Schweitzer Status = ZwSetSecurityObject(FileHandle, DACL_SECURITY_INFORMATION, &SecurityDescriptor); 66928b4b419SPierre Schweitzer if (!NT_SUCCESS(Status)) 67028b4b419SPierre Schweitzer { 67128b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 67228b4b419SPierre Schweitzer ZwClose(FileHandle); 67334e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 67428b4b419SPierre Schweitzer return Status; 67528b4b419SPierre Schweitzer } 67628b4b419SPierre Schweitzer } 67728b4b419SPierre Schweitzer 67828b4b419SPierre Schweitzer /* DACL is no longer needed, free it */ 67928b4b419SPierre Schweitzer ExFreePoolWithTag(Dacl, 'lcaD'); 68028b4b419SPierre Schweitzer 6812969c28aSPierre Schweitzer /* Set its end of file to initial size */ 682c2c66affSColin Finck Status = ZwSetInformationFile(FileHandle, 683c2c66affSColin Finck &IoStatus, 684c2c66affSColin Finck &SafeInitialSize, 685c2c66affSColin Finck sizeof(LARGE_INTEGER), 6862969c28aSPierre Schweitzer FileEndOfFileInformation); 6872969c28aSPierre Schweitzer if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStatus.Status)) 688c2c66affSColin Finck { 689c2c66affSColin Finck ZwClose(FileHandle); 69034e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 69134e8f451SPierre Schweitzer return Status; 692c2c66affSColin Finck } 693c2c66affSColin Finck 694c2c66affSColin Finck Status = ObReferenceObjectByHandle(FileHandle, 695c2c66affSColin Finck FILE_ALL_ACCESS, 696c2c66affSColin Finck IoFileObjectType, 697c2c66affSColin Finck KernelMode, 698c2c66affSColin Finck (PVOID*)&FileObject, 699c2c66affSColin Finck NULL); 700c2c66affSColin Finck if (!NT_SUCCESS(Status)) 701c2c66affSColin Finck { 702c2c66affSColin Finck ZwClose(FileHandle); 70334e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 70434e8f451SPierre Schweitzer return Status; 705c2c66affSColin Finck } 706c2c66affSColin Finck 70736c20dc5SPierre Schweitzer /* Deny page file creation on a floppy disk */ 70836c20dc5SPierre Schweitzer FsDeviceInfo.Characteristics = 0; 70936c20dc5SPierre Schweitzer IoQueryVolumeInformation(FileObject, FileFsDeviceInformation, sizeof(FsDeviceInfo), &FsDeviceInfo, &Count); 71036c20dc5SPierre Schweitzer if (BooleanFlagOn(FsDeviceInfo.Characteristics, FILE_FLOPPY_DISKETTE)) 71136c20dc5SPierre Schweitzer { 71236c20dc5SPierre Schweitzer ObDereferenceObject(FileObject); 71336c20dc5SPierre Schweitzer ZwClose(FileHandle); 71434e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 71536c20dc5SPierre Schweitzer return STATUS_FLOPPY_VOLUME; 71636c20dc5SPierre Schweitzer } 71736c20dc5SPierre Schweitzer 7181ea68d05SPierre Schweitzer PagingFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(*PagingFile), TAG_MM); 719c2c66affSColin Finck if (PagingFile == NULL) 720c2c66affSColin Finck { 721c2c66affSColin Finck ObDereferenceObject(FileObject); 722c2c66affSColin Finck ZwClose(FileHandle); 72334e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 7241ea68d05SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES; 725c2c66affSColin Finck } 726c2c66affSColin Finck 727c2c66affSColin Finck RtlZeroMemory(PagingFile, sizeof(*PagingFile)); 728c2c66affSColin Finck 7292969c28aSPierre Schweitzer PagingFile->FileHandle = FileHandle; 730c2c66affSColin Finck PagingFile->FileObject = FileObject; 731c2c66affSColin Finck PagingFile->MaximumSize.QuadPart = SafeMaximumSize.QuadPart; 732c2c66affSColin Finck PagingFile->CurrentSize.QuadPart = SafeInitialSize.QuadPart; 733c2c66affSColin Finck PagingFile->FreePages = (ULONG)(SafeInitialSize.QuadPart / PAGE_SIZE); 734c2c66affSColin Finck PagingFile->UsedPages = 0; 735c2c66affSColin Finck KeInitializeSpinLock(&PagingFile->AllocMapLock); 73634e8f451SPierre Schweitzer PagingFile->PageFileName = PageFileName; 737c2c66affSColin Finck 738f080ee13SPierre Schweitzer AllocMapSize = sizeof(RTL_BITMAP) + (((PagingFile->FreePages + 31) / 32) * sizeof(ULONG)); 739f080ee13SPierre Schweitzer PagingFile->AllocMap = ExAllocatePoolWithTag(NonPagedPool, 740f080ee13SPierre Schweitzer AllocMapSize, 741f080ee13SPierre Schweitzer TAG_MM); 742c2c66affSColin Finck if (PagingFile->AllocMap == NULL) 743c2c66affSColin Finck { 7441ea68d05SPierre Schweitzer ExFreePoolWithTag(PagingFile, TAG_MM); 745c2c66affSColin Finck ObDereferenceObject(FileObject); 746c2c66affSColin Finck ZwClose(FileHandle); 74734e8f451SPierre Schweitzer ExFreePoolWithTag(Buffer, TAG_MM); 7481ea68d05SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES; 749c2c66affSColin Finck } 750c2c66affSColin Finck 751f080ee13SPierre Schweitzer RtlInitializeBitMap(PagingFile->AllocMap, 752f080ee13SPierre Schweitzer (PULONG)(PagingFile->AllocMap + 1), 753f080ee13SPierre Schweitzer (ULONG)(PagingFile->FreePages)); 754f080ee13SPierre Schweitzer RtlClearAllBits(PagingFile->AllocMap); 755c2c66affSColin Finck 756c2c66affSColin Finck KeAcquireSpinLock(&PagingFileListLock, &oldIrql); 75702b0ca08SPierre Schweitzer ASSERT(MmPagingFile[MmNumberOfPagingFiles] == NULL); 758f106c297SPierre Schweitzer MmPagingFile[MmNumberOfPagingFiles] = PagingFile; 75902b0ca08SPierre Schweitzer MmNumberOfPagingFiles++; 760f106c297SPierre Schweitzer MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages; 761c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 762c2c66affSColin Finck 763c2c66affSColin Finck MmSwapSpaceMessage = FALSE; 764c2c66affSColin Finck 7651ea68d05SPierre Schweitzer return STATUS_SUCCESS; 766c2c66affSColin Finck } 767c2c66affSColin Finck 768c2c66affSColin Finck /* EOF */ 769