ReactOS 0.4.17-dev-117-g313be0c
section.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 * PURPOSE: Implements section objects
21 *
22 * PROGRAMMERS: Rex Jolliff
23 * David Welch
24 * Eric Kohl
25 * Emanuele Aliberti
26 * Eugene Ingerman
27 * Casper Hornstrup
28 * KJK::Hyperion
29 * Guido de Jong
30 * Ge van Geldorp
31 * Royce Mitchell III
32 * Filip Navara
33 * Aleksey Bragin
34 * Jason Filby
35 * Thomas Weidenmueller
36 * Gunnar Andre' Dalsnes
37 * Mike Nordell
38 * Alex Ionescu
39 * Gregor Anich
40 * Steven Edwards
41 * Herve Poussineau
42 */
43
44/* INCLUDES *****************************************************************/
45
46#include <ntoskrnl.h>
47#include <cache/newcc.h>
48#include <cache/section/newmm.h>
49#define NDEBUG
50#include <debug.h>
51#include <reactos/exeformat.h>
52
53#include "ARM3/miarm.h"
54
55#undef MmSetPageEntrySectionSegment
56#define MmSetPageEntrySectionSegment(S,O,E) \
57 _MmSetPageEntrySectionSegment((S),(O),(E),__FILE__,__LINE__)
58
59extern MMSESSION MmSession;
60
61static LARGE_INTEGER TinyTime = {{-1L, -1L}};
62
63#ifndef NEWCC
65
66VOID
69{
70 //DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line);
72 Segment->Locked = TRUE;
73}
74
75VOID
78{
79 ASSERT(Segment->Locked);
80 Segment->Locked = FALSE;
82 //DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line);
83}
84#endif
85
86static
89{
90 KIRQL OldIrql = MiAcquirePfnLock();
92
93 while (TRUE)
94 {
95 Segment = SectionObjectPointer->DataSectionObject;
96 if (!Segment)
97 break;
98
100 {
101 MiReleasePfnLock(OldIrql);
103 OldIrql = MiAcquirePfnLock();
104 continue;
105 }
106
109 break;
110 }
111
112 MiReleasePfnLock(OldIrql);
113
114 return Segment;
115}
116
117/* Somewhat grotesque, but eh... */
119{
120 ASSERT((Segment->SegFlags & MM_DATAFILE_SEGMENT) == 0);
121
122 return CONTAINING_RECORD(Segment->ReferenceCount, MM_IMAGE_SECTION_OBJECT, RefCount);
123}
124
127 IN PVOID Session,
131
133NTAPI
137 IN PLARGE_INTEGER InputMaximumSize,
142
144NTAPI
156 _In_range_(ViewShare, ViewUnmap) SECTION_INHERIT InheritDisposition,
159
160//
161// PeFmtCreateSection depends on the following:
162//
165
169
179
180/* TYPES *********************************************************************/
181
182typedef struct
183{
191}
193
194/* GLOBALS *******************************************************************/
195
197
199
201{
202 PAGE_NOACCESS, /* 0 = NONE */
203 PAGE_NOACCESS, /* 1 = SHARED */
204 PAGE_EXECUTE, /* 2 = EXECUTABLE */
205 PAGE_EXECUTE, /* 3 = EXECUTABLE, SHARED */
206 PAGE_READONLY, /* 4 = READABLE */
207 PAGE_READONLY, /* 5 = READABLE, SHARED */
208 PAGE_EXECUTE_READ, /* 6 = READABLE, EXECUTABLE */
209 PAGE_EXECUTE_READ, /* 7 = READABLE, EXECUTABLE, SHARED */
210 /*
211 * FIXME? do we really need the WriteCopy field in segments? can't we use
212 * PAGE_WRITECOPY here?
213 */
214 PAGE_READWRITE, /* 8 = WRITABLE */
215 PAGE_READWRITE, /* 9 = WRITABLE, SHARED */
216 PAGE_EXECUTE_READWRITE, /* 10 = WRITABLE, EXECUTABLE */
217 PAGE_EXECUTE_READWRITE, /* 11 = WRITABLE, EXECUTABLE, SHARED */
218 PAGE_READWRITE, /* 12 = WRITABLE, READABLE */
219 PAGE_READWRITE, /* 13 = WRITABLE, READABLE, SHARED */
220 PAGE_EXECUTE_READWRITE, /* 14 = WRITABLE, READABLE, EXECUTABLE */
221 PAGE_EXECUTE_READWRITE, /* 15 = WRITABLE, READABLE, EXECUTABLE, SHARED */
222};
223
226{
231};
232
233
234/* FUNCTIONS *****************************************************************/
235
236
237
239NTAPI
241 LONGLONG SegOffset,
243/*
244 * FUNCTION: write a page for a section backed memory area.
245 * PARAMETERS:
246 * MemoryArea - Memory area to write the page for.
247 * Offset - Offset of the page to write.
248 * Page - Page which contains the data to write.
249 */
250{
254 UCHAR MdlBase[sizeof(MDL) + sizeof(PFN_NUMBER)];
255 PMDL Mdl = (PMDL)MdlBase;
256 PFILE_OBJECT FileObject = Segment->FileObject;
258
259 FileOffset.QuadPart = Segment->Image.FileOffset + SegOffset;
260
261 RtlZeroMemory(MdlBase, sizeof(MdlBase));
264 Mdl->MdlFlags |= MDL_PAGES_LOCKED;
265
268 if (Status == STATUS_PENDING)
269 {
271 Status = IoStatus.Status;
272 }
273 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
274 {
275 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
276 }
277
278 return Status;
279}
280
281
282/*
283 References:
284 [1] Microsoft Corporation, "Microsoft Portable Executable and Common Object
285 File Format Specification", revision 6.0 (February 1999)
286*/
288 IN SIZE_T FileHeaderSize,
289 IN PVOID File,
290 OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
292 IN PEXEFMT_CB_READ_FILE ReadFileCb,
293 IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb)
294{
295 NTSTATUS nStatus;
296 ULONG cbFileHeaderOffsetSize = 0;
297 ULONG cbSectionHeadersOffset = 0;
298 ULONG cbSectionHeadersSize;
299 ULONG cbSectionHeadersOffsetSize = 0;
300 ULONG cbOptHeaderSize;
301 ULONG cbHeadersSize = 0;
302 ULONG nSectionAlignment;
303 ULONG nFileAlignment;
304 ULONG_PTR ImageBase = 0;
305 const IMAGE_DOS_HEADER * pidhDosHeader;
306 const IMAGE_NT_HEADERS32 * pinhNtHeader;
307 const IMAGE_OPTIONAL_HEADER32 * piohOptHeader;
308 const IMAGE_SECTION_HEADER * pishSectionHeaders;
309 PMM_SECTION_SEGMENT pssSegments;
310 LARGE_INTEGER lnOffset;
312 SIZE_T nPrevVirtualEndOfSegment = 0;
313 ULONG nFileSizeOfHeaders = 0;
314 ULONG i;
315 ULONG AlignedLength;
316
317 ASSERT(FileHeader);
318 ASSERT(FileHeaderSize > 0);
319 ASSERT(File);
320 ASSERT(ImageSectionObject);
321 ASSERT(ReadFileCb);
322 ASSERT(AllocateSegmentsCb);
323
324 ASSERT(Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize));
325
326 ASSERT(((UINT_PTR)FileHeader % TYPE_ALIGNMENT(IMAGE_DOS_HEADER)) == 0);
327
328#define DIE(ARGS_) { DPRINT ARGS_; goto l_Return; }
329
330 pBuffer = NULL;
331 pidhDosHeader = FileHeader;
332
333 /* DOS HEADER */
335
336 /* image too small to be an MZ executable */
337 if(FileHeaderSize < sizeof(IMAGE_DOS_HEADER))
338 DIE(("Too small to be an MZ executable, size is %lu\n", FileHeaderSize));
339
340 /* no MZ signature */
341 if(pidhDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
342 DIE(("No MZ signature found, e_magic is %hX\n", pidhDosHeader->e_magic));
343
344 /* NT HEADER */
346
347 /* not a Windows executable */
348 if(pidhDosHeader->e_lfanew <= 0)
349 DIE(("Not a Windows executable, e_lfanew is %d\n", pidhDosHeader->e_lfanew));
350
351 if(!Intsafe_AddULong32(&cbFileHeaderOffsetSize, pidhDosHeader->e_lfanew, RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader)))
352 DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
353
354 if(FileHeaderSize < cbFileHeaderOffsetSize)
355 pinhNtHeader = NULL;
356 else
357 {
358 /*
359 * we already know that Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize),
360 * and FileHeaderSize >= cbFileHeaderOffsetSize, so this holds true too
361 */
362 ASSERT(Intsafe_CanOffsetPointer(FileHeader, pidhDosHeader->e_lfanew));
363 pinhNtHeader = (PVOID)((UINT_PTR)FileHeader + pidhDosHeader->e_lfanew);
364 }
365
366 /*
367 * the buffer doesn't contain the NT file header, or the alignment is wrong: we
368 * need to read the header from the file
369 */
370 if(FileHeaderSize < cbFileHeaderOffsetSize ||
371 (UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
372 {
373 ULONG cbNtHeaderSize;
374 ULONG cbReadSize;
375 PVOID pData;
376
377l_ReadHeaderFromFile:
378 cbNtHeaderSize = 0;
379 lnOffset.QuadPart = pidhDosHeader->e_lfanew;
380
381 /* read the header from the file */
382 nStatus = ReadFileCb(File, &lnOffset, sizeof(IMAGE_NT_HEADERS64), &pData, &pBuffer, &cbReadSize);
383
384 if(!NT_SUCCESS(nStatus))
385 {
386 NTSTATUS ReturnedStatus = nStatus;
387
388 /* If it attempted to read past the end of the file, it means e_lfanew is invalid */
389 if (ReturnedStatus == STATUS_END_OF_FILE) nStatus = STATUS_INVALID_IMAGE_PROTECT;
390
391 DIE(("ReadFile failed, status %08X\n", ReturnedStatus));
392 }
393
394 ASSERT(pData);
396 ASSERT(cbReadSize > 0);
397
399
400 /* the buffer doesn't contain the file header */
401 if(cbReadSize < RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader))
402 DIE(("The file doesn't contain the PE file header\n"));
403
404 pinhNtHeader = pData;
405
406 /* object still not aligned: copy it to the beginning of the buffer */
407 if((UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
408 {
410 RtlMoveMemory(pBuffer, pData, cbReadSize);
411 pinhNtHeader = pBuffer;
412 }
413
414 /* invalid NT header */
416
417 if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
418 DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
419
421
422 if(!Intsafe_AddULong32(&cbNtHeaderSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
423 DIE(("The full NT header is too large\n"));
424
425 /* the buffer doesn't contain the whole NT header */
426 if(cbReadSize < cbNtHeaderSize)
427 DIE(("The file doesn't contain the full NT header\n"));
428 }
429 else
430 {
431 ULONG cbOptHeaderOffsetSize = 0;
432
434
435 /* don't trust an invalid NT header */
436 if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
437 DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
438
439 if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
440 DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
441
443
444 if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, cbOptHeaderOffsetSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
445 DIE(("The NT header is too large, SizeOfOptionalHeader is %X\n", pinhNtHeader->FileHeader.SizeOfOptionalHeader));
446
447 /* the buffer doesn't contain the whole NT header: read it from the file */
448 if(cbOptHeaderOffsetSize > FileHeaderSize)
449 goto l_ReadHeaderFromFile;
450 }
451
452 /* read information from the NT header */
453 piohOptHeader = &pinhNtHeader->OptionalHeader;
454 cbOptHeaderSize = pinhNtHeader->FileHeader.SizeOfOptionalHeader;
455
457
458 if(!RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Magic))
459 DIE(("The optional header doesn't contain the Magic field, SizeOfOptionalHeader is %X\n", cbOptHeaderSize));
460
461 /* ASSUME: RtlZeroMemory(ImageSectionObject, sizeof(*ImageSectionObject)); */
462
463 switch(piohOptHeader->Magic)
464 {
466#ifndef _WIN64
468 DIE(("Win64 optional header, unsupported\n"));
469#else
470 // Fall through.
471#endif
473 break;
474 default:
475 DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
476 }
477
478 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SectionAlignment) &&
479 RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, FileAlignment))
480 {
481 /* See [1], section 3.4.2 */
482 if(piohOptHeader->SectionAlignment < PAGE_SIZE)
483 {
484 if(piohOptHeader->FileAlignment != piohOptHeader->SectionAlignment)
485 DIE(("Sections aren't page-aligned and the file alignment isn't the same\n"));
486 }
487 else if(piohOptHeader->SectionAlignment < piohOptHeader->FileAlignment)
488 DIE(("The section alignment is smaller than the file alignment\n"));
489
490 nSectionAlignment = piohOptHeader->SectionAlignment;
491 nFileAlignment = piohOptHeader->FileAlignment;
492
493 if(!IsPowerOf2(nSectionAlignment) || !IsPowerOf2(nFileAlignment))
494 DIE(("The section alignment (%u) and file alignment (%u) aren't both powers of 2\n", nSectionAlignment, nFileAlignment));
495 }
496 else
497 {
498 nSectionAlignment = PAGE_SIZE;
499 nFileAlignment = PAGE_SIZE;
500 }
501
502 ASSERT(IsPowerOf2(nSectionAlignment));
503 ASSERT(IsPowerOf2(nFileAlignment));
504
505 switch(piohOptHeader->Magic)
506 {
507 /* PE32 */
509 {
510 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, ImageBase))
511 ImageBase = piohOptHeader->ImageBase;
512
513 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfImage))
514 ImageSectionObject->ImageInformation.ImageFileSize = piohOptHeader->SizeOfImage;
515
516 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackReserve))
517 ImageSectionObject->ImageInformation.MaximumStackSize = piohOptHeader->SizeOfStackReserve;
518
519 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackCommit))
520 ImageSectionObject->ImageInformation.CommittedStackSize = piohOptHeader->SizeOfStackCommit;
521
522 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Subsystem))
523 {
524 ImageSectionObject->ImageInformation.SubSystemType = piohOptHeader->Subsystem;
525
526 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
527 RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MajorSubsystemVersion))
528 {
529 ImageSectionObject->ImageInformation.SubSystemMinorVersion = piohOptHeader->MinorSubsystemVersion;
530 ImageSectionObject->ImageInformation.SubSystemMajorVersion = piohOptHeader->MajorSubsystemVersion;
531 }
532 }
533
534 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
535 {
536 ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
537 piohOptHeader->AddressOfEntryPoint);
538 }
539
540 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfCode))
541 ImageSectionObject->ImageInformation.ImageContainsCode = piohOptHeader->SizeOfCode != 0;
542 else
543 ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
544
545 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
546 {
547 if (piohOptHeader->AddressOfEntryPoint == 0)
548 {
549 ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
550 }
551 }
552
553 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, LoaderFlags))
554 ImageSectionObject->ImageInformation.LoaderFlags = piohOptHeader->LoaderFlags;
555
556 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, DllCharacteristics))
557 {
558 ImageSectionObject->ImageInformation.DllCharacteristics = piohOptHeader->DllCharacteristics;
559
560 /*
561 * Since we don't really implement SxS yet and LD doesn't supoprt /ALLOWISOLATION:NO, hard-code
562 * this flag here, which will prevent the loader and other code from doing any .manifest or SxS
563 * magic to any binary.
564 *
565 * This will break applications that depend on SxS when running with real Windows Kernel32/SxS/etc
566 * but honestly that's not tested. It will also break them when running no ReactOS once we implement
567 * the SxS support -- at which point, duh, this should be removed.
568 *
569 * But right now, any app depending on SxS is already broken anyway, so this flag only helps.
570 */
571 ImageSectionObject->ImageInformation.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NO_ISOLATION;
572 }
573
574 break;
575 }
576#ifdef _WIN64
577 /* PE64 */
579 {
580 const IMAGE_OPTIONAL_HEADER64 * pioh64OptHeader;
581
582 pioh64OptHeader = (const IMAGE_OPTIONAL_HEADER64 *)piohOptHeader;
583
584 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, ImageBase))
585 {
586 ImageBase = pioh64OptHeader->ImageBase;
587 if(pioh64OptHeader->ImageBase > MAXULONG_PTR)
588 DIE(("ImageBase exceeds the address space\n"));
589 }
590
591 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfImage))
592 {
593 if(pioh64OptHeader->SizeOfImage > MAXULONG_PTR)
594 DIE(("SizeOfImage exceeds the address space\n"));
595
596 ImageSectionObject->ImageInformation.ImageFileSize = pioh64OptHeader->SizeOfImage;
597 }
598
599 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackReserve))
600 {
601 if(pioh64OptHeader->SizeOfStackReserve > MAXULONG_PTR)
602 DIE(("SizeOfStackReserve exceeds the address space\n"));
603
604 ImageSectionObject->ImageInformation.MaximumStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackReserve;
605 }
606
607 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackCommit))
608 {
609 if(pioh64OptHeader->SizeOfStackCommit > MAXULONG_PTR)
610 DIE(("SizeOfStackCommit exceeds the address space\n"));
611
612 ImageSectionObject->ImageInformation.CommittedStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackCommit;
613 }
614
615 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, Subsystem))
616 {
617 ImageSectionObject->ImageInformation.SubSystemType = pioh64OptHeader->Subsystem;
618
619 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
620 RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MajorSubsystemVersion))
621 {
622 ImageSectionObject->ImageInformation.SubSystemMinorVersion = pioh64OptHeader->MinorSubsystemVersion;
623 ImageSectionObject->ImageInformation.SubSystemMajorVersion = pioh64OptHeader->MajorSubsystemVersion;
624 }
625 }
626
627 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
628 {
629 ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
630 pioh64OptHeader->AddressOfEntryPoint);
631 }
632
633 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfCode))
634 ImageSectionObject->ImageInformation.ImageContainsCode = pioh64OptHeader->SizeOfCode != 0;
635 else
636 ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
637
638 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
639 {
640 if (pioh64OptHeader->AddressOfEntryPoint == 0)
641 {
642 ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
643 }
644 }
645
646 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, LoaderFlags))
647 ImageSectionObject->ImageInformation.LoaderFlags = pioh64OptHeader->LoaderFlags;
648
649 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, DllCharacteristics))
650 ImageSectionObject->ImageInformation.DllCharacteristics = pioh64OptHeader->DllCharacteristics;
651
652 break;
653 }
654#endif // _WIN64
655 }
656
657 /* [1], section 3.4.2 */
658 if((ULONG_PTR)ImageBase % 0x10000)
659 DIE(("ImageBase is not aligned on a 64KB boundary"));
660
661 ImageSectionObject->ImageInformation.ImageCharacteristics = pinhNtHeader->FileHeader.Characteristics;
662 ImageSectionObject->ImageInformation.Machine = pinhNtHeader->FileHeader.Machine;
663 ImageSectionObject->ImageInformation.GpValue = 0;
664 ImageSectionObject->ImageInformation.ZeroBits = 0;
665 ImageSectionObject->BasedAddress = (PVOID)ImageBase;
666
667 /* SECTION HEADERS */
669
670 /* see [1], section 3.3 */
671 if(pinhNtHeader->FileHeader.NumberOfSections > 96)
672 DIE(("Too many sections, NumberOfSections is %u\n", pinhNtHeader->FileHeader.NumberOfSections));
673
674 /*
675 * the additional segment is for the file's headers. They need to be present for
676 * the benefit of the dynamic loader (to locate exports, defaults for thread
677 * parameters, resources, etc.)
678 */
679 ImageSectionObject->NrSegments = pinhNtHeader->FileHeader.NumberOfSections + 1;
680
681 /* file offset for the section headers */
682 if(!Intsafe_AddULong32(&cbSectionHeadersOffset, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
683 DIE(("Offset overflow\n"));
684
685 if(!Intsafe_AddULong32(&cbSectionHeadersOffset, cbSectionHeadersOffset, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
686 DIE(("Offset overflow\n"));
687
688 /* size of the section headers */
690 cbSectionHeadersSize = pinhNtHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
691
692 if(!Intsafe_AddULong32(&cbSectionHeadersOffsetSize, cbSectionHeadersOffset, cbSectionHeadersSize))
693 DIE(("Section headers too large\n"));
694
695 /* size of the executable's headers */
696 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfHeaders))
697 {
698// if(!IsAligned(piohOptHeader->SizeOfHeaders, nFileAlignment))
699// DIE(("SizeOfHeaders is not aligned\n"));
700
701 if(cbSectionHeadersSize > piohOptHeader->SizeOfHeaders)
702 DIE(("The section headers overflow SizeOfHeaders\n"));
703
704 cbHeadersSize = piohOptHeader->SizeOfHeaders;
705 }
706 else if(!AlignUp(&cbHeadersSize, cbSectionHeadersOffsetSize, nFileAlignment))
707 DIE(("Overflow aligning the size of headers\n"));
708
709 if(pBuffer)
710 {
712 pBuffer = NULL;
713 }
714 /* WARNING: pinhNtHeader IS NO LONGER USABLE */
715 /* WARNING: piohOptHeader IS NO LONGER USABLE */
716 /* WARNING: pioh64OptHeader IS NO LONGER USABLE */
717
718 if(FileHeaderSize < cbSectionHeadersOffsetSize)
719 pishSectionHeaders = NULL;
720 else
721 {
722 /*
723 * we already know that Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize),
724 * and FileHeaderSize >= cbSectionHeadersOffsetSize, so this holds true too
725 */
726 ASSERT(Intsafe_CanOffsetPointer(FileHeader, cbSectionHeadersOffset));
727 pishSectionHeaders = (PVOID)((UINT_PTR)FileHeader + cbSectionHeadersOffset);
728 }
729
730 /*
731 * the buffer doesn't contain the section headers, or the alignment is wrong:
732 * read the headers from the file
733 */
734 if(FileHeaderSize < cbSectionHeadersOffsetSize ||
735 (UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
736 {
737 PVOID pData;
738 ULONG cbReadSize;
739
740 lnOffset.QuadPart = cbSectionHeadersOffset;
741
742 /* read the header from the file */
743 nStatus = ReadFileCb(File, &lnOffset, cbSectionHeadersSize, &pData, &pBuffer, &cbReadSize);
744
745 if(!NT_SUCCESS(nStatus))
746 DIE(("ReadFile failed with status %08X\n", nStatus));
747
748 ASSERT(pData);
750 ASSERT(cbReadSize > 0);
751
753
754 /* the buffer doesn't contain all the section headers */
755 if(cbReadSize < cbSectionHeadersSize)
756 DIE(("The file doesn't contain all of the section headers\n"));
757
758 pishSectionHeaders = pData;
759
760 /* object still not aligned: copy it to the beginning of the buffer */
761 if((UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
762 {
764 RtlMoveMemory(pBuffer, pData, cbReadSize);
765 pishSectionHeaders = pBuffer;
766 }
767 }
768
769 /* SEGMENTS */
770 /* allocate the segments */
772 ImageSectionObject->Segments = AllocateSegmentsCb(ImageSectionObject->NrSegments);
773
774 if(ImageSectionObject->Segments == NULL)
775 DIE(("AllocateSegments failed\n"));
776
777 /* initialize the headers segment */
778 pssSegments = ImageSectionObject->Segments;
779
780// ASSERT(IsAligned(cbHeadersSize, nFileAlignment));
781
782 if(!AlignUp(&nFileSizeOfHeaders, cbHeadersSize, nFileAlignment))
783 DIE(("Cannot align the size of the section headers\n"));
784
785 nPrevVirtualEndOfSegment = ALIGN_UP_BY(cbHeadersSize, nSectionAlignment);
786 if (nPrevVirtualEndOfSegment < cbHeadersSize)
787 DIE(("Cannot align the size of the section headers\n"));
788
789 pssSegments[0].Image.FileOffset = 0;
790 pssSegments[0].Protection = PAGE_READONLY;
791 pssSegments[0].Length.QuadPart = nPrevVirtualEndOfSegment;
792 pssSegments[0].RawLength.QuadPart = nFileSizeOfHeaders;
793 pssSegments[0].Image.VirtualAddress = 0;
794 pssSegments[0].Image.Characteristics = 0;
795 pssSegments[0].WriteCopy = TRUE;
796
797 /* skip the headers segment */
798 ++ pssSegments;
799
801
802 ASSERT(ImageSectionObject->RefCount > 0);
803
804 /* convert the executable sections into segments. See also [1], section 4 */
805 for(i = 0; i < ImageSectionObject->NrSegments - 1; ++ i)
806 {
807 ULONG nCharacteristics;
808
809 /* validate the alignment */
810 if(!IsAligned(pishSectionHeaders[i].VirtualAddress, nSectionAlignment))
811 DIE(("Image.VirtualAddress[%u] is not aligned\n", i));
812
813 /* sections must be contiguous, ordered by base address and non-overlapping */
814 if(pishSectionHeaders[i].VirtualAddress != nPrevVirtualEndOfSegment)
815 DIE(("Memory gap between section %u and the previous\n", i));
816
817 /* ignore explicit BSS sections */
818 if(pishSectionHeaders[i].PointerToRawData != 0 && pishSectionHeaders[i].SizeOfRawData != 0)
819 {
820 /* validate the alignment */
821#if 0
822 /* Yes, this should be a multiple of FileAlignment, but there's
823 * stuff out there that isn't. We can cope with that
824 */
825 if(!IsAligned(pishSectionHeaders[i].SizeOfRawData, nFileAlignment))
826 DIE(("SizeOfRawData[%u] is not aligned\n", i));
827#endif
828
829// if(!IsAligned(pishSectionHeaders[i].PointerToRawData, nFileAlignment))
830// DIE(("PointerToRawData[%u] is not aligned\n", i));
831
832 if(!Intsafe_CanAddULong32(pishSectionHeaders[i].PointerToRawData, pishSectionHeaders[i].SizeOfRawData))
833 DIE(("SizeOfRawData[%u] too large\n", i));
834
835 /* conversion */
836 pssSegments[i].Image.FileOffset = pishSectionHeaders[i].PointerToRawData;
837 pssSegments[i].RawLength.QuadPart = pishSectionHeaders[i].SizeOfRawData;
838 }
839 else
840 {
841 /* FIXME: Should reset PointerToRawData to 0 in the image mapping */
842 ASSERT(pssSegments[i].Image.FileOffset == 0);
843 ASSERT(pssSegments[i].RawLength.QuadPart == 0);
844 }
845
846 ASSERT(Intsafe_CanAddLong64(pssSegments[i].Image.FileOffset, pssSegments[i].RawLength.QuadPart));
847
848 nCharacteristics = pishSectionHeaders[i].Characteristics;
849
850 /* no explicit protection */
851 if((nCharacteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)) == 0)
852 {
853 if(nCharacteristics & IMAGE_SCN_CNT_CODE)
854 nCharacteristics |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;
855
856 if(nCharacteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
857 nCharacteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
858
859 if(nCharacteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
860 nCharacteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
861 }
862
863 /* see table above */
864 pssSegments[i].Protection = SectionCharacteristicsToProtect[nCharacteristics >> 28];
865 pssSegments[i].WriteCopy = !(nCharacteristics & IMAGE_SCN_MEM_SHARED);
866
867 if(pishSectionHeaders[i].Misc.VirtualSize == 0)
868 pssSegments[i].Length.QuadPart = pishSectionHeaders[i].SizeOfRawData;
869 else
870 pssSegments[i].Length.QuadPart = pishSectionHeaders[i].Misc.VirtualSize;
871
872 AlignedLength = ALIGN_UP_BY(pssSegments[i].Length.LowPart, nSectionAlignment);
873 if(AlignedLength < pssSegments[i].Length.LowPart)
874 DIE(("Cannot align the virtual size of section %u\n", i));
875
876 pssSegments[i].Length.LowPart = AlignedLength;
877
878 if(pssSegments[i].Length.QuadPart == 0)
879 DIE(("Virtual size of section %u is null\n", i));
880
881 pssSegments[i].Image.VirtualAddress = pishSectionHeaders[i].VirtualAddress;
882 pssSegments[i].Image.Characteristics = pishSectionHeaders[i].Characteristics;
883
884 /* ensure the memory image is no larger than 4GB */
885 nPrevVirtualEndOfSegment = (ULONG_PTR)(pssSegments[i].Image.VirtualAddress + pssSegments[i].Length.QuadPart);
886 if (nPrevVirtualEndOfSegment < pssSegments[i].Image.VirtualAddress)
887 DIE(("The image is too large\n"));
888 }
889
890 if(nSectionAlignment >= PAGE_SIZE)
892
893 /* Success */
894 nStatus = STATUS_SUCCESS;// STATUS_ROS_EXEFMT_LOADED_FORMAT | EXEFMT_LOADED_PE32;
895
896l_Return:
897 if(pBuffer)
899
900 return nStatus;
901}
902
903/*
904 * FUNCTION: Waits in kernel mode indefinitely for a file object lock.
905 * ARGUMENTS: PFILE_OBJECT to wait for.
906 * RETURNS: Status of the wait.
907 */
910{
911 return STATUS_SUCCESS;
912 //return KeWaitForSingleObject(&File->Lock, 0, KernelMode, FALSE, NULL);
913}
914
915
916
917VOID
918NTAPI
920{
924 SWAPENTRY SavedSwapEntry;
926
927 Page = 0;
928
930
931 Length = PAGE_ROUND_UP(Segment->Length.QuadPart);
932 for (Offset.QuadPart = 0; Offset.QuadPart < Length; Offset.QuadPart += PAGE_SIZE)
933 {
935 if (Entry)
936 {
939 {
941 }
942 else
943 {
945 SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
946 if (SavedSwapEntry != 0)
947 {
949 MmFreeSwapPage(SavedSwapEntry);
950 }
952 }
953 }
954 }
955
957}
958
959static
960VOID
961NTAPI
963{
966
968
970
972
973 /* This must be either a valid entry or nothing */
975
976 /* There should be no reference anymore */
978
980 /* If there is a page, this must be because it's still dirty */
981 ASSERT(Page != 0);
982
983 /* Write the page */
984 if (IS_DIRTY_SSE(Entry))
985 MiWritePage(Segment, Offset->QuadPart, Page);
986
988}
989
995VOID
996NTAPI
997MmDereferenceSegmentWithLock(
1000{
1001 /* Lock the PFN lock because we mess around with SectionObjectPointers */
1002 if (OldIrql == MM_NOIRQL)
1003 {
1004 OldIrql = MiAcquirePfnLock();
1005 }
1006
1007 if (InterlockedDecrement64(Segment->ReferenceCount) > 0)
1008 {
1009 /* Nothing to do yet */
1010 MiReleasePfnLock(OldIrql);
1011 return;
1012 }
1013
1014 *Segment->Flags |= MM_SEGMENT_INDELETE;
1015
1016 /* Flush the segment */
1017 if (*Segment->Flags & MM_DATAFILE_SEGMENT)
1018 {
1019 MiReleasePfnLock(OldIrql);
1020 /* Free the page table. This will flush any remaining dirty data */
1022
1023 OldIrql = MiAcquirePfnLock();
1024 /* Delete the pointer on the file */
1025 ASSERT(Segment->FileObject->SectionObjectPointer->DataSectionObject == Segment);
1026 Segment->FileObject->SectionObjectPointer->DataSectionObject = NULL;
1027 MiReleasePfnLock(OldIrql);
1028 ObDereferenceObject(Segment->FileObject);
1029
1031 }
1032 else
1033 {
1034 /* Most grotesque thing ever */
1035 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = CONTAINING_RECORD(Segment->ReferenceCount, MM_IMAGE_SECTION_OBJECT, RefCount);
1036 PMM_SECTION_SEGMENT SectionSegments;
1037 ULONG NrSegments;
1038 ULONG i;
1039
1040 /* Delete the pointer on the file */
1041 ASSERT(ImageSectionObject->FileObject->SectionObjectPointer->ImageSectionObject == ImageSectionObject);
1042 ImageSectionObject->FileObject->SectionObjectPointer->ImageSectionObject = NULL;
1043 MiReleasePfnLock(OldIrql);
1044
1045 ObDereferenceObject(ImageSectionObject->FileObject);
1046
1047 NrSegments = ImageSectionObject->NrSegments;
1048 SectionSegments = ImageSectionObject->Segments;
1049 for (i = 0; i < NrSegments; i++)
1050 {
1051 if (SectionSegments[i].Image.Characteristics & IMAGE_SCN_MEM_SHARED)
1052 {
1053 MmpFreePageFileSegment(&SectionSegments[i]);
1054 }
1055
1056 MmFreePageTablesSectionSegment(&SectionSegments[i], NULL);
1057 }
1058
1060 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
1061 }
1062}
1063
1064VOID
1065NTAPI
1068{
1070
1072 if (Entry == 0)
1073 {
1074 DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
1075 KeBugCheck(MEMORY_MANAGEMENT);
1076 }
1078 {
1079 DPRINT1("Maximum share count reached\n");
1080 KeBugCheck(MEMORY_MANAGEMENT);
1081 }
1083 {
1084 KeBugCheck(MEMORY_MANAGEMENT);
1085 }
1087}
1088
1089BOOLEAN
1090NTAPI
1094 BOOLEAN Dirty,
1096 ULONG_PTR *InEntry)
1097{
1100 BOOLEAN IsDataMap = BooleanFlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT);
1101 SWAPENTRY SwapEntry;
1102
1103 if (Entry == 0)
1104 {
1105 DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
1106 KeBugCheck(MEMORY_MANAGEMENT);
1107 }
1108 if (SHARE_COUNT_FROM_SSE(Entry) == 0)
1109 {
1110 DPRINT1("Zero share count for unshare (Seg %p Offset %x Page %x)\n", Segment, Offset->LowPart, PFN_FROM_SSE(Entry));
1111 KeBugCheck(MEMORY_MANAGEMENT);
1112 }
1114 {
1115 KeBugCheck(MEMORY_MANAGEMENT);
1116 }
1118 if (Dirty) Entry = DIRTY_SSE(Entry);
1119
1120 /* If we are paging-out, pruning the page for real will be taken care of in MmCheckDirtySegment */
1121 if ((SHARE_COUNT_FROM_SSE(Entry) > 0) || PageOut)
1122 {
1123 /* Update the page mapping in the segment and we're done */
1125 return FALSE;
1126 }
1127
1128 /* We are pruning the last mapping on this page. See if we can keep it a bit more. */
1129 ASSERT(!PageOut);
1130
1131 if (IsDataMap)
1132 {
1133 /* We can always keep memory in for data maps */
1135 return FALSE;
1136 }
1137
1138 if (!FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED))
1139 {
1140 ASSERT(Segment->WriteCopy);
1143 /* So this must have been a read-only page. Keep it ! */
1145 return FALSE;
1146 }
1147
1148 /*
1149 * So this is a page for a shared section of a DLL.
1150 * We can keep it if it is not dirty.
1151 */
1152 SwapEntry = MmGetSavedSwapEntryPage(Page);
1153 if ((SwapEntry == 0) && !IS_DIRTY_SSE(Entry))
1154 {
1156 return FALSE;
1157 }
1158
1159 /* No more processes are referencing this shared dirty page. Ditch it. */
1160 if (SwapEntry)
1161 {
1163 MmFreeSwapPage(SwapEntry);
1164 }
1167 return TRUE;
1168}
1169
1170static
1172MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
1173{
1175 KIRQL Irql;
1176 PVOID DestAddress;
1177
1179 DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
1180 if (DestAddress == NULL)
1181 {
1182 return STATUS_NO_MEMORY;
1183 }
1184 ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
1185 ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
1186 RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
1187 MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
1188 return STATUS_SUCCESS;
1189}
1190
1191static
1193NTAPI
1198 _In_opt_ PLARGE_INTEGER ValidDataLength,
1199 _In_ BOOLEAN SetDirty)
1200{
1201 /* Let's use a 64K granularity. */
1202 LONGLONG RangeStart, RangeEnd;
1204 PFILE_OBJECT FileObject = Segment->FileObject;
1205
1206 /* Calculate our range, aligned on 64K if possible. */
1207 Status = RtlLongLongAdd(Offset, Length, &RangeEnd);
1209 if (!NT_SUCCESS(Status))
1210 return Status;
1211
1212 /* If the file is not random access and we are not the page out thread
1213 * read a 64K Chunk. */
1215 && !FlagOn(FileObject->Flags, FO_RANDOM_ACCESS))
1216 {
1217 RangeStart = Offset - (Offset % _64K);
1218 if (RangeEnd % _64K)
1219 RangeEnd += _64K - (RangeEnd % _64K);
1220 }
1221 else
1222 {
1223 RangeStart = Offset - (Offset % PAGE_SIZE);
1224 if (RangeEnd % PAGE_SIZE)
1225 RangeEnd += PAGE_SIZE - (RangeEnd % PAGE_SIZE);
1226 }
1227
1228 /* Clamp if needed */
1229 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
1230 {
1231 if (RangeEnd > Segment->RawLength.QuadPart)
1232 RangeEnd = Segment->RawLength.QuadPart;
1233 }
1234
1235 /* Let's gooooooooo */
1236 for ( ; RangeStart < RangeEnd; RangeStart += _64K)
1237 {
1238 /* First take a look at where we miss pages */
1239 ULONG ToReadPageBits = 0;
1240 LONGLONG ChunkEnd = RangeStart + _64K;
1241
1242 if (ChunkEnd > RangeEnd)
1243 ChunkEnd = RangeEnd;
1244
1246 for (LONGLONG ChunkOffset = RangeStart; ChunkOffset < ChunkEnd; ChunkOffset += PAGE_SIZE)
1247 {
1248 LARGE_INTEGER CurrentOffset;
1249
1250 CurrentOffset.QuadPart = ChunkOffset;
1252
1253 /* Let any pending read proceed */
1254 while (MM_IS_WAIT_PTE(Entry))
1255 {
1257
1259
1261 Entry = MmGetPageEntrySectionSegment(Segment, &CurrentOffset);
1262 }
1263
1264 if (Entry != 0)
1265 {
1266 /* Dirtify it if it's a resident page and we're asked to */
1267 if (SetDirty && !IS_SWAP_FROM_SSE(Entry))
1268 {
1270 }
1271 continue;
1272 }
1273
1274 ToReadPageBits |= 1UL << ((ChunkOffset - RangeStart) >> PAGE_SHIFT);
1275
1276 /* Put a wait entry here */
1277 Status = MmSetPageEntrySectionSegment(Segment, &CurrentOffset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
1278 if (!NT_SUCCESS(Status))
1279 {
1280 /* Failed, roll back! */
1281 DPRINT1("Failed to set wait entry for segment %p at offset %I64d\n", Segment, ChunkOffset);
1282 LARGE_INTEGER RollbackOffset;
1283 RollbackOffset.QuadPart = ChunkOffset;
1284 while (RollbackOffset.QuadPart > RangeStart)
1285 {
1286 RollbackOffset.QuadPart -= PAGE_SIZE;
1288 {
1290 }
1291 }
1292
1294 return Status;
1295 }
1297 }
1299
1300 if (ToReadPageBits == 0)
1301 {
1302 /* Nothing to do for this chunk */
1303 continue;
1304 }
1305
1306 /* Now perform the actual read */
1307 LONGLONG ChunkOffset = RangeStart;
1308 while (ChunkOffset < ChunkEnd)
1309 {
1310 /* Move forward if there is a hole */
1311 ULONG BitSet;
1312 if (!_BitScanForward(&BitSet, ToReadPageBits))
1313 {
1314 /* Nothing more to read */
1315 break;
1316 }
1317 ToReadPageBits >>= BitSet;
1318 ChunkOffset += BitSet * PAGE_SIZE;
1319 ASSERT(ChunkOffset < ChunkEnd);
1320
1321 /* Get the range we have to read */
1322 _BitScanForward(&BitSet, ~ToReadPageBits);
1323 ULONG ReadLength = BitSet * PAGE_SIZE;
1324
1326
1327 /* Clamp (This is for image mappings */
1328 if ((ChunkOffset + ReadLength) > ChunkEnd)
1329 ReadLength = ChunkEnd - ChunkOffset;
1330
1331 ASSERT(ReadLength != 0);
1332
1333 /* Allocate a MDL */
1335 if (!Mdl)
1336 {
1337 /* Damn. Roll-back. */
1339 while (ChunkOffset < ChunkEnd)
1340 {
1341 if (ToReadPageBits & 1)
1342 {
1343 LARGE_INTEGER CurrentOffset;
1344 CurrentOffset.QuadPart = ChunkOffset;
1346 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, 0);
1347 }
1348 ToReadPageBits >>= 1;
1349 ChunkOffset += PAGE_SIZE;
1350 }
1353 }
1354
1355 /* Get our pages */
1358 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1359 {
1361 if (!NT_SUCCESS(Status))
1362 {
1363 /* Damn. Roll-back. */
1364 for (UINT j = 0; j < i; j++)
1366 goto Failed;
1367 }
1368 }
1369
1370 Mdl->MdlFlags |= MDL_PAGES_LOCKED | MDL_IO_PAGE_READ;
1371
1373 FileOffset.QuadPart = Segment->Image.FileOffset + ChunkOffset;
1374
1375 /* Clamp to VDL */
1376 if (ValidDataLength && ((FileOffset.QuadPart + ReadLength) > ValidDataLength->QuadPart))
1377 {
1378 if (FileOffset.QuadPart > ValidDataLength->QuadPart)
1379 {
1380 /* Great, nothing to read. */
1381 goto AssignPagesToSegment;
1382 }
1383
1384 Mdl->Size = (FileOffset.QuadPart + ReadLength) - ValidDataLength->QuadPart;
1385 }
1386
1387 KEVENT Event;
1389
1390 /* Disable APCs */
1391 KIRQL OldIrql;
1393
1396 if (Status == STATUS_PENDING)
1397 {
1399 Status = Iosb.Status;
1400 }
1401
1402 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
1403 {
1404 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
1405 }
1406
1408
1410 {
1411 DPRINT1("Got STATUS_END_OF_FILE at offset %I64d for file %wZ.\n", FileOffset.QuadPart, &FileObject->FileName);
1413 }
1414
1415 if (!NT_SUCCESS(Status))
1416 {
1417 /* Damn. Roll back. */
1418 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1420
1421Failed:
1423 while (ChunkOffset < ChunkEnd)
1424 {
1425 if (ToReadPageBits & 1)
1426 {
1427 LARGE_INTEGER CurrentOffset;
1428 CurrentOffset.QuadPart = ChunkOffset;
1430 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, 0);
1431 }
1432 ToReadPageBits >>= 1;
1433 ChunkOffset += PAGE_SIZE;
1434 }
1436 IoFreeMdl(Mdl);;
1437 return Status;
1438 }
1439
1440AssignPagesToSegment:
1442
1443 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1444 {
1445 ULONG_PTR Entry = MAKE_SSE(Pages[i] << PAGE_SHIFT, 0);
1446 LARGE_INTEGER CurrentOffset;
1447 CurrentOffset.QuadPart = ChunkOffset + (i * PAGE_SIZE);
1448
1450
1451 if (SetDirty)
1453
1454 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, Entry);
1455 }
1456
1458
1459 IoFreeMdl(Mdl);
1460 ToReadPageBits >>= BitSet;
1461 ChunkOffset += BitSet * PAGE_SIZE;
1462 }
1463 }
1464
1465 return STATUS_SUCCESS;
1466}
1467
1468static VOID
1472 ULONG OldType,
1473 ULONG OldProtect,
1474 ULONG NewType,
1476{
1479 BOOLEAN DoCOW = FALSE;
1480 ULONG i;
1482
1485 Segment = MemoryArea->SectionData.Segment;
1487
1488 if ((Segment->WriteCopy) &&
1490 {
1491 DoCOW = TRUE;
1492 }
1493
1494 if (OldProtect != NewProtect)
1495 {
1496 for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
1497 {
1498 SWAPENTRY SwapEntry;
1499 PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
1501
1502 /* Wait for a wait entry to disappear */
1503 do
1504 {
1505 MmGetPageFileMapping(Process, Address, &SwapEntry);
1506 if (SwapEntry != MM_WAIT_ENTRY)
1507 break;
1513 }
1514 while (TRUE);
1515
1516 /*
1517 * If we doing COW for this segment then check if the page is
1518 * already private.
1519 */
1521 {
1525
1527 + MemoryArea->SectionData.ViewOffset;
1529 /*
1530 * An MM_WAIT_ENTRY is ok in this case... It'll just count as
1531 * IS_SWAP_FROM_SSE and we'll do the right thing.
1532 */
1534
1535 /* Choose protection based on what was requested */
1538 else
1540
1542 {
1544 }
1545 }
1546
1548 {
1550 Protect);
1551 }
1552 }
1553 }
1554
1556}
1557
1559NTAPI
1562 PVOID Address,
1564{
1570 ULONG_PTR Entry1;
1573 BOOLEAN HasSwapEntry;
1574 PVOID PAddress;
1576 SWAPENTRY SwapEntry;
1577
1578 ASSERT(Locked);
1579
1580 /*
1581 * There is a window between taking the page fault and locking the
1582 * address space when another thread could load the page so we check
1583 * that.
1584 */
1586 {
1587 return STATUS_SUCCESS;
1588 }
1589
1591 {
1593 }
1594
1595 /*
1596 * Check for the virtual memory area being deleted.
1597 */
1599 {
1600 return STATUS_UNSUCCESSFUL;
1601 }
1602
1603 PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
1604 Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
1605 + MemoryArea->SectionData.ViewOffset;
1606
1607 Segment = MemoryArea->SectionData.Segment;
1609 &MemoryArea->SectionData.RegionListHead,
1610 Address, NULL);
1611 ASSERT(Region != NULL);
1612
1613 /* Check for a NOACCESS mapping */
1614 if (Region->Protect & PAGE_NOACCESS)
1615 {
1617 }
1618
1619 if (Region->Protect & PAGE_GUARD)
1620 {
1621 /* Remove it */
1623 &MemoryArea->SectionData.RegionListHead,
1624 Address, PAGE_SIZE, Region->Type, Region->Protect & ~PAGE_GUARD,
1626
1627 if (!NT_SUCCESS(Status))
1628 {
1629 DPRINT1("Removing PAGE_GUARD protection failed : 0x%08x.\n", Status);
1630 }
1631
1633 }
1634
1635 HasSwapEntry = MmIsPageSwapEntry(Process, Address);
1636
1637 /* See if we should use a private page */
1638 if (HasSwapEntry)
1639 {
1640 SWAPENTRY DummyEntry;
1641
1642 MmGetPageFileMapping(Process, Address, &SwapEntry);
1643 if (SwapEntry == MM_WAIT_ENTRY)
1644 {
1649 }
1650
1652 if (Process) MI_SET_PROCESS2(Process->ImageFileName);
1653 if (!Process) MI_SET_PROCESS2("Kernel Section");
1655 if (!NT_SUCCESS(Status))
1656 {
1657 return STATUS_NO_MEMORY;
1658 }
1659
1660 /*
1661 * Must be private page we have swapped out.
1662 */
1663
1664 /*
1665 * Sanity check
1666 */
1668 ASSERT(DummyEntry == SwapEntry);
1669
1670 /* Tell everyone else we are serving the fault. */
1671 MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
1672
1674
1675 Status = MmReadFromSwapPage(SwapEntry, Page);
1676 if (!NT_SUCCESS(Status))
1677 {
1678 DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
1679 KeBugCheck(MEMORY_MANAGEMENT);
1680 }
1681
1683 MmDeletePageFileMapping(Process, PAddress, &DummyEntry);
1684 ASSERT(DummyEntry == MM_WAIT_ENTRY);
1685
1687 PAddress,
1688 Region->Protect,
1689 Page);
1690 if (!NT_SUCCESS(Status))
1691 {
1692 DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
1693 KeBugCheck(MEMORY_MANAGEMENT);
1694 return Status;
1695 }
1696
1697 /*
1698 * Store the swap entry for later use.
1699 */
1700 MmSetSavedSwapEntryPage(Page, SwapEntry);
1701
1702 /*
1703 * Add the page to the process's working set
1704 */
1706 /*
1707 * Finish the operation
1708 */
1709 DPRINT("Address 0x%p\n", Address);
1710 return STATUS_SUCCESS;
1711 }
1712
1713 /*
1714 * Lock the segment
1715 */
1717
1718 /*
1719 * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
1720 */
1721 if ((*Segment->Flags) & MM_PHYSICALMEMORY_SEGMENT)
1722 {
1724 /*
1725 * Just map the desired physical page
1726 */
1727 Page = (PFN_NUMBER)(Offset.QuadPart >> PAGE_SHIFT);
1729 PAddress,
1730 Region->Protect,
1731 Page);
1732 if (!NT_SUCCESS(Status))
1733 {
1734 DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
1735 KeBugCheck(MEMORY_MANAGEMENT);
1736 return Status;
1737 }
1738
1739 /*
1740 * Cleanup and release locks
1741 */
1742 DPRINT("Address 0x%p\n", Address);
1743 return STATUS_SUCCESS;
1744 }
1745
1746 /*
1747 * Check if this page needs to be mapped COW
1748 */
1749 if ((Segment->WriteCopy) &&
1750 (Region->Protect == PAGE_READWRITE || Region->Protect == PAGE_EXECUTE_READWRITE))
1751 {
1753 }
1754 else
1755 {
1756 Attributes = Region->Protect;
1757 }
1758
1759
1760 /*
1761 * Get the entry corresponding to the offset within the section
1762 */
1764 if (Entry == 0)
1765 {
1766 /*
1767 * If the entry is zero, then we need to load the page.
1768 */
1769 if ((Offset.QuadPart >= (LONGLONG)PAGE_ROUND_UP(Segment->RawLength.QuadPart)) && (MemoryArea->VadNode.u.VadFlags.VadType == VadImageMap))
1770 {
1771 /* We are beyond the data which is on file. Just get a new page. */
1773 if (Process) MI_SET_PROCESS2(Process->ImageFileName);
1774 if (!Process) MI_SET_PROCESS2("Kernel Section");
1776 if (!NT_SUCCESS(Status))
1777 {
1779 return STATUS_NO_MEMORY;
1780 }
1783
1785 if (!NT_SUCCESS(Status))
1786 {
1787 DPRINT1("Unable to create virtual mapping\n");
1788 KeBugCheck(MEMORY_MANAGEMENT);
1789 }
1790 ASSERT(MmIsPagePresent(Process, PAddress));
1791 if (Process)
1793
1794 DPRINT("Address 0x%p\n", Address);
1795 return STATUS_SUCCESS;
1796 }
1797
1800
1801 /* The data must be paged in. Lock the file, so that the VDL doesn't get updated behind us. */
1803
1804 PFSRTL_COMMON_FCB_HEADER FcbHeader = Segment->FileObject->FsContext;
1805
1807
1808 FsRtlReleaseFile(Segment->FileObject);
1809
1810 /* Lock address space again */
1812 if (!NT_SUCCESS(Status))
1813 {
1814 if (Status == STATUS_NO_MEMORY)
1815 {
1816 return Status;
1817 }
1818 /* Damn */
1819 DPRINT1("Failed to page data in!\n");
1820 return STATUS_IN_PAGE_ERROR;
1821 }
1822
1823 /* Everything went fine. Restart the operation */
1825 }
1826 else if (IS_SWAP_FROM_SSE(Entry))
1827 {
1828 SWAPENTRY SwapEntry;
1829
1830 SwapEntry = SWAPENTRY_FROM_SSE(Entry);
1831
1832 /* See if a page op is running on this segment. */
1833 if (SwapEntry == MM_WAIT_ENTRY)
1834 {
1840 }
1841
1843 if (!NT_SUCCESS(Status))
1844 {
1846 return STATUS_NO_MEMORY;
1847 }
1848
1849 /*
1850 * Release all our locks and read in the page from disk
1851 */
1854
1856
1857 Status = MmReadFromSwapPage(SwapEntry, Page);
1858 if (!NT_SUCCESS(Status))
1859 {
1860 KeBugCheck(MEMORY_MANAGEMENT);
1861 }
1862
1863 /*
1864 * Relock the address space and segment
1865 */
1868
1869 /*
1870 * Check the entry. No one should change the status of a page
1871 * that has a pending page-in.
1872 */
1874 if (Entry1 != MAKE_SWAP_SSE(MM_WAIT_ENTRY))
1875 {
1876 DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
1877 KeBugCheck(MEMORY_MANAGEMENT);
1878 }
1879
1880 /*
1881 * Save the swap entry.
1882 */
1883 MmSetSavedSwapEntryPage(Page, SwapEntry);
1884
1885 /* Map the page into the process address space */
1887 PAddress,
1888 Attributes,
1889 Page);
1890 if (!NT_SUCCESS(Status))
1891 {
1892 DPRINT1("Unable to create virtual mapping\n");
1893 KeBugCheck(MEMORY_MANAGEMENT);
1894 }
1895 if (Process)
1897
1898 /*
1899 * Mark the offset within the section as having valid, in-memory
1900 * data
1901 */
1902 Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
1905
1906 DPRINT("Address 0x%p\n", Address);
1907 return STATUS_SUCCESS;
1908 }
1909 else
1910 {
1911 /* We already have a page on this section offset. Map it into the process address space. */
1913
1915 PAddress,
1916 Attributes,
1917 Page);
1918 if (!NT_SUCCESS(Status))
1919 {
1920 DPRINT1("Unable to create virtual mapping\n");
1921 KeBugCheck(MEMORY_MANAGEMENT);
1922 }
1923
1924 if (Process)
1926
1927 /* Take a reference on it */
1930
1931 DPRINT("Address 0x%p\n", Address);
1932 return STATUS_SUCCESS;
1933 }
1934}
1935
1937NTAPI
1940 PVOID Address,
1942{
1944 PFN_NUMBER OldPage;
1945 PFN_NUMBER NewPage;
1946 PFN_NUMBER UnmappedPage;
1947 PVOID PAddress;
1952 BOOLEAN Cow = FALSE;
1954 BOOLEAN Unmapped;
1956
1957 DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
1958
1959 /* Get the region for this address */
1961 &MemoryArea->SectionData.RegionListHead,
1962 Address, NULL);
1963 ASSERT(Region != NULL);
1964 if (!(Region->Protect & PAGE_IS_WRITABLE))
1966
1967 /* Make sure we have a page mapping for this address. */
1969 {
1971 if (!NT_SUCCESS(Status))
1972 {
1973 /* This is invalid access ! */
1974 return Status;
1975 }
1976 }
1977
1978 /*
1979 * Check if the page has already been set readwrite
1980 */
1982 {
1983 DPRINT("Address 0x%p\n", Address);
1984 return STATUS_SUCCESS;
1985 }
1986
1987 /* Check if we are doing Copy-On-Write */
1988 Segment = MemoryArea->SectionData.Segment;
1989 Cow = Segment->WriteCopy || (Region->Protect & PAGE_IS_WRITECOPY);
1990
1991 if (!Cow)
1992 {
1993 /* Simply update page protection and we're done */
1995 return STATUS_SUCCESS;
1996 }
1997
1998 /* Calculate the new protection & check if we should update the region */
1999 NewProtect = Region->Protect;
2001 {
2002 NewProtect &= ~PAGE_IS_WRITECOPY;
2003 if (Region->Protect & PAGE_IS_EXECUTABLE)
2005 else
2008 &MemoryArea->SectionData.RegionListHead,
2011 }
2012
2013 /*
2014 * Find the offset of the page
2015 */
2016 PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
2017 Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
2018 + MemoryArea->SectionData.ViewOffset;
2019
2020 /* Get the page mapping this section offset. */
2023
2024 /* Get the current page mapping for the process */
2025 ASSERT(MmIsPagePresent(Process, PAddress));
2026 OldPage = MmGetPfnForProcess(Process, PAddress);
2027 ASSERT(OldPage != 0);
2028
2029 if (IS_SWAP_FROM_SSE(Entry) ||
2030 PFN_FROM_SSE(Entry) != OldPage)
2031 {
2033 /* This is a private page. We must only change the page protection. */
2035 return STATUS_SUCCESS;
2036 }
2037
2038 /*
2039 * Allocate a page
2040 */
2042 if (!NT_SUCCESS(Status))
2043 {
2045 return STATUS_NO_MEMORY;
2046 }
2047
2048 /*
2049 * Copy the old page
2050 */
2051 NT_VERIFY(NT_SUCCESS(MiCopyFromUserPage(NewPage, PAddress)));
2052
2053 /*
2054 * Unshare the old page.
2055 */
2056 DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
2057 Unmapped = MmDeleteVirtualMapping(Process, PAddress, NULL, &UnmappedPage);
2058 if (!Unmapped || (UnmappedPage != OldPage))
2059 {
2060 /* Uh , we had a page just before, but suddenly it changes. Someone corrupted us. */
2061 KeBugCheckEx(MEMORY_MANAGEMENT,
2063 (ULONG_PTR)PAddress,
2064 (ULONG_PTR)__FILE__,
2065 __LINE__);
2066 }
2067
2068 if (Process)
2069 MmDeleteRmap(OldPage, Process, PAddress);
2072
2073 /*
2074 * Set the PTE to point to the new page
2075 */
2076 if (!NT_SUCCESS(MmCreateVirtualMapping(Process, PAddress, NewProtect, NewPage)))
2077 {
2078 DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
2079 KeBugCheck(MEMORY_MANAGEMENT);
2080 }
2081
2082 if (Process)
2083 MmInsertRmap(NewPage, Process, PAddress);
2084
2085 DPRINT("Address 0x%p\n", Address);
2086 return STATUS_SUCCESS;
2087}
2088
2090NTAPI
2094 SIZE_T Length,
2095 ULONG Protect,
2096 PULONG OldProtect)
2097{
2100 ULONG_PTR MaxLength;
2101
2103
2105 {
2106 return STATUS_UNSUCCESSFUL;
2107 }
2108
2110 if (Length > MaxLength)
2111 Length = (ULONG)MaxLength;
2112
2114 &MemoryArea->SectionData.RegionListHead,
2115 BaseAddress, NULL);
2116 ASSERT(Region != NULL);
2117
2118 if ((MemoryArea->Flags & SEC_NO_CHANGE) &&
2119 Region->Protect != Protect)
2120 {
2122 }
2123
2124 if (OldProtect != NULL)
2125 *OldProtect = Region->Protect;
2127 &MemoryArea->SectionData.RegionListHead,
2130
2131 return Status;
2132}
2133
2136 PVOID Address,
2139{
2141 PVOID RegionBaseAddress;
2143
2145 &MemoryArea->SectionData.RegionListHead,
2146 Address, &RegionBaseAddress);
2147 if (Region == NULL)
2148 {
2149 return STATUS_UNSUCCESSFUL;
2150 }
2151
2153 {
2154 Segment = MemoryArea->SectionData.Segment;
2155 Info->AllocationBase = (PUCHAR)MA_GetStartingAddress(MemoryArea) - Segment->Image.VirtualAddress;
2156 Info->Type = MEM_IMAGE;
2157 }
2158 else
2159 {
2160 Info->AllocationBase = (PVOID)MA_GetStartingAddress(MemoryArea);
2161 Info->Type = MEM_MAPPED;
2162 }
2163 Info->BaseAddress = RegionBaseAddress;
2165 Info->RegionSize = Region->Length;
2166 Info->State = MEM_COMMIT;
2167 Info->Protect = Region->Protect;
2168
2170 return STATUS_SUCCESS;
2171}
2172
2173VOID NTAPI
2175{
2176 PSECTION Section = ObjectBody;
2177
2178 /* Check if it's an ARM3, or ReactOS section */
2179 if (!MiIsRosSectionObject(Section))
2180 {
2181 MiDeleteARM3Section(ObjectBody);
2182 return;
2183 }
2184
2185 DPRINT("MmpDeleteSection(ObjectBody %p)\n", ObjectBody);
2186 if (Section->u.Flags.Image)
2187 {
2188 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)Section->Segment;
2189
2190 /*
2191 * NOTE: Section->ImageSection can be NULL for short time
2192 * during the section creating. If we fail for some reason
2193 * until the image section is properly initialized we shouldn't
2194 * process further here.
2195 */
2196 if (Section->Segment == NULL)
2197 return;
2198
2199 KIRQL OldIrql = MiAcquirePfnLock();
2200 ImageSectionObject->SectionCount--;
2201
2202 /* We just dereference the first segment */
2203 ASSERT(ImageSectionObject->RefCount > 0);
2204 /* MmDereferenceSegmentWithLock releases PFN lock */
2205 MmDereferenceSegmentWithLock(ImageSectionObject->Segments, OldIrql);
2206 }
2207 else
2208 {
2210
2211 /*
2212 * NOTE: Section->Segment can be NULL for short time
2213 * during the section creating.
2214 */
2215 if (Segment == NULL)
2216 return;
2217
2218 KIRQL OldIrql = MiAcquirePfnLock();
2219 Segment->SectionCount--;
2220
2221 /* MmDereferenceSegmentWithLock releases PFN lock */
2222 MmDereferenceSegmentWithLock(Segment, OldIrql);
2223 }
2224}
2225
2226VOID NTAPI
2228 IN PVOID Object,
2231 IN ULONG SystemHandleCount)
2232{
2233 DPRINT("MmpCloseSection(OB %p, HC %lu)\n", Object, ProcessHandleCount);
2234}
2235
2236CODE_SEG("INIT")
2238NTAPI
2240{
2241 PSECTION PhysSection;
2244 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
2245 LARGE_INTEGER SectionSize;
2246 HANDLE Handle;
2248
2249 /*
2250 * Create the section mapping physical memory
2251 */
2254 &Name,
2256 NULL,
2257 NULL);
2258 /*
2259 * Create the Object
2260 */
2263 &Obj,
2265 NULL,
2266 sizeof(*PhysSection),
2267 0,
2268 0,
2269 (PVOID*)&PhysSection);
2270 if (!NT_SUCCESS(Status))
2271 {
2272 DPRINT1("MmCreatePhysicalMemorySection: failed to create object (0x%lx)\n", Status);
2273 return Status;
2274 }
2275
2276 /*
2277 * Initialize it
2278 */
2279 RtlZeroMemory(PhysSection, sizeof(*PhysSection));
2280
2281 /* Mark this as a "ROS Section" */
2282 PhysSection->u.Flags.filler = 1;
2284 PhysSection->u.Flags.PhysicalMemory = 1;
2285 PhysSection->SizeOfSection = SectionSize;
2288 if (Segment == NULL)
2289 {
2290 ObDereferenceObject(PhysSection);
2291 return STATUS_NO_MEMORY;
2292 }
2294 PhysSection->Segment = (PSEGMENT)Segment;
2295 Segment->RefCount = 1;
2296
2297 Segment->ReferenceCount = &Segment->RefCount;
2298 Segment->Flags = &Segment->SegFlags;
2299
2301 Segment->Image.FileOffset = 0;
2302 Segment->Protection = PAGE_EXECUTE_READWRITE;
2303 Segment->RawLength = SectionSize;
2304 Segment->Length = SectionSize;
2306 Segment->WriteCopy = FALSE;
2307 Segment->Image.VirtualAddress = 0;
2308 Segment->Image.Characteristics = 0;
2310
2311 Status = ObInsertObject(PhysSection,
2312 NULL,
2314 0,
2315 NULL,
2316 &Handle);
2317 if (!NT_SUCCESS(Status))
2318 {
2319 /* Note: ObInsertObject dereferences PhysSection on failure */
2320 return Status;
2321 }
2323
2324 return STATUS_SUCCESS;
2325}
2326
2327CODE_SEG("INIT")
2329NTAPI
2331{
2332 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
2334
2335 DPRINT("Creating Section Object Type\n");
2336
2337 /* Initialize the section based root */
2340
2341 /* Initialize the Section object type */
2342 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
2343 RtlInitUnicodeString(&Name, L"Section");
2344 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
2345 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(SECTION);
2346 ObjectTypeInitializer.PoolType = PagedPool;
2347 ObjectTypeInitializer.UseDefaultObject = TRUE;
2348 ObjectTypeInitializer.GenericMapping = MmpSectionMapping;
2349 ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
2350 ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
2351 ObjectTypeInitializer.ValidAccessMask = SECTION_ALL_ACCESS;
2352 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
2353 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &MmSectionObjectType);
2354
2356
2357 return STATUS_SUCCESS;
2358}
2359
2360static
2362NTAPI
2366 PLARGE_INTEGER UMaximumSize,
2370 BOOLEAN GotFileHandle)
2371/*
2372 * Create a section backed by a data file
2373 */
2374{
2375 PSECTION Section;
2379 KIRQL OldIrql;
2380
2381 /*
2382 * Create the section
2383 */
2388 NULL,
2389 sizeof(*Section),
2390 0,
2391 0,
2392 (PVOID*)&Section);
2393 if (!NT_SUCCESS(Status))
2394 {
2395 return Status;
2396 }
2397 /*
2398 * Initialize it
2399 */
2400 RtlZeroMemory(Section, sizeof(*Section));
2401
2402 /* Mark this as a "ROS" section */
2403 Section->u.Flags.filler = 1;
2405 Section->u.Flags.File = 1;
2406
2408 Section->u.Flags.NoChange = 1;
2409
2410 if (!GotFileHandle)
2411 {
2412 ASSERT(UMaximumSize != NULL);
2413 // ASSERT(UMaximumSize->QuadPart != 0);
2414 MaximumSize = *UMaximumSize;
2415 }
2416 else
2417 {
2420 if (!NT_SUCCESS(Status))
2421 {
2422 ObDereferenceObject(Section);
2423 return Status;
2424 }
2425
2426 /*
2427 * FIXME: Revise this once a locking order for file size changes is
2428 * decided
2429 */
2430 if ((UMaximumSize != NULL) && (UMaximumSize->QuadPart != 0))
2431 {
2432 MaximumSize = *UMaximumSize;
2433 }
2434 else
2435 {
2437 /* Mapping zero-sized files isn't allowed. */
2438 if (MaximumSize.QuadPart == 0)
2439 {
2440 ObDereferenceObject(Section);
2442 }
2443 }
2444
2445 if (MaximumSize.QuadPart > FileSize.QuadPart)
2446 {
2449 sizeof(LARGE_INTEGER),
2450 &MaximumSize);
2451 if (!NT_SUCCESS(Status))
2452 {
2453 ObDereferenceObject(Section);
2455 }
2456 }
2457 }
2458
2459 if (FileObject->SectionObjectPointer == NULL)
2460 {
2461 ObDereferenceObject(Section);
2463 }
2464
2465 /*
2466 * Lock the file
2467 */
2469 if (Status != STATUS_SUCCESS)
2470 {
2471 ObDereferenceObject(Section);
2472 return Status;
2473 }
2474
2475 /* Lock the PFN lock while messing with Section Object pointers */
2476grab_segment:
2477 OldIrql = MiAcquirePfnLock();
2478 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2479
2480 while (Segment && (Segment->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
2481 {
2482 MiReleasePfnLock(OldIrql);
2484 OldIrql = MiAcquirePfnLock();
2485 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2486 }
2487
2488 /*
2489 * If this file hasn't been mapped as a data file before then allocate a
2490 * section segment to describe the data file mapping
2491 */
2492 if (Segment == NULL)
2493 {
2494 /* Release the lock. ExAllocatePoolWithTag might acquire it */
2495 MiReleasePfnLock(OldIrql);
2496
2499 if (Segment == NULL)
2500 {
2501 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2502 ObDereferenceObject(Section);
2503 return STATUS_NO_MEMORY;
2504 }
2505
2506 /* We are creating it */
2507 RtlZeroMemory(Segment, sizeof(*Segment));
2509 Segment->RefCount = 1;
2510
2511 /* Acquire lock again */
2512 OldIrql = MiAcquirePfnLock();
2513
2514 if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
2515 {
2516 /* Well that's bad luck. Restart it all over */
2517 MiReleasePfnLock(OldIrql);
2519 goto grab_segment;
2520 }
2521
2522 FileObject->SectionObjectPointer->DataSectionObject = Segment;
2523
2524 /* We're safe to release the lock now */
2525 MiReleasePfnLock(OldIrql);
2526
2527 Section->Segment = (PSEGMENT)Segment;
2528
2529 /* Self-referencing segment */
2530 Segment->Flags = &Segment->SegFlags;
2531 Segment->ReferenceCount = &Segment->RefCount;
2532
2533 Segment->SectionCount = 1;
2534
2536 Segment->FileObject = FileObject;
2538
2539 Segment->Image.FileOffset = 0;
2540 Segment->Protection = SectionPageProtection;
2541
2542 Segment->Image.Characteristics = 0;
2545 {
2546 Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0;
2547 }
2548 else
2549 {
2550 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2551 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2552 }
2553 Segment->Image.VirtualAddress = 0;
2555
2556 /* We're good to use it now */
2557 OldIrql = MiAcquirePfnLock();
2558 Segment->SegFlags &= ~MM_SEGMENT_INCREATE;
2559 MiReleasePfnLock(OldIrql);
2560 }
2561 else
2562 {
2563 Section->Segment = (PSEGMENT)Segment;
2564 InterlockedIncrement64(&Segment->RefCount);
2565 InterlockedIncrementUL(&Segment->SectionCount);
2566
2567 MiReleasePfnLock(OldIrql);
2568
2570
2571 if (MaximumSize.QuadPart > Segment->RawLength.QuadPart &&
2573 {
2574 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2575 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2576 }
2577
2579 }
2580 Section->SizeOfSection = MaximumSize;
2581
2582 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2583 *SectionObject = Section;
2584 return STATUS_SUCCESS;
2585}
2586
2587/*
2588 TODO: not that great (declaring loaders statically, having to declare all of
2589 them, having to keep them extern, etc.), will fix in the future
2590*/
2592(
2593 IN CONST VOID * FileHeader,
2594 IN SIZE_T FileHeaderSize,
2595 IN PVOID File,
2596 OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2598 IN PEXEFMT_CB_READ_FILE ReadFileCb,
2599 IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
2600);
2601
2603(
2604 IN CONST VOID * FileHeader,
2605 IN SIZE_T FileHeaderSize,
2606 IN PVOID File,
2607 OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2609 IN PEXEFMT_CB_READ_FILE ReadFileCb,
2610 IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
2611);
2612
2614{
2616#ifdef __ELF
2618#endif
2619};
2620
2621static
2623NTAPI
2625{
2626 SIZE_T SizeOfSegments;
2627 PMM_SECTION_SEGMENT Segments;
2628
2629 /* TODO: check for integer overflow */
2630 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * NrSegments;
2631
2633 SizeOfSegments,
2635
2636 if(Segments)
2637 RtlZeroMemory(Segments, SizeOfSegments);
2638
2639 return Segments;
2640}
2641static
2643NTAPI
2646 IN ULONG Length,
2647 OUT PVOID * Data,
2648 OUT PVOID * AllocBase,
2649 OUT PULONG ReadSize)
2650{
2653 ULONG AdjustOffset;
2654 ULONG OffsetAdjustment;
2656 ULONG UsedSize;
2657 PVOID Buffer;
2660
2662
2663 if(Length == 0)
2664 {
2665 KeBugCheck(MEMORY_MANAGEMENT);
2666 }
2667
2668 FileOffset = *Offset;
2669
2670 /* Negative/special offset: it cannot be used in this context */
2671 if(FileOffset.u.HighPart < 0)
2672 {
2673 KeBugCheck(MEMORY_MANAGEMENT);
2674 }
2675
2676 AdjustOffset = PAGE_ROUND_DOWN(FileOffset.u.LowPart);
2677 OffsetAdjustment = FileOffset.u.LowPart - AdjustOffset;
2678 FileOffset.u.LowPart = AdjustOffset;
2679
2680 BufferSize = Length + OffsetAdjustment;
2682
2683 /*
2684 * It's ok to use paged pool, because this is a temporary buffer only used in
2685 * the loading of executables. The assumption is that MmCreateSection is
2686 * always called at low IRQLs and that these buffers don't survive a brief
2687 * initialization phase
2688 */
2690 if (!Buffer)
2691 {
2693 }
2694
2696
2697 UsedSize = (ULONG)Iosb.Information;
2698
2699 if(NT_SUCCESS(Status) && UsedSize < OffsetAdjustment)
2700 {
2703 }
2704
2705 if(NT_SUCCESS(Status))
2706 {
2707 *Data = (PVOID)((ULONG_PTR)Buffer + OffsetAdjustment);
2708 *AllocBase = Buffer;
2709 *ReadSize = UsedSize - OffsetAdjustment;
2710 }
2711 else
2712 {
2713 ExFreePoolWithTag(Buffer, 'rXmM');
2714 }
2715
2716 return Status;
2717}
2718
2719#ifdef NASSERT
2720# define MmspAssertSegmentsSorted(OBJ_) ((void)0)
2721# define MmspAssertSegmentsNoOverlap(OBJ_) ((void)0)
2722# define MmspAssertSegmentsPageAligned(OBJ_) ((void)0)
2723#else
2724static
2725VOID
2726NTAPI
2728{
2729 ULONG i;
2730
2731 for( i = 1; i < ImageSectionObject->NrSegments; ++ i )
2732 {
2733 ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
2734 ImageSectionObject->Segments[i - 1].Image.VirtualAddress);
2735 }
2736}
2737
2738static
2739VOID
2740NTAPI
2742{
2743 ULONG i;
2744
2745 MmspAssertSegmentsSorted(ImageSectionObject);
2746
2747 for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2748 {
2749 ASSERT(ImageSectionObject->Segments[i].Length.QuadPart > 0);
2750
2751 if(i > 0)
2752 {
2753 ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
2754 (ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
2755 ImageSectionObject->Segments[i - 1].Length.QuadPart));
2756 }
2757 }
2758}
2759
2760static
2761VOID
2762NTAPI
2764{
2765 ULONG i;
2766
2767 for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2768 {
2769 ASSERT((ImageSectionObject->Segments[i].Image.VirtualAddress % PAGE_SIZE) == 0);
2770 ASSERT((ImageSectionObject->Segments[i].Length.QuadPart % PAGE_SIZE) == 0);
2771 }
2772}
2773#endif
2774
2775static
2776int
2777__cdecl
2779 const void * y)
2780{
2781 const MM_SECTION_SEGMENT *Segment1 = (const MM_SECTION_SEGMENT *)x;
2782 const MM_SECTION_SEGMENT *Segment2 = (const MM_SECTION_SEGMENT *)y;
2783
2784 if (Segment1->Image.VirtualAddress > Segment2->Image.VirtualAddress)
2785 return 1;
2786 else if (Segment1->Image.VirtualAddress < Segment2->Image.VirtualAddress)
2787 return -1;
2788 else
2789 return 0;
2790}
2791
2792/*
2793 * Ensures an image section's segments are sorted in memory
2794 */
2795static
2796VOID
2797NTAPI
2799 IN ULONG Flags)
2800{
2802 {
2803 MmspAssertSegmentsSorted(ImageSectionObject);
2804 }
2805 else
2806 {
2807 qsort(ImageSectionObject->Segments,
2808 ImageSectionObject->NrSegments,
2809 sizeof(ImageSectionObject->Segments[0]),
2811 }
2812}
2813
2814
2815/*
2816 * Ensures an image section's segments don't overlap in memory and don't have
2817 * gaps and don't have a null size. We let them map to overlapping file regions,
2818 * though - that's not necessarily an error
2819 */
2820static
2821BOOLEAN
2822NTAPI
2824(
2825 IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2826 IN ULONG Flags
2827)
2828{
2829 ULONG i;
2830
2832 {
2833 MmspAssertSegmentsNoOverlap(ImageSectionObject);
2834 return TRUE;
2835 }
2836
2837 ASSERT(ImageSectionObject->NrSegments >= 1);
2838
2839 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2840 {
2841 if(ImageSectionObject->Segments[i].Length.QuadPart == 0)
2842 {
2843 return FALSE;
2844 }
2845
2846 if(i > 0)
2847 {
2848 /*
2849 * TODO: relax the limitation on gaps. For example, gaps smaller than a
2850 * page could be OK (Windows seems to be OK with them), and larger gaps
2851 * could lead to image sections spanning several discontiguous regions
2852 * (NtMapViewOfSection could then refuse to map them, and they could
2853 * e.g. only be allowed as parameters to NtCreateProcess, like on UNIX)
2854 */
2855 if ((ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
2856 ImageSectionObject->Segments[i - 1].Length.QuadPart) !=
2857 ImageSectionObject->Segments[i].Image.VirtualAddress)
2858 {
2859 return FALSE;
2860 }
2861 }
2862 }
2863
2864 return TRUE;
2865}
2866
2867/*
2868 * Merges and pads an image section's segments until they all are page-aligned
2869 * and have a size that is a multiple of the page size
2870 */
2871static
2872BOOLEAN
2873NTAPI
2875(
2876 IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2877 IN ULONG Flags
2878)
2879{
2880 ULONG i;
2881 ULONG LastSegment;
2882 PMM_SECTION_SEGMENT EffectiveSegment;
2883
2885 {
2886 MmspAssertSegmentsPageAligned(ImageSectionObject);
2887 return TRUE;
2888 }
2889
2890 LastSegment = 0;
2891 EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
2892
2893 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2894 {
2895 /*
2896 * The first segment requires special handling
2897 */
2898 if (i == 0)
2899 {
2901 ULONG_PTR VirtualOffset;
2902
2903 VirtualAddress = EffectiveSegment->Image.VirtualAddress;
2904
2905 /* Round down the virtual address to the nearest page */
2906 EffectiveSegment->Image.VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
2907
2908 /* Round up the virtual size to the nearest page */
2909 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length.QuadPart) -
2910 EffectiveSegment->Image.VirtualAddress;
2911
2912 /* Adjust the raw address and size */
2913 VirtualOffset = VirtualAddress - EffectiveSegment->Image.VirtualAddress;
2914
2915 if (EffectiveSegment->Image.FileOffset < VirtualOffset)
2916 {
2917 return FALSE;
2918 }
2919
2920 /*
2921 * Garbage in, garbage out: unaligned base addresses make the file
2922 * offset point in curious and odd places, but that's what we were
2923 * asked for
2924 */
2925 EffectiveSegment->Image.FileOffset -= VirtualOffset;
2926 EffectiveSegment->RawLength.QuadPart += VirtualOffset;
2927 }
2928 else
2929 {
2930 PMM_SECTION_SEGMENT Segment = &ImageSectionObject->Segments[i];
2931 ULONG_PTR EndOfEffectiveSegment;
2932
2933 EndOfEffectiveSegment = (ULONG_PTR)(EffectiveSegment->Image.VirtualAddress + EffectiveSegment->Length.QuadPart);
2934 ASSERT((EndOfEffectiveSegment % PAGE_SIZE) == 0);
2935
2936 /*
2937 * The current segment begins exactly where the current effective
2938 * segment ended, therefore beginning a new effective segment
2939 */
2940 if (EndOfEffectiveSegment == Segment->Image.VirtualAddress)
2941 {
2942 LastSegment ++;
2943 ASSERT(LastSegment <= i);
2944 ASSERT(LastSegment < ImageSectionObject->NrSegments);
2945
2946 EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
2947
2948 if (LastSegment != i)
2949 {
2950 /*
2951 * Copy the current segment. If necessary, the effective segment
2952 * will be expanded later
2953 */
2954 *EffectiveSegment = *Segment;
2955 }
2956
2957 /*
2958 * Page-align the virtual size. We know for sure the virtual address
2959 * already is
2960 */
2961 ASSERT((EffectiveSegment->Image.VirtualAddress % PAGE_SIZE) == 0);
2962 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(EffectiveSegment->Length.QuadPart);
2963 }
2964 /*
2965 * The current segment is still part of the current effective segment:
2966 * extend the effective segment to reflect this
2967 */
2968 else if (EndOfEffectiveSegment > Segment->Image.VirtualAddress)
2969 {
2970 static const ULONG FlagsToProtection[16] =
2971 {
2988 };
2989
2990 unsigned ProtectionFlags;
2991
2992 /*
2993 * Extend the file size
2994 */
2995
2996 /* Unaligned segments must be contiguous within the file */
2997 if (Segment->Image.FileOffset != (EffectiveSegment->Image.FileOffset +
2998 EffectiveSegment->RawLength.QuadPart))
2999 {
3000 return FALSE;
3001 }
3002
3003 EffectiveSegment->RawLength.QuadPart += Segment->RawLength.QuadPart;
3004
3005 /*
3006 * Extend the virtual size
3007 */
3008 ASSERT(PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) >= EndOfEffectiveSegment);
3009
3010 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) -
3011 EffectiveSegment->Image.VirtualAddress;
3012
3013 /*
3014 * Merge the protection
3015 */
3016 EffectiveSegment->Protection |= Segment->Protection;
3017
3018 /* Clean up redundance */
3019 ProtectionFlags = 0;
3020
3021 if(EffectiveSegment->Protection & PAGE_IS_READABLE)
3022 ProtectionFlags |= 1 << 0;
3023
3024 if(EffectiveSegment->Protection & PAGE_IS_WRITABLE)
3025 ProtectionFlags |= 1 << 1;
3026
3027 if(EffectiveSegment->Protection & PAGE_IS_EXECUTABLE)
3028 ProtectionFlags |= 1 << 2;
3029
3030 if(EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
3031 ProtectionFlags |= 1 << 3;
3032
3033 ASSERT(ProtectionFlags < 16);
3034 EffectiveSegment->Protection = FlagsToProtection[ProtectionFlags];
3035
3036 /* If a segment was required to be shared and cannot, fail */
3037 if(!(Segment->Protection & PAGE_IS_WRITECOPY) &&
3038 EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
3039 {
3040 return FALSE;
3041 }
3042 }
3043 /*
3044 * We assume no holes between segments at this point
3045 */
3046 else
3047 {
3048 KeBugCheck(MEMORY_MANAGEMENT);
3049 }
3050 }
3051 }
3052 ImageSectionObject->NrSegments = LastSegment + 1;
3053
3054 return TRUE;
3055}
3056
3059 PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
3060{
3062 PVOID FileHeader;
3063 PVOID FileHeaderBuffer;
3064 ULONG FileHeaderSize;
3065 ULONG Flags;
3066 ULONG OldNrSegments;
3068 ULONG i;
3069
3070 /*
3071 * Read the beginning of the file (2 pages). Should be enough to contain
3072 * all (or most) of the headers
3073 */
3074 Offset.QuadPart = 0;
3075
3077 &Offset,
3078 PAGE_SIZE * 2,
3079 &FileHeader,
3080 &FileHeaderBuffer,
3081 &FileHeaderSize);
3082
3083 if (!NT_SUCCESS(Status))
3084 return Status;
3085
3086 if (FileHeaderSize == 0)
3087 {
3088 ExFreePool(FileHeaderBuffer);
3089 return STATUS_UNSUCCESSFUL;
3090 }
3091
3092 /*
3093 * Look for a loader that can handle this executable
3094 */
3095 for (i = 0; i < RTL_NUMBER_OF(ExeFmtpLoaders); ++ i)
3096 {
3097 Flags = 0;
3098
3099 Status = ExeFmtpLoaders[i](FileHeader,
3100 FileHeaderSize,
3101 FileObject,
3102 ImageSectionObject,
3103 &Flags,
3106
3107 if (!NT_SUCCESS(Status))
3108 {
3109 if (ImageSectionObject->Segments)
3110 {
3111 ExFreePool(ImageSectionObject->Segments);
3112 ImageSectionObject->Segments = NULL;
3113 }
3114 }
3115
3117 break;
3118 }
3119
3120 ExFreePoolWithTag(FileHeaderBuffer, 'rXmM');
3121
3122 /*
3123 * No loader handled the format
3124 */
3126 {
3129 }
3130
3131 if (!NT_SUCCESS(Status))
3132 return Status;
3133
3134 ASSERT(ImageSectionObject->Segments != NULL);
3135 ASSERT(ImageSectionObject->RefCount > 0);
3136
3137 /*
3138 * Some defaults
3139 */
3140 /* FIXME? are these values platform-dependent? */
3141 if (ImageSectionObject->ImageInformation.MaximumStackSize == 0)
3142 ImageSectionObject->ImageInformation.MaximumStackSize = 0x40000;
3143
3144 if(ImageSectionObject->ImageInformation.CommittedStackSize == 0)
3145 ImageSectionObject->ImageInformation.CommittedStackSize = 0x1000;
3146
3147 if(ImageSectionObject->BasedAddress == NULL)
3148 {
3149 if(ImageSectionObject->ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL)
3150 ImageSectionObject->BasedAddress = (PVOID)0x10000000;
3151 else
3152 ImageSectionObject->BasedAddress = (PVOID)0x00400000;
3153 }
3154
3155 /*
3156 * And now the fun part: fixing the segments
3157 */
3158
3159 /* Sort them by virtual address */
3160 MmspSortSegments(ImageSectionObject, Flags);
3161
3162 /* Ensure they don't overlap in memory */
3163 if (!MmspCheckSegmentBounds(ImageSectionObject, Flags))
3165
3166 /* Ensure they are aligned */
3167 OldNrSegments = ImageSectionObject->NrSegments;
3168
3169 if (!MmspPageAlignSegments(ImageSectionObject, Flags))
3171
3172 /* Trim them if the alignment phase merged some of them */
3173 if (ImageSectionObject->NrSegments < OldNrSegments)
3174 {
3175 PMM_SECTION_SEGMENT Segments;
3176 SIZE_T SizeOfSegments;
3177
3178 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
3179
3181 SizeOfSegments,
3183
3184 if (Segments == NULL)
3186
3187 RtlCopyMemory(Segments, ImageSectionObject->Segments, SizeOfSegments);
3188 ExFreePool(ImageSectionObject->Segments);
3189 ImageSectionObject->Segments = Segments;
3190 }
3191
3192 /* And finish their initialization */
3193 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
3194 {
3195 ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock);
3196 ImageSectionObject->Segments[i].ReferenceCount = &ImageSectionObject->RefCount;
3197 ImageSectionObject->Segments[i].Flags = &ImageSectionObject->SegFlags;
3198 MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]);
3199 ImageSectionObject->Segments[i].FileObject = FileObject;
3200 }
3201
3202 ASSERT(ImageSectionObject->RefCount > 0);
3203
3204 ImageSectionObject->FileObject = FileObject;
3205
3207 return Status;
3208}
3209
3214 PLARGE_INTEGER UMaximumSize,
3218{
3219 PSECTION Section;
3221 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3222 KIRQL OldIrql;
3223
3224
3225 if (FileObject == NULL)
3227
3228 if (FileObject->SectionObjectPointer == NULL)
3229 {
3230 DPRINT1("Denying section creation due to missing cache initialization\n");
3232 }
3233
3234 /*
3235 * Create the section
3236 */
3241 NULL,
3242 sizeof(*Section),
3243 0,
3244 0,
3245 (PVOID*)(PVOID)&Section);
3246 if (!NT_SUCCESS(Status))
3247 {
3248 return Status;
3249 }
3250
3251 /*
3252 * Initialize it
3253 */
3254 RtlZeroMemory(Section, sizeof(*Section));
3255
3256 /* Mark this as a "ROS" Section */
3257 Section->u.Flags.filler = 1;
3258
3260 Section->SizeOfSection = *UMaximumSize;
3261 Section->u.Flags.File = 1;
3262 Section->u.Flags.Image = 1;
3264 Section->u.Flags.NoChange = 1;
3265
3266grab_image_section_object:
3267 OldIrql = MiAcquirePfnLock();
3268
3269 /* Wait for it to be properly created or deleted */
3270 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3271 while(ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
3272 {
3273 MiReleasePfnLock(OldIrql);
3274
3276
3277 OldIrql = MiAcquirePfnLock();
3278 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3279 }
3280
3281 if (ImageSectionObject == NULL)
3282 {
3283 NTSTATUS StatusExeFmt;
3284
3285 /* Release the lock because ExAllocatePoolWithTag could need to acquire it */
3286 MiReleasePfnLock(OldIrql);
3287
3289 if (ImageSectionObject == NULL)
3290 {
3291 ObDereferenceObject(Section);
3292 return STATUS_NO_MEMORY;
3293 }
3294
3295 ImageSectionObject->SegFlags = MM_SEGMENT_INCREATE;
3296 ImageSectionObject->RefCount = 1;
3297 ImageSectionObject->SectionCount = 1;
3298
3299 OldIrql = MiAcquirePfnLock();
3300 if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
3301 {
3302 MiReleasePfnLock(OldIrql);
3303 /* Bad luck. Start over */
3304 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3305 goto grab_image_section_object;
3306 }
3307
3308 FileObject->SectionObjectPointer->ImageSectionObject = ImageSectionObject;
3309
3310 MiReleasePfnLock(OldIrql);
3311
3312 /* Purge the cache */
3313 CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, NULL);
3314
3315 StatusExeFmt = ExeFmtpCreateImageSection(FileObject, ImageSectionObject);
3316
3317 if (!NT_SUCCESS(StatusExeFmt))
3318 {
3319 /* Unset */
3320 OldIrql = MiAcquirePfnLock();
3321 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3322 MiReleasePfnLock(OldIrql);
3323
3324 if(ImageSectionObject->Segments != NULL)
3325 ExFreePool(ImageSectionObject->Segments);
3326
3327 /*
3328 * If image file is empty, then return that the file is invalid for section
3329 */
3330 Status = StatusExeFmt;
3331 if (StatusExeFmt == STATUS_END_OF_FILE)
3332 {
3334 }
3335
3336 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3337 ObDereferenceObject(Section);
3338 return Status;
3339 }
3340
3341 Section->Segment = (PSEGMENT)ImageSectionObject;
3342 ASSERT(ImageSectionObject->Segments);
3343 ASSERT(ImageSectionObject->RefCount > 0);
3344
3345 /*
3346 * Lock the file
3347 */
3349 if (!NT_SUCCESS(Status))
3350 {
3351 /* Unset */
3352 OldIrql = MiAcquirePfnLock();
3353 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3354 MiReleasePfnLock(OldIrql);
3355
3356 ExFreePool(ImageSectionObject->Segments);
3357 ExFreePool(ImageSectionObject);
3358 ObDereferenceObject(Section);
3359 return Status;
3360 }
3361
3362 OldIrql = MiAcquirePfnLock();
3363 ImageSectionObject->SegFlags &= ~MM_SEGMENT_INCREATE;
3364
3365 /* Take a ref on the file on behalf of the newly created structure */
3367
3368 MiReleasePfnLock(OldIrql);
3369
3370 Status = StatusExeFmt;
3371 }
3372 else
3373 {
3374 /* If FS driver called for delete, tell them it's not possible anymore. */
3375 ImageSectionObject->SegFlags &= ~MM_IMAGE_SECTION_FLUSH_DELETE;
3376
3377 /* Take one ref */
3378 InterlockedIncrement64(&ImageSectionObject->RefCount);
3379 ImageSectionObject->SectionCount++;
3380
3381 MiReleasePfnLock(OldIrql);
3382
3383 Section->Segment = (PSEGMENT)ImageSectionObject;
3384
3386 }
3387
3388 if (Section->SizeOfSection.QuadPart == 0)
3389 {
3390 Section->SizeOfSection.QuadPart = ImageSectionObject->ImageInformation.ImageFileSize;
3391 }
3392
3393 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
3394 *SectionObject = Section;
3395 ASSERT(ImageSectionObject->RefCount > 0);
3396
3397 return Status;
3398}
3399
3400
3401
3402static NTSTATUS
3405 BOOLEAN AsImage,
3409 ULONG Protect,
3410 LONGLONG ViewOffset,
3412{
3413 PMEMORY_AREA MArea;
3415 ULONG Granularity;
3416
3417 ASSERT(ViewSize != 0);
3418
3419 if (Segment->WriteCopy)
3420 {
3421 /* We have to do this because the not present fault
3422 * and access fault handlers depend on the protection
3423 * that should be granted AFTER the COW fault takes
3424 * place to be in Region->Protect. The not present fault
3425 * handler changes this to the correct protection for COW when
3426 * mapping the pages into the process's address space. If a COW
3427 * fault takes place, the access fault handler sets the page protection
3428 * to these values for the newly copied pages
3429 */
3430 if (Protect == PAGE_WRITECOPY)
3432 else if (Protect == PAGE_EXECUTE_WRITECOPY)
3434 }
3435
3436 if (*BaseAddress == NULL)
3437 Granularity = MM_ALLOCATION_GRANULARITY;
3438 else
3439 Granularity = PAGE_SIZE;
3440
3441#ifdef NEWCC
3442 if (Segment->Flags & MM_DATAFILE_SEGMENT)
3443 {
3445 FileOffset.QuadPart = ViewOffset;
3446 ObReferenceObject(Section);
3448 }
3449#endif
3453 ViewSize,
3454 Protect,
3455 &MArea,
3457 Granularity);
3458 if (!NT_SUCCESS(Status))
3459 {
3460 DPRINT1("Mapping between 0x%p and 0x%p failed (%X).\n",
3461 (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status);
3462 return Status;
3463 }
3464
3465 InterlockedIncrement64(Segment->ReferenceCount);
3466
3467 MArea->SectionData.Segment = Segment;
3468 MArea->SectionData.ViewOffset = ViewOffset;
3469 if (AsImage)
3470 {
3472 }
3473
3474 MmInitializeRegion(&MArea->SectionData.RegionListHead,
3475 ViewSize, 0, Protect);
3476
3477 return STATUS_SUCCESS;
3478}
3479
3480
3481static VOID
3483 PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
3484{
3487 SWAPENTRY SavedSwapEntry;
3491
3494
3496
3498 MemoryArea->SectionData.ViewOffset;
3499
3500 Segment = MemoryArea->SectionData.Segment;
3501
3503 while (Entry && MM_IS_WAIT_PTE(Entry))
3504 {
3507
3509
3513 }
3514
3515 /*
3516 * For a dirty, datafile, non-private page, there shoulkd be no swap entry
3517 */
3518 if (*Segment->Flags & MM_DATAFILE_SEGMENT)
3519 {
3520 if (Page == PFN_FROM_SSE(Entry) && Dirty)
3521 {
3522 ASSERT(SwapEntry == 0);
3523 }
3524 }
3525
3526 if (SwapEntry != 0)
3527 {
3528 /*
3529 * Sanity check
3530 */
3531 MmFreeSwapPage(SwapEntry);
3532 }
3533 else if (Page != 0)
3534 {
3535 if (IS_SWAP_FROM_SSE(Entry) ||
3537 {
3538 ASSERT(Process != NULL);
3539
3540 /*
3541 * Just dereference private pages
3542 */
3543 SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
3544 if (SavedSwapEntry != 0)
3545 {
3546 MmFreeSwapPage(SavedSwapEntry);
3548 }
3551 }
3552 else
3553 {
3554 if (Process)
3555 {
3557 }
3558
3559 /* We don't dirtify for System Space Maps. We let Cc manage that */
3561 }
3562 }
3563}
3564
3565static NTSTATUS
3568{
3572 PLIST_ENTRY CurrentEntry;
3573 PMM_REGION CurrentRegion;
3574 PLIST_ENTRY RegionListHead;
3575
3577 BaseAddress);
3578 if (MemoryArea == NULL)
3579 {
3580 return STATUS_UNSUCCESSFUL;
3581 }
3582
3583 Segment = MemoryArea->SectionData.Segment;
3584
3585#ifdef NEWCC
3586 if (Segment->Flags & MM_DATAFILE_SEGMENT)
3587 {
3591
3592 return Status;
3593 }
3594#endif
3595
3597
3599
3600 RegionListHead = &MemoryArea->SectionData.RegionListHead;
3601 while (!IsListEmpty(RegionListHead))
3602 {
3603 CurrentEntry = RemoveHeadList(RegionListHead);
3604 CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
3605 ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
3606 }
3607
3608 if ((*Segment->Flags) & MM_PHYSICALMEMORY_SEGMENT)
3609 {
3611 MemoryArea,
3612 NULL,
3613 NULL);
3614 }
3615 else
3616 {
3618 MemoryArea,
3620 AddressSpace);
3621 }
3623 MmDereferenceSegment(Segment);
3624 return Status;
3625}
3626
3627/* This functions must be called with a locked address space */
3629NTAPI
3634 _In_ BOOLEAN SkipDebuggerNotify)
3635{
3638 PVOID ImageBaseAddress = 0;
3639
3640 DPRINT("Opening memory area Process %p BaseAddress %p\n",
3642
3643 ASSERT(Process);
3645
3646 AddressSpace = &Process->Vm;
3647
3648 if (MemoryArea == NULL ||
3649#ifdef NEWCC
3650 ((MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) && (MemoryArea->Type != MEMORY_AREA_CACHE)) ||
3651#else
3653#endif
3655
3656 {
3658
3659 DPRINT1("Unable to find memory area at address %p.\n", BaseAddress);
3661 }
3662
3664 {
3665 ULONG i;
3666 ULONG NrSegments;
3667 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3668 PMM_SECTION_SEGMENT SectionSegments;
3670 ULONG MapCount;
3671
3672 Segment = MemoryArea->SectionData.Segment;
3673 ImageSectionObject = ImageSectionObjectFromSegment(Segment);
3674 SectionSegments = ImageSectionObject->Segments;
3675 NrSegments = ImageSectionObject->NrSegments;
3676
3678
3679 /* Search for the current segment within the section segments
3680 * and calculate the image base address */
3681 for (i = 0; i < NrSegments; i++)
3682 {
3683 if (Segment == &SectionSegments[i])
3684 {
3685 ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
3686 break;
3687 }
3688 }
3689 if (i >= NrSegments)
3690 {
3691 KeBugCheck(MEMORY_MANAGEMENT);
3692 }
3693
3694 for (i = 0; i < NrSegments; i++)
3695 {
3696 PVOID SBaseAddress = (PVOID)
3697 ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
3698
3699 Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
3700 if (!NT_SUCCESS(Status))
3701 {
3702 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3703 SBaseAddress, Process, Status);
3705 }
3706 }
3707 DPRINT("One mapping less for %p\n", ImageSectionObject->FileObject->SectionObjectPointer);
3708 MapCount = InterlockedDecrement(&ImageSectionObject->MapCount);
3709 if (MapCount != 0)
3710 ImageBaseAddress = NULL;
3711 }
3712 else
3713 {
3715 PMMVAD Vad = &MemoryArea->VadNode;
3716 PCONTROL_AREA ControlArea = Vad->ControlArea;
3719 LARGE_INTEGER ViewOffset;
3720 ViewOffset.QuadPart = MemoryArea->SectionData.ViewOffset;
3721
3722 InterlockedIncrement64(Segment->ReferenceCount);
3723
3724 ViewSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
3725
3727 if (!NT_SUCCESS(Status))
3728 {
3729 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3732 }
3733
3734 /* These might be deleted now */
3735 Vad = NULL;
3736 MemoryArea = NULL;
3737
3739 {
3740 /* Don't bother */
3741 MmDereferenceSegment(Segment);
3742 return STATUS_SUCCESS;
3743 }
3745
3746 FileObject = Segment->FileObject;
3748
3749 /* Don't bother for auto-delete closed file. */
3751 {
3753 MmDereferenceSegment(Segment);
3754 return STATUS_SUCCESS;
3755 }
3756
3757 /*
3758 * Flush only when last mapping is deleted.
3759 * FIXME: Why ControlArea == NULL? Or rather: is ControlArea ever not NULL here?
3760 */
3761 if (ControlArea == NULL || ControlArea->NumberOfMappedViews == 1)
3762 {
3763 while (ViewSize > 0)
3764 {
3765 ULONG FlushSize = min(ViewSize, PAGE_ROUND_DOWN(MAXULONG));
3766 MmFlushSegment(FileObject->SectionObjectPointer,
3767 &ViewOffset,
3768 FlushSize,
3769 NULL);
3770 ViewSize -= FlushSize;
3771 ViewOffset.QuadPart += FlushSize;
3772 }
3773 }
3774
3776 MmDereferenceSegment(Segment);
3777 }
3778
3779 /* Notify debugger */
3780 if (ImageBaseAddress && !SkipDebuggerNotify) DbgkUnMapViewOfSection(ImageBaseAddress);
3781
3782 return STATUS_SUCCESS;
3783}
3784
3785
3786
3787
3811NTAPI
3813 _In_ HANDLE SectionHandle,
3814 _In_ SECTION_INFORMATION_CLASS SectionInformationClass,
3815 _Out_ PVOID SectionInformation,
3816 _In_ SIZE_T SectionInformationLength,
3818{
3819 PSECTION Section;
3822 PAGED_CODE();
3823
3825 if (PreviousMode != KernelMode)
3826 {
3827 _SEH2_TRY
3828 {
3829 ProbeForWrite(SectionInformation,
3830 SectionInformationLength,
3831 __alignof(ULONG));
3832 if (ResultLength != NULL)
3833 {
3835 sizeof(*ResultLength),
3836 __alignof(SIZE_T));
3837 }
3838 }
3840 {
3842 }
3843 _SEH2_END;
3844 }
3845
3846 if (SectionInformationClass == SectionBasicInformation)
3847 {
3848 if (SectionInformationLength < sizeof(SECTION_BASIC_INFORMATION))
3849 {
3851 }
3852 }
3853 else if (SectionInformationClass == SectionImageInformation)
3854 {
3855 if (SectionInformationLength < sizeof(SECTION_IMAGE_INFORMATION))
3856 {
3858 }
3859 }
3860 else
3861 {
3863 }
3864
3865 Status = ObReferenceObjectByHandle(SectionHandle,
3869 (PVOID*)(PVOID)&Section,
3870 NULL);
3871 if (!NT_SUCCESS(Status))
3872 {
3873 DPRINT1("Failed to reference section: 0x%lx\n", Status);
3874 return Status;
3875 }
3876
3877 switch(SectionInformationClass)
3878 {
3880 {
3881 SECTION_BASIC_INFORMATION Sbi = { 0 };
3882
3883 Sbi.Size = Section->SizeOfSection;
3884 Sbi.BaseAddress = NULL;
3885
3886 if (Section->u.Flags.File)
3887 Sbi.Attributes |= SEC_FILE;
3888 if (Section->u.Flags.Image)
3889 Sbi.Attributes |= SEC_IMAGE;
3890 if (Section->u.Flags.Commit)
3891 Sbi.Attributes |= SEC_COMMIT;
3892 if (Section->u.Flags.Reserve)
3893 Sbi.Attributes |= SEC_RESERVE;
3894 if (Section->u.Flags.Based)
3895 Sbi.Attributes |= SEC_BASED;
3896
3897 if (Section->u.Flags.Image)
3898 {
3899 if (!MiIsRosSectionObject(Section))
3900 {
3901 /* Not supported yet */
3902 ASSERT(FALSE);
3903 }
3904 }
3905 else if (MiIsRosSectionObject(Section))
3906 {
3907 Sbi.BaseAddress = (PVOID)((PMM_SECTION_SEGMENT)Section->Segment)->Image.VirtualAddress;
3908 }
3909 else
3910 {
3911 Sbi.BaseAddress = Section->Segment->BasedAddress;
3912 }
3913
3914 _SEH2_TRY
3915 {
3916 *((SECTION_BASIC_INFORMATION*)SectionInformation) = Sbi;
3917 if (ResultLength != NULL)
3918 {
3919 *ResultLength = sizeof(Sbi);
3920 }
3921 }
3923 {
3925 }
3926 _SEH2_END;
3927 break;
3928 }
3930 {
3931 if (!Section->u.Flags.Image)
3932 {
3934 }
3935 else if (MiIsRosSectionObject(Section))
3936 {
3937 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
3938
3939 _SEH2_TRY
3940 {
3942 *Sii = ImageSectionObject->ImageInformation;
3943 if (ResultLength != NULL)
3944 {
3945 *ResultLength = sizeof(*Sii);
3946 }
3947 }
3949 {
3951 }
3952 _SEH2_END;
3953 }
3954 else
3955 {
3956 _SEH2_TRY
3957 {
3959 *Sii = *Section->Segment->u2.ImageInformation;
3960 if (ResultLength != NULL)
3961 *ResultLength = sizeof(*Sii);
3962 }
3964 {
3966 }
3967 _SEH2_END;
3968 }
3969 break;
3970 }
3971 default:
3972 DPRINT1("Unknown SectionInformationClass: %d\n", SectionInformationClass);
3974 }
3975
3976 ObDereferenceObject(Section);
3977
3978 return Status;
3979}
3980
3981/**********************************************************************
3982 * NAME EXPORTED
3983 * MmMapViewOfSection
3984 *
3985 * DESCRIPTION
3986 * Maps a view of a section into the virtual address space of a
3987 * process.
3988 *
3989 * ARGUMENTS
3990 * Section
3991 * Pointer to the section object.
3992 *
3993 * ProcessHandle
3994 * Pointer to the process.
3995 *
3996 * BaseAddress
3997 * Desired base address (or NULL) on entry;
3998 * Actual base address of the view on exit.
3999 *
4000 * ZeroBits
4001 * Number of high order address bits that must be zero.
4002 *
4003 * CommitSize
4004 * Size in bytes of the initially committed section of
4005 * the view.
4006 *
4007 * SectionOffset
4008 * Offset in bytes from the beginning of the section
4009 * to the beginning of the view.
4010 *
4011 * ViewSize
4012 * Desired length of map (or zero to map all) on entry
4013 * Actual length mapped on exit.
4014 *
4015 * InheritDisposition
4016 * Specified how the view is to be shared with
4017 * child processes.
4018 *
4019 * AllocationType
4020 * Type of allocation for the pages.
4021 *
4022 * Protect
4023 * Protection for the committed region of the view.
4024 *
4025 * RETURN VALUE
4026 * Status.
4027 *
4028 * @implemented
4029 */
4039 _In_range_(ViewShare, ViewUnmap) SECTION_INHERIT InheritDisposition,
4042{
4043 PSECTION Section;
4046 BOOLEAN NotAtBase = FALSE;
4047 BOOLEAN IsAttached = FALSE;
4049
4051 {
4052 DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
4055 Process,
4057 ZeroBits,
4058 CommitSize,
4060 ViewSize,
4061 InheritDisposition,
4063 Protect);
4064 }
4065
4066 ASSERT(Process);
4067
4069 {
4071 }
4072
4074 {
4076 IsAttached = TRUE;
4077 }
4078
4079 Section = SectionObject;
4080 AddressSpace = &Process->Vm;
4081
4082 if (Section->u.Flags.NoChange)
4084
4086
4087 if (Section->u.Flags.Image)
4088 {
4089 ULONG i;
4090 ULONG NrSegments;
4091 ULONG_PTR ImageBase;
4092 SIZE_T ImageSize;
4093 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
4094 PMM_SECTION_SEGMENT SectionSegments;
4095
4096 ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
4097 SectionSegments = ImageSectionObject->Segments;
4098 NrSegments = ImageSectionObject->NrSegments;
4099
4100 ASSERT(ImageSectionObject->RefCount > 0);
4101
4102 ImageBase = (ULONG_PTR)*BaseAddress;
4103 if (ImageBase == 0)
4104 {
4105 ImageBase = (ULONG_PTR)ImageSectionObject->BasedAddress;
4106 }
4107
4108 ImageSize = 0;
4109 for (i = 0; i < NrSegments; i++)
4110 {
4111 ULONG_PTR MaxExtent;
4112 MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
4113 SectionSegments[i].Length.QuadPart);
4114 ImageSize = max(ImageSize, MaxExtent);
4115 }
4116
4117 ImageSectionObject->ImageInformation.ImageFileSize = (ULONG)ImageSize;
4118
4119 /* Check for an illegal base address */
4120 if (((ImageBase + ImageSize) > (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS) ||
4121 ((ImageBase + ImageSize) < ImageSize))
4122 {
4123 ASSERT(*BaseAddress == NULL);
4124 ImageBase = ALIGN_DOWN_BY((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - ImageSize,
4126 NotAtBase = TRUE;
4127 }
4128 else if (ImageBase != ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY))
4129 {
4130 ASSERT(*BaseAddress == NULL);
4131 ImageBase = ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY);
4132 NotAtBase = TRUE;
4133 }
4134
4135 /* Check there is enough space to map the section at that point. */
4136 if (!MmIsAddressRangeFree(AddressSpace, (PVOID)ImageBase, PAGE_ROUND_UP(ImageSize)))
4137 {
4138 /* Fail if the user requested a fixed base address. */
4139 if ((*BaseAddress) != NULL)
4140 {
4142 goto Exit;
4143 }
4144 /* Otherwise find a gap to map the image. */
4146 if (ImageBase == 0)
4147 {
4149 goto Exit;
4150 }
4151 /* Remember that we loaded image at a different base address */
4152 NotAtBase = TRUE;
4153 }
4154
4155 for (i = 0; i < NrSegments; i++)
4156 {
4157 PVOID SBaseAddress = (PVOID)
4158 ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4159 MmLockSectionSegment(&SectionSegments[i]);
4161 TRUE,
4162 &SectionSegments[i],
4163 &SBaseAddress,
4164 SectionSegments[i].Length.QuadPart,
4165 SectionSegments[i].Protection,
4166 0,
4167 0);
4168 MmUnlockSectionSegment(&SectionSegments[i]);
4169 if (!NT_SUCCESS(Status))
4170 {
4171 /* roll-back */
4172 while (i--)
4173 {
4174 SBaseAddress = ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4175 MmLockSectionSegment(&SectionSegments[i]);
4176 MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
4177 MmUnlockSectionSegment(&SectionSegments[i]);
4178 }
4179
4180 goto Exit;
4181 }
4182 }
4183
4184 *BaseAddress = (PVOID)ImageBase;
4185 *ViewSize = ImageSize;
4186
4187 DPRINT("Mapped %p for section pointer %p\n", ImageSectionObject, ImageSectionObject->FileObject->SectionObjectPointer);
4188
4189 /* One more map */
4190 InterlockedIncrement(&ImageSectionObject->MapCount);
4191 }
4192 else
4193 {
4195 LONGLONG ViewOffset;
4196
4197 ASSERT(Segment->RefCount > 0);
4198
4199 /* check for write access */
4202 {
4204 goto Exit;
4205 }
4206 /* check for read access */
4209 {
4211 goto Exit;
4212 }
4213 /* check for execute access */
4216 {
4218 goto Exit;
4219 }
4220
4221 if (SectionOffset == NULL)
4222 {
4223 ViewOffset = 0;
4224 }
4225 else
4226 {
4227 SectionOffset->QuadPart &= ~(PAGE_SIZE - 1);
4228 ViewOffset = SectionOffset->QuadPart;
4229 }
4230
4231 /* Check if the offset and size would cause an overflow */
4232 if (((ULONG64)ViewOffset + *ViewSize) < (ULONG64)ViewOffset)
4233 {
4234 DPRINT1("Section offset overflows\n");
4236 goto Exit;
4237 }
4238
4239 /* Check if the offset and size are bigger than the section itself */
4240 if (((ULONG64)ViewOffset + *ViewSize) > (ULONG64)Section->SizeOfSection.QuadPart)
4241 {
4242 /* This is allowed for physical memory sections and kernel mode callers */
4243 if (!Section->u.Flags.PhysicalMemory || (ExGetPreviousMode() == UserMode))
4244 {
4245 DPRINT1("Section offset and size are larger than section\n");
4247 goto Exit;
4248 }
4249 }
4250
4251 if ((*ViewSize) == 0)
4252 {
4253 /* Calculate a view size and make sure it doesn't overflow a SIZE_T */
4254 ULONG64 CalculatedSize = Section->SizeOfSection.QuadPart - ViewOffset;
4255 if (CalculatedSize > SIZE_T_MAX)
4256 {
4257 DPRINT1("ViewSize is larger than SIZE_T_MAX\n");
4259 goto Exit;
4260 }
4261
4262 *ViewSize = (SIZE_T)CalculatedSize;
4263 }
4264 else if ((ExGetPreviousMode() == UserMode) &&
4265 (((*ViewSize)+ViewOffset) > Section->SizeOfSection.QuadPart) &&
4266 (!Section->u.Flags.Reserve))
4267 {
4268 /* Dubious */
4269 (*ViewSize) = MIN(Section->SizeOfSection.QuadPart - ViewOffset, SIZE_T_MAX - PAGE_SIZE);
4270 }
4271
4273
4276 FALSE,
4277 Segment,
4279 *ViewSize,
4280 Protect,
4281 ViewOffset,
4284 if (!NT_SUCCESS(Status))
4285 {
4286 goto Exit;
4287 }
4288 }
4289
4290 if (NotAtBase)
4292 else
4294
4295Exit:
4296
4298
4299 if (IsAttached)
4300 {
4302 }
4303
4304 return Status;
4305}
4306
4307/*
4308 * @unimplemented
4309 */
4310BOOLEAN
4311NTAPI
4315{
4316 BOOLEAN Ret;
4318
4319 /* Check whether an ImageSectionObject exists */
4320 if (SectionObjectPointer->ImageSectionObject != NULL)
4321 {
4322 DPRINT1("ERROR: File can't be truncated because it has an image section\n");
4323 return FALSE;
4324 }
4325
4327 if (!Segment)
4328 {
4329 /* There is no data section. It's fine to do anything. */
4330 return TRUE;
4331 }
4332
4334 if ((Segment->SectionCount == 0) ||
4335 ((Segment->SectionCount == 1) && (SectionObjectPointer->SharedCacheMap != NULL)))
4336 {
4337 /* If the cache is the only one holding a reference to the segment, then it's fine to resize */
4338 Ret = TRUE;
4339 }
4340 else if (NewFileSize != NULL)
4341 {
4342 /* We can't shrink, but we can extend */
4343 Ret = NewFileSize->QuadPart >= Segment->RawLength.QuadPart;
4344#if DBG
4345 if (!Ret)
4346 {
4347 DPRINT1("Cannot truncate data: New Size %I64d, Segment Size %I64d\n", NewFileSize->QuadPart, Segment->RawLength.QuadPart);
4348 }
4349#endif
4350 }
4351 else
4352 {
4353 DPRINT1("ERROR: File can't be truncated because it has references held to its data section\n");
4354 Ret = FALSE;
4355 }
4356
4358 MmDereferenceSegment(Segment);
4359
4360 DPRINT("FIXME: didn't check for outstanding write probes\n");
4361
4362 return Ret;
4363}
4364
4365static
4366BOOLEAN
4368{
4370
4372
4373 /* Loop over all entries */
4374 for (PageTable = RtlEnumerateGenericTable(&Segment->PageTable, TRUE);
4375 PageTable != NULL;
4377 {
4378 for (ULONG i = 0; i < _countof(PageTable->PageEntries); i++)
4379 {
4380 ULONG_PTR Entry = PageTable->PageEntries[i];
4382
4383 if (!Entry)
4384 continue;
4385
4387 {
4388 /* I/O ongoing or swap entry. Someone mapped this file as we were not looking */
4390 return FALSE;
4391 }
4392
4393 /* Regular entry */
4396
4397 /* Properly remove using the used API */
4398 Offset.QuadPart = PageTable->FileOffset.QuadPart + (i << PAGE_SHIFT);
4401 }
4402 }
4403
4405
4406 return TRUE;
4407}
4408
4409/*
4410 * @implemented
4411 */
4415{
4416 switch(FlushType)
4417 {
4418 case MmFlushForDelete:
4419 {
4420 /*
4421 * FIXME: Check for outstanding write probes on Data section.
4422 * How do we do that ?
4423 */
4424 }
4425 /* Fall-through */
4426 case MmFlushForWrite:
4427 {
4428 KIRQL OldIrql = MiAcquirePfnLock();
4429 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4430
4431 DPRINT("Deleting or modifying %p\n", SectionObjectPointer);
4432
4433 /* Wait for concurrent creation or deletion of image to be done */
4434 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4435 while (ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INCREATE | MM_SEGMENT_INDELETE)))
4436 {
4437 MiReleasePfnLock(OldIrql);
4439 OldIrql = MiAcquirePfnLock();
4440 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4441 }
4442
4443 if (!ImageSectionObject)
4444 {
4445 DPRINT("No image section object. Accepting\n");
4446 /* Nothing to do */
4447 MiReleasePfnLock(OldIrql);
4448 return TRUE;
4449 }
4450
4451 /* Do we have open sections or mappings on it ? */
4452 if ((ImageSectionObject->SectionCount) || (ImageSectionObject->MapCount))
4453 {
4454 /* We do. No way to delete it */
4455 MiReleasePfnLock(OldIrql);
4456 DPRINT("Denying. There are mappings open\n");
4457 return FALSE;
4458 }
4459
4460 /* There are no sections open on it, but we must still have pages around. Discard everything */
4461 ImageSectionObject->SegFlags |= MM_IMAGE_SECTION_FLUSH_DELETE;
4462 InterlockedIncrement64(&ImageSectionObject->RefCount);
4463 MiReleasePfnLock(OldIrql);
4464
4465 DPRINT("Purging\n");
4466
4467 for (ULONG i = 0; i < ImageSectionObject->NrSegments; i++)
4468 {
4469 if (!MiPurgeImageSegment(&ImageSectionObject->Segments[i]))
4470 break;
4471 }
4472
4473 /* Grab lock again */
4474 OldIrql = MiAcquirePfnLock();
4475
4476 if (!(ImageSectionObject->SegFlags & MM_IMAGE_SECTION_FLUSH_DELETE))
4477 {
4478 /*
4479 * Someone actually created a section while we were not looking.
4480 * Drop our ref and deny.
4481 * MmDereferenceSegmentWithLock releases Pfn lock
4482 */
4483 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4484 return FALSE;
4485 }
4486
4487 /* We should be the last one holding a ref here. */
4488 ASSERT(ImageSectionObject->RefCount == 1);
4489 ASSERT(ImageSectionObject->SectionCount == 0);
4490
4491 /* Dereference the first segment, this will free everything & release the lock */
4492 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4493 return TRUE;
4494 }
4495 }
4496 return FALSE;
4497}
4498
4499/*
4500 * @implemented
4501 */
4503NTAPI
4507{
4509
4510 SectionOffset.QuadPart = 0;
4511
4513}
4514
4516NTAPI
4523 )
4524{
4525 PSECTION Section = SectionObject;
4529
4531
4532 PAGED_CODE();
4533
4535 {
4537 &MmSession,
4538 MappedBase,
4539 ViewSize,
4541 }
4542
4543 DPRINT("MmMapViewInSystemSpaceEx() called\n");
4544
4545 /* unsupported for now */
4546 ASSERT(Section->u.Flags.Image == 0);
4547
4548 Section = SectionObject;
4550
4551 if (*ViewSize == 0)
4552 {
4553 LONGLONG MapSizeLL;
4554
4555 /* Page-align the mapping */
4556 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4557
4558 if (!NT_SUCCESS(RtlLongLongSub(Section->SizeOfSection.QuadPart, SectionOffset->QuadPart, &MapSizeLL)))
4560
4561 if (!NT_SUCCESS(RtlLongLongToSIZET(MapSizeLL, ViewSize)))
4563 }
4564 else
4565 {
4566 LONGLONG HelperLL;
4567
4568 /* Get the map end */
4569 if (!NT_SUCCESS(RtlLongLongAdd(SectionOffset->QuadPart, *ViewSize, &HelperLL)))
4571
4572 /* Round it up, if needed */
4573 if (HelperLL % PAGE_SIZE)
4574 {
4575 if (!NT_SUCCESS(RtlLongLongAdd(HelperLL, PAGE_SIZE - (HelperLL % PAGE_SIZE), &HelperLL)))
4577 }
4578
4579 /* Now that we have the mapping end, we can align down its start */
4580 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4581
4582 /* Get the new size */
4583 if (!NT_SUCCESS(RtlLongLongSub(HelperLL, SectionOffset->QuadPart, &HelperLL)))
4585
4586 if (!NT_SUCCESS(RtlLongLongToSIZET(HelperLL, ViewSize)))
4588 }
4589
4591
4593
4595
4597 Section->u.Flags.Image,
4598 Segment,
4599 MappedBase,
4600 *ViewSize,
4602 SectionOffset->QuadPart,
4603 SEC_RESERVE);
4604
4607
4608 return Status;
4609}
4610
4611/* This function must be called with address space lock held */
4613NTAPI
4615{
4616 DPRINT("MmUnmapViewInSystemSpace() called\n");
4617
4619}
4620
4621/**********************************************************************
4622 * NAME EXPORTED
4623 * MmCreateSection@
4624 *
4625 * DESCRIPTION
4626 * Creates a section object.
4627 *
4628 * ARGUMENTS
4629 * SectionObject (OUT)
4630 * Caller supplied storage for the resulting pointer
4631 * to a SECTION_OBJECT instance;
4632 *
4633 * DesiredAccess
4634 * Specifies the desired access to the section can be a
4635 * combination of:
4636 * STANDARD_RIGHTS_REQUIRED |
4637 * SECTION_QUERY |
4638 * SECTION_MAP_WRITE |
4639 * SECTION_MAP_READ |
4640 * SECTION_MAP_EXECUTE
4641 *
4642 * ObjectAttributes [OPTIONAL]
4643 * Initialized attributes for the object can be used
4644 * to create a named section;
4645 *
4646 * MaximumSize
4647 * Maximizes the size of the memory section. Must be
4648 * non-NULL for a page-file backed section.
4649 * If value specified for a mapped file and the file is
4650 * not large enough, file will be extended.
4651 *
4652 * SectionPageProtection
4653 * Can be a combination of:
4654 * PAGE_READONLY |
4655 * PAGE_READWRITE |
4656 * PAGE_WRITEONLY |
4657 * PAGE_WRITECOPY
4658 *
4659 * AllocationAttributes
4660 * Can be a combination of:
4661 * SEC_IMAGE |
4662 * SEC_RESERVE
4663 *
4664 * FileHandle
4665 * Handle to a file to create a section mapped to a file
4666 * instead of a memory backed section;
4667 *
4668 * File
4669 * Unknown.
4670 *
4671 * RETURN VALUE
4672 * Status.
4673 *
4674 * @implemented
4675 */
4685{
4687 ULONG Protection;
4688 PSECTION *SectionObject = (PSECTION *)Section;
4689 BOOLEAN FileLock = FALSE;
4690 BOOLEAN HaveFileObject = FALSE;
4691
4692 // FIXME: Implement support for large pages
4694 {
4695 DPRINT1("SEC_LARGE_PAGES is not supported\n");
4697 }
4698
4699 /* Check if an ARM3 section is being created instead */
4701 {
4702 if (!(FileObject) && !(FileHandle))
4703 {
4704 return MmCreateArm3Section(Section,
4710 FileHandle,
4711 FileObject);
4712 }
4713 }
4714
4715 /* Convert section flag to page flag */
4717
4718 /* Check to make sure the protection is correct. Nt* does this already */
4720 if (Protection == MM_INVALID_PROTECTION)
4721 {
4722 DPRINT1("Page protection is invalid\n");
4724 }
4725
4726 /* Check if this is going to be a data or image backed file section */
4727 if ((FileHandle) || (FileObject))
4728 {
4729 /* These cannot be mapped with large pages */
4731 {
4732 DPRINT1("Large pages cannot be used with an image mapping\n");
4734 }
4735
4736 /* Did the caller pass a file object ? */
4737 if (FileObject)
4738 {
4739 /* Reference the object directly */
4741 HaveFileObject = TRUE;
4742 }
4743 else
4744 {
4745 /* Reference the file handle to get the object */
4747 MmMakeFileAccess[Protection],
4750 (PVOID*)&FileObject,
4751 NULL);
4752 if (!NT_SUCCESS(Status))
4753 {
4754 DPRINT1("Failed to get a handle to the FO: %lx\n", Status);
4755 return Status;
4756 }
4757
4758 /* Lock the file */
4760 if (!NT_SUCCESS(Status))
4761 {
4763 return Status;
4764 }
4765
4766 FileLock = TRUE;
4767
4768 /* Deny access if there are writes on the file */
4769#if 0
4771 {
4772 DPRINT1("Cannot create image maps with writers open on the file!\n");
4774 goto Quit;
4775 }
4776#else
4778 DPRINT1("Creating image map with writers open on the file!\n");
4779#endif
4780 }
4781 }
4782 else
4783 {
4784 /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
4786 }
4787
4788 if (FileObject == NULL)
4789 {
4791 goto Exit;
4792 }
4793
4795 {
4802 FileObject);
4803
4804 /* If the file was ivalid, and we got a FileObject passed, fall back to data section */
4805 if (!NT_SUCCESS(Status) && HaveFileObject)
4806 {
4807 AllocationAttributes &= ~SEC_IMAGE;
4808 }
4809 }
4810
4811#ifndef NEWCC
4813 {
4820 FileObject,
4821 FileHandle != NULL);
4822 }
4823#else
4824 else
4825 {
4832 FileObject);
4833 }
4834#endif
4835
4836Exit:
4837
4838 if (FileLock)
4840 if (FileObject)
4842
4843 return Status;
4844}
4845
4846/* This function is not used. It is left for future use, when per-process
4847 * address space is considered. */
4848#if 0
4849BOOLEAN
4850NTAPI
4851MmArePagesResident(
4855{
4857 BOOLEAN Ret = TRUE;
4859 LARGE_INTEGER SegmentOffset, RangeEnd;
4861
4863
4865 if (MemoryArea == NULL)
4866 {
4868 return FALSE;
4869 }
4870
4871 /* Only supported in old Mm for now */
4873 /* For file mappings */
4875
4876 Segment = MemoryArea->SectionData.Segment;
4878
4880 + MemoryArea->SectionData.ViewOffset;
4882 + MemoryArea->SectionData.ViewOffset;
4883
4884 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
4885 {
4887 if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
4888 {
4889 Ret = FALSE;
4890 break;
4891 }
4892 SegmentOffset.QuadPart += PAGE_SIZE;
4893 }
4894
4896
4898 return Ret;
4899}
4900#endif
4901
4902/* Like CcPurgeCache but for the in-memory segment */
4903BOOLEAN
4904NTAPI
4909{
4910 LARGE_INTEGER PurgeStart, PurgeEnd;
4912
4913 PurgeStart.QuadPart = Offset ? Offset->QuadPart : 0LL;
4914 if (Length && Offset)
4915 {
4916 if (!NT_SUCCESS(RtlLongLongAdd(PurgeStart.QuadPart, Length, &PurgeEnd.QuadPart)))
4917 return FALSE;
4918 }
4919
4921 if (!Segment)
4922 {
4923 /* Nothing to purge */
4924 return TRUE;
4925 }
4926
4928
4929 if (!Length || !Offset)
4930 {
4931 /* We must calculate the length for ourselves */
4932 /* FIXME: All of this is suboptimal */
4933 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
4934 if (!ElemCount)
4935 {
4936 /* No page. Nothing to purge */
4938 MmDereferenceSegment(Segment);
4939 return TRUE;
4940 }
4941
4943 PurgeEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
4944 }
4945
4946 /* Find byte offset of the page to start */
4947 PurgeStart.QuadPart = PAGE_ROUND_DOWN_64(PurgeStart.QuadPart);
4948
4949 while (PurgeStart.QuadPart < PurgeEnd.QuadPart)
4950 {
4952
4953 if (Entry == 0)
4954 {
4955 PurgeStart.QuadPart += PAGE_SIZE;
4956 continue;
4957 }
4958
4960 {
4961 ASSERT(SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY);
4962 /* The page is currently being read. Meaning someone will need it soon. Bad luck */
4964 MmDereferenceSegment(Segment);
4965 return FALSE;
4966 }
4967
4968 if (IS_WRITE_SSE(Entry))
4969 {
4970 /* We're trying to purge an entry which is being written. Restart this loop iteration */
4974 continue;
4975 }
4976
4977 if (SHARE_COUNT_FROM_SSE(Entry) > 0)
4978 {
4979 /* This page is currently in use. Bad luck */
4981 MmDereferenceSegment(Segment);
4982 return FALSE;
4983 }
4984
4985 /* We can let this page go */
4986 MmSetPageEntrySectionSegment(Segment, &PurgeStart, 0);
4988
4989 PurgeStart.QuadPart += PAGE_SIZE;
4990 }
4991
4992 /* This page is currently in use. Bad luck */
4994 MmDereferenceSegment(Segment);
4995 return TRUE;
4996}
4997
4998BOOLEAN
4999NTAPI
5004{
5006 LARGE_INTEGER RangeStart, RangeEnd;
5007 BOOLEAN Ret = TRUE;
5008
5009 RangeStart.QuadPart = Offset;
5010 if (!NT_SUCCESS(RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart)))
5011 return FALSE;
5012
5014 if (!Segment)
5015 return FALSE;
5016
5017 /* Find byte offset of the page to start */
5018 RangeStart.QuadPart = PAGE_ROUND_DOWN_64(RangeStart.QuadPart);
5019
5021
5022 while (RangeStart.QuadPart < RangeEnd.QuadPart)
5023 {
5025 if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
5026 {
5027 Ret = FALSE;
5028 break;
5029 }
5030
5031 RangeStart.QuadPart += PAGE_SIZE;
5032 }
5033
5035 MmDereferenceSegment(Segment);
5036
5037 return Ret;
5038}
5039
5041NTAPI
5046 _In_ PLARGE_INTEGER ValidDataLength)
5047{
5049
5050 /* There must be a segment for this call */
5051 ASSERT(Segment);
5052
5054
5055 MmDereferenceSegment(Segment);
5056
5057 return Status;
5058}
5059
5061NTAPI
5066{
5068 LARGE_INTEGER RangeStart, RangeEnd;
5070
5071 RangeStart.QuadPart = Offset;
5072 Status = RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart);
5073 if (!NT_SUCCESS(Status))
5074 return Status;
5075
5077 if (!Segment)
5079
5080 /* Find byte offset of the page to start */
5081 RangeStart.QuadPart = PAGE_ROUND_DOWN_64(RangeStart.QuadPart);
5082
5084
5085 while (RangeStart.QuadPart < RangeEnd.QuadPart)
5086 {
5088
5089 /* Let any pending read proceed */
5090 while (MM_IS_WAIT_PTE(Entry))
5091 {
5096 }
5097
5098 /* We are called from Cc, this can't be backed by the page files */
5100
5101 /* If there is no page there, there is nothing to make dirty */
5102 if (Entry != 0)
5103 {
5104 /* Dirtify the entry */
5106 }
5107
5108 RangeStart.QuadPart += PAGE_SIZE;
5109 }
5110
5112 MmDereferenceSegment(Segment);
5113
5114 return STATUS_SUCCESS;
5115}
5116
5118NTAPI
5124{
5125 LARGE_INTEGER FlushStart, FlushEnd;
5127
5128 if (Offset)
5129 {
5130 FlushStart = *Offset;
5131 Status = RtlLongLongAdd(FlushStart.QuadPart, Length, &FlushEnd.QuadPart);
5132 if (!NT_SUCCESS(Status))
5133 return Status;
5134 }
5135
5136 if (Iosb)
5137 Iosb->Information = 0;
5138
5140 if (!Segment)
5141 {
5142 /* Nothing to flush */
5143 goto Quit;
5144 }
5145
5147
5149
5150 if (!Offset)
5151 {
5152 FlushStart.QuadPart = 0;
5153
5154 /* FIXME: All of this is suboptimal */
5155 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
5156 if (!ElemCount)
5157 {
5158 /* No page. Nothing to flush */
5160 MmDereferenceSegment(Segment);
5161 goto Quit;
5162 }
5163
5165 FlushEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
5166 }
5167
5168 /* Find byte offset of the page to start */
5169 FlushStart.QuadPart = PAGE_ROUND_DOWN_64(FlushStart.QuadPart);
5170
5171 while (FlushStart.QuadPart < FlushEnd.QuadPart)
5172 {
5174
5175 if (IS_DIRTY_SSE(Entry))
5176 {
5177 MmCheckDirtySegment(Segment, &FlushStart, FALSE, FALSE);
5178
5179 if (Iosb)
5180 Iosb->Information += PAGE_SIZE;
5181 }
5182
5183 FlushStart.QuadPart += PAGE_SIZE;
5184 }
5185
5187 MmDereferenceSegment(Segment);
5188
5189Quit:
5190 /* FIXME: Handle failures */
5191 if (Iosb)
5192 Iosb->Status = STATUS_SUCCESS;
5193
5194 return STATUS_SUCCESS;
5195}
5196
5198BOOLEAN
5199NTAPI
5205{
5209
5210 ASSERT(Segment->Locked);
5211
5212 ASSERT((Offset->QuadPart % PAGE_SIZE) == 0);
5213
5214 DPRINT("Checking segment for file %wZ at offset 0x%I64X.\n", &Segment->FileObject->FileName, Offset->QuadPart);
5215
5217 if (Entry == 0)
5218 return FALSE;
5219
5221 if ((IS_DIRTY_SSE(Entry)) || ForceDirty)
5222 {
5223 BOOLEAN DirtyAgain;
5224
5225 /*
5226 * We got a dirty entry. This path is for the shared data,
5227 * be-it regular file maps or shared sections of DLLs
5228 */
5230 FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5231
5232 /* Insert the cleaned entry back. Mark it as write in progress, and clear the dirty bit. */
5236
5238
5239 if (FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5240 {
5242 KIRQL OldIrql;
5243
5244 /* We have to write it back to the file. Tell the FS driver who we are */
5245 if (PageOut)
5246 {
5247 LARGE_INTEGER EndOffset = *Offset;
5248
5250
5251 /* We need to disable all APCs */
5253
5254 EndOffset.QuadPart += PAGE_SIZE;
5256 &EndOffset,
5258 if (NT_SUCCESS(Status))
5259 {
5261 }
5262 else
5263 {
5264 /* Make sure we will not try to release anything */
5266 }
5267 }
5268 else
5269 {
5270 /* We don't have to lock. Say this is success */
5272 }
5273
5274 /* Go ahead and write the page, if previous locking succeeded */
5275 if (NT_SUCCESS(Status))
5276 {
5277 DPRINT("Writing page at offset %I64d for file %wZ, Pageout: %s\n",
5278 Offset->QuadPart, &Segment->FileObject->FileName, PageOut ? "TRUE" : "FALSE");
5279 Status = MiWritePage(Segment, Offset->QuadPart, Page);
5280 }
5281
5282 if (PageOut)
5283 {
5285 if (ResourceToRelease != NULL)
5286 {
5288 }
5290 }
5291 }
5292 else
5293 {
5294 /* This must only be called by the page-out path */
5295 ASSERT(PageOut);
5296
5297 /* And this must be for a shared section in a DLL */
5298 ASSERT(FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5299
5301 if (!SwapEntry)
5302 {
5303 SwapEntry = MmAllocSwapPage();
5304 }
5305
5306 if (SwapEntry)
5307 {
5308 Status = MmWriteToSwapPage(SwapEntry, Page);
5309 if (NT_SUCCESS(Status))
5310 {
5311 MmSetSavedSwapEntryPage(Page, SwapEntry);
5312 }
5313 else
5314 {
5315 MmFreeSwapPage(SwapEntry);
5316 }
5317 }
5318 else
5319 {
5320 DPRINT1("Failed to allocate a swap page!\n");
5322 }
5323 }
5324
5326
5327 /* Get the entry again */
5330
5331 if (!NT_SUCCESS(Status))
5332 {
5333 /* Damn, this failed. Consider this page as still dirty */
5334 DPRINT1("MiWritePage FAILED: Status 0x%08x!\n", Status);
5335 DirtyAgain = TRUE;
5336 }
5337 else
5338 {
5339 /* Check if someone dirtified this page while we were not looking */
5340 DirtyAgain = IS_DIRTY_SSE(Entry);
5341 }
5342
5343 /* Drop the reference we got, deleting the write altogether. */
5345 if (DirtyAgain)
5346 {
5348 }
5350 }
5351
5352 /* Were this page hanging there just for the sake of being present ? */
5354 {
5355 ULONG_PTR NewEntry = 0;
5356 /* Restore the swap entry here */
5357 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5358 {
5360 if (SwapEntry)
5361 NewEntry = MAKE_SWAP_SSE(SwapEntry);
5362 }
5363
5364 /* Yes. Release it */
5367 /* Tell the caller we released the page */
5368 return TRUE;
5369 }
5370
5371 return FALSE;
5372}
5373
5374/* This function is not used. It is left for future use, when per-process
5375 * address space is considered. */
5376#if 0
5378NTAPI
5379MmMakePagesDirty(
5383{
5386 LARGE_INTEGER SegmentOffset, RangeEnd;
5388
5390
5392 if (MemoryArea == NULL)
5393 {
5394 DPRINT1("Unable to find memory area at address %p.\n", Address);
5397 }
5398
5399 /* Only supported in old Mm for now */
5401 /* For file mappings */
5403
5404 Segment = MemoryArea->SectionData.Segment;
5406
5408 + MemoryArea->SectionData.ViewOffset;
5410 + MemoryArea->SectionData.ViewOffset;
5411
5412 DPRINT("MmMakePagesResident: Segment %p, 0x%I64x -> 0x%I64x\n", Segment, SegmentOffset.QuadPart, RangeEnd.QuadPart);
5413
5414 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
5415 {
5417
5418 /* Let any pending read proceed */
5419 while (MM_IS_WAIT_PTE(Entry))
5420 {
5426 Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset);
5427 }
5428
5429 /* We are called from Cc, this can't be backed by the page files */
5431
5432 /* If there is no page there, there is nothing to make dirty */
5433 if (Entry != 0)
5434 {
5435 /* Dirtify the entry */
5437 }
5438
5439 SegmentOffset.QuadPart += PAGE_SIZE;
5440 }
5441
5443
5445 return STATUS_SUCCESS;
5446}
5447#endif
5448
5450NTAPI
5452 _In_ PVOID _Section,
5454{
5455 PSECTION Section = _Section;
5456
5457 /* It makes no sense to extend an image mapping */
5458 if (Section->u.Flags.Image)
5460
5461 /* Nor is it possible to extend a page file mapping */
5462 if (!Section->u.Flags.File)
5464
5465 if (!MiIsRosSectionObject(Section))
5467
5468 /* We just extend the sizes. Shrinking is a no-op ? */
5469 if (NewSize->QuadPart > Section->SizeOfSection.QuadPart)
5470 {
5472 Section->SizeOfSection = *NewSize;
5473
5474 if (!Section->u.Flags.Reserve)
5475 {
5477 if (Segment->RawLength.QuadPart < NewSize->QuadPart)
5478 {
5479 Segment->RawLength = *NewSize;
5480 Segment->Length.QuadPart = (NewSize->QuadPart + PAGE_SIZE - 1) & ~((LONGLONG)PAGE_SIZE);
5481 }
5483 }
5484 }
5485
5486 return STATUS_SUCCESS;
5487}
5488
5489/* EOF */
NTSTATUS MiMapViewInSystemSpace(_In_ PVOID Section, _In_ PMMSESSION Session, _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, _Inout_ PSIZE_T ViewSize, _Inout_ PLARGE_INTEGER SectionOffset)
Definition: section.c:1041
MMSESSION MmSession
Definition: section.c:107
NTSTATUS NTAPI MmCreateArm3Section(OUT PVOID *SectionObject, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER InputMaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: section.c:2105
VOID NTAPI MiDeleteARM3Section(PVOID ObjectBody)
Definition: section.c:2958
NTSTATUS NTAPI MmMapViewOfArm3Section(_In_ PVOID SectionObject, _In_ PEPROCESS Process, _Outptr_result_bytebuffer_(*ViewSize) _When_(*ViewSize !=0, _Pre_opt_valid_) _When_(*ViewSize==0, _Pre_valid_) PVOID *BaseAddress, _In_ ULONG_PTR ZeroBits, _In_ SIZE_T CommitSize, _Inout_ PLARGE_INTEGER SectionOffset, _Inout_ PSIZE_T ViewSize, _In_range_(ViewShare, ViewUnmap) SECTION_INHERIT InheritDisposition, _In_ ULONG AllocationType, _In_ ULONG Protect)
Definition: section.c:2534
ACCESS_MASK MmMakeFileAccess[8]
Definition: section.c:32
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:140
#define PAGED_CODE()
#define CODE_SEG(...)
ULONG ReadLength
#define ALIGN_DOWN_BY(size, align)
#define ALIGN_UP_BY(size, align)
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG _In_ KPROCESSOR_MODE PreviousMode
ULONG_PTR PFN_NUMBER
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
unsigned char BOOLEAN
Definition: actypes.h:127
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define MIN(x, y)
Definition: rdesktop.h:171
#define DPRINT1
Definition: precomp.h:8
#define MAXULONG_PTR
Definition: basetsd.h:97
DECLSPEC_NORETURN VOID NTAPI KeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
Definition: debug.c:485
#define InterlockedIncrement64(a)
Definition: btrfs_drv.h:143
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1434
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
Definition: bufpool.h:45
Definition: File.h:16
#define _Requires_lock_held_(lock)
#define _Requires_lock_not_held_(lock)
#define _Releases_lock_(lock)
#define _Requires_exclusive_lock_held_(lock)
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_Out_ PKIRQL Irql
Definition: csq.h:179
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
VOID NTAPI DbgkUnMapViewOfSection(IN PVOID BaseAddress)
Definition: dbgkutil.c:436
#define BufferSize
Definition: mmc.h:75
LPWSTR Name
Definition: desk.c:124
#define SIZE_T_MAX
Definition: dhcpd.h:91
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define PAGE_READONLY
Definition: compat.h:138
#define SECTION_MAP_READ
Definition: compat.h:139
#define __cdecl
Definition: corecrt.h:121
_ACRTIMP void __cdecl qsort(void *, size_t, size_t, int(__cdecl *)(const void *, const void *))
#define L(x)
Definition: resources.c:13
return Iosb
Definition: create.c:4403
#define ULONG_PTR
Definition: config.h:101
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define _IRQL_restores_
Definition: driverspecs.h:233
#define _IRQL_requires_(irql)
Definition: driverspecs.h:229
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define PagedPool
Definition: env_spec_w32.h:308
#define ExGetPreviousMode
Definition: ex.h:143
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1544
#define EXEFMT_LOAD_ASSUME_SEGMENTS_SORTED
Definition: exeformat.h:8
#define STATUS_ROS_EXEFMT_UNKNOWN_FORMAT
Definition: exeformat.h:72
#define PEFMT_FIELDS_EQUAL(TYPE1_, TYPE2_, FIELD_)
Definition: exeformat.h:165
#define EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED
Definition: exeformat.h:10
static __inline BOOLEAN IsPowerOf2(IN ULONG Number)
Definition: exeformat.h:134
static __inline BOOLEAN Intsafe_CanAddLong64(IN LONG64 Addend1, IN LONG64 Addend2)
Definition: exeformat.h:104
NTSTATUS(NTAPI * PEXEFMT_CB_READ_FILE)(IN PVOID File, IN PLARGE_INTEGER Offset, IN ULONG Length, OUT PVOID *Data, OUT PVOID *AllocBase, OUT PULONG ReadSize)
Definition: exeformat.h:36
#define EXEFMT_LOAD_ASSUME_SEGMENTS_NO_OVERLAP
Definition: exeformat.h:9
static __inline BOOLEAN Intsafe_CanMulULong32(IN ULONG Factor1, IN ULONG Factor2)
Definition: exeformat.h:123
NTSTATUS(NTAPI * PEXEFMT_LOADER)(IN CONST VOID *FileHeader, IN SIZE_T FileHeaderSize, IN PVOID File, OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, OUT PULONG Flags, IN PEXEFMT_CB_READ_FILE ReadFileCb, IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb)
Definition: exeformat.h:51
static __inline BOOLEAN Intsafe_CanAddULong32(IN ULONG Addend1, IN ULONG Addend2)
Definition: exeformat.h:109
#define EXEFMT_LOAD_HEADER_SIZE
Definition: exeformat.h:23
PMM_SECTION_SEGMENT(NTAPI * PEXEFMT_CB_ALLOCATE_SEGMENTS)(IN ULONG NrSegments)
Definition: exeformat.h:46
static __inline BOOLEAN IsAligned(IN ULONG Address, IN ULONG Alignment)
Definition: exeformat.h:147
static __inline BOOLEAN Intsafe_CanOffsetPointer(IN CONST VOID *Pointer, IN SIZE_T Offset)
Definition: exeformat.h:128
static __inline BOOLEAN Intsafe_AddULong32(OUT PULONG Result, IN ULONG Addend1, IN ULONG Addend2)
Definition: exeformat.h:114
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN PFCB IN FAT_FLUSH_TYPE FlushType
Definition: fatprocs.h:1083
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
#define STATUS_ACCESS_VIOLATION
@ FileEndOfFileInformation
Definition: from_kernel.h:81
_Must_inspect_result_ _In_ PDEVICE_OBJECT _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer
Definition: fsrtlfuncs.h:1369
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
#define FSRTL_MOD_WRITE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:61
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define InterlockedDecrement64
Definition: interlocked.h:159
#define C_ASSERT(e)
Definition: intsafe.h:73
NTSTATUS NTAPI IoPageRead(IN PFILE_OBJECT FileObject, IN PMDL Mdl, IN PLARGE_INTEGER Offset, IN PKEVENT Event, IN PIO_STATUS_BLOCK StatusBlock)
Definition: iofunc.c:1201
NTSTATUS NTAPI IoSetInformation(IN PFILE_OBJECT FileObject, IN FILE_INFORMATION_CLASS FileInformationClass, IN ULONG Length, IN PVOID FileInformation)
Definition: iofunc.c:1314
NTSTATUS NTAPI IoSynchronousPageWrite(IN PFILE_OBJECT FileObject, IN PMDL Mdl, IN PLARGE_INTEGER Offset, IN PKEVENT Event, IN PIO_STATUS_BLOCK StatusBlock)
Definition: iofunc.c:1146
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
if(dx< 0)
Definition: linetemp.h:194
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
FORCEINLINE BOOLEAN MiIsRosSectionObject(IN PSECTION Section)
Definition: miarm.h:1105
#define _64K
Definition: miarm.h:23
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
NTSTATUS NTAPI MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:4614
NTSTATUS NTAPI MiRosUnmapViewOfSection(_In_ PEPROCESS Process, _In_ PMEMORY_AREA MemoryArea, _In_ PVOID BaseAddress, _In_ BOOLEAN SkipDebuggerNotify)
Definition: section.c:3630
VOID NTAPI MmUnmapLockedPages(IN PVOID BaseAddress, IN PMDL Mdl)
Definition: mdlsup.c:837
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
unsigned __int64 ULONG64
Definition: imports.h:198
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define SECTION
Definition: profile.c:31
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
#define min(a, b)
Definition: monoChain.cc:55
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
unsigned int UINT
Definition: ndis.h:50
#define MM_ALLOCATION_GRANULARITY
Definition: mmtypes.h:36
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER SectionOffset
Definition: mmfuncs.h:407
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID _In_ ULONG_PTR ZeroBits
Definition: mmfuncs.h:405
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER MaximumSize
Definition: mmfuncs.h:362
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG SectionPageProtection
Definition: mmfuncs.h:363
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ ULONG AllocationType
Definition: mmfuncs.h:410
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ ULONG AllocationAttributes
Definition: mmfuncs.h:364
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID * BaseAddress
Definition: mmfuncs.h:404
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:408
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:406
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
struct _SEGMENT * PSEGMENT
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
enum _SECTION_INFORMATION_CLASS SECTION_INFORMATION_CLASS
@ VadImageMap
Definition: mmtypes.h:206
#define MEM_IMAGE
Definition: mmtypes.h:89
#define SEC_NOCACHE
Definition: mmtypes.h:101
struct _SECTION_IMAGE_INFORMATION * PSECTION_IMAGE_INFORMATION
#define SEC_COMMIT
Definition: mmtypes.h:100
#define SEC_IMAGE
Definition: mmtypes.h:97
struct _MMSUPPORT * PMMSUPPORT
#define SEC_FILE
Definition: mmtypes.h:96
#define SEC_LARGE_PAGES
Definition: mmtypes.h:103
#define SEC_NO_CHANGE
Definition: mmtypes.h:95
struct _MEMORY_BASIC_INFORMATION MEMORY_BASIC_INFORMATION
@ SectionBasicInformation
Definition: mmtypes.h:195
@ SectionImageInformation
Definition: mmtypes.h:196
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
#define OBJ_KERNEL_EXCLUSIVE
Definition: obtypes.h:91
NTSTATUS NTAPI MmCreateCacheSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
VOID NTAPI MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage)
Definition: sptab.c:321
_In_ PMEMORY_AREA MemoryArea
Definition: newmm.h:207
NTSTATUS NTAPI MmUnmapViewOfCacheSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
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)
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:209
VOID NTAPI MiInitializeSectionPageTable(PMM_SECTION_SEGMENT Segment)
Definition: sptab.c:165
#define _Outptr_result_bytebuffer_(s)
Definition: no_sal2.h:288
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Pre_valid_
Definition: no_sal2.h:518
#define _Inout_opt_
Definition: no_sal2.h:216
#define _Pre_opt_valid_
Definition: no_sal2.h:520
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _In_range_(l, h)
Definition: no_sal2.h:368
#define _When_(c, a)
Definition: no_sal2.h:38
#define MEM_TOP_DOWN
Definition: nt_native.h:1324
#define SECTION_MAP_EXECUTE
Definition: nt_native.h:1293
#define PAGE_WRITECOPY
Definition: nt_native.h:1308
#define SECTION_MAP_WRITE
Definition: nt_native.h:1291
#define PAGE_NOCACHE
Definition: nt_native.h:1314
#define PAGE_READWRITE
Definition: nt_native.h:1307
#define PAGE_EXECUTE_READ
Definition: nt_native.h:1310
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1296
#define SECTION_QUERY
Definition: nt_native.h:1290
#define PAGE_EXECUTE
Definition: nt_native.h:1309
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define SEC_RESERVE
Definition: nt_native.h:1326
#define MEM_MAPPED
Definition: nt_native.h:1322
enum _SECTION_INHERIT SECTION_INHERIT
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
@ ViewUnmap
Definition: nt_native.h:1282
@ ViewShare
Definition: nt_native.h:1281
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define PAGE_EXECUTE_WRITECOPY
Definition: nt_native.h:1312
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
#define MEM_COMMIT
Definition: nt_native.h:1316
#define PAGE_NOACCESS
Definition: nt_native.h:1305
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1311
#define PAGE_GUARD
Definition: nt_native.h:1313
#define TYPE_ALIGNMENT(t)
Definition: ntbasedef.h:117
#define RTL_CONTAINS_FIELD(Struct, Size, Field)
Definition: ntbasedef.h:687
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:684
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
#define SEC_BASED
#define IMAGE_SCN_MEM_WRITE
Definition: ntimage.h:241
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC
Definition: ntimage.h:376
#define IMAGE_SCN_CNT_INITIALIZED_DATA
Definition: ntimage.h:231
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC
Definition: ntimage.h:377
#define IMAGE_SCN_CNT_CODE
Definition: ntimage.h:230
#define IMAGE_SCN_MEM_EXECUTE
Definition: ntimage.h:239
#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION
Definition: ntimage.h:458
#define IMAGE_SCN_MEM_READ
Definition: ntimage.h:240
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA
Definition: ntimage.h:232
#define IMAGE_SCN_MEM_SHARED
Definition: ntimage.h:238
NTSTATUS NTAPI MiSimpleRead(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PVOID Buffer, ULONG Length, BOOLEAN Paging, PIO_STATUS_BLOCK ReadStatus)
Definition: io.c:109
NTSTATUS NTAPI FsRtlGetFileSize(IN PFILE_OBJECT FileObject, IN OUT PLARGE_INTEGER FileSize)
Definition: fastio.c:815
_Check_return_ NTSTATUS NTAPI FsRtlAcquireFileForModWriteEx(_In_ PFILE_OBJECT FileObject, _In_ PLARGE_INTEGER EndingOffset, _Outptr_result_maybenull_ PERESOURCE *ResourceToRelease)
Lock a file object before flushing pages to disk. To be called by the Modified Page Writer (MPW)
Definition: fastio.c:1858
VOID NTAPI FsRtlReleaseFileForModWrite(_In_ PFILE_OBJECT FileObject, _In_ PERESOURCE ResourceToRelease)
Unlock a file object after flushing pages to disk. To be called by the Modified Page Writer (MPW) aft...
Definition: fastio.c:1965
VOID NTAPI FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1665
VOID NTAPI FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1640
NTSTATUS NTAPI FsRtlAcquireToCreateMappedSection(_In_ PFILE_OBJECT FileObject, _In_ ULONG SectionPageProtection)
Definition: fastio.c:1653
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:46
#define MmGetPageEntrySectionSegment(S, O)
Definition: mm.h:1601
#define MI_SET_PROCESS2(x)
Definition: mm.h:329
#define MM_NOIRQL
Definition: mm.h:70
@ MI_USAGE_SECTION
Definition: mm.h:343
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1695
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
KSPIN_LOCK MmPfnLock
Definition: krnlinit.c:45
#define DIRTY_SSE(E)
Definition: mm.h:1374
VOID NTAPI MiUnmapPageInHyperSpace(IN PEPROCESS Process, IN PVOID Address, IN KIRQL OldIrql)
Definition: hypermap.c:91
VOID NTAPI MmGetPageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY *SwapEntry)
Definition: page.c:299
ULONG NTAPI MmGetPageProtect(struct _EPROCESS *Process, PVOID Address)
#define MmLockSectionSegment(x)
Definition: mm.h:1396
NTSTATUS NTAPI MmCreateMemoryArea(PMMSUPPORT AddressSpace, ULONG Type, PVOID *BaseAddress, SIZE_T Length, ULONG Protection, PMEMORY_AREA *Result, ULONG AllocationFlags, ULONG AllocationGranularity)
#define MAKE_SSE(P, C)
Definition: mm.h:1386
#define MAX_SHARE_COUNT
Definition: mm.h:1385
#define SHARE_COUNT_FROM_SSE(E)
Definition: mm.h:1384
#define MC_USER
Definition: mm.h:112
PVOID NTAPI MiMapPageInHyperSpace(IN PEPROCESS Process, IN PFN_NUMBER Page, IN PKIRQL OldIrql)
Definition: hypermap.c:28
#define MM_VIRTMEM_GRANULARITY
Definition: mm.h:102
NTSTATUS NTAPI MmFreeMemoryArea(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_FREE_PAGE_FUNC FreePage, PVOID FreePageContext)
Definition: marea.c:258
#define IS_WRITE_SSE(E)
Definition: mm.h:1378
#define MmUnlockSectionSegment(x)
Definition: mm.h:1404
BOOLEAN NTAPI MmIsPageSwapEntry(struct _EPROCESS *Process, PVOID Address)
BOOLEAN NTAPI MmIsDisabledPage(struct _EPROCESS *Process, PVOID Address)
SWAPENTRY NTAPI MmAllocSwapPage(VOID)
Definition: pagefile.c:322
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:61
#define IS_DIRTY_SSE(E)
Definition: mm.h:1376
struct _MM_IMAGE_SECTION_OBJECT * PMM_IMAGE_SECTION_OBJECT
#define SWAPENTRY_FROM_SSE(E)
Definition: mm.h:1372
BOOLEAN NTAPI MmCheckDirtySegment(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, BOOLEAN ForceDirty, BOOLEAN PageOut)
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:97
struct _MM_SECTION_SEGMENT MM_SECTION_SEGMENT
NTSTATUS NTAPI MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
Definition: pagefile.c:147
VOID NTAPI MmInitializeRegion(PLIST_ENTRY RegionListHead, SIZE_T Length, ULONG Type, ULONG Protect)
Definition: region.c:239
PMM_REGION NTAPI MmFindRegion(PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID Address, PVOID *RegionBaseAddress)
Definition: region.c:257
#define MAKE_SWAP_SSE(S)
Definition: mm.h:1373
ULONG_PTR SWAPENTRY
Definition: mm.h:57
#define MA_GetEndingAddress(_MemoryArea)
Definition: mm.h:251
PFN_NUMBER NTAPI MmGetPfnForProcess(struct _EPROCESS *Process, PVOID Address)
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:250
#define PAGE_IS_WRITABLE
Definition: mm.h:159
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1708
NTSTATUS NTAPI MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
Definition: pagefile.c:204
VOID NTAPI MmDeletePageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY *SwapEntry)
#define PAGE_FROM_SSE(E)
Definition: mm.h:1382
#define MI_SET_USAGE(x)
Definition: mm.h:327
#define MM_SEGMENT_INDELETE
Definition: mm.h:245
#define PAGE_FLAGS_VALID_FOR_SECTION
Definition: mm.h:139
#define MM_SEGMENT_INCREATE
Definition: mm.h:246
NTSTATUS NTAPI MmExtendSection(_In_ PVOID Section, _Inout_ PLARGE_INTEGER NewSize)
Definition: section.c:5451
BOOLEAN NTAPI MmIsAddressRangeFree(_In_ PMMSUPPORT AddressSpace, _In_ PVOID Address, _In_ ULONG_PTR Length)
Definition: marea.c:111
FORCEINLINE PEPROCESS MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
Definition: mm.h:1715
BOOLEAN NTAPI MmIsPagePresent(struct _EPROCESS *Process, PVOID Address)
VOID NTAPI MmFreeSwapPage(SWAPENTRY Entry)
Definition: pagefile.c:291
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1769
VOID NTAPI MmSetSavedSwapEntryPage(PFN_NUMBER Page, SWAPENTRY SavedSwapEntry)
Definition: freelist.c:484
NTSTATUS NTAPI MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID StartAddress, SIZE_T Length, ULONG NewType, ULONG NewProtect, PMM_ALTER_REGION_FUNC AlterFunc)
Definition: region.c:108
#define PAGE_IS_EXECUTABLE
Definition: mm.h:165
NTSTATUS NTAPI MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN MyWait, PPFN_NUMBER AllocatedPage)
Definition: balance.c:313
#define PFN_FROM_SSE(E)
Definition: mm.h:1367
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:93
SWAPENTRY NTAPI MmGetSavedSwapEntryPage(PFN_NUMBER Page)
Definition: freelist.c:500
NTSTATUS NTAPI MmCreatePhysicalMapping(_Inout_opt_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG flProtect, _In_ PFN_NUMBER Page)
Definition: page.c:735
#define MM_IMAGE_SECTION_FLUSH_DELETE
Definition: mm.h:247
#define PAGE_ROUND_DOWN_64(x)
Definition: mm.h:136
NTSTATUS NTAPI MmCreateVirtualMapping(struct _EPROCESS *Process, PVOID Address, ULONG flProtect, PFN_NUMBER Page)
NTSTATUS NTAPI MmCreatePageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY SwapEntry)
VOID NTAPI MmDeleteRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
struct _MM_SECTION_SEGMENT * PMM_SECTION_SEGMENT
PVOID NTAPI MmFindGap(PMMSUPPORT AddressSpace, SIZE_T Length, ULONG_PTR Granularity, BOOLEAN TopDown)
#define DECREF_SSE(E)
Definition: mm.h:1388
#define MM_ROUND_DOWN(x, s)
Definition: mm.h:129
#define MM_IS_WAIT_PTE(E)
Definition: mm.h:1369
#define MM_PHYSICALMEMORY_SEGMENT
Definition: mm.h:243
#define BUMPREF_SSE(E)
Definition: mm.h:1387
#define IS_SWAP_FROM_SSE(E)
Definition: mm.h:1368
NTSTATUS NTAPI MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
Definition: balance.c:72
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1730
VOID NTAPI MmInsertRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
#define MM_DATAFILE_SEGMENT
Definition: mm.h:244
#define STATUS_MM_RESTART_OPERATION
Definition: mm.h:104
#define PAGE_IS_READABLE
Definition: mm.h:151
#define WRITE_SSE(E)
Definition: mm.h:1377
#define PAGE_IS_WRITECOPY
Definition: mm.h:171
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
const ULONG MmProtectToValue[32]
Definition: page.c:71
VOID NTAPI MmDeleteVirtualMapping(IN PEPROCESS Process, IN PVOID Address, OUT PBOOLEAN WasDirty, OUT PPFN_NUMBER Page)
Definition: page.c:177
#define STATUS_INVALID_VIEW_SIZE
Definition: ntstatus.h:361
#define STATUS_INVALID_IMAGE_WIN_64
Definition: ntstatus.h:1029
#define STATUS_SECTION_PROTECTION
Definition: ntstatus.h:408
#define STATUS_INVALID_IMAGE_FORMAT
Definition: ntstatus.h:453
#define STATUS_SECTION_NOT_IMAGE
Definition: ntstatus.h:403
#define STATUS_NOT_MAPPED_VIEW
Definition: ntstatus.h:355
#define STATUS_INVALID_IMAGE_NOT_MZ
Definition: ntstatus.h:633
#define STATUS_INVALID_IMAGE_PROTECT
Definition: ntstatus.h:634
#define STATUS_FILE_LOCKED_WITH_WRITERS
Definition: ntstatus.h:168
#define STATUS_INVALID_FILE_FOR_SECTION
Definition: ntstatus.h:362
#define STATUS_MAPPED_FILE_SIZE_ZERO
Definition: ntstatus.h:616
#define STATUS_INVALID_PARAMETER_6
Definition: ntstatus.h:574
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:336
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:354
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:399
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:333
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:262
#define STATUS_SECTION_NOT_EXTENDED
Definition: ntstatus.h:465
#define STATUS_IMAGE_NOT_AT_BASE
Definition: ntstatus.h:192
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
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:1039
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1136
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define CONST
Definition: pedump.c:81
#define IMAGE_NT_SIGNATURE
Definition: pedump.c:93
#define IMAGE_FILE_DLL
Definition: pedump.c:169
#define IMAGE_DOS_SIGNATURE
Definition: pedump.c:89
struct _IMAGE_SECTION_HEADER IMAGE_SECTION_HEADER
static WCHAR Address[46]
Definition: ping.c:68
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
#define OBJ_OPENLINK
Definition: winternl.h:230
#define OBJ_PERMANENT
Definition: winternl.h:226
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:207
PVOID pBuffer
VOID NTAPI MmBuildMdlFromPages(PMDL Mdl, PPFN_NUMBER Pages)
Definition: pagefile.c:111
@ Failed
Definition: arc.h:88
#define ASSERT_IRQL_LESS(x)
Definition: debug.h:253
unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask)
Definition: intrin_arm.h:57
ULONG * PPFN_NUMBER
Definition: ke.h:9
static GENERIC_MAPPING MmpSectionMapping
Definition: section.c:225
PFN_NUMBER Page
Definition: section.c:5208
NTSTATUS NTAPI MmMapViewInSystemSpace(IN PVOID SectionObject, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:4504
BOOLEAN NTAPI MmCanFileBeTruncated(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
Definition: section.c:4312
static NTSTATUS NTAPI MmCreateDataFileSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject, BOOLEAN GotFileHandle)
Definition: section.c:2363
VOID NTAPI MmpDeleteSection(PVOID ObjectBody)
Definition: section.c:2174
static LARGE_INTEGER TinyTime
Definition: section.c:61
PMM_IMAGE_SECTION_OBJECT ImageSectionObjectFromSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:118
NTSTATUS NTAPI ElfFmtCreateSection(IN CONST VOID *FileHeader, IN SIZE_T FileHeaderSize, IN PVOID File, OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, OUT PULONG Flags, IN PEXEFMT_CB_READ_FILE ReadFileCb, IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb)
NTSTATUS NTAPI MmMakeSegmentDirty(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
Definition: section.c:5062
NTSTATUS NTAPI PeFmtCreateSection(IN CONST VOID *FileHeader, IN SIZE_T FileHeaderSize, IN PVOID File, OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, OUT PULONG Flags, IN PEXEFMT_CB_READ_FILE ReadFileCb, IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb)
Definition: section.c:287
static PMM_SECTION_SEGMENT NTAPI ExeFmtpAllocateSegments(IN ULONG NrSegments)
Definition: section.c:2624
ULONG_PTR MmSubsectionBase
Definition: section.c:198
static BOOLEAN NTAPI MmspPageAlignSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2875
NTSTATUS NTAPI MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, MEMORY_AREA *MemoryArea, PVOID Address, BOOLEAN Locked)
Definition: section.c:1560
NTSTATUS MmspWaitForFileLock(PFILE_OBJECT File)
Definition: section.c:909
PLARGE_INTEGER BOOLEAN BOOLEAN PageOut
Definition: section.c:5205
static BOOLEAN NTAPI MmspCheckSegmentBounds(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2824
#define MmSetPageEntrySectionSegment(S, O, E)
Definition: section.c:56
static ULONG SectionCharacteristicsToProtect[16]
Definition: section.c:200
NTSTATUS NTAPI MmCreateSection(OUT PVOID *Section, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: section.c:4677
static BOOLEAN MiPurgeImageSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:4367
POBJECT_TYPE MmSectionObjectType
Definition: section.c:196
NTSTATUS NTAPI MmMapViewOfSection(_In_ PVOID SectionObject, _In_ PEPROCESS Process, _Outptr_result_bytebuffer_(*ViewSize) _Pre_opt_valid_ PVOID *BaseAddress, _In_ ULONG_PTR ZeroBits, _In_ SIZE_T CommitSize, _Inout_opt_ PLARGE_INTEGER SectionOffset, _Inout_ PSIZE_T ViewSize, _In_range_(ViewShare, ViewUnmap) SECTION_INHERIT InheritDisposition, _In_ ULONG AllocationType, _In_ ULONG Protect)
Definition: section.c:4031
VOID NTAPI _MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line)
Definition: section.c:77
static NTSTATUS MmUnmapViewOfSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
Definition: section.c:3566
BOOLEAN NTAPI MmPurgeSegment(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length)
Definition: section.c:4905
BOOLEAN NTAPI MmUnsharePageEntrySectionSegment(PMEMORY_AREA MemoryArea, PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, BOOLEAN Dirty, BOOLEAN PageOut, ULONG_PTR *InEntry)
Definition: section.c:1091
NTSTATUS NTAPI MmQuerySectionView(PMEMORY_AREA MemoryArea, PVOID Address, PMEMORY_BASIC_INFORMATION Info, PSIZE_T ResultLength)
Definition: section.c:2135
NTSTATUS NTAPI MmProtectSectionView(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PVOID BaseAddress, SIZE_T Length, ULONG Protect, PULONG OldProtect)
Definition: section.c:2091
VOID NTAPI MmpCloseSection(IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG ProcessHandleCount, IN ULONG SystemHandleCount)
Definition: section.c:2227
NTSTATUS NTAPI MmMapViewInSystemSpaceEx(_In_ PVOID SectionObject, _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, _Inout_ PSIZE_T ViewSize, _Inout_ PLARGE_INTEGER SectionOffset, _In_ ULONG_PTR Flags)
Definition: section.c:4517
Entry
Definition: section.c:5216
static VOID NTAPI FreeSegmentPage(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
Definition: section.c:962
NTSTATUS NTAPI MiWritePage(PMM_SECTION_SEGMENT Segment, LONGLONG SegOffset, PFN_NUMBER Page)
Definition: section.c:240
VOID NTAPI MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:919
static VOID NTAPI MmspAssertSegmentsPageAligned(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2763
static VOID NTAPI MmspSortSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2798
NTSTATUS NTAPI MmAccessFaultSectionView(PMMSUPPORT AddressSpace, MEMORY_AREA *MemoryArea, PVOID Address, BOOLEAN Locked)
Definition: section.c:1938
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4413
static NTSTATUS MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
Definition: section.c:1172
NTSTATUS NTAPI NtQuerySection(_In_ HANDLE SectionHandle, _In_ SECTION_INFORMATION_CLASS SectionInformationClass, _Out_ PVOID SectionInformation, _In_ SIZE_T SectionInformationLength, _Out_opt_ PSIZE_T ResultLength)
Definition: section.c:3812
static NTSTATUS NTAPI ExeFmtpReadFile(IN PVOID File, IN PLARGE_INTEGER Offset, IN ULONG Length, OUT PVOID *Data, OUT PVOID *AllocBase, OUT PULONG ReadSize)
Definition: section.c:2644
NTSTATUS MmCreateImageSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
Definition: section.c:3211
BOOLEAN NTAPI MmIsDataSectionResident(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
Definition: section.c:5000
NTSTATUS NTAPI MmFlushSegment(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: section.c:5119
static VOID NTAPI MmspAssertSegmentsSorted(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2727
NTSTATUS NTAPI MmInitSectionImplementation(VOID)
Definition: section.c:2330
static PEXEFMT_LOADER ExeFmtpLoaders[]
Definition: section.c:2613
static VOID MmAlterViewAttributes(PMMSUPPORT AddressSpace, PVOID BaseAddress, SIZE_T RegionSize, ULONG OldType, ULONG OldProtect, ULONG NewType, ULONG NewProtect)
Definition: section.c:1469
VOID NTAPI MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
Definition: section.c:1066
VOID NTAPI _MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line)
Definition: section.c:68
NTSTATUS NTAPI MmMakeDataSectionResident(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length, _In_ PLARGE_INTEGER ValidDataLength)
Definition: section.c:5042
static int __cdecl MmspCompareSegments(const void *x, const void *y)
Definition: section.c:2778
KEVENT MmWaitPageEvent
Definition: section.c:64
static VOID NTAPI MmspAssertSegmentsNoOverlap(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2741
static NTSTATUS NTAPI MmMakeSegmentResident(_In_ PMM_SECTION_SEGMENT Segment, _In_ LONGLONG Offset, _In_ ULONG Length, _In_opt_ PLARGE_INTEGER ValidDataLength, _In_ BOOLEAN SetDirty)
Definition: section.c:1194
static PMM_SECTION_SEGMENT MiGrabDataSection(PSECTION_OBJECT_POINTERS SectionObjectPointer)
Definition: section.c:88
#define DIE(ARGS_)
NTSTATUS ExeFmtpCreateImageSection(PFILE_OBJECT FileObject, PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:3058
PLARGE_INTEGER BOOLEAN ForceDirty
Definition: section.c:5203
static VOID MmFreeSectionPage(PVOID Context, MEMORY_AREA *MemoryArea, PVOID Address, PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
Definition: section.c:3482
NTSTATUS NTAPI MmCreatePhysicalMemorySection(VOID)
Definition: section.c:2239
static NTSTATUS MmMapViewOfSegment(PMMSUPPORT AddressSpace, BOOLEAN AsImage, PMM_SECTION_SEGMENT Segment, PVOID *BaseAddress, SIZE_T ViewSize, ULONG Protect, LONGLONG ViewOffset, ULONG AllocationType)
Definition: section.c:3403
PLARGE_INTEGER Offset
Definition: section.c:5202
ULONGLONG AlignUp(IN ULONGLONG Value, IN ULONG Alignment)
Definition: partlist.c:81
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
#define _countof(array)
Definition: sndvol32.h:70
static void Exit(void)
Definition: sock.c:1330
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
_In_ PVOID Context
Definition: storport.h:2269
PMM_SECTION_SEGMENT Segment
Definition: section.c:185
PMEMORY_AREA MemoryArea
Definition: section.c:184
LARGE_INTEGER Offset
Definition: section.c:186
ULONG NumberOfMappedViews
Definition: mmtypes.h:525
LARGE_INTEGER ValidDataLength
Definition: env_spec_w32.h:757
WORD SizeOfOptionalHeader
Definition: ntddk_ex.h:127
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
USHORT MajorSubsystemVersion
Definition: ntimage.h:356
ULONGLONG SizeOfStackReserve
Definition: ntimage.h:364
USHORT MinorSubsystemVersion
Definition: ntimage.h:357
ULONGLONG SizeOfStackCommit
Definition: ntimage.h:365
union _IMAGE_SECTION_HEADER::@1688 Misc
DWORD PointerToRawData
Definition: pedump.c:290
Definition: typedefs.h:120
struct _MEMORY_AREA::@1949 SectionData
ULONG Flags
Definition: mm.h:258
BOOLEAN DeleteInProgress
Definition: mm.h:259
ULONG Type
Definition: mm.h:257
MMVAD VadNode
Definition: mm.h:255
union _MMADDRESS_NODE::@2854 u1
struct _MMADDRESS_NODE * Parent
Definition: mmtypes.h:649
ULONG PhysicalMemory
Definition: mmtypes.h:473
ULONG NoChange
Definition: mmtypes.h:486
ULONG_PTR Protection
Definition: mmtypes.h:696
ULONG_PTR VadType
Definition: mmtypes.h:694
ULONG_PTR EndingVpn
Definition: mmtypes.h:730
union _MMVAD::@2856 u
PCONTROL_AREA ControlArea
Definition: mmtypes.h:736
ULONG_PTR StartingVpn
Definition: mmtypes.h:729
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:734
ULONG_PTR NumberGenericTableElements
Definition: mmtypes.h:668
MMADDRESS_NODE BalancedRoot
Definition: mmtypes.h:662
PMM_SECTION_SEGMENT Segments
Definition: mm.h:240
PFILE_OBJECT FileObject
Definition: mm.h:232
SECTION_IMAGE_INFORMATION ImageInformation
Definition: mm.h:237
Definition: mm.h:482
PULONG Flags
Definition: mm.h:211
LARGE_INTEGER RawLength
Definition: mm.h:206
struct _MM_SECTION_SEGMENT::@1948 Image
PLONG64 ReferenceCount
Definition: mm.h:208
FAST_MUTEX Lock
Definition: mm.h:205
PFILE_OBJECT FileObject
Definition: mm.h:203
BOOLEAN WriteCopy
Definition: mm.h:212
ULONG Protection
Definition: mm.h:210
LARGE_INTEGER Length
Definition: mm.h:207
OB_CLOSE_METHOD CloseProcedure
Definition: obtypes.h:368
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
OB_DELETE_METHOD DeleteProcedure
Definition: obtypes.h:369
LARGE_INTEGER Size
Definition: mmtypes.h:336
MMSECTION_FLAGS Flags
Definition: mmtypes.h:817
union _SECTION::@2865 u
PSEGMENT Segment
Definition: mmtypes.h:812
ULONG InitialPageProtection
Definition: mmtypes.h:819
LARGE_INTEGER SizeOfSection
Definition: mmtypes.h:813
PVOID BasedAddress
Definition: mmtypes.h:418
PSECTION_IMAGE_INFORMATION ImageInformation
Definition: mmtypes.h:426
union _SEGMENT::@2848 u2
Definition: fci.c:127
Definition: parser.c:49
static PMEM_HOOK PageTable[TOTAL_PAGES]
Definition: memory.c:43
#define max(a, b)
Definition: svc.c:63
#define TAG_MM_SECTION_SEGMENT
Definition: tag.h:113
#define TAG_MM_REGION
Definition: tag.h:110
#define STATUS_PENDING
Definition: telnetd.h:14
else
Definition: tritemp.h:161
#define LL
Definition: tui.h:166
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
PVOID PMDL
Definition: usb.h:39
static int Protect(const char **args)
Definition: vfdcmd.c:2132
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3782
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2664
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
@ ProcessHandleCount
Definition: winternl.h:1902
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2274
_In_ PLARGE_INTEGER _Out_ struct _ERESOURCE ** ResourceToRelease
Definition: iotypes.h:1598
#define FO_RANDOM_ACCESS
Definition: iotypes.h:1796
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FO_DELETE_ON_CLOSE
Definition: iotypes.h:1792
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ WrPageIn
Definition: ketypes.h:476
@ Executive
Definition: ketypes.h:467
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
KAPC_STATE
Definition: ketypes.h:1711
_Must_inspect_result_ _Outptr_result_bytebuffer_ ViewSize PVOID * MappedBase
Definition: mmfuncs.h:492
#define MmInitializeMdl(_MemoryDescriptorList, _BaseVa, _Length)
#define BYTES_TO_PAGES(Size)
_Must_inspect_result_ _In_ ULONG NewProtect
Definition: mmfuncs.h:682
#define MmGetMdlPfnArray(_Mdl)
_In_opt_ PLARGE_INTEGER NewFileSize
Definition: mmfuncs.h:608
MMFLUSH_TYPE
Definition: mmtypes.h:183
MDL
Definition: mmtypes.h:117
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define MDL_IO_PAGE_READ
Definition: mmtypes.h:24
#define MDL_MAPPED_TO_SYSTEM_VA
Definition: mmtypes.h:18
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ BOOLEAN Restart)
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlGetElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ ULONG I)
NTSYSAPI ULONG NTAPI RtlNumberGenericTableElements(_In_ PRTL_GENERIC_TABLE Table)
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:20