ReactOS 0.4.15-dev-7788-g1ad9096
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) do { \
57 DPRINT("SetPageEntrySectionSegment(old,%p,%x,%x)\n",(S),(O)->LowPart,E); \
58 _MmSetPageEntrySectionSegment((S),(O),(E),__FILE__,__LINE__); \
59 } while (0)
60
61extern MMSESSION MmSession;
62
63static LARGE_INTEGER TinyTime = {{-1L, -1L}};
64
65#ifndef NEWCC
67
68VOID
71{
72 //DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line);
74 Segment->Locked = TRUE;
75}
76
77VOID
80{
81 ASSERT(Segment->Locked);
82 Segment->Locked = FALSE;
84 //DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line);
85}
86#endif
87
88static
91{
92 KIRQL OldIrql = MiAcquirePfnLock();
94
95 while (TRUE)
96 {
97 Segment = SectionObjectPointer->DataSectionObject;
98 if (!Segment)
99 break;
100
102 {
103 MiReleasePfnLock(OldIrql);
105 OldIrql = MiAcquirePfnLock();
106 continue;
107 }
108
111 break;
112 }
113
114 MiReleasePfnLock(OldIrql);
115
116 return Segment;
117}
118
119/* Somewhat grotesque, but eh... */
121{
122 ASSERT((Segment->SegFlags & MM_DATAFILE_SEGMENT) == 0);
123
124 return CONTAINING_RECORD(Segment->ReferenceCount, MM_IMAGE_SECTION_OBJECT, RefCount);
125}
126
129 IN PVOID Session,
133
135NTAPI
139 IN PLARGE_INTEGER InputMaximumSize,
144
146NTAPI
157
158//
159// PeFmtCreateSection depends on the following:
160//
163
167
177
178/* TYPES *********************************************************************/
179
180typedef struct
181{
189}
191
192/* GLOBALS *******************************************************************/
193
195
197
199{
200 PAGE_NOACCESS, /* 0 = NONE */
201 PAGE_NOACCESS, /* 1 = SHARED */
202 PAGE_EXECUTE, /* 2 = EXECUTABLE */
203 PAGE_EXECUTE, /* 3 = EXECUTABLE, SHARED */
204 PAGE_READONLY, /* 4 = READABLE */
205 PAGE_READONLY, /* 5 = READABLE, SHARED */
206 PAGE_EXECUTE_READ, /* 6 = READABLE, EXECUTABLE */
207 PAGE_EXECUTE_READ, /* 7 = READABLE, EXECUTABLE, SHARED */
208 /*
209 * FIXME? do we really need the WriteCopy field in segments? can't we use
210 * PAGE_WRITECOPY here?
211 */
212 PAGE_READWRITE, /* 8 = WRITABLE */
213 PAGE_READWRITE, /* 9 = WRITABLE, SHARED */
214 PAGE_EXECUTE_READWRITE, /* 10 = WRITABLE, EXECUTABLE */
215 PAGE_EXECUTE_READWRITE, /* 11 = WRITABLE, EXECUTABLE, SHARED */
216 PAGE_READWRITE, /* 12 = WRITABLE, READABLE */
217 PAGE_READWRITE, /* 13 = WRITABLE, READABLE, SHARED */
218 PAGE_EXECUTE_READWRITE, /* 14 = WRITABLE, READABLE, EXECUTABLE */
219 PAGE_EXECUTE_READWRITE, /* 15 = WRITABLE, READABLE, EXECUTABLE, SHARED */
220};
221
224{
229};
230
231
232/* FUNCTIONS *****************************************************************/
233
234
235
237NTAPI
239 LONGLONG SegOffset,
241/*
242 * FUNCTION: write a page for a section backed memory area.
243 * PARAMETERS:
244 * MemoryArea - Memory area to write the page for.
245 * Offset - Offset of the page to write.
246 * Page - Page which contains the data to write.
247 */
248{
252 UCHAR MdlBase[sizeof(MDL) + sizeof(PFN_NUMBER)];
253 PMDL Mdl = (PMDL)MdlBase;
254 PFILE_OBJECT FileObject = Segment->FileObject;
256
257 FileOffset.QuadPart = Segment->Image.FileOffset + SegOffset;
258
259 RtlZeroMemory(MdlBase, sizeof(MdlBase));
262 Mdl->MdlFlags |= MDL_PAGES_LOCKED;
263
266 if (Status == STATUS_PENDING)
267 {
269 Status = IoStatus.Status;
270 }
271 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
272 {
273 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
274 }
275
276 return Status;
277}
278
279
280/*
281 References:
282 [1] Microsoft Corporation, "Microsoft Portable Executable and Common Object
283 File Format Specification", revision 6.0 (February 1999)
284*/
286 IN SIZE_T FileHeaderSize,
287 IN PVOID File,
288 OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
290 IN PEXEFMT_CB_READ_FILE ReadFileCb,
291 IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb)
292{
293 NTSTATUS nStatus;
294 ULONG cbFileHeaderOffsetSize = 0;
295 ULONG cbSectionHeadersOffset = 0;
296 ULONG cbSectionHeadersSize;
297 ULONG cbSectionHeadersOffsetSize = 0;
298 ULONG cbOptHeaderSize;
299 ULONG cbHeadersSize = 0;
300 ULONG nSectionAlignment;
301 ULONG nFileAlignment;
302 ULONG_PTR ImageBase = 0;
303 const IMAGE_DOS_HEADER * pidhDosHeader;
304 const IMAGE_NT_HEADERS32 * pinhNtHeader;
305 const IMAGE_OPTIONAL_HEADER32 * piohOptHeader;
306 const IMAGE_SECTION_HEADER * pishSectionHeaders;
307 PMM_SECTION_SEGMENT pssSegments;
308 LARGE_INTEGER lnOffset;
310 SIZE_T nPrevVirtualEndOfSegment = 0;
311 ULONG nFileSizeOfHeaders = 0;
312 ULONG i;
313 ULONG AlignedLength;
314
315 ASSERT(FileHeader);
316 ASSERT(FileHeaderSize > 0);
317 ASSERT(File);
318 ASSERT(ImageSectionObject);
319 ASSERT(ReadFileCb);
320 ASSERT(AllocateSegmentsCb);
321
322 ASSERT(Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize));
323
324 ASSERT(((UINT_PTR)FileHeader % TYPE_ALIGNMENT(IMAGE_DOS_HEADER)) == 0);
325
326#define DIE(ARGS_) { DPRINT ARGS_; goto l_Return; }
327
328 pBuffer = NULL;
329 pidhDosHeader = FileHeader;
330
331 /* DOS HEADER */
333
334 /* image too small to be an MZ executable */
335 if(FileHeaderSize < sizeof(IMAGE_DOS_HEADER))
336 DIE(("Too small to be an MZ executable, size is %lu\n", FileHeaderSize));
337
338 /* no MZ signature */
339 if(pidhDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
340 DIE(("No MZ signature found, e_magic is %hX\n", pidhDosHeader->e_magic));
341
342 /* NT HEADER */
344
345 /* not a Windows executable */
346 if(pidhDosHeader->e_lfanew <= 0)
347 DIE(("Not a Windows executable, e_lfanew is %d\n", pidhDosHeader->e_lfanew));
348
349 if(!Intsafe_AddULong32(&cbFileHeaderOffsetSize, pidhDosHeader->e_lfanew, RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader)))
350 DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
351
352 if(FileHeaderSize < cbFileHeaderOffsetSize)
353 pinhNtHeader = NULL;
354 else
355 {
356 /*
357 * we already know that Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize),
358 * and FileHeaderSize >= cbFileHeaderOffsetSize, so this holds true too
359 */
360 ASSERT(Intsafe_CanOffsetPointer(FileHeader, pidhDosHeader->e_lfanew));
361 pinhNtHeader = (PVOID)((UINT_PTR)FileHeader + pidhDosHeader->e_lfanew);
362 }
363
364 /*
365 * the buffer doesn't contain the NT file header, or the alignment is wrong: we
366 * need to read the header from the file
367 */
368 if(FileHeaderSize < cbFileHeaderOffsetSize ||
369 (UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
370 {
371 ULONG cbNtHeaderSize;
372 ULONG cbReadSize;
373 PVOID pData;
374
375l_ReadHeaderFromFile:
376 cbNtHeaderSize = 0;
377 lnOffset.QuadPart = pidhDosHeader->e_lfanew;
378
379 /* read the header from the file */
380 nStatus = ReadFileCb(File, &lnOffset, sizeof(IMAGE_NT_HEADERS64), &pData, &pBuffer, &cbReadSize);
381
382 if(!NT_SUCCESS(nStatus))
383 {
384 NTSTATUS ReturnedStatus = nStatus;
385
386 /* If it attempted to read past the end of the file, it means e_lfanew is invalid */
387 if (ReturnedStatus == STATUS_END_OF_FILE) nStatus = STATUS_INVALID_IMAGE_PROTECT;
388
389 DIE(("ReadFile failed, status %08X\n", ReturnedStatus));
390 }
391
392 ASSERT(pData);
394 ASSERT(cbReadSize > 0);
395
397
398 /* the buffer doesn't contain the file header */
399 if(cbReadSize < RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader))
400 DIE(("The file doesn't contain the PE file header\n"));
401
402 pinhNtHeader = pData;
403
404 /* object still not aligned: copy it to the beginning of the buffer */
405 if((UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
406 {
408 RtlMoveMemory(pBuffer, pData, cbReadSize);
409 pinhNtHeader = pBuffer;
410 }
411
412 /* invalid NT header */
414
415 if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
416 DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
417
419
420 if(!Intsafe_AddULong32(&cbNtHeaderSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
421 DIE(("The full NT header is too large\n"));
422
423 /* the buffer doesn't contain the whole NT header */
424 if(cbReadSize < cbNtHeaderSize)
425 DIE(("The file doesn't contain the full NT header\n"));
426 }
427 else
428 {
429 ULONG cbOptHeaderOffsetSize = 0;
430
432
433 /* don't trust an invalid NT header */
434 if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
435 DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
436
437 if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
438 DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
439
441
442 if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, cbOptHeaderOffsetSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
443 DIE(("The NT header is too large, SizeOfOptionalHeader is %X\n", pinhNtHeader->FileHeader.SizeOfOptionalHeader));
444
445 /* the buffer doesn't contain the whole NT header: read it from the file */
446 if(cbOptHeaderOffsetSize > FileHeaderSize)
447 goto l_ReadHeaderFromFile;
448 }
449
450 /* read information from the NT header */
451 piohOptHeader = &pinhNtHeader->OptionalHeader;
452 cbOptHeaderSize = pinhNtHeader->FileHeader.SizeOfOptionalHeader;
453
455
456 if(!RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Magic))
457 DIE(("The optional header doesn't contain the Magic field, SizeOfOptionalHeader is %X\n", cbOptHeaderSize));
458
459 /* ASSUME: RtlZeroMemory(ImageSectionObject, sizeof(*ImageSectionObject)); */
460
461 switch(piohOptHeader->Magic)
462 {
464#ifndef _WIN64
466 DIE(("Win64 optional header, unsupported\n"));
467#else
468 // Fall through.
469#endif
471 break;
472 default:
473 DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
474 }
475
476 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SectionAlignment) &&
477 RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, FileAlignment))
478 {
479 /* See [1], section 3.4.2 */
480 if(piohOptHeader->SectionAlignment < PAGE_SIZE)
481 {
482 if(piohOptHeader->FileAlignment != piohOptHeader->SectionAlignment)
483 DIE(("Sections aren't page-aligned and the file alignment isn't the same\n"));
484 }
485 else if(piohOptHeader->SectionAlignment < piohOptHeader->FileAlignment)
486 DIE(("The section alignment is smaller than the file alignment\n"));
487
488 nSectionAlignment = piohOptHeader->SectionAlignment;
489 nFileAlignment = piohOptHeader->FileAlignment;
490
491 if(!IsPowerOf2(nSectionAlignment) || !IsPowerOf2(nFileAlignment))
492 DIE(("The section alignment (%u) and file alignment (%u) aren't both powers of 2\n", nSectionAlignment, nFileAlignment));
493 }
494 else
495 {
496 nSectionAlignment = PAGE_SIZE;
497 nFileAlignment = PAGE_SIZE;
498 }
499
500 ASSERT(IsPowerOf2(nSectionAlignment));
501 ASSERT(IsPowerOf2(nFileAlignment));
502
503 switch(piohOptHeader->Magic)
504 {
505 /* PE32 */
507 {
508 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, ImageBase))
509 ImageBase = piohOptHeader->ImageBase;
510
511 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfImage))
512 ImageSectionObject->ImageInformation.ImageFileSize = piohOptHeader->SizeOfImage;
513
514 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackReserve))
515 ImageSectionObject->ImageInformation.MaximumStackSize = piohOptHeader->SizeOfStackReserve;
516
517 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackCommit))
518 ImageSectionObject->ImageInformation.CommittedStackSize = piohOptHeader->SizeOfStackCommit;
519
520 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Subsystem))
521 {
522 ImageSectionObject->ImageInformation.SubSystemType = piohOptHeader->Subsystem;
523
524 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
525 RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MajorSubsystemVersion))
526 {
527 ImageSectionObject->ImageInformation.SubSystemMinorVersion = piohOptHeader->MinorSubsystemVersion;
528 ImageSectionObject->ImageInformation.SubSystemMajorVersion = piohOptHeader->MajorSubsystemVersion;
529 }
530 }
531
532 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
533 {
534 ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
535 piohOptHeader->AddressOfEntryPoint);
536 }
537
538 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfCode))
539 ImageSectionObject->ImageInformation.ImageContainsCode = piohOptHeader->SizeOfCode != 0;
540 else
541 ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
542
543 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
544 {
545 if (piohOptHeader->AddressOfEntryPoint == 0)
546 {
547 ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
548 }
549 }
550
551 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, LoaderFlags))
552 ImageSectionObject->ImageInformation.LoaderFlags = piohOptHeader->LoaderFlags;
553
554 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, DllCharacteristics))
555 {
556 ImageSectionObject->ImageInformation.DllCharacteristics = piohOptHeader->DllCharacteristics;
557
558 /*
559 * Since we don't really implement SxS yet and LD doesn't supoprt /ALLOWISOLATION:NO, hard-code
560 * this flag here, which will prevent the loader and other code from doing any .manifest or SxS
561 * magic to any binary.
562 *
563 * This will break applications that depend on SxS when running with real Windows Kernel32/SxS/etc
564 * but honestly that's not tested. It will also break them when running no ReactOS once we implement
565 * the SxS support -- at which point, duh, this should be removed.
566 *
567 * But right now, any app depending on SxS is already broken anyway, so this flag only helps.
568 */
569 ImageSectionObject->ImageInformation.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NO_ISOLATION;
570 }
571
572 break;
573 }
574#ifdef _WIN64
575 /* PE64 */
577 {
578 const IMAGE_OPTIONAL_HEADER64 * pioh64OptHeader;
579
580 pioh64OptHeader = (const IMAGE_OPTIONAL_HEADER64 *)piohOptHeader;
581
582 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, ImageBase))
583 {
584 ImageBase = pioh64OptHeader->ImageBase;
585 if(pioh64OptHeader->ImageBase > MAXULONG_PTR)
586 DIE(("ImageBase exceeds the address space\n"));
587 }
588
589 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfImage))
590 {
591 if(pioh64OptHeader->SizeOfImage > MAXULONG_PTR)
592 DIE(("SizeOfImage exceeds the address space\n"));
593
594 ImageSectionObject->ImageInformation.ImageFileSize = pioh64OptHeader->SizeOfImage;
595 }
596
597 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackReserve))
598 {
599 if(pioh64OptHeader->SizeOfStackReserve > MAXULONG_PTR)
600 DIE(("SizeOfStackReserve exceeds the address space\n"));
601
602 ImageSectionObject->ImageInformation.MaximumStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackReserve;
603 }
604
605 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackCommit))
606 {
607 if(pioh64OptHeader->SizeOfStackCommit > MAXULONG_PTR)
608 DIE(("SizeOfStackCommit exceeds the address space\n"));
609
610 ImageSectionObject->ImageInformation.CommittedStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackCommit;
611 }
612
613 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, Subsystem))
614 {
615 ImageSectionObject->ImageInformation.SubSystemType = pioh64OptHeader->Subsystem;
616
617 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
618 RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MajorSubsystemVersion))
619 {
620 ImageSectionObject->ImageInformation.SubSystemMinorVersion = pioh64OptHeader->MinorSubsystemVersion;
621 ImageSectionObject->ImageInformation.SubSystemMajorVersion = pioh64OptHeader->MajorSubsystemVersion;
622 }
623 }
624
625 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
626 {
627 ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
628 pioh64OptHeader->AddressOfEntryPoint);
629 }
630
631 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfCode))
632 ImageSectionObject->ImageInformation.ImageContainsCode = pioh64OptHeader->SizeOfCode != 0;
633 else
634 ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
635
636 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
637 {
638 if (pioh64OptHeader->AddressOfEntryPoint == 0)
639 {
640 ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
641 }
642 }
643
644 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, LoaderFlags))
645 ImageSectionObject->ImageInformation.LoaderFlags = pioh64OptHeader->LoaderFlags;
646
647 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, DllCharacteristics))
648 ImageSectionObject->ImageInformation.DllCharacteristics = pioh64OptHeader->DllCharacteristics;
649
650 break;
651 }
652#endif // _WIN64
653 }
654
655 /* [1], section 3.4.2 */
656 if((ULONG_PTR)ImageBase % 0x10000)
657 DIE(("ImageBase is not aligned on a 64KB boundary"));
658
659 ImageSectionObject->ImageInformation.ImageCharacteristics = pinhNtHeader->FileHeader.Characteristics;
660 ImageSectionObject->ImageInformation.Machine = pinhNtHeader->FileHeader.Machine;
661 ImageSectionObject->ImageInformation.GpValue = 0;
662 ImageSectionObject->ImageInformation.ZeroBits = 0;
663 ImageSectionObject->BasedAddress = (PVOID)ImageBase;
664
665 /* SECTION HEADERS */
667
668 /* see [1], section 3.3 */
669 if(pinhNtHeader->FileHeader.NumberOfSections > 96)
670 DIE(("Too many sections, NumberOfSections is %u\n", pinhNtHeader->FileHeader.NumberOfSections));
671
672 /*
673 * the additional segment is for the file's headers. They need to be present for
674 * the benefit of the dynamic loader (to locate exports, defaults for thread
675 * parameters, resources, etc.)
676 */
677 ImageSectionObject->NrSegments = pinhNtHeader->FileHeader.NumberOfSections + 1;
678
679 /* file offset for the section headers */
680 if(!Intsafe_AddULong32(&cbSectionHeadersOffset, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
681 DIE(("Offset overflow\n"));
682
683 if(!Intsafe_AddULong32(&cbSectionHeadersOffset, cbSectionHeadersOffset, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
684 DIE(("Offset overflow\n"));
685
686 /* size of the section headers */
688 cbSectionHeadersSize = pinhNtHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
689
690 if(!Intsafe_AddULong32(&cbSectionHeadersOffsetSize, cbSectionHeadersOffset, cbSectionHeadersSize))
691 DIE(("Section headers too large\n"));
692
693 /* size of the executable's headers */
694 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfHeaders))
695 {
696// if(!IsAligned(piohOptHeader->SizeOfHeaders, nFileAlignment))
697// DIE(("SizeOfHeaders is not aligned\n"));
698
699 if(cbSectionHeadersSize > piohOptHeader->SizeOfHeaders)
700 DIE(("The section headers overflow SizeOfHeaders\n"));
701
702 cbHeadersSize = piohOptHeader->SizeOfHeaders;
703 }
704 else if(!AlignUp(&cbHeadersSize, cbSectionHeadersOffsetSize, nFileAlignment))
705 DIE(("Overflow aligning the size of headers\n"));
706
707 if(pBuffer)
708 {
710 pBuffer = NULL;
711 }
712 /* WARNING: pinhNtHeader IS NO LONGER USABLE */
713 /* WARNING: piohOptHeader IS NO LONGER USABLE */
714 /* WARNING: pioh64OptHeader IS NO LONGER USABLE */
715
716 if(FileHeaderSize < cbSectionHeadersOffsetSize)
717 pishSectionHeaders = NULL;
718 else
719 {
720 /*
721 * we already know that Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize),
722 * and FileHeaderSize >= cbSectionHeadersOffsetSize, so this holds true too
723 */
724 ASSERT(Intsafe_CanOffsetPointer(FileHeader, cbSectionHeadersOffset));
725 pishSectionHeaders = (PVOID)((UINT_PTR)FileHeader + cbSectionHeadersOffset);
726 }
727
728 /*
729 * the buffer doesn't contain the section headers, or the alignment is wrong:
730 * read the headers from the file
731 */
732 if(FileHeaderSize < cbSectionHeadersOffsetSize ||
733 (UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
734 {
735 PVOID pData;
736 ULONG cbReadSize;
737
738 lnOffset.QuadPart = cbSectionHeadersOffset;
739
740 /* read the header from the file */
741 nStatus = ReadFileCb(File, &lnOffset, cbSectionHeadersSize, &pData, &pBuffer, &cbReadSize);
742
743 if(!NT_SUCCESS(nStatus))
744 DIE(("ReadFile failed with status %08X\n", nStatus));
745
746 ASSERT(pData);
748 ASSERT(cbReadSize > 0);
749
751
752 /* the buffer doesn't contain all the section headers */
753 if(cbReadSize < cbSectionHeadersSize)
754 DIE(("The file doesn't contain all of the section headers\n"));
755
756 pishSectionHeaders = pData;
757
758 /* object still not aligned: copy it to the beginning of the buffer */
759 if((UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
760 {
762 RtlMoveMemory(pBuffer, pData, cbReadSize);
763 pishSectionHeaders = pBuffer;
764 }
765 }
766
767 /* SEGMENTS */
768 /* allocate the segments */
770 ImageSectionObject->Segments = AllocateSegmentsCb(ImageSectionObject->NrSegments);
771
772 if(ImageSectionObject->Segments == NULL)
773 DIE(("AllocateSegments failed\n"));
774
775 /* initialize the headers segment */
776 pssSegments = ImageSectionObject->Segments;
777
778// ASSERT(IsAligned(cbHeadersSize, nFileAlignment));
779
780 if(!AlignUp(&nFileSizeOfHeaders, cbHeadersSize, nFileAlignment))
781 DIE(("Cannot align the size of the section headers\n"));
782
783 nPrevVirtualEndOfSegment = ALIGN_UP_BY(cbHeadersSize, nSectionAlignment);
784 if (nPrevVirtualEndOfSegment < cbHeadersSize)
785 DIE(("Cannot align the size of the section headers\n"));
786
787 pssSegments[0].Image.FileOffset = 0;
788 pssSegments[0].Protection = PAGE_READONLY;
789 pssSegments[0].Length.QuadPart = nPrevVirtualEndOfSegment;
790 pssSegments[0].RawLength.QuadPart = nFileSizeOfHeaders;
791 pssSegments[0].Image.VirtualAddress = 0;
792 pssSegments[0].Image.Characteristics = 0;
793 pssSegments[0].WriteCopy = TRUE;
794
795 /* skip the headers segment */
796 ++ pssSegments;
797
799
800 ASSERT(ImageSectionObject->RefCount > 0);
801
802 /* convert the executable sections into segments. See also [1], section 4 */
803 for(i = 0; i < ImageSectionObject->NrSegments - 1; ++ i)
804 {
805 ULONG nCharacteristics;
806
807 /* validate the alignment */
808 if(!IsAligned(pishSectionHeaders[i].VirtualAddress, nSectionAlignment))
809 DIE(("Image.VirtualAddress[%u] is not aligned\n", i));
810
811 /* sections must be contiguous, ordered by base address and non-overlapping */
812 if(pishSectionHeaders[i].VirtualAddress != nPrevVirtualEndOfSegment)
813 DIE(("Memory gap between section %u and the previous\n", i));
814
815 /* ignore explicit BSS sections */
816 if(pishSectionHeaders[i].PointerToRawData != 0 && pishSectionHeaders[i].SizeOfRawData != 0)
817 {
818 /* validate the alignment */
819#if 0
820 /* Yes, this should be a multiple of FileAlignment, but there's
821 * stuff out there that isn't. We can cope with that
822 */
823 if(!IsAligned(pishSectionHeaders[i].SizeOfRawData, nFileAlignment))
824 DIE(("SizeOfRawData[%u] is not aligned\n", i));
825#endif
826
827// if(!IsAligned(pishSectionHeaders[i].PointerToRawData, nFileAlignment))
828// DIE(("PointerToRawData[%u] is not aligned\n", i));
829
830 if(!Intsafe_CanAddULong32(pishSectionHeaders[i].PointerToRawData, pishSectionHeaders[i].SizeOfRawData))
831 DIE(("SizeOfRawData[%u] too large\n", i));
832
833 /* conversion */
834 pssSegments[i].Image.FileOffset = pishSectionHeaders[i].PointerToRawData;
835 pssSegments[i].RawLength.QuadPart = pishSectionHeaders[i].SizeOfRawData;
836 }
837 else
838 {
839 /* FIXME: Should reset PointerToRawData to 0 in the image mapping */
840 ASSERT(pssSegments[i].Image.FileOffset == 0);
841 ASSERT(pssSegments[i].RawLength.QuadPart == 0);
842 }
843
844 ASSERT(Intsafe_CanAddLong64(pssSegments[i].Image.FileOffset, pssSegments[i].RawLength.QuadPart));
845
846 nCharacteristics = pishSectionHeaders[i].Characteristics;
847
848 /* no explicit protection */
849 if((nCharacteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)) == 0)
850 {
851 if(nCharacteristics & IMAGE_SCN_CNT_CODE)
852 nCharacteristics |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;
853
854 if(nCharacteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
855 nCharacteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
856
857 if(nCharacteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
858 nCharacteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
859 }
860
861 /* see table above */
862 pssSegments[i].Protection = SectionCharacteristicsToProtect[nCharacteristics >> 28];
863 pssSegments[i].WriteCopy = !(nCharacteristics & IMAGE_SCN_MEM_SHARED);
864
865 if(pishSectionHeaders[i].Misc.VirtualSize == 0)
866 pssSegments[i].Length.QuadPart = pishSectionHeaders[i].SizeOfRawData;
867 else
868 pssSegments[i].Length.QuadPart = pishSectionHeaders[i].Misc.VirtualSize;
869
870 AlignedLength = ALIGN_UP_BY(pssSegments[i].Length.LowPart, nSectionAlignment);
871 if(AlignedLength < pssSegments[i].Length.LowPart)
872 DIE(("Cannot align the virtual size of section %u\n", i));
873
874 pssSegments[i].Length.LowPart = AlignedLength;
875
876 if(pssSegments[i].Length.QuadPart == 0)
877 DIE(("Virtual size of section %u is null\n", i));
878
879 pssSegments[i].Image.VirtualAddress = pishSectionHeaders[i].VirtualAddress;
880 pssSegments[i].Image.Characteristics = pishSectionHeaders[i].Characteristics;
881
882 /* ensure the memory image is no larger than 4GB */
883 nPrevVirtualEndOfSegment = (ULONG_PTR)(pssSegments[i].Image.VirtualAddress + pssSegments[i].Length.QuadPart);
884 if (nPrevVirtualEndOfSegment < pssSegments[i].Image.VirtualAddress)
885 DIE(("The image is too large\n"));
886 }
887
888 if(nSectionAlignment >= PAGE_SIZE)
890
891 /* Success */
892 nStatus = STATUS_SUCCESS;// STATUS_ROS_EXEFMT_LOADED_FORMAT | EXEFMT_LOADED_PE32;
893
894l_Return:
895 if(pBuffer)
897
898 return nStatus;
899}
900
901/*
902 * FUNCTION: Waits in kernel mode indefinitely for a file object lock.
903 * ARGUMENTS: PFILE_OBJECT to wait for.
904 * RETURNS: Status of the wait.
905 */
908{
909 return STATUS_SUCCESS;
910 //return KeWaitForSingleObject(&File->Lock, 0, KernelMode, FALSE, NULL);
911}
912
913
914
915VOID
916NTAPI
918{
922 SWAPENTRY SavedSwapEntry;
924
925 Page = 0;
926
928
929 Length = PAGE_ROUND_UP(Segment->Length.QuadPart);
930 for (Offset.QuadPart = 0; Offset.QuadPart < Length; Offset.QuadPart += PAGE_SIZE)
931 {
933 if (Entry)
934 {
937 {
939 }
940 else
941 {
943 SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
944 if (SavedSwapEntry != 0)
945 {
947 MmFreeSwapPage(SavedSwapEntry);
948 }
950 }
951 }
952 }
953
955}
956
957static
958VOID
959NTAPI
961{
964
966
968
970
971 /* This must be either a valid entry or nothing */
973
974 /* There should be no reference anymore */
976
978 /* If there is a page, this must be because it's still dirty */
979 ASSERT(Page != 0);
980
981 /* Write the page */
982 if (IS_DIRTY_SSE(Entry))
983 MiWritePage(Segment, Offset->QuadPart, Page);
984
986}
987
993VOID
994NTAPI
995MmDereferenceSegmentWithLock(
998{
999 /* Lock the PFN lock because we mess around with SectionObjectPointers */
1000 if (OldIrql == MM_NOIRQL)
1001 {
1002 OldIrql = MiAcquirePfnLock();
1003 }
1004
1005 if (InterlockedDecrement64(Segment->ReferenceCount) > 0)
1006 {
1007 /* Nothing to do yet */
1008 MiReleasePfnLock(OldIrql);
1009 return;
1010 }
1011
1012 *Segment->Flags |= MM_SEGMENT_INDELETE;
1013
1014 /* Flush the segment */
1015 if (*Segment->Flags & MM_DATAFILE_SEGMENT)
1016 {
1017 MiReleasePfnLock(OldIrql);
1018 /* Free the page table. This will flush any remaining dirty data */
1020
1021 OldIrql = MiAcquirePfnLock();
1022 /* Delete the pointer on the file */
1023 ASSERT(Segment->FileObject->SectionObjectPointer->DataSectionObject == Segment);
1024 Segment->FileObject->SectionObjectPointer->DataSectionObject = NULL;
1025 MiReleasePfnLock(OldIrql);
1026 ObDereferenceObject(Segment->FileObject);
1027
1029 }
1030 else
1031 {
1032 /* Most grotesque thing ever */
1033 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = CONTAINING_RECORD(Segment->ReferenceCount, MM_IMAGE_SECTION_OBJECT, RefCount);
1034 PMM_SECTION_SEGMENT SectionSegments;
1035 ULONG NrSegments;
1036 ULONG i;
1037
1038 /* Delete the pointer on the file */
1039 ASSERT(ImageSectionObject->FileObject->SectionObjectPointer->ImageSectionObject == ImageSectionObject);
1040 ImageSectionObject->FileObject->SectionObjectPointer->ImageSectionObject = NULL;
1041 MiReleasePfnLock(OldIrql);
1042
1043 ObDereferenceObject(ImageSectionObject->FileObject);
1044
1045 NrSegments = ImageSectionObject->NrSegments;
1046 SectionSegments = ImageSectionObject->Segments;
1047 for (i = 0; i < NrSegments; i++)
1048 {
1049 if (SectionSegments[i].Image.Characteristics & IMAGE_SCN_MEM_SHARED)
1050 {
1051 MmpFreePageFileSegment(&SectionSegments[i]);
1052 }
1053
1054 MmFreePageTablesSectionSegment(&SectionSegments[i], NULL);
1055 }
1056
1058 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
1059 }
1060}
1061
1062VOID
1063NTAPI
1066{
1068
1070 if (Entry == 0)
1071 {
1072 DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
1073 KeBugCheck(MEMORY_MANAGEMENT);
1074 }
1076 {
1077 DPRINT1("Maximum share count reached\n");
1078 KeBugCheck(MEMORY_MANAGEMENT);
1079 }
1081 {
1082 KeBugCheck(MEMORY_MANAGEMENT);
1083 }
1085}
1086
1087BOOLEAN
1088NTAPI
1092 BOOLEAN Dirty,
1094 ULONG_PTR *InEntry)
1095{
1098 BOOLEAN IsDataMap = BooleanFlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT);
1099 SWAPENTRY SwapEntry;
1100
1101 if (Entry == 0)
1102 {
1103 DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
1104 KeBugCheck(MEMORY_MANAGEMENT);
1105 }
1106 if (SHARE_COUNT_FROM_SSE(Entry) == 0)
1107 {
1108 DPRINT1("Zero share count for unshare (Seg %p Offset %x Page %x)\n", Segment, Offset->LowPart, PFN_FROM_SSE(Entry));
1109 KeBugCheck(MEMORY_MANAGEMENT);
1110 }
1112 {
1113 KeBugCheck(MEMORY_MANAGEMENT);
1114 }
1116 if (Dirty) Entry = DIRTY_SSE(Entry);
1117
1118 /* If we are paging-out, pruning the page for real will be taken care of in MmCheckDirtySegment */
1119 if ((SHARE_COUNT_FROM_SSE(Entry) > 0) || PageOut)
1120 {
1121 /* Update the page mapping in the segment and we're done */
1123 return FALSE;
1124 }
1125
1126 /* We are pruning the last mapping on this page. See if we can keep it a bit more. */
1127 ASSERT(!PageOut);
1128
1129 if (IsDataMap)
1130 {
1131 /* We can always keep memory in for data maps */
1133 return FALSE;
1134 }
1135
1136 if (!FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED))
1137 {
1138 ASSERT(Segment->WriteCopy);
1141 /* So this must have been a read-only page. Keep it ! */
1143 return FALSE;
1144 }
1145
1146 /*
1147 * So this is a page for a shared section of a DLL.
1148 * We can keep it if it is not dirty.
1149 */
1150 SwapEntry = MmGetSavedSwapEntryPage(Page);
1151 if ((SwapEntry == 0) && !IS_DIRTY_SSE(Entry))
1152 {
1154 return FALSE;
1155 }
1156
1157 /* No more processes are referencing this shared dirty page. Ditch it. */
1158 if (SwapEntry)
1159 {
1161 MmFreeSwapPage(SwapEntry);
1162 }
1165 return TRUE;
1166}
1167
1168static
1170MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
1171{
1173 KIRQL Irql;
1174 PVOID DestAddress;
1175
1177 DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
1178 if (DestAddress == NULL)
1179 {
1180 return STATUS_NO_MEMORY;
1181 }
1182 ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
1183 ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
1184 RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
1185 MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
1186 return STATUS_SUCCESS;
1187}
1188
1189static
1191NTAPI
1196 _In_opt_ PLARGE_INTEGER ValidDataLength,
1197 _In_ BOOLEAN SetDirty)
1198{
1199 /* Let's use a 64K granularity. */
1200 LONGLONG RangeStart, RangeEnd;
1202 PFILE_OBJECT FileObject = Segment->FileObject;
1203
1204 /* Calculate our range, aligned on 64K if possible. */
1205 Status = RtlLongLongAdd(Offset, Length, &RangeEnd);
1207 if (!NT_SUCCESS(Status))
1208 return Status;
1209
1210 /* If the file is not random access and we are not the page out thread
1211 * read a 64K Chunk. */
1213 && !FlagOn(FileObject->Flags, FO_RANDOM_ACCESS))
1214 {
1215 RangeStart = Offset - (Offset % _64K);
1216 if (RangeEnd % _64K)
1217 RangeEnd += _64K - (RangeEnd % _64K);
1218 }
1219 else
1220 {
1221 RangeStart = Offset - (Offset % PAGE_SIZE);
1222 if (RangeEnd % PAGE_SIZE)
1223 RangeEnd += PAGE_SIZE - (RangeEnd % PAGE_SIZE);
1224 }
1225
1226 /* Clamp if needed */
1227 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
1228 {
1229 if (RangeEnd > Segment->RawLength.QuadPart)
1230 RangeEnd = Segment->RawLength.QuadPart;
1231 }
1232
1233 /* Let's gooooooooo */
1234 for ( ; RangeStart < RangeEnd; RangeStart += _64K)
1235 {
1236 /* First take a look at where we miss pages */
1237 ULONG ToReadPageBits = 0;
1238 LONGLONG ChunkEnd = RangeStart + _64K;
1239
1240 if (ChunkEnd > RangeEnd)
1241 ChunkEnd = RangeEnd;
1242
1244 for (LONGLONG ChunkOffset = RangeStart; ChunkOffset < ChunkEnd; ChunkOffset += PAGE_SIZE)
1245 {
1246 LARGE_INTEGER CurrentOffset;
1247
1248 CurrentOffset.QuadPart = ChunkOffset;
1250
1251 /* Let any pending read proceed */
1252 while (MM_IS_WAIT_PTE(Entry))
1253 {
1255
1257
1259 Entry = MmGetPageEntrySectionSegment(Segment, &CurrentOffset);
1260 }
1261
1262 if (Entry != 0)
1263 {
1264 /* Dirtify it if it's a resident page and we're asked to */
1265 if (SetDirty && !IS_SWAP_FROM_SSE(Entry))
1267 continue;
1268 }
1269
1270 ToReadPageBits |= 1UL << ((ChunkOffset - RangeStart) >> PAGE_SHIFT);
1271
1272 /* Put a wait entry here */
1273 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
1274 }
1276
1277 if (ToReadPageBits == 0)
1278 {
1279 /* Nothing to do for this chunk */
1280 continue;
1281 }
1282
1283 /* Now perform the actual read */
1284 LONGLONG ChunkOffset = RangeStart;
1285 while (ChunkOffset < ChunkEnd)
1286 {
1287 /* Move forward if there is a hole */
1288 ULONG BitSet;
1289 if (!_BitScanForward(&BitSet, ToReadPageBits))
1290 {
1291 /* Nothing more to read */
1292 break;
1293 }
1294 ToReadPageBits >>= BitSet;
1295 ChunkOffset += BitSet * PAGE_SIZE;
1296 ASSERT(ChunkOffset < ChunkEnd);
1297
1298 /* Get the range we have to read */
1299 _BitScanForward(&BitSet, ~ToReadPageBits);
1300 ULONG ReadLength = BitSet * PAGE_SIZE;
1301
1303
1304 /* Clamp (This is for image mappings */
1305 if ((ChunkOffset + ReadLength) > ChunkEnd)
1306 ReadLength = ChunkEnd - ChunkOffset;
1307
1308 ASSERT(ReadLength != 0);
1309
1310 /* Allocate a MDL */
1312 if (!Mdl)
1313 {
1314 /* Damn. Roll-back. */
1316 while (ChunkOffset < ChunkEnd)
1317 {
1318 if (ToReadPageBits & 1)
1319 {
1320 LARGE_INTEGER CurrentOffset;
1321 CurrentOffset.QuadPart = ChunkOffset;
1323 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, 0);
1324 }
1325 ToReadPageBits >>= 1;
1326 ChunkOffset += PAGE_SIZE;
1327 }
1330 }
1331
1332 /* Get our pages */
1335 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1336 {
1338 if (!NT_SUCCESS(Status))
1339 {
1340 /* Damn. Roll-back. */
1341 for (UINT j = 0; j < i; j++)
1343 goto Failed;
1344 }
1345 }
1346
1347 Mdl->MdlFlags |= MDL_PAGES_LOCKED | MDL_IO_PAGE_READ;
1348
1350 FileOffset.QuadPart = Segment->Image.FileOffset + ChunkOffset;
1351
1352 /* Clamp to VDL */
1353 if (ValidDataLength && ((FileOffset.QuadPart + ReadLength) > ValidDataLength->QuadPart))
1354 {
1355 if (FileOffset.QuadPart > ValidDataLength->QuadPart)
1356 {
1357 /* Great, nothing to read. */
1358 goto AssignPagesToSegment;
1359 }
1360
1361 Mdl->Size = (FileOffset.QuadPart + ReadLength) - ValidDataLength->QuadPart;
1362 }
1363
1364 KEVENT Event;
1366
1367 /* Disable APCs */
1368 KIRQL OldIrql;
1370
1373 if (Status == STATUS_PENDING)
1374 {
1376 Status = Iosb.Status;
1377 }
1378
1379 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
1380 {
1381 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
1382 }
1383
1385
1387 {
1388 DPRINT1("Got STATUS_END_OF_FILE at offset %I64d for file %wZ.\n", FileOffset.QuadPart, &FileObject->FileName);
1390 }
1391
1392 if (!NT_SUCCESS(Status))
1393 {
1394 /* Damn. Roll back. */
1395 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1397
1398Failed:
1400 while (ChunkOffset < ChunkEnd)
1401 {
1402 if (ToReadPageBits & 1)
1403 {
1404 LARGE_INTEGER CurrentOffset;
1405 CurrentOffset.QuadPart = ChunkOffset;
1407 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, 0);
1408 }
1409 ToReadPageBits >>= 1;
1410 ChunkOffset += PAGE_SIZE;
1411 }
1413 IoFreeMdl(Mdl);;
1414 return Status;
1415 }
1416
1417AssignPagesToSegment:
1419
1420 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1421 {
1422 ULONG_PTR Entry = MAKE_SSE(Pages[i] << PAGE_SHIFT, 0);
1423 LARGE_INTEGER CurrentOffset;
1424 CurrentOffset.QuadPart = ChunkOffset + (i * PAGE_SIZE);
1425
1427
1428 if (SetDirty)
1430
1431 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, Entry);
1432 }
1433
1435
1436 IoFreeMdl(Mdl);
1437 ToReadPageBits >>= BitSet;
1438 ChunkOffset += BitSet * PAGE_SIZE;
1439 }
1440 }
1441
1442 return STATUS_SUCCESS;
1443}
1444
1445static VOID
1449 ULONG OldType,
1450 ULONG OldProtect,
1451 ULONG NewType,
1453{
1456 BOOLEAN DoCOW = FALSE;
1457 ULONG i;
1459
1462 Segment = MemoryArea->SectionData.Segment;
1464
1465 if ((Segment->WriteCopy) &&
1467 {
1468 DoCOW = TRUE;
1469 }
1470
1471 if (OldProtect != NewProtect)
1472 {
1473 for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
1474 {
1475 SWAPENTRY SwapEntry;
1476 PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
1478
1479 /* Wait for a wait entry to disappear */
1480 do
1481 {
1482 MmGetPageFileMapping(Process, Address, &SwapEntry);
1483 if (SwapEntry != MM_WAIT_ENTRY)
1484 break;
1490 }
1491 while (TRUE);
1492
1493 /*
1494 * If we doing COW for this segment then check if the page is
1495 * already private.
1496 */
1498 {
1502
1504 + MemoryArea->SectionData.ViewOffset;
1506 /*
1507 * An MM_WAIT_ENTRY is ok in this case... It'll just count as
1508 * IS_SWAP_FROM_SSE and we'll do the right thing.
1509 */
1511
1514 {
1516 }
1517 }
1518
1520 {
1522 Protect);
1523 }
1524 }
1525 }
1526
1528}
1529
1531NTAPI
1534 PVOID Address,
1536{
1542 ULONG_PTR Entry1;
1545 BOOLEAN HasSwapEntry;
1546 PVOID PAddress;
1548 SWAPENTRY SwapEntry;
1549
1550 ASSERT(Locked);
1551
1552 /*
1553 * There is a window between taking the page fault and locking the
1554 * address space when another thread could load the page so we check
1555 * that.
1556 */
1558 {
1559 return STATUS_SUCCESS;
1560 }
1561
1563 {
1565 }
1566
1567 /*
1568 * Check for the virtual memory area being deleted.
1569 */
1571 {
1572 return STATUS_UNSUCCESSFUL;
1573 }
1574
1575 PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
1576 Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
1577 + MemoryArea->SectionData.ViewOffset;
1578
1579 Segment = MemoryArea->SectionData.Segment;
1581 &MemoryArea->SectionData.RegionListHead,
1582 Address, NULL);
1583 ASSERT(Region != NULL);
1584
1585 /* Check for a NOACCESS mapping */
1586 if (Region->Protect & PAGE_NOACCESS)
1587 {
1589 }
1590
1591 if (Region->Protect & PAGE_GUARD)
1592 {
1593 /* Remove it */
1595 &MemoryArea->SectionData.RegionListHead,
1596 Address, PAGE_SIZE, Region->Type, Region->Protect & ~PAGE_GUARD,
1598
1599 if (!NT_SUCCESS(Status))
1600 {
1601 DPRINT1("Removing PAGE_GUARD protection failed : 0x%08x.\n", Status);
1602 }
1603
1605 }
1606
1607 HasSwapEntry = MmIsPageSwapEntry(Process, Address);
1608
1609 /* See if we should use a private page */
1610 if (HasSwapEntry)
1611 {
1612 SWAPENTRY DummyEntry;
1613
1614 MmGetPageFileMapping(Process, Address, &SwapEntry);
1615 if (SwapEntry == MM_WAIT_ENTRY)
1616 {
1621 }
1622
1624 if (Process) MI_SET_PROCESS2(Process->ImageFileName);
1625 if (!Process) MI_SET_PROCESS2("Kernel Section");
1627 if (!NT_SUCCESS(Status))
1628 {
1629 return STATUS_NO_MEMORY;
1630 }
1631
1632 /*
1633 * Must be private page we have swapped out.
1634 */
1635
1636 /*
1637 * Sanity check
1638 */
1640 ASSERT(DummyEntry == SwapEntry);
1641
1642 /* Tell everyone else we are serving the fault. */
1643 MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
1644
1646
1647 Status = MmReadFromSwapPage(SwapEntry, Page);
1648 if (!NT_SUCCESS(Status))
1649 {
1650 DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
1651 KeBugCheck(MEMORY_MANAGEMENT);
1652 }
1653
1655 MmDeletePageFileMapping(Process, PAddress, &DummyEntry);
1656 ASSERT(DummyEntry == MM_WAIT_ENTRY);
1657
1659 PAddress,
1660 Region->Protect,
1661 Page);
1662 if (!NT_SUCCESS(Status))
1663 {
1664 DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
1665 KeBugCheck(MEMORY_MANAGEMENT);
1666 return Status;
1667 }
1668
1669 /*
1670 * Store the swap entry for later use.
1671 */
1672 MmSetSavedSwapEntryPage(Page, SwapEntry);
1673
1674 /*
1675 * Add the page to the process's working set
1676 */
1678 /*
1679 * Finish the operation
1680 */
1681 DPRINT("Address 0x%p\n", Address);
1682 return STATUS_SUCCESS;
1683 }
1684
1685 /*
1686 * Lock the segment
1687 */
1689
1690 /*
1691 * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
1692 */
1693 if ((*Segment->Flags) & MM_PHYSICALMEMORY_SEGMENT)
1694 {
1696 /*
1697 * Just map the desired physical page
1698 */
1699 Page = (PFN_NUMBER)(Offset.QuadPart >> PAGE_SHIFT);
1701 PAddress,
1702 Region->Protect,
1703 Page);
1704 if (!NT_SUCCESS(Status))
1705 {
1706 DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
1707 KeBugCheck(MEMORY_MANAGEMENT);
1708 return Status;
1709 }
1710
1711 /*
1712 * Cleanup and release locks
1713 */
1714 DPRINT("Address 0x%p\n", Address);
1715 return STATUS_SUCCESS;
1716 }
1717
1718 /*
1719 * Check if this page needs to be mapped COW
1720 */
1721 if ((Segment->WriteCopy) &&
1722 (Region->Protect == PAGE_READWRITE || Region->Protect == PAGE_EXECUTE_READWRITE))
1723 {
1725 }
1726 else
1727 {
1728 Attributes = Region->Protect;
1729 }
1730
1731
1732 /*
1733 * Get the entry corresponding to the offset within the section
1734 */
1736 if (Entry == 0)
1737 {
1738 /*
1739 * If the entry is zero, then we need to load the page.
1740 */
1741 if ((Offset.QuadPart >= (LONGLONG)PAGE_ROUND_UP(Segment->RawLength.QuadPart)) && (MemoryArea->VadNode.u.VadFlags.VadType == VadImageMap))
1742 {
1743 /* We are beyond the data which is on file. Just get a new page. */
1745 if (Process) MI_SET_PROCESS2(Process->ImageFileName);
1746 if (!Process) MI_SET_PROCESS2("Kernel Section");
1748 if (!NT_SUCCESS(Status))
1749 {
1751 return STATUS_NO_MEMORY;
1752 }
1755
1757 if (!NT_SUCCESS(Status))
1758 {
1759 DPRINT1("Unable to create virtual mapping\n");
1760 KeBugCheck(MEMORY_MANAGEMENT);
1761 }
1762 ASSERT(MmIsPagePresent(Process, PAddress));
1763 if (Process)
1765
1766 DPRINT("Address 0x%p\n", Address);
1767 return STATUS_SUCCESS;
1768 }
1769
1772
1773 /* The data must be paged in. Lock the file, so that the VDL doesn't get updated behind us. */
1775
1776 PFSRTL_COMMON_FCB_HEADER FcbHeader = Segment->FileObject->FsContext;
1777
1779
1780 FsRtlReleaseFile(Segment->FileObject);
1781
1782 /* Lock address space again */
1784 if (!NT_SUCCESS(Status))
1785 {
1786 if (Status == STATUS_NO_MEMORY)
1787 {
1788 return Status;
1789 }
1790 /* Damn */
1791 DPRINT1("Failed to page data in!\n");
1792 return STATUS_IN_PAGE_ERROR;
1793 }
1794
1795 /* Everything went fine. Restart the operation */
1797 }
1798 else if (IS_SWAP_FROM_SSE(Entry))
1799 {
1800 SWAPENTRY SwapEntry;
1801
1802 SwapEntry = SWAPENTRY_FROM_SSE(Entry);
1803
1804 /* See if a page op is running on this segment. */
1805 if (SwapEntry == MM_WAIT_ENTRY)
1806 {
1812 }
1813
1815 if (!NT_SUCCESS(Status))
1816 {
1818 return STATUS_NO_MEMORY;
1819 }
1820
1821 /*
1822 * Release all our locks and read in the page from disk
1823 */
1826
1828
1829 Status = MmReadFromSwapPage(SwapEntry, Page);
1830 if (!NT_SUCCESS(Status))
1831 {
1832 KeBugCheck(MEMORY_MANAGEMENT);
1833 }
1834
1835 /*
1836 * Relock the address space and segment
1837 */
1840
1841 /*
1842 * Check the entry. No one should change the status of a page
1843 * that has a pending page-in.
1844 */
1846 if (Entry1 != MAKE_SWAP_SSE(MM_WAIT_ENTRY))
1847 {
1848 DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
1849 KeBugCheck(MEMORY_MANAGEMENT);
1850 }
1851
1852 /*
1853 * Save the swap entry.
1854 */
1855 MmSetSavedSwapEntryPage(Page, SwapEntry);
1856
1857 /* Map the page into the process address space */
1859 PAddress,
1860 Attributes,
1861 Page);
1862 if (!NT_SUCCESS(Status))
1863 {
1864 DPRINT1("Unable to create virtual mapping\n");
1865 KeBugCheck(MEMORY_MANAGEMENT);
1866 }
1867 if (Process)
1869
1870 /*
1871 * Mark the offset within the section as having valid, in-memory
1872 * data
1873 */
1874 Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
1877
1878 DPRINT("Address 0x%p\n", Address);
1879 return STATUS_SUCCESS;
1880 }
1881 else
1882 {
1883 /* We already have a page on this section offset. Map it into the process address space. */
1885
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
1896 if (Process)
1898
1899 /* Take a reference on it */
1902
1903 DPRINT("Address 0x%p\n", Address);
1904 return STATUS_SUCCESS;
1905 }
1906}
1907
1909NTAPI
1912 PVOID Address,
1914{
1916 PFN_NUMBER OldPage;
1917 PFN_NUMBER NewPage;
1918 PFN_NUMBER UnmappedPage;
1919 PVOID PAddress;
1924 BOOLEAN Cow = FALSE;
1926 BOOLEAN Unmapped;
1928
1929 DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
1930
1931 /* Get the region for this address */
1933 &MemoryArea->SectionData.RegionListHead,
1934 Address, NULL);
1935 ASSERT(Region != NULL);
1936 if (!(Region->Protect & PAGE_IS_WRITABLE))
1938
1939 /* Make sure we have a page mapping for this address. */
1941 {
1943 if (!NT_SUCCESS(Status))
1944 {
1945 /* This is invalid access ! */
1946 return Status;
1947 }
1948 }
1949
1950 /*
1951 * Check if the page has already been set readwrite
1952 */
1954 {
1955 DPRINT("Address 0x%p\n", Address);
1956 return STATUS_SUCCESS;
1957 }
1958
1959 /* Check if we are doing Copy-On-Write */
1960 Segment = MemoryArea->SectionData.Segment;
1961 Cow = Segment->WriteCopy || (Region->Protect & PAGE_IS_WRITECOPY);
1962
1963 if (!Cow)
1964 {
1965 /* Simply update page protection and we're done */
1967 return STATUS_SUCCESS;
1968 }
1969
1970 /* Calculate the new protection & check if we should update the region */
1971 NewProtect = Region->Protect;
1973 {
1974 NewProtect &= ~PAGE_IS_WRITECOPY;
1975 if (Region->Protect & PAGE_IS_EXECUTABLE)
1977 else
1980 &MemoryArea->SectionData.RegionListHead,
1983 }
1984
1985 /*
1986 * Find the offset of the page
1987 */
1988 PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
1989 Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
1990 + MemoryArea->SectionData.ViewOffset;
1991
1992 /* Get the page mapping this section offset. */
1995
1996 /* Get the current page mapping for the process */
1997 ASSERT(MmIsPagePresent(Process, PAddress));
1998 OldPage = MmGetPfnForProcess(Process, PAddress);
1999 ASSERT(OldPage != 0);
2000
2001 if (IS_SWAP_FROM_SSE(Entry) ||
2002 PFN_FROM_SSE(Entry) != OldPage)
2003 {
2005 /* This is a private page. We must only change the page protection. */
2007 return STATUS_SUCCESS;
2008 }
2009
2010 /*
2011 * Allocate a page
2012 */
2014 if (!NT_SUCCESS(Status))
2015 {
2017 return STATUS_NO_MEMORY;
2018 }
2019
2020 /*
2021 * Copy the old page
2022 */
2023 NT_VERIFY(NT_SUCCESS(MiCopyFromUserPage(NewPage, PAddress)));
2024
2025 /*
2026 * Unshare the old page.
2027 */
2028 DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
2029 Unmapped = MmDeleteVirtualMapping(Process, PAddress, NULL, &UnmappedPage);
2030 if (!Unmapped || (UnmappedPage != OldPage))
2031 {
2032 /* Uh , we had a page just before, but suddenly it changes. Someone corrupted us. */
2033 KeBugCheckEx(MEMORY_MANAGEMENT,
2035 (ULONG_PTR)PAddress,
2036 (ULONG_PTR)__FILE__,
2037 __LINE__);
2038 }
2039
2040 if (Process)
2041 MmDeleteRmap(OldPage, Process, PAddress);
2044
2045 /*
2046 * Set the PTE to point to the new page
2047 */
2048 if (!NT_SUCCESS(MmCreateVirtualMapping(Process, PAddress, NewProtect, NewPage)))
2049 {
2050 DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
2051 KeBugCheck(MEMORY_MANAGEMENT);
2052 }
2053
2054 if (Process)
2055 MmInsertRmap(NewPage, Process, PAddress);
2056
2057 DPRINT("Address 0x%p\n", Address);
2058 return STATUS_SUCCESS;
2059}
2060
2062NTAPI
2066 SIZE_T Length,
2067 ULONG Protect,
2068 PULONG OldProtect)
2069{
2072 ULONG_PTR MaxLength;
2073
2075 if (Length > MaxLength)
2076 Length = (ULONG)MaxLength;
2077
2079 &MemoryArea->SectionData.RegionListHead,
2080 BaseAddress, NULL);
2081 ASSERT(Region != NULL);
2082
2083 if ((MemoryArea->Flags & SEC_NO_CHANGE) &&
2084 Region->Protect != Protect)
2085 {
2087 }
2088
2089 *OldProtect = Region->Protect;
2091 &MemoryArea->SectionData.RegionListHead,
2094
2095 return Status;
2096}
2097
2100 PVOID Address,
2103{
2105 PVOID RegionBaseAddress;
2107
2109 &MemoryArea->SectionData.RegionListHead,
2110 Address, &RegionBaseAddress);
2111 if (Region == NULL)
2112 {
2113 return STATUS_UNSUCCESSFUL;
2114 }
2115
2117 {
2118 Segment = MemoryArea->SectionData.Segment;
2119 Info->AllocationBase = (PUCHAR)MA_GetStartingAddress(MemoryArea) - Segment->Image.VirtualAddress;
2120 Info->Type = MEM_IMAGE;
2121 }
2122 else
2123 {
2124 Info->AllocationBase = (PVOID)MA_GetStartingAddress(MemoryArea);
2125 Info->Type = MEM_MAPPED;
2126 }
2127 Info->BaseAddress = RegionBaseAddress;
2129 Info->RegionSize = Region->Length;
2130 Info->State = MEM_COMMIT;
2131 Info->Protect = Region->Protect;
2132
2134 return STATUS_SUCCESS;
2135}
2136
2137VOID NTAPI
2139{
2140 PSECTION Section = ObjectBody;
2141
2142 /* Check if it's an ARM3, or ReactOS section */
2143 if (!MiIsRosSectionObject(Section))
2144 {
2145 MiDeleteARM3Section(ObjectBody);
2146 return;
2147 }
2148
2149 DPRINT("MmpDeleteSection(ObjectBody %p)\n", ObjectBody);
2150 if (Section->u.Flags.Image)
2151 {
2152 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)Section->Segment;
2153
2154 /*
2155 * NOTE: Section->ImageSection can be NULL for short time
2156 * during the section creating. If we fail for some reason
2157 * until the image section is properly initialized we shouldn't
2158 * process further here.
2159 */
2160 if (Section->Segment == NULL)
2161 return;
2162
2163 KIRQL OldIrql = MiAcquirePfnLock();
2164 ImageSectionObject->SectionCount--;
2165
2166 /* We just dereference the first segment */
2167 ASSERT(ImageSectionObject->RefCount > 0);
2168 /* MmDereferenceSegmentWithLock releases PFN lock */
2169 MmDereferenceSegmentWithLock(ImageSectionObject->Segments, OldIrql);
2170 }
2171 else
2172 {
2174
2175 /*
2176 * NOTE: Section->Segment can be NULL for short time
2177 * during the section creating.
2178 */
2179 if (Segment == NULL)
2180 return;
2181
2182 KIRQL OldIrql = MiAcquirePfnLock();
2183 Segment->SectionCount--;
2184
2185 /* MmDereferenceSegmentWithLock releases PFN lock */
2186 MmDereferenceSegmentWithLock(Segment, OldIrql);
2187 }
2188}
2189
2190VOID NTAPI
2192 IN PVOID Object,
2195 IN ULONG SystemHandleCount)
2196{
2197 DPRINT("MmpCloseSection(OB %p, HC %lu)\n", Object, ProcessHandleCount);
2198}
2199
2200CODE_SEG("INIT")
2202NTAPI
2204{
2205 PSECTION PhysSection;
2208 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
2209 LARGE_INTEGER SectionSize;
2210 HANDLE Handle;
2212
2213 /*
2214 * Create the section mapping physical memory
2215 */
2218 &Name,
2220 NULL,
2221 NULL);
2222 /*
2223 * Create the Object
2224 */
2227 &Obj,
2229 NULL,
2230 sizeof(*PhysSection),
2231 0,
2232 0,
2233 (PVOID*)&PhysSection);
2234 if (!NT_SUCCESS(Status))
2235 {
2236 DPRINT1("MmCreatePhysicalMemorySection: failed to create object (0x%lx)\n", Status);
2237 return Status;
2238 }
2239
2240 /*
2241 * Initialize it
2242 */
2243 RtlZeroMemory(PhysSection, sizeof(*PhysSection));
2244
2245 /* Mark this as a "ROS Section" */
2246 PhysSection->u.Flags.filler = 1;
2248 PhysSection->u.Flags.PhysicalMemory = 1;
2249 PhysSection->SizeOfSection = SectionSize;
2252 if (Segment == NULL)
2253 {
2254 ObDereferenceObject(PhysSection);
2255 return STATUS_NO_MEMORY;
2256 }
2258 PhysSection->Segment = (PSEGMENT)Segment;
2259 Segment->RefCount = 1;
2260
2261 Segment->ReferenceCount = &Segment->RefCount;
2262 Segment->Flags = &Segment->SegFlags;
2263
2265 Segment->Image.FileOffset = 0;
2266 Segment->Protection = PAGE_EXECUTE_READWRITE;
2267 Segment->RawLength = SectionSize;
2268 Segment->Length = SectionSize;
2270 Segment->WriteCopy = FALSE;
2271 Segment->Image.VirtualAddress = 0;
2272 Segment->Image.Characteristics = 0;
2274
2275 Status = ObInsertObject(PhysSection,
2276 NULL,
2278 0,
2279 NULL,
2280 &Handle);
2281 if (!NT_SUCCESS(Status))
2282 {
2283 ObDereferenceObject(PhysSection);
2284 return Status;
2285 }
2287
2288 return STATUS_SUCCESS;
2289}
2290
2291CODE_SEG("INIT")
2293NTAPI
2295{
2296 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
2298
2299 DPRINT("Creating Section Object Type\n");
2300
2301 /* Initialize the section based root */
2304
2305 /* Initialize the Section object type */
2306 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
2307 RtlInitUnicodeString(&Name, L"Section");
2308 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
2309 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(SECTION);
2310 ObjectTypeInitializer.PoolType = PagedPool;
2311 ObjectTypeInitializer.UseDefaultObject = TRUE;
2312 ObjectTypeInitializer.GenericMapping = MmpSectionMapping;
2313 ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
2314 ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
2315 ObjectTypeInitializer.ValidAccessMask = SECTION_ALL_ACCESS;
2316 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
2317 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &MmSectionObjectType);
2318
2320
2321 return STATUS_SUCCESS;
2322}
2323
2324static
2326NTAPI
2330 PLARGE_INTEGER UMaximumSize,
2334 BOOLEAN GotFileHandle)
2335/*
2336 * Create a section backed by a data file
2337 */
2338{
2339 PSECTION Section;
2343 KIRQL OldIrql;
2344
2345 /*
2346 * Create the section
2347 */
2352 NULL,
2353 sizeof(*Section),
2354 0,
2355 0,
2356 (PVOID*)&Section);
2357 if (!NT_SUCCESS(Status))
2358 {
2359 return Status;
2360 }
2361 /*
2362 * Initialize it
2363 */
2364 RtlZeroMemory(Section, sizeof(*Section));
2365
2366 /* Mark this as a "ROS" section */
2367 Section->u.Flags.filler = 1;
2369 Section->u.Flags.File = 1;
2370
2372 Section->u.Flags.NoChange = 1;
2374 Section->u.Flags.Reserve = 1;
2375
2376 if (!GotFileHandle)
2377 {
2378 ASSERT(UMaximumSize != NULL);
2379 // ASSERT(UMaximumSize->QuadPart != 0);
2380 MaximumSize = *UMaximumSize;
2381 }
2382 else
2383 {
2386 if (!NT_SUCCESS(Status))
2387 {
2388 ObDereferenceObject(Section);
2389 return Status;
2390 }
2391
2392 /*
2393 * FIXME: Revise this once a locking order for file size changes is
2394 * decided
2395 */
2396 if ((UMaximumSize != NULL) && (UMaximumSize->QuadPart != 0))
2397 {
2398 MaximumSize = *UMaximumSize;
2399 }
2400 else
2401 {
2403 /* Mapping zero-sized files isn't allowed. */
2404 if (MaximumSize.QuadPart == 0)
2405 {
2406 ObDereferenceObject(Section);
2408 }
2409 }
2410
2411 if (MaximumSize.QuadPart > FileSize.QuadPart)
2412 {
2415 sizeof(LARGE_INTEGER),
2416 &MaximumSize);
2417 if (!NT_SUCCESS(Status))
2418 {
2419 ObDereferenceObject(Section);
2421 }
2422 }
2423 }
2424
2425 if (FileObject->SectionObjectPointer == NULL)
2426 {
2427 ObDereferenceObject(Section);
2429 }
2430
2431 /*
2432 * Lock the file
2433 */
2435 if (Status != STATUS_SUCCESS)
2436 {
2437 ObDereferenceObject(Section);
2438 return Status;
2439 }
2440
2441 /* Lock the PFN lock while messing with Section Object pointers */
2442grab_segment:
2443 OldIrql = MiAcquirePfnLock();
2444 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2445
2446 while (Segment && (Segment->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
2447 {
2448 MiReleasePfnLock(OldIrql);
2450 OldIrql = MiAcquirePfnLock();
2451 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2452 }
2453
2454 /*
2455 * If this file hasn't been mapped as a data file before then allocate a
2456 * section segment to describe the data file mapping
2457 */
2458 if (Segment == NULL)
2459 {
2460 /* Release the lock. ExAllocatePoolWithTag might acquire it */
2461 MiReleasePfnLock(OldIrql);
2462
2465 if (Segment == NULL)
2466 {
2467 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2468 ObDereferenceObject(Section);
2469 return STATUS_NO_MEMORY;
2470 }
2471
2472 /* We are creating it */
2473 RtlZeroMemory(Segment, sizeof(*Segment));
2475 Segment->RefCount = 1;
2476
2477 /* Acquire lock again */
2478 OldIrql = MiAcquirePfnLock();
2479
2480 if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
2481 {
2482 /* Well that's bad luck. Restart it all over */
2483 MiReleasePfnLock(OldIrql);
2485 goto grab_segment;
2486 }
2487
2488 FileObject->SectionObjectPointer->DataSectionObject = Segment;
2489
2490 /* We're safe to release the lock now */
2491 MiReleasePfnLock(OldIrql);
2492
2493 Section->Segment = (PSEGMENT)Segment;
2494
2495 /* Self-referencing segment */
2496 Segment->Flags = &Segment->SegFlags;
2497 Segment->ReferenceCount = &Segment->RefCount;
2498
2499 Segment->SectionCount = 1;
2500
2502 Segment->FileObject = FileObject;
2504
2505 Segment->Image.FileOffset = 0;
2506 Segment->Protection = SectionPageProtection;
2507
2508 Segment->Image.Characteristics = 0;
2511 {
2512 Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0;
2513 }
2514 else
2515 {
2516 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2517 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2518 }
2519 Segment->Image.VirtualAddress = 0;
2521
2522 /* We're good to use it now */
2523 OldIrql = MiAcquirePfnLock();
2524 Segment->SegFlags &= ~MM_SEGMENT_INCREATE;
2525 MiReleasePfnLock(OldIrql);
2526 }
2527 else
2528 {
2529 Section->Segment = (PSEGMENT)Segment;
2530 InterlockedIncrement64(&Segment->RefCount);
2531 InterlockedIncrementUL(&Segment->SectionCount);
2532
2533 MiReleasePfnLock(OldIrql);
2534
2536
2537 if (MaximumSize.QuadPart > Segment->RawLength.QuadPart &&
2539 {
2540 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2541 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2542 }
2543
2545 }
2546 Section->SizeOfSection = MaximumSize;
2547
2548 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2549 *SectionObject = Section;
2550 return STATUS_SUCCESS;
2551}
2552
2553/*
2554 TODO: not that great (declaring loaders statically, having to declare all of
2555 them, having to keep them extern, etc.), will fix in the future
2556*/
2558(
2559 IN CONST VOID * FileHeader,
2560 IN SIZE_T FileHeaderSize,
2561 IN PVOID File,
2562 OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2564 IN PEXEFMT_CB_READ_FILE ReadFileCb,
2565 IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
2566);
2567
2569(
2570 IN CONST VOID * FileHeader,
2571 IN SIZE_T FileHeaderSize,
2572 IN PVOID File,
2573 OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2575 IN PEXEFMT_CB_READ_FILE ReadFileCb,
2576 IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
2577);
2578
2580{
2582#ifdef __ELF
2584#endif
2585};
2586
2587static
2589NTAPI
2591{
2592 SIZE_T SizeOfSegments;
2593 PMM_SECTION_SEGMENT Segments;
2594
2595 /* TODO: check for integer overflow */
2596 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * NrSegments;
2597
2599 SizeOfSegments,
2601
2602 if(Segments)
2603 RtlZeroMemory(Segments, SizeOfSegments);
2604
2605 return Segments;
2606}
2607static
2609NTAPI
2612 IN ULONG Length,
2613 OUT PVOID * Data,
2614 OUT PVOID * AllocBase,
2615 OUT PULONG ReadSize)
2616{
2619 ULONG AdjustOffset;
2620 ULONG OffsetAdjustment;
2622 ULONG UsedSize;
2623 PVOID Buffer;
2626
2628
2629 if(Length == 0)
2630 {
2631 KeBugCheck(MEMORY_MANAGEMENT);
2632 }
2633
2634 FileOffset = *Offset;
2635
2636 /* Negative/special offset: it cannot be used in this context */
2637 if(FileOffset.u.HighPart < 0)
2638 {
2639 KeBugCheck(MEMORY_MANAGEMENT);
2640 }
2641
2642 AdjustOffset = PAGE_ROUND_DOWN(FileOffset.u.LowPart);
2643 OffsetAdjustment = FileOffset.u.LowPart - AdjustOffset;
2644 FileOffset.u.LowPart = AdjustOffset;
2645
2646 BufferSize = Length + OffsetAdjustment;
2648
2649 /*
2650 * It's ok to use paged pool, because this is a temporary buffer only used in
2651 * the loading of executables. The assumption is that MmCreateSection is
2652 * always called at low IRQLs and that these buffers don't survive a brief
2653 * initialization phase
2654 */
2656 if (!Buffer)
2657 {
2659 }
2660
2662
2663 UsedSize = (ULONG)Iosb.Information;
2664
2665 if(NT_SUCCESS(Status) && UsedSize < OffsetAdjustment)
2666 {
2669 }
2670
2671 if(NT_SUCCESS(Status))
2672 {
2673 *Data = (PVOID)((ULONG_PTR)Buffer + OffsetAdjustment);
2674 *AllocBase = Buffer;
2675 *ReadSize = UsedSize - OffsetAdjustment;
2676 }
2677 else
2678 {
2679 ExFreePoolWithTag(Buffer, 'rXmM');
2680 }
2681
2682 return Status;
2683}
2684
2685#ifdef NASSERT
2686# define MmspAssertSegmentsSorted(OBJ_) ((void)0)
2687# define MmspAssertSegmentsNoOverlap(OBJ_) ((void)0)
2688# define MmspAssertSegmentsPageAligned(OBJ_) ((void)0)
2689#else
2690static
2691VOID
2692NTAPI
2694{
2695 ULONG i;
2696
2697 for( i = 1; i < ImageSectionObject->NrSegments; ++ i )
2698 {
2699 ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
2700 ImageSectionObject->Segments[i - 1].Image.VirtualAddress);
2701 }
2702}
2703
2704static
2705VOID
2706NTAPI
2708{
2709 ULONG i;
2710
2711 MmspAssertSegmentsSorted(ImageSectionObject);
2712
2713 for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2714 {
2715 ASSERT(ImageSectionObject->Segments[i].Length.QuadPart > 0);
2716
2717 if(i > 0)
2718 {
2719 ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
2720 (ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
2721 ImageSectionObject->Segments[i - 1].Length.QuadPart));
2722 }
2723 }
2724}
2725
2726static
2727VOID
2728NTAPI
2730{
2731 ULONG i;
2732
2733 for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2734 {
2735 ASSERT((ImageSectionObject->Segments[i].Image.VirtualAddress % PAGE_SIZE) == 0);
2736 ASSERT((ImageSectionObject->Segments[i].Length.QuadPart % PAGE_SIZE) == 0);
2737 }
2738}
2739#endif
2740
2741static
2742int
2743__cdecl
2745 const void * y)
2746{
2747 const MM_SECTION_SEGMENT *Segment1 = (const MM_SECTION_SEGMENT *)x;
2748 const MM_SECTION_SEGMENT *Segment2 = (const MM_SECTION_SEGMENT *)y;
2749
2750 if (Segment1->Image.VirtualAddress > Segment2->Image.VirtualAddress)
2751 return 1;
2752 else if (Segment1->Image.VirtualAddress < Segment2->Image.VirtualAddress)
2753 return -1;
2754 else
2755 return 0;
2756}
2757
2758/*
2759 * Ensures an image section's segments are sorted in memory
2760 */
2761static
2762VOID
2763NTAPI
2765 IN ULONG Flags)
2766{
2768 {
2769 MmspAssertSegmentsSorted(ImageSectionObject);
2770 }
2771 else
2772 {
2773 qsort(ImageSectionObject->Segments,
2774 ImageSectionObject->NrSegments,
2775 sizeof(ImageSectionObject->Segments[0]),
2777 }
2778}
2779
2780
2781/*
2782 * Ensures an image section's segments don't overlap in memory and don't have
2783 * gaps and don't have a null size. We let them map to overlapping file regions,
2784 * though - that's not necessarily an error
2785 */
2786static
2787BOOLEAN
2788NTAPI
2790(
2791 IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2792 IN ULONG Flags
2793)
2794{
2795 ULONG i;
2796
2798 {
2799 MmspAssertSegmentsNoOverlap(ImageSectionObject);
2800 return TRUE;
2801 }
2802
2803 ASSERT(ImageSectionObject->NrSegments >= 1);
2804
2805 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2806 {
2807 if(ImageSectionObject->Segments[i].Length.QuadPart == 0)
2808 {
2809 return FALSE;
2810 }
2811
2812 if(i > 0)
2813 {
2814 /*
2815 * TODO: relax the limitation on gaps. For example, gaps smaller than a
2816 * page could be OK (Windows seems to be OK with them), and larger gaps
2817 * could lead to image sections spanning several discontiguous regions
2818 * (NtMapViewOfSection could then refuse to map them, and they could
2819 * e.g. only be allowed as parameters to NtCreateProcess, like on UNIX)
2820 */
2821 if ((ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
2822 ImageSectionObject->Segments[i - 1].Length.QuadPart) !=
2823 ImageSectionObject->Segments[i].Image.VirtualAddress)
2824 {
2825 return FALSE;
2826 }
2827 }
2828 }
2829
2830 return TRUE;
2831}
2832
2833/*
2834 * Merges and pads an image section's segments until they all are page-aligned
2835 * and have a size that is a multiple of the page size
2836 */
2837static
2838BOOLEAN
2839NTAPI
2841(
2842 IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2843 IN ULONG Flags
2844)
2845{
2846 ULONG i;
2847 ULONG LastSegment;
2848 PMM_SECTION_SEGMENT EffectiveSegment;
2849
2851 {
2852 MmspAssertSegmentsPageAligned(ImageSectionObject);
2853 return TRUE;
2854 }
2855
2856 LastSegment = 0;
2857 EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
2858
2859 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2860 {
2861 /*
2862 * The first segment requires special handling
2863 */
2864 if (i == 0)
2865 {
2867 ULONG_PTR VirtualOffset;
2868
2869 VirtualAddress = EffectiveSegment->Image.VirtualAddress;
2870
2871 /* Round down the virtual address to the nearest page */
2872 EffectiveSegment->Image.VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
2873
2874 /* Round up the virtual size to the nearest page */
2875 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length.QuadPart) -
2876 EffectiveSegment->Image.VirtualAddress;
2877
2878 /* Adjust the raw address and size */
2879 VirtualOffset = VirtualAddress - EffectiveSegment->Image.VirtualAddress;
2880
2881 if (EffectiveSegment->Image.FileOffset < VirtualOffset)
2882 {
2883 return FALSE;
2884 }
2885
2886 /*
2887 * Garbage in, garbage out: unaligned base addresses make the file
2888 * offset point in curious and odd places, but that's what we were
2889 * asked for
2890 */
2891 EffectiveSegment->Image.FileOffset -= VirtualOffset;
2892 EffectiveSegment->RawLength.QuadPart += VirtualOffset;
2893 }
2894 else
2895 {
2896 PMM_SECTION_SEGMENT Segment = &ImageSectionObject->Segments[i];
2897 ULONG_PTR EndOfEffectiveSegment;
2898
2899 EndOfEffectiveSegment = (ULONG_PTR)(EffectiveSegment->Image.VirtualAddress + EffectiveSegment->Length.QuadPart);
2900 ASSERT((EndOfEffectiveSegment % PAGE_SIZE) == 0);
2901
2902 /*
2903 * The current segment begins exactly where the current effective
2904 * segment ended, therefore beginning a new effective segment
2905 */
2906 if (EndOfEffectiveSegment == Segment->Image.VirtualAddress)
2907 {
2908 LastSegment ++;
2909 ASSERT(LastSegment <= i);
2910 ASSERT(LastSegment < ImageSectionObject->NrSegments);
2911
2912 EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
2913
2914 if (LastSegment != i)
2915 {
2916 /*
2917 * Copy the current segment. If necessary, the effective segment
2918 * will be expanded later
2919 */
2920 *EffectiveSegment = *Segment;
2921 }
2922
2923 /*
2924 * Page-align the virtual size. We know for sure the virtual address
2925 * already is
2926 */
2927 ASSERT((EffectiveSegment->Image.VirtualAddress % PAGE_SIZE) == 0);
2928 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(EffectiveSegment->Length.QuadPart);
2929 }
2930 /*
2931 * The current segment is still part of the current effective segment:
2932 * extend the effective segment to reflect this
2933 */
2934 else if (EndOfEffectiveSegment > Segment->Image.VirtualAddress)
2935 {
2936 static const ULONG FlagsToProtection[16] =
2937 {
2954 };
2955
2956 unsigned ProtectionFlags;
2957
2958 /*
2959 * Extend the file size
2960 */
2961
2962 /* Unaligned segments must be contiguous within the file */
2963 if (Segment->Image.FileOffset != (EffectiveSegment->Image.FileOffset +
2964 EffectiveSegment->RawLength.QuadPart))
2965 {
2966 return FALSE;
2967 }
2968
2969 EffectiveSegment->RawLength.QuadPart += Segment->RawLength.QuadPart;
2970
2971 /*
2972 * Extend the virtual size
2973 */
2974 ASSERT(PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) >= EndOfEffectiveSegment);
2975
2976 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) -
2977 EffectiveSegment->Image.VirtualAddress;
2978
2979 /*
2980 * Merge the protection
2981 */
2982 EffectiveSegment->Protection |= Segment->Protection;
2983
2984 /* Clean up redundance */
2985 ProtectionFlags = 0;
2986
2987 if(EffectiveSegment->Protection & PAGE_IS_READABLE)
2988 ProtectionFlags |= 1 << 0;
2989
2990 if(EffectiveSegment->Protection & PAGE_IS_WRITABLE)
2991 ProtectionFlags |= 1 << 1;
2992
2993 if(EffectiveSegment->Protection & PAGE_IS_EXECUTABLE)
2994 ProtectionFlags |= 1 << 2;
2995
2996 if(EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
2997 ProtectionFlags |= 1 << 3;
2998
2999 ASSERT(ProtectionFlags < 16);
3000 EffectiveSegment->Protection = FlagsToProtection[ProtectionFlags];
3001
3002 /* If a segment was required to be shared and cannot, fail */
3003 if(!(Segment->Protection & PAGE_IS_WRITECOPY) &&
3004 EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
3005 {
3006 return FALSE;
3007 }
3008 }
3009 /*
3010 * We assume no holes between segments at this point
3011 */
3012 else
3013 {
3014 KeBugCheck(MEMORY_MANAGEMENT);
3015 }
3016 }
3017 }
3018 ImageSectionObject->NrSegments = LastSegment + 1;
3019
3020 return TRUE;
3021}
3022
3025 PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
3026{
3028 PVOID FileHeader;
3029 PVOID FileHeaderBuffer;
3030 ULONG FileHeaderSize;
3031 ULONG Flags;
3032 ULONG OldNrSegments;
3034 ULONG i;
3035
3036 /*
3037 * Read the beginning of the file (2 pages). Should be enough to contain
3038 * all (or most) of the headers
3039 */
3040 Offset.QuadPart = 0;
3041
3043 &Offset,
3044 PAGE_SIZE * 2,
3045 &FileHeader,
3046 &FileHeaderBuffer,
3047 &FileHeaderSize);
3048
3049 if (!NT_SUCCESS(Status))
3050 return Status;
3051
3052 if (FileHeaderSize == 0)
3053 {
3054 ExFreePool(FileHeaderBuffer);
3055 return STATUS_UNSUCCESSFUL;
3056 }
3057
3058 /*
3059 * Look for a loader that can handle this executable
3060 */
3061 for (i = 0; i < RTL_NUMBER_OF(ExeFmtpLoaders); ++ i)
3062 {
3063 Flags = 0;
3064
3065 Status = ExeFmtpLoaders[i](FileHeader,
3066 FileHeaderSize,
3067 FileObject,
3068 ImageSectionObject,
3069 &Flags,
3072
3073 if (!NT_SUCCESS(Status))
3074 {
3075 if (ImageSectionObject->Segments)
3076 {
3077 ExFreePool(ImageSectionObject->Segments);
3078 ImageSectionObject->Segments = NULL;
3079 }
3080 }
3081
3083 break;
3084 }
3085
3086 ExFreePoolWithTag(FileHeaderBuffer, 'rXmM');
3087
3088 /*
3089 * No loader handled the format
3090 */
3092 {
3095 }
3096
3097 if (!NT_SUCCESS(Status))
3098 return Status;
3099
3100 ASSERT(ImageSectionObject->Segments != NULL);
3101 ASSERT(ImageSectionObject->RefCount > 0);
3102
3103 /*
3104 * Some defaults
3105 */
3106 /* FIXME? are these values platform-dependent? */
3107 if (ImageSectionObject->ImageInformation.MaximumStackSize == 0)
3108 ImageSectionObject->ImageInformation.MaximumStackSize = 0x40000;
3109
3110 if(ImageSectionObject->ImageInformation.CommittedStackSize == 0)
3111 ImageSectionObject->ImageInformation.CommittedStackSize = 0x1000;
3112
3113 if(ImageSectionObject->BasedAddress == NULL)
3114 {
3115 if(ImageSectionObject->ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL)
3116 ImageSectionObject->BasedAddress = (PVOID)0x10000000;
3117 else
3118 ImageSectionObject->BasedAddress = (PVOID)0x00400000;
3119 }
3120
3121 /*
3122 * And now the fun part: fixing the segments
3123 */
3124
3125 /* Sort them by virtual address */
3126 MmspSortSegments(ImageSectionObject, Flags);
3127
3128 /* Ensure they don't overlap in memory */
3129 if (!MmspCheckSegmentBounds(ImageSectionObject, Flags))
3131
3132 /* Ensure they are aligned */
3133 OldNrSegments = ImageSectionObject->NrSegments;
3134
3135 if (!MmspPageAlignSegments(ImageSectionObject, Flags))
3137
3138 /* Trim them if the alignment phase merged some of them */
3139 if (ImageSectionObject->NrSegments < OldNrSegments)
3140 {
3141 PMM_SECTION_SEGMENT Segments;
3142 SIZE_T SizeOfSegments;
3143
3144 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
3145
3147 SizeOfSegments,
3149
3150 if (Segments == NULL)
3152
3153 RtlCopyMemory(Segments, ImageSectionObject->Segments, SizeOfSegments);
3154 ExFreePool(ImageSectionObject->Segments);
3155 ImageSectionObject->Segments = Segments;
3156 }
3157
3158 /* And finish their initialization */
3159 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
3160 {
3161 ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock);
3162 ImageSectionObject->Segments[i].ReferenceCount = &ImageSectionObject->RefCount;
3163 ImageSectionObject->Segments[i].Flags = &ImageSectionObject->SegFlags;
3164 MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]);
3165 ImageSectionObject->Segments[i].FileObject = FileObject;
3166 }
3167
3168 ASSERT(ImageSectionObject->RefCount > 0);
3169
3170 ImageSectionObject->FileObject = FileObject;
3171
3173 return Status;
3174}
3175
3180 PLARGE_INTEGER UMaximumSize,
3184{
3185 PSECTION Section;
3187 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3188 KIRQL OldIrql;
3189
3190
3191 if (FileObject == NULL)
3193
3194 if (FileObject->SectionObjectPointer == NULL)
3195 {
3196 DPRINT1("Denying section creation due to missing cache initialization\n");
3198 }
3199
3200 /*
3201 * Create the section
3202 */
3207 NULL,
3208 sizeof(*Section),
3209 0,
3210 0,
3211 (PVOID*)(PVOID)&Section);
3212 if (!NT_SUCCESS(Status))
3213 {
3214 return Status;
3215 }
3216
3217 /*
3218 * Initialize it
3219 */
3220 RtlZeroMemory(Section, sizeof(*Section));
3221
3222 /* Mark this as a "ROS" Section */
3223 Section->u.Flags.filler = 1;
3224
3226 Section->u.Flags.File = 1;
3227 Section->u.Flags.Image = 1;
3229 Section->u.Flags.NoChange = 1;
3230
3231grab_image_section_object:
3232 OldIrql = MiAcquirePfnLock();
3233
3234 /* Wait for it to be properly created or deleted */
3235 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3236 while(ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
3237 {
3238 MiReleasePfnLock(OldIrql);
3239
3241
3242 OldIrql = MiAcquirePfnLock();
3243 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3244 }
3245
3246 if (ImageSectionObject == NULL)
3247 {
3248 NTSTATUS StatusExeFmt;
3249
3250 /* Release the lock because ExAllocatePoolWithTag could need to acquire it */
3251 MiReleasePfnLock(OldIrql);
3252
3253 ImageSectionObject = ExAllocatePoolZero(NonPagedPool, sizeof(MM_IMAGE_SECTION_OBJECT), TAG_MM_SECTION_SEGMENT);
3254 if (ImageSectionObject == NULL)
3255 {
3256 ObDereferenceObject(Section);
3257 return STATUS_NO_MEMORY;
3258 }
3259
3260 ImageSectionObject->SegFlags = MM_SEGMENT_INCREATE;
3261 ImageSectionObject->RefCount = 1;
3262 ImageSectionObject->SectionCount = 1;
3263
3264 OldIrql = MiAcquirePfnLock();
3265 if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
3266 {
3267 MiReleasePfnLock(OldIrql);
3268 /* Bad luck. Start over */
3269 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3270 goto grab_image_section_object;
3271 }
3272
3273 FileObject->SectionObjectPointer->ImageSectionObject = ImageSectionObject;
3274
3275 MiReleasePfnLock(OldIrql);
3276
3277 /* Purge the cache */
3278 CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, NULL);
3279
3280 StatusExeFmt = ExeFmtpCreateImageSection(FileObject, ImageSectionObject);
3281
3282 if (!NT_SUCCESS(StatusExeFmt))
3283 {
3284 /* Unset */
3285 OldIrql = MiAcquirePfnLock();
3286 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3287 MiReleasePfnLock(OldIrql);
3288
3289 if(ImageSectionObject->Segments != NULL)
3290 ExFreePool(ImageSectionObject->Segments);
3291
3292 /*
3293 * If image file is empty, then return that the file is invalid for section
3294 */
3295 Status = StatusExeFmt;
3296 if (StatusExeFmt == STATUS_END_OF_FILE)
3297 {
3299 }
3300
3301 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3302 ObDereferenceObject(Section);
3303 return Status;
3304 }
3305
3306 Section->Segment = (PSEGMENT)ImageSectionObject;
3307 ASSERT(ImageSectionObject->Segments);
3308 ASSERT(ImageSectionObject->RefCount > 0);
3309
3310 /*
3311 * Lock the file
3312 */
3314 if (!NT_SUCCESS(Status))
3315 {
3316 /* Unset */
3317 OldIrql = MiAcquirePfnLock();
3318 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3319 MiReleasePfnLock(OldIrql);
3320
3321 ExFreePool(ImageSectionObject->Segments);
3322 ExFreePool(ImageSectionObject);
3323 ObDereferenceObject(Section);
3324 return Status;
3325 }
3326
3327 OldIrql = MiAcquirePfnLock();
3328 ImageSectionObject->SegFlags &= ~MM_SEGMENT_INCREATE;
3329
3330 /* Take a ref on the file on behalf of the newly created structure */
3332
3333 MiReleasePfnLock(OldIrql);
3334
3335 Status = StatusExeFmt;
3336 }
3337 else
3338 {
3339 /* If FS driver called for delete, tell them it's not possible anymore. */
3340 ImageSectionObject->SegFlags &= ~MM_IMAGE_SECTION_FLUSH_DELETE;
3341
3342 /* Take one ref */
3343 InterlockedIncrement64(&ImageSectionObject->RefCount);
3344 ImageSectionObject->SectionCount++;
3345
3346 MiReleasePfnLock(OldIrql);
3347
3348 Section->Segment = (PSEGMENT)ImageSectionObject;
3349
3351 }
3352 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
3353 *SectionObject = Section;
3354 ASSERT(ImageSectionObject->RefCount > 0);
3355
3356 return Status;
3357}
3358
3359
3360
3361static NTSTATUS
3364 BOOLEAN AsImage,
3368 ULONG Protect,
3369 LONGLONG ViewOffset,
3371{
3372 PMEMORY_AREA MArea;
3374 ULONG Granularity;
3375
3376 ASSERT(ViewSize != 0);
3377
3378 if (Segment->WriteCopy)
3379 {
3380 /* We have to do this because the not present fault
3381 * and access fault handlers depend on the protection
3382 * that should be granted AFTER the COW fault takes
3383 * place to be in Region->Protect. The not present fault
3384 * handler changes this to the correct protection for COW when
3385 * mapping the pages into the process's address space. If a COW
3386 * fault takes place, the access fault handler sets the page protection
3387 * to these values for the newly copied pages
3388 */
3389 if (Protect == PAGE_WRITECOPY)
3391 else if (Protect == PAGE_EXECUTE_WRITECOPY)
3393 }
3394
3395 if (*BaseAddress == NULL)
3396 Granularity = MM_ALLOCATION_GRANULARITY;
3397 else
3398 Granularity = PAGE_SIZE;
3399
3400#ifdef NEWCC
3401 if (Segment->Flags & MM_DATAFILE_SEGMENT)
3402 {
3404 FileOffset.QuadPart = ViewOffset;
3405 ObReferenceObject(Section);
3407 }
3408#endif
3412 ViewSize,
3413 Protect,
3414 &MArea,
3416 Granularity);
3417 if (!NT_SUCCESS(Status))
3418 {
3419 DPRINT1("Mapping between 0x%p and 0x%p failed (%X).\n",
3420 (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status);
3421 return Status;
3422 }
3423
3424 InterlockedIncrement64(Segment->ReferenceCount);
3425
3426 MArea->SectionData.Segment = Segment;
3427 MArea->SectionData.ViewOffset = ViewOffset;
3428 if (AsImage)
3429 {
3431 }
3432
3433 MmInitializeRegion(&MArea->SectionData.RegionListHead,
3434 ViewSize, 0, Protect);
3435
3436 return STATUS_SUCCESS;
3437}
3438
3439
3440static VOID
3442 PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
3443{
3446 SWAPENTRY SavedSwapEntry;
3450
3453
3455
3457 MemoryArea->SectionData.ViewOffset;
3458
3459 Segment = MemoryArea->SectionData.Segment;
3460
3462 while (Entry && MM_IS_WAIT_PTE(Entry))
3463 {
3466
3468
3472 }
3473
3474 /*
3475 * For a dirty, datafile, non-private page, there shoulkd be no swap entry
3476 */
3477 if (*Segment->Flags & MM_DATAFILE_SEGMENT)
3478 {
3479 if (Page == PFN_FROM_SSE(Entry) && Dirty)
3480 {
3481 ASSERT(SwapEntry == 0);
3482 }
3483 }
3484
3485 if (SwapEntry != 0)
3486 {
3487 /*
3488 * Sanity check
3489 */
3490 MmFreeSwapPage(SwapEntry);
3491 }
3492 else if (Page != 0)
3493 {
3494 if (IS_SWAP_FROM_SSE(Entry) ||
3496 {
3497 ASSERT(Process != NULL);
3498
3499 /*
3500 * Just dereference private pages
3501 */
3502 SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
3503 if (SavedSwapEntry != 0)
3504 {
3505 MmFreeSwapPage(SavedSwapEntry);
3507 }
3510 }
3511 else
3512 {
3513 if (Process)
3514 {
3516 }
3517
3518 /* We don't dirtify for System Space Maps. We let Cc manage that */
3520 }
3521 }
3522}
3523
3524static NTSTATUS
3527{
3531 PLIST_ENTRY CurrentEntry;
3532 PMM_REGION CurrentRegion;
3533 PLIST_ENTRY RegionListHead;
3534
3536 BaseAddress);
3537 if (MemoryArea == NULL)
3538 {
3539 return STATUS_UNSUCCESSFUL;
3540 }
3541
3542 Segment = MemoryArea->SectionData.Segment;
3543
3544#ifdef NEWCC
3545 if (Segment->Flags & MM_DATAFILE_SEGMENT)
3546 {
3550
3551 return Status;
3552 }
3553#endif
3554
3556
3558
3559 RegionListHead = &MemoryArea->SectionData.RegionListHead;
3560 while (!IsListEmpty(RegionListHead))
3561 {
3562 CurrentEntry = RemoveHeadList(RegionListHead);
3563 CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
3564 ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
3565 }
3566
3567 if ((*Segment->Flags) & MM_PHYSICALMEMORY_SEGMENT)
3568 {
3570 MemoryArea,
3571 NULL,
3572 NULL);
3573 }
3574 else
3575 {
3577 MemoryArea,
3579 AddressSpace);
3580 }
3582 MmDereferenceSegment(Segment);
3583 return Status;
3584}
3585
3586/* This functions must be called with a locked address space */
3588NTAPI
3591 IN BOOLEAN SkipDebuggerNotify)
3592{
3596 PVOID ImageBaseAddress = 0;
3597
3598 DPRINT("Opening memory area Process %p BaseAddress %p\n",
3600
3601 ASSERT(Process);
3602
3603 AddressSpace = &Process->Vm;
3604
3606 BaseAddress);
3607 if (MemoryArea == NULL ||
3608#ifdef NEWCC
3609 ((MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) && (MemoryArea->Type != MEMORY_AREA_CACHE)) ||
3610#else
3612#endif
3614
3615 {
3617
3618 DPRINT1("Unable to find memory area at address %p.\n", BaseAddress);
3620 }
3621
3623 {
3624 ULONG i;
3625 ULONG NrSegments;
3626 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3627 PMM_SECTION_SEGMENT SectionSegments;
3629
3630 Segment = MemoryArea->SectionData.Segment;
3631 ImageSectionObject = ImageSectionObjectFromSegment(Segment);
3632 SectionSegments = ImageSectionObject->Segments;
3633 NrSegments = ImageSectionObject->NrSegments;
3634
3636
3637 /* Search for the current segment within the section segments
3638 * and calculate the image base address */
3639 for (i = 0; i < NrSegments; i++)
3640 {
3641 if (Segment == &SectionSegments[i])
3642 {
3643 ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
3644 break;
3645 }
3646 }
3647 if (i >= NrSegments)
3648 {
3649 KeBugCheck(MEMORY_MANAGEMENT);
3650 }
3651
3652 for (i = 0; i < NrSegments; i++)
3653 {
3654 PVOID SBaseAddress = (PVOID)
3655 ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
3656
3657 Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
3658 if (!NT_SUCCESS(Status))
3659 {
3660 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3661 SBaseAddress, Process, Status);
3663 }
3664 }
3665 DPRINT("One mapping less for %p\n", ImageSectionObject->FileObject->SectionObjectPointer);
3666 InterlockedDecrement(&ImageSectionObject->MapCount);
3667 }
3668 else
3669 {
3671 PMMVAD Vad = &MemoryArea->VadNode;
3672 PCONTROL_AREA ControlArea = Vad->ControlArea;
3675 LARGE_INTEGER ViewOffset;
3676 ViewOffset.QuadPart = MemoryArea->SectionData.ViewOffset;
3677
3678 InterlockedIncrement64(Segment->ReferenceCount);
3679
3680 ViewSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
3681
3683 if (!NT_SUCCESS(Status))
3684 {
3685 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3688 }
3689
3690 /* These might be deleted now */
3691 Vad = NULL;
3692 MemoryArea = NULL;
3693
3695 {
3696 /* Don't bother */
3697 MmDereferenceSegment(Segment);
3698 return STATUS_SUCCESS;
3699 }
3701
3702 FileObject = Segment->FileObject;
3704
3705 /* Don't bother for auto-delete closed file. */
3707 {
3709 MmDereferenceSegment(Segment);
3710 return STATUS_SUCCESS;
3711 }
3712
3713 /*
3714 * Flush only when last mapping is deleted.
3715 * FIXME: Why ControlArea == NULL? Or rather: is ControlArea ever not NULL here?
3716 */
3717 if (ControlArea == NULL || ControlArea->NumberOfMappedViews == 1)
3718 {
3719 while (ViewSize > 0)
3720 {
3721 ULONG FlushSize = min(ViewSize, PAGE_ROUND_DOWN(MAXULONG));
3722 MmFlushSegment(FileObject->SectionObjectPointer,
3723 &ViewOffset,
3724 FlushSize,
3725 NULL);
3726 ViewSize -= FlushSize;
3727 ViewOffset.QuadPart += FlushSize;
3728 }
3729 }
3730
3732 MmDereferenceSegment(Segment);
3733 }
3734
3735 /* Notify debugger */
3736 if (ImageBaseAddress && !SkipDebuggerNotify) DbgkUnMapViewOfSection(ImageBaseAddress);
3737
3738 return STATUS_SUCCESS;
3739}
3740
3741
3742
3743
3767NTAPI
3769 _In_ HANDLE SectionHandle,
3770 _In_ SECTION_INFORMATION_CLASS SectionInformationClass,
3771 _Out_ PVOID SectionInformation,
3772 _In_ SIZE_T SectionInformationLength,
3774{
3775 PSECTION Section;
3778 PAGED_CODE();
3779
3781 if (PreviousMode != KernelMode)
3782 {
3783 _SEH2_TRY
3784 {
3785 ProbeForWrite(SectionInformation,
3786 SectionInformationLength,
3787 __alignof(ULONG));
3788 if (ResultLength != NULL)
3789 {
3791 sizeof(*ResultLength),
3792 __alignof(SIZE_T));
3793 }
3794 }
3796 {
3798 }
3799 _SEH2_END;
3800 }
3801
3802 if (SectionInformationClass == SectionBasicInformation)
3803 {
3804 if (SectionInformationLength < sizeof(SECTION_BASIC_INFORMATION))
3805 {
3807 }
3808 }
3809 else if (SectionInformationClass == SectionImageInformation)
3810 {
3811 if (SectionInformationLength < sizeof(SECTION_IMAGE_INFORMATION))
3812 {
3814 }
3815 }
3816 else
3817 {
3819 }
3820
3821 Status = ObReferenceObjectByHandle(SectionHandle,
3825 (PVOID*)(PVOID)&Section,
3826 NULL);
3827 if (!NT_SUCCESS(Status))
3828 {
3829 DPRINT1("Failed to reference section: 0x%lx\n", Status);
3830 return Status;
3831 }
3832
3833 switch(SectionInformationClass)
3834 {
3836 {
3838
3839 Sbi.Size = Section->SizeOfSection;
3840 Sbi.BaseAddress = (PVOID)Section->Address.StartingVpn;
3841
3842 Sbi.Attributes = 0;
3843 if (Section->u.Flags.File)
3844 Sbi.Attributes |= SEC_FILE;
3845 if (Section->u.Flags.Image)
3846 Sbi.Attributes |= SEC_IMAGE;
3847
3848 /* Those are not set *************
3849 if (Section->u.Flags.Commit)
3850 Sbi.Attributes |= SEC_COMMIT;
3851 if (Section->u.Flags.Reserve)
3852 Sbi.Attributes |= SEC_RESERVE;
3853 **********************************/
3854
3855 if (Section->u.Flags.Image)
3856 {
3857 if (MiIsRosSectionObject(Section))
3858 {
3859 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
3860 Sbi.BaseAddress = 0;
3861 Sbi.Size.QuadPart = ImageSectionObject->ImageInformation.ImageFileSize;
3862 }
3863 else
3864 {
3865 /* Not supported yet */
3866 ASSERT(FALSE);
3867 }
3868 }
3869 else if (MiIsRosSectionObject(Section))
3870 {
3871 Sbi.BaseAddress = (PVOID)((PMM_SECTION_SEGMENT)Section->Segment)->Image.VirtualAddress;
3872 Sbi.Size.QuadPart = ((PMM_SECTION_SEGMENT)Section->Segment)->RawLength.QuadPart;
3873 }
3874 else
3875 {
3876 DPRINT1("Unimplemented code path\n");
3877 }
3878
3879 _SEH2_TRY
3880 {
3881 *((SECTION_BASIC_INFORMATION*)SectionInformation) = Sbi;
3882 if (ResultLength != NULL)
3883 {
3884 *ResultLength = sizeof(Sbi);
3885 }
3886 }
3888 {
3890 }
3891 _SEH2_END;
3892 break;
3893 }
3895 {
3896 if (!Section->u.Flags.Image)
3897 {
3899 }
3900 else if (MiIsRosSectionObject(Section))
3901 {
3902 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
3903
3904 _SEH2_TRY
3905 {
3907 *Sii = ImageSectionObject->ImageInformation;
3908 if (ResultLength != NULL)
3909 {
3910 *ResultLength = sizeof(*Sii);
3911 }
3912 }
3914 {
3916 }
3917 _SEH2_END;
3918 }
3919 else
3920 {
3921 _SEH2_TRY
3922 {
3924 *Sii = *Section->Segment->u2.ImageInformation;
3925 if (ResultLength != NULL)
3926 *ResultLength = sizeof(*Sii);
3927 }
3929 {
3931 }
3932 _SEH2_END;
3933 }
3934 break;
3935 }
3936 default:
3937 DPRINT1("Unknown SectionInformationClass: %d\n", SectionInformationClass);
3939 }
3940
3941 ObDereferenceObject(Section);
3942
3943 return Status;
3944}
3945
3946/**********************************************************************
3947 * NAME EXPORTED
3948 * MmMapViewOfSection
3949 *
3950 * DESCRIPTION
3951 * Maps a view of a section into the virtual address space of a
3952 * process.
3953 *
3954 * ARGUMENTS
3955 * Section
3956 * Pointer to the section object.
3957 *
3958 * ProcessHandle
3959 * Pointer to the process.
3960 *
3961 * BaseAddress
3962 * Desired base address (or NULL) on entry;
3963 * Actual base address of the view on exit.
3964 *
3965 * ZeroBits
3966 * Number of high order address bits that must be zero.
3967 *
3968 * CommitSize
3969 * Size in bytes of the initially committed section of
3970 * the view.
3971 *
3972 * SectionOffset
3973 * Offset in bytes from the beginning of the section
3974 * to the beginning of the view.
3975 *
3976 * ViewSize
3977 * Desired length of map (or zero to map all) on entry
3978 * Actual length mapped on exit.
3979 *
3980 * InheritDisposition
3981 * Specified how the view is to be shared with
3982 * child processes.
3983 *
3984 * AllocationType
3985 * Type of allocation for the pages.
3986 *
3987 * Protect
3988 * Protection for the committed region of the view.
3989 *
3990 * RETURN VALUE
3991 * Status.
3992 *
3993 * @implemented
3994 */
4006{
4007 PSECTION Section;
4010 BOOLEAN NotAtBase = FALSE;
4011 BOOLEAN IsAttached = FALSE;
4013
4015 {
4016 DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
4018 Process,
4020 ZeroBits,
4021 CommitSize,
4023 ViewSize,
4026 Protect);
4027 }
4028
4029 ASSERT(Process);
4030
4032 {
4034 }
4035
4037 {
4039 IsAttached = TRUE;
4040 }
4041
4042 /* FIXME: We should keep this, but it would break code checking equality */
4043 Protect &= ~PAGE_NOCACHE;
4044
4045 Section = SectionObject;
4046 AddressSpace = &Process->Vm;
4047
4048 if (Section->u.Flags.NoChange)
4050
4052
4053 if (Section->u.Flags.Image)
4054 {
4055 ULONG i;
4056 ULONG NrSegments;
4057 ULONG_PTR ImageBase;
4058 SIZE_T ImageSize;
4059 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
4060 PMM_SECTION_SEGMENT SectionSegments;
4061
4062 ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
4063 SectionSegments = ImageSectionObject->Segments;
4064 NrSegments = ImageSectionObject->NrSegments;
4065
4066 ASSERT(ImageSectionObject->RefCount > 0);
4067
4068 ImageBase = (ULONG_PTR)*BaseAddress;
4069 if (ImageBase == 0)
4070 {
4071 ImageBase = (ULONG_PTR)ImageSectionObject->BasedAddress;
4072 }
4073
4074 ImageSize = 0;
4075 for (i = 0; i < NrSegments; i++)
4076 {
4077 ULONG_PTR MaxExtent;
4078 MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
4079 SectionSegments[i].Length.QuadPart);
4080 ImageSize = max(ImageSize, MaxExtent);
4081 }
4082
4083 ImageSectionObject->ImageInformation.ImageFileSize = (ULONG)ImageSize;
4084
4085 /* Check for an illegal base address */
4086 if (((ImageBase + ImageSize) > (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS) ||
4087 ((ImageBase + ImageSize) < ImageSize))
4088 {
4089 ASSERT(*BaseAddress == NULL);
4090 ImageBase = ALIGN_DOWN_BY((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - ImageSize,
4092 NotAtBase = TRUE;
4093 }
4094 else if (ImageBase != ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY))
4095 {
4096 ASSERT(*BaseAddress == NULL);
4097 ImageBase = ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY);
4098 NotAtBase = TRUE;
4099 }
4100
4101 /* Check there is enough space to map the section at that point. */
4103 PAGE_ROUND_UP(ImageSize)) != NULL)
4104 {
4105 /* Fail if the user requested a fixed base address. */
4106 if ((*BaseAddress) != NULL)
4107 {
4109 goto Exit;
4110 }
4111 /* Otherwise find a gap to map the image. */
4113 if (ImageBase == 0)
4114 {
4116 goto Exit;
4117 }
4118 /* Remember that we loaded image at a different base address */
4119 NotAtBase = TRUE;
4120 }
4121
4122 for (i = 0; i < NrSegments; i++)
4123 {
4124 PVOID SBaseAddress = (PVOID)
4125 ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4126 MmLockSectionSegment(&SectionSegments[i]);
4128 TRUE,
4129 &SectionSegments[i],
4130 &SBaseAddress,
4131 SectionSegments[i].Length.QuadPart,
4132 SectionSegments[i].Protection,
4133 0,
4134 0);
4135 MmUnlockSectionSegment(&SectionSegments[i]);
4136 if (!NT_SUCCESS(Status))
4137 {
4138 /* roll-back */
4139 while (i--)
4140 {
4141 SBaseAddress = ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4142 MmLockSectionSegment(&SectionSegments[i]);
4143 MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
4144 MmUnlockSectionSegment(&SectionSegments[i]);
4145 }
4146
4147 goto Exit;
4148 }
4149 }
4150
4151 *BaseAddress = (PVOID)ImageBase;
4152 *ViewSize = ImageSize;
4153
4154 DPRINT("Mapped %p for section pointer %p\n", ImageSectionObject, ImageSectionObject->FileObject->SectionObjectPointer);
4155
4156 /* One more map */
4157 InterlockedIncrement(&ImageSectionObject->MapCount);
4158 }
4159 else
4160 {
4162 LONGLONG ViewOffset;
4163
4164 ASSERT(Segment->RefCount > 0);
4165
4166 /* check for write access */
4169 {
4171 goto Exit;
4172 }
4173 /* check for read access */
4176 {
4178 goto Exit;
4179 }
4180 /* check for execute access */
4183 {
4185 goto Exit;
4186 }
4187
4188 if (SectionOffset == NULL)
4189 {
4190 ViewOffset = 0;
4191 }
4192 else
4193 {
4194 ViewOffset = SectionOffset->QuadPart;
4195 }
4196
4197 if ((ViewOffset % PAGE_SIZE) != 0)
4198 {
4200 goto Exit;
4201 }
4202
4203 if ((*ViewSize) == 0)
4204 {
4205 (*ViewSize) = Section->SizeOfSection.QuadPart - ViewOffset;
4206 }
4207 else if ((ExGetPreviousMode() == UserMode) &&
4208 (((*ViewSize)+ViewOffset) > Section->SizeOfSection.QuadPart) &&
4209 (!Section->u.Flags.Reserve))
4210 {
4211 /* Dubious */
4212 (*ViewSize) = MIN(Section->SizeOfSection.QuadPart - ViewOffset, SIZE_T_MAX - PAGE_SIZE);
4213 }
4214
4216
4219 FALSE,
4220 Segment,
4222 *ViewSize,
4223 Protect,
4224 ViewOffset,
4227 if (!NT_SUCCESS(Status))
4228 {
4229 goto Exit;
4230 }
4231 }
4232
4233 if (NotAtBase)
4235 else
4237
4238Exit:
4239
4241
4242 if (IsAttached)
4243 {
4245 }
4246
4247 return Status;
4248}
4249
4250/*
4251 * @unimplemented
4252 */
4253BOOLEAN
4254NTAPI
4258{
4259 BOOLEAN Ret;
4261
4262 /* Check whether an ImageSectionObject exists */
4263 if (SectionObjectPointer->ImageSectionObject != NULL)
4264 {
4265 DPRINT1("ERROR: File can't be truncated because it has an image section\n");
4266 return FALSE;
4267 }
4268
4270 if (!Segment)
4271 {
4272 /* There is no data section. It's fine to do anything. */
4273 return TRUE;
4274 }
4275
4277 if ((Segment->SectionCount == 0) ||
4278 ((Segment->SectionCount == 1) && (SectionObjectPointer->SharedCacheMap != NULL)))
4279 {
4280 /* If the cache is the only one holding a reference to the segment, then it's fine to resize */
4281 Ret = TRUE;
4282 }
4283 else if (NewFileSize != NULL)
4284 {
4285 /* We can't shrink, but we can extend */
4286 Ret = NewFileSize->QuadPart >= Segment->RawLength.QuadPart;
4287#if DBG
4288 if (!Ret)
4289 {
4290 DPRINT1("Cannot truncate data: New Size %I64d, Segment Size %I64d\n", NewFileSize->QuadPart, Segment->RawLength.QuadPart);
4291 }
4292#endif
4293 }
4294 else
4295 {
4296 DPRINT1("ERROR: File can't be truncated because it has references held to its data section\n");
4297 Ret = FALSE;
4298 }
4299
4301 MmDereferenceSegment(Segment);
4302
4303 DPRINT("FIXME: didn't check for outstanding write probes\n");
4304
4305 return Ret;
4306}
4307
4308static
4309BOOLEAN
4311{
4313
4315
4316 /* Loop over all entries */
4317 for (PageTable = RtlEnumerateGenericTable(&Segment->PageTable, TRUE);
4318 PageTable != NULL;
4320 {
4321 for (ULONG i = 0; i < _countof(PageTable->PageEntries); i++)
4322 {
4323 ULONG_PTR Entry = PageTable->PageEntries[i];
4325
4326 if (!Entry)
4327 continue;
4328
4330 {
4331 /* I/O ongoing or swap entry. Someone mapped this file as we were not looking */
4333 return FALSE;
4334 }
4335
4336 /* Regular entry */
4339
4340 /* Properly remove using the used API */
4341 Offset.QuadPart = PageTable->FileOffset.QuadPart + (i << PAGE_SHIFT);
4344 }
4345 }
4346
4348
4349 return TRUE;
4350}
4351
4352/*
4353 * @implemented
4354 */
4358{
4359 switch(FlushType)
4360 {
4361 case MmFlushForDelete:
4362 {
4363 /*
4364 * FIXME: Check for outstanding write probes on Data section.
4365 * How do we do that ?
4366 */
4367 }
4368 /* Fall-through */
4369 case MmFlushForWrite:
4370 {
4371 KIRQL OldIrql = MiAcquirePfnLock();
4372 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4373
4374 DPRINT("Deleting or modifying %p\n", SectionObjectPointer);
4375
4376 /* Wait for concurrent creation or deletion of image to be done */
4377 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4378 while (ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INCREATE | MM_SEGMENT_INDELETE)))
4379 {
4380 MiReleasePfnLock(OldIrql);
4382 OldIrql = MiAcquirePfnLock();
4383 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4384 }
4385
4386 if (!ImageSectionObject)
4387 {
4388 DPRINT("No image section object. Accepting\n");
4389 /* Nothing to do */
4390 MiReleasePfnLock(OldIrql);
4391 return TRUE;
4392 }
4393
4394 /* Do we have open sections or mappings on it ? */
4395 if ((ImageSectionObject->SectionCount) || (ImageSectionObject->MapCount))
4396 {
4397 /* We do. No way to delete it */
4398 MiReleasePfnLock(OldIrql);
4399 DPRINT("Denying. There are mappings open\n");
4400 return FALSE;
4401 }
4402
4403 /* There are no sections open on it, but we must still have pages around. Discard everything */
4404 ImageSectionObject->SegFlags |= MM_IMAGE_SECTION_FLUSH_DELETE;
4405 InterlockedIncrement64(&ImageSectionObject->RefCount);
4406 MiReleasePfnLock(OldIrql);
4407
4408 DPRINT("Purging\n");
4409
4410 for (ULONG i = 0; i < ImageSectionObject->NrSegments; i++)
4411 {
4412 if (!MiPurgeImageSegment(&ImageSectionObject->Segments[i]))
4413 break;
4414 }
4415
4416 /* Grab lock again */
4417 OldIrql = MiAcquirePfnLock();
4418
4419 if (!(ImageSectionObject->SegFlags & MM_IMAGE_SECTION_FLUSH_DELETE))
4420 {
4421 /*
4422 * Someone actually created a section while we were not looking.
4423 * Drop our ref and deny.
4424 * MmDereferenceSegmentWithLock releases Pfn lock
4425 */
4426 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4427 return FALSE;
4428 }
4429
4430 /* We should be the last one holding a ref here. */
4431 ASSERT(ImageSectionObject->RefCount == 1);
4432 ASSERT(ImageSectionObject->SectionCount == 0);
4433
4434 /* Dereference the first segment, this will free everything & release the lock */
4435 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4436 return TRUE;
4437 }
4438 }
4439 return FALSE;
4440}
4441
4442/*
4443 * @implemented
4444 */
4446NTAPI
4450{
4452
4453 SectionOffset.QuadPart = 0;
4454
4456}
4457
4459NTAPI
4466 )
4467{
4468 PSECTION Section = SectionObject;
4472
4474
4475 PAGED_CODE();
4476
4478 {
4480 &MmSession,
4481 MappedBase,
4482 ViewSize,
4484 }
4485
4486 DPRINT("MmMapViewInSystemSpaceEx() called\n");
4487
4488 /* unsupported for now */
4489 ASSERT(Section->u.Flags.Image == 0);
4490
4491 Section = SectionObject;
4493
4494 if (*ViewSize == 0)
4495 {
4496 LONGLONG MapSizeLL;
4497
4498 /* Page-align the mapping */
4499 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4500
4501 if (!NT_SUCCESS(RtlLongLongSub(Section->SizeOfSection.QuadPart, SectionOffset->QuadPart, &MapSizeLL)))
4503
4504 if (!NT_SUCCESS(RtlLongLongToSIZET(MapSizeLL, ViewSize)))
4506 }
4507 else
4508 {
4509 LONGLONG HelperLL;
4510
4511 /* Get the map end */
4512 if (!NT_SUCCESS(RtlLongLongAdd(SectionOffset->QuadPart, *ViewSize, &HelperLL)))
4514
4515 /* Round it up, if needed */
4516 if (HelperLL % PAGE_SIZE)
4517 {
4518 if (!NT_SUCCESS(RtlLongLongAdd(HelperLL, PAGE_SIZE - (HelperLL % PAGE_SIZE), &HelperLL)))
4520 }
4521
4522 /* Now that we have the mapping end, we can align down its start */
4523 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4524
4525 /* Get the new size */
4526 if (!NT_SUCCESS(RtlLongLongSub(HelperLL, SectionOffset->QuadPart, &HelperLL)))
4528
4529 if (!NT_SUCCESS(RtlLongLongToSIZET(HelperLL, ViewSize)))
4531 }
4532
4534
4536
4538
4540 Section->u.Flags.Image,
4541 Segment,
4542 MappedBase,
4543 *ViewSize,
4545 SectionOffset->QuadPart,
4546 SEC_RESERVE);
4547
4550
4551 return Status;
4552}
4553
4554/* This function must be called with address space lock held */
4556NTAPI
4558{
4559 DPRINT("MmUnmapViewInSystemSpace() called\n");
4560
4562}
4563
4564/**********************************************************************
4565 * NAME EXPORTED
4566 * MmCreateSection@
4567 *
4568 * DESCRIPTION
4569 * Creates a section object.
4570 *
4571 * ARGUMENTS
4572 * SectionObject (OUT)
4573 * Caller supplied storage for the resulting pointer
4574 * to a SECTION_OBJECT instance;
4575 *
4576 * DesiredAccess
4577 * Specifies the desired access to the section can be a
4578 * combination of:
4579 * STANDARD_RIGHTS_REQUIRED |
4580 * SECTION_QUERY |
4581 * SECTION_MAP_WRITE |
4582 * SECTION_MAP_READ |
4583 * SECTION_MAP_EXECUTE
4584 *
4585 * ObjectAttributes [OPTIONAL]
4586 * Initialized attributes for the object can be used
4587 * to create a named section;
4588 *
4589 * MaximumSize
4590 * Maximizes the size of the memory section. Must be
4591 * non-NULL for a page-file backed section.
4592 * If value specified for a mapped file and the file is
4593 * not large enough, file will be extended.
4594 *
4595 * SectionPageProtection
4596 * Can be a combination of:
4597 * PAGE_READONLY |
4598 * PAGE_READWRITE |
4599 * PAGE_WRITEONLY |
4600 * PAGE_WRITECOPY
4601 *
4602 * AllocationAttributes
4603 * Can be a combination of:
4604 * SEC_IMAGE |
4605 * SEC_RESERVE
4606 *
4607 * FileHandle
4608 * Handle to a file to create a section mapped to a file
4609 * instead of a memory backed section;
4610 *
4611 * File
4612 * Unknown.
4613 *
4614 * RETURN VALUE
4615 * Status.
4616 *
4617 * @implemented
4618 */
4628{
4630 ULONG Protection;
4631 PSECTION *SectionObject = (PSECTION *)Section;
4632 BOOLEAN FileLock = FALSE;
4633
4634 /* Check if an ARM3 section is being created instead */
4636 {
4637 if (!(FileObject) && !(FileHandle))
4638 {
4639 return MmCreateArm3Section(Section,
4645 FileHandle,
4646 FileObject);
4647 }
4648 }
4649
4650 /* Convert section flag to page flag */
4652
4653 /* Check to make sure the protection is correct. Nt* does this already */
4655 if (Protection == MM_INVALID_PROTECTION)
4656 {
4657 DPRINT1("Page protection is invalid\n");
4659 }
4660
4661 /* Check if this is going to be a data or image backed file section */
4662 if ((FileHandle) || (FileObject))
4663 {
4664 /* These cannot be mapped with large pages */
4666 {
4667 DPRINT1("Large pages cannot be used with an image mapping\n");
4669 }
4670
4671 /* Did the caller pass a file object ? */
4672 if (FileObject)
4673 {
4674 /* Reference the object directly */
4676
4677 /* We don't create image mappings with file objects */
4678 AllocationAttributes &= ~SEC_IMAGE;
4679 }
4680 else
4681 {
4682 /* Reference the file handle to get the object */
4684 MmMakeFileAccess[Protection],
4687 (PVOID*)&FileObject,
4688 NULL);
4689 if (!NT_SUCCESS(Status))
4690 {
4691 DPRINT1("Failed to get a handle to the FO: %lx\n", Status);
4692 return Status;
4693 }
4694
4695 /* Lock the file */
4697 if (!NT_SUCCESS(Status))
4698 {
4700 return Status;
4701 }
4702
4703 FileLock = TRUE;
4704
4705 /* Deny access if there are writes on the file */
4706#if 0
4708 {
4709 DPRINT1("Cannot create image maps with writers open on the file!\n");
4711 goto Quit;
4712 }
4713#else
4715 DPRINT1("Creating image map with writers open on the file!\n");
4716#endif
4717 }
4718 }
4719 else
4720 {
4721 /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
4723 }
4724
4726 {
4733 FileObject);
4734 }
4735#ifndef NEWCC
4736 else if (FileObject != NULL)
4737 {
4744 FileObject,
4745 FileHandle != NULL);
4746 }
4747#else
4748 else if (FileHandle != NULL || FileObject != NULL)
4749 {
4756 FileObject);
4757 }
4758#endif
4759 else
4760 {
4761 /* All cases should be handled above */
4763 }
4764
4765 if (FileLock)
4767 if (FileObject)
4769
4770 return Status;
4771}
4772
4773BOOLEAN
4774NTAPI
4779{
4781 BOOLEAN Ret = TRUE;
4783 LARGE_INTEGER SegmentOffset, RangeEnd;
4785
4787
4789 if (MemoryArea == NULL)
4790 {
4792 return FALSE;
4793 }
4794
4795 /* Only supported in old Mm for now */
4797 /* For file mappings */
4799
4800 Segment = MemoryArea->SectionData.Segment;
4802
4804 + MemoryArea->SectionData.ViewOffset;
4806 + MemoryArea->SectionData.ViewOffset;
4807
4808 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
4809 {
4811 if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
4812 {
4813 Ret = FALSE;
4814 break;
4815 }
4816 SegmentOffset.QuadPart += PAGE_SIZE;
4817 }
4818
4820
4822 return Ret;
4823}
4824
4825/* Like CcPurgeCache but for the in-memory segment */
4826BOOLEAN
4827NTAPI
4832{
4833 LARGE_INTEGER PurgeStart, PurgeEnd;
4835
4837 if (!Segment)
4838 {
4839 /* Nothing to purge */
4840 return TRUE;
4841 }
4842
4843 PurgeStart.QuadPart = Offset ? Offset->QuadPart : 0LL;
4844 if (Length && Offset)
4845 {
4846 if (!NT_SUCCESS(RtlLongLongAdd(PurgeStart.QuadPart, Length, &PurgeEnd.QuadPart)))
4847 return FALSE;
4848 }
4849
4851
4852 if (!Length || !Offset)
4853 {
4854 /* We must calculate the length for ourselves */
4855 /* FIXME: All of this is suboptimal */
4856 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
4857 /* No page. Nothing to purge */
4858 if (!ElemCount)
4859 {
4861 MmDereferenceSegment(Segment);
4862 return TRUE;
4863 }
4864
4866 PurgeEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
4867 }
4868
4869 while (PurgeStart.QuadPart < PurgeEnd.QuadPart)
4870 {
4872
4873 if (Entry == 0)
4874 {
4875 PurgeStart.QuadPart += PAGE_SIZE;
4876 continue;
4877 }
4878
4880 {
4881 ASSERT(SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY);
4882 /* The page is currently being read. Meaning someone will need it soon. Bad luck */
4884 MmDereferenceSegment(Segment);
4885 return FALSE;
4886 }
4887
4888 if (IS_WRITE_SSE(Entry))
4889 {
4890 /* We're trying to purge an entry which is being written. Restart this loop iteration */
4894 continue;
4895 }
4896
4897 if (SHARE_COUNT_FROM_SSE(Entry) > 0)
4898 {
4899 /* This page is currently in use. Bad luck */
4901 MmDereferenceSegment(Segment);
4902 return FALSE;
4903 }
4904
4905 /* We can let this page go */
4906 MmSetPageEntrySectionSegment(Segment, &PurgeStart, 0);
4908
4909 PurgeStart.QuadPart += PAGE_SIZE;
4910 }
4911
4912 /* This page is currently in use. Bad luck */
4914 MmDereferenceSegment(Segment);
4915 return TRUE;
4916}
4917
4919NTAPI
4924 _In_ PLARGE_INTEGER ValidDataLength)
4925{
4927
4928 /* There must be a segment for this call */
4929 ASSERT(Segment);
4930
4932
4933 MmDereferenceSegment(Segment);
4934
4935 return Status;
4936}
4937
4939NTAPI
4945{
4946 LARGE_INTEGER FlushStart, FlushEnd;
4948
4949 if (Offset)
4950 {
4951 FlushStart = *Offset;
4952 Status = RtlLongLongAdd(FlushStart.QuadPart, Length, &FlushEnd.QuadPart);
4953 if (!NT_SUCCESS(Status))
4954 return Status;
4955 }
4956
4957 if (Iosb)
4958 Iosb->Information = 0;
4959
4961 if (!Segment)
4962 {
4963 /* Nothing to flush */
4964 if (Iosb)
4965 Iosb->Status = STATUS_SUCCESS;
4966 return STATUS_SUCCESS;
4967 }
4968
4970
4972
4973 if (!Offset)
4974 {
4975 FlushStart.QuadPart = 0;
4976
4977 /* FIXME: All of this is suboptimal */
4978 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
4979 /* No page. Nothing to flush */
4980 if (!ElemCount)
4981 {
4983 MmDereferenceSegment(Segment);
4984 if (Iosb)
4985 {
4986 Iosb->Status = STATUS_SUCCESS;
4987 Iosb->Information = 0;
4988 }
4989 return STATUS_SUCCESS;
4990 }
4991
4993 FlushEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
4994 }
4995
4996 FlushStart.QuadPart >>= PAGE_SHIFT;
4997 FlushStart.QuadPart <<= PAGE_SHIFT;
4998
4999 while (FlushStart.QuadPart < FlushEnd.QuadPart)
5000 {
5002
5003 if (IS_DIRTY_SSE(Entry))
5004 {
5005 MmCheckDirtySegment(Segment, &FlushStart, FALSE, FALSE);
5006
5007 if (Iosb)
5008 Iosb->Information += PAGE_SIZE;
5009 }
5010
5011 FlushStart.QuadPart += PAGE_SIZE;
5012 }
5013
5015 MmDereferenceSegment(Segment);
5016
5017 if (Iosb)
5018 Iosb->Status = STATUS_SUCCESS;
5019
5020 return STATUS_SUCCESS;
5021}
5022
5024BOOLEAN
5025NTAPI
5031{
5035
5036 ASSERT(Segment->Locked);
5037
5038 ASSERT((Offset->QuadPart % PAGE_SIZE) == 0);
5039
5040 DPRINT("Checking segment for file %wZ at offset 0x%I64X.\n", &Segment->FileObject->FileName, Offset->QuadPart);
5041
5043 if (Entry == 0)
5044 return FALSE;
5045
5047 if ((IS_DIRTY_SSE(Entry)) || ForceDirty)
5048 {
5049 BOOLEAN DirtyAgain;
5050
5051 /*
5052 * We got a dirty entry. This path is for the shared data,
5053 * be-it regular file maps or shared sections of DLLs
5054 */
5056 FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5057
5058 /* Insert the cleaned entry back. Mark it as write in progress, and clear the dirty bit. */
5062
5064
5065 if (FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5066 {
5068 KIRQL OldIrql;
5069
5070 /* We have to write it back to the file. Tell the FS driver who we are */
5071 if (PageOut)
5072 {
5073 LARGE_INTEGER EndOffset = *Offset;
5074
5076
5077 /* We need to disable all APCs */
5079
5080 EndOffset.QuadPart += PAGE_SIZE;
5082 &EndOffset,
5084 if (NT_SUCCESS(Status))
5085 {
5087 }
5088 else
5089 {
5090 /* Make sure we will not try to release anything */
5092 }
5093 }
5094 else
5095 {
5096 /* We don't have to lock. Say this is success */
5098 }
5099
5100 /* Go ahead and write the page, if previous locking succeeded */
5101 if (NT_SUCCESS(Status))
5102 {
5103 DPRINT("Writing page at offset %I64d for file %wZ, Pageout: %s\n",
5104 Offset->QuadPart, &Segment->FileObject->FileName, PageOut ? "TRUE" : "FALSE");
5105 Status = MiWritePage(Segment, Offset->QuadPart, Page);
5106 }
5107
5108 if (PageOut)
5109 {
5111 if (ResourceToRelease != NULL)
5112 {
5114 }
5116 }
5117 }
5118 else
5119 {
5120 /* This must only be called by the page-out path */
5121 ASSERT(PageOut);
5122
5123 /* And this must be for a shared section in a DLL */
5124 ASSERT(FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5125
5127 if (!SwapEntry)
5128 {
5129 SwapEntry = MmAllocSwapPage();
5130 }
5131
5132 if (SwapEntry)
5133 {
5134 Status = MmWriteToSwapPage(SwapEntry, Page);
5135 if (NT_SUCCESS(Status))
5136 {
5137 MmSetSavedSwapEntryPage(Page, SwapEntry);
5138 }
5139 else
5140 {
5141 MmFreeSwapPage(SwapEntry);
5142 }
5143 }
5144 else
5145 {
5146 DPRINT1("Failed to allocate a swap page!\n");
5148 }
5149 }
5150
5152
5153 /* Get the entry again */
5156
5157 if (!NT_SUCCESS(Status))
5158 {
5159 /* Damn, this failed. Consider this page as still dirty */
5160 DPRINT1("MiWritePage FAILED: Status 0x%08x!\n", Status);
5161 DirtyAgain = TRUE;
5162 }
5163 else
5164 {
5165 /* Check if someone dirtified this page while we were not looking */
5166 DirtyAgain = IS_DIRTY_SSE(Entry);
5167 }
5168
5169 /* Drop the reference we got, deleting the write altogether. */
5171 if (DirtyAgain)
5172 {
5174 }
5176 }
5177
5178 /* Were this page hanging there just for the sake of being present ? */
5180 {
5181 ULONG_PTR NewEntry = 0;
5182 /* Restore the swap entry here */
5183 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5184 {
5186 if (SwapEntry)
5187 NewEntry = MAKE_SWAP_SSE(SwapEntry);
5188 }
5189
5190 /* Yes. Release it */
5193 /* Tell the caller we released the page */
5194 return TRUE;
5195 }
5196
5197 return FALSE;
5198}
5199
5201NTAPI
5206{
5209 LARGE_INTEGER SegmentOffset, RangeEnd;
5211
5213
5215 if (MemoryArea == NULL)
5216 {
5217 DPRINT1("Unable to find memory area at address %p.\n", Address);
5220 }
5221
5222 /* Only supported in old Mm for now */
5224 /* For file mappings */
5226
5227 Segment = MemoryArea->SectionData.Segment;
5229
5231 + MemoryArea->SectionData.ViewOffset;
5233 + MemoryArea->SectionData.ViewOffset;
5234
5235 DPRINT("MmMakePagesResident: Segment %p, 0x%I64x -> 0x%I64x\n", Segment, SegmentOffset.QuadPart, RangeEnd.QuadPart);
5236
5237 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
5238 {
5240
5241 /* Let any pending read proceed */
5242 while (MM_IS_WAIT_PTE(Entry))
5243 {
5249 Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset);
5250 }
5251
5252 /* We are called from Cc, this can't be backed by the page files */
5254
5255 /* If there is no page there, there is nothing to make dirty */
5256 if (Entry != 0)
5257 {
5258 /* Dirtify the entry */
5260 }
5261
5262 SegmentOffset.QuadPart += PAGE_SIZE;
5263 }
5264
5266
5268 return STATUS_SUCCESS;
5269}
5270
5272NTAPI
5274 _In_ PVOID _Section,
5276{
5277 PSECTION Section = _Section;
5278
5279 /* It makes no sense to extend an image mapping */
5280 if (Section->u.Flags.Image)
5282
5283 /* Nor is it possible to extend a page file mapping */
5284 if (!Section->u.Flags.File)
5286
5287 if (!MiIsRosSectionObject(Section))
5289
5290 /* We just extend the sizes. Shrinking is a no-op ? */
5291 if (NewSize->QuadPart > Section->SizeOfSection.QuadPart)
5292 {
5294 Section->SizeOfSection = *NewSize;
5295
5296 if (!Section->u.Flags.Reserve)
5297 {
5299 if (Segment->RawLength.QuadPart < NewSize->QuadPart)
5300 {
5301 Segment->RawLength = *NewSize;
5302 Segment->Length.QuadPart = (NewSize->QuadPart + PAGE_SIZE - 1) & ~((LONGLONG)PAGE_SIZE);
5303 }
5305 }
5306 }
5307
5308 return STATUS_SUCCESS;
5309}
5310
5311/* 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:1040
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:2468
VOID NTAPI MiDeleteARM3Section(PVOID ObjectBody)
Definition: section.c:3316
NTSTATUS NTAPI MmMapViewOfArm3Section(IN PVOID SectionObject, IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:2896
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()
ULONG ReadLength
#define ALIGN_DOWN_BY(size, align)
#define ALIGN_UP_BY(size, align)
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define __cdecl
Definition: accygwin.h:79
struct NameRec_ * Name
Definition: cdprocs.h:460
#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:103
#define InterlockedIncrement64(a)
Definition: btrfs_drv.h:143
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1431
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
VOID NTAPI DbgkUnMapViewOfSection(IN PVOID BaseAddress)
Definition: dbgkutil.c:436
#define BufferSize
Definition: mmc.h:75
#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:32
#define PAGE_READONLY
Definition: compat.h:138
#define SECTION_MAP_READ
Definition: compat.h:139
return Iosb
Definition: create.c:4402
#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:140
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1527
#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:1082
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
@ 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:85
#define OBJ_OPENLINK
Definition: winternl.h:230
#define OBJ_PERMANENT
Definition: winternl.h:226
@ ProcessHandleCount
Definition: winternl.h:876
#define InterlockedDecrement64
Definition: interlocked.h:144
unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask)
Definition: intrin_arm.h:57
#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
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
if(dx< 0)
Definition: linetemp.h:194
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
FORCEINLINE BOOLEAN MiIsRosSectionObject(IN PSECTION Section)
Definition: miarm.h:1098
#define _64K
Definition: miarm.h:23
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
NTSTATUS NTAPI MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:4557
NTSTATUS NTAPI MiRosUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress, IN BOOLEAN SkipDebuggerNotify)
Definition: section.c:3589
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
#define SECTION
Definition: profile.c:31
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
#define _Outptr_result_bytebuffer_(size)
Definition: ms_sal.h:472
#define _Out_opt_
Definition: ms_sal.h:346
#define _Inout_
Definition: ms_sal.h:378
#define _Out_
Definition: ms_sal.h:345
#define _When_(expr, annos)
Definition: ms_sal.h:254
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
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 KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
#define MM_ALLOCATION_GRANULARITY
Definition: mmtypes.h:36
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT InheritDisposition
Definition: mmfuncs.h:409
_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 PVOID _In_ ULONG_PTR ZeroBits
Definition: mmfuncs.h:405
_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 PVOID * BaseAddress
Definition: mmfuncs.h:404
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG AllocationType
Definition: mmfuncs.h:410
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER SectionOffset
Definition: mmfuncs.h:407
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:406
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:408
__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_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 MEM_TOP_DOWN
Definition: nt_native.h:1321
#define SECTION_MAP_EXECUTE
Definition: nt_native.h:1290
#define PAGE_WRITECOPY
Definition: nt_native.h:1305
#define SECTION_MAP_WRITE
Definition: nt_native.h:1288
#define PAGE_NOCACHE
Definition: nt_native.h:1311
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define PAGE_EXECUTE_READ
Definition: nt_native.h:1307
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
#define SECTION_QUERY
Definition: nt_native.h:1287
#define PAGE_EXECUTE
Definition: nt_native.h:1306
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define SEC_RESERVE
Definition: nt_native.h:1323
#define MEM_MAPPED
Definition: nt_native.h:1319
enum _SECTION_INHERIT SECTION_INHERIT
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define PAGE_EXECUTE_WRITECOPY
Definition: nt_native.h:1309
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
#define MEM_COMMIT
Definition: nt_native.h:1313
#define PAGE_NOACCESS
Definition: nt_native.h:1302
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
#define PAGE_GUARD
Definition: nt_native.h:1310
#define TYPE_ALIGNMENT(t)
Definition: ntbasedef.h:117
#define RTL_CONTAINS_FIELD(Struct, Size, Field)
Definition: ntbasedef.h:675
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
#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:1852
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:1959
VOID NTAPI FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1659
VOID NTAPI FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1634
NTSTATUS NTAPI FsRtlAcquireToCreateMappedSection(_In_ PFILE_OBJECT FileObject, _In_ ULONG SectionPageProtection)
Definition: fastio.c:1647
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:46
#define MmGetPageEntrySectionSegment(S, O)
Definition: mm.h:1602
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
#define MM_NOIRQL
Definition: mm.h:70
@ MI_USAGE_SECTION
Definition: mm.h:333
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1691
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
KSPIN_LOCK MmPfnLock
Definition: krnlinit.c:49
#define DIRTY_SSE(E)
Definition: mm.h:1375
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:1397
NTSTATUS NTAPI MmCreateMemoryArea(PMMSUPPORT AddressSpace, ULONG Type, PVOID *BaseAddress, SIZE_T Length, ULONG Protection, PMEMORY_AREA *Result, ULONG AllocationFlags, ULONG AllocationGranularity)
Definition: marea.c:410
#define MAKE_SSE(P, C)
Definition: mm.h:1387
#define MAX_SHARE_COUNT
Definition: mm.h:1386
#define SHARE_COUNT_FROM_SSE(E)
Definition: mm.h:1385
#define MC_USER
Definition: mm.h:114
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:283
#define IS_WRITE_SSE(E)
Definition: mm.h:1379
#define MmUnlockSectionSegment(x)
Definition: mm.h:1405
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:60
#define IS_DIRTY_SSE(E)
Definition: mm.h:1377
struct _MM_IMAGE_SECTION_OBJECT * PMM_IMAGE_SECTION_OBJECT
#define SWAPENTRY_FROM_SSE(E)
Definition: mm.h:1373
#define SEC_PHYSICALMEMORY
Definition: mm.h:112
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:1374
ULONG_PTR SWAPENTRY
Definition: mm.h:57
#define MA_GetEndingAddress(_MemoryArea)
Definition: mm.h:245
PFN_NUMBER NTAPI MmGetPfnForProcess(struct _EPROCESS *Process, PVOID Address)
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:244
#define PAGE_IS_WRITABLE
Definition: mm.h:153
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1704
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:1383
#define MI_SET_USAGE(x)
Definition: mm.h:317
#define MM_SEGMENT_INDELETE
Definition: mm.h:239
#define PAGE_FLAGS_VALID_FOR_SECTION
Definition: mm.h:134
#define MM_SEGMENT_INCREATE
Definition: mm.h:240
NTSTATUS NTAPI MmExtendSection(_In_ PVOID Section, _Inout_ PLARGE_INTEGER NewSize)
Definition: section.c:5273
FORCEINLINE PEPROCESS MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
Definition: mm.h:1711
BOOLEAN NTAPI MmIsPagePresent(struct _EPROCESS *Process, PVOID Address)
VOID NTAPI MmFreeSwapPage(SWAPENTRY Entry)
Definition: pagefile.c:291
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1765
VOID NTAPI MmSetSavedSwapEntryPage(PFN_NUMBER Page, SWAPENTRY SavedSwapEntry)
Definition: freelist.c:483
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:159
NTSTATUS NTAPI MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN MyWait, PPFN_NUMBER AllocatedPage)
Definition: balance.c:313
#define PFN_FROM_SSE(E)
Definition: mm.h:1368
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:93
SWAPENTRY NTAPI MmGetSavedSwapEntryPage(PFN_NUMBER Page)
Definition: freelist.c:499
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:241
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)
Definition: marea.c:215
#define DECREF_SSE(E)
Definition: mm.h:1389
#define MM_ROUND_DOWN(x, s)
Definition: mm.h:131
#define MM_IS_WAIT_PTE(E)
Definition: mm.h:1370
#define MM_PHYSICALMEMORY_SEGMENT
Definition: mm.h:237
#define BUMPREF_SSE(E)
Definition: mm.h:1388
#define IS_SWAP_FROM_SSE(E)
Definition: mm.h:1369
NTSTATUS NTAPI MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
Definition: balance.c:72
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1726
VOID NTAPI MmInsertRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
PMEMORY_AREA NTAPI MmLocateMemoryAreaByRegion(PMMSUPPORT AddressSpace, PVOID Address, SIZE_T Length)
Definition: marea.c:106
#define MM_DATAFILE_SEGMENT
Definition: mm.h:238
#define STATUS_MM_RESTART_OPERATION
Definition: mm.h:104
#define PAGE_IS_READABLE
Definition: mm.h:145
#define WRITE_SSE(E)
Definition: mm.h:1378
#define PAGE_IS_WRITECOPY
Definition: mm.h:165
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:268
#define STATUS_INVALID_IMAGE_WIN_64
Definition: ntstatus.h:901
#define STATUS_MAPPED_ALIGNMENT
Definition: ntstatus.h:676
#define STATUS_SECTION_PROTECTION
Definition: ntstatus.h:314
#define STATUS_INVALID_IMAGE_FORMAT
Definition: ntstatus.h:359
#define STATUS_SECTION_NOT_IMAGE
Definition: ntstatus.h:309
#define STATUS_NOT_MAPPED_VIEW
Definition: ntstatus.h:262
#define STATUS_INVALID_IMAGE_NOT_MZ
Definition: ntstatus.h:539
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_INVALID_IMAGE_PROTECT
Definition: ntstatus.h:540
#define STATUS_FILE_LOCKED_WITH_WRITERS
Definition: ntstatus.h:112
#define STATUS_INVALID_FILE_FOR_SECTION
Definition: ntstatus.h:269
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define STATUS_MAPPED_FILE_SIZE_ZERO
Definition: ntstatus.h:522
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_INVALID_PARAMETER_6
Definition: ntstatus.h:480
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:243
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:261
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:305
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:182
#define STATUS_SECTION_NOT_EXTENDED
Definition: ntstatus.h:371
#define STATUS_IMAGE_NOT_AT_BASE
Definition: ntstatus.h:117
#define L(x)
Definition: ntvdm.h:50
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 _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
PVOID pBuffer
VOID NTAPI MmBuildMdlFromPages(PMDL Mdl, PPFN_NUMBER Pages)
Definition: pagefile.c:111
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
@ Failed
Definition: arc.h:79
#define ASSERT_IRQL_LESS(x)
Definition: debug.h:253
ULONG * PPFN_NUMBER
Definition: ke.h:9
ULONG PFN_NUMBER
Definition: ke.h:9
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))
static GENERIC_MAPPING MmpSectionMapping
Definition: section.c:223
PFN_NUMBER Page
Definition: section.c:5034
NTSTATUS NTAPI MmMapViewInSystemSpace(IN PVOID SectionObject, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:4447
BOOLEAN NTAPI MmCanFileBeTruncated(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
Definition: section.c:4255
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:2327
VOID NTAPI MmpDeleteSection(PVOID ObjectBody)
Definition: section.c:2138
static LARGE_INTEGER TinyTime
Definition: section.c:63
PMM_IMAGE_SECTION_OBJECT ImageSectionObjectFromSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:120
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 MmMapViewOfSection(IN PVOID SectionObject, IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:3996
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:285
BOOLEAN NTAPI MmArePagesResident(_In_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG Length)
Definition: section.c:4775
static PMM_SECTION_SEGMENT NTAPI ExeFmtpAllocateSegments(IN ULONG NrSegments)
Definition: section.c:2590
ULONG_PTR MmSubsectionBase
Definition: section.c:196
static BOOLEAN NTAPI MmspPageAlignSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2841
NTSTATUS NTAPI MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, MEMORY_AREA *MemoryArea, PVOID Address, BOOLEAN Locked)
Definition: section.c:1532
NTSTATUS MmspWaitForFileLock(PFILE_OBJECT File)
Definition: section.c:907
PLARGE_INTEGER BOOLEAN BOOLEAN PageOut
Definition: section.c:5031
static BOOLEAN NTAPI MmspCheckSegmentBounds(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2790
#define MmSetPageEntrySectionSegment(S, O, E)
Definition: section.c:56
static ULONG SectionCharacteristicsToProtect[16]
Definition: section.c:198
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:4620
static BOOLEAN MiPurgeImageSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:4310
POBJECT_TYPE MmSectionObjectType
Definition: section.c:194
VOID NTAPI _MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line)
Definition: section.c:79
static NTSTATUS MmUnmapViewOfSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
Definition: section.c:3525
BOOLEAN NTAPI MmPurgeSegment(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length)
Definition: section.c:4828
BOOLEAN NTAPI MmUnsharePageEntrySectionSegment(PMEMORY_AREA MemoryArea, PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, BOOLEAN Dirty, BOOLEAN PageOut, ULONG_PTR *InEntry)
Definition: section.c:1089
NTSTATUS NTAPI MmQuerySectionView(PMEMORY_AREA MemoryArea, PVOID Address, PMEMORY_BASIC_INFORMATION Info, PSIZE_T ResultLength)
Definition: section.c:2099
NTSTATUS NTAPI MmProtectSectionView(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PVOID BaseAddress, SIZE_T Length, ULONG Protect, PULONG OldProtect)
Definition: section.c:2063
VOID NTAPI MmpCloseSection(IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG ProcessHandleCount, IN ULONG SystemHandleCount)
Definition: section.c:2191
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:4460
static VOID NTAPI FreeSegmentPage(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
Definition: section.c:960
NTSTATUS NTAPI MiWritePage(PMM_SECTION_SEGMENT Segment, LONGLONG SegOffset, PFN_NUMBER Page)
Definition: section.c:238
VOID NTAPI MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:917
static VOID NTAPI MmspAssertSegmentsPageAligned(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2729
static VOID NTAPI MmspSortSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2764
NTSTATUS NTAPI MmAccessFaultSectionView(PMMSUPPORT AddressSpace, MEMORY_AREA *MemoryArea, PVOID Address, BOOLEAN Locked)
Definition: section.c:1910
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4356
static NTSTATUS MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
Definition: section.c:1170
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:3768
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:2610
NTSTATUS MmCreateImageSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
Definition: section.c:3177
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:4940
static VOID NTAPI MmspAssertSegmentsSorted(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2693
NTSTATUS NTAPI MmInitSectionImplementation(VOID)
Definition: section.c:2294
static PEXEFMT_LOADER ExeFmtpLoaders[]
Definition: section.c:2579
static VOID MmAlterViewAttributes(PMMSUPPORT AddressSpace, PVOID BaseAddress, SIZE_T RegionSize, ULONG OldType, ULONG OldProtect, ULONG NewType, ULONG NewProtect)
Definition: section.c:1446
NTSTATUS NTAPI MmMakePagesDirty(_In_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG Length)
Definition: section.c:5202
VOID NTAPI MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
Definition: section.c:1064
VOID NTAPI _MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line)
Definition: section.c:70
NTSTATUS NTAPI MmMakeDataSectionResident(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length, _In_ PLARGE_INTEGER ValidDataLength)
Definition: section.c:4920
static int __cdecl MmspCompareSegments(const void *x, const void *y)
Definition: section.c:2744
KEVENT MmWaitPageEvent
Definition: section.c:66
static VOID NTAPI MmspAssertSegmentsNoOverlap(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2707
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:1192
static PMM_SECTION_SEGMENT MiGrabDataSection(PSECTION_OBJECT_POINTERS SectionObjectPointer)
Definition: section.c:90
#define DIE(ARGS_)
NTSTATUS ExeFmtpCreateImageSection(PFILE_OBJECT FileObject, PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:3024
PLARGE_INTEGER BOOLEAN ForceDirty
Definition: section.c:5029
static VOID MmFreeSectionPage(PVOID Context, MEMORY_AREA *MemoryArea, PVOID Address, PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
Definition: section.c:3441
NTSTATUS NTAPI MmCreatePhysicalMemorySection(VOID)
Definition: section.c:2203
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:3362
PLARGE_INTEGER Offset
Definition: section.c:5028
ULONGLONG AlignUp(IN ULONGLONG Value, IN ULONG Alignment)
Definition: partlist.c:79
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
#define _countof(array)
Definition: sndvol32.h:68
static void Exit(void)
Definition: sock.c:1330
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
base of all file and directory entries
Definition: entries.h:83
PMM_SECTION_SEGMENT Segment
Definition: section.c:183
PMEMORY_AREA MemoryArea
Definition: section.c:182
LARGE_INTEGER Offset
Definition: section.c:184
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
DWORD PointerToRawData
Definition: pedump.c:290
union _IMAGE_SECTION_HEADER::@1555 Misc
Definition: typedefs.h:120
struct _MEMORY_AREA::@1787 SectionData
ULONG Flags
Definition: mm.h:252
BOOLEAN DeleteInProgress
Definition: mm.h:253
ULONG Type
Definition: mm.h:251
MMVAD VadNode
Definition: mm.h:249
ULONG_PTR StartingVpn
Definition: mmtypes.h:653
union _MMADDRESS_NODE::@2604 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
PCONTROL_AREA ControlArea
Definition: mmtypes.h:736
ULONG_PTR StartingVpn
Definition: mmtypes.h:729
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:734
union _MMVAD::@2606 u
ULONG_PTR NumberGenericTableElements
Definition: mmtypes.h:668
MMADDRESS_NODE BalancedRoot
Definition: mmtypes.h:662
PMM_SECTION_SEGMENT Segments
Definition: mm.h:234
PFILE_OBJECT FileObject
Definition: mm.h:226
SECTION_IMAGE_INFORMATION ImageInformation
Definition: mm.h:231
Definition: mm.h:463
PULONG Flags
Definition: mm.h:205
LARGE_INTEGER RawLength
Definition: mm.h:200
struct _MM_SECTION_SEGMENT::@1786 Image
PLONG64 ReferenceCount
Definition: mm.h:202
FAST_MUTEX Lock
Definition: mm.h:199
PFILE_OBJECT FileObject
Definition: mm.h:197
BOOLEAN WriteCopy
Definition: mm.h:206
ULONG Protection
Definition: mm.h:204
LARGE_INTEGER Length
Definition: mm.h:201
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
union _SECTION::@2615 u
MMSECTION_FLAGS Flags
Definition: mmtypes.h:817
PSEGMENT Segment
Definition: mmtypes.h:812
ULONG InitialPageProtection
Definition: mmtypes.h:819
MMADDRESS_NODE Address
Definition: mmtypes.h:811
LARGE_INTEGER SizeOfSection
Definition: mmtypes.h:813
union _SEGMENT::@2598 u2
PSECTION_IMAGE_INFORMATION ImageInformation
Definition: mmtypes.h:426
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:114
#define TAG_MM_REGION
Definition: tag.h:111
else
Definition: tritemp.h:161
#define LL
Definition: tui.h:167
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
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
#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_INVALID_PARAMETER
Definition: udferr_usr.h:135
#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
_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:3776
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_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
_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:424
@ Executive
Definition: ketypes.h:415
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
KAPC_STATE
Definition: ketypes.h:1409
_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:3287
_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_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
_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
unsigned char UCHAR
Definition: xmlstorage.h:181
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG _In_ ULONG Protect
Definition: zwfuncs.h:221