592fe7b681bad497d2408415c07a872b4fb30962
[reactos.git] / reactos / ntoskrnl / mm / section.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: section.c,v 1.53 2001/03/29 17:24:43 dwelch Exp $
20 *
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/mm/section.c
23 * PURPOSE: Implements section objects
24 * PROGRAMMER: David Welch (welch@mcmail.com)
25 * UPDATE HISTORY:
26 * Created 22/05/98
27 */
28
29 /* INCLUDES *****************************************************************/
30
31 #include <limits.h>
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>
39
40 #define NDEBUG
41 #include <internal/debug.h>
42
43 /* GLOBALS *******************************************************************/
44
45 POBJECT_TYPE EXPORTED MmSectionObjectType = NULL;
46
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,
51 SECTION_ALL_ACCESS};
52
53 #define TAG_MM_SECTION_SEGMENT TAG('M', 'M', 'S', 'S')
54 #define TAG_SECTION_PAGE_TABLE TAG('M', 'S', 'P', 'T')
55
56 #define SHARE_COUNT(E) ((E) & 0xFFF)
57 #define MAX_SHARE_COUNT 0xFFF
58
59 /* FUNCTIONS *****************************************************************/
60
61 VOID
62 MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment)
63 {
64 ULONG i;
65
66 for (i = 0; i < NR_SECTION_PAGE_TABLES; i++)
67 {
68 if (Segment->PageDirectory.PageTables[i] != NULL)
69 {
70 ExFreePool(Segment->PageDirectory.PageTables[i]);
71 }
72 }
73 }
74
75 VOID
76 MmFreeSectionSegments(PFILE_OBJECT FileObject)
77 {
78 if (FileObject->SectionObjectPointers->ImageSectionObject != NULL)
79 {
80 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
81
82 ULONG i;
83
84 ImageSectionObject =
85 (PMM_IMAGE_SECTION_OBJECT)FileObject->SectionObjectPointers->
86 ImageSectionObject;
87
88 for (i = 0; i < ImageSectionObject->NrSegments; i++)
89 {
90 if (ImageSectionObject->Segments[i].ReferenceCount != 0)
91 {
92 DPRINT1("Image segment %d still referenced (was %d)\n", i,
93 ImageSectionObject->Segments[i].ReferenceCount);
94 KeBugCheck(0);
95 }
96 MmFreePageTablesSectionSegment(&ImageSectionObject->Segments[i]);
97 }
98 ExFreePool(ImageSectionObject);
99 FileObject->SectionObjectPointers->ImageSectionObject = NULL;
100 }
101 if (FileObject->SectionObjectPointers->DataSectionObject != NULL)
102 {
103 PMM_SECTION_SEGMENT Segment;
104
105 Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers->
106 DataSectionObject;
107
108 if (Segment->ReferenceCount != 0)
109 {
110 DPRINT1("Data segment still referenced\n");
111 KeBugCheck(0);
112 }
113 MmFreePageTablesSectionSegment(Segment);
114 ExFreePool(Segment);
115 FileObject->SectionObjectPointers->DataSectionObject = NULL;
116 }
117 }
118
119 NTSTATUS
120 MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
121 PMEMORY_AREA MArea,
122 PVOID Address)
123 {
124 return(STATUS_UNSUCCESSFUL);
125 }
126
127 VOID
128 MmLockSection(PSECTION_OBJECT Section)
129 {
130 KeWaitForSingleObject(&Section->Lock,
131 UserRequest,
132 KernelMode,
133 FALSE,
134 NULL);
135 }
136
137 VOID
138 MmUnlockSection(PSECTION_OBJECT Section)
139 {
140 KeReleaseMutex(&Section->Lock, FALSE);
141 }
142
143 VOID
144 MmLockSectionSegment(PMM_SECTION_SEGMENT Segment)
145 {
146 KeWaitForSingleObject(&Segment->Lock,
147 UserRequest,
148 KernelMode,
149 FALSE,
150 NULL);
151 }
152
153 VOID
154 MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment)
155 {
156 KeReleaseMutex(&Segment->Lock, FALSE);
157 }
158
159
160
161 VOID
162 MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
163 ULONG Offset,
164 ULONG Entry)
165 {
166 PSECTION_PAGE_TABLE Table;
167 ULONG DirectoryOffset;
168 ULONG TableOffset;
169
170 DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
171 Table = Segment->PageDirectory.PageTables[DirectoryOffset];
172 if (Table == NULL)
173 {
174 Table =
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);
180 }
181 TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
182 Table->Pages[TableOffset] = Entry;
183 }
184
185
186 ULONG
187 MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
188 ULONG Offset)
189 {
190 PSECTION_PAGE_TABLE Table;
191 ULONG Entry;
192 ULONG DirectoryOffset;
193 ULONG TableOffset;
194
195 DPRINT("MmGetPageEntrySection(Offset %x)\n", Offset);
196
197 DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
198 Table = Segment->PageDirectory.PageTables[DirectoryOffset];
199 DPRINT("Table %x\n", Table);
200 if (Table == NULL)
201 {
202 return(0);
203 }
204 TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
205 Entry = Table->Pages[TableOffset];
206 return(Entry);
207 }
208
209 VOID
210 MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
211 ULONG Offset)
212 {
213 ULONG Entry;
214
215 Entry = MmGetPageEntrySectionSegment(Segment, Offset);
216 if (Entry == 0)
217 {
218 DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
219 KeBugCheck(0);
220 }
221 if (SHARE_COUNT(Entry) == MAX_SHARE_COUNT)
222 {
223 DPRINT1("Maximum share count reached\n");
224 KeBugCheck(0);
225 }
226 Entry++;
227 MmSetPageEntrySectionSegment(Segment, Offset, Entry);
228 }
229
230 VOID
231 MmUnsharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
232 ULONG Offset)
233 {
234 ULONG Entry;
235
236 Entry = MmGetPageEntrySectionSegment(Segment, Offset);
237 if (Entry == 0)
238 {
239 DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
240 KeBugCheck(0);
241 }
242 if (SHARE_COUNT(Entry) == 0)
243 {
244 DPRINT1("Zero share count for unshare\n");
245 KeBugCheck(0);
246 }
247 Entry--;
248 MmSetPageEntrySectionSegment(Segment, Offset, Entry);
249 }
250
251
252 NTSTATUS
253 MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
254 MEMORY_AREA* MemoryArea,
255 PVOID Address,
256 BOOLEAN Locked)
257 {
258 LARGE_INTEGER Offset;
259 IO_STATUS_BLOCK IoStatus;
260 PMDL Mdl;
261 PVOID Page;
262 NTSTATUS Status;
263 ULONG PAddress;
264 PSECTION_OBJECT Section;
265 PMM_SECTION_SEGMENT Segment;
266 ULONG Entry;
267 ULONG Entry1;
268 ULONG Attributes;
269 PMM_PAGEOP PageOp;
270
271 /*
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
274 * that.
275 */
276 if (MmIsPagePresent(NULL, Address))
277 {
278 if (Locked)
279 {
280 MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
281 }
282 return(STATUS_SUCCESS);
283 }
284
285 PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
286 Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
287 MemoryArea->Data.SectionData.ViewOffset;
288
289 /*
290 * Lock the segment
291 */
292 Segment = MemoryArea->Data.SectionData.Segment;
293 Section = MemoryArea->Data.SectionData.Section;
294 MmLockSection(Section);
295 MmLockSectionSegment(Segment);
296
297 /*
298 * Get or create a page operation descriptor
299 */
300 PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart);
301 if (PageOp == NULL)
302 {
303 DPRINT1("MmGetPageOp failed\n");
304 KeBugCheck(0);
305 }
306
307 /*
308 * Check if someone else is already handling this fault, if so wait
309 * for them
310 */
311 if (PageOp->Thread != PsGetCurrentThread())
312 {
313 MmUnlockSectionSegment(Segment);
314 MmUnlockSection(Section);
315 MmUnlockAddressSpace(AddressSpace);
316 Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
317 0,
318 KernelMode,
319 FALSE,
320 NULL);
321 /*
322 * Check for various strange conditions
323 */
324 if (Status != STATUS_SUCCESS)
325 {
326 DPRINT1("Failed to wait for page op\n");
327 KeBugCheck(0);
328 }
329 if (PageOp->Status == STATUS_PENDING)
330 {
331 DPRINT1("Woke for page op before completion\n");
332 KeBugCheck(0);
333 }
334 /*
335 * If the thread handling this fault has failed then we don't retry
336 */
337 if (!NT_SUCCESS(PageOp->Status))
338 {
339 return(PageOp->Status);
340 }
341 MmLockAddressSpace(AddressSpace);
342 MmLockSection(Section);
343 MmLockSectionSegment(Segment);
344 /*
345 * If the completed fault was for another address space then set the
346 * page in this one.
347 */
348 if (!MmIsPagePresent(NULL, Address))
349 {
350 Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
351
352 Page = (PVOID)(Entry & 0xFFFFF000);
353 MmReferencePage(Page);
354 // MmSharePageEntrySectionSegment(Segment, Offset.u.LowPart);
355
356 Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
357 Address,
358 Attributes,
359 (ULONG)Page);
360 if (!NT_SUCCESS(Status))
361 {
362 DbgPrint("Unable to create virtual mapping\n");
363 KeBugCheck(0);
364 }
365 }
366 if (Locked)
367 {
368 MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
369 }
370 MmUnlockSectionSegment(Segment);
371 MmUnlockSection(Section);
372 MmReleasePageOp(PageOp);
373 return(STATUS_SUCCESS);
374 }
375
376 /*
377 * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
378 */
379 if (Section->Flags & SO_PHYSICAL_MEMORY)
380 {
381 /*
382 * Just map the desired physical page
383 */
384 Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
385 Address,
386 MemoryArea->Attributes,
387 Offset.QuadPart);
388 if (Locked)
389 {
390 MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
391 }
392
393 /*
394 * Cleanup and release locks
395 */
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);
402 }
403
404 /*
405 * Map anonymous memory for BSS sections
406 */
407 if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS)
408 {
409 Page = MmAllocPage(0);
410 while (Page == NULL)
411 {
412 MmUnlockSectionSegment(Segment);
413 MmUnlockSection(Section);
414 MmUnlockAddressSpace(AddressSpace);
415 MmWaitForFreePages();
416 MmLockAddressSpace(AddressSpace);
417 MmLockSection(Section);
418 MmLockSectionSegment(Segment);
419 Page = MmAllocPage(0);
420 }
421 Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
422 Address,
423 MemoryArea->Attributes,
424 (ULONG)Page);
425 if (Locked)
426 {
427 MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
428 }
429
430 /*
431 * Cleanup and release locks
432 */
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);
439 }
440
441 /*
442 * Check if this page needs to be mapped COW
443 */
444 if (Segment->Characteristics & IMAGE_SECTION_CHAR_DATA)
445 {
446 Attributes = PAGE_READONLY;
447 }
448 else
449 {
450 Attributes = MemoryArea->Attributes;
451 }
452
453 /*
454 * Get the entry corresponding to the offset within the section
455 */
456 Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
457
458 if (Entry == 0)
459 {
460 /*
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.
463 */
464
465 /*
466 * Allocate a page, this is rather complicated by the possibility
467 * we might have to move other things out of memory
468 */
469 Page = MmAllocPage(0);
470 while (Page == NULL)
471 {
472 MmUnlockSectionSegment(Segment);
473 MmUnlockSection(Section);
474 MmUnlockAddressSpace(AddressSpace);
475 MmWaitForFreePages();
476 MmLockAddressSpace(AddressSpace);
477 MmLockSection(Section);
478 MmLockSectionSegment(Segment);
479 Page = MmAllocPage(0);
480 }
481
482 /*
483 * Create an mdl to hold the page we are going to read data into.
484 */
485 Mdl = MmCreateMdl(NULL, NULL, PAGESIZE);
486 MmBuildMdlFromPages(Mdl, (PULONG)&Page);
487
488 /*
489 * Release all our locks and read in the page from disk
490 */
491 MmUnlockSectionSegment(Segment);
492 MmUnlockSection(Section);
493 MmUnlockAddressSpace(AddressSpace);
494 Status = IoPageRead(MemoryArea->Data.SectionData.Section->FileObject,
495 Mdl,
496 &Offset,
497 &IoStatus,
498 FALSE);
499 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
500 {
501 /*
502 * FIXME: What do we know in this case?
503 */
504 DPRINT1("IoPageRead failed (Status %x)\n", Status);
505
506 /*
507 * Cleanup and release locks
508 */
509 PageOp->Status = Status;
510 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
511 MmReleasePageOp(PageOp);
512 MmLockAddressSpace(AddressSpace);
513 return(Status);
514 }
515
516 /*
517 * Relock the address space, section and segment
518 */
519 MmLockAddressSpace(AddressSpace);
520 MmLockSection(Section);
521 MmLockSectionSegment(Segment);
522
523 /*
524 * Check the entry. No one should change the status of a page
525 * that has a pending page-in.
526 */
527 Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
528 if (Entry != Entry1)
529 {
530 DbgPrint("Someone changed ppte entry while we slept\n");
531 KeBugCheck(0);
532 }
533
534 /*
535 * Mark the offset within the section as having valid, in-memory
536 * data
537 */
538 Entry = (ULONG)Page;
539 MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
540 // MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
541
542 Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
543 Address,
544 Attributes,
545 (ULONG)Page);
546 if (!NT_SUCCESS(Status))
547 {
548 DbgPrint("Unable to create virtual mapping\n");
549 KeBugCheck(0);
550 }
551 if (Locked)
552 {
553 MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
554 }
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);
562 }
563 else
564 {
565 /*
566 * If the section offset is already in-memory and valid then just
567 * take another reference to the page
568 */
569
570 Page = (PVOID)Entry;
571 MmReferencePage(Page);
572 // MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
573
574 Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
575 Address,
576 Attributes,
577 (ULONG)Page);
578 if (!NT_SUCCESS(Status))
579 {
580 DbgPrint("Unable to create virtual mapping\n");
581 KeBugCheck(0);
582 }
583 if (Locked)
584 {
585 MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
586 }
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);
593 }
594 }
595
596 NTSTATUS
597 MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
598 MEMORY_AREA* MemoryArea,
599 PVOID Address,
600 BOOLEAN Locked)
601 {
602 PMM_SECTION_SEGMENT Segment;
603 PSECTION_OBJECT Section;
604 ULONG OldPage;
605 PVOID NewPage;
606 PVOID NewAddress;
607 NTSTATUS Status;
608
609 /*
610 * Check if the page has been paged out or has already been set readwrite
611 */
612 if (!MmIsPagePresent(NULL, Address) ||
613 MmGetPageProtect(NULL, Address) & PAGE_READWRITE)
614 {
615 return(STATUS_SUCCESS);
616 }
617
618 /*
619 * Lock the segment
620 */
621 Segment = MemoryArea->Data.SectionData.Segment;
622 Section = MemoryArea->Data.SectionData.Section;
623 MmLockSection(Section);
624 MmLockSectionSegment(Segment);
625
626 if (!(Segment->Characteristics & IMAGE_SECTION_CHAR_DATA))
627 {
628 MmUnlockSection(Section);
629 MmUnlockSectionSegment(Segment);
630 return(STATUS_UNSUCCESSFUL);
631 }
632
633 /*
634 * Allocate a page
635 */
636 NewPage = MmAllocPage(0);
637 while (NewPage == NULL)
638 {
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)
646 {
647 MmUnlockAddressSpace(AddressSpace);
648 return(STATUS_SUCCESS);
649 }
650 MmLockSection(Section);
651 MmLockSectionSegment(Segment);
652 NewPage = MmAllocPage(0);
653 }
654
655 OldPage = MmGetPhysicalAddressForProcess(NULL, Address);
656
657 NewAddress = ExAllocatePageWithPhysPage((ULONG)NewPage);
658 memcpy(NewAddress, (PVOID)PAGE_ROUND_DOWN(Address), PAGESIZE);
659 ExUnmapPage(NewAddress);
660
661 Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
662 Address,
663 MemoryArea->Attributes,
664 (ULONG)NewPage);
665 if (!NT_SUCCESS(Status))
666 {
667 DbgPrint("Unable to create virtual mapping\n");
668 KeBugCheck(0);
669 }
670 if (Locked)
671 {
672 MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
673 }
674 MmUnlockSectionSegment(Segment);
675 MmUnlockSection(Section);
676 return(STATUS_SUCCESS);
677 }
678
679 ULONG
680 MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
681 MEMORY_AREA* MemoryArea,
682 PVOID Address,
683 PBOOLEAN Ul)
684 {
685 (*Ul) = FALSE;
686 return(0);
687 }
688
689 VOID
690 MmpDeleteSection(PVOID ObjectBody)
691 {
692 PSECTION_OBJECT Section = (PSECTION_OBJECT)ObjectBody;
693
694 DPRINT("MmpDeleteSection(ObjectBody %x)\n", ObjectBody);
695 if (Section->Flags & MM_IMAGE_SECTION)
696 {
697 ULONG i;
698
699 for (i = 0; i < Section->NrSegments; i++)
700 {
701 InterlockedDecrement(&Section->Segments[i].ReferenceCount);
702 }
703 }
704 else
705 {
706 InterlockedDecrement(&Section->Segments->ReferenceCount);
707 }
708 if (Section->FileObject != NULL)
709 {
710 ObDereferenceObject(Section->FileObject);
711 Section->FileObject = NULL;
712 }
713 }
714
715 VOID
716 MmpCloseSection(PVOID ObjectBody,
717 ULONG HandleCount)
718 {
719 DPRINT("MmpCloseSection(OB %x, HC %d) RC %d\n",
720 ObjectBody, HandleCount, ObGetReferenceCount(ObjectBody));
721
722 }
723
724 NTSTATUS MmpCreateSection(PVOID ObjectBody,
725 PVOID Parent,
726 PWSTR RemainingPath,
727 POBJECT_ATTRIBUTES ObjectAttributes)
728 {
729 NTSTATUS Status;
730
731 DPRINT("MmpCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
732 ObjectBody, Parent, RemainingPath);
733
734 if (RemainingPath == NULL)
735 {
736 return(STATUS_SUCCESS);
737 }
738
739 if (wcschr(RemainingPath+1, L'\\') != NULL)
740 {
741 return(STATUS_UNSUCCESSFUL);
742 }
743
744 Status = ObReferenceObjectByPointer(Parent,
745 STANDARD_RIGHTS_REQUIRED,
746 ObDirectoryType,
747 UserMode);
748 if (!NT_SUCCESS(Status))
749 {
750 return(Status);
751 }
752
753 ObAddEntryDirectory(Parent, ObjectBody, RemainingPath+1);
754 ObDereferenceObject(Parent);
755
756 return(STATUS_SUCCESS);
757 }
758
759 NTSTATUS
760 MmCreatePhysicalMemorySection(VOID)
761 {
762 HANDLE PhysSectionH;
763 PSECTION_OBJECT PhysSection;
764 NTSTATUS Status;
765 OBJECT_ATTRIBUTES Obj;
766 UNICODE_STRING Name;
767 LARGE_INTEGER SectionSize;
768
769 /*
770 * Create the section mapping physical memory
771 */
772 SectionSize.QuadPart = 0xFFFFFFFF;
773 RtlInitUnicodeString(&Name, L"\\Device\\PhysicalMemory");
774 InitializeObjectAttributes(&Obj,
775 &Name,
776 0,
777 NULL,
778 NULL);
779 Status = NtCreateSection(&PhysSectionH,
780 SECTION_ALL_ACCESS,
781 &Obj,
782 &SectionSize,
783 PAGE_EXECUTE_READWRITE,
784 0,
785 NULL);
786 if (!NT_SUCCESS(Status))
787 {
788 DbgPrint("Failed to create PhysicalMemory section\n");
789 KeBugCheck(0);
790 }
791 Status = ObReferenceObjectByHandle(PhysSectionH,
792 SECTION_ALL_ACCESS,
793 NULL,
794 KernelMode,
795 (PVOID*)&PhysSection,
796 NULL);
797 if (!NT_SUCCESS(Status))
798 {
799 DbgPrint("Failed to reference PhysicalMemory section\n");
800 KeBugCheck(0);
801 }
802 PhysSection->Flags = PhysSection->Flags | SO_PHYSICAL_MEMORY;
803 ObDereferenceObject((PVOID)PhysSection);
804
805 return(STATUS_SUCCESS);
806 }
807
808 NTSTATUS
809 MmInitSectionImplementation(VOID)
810 {
811 MmSectionObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
812
813 RtlInitUnicodeString(&MmSectionObjectType->TypeName, L"Section");
814
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;
832
833 return(STATUS_SUCCESS);
834 }
835
836 NTSTATUS
837 MmCreatePageFileSection(PHANDLE SectionHandle,
838 ACCESS_MASK DesiredAccess,
839 POBJECT_ATTRIBUTES ObjectAttributes,
840 PLARGE_INTEGER UMaximumSize,
841 ULONG SectionPageProtection,
842 ULONG AllocationAttributes)
843 /*
844 * Create a section which is backed by the pagefile
845 */
846 {
847 LARGE_INTEGER MaximumSize;
848 PSECTION_OBJECT Section;
849 PMM_SECTION_SEGMENT Segment;
850
851 if (UMaximumSize == NULL)
852 {
853 return(STATUS_UNSUCCESSFUL);
854 }
855 MaximumSize = *UMaximumSize;
856
857 /*
858 * Check the protection
859 */
860 if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
861 SectionPageProtection)
862 {
863 return(STATUS_INVALID_PAGE_PROTECTION);
864 }
865
866 /*
867 * Create the section
868 */
869 Section = ObCreateObject(SectionHandle,
870 DesiredAccess,
871 ObjectAttributes,
872 MmSectionObjectType);
873 if (Section == NULL)
874 {
875 return(STATUS_UNSUCCESSFUL);
876 }
877
878 /*
879 * Initialize it
880 */
881 Section->SectionPageProtection = SectionPageProtection;
882 Section->AllocateAttributes = AllocationAttributes;
883 InitializeListHead(&Section->ViewListHead);
884 KeInitializeSpinLock(&Section->ViewListLock);
885 KeInitializeMutex(&Section->Lock, 0);
886 Section->Flags = 0;
887 Section->FileObject = NULL;
888 Section->MaximumSize = MaximumSize;
889 Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
890 TAG_MM_SECTION_SEGMENT);
891 if (Segment == NULL)
892 {
893 ZwClose(*SectionHandle);
894 ObDereferenceObject(Section);
895 return(STATUS_NO_MEMORY);
896 }
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);
906 }
907
908
909 NTSTATUS
910 MmCreateDataFileSection(PHANDLE SectionHandle,
911 ACCESS_MASK DesiredAccess,
912 POBJECT_ATTRIBUTES ObjectAttributes,
913 PLARGE_INTEGER UMaximumSize,
914 ULONG SectionPageProtection,
915 ULONG AllocationAttributes,
916 HANDLE FileHandle)
917 /*
918 * Create a section backed by a data file
919 */
920 {
921 PSECTION_OBJECT Section;
922 NTSTATUS Status;
923 LARGE_INTEGER MaximumSize;
924 PFILE_OBJECT FileObject;
925 PMM_SECTION_SEGMENT Segment;
926 ULONG FileAccess;
927
928 /*
929 * Check the protection
930 */
931 if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
932 SectionPageProtection)
933 {
934 return(STATUS_INVALID_PAGE_PROTECTION);
935 }
936
937 /*
938 * Create the section
939 */
940 Section = ObCreateObject(SectionHandle,
941 DesiredAccess,
942 ObjectAttributes,
943 MmSectionObjectType);
944 if (Section == NULL)
945 {
946 return(STATUS_UNSUCCESSFUL);
947 }
948
949 /*
950 * Initialize it
951 */
952 Section->SectionPageProtection = SectionPageProtection;
953 Section->AllocateAttributes = AllocationAttributes;
954 InitializeListHead(&Section->ViewListHead);
955 KeInitializeSpinLock(&Section->ViewListLock);
956 KeInitializeMutex(&Section->Lock, 0);
957 Section->Flags = 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;
969
970 /*
971 * Check file access required
972 */
973 if (SectionPageProtection & PAGE_READWRITE ||
974 SectionPageProtection & PAGE_EXECUTE_READWRITE)
975 {
976 FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
977 }
978 else
979 {
980 FileAccess = FILE_READ_DATA;
981 }
982
983 /*
984 * Reference the file handle
985 */
986 Status = ObReferenceObjectByHandle(FileHandle,
987 FileAccess,
988 IoFileObjectType,
989 UserMode,
990 (PVOID*)&FileObject,
991 NULL);
992 if (!NT_SUCCESS(Status))
993 {
994 ZwClose(*SectionHandle);
995 ObDereferenceObject(Section);
996 return(Status);
997 }
998
999 /*
1000 * We can't do memory mappings if the file system doesn't support the
1001 * standard FCB
1002 */
1003 if (!(FileObject->Flags & FO_FCB_IS_VALID))
1004 {
1005 ZwClose(*SectionHandle);
1006 ObDereferenceObject(Section);
1007 ObDereferenceObject(FileObject);
1008 return(STATUS_INVALID_FILE_FOR_SECTION);
1009 }
1010
1011 /*
1012 * FIXME: Revise this once a locking order for file size changes is
1013 * decided
1014 */
1015 if (UMaximumSize != NULL)
1016 {
1017 MaximumSize = *UMaximumSize;
1018 }
1019 else
1020 {
1021 MaximumSize =
1022 ((PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize;
1023 }
1024
1025 /*
1026 * Lock the file
1027 */
1028 Status = KeWaitForSingleObject((PVOID)&FileObject->Lock,
1029 0,
1030 KernelMode,
1031 FALSE,
1032 NULL);
1033 if (Status != STATUS_SUCCESS)
1034 {
1035 ZwClose(*SectionHandle);
1036 ObDereferenceObject(Section);
1037 ObDereferenceObject(FileObject);
1038 return(Status);
1039 }
1040
1041 /*
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
1044 */
1045 if (FileObject->SectionObjectPointers->DataSectionObject == NULL)
1046 {
1047 Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT),
1048 TAG_MM_SECTION_SEGMENT);
1049 if (Segment == NULL)
1050 {
1051 KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
1052 ZwClose(*SectionHandle);
1053 ObDereferenceObject(Section);
1054 ObDereferenceObject(FileObject);
1055 return(STATUS_NO_MEMORY);
1056 }
1057 Section->Segments = Segment;
1058 Segment->ReferenceCount = 1;
1059 KeInitializeMutex(&Segment->Lock, 0);
1060
1061 /*
1062 * Set the lock before assigning the segment to the file object
1063 */
1064 Status = KeWaitForSingleObject((PVOID)&Segment->Lock,
1065 0,
1066 KernelMode,
1067 FALSE,
1068 NULL);
1069 if (Status != STATUS_SUCCESS)
1070 {
1071 KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
1072 ExFreePool(Segment);
1073 ZwClose(*SectionHandle);
1074 ObDereferenceObject(Section);
1075 ObDereferenceObject(FileObject);
1076 return(Status);
1077 }
1078 FileObject->SectionObjectPointers->DataSectionObject = (PVOID)Segment;
1079
1080 Segment->FileOffset = 0;
1081 Segment->Protection = 0;
1082 Segment->Attributes = 0;
1083 Segment->Flags = 0;
1084 Segment->Characteristics = 0;
1085 if (AllocationAttributes & SEC_RESERVE)
1086 {
1087 Segment->Length = 0;
1088 }
1089 else
1090 {
1091 Segment->Length = MaximumSize.u.LowPart;
1092 }
1093 Segment->VirtualAddress = NULL;
1094 }
1095 else
1096 {
1097 /*
1098 * If the file is already mapped as a data file then we may need
1099 * to extend it
1100 */
1101 Segment =
1102 (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers->
1103 DataSectionObject;
1104 Section->Segments = Segment;
1105 InterlockedIncrement((PLONG)&Segment->ReferenceCount);
1106 Status = KeWaitForSingleObject((PVOID)&Section->Lock,
1107 0,
1108 KernelMode,
1109 FALSE,
1110 NULL);
1111 if (Status != STATUS_SUCCESS)
1112 {
1113 InterlockedDecrement((PLONG)&Segment->ReferenceCount);
1114 KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
1115 ZwClose(*SectionHandle);
1116 ObDereferenceObject(Section);
1117 ObDereferenceObject(FileObject);
1118 return(Status);
1119 }
1120 if (MaximumSize.u.LowPart > Segment->Length &&
1121 !(AllocationAttributes & SEC_RESERVE))
1122 {
1123 Segment->Length = MaximumSize.u.LowPart;
1124 }
1125 }
1126 KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
1127 Section->FileObject = FileObject;
1128 KeReleaseMutex(&Segment->Lock, FALSE);
1129
1130 ObDereferenceObject(Section);
1131 return(STATUS_SUCCESS);
1132 }
1133
1134 NTSTATUS
1135 MmCreateImageSection(PHANDLE SectionHandle,
1136 ACCESS_MASK DesiredAccess,
1137 POBJECT_ATTRIBUTES ObjectAttributes,
1138 PLARGE_INTEGER UMaximumSize,
1139 ULONG SectionPageProtection,
1140 ULONG AllocationAttributes,
1141 HANDLE FileHandle)
1142 {
1143 PSECTION_OBJECT Section;
1144 NTSTATUS Status;
1145 PFILE_OBJECT FileObject;
1146 ULONG FileAccess;
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;
1153 ULONG NrSegments;
1154 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
1155
1156 /*
1157 * Check the protection
1158 */
1159 if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) !=
1160 SectionPageProtection)
1161 {
1162 return(STATUS_INVALID_PAGE_PROTECTION);
1163 }
1164
1165 /*
1166 * Specifying a maximum size is meaningless for an image section
1167 */
1168 if (UMaximumSize != NULL)
1169 {
1170 return(STATUS_INVALID_PARAMETER_4);
1171 }
1172
1173 /*
1174 * Read the dos header
1175 */
1176 Offset.QuadPart = 0;
1177 Status = ZwReadFile(FileHandle,
1178 NULL,
1179 NULL,
1180 NULL,
1181 &Iosb,
1182 &DosHeader,
1183 sizeof(DosHeader),
1184 &Offset,
1185 0);
1186 if (!NT_SUCCESS(Status))
1187 {
1188 return(Status);
1189 }
1190 if (Iosb.Information != sizeof(DosHeader))
1191 {
1192 return(STATUS_INVALID_IMAGE_FORMAT);
1193 }
1194
1195 /*
1196 * Check the DOS signature
1197 */
1198 if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
1199 {
1200 return(STATUS_INVALID_IMAGE_FORMAT);
1201 }
1202
1203 /*
1204 * Read the PE header
1205 */
1206 Offset.QuadPart = DosHeader.e_lfanew;
1207 Status = ZwReadFile(FileHandle,
1208 NULL,
1209 NULL,
1210 NULL,
1211 &Iosb,
1212 &PEHeader,
1213 sizeof(PEHeader),
1214 &Offset,
1215 0);
1216 if (!NT_SUCCESS(Status))
1217 {
1218 return(Status);
1219 }
1220 if (Iosb.Information != sizeof(PEHeader))
1221 {
1222 return(STATUS_INVALID_IMAGE_FORMAT);
1223 }
1224
1225 /*
1226 * Check the signature
1227 */
1228 if (PEHeader.Signature != IMAGE_NT_SIGNATURE)
1229 {
1230 return(STATUS_INVALID_IMAGE_FORMAT);
1231 }
1232
1233 /*
1234 * Read in the section headers
1235 */
1236 Offset.QuadPart = DosHeader.e_lfanew + sizeof(PEHeader);
1237 ImageSections =
1238 ExAllocatePool(NonPagedPool,
1239 PEHeader.FileHeader.NumberOfSections *
1240 sizeof(IMAGE_SECTION_HEADER));
1241 Status = ZwReadFile(FileHandle,
1242 NULL,
1243 NULL,
1244 NULL,
1245 &Iosb,
1246 ImageSections,
1247 PEHeader.FileHeader.NumberOfSections *
1248 sizeof(IMAGE_SECTION_HEADER),
1249 &Offset,
1250 0);
1251 if (!NT_SUCCESS(Status))
1252 {
1253 ExFreePool(ImageSections);
1254 return(Status);
1255 }
1256 if (Iosb.Information !=
1257 (PEHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)))
1258 {
1259 ExFreePool(ImageSections);
1260 return(STATUS_INVALID_IMAGE_FORMAT);
1261 }
1262
1263 /*
1264 * Create the section
1265 */
1266 Section = ObCreateObject(SectionHandle,
1267 DesiredAccess,
1268 ObjectAttributes,
1269 MmSectionObjectType);
1270 if (Section == NULL)
1271 {
1272 ExFreePool(ImageSections);
1273 return(STATUS_UNSUCCESSFUL);
1274 }
1275
1276 /*
1277 * Initialize it
1278 */
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);
1298
1299 /*
1300 * Check file access required
1301 */
1302 if (SectionPageProtection & PAGE_READWRITE ||
1303 SectionPageProtection & PAGE_EXECUTE_READWRITE)
1304 {
1305 FileAccess = FILE_READ_DATA | FILE_WRITE_DATA;
1306 }
1307 else
1308 {
1309 FileAccess = FILE_READ_DATA;
1310 }
1311
1312 /*
1313 * Reference the file handle
1314 */
1315 Status = ObReferenceObjectByHandle(FileHandle,
1316 FileAccess,
1317 IoFileObjectType,
1318 UserMode,
1319 (PVOID*)&FileObject,
1320 NULL);
1321 if (!NT_SUCCESS(Status))
1322 {
1323 ZwClose(*SectionHandle);
1324 ObDereferenceObject(Section);
1325 ExFreePool(ImageSections);
1326 return(Status);
1327 }
1328
1329 /*
1330 * We can't do memory mappings if the file system doesn't support the
1331 * standard FCB
1332 */
1333 if (!(FileObject->Flags & FO_FCB_IS_VALID))
1334 {
1335 ZwClose(*SectionHandle);
1336 ObDereferenceObject(Section);
1337 ObDereferenceObject(FileObject);
1338 ExFreePool(ImageSections);
1339 return(STATUS_INVALID_FILE_FOR_SECTION);
1340 }
1341
1342 /*
1343 * Lock the file
1344 */
1345 Status = KeWaitForSingleObject((PVOID)&FileObject->Lock,
1346 0,
1347 KernelMode,
1348 FALSE,
1349 NULL);
1350 if (Status != STATUS_SUCCESS)
1351 {
1352 ZwClose(*SectionHandle);
1353 ObDereferenceObject(Section);
1354 ObDereferenceObject(FileObject);
1355 ExFreePool(ImageSections);
1356 return(Status);
1357 }
1358
1359 /*
1360 * If this file hasn't been mapped as a image file before then allocate the
1361 * section segments to describe the mapping
1362 */
1363 NrSegments = PEHeader.FileHeader.NumberOfSections + 1;
1364 if (FileObject->SectionObjectPointers->ImageSectionObject == NULL)
1365 {
1366 ULONG i;
1367 ULONG Size;
1368
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)
1374 {
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);
1381 }
1382 ImageSectionObject->NrSegments = NrSegments;
1383 SectionSegments = ImageSectionObject->Segments;
1384 Section->Segments = SectionSegments;
1385
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);
1395
1396 for (i = 1; i < NrSegments; i++)
1397 {
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)
1403 {
1404 SectionSegments[i].Protection = PAGE_EXECUTE_READ;
1405 SectionSegments[i].Attributes = 0;
1406 }
1407 else if (ImageSections[i-1].Characteristics &
1408 IMAGE_SECTION_CHAR_DATA)
1409 {
1410 SectionSegments[i].Protection = PAGE_READWRITE;
1411 SectionSegments[i].Attributes = 0;
1412 }
1413 else if (ImageSections[i-1].Characteristics & IMAGE_SECTION_CHAR_BSS)
1414 {
1415 SectionSegments[i].Protection = PAGE_READWRITE;
1416 SectionSegments[i].Attributes = MM_SECTION_SEGMENT_BSS;
1417 }
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);
1426 }
1427
1428 FileObject->SectionObjectPointers->ImageSectionObject =
1429 (PVOID)ImageSectionObject;
1430 ExFreePool(ImageSections);
1431 }
1432 else
1433 {
1434 ULONG i;
1435
1436 ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)
1437 FileObject->SectionObjectPointers->ImageSectionObject;
1438 SectionSegments = ImageSectionObject->Segments;
1439 Section->Segments = SectionSegments;
1440
1441 /*
1442 * Otherwise just reference all the section segments
1443 */
1444 for (i = 0; i < NrSegments; i++)
1445 {
1446 InterlockedIncrement(&SectionSegments[i].ReferenceCount);
1447 }
1448
1449 }
1450 KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
1451 Section->FileObject = FileObject;
1452
1453 ObDereferenceObject(Section);
1454 return(STATUS_SUCCESS);
1455 }
1456
1457 NTSTATUS STDCALL
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)
1465 {
1466 if (AllocationAttributes & SEC_IMAGE)
1467 {
1468 return(MmCreateImageSection(SectionHandle,
1469 DesiredAccess,
1470 ObjectAttributes,
1471 MaximumSize,
1472 SectionPageProtection,
1473 AllocationAttributes,
1474 FileHandle));
1475 }
1476 else if (FileHandle != NULL)
1477 {
1478 return(MmCreateDataFileSection(SectionHandle,
1479 DesiredAccess,
1480 ObjectAttributes,
1481 MaximumSize,
1482 SectionPageProtection,
1483 AllocationAttributes,
1484 FileHandle));
1485 }
1486 else
1487 {
1488 return(MmCreatePageFileSection(SectionHandle,
1489 DesiredAccess,
1490 ObjectAttributes,
1491 MaximumSize,
1492 SectionPageProtection,
1493 AllocationAttributes));
1494 }
1495 }
1496
1497
1498 /**********************************************************************
1499 * NAME
1500 * NtOpenSection
1501 *
1502 * DESCRIPTION
1503 *
1504 * ARGUMENTS
1505 * SectionHandle
1506 *
1507 * DesiredAccess
1508 *
1509 * ObjectAttributes
1510 *
1511 * RETURN VALUE
1512 *
1513 * REVISIONS
1514 *
1515 */
1516 NTSTATUS STDCALL
1517 NtOpenSection(PHANDLE SectionHandle,
1518 ACCESS_MASK DesiredAccess,
1519 POBJECT_ATTRIBUTES ObjectAttributes)
1520 {
1521 NTSTATUS Status;
1522
1523 *SectionHandle = 0;
1524
1525 Status = ObOpenObjectByName(ObjectAttributes,
1526 MmSectionObjectType,
1527 NULL,
1528 UserMode,
1529 DesiredAccess,
1530 NULL,
1531 SectionHandle);
1532
1533 return(Status);
1534 }
1535
1536 NTSTATUS
1537 MmMapViewOfSegment(PEPROCESS Process,
1538 PMADDRESS_SPACE AddressSpace,
1539 PSECTION_OBJECT Section,
1540 PMM_SECTION_SEGMENT Segment,
1541 PVOID* BaseAddress,
1542 ULONG ViewSize,
1543 ULONG Protect,
1544 ULONG ViewOffset)
1545 {
1546 PMEMORY_AREA MArea;
1547 NTSTATUS Status;
1548 KIRQL oldIrql;
1549
1550 Status = MmCreateMemoryArea(Process,
1551 &Process->AddressSpace,
1552 MEMORY_AREA_SECTION_VIEW_COMMIT,
1553 BaseAddress,
1554 ViewSize,
1555 Protect,
1556 &MArea,
1557 FALSE);
1558 if (!NT_SUCCESS(Status))
1559 {
1560 MmUnlockAddressSpace(AddressSpace);
1561 return(Status);
1562 }
1563
1564 KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
1565 InsertTailList(&Section->ViewListHead,
1566 &MArea->Data.SectionData.ViewListEntry);
1567 KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
1568
1569 ObReferenceObjectByPointer((PVOID)Section,
1570 SECTION_MAP_READ,
1571 NULL,
1572 ExGetPreviousMode());
1573 MArea->Data.SectionData.Segment = Segment;
1574 MArea->Data.SectionData.Section = Section;
1575 MArea->Data.SectionData.ViewOffset = ViewOffset;
1576
1577 return(STATUS_SUCCESS);
1578 }
1579
1580
1581 /**********************************************************************
1582 * NAME EXPORTED
1583 * NtMapViewOfSection
1584 *
1585 * DESCRIPTION
1586 * Maps a view of a section into the virtual address space of a
1587 * process.
1588 *
1589 * ARGUMENTS
1590 * SectionHandle
1591 * Handle of the section.
1592 *
1593 * ProcessHandle
1594 * Handle of the process.
1595 *
1596 * BaseAddress
1597 * Desired base address (or NULL) on entry;
1598 * Actual base address of the view on exit.
1599 *
1600 * ZeroBits
1601 * Number of high order address bits that must be zero.
1602 *
1603 * CommitSize
1604 * Size in bytes of the initially committed section of
1605 * the view.
1606 *
1607 * SectionOffset
1608 * Offset in bytes from the beginning of the section
1609 * to the beginning of the view.
1610 *
1611 * ViewSize
1612 * Desired length of map (or zero to map all) on entry
1613 * Actual length mapped on exit.
1614 *
1615 * InheritDisposition
1616 * Specified how the view is to be shared with
1617 * child processes.
1618 *
1619 * AllocateType
1620 * Type of allocation for the pages.
1621 *
1622 * Protect
1623 * Protection for the committed region of the view.
1624 *
1625 * RETURN VALUE
1626 * Status.
1627 */
1628 NTSTATUS STDCALL
1629 NtMapViewOfSection(HANDLE SectionHandle,
1630 HANDLE ProcessHandle,
1631 PVOID* BaseAddress,
1632 ULONG ZeroBits,
1633 ULONG CommitSize,
1634 PLARGE_INTEGER SectionOffset,
1635 PULONG ViewSize,
1636 SECTION_INHERIT InheritDisposition,
1637 ULONG AllocationType,
1638 ULONG Protect)
1639 {
1640 PSECTION_OBJECT Section;
1641 PEPROCESS Process;
1642 NTSTATUS Status;
1643 ULONG ViewOffset;
1644 PMADDRESS_SPACE AddressSpace;
1645
1646 Status = ObReferenceObjectByHandle(ProcessHandle,
1647 PROCESS_VM_OPERATION,
1648 PsProcessType,
1649 UserMode,
1650 (PVOID*)&Process,
1651 NULL);
1652 if (!NT_SUCCESS(Status))
1653 {
1654 return(Status);
1655 }
1656
1657 AddressSpace = &Process->AddressSpace;
1658
1659 Status = ObReferenceObjectByHandle(SectionHandle,
1660 SECTION_MAP_READ,
1661 MmSectionObjectType,
1662 UserMode,
1663 (PVOID*)&Section,
1664 NULL);
1665 if (!(NT_SUCCESS(Status)))
1666 {
1667 DPRINT("ObReference failed rc=%x\n",Status);
1668 ObDereferenceObject(Process);
1669 return(Status);
1670 }
1671
1672 MmLockAddressSpace(AddressSpace);
1673 MmLockSection(Section);
1674
1675 if (Section->Flags & MM_IMAGE_SECTION)
1676 {
1677 ULONG i;
1678
1679 for (i = 0; i < Section->NrSegments; i++)
1680 {
1681 PVOID SBaseAddress;
1682
1683 SBaseAddress = (PVOID)
1684 ((ULONG)Section->ImageBase +
1685 (ULONG)Section->Segments[i].VirtualAddress);
1686
1687 MmLockSectionSegment(&Section->Segments[i]);
1688 Status = MmMapViewOfSegment(Process,
1689 &Process->AddressSpace,
1690 Section,
1691 &Section->Segments[i],
1692 &SBaseAddress,
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))
1698 {
1699 MmUnlockSection(Section);
1700 MmUnlockAddressSpace(AddressSpace);
1701 ObDereferenceObject(Section);
1702 ObDereferenceObject(Process);
1703 return(Status);
1704 }
1705 }
1706 *BaseAddress = Section->ImageBase;
1707 }
1708 else
1709 {
1710 if (SectionOffset == NULL)
1711 {
1712 ViewOffset = 0;
1713 }
1714 else
1715 {
1716 ViewOffset = SectionOffset->u.LowPart;
1717 }
1718
1719 if ((ViewOffset % PAGESIZE) != 0)
1720 {
1721 MmUnlockSection(Section);
1722 MmUnlockAddressSpace(AddressSpace);
1723 ObDereferenceObject(Section);
1724 ObDereferenceObject(Process);
1725 return(STATUS_MAPPED_ALIGNMENT);
1726 }
1727
1728 if (((*ViewSize)+ViewOffset) > Section->MaximumSize.u.LowPart)
1729 {
1730 (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
1731 }
1732
1733 MmLockSectionSegment(Section->Segments);
1734 Status = MmMapViewOfSegment(Process,
1735 &Process->AddressSpace,
1736 Section,
1737 Section->Segments,
1738 BaseAddress,
1739 *ViewSize,
1740 Protect,
1741 ViewOffset);
1742 MmUnlockSectionSegment(Section->Segments);
1743 if (!NT_SUCCESS(Status))
1744 {
1745 MmUnlockSection(Section);
1746 MmUnlockAddressSpace(AddressSpace);
1747 ObDereferenceObject(Section);
1748 ObDereferenceObject(Process);
1749 return(Status);
1750 }
1751 }
1752
1753 MmUnlockSection(Section);
1754 MmUnlockAddressSpace(AddressSpace);
1755 ObDereferenceObject(Section);
1756 ObDereferenceObject(Process);
1757
1758 return(STATUS_SUCCESS);
1759 }
1760
1761 VOID STATIC
1762 MmFreeSectionPage(PVOID Context, PVOID Address, ULONG PhysAddr)
1763 {
1764 PMEMORY_AREA MArea;
1765 ULONG Entry;
1766
1767 MArea = (PMEMORY_AREA)Context;
1768
1769 if (PhysAddr != 0)
1770 {
1771 ULONG Offset;
1772
1773 Offset =
1774 ((ULONG)PAGE_ROUND_DOWN(Address) - (ULONG)MArea->BaseAddress) +
1775 MArea->Data.SectionData.ViewOffset;
1776
1777 Entry = MmGetPageEntrySectionSegment(MArea->Data.SectionData.Segment,
1778 Offset);
1779 /*
1780 * Just dereference private pages
1781 */
1782 if (PhysAddr != (Entry & 0xFFFFF000))
1783 {
1784 MmDereferencePage((PVOID)PhysAddr);
1785 }
1786 else
1787 {
1788 #if 0
1789 MmUnsharePageEntrySectionSegment(MArea->Data.SectionData.Segment,
1790 Offset);
1791 MmDereferencePage((PVOID)PhysAddr);
1792 #endif
1793 }
1794 }
1795 }
1796
1797 NTSTATUS STDCALL
1798 MmUnmapViewOfSection(PEPROCESS Process,
1799 PVOID BaseAddress)
1800 {
1801 NTSTATUS Status;
1802 PMEMORY_AREA MemoryArea;
1803 PMADDRESS_SPACE AddressSpace;
1804 PSECTION_OBJECT Section;
1805 PMM_SECTION_SEGMENT Segment;
1806 KIRQL oldIrql;
1807
1808 AddressSpace = &Process->AddressSpace;
1809
1810 DPRINT("Opening memory area Process %x BaseAddress %x\n",
1811 Process, BaseAddress);
1812 MmLockAddressSpace(AddressSpace);
1813 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
1814 BaseAddress);
1815 if (MemoryArea == NULL)
1816 {
1817 MmUnlockAddressSpace(AddressSpace);
1818 return(STATUS_UNSUCCESSFUL);
1819 }
1820
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)
1829 {
1830 Status = MmFreeMemoryArea(&Process->AddressSpace,
1831 BaseAddress,
1832 0,
1833 NULL,
1834 NULL);
1835 }
1836 else
1837 {
1838 Status = MmFreeMemoryArea(&Process->AddressSpace,
1839 BaseAddress,
1840 0,
1841 MmFreeSectionPage,
1842 MemoryArea);
1843 }
1844 MmUnlockSection(Section);
1845 MmUnlockSectionSegment(Segment);
1846 ObDereferenceObject(Section);
1847 MmUnlockAddressSpace(AddressSpace);
1848 return(STATUS_SUCCESS);
1849 }
1850
1851 /**********************************************************************
1852 * NAME EXPORTED
1853 * NtUnmapViewOfSection
1854 *
1855 * DESCRIPTION
1856 *
1857 * ARGUMENTS
1858 * ProcessHandle
1859 *
1860 * BaseAddress
1861 *
1862 * RETURN VALUE
1863 * Status.
1864 *
1865 * REVISIONS
1866 *
1867 */
1868 NTSTATUS STDCALL
1869 NtUnmapViewOfSection (HANDLE ProcessHandle,
1870 PVOID BaseAddress)
1871 {
1872 PEPROCESS Process;
1873 NTSTATUS Status;
1874
1875 DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n",
1876 ProcessHandle, BaseAddress);
1877
1878 DPRINT("Referencing process\n");
1879 Status = ObReferenceObjectByHandle(ProcessHandle,
1880 PROCESS_VM_OPERATION,
1881 PsProcessType,
1882 UserMode,
1883 (PVOID*)&Process,
1884 NULL);
1885 if (!NT_SUCCESS(Status))
1886 {
1887 DPRINT("ObReferenceObjectByHandle failed (Status %x)\n", Status);
1888 return(Status);
1889 }
1890
1891 Status = MmUnmapViewOfSection(Process, BaseAddress);
1892
1893 ObDereferenceObject(Process);
1894
1895 return Status;
1896 }
1897
1898
1899 NTSTATUS STDCALL
1900 NtQuerySection (IN HANDLE SectionHandle,
1901 IN CINT SectionInformationClass,
1902 OUT PVOID SectionInformation,
1903 IN ULONG Length,
1904 OUT PULONG ResultLength)
1905 /*
1906 * FUNCTION: Queries the information of a section object.
1907 * ARGUMENTS:
1908 * SectionHandle = Handle to the section link object
1909 * SectionInformationClass = Index to a certain information structure
1910 * SectionInformation (OUT)= Caller supplies storage for resulting
1911 * information
1912 * Length = Size of the supplied storage
1913 * ResultLength = Data written
1914 * RETURNS: Status
1915 *
1916 */
1917 {
1918 PSECTION_OBJECT Section;
1919 NTSTATUS Status;
1920
1921 Status = ObReferenceObjectByHandle(SectionHandle,
1922 SECTION_MAP_READ,
1923 MmSectionObjectType,
1924 UserMode,
1925 (PVOID*)&Section,
1926 NULL);
1927 if (!(NT_SUCCESS(Status)))
1928 {
1929 return(Status);
1930 }
1931
1932 switch (SectionInformationClass)
1933 {
1934 case SectionBasicInformation:
1935 {
1936 PSECTION_BASIC_INFORMATION Sbi;
1937
1938 if (Length != sizeof(SECTION_BASIC_INFORMATION))
1939 {
1940 ObDereferenceObject(Section);
1941 return(STATUS_INFO_LENGTH_MISMATCH);
1942 }
1943
1944 Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
1945
1946 Sbi->BaseAddress = 0;
1947 Sbi->Attributes = 0;
1948 Sbi->Size.QuadPart = 0;
1949
1950 Status = STATUS_SUCCESS;
1951
1952 break;
1953 }
1954
1955 case SectionImageInformation:
1956 {
1957 PSECTION_IMAGE_INFORMATION Sii;
1958
1959 if (Length != sizeof(SECTION_IMAGE_INFORMATION))
1960 {
1961 ObDereferenceObject(Section);
1962 return(STATUS_INFO_LENGTH_MISMATCH);
1963 }
1964
1965 Sii->EntryPoint = Section->EntryPoint;
1966 Sii->Unknown1 = 0;
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;
1972 Sii->Unknown2 = 0;
1973 Sii->Characteristics = Section->ImageCharacteristics;
1974 Sii->ImageNumber = Section->Machine;
1975 Sii->Executable = Section->Executable;
1976 Sii->Unknown3 = 0;
1977 Sii->Unknown4[0] = 0;
1978 Sii->Unknown4[1] = 0;
1979 Sii->Unknown4[2] = 0;
1980
1981 Status = STATUS_SUCCESS;
1982 break;
1983 }
1984
1985 default:
1986 Status = STATUS_INVALID_INFO_CLASS;
1987 }
1988 ObDereferenceObject(Section);
1989 return(Status);
1990 }
1991
1992
1993 NTSTATUS STDCALL
1994 NtExtendSection(IN HANDLE SectionHandle,
1995 IN ULONG NewMaximumSize)
1996 {
1997 UNIMPLEMENTED;
1998 }
1999
2000
2001 /**********************************************************************
2002 * NAME INTERNAL
2003 * MmAllocateSection@4
2004 *
2005 * DESCRIPTION
2006 *
2007 * ARGUMENTS
2008 * Length
2009 *
2010 * RETURN VALUE
2011 *
2012 * NOTE
2013 * Code taken from ntoskrnl/mm/special.c.
2014 *
2015 * REVISIONS
2016 *
2017 */
2018 PVOID STDCALL
2019 MmAllocateSection (IN ULONG Length)
2020 {
2021 PVOID Result;
2022 MEMORY_AREA* marea;
2023 NTSTATUS Status;
2024 ULONG i;
2025 PMADDRESS_SPACE AddressSpace;
2026
2027 DPRINT("MmAllocateSection(Length %x)\n",Length);
2028
2029 AddressSpace = MmGetKernelAddressSpace();
2030 Result = NULL;
2031 MmLockAddressSpace(AddressSpace);
2032 Status = MmCreateMemoryArea (NULL,
2033 AddressSpace,
2034 MEMORY_AREA_SYSTEM,
2035 &Result,
2036 Length,
2037 0,
2038 &marea,
2039 FALSE);
2040 if (!NT_SUCCESS(STATUS_SUCCESS))
2041 {
2042 return (NULL);
2043 }
2044 DPRINT("Result %p\n",Result);
2045 for (i = 0; (i <= (Length / PAGESIZE)); i++)
2046 {
2047 Status = MmCreateVirtualMapping (NULL,
2048 (Result + (i * PAGESIZE)),
2049 PAGE_READWRITE,
2050 (ULONG)MmAllocPage(0));
2051 if (!NT_SUCCESS(Status))
2052 {
2053 DbgPrint("Unable to create virtual mapping\n");
2054 KeBugCheck(0);
2055 }
2056 }
2057 MmUnlockAddressSpace(AddressSpace);
2058 return ((PVOID)Result);
2059 }
2060
2061
2062 /**********************************************************************
2063 * NAME EXPORTED
2064 * MmMapViewOfSection@40
2065 *
2066 * DESCRIPTION
2067 *
2068 * ARGUMENTS
2069 * FIXME: stack space allocated is 40 bytes, but nothing
2070 * is known about what they are filled with.
2071 *
2072 * RETURN VALUE
2073 * Status.
2074 *
2075 */
2076 PVOID STDCALL
2077 MmMapViewOfSection (DWORD Unknown0,
2078 DWORD Unknown1,
2079 DWORD Unknown2,
2080 DWORD Unknown3,
2081 DWORD Unknown4,
2082 DWORD Unknown5,
2083 DWORD Unknown6,
2084 DWORD Unknown7,
2085 DWORD Unknown8,
2086 DWORD Unknown9)
2087 {
2088 UNIMPLEMENTED;
2089 return (NULL);
2090 }
2091
2092
2093 BOOLEAN STDCALL
2094 MmCanFileBeTruncated (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
2095 IN PLARGE_INTEGER NewFileSize)
2096 {
2097 UNIMPLEMENTED;
2098 return (FALSE);
2099 }
2100
2101
2102 BOOLEAN STDCALL
2103 MmDisableModifiedWriteOfSection (DWORD Unknown0)
2104 {
2105 UNIMPLEMENTED;
2106 return (FALSE);
2107 }
2108
2109 BOOLEAN STDCALL
2110 MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
2111 IN MMFLUSH_TYPE FlushType)
2112 {
2113 UNIMPLEMENTED;
2114 return (FALSE);
2115 }
2116
2117 BOOLEAN STDCALL
2118 MmForceSectionClosed (DWORD Unknown0,
2119 DWORD Unknown1)
2120 {
2121 UNIMPLEMENTED;
2122 return (FALSE);
2123 }
2124
2125
2126 NTSTATUS STDCALL
2127 MmMapViewInSystemSpace (IN PVOID Section,
2128 OUT PVOID * MappedBase,
2129 IN PULONG ViewSize)
2130 {
2131 UNIMPLEMENTED;
2132 return (STATUS_NOT_IMPLEMENTED);
2133 }
2134
2135 NTSTATUS STDCALL
2136 MmUnmapViewInSystemSpace (DWORD Unknown0)
2137 {
2138 UNIMPLEMENTED;
2139 return (STATUS_NOT_IMPLEMENTED);
2140 }
2141
2142
2143 NTSTATUS STDCALL
2144 MmSetBankedSection (DWORD Unknown0,
2145 DWORD Unknown1,
2146 DWORD Unknown2,
2147 DWORD Unknown3,
2148 DWORD Unknown4,
2149 DWORD Unknown5)
2150 {
2151 UNIMPLEMENTED;
2152 return (STATUS_NOT_IMPLEMENTED);
2153 }
2154
2155
2156 /**********************************************************************
2157 * NAME EXPORTED
2158 * MmCreateSection@
2159 *
2160 * DESCRIPTION
2161 * Creates a section object.
2162 *
2163 * ARGUMENTS
2164 * SectionObjiect (OUT)
2165 * Caller supplied storage for the resulting pointer
2166 * to a SECTION_BOJECT instance;
2167 *
2168 * DesiredAccess
2169 * Specifies the desired access to the section can be a
2170 * combination of:
2171 * STANDARD_RIGHTS_REQUIRED |
2172 * SECTION_QUERY |
2173 * SECTION_MAP_WRITE |
2174 * SECTION_MAP_READ |
2175 * SECTION_MAP_EXECUTE
2176 *
2177 * ObjectAttributes [OPTIONAL]
2178 * Initialized attributes for the object can be used
2179 * to create a named section;
2180 *
2181 * MaximumSize
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.
2186 *
2187 * SectionPageProtection
2188 * Can be a combination of:
2189 * PAGE_READONLY |
2190 * PAGE_READWRITE |
2191 * PAGE_WRITEONLY |
2192 * PAGE_WRITECOPY
2193 *
2194 * AllocationAttributes
2195 * Can be a combination of:
2196 * SEC_IMAGE |
2197 * SEC_RESERVE
2198 *
2199 * FileHandle
2200 * Handle to a file to create a section mapped to a file
2201 * instead of a memory backed section;
2202 *
2203 * File
2204 * Unknown.
2205 *
2206 * RETURN VALUE
2207 * Status.
2208 */
2209 NTSTATUS STDCALL
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)
2218 {
2219 return (STATUS_NOT_IMPLEMENTED);
2220 }
2221
2222 /* EOF */
2223
2224
2225
2226
2227
2228