2001-03-29 17:24:43 +00:00
|
|
|
/*
|
|
|
|
* ReactOS kernel
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
|
|
|
|
*
|
|
|
|
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
2001-09-25 19:52:28 +00:00
|
|
|
/* $Id: section.c,v 1.62 2001/09/25 19:52:28 dwelch Exp $
|
1999-08-29 06:59:11 +00:00
|
|
|
*
|
1998-08-25 04:27:26 +00:00
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* FILE: ntoskrnl/mm/section.c
|
|
|
|
* PURPOSE: Implements section objects
|
|
|
|
* PROGRAMMER: David Welch (welch@mcmail.com)
|
|
|
|
* UPDATE HISTORY:
|
|
|
|
* Created 22/05/98
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2000-06-29 23:35:53 +00:00
|
|
|
#include <limits.h>
|
1998-08-25 04:27:26 +00:00
|
|
|
#include <ddk/ntddk.h>
|
1998-09-05 17:34:23 +00:00
|
|
|
#include <internal/mm.h>
|
1998-10-05 04:01:30 +00:00
|
|
|
#include <internal/ob.h>
|
|
|
|
#include <internal/io.h>
|
|
|
|
#include <internal/ps.h>
|
2001-03-07 16:48:45 +00:00
|
|
|
#include <internal/pool.h>
|
2001-04-03 17:25:50 +00:00
|
|
|
#include <internal/cc.h>
|
2001-02-10 22:51:11 +00:00
|
|
|
#include <ddk/ntifs.h>
|
1998-08-25 04:27:26 +00:00
|
|
|
|
1998-10-05 04:01:30 +00:00
|
|
|
#define NDEBUG
|
1998-08-25 04:27:26 +00:00
|
|
|
#include <internal/debug.h>
|
|
|
|
|
1998-10-05 04:01:30 +00:00
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
|
2000-04-02 13:32:43 +00:00
|
|
|
POBJECT_TYPE EXPORTED MmSectionObjectType = NULL;
|
1998-10-05 04:01:30 +00:00
|
|
|
|
2001-01-28 15:17:52 +00:00
|
|
|
static GENERIC_MAPPING MmpSectionMapping = {
|
|
|
|
STANDARD_RIGHTS_READ | SECTION_MAP_READ | SECTION_QUERY,
|
|
|
|
STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE,
|
|
|
|
STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE,
|
|
|
|
SECTION_ALL_ACCESS};
|
|
|
|
|
2001-03-07 16:48:45 +00:00
|
|
|
#define TAG_MM_SECTION_SEGMENT TAG('M', 'M', 'S', 'S')
|
|
|
|
#define TAG_SECTION_PAGE_TABLE TAG('M', 'S', 'P', 'T')
|
|
|
|
|
2001-03-29 17:24:43 +00:00
|
|
|
#define SHARE_COUNT(E) ((E) & 0xFFF)
|
|
|
|
#define MAX_SHARE_COUNT 0xFFF
|
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2001-03-09 14:40:28 +00:00
|
|
|
VOID
|
|
|
|
MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment)
|
|
|
|
{
|
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
for (i = 0; i < NR_SECTION_PAGE_TABLES; i++)
|
|
|
|
{
|
|
|
|
if (Segment->PageDirectory.PageTables[i] != NULL)
|
|
|
|
{
|
|
|
|
ExFreePool(Segment->PageDirectory.PageTables[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
MmFreeSectionSegments(PFILE_OBJECT FileObject)
|
|
|
|
{
|
|
|
|
if (FileObject->SectionObjectPointers->ImageSectionObject != NULL)
|
|
|
|
{
|
|
|
|
PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
|
2001-03-29 17:24:43 +00:00
|
|
|
|
2001-03-09 14:40:28 +00:00
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
ImageSectionObject =
|
|
|
|
(PMM_IMAGE_SECTION_OBJECT)FileObject->SectionObjectPointers->
|
|
|
|
ImageSectionObject;
|
|
|
|
|
|
|
|
for (i = 0; i < ImageSectionObject->NrSegments; i++)
|
|
|
|
{
|
|
|
|
if (ImageSectionObject->Segments[i].ReferenceCount != 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Image segment %d still referenced (was %d)\n", i,
|
|
|
|
ImageSectionObject->Segments[i].ReferenceCount);
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
MmFreePageTablesSectionSegment(&ImageSectionObject->Segments[i]);
|
|
|
|
}
|
|
|
|
ExFreePool(ImageSectionObject);
|
|
|
|
FileObject->SectionObjectPointers->ImageSectionObject = NULL;
|
|
|
|
}
|
|
|
|
if (FileObject->SectionObjectPointers->DataSectionObject != NULL)
|
|
|
|
{
|
|
|
|
PMM_SECTION_SEGMENT Segment;
|
|
|
|
|
|
|
|
Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers->
|
|
|
|
DataSectionObject;
|
|
|
|
|
|
|
|
if (Segment->ReferenceCount != 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Data segment still referenced\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
MmFreePageTablesSectionSegment(Segment);
|
|
|
|
ExFreePool(Segment);
|
|
|
|
FileObject->SectionObjectPointers->DataSectionObject = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-01-08 02:14:06 +00:00
|
|
|
NTSTATUS
|
|
|
|
MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
|
|
|
|
PMEMORY_AREA MArea,
|
|
|
|
PVOID Address)
|
2000-07-07 10:30:57 +00:00
|
|
|
{
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
VOID
|
|
|
|
MmLockSection(PSECTION_OBJECT Section)
|
2000-05-13 13:51:08 +00:00
|
|
|
{
|
2001-02-10 22:51:11 +00:00
|
|
|
KeWaitForSingleObject(&Section->Lock,
|
|
|
|
UserRequest,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
2000-05-13 13:51:08 +00:00
|
|
|
}
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
VOID
|
|
|
|
MmUnlockSection(PSECTION_OBJECT Section)
|
2000-05-13 13:51:08 +00:00
|
|
|
{
|
|
|
|
KeReleaseMutex(&Section->Lock, FALSE);
|
|
|
|
}
|
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
VOID
|
|
|
|
MmLockSectionSegment(PMM_SECTION_SEGMENT Segment)
|
|
|
|
{
|
|
|
|
KeWaitForSingleObject(&Segment->Lock,
|
|
|
|
UserRequest,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment)
|
|
|
|
{
|
|
|
|
KeReleaseMutex(&Segment->Lock, FALSE);
|
|
|
|
}
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
VOID
|
2001-02-10 22:51:11 +00:00
|
|
|
MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
|
|
|
ULONG Offset,
|
|
|
|
ULONG Entry)
|
2000-04-03 21:54:42 +00:00
|
|
|
{
|
|
|
|
PSECTION_PAGE_TABLE Table;
|
|
|
|
ULONG DirectoryOffset;
|
|
|
|
ULONG TableOffset;
|
|
|
|
|
|
|
|
DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
|
2001-02-10 22:51:11 +00:00
|
|
|
Table = Segment->PageDirectory.PageTables[DirectoryOffset];
|
2000-04-03 21:54:42 +00:00
|
|
|
if (Table == NULL)
|
|
|
|
{
|
|
|
|
Table =
|
2001-02-10 22:51:11 +00:00
|
|
|
Segment->PageDirectory.PageTables[DirectoryOffset] =
|
2001-03-07 16:48:45 +00:00
|
|
|
ExAllocatePoolWithTag(NonPagedPool, sizeof(SECTION_PAGE_TABLE),
|
|
|
|
TAG_SECTION_PAGE_TABLE);
|
2000-05-24 22:29:38 +00:00
|
|
|
memset(Table, 0, sizeof(SECTION_PAGE_TABLE));
|
|
|
|
DPRINT("Table %x\n", Table);
|
2000-04-03 21:54:42 +00:00
|
|
|
}
|
|
|
|
TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
|
|
|
|
Table->Pages[TableOffset] = Entry;
|
|
|
|
}
|
|
|
|
|
2001-03-29 17:24:43 +00:00
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
ULONG
|
2001-02-10 22:51:11 +00:00
|
|
|
MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
|
|
|
ULONG Offset)
|
2000-04-03 21:54:42 +00:00
|
|
|
{
|
|
|
|
PSECTION_PAGE_TABLE Table;
|
2000-06-25 03:59:17 +00:00
|
|
|
ULONG Entry;
|
2000-04-03 21:54:42 +00:00
|
|
|
ULONG DirectoryOffset;
|
|
|
|
ULONG TableOffset;
|
|
|
|
|
2000-05-24 22:29:38 +00:00
|
|
|
DPRINT("MmGetPageEntrySection(Offset %x)\n", Offset);
|
|
|
|
|
2000-04-03 21:54:42 +00:00
|
|
|
DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
|
2001-02-10 22:51:11 +00:00
|
|
|
Table = Segment->PageDirectory.PageTables[DirectoryOffset];
|
2000-05-24 22:29:38 +00:00
|
|
|
DPRINT("Table %x\n", Table);
|
2000-04-03 21:54:42 +00:00
|
|
|
if (Table == NULL)
|
|
|
|
{
|
2000-06-25 03:59:17 +00:00
|
|
|
return(0);
|
2000-04-03 21:54:42 +00:00
|
|
|
}
|
|
|
|
TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
|
|
|
|
Entry = Table->Pages[TableOffset];
|
|
|
|
return(Entry);
|
|
|
|
}
|
|
|
|
|
2001-03-29 17:24:43 +00:00
|
|
|
VOID
|
|
|
|
MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
|
|
|
ULONG Offset)
|
|
|
|
{
|
|
|
|
ULONG Entry;
|
|
|
|
|
|
|
|
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
|
|
|
|
if (Entry == 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
if (SHARE_COUNT(Entry) == MAX_SHARE_COUNT)
|
|
|
|
{
|
|
|
|
DPRINT1("Maximum share count reached\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
Entry++;
|
|
|
|
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
MmUnsharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
|
|
|
ULONG Offset)
|
|
|
|
{
|
|
|
|
ULONG Entry;
|
|
|
|
|
|
|
|
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
|
|
|
|
if (Entry == 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
if (SHARE_COUNT(Entry) == 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Zero share count for unshare\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
Entry--;
|
|
|
|
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
|
|
|
|
}
|
|
|
|
|
2001-04-03 17:25:50 +00:00
|
|
|
NTSTATUS
|
|
|
|
MiReadPage(PMEMORY_AREA MemoryArea,
|
|
|
|
PLARGE_INTEGER Offset,
|
|
|
|
PVOID* Page)
|
2001-09-25 19:41:38 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Read a page for a section backed memory area.
|
|
|
|
* PARAMETERS:
|
|
|
|
* MemoryArea - Memory area to read the page for.
|
|
|
|
* Offset - Offset of the page to read.
|
|
|
|
* Page - Variable that receives a page contains the read data.
|
|
|
|
*/
|
2001-04-03 17:25:50 +00:00
|
|
|
{
|
|
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
PFILE_OBJECT FileObject;
|
|
|
|
PMDL Mdl;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PREACTOS_COMMON_FCB_HEADER Fcb;
|
|
|
|
|
|
|
|
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
|
|
|
|
Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
|
2001-08-03 09:36:19 +00:00
|
|
|
|
2001-09-25 19:41:38 +00:00
|
|
|
/*
|
|
|
|
* If the file system is letting us go directly to the cache and the
|
|
|
|
* memory area was mapped at an offset in the file which is page aligned
|
|
|
|
* then get the related cache segment.
|
|
|
|
*/
|
2001-04-03 17:25:50 +00:00
|
|
|
if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
|
|
|
|
(Offset->QuadPart % PAGESIZE) == 0)
|
|
|
|
{
|
|
|
|
ULONG BaseOffset;
|
|
|
|
PVOID BaseAddress;
|
|
|
|
BOOLEAN UptoDate;
|
|
|
|
PCACHE_SEGMENT CacheSeg;
|
|
|
|
LARGE_INTEGER SegOffset;
|
|
|
|
PHYSICAL_ADDRESS Addr;
|
2001-09-25 19:41:38 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the related cache segment; we use a lower level interface than
|
|
|
|
* filesystems do because it is safe for us to use an offset with a
|
|
|
|
* alignment less than the file system block size.
|
|
|
|
*/
|
2001-05-04 01:21:45 +00:00
|
|
|
Status = CcRosGetCacheSegment(Fcb->Bcb,
|
2001-09-25 19:41:38 +00:00
|
|
|
(ULONG)Offset->QuadPart,
|
|
|
|
&BaseOffset,
|
|
|
|
&BaseAddress,
|
|
|
|
&UptoDate,
|
|
|
|
&CacheSeg);
|
2001-04-03 17:25:50 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
if (!UptoDate)
|
|
|
|
{
|
2001-09-25 19:41:38 +00:00
|
|
|
/*
|
|
|
|
* If the cache segment isn't up to date then call the file
|
|
|
|
* system to read in the data.
|
|
|
|
*/
|
|
|
|
|
2001-04-03 17:25:50 +00:00
|
|
|
Mdl = MmCreateMdl(NULL, BaseAddress, Fcb->Bcb->CacheSegmentSize);
|
|
|
|
MmBuildMdlForNonPagedPool(Mdl);
|
|
|
|
SegOffset.QuadPart = BaseOffset;
|
|
|
|
Status = IoPageRead(FileObject,
|
|
|
|
Mdl,
|
|
|
|
&SegOffset,
|
|
|
|
&IoStatus,
|
|
|
|
TRUE);
|
2001-09-25 19:52:28 +00:00
|
|
|
if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
|
2001-04-03 17:25:50 +00:00
|
|
|
{
|
2001-05-04 01:21:45 +00:00
|
|
|
CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, FALSE);
|
2001-04-03 17:25:50 +00:00
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
}
|
2001-09-25 19:41:38 +00:00
|
|
|
/*
|
|
|
|
* Retrieve the page from the cache segment that we actually want.
|
|
|
|
*/
|
2001-04-03 17:25:50 +00:00
|
|
|
Addr = MmGetPhysicalAddress(BaseAddress +
|
|
|
|
Offset->QuadPart - BaseOffset);
|
|
|
|
(*Page) = (PVOID)(ULONG)Addr.QuadPart;
|
|
|
|
MmReferencePage((*Page));
|
|
|
|
|
2001-05-04 01:21:45 +00:00
|
|
|
CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE);
|
2001-04-03 17:25:50 +00:00
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Allocate a page, this is rather complicated by the possibility
|
|
|
|
* we might have to move other things out of memory
|
|
|
|
*/
|
|
|
|
(*Page) = MmAllocPage(0);
|
|
|
|
while ((*Page) == NULL)
|
|
|
|
{
|
|
|
|
MmWaitForFreePages();
|
|
|
|
(*Page) = MmAllocPage(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create an mdl to hold the page we are going to read data into.
|
|
|
|
*/
|
|
|
|
Mdl = MmCreateMdl(NULL, NULL, PAGESIZE);
|
|
|
|
MmBuildMdlFromPages(Mdl, (PULONG)Page);
|
|
|
|
/*
|
|
|
|
* Call the FSD to read the page
|
|
|
|
*/
|
|
|
|
Status = IoPageRead(FileObject,
|
|
|
|
Mdl,
|
|
|
|
Offset,
|
|
|
|
&IoStatus,
|
|
|
|
FALSE);
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
}
|
2001-03-29 17:24:43 +00:00
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
NTSTATUS
|
|
|
|
MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
|
|
|
MEMORY_AREA* MemoryArea,
|
2001-02-14 02:53:54 +00:00
|
|
|
PVOID Address,
|
|
|
|
BOOLEAN Locked)
|
2000-06-25 03:59:17 +00:00
|
|
|
{
|
|
|
|
LARGE_INTEGER Offset;
|
|
|
|
PVOID Page;
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG PAddress;
|
|
|
|
PSECTION_OBJECT Section;
|
2001-02-10 22:51:11 +00:00
|
|
|
PMM_SECTION_SEGMENT Segment;
|
2000-06-25 03:59:17 +00:00
|
|
|
ULONG Entry;
|
|
|
|
ULONG Entry1;
|
2001-02-10 22:51:11 +00:00
|
|
|
ULONG Attributes;
|
2001-03-13 16:25:55 +00:00
|
|
|
PMM_PAGEOP PageOp;
|
2000-06-26 19:41:43 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* There is a window between taking the page fault and locking the
|
|
|
|
* address space when another thread could load the page so we check
|
|
|
|
* that.
|
|
|
|
*/
|
2000-06-25 03:59:17 +00:00
|
|
|
if (MmIsPagePresent(NULL, Address))
|
|
|
|
{
|
2001-02-14 02:53:54 +00:00
|
|
|
if (Locked)
|
|
|
|
{
|
|
|
|
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
|
|
|
}
|
2000-06-26 19:41:43 +00:00
|
|
|
return(STATUS_SUCCESS);
|
2000-06-25 03:59:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
|
|
|
|
Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
|
|
|
|
MemoryArea->Data.SectionData.ViewOffset;
|
|
|
|
|
2000-06-26 19:41:43 +00:00
|
|
|
/*
|
2001-02-10 22:51:11 +00:00
|
|
|
* Lock the segment
|
2000-06-26 19:41:43 +00:00
|
|
|
*/
|
2001-02-10 22:51:11 +00:00
|
|
|
Segment = MemoryArea->Data.SectionData.Segment;
|
2000-06-25 03:59:17 +00:00
|
|
|
Section = MemoryArea->Data.SectionData.Section;
|
|
|
|
MmLockSection(Section);
|
2001-02-10 22:51:11 +00:00
|
|
|
MmLockSectionSegment(Segment);
|
2000-06-25 03:59:17 +00:00
|
|
|
|
2001-03-13 16:25:55 +00:00
|
|
|
/*
|
|
|
|
* Get or create a page operation descriptor
|
|
|
|
*/
|
2001-04-04 22:21:32 +00:00
|
|
|
PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart,
|
|
|
|
MM_PAGEOP_PAGEIN);
|
2001-03-13 16:25:55 +00:00
|
|
|
if (PageOp == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("MmGetPageOp failed\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if someone else is already handling this fault, if so wait
|
|
|
|
* for them
|
|
|
|
*/
|
|
|
|
if (PageOp->Thread != PsGetCurrentThread())
|
|
|
|
{
|
|
|
|
MmUnlockSectionSegment(Segment);
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
|
|
|
|
0,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
/*
|
|
|
|
* Check for various strange conditions
|
|
|
|
*/
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to wait for page op\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
if (PageOp->Status == STATUS_PENDING)
|
|
|
|
{
|
|
|
|
DPRINT1("Woke for page op before completion\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
2001-04-04 22:21:32 +00:00
|
|
|
/*
|
|
|
|
* If this wasn't a pagein then restart the operation
|
|
|
|
*/
|
|
|
|
if (PageOp->OpType != MM_PAGEOP_PAGEIN)
|
|
|
|
{
|
|
|
|
MmLockAddressSpace(AddressSpace);
|
|
|
|
MmReleasePageOp(PageOp);
|
|
|
|
return(STATUS_MM_RESTART_OPERATION);
|
|
|
|
}
|
2001-03-13 16:25:55 +00:00
|
|
|
/*
|
|
|
|
* If the thread handling this fault has failed then we don't retry
|
|
|
|
*/
|
|
|
|
if (!NT_SUCCESS(PageOp->Status))
|
|
|
|
{
|
2001-04-04 22:21:32 +00:00
|
|
|
MmLockAddressSpace(AddressSpace);
|
2001-03-29 17:24:43 +00:00
|
|
|
return(PageOp->Status);
|
2001-03-13 16:25:55 +00:00
|
|
|
}
|
|
|
|
MmLockAddressSpace(AddressSpace);
|
|
|
|
MmLockSection(Section);
|
|
|
|
MmLockSectionSegment(Segment);
|
|
|
|
/*
|
|
|
|
* If the completed fault was for another address space then set the
|
|
|
|
* page in this one.
|
|
|
|
*/
|
|
|
|
if (!MmIsPagePresent(NULL, Address))
|
|
|
|
{
|
|
|
|
Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
|
|
|
|
|
|
|
|
Page = (PVOID)(Entry & 0xFFFFF000);
|
|
|
|
MmReferencePage(Page);
|
2001-03-29 17:24:43 +00:00
|
|
|
// MmSharePageEntrySectionSegment(Segment, Offset.u.LowPart);
|
2001-03-13 16:25:55 +00:00
|
|
|
|
|
|
|
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
|
|
|
Address,
|
|
|
|
Attributes,
|
|
|
|
(ULONG)Page);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DbgPrint("Unable to create virtual mapping\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Locked)
|
|
|
|
{
|
|
|
|
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
|
|
|
}
|
|
|
|
MmUnlockSectionSegment(Segment);
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
MmReleasePageOp(PageOp);
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
/*
|
|
|
|
* Satisfying a page fault on a map of /Device/PhysicalMemory is easy
|
|
|
|
*/
|
2000-12-28 03:38:08 +00:00
|
|
|
if (Section->Flags & SO_PHYSICAL_MEMORY)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Just map the desired physical page
|
|
|
|
*/
|
2001-02-18 17:43:32 +00:00
|
|
|
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
2000-12-28 03:38:08 +00:00
|
|
|
Address,
|
|
|
|
MemoryArea->Attributes,
|
|
|
|
Offset.QuadPart);
|
2001-02-14 02:53:54 +00:00
|
|
|
if (Locked)
|
|
|
|
{
|
|
|
|
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
|
|
|
}
|
2001-03-13 16:25:55 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Cleanup and release locks
|
|
|
|
*/
|
|
|
|
PageOp->Status = STATUS_SUCCESS;
|
|
|
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
|
|
|
MmReleasePageOp(PageOp);
|
2001-02-10 22:51:11 +00:00
|
|
|
MmUnlockSectionSegment(Segment);
|
2000-12-28 03:38:08 +00:00
|
|
|
MmUnlockSection(Section);
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
/*
|
|
|
|
* Map anonymous memory for BSS sections
|
|
|
|
*/
|
|
|
|
if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS)
|
|
|
|
{
|
|
|
|
Page = MmAllocPage(0);
|
|
|
|
while (Page == NULL)
|
|
|
|
{
|
|
|
|
MmUnlockSectionSegment(Segment);
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
MmWaitForFreePages();
|
|
|
|
MmLockAddressSpace(AddressSpace);
|
|
|
|
MmLockSection(Section);
|
|
|
|
MmLockSectionSegment(Segment);
|
|
|
|
Page = MmAllocPage(0);
|
|
|
|
}
|
2001-02-18 17:43:32 +00:00
|
|
|
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
2001-02-10 22:51:11 +00:00
|
|
|
Address,
|
|
|
|
MemoryArea->Attributes,
|
|
|
|
(ULONG)Page);
|
2001-02-14 02:53:54 +00:00
|
|
|
if (Locked)
|
|
|
|
{
|
|
|
|
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
|
|
|
}
|
2001-03-13 16:25:55 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Cleanup and release locks
|
|
|
|
*/
|
|
|
|
PageOp->Status = STATUS_SUCCESS;
|
|
|
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
|
|
|
MmReleasePageOp(PageOp);
|
2001-02-10 22:51:11 +00:00
|
|
|
MmUnlockSectionSegment(Segment);
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
2001-03-13 16:25:55 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if this page needs to be mapped COW
|
|
|
|
*/
|
2001-02-10 22:51:11 +00:00
|
|
|
if (Segment->Characteristics & IMAGE_SECTION_CHAR_DATA)
|
|
|
|
{
|
|
|
|
Attributes = PAGE_READONLY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Attributes = MemoryArea->Attributes;
|
|
|
|
}
|
|
|
|
|
2000-06-26 19:41:43 +00:00
|
|
|
/*
|
|
|
|
* Get the entry corresponding to the offset within the section
|
|
|
|
*/
|
2001-02-10 22:51:11 +00:00
|
|
|
Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
|
2000-06-25 03:59:17 +00:00
|
|
|
|
|
|
|
if (Entry == 0)
|
|
|
|
{
|
2000-06-26 19:41:43 +00:00
|
|
|
/*
|
|
|
|
* If the entry is zero (and it can't change because we have
|
2001-02-10 22:51:11 +00:00
|
|
|
* locked the segment) then we need to load the page.
|
2000-06-26 19:41:43 +00:00
|
|
|
*/
|
2001-04-03 17:25:50 +00:00
|
|
|
|
2000-06-26 19:41:43 +00:00
|
|
|
/*
|
|
|
|
* Release all our locks and read in the page from disk
|
|
|
|
*/
|
2001-02-10 22:51:11 +00:00
|
|
|
MmUnlockSectionSegment(Segment);
|
2000-06-25 03:59:17 +00:00
|
|
|
MmUnlockSection(Section);
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2001-04-03 17:25:50 +00:00
|
|
|
|
|
|
|
Status = MiReadPage(MemoryArea, &Offset, &Page);
|
2000-07-07 10:30:57 +00:00
|
|
|
if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
|
2000-06-25 03:59:17 +00:00
|
|
|
{
|
2000-06-26 19:41:43 +00:00
|
|
|
/*
|
|
|
|
* FIXME: What do we know in this case?
|
|
|
|
*/
|
2001-03-29 17:24:43 +00:00
|
|
|
DPRINT1("IoPageRead failed (Status %x)\n", Status);
|
2001-03-13 16:25:55 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Cleanup and release locks
|
|
|
|
*/
|
|
|
|
PageOp->Status = Status;
|
|
|
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
|
|
|
MmReleasePageOp(PageOp);
|
2001-01-08 02:14:06 +00:00
|
|
|
MmLockAddressSpace(AddressSpace);
|
|
|
|
return(Status);
|
2000-06-25 03:59:17 +00:00
|
|
|
}
|
|
|
|
|
2000-06-26 19:41:43 +00:00
|
|
|
/*
|
2001-02-10 22:51:11 +00:00
|
|
|
* Relock the address space, section and segment
|
2000-06-26 19:41:43 +00:00
|
|
|
*/
|
2000-06-25 03:59:17 +00:00
|
|
|
MmLockAddressSpace(AddressSpace);
|
|
|
|
MmLockSection(Section);
|
2001-02-10 22:51:11 +00:00
|
|
|
MmLockSectionSegment(Segment);
|
2000-06-25 03:59:17 +00:00
|
|
|
|
2000-06-26 19:41:43 +00:00
|
|
|
/*
|
|
|
|
* Check the entry. No one should change the status of a page
|
|
|
|
* that has a pending page-in.
|
|
|
|
*/
|
2001-02-10 22:51:11 +00:00
|
|
|
Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
|
2000-06-25 03:59:17 +00:00
|
|
|
if (Entry != Entry1)
|
|
|
|
{
|
|
|
|
DbgPrint("Someone changed ppte entry while we slept\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
|
2000-06-26 19:41:43 +00:00
|
|
|
/*
|
|
|
|
* Mark the offset within the section as having valid, in-memory
|
|
|
|
* data
|
|
|
|
*/
|
2000-06-25 03:59:17 +00:00
|
|
|
Entry = (ULONG)Page;
|
2001-02-10 22:51:11 +00:00
|
|
|
MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
|
2001-03-29 17:24:43 +00:00
|
|
|
// MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
|
2000-06-26 19:41:43 +00:00
|
|
|
|
2001-02-18 17:43:32 +00:00
|
|
|
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
2000-08-20 17:02:10 +00:00
|
|
|
Address,
|
2001-02-10 22:51:11 +00:00
|
|
|
Attributes,
|
2000-08-20 17:02:10 +00:00
|
|
|
(ULONG)Page);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DbgPrint("Unable to create virtual mapping\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
2001-02-14 02:53:54 +00:00
|
|
|
if (Locked)
|
|
|
|
{
|
|
|
|
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
|
|
|
}
|
2001-03-13 16:25:55 +00:00
|
|
|
PageOp->Status = STATUS_SUCCESS;
|
|
|
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
|
|
|
MmReleasePageOp(PageOp);
|
|
|
|
MmUnlockSectionSegment(Segment);
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
DPRINT("MmNotPresentFaultSectionView succeeded\n");
|
|
|
|
return(STATUS_SUCCESS);
|
2000-06-25 03:59:17 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-06-26 19:41:43 +00:00
|
|
|
/*
|
|
|
|
* If the section offset is already in-memory and valid then just
|
|
|
|
* take another reference to the page
|
|
|
|
*/
|
|
|
|
|
2000-06-25 03:59:17 +00:00
|
|
|
Page = (PVOID)Entry;
|
2000-05-13 13:51:08 +00:00
|
|
|
MmReferencePage(Page);
|
2001-03-29 17:24:43 +00:00
|
|
|
// MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
|
2000-07-06 14:34:52 +00:00
|
|
|
|
2001-02-18 17:43:32 +00:00
|
|
|
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
2000-08-20 17:02:10 +00:00
|
|
|
Address,
|
2001-02-10 22:51:11 +00:00
|
|
|
Attributes,
|
2000-08-20 17:02:10 +00:00
|
|
|
(ULONG)Page);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DbgPrint("Unable to create virtual mapping\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
2001-02-14 02:53:54 +00:00
|
|
|
if (Locked)
|
|
|
|
{
|
|
|
|
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
|
|
|
}
|
2001-03-13 16:25:55 +00:00
|
|
|
PageOp->Status = STATUS_SUCCESS;
|
|
|
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
|
|
|
MmReleasePageOp(PageOp);
|
|
|
|
MmUnlockSectionSegment(Segment);
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
return(STATUS_SUCCESS);
|
1999-11-24 11:51:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
NTSTATUS
|
|
|
|
MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
2001-02-14 02:53:54 +00:00
|
|
|
MEMORY_AREA* MemoryArea,
|
|
|
|
PVOID Address,
|
|
|
|
BOOLEAN Locked)
|
2001-02-10 22:51:11 +00:00
|
|
|
{
|
|
|
|
PMM_SECTION_SEGMENT Segment;
|
|
|
|
PSECTION_OBJECT Section;
|
|
|
|
ULONG OldPage;
|
|
|
|
PVOID NewPage;
|
|
|
|
PVOID NewAddress;
|
|
|
|
NTSTATUS Status;
|
2001-04-04 22:21:32 +00:00
|
|
|
ULONG PAddress;
|
|
|
|
LARGE_INTEGER Offset;
|
|
|
|
PMM_PAGEOP PageOp;
|
2001-02-10 22:51:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if the page has been paged out or has already been set readwrite
|
|
|
|
*/
|
|
|
|
if (!MmIsPagePresent(NULL, Address) ||
|
|
|
|
MmGetPageProtect(NULL, Address) & PAGE_READWRITE)
|
|
|
|
{
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2001-04-04 22:21:32 +00:00
|
|
|
/*
|
|
|
|
* Find the offset of the page
|
|
|
|
*/
|
|
|
|
PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
|
|
|
|
Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
|
|
|
|
MemoryArea->Data.SectionData.ViewOffset;
|
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
/*
|
|
|
|
* Lock the segment
|
|
|
|
*/
|
|
|
|
Segment = MemoryArea->Data.SectionData.Segment;
|
|
|
|
Section = MemoryArea->Data.SectionData.Section;
|
|
|
|
MmLockSection(Section);
|
|
|
|
MmLockSectionSegment(Segment);
|
|
|
|
|
2001-04-04 22:21:32 +00:00
|
|
|
/*
|
|
|
|
* Check if we are doing COW
|
|
|
|
*/
|
2001-02-10 22:51:11 +00:00
|
|
|
if (!(Segment->Characteristics & IMAGE_SECTION_CHAR_DATA))
|
|
|
|
{
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
MmUnlockSectionSegment(Segment);
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2001-04-04 22:21:32 +00:00
|
|
|
* Get or create a pageop
|
2001-02-10 22:51:11 +00:00
|
|
|
*/
|
2001-04-04 22:21:32 +00:00
|
|
|
PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart,
|
|
|
|
MM_PAGEOP_ACCESSFAULT);
|
|
|
|
if (PageOp == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("MmGetPageOp failed\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Wait for any other operations to complete
|
|
|
|
*/
|
|
|
|
if (PageOp->Thread != PsGetCurrentThread())
|
2001-02-10 22:51:11 +00:00
|
|
|
{
|
|
|
|
MmUnlockSectionSegment(Segment);
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2001-04-04 22:21:32 +00:00
|
|
|
Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
|
|
|
|
0,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
/*
|
|
|
|
* Check for various strange conditions
|
|
|
|
*/
|
|
|
|
if (Status != STATUS_SUCCESS)
|
2001-02-10 22:51:11 +00:00
|
|
|
{
|
2001-04-04 22:21:32 +00:00
|
|
|
DPRINT1("Failed to wait for page op\n");
|
|
|
|
KeBugCheck(0);
|
2001-02-10 22:51:11 +00:00
|
|
|
}
|
2001-04-04 22:21:32 +00:00
|
|
|
if (PageOp->Status == STATUS_PENDING)
|
|
|
|
{
|
|
|
|
DPRINT1("Woke for page op before completion\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Restart the operation
|
|
|
|
*/
|
|
|
|
MmLockAddressSpace(AddressSpace);
|
|
|
|
MmReleasePageOp(PageOp);
|
|
|
|
return(STATUS_MM_RESTART_OPERATION);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Release locks now we have the pageop
|
|
|
|
*/
|
|
|
|
MmUnlockSectionSegment(Segment);
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate a page
|
|
|
|
*/
|
|
|
|
NewPage = MmAllocPage(0);
|
|
|
|
while (NewPage == NULL)
|
|
|
|
{
|
|
|
|
MmWaitForFreePages();
|
2001-02-10 22:51:11 +00:00
|
|
|
NewPage = MmAllocPage(0);
|
|
|
|
}
|
|
|
|
|
2001-04-04 22:21:32 +00:00
|
|
|
/*
|
|
|
|
* Copy the old page
|
|
|
|
*/
|
2001-02-10 22:51:11 +00:00
|
|
|
OldPage = MmGetPhysicalAddressForProcess(NULL, Address);
|
|
|
|
|
|
|
|
NewAddress = ExAllocatePageWithPhysPage((ULONG)NewPage);
|
|
|
|
memcpy(NewAddress, (PVOID)PAGE_ROUND_DOWN(Address), PAGESIZE);
|
|
|
|
ExUnmapPage(NewAddress);
|
|
|
|
|
2001-04-04 22:21:32 +00:00
|
|
|
/*
|
|
|
|
* Set the PTE to point to the new page
|
|
|
|
*/
|
|
|
|
MmLockAddressSpace(AddressSpace);
|
2001-02-18 17:43:32 +00:00
|
|
|
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
2001-02-10 22:51:11 +00:00
|
|
|
Address,
|
|
|
|
MemoryArea->Attributes,
|
|
|
|
(ULONG)NewPage);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DbgPrint("Unable to create virtual mapping\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
2001-02-14 02:53:54 +00:00
|
|
|
if (Locked)
|
|
|
|
{
|
|
|
|
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
|
|
|
}
|
2001-04-04 22:21:32 +00:00
|
|
|
PageOp->Status = STATUS_SUCCESS;
|
|
|
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
|
|
|
MmReleasePageOp(PageOp);
|
2001-02-10 22:51:11 +00:00
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
ULONG
|
|
|
|
MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
|
|
|
|
MEMORY_AREA* MemoryArea,
|
|
|
|
PVOID Address,
|
|
|
|
PBOOLEAN Ul)
|
2000-06-25 03:59:17 +00:00
|
|
|
{
|
2000-07-06 14:34:52 +00:00
|
|
|
(*Ul) = FALSE;
|
2000-06-25 03:59:17 +00:00
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
2001-08-26 17:30:21 +00:00
|
|
|
VOID STDCALL
|
2000-12-28 03:38:08 +00:00
|
|
|
MmpDeleteSection(PVOID ObjectBody)
|
1999-02-01 20:58:37 +00:00
|
|
|
{
|
2001-03-09 14:40:28 +00:00
|
|
|
PSECTION_OBJECT Section = (PSECTION_OBJECT)ObjectBody;
|
|
|
|
|
|
|
|
DPRINT("MmpDeleteSection(ObjectBody %x)\n", ObjectBody);
|
|
|
|
if (Section->Flags & MM_IMAGE_SECTION)
|
|
|
|
{
|
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
for (i = 0; i < Section->NrSegments; i++)
|
|
|
|
{
|
|
|
|
InterlockedDecrement(&Section->Segments[i].ReferenceCount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
InterlockedDecrement(&Section->Segments->ReferenceCount);
|
|
|
|
}
|
|
|
|
if (Section->FileObject != NULL)
|
|
|
|
{
|
|
|
|
ObDereferenceObject(Section->FileObject);
|
|
|
|
Section->FileObject = NULL;
|
|
|
|
}
|
2000-04-03 21:54:42 +00:00
|
|
|
}
|
|
|
|
|
2001-08-26 17:30:21 +00:00
|
|
|
VOID STDCALL
|
2000-12-28 03:38:08 +00:00
|
|
|
MmpCloseSection(PVOID ObjectBody,
|
|
|
|
ULONG HandleCount)
|
2000-04-03 21:54:42 +00:00
|
|
|
{
|
2000-04-07 02:24:03 +00:00
|
|
|
DPRINT("MmpCloseSection(OB %x, HC %d) RC %d\n",
|
2000-04-03 21:54:42 +00:00
|
|
|
ObjectBody, HandleCount, ObGetReferenceCount(ObjectBody));
|
2001-03-07 16:48:45 +00:00
|
|
|
|
1999-02-01 20:58:37 +00:00
|
|
|
}
|
|
|
|
|
2001-08-26 17:30:21 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
MmpCreateSection(PVOID ObjectBody,
|
|
|
|
PVOID Parent,
|
|
|
|
PWSTR RemainingPath,
|
|
|
|
POBJECT_ATTRIBUTES ObjectAttributes)
|
1999-02-01 20:58:37 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2000-01-12 19:05:32 +00:00
|
|
|
DPRINT("MmpCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
|
1999-02-01 20:58:37 +00:00
|
|
|
ObjectBody, Parent, RemainingPath);
|
|
|
|
|
|
|
|
if (RemainingPath == NULL)
|
|
|
|
{
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
1999-11-25 23:37:02 +00:00
|
|
|
if (wcschr(RemainingPath+1, L'\\') != NULL)
|
1999-02-01 20:58:37 +00:00
|
|
|
{
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = ObReferenceObjectByPointer(Parent,
|
|
|
|
STANDARD_RIGHTS_REQUIRED,
|
|
|
|
ObDirectoryType,
|
|
|
|
UserMode);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
ObAddEntryDirectory(Parent, ObjectBody, RemainingPath+1);
|
1999-04-18 08:56:23 +00:00
|
|
|
ObDereferenceObject(Parent);
|
|
|
|
|
1999-02-01 20:58:37 +00:00
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
NTSTATUS
|
|
|
|
MmCreatePhysicalMemorySection(VOID)
|
1998-10-05 04:01:30 +00:00
|
|
|
{
|
2000-12-28 03:38:08 +00:00
|
|
|
HANDLE PhysSectionH;
|
|
|
|
PSECTION_OBJECT PhysSection;
|
|
|
|
NTSTATUS Status;
|
|
|
|
OBJECT_ATTRIBUTES Obj;
|
|
|
|
UNICODE_STRING Name;
|
|
|
|
LARGE_INTEGER SectionSize;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the section mapping physical memory
|
|
|
|
*/
|
|
|
|
SectionSize.QuadPart = 0xFFFFFFFF;
|
|
|
|
RtlInitUnicodeString(&Name, L"\\Device\\PhysicalMemory");
|
2001-01-28 15:17:52 +00:00
|
|
|
InitializeObjectAttributes(&Obj,
|
2000-12-28 03:38:08 +00:00
|
|
|
&Name,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
Status = NtCreateSection(&PhysSectionH,
|
|
|
|
SECTION_ALL_ACCESS,
|
2001-01-28 15:17:52 +00:00
|
|
|
&Obj,
|
2000-12-28 03:38:08 +00:00
|
|
|
&SectionSize,
|
|
|
|
PAGE_EXECUTE_READWRITE,
|
|
|
|
0,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DbgPrint("Failed to create PhysicalMemory section\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
Status = ObReferenceObjectByHandle(PhysSectionH,
|
|
|
|
SECTION_ALL_ACCESS,
|
|
|
|
NULL,
|
|
|
|
KernelMode,
|
|
|
|
(PVOID*)&PhysSection,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DbgPrint("Failed to reference PhysicalMemory section\n");
|
|
|
|
KeBugCheck(0);
|
|
|
|
}
|
|
|
|
PhysSection->Flags = PhysSection->Flags | SO_PHYSICAL_MEMORY;
|
|
|
|
ObDereferenceObject((PVOID)PhysSection);
|
|
|
|
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
MmInitSectionImplementation(VOID)
|
|
|
|
{
|
2001-01-28 15:17:52 +00:00
|
|
|
MmSectionObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&MmSectionObjectType->TypeName, L"Section");
|
|
|
|
|
2001-03-07 16:48:45 +00:00
|
|
|
MmSectionObjectType->Tag = TAG('S', 'E', 'C', 'T');
|
2001-01-28 15:17:52 +00:00
|
|
|
MmSectionObjectType->TotalObjects = 0;
|
|
|
|
MmSectionObjectType->TotalHandles = 0;
|
|
|
|
MmSectionObjectType->MaxObjects = ULONG_MAX;
|
|
|
|
MmSectionObjectType->MaxHandles = ULONG_MAX;
|
|
|
|
MmSectionObjectType->PagedPoolCharge = 0;
|
|
|
|
MmSectionObjectType->NonpagedPoolCharge = sizeof(SECTION_OBJECT);
|
|
|
|
MmSectionObjectType->Mapping = &MmpSectionMapping;
|
|
|
|
MmSectionObjectType->Dump = NULL;
|
|
|
|
MmSectionObjectType->Open = NULL;
|
|
|
|
MmSectionObjectType->Close = MmpCloseSection;
|
|
|
|
MmSectionObjectType->Delete = MmpDeleteSection;
|
|
|
|
MmSectionObjectType->Parse = NULL;
|
|
|
|
MmSectionObjectType->Security = NULL;
|
|
|
|
MmSectionObjectType->QueryName = NULL;
|
|
|
|
MmSectionObjectType->OkayToClose = NULL;
|
|
|
|
MmSectionObjectType->Create = MmpCreateSection;
|
2000-12-28 03:38:08 +00:00
|
|
|
|
2001-01-28 15:17:52 +00:00
|
|
|
return(STATUS_SUCCESS);
|
1998-10-05 04:01:30 +00:00
|
|
|
}
|
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
NTSTATUS
|
|
|
|
MmCreatePageFileSection(PHANDLE SectionHandle,
|
|
|
|
ACCESS_MASK DesiredAccess,
|
|
|
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
|
|
PLARGE_INTEGER UMaximumSize,
|
|
|
|
ULONG SectionPageProtection,
|
|
|
|
ULONG AllocationAttributes)
|
|
|
|
/*
|
|
|
|
* Create a section which is backed by the pagefile
|
|
|
|
*/
|
1998-09-05 17:34:23 +00:00
|
|
|
{
|
2001-02-10 22:51:11 +00:00
|
|
|
LARGE_INTEGER MaximumSize;
|
|
|
|
PSECTION_OBJECT Section;
|
|
|
|
PMM_SECTION_SEGMENT Segment;
|
2001-06-16 14:11:31 +00:00
|
|
|
NTSTATUS Status;
|
1998-10-05 04:01:30 +00:00
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
if (UMaximumSize == NULL)
|
|
|
|
{
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
|
|
|
MaximumSize = *UMaximumSize;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check the protection
|
|
|
|
*/
|
|
|
|
if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
|
|
|
|
SectionPageProtection)
|
|
|
|
{
|
|
|
|
return(STATUS_INVALID_PAGE_PROTECTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the section
|
|
|
|
*/
|
2001-06-16 14:11:31 +00:00
|
|
|
Status = ObCreateObject(SectionHandle,
|
|
|
|
DesiredAccess,
|
|
|
|
ObjectAttributes,
|
|
|
|
MmSectionObjectType,
|
|
|
|
(PVOID*)&Section);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-02-10 22:51:11 +00:00
|
|
|
{
|
2001-06-16 14:11:31 +00:00
|
|
|
return(Status);
|
2001-02-10 22:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize it
|
|
|
|
*/
|
|
|
|
Section->SectionPageProtection = SectionPageProtection;
|
|
|
|
Section->AllocateAttributes = AllocationAttributes;
|
|
|
|
InitializeListHead(&Section->ViewListHead);
|
|
|
|
KeInitializeSpinLock(&Section->ViewListLock);
|
|
|
|
KeInitializeMutex(&Section->Lock, 0);
|
|
|
|
Section->Flags = 0;
|
|
|
|
Section->FileObject = NULL;
|
|
|
|
Section->MaximumSize = MaximumSize;
|
2001-03-07 16:48:45 +00:00
|
|
|
Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
|
|
|
|
TAG_MM_SECTION_SEGMENT);
|
2001-02-10 22:51:11 +00:00
|
|
|
if (Segment == NULL)
|
|
|
|
{
|
|
|
|
ZwClose(*SectionHandle);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
return(STATUS_NO_MEMORY);
|
|
|
|
}
|
|
|
|
Section->Segments = Segment;
|
|
|
|
Segment->ReferenceCount = 1;
|
|
|
|
KeInitializeMutex(&Segment->Lock, 0);
|
|
|
|
Segment->FileOffset = 0;
|
|
|
|
Segment->Protection = SectionPageProtection;
|
|
|
|
Segment->Attributes = AllocationAttributes;
|
|
|
|
Segment->Length = MaximumSize.u.LowPart;
|
2001-06-16 14:11:31 +00:00
|
|
|
Segment->Flags = MM_PAGEFILE_SECTION;
|
2001-02-10 22:51:11 +00:00
|
|
|
return(STATUS_SUCCESS);
|
2001-06-16 14:11:31 +00:00
|
|
|
}
|
|
|
|
|
1998-09-05 17:34:23 +00:00
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
NTSTATUS
|
|
|
|
MmCreateDataFileSection(PHANDLE SectionHandle,
|
|
|
|
ACCESS_MASK DesiredAccess,
|
|
|
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
|
|
PLARGE_INTEGER UMaximumSize,
|
|
|
|
ULONG SectionPageProtection,
|
|
|
|
ULONG AllocationAttributes,
|
|
|
|
HANDLE FileHandle)
|
|
|
|
/*
|
|
|
|
* Create a section backed by a data file
|
|
|
|
*/
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2001-02-10 22:51:11 +00:00
|
|
|
PSECTION_OBJECT Section;
|
|
|
|
NTSTATUS Status;
|
|
|
|
LARGE_INTEGER MaximumSize;
|
|
|
|
PFILE_OBJECT FileObject;
|
|
|
|
PMM_SECTION_SEGMENT Segment;
|
|
|
|
ULONG FileAccess;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check the protection
|
|
|
|
*/
|
|
|
|
if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
|
|
|
|
SectionPageProtection)
|
|
|
|
{
|
|
|
|
return(STATUS_INVALID_PAGE_PROTECTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the section
|
|
|
|
*/
|
2001-06-16 14:11:31 +00:00
|
|
|
Status = ObCreateObject(SectionHandle,
|
|
|
|
DesiredAccess,
|
|
|
|
ObjectAttributes,
|
|
|
|
MmSectionObjectType,
|
|
|
|
(PVOID*)&Section);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-02-10 22:51:11 +00:00
|
|
|
{
|
2001-06-16 14:11:31 +00:00
|
|
|
return(Status);
|
2001-02-10 22:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize it
|
|
|
|
*/
|
|
|
|
Section->SectionPageProtection = SectionPageProtection;
|
|
|
|
Section->AllocateAttributes = AllocationAttributes;
|
|
|
|
InitializeListHead(&Section->ViewListHead);
|
|
|
|
KeInitializeSpinLock(&Section->ViewListLock);
|
|
|
|
KeInitializeMutex(&Section->Lock, 0);
|
|
|
|
Section->Flags = 0;
|
|
|
|
Section->NrSegments = 1;
|
|
|
|
Section->ImageBase = NULL;
|
|
|
|
Section->EntryPoint = NULL;
|
|
|
|
Section->StackReserve = 0;
|
|
|
|
Section->StackCommit = 0;
|
|
|
|
Section->Subsystem = 0;
|
|
|
|
Section->MinorSubsystemVersion = 0;
|
|
|
|
Section->MajorSubsystemVersion = 0;
|
|
|
|
Section->ImageCharacteristics = 0;
|
|
|
|
Section->Machine = 0;
|
|
|
|
Section->Executable = FALSE;
|
1998-10-05 04:01:30 +00:00
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
/*
|
|
|
|
* Check file access required
|
|
|
|
*/
|
|
|
|
if (SectionPageProtection & PAGE_READWRITE ||
|
|
|
|
SectionPageProtection & PAGE_EXECUTE_READWRITE)
|
|
|
|
{
|
|
|
|
FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FileAccess = FILE_READ_DATA;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reference the file handle
|
|
|
|
*/
|
|
|
|
Status = ObReferenceObjectByHandle(FileHandle,
|
|
|
|
FileAccess,
|
|
|
|
IoFileObjectType,
|
|
|
|
UserMode,
|
|
|
|
(PVOID*)&FileObject,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ZwClose(*SectionHandle);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
return(Status);
|
|
|
|
}
|
1999-08-29 06:59:11 +00:00
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
/*
|
|
|
|
* We can't do memory mappings if the file system doesn't support the
|
|
|
|
* standard FCB
|
|
|
|
*/
|
|
|
|
if (!(FileObject->Flags & FO_FCB_IS_VALID))
|
|
|
|
{
|
|
|
|
ZwClose(*SectionHandle);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return(STATUS_INVALID_FILE_FOR_SECTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: Revise this once a locking order for file size changes is
|
|
|
|
* decided
|
|
|
|
*/
|
|
|
|
if (UMaximumSize != NULL)
|
|
|
|
{
|
|
|
|
MaximumSize = *UMaximumSize;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MaximumSize =
|
|
|
|
((PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock the file
|
|
|
|
*/
|
|
|
|
Status = KeWaitForSingleObject((PVOID)&FileObject->Lock,
|
|
|
|
0,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
ZwClose(*SectionHandle);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this file hasn't been mapped as a data file before then allocate a
|
|
|
|
* section segment to describe the data file mapping
|
|
|
|
*/
|
|
|
|
if (FileObject->SectionObjectPointers->DataSectionObject == NULL)
|
|
|
|
{
|
2001-03-07 16:48:45 +00:00
|
|
|
Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
|
|
|
|
TAG_MM_SECTION_SEGMENT);
|
2001-02-10 22:51:11 +00:00
|
|
|
if (Segment == NULL)
|
|
|
|
{
|
|
|
|
KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
|
|
|
|
ZwClose(*SectionHandle);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return(STATUS_NO_MEMORY);
|
|
|
|
}
|
|
|
|
Section->Segments = Segment;
|
|
|
|
Segment->ReferenceCount = 1;
|
|
|
|
KeInitializeMutex(&Segment->Lock, 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the lock before assigning the segment to the file object
|
|
|
|
*/
|
|
|
|
Status = KeWaitForSingleObject((PVOID)&Segment->Lock,
|
|
|
|
0,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
|
|
|
|
ExFreePool(Segment);
|
|
|
|
ZwClose(*SectionHandle);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
FileObject->SectionObjectPointers->DataSectionObject = (PVOID)Segment;
|
|
|
|
|
|
|
|
Segment->FileOffset = 0;
|
|
|
|
Segment->Protection = 0;
|
|
|
|
Segment->Attributes = 0;
|
|
|
|
Segment->Flags = 0;
|
|
|
|
Segment->Characteristics = 0;
|
|
|
|
if (AllocationAttributes & SEC_RESERVE)
|
|
|
|
{
|
|
|
|
Segment->Length = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Segment->Length = MaximumSize.u.LowPart;
|
|
|
|
}
|
|
|
|
Segment->VirtualAddress = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If the file is already mapped as a data file then we may need
|
|
|
|
* to extend it
|
|
|
|
*/
|
|
|
|
Segment =
|
|
|
|
(PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers->
|
|
|
|
DataSectionObject;
|
|
|
|
Section->Segments = Segment;
|
|
|
|
InterlockedIncrement((PLONG)&Segment->ReferenceCount);
|
|
|
|
Status = KeWaitForSingleObject((PVOID)&Section->Lock,
|
|
|
|
0,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
InterlockedDecrement((PLONG)&Segment->ReferenceCount);
|
|
|
|
KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
|
|
|
|
ZwClose(*SectionHandle);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
if (MaximumSize.u.LowPart > Segment->Length &&
|
|
|
|
!(AllocationAttributes & SEC_RESERVE))
|
|
|
|
{
|
|
|
|
Segment->Length = MaximumSize.u.LowPart;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
|
|
|
|
Section->FileObject = FileObject;
|
|
|
|
KeReleaseMutex(&Segment->Lock, FALSE);
|
|
|
|
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
MmCreateImageSection(PHANDLE SectionHandle,
|
|
|
|
ACCESS_MASK DesiredAccess,
|
|
|
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
|
|
PLARGE_INTEGER UMaximumSize,
|
|
|
|
ULONG SectionPageProtection,
|
|
|
|
ULONG AllocationAttributes,
|
|
|
|
HANDLE FileHandle)
|
|
|
|
{
|
|
|
|
PSECTION_OBJECT Section;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PFILE_OBJECT FileObject;
|
|
|
|
ULONG FileAccess;
|
|
|
|
IMAGE_DOS_HEADER DosHeader;
|
|
|
|
IO_STATUS_BLOCK Iosb;
|
|
|
|
LARGE_INTEGER Offset;
|
|
|
|
IMAGE_NT_HEADERS PEHeader;
|
|
|
|
PIMAGE_SECTION_HEADER ImageSections;
|
|
|
|
PMM_SECTION_SEGMENT SectionSegments;
|
|
|
|
ULONG NrSegments;
|
2001-03-09 14:40:28 +00:00
|
|
|
PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
|
2001-02-10 22:51:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check the protection
|
|
|
|
*/
|
|
|
|
if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
|
|
|
|
SectionPageProtection)
|
|
|
|
{
|
|
|
|
return(STATUS_INVALID_PAGE_PROTECTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Specifying a maximum size is meaningless for an image section
|
|
|
|
*/
|
|
|
|
if (UMaximumSize != NULL)
|
|
|
|
{
|
|
|
|
return(STATUS_INVALID_PARAMETER_4);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read the dos header
|
|
|
|
*/
|
|
|
|
Offset.QuadPart = 0;
|
|
|
|
Status = ZwReadFile(FileHandle,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&Iosb,
|
|
|
|
&DosHeader,
|
|
|
|
sizeof(DosHeader),
|
|
|
|
&Offset,
|
|
|
|
0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
if (Iosb.Information != sizeof(DosHeader))
|
|
|
|
{
|
|
|
|
return(STATUS_INVALID_IMAGE_FORMAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check the DOS signature
|
|
|
|
*/
|
|
|
|
if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
|
|
|
|
{
|
|
|
|
return(STATUS_INVALID_IMAGE_FORMAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read the PE header
|
|
|
|
*/
|
|
|
|
Offset.QuadPart = DosHeader.e_lfanew;
|
|
|
|
Status = ZwReadFile(FileHandle,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&Iosb,
|
|
|
|
&PEHeader,
|
|
|
|
sizeof(PEHeader),
|
|
|
|
&Offset,
|
|
|
|
0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
if (Iosb.Information != sizeof(PEHeader))
|
|
|
|
{
|
|
|
|
return(STATUS_INVALID_IMAGE_FORMAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check the signature
|
|
|
|
*/
|
|
|
|
if (PEHeader.Signature != IMAGE_NT_SIGNATURE)
|
|
|
|
{
|
|
|
|
return(STATUS_INVALID_IMAGE_FORMAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read in the section headers
|
|
|
|
*/
|
|
|
|
Offset.QuadPart = DosHeader.e_lfanew + sizeof(PEHeader);
|
|
|
|
ImageSections =
|
|
|
|
ExAllocatePool(NonPagedPool,
|
|
|
|
PEHeader.FileHeader.NumberOfSections *
|
|
|
|
sizeof(IMAGE_SECTION_HEADER));
|
|
|
|
Status = ZwReadFile(FileHandle,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&Iosb,
|
|
|
|
ImageSections,
|
|
|
|
PEHeader.FileHeader.NumberOfSections *
|
|
|
|
sizeof(IMAGE_SECTION_HEADER),
|
|
|
|
&Offset,
|
|
|
|
0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ExFreePool(ImageSections);
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
if (Iosb.Information !=
|
|
|
|
(PEHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)))
|
|
|
|
{
|
|
|
|
ExFreePool(ImageSections);
|
|
|
|
return(STATUS_INVALID_IMAGE_FORMAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the section
|
|
|
|
*/
|
2001-06-16 14:11:31 +00:00
|
|
|
Status = ObCreateObject(SectionHandle,
|
|
|
|
DesiredAccess,
|
|
|
|
ObjectAttributes,
|
|
|
|
MmSectionObjectType,
|
|
|
|
(PVOID*)&Section);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-02-10 22:51:11 +00:00
|
|
|
{
|
|
|
|
ExFreePool(ImageSections);
|
2001-06-16 14:11:31 +00:00
|
|
|
return(Status);
|
2001-02-10 22:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize it
|
|
|
|
*/
|
|
|
|
Section->SectionPageProtection = SectionPageProtection;
|
|
|
|
Section->AllocateAttributes = AllocationAttributes;
|
|
|
|
InitializeListHead(&Section->ViewListHead);
|
|
|
|
KeInitializeSpinLock(&Section->ViewListLock);
|
|
|
|
KeInitializeMutex(&Section->Lock, 0);
|
|
|
|
Section->Flags = MM_IMAGE_SECTION;
|
|
|
|
Section->NrSegments = PEHeader.FileHeader.NumberOfSections + 1;
|
|
|
|
Section->ImageBase = (PVOID)PEHeader.OptionalHeader.ImageBase;
|
|
|
|
Section->EntryPoint = (PVOID)PEHeader.OptionalHeader.AddressOfEntryPoint;
|
|
|
|
Section->StackReserve = PEHeader.OptionalHeader.SizeOfStackReserve;
|
|
|
|
Section->StackCommit = PEHeader.OptionalHeader.SizeOfStackCommit;
|
|
|
|
Section->Subsystem = PEHeader.OptionalHeader.Subsystem;
|
|
|
|
Section->MinorSubsystemVersion =
|
|
|
|
PEHeader.OptionalHeader.MinorSubsystemVersion;
|
|
|
|
Section->MajorSubsystemVersion =
|
|
|
|
PEHeader.OptionalHeader.MajorSubsystemVersion;
|
|
|
|
Section->ImageCharacteristics = PEHeader.FileHeader.Characteristics;
|
|
|
|
Section->Machine = PEHeader.FileHeader.Machine;
|
|
|
|
Section->Executable = (PEHeader.OptionalHeader.SizeOfCode != 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check file access required
|
|
|
|
*/
|
|
|
|
if (SectionPageProtection & PAGE_READWRITE ||
|
|
|
|
SectionPageProtection & PAGE_EXECUTE_READWRITE)
|
|
|
|
{
|
|
|
|
FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FileAccess = FILE_READ_DATA;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reference the file handle
|
|
|
|
*/
|
|
|
|
Status = ObReferenceObjectByHandle(FileHandle,
|
|
|
|
FileAccess,
|
|
|
|
IoFileObjectType,
|
|
|
|
UserMode,
|
|
|
|
(PVOID*)&FileObject,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ZwClose(*SectionHandle);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ExFreePool(ImageSections);
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We can't do memory mappings if the file system doesn't support the
|
|
|
|
* standard FCB
|
|
|
|
*/
|
|
|
|
if (!(FileObject->Flags & FO_FCB_IS_VALID))
|
|
|
|
{
|
|
|
|
ZwClose(*SectionHandle);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
ExFreePool(ImageSections);
|
|
|
|
return(STATUS_INVALID_FILE_FOR_SECTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock the file
|
|
|
|
*/
|
|
|
|
Status = KeWaitForSingleObject((PVOID)&FileObject->Lock,
|
|
|
|
0,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
ZwClose(*SectionHandle);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
ExFreePool(ImageSections);
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this file hasn't been mapped as a image file before then allocate the
|
|
|
|
* section segments to describe the mapping
|
|
|
|
*/
|
|
|
|
NrSegments = PEHeader.FileHeader.NumberOfSections + 1;
|
|
|
|
if (FileObject->SectionObjectPointers->ImageSectionObject == NULL)
|
|
|
|
{
|
|
|
|
ULONG i;
|
2001-03-09 14:40:28 +00:00
|
|
|
ULONG Size;
|
|
|
|
|
|
|
|
Size = sizeof(MM_IMAGE_SECTION_OBJECT) +
|
|
|
|
(sizeof(MM_SECTION_SEGMENT) * NrSegments);
|
|
|
|
ImageSectionObject =
|
|
|
|
ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MM_SECTION_SEGMENT);
|
|
|
|
if (ImageSectionObject == NULL)
|
2001-02-10 22:51:11 +00:00
|
|
|
{
|
|
|
|
KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
|
|
|
|
ZwClose(*SectionHandle);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
ExFreePool(ImageSections);
|
|
|
|
return(STATUS_NO_MEMORY);
|
|
|
|
}
|
2001-03-09 14:40:28 +00:00
|
|
|
ImageSectionObject->NrSegments = NrSegments;
|
|
|
|
SectionSegments = ImageSectionObject->Segments;
|
2001-02-10 22:51:11 +00:00
|
|
|
Section->Segments = SectionSegments;
|
|
|
|
|
|
|
|
SectionSegments[0].FileOffset = 0;
|
|
|
|
SectionSegments[0].Characteristics = IMAGE_SECTION_CHAR_DATA;
|
|
|
|
SectionSegments[0].Protection = PAGE_READWRITE;
|
|
|
|
SectionSegments[0].RawLength = PAGESIZE;
|
|
|
|
SectionSegments[0].Length = PAGESIZE;
|
|
|
|
SectionSegments[0].Flags = 0;
|
2001-03-09 14:40:28 +00:00
|
|
|
SectionSegments[0].ReferenceCount = 1;
|
2001-02-10 22:51:11 +00:00
|
|
|
SectionSegments[0].VirtualAddress = 0;
|
|
|
|
KeInitializeMutex(&SectionSegments[0].Lock, 0);
|
|
|
|
|
|
|
|
for (i = 1; i < NrSegments; i++)
|
|
|
|
{
|
|
|
|
SectionSegments[i].FileOffset =
|
|
|
|
ImageSections[i-1].PointerToRawData;
|
|
|
|
SectionSegments[i].Characteristics =
|
|
|
|
ImageSections[i-1].Characteristics;
|
|
|
|
if (ImageSections[i-1].Characteristics & IMAGE_SECTION_CHAR_CODE)
|
|
|
|
{
|
|
|
|
SectionSegments[i].Protection = PAGE_EXECUTE_READ;
|
|
|
|
SectionSegments[i].Attributes = 0;
|
|
|
|
}
|
|
|
|
else if (ImageSections[i-1].Characteristics &
|
|
|
|
IMAGE_SECTION_CHAR_DATA)
|
|
|
|
{
|
|
|
|
SectionSegments[i].Protection = PAGE_READWRITE;
|
|
|
|
SectionSegments[i].Attributes = 0;
|
|
|
|
}
|
|
|
|
else if (ImageSections[i-1].Characteristics & IMAGE_SECTION_CHAR_BSS)
|
|
|
|
{
|
|
|
|
SectionSegments[i].Protection = PAGE_READWRITE;
|
|
|
|
SectionSegments[i].Attributes = MM_SECTION_SEGMENT_BSS;
|
|
|
|
}
|
|
|
|
SectionSegments[i].RawLength = ImageSections[i-1].SizeOfRawData;
|
|
|
|
SectionSegments[i].Length =
|
|
|
|
ImageSections[i-1].Misc.VirtualSize;
|
|
|
|
SectionSegments[i].Flags = 0;
|
|
|
|
SectionSegments[i].ReferenceCount = 1;
|
|
|
|
SectionSegments[i].VirtualAddress =
|
|
|
|
(PVOID)ImageSections[i-1].VirtualAddress;
|
|
|
|
KeInitializeMutex(&SectionSegments[i].Lock, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
FileObject->SectionObjectPointers->ImageSectionObject =
|
2001-03-09 14:40:28 +00:00
|
|
|
(PVOID)ImageSectionObject;
|
2001-03-07 16:48:45 +00:00
|
|
|
ExFreePool(ImageSections);
|
2001-02-10 22:51:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ULONG i;
|
|
|
|
|
2001-03-09 14:40:28 +00:00
|
|
|
ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)
|
2001-02-10 22:51:11 +00:00
|
|
|
FileObject->SectionObjectPointers->ImageSectionObject;
|
2001-03-09 14:40:28 +00:00
|
|
|
SectionSegments = ImageSectionObject->Segments;
|
2001-02-10 22:51:11 +00:00
|
|
|
Section->Segments = SectionSegments;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise just reference all the section segments
|
|
|
|
*/
|
|
|
|
for (i = 0; i < NrSegments; i++)
|
|
|
|
{
|
|
|
|
InterlockedIncrement(&SectionSegments[i].ReferenceCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
|
|
|
|
Section->FileObject = FileObject;
|
|
|
|
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS STDCALL
|
|
|
|
NtCreateSection (OUT PHANDLE SectionHandle,
|
|
|
|
IN ACCESS_MASK DesiredAccess,
|
|
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
|
|
|
IN PLARGE_INTEGER MaximumSize OPTIONAL,
|
|
|
|
IN ULONG SectionPageProtection OPTIONAL,
|
|
|
|
IN ULONG AllocationAttributes,
|
|
|
|
IN HANDLE FileHandle OPTIONAL)
|
|
|
|
{
|
|
|
|
if (AllocationAttributes & SEC_IMAGE)
|
|
|
|
{
|
|
|
|
return(MmCreateImageSection(SectionHandle,
|
|
|
|
DesiredAccess,
|
|
|
|
ObjectAttributes,
|
|
|
|
MaximumSize,
|
|
|
|
SectionPageProtection,
|
|
|
|
AllocationAttributes,
|
|
|
|
FileHandle));
|
|
|
|
}
|
|
|
|
else if (FileHandle != NULL)
|
|
|
|
{
|
|
|
|
return(MmCreateDataFileSection(SectionHandle,
|
|
|
|
DesiredAccess,
|
|
|
|
ObjectAttributes,
|
|
|
|
MaximumSize,
|
|
|
|
SectionPageProtection,
|
|
|
|
AllocationAttributes,
|
|
|
|
FileHandle));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return(MmCreatePageFileSection(SectionHandle,
|
|
|
|
DesiredAccess,
|
|
|
|
ObjectAttributes,
|
|
|
|
MaximumSize,
|
|
|
|
SectionPageProtection,
|
|
|
|
AllocationAttributes));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* NAME
|
|
|
|
* NtOpenSection
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
|
|
|
* SectionHandle
|
|
|
|
*
|
|
|
|
* DesiredAccess
|
|
|
|
*
|
|
|
|
* ObjectAttributes
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
*
|
|
|
|
* REVISIONS
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
NTSTATUS STDCALL
|
|
|
|
NtOpenSection(PHANDLE SectionHandle,
|
|
|
|
ACCESS_MASK DesiredAccess,
|
|
|
|
POBJECT_ATTRIBUTES ObjectAttributes)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
*SectionHandle = 0;
|
|
|
|
|
|
|
|
Status = ObOpenObjectByName(ObjectAttributes,
|
|
|
|
MmSectionObjectType,
|
|
|
|
NULL,
|
|
|
|
UserMode,
|
|
|
|
DesiredAccess,
|
|
|
|
NULL,
|
|
|
|
SectionHandle);
|
|
|
|
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
MmMapViewOfSegment(PEPROCESS Process,
|
|
|
|
PMADDRESS_SPACE AddressSpace,
|
|
|
|
PSECTION_OBJECT Section,
|
|
|
|
PMM_SECTION_SEGMENT Segment,
|
|
|
|
PVOID* BaseAddress,
|
|
|
|
ULONG ViewSize,
|
|
|
|
ULONG Protect,
|
|
|
|
ULONG ViewOffset)
|
|
|
|
{
|
|
|
|
PMEMORY_AREA MArea;
|
|
|
|
NTSTATUS Status;
|
|
|
|
KIRQL oldIrql;
|
2001-08-03 09:36:19 +00:00
|
|
|
MmLockAddressSpace(&Process->AddressSpace);
|
2001-02-10 22:51:11 +00:00
|
|
|
Status = MmCreateMemoryArea(Process,
|
|
|
|
&Process->AddressSpace,
|
|
|
|
MEMORY_AREA_SECTION_VIEW_COMMIT,
|
|
|
|
BaseAddress,
|
|
|
|
ViewSize,
|
|
|
|
Protect,
|
2001-03-25 03:34:30 +00:00
|
|
|
&MArea,
|
|
|
|
FALSE);
|
2001-08-03 09:36:19 +00:00
|
|
|
MmUnlockAddressSpace(&Process->AddressSpace);
|
2001-02-10 22:51:11 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
|
|
|
|
InsertTailList(&Section->ViewListHead,
|
|
|
|
&MArea->Data.SectionData.ViewListEntry);
|
|
|
|
KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
|
2001-03-08 22:06:02 +00:00
|
|
|
|
|
|
|
ObReferenceObjectByPointer((PVOID)Section,
|
|
|
|
SECTION_MAP_READ,
|
|
|
|
NULL,
|
|
|
|
ExGetPreviousMode());
|
2001-02-10 22:51:11 +00:00
|
|
|
MArea->Data.SectionData.Segment = Segment;
|
|
|
|
MArea->Data.SectionData.Section = Section;
|
|
|
|
MArea->Data.SectionData.ViewOffset = ViewOffset;
|
|
|
|
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* NAME EXPORTED
|
|
|
|
* NtMapViewOfSection
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
* Maps a view of a section into the virtual address space of a
|
1999-08-29 06:59:11 +00:00
|
|
|
* process.
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
|
|
|
* SectionHandle
|
|
|
|
* Handle of the section.
|
|
|
|
*
|
|
|
|
* ProcessHandle
|
|
|
|
* Handle of the process.
|
|
|
|
*
|
|
|
|
* BaseAddress
|
|
|
|
* Desired base address (or NULL) on entry;
|
|
|
|
* Actual base address of the view on exit.
|
|
|
|
*
|
|
|
|
* ZeroBits
|
|
|
|
* Number of high order address bits that must be zero.
|
|
|
|
*
|
|
|
|
* CommitSize
|
|
|
|
* Size in bytes of the initially committed section of
|
|
|
|
* the view.
|
|
|
|
*
|
|
|
|
* SectionOffset
|
|
|
|
* Offset in bytes from the beginning of the section
|
|
|
|
* to the beginning of the view.
|
|
|
|
*
|
|
|
|
* ViewSize
|
|
|
|
* Desired length of map (or zero to map all) on entry
|
|
|
|
* Actual length mapped on exit.
|
|
|
|
*
|
|
|
|
* InheritDisposition
|
|
|
|
* Specified how the view is to be shared with
|
|
|
|
* child processes.
|
|
|
|
*
|
|
|
|
* AllocateType
|
|
|
|
* Type of allocation for the pages.
|
|
|
|
*
|
|
|
|
* Protect
|
|
|
|
* Protection for the committed region of the view.
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
* Status.
|
|
|
|
*/
|
2000-12-28 03:38:08 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
NtMapViewOfSection(HANDLE SectionHandle,
|
|
|
|
HANDLE ProcessHandle,
|
|
|
|
PVOID* BaseAddress,
|
|
|
|
ULONG ZeroBits,
|
|
|
|
ULONG CommitSize,
|
|
|
|
PLARGE_INTEGER SectionOffset,
|
|
|
|
PULONG ViewSize,
|
|
|
|
SECTION_INHERIT InheritDisposition,
|
|
|
|
ULONG AllocationType,
|
|
|
|
ULONG Protect)
|
2001-02-10 22:51:11 +00:00
|
|
|
{
|
2000-05-13 13:51:08 +00:00
|
|
|
PSECTION_OBJECT Section;
|
|
|
|
PEPROCESS Process;
|
|
|
|
NTSTATUS Status;
|
1999-11-24 11:51:55 +00:00
|
|
|
ULONG ViewOffset;
|
2000-03-29 13:11:55 +00:00
|
|
|
PMADDRESS_SPACE AddressSpace;
|
2001-02-10 22:51:11 +00:00
|
|
|
|
|
|
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
|
|
|
PROCESS_VM_OPERATION,
|
|
|
|
PsProcessType,
|
|
|
|
UserMode,
|
|
|
|
(PVOID*)&Process,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
1999-03-19 05:55:55 +00:00
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
AddressSpace = &Process->AddressSpace;
|
1998-10-05 04:01:30 +00:00
|
|
|
|
1999-11-24 11:51:55 +00:00
|
|
|
Status = ObReferenceObjectByHandle(SectionHandle,
|
|
|
|
SECTION_MAP_READ,
|
2000-04-02 13:32:43 +00:00
|
|
|
MmSectionObjectType,
|
1999-11-24 11:51:55 +00:00
|
|
|
UserMode,
|
|
|
|
(PVOID*)&Section,
|
|
|
|
NULL);
|
|
|
|
if (!(NT_SUCCESS(Status)))
|
|
|
|
{
|
2001-01-28 15:17:52 +00:00
|
|
|
DPRINT("ObReference failed rc=%x\n",Status);
|
2001-02-10 22:51:11 +00:00
|
|
|
ObDereferenceObject(Process);
|
2000-12-28 03:38:08 +00:00
|
|
|
return(Status);
|
1999-11-24 11:51:55 +00:00
|
|
|
}
|
2001-02-10 22:51:11 +00:00
|
|
|
|
|
|
|
MmLockAddressSpace(AddressSpace);
|
2000-05-13 13:51:08 +00:00
|
|
|
MmLockSection(Section);
|
1999-03-19 05:55:55 +00:00
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
if (Section->Flags & MM_IMAGE_SECTION)
|
1999-11-24 11:51:55 +00:00
|
|
|
{
|
2001-02-10 22:51:11 +00:00
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
for (i = 0; i < Section->NrSegments; i++)
|
|
|
|
{
|
|
|
|
PVOID SBaseAddress;
|
|
|
|
|
2001-03-30 15:14:53 +00:00
|
|
|
if (!(Section->Segments[i].Characteristics & IMAGE_SECTION_NOLOAD))
|
2001-02-10 22:51:11 +00:00
|
|
|
{
|
2001-03-30 15:14:53 +00:00
|
|
|
SBaseAddress = (PVOID)
|
|
|
|
((ULONG)Section->ImageBase +
|
|
|
|
(ULONG)Section->Segments[i].VirtualAddress);
|
|
|
|
|
|
|
|
MmLockSectionSegment(&Section->Segments[i]);
|
|
|
|
Status = MmMapViewOfSegment(Process,
|
|
|
|
&Process->AddressSpace,
|
|
|
|
Section,
|
|
|
|
&Section->Segments[i],
|
|
|
|
&SBaseAddress,
|
|
|
|
Section->Segments[i].Length,
|
|
|
|
Section->Segments[i].Protection,
|
|
|
|
Section->Segments[i].FileOffset);
|
|
|
|
MmUnlockSectionSegment(&Section->Segments[i]);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
return(Status);
|
|
|
|
}
|
2001-02-10 22:51:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
*BaseAddress = Section->ImageBase;
|
1999-11-24 11:51:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-02-10 22:51:11 +00:00
|
|
|
if (SectionOffset == NULL)
|
|
|
|
{
|
|
|
|
ViewOffset = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ViewOffset = SectionOffset->u.LowPart;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ViewOffset % PAGESIZE) != 0)
|
|
|
|
{
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
return(STATUS_MAPPED_ALIGNMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (((*ViewSize)+ViewOffset) > Section->MaximumSize.u.LowPart)
|
|
|
|
{
|
1999-11-24 11:51:55 +00:00
|
|
|
(*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
|
2001-02-10 22:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MmLockSectionSegment(Section->Segments);
|
|
|
|
Status = MmMapViewOfSegment(Process,
|
|
|
|
&Process->AddressSpace,
|
|
|
|
Section,
|
|
|
|
Section->Segments,
|
|
|
|
BaseAddress,
|
|
|
|
*ViewSize,
|
|
|
|
Protect,
|
|
|
|
ViewOffset);
|
|
|
|
MmUnlockSectionSegment(Section->Segments);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
return(Status);
|
|
|
|
}
|
2000-12-28 03:38:08 +00:00
|
|
|
}
|
2001-02-10 22:51:11 +00:00
|
|
|
|
|
|
|
MmUnlockSection(Section);
|
2000-03-29 13:11:55 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2001-03-08 22:06:02 +00:00
|
|
|
ObDereferenceObject(Section);
|
|
|
|
ObDereferenceObject(Process);
|
1999-11-24 11:51:55 +00:00
|
|
|
|
|
|
|
return(STATUS_SUCCESS);
|
1998-10-05 04:01:30 +00:00
|
|
|
}
|
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
VOID STATIC
|
2001-03-08 22:06:02 +00:00
|
|
|
MmFreeSectionPage(PVOID Context, PVOID Address, ULONG PhysAddr)
|
2001-02-10 22:51:11 +00:00
|
|
|
{
|
|
|
|
PMEMORY_AREA MArea;
|
2001-03-29 17:24:43 +00:00
|
|
|
ULONG Entry;
|
2001-02-10 22:51:11 +00:00
|
|
|
|
|
|
|
MArea = (PMEMORY_AREA)Context;
|
|
|
|
|
|
|
|
if (PhysAddr != 0)
|
|
|
|
{
|
2001-03-29 17:24:43 +00:00
|
|
|
ULONG Offset;
|
|
|
|
|
|
|
|
Offset =
|
|
|
|
((ULONG)PAGE_ROUND_DOWN(Address) - (ULONG)MArea->BaseAddress) +
|
|
|
|
MArea->Data.SectionData.ViewOffset;
|
2001-02-10 22:51:11 +00:00
|
|
|
|
2001-03-29 17:24:43 +00:00
|
|
|
Entry = MmGetPageEntrySectionSegment(MArea->Data.SectionData.Segment,
|
|
|
|
Offset);
|
|
|
|
/*
|
|
|
|
* Just dereference private pages
|
|
|
|
*/
|
|
|
|
if (PhysAddr != (Entry & 0xFFFFF000))
|
|
|
|
{
|
|
|
|
MmDereferencePage((PVOID)PhysAddr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
MmUnsharePageEntrySectionSegment(MArea->Data.SectionData.Segment,
|
|
|
|
Offset);
|
|
|
|
MmDereferencePage((PVOID)PhysAddr);
|
|
|
|
#endif
|
2001-02-10 22:51:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS STDCALL
|
2000-12-28 03:38:08 +00:00
|
|
|
MmUnmapViewOfSection(PEPROCESS Process,
|
2001-03-08 22:06:02 +00:00
|
|
|
PVOID BaseAddress)
|
1999-11-24 11:51:55 +00:00
|
|
|
{
|
2001-02-10 22:51:11 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PMEMORY_AREA MemoryArea;
|
|
|
|
PMADDRESS_SPACE AddressSpace;
|
1999-11-24 11:51:55 +00:00
|
|
|
PSECTION_OBJECT Section;
|
2001-02-10 22:51:11 +00:00
|
|
|
PMM_SECTION_SEGMENT Segment;
|
1999-11-24 11:51:55 +00:00
|
|
|
KIRQL oldIrql;
|
2001-02-10 22:51:11 +00:00
|
|
|
|
|
|
|
AddressSpace = &Process->AddressSpace;
|
1999-11-24 11:51:55 +00:00
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
DPRINT("Opening memory area Process %x BaseAddress %x\n",
|
|
|
|
Process, BaseAddress);
|
|
|
|
MmLockAddressSpace(AddressSpace);
|
|
|
|
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
|
|
|
|
BaseAddress);
|
|
|
|
if (MemoryArea == NULL)
|
|
|
|
{
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
2000-04-03 21:54:42 +00:00
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
MmLockSection(MemoryArea->Data.SectionData.Section);
|
|
|
|
MmLockSectionSegment(MemoryArea->Data.SectionData.Segment);
|
|
|
|
Section = MemoryArea->Data.SectionData.Section;
|
|
|
|
Segment = MemoryArea->Data.SectionData.Segment;
|
1999-11-24 11:51:55 +00:00
|
|
|
KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
|
|
|
|
RemoveEntryList(&MemoryArea->Data.SectionData.ViewListEntry);
|
|
|
|
KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
|
2001-02-10 22:51:11 +00:00
|
|
|
if (MemoryArea->Data.SectionData.Section->Flags & SO_PHYSICAL_MEMORY)
|
|
|
|
{
|
|
|
|
Status = MmFreeMemoryArea(&Process->AddressSpace,
|
|
|
|
BaseAddress,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = MmFreeMemoryArea(&Process->AddressSpace,
|
|
|
|
BaseAddress,
|
|
|
|
0,
|
|
|
|
MmFreeSectionPage,
|
|
|
|
MemoryArea);
|
|
|
|
}
|
|
|
|
MmUnlockSection(Section);
|
|
|
|
MmUnlockSectionSegment(Segment);
|
2001-03-08 22:06:02 +00:00
|
|
|
ObDereferenceObject(Section);
|
2001-02-10 22:51:11 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
1999-11-24 11:51:55 +00:00
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
1998-08-25 04:27:26 +00:00
|
|
|
|
1999-08-29 06:59:11 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* NAME EXPORTED
|
|
|
|
* NtUnmapViewOfSection
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
|
|
|
* ProcessHandle
|
|
|
|
*
|
|
|
|
* BaseAddress
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
* Status.
|
|
|
|
*
|
|
|
|
* REVISIONS
|
|
|
|
*
|
|
|
|
*/
|
2000-12-28 03:38:08 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
NtUnmapViewOfSection (HANDLE ProcessHandle,
|
|
|
|
PVOID BaseAddress)
|
1998-10-05 04:01:30 +00:00
|
|
|
{
|
1999-11-24 11:51:55 +00:00
|
|
|
PEPROCESS Process;
|
2001-02-10 22:51:11 +00:00
|
|
|
NTSTATUS Status;
|
1999-11-24 11:51:55 +00:00
|
|
|
|
2000-02-13 16:05:19 +00:00
|
|
|
DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n",
|
2000-04-07 02:24:03 +00:00
|
|
|
ProcessHandle, BaseAddress);
|
2000-02-13 16:05:19 +00:00
|
|
|
|
|
|
|
DPRINT("Referencing process\n");
|
1999-11-24 11:51:55 +00:00
|
|
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
|
|
|
PROCESS_VM_OPERATION,
|
|
|
|
PsProcessType,
|
|
|
|
UserMode,
|
|
|
|
(PVOID*)&Process,
|
|
|
|
NULL);
|
2000-02-13 16:05:19 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("ObReferenceObjectByHandle failed (Status %x)\n", Status);
|
|
|
|
return(Status);
|
|
|
|
}
|
2001-02-10 22:51:11 +00:00
|
|
|
|
|
|
|
Status = MmUnmapViewOfSection(Process, BaseAddress);
|
|
|
|
|
1999-11-24 11:51:55 +00:00
|
|
|
ObDereferenceObject(Process);
|
1999-08-29 06:59:11 +00:00
|
|
|
|
1999-11-24 11:51:55 +00:00
|
|
|
return Status;
|
1998-10-05 04:01:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
NtQuerySection (IN HANDLE SectionHandle,
|
|
|
|
IN CINT SectionInformationClass,
|
|
|
|
OUT PVOID SectionInformation,
|
|
|
|
IN ULONG Length,
|
|
|
|
OUT PULONG ResultLength)
|
1998-10-05 04:01:30 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Queries the information of a section object.
|
|
|
|
* ARGUMENTS:
|
|
|
|
* SectionHandle = Handle to the section link object
|
|
|
|
* SectionInformationClass = Index to a certain information structure
|
|
|
|
* SectionInformation (OUT)= Caller supplies storage for resulting
|
|
|
|
* information
|
|
|
|
* Length = Size of the supplied storage
|
|
|
|
* ResultLength = Data written
|
|
|
|
* RETURNS: Status
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
{
|
2001-02-10 22:51:11 +00:00
|
|
|
PSECTION_OBJECT Section;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = ObReferenceObjectByHandle(SectionHandle,
|
|
|
|
SECTION_MAP_READ,
|
|
|
|
MmSectionObjectType,
|
|
|
|
UserMode,
|
|
|
|
(PVOID*)&Section,
|
|
|
|
NULL);
|
|
|
|
if (!(NT_SUCCESS(Status)))
|
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (SectionInformationClass)
|
|
|
|
{
|
|
|
|
case SectionBasicInformation:
|
|
|
|
{
|
|
|
|
PSECTION_BASIC_INFORMATION Sbi;
|
|
|
|
|
|
|
|
if (Length != sizeof(SECTION_BASIC_INFORMATION))
|
|
|
|
{
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
return(STATUS_INFO_LENGTH_MISMATCH);
|
|
|
|
}
|
|
|
|
|
|
|
|
Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
|
|
|
|
|
|
|
|
Sbi->BaseAddress = 0;
|
|
|
|
Sbi->Attributes = 0;
|
|
|
|
Sbi->Size.QuadPart = 0;
|
|
|
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SectionImageInformation:
|
|
|
|
{
|
|
|
|
PSECTION_IMAGE_INFORMATION Sii;
|
|
|
|
|
|
|
|
if (Length != sizeof(SECTION_IMAGE_INFORMATION))
|
|
|
|
{
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
return(STATUS_INFO_LENGTH_MISMATCH);
|
|
|
|
}
|
2001-08-03 09:36:19 +00:00
|
|
|
Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
|
2001-02-10 22:51:11 +00:00
|
|
|
Sii->EntryPoint = Section->EntryPoint;
|
|
|
|
Sii->Unknown1 = 0;
|
|
|
|
Sii->StackReserve = Section->StackReserve;
|
|
|
|
Sii->StackCommit = Section->StackCommit;
|
|
|
|
Sii->Subsystem = Section->Subsystem;
|
|
|
|
Sii->MinorSubsystemVersion = Section->MinorSubsystemVersion;
|
|
|
|
Sii->MajorSubsystemVersion = Section->MajorSubsystemVersion;
|
|
|
|
Sii->Unknown2 = 0;
|
|
|
|
Sii->Characteristics = Section->ImageCharacteristics;
|
|
|
|
Sii->ImageNumber = Section->Machine;
|
|
|
|
Sii->Executable = Section->Executable;
|
|
|
|
Sii->Unknown3 = 0;
|
|
|
|
Sii->Unknown4[0] = 0;
|
|
|
|
Sii->Unknown4[1] = 0;
|
|
|
|
Sii->Unknown4[2] = 0;
|
|
|
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
Status = STATUS_INVALID_INFO_CLASS;
|
|
|
|
}
|
|
|
|
ObDereferenceObject(Section);
|
|
|
|
return(Status);
|
1998-10-05 04:01:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
NtExtendSection(IN HANDLE SectionHandle,
|
|
|
|
IN ULONG NewMaximumSize)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
1999-11-24 11:51:55 +00:00
|
|
|
UNIMPLEMENTED;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
1999-08-29 06:59:11 +00:00
|
|
|
|
|
|
|
|
2000-03-19 09:14:52 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* NAME INTERNAL
|
|
|
|
* MmAllocateSection@4
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
|
|
|
* Length
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
*
|
|
|
|
* NOTE
|
|
|
|
* Code taken from ntoskrnl/mm/special.c.
|
|
|
|
*
|
|
|
|
* REVISIONS
|
|
|
|
*
|
|
|
|
*/
|
2000-12-28 03:38:08 +00:00
|
|
|
PVOID STDCALL
|
|
|
|
MmAllocateSection (IN ULONG Length)
|
2000-03-19 09:14:52 +00:00
|
|
|
{
|
2000-03-29 13:11:55 +00:00
|
|
|
PVOID Result;
|
|
|
|
MEMORY_AREA* marea;
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG i;
|
|
|
|
PMADDRESS_SPACE AddressSpace;
|
|
|
|
|
|
|
|
DPRINT("MmAllocateSection(Length %x)\n",Length);
|
|
|
|
|
|
|
|
AddressSpace = MmGetKernelAddressSpace();
|
|
|
|
Result = NULL;
|
|
|
|
MmLockAddressSpace(AddressSpace);
|
|
|
|
Status = MmCreateMemoryArea (NULL,
|
|
|
|
AddressSpace,
|
|
|
|
MEMORY_AREA_SYSTEM,
|
|
|
|
&Result,
|
|
|
|
Length,
|
|
|
|
0,
|
2001-03-25 03:34:30 +00:00
|
|
|
&marea,
|
|
|
|
FALSE);
|
2001-02-10 22:51:11 +00:00
|
|
|
if (!NT_SUCCESS(STATUS_SUCCESS))
|
2000-03-29 13:11:55 +00:00
|
|
|
{
|
2001-08-03 09:36:19 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2000-03-29 13:11:55 +00:00
|
|
|
return (NULL);
|
2000-07-04 08:52:47 +00:00
|
|
|
}
|
2000-03-29 13:11:55 +00:00
|
|
|
DPRINT("Result %p\n",Result);
|
|
|
|
for (i = 0; (i <= (Length / PAGESIZE)); i++)
|
|
|
|
{
|
2000-08-20 17:02:10 +00:00
|
|
|
Status = MmCreateVirtualMapping (NULL,
|
|
|
|
(Result + (i * PAGESIZE)),
|
|
|
|
PAGE_READWRITE,
|
|
|
|
(ULONG)MmAllocPage(0));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DbgPrint("Unable to create virtual mapping\n");
|
2001-08-03 09:36:19 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
KeBugCheck(0);
|
2000-08-20 17:02:10 +00:00
|
|
|
}
|
2000-03-29 13:11:55 +00:00
|
|
|
}
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
return ((PVOID)Result);
|
2000-03-19 09:14:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-04-02 13:32:43 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* NAME EXPORTED
|
|
|
|
* MmMapViewOfSection@40
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
|
|
|
* FIXME: stack space allocated is 40 bytes, but nothing
|
|
|
|
* is known about what they are filled with.
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
* Status.
|
|
|
|
*
|
|
|
|
*/
|
2000-12-28 03:38:08 +00:00
|
|
|
PVOID STDCALL
|
|
|
|
MmMapViewOfSection (DWORD Unknown0,
|
|
|
|
DWORD Unknown1,
|
|
|
|
DWORD Unknown2,
|
|
|
|
DWORD Unknown3,
|
|
|
|
DWORD Unknown4,
|
|
|
|
DWORD Unknown5,
|
|
|
|
DWORD Unknown6,
|
|
|
|
DWORD Unknown7,
|
|
|
|
DWORD Unknown8,
|
|
|
|
DWORD Unknown9)
|
2000-04-02 13:32:43 +00:00
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
BOOLEAN STDCALL
|
|
|
|
MmCanFileBeTruncated (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
|
|
|
|
IN PLARGE_INTEGER NewFileSize)
|
2000-04-02 13:32:43 +00:00
|
|
|
{
|
2000-12-28 03:38:08 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return (FALSE);
|
2000-04-02 13:32:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
BOOLEAN STDCALL
|
|
|
|
MmDisableModifiedWriteOfSection (DWORD Unknown0)
|
2000-04-02 13:32:43 +00:00
|
|
|
{
|
2000-12-28 03:38:08 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return (FALSE);
|
2000-04-02 13:32:43 +00:00
|
|
|
}
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
BOOLEAN STDCALL
|
|
|
|
MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
|
|
|
|
IN MMFLUSH_TYPE FlushType)
|
2000-04-02 13:32:43 +00:00
|
|
|
{
|
2000-12-28 03:38:08 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return (FALSE);
|
2000-04-02 13:32:43 +00:00
|
|
|
}
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
BOOLEAN STDCALL
|
|
|
|
MmForceSectionClosed (DWORD Unknown0,
|
|
|
|
DWORD Unknown1)
|
2000-04-02 13:32:43 +00:00
|
|
|
{
|
2000-12-28 03:38:08 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return (FALSE);
|
2000-04-02 13:32:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
MmMapViewInSystemSpace (IN PVOID Section,
|
|
|
|
OUT PVOID * MappedBase,
|
|
|
|
IN PULONG ViewSize)
|
2000-04-02 13:32:43 +00:00
|
|
|
{
|
2000-12-28 03:38:08 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return (STATUS_NOT_IMPLEMENTED);
|
2000-04-02 13:32:43 +00:00
|
|
|
}
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
MmUnmapViewInSystemSpace (DWORD Unknown0)
|
2000-04-02 13:32:43 +00:00
|
|
|
{
|
2000-12-28 03:38:08 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return (STATUS_NOT_IMPLEMENTED);
|
2000-04-02 13:32:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-12-28 03:38:08 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
MmSetBankedSection (DWORD Unknown0,
|
|
|
|
DWORD Unknown1,
|
|
|
|
DWORD Unknown2,
|
|
|
|
DWORD Unknown3,
|
|
|
|
DWORD Unknown4,
|
|
|
|
DWORD Unknown5)
|
2000-04-02 13:32:43 +00:00
|
|
|
{
|
2000-12-28 03:38:08 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return (STATUS_NOT_IMPLEMENTED);
|
2000-04-02 13:32:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* NAME EXPORTED
|
|
|
|
* MmCreateSection@
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
* Creates a section object.
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
|
|
|
* SectionObjiect (OUT)
|
|
|
|
* Caller supplied storage for the resulting pointer
|
|
|
|
* to a SECTION_BOJECT instance;
|
|
|
|
*
|
|
|
|
* DesiredAccess
|
|
|
|
* Specifies the desired access to the section can be a
|
|
|
|
* combination of:
|
|
|
|
* STANDARD_RIGHTS_REQUIRED |
|
|
|
|
* SECTION_QUERY |
|
|
|
|
* SECTION_MAP_WRITE |
|
|
|
|
* SECTION_MAP_READ |
|
|
|
|
* SECTION_MAP_EXECUTE
|
|
|
|
*
|
|
|
|
* ObjectAttributes [OPTIONAL]
|
|
|
|
* Initialized attributes for the object can be used
|
|
|
|
* to create a named section;
|
|
|
|
*
|
|
|
|
* MaximumSize
|
|
|
|
* Maximizes the size of the memory section. Must be
|
|
|
|
* non-NULL for a page-file backed section.
|
|
|
|
* If value specified for a mapped file and the file is
|
|
|
|
* not large enough, file will be extended.
|
|
|
|
*
|
|
|
|
* SectionPageProtection
|
|
|
|
* Can be a combination of:
|
|
|
|
* PAGE_READONLY |
|
|
|
|
* PAGE_READWRITE |
|
|
|
|
* PAGE_WRITEONLY |
|
|
|
|
* PAGE_WRITECOPY
|
|
|
|
*
|
|
|
|
* AllocationAttributes
|
|
|
|
* Can be a combination of:
|
|
|
|
* SEC_IMAGE |
|
|
|
|
* SEC_RESERVE
|
|
|
|
*
|
|
|
|
* FileHandle
|
|
|
|
* Handle to a file to create a section mapped to a file
|
|
|
|
* instead of a memory backed section;
|
|
|
|
*
|
|
|
|
* File
|
|
|
|
* Unknown.
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
* Status.
|
|
|
|
*/
|
2000-12-28 03:38:08 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
MmCreateSection (OUT PSECTION_OBJECT * SectionObject,
|
|
|
|
IN ACCESS_MASK DesiredAccess,
|
|
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
|
|
|
IN PLARGE_INTEGER MaximumSize,
|
|
|
|
IN ULONG SectionPageProtection,
|
|
|
|
IN ULONG AllocationAttributes,
|
|
|
|
IN HANDLE FileHandle OPTIONAL,
|
|
|
|
IN PFILE_OBJECT File OPTIONAL)
|
2000-04-02 13:32:43 +00:00
|
|
|
{
|
2000-12-28 03:38:08 +00:00
|
|
|
return (STATUS_NOT_IMPLEMENTED);
|
2000-04-02 13:32:43 +00:00
|
|
|
}
|
|
|
|
|
1999-08-29 06:59:11 +00:00
|
|
|
/* EOF */
|
2000-12-28 03:38:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|