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);
97 MiZeroFillSection(PVOID Address
, PLARGE_INTEGER FileOffsetPtr
, ULONG Length
)
100 PMMSUPPORT AddressSpace
;
101 PMEMORY_AREA MemoryArea
;
102 PMM_SECTION_SEGMENT Segment
;
103 LARGE_INTEGER FileOffset
= *FileOffsetPtr
, End
, FirstMapped
;
106 DPRINT("MiZeroFillSection(Address %x,Offset %x,Length %x)\n",
111 AddressSpace
= MmGetKernelAddressSpace();
113 MmLockAddressSpace(AddressSpace
);
114 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, Address
);
115 MmUnlockAddressSpace(AddressSpace
);
116 if (!MemoryArea
|| MemoryArea
->Type
!= MEMORY_AREA_SECTION_VIEW
|| MemoryArea
->DeleteInProgress
)
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
;
126 DPRINT("Pulling zero pages for %08x%08x-%08x%08x\n",
127 FileOffset
.u
.HighPart
, FileOffset
.u
.LowPart
,
128 End
.u
.HighPart
, End
.u
.LowPart
);
129 while (FileOffset
.QuadPart
< End
.QuadPart
)
134 if (!NT_SUCCESS(MmRequestPageMemoryConsumer(MC_CACHE
, TRUE
, &Page
)))
137 MmLockAddressSpace(AddressSpace
);
138 MmLockSectionSegment(Segment
);
140 Entry
= MmGetPageEntrySectionSegment(Segment
, &FileOffset
);
143 MmSetPageEntrySectionSegment(Segment
, &FileOffset
, MAKE_PFN_SSE(Page
));
144 Address
= ((PCHAR
)MemoryArea
->StartingAddress
) + FileOffset
.QuadPart
- FirstMapped
.QuadPart
;
146 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
147 MmReferencePage(Page
);
148 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
150 MmCreateVirtualMapping(NULL
, Address
, PAGE_READWRITE
, &Page
, 1);
151 MmInsertRmap(Page
, NULL
, Address
);
155 MmReleasePageMemoryConsumer(MC_CACHE
, Page
);
158 MmUnlockSectionSegment(Segment
);
159 MmUnlockAddressSpace(AddressSpace
);
161 FileOffset
.QuadPart
+= PAGE_SIZE
;
163 return STATUS_SUCCESS
;
168 _MiFlushMappedSection(PVOID BaseAddress
,
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",
195 MmLockAddressSpace(AddressSpace
);
196 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, BaseAddress
);
197 if (!MemoryArea
|| MemoryArea
->Type
!= MEMORY_AREA_CACHE
|| MemoryArea
->DeleteInProgress
)
199 MmUnlockAddressSpace(AddressSpace
);
200 DPRINT("STATUS_NOT_MAPPED_DATA\n");
201 return STATUS_NOT_MAPPED_DATA
;
203 BeginningAddress
= PAGE_ROUND_DOWN((ULONG_PTR
)MemoryArea
->StartingAddress
);
204 EndingAddress
= PAGE_ROUND_UP((ULONG_PTR
)MemoryArea
->EndingAddress
);
205 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
206 ViewOffset
.QuadPart
= MemoryArea
->Data
.SectionData
.ViewOffset
.QuadPart
;
208 ASSERT(ViewOffset
.QuadPart
== BaseOffset
->QuadPart
);
210 MmLockSectionSegment(Segment
);
212 Pages
= ExAllocatePool(NonPagedPool
,
213 sizeof(PFN_NUMBER
) * ((EndingAddress
- BeginningAddress
) >> PAGE_SHIFT
));
220 //DPRINT("Getting pages in range %08x-%08x\n", BeginningAddress, EndingAddress);
222 for (PageAddress
= BeginningAddress
;
223 PageAddress
< EndingAddress
;
224 PageAddress
+= PAGE_SIZE
)
227 FileOffset
.QuadPart
= ViewOffset
.QuadPart
+ PageAddress
- BeginningAddress
;
228 Entry
= MmGetPageEntrySectionSegment(MemoryArea
->Data
.SectionData
.Segment
,
230 Page
= PFN_FROM_SSE(Entry
);
231 if (Entry
!= 0 && !IS_SWAP_FROM_SSE(Entry
) &&
232 (MmIsDirtyPageRmap(Page
) || IS_DIRTY_SSE(Entry
)) &&
233 FileOffset
.QuadPart
< FileSize
->QuadPart
)
235 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
236 MmReferencePage(Page
);
237 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
238 Pages
[(PageAddress
- BeginningAddress
) >> PAGE_SHIFT
] = Entry
;
242 Pages
[(PageAddress
- BeginningAddress
) >> PAGE_SHIFT
] = 0;
246 MmUnlockSectionSegment(Segment
);
247 MmUnlockAddressSpace(AddressSpace
);
249 for (PageAddress
= BeginningAddress
;
250 PageAddress
< EndingAddress
;
251 PageAddress
+= PAGE_SIZE
)
254 FileOffset
.QuadPart
= ViewOffset
.QuadPart
+ PageAddress
- BeginningAddress
;
255 Entry
= Pages
[(PageAddress
- BeginningAddress
) >> PAGE_SHIFT
];
256 Page
= PFN_FROM_SSE(Entry
);
260 //DPRINT("MiWriteBackPage(%wZ,addr %x,%08x%08x)\n", &Segment->FileObject->FileName, PageAddress, FileOffset.u.HighPart, FileOffset.u.LowPart);
261 Status
= MiWriteBackPage(Segment
->FileObject
, &FileOffset
, PAGE_SIZE
, Page
);
263 Status
= STATUS_SUCCESS
;
265 if (NT_SUCCESS(Status
)) {
266 MmLockAddressSpace(AddressSpace
);
267 MmSetCleanAllRmaps(Page
);
269 MmSetPageProtect(MmGetAddressSpaceOwner(AddressSpace
),
273 MmLockSectionSegment(Segment
);
274 Entry
= MmGetPageEntrySectionSegment(Segment
, &FileOffset
);
276 if (Entry
&& !IS_SWAP_FROM_SSE(Entry
) && PFN_FROM_SSE(Entry
) == Page
)
277 MmSetPageEntrySectionSegment(Segment
, &FileOffset
, CLEAN_SSE(Entry
));
279 MmUnlockSectionSegment(Segment
);
280 MmUnlockAddressSpace(AddressSpace
);
282 DPRINT("Writeback from section flush %08x%08x (%x) %x@%x (%08x%08x:%wZ) failed %x\n",
283 FileOffset
.u
.HighPart
,
284 FileOffset
.u
.LowPart
,
285 (ULONG
)(FileSize
->QuadPart
- FileOffset
.QuadPart
),
288 FileSize
->u
.HighPart
,
290 &Segment
->FileObject
->FileName
,
293 MmReleasePageMemoryConsumer(MC_CACHE
, Page
);
304 MmFinalizeSegment(PMM_SECTION_SEGMENT Segment
)
308 DPRINT("Finalize segment %p\n", Segment
);
310 MmLockSectionSegment(Segment
);
311 RemoveEntryList(&Segment
->ListOfSegments
);
312 if (Segment
->Flags
& MM_DATAFILE_SEGMENT
) {
313 KeAcquireSpinLock(&Segment
->FileObject
->IrpListLock
, &OldIrql
);
314 if (Segment
->Flags
& MM_SEGMENT_FINALIZE
) {
315 KeReleaseSpinLock(&Segment
->FileObject
->IrpListLock
, OldIrql
);
316 MmUnlockSectionSegment(Segment
);
319 Segment
->Flags
|= MM_SEGMENT_FINALIZE
;
320 DPRINTC("Finalizing data file segment %p\n", Segment
);
322 Segment
->FileObject
->SectionObjectPointer
->DataSectionObject
= NULL
;
323 KeReleaseSpinLock(&Segment
->FileObject
->IrpListLock
, OldIrql
);
324 MmFreePageTablesSectionSegment(Segment
, MiFreeSegmentPage
);
325 MmUnlockSectionSegment(Segment
);
326 DPRINT("Dereference file object %wZ\n", &Segment
->FileObject
->FileName
);
327 ObDereferenceObject(Segment
->FileObject
);
328 DPRINT("Done with %wZ\n", &Segment
->FileObject
->FileName
);
329 Segment
->FileObject
= NULL
;
331 DPRINTC("Finalizing segment %p\n", Segment
);
332 MmFreePageTablesSectionSegment(Segment
, MiFreeSegmentPage
);
333 MmUnlockSectionSegment(Segment
);
335 DPRINTC("Segment %p destroy\n", Segment
);
336 ExFreePoolWithTag(Segment
, TAG_MM_SECTION_SEGMENT
);
341 MmCreateCacheSection(PROS_SECTION_OBJECT
*SectionObject
,
342 ACCESS_MASK DesiredAccess
,
343 POBJECT_ATTRIBUTES ObjectAttributes
,
344 PLARGE_INTEGER UMaximumSize
,
345 ULONG SectionPageProtection
,
346 ULONG AllocationAttributes
,
347 PFILE_OBJECT FileObject
)
349 * Create a section backed by a data file
352 PROS_SECTION_OBJECT Section
;
354 LARGE_INTEGER MaximumSize
;
355 PMM_SECTION_SEGMENT Segment
;
356 IO_STATUS_BLOCK Iosb
;
357 CC_FILE_SIZES FileSizes
;
358 FILE_STANDARD_INFORMATION FileInfo
;
361 DPRINT("MmCreateDataFileSection\n");
363 /* Create the section */
364 Status
= ObCreateObject(ExGetPreviousMode(),
369 sizeof(ROS_SECTION_OBJECT
),
372 (PVOID
*)(PVOID
)&Section
);
373 if (!NT_SUCCESS(Status
))
375 DPRINT("Failed: %x\n", Status
);
380 RtlZeroMemory(Section
, sizeof(ROS_SECTION_OBJECT
));
381 Section
->Type
= 'SC';
382 Section
->Size
= 'TN';
383 Section
->SectionPageProtection
= SectionPageProtection
;
384 Section
->AllocationAttributes
= AllocationAttributes
;
385 Section
->Segment
= NULL
;
387 Section
->FileObject
= FileObject
;
389 DPRINT("Getting original file size\n");
390 /* A hack: If we're cached, we can overcome deadlocking with the upper
391 * layer filesystem call by retriving the object sizes from the cache
392 * which is made to keep track. If I had to guess, they were figuring
393 * out a similar problem.
395 if (!CcGetFileSizes(FileObject
, &FileSizes
))
399 * FIXME: This is propably not entirely correct. We can't look into
400 * the standard FCB header because it might not be initialized yet
401 * (as in case of the EXT2FS driver by Manoj Paul Joseph where the
402 * standard file information is filled on first request).
404 DPRINT("Querying info\n");
405 Status
= IoQueryFileInformation(FileObject
,
406 FileStandardInformation
,
407 sizeof(FILE_STANDARD_INFORMATION
),
410 Iosb
.Information
= Information
;
411 DPRINT("Query => %x\n", Status
);
413 if (!NT_SUCCESS(Status
))
415 DPRINT("Status %x\n", Status
);
416 ObDereferenceObject(Section
);
419 ASSERT(Status
!= STATUS_PENDING
);
421 FileSizes
.ValidDataLength
= FileInfo
.EndOfFile
;
422 FileSizes
.FileSize
= FileInfo
.EndOfFile
;
424 DPRINT("Got %08x\n", FileSizes
.ValidDataLength
.u
.LowPart
);
427 * FIXME: Revise this once a locking order for file size changes is
430 * We're handed down a maximum size in every case. Should we still check at all?
432 if (UMaximumSize
!= NULL
&& UMaximumSize
->QuadPart
)
434 DPRINT("Taking maximum %x\n", UMaximumSize
->LowPart
);
435 MaximumSize
.QuadPart
= UMaximumSize
->QuadPart
;
439 DPRINT("Got file size %08x%08x\n",
440 FileSizes
.FileSize
.u
.HighPart
,
441 FileSizes
.FileSize
.u
.LowPart
);
443 MaximumSize
.QuadPart
= FileSizes
.FileSize
.QuadPart
;
446 /* Mapping zero-sized files isn't allowed. */
447 if (MaximumSize
.QuadPart
== 0)
449 DPRINT("Zero size file\n");
450 ObDereferenceObject(Section
);
451 return STATUS_FILE_INVALID
;
454 Segment
= ExAllocatePoolWithTag(NonPagedPool
,
455 sizeof(MM_SECTION_SEGMENT
),
456 TAG_MM_SECTION_SEGMENT
);
459 DPRINT("Failed: STATUS_NO_MEMORY\n");
460 ObDereferenceObject(Section
);
461 return STATUS_NO_MEMORY
;
464 DPRINT("Zeroing %x\n", Segment
);
465 RtlZeroMemory(Segment
, sizeof(MM_SECTION_SEGMENT
));
466 ExInitializeFastMutex(&Segment
->Lock
);
468 Segment
->ReferenceCount
= 1;
469 Segment
->Locked
= TRUE
;
470 RtlZeroMemory(&Segment
->Image
, sizeof(Segment
->Image
));
471 Section
->Segment
= Segment
;
473 KeAcquireSpinLock(&FileObject
->IrpListLock
, &OldIrql
);
475 * If this file hasn't been mapped as a data file before then allocate a
476 * section segment to describe the data file mapping
478 if (FileObject
->SectionObjectPointer
->DataSectionObject
== NULL
)
480 FileObject
->SectionObjectPointer
->DataSectionObject
= (PVOID
)Segment
;
481 KeReleaseSpinLock(&FileObject
->IrpListLock
, OldIrql
);
484 * Set the lock before assigning the segment to the file object
486 ExAcquireFastMutex(&Segment
->Lock
);
488 DPRINT("Filling out Segment info (No previous data section)\n");
489 ObReferenceObject(FileObject
);
490 Segment
->FileObject
= FileObject
;
491 Segment
->Protection
= SectionPageProtection
;
492 Segment
->Flags
= MM_DATAFILE_SEGMENT
;
493 memset(&Segment
->Image
, 0, sizeof(Segment
->Image
));
494 Segment
->WriteCopy
= FALSE
;
496 if (AllocationAttributes
& SEC_RESERVE
)
498 Segment
->Length
.QuadPart
= Segment
->RawLength
.QuadPart
= 0;
502 Segment
->RawLength
.QuadPart
= MaximumSize
.QuadPart
;
503 Segment
->Length
.QuadPart
= PAGE_ROUND_UP(Segment
->RawLength
.QuadPart
);
505 MiInitializeSectionPageTable(Segment
);
506 InsertHeadList(&MiSegmentList
, &Segment
->ListOfSegments
);
510 KeReleaseSpinLock(&FileObject
->IrpListLock
, OldIrql
);
511 DPRINTC("Free Segment %x\n", Segment
);
514 DPRINT("Filling out Segment info (previous data section)\n");
517 * If the file is already mapped as a data file then we may need
520 Segment
= (PMM_SECTION_SEGMENT
)FileObject
->SectionObjectPointer
->DataSectionObject
;
521 Section
->Segment
= Segment
;
522 (void)InterlockedIncrementUL(&Segment
->ReferenceCount
);
524 MmLockSectionSegment(Segment
);
526 if (MaximumSize
.QuadPart
> Segment
->RawLength
.QuadPart
&&
527 !(AllocationAttributes
& SEC_RESERVE
))
529 Segment
->RawLength
.QuadPart
= MaximumSize
.QuadPart
;
530 Segment
->Length
.QuadPart
= PAGE_ROUND_UP(Segment
->RawLength
.QuadPart
);
534 MmUnlockSectionSegment(Segment
);
536 Section
->MaximumSize
.QuadPart
= MaximumSize
.QuadPart
;
538 /* Extend file if section is longer */
539 DPRINT("MaximumSize %08x%08x ValidDataLength %08x%08x\n",
540 MaximumSize
.u
.HighPart
,
541 MaximumSize
.u
.LowPart
,
542 FileSizes
.ValidDataLength
.u
.HighPart
,
543 FileSizes
.ValidDataLength
.u
.LowPart
);
544 if (MaximumSize
.QuadPart
> FileSizes
.ValidDataLength
.QuadPart
)
546 DPRINT("Changing file size to %08x%08x, segment %x\n",
547 MaximumSize
.u
.HighPart
,
548 MaximumSize
.u
.LowPart
,
551 Status
= IoSetInformation(FileObject
,
552 FileEndOfFileInformation
,
553 sizeof(LARGE_INTEGER
),
556 DPRINT("Change: Status %x\n", Status
);
557 if (!NT_SUCCESS(Status
))
559 DPRINT("Could not expand section\n");
560 ObDereferenceObject(Section
);
565 DPRINTC("Segment %x created (%x)\n", Segment
, Segment
->Flags
);
567 *SectionObject
= Section
;
568 return STATUS_SUCCESS
;
573 _MiMapViewOfSegment(PMMSUPPORT AddressSpace
,
574 PMM_SECTION_SEGMENT Segment
,
578 PLARGE_INTEGER ViewOffset
,
579 ULONG AllocationType
,
585 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
587 BoundaryAddressMultiple
.QuadPart
= 0;
589 Status
= MmCreateMemoryArea(AddressSpace
,
597 BoundaryAddressMultiple
);
599 if (!NT_SUCCESS(Status
))
601 DPRINT("Mapping between 0x%.8X and 0x%.8X failed (%X).\n",
603 (char*)(*BaseAddress
) + ViewSize
,
609 DPRINTC("MiMapViewOfSegment %x %x %x %x %x %wZ %s:%d\n",
610 MmGetAddressSpaceOwner(AddressSpace
),
613 ViewOffset
? ViewOffset
->LowPart
: 0,
615 Segment
->FileObject
? &Segment
->FileObject
->FileName
: NULL
,
619 MArea
->Data
.SectionData
.Segment
= Segment
;
621 MArea
->Data
.SectionData
.ViewOffset
= *ViewOffset
;
623 MArea
->Data
.SectionData
.ViewOffset
.QuadPart
= 0;
626 MArea
->NotPresent
= MmNotPresentFaultPageFile
;
627 MArea
->AccessFault
= MiCowSectionPage
;
628 MArea
->PageOut
= MmPageOutPageFileView
;
631 MmInitializeRegion(&MArea
->Data
.SectionData
.RegionListHead
,
636 DPRINTC("MiMapViewOfSegment(P %x, A %x, T %x)\n",
637 MmGetAddressSpaceOwner(AddressSpace
),
641 return STATUS_SUCCESS
;
646 MiFreeSegmentPage(PMM_SECTION_SEGMENT Segment
,
647 PLARGE_INTEGER FileOffset
)
650 PFILE_OBJECT FileObject
= Segment
->FileObject
;
652 Entry
= MmGetPageEntrySectionSegment(Segment
, FileOffset
);
653 DPRINTC("MiFreeSegmentPage(%x:%08x%08x -> Entry %x\n",
655 FileOffset
->HighPart
,
659 if (Entry
&& !IS_SWAP_FROM_SSE(Entry
))
661 // The segment is carrying a dirty page.
662 PFN_NUMBER OldPage
= PFN_FROM_SSE(Entry
);
663 if (IS_DIRTY_SSE(Entry
) && FileObject
)
665 DPRINT("MiWriteBackPage(%x,%wZ,%08x%08x)\n",
667 &FileObject
->FileName
,
668 FileOffset
->u
.HighPart
,
669 FileOffset
->u
.LowPart
);
671 MiWriteBackPage(FileObject
, FileOffset
, PAGE_SIZE
, OldPage
);
673 DPRINTC("Free page %x (off %x from %x) (ref ct %d, ent %x, dirty? %s)\n",
677 MmGetReferenceCountPage(OldPage
),
679 IS_DIRTY_SSE(Entry
) ? "true" : "false");
681 MmSetPageEntrySectionSegment(Segment
, FileOffset
, 0);
682 MmReleasePageMemoryConsumer(MC_CACHE
, OldPage
);
684 else if (IS_SWAP_FROM_SSE(Entry
))
686 DPRINT("Free swap\n");
687 MmFreeSwapPage(SWAPENTRY_FROM_SSE(Entry
));
694 MmFreeCacheSectionPage(PVOID Context
,
695 MEMORY_AREA
* MemoryArea
,
702 PVOID
*ContextData
= Context
;
703 PMMSUPPORT AddressSpace
;
705 PMM_SECTION_SEGMENT Segment
;
706 LARGE_INTEGER Offset
;
708 DPRINT("MmFreeSectionPage(%x,%x,%x,%x,%d)\n",
709 MmGetAddressSpaceOwner(ContextData
[0]),
715 AddressSpace
= ContextData
[0];
716 Process
= MmGetAddressSpaceOwner(AddressSpace
);
717 Address
= (PVOID
)PAGE_ROUND_DOWN(Address
);
718 Segment
= ContextData
[1];
719 Offset
.QuadPart
= (ULONG_PTR
)Address
- (ULONG_PTR
)MemoryArea
->StartingAddress
+
720 MemoryArea
->Data
.SectionData
.ViewOffset
.QuadPart
;
722 Entry
= MmGetPageEntrySectionSegment(Segment
, &Offset
);
724 if (Page
!= 0 && PFN_FROM_SSE(Entry
) == Page
&& Dirty
)
726 DPRINT("Freeing section page %x:%x -> %x\n", Segment
, Offset
.LowPart
, Entry
);
727 MmSetPageEntrySectionSegment(Segment
, &Offset
, DIRTY_SSE(Entry
));
731 DPRINT("Removing page %x:%x -> %x\n", Segment
, Offset
.LowPart
, Entry
);
732 MmSetSavedSwapEntryPage(Page
, 0);
733 MmDeleteRmap(Page
, Process
, Address
);
734 MmDeleteVirtualMapping(Process
, Address
, FALSE
, NULL
, NULL
);
735 MmReleasePageMemoryConsumer(MC_CACHE
, Page
);
739 MmFreeSwapPage(SwapEntry
);
745 MmUnmapViewOfCacheSegment(PMMSUPPORT AddressSpace
,
749 PMEMORY_AREA MemoryArea
;
750 PMM_SECTION_SEGMENT Segment
;
752 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, BaseAddress
);
753 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
756 return STATUS_UNSUCCESSFUL
;
759 MemoryArea
->DeleteInProgress
= TRUE
;
760 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
761 MemoryArea
->Data
.SectionData
.Segment
= NULL
;
763 MmLockSectionSegment(Segment
);
765 Context
[0] = AddressSpace
;
766 Context
[1] = Segment
;
768 DPRINT("MmFreeMemoryArea(%x,%x)\n",
769 MmGetAddressSpaceOwner(AddressSpace
),
770 MemoryArea
->StartingAddress
);
772 MmFreeMemoryArea(AddressSpace
, MemoryArea
, MmFreeCacheSectionPage
, Context
);
774 MmUnlockSectionSegment(Segment
);
776 DPRINTC("MiUnmapViewOfSegment %x %x %x\n",
777 MmGetAddressSpaceOwner(AddressSpace
),
781 return STATUS_SUCCESS
;
786 MmExtendCacheSection(PROS_SECTION_OBJECT Section
,
787 PLARGE_INTEGER NewSize
,
790 LARGE_INTEGER OldSize
;
791 PMM_SECTION_SEGMENT Segment
= Section
->Segment
;
792 DPRINT("Extend Segment %x\n", Segment
);
794 MmLockSectionSegment(Segment
);
795 OldSize
.QuadPart
= Segment
->RawLength
.QuadPart
;
796 MmUnlockSectionSegment(Segment
);
798 DPRINT("OldSize %08x%08x NewSize %08x%08x\n",
799 OldSize
.u
.HighPart
, OldSize
.u
.LowPart
,
800 NewSize
->u
.HighPart
, NewSize
->u
.LowPart
);
802 if (ExtendFile
&& OldSize
.QuadPart
< NewSize
->QuadPart
)
806 Status
= IoSetInformation(Segment
->FileObject
,
807 FileEndOfFileInformation
,
808 sizeof(LARGE_INTEGER
),
811 if (!NT_SUCCESS(Status
)) return Status
;
814 MmLockSectionSegment(Segment
);
815 Segment
->RawLength
.QuadPart
= NewSize
->QuadPart
;
816 Segment
->Length
.QuadPart
= MAX(Segment
->Length
.QuadPart
,
817 PAGE_ROUND_UP(Segment
->RawLength
.LowPart
));
818 MmUnlockSectionSegment(Segment
);
819 return STATUS_SUCCESS
;
824 MmMapCacheViewInSystemSpaceAtOffset(IN PMM_SECTION_SEGMENT Segment
,
825 OUT PVOID
*MappedBase
,
826 PLARGE_INTEGER FileOffset
,
827 IN OUT PULONG ViewSize
)
829 PMMSUPPORT AddressSpace
;
832 DPRINT("MmMapViewInSystemSpaceAtOffset() called offset %08x%08x\n",
833 FileOffset
->HighPart
,
834 FileOffset
->LowPart
);
836 AddressSpace
= MmGetKernelAddressSpace();
838 MmLockAddressSpace(AddressSpace
);
839 MmLockSectionSegment(Segment
);
841 Status
= MiMapViewOfSegment(AddressSpace
,
849 MmUnlockSectionSegment(Segment
);
850 MmUnlockAddressSpace(AddressSpace
);
859 MmUnmapCacheViewInSystemSpace (IN PVOID MappedBase
)
861 PMMSUPPORT AddressSpace
;
864 DPRINT("MmUnmapViewInSystemSpace() called\n");
866 AddressSpace
= MmGetKernelAddressSpace();
868 Status
= MmUnmapViewOfCacheSegment(AddressSpace
, MappedBase
);