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