- Implement and export MmCommitSessionMappedView. No gurantees this works until ThFabba writes a test for it, but it does what Windows does :P, minus charging commit since we don't do that yet. Nothing in ROS calls this so guranteed 0 regressions.

svn path=/trunk/; revision=60329
This commit is contained in:
Alex Ionescu 2013-09-23 02:30:58 +00:00
parent 8b1a283ee8
commit 736b50b0db
2 changed files with 166 additions and 1 deletions

View File

@ -2742,6 +2742,171 @@ MmUnmapViewInSystemSpace(IN PVOID MappedBase)
return MiUnmapViewInSystemSpace(&MmSession, MappedBase);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
MmCommitSessionMappedView(IN PVOID MappedBase,
IN SIZE_T ViewSize)
{
ULONG_PTR StartAddress, EndingAddress, Base;
ULONG Hash, Count, Size, QuotaCharge;
PMMSESSION Session;
PMMPTE LastProtoPte, PointerPte, ProtoPte;
PCONTROL_AREA ControlArea;
PSEGMENT Segment;
PSUBSECTION Subsection;
MMPTE TempPte;
PAGED_CODE();
/* Make sure the base isn't past the session view range */
if ((MappedBase < MiSessionViewStart) ||
(MappedBase >= (PVOID)((ULONG_PTR)MiSessionViewStart + MmSessionViewSize)))
{
DPRINT1("Base outside of valid range\n");
return STATUS_INVALID_PARAMETER_1;
}
/* Make sure the size isn't past the session view range */
if (((ULONG_PTR)MiSessionViewStart + MmSessionViewSize -
(ULONG_PTR)MappedBase) < ViewSize)
{
DPRINT1("Size outside of valid range\n");
return STATUS_INVALID_PARAMETER_2;
}
/* Sanity check */
ASSERT(ViewSize != 0);
/* Process must be in a session */
if (PsGetCurrentProcess()->ProcessInSession == FALSE)
{
DPRINT1("Process is not in session\n");
return STATUS_NOT_MAPPED_VIEW;
}
/* Compute the correctly aligned base and end addresses */
StartAddress = (ULONG_PTR)PAGE_ALIGN(MappedBase);
EndingAddress = ((ULONG_PTR)MappedBase + ViewSize - 1) | (PAGE_SIZE - 1);
/* Sanity check and grab the session */
ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE);
Session = &MmSessionSpace->Session;
/* Get the hash entry for this allocation */
Hash = (StartAddress >> 16) % Session->SystemSpaceHashKey;
/* Lock system space */
KeAcquireGuardedMutex(Session->SystemSpaceViewLockPointer);
/* Loop twice so we can try rolling over if needed */
while (TRUE)
{
/* Extract the size and base addresses from the entry */
Base = Session->SystemSpaceViewTable[Hash].Entry & ~0xFFFF;
Size = Session->SystemSpaceViewTable[Hash].Entry & 0xFFFF;
/* Convert the size to bucket chunks */
Size *= MI_SYSTEM_VIEW_BUCKET_SIZE;
/* Bail out if this entry fits in here */
if ((StartAddress >= Base) && (EndingAddress < (Base + Size))) break;
/* Check if we overflew past the end of the hash table */
if (++Hash >= Session->SystemSpaceHashSize)
{
/* Reset the hash to zero and keep searching from the bottom */
Hash = 0;
if (++Count == 2)
{
/* But if we overflew twice, then this is not a real mapping */
KeBugCheckEx(0xD7, //DRIVER_UNMAPPING_INVALID_VIEW,
Base,
2,
0,
0);
}
}
}
/* Make sure the view being mapped is not file-based */
ControlArea = Session->SystemSpaceViewTable[Hash].ControlArea;
if (ControlArea->FilePointer != NULL)
{
/* It is, so we have to bail out */
DPRINT1("Only page-filed backed sections can be commited\n");
KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
return STATUS_ALREADY_COMMITTED;
}
/* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
ASSERT(ControlArea->u.Flags.Rom == 0);
Subsection = (PSUBSECTION)(ControlArea + 1);
/* Get the start and end PTEs -- make sure the end PTE isn't past the end */
ProtoPte = Subsection->SubsectionBase + ((StartAddress - Base) >> PAGE_SHIFT);
QuotaCharge = MiAddressToPte(EndingAddress) - MiAddressToPte(StartAddress) + 1;
LastProtoPte = ProtoPte + QuotaCharge;
if (LastProtoPte >= Subsection->SubsectionBase + Subsection->PtesInSubsection)
{
DPRINT1("PTE is out of bounds\n");
KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
return STATUS_INVALID_PARAMETER_2;
}
/* Acquire the commit lock and count all the non-committed PTEs */
KeAcquireGuardedMutexUnsafe(&MmSectionCommitMutex);
PointerPte = ProtoPte;
while (PointerPte < LastProtoPte)
{
if (PointerPte->u.Long) QuotaCharge--;
PointerPte++;
}
/* Was everything committed already? */
if (!QuotaCharge)
{
/* Nothing to do! */
KeReleaseGuardedMutexUnsafe(&MmSectionCommitMutex);
KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
return STATUS_SUCCESS;
}
/* Pick the segment and template PTE */
Segment = ControlArea->Segment;
TempPte = Segment->SegmentPteTemplate;
ASSERT(TempPte.u.Long != 0);
/* Loop all prototype PTEs to be committed */
while (PointerPte < LastProtoPte)
{
/* Make sure the PTE is already invalid */
if (PointerPte->u.Long == 0)
{
/* And write the invalid PTE */
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
}
/* Move to the next PTE */
PointerPte++;
}
/* Check if we had at least one page charged */
if (QuotaCharge)
{
/* Update the accounting data */
Segment->NumberOfCommittedPages += QuotaCharge;
InterlockedExchangeAddSizeT(&MmSharedCommit, QuotaCharge);
}
/* Release all */
KeReleaseGuardedMutexUnsafe(&MmSectionCommitMutex);
KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
return STATUS_SUCCESS;
}
/* SYSTEM CALLS ***************************************************************/
NTSTATUS

View File

@ -758,7 +758,7 @@
@ stdcall MmAllocatePagesForMdlEx(long long long long long long long long long)
@ stdcall MmBuildMdlForNonPagedPool(ptr)
@ stdcall MmCanFileBeTruncated(ptr ptr)
;MmCommitSessionMappedView
@ stdcall MmCommitSessionMappedView(ptr ptr)
@ stdcall MmCreateMdl(ptr ptr long)
;MmCreateMirror
@ stdcall MmCreateSection(ptr long ptr ptr long long ptr ptr)