e720011440319fdc30fa48ea4792c1ce9dce8123
[reactos.git] / reactos / ntoskrnl / mm / section.c
1 /* $Id: section.c,v 1.39 2000/10/22 16:36:52 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/section.c
6 * PURPOSE: Implements section objects
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <limits.h>
15 #include <ddk/ntddk.h>
16 #include <internal/mm.h>
17 #include <internal/ob.h>
18 #include <internal/io.h>
19 #include <internal/ps.h>
20
21 #define NDEBUG
22 #include <internal/debug.h>
23
24 /* GLOBALS *******************************************************************/
25
26 POBJECT_TYPE EXPORTED MmSectionObjectType = NULL;
27
28 /* FUNCTIONS *****************************************************************/
29
30 NTSTATUS MmWritePageSectionView(PMADDRESS_SPACE AddressSpace,
31 PMEMORY_AREA MArea,
32 PVOID Address)
33 {
34 return(STATUS_UNSUCCESSFUL);
35 }
36
37 VOID MmLockSection(PSECTION_OBJECT Section)
38 {
39 KeWaitForSingleObject(&Section->Lock,
40 UserRequest,
41 KernelMode,
42 FALSE,
43 NULL);
44 }
45
46 VOID MmUnlockSection(PSECTION_OBJECT Section)
47 {
48 KeReleaseMutex(&Section->Lock, FALSE);
49 }
50
51 VOID MmSetPageEntrySection(PSECTION_OBJECT Section,
52 ULONG Offset,
53 ULONG Entry)
54 {
55 PSECTION_PAGE_TABLE Table;
56 ULONG DirectoryOffset;
57 ULONG TableOffset;
58
59 DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
60 Table = Section->PageDirectory.PageTables[DirectoryOffset];
61 if (Table == NULL)
62 {
63 Table =
64 Section->PageDirectory.PageTables[DirectoryOffset] =
65 ExAllocatePool(NonPagedPool, sizeof(SECTION_PAGE_TABLE));
66 memset(Table, 0, sizeof(SECTION_PAGE_TABLE));
67 DPRINT("Table %x\n", Table);
68 }
69 TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
70 Table->Pages[TableOffset] = Entry;
71 }
72
73 ULONG MmGetPageEntrySection(PSECTION_OBJECT Section,
74 ULONG Offset)
75 {
76 PSECTION_PAGE_TABLE Table;
77 ULONG Entry;
78 ULONG DirectoryOffset;
79 ULONG TableOffset;
80
81 DPRINT("MmGetPageEntrySection(Offset %x)\n", Offset);
82
83 DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset);
84 Table = Section->PageDirectory.PageTables[DirectoryOffset];
85 DPRINT("Table %x\n", Table);
86 if (Table == NULL)
87 {
88 return(0);
89 }
90 TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
91 Entry = Table->Pages[TableOffset];
92 return(Entry);
93 }
94
95 NTSTATUS MmUnalignedLoadPageForSection(PMADDRESS_SPACE AddressSpace,
96 MEMORY_AREA* MemoryArea,
97 PVOID Address)
98 {
99 LARGE_INTEGER Offset;
100 IO_STATUS_BLOCK IoStatus;
101 PMDL Mdl;
102 PVOID Page;
103 NTSTATUS Status;
104 ULONG PAddress;
105 PSECTION_OBJECT Section;
106
107 DPRINT("MmOldLoadPageForSection(MemoryArea %x, Address %x)\n",
108 MemoryArea,Address);
109
110 if (MmIsPagePresent(NULL, Address))
111 {
112 DPRINT("Page is already present\n");
113 return(STATUS_SUCCESS);
114 }
115
116 PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
117 Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
118 MemoryArea->Data.SectionData.ViewOffset;
119
120 DPRINT("MemoryArea->BaseAddress %x\n", MemoryArea->BaseAddress);
121 DPRINT("MemoryArea->Data.SectionData.ViewOffset %x\n",
122 MemoryArea->Data.SectionData.ViewOffset);
123 DPRINT("Got offset %x\n", Offset.QuadPart);
124
125 Section = MemoryArea->Data.SectionData.Section;
126
127 DPRINT("Section %x\n", Section);
128
129 MmLockSection(Section);
130
131 Page = MmAllocPageMaybeSwap(0);
132 Mdl = MmCreateMdl(NULL, NULL, PAGESIZE);
133 MmBuildMdlFromPages(Mdl, (PULONG)&Page);
134 MmUnlockSection(Section);
135 MmUnlockAddressSpace(AddressSpace);
136 DPRINT("Reading file offset %x\n", Offset.QuadPart);
137 Status = IoPageRead(MemoryArea->Data.SectionData.Section->FileObject,
138 Mdl,
139 &Offset,
140 &IoStatus);
141 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
142 {
143 MmLockAddressSpace(AddressSpace);
144 return(Status);
145 }
146
147 MmLockAddressSpace(AddressSpace);
148 MmLockSection(Section);
149
150 Status = MmCreateVirtualMapping(NULL,
151 Address,
152 MemoryArea->Attributes,
153 (ULONG)Page);
154 if (!NT_SUCCESS(Status))
155 {
156 DbgPrint("Unable to create virtual mapping\n");
157 KeBugCheck(0);
158 }
159 MmUnlockSection(Section);
160
161 return(STATUS_SUCCESS);
162
163 }
164
165 NTSTATUS MmWaitForPendingOperationSection(PMADDRESS_SPACE AddressSpace,
166 PMEMORY_AREA MemoryArea,
167 PVOID Address,
168 PSECTION_OBJECT Section,
169 LARGE_INTEGER Offset,
170 ULONG Entry)
171 {
172 PVOID Page;
173 NTSTATUS Status;
174
175 /*
176 * If a page-in on that section offset is pending that wait for
177 * it to finish.
178 */
179
180 do
181 {
182 /*
183 * Release all our locks and wait for the pending operation
184 * to complete
185 */
186 MmUnlockSection(Section);
187 MmUnlockAddressSpace(AddressSpace);
188 /*
189 * FIXME: What if the event is set and cleared after we
190 * unlock the section but before we wait.
191 */
192 Status = MmWaitForPage((PVOID)(Entry & (~SPE_PAGEIN_PENDING)));
193 if (!NT_SUCCESS(Status))
194 {
195 /*
196 * FIXME: What do we do in this case? Maybe the thread
197 * has terminated.
198 */
199
200 DbgPrint("Failed to wait for page\n");
201 KeBugCheck(0);
202 return(STATUS_UNSUCCESSFUL);
203 }
204
205 /*
206 * Relock the address space and section
207 */
208 MmLockAddressSpace(AddressSpace);
209 MmLockSection(Section);
210
211 /*
212 * Get the entry for the section offset. If the entry is still
213 * pending that means another thread is already trying the
214 * page-in again so we have to wait again.
215 */
216 Entry = MmGetPageEntrySection(Section,
217 Offset.u.LowPart);
218 } while (Entry & SPE_PAGEIN_PENDING);
219
220 /*
221 * Setting the entry to null means the read failing.
222 * FIXME: We should retry it (unless that filesystem has gone
223 * entirely e.g. the network died).
224 */
225 if (Entry == 0)
226 {
227 DbgPrint("Entry set to null while we slept\n");
228 KeBugCheck(0);
229 }
230
231 /*
232 * Maybe the thread did the page-in took the fault on the
233 * same address-space/address as we did. If so we can just
234 * return success.
235 */
236 if (MmIsPagePresent(NULL, Address))
237 {
238 MmUnlockSection(Section);
239 return(STATUS_SUCCESS);
240 }
241
242 /*
243 * Get a reference to the page containing the data for the page.
244 */
245 Page = (PVOID)Entry;
246 MmReferencePage(Page);
247
248 /*
249 * When we reach here, we have the address space and section locked
250 * and have a reference to a page containing valid data for the
251 * section offset. Set the page and return success.
252 */
253 Status = MmCreateVirtualMapping(NULL,
254 Address,
255 MemoryArea->Attributes,
256 (ULONG)Page);
257 if (!NT_SUCCESS(Status))
258 {
259 DbgPrint("Unable to create virtual mapping\n");
260 KeBugCheck(0);
261 }
262 MmUnlockSection(Section);
263
264 return(STATUS_SUCCESS);
265 }
266
267 NTSTATUS MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
268 MEMORY_AREA* MemoryArea,
269 PVOID Address)
270 {
271 LARGE_INTEGER Offset;
272 IO_STATUS_BLOCK IoStatus;
273 PMDL Mdl;
274 PVOID Page;
275 NTSTATUS Status;
276 ULONG PAddress;
277 PSECTION_OBJECT Section;
278 ULONG Entry;
279 ULONG Entry1;
280
281 DPRINT("MmSectionHandleFault(MemoryArea %x, Address %x)\n",
282 MemoryArea,Address);
283
284
285 /*
286 * There is a window between taking the page fault and locking the
287 * address space when another thread could load the page so we check
288 * that.
289 */
290 if (MmIsPagePresent(NULL, Address))
291 {
292 DbgPrint("Page is already present\n");
293 return(STATUS_SUCCESS);
294 }
295
296 PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
297 Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
298 MemoryArea->Data.SectionData.ViewOffset;
299
300 /*
301 * This is a temporary hack because we need to map PE sections
302 * to within a finer granularity than data file section.
303 */
304 if ((MemoryArea->Data.SectionData.ViewOffset % PAGESIZE) != 0)
305 {
306 return(MmUnalignedLoadPageForSection(AddressSpace,
307 MemoryArea,
308 Address));
309 }
310
311 DPRINT("MemoryArea->BaseAddress %x\n", MemoryArea->BaseAddress);
312 DPRINT("MemoryArea->Data.SectionData.ViewOffset %x\n",
313 MemoryArea->Data.SectionData.ViewOffset);
314 DPRINT("Got offset %x\n", Offset.QuadPart);
315
316 /*
317 * Lock the section
318 */
319 Section = MemoryArea->Data.SectionData.Section;
320 MmLockSection(Section);
321
322 /*
323 * Get the entry corresponding to the offset within the section
324 */
325 Entry = MmGetPageEntrySection(Section, Offset.u.LowPart);
326
327 DPRINT("Entry %x\n", Entry);
328
329 if (Entry == 0)
330 {
331 /*
332 * If the entry is zero (and it can't change because we have
333 * locked the section) then we need to load the page.
334 */
335
336 /*
337 *
338 */
339 Page = MmAllocPage(0);
340 while (Page == NULL)
341 {
342 MmUnlockSection(Section);
343 MmUnlockAddressSpace(AddressSpace);
344 MmWaitForFreePages();
345 MmLockAddressSpace(AddressSpace);
346 MmLockSection(Section);
347 Entry1 = MmGetPageEntrySection(Section, Offset.u.LowPart);
348 if (Entry1 & SPE_PAGEIN_PENDING)
349 {
350 return(MmWaitForPendingOperationSection(AddressSpace,
351 MemoryArea,
352 Address,
353 Section,
354 Offset,
355 Entry1));
356 }
357 else if (Entry1 != 0)
358 {
359 Page = (PVOID)Entry;
360 MmReferencePage(Page);
361
362 Status = MmCreateVirtualMapping(NULL,
363 Address,
364 MemoryArea->Attributes,
365 (ULONG)Page);
366 if (!NT_SUCCESS(Status))
367 {
368 DbgPrint("Unable to create virtual mapping\n");
369 KeBugCheck(0);
370 }
371 MmUnlockSection(Section);
372
373 return(STATUS_SUCCESS);
374 }
375 Page = MmAllocPage(0);
376 }
377
378 /*
379 * Create an mdl to hold the page we are going to read data into.
380 */
381 Mdl = MmCreateMdl(NULL, NULL, PAGESIZE);
382 MmBuildMdlFromPages(Mdl, (PULONG)&Page);
383
384 /*
385 * Clear the wait state (Since we are holding the only reference to
386 * page this is safe)
387 */
388 MmClearWaitPage(Page);
389
390 /*
391 * Notify any other threads that fault on the same section offset
392 * that a page-in is pending.
393 */
394 Entry = ((ULONG)Page) | SPE_PAGEIN_PENDING;
395 MmSetPageEntrySection(Section,
396 Offset.u.LowPart,
397 Entry);
398
399 /*
400 * Release all our locks and read in the page from disk
401 */
402 MmUnlockSection(Section);
403 MmUnlockAddressSpace(AddressSpace);
404 DPRINT("Reading file offset %x\n", Offset.QuadPart);
405 Status = IoPageRead(MemoryArea->Data.SectionData.Section->FileObject,
406 Mdl,
407 &Offset,
408 &IoStatus);
409 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
410 {
411 /*
412 * FIXME: What do we know in this case?
413 */
414
415 MmLockAddressSpace(AddressSpace);
416 return(Status);
417 }
418
419 /*
420 * Relock the address space and section
421 */
422 MmLockAddressSpace(AddressSpace);
423 MmLockSection(Section);
424
425 /*
426 * Check the entry. No one should change the status of a page
427 * that has a pending page-in.
428 */
429 Entry1 = MmGetPageEntrySection(Section, Offset.QuadPart);
430 if (Entry != Entry1)
431 {
432 DbgPrint("Someone changed ppte entry while we slept\n");
433 KeBugCheck(0);
434 }
435
436 /*
437 * Mark the offset within the section as having valid, in-memory
438 * data
439 */
440 Entry = (ULONG)Page;
441 MmSetPageEntrySection(Section,
442 Offset.QuadPart,
443 Entry);
444
445 /*
446 * Set the event associated with the page so other threads that
447 * may be waiting know that valid data is now in-memory.
448 */
449 MmSetWaitPage(Page);
450
451 Status = MmCreateVirtualMapping(NULL,
452 Address,
453 MemoryArea->Attributes,
454 (ULONG)Page);
455 if (!NT_SUCCESS(Status))
456 {
457 DbgPrint("Unable to create virtual mapping\n");
458 KeBugCheck(0);
459 }
460 MmUnlockSection(Section);
461
462 return(STATUS_SUCCESS);
463
464 }
465 else if (Entry & SPE_PAGEIN_PENDING)
466 {
467 return(MmWaitForPendingOperationSection(AddressSpace,
468 MemoryArea,
469 Address,
470 Section,
471 Offset,
472 Entry));
473 }
474 else
475 {
476 /*
477 * If the section offset is already in-memory and valid then just
478 * take another reference to the page
479 */
480
481 Page = (PVOID)Entry;
482 MmReferencePage(Page);
483
484 Status = MmCreateVirtualMapping(NULL,
485 Address,
486 MemoryArea->Attributes,
487 (ULONG)Page);
488 if (!NT_SUCCESS(Status))
489 {
490 DbgPrint("Unable to create virtual mapping\n");
491 KeBugCheck(0);
492 }
493 MmUnlockSection(Section);
494
495 return(STATUS_SUCCESS);
496 }
497 }
498
499 ULONG MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
500 MEMORY_AREA* MemoryArea,
501 PVOID Address,
502 PBOOLEAN Ul)
503 {
504 (*Ul) = FALSE;
505 return(0);
506 }
507
508 VOID MmpDeleteSection(PVOID ObjectBody)
509 {
510 DPRINT("MmpDeleteSection(ObjectBody %x)\n", ObjectBody);
511 }
512
513 VOID MmpCloseSection(PVOID ObjectBody,
514 ULONG HandleCount)
515 {
516 DPRINT("MmpCloseSection(OB %x, HC %d) RC %d\n",
517 ObjectBody, HandleCount, ObGetReferenceCount(ObjectBody));
518 }
519
520 NTSTATUS MmpCreateSection(PVOID ObjectBody,
521 PVOID Parent,
522 PWSTR RemainingPath,
523 POBJECT_ATTRIBUTES ObjectAttributes)
524 {
525 NTSTATUS Status;
526
527 DPRINT("MmpCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
528 ObjectBody, Parent, RemainingPath);
529
530 if (RemainingPath == NULL)
531 {
532 return(STATUS_SUCCESS);
533 }
534
535 if (wcschr(RemainingPath+1, L'\\') != NULL)
536 {
537 return(STATUS_UNSUCCESSFUL);
538 }
539
540 Status = ObReferenceObjectByPointer(Parent,
541 STANDARD_RIGHTS_REQUIRED,
542 ObDirectoryType,
543 UserMode);
544 if (!NT_SUCCESS(Status))
545 {
546 return(Status);
547 }
548
549 ObAddEntryDirectory(Parent, ObjectBody, RemainingPath+1);
550 ObDereferenceObject(Parent);
551
552 return(STATUS_SUCCESS);
553 }
554
555 NTSTATUS MmInitSectionImplementation(VOID)
556 {
557 MmSectionObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
558
559 RtlInitUnicodeString(&MmSectionObjectType->TypeName, L"Section");
560
561 MmSectionObjectType->TotalObjects = 0;
562 MmSectionObjectType->TotalHandles = 0;
563 MmSectionObjectType->MaxObjects = ULONG_MAX;
564 MmSectionObjectType->MaxHandles = ULONG_MAX;
565 MmSectionObjectType->PagedPoolCharge = 0;
566 MmSectionObjectType->NonpagedPoolCharge = sizeof(SECTION_OBJECT);
567 MmSectionObjectType->Dump = NULL;
568 MmSectionObjectType->Open = NULL;
569 MmSectionObjectType->Close = MmpCloseSection;
570 MmSectionObjectType->Delete = MmpDeleteSection;
571 MmSectionObjectType->Parse = NULL;
572 MmSectionObjectType->Security = NULL;
573 MmSectionObjectType->QueryName = NULL;
574 MmSectionObjectType->OkayToClose = NULL;
575 MmSectionObjectType->Create = MmpCreateSection;
576
577 return(STATUS_SUCCESS);
578 }
579
580
581 /* FIXME: NtCS should call MmCS */
582 NTSTATUS STDCALL NtCreateSection (OUT PHANDLE SectionHandle,
583 IN ACCESS_MASK DesiredAccess,
584 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
585 IN PLARGE_INTEGER MaximumSize OPTIONAL,
586 IN ULONG SectionPageProtection OPTIONAL,
587 IN ULONG AllocationAttributes,
588 IN HANDLE FileHandle OPTIONAL)
589 /*
590 * FUNCTION: Creates a section object.
591 * ARGUMENTS:
592 * SectionHandle (OUT) = Caller supplied storage for the resulting
593 * handle
594 * DesiredAccess = Specifies the desired access to the section can be a
595 * combination of STANDARD_RIGHTS_REQUIRED |
596 * SECTION_QUERY | SECTION_MAP_WRITE |
597 * SECTION_MAP_READ | SECTION_MAP_EXECUTE.
598 * ObjectAttribute = Initialized attributes for the object can be used
599 * to create a named section
600 * MaxiumSize = Maximizes the size of the memory section. Must be
601 * non-NULL for a page-file backed section.
602 * If value specified for a mapped file and the file is
603 * not large enough, file will be extended.
604 * SectionPageProtection = Can be a combination of PAGE_READONLY |
605 * PAGE_READWRITE | PAGE_WRITEONLY |
606 * PAGE_WRITECOPY.
607 * AllocationAttributes = can be a combination of SEC_IMAGE |
608 * SEC_RESERVE
609 * FileHandle = Handle to a file to create a section mapped to a file
610 * instead of a memory backed section.
611 * RETURNS: Status
612 */
613 {
614 PSECTION_OBJECT Section;
615 NTSTATUS Status;
616
617 DPRINT("NtCreateSection()\n");
618
619 Section = ObCreateObject(SectionHandle,
620 DesiredAccess,
621 ObjectAttributes,
622 MmSectionObjectType);
623 DPRINT("SectionHandle %x\n", SectionHandle);
624 if (Section == NULL)
625 {
626 return(STATUS_UNSUCCESSFUL);
627 }
628
629 if (MaximumSize != NULL)
630 {
631 Section->MaximumSize = *MaximumSize;
632 }
633 else
634 {
635 Section->MaximumSize.QuadPart = 0xffffffff;
636 }
637 Section->SectionPageProtection = SectionPageProtection;
638 Section->AllocateAttributes = AllocationAttributes;
639 InitializeListHead(&Section->ViewListHead);
640 KeInitializeSpinLock(&Section->ViewListLock);
641 KeInitializeMutex(&Section->Lock, 0);
642 memset(&Section->PageDirectory, 0, sizeof(Section->PageDirectory));
643
644 if (FileHandle != (HANDLE)0xffffffff)
645 {
646 Status = ObReferenceObjectByHandle(FileHandle,
647 FILE_READ_DATA,
648 IoFileObjectType,
649 UserMode,
650 (PVOID*)&Section->FileObject,
651 NULL);
652 if (!NT_SUCCESS(Status))
653 {
654 DPRINT("NtCreateSection() = %x\n",Status);
655 ZwClose(SectionHandle);
656 ObDereferenceObject(Section);
657 return(Status);
658 }
659 }
660 else
661 {
662 Section->FileObject = NULL;
663 }
664
665 DPRINT("NtCreateSection() = STATUS_SUCCESS\n");
666 ObDereferenceObject(Section);
667 return(STATUS_SUCCESS);
668 }
669
670
671 /**********************************************************************
672 * NAME
673 * NtOpenSection
674 *
675 * DESCRIPTION
676 *
677 * ARGUMENTS
678 * SectionHandle
679 *
680 * DesiredAccess
681 *
682 * ObjectAttributes
683 *
684 * RETURN VALUE
685 *
686 * REVISIONS
687 *
688 */
689 NTSTATUS STDCALL NtOpenSection(PHANDLE SectionHandle,
690 ACCESS_MASK DesiredAccess,
691 POBJECT_ATTRIBUTES ObjectAttributes)
692 {
693 PVOID Object;
694 NTSTATUS Status;
695
696 *SectionHandle = 0;
697
698 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
699 ObjectAttributes->Attributes,
700 NULL,
701 DesiredAccess,
702 MmSectionObjectType,
703 UserMode,
704 NULL,
705 &Object);
706 if (!NT_SUCCESS(Status))
707 {
708 return Status;
709 }
710
711 Status = ObCreateHandle(PsGetCurrentProcess(),
712 Object,
713 DesiredAccess,
714 FALSE,
715 SectionHandle);
716 ObDereferenceObject(Object);
717 return(Status);
718 }
719
720
721 /**********************************************************************
722 * NAME EXPORTED
723 * NtMapViewOfSection
724 *
725 * DESCRIPTION
726 * Maps a view of a section into the virtual address space of a
727 * process.
728 *
729 * ARGUMENTS
730 * SectionHandle
731 * Handle of the section.
732 *
733 * ProcessHandle
734 * Handle of the process.
735 *
736 * BaseAddress
737 * Desired base address (or NULL) on entry;
738 * Actual base address of the view on exit.
739 *
740 * ZeroBits
741 * Number of high order address bits that must be zero.
742 *
743 * CommitSize
744 * Size in bytes of the initially committed section of
745 * the view.
746 *
747 * SectionOffset
748 * Offset in bytes from the beginning of the section
749 * to the beginning of the view.
750 *
751 * ViewSize
752 * Desired length of map (or zero to map all) on entry
753 * Actual length mapped on exit.
754 *
755 * InheritDisposition
756 * Specified how the view is to be shared with
757 * child processes.
758 *
759 * AllocateType
760 * Type of allocation for the pages.
761 *
762 * Protect
763 * Protection for the committed region of the view.
764 *
765 * RETURN VALUE
766 * Status.
767 */
768 NTSTATUS STDCALL NtMapViewOfSection(HANDLE SectionHandle,
769 HANDLE ProcessHandle,
770 PVOID* BaseAddress,
771 ULONG ZeroBits,
772 ULONG CommitSize,
773 PLARGE_INTEGER SectionOffset,
774 PULONG ViewSize,
775 SECTION_INHERIT InheritDisposition,
776 ULONG AllocationType,
777 ULONG Protect)
778 {
779 PSECTION_OBJECT Section;
780 PEPROCESS Process;
781 MEMORY_AREA* Result;
782 NTSTATUS Status;
783 KIRQL oldIrql;
784 ULONG ViewOffset;
785 PMADDRESS_SPACE AddressSpace;
786
787 DPRINT("NtMapViewOfSection(Section:%08lx, Process:%08lx,\n"
788 " Base:%08lx, ZeroBits:%08lx, CommitSize:%08lx,\n"
789 " SectionOffs:%08lx, *ViewSize:%08lx, InheritDisp:%08lx,\n"
790 " AllocType:%08lx, Protect:%08lx)\n",
791 SectionHandle, ProcessHandle, BaseAddress, ZeroBits,
792 CommitSize, SectionOffset, *ViewSize, InheritDisposition,
793 AllocationType, Protect);
794
795 DPRINT(" *Base:%08lx\n", *BaseAddress);
796
797 Status = ObReferenceObjectByHandle(SectionHandle,
798 SECTION_MAP_READ,
799 MmSectionObjectType,
800 UserMode,
801 (PVOID*)&Section,
802 NULL);
803 if (!(NT_SUCCESS(Status)))
804 {
805 DPRINT("ObReference failed rc=%x\n",Status);
806 return Status;
807 }
808
809 DPRINT("Section %x\n",Section);
810 MmLockSection(Section);
811
812 Status = ObReferenceObjectByHandle(ProcessHandle,
813 PROCESS_VM_OPERATION,
814 PsProcessType,
815 UserMode,
816 (PVOID*)&Process,
817 NULL);
818 if (!NT_SUCCESS(Status))
819 {
820 DPRINT("ObReferenceObjectByHandle(ProcessHandle, ...) failed (%x)\n",
821 Status);
822 MmUnlockSection(Section);
823 ObDereferenceObject(Section);
824 return Status;
825 }
826
827 AddressSpace = &Process->AddressSpace;
828
829 DPRINT("Process %x\n", Process);
830 DPRINT("ViewSize %x\n",ViewSize);
831
832 if (SectionOffset == NULL)
833 {
834 ViewOffset = 0;
835 }
836 else
837 {
838 ViewOffset = SectionOffset->u.LowPart;
839 }
840
841 if (((*ViewSize)+ViewOffset) > Section->MaximumSize.u.LowPart)
842 {
843 (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset;
844 }
845
846 DPRINT("Creating memory area\n");
847 MmLockAddressSpace(AddressSpace);
848 Status = MmCreateMemoryArea(Process,
849 &Process->AddressSpace,
850 MEMORY_AREA_SECTION_VIEW_COMMIT,
851 BaseAddress,
852 *ViewSize,
853 Protect,
854 &Result);
855 if (!NT_SUCCESS(Status))
856 {
857 DPRINT("NtMapViewOfSection() = %x\n",Status);
858
859 MmUnlockAddressSpace(AddressSpace);
860 ObDereferenceObject(Process);
861 MmUnlockSection(Section);
862 ObDereferenceObject(Section);
863
864 return Status;
865 }
866
867 KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
868 InsertTailList(&Section->ViewListHead,
869 &Result->Data.SectionData.ViewListEntry);
870 KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
871
872 Result->Data.SectionData.Section = Section;
873 Result->Data.SectionData.ViewOffset = ViewOffset;
874
875 DPRINT("SectionOffset %x\n",SectionOffset);
876
877
878 DPRINT("*BaseAddress %x\n",*BaseAddress);
879 MmUnlockAddressSpace(AddressSpace);
880 ObDereferenceObject(Process);
881 MmUnlockSection(Section);
882
883 DPRINT("NtMapViewOfSection() returning (Status %x)\n", STATUS_SUCCESS);
884 return(STATUS_SUCCESS);
885 }
886
887 NTSTATUS STDCALL MmUnmapViewOfSection(PEPROCESS Process,
888 PMEMORY_AREA MemoryArea)
889 {
890 PSECTION_OBJECT Section;
891 KIRQL oldIrql;
892
893 Section = MemoryArea->Data.SectionData.Section;
894
895 DPRINT("MmUnmapViewOfSection(Section %x) SectionRC %d\n",
896 Section, ObGetReferenceCount(Section));
897
898 MmLockSection(Section);
899 KeAcquireSpinLock(&Section->ViewListLock, &oldIrql);
900 RemoveEntryList(&MemoryArea->Data.SectionData.ViewListEntry);
901 KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
902 MmUnlockSection(Section);
903 ObDereferenceObject(Section);
904
905 return(STATUS_SUCCESS);
906 }
907
908 /**********************************************************************
909 * NAME EXPORTED
910 * NtUnmapViewOfSection
911 *
912 * DESCRIPTION
913 *
914 * ARGUMENTS
915 * ProcessHandle
916 *
917 * BaseAddress
918 *
919 * RETURN VALUE
920 * Status.
921 *
922 * REVISIONS
923 *
924 */
925 NTSTATUS STDCALL NtUnmapViewOfSection (HANDLE ProcessHandle,
926 PVOID BaseAddress)
927 {
928 PEPROCESS Process;
929 NTSTATUS Status;
930 PMEMORY_AREA MemoryArea;
931 PMADDRESS_SPACE AddressSpace;
932
933 DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n",
934 ProcessHandle, BaseAddress);
935
936 DPRINT("Referencing process\n");
937 Status = ObReferenceObjectByHandle(ProcessHandle,
938 PROCESS_VM_OPERATION,
939 PsProcessType,
940 UserMode,
941 (PVOID*)&Process,
942 NULL);
943 if (!NT_SUCCESS(Status))
944 {
945 DPRINT("ObReferenceObjectByHandle failed (Status %x)\n", Status);
946 return(Status);
947 }
948
949 AddressSpace = &Process->AddressSpace;
950
951 DPRINT("Opening memory area Process %x BaseAddress %x\n",
952 Process, BaseAddress);
953 MmLockAddressSpace(AddressSpace);
954 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
955 BaseAddress);
956 if (MemoryArea == NULL)
957 {
958 MmUnlockAddressSpace(AddressSpace);
959 ObDereferenceObject(Process);
960 return(STATUS_UNSUCCESSFUL);
961 }
962
963 Status = MmUnmapViewOfSection(Process,
964 MemoryArea);
965
966 DPRINT("MmFreeMemoryArea()\n");
967 Status = MmFreeMemoryArea(&Process->AddressSpace,
968 BaseAddress,
969 0,
970 TRUE);
971 MmUnlockAddressSpace(AddressSpace);
972 ObDereferenceObject(Process);
973
974 return Status;
975 }
976
977
978 NTSTATUS STDCALL NtQuerySection (IN HANDLE SectionHandle,
979 IN CINT SectionInformationClass,
980 OUT PVOID SectionInformation,
981 IN ULONG Length,
982 OUT PULONG ResultLength)
983 /*
984 * FUNCTION: Queries the information of a section object.
985 * ARGUMENTS:
986 * SectionHandle = Handle to the section link object
987 * SectionInformationClass = Index to a certain information structure
988 * SectionInformation (OUT)= Caller supplies storage for resulting
989 * information
990 * Length = Size of the supplied storage
991 * ResultLength = Data written
992 * RETURNS: Status
993 *
994 */
995 {
996 return(STATUS_UNSUCCESSFUL);
997 }
998
999
1000 NTSTATUS STDCALL NtExtendSection(IN HANDLE SectionHandle,
1001 IN ULONG NewMaximumSize)
1002 {
1003 UNIMPLEMENTED;
1004 }
1005
1006
1007 /**********************************************************************
1008 * NAME INTERNAL
1009 * MmAllocateSection@4
1010 *
1011 * DESCRIPTION
1012 *
1013 * ARGUMENTS
1014 * Length
1015 *
1016 * RETURN VALUE
1017 *
1018 * NOTE
1019 * Code taken from ntoskrnl/mm/special.c.
1020 *
1021 * REVISIONS
1022 *
1023 */
1024 PVOID STDCALL MmAllocateSection (IN ULONG Length)
1025 {
1026 PVOID Result;
1027 MEMORY_AREA* marea;
1028 NTSTATUS Status;
1029 ULONG i;
1030 PMADDRESS_SPACE AddressSpace;
1031
1032 DPRINT("MmAllocateSection(Length %x)\n",Length);
1033
1034 AddressSpace = MmGetKernelAddressSpace();
1035 Result = NULL;
1036 MmLockAddressSpace(AddressSpace);
1037 Status = MmCreateMemoryArea (NULL,
1038 AddressSpace,
1039 MEMORY_AREA_SYSTEM,
1040 &Result,
1041 Length,
1042 0,
1043 &marea);
1044 if (!NT_SUCCESS(STATUS_SUCCESS))
1045 {
1046 return (NULL);
1047 }
1048 DPRINT("Result %p\n",Result);
1049 for (i = 0; (i <= (Length / PAGESIZE)); i++)
1050 {
1051 Status = MmCreateVirtualMapping (NULL,
1052 (Result + (i * PAGESIZE)),
1053 PAGE_READWRITE,
1054 (ULONG)MmAllocPage(0));
1055 if (!NT_SUCCESS(Status))
1056 {
1057 DbgPrint("Unable to create virtual mapping\n");
1058 KeBugCheck(0);
1059 }
1060 }
1061 MmUnlockAddressSpace(AddressSpace);
1062 return ((PVOID)Result);
1063 }
1064
1065
1066 /**********************************************************************
1067 * NAME EXPORTED
1068 * MmMapViewOfSection@40
1069 *
1070 * DESCRIPTION
1071 *
1072 * ARGUMENTS
1073 * FIXME: stack space allocated is 40 bytes, but nothing
1074 * is known about what they are filled with.
1075 *
1076 * RETURN VALUE
1077 * Status.
1078 *
1079 */
1080 PVOID
1081 STDCALL
1082 MmMapViewOfSection (
1083 DWORD Unknown0,
1084 DWORD Unknown1,
1085 DWORD Unknown2,
1086 DWORD Unknown3,
1087 DWORD Unknown4,
1088 DWORD Unknown5,
1089 DWORD Unknown6,
1090 DWORD Unknown7,
1091 DWORD Unknown8,
1092 DWORD Unknown9
1093 )
1094 {
1095 UNIMPLEMENTED;
1096 return (NULL);
1097 }
1098
1099
1100 BOOLEAN
1101 STDCALL
1102 MmCanFileBeTruncated (
1103 IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
1104 IN PLARGE_INTEGER NewFileSize
1105 )
1106 {
1107 UNIMPLEMENTED;
1108 return (FALSE);
1109 }
1110
1111
1112 BOOLEAN
1113 STDCALL
1114 MmDisableModifiedWriteOfSection (
1115 DWORD Unknown0
1116 )
1117 {
1118 UNIMPLEMENTED;
1119 return (FALSE);
1120 }
1121
1122 BOOLEAN
1123 STDCALL
1124 MmFlushImageSection (
1125 IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
1126 IN MMFLUSH_TYPE FlushType
1127 )
1128 {
1129 UNIMPLEMENTED;
1130 return (FALSE);
1131 }
1132
1133 BOOLEAN
1134 STDCALL
1135 MmForceSectionClosed (
1136 DWORD Unknown0,
1137 DWORD Unknown1
1138 )
1139 {
1140 UNIMPLEMENTED;
1141 return (FALSE);
1142 }
1143
1144
1145 NTSTATUS
1146 STDCALL
1147 MmMapViewInSystemSpace (
1148 IN PVOID Section,
1149 OUT PVOID * MappedBase,
1150 IN PULONG ViewSize
1151 )
1152 {
1153 UNIMPLEMENTED;
1154 return (STATUS_NOT_IMPLEMENTED);
1155 }
1156
1157 NTSTATUS
1158 STDCALL
1159 MmUnmapViewInSystemSpace (
1160 DWORD Unknown0
1161 )
1162 {
1163 UNIMPLEMENTED;
1164 return (STATUS_NOT_IMPLEMENTED);
1165 }
1166
1167
1168 NTSTATUS
1169 STDCALL
1170 MmSetBankedSection (
1171 DWORD Unknown0,
1172 DWORD Unknown1,
1173 DWORD Unknown2,
1174 DWORD Unknown3,
1175 DWORD Unknown4,
1176 DWORD Unknown5
1177 )
1178 {
1179 UNIMPLEMENTED;
1180 return (STATUS_NOT_IMPLEMENTED);
1181 }
1182
1183
1184 /**********************************************************************
1185 * NAME EXPORTED
1186 * MmCreateSection@
1187 *
1188 * DESCRIPTION
1189 * Creates a section object.
1190 *
1191 * ARGUMENTS
1192 * SectionObjiect (OUT)
1193 * Caller supplied storage for the resulting pointer
1194 * to a SECTION_BOJECT instance;
1195 *
1196 * DesiredAccess
1197 * Specifies the desired access to the section can be a
1198 * combination of:
1199 * STANDARD_RIGHTS_REQUIRED |
1200 * SECTION_QUERY |
1201 * SECTION_MAP_WRITE |
1202 * SECTION_MAP_READ |
1203 * SECTION_MAP_EXECUTE
1204 *
1205 * ObjectAttributes [OPTIONAL]
1206 * Initialized attributes for the object can be used
1207 * to create a named section;
1208 *
1209 * MaximumSize
1210 * Maximizes the size of the memory section. Must be
1211 * non-NULL for a page-file backed section.
1212 * If value specified for a mapped file and the file is
1213 * not large enough, file will be extended.
1214 *
1215 * SectionPageProtection
1216 * Can be a combination of:
1217 * PAGE_READONLY |
1218 * PAGE_READWRITE |
1219 * PAGE_WRITEONLY |
1220 * PAGE_WRITECOPY
1221 *
1222 * AllocationAttributes
1223 * Can be a combination of:
1224 * SEC_IMAGE |
1225 * SEC_RESERVE
1226 *
1227 * FileHandle
1228 * Handle to a file to create a section mapped to a file
1229 * instead of a memory backed section;
1230 *
1231 * File
1232 * Unknown.
1233 *
1234 * RETURN VALUE
1235 * Status.
1236 */
1237 NTSTATUS
1238 STDCALL
1239 MmCreateSection (
1240 OUT PSECTION_OBJECT * SectionObject,
1241 IN ACCESS_MASK DesiredAccess,
1242 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
1243 IN PLARGE_INTEGER MaximumSize,
1244 IN ULONG SectionPageProtection,
1245 IN ULONG AllocationAttributes,
1246 IN HANDLE FileHandle OPTIONAL,
1247 IN PFILE_OBJECT File OPTIONAL
1248 )
1249 {
1250 return (STATUS_NOT_IMPLEMENTED);
1251 }
1252
1253 /* EOF */