/* INCLUDES *****************************************************************/
#include <limits.h>
-#include <ddk/ntddk.h>
+#define NTOS_MODE_KERNEL
+#include <ntos.h>
#include <internal/mm.h>
#include <internal/io.h>
#include <internal/ps.h>
{
PSECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
- LARGE_INTEGER Offset;
+ ULONG Offset;
BOOLEAN WasDirty;
BOOLEAN Private;
} MM_SECTION_PAGEOUT_CONTEXT;
MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment)
{
ULONG i;
-
- for (i = 0; i < NR_SECTION_PAGE_TABLES; i++)
+ if (Segment->Length > NR_SECTION_PAGE_TABLES * PAGE_SIZE)
{
- if (Segment->PageDirectory.PageTables[i] != NULL)
- {
- ExFreePool(Segment->PageDirectory.PageTables[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)
+ if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
{
PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
-
+ PMM_SECTION_SEGMENT SectionSegments;
+ ULONG NrSegments;
ULONG i;
- ImageSectionObject =
- (PMM_IMAGE_SECTION_OBJECT)FileObject->SectionObjectPointers->
- ImageSectionObject;
-
- for (i = 0; i < ImageSectionObject->NrSegments; i++)
+ ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)FileObject->SectionObjectPointer->ImageSectionObject;
+ NrSegments = ImageSectionObject->NrSegments;
+ SectionSegments = ImageSectionObject->Segments;
+ for (i = 0; i < NrSegments; i++)
{
- if (ImageSectionObject->Segments[i].ReferenceCount != 0)
+ if (SectionSegments[i].ReferenceCount != 0)
{
DPRINT1("Image segment %d still referenced (was %d)\n", i,
- ImageSectionObject->Segments[i].ReferenceCount);
- KeBugCheck(0);
+ SectionSegments[i].ReferenceCount);
+ KEBUGCHECK(0);
}
- MmFreePageTablesSectionSegment(&ImageSectionObject->Segments[i]);
+ MmFreePageTablesSectionSegment(&SectionSegments[i]);
}
ExFreePool(ImageSectionObject);
- FileObject->SectionObjectPointers->ImageSectionObject = NULL;
+ FileObject->SectionObjectPointer->ImageSectionObject = NULL;
}
- if (FileObject->SectionObjectPointers->DataSectionObject != NULL)
+ if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
{
PMM_SECTION_SEGMENT Segment;
- Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers->
+ Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
DataSectionObject;
if (Segment->ReferenceCount != 0)
{
DPRINT1("Data segment still referenced\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
MmFreePageTablesSectionSegment(Segment);
ExFreePool(Segment);
- FileObject->SectionObjectPointers->DataSectionObject = NULL;
+ FileObject->SectionObjectPointer->DataSectionObject = NULL;
}
}
VOID
-MmLockSection(PSECTION_OBJECT Section)
-{
- KeWaitForSingleObject(&Section->Lock,
- UserRequest,
- KernelMode,
- FALSE,
- NULL);
-}
-
-VOID
-MmUnlockSection(PSECTION_OBJECT Section)
-{
- KeReleaseMutex(&Section->Lock, FALSE);
-}
-
-VOID
MmLockSectionSegment(PMM_SECTION_SEGMENT Segment)
{
- KeWaitForSingleObject(&Segment->Lock,
- UserRequest,
- KernelMode,
- FALSE,
- NULL);
+ ExAcquireFastMutex(&Segment->Lock);
}
VOID
MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment)
{
- KeReleaseMutex(&Segment->Lock, FALSE);
+ ExReleaseFastMutex(&Segment->Lock);
}
VOID
PSECTION_PAGE_TABLE Table;
ULONG DirectoryOffset;
ULONG TableOffset;
-
- DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
- Table = Segment->PageDirectory.PageTables[DirectoryOffset];
- if (Table == NULL)
+
+ if (Segment->Length <= NR_SECTION_PAGE_TABLES * PAGE_SIZE)
+ {
+ Table = (PSECTION_PAGE_TABLE)&Segment->PageDirectory;
+ }
+ else
{
- Table =
- Segment->PageDirectory.PageTables[DirectoryOffset] =
- ExAllocatePoolWithTag(NonPagedPool, sizeof(SECTION_PAGE_TABLE),
- TAG_SECTION_PAGE_TABLE);
- memset(Table, 0, sizeof(SECTION_PAGE_TABLE));
- DPRINT("Table %x\n", Table);
+ DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
+ Table = Segment->PageDirectory.PageTables[DirectoryOffset];
+ if (Table == NULL)
+ {
+ Table =
+ Segment->PageDirectory.PageTables[DirectoryOffset] =
+ ExAllocatePoolWithTag(NonPagedPool, sizeof(SECTION_PAGE_TABLE),
+ TAG_SECTION_PAGE_TABLE);
+ if (Table == NULL)
+ {
+ KEBUGCHECK(0);
+ }
+ memset(Table, 0, sizeof(SECTION_PAGE_TABLE));
+ DPRINT("Table %x\n", Table);
+ }
}
TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
Table->Entry[TableOffset] = Entry;
DPRINT("MmGetPageEntrySection(Offset %x)\n", Offset);
- DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
- Table = Segment->PageDirectory.PageTables[DirectoryOffset];
- DPRINT("Table %x\n", Table);
- if (Table == NULL)
+ if (Segment->Length <= NR_SECTION_PAGE_TABLES * PAGE_SIZE)
+ {
+ Table = (PSECTION_PAGE_TABLE)&Segment->PageDirectory;
+ }
+ else
{
- return(0);
+ DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
+ Table = Segment->PageDirectory.PageTables[DirectoryOffset];
+ DPRINT("Table %x\n", Table);
+ if (Table == NULL)
+ {
+ return(0);
+ }
}
TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
Entry = Table->Entry[TableOffset];
if (Entry == 0)
{
DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
if (SHARE_COUNT_FROM_SSE(Entry) == MAX_SHARE_COUNT)
{
DPRINT1("Maximum share count reached\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
if (IS_SWAP_FROM_SSE(Entry))
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) + 1);
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
BOOLEAN
MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
PMM_SECTION_SEGMENT Segment,
- ULONG Offset,
+ ULONG Offset,
BOOLEAN Dirty)
{
ULONG Entry;
if (Entry == 0)
{
DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
if (SHARE_COUNT_FROM_SSE(Entry) == 0)
{
DPRINT1("Zero share count for unshare\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
if (IS_SWAP_FROM_SSE(Entry))
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) - 1);
/*
if (SHARE_COUNT_FROM_SSE(Entry) == 0)
{
PFILE_OBJECT FileObject;
- PREACTOS_COMMON_FCB_HEADER Fcb;
+ PBCB Bcb;
SWAPENTRY SavedSwapEntry;
PHYSICAL_ADDRESS Page;
-
- MmSetPageEntrySectionSegment(Segment, Offset, 0);
+ BOOLEAN IsImageSection;
+ ULONG FileOffset;
+
+ FileOffset = Offset + Segment->FileOffset;
+
+ IsImageSection = Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+
+ Page = (PHYSICAL_ADDRESS)(LONGLONG)PAGE_FROM_SSE(Entry);
FileObject = Section->FileObject;
if (FileObject != NULL)
{
- Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
-
+
if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
- (Offset % PAGE_SIZE) == 0)
+ (FileOffset % PAGE_SIZE) == 0 &&
+ (Offset + PAGE_SIZE <= Segment->RawLength || !IsImageSection))
{
NTSTATUS Status;
- Status = CcRosUnmapCacheSegment(Fcb->Bcb, Offset, Dirty);
+ Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+ Status = CcRosUnmapCacheSegment(Bcb, FileOffset, Dirty);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(0);
+ DPRINT1("CcRosUnmapCacheSegment failed, status = %x\n", Status);
+ KEBUGCHECK(0);
}
}
}
- Page = (PHYSICAL_ADDRESS)(LONGLONG)PAGE_FROM_SSE(Entry);
SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
- if (SavedSwapEntry != 0)
+ if (SavedSwapEntry == 0)
+ {
+ if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ /*
+ * FIXME:
+ * Try to page out this page and set the swap entry
+ * within the section segment. There exist no rmap entry
+ * for this page. The pager thread can't page out a
+ * page without a rmap entry.
+ */
+ MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ MmReferencePage(Page);
+ }
+ else
+ {
+ MmSetPageEntrySectionSegment(Segment, Offset, 0);
+ }
+ }
+ else
{
- MmFreeSwapPage(SavedSwapEntry);
MmSetSavedSwapEntryPage(Page, 0);
+ if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
+ }
+ else
+ {
+ MmSetPageEntrySectionSegment(Segment, Offset, 0);
+ MmFreeSwapPage(SavedSwapEntry);
+ }
}
}
else
{
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
}
- return(SHARE_COUNT_FROM_SSE(Entry) > 1);
+ return(SHARE_COUNT_FROM_SSE(Entry) > 0);
+}
+
+BOOL MiIsPageFromCache(PMEMORY_AREA MemoryArea,
+ ULONG SegOffset)
+{
+ PBCB Bcb;
+ PCACHE_SEGMENT CacheSeg;
+
+ Bcb = MemoryArea->Data.SectionData.Section->FileObject->SectionObjectPointer->SharedCacheMap;
+ CacheSeg = CcRosLookupCacheSegment(Bcb, SegOffset + MemoryArea->Data.SectionData.Segment->FileOffset);
+ if (CacheSeg)
+ {
+ CcRosReleaseCacheSegment(Bcb, CacheSeg, CacheSeg->Valid, FALSE, TRUE);
+ return TRUE;
+ }
+ return FALSE;
}
NTSTATUS
MiReadPage(PMEMORY_AREA MemoryArea,
- PLARGE_INTEGER Offset,
+ ULONG SegOffset,
PHYSICAL_ADDRESS* Page)
/*
* FUNCTION: Read a page for a section backed memory area.
*/
{
ULONG BaseOffset;
+ ULONG FileOffset;
PVOID BaseAddress;
BOOLEAN UptoDate;
PCACHE_SEGMENT CacheSeg;
PFILE_OBJECT FileObject;
NTSTATUS Status;
- PREACTOS_COMMON_FCB_HEADER Fcb;
-
+ ULONG RawLength;
+ PBCB Bcb;
+ BOOLEAN IsImageSection;
+ ULONG Length;
+
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
- Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
+ Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+ RawLength = MemoryArea->Data.SectionData.Segment->RawLength;
+ FileOffset = SegOffset + MemoryArea->Data.SectionData.Segment->FileOffset;
+ IsImageSection = MemoryArea->Data.SectionData.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
- assert(Fcb->Bcb);
+ assert(Bcb);
+
+ DPRINT("%S %x\n", FileObject->FileName.Buffer, FileOffset);
/*
* If the file system is letting us go directly to the cache and the
* then get the related cache segment.
*/
if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
- (Offset->QuadPart % PAGE_SIZE) == 0)
+ (FileOffset % PAGE_SIZE) == 0 &&
+ (SegOffset + PAGE_SIZE <= RawLength || !IsImageSection))
{
PHYSICAL_ADDRESS Addr;
* filesystems do because it is safe for us to use an offset with a
* alignment less than the file system block size.
*/
- Status = CcRosGetCacheSegment(Fcb->Bcb,
- Offset->u.LowPart,
- &BaseOffset,
- &BaseAddress,
- &UptoDate,
- &CacheSeg);
+ Status = CcRosGetCacheSegment(Bcb,
+ FileOffset,
+ &BaseOffset,
+ &BaseAddress,
+ &UptoDate,
+ &CacheSeg);
if (!NT_SUCCESS(Status))
{
return(Status);
Status = ReadCacheSegment(CacheSeg);
if (!NT_SUCCESS(Status))
{
- CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, FALSE, FALSE, FALSE);
+ CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
return Status;
}
}
* Retrieve the page from the cache segment that we actually want.
*/
Addr = MmGetPhysicalAddress(BaseAddress +
- Offset->u.LowPart - BaseOffset);
+ FileOffset - BaseOffset);
(*Page) = Addr;
MmReferencePage((*Page));
- CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE, FALSE, TRUE);
+ CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, TRUE);
}
else
{
PVOID PageAddr;
- ULONG OffsetInPage;
+ ULONG CacheSegOffset;
/*
* Allocate a page, this is rather complicated by the possibility
* we might have to move other things out of memory
{
return(Status);
}
-
- Status = CcRosGetCacheSegment(Fcb->Bcb,
- Offset->u.LowPart,
- &BaseOffset,
- &BaseAddress,
- &UptoDate,
- &CacheSeg);
+ Status = CcRosGetCacheSegment(Bcb,
+ FileOffset,
+ &BaseOffset,
+ &BaseAddress,
+ &UptoDate,
+ &CacheSeg);
if (!NT_SUCCESS(Status))
{
return(Status);
Status = ReadCacheSegment(CacheSeg);
if (!NT_SUCCESS(Status))
{
- CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, FALSE, FALSE, FALSE);
+ CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
return Status;
}
}
PageAddr = ExAllocatePageWithPhysPage(*Page);
- OffsetInPage = BaseOffset + CacheSeg->Bcb->CacheSegmentSize - Offset->u.LowPart;
- if (OffsetInPage >= PAGE_SIZE)
+ CacheSegOffset = BaseOffset + CacheSeg->Bcb->CacheSegmentSize - FileOffset;
+ Length = RawLength - SegOffset;
+ if (Length <= CacheSegOffset && Length <= PAGE_SIZE)
+ {
+ memcpy(PageAddr, BaseAddress + FileOffset - BaseOffset, Length);
+ }
+ else if (CacheSegOffset >= PAGE_SIZE)
{
- memcpy(PageAddr, BaseAddress + Offset->u.LowPart - BaseOffset, PAGE_SIZE);
+ memcpy(PageAddr, BaseAddress + FileOffset - BaseOffset, PAGE_SIZE);
}
else
{
- memcpy(PageAddr, BaseAddress + Offset->u.LowPart - BaseOffset, OffsetInPage);
- CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE, FALSE, FALSE);
- Status = CcRosGetCacheSegment(Fcb->Bcb,
- Offset->u.LowPart + OffsetInPage,
- &BaseOffset,
- &BaseAddress,
- &UptoDate,
- &CacheSeg);
+ memcpy(PageAddr, BaseAddress + FileOffset - BaseOffset, CacheSegOffset);
+ CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
+ Status = CcRosGetCacheSegment(Bcb,
+ FileOffset + CacheSegOffset,
+ &BaseOffset,
+ &BaseAddress,
+ &UptoDate,
+ &CacheSeg);
if (!NT_SUCCESS(Status))
{
ExUnmapPage(PageAddr);
Status = ReadCacheSegment(CacheSeg);
if (!NT_SUCCESS(Status))
{
- CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, FALSE, FALSE, FALSE);
- ExUnmapPage(PageAddr);
+ CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
+ ExUnmapPage(PageAddr);
return Status;
}
}
- memcpy(PageAddr + OffsetInPage, BaseAddress, PAGE_SIZE - OffsetInPage);
+ if (Length < PAGE_SIZE)
+ {
+ memcpy(PageAddr + CacheSegOffset, BaseAddress, Length - CacheSegOffset);
+ }
+ else
+ {
+ memcpy(PageAddr + CacheSegOffset, BaseAddress, PAGE_SIZE - CacheSegOffset);
+ }
}
- CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE, FALSE, FALSE);
+ CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
ExUnmapPage(PageAddr);
}
return(STATUS_SUCCESS);
PVOID Address,
BOOLEAN Locked)
{
- LARGE_INTEGER Offset;
+ ULONG Offset;
LARGE_INTEGER Page;
NTSTATUS Status;
ULONG PAddress;
ULONG Attributes;
PMM_PAGEOP PageOp;
PMM_REGION Region;
+ LARGE_INTEGER Timeout;
/*
* 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.
*/
- if (MmIsPagePresent(NULL, Address))
+ if (MmIsPagePresent(AddressSpace->Process, Address))
{
if (Locked)
{
- MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+ MmLockPage(MmGetPhysicalAddressForProcess(AddressSpace->Process, Address));
}
return(STATUS_SUCCESS);
}
PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
- Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
- MemoryArea->Data.SectionData.ViewOffset;
+ Offset = PAddress - (ULONG)MemoryArea->BaseAddress;
- /*
- * Lock the segment
- */
Segment = MemoryArea->Data.SectionData.Segment;
Section = MemoryArea->Data.SectionData.Section;
Region = MmFindRegion(MemoryArea->BaseAddress,
&MemoryArea->Data.SectionData.RegionListHead,
Address, NULL);
- MmLockSection(Section);
+ /*
+ * Lock the segment
+ */
MmLockSectionSegment(Segment);
/*
(Region->Protect == PAGE_READWRITE ||
Region->Protect == PAGE_EXECUTE_READWRITE))
{
- Attributes = PAGE_READONLY;
+ Attributes = Region->Protect == PAGE_READWRITE ? PAGE_READONLY : PAGE_EXECUTE_READ;
}
else
{
/*
* Get or create a page operation descriptor
*/
- PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart,
- MM_PAGEOP_PAGEIN);
+ PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset, MM_PAGEOP_PAGEIN);
if (PageOp == NULL)
{
DPRINT1("MmGetPageOp failed\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
/*
if (PageOp->Thread != PsGetCurrentThread())
{
MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
+ Timeout.QuadPart = -100000000LL; // 10 sec
Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
0,
KernelMode,
FALSE,
- NULL);
+ &Timeout);
+
/*
* Check for various strange conditions
*/
if (Status != STATUS_SUCCESS)
{
- DPRINT1("Failed to wait for page op\n");
- KeBugCheck(0);
+ DPRINT1("Failed to wait for page op, status = %x\n", Status);
+ KEBUGCHECK(0);
}
if (PageOp->Status == STATUS_PENDING)
{
DPRINT1("Woke for page op before completion\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
+ MmLockAddressSpace(AddressSpace);
/*
* If this wasn't a pagein then restart the operation
*/
if (PageOp->OpType != MM_PAGEOP_PAGEIN)
{
- MmLockAddressSpace(AddressSpace);
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_MM_RESTART_OPERATION);
}
+
/*
* If the thread handling this fault has failed then we don't retry
*/
if (!NT_SUCCESS(PageOp->Status))
{
- MmLockAddressSpace(AddressSpace);
Status = PageOp->Status;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address);
return(Status);
}
- 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))
+ if (!MmIsPagePresent(AddressSpace->Process, Address))
{
- Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
+ Entry = MmGetPageEntrySectionSegment(Segment, Offset);
if (Entry == 0)
{
- MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
+ MmUnlockSectionSegment(Segment);
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
return(STATUS_MM_RESTART_OPERATION);
Page = (LARGE_INTEGER)(LONGLONG)(PAGE_FROM_SSE(Entry));
MmReferencePage(Page);
- MmSharePageEntrySectionSegment(Segment, Offset.u.LowPart);
+ MmSharePageEntrySectionSegment(Segment, Offset);
Status = MmCreateVirtualMapping(MemoryArea->Process,
Address,
- MemoryArea->Attributes,
+ Attributes,
Page,
FALSE);
+ if (Status == STATUS_NO_MEMORY)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ Status = MmCreateVirtualMapping(MemoryArea->Process,
+ Address,
+ Attributes,
+ Page,
+ TRUE);
+ MmLockAddressSpace(AddressSpace);
+ }
+
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
- MmInsertRmap(Page, MemoryArea->Process,
- (PVOID)PAGE_ROUND_DOWN(Address));
+ MmInsertRmap(Page, MemoryArea->Process, (PVOID)PAddress);
}
if (Locked)
{
- MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+ MmLockPage(Page);
}
MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
/*
* Must be private page we have swapped out.
*/
- if (MmIsPageSwapEntry(NULL, (PVOID)PAddress))
+ if (MmIsPageSwapEntry(AddressSpace->Process, (PVOID)PAddress))
{
SWAPENTRY SwapEntry;
PMDL Mdl;
+ /*
+ * Sanity check
+ */
+ if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ DPRINT1("Found a swaped out private page in a pagefile section.\n");
+ KEBUGCHECK(0);
+ }
+
MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
-
- MmDeletePageFileMapping(NULL, (PVOID)PAddress, &SwapEntry);
+ MmDeletePageFileMapping(AddressSpace->Process, (PVOID)PAddress, &SwapEntry);
+ MmUnlockAddressSpace(AddressSpace);
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
Status = MmReadFromSwapPage(SwapEntry, Mdl);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(0);
+ DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
+ KEBUGCHECK(0);
}
-
+ MmLockAddressSpace(AddressSpace);
Status = MmCreateVirtualMapping(AddressSpace->Process,
Address,
Region->Protect,
Page,
FALSE);
- while (Status == STATUS_NO_MEMORY)
+ if (Status == STATUS_NO_MEMORY)
{
MmUnlockAddressSpace(AddressSpace);
Status = MmCreateVirtualMapping(AddressSpace->Process,
}
if (!NT_SUCCESS(Status))
{
- DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
- KeBugCheck(0);
+ DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+ KEBUGCHECK(0);
return(Status);
}
/*
* Add the page to the process's working set
*/
- MmInsertRmap(Page, AddressSpace->Process,
- (PVOID)PAGE_ROUND_DOWN(Address));
+ MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
/*
* Finish the operation
*/
if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
{
+ MmUnlockSectionSegment(Segment);
/*
* Just map the desired physical page
*/
+ Page.QuadPart = Offset + MemoryArea->Data.SectionData.ViewOffset;
Status = MmCreateVirtualMapping(AddressSpace->Process,
Address,
Region->Protect,
- Offset,
+ Page,
FALSE);
+ if (Status == STATUS_NO_MEMORY)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
+ Address,
+ Region->Protect,
+ Page,
+ TRUE);
+ MmLockAddressSpace(AddressSpace);
+ }
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+ KEBUGCHECK(0);
+ return(Status);
+ }
/*
* Don't add an rmap entry since the page mapped could be for
* anything.
*/
if (Locked)
{
- MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+ MmLockPage(Page);
}
/*
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
- MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
*/
if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS)
{
+ MmUnlockSectionSegment(Segment);
Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
if (!NT_SUCCESS(Status))
{
- MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
- MmUnlockAddressSpace(AddressSpace);
- MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
- MmLockAddressSpace(AddressSpace);
- MmLockSection(Section);
- MmLockSectionSegment(Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
+ MmLockAddressSpace(AddressSpace);
}
-
+ if (!NT_SUCCESS(Status))
+ {
+ KEBUGCHECK(0);
+ }
Status = MmCreateVirtualMapping(AddressSpace->Process,
Address,
Region->Protect,
Page,
FALSE);
- MmInsertRmap(Page, AddressSpace->Process,
- (PVOID)PAGE_ROUND_DOWN(Address));
+ if (Status == STATUS_NO_MEMORY)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
+ Address,
+ Region->Protect,
+ Page,
+ TRUE);
+ MmLockAddressSpace(AddressSpace);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+ KEBUGCHECK(0);
+ return(Status);
+ }
+ MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
if (Locked)
{
- MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+ MmLockPage(Page);
}
/*
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
- MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
/*
* Get the entry corresponding to the offset within the section
*/
- Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
+ Entry = MmGetPageEntrySectionSegment(Segment, Offset);
if (Entry == 0)
{
* If the entry is zero (and it can't change because we have
* locked the segment) then we need to load the page.
*/
-
+
/*
* Release all our locks and read in the page from disk
*/
MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
-
- if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+
+ if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
+ (Offset >= PAGE_ROUND_UP(Segment->RawLength) && Section->AllocationAttributes & SEC_IMAGE))
{
- Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
+ Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status);
+ }
}
else
- {
- Status = MiReadPage(MemoryArea, &Offset, &Page);
+ {
+ Status = MiReadPage(MemoryArea, Offset, &Page);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MiReadPage failed (Status %x)\n", Status);
+ }
}
- if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
+ if (!NT_SUCCESS(Status))
{
/*
* FIXME: What do we know in this case?
*/
- DPRINT1("IoPageRead failed (Status %x)\n", Status);
-
/*
* Cleanup and release locks
*/
+ MmLockAddressSpace(AddressSpace);
PageOp->Status = Status;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
- MmLockAddressSpace(AddressSpace);
+ DPRINT("Address 0x%.8X\n", Address);
return(Status);
}
-
/*
- * Relock the address space, section and segment
+ * Relock the address space and segment
*/
MmLockAddressSpace(AddressSpace);
- MmLockSection(Section);
MmLockSectionSegment(Segment);
/*
* Check the entry. No one should change the status of a page
* that has a pending page-in.
*/
- Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
+ Entry1 = MmGetPageEntrySectionSegment(Segment, Offset);
if (Entry != Entry1)
{
DbgPrint("Someone changed ppte entry while we slept\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
/*
* Mark the offset within the section as having valid, in-memory
* data
*/
- Entry = Page.u.LowPart;
- MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
- MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
-
+ Entry = MAKE_SSE(Page.u.LowPart, 1);
+ MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ MmUnlockSectionSegment(Segment);
+
Status = MmCreateVirtualMapping(AddressSpace->Process,
Address,
Attributes,
Page,
FALSE);
+ if (Status == STATUS_NO_MEMORY)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
+ Address,
+ Attributes,
+ Page,
+ TRUE);
+ MmLockAddressSpace(AddressSpace);
+ }
if (!NT_SUCCESS(Status))
- {
- MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
- MmUnlockAddressSpace(AddressSpace);
- Status = MmCreateVirtualMapping(AddressSpace->Process,
- Address,
- Attributes,
- Page,
- TRUE);
- if (!NT_SUCCESS(Status))
- {
- KeBugCheck(0);
- }
- MmLockAddressSpace(AddressSpace);
- MmLockSection(Section);
- MmLockSectionSegment(Segment);
- }
- MmInsertRmap(Page, AddressSpace->Process,
- (PVOID)PAGE_ROUND_DOWN(Address));
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("Unable to create virtual mapping\n");
- KeBugCheck(0);
- }
+ {
+ DbgPrint("Unable to create virtual mapping\n");
+ KEBUGCHECK(0);
+ }
+ MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
+
if (Locked)
{
- MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+ MmLockPage(Page);
}
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
- MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
- DPRINT("MmNotPresentFaultSectionView succeeded\n");
+ DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
else if (IS_SWAP_FROM_SSE(Entry))
* Release all our locks and read in the page from disk
*/
MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
+
MmUnlockAddressSpace(AddressSpace);
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
Status = MmReadFromSwapPage(SwapEntry, Mdl);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
/*
- * Relock the address space, section and segment
+ * Relock the address space and segment
*/
MmLockAddressSpace(AddressSpace);
- MmLockSection(Section);
MmLockSectionSegment(Segment);
/*
* Check the entry. No one should change the status of a page
* that has a pending page-in.
*/
- Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
+ Entry1 = MmGetPageEntrySectionSegment(Segment, Offset);
if (Entry != Entry1)
{
DbgPrint("Someone changed ppte entry while we slept\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
/*
* Mark the offset within the section as having valid, in-memory
* data
*/
- Entry = Page.u.LowPart;
- MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
- MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
+ Entry = MAKE_SSE(Page.u.LowPart, 1);
+ MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ MmUnlockSectionSegment(Segment);
/*
* Save the swap entry.
*/
MmSetSavedSwapEntryPage(Page, SwapEntry);
-
Status = MmCreateVirtualMapping(AddressSpace->Process,
Address,
- Attributes,
+ Region->Protect,
Page,
FALSE);
- MmInsertRmap(Page, AddressSpace->Process,
- (PVOID)PAGE_ROUND_DOWN(Address));
+ if (Status == STATUS_NO_MEMORY)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
+ Address,
+ Region->Protect,
+ Page,
+ TRUE);
+ MmLockAddressSpace(AddressSpace);
+ }
if (!NT_SUCCESS(Status))
- {
- DbgPrint("Unable to create virtual mapping\n");
- KeBugCheck(0);
- }
+ {
+ DbgPrint("Unable to create virtual mapping\n");
+ KEBUGCHECK(0);
+ }
+ MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
if (Locked)
{
- MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+ MmLockPage(Page);
}
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
- MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
- DPRINT("MmNotPresentFaultSectionView succeeded\n");
+ DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
else
{
- /*
- * If the section offset is already in-memory and valid then just
- * take another reference to the page
- */
-
- Page = (LARGE_INTEGER)(LONGLONG)PAGE_FROM_SSE(Entry);
- MmReferencePage(Page);
- MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
+ /*
+ * If the section offset is already in-memory and valid then just
+ * take another reference to the page
+ */
- Status = MmCreateVirtualMapping(AddressSpace->Process,
- Address,
- Attributes,
- Page,
- FALSE);
- MmInsertRmap(Page, AddressSpace->Process,
- (PVOID)PAGE_ROUND_DOWN(Address));
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("Unable to create virtual mapping\n");
- KeBugCheck(0);
- }
+ Page = (LARGE_INTEGER)(LONGLONG)PAGE_FROM_SSE(Entry);
+ MmReferencePage(Page);
+ MmSharePageEntrySectionSegment(Segment, Offset);
+ MmUnlockSectionSegment(Segment);
+
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
+ Address,
+ Attributes,
+ Page,
+ FALSE);
+ if (Status == STATUS_NO_MEMORY)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
+ Address,
+ Attributes,
+ Page,
+ TRUE);
+ MmLockAddressSpace(AddressSpace);
+ }
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("Unable to create virtual mapping\n");
+ KEBUGCHECK(0);
+ }
+ MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
if (Locked)
- {
- MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
- }
+ {
+ MmLockPage(Page);
+ }
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
- MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
+ DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
}
PVOID NewAddress;
NTSTATUS Status;
ULONG PAddress;
- LARGE_INTEGER Offset;
+ ULONG Offset;
PMM_PAGEOP PageOp;
PMM_REGION Region;
+ LARGE_INTEGER Timeout;
/*
* Check if the page has been paged out or has already been set readwrite
*/
- if (!MmIsPagePresent(NULL, Address) ||
- MmGetPageProtect(NULL, Address) & PAGE_READWRITE)
+ if (!MmIsPagePresent(AddressSpace->Process, Address) ||
+ MmGetPageProtect(AddressSpace->Process, Address) & PAGE_READWRITE)
{
- return(STATUS_SUCCESS);
+ DPRINT("Address 0x%.8X\n", Address);
+ return(STATUS_SUCCESS);
}
/*
* Find the offset of the page
*/
PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
- Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
- MemoryArea->Data.SectionData.ViewOffset;
+ Offset = PAddress - (ULONG)MemoryArea->BaseAddress;
- /*
- * Lock the segment
- */
Segment = MemoryArea->Data.SectionData.Segment;
Section = MemoryArea->Data.SectionData.Section;
Region = MmFindRegion(MemoryArea->BaseAddress,
&MemoryArea->Data.SectionData.RegionListHead,
Address, NULL);
- MmLockSection(Section);
+ /*
+ * Lock the segment
+ */
MmLockSectionSegment(Segment);
/*
* Sanity check.
*/
- if (MmGetPageEntrySectionSegment(Segment, Offset.QuadPart) == 0)
+ if (MmGetPageEntrySectionSegment(Segment, Offset) == 0)
{
DPRINT1("COW fault for page with PESS 0. Address was 0x%.8X\n",
Address);
}
-
+ MmUnlockSectionSegment(Segment);
/*
* Check if we are doing COW
*/
(Region->Protect == PAGE_READWRITE ||
Region->Protect == PAGE_EXECUTE_READWRITE)))
{
- MmUnlockSection(Section);
- MmUnlockSectionSegment(Segment);
+ DPRINT("Address 0x%.8X\n", Address);
return(STATUS_UNSUCCESSFUL);
}
/*
* Get or create a pageop
*/
- PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart,
+ PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset,
MM_PAGEOP_ACCESSFAULT);
if (PageOp == NULL)
{
DPRINT1("MmGetPageOp failed\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
/*
*/
if (PageOp->Thread != PsGetCurrentThread())
{
- MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
+ Timeout.QuadPart = -100000000LL; // 10 sec
Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
0,
KernelMode,
FALSE,
- NULL);
+ &Timeout);
/*
* Check for various strange conditions
*/
- if (Status != STATUS_SUCCESS)
+ if (Status == STATUS_TIMEOUT)
{
- DPRINT1("Failed to wait for page op\n");
- KeBugCheck(0);
+ DPRINT1("Failed to wait for page op, status = %x\n", Status);
+ KEBUGCHECK(0);
}
if (PageOp->Status == STATUS_PENDING)
{
DPRINT1("Woke for page op before completion\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
/*
* Restart the operation
MmLockAddressSpace(AddressSpace);
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
+ DPRINT("Address 0x%.8X\n", Address);
return(STATUS_MM_RESTART_OPERATION);
}
/*
* Release locks now we have the pageop
*/
- MmUnlockSectionSegment(Segment);
- MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
/*
* Allocate a page
*/
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage);
+ if (!NT_SUCCESS(Status))
+ {
+ KEBUGCHECK(0);
+ }
/*
* Copy the old page
OldPage = MmGetPhysicalAddressForProcess(NULL, Address);
NewAddress = ExAllocatePageWithPhysPage(NewPage);
- memcpy(NewAddress, (PVOID)PAGE_ROUND_DOWN(Address), PAGE_SIZE);
+ memcpy(NewAddress, (PVOID)PAddress, PAGE_SIZE);
ExUnmapPage(NewAddress);
/*
Region->Protect,
NewPage,
FALSE);
- MmInsertRmap(NewPage, AddressSpace->Process,
- (PVOID)PAGE_ROUND_DOWN(Address));
+ if (Status == STATUS_NO_MEMORY)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ Status = MmCreateVirtualMapping(AddressSpace->Process,
+ Address,
+ Region->Protect,
+ NewPage,
+ TRUE);
+ MmLockAddressSpace(AddressSpace);
+ }
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+ KEBUGCHECK(0);
+ return(Status);
+ }
+ MmInsertRmap(NewPage, AddressSpace->Process, (PVOID)PAddress);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
if (Locked)
{
- MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
+ MmLockPage(NewPage);
}
/*
* Unshare the old page.
*/
- MmUnsharePageEntrySectionSegment(Section, Segment, Offset.QuadPart, FALSE);
- MmDeleteRmap(OldPage, AddressSpace->Process,
- (PVOID)PAGE_ROUND_DOWN(Address));
+ MmDeleteRmap(OldPage, AddressSpace->Process, (PVOID)PAddress);
+ MmLockSectionSegment(Segment);
+ MmUnsharePageEntrySectionSegment(Section, Segment, Offset, FALSE);
+ MmUnlockSectionSegment(Segment);
MmReleasePageMemoryConsumer(MC_USER, OldPage);
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
+ DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
{
MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
BOOL WasDirty;
- PHYSICAL_ADDRESS PhysicalAddress;
+ PHYSICAL_ADDRESS Page;
PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
MmDeleteVirtualMapping(Process,
Address,
FALSE,
&WasDirty,
- &PhysicalAddress);
+ &Page);
if (WasDirty)
{
PageOutContext->WasDirty = TRUE;
{
MmUnsharePageEntrySectionSegment(PageOutContext->Section,
PageOutContext->Segment,
- PageOutContext->Offset.u.LowPart,
+ PageOutContext->Offset,
PageOutContext->WasDirty);
}
- MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ DPRINT("PhysicalAddress %I64x, Address %x\n", Page, Address);
}
NTSTATUS
PVOID Address,
PMM_PAGEOP PageOp)
{
- LARGE_INTEGER Offset;
- PSECTION_OBJECT Section;
- PMM_SECTION_SEGMENT Segment;
PHYSICAL_ADDRESS PhysicalAddress;
MM_SECTION_PAGEOUT_CONTEXT Context;
SWAPENTRY SwapEntry;
PMDL Mdl;
ULONG Entry;
- BOOLEAN Private;
+ ULONG FileOffset;
NTSTATUS Status;
PFILE_OBJECT FileObject;
- PREACTOS_COMMON_FCB_HEADER Fcb;
+ PBCB Bcb = NULL;
BOOLEAN DirectMapped;
+ BOOLEAN IsImageSection;
Address = (PVOID)PAGE_ROUND_DOWN(Address);
- Offset.QuadPart = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) +
- MemoryArea->Data.SectionData.ViewOffset;
+ /*
+ * Get the segment and section.
+ */
+ Context.Segment = MemoryArea->Data.SectionData.Segment;
+ Context.Section = MemoryArea->Data.SectionData.Section;
- FileObject = MemoryArea->Data.SectionData.Section->FileObject;
+ Context.Offset = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress);
+ FileOffset = Context.Offset + Context.Segment->FileOffset;
+
+ IsImageSection = Context.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+
+ FileObject = Context.Section->FileObject;
DirectMapped = FALSE;
if (FileObject != NULL)
{
- Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
+ Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
/*
* If the file system is letting us go directly to the cache and the
* then note this is a direct mapped page.
*/
if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
- (Offset.QuadPart % PAGE_SIZE) == 0)
+ (FileOffset % PAGE_SIZE) == 0 &&
+ (Context.Offset + PAGE_SIZE <= Context.Segment->RawLength || !IsImageSection))
{
DirectMapped = TRUE;
}
}
- /*
- * Get the segment and section.
- */
- Segment = MemoryArea->Data.SectionData.Segment;
- Section = MemoryArea->Data.SectionData.Section;
/*
* This should never happen since mappings of physical memory are never
* placed in the rmap lists.
*/
- if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
+ if (Context.Section->AllocationAttributes & SEC_PHYSICALMEMORY)
{
DPRINT1("Trying to page out from physical memory section address 0x%X "
- "process %d\n", Address, AddressSpace->Process->UniqueProcessId);
- KeBugCheck(0);
+ "process %d\n", Address,
+ AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0);
+ KEBUGCHECK(0);
}
/*
* Get the section segment entry and the physical address.
*/
- Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
+ Entry = MmGetPageEntrySectionSegment(Context.Segment, Context.Offset);
if (!MmIsPagePresent(AddressSpace->Process, Address))
{
DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
- AddressSpace->Process->UniqueProcessId, Address);
- KeBugCheck(0);
+ AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0, Address);
+ KEBUGCHECK(0);
}
PhysicalAddress =
MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
/*
* Prepare the context structure for the rmap delete call.
*/
- Context.Section = Section;
- Context.Segment = Segment;
- Context.Offset = Offset;
Context.WasDirty = FALSE;
- if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS ||
+ if (Context.Segment->Characteristics & IMAGE_SECTION_CHAR_BSS ||
IS_SWAP_FROM_SSE(Entry) ||
(LONGLONG)PAGE_FROM_SSE(Entry) != PhysicalAddress.QuadPart)
{
- Context.Private = Private = TRUE;
+ Context.Private = TRUE;
}
else
{
- Context.Private = Private = FALSE;
+ Context.Private = FALSE;
}
/*
- * Take an additional reference to the page.
- */
-// MmReferencePage(PhysicalAddress);
-
- /*
* Paging out data mapped read-only is easy.
*/
- if (MemoryArea->Attributes & PAGE_READONLY ||
- MemoryArea->Attributes & PAGE_EXECUTE_READ)
+ if (Context.Segment->Protection & (PAGE_READONLY|PAGE_EXECUTE_READ))
{
/*
* Read-only data should never be in the swapfile.
DPRINT1("SwapEntry != 0 was 0x%.8X at address 0x%.8X, "
"paddress 0x%.8X\n", SwapEntry, Address,
PhysicalAddress);
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
/*
* Read-only data should never be COWed
*/
- if (Private)
+ if (Context.Private)
{
DPRINT1("Had private copy of read-only page.\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
/*
MmPageOutDeleteMapping);
if (Context.WasDirty)
{
- KeBugCheck(0);
- }
- /*
- * If this page wasn't direct mapped then we have a private copy so
- * release back to the system; otherwise the cache manager will have
- * handled freeing the cache segment which we mapped from.
- */
- if (!DirectMapped)
- {
- MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+ DPRINT1("Had a dirty page of a read-only page.\n");
+ KEBUGCHECK(0);
}
-
+
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
/*
* Otherwise we have read-write data.
*/
+
+ /*
+ * Take an additional reference to the page or the cache segment.
+ */
+ if (DirectMapped && !Context.Private)
+ {
+ if(!MiIsPageFromCache(MemoryArea, Context.Offset))
+ {
+ DPRINT1("Direct mapped non private page is not associated with the cache.\n")
+ KEBUGCHECK(0);
+ }
+ }
+ else
+ {
+ MmReferencePage(PhysicalAddress);
+ }
+
MmDeleteAllRmaps(PhysicalAddress, (PVOID)&Context, MmPageOutDeleteMapping);
/*
* If this wasn't a private page then we should have reduced the entry to
* zero by deleting all the rmaps.
*/
- if (!Private && MmGetPageEntrySectionSegment(Segment, Offset.QuadPart) != 0)
+ if (!Context.Private && MmGetPageEntrySectionSegment(Context.Segment, Context.Offset) != 0)
{
- KeBugCheck(0);
+ if (!(Context.Segment->Flags & MM_PAGEFILE_SEGMENT))
+ {
+ CHECKPOINT1;
+ KEBUGCHECK(0);
+ }
}
/*
* If the page wasn't dirty then we can just free it as for a readonly page.
* Since we unmapped all the mappings above we know it will not suddenly
- * become dirty.
+ * become dirty.
+ * If the page is from a pagefile section and has no swap entry,
+ * we can't free the page at this point.
*/
- if (!Context.WasDirty)
+ SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
+ if (!Context.WasDirty &&
+ !(SwapEntry == 0 && Context.Segment->Flags & MM_PAGEFILE_SEGMENT))
+
{
- if (!DirectMapped || Private)
+ if (Context.Private)
{
MmSetSavedSwapEntryPage(PhysicalAddress, 0);
- MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
- }
- if (Private)
- {
- if (!(Segment->Characteristics & IMAGE_SECTION_CHAR_BSS) &&
+ if (!(Context.Segment->Characteristics & IMAGE_SECTION_CHAR_BSS) &&
SwapEntry == 0)
{
DPRINT1("Private page, non-dirty but not swapped out "
"process %d address 0x%.8X\n",
- AddressSpace->Process->UniqueProcessId,
+ AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0,
Address);
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
else
{
SwapEntry);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
}
}
+ if (DirectMapped && !Context.Private)
+ {
+ Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status);
+ KEBUGCHECK(0);
+ }
+ }
+ else
+ {
+ MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+ }
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
* If this page was direct mapped from the cache then the cache manager
* will already have taken care of writing it back.
*/
- if (DirectMapped && !Private)
+ if (DirectMapped && !Context.Private)
{
assert(SwapEntry == 0);
- MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
+ Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CcRosUnmapCacheSegment failed, status = %x\n", Status);
+ KEBUGCHECK(0);
+ }
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
/*
* If necessary, allocate an entry in the paging file for this page
*/
- SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
if (SwapEntry == 0)
{
SwapEntry = MmAllocSwapPage();
/*
* For private pages restore the old mappings.
*/
- if (Private)
+ if (Context.Private)
{
Status = MmCreateVirtualMapping(MemoryArea->Process,
Address,
MmInsertRmap(PhysicalAddress,
MemoryArea->Process,
Address);
- MmSetPageEntrySectionSegment(Segment, Offset.QuadPart,
- PhysicalAddress.u.LowPart);
- MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
+ Entry = MAKE_SSE(PhysicalAddress.u.LowPart, 1);
+ MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
}
- PageOp->Status = STATUS_UNSUCCESSFUL;
- KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
- MmReleasePageOp(PageOp);
- return(STATUS_UNSUCCESSFUL);
+ PageOp->Status = STATUS_UNSUCCESSFUL;
+ KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
+ MmReleasePageOp(PageOp);
+ return(STATUS_PAGEFILE_QUOTA);
}
}
* As above: undo our actions.
* FIXME: Also free the swap page.
*/
- if (Private)
+ if (Context.Private)
{
Status = MmCreateVirtualMapping(MemoryArea->Process,
Address,
MmInsertRmap(PhysicalAddress,
MemoryArea->Process,
Address);
- MmSetPageEntrySectionSegment(Segment, Offset.QuadPart,
- PhysicalAddress.u.LowPart);
- MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
+ Entry = MAKE_SSE(PhysicalAddress.u.LowPart, 1);
+ MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
}
PageOp->Status = STATUS_UNSUCCESSFUL;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmSetSavedSwapEntryPage(PhysicalAddress, 0);
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
- if (Private)
+ if (Context.Private)
{
Status = MmCreatePageFileMapping(MemoryArea->Process,
Address,
SwapEntry);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
}
else
{
Entry = MAKE_SWAP_SSE(SwapEntry);
- MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
+ MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
}
PageOp->Status = STATUS_SUCCESS;
PVOID Address,
PMM_PAGEOP PageOp)
{
- LARGE_INTEGER Offset;
+ ULONG Offset;
PSECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
PHYSICAL_ADDRESS PhysicalAddress;
BOOLEAN Private;
NTSTATUS Status;
PFILE_OBJECT FileObject;
- PREACTOS_COMMON_FCB_HEADER Fcb = NULL;
+ PBCB Bcb = NULL;
BOOLEAN DirectMapped;
+ BOOLEAN IsImageSection;
Address = (PVOID)PAGE_ROUND_DOWN(Address);
- Offset.QuadPart = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) +
- MemoryArea->Data.SectionData.ViewOffset;
+ Offset = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress);
- FileObject = MemoryArea->Data.SectionData.Section->FileObject;
+ /*
+ * Get the segment and section.
+ */
+ Segment = MemoryArea->Data.SectionData.Segment;
+ Section = MemoryArea->Data.SectionData.Section;
+ IsImageSection = Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
+
+ FileObject = Section->FileObject;
DirectMapped = FALSE;
if (FileObject != NULL)
{
- Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
+ Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
/*
* If the file system is letting us go directly to the cache and the
* then note this is a direct mapped page.
*/
if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
- (Offset.QuadPart % PAGE_SIZE) == 0)
+ (Offset + MemoryArea->Data.SectionData.ViewOffset % PAGE_SIZE) == 0 &&
+ (Offset + PAGE_SIZE <= Segment->RawLength || !IsImageSection))
{
DirectMapped = TRUE;
}
}
/*
- * Get the segment and section.
- */
- Segment = MemoryArea->Data.SectionData.Segment;
- Section = MemoryArea->Data.SectionData.Section;
-
- /*
* This should never happen since mappings of physical memory are never
* placed in the rmap lists.
*/
if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
{
DPRINT1("Trying to write back page from physical memory mapped at %X "
- "process %d\n", Address, AddressSpace->Process->UniqueProcessId);
- KeBugCheck(0);
+ "process %d\n", Address,
+ AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0);
+ KEBUGCHECK(0);
}
/*
* Get the section segment entry and the physical address.
*/
- Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
+ Entry = MmGetPageEntrySectionSegment(Segment, Offset);
if (!MmIsPagePresent(AddressSpace->Process, Address))
{
DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
- AddressSpace->Process->UniqueProcessId, Address);
- KeBugCheck(0);
+ AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0, Address);
+ KEBUGCHECK(0);
}
PhysicalAddress =
MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
if (DirectMapped && !Private)
{
assert(SwapEntry == 0);
- CcRosMarkDirtyCacheSegment(Fcb->Bcb, Offset.u.LowPart);
+ CcRosMarkDirtyCacheSegment(Bcb, Offset + MemoryArea->Data.SectionData.ViewOffset);
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
/*
* If necessary, allocate an entry in the paging file for this page
*/
- SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
if (SwapEntry == 0)
{
SwapEntry = MmAllocSwapPage();
PageOp->Status = STATUS_UNSUCCESSFUL;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
- return(STATUS_UNSUCCESSFUL);
+ return(STATUS_PAGEFILE_QUOTA);
}
}
*/
if (DoCOW && MmIsPagePresent(AddressSpace->Process, Address))
{
- LARGE_INTEGER Offset;
+ ULONG Offset;
ULONG Entry;
LARGE_INTEGER PhysicalAddress;
- Offset.QuadPart =
- (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) +
- MemoryArea->Data.SectionData.ViewOffset;
- Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
+ Offset = (ULONG)Address - (ULONG)MemoryArea->BaseAddress;
+ Entry = MmGetPageEntrySectionSegment(Segment, Offset);
PhysicalAddress =
MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
Region = MmFindRegion(MemoryArea->BaseAddress,
&MemoryArea->Data.SectionData.RegionListHead,
Address, &RegionBaseAddress);
+ if (Region == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
Info->AllocationBase = MemoryArea->BaseAddress;
Info->AllocationProtect = MemoryArea->Attributes;
if (Section->AllocationAttributes & SEC_IMAGE)
{
ULONG i;
-
- for (i = 0; i < Section->NrSegments; i++)
+ ULONG NrSegments;
+ PMM_SECTION_SEGMENT SectionSegments;
+
+ SectionSegments = Section->ImageSection->Segments;
+ NrSegments = Section->ImageSection->NrSegments;
+
+ for (i = 0; i < NrSegments; i++)
{
- InterlockedDecrement(&Section->Segments[i].ReferenceCount);
+ InterlockedDecrement((LONG *)&SectionSegments[i].ReferenceCount);
}
}
else
{
- InterlockedDecrement(&Section->Segments->ReferenceCount);
+ if (Section->Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ ULONG Offset;
+ ULONG Length;
+ ULONG Entry;
+ PMM_SECTION_SEGMENT Segment;
+
+ Segment = Section->Segment;
+ Length = PAGE_ROUND_UP(Segment->Length);
+
+ for (Offset = 0; Offset < Length; Offset += PAGE_SIZE)
+ {
+ Entry = MmGetPageEntrySectionSegment(Segment, Offset);
+ if (Entry)
+ {
+ if (IS_SWAP_FROM_SSE(Entry))
+ {
+ MmFreeSwapPage(SWAPENTRY_FROM_SSE(Entry));
+ }
+ else
+ {
+ PHYSICAL_ADDRESS Page = (PHYSICAL_ADDRESS)(LONGLONG)PAGE_FROM_SSE(Entry);
+ MmReleasePageMemoryConsumer(MC_USER, Page);
+ }
+ }
+ }
+ MmFreePageTablesSectionSegment(Section->Segment);
+ ExFreePool(Section->Segment);
+ Section->Segment = NULL;
+ }
+ else
+ {
+ InterlockedDecrement((LONG *)&Section->Segment->ReferenceCount);
+ }
}
if (Section->FileObject != NULL)
{
CcRosDereferenceCache(Section->FileObject);
ObDereferenceObject(Section->FileObject);
Section->FileObject = NULL;
- }
-
- if (Section->Segments->Flags & MM_PAGEFILE_SEGMENT)
- {
- MmFreePageTablesSectionSegment(Section->Segments);
- ExFreePool(Section->Segments);
- }
+ }
}
VOID STDCALL
{
DPRINT("MmpCloseSection(OB %x, HC %d) RC %d\n",
ObjectBody, HandleCount, ObGetObjectPointerCount(ObjectBody));
-
}
NTSTATUS STDCALL
POBJECT_ATTRIBUTES ObjectAttributes)
{
DPRINT("MmpCreateSection(ObjectBody %x, Parent %x, RemainingPath %S)\n",
- ObjectBody, Parent, RemainingPath);
+ ObjectBody, Parent, RemainingPath);
if (RemainingPath == NULL)
{
- return(STATUS_SUCCESS);
+ return(STATUS_SUCCESS);
}
if (wcschr(RemainingPath+1, L'\\') != NULL)
{
return(STATUS_UNSUCCESSFUL);
}
-
return(STATUS_SUCCESS);
}
if (!NT_SUCCESS(Status))
{
DbgPrint("Failed to create PhysicalMemory section\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
Status = ObReferenceObjectByHandle(PhysSectionH,
SECTION_ALL_ACCESS,
if (!NT_SUCCESS(Status))
{
DbgPrint("Failed to reference PhysicalMemory section\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY;
ObDereferenceObject((PVOID)PhysSection);
/*
* Create the section
*/
- Status = ObCreateObject(SectionHandle,
+ Status = ObRosCreateObject(SectionHandle,
DesiredAccess,
ObjectAttributes,
MmSectionObjectType,
Section->AllocationAttributes = AllocationAttributes;
InitializeListHead(&Section->ViewListHead);
KeInitializeSpinLock(&Section->ViewListLock);
- KeInitializeMutex(&Section->Lock, 0);
Section->FileObject = NULL;
Section->MaximumSize = MaximumSize;
Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
ObDereferenceObject(Section);
return(STATUS_NO_MEMORY);
}
- Section->Segments = Segment;
+ Section->Segment = Segment;
Segment->ReferenceCount = 1;
- KeInitializeMutex(&Segment->Lock, 0);
+ ExInitializeFastMutex(&Segment->Lock);
Segment->FileOffset = 0;
Segment->Protection = SectionPageProtection;
Segment->Attributes = AllocationAttributes;
/*
* Create the section
*/
- Status = ObCreateObject(SectionHandle,
+ Status = ObRosCreateObject(SectionHandle,
DesiredAccess,
ObjectAttributes,
MmSectionObjectType,
Section->AllocationAttributes = AllocationAttributes;
InitializeListHead(&Section->ViewListHead);
KeInitializeSpinLock(&Section->ViewListLock);
- KeInitializeMutex(&Section->Lock, 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;
/*
* Check file access required
else
{
MaximumSize =
- ((PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize;
+ ((PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize;
}
if (MaximumSize.QuadPart >
- ((PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize.QuadPart)
+ ((PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize.QuadPart)
{
IO_STATUS_BLOCK Iosb;
Status = NtSetInformationFile(FileHandle,
* 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)
+ if (FileObject->SectionObjectPointer->DataSectionObject == NULL)
{
Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
TAG_MM_SECTION_SEGMENT);
ObDereferenceObject(FileObject);
return(STATUS_NO_MEMORY);
}
- Section->Segments = Segment;
+ Section->Segment = Segment;
Segment->ReferenceCount = 1;
- KeInitializeMutex(&Segment->Lock, 0);
-
+ ExInitializeFastMutex(&Segment->Lock);
/*
* 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;
+ ExAcquireFastMutex(&Segment->Lock);
+ FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment;
Segment->FileOffset = 0;
Segment->Protection = 0;
Segment->WriteCopy = FALSE;
if (AllocationAttributes & SEC_RESERVE)
{
- Segment->Length = 0;
+ Segment->Length = Segment->RawLength = 0;
}
else
{
- Segment->Length = MaximumSize.u.LowPart;
+ Segment->RawLength = MaximumSize.u.LowPart;
+ Segment->Length = PAGE_ROUND_UP(Segment->RawLength);
}
Segment->VirtualAddress = NULL;
}
* to extend it
*/
Segment =
- (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers->
+ (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->
DataSectionObject;
- Section->Segments = Segment;
+ Section->Segment = Segment;
InterlockedIncrement((PLONG)&Segment->ReferenceCount);
- Status = KeWaitForSingleObject((PVOID)&Segment->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 &&
+ MmLockSectionSegment(Segment);
+
+ if (MaximumSize.u.LowPart > Segment->RawLength &&
!(AllocationAttributes & SEC_RESERVE))
{
- Segment->Length = MaximumSize.u.LowPart;
+ Segment->RawLength = MaximumSize.u.LowPart;
+ Segment->Length = PAGE_ROUND_UP(Segment->RawLength);
}
}
- KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
- CcRosReferenceCache(FileObject);
+ MmUnlockSectionSegment(Segment);
Section->FileObject = FileObject;
Section->MaximumSize = MaximumSize;
- KeReleaseMutex(&Segment->Lock, FALSE);
-
+ CcRosReferenceCache(FileObject);
+ KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
ObDereferenceObject(Section);
return(STATUS_SUCCESS);
}
PSECTION_OBJECT Section;
NTSTATUS Status;
PFILE_OBJECT FileObject;
- ULONG FileAccess;
IMAGE_DOS_HEADER DosHeader;
IO_STATUS_BLOCK Iosb;
LARGE_INTEGER Offset;
PMM_SECTION_SEGMENT SectionSegments;
ULONG NrSegments;
PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
-
+ ULONG i;
+ ULONG Size;
+ ULONG Characteristics;
+ ULONG FileAccess = 0;
/*
* Check the protection
*/
}
/*
- * 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
- */
- Status = ObCreateObject(SectionHandle,
- DesiredAccess,
- ObjectAttributes,
- MmSectionObjectType,
- (PVOID*)&Section);
- if (!NT_SUCCESS(Status))
- {
- ExFreePool(ImageSections);
- return(Status);
- }
-
- /*
- * Initialize it
- */
- Section->SectionPageProtection = SectionPageProtection;
- Section->AllocationAttributes = AllocationAttributes;
- InitializeListHead(&Section->ViewListHead);
- KeInitializeSpinLock(&Section->ViewListLock);
- KeInitializeMutex(&Section->Lock, 0);
- 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,
NULL);
if (!NT_SUCCESS(Status))
{
- ZwClose(*SectionHandle);
- ObDereferenceObject(Section);
- ExFreePool(ImageSections);
- return(Status);
+ return Status;
}
/*
- * We can't do memory mappings if the file system doesn't support the
- * standard FCB
+ * Initialized caching for this file object if previously caching
+ * was initialized for the same on disk file
*/
- if (!(FileObject->Flags & FO_FCB_IS_VALID))
- {
- ZwClose(*SectionHandle);
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- ExFreePool(ImageSections);
- return(STATUS_INVALID_FILE_FOR_SECTION);
- }
+ Status = CcTryToInitializeFileCache(FileObject);
- /*
- * Lock the file
- */
- Status = KeWaitForSingleObject((PVOID)&FileObject->Lock,
- 0,
- KernelMode,
- FALSE,
- NULL);
- if (Status != STATUS_SUCCESS)
+ if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL)
{
- ZwClose(*SectionHandle);
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- ExFreePool(ImageSections);
- return(Status);
- }
+ /*
+ * Read the dos header and check the DOS signature
+ */
+ Offset.QuadPart = 0;
+ Status = ZwReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ &DosHeader,
+ sizeof(DosHeader),
+ &Offset,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(FileObject);
+ return(Status);
+ }
+
+ /*
+ * Check the DOS signature
+ */
+ if (Iosb.Information != sizeof(DosHeader) ||
+ DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
+ {
+ ObDereferenceObject(FileObject);
+ return(STATUS_INVALID_IMAGE_FORMAT);
+ }
- /*
- * 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;
- ULONG Size;
- ULONG Characteristics;
-
- Size = sizeof(MM_IMAGE_SECTION_OBJECT) +
- (sizeof(MM_SECTION_SEGMENT) * NrSegments);
- ImageSectionObject =
- ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MM_SECTION_SEGMENT);
- if (ImageSectionObject == NULL)
- {
- KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
- ZwClose(*SectionHandle);
- ObDereferenceObject(Section);
+ /*
+ * 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))
+ {
+ ObDereferenceObject(FileObject);
+ return(Status);
+ }
+
+ /*
+ * Check the signature
+ */
+ if (Iosb.Information != sizeof(PEHeader) ||
+ PEHeader.Signature != IMAGE_NT_SIGNATURE)
+ {
+ ObDereferenceObject(FileObject);
+ 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));
+ if (ImageSections == NULL)
+ {
ObDereferenceObject(FileObject);
- ExFreePool(ImageSections);
return(STATUS_NO_MEMORY);
}
- ImageSectionObject->NrSegments = NrSegments;
- SectionSegments = ImageSectionObject->Segments;
- Section->Segments = SectionSegments;
-
- SectionSegments[0].FileOffset = 0;
- SectionSegments[0].Characteristics = IMAGE_SECTION_CHAR_DATA;
- SectionSegments[0].Protection = PAGE_READWRITE;
- SectionSegments[0].RawLength = PAGE_SIZE;
- SectionSegments[0].Length = PAGE_SIZE;
- SectionSegments[0].Flags = 0;
- SectionSegments[0].ReferenceCount = 1;
- SectionSegments[0].VirtualAddress = 0;
- SectionSegments[0].WriteCopy = TRUE;
- 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;
- /*
- * Set up the protection and write copy variables.
- */
- Characteristics = ImageSections[i - 1].Characteristics;
- if ((Characteristics & IMAGE_SECTION_CHAR_READABLE) ||
- (Characteristics & IMAGE_SECTION_CHAR_WRITABLE) ||
- (Characteristics & IMAGE_SECTION_CHAR_EXECUTABLE))
- {
- SectionSegments[i].Protection =
- SectionCharacteristicsToProtect[Characteristics >> 28];
- SectionSegments[i].WriteCopy =
- !(Characteristics & IMAGE_SECTION_CHAR_SHARED);
- }
- else if (Characteristics & IMAGE_SECTION_CHAR_CODE)
- {
- SectionSegments[i].Protection = PAGE_EXECUTE_READ;
- SectionSegments[i].WriteCopy = TRUE;
- }
- else if (Characteristics & IMAGE_SECTION_CHAR_DATA)
- {
- SectionSegments[i].Protection = PAGE_READWRITE;
- SectionSegments[i].WriteCopy = TRUE;
- }
- else if (Characteristics & IMAGE_SECTION_CHAR_BSS)
- {
- SectionSegments[i].Protection = PAGE_READWRITE;
- SectionSegments[i].WriteCopy = TRUE;
- }
- else
- {
- SectionSegments[i].Protection = PAGE_NOACCESS;
- SectionSegments[i].WriteCopy = TRUE;
- }
-
- /*
- * Set up the attributes.
- */
- if (Characteristics & IMAGE_SECTION_CHAR_CODE)
- {
- SectionSegments[i].Attributes = 0;
- }
- else if (Characteristics & IMAGE_SECTION_CHAR_DATA)
- {
- SectionSegments[i].Attributes = 0;
- }
- else if (Characteristics & IMAGE_SECTION_CHAR_BSS)
- {
- SectionSegments[i].Attributes = MM_SECTION_SEGMENT_BSS;
- }
- else
- {
- SectionSegments[i].Attributes = 0;
- }
+ Status = ZwReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ ImageSections,
+ PEHeader.FileHeader.NumberOfSections *
+ sizeof(IMAGE_SECTION_HEADER),
+ &Offset,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(FileObject);
+ ExFreePool(ImageSections);
+ return(Status);
+ }
+ if (Iosb.Information != (PEHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)))
+ {
+ ObDereferenceObject(FileObject);
+ ExFreePool(ImageSections);
+ return(STATUS_INVALID_IMAGE_FORMAT);
+ }
- 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);
- }
+ /*
+ * Create the section
+ */
+ Status = ObRosCreateObject(SectionHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ MmSectionObjectType,
+ (PVOID*)&Section);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(FileObject);
+ ExFreePool(ImageSections);
+ return(Status);
+ }
+
+ /*
+ * Initialize it
+ */
+ Section->SectionPageProtection = SectionPageProtection;
+ Section->AllocationAttributes = AllocationAttributes;
+ InitializeListHead(&Section->ViewListHead);
+ KeInitializeSpinLock(&Section->ViewListLock);
- FileObject->SectionObjectPointers->ImageSectionObject =
- (PVOID)ImageSectionObject;
+ /*
+ * Check file access required
+ */
+ if (SectionPageProtection & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
+ {
+ FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
+ }
+ else
+ {
+ FileAccess = FILE_READ_DATA;
+ }
+
+ /*
+ * 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);
+ }
+
+ /*
+ * allocate the section segments to describe the mapping
+ */
+ NrSegments = PEHeader.FileHeader.NumberOfSections + 1;
+ Size = sizeof(MM_IMAGE_SECTION_OBJECT) + sizeof(MM_SECTION_SEGMENT) * NrSegments;
+ ImageSectionObject = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MM_SECTION_SEGMENT);
+ if (ImageSectionObject == NULL)
+ {
+ KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
+ ZwClose(*SectionHandle);
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ ExFreePool(ImageSections);
+ return(STATUS_NO_MEMORY);
+ }
+ Section->ImageSection = ImageSectionObject;
+ ImageSectionObject->NrSegments = NrSegments;
+ ImageSectionObject->ImageBase = (PVOID)PEHeader.OptionalHeader.ImageBase;
+ ImageSectionObject->EntryPoint = (PVOID)PEHeader.OptionalHeader.AddressOfEntryPoint;
+ ImageSectionObject->StackReserve = PEHeader.OptionalHeader.SizeOfStackReserve;
+ ImageSectionObject->StackCommit = PEHeader.OptionalHeader.SizeOfStackCommit;
+ ImageSectionObject->Subsystem = PEHeader.OptionalHeader.Subsystem;
+ ImageSectionObject->MinorSubsystemVersion = PEHeader.OptionalHeader.MinorSubsystemVersion;
+ ImageSectionObject->MajorSubsystemVersion = PEHeader.OptionalHeader.MajorSubsystemVersion;
+ ImageSectionObject->ImageCharacteristics = PEHeader.FileHeader.Characteristics;
+ ImageSectionObject->Machine = PEHeader.FileHeader.Machine;
+ ImageSectionObject->Executable = (PEHeader.OptionalHeader.SizeOfCode != 0);
+
+ SectionSegments = ImageSectionObject->Segments;
+ SectionSegments[0].FileOffset = 0;
+ SectionSegments[0].Characteristics = IMAGE_SECTION_CHAR_DATA;
+ SectionSegments[0].Protection = PAGE_READONLY;
+ SectionSegments[0].RawLength = PAGE_SIZE;
+ SectionSegments[0].Length = PAGE_SIZE;
+ SectionSegments[0].Flags = 0;
+ SectionSegments[0].ReferenceCount = 1;
+ SectionSegments[0].VirtualAddress = 0;
+ SectionSegments[0].WriteCopy = FALSE;
+ ExInitializeFastMutex(&SectionSegments[0].Lock);
+ for (i = 1; i < NrSegments; i++)
+ {
+ SectionSegments[i].FileOffset = ImageSections[i-1].PointerToRawData;
+ SectionSegments[i].Characteristics = ImageSections[i-1].Characteristics;
+
+ /*
+ * Set up the protection and write copy variables.
+ */
+ Characteristics = ImageSections[i - 1].Characteristics;
+ if (Characteristics & (IMAGE_SECTION_CHAR_READABLE|IMAGE_SECTION_CHAR_WRITABLE|IMAGE_SECTION_CHAR_EXECUTABLE))
+ {
+ SectionSegments[i].Protection = SectionCharacteristicsToProtect[Characteristics >> 28];
+ SectionSegments[i].WriteCopy = !(Characteristics & IMAGE_SECTION_CHAR_SHARED);
+ }
+ else if (Characteristics & IMAGE_SECTION_CHAR_CODE)
+ {
+ SectionSegments[i].Protection = PAGE_EXECUTE_READ;
+ SectionSegments[i].WriteCopy = TRUE;
+ }
+ else if (Characteristics & IMAGE_SECTION_CHAR_DATA)
+ {
+ SectionSegments[i].Protection = PAGE_READWRITE;
+ SectionSegments[i].WriteCopy = TRUE;
+ }
+ else if (Characteristics & IMAGE_SECTION_CHAR_BSS)
+ {
+ SectionSegments[i].Protection = PAGE_READWRITE;
+ SectionSegments[i].WriteCopy = TRUE;
+ }
+ else
+ {
+ SectionSegments[i].Protection = PAGE_NOACCESS;
+ SectionSegments[i].WriteCopy = TRUE;
+ }
+
+ /*
+ * Set up the attributes.
+ */
+ if (Characteristics & IMAGE_SECTION_CHAR_CODE)
+ {
+ SectionSegments[i].Attributes = 0;
+ }
+ else if (Characteristics & IMAGE_SECTION_CHAR_DATA)
+ {
+ SectionSegments[i].Attributes = 0;
+ }
+ else if (Characteristics & IMAGE_SECTION_CHAR_BSS)
+ {
+ SectionSegments[i].Attributes = MM_SECTION_SEGMENT_BSS;
+ }
+ else
+ {
+ SectionSegments[i].Attributes = 0;
+ }
+
+ 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;
+ ExInitializeFastMutex(&SectionSegments[i].Lock);
+ }
+ if (0 != InterlockedCompareExchange((PLONG)&FileObject->SectionObjectPointer->ImageSectionObject,
+ (LONG)ImageSectionObject, 0))
+ {
+ /*
+ * An other thread has initialized the some image in the background
+ */
+ ExFreePool(ImageSectionObject);
+ ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
+ Section->ImageSection = ImageSectionObject;
+ SectionSegments = ImageSectionObject->Segments;
+
+ for (i = 0; i < NrSegments; i++)
+ {
+ InterlockedIncrement((LONG *)&SectionSegments[i].ReferenceCount);
+ }
+ }
+ ExFreePool(ImageSections);
}
else
{
- ULONG i;
+ /*
+ * Create the section
+ */
+ Status = ObRosCreateObject(SectionHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ MmSectionObjectType,
+ (PVOID*)&Section);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(FileObject);
+ return(Status);
+ }
- ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)
- FileObject->SectionObjectPointers->ImageSectionObject;
+ /*
+ * Initialize it
+ */
+ Section->SectionPageProtection = SectionPageProtection;
+ Section->AllocationAttributes = AllocationAttributes;
+ InitializeListHead(&Section->ViewListHead);
+ KeInitializeSpinLock(&Section->ViewListLock);
+
+ /*
+ * Check file access required
+ */
+ if (SectionPageProtection & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))
+ {
+ FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
+ }
+ else
+ {
+ FileAccess = FILE_READ_DATA;
+ }
+
+ /*
+ * Lock the file
+ */
+ Status = KeWaitForSingleObject((PVOID)&FileObject->Lock,
+ 0,
+ KernelMode,
+ FALSE,
+ NULL);
+ if (Status != STATUS_SUCCESS)
+ {
+ ZwClose(*SectionHandle);
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ return(Status);
+ }
+
+ ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
+ Section->ImageSection = ImageSectionObject;
SectionSegments = ImageSectionObject->Segments;
- Section->Segments = SectionSegments;
+ NrSegments = ImageSectionObject->NrSegments;
/*
* Otherwise just reference all the section segments
*/
for (i = 0; i < NrSegments; i++)
{
- InterlockedIncrement(&SectionSegments[i].ReferenceCount);
+ InterlockedIncrement((LONG *)&SectionSegments[i].ReferenceCount);
}
}
- ExFreePool(ImageSections);
- KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
- CcRosReferenceCache(FileObject);
Section->FileObject = FileObject;
-
+ CcRosReferenceCache(FileObject);
+ KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
ObDereferenceObject(Section);
return(STATUS_SUCCESS);
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
NtCreateSection (OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
* RETURN VALUE
*
* REVISIONS
- *
*/
NTSTATUS STDCALL
NtOpenSection(PHANDLE SectionHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes)
{
- NTSTATUS Status;
-
- *SectionHandle = 0;
+ NTSTATUS Status;
- Status = ObOpenObjectByName(ObjectAttributes,
- MmSectionObjectType,
- NULL,
- UserMode,
- DesiredAccess,
- NULL,
- SectionHandle);
+ *SectionHandle = 0;
- return(Status);
+ Status = ObOpenObjectByName(ObjectAttributes,
+ MmSectionObjectType,
+ NULL,
+ UserMode,
+ DesiredAccess,
+ NULL,
+ SectionHandle);
+
+ return(Status);
}
NTSTATUS STATIC
PVOID* BaseAddress,
ULONG ViewSize,
ULONG Protect,
- ULONG ViewOffset)
+ ULONG ViewOffset,
+ BOOL TopDown)
{
PMEMORY_AREA MArea;
NTSTATUS Status;
KIRQL oldIrql;
Status = MmCreateMemoryArea(Process,
- &Process->AddressSpace,
+ AddressSpace,
MEMORY_AREA_SECTION_VIEW,
BaseAddress,
ViewSize,
Protect,
&MArea,
- FALSE);
+ FALSE,
+ TopDown);
if (!NT_SUCCESS(Status))
{
DPRINT1("Mapping between 0x%.8X and 0x%.8X failed.\n",
(*BaseAddress), (*BaseAddress) + ViewSize);
return(Status);
}
-
+
KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
- InsertTailList(&Section->ViewListHead,
+ InsertTailList(&Section->ViewListHead,
&MArea->Data.SectionData.ViewListEntry);
KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
-
+
ObReferenceObjectByPointer((PVOID)Section,
SECTION_MAP_READ,
NULL,
MArea->Data.SectionData.WriteCopyView = FALSE;
MmInitialiseRegion(&MArea->Data.SectionData.RegionListHead,
ViewSize, 0, Protect);
-
+
return(STATUS_SUCCESS);
}
*
* RETURN VALUE
* Status.
+ *
+ * @implemented
*/
NTSTATUS STDCALL
NtMapViewOfSection(HANDLE SectionHandle,
PMEMORY_AREA MArea;
ULONG Entry;
PFILE_OBJECT FileObject;
- PREACTOS_COMMON_FCB_HEADER Fcb;
+ PBCB Bcb;
ULONG Offset;
SWAPENTRY SavedSwapEntry;
PMM_PAGEOP PageOp;
+ LARGE_INTEGER Timeout;
+ NTSTATUS Status;
+ PSECTION_OBJECT Section;
+ PMM_SECTION_SEGMENT Segment;
MArea = (PMEMORY_AREA)Context;
- Offset = ((ULONG)PAGE_ROUND_DOWN(Address) - (ULONG)MArea->BaseAddress) +
- MArea->Data.SectionData.ViewOffset;
- Entry = MmGetPageEntrySectionSegment(MArea->Data.SectionData.Segment,
- Offset);
+ Address = (PVOID)PAGE_ROUND_DOWN(Address);
+
+ Offset = ((ULONG)Address - (ULONG)MArea->BaseAddress);
+
+ Section = MArea->Data.SectionData.Section;
+ Segment = MArea->Data.SectionData.Segment;
- PageOp = MmCheckForPageOp(MArea, 0, NULL, MArea->Data.SectionData.Segment,
- Offset);
+
+ PageOp = MmCheckForPageOp(MArea, 0, NULL, Segment, Offset);
- if (PageOp)
- {
- KeWaitForSingleObject(&PageOp->CompletionEvent,
- 0,
- KernelMode,
- FALSE,
- NULL);
+ while (PageOp)
+ {
+ MmUnlockSectionSegment(Segment);
+ MmUnlockAddressSpace(&MArea->Process->AddressSpace);
+
+ Timeout.QuadPart = -100000000LL; // 10 sec
+ Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
+ 0,
+ KernelMode,
+ FALSE,
+ &Timeout);
+ if (Status != STATUS_SUCCESS)
+ {
+ DPRINT1("Failed to wait for page op, status = %x\n", Status);
+ KEBUGCHECK(0);
+ }
+
+ MmLockAddressSpace(&MArea->Process->AddressSpace);
+ MmLockSectionSegment(Segment);
+ KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
- PageOp = MmCheckForPageOp(MArea, 0, NULL, MArea->Data.SectionData.Segment,
- Offset);
+ PageOp = MmCheckForPageOp(MArea, 0, NULL, Segment, Offset);
}
-
- assert(PageOp == NULL);
+ Entry = MmGetPageEntrySectionSegment(Segment, Offset);
+
/*
* For a dirty, datafile, non-private page mark it as dirty in the
* cache manager.
*/
- if (MArea->Data.SectionData.Segment->Flags & MM_DATAFILE_SEGMENT)
+ if (Segment->Flags & MM_DATAFILE_SEGMENT)
{
if (PhysAddr.QuadPart == PAGE_FROM_SSE(Entry) && Dirty)
{
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
- Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
- CcRosMarkDirtyCacheSegment(Fcb->Bcb, Offset);
+ Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+ CcRosMarkDirtyCacheSegment(Bcb, Offset);
assert(SwapEntry == 0);
}
}
if (SwapEntry != 0)
{
+ /*
+ * Sanity check
+ */
+ if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ DPRINT1("Found a swap entry for a page in a pagefile section.\n");
+ KEBUGCHECK(0);
+ }
MmFreeSwapPage(SwapEntry);
}
else if (PhysAddr.QuadPart != 0)
if (IS_SWAP_FROM_SSE(Entry) ||
PhysAddr.QuadPart != (PAGE_FROM_SSE(Entry)))
{
+ /*
+ * Sanity check
+ */
+ if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ DPRINT1("Found a private page in a pagefile section.\n");
+ KEBUGCHECK(0);
+ }
/*
* Just dereference private pages
*/
MmFreeSwapPage(SavedSwapEntry);
MmSetSavedSwapEntryPage(PhysAddr, 0);
}
+ MmDeleteRmap(PhysAddr, MArea->Process, Address);
+ MmReleasePageMemoryConsumer(MC_USER, PhysAddr);
}
else
{
- MmUnsharePageEntrySectionSegment(MArea->Data.SectionData.Section,
- MArea->Data.SectionData.Segment,
- Offset,
- Dirty);
+ MmDeleteRmap(PhysAddr, MArea->Process, Address);
+ MmUnsharePageEntrySectionSegment(Section, Segment, Offset, Dirty);
+ MmReleasePageMemoryConsumer(MC_USER, PhysAddr);
}
- MmDeleteRmap(PhysAddr, MArea->Process, Address);
- MmReleasePageMemoryConsumer(MC_USER, PhysAddr);
}
}
-NTSTATUS STDCALL
-MmUnmapViewOfSection(PEPROCESS Process,
+NTSTATUS
+MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace,
PVOID BaseAddress)
{
- NTSTATUS Status;
+ NTSTATUS Status;
PMEMORY_AREA MemoryArea;
- PMADDRESS_SPACE AddressSpace;
PSECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
KIRQL oldIrql;
PLIST_ENTRY CurrentEntry;
PMM_REGION CurrentRegion;
-
- AddressSpace = &Process->AddressSpace;
-
- DPRINT("Opening memory area Process %x BaseAddress %x\n",
- Process, BaseAddress);
+ PLIST_ENTRY RegionListHead;
+
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
BaseAddress);
if (MemoryArea == NULL)
}
MemoryArea->DeleteInProgress = TRUE;
-
- MmLockSection(MemoryArea->Data.SectionData.Section);
- MmLockSectionSegment(MemoryArea->Data.SectionData.Segment);
Section = MemoryArea->Data.SectionData.Section;
Segment = MemoryArea->Data.SectionData.Segment;
+
+ MmLockSectionSegment(Segment);
KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
RemoveEntryList(&MemoryArea->Data.SectionData.ViewListEntry);
KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
- CurrentEntry = MemoryArea->Data.SectionData.RegionListHead.Flink;
- while (CurrentEntry != &MemoryArea->Data.SectionData.RegionListHead)
+ RegionListHead = &MemoryArea->Data.SectionData.RegionListHead;
+ while (!IsListEmpty(RegionListHead))
{
- CurrentRegion =
- CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
- CurrentEntry = CurrentEntry->Flink;
+ CurrentEntry = RemoveHeadList(RegionListHead);
+ CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
ExFreePool(CurrentRegion);
}
- if (MemoryArea->Data.SectionData.Section->AllocationAttributes &
- SEC_PHYSICALMEMORY)
+ if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
{
- Status = MmFreeMemoryArea(&Process->AddressSpace,
- BaseAddress,
+ Status = MmFreeMemoryArea(AddressSpace,
+ BaseAddress,
0,
NULL,
NULL);
}
else
{
- Status = MmFreeMemoryArea(&Process->AddressSpace,
+ Status = MmFreeMemoryArea(AddressSpace,
BaseAddress,
0,
MmFreeSectionPage,
MemoryArea);
- }
- MmUnlockSection(Section);
+ }
MmUnlockSectionSegment(Segment);
ObDereferenceObject(Section);
return(STATUS_SUCCESS);
}
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+MmUnmapViewOfSection(PEPROCESS Process,
+ PVOID BaseAddress)
+{
+ NTSTATUS Status;
+ PMEMORY_AREA MemoryArea;
+ PMADDRESS_SPACE AddressSpace;
+ PSECTION_OBJECT Section;
+
+ DPRINT("Opening memory area Process %x BaseAddress %x\n",
+ Process, BaseAddress);
+
+ assert(Process);
+
+ AddressSpace = &Process->AddressSpace;
+ MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
+ BaseAddress);
+ if (MemoryArea == NULL)
+ {
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ Section = MemoryArea->Data.SectionData.Section;
+
+ if (Section->AllocationAttributes & SEC_IMAGE)
+ {
+ ULONG i;
+ ULONG NrSegments;
+ PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+ PMM_SECTION_SEGMENT SectionSegments;
+ PVOID ImageBaseAddress;
+ PMM_SECTION_SEGMENT Segment;
+
+ Segment = MemoryArea->Data.SectionData.Segment;
+ ImageSectionObject = Section->ImageSection;
+ SectionSegments = ImageSectionObject->Segments;
+ NrSegments = ImageSectionObject->NrSegments;
+
+ /* Search for the current segment within the section segments
+ * and calculate the image base address */
+ for (i = 0; i < NrSegments; i++)
+ {
+ if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+ {
+ if (Segment == &SectionSegments[i])
+ {
+ ImageBaseAddress = BaseAddress - (ULONG_PTR)SectionSegments[i].VirtualAddress;
+ break;
+ }
+ }
+ }
+ if (i >= NrSegments)
+ {
+ KEBUGCHECK(0);
+ }
+
+ for (i = 0; i < NrSegments; i++)
+ {
+ if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+ {
+ PVOID SBaseAddress = (PVOID)
+ (ImageBaseAddress + (ULONG_PTR)SectionSegments[i].VirtualAddress);
+
+ Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
+ }
+ }
+ }
+ else
+ {
+ Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress);
+ }
+ return(STATUS_SUCCESS);
+}
+
/**********************************************************************
* NAME EXPORTED
* NtUnmapViewOfSection
* Status.
*
* REVISIONS
- *
*/
NTSTATUS STDCALL
NtUnmapViewOfSection (HANDLE ProcessHandle,
ObDereferenceObject(Section);
return(STATUS_INFO_LENGTH_MISMATCH);
}
+
Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
- 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;
-
+ memset(Sii, 0, sizeof(SECTION_IMAGE_INFORMATION));
+ if (Section->AllocationAttributes & SEC_IMAGE)
+ {
+ PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+ ImageSectionObject = Section->ImageSection;
+
+ Sii->EntryPoint = ImageSectionObject->EntryPoint;
+ Sii->StackReserve = ImageSectionObject->StackReserve;
+ Sii->StackCommit = ImageSectionObject->StackCommit;
+ Sii->Subsystem = ImageSectionObject->Subsystem;
+ Sii->MinorSubsystemVersion = ImageSectionObject->MinorSubsystemVersion;
+ Sii->MajorSubsystemVersion = ImageSectionObject->MajorSubsystemVersion;
+ Sii->Characteristics = ImageSectionObject->ImageCharacteristics;
+ Sii->ImageNumber = ImageSectionObject->Machine;
+ Sii->Executable = ImageSectionObject->Executable;
+ }
*ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
Status = STATUS_SUCCESS;
break;
IN ULONG NewMaximumSize)
{
UNIMPLEMENTED;
+ return(STATUS_NOT_IMPLEMENTED);
}
* Code taken from ntoskrnl/mm/special.c.
*
* REVISIONS
- *
*/
PVOID STDCALL
MmAllocateSection (IN ULONG Length)
Length,
0,
&marea,
+ FALSE,
FALSE);
if (!NT_SUCCESS(Status))
{
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to allocate page\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
Status = MmCreateVirtualMapping (NULL,
(Result + (i * PAGE_SIZE)),
TRUE);
if (!NT_SUCCESS(Status))
{
- DbgPrint("Unable to create virtual mapping\n");
- KeBugCheck(0);
+ DbgPrint("Unable to create virtual mapping\n");
+ KEBUGCHECK(0);
}
}
return ((PVOID)Result);
*
* RETURN VALUE
* Status.
+ *
+ * @implemented
*/
NTSTATUS STDCALL
MmMapViewOfSection(IN PVOID SectionObject,
ULONG ViewOffset;
NTSTATUS Status = STATUS_SUCCESS;
+ assert(Process);
+
Section = (PSECTION_OBJECT)SectionObject;
AddressSpace = &Process->AddressSpace;
MmLockAddressSpace(AddressSpace);
- MmLockSection(SectionObject);
-
+
if (Section->AllocationAttributes & SEC_IMAGE)
{
ULONG i;
+ ULONG NrSegments;
PVOID ImageBase;
- ULONG ImageSize;
-
+ ULONG ImageSize;
+ PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+ PMM_SECTION_SEGMENT SectionSegments;
+
+ ImageSectionObject = Section->ImageSection;
+ SectionSegments = ImageSectionObject->Segments;
+ NrSegments = ImageSectionObject->NrSegments;
+
+
ImageBase = *BaseAddress;
if (ImageBase == NULL)
{
- ImageBase = Section->ImageBase;
+ ImageBase = ImageSectionObject->ImageBase;
}
-
+
ImageSize = 0;
- for (i = 0; i < Section->NrSegments; i++)
+ for (i = 0; i < NrSegments; i++)
{
- if (!(Section->Segments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+ if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
{
ULONG MaxExtent;
- MaxExtent = (ULONG)(Section->Segments[i].VirtualAddress +
- Section->Segments[i].Length);
+ MaxExtent = (ULONG)(SectionSegments[i].VirtualAddress +
+ SectionSegments[i].Length);
ImageSize = max(ImageSize, MaxExtent);
}
}
/* Fail if the user requested a fixed base address. */
if ((*BaseAddress) != NULL)
{
- MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
return(STATUS_UNSUCCESSFUL);
}
/* Otherwise find a gap to map the image. */
- ImageBase = MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize));
+ ImageBase = MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), FALSE);
if (ImageBase == NULL)
{
- MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
return(STATUS_UNSUCCESSFUL);
}
}
-
- for (i = 0; i < Section->NrSegments; i++)
+
+ for (i = 0; i < NrSegments; i++)
{
- PVOID SBaseAddress;
-
- if (!(Section->Segments[i].Characteristics & IMAGE_SECTION_NOLOAD))
+ PVOID SBaseAddress;
+
+ if (!(SectionSegments[i].Characteristics & IMAGE_SECTION_NOLOAD))
{
SBaseAddress = (PVOID)
- (ImageBase + (ULONG_PTR)Section->Segments[i].VirtualAddress);
-
- MmLockSectionSegment(&Section->Segments[i]);
+ (ImageBase + (ULONG_PTR)SectionSegments[i].VirtualAddress);
+ MmLockSectionSegment(&SectionSegments[i]);
Status = MmMapViewOfSegment(Process,
- &Process->AddressSpace,
+ AddressSpace,
Section,
- &Section->Segments[i],
+ &SectionSegments[i],
&SBaseAddress,
- Section->Segments[i].Length,
- Section->Segments[i].Protection,
- Section->Segments[i].FileOffset);
- MmUnlockSectionSegment(&Section->Segments[i]);
+ SectionSegments[i].Length,
+ SectionSegments[i].Protection,
+ (ULONG_PTR)SectionSegments[i].VirtualAddress,
+ FALSE);
+ MmUnlockSectionSegment(&SectionSegments[i]);
if (!NT_SUCCESS(Status))
{
- MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
return(Status);
}
}
}
+
*BaseAddress = ImageBase;
}
else
{
ViewOffset = SectionOffset->u.LowPart;
}
-
+
if ((ViewOffset % PAGE_SIZE) != 0)
{
- MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
return(STATUS_MAPPED_ALIGNMENT);
}
{
(*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
}
-
- MmLockSectionSegment(Section->Segments);
+
+ MmLockSectionSegment(Section->Segment);
Status = MmMapViewOfSegment(Process,
- &Process->AddressSpace,
+ AddressSpace,
Section,
- Section->Segments,
+ Section->Segment,
BaseAddress,
*ViewSize,
Protect,
- ViewOffset);
- MmUnlockSectionSegment(Section->Segments);
+ ViewOffset,
+ (AllocationType & MEM_TOP_DOWN));
+ MmUnlockSectionSegment(Section->Segment);
if (!NT_SUCCESS(Status))
{
- MmUnlockSection(Section);
- MmUnlockAddressSpace(AddressSpace);
+ MmUnlockAddressSpace(AddressSpace);
return(Status);
}
}
- MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
return(STATUS_SUCCESS);
}
+/*
+ * @unimplemented
+ */
BOOLEAN STDCALL
MmCanFileBeTruncated (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
IN PLARGE_INTEGER NewFileSize)
}
+/*
+ * @unimplemented
+ */
BOOLEAN STDCALL
MmDisableModifiedWriteOfSection (DWORD Unknown0)
{
return (FALSE);
}
+/*
+ * @implemented
+ */
BOOLEAN STDCALL
MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
IN MMFLUSH_TYPE FlushType)
return FALSE;
}
+/*
+ * @unimplemented
+ */
BOOLEAN STDCALL
MmForceSectionClosed (DWORD Unknown0,
DWORD Unknown1)
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
-MmMapViewInSystemSpace (IN PVOID Section,
+MmMapViewInSystemSpace (IN PVOID SectionObject,
OUT PVOID * MappedBase,
- IN PULONG ViewSize)
+ IN OUT PULONG ViewSize)
{
- UNIMPLEMENTED;
- return (STATUS_NOT_IMPLEMENTED);
+ PSECTION_OBJECT Section;
+ PMADDRESS_SPACE AddressSpace;
+ NTSTATUS Status;
+
+ DPRINT("MmMapViewInSystemSpace() called\n");
+
+ Section = (PSECTION_OBJECT)SectionObject;
+ AddressSpace = MmGetKernelAddressSpace();
+
+ MmLockAddressSpace(AddressSpace);
+
+
+ if ((*ViewSize) == 0)
+ {
+ (*ViewSize) = Section->MaximumSize.u.LowPart;
+ }
+ else if ((*ViewSize) > Section->MaximumSize.u.LowPart)
+ {
+ (*ViewSize) = Section->MaximumSize.u.LowPart;
+ }
+
+ MmLockSectionSegment(Section->Segment);
+
+
+ Status = MmMapViewOfSegment(NULL,
+ AddressSpace,
+ Section,
+ Section->Segment,
+ MappedBase,
+ *ViewSize,
+ PAGE_READWRITE,
+ 0,
+ FALSE);
+
+ MmUnlockSectionSegment(Section->Segment);
+ MmUnlockAddressSpace(AddressSpace);
+
+ return Status;
}
+
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
-MmUnmapViewInSystemSpace (DWORD Unknown0)
+MmUnmapViewInSystemSpace (IN PVOID MappedBase)
{
- UNIMPLEMENTED;
- return (STATUS_NOT_IMPLEMENTED);
+ PMADDRESS_SPACE AddressSpace;
+ NTSTATUS Status;
+
+ DPRINT("MmUnmapViewInSystemSpace() called\n");
+
+ AddressSpace = MmGetKernelAddressSpace();
+
+ Status = MmUnmapViewOfSegment(AddressSpace, MappedBase);
+
+ return Status;
}
+/*
+ * @unimplemented
+ */
NTSTATUS STDCALL
MmSetBankedSection (DWORD Unknown0,
DWORD Unknown1,
* ARGUMENTS
* SectionObjiect (OUT)
* Caller supplied storage for the resulting pointer
- * to a SECTION_BOJECT instance;
+ * to a SECTION_OBJECT instance;
*
* DesiredAccess
* Specifies the desired access to the section can be a
*
* RETURN VALUE
* Status.
+ *
+ * @unimplemented
*/
NTSTATUS STDCALL
MmCreateSection (OUT PSECTION_OBJECT * SectionObject,
}
/* EOF */
-
-
-
-
-
-