mirror of
https://github.com/reactos/reactos.git
synced 2024-11-27 13:33:32 +08:00
- 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:
parent
8b1a283ee8
commit
736b50b0db
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user