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.39 2003/11/30 17:19:28 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>
37 #include <rosrtl/string.h>
40 #include <internal/debug.h>
42 /* TYPES *********************************************************************/
44 typedef struct _PAGINGFILE
46 LIST_ENTRY PagingFileListEntry
;
47 PFILE_OBJECT FileObject
;
48 LARGE_INTEGER MaximumSize
;
49 LARGE_INTEGER CurrentSize
;
53 KSPIN_LOCK AllocMapLock
;
55 PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
56 } PAGINGFILE
, *PPAGINGFILE
;
58 typedef struct _RETRIEVEL_DESCRIPTOR_LIST
60 struct _RETRIEVEL_DESCRIPTOR_LIST
* Next
;
61 GET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
63 RETRIEVEL_DESCRIPTOR_LIST
, *PRETRIEVEL_DESCRIPTOR_LIST
;
65 /* GLOBALS *******************************************************************/
67 #define PAIRS_PER_RUN (1024)
69 #define MAX_PAGING_FILES (32)
71 /* List of paging files, both used and free */
72 static PPAGINGFILE PagingFileList
[MAX_PAGING_FILES
];
74 /* Lock for examining the list of paging files */
75 static KSPIN_LOCK PagingFileListLock
;
77 /* Number of paging files */
78 static ULONG MiPagingFileCount
;
80 /* Number of pages that are available for swapping */
81 static ULONG MiFreeSwapPages
;
83 /* Number of pages that have been allocated for swapping */
84 static ULONG MiUsedSwapPages
;
87 * Number of pages that have been reserved for swapping but not yet allocated
89 static ULONG MiReservedSwapPages
;
92 * Ratio between reserved and available swap pages, e.g. setting this to five
93 * forces one swap page to be available for every five swap pages that are
94 * reserved. Setting this to zero turns off commit checking altogether.
96 #define MM_PAGEFILE_COMMIT_RATIO (1)
99 * Number of pages that can be used for potentially swapable memory without
100 * pagefile space being reserved. The intention is that this allows smss
101 * to start up and create page files while ordinarily having a commit
104 #define MM_PAGEFILE_COMMIT_GRACE (256)
106 static PVOID MmCoreDumpPageFrame
= NULL
;
107 static ULONG MmCoreDumpSize
;
108 static DUMP_POINTERS MmCoreDumpPointers
;
109 static PMM_CORE_DUMP_FUNCTIONS MmCoreDumpFunctions
;
110 static ULONG MmCoreDumpPageFile
= 0xFFFFFFFF;
111 static ROS_QUERY_LCN_MAPPING MmCoreDumpLcnMapping
;
113 ULONG MmCoreDumpType
= MM_CORE_DUMP_TYPE_NONE
;
116 * Translate between a swap entry and a file and offset pair.
118 #define FILE_FROM_ENTRY(i) ((i) >> 24)
119 #define OFFSET_FROM_ENTRY(i) (((i) & 0xffffff) - 1)
120 #define ENTRY_FROM_FILE_OFFSET(i, j) (((i) << 24) | ((j) + 1))
122 static BOOLEAN MmSwapSpaceMessage
= FALSE
;
124 /* FUNCTIONS *****************************************************************/
127 MmShowOutOfSpaceMessagePagingFile(VOID
)
129 if (!MmSwapSpaceMessage
)
131 DPRINT1("MM: Out of swap space.\n");
132 MmSwapSpaceMessage
= TRUE
;
137 MmGetOffsetPageFile(PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
, LARGE_INTEGER Offset
)
139 /* Simple binary search */
140 ULONG first
, last
, mid
;
142 last
= RetrievalPointers
->NumberOfPairs
- 1;
143 while (first
<= last
)
145 mid
= (last
- first
) / 2 + first
;
146 if ((ULONGLONG
) Offset
.QuadPart
< RetrievalPointers
->Pair
[mid
].Vcn
)
150 Offset
.QuadPart
+= RetrievalPointers
->Pair
[0].Lcn
- RetrievalPointers
->StartVcn
;
155 if ((ULONGLONG
) Offset
.QuadPart
>= RetrievalPointers
->Pair
[mid
-1].Vcn
)
157 Offset
.QuadPart
+= RetrievalPointers
->Pair
[mid
].Lcn
- RetrievalPointers
->Pair
[mid
-1].Vcn
;
165 if (mid
== RetrievalPointers
->NumberOfPairs
- 1)
169 if ((ULONGLONG
) Offset
.QuadPart
< RetrievalPointers
->Pair
[mid
+1].Vcn
)
171 Offset
.QuadPart
+= RetrievalPointers
->Pair
[mid
+1].Lcn
- RetrievalPointers
->Pair
[mid
].Vcn
;
178 return (LARGE_INTEGER
)0LL;
181 NTSTATUS
MmWriteToSwapPage(SWAPENTRY SwapEntry
, PMDL Mdl
)
184 LARGE_INTEGER file_offset
;
185 IO_STATUS_BLOCK Iosb
;
189 DPRINT("MmWriteToSwapPage\n");
194 return(STATUS_UNSUCCESSFUL
);
197 i
= FILE_FROM_ENTRY(SwapEntry
);
198 offset
= OFFSET_FROM_ENTRY(SwapEntry
);
200 if (i
>= MAX_PAGING_FILES
)
202 DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry
);
205 if (PagingFileList
[i
]->FileObject
== NULL
||
206 PagingFileList
[i
]->FileObject
->DeviceObject
== NULL
)
208 DPRINT1("Bad paging file 0x%.8X\n", SwapEntry
);
212 file_offset
.QuadPart
= offset
* PAGE_SIZE
;
213 file_offset
= MmGetOffsetPageFile(PagingFileList
[i
]->RetrievalPointers
, file_offset
);
215 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
216 Status
= IoPageWrite(PagingFileList
[i
]->FileObject
,
221 if (Status
== STATUS_PENDING
)
223 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
229 NTSTATUS
MmReadFromSwapPage(SWAPENTRY SwapEntry
, PMDL Mdl
)
232 LARGE_INTEGER file_offset
;
233 IO_STATUS_BLOCK Iosb
;
237 DPRINT("MmReadFromSwapPage\n");
242 return(STATUS_UNSUCCESSFUL
);
245 i
= FILE_FROM_ENTRY(SwapEntry
);
246 offset
= OFFSET_FROM_ENTRY(SwapEntry
);
248 if (i
>= MAX_PAGING_FILES
)
250 DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry
);
253 if (PagingFileList
[i
]->FileObject
== NULL
||
254 PagingFileList
[i
]->FileObject
->DeviceObject
== NULL
)
256 DPRINT1("Bad paging file 0x%.8X\n", SwapEntry
);
260 file_offset
.QuadPart
= offset
* PAGE_SIZE
;
261 file_offset
= MmGetOffsetPageFile(PagingFileList
[i
]->RetrievalPointers
, file_offset
);
263 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
264 Status
= IoPageRead(PagingFileList
[i
]->FileObject
,
269 if (Status
== STATUS_PENDING
)
271 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
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
);
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
)))
361 PagingFile
->AllocMap
[i
] |= (1 << j
);
362 PagingFile
->UsedPages
++;
363 PagingFile
->FreePages
--;
364 KeReleaseSpinLock(&PagingFile
->AllocMapLock
, oldIrql
);
365 return((i
* 32) + j
);
368 KeReleaseSpinLock(&PagingFile
->AllocMapLock
, oldIrql
);
373 MmFreeSwapPage(SWAPENTRY Entry
)
379 i
= FILE_FROM_ENTRY(Entry
);
380 off
= OFFSET_FROM_ENTRY(Entry
);
382 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
383 if (PagingFileList
[i
] == NULL
)
387 KeAcquireSpinLockAtDpcLevel(&PagingFileList
[i
]->AllocMapLock
);
389 PagingFileList
[i
]->AllocMap
[off
/ 32] &= (~(1 << (off
% 32)));
391 PagingFileList
[i
]->FreePages
++;
392 PagingFileList
[i
]->UsedPages
--;
397 KeReleaseSpinLockFromDpcLevel(&PagingFileList
[i
]->AllocMapLock
);
398 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
402 MmIsAvailableSwapPage(VOID
)
404 return(MiFreeSwapPages
> 0);
408 MmAllocSwapPage(VOID
)
415 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
417 if (MiFreeSwapPages
== 0)
419 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
423 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
425 if (PagingFileList
[i
] != NULL
&&
426 PagingFileList
[i
]->FreePages
>= 1)
428 off
= MiAllocPageFromPagingFile(PagingFileList
[i
]);
429 if (off
== 0xFFFFFFFF)
432 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
433 return(STATUS_UNSUCCESSFUL
);
437 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
439 entry
= ENTRY_FROM_FILE_OFFSET(i
, off
);
444 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
450 MmDumpToPagingFile(ULONG BugCode
,
451 ULONG BugCodeParameter1
,
452 ULONG BugCodeParameter2
,
453 ULONG BugCodeParameter3
,
454 ULONG BugCodeParameter4
,
455 PKTRAP_FRAME TrapFrame
)
457 PMM_CORE_DUMP_HEADER Headers
;
459 UCHAR MdlBase
[sizeof(MDL
) + sizeof(PVOID
)];
460 PMDL Mdl
= (PMDL
)MdlBase
;
461 PETHREAD Thread
= PsGetCurrentThread();
464 LONGLONG NextOffset
= 0;
466 PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers
;
467 LARGE_INTEGER DiskOffset
;
469 if (MmCoreDumpPageFile
== 0xFFFFFFFF)
471 return(STATUS_UNSUCCESSFUL
);
474 DbgPrint("\nMM: Dumping core: ");
476 /* Prepare the dump headers. */
477 Headers
= (PMM_CORE_DUMP_HEADER
)MmCoreDumpPageFrame
;
478 Headers
->Magic
= MM_CORE_DUMP_HEADER_MAGIC
;
479 Headers
->Version
= MM_CORE_DUMP_HEADER_VERSION
;
480 Headers
->Type
= MmCoreDumpType
;
481 if (TrapFrame
!= NULL
)
483 if (!(TrapFrame
->Eflags
& (1 << 17)))
485 memcpy(&Headers
->TrapFrame
, TrapFrame
,
486 sizeof(KTRAP_FRAME
) - (4 * sizeof(DWORD
)));
490 memcpy(&Headers
->TrapFrame
, TrapFrame
, sizeof(KTRAP_FRAME
));
493 Headers
->BugCheckCode
= BugCode
;
494 Headers
->BugCheckParameters
[0] = BugCodeParameter1
;
495 Headers
->BugCheckParameters
[1] = BugCodeParameter2
;
496 Headers
->BugCheckParameters
[2] = BugCodeParameter3
;
497 Headers
->BugCheckParameters
[3] = BugCodeParameter4
;
498 Headers
->FaultingStackBase
= (PVOID
)Thread
->Tcb
.StackLimit
;
499 Headers
->FaultingStackSize
= StackSize
=
500 (ULONG
)(Thread
->Tcb
.StackBase
- Thread
->Tcb
.StackLimit
);
501 Headers
->PhysicalMemorySize
= MmStats
.NrTotalPages
* PAGE_SIZE
;
503 /* Initialize the dump device. */
504 MmCoreDumpFunctions
->DumpInit();
505 if (!NT_SUCCESS(Status
))
507 DPRINT1("MM: Failed to initialize core dump device.\n");
511 /* Initialize the MDL. */
513 Mdl
->Size
= sizeof(MDL
) + sizeof(PVOID
);
514 Mdl
->MdlFlags
= MDL_SOURCE_IS_NONPAGED_POOL
;
516 Mdl
->MappedSystemVa
= MmCoreDumpPageFrame
;
518 Mdl
->ByteCount
= PAGE_SIZE
;
520 MdlMap
= (PULONG
)(Mdl
+ 1);
523 /* Initialize the retrieval offsets. */
524 RetrievalPointers
= PagingFileList
[MmCoreDumpPageFile
]->RetrievalPointers
;
526 /* Dump the header. */
527 MdlMap
[0] = MmGetPhysicalAddress(MmCoreDumpPageFrame
).u
.LowPart
;
528 DiskOffset
= MmGetOffsetPageFile(RetrievalPointers
, (LARGE_INTEGER
)0LL);
529 DiskOffset
.QuadPart
+= MmCoreDumpLcnMapping
.LcnDiskOffset
.QuadPart
;
530 Status
= MmCoreDumpFunctions
->DumpWrite(DiskOffset
, Mdl
);
531 if (!NT_SUCCESS(Status
))
533 DPRINT1("MM: Failed to write core dump header\n.");
536 NextOffset
+= PAGE_SIZE
;;
540 /* Write out the contents of physical memory. */
541 if (MmCoreDumpType
== MM_CORE_DUMP_TYPE_FULL
)
543 for (i
= 0; i
< MmStats
.NrTotalPages
; i
++)
545 LARGE_INTEGER PhysicalAddress
;
546 PhysicalAddress
.QuadPart
= i
* PAGE_SIZE
;
547 MdlMap
[0] = i
* PAGE_SIZE
;
548 MmCreateVirtualMappingDump(MmCoreDumpPageFrame
,
551 DiskOffset
= MmGetOffsetPageFile(RetrievalPointers
,
552 (LARGE_INTEGER
)NextOffset
);
553 DiskOffset
.QuadPart
+= MmCoreDumpLcnMapping
.LcnDiskOffset
.QuadPart
;
554 Status
= MmCoreDumpFunctions
->DumpWrite(DiskOffset
, Mdl
);
555 if (!NT_SUCCESS(Status
))
557 DPRINT1("MM: Failed to write page to core dump.\n");
560 if ((i
% ((1024*1024) / PAGE_SIZE
)) == 0)
562 DbgPrint("\b\b%.2d", i
/ ((1024*1024)/PAGE_SIZE
));
564 NextOffset
+= PAGE_SIZE
;
569 MmCoreDumpFunctions
->DumpFinish();
570 return(STATUS_SUCCESS
);
574 MmInitializeCrashDump(HANDLE PageFileHandle
, ULONG PageFileNum
)
576 PFILE_OBJECT PageFile
;
577 PDEVICE_OBJECT PageFileDevice
;
581 IO_STATUS_BLOCK Iosb
;
582 UNICODE_STRING DiskDumpName
;
583 ANSI_STRING ProcName
;
584 PIO_STACK_LOCATION StackPtr
;
585 PMODULE_OBJECT ModuleObject
;
587 Status
= ZwFsControlFile(PageFileHandle
,
592 FSCTL_ROS_QUERY_LCN_MAPPING
,
595 &MmCoreDumpLcnMapping
,
596 sizeof(ROS_QUERY_LCN_MAPPING
));
597 if (!NT_SUCCESS(Status
) ||
598 Iosb
.Information
!= sizeof(ROS_QUERY_LCN_MAPPING
))
603 /* Get the underlying storage device. */
605 ObReferenceObjectByHandle(PageFileHandle
,
611 if (!NT_SUCCESS(Status
))
616 PageFileDevice
= PageFile
->Vpb
->RealDevice
;
618 /* Get the dump pointers. */
619 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
620 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_DUMP_POINTERS
,
625 sizeof(MmCoreDumpPointers
),
629 StackPtr
= IoGetNextIrpStackLocation(Irp
);
630 StackPtr
->FileObject
= PageFile
;
631 StackPtr
->DeviceObject
= PageFileDevice
;
632 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= 0;
633 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
= sizeof(MmCoreDumpPointers
);
635 Status
= IoCallDriver(PageFileDevice
,Irp
);
636 if (Status
== STATUS_PENDING
)
638 Status
= KeWaitForSingleObject(&Event
,
644 if (Status
!= STATUS_SUCCESS
||
645 Iosb
.Information
!= sizeof(MmCoreDumpPointers
))
647 ObDereferenceObject(PageFile
);
651 /* Load the diskdump driver. */
652 RtlRosInitUnicodeStringFromLiteral(&DiskDumpName
, L
"DiskDump");
653 ModuleObject
= LdrGetModuleObject(&DiskDumpName
);
654 if (ModuleObject
== NULL
)
656 return(STATUS_OBJECT_NAME_NOT_FOUND
);
658 RtlInitAnsiString(&ProcName
, "DiskDumpFunctions");
659 Status
= LdrGetProcedureAddress(ModuleObject
->Base
,
662 (PVOID
*)&MmCoreDumpFunctions
);
663 if (!NT_SUCCESS(Status
))
665 ObDereferenceObject(PageFile
);
669 /* Prepare for disk dumping. */
670 Status
= MmCoreDumpFunctions
->DumpPrepare(PageFileDevice
,
671 &MmCoreDumpPointers
);
672 if (!NT_SUCCESS(Status
))
674 ObDereferenceObject(PageFile
);
678 MmCoreDumpPageFile
= PageFileNum
;
679 ObDereferenceObject(PageFile
);
680 return(STATUS_SUCCESS
);
684 NtCreatePagingFile(IN PUNICODE_STRING FileName
,
685 IN PLARGE_INTEGER InitialSize
,
686 IN PLARGE_INTEGER MaximumSize
,
690 OBJECT_ATTRIBUTES ObjectAttributes
;
692 IO_STATUS_BLOCK IoStatus
;
693 PFILE_OBJECT FileObject
;
694 PPAGINGFILE PagingFile
;
698 FILE_FS_SIZE_INFORMATION FsSizeInformation
;
699 PRETRIEVEL_DESCRIPTOR_LIST RetDescList
;
700 PRETRIEVEL_DESCRIPTOR_LIST CurrentRetDescList
;
702 ULONG BytesPerAllocationUnit
;
708 DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n",
709 FileName
, InitialSize
->QuadPart
);
711 if (MiPagingFileCount
>= MAX_PAGING_FILES
)
713 return(STATUS_TOO_MANY_PAGING_FILES
);
716 InitializeObjectAttributes(&ObjectAttributes
,
722 Status
= IoCreateFile(&FileHandle
,
730 FILE_SYNCHRONOUS_IO_NONALERT
,
735 SL_OPEN_PAGING_FILE
);
736 if (!NT_SUCCESS(Status
))
741 Status
= NtQueryVolumeInformationFile(FileHandle
,
744 sizeof(FILE_FS_SIZE_INFORMATION
),
745 FileFsSizeInformation
);
746 if (!NT_SUCCESS(Status
))
752 BytesPerAllocationUnit
= FsSizeInformation
.SectorsPerAllocationUnit
* FsSizeInformation
.BytesPerSector
;
753 if (BytesPerAllocationUnit
% PAGE_SIZE
)
756 return STATUS_UNSUCCESSFUL
;
759 Status
= NtSetInformationFile(FileHandle
,
762 sizeof(LARGE_INTEGER
),
763 FileAllocationInformation
);
764 if (!NT_SUCCESS(Status
))
770 Status
= ObReferenceObjectByHandle(FileHandle
,
776 if (!NT_SUCCESS(Status
))
782 Size
= sizeof(RETRIEVEL_DESCRIPTOR_LIST
) + PAIRS_PER_RUN
* sizeof(MAPPING_PAIR
);
783 CurrentRetDescList
= RetDescList
= ExAllocatePool(NonPagedPool
, Size
);
785 if (CurrentRetDescList
== NULL
)
787 ObDereferenceObject(FileObject
);
789 return(STATUS_NO_MEMORY
);
794 MaxVcn
= (InitialSize
->QuadPart
+ BytesPerAllocationUnit
- 1) / BytesPerAllocationUnit
;
797 Status
= NtFsControlFile(FileHandle
,
802 FSCTL_GET_RETRIEVAL_POINTERS
,
804 sizeof(LARGE_INTEGER
),
805 &CurrentRetDescList
->RetrievalPointers
,
806 sizeof(GET_RETRIEVAL_DESCRIPTOR
) + PAIRS_PER_RUN
* sizeof(MAPPING_PAIR
));
807 if (!NT_SUCCESS(Status
))
811 CurrentRetDescList
= RetDescList
;
812 RetDescList
= RetDescList
->Next
;
813 ExFreePool(CurrentRetDescList
);
815 ObDereferenceObject(FileObject
);
819 ExtentCount
+= CurrentRetDescList
->RetrievalPointers
.NumberOfPairs
;
820 if ((ULONG
)CurrentRetDescList
->RetrievalPointers
.Pair
[CurrentRetDescList
->RetrievalPointers
.NumberOfPairs
-1].Vcn
< MaxVcn
)
822 CurrentRetDescList
->Next
= ExAllocatePool(NonPagedPool
, Size
);
823 if (CurrentRetDescList
->Next
== NULL
)
827 CurrentRetDescList
= RetDescList
;
828 RetDescList
= RetDescList
->Next
;
829 ExFreePool(CurrentRetDescList
);
831 ObDereferenceObject(FileObject
);
833 return(STATUS_NO_MEMORY
);
835 Vcn
.QuadPart
= CurrentRetDescList
->RetrievalPointers
.Pair
[CurrentRetDescList
->RetrievalPointers
.NumberOfPairs
-1].Vcn
;
836 CurrentRetDescList
= CurrentRetDescList
->Next
;
844 PagingFile
= ExAllocatePool(NonPagedPool
, sizeof(*PagingFile
));
845 if (PagingFile
== NULL
)
849 CurrentRetDescList
= RetDescList
;
850 RetDescList
= RetDescList
->Next
;
851 ExFreePool(CurrentRetDescList
);
853 ObDereferenceObject(FileObject
);
855 return(STATUS_NO_MEMORY
);
858 PagingFile
->FileObject
= FileObject
;
859 PagingFile
->MaximumSize
.QuadPart
= MaximumSize
->QuadPart
;
860 PagingFile
->CurrentSize
.QuadPart
= InitialSize
->QuadPart
;
861 PagingFile
->FreePages
= InitialSize
->QuadPart
/ PAGE_SIZE
;
862 PagingFile
->UsedPages
= 0;
863 KeInitializeSpinLock(&PagingFile
->AllocMapLock
);
865 AllocMapSize
= (PagingFile
->FreePages
/ 32) + 1;
866 PagingFile
->AllocMap
= ExAllocatePool(NonPagedPool
,
867 AllocMapSize
* sizeof(ULONG
));
868 PagingFile
->AllocMapSize
= AllocMapSize
;
870 if (PagingFile
->AllocMap
== NULL
)
874 CurrentRetDescList
= RetDescList
;
875 RetDescList
= RetDescList
->Next
;
876 ExFreePool(CurrentRetDescList
);
878 ExFreePool(PagingFile
);
879 ObDereferenceObject(FileObject
);
881 return(STATUS_NO_MEMORY
);
883 DPRINT("ExtentCount: %d\n", ExtentCount
);
884 Size
= sizeof(GET_RETRIEVAL_DESCRIPTOR
) + ExtentCount
* sizeof(MAPPING_PAIR
);
885 PagingFile
->RetrievalPointers
= ExAllocatePool(NonPagedPool
, Size
);
886 if (PagingFile
->RetrievalPointers
== NULL
)
890 CurrentRetDescList
= RetDescList
;
891 RetDescList
= RetDescList
->Next
;
892 ExFreePool(CurrentRetDescList
);
894 ExFreePool(PagingFile
->AllocMap
);
895 ExFreePool(PagingFile
);
896 ObDereferenceObject(FileObject
);
898 return(STATUS_NO_MEMORY
);
902 PagingFile
->RetrievalPointers
->NumberOfPairs
= ExtentCount
;
903 PagingFile
->RetrievalPointers
->StartVcn
= RetDescList
->RetrievalPointers
.StartVcn
;
904 CurrentRetDescList
= RetDescList
;
905 while (CurrentRetDescList
)
907 memcpy(&PagingFile
->RetrievalPointers
->Pair
[Count
],
908 CurrentRetDescList
->RetrievalPointers
.Pair
,
909 CurrentRetDescList
->RetrievalPointers
.NumberOfPairs
* sizeof(MAPPING_PAIR
));
910 Count
+= CurrentRetDescList
->RetrievalPointers
.NumberOfPairs
;
911 RetDescList
= CurrentRetDescList
;
912 CurrentRetDescList
= CurrentRetDescList
->Next
;
913 ExFreePool(RetDescList
);
916 if (PagingFile
->RetrievalPointers
->NumberOfPairs
!= ExtentCount
||
917 (ULONG
)PagingFile
->RetrievalPointers
->Pair
[ExtentCount
- 1].Vcn
!= MaxVcn
)
919 ExFreePool(PagingFile
->RetrievalPointers
);
920 ExFreePool(PagingFile
->AllocMap
);
921 ExFreePool(PagingFile
);
922 ObDereferenceObject(FileObject
);
924 return(STATUS_UNSUCCESSFUL
);
928 * Change the entries from lcn's to volume offset's.
930 PagingFile
->RetrievalPointers
->StartVcn
*= BytesPerAllocationUnit
;
931 for (i
= 0; i
< ExtentCount
; i
++)
933 PagingFile
->RetrievalPointers
->Pair
[i
].Lcn
*= BytesPerAllocationUnit
;
934 PagingFile
->RetrievalPointers
->Pair
[i
].Vcn
*= BytesPerAllocationUnit
;
937 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
938 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
940 if (PagingFileList
[i
] == NULL
)
942 PagingFileList
[i
] = PagingFile
;
946 MiFreeSwapPages
= MiFreeSwapPages
+ PagingFile
->FreePages
;
948 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
950 /* Check whether this pagefile can be a crash dump target. */
951 if (MmCoreDumpType
!= MM_CORE_DUMP_TYPE_NONE
&&
952 PagingFile
->CurrentSize
.QuadPart
>= MmCoreDumpSize
&&
953 MmCoreDumpPageFile
== 0xFFFFFFFF)
955 MmInitializeCrashDump(FileHandle
, i
);
959 MmSwapSpaceMessage
= FALSE
;
961 return(STATUS_SUCCESS
);