X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fntoskrnl%2Fmm%2Fpagefile.c;h=5cccff87bcfced4082a98ed0da532241d429c7d3;hp=32bd61baebed9cdd0cdeff768dc251ce086b73c8;hb=09a762db1d881b1679e91900d41046d89e9d98af;hpb=36e302cc700b34d3cef43b4f696e56cbd81caa93 diff --git a/reactos/ntoskrnl/mm/pagefile.c b/reactos/ntoskrnl/mm/pagefile.c index 32bd61baebe..5cccff87bcf 100644 --- a/reactos/ntoskrnl/mm/pagefile.c +++ b/reactos/ntoskrnl/mm/pagefile.c @@ -16,8 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: pagefile.c,v 1.39 2003/11/30 17:19:28 hbirr Exp $ - * +/* * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/pagefile.c * PURPOSE: Paging file functions @@ -28,17 +27,15 @@ /* INCLUDES *****************************************************************/ -#include -#include -#include -#include -#include -#include -#include - +#include #define NDEBUG #include +#if defined (ALLOC_PRAGMA) +#pragma alloc_text(INIT, MmInitPagingFile) +#endif + + /* TYPES *********************************************************************/ typedef struct _PAGINGFILE @@ -52,19 +49,20 @@ typedef struct _PAGINGFILE PULONG AllocMap; KSPIN_LOCK AllocMapLock; ULONG AllocMapSize; - PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers; -} PAGINGFILE, *PPAGINGFILE; + PRETRIEVAL_POINTERS_BUFFER RetrievalPointers; +} +PAGINGFILE, *PPAGINGFILE; typedef struct _RETRIEVEL_DESCRIPTOR_LIST { - struct _RETRIEVEL_DESCRIPTOR_LIST* Next; - GET_RETRIEVAL_DESCRIPTOR RetrievalPointers; + struct _RETRIEVEL_DESCRIPTOR_LIST* Next; + RETRIEVAL_POINTERS_BUFFER RetrievalPointers; } RETRIEVEL_DESCRIPTOR_LIST, *PRETRIEVEL_DESCRIPTOR_LIST; /* GLOBALS *******************************************************************/ -#define PAIRS_PER_RUN (1024) +#define PAIRS_PER_RUN (1024) #define MAX_PAGING_FILES (32) @@ -78,17 +76,17 @@ static KSPIN_LOCK PagingFileListLock; static ULONG MiPagingFileCount; /* Number of pages that are available for swapping */ -static ULONG MiFreeSwapPages; +ULONG MiFreeSwapPages; /* Number of pages that have been allocated for swapping */ -static ULONG MiUsedSwapPages; +ULONG MiUsedSwapPages; -/* - * Number of pages that have been reserved for swapping but not yet allocated +/* + * Number of pages that have been reserved for swapping but not yet allocated */ static ULONG MiReservedSwapPages; -/* +/* * Ratio between reserved and available swap pages, e.g. setting this to five * forces one swap page to be available for every five swap pages that are * reserved. Setting this to zero turns off commit checking altogether. @@ -123,568 +121,660 @@ static BOOLEAN MmSwapSpaceMessage = FALSE; /* FUNCTIONS *****************************************************************/ +BOOLEAN +STDCALL +MmIsFileAPagingFile(PFILE_OBJECT FileObject) +{ + ULONG i; + + /* Loop through all the paging files */ + for (i = 0; i < MiPagingFileCount; i++) + { + /* Check if this is one of them */ + if (PagingFileList[i]->FileObject == FileObject) return TRUE; + } + + /* Nothing found */ + return FALSE; +} + VOID +NTAPI MmShowOutOfSpaceMessagePagingFile(VOID) { - if (!MmSwapSpaceMessage) - { + if (!MmSwapSpaceMessage) + { DPRINT1("MM: Out of swap space.\n"); MmSwapSpaceMessage = TRUE; - } + } } LARGE_INTEGER STATIC -MmGetOffsetPageFile(PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers, LARGE_INTEGER Offset) +MmGetOffsetPageFile(PRETRIEVAL_POINTERS_BUFFER RetrievalPointers, LARGE_INTEGER Offset) { /* Simple binary search */ ULONG first, last, mid; first = 0; - last = RetrievalPointers->NumberOfPairs - 1; + last = RetrievalPointers->ExtentCount - 1; while (first <= last) - { - mid = (last - first) / 2 + first; - if ((ULONGLONG) Offset.QuadPart < RetrievalPointers->Pair[mid].Vcn) + { + mid = (last - first) / 2 + first; + if (Offset.QuadPart < RetrievalPointers->Extents[mid].NextVcn.QuadPart) + { + if (mid == 0) { - if (mid == 0) - { - Offset.QuadPart += RetrievalPointers->Pair[0].Lcn - RetrievalPointers->StartVcn; - return Offset; - } - else - { - if ((ULONGLONG) Offset.QuadPart >= RetrievalPointers->Pair[mid-1].Vcn) - { - Offset.QuadPart += RetrievalPointers->Pair[mid].Lcn - RetrievalPointers->Pair[mid-1].Vcn; - return Offset; - } - last = mid - 1; - } - } - else + Offset.QuadPart += RetrievalPointers->Extents[0].Lcn.QuadPart - RetrievalPointers->StartingVcn.QuadPart; + return Offset; + } + else { - if (mid == RetrievalPointers->NumberOfPairs - 1) - { - break; - } - if ((ULONGLONG) Offset.QuadPart < RetrievalPointers->Pair[mid+1].Vcn) - { - Offset.QuadPart += RetrievalPointers->Pair[mid+1].Lcn - RetrievalPointers->Pair[mid].Vcn; - return Offset; - } - first = mid + 1; - } - } + if (Offset.QuadPart >= RetrievalPointers->Extents[mid-1].NextVcn.QuadPart) + { + Offset.QuadPart += RetrievalPointers->Extents[mid].Lcn.QuadPart - RetrievalPointers->Extents[mid-1].NextVcn.QuadPart; + return Offset; + } + last = mid - 1; + } + } + else + { + if (mid == RetrievalPointers->ExtentCount - 1) + { + break; + } + if (Offset.QuadPart < RetrievalPointers->Extents[mid+1].NextVcn.QuadPart) + { + Offset.QuadPart += RetrievalPointers->Extents[mid+1].Lcn.QuadPart - RetrievalPointers->Extents[mid].NextVcn.QuadPart; + return Offset; + } + first = mid + 1; + } + } KEBUGCHECK(0); +#if defined(__GNUC__) + return (LARGE_INTEGER)0LL; +#else + + { + const LARGE_INTEGER dummy = + { + 0 + }; + return dummy; + } +#endif } -NTSTATUS MmWriteToSwapPage(SWAPENTRY SwapEntry, PMDL Mdl) +NTSTATUS +NTAPI +MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_TYPE Page) { ULONG i, offset; LARGE_INTEGER file_offset; IO_STATUS_BLOCK Iosb; NTSTATUS Status; KEVENT Event; + UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)]; + PMDL Mdl = (PMDL)MdlBase; DPRINT("MmWriteToSwapPage\n"); - + if (SwapEntry == 0) - { - KEBUGCHECK(0); - return(STATUS_UNSUCCESSFUL); - } - + { + KEBUGCHECK(0); + return(STATUS_UNSUCCESSFUL); + } + i = FILE_FROM_ENTRY(SwapEntry); offset = OFFSET_FROM_ENTRY(SwapEntry); if (i >= MAX_PAGING_FILES) - { - DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry); - KEBUGCHECK(0); - } + { + DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry); + KEBUGCHECK(0); + } if (PagingFileList[i]->FileObject == NULL || - PagingFileList[i]->FileObject->DeviceObject == NULL) - { - DPRINT1("Bad paging file 0x%.8X\n", SwapEntry); - KEBUGCHECK(0); - } - + PagingFileList[i]->FileObject->DeviceObject == NULL) + { + DPRINT1("Bad paging file 0x%.8X\n", SwapEntry); + KEBUGCHECK(0); + } + + MmInitializeMdl(Mdl, NULL, PAGE_SIZE); + MmBuildMdlFromPages(Mdl, &Page); + file_offset.QuadPart = offset * PAGE_SIZE; file_offset = MmGetOffsetPageFile(PagingFileList[i]->RetrievalPointers, file_offset); - + KeInitializeEvent(&Event, NotificationEvent, FALSE); - Status = IoPageWrite(PagingFileList[i]->FileObject, - Mdl, - &file_offset, - &Event, - &Iosb); + Status = IoSynchronousPageWrite(PagingFileList[i]->FileObject, + Mdl, + &file_offset, + &Event, + &Iosb); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); - return(Iosb.Status); + Status = Iosb.Status; } + MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl); return(Status); } -NTSTATUS MmReadFromSwapPage(SWAPENTRY SwapEntry, PMDL Mdl) +NTSTATUS +NTAPI +MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_TYPE Page) { ULONG i, offset; LARGE_INTEGER file_offset; IO_STATUS_BLOCK Iosb; NTSTATUS Status; KEVENT Event; + UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)]; + PMDL Mdl = (PMDL)MdlBase; DPRINT("MmReadFromSwapPage\n"); - + if (SwapEntry == 0) - { - KEBUGCHECK(0); - return(STATUS_UNSUCCESSFUL); - } - + { + KEBUGCHECK(0); + return(STATUS_UNSUCCESSFUL); + } + i = FILE_FROM_ENTRY(SwapEntry); offset = OFFSET_FROM_ENTRY(SwapEntry); if (i >= MAX_PAGING_FILES) - { - DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry); - KEBUGCHECK(0); - } + { + DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry); + KEBUGCHECK(0); + } if (PagingFileList[i]->FileObject == NULL || - PagingFileList[i]->FileObject->DeviceObject == NULL) - { - DPRINT1("Bad paging file 0x%.8X\n", SwapEntry); - KEBUGCHECK(0); - } + PagingFileList[i]->FileObject->DeviceObject == NULL) + { + DPRINT1("Bad paging file 0x%.8X\n", SwapEntry); + KEBUGCHECK(0); + } + + MmInitializeMdl(Mdl, NULL, PAGE_SIZE); + MmBuildMdlFromPages(Mdl, &Page); file_offset.QuadPart = offset * PAGE_SIZE; file_offset = MmGetOffsetPageFile(PagingFileList[i]->RetrievalPointers, file_offset); - + KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = IoPageRead(PagingFileList[i]->FileObject, - Mdl, - &file_offset, - &Event, - &Iosb); + Mdl, + &file_offset, + &Event, + &Iosb); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); - return(Iosb.Status); + Status = Iosb.Status; } + MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl); return(Status); } -VOID INIT_FUNCTION +VOID +INIT_FUNCTION +NTAPI MmInitPagingFile(VOID) { ULONG i; - + KeInitializeSpinLock(&PagingFileListLock); - + MiFreeSwapPages = 0; MiUsedSwapPages = 0; MiReservedSwapPages = 0; - + for (i = 0; i < MAX_PAGING_FILES; i++) - { - PagingFileList[i] = NULL; - } + { + PagingFileList[i] = NULL; + } MiPagingFileCount = 0; /* * Initialize the crash dump support. */ if (MmCoreDumpType != MM_CORE_DUMP_TYPE_NONE) - { - MmCoreDumpPageFrame = MmAllocateSection(PAGE_SIZE); - if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL) - { - MmCoreDumpSize = MmStats.NrTotalPages * 4096 + 1024 * 1024; - } - else - { - MmCoreDumpSize = 1024 * 1024; - } - } + { + MmCoreDumpPageFrame = MmAllocateSection(PAGE_SIZE, NULL); + if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL) + { + MmCoreDumpSize = MmStats.NrTotalPages * 4096 + 1024 * 1024; + } + else + { + MmCoreDumpSize = 1024 * 1024; + } + } } BOOLEAN +NTAPI MmReserveSwapPages(ULONG Nr) { KIRQL oldIrql; ULONG MiAvailSwapPages; - + KeAcquireSpinLock(&PagingFileListLock, &oldIrql); MiAvailSwapPages = - (MiFreeSwapPages * MM_PAGEFILE_COMMIT_RATIO) + MM_PAGEFILE_COMMIT_GRACE; + (MiFreeSwapPages * MM_PAGEFILE_COMMIT_RATIO) + MM_PAGEFILE_COMMIT_GRACE; MiReservedSwapPages = MiReservedSwapPages + Nr; if (MM_PAGEFILE_COMMIT_RATIO != 0 && MiAvailSwapPages < MiReservedSwapPages) - { - KeReleaseSpinLock(&PagingFileListLock, oldIrql); - return(FALSE); - } + { + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + return(FALSE); + } KeReleaseSpinLock(&PagingFileListLock, oldIrql); return(TRUE); } -VOID +VOID +NTAPI MmDereserveSwapPages(ULONG Nr) { KIRQL oldIrql; - + KeAcquireSpinLock(&PagingFileListLock, &oldIrql); MiReservedSwapPages = MiReservedSwapPages - Nr; KeReleaseSpinLock(&PagingFileListLock, oldIrql); } -static ULONG +static ULONG MiAllocPageFromPagingFile(PPAGINGFILE PagingFile) { KIRQL oldIrql; ULONG i, j; - + KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql); - + for (i = 0; i < PagingFile->AllocMapSize; i++) - { - for (j = 0; j < 32; j++) - { - if (!(PagingFile->AllocMap[i] & (1 << j))) - { - break; - } - } - if (j == 32) - { - continue; - } - PagingFile->AllocMap[i] |= (1 << j); - PagingFile->UsedPages++; - PagingFile->FreePages--; - KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql); - return((i * 32) + j); - } - + { + for (j = 0; j < 32; j++) + { + if (!(PagingFile->AllocMap[i] & (1 << j))) + { + PagingFile->AllocMap[i] |= (1 << j); + PagingFile->UsedPages++; + PagingFile->FreePages--; + KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql); + return((i * 32) + j); + } + } + } + KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql); return(0xFFFFFFFF); } -VOID +VOID +NTAPI MmFreeSwapPage(SWAPENTRY Entry) { ULONG i; ULONG off; KIRQL oldIrql; - + i = FILE_FROM_ENTRY(Entry); off = OFFSET_FROM_ENTRY(Entry); - + + if (i >= MAX_PAGING_FILES) + { + DPRINT1("Bad swap entry 0x%.8X\n", Entry); + KEBUGCHECK(0); + } + KeAcquireSpinLock(&PagingFileListLock, &oldIrql); if (PagingFileList[i] == NULL) - { - KEBUGCHECK(0); - } + { + KEBUGCHECK(0); + } KeAcquireSpinLockAtDpcLevel(&PagingFileList[i]->AllocMapLock); - - PagingFileList[i]->AllocMap[off / 32] &= (~(1 << (off % 32))); - + + PagingFileList[i]->AllocMap[off >> 5] &= (~(1 << (off % 32))); + PagingFileList[i]->FreePages++; PagingFileList[i]->UsedPages--; - + MiFreeSwapPages++; MiUsedSwapPages--; - + KeReleaseSpinLockFromDpcLevel(&PagingFileList[i]->AllocMapLock); KeReleaseSpinLock(&PagingFileListLock, oldIrql); } BOOLEAN +NTAPI MmIsAvailableSwapPage(VOID) { - return(MiFreeSwapPages > 0); + return(MiFreeSwapPages > 0); } -SWAPENTRY +SWAPENTRY +NTAPI MmAllocSwapPage(VOID) { KIRQL oldIrql; ULONG i; ULONG off; - SWAPENTRY entry; - + SWAPENTRY entry; + KeAcquireSpinLock(&PagingFileListLock, &oldIrql); - + if (MiFreeSwapPages == 0) - { - KeReleaseSpinLock(&PagingFileListLock, oldIrql); - return(0); - } - + { + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + return(0); + } + for (i = 0; i < MAX_PAGING_FILES; i++) - { - if (PagingFileList[i] != NULL && - PagingFileList[i]->FreePages >= 1) - { - off = MiAllocPageFromPagingFile(PagingFileList[i]); - if (off == 0xFFFFFFFF) - { - KEBUGCHECK(0); - KeReleaseSpinLock(&PagingFileListLock, oldIrql); - return(STATUS_UNSUCCESSFUL); - } - MiUsedSwapPages++; - MiFreeSwapPages--; - KeReleaseSpinLock(&PagingFileListLock, oldIrql); - - entry = ENTRY_FROM_FILE_OFFSET(i, off); - return(entry); - } - } - - KeReleaseSpinLock(&PagingFileListLock, oldIrql); + { + if (PagingFileList[i] != NULL && + PagingFileList[i]->FreePages >= 1) + { + off = MiAllocPageFromPagingFile(PagingFileList[i]); + if (off == 0xFFFFFFFF) + { + KEBUGCHECK(0); + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + return(STATUS_UNSUCCESSFUL); + } + MiUsedSwapPages++; + MiFreeSwapPages--; + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + + entry = ENTRY_FROM_FILE_OFFSET(i, off); + return(entry); + } + } + + KeReleaseSpinLock(&PagingFileListLock, oldIrql); KEBUGCHECK(0); return(0); } -NTSTATUS STDCALL +STATIC PRETRIEVEL_DESCRIPTOR_LIST FASTCALL +MmAllocRetrievelDescriptorList(ULONG Pairs) +{ + ULONG Size; + PRETRIEVEL_DESCRIPTOR_LIST RetDescList; + + Size = sizeof(RETRIEVEL_DESCRIPTOR_LIST) + Pairs * 2 * sizeof(LARGE_INTEGER); + RetDescList = ExAllocatePool(NonPagedPool, Size); + if (RetDescList) + { + RtlZeroMemory(RetDescList, Size); + } + + return RetDescList; +} + +NTSTATUS STDCALL MmDumpToPagingFile(ULONG BugCode, - ULONG BugCodeParameter1, - ULONG BugCodeParameter2, - ULONG BugCodeParameter3, - ULONG BugCodeParameter4, - PKTRAP_FRAME TrapFrame) + ULONG BugCodeParameter1, + ULONG BugCodeParameter2, + ULONG BugCodeParameter3, + ULONG BugCodeParameter4, + PKTRAP_FRAME TrapFrame) { - PMM_CORE_DUMP_HEADER Headers; - NTSTATUS Status; - UCHAR MdlBase[sizeof(MDL) + sizeof(PVOID)]; - PMDL Mdl = (PMDL)MdlBase; - PETHREAD Thread = PsGetCurrentThread(); - ULONG StackSize; - PULONG MdlMap; - LONGLONG NextOffset = 0; - ULONG i; - PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers; - LARGE_INTEGER DiskOffset; - - if (MmCoreDumpPageFile == 0xFFFFFFFF) - { + PMM_CORE_DUMP_HEADER Headers; + NTSTATUS Status; + UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)]; + PMDL Mdl = (PMDL)MdlBase; + PETHREAD Thread = PsGetCurrentThread(); + ULONG_PTR StackSize; + PULONG MdlMap; + LONGLONG NextOffset = 0; + ULONG i; + PRETRIEVAL_POINTERS_BUFFER RetrievalPointers; + LARGE_INTEGER DiskOffset; + + if (MmCoreDumpPageFile == 0xFFFFFFFF) + { return(STATUS_UNSUCCESSFUL); - } + } - DbgPrint("\nMM: Dumping core: "); + DbgPrint("\nMM: Dumping core: "); - /* Prepare the dump headers. */ - Headers = (PMM_CORE_DUMP_HEADER)MmCoreDumpPageFrame; - Headers->Magic = MM_CORE_DUMP_HEADER_MAGIC; - Headers->Version = MM_CORE_DUMP_HEADER_VERSION; - Headers->Type = MmCoreDumpType; - if (TrapFrame != NULL) - { - if (!(TrapFrame->Eflags & (1 << 17))) - { - memcpy(&Headers->TrapFrame, TrapFrame, - sizeof(KTRAP_FRAME) - (4 * sizeof(DWORD))); - } + /* Prepare the dump headers. */ + Headers = (PMM_CORE_DUMP_HEADER)MmCoreDumpPageFrame; + Headers->Magic = MM_CORE_DUMP_HEADER_MAGIC; + Headers->Version = MM_CORE_DUMP_HEADER_VERSION; + Headers->Type = MmCoreDumpType; + if (TrapFrame != NULL) + { + if (!(TrapFrame->EFlags & (1 << 17))) + { + memcpy(&Headers->TrapFrame, TrapFrame, + sizeof(KTRAP_FRAME) - (4 * sizeof(DWORD))); + } else - { - memcpy(&Headers->TrapFrame, TrapFrame, sizeof(KTRAP_FRAME)); - } - } - Headers->BugCheckCode = BugCode; - Headers->BugCheckParameters[0] = BugCodeParameter1; - Headers->BugCheckParameters[1] = BugCodeParameter2; - Headers->BugCheckParameters[2] = BugCodeParameter3; - Headers->BugCheckParameters[3] = BugCodeParameter4; - Headers->FaultingStackBase = (PVOID)Thread->Tcb.StackLimit; - Headers->FaultingStackSize = StackSize = - (ULONG)(Thread->Tcb.StackBase - Thread->Tcb.StackLimit); - Headers->PhysicalMemorySize = MmStats.NrTotalPages * PAGE_SIZE; - - /* Initialize the dump device. */ - MmCoreDumpFunctions->DumpInit(); - if (!NT_SUCCESS(Status)) - { + { + memcpy(&Headers->TrapFrame, TrapFrame, sizeof(KTRAP_FRAME)); + } + } + Headers->BugCheckCode = BugCode; + Headers->BugCheckParameters[0] = BugCodeParameter1; + Headers->BugCheckParameters[1] = BugCodeParameter2; + Headers->BugCheckParameters[2] = BugCodeParameter3; + Headers->BugCheckParameters[3] = BugCodeParameter4; + Headers->FaultingStackBase = (PVOID)Thread->Tcb.StackLimit; + Headers->FaultingStackSize = + StackSize = (ULONG_PTR)Thread->Tcb.StackBase - (ULONG_PTR)Thread->Tcb.StackLimit; + Headers->PhysicalMemorySize = MmStats.NrTotalPages * PAGE_SIZE; + + /* Initialize the dump device. */ + Status = MmCoreDumpFunctions->DumpInit(); + if (!NT_SUCCESS(Status)) + { DPRINT1("MM: Failed to initialize core dump device.\n"); return(Status); - } + } - /* Initialize the MDL. */ - Mdl->Next = NULL; - Mdl->Size = sizeof(MDL) + sizeof(PVOID); - Mdl->MdlFlags = MDL_SOURCE_IS_NONPAGED_POOL; - Mdl->Process = NULL; - Mdl->MappedSystemVa = MmCoreDumpPageFrame; - Mdl->StartVa = NULL; - Mdl->ByteCount = PAGE_SIZE; - Mdl->ByteOffset = 0; - MdlMap = (PULONG)(Mdl + 1); - - - /* Initialize the retrieval offsets. */ - RetrievalPointers = PagingFileList[MmCoreDumpPageFile]->RetrievalPointers; - - /* Dump the header. */ - MdlMap[0] = MmGetPhysicalAddress(MmCoreDumpPageFrame).u.LowPart; - DiskOffset = MmGetOffsetPageFile(RetrievalPointers, (LARGE_INTEGER)0LL); - DiskOffset.QuadPart += MmCoreDumpLcnMapping.LcnDiskOffset.QuadPart; - Status = MmCoreDumpFunctions->DumpWrite(DiskOffset, Mdl); - if (!NT_SUCCESS(Status)) - { + /* Initialize the MDL. */ + MmInitializeMdl(Mdl, MmCoreDumpPageFrame, PAGE_SIZE); + Mdl->MdlFlags = MDL_PAGES_LOCKED|MDL_IO_PAGE_READ|MDL_SOURCE_IS_NONPAGED_POOL; + MdlMap = (PULONG)(Mdl + 1); + + + /* Initialize the retrieval offsets. */ + RetrievalPointers = PagingFileList[MmCoreDumpPageFile]->RetrievalPointers; + + /* Dump the header. */ + MdlMap[0] = MmGetPhysicalAddress(MmCoreDumpPageFrame).QuadPart >> PAGE_SHIFT; +#if defined(__GNUC__) + + DiskOffset = MmGetOffsetPageFile(RetrievalPointers, (LARGE_INTEGER)0LL); +#else + + { + const LARGE_INTEGER dummy = + { + 0 + }; + DiskOffset = MmGetOffsetPageFile(RetrievalPointers, dummy); + } +#endif + DiskOffset.QuadPart += MmCoreDumpLcnMapping.LcnDiskOffset.QuadPart; + Status = MmCoreDumpFunctions->DumpWrite(DiskOffset, Mdl); + if (!NT_SUCCESS(Status)) + { DPRINT1("MM: Failed to write core dump header\n."); return(Status); - } - NextOffset += PAGE_SIZE;; - DbgPrint("00"); + } + NextOffset += PAGE_SIZE; + ; + DbgPrint("00"); - - /* Write out the contents of physical memory. */ - if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL) - { + + /* Write out the contents of physical memory. */ + if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL) + { for (i = 0; i < MmStats.NrTotalPages; i++) - { - LARGE_INTEGER PhysicalAddress; - PhysicalAddress.QuadPart = i * PAGE_SIZE; - MdlMap[0] = i * PAGE_SIZE; - MmCreateVirtualMappingDump(MmCoreDumpPageFrame, - PAGE_READWRITE, - PhysicalAddress); - DiskOffset = MmGetOffsetPageFile(RetrievalPointers, - (LARGE_INTEGER)NextOffset); - DiskOffset.QuadPart += MmCoreDumpLcnMapping.LcnDiskOffset.QuadPart; - Status = MmCoreDumpFunctions->DumpWrite(DiskOffset, Mdl); - if (!NT_SUCCESS(Status)) - { - DPRINT1("MM: Failed to write page to core dump.\n"); - return(Status); - } - if ((i % ((1024*1024) / PAGE_SIZE)) == 0) - { - DbgPrint("\b\b%.2d", i / ((1024*1024)/PAGE_SIZE)); - } - NextOffset += PAGE_SIZE; - } - } + { + MdlMap[0] = i; + MmCreateVirtualMappingForKernel(MmCoreDumpPageFrame, + PAGE_READWRITE, + MdlMap, + 1); +#if defined(__GNUC__) + + DiskOffset = MmGetOffsetPageFile(RetrievalPointers, + (LARGE_INTEGER)NextOffset); +#else - DbgPrint("\n"); - MmCoreDumpFunctions->DumpFinish(); - return(STATUS_SUCCESS); + { + LARGE_INTEGER dummy; + dummy.QuadPart = NextOffset; + DiskOffset = MmGetOffsetPageFile(RetrievalPointers, dummy); + } +#endif + DiskOffset.QuadPart += MmCoreDumpLcnMapping.LcnDiskOffset.QuadPart; + Status = MmCoreDumpFunctions->DumpWrite(DiskOffset, Mdl); + MmRawDeleteVirtualMapping(MmCoreDumpPageFrame); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MM: Failed to write page to core dump.\n"); + return(Status); + } + if ((i % ((1024*1024) / PAGE_SIZE)) == 0) + { + DbgPrint("\b\b%.2d", i / ((1024*1024)/PAGE_SIZE)); + } + NextOffset += PAGE_SIZE; + } + } + + DbgPrint("\n"); + MmCoreDumpFunctions->DumpFinish(); + return(STATUS_SUCCESS); } NTSTATUS STDCALL MmInitializeCrashDump(HANDLE PageFileHandle, ULONG PageFileNum) { - PFILE_OBJECT PageFile; - PDEVICE_OBJECT PageFileDevice; - NTSTATUS Status; - PIRP Irp; - KEVENT Event; - IO_STATUS_BLOCK Iosb; - UNICODE_STRING DiskDumpName; - ANSI_STRING ProcName; - PIO_STACK_LOCATION StackPtr; - PMODULE_OBJECT ModuleObject; - - Status = ZwFsControlFile(PageFileHandle, - 0, - NULL, - NULL, - &Iosb, - FSCTL_ROS_QUERY_LCN_MAPPING, - NULL, - 0, - &MmCoreDumpLcnMapping, - sizeof(ROS_QUERY_LCN_MAPPING)); - if (!NT_SUCCESS(Status) || - Iosb.Information != sizeof(ROS_QUERY_LCN_MAPPING)) - { + PFILE_OBJECT PageFile; + PDEVICE_OBJECT PageFileDevice; + NTSTATUS Status; + PIRP Irp; + KEVENT Event; + IO_STATUS_BLOCK Iosb; + UNICODE_STRING DiskDumpName = RTL_CONSTANT_STRING(L"DiskDump"); + ANSI_STRING ProcName; + PIO_STACK_LOCATION StackPtr; + PLDR_DATA_TABLE_ENTRY ModuleObject; + + Status = ZwFsControlFile(PageFileHandle, + 0, + NULL, + NULL, + &Iosb, + FSCTL_ROS_QUERY_LCN_MAPPING, + NULL, + 0, + &MmCoreDumpLcnMapping, + sizeof(ROS_QUERY_LCN_MAPPING)); + if (!NT_SUCCESS(Status) || + Iosb.Information != sizeof(ROS_QUERY_LCN_MAPPING)) + { return(Status); - } + } - /* Get the underlying storage device. */ - Status = - ObReferenceObjectByHandle(PageFileHandle, - FILE_ALL_ACCESS, - NULL, - KernelMode, - (PVOID*)&PageFile, - NULL); - if (!NT_SUCCESS(Status)) - { + /* Get the underlying storage device. */ + Status = + ObReferenceObjectByHandle(PageFileHandle, + FILE_ALL_ACCESS, + NULL, + KernelMode, + (PVOID*)&PageFile, + NULL); + if (!NT_SUCCESS(Status)) + { return(Status); - } + } - PageFileDevice = PageFile->Vpb->RealDevice; - - /* Get the dump pointers. */ - KeInitializeEvent(&Event, NotificationEvent, FALSE); - Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_DUMP_POINTERS, - PageFileDevice, - NULL, - 0, - &MmCoreDumpPointers, - sizeof(MmCoreDumpPointers), - FALSE, - &Event, - &Iosb); - StackPtr = IoGetNextIrpStackLocation(Irp); - StackPtr->FileObject = PageFile; - StackPtr->DeviceObject = PageFileDevice; - StackPtr->Parameters.DeviceIoControl.InputBufferLength = 0; - StackPtr->Parameters.DeviceIoControl.OutputBufferLength = sizeof(MmCoreDumpPointers); - - Status = IoCallDriver(PageFileDevice,Irp); - if (Status == STATUS_PENDING) - { + PageFileDevice = PageFile->Vpb->RealDevice; + + /* Get the dump pointers. */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_DUMP_POINTERS, + PageFileDevice, + NULL, + 0, + &MmCoreDumpPointers, + sizeof(MmCoreDumpPointers), + FALSE, + &Event, + &Iosb); + if(Irp == NULL) + { + ObDereferenceObject(PageFile); + return(STATUS_NO_MEMORY);// tMk - is this correct return code ??? + } + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = PageFile; + StackPtr->DeviceObject = PageFileDevice; + StackPtr->Parameters.DeviceIoControl.InputBufferLength = 0; + StackPtr->Parameters.DeviceIoControl.OutputBufferLength = sizeof(MmCoreDumpPointers); + + Status = IoCallDriver(PageFileDevice,Irp); + if (Status == STATUS_PENDING) + { Status = KeWaitForSingleObject(&Event, - Executive, - KernelMode, - FALSE, - NULL); - } - if (Status != STATUS_SUCCESS || - Iosb.Information != sizeof(MmCoreDumpPointers)) - { + Executive, + KernelMode, + FALSE, + NULL); + } + if (Status != STATUS_SUCCESS || + Iosb.Information != sizeof(MmCoreDumpPointers)) + { ObDereferenceObject(PageFile); return(Status); - } + } - /* Load the diskdump driver. */ - RtlRosInitUnicodeStringFromLiteral(&DiskDumpName, L"DiskDump"); - ModuleObject = LdrGetModuleObject(&DiskDumpName); - if (ModuleObject == NULL) - { + /* Load the diskdump driver. */ + ModuleObject = LdrGetModuleObject(&DiskDumpName); + if (ModuleObject == NULL) + { return(STATUS_OBJECT_NAME_NOT_FOUND); - } - RtlInitAnsiString(&ProcName, "DiskDumpFunctions"); - Status = LdrGetProcedureAddress(ModuleObject->Base, - &ProcName, - 0, - (PVOID*)&MmCoreDumpFunctions); - if (!NT_SUCCESS(Status)) - { + } + RtlInitAnsiString(&ProcName, "DiskDumpFunctions"); + Status = LdrGetProcedureAddress(ModuleObject->DllBase, + &ProcName, + 0, + (PVOID*)&MmCoreDumpFunctions); + if (!NT_SUCCESS(Status)) + { ObDereferenceObject(PageFile); return(Status); - } + } - /* Prepare for disk dumping. */ - Status = MmCoreDumpFunctions->DumpPrepare(PageFileDevice, - &MmCoreDumpPointers); - if (!NT_SUCCESS(Status)) - { + /* Prepare for disk dumping. */ + Status = MmCoreDumpFunctions->DumpPrepare(PageFileDevice, + &MmCoreDumpPointers); + if (!NT_SUCCESS(Status)) + { ObDereferenceObject(PageFile); return(Status); - } + } - MmCoreDumpPageFile = PageFileNum; - ObDereferenceObject(PageFile); - return(STATUS_SUCCESS); + MmCoreDumpPageFile = PageFileNum; + ObDereferenceObject(PageFile); + return(STATUS_SUCCESS); } NTSTATUS STDCALL NtCreatePagingFile(IN PUNICODE_STRING FileName, - IN PLARGE_INTEGER InitialSize, - IN PLARGE_INTEGER MaximumSize, - IN ULONG Reserved) + IN PLARGE_INTEGER InitialSize, + IN PLARGE_INTEGER MaximumSize, + IN ULONG Reserved) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; @@ -694,7 +784,6 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, PPAGINGFILE PagingFile; KIRQL oldIrql; ULONG AllocMapSize; - ULONG Size; FILE_FS_SIZE_INFORMATION FsSizeInformation; PRETRIEVEL_DESCRIPTOR_LIST RetDescList; PRETRIEVEL_DESCRIPTOR_LIST CurrentRetDescList; @@ -702,259 +791,333 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, ULONG BytesPerAllocationUnit; LARGE_INTEGER Vcn; ULONG ExtentCount; - ULONG MaxVcn; + LARGE_INTEGER MaxVcn; ULONG Count; + ULONG Size; + KPROCESSOR_MODE PreviousMode; + UNICODE_STRING CapturedFileName; + LARGE_INTEGER SafeInitialSize, SafeMaximumSize; DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n", - FileName, InitialSize->QuadPart); - + FileName, InitialSize->QuadPart); + if (MiPagingFileCount >= MAX_PAGING_FILES) - { - return(STATUS_TOO_MANY_PAGING_FILES); - } - + { + return(STATUS_TOO_MANY_PAGING_FILES); + } + + PreviousMode = ExGetPreviousMode(); + + if (PreviousMode != KernelMode) + { + _SEH_TRY + { + SafeInitialSize = ProbeForReadLargeInteger(InitialSize); + SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if (!NT_SUCCESS(Status)) + { + return Status; + } + } + else + { + SafeInitialSize = *InitialSize; + SafeMaximumSize = *MaximumSize; + } + + /* Pagefiles can't be larger than 4GB and ofcourse the minimum should be + smaller than the maximum */ + if (0 != SafeInitialSize.u.HighPart) + { + return STATUS_INVALID_PARAMETER_2; + } + if (0 != SafeMaximumSize.u.HighPart) + { + return STATUS_INVALID_PARAMETER_3; + } + if (SafeMaximumSize.u.LowPart < SafeInitialSize.u.LowPart) + { + return STATUS_INVALID_PARAMETER_MIX; + } + + Status = ProbeAndCaptureUnicodeString(&CapturedFileName, + PreviousMode, + FileName); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + InitializeObjectAttributes(&ObjectAttributes, - FileName, - 0, - NULL, - NULL); - + &CapturedFileName, + 0, + NULL, + NULL); + Status = IoCreateFile(&FileHandle, - FILE_ALL_ACCESS, - &ObjectAttributes, - &IoStatus, - NULL, - 0, - 0, - FILE_OPEN_IF, - FILE_SYNCHRONOUS_IO_NONALERT, - NULL, - 0, - CreateFileTypeNone, - NULL, - SL_OPEN_PAGING_FILE); + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoStatus, + NULL, + 0, + 0, + FILE_OPEN_IF, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0, + CreateFileTypeNone, + NULL, + SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING); + + ReleaseCapturedUnicodeString(&CapturedFileName, + PreviousMode); if (!NT_SUCCESS(Status)) - { - return(Status); - } - - Status = NtQueryVolumeInformationFile(FileHandle, + { + return(Status); + } + + Status = ZwQueryVolumeInformationFile(FileHandle, &IoStatus, - &FsSizeInformation, - sizeof(FILE_FS_SIZE_INFORMATION), - FileFsSizeInformation); + &FsSizeInformation, + sizeof(FILE_FS_SIZE_INFORMATION), + FileFsSizeInformation); if (!NT_SUCCESS(Status)) - { - NtClose(FileHandle); - return Status; - } - - BytesPerAllocationUnit = FsSizeInformation.SectorsPerAllocationUnit * FsSizeInformation.BytesPerSector; + { + ZwClose(FileHandle); + return Status; + } + + BytesPerAllocationUnit = FsSizeInformation.SectorsPerAllocationUnit * + FsSizeInformation.BytesPerSector; + /* FIXME: If we have 2048 BytesPerAllocationUnit (FAT16 < 128MB) there is + * a problem if the paging file is fragmented. Suppose the first cluster + * of the paging file is cluster 3042 but cluster 3043 is NOT part of the + * paging file but of another file. We can't write a complete page (4096 + * bytes) to the physical location of cluster 3042 then. */ if (BytesPerAllocationUnit % PAGE_SIZE) - { - NtClose(FileHandle); - return STATUS_UNSUCCESSFUL; - } - - Status = NtSetInformationFile(FileHandle, - &IoStatus, - InitialSize, - sizeof(LARGE_INTEGER), - FileAllocationInformation); + { + DPRINT1("BytesPerAllocationUnit %d is not a multiple of PAGE_SIZE %d\n", + BytesPerAllocationUnit, PAGE_SIZE); + ZwClose(FileHandle); + return STATUS_UNSUCCESSFUL; + } + + Status = ZwSetInformationFile(FileHandle, + &IoStatus, + &SafeInitialSize, + sizeof(LARGE_INTEGER), + FileAllocationInformation); if (!NT_SUCCESS(Status)) - { - NtClose(FileHandle); - return(Status); - } + { + ZwClose(FileHandle); + return(Status); + } Status = ObReferenceObjectByHandle(FileHandle, - FILE_ALL_ACCESS, - IoFileObjectType, - UserMode, - (PVOID*)&FileObject, - NULL); + FILE_ALL_ACCESS, + IoFileObjectType, + PreviousMode, + (PVOID*)&FileObject, + NULL); if (!NT_SUCCESS(Status)) - { - NtClose(FileHandle); - return(Status); - } + { + ZwClose(FileHandle); + return(Status); + } - Size = sizeof(RETRIEVEL_DESCRIPTOR_LIST) + PAIRS_PER_RUN * sizeof(MAPPING_PAIR); - CurrentRetDescList = RetDescList = ExAllocatePool(NonPagedPool, Size); + CurrentRetDescList = RetDescList = MmAllocRetrievelDescriptorList(PAIRS_PER_RUN); if (CurrentRetDescList == NULL) - { - ObDereferenceObject(FileObject); - NtClose(FileHandle); - return(STATUS_NO_MEMORY); - } + { + ObDereferenceObject(FileObject); + ZwClose(FileHandle); + return(STATUS_NO_MEMORY); + } +#if defined(__GNUC__) Vcn.QuadPart = 0LL; +#else + + Vcn.QuadPart = 0; +#endif + ExtentCount = 0; - MaxVcn = (InitialSize->QuadPart + BytesPerAllocationUnit - 1) / BytesPerAllocationUnit; + MaxVcn.QuadPart = (SafeInitialSize.QuadPart + BytesPerAllocationUnit - 1) / BytesPerAllocationUnit; while(1) - { - Status = NtFsControlFile(FileHandle, - 0, - NULL, - NULL, - &IoStatus, - FSCTL_GET_RETRIEVAL_POINTERS, - &Vcn, - sizeof(LARGE_INTEGER), - &CurrentRetDescList->RetrievalPointers, - sizeof(GET_RETRIEVAL_DESCRIPTOR) + PAIRS_PER_RUN * sizeof(MAPPING_PAIR)); - if (!NT_SUCCESS(Status)) - { - while (RetDescList) - { - CurrentRetDescList = RetDescList; - RetDescList = RetDescList->Next; - ExFreePool(CurrentRetDescList); - } - ObDereferenceObject(FileObject); - NtClose(FileHandle); - return(Status); - } - ExtentCount += CurrentRetDescList->RetrievalPointers.NumberOfPairs; - if ((ULONG)CurrentRetDescList->RetrievalPointers.Pair[CurrentRetDescList->RetrievalPointers.NumberOfPairs-1].Vcn < MaxVcn) + { + Status = ZwFsControlFile(FileHandle, + 0, + NULL, + NULL, + &IoStatus, + FSCTL_GET_RETRIEVAL_POINTERS, + &Vcn, + sizeof(LARGE_INTEGER), + &CurrentRetDescList->RetrievalPointers, + sizeof(RETRIEVAL_POINTERS_BUFFER) + PAIRS_PER_RUN * 2 * sizeof(LARGE_INTEGER)); + if (!NT_SUCCESS(Status)) + { + while (RetDescList) { - CurrentRetDescList->Next = ExAllocatePool(NonPagedPool, Size); - if (CurrentRetDescList->Next == NULL) - { - while (RetDescList) - { - CurrentRetDescList = RetDescList; - RetDescList = RetDescList->Next; - ExFreePool(CurrentRetDescList); - } - ObDereferenceObject(FileObject); - NtClose(FileHandle); - return(STATUS_NO_MEMORY); - } - Vcn.QuadPart = CurrentRetDescList->RetrievalPointers.Pair[CurrentRetDescList->RetrievalPointers.NumberOfPairs-1].Vcn; - CurrentRetDescList = CurrentRetDescList->Next; + CurrentRetDescList = RetDescList; + RetDescList = RetDescList->Next; + ExFreePool(CurrentRetDescList); } - else + ObDereferenceObject(FileObject); + ZwClose(FileHandle); + return(Status); + } + ExtentCount += CurrentRetDescList->RetrievalPointers.ExtentCount; + if (CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn.QuadPart < MaxVcn.QuadPart) + { + CurrentRetDescList->Next = MmAllocRetrievelDescriptorList(PAIRS_PER_RUN); + if (CurrentRetDescList->Next == NULL) { - break; + while (RetDescList) + { + CurrentRetDescList = RetDescList; + RetDescList = RetDescList->Next; + ExFreePool(CurrentRetDescList); + } + ObDereferenceObject(FileObject); + ZwClose(FileHandle); + return(STATUS_NO_MEMORY); } - } + Vcn = CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn; + CurrentRetDescList = CurrentRetDescList->Next; + } + else + { + break; + } + } PagingFile = ExAllocatePool(NonPagedPool, sizeof(*PagingFile)); if (PagingFile == NULL) - { - while (RetDescList) - { - CurrentRetDescList = RetDescList; - RetDescList = RetDescList->Next; - ExFreePool(CurrentRetDescList); - } - ObDereferenceObject(FileObject); - NtClose(FileHandle); - return(STATUS_NO_MEMORY); - } - + { + while (RetDescList) + { + CurrentRetDescList = RetDescList; + RetDescList = RetDescList->Next; + ExFreePool(CurrentRetDescList); + } + ObDereferenceObject(FileObject); + ZwClose(FileHandle); + return(STATUS_NO_MEMORY); + } + + RtlZeroMemory(PagingFile, sizeof(*PagingFile)); + PagingFile->FileObject = FileObject; - PagingFile->MaximumSize.QuadPart = MaximumSize->QuadPart; - PagingFile->CurrentSize.QuadPart = InitialSize->QuadPart; - PagingFile->FreePages = InitialSize->QuadPart / PAGE_SIZE; + PagingFile->MaximumSize.QuadPart = SafeMaximumSize.QuadPart; + PagingFile->CurrentSize.QuadPart = SafeInitialSize.QuadPart; + PagingFile->FreePages = (ULONG)(SafeInitialSize.QuadPart / PAGE_SIZE); PagingFile->UsedPages = 0; KeInitializeSpinLock(&PagingFile->AllocMapLock); - + AllocMapSize = (PagingFile->FreePages / 32) + 1; - PagingFile->AllocMap = ExAllocatePool(NonPagedPool, - AllocMapSize * sizeof(ULONG)); + PagingFile->AllocMap = ExAllocatePool(NonPagedPool, + AllocMapSize * sizeof(ULONG)); PagingFile->AllocMapSize = AllocMapSize; - + if (PagingFile->AllocMap == NULL) - { - while (RetDescList) - { - CurrentRetDescList = RetDescList; - RetDescList = RetDescList->Next; - ExFreePool(CurrentRetDescList); - } - ExFreePool(PagingFile); - ObDereferenceObject(FileObject); - ZwClose(FileHandle); - return(STATUS_NO_MEMORY); - } + { + while (RetDescList) + { + CurrentRetDescList = RetDescList; + RetDescList = RetDescList->Next; + ExFreePool(CurrentRetDescList); + } + ExFreePool(PagingFile); + ObDereferenceObject(FileObject); + ZwClose(FileHandle); + return(STATUS_NO_MEMORY); + } DPRINT("ExtentCount: %d\n", ExtentCount); - Size = sizeof(GET_RETRIEVAL_DESCRIPTOR) + ExtentCount * sizeof(MAPPING_PAIR); + Size = sizeof(RETRIEVAL_POINTERS_BUFFER) + ExtentCount * 2 * sizeof(LARGE_INTEGER); PagingFile->RetrievalPointers = ExAllocatePool(NonPagedPool, Size); if (PagingFile->RetrievalPointers == NULL) { - while (RetDescList) - { - CurrentRetDescList = RetDescList; - RetDescList = RetDescList->Next; - ExFreePool(CurrentRetDescList); - } + while (RetDescList) + { + CurrentRetDescList = RetDescList; + RetDescList = RetDescList->Next; + ExFreePool(CurrentRetDescList); + } ExFreePool(PagingFile->AllocMap); ExFreePool(PagingFile); ObDereferenceObject(FileObject); - NtClose(FileHandle); + ZwClose(FileHandle); return(STATUS_NO_MEMORY); } + RtlZeroMemory(PagingFile->AllocMap, AllocMapSize * sizeof(ULONG)); + RtlZeroMemory(PagingFile->RetrievalPointers, Size); + Count = 0; - PagingFile->RetrievalPointers->NumberOfPairs = ExtentCount; - PagingFile->RetrievalPointers->StartVcn = RetDescList->RetrievalPointers.StartVcn; + PagingFile->RetrievalPointers->ExtentCount = ExtentCount; + PagingFile->RetrievalPointers->StartingVcn = RetDescList->RetrievalPointers.StartingVcn; CurrentRetDescList = RetDescList; while (CurrentRetDescList) - { - memcpy(&PagingFile->RetrievalPointers->Pair[Count], - CurrentRetDescList->RetrievalPointers.Pair, - CurrentRetDescList->RetrievalPointers.NumberOfPairs * sizeof(MAPPING_PAIR)); - Count += CurrentRetDescList->RetrievalPointers.NumberOfPairs; - RetDescList = CurrentRetDescList; - CurrentRetDescList = CurrentRetDescList->Next; - ExFreePool(RetDescList); - } - - if (PagingFile->RetrievalPointers->NumberOfPairs != ExtentCount || - (ULONG)PagingFile->RetrievalPointers->Pair[ExtentCount - 1].Vcn != MaxVcn) - { - ExFreePool(PagingFile->RetrievalPointers); - ExFreePool(PagingFile->AllocMap); - ExFreePool(PagingFile); - ObDereferenceObject(FileObject); - NtClose(FileHandle); - return(STATUS_UNSUCCESSFUL); - } - - /* + { + memcpy(&PagingFile->RetrievalPointers->Extents[Count], + CurrentRetDescList->RetrievalPointers.Extents, + CurrentRetDescList->RetrievalPointers.ExtentCount * 2 * sizeof(LARGE_INTEGER)); + Count += CurrentRetDescList->RetrievalPointers.ExtentCount; + RetDescList = CurrentRetDescList; + CurrentRetDescList = CurrentRetDescList->Next; + ExFreePool(RetDescList); + } + + if (PagingFile->RetrievalPointers->ExtentCount != ExtentCount || + PagingFile->RetrievalPointers->Extents[ExtentCount - 1].NextVcn.QuadPart != MaxVcn.QuadPart) + { + ExFreePool(PagingFile->RetrievalPointers); + ExFreePool(PagingFile->AllocMap); + ExFreePool(PagingFile); + ObDereferenceObject(FileObject); + ZwClose(FileHandle); + return(STATUS_UNSUCCESSFUL); + } + + /* * Change the entries from lcn's to volume offset's. */ - PagingFile->RetrievalPointers->StartVcn *= BytesPerAllocationUnit; + PagingFile->RetrievalPointers->StartingVcn.QuadPart *= BytesPerAllocationUnit; for (i = 0; i < ExtentCount; i++) - { - PagingFile->RetrievalPointers->Pair[i].Lcn *= BytesPerAllocationUnit; - PagingFile->RetrievalPointers->Pair[i].Vcn *= BytesPerAllocationUnit; - } + { + PagingFile->RetrievalPointers->Extents[i].Lcn.QuadPart *= BytesPerAllocationUnit; + PagingFile->RetrievalPointers->Extents[i].NextVcn.QuadPart *= BytesPerAllocationUnit; + } KeAcquireSpinLock(&PagingFileListLock, &oldIrql); for (i = 0; i < MAX_PAGING_FILES; i++) - { - if (PagingFileList[i] == NULL) - { - PagingFileList[i] = PagingFile; - break; - } - } + { + if (PagingFileList[i] == NULL) + { + PagingFileList[i] = PagingFile; + break; + } + } MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages; MiPagingFileCount++; KeReleaseSpinLock(&PagingFileListLock, oldIrql); - + /* Check whether this pagefile can be a crash dump target. */ if (MmCoreDumpType != MM_CORE_DUMP_TYPE_NONE && - PagingFile->CurrentSize.QuadPart >= MmCoreDumpSize && - MmCoreDumpPageFile == 0xFFFFFFFF) - { - MmInitializeCrashDump(FileHandle, i); - } - NtClose(FileHandle); + PagingFile->CurrentSize.QuadPart >= MmCoreDumpSize && + MmCoreDumpPageFile == 0xFFFFFFFF) + { + MmInitializeCrashDump(FileHandle, i); + } + ZwClose(FileHandle); MmSwapSpaceMessage = FALSE;