ReactOS  r76032
data.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  *
19  * PROJECT: ReactOS kernel
20  * FILE: ntoskrnl/cache/section/data.c
21  * PURPOSE: Implements section objects
22  *
23  * PROGRAMMERS: Rex Jolliff
24  * David Welch
25  * Eric Kohl
26  * Emanuele Aliberti
27  * Eugene Ingerman
28  * Casper Hornstrup
29  * KJK::Hyperion
30  * Guido de Jong
31  * Ge van Geldorp
32  * Royce Mitchell III
33  * Filip Navara
34  * Aleksey Bragin
35  * Jason Filby
36  * Thomas Weidenmueller
37  * Gunnar Andre' Dalsnes
38  * Mike Nordell
39  * Alex Ionescu
40  * Gregor Anich
41  * Steven Edwards
42  * Herve Poussineau
43  */
44 
45 /*
46 
47 A note on this code:
48 
49 Unlike the previous section code, this code does not rely on an active map
50 for a page to exist in a data segment. Each mapping contains a large integer
51 offset to map at, and the segment always represents the entire section space
52 from zero to the maximum long long. This allows us to associate one single
53 page map with each file object, and to let each mapping view an offset into
54 the overall mapped file. Temporarily unmapping the file has no effect on the
55 section membership.
56 
57 This necessitates a change in the section page table implementation, which is
58 now an RtlGenericTable. This will be elaborated more in sptab.c. One upshot
59 of this change is that a mapping of a small files takes a bit more than 1/4
60 of the size in nonpaged kernel space as it did previously.
61 
62 When we need other threads that may be competing for the same page fault to
63 wait, we have a mechanism seperate from PageOps for dealing with that, which
64 was suggested by Travis Geiselbrecht after a conversation I had with Alex
65 Ionescu. That mechanism is the MM_WAIT_ENTRY, which is the all-ones SWAPENTRY.
66 
67 When we wish for other threads to know that we're waiting and will finish
68 handling a page fault, we place the swap entry MM_WAIT_ENTRY in the page table
69 at the fault address (this works on either the section page table or a process
70 address space), perform any blocking operations required, then replace the
71 entry.
72 
73 */
74 
75 /* INCLUDES *****************************************************************/
76 
77 #include <ntoskrnl.h>
78 #include "newmm.h"
79 #include <cache/newcc.h>
80 #define NDEBUG
81 #include <debug.h>
82 #include <mm/ARM3/miarm.h>
83 
84 #define DPRINTC DPRINT
85 
87 
88 extern KEVENT MpwThreadEvent;
91 
92 /* FUNCTIONS *****************************************************************/
93 
94 /* Note: Mmsp prefix denotes "Memory Manager Section Private". */
95 
96 VOID
97 NTAPI
99 {
100  //DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line);
101  ExAcquireFastMutex(&Segment->Lock);
102  Segment->Locked = TRUE;
103 }
104 
105 VOID
106 NTAPI
108 {
109  ASSERT(Segment->Locked);
110  Segment->Locked = FALSE;
111  ExReleaseFastMutex(&Segment->Lock);
112  //DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line);
113 }
114 
115 /*
116 
117 MiFlushMappedSection
118 
119 Called from cache code to cause dirty pages of a section
120 to be written back. This doesn't affect the mapping.
121 
122 BaseOffset is the base at which to start writing in file space.
123 FileSize is the length of the file as understood by the cache.
124 
125  */
126 NTSTATUS
127 NTAPI
129  PLARGE_INTEGER BaseOffset,
132  const char *File,
133  int Line)
134 {
140  ULONG_PTR BeginningAddress, EndingAddress;
141  LARGE_INTEGER ViewOffset;
143  PFN_NUMBER Page;
144  PPFN_NUMBER Pages;
145  KIRQL OldIrql;
146 
147  DPRINT("MiFlushMappedSection(%p,%I64x,%I64x,%u,%s:%d)\n",
148  BaseAddress,
149  BaseOffset->QuadPart,
150  FileSize ? FileSize->QuadPart : 0,
151  WriteData,
152  File,
153  Line);
154 
155  MmLockAddressSpace(AddressSpace);
156  MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
157  if (!MemoryArea || MemoryArea->Type != MEMORY_AREA_CACHE || MemoryArea->DeleteInProgress)
158  {
159  MmUnlockAddressSpace(AddressSpace);
160  DPRINT("STATUS_NOT_MAPPED_DATA\n");
161  return STATUS_NOT_MAPPED_DATA;
162  }
163  BeginningAddress = PAGE_ROUND_DOWN(MA_GetStartingAddress(MemoryArea));
164  EndingAddress = PAGE_ROUND_UP(MA_GetEndingAddress(MemoryArea));
165  Segment = MemoryArea->Data.SectionData.Segment;
166  ViewOffset.QuadPart = MemoryArea->Data.SectionData.ViewOffset.QuadPart;
167 
168  ASSERT(ViewOffset.QuadPart == BaseOffset->QuadPart);
169 
170  MmLockSectionSegment(Segment);
171 
173  sizeof(PFN_NUMBER) * ((EndingAddress - BeginningAddress) >> PAGE_SHIFT));
174 
175  if (!Pages)
176  {
177  ASSERT(FALSE);
178  }
179 
180  //DPRINT("Getting pages in range %08x-%08x\n", BeginningAddress, EndingAddress);
181 
182  for (PageAddress = BeginningAddress;
183  PageAddress < EndingAddress;
184  PageAddress += PAGE_SIZE)
185  {
187  FileOffset.QuadPart = ViewOffset.QuadPart + PageAddress - BeginningAddress;
188  Entry = MmGetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment,
189  &FileOffset);
190  Page = PFN_FROM_SSE(Entry);
191  if (Entry != 0 && !IS_SWAP_FROM_SSE(Entry) &&
192  (MmIsDirtyPageRmap(Page) || IS_DIRTY_SSE(Entry)) &&
193  FileOffset.QuadPart < FileSize->QuadPart)
194  {
196  MmReferencePage(Page);
198  Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT] = Entry;
199  }
200  else
201  {
202  Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT] = 0;
203  }
204  }
205 
206  MmUnlockSectionSegment(Segment);
207  MmUnlockAddressSpace(AddressSpace);
208 
209  for (PageAddress = BeginningAddress;
210  PageAddress < EndingAddress;
211  PageAddress += PAGE_SIZE)
212  {
214  FileOffset.QuadPart = ViewOffset.QuadPart + PageAddress - BeginningAddress;
215  Entry = Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT];
216  Page = PFN_FROM_SSE(Entry);
217  if (Page)
218  {
219  if (WriteData) {
220  //DPRINT("MiWriteBackPage(%wZ,addr %x,%08x%08x)\n", &Segment->FileObject->FileName, PageAddress, FileOffset.u.HighPart, FileOffset.u.LowPart);
221  Status = MiWriteBackPage(Segment->FileObject, &FileOffset, PAGE_SIZE, Page);
222  } else
223  Status = STATUS_SUCCESS;
224 
225  if (NT_SUCCESS(Status)) {
226  MmLockAddressSpace(AddressSpace);
227  MmSetCleanAllRmaps(Page);
228 
230  (PVOID)PageAddress,
231  PAGE_READONLY);
232 
233  MmLockSectionSegment(Segment);
234  Entry = MmGetPageEntrySectionSegment(Segment, &FileOffset);
235 
236  if (Entry && !IS_SWAP_FROM_SSE(Entry) && PFN_FROM_SSE(Entry) == Page)
237  MmSetPageEntrySectionSegment(Segment, &FileOffset, CLEAN_SSE(Entry));
238 
239  MmUnlockSectionSegment(Segment);
240  MmUnlockAddressSpace(AddressSpace);
241  } else {
242  DPRINT("Writeback from section flush %08x%08x (%x) %x@%x (%08x%08x:%wZ) failed %x\n",
243  FileOffset.u.HighPart,
244  FileOffset.u.LowPart,
245  (ULONG)(FileSize->QuadPart - FileOffset.QuadPart),
246  PageAddress,
247  Page,
248  FileSize->u.HighPart,
249  FileSize->u.LowPart,
250  &Segment->FileObject->FileName,
251  Status);
252  }
254  }
255  }
256 
257  ExFreePool(Pages);
258 
259  return Status;
260 }
261 
262 /*
263 
264 This deletes a segment entirely including its page map.
265 It must have been unmapped in every address space.
266 
267  */
268 
269 VOID
270 NTAPI
272 {
273  KIRQL OldIrql = 0;
274 
275  DPRINT("Finalize segment %p\n", Segment);
276 
277  MmLockSectionSegment(Segment);
278  RemoveEntryList(&Segment->ListOfSegments);
279  if (Segment->Flags & MM_DATAFILE_SEGMENT) {
280  KeAcquireSpinLock(&Segment->FileObject->IrpListLock, &OldIrql);
281  if (Segment->Flags & MM_SEGMENT_FINALIZE) {
282  KeReleaseSpinLock(&Segment->FileObject->IrpListLock, OldIrql);
283  MmUnlockSectionSegment(Segment);
284  return;
285  }
286  Segment->Flags |= MM_SEGMENT_FINALIZE;
287  DPRINTC("Finalizing data file segment %p\n", Segment);
288 
289  Segment->FileObject->SectionObjectPointer->DataSectionObject = NULL;
290  KeReleaseSpinLock(&Segment->FileObject->IrpListLock, OldIrql);
292  MmUnlockSectionSegment(Segment);
293  DPRINT("Dereference file object %wZ\n", &Segment->FileObject->FileName);
295  DPRINT("Done with %wZ\n", &Segment->FileObject->FileName);
296  Segment->FileObject = NULL;
297  } else {
298  DPRINTC("Finalizing segment %p\n", Segment);
300  MmUnlockSectionSegment(Segment);
301  }
302  DPRINTC("Segment %p destroy\n", Segment);
304 }
305 
306 NTSTATUS
307 NTAPI
311  PLARGE_INTEGER UMaximumSize,
315 /*
316  * Create a section backed by a data file.
317  */
318 {
319  PROS_SECTION_OBJECT Section;
324  CC_FILE_SIZES FileSizes;
326  KIRQL OldIrql;
327 
328  DPRINT("MmCreateDataFileSection\n");
329 
330  /* Create the section */
333  ObjectAttributes,
335  NULL,
336  sizeof(ROS_SECTION_OBJECT),
337  0,
338  0,
339  (PVOID*)(PVOID)&Section);
340  if (!NT_SUCCESS(Status))
341  {
342  DPRINT("Failed: %x\n", Status);
343  ObDereferenceObject(FileObject);
344  return Status;
345  }
346 
347  /* Initialize it */
348  RtlZeroMemory(Section, sizeof(ROS_SECTION_OBJECT));
349  Section->Type = 'SC';
350  Section->Size = 'TN';
351  Section->SectionPageProtection = SectionPageProtection;
352  Section->AllocationAttributes = AllocationAttributes;
353  Section->Segment = NULL;
354 
355  Section->FileObject = FileObject;
356 
357  DPRINT("Getting original file size\n");
358  /* A hack: If we're cached, we can overcome deadlocking with the upper
359  * layer filesystem call by retriving the object sizes from the cache
360  * which is made to keep track. If I had to guess, they were figuring
361  * out a similar problem.
362  */
363  if (!CcGetFileSizes(FileObject, &FileSizes))
364  {
366  /*
367  * FIXME: This is propably not entirely correct. We can't look into
368  * the standard FCB header because it might not be initialized yet
369  * (as in case of the EXT2FS driver by Manoj Paul Joseph where the
370  * standard file information is filled on first request).
371  */
372  DPRINT("Querying info\n");
373  Status = IoQueryFileInformation(FileObject,
376  &FileInfo,
377  &Information);
378  Iosb.Information = Information;
379  DPRINT("Query => %x\n", Status);
381 
382  if (!NT_SUCCESS(Status))
383  {
384  DPRINT("Status %x\n", Status);
385  ObDereferenceObject(Section);
386  ObDereferenceObject(FileObject);
387  return Status;
388  }
389  ASSERT(Status != STATUS_PENDING);
390 
391  FileSizes.ValidDataLength = FileInfo.EndOfFile;
392  FileSizes.FileSize = FileInfo.EndOfFile;
393  }
394  DPRINT("Got %I64x\n", FileSizes.ValidDataLength.QuadPart);
395 
396  /*
397  * FIXME: Revise this once a locking order for file size changes is
398  * decided
399  *
400  * We're handed down a maximum size in every case. Should we still check at all?
401  */
402  if (UMaximumSize != NULL && UMaximumSize->QuadPart)
403  {
404  DPRINT("Taking maximum %I64x\n", UMaximumSize->QuadPart);
405  MaximumSize.QuadPart = UMaximumSize->QuadPart;
406  }
407  else
408  {
409  DPRINT("Got file size %I64x\n", FileSizes.FileSize.QuadPart);
410  MaximumSize.QuadPart = FileSizes.FileSize.QuadPart;
411  }
412 
413  /* Mapping zero-sized files isn't allowed. */
414  if (MaximumSize.QuadPart == 0)
415  {
416  DPRINT("Zero size file\n");
417  ObDereferenceObject(Section);
418  ObDereferenceObject(FileObject);
419  return STATUS_FILE_INVALID;
420  }
421 
423  sizeof(MM_SECTION_SEGMENT),
425  if (Segment == NULL)
426  {
427  DPRINT("Failed: STATUS_NO_MEMORY\n");
428  ObDereferenceObject(Section);
429  ObDereferenceObject(FileObject);
430  return STATUS_NO_MEMORY;
431  }
432 
433  DPRINT("Zeroing %p\n", Segment);
434  RtlZeroMemory(Segment, sizeof(MM_SECTION_SEGMENT));
435  ExInitializeFastMutex(&Segment->Lock);
436 
437  Segment->ReferenceCount = 1;
438  Segment->Locked = TRUE;
439  RtlZeroMemory(&Segment->Image, sizeof(Segment->Image));
440  Section->Segment = Segment;
441 
442  KeAcquireSpinLock(&FileObject->IrpListLock, &OldIrql);
443  /*
444  * If this file hasn't been mapped as a data file before then allocate a
445  * section segment to describe the data file mapping
446  */
447  if (FileObject->SectionObjectPointer->DataSectionObject == NULL)
448  {
449  FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment;
450  KeReleaseSpinLock(&FileObject->IrpListLock, OldIrql);
451 
452  /*
453  * Set the lock before assigning the segment to the file object
454  */
455  ExAcquireFastMutex(&Segment->Lock);
456 
457  DPRINT("Filling out Segment info (No previous data section)\n");
458  ObReferenceObject(FileObject);
459  Segment->FileObject = FileObject;
461  Segment->Flags = MM_DATAFILE_SEGMENT;
462  memset(&Segment->Image, 0, sizeof(Segment->Image));
463  Segment->WriteCopy = FALSE;
464 
465  if (AllocationAttributes & SEC_RESERVE)
466  {
467  Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0;
468  }
469  else
470  {
471  Segment->RawLength.QuadPart = MaximumSize.QuadPart;
472  Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
473  }
475  InsertHeadList(&MiSegmentList, &Segment->ListOfSegments);
476  }
477  else
478  {
479  KeReleaseSpinLock(&FileObject->IrpListLock, OldIrql);
480  DPRINTC("Free Segment %p\n", Segment);
482 
483  DPRINT("Filling out Segment info (previous data section)\n");
484 
485  /*
486  * If the file is already mapped as a data file then we may need
487  * to extend it
488  */
489  Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointer->DataSectionObject;
490  Section->Segment = Segment;
491  (void)InterlockedIncrementUL(&Segment->ReferenceCount);
492 
493  MmLockSectionSegment(Segment);
494 
495  if (MaximumSize.QuadPart > Segment->RawLength.QuadPart &&
496  !(AllocationAttributes & SEC_RESERVE))
497  {
498  Segment->RawLength.QuadPart = MaximumSize.QuadPart;
499  Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
500  }
501  }
502 
503  MmUnlockSectionSegment(Segment);
504 
505  Section->MaximumSize.QuadPart = MaximumSize.QuadPart;
506 
507  /* Extend file if section is longer */
508  DPRINT("MaximumSize %I64x ValidDataLength %I64x\n",
509  MaximumSize.QuadPart,
510  FileSizes.ValidDataLength.QuadPart);
511  if (MaximumSize.QuadPart > FileSizes.ValidDataLength.QuadPart)
512  {
513  DPRINT("Changing file size to %I64x, segment %p\n",
514  MaximumSize.QuadPart,
515  Segment);
516 
517  Status = IoSetInformation(FileObject,
519  sizeof(LARGE_INTEGER),
520  &MaximumSize);
521 
522  DPRINT("Change: Status %x\n", Status);
523  if (!NT_SUCCESS(Status))
524  {
525  DPRINT("Could not expand section\n");
526  ObDereferenceObject(Section);
527  return Status;
528  }
529  }
530 
531  DPRINTC("Segment %p created (%x)\n", Segment, Segment->Flags);
532 
533  *SectionObject = Section;
534  return STATUS_SUCCESS;
535 }
536 
537 NTSTATUS
538 NTAPI
543  ULONG Protect,
544  PLARGE_INTEGER ViewOffset,
546  const char *file,
547  int line)
548 {
549  PMEMORY_AREA MArea;
551 
552  Status = MmCreateMemoryArea(AddressSpace,
554  BaseAddress,
555  ViewSize,
556  Protect,
557  &MArea,
558  AllocationType,
559  *BaseAddress ?
561 
562  if (!NT_SUCCESS(Status))
563  {
564  DPRINT("Mapping between 0x%p and 0x%p failed (%X).\n",
565  (*BaseAddress),
566  (char*)(*BaseAddress) + ViewSize,
567  Status);
568 
569  return Status;
570  }
571 
572  DPRINTC("MiMapViewOfSegment %p %p %p %I64x %Ix %wZ %s:%d\n",
573  MmGetAddressSpaceOwner(AddressSpace),
574  *BaseAddress,
575  Segment,
576  ViewOffset ? ViewOffset->QuadPart : 0,
577  ViewSize,
578  Segment->FileObject ? &Segment->FileObject->FileName : NULL,
579  file,
580  line);
581 
582  MArea->Data.SectionData.Segment = Segment;
583  if (ViewOffset)
584  MArea->Data.SectionData.ViewOffset = *ViewOffset;
585  else
586  MArea->Data.SectionData.ViewOffset.QuadPart = 0;
587 
588 #if 0
589  MArea->NotPresent = MmNotPresentFaultPageFile;
590  MArea->AccessFault = MiCowSectionPage;
591  MArea->PageOut = MmPageOutPageFileView;
592 #endif
593 
594  MmInitializeRegion(&MArea->Data.SectionData.RegionListHead,
595  ViewSize,
596  0,
597  Protect);
598 
599  DPRINTC("MiMapViewOfSegment(P %p, A %p, T %x)\n",
600  MmGetAddressSpaceOwner(AddressSpace),
601  *BaseAddress,
602  MArea->Type);
603 
604  return STATUS_SUCCESS;
605 }
606 
607 /*
608 
609 Completely remove the page at FileOffset in Segment. The page must not
610 be mapped.
611 
612 */
613 
614 VOID
615 NTAPI
618 {
621 
622  Entry = MmGetPageEntrySectionSegment(Segment, FileOffset);
623  DPRINTC("MiFreeSegmentPage(%p:%I64x -> Entry %Ix\n",
624  Segment,
625  FileOffset->QuadPart,
626  Entry);
627 
628  if (Entry && !IS_SWAP_FROM_SSE(Entry))
629  {
630  // The segment is carrying a dirty page.
631  PFN_NUMBER OldPage = PFN_FROM_SSE(Entry);
632  if (IS_DIRTY_SSE(Entry) && FileObject)
633  {
634  DPRINT("MiWriteBackPage(%p,%wZ,%I64x)\n",
635  Segment,
636  &FileObject->FileName,
637  FileOffset->QuadPart);
638 
639  MiWriteBackPage(FileObject, FileOffset, PAGE_SIZE, OldPage);
640  }
641  DPRINTC("Free page %Ix (off %I64x from %p) (ref ct %lu, ent %Ix, dirty? %s)\n",
642  OldPage,
643  FileOffset->QuadPart,
644  Segment,
645  MmGetReferenceCountPage(OldPage),
646  Entry,
647  IS_DIRTY_SSE(Entry) ? "true" : "false");
648 
649  MmSetPageEntrySectionSegment(Segment, FileOffset, 0);
651  }
652  else if (IS_SWAP_FROM_SSE(Entry))
653  {
654  DPRINT("Free swap\n");
656  }
657 
658  DPRINT("Done\n");
659 }
660 
661 VOID
664  PVOID Address,
665  PFN_NUMBER Page,
666  SWAPENTRY SwapEntry,
667  BOOLEAN Dirty)
668 {
670  PVOID *ContextData = Context;
675 
676  DPRINT("MmFreeSectionPage(%p,%p,%Ix,%Ix,%u)\n",
677  MmGetAddressSpaceOwner(ContextData[0]),
678  Address,
679  Page,
680  SwapEntry,
681  Dirty);
682 
683  AddressSpace = ContextData[0];
684  Process = MmGetAddressSpaceOwner(AddressSpace);
685  Address = (PVOID)PAGE_ROUND_DOWN(Address);
686  Segment = ContextData[1];
687  Offset.QuadPart = (ULONG_PTR)Address - MA_GetStartingAddress(MemoryArea) +
688  MemoryArea->Data.SectionData.ViewOffset.QuadPart;
689 
690  Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
691 
692  if (Page != 0 && PFN_FROM_SSE(Entry) == Page && Dirty)
693  {
694  DPRINT("Freeing section page %p:%I64x -> %Ix\n", Segment, Offset.QuadPart, Entry);
695  MmSetPageEntrySectionSegment(Segment, &Offset, DIRTY_SSE(Entry));
696  }
697  if (Page)
698  {
699  DPRINT("Removing page %p:%I64x -> %x\n", Segment, Offset.QuadPart, Entry);
700  MmSetSavedSwapEntryPage(Page, 0);
701  MmDeleteRmap(Page, Process, Address);
702  MmDeleteVirtualMapping(Process, Address, NULL, NULL);
704  }
705  if (SwapEntry != 0)
706  {
707  MmFreeSwapPage(SwapEntry);
708  }
709 }
710 
711 NTSTATUS
712 NTAPI
715 {
716  PVOID Context[2];
719 
720  MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
721  if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
722  {
723  ASSERT(MemoryArea);
724  return STATUS_UNSUCCESSFUL;
725  }
726 
727  MemoryArea->DeleteInProgress = TRUE;
728  Segment = MemoryArea->Data.SectionData.Segment;
729  MemoryArea->Data.SectionData.Segment = NULL;
730 
731  MmLockSectionSegment(Segment);
732 
733  Context[0] = AddressSpace;
734  Context[1] = Segment;
735 
736  DPRINT("MmFreeMemoryArea(%p,%p)\n",
737  MmGetAddressSpaceOwner(AddressSpace),
738  MA_GetStartingAddress(MemoryArea));
739 
740  MmLockAddressSpace(AddressSpace);
741 
742  MmFreeMemoryArea(AddressSpace, MemoryArea, MmFreeCacheSectionPage, Context);
743 
744  MmUnlockAddressSpace(AddressSpace);
745 
746  MmUnlockSectionSegment(Segment);
747 
748  DPRINTC("MiUnmapViewOfSegment %p %p %p\n",
749  MmGetAddressSpaceOwner(AddressSpace),
750  BaseAddress,
751  Segment);
752 
753  return STATUS_SUCCESS;
754 }
755 
756 NTSTATUS
757 NTAPI
760  BOOLEAN ExtendFile)
761 {
762  LARGE_INTEGER OldSize;
764  DPRINT("Extend Segment %p\n", Segment);
765 
766  MmLockSectionSegment(Segment);
767  OldSize.QuadPart = Segment->RawLength.QuadPart;
768  MmUnlockSectionSegment(Segment);
769 
770  DPRINT("OldSize 0x%I64x NewSize 0x%I64x\n",
771  OldSize.QuadPart,
772  NewSize->QuadPart);
773 
774  if (ExtendFile && OldSize.QuadPart < NewSize->QuadPart)
775  {
777 
778  Status = IoSetInformation(Segment->FileObject,
780  sizeof(LARGE_INTEGER),
781  NewSize);
782 
783  if (!NT_SUCCESS(Status)) return Status;
784  }
785 
786  MmLockSectionSegment(Segment);
787  Segment->RawLength.QuadPart = NewSize->QuadPart;
788  Segment->Length.QuadPart = MAX(Segment->Length.QuadPart,
790  MmUnlockSectionSegment(Segment);
791  return STATUS_SUCCESS;
792 }
793 
794 NTSTATUS
795 NTAPI
800 {
803 
804  DPRINT("MmMapViewInSystemSpaceAtOffset() called offset 0x%I64x\n",
805  FileOffset->QuadPart);
806 
807  AddressSpace = MmGetKernelAddressSpace();
808 
809  MmLockAddressSpace(AddressSpace);
810  MmLockSectionSegment(Segment);
811 
812  Status = MiMapViewOfSegment(AddressSpace,
813  Segment,
814  MappedBase,
815  *ViewSize,
817  FileOffset,
818  0);
819 
820  MmUnlockSectionSegment(Segment);
821  MmUnlockAddressSpace(AddressSpace);
822 
823  return Status;
824 }
825 
826 /*
827  * @implemented
828  */
831 {
834 
835  DPRINT("MmUnmapViewInSystemSpace() called\n");
836 
837  AddressSpace = MmGetKernelAddressSpace();
838 
839  Status = MmUnmapViewOfCacheSegment(AddressSpace, MappedBase);
840 
841  return Status;
842 }
843 
844 /* EOF */
#define MmSetPageEntrySectionSegment(S, O, E)
Definition: newmm.h:141
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
DWORD *typedef PVOID
Definition: winlogon.h:52
VOID NTAPI MmSetCleanAllRmaps(PFN_NUMBER Page)
Definition: rmap.c:195
#define DPRINTC
Definition: data.c:84
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
BOOLEAN WriteCopy
Definition: mm.h:166
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
PVOID ULONG Address
Definition: oprghdlr.h:14
#define STATUS_NOT_MAPPED_DATA
Definition: udferr_usr.h:157
#define IS_DIRTY_SSE(E)
Definition: newmm.h:16
union _MEMORY_AREA::@1561 Data
ULONG Type
Definition: mm.h:210
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ ULONG AllocationAttributes
Definition: mmfuncs.h:360
struct _Entry Entry
Definition: kefuncs.h:640
#define PFN_FROM_SSE(E)
Definition: newmm.h:7
NTSTATUS NTAPI MmMapCacheViewInSystemSpaceAtOffset(IN PMM_SECTION_SEGMENT Segment, OUT PVOID *MappedBase, PLARGE_INTEGER FileOffset, IN OUT PULONG ViewSize)
Definition: data.c:796
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define CLEAN_SSE(E)
Definition: newmm.h:15
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
static SIZE_T FileSize
Definition: cabinet.c:51
return STATUS_SUCCESS
Definition: btrfs.c:2664
LIST_ENTRY ListOfSegments
Definition: mm.h:176
VOID NTAPI MmDeleteRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2268
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1350
struct _MM_SECTION_SEGMENT::@1558 Image
NTSTATUS NTAPI MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
Definition: balance.c:97
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
BOOLEAN NTAPI MmIsDirtyPageRmap(PFN_NUMBER Page)
Definition: rmap.c:239
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:2740
NTSTATUS NTAPI IoSetInformation(IN PFILE_OBJECT FileObject, IN FILE_INFORMATION_CLASS FileInformationClass, IN ULONG Length, IN PVOID FileInformation)
Definition: iofunc.c:1164
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:267
#define STATUS_FILE_INVALID
Definition: ntstatus.h:374
IN POBJECT_ATTRIBUTES PortAttributes IN ACCESS_MASK DesiredAccess
Definition: creport.c:28
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
#define PAGE_ROUND_UP(x)
Definition: scsiport_int.h:13
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define MEMORY_AREA_CACHE
Definition: mm.h:70
NTSTATUS NTAPI IoQueryFileInformation(IN PFILE_OBJECT FileObject, IN FILE_INFORMATION_CLASS FileInformationClass, IN ULONG Length, OUT PVOID FileInformation, OUT PULONG ReturnedLength)
Definition: iofunc.c:1124
BOOLEAN NTAPI CcGetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:373
struct _LARGE_INTEGER::@2037 u
LARGE_INTEGER FileSize
Definition: cctypes.h:16
_Must_inspect_result_ _In_ SIZE_T _In_ PVOID PageAddress
Definition: mmfuncs.h:472
LIST_ENTRY MiSegmentList
Definition: data.c:86
uint32_t ULONG_PTR
Definition: typedefs.h:63
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG SectionPageProtection
Definition: mmfuncs.h:360
_Must_inspect_result_ _Out_ PIO_STATUS_BLOCK Iosb
Definition: fltkernel.h:1761
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG * PPFN_NUMBER
Definition: ke.h:8
VOID NTAPI MmFinalizeSegment(PMM_SECTION_SEGMENT Segment)
Definition: data.c:271
ULONG PFN_NUMBER
Definition: ke.h:8
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define FALSE
Definition: types.h:117
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG _In_ ULONG Protect
Definition: zwfuncs.h:214
ULONG Protection
Definition: mm.h:164
#define SEC_RESERVE
Definition: nt_native.h:1323
BOOLEAN Locked
Definition: mm.h:167
Irp IoStatus Information
smooth NULL
Definition: ftsmooth.c:557
VOID NTAPI MmDeleteVirtualMapping(struct _EPROCESS *Process, PVOID Address, BOOLEAN *WasDirty, PPFN_NUMBER Page)
_In_ PFILE_OBJECT FileObject
Definition: classpnp.h:1229
LARGE_INTEGER EndOfFile
Definition: nt_native.h:948
Definition: parser.c:48
void DPRINT(...)
Definition: polytest.cpp:61
NTSTATUS NTAPI MmCreateCacheSection(PROS_SECTION_OBJECT *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
Definition: data.c:308
NTSTATUS NTAPI MmUnmapCacheViewInSystemSpace(IN PVOID MappedBase)
Definition: data.c:830
PFILE_OBJECT FileObject
Definition: mm.h:159
_Inout_ PVOID Segment
Definition: exfuncs.h:893
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:938
LARGE_INTEGER Length
Definition: mm.h:161
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:318
int64_t LONG64
Definition: typedefs.h:66
unsigned char BOOLEAN
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
KEVENT MpwThreadEvent
Definition: mminit.c:23
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
#define STATUS_PENDING
Definition: ntstatus.h:82
#define SWAPENTRY_FROM_SSE(E)
Definition: newmm.h:12
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
BOOLEAN DeleteInProgress
Definition: mm.h:213
LARGE_INTEGER RawLength
Definition: mm.h:160
NTSTATUS NTAPI MmFreeMemoryArea(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_FREE_PAGE_FUNC FreePage, PVOID FreePageContext)
Definition: marea.c:278
VOID NTAPI MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage)
Definition: sptab.c:278
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
#define MA_GetEndingAddress(_MemoryArea)
Definition: mm.h:204
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
#define MM_DATAFILE_SEGMENT
Definition: mm.h:89
POBJECT_TYPE MmSectionObjectType
Definition: section.c:136
* PFILE_OBJECT
Definition: iotypes.h:1949
VOID NTAPI _MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line)
Definition: data.c:98
NTSTATUS NTAPI MmCreateMemoryArea(PMMSUPPORT AddressSpace, ULONG Type, PVOID *BaseAddress, SIZE_T Length, ULONG Protection, PMEMORY_AREA *Result, ULONG AllocationFlags, ULONG AllocationGranularity)
Definition: marea.c:410
ULONG NTAPI MmGetReferenceCountPage(PFN_NUMBER Page)
Definition: freelist.c:509
struct _MM_SECTION_SEGMENT * PMM_SECTION_SEGMENT
ULONG Flags
Definition: mm.h:165
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
Definition: ncftp.h:79
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
NTSTATUS NTAPI _MiMapViewOfSegment(PMMSUPPORT AddressSpace, PMM_SECTION_SEGMENT Segment, PVOID *BaseAddress, SIZE_T ViewSize, ULONG Protect, PLARGE_INTEGER ViewOffset, ULONG AllocationType, const char *file, int line)
Definition: data.c:539
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
LARGE_INTEGER ValidDataLength
Definition: cctypes.h:17
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:117
ULONG ReferenceCount
Definition: mm.h:162
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
#define IS_SWAP_FROM_SSE(E)
Definition: newmm.h:8
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG AllocationType
Definition: mmfuncs.h:404
VOID NTAPI MiInitializeSectionPageTable(PMM_SECTION_SEGMENT Segment)
Definition: sptab.c:165
struct _MEMORY_AREA::@1561::@1562 SectionData
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:203
PMMWSL MmWorkingSetList
Definition: procsup.c:21
Status
Definition: gdiplustypes.h:24
T MAX(T a, T b)
Definition: polytest.cpp:85
NTSTATUS NTAPI MmExtendCacheSection(PROS_SECTION_OBJECT Section, PLARGE_INTEGER NewSize, BOOLEAN ExtendFile)
Definition: data.c:758
NTSTATUS NTAPI MmUnmapViewOfCacheSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
Definition: data.c:713
NTSTATUS NTAPI _MiFlushMappedSection(PVOID BaseAddress, PLARGE_INTEGER BaseOffset, PLARGE_INTEGER FileSize, BOOLEAN WriteData, const char *File, int Line)
Definition: data.c:128
ULONG_PTR SIZE_T
Definition: typedefs.h:78
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1372
LONG NTSTATUS
Definition: DriverTester.h:11
#define MM_SEGMENT_FINALIZE
Definition: newmm.h:22
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
#define TAG_MM_SECTION_SEGMENT
Definition: tag.h:139
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1455
ULONG_PTR SWAPENTRY
Definition: mm.h:45
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
FORCEINLINE PEPROCESS MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
Definition: mm.h:1357
unsigned int * PULONG
Definition: retypes.h:1
#define PAGE_READONLY
Definition: compat.h:127
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER MaximumSize
Definition: mmfuncs.h:360
VOID NTAPI MmInitializeRegion(PLIST_ENTRY RegionListHead, SIZE_T Length, ULONG Type, ULONG Protect)
Definition: region.c:239
_Must_inspect_result_ _Outptr_result_bytebuffer_ ViewSize PVOID * MappedBase
Definition: mmfuncs.h:493
#define MmLockSectionSegment(x)
Definition: newmm.h:276
KSPIN_LOCK MiSectionPageTableLock
_In_ PLARGE_INTEGER FileOffset
Definition: cctypes.h:53
VOID NTAPI MmSetSavedSwapEntryPage(PFN_NUMBER Page, SWAPENTRY SavedSwapEntry)
Definition: freelist.c:454
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
FAST_MUTEX Lock
Definition: mm.h:158
#define MC_CACHE
Definition: mm.h:91
#define OUT
Definition: typedefs.h:39
#define ObReferenceObject
Definition: obfuncs.h:204
struct FileInfo FileInfo
#define DIRTY_SSE(E)
Definition: newmm.h:14
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:404
VOID NTAPI _MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line)
Definition: data.c:107
struct tagContext Context
Definition: acpixf.h:1014
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI MiFreeSegmentPage(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset)
Definition: data.c:616
VOID MmFreeCacheSectionPage(PVOID Context, MEMORY_AREA *MemoryArea, PVOID Address, PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
Definition: data.c:662
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
Definition: File.h:15
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1097
#define MmUnlockSectionSegment(x)
Definition: newmm.h:284
PMM_SECTION_SEGMENT Segment
Definition: mm.h:199
VOID NTAPI MmReferencePage(PFN_NUMBER Page)
Definition: freelist.c:489
#define memset(x, y, z)
Definition: compat.h:39
NTSTATUS NTAPI MmPageOutPageFileView(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PVOID Address, PMM_REQUIRED_RESOURCES Required)
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:65
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1343
static VOID WriteData(USHORT Data)
Definition: hardware.c:25
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define MmGetPageEntrySectionSegment(S, O)
Definition: newmm.h:143
#define MM_ALLOCATION_GRANULARITY
Definition: mmtypes.h:36
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
VOID NTAPI MmFreeSwapPage(SWAPENTRY Entry)
Definition: pagefile.c:392
LONGLONG QuadPart
Definition: typedefs.h:112
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define MiMapViewOfSegment(AddressSpace, Segment, BaseAddress, ViewSize, Protect, ViewOffset, AllocationType)
Definition: newmm.h:332
Definition: fci.c:114
#define MiWriteBackPage(F, O, L, P)
Definition: newmm.h:209