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) 24c2c66affSColin Finck * UPDATE HISTORY: 25c2c66affSColin Finck * Created 22/05/98 26c2c66affSColin Finck */ 27c2c66affSColin Finck 28c2c66affSColin Finck /* INCLUDES *****************************************************************/ 29c2c66affSColin Finck 30c2c66affSColin Finck #include <ntoskrnl.h> 31c2c66affSColin Finck #define NDEBUG 32c2c66affSColin Finck #include <debug.h> 33c2c66affSColin Finck 34c2c66affSColin Finck #if defined (ALLOC_PRAGMA) 35c2c66affSColin Finck #pragma alloc_text(INIT, MmInitPagingFile) 36c2c66affSColin Finck #endif 37c2c66affSColin Finck 38c2c66affSColin Finck PVOID 39c2c66affSColin Finck NTAPI 40c2c66affSColin Finck MiFindExportedRoutineByName(IN PVOID DllBase, 41c2c66affSColin Finck IN PANSI_STRING ExportName); 42c2c66affSColin Finck 43c2c66affSColin Finck /* TYPES *********************************************************************/ 44c2c66affSColin Finck 45c2c66affSColin Finck typedef struct _PAGINGFILE 46c2c66affSColin Finck { 47c2c66affSColin Finck LIST_ENTRY PagingFileListEntry; 48c2c66affSColin Finck PFILE_OBJECT FileObject; 49*2969c28aSPierre Schweitzer HANDLE FileHandle; 50c2c66affSColin Finck LARGE_INTEGER MaximumSize; 51c2c66affSColin Finck LARGE_INTEGER CurrentSize; 52c2c66affSColin Finck PFN_NUMBER FreePages; 53c2c66affSColin Finck PFN_NUMBER UsedPages; 54c2c66affSColin Finck PULONG AllocMap; 55c2c66affSColin Finck KSPIN_LOCK AllocMapLock; 56c2c66affSColin Finck ULONG AllocMapSize; 57c2c66affSColin Finck PRETRIEVAL_POINTERS_BUFFER RetrievalPointers; 58c2c66affSColin Finck } 59c2c66affSColin Finck PAGINGFILE, *PPAGINGFILE; 60c2c66affSColin Finck 61c2c66affSColin Finck typedef struct _RETRIEVEL_DESCRIPTOR_LIST 62c2c66affSColin Finck { 63c2c66affSColin Finck struct _RETRIEVEL_DESCRIPTOR_LIST* Next; 64c2c66affSColin Finck RETRIEVAL_POINTERS_BUFFER RetrievalPointers; 65c2c66affSColin Finck } 66c2c66affSColin Finck RETRIEVEL_DESCRIPTOR_LIST, *PRETRIEVEL_DESCRIPTOR_LIST; 67c2c66affSColin Finck 68c2c66affSColin Finck /* GLOBALS *******************************************************************/ 69c2c66affSColin Finck 70c2c66affSColin Finck #define PAIRS_PER_RUN (1024) 71c2c66affSColin Finck 72c2c66affSColin Finck #define MAX_PAGING_FILES (16) 73c2c66affSColin Finck 74c2c66affSColin Finck /* List of paging files, both used and free */ 75c2c66affSColin Finck static PPAGINGFILE PagingFileList[MAX_PAGING_FILES]; 76c2c66affSColin Finck 77c2c66affSColin Finck /* Lock for examining the list of paging files */ 78c2c66affSColin Finck static KSPIN_LOCK PagingFileListLock; 79c2c66affSColin Finck 80c2c66affSColin Finck /* Number of paging files */ 81c2c66affSColin Finck ULONG MmNumberOfPagingFiles; 82c2c66affSColin Finck 83c2c66affSColin Finck /* Number of pages that are available for swapping */ 84c2c66affSColin Finck PFN_COUNT MiFreeSwapPages; 85c2c66affSColin Finck 86c2c66affSColin Finck /* Number of pages that have been allocated for swapping */ 87c2c66affSColin Finck PFN_COUNT MiUsedSwapPages; 88c2c66affSColin Finck 89c2c66affSColin Finck BOOLEAN MmZeroPageFile; 90c2c66affSColin Finck 91c2c66affSColin Finck /* 92c2c66affSColin Finck * Number of pages that have been reserved for swapping but not yet allocated 93c2c66affSColin Finck */ 94c2c66affSColin Finck static PFN_COUNT MiReservedSwapPages; 95c2c66affSColin Finck 96c2c66affSColin Finck /* 97c2c66affSColin Finck * Ratio between reserved and available swap pages, e.g. setting this to five 98c2c66affSColin Finck * forces one swap page to be available for every five swap pages that are 99c2c66affSColin Finck * reserved. Setting this to zero turns off commit checking altogether. 100c2c66affSColin Finck */ 101c2c66affSColin Finck #define MM_PAGEFILE_COMMIT_RATIO (1) 102c2c66affSColin Finck 103c2c66affSColin Finck /* 104c2c66affSColin Finck * Number of pages that can be used for potentially swapable memory without 105c2c66affSColin Finck * pagefile space being reserved. The intention is that this allows smss 106c2c66affSColin Finck * to start up and create page files while ordinarily having a commit 107c2c66affSColin Finck * ratio of one. 108c2c66affSColin Finck */ 109c2c66affSColin Finck #define MM_PAGEFILE_COMMIT_GRACE (256) 110c2c66affSColin Finck 111c2c66affSColin Finck /* 112c2c66affSColin Finck * Translate between a swap entry and a file and offset pair. 113c2c66affSColin Finck */ 114c2c66affSColin Finck #define FILE_FROM_ENTRY(i) ((i) & 0x0f) 115c2c66affSColin Finck #define OFFSET_FROM_ENTRY(i) ((i) >> 11) 116c2c66affSColin Finck #define ENTRY_FROM_FILE_OFFSET(i, j) ((i) | ((j) << 11) | 0x400) 117c2c66affSColin Finck 118c2c66affSColin Finck /* Make sure there can be only 16 paging files */ 119c2c66affSColin Finck C_ASSERT(FILE_FROM_ENTRY(0xffffffff) < MAX_PAGING_FILES); 120c2c66affSColin Finck 121c2c66affSColin Finck static BOOLEAN MmSwapSpaceMessage = FALSE; 122c2c66affSColin Finck 123c2c66affSColin Finck /* FUNCTIONS *****************************************************************/ 124c2c66affSColin Finck 125c2c66affSColin Finck VOID 126c2c66affSColin Finck NTAPI 127c2c66affSColin Finck MmBuildMdlFromPages(PMDL Mdl, PPFN_NUMBER Pages) 128c2c66affSColin Finck { 129c2c66affSColin Finck memcpy(Mdl + 1, Pages, sizeof(PFN_NUMBER) * (PAGE_ROUND_UP(Mdl->ByteOffset+Mdl->ByteCount)/PAGE_SIZE)); 130c2c66affSColin Finck 131c2c66affSColin Finck /* FIXME: this flag should be set by the caller perhaps? */ 132c2c66affSColin Finck Mdl->MdlFlags |= MDL_IO_PAGE_READ; 133c2c66affSColin Finck } 134c2c66affSColin Finck 135c2c66affSColin Finck 136c2c66affSColin Finck BOOLEAN 137c2c66affSColin Finck NTAPI 138c2c66affSColin Finck MmIsFileObjectAPagingFile(PFILE_OBJECT FileObject) 139c2c66affSColin Finck { 140c2c66affSColin Finck ULONG i; 141c2c66affSColin Finck 142c2c66affSColin Finck /* Loop through all the paging files */ 143c2c66affSColin Finck for (i = 0; i < MmNumberOfPagingFiles; i++) 144c2c66affSColin Finck { 145c2c66affSColin Finck /* Check if this is one of them */ 146c2c66affSColin Finck if (PagingFileList[i]->FileObject == FileObject) return TRUE; 147c2c66affSColin Finck } 148c2c66affSColin Finck 149c2c66affSColin Finck /* Nothing found */ 150c2c66affSColin Finck return FALSE; 151c2c66affSColin Finck } 152c2c66affSColin Finck 153c2c66affSColin Finck VOID 154c2c66affSColin Finck NTAPI 155c2c66affSColin Finck MmShowOutOfSpaceMessagePagingFile(VOID) 156c2c66affSColin Finck { 157c2c66affSColin Finck if (!MmSwapSpaceMessage) 158c2c66affSColin Finck { 159c2c66affSColin Finck DPRINT1("MM: Out of swap space.\n"); 160c2c66affSColin Finck MmSwapSpaceMessage = TRUE; 161c2c66affSColin Finck } 162c2c66affSColin Finck } 163c2c66affSColin Finck 164c2c66affSColin Finck static LARGE_INTEGER 165c2c66affSColin Finck MmGetOffsetPageFile(PRETRIEVAL_POINTERS_BUFFER RetrievalPointers, LARGE_INTEGER Offset) 166c2c66affSColin Finck { 167c2c66affSColin Finck /* Simple binary search */ 168c2c66affSColin Finck ULONG first, last, mid; 169c2c66affSColin Finck first = 0; 170c2c66affSColin Finck last = RetrievalPointers->ExtentCount - 1; 171c2c66affSColin Finck while (first <= last) 172c2c66affSColin Finck { 173c2c66affSColin Finck mid = (last - first) / 2 + first; 174c2c66affSColin Finck if (Offset.QuadPart < RetrievalPointers->Extents[mid].NextVcn.QuadPart) 175c2c66affSColin Finck { 176c2c66affSColin Finck if (mid == 0) 177c2c66affSColin Finck { 178c2c66affSColin Finck Offset.QuadPart += RetrievalPointers->Extents[0].Lcn.QuadPart - RetrievalPointers->StartingVcn.QuadPart; 179c2c66affSColin Finck return Offset; 180c2c66affSColin Finck } 181c2c66affSColin Finck else 182c2c66affSColin Finck { 183c2c66affSColin Finck if (Offset.QuadPart >= RetrievalPointers->Extents[mid-1].NextVcn.QuadPart) 184c2c66affSColin Finck { 185c2c66affSColin Finck Offset.QuadPart += RetrievalPointers->Extents[mid].Lcn.QuadPart - RetrievalPointers->Extents[mid-1].NextVcn.QuadPart; 186c2c66affSColin Finck return Offset; 187c2c66affSColin Finck } 188c2c66affSColin Finck last = mid - 1; 189c2c66affSColin Finck } 190c2c66affSColin Finck } 191c2c66affSColin Finck else 192c2c66affSColin Finck { 193c2c66affSColin Finck if (mid == RetrievalPointers->ExtentCount - 1) 194c2c66affSColin Finck { 195c2c66affSColin Finck break; 196c2c66affSColin Finck } 197c2c66affSColin Finck if (Offset.QuadPart < RetrievalPointers->Extents[mid+1].NextVcn.QuadPart) 198c2c66affSColin Finck { 199c2c66affSColin Finck Offset.QuadPart += RetrievalPointers->Extents[mid+1].Lcn.QuadPart - RetrievalPointers->Extents[mid].NextVcn.QuadPart; 200c2c66affSColin Finck return Offset; 201c2c66affSColin Finck } 202c2c66affSColin Finck first = mid + 1; 203c2c66affSColin Finck } 204c2c66affSColin Finck } 205c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 206c2c66affSColin Finck #if defined(__GNUC__) 207c2c66affSColin Finck 208c2c66affSColin Finck return (LARGE_INTEGER)0LL; 209c2c66affSColin Finck #else 210c2c66affSColin Finck 211c2c66affSColin Finck { 212c2c66affSColin Finck const LARGE_INTEGER dummy = 213c2c66affSColin Finck { 214840320cbSAmine Khaldi {0} 215c2c66affSColin Finck }; 216c2c66affSColin Finck return dummy; 217c2c66affSColin Finck } 218c2c66affSColin Finck #endif 219c2c66affSColin Finck } 220c2c66affSColin Finck 221c2c66affSColin Finck NTSTATUS 222c2c66affSColin Finck NTAPI 223c2c66affSColin Finck MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page) 224c2c66affSColin Finck { 225c2c66affSColin Finck ULONG i; 226c2c66affSColin Finck ULONG_PTR offset; 227c2c66affSColin Finck LARGE_INTEGER file_offset; 228c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 229c2c66affSColin Finck NTSTATUS Status; 230c2c66affSColin Finck KEVENT Event; 231c2c66affSColin Finck UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)]; 232c2c66affSColin Finck PMDL Mdl = (PMDL)MdlBase; 233c2c66affSColin Finck 234c2c66affSColin Finck DPRINT("MmWriteToSwapPage\n"); 235c2c66affSColin Finck 236c2c66affSColin Finck if (SwapEntry == 0) 237c2c66affSColin Finck { 238c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 239c2c66affSColin Finck return(STATUS_UNSUCCESSFUL); 240c2c66affSColin Finck } 241c2c66affSColin Finck 242c2c66affSColin Finck i = FILE_FROM_ENTRY(SwapEntry); 243c2c66affSColin Finck offset = OFFSET_FROM_ENTRY(SwapEntry) - 1; 244c2c66affSColin Finck 245c2c66affSColin Finck if (PagingFileList[i]->FileObject == NULL || 246c2c66affSColin Finck PagingFileList[i]->FileObject->DeviceObject == NULL) 247c2c66affSColin Finck { 248c2c66affSColin Finck DPRINT1("Bad paging file 0x%.8X\n", SwapEntry); 249c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 250c2c66affSColin Finck } 251c2c66affSColin Finck 252c2c66affSColin Finck MmInitializeMdl(Mdl, NULL, PAGE_SIZE); 253c2c66affSColin Finck MmBuildMdlFromPages(Mdl, &Page); 254c2c66affSColin Finck Mdl->MdlFlags |= MDL_PAGES_LOCKED; 255c2c66affSColin Finck 256c2c66affSColin Finck file_offset.QuadPart = offset * PAGE_SIZE; 257c2c66affSColin Finck file_offset = MmGetOffsetPageFile(PagingFileList[i]->RetrievalPointers, file_offset); 258c2c66affSColin Finck 259c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE); 260c2c66affSColin Finck Status = IoSynchronousPageWrite(PagingFileList[i]->FileObject, 261c2c66affSColin Finck Mdl, 262c2c66affSColin Finck &file_offset, 263c2c66affSColin Finck &Event, 264c2c66affSColin Finck &Iosb); 265c2c66affSColin Finck if (Status == STATUS_PENDING) 266c2c66affSColin Finck { 267c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 268c2c66affSColin Finck Status = Iosb.Status; 269c2c66affSColin Finck } 270c2c66affSColin Finck 271c2c66affSColin Finck if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) 272c2c66affSColin Finck { 273c2c66affSColin Finck MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); 274c2c66affSColin Finck } 275c2c66affSColin Finck return(Status); 276c2c66affSColin Finck } 277c2c66affSColin Finck 278c2c66affSColin Finck 279c2c66affSColin Finck NTSTATUS 280c2c66affSColin Finck NTAPI 281c2c66affSColin Finck MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page) 282c2c66affSColin Finck { 283c2c66affSColin Finck return MiReadPageFile(Page, FILE_FROM_ENTRY(SwapEntry), OFFSET_FROM_ENTRY(SwapEntry) - 1); 284c2c66affSColin Finck } 285c2c66affSColin Finck 286c2c66affSColin Finck NTSTATUS 287c2c66affSColin Finck NTAPI 288c2c66affSColin Finck MiReadPageFile( 289c2c66affSColin Finck _In_ PFN_NUMBER Page, 290c2c66affSColin Finck _In_ ULONG PageFileIndex, 291c2c66affSColin Finck _In_ ULONG_PTR PageFileOffset) 292c2c66affSColin Finck { 293c2c66affSColin Finck LARGE_INTEGER file_offset; 294c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 295c2c66affSColin Finck NTSTATUS Status; 296c2c66affSColin Finck KEVENT Event; 297c2c66affSColin Finck UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)]; 298c2c66affSColin Finck PMDL Mdl = (PMDL)MdlBase; 299c2c66affSColin Finck PPAGINGFILE PagingFile; 300c2c66affSColin Finck 301c2c66affSColin Finck DPRINT("MiReadSwapFile\n"); 302c2c66affSColin Finck 303c2c66affSColin Finck if (PageFileOffset == 0) 304c2c66affSColin Finck { 305c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 306c2c66affSColin Finck return(STATUS_UNSUCCESSFUL); 307c2c66affSColin Finck } 308c2c66affSColin Finck 309c2c66affSColin Finck ASSERT(PageFileIndex < MAX_PAGING_FILES); 310c2c66affSColin Finck 311c2c66affSColin Finck PagingFile = PagingFileList[PageFileIndex]; 312c2c66affSColin Finck 313c2c66affSColin Finck if (PagingFile->FileObject == NULL || PagingFile->FileObject->DeviceObject == NULL) 314c2c66affSColin Finck { 315c2c66affSColin Finck DPRINT1("Bad paging file %u\n", PageFileIndex); 316c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 317c2c66affSColin Finck } 318c2c66affSColin Finck 319c2c66affSColin Finck MmInitializeMdl(Mdl, NULL, PAGE_SIZE); 320c2c66affSColin Finck MmBuildMdlFromPages(Mdl, &Page); 321c2c66affSColin Finck Mdl->MdlFlags |= MDL_PAGES_LOCKED; 322c2c66affSColin Finck 323c2c66affSColin Finck file_offset.QuadPart = PageFileOffset * PAGE_SIZE; 324c2c66affSColin Finck file_offset = MmGetOffsetPageFile(PagingFile->RetrievalPointers, file_offset); 325c2c66affSColin Finck 326c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE); 327c2c66affSColin Finck Status = IoPageRead(PagingFile->FileObject, 328c2c66affSColin Finck Mdl, 329c2c66affSColin Finck &file_offset, 330c2c66affSColin Finck &Event, 331c2c66affSColin Finck &Iosb); 332c2c66affSColin Finck if (Status == STATUS_PENDING) 333c2c66affSColin Finck { 334c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 335c2c66affSColin Finck Status = Iosb.Status; 336c2c66affSColin Finck } 337c2c66affSColin Finck if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) 338c2c66affSColin Finck { 339c2c66affSColin Finck MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); 340c2c66affSColin Finck } 341c2c66affSColin Finck return(Status); 342c2c66affSColin Finck } 343c2c66affSColin Finck 344c2c66affSColin Finck VOID 345c2c66affSColin Finck INIT_FUNCTION 346c2c66affSColin Finck NTAPI 347c2c66affSColin Finck MmInitPagingFile(VOID) 348c2c66affSColin Finck { 349c2c66affSColin Finck ULONG i; 350c2c66affSColin Finck 351c2c66affSColin Finck KeInitializeSpinLock(&PagingFileListLock); 352c2c66affSColin Finck 353c2c66affSColin Finck MiFreeSwapPages = 0; 354c2c66affSColin Finck MiUsedSwapPages = 0; 355c2c66affSColin Finck MiReservedSwapPages = 0; 356c2c66affSColin Finck 357c2c66affSColin Finck for (i = 0; i < MAX_PAGING_FILES; i++) 358c2c66affSColin Finck { 359c2c66affSColin Finck PagingFileList[i] = NULL; 360c2c66affSColin Finck } 361c2c66affSColin Finck MmNumberOfPagingFiles = 0; 362c2c66affSColin Finck } 363c2c66affSColin Finck 364c2c66affSColin Finck static ULONG 365c2c66affSColin Finck MiAllocPageFromPagingFile(PPAGINGFILE PagingFile) 366c2c66affSColin Finck { 367c2c66affSColin Finck KIRQL oldIrql; 368c2c66affSColin Finck ULONG i, j; 369c2c66affSColin Finck 370c2c66affSColin Finck KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql); 371c2c66affSColin Finck 372c2c66affSColin Finck for (i = 0; i < PagingFile->AllocMapSize; i++) 373c2c66affSColin Finck { 374c2c66affSColin Finck for (j = 0; j < 32; j++) 375c2c66affSColin Finck { 376c2c66affSColin Finck if (!(PagingFile->AllocMap[i] & (1 << j))) 377c2c66affSColin Finck { 378c2c66affSColin Finck PagingFile->AllocMap[i] |= (1 << j); 379c2c66affSColin Finck PagingFile->UsedPages++; 380c2c66affSColin Finck PagingFile->FreePages--; 381c2c66affSColin Finck KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql); 382c2c66affSColin Finck return((i * 32) + j); 383c2c66affSColin Finck } 384c2c66affSColin Finck } 385c2c66affSColin Finck } 386c2c66affSColin Finck 387c2c66affSColin Finck KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql); 388c2c66affSColin Finck return(0xFFFFFFFF); 389c2c66affSColin Finck } 390c2c66affSColin Finck 391c2c66affSColin Finck VOID 392c2c66affSColin Finck NTAPI 393c2c66affSColin Finck MmFreeSwapPage(SWAPENTRY Entry) 394c2c66affSColin Finck { 395c2c66affSColin Finck ULONG i; 396c2c66affSColin Finck ULONG_PTR off; 397c2c66affSColin Finck KIRQL oldIrql; 398c2c66affSColin Finck 399c2c66affSColin Finck i = FILE_FROM_ENTRY(Entry); 400c2c66affSColin Finck off = OFFSET_FROM_ENTRY(Entry) - 1; 401c2c66affSColin Finck 402c2c66affSColin Finck KeAcquireSpinLock(&PagingFileListLock, &oldIrql); 403c2c66affSColin Finck if (PagingFileList[i] == NULL) 404c2c66affSColin Finck { 405c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 406c2c66affSColin Finck } 407c2c66affSColin Finck KeAcquireSpinLockAtDpcLevel(&PagingFileList[i]->AllocMapLock); 408c2c66affSColin Finck 409c2c66affSColin Finck PagingFileList[i]->AllocMap[off >> 5] &= (~(1 << (off % 32))); 410c2c66affSColin Finck 411c2c66affSColin Finck PagingFileList[i]->FreePages++; 412c2c66affSColin Finck PagingFileList[i]->UsedPages--; 413c2c66affSColin Finck 414c2c66affSColin Finck MiFreeSwapPages++; 415c2c66affSColin Finck MiUsedSwapPages--; 416c2c66affSColin Finck 417c2c66affSColin Finck KeReleaseSpinLockFromDpcLevel(&PagingFileList[i]->AllocMapLock); 418c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 419c2c66affSColin Finck } 420c2c66affSColin Finck 421c2c66affSColin Finck SWAPENTRY 422c2c66affSColin Finck NTAPI 423c2c66affSColin Finck MmAllocSwapPage(VOID) 424c2c66affSColin Finck { 425c2c66affSColin Finck KIRQL oldIrql; 426c2c66affSColin Finck ULONG i; 427c2c66affSColin Finck ULONG off; 428c2c66affSColin Finck SWAPENTRY entry; 429c2c66affSColin Finck 430c2c66affSColin Finck KeAcquireSpinLock(&PagingFileListLock, &oldIrql); 431c2c66affSColin Finck 432c2c66affSColin Finck if (MiFreeSwapPages == 0) 433c2c66affSColin Finck { 434c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 435c2c66affSColin Finck return(0); 436c2c66affSColin Finck } 437c2c66affSColin Finck 438c2c66affSColin Finck for (i = 0; i < MAX_PAGING_FILES; i++) 439c2c66affSColin Finck { 440c2c66affSColin Finck if (PagingFileList[i] != NULL && 441c2c66affSColin Finck PagingFileList[i]->FreePages >= 1) 442c2c66affSColin Finck { 443c2c66affSColin Finck off = MiAllocPageFromPagingFile(PagingFileList[i]); 444c2c66affSColin Finck if (off == 0xFFFFFFFF) 445c2c66affSColin Finck { 446c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 447c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 448c2c66affSColin Finck return(STATUS_UNSUCCESSFUL); 449c2c66affSColin Finck } 450c2c66affSColin Finck MiUsedSwapPages++; 451c2c66affSColin Finck MiFreeSwapPages--; 452c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 453c2c66affSColin Finck 454c2c66affSColin Finck entry = ENTRY_FROM_FILE_OFFSET(i, off + 1); 455c2c66affSColin Finck return(entry); 456c2c66affSColin Finck } 457c2c66affSColin Finck } 458c2c66affSColin Finck 459c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 460c2c66affSColin Finck KeBugCheck(MEMORY_MANAGEMENT); 461c2c66affSColin Finck return(0); 462c2c66affSColin Finck } 463c2c66affSColin Finck 464c2c66affSColin Finck static PRETRIEVEL_DESCRIPTOR_LIST FASTCALL 465c2c66affSColin Finck MmAllocRetrievelDescriptorList(ULONG Pairs) 466c2c66affSColin Finck { 467c2c66affSColin Finck ULONG Size; 468c2c66affSColin Finck PRETRIEVEL_DESCRIPTOR_LIST RetDescList; 469c2c66affSColin Finck 470c2c66affSColin Finck Size = sizeof(RETRIEVEL_DESCRIPTOR_LIST) + Pairs * 2 * sizeof(LARGE_INTEGER); 471c2c66affSColin Finck RetDescList = ExAllocatePool(NonPagedPool, Size); 472c2c66affSColin Finck if (RetDescList) 473c2c66affSColin Finck { 474c2c66affSColin Finck RtlZeroMemory(RetDescList, Size); 475c2c66affSColin Finck } 476c2c66affSColin Finck 477c2c66affSColin Finck return RetDescList; 478c2c66affSColin Finck } 479c2c66affSColin Finck 480c2c66affSColin Finck NTSTATUS NTAPI 481c2c66affSColin Finck NtCreatePagingFile(IN PUNICODE_STRING FileName, 482c2c66affSColin Finck IN PLARGE_INTEGER InitialSize, 483c2c66affSColin Finck IN PLARGE_INTEGER MaximumSize, 484c2c66affSColin Finck IN ULONG Reserved) 485c2c66affSColin Finck { 486c2c66affSColin Finck NTSTATUS Status; 487c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 488c2c66affSColin Finck HANDLE FileHandle; 489c2c66affSColin Finck IO_STATUS_BLOCK IoStatus; 490c2c66affSColin Finck PFILE_OBJECT FileObject; 491c2c66affSColin Finck PPAGINGFILE PagingFile; 492c2c66affSColin Finck KIRQL oldIrql; 493c2c66affSColin Finck ULONG AllocMapSize; 494c2c66affSColin Finck FILE_FS_SIZE_INFORMATION FsSizeInformation; 495c2c66affSColin Finck PRETRIEVEL_DESCRIPTOR_LIST RetDescList; 496c2c66affSColin Finck PRETRIEVEL_DESCRIPTOR_LIST CurrentRetDescList; 497c2c66affSColin Finck ULONG i; 498c2c66affSColin Finck ULONG BytesPerAllocationUnit; 499c2c66affSColin Finck LARGE_INTEGER Vcn; 500c2c66affSColin Finck ULONG ExtentCount; 501c2c66affSColin Finck LARGE_INTEGER MaxVcn; 502c2c66affSColin Finck ULONG Count; 503c2c66affSColin Finck ULONG Size; 504c2c66affSColin Finck KPROCESSOR_MODE PreviousMode; 505c2c66affSColin Finck UNICODE_STRING CapturedFileName; 506*2969c28aSPierre Schweitzer LARGE_INTEGER SafeInitialSize, SafeMaximumSize, AllocationSize; 507c2c66affSColin Finck 508c2c66affSColin Finck DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n", 509c2c66affSColin Finck FileName, InitialSize->QuadPart); 510c2c66affSColin Finck 511c2c66affSColin Finck if (MmNumberOfPagingFiles >= MAX_PAGING_FILES) 512c2c66affSColin Finck { 5130ad4ef60SPierre Schweitzer return STATUS_TOO_MANY_PAGING_FILES; 514c2c66affSColin Finck } 515c2c66affSColin Finck 516c2c66affSColin Finck PreviousMode = ExGetPreviousMode(); 517c2c66affSColin Finck 518c2c66affSColin Finck if (PreviousMode != KernelMode) 519c2c66affSColin Finck { 5200ad4ef60SPierre Schweitzer if (SeSinglePrivilegeCheck(SeCreatePagefilePrivilege, PreviousMode) != TRUE) 5210ad4ef60SPierre Schweitzer { 5220ad4ef60SPierre Schweitzer return STATUS_PRIVILEGE_NOT_HELD; 5230ad4ef60SPierre Schweitzer } 5240ad4ef60SPierre Schweitzer 525c2c66affSColin Finck _SEH2_TRY 526c2c66affSColin Finck { 527c2c66affSColin Finck SafeInitialSize = ProbeForReadLargeInteger(InitialSize); 528c2c66affSColin Finck SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize); 529c2c66affSColin Finck } 530c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 531c2c66affSColin Finck { 532c2c66affSColin Finck /* Return the exception code */ 533c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 534c2c66affSColin Finck } 535c2c66affSColin Finck _SEH2_END; 536c2c66affSColin Finck } 537c2c66affSColin Finck else 538c2c66affSColin Finck { 539c2c66affSColin Finck SafeInitialSize = *InitialSize; 540c2c66affSColin Finck SafeMaximumSize = *MaximumSize; 541c2c66affSColin Finck } 542c2c66affSColin Finck 543c2c66affSColin Finck /* Pagefiles can't be larger than 4GB and ofcourse the minimum should be 544c2c66affSColin Finck smaller than the maximum */ 545c2c66affSColin Finck if (0 != SafeInitialSize.u.HighPart) 546c2c66affSColin Finck { 547c2c66affSColin Finck return STATUS_INVALID_PARAMETER_2; 548c2c66affSColin Finck } 549c2c66affSColin Finck if (0 != SafeMaximumSize.u.HighPart) 550c2c66affSColin Finck { 551c2c66affSColin Finck return STATUS_INVALID_PARAMETER_3; 552c2c66affSColin Finck } 553c2c66affSColin Finck if (SafeMaximumSize.u.LowPart < SafeInitialSize.u.LowPart) 554c2c66affSColin Finck { 555c2c66affSColin Finck return STATUS_INVALID_PARAMETER_MIX; 556c2c66affSColin Finck } 557c2c66affSColin Finck 558c2c66affSColin Finck Status = ProbeAndCaptureUnicodeString(&CapturedFileName, 559c2c66affSColin Finck PreviousMode, 560c2c66affSColin Finck FileName); 561c2c66affSColin Finck if (!NT_SUCCESS(Status)) 562c2c66affSColin Finck { 563c2c66affSColin Finck return(Status); 564c2c66affSColin Finck } 565c2c66affSColin Finck 566c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 567c2c66affSColin Finck &CapturedFileName, 568c2c66affSColin Finck OBJ_KERNEL_HANDLE, 569c2c66affSColin Finck NULL, 570c2c66affSColin Finck NULL); 571c2c66affSColin Finck 572*2969c28aSPierre Schweitzer /* Make sure we can at least store a complete page: 573*2969c28aSPierre Schweitzer * If we have 2048 BytesPerAllocationUnit (FAT16 < 128MB) there is 574*2969c28aSPierre Schweitzer * a problem if the paging file is fragmented. Suppose the first cluster 575*2969c28aSPierre Schweitzer * of the paging file is cluster 3042 but cluster 3043 is NOT part of the 576*2969c28aSPierre Schweitzer * paging file but of another file. We can't write a complete page (4096 577*2969c28aSPierre Schweitzer * bytes) to the physical location of cluster 3042 then. */ 578*2969c28aSPierre Schweitzer AllocationSize.QuadPart = SafeInitialSize.QuadPart + PAGE_SIZE; 579*2969c28aSPierre Schweitzer 580*2969c28aSPierre Schweitzer /* First, attempt to replace the page file, if existing */ 581c2c66affSColin Finck Status = IoCreateFile(&FileHandle, 582*2969c28aSPierre Schweitzer SYNCHRONIZE | WRITE_DAC | FILE_READ_DATA | FILE_WRITE_DATA, 583c2c66affSColin Finck &ObjectAttributes, 584c2c66affSColin Finck &IoStatus, 585*2969c28aSPierre Schweitzer &AllocationSize, 586*2969c28aSPierre Schweitzer FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 587*2969c28aSPierre Schweitzer FILE_SHARE_WRITE, 588*2969c28aSPierre Schweitzer FILE_SUPERSEDE, 589*2969c28aSPierre Schweitzer FILE_DELETE_ON_CLOSE | FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING, 590c2c66affSColin Finck NULL, 591c2c66affSColin Finck 0, 592c2c66affSColin Finck CreateFileTypeNone, 593c2c66affSColin Finck NULL, 594c2c66affSColin Finck SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING); 595*2969c28aSPierre Schweitzer /* If we failed, relax a bit constraints, someone may be already holding the 596*2969c28aSPierre Schweitzer * the file, so share write, don't attempt to replace and don't delete on close 597*2969c28aSPierre Schweitzer * (basically, don't do anything conflicting) 598*2969c28aSPierre Schweitzer */ 599*2969c28aSPierre Schweitzer if (!NT_SUCCESS(Status)) 600*2969c28aSPierre Schweitzer { 601*2969c28aSPierre Schweitzer Status = IoCreateFile(&FileHandle, 602*2969c28aSPierre Schweitzer SYNCHRONIZE | FILE_WRITE_DATA, 603*2969c28aSPierre Schweitzer &ObjectAttributes, 604*2969c28aSPierre Schweitzer &IoStatus, 605*2969c28aSPierre Schweitzer &AllocationSize, 606*2969c28aSPierre Schweitzer FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 607*2969c28aSPierre Schweitzer FILE_SHARE_WRITE | FILE_SHARE_READ, 608*2969c28aSPierre Schweitzer FILE_OPEN, 609*2969c28aSPierre Schweitzer FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING, 610*2969c28aSPierre Schweitzer NULL, 611*2969c28aSPierre Schweitzer 0, 612*2969c28aSPierre Schweitzer CreateFileTypeNone, 613*2969c28aSPierre Schweitzer NULL, 614*2969c28aSPierre Schweitzer SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING); 615*2969c28aSPierre Schweitzer } 616c2c66affSColin Finck 617c2c66affSColin Finck ReleaseCapturedUnicodeString(&CapturedFileName, 618c2c66affSColin Finck PreviousMode); 619c2c66affSColin Finck if (!NT_SUCCESS(Status)) 620c2c66affSColin Finck { 621*2969c28aSPierre Schweitzer DPRINT1("Failed creating page file: %lx\n", Status); 622c2c66affSColin Finck return(Status); 623c2c66affSColin Finck } 624c2c66affSColin Finck 625c2c66affSColin Finck Status = ZwQueryVolumeInformationFile(FileHandle, 626c2c66affSColin Finck &IoStatus, 627c2c66affSColin Finck &FsSizeInformation, 628c2c66affSColin Finck sizeof(FILE_FS_SIZE_INFORMATION), 629c2c66affSColin Finck FileFsSizeInformation); 630c2c66affSColin Finck if (!NT_SUCCESS(Status)) 631c2c66affSColin Finck { 632c2c66affSColin Finck ZwClose(FileHandle); 633c2c66affSColin Finck return Status; 634c2c66affSColin Finck } 635c2c66affSColin Finck 636c2c66affSColin Finck BytesPerAllocationUnit = FsSizeInformation.SectorsPerAllocationUnit * 637c2c66affSColin Finck FsSizeInformation.BytesPerSector; 638c2c66affSColin Finck 639*2969c28aSPierre Schweitzer /* Set its end of file to initial size */ 640c2c66affSColin Finck Status = ZwSetInformationFile(FileHandle, 641c2c66affSColin Finck &IoStatus, 642c2c66affSColin Finck &SafeInitialSize, 643c2c66affSColin Finck sizeof(LARGE_INTEGER), 644*2969c28aSPierre Schweitzer FileEndOfFileInformation); 645*2969c28aSPierre Schweitzer if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStatus.Status)) 646c2c66affSColin Finck { 647c2c66affSColin Finck ZwClose(FileHandle); 648c2c66affSColin Finck return(Status); 649c2c66affSColin Finck } 650c2c66affSColin Finck 651c2c66affSColin Finck Status = ObReferenceObjectByHandle(FileHandle, 652c2c66affSColin Finck FILE_ALL_ACCESS, 653c2c66affSColin Finck IoFileObjectType, 654c2c66affSColin Finck KernelMode, 655c2c66affSColin Finck (PVOID*)&FileObject, 656c2c66affSColin Finck NULL); 657c2c66affSColin Finck if (!NT_SUCCESS(Status)) 658c2c66affSColin Finck { 659c2c66affSColin Finck ZwClose(FileHandle); 660c2c66affSColin Finck return(Status); 661c2c66affSColin Finck } 662c2c66affSColin Finck 663c2c66affSColin Finck CurrentRetDescList = RetDescList = MmAllocRetrievelDescriptorList(PAIRS_PER_RUN); 664c2c66affSColin Finck 665c2c66affSColin Finck if (CurrentRetDescList == NULL) 666c2c66affSColin Finck { 667c2c66affSColin Finck ObDereferenceObject(FileObject); 668c2c66affSColin Finck ZwClose(FileHandle); 669c2c66affSColin Finck return(STATUS_NO_MEMORY); 670c2c66affSColin Finck } 671c2c66affSColin Finck 672c2c66affSColin Finck #if defined(__GNUC__) 673c2c66affSColin Finck Vcn.QuadPart = 0LL; 674c2c66affSColin Finck #else 675c2c66affSColin Finck 676c2c66affSColin Finck Vcn.QuadPart = 0; 677c2c66affSColin Finck #endif 678c2c66affSColin Finck 679c2c66affSColin Finck ExtentCount = 0; 680c2c66affSColin Finck MaxVcn.QuadPart = (SafeInitialSize.QuadPart + BytesPerAllocationUnit - 1) / BytesPerAllocationUnit; 681c2c66affSColin Finck while(1) 682c2c66affSColin Finck { 683c2c66affSColin Finck Status = ZwFsControlFile(FileHandle, 684c2c66affSColin Finck 0, 685c2c66affSColin Finck NULL, 686c2c66affSColin Finck NULL, 687c2c66affSColin Finck &IoStatus, 688c2c66affSColin Finck FSCTL_GET_RETRIEVAL_POINTERS, 689c2c66affSColin Finck &Vcn, 690c2c66affSColin Finck sizeof(LARGE_INTEGER), 691c2c66affSColin Finck &CurrentRetDescList->RetrievalPointers, 692c2c66affSColin Finck sizeof(RETRIEVAL_POINTERS_BUFFER) + PAIRS_PER_RUN * 2 * sizeof(LARGE_INTEGER)); 693c2c66affSColin Finck if (!NT_SUCCESS(Status)) 694c2c66affSColin Finck { 695c2c66affSColin Finck while (RetDescList) 696c2c66affSColin Finck { 697c2c66affSColin Finck CurrentRetDescList = RetDescList; 698c2c66affSColin Finck RetDescList = RetDescList->Next; 699c2c66affSColin Finck ExFreePool(CurrentRetDescList); 700c2c66affSColin Finck } 701c2c66affSColin Finck ObDereferenceObject(FileObject); 702c2c66affSColin Finck ZwClose(FileHandle); 703c2c66affSColin Finck return(Status); 704c2c66affSColin Finck } 705c2c66affSColin Finck ExtentCount += CurrentRetDescList->RetrievalPointers.ExtentCount; 706c2c66affSColin Finck if (CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn.QuadPart < MaxVcn.QuadPart) 707c2c66affSColin Finck { 708c2c66affSColin Finck CurrentRetDescList->Next = MmAllocRetrievelDescriptorList(PAIRS_PER_RUN); 709c2c66affSColin Finck if (CurrentRetDescList->Next == NULL) 710c2c66affSColin Finck { 711c2c66affSColin Finck while (RetDescList) 712c2c66affSColin Finck { 713c2c66affSColin Finck CurrentRetDescList = RetDescList; 714c2c66affSColin Finck RetDescList = RetDescList->Next; 715c2c66affSColin Finck ExFreePool(CurrentRetDescList); 716c2c66affSColin Finck } 717c2c66affSColin Finck ObDereferenceObject(FileObject); 718c2c66affSColin Finck ZwClose(FileHandle); 719c2c66affSColin Finck return(STATUS_NO_MEMORY); 720c2c66affSColin Finck } 721c2c66affSColin Finck Vcn = CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn; 722c2c66affSColin Finck CurrentRetDescList = CurrentRetDescList->Next; 723c2c66affSColin Finck } 724c2c66affSColin Finck else 725c2c66affSColin Finck { 726c2c66affSColin Finck break; 727c2c66affSColin Finck } 728c2c66affSColin Finck } 729c2c66affSColin Finck 730c2c66affSColin Finck PagingFile = ExAllocatePool(NonPagedPool, sizeof(*PagingFile)); 731c2c66affSColin Finck if (PagingFile == NULL) 732c2c66affSColin Finck { 733c2c66affSColin Finck while (RetDescList) 734c2c66affSColin Finck { 735c2c66affSColin Finck CurrentRetDescList = RetDescList; 736c2c66affSColin Finck RetDescList = RetDescList->Next; 737c2c66affSColin Finck ExFreePool(CurrentRetDescList); 738c2c66affSColin Finck } 739c2c66affSColin Finck ObDereferenceObject(FileObject); 740c2c66affSColin Finck ZwClose(FileHandle); 741c2c66affSColin Finck return(STATUS_NO_MEMORY); 742c2c66affSColin Finck } 743c2c66affSColin Finck 744c2c66affSColin Finck RtlZeroMemory(PagingFile, sizeof(*PagingFile)); 745c2c66affSColin Finck 746*2969c28aSPierre Schweitzer PagingFile->FileHandle = FileHandle; 747c2c66affSColin Finck PagingFile->FileObject = FileObject; 748c2c66affSColin Finck PagingFile->MaximumSize.QuadPart = SafeMaximumSize.QuadPart; 749c2c66affSColin Finck PagingFile->CurrentSize.QuadPart = SafeInitialSize.QuadPart; 750c2c66affSColin Finck PagingFile->FreePages = (ULONG)(SafeInitialSize.QuadPart / PAGE_SIZE); 751c2c66affSColin Finck PagingFile->UsedPages = 0; 752c2c66affSColin Finck KeInitializeSpinLock(&PagingFile->AllocMapLock); 753c2c66affSColin Finck 754c2c66affSColin Finck AllocMapSize = (PagingFile->FreePages / 32) + 1; 755c2c66affSColin Finck PagingFile->AllocMap = ExAllocatePool(NonPagedPool, 756c2c66affSColin Finck AllocMapSize * sizeof(ULONG)); 757c2c66affSColin Finck PagingFile->AllocMapSize = AllocMapSize; 758c2c66affSColin Finck 759c2c66affSColin Finck if (PagingFile->AllocMap == NULL) 760c2c66affSColin Finck { 761c2c66affSColin Finck while (RetDescList) 762c2c66affSColin Finck { 763c2c66affSColin Finck CurrentRetDescList = RetDescList; 764c2c66affSColin Finck RetDescList = RetDescList->Next; 765c2c66affSColin Finck ExFreePool(CurrentRetDescList); 766c2c66affSColin Finck } 767c2c66affSColin Finck ExFreePool(PagingFile); 768c2c66affSColin Finck ObDereferenceObject(FileObject); 769c2c66affSColin Finck ZwClose(FileHandle); 770c2c66affSColin Finck return(STATUS_NO_MEMORY); 771c2c66affSColin Finck } 772c2c66affSColin Finck DPRINT("ExtentCount: %lu\n", ExtentCount); 773c2c66affSColin Finck Size = sizeof(RETRIEVAL_POINTERS_BUFFER) + ExtentCount * 2 * sizeof(LARGE_INTEGER); 774c2c66affSColin Finck PagingFile->RetrievalPointers = ExAllocatePool(NonPagedPool, Size); 775c2c66affSColin Finck if (PagingFile->RetrievalPointers == NULL) 776c2c66affSColin Finck { 777c2c66affSColin Finck while (RetDescList) 778c2c66affSColin Finck { 779c2c66affSColin Finck CurrentRetDescList = RetDescList; 780c2c66affSColin Finck RetDescList = RetDescList->Next; 781c2c66affSColin Finck ExFreePool(CurrentRetDescList); 782c2c66affSColin Finck } 783c2c66affSColin Finck ExFreePool(PagingFile->AllocMap); 784c2c66affSColin Finck ExFreePool(PagingFile); 785c2c66affSColin Finck ObDereferenceObject(FileObject); 786c2c66affSColin Finck ZwClose(FileHandle); 787c2c66affSColin Finck return(STATUS_NO_MEMORY); 788c2c66affSColin Finck } 789c2c66affSColin Finck 790c2c66affSColin Finck RtlZeroMemory(PagingFile->AllocMap, AllocMapSize * sizeof(ULONG)); 791c2c66affSColin Finck RtlZeroMemory(PagingFile->RetrievalPointers, Size); 792c2c66affSColin Finck 793c2c66affSColin Finck Count = 0; 794c2c66affSColin Finck PagingFile->RetrievalPointers->ExtentCount = ExtentCount; 795c2c66affSColin Finck PagingFile->RetrievalPointers->StartingVcn = RetDescList->RetrievalPointers.StartingVcn; 796c2c66affSColin Finck CurrentRetDescList = RetDescList; 797c2c66affSColin Finck while (CurrentRetDescList) 798c2c66affSColin Finck { 799c2c66affSColin Finck memcpy(&PagingFile->RetrievalPointers->Extents[Count], 800c2c66affSColin Finck CurrentRetDescList->RetrievalPointers.Extents, 801c2c66affSColin Finck CurrentRetDescList->RetrievalPointers.ExtentCount * 2 * sizeof(LARGE_INTEGER)); 802c2c66affSColin Finck Count += CurrentRetDescList->RetrievalPointers.ExtentCount; 803c2c66affSColin Finck RetDescList = CurrentRetDescList; 804c2c66affSColin Finck CurrentRetDescList = CurrentRetDescList->Next; 805c2c66affSColin Finck ExFreePool(RetDescList); 806c2c66affSColin Finck } 807c2c66affSColin Finck 808c2c66affSColin Finck if (PagingFile->RetrievalPointers->ExtentCount != ExtentCount || 809c2c66affSColin Finck PagingFile->RetrievalPointers->Extents[ExtentCount - 1].NextVcn.QuadPart != MaxVcn.QuadPart) 810c2c66affSColin Finck { 811c2c66affSColin Finck ExFreePool(PagingFile->RetrievalPointers); 812c2c66affSColin Finck ExFreePool(PagingFile->AllocMap); 813c2c66affSColin Finck ExFreePool(PagingFile); 814c2c66affSColin Finck ObDereferenceObject(FileObject); 815c2c66affSColin Finck ZwClose(FileHandle); 816c2c66affSColin Finck return(STATUS_UNSUCCESSFUL); 817c2c66affSColin Finck } 818c2c66affSColin Finck 819c2c66affSColin Finck /* 820c2c66affSColin Finck * Change the entries from lcn's to volume offset's. 821c2c66affSColin Finck */ 822c2c66affSColin Finck PagingFile->RetrievalPointers->StartingVcn.QuadPart *= BytesPerAllocationUnit; 823c2c66affSColin Finck for (i = 0; i < ExtentCount; i++) 824c2c66affSColin Finck { 825c2c66affSColin Finck PagingFile->RetrievalPointers->Extents[i].Lcn.QuadPart *= BytesPerAllocationUnit; 826c2c66affSColin Finck PagingFile->RetrievalPointers->Extents[i].NextVcn.QuadPart *= BytesPerAllocationUnit; 827c2c66affSColin Finck } 828c2c66affSColin Finck 829c2c66affSColin Finck KeAcquireSpinLock(&PagingFileListLock, &oldIrql); 830c2c66affSColin Finck for (i = 0; i < MAX_PAGING_FILES; i++) 831c2c66affSColin Finck { 832c2c66affSColin Finck if (PagingFileList[i] == NULL) 833c2c66affSColin Finck { 834c2c66affSColin Finck PagingFileList[i] = PagingFile; 835c2c66affSColin Finck break; 836c2c66affSColin Finck } 837c2c66affSColin Finck } 838c2c66affSColin Finck MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages; 839c2c66affSColin Finck MmNumberOfPagingFiles++; 840c2c66affSColin Finck KeReleaseSpinLock(&PagingFileListLock, oldIrql); 841c2c66affSColin Finck 842c2c66affSColin Finck MmSwapSpaceMessage = FALSE; 843c2c66affSColin Finck 844c2c66affSColin Finck return(STATUS_SUCCESS); 845c2c66affSColin Finck } 846c2c66affSColin Finck 847c2c66affSColin Finck /* EOF */ 848