_MmSetPageEntrySectionSegment(S,O,E,__FILE__,__LINE__); \
} while (0)
+extern MMSESSION MmSession;
+
NTSTATUS
NTAPI
MiMapViewInSystemSpace(IN PVOID Section,
BOOLEAN WasDirty;
BOOLEAN Private;
PEPROCESS CallingProcess;
+ ULONG_PTR SectionEntry;
}
MM_SECTION_PAGEOUT_CONTEXT;
STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE,
SECTION_ALL_ACCESS};
-#define PAGE_FROM_SSE(E) ((E) & 0xFFFFF000)
-#define PFN_FROM_SSE(E) ((E) >> PAGE_SHIFT)
-#define SHARE_COUNT_FROM_SSE(E) (((E) & 0x00000FFC) >> 2)
-#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
-#define MAX_SHARE_COUNT 0x3FF
-#define MAKE_SSE(P, C) ((P) | ((C) << 2))
-#define SWAPENTRY_FROM_SSE(E) ((E) >> 1)
-#define MAKE_SWAP_SSE(S) (((ULONG)(S) << 1) | 0x1)
-
static const INFORMATION_CLASS_INFO ExSectionInfoClass[] =
{
ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionBasicInformation */
pssSegments[i].Image.Characteristics = pishSectionHeaders[i].Characteristics;
/* ensure the memory image is no larger than 4GB */
- nPrevVirtualEndOfSegment = pssSegments[i].Image.VirtualAddress + pssSegments[i].Length.QuadPart;
+ nPrevVirtualEndOfSegment = (ULONG_PTR)(pssSegments[i].Image.VirtualAddress + pssSegments[i].Length.QuadPart);
if (nPrevVirtualEndOfSegment < pssSegments[i].Image.VirtualAddress)
DIE(("The image is too large\n"));
}
return nStatus;
}
-/* Note: Mmsp prefix denotes "Memory Manager Section Private". */
-
-/*
- * FUNCTION: Waits in kernel mode up to ten seconds for an MM_PAGEOP event.
- * ARGUMENTS: PMM_PAGEOP which event we should wait for.
- * RETURNS: Status of the wait.
- */
-static NTSTATUS
-MmspWaitForPageOpCompletionEvent(PMM_PAGEOP PageOp)
-{
- LARGE_INTEGER Timeout;
-#ifdef __GNUC__ /* TODO: Use other macro to check for suffix to use? */
-
- Timeout.QuadPart = -100000000LL; // 10 sec
-#else
-
- Timeout.QuadPart = -100000000; // 10 sec
-#endif
-
- return KeWaitForSingleObject(&PageOp->CompletionEvent, 0, KernelMode, FALSE, &Timeout);
-}
-
-
-/*
- * FUNCTION: Sets the page op completion event and releases the page op.
- * ARGUMENTS: PMM_PAGEOP.
- * RETURNS: In shorter time than it takes you to even read this
- * description, so don't even think about geting a mug of coffee.
- */
-static void
-MmspCompleteAndReleasePageOp(PMM_PAGEOP PageOp)
-{
- KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
- MmReleasePageOp(PageOp);
-}
-
-
/*
* FUNCTION: Waits in kernel mode indefinitely for a file object lock.
* ARGUMENTS: PFILE_OBJECT to wait for.
MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset)
{
- ULONG Entry;
+ ULONG_PTR Entry;
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
if (Entry == 0)
PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset,
BOOLEAN Dirty,
- BOOLEAN PageOut)
+ BOOLEAN PageOut,
+ ULONG_PTR *InEntry)
{
- ULONG Entry;
+ ULONG_PTR Entry = InEntry ? *InEntry : MmGetPageEntrySectionSegment(Segment, Offset);
BOOLEAN IsDirectMapped = FALSE;
- Entry = MmGetPageEntrySectionSegment(Segment, Offset);
if (Entry == 0)
{
DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
}
if (SHARE_COUNT_FROM_SSE(Entry) == 0)
{
- DPRINT1("Zero share count for unshare\n");
+ DPRINT1("Zero share count for unshare (Seg %p Offset %x Page %x)\n", Segment, Offset->LowPart, PFN_FROM_SSE(Entry));
KeBugCheck(MEMORY_MANAGEMENT);
}
if (IS_SWAP_FROM_SSE(Entry))
* page without a rmap entry.
*/
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ if (InEntry) *InEntry = Entry;
+ MiSetPageEvent(NULL, NULL);
}
else
{
MmSetPageEntrySectionSegment(Segment, Offset, 0);
+ if (InEntry) *InEntry = 0;
+ MiSetPageEvent(NULL, NULL);
if (!IsDirectMapped)
{
MmReleasePageMemoryConsumer(MC_USER, Page);
}
}
MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
+ if (InEntry) *InEntry = MAKE_SWAP_SSE(SavedSwapEntry);
MmSetSavedSwapEntryPage(Page, 0);
+ MiSetPageEvent(NULL, NULL);
}
MmReleasePageMemoryConsumer(MC_USER, Page);
}
}
else
{
- MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+ if (InEntry)
+ *InEntry = Entry;
+ else
+ MmSetPageEntrySectionSegment(Segment, Offset, Entry);
}
return(SHARE_COUNT_FROM_SSE(Entry) > 0);
}
PBCB Bcb;
PCACHE_SEGMENT CacheSeg;
Bcb = MemoryArea->Data.SectionData.Section->FileObject->SectionObjectPointer->SharedCacheMap;
- CacheSeg = CcRosLookupCacheSegment(Bcb, SegOffset + MemoryArea->Data.SectionData.Segment->Image.FileOffset);
+ CacheSeg = CcRosLookupCacheSegment(Bcb, (ULONG)(SegOffset + MemoryArea->Data.SectionData.Segment->Image.FileOffset));
if (CacheSeg)
{
CcRosReleaseCacheSegment(Bcb, CacheSeg, CacheSeg->Valid, FALSE, TRUE);
NTSTATUS
NTAPI
-MiCopyFromUserPage(PFN_NUMBER DestPage, PVOID SourceAddress)
+MiCopyFromUserPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage)
{
PEPROCESS Process;
- KIRQL Irql;
- PVOID TempAddress;
+ KIRQL Irql, Irql2;
+ PVOID DestAddress, SrcAddress;
- ASSERT((ULONG_PTR)SourceAddress % PAGE_SIZE == 0);
Process = PsGetCurrentProcess();
- TempAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
- if (TempAddress == NULL)
+ DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
+ SrcAddress = MiMapPageInHyperSpace(Process, SrcPage, &Irql2);
+ if (DestAddress == NULL || SrcAddress == NULL)
{
return(STATUS_NO_MEMORY);
}
- ASSERT((ULONG_PTR)TempAddress % PAGE_SIZE == 0);
- RtlCopyMemory(TempAddress, SourceAddress, PAGE_SIZE);
- MiUnmapPageInHyperSpace(Process, TempAddress, Irql);
+ ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
+ ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
+ RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
+ MiUnmapPageInHyperSpace(Process, SrcAddress, Irql2);
+ MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
return(STATUS_SUCCESS);
}
*/
{
ULONG BaseOffset;
- ULONG_PTR FileOffset;
+ ULONGLONG FileOffset;
PVOID BaseAddress;
BOOLEAN UptoDate;
PCACHE_SEGMENT CacheSeg;
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
- RawLength = MemoryArea->Data.SectionData.Segment->RawLength.QuadPart;
+ RawLength = (ULONG_PTR)(MemoryArea->Data.SectionData.Segment->RawLength.QuadPart);
FileOffset = SegOffset + MemoryArea->Data.SectionData.Segment->Image.FileOffset;
IsImageSection = MemoryArea->Data.SectionData.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
* memory area was mapped at an offset in the file which is page aligned
* then get the related cache segment.
*/
- if ((FileOffset % PAGE_SIZE) == 0 &&
- (SegOffset + PAGE_SIZE <= RawLength || !IsImageSection) &&
+ if (((FileOffset % PAGE_SIZE) == 0) &&
+ ((SegOffset + PAGE_SIZE <= RawLength) || !IsImageSection) &&
!(MemoryArea->Data.SectionData.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
{
Process = PsGetCurrentProcess();
PageAddr = MiMapPageInHyperSpace(Process, *Page, &Irql);
- CacheSegOffset = BaseOffset + CacheSeg->Bcb->CacheSegmentSize - FileOffset;
+ CacheSegOffset = (ULONG_PTR)(BaseOffset + CacheSeg->Bcb->CacheSegmentSize - FileOffset);
Length = RawLength - SegOffset;
if (Length <= CacheSegOffset && Length <= PAGE_SIZE)
{
NTSTATUS
NTAPI
MiReadPage(PMEMORY_AREA MemoryArea,
- ULONG SegOffset,
+ ULONG_PTR SegOffset,
PPFN_NUMBER Page)
/*
* FUNCTION: Read a page for a section backed memory area.
Resources.Consumer = MC_USER;
Resources.Amount = PAGE_SIZE;
- DPRINT1("%S, offset %x, len %d, page %x\n", ((PFILE_OBJECT)Resources.Context)->FileName.Buffer, Resources.FileOffset.LowPart, Resources.Amount, Resources.Page[0]);
+ DPRINT("%S, offset 0x%x, len 0x%x, page 0x%x\n", ((PFILE_OBJECT)Resources.Context)->FileName.Buffer, Resources.FileOffset.LowPart, Resources.Amount, Resources.Page[0]);
Status = MiReadFilePage(MmGetKernelAddressSpace(), MemoryArea, &Resources);
*Page = Resources.Page[0];
ULONG_PTR Entry;
ULONG_PTR Entry1;
ULONG Attributes;
- PMM_PAGEOP PageOp;
PMM_REGION Region;
BOOLEAN HasSwapEntry;
PVOID PAddress;
* Lock the segment
*/
MmLockSectionSegment(Segment);
-
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
/*
* Check if this page needs to be mapped COW
*/
Attributes = Region->Protect;
}
- /*
- * Get or create a page operation descriptor
- */
- PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset.LowPart, MM_PAGEOP_PAGEIN, FALSE);
- if (PageOp == NULL)
- {
- DPRINT1("MmGetPageOp failed\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
/*
* Check if someone else is already handling this fault, if so wait
* for them
*/
- if (PageOp->Thread != PsGetCurrentThread())
+ if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
{
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
- Status = MmspWaitForPageOpCompletionEvent(PageOp);
- /*
- * Check for various strange conditions
- */
- if (Status != STATUS_SUCCESS)
- {
- DPRINT1("Failed to wait for page op, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- if (PageOp->Status == STATUS_PENDING)
- {
- DPRINT1("Woke for page op before completion\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
+ MiWaitForPageEvent(NULL, NULL);
MmLockAddressSpace(AddressSpace);
- /*
- * If this wasn't a pagein then restart the operation
- */
- if (PageOp->OpType != MM_PAGEOP_PAGEIN)
- {
- MmspCompleteAndReleasePageOp(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))
- {
- Status = PageOp->Status;
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
- return(Status);
- }
- MmLockSectionSegment(Segment);
- /*
- * If the completed fault was for another address space then set the
- * page in this one.
- */
- if (!MmIsPagePresent(Process, Address))
- {
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
- HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress);
-
- if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry)
- {
- /*
- * The page was a private page in another or in our address space
- */
- MmUnlockSectionSegment(Segment);
- MmspCompleteAndReleasePageOp(PageOp);
- return(STATUS_MM_RESTART_OPERATION);
- }
-
- Page = PFN_FROM_SSE(Entry);
-
- MmSharePageEntrySectionSegment(Segment, &Offset);
-
- #if (_MI_PAGING_LEVELS == 2)
- /* Reference Page Directory Entry */
- if(Address < MmSystemRangeStart)
- {
- MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
- ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT);
- }
-#endif
-
- /* FIXME: Should we call MmCreateVirtualMappingUnsafe if
- * (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true?
- */
- Status = MmCreateVirtualMapping(Process,
- PAddress,
- Attributes,
- &Page,
- 1);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to create virtual mapping\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- MmInsertRmap(Page, Process, Address);
- }
- MmUnlockSectionSegment(Segment);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_SUCCESS);
+ return(STATUS_MM_RESTART_OPERATION);
}
HasSwapEntry = MmIsPageSwapEntry(Process, Address);
+
if (HasSwapEntry)
{
+ SWAPENTRY SwapEntry;
+ /*
+ * Is it a wait entry?
+ */
+ MmGetPageFileMapping(Process, Address, &SwapEntry);
+
+ if (SwapEntry == MM_WAIT_ENTRY)
+ {
+ MmUnlockSectionSegment(Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ MiWaitForPageEvent(NULL, NULL);
+ MmLockAddressSpace(AddressSpace);
+ return STATUS_MM_RESTART_OPERATION;
+ }
+
/*
* Must be private page we have swapped out.
*/
- SWAPENTRY SwapEntry;
/*
* Sanity check
}
MmLockAddressSpace(AddressSpace);
Status = MmCreateVirtualMapping(Process,
- Address,
+ PAddress,
Region->Protect,
&Page,
1);
/*
* Finish the operation
*/
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
-#if (_MI_PAGING_LEVELS == 2)
- /* Reference Page Directory Entry */
- if(Address < MmSystemRangeStart)
- {
- MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
- ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT);
- }
-#endif
-
/*
* Satisfying a page fault on a map of /Device/PhysicalMemory is easy
*/
/*
* Just map the desired physical page
*/
- Page = Offset.QuadPart >> PAGE_SHIFT;
+ Page = (PFN_NUMBER)(Offset.QuadPart >> PAGE_SHIFT);
Status = MmCreateVirtualMappingUnsafe(Process,
PAddress,
Region->Protect,
/*
* Cleanup and release locks
*/
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
/*
* Cleanup and release locks
*/
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
/*
* Release all our locks and read in the page from disk
*/
+ MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
- (Offset.QuadPart >= PAGE_ROUND_UP(Segment->RawLength.QuadPart) && Section->AllocationAttributes & SEC_IMAGE))
+ ((Offset.QuadPart >= (LONGLONG)PAGE_ROUND_UP(Segment->RawLength.QuadPart) &&
+ (Section->AllocationAttributes & SEC_IMAGE))))
{
MI_SET_USAGE(MI_USAGE_SECTION);
if (Process) MI_SET_PROCESS2(Process->ImageFileName);
}
else
{
- Status = MiReadPage(MemoryArea, Offset.QuadPart, &Page);
+ Status = MiReadPage(MemoryArea, (ULONG_PTR)Offset.QuadPart, &Page);
if (!NT_SUCCESS(Status))
{
DPRINT1("MiReadPage failed (Status %x)\n", Status);
/*
* Cleanup and release locks
*/
-#if (_MI_PAGING_LEVELS == 2)
- if(Address < MmSystemRangeStart)
- {
- MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
- }
-#endif
MmLockAddressSpace(AddressSpace);
- PageOp->Status = Status;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(Status);
}
- /*
- * Relock the address space and segment
- */
- MmLockAddressSpace(AddressSpace);
- MmLockSectionSegment(Segment);
-
- /*
- * Check the entry. No one should change the status of a page
- * that has a pending page-in.
- */
- Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
- if (Entry != Entry1)
- {
- DPRINT1("Someone changed ppte entry while we slept\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
/*
* Mark the offset within the section as having valid, in-memory
* data
*/
+ MmLockAddressSpace(AddressSpace);
+ MmLockSectionSegment(Segment);
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
MmUnlockSectionSegment(Segment);
}
MmInsertRmap(Page, Process, Address);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
if (Entry != Entry1)
{
- DPRINT1("Someone changed ppte entry while we slept\n");
+ DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
KeBugCheck(MEMORY_MANAGEMENT);
}
*/
MmSetSavedSwapEntryPage(Page, SwapEntry);
Status = MmCreateVirtualMapping(Process,
- Address,
+ PAddress,
Region->Protect,
&Page,
1);
KeBugCheck(MEMORY_MANAGEMENT);
}
MmInsertRmap(Page, Process, Address);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
KeBugCheck(MEMORY_MANAGEMENT);
}
MmInsertRmap(Page, Process, Address);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
NTSTATUS Status;
PVOID PAddress;
LARGE_INTEGER Offset;
- PMM_PAGEOP PageOp;
PMM_REGION Region;
- ULONG Entry;
+ ULONG_PTR Entry;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+ SWAPENTRY SwapEntry;
DPRINT("MmAccessFaultSectionView(%x, %x, %x, %x)\n", AddressSpace, MemoryArea, Address);
MmSetPageProtect(Process, Address, Region->Protect);
return(STATUS_SUCCESS);
}
-
+
if(OldPage == 0)
DPRINT("OldPage == 0!\n");
-
+
/*
* Get or create a pageop
*/
- PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset.LowPart,
- MM_PAGEOP_ACCESSFAULT, FALSE);
- if (PageOp == NULL)
- {
- DPRINT1("MmGetPageOp failed\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
+ MmLockSectionSegment(Segment);
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
/*
* Wait for any other operations to complete
*/
- if (PageOp->Thread != PsGetCurrentThread())
+ if (Entry == SWAPENTRY_FROM_SSE(MM_WAIT_ENTRY))
{
- MmUnlockAddressSpace(AddressSpace);
- Status = MmspWaitForPageOpCompletionEvent(PageOp);
- /*
- * Check for various strange conditions
- */
- if (Status == STATUS_TIMEOUT)
- {
- DPRINT1("Failed to wait for page op, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- if (PageOp->Status == STATUS_PENDING)
- {
- DPRINT1("Woke for page op before completion\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- /*
- * Restart the operation
- */
- MmLockAddressSpace(AddressSpace);
- MmspCompleteAndReleasePageOp(PageOp);
- DPRINT("Address 0x%.8X\n", Address);
- return(STATUS_MM_RESTART_OPERATION);
+ MmUnlockSectionSegment(Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ MiWaitForPageEvent(NULL, NULL);
+ /*
+ * Restart the operation
+ */
+ MmLockAddressSpace(AddressSpace);
+ DPRINT("Address 0x%.8X\n", Address);
+ return(STATUS_MM_RESTART_OPERATION);
}
+ MmDeleteRmap(OldPage, Process, PAddress);
+ MmDeleteVirtualMapping(Process, PAddress, FALSE, NULL, NULL);
+ MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
+
/*
* Release locks now we have the pageop
*/
+ MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
/*
/*
* Copy the old page
*/
- MiCopyFromUserPage(NewPage, PAddress);
+ MiCopyFromUserPage(NewPage, OldPage);
MmLockAddressSpace(AddressSpace);
- /*
- * Delete the old entry.
- */
- MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL);
/*
* Set the PTE to point to the new page
*/
+ MmDeletePageFileMapping(Process, PAddress, &SwapEntry);
Status = MmCreateVirtualMapping(Process,
PAddress,
Region->Protect,
/*
* Unshare the old page.
*/
- MmDeleteRmap(OldPage, Process, PAddress);
+ DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
MmInsertRmap(NewPage, Process, PAddress);
MmLockSectionSegment(Segment);
- MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE);
+ MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
MmUnlockSectionSegment(Segment);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
{
MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
BOOLEAN WasDirty;
- PFN_NUMBER Page;
+ PFN_NUMBER Page = 0;
PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
if (Process)
PageOutContext->Segment,
&PageOutContext->Offset,
PageOutContext->WasDirty,
- TRUE);
+ TRUE,
+ &PageOutContext->SectionEntry);
MmUnlockSectionSegment(PageOutContext->Segment);
}
if (Process)
{
MmReleasePageMemoryConsumer(MC_USER, Page);
}
-
-#if (_MI_PAGING_LEVELS == 2)
- /* If this is for the calling process, we take care of te reference in the main function */
- if((Address < MmSystemRangeStart) && (Process != PageOutContext->CallingProcess))
- {
- Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
- ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_COUNT);
- }
-#endif
-
- DPRINT("PhysicalAddress %x, Address %x\n", Page << PAGE_SHIFT, Address);
}
NTSTATUS
NTAPI
MmPageOutSectionView(PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
- PVOID Address,
- PMM_PAGEOP PageOp)
+ PVOID Address, ULONG_PTR Entry)
{
PFN_NUMBER Page;
MM_SECTION_PAGEOUT_CONTEXT Context;
SWAPENTRY SwapEntry;
- ULONG Entry;
- ULONG FileOffset;
+ ULONGLONG FileOffset;
NTSTATUS Status;
PFILE_OBJECT FileObject;
#ifndef NEWCC
*/
Context.Segment = MemoryArea->Data.SectionData.Segment;
Context.Section = MemoryArea->Data.SectionData.Section;
+ Context.SectionEntry = Entry;
Context.CallingProcess = Process;
Context.Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
FileObject = Context.Section->FileObject;
DirectMapped = FALSE;
+ MmLockSectionSegment(Context.Segment);
+
#ifndef NEWCC
if (FileObject != NULL &&
!(Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
{
DPRINT("Cannot page out locked section page: 0x%p (RefCount: %d)\n",
Page, MmGetReferenceCountPage(Page));
- PageOp->Status = STATUS_UNSUCCESSFUL;
- MmspCompleteAndReleasePageOp(PageOp);
+ MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+ MmUnlockSectionSegment(Context.Segment);
return STATUS_UNSUCCESSFUL;
}
/*
* Prepare the context structure for the rmap delete call.
*/
- MmLockSectionSegment(Context.Segment);
- Entry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
MmUnlockSectionSegment(Context.Segment);
Context.WasDirty = FALSE;
if (Context.Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
}
MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping);
- MmLockSectionSegment(Context.Segment);
- Entry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
- MmUnlockSectionSegment(Context.Segment);
+
+ /* Since we passed in a surrogate, we'll get back the page entry
+ * state in our context. This is intended to make intermediate
+ * decrements of share count not release the wait entry.
+ */
+ Entry = Context.SectionEntry;
/*
* If this wasn't a private page then we should have reduced the entry to
}
if (!Context.WasDirty && SwapEntry != 0)
{
-#if (_MI_PAGING_LEVELS == 2)
- /* We keep the pagefile index global to the segment, not in the PTE */
- if(Address < MmSystemRangeStart)
- {
- Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
- ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_COUNT);
- }
-#endif
MmSetSavedSwapEntryPage(Page, 0);
MmLockSectionSegment(Context.Segment);
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
MmUnlockSectionSegment(Context.Segment);
MmReleasePageMemoryConsumer(MC_USER, Page);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
}
}
if (!Context.WasDirty || SwapEntry != 0)
{
-#if (_MI_PAGING_LEVELS == 2)
- /* We keep the pagefile index global to the segment, not in the PTE */
- if(Address < MmSystemRangeStart)
- {
- Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
- ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_COUNT);
- }
-#endif
MmSetSavedSwapEntryPage(Page, 0);
if (SwapEntry != 0)
{
MmUnlockSectionSegment(Context.Segment);
}
MmReleasePageMemoryConsumer(MC_USER, Page);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
}
else if (!Context.Private && DirectMapped)
{
-#if (_MI_PAGING_LEVELS == 2)
- /* Read only page, no need for a pagefile entry -> PDE-- */
- if(Address < MmSystemRangeStart)
- {
- Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
- ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_COUNT);
- }
-#endif
if (SwapEntry != 0)
{
DPRINT1("Found a swapentry for a non private and direct mapped page (address %x)\n",
KeBugCheckEx(MEMORY_MANAGEMENT, STATUS_UNSUCCESSFUL, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address);
}
#ifndef NEWCC
- Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
+ Status = CcRosUnmapCacheSegment(Bcb, (ULONG)FileOffset, FALSE);
#else
Status = STATUS_SUCCESS;
#endif
if (!NT_SUCCESS(Status))
{
DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status);
- KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Bcb, FileOffset, (ULONG_PTR)Address);
+ KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Bcb, (ULONG_PTR)FileOffset, (ULONG_PTR)Address);
}
#endif
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
else if (!Context.WasDirty && !DirectMapped && !Context.Private)
Address);
KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, Page, (ULONG_PTR)Process, (ULONG_PTR)Address);
}
-#if (_MI_PAGING_LEVELS == 2)
- /* Non dirty, non private, non direct-mapped -> PDE-- */
- if(Address < MmSystemRangeStart)
- {
- Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
- ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_COUNT);
- }
-#endif
MmReleasePageMemoryConsumer(MC_USER, Page);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
{
- DPRINT1("Not dirty and private and not swapped (%p:%p)\n", Process, Address);
+ DPRINT("Not dirty and private and not swapped (%p:%p)\n", Process, Address);
MmSetSavedSwapEntryPage(Page, 0);
MmLockAddressSpace(AddressSpace);
Status = MmCreatePageFileMapping(Process,
KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
}
MmReleasePageMemoryConsumer(MC_USER, Page);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
}
else
{
- LONG OldEntry;
+ ULONG_PTR OldEntry;
/*
* For non-private pages if the page wasn't direct mapped then
* set it back into the section segment entry so we don't loose
MmInsertRmap(Page,
Process,
Address);
- // If we got here, the previous entry should have been a wait
+ // If we got here, the previous entry should have been a wait
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmLockSectionSegment(Context.Segment);
- OldEntry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
- ASSERT(OldEntry == 0 || OldEntry == MAKE_SWAP_SSE(MM_WAIT_ENTRY));
+ MmLockSectionSegment(Context.Segment);
+ OldEntry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
+ ASSERT(OldEntry == 0 || OldEntry == MAKE_SWAP_SSE(MM_WAIT_ENTRY));
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
- MmUnlockSectionSegment(Context.Segment);
+ MmUnlockSectionSegment(Context.Segment);
}
MmUnlockAddressSpace(AddressSpace);
- PageOp->Status = STATUS_UNSUCCESSFUL;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_PAGEFILE_QUOTA);
}
}
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
}
MmUnlockAddressSpace(AddressSpace);
- PageOp->Status = STATUS_UNSUCCESSFUL;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_UNSUCCESSFUL);
}
* Otherwise we have succeeded.
*/
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
- MmLockSectionSegment(Context.Segment);
MmSetSavedSwapEntryPage(Page, 0);
if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
{
+ MmLockSectionSegment(Context.Segment);
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
+ MmUnlockSectionSegment(Context.Segment);
}
else
{
if (Context.Private)
{
MmLockAddressSpace(AddressSpace);
+ MmLockSectionSegment(Context.Segment);
Status = MmCreatePageFileMapping(Process,
Address,
SwapEntry);
+ MmUnlockSectionSegment(Context.Segment);
MmUnlockAddressSpace(AddressSpace);
if (!NT_SUCCESS(Status))
{
}
else
{
-#if (_MI_PAGING_LEVELS == 2)
- /* We keep the pagefile index global to the segment, not in the PTE */
- if(Address < MmSystemRangeStart)
- {
- Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
- ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_COUNT);
- }
-#endif
+ MmLockAddressSpace(AddressSpace);
+ MmLockSectionSegment(Context.Segment);
Entry = MAKE_SWAP_SSE(SwapEntry);
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+ MmUnlockSectionSegment(Context.Segment);
+ MmUnlockAddressSpace(AddressSpace);
}
- MmUnlockSectionSegment(Context.Segment);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
MmWritePageSectionView(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
- PMM_PAGEOP PageOp)
+ ULONG PageEntry)
{
LARGE_INTEGER Offset;
PROS_SECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
PFN_NUMBER Page;
SWAPENTRY SwapEntry;
- ULONG Entry;
+ ULONG_PTR Entry;
BOOLEAN Private;
NTSTATUS Status;
PFILE_OBJECT FileObject;
*/
if (DirectMapped && !Private)
{
+ LARGE_INTEGER SOffset;
ASSERT(SwapEntry == 0);
+ SOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset;
#ifndef NEWCC
- CcRosMarkDirtyCacheSegment(Bcb, Offset.LowPart + Segment->Image.FileOffset);
+ CcRosMarkDirtyCacheSegment(Bcb, Offset.LowPart);
#endif
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MmLockSectionSegment(Segment);
+ MmSetPageEntrySectionSegment(Segment, &Offset, PageEntry);
+ MmUnlockSectionSegment(Segment);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
if (SwapEntry == 0)
{
MmSetDirtyAllRmaps(Page);
- PageOp->Status = STATUS_UNSUCCESSFUL;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_PAGEFILE_QUOTA);
}
MmSetSavedSwapEntryPage(Page, SwapEntry);
DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
Status);
MmSetDirtyAllRmaps(Page);
- PageOp->Status = STATUS_UNSUCCESSFUL;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_UNSUCCESSFUL);
}
* Otherwise we have succeeded.
*/
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
- PageOp->Status = STATUS_SUCCESS;
- MmspCompleteAndReleasePageOp(PageOp);
+ MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
{
for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
{
+ SWAPENTRY SwapEntry;
PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
ULONG Protect = NewProtect;
+ /* Wait for a wait entry to disappear */
+ do {
+ MmGetPageFileMapping(Process, Address, &SwapEntry);
+ if (SwapEntry != MM_WAIT_ENTRY)
+ break;
+ MiWaitForPageEvent(Process, Address);
+ } while (TRUE);
+
/*
* If we doing COW for this segment then check if the page is
* already private.
if (DoCOW && MmIsPagePresent(Process, Address))
{
LARGE_INTEGER Offset;
- ULONG Entry;
+ ULONG_PTR Entry;
PFN_NUMBER Page;
Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
+ MemoryArea->Data.SectionData.ViewOffset.QuadPart;
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+ /*
+ * An MM_WAIT_ENTRY is ok in this case... It'll just count as
+ * IS_SWAP_FROM_SSE and we'll do the right thing.
+ */
Page = MmGetPfnForProcess(Process, Address);
Protect = PAGE_READONLY;
{
ULONG Length;
LARGE_INTEGER Offset;
- ULONG Entry;
+ ULONG_PTR Entry;
SWAPENTRY SavedSwapEntry;
PFN_NUMBER Page;
ULONG RefCount = 0;
PMM_SECTION_SEGMENT Segment = Section->Segment;
- if (Segment &&
+ if (Segment &&
(RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0)
{
DPRINT("Freeing section segment\n");
DPRINT("Creating Section Object Type\n");
+ /* Initialize the section based root */
+ ASSERT(MmSectionBasedRoot.NumberGenericTableElements == 0);
+ MmSectionBasedRoot.BalancedRoot.u1.Parent = &MmSectionBasedRoot.BalancedRoot;
+
/* Initialize the Section object type */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
RtlInitUnicodeString(&Name, L"Section");
* Initialize it
*/
RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
+ Section->Type = 'SC';
+ Section->Size = 'TN';
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
Section->MaximumSize = MaximumSize;
* Initialize it
*/
RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
+ Section->Type = 'SC';
+ Section->Size = 'TN';
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
Status = MiSimpleRead(FileObject, &FileOffset, Buffer, BufferSize, TRUE, &Iosb);
- UsedSize = Iosb.Information;
+ UsedSize = (ULONG)Iosb.Information;
if(NT_SUCCESS(Status) && UsedSize < OffsetAdjustment)
{
PMM_SECTION_SEGMENT Segment = &ImageSectionObject->Segments[i];
ULONG_PTR EndOfEffectiveSegment;
- EndOfEffectiveSegment = EffectiveSegment->Image.VirtualAddress + EffectiveSegment->Length.QuadPart;
+ EndOfEffectiveSegment = (ULONG_PTR)(EffectiveSegment->Image.VirtualAddress + EffectiveSegment->Length.QuadPart);
ASSERT((EndOfEffectiveSegment % PAGE_SIZE) == 0);
/*
* Initialize it
*/
RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
+ Section->Type = 'SC';
+ Section->Size = 'TN';
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
{
- ULONG Entry;
+ ULONG_PTR Entry;
PFILE_OBJECT FileObject;
PBCB Bcb;
LARGE_INTEGER Offset;
SWAPENTRY SavedSwapEntry;
- PMM_PAGEOP PageOp;
- NTSTATUS Status;
PROS_SECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
PMMSUPPORT AddressSpace;
Section = MemoryArea->Data.SectionData.Section;
Segment = MemoryArea->Data.SectionData.Segment;
- PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset.LowPart);
-
- while (PageOp)
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+ while (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
{
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
- Status = MmspWaitForPageOpCompletionEvent(PageOp);
- if (Status != STATUS_SUCCESS)
- {
- DPRINT1("Failed to wait for page op, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
+ MiWaitForPageEvent(NULL, NULL);
MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Segment);
- MmspCompleteAndReleasePageOp(PageOp);
- PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset.LowPart);
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
}
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
-
/*
* For a dirty, datafile, non-private page mark it as dirty in the
* cache manager.
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
#ifndef NEWCC
- CcRosMarkDirtyCacheSegment(Bcb, Offset.QuadPart + Segment->Image.FileOffset);
+ CcRosMarkDirtyCacheSegment(Bcb, (ULONG)(Offset.QuadPart + Segment->Image.FileOffset));
#endif
ASSERT(SwapEntry == 0);
}
else
{
MmDeleteRmap(Page, Process, Address);
- MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE);
+ MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE, NULL);
}
}
}
return(Status);
}
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-MmUnmapViewOfSection(PEPROCESS Process,
- PVOID BaseAddress)
+NTSTATUS
+NTAPI
+MiRosUnmapViewOfSection(IN PEPROCESS Process,
+ IN PVOID BaseAddress,
+ IN ULONG Flags)
{
NTSTATUS Status;
PMEMORY_AREA MemoryArea;
PMMSUPPORT AddressSpace;
PROS_SECTION_OBJECT Section;
- PMM_PAGEOP PageOp;
- ULONG_PTR Offset;
- PVOID ImageBaseAddress = 0;
+ PVOID ImageBaseAddress = 0;
DPRINT("Opening memory area Process %x BaseAddress %x\n",
Process, BaseAddress);
MemoryArea->Type != MEMORY_AREA_SECTION_VIEW ||
MemoryArea->DeleteInProgress)
{
+ ASSERT(MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3);
MmUnlockAddressSpace(AddressSpace);
return STATUS_NOT_MAPPED_VIEW;
}
MemoryArea->DeleteInProgress = TRUE;
- while (MemoryArea->PageOpCount)
- {
- Offset = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)MemoryArea->StartingAddress);
-
- while (Offset)
- {
- Offset -= PAGE_SIZE;
- PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL,
- MemoryArea->Data.SectionData.Segment,
- Offset + MemoryArea->Data.SectionData.ViewOffset.QuadPart);
- if (PageOp)
- {
- MmUnlockAddressSpace(AddressSpace);
- Status = MmspWaitForPageOpCompletionEvent(PageOp);
- if (Status != STATUS_SUCCESS)
- {
- DPRINT1("Failed to wait for page op, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- MmLockAddressSpace(AddressSpace);
- MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
- BaseAddress);
- if (MemoryArea == NULL ||
- MemoryArea->Type != MEMORY_AREA_SECTION_VIEW)
- {
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_NOT_MAPPED_VIEW;
- }
- break;
- }
- }
- }
-
Section = MemoryArea->Data.SectionData.Section;
if (Section->AllocationAttributes & SEC_IMAGE)
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN NotAtBase = FALSE;
- if ((ULONG_PTR)SectionObject & 1)
+ if (MiIsRosSectionObject(SectionObject) == FALSE)
{
- return MmMapViewOfArm3Section((PVOID)((ULONG_PTR)SectionObject & ~1),
+ DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
+ return MmMapViewOfArm3Section(SectionObject,
Process,
BaseAddress,
ZeroBits,
if (!(SectionSegments[i].Image.Characteristics & IMAGE_SCN_TYPE_NOLOAD))
{
ULONG_PTR MaxExtent;
- MaxExtent = (ULONG_PTR)SectionSegments[i].Image.VirtualAddress +
- SectionSegments[i].Length.QuadPart;
+ MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
+ SectionSegments[i].Length.QuadPart);
ImageSize = max(ImageSize, MaxExtent);
}
}
NTSTATUS Status;
PAGED_CODE();
- if ((ULONG_PTR)SectionObject & 1)
+ if (MiIsRosSectionObject(SectionObject) == FALSE)
{
- extern PVOID MmSession;
- return MiMapViewInSystemSpace((PVOID)((ULONG_PTR)SectionObject & ~1),
+ return MiMapViewInSystemSpace(SectionObject,
&MmSession,
MappedBase,
ViewSize);
return Status;
}
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-MmUnmapViewInSystemSpace (IN PVOID MappedBase)
+NTSTATUS
+NTAPI
+MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
{
PMMSUPPORT AddressSpace;
NTSTATUS Status;
return Status;
}
-
/**********************************************************************
* NAME EXPORTED
* MmCreateSection@
/* Check if an ARM3 section is being created instead */
if (AllocationAttributes & 1)
{
- DPRINT1("arm 3 path\n");
+ DPRINT1("Creating ARM3 section\n");
return MmCreateArm3Section(Section,
DesiredAccess,
ObjectAttributes,
DPRINT("Creating a section with WRITE access\n");
FileAccess = FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE;
}
- else
+ else
{
DPRINT("Creating a section with READ access\n");
FileAccess = FILE_READ_DATA | SYNCHRONIZE;
return Status;
}
+VOID
+MmModifyAttributes(IN PMMSUPPORT AddressSpace,
+ IN PVOID BaseAddress,
+ IN SIZE_T RegionSize,
+ IN ULONG OldType,
+ IN ULONG OldProtect,
+ IN ULONG NewType,
+ IN ULONG NewProtect)
+{
+ //
+ // This function is deprecated but remains in order to support VirtualAlloc
+ // calls with MEM_COMMIT on top of MapViewOfFile calls with SEC_RESERVE.
+ //
+ // Win32k's shared user heap, for example, uses that mechanism. The two
+ // conditions when this function needs to do something are ASSERTed for,
+ // because they should not arise.
+ //
+ if (NewType == MEM_RESERVE && OldType == MEM_COMMIT)
+ {
+ ASSERT(FALSE);
+ }
+
+ if ((NewType == MEM_COMMIT) && (OldType == MEM_COMMIT))
+ {
+ ASSERT(OldProtect == NewProtect);
+ }
+}
+
+NTSTATUS
+NTAPI
+MiRosAllocateVirtualMemory(IN HANDLE ProcessHandle,
+ IN PEPROCESS Process,
+ IN PMEMORY_AREA MemoryArea,
+ IN PMMSUPPORT AddressSpace,
+ IN OUT PVOID* UBaseAddress,
+ IN BOOLEAN Attached,
+ IN OUT PSIZE_T URegionSize,
+ IN ULONG AllocationType,
+ IN ULONG Protect)
+{
+ ULONG_PTR PRegionSize;
+ ULONG Type, RegionSize;
+ NTSTATUS Status;
+ PVOID PBaseAddress, BaseAddress;
+ KAPC_STATE ApcState;
+
+ PBaseAddress = *UBaseAddress;
+ PRegionSize = *URegionSize;
+
+ BaseAddress = (PVOID)PAGE_ROUND_DOWN(PBaseAddress);
+ RegionSize = PAGE_ROUND_UP((ULONG_PTR)PBaseAddress + PRegionSize) -
+ PAGE_ROUND_DOWN(PBaseAddress);
+ Type = (AllocationType & MEM_COMMIT) ? MEM_COMMIT : MEM_RESERVE;
+
+ ASSERT(PBaseAddress != 0);
+ ASSERT(Type == MEM_COMMIT);
+ ASSERT(MemoryArea->Type == MEMORY_AREA_SECTION_VIEW);
+ ASSERT(((ULONG_PTR)BaseAddress + RegionSize) <= (ULONG_PTR)MemoryArea->EndingAddress);
+ ASSERT(((ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)MemoryArea->StartingAddress) >= RegionSize);
+ ASSERT(MemoryArea->Data.SectionData.RegionListHead.Flink);
+
+ Status = MmAlterRegion(AddressSpace,
+ MemoryArea->StartingAddress,
+ &MemoryArea->Data.SectionData.RegionListHead,
+ BaseAddress,
+ RegionSize,
+ Type,
+ Protect,
+ MmModifyAttributes);
+
+ MmUnlockAddressSpace(AddressSpace);
+ if (Attached) KeUnstackDetachProcess(&ApcState);
+ if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
+ if (NT_SUCCESS(Status))
+ {
+ *UBaseAddress = BaseAddress;
+ *URegionSize = RegionSize;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+MiRosProtectVirtualMemory(IN PEPROCESS Process,
+ IN OUT PVOID *BaseAddress,
+ IN OUT PSIZE_T NumberOfBytesToProtect,
+ IN ULONG NewAccessProtection,
+ OUT PULONG OldAccessProtection OPTIONAL)
+{
+ PMEMORY_AREA MemoryArea;
+ PMMSUPPORT AddressSpace;
+ ULONG OldAccessProtection_;
+ NTSTATUS Status;
+
+ *NumberOfBytesToProtect = PAGE_ROUND_UP((ULONG_PTR)(*BaseAddress) + (*NumberOfBytesToProtect)) - PAGE_ROUND_DOWN(*BaseAddress);
+ *BaseAddress = (PVOID)PAGE_ROUND_DOWN(*BaseAddress);
+
+ AddressSpace = &Process->Vm;
+ MmLockAddressSpace(AddressSpace);
+ MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, *BaseAddress);
+ if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (OldAccessProtection == NULL) OldAccessProtection = &OldAccessProtection_;
+
+ if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
+ {
+ Status = MmProtectSectionView(AddressSpace,
+ MemoryArea,
+ *BaseAddress,
+ *NumberOfBytesToProtect,
+ NewAccessProtection,
+ OldAccessProtection);
+ }
+ else
+ {
+ /* FIXME: Should we return failure or success in this case? */
+ Status = STATUS_CONFLICTING_ADDRESSES;
+ }
+
+ MmUnlockAddressSpace(AddressSpace);
+
+ return Status;
+}
+
/* EOF */