@@ -4775,10 +4775,13 @@ MmCreateSection (OUT PVOID * Section,
47754775 return Status ;
47764776}
47774777
4778+ /* This function is not used. It is left for future use, when per-process
4779+ * address space is considered. */
4780+ #if 0
47784781BOOLEAN
47794782NTAPI
47804783MmArePagesResident (
4781- _In_ PEPROCESS Process ,
4784+ _In_opt_ PEPROCESS Process ,
47824785 _In_ PVOID Address ,
47834786 _In_ ULONG Length )
47844787{
@@ -4826,6 +4829,7 @@ MmArePagesResident(
48264829 MmUnlockAddressSpace (AddressSpace );
48274830 return Ret ;
48284831}
4832+ #endif
48294833
48304834/* Like CcPurgeCache but for the in-memory segment */
48314835BOOLEAN
@@ -4859,9 +4863,9 @@ MmPurgeSegment(
48594863 /* We must calculate the length for ourselves */
48604864 /* FIXME: All of this is suboptimal */
48614865 ULONG ElemCount = RtlNumberGenericTableElements (& Segment -> PageTable );
4862- /* No page. Nothing to purge */
48634866 if (!ElemCount )
48644867 {
4868+ /* No page. Nothing to purge */
48654869 MmUnlockSectionSegment (Segment );
48664870 MmDereferenceSegment (Segment );
48674871 return TRUE;
@@ -4871,6 +4875,9 @@ MmPurgeSegment(
48714875 PurgeEnd .QuadPart = PageTable -> FileOffset .QuadPart + _countof (PageTable -> PageEntries ) * PAGE_SIZE ;
48724876 }
48734877
4878+ /* Find byte offset of the page to start */
4879+ PurgeStart .QuadPart = PAGE_ROUND_DOWN (PurgeStart .QuadPart );
4880+
48744881 while (PurgeStart .QuadPart < PurgeEnd .QuadPart )
48754882 {
48764883 ULONG_PTR Entry = MmGetPageEntrySectionSegment (Segment , & PurgeStart );
@@ -4920,6 +4927,48 @@ MmPurgeSegment(
49204927 return TRUE;
49214928}
49224929
4930+ BOOLEAN
4931+ NTAPI
4932+ MmIsDataSectionResident (
4933+ _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer ,
4934+ _In_ LONGLONG Offset ,
4935+ _In_ ULONG Length )
4936+ {
4937+ PMM_SECTION_SEGMENT Segment ;
4938+ LARGE_INTEGER RangeStart , RangeEnd ;
4939+ BOOLEAN Ret = TRUE;
4940+
4941+ RangeStart .QuadPart = Offset ;
4942+ if (!NT_SUCCESS (RtlLongLongAdd (RangeStart .QuadPart , Length , & RangeEnd .QuadPart )))
4943+ return FALSE;
4944+
4945+ Segment = MiGrabDataSection (SectionObjectPointer );
4946+ if (!Segment )
4947+ return FALSE;
4948+
4949+ /* Find byte offset of the page to start */
4950+ RangeStart .QuadPart = PAGE_ROUND_DOWN (RangeStart .QuadPart );
4951+
4952+ MmLockSectionSegment (Segment );
4953+
4954+ while (RangeStart .QuadPart < RangeEnd .QuadPart )
4955+ {
4956+ ULONG_PTR Entry = MmGetPageEntrySectionSegment (Segment , & RangeStart );
4957+ if ((Entry == 0 ) || IS_SWAP_FROM_SSE (Entry ))
4958+ {
4959+ Ret = FALSE;
4960+ break ;
4961+ }
4962+
4963+ RangeStart .QuadPart += PAGE_SIZE ;
4964+ }
4965+
4966+ MmUnlockSectionSegment (Segment );
4967+ MmDereferenceSegment (Segment );
4968+
4969+ return Ret ;
4970+ }
4971+
49234972NTSTATUS
49244973NTAPI
49254974MmMakeDataSectionResident (
@@ -4940,6 +4989,63 @@ MmMakeDataSectionResident(
49404989 return Status ;
49414990}
49424991
4992+ NTSTATUS
4993+ NTAPI
4994+ MmMakeSegmentDirty (
4995+ _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer ,
4996+ _In_ LONGLONG Offset ,
4997+ _In_ ULONG Length )
4998+ {
4999+ PMM_SECTION_SEGMENT Segment ;
5000+ LARGE_INTEGER RangeStart , RangeEnd ;
5001+ NTSTATUS Status ;
5002+
5003+ RangeStart .QuadPart = Offset ;
5004+ Status = RtlLongLongAdd (RangeStart .QuadPart , Length , & RangeEnd .QuadPart );
5005+ if (!NT_SUCCESS (Status ))
5006+ return Status ;
5007+
5008+ Segment = MiGrabDataSection (SectionObjectPointer );
5009+ if (!Segment )
5010+ return STATUS_NOT_MAPPED_VIEW ;
5011+
5012+ /* Find byte offset of the page to start */
5013+ RangeStart .QuadPart = PAGE_ROUND_DOWN (RangeStart .QuadPart );
5014+
5015+ MmLockSectionSegment (Segment );
5016+
5017+ while (RangeStart .QuadPart < RangeEnd .QuadPart )
5018+ {
5019+ ULONG_PTR Entry = MmGetPageEntrySectionSegment (Segment , & RangeStart );
5020+
5021+ /* Let any pending read proceed */
5022+ while (MM_IS_WAIT_PTE (Entry ))
5023+ {
5024+ MmUnlockSectionSegment (Segment );
5025+ KeDelayExecutionThread (KernelMode , FALSE, & TinyTime );
5026+ MmLockSectionSegment (Segment );
5027+ Entry = MmGetPageEntrySectionSegment (Segment , & RangeStart );
5028+ }
5029+
5030+ /* We are called from Cc, this can't be backed by the page files */
5031+ ASSERT (!IS_SWAP_FROM_SSE (Entry ));
5032+
5033+ /* If there is no page there, there is nothing to make dirty */
5034+ if (Entry != 0 )
5035+ {
5036+ /* Dirtify the entry */
5037+ MmSetPageEntrySectionSegment (Segment , & RangeStart , DIRTY_SSE (Entry ));
5038+ }
5039+
5040+ RangeStart .QuadPart += PAGE_SIZE ;
5041+ }
5042+
5043+ MmUnlockSectionSegment (Segment );
5044+ MmDereferenceSegment (Segment );
5045+
5046+ return STATUS_SUCCESS ;
5047+ }
5048+
49435049NTSTATUS
49445050NTAPI
49455051MmFlushSegment (
@@ -4991,8 +5097,8 @@ MmFlushSegment(
49915097 FlushEnd .QuadPart = PageTable -> FileOffset .QuadPart + _countof (PageTable -> PageEntries ) * PAGE_SIZE ;
49925098 }
49935099
4994- FlushStart . QuadPart >>= PAGE_SHIFT ;
4995- FlushStart .QuadPart <<= PAGE_SHIFT ;
5100+ /* Find byte offset of the page to start */
5101+ FlushStart .QuadPart = PAGE_ROUND_DOWN ( FlushStart . QuadPart ) ;
49965102
49975103 while (FlushStart .QuadPart < FlushEnd .QuadPart )
49985104 {
@@ -5197,10 +5303,13 @@ MmCheckDirtySegment(
51975303 return FALSE;
51985304}
51995305
5306+ /* This function is not used. It is left for future use, when per-process
5307+ * address space is considered. */
5308+ #if 0
52005309NTSTATUS
52015310NTAPI
52025311MmMakePagesDirty (
5203- _In_ PEPROCESS Process ,
5312+ _In_opt_ PEPROCESS Process ,
52045313 _In_ PVOID Address ,
52055314 _In_ ULONG Length )
52065315{
@@ -5267,6 +5376,7 @@ MmMakePagesDirty(
52675376 MmUnlockAddressSpace (AddressSpace );
52685377 return STATUS_SUCCESS ;
52695378}
5379+ #endif
52705380
52715381NTSTATUS
52725382NTAPI
0 commit comments