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.53 2001/03/29 17:24:43 dwelch 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 #include <ddk/ntddk.h>
33 #include <internal/mm.h>
34 #include <internal/ob.h>
35 #include <internal/io.h>
36 #include <internal/ps.h>
37 #include <internal/pool.h>
38 #include <ddk/ntifs.h>
41 #include <internal/debug.h>
43 /* GLOBALS *******************************************************************/
45 POBJECT_TYPE EXPORTED MmSectionObjectType
= NULL
;
47 static GENERIC_MAPPING MmpSectionMapping
= {
48 STANDARD_RIGHTS_READ
| SECTION_MAP_READ
| SECTION_QUERY
,
49 STANDARD_RIGHTS_WRITE
| SECTION_MAP_WRITE
,
50 STANDARD_RIGHTS_EXECUTE
| SECTION_MAP_EXECUTE
,
53 #define TAG_MM_SECTION_SEGMENT TAG('M', 'M', 'S', 'S')
54 #define TAG_SECTION_PAGE_TABLE TAG('M', 'S', 'P', 'T')
56 #define SHARE_COUNT(E) ((E) & 0xFFF)
57 #define MAX_SHARE_COUNT 0xFFF
59 /* FUNCTIONS *****************************************************************/
62 MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment
)
66 for (i
= 0; i
< NR_SECTION_PAGE_TABLES
; i
++)
68 if (Segment
->PageDirectory
.PageTables
[i
] != NULL
)
70 ExFreePool(Segment
->PageDirectory
.PageTables
[i
]);
76 MmFreeSectionSegments(PFILE_OBJECT FileObject
)
78 if (FileObject
->SectionObjectPointers
->ImageSectionObject
!= NULL
)
80 PMM_IMAGE_SECTION_OBJECT ImageSectionObject
;
85 (PMM_IMAGE_SECTION_OBJECT
)FileObject
->SectionObjectPointers
->
88 for (i
= 0; i
< ImageSectionObject
->NrSegments
; i
++)
90 if (ImageSectionObject
->Segments
[i
].ReferenceCount
!= 0)
92 DPRINT1("Image segment %d still referenced (was %d)\n", i
,
93 ImageSectionObject
->Segments
[i
].ReferenceCount
);
96 MmFreePageTablesSectionSegment(&ImageSectionObject
->Segments
[i
]);
98 ExFreePool(ImageSectionObject
);
99 FileObject
->SectionObjectPointers
->ImageSectionObject
= NULL
;
101 if (FileObject
->SectionObjectPointers
->DataSectionObject
!= NULL
)
103 PMM_SECTION_SEGMENT Segment
;
105 Segment
= (PMM_SECTION_SEGMENT
)FileObject
->SectionObjectPointers
->
108 if (Segment
->ReferenceCount
!= 0)
110 DPRINT1("Data segment still referenced\n");
113 MmFreePageTablesSectionSegment(Segment
);
115 FileObject
->SectionObjectPointers
->DataSectionObject
= NULL
;
120 MmWritePageSectionView(PMADDRESS_SPACE AddressSpace
,
124 return(STATUS_UNSUCCESSFUL
);
128 MmLockSection(PSECTION_OBJECT Section
)
130 KeWaitForSingleObject(&Section
->Lock
,
138 MmUnlockSection(PSECTION_OBJECT Section
)
140 KeReleaseMutex(&Section
->Lock
, FALSE
);
144 MmLockSectionSegment(PMM_SECTION_SEGMENT Segment
)
146 KeWaitForSingleObject(&Segment
->Lock
,
154 MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment
)
156 KeReleaseMutex(&Segment
->Lock
, FALSE
);
162 MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment
,
166 PSECTION_PAGE_TABLE Table
;
167 ULONG DirectoryOffset
;
170 DirectoryOffset
= PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset
);
171 Table
= Segment
->PageDirectory
.PageTables
[DirectoryOffset
];
175 Segment
->PageDirectory
.PageTables
[DirectoryOffset
] =
176 ExAllocatePoolWithTag(NonPagedPool
, sizeof(SECTION_PAGE_TABLE
),
177 TAG_SECTION_PAGE_TABLE
);
178 memset(Table
, 0, sizeof(SECTION_PAGE_TABLE
));
179 DPRINT("Table %x\n", Table
);
181 TableOffset
= PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset
);
182 Table
->Pages
[TableOffset
] = Entry
;
187 MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment
,
190 PSECTION_PAGE_TABLE Table
;
192 ULONG DirectoryOffset
;
195 DPRINT("MmGetPageEntrySection(Offset %x)\n", Offset
);
197 DirectoryOffset
= PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset
);
198 Table
= Segment
->PageDirectory
.PageTables
[DirectoryOffset
];
199 DPRINT("Table %x\n", Table
);
204 TableOffset
= PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset
);
205 Entry
= Table
->Pages
[TableOffset
];
210 MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment
,
215 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
);
218 DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
221 if (SHARE_COUNT(Entry
) == MAX_SHARE_COUNT
)
223 DPRINT1("Maximum share count reached\n");
227 MmSetPageEntrySectionSegment(Segment
, Offset
, Entry
);
231 MmUnsharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment
,
236 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
);
239 DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
242 if (SHARE_COUNT(Entry
) == 0)
244 DPRINT1("Zero share count for unshare\n");
248 MmSetPageEntrySectionSegment(Segment
, Offset
, Entry
);
253 MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace
,
254 MEMORY_AREA
* MemoryArea
,
258 LARGE_INTEGER Offset
;
259 IO_STATUS_BLOCK IoStatus
;
264 PSECTION_OBJECT Section
;
265 PMM_SECTION_SEGMENT Segment
;
272 * There is a window between taking the page fault and locking the
273 * address space when another thread could load the page so we check
276 if (MmIsPagePresent(NULL
, Address
))
280 MmLockPage((PVOID
)MmGetPhysicalAddressForProcess(NULL
, Address
));
282 return(STATUS_SUCCESS
);
285 PAddress
= (ULONG
)PAGE_ROUND_DOWN(((ULONG
)Address
));
286 Offset
.QuadPart
= (PAddress
- (ULONG
)MemoryArea
->BaseAddress
) +
287 MemoryArea
->Data
.SectionData
.ViewOffset
;
292 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
293 Section
= MemoryArea
->Data
.SectionData
.Section
;
294 MmLockSection(Section
);
295 MmLockSectionSegment(Segment
);
298 * Get or create a page operation descriptor
300 PageOp
= MmGetPageOp(MemoryArea
, 0, 0, Segment
, Offset
.u
.LowPart
);
303 DPRINT1("MmGetPageOp failed\n");
308 * Check if someone else is already handling this fault, if so wait
311 if (PageOp
->Thread
!= PsGetCurrentThread())
313 MmUnlockSectionSegment(Segment
);
314 MmUnlockSection(Section
);
315 MmUnlockAddressSpace(AddressSpace
);
316 Status
= KeWaitForSingleObject(&PageOp
->CompletionEvent
,
322 * Check for various strange conditions
324 if (Status
!= STATUS_SUCCESS
)
326 DPRINT1("Failed to wait for page op\n");
329 if (PageOp
->Status
== STATUS_PENDING
)
331 DPRINT1("Woke for page op before completion\n");
335 * If the thread handling this fault has failed then we don't retry
337 if (!NT_SUCCESS(PageOp
->Status
))
339 return(PageOp
->Status
);
341 MmLockAddressSpace(AddressSpace
);
342 MmLockSection(Section
);
343 MmLockSectionSegment(Segment
);
345 * If the completed fault was for another address space then set the
348 if (!MmIsPagePresent(NULL
, Address
))
350 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
.u
.LowPart
);
352 Page
= (PVOID
)(Entry
& 0xFFFFF000);
353 MmReferencePage(Page
);
354 // MmSharePageEntrySectionSegment(Segment, Offset.u.LowPart);
356 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
360 if (!NT_SUCCESS(Status
))
362 DbgPrint("Unable to create virtual mapping\n");
368 MmLockPage((PVOID
)MmGetPhysicalAddressForProcess(NULL
, Address
));
370 MmUnlockSectionSegment(Segment
);
371 MmUnlockSection(Section
);
372 MmReleasePageOp(PageOp
);
373 return(STATUS_SUCCESS
);
377 * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
379 if (Section
->Flags
& SO_PHYSICAL_MEMORY
)
382 * Just map the desired physical page
384 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
386 MemoryArea
->Attributes
,
390 MmLockPage((PVOID
)MmGetPhysicalAddressForProcess(NULL
, Address
));
394 * Cleanup and release locks
396 PageOp
->Status
= STATUS_SUCCESS
;
397 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
398 MmReleasePageOp(PageOp
);
399 MmUnlockSectionSegment(Segment
);
400 MmUnlockSection(Section
);
401 return(STATUS_SUCCESS
);
405 * Map anonymous memory for BSS sections
407 if (Segment
->Characteristics
& IMAGE_SECTION_CHAR_BSS
)
409 Page
= MmAllocPage(0);
412 MmUnlockSectionSegment(Segment
);
413 MmUnlockSection(Section
);
414 MmUnlockAddressSpace(AddressSpace
);
415 MmWaitForFreePages();
416 MmLockAddressSpace(AddressSpace
);
417 MmLockSection(Section
);
418 MmLockSectionSegment(Segment
);
419 Page
= MmAllocPage(0);
421 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
423 MemoryArea
->Attributes
,
427 MmLockPage((PVOID
)MmGetPhysicalAddressForProcess(NULL
, Address
));
431 * Cleanup and release locks
433 PageOp
->Status
= STATUS_SUCCESS
;
434 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
435 MmReleasePageOp(PageOp
);
436 MmUnlockSectionSegment(Segment
);
437 MmUnlockSection(Section
);
438 return(STATUS_SUCCESS
);
442 * Check if this page needs to be mapped COW
444 if (Segment
->Characteristics
& IMAGE_SECTION_CHAR_DATA
)
446 Attributes
= PAGE_READONLY
;
450 Attributes
= MemoryArea
->Attributes
;
454 * Get the entry corresponding to the offset within the section
456 Entry
= MmGetPageEntrySectionSegment(Segment
, Offset
.u
.LowPart
);
461 * If the entry is zero (and it can't change because we have
462 * locked the segment) then we need to load the page.
466 * Allocate a page, this is rather complicated by the possibility
467 * we might have to move other things out of memory
469 Page
= MmAllocPage(0);
472 MmUnlockSectionSegment(Segment
);
473 MmUnlockSection(Section
);
474 MmUnlockAddressSpace(AddressSpace
);
475 MmWaitForFreePages();
476 MmLockAddressSpace(AddressSpace
);
477 MmLockSection(Section
);
478 MmLockSectionSegment(Segment
);
479 Page
= MmAllocPage(0);
483 * Create an mdl to hold the page we are going to read data into.
485 Mdl
= MmCreateMdl(NULL
, NULL
, PAGESIZE
);
486 MmBuildMdlFromPages(Mdl
, (PULONG
)&Page
);
489 * Release all our locks and read in the page from disk
491 MmUnlockSectionSegment(Segment
);
492 MmUnlockSection(Section
);
493 MmUnlockAddressSpace(AddressSpace
);
494 Status
= IoPageRead(MemoryArea
->Data
.SectionData
.Section
->FileObject
,
499 if (!NT_SUCCESS(Status
) && Status
!= STATUS_END_OF_FILE
)
502 * FIXME: What do we know in this case?
504 DPRINT1("IoPageRead failed (Status %x)\n", Status
);
507 * Cleanup and release locks
509 PageOp
->Status
= Status
;
510 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
511 MmReleasePageOp(PageOp
);
512 MmLockAddressSpace(AddressSpace
);
517 * Relock the address space, section and segment
519 MmLockAddressSpace(AddressSpace
);
520 MmLockSection(Section
);
521 MmLockSectionSegment(Segment
);
524 * Check the entry. No one should change the status of a page
525 * that has a pending page-in.
527 Entry1
= MmGetPageEntrySectionSegment(Segment
, Offset
.QuadPart
);
530 DbgPrint("Someone changed ppte entry while we slept\n");
535 * Mark the offset within the section as having valid, in-memory
539 MmSetPageEntrySectionSegment(Segment
, Offset
.QuadPart
, Entry
);
540 // MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
542 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
546 if (!NT_SUCCESS(Status
))
548 DbgPrint("Unable to create virtual mapping\n");
553 MmLockPage((PVOID
)MmGetPhysicalAddressForProcess(NULL
, Address
));
555 PageOp
->Status
= STATUS_SUCCESS
;
556 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
557 MmReleasePageOp(PageOp
);
558 MmUnlockSectionSegment(Segment
);
559 MmUnlockSection(Section
);
560 DPRINT("MmNotPresentFaultSectionView succeeded\n");
561 return(STATUS_SUCCESS
);
566 * If the section offset is already in-memory and valid then just
567 * take another reference to the page
571 MmReferencePage(Page
);
572 // MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
574 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
578 if (!NT_SUCCESS(Status
))
580 DbgPrint("Unable to create virtual mapping\n");
585 MmLockPage((PVOID
)MmGetPhysicalAddressForProcess(NULL
, Address
));
587 PageOp
->Status
= STATUS_SUCCESS
;
588 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
589 MmReleasePageOp(PageOp
);
590 MmUnlockSectionSegment(Segment
);
591 MmUnlockSection(Section
);
592 return(STATUS_SUCCESS
);
597 MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace
,
598 MEMORY_AREA
* MemoryArea
,
602 PMM_SECTION_SEGMENT Segment
;
603 PSECTION_OBJECT Section
;
610 * Check if the page has been paged out or has already been set readwrite
612 if (!MmIsPagePresent(NULL
, Address
) ||
613 MmGetPageProtect(NULL
, Address
) & PAGE_READWRITE
)
615 return(STATUS_SUCCESS
);
621 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
622 Section
= MemoryArea
->Data
.SectionData
.Section
;
623 MmLockSection(Section
);
624 MmLockSectionSegment(Segment
);
626 if (!(Segment
->Characteristics
& IMAGE_SECTION_CHAR_DATA
))
628 MmUnlockSection(Section
);
629 MmUnlockSectionSegment(Segment
);
630 return(STATUS_UNSUCCESSFUL
);
636 NewPage
= MmAllocPage(0);
637 while (NewPage
== NULL
)
639 MmUnlockSectionSegment(Segment
);
640 MmUnlockSection(Section
);
641 MmUnlockAddressSpace(AddressSpace
);
642 MmWaitForFreePages();
643 MmLockAddressSpace(AddressSpace
);
644 if (!MmIsPagePresent(NULL
, Address
) ||
645 MmGetPageProtect(NULL
, Address
) & PAGE_READWRITE
)
647 MmUnlockAddressSpace(AddressSpace
);
648 return(STATUS_SUCCESS
);
650 MmLockSection(Section
);
651 MmLockSectionSegment(Segment
);
652 NewPage
= MmAllocPage(0);
655 OldPage
= MmGetPhysicalAddressForProcess(NULL
, Address
);
657 NewAddress
= ExAllocatePageWithPhysPage((ULONG
)NewPage
);
658 memcpy(NewAddress
, (PVOID
)PAGE_ROUND_DOWN(Address
), PAGESIZE
);
659 ExUnmapPage(NewAddress
);
661 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
663 MemoryArea
->Attributes
,
665 if (!NT_SUCCESS(Status
))
667 DbgPrint("Unable to create virtual mapping\n");
672 MmLockPage((PVOID
)MmGetPhysicalAddressForProcess(NULL
, Address
));
674 MmUnlockSectionSegment(Segment
);
675 MmUnlockSection(Section
);
676 return(STATUS_SUCCESS
);
680 MmPageOutSectionView(PMADDRESS_SPACE AddressSpace
,
681 MEMORY_AREA
* MemoryArea
,
690 MmpDeleteSection(PVOID ObjectBody
)
692 PSECTION_OBJECT Section
= (PSECTION_OBJECT
)ObjectBody
;
694 DPRINT("MmpDeleteSection(ObjectBody %x)\n", ObjectBody
);
695 if (Section
->Flags
& MM_IMAGE_SECTION
)
699 for (i
= 0; i
< Section
->NrSegments
; i
++)
701 InterlockedDecrement(&Section
->Segments
[i
].ReferenceCount
);
706 InterlockedDecrement(&Section
->Segments
->ReferenceCount
);
708 if (Section
->FileObject
!= NULL
)
710 ObDereferenceObject(Section
->FileObject
);
711 Section
->FileObject
= NULL
;
716 MmpCloseSection(PVOID ObjectBody
,
719 DPRINT("MmpCloseSection(OB %x, HC %d) RC %d\n",
720 ObjectBody
, HandleCount
, ObGetReferenceCount(ObjectBody
));
724 NTSTATUS
MmpCreateSection(PVOID ObjectBody
,
727 POBJECT_ATTRIBUTES ObjectAttributes
)
731 DPRINT("MmpCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
732 ObjectBody
, Parent
, RemainingPath
);
734 if (RemainingPath
== NULL
)
736 return(STATUS_SUCCESS
);
739 if (wcschr(RemainingPath
+1, L
'\\') != NULL
)
741 return(STATUS_UNSUCCESSFUL
);
744 Status
= ObReferenceObjectByPointer(Parent
,
745 STANDARD_RIGHTS_REQUIRED
,
748 if (!NT_SUCCESS(Status
))
753 ObAddEntryDirectory(Parent
, ObjectBody
, RemainingPath
+1);
754 ObDereferenceObject(Parent
);
756 return(STATUS_SUCCESS
);
760 MmCreatePhysicalMemorySection(VOID
)
763 PSECTION_OBJECT PhysSection
;
765 OBJECT_ATTRIBUTES Obj
;
767 LARGE_INTEGER SectionSize
;
770 * Create the section mapping physical memory
772 SectionSize
.QuadPart
= 0xFFFFFFFF;
773 RtlInitUnicodeString(&Name
, L
"\\Device\\PhysicalMemory");
774 InitializeObjectAttributes(&Obj
,
779 Status
= NtCreateSection(&PhysSectionH
,
783 PAGE_EXECUTE_READWRITE
,
786 if (!NT_SUCCESS(Status
))
788 DbgPrint("Failed to create PhysicalMemory section\n");
791 Status
= ObReferenceObjectByHandle(PhysSectionH
,
795 (PVOID
*)&PhysSection
,
797 if (!NT_SUCCESS(Status
))
799 DbgPrint("Failed to reference PhysicalMemory section\n");
802 PhysSection
->Flags
= PhysSection
->Flags
| SO_PHYSICAL_MEMORY
;
803 ObDereferenceObject((PVOID
)PhysSection
);
805 return(STATUS_SUCCESS
);
809 MmInitSectionImplementation(VOID
)
811 MmSectionObjectType
= ExAllocatePool(NonPagedPool
,sizeof(OBJECT_TYPE
));
813 RtlInitUnicodeString(&MmSectionObjectType
->TypeName
, L
"Section");
815 MmSectionObjectType
->Tag
= TAG('S', 'E', 'C', 'T');
816 MmSectionObjectType
->TotalObjects
= 0;
817 MmSectionObjectType
->TotalHandles
= 0;
818 MmSectionObjectType
->MaxObjects
= ULONG_MAX
;
819 MmSectionObjectType
->MaxHandles
= ULONG_MAX
;
820 MmSectionObjectType
->PagedPoolCharge
= 0;
821 MmSectionObjectType
->NonpagedPoolCharge
= sizeof(SECTION_OBJECT
);
822 MmSectionObjectType
->Mapping
= &MmpSectionMapping
;
823 MmSectionObjectType
->Dump
= NULL
;
824 MmSectionObjectType
->Open
= NULL
;
825 MmSectionObjectType
->Close
= MmpCloseSection
;
826 MmSectionObjectType
->Delete
= MmpDeleteSection
;
827 MmSectionObjectType
->Parse
= NULL
;
828 MmSectionObjectType
->Security
= NULL
;
829 MmSectionObjectType
->QueryName
= NULL
;
830 MmSectionObjectType
->OkayToClose
= NULL
;
831 MmSectionObjectType
->Create
= MmpCreateSection
;
833 return(STATUS_SUCCESS
);
837 MmCreatePageFileSection(PHANDLE SectionHandle
,
838 ACCESS_MASK DesiredAccess
,
839 POBJECT_ATTRIBUTES ObjectAttributes
,
840 PLARGE_INTEGER UMaximumSize
,
841 ULONG SectionPageProtection
,
842 ULONG AllocationAttributes
)
844 * Create a section which is backed by the pagefile
847 LARGE_INTEGER MaximumSize
;
848 PSECTION_OBJECT Section
;
849 PMM_SECTION_SEGMENT Segment
;
851 if (UMaximumSize
== NULL
)
853 return(STATUS_UNSUCCESSFUL
);
855 MaximumSize
= *UMaximumSize
;
858 * Check the protection
860 if ((SectionPageProtection
& PAGE_FLAGS_VALID_FROM_USER_MODE
) !=
861 SectionPageProtection
)
863 return(STATUS_INVALID_PAGE_PROTECTION
);
869 Section
= ObCreateObject(SectionHandle
,
872 MmSectionObjectType
);
875 return(STATUS_UNSUCCESSFUL
);
881 Section
->SectionPageProtection
= SectionPageProtection
;
882 Section
->AllocateAttributes
= AllocationAttributes
;
883 InitializeListHead(&Section
->ViewListHead
);
884 KeInitializeSpinLock(&Section
->ViewListLock
);
885 KeInitializeMutex(&Section
->Lock
, 0);
887 Section
->FileObject
= NULL
;
888 Section
->MaximumSize
= MaximumSize
;
889 Segment
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(MM_SECTION_SEGMENT
),
890 TAG_MM_SECTION_SEGMENT
);
893 ZwClose(*SectionHandle
);
894 ObDereferenceObject(Section
);
895 return(STATUS_NO_MEMORY
);
897 Section
->Segments
= Segment
;
898 Segment
->ReferenceCount
= 1;
899 KeInitializeMutex(&Segment
->Lock
, 0);
900 Segment
->FileOffset
= 0;
901 Segment
->Protection
= SectionPageProtection
;
902 Segment
->Attributes
= AllocationAttributes
;
903 Segment
->Length
= MaximumSize
.u
.LowPart
;
904 Segment
->Flags
= MM_PAGEFILE_SECTION
;
905 return(STATUS_SUCCESS
);
910 MmCreateDataFileSection(PHANDLE SectionHandle
,
911 ACCESS_MASK DesiredAccess
,
912 POBJECT_ATTRIBUTES ObjectAttributes
,
913 PLARGE_INTEGER UMaximumSize
,
914 ULONG SectionPageProtection
,
915 ULONG AllocationAttributes
,
918 * Create a section backed by a data file
921 PSECTION_OBJECT Section
;
923 LARGE_INTEGER MaximumSize
;
924 PFILE_OBJECT FileObject
;
925 PMM_SECTION_SEGMENT Segment
;
929 * Check the protection
931 if ((SectionPageProtection
& PAGE_FLAGS_VALID_FROM_USER_MODE
) !=
932 SectionPageProtection
)
934 return(STATUS_INVALID_PAGE_PROTECTION
);
940 Section
= ObCreateObject(SectionHandle
,
943 MmSectionObjectType
);
946 return(STATUS_UNSUCCESSFUL
);
952 Section
->SectionPageProtection
= SectionPageProtection
;
953 Section
->AllocateAttributes
= AllocationAttributes
;
954 InitializeListHead(&Section
->ViewListHead
);
955 KeInitializeSpinLock(&Section
->ViewListLock
);
956 KeInitializeMutex(&Section
->Lock
, 0);
958 Section
->NrSegments
= 1;
959 Section
->ImageBase
= NULL
;
960 Section
->EntryPoint
= NULL
;
961 Section
->StackReserve
= 0;
962 Section
->StackCommit
= 0;
963 Section
->Subsystem
= 0;
964 Section
->MinorSubsystemVersion
= 0;
965 Section
->MajorSubsystemVersion
= 0;
966 Section
->ImageCharacteristics
= 0;
967 Section
->Machine
= 0;
968 Section
->Executable
= FALSE
;
971 * Check file access required
973 if (SectionPageProtection
& PAGE_READWRITE
||
974 SectionPageProtection
& PAGE_EXECUTE_READWRITE
)
976 FileAccess
= FILE_READ_DATA
| FILE_WRITE_DATA
;
980 FileAccess
= FILE_READ_DATA
;
984 * Reference the file handle
986 Status
= ObReferenceObjectByHandle(FileHandle
,
992 if (!NT_SUCCESS(Status
))
994 ZwClose(*SectionHandle
);
995 ObDereferenceObject(Section
);
1000 * We can't do memory mappings if the file system doesn't support the
1003 if (!(FileObject
->Flags
& FO_FCB_IS_VALID
))
1005 ZwClose(*SectionHandle
);
1006 ObDereferenceObject(Section
);
1007 ObDereferenceObject(FileObject
);
1008 return(STATUS_INVALID_FILE_FOR_SECTION
);
1012 * FIXME: Revise this once a locking order for file size changes is
1015 if (UMaximumSize
!= NULL
)
1017 MaximumSize
= *UMaximumSize
;
1022 ((PREACTOS_COMMON_FCB_HEADER
)FileObject
->FsContext
)->FileSize
;
1028 Status
= KeWaitForSingleObject((PVOID
)&FileObject
->Lock
,
1033 if (Status
!= STATUS_SUCCESS
)
1035 ZwClose(*SectionHandle
);
1036 ObDereferenceObject(Section
);
1037 ObDereferenceObject(FileObject
);
1042 * If this file hasn't been mapped as a data file before then allocate a
1043 * section segment to describe the data file mapping
1045 if (FileObject
->SectionObjectPointers
->DataSectionObject
== NULL
)
1047 Segment
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(MM_SECTION_SEGMENT
),
1048 TAG_MM_SECTION_SEGMENT
);
1049 if (Segment
== NULL
)
1051 KeSetEvent((PVOID
)&FileObject
->Lock
, IO_NO_INCREMENT
, FALSE
);
1052 ZwClose(*SectionHandle
);
1053 ObDereferenceObject(Section
);
1054 ObDereferenceObject(FileObject
);
1055 return(STATUS_NO_MEMORY
);
1057 Section
->Segments
= Segment
;
1058 Segment
->ReferenceCount
= 1;
1059 KeInitializeMutex(&Segment
->Lock
, 0);
1062 * Set the lock before assigning the segment to the file object
1064 Status
= KeWaitForSingleObject((PVOID
)&Segment
->Lock
,
1069 if (Status
!= STATUS_SUCCESS
)
1071 KeSetEvent((PVOID
)&FileObject
->Lock
, IO_NO_INCREMENT
, FALSE
);
1072 ExFreePool(Segment
);
1073 ZwClose(*SectionHandle
);
1074 ObDereferenceObject(Section
);
1075 ObDereferenceObject(FileObject
);
1078 FileObject
->SectionObjectPointers
->DataSectionObject
= (PVOID
)Segment
;
1080 Segment
->FileOffset
= 0;
1081 Segment
->Protection
= 0;
1082 Segment
->Attributes
= 0;
1084 Segment
->Characteristics
= 0;
1085 if (AllocationAttributes
& SEC_RESERVE
)
1087 Segment
->Length
= 0;
1091 Segment
->Length
= MaximumSize
.u
.LowPart
;
1093 Segment
->VirtualAddress
= NULL
;
1098 * If the file is already mapped as a data file then we may need
1102 (PMM_SECTION_SEGMENT
)FileObject
->SectionObjectPointers
->
1104 Section
->Segments
= Segment
;
1105 InterlockedIncrement((PLONG
)&Segment
->ReferenceCount
);
1106 Status
= KeWaitForSingleObject((PVOID
)&Section
->Lock
,
1111 if (Status
!= STATUS_SUCCESS
)
1113 InterlockedDecrement((PLONG
)&Segment
->ReferenceCount
);
1114 KeSetEvent((PVOID
)&FileObject
->Lock
, IO_NO_INCREMENT
, FALSE
);
1115 ZwClose(*SectionHandle
);
1116 ObDereferenceObject(Section
);
1117 ObDereferenceObject(FileObject
);
1120 if (MaximumSize
.u
.LowPart
> Segment
->Length
&&
1121 !(AllocationAttributes
& SEC_RESERVE
))
1123 Segment
->Length
= MaximumSize
.u
.LowPart
;
1126 KeSetEvent((PVOID
)&FileObject
->Lock
, IO_NO_INCREMENT
, FALSE
);
1127 Section
->FileObject
= FileObject
;
1128 KeReleaseMutex(&Segment
->Lock
, FALSE
);
1130 ObDereferenceObject(Section
);
1131 return(STATUS_SUCCESS
);
1135 MmCreateImageSection(PHANDLE SectionHandle
,
1136 ACCESS_MASK DesiredAccess
,
1137 POBJECT_ATTRIBUTES ObjectAttributes
,
1138 PLARGE_INTEGER UMaximumSize
,
1139 ULONG SectionPageProtection
,
1140 ULONG AllocationAttributes
,
1143 PSECTION_OBJECT Section
;
1145 PFILE_OBJECT FileObject
;
1147 IMAGE_DOS_HEADER DosHeader
;
1148 IO_STATUS_BLOCK Iosb
;
1149 LARGE_INTEGER Offset
;
1150 IMAGE_NT_HEADERS PEHeader
;
1151 PIMAGE_SECTION_HEADER ImageSections
;
1152 PMM_SECTION_SEGMENT SectionSegments
;
1154 PMM_IMAGE_SECTION_OBJECT ImageSectionObject
;
1157 * Check the protection
1159 if ((SectionPageProtection
& PAGE_FLAGS_VALID_FROM_USER_MODE
) !=
1160 SectionPageProtection
)
1162 return(STATUS_INVALID_PAGE_PROTECTION
);
1166 * Specifying a maximum size is meaningless for an image section
1168 if (UMaximumSize
!= NULL
)
1170 return(STATUS_INVALID_PARAMETER_4
);
1174 * Read the dos header
1176 Offset
.QuadPart
= 0;
1177 Status
= ZwReadFile(FileHandle
,
1186 if (!NT_SUCCESS(Status
))
1190 if (Iosb
.Information
!= sizeof(DosHeader
))
1192 return(STATUS_INVALID_IMAGE_FORMAT
);
1196 * Check the DOS signature
1198 if (DosHeader
.e_magic
!= IMAGE_DOS_SIGNATURE
)
1200 return(STATUS_INVALID_IMAGE_FORMAT
);
1204 * Read the PE header
1206 Offset
.QuadPart
= DosHeader
.e_lfanew
;
1207 Status
= ZwReadFile(FileHandle
,
1216 if (!NT_SUCCESS(Status
))
1220 if (Iosb
.Information
!= sizeof(PEHeader
))
1222 return(STATUS_INVALID_IMAGE_FORMAT
);
1226 * Check the signature
1228 if (PEHeader
.Signature
!= IMAGE_NT_SIGNATURE
)
1230 return(STATUS_INVALID_IMAGE_FORMAT
);
1234 * Read in the section headers
1236 Offset
.QuadPart
= DosHeader
.e_lfanew
+ sizeof(PEHeader
);
1238 ExAllocatePool(NonPagedPool
,
1239 PEHeader
.FileHeader
.NumberOfSections
*
1240 sizeof(IMAGE_SECTION_HEADER
));
1241 Status
= ZwReadFile(FileHandle
,
1247 PEHeader
.FileHeader
.NumberOfSections
*
1248 sizeof(IMAGE_SECTION_HEADER
),
1251 if (!NT_SUCCESS(Status
))
1253 ExFreePool(ImageSections
);
1256 if (Iosb
.Information
!=
1257 (PEHeader
.FileHeader
.NumberOfSections
* sizeof(IMAGE_SECTION_HEADER
)))
1259 ExFreePool(ImageSections
);
1260 return(STATUS_INVALID_IMAGE_FORMAT
);
1264 * Create the section
1266 Section
= ObCreateObject(SectionHandle
,
1269 MmSectionObjectType
);
1270 if (Section
== NULL
)
1272 ExFreePool(ImageSections
);
1273 return(STATUS_UNSUCCESSFUL
);
1279 Section
->SectionPageProtection
= SectionPageProtection
;
1280 Section
->AllocateAttributes
= AllocationAttributes
;
1281 InitializeListHead(&Section
->ViewListHead
);
1282 KeInitializeSpinLock(&Section
->ViewListLock
);
1283 KeInitializeMutex(&Section
->Lock
, 0);
1284 Section
->Flags
= MM_IMAGE_SECTION
;
1285 Section
->NrSegments
= PEHeader
.FileHeader
.NumberOfSections
+ 1;
1286 Section
->ImageBase
= (PVOID
)PEHeader
.OptionalHeader
.ImageBase
;
1287 Section
->EntryPoint
= (PVOID
)PEHeader
.OptionalHeader
.AddressOfEntryPoint
;
1288 Section
->StackReserve
= PEHeader
.OptionalHeader
.SizeOfStackReserve
;
1289 Section
->StackCommit
= PEHeader
.OptionalHeader
.SizeOfStackCommit
;
1290 Section
->Subsystem
= PEHeader
.OptionalHeader
.Subsystem
;
1291 Section
->MinorSubsystemVersion
=
1292 PEHeader
.OptionalHeader
.MinorSubsystemVersion
;
1293 Section
->MajorSubsystemVersion
=
1294 PEHeader
.OptionalHeader
.MajorSubsystemVersion
;
1295 Section
->ImageCharacteristics
= PEHeader
.FileHeader
.Characteristics
;
1296 Section
->Machine
= PEHeader
.FileHeader
.Machine
;
1297 Section
->Executable
= (PEHeader
.OptionalHeader
.SizeOfCode
!= 0);
1300 * Check file access required
1302 if (SectionPageProtection
& PAGE_READWRITE
||
1303 SectionPageProtection
& PAGE_EXECUTE_READWRITE
)
1305 FileAccess
= FILE_READ_DATA
| FILE_WRITE_DATA
;
1309 FileAccess
= FILE_READ_DATA
;
1313 * Reference the file handle
1315 Status
= ObReferenceObjectByHandle(FileHandle
,
1319 (PVOID
*)&FileObject
,
1321 if (!NT_SUCCESS(Status
))
1323 ZwClose(*SectionHandle
);
1324 ObDereferenceObject(Section
);
1325 ExFreePool(ImageSections
);
1330 * We can't do memory mappings if the file system doesn't support the
1333 if (!(FileObject
->Flags
& FO_FCB_IS_VALID
))
1335 ZwClose(*SectionHandle
);
1336 ObDereferenceObject(Section
);
1337 ObDereferenceObject(FileObject
);
1338 ExFreePool(ImageSections
);
1339 return(STATUS_INVALID_FILE_FOR_SECTION
);
1345 Status
= KeWaitForSingleObject((PVOID
)&FileObject
->Lock
,
1350 if (Status
!= STATUS_SUCCESS
)
1352 ZwClose(*SectionHandle
);
1353 ObDereferenceObject(Section
);
1354 ObDereferenceObject(FileObject
);
1355 ExFreePool(ImageSections
);
1360 * If this file hasn't been mapped as a image file before then allocate the
1361 * section segments to describe the mapping
1363 NrSegments
= PEHeader
.FileHeader
.NumberOfSections
+ 1;
1364 if (FileObject
->SectionObjectPointers
->ImageSectionObject
== NULL
)
1369 Size
= sizeof(MM_IMAGE_SECTION_OBJECT
) +
1370 (sizeof(MM_SECTION_SEGMENT
) * NrSegments
);
1371 ImageSectionObject
=
1372 ExAllocatePoolWithTag(NonPagedPool
, Size
, TAG_MM_SECTION_SEGMENT
);
1373 if (ImageSectionObject
== NULL
)
1375 KeSetEvent((PVOID
)&FileObject
->Lock
, IO_NO_INCREMENT
, FALSE
);
1376 ZwClose(*SectionHandle
);
1377 ObDereferenceObject(Section
);
1378 ObDereferenceObject(FileObject
);
1379 ExFreePool(ImageSections
);
1380 return(STATUS_NO_MEMORY
);
1382 ImageSectionObject
->NrSegments
= NrSegments
;
1383 SectionSegments
= ImageSectionObject
->Segments
;
1384 Section
->Segments
= SectionSegments
;
1386 SectionSegments
[0].FileOffset
= 0;
1387 SectionSegments
[0].Characteristics
= IMAGE_SECTION_CHAR_DATA
;
1388 SectionSegments
[0].Protection
= PAGE_READWRITE
;
1389 SectionSegments
[0].RawLength
= PAGESIZE
;
1390 SectionSegments
[0].Length
= PAGESIZE
;
1391 SectionSegments
[0].Flags
= 0;
1392 SectionSegments
[0].ReferenceCount
= 1;
1393 SectionSegments
[0].VirtualAddress
= 0;
1394 KeInitializeMutex(&SectionSegments
[0].Lock
, 0);
1396 for (i
= 1; i
< NrSegments
; i
++)
1398 SectionSegments
[i
].FileOffset
=
1399 ImageSections
[i
-1].PointerToRawData
;
1400 SectionSegments
[i
].Characteristics
=
1401 ImageSections
[i
-1].Characteristics
;
1402 if (ImageSections
[i
-1].Characteristics
& IMAGE_SECTION_CHAR_CODE
)
1404 SectionSegments
[i
].Protection
= PAGE_EXECUTE_READ
;
1405 SectionSegments
[i
].Attributes
= 0;
1407 else if (ImageSections
[i
-1].Characteristics
&
1408 IMAGE_SECTION_CHAR_DATA
)
1410 SectionSegments
[i
].Protection
= PAGE_READWRITE
;
1411 SectionSegments
[i
].Attributes
= 0;
1413 else if (ImageSections
[i
-1].Characteristics
& IMAGE_SECTION_CHAR_BSS
)
1415 SectionSegments
[i
].Protection
= PAGE_READWRITE
;
1416 SectionSegments
[i
].Attributes
= MM_SECTION_SEGMENT_BSS
;
1418 SectionSegments
[i
].RawLength
= ImageSections
[i
-1].SizeOfRawData
;
1419 SectionSegments
[i
].Length
=
1420 ImageSections
[i
-1].Misc
.VirtualSize
;
1421 SectionSegments
[i
].Flags
= 0;
1422 SectionSegments
[i
].ReferenceCount
= 1;
1423 SectionSegments
[i
].VirtualAddress
=
1424 (PVOID
)ImageSections
[i
-1].VirtualAddress
;
1425 KeInitializeMutex(&SectionSegments
[i
].Lock
, 0);
1428 FileObject
->SectionObjectPointers
->ImageSectionObject
=
1429 (PVOID
)ImageSectionObject
;
1430 ExFreePool(ImageSections
);
1436 ImageSectionObject
= (PMM_IMAGE_SECTION_OBJECT
)
1437 FileObject
->SectionObjectPointers
->ImageSectionObject
;
1438 SectionSegments
= ImageSectionObject
->Segments
;
1439 Section
->Segments
= SectionSegments
;
1442 * Otherwise just reference all the section segments
1444 for (i
= 0; i
< NrSegments
; i
++)
1446 InterlockedIncrement(&SectionSegments
[i
].ReferenceCount
);
1450 KeSetEvent((PVOID
)&FileObject
->Lock
, IO_NO_INCREMENT
, FALSE
);
1451 Section
->FileObject
= FileObject
;
1453 ObDereferenceObject(Section
);
1454 return(STATUS_SUCCESS
);
1458 NtCreateSection (OUT PHANDLE SectionHandle
,
1459 IN ACCESS_MASK DesiredAccess
,
1460 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1461 IN PLARGE_INTEGER MaximumSize OPTIONAL
,
1462 IN ULONG SectionPageProtection OPTIONAL
,
1463 IN ULONG AllocationAttributes
,
1464 IN HANDLE FileHandle OPTIONAL
)
1466 if (AllocationAttributes
& SEC_IMAGE
)
1468 return(MmCreateImageSection(SectionHandle
,
1472 SectionPageProtection
,
1473 AllocationAttributes
,
1476 else if (FileHandle
!= NULL
)
1478 return(MmCreateDataFileSection(SectionHandle
,
1482 SectionPageProtection
,
1483 AllocationAttributes
,
1488 return(MmCreatePageFileSection(SectionHandle
,
1492 SectionPageProtection
,
1493 AllocationAttributes
));
1498 /**********************************************************************
1517 NtOpenSection(PHANDLE SectionHandle
,
1518 ACCESS_MASK DesiredAccess
,
1519 POBJECT_ATTRIBUTES ObjectAttributes
)
1525 Status
= ObOpenObjectByName(ObjectAttributes
,
1526 MmSectionObjectType
,
1537 MmMapViewOfSegment(PEPROCESS Process
,
1538 PMADDRESS_SPACE AddressSpace
,
1539 PSECTION_OBJECT Section
,
1540 PMM_SECTION_SEGMENT Segment
,
1550 Status
= MmCreateMemoryArea(Process
,
1551 &Process
->AddressSpace
,
1552 MEMORY_AREA_SECTION_VIEW_COMMIT
,
1558 if (!NT_SUCCESS(Status
))
1560 MmUnlockAddressSpace(AddressSpace
);
1564 KeAcquireSpinLock(&Section
->ViewListLock
, &oldIrql
);
1565 InsertTailList(&Section
->ViewListHead
,
1566 &MArea
->Data
.SectionData
.ViewListEntry
);
1567 KeReleaseSpinLock(&Section
->ViewListLock
, oldIrql
);
1569 ObReferenceObjectByPointer((PVOID
)Section
,
1572 ExGetPreviousMode());
1573 MArea
->Data
.SectionData
.Segment
= Segment
;
1574 MArea
->Data
.SectionData
.Section
= Section
;
1575 MArea
->Data
.SectionData
.ViewOffset
= ViewOffset
;
1577 return(STATUS_SUCCESS
);
1581 /**********************************************************************
1583 * NtMapViewOfSection
1586 * Maps a view of a section into the virtual address space of a
1591 * Handle of the section.
1594 * Handle of the process.
1597 * Desired base address (or NULL) on entry;
1598 * Actual base address of the view on exit.
1601 * Number of high order address bits that must be zero.
1604 * Size in bytes of the initially committed section of
1608 * Offset in bytes from the beginning of the section
1609 * to the beginning of the view.
1612 * Desired length of map (or zero to map all) on entry
1613 * Actual length mapped on exit.
1615 * InheritDisposition
1616 * Specified how the view is to be shared with
1620 * Type of allocation for the pages.
1623 * Protection for the committed region of the view.
1629 NtMapViewOfSection(HANDLE SectionHandle
,
1630 HANDLE ProcessHandle
,
1634 PLARGE_INTEGER SectionOffset
,
1636 SECTION_INHERIT InheritDisposition
,
1637 ULONG AllocationType
,
1640 PSECTION_OBJECT Section
;
1644 PMADDRESS_SPACE AddressSpace
;
1646 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1647 PROCESS_VM_OPERATION
,
1652 if (!NT_SUCCESS(Status
))
1657 AddressSpace
= &Process
->AddressSpace
;
1659 Status
= ObReferenceObjectByHandle(SectionHandle
,
1661 MmSectionObjectType
,
1665 if (!(NT_SUCCESS(Status
)))
1667 DPRINT("ObReference failed rc=%x\n",Status
);
1668 ObDereferenceObject(Process
);
1672 MmLockAddressSpace(AddressSpace
);
1673 MmLockSection(Section
);
1675 if (Section
->Flags
& MM_IMAGE_SECTION
)
1679 for (i
= 0; i
< Section
->NrSegments
; i
++)
1683 SBaseAddress
= (PVOID
)
1684 ((ULONG
)Section
->ImageBase
+
1685 (ULONG
)Section
->Segments
[i
].VirtualAddress
);
1687 MmLockSectionSegment(&Section
->Segments
[i
]);
1688 Status
= MmMapViewOfSegment(Process
,
1689 &Process
->AddressSpace
,
1691 &Section
->Segments
[i
],
1693 Section
->Segments
[i
].Length
,
1694 Section
->Segments
[i
].Protection
,
1695 Section
->Segments
[i
].FileOffset
);
1696 MmUnlockSectionSegment(&Section
->Segments
[i
]);
1697 if (!NT_SUCCESS(Status
))
1699 MmUnlockSection(Section
);
1700 MmUnlockAddressSpace(AddressSpace
);
1701 ObDereferenceObject(Section
);
1702 ObDereferenceObject(Process
);
1706 *BaseAddress
= Section
->ImageBase
;
1710 if (SectionOffset
== NULL
)
1716 ViewOffset
= SectionOffset
->u
.LowPart
;
1719 if ((ViewOffset
% PAGESIZE
) != 0)
1721 MmUnlockSection(Section
);
1722 MmUnlockAddressSpace(AddressSpace
);
1723 ObDereferenceObject(Section
);
1724 ObDereferenceObject(Process
);
1725 return(STATUS_MAPPED_ALIGNMENT
);
1728 if (((*ViewSize
)+ViewOffset
) > Section
->MaximumSize
.u
.LowPart
)
1730 (*ViewSize
) = Section
->MaximumSize
.u
.LowPart
- ViewOffset
;
1733 MmLockSectionSegment(Section
->Segments
);
1734 Status
= MmMapViewOfSegment(Process
,
1735 &Process
->AddressSpace
,
1742 MmUnlockSectionSegment(Section
->Segments
);
1743 if (!NT_SUCCESS(Status
))
1745 MmUnlockSection(Section
);
1746 MmUnlockAddressSpace(AddressSpace
);
1747 ObDereferenceObject(Section
);
1748 ObDereferenceObject(Process
);
1753 MmUnlockSection(Section
);
1754 MmUnlockAddressSpace(AddressSpace
);
1755 ObDereferenceObject(Section
);
1756 ObDereferenceObject(Process
);
1758 return(STATUS_SUCCESS
);
1762 MmFreeSectionPage(PVOID Context
, PVOID Address
, ULONG PhysAddr
)
1767 MArea
= (PMEMORY_AREA
)Context
;
1774 ((ULONG
)PAGE_ROUND_DOWN(Address
) - (ULONG
)MArea
->BaseAddress
) +
1775 MArea
->Data
.SectionData
.ViewOffset
;
1777 Entry
= MmGetPageEntrySectionSegment(MArea
->Data
.SectionData
.Segment
,
1780 * Just dereference private pages
1782 if (PhysAddr
!= (Entry
& 0xFFFFF000))
1784 MmDereferencePage((PVOID
)PhysAddr
);
1789 MmUnsharePageEntrySectionSegment(MArea
->Data
.SectionData
.Segment
,
1791 MmDereferencePage((PVOID
)PhysAddr
);
1798 MmUnmapViewOfSection(PEPROCESS Process
,
1802 PMEMORY_AREA MemoryArea
;
1803 PMADDRESS_SPACE AddressSpace
;
1804 PSECTION_OBJECT Section
;
1805 PMM_SECTION_SEGMENT Segment
;
1808 AddressSpace
= &Process
->AddressSpace
;
1810 DPRINT("Opening memory area Process %x BaseAddress %x\n",
1811 Process
, BaseAddress
);
1812 MmLockAddressSpace(AddressSpace
);
1813 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
1815 if (MemoryArea
== NULL
)
1817 MmUnlockAddressSpace(AddressSpace
);
1818 return(STATUS_UNSUCCESSFUL
);
1821 MmLockSection(MemoryArea
->Data
.SectionData
.Section
);
1822 MmLockSectionSegment(MemoryArea
->Data
.SectionData
.Segment
);
1823 Section
= MemoryArea
->Data
.SectionData
.Section
;
1824 Segment
= MemoryArea
->Data
.SectionData
.Segment
;
1825 KeAcquireSpinLock(&Section
->ViewListLock
, &oldIrql
);
1826 RemoveEntryList(&MemoryArea
->Data
.SectionData
.ViewListEntry
);
1827 KeReleaseSpinLock(&Section
->ViewListLock
, oldIrql
);
1828 if (MemoryArea
->Data
.SectionData
.Section
->Flags
& SO_PHYSICAL_MEMORY
)
1830 Status
= MmFreeMemoryArea(&Process
->AddressSpace
,
1838 Status
= MmFreeMemoryArea(&Process
->AddressSpace
,
1844 MmUnlockSection(Section
);
1845 MmUnlockSectionSegment(Segment
);
1846 ObDereferenceObject(Section
);
1847 MmUnlockAddressSpace(AddressSpace
);
1848 return(STATUS_SUCCESS
);
1851 /**********************************************************************
1853 * NtUnmapViewOfSection
1869 NtUnmapViewOfSection (HANDLE ProcessHandle
,
1875 DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n",
1876 ProcessHandle
, BaseAddress
);
1878 DPRINT("Referencing process\n");
1879 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1880 PROCESS_VM_OPERATION
,
1885 if (!NT_SUCCESS(Status
))
1887 DPRINT("ObReferenceObjectByHandle failed (Status %x)\n", Status
);
1891 Status
= MmUnmapViewOfSection(Process
, BaseAddress
);
1893 ObDereferenceObject(Process
);
1900 NtQuerySection (IN HANDLE SectionHandle
,
1901 IN CINT SectionInformationClass
,
1902 OUT PVOID SectionInformation
,
1904 OUT PULONG ResultLength
)
1906 * FUNCTION: Queries the information of a section object.
1908 * SectionHandle = Handle to the section link object
1909 * SectionInformationClass = Index to a certain information structure
1910 * SectionInformation (OUT)= Caller supplies storage for resulting
1912 * Length = Size of the supplied storage
1913 * ResultLength = Data written
1918 PSECTION_OBJECT Section
;
1921 Status
= ObReferenceObjectByHandle(SectionHandle
,
1923 MmSectionObjectType
,
1927 if (!(NT_SUCCESS(Status
)))
1932 switch (SectionInformationClass
)
1934 case SectionBasicInformation
:
1936 PSECTION_BASIC_INFORMATION Sbi
;
1938 if (Length
!= sizeof(SECTION_BASIC_INFORMATION
))
1940 ObDereferenceObject(Section
);
1941 return(STATUS_INFO_LENGTH_MISMATCH
);
1944 Sbi
= (PSECTION_BASIC_INFORMATION
)SectionInformation
;
1946 Sbi
->BaseAddress
= 0;
1947 Sbi
->Attributes
= 0;
1948 Sbi
->Size
.QuadPart
= 0;
1950 Status
= STATUS_SUCCESS
;
1955 case SectionImageInformation
:
1957 PSECTION_IMAGE_INFORMATION Sii
;
1959 if (Length
!= sizeof(SECTION_IMAGE_INFORMATION
))
1961 ObDereferenceObject(Section
);
1962 return(STATUS_INFO_LENGTH_MISMATCH
);
1965 Sii
->EntryPoint
= Section
->EntryPoint
;
1967 Sii
->StackReserve
= Section
->StackReserve
;
1968 Sii
->StackCommit
= Section
->StackCommit
;
1969 Sii
->Subsystem
= Section
->Subsystem
;
1970 Sii
->MinorSubsystemVersion
= Section
->MinorSubsystemVersion
;
1971 Sii
->MajorSubsystemVersion
= Section
->MajorSubsystemVersion
;
1973 Sii
->Characteristics
= Section
->ImageCharacteristics
;
1974 Sii
->ImageNumber
= Section
->Machine
;
1975 Sii
->Executable
= Section
->Executable
;
1977 Sii
->Unknown4
[0] = 0;
1978 Sii
->Unknown4
[1] = 0;
1979 Sii
->Unknown4
[2] = 0;
1981 Status
= STATUS_SUCCESS
;
1986 Status
= STATUS_INVALID_INFO_CLASS
;
1988 ObDereferenceObject(Section
);
1994 NtExtendSection(IN HANDLE SectionHandle
,
1995 IN ULONG NewMaximumSize
)
2001 /**********************************************************************
2003 * MmAllocateSection@4
2013 * Code taken from ntoskrnl/mm/special.c.
2019 MmAllocateSection (IN ULONG Length
)
2025 PMADDRESS_SPACE AddressSpace
;
2027 DPRINT("MmAllocateSection(Length %x)\n",Length
);
2029 AddressSpace
= MmGetKernelAddressSpace();
2031 MmLockAddressSpace(AddressSpace
);
2032 Status
= MmCreateMemoryArea (NULL
,
2040 if (!NT_SUCCESS(STATUS_SUCCESS
))
2044 DPRINT("Result %p\n",Result
);
2045 for (i
= 0; (i
<= (Length
/ PAGESIZE
)); i
++)
2047 Status
= MmCreateVirtualMapping (NULL
,
2048 (Result
+ (i
* PAGESIZE
)),
2050 (ULONG
)MmAllocPage(0));
2051 if (!NT_SUCCESS(Status
))
2053 DbgPrint("Unable to create virtual mapping\n");
2057 MmUnlockAddressSpace(AddressSpace
);
2058 return ((PVOID
)Result
);
2062 /**********************************************************************
2064 * MmMapViewOfSection@40
2069 * FIXME: stack space allocated is 40 bytes, but nothing
2070 * is known about what they are filled with.
2077 MmMapViewOfSection (DWORD Unknown0
,
2094 MmCanFileBeTruncated (IN PSECTION_OBJECT_POINTERS SectionObjectPointer
,
2095 IN PLARGE_INTEGER NewFileSize
)
2103 MmDisableModifiedWriteOfSection (DWORD Unknown0
)
2110 MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer
,
2111 IN MMFLUSH_TYPE FlushType
)
2118 MmForceSectionClosed (DWORD Unknown0
,
2127 MmMapViewInSystemSpace (IN PVOID Section
,
2128 OUT PVOID
* MappedBase
,
2132 return (STATUS_NOT_IMPLEMENTED
);
2136 MmUnmapViewInSystemSpace (DWORD Unknown0
)
2139 return (STATUS_NOT_IMPLEMENTED
);
2144 MmSetBankedSection (DWORD Unknown0
,
2152 return (STATUS_NOT_IMPLEMENTED
);
2156 /**********************************************************************
2161 * Creates a section object.
2164 * SectionObjiect (OUT)
2165 * Caller supplied storage for the resulting pointer
2166 * to a SECTION_BOJECT instance;
2169 * Specifies the desired access to the section can be a
2171 * STANDARD_RIGHTS_REQUIRED |
2173 * SECTION_MAP_WRITE |
2174 * SECTION_MAP_READ |
2175 * SECTION_MAP_EXECUTE
2177 * ObjectAttributes [OPTIONAL]
2178 * Initialized attributes for the object can be used
2179 * to create a named section;
2182 * Maximizes the size of the memory section. Must be
2183 * non-NULL for a page-file backed section.
2184 * If value specified for a mapped file and the file is
2185 * not large enough, file will be extended.
2187 * SectionPageProtection
2188 * Can be a combination of:
2194 * AllocationAttributes
2195 * Can be a combination of:
2200 * Handle to a file to create a section mapped to a file
2201 * instead of a memory backed section;
2210 MmCreateSection (OUT PSECTION_OBJECT
* SectionObject
,
2211 IN ACCESS_MASK DesiredAccess
,
2212 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
2213 IN PLARGE_INTEGER MaximumSize
,
2214 IN ULONG SectionPageProtection
,
2215 IN ULONG AllocationAttributes
,
2216 IN HANDLE FileHandle OPTIONAL
,
2217 IN PFILE_OBJECT File OPTIONAL
)
2219 return (STATUS_NOT_IMPLEMENTED
);