3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: section.c,v 1.149 2004/05/01 17:11:34 tamlin Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/mm/section.c
23 * PURPOSE: Implements section objects
24 * PROGRAMMER: David Welch (welch@mcmail.com)
29 /* INCLUDES *****************************************************************/
32 #define NTOS_MODE_KERNEL
34 #include <internal/mm.h>
35 #include <internal/io.h>
36 #include <internal/ob.h>
37 #include <internal/ps.h>
38 #include <internal/pool.h>
39 #include <internal/cc.h>
40 #include <ddk/ntifs.h>
41 #include <ntos/minmax.h>
42 #include <rosrtl/string.h>
43 #include <reactos/bugcodes.h>
46 #include <internal/debug.h>
48 /* TYPES *********************************************************************/
52 PSECTION_OBJECT Section
;
53 PMM_SECTION_SEGMENT Segment
;
58 MM_SECTION_PAGEOUT_CONTEXT
;
60 /* GLOBALS *******************************************************************/
62 POBJECT_TYPE EXPORTED MmSectionObjectType
= NULL
;
64 static GENERIC_MAPPING MmpSectionMapping
= {
65 STANDARD_RIGHTS_READ
| SECTION_MAP_READ
| SECTION_QUERY
,
66 STANDARD_RIGHTS_WRITE
| SECTION_MAP_WRITE
,
67 STANDARD_RIGHTS_EXECUTE
| SECTION_MAP_EXECUTE
,
70 #define TAG_MM_SECTION_SEGMENT TAG('M', 'M', 'S', 'S')
71 #define TAG_SECTION_PAGE_TABLE TAG('M', 'S', 'P', 'T')
73 #define PAGE_FROM_SSE(E) ((E) & 0xFFFFF000)
74 #define SHARE_COUNT_FROM_SSE(E) (((E) & 0x00000FFE) >> 1)
75 #define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
76 #define MAX_SHARE_COUNT 0x7FF
77 #define MAKE_SSE(P, C) ((P) | ((C) << 1))
78 #define SWAPENTRY_FROM_SSE(E) ((E) >> 1)
79 #define MAKE_SWAP_SSE(S) (((S) << 1) | 0x1)
81 /* FUNCTIONS *****************************************************************/
83 /* Note: Mmsp prefix denotes "Memory Manager Section Private". */
86 * FUNCTION: Waits in kernel mode up to ten seconds for an MM_PAGEOP event.
87 * ARGUMENTS: PMM_PAGEOP which event we should wait for.
88 * RETURNS: Status of the wait.
91 MmspWaitForPageOpCompletionEvent(PMM_PAGEOP PageOp
)
93 LARGE_INTEGER Timeout
;
94 #ifdef __GNUC__ /* TODO: Use other macro to check for suffix to use? */
96 Timeout
.QuadPart
= -100000000LL; // 10 sec
99 Timeout
.QuadPart
= -100000000; // 10 sec
102 return KeWaitForSingleObject(&PageOp
->CompletionEvent
, 0, KernelMode
, FALSE
, &Timeout
);
107 * FUNCTION: Sets the page op completion event and releases the page op.
108 * ARGUMENTS: PMM_PAGEOP.
109 * RETURNS: In shorter time than it takes you to even read this
110 * description, so don't even think about geting a mug of coffee.
113 MmspCompleteAndReleasePageOp(PMM_PAGEOP PageOp
)
115 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
116 MmReleasePageOp(PageOp
);
121 * FUNCTION: Waits in kernel mode indefinitely for a file object lock.
122 * ARGUMENTS: PFILE_OBJECT to wait for.
123 * RETURNS: Status of the wait.
126 MmspWaitForFileLock(PFILE_OBJECT File
)
128 return KeWaitForSingleObject(&File
->Lock
, 0, KernelMode
, FALSE
, NULL
);
133 MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment
)
136 if (Segment
->Length
> NR_SECTION_PAGE_TABLES
* PAGE_SIZE
)
138 for (i
= 0; i
< NR_SECTION_PAGE_TABLES
; i
++)
140 if (Segment
->PageDirectory
.PageTables
[i
] != NULL
)
142 ExFreePool(Segment
->PageDirectory
.PageTables
[i
]);
149 MmFreeSectionSegments(PFILE_OBJECT FileObject
)
151 if (FileObject
->SectionObjectPointer
->ImageSectionObject
!= NULL
)
153 PMM_IMAGE_SECTION_OBJECT ImageSectionObject
;
154 PMM_SECTION_SEGMENT SectionSegments
;
158 ImageSectionObject
= (PMM_IMAGE_SECTION_OBJECT
)FileObject
->SectionObjectPointer
->ImageSectionObject
;
159 NrSegments
= ImageSectionObject
->NrSegments
;
160 SectionSegments
= ImageSectionObject
->Segments
;
161 for (i
= 0; i
< NrSegments
; i
++)
163 if (SectionSegments
[i
].ReferenceCount
!= 0)
165 DPRINT1("Image segment %d still referenced (was %d)\n", i
,
166 SectionSegments
[i
].ReferenceCount
);
169 MmFreePageTablesSectionSegment(&SectionSegments
[i
]);
171 ExFreePool(ImageSectionObject
);
172 FileObject
->SectionObjectPointer
->ImageSectionObject
= NULL
;
174 if (FileObject
->SectionObjectPointer
->DataSectionObject
!= NULL
)
176 PMM_SECTION_SEGMENT Segment
;
178 Segment
= (PMM_SECTION_SEGMENT
)FileObject
->SectionObjectPointer
->
181 if (Segment
->ReferenceCount
!= 0)
183 DPRINT1("Data segment still referenced\n");
186 MmFreePageTablesSectionSegment(Segment
);
188 FileObject
->SectionObjectPointer
->DataSectionObject
= NULL
;
193 MmLockSectionSegment(PMM_SECTION_SEGMENT Segment
)
195 ExAcquireFastMutex(&Segment
->Lock
);
199 MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment
)
201 ExReleaseFastMutex(&Segment
->Lock
);
205 MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment
,
209 PSECTION_PAGE_TABLE Table
;
210 ULONG DirectoryOffset
;
213 if (Segment
->Length
<= NR_SECTION_PAGE_TABLES
* PAGE_SIZE
)
215 Table
= (PSECTION_PAGE_TABLE
)&Segment
->PageDirectory
;
219 DirectoryOffset
= PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset
);
220 Table
= Segment
->PageDirectory
.PageTables
[DirectoryOffset
];
224 Segment
->PageDirectory
.PageTables
[DirectoryOffset
] =
225 ExAllocatePoolWithTag(NonPagedPool
, sizeof(SECTION_PAGE_TABLE
),
226 TAG_SECTION_PAGE_TABLE
);
231 memset(Table
, 0, sizeof(SECTION_PAGE_TABLE
));
232 DPRINT("Table %x\n", Table
);
235 TableOffset
= PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset
);
236 Table
->Entry
[TableOffset
] = Entry
;
241 MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment
,
244 PSECTION_PAGE_TABLE Table
;
246 ULONG DirectoryOffset
;
249 DPRINT("MmGetPageEntrySection(Offset %x)\n", Offset
);
251 if (Segment
->Length
<= NR_SECTION_PAGE_TABLES
* PAGE_SIZE
)
253 Table
= (PSECTION_PAGE_TABLE
)&Segment
->PageDirectory
;
257 DirectoryOffset
= PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset
);
258 Table
= Segment
->PageDirectory
.PageTables
[DirectoryOffset
];
259 DPRINT("Table %x\n", Table
);
265 TableOffset
= PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset
);
266 Entry
= Table
->Entry
[TableOffset
];
271 MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment
,
276 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
);
279 DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
282 if (SHARE_COUNT_FROM_SSE(Entry
) == MAX_SHARE_COUNT
)
284 DPRINT1("Maximum share count reached\n");
287 if (IS_SWAP_FROM_SSE(Entry
))
291 Entry
= MAKE_SSE(PAGE_FROM_SSE(Entry
), SHARE_COUNT_FROM_SSE(Entry
) + 1);
292 MmSetPageEntrySectionSegment(Segment
, Offset
, Entry
);
296 MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section
,
297 PMM_SECTION_SEGMENT Segment
,
303 BOOLEAN IsDirectMapped
= FALSE
;
305 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
);
308 DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
311 if (SHARE_COUNT_FROM_SSE(Entry
) == 0)
313 DPRINT1("Zero share count for unshare\n");
316 if (IS_SWAP_FROM_SSE(Entry
))
320 Entry
= MAKE_SSE(PAGE_FROM_SSE(Entry
), SHARE_COUNT_FROM_SSE(Entry
) - 1);
322 * If we reducing the share count of this entry to zero then set the entry
323 * to zero and tell the cache the page is no longer mapped.
325 if (SHARE_COUNT_FROM_SSE(Entry
) == 0)
327 PFILE_OBJECT FileObject
;
329 SWAPENTRY SavedSwapEntry
;
330 PHYSICAL_ADDRESS Page
;
331 BOOLEAN IsImageSection
;
334 FileOffset
= Offset
+ Segment
->FileOffset
;
336 IsImageSection
= Section
->AllocationAttributes
& SEC_IMAGE
? TRUE
: FALSE
;
338 Page
.QuadPart
= (LONGLONG
)PAGE_FROM_SSE(Entry
);
339 FileObject
= Section
->FileObject
;
340 if (FileObject
!= NULL
&&
341 !(Segment
->Characteristics
& IMAGE_SECTION_CHAR_SHARED
))
344 if ((FileOffset
% PAGE_SIZE
) == 0 &&
345 (Offset
+ PAGE_SIZE
<= Segment
->RawLength
|| !IsImageSection
))
348 Bcb
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
349 IsDirectMapped
= TRUE
;
350 Status
= CcRosUnmapCacheSegment(Bcb
, FileOffset
, Dirty
);
351 if (!NT_SUCCESS(Status
))
353 DPRINT1("CcRosUnmapCacheSegment failed, status = %x\n", Status
);
359 SavedSwapEntry
= MmGetSavedSwapEntryPage(Page
);
360 if (SavedSwapEntry
== 0)
363 ((Segment
->Flags
& MM_PAGEFILE_SEGMENT
) ||
364 (Segment
->Characteristics
& IMAGE_SECTION_CHAR_SHARED
)))
368 * Try to page out this page and set the swap entry
369 * within the section segment. There exist no rmap entry
370 * for this page. The pager thread can't page out a
371 * page without a rmap entry.
373 MmSetPageEntrySectionSegment(Segment
, Offset
, Entry
);
377 MmSetPageEntrySectionSegment(Segment
, Offset
, 0);
380 MmReleasePageMemoryConsumer(MC_USER
, Page
);
386 if ((Segment
->Flags
& MM_PAGEFILE_SEGMENT
) ||
387 (Segment
->Characteristics
& IMAGE_SECTION_CHAR_SHARED
))
395 * We hold all locks. Nobody can do something with the current
396 * process and the current segment (also not within an other process).
400 Mdl
= MmCreateMdl(NULL
, NULL
, PAGE_SIZE
);
401 MmBuildMdlFromPages(Mdl
, (PULONG
)&Page
);
402 Status
= MmWriteToSwapPage(SavedSwapEntry
, Mdl
);
403 if (!NT_SUCCESS(Status
))
405 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", Status
);
409 MmSetPageEntrySectionSegment(Segment
, Offset
, MAKE_SWAP_SSE(SavedSwapEntry
));
410 MmSetSavedSwapEntryPage(Page
, 0);
412 MmReleasePageMemoryConsumer(MC_USER
, Page
);
416 DPRINT1("Found a swapentry for a non private page in an image or data file sgment\n");
423 MmSetPageEntrySectionSegment(Segment
, Offset
, Entry
);
425 return(SHARE_COUNT_FROM_SSE(Entry
) > 0);
428 BOOL
MiIsPageFromCache(PMEMORY_AREA MemoryArea
,
431 if (!(MemoryArea
->Data
.SectionData
.Segment
->Characteristics
& IMAGE_SECTION_CHAR_SHARED
))
434 PCACHE_SEGMENT CacheSeg
;
435 Bcb
= MemoryArea
->Data
.SectionData
.Section
->FileObject
->SectionObjectPointer
->SharedCacheMap
;
436 CacheSeg
= CcRosLookupCacheSegment(Bcb
, SegOffset
+ MemoryArea
->Data
.SectionData
.Segment
->FileOffset
);
439 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, CacheSeg
->Valid
, FALSE
, TRUE
);
447 MiReadPage(PMEMORY_AREA MemoryArea
,
449 PHYSICAL_ADDRESS
* Page
)
451 * FUNCTION: Read a page for a section backed memory area.
453 * MemoryArea - Memory area to read the page for.
454 * Offset - Offset of the page to read.
455 * Page - Variable that receives a page contains the read data.
462 PCACHE_SEGMENT CacheSeg
;
463 PFILE_OBJECT FileObject
;
467 BOOLEAN IsImageSection
;
470 FileObject
= MemoryArea
->Data
.SectionData
.Section
->FileObject
;
471 Bcb
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
472 RawLength
= MemoryArea
->Data
.SectionData
.Segment
->RawLength
;
473 FileOffset
= SegOffset
+ MemoryArea
->Data
.SectionData
.Segment
->FileOffset
;
474 IsImageSection
= MemoryArea
->Data
.SectionData
.Section
->AllocationAttributes
& SEC_IMAGE
? TRUE
: FALSE
;
478 DPRINT("%S %x\n", FileObject
->FileName
.Buffer
, FileOffset
);
481 * If the file system is letting us go directly to the cache and the
482 * memory area was mapped at an offset in the file which is page aligned
483 * then get the related cache segment.
485 if ((FileOffset
% PAGE_SIZE
) == 0 &&
486 (SegOffset
+ PAGE_SIZE
<= RawLength
|| !IsImageSection
) &&
487 !(MemoryArea
->Data
.SectionData
.Segment
->Characteristics
& IMAGE_SECTION_CHAR_SHARED
))
491 * Get the related cache segment; we use a lower level interface than
492 * filesystems do because it is safe for us to use an offset with a
493 * alignment less than the file system block size.
495 Status
= CcRosGetCacheSegment(Bcb
,
501 if (!NT_SUCCESS(Status
))
508 * If the cache segment isn't up to date then call the file
509 * system to read in the data.
511 Status
= ReadCacheSegment(CacheSeg
);
512 if (!NT_SUCCESS(Status
))
514 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, FALSE
, FALSE
, FALSE
);
519 * Retrieve the page from the cache segment that we actually want.
521 (*Page
) = MmGetPhysicalAddress((char*)BaseAddress
+
522 FileOffset
- BaseOffset
);
524 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, TRUE
, FALSE
, TRUE
);
529 ULONG CacheSegOffset
;
531 * Allocate a page, this is rather complicated by the possibility
532 * we might have to move other things out of memory
534 Status
= MmRequestPageMemoryConsumer(MC_USER
, TRUE
, Page
);
535 if (!NT_SUCCESS(Status
))
539 Status
= CcRosGetCacheSegment(Bcb
,
545 if (!NT_SUCCESS(Status
))
552 * If the cache segment isn't up to date then call the file
553 * system to read in the data.
555 Status
= ReadCacheSegment(CacheSeg
);
556 if (!NT_SUCCESS(Status
))
558 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, FALSE
, FALSE
, FALSE
);
562 PageAddr
= ExAllocatePageWithPhysPage(*Page
);
563 CacheSegOffset
= BaseOffset
+ CacheSeg
->Bcb
->CacheSegmentSize
- FileOffset
;
564 Length
= RawLength
- SegOffset
;
565 if (Length
<= CacheSegOffset
&& Length
<= PAGE_SIZE
)
567 memcpy(PageAddr
, (char*)BaseAddress
+ FileOffset
- BaseOffset
, Length
);
569 else if (CacheSegOffset
>= PAGE_SIZE
)
571 memcpy(PageAddr
, (char*)BaseAddress
+ FileOffset
- BaseOffset
, PAGE_SIZE
);
575 memcpy(PageAddr
, (char*)BaseAddress
+ FileOffset
- BaseOffset
, CacheSegOffset
);
576 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, TRUE
, FALSE
, FALSE
);
577 Status
= CcRosGetCacheSegment(Bcb
,
578 FileOffset
+ CacheSegOffset
,
583 if (!NT_SUCCESS(Status
))
585 ExUnmapPage(PageAddr
);
591 * If the cache segment isn't up to date then call the file
592 * system to read in the data.
594 Status
= ReadCacheSegment(CacheSeg
);
595 if (!NT_SUCCESS(Status
))
597 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, FALSE
, FALSE
, FALSE
);
598 ExUnmapPage(PageAddr
);
602 if (Length
< PAGE_SIZE
)
604 memcpy((char*)PageAddr
+ CacheSegOffset
, BaseAddress
, Length
- CacheSegOffset
);
608 memcpy((char*)PageAddr
+ CacheSegOffset
, BaseAddress
, PAGE_SIZE
- CacheSegOffset
);
611 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, TRUE
, FALSE
, FALSE
);
612 ExUnmapPage(PageAddr
);
614 return(STATUS_SUCCESS
);
618 MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace
,
619 MEMORY_AREA
* MemoryArea
,
627 PSECTION_OBJECT Section
;
628 PMM_SECTION_SEGMENT Segment
;
637 * There is a window between taking the page fault and locking the
638 * address space when another thread could load the page so we check
641 if (MmIsPagePresent(AddressSpace
->Process
, Address
))
645 MmLockPage(MmGetPhysicalAddressForProcess(AddressSpace
->Process
, Address
));
647 return(STATUS_SUCCESS
);
650 PAddress
= (ULONG
)PAGE_ROUND_DOWN(((ULONG
)Address
));
651 Offset
= PAddress
- (ULONG
)MemoryArea
->BaseAddress
;
653 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
654 Section
= MemoryArea
->Data
.SectionData
.Section
;
655 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
656 &MemoryArea
->Data
.SectionData
.RegionListHead
,
661 MmLockSectionSegment(Segment
);
664 * Check if this page needs to be mapped COW
666 if ((Segment
->WriteCopy
|| MemoryArea
->Data
.SectionData
.WriteCopyView
) &&
667 (Region
->Protect
== PAGE_READWRITE
||
668 Region
->Protect
== PAGE_EXECUTE_READWRITE
))
670 Attributes
= Region
->Protect
== PAGE_READWRITE
? PAGE_READONLY
: PAGE_EXECUTE_READ
;
674 Attributes
= Region
->Protect
;
678 * Get or create a page operation descriptor
680 PageOp
= MmGetPageOp(MemoryArea
, 0, 0, Segment
, Offset
, MM_PAGEOP_PAGEIN
, FALSE
);
683 DPRINT1("MmGetPageOp failed\n");
688 * Check if someone else is already handling this fault, if so wait
691 if (PageOp
->Thread
!= PsGetCurrentThread())
693 MmUnlockSectionSegment(Segment
);
694 MmUnlockAddressSpace(AddressSpace
);
695 Status
= MmspWaitForPageOpCompletionEvent(PageOp
);
697 * Check for various strange conditions
699 if (Status
!= STATUS_SUCCESS
)
701 DPRINT1("Failed to wait for page op, status = %x\n", Status
);
704 if (PageOp
->Status
== STATUS_PENDING
)
706 DPRINT1("Woke for page op before completion\n");
709 MmLockAddressSpace(AddressSpace
);
711 * If this wasn't a pagein then restart the operation
713 if (PageOp
->OpType
!= MM_PAGEOP_PAGEIN
)
715 MmspCompleteAndReleasePageOp(PageOp
);
716 DPRINT("Address 0x%.8X\n", Address
);
717 return(STATUS_MM_RESTART_OPERATION
);
721 * If the thread handling this fault has failed then we don't retry
723 if (!NT_SUCCESS(PageOp
->Status
))
725 Status
= PageOp
->Status
;
726 MmspCompleteAndReleasePageOp(PageOp
);
727 DPRINT("Address 0x%.8X\n", Address
);
730 MmLockSectionSegment(Segment
);
732 * If the completed fault was for another address space then set the
735 if (!MmIsPagePresent(AddressSpace
->Process
, Address
))
737 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
);
738 HasSwapEntry
= MmIsPageSwapEntry(AddressSpace
->Process
, (PVOID
)PAddress
);
740 if (PAGE_FROM_SSE(Entry
) == 0 || HasSwapEntry
)
743 * The page was a private page in another or in our address space
745 MmUnlockSectionSegment(Segment
);
746 MmspCompleteAndReleasePageOp(PageOp
);
747 return(STATUS_MM_RESTART_OPERATION
);
750 Page
.QuadPart
= (LONGLONG
)(PAGE_FROM_SSE(Entry
));
752 MmSharePageEntrySectionSegment(Segment
, Offset
);
754 Status
= MmCreateVirtualMapping(MemoryArea
->Process
,
759 if (Status
== STATUS_NO_MEMORY
)
761 MmUnlockAddressSpace(AddressSpace
);
762 Status
= MmCreateVirtualMapping(MemoryArea
->Process
,
767 MmLockAddressSpace(AddressSpace
);
770 if (!NT_SUCCESS(Status
))
772 DbgPrint("Unable to create virtual mapping\n");
775 MmInsertRmap(Page
, MemoryArea
->Process
, (PVOID
)PAddress
);
781 MmUnlockSectionSegment(Segment
);
782 PageOp
->Status
= STATUS_SUCCESS
;
783 MmspCompleteAndReleasePageOp(PageOp
);
784 DPRINT("Address 0x%.8X\n", Address
);
785 return(STATUS_SUCCESS
);
788 HasSwapEntry
= MmIsPageSwapEntry(AddressSpace
->Process
, (PVOID
)PAddress
);
792 * Must be private page we have swapped out.
800 if (Segment
->Flags
& MM_PAGEFILE_SEGMENT
)
802 DPRINT1("Found a swaped out private page in a pagefile section.\n");
806 MmUnlockSectionSegment(Segment
);
807 MmDeletePageFileMapping(AddressSpace
->Process
, (PVOID
)PAddress
, &SwapEntry
);
809 MmUnlockAddressSpace(AddressSpace
);
810 Status
= MmRequestPageMemoryConsumer(MC_USER
, TRUE
, &Page
);
811 if (!NT_SUCCESS(Status
))
816 Mdl
= MmCreateMdl(NULL
, NULL
, PAGE_SIZE
);
817 MmBuildMdlFromPages(Mdl
, (PULONG
)&Page
);
818 Status
= MmReadFromSwapPage(SwapEntry
, Mdl
);
819 if (!NT_SUCCESS(Status
))
821 DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status
);
824 MmLockAddressSpace(AddressSpace
);
825 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
830 if (Status
== STATUS_NO_MEMORY
)
832 MmUnlockAddressSpace(AddressSpace
);
833 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
838 MmLockAddressSpace(AddressSpace
);
840 if (!NT_SUCCESS(Status
))
842 DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
848 * Store the swap entry for later use.
850 MmSetSavedSwapEntryPage(Page
, SwapEntry
);
853 * Add the page to the process's working set
855 MmInsertRmap(Page
, AddressSpace
->Process
, (PVOID
)PAddress
);
858 * Finish the operation
862 MmLockPage(MmGetPhysicalAddressForProcess(NULL
, Address
));
864 PageOp
->Status
= STATUS_SUCCESS
;
865 MmspCompleteAndReleasePageOp(PageOp
);
866 DPRINT("Address 0x%.8X\n", Address
);
867 return(STATUS_SUCCESS
);
871 * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
873 if (Section
->AllocationAttributes
& SEC_PHYSICALMEMORY
)
875 MmUnlockSectionSegment(Segment
);
877 * Just map the desired physical page
879 Page
.QuadPart
= Offset
+ MemoryArea
->Data
.SectionData
.ViewOffset
;
880 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
885 if (Status
== STATUS_NO_MEMORY
)
887 MmUnlockAddressSpace(AddressSpace
);
888 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
893 MmLockAddressSpace(AddressSpace
);
895 if (!NT_SUCCESS(Status
))
897 DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
902 * Don't add an rmap entry since the page mapped could be for
911 * Cleanup and release locks
913 PageOp
->Status
= STATUS_SUCCESS
;
914 MmspCompleteAndReleasePageOp(PageOp
);
915 DPRINT("Address 0x%.8X\n", Address
);
916 return(STATUS_SUCCESS
);
920 * Map anonymous memory for BSS sections
922 if (Segment
->Characteristics
& IMAGE_SECTION_CHAR_BSS
)
924 MmUnlockSectionSegment(Segment
);
925 Status
= MmRequestPageMemoryConsumer(MC_USER
, FALSE
, &Page
);
926 if (!NT_SUCCESS(Status
))
928 MmUnlockAddressSpace(AddressSpace
);
929 Status
= MmRequestPageMemoryConsumer(MC_USER
, TRUE
, &Page
);
930 MmLockAddressSpace(AddressSpace
);
932 if (!NT_SUCCESS(Status
))
936 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
941 if (Status
== STATUS_NO_MEMORY
)
943 MmUnlockAddressSpace(AddressSpace
);
944 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
949 MmLockAddressSpace(AddressSpace
);
952 if (!NT_SUCCESS(Status
))
954 DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
958 MmInsertRmap(Page
, AddressSpace
->Process
, (PVOID
)PAddress
);
965 * Cleanup and release locks
967 PageOp
->Status
= STATUS_SUCCESS
;
968 MmspCompleteAndReleasePageOp(PageOp
);
969 DPRINT("Address 0x%.8X\n", Address
);
970 return(STATUS_SUCCESS
);
974 * Get the entry corresponding to the offset within the section
976 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
);
981 * If the entry is zero (and it can't change because we have
982 * locked the segment) then we need to load the page.
986 * Release all our locks and read in the page from disk
988 MmUnlockSectionSegment(Segment
);
989 MmUnlockAddressSpace(AddressSpace
);
991 if ((Segment
->Flags
& MM_PAGEFILE_SEGMENT
) ||
992 (Offset
>= PAGE_ROUND_UP(Segment
->RawLength
) && Section
->AllocationAttributes
& SEC_IMAGE
))
994 Status
= MmRequestPageMemoryConsumer(MC_USER
, TRUE
, &Page
);
995 if (!NT_SUCCESS(Status
))
997 DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status
);
1002 Status
= MiReadPage(MemoryArea
, Offset
, &Page
);
1003 if (!NT_SUCCESS(Status
))
1005 DPRINT1("MiReadPage failed (Status %x)\n", Status
);
1008 if (!NT_SUCCESS(Status
))
1011 * FIXME: What do we know in this case?
1014 * Cleanup and release locks
1016 MmLockAddressSpace(AddressSpace
);
1017 PageOp
->Status
= Status
;
1018 MmspCompleteAndReleasePageOp(PageOp
);
1019 DPRINT("Address 0x%.8X\n", Address
);
1023 * Relock the address space and segment
1025 MmLockAddressSpace(AddressSpace
);
1026 MmLockSectionSegment(Segment
);
1029 * Check the entry. No one should change the status of a page
1030 * that has a pending page-in.
1032 Entry1
= MmGetPageEntrySectionSegment(Segment
, Offset
);
1033 if (Entry
!= Entry1
)
1035 DbgPrint("Someone changed ppte entry while we slept\n");
1040 * Mark the offset within the section as having valid, in-memory
1043 Entry
= MAKE_SSE(Page
.u
.LowPart
, 1);
1044 MmSetPageEntrySectionSegment(Segment
, Offset
, Entry
);
1045 MmUnlockSectionSegment(Segment
);
1047 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
1052 if (Status
== STATUS_NO_MEMORY
)
1054 MmUnlockAddressSpace(AddressSpace
);
1055 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
1060 MmLockAddressSpace(AddressSpace
);
1062 if (!NT_SUCCESS(Status
))
1064 DbgPrint("Unable to create virtual mapping\n");
1067 MmInsertRmap(Page
, AddressSpace
->Process
, (PVOID
)PAddress
);
1073 PageOp
->Status
= STATUS_SUCCESS
;
1074 MmspCompleteAndReleasePageOp(PageOp
);
1075 DPRINT("Address 0x%.8X\n", Address
);
1076 return(STATUS_SUCCESS
);
1078 else if (IS_SWAP_FROM_SSE(Entry
))
1080 SWAPENTRY SwapEntry
;
1083 SwapEntry
= SWAPENTRY_FROM_SSE(Entry
);
1086 * Release all our locks and read in the page from disk
1088 MmUnlockSectionSegment(Segment
);
1090 MmUnlockAddressSpace(AddressSpace
);
1092 Status
= MmRequestPageMemoryConsumer(MC_USER
, TRUE
, &Page
);
1093 if (!NT_SUCCESS(Status
))
1098 Mdl
= MmCreateMdl(NULL
, NULL
, PAGE_SIZE
);
1099 MmBuildMdlFromPages(Mdl
, (PULONG
)&Page
);
1100 Status
= MmReadFromSwapPage(SwapEntry
, Mdl
);
1101 if (!NT_SUCCESS(Status
))
1107 * Relock the address space and segment
1109 MmLockAddressSpace(AddressSpace
);
1110 MmLockSectionSegment(Segment
);
1113 * Check the entry. No one should change the status of a page
1114 * that has a pending page-in.
1116 Entry1
= MmGetPageEntrySectionSegment(Segment
, Offset
);
1117 if (Entry
!= Entry1
)
1119 DbgPrint("Someone changed ppte entry while we slept\n");
1124 * Mark the offset within the section as having valid, in-memory
1127 Entry
= MAKE_SSE(Page
.u
.LowPart
, 1);
1128 MmSetPageEntrySectionSegment(Segment
, Offset
, Entry
);
1129 MmUnlockSectionSegment(Segment
);
1132 * Save the swap entry.
1134 MmSetSavedSwapEntryPage(Page
, SwapEntry
);
1135 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
1140 if (Status
== STATUS_NO_MEMORY
)
1142 MmUnlockAddressSpace(AddressSpace
);
1143 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
1148 MmLockAddressSpace(AddressSpace
);
1150 if (!NT_SUCCESS(Status
))
1152 DbgPrint("Unable to create virtual mapping\n");
1155 MmInsertRmap(Page
, AddressSpace
->Process
, (PVOID
)PAddress
);
1160 PageOp
->Status
= STATUS_SUCCESS
;
1161 MmspCompleteAndReleasePageOp(PageOp
);
1162 DPRINT("Address 0x%.8X\n", Address
);
1163 return(STATUS_SUCCESS
);
1168 * If the section offset is already in-memory and valid then just
1169 * take another reference to the page
1172 Page
.QuadPart
= (LONGLONG
)PAGE_FROM_SSE(Entry
);
1174 MmSharePageEntrySectionSegment(Segment
, Offset
);
1175 MmUnlockSectionSegment(Segment
);
1177 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
1182 if (Status
== STATUS_NO_MEMORY
)
1184 MmUnlockAddressSpace(AddressSpace
);
1185 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
1190 MmLockAddressSpace(AddressSpace
);
1192 if (!NT_SUCCESS(Status
))
1194 DbgPrint("Unable to create virtual mapping\n");
1197 MmInsertRmap(Page
, AddressSpace
->Process
, (PVOID
)PAddress
);
1202 PageOp
->Status
= STATUS_SUCCESS
;
1203 MmspCompleteAndReleasePageOp(PageOp
);
1204 DPRINT("Address 0x%.8X\n", Address
);
1205 return(STATUS_SUCCESS
);
1210 MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace
,
1211 MEMORY_AREA
* MemoryArea
,
1215 PMM_SECTION_SEGMENT Segment
;
1216 PSECTION_OBJECT Section
;
1217 PHYSICAL_ADDRESS OldPage
;
1218 PHYSICAL_ADDRESS NewPage
;
1228 * Check if the page has been paged out or has already been set readwrite
1230 if (!MmIsPagePresent(AddressSpace
->Process
, Address
) ||
1231 MmGetPageProtect(AddressSpace
->Process
, Address
) & PAGE_READWRITE
)
1233 DPRINT("Address 0x%.8X\n", Address
);
1234 return(STATUS_SUCCESS
);
1238 * Find the offset of the page
1240 PAddress
= (ULONG
)PAGE_ROUND_DOWN(((ULONG
)Address
));
1241 Offset
= PAddress
- (ULONG
)MemoryArea
->BaseAddress
;
1243 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
1244 Section
= MemoryArea
->Data
.SectionData
.Section
;
1245 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
1246 &MemoryArea
->Data
.SectionData
.RegionListHead
,
1251 MmLockSectionSegment(Segment
);
1253 OldPage
= MmGetPhysicalAddressForProcess(NULL
, Address
);
1254 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
);
1256 MmUnlockSectionSegment(Segment
);
1259 * Check if we are doing COW
1261 if (!((Segment
->WriteCopy
|| MemoryArea
->Data
.SectionData
.WriteCopyView
) &&
1262 (Region
->Protect
== PAGE_READWRITE
||
1263 Region
->Protect
== PAGE_EXECUTE_READWRITE
)))
1265 DPRINT("Address 0x%.8X\n", Address
);
1266 return(STATUS_UNSUCCESSFUL
);
1269 if (IS_SWAP_FROM_SSE(Entry
) ||
1270 PAGE_FROM_SSE(Entry
) != OldPage
.u
.LowPart
)
1272 /* This is a private page. We must only change the page protection. */
1273 MmSetPageProtect(AddressSpace
->Process
, (PVOID
)PAddress
, Region
->Protect
);
1274 return(STATUS_SUCCESS
);
1278 * Get or create a pageop
1280 PageOp
= MmGetPageOp(MemoryArea
, 0, 0, Segment
, Offset
,
1281 MM_PAGEOP_ACCESSFAULT
, FALSE
);
1284 DPRINT1("MmGetPageOp failed\n");
1289 * Wait for any other operations to complete
1291 if (PageOp
->Thread
!= PsGetCurrentThread())
1293 MmUnlockAddressSpace(AddressSpace
);
1294 Status
= MmspWaitForPageOpCompletionEvent(PageOp
);
1296 * Check for various strange conditions
1298 if (Status
== STATUS_TIMEOUT
)
1300 DPRINT1("Failed to wait for page op, status = %x\n", Status
);
1303 if (PageOp
->Status
== STATUS_PENDING
)
1305 DPRINT1("Woke for page op before completion\n");
1309 * Restart the operation
1311 MmLockAddressSpace(AddressSpace
);
1312 MmspCompleteAndReleasePageOp(PageOp
);
1313 DPRINT("Address 0x%.8X\n", Address
);
1314 return(STATUS_MM_RESTART_OPERATION
);
1318 * Release locks now we have the pageop
1320 MmUnlockAddressSpace(AddressSpace
);
1325 Status
= MmRequestPageMemoryConsumer(MC_USER
, TRUE
, &NewPage
);
1326 if (!NT_SUCCESS(Status
))
1335 NewAddress
= ExAllocatePageWithPhysPage(NewPage
);
1336 memcpy(NewAddress
, (PVOID
)PAddress
, PAGE_SIZE
);
1337 ExUnmapPage(NewAddress
);
1340 * Delete the old entry.
1342 MmDeleteVirtualMapping(AddressSpace
->Process
, Address
, FALSE
, NULL
, NULL
);
1345 * Set the PTE to point to the new page
1347 MmLockAddressSpace(AddressSpace
);
1348 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
1353 if (Status
== STATUS_NO_MEMORY
)
1355 MmUnlockAddressSpace(AddressSpace
);
1356 Status
= MmCreateVirtualMapping(AddressSpace
->Process
,
1361 MmLockAddressSpace(AddressSpace
);
1363 if (!NT_SUCCESS(Status
))
1365 DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
1369 MmInsertRmap(NewPage
, AddressSpace
->Process
, (PVOID
)PAddress
);
1370 if (!NT_SUCCESS(Status
))
1372 DbgPrint("Unable to create virtual mapping\n");
1377 MmLockPage(NewPage
);
1378 MmUnlockPage(OldPage
);
1382 * Unshare the old page.
1384 MmDeleteRmap(OldPage
, AddressSpace
->Process
, (PVOID
)PAddress
);
1385 MmLockSectionSegment(Segment
);
1386 MmUnsharePageEntrySectionSegment(Section
, Segment
, Offset
, FALSE
, FALSE
);
1387 MmUnlockSectionSegment(Segment
);
1389 PageOp
->Status
= STATUS_SUCCESS
;
1390 MmspCompleteAndReleasePageOp(PageOp
);
1391 DPRINT("Address 0x%.8X\n", Address
);
1392 return(STATUS_SUCCESS
);
1396 MmPageOutDeleteMapping(PVOID Context
, PEPROCESS Process
, PVOID Address
)
1398 MM_SECTION_PAGEOUT_CONTEXT
* PageOutContext
;
1400 PHYSICAL_ADDRESS Page
;
1402 PageOutContext
= (MM_SECTION_PAGEOUT_CONTEXT
*)Context
;
1403 MmDeleteVirtualMapping(Process
,
1410 PageOutContext
->WasDirty
= TRUE
;
1412 if (!PageOutContext
->Private
)
1414 MmUnsharePageEntrySectionSegment(PageOutContext
->Section
,
1415 PageOutContext
->Segment
,
1416 PageOutContext
->Offset
,
1417 PageOutContext
->WasDirty
,
1422 MmReleasePageMemoryConsumer(MC_USER
, Page
);
1425 DPRINT("PhysicalAddress %I64x, Address %x\n", Page
, Address
);
1429 MmPageOutSectionView(PMADDRESS_SPACE AddressSpace
,
1430 MEMORY_AREA
* MemoryArea
,
1434 PHYSICAL_ADDRESS PhysicalAddress
;
1435 MM_SECTION_PAGEOUT_CONTEXT Context
;
1436 SWAPENTRY SwapEntry
;
1441 PFILE_OBJECT FileObject
;
1443 BOOLEAN DirectMapped
;
1444 BOOLEAN IsImageSection
;
1446 Address
= (PVOID
)PAGE_ROUND_DOWN(Address
);
1449 * Get the segment and section.
1451 Context
.Segment
= MemoryArea
->Data
.SectionData
.Segment
;
1452 Context
.Section
= MemoryArea
->Data
.SectionData
.Section
;
1454 Context
.Offset
= (ULONG
)((char*)Address
- (ULONG
)MemoryArea
->BaseAddress
);
1455 FileOffset
= Context
.Offset
+ Context
.Segment
->FileOffset
;
1457 IsImageSection
= Context
.Section
->AllocationAttributes
& SEC_IMAGE
? TRUE
: FALSE
;
1459 FileObject
= Context
.Section
->FileObject
;
1460 DirectMapped
= FALSE
;
1461 if (FileObject
!= NULL
&&
1462 !(Context
.Segment
->Characteristics
& IMAGE_SECTION_CHAR_SHARED
))
1464 Bcb
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1467 * If the file system is letting us go directly to the cache and the
1468 * memory area was mapped at an offset in the file which is page aligned
1469 * then note this is a direct mapped page.
1471 if ((FileOffset
% PAGE_SIZE
) == 0 &&
1472 (Context
.Offset
+ PAGE_SIZE
<= Context
.Segment
->RawLength
|| !IsImageSection
))
1474 DirectMapped
= TRUE
;
1480 * This should never happen since mappings of physical memory are never
1481 * placed in the rmap lists.
1483 if (Context
.Section
->AllocationAttributes
& SEC_PHYSICALMEMORY
)
1485 DPRINT1("Trying to page out from physical memory section address 0x%X "
1486 "process %d\n", Address
,
1487 AddressSpace
->Process
? AddressSpace
->Process
->UniqueProcessId
: 0);
1492 * Get the section segment entry and the physical address.
1494 Entry
= MmGetPageEntrySectionSegment(Context
.Segment
, Context
.Offset
);
1495 if (!MmIsPagePresent(AddressSpace
->Process
, Address
))
1497 DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
1498 AddressSpace
->Process
? AddressSpace
->Process
->UniqueProcessId
: 0, Address
);
1502 MmGetPhysicalAddressForProcess(AddressSpace
->Process
, Address
);
1503 SwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddress
);
1506 * Prepare the context structure for the rmap delete call.
1508 Context
.WasDirty
= FALSE
;
1509 if (Context
.Segment
->Characteristics
& IMAGE_SECTION_CHAR_BSS
||
1510 IS_SWAP_FROM_SSE(Entry
) ||
1511 (LONGLONG
)PAGE_FROM_SSE(Entry
) != PhysicalAddress
.QuadPart
)
1513 Context
.Private
= TRUE
;
1517 Context
.Private
= FALSE
;
1521 * Take an additional reference to the page or the cache segment.
1523 if (DirectMapped
&& !Context
.Private
)
1525 if(!MiIsPageFromCache(MemoryArea
, Context
.Offset
))
1527 DPRINT1("Direct mapped non private page is not associated with the cache.\n");
1533 MmReferencePage(PhysicalAddress
);
1536 MmDeleteAllRmaps(PhysicalAddress
, (PVOID
)&Context
, MmPageOutDeleteMapping
);
1539 * If this wasn't a private page then we should have reduced the entry to
1540 * zero by deleting all the rmaps.
1542 if (!Context
.Private
&& MmGetPageEntrySectionSegment(Context
.Segment
, Context
.Offset
) != 0)
1544 if (!(Context
.Segment
->Flags
& MM_PAGEFILE_SEGMENT
) &&
1545 !(Context
.Segment
->Characteristics
& IMAGE_SECTION_CHAR_SHARED
))
1552 * If the page wasn't dirty then we can just free it as for a readonly page.
1553 * Since we unmapped all the mappings above we know it will not suddenly
1555 * If the page is from a pagefile section and has no swap entry,
1556 * we can't free the page at this point.
1558 SwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddress
);
1559 if (Context
.Segment
->Flags
& MM_PAGEFILE_SEGMENT
)
1561 if (Context
.Private
)
1563 DPRINT1("Found a %s private page (address %x) in a pagefile segment.\n",
1564 Context
.WasDirty
? "dirty" : "clean", Address
);
1567 if (!Context
.WasDirty
&& SwapEntry
!= 0)
1569 MmSetSavedSwapEntryPage(PhysicalAddress
, 0);
1570 MmSetPageEntrySectionSegment(Context
.Segment
, Context
.Offset
, MAKE_SWAP_SSE(SwapEntry
));
1571 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
1572 PageOp
->Status
= STATUS_SUCCESS
;
1573 MmspCompleteAndReleasePageOp(PageOp
);
1574 return(STATUS_SUCCESS
);
1577 else if (Context
.Segment
->Characteristics
& IMAGE_SECTION_CHAR_SHARED
)
1579 if (Context
.Private
)
1581 DPRINT1("Found a %s private page (address %x) in a shared section segment.\n",
1582 Context
.WasDirty
? "dirty" : "clean", Address
);
1585 if (!Context
.WasDirty
|| SwapEntry
!= 0)
1587 MmSetSavedSwapEntryPage(PhysicalAddress
, 0);
1590 MmSetPageEntrySectionSegment(Context
.Segment
, Context
.Offset
, MAKE_SWAP_SSE(SwapEntry
));
1592 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
1593 PageOp
->Status
= STATUS_SUCCESS
;
1594 MmspCompleteAndReleasePageOp(PageOp
);
1595 return(STATUS_SUCCESS
);
1598 else if (!Context
.Private
&& DirectMapped
)
1602 DPRINT1("Found a swapentry for a non private and direct mapped page (address %x)\n",
1606 Status
= CcRosUnmapCacheSegment(Bcb
, FileOffset
, FALSE
);
1607 if (!NT_SUCCESS(Status
))
1609 DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status
);
1612 PageOp
->Status
= STATUS_SUCCESS
;
1613 MmspCompleteAndReleasePageOp(PageOp
);
1614 return(STATUS_SUCCESS
);
1616 else if (!Context
.WasDirty
&& !DirectMapped
&& !Context
.Private
)
1620 DPRINT1("Found a swap entry for a non dirty, non private and not direct mapped page (address %x)\n",
1624 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
1625 PageOp
->Status
= STATUS_SUCCESS
;
1626 MmspCompleteAndReleasePageOp(PageOp
);
1627 return(STATUS_SUCCESS
);
1629 else if (!Context
.WasDirty
&& Context
.Private
&& SwapEntry
!= 0)
1631 MmSetSavedSwapEntryPage(PhysicalAddress
, 0);
1632 Status
= MmCreatePageFileMapping(AddressSpace
->Process
,
1635 if (!NT_SUCCESS(Status
))
1639 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
1640 PageOp
->Status
= STATUS_SUCCESS
;
1641 MmspCompleteAndReleasePageOp(PageOp
);
1642 return(STATUS_SUCCESS
);
1646 * If necessary, allocate an entry in the paging file for this page
1650 SwapEntry
= MmAllocSwapPage();
1653 MmShowOutOfSpaceMessagePagingFile();
1656 * For private pages restore the old mappings.
1658 if (Context
.Private
)
1660 Status
= MmCreateVirtualMapping(MemoryArea
->Process
,
1662 MemoryArea
->Attributes
,
1665 MmSetDirtyPage(MemoryArea
->Process
, Address
);
1666 MmInsertRmap(PhysicalAddress
,
1667 MemoryArea
->Process
,
1673 * For non-private pages if the page wasn't direct mapped then
1674 * set it back into the section segment entry so we don't loose
1675 * our copy. Otherwise it will be handled by the cache manager.
1677 Status
= MmCreateVirtualMapping(MemoryArea
->Process
,
1679 MemoryArea
->Attributes
,
1682 MmSetDirtyPage(MemoryArea
->Process
, Address
);
1683 MmInsertRmap(PhysicalAddress
,
1684 MemoryArea
->Process
,
1686 Entry
= MAKE_SSE(PhysicalAddress
.u
.LowPart
, 1);
1687 MmSetPageEntrySectionSegment(Context
.Segment
, Context
.Offset
, Entry
);
1689 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
1690 MmspCompleteAndReleasePageOp(PageOp
);
1691 return(STATUS_PAGEFILE_QUOTA
);
1696 * Write the page to the pagefile
1698 Mdl
= MmCreateMdl(NULL
, NULL
, PAGE_SIZE
);
1699 MmBuildMdlFromPages(Mdl
, (PULONG
)&PhysicalAddress
);
1700 Status
= MmWriteToSwapPage(SwapEntry
, Mdl
);
1701 if (!NT_SUCCESS(Status
))
1703 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
1706 * As above: undo our actions.
1707 * FIXME: Also free the swap page.
1709 if (Context
.Private
)
1711 Status
= MmCreateVirtualMapping(MemoryArea
->Process
,
1713 MemoryArea
->Attributes
,
1716 MmSetDirtyPage(MemoryArea
->Process
, Address
);
1717 MmInsertRmap(PhysicalAddress
,
1718 MemoryArea
->Process
,
1723 Status
= MmCreateVirtualMapping(MemoryArea
->Process
,
1725 MemoryArea
->Attributes
,
1728 MmSetDirtyPage(MemoryArea
->Process
, Address
);
1729 MmInsertRmap(PhysicalAddress
,
1730 MemoryArea
->Process
,
1732 Entry
= MAKE_SSE(PhysicalAddress
.u
.LowPart
, 1);
1733 MmSetPageEntrySectionSegment(Context
.Segment
, Context
.Offset
, Entry
);
1735 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
1736 MmspCompleteAndReleasePageOp(PageOp
);
1737 return(STATUS_UNSUCCESSFUL
);
1741 * Otherwise we have succeeded.
1743 DPRINT("MM: Wrote section page 0x%.8X to swap!\n", PhysicalAddress
);
1744 MmSetSavedSwapEntryPage(PhysicalAddress
, 0);
1745 if (Context
.Segment
->Flags
& MM_PAGEFILE_SEGMENT
||
1746 Context
.Segment
->Characteristics
& IMAGE_SECTION_CHAR_SHARED
)
1748 MmSetPageEntrySectionSegment(Context
.Segment
, Context
.Offset
, MAKE_SWAP_SSE(SwapEntry
));
1752 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
1755 if (Context
.Private
)
1757 Status
= MmCreatePageFileMapping(MemoryArea
->Process
,
1760 if (!NT_SUCCESS(Status
))
1767 Entry
= MAKE_SWAP_SSE(SwapEntry
);
1768 MmSetPageEntrySectionSegment(Context
.Segment
, Context
.Offset
, Entry
);
1771 PageOp
->Status
= STATUS_SUCCESS
;
1772 MmspCompleteAndReleasePageOp(PageOp
);
1773 return(STATUS_SUCCESS
);
1777 MmWritePageSectionView(PMADDRESS_SPACE AddressSpace
,
1778 PMEMORY_AREA MemoryArea
,
1783 PSECTION_OBJECT Section
;
1784 PMM_SECTION_SEGMENT Segment
;
1785 PHYSICAL_ADDRESS PhysicalAddress
;
1786 SWAPENTRY SwapEntry
;
1791 PFILE_OBJECT FileObject
;
1793 BOOLEAN DirectMapped
;
1794 BOOLEAN IsImageSection
;
1796 Address
= (PVOID
)PAGE_ROUND_DOWN(Address
);
1798 Offset
= (ULONG
)((char*)Address
- (ULONG
)MemoryArea
->BaseAddress
);
1801 * Get the segment and section.
1803 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
1804 Section
= MemoryArea
->Data
.SectionData
.Section
;
1805 IsImageSection
= Section
->AllocationAttributes
& SEC_IMAGE
? TRUE
: FALSE
;
1807 FileObject
= Section
->FileObject
;
1808 DirectMapped
= FALSE
;
1809 if (FileObject
!= NULL
&&
1810 !(Segment
->Characteristics
& IMAGE_SECTION_CHAR_SHARED
))
1812 Bcb
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1815 * If the file system is letting us go directly to the cache and the
1816 * memory area was mapped at an offset in the file which is page aligned
1817 * then note this is a direct mapped page.
1819 if ((Offset
+ MemoryArea
->Data
.SectionData
.ViewOffset
% PAGE_SIZE
) == 0 &&
1820 (Offset
+ PAGE_SIZE
<= Segment
->RawLength
|| !IsImageSection
))
1822 DirectMapped
= TRUE
;
1827 * This should never happen since mappings of physical memory are never
1828 * placed in the rmap lists.
1830 if (Section
->AllocationAttributes
& SEC_PHYSICALMEMORY
)
1832 DPRINT1("Trying to write back page from physical memory mapped at %X "
1833 "process %d\n", Address
,
1834 AddressSpace
->Process
? AddressSpace
->Process
->UniqueProcessId
: 0);
1839 * Get the section segment entry and the physical address.
1841 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
);
1842 if (!MmIsPagePresent(AddressSpace
->Process
, Address
))
1844 DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
1845 AddressSpace
->Process
? AddressSpace
->Process
->UniqueProcessId
: 0, Address
);
1849 MmGetPhysicalAddressForProcess(AddressSpace
->Process
, Address
);
1850 SwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddress
);
1853 * Check for a private (COWed) page.
1855 if (Segment
->Characteristics
& IMAGE_SECTION_CHAR_BSS
||
1856 IS_SWAP_FROM_SSE(Entry
) ||
1857 (LONGLONG
)PAGE_FROM_SSE(Entry
) != PhysicalAddress
.QuadPart
)
1867 * Speculatively set all mappings of the page to clean.
1869 MmSetCleanAllRmaps(PhysicalAddress
);
1872 * If this page was direct mapped from the cache then the cache manager
1873 * will take care of writing it back to disk.
1875 if (DirectMapped
&& !Private
)
1877 assert(SwapEntry
== 0);
1878 CcRosMarkDirtyCacheSegment(Bcb
, Offset
+ MemoryArea
->Data
.SectionData
.ViewOffset
);
1879 PageOp
->Status
= STATUS_SUCCESS
;
1880 MmspCompleteAndReleasePageOp(PageOp
);
1881 return(STATUS_SUCCESS
);
1885 * If necessary, allocate an entry in the paging file for this page
1889 SwapEntry
= MmAllocSwapPage();
1892 MmSetDirtyAllRmaps(PhysicalAddress
);
1893 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
1894 MmspCompleteAndReleasePageOp(PageOp
);
1895 return(STATUS_PAGEFILE_QUOTA
);
1897 MmSetSavedSwapEntryPage(PhysicalAddress
, SwapEntry
);
1901 * Write the page to the pagefile
1903 Mdl
= MmCreateMdl(NULL
, NULL
, PAGE_SIZE
);
1904 MmBuildMdlFromPages(Mdl
, (PULONG
)&PhysicalAddress
);
1905 Status
= MmWriteToSwapPage(SwapEntry
, Mdl
);
1906 if (!NT_SUCCESS(Status
))
1908 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
1910 MmSetDirtyAllRmaps(PhysicalAddress
);
1911 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
1912 MmspCompleteAndReleasePageOp(PageOp
);
1913 return(STATUS_UNSUCCESSFUL
);
1917 * Otherwise we have succeeded.
1919 DPRINT("MM: Wrote section page 0x%.8X to swap!\n", PhysicalAddress
);
1920 PageOp
->Status
= STATUS_SUCCESS
;
1921 MmspCompleteAndReleasePageOp(PageOp
);
1922 return(STATUS_SUCCESS
);
1926 MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace
,
1934 PMEMORY_AREA MemoryArea
;
1935 PMM_SECTION_SEGMENT Segment
;
1939 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
, BaseAddress
);
1940 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
1942 if ((Segment
->WriteCopy
|| MemoryArea
->Data
.SectionData
.WriteCopyView
) &&
1943 (NewProtect
== PAGE_READWRITE
|| NewProtect
== PAGE_EXECUTE_READWRITE
))
1948 if (OldProtect
!= NewProtect
)
1950 for (i
= 0; i
< PAGE_ROUND_UP(RegionSize
) / PAGE_SIZE
; i
++)
1952 PVOID Address
= (char*)BaseAddress
+ (i
* PAGE_SIZE
);
1953 ULONG Protect
= NewProtect
;
1956 * If we doing COW for this segment then check if the page is
1959 if (DoCOW
&& MmIsPagePresent(AddressSpace
->Process
, Address
))
1963 LARGE_INTEGER PhysicalAddress
;
1965 Offset
= (ULONG
)Address
- (ULONG
)MemoryArea
->BaseAddress
;
1966 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
);
1968 MmGetPhysicalAddressForProcess(AddressSpace
->Process
, Address
);
1970 Protect
= PAGE_READONLY
;
1971 if ((Segment
->Characteristics
& IMAGE_SECTION_CHAR_BSS
||
1972 IS_SWAP_FROM_SSE(Entry
) ||
1973 (LONGLONG
)PAGE_FROM_SSE(Entry
) != PhysicalAddress
.QuadPart
))
1975 Protect
= NewProtect
;
1979 if (MmIsPagePresent(AddressSpace
->Process
, Address
))
1981 MmSetPageProtect(AddressSpace
->Process
, BaseAddress
,
1989 MmProtectSectionView(PMADDRESS_SPACE AddressSpace
,
1990 PMEMORY_AREA MemoryArea
,
2000 min(Length
, (ULONG
) ((char*)MemoryArea
->BaseAddress
+ MemoryArea
->Length
- (char*)BaseAddress
));
2001 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
2002 &MemoryArea
->Data
.SectionData
.RegionListHead
,
2004 *OldProtect
= Region
->Protect
;
2005 Status
= MmAlterRegion(AddressSpace
, MemoryArea
->BaseAddress
,
2006 &MemoryArea
->Data
.SectionData
.RegionListHead
,
2007 BaseAddress
, Length
, Region
->Type
, Protect
,
2008 MmAlterViewAttributes
);
2014 MmQuerySectionView(PMEMORY_AREA MemoryArea
,
2016 PMEMORY_BASIC_INFORMATION Info
,
2017 PULONG ResultLength
)
2020 PVOID RegionBaseAddress
;
2021 PSECTION_OBJECT Section
;
2022 PLIST_ENTRY CurrentEntry
;
2023 PMEMORY_AREA CurrentMArea
;
2026 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
2027 &MemoryArea
->Data
.SectionData
.RegionListHead
,
2028 Address
, &RegionBaseAddress
);
2031 return STATUS_UNSUCCESSFUL
;
2033 Section
= MemoryArea
->Data
.SectionData
.Section
;
2034 if (Section
->AllocationAttributes
& SEC_IMAGE
)
2036 KeAcquireSpinLock(&Section
->ViewListLock
, &oldIrql
);
2037 CurrentEntry
= Section
->ViewListHead
.Flink
;
2038 Info
->AllocationBase
= NULL
;
2039 while (CurrentEntry
!= &Section
->ViewListHead
)
2041 CurrentMArea
= CONTAINING_RECORD(CurrentEntry
, MEMORY_AREA
, Data
.SectionData
.ViewListEntry
);
2042 CurrentEntry
= CurrentEntry
->Flink
;
2043 if (Info
->AllocationBase
== NULL
)
2045 Info
->AllocationBase
= CurrentMArea
->BaseAddress
;
2047 else if (CurrentMArea
->BaseAddress
< Info
->AllocationBase
)
2049 Info
->AllocationBase
= CurrentMArea
->BaseAddress
;
2052 KeReleaseSpinLock(&Section
->ViewListLock
, oldIrql
);
2053 Info
->BaseAddress
= MemoryArea
->BaseAddress
;
2054 Info
->AllocationProtect
= MemoryArea
->Attributes
;
2055 Info
->Type
= MEM_IMAGE
;
2059 Info
->BaseAddress
= RegionBaseAddress
;
2060 Info
->AllocationBase
= MemoryArea
->BaseAddress
;
2061 Info
->AllocationProtect
= Region
->Protect
;
2062 Info
->Type
= MEM_MAPPED
;
2064 Info
->RegionSize
= MemoryArea
->Length
;
2065 Info
->State
= MEM_COMMIT
;
2066 Info
->Protect
= Region
->Protect
;
2068 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
2069 return(STATUS_SUCCESS
);
2073 MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment
)
2078 ULONG SavedSwapEntry
;
2079 PHYSICAL_ADDRESS Page
;
2081 Page
.u
.HighPart
= 0;
2083 Length
= PAGE_ROUND_UP(Segment
->Length
);
2084 for (Offset
= 0; Offset
< Length
; Offset
+= PAGE_SIZE
)
2086 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
);
2089 if (IS_SWAP_FROM_SSE(Entry
))
2091 MmFreeSwapPage(SWAPENTRY_FROM_SSE(Entry
));
2095 Page
.u
.LowPart
= PAGE_FROM_SSE(Entry
);
2096 SavedSwapEntry
= MmGetSavedSwapEntryPage(Page
);
2097 if (SavedSwapEntry
!= 0)
2099 MmSetSavedSwapEntryPage(Page
, 0);
2100 MmFreeSwapPage(SavedSwapEntry
);
2102 MmReleasePageMemoryConsumer(MC_USER
, Page
);
2104 MmSetPageEntrySectionSegment(Segment
, Offset
, 0);
2110 MmpDeleteSection(PVOID ObjectBody
)
2112 PSECTION_OBJECT Section
= (PSECTION_OBJECT
)ObjectBody
;
2114 DPRINT("MmpDeleteSection(ObjectBody %x)\n", ObjectBody
);
2115 if (Section
->AllocationAttributes
& SEC_IMAGE
)
2120 PMM_SECTION_SEGMENT SectionSegments
;
2122 SectionSegments
= Section
->ImageSection
->Segments
;
2123 NrSegments
= Section
->ImageSection
->NrSegments
;
2125 for (i
= 0; i
< NrSegments
; i
++)
2127 if (SectionSegments
[i
].Characteristics
& IMAGE_SECTION_CHAR_SHARED
)
2129 MmLockSectionSegment(&SectionSegments
[i
]);
2131 RefCount
= InterlockedDecrement((LONG
*)&SectionSegments
[i
].ReferenceCount
);
2132 if (SectionSegments
[i
].Characteristics
& IMAGE_SECTION_CHAR_SHARED
)
2136 MmpFreePageFileSegment(&SectionSegments
[i
]);
2138 MmUnlockSectionSegment(&SectionSegments
[i
]);
2144 if (Section
->Segment
->Flags
& MM_PAGEFILE_SEGMENT
)
2146 MmpFreePageFileSegment(Section
->Segment
);
2147 MmFreePageTablesSectionSegment(Section
->Segment
);
2148 ExFreePool(Section
->Segment
);
2149 Section
->Segment
= NULL
;
2153 InterlockedDecrement((LONG
*)&Section
->Segment
->ReferenceCount
);
2156 if (Section
->FileObject
!= NULL
)
2158 CcRosDereferenceCache(Section
->FileObject
);
2159 ObDereferenceObject(Section
->FileObject
);
2160 Section
->FileObject
= NULL
;
2165 MmpCloseSection(PVOID ObjectBody
,
2168 DPRINT("MmpCloseSection(OB %x, HC %d) RC %d\n",
2169 ObjectBody
, HandleCount
, ObGetObjectPointerCount(ObjectBody
));
2173 MmpCreateSection(PVOID ObjectBody
,
2175 PWSTR RemainingPath
,
2176 POBJECT_ATTRIBUTES ObjectAttributes
)
2178 DPRINT("MmpCreateSection(ObjectBody %x, Parent %x, RemainingPath %S)\n",
2179 ObjectBody
, Parent
, RemainingPath
);
2181 if (RemainingPath
== NULL
)
2183 return(STATUS_SUCCESS
);
2186 if (wcschr(RemainingPath
+1, L
'\\') != NULL
)
2188 return(STATUS_UNSUCCESSFUL
);
2190 return(STATUS_SUCCESS
);
2193 NTSTATUS INIT_FUNCTION
2194 MmCreatePhysicalMemorySection(VOID
)
2196 HANDLE PhysSectionH
;
2197 PSECTION_OBJECT PhysSection
;
2199 OBJECT_ATTRIBUTES Obj
;
2200 UNICODE_STRING Name
= ROS_STRING_INITIALIZER(L
"\\Device\\PhysicalMemory");
2201 LARGE_INTEGER SectionSize
;
2204 * Create the section mapping physical memory
2206 SectionSize
.QuadPart
= 0xFFFFFFFF;
2207 InitializeObjectAttributes(&Obj
,
2212 Status
= NtCreateSection(&PhysSectionH
,
2216 PAGE_EXECUTE_READWRITE
,
2219 if (!NT_SUCCESS(Status
))
2221 DbgPrint("Failed to create PhysicalMemory section\n");
2224 Status
= ObReferenceObjectByHandle(PhysSectionH
,
2228 (PVOID
*)&PhysSection
,
2230 if (!NT_SUCCESS(Status
))
2232 DbgPrint("Failed to reference PhysicalMemory section\n");
2235 PhysSection
->AllocationAttributes
|= SEC_PHYSICALMEMORY
;
2236 ObDereferenceObject((PVOID
)PhysSection
);
2238 return(STATUS_SUCCESS
);
2241 NTSTATUS INIT_FUNCTION
2242 MmInitSectionImplementation(VOID
)
2244 MmSectionObjectType
= ExAllocatePool(NonPagedPool
,sizeof(OBJECT_TYPE
));
2246 RtlRosInitUnicodeStringFromLiteral(&MmSectionObjectType
->TypeName
, L
"Section");
2248 MmSectionObjectType
->Tag
= TAG('S', 'E', 'C', 'T');
2249 MmSectionObjectType
->TotalObjects
= 0;
2250 MmSectionObjectType
->TotalHandles
= 0;
2251 MmSectionObjectType
->MaxObjects
= ULONG_MAX
;
2252 MmSectionObjectType
->MaxHandles
= ULONG_MAX
;
2253 MmSectionObjectType
->PagedPoolCharge
= 0;
2254 MmSectionObjectType
->NonpagedPoolCharge
= sizeof(SECTION_OBJECT
);
2255 MmSectionObjectType
->Mapping
= &MmpSectionMapping
;
2256 MmSectionObjectType
->Dump
= NULL
;
2257 MmSectionObjectType
->Open
= NULL
;
2258 MmSectionObjectType
->Close
= MmpCloseSection
;
2259 MmSectionObjectType
->Delete
= MmpDeleteSection
;
2260 MmSectionObjectType
->Parse
= NULL
;
2261 MmSectionObjectType
->Security
= NULL
;
2262 MmSectionObjectType
->QueryName
= NULL
;
2263 MmSectionObjectType
->OkayToClose
= NULL
;
2264 MmSectionObjectType
->Create
= MmpCreateSection
;
2265 MmSectionObjectType
->DuplicationNotify
= NULL
;
2268 * NOTE: Do not register the section object type here because
2269 * the object manager it not initialized yet!
2270 * The section object type will be created in ObInit().
2272 ObpCreateTypeObject(MmSectionObjectType
);
2274 return(STATUS_SUCCESS
);
2278 MmCreatePageFileSection(PHANDLE SectionHandle
,
2279 ACCESS_MASK DesiredAccess
,
2280 POBJECT_ATTRIBUTES ObjectAttributes
,
2281 PLARGE_INTEGER UMaximumSize
,
2282 ULONG SectionPageProtection
,
2283 ULONG AllocationAttributes
)
2285 * Create a section which is backed by the pagefile
2288 LARGE_INTEGER MaximumSize
;
2289 PSECTION_OBJECT Section
;
2290 PMM_SECTION_SEGMENT Segment
;
2293 if (UMaximumSize
== NULL
)
2295 return(STATUS_UNSUCCESSFUL
);
2297 MaximumSize
= *UMaximumSize
;
2300 * Check the protection
2302 if ((SectionPageProtection
& PAGE_FLAGS_VALID_FROM_USER_MODE
) !=
2303 SectionPageProtection
)
2305 return(STATUS_INVALID_PAGE_PROTECTION
);
2309 * Create the section
2311 Status
= ObCreateObject(ExGetPreviousMode(),
2312 MmSectionObjectType
,
2314 ExGetPreviousMode(),
2316 sizeof(SECTION_OBJECT
),
2320 if (!NT_SUCCESS(Status
))
2325 Status
= ObInsertObject ((PVOID
)Section
,
2331 if (!NT_SUCCESS(Status
))
2333 ObDereferenceObject(Section
);
2340 Section
->SectionPageProtection
= SectionPageProtection
;
2341 Section
->AllocationAttributes
= AllocationAttributes
;
2342 InitializeListHead(&Section
->ViewListHead
);
2343 KeInitializeSpinLock(&Section
->ViewListLock
);
2344 Section
->FileObject
= NULL
;
2345 Section
->MaximumSize
= MaximumSize
;
2346 Segment
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(MM_SECTION_SEGMENT
),
2347 TAG_MM_SECTION_SEGMENT
);
2348 if (Segment
== NULL
)
2350 ZwClose(*SectionHandle
);
2351 ObDereferenceObject(Section
);
2352 return(STATUS_NO_MEMORY
);
2354 Section
->Segment
= Segment
;
2355 Segment
->ReferenceCount
= 1;
2356 ExInitializeFastMutex(&Segment
->Lock
);
2357 Segment
->FileOffset
= 0;
2358 Segment
->Protection
= SectionPageProtection
;
2359 Segment
->Attributes
= AllocationAttributes
;
2360 Segment
->RawLength
= MaximumSize
.u
.LowPart
;
2361 Segment
->Length
= PAGE_ROUND_UP(MaximumSize
.u
.LowPart
);
2362 Segment
->Flags
= MM_PAGEFILE_SEGMENT
;
2363 Segment
->WriteCopy
= FALSE
;
2364 RtlZeroMemory(&Segment
->PageDirectory
, sizeof(SECTION_PAGE_DIRECTORY
));
2365 Segment
->VirtualAddress
= 0;
2366 Segment
->Characteristics
= 0;
2367 ObDereferenceObject(Section
);
2368 return(STATUS_SUCCESS
);
2373 MmCreateDataFileSection(PHANDLE SectionHandle
,
2374 ACCESS_MASK DesiredAccess
,
2375 POBJECT_ATTRIBUTES ObjectAttributes
,
2376 PLARGE_INTEGER UMaximumSize
,
2377 ULONG SectionPageProtection
,
2378 ULONG AllocationAttributes
,
2381 * Create a section backed by a data file
2384 PSECTION_OBJECT Section
;
2386 LARGE_INTEGER MaximumSize
;
2387 PFILE_OBJECT FileObject
;
2388 PMM_SECTION_SEGMENT Segment
;
2390 IO_STATUS_BLOCK Iosb
;
2391 LARGE_INTEGER Offset
;
2395 * Check the protection
2397 if ((SectionPageProtection
& PAGE_FLAGS_VALID_FROM_USER_MODE
) !=
2398 SectionPageProtection
)
2400 return(STATUS_INVALID_PAGE_PROTECTION
);
2403 * Create the section
2405 Status
= ObCreateObject(ExGetPreviousMode(),
2406 MmSectionObjectType
,
2408 ExGetPreviousMode(),
2410 sizeof(SECTION_OBJECT
),
2414 if (!NT_SUCCESS(Status
))
2419 Status
= ObInsertObject ((PVOID
)Section
,
2425 if (!NT_SUCCESS(Status
))
2427 ObDereferenceObject(Section
);
2434 Section
->SectionPageProtection
= SectionPageProtection
;
2435 Section
->AllocationAttributes
= AllocationAttributes
;
2436 InitializeListHead(&Section
->ViewListHead
);
2437 KeInitializeSpinLock(&Section
->ViewListLock
);
2440 * Check file access required
2442 if (SectionPageProtection
& PAGE_READWRITE
||
2443 SectionPageProtection
& PAGE_EXECUTE_READWRITE
)
2445 FileAccess
= FILE_READ_DATA
| FILE_WRITE_DATA
;
2449 FileAccess
= FILE_READ_DATA
;
2453 * Reference the file handle
2455 Status
= ObReferenceObjectByHandle(FileHandle
,
2459 (PVOID
*)&FileObject
,
2461 if (!NT_SUCCESS(Status
))
2463 ZwClose(*SectionHandle
);
2464 ObDereferenceObject(Section
);
2469 * We can't do memory mappings if the file system doesn't support the
2472 if (!(FileObject
->Flags
& FO_FCB_IS_VALID
))
2474 ZwClose(*SectionHandle
);
2475 ObDereferenceObject(Section
);
2476 ObDereferenceObject(FileObject
);
2477 return(STATUS_INVALID_FILE_FOR_SECTION
);
2481 * FIXME: Revise this once a locking order for file size changes is
2484 if (UMaximumSize
!= NULL
)
2486 MaximumSize
= *UMaximumSize
;
2491 ((PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
)->FileSize
;
2494 if (MaximumSize
.QuadPart
>
2495 ((PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
)->FileSize
.QuadPart
)
2497 Status
= NtSetInformationFile(FileHandle
,
2500 sizeof(LARGE_INTEGER
),
2501 FileAllocationInformation
);
2502 if (!NT_SUCCESS(Status
))
2504 ZwClose(*SectionHandle
);
2505 ObDereferenceObject(Section
);
2506 ObDereferenceObject(FileObject
);
2507 return(STATUS_SECTION_NOT_EXTENDED
);
2511 if (FileObject
->SectionObjectPointer
== NULL
||
2512 FileObject
->SectionObjectPointer
->SharedCacheMap
== NULL
)
2515 * Read a bit so caching is initiated for the file object.
2516 * This is only needed because MiReadPage currently cannot
2517 * handle non-cached streams.
2519 Offset
.QuadPart
= 0;
2520 Status
= ZwReadFile(FileHandle
,
2529 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_END_OF_FILE
))
2531 ZwClose(*SectionHandle
);
2532 ObDereferenceObject(Section
);
2533 ObDereferenceObject(FileObject
);
2536 if (FileObject
->SectionObjectPointer
== NULL
||
2537 FileObject
->SectionObjectPointer
->SharedCacheMap
== NULL
)
2539 /* FIXME: handle this situation */
2540 ZwClose(*SectionHandle
);
2541 ObDereferenceObject(Section
);
2542 ObDereferenceObject(FileObject
);
2543 return STATUS_INVALID_PARAMETER
;
2550 Status
= MmspWaitForFileLock(FileObject
);
2551 if (Status
!= STATUS_SUCCESS
)
2553 ZwClose(*SectionHandle
);
2554 ObDereferenceObject(Section
);
2555 ObDereferenceObject(FileObject
);
2560 * If this file hasn't been mapped as a data file before then allocate a
2561 * section segment to describe the data file mapping
2563 if (FileObject
->SectionObjectPointer
->DataSectionObject
== NULL
)
2565 Segment
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(MM_SECTION_SEGMENT
),
2566 TAG_MM_SECTION_SEGMENT
);
2567 if (Segment
== NULL
)
2569 KeSetEvent((PVOID
)&FileObject
->Lock
, IO_NO_INCREMENT
, FALSE
);
2570 ZwClose(*SectionHandle
);
2571 ObDereferenceObject(Section
);
2572 ObDereferenceObject(FileObject
);
2573 return(STATUS_NO_MEMORY
);
2575 Section
->Segment
= Segment
;
2576 Segment
->ReferenceCount
= 1;
2577 ExInitializeFastMutex(&Segment
->Lock
);
2579 * Set the lock before assigning the segment to the file object
2581 ExAcquireFastMutex(&Segment
->Lock
);
2582 FileObject
->SectionObjectPointer
->DataSectionObject
= (PVOID
)Segment
;
2584 Segment
->FileOffset
= 0;
2585 Segment
->Protection
= SectionPageProtection
;
2586 Segment
->Attributes
= 0;
2587 Segment
->Flags
= MM_DATAFILE_SEGMENT
;
2588 Segment
->Characteristics
= 0;
2589 Segment
->WriteCopy
= FALSE
;
2590 if (AllocationAttributes
& SEC_RESERVE
)
2592 Segment
->Length
= Segment
->RawLength
= 0;
2596 Segment
->RawLength
= MaximumSize
.u
.LowPart
;
2597 Segment
->Length
= PAGE_ROUND_UP(Segment
->RawLength
);
2599 Segment
->VirtualAddress
= NULL
;
2600 RtlZeroMemory(&Segment
->PageDirectory
, sizeof(SECTION_PAGE_DIRECTORY
));
2605 * If the file is already mapped as a data file then we may need
2609 (PMM_SECTION_SEGMENT
)FileObject
->SectionObjectPointer
->
2611 Section
->Segment
= Segment
;
2612 InterlockedIncrement((PLONG
)&Segment
->ReferenceCount
);
2613 MmLockSectionSegment(Segment
);
2615 if (MaximumSize
.u
.LowPart
> Segment
->RawLength
&&
2616 !(AllocationAttributes
& SEC_RESERVE
))
2618 Segment
->RawLength
= MaximumSize
.u
.LowPart
;
2619 Segment
->Length
= PAGE_ROUND_UP(Segment
->RawLength
);
2622 MmUnlockSectionSegment(Segment
);
2623 Section
->FileObject
= FileObject
;
2624 Section
->MaximumSize
= MaximumSize
;
2625 CcRosReferenceCache(FileObject
);
2626 KeSetEvent((PVOID
)&FileObject
->Lock
, IO_NO_INCREMENT
, FALSE
);
2627 ObDereferenceObject(Section
);
2628 return(STATUS_SUCCESS
);
2631 static ULONG SectionCharacteristicsToProtect
[16] =
2633 PAGE_NOACCESS
, // 0 = NONE
2634 PAGE_NOACCESS
, // 1 = SHARED
2635 PAGE_EXECUTE
, // 2 = EXECUTABLE
2636 PAGE_EXECUTE
, // 3 = EXECUTABLE, SHARED
2637 PAGE_READONLY
, // 4 = READABLE
2638 PAGE_READONLY
, // 5 = READABLE, SHARED
2639 PAGE_EXECUTE_READ
, // 6 = READABLE, EXECUTABLE
2640 PAGE_EXECUTE_READ
, // 7 = READABLE, EXECUTABLE, SHARED
2641 PAGE_READWRITE
, // 8 = WRITABLE
2642 PAGE_READWRITE
, // 9 = WRITABLE, SHARED
2643 PAGE_EXECUTE_READWRITE
, // 10 = WRITABLE, EXECUTABLE
2644 PAGE_EXECUTE_READWRITE
, // 11 = WRITABLE, EXECUTABLE, SHARED
2645 PAGE_READWRITE
, // 12 = WRITABLE, READABLE
2646 PAGE_READWRITE
, // 13 = WRITABLE, READABLE, SHARED
2647 PAGE_EXECUTE_READWRITE
, // 14 = WRITABLE, READABLE, EXECUTABLE,
2648 PAGE_EXECUTE_READWRITE
, // 15 = WRITABLE, READABLE, EXECUTABLE, SHARED
2652 MmCreateImageSection(PHANDLE SectionHandle
,
2653 ACCESS_MASK DesiredAccess
,
2654 POBJECT_ATTRIBUTES ObjectAttributes
,
2655 PLARGE_INTEGER UMaximumSize
,
2656 ULONG SectionPageProtection
,
2657 ULONG AllocationAttributes
,
2660 PSECTION_OBJECT Section
;
2662 PFILE_OBJECT FileObject
;
2663 IMAGE_DOS_HEADER DosHeader
;
2664 IO_STATUS_BLOCK Iosb
;
2665 LARGE_INTEGER Offset
;
2666 IMAGE_NT_HEADERS PEHeader
;
2667 PMM_SECTION_SEGMENT SectionSegments
;
2669 PMM_IMAGE_SECTION_OBJECT ImageSectionObject
;
2672 ULONG Characteristics
;
2673 ULONG FileAccess
= 0;
2675 * Check the protection
2677 if ((SectionPageProtection
& PAGE_FLAGS_VALID_FROM_USER_MODE
) !=
2678 SectionPageProtection
)
2680 return(STATUS_INVALID_PAGE_PROTECTION
);
2684 * Specifying a maximum size is meaningless for an image section
2686 if (UMaximumSize
!= NULL
)
2688 return(STATUS_INVALID_PARAMETER_4
);
2692 * Reference the file handle
2694 Status
= ObReferenceObjectByHandle(FileHandle
,
2698 (PVOID
*)&FileObject
,
2700 if (!NT_SUCCESS(Status
))
2706 * Initialized caching for this file object if previously caching
2707 * was initialized for the same on disk file
2709 Status
= CcTryToInitializeFileCache(FileObject
);
2711 if (!NT_SUCCESS(Status
) || FileObject
->SectionObjectPointer
->ImageSectionObject
== NULL
)
2713 PIMAGE_SECTION_HEADER ImageSections
;
2715 * Read the dos header and check the DOS signature
2717 Offset
.QuadPart
= 0;
2718 Status
= ZwReadFile(FileHandle
,
2727 if (!NT_SUCCESS(Status
))
2729 ObDereferenceObject(FileObject
);
2734 * Check the DOS signature
2736 if (Iosb
.Information
!= sizeof(DosHeader
) ||
2737 DosHeader
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2739 ObDereferenceObject(FileObject
);
2740 return(STATUS_INVALID_IMAGE_FORMAT
);
2744 * Read the PE header
2746 Offset
.QuadPart
= DosHeader
.e_lfanew
;
2747 Status
= ZwReadFile(FileHandle
,
2756 if (!NT_SUCCESS(Status
))
2758 ObDereferenceObject(FileObject
);
2763 * Check the signature
2765 if (Iosb
.Information
!= sizeof(PEHeader
) ||
2766 PEHeader
.Signature
!= IMAGE_NT_SIGNATURE
)
2768 ObDereferenceObject(FileObject
);
2769 return(STATUS_INVALID_IMAGE_FORMAT
);
2773 * Read in the section headers
2775 Offset
.QuadPart
= DosHeader
.e_lfanew
+ sizeof(PEHeader
);
2776 ImageSections
= ExAllocatePool(NonPagedPool
,
2777 PEHeader
.FileHeader
.NumberOfSections
*
2778 sizeof(IMAGE_SECTION_HEADER
));
2779 if (ImageSections
== NULL
)
2781 ObDereferenceObject(FileObject
);
2782 return(STATUS_NO_MEMORY
);
2785 Status
= ZwReadFile(FileHandle
,
2791 PEHeader
.FileHeader
.NumberOfSections
*
2792 sizeof(IMAGE_SECTION_HEADER
),
2795 if (!NT_SUCCESS(Status
))
2797 ObDereferenceObject(FileObject
);
2798 ExFreePool(ImageSections
);
2801 if (Iosb
.Information
!= (PEHeader
.FileHeader
.NumberOfSections
* sizeof(IMAGE_SECTION_HEADER
)))
2803 ObDereferenceObject(FileObject
);
2804 ExFreePool(ImageSections
);
2805 return(STATUS_INVALID_IMAGE_FORMAT
);
2809 * Create the section
2811 Status
= ObCreateObject (ExGetPreviousMode(),
2812 MmSectionObjectType
,
2814 ExGetPreviousMode(),
2816 sizeof(SECTION_OBJECT
),
2820 if (!NT_SUCCESS(Status
))
2822 ObDereferenceObject(FileObject
);
2823 ExFreePool(ImageSections
);
2827 Status
= ObInsertObject ((PVOID
)Section
,
2833 if (!NT_SUCCESS(Status
))
2835 ObDereferenceObject(Section
);
2836 ObDereferenceObject(FileObject
);
2837 ExFreePool(ImageSections
);
2844 Section
->SectionPageProtection
= SectionPageProtection
;
2845 Section
->AllocationAttributes
= AllocationAttributes
;
2846 InitializeListHead(&Section
->ViewListHead
);
2847 KeInitializeSpinLock(&Section
->ViewListLock
);
2850 * Check file access required
2852 if (SectionPageProtection
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
2854 FileAccess
= FILE_READ_DATA
| FILE_WRITE_DATA
;
2858 FileAccess
= FILE_READ_DATA
;
2862 * We can't do memory mappings if the file system doesn't support the
2865 if (!(FileObject
->Flags
& FO_FCB_IS_VALID
))
2867 ZwClose(*SectionHandle
);
2868 ObDereferenceObject(Section
);
2869 ObDereferenceObject(FileObject
);
2870 ExFreePool(ImageSections
);
2871 return(STATUS_INVALID_FILE_FOR_SECTION
);
2877 Status
= MmspWaitForFileLock(FileObject
);
2878 if (Status
!= STATUS_SUCCESS
)
2880 ZwClose(*SectionHandle
);
2881 ObDereferenceObject(Section
);
2882 ObDereferenceObject(FileObject
);
2883 ExFreePool(ImageSections
);
2888 * allocate the section segments to describe the mapping
2890 NrSegments
= PEHeader
.FileHeader
.NumberOfSections
+ 1;
2891 Size
= sizeof(MM_IMAGE_SECTION_OBJECT
) + sizeof(MM_SECTION_SEGMENT
) * NrSegments
;
2892 ImageSectionObject
= ExAllocatePoolWithTag(NonPagedPool
, Size
, TAG_MM_SECTION_SEGMENT
);
2893 if (ImageSectionObject
== NULL
)
2895 KeSetEvent((PVOID
)&FileObject
->Lock
, IO_NO_INCREMENT
, FALSE
);
2896 ZwClose(*SectionHandle
);
2897 ObDereferenceObject(Section
);
2898 ObDereferenceObject(FileObject
);
2899 ExFreePool(ImageSections
);
2900 return(STATUS_NO_MEMORY
);
2902 Section
->ImageSection
= ImageSectionObject
;
2903 ImageSectionObject
->NrSegments
= NrSegments
;
2904 ImageSectionObject
->ImageBase
= (PVOID
)PEHeader
.OptionalHeader
.ImageBase
;
2905 ImageSectionObject
->EntryPoint
= (PVOID
)PEHeader
.OptionalHeader
.AddressOfEntryPoint
;
2906 ImageSectionObject
->StackReserve
= PEHeader
.OptionalHeader
.SizeOfStackReserve
;
2907 ImageSectionObject
->StackCommit
= PEHeader
.OptionalHeader
.SizeOfStackCommit
;
2908 ImageSectionObject
->Subsystem
= PEHeader
.OptionalHeader
.Subsystem
;
2909 ImageSectionObject
->MinorSubsystemVersion
= PEHeader
.OptionalHeader
.MinorSubsystemVersion
;
2910 ImageSectionObject
->MajorSubsystemVersion
= PEHeader
.OptionalHeader
.MajorSubsystemVersion
;
2911 ImageSectionObject
->ImageCharacteristics
= PEHeader
.FileHeader
.Characteristics
;
2912 ImageSectionObject
->Machine
= PEHeader
.FileHeader
.Machine
;
2913 ImageSectionObject
->Executable
= (PEHeader
.OptionalHeader
.SizeOfCode
!= 0);
2915 SectionSegments
= ImageSectionObject
->Segments
;
2916 SectionSegments
[0].FileOffset
= 0;
2917 SectionSegments
[0].Characteristics
= IMAGE_SECTION_CHAR_DATA
;
2918 SectionSegments
[0].Protection
= PAGE_READONLY
;
2919 SectionSegments
[0].RawLength
= PAGE_SIZE
;
2920 SectionSegments
[0].Length
= PAGE_SIZE
;
2921 SectionSegments
[0].Flags
= 0;
2922 SectionSegments
[0].ReferenceCount
= 1;
2923 SectionSegments
[0].VirtualAddress
= 0;
2924 SectionSegments
[0].WriteCopy
= TRUE
;
2925 SectionSegments
[0].Attributes
= 0;
2926 ExInitializeFastMutex(&SectionSegments
[0].Lock
);
2927 RtlZeroMemory(&SectionSegments
[0].PageDirectory
, sizeof(SECTION_PAGE_DIRECTORY
));
2928 for (i
= 1; i
< NrSegments
; i
++)
2930 SectionSegments
[i
].FileOffset
= ImageSections
[i
-1].PointerToRawData
;
2931 SectionSegments
[i
].Characteristics
= ImageSections
[i
-1].Characteristics
;
2934 * Set up the protection and write copy variables.
2936 Characteristics
= ImageSections
[i
- 1].Characteristics
;
2937 if (Characteristics
& (IMAGE_SECTION_CHAR_READABLE
|IMAGE_SECTION_CHAR_WRITABLE
|IMAGE_SECTION_CHAR_EXECUTABLE
))
2939 SectionSegments
[i
].Protection
= SectionCharacteristicsToProtect
[Characteristics
>> 28];
2940 SectionSegments
[i
].WriteCopy
= !(Characteristics
& IMAGE_SECTION_CHAR_SHARED
);
2942 else if (Characteristics
& IMAGE_SECTION_CHAR_CODE
)
2944 SectionSegments
[i
].Protection
= PAGE_EXECUTE_READ
;
2945 SectionSegments
[i
].WriteCopy
= TRUE
;
2947 else if (Characteristics
& IMAGE_SECTION_CHAR_DATA
)
2949 SectionSegments
[i
].Protection
= PAGE_READWRITE
;
2950 SectionSegments
[i
].WriteCopy
= TRUE
;
2952 else if (Characteristics
& IMAGE_SECTION_CHAR_BSS
)
2954 SectionSegments
[i
].Protection
= PAGE_READWRITE
;
2955 SectionSegments
[i
].WriteCopy
= TRUE
;
2959 SectionSegments
[i
].Protection
= PAGE_NOACCESS
;
2960 SectionSegments
[i
].WriteCopy
= TRUE
;
2964 * Set up the attributes.
2966 if (Characteristics
& IMAGE_SECTION_CHAR_CODE
)
2968 SectionSegments
[i
].Attributes
= 0;
2970 else if (Characteristics
& IMAGE_SECTION_CHAR_DATA
)
2972 SectionSegments
[i
].Attributes
= 0;
2974 else if (Characteristics
& IMAGE_SECTION_CHAR_BSS
)
2976 SectionSegments
[i
].Attributes
= MM_SECTION_SEGMENT_BSS
;
2980 SectionSegments
[i
].Attributes
= 0;
2983 SectionSegments
[i
].RawLength
= ImageSections
[i
-1].SizeOfRawData
;
2984 SectionSegments
[i
].Length
= ImageSections
[i
-1].Misc
.VirtualSize
;
2985 SectionSegments
[i
].Flags
= 0;
2986 SectionSegments
[i
].ReferenceCount
= 1;
2987 SectionSegments
[i
].VirtualAddress
= (PVOID
)ImageSections
[i
-1].VirtualAddress
;
2988 ExInitializeFastMutex(&SectionSegments
[i
].Lock
);
2989 RtlZeroMemory(&SectionSegments
[i
].PageDirectory
, sizeof(SECTION_PAGE_DIRECTORY
));
2991 if (0 != InterlockedCompareExchange((PLONG
)&FileObject
->SectionObjectPointer
->ImageSectionObject
,
2992 (LONG
)ImageSectionObject
, 0))
2995 * An other thread has initialized the some image in the background
2997 ExFreePool(ImageSectionObject
);
2998 ImageSectionObject
= FileObject
->SectionObjectPointer
->ImageSectionObject
;
2999 Section
->ImageSection
= ImageSectionObject
;
3000 SectionSegments
= ImageSectionObject
->Segments
;
3002 for (i
= 0; i
< NrSegments
; i
++)
3004 InterlockedIncrement((LONG
*)&SectionSegments
[i
].ReferenceCount
);
3007 ExFreePool(ImageSections
);
3012 * Create the section
3014 Status
= ObCreateObject (ExGetPreviousMode(),
3015 MmSectionObjectType
,
3017 ExGetPreviousMode(),
3019 sizeof(SECTION_OBJECT
),
3023 if (!NT_SUCCESS(Status
))
3025 ObDereferenceObject(FileObject
);
3029 Status
= ObInsertObject ((PVOID
)Section
,
3035 if (!NT_SUCCESS(Status
))
3037 ObDereferenceObject(Section
);
3038 ObDereferenceObject(FileObject
);
3045 Section
->SectionPageProtection
= SectionPageProtection
;
3046 Section
->AllocationAttributes
= AllocationAttributes
;
3047 InitializeListHead(&Section
->ViewListHead
);
3048 KeInitializeSpinLock(&Section
->ViewListLock
);
3051 * Check file access required
3053 if (SectionPageProtection
& (PAGE_READWRITE
|PAGE_EXECUTE_READWRITE
))
3055 FileAccess
= FILE_READ_DATA
| FILE_WRITE_DATA
;
3059 FileAccess
= FILE_READ_DATA
;
3065 Status
= MmspWaitForFileLock(FileObject
);
3066 if (Status
!= STATUS_SUCCESS
)
3068 ZwClose(*SectionHandle
);
3069 ObDereferenceObject(Section
);
3070 ObDereferenceObject(FileObject
);
3074 ImageSectionObject
= FileObject
->SectionObjectPointer
->ImageSectionObject
;
3075 Section
->ImageSection
= ImageSectionObject
;
3076 SectionSegments
= ImageSectionObject
->Segments
;
3077 NrSegments
= ImageSectionObject
->NrSegments
;
3080 * Otherwise just reference all the section segments
3082 for (i
= 0; i
< NrSegments
; i
++)
3084 InterlockedIncrement((LONG
*)&SectionSegments
[i
].ReferenceCount
);
3088 Section
->FileObject
= FileObject
;
3089 CcRosReferenceCache(FileObject
);
3090 KeSetEvent((PVOID
)&FileObject
->Lock
, IO_NO_INCREMENT
, FALSE
);
3091 ObDereferenceObject(Section
);
3092 return(STATUS_SUCCESS
);
3099 NtCreateSection (OUT PHANDLE SectionHandle
,
3100 IN ACCESS_MASK DesiredAccess
,
3101 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
3102 IN PLARGE_INTEGER MaximumSize OPTIONAL
,
3103 IN ULONG SectionPageProtection OPTIONAL
,
3104 IN ULONG AllocationAttributes
,
3105 IN HANDLE FileHandle OPTIONAL
)
3107 if (AllocationAttributes
& SEC_IMAGE
)
3109 return(MmCreateImageSection(SectionHandle
,
3113 SectionPageProtection
,
3114 AllocationAttributes
,
3118 if (FileHandle
!= NULL
)
3120 return(MmCreateDataFileSection(SectionHandle
,
3124 SectionPageProtection
,
3125 AllocationAttributes
,
3129 return(MmCreatePageFileSection(SectionHandle
,
3133 SectionPageProtection
,
3134 AllocationAttributes
));
3138 /**********************************************************************
3156 NtOpenSection(PHANDLE SectionHandle
,
3157 ACCESS_MASK DesiredAccess
,
3158 POBJECT_ATTRIBUTES ObjectAttributes
)
3164 Status
= ObOpenObjectByName(ObjectAttributes
,
3165 MmSectionObjectType
,
3176 MmMapViewOfSegment(PEPROCESS Process
,
3177 PMADDRESS_SPACE AddressSpace
,
3178 PSECTION_OBJECT Section
,
3179 PMM_SECTION_SEGMENT Segment
,
3189 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
3191 BoundaryAddressMultiple
.QuadPart
= 0;
3193 Status
= MmCreateMemoryArea(Process
,
3195 MEMORY_AREA_SECTION_VIEW
,
3202 BoundaryAddressMultiple
);
3203 if (!NT_SUCCESS(Status
))
3205 DPRINT1("Mapping between 0x%.8X and 0x%.8X failed.\n",
3206 (*BaseAddress
), (char*)(*BaseAddress
) + ViewSize
);
3210 KeAcquireSpinLock(&Section
->ViewListLock
, &oldIrql
);
3211 InsertTailList(&Section
->ViewListHead
,
3212 &MArea
->Data
.SectionData
.ViewListEntry
);
3213 KeReleaseSpinLock(&Section
->ViewListLock
, oldIrql
);
3215 ObReferenceObjectByPointer((PVOID
)Section
,
3218 ExGetPreviousMode());
3219 MArea
->Data
.SectionData
.Segment
= Segment
;
3220 MArea
->Data
.SectionData
.Section
= Section
;
3221 MArea
->Data
.SectionData
.ViewOffset
= ViewOffset
;
3222 MArea
->Data
.SectionData
.WriteCopyView
= FALSE
;
3223 MmInitialiseRegion(&MArea
->Data
.SectionData
.RegionListHead
,
3224 ViewSize
, 0, Protect
);
3226 return(STATUS_SUCCESS
);
3230 /**********************************************************************
3232 * NtMapViewOfSection
3235 * Maps a view of a section into the virtual address space of a
3240 * Handle of the section.
3243 * Handle of the process.
3246 * Desired base address (or NULL) on entry;
3247 * Actual base address of the view on exit.
3250 * Number of high order address bits that must be zero.
3253 * Size in bytes of the initially committed section of
3257 * Offset in bytes from the beginning of the section
3258 * to the beginning of the view.
3261 * Desired length of map (or zero to map all) on entry
3262 * Actual length mapped on exit.
3264 * InheritDisposition
3265 * Specified how the view is to be shared with
3269 * Type of allocation for the pages.
3272 * Protection for the committed region of the view.
3280 NtMapViewOfSection(HANDLE SectionHandle
,
3281 HANDLE ProcessHandle
,
3285 PLARGE_INTEGER SectionOffset
,
3287 SECTION_INHERIT InheritDisposition
,
3288 ULONG AllocationType
,
3291 PSECTION_OBJECT Section
;
3294 PMADDRESS_SPACE AddressSpace
;
3296 Status
= ObReferenceObjectByHandle(ProcessHandle
,
3297 PROCESS_VM_OPERATION
,
3302 if (!NT_SUCCESS(Status
))
3307 AddressSpace
= &Process
->AddressSpace
;
3309 Status
= ObReferenceObjectByHandle(SectionHandle
,
3311 MmSectionObjectType
,
3315 if (!(NT_SUCCESS(Status
)))
3317 DPRINT("ObReference failed rc=%x\n",Status
);
3318 ObDereferenceObject(Process
);
3322 Status
= MmMapViewOfSection(Section
,
3333 ObDereferenceObject(Section
);
3334 ObDereferenceObject(Process
);
3340 MmFreeSectionPage(PVOID Context
, MEMORY_AREA
* MemoryArea
, PVOID Address
,
3341 PHYSICAL_ADDRESS PhysAddr
, SWAPENTRY SwapEntry
,
3346 PFILE_OBJECT FileObject
;
3349 SWAPENTRY SavedSwapEntry
;
3352 PSECTION_OBJECT Section
;
3353 PMM_SECTION_SEGMENT Segment
;
3355 MArea
= (PMEMORY_AREA
)Context
;
3357 Address
= (PVOID
)PAGE_ROUND_DOWN(Address
);
3359 Offset
= ((ULONG
)Address
- (ULONG
)MArea
->BaseAddress
);
3361 Section
= MArea
->Data
.SectionData
.Section
;
3362 Segment
= MArea
->Data
.SectionData
.Segment
;
3365 PageOp
= MmCheckForPageOp(MArea
, 0, NULL
, Segment
, Offset
);
3369 MmUnlockSectionSegment(Segment
);
3370 MmUnlockAddressSpace(&MArea
->Process
->AddressSpace
);
3372 Status
= MmspWaitForPageOpCompletionEvent(PageOp
);
3373 if (Status
!= STATUS_SUCCESS
)
3375 DPRINT1("Failed to wait for page op, status = %x\n", Status
);
3379 MmLockAddressSpace(&MArea
->Process
->AddressSpace
);
3380 MmLockSectionSegment(Segment
);
3381 MmspCompleteAndReleasePageOp(PageOp
);
3382 PageOp
= MmCheckForPageOp(MArea
, 0, NULL
, Segment
, Offset
);
3385 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
);
3388 * For a dirty, datafile, non-private page mark it as dirty in the
3391 if (Segment
->Flags
& MM_DATAFILE_SEGMENT
)
3393 if (PhysAddr
.QuadPart
== PAGE_FROM_SSE(Entry
) && Dirty
)
3395 FileObject
= MemoryArea
->Data
.SectionData
.Section
->FileObject
;
3396 Bcb
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
3397 CcRosMarkDirtyCacheSegment(Bcb
, Offset
);
3398 assert(SwapEntry
== 0);
3407 if (Segment
->Flags
& MM_PAGEFILE_SEGMENT
)
3409 DPRINT1("Found a swap entry for a page in a pagefile section.\n");
3412 MmFreeSwapPage(SwapEntry
);
3414 else if (PhysAddr
.QuadPart
!= 0)
3416 if (IS_SWAP_FROM_SSE(Entry
) ||
3417 PhysAddr
.QuadPart
!= (PAGE_FROM_SSE(Entry
)))
3422 if (Segment
->Flags
& MM_PAGEFILE_SEGMENT
)
3424 DPRINT1("Found a private page in a pagefile section.\n");
3428 * Just dereference private pages
3430 SavedSwapEntry
= MmGetSavedSwapEntryPage(PhysAddr
);
3431 if (SavedSwapEntry
!= 0)
3433 MmFreeSwapPage(SavedSwapEntry
);
3434 MmSetSavedSwapEntryPage(PhysAddr
, 0);
3436 MmDeleteRmap(PhysAddr
, MArea
->Process
, Address
);
3437 MmReleasePageMemoryConsumer(MC_USER
, PhysAddr
);
3441 MmDeleteRmap(PhysAddr
, MArea
->Process
, Address
);
3442 MmUnsharePageEntrySectionSegment(Section
, Segment
, Offset
, Dirty
, FALSE
);
3448 MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace
,
3452 PMEMORY_AREA MemoryArea
;
3453 PSECTION_OBJECT Section
;
3454 PMM_SECTION_SEGMENT Segment
;
3456 PLIST_ENTRY CurrentEntry
;
3457 PMM_REGION CurrentRegion
;
3458 PLIST_ENTRY RegionListHead
;
3460 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
3462 if (MemoryArea
== NULL
)
3464 return(STATUS_UNSUCCESSFUL
);
3467 MemoryArea
->DeleteInProgress
= TRUE
;
3468 Section
= MemoryArea
->Data
.SectionData
.Section
;
3469 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
3471 MmLockSectionSegment(Segment
);
3472 KeAcquireSpinLock(&Section
->ViewListLock
, &oldIrql
);
3473 RemoveEntryList(&MemoryArea
->Data
.SectionData
.ViewListEntry
);
3474 KeReleaseSpinLock(&Section
->ViewListLock
, oldIrql
);
3476 RegionListHead
= &MemoryArea
->Data
.SectionData
.RegionListHead
;
3477 while (!IsListEmpty(RegionListHead
))
3479 CurrentEntry
= RemoveHeadList(RegionListHead
);
3480 CurrentRegion
= CONTAINING_RECORD(CurrentEntry
, MM_REGION
, RegionListEntry
);
3481 ExFreePool(CurrentRegion
);
3484 if (Section
->AllocationAttributes
& SEC_PHYSICALMEMORY
)
3486 Status
= MmFreeMemoryArea(AddressSpace
,
3494 Status
= MmFreeMemoryArea(AddressSpace
,
3500 MmUnlockSectionSegment(Segment
);
3501 ObDereferenceObject(Section
);
3502 return(STATUS_SUCCESS
);
3509 MmUnmapViewOfSection(PEPROCESS Process
,
3513 PMEMORY_AREA MemoryArea
;
3514 PMADDRESS_SPACE AddressSpace
;
3515 PSECTION_OBJECT Section
;
3517 DPRINT("Opening memory area Process %x BaseAddress %x\n",
3518 Process
, BaseAddress
);
3522 AddressSpace
= &Process
->AddressSpace
;
3523 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
3525 if (MemoryArea
== NULL
)
3527 return(STATUS_UNSUCCESSFUL
);
3530 Section
= MemoryArea
->Data
.SectionData
.Section
;
3532 if (Section
->AllocationAttributes
& SEC_IMAGE
)
3536 PMM_IMAGE_SECTION_OBJECT ImageSectionObject
;
3537 PMM_SECTION_SEGMENT SectionSegments
;
3538 PVOID ImageBaseAddress
= 0;
3539 PMM_SECTION_SEGMENT Segment
;
3541 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
3542 ImageSectionObject
= Section
->ImageSection
;
3543 SectionSegments
= ImageSectionObject
->Segments
;
3544 NrSegments
= ImageSectionObject
->NrSegments
;
3546 /* Search for the current segment within the section segments
3547 * and calculate the image base address */
3548 for (i
= 0; i
< NrSegments
; i
++)
3550 if (!(SectionSegments
[i
].Characteristics
& IMAGE_SECTION_NOLOAD
))
3552 if (Segment
== &SectionSegments
[i
])
3554 ImageBaseAddress
= (char*)BaseAddress
- (ULONG_PTR
)SectionSegments
[i
].VirtualAddress
;
3559 if (i
>= NrSegments
)
3564 for (i
= 0; i
< NrSegments
; i
++)
3566 if (!(SectionSegments
[i
].Characteristics
& IMAGE_SECTION_NOLOAD
))
3568 PVOID SBaseAddress
= (PVOID
)
3569 ((char*)ImageBaseAddress
+ (ULONG_PTR
)SectionSegments
[i
].VirtualAddress
);
3571 Status
= MmUnmapViewOfSegment(AddressSpace
, SBaseAddress
);
3577 Status
= MmUnmapViewOfSegment(AddressSpace
, BaseAddress
);
3579 return(STATUS_SUCCESS
);
3582 /**********************************************************************
3584 * NtUnmapViewOfSection
3599 NtUnmapViewOfSection (HANDLE ProcessHandle
,
3605 DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n",
3606 ProcessHandle
, BaseAddress
);
3608 DPRINT("Referencing process\n");
3609 Status
= ObReferenceObjectByHandle(ProcessHandle
,
3610 PROCESS_VM_OPERATION
,
3615 if (!NT_SUCCESS(Status
))
3617 DPRINT("ObReferenceObjectByHandle failed (Status %x)\n", Status
);
3621 MmLockAddressSpace(&Process
->AddressSpace
);
3622 Status
= MmUnmapViewOfSection(Process
, BaseAddress
);
3623 MmUnlockAddressSpace(&Process
->AddressSpace
);
3625 ObDereferenceObject(Process
);
3632 NtQuerySection (IN HANDLE SectionHandle
,
3633 IN CINT SectionInformationClass
,
3634 OUT PVOID SectionInformation
,
3636 OUT PULONG ResultLength
)
3638 * FUNCTION: Queries the information of a section object.
3640 * SectionHandle = Handle to the section link object
3641 * SectionInformationClass = Index to a certain information structure
3642 * SectionInformation (OUT)= Caller supplies storage for resulting
3644 * Length = Size of the supplied storage
3645 * ResultLength = Data written
3650 PSECTION_OBJECT Section
;
3653 Status
= ObReferenceObjectByHandle(SectionHandle
,
3655 MmSectionObjectType
,
3659 if (!(NT_SUCCESS(Status
)))
3664 switch (SectionInformationClass
)
3666 case SectionBasicInformation
:
3668 PSECTION_BASIC_INFORMATION Sbi
;
3670 if (Length
!= sizeof(SECTION_BASIC_INFORMATION
))
3672 ObDereferenceObject(Section
);
3673 return(STATUS_INFO_LENGTH_MISMATCH
);
3676 Sbi
= (PSECTION_BASIC_INFORMATION
)SectionInformation
;
3678 Sbi
->BaseAddress
= 0;
3679 Sbi
->Attributes
= 0;
3680 Sbi
->Size
.QuadPart
= 0;
3682 *ResultLength
= sizeof(SECTION_BASIC_INFORMATION
);
3683 Status
= STATUS_SUCCESS
;
3687 case SectionImageInformation
:
3689 PSECTION_IMAGE_INFORMATION Sii
;
3691 if (Length
!= sizeof(SECTION_IMAGE_INFORMATION
))
3693 ObDereferenceObject(Section
);
3694 return(STATUS_INFO_LENGTH_MISMATCH
);
3697 Sii
= (PSECTION_IMAGE_INFORMATION
)SectionInformation
;
3698 memset(Sii
, 0, sizeof(SECTION_IMAGE_INFORMATION
));
3699 if (Section
->AllocationAttributes
& SEC_IMAGE
)
3701 PMM_IMAGE_SECTION_OBJECT ImageSectionObject
;
3702 ImageSectionObject
= Section
->ImageSection
;
3704 Sii
->EntryPoint
= ImageSectionObject
->EntryPoint
;
3705 Sii
->StackReserve
= ImageSectionObject
->StackReserve
;
3706 Sii
->StackCommit
= ImageSectionObject
->StackCommit
;
3707 Sii
->Subsystem
= ImageSectionObject
->Subsystem
;
3708 Sii
->MinorSubsystemVersion
= (USHORT
)ImageSectionObject
->MinorSubsystemVersion
;
3709 Sii
->MajorSubsystemVersion
= (USHORT
)ImageSectionObject
->MajorSubsystemVersion
;
3710 Sii
->Characteristics
= ImageSectionObject
->ImageCharacteristics
;
3711 Sii
->ImageNumber
= ImageSectionObject
->Machine
;
3712 Sii
->Executable
= ImageSectionObject
->Executable
;
3714 *ResultLength
= sizeof(SECTION_IMAGE_INFORMATION
);
3715 Status
= STATUS_SUCCESS
;
3721 Status
= STATUS_INVALID_INFO_CLASS
;
3723 ObDereferenceObject(Section
);
3729 NtExtendSection(IN HANDLE SectionHandle
,
3730 IN ULONG NewMaximumSize
)
3733 return(STATUS_NOT_IMPLEMENTED
);
3737 /**********************************************************************
3739 * MmAllocateSection@4
3749 * Code taken from ntoskrnl/mm/special.c.
3754 MmAllocateSection (IN ULONG Length
)
3760 PMADDRESS_SPACE AddressSpace
;
3761 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
3763 DPRINT("MmAllocateSection(Length %x)\n",Length
);
3765 BoundaryAddressMultiple
.QuadPart
= 0;
3767 AddressSpace
= MmGetKernelAddressSpace();
3769 MmLockAddressSpace(AddressSpace
);
3770 Status
= MmCreateMemoryArea (NULL
,
3779 BoundaryAddressMultiple
);
3780 MmUnlockAddressSpace(AddressSpace
);
3782 if (!NT_SUCCESS(Status
))
3786 DPRINT("Result %p\n",Result
);
3787 for (i
= 0; i
< PAGE_ROUND_UP(Length
) / PAGE_SIZE
; i
++)
3789 PHYSICAL_ADDRESS Page
;
3791 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
, &Page
);
3792 if (!NT_SUCCESS(Status
))
3794 DbgPrint("Unable to allocate page\n");
3797 Status
= MmCreateVirtualMapping (NULL
,
3798 ((char*)Result
+ (i
* PAGE_SIZE
)),
3802 if (!NT_SUCCESS(Status
))
3804 DbgPrint("Unable to create virtual mapping\n");
3808 return ((PVOID
)Result
);
3812 /**********************************************************************
3814 * MmMapViewOfSection
3817 * Maps a view of a section into the virtual address space of a
3822 * Pointer to the section object.
3825 * Pointer to the process.
3828 * Desired base address (or NULL) on entry;
3829 * Actual base address of the view on exit.
3832 * Number of high order address bits that must be zero.
3835 * Size in bytes of the initially committed section of
3839 * Offset in bytes from the beginning of the section
3840 * to the beginning of the view.
3843 * Desired length of map (or zero to map all) on entry
3844 * Actual length mapped on exit.
3846 * InheritDisposition
3847 * Specified how the view is to be shared with
3851 * Type of allocation for the pages.
3854 * Protection for the committed region of the view.
3862 MmMapViewOfSection(IN PVOID SectionObject
,
3863 IN PEPROCESS Process
,
3864 IN OUT PVOID
*BaseAddress
,
3866 IN ULONG CommitSize
,
3867 IN OUT PLARGE_INTEGER SectionOffset OPTIONAL
,
3868 IN OUT PULONG ViewSize
,
3869 IN SECTION_INHERIT InheritDisposition
,
3870 IN ULONG AllocationType
,
3873 PSECTION_OBJECT Section
;
3874 PMADDRESS_SPACE AddressSpace
;
3876 NTSTATUS Status
= STATUS_SUCCESS
;
3880 Section
= (PSECTION_OBJECT
)SectionObject
;
3881 AddressSpace
= &Process
->AddressSpace
;
3883 MmLockAddressSpace(AddressSpace
);
3885 if (Section
->AllocationAttributes
& SEC_IMAGE
)
3891 PMM_IMAGE_SECTION_OBJECT ImageSectionObject
;
3892 PMM_SECTION_SEGMENT SectionSegments
;
3894 ImageSectionObject
= Section
->ImageSection
;
3895 SectionSegments
= ImageSectionObject
->Segments
;
3896 NrSegments
= ImageSectionObject
->NrSegments
;
3899 ImageBase
= *BaseAddress
;
3900 if (ImageBase
== NULL
)
3902 ImageBase
= ImageSectionObject
->ImageBase
;
3906 for (i
= 0; i
< NrSegments
; i
++)
3908 if (!(SectionSegments
[i
].Characteristics
& IMAGE_SECTION_NOLOAD
))
3911 MaxExtent
= (ULONG
)((char*)SectionSegments
[i
].VirtualAddress
+
3912 SectionSegments
[i
].Length
);
3913 ImageSize
= max(ImageSize
, MaxExtent
);
3917 /* Check there is enough space to map the section at that point. */
3918 if (MmOpenMemoryAreaByRegion(AddressSpace
, ImageBase
,
3919 PAGE_ROUND_UP(ImageSize
)) != NULL
)
3921 /* Fail if the user requested a fixed base address. */
3922 if ((*BaseAddress
) != NULL
)
3924 MmUnlockAddressSpace(AddressSpace
);
3925 return(STATUS_UNSUCCESSFUL
);
3927 /* Otherwise find a gap to map the image. */
3928 ImageBase
= MmFindGap(AddressSpace
, PAGE_ROUND_UP(ImageSize
), FALSE
);
3929 if (ImageBase
== NULL
)
3931 MmUnlockAddressSpace(AddressSpace
);
3932 return(STATUS_UNSUCCESSFUL
);
3936 for (i
= 0; i
< NrSegments
; i
++)
3938 if (!(SectionSegments
[i
].Characteristics
& IMAGE_SECTION_NOLOAD
))
3940 PVOID SBaseAddress
= (PVOID
)
3941 ((char*)ImageBase
+ (ULONG_PTR
)SectionSegments
[i
].VirtualAddress
);
3942 MmLockSectionSegment(&SectionSegments
[i
]);
3943 Status
= MmMapViewOfSegment(Process
,
3946 &SectionSegments
[i
],
3948 SectionSegments
[i
].Length
,
3949 SectionSegments
[i
].Protection
,
3950 (ULONG_PTR
)SectionSegments
[i
].VirtualAddress
,
3952 MmUnlockSectionSegment(&SectionSegments
[i
]);
3953 if (!NT_SUCCESS(Status
))
3955 MmUnlockAddressSpace(AddressSpace
);
3961 *BaseAddress
= ImageBase
;
3965 if (ViewSize
== NULL
)
3967 /* Following this pointer would lead to us to the dark side */
3968 /* What to do? Bugcheck? Return status? Do the mambo? */
3969 KEBUGCHECK(MEMORY_MANAGEMENT
);
3972 if (SectionOffset
== NULL
)
3978 ViewOffset
= SectionOffset
->u
.LowPart
;
3981 if ((ViewOffset
% PAGE_SIZE
) != 0)
3983 MmUnlockAddressSpace(AddressSpace
);
3984 return(STATUS_MAPPED_ALIGNMENT
);
3987 if ((*ViewSize
) == 0)
3989 (*ViewSize
) = Section
->MaximumSize
.u
.LowPart
- ViewOffset
;
3991 else if (((*ViewSize
)+ViewOffset
) > Section
->MaximumSize
.u
.LowPart
)
3993 (*ViewSize
) = Section
->MaximumSize
.u
.LowPart
- ViewOffset
;
3996 MmLockSectionSegment(Section
->Segment
);
3997 Status
= MmMapViewOfSegment(Process
,
4005 (AllocationType
& MEM_TOP_DOWN
));
4006 MmUnlockSectionSegment(Section
->Segment
);
4007 if (!NT_SUCCESS(Status
))
4009 MmUnlockAddressSpace(AddressSpace
);
4014 MmUnlockAddressSpace(AddressSpace
);
4016 return(STATUS_SUCCESS
);
4023 MmCanFileBeTruncated (IN PSECTION_OBJECT_POINTERS SectionObjectPointer
,
4024 IN PLARGE_INTEGER NewFileSize
)
4035 MmDisableModifiedWriteOfSection (DWORD Unknown0
)
4045 MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer
,
4046 IN MMFLUSH_TYPE FlushType
)
4050 case MmFlushForDelete
:
4051 if (SectionObjectPointer
->ImageSectionObject
||
4052 SectionObjectPointer
->DataSectionObject
)
4056 CcRosSetRemoveOnClose(SectionObjectPointer
);
4058 case MmFlushForWrite
:
4068 MmForceSectionClosed (DWORD Unknown0
,
4080 MmMapViewInSystemSpace (IN PVOID SectionObject
,
4081 OUT PVOID
* MappedBase
,
4082 IN OUT PULONG ViewSize
)
4084 PSECTION_OBJECT Section
;
4085 PMADDRESS_SPACE AddressSpace
;
4088 DPRINT("MmMapViewInSystemSpace() called\n");
4090 Section
= (PSECTION_OBJECT
)SectionObject
;
4091 AddressSpace
= MmGetKernelAddressSpace();
4093 MmLockAddressSpace(AddressSpace
);
4096 if ((*ViewSize
) == 0)
4098 (*ViewSize
) = Section
->MaximumSize
.u
.LowPart
;
4100 else if ((*ViewSize
) > Section
->MaximumSize
.u
.LowPart
)
4102 (*ViewSize
) = Section
->MaximumSize
.u
.LowPart
;
4105 MmLockSectionSegment(Section
->Segment
);
4108 Status
= MmMapViewOfSegment(NULL
,
4118 MmUnlockSectionSegment(Section
->Segment
);
4119 MmUnlockAddressSpace(AddressSpace
);
4129 MmUnmapViewInSystemSpace (IN PVOID MappedBase
)
4131 PMADDRESS_SPACE AddressSpace
;
4134 DPRINT("MmUnmapViewInSystemSpace() called\n");
4136 AddressSpace
= MmGetKernelAddressSpace();
4138 Status
= MmUnmapViewOfSegment(AddressSpace
, MappedBase
);
4148 MmSetBankedSection (DWORD Unknown0
,
4156 return (STATUS_NOT_IMPLEMENTED
);
4160 /**********************************************************************
4165 * Creates a section object.
4168 * SectionObjiect (OUT)
4169 * Caller supplied storage for the resulting pointer
4170 * to a SECTION_OBJECT instance;
4173 * Specifies the desired access to the section can be a
4175 * STANDARD_RIGHTS_REQUIRED |
4177 * SECTION_MAP_WRITE |
4178 * SECTION_MAP_READ |
4179 * SECTION_MAP_EXECUTE
4181 * ObjectAttributes [OPTIONAL]
4182 * Initialized attributes for the object can be used
4183 * to create a named section;
4186 * Maximizes the size of the memory section. Must be
4187 * non-NULL for a page-file backed section.
4188 * If value specified for a mapped file and the file is
4189 * not large enough, file will be extended.
4191 * SectionPageProtection
4192 * Can be a combination of:
4198 * AllocationAttributes
4199 * Can be a combination of:
4204 * Handle to a file to create a section mapped to a file
4205 * instead of a memory backed section;
4216 MmCreateSection (OUT PSECTION_OBJECT
* SectionObject
,
4217 IN ACCESS_MASK DesiredAccess
,
4218 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
4219 IN PLARGE_INTEGER MaximumSize
,
4220 IN ULONG SectionPageProtection
,
4221 IN ULONG AllocationAttributes
,
4222 IN HANDLE FileHandle OPTIONAL
,
4223 IN PFILE_OBJECT File OPTIONAL
)
4225 return (STATUS_NOT_IMPLEMENTED
);