3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: pagefile.c,v 1.37 2003/10/12 17:05:48 hbirr Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/mm/pagefile.c
23 * PURPOSE: Paging file functions
24 * PROGRAMMER: David Welch (welch@mcmail.com)
29 /* INCLUDES *****************************************************************/
31 #include <ddk/ntddk.h>
32 #include <internal/io.h>
33 #include <internal/mm.h>
34 #include <napi/core.h>
35 #include <internal/ps.h>
36 #include <internal/ldr.h>
39 #include <internal/debug.h>
41 /* TYPES *********************************************************************/
43 typedef struct _PAGINGFILE
45 LIST_ENTRY PagingFileListEntry
;
46 PFILE_OBJECT FileObject
;
47 LARGE_INTEGER MaximumSize
;
48 LARGE_INTEGER CurrentSize
;
52 KSPIN_LOCK AllocMapLock
;
54 PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
55 } PAGINGFILE
, *PPAGINGFILE
;
57 /* GLOBALS *******************************************************************/
59 #define MAX_PAGING_FILES (32)
61 /* List of paging files, both used and free */
62 static PPAGINGFILE PagingFileList
[MAX_PAGING_FILES
];
64 /* Lock for examining the list of paging files */
65 static KSPIN_LOCK PagingFileListLock
;
67 /* Number of paging files */
68 static ULONG MiPagingFileCount
;
70 /* Number of pages that are available for swapping */
71 static ULONG MiFreeSwapPages
;
73 /* Number of pages that have been allocated for swapping */
74 static ULONG MiUsedSwapPages
;
77 * Number of pages that have been reserved for swapping but not yet allocated
79 static ULONG MiReservedSwapPages
;
82 * Ratio between reserved and available swap pages, e.g. setting this to five
83 * forces one swap page to be available for every five swap pages that are
84 * reserved. Setting this to zero turns off commit checking altogether.
86 #define MM_PAGEFILE_COMMIT_RATIO (1)
89 * Number of pages that can be used for potentially swapable memory without
90 * pagefile space being reserved. The intention is that this allows smss
91 * to start up and create page files while ordinarily having a commit
94 #define MM_PAGEFILE_COMMIT_GRACE (256)
96 static PVOID MmCoreDumpPageFrame
= NULL
;
97 static ULONG MmCoreDumpSize
;
98 static DUMP_POINTERS MmCoreDumpPointers
;
99 static PMM_CORE_DUMP_FUNCTIONS MmCoreDumpFunctions
;
100 static ULONG MmCoreDumpPageFile
= 0xFFFFFFFF;
101 static ROS_QUERY_LCN_MAPPING MmCoreDumpLcnMapping
;
103 ULONG MmCoreDumpType
= MM_CORE_DUMP_TYPE_NONE
;
106 * Translate between a swap entry and a file and offset pair.
108 #define FILE_FROM_ENTRY(i) ((i) >> 24)
109 #define OFFSET_FROM_ENTRY(i) (((i) & 0xffffff) - 1)
110 #define ENTRY_FROM_FILE_OFFSET(i, j) (((i) << 24) | ((j) + 1))
112 static BOOLEAN MmSwapSpaceMessage
= FALSE
;
114 /* FUNCTIONS *****************************************************************/
117 MmShowOutOfSpaceMessagePagingFile(VOID
)
119 if (!MmSwapSpaceMessage
)
121 DPRINT1("MM: Out of swap space.\n");
122 MmSwapSpaceMessage
= TRUE
;
126 NTSTATUS
MmWriteToSwapPage(SWAPENTRY SwapEntry
, PMDL Mdl
)
129 LARGE_INTEGER file_offset
;
130 IO_STATUS_BLOCK Iosb
;
133 PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
135 DPRINT("MmWriteToSwapPage\n");
140 return(STATUS_UNSUCCESSFUL
);
143 i
= FILE_FROM_ENTRY(SwapEntry
);
144 offset
= OFFSET_FROM_ENTRY(SwapEntry
);
146 if (i
>= MAX_PAGING_FILES
)
148 DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry
);
151 if (PagingFileList
[i
]->FileObject
== NULL
||
152 PagingFileList
[i
]->FileObject
->DeviceObject
== NULL
)
154 DPRINT1("Bad paging file 0x%.8X\n", SwapEntry
);
158 file_offset
.QuadPart
= offset
* PAGE_SIZE
;
159 RetrievalPointers
= PagingFileList
[i
]->RetrievalPointers
;
161 for (j
= 0; j
< RetrievalPointers
->NumberOfPairs
; j
++)
163 if ((ULONGLONG
) file_offset
.QuadPart
< RetrievalPointers
->Pair
[j
].Vcn
)
167 file_offset
.QuadPart
+= RetrievalPointers
->Pair
[0].Lcn
- RetrievalPointers
->StartVcn
;
171 file_offset
.QuadPart
+= RetrievalPointers
->Pair
[j
].Lcn
- RetrievalPointers
->Pair
[j
-1].Vcn
;
176 if (j
>= RetrievalPointers
->NumberOfPairs
)
182 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
183 Status
= IoPageWrite(PagingFileList
[i
]->FileObject
,
188 if (Status
== STATUS_PENDING
)
190 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
196 NTSTATUS
MmReadFromSwapPage(SWAPENTRY SwapEntry
, PMDL Mdl
)
199 LARGE_INTEGER file_offset
;
200 IO_STATUS_BLOCK Iosb
;
203 PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
205 DPRINT("MmReadFromSwapPage\n");
210 return(STATUS_UNSUCCESSFUL
);
213 i
= FILE_FROM_ENTRY(SwapEntry
);
214 offset
= OFFSET_FROM_ENTRY(SwapEntry
);
216 if (i
>= MAX_PAGING_FILES
)
218 DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry
);
221 if (PagingFileList
[i
]->FileObject
== NULL
||
222 PagingFileList
[i
]->FileObject
->DeviceObject
== NULL
)
224 DPRINT1("Bad paging file 0x%.8X\n", SwapEntry
);
228 file_offset
.QuadPart
= offset
* PAGE_SIZE
;
229 RetrievalPointers
= PagingFileList
[i
]->RetrievalPointers
;
231 for (j
= 0; j
< RetrievalPointers
->NumberOfPairs
; j
++)
233 if ((ULONGLONG
) file_offset
.QuadPart
< RetrievalPointers
->Pair
[j
].Vcn
)
237 file_offset
.QuadPart
+= RetrievalPointers
->Pair
[0].Lcn
- RetrievalPointers
->StartVcn
;
241 file_offset
.QuadPart
+= RetrievalPointers
->Pair
[j
].Lcn
- RetrievalPointers
->Pair
[j
-1].Vcn
;
246 if (j
>= RetrievalPointers
->NumberOfPairs
)
251 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
252 Status
= IoPageRead(PagingFileList
[i
]->FileObject
,
257 if (Status
== STATUS_PENDING
)
259 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
266 MmInitPagingFile(VOID
)
270 KeInitializeSpinLock(&PagingFileListLock
);
274 MiReservedSwapPages
= 0;
276 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
278 PagingFileList
[i
] = NULL
;
280 MiPagingFileCount
= 0;
283 * Initialize the crash dump support.
285 if (MmCoreDumpType
!= MM_CORE_DUMP_TYPE_NONE
)
287 MmCoreDumpPageFrame
= MmAllocateSection(PAGE_SIZE
);
288 if (MmCoreDumpType
== MM_CORE_DUMP_TYPE_FULL
)
290 MmCoreDumpSize
= MmStats
.NrTotalPages
* 4096 + 1024 * 1024;
294 MmCoreDumpSize
= 1024 * 1024;
300 MmReserveSwapPages(ULONG Nr
)
303 ULONG MiAvailSwapPages
;
305 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
307 (MiFreeSwapPages
* MM_PAGEFILE_COMMIT_RATIO
) + MM_PAGEFILE_COMMIT_GRACE
;
308 MiReservedSwapPages
= MiReservedSwapPages
+ Nr
;
309 if (MM_PAGEFILE_COMMIT_RATIO
!= 0 && MiAvailSwapPages
< MiReservedSwapPages
)
311 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
314 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
319 MmDereserveSwapPages(ULONG Nr
)
323 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
324 MiReservedSwapPages
= MiReservedSwapPages
- Nr
;
325 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
329 MiAllocPageFromPagingFile(PPAGINGFILE PagingFile
)
334 KeAcquireSpinLock(&PagingFile
->AllocMapLock
, &oldIrql
);
336 for (i
= 0; i
< PagingFile
->AllocMapSize
; i
++)
338 for (j
= 0; j
< 32; j
++)
340 if (!(PagingFile
->AllocMap
[i
] & (1 << j
)))
349 PagingFile
->AllocMap
[i
] |= (1 << j
);
350 PagingFile
->UsedPages
++;
351 PagingFile
->FreePages
--;
352 KeReleaseSpinLock(&PagingFile
->AllocMapLock
, oldIrql
);
353 return((i
* 32) + j
);
356 KeReleaseSpinLock(&PagingFile
->AllocMapLock
, oldIrql
);
361 MmFreeSwapPage(SWAPENTRY Entry
)
367 i
= FILE_FROM_ENTRY(Entry
);
368 off
= OFFSET_FROM_ENTRY(Entry
);
370 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
371 if (PagingFileList
[i
] == NULL
)
375 KeAcquireSpinLockAtDpcLevel(&PagingFileList
[i
]->AllocMapLock
);
377 PagingFileList
[i
]->AllocMap
[off
/ 32] &= (~(1 << (off
% 32)));
379 PagingFileList
[i
]->FreePages
++;
380 PagingFileList
[i
]->UsedPages
--;
385 KeReleaseSpinLockFromDpcLevel(&PagingFileList
[i
]->AllocMapLock
);
386 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
390 MmIsAvailableSwapPage(VOID
)
392 return(MiFreeSwapPages
> 0);
396 MmAllocSwapPage(VOID
)
403 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
405 if (MiFreeSwapPages
== 0)
407 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
411 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
413 if (PagingFileList
[i
] != NULL
&&
414 PagingFileList
[i
]->FreePages
>= 1)
416 off
= MiAllocPageFromPagingFile(PagingFileList
[i
]);
417 if (off
== 0xFFFFFFFF)
420 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
421 return(STATUS_UNSUCCESSFUL
);
425 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
427 entry
= ENTRY_FROM_FILE_OFFSET(i
, off
);
432 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
438 MmGetOffsetPageFile(PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
, LARGE_INTEGER Offset
)
441 for (j
= 0; j
< RetrievalPointers
->NumberOfPairs
; j
++)
443 if (Offset
.QuadPart
< RetrievalPointers
->Pair
[j
].Vcn
)
447 Offset
.QuadPart
+= RetrievalPointers
->Pair
[0].Lcn
- RetrievalPointers
->StartVcn
;
451 Offset
.QuadPart
+= RetrievalPointers
->Pair
[j
].Lcn
- RetrievalPointers
->Pair
[j
-1].Vcn
;
456 if (j
>= RetrievalPointers
->NumberOfPairs
)
465 MmDumpToPagingFile(ULONG BugCode
,
466 ULONG BugCodeParameter1
,
467 ULONG BugCodeParameter2
,
468 ULONG BugCodeParameter3
,
469 ULONG BugCodeParameter4
,
470 PKTRAP_FRAME TrapFrame
)
472 PMM_CORE_DUMP_HEADER Headers
;
474 UCHAR MdlBase
[sizeof(MDL
) + sizeof(PVOID
)];
475 PMDL Mdl
= (PMDL
)MdlBase
;
476 PETHREAD Thread
= PsGetCurrentThread();
479 LONGLONG NextOffset
= 0;
481 PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
482 LARGE_INTEGER DiskOffset
;
484 if (MmCoreDumpPageFile
== 0xFFFFFFFF)
486 return(STATUS_UNSUCCESSFUL
);
489 DbgPrint("\nMM: Dumping core: ");
491 /* Prepare the dump headers. */
492 Headers
= (PMM_CORE_DUMP_HEADER
)MmCoreDumpPageFrame
;
493 Headers
->Magic
= MM_CORE_DUMP_HEADER_MAGIC
;
494 Headers
->Version
= MM_CORE_DUMP_HEADER_VERSION
;
495 Headers
->Type
= MmCoreDumpType
;
496 if (TrapFrame
!= NULL
)
498 if (!(TrapFrame
->Eflags
& (1 << 17)))
500 memcpy(&Headers
->TrapFrame
, TrapFrame
,
501 sizeof(KTRAP_FRAME
) - (4 * sizeof(DWORD
)));
505 memcpy(&Headers
->TrapFrame
, TrapFrame
, sizeof(KTRAP_FRAME
));
508 Headers
->BugCheckCode
= BugCode
;
509 Headers
->BugCheckParameters
[0] = BugCodeParameter1
;
510 Headers
->BugCheckParameters
[1] = BugCodeParameter2
;
511 Headers
->BugCheckParameters
[2] = BugCodeParameter3
;
512 Headers
->BugCheckParameters
[3] = BugCodeParameter4
;
513 Headers
->FaultingStackBase
= (PVOID
)Thread
->Tcb
.StackLimit
;
514 Headers
->FaultingStackSize
= StackSize
=
515 (ULONG
)(Thread
->Tcb
.StackBase
- Thread
->Tcb
.StackLimit
);
516 Headers
->PhysicalMemorySize
= MmStats
.NrTotalPages
* PAGE_SIZE
;
518 /* Initialize the dump device. */
519 MmCoreDumpFunctions
->DumpInit();
520 if (!NT_SUCCESS(Status
))
522 DPRINT1("MM: Failed to initialize core dump device.\n");
526 /* Initialize the MDL. */
528 Mdl
->Size
= sizeof(MDL
) + sizeof(PVOID
);
529 Mdl
->MdlFlags
= MDL_SOURCE_IS_NONPAGED_POOL
;
531 Mdl
->MappedSystemVa
= MmCoreDumpPageFrame
;
533 Mdl
->ByteCount
= PAGE_SIZE
;
535 MdlMap
= (PULONG
)(Mdl
+ 1);
538 /* Initialize the retrieval offsets. */
539 RetrievalPointers
= PagingFileList
[MmCoreDumpPageFile
]->RetrievalPointers
;
541 /* Dump the header. */
542 MdlMap
[0] = MmGetPhysicalAddress(MmCoreDumpPageFrame
).u
.LowPart
;
543 DiskOffset
= MmGetOffsetPageFile(RetrievalPointers
, (LARGE_INTEGER
)0LL);
544 DiskOffset
.QuadPart
+= MmCoreDumpLcnMapping
.LcnDiskOffset
.QuadPart
;
545 Status
= MmCoreDumpFunctions
->DumpWrite(DiskOffset
, Mdl
);
546 if (!NT_SUCCESS(Status
))
548 DPRINT1("MM: Failed to write core dump header\n.");
551 NextOffset
+= PAGE_SIZE
;;
555 /* Write out the contents of physical memory. */
556 if (MmCoreDumpType
== MM_CORE_DUMP_TYPE_FULL
)
558 for (i
= 0; i
< MmStats
.NrTotalPages
; i
++)
560 LARGE_INTEGER PhysicalAddress
;
561 PhysicalAddress
.QuadPart
= i
* PAGE_SIZE
;
562 MdlMap
[0] = i
* PAGE_SIZE
;
563 MmCreateVirtualMappingDump(MmCoreDumpPageFrame
,
566 DiskOffset
= MmGetOffsetPageFile(RetrievalPointers
,
567 (LARGE_INTEGER
)NextOffset
);
568 DiskOffset
.QuadPart
+= MmCoreDumpLcnMapping
.LcnDiskOffset
.QuadPart
;
569 Status
= MmCoreDumpFunctions
->DumpWrite(DiskOffset
, Mdl
);
570 if (!NT_SUCCESS(Status
))
572 DPRINT1("MM: Failed to write page to core dump.\n");
575 if ((i
% ((1024*1024) / PAGE_SIZE
)) == 0)
577 DbgPrint("\b\b%.2d", i
/ ((1024*1024)/PAGE_SIZE
));
579 NextOffset
+= PAGE_SIZE
;
584 MmCoreDumpFunctions
->DumpFinish();
585 return(STATUS_SUCCESS
);
589 MmInitializeCrashDump(HANDLE PageFileHandle
, ULONG PageFileNum
)
591 PFILE_OBJECT PageFile
;
592 PDEVICE_OBJECT PageFileDevice
;
596 IO_STATUS_BLOCK Iosb
;
597 UNICODE_STRING DiskDumpName
;
598 ANSI_STRING ProcName
;
599 PIO_STACK_LOCATION StackPtr
;
600 PMODULE_OBJECT ModuleObject
;
602 Status
= ZwFsControlFile(PageFileHandle
,
607 FSCTL_ROS_QUERY_LCN_MAPPING
,
610 &MmCoreDumpLcnMapping
,
611 sizeof(ROS_QUERY_LCN_MAPPING
));
612 if (!NT_SUCCESS(Status
) ||
613 Iosb
.Information
!= sizeof(ROS_QUERY_LCN_MAPPING
))
618 /* Get the underlying storage device. */
620 ObReferenceObjectByHandle(PageFileHandle
,
626 if (!NT_SUCCESS(Status
))
631 PageFileDevice
= PageFile
->Vpb
->RealDevice
;
633 /* Get the dump pointers. */
634 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
635 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_DUMP_POINTERS
,
640 sizeof(MmCoreDumpPointers
),
644 StackPtr
= IoGetNextIrpStackLocation(Irp
);
645 StackPtr
->FileObject
= PageFile
;
646 StackPtr
->DeviceObject
= PageFileDevice
;
647 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
648 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
= sizeof(MmCoreDumpPointers
);
650 Status
= IoCallDriver(PageFileDevice
,Irp
);
651 if (Status
== STATUS_PENDING
)
653 Status
= KeWaitForSingleObject(&Event
,
659 if (Status
!= STATUS_SUCCESS
||
660 Iosb
.Information
!= sizeof(MmCoreDumpPointers
))
662 ObDereferenceObject(PageFile
);
666 /* Load the diskdump driver. */
667 RtlInitUnicodeStringFromLiteral(&DiskDumpName
, L
"DiskDump");
668 ModuleObject
= LdrGetModuleObject(&DiskDumpName
);
669 if (ModuleObject
== NULL
)
671 return(STATUS_OBJECT_NAME_NOT_FOUND
);
673 RtlInitAnsiString(&ProcName
, "DiskDumpFunctions");
674 Status
= LdrGetProcedureAddress(ModuleObject
->Base
,
677 (PVOID
*)&MmCoreDumpFunctions
);
678 if (!NT_SUCCESS(Status
))
680 ObDereferenceObject(PageFile
);
684 /* Prepare for disk dumping. */
685 Status
= MmCoreDumpFunctions
->DumpPrepare(PageFileDevice
,
686 &MmCoreDumpPointers
);
687 if (!NT_SUCCESS(Status
))
689 ObDereferenceObject(PageFile
);
693 MmCoreDumpPageFile
= PageFileNum
;
694 ObDereferenceObject(PageFile
);
695 return(STATUS_SUCCESS
);
699 NtCreatePagingFile(IN PUNICODE_STRING FileName
,
700 IN PLARGE_INTEGER InitialSize
,
701 IN PLARGE_INTEGER MaximumSize
,
705 OBJECT_ATTRIBUTES ObjectAttributes
;
707 IO_STATUS_BLOCK IoStatus
;
708 PFILE_OBJECT FileObject
;
709 PPAGINGFILE PagingFile
;
713 FILE_FS_SIZE_INFORMATION FsSizeInformation
;
714 PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
716 ULONG BytesPerAllocationUnit
;
721 DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n",
722 FileName
, InitialSize
->QuadPart
);
724 if (MiPagingFileCount
>= MAX_PAGING_FILES
)
726 return(STATUS_TOO_MANY_PAGING_FILES
);
729 InitializeObjectAttributes(&ObjectAttributes
,
735 Status
= IoCreateFile(&FileHandle
,
743 FILE_SYNCHRONOUS_IO_NONALERT
,
748 SL_OPEN_PAGING_FILE
);
749 if (!NT_SUCCESS(Status
))
754 Status
= NtQueryVolumeInformationFile(FileHandle
,
757 sizeof(FILE_FS_SIZE_INFORMATION
),
758 FileFsSizeInformation
);
759 if (!NT_SUCCESS(Status
))
765 BytesPerAllocationUnit
= FsSizeInformation
.SectorsPerAllocationUnit
* FsSizeInformation
.BytesPerSector
;
766 if (BytesPerAllocationUnit
% PAGE_SIZE
)
769 return STATUS_UNSUCCESSFUL
;
772 Status
= NtSetInformationFile(FileHandle
,
775 sizeof(LARGE_INTEGER
),
776 FileAllocationInformation
);
777 if (!NT_SUCCESS(Status
))
783 Status
= ObReferenceObjectByHandle(FileHandle
,
789 if (!NT_SUCCESS(Status
))
795 RetrievalPointers
= ExAllocatePool(NonPagedPool
, sizeof(GET_RETRIEVAL_DESCRIPTOR
) + sizeof(MAPPING_PAIR
));
797 if (RetrievalPointers
== NULL
)
799 ObDereferenceObject(FileObject
);
801 return(STATUS_NO_MEMORY
);
806 MaxVcn
= (InitialSize
->QuadPart
+ BytesPerAllocationUnit
- 1) / BytesPerAllocationUnit
;
809 Status
= NtFsControlFile(FileHandle
,
814 FSCTL_GET_RETRIEVAL_POINTERS
,
816 sizeof(LARGE_INTEGER
),
818 sizeof(GET_RETRIEVAL_DESCRIPTOR
) + sizeof(MAPPING_PAIR
));
819 if (!NT_SUCCESS(Status
))
821 ExFreePool(RetrievalPointers
);
822 ObDereferenceObject(FileObject
);
826 ExtentCount
+= RetrievalPointers
->NumberOfPairs
;
827 if ((ULONG
)RetrievalPointers
->Pair
[0].Vcn
< MaxVcn
)
829 Vcn
.QuadPart
= RetrievalPointers
->Pair
[0].Vcn
;
836 ExFreePool(RetrievalPointers
);
838 PagingFile
= ExAllocatePool(NonPagedPool
, sizeof(*PagingFile
));
839 if (PagingFile
== NULL
)
841 ObDereferenceObject(FileObject
);
843 return(STATUS_NO_MEMORY
);
846 PagingFile
->FileObject
= FileObject
;
847 PagingFile
->MaximumSize
.QuadPart
= MaximumSize
->QuadPart
;
848 PagingFile
->CurrentSize
.QuadPart
= InitialSize
->QuadPart
;
849 PagingFile
->FreePages
= InitialSize
->QuadPart
/ PAGE_SIZE
;
850 PagingFile
->UsedPages
= 0;
851 KeInitializeSpinLock(&PagingFile
->AllocMapLock
);
853 AllocMapSize
= (PagingFile
->FreePages
/ 32) + 1;
854 PagingFile
->AllocMap
= ExAllocatePool(NonPagedPool
,
855 AllocMapSize
* sizeof(ULONG
));
856 PagingFile
->AllocMapSize
= AllocMapSize
;
858 if (PagingFile
->AllocMap
== NULL
)
860 ExFreePool(PagingFile
);
861 ObDereferenceObject(FileObject
);
863 return(STATUS_NO_MEMORY
);
866 Size
= sizeof(GET_RETRIEVAL_DESCRIPTOR
) + ExtentCount
* sizeof(MAPPING_PAIR
);
867 PagingFile
->RetrievalPointers
= ExAllocatePool(NonPagedPool
, Size
);
868 if (PagingFile
->RetrievalPointers
== NULL
)
870 ExFreePool(PagingFile
->AllocMap
);
871 ExFreePool(PagingFile
);
872 ObDereferenceObject(FileObject
);
874 return(STATUS_NO_MEMORY
);
878 Status
= NtFsControlFile(FileHandle
,
883 FSCTL_GET_RETRIEVAL_POINTERS
,
885 sizeof(LARGE_INTEGER
),
886 PagingFile
->RetrievalPointers
,
888 if (!NT_SUCCESS(Status
))
890 ExFreePool(PagingFile
->RetrievalPointers
);
891 ExFreePool(PagingFile
->AllocMap
);
892 ExFreePool(PagingFile
);
893 ObDereferenceObject(FileObject
);
895 return(STATUS_NO_MEMORY
);
898 if (PagingFile
->RetrievalPointers
->NumberOfPairs
!= ExtentCount
||
899 (ULONG
)PagingFile
->RetrievalPointers
->Pair
[ExtentCount
- 1].Vcn
!= MaxVcn
)
901 ExFreePool(PagingFile
->RetrievalPointers
);
902 ExFreePool(PagingFile
->AllocMap
);
903 ExFreePool(PagingFile
);
904 ObDereferenceObject(FileObject
);
906 return(STATUS_UNSUCCESSFUL
);
910 * Change the entries from lcn's to volume offset's.
912 PagingFile
->RetrievalPointers
->StartVcn
*= BytesPerAllocationUnit
;
913 for (i
= 0; i
< ExtentCount
; i
++)
915 PagingFile
->RetrievalPointers
->Pair
[i
].Lcn
*= BytesPerAllocationUnit
;
916 PagingFile
->RetrievalPointers
->Pair
[i
].Vcn
*= BytesPerAllocationUnit
;
919 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
920 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
922 if (PagingFileList
[i
] == NULL
)
924 PagingFileList
[i
] = PagingFile
;
928 MiFreeSwapPages
= MiFreeSwapPages
+ PagingFile
->FreePages
;
930 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
932 /* Check whether this pagefile can be a crash dump target. */
933 if (MmCoreDumpType
!= MM_CORE_DUMP_TYPE_NONE
&&
934 PagingFile
->CurrentSize
.QuadPart
>= MmCoreDumpSize
&&
935 MmCoreDumpPageFile
== 0xFFFFFFFF)
937 MmInitializeCrashDump(FileHandle
, i
);
941 MmSwapSpaceMessage
= FALSE
;
943 return(STATUS_SUCCESS
);