2 * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * PROJECT: ReactOS kernel
20 * FILE: ntoskrnl/mm/section.c
21 * PURPOSE: Implements section objects
23 * PROGRAMMERS: Rex Jolliff
36 * Thomas Weidenmueller
37 * Gunnar Andre' Dalsnes
45 /* INCLUDES *****************************************************************/
52 #include "../mm/ARM3/miarm.h"
54 #define DPRINTC DPRINT
56 LIST_ENTRY MiSegmentList
;
58 extern KEVENT MpwThreadEvent
;
59 extern KSPIN_LOCK MiSectionPageTableLock
;
60 extern PMMWSL MmWorkingSetList
;
62 /* GLOBALS *******************************************************************/
64 ULONG_PTR MmSubsectionBase
;
66 static const INFORMATION_CLASS_INFO ExSectionInfoClass
[] =
68 ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
), /* SectionBasicInformation */
69 ICI_SQ_SAME( sizeof(SECTION_IMAGE_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
), /* SectionImageInformation */
72 /* FUNCTIONS *****************************************************************/
74 /* Note: Mmsp prefix denotes "Memory Manager Section Private". */
78 _MmLockSectionSegment(PMM_SECTION_SEGMENT Segment
, const char *file
, int line
)
80 //DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line);
81 ExAcquireFastMutex(&Segment
->Lock
);
82 Segment
->Locked
= TRUE
;
87 _MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment
, const char *file
, int line
)
89 ASSERT(Segment
->Locked
);
90 Segment
->Locked
= FALSE
;
91 ExReleaseFastMutex(&Segment
->Lock
);
92 //DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line);
99 PLARGE_INTEGER FileOffsetPtr
,
103 PMMSUPPORT AddressSpace
;
104 PMEMORY_AREA MemoryArea
;
105 PMM_SECTION_SEGMENT Segment
;
106 LARGE_INTEGER FileOffset
= *FileOffsetPtr
, End
, FirstMapped
;
109 DPRINT("MiZeroFillSection(Address %x,Offset %x,Length %x)\n", Address
, FileOffset
.LowPart
, Length
);
111 AddressSpace
= MmGetKernelAddressSpace();
113 MmLockAddressSpace(AddressSpace
);
114 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, Address
);
115 MmUnlockAddressSpace(AddressSpace
);
116 if (!MemoryArea
|| MemoryArea
->Type
!= MEMORY_AREA_SECTION_VIEW
)
118 return STATUS_NOT_MAPPED_DATA
;
121 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
122 End
.QuadPart
= FileOffset
.QuadPart
+ Length
;
123 End
.LowPart
= PAGE_ROUND_DOWN(End
.LowPart
);
124 FileOffset
.LowPart
= PAGE_ROUND_UP(FileOffset
.LowPart
);
125 FirstMapped
.QuadPart
= MemoryArea
->Data
.SectionData
.ViewOffset
.QuadPart
;
127 ("Pulling zero pages for %08x%08x-%08x%08x\n",
128 FileOffset
.u
.HighPart
, FileOffset
.u
.LowPart
,
129 End
.u
.HighPart
, End
.u
.LowPart
);
130 while (FileOffset
.QuadPart
< End
.QuadPart
)
135 if (!NT_SUCCESS(MmRequestPageMemoryConsumer(MC_CACHE
, TRUE
, &Page
)))
138 MmLockAddressSpace(AddressSpace
);
139 MmLockSectionSegment(Segment
);
141 Entry
= MmGetPageEntrySectionSegment(Segment
, &FileOffset
);
144 MmSetPageEntrySectionSegment(Segment
, &FileOffset
, MAKE_PFN_SSE(Page
));
145 Address
= ((PCHAR
)MemoryArea
->StartingAddress
) + FileOffset
.QuadPart
- FirstMapped
.QuadPart
;
147 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
148 MmReferencePage(Page
);
149 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
151 MmCreateVirtualMapping(NULL
, Address
, PAGE_READWRITE
, &Page
, 1);
152 MmInsertRmap(Page
, NULL
, Address
);
155 MmReleasePageMemoryConsumer(MC_CACHE
, Page
);
157 MmUnlockSectionSegment(Segment
);
158 MmUnlockAddressSpace(AddressSpace
);
160 FileOffset
.QuadPart
+= PAGE_SIZE
;
162 return STATUS_SUCCESS
;
167 _MiFlushMappedSection
169 PLARGE_INTEGER BaseOffset
,
170 PLARGE_INTEGER FileSize
,
175 NTSTATUS Status
= STATUS_SUCCESS
;
176 ULONG_PTR PageAddress
;
177 PMMSUPPORT AddressSpace
= MmGetKernelAddressSpace();
178 PMEMORY_AREA MemoryArea
;
179 PMM_SECTION_SEGMENT Segment
;
180 ULONG_PTR BeginningAddress
, EndingAddress
;
181 LARGE_INTEGER ViewOffset
;
182 LARGE_INTEGER FileOffset
;
187 DPRINT("MiFlushMappedSection(%x,%08x,%x,%d,%s:%d)\n", BaseAddress
, BaseOffset
->LowPart
, FileSize
, WriteData
, File
, Line
);
189 MmLockAddressSpace(AddressSpace
);
190 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, BaseAddress
);
191 if (!MemoryArea
|| MemoryArea
->Type
!= MEMORY_AREA_CACHE
)
193 MmUnlockAddressSpace(AddressSpace
);
194 DPRINT("STATUS_NOT_MAPPED_DATA\n");
195 return STATUS_NOT_MAPPED_DATA
;
197 BeginningAddress
= PAGE_ROUND_DOWN((ULONG_PTR
)MemoryArea
->StartingAddress
);
198 EndingAddress
= PAGE_ROUND_UP((ULONG_PTR
)MemoryArea
->EndingAddress
);
199 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
200 ViewOffset
.QuadPart
= MemoryArea
->Data
.SectionData
.ViewOffset
.QuadPart
;
202 ASSERT(ViewOffset
.QuadPart
== BaseOffset
->QuadPart
);
204 MmLockSectionSegment(Segment
);
206 Pages
= ExAllocatePool
209 ((EndingAddress
- BeginningAddress
) >> PAGE_SHIFT
));
216 //DPRINT("Getting pages in range %08x-%08x\n", BeginningAddress, EndingAddress);
218 for (PageAddress
= BeginningAddress
;
219 PageAddress
< EndingAddress
;
220 PageAddress
+= PAGE_SIZE
)
223 FileOffset
.QuadPart
= ViewOffset
.QuadPart
+ PageAddress
- BeginningAddress
;
225 MmGetPageEntrySectionSegment
226 (MemoryArea
->Data
.SectionData
.Segment
,
228 Page
= PFN_FROM_SSE(Entry
);
229 if (Entry
!= 0 && !IS_SWAP_FROM_SSE(Entry
) &&
230 (MmIsDirtyPageRmap(Page
) || IS_DIRTY_SSE(Entry
)) &&
231 FileOffset
.QuadPart
< FileSize
->QuadPart
)
233 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
234 MmReferencePage(Page
);
235 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
236 Pages
[(PageAddress
- BeginningAddress
) >> PAGE_SHIFT
] = Entry
;
239 Pages
[(PageAddress
- BeginningAddress
) >> PAGE_SHIFT
] = 0;
242 MmUnlockSectionSegment(Segment
);
243 MmUnlockAddressSpace(AddressSpace
);
245 for (PageAddress
= BeginningAddress
;
246 PageAddress
< EndingAddress
;
247 PageAddress
+= PAGE_SIZE
)
250 FileOffset
.QuadPart
= ViewOffset
.QuadPart
+ PageAddress
- BeginningAddress
;
251 Entry
= Pages
[(PageAddress
- BeginningAddress
) >> PAGE_SHIFT
];
252 Page
= PFN_FROM_SSE(Entry
);
256 //DPRINT("MiWriteBackPage(%wZ,addr %x,%08x%08x)\n", &Segment->FileObject->FileName, PageAddress, FileOffset.u.HighPart, FileOffset.u.LowPart);
257 Status
= MiWriteBackPage(Segment
->FileObject
, &FileOffset
, PAGE_SIZE
, Page
);
259 Status
= STATUS_SUCCESS
;
261 if (NT_SUCCESS(Status
)) {
262 MmLockAddressSpace(AddressSpace
);
263 MmSetCleanAllRmaps(Page
);
264 MmSetPageProtect(MmGetAddressSpaceOwner(AddressSpace
), (PVOID
)PageAddress
, PAGE_READONLY
);
265 MmLockSectionSegment(Segment
);
266 Entry
= MmGetPageEntrySectionSegment(Segment
, &FileOffset
);
267 if (Entry
&& !IS_SWAP_FROM_SSE(Entry
) && PFN_FROM_SSE(Entry
) == Page
)
268 MmSetPageEntrySectionSegment(Segment
, &FileOffset
, CLEAN_SSE(Entry
));
269 MmUnlockSectionSegment(Segment
);
270 MmUnlockAddressSpace(AddressSpace
);
273 ("Writeback from section flush %08x%08x (%x) %x@%x (%08x%08x:%wZ) failed %x\n",
274 FileOffset
.u
.HighPart
, FileOffset
.u
.LowPart
,
275 (ULONG
)(FileSize
->QuadPart
- FileOffset
.QuadPart
),
278 FileSize
->u
.HighPart
,
280 &Segment
->FileObject
->FileName
,
283 MmReleasePageMemoryConsumer(MC_CACHE
, Page
);
294 MmFinalizeSegment(PMM_SECTION_SEGMENT Segment
)
298 DPRINT("Finalize segment %p\n", Segment
);
300 MmLockSectionSegment(Segment
);
301 RemoveEntryList(&Segment
->ListOfSegments
);
302 if (Segment
->Flags
& MM_DATAFILE_SEGMENT
) {
303 KeAcquireSpinLock(&Segment
->FileObject
->IrpListLock
, &OldIrql
);
304 if (Segment
->Flags
& MM_SEGMENT_FINALIZE
) {
305 KeReleaseSpinLock(&Segment
->FileObject
->IrpListLock
, OldIrql
);
306 MmUnlockSectionSegment(Segment
);
309 Segment
->Flags
|= MM_SEGMENT_FINALIZE
;
310 DPRINTC("Finalizing data file segment %p\n", Segment
);
312 Segment
->FileObject
->SectionObjectPointer
->DataSectionObject
= NULL
;
313 KeReleaseSpinLock(&Segment
->FileObject
->IrpListLock
, OldIrql
);
314 MmFreePageTablesSectionSegment(Segment
, MiFreeSegmentPage
);
315 MmUnlockSectionSegment(Segment
);
316 DPRINT("Dereference file object %wZ\n", &Segment
->FileObject
->FileName
);
317 ObDereferenceObject(Segment
->FileObject
);
318 DPRINT("Done with %wZ\n", &Segment
->FileObject
->FileName
);
319 Segment
->FileObject
= NULL
;
321 DPRINTC("Finalizing segment %p\n", Segment
);
322 MmFreePageTablesSectionSegment(Segment
, MiFreeSegmentPage
);
323 MmUnlockSectionSegment(Segment
);
325 DPRINTC("Segment %p destroy\n", Segment
);
326 ExFreePoolWithTag(Segment
, TAG_MM_SECTION_SEGMENT
);
331 MmCreateCacheSection(PROS_SECTION_OBJECT
*SectionObject
,
332 ACCESS_MASK DesiredAccess
,
333 POBJECT_ATTRIBUTES ObjectAttributes
,
334 PLARGE_INTEGER UMaximumSize
,
335 ULONG SectionPageProtection
,
336 ULONG AllocationAttributes
,
337 PFILE_OBJECT FileObject
)
339 * Create a section backed by a data file
342 PROS_SECTION_OBJECT Section
;
344 ULARGE_INTEGER MaximumSize
;
345 PMM_SECTION_SEGMENT Segment
;
346 IO_STATUS_BLOCK Iosb
;
347 CC_FILE_SIZES FileSizes
;
348 FILE_STANDARD_INFORMATION FileInfo
;
351 DPRINT("MmCreateDataFileSection\n");
356 Status
= ObCreateObject(ExGetPreviousMode(),
361 sizeof(ROS_SECTION_OBJECT
),
364 (PVOID
*)(PVOID
)&Section
);
365 if (!NT_SUCCESS(Status
))
367 DPRINT("Failed: %x\n", Status
);
373 RtlZeroMemory(Section
, sizeof(ROS_SECTION_OBJECT
));
374 Section
->Type
= 'SC';
375 Section
->Size
= 'TN';
376 Section
->SectionPageProtection
= SectionPageProtection
;
377 Section
->AllocationAttributes
= AllocationAttributes
;
378 Section
->Segment
= NULL
;
380 Section
->FileObject
= FileObject
;
382 DPRINT("Getting original file size\n");
383 /* A hack: If we're cached, we can overcome deadlocking with the upper
384 * layer filesystem call by retriving the object sizes from the cache
385 * which is made to keep track. If I had to guess, they were figuring
386 * out a similar problem.
388 if (!CcGetFileSizes(FileObject
, &FileSizes
))
391 * FIXME: This is propably not entirely correct. We can't look into
392 * the standard FCB header because it might not be initialized yet
393 * (as in case of the EXT2FS driver by Manoj Paul Joseph where the
394 * standard file information is filled on first request).
396 DPRINT("Querying info\n");
397 Status
= IoQueryFileInformation
399 FileStandardInformation
,
400 sizeof(FILE_STANDARD_INFORMATION
),
403 DPRINT("Query => %x\n", Status
);
405 if (!NT_SUCCESS(Status
))
407 DPRINT("Status %x\n", Status
);
408 ObDereferenceObject(Section
);
411 ASSERT(Status
!= STATUS_PENDING
);
413 FileSizes
.ValidDataLength
= FileInfo
.EndOfFile
;
414 FileSizes
.FileSize
= FileInfo
.EndOfFile
;
416 DPRINT("Got %08x\n", FileSizes
.ValidDataLength
.u
.LowPart
);
419 * FIXME: Revise this once a locking order for file size changes is
422 * We're handed down a maximum size in every case. Should we still check at all?
424 if (UMaximumSize
!= NULL
&& UMaximumSize
->QuadPart
)
426 DPRINT("Taking maximum %x\n", UMaximumSize
->LowPart
);
427 MaximumSize
.QuadPart
= UMaximumSize
->QuadPart
;
431 DPRINT("Got file size %08x%08x\n", FileSizes
.FileSize
.u
.HighPart
, FileSizes
.FileSize
.u
.LowPart
);
432 MaximumSize
.QuadPart
= FileSizes
.FileSize
.QuadPart
;
435 /* Mapping zero-sized files isn't allowed. */
436 if (MaximumSize
.QuadPart
== 0)
438 DPRINT("Zero size file\n");
439 ObDereferenceObject(Section
);
440 return STATUS_FILE_INVALID
;
443 Segment
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(MM_SECTION_SEGMENT
),
444 TAG_MM_SECTION_SEGMENT
);
447 DPRINT("Failed: STATUS_NO_MEMORY\n");
448 ObDereferenceObject(Section
);
449 return(STATUS_NO_MEMORY
);
452 DPRINT("Zeroing %x\n", Segment
);
453 RtlZeroMemory(Segment
, sizeof(MM_SECTION_SEGMENT
));
454 ExInitializeFastMutex(&Segment
->Lock
);
456 Segment
->ReferenceCount
= 1;
457 Segment
->Locked
= TRUE
;
458 RtlZeroMemory(&Segment
->Image
, sizeof(Segment
->Image
));
459 Section
->Segment
= Segment
;
461 KeAcquireSpinLock(&FileObject
->IrpListLock
, &OldIrql
);
463 * If this file hasn't been mapped as a data file before then allocate a
464 * section segment to describe the data file mapping
466 if (FileObject
->SectionObjectPointer
->DataSectionObject
== NULL
)
468 FileObject
->SectionObjectPointer
->DataSectionObject
= (PVOID
)Segment
;
469 KeReleaseSpinLock(&FileObject
->IrpListLock
, OldIrql
);
472 * Set the lock before assigning the segment to the file object
474 ExAcquireFastMutex(&Segment
->Lock
);
476 DPRINT("Filling out Segment info (No previous data section)\n");
477 ObReferenceObject(FileObject
);
478 Segment
->FileObject
= FileObject
;
479 Segment
->Protection
= SectionPageProtection
;
480 Segment
->Flags
= MM_DATAFILE_SEGMENT
;
481 memset(&Segment
->Image
, 0, sizeof(Segment
->Image
));
482 Segment
->WriteCopy
= FALSE
;
484 if (AllocationAttributes
& SEC_RESERVE
)
486 Segment
->Length
.QuadPart
= Segment
->RawLength
.QuadPart
= 0;
490 Segment
->RawLength
.QuadPart
= MaximumSize
.QuadPart
;
491 Segment
->Length
.QuadPart
= PAGE_ROUND_UP(Segment
->RawLength
.QuadPart
);
493 MiInitializeSectionPageTable(Segment
);
494 InsertHeadList(&MiSegmentList
, &Segment
->ListOfSegments
);
498 KeReleaseSpinLock(&FileObject
->IrpListLock
, OldIrql
);
499 DPRINTC("Free Segment %x\n", Segment
);
502 DPRINT("Filling out Segment info (previous data section)\n");
505 * If the file is already mapped as a data file then we may need
509 (PMM_SECTION_SEGMENT
)FileObject
->SectionObjectPointer
->
511 Section
->Segment
= Segment
;
512 (void)InterlockedIncrementUL(&Segment
->ReferenceCount
);
514 MmLockSectionSegment(Segment
);
516 if (MaximumSize
.QuadPart
> Segment
->RawLength
.QuadPart
&&
517 !(AllocationAttributes
& SEC_RESERVE
))
519 Segment
->RawLength
.QuadPart
= MaximumSize
.QuadPart
;
520 Segment
->Length
.QuadPart
= PAGE_ROUND_UP(Segment
->RawLength
.QuadPart
);
524 MmUnlockSectionSegment(Segment
);
526 Section
->MaximumSize
.QuadPart
= MaximumSize
.QuadPart
;
528 /* Extend file if section is longer */
529 DPRINT("MaximumSize %08x%08x ValidDataLength %08x%08x\n",
530 MaximumSize
.u
.HighPart
, MaximumSize
.u
.LowPart
,
531 FileSizes
.ValidDataLength
.u
.HighPart
, FileSizes
.ValidDataLength
.u
.LowPart
);
532 if (MaximumSize
.QuadPart
> FileSizes
.ValidDataLength
.QuadPart
)
534 DPRINT("Changing file size to %08x%08x, segment %x\n", MaximumSize
.u
.HighPart
, MaximumSize
.u
.LowPart
, Segment
);
535 Status
= IoSetInformation(FileObject
, FileEndOfFileInformation
, sizeof(LARGE_INTEGER
), &MaximumSize
);
536 DPRINT("Change: Status %x\n", Status
);
537 if (!NT_SUCCESS(Status
))
539 DPRINT("Could not expand section\n");
540 ObDereferenceObject(Section
);
545 DPRINTC("Segment %x created (%x)\n", Segment
, Segment
->Flags
);
547 *SectionObject
= Section
;
548 return(STATUS_SUCCESS
);
554 (PMMSUPPORT AddressSpace
,
555 PMM_SECTION_SEGMENT Segment
,
559 PLARGE_INTEGER ViewOffset
,
560 ULONG AllocationType
,
566 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
568 BoundaryAddressMultiple
.QuadPart
= 0;
570 Status
= MmCreateMemoryArea
579 BoundaryAddressMultiple
);
581 if (!NT_SUCCESS(Status
))
583 DPRINT("Mapping between 0x%.8X and 0x%.8X failed (%X).\n",
584 (*BaseAddress
), (char*)(*BaseAddress
) + ViewSize
, Status
);
588 DPRINTC("MiMapViewOfSegment %x %x %x %x %x %wZ %s:%d\n", MmGetAddressSpaceOwner(AddressSpace
), *BaseAddress
, Segment
, ViewOffset
? ViewOffset
->LowPart
: 0, ViewSize
, Segment
->FileObject
? &Segment
->FileObject
->FileName
: NULL
, file
, line
);
590 MArea
->Data
.SectionData
.Segment
= Segment
;
592 MArea
->Data
.SectionData
.ViewOffset
= *ViewOffset
;
594 MArea
->Data
.SectionData
.ViewOffset
.QuadPart
= 0;
597 MArea
->NotPresent
= MmNotPresentFaultPageFile
;
598 MArea
->AccessFault
= MiCowSectionPage
;
599 MArea
->PageOut
= MmPageOutPageFileView
;
602 MmInitializeRegion(&MArea
->Data
.SectionData
.RegionListHead
,
603 ViewSize
, 0, Protect
);
606 ("MiMapViewOfSegment(P %x, A %x, T %x)\n",
607 MmGetAddressSpaceOwner(AddressSpace
), *BaseAddress
, MArea
->Type
);
609 return(STATUS_SUCCESS
);
615 (PMM_SECTION_SEGMENT Segment
,
616 PLARGE_INTEGER FileOffset
)
619 PFILE_OBJECT FileObject
= Segment
->FileObject
;
621 Entry
= MmGetPageEntrySectionSegment(Segment
, FileOffset
);
622 DPRINTC("MiFreeSegmentPage(%x:%08x%08x -> Entry %x\n",
623 Segment
, FileOffset
->HighPart
, FileOffset
->LowPart
, Entry
);
625 if (Entry
&& !IS_SWAP_FROM_SSE(Entry
))
627 // The segment is carrying a dirty page.
628 PFN_NUMBER OldPage
= PFN_FROM_SSE(Entry
);
629 if (IS_DIRTY_SSE(Entry
) && FileObject
)
631 DPRINT("MiWriteBackPage(%x,%wZ,%08x%08x)\n", Segment
, &FileObject
->FileName
, FileOffset
->u
.HighPart
, FileOffset
->u
.LowPart
);
632 MiWriteBackPage(FileObject
, FileOffset
, PAGE_SIZE
, OldPage
);
634 DPRINTC("Free page %x (off %x from %x) (ref ct %d, ent %x, dirty? %s)\n", OldPage
, FileOffset
->LowPart
, Segment
, MmGetReferenceCountPage(OldPage
), Entry
, IS_DIRTY_SSE(Entry
) ? "true" : "false");
636 MmSetPageEntrySectionSegment(Segment
, FileOffset
, 0);
637 MmReleasePageMemoryConsumer(MC_CACHE
, OldPage
);
639 else if (IS_SWAP_FROM_SSE(Entry
))
641 DPRINT("Free swap\n");
642 MmFreeSwapPage(SWAPENTRY_FROM_SSE(Entry
));
649 MmFreeCacheSectionPage
650 (PVOID Context
, MEMORY_AREA
* MemoryArea
, PVOID Address
,
651 PFN_NUMBER Page
, SWAPENTRY SwapEntry
, BOOLEAN Dirty
)
654 PVOID
*ContextData
= Context
;
655 PMMSUPPORT AddressSpace
;
657 PMM_SECTION_SEGMENT Segment
;
658 LARGE_INTEGER Offset
;
660 DPRINT("MmFreeSectionPage(%x,%x,%x,%x,%d)\n", MmGetAddressSpaceOwner(ContextData
[0]), Address
, Page
, SwapEntry
, Dirty
);
662 AddressSpace
= ContextData
[0];
663 Process
= MmGetAddressSpaceOwner(AddressSpace
);
664 Address
= (PVOID
)PAGE_ROUND_DOWN(Address
);
665 Segment
= ContextData
[1];
666 Offset
.QuadPart
= (ULONG_PTR
)Address
- (ULONG_PTR
)MemoryArea
->StartingAddress
+
667 MemoryArea
->Data
.SectionData
.ViewOffset
.QuadPart
;
669 Entry
= MmGetPageEntrySectionSegment(Segment
, &Offset
);
671 if (Page
!= 0 && PFN_FROM_SSE(Entry
) == Page
&& Dirty
)
673 DPRINT("Freeing section page %x:%x -> %x\n", Segment
, Offset
.LowPart
, Entry
);
674 MmSetPageEntrySectionSegment(Segment
, &Offset
, DIRTY_SSE(Entry
));
678 DPRINT("Removing page %x:%x -> %x\n", Segment
, Offset
.LowPart
, Entry
);
679 MmSetSavedSwapEntryPage(Page
, 0);
680 MmDeleteRmap(Page
, Process
, Address
);
681 MmDeleteVirtualMapping(Process
, Address
, FALSE
, NULL
, NULL
);
682 MmReleasePageMemoryConsumer(MC_CACHE
, Page
);
686 MmFreeSwapPage(SwapEntry
);
692 MmUnmapViewOfCacheSegment
693 (PMMSUPPORT AddressSpace
,
697 PMEMORY_AREA MemoryArea
;
698 PMM_SECTION_SEGMENT Segment
;
700 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, BaseAddress
);
701 if (MemoryArea
== NULL
)
704 return(STATUS_UNSUCCESSFUL
);
707 MemoryArea
->DeleteInProgress
= TRUE
;
708 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
709 MemoryArea
->Data
.SectionData
.Segment
= NULL
;
711 MmLockSectionSegment(Segment
);
713 Context
[0] = AddressSpace
;
714 Context
[1] = Segment
;
715 DPRINT("MmFreeMemoryArea(%x,%x)\n", MmGetAddressSpaceOwner(AddressSpace
), MemoryArea
->StartingAddress
);
716 MmFreeMemoryArea(AddressSpace
, MemoryArea
, MmFreeCacheSectionPage
, Context
);
718 MmUnlockSectionSegment(Segment
);
720 DPRINTC("MiUnmapViewOfSegment %x %x %x\n", MmGetAddressSpaceOwner(AddressSpace
), BaseAddress
, Segment
);
722 return(STATUS_SUCCESS
);
728 (PROS_SECTION_OBJECT Section
,
729 PLARGE_INTEGER NewSize
,
732 LARGE_INTEGER OldSize
;
733 PMM_SECTION_SEGMENT Segment
= Section
->Segment
;
734 DPRINT("Extend Segment %x\n", Segment
);
736 MmLockSectionSegment(Segment
);
737 OldSize
.QuadPart
= Segment
->RawLength
.QuadPart
;
738 MmUnlockSectionSegment(Segment
);
740 DPRINT("OldSize %08x%08x NewSize %08x%08x\n",
741 OldSize
.u
.HighPart
, OldSize
.u
.LowPart
,
742 NewSize
->u
.HighPart
, NewSize
->u
.LowPart
);
744 if (ExtendFile
&& OldSize
.QuadPart
< NewSize
->QuadPart
)
747 Status
= IoSetInformation(Segment
->FileObject
, FileEndOfFileInformation
, sizeof(LARGE_INTEGER
), NewSize
);
748 if (!NT_SUCCESS(Status
)) return Status
;
751 MmLockSectionSegment(Segment
);
752 Segment
->RawLength
.QuadPart
= NewSize
->QuadPart
;
753 Segment
->Length
.QuadPart
= MAX(Segment
->Length
.QuadPart
, PAGE_ROUND_UP(Segment
->RawLength
.LowPart
));
754 MmUnlockSectionSegment(Segment
);
755 return STATUS_SUCCESS
;
760 MmMapCacheViewInSystemSpaceAtOffset
761 (IN PMM_SECTION_SEGMENT Segment
,
762 OUT PVOID
*MappedBase
,
763 PLARGE_INTEGER FileOffset
,
764 IN OUT PULONG ViewSize
)
766 PMMSUPPORT AddressSpace
;
769 DPRINT("MmMapViewInSystemSpaceAtOffset() called offset %08x%08x\n", FileOffset
->HighPart
, FileOffset
->LowPart
);
771 AddressSpace
= MmGetKernelAddressSpace();
773 MmLockAddressSpace(AddressSpace
);
774 MmLockSectionSegment(Segment
);
776 Status
= MiMapViewOfSegment
785 MmUnlockSectionSegment(Segment
);
786 MmUnlockAddressSpace(AddressSpace
);
795 MmUnmapCacheViewInSystemSpace (IN PVOID MappedBase
)
797 PMMSUPPORT AddressSpace
;
800 DPRINT("MmUnmapViewInSystemSpace() called\n");
802 AddressSpace
= MmGetKernelAddressSpace();
804 Status
= MmUnmapViewOfCacheSegment(AddressSpace
, MappedBase
);