Author: ion Date: Mon Sep 23 02:30:58 2013 New Revision: 60329
URL: http://svn.reactos.org/svn/reactos?rev=60329&view=rev Log: - 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.
Modified: trunk/reactos/ntoskrnl/mm/ARM3/section.c trunk/reactos/ntoskrnl/ntoskrnl.spec
Modified: trunk/reactos/ntoskrnl/mm/ARM3/section.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/section.c?... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/section.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/section.c [iso-8859-1] Mon Sep 23 02:30:58 2013 @@ -2742,6 +2742,171 @@ 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
Modified: trunk/reactos/ntoskrnl/ntoskrnl.spec URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl.spec?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ntoskrnl.spec [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ntoskrnl.spec [iso-8859-1] Mon Sep 23 02:30:58 2013 @@ -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)