3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/pagefile.c
6 * PURPOSE: Paging file functions
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* TYPES *********************************************************************/
19 typedef struct _PAGINGFILE
21 LIST_ENTRY PagingFileListEntry
;
22 PFILE_OBJECT FileObject
;
23 LARGE_INTEGER MaximumSize
;
24 LARGE_INTEGER CurrentSize
;
28 KSPIN_LOCK AllocMapLock
;
30 PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
32 PAGINGFILE
, *PPAGINGFILE
;
34 typedef struct _RETRIEVEL_DESCRIPTOR_LIST
36 struct _RETRIEVEL_DESCRIPTOR_LIST
* Next
;
37 GET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
39 RETRIEVEL_DESCRIPTOR_LIST
, *PRETRIEVEL_DESCRIPTOR_LIST
;
41 /* GLOBALS *******************************************************************/
43 #define PAIRS_PER_RUN (1024)
45 #define MAX_PAGING_FILES (32)
47 /* List of paging files, both used and free */
48 static PPAGINGFILE PagingFileList
[MAX_PAGING_FILES
];
50 /* Lock for examining the list of paging files */
51 static KSPIN_LOCK PagingFileListLock
;
53 /* Number of paging files */
54 static ULONG MiPagingFileCount
;
56 /* Number of pages that are available for swapping */
57 ULONG MiFreeSwapPages
;
59 /* Number of pages that have been allocated for swapping */
60 ULONG MiUsedSwapPages
;
63 * Number of pages that have been reserved for swapping but not yet allocated
65 static ULONG MiReservedSwapPages
;
68 * Ratio between reserved and available swap pages, e.g. setting this to five
69 * forces one swap page to be available for every five swap pages that are
70 * reserved. Setting this to zero turns off commit checking altogether.
72 #define MM_PAGEFILE_COMMIT_RATIO (1)
75 * Number of pages that can be used for potentially swapable memory without
76 * pagefile space being reserved. The intention is that this allows smss
77 * to start up and create page files while ordinarily having a commit
80 #define MM_PAGEFILE_COMMIT_GRACE (256)
82 static PVOID MmCoreDumpPageFrame
= NULL
;
83 static ULONG MmCoreDumpSize
;
84 static DUMP_POINTERS MmCoreDumpPointers
;
85 static PMM_CORE_DUMP_FUNCTIONS MmCoreDumpFunctions
;
86 static ULONG MmCoreDumpPageFile
= 0xFFFFFFFF;
87 static ROS_QUERY_LCN_MAPPING MmCoreDumpLcnMapping
;
89 ULONG MmCoreDumpType
= MM_CORE_DUMP_TYPE_NONE
;
92 * Translate between a swap entry and a file and offset pair.
94 #define FILE_FROM_ENTRY(i) ((i) >> 24)
95 #define OFFSET_FROM_ENTRY(i) (((i) & 0xffffff) - 1)
96 #define ENTRY_FROM_FILE_OFFSET(i, j) (((i) << 24) | ((j) + 1))
98 static BOOLEAN MmSwapSpaceMessage
= FALSE
;
100 /* FUNCTIONS *****************************************************************/
103 MmShowOutOfSpaceMessagePagingFile(VOID
)
105 if (!MmSwapSpaceMessage
)
107 DPRINT1("MM: Out of swap space.\n");
108 MmSwapSpaceMessage
= TRUE
;
113 MmGetOffsetPageFile(PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
, LARGE_INTEGER Offset
)
115 /* Simple binary search */
116 ULONG first
, last
, mid
;
118 last
= RetrievalPointers
->NumberOfPairs
- 1;
119 while (first
<= last
)
121 mid
= (last
- first
) / 2 + first
;
122 if ((ULONGLONG
) Offset
.QuadPart
< RetrievalPointers
->Pair
[mid
].Vcn
)
126 Offset
.QuadPart
+= RetrievalPointers
->Pair
[0].Lcn
- RetrievalPointers
->StartVcn
;
131 if ((ULONGLONG
) Offset
.QuadPart
>= RetrievalPointers
->Pair
[mid
-1].Vcn
)
133 Offset
.QuadPart
+= RetrievalPointers
->Pair
[mid
].Lcn
- RetrievalPointers
->Pair
[mid
-1].Vcn
;
141 if (mid
== RetrievalPointers
->NumberOfPairs
- 1)
145 if ((ULONGLONG
) Offset
.QuadPart
< RetrievalPointers
->Pair
[mid
+1].Vcn
)
147 Offset
.QuadPart
+= RetrievalPointers
->Pair
[mid
+1].Lcn
- RetrievalPointers
->Pair
[mid
].Vcn
;
154 #if defined(__GNUC__)
156 return (LARGE_INTEGER
)0LL;
160 const LARGE_INTEGER dummy
=
169 NTSTATUS
MmWriteToSwapPage(SWAPENTRY SwapEntry
, PFN_TYPE Page
)
172 LARGE_INTEGER file_offset
;
173 IO_STATUS_BLOCK Iosb
;
176 UCHAR MdlBase
[sizeof(MDL
) + sizeof(ULONG
)];
177 PMDL Mdl
= (PMDL
)MdlBase
;
179 DPRINT("MmWriteToSwapPage\n");
184 return(STATUS_UNSUCCESSFUL
);
187 i
= FILE_FROM_ENTRY(SwapEntry
);
188 offset
= OFFSET_FROM_ENTRY(SwapEntry
);
190 if (i
>= MAX_PAGING_FILES
)
192 DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry
);
195 if (PagingFileList
[i
]->FileObject
== NULL
||
196 PagingFileList
[i
]->FileObject
->DeviceObject
== NULL
)
198 DPRINT1("Bad paging file 0x%.8X\n", SwapEntry
);
202 MmInitializeMdl(Mdl
, NULL
, PAGE_SIZE
);
203 MmBuildMdlFromPages(Mdl
, &Page
);
205 file_offset
.QuadPart
= offset
* PAGE_SIZE
;
206 file_offset
= MmGetOffsetPageFile(PagingFileList
[i
]->RetrievalPointers
, file_offset
);
208 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
209 Status
= IoPageWrite(PagingFileList
[i
]->FileObject
,
214 if (Status
== STATUS_PENDING
)
216 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
217 Status
= Iosb
.Status
;
219 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
223 NTSTATUS
MmReadFromSwapPage(SWAPENTRY SwapEntry
, PFN_TYPE Page
)
226 LARGE_INTEGER file_offset
;
227 IO_STATUS_BLOCK Iosb
;
230 UCHAR MdlBase
[sizeof(MDL
) + sizeof(ULONG
)];
231 PMDL Mdl
= (PMDL
)MdlBase
;
233 DPRINT("MmReadFromSwapPage\n");
238 return(STATUS_UNSUCCESSFUL
);
241 i
= FILE_FROM_ENTRY(SwapEntry
);
242 offset
= OFFSET_FROM_ENTRY(SwapEntry
);
244 if (i
>= MAX_PAGING_FILES
)
246 DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry
);
249 if (PagingFileList
[i
]->FileObject
== NULL
||
250 PagingFileList
[i
]->FileObject
->DeviceObject
== NULL
)
252 DPRINT1("Bad paging file 0x%.8X\n", SwapEntry
);
256 MmInitializeMdl(Mdl
, NULL
, PAGE_SIZE
);
257 MmBuildMdlFromPages(Mdl
, &Page
);
259 file_offset
.QuadPart
= offset
* PAGE_SIZE
;
260 file_offset
= MmGetOffsetPageFile(PagingFileList
[i
]->RetrievalPointers
, file_offset
);
262 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
263 Status
= IoPageRead(PagingFileList
[i
]->FileObject
,
268 if (Status
== STATUS_PENDING
)
270 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
271 Status
= Iosb
.Status
;
273 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
278 MmInitPagingFile(VOID
)
282 KeInitializeSpinLock(&PagingFileListLock
);
286 MiReservedSwapPages
= 0;
288 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
290 PagingFileList
[i
] = NULL
;
292 MiPagingFileCount
= 0;
295 * Initialize the crash dump support.
297 if (MmCoreDumpType
!= MM_CORE_DUMP_TYPE_NONE
)
299 MmCoreDumpPageFrame
= MmAllocateSection(PAGE_SIZE
, NULL
);
300 if (MmCoreDumpType
== MM_CORE_DUMP_TYPE_FULL
)
302 MmCoreDumpSize
= MmStats
.NrTotalPages
* 4096 + 1024 * 1024;
306 MmCoreDumpSize
= 1024 * 1024;
312 MmReserveSwapPages(ULONG Nr
)
315 ULONG MiAvailSwapPages
;
317 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
319 (MiFreeSwapPages
* MM_PAGEFILE_COMMIT_RATIO
) + MM_PAGEFILE_COMMIT_GRACE
;
320 MiReservedSwapPages
= MiReservedSwapPages
+ Nr
;
321 if (MM_PAGEFILE_COMMIT_RATIO
!= 0 && MiAvailSwapPages
< MiReservedSwapPages
)
323 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
326 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
331 MmDereserveSwapPages(ULONG Nr
)
335 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
336 MiReservedSwapPages
= MiReservedSwapPages
- Nr
;
337 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
341 MiAllocPageFromPagingFile(PPAGINGFILE PagingFile
)
346 KeAcquireSpinLock(&PagingFile
->AllocMapLock
, &oldIrql
);
348 for (i
= 0; i
< PagingFile
->AllocMapSize
; i
++)
350 for (j
= 0; j
< 32; j
++)
352 if (!(PagingFile
->AllocMap
[i
] & (1 << j
)))
354 PagingFile
->AllocMap
[i
] |= (1 << j
);
355 PagingFile
->UsedPages
++;
356 PagingFile
->FreePages
--;
357 KeReleaseSpinLock(&PagingFile
->AllocMapLock
, oldIrql
);
358 return((i
* 32) + j
);
363 KeReleaseSpinLock(&PagingFile
->AllocMapLock
, oldIrql
);
368 MmFreeSwapPage(SWAPENTRY Entry
)
374 i
= FILE_FROM_ENTRY(Entry
);
375 off
= OFFSET_FROM_ENTRY(Entry
);
377 if (i
>= MAX_PAGING_FILES
)
379 DPRINT1("Bad swap entry 0x%.8X\n", Entry
);
383 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
384 if (PagingFileList
[i
] == NULL
)
388 KeAcquireSpinLockAtDpcLevel(&PagingFileList
[i
]->AllocMapLock
);
390 PagingFileList
[i
]->AllocMap
[off
>> 5] &= (~(1 << (off
% 32)));
392 PagingFileList
[i
]->FreePages
++;
393 PagingFileList
[i
]->UsedPages
--;
398 KeReleaseSpinLockFromDpcLevel(&PagingFileList
[i
]->AllocMapLock
);
399 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
403 MmIsAvailableSwapPage(VOID
)
405 return(MiFreeSwapPages
> 0);
409 MmAllocSwapPage(VOID
)
416 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
418 if (MiFreeSwapPages
== 0)
420 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
424 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
426 if (PagingFileList
[i
] != NULL
&&
427 PagingFileList
[i
]->FreePages
>= 1)
429 off
= MiAllocPageFromPagingFile(PagingFileList
[i
]);
430 if (off
== 0xFFFFFFFF)
433 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
434 return(STATUS_UNSUCCESSFUL
);
438 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
440 entry
= ENTRY_FROM_FILE_OFFSET(i
, off
);
445 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
450 STATIC PRETRIEVEL_DESCRIPTOR_LIST FASTCALL
451 MmAllocRetrievelDescriptorList(ULONG Pairs
)
454 PRETRIEVEL_DESCRIPTOR_LIST RetDescList
;
456 Size
= sizeof(RETRIEVEL_DESCRIPTOR_LIST
) + Pairs
* sizeof(MAPPING_PAIR
);
457 RetDescList
= ExAllocatePool(NonPagedPool
, Size
);
460 RtlZeroMemory(RetDescList
, Size
);
467 MmDumpToPagingFile(ULONG BugCode
,
468 ULONG BugCodeParameter1
,
469 ULONG BugCodeParameter2
,
470 ULONG BugCodeParameter3
,
471 ULONG BugCodeParameter4
,
472 PKTRAP_FRAME TrapFrame
)
474 PMM_CORE_DUMP_HEADER Headers
;
476 UCHAR MdlBase
[sizeof(MDL
) + sizeof(ULONG
)];
477 PMDL Mdl
= (PMDL
)MdlBase
;
478 PETHREAD Thread
= PsGetCurrentThread();
481 LONGLONG NextOffset
= 0;
483 PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
484 LARGE_INTEGER DiskOffset
;
486 if (MmCoreDumpPageFile
== 0xFFFFFFFF)
488 return(STATUS_UNSUCCESSFUL
);
491 DbgPrint("\nMM: Dumping core: ");
493 /* Prepare the dump headers. */
494 Headers
= (PMM_CORE_DUMP_HEADER
)MmCoreDumpPageFrame
;
495 Headers
->Magic
= MM_CORE_DUMP_HEADER_MAGIC
;
496 Headers
->Version
= MM_CORE_DUMP_HEADER_VERSION
;
497 Headers
->Type
= MmCoreDumpType
;
498 if (TrapFrame
!= NULL
)
500 if (!(TrapFrame
->Eflags
& (1 << 17)))
502 memcpy(&Headers
->TrapFrame
, TrapFrame
,
503 sizeof(KTRAP_FRAME
) - (4 * sizeof(DWORD
)));
507 memcpy(&Headers
->TrapFrame
, TrapFrame
, sizeof(KTRAP_FRAME
));
510 Headers
->BugCheckCode
= BugCode
;
511 Headers
->BugCheckParameters
[0] = BugCodeParameter1
;
512 Headers
->BugCheckParameters
[1] = BugCodeParameter2
;
513 Headers
->BugCheckParameters
[2] = BugCodeParameter3
;
514 Headers
->BugCheckParameters
[3] = BugCodeParameter4
;
515 Headers
->FaultingStackBase
= (PVOID
)Thread
->Tcb
.StackLimit
;
516 Headers
->FaultingStackSize
=
517 StackSize
= (ULONG_PTR
)Thread
->Tcb
.StackBase
- (ULONG_PTR
)Thread
->Tcb
.StackLimit
;
518 Headers
->PhysicalMemorySize
= MmStats
.NrTotalPages
* PAGE_SIZE
;
520 /* Initialize the dump device. */
521 Status
= MmCoreDumpFunctions
->DumpInit();
522 if (!NT_SUCCESS(Status
))
524 DPRINT1("MM: Failed to initialize core dump device.\n");
528 /* Initialize the MDL. */
529 MmInitializeMdl(Mdl
, MmCoreDumpPageFrame
, PAGE_SIZE
);
530 Mdl
->MdlFlags
= MDL_PAGES_LOCKED
|MDL_IO_PAGE_READ
|MDL_SOURCE_IS_NONPAGED_POOL
;
531 MdlMap
= (PULONG
)(Mdl
+ 1);
534 /* Initialize the retrieval offsets. */
535 RetrievalPointers
= PagingFileList
[MmCoreDumpPageFile
]->RetrievalPointers
;
537 /* Dump the header. */
538 MdlMap
[0] = MmGetPhysicalAddress(MmCoreDumpPageFrame
).QuadPart
>> PAGE_SHIFT
;
539 #if defined(__GNUC__)
541 DiskOffset
= MmGetOffsetPageFile(RetrievalPointers
, (LARGE_INTEGER
)0LL);
545 const LARGE_INTEGER dummy
=
549 DiskOffset
= MmGetOffsetPageFile(RetrievalPointers
, dummy
);
552 DiskOffset
.QuadPart
+= MmCoreDumpLcnMapping
.LcnDiskOffset
.QuadPart
;
553 Status
= MmCoreDumpFunctions
->DumpWrite(DiskOffset
, Mdl
);
554 if (!NT_SUCCESS(Status
))
556 DPRINT1("MM: Failed to write core dump header\n.");
559 NextOffset
+= PAGE_SIZE
;
564 /* Write out the contents of physical memory. */
565 if (MmCoreDumpType
== MM_CORE_DUMP_TYPE_FULL
)
567 for (i
= 0; i
< MmStats
.NrTotalPages
; i
++)
570 MmCreateVirtualMappingForKernel(MmCoreDumpPageFrame
,
574 #if defined(__GNUC__)
576 DiskOffset
= MmGetOffsetPageFile(RetrievalPointers
,
577 (LARGE_INTEGER
)NextOffset
);
582 dummy
.QuadPart
= NextOffset
;
583 DiskOffset
= MmGetOffsetPageFile(RetrievalPointers
, dummy
);
586 DiskOffset
.QuadPart
+= MmCoreDumpLcnMapping
.LcnDiskOffset
.QuadPart
;
587 Status
= MmCoreDumpFunctions
->DumpWrite(DiskOffset
, Mdl
);
588 MmRawDeleteVirtualMapping(MmCoreDumpPageFrame
);
589 if (!NT_SUCCESS(Status
))
591 DPRINT1("MM: Failed to write page to core dump.\n");
594 if ((i
% ((1024*1024) / PAGE_SIZE
)) == 0)
596 DbgPrint("\b\b%.2d", i
/ ((1024*1024)/PAGE_SIZE
));
598 NextOffset
+= PAGE_SIZE
;
603 MmCoreDumpFunctions
->DumpFinish();
604 return(STATUS_SUCCESS
);
608 MmInitializeCrashDump(HANDLE PageFileHandle
, ULONG PageFileNum
)
610 PFILE_OBJECT PageFile
;
611 PDEVICE_OBJECT PageFileDevice
;
615 IO_STATUS_BLOCK Iosb
;
616 UNICODE_STRING DiskDumpName
;
617 ANSI_STRING ProcName
;
618 PIO_STACK_LOCATION StackPtr
;
619 PMODULE_OBJECT ModuleObject
;
621 Status
= ZwFsControlFile(PageFileHandle
,
626 FSCTL_ROS_QUERY_LCN_MAPPING
,
629 &MmCoreDumpLcnMapping
,
630 sizeof(ROS_QUERY_LCN_MAPPING
));
631 if (!NT_SUCCESS(Status
) ||
632 Iosb
.Information
!= sizeof(ROS_QUERY_LCN_MAPPING
))
637 /* Get the underlying storage device. */
639 ObReferenceObjectByHandle(PageFileHandle
,
645 if (!NT_SUCCESS(Status
))
650 PageFileDevice
= PageFile
->Vpb
->RealDevice
;
652 /* Get the dump pointers. */
653 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
654 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_DUMP_POINTERS
,
659 sizeof(MmCoreDumpPointers
),
665 ObDereferenceObject(PageFile
);
666 return(STATUS_NO_MEMORY
);// tMk - is this correct return code ???
669 StackPtr
= IoGetNextIrpStackLocation(Irp
);
670 StackPtr
->FileObject
= PageFile
;
671 StackPtr
->DeviceObject
= PageFileDevice
;
672 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
673 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
= sizeof(MmCoreDumpPointers
);
675 Status
= IoCallDriver(PageFileDevice
,Irp
);
676 if (Status
== STATUS_PENDING
)
678 Status
= KeWaitForSingleObject(&Event
,
684 if (Status
!= STATUS_SUCCESS
||
685 Iosb
.Information
!= sizeof(MmCoreDumpPointers
))
687 ObDereferenceObject(PageFile
);
691 /* Load the diskdump driver. */
692 RtlRosInitUnicodeStringFromLiteral(&DiskDumpName
, L
"DiskDump");
693 ModuleObject
= LdrGetModuleObject(&DiskDumpName
);
694 if (ModuleObject
== NULL
)
696 return(STATUS_OBJECT_NAME_NOT_FOUND
);
698 RtlInitAnsiString(&ProcName
, "DiskDumpFunctions");
699 Status
= LdrGetProcedureAddress(ModuleObject
->Base
,
702 (PVOID
*)&MmCoreDumpFunctions
);
703 if (!NT_SUCCESS(Status
))
705 ObDereferenceObject(PageFile
);
709 /* Prepare for disk dumping. */
710 Status
= MmCoreDumpFunctions
->DumpPrepare(PageFileDevice
,
711 &MmCoreDumpPointers
);
712 if (!NT_SUCCESS(Status
))
714 ObDereferenceObject(PageFile
);
718 MmCoreDumpPageFile
= PageFileNum
;
719 ObDereferenceObject(PageFile
);
720 return(STATUS_SUCCESS
);
724 NtCreatePagingFile(IN PUNICODE_STRING FileName
,
725 IN PLARGE_INTEGER InitialSize
,
726 IN PLARGE_INTEGER MaximumSize
,
730 OBJECT_ATTRIBUTES ObjectAttributes
;
732 IO_STATUS_BLOCK IoStatus
;
733 PFILE_OBJECT FileObject
;
734 PPAGINGFILE PagingFile
;
737 FILE_FS_SIZE_INFORMATION FsSizeInformation
;
738 PRETRIEVEL_DESCRIPTOR_LIST RetDescList
;
739 PRETRIEVEL_DESCRIPTOR_LIST CurrentRetDescList
;
741 ULONG BytesPerAllocationUnit
;
747 KPROCESSOR_MODE PreviousMode
;
748 UNICODE_STRING CapturedFileName
;
749 LARGE_INTEGER SafeInitialSize
, SafeMaximumSize
;
751 DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n",
752 FileName
, InitialSize
->QuadPart
);
754 if (MiPagingFileCount
>= MAX_PAGING_FILES
)
756 return(STATUS_TOO_MANY_PAGING_FILES
);
759 PreviousMode
= ExGetPreviousMode();
760 Status
= RtlCaptureUnicodeString(&CapturedFileName
,
765 if (!NT_SUCCESS(Status
))
769 if (PreviousMode
== UserMode
)
773 ProbeForRead(InitialSize
,
774 sizeof(LARGE_INTEGER
),
776 SafeInitialSize
= *InitialSize
;
777 ProbeForRead(MaximumSize
,
778 sizeof(LARGE_INTEGER
),
780 SafeMaximumSize
= *MaximumSize
;
784 Status
= _SEH_GetExceptionCode();
788 if (!NT_SUCCESS(Status
))
795 SafeInitialSize
= *InitialSize
;
796 SafeMaximumSize
= *MaximumSize
;
799 InitializeObjectAttributes(&ObjectAttributes
,
805 Status
= IoCreateFile(&FileHandle
,
813 FILE_SYNCHRONOUS_IO_NONALERT
,
818 SL_OPEN_PAGING_FILE
| IO_NO_PARAMETER_CHECKING
);
819 RtlReleaseCapturedUnicodeString(&CapturedFileName
,
822 if (!NT_SUCCESS(Status
))
827 Status
= ZwQueryVolumeInformationFile(FileHandle
,
830 sizeof(FILE_FS_SIZE_INFORMATION
),
831 FileFsSizeInformation
);
832 if (!NT_SUCCESS(Status
))
838 BytesPerAllocationUnit
= FsSizeInformation
.SectorsPerAllocationUnit
* FsSizeInformation
.BytesPerSector
;
839 if (BytesPerAllocationUnit
% PAGE_SIZE
)
842 return STATUS_UNSUCCESSFUL
;
845 Status
= ZwSetInformationFile(FileHandle
,
848 sizeof(LARGE_INTEGER
),
849 FileAllocationInformation
);
850 if (!NT_SUCCESS(Status
))
856 Status
= ObReferenceObjectByHandle(FileHandle
,
862 if (!NT_SUCCESS(Status
))
868 CurrentRetDescList
= RetDescList
= MmAllocRetrievelDescriptorList(PAIRS_PER_RUN
);
870 if (CurrentRetDescList
== NULL
)
872 ObDereferenceObject(FileObject
);
874 return(STATUS_NO_MEMORY
);
877 #if defined(__GNUC__)
885 MaxVcn
= (ULONG
)((SafeInitialSize
.QuadPart
+ BytesPerAllocationUnit
- 1) / BytesPerAllocationUnit
);
888 Status
= ZwFsControlFile(FileHandle
,
893 FSCTL_GET_RETRIEVAL_POINTERS
,
895 sizeof(LARGE_INTEGER
),
896 &CurrentRetDescList
->RetrievalPointers
,
897 sizeof(GET_RETRIEVAL_DESCRIPTOR
) + PAIRS_PER_RUN
* sizeof(MAPPING_PAIR
));
898 if (!NT_SUCCESS(Status
))
902 CurrentRetDescList
= RetDescList
;
903 RetDescList
= RetDescList
->Next
;
904 ExFreePool(CurrentRetDescList
);
906 ObDereferenceObject(FileObject
);
910 ExtentCount
+= CurrentRetDescList
->RetrievalPointers
.NumberOfPairs
;
911 if ((ULONG
)CurrentRetDescList
->RetrievalPointers
.Pair
[CurrentRetDescList
->RetrievalPointers
.NumberOfPairs
-1].Vcn
< MaxVcn
)
913 CurrentRetDescList
->Next
= MmAllocRetrievelDescriptorList(PAIRS_PER_RUN
);
914 if (CurrentRetDescList
->Next
== NULL
)
918 CurrentRetDescList
= RetDescList
;
919 RetDescList
= RetDescList
->Next
;
920 ExFreePool(CurrentRetDescList
);
922 ObDereferenceObject(FileObject
);
924 return(STATUS_NO_MEMORY
);
926 Vcn
.QuadPart
= CurrentRetDescList
->RetrievalPointers
.Pair
[CurrentRetDescList
->RetrievalPointers
.NumberOfPairs
-1].Vcn
;
927 CurrentRetDescList
= CurrentRetDescList
->Next
;
935 PagingFile
= ExAllocatePool(NonPagedPool
, sizeof(*PagingFile
));
936 if (PagingFile
== NULL
)
940 CurrentRetDescList
= RetDescList
;
941 RetDescList
= RetDescList
->Next
;
942 ExFreePool(CurrentRetDescList
);
944 ObDereferenceObject(FileObject
);
946 return(STATUS_NO_MEMORY
);
949 RtlZeroMemory(PagingFile
, sizeof(*PagingFile
));
951 PagingFile
->FileObject
= FileObject
;
952 PagingFile
->MaximumSize
.QuadPart
= SafeMaximumSize
.QuadPart
;
953 PagingFile
->CurrentSize
.QuadPart
= SafeInitialSize
.QuadPart
;
954 PagingFile
->FreePages
= (ULONG
)(SafeInitialSize
.QuadPart
/ PAGE_SIZE
);
955 PagingFile
->UsedPages
= 0;
956 KeInitializeSpinLock(&PagingFile
->AllocMapLock
);
958 AllocMapSize
= (PagingFile
->FreePages
/ 32) + 1;
959 PagingFile
->AllocMap
= ExAllocatePool(NonPagedPool
,
960 AllocMapSize
* sizeof(ULONG
));
961 PagingFile
->AllocMapSize
= AllocMapSize
;
963 if (PagingFile
->AllocMap
== NULL
)
967 CurrentRetDescList
= RetDescList
;
968 RetDescList
= RetDescList
->Next
;
969 ExFreePool(CurrentRetDescList
);
971 ExFreePool(PagingFile
);
972 ObDereferenceObject(FileObject
);
974 return(STATUS_NO_MEMORY
);
976 DPRINT("ExtentCount: %d\n", ExtentCount
);
977 Size
= sizeof(GET_RETRIEVAL_DESCRIPTOR
) + ExtentCount
* sizeof(MAPPING_PAIR
);
978 PagingFile
->RetrievalPointers
= ExAllocatePool(NonPagedPool
, Size
);
979 if (PagingFile
->RetrievalPointers
== NULL
)
983 CurrentRetDescList
= RetDescList
;
984 RetDescList
= RetDescList
->Next
;
985 ExFreePool(CurrentRetDescList
);
987 ExFreePool(PagingFile
->AllocMap
);
988 ExFreePool(PagingFile
);
989 ObDereferenceObject(FileObject
);
991 return(STATUS_NO_MEMORY
);
994 RtlZeroMemory(PagingFile
->AllocMap
, AllocMapSize
* sizeof(ULONG
));
995 RtlZeroMemory(PagingFile
->RetrievalPointers
, Size
);
998 PagingFile
->RetrievalPointers
->NumberOfPairs
= ExtentCount
;
999 PagingFile
->RetrievalPointers
->StartVcn
= RetDescList
->RetrievalPointers
.StartVcn
;
1000 CurrentRetDescList
= RetDescList
;
1001 while (CurrentRetDescList
)
1003 memcpy(&PagingFile
->RetrievalPointers
->Pair
[Count
],
1004 CurrentRetDescList
->RetrievalPointers
.Pair
,
1005 CurrentRetDescList
->RetrievalPointers
.NumberOfPairs
* sizeof(MAPPING_PAIR
));
1006 Count
+= CurrentRetDescList
->RetrievalPointers
.NumberOfPairs
;
1007 RetDescList
= CurrentRetDescList
;
1008 CurrentRetDescList
= CurrentRetDescList
->Next
;
1009 ExFreePool(RetDescList
);
1012 if (PagingFile
->RetrievalPointers
->NumberOfPairs
!= ExtentCount
||
1013 (ULONG
)PagingFile
->RetrievalPointers
->Pair
[ExtentCount
- 1].Vcn
!= MaxVcn
)
1015 ExFreePool(PagingFile
->RetrievalPointers
);
1016 ExFreePool(PagingFile
->AllocMap
);
1017 ExFreePool(PagingFile
);
1018 ObDereferenceObject(FileObject
);
1019 ZwClose(FileHandle
);
1020 return(STATUS_UNSUCCESSFUL
);
1024 * Change the entries from lcn's to volume offset's.
1026 PagingFile
->RetrievalPointers
->StartVcn
*= BytesPerAllocationUnit
;
1027 for (i
= 0; i
< ExtentCount
; i
++)
1029 PagingFile
->RetrievalPointers
->Pair
[i
].Lcn
*= BytesPerAllocationUnit
;
1030 PagingFile
->RetrievalPointers
->Pair
[i
].Vcn
*= BytesPerAllocationUnit
;
1033 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
1034 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
1036 if (PagingFileList
[i
] == NULL
)
1038 PagingFileList
[i
] = PagingFile
;
1042 MiFreeSwapPages
= MiFreeSwapPages
+ PagingFile
->FreePages
;
1043 MiPagingFileCount
++;
1044 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
1046 /* Check whether this pagefile can be a crash dump target. */
1047 if (MmCoreDumpType
!= MM_CORE_DUMP_TYPE_NONE
&&
1048 PagingFile
->CurrentSize
.QuadPart
>= MmCoreDumpSize
&&
1049 MmCoreDumpPageFile
== 0xFFFFFFFF)
1051 MmInitializeCrashDump(FileHandle
, i
);
1053 ZwClose(FileHandle
);
1055 MmSwapSpaceMessage
= FALSE
;
1057 return(STATUS_SUCCESS
);