mirror of
https://github.com/reactos/reactos.git
synced 2024-09-19 17:21:14 +00:00
270 lines
6.8 KiB
C
270 lines
6.8 KiB
C
|
/*
|
||
|
* 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/mm/section.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
|
||
|
*/
|
||
|
|
||
|
/* INCLUDES *****************************************************************/
|
||
|
|
||
|
#include <ntoskrnl.h>
|
||
|
#include "newmm.h"
|
||
|
#define NDEBUG
|
||
|
#include <debug.h>
|
||
|
|
||
|
#define DPRINTC DPRINT
|
||
|
|
||
|
NTSTATUS
|
||
|
NTAPI
|
||
|
MiGetOnePage
|
||
|
(PMMSUPPORT AddressSpace,
|
||
|
PMEMORY_AREA MemoryArea,
|
||
|
PMM_REQUIRED_RESOURCES Required)
|
||
|
{
|
||
|
int 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(MC_CACHE, Required->Page[i-1]);
|
||
|
i--;
|
||
|
}
|
||
|
return Status;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
NTAPI
|
||
|
MiReadFilePage
|
||
|
(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;
|
||
|
PMEMORY_AREA TmpArea;
|
||
|
IO_STATUS_BLOCK IOSB;
|
||
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||
|
|
||
|
BoundaryAddressMultiple.QuadPart = 0;
|
||
|
|
||
|
DPRINTC
|
||
|
("Pulling page %08x%08x from %wZ to %x\n",
|
||
|
FileOffset->u.HighPart, FileOffset->u.LowPart,
|
||
|
&FileObject->FileName,
|
||
|
Page);
|
||
|
|
||
|
Status = MmRequestPageMemoryConsumer(RequiredResources->Consumer, TRUE, Page);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
DPRINT1("Status: %x\n", Status);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||
|
Status = MmCreateMemoryArea
|
||
|
(MmGetKernelAddressSpace(),
|
||
|
MEMORY_AREA_VIRTUAL_MEMORY,
|
||
|
&PageBuf,
|
||
|
PAGE_SIZE,
|
||
|
PAGE_READWRITE,
|
||
|
&TmpArea,
|
||
|
FALSE,
|
||
|
MEM_TOP_DOWN,
|
||
|
BoundaryAddressMultiple);
|
||
|
|
||
|
DPRINT("Status %x, PageBuf %x\n", Status, PageBuf);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
DPRINT1("STATUS_NO_MEMORY: %x\n", Status);
|
||
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||
|
MmReleasePageMemoryConsumer(MC_CACHE, *Page);
|
||
|
return STATUS_NO_MEMORY;
|
||
|
}
|
||
|
|
||
|
Status = MmCreateVirtualMapping(NULL, PageBuf, PAGE_READWRITE, Page, 1);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL);
|
||
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||
|
MmReleasePageMemoryConsumer(MC_CACHE, *Page);
|
||
|
DPRINT1("Status: %x\n", Status);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||
|
|
||
|
Status = MiSimpleRead
|
||
|
(FileObject,
|
||
|
FileOffset,
|
||
|
PageBuf,
|
||
|
RequiredResources->Amount,
|
||
|
&IOSB);
|
||
|
RtlZeroMemory
|
||
|
((PCHAR)PageBuf+RequiredResources->Amount,
|
||
|
PAGE_SIZE-RequiredResources->Amount);
|
||
|
|
||
|
DPRINT("Read Status %x (Page %x)\n", Status, *Page);
|
||
|
|
||
|
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||
|
MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL);
|
||
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
MmReleasePageMemoryConsumer(MC_CACHE, *Page);
|
||
|
DPRINT("Status: %x\n", Status);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
ULONG
|
||
|
NTAPI
|
||
|
MiChecksumPage(PFN_NUMBER Page, BOOLEAN Lock)
|
||
|
{
|
||
|
int i;
|
||
|
NTSTATUS Status;
|
||
|
ULONG Total = 0;
|
||
|
PULONG PageBuf = NULL;
|
||
|
PMEMORY_AREA TmpArea;
|
||
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||
|
|
||
|
BoundaryAddressMultiple.QuadPart = 0;
|
||
|
|
||
|
if (Lock) MmLockAddressSpace(MmGetKernelAddressSpace());
|
||
|
|
||
|
Status = MmCreateMemoryArea
|
||
|
(MmGetKernelAddressSpace(),
|
||
|
MEMORY_AREA_VIRTUAL_MEMORY,
|
||
|
(PVOID*)&PageBuf,
|
||
|
PAGE_SIZE,
|
||
|
PAGE_READWRITE,
|
||
|
&TmpArea,
|
||
|
FALSE,
|
||
|
MEM_TOP_DOWN,
|
||
|
BoundaryAddressMultiple);
|
||
|
|
||
|
DPRINT("Status %x, PageBuf %x\n", Status, PageBuf);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
DPRINT1("STATUS_NO_MEMORY: %x\n", Status);
|
||
|
if (Lock) MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
Status = MmCreateVirtualMapping(NULL, PageBuf, PAGE_READWRITE, &Page, 1);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL);
|
||
|
if (Lock) MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||
|
DPRINT1("Status: %x\n", Status);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < 1024; i++) {
|
||
|
Total += PageBuf[i];
|
||
|
}
|
||
|
|
||
|
MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL);
|
||
|
if (Lock) MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||
|
|
||
|
return Total;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
NTAPI
|
||
|
MiSwapInPage
|
||
|
(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;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
NTAPI
|
||
|
MiWriteFilePage
|
||
|
(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]);
|
||
|
}
|