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.
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 #include <ddk/ntddk.h>
33 #include <internal/mm.h>
34 #include <internal/io.h>
35 #include <internal/ps.h>
36 #include <internal/pool.h>
37 #include <internal/cc.h>
38 #include <ddk/ntifs.h>
39 #include <ntos/minmax.h>
42 #include <internal/debug.h>
44 /* TYPES *********************************************************************/
48 PSECTION_OBJECT Section;
49 PMM_SECTION_SEGMENT Segment;
53 } MM_SECTION_PAGEOUT_CONTEXT;
55 /* GLOBALS *******************************************************************/
57 POBJECT_TYPE EXPORTED MmSectionObjectType = NULL;
59 static GENERIC_MAPPING MmpSectionMapping = {
60 STANDARD_RIGHTS_READ | SECTION_MAP_READ | SECTION_QUERY,
61 STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE,
62 STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE,
65 #define TAG_MM_SECTION_SEGMENT TAG('M', 'M', 'S', 'S')
66 #define TAG_SECTION_PAGE_TABLE TAG('M', 'S', 'P', 'T')
68 #define PAGE_FROM_SSE(E) ((E) & 0xFFFFF000)
69 #define SHARE_COUNT_FROM_SSE(E) (((E) & 0x00000FFE) >> 1)
70 #define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
71 #define MAX_SHARE_COUNT 0x7FF
72 #define MAKE_SSE(P, C) ((P) | ((C) << 1))
73 #define SWAPENTRY_FROM_SSE(E) ((E) >> 1)
74 #define MAKE_SWAP_SSE(S) (((S) << 1) | 0x1)
76 /* FUNCTIONS *****************************************************************/
79 MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment)
83 for (i = 0; i < NR_SECTION_PAGE_TABLES; i++)
85 if (Segment->PageDirectory.PageTables[i] != NULL)
87 ExFreePool(Segment->PageDirectory.PageTables[i]);
93 MmFreeSectionSegments(PFILE_OBJECT FileObject)
95 if (FileObject->SectionObjectPointers->ImageSectionObject != NULL)
97 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
102 (PMM_IMAGE_SECTION_OBJECT)FileObject->SectionObjectPointers->
105 for (i = 0; i < ImageSectionObject->NrSegments; i++)
107 if (ImageSectionObject->Segments[i].ReferenceCount != 0)
109 DPRINT1("Image segment %d still referenced (was %d)\n", i,
110 ImageSectionObject->Segments[i].ReferenceCount);
113 MmFreePageTablesSectionSegment(&ImageSectionObject->Segments[i]);
115 ExFreePool(ImageSectionObject);
116 FileObject->SectionObjectPointers->ImageSectionObject = NULL;
118 if (FileObject->SectionObjectPointers->DataSectionObject != NULL)
120 PMM_SECTION_SEGMENT Segment;
122 Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers->
125 if (Segment->ReferenceCount != 0)
127 DPRINT1("Data segment still referenced\n");
130 MmFreePageTablesSectionSegment(Segment);
132 FileObject->SectionObjectPointers->DataSectionObject = NULL;
137 MmLockSection(PSECTION_OBJECT Section)
139 KeWaitForSingleObject(&Section->Lock,
147 MmUnlockSection(PSECTION_OBJECT Section)
149 KeReleaseMutex(&Section->Lock, FALSE);
153 MmLockSectionSegment(PMM_SECTION_SEGMENT Segment)
155 KeWaitForSingleObject(&Segment->Lock,
163 MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment)
165 KeReleaseMutex(&Segment->Lock, FALSE);
169 MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
173 PSECTION_PAGE_TABLE Table;
174 ULONG DirectoryOffset;
177 DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
178 Table = Segment->PageDirectory.PageTables[DirectoryOffset];
182 Segment->PageDirectory.PageTables[DirectoryOffset] =
183 ExAllocatePoolWithTag(NonPagedPool, sizeof(SECTION_PAGE_TABLE),
184 TAG_SECTION_PAGE_TABLE);
185 memset(Table, 0, sizeof(SECTION_PAGE_TABLE));
186 DPRINT("Table %x\n", Table);
188 TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
189 Table->Entry[TableOffset] = Entry;
194 MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
197 PSECTION_PAGE_TABLE Table;
199 ULONG DirectoryOffset;
202 DPRINT("MmGetPageEntrySection(Offset %x)\n", Offset);
204 DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
205 Table = Segment->PageDirectory.PageTables[DirectoryOffset];
206 DPRINT("Table %x\n", Table);
211 TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
212 Entry = Table->Entry[TableOffset];
217 MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
222 Entry = MmGetPageEntrySectionSegment(Segment, Offset);
225 DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
228 if (SHARE_COUNT_FROM_SSE(Entry) == MAX_SHARE_COUNT)
230 DPRINT1("Maximum share count reached\n");
233 if (IS_SWAP_FROM_SSE(Entry))
237 Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) + 1);
238 MmSetPageEntrySectionSegment(Segment, Offset, Entry);
242 MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
243 PMM_SECTION_SEGMENT Segment,
249 Entry = MmGetPageEntrySectionSegment(Segment, Offset);
252 DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
255 if (SHARE_COUNT_FROM_SSE(Entry) == 0)
257 DPRINT1("Zero share count for unshare\n");
260 if (IS_SWAP_FROM_SSE(Entry))
264 Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) - 1);
266 * If we reducing the share count of this entry to zero then set the entry
267 * to zero and tell the cache the page is no longer mapped.
269 if (SHARE_COUNT_FROM_SSE(Entry) == 0)
271 PFILE_OBJECT FileObject;
272 PREACTOS_COMMON_FCB_HEADER Fcb;
273 SWAPENTRY SavedSwapEntry;
274 PHYSICAL_ADDRESS Page;
276 MmSetPageEntrySectionSegment(Segment, Offset, 0);
277 FileObject = Section->FileObject;
278 if (FileObject != NULL)
280 Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
282 if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
283 (Offset % PAGE_SIZE) == 0)
286 Status = CcRosUnmapCacheSegment(Fcb->Bcb, Offset, Dirty);
287 if (!NT_SUCCESS(Status))
294 Page = (PHYSICAL_ADDRESS)(LONGLONG)PAGE_FROM_SSE(Entry);
295 SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
296 if (SavedSwapEntry != 0)
298 MmFreeSwapPage(SavedSwapEntry);
299 MmSetSavedSwapEntryPage(Page, 0);
304 MmSetPageEntrySectionSegment(Segment, Offset, Entry);
306 return(SHARE_COUNT_FROM_SSE(Entry) > 1);
310 MiReadPage(PMEMORY_AREA MemoryArea,
311 PLARGE_INTEGER Offset,
312 PHYSICAL_ADDRESS* Page)
314 * FUNCTION: Read a page for a section backed memory area.
316 * MemoryArea - Memory area to read the page for.
317 * Offset - Offset of the page to read.
318 * Page - Variable that receives a page contains the read data.
324 PCACHE_SEGMENT CacheSeg;
325 PFILE_OBJECT FileObject;
327 PREACTOS_COMMON_FCB_HEADER Fcb;
329 FileObject = MemoryArea->Data.SectionData.Section->FileObject;
330 Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
335 * If the file system is letting us go directly to the cache and the
336 * memory area was mapped at an offset in the file which is page aligned
337 * then get the related cache segment.
339 if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
340 (Offset->QuadPart % PAGE_SIZE) == 0)
342 PHYSICAL_ADDRESS Addr;
345 * Get the related cache segment; we use a lower level interface than
346 * filesystems do because it is safe for us to use an offset with a
347 * alignment less than the file system block size.
349 Status = CcRosGetCacheSegment(Fcb->Bcb,
355 if (!NT_SUCCESS(Status))
362 * If the cache segment isn't up to date then call the file
363 * system to read in the data.
365 Status = ReadCacheSegment(CacheSeg);
366 if (!NT_SUCCESS(Status))
368 CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, FALSE, FALSE, FALSE);
373 * Retrieve the page from the cache segment that we actually want.
375 Addr = MmGetPhysicalAddress(BaseAddress +
376 Offset->u.LowPart - BaseOffset);
378 MmReferencePage((*Page));
380 CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE, FALSE, TRUE);
387 * Allocate a page, this is rather complicated by the possibility
388 * we might have to move other things out of memory
390 Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, Page);
391 if (!NT_SUCCESS(Status))
396 Status = CcRosGetCacheSegment(Fcb->Bcb,
402 if (!NT_SUCCESS(Status))
409 * If the cache segment isn't up to date then call the file
410 * system to read in the data.
412 Status = ReadCacheSegment(CacheSeg);
413 if (!NT_SUCCESS(Status))
415 CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, FALSE, FALSE, FALSE);
419 PageAddr = ExAllocatePageWithPhysPage(*Page);
420 OffsetInPage = BaseOffset + CacheSeg->Bcb->CacheSegmentSize - Offset->u.LowPart;
421 if (OffsetInPage >= PAGE_SIZE)
423 memcpy(PageAddr, BaseAddress + Offset->u.LowPart - BaseOffset, PAGE_SIZE);
427 memcpy(PageAddr, BaseAddress + Offset->u.LowPart - BaseOffset, OffsetInPage);
428 CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE, FALSE, FALSE);
429 Status = CcRosGetCacheSegment(Fcb->Bcb,
430 Offset->u.LowPart + OffsetInPage,
435 if (!NT_SUCCESS(Status))
437 ExUnmapPage(PageAddr);
443 * If the cache segment isn't up to date then call the file
444 * system to read in the data.
446 Status = ReadCacheSegment(CacheSeg);
447 if (!NT_SUCCESS(Status))
449 CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, FALSE, FALSE, FALSE);
450 ExUnmapPage(PageAddr);
454 memcpy(PageAddr + OffsetInPage, BaseAddress, PAGE_SIZE - OffsetInPage);
456 CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE, FALSE, FALSE);
457 ExUnmapPage(PageAddr);
459 return(STATUS_SUCCESS);
463 MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
464 MEMORY_AREA* MemoryArea,
468 LARGE_INTEGER Offset;
472 PSECTION_OBJECT Section;
473 PMM_SECTION_SEGMENT Segment;
481 * There is a window between taking the page fault and locking the
482 * address space when another thread could load the page so we check
485 if (MmIsPagePresent(NULL, Address))
489 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
491 return(STATUS_SUCCESS);
494 PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
495 Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
496 MemoryArea->Data.SectionData.ViewOffset;
501 Segment = MemoryArea->Data.SectionData.Segment;
502 Section = MemoryArea->Data.SectionData.Section;
503 Region = MmFindRegion(MemoryArea->BaseAddress,
504 &MemoryArea->Data.SectionData.RegionListHead,
506 MmLockSection(Section);
507 MmLockSectionSegment(Segment);
510 * Check if this page needs to be mapped COW
512 if ((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) &&
513 (Region->Protect == PAGE_READWRITE ||
514 Region->Protect == PAGE_EXECUTE_READWRITE))
516 Attributes = PAGE_READONLY;
520 Attributes = Region->Protect;
524 * Get or create a page operation descriptor
526 PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart,
530 DPRINT1("MmGetPageOp failed\n");
535 * Check if someone else is already handling this fault, if so wait
538 if (PageOp->Thread != PsGetCurrentThread())
540 MmUnlockSectionSegment(Segment);
541 MmUnlockSection(Section);
542 MmUnlockAddressSpace(AddressSpace);
543 Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
549 * Check for various strange conditions
551 if (Status != STATUS_SUCCESS)
553 DPRINT1("Failed to wait for page op\n");
556 if (PageOp->Status == STATUS_PENDING)
558 DPRINT1("Woke for page op before completion\n");
562 * If this wasn't a pagein then restart the operation
564 if (PageOp->OpType != MM_PAGEOP_PAGEIN)
566 MmLockAddressSpace(AddressSpace);
567 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
568 MmReleasePageOp(PageOp);
569 DPRINT("Address 0x%.8X\n", Address);
570 return(STATUS_MM_RESTART_OPERATION);
573 * If the thread handling this fault has failed then we don't retry
575 if (!NT_SUCCESS(PageOp->Status))
577 MmLockAddressSpace(AddressSpace);
578 Status = PageOp->Status;
579 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
580 MmReleasePageOp(PageOp);
581 DPRINT("Address 0x%.8X\n", Address);
584 MmLockAddressSpace(AddressSpace);
585 MmLockSection(Section);
586 MmLockSectionSegment(Segment);
588 * If the completed fault was for another address space then set the
591 if (!MmIsPagePresent(NULL, Address))
593 Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
596 MmUnlockSectionSegment(Segment);
597 MmUnlockSection(Section);
598 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
599 MmReleasePageOp(PageOp);
600 return(STATUS_MM_RESTART_OPERATION);
603 Page = (LARGE_INTEGER)(LONGLONG)(PAGE_FROM_SSE(Entry));
604 MmReferencePage(Page);
605 MmSharePageEntrySectionSegment(Segment, Offset.u.LowPart);
607 Status = MmCreateVirtualMapping(MemoryArea->Process,
609 MemoryArea->Attributes,
612 if (!NT_SUCCESS(Status))
614 DbgPrint("Unable to create virtual mapping\n");
617 MmInsertRmap(Page, MemoryArea->Process,
618 (PVOID)PAGE_ROUND_DOWN(Address));
622 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
624 MmUnlockSectionSegment(Segment);
625 MmUnlockSection(Section);
626 PageOp->Status = STATUS_SUCCESS;
627 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
628 MmReleasePageOp(PageOp);
629 DPRINT("Address 0x%.8X\n", Address);
630 return(STATUS_SUCCESS);
634 * Must be private page we have swapped out.
636 if (MmIsPageSwapEntry(NULL, (PVOID)PAddress))
641 MmUnlockSectionSegment(Segment);
642 MmUnlockSection(Section);
644 MmDeletePageFileMapping(NULL, (PVOID)PAddress, &SwapEntry);
646 Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
647 if (!NT_SUCCESS(Status))
652 Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
653 MmBuildMdlFromPages(Mdl, (PULONG)&Page);
654 Status = MmReadFromSwapPage(SwapEntry, Mdl);
655 if (!NT_SUCCESS(Status))
660 Status = MmCreateVirtualMapping(AddressSpace->Process,
665 while (Status == STATUS_NO_MEMORY)
667 MmUnlockAddressSpace(AddressSpace);
668 Status = MmCreateVirtualMapping(AddressSpace->Process,
673 MmLockAddressSpace(AddressSpace);
675 if (!NT_SUCCESS(Status))
677 DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
683 * Store the swap entry for later use.
685 MmSetSavedSwapEntryPage(Page, SwapEntry);
688 * Add the page to the process's working set
690 MmInsertRmap(Page, AddressSpace->Process,
691 (PVOID)PAGE_ROUND_DOWN(Address));
694 * Finish the operation
698 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
700 PageOp->Status = STATUS_SUCCESS;
701 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
702 MmReleasePageOp(PageOp);
703 DPRINT("Address 0x%.8X\n", Address);
704 return(STATUS_SUCCESS);
708 * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
710 if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
713 * Just map the desired physical page
715 Status = MmCreateVirtualMapping(AddressSpace->Process,
721 * Don't add an rmap entry since the page mapped could be for
726 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
730 * Cleanup and release locks
732 PageOp->Status = STATUS_SUCCESS;
733 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
734 MmReleasePageOp(PageOp);
735 MmUnlockSectionSegment(Segment);
736 MmUnlockSection(Section);
737 DPRINT("Address 0x%.8X\n", Address);
738 return(STATUS_SUCCESS);
742 * Map anonymous memory for BSS sections
744 if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS)
746 Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
747 if (!NT_SUCCESS(Status))
749 MmUnlockSectionSegment(Segment);
750 MmUnlockSection(Section);
751 MmUnlockAddressSpace(AddressSpace);
752 MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
753 MmLockAddressSpace(AddressSpace);
754 MmLockSection(Section);
755 MmLockSectionSegment(Segment);
758 Status = MmCreateVirtualMapping(AddressSpace->Process,
763 MmInsertRmap(Page, AddressSpace->Process,
764 (PVOID)PAGE_ROUND_DOWN(Address));
767 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
771 * Cleanup and release locks
773 PageOp->Status = STATUS_SUCCESS;
774 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
775 MmReleasePageOp(PageOp);
776 MmUnlockSectionSegment(Segment);
777 MmUnlockSection(Section);
778 DPRINT("Address 0x%.8X\n", Address);
779 return(STATUS_SUCCESS);
783 * Get the entry corresponding to the offset within the section
785 Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
790 * If the entry is zero (and it can't change because we have
791 * locked the segment) then we need to load the page.
795 * Release all our locks and read in the page from disk
797 MmUnlockSectionSegment(Segment);
798 MmUnlockSection(Section);
799 MmUnlockAddressSpace(AddressSpace);
801 if (Segment->Flags & MM_PAGEFILE_SEGMENT)
803 Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
807 Status = MiReadPage(MemoryArea, &Offset, &Page);
809 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
812 * FIXME: What do we know in this case?
814 DPRINT1("IoPageRead failed (Status %x)\n", Status);
817 * Cleanup and release locks
819 PageOp->Status = Status;
820 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
821 MmReleasePageOp(PageOp);
822 MmLockAddressSpace(AddressSpace);
827 * Relock the address space, section and segment
829 MmLockAddressSpace(AddressSpace);
830 MmLockSection(Section);
831 MmLockSectionSegment(Segment);
834 * Check the entry. No one should change the status of a page
835 * that has a pending page-in.
837 Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
840 DbgPrint("Someone changed ppte entry while we slept\n");
845 * Mark the offset within the section as having valid, in-memory
848 Entry = Page.u.LowPart;
849 MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
850 MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
852 Status = MmCreateVirtualMapping(AddressSpace->Process,
857 if (!NT_SUCCESS(Status))
859 MmUnlockSectionSegment(Segment);
860 MmUnlockSection(Section);
861 MmUnlockAddressSpace(AddressSpace);
862 Status = MmCreateVirtualMapping(AddressSpace->Process,
867 if (!NT_SUCCESS(Status))
871 MmLockAddressSpace(AddressSpace);
872 MmLockSection(Section);
873 MmLockSectionSegment(Segment);
875 MmInsertRmap(Page, AddressSpace->Process,
876 (PVOID)PAGE_ROUND_DOWN(Address));
877 if (!NT_SUCCESS(Status))
879 DbgPrint("Unable to create virtual mapping\n");
884 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
886 PageOp->Status = STATUS_SUCCESS;
887 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
888 MmReleasePageOp(PageOp);
889 MmUnlockSectionSegment(Segment);
890 MmUnlockSection(Section);
891 DPRINT("MmNotPresentFaultSectionView succeeded\n");
892 return(STATUS_SUCCESS);
894 else if (IS_SWAP_FROM_SSE(Entry))
899 SwapEntry = SWAPENTRY_FROM_SSE(Entry);
902 * Release all our locks and read in the page from disk
904 MmUnlockSectionSegment(Segment);
905 MmUnlockSection(Section);
906 MmUnlockAddressSpace(AddressSpace);
908 Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
909 if (!NT_SUCCESS(Status))
914 Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
915 MmBuildMdlFromPages(Mdl, (PULONG)&Page);
916 Status = MmReadFromSwapPage(SwapEntry, Mdl);
917 if (!NT_SUCCESS(Status))
923 * Relock the address space, section and segment
925 MmLockAddressSpace(AddressSpace);
926 MmLockSection(Section);
927 MmLockSectionSegment(Segment);
930 * Check the entry. No one should change the status of a page
931 * that has a pending page-in.
933 Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
936 DbgPrint("Someone changed ppte entry while we slept\n");
941 * Mark the offset within the section as having valid, in-memory
944 Entry = Page.u.LowPart;
945 MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
946 MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
949 * Save the swap entry.
951 MmSetSavedSwapEntryPage(Page, SwapEntry);
953 Status = MmCreateVirtualMapping(AddressSpace->Process,
958 MmInsertRmap(Page, AddressSpace->Process,
959 (PVOID)PAGE_ROUND_DOWN(Address));
960 if (!NT_SUCCESS(Status))
962 DbgPrint("Unable to create virtual mapping\n");
967 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
969 PageOp->Status = STATUS_SUCCESS;
970 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
971 MmReleasePageOp(PageOp);
972 MmUnlockSectionSegment(Segment);
973 MmUnlockSection(Section);
974 DPRINT("MmNotPresentFaultSectionView succeeded\n");
975 return(STATUS_SUCCESS);
980 * If the section offset is already in-memory and valid then just
981 * take another reference to the page
984 Page = (LARGE_INTEGER)(LONGLONG)PAGE_FROM_SSE(Entry);
985 MmReferencePage(Page);
986 MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
988 Status = MmCreateVirtualMapping(AddressSpace->Process,
993 MmInsertRmap(Page, AddressSpace->Process,
994 (PVOID)PAGE_ROUND_DOWN(Address));
995 if (!NT_SUCCESS(Status))
997 DbgPrint("Unable to create virtual mapping\n");
1002 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
1004 PageOp->Status = STATUS_SUCCESS;
1005 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1006 MmReleasePageOp(PageOp);
1007 MmUnlockSectionSegment(Segment);
1008 MmUnlockSection(Section);
1009 return(STATUS_SUCCESS);
1014 MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
1015 MEMORY_AREA* MemoryArea,
1019 PMM_SECTION_SEGMENT Segment;
1020 PSECTION_OBJECT Section;
1021 PHYSICAL_ADDRESS OldPage;
1022 PHYSICAL_ADDRESS NewPage;
1026 LARGE_INTEGER Offset;
1031 * Check if the page has been paged out or has already been set readwrite
1033 if (!MmIsPagePresent(NULL, Address) ||
1034 MmGetPageProtect(NULL, Address) & PAGE_READWRITE)
1036 return(STATUS_SUCCESS);
1040 * Find the offset of the page
1042 PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
1043 Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
1044 MemoryArea->Data.SectionData.ViewOffset;
1049 Segment = MemoryArea->Data.SectionData.Segment;
1050 Section = MemoryArea->Data.SectionData.Section;
1051 Region = MmFindRegion(MemoryArea->BaseAddress,
1052 &MemoryArea->Data.SectionData.RegionListHead,
1054 MmLockSection(Section);
1055 MmLockSectionSegment(Segment);
1060 if (MmGetPageEntrySectionSegment(Segment, Offset.QuadPart) == 0)
1062 DPRINT1("COW fault for page with PESS 0. Address was 0x%.8X\n",
1067 * Check if we are doing COW
1069 if (!((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) &&
1070 (Region->Protect == PAGE_READWRITE ||
1071 Region->Protect == PAGE_EXECUTE_READWRITE)))
1073 MmUnlockSection(Section);
1074 MmUnlockSectionSegment(Segment);
1075 return(STATUS_UNSUCCESSFUL);
1079 * Get or create a pageop
1081 PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart,
1082 MM_PAGEOP_ACCESSFAULT);
1085 DPRINT1("MmGetPageOp failed\n");
1090 * Wait for any other operations to complete
1092 if (PageOp->Thread != PsGetCurrentThread())
1094 MmUnlockSectionSegment(Segment);
1095 MmUnlockSection(Section);
1096 MmUnlockAddressSpace(AddressSpace);
1097 Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
1103 * Check for various strange conditions
1105 if (Status != STATUS_SUCCESS)
1107 DPRINT1("Failed to wait for page op\n");
1110 if (PageOp->Status == STATUS_PENDING)
1112 DPRINT1("Woke for page op before completion\n");
1116 * Restart the operation
1118 MmLockAddressSpace(AddressSpace);
1119 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1120 MmReleasePageOp(PageOp);
1121 return(STATUS_MM_RESTART_OPERATION);
1125 * Release locks now we have the pageop
1127 MmUnlockSectionSegment(Segment);
1128 MmUnlockSection(Section);
1129 MmUnlockAddressSpace(AddressSpace);
1134 Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage);
1139 OldPage = MmGetPhysicalAddressForProcess(NULL, Address);
1141 NewAddress = ExAllocatePageWithPhysPage(NewPage);
1142 memcpy(NewAddress, (PVOID)PAGE_ROUND_DOWN(Address), PAGE_SIZE);
1143 ExUnmapPage(NewAddress);
1146 * Delete the old entry.
1148 MmDeleteVirtualMapping(AddressSpace->Process, Address, FALSE, NULL, NULL);
1151 * Set the PTE to point to the new page
1153 MmLockAddressSpace(AddressSpace);
1154 Status = MmCreateVirtualMapping(AddressSpace->Process,
1159 MmInsertRmap(NewPage, AddressSpace->Process,
1160 (PVOID)PAGE_ROUND_DOWN(Address));
1161 if (!NT_SUCCESS(Status))
1163 DbgPrint("Unable to create virtual mapping\n");
1168 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
1172 * Unshare the old page.
1174 MmUnsharePageEntrySectionSegment(Section, Segment, Offset.QuadPart, FALSE);
1175 MmDeleteRmap(OldPage, AddressSpace->Process,
1176 (PVOID)PAGE_ROUND_DOWN(Address));
1177 MmReleasePageMemoryConsumer(MC_USER, OldPage);
1179 PageOp->Status = STATUS_SUCCESS;
1180 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1181 MmReleasePageOp(PageOp);
1182 return(STATUS_SUCCESS);
1186 MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
1188 MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
1190 PHYSICAL_ADDRESS PhysicalAddress;
1192 PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
1193 MmDeleteVirtualMapping(Process,
1200 PageOutContext->WasDirty = TRUE;
1202 if (!PageOutContext->Private)
1204 MmUnsharePageEntrySectionSegment(PageOutContext->Section,
1205 PageOutContext->Segment,
1206 PageOutContext->Offset.u.LowPart,
1207 PageOutContext->WasDirty);
1209 MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
1213 MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
1214 MEMORY_AREA* MemoryArea,
1218 LARGE_INTEGER Offset;
1219 PSECTION_OBJECT Section;
1220 PMM_SECTION_SEGMENT Segment;
1221 PHYSICAL_ADDRESS PhysicalAddress;
1222 MM_SECTION_PAGEOUT_CONTEXT Context;
1223 SWAPENTRY SwapEntry;
1228 PFILE_OBJECT FileObject;
1229 PREACTOS_COMMON_FCB_HEADER Fcb;
1230 BOOLEAN DirectMapped;
1232 Address = (PVOID)PAGE_ROUND_DOWN(Address);
1234 Offset.QuadPart = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) +
1235 MemoryArea->Data.SectionData.ViewOffset;
1237 FileObject = MemoryArea->Data.SectionData.Section->FileObject;
1238 DirectMapped = FALSE;
1239 if (FileObject != NULL)
1241 Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
1244 * If the file system is letting us go directly to the cache and the
1245 * memory area was mapped at an offset in the file which is page aligned
1246 * then note this is a direct mapped page.
1248 if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
1249 (Offset.QuadPart % PAGE_SIZE) == 0)
1251 DirectMapped = TRUE;
1256 * Get the segment and section.
1258 Segment = MemoryArea->Data.SectionData.Segment;
1259 Section = MemoryArea->Data.SectionData.Section;
1262 * This should never happen since mappings of physical memory are never
1263 * placed in the rmap lists.
1265 if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
1267 DPRINT1("Trying to page out from physical memory section address 0x%X "
1268 "process %d\n", Address, AddressSpace->Process->UniqueProcessId);
1273 * Get the section segment entry and the physical address.
1275 Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
1276 if (!MmIsPagePresent(AddressSpace->Process, Address))
1278 DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
1279 AddressSpace->Process->UniqueProcessId, Address);
1283 MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
1284 SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
1287 * Prepare the context structure for the rmap delete call.
1289 Context.Section = Section;
1290 Context.Segment = Segment;
1291 Context.Offset = Offset;
1292 Context.WasDirty = FALSE;
1293 if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS ||
1294 IS_SWAP_FROM_SSE(Entry) ||
1295 (LONGLONG)PAGE_FROM_SSE(Entry) != PhysicalAddress.QuadPart)
1297 Context.Private = Private = TRUE;
1301 Context.Private = Private = FALSE;
1305 * Take an additional reference to the page.
1307 // MmReferencePage(PhysicalAddress);
1310 * Paging out data mapped read-only is easy.
1312 if (MemoryArea->Attributes & PAGE_READONLY ||
1313 MemoryArea->Attributes & PAGE_EXECUTE_READ)
1316 * Read-only data should never be in the swapfile.
1320 DPRINT1("SwapEntry != 0 was 0x%.8X at address 0x%.8X, "
1321 "paddress 0x%.8X\n", SwapEntry, Address,
1327 * Read-only data should never be COWed
1331 DPRINT1("Had private copy of read-only page.\n");
1336 * Delete all mappings of this page.
1338 MmDeleteAllRmaps(PhysicalAddress, (PVOID)&Context,
1339 MmPageOutDeleteMapping);
1340 if (Context.WasDirty)
1345 * If this page wasn't direct mapped then we have a private copy so
1346 * release back to the system; otherwise the cache manager will have
1347 * handled freeing the cache segment which we mapped from.
1351 MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
1354 PageOp->Status = STATUS_SUCCESS;
1355 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1356 MmReleasePageOp(PageOp);
1357 return(STATUS_SUCCESS);
1361 * Otherwise we have read-write data.
1363 MmDeleteAllRmaps(PhysicalAddress, (PVOID)&Context, MmPageOutDeleteMapping);
1366 * If this wasn't a private page then we should have reduced the entry to
1367 * zero by deleting all the rmaps.
1369 if (!Private && MmGetPageEntrySectionSegment(Segment, Offset.QuadPart) != 0)
1375 * If the page wasn't dirty then we can just free it as for a readonly page.
1376 * Since we unmapped all the mappings above we know it will not suddenly
1379 if (!Context.WasDirty)
1381 if (!DirectMapped || Private)
1383 MmSetSavedSwapEntryPage(PhysicalAddress, 0);
1384 MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
1388 if (!(Segment->Characteristics & IMAGE_SECTION_CHAR_BSS) &&
1391 DPRINT1("Private page, non-dirty but not swapped out "
1392 "process %d address 0x%.8X\n",
1393 AddressSpace->Process->UniqueProcessId,
1399 Status = MmCreatePageFileMapping(AddressSpace->Process,
1402 if (!NT_SUCCESS(Status))
1409 PageOp->Status = STATUS_SUCCESS;
1410 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1411 MmReleasePageOp(PageOp);
1412 return(STATUS_SUCCESS);
1416 * If this page was direct mapped from the cache then the cache manager
1417 * will already have taken care of writing it back.
1419 if (DirectMapped && !Private)
1421 assert(SwapEntry == 0);
1422 MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
1423 PageOp->Status = STATUS_SUCCESS;
1424 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1425 MmReleasePageOp(PageOp);
1426 return(STATUS_SUCCESS);
1430 * If necessary, allocate an entry in the paging file for this page
1432 SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
1435 SwapEntry = MmAllocSwapPage();
1438 MmShowOutOfSpaceMessagePagingFile();
1441 * For private pages restore the old mappings.
1445 Status = MmCreateVirtualMapping(MemoryArea->Process,
1447 MemoryArea->Attributes,
1450 MmSetDirtyPage(MemoryArea->Process, Address);
1451 MmInsertRmap(PhysicalAddress,
1452 MemoryArea->Process,
1458 * For non-private pages if the page wasn't direct mapped then
1459 * set it back into the section segment entry so we don't loose
1460 * our copy. Otherwise it will be handled by the cache manager.
1462 Status = MmCreateVirtualMapping(MemoryArea->Process,
1464 MemoryArea->Attributes,
1467 MmSetDirtyPage(MemoryArea->Process, Address);
1468 MmInsertRmap(PhysicalAddress,
1469 MemoryArea->Process,
1471 MmSetPageEntrySectionSegment(Segment, Offset.QuadPart,
1472 PhysicalAddress.u.LowPart);
1473 MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
1475 PageOp->Status = STATUS_UNSUCCESSFUL;
1476 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1477 MmReleasePageOp(PageOp);
1478 return(STATUS_UNSUCCESSFUL);
1483 * Write the page to the pagefile
1485 Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
1486 MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress);
1487 Status = MmWriteToSwapPage(SwapEntry, Mdl);
1488 if (!NT_SUCCESS(Status))
1490 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
1493 * As above: undo our actions.
1494 * FIXME: Also free the swap page.
1498 Status = MmCreateVirtualMapping(MemoryArea->Process,
1500 MemoryArea->Attributes,
1503 MmSetDirtyPage(MemoryArea->Process, Address);
1504 MmInsertRmap(PhysicalAddress,
1505 MemoryArea->Process,
1510 Status = MmCreateVirtualMapping(MemoryArea->Process,
1512 MemoryArea->Attributes,
1515 MmSetDirtyPage(MemoryArea->Process, Address);
1516 MmInsertRmap(PhysicalAddress,
1517 MemoryArea->Process,
1519 MmSetPageEntrySectionSegment(Segment, Offset.QuadPart,
1520 PhysicalAddress.u.LowPart);
1521 MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
1523 PageOp->Status = STATUS_UNSUCCESSFUL;
1524 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1525 MmReleasePageOp(PageOp);
1526 return(STATUS_UNSUCCESSFUL);
1530 * Otherwise we have succeeded.
1532 DPRINT("MM: Wrote section page 0x%.8X to swap!\n", PhysicalAddress);
1533 MmSetSavedSwapEntryPage(PhysicalAddress, 0);
1534 MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
1538 Status = MmCreatePageFileMapping(MemoryArea->Process,
1541 if (!NT_SUCCESS(Status))
1548 Entry = MAKE_SWAP_SSE(SwapEntry);
1549 MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
1552 PageOp->Status = STATUS_SUCCESS;
1553 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1554 MmReleasePageOp(PageOp);
1555 return(STATUS_SUCCESS);
1559 MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
1560 PMEMORY_AREA MemoryArea,
1564 LARGE_INTEGER Offset;
1565 PSECTION_OBJECT Section;
1566 PMM_SECTION_SEGMENT Segment;
1567 PHYSICAL_ADDRESS PhysicalAddress;
1568 SWAPENTRY SwapEntry;
1573 PFILE_OBJECT FileObject;
1574 PREACTOS_COMMON_FCB_HEADER Fcb = NULL;
1575 BOOLEAN DirectMapped;
1577 Address = (PVOID)PAGE_ROUND_DOWN(Address);
1579 Offset.QuadPart = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) +
1580 MemoryArea->Data.SectionData.ViewOffset;
1582 FileObject = MemoryArea->Data.SectionData.Section->FileObject;
1583 DirectMapped = FALSE;
1584 if (FileObject != NULL)
1586 Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
1589 * If the file system is letting us go directly to the cache and the
1590 * memory area was mapped at an offset in the file which is page aligned
1591 * then note this is a direct mapped page.
1593 if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
1594 (Offset.QuadPart % PAGE_SIZE) == 0)
1596 DirectMapped = TRUE;
1601 * Get the segment and section.
1603 Segment = MemoryArea->Data.SectionData.Segment;
1604 Section = MemoryArea->Data.SectionData.Section;
1607 * This should never happen since mappings of physical memory are never
1608 * placed in the rmap lists.
1610 if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
1612 DPRINT1("Trying to write back page from physical memory mapped at %X "
1613 "process %d\n", Address, AddressSpace->Process->UniqueProcessId);
1618 * Get the section segment entry and the physical address.
1620 Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
1621 if (!MmIsPagePresent(AddressSpace->Process, Address))
1623 DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n",
1624 AddressSpace->Process->UniqueProcessId, Address);
1628 MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
1629 SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
1632 * Check for a private (COWed) page.
1634 if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS ||
1635 IS_SWAP_FROM_SSE(Entry) ||
1636 (LONGLONG)PAGE_FROM_SSE(Entry) != PhysicalAddress.QuadPart)
1646 * Speculatively set all mappings of the page to clean.
1648 MmSetCleanAllRmaps(PhysicalAddress);
1651 * If this page was direct mapped from the cache then the cache manager
1652 * will take care of writing it back to disk.
1654 if (DirectMapped && !Private)
1656 assert(SwapEntry == 0);
1657 CcRosMarkDirtyCacheSegment(Fcb->Bcb, Offset.u.LowPart);
1658 PageOp->Status = STATUS_SUCCESS;
1659 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1660 MmReleasePageOp(PageOp);
1661 return(STATUS_SUCCESS);
1665 * If necessary, allocate an entry in the paging file for this page
1667 SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
1670 SwapEntry = MmAllocSwapPage();
1673 MmSetDirtyAllRmaps(PhysicalAddress);
1674 PageOp->Status = STATUS_UNSUCCESSFUL;
1675 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1676 MmReleasePageOp(PageOp);
1677 return(STATUS_UNSUCCESSFUL);
1682 * Write the page to the pagefile
1684 Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
1685 MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress);
1686 Status = MmWriteToSwapPage(SwapEntry, Mdl);
1687 if (!NT_SUCCESS(Status))
1689 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
1691 MmSetDirtyAllRmaps(PhysicalAddress);
1692 PageOp->Status = STATUS_UNSUCCESSFUL;
1693 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1694 MmReleasePageOp(PageOp);
1695 return(STATUS_UNSUCCESSFUL);
1699 * Otherwise we have succeeded.
1701 DPRINT("MM: Wrote section page 0x%.8X to swap!\n", PhysicalAddress);
1702 MmSetSavedSwapEntryPage(PhysicalAddress, SwapEntry);
1703 PageOp->Status = STATUS_SUCCESS;
1704 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
1705 MmReleasePageOp(PageOp);
1706 return(STATUS_SUCCESS);
1710 MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace,
1718 PMEMORY_AREA MemoryArea;
1719 PMM_SECTION_SEGMENT Segment;
1723 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, BaseAddress);
1724 Segment = MemoryArea->Data.SectionData.Segment;
1726 if ((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) &&
1727 (NewProtect == PAGE_READWRITE || NewProtect == PAGE_EXECUTE_READWRITE))
1732 if (OldProtect != NewProtect)
1734 for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
1736 PVOID Address = BaseAddress + (i * PAGE_SIZE);
1737 ULONG Protect = NewProtect;
1740 * If we doing COW for this segment then check if the page is
1743 if (DoCOW && MmIsPagePresent(AddressSpace->Process, Address))
1745 LARGE_INTEGER Offset;
1747 LARGE_INTEGER PhysicalAddress;
1750 (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) +
1751 MemoryArea->Data.SectionData.ViewOffset;
1752 Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
1754 MmGetPhysicalAddressForProcess(AddressSpace->Process, Address);
1756 Protect = PAGE_READONLY;
1757 if ((Segment->Characteristics & IMAGE_SECTION_CHAR_BSS ||
1758 IS_SWAP_FROM_SSE(Entry) ||
1759 (LONGLONG)PAGE_FROM_SSE(Entry) != PhysicalAddress.QuadPart))
1761 Protect = NewProtect;
1765 if (MmIsPagePresent(AddressSpace->Process, Address))
1767 MmSetPageProtect(AddressSpace->Process, BaseAddress,
1775 MmProtectSectionView(PMADDRESS_SPACE AddressSpace,
1776 PMEMORY_AREA MemoryArea,
1786 min(Length, (ULONG) (MemoryArea->BaseAddress + MemoryArea->Length - BaseAddress));
1787 Region = MmFindRegion(MemoryArea->BaseAddress,
1788 &MemoryArea->Data.SectionData.RegionListHead,
1790 *OldProtect = Region->Protect;
1791 Status = MmAlterRegion(AddressSpace, MemoryArea->BaseAddress,
1792 &MemoryArea->Data.SectionData.RegionListHead,
1793 BaseAddress, Length, Region->Type, Protect,
1794 MmAlterViewAttributes);
1800 MmQuerySectionView(PMEMORY_AREA MemoryArea,
1802 PMEMORY_BASIC_INFORMATION Info,
1803 PULONG ResultLength)
1806 PVOID RegionBaseAddress;
1808 Region = MmFindRegion(MemoryArea->BaseAddress,
1809 &MemoryArea->Data.SectionData.RegionListHead,
1810 Address, &RegionBaseAddress);
1811 Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
1812 Info->AllocationBase = MemoryArea->BaseAddress;
1813 Info->AllocationProtect = MemoryArea->Attributes;
1814 Info->RegionSize = MemoryArea->Length;
1815 Info->State = MEM_COMMIT;
1816 Info->Protect = Region->Protect;
1817 if (MemoryArea->Data.SectionData.Section->AllocationAttributes & SEC_IMAGE)
1819 Info->Type = MEM_IMAGE;
1823 Info->Type = MEM_MAPPED;
1826 return(STATUS_SUCCESS);
1830 MmpDeleteSection(PVOID ObjectBody)
1832 PSECTION_OBJECT Section = (PSECTION_OBJECT)ObjectBody;
1834 DPRINT("MmpDeleteSection(ObjectBody %x)\n", ObjectBody);
1835 if (Section->AllocationAttributes & SEC_IMAGE)
1839 for (i = 0; i < Section->NrSegments; i++)
1841 InterlockedDecrement(&Section->Segments[i].ReferenceCount);
1846 InterlockedDecrement(&Section->Segments->ReferenceCount);
1848 if (Section->FileObject != NULL)
1850 CcRosDereferenceCache(Section->FileObject);
1851 ObDereferenceObject(Section->FileObject);
1852 Section->FileObject = NULL;
1855 if (Section->Segments->Flags & MM_PAGEFILE_SEGMENT)
1857 MmFreePageTablesSectionSegment(Section->Segments);
1858 ExFreePool(Section->Segments);
1863 MmpCloseSection(PVOID ObjectBody,
1866 DPRINT("MmpCloseSection(OB %x, HC %d) RC %d\n",
1867 ObjectBody, HandleCount, ObGetObjectPointerCount(ObjectBody));
1872 MmpCreateSection(PVOID ObjectBody,
1874 PWSTR RemainingPath,
1875 POBJECT_ATTRIBUTES ObjectAttributes)
1877 DPRINT("MmpCreateSection(ObjectBody %x, Parent %x, RemainingPath %S)\n",
1878 ObjectBody, Parent, RemainingPath);
1880 if (RemainingPath == NULL)
1882 return(STATUS_SUCCESS);
1885 if (wcschr(RemainingPath+1, L'\\') != NULL)
1887 return(STATUS_UNSUCCESSFUL);
1890 return(STATUS_SUCCESS);
1894 MmCreatePhysicalMemorySection(VOID)
1896 HANDLE PhysSectionH;
1897 PSECTION_OBJECT PhysSection;
1899 OBJECT_ATTRIBUTES Obj;
1900 UNICODE_STRING Name = UNICODE_STRING_INITIALIZER(L"\\Device\\PhysicalMemory");
1901 LARGE_INTEGER SectionSize;
1904 * Create the section mapping physical memory
1906 SectionSize.QuadPart = 0xFFFFFFFF;
1907 InitializeObjectAttributes(&Obj,
1912 Status = NtCreateSection(&PhysSectionH,
1916 PAGE_EXECUTE_READWRITE,
1919 if (!NT_SUCCESS(Status))
1921 DbgPrint("Failed to create PhysicalMemory section\n");
1924 Status = ObReferenceObjectByHandle(PhysSectionH,
1928 (PVOID*)&PhysSection,
1930 if (!NT_SUCCESS(Status))
1932 DbgPrint("Failed to reference PhysicalMemory section\n");
1935 PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY;
1936 ObDereferenceObject((PVOID)PhysSection);
1938 return(STATUS_SUCCESS);
1942 MmInitSectionImplementation(VOID)
1944 MmSectionObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
1946 RtlInitUnicodeStringFromLiteral(&MmSectionObjectType->TypeName, L"Section");
1948 MmSectionObjectType->Tag = TAG('S', 'E', 'C', 'T');
1949 MmSectionObjectType->TotalObjects = 0;
1950 MmSectionObjectType->TotalHandles = 0;
1951 MmSectionObjectType->MaxObjects = ULONG_MAX;
1952 MmSectionObjectType->MaxHandles = ULONG_MAX;
1953 MmSectionObjectType->PagedPoolCharge = 0;
1954 MmSectionObjectType->NonpagedPoolCharge = sizeof(SECTION_OBJECT);
1955 MmSectionObjectType->Mapping = &MmpSectionMapping;
1956 MmSectionObjectType->Dump = NULL;
1957 MmSectionObjectType->Open = NULL;
1958 MmSectionObjectType->Close = MmpCloseSection;
1959 MmSectionObjectType->Delete = MmpDeleteSection;
1960 MmSectionObjectType->Parse = NULL;
1961 MmSectionObjectType->Security = NULL;
1962 MmSectionObjectType->QueryName = NULL;
1963 MmSectionObjectType->OkayToClose = NULL;
1964 MmSectionObjectType->Create = MmpCreateSection;
1965 MmSectionObjectType->DuplicationNotify = NULL;
1967 return(STATUS_SUCCESS);
1971 MmCreatePageFileSection(PHANDLE SectionHandle,
1972 ACCESS_MASK DesiredAccess,
1973 POBJECT_ATTRIBUTES ObjectAttributes,
1974 PLARGE_INTEGER UMaximumSize,
1975 ULONG SectionPageProtection,
1976 ULONG AllocationAttributes)
1978 * Create a section which is backed by the pagefile
1981 LARGE_INTEGER MaximumSize;
1982 PSECTION_OBJECT Section;
1983 PMM_SECTION_SEGMENT Segment;
1986 if (UMaximumSize == NULL)
1988 return(STATUS_UNSUCCESSFUL);
1990 MaximumSize = *UMaximumSize;
1993 * Check the protection
1995 if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
1996 SectionPageProtection)
1998 return(STATUS_INVALID_PAGE_PROTECTION);
2002 * Create the section
2004 Status = ObCreateObject(SectionHandle,
2007 MmSectionObjectType,
2009 if (!NT_SUCCESS(Status))
2017 Section->SectionPageProtection = SectionPageProtection;
2018 Section->AllocationAttributes = AllocationAttributes;
2019 InitializeListHead(&Section->ViewListHead);
2020 KeInitializeSpinLock(&Section->ViewListLock);
2021 KeInitializeMutex(&Section->Lock, 0);
2022 Section->FileObject = NULL;
2023 Section->MaximumSize = MaximumSize;
2024 Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
2025 TAG_MM_SECTION_SEGMENT);
2026 if (Segment == NULL)
2028 ZwClose(*SectionHandle);
2029 ObDereferenceObject(Section);
2030 return(STATUS_NO_MEMORY);
2032 Section->Segments = Segment;
2033 Segment->ReferenceCount = 1;
2034 KeInitializeMutex(&Segment->Lock, 0);
2035 Segment->FileOffset = 0;
2036 Segment->Protection = SectionPageProtection;
2037 Segment->Attributes = AllocationAttributes;
2038 Segment->Length = MaximumSize.u.LowPart;
2039 Segment->Flags = MM_PAGEFILE_SEGMENT;
2040 Segment->WriteCopy = FALSE;
2041 ObDereferenceObject(Section);
2042 return(STATUS_SUCCESS);
2047 MmCreateDataFileSection(PHANDLE SectionHandle,
2048 ACCESS_MASK DesiredAccess,
2049 POBJECT_ATTRIBUTES ObjectAttributes,
2050 PLARGE_INTEGER UMaximumSize,
2051 ULONG SectionPageProtection,
2052 ULONG AllocationAttributes,
2055 * Create a section backed by a data file
2058 PSECTION_OBJECT Section;
2060 LARGE_INTEGER MaximumSize;
2061 PFILE_OBJECT FileObject;
2062 PMM_SECTION_SEGMENT Segment;
2064 IO_STATUS_BLOCK Iosb;
2065 LARGE_INTEGER Offset;
2069 * Check the protection
2071 if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
2072 SectionPageProtection)
2074 return(STATUS_INVALID_PAGE_PROTECTION);
2078 * Read a bit so caching is initiated for the file object.
2079 * This is only needed because MiReadPage currently cannot
2080 * handle non-cached streams.
2082 Offset.QuadPart = 0;
2083 Status = ZwReadFile(FileHandle,
2092 if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
2098 * Create the section
2100 Status = ObCreateObject(SectionHandle,
2103 MmSectionObjectType,
2105 if (!NT_SUCCESS(Status))
2113 Section->SectionPageProtection = SectionPageProtection;
2114 Section->AllocationAttributes = AllocationAttributes;
2115 InitializeListHead(&Section->ViewListHead);
2116 KeInitializeSpinLock(&Section->ViewListLock);
2117 KeInitializeMutex(&Section->Lock, 0);
2118 Section->NrSegments = 1;
2119 Section->ImageBase = NULL;
2120 Section->EntryPoint = NULL;
2121 Section->StackReserve = 0;
2122 Section->StackCommit = 0;
2123 Section->Subsystem = 0;
2124 Section->MinorSubsystemVersion = 0;
2125 Section->MajorSubsystemVersion = 0;
2126 Section->ImageCharacteristics = 0;
2127 Section->Machine = 0;
2128 Section->Executable = FALSE;
2131 * Check file access required
2133 if (SectionPageProtection & PAGE_READWRITE ||
2134 SectionPageProtection & PAGE_EXECUTE_READWRITE)
2136 FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
2140 FileAccess = FILE_READ_DATA;
2144 * Reference the file handle
2146 Status = ObReferenceObjectByHandle(FileHandle,
2150 (PVOID*)&FileObject,
2152 if (!NT_SUCCESS(Status))
2154 ZwClose(*SectionHandle);
2155 ObDereferenceObject(Section);
2160 * We can't do memory mappings if the file system doesn't support the
2163 if (!(FileObject->Flags & FO_FCB_IS_VALID))
2165 ZwClose(*SectionHandle);
2166 ObDereferenceObject(Section);
2167 ObDereferenceObject(FileObject);
2168 return(STATUS_INVALID_FILE_FOR_SECTION);
2172 * FIXME: Revise this once a locking order for file size changes is
2175 if (UMaximumSize != NULL)
2177 MaximumSize = *UMaximumSize;
2182 ((PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize;
2185 if (MaximumSize.QuadPart >
2186 ((PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize.QuadPart)
2188 IO_STATUS_BLOCK Iosb;
2189 Status = NtSetInformationFile(FileHandle,
2192 sizeof(LARGE_INTEGER),
2193 FileAllocationInformation);
2194 if (!NT_SUCCESS(Status))
2196 ZwClose(*SectionHandle);
2197 ObDereferenceObject(Section);
2198 ObDereferenceObject(FileObject);
2199 return(STATUS_SECTION_NOT_EXTENDED);
2206 Status = KeWaitForSingleObject((PVOID)&FileObject->Lock,
2211 if (Status != STATUS_SUCCESS)
2213 ZwClose(*SectionHandle);
2214 ObDereferenceObject(Section);
2215 ObDereferenceObject(FileObject);
2220 * If this file hasn't been mapped as a data file before then allocate a
2221 * section segment to describe the data file mapping
2223 if (FileObject->SectionObjectPointers->DataSectionObject == NULL)
2225 Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
2226 TAG_MM_SECTION_SEGMENT);
2227 if (Segment == NULL)
2229 KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2230 ZwClose(*SectionHandle);
2231 ObDereferenceObject(Section);
2232 ObDereferenceObject(FileObject);
2233 return(STATUS_NO_MEMORY);
2235 Section->Segments = Segment;
2236 Segment->ReferenceCount = 1;
2237 KeInitializeMutex(&Segment->Lock, 0);
2240 * Set the lock before assigning the segment to the file object
2242 Status = KeWaitForSingleObject((PVOID)&Segment->Lock,
2247 if (Status != STATUS_SUCCESS)
2249 KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2250 ExFreePool(Segment);
2251 ZwClose(*SectionHandle);
2252 ObDereferenceObject(Section);
2253 ObDereferenceObject(FileObject);
2256 FileObject->SectionObjectPointers->DataSectionObject = (PVOID)Segment;
2258 Segment->FileOffset = 0;
2259 Segment->Protection = 0;
2260 Segment->Attributes = 0;
2261 Segment->Flags = MM_DATAFILE_SEGMENT;
2262 Segment->Characteristics = 0;
2263 Segment->WriteCopy = FALSE;
2264 if (AllocationAttributes & SEC_RESERVE)
2266 Segment->Length = 0;
2270 Segment->Length = MaximumSize.u.LowPart;
2272 Segment->VirtualAddress = NULL;
2277 * If the file is already mapped as a data file then we may need
2281 (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers->
2283 Section->Segments = Segment;
2284 InterlockedIncrement((PLONG)&Segment->ReferenceCount);
2285 Status = KeWaitForSingleObject((PVOID)&Segment->Lock,
2290 if (Status != STATUS_SUCCESS)
2292 InterlockedDecrement((PLONG)&Segment->ReferenceCount);
2293 KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2294 ZwClose(*SectionHandle);
2295 ObDereferenceObject(Section);
2296 ObDereferenceObject(FileObject);
2299 if (MaximumSize.u.LowPart > Segment->Length &&
2300 !(AllocationAttributes & SEC_RESERVE))
2302 Segment->Length = MaximumSize.u.LowPart;
2305 KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2306 CcRosReferenceCache(FileObject);
2307 Section->FileObject = FileObject;
2308 Section->MaximumSize = MaximumSize;
2309 KeReleaseMutex(&Segment->Lock, FALSE);
2311 ObDereferenceObject(Section);
2312 return(STATUS_SUCCESS);
2315 static ULONG SectionCharacteristicsToProtect[16] =
2317 PAGE_NOACCESS, // 0 = NONE
2318 PAGE_NOACCESS, // 1 = SHARED
2319 PAGE_EXECUTE, // 2 = EXECUTABLE
2320 PAGE_EXECUTE, // 3 = EXECUTABLE, SHARED
2321 PAGE_READONLY, // 4 = READABLE
2322 PAGE_READONLY, // 5 = READABLE, SHARED
2323 PAGE_EXECUTE_READ, // 6 = READABLE, EXECUTABLE
2324 PAGE_EXECUTE_READ, // 7 = READABLE, EXECUTABLE, SHARED
2325 PAGE_READWRITE, // 8 = WRITABLE
2326 PAGE_READWRITE, // 9 = WRITABLE, SHARED
2327 PAGE_EXECUTE_READWRITE, // 10 = WRITABLE, EXECUTABLE
2328 PAGE_EXECUTE_READWRITE, // 11 = WRITABLE, EXECUTABLE, SHARED
2329 PAGE_READWRITE, // 12 = WRITABLE, READABLE
2330 PAGE_READWRITE, // 13 = WRITABLE, READABLE, SHARED
2331 PAGE_EXECUTE_READWRITE, // 14 = WRITABLE, READABLE, EXECUTABLE,
2332 PAGE_EXECUTE_READWRITE, // 15 = WRITABLE, READABLE, EXECUTABLE, SHARED
2336 MmCreateImageSection(PHANDLE SectionHandle,
2337 ACCESS_MASK DesiredAccess,
2338 POBJECT_ATTRIBUTES ObjectAttributes,
2339 PLARGE_INTEGER UMaximumSize,
2340 ULONG SectionPageProtection,
2341 ULONG AllocationAttributes,
2344 PSECTION_OBJECT Section;
2346 PFILE_OBJECT FileObject;
2348 IMAGE_DOS_HEADER DosHeader;
2349 IO_STATUS_BLOCK Iosb;
2350 LARGE_INTEGER Offset;
2351 IMAGE_NT_HEADERS PEHeader;
2352 PIMAGE_SECTION_HEADER ImageSections;
2353 PMM_SECTION_SEGMENT SectionSegments;
2355 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
2358 * Check the protection
2360 if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
2361 SectionPageProtection)
2363 return(STATUS_INVALID_PAGE_PROTECTION);
2367 * Specifying a maximum size is meaningless for an image section
2369 if (UMaximumSize != NULL)
2371 return(STATUS_INVALID_PARAMETER_4);
2375 * Read the dos header
2377 Offset.QuadPart = 0;
2378 Status = ZwReadFile(FileHandle,
2387 if (!NT_SUCCESS(Status))
2391 if (Iosb.Information != sizeof(DosHeader))
2393 return(STATUS_INVALID_IMAGE_FORMAT);
2397 * Check the DOS signature
2399 if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
2401 return(STATUS_INVALID_IMAGE_FORMAT);
2405 * Read the PE header
2407 Offset.QuadPart = DosHeader.e_lfanew;
2408 Status = ZwReadFile(FileHandle,
2417 if (!NT_SUCCESS(Status))
2421 if (Iosb.Information != sizeof(PEHeader))
2423 return(STATUS_INVALID_IMAGE_FORMAT);
2427 * Check the signature
2429 if (PEHeader.Signature != IMAGE_NT_SIGNATURE)
2431 return(STATUS_INVALID_IMAGE_FORMAT);
2435 * Read in the section headers
2437 Offset.QuadPart = DosHeader.e_lfanew + sizeof(PEHeader);
2439 ExAllocatePool(NonPagedPool,
2440 PEHeader.FileHeader.NumberOfSections *
2441 sizeof(IMAGE_SECTION_HEADER));
2442 Status = ZwReadFile(FileHandle,
2448 PEHeader.FileHeader.NumberOfSections *
2449 sizeof(IMAGE_SECTION_HEADER),
2452 if (!NT_SUCCESS(Status))
2454 ExFreePool(ImageSections);
2457 if (Iosb.Information !=
2458 (PEHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)))
2460 ExFreePool(ImageSections);
2461 return(STATUS_INVALID_IMAGE_FORMAT);
2465 * Create the section
2467 Status = ObCreateObject(SectionHandle,
2470 MmSectionObjectType,
2472 if (!NT_SUCCESS(Status))
2474 ExFreePool(ImageSections);
2481 Section->SectionPageProtection = SectionPageProtection;
2482 Section->AllocationAttributes = AllocationAttributes;
2483 InitializeListHead(&Section->ViewListHead);
2484 KeInitializeSpinLock(&Section->ViewListLock);
2485 KeInitializeMutex(&Section->Lock, 0);
2486 Section->NrSegments = PEHeader.FileHeader.NumberOfSections + 1;
2487 Section->ImageBase = (PVOID)PEHeader.OptionalHeader.ImageBase;
2488 Section->EntryPoint = (PVOID)PEHeader.OptionalHeader.AddressOfEntryPoint;
2489 Section->StackReserve = PEHeader.OptionalHeader.SizeOfStackReserve;
2490 Section->StackCommit = PEHeader.OptionalHeader.SizeOfStackCommit;
2491 Section->Subsystem = PEHeader.OptionalHeader.Subsystem;
2492 Section->MinorSubsystemVersion =
2493 PEHeader.OptionalHeader.MinorSubsystemVersion;
2494 Section->MajorSubsystemVersion =
2495 PEHeader.OptionalHeader.MajorSubsystemVersion;
2496 Section->ImageCharacteristics = PEHeader.FileHeader.Characteristics;
2497 Section->Machine = PEHeader.FileHeader.Machine;
2498 Section->Executable = (PEHeader.OptionalHeader.SizeOfCode != 0);
2501 * Check file access required
2503 if (SectionPageProtection & PAGE_READWRITE ||
2504 SectionPageProtection & PAGE_EXECUTE_READWRITE)
2506 FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
2510 FileAccess = FILE_READ_DATA;
2514 * Reference the file handle
2516 Status = ObReferenceObjectByHandle(FileHandle,
2520 (PVOID*)&FileObject,
2522 if (!NT_SUCCESS(Status))
2524 ZwClose(*SectionHandle);
2525 ObDereferenceObject(Section);
2526 ExFreePool(ImageSections);
2531 * We can't do memory mappings if the file system doesn't support the
2534 if (!(FileObject->Flags & FO_FCB_IS_VALID))
2536 ZwClose(*SectionHandle);
2537 ObDereferenceObject(Section);
2538 ObDereferenceObject(FileObject);
2539 ExFreePool(ImageSections);
2540 return(STATUS_INVALID_FILE_FOR_SECTION);
2546 Status = KeWaitForSingleObject((PVOID)&FileObject->Lock,
2551 if (Status != STATUS_SUCCESS)
2553 ZwClose(*SectionHandle);
2554 ObDereferenceObject(Section);
2555 ObDereferenceObject(FileObject);
2556 ExFreePool(ImageSections);
2561 * If this file hasn't been mapped as a image file before then allocate the
2562 * section segments to describe the mapping
2564 NrSegments = PEHeader.FileHeader.NumberOfSections + 1;
2565 if (FileObject->SectionObjectPointers->ImageSectionObject == NULL)
2569 ULONG Characteristics;
2571 Size = sizeof(MM_IMAGE_SECTION_OBJECT) +
2572 (sizeof(MM_SECTION_SEGMENT) * NrSegments);
2573 ImageSectionObject =
2574 ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MM_SECTION_SEGMENT);
2575 if (ImageSectionObject == NULL)
2577 KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2578 ZwClose(*SectionHandle);
2579 ObDereferenceObject(Section);
2580 ObDereferenceObject(FileObject);
2581 ExFreePool(ImageSections);
2582 return(STATUS_NO_MEMORY);
2584 ImageSectionObject->NrSegments = NrSegments;
2585 SectionSegments = ImageSectionObject->Segments;
2586 Section->Segments = SectionSegments;
2588 SectionSegments[0].FileOffset = 0;
2589 SectionSegments[0].Characteristics = IMAGE_SECTION_CHAR_DATA;
2590 SectionSegments[0].Protection = PAGE_READWRITE;
2591 SectionSegments[0].RawLength = PAGE_SIZE;
2592 SectionSegments[0].Length = PAGE_SIZE;
2593 SectionSegments[0].Flags = 0;
2594 SectionSegments[0].ReferenceCount = 1;
2595 SectionSegments[0].VirtualAddress = 0;
2596 SectionSegments[0].WriteCopy = TRUE;
2597 KeInitializeMutex(&SectionSegments[0].Lock, 0);
2599 for (i = 1; i < NrSegments; i++)
2601 SectionSegments[i].FileOffset =
2602 ImageSections[i-1].PointerToRawData;
2603 SectionSegments[i].Characteristics =
2604 ImageSections[i-1].Characteristics;
2607 * Set up the protection and write copy variables.
2609 Characteristics = ImageSections[i - 1].Characteristics;
2610 if ((Characteristics & IMAGE_SECTION_CHAR_READABLE) ||
2611 (Characteristics & IMAGE_SECTION_CHAR_WRITABLE) ||
2612 (Characteristics & IMAGE_SECTION_CHAR_EXECUTABLE))
2614 SectionSegments[i].Protection =
2615 SectionCharacteristicsToProtect[Characteristics >> 28];
2616 SectionSegments[i].WriteCopy =
2617 !(Characteristics & IMAGE_SECTION_CHAR_SHARED);
2619 else if (Characteristics & IMAGE_SECTION_CHAR_CODE)
2621 SectionSegments[i].Protection = PAGE_EXECUTE_READ;
2622 SectionSegments[i].WriteCopy = TRUE;
2624 else if (Characteristics & IMAGE_SECTION_CHAR_DATA)
2626 SectionSegments[i].Protection = PAGE_READWRITE;
2627 SectionSegments[i].WriteCopy = TRUE;
2629 else if (Characteristics & IMAGE_SECTION_CHAR_BSS)
2631 SectionSegments[i].Protection = PAGE_READWRITE;
2632 SectionSegments[i].WriteCopy = TRUE;
2636 SectionSegments[i].Protection = PAGE_NOACCESS;
2637 SectionSegments[i].WriteCopy = TRUE;
2641 * Set up the attributes.
2643 if (Characteristics & IMAGE_SECTION_CHAR_CODE)
2645 SectionSegments[i].Attributes = 0;
2647 else if (Characteristics & IMAGE_SECTION_CHAR_DATA)
2649 SectionSegments[i].Attributes = 0;
2651 else if (Characteristics & IMAGE_SECTION_CHAR_BSS)
2653 SectionSegments[i].Attributes = MM_SECTION_SEGMENT_BSS;
2657 SectionSegments[i].Attributes = 0;
2660 SectionSegments[i].RawLength = ImageSections[i-1].SizeOfRawData;
2661 SectionSegments[i].Length =
2662 ImageSections[i-1].Misc.VirtualSize;
2663 SectionSegments[i].Flags = 0;
2664 SectionSegments[i].ReferenceCount = 1;
2665 SectionSegments[i].VirtualAddress =
2666 (PVOID)ImageSections[i-1].VirtualAddress;
2667 KeInitializeMutex(&SectionSegments[i].Lock, 0);
2670 FileObject->SectionObjectPointers->ImageSectionObject =
2671 (PVOID)ImageSectionObject;
2677 ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)
2678 FileObject->SectionObjectPointers->ImageSectionObject;
2679 SectionSegments = ImageSectionObject->Segments;
2680 Section->Segments = SectionSegments;
2683 * Otherwise just reference all the section segments
2685 for (i = 0; i < NrSegments; i++)
2687 InterlockedIncrement(&SectionSegments[i].ReferenceCount);
2691 ExFreePool(ImageSections);
2692 KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2693 CcRosReferenceCache(FileObject);
2694 Section->FileObject = FileObject;
2696 ObDereferenceObject(Section);
2697 return(STATUS_SUCCESS);
2701 NtCreateSection (OUT PHANDLE SectionHandle,
2702 IN ACCESS_MASK DesiredAccess,
2703 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
2704 IN PLARGE_INTEGER MaximumSize OPTIONAL,
2705 IN ULONG SectionPageProtection OPTIONAL,
2706 IN ULONG AllocationAttributes,
2707 IN HANDLE FileHandle OPTIONAL)
2709 if (AllocationAttributes & SEC_IMAGE)
2711 return(MmCreateImageSection(SectionHandle,
2715 SectionPageProtection,
2716 AllocationAttributes,
2719 else if (FileHandle != NULL)
2721 return(MmCreateDataFileSection(SectionHandle,
2725 SectionPageProtection,
2726 AllocationAttributes,
2731 return(MmCreatePageFileSection(SectionHandle,
2735 SectionPageProtection,
2736 AllocationAttributes));
2741 /**********************************************************************
2760 NtOpenSection(PHANDLE SectionHandle,
2761 ACCESS_MASK DesiredAccess,
2762 POBJECT_ATTRIBUTES ObjectAttributes)
2768 Status = ObOpenObjectByName(ObjectAttributes,
2769 MmSectionObjectType,
2780 MmMapViewOfSegment(PEPROCESS Process,
2781 PMADDRESS_SPACE AddressSpace,
2782 PSECTION_OBJECT Section,
2783 PMM_SECTION_SEGMENT Segment,
2793 Status = MmCreateMemoryArea(Process,
2794 &Process->AddressSpace,
2795 MEMORY_AREA_SECTION_VIEW,
2801 if (!NT_SUCCESS(Status))
2803 DPRINT1("Mapping between 0x%.8X and 0x%.8X failed.\n",
2804 (*BaseAddress), (*BaseAddress) + ViewSize);
2808 KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
2809 InsertTailList(&Section->ViewListHead,
2810 &MArea->Data.SectionData.ViewListEntry);
2811 KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
2813 ObReferenceObjectByPointer((PVOID)Section,
2816 ExGetPreviousMode());
2817 MArea->Data.SectionData.Segment = Segment;
2818 MArea->Data.SectionData.Section = Section;
2819 MArea->Data.SectionData.ViewOffset = ViewOffset;
2820 MArea->Data.SectionData.WriteCopyView = FALSE;
2821 MmInitialiseRegion(&MArea->Data.SectionData.RegionListHead,
2822 ViewSize, 0, Protect);
2824 return(STATUS_SUCCESS);
2828 /**********************************************************************
2830 * NtMapViewOfSection
2833 * Maps a view of a section into the virtual address space of a
2838 * Handle of the section.
2841 * Handle of the process.
2844 * Desired base address (or NULL) on entry;
2845 * Actual base address of the view on exit.
2848 * Number of high order address bits that must be zero.
2851 * Size in bytes of the initially committed section of
2855 * Offset in bytes from the beginning of the section
2856 * to the beginning of the view.
2859 * Desired length of map (or zero to map all) on entry
2860 * Actual length mapped on exit.
2862 * InheritDisposition
2863 * Specified how the view is to be shared with
2867 * Type of allocation for the pages.
2870 * Protection for the committed region of the view.
2876 NtMapViewOfSection(HANDLE SectionHandle,
2877 HANDLE ProcessHandle,
2881 PLARGE_INTEGER SectionOffset,
2883 SECTION_INHERIT InheritDisposition,
2884 ULONG AllocationType,
2887 PSECTION_OBJECT Section;
2890 PMADDRESS_SPACE AddressSpace;
2892 Status = ObReferenceObjectByHandle(ProcessHandle,
2893 PROCESS_VM_OPERATION,
2898 if (!NT_SUCCESS(Status))
2903 AddressSpace = &Process->AddressSpace;
2905 Status = ObReferenceObjectByHandle(SectionHandle,
2907 MmSectionObjectType,
2911 if (!(NT_SUCCESS(Status)))
2913 DPRINT("ObReference failed rc=%x\n",Status);
2914 ObDereferenceObject(Process);
2918 Status = MmMapViewOfSection(Section,
2929 ObDereferenceObject(Section);
2930 ObDereferenceObject(Process);
2936 MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
2937 PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
2942 PFILE_OBJECT FileObject;
2943 PREACTOS_COMMON_FCB_HEADER Fcb;
2945 SWAPENTRY SavedSwapEntry;
2948 MArea = (PMEMORY_AREA)Context;
2950 Offset = ((ULONG)PAGE_ROUND_DOWN(Address) - (ULONG)MArea->BaseAddress) +
2951 MArea->Data.SectionData.ViewOffset;
2952 Entry = MmGetPageEntrySectionSegment(MArea->Data.SectionData.Segment,
2955 PageOp = MmCheckForPageOp(MArea, 0, NULL, MArea->Data.SectionData.Segment,
2960 KeWaitForSingleObject(&PageOp->CompletionEvent,
2965 MmReleasePageOp(PageOp);
2966 PageOp = MmCheckForPageOp(MArea, 0, NULL, MArea->Data.SectionData.Segment,
2970 assert(PageOp == NULL);
2973 * For a dirty, datafile, non-private page mark it as dirty in the
2976 if (MArea->Data.SectionData.Segment->Flags & MM_DATAFILE_SEGMENT)
2978 if (PhysAddr.QuadPart == PAGE_FROM_SSE(Entry) && Dirty)
2980 FileObject = MemoryArea->Data.SectionData.Section->FileObject;
2981 Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
2982 CcRosMarkDirtyCacheSegment(Fcb->Bcb, Offset);
2983 assert(SwapEntry == 0);
2989 MmFreeSwapPage(SwapEntry);
2991 else if (PhysAddr.QuadPart != 0)
2993 if (IS_SWAP_FROM_SSE(Entry) ||
2994 PhysAddr.QuadPart != (PAGE_FROM_SSE(Entry)))
2997 * Just dereference private pages
2999 SavedSwapEntry = MmGetSavedSwapEntryPage(PhysAddr);
3000 if (SavedSwapEntry != 0)
3002 MmFreeSwapPage(SavedSwapEntry);
3003 MmSetSavedSwapEntryPage(PhysAddr, 0);
3008 MmUnsharePageEntrySectionSegment(MArea->Data.SectionData.Section,
3009 MArea->Data.SectionData.Segment,
3013 MmDeleteRmap(PhysAddr, MArea->Process, Address);
3014 MmReleasePageMemoryConsumer(MC_USER, PhysAddr);
3019 MmUnmapViewOfSection(PEPROCESS Process,
3023 PMEMORY_AREA MemoryArea;
3024 PMADDRESS_SPACE AddressSpace;
3025 PSECTION_OBJECT Section;
3026 PMM_SECTION_SEGMENT Segment;
3028 PLIST_ENTRY CurrentEntry;
3029 PMM_REGION CurrentRegion;
3031 AddressSpace = &Process->AddressSpace;
3033 DPRINT("Opening memory area Process %x BaseAddress %x\n",
3034 Process, BaseAddress);
3035 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
3037 if (MemoryArea == NULL)
3039 return(STATUS_UNSUCCESSFUL);
3042 MemoryArea->DeleteInProgress = TRUE;
3044 MmLockSection(MemoryArea->Data.SectionData.Section);
3045 MmLockSectionSegment(MemoryArea->Data.SectionData.Segment);
3046 Section = MemoryArea->Data.SectionData.Section;
3047 Segment = MemoryArea->Data.SectionData.Segment;
3048 KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
3049 RemoveEntryList(&MemoryArea->Data.SectionData.ViewListEntry);
3050 KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
3052 CurrentEntry = MemoryArea->Data.SectionData.RegionListHead.Flink;
3053 while (CurrentEntry != &MemoryArea->Data.SectionData.RegionListHead)
3056 CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
3057 CurrentEntry = CurrentEntry->Flink;
3058 ExFreePool(CurrentRegion);
3061 if (MemoryArea->Data.SectionData.Section->AllocationAttributes &
3064 Status = MmFreeMemoryArea(&Process->AddressSpace,
3072 Status = MmFreeMemoryArea(&Process->AddressSpace,
3078 MmUnlockSection(Section);
3079 MmUnlockSectionSegment(Segment);
3080 ObDereferenceObject(Section);
3081 return(STATUS_SUCCESS);
3084 /**********************************************************************
3086 * NtUnmapViewOfSection
3102 NtUnmapViewOfSection (HANDLE ProcessHandle,
3108 DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n",
3109 ProcessHandle, BaseAddress);
3111 DPRINT("Referencing process\n");
3112 Status = ObReferenceObjectByHandle(ProcessHandle,
3113 PROCESS_VM_OPERATION,
3118 if (!NT_SUCCESS(Status))
3120 DPRINT("ObReferenceObjectByHandle failed (Status %x)\n", Status);
3124 MmLockAddressSpace(&Process->AddressSpace);
3125 Status = MmUnmapViewOfSection(Process, BaseAddress);
3126 MmUnlockAddressSpace(&Process->AddressSpace);
3128 ObDereferenceObject(Process);
3135 NtQuerySection (IN HANDLE SectionHandle,
3136 IN CINT SectionInformationClass,
3137 OUT PVOID SectionInformation,
3139 OUT PULONG ResultLength)
3141 * FUNCTION: Queries the information of a section object.
3143 * SectionHandle = Handle to the section link object
3144 * SectionInformationClass = Index to a certain information structure
3145 * SectionInformation (OUT)= Caller supplies storage for resulting
3147 * Length = Size of the supplied storage
3148 * ResultLength = Data written
3153 PSECTION_OBJECT Section;
3156 Status = ObReferenceObjectByHandle(SectionHandle,
3158 MmSectionObjectType,
3162 if (!(NT_SUCCESS(Status)))
3167 switch (SectionInformationClass)
3169 case SectionBasicInformation:
3171 PSECTION_BASIC_INFORMATION Sbi;
3173 if (Length != sizeof(SECTION_BASIC_INFORMATION))
3175 ObDereferenceObject(Section);
3176 return(STATUS_INFO_LENGTH_MISMATCH);
3179 Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
3181 Sbi->BaseAddress = 0;
3182 Sbi->Attributes = 0;
3183 Sbi->Size.QuadPart = 0;
3185 *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
3186 Status = STATUS_SUCCESS;
3190 case SectionImageInformation:
3192 PSECTION_IMAGE_INFORMATION Sii;
3194 if (Length != sizeof(SECTION_IMAGE_INFORMATION))
3196 ObDereferenceObject(Section);
3197 return(STATUS_INFO_LENGTH_MISMATCH);
3199 Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
3200 Sii->EntryPoint = Section->EntryPoint;
3202 Sii->StackReserve = Section->StackReserve;
3203 Sii->StackCommit = Section->StackCommit;
3204 Sii->Subsystem = Section->Subsystem;
3205 Sii->MinorSubsystemVersion = Section->MinorSubsystemVersion;
3206 Sii->MajorSubsystemVersion = Section->MajorSubsystemVersion;
3208 Sii->Characteristics = Section->ImageCharacteristics;
3209 Sii->ImageNumber = Section->Machine;
3210 Sii->Executable = Section->Executable;
3212 Sii->Unknown4[0] = 0;
3213 Sii->Unknown4[1] = 0;
3214 Sii->Unknown4[2] = 0;
3216 *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
3217 Status = STATUS_SUCCESS;
3223 Status = STATUS_INVALID_INFO_CLASS;
3225 ObDereferenceObject(Section);
3231 NtExtendSection(IN HANDLE SectionHandle,
3232 IN ULONG NewMaximumSize)
3238 /**********************************************************************
3240 * MmAllocateSection@4
3250 * Code taken from ntoskrnl/mm/special.c.
3256 MmAllocateSection (IN ULONG Length)
3262 PMADDRESS_SPACE AddressSpace;
3264 DPRINT("MmAllocateSection(Length %x)\n",Length);
3266 AddressSpace = MmGetKernelAddressSpace();
3268 MmLockAddressSpace(AddressSpace);
3269 Status = MmCreateMemoryArea (NULL,
3277 if (!NT_SUCCESS(Status))
3279 MmUnlockAddressSpace(AddressSpace);
3282 MmUnlockAddressSpace(AddressSpace);
3283 DPRINT("Result %p\n",Result);
3284 for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
3286 PHYSICAL_ADDRESS Page;
3288 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page);
3289 if (!NT_SUCCESS(Status))
3291 DbgPrint("Unable to allocate page\n");
3294 Status = MmCreateVirtualMapping (NULL,
3295 (Result + (i * PAGE_SIZE)),
3299 if (!NT_SUCCESS(Status))
3301 DbgPrint("Unable to create virtual mapping\n");
3305 return ((PVOID)Result);
3309 /**********************************************************************
3311 * MmMapViewOfSection
3314 * Maps a view of a section into the virtual address space of a
3319 * Pointer to the section object.
3322 * Pointer to the process.
3325 * Desired base address (or NULL) on entry;
3326 * Actual base address of the view on exit.
3329 * Number of high order address bits that must be zero.
3332 * Size in bytes of the initially committed section of
3336 * Offset in bytes from the beginning of the section
3337 * to the beginning of the view.
3340 * Desired length of map (or zero to map all) on entry
3341 * Actual length mapped on exit.
3343 * InheritDisposition
3344 * Specified how the view is to be shared with
3348 * Type of allocation for the pages.
3351 * Protection for the committed region of the view.
3357 MmMapViewOfSection(IN PVOID SectionObject,
3358 IN PEPROCESS Process,
3359 IN OUT PVOID *BaseAddress,
3361 IN ULONG CommitSize,
3362 IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
3363 IN OUT PULONG ViewSize,
3364 IN SECTION_INHERIT InheritDisposition,
3365 IN ULONG AllocationType,
3368 PSECTION_OBJECT Section;
3369 PMADDRESS_SPACE AddressSpace;
3371 NTSTATUS Status = STATUS_SUCCESS;
3373 Section = (PSECTION_OBJECT)SectionObject;
3374 AddressSpace = &Process->AddressSpace;
3376 MmLockAddressSpace(AddressSpace);
3377 MmLockSection(SectionObject);
3379 if (Section->AllocationAttributes & SEC_IMAGE)
3385 ImageBase = *BaseAddress;
3386 if (ImageBase == NULL)
3388 ImageBase = Section->ImageBase;
3392 for (i = 0; i < Section->NrSegments; i++)
3394 if (!(Section->Segments[i].Characteristics & IMAGE_SECTION_NOLOAD))
3397 MaxExtent = (ULONG)(Section->Segments[i].VirtualAddress +
3398 Section->Segments[i].Length);
3399 ImageSize = max(ImageSize, MaxExtent);
3403 /* Check there is enough space to map the section at that point. */
3404 if (MmOpenMemoryAreaByRegion(AddressSpace, ImageBase,
3405 PAGE_ROUND_UP(ImageSize)) != NULL)
3407 /* Fail if the user requested a fixed base address. */
3408 if ((*BaseAddress) != NULL)
3410 MmUnlockSection(Section);
3411 MmUnlockAddressSpace(AddressSpace);
3412 return(STATUS_UNSUCCESSFUL);
3414 /* Otherwise find a gap to map the image. */
3415 ImageBase = MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize));
3416 if (ImageBase == NULL)
3418 MmUnlockSection(Section);
3419 MmUnlockAddressSpace(AddressSpace);
3420 return(STATUS_UNSUCCESSFUL);
3424 for (i = 0; i < Section->NrSegments; i++)
3428 if (!(Section->Segments[i].Characteristics & IMAGE_SECTION_NOLOAD))
3430 SBaseAddress = (PVOID)
3431 (ImageBase + (ULONG_PTR)Section->Segments[i].VirtualAddress);
3433 MmLockSectionSegment(&Section->Segments[i]);
3434 Status = MmMapViewOfSegment(Process,
3435 &Process->AddressSpace,
3437 &Section->Segments[i],
3439 Section->Segments[i].Length,
3440 Section->Segments[i].Protection,
3441 Section->Segments[i].FileOffset);
3442 MmUnlockSectionSegment(&Section->Segments[i]);
3443 if (!NT_SUCCESS(Status))
3445 MmUnlockSection(Section);
3446 MmUnlockAddressSpace(AddressSpace);
3451 *BaseAddress = ImageBase;
3455 if (SectionOffset == NULL)
3461 ViewOffset = SectionOffset->u.LowPart;
3464 if ((ViewOffset % PAGE_SIZE) != 0)
3466 MmUnlockSection(Section);
3467 MmUnlockAddressSpace(AddressSpace);
3468 return(STATUS_MAPPED_ALIGNMENT);
3471 if ((*ViewSize) == 0)
3473 (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
3475 else if (((*ViewSize)+ViewOffset) > Section->MaximumSize.u.LowPart)
3477 (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
3480 MmLockSectionSegment(Section->Segments);
3481 Status = MmMapViewOfSegment(Process,
3482 &Process->AddressSpace,
3489 MmUnlockSectionSegment(Section->Segments);
3490 if (!NT_SUCCESS(Status))
3492 MmUnlockSection(Section);
3493 MmUnlockAddressSpace(AddressSpace);
3498 MmUnlockSection(Section);
3499 MmUnlockAddressSpace(AddressSpace);
3501 return(STATUS_SUCCESS);
3505 MmCanFileBeTruncated (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
3506 IN PLARGE_INTEGER NewFileSize)
3514 MmDisableModifiedWriteOfSection (DWORD Unknown0)
3521 MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
3522 IN MMFLUSH_TYPE FlushType)
3526 case MmFlushForDelete:
3527 if (SectionObjectPointer->ImageSectionObject ||
3528 SectionObjectPointer->DataSectionObject)
3532 CcRosSetRemoveOnClose(SectionObjectPointer);
3534 case MmFlushForWrite:
3541 MmForceSectionClosed (DWORD Unknown0,
3550 MmMapViewInSystemSpace (IN PVOID Section,
3551 OUT PVOID * MappedBase,
3555 return (STATUS_NOT_IMPLEMENTED);
3559 MmUnmapViewInSystemSpace (DWORD Unknown0)
3562 return (STATUS_NOT_IMPLEMENTED);
3567 MmSetBankedSection (DWORD Unknown0,
3575 return (STATUS_NOT_IMPLEMENTED);
3579 /**********************************************************************
3584 * Creates a section object.
3587 * SectionObjiect (OUT)
3588 * Caller supplied storage for the resulting pointer
3589 * to a SECTION_BOJECT instance;
3592 * Specifies the desired access to the section can be a
3594 * STANDARD_RIGHTS_REQUIRED |
3596 * SECTION_MAP_WRITE |
3597 * SECTION_MAP_READ |
3598 * SECTION_MAP_EXECUTE
3600 * ObjectAttributes [OPTIONAL]
3601 * Initialized attributes for the object can be used
3602 * to create a named section;
3605 * Maximizes the size of the memory section. Must be
3606 * non-NULL for a page-file backed section.
3607 * If value specified for a mapped file and the file is
3608 * not large enough, file will be extended.
3610 * SectionPageProtection
3611 * Can be a combination of:
3617 * AllocationAttributes
3618 * Can be a combination of:
3623 * Handle to a file to create a section mapped to a file
3624 * instead of a memory backed section;
3633 MmCreateSection (OUT PSECTION_OBJECT * SectionObject,
3634 IN ACCESS_MASK DesiredAccess,
3635 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
3636 IN PLARGE_INTEGER MaximumSize,
3637 IN ULONG SectionPageProtection,
3638 IN ULONG AllocationAttributes,
3639 IN HANDLE FileHandle OPTIONAL,
3640 IN PFILE_OBJECT File OPTIONAL)
3642 return (STATUS_NOT_IMPLEMENTED);