Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284/* * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * PROJECT: ReactOS kernel * FILE: ntoskrnl/cache/section/reqtools.c * PURPOSE: Implements section objects * * PROGRAMMERS: Rex Jolliff * David Welch * Eric Kohl * Emanuele Aliberti * Eugene Ingerman * Casper Hornstrup * KJK::Hyperion * Guido de Jong * Ge van Geldorp * Royce Mitchell III * Filip Navara * Aleksey Bragin * Jason Filby * Thomas Weidenmueller * Gunnar Andre' Dalsnes * Mike Nordell * Alex Ionescu * Gregor Anich * Steven Edwards * Herve Poussineau */
/* This file contains functions used by fault.c to do blocking resource acquisition. To call one of these functions, fill out your MM_REQUIRED_RESOURCES with a pointer to the desired function and configure the other members as below. */
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>#include "newmm.h"#define NDEBUG#include <debug.h>
#define DPRINTC DPRINT
VOIDNTAPIMmBuildMdlFromPages(PMDL Mdl, PPFN_NUMBER Pages);
/*
Blocking function to acquire zeroed pages from the balancer.
Upon entry:
Required->Amount: Number of pages to acquireRequired->Consumer: consumer to charge the page to
Upon return:
Required->Pages[0..Amount]: Allocated pages.
The function fails unless all requested pages can be allocated.
*/NTSTATUSNTAPIMiGetOnePage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES Required){ ULONG i; NTSTATUS Status = STATUS_SUCCESS;
for (i = 0; i < Required->Amount; i++) { DPRINTC("MiGetOnePage(%s:%d)\n", Required->File, Required->Line); Status = MmRequestPageMemoryConsumer(Required->Consumer, TRUE, &Required->Page[i]); if (!NT_SUCCESS(Status)) { while (i > 0) { MmReleasePageMemoryConsumer(Required->Consumer, Required->Page[i-1]); i--; } return Status; } }
return Status;}
/*
Blocking function to read (part of) a page from a file.
Upon entry:
Required->Context: a FILE_OBJECT to readRequired->Consumer: consumer to charge the page toRequired->FileOffset: Offset to read atRequired->Amount: Number of bytes to read (0 -> 4096)
Upon return:
Required->Page[Required->Offset]: The allocated and read in page
The indicated page is filled to Required->Amount with file data and zeroedafterward.
*/
NTSTATUSNTAPIMiReadFilePage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES RequiredResources){ PFILE_OBJECT FileObject = RequiredResources->Context; PPFN_NUMBER Page = &RequiredResources->Page[RequiredResources->Offset]; PLARGE_INTEGER FileOffset = &RequiredResources->FileOffset; NTSTATUS Status; PVOID PageBuf = NULL; KEVENT Event; IO_STATUS_BLOCK IOSB; UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)]; PMDL Mdl = (PMDL)MdlBase; KIRQL OldIrql;
DPRINTC("Pulling page %I64x from %wZ to %Ix\n", FileOffset->QuadPart, &FileObject->FileName, *Page);
Status = MmRequestPageMemoryConsumer(RequiredResources->Consumer, TRUE, Page);
if (!NT_SUCCESS(Status)) { DPRINT1("Status: %x\n", Status); return Status; }
MmInitializeMdl(Mdl, NULL, PAGE_SIZE); MmBuildMdlFromPages(Mdl, Page); Mdl->MdlFlags |= MDL_PAGES_LOCKED;
KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = IoPageRead(FileObject, Mdl, FileOffset, &Event, &IOSB); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = IOSB.Status; } if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) { MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); }
PageBuf = MiMapPageInHyperSpace(PsGetCurrentProcess(), *Page, &OldIrql); if (!PageBuf) { MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page); return STATUS_NO_MEMORY; }
RtlZeroMemory((PCHAR)PageBuf+RequiredResources->Amount, PAGE_SIZE-RequiredResources->Amount);
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PageBuf, OldIrql);
DPRINT("Read Status %x (Page %x)\n", Status, *Page);
if (!NT_SUCCESS(Status)) { MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page); DPRINT("Status: %x\n", Status); return Status; }
return STATUS_SUCCESS;}
/*
Blocking function to read a swap page into a memory page.
Upon entry:
Required->Consumer: consumer to charge the page toRequired->SwapEntry: swap entry to use
Upon return:
Required->Page[Required->Offset]: Populated page
*/
NTSTATUSNTAPIMiSwapInPage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES Resources){ NTSTATUS Status;
Status = MmRequestPageMemoryConsumer(Resources->Consumer, TRUE, &Resources->Page[Resources->Offset]); if (!NT_SUCCESS(Status)) { DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status); return Status; }
Status = MmReadFromSwapPage(Resources->SwapEntry, Resources->Page[Resources->Offset]); if (!NT_SUCCESS(Status)) { DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status); return Status; }
MmSetSavedSwapEntryPage(Resources->Page[Resources->Offset], Resources->SwapEntry);
DPRINT1("MiSwapInPage(%x,%x)\n", Resources->Page[Resources->Offset], Resources->SwapEntry);
return Status;}
/*
A way to write a page without a lock acquired using the same blocking mechanismas resource acquisition.
Upon entry:
Required->Page[Required->Offset]: Page to writeRequired->Context: FILE_OBJECT to write toRequired->FileOffset: offset to write at
This always does a paging write with whole page size. Note that paging IOdoesn't change the valid data length of a file.
*/
NTSTATUSNTAPIMiWriteFilePage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES Required){ DPRINT1("MiWriteFilePage(%x,%x)\n", Required->Page[Required->Offset], Required->FileOffset.LowPart);
return MiWriteBackPage(Required->Context, &Required->FileOffset, PAGE_SIZE, Required->Page[Required->Offset]);}