ReactOS 0.4.16-dev-1151-g3842b59
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
1512 /* Choose protection based on what was requested */
1515 else
1517
1519 {
1521 }
1522 }
1523
1525 {
1527 Protect);
1528 }
1529 }
1530 }
1531
1533}
1534
1536NTAPI
1539 PVOID Address,
1541{
1547 ULONG_PTR Entry1;
1550 BOOLEAN HasSwapEntry;
1551 PVOID PAddress;
1553 SWAPENTRY SwapEntry;
1554
1555 ASSERT(Locked);
1556
1557 /*
1558 * There is a window between taking the page fault and locking the
1559 * address space when another thread could load the page so we check
1560 * that.
1561 */
1563 {
1564 return STATUS_SUCCESS;
1565 }
1566
1568 {
1570 }
1571
1572 /*
1573 * Check for the virtual memory area being deleted.
1574 */
1576 {
1577 return STATUS_UNSUCCESSFUL;
1578 }
1579
1580 PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
1581 Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
1582 + MemoryArea->SectionData.ViewOffset;
1583
1584 Segment = MemoryArea->SectionData.Segment;
1586 &MemoryArea->SectionData.RegionListHead,
1587 Address, NULL);
1588 ASSERT(Region != NULL);
1589
1590 /* Check for a NOACCESS mapping */
1591 if (Region->Protect & PAGE_NOACCESS)
1592 {
1594 }
1595
1596 if (Region->Protect & PAGE_GUARD)
1597 {
1598 /* Remove it */
1600 &MemoryArea->SectionData.RegionListHead,
1601 Address, PAGE_SIZE, Region->Type, Region->Protect & ~PAGE_GUARD,
1603
1604 if (!NT_SUCCESS(Status))
1605 {
1606 DPRINT1("Removing PAGE_GUARD protection failed : 0x%08x.\n", Status);
1607 }
1608
1610 }
1611
1612 HasSwapEntry = MmIsPageSwapEntry(Process, Address);
1613
1614 /* See if we should use a private page */
1615 if (HasSwapEntry)
1616 {
1617 SWAPENTRY DummyEntry;
1618
1619 MmGetPageFileMapping(Process, Address, &SwapEntry);
1620 if (SwapEntry == MM_WAIT_ENTRY)
1621 {
1626 }
1627
1629 if (Process) MI_SET_PROCESS2(Process->ImageFileName);
1630 if (!Process) MI_SET_PROCESS2("Kernel Section");
1632 if (!NT_SUCCESS(Status))
1633 {
1634 return STATUS_NO_MEMORY;
1635 }
1636
1637 /*
1638 * Must be private page we have swapped out.
1639 */
1640
1641 /*
1642 * Sanity check
1643 */
1645 ASSERT(DummyEntry == SwapEntry);
1646
1647 /* Tell everyone else we are serving the fault. */
1648 MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
1649
1651
1652 Status = MmReadFromSwapPage(SwapEntry, Page);
1653 if (!NT_SUCCESS(Status))
1654 {
1655 DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
1656 KeBugCheck(MEMORY_MANAGEMENT);
1657 }
1658
1660 MmDeletePageFileMapping(Process, PAddress, &DummyEntry);
1661 ASSERT(DummyEntry == MM_WAIT_ENTRY);
1662
1664 PAddress,
1665 Region->Protect,
1666 Page);
1667 if (!NT_SUCCESS(Status))
1668 {
1669 DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
1670 KeBugCheck(MEMORY_MANAGEMENT);
1671 return Status;
1672 }
1673
1674 /*
1675 * Store the swap entry for later use.
1676 */
1677 MmSetSavedSwapEntryPage(Page, SwapEntry);
1678
1679 /*
1680 * Add the page to the process's working set
1681 */
1683 /*
1684 * Finish the operation
1685 */
1686 DPRINT("Address 0x%p\n", Address);
1687 return STATUS_SUCCESS;
1688 }
1689
1690 /*
1691 * Lock the segment
1692 */
1694
1695 /*
1696 * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
1697 */
1698 if ((*Segment->Flags) & MM_PHYSICALMEMORY_SEGMENT)
1699 {
1701 /*
1702 * Just map the desired physical page
1703 */
1704 Page = (PFN_NUMBER)(Offset.QuadPart >> PAGE_SHIFT);
1706 PAddress,
1707 Region->Protect,
1708 Page);
1709 if (!NT_SUCCESS(Status))
1710 {
1711 DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
1712 KeBugCheck(MEMORY_MANAGEMENT);
1713 return Status;
1714 }
1715
1716 /*
1717 * Cleanup and release locks
1718 */
1719 DPRINT("Address 0x%p\n", Address);
1720 return STATUS_SUCCESS;
1721 }
1722
1723 /*
1724 * Check if this page needs to be mapped COW
1725 */
1726 if ((Segment->WriteCopy) &&
1727 (Region->Protect == PAGE_READWRITE || Region->Protect == PAGE_EXECUTE_READWRITE))
1728 {
1730 }
1731 else
1732 {
1733 Attributes = Region->Protect;
1734 }
1735
1736
1737 /*
1738 * Get the entry corresponding to the offset within the section
1739 */
1741 if (Entry == 0)
1742 {
1743 /*
1744 * If the entry is zero, then we need to load the page.
1745 */
1746 if ((Offset.QuadPart >= (LONGLONG)PAGE_ROUND_UP(Segment->RawLength.QuadPart)) && (MemoryArea->VadNode.u.VadFlags.VadType == VadImageMap))
1747 {
1748 /* We are beyond the data which is on file. Just get a new page. */
1750 if (Process) MI_SET_PROCESS2(Process->ImageFileName);
1751 if (!Process) MI_SET_PROCESS2("Kernel Section");
1753 if (!NT_SUCCESS(Status))
1754 {
1756 return STATUS_NO_MEMORY;
1757 }
1760
1762 if (!NT_SUCCESS(Status))
1763 {
1764 DPRINT1("Unable to create virtual mapping\n");
1765 KeBugCheck(MEMORY_MANAGEMENT);
1766 }
1767 ASSERT(MmIsPagePresent(Process, PAddress));
1768 if (Process)
1770
1771 DPRINT("Address 0x%p\n", Address);
1772 return STATUS_SUCCESS;
1773 }
1774
1777
1778 /* The data must be paged in. Lock the file, so that the VDL doesn't get updated behind us. */
1780
1781 PFSRTL_COMMON_FCB_HEADER FcbHeader = Segment->FileObject->FsContext;
1782
1784
1785 FsRtlReleaseFile(Segment->FileObject);
1786
1787 /* Lock address space again */
1789 if (!NT_SUCCESS(Status))
1790 {
1791 if (Status == STATUS_NO_MEMORY)
1792 {
1793 return Status;
1794 }
1795 /* Damn */
1796 DPRINT1("Failed to page data in!\n");
1797 return STATUS_IN_PAGE_ERROR;
1798 }
1799
1800 /* Everything went fine. Restart the operation */
1802 }
1803 else if (IS_SWAP_FROM_SSE(Entry))
1804 {
1805 SWAPENTRY SwapEntry;
1806
1807 SwapEntry = SWAPENTRY_FROM_SSE(Entry);
1808
1809 /* See if a page op is running on this segment. */
1810 if (SwapEntry == MM_WAIT_ENTRY)
1811 {
1817 }
1818
1820 if (!NT_SUCCESS(Status))
1821 {
1823 return STATUS_NO_MEMORY;
1824 }
1825
1826 /*
1827 * Release all our locks and read in the page from disk
1828 */
1831
1833
1834 Status = MmReadFromSwapPage(SwapEntry, Page);
1835 if (!NT_SUCCESS(Status))
1836 {
1837 KeBugCheck(MEMORY_MANAGEMENT);
1838 }
1839
1840 /*
1841 * Relock the address space and segment
1842 */
1845
1846 /*
1847 * Check the entry. No one should change the status of a page
1848 * that has a pending page-in.
1849 */
1851 if (Entry1 != MAKE_SWAP_SSE(MM_WAIT_ENTRY))
1852 {
1853 DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
1854 KeBugCheck(MEMORY_MANAGEMENT);
1855 }
1856
1857 /*
1858 * Save the swap entry.
1859 */
1860 MmSetSavedSwapEntryPage(Page, SwapEntry);
1861
1862 /* Map the page into the process address space */
1864 PAddress,
1865 Attributes,
1866 Page);
1867 if (!NT_SUCCESS(Status))
1868 {
1869 DPRINT1("Unable to create virtual mapping\n");
1870 KeBugCheck(MEMORY_MANAGEMENT);
1871 }
1872 if (Process)
1874
1875 /*
1876 * Mark the offset within the section as having valid, in-memory
1877 * data
1878 */
1879 Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
1882
1883 DPRINT("Address 0x%p\n", Address);
1884 return STATUS_SUCCESS;
1885 }
1886 else
1887 {
1888 /* We already have a page on this section offset. Map it into the process address space. */
1890
1892 PAddress,
1893 Attributes,
1894 Page);
1895 if (!NT_SUCCESS(Status))
1896 {
1897 DPRINT1("Unable to create virtual mapping\n");
1898 KeBugCheck(MEMORY_MANAGEMENT);
1899 }
1900
1901 if (Process)
1903
1904 /* Take a reference on it */
1907
1908 DPRINT("Address 0x%p\n", Address);
1909 return STATUS_SUCCESS;
1910 }
1911}
1912
1914NTAPI
1917 PVOID Address,
1919{
1921 PFN_NUMBER OldPage;
1922 PFN_NUMBER NewPage;
1923 PFN_NUMBER UnmappedPage;
1924 PVOID PAddress;
1929 BOOLEAN Cow = FALSE;
1931 BOOLEAN Unmapped;
1933
1934 DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
1935
1936 /* Get the region for this address */
1938 &MemoryArea->SectionData.RegionListHead,
1939 Address, NULL);
1940 ASSERT(Region != NULL);
1941 if (!(Region->Protect & PAGE_IS_WRITABLE))
1943
1944 /* Make sure we have a page mapping for this address. */
1946 {
1948 if (!NT_SUCCESS(Status))
1949 {
1950 /* This is invalid access ! */
1951 return Status;
1952 }
1953 }
1954
1955 /*
1956 * Check if the page has already been set readwrite
1957 */
1959 {
1960 DPRINT("Address 0x%p\n", Address);
1961 return STATUS_SUCCESS;
1962 }
1963
1964 /* Check if we are doing Copy-On-Write */
1965 Segment = MemoryArea->SectionData.Segment;
1966 Cow = Segment->WriteCopy || (Region->Protect & PAGE_IS_WRITECOPY);
1967
1968 if (!Cow)
1969 {
1970 /* Simply update page protection and we're done */
1972 return STATUS_SUCCESS;
1973 }
1974
1975 /* Calculate the new protection & check if we should update the region */
1976 NewProtect = Region->Protect;
1978 {
1979 NewProtect &= ~PAGE_IS_WRITECOPY;
1980 if (Region->Protect & PAGE_IS_EXECUTABLE)
1982 else
1985 &MemoryArea->SectionData.RegionListHead,
1988 }
1989
1990 /*
1991 * Find the offset of the page
1992 */
1993 PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
1994 Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
1995 + MemoryArea->SectionData.ViewOffset;
1996
1997 /* Get the page mapping this section offset. */
2000
2001 /* Get the current page mapping for the process */
2002 ASSERT(MmIsPagePresent(Process, PAddress));
2003 OldPage = MmGetPfnForProcess(Process, PAddress);
2004 ASSERT(OldPage != 0);
2005
2006 if (IS_SWAP_FROM_SSE(Entry) ||
2007 PFN_FROM_SSE(Entry) != OldPage)
2008 {
2010 /* This is a private page. We must only change the page protection. */
2012 return STATUS_SUCCESS;
2013 }
2014
2015 /*
2016 * Allocate a page
2017 */
2019 if (!NT_SUCCESS(Status))
2020 {
2022 return STATUS_NO_MEMORY;
2023 }
2024
2025 /*
2026 * Copy the old page
2027 */
2028 NT_VERIFY(NT_SUCCESS(MiCopyFromUserPage(NewPage, PAddress)));
2029
2030 /*
2031 * Unshare the old page.
2032 */
2033 DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
2034 Unmapped = MmDeleteVirtualMapping(Process, PAddress, NULL, &UnmappedPage);
2035 if (!Unmapped || (UnmappedPage != OldPage))
2036 {
2037 /* Uh , we had a page just before, but suddenly it changes. Someone corrupted us. */
2038 KeBugCheckEx(MEMORY_MANAGEMENT,
2040 (ULONG_PTR)PAddress,
2041 (ULONG_PTR)__FILE__,
2042 __LINE__);
2043 }
2044
2045 if (Process)
2046 MmDeleteRmap(OldPage, Process, PAddress);
2049
2050 /*
2051 * Set the PTE to point to the new page
2052 */
2053 if (!NT_SUCCESS(MmCreateVirtualMapping(Process, PAddress, NewProtect, NewPage)))
2054 {
2055 DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
2056 KeBugCheck(MEMORY_MANAGEMENT);
2057 }
2058
2059 if (Process)
2060 MmInsertRmap(NewPage, Process, PAddress);
2061
2062 DPRINT("Address 0x%p\n", Address);
2063 return STATUS_SUCCESS;
2064}
2065
2067NTAPI
2071 SIZE_T Length,
2072 ULONG Protect,
2073 PULONG OldProtect)
2074{
2077 ULONG_PTR MaxLength;
2078
2080
2082 {
2083 return STATUS_UNSUCCESSFUL;
2084 }
2085
2087 if (Length > MaxLength)
2088 Length = (ULONG)MaxLength;
2089
2091 &MemoryArea->SectionData.RegionListHead,
2092 BaseAddress, NULL);
2093 ASSERT(Region != NULL);
2094
2095 if ((MemoryArea->Flags & SEC_NO_CHANGE) &&
2096 Region->Protect != Protect)
2097 {
2099 }
2100
2101 if (OldProtect != NULL)
2102 *OldProtect = Region->Protect;
2104 &MemoryArea->SectionData.RegionListHead,
2107
2108 return Status;
2109}
2110
2113 PVOID Address,
2116{
2118 PVOID RegionBaseAddress;
2120
2122 &MemoryArea->SectionData.RegionListHead,
2123 Address, &RegionBaseAddress);
2124 if (Region == NULL)
2125 {
2126 return STATUS_UNSUCCESSFUL;
2127 }
2128
2130 {
2131 Segment = MemoryArea->SectionData.Segment;
2132 Info->AllocationBase = (PUCHAR)MA_GetStartingAddress(MemoryArea) - Segment->Image.VirtualAddress;
2133 Info->Type = MEM_IMAGE;
2134 }
2135 else
2136 {
2137 Info->AllocationBase = (PVOID)MA_GetStartingAddress(MemoryArea);
2138 Info->Type = MEM_MAPPED;
2139 }
2140 Info->BaseAddress = RegionBaseAddress;
2142 Info->RegionSize = Region->Length;
2143 Info->State = MEM_COMMIT;
2144 Info->Protect = Region->Protect;
2145
2147 return STATUS_SUCCESS;
2148}
2149
2150VOID NTAPI
2152{
2153 PSECTION Section = ObjectBody;
2154
2155 /* Check if it's an ARM3, or ReactOS section */
2156 if (!MiIsRosSectionObject(Section))
2157 {
2158 MiDeleteARM3Section(ObjectBody);
2159 return;
2160 }
2161
2162 DPRINT("MmpDeleteSection(ObjectBody %p)\n", ObjectBody);
2163 if (Section->u.Flags.Image)
2164 {
2165 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)Section->Segment;
2166
2167 /*
2168 * NOTE: Section->ImageSection can be NULL for short time
2169 * during the section creating. If we fail for some reason
2170 * until the image section is properly initialized we shouldn't
2171 * process further here.
2172 */
2173 if (Section->Segment == NULL)
2174 return;
2175
2176 KIRQL OldIrql = MiAcquirePfnLock();
2177 ImageSectionObject->SectionCount--;
2178
2179 /* We just dereference the first segment */
2180 ASSERT(ImageSectionObject->RefCount > 0);
2181 /* MmDereferenceSegmentWithLock releases PFN lock */
2182 MmDereferenceSegmentWithLock(ImageSectionObject->Segments, OldIrql);
2183 }
2184 else
2185 {
2187
2188 /*
2189 * NOTE: Section->Segment can be NULL for short time
2190 * during the section creating.
2191 */
2192 if (Segment == NULL)
2193 return;
2194
2195 KIRQL OldIrql = MiAcquirePfnLock();
2196 Segment->SectionCount--;
2197
2198 /* MmDereferenceSegmentWithLock releases PFN lock */
2199 MmDereferenceSegmentWithLock(Segment, OldIrql);
2200 }
2201}
2202
2203VOID NTAPI
2205 IN PVOID Object,
2208 IN ULONG SystemHandleCount)
2209{
2210 DPRINT("MmpCloseSection(OB %p, HC %lu)\n", Object, ProcessHandleCount);
2211}
2212
2213CODE_SEG("INIT")
2215NTAPI
2217{
2218 PSECTION PhysSection;
2221 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
2222 LARGE_INTEGER SectionSize;
2223 HANDLE Handle;
2225
2226 /*
2227 * Create the section mapping physical memory
2228 */
2231 &Name,
2233 NULL,
2234 NULL);
2235 /*
2236 * Create the Object
2237 */
2240 &Obj,
2242 NULL,
2243 sizeof(*PhysSection),
2244 0,
2245 0,
2246 (PVOID*)&PhysSection);
2247 if (!NT_SUCCESS(Status))
2248 {
2249 DPRINT1("MmCreatePhysicalMemorySection: failed to create object (0x%lx)\n", Status);
2250 return Status;
2251 }
2252
2253 /*
2254 * Initialize it
2255 */
2256 RtlZeroMemory(PhysSection, sizeof(*PhysSection));
2257
2258 /* Mark this as a "ROS Section" */
2259 PhysSection->u.Flags.filler = 1;
2261 PhysSection->u.Flags.PhysicalMemory = 1;
2262 PhysSection->SizeOfSection = SectionSize;
2265 if (Segment == NULL)
2266 {
2267 ObDereferenceObject(PhysSection);
2268 return STATUS_NO_MEMORY;
2269 }
2271 PhysSection->Segment = (PSEGMENT)Segment;
2272 Segment->RefCount = 1;
2273
2274 Segment->ReferenceCount = &Segment->RefCount;
2275 Segment->Flags = &Segment->SegFlags;
2276
2278 Segment->Image.FileOffset = 0;
2279 Segment->Protection = PAGE_EXECUTE_READWRITE;
2280 Segment->RawLength = SectionSize;
2281 Segment->Length = SectionSize;
2283 Segment->WriteCopy = FALSE;
2284 Segment->Image.VirtualAddress = 0;
2285 Segment->Image.Characteristics = 0;
2287
2288 Status = ObInsertObject(PhysSection,
2289 NULL,
2291 0,
2292 NULL,
2293 &Handle);
2294 if (!NT_SUCCESS(Status))
2295 {
2296 ObDereferenceObject(PhysSection);
2297 return Status;
2298 }
2300
2301 return STATUS_SUCCESS;
2302}
2303
2304CODE_SEG("INIT")
2306NTAPI
2308{
2309 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
2311
2312 DPRINT("Creating Section Object Type\n");
2313
2314 /* Initialize the section based root */
2317
2318 /* Initialize the Section object type */
2319 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
2320 RtlInitUnicodeString(&Name, L"Section");
2321 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
2322 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(SECTION);
2323 ObjectTypeInitializer.PoolType = PagedPool;
2324 ObjectTypeInitializer.UseDefaultObject = TRUE;
2325 ObjectTypeInitializer.GenericMapping = MmpSectionMapping;
2326 ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
2327 ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
2328 ObjectTypeInitializer.ValidAccessMask = SECTION_ALL_ACCESS;
2329 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
2330 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &MmSectionObjectType);
2331
2333
2334 return STATUS_SUCCESS;
2335}
2336
2337static
2339NTAPI
2343 PLARGE_INTEGER UMaximumSize,
2347 BOOLEAN GotFileHandle)
2348/*
2349 * Create a section backed by a data file
2350 */
2351{
2352 PSECTION Section;
2356 KIRQL OldIrql;
2357
2358 /*
2359 * Create the section
2360 */
2365 NULL,
2366 sizeof(*Section),
2367 0,
2368 0,
2369 (PVOID*)&Section);
2370 if (!NT_SUCCESS(Status))
2371 {
2372 return Status;
2373 }
2374 /*
2375 * Initialize it
2376 */
2377 RtlZeroMemory(Section, sizeof(*Section));
2378
2379 /* Mark this as a "ROS" section */
2380 Section->u.Flags.filler = 1;
2382 Section->u.Flags.File = 1;
2383
2385 Section->u.Flags.NoChange = 1;
2387 Section->u.Flags.Reserve = 1;
2388
2389 if (!GotFileHandle)
2390 {
2391 ASSERT(UMaximumSize != NULL);
2392 // ASSERT(UMaximumSize->QuadPart != 0);
2393 MaximumSize = *UMaximumSize;
2394 }
2395 else
2396 {
2399 if (!NT_SUCCESS(Status))
2400 {
2401 ObDereferenceObject(Section);
2402 return Status;
2403 }
2404
2405 /*
2406 * FIXME: Revise this once a locking order for file size changes is
2407 * decided
2408 */
2409 if ((UMaximumSize != NULL) && (UMaximumSize->QuadPart != 0))
2410 {
2411 MaximumSize = *UMaximumSize;
2412 }
2413 else
2414 {
2416 /* Mapping zero-sized files isn't allowed. */
2417 if (MaximumSize.QuadPart == 0)
2418 {
2419 ObDereferenceObject(Section);
2421 }
2422 }
2423
2424 if (MaximumSize.QuadPart > FileSize.QuadPart)
2425 {
2428 sizeof(LARGE_INTEGER),
2429 &MaximumSize);
2430 if (!NT_SUCCESS(Status))
2431 {
2432 ObDereferenceObject(Section);
2434 }
2435 }
2436 }
2437
2438 if (FileObject->SectionObjectPointer == NULL)
2439 {
2440 ObDereferenceObject(Section);
2442 }
2443
2444 /*
2445 * Lock the file
2446 */
2448 if (Status != STATUS_SUCCESS)
2449 {
2450 ObDereferenceObject(Section);
2451 return Status;
2452 }
2453
2454 /* Lock the PFN lock while messing with Section Object pointers */
2455grab_segment:
2456 OldIrql = MiAcquirePfnLock();
2457 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2458
2459 while (Segment && (Segment->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
2460 {
2461 MiReleasePfnLock(OldIrql);
2463 OldIrql = MiAcquirePfnLock();
2464 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2465 }
2466
2467 /*
2468 * If this file hasn't been mapped as a data file before then allocate a
2469 * section segment to describe the data file mapping
2470 */
2471 if (Segment == NULL)
2472 {
2473 /* Release the lock. ExAllocatePoolWithTag might acquire it */
2474 MiReleasePfnLock(OldIrql);
2475
2478 if (Segment == NULL)
2479 {
2480 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2481 ObDereferenceObject(Section);
2482 return STATUS_NO_MEMORY;
2483 }
2484
2485 /* We are creating it */
2486 RtlZeroMemory(Segment, sizeof(*Segment));
2488 Segment->RefCount = 1;
2489
2490 /* Acquire lock again */
2491 OldIrql = MiAcquirePfnLock();
2492
2493 if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
2494 {
2495 /* Well that's bad luck. Restart it all over */
2496 MiReleasePfnLock(OldIrql);
2498 goto grab_segment;
2499 }
2500
2501 FileObject->SectionObjectPointer->DataSectionObject = Segment;
2502
2503 /* We're safe to release the lock now */
2504 MiReleasePfnLock(OldIrql);
2505
2506 Section->Segment = (PSEGMENT)Segment;
2507
2508 /* Self-referencing segment */
2509 Segment->Flags = &Segment->SegFlags;
2510 Segment->ReferenceCount = &Segment->RefCount;
2511
2512 Segment->SectionCount = 1;
2513
2515 Segment->FileObject = FileObject;
2517
2518 Segment->Image.FileOffset = 0;
2519 Segment->Protection = SectionPageProtection;
2520
2521 Segment->Image.Characteristics = 0;
2524 {
2525 Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0;
2526 }
2527 else
2528 {
2529 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2530 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2531 }
2532 Segment->Image.VirtualAddress = 0;
2534
2535 /* We're good to use it now */
2536 OldIrql = MiAcquirePfnLock();
2537 Segment->SegFlags &= ~MM_SEGMENT_INCREATE;
2538 MiReleasePfnLock(OldIrql);
2539 }
2540 else
2541 {
2542 Section->Segment = (PSEGMENT)Segment;
2543 InterlockedIncrement64(&Segment->RefCount);
2544 InterlockedIncrementUL(&Segment->SectionCount);
2545
2546 MiReleasePfnLock(OldIrql);
2547
2549
2550 if (MaximumSize.QuadPart > Segment->RawLength.QuadPart &&
2552 {
2553 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2554 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2555 }
2556
2558 }
2559 Section->SizeOfSection = MaximumSize;
2560
2561 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2562 *SectionObject = Section;
2563 return STATUS_SUCCESS;
2564}
2565
2566/*
2567 TODO: not that great (declaring loaders statically, having to declare all of
2568 them, having to keep them extern, etc.), will fix in the future
2569*/
2571(
2572 IN CONST VOID * FileHeader,
2573 IN SIZE_T FileHeaderSize,
2574 IN PVOID File,
2575 OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2577 IN PEXEFMT_CB_READ_FILE ReadFileCb,
2578 IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
2579);
2580
2582(
2583 IN CONST VOID * FileHeader,
2584 IN SIZE_T FileHeaderSize,
2585 IN PVOID File,
2586 OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2588 IN PEXEFMT_CB_READ_FILE ReadFileCb,
2589 IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
2590);
2591
2593{
2595#ifdef __ELF
2597#endif
2598};
2599
2600static
2602NTAPI
2604{
2605 SIZE_T SizeOfSegments;
2606 PMM_SECTION_SEGMENT Segments;
2607
2608 /* TODO: check for integer overflow */
2609 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * NrSegments;
2610
2612 SizeOfSegments,
2614
2615 if(Segments)
2616 RtlZeroMemory(Segments, SizeOfSegments);
2617
2618 return Segments;
2619}
2620static
2622NTAPI
2625 IN ULONG Length,
2626 OUT PVOID * Data,
2627 OUT PVOID * AllocBase,
2628 OUT PULONG ReadSize)
2629{
2632 ULONG AdjustOffset;
2633 ULONG OffsetAdjustment;
2635 ULONG UsedSize;
2636 PVOID Buffer;
2639
2641
2642 if(Length == 0)
2643 {
2644 KeBugCheck(MEMORY_MANAGEMENT);
2645 }
2646
2647 FileOffset = *Offset;
2648
2649 /* Negative/special offset: it cannot be used in this context */
2650 if(FileOffset.u.HighPart < 0)
2651 {
2652 KeBugCheck(MEMORY_MANAGEMENT);
2653 }
2654
2655 AdjustOffset = PAGE_ROUND_DOWN(FileOffset.u.LowPart);
2656 OffsetAdjustment = FileOffset.u.LowPart - AdjustOffset;
2657 FileOffset.u.LowPart = AdjustOffset;
2658
2659 BufferSize = Length + OffsetAdjustment;
2661
2662 /*
2663 * It's ok to use paged pool, because this is a temporary buffer only used in
2664 * the loading of executables. The assumption is that MmCreateSection is
2665 * always called at low IRQLs and that these buffers don't survive a brief
2666 * initialization phase
2667 */
2669 if (!Buffer)
2670 {
2672 }
2673
2675
2676 UsedSize = (ULONG)Iosb.Information;
2677
2678 if(NT_SUCCESS(Status) && UsedSize < OffsetAdjustment)
2679 {
2682 }
2683
2684 if(NT_SUCCESS(Status))
2685 {
2686 *Data = (PVOID)((ULONG_PTR)Buffer + OffsetAdjustment);
2687 *AllocBase = Buffer;
2688 *ReadSize = UsedSize - OffsetAdjustment;
2689 }
2690 else
2691 {
2692 ExFreePoolWithTag(Buffer, 'rXmM');
2693 }
2694
2695 return Status;
2696}
2697
2698#ifdef NASSERT
2699# define MmspAssertSegmentsSorted(OBJ_) ((void)0)
2700# define MmspAssertSegmentsNoOverlap(OBJ_) ((void)0)
2701# define MmspAssertSegmentsPageAligned(OBJ_) ((void)0)
2702#else
2703static
2704VOID
2705NTAPI
2707{
2708 ULONG i;
2709
2710 for( i = 1; i < ImageSectionObject->NrSegments; ++ i )
2711 {
2712 ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
2713 ImageSectionObject->Segments[i - 1].Image.VirtualAddress);
2714 }
2715}
2716
2717static
2718VOID
2719NTAPI
2721{
2722 ULONG i;
2723
2724 MmspAssertSegmentsSorted(ImageSectionObject);
2725
2726 for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2727 {
2728 ASSERT(ImageSectionObject->Segments[i].Length.QuadPart > 0);
2729
2730 if(i > 0)
2731 {
2732 ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
2733 (ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
2734 ImageSectionObject->Segments[i - 1].Length.QuadPart));
2735 }
2736 }
2737}
2738
2739static
2740VOID
2741NTAPI
2743{
2744 ULONG i;
2745
2746 for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2747 {
2748 ASSERT((ImageSectionObject->Segments[i].Image.VirtualAddress % PAGE_SIZE) == 0);
2749 ASSERT((ImageSectionObject->Segments[i].Length.QuadPart % PAGE_SIZE) == 0);
2750 }
2751}
2752#endif
2753
2754static
2755int
2756__cdecl
2758 const void * y)
2759{
2760 const MM_SECTION_SEGMENT *Segment1 = (const MM_SECTION_SEGMENT *)x;
2761 const MM_SECTION_SEGMENT *Segment2 = (const MM_SECTION_SEGMENT *)y;
2762
2763 if (Segment1->Image.VirtualAddress > Segment2->Image.VirtualAddress)
2764 return 1;
2765 else if (Segment1->Image.VirtualAddress < Segment2->Image.VirtualAddress)
2766 return -1;
2767 else
2768 return 0;
2769}
2770
2771/*
2772 * Ensures an image section's segments are sorted in memory
2773 */
2774static
2775VOID
2776NTAPI
2778 IN ULONG Flags)
2779{
2781 {
2782 MmspAssertSegmentsSorted(ImageSectionObject);
2783 }
2784 else
2785 {
2786 qsort(ImageSectionObject->Segments,
2787 ImageSectionObject->NrSegments,
2788 sizeof(ImageSectionObject->Segments[0]),
2790 }
2791}
2792
2793
2794/*
2795 * Ensures an image section's segments don't overlap in memory and don't have
2796 * gaps and don't have a null size. We let them map to overlapping file regions,
2797 * though - that's not necessarily an error
2798 */
2799static
2800BOOLEAN
2801NTAPI
2803(
2804 IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2805 IN ULONG Flags
2806)
2807{
2808 ULONG i;
2809
2811 {
2812 MmspAssertSegmentsNoOverlap(ImageSectionObject);
2813 return TRUE;
2814 }
2815
2816 ASSERT(ImageSectionObject->NrSegments >= 1);
2817
2818 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2819 {
2820 if(ImageSectionObject->Segments[i].Length.QuadPart == 0)
2821 {
2822 return FALSE;
2823 }
2824
2825 if(i > 0)
2826 {
2827 /*
2828 * TODO: relax the limitation on gaps. For example, gaps smaller than a
2829 * page could be OK (Windows seems to be OK with them), and larger gaps
2830 * could lead to image sections spanning several discontiguous regions
2831 * (NtMapViewOfSection could then refuse to map them, and they could
2832 * e.g. only be allowed as parameters to NtCreateProcess, like on UNIX)
2833 */
2834 if ((ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
2835 ImageSectionObject->Segments[i - 1].Length.QuadPart) !=
2836 ImageSectionObject->Segments[i].Image.VirtualAddress)
2837 {
2838 return FALSE;
2839 }
2840 }
2841 }
2842
2843 return TRUE;
2844}
2845
2846/*
2847 * Merges and pads an image section's segments until they all are page-aligned
2848 * and have a size that is a multiple of the page size
2849 */
2850static
2851BOOLEAN
2852NTAPI
2854(
2855 IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2856 IN ULONG Flags
2857)
2858{
2859 ULONG i;
2860 ULONG LastSegment;
2861 PMM_SECTION_SEGMENT EffectiveSegment;
2862
2864 {
2865 MmspAssertSegmentsPageAligned(ImageSectionObject);
2866 return TRUE;
2867 }
2868
2869 LastSegment = 0;
2870 EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
2871
2872 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2873 {
2874 /*
2875 * The first segment requires special handling
2876 */
2877 if (i == 0)
2878 {
2880 ULONG_PTR VirtualOffset;
2881
2882 VirtualAddress = EffectiveSegment->Image.VirtualAddress;
2883
2884 /* Round down the virtual address to the nearest page */
2885 EffectiveSegment->Image.VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
2886
2887 /* Round up the virtual size to the nearest page */
2888 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length.QuadPart) -
2889 EffectiveSegment->Image.VirtualAddress;
2890
2891 /* Adjust the raw address and size */
2892 VirtualOffset = VirtualAddress - EffectiveSegment->Image.VirtualAddress;
2893
2894 if (EffectiveSegment->Image.FileOffset < VirtualOffset)
2895 {
2896 return FALSE;
2897 }
2898
2899 /*
2900 * Garbage in, garbage out: unaligned base addresses make the file
2901 * offset point in curious and odd places, but that's what we were
2902 * asked for
2903 */
2904 EffectiveSegment->Image.FileOffset -= VirtualOffset;
2905 EffectiveSegment->RawLength.QuadPart += VirtualOffset;
2906 }
2907 else
2908 {
2909 PMM_SECTION_SEGMENT Segment = &ImageSectionObject->Segments[i];
2910 ULONG_PTR EndOfEffectiveSegment;
2911
2912 EndOfEffectiveSegment = (ULONG_PTR)(EffectiveSegment->Image.VirtualAddress + EffectiveSegment->Length.QuadPart);
2913 ASSERT((EndOfEffectiveSegment % PAGE_SIZE) == 0);
2914
2915 /*
2916 * The current segment begins exactly where the current effective
2917 * segment ended, therefore beginning a new effective segment
2918 */
2919 if (EndOfEffectiveSegment == Segment->Image.VirtualAddress)
2920 {
2921 LastSegment ++;
2922 ASSERT(LastSegment <= i);
2923 ASSERT(LastSegment < ImageSectionObject->NrSegments);
2924
2925 EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
2926
2927 if (LastSegment != i)
2928 {
2929 /*
2930 * Copy the current segment. If necessary, the effective segment
2931 * will be expanded later
2932 */
2933 *EffectiveSegment = *Segment;
2934 }
2935
2936 /*
2937 * Page-align the virtual size. We know for sure the virtual address
2938 * already is
2939 */
2940 ASSERT((EffectiveSegment->Image.VirtualAddress % PAGE_SIZE) == 0);
2941 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(EffectiveSegment->Length.QuadPart);
2942 }
2943 /*
2944 * The current segment is still part of the current effective segment:
2945 * extend the effective segment to reflect this
2946 */
2947 else if (EndOfEffectiveSegment > Segment->Image.VirtualAddress)
2948 {
2949 static const ULONG FlagsToProtection[16] =
2950 {
2967 };
2968
2969 unsigned ProtectionFlags;
2970
2971 /*
2972 * Extend the file size
2973 */
2974
2975 /* Unaligned segments must be contiguous within the file */
2976 if (Segment->Image.FileOffset != (EffectiveSegment->Image.FileOffset +
2977 EffectiveSegment->RawLength.QuadPart))
2978 {
2979 return FALSE;
2980 }
2981
2982 EffectiveSegment->RawLength.QuadPart += Segment->RawLength.QuadPart;
2983
2984 /*
2985 * Extend the virtual size
2986 */
2987 ASSERT(PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) >= EndOfEffectiveSegment);
2988
2989 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) -
2990 EffectiveSegment->Image.VirtualAddress;
2991
2992 /*
2993 * Merge the protection
2994 */
2995 EffectiveSegment->Protection |= Segment->Protection;
2996
2997 /* Clean up redundance */
2998 ProtectionFlags = 0;
2999
3000 if(EffectiveSegment->Protection & PAGE_IS_READABLE)
3001 ProtectionFlags |= 1 << 0;
3002
3003 if(EffectiveSegment->Protection & PAGE_IS_WRITABLE)
3004 ProtectionFlags |= 1 << 1;
3005
3006 if(EffectiveSegment->Protection & PAGE_IS_EXECUTABLE)
3007 ProtectionFlags |= 1 << 2;
3008
3009 if(EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
3010 ProtectionFlags |= 1 << 3;
3011
3012 ASSERT(ProtectionFlags < 16);
3013 EffectiveSegment->Protection = FlagsToProtection[ProtectionFlags];
3014
3015 /* If a segment was required to be shared and cannot, fail */
3016 if(!(Segment->Protection & PAGE_IS_WRITECOPY) &&
3017 EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
3018 {
3019 return FALSE;
3020 }
3021 }
3022 /*
3023 * We assume no holes between segments at this point
3024 */
3025 else
3026 {
3027 KeBugCheck(MEMORY_MANAGEMENT);
3028 }
3029 }
3030 }
3031 ImageSectionObject->NrSegments = LastSegment + 1;
3032
3033 return TRUE;
3034}
3035
3038 PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
3039{
3041 PVOID FileHeader;
3042 PVOID FileHeaderBuffer;
3043 ULONG FileHeaderSize;
3044 ULONG Flags;
3045 ULONG OldNrSegments;
3047 ULONG i;
3048
3049 /*
3050 * Read the beginning of the file (2 pages). Should be enough to contain
3051 * all (or most) of the headers
3052 */
3053 Offset.QuadPart = 0;
3054
3056 &Offset,
3057 PAGE_SIZE * 2,
3058 &FileHeader,
3059 &FileHeaderBuffer,
3060 &FileHeaderSize);
3061
3062 if (!NT_SUCCESS(Status))
3063 return Status;
3064
3065 if (FileHeaderSize == 0)
3066 {
3067 ExFreePool(FileHeaderBuffer);
3068 return STATUS_UNSUCCESSFUL;
3069 }
3070
3071 /*
3072 * Look for a loader that can handle this executable
3073 */
3074 for (i = 0; i < RTL_NUMBER_OF(ExeFmtpLoaders); ++ i)
3075 {
3076 Flags = 0;
3077
3078 Status = ExeFmtpLoaders[i](FileHeader,
3079 FileHeaderSize,
3080 FileObject,
3081 ImageSectionObject,
3082 &Flags,
3085
3086 if (!NT_SUCCESS(Status))
3087 {
3088 if (ImageSectionObject->Segments)
3089 {
3090 ExFreePool(ImageSectionObject->Segments);
3091 ImageSectionObject->Segments = NULL;
3092 }
3093 }
3094
3096 break;
3097 }
3098
3099 ExFreePoolWithTag(FileHeaderBuffer, 'rXmM');
3100
3101 /*
3102 * No loader handled the format
3103 */
3105 {
3108 }
3109
3110 if (!NT_SUCCESS(Status))
3111 return Status;
3112
3113 ASSERT(ImageSectionObject->Segments != NULL);
3114 ASSERT(ImageSectionObject->RefCount > 0);
3115
3116 /*
3117 * Some defaults
3118 */
3119 /* FIXME? are these values platform-dependent? */
3120 if (ImageSectionObject->ImageInformation.MaximumStackSize == 0)
3121 ImageSectionObject->ImageInformation.MaximumStackSize = 0x40000;
3122
3123 if(ImageSectionObject->ImageInformation.CommittedStackSize == 0)
3124 ImageSectionObject->ImageInformation.CommittedStackSize = 0x1000;
3125
3126 if(ImageSectionObject->BasedAddress == NULL)
3127 {
3128 if(ImageSectionObject->ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL)
3129 ImageSectionObject->BasedAddress = (PVOID)0x10000000;
3130 else
3131 ImageSectionObject->BasedAddress = (PVOID)0x00400000;
3132 }
3133
3134 /*
3135 * And now the fun part: fixing the segments
3136 */
3137
3138 /* Sort them by virtual address */
3139 MmspSortSegments(ImageSectionObject, Flags);
3140
3141 /* Ensure they don't overlap in memory */
3142 if (!MmspCheckSegmentBounds(ImageSectionObject, Flags))
3144
3145 /* Ensure they are aligned */
3146 OldNrSegments = ImageSectionObject->NrSegments;
3147
3148 if (!MmspPageAlignSegments(ImageSectionObject, Flags))
3150
3151 /* Trim them if the alignment phase merged some of them */
3152 if (ImageSectionObject->NrSegments < OldNrSegments)
3153 {
3154 PMM_SECTION_SEGMENT Segments;
3155 SIZE_T SizeOfSegments;
3156
3157 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
3158
3160 SizeOfSegments,
3162
3163 if (Segments == NULL)
3165
3166 RtlCopyMemory(Segments, ImageSectionObject->Segments, SizeOfSegments);
3167 ExFreePool(ImageSectionObject->Segments);
3168 ImageSectionObject->Segments = Segments;
3169 }
3170
3171 /* And finish their initialization */
3172 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
3173 {
3174 ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock);
3175 ImageSectionObject->Segments[i].ReferenceCount = &ImageSectionObject->RefCount;
3176 ImageSectionObject->Segments[i].Flags = &ImageSectionObject->SegFlags;
3177 MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]);
3178 ImageSectionObject->Segments[i].FileObject = FileObject;
3179 }
3180
3181 ASSERT(ImageSectionObject->RefCount > 0);
3182
3183 ImageSectionObject->FileObject = FileObject;
3184
3186 return Status;
3187}
3188
3193 PLARGE_INTEGER UMaximumSize,
3197{
3198 PSECTION Section;
3200 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3201 KIRQL OldIrql;
3202
3203
3204 if (FileObject == NULL)
3206
3207 if (FileObject->SectionObjectPointer == NULL)
3208 {
3209 DPRINT1("Denying section creation due to missing cache initialization\n");
3211 }
3212
3213 /*
3214 * Create the section
3215 */
3220 NULL,
3221 sizeof(*Section),
3222 0,
3223 0,
3224 (PVOID*)(PVOID)&Section);
3225 if (!NT_SUCCESS(Status))
3226 {
3227 return Status;
3228 }
3229
3230 /*
3231 * Initialize it
3232 */
3233 RtlZeroMemory(Section, sizeof(*Section));
3234
3235 /* Mark this as a "ROS" Section */
3236 Section->u.Flags.filler = 1;
3237
3239 Section->u.Flags.File = 1;
3240 Section->u.Flags.Image = 1;
3242 Section->u.Flags.NoChange = 1;
3243
3244grab_image_section_object:
3245 OldIrql = MiAcquirePfnLock();
3246
3247 /* Wait for it to be properly created or deleted */
3248 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3249 while(ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
3250 {
3251 MiReleasePfnLock(OldIrql);
3252
3254
3255 OldIrql = MiAcquirePfnLock();
3256 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3257 }
3258
3259 if (ImageSectionObject == NULL)
3260 {
3261 NTSTATUS StatusExeFmt;
3262
3263 /* Release the lock because ExAllocatePoolWithTag could need to acquire it */
3264 MiReleasePfnLock(OldIrql);
3265
3267 if (ImageSectionObject == NULL)
3268 {
3269 ObDereferenceObject(Section);
3270 return STATUS_NO_MEMORY;
3271 }
3272
3273 ImageSectionObject->SegFlags = MM_SEGMENT_INCREATE;
3274 ImageSectionObject->RefCount = 1;
3275 ImageSectionObject->SectionCount = 1;
3276
3277 OldIrql = MiAcquirePfnLock();
3278 if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
3279 {
3280 MiReleasePfnLock(OldIrql);
3281 /* Bad luck. Start over */
3282 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3283 goto grab_image_section_object;
3284 }
3285
3286 FileObject->SectionObjectPointer->ImageSectionObject = ImageSectionObject;
3287
3288 MiReleasePfnLock(OldIrql);
3289
3290 /* Purge the cache */
3291 CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, NULL);
3292
3293 StatusExeFmt = ExeFmtpCreateImageSection(FileObject, ImageSectionObject);
3294
3295 if (!NT_SUCCESS(StatusExeFmt))
3296 {
3297 /* Unset */
3298 OldIrql = MiAcquirePfnLock();
3299 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3300 MiReleasePfnLock(OldIrql);
3301
3302 if(ImageSectionObject->Segments != NULL)
3303 ExFreePool(ImageSectionObject->Segments);
3304
3305 /*
3306 * If image file is empty, then return that the file is invalid for section
3307 */
3308 Status = StatusExeFmt;
3309 if (StatusExeFmt == STATUS_END_OF_FILE)
3310 {
3312 }
3313
3314 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3315 ObDereferenceObject(Section);
3316 return Status;
3317 }
3318
3319 Section->Segment = (PSEGMENT)ImageSectionObject;
3320 ASSERT(ImageSectionObject->Segments);
3321 ASSERT(ImageSectionObject->RefCount > 0);
3322
3323 /*
3324 * Lock the file
3325 */
3327 if (!NT_SUCCESS(Status))
3328 {
3329 /* Unset */
3330 OldIrql = MiAcquirePfnLock();
3331 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3332 MiReleasePfnLock(OldIrql);
3333
3334 ExFreePool(ImageSectionObject->Segments);
3335 ExFreePool(ImageSectionObject);
3336 ObDereferenceObject(Section);
3337 return Status;
3338 }
3339
3340 OldIrql = MiAcquirePfnLock();
3341 ImageSectionObject->SegFlags &= ~MM_SEGMENT_INCREATE;
3342
3343 /* Take a ref on the file on behalf of the newly created structure */
3345
3346 MiReleasePfnLock(OldIrql);
3347
3348 Status = StatusExeFmt;
3349 }
3350 else
3351 {
3352 /* If FS driver called for delete, tell them it's not possible anymore. */
3353 ImageSectionObject->SegFlags &= ~MM_IMAGE_SECTION_FLUSH_DELETE;
3354
3355 /* Take one ref */
3356 InterlockedIncrement64(&ImageSectionObject->RefCount);
3357 ImageSectionObject->SectionCount++;
3358
3359 MiReleasePfnLock(OldIrql);
3360
3361 Section->Segment = (PSEGMENT)ImageSectionObject;
3362
3364 }
3365 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
3366 *SectionObject = Section;
3367 ASSERT(ImageSectionObject->RefCount > 0);
3368
3369 return Status;
3370}
3371
3372
3373
3374static NTSTATUS
3377 BOOLEAN AsImage,
3381 ULONG Protect,
3382 LONGLONG ViewOffset,
3384{
3385 PMEMORY_AREA MArea;
3387 ULONG Granularity;
3388
3389 ASSERT(ViewSize != 0);
3390
3391 if (Segment->WriteCopy)
3392 {
3393 /* We have to do this because the not present fault
3394 * and access fault handlers depend on the protection
3395 * that should be granted AFTER the COW fault takes
3396 * place to be in Region->Protect. The not present fault
3397 * handler changes this to the correct protection for COW when
3398 * mapping the pages into the process's address space. If a COW
3399 * fault takes place, the access fault handler sets the page protection
3400 * to these values for the newly copied pages
3401 */
3402 if (Protect == PAGE_WRITECOPY)
3404 else if (Protect == PAGE_EXECUTE_WRITECOPY)
3406 }
3407
3408 if (*BaseAddress == NULL)
3409 Granularity = MM_ALLOCATION_GRANULARITY;
3410 else
3411 Granularity = PAGE_SIZE;
3412
3413#ifdef NEWCC
3414 if (Segment->Flags & MM_DATAFILE_SEGMENT)
3415 {
3417 FileOffset.QuadPart = ViewOffset;
3418 ObReferenceObject(Section);
3420 }
3421#endif
3425 ViewSize,
3426 Protect,
3427 &MArea,
3429 Granularity);
3430 if (!NT_SUCCESS(Status))
3431 {
3432 DPRINT1("Mapping between 0x%p and 0x%p failed (%X).\n",
3433 (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status);
3434 return Status;
3435 }
3436
3437 InterlockedIncrement64(Segment->ReferenceCount);
3438
3439 MArea->SectionData.Segment = Segment;
3440 MArea->SectionData.ViewOffset = ViewOffset;
3441 if (AsImage)
3442 {
3444 }
3445
3446 MmInitializeRegion(&MArea->SectionData.RegionListHead,
3447 ViewSize, 0, Protect);
3448
3449 return STATUS_SUCCESS;
3450}
3451
3452
3453static VOID
3455 PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
3456{
3459 SWAPENTRY SavedSwapEntry;
3463
3466
3468
3470 MemoryArea->SectionData.ViewOffset;
3471
3472 Segment = MemoryArea->SectionData.Segment;
3473
3475 while (Entry && MM_IS_WAIT_PTE(Entry))
3476 {
3479
3481
3485 }
3486
3487 /*
3488 * For a dirty, datafile, non-private page, there shoulkd be no swap entry
3489 */
3490 if (*Segment->Flags & MM_DATAFILE_SEGMENT)
3491 {
3492 if (Page == PFN_FROM_SSE(Entry) && Dirty)
3493 {
3494 ASSERT(SwapEntry == 0);
3495 }
3496 }
3497
3498 if (SwapEntry != 0)
3499 {
3500 /*
3501 * Sanity check
3502 */
3503 MmFreeSwapPage(SwapEntry);
3504 }
3505 else if (Page != 0)
3506 {
3507 if (IS_SWAP_FROM_SSE(Entry) ||
3509 {
3510 ASSERT(Process != NULL);
3511
3512 /*
3513 * Just dereference private pages
3514 */
3515 SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
3516 if (SavedSwapEntry != 0)
3517 {
3518 MmFreeSwapPage(SavedSwapEntry);
3520 }
3523 }
3524 else
3525 {
3526 if (Process)
3527 {
3529 }
3530
3531 /* We don't dirtify for System Space Maps. We let Cc manage that */
3533 }
3534 }
3535}
3536
3537static NTSTATUS
3540{
3544 PLIST_ENTRY CurrentEntry;
3545 PMM_REGION CurrentRegion;
3546 PLIST_ENTRY RegionListHead;
3547
3549 BaseAddress);
3550 if (MemoryArea == NULL)
3551 {
3552 return STATUS_UNSUCCESSFUL;
3553 }
3554
3555 Segment = MemoryArea->SectionData.Segment;
3556
3557#ifdef NEWCC
3558 if (Segment->Flags & MM_DATAFILE_SEGMENT)
3559 {
3563
3564 return Status;
3565 }
3566#endif
3567
3569
3571
3572 RegionListHead = &MemoryArea->SectionData.RegionListHead;
3573 while (!IsListEmpty(RegionListHead))
3574 {
3575 CurrentEntry = RemoveHeadList(RegionListHead);
3576 CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
3577 ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
3578 }
3579
3580 if ((*Segment->Flags) & MM_PHYSICALMEMORY_SEGMENT)
3581 {
3583 MemoryArea,
3584 NULL,
3585 NULL);
3586 }
3587 else
3588 {
3590 MemoryArea,
3592 AddressSpace);
3593 }
3595 MmDereferenceSegment(Segment);
3596 return Status;
3597}
3598
3599/* This functions must be called with a locked address space */
3601NTAPI
3606 _In_ BOOLEAN SkipDebuggerNotify)
3607{
3610 PVOID ImageBaseAddress = 0;
3611
3612 DPRINT("Opening memory area Process %p BaseAddress %p\n",
3614
3615 ASSERT(Process);
3617
3618 AddressSpace = &Process->Vm;
3619
3620 if (MemoryArea == NULL ||
3621#ifdef NEWCC
3622 ((MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) && (MemoryArea->Type != MEMORY_AREA_CACHE)) ||
3623#else
3625#endif
3627
3628 {
3630
3631 DPRINT1("Unable to find memory area at address %p.\n", BaseAddress);
3633 }
3634
3636 {
3637 ULONG i;
3638 ULONG NrSegments;
3639 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3640 PMM_SECTION_SEGMENT SectionSegments;
3642
3643 Segment = MemoryArea->SectionData.Segment;
3644 ImageSectionObject = ImageSectionObjectFromSegment(Segment);
3645 SectionSegments = ImageSectionObject->Segments;
3646 NrSegments = ImageSectionObject->NrSegments;
3647
3649
3650 /* Search for the current segment within the section segments
3651 * and calculate the image base address */
3652 for (i = 0; i < NrSegments; i++)
3653 {
3654 if (Segment == &SectionSegments[i])
3655 {
3656 ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
3657 break;
3658 }
3659 }
3660 if (i >= NrSegments)
3661 {
3662 KeBugCheck(MEMORY_MANAGEMENT);
3663 }
3664
3665 for (i = 0; i < NrSegments; i++)
3666 {
3667 PVOID SBaseAddress = (PVOID)
3668 ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
3669
3670 Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
3671 if (!NT_SUCCESS(Status))
3672 {
3673 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3674 SBaseAddress, Process, Status);
3676 }
3677 }
3678 DPRINT("One mapping less for %p\n", ImageSectionObject->FileObject->SectionObjectPointer);
3679 InterlockedDecrement(&ImageSectionObject->MapCount);
3680 }
3681 else
3682 {
3684 PMMVAD Vad = &MemoryArea->VadNode;
3685 PCONTROL_AREA ControlArea = Vad->ControlArea;
3688 LARGE_INTEGER ViewOffset;
3689 ViewOffset.QuadPart = MemoryArea->SectionData.ViewOffset;
3690
3691 InterlockedIncrement64(Segment->ReferenceCount);
3692
3693 ViewSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
3694
3696 if (!NT_SUCCESS(Status))
3697 {
3698 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3701 }
3702
3703 /* These might be deleted now */
3704 Vad = NULL;
3705 MemoryArea = NULL;
3706
3708 {
3709 /* Don't bother */
3710 MmDereferenceSegment(Segment);
3711 return STATUS_SUCCESS;
3712 }
3714
3715 FileObject = Segment->FileObject;
3717
3718 /* Don't bother for auto-delete closed file. */
3720 {
3722 MmDereferenceSegment(Segment);
3723 return STATUS_SUCCESS;
3724 }
3725
3726 /*
3727 * Flush only when last mapping is deleted.
3728 * FIXME: Why ControlArea == NULL? Or rather: is ControlArea ever not NULL here?
3729 */
3730 if (ControlArea == NULL || ControlArea->NumberOfMappedViews == 1)
3731 {
3732 while (ViewSize > 0)
3733 {
3734 ULONG FlushSize = min(ViewSize, PAGE_ROUND_DOWN(MAXULONG));
3735 MmFlushSegment(FileObject->SectionObjectPointer,
3736 &ViewOffset,
3737 FlushSize,
3738 NULL);
3739 ViewSize -= FlushSize;
3740 ViewOffset.QuadPart += FlushSize;
3741 }
3742 }
3743
3745 MmDereferenceSegment(Segment);
3746 }
3747
3748 /* Notify debugger */
3749 if (ImageBaseAddress && !SkipDebuggerNotify) DbgkUnMapViewOfSection(ImageBaseAddress);
3750
3751 return STATUS_SUCCESS;
3752}
3753
3754
3755
3756
3780NTAPI
3782 _In_ HANDLE SectionHandle,
3783 _In_ SECTION_INFORMATION_CLASS SectionInformationClass,
3784 _Out_ PVOID SectionInformation,
3785 _In_ SIZE_T SectionInformationLength,
3787{
3788 PSECTION Section;
3791 PAGED_CODE();
3792
3794 if (PreviousMode != KernelMode)
3795 {
3796 _SEH2_TRY
3797 {
3798 ProbeForWrite(SectionInformation,
3799 SectionInformationLength,
3800 __alignof(ULONG));
3801 if (ResultLength != NULL)
3802 {
3804 sizeof(*ResultLength),
3805 __alignof(SIZE_T));
3806 }
3807 }
3809 {
3811 }
3812 _SEH2_END;
3813 }
3814
3815 if (SectionInformationClass == SectionBasicInformation)
3816 {
3817 if (SectionInformationLength < sizeof(SECTION_BASIC_INFORMATION))
3818 {
3820 }
3821 }
3822 else if (SectionInformationClass == SectionImageInformation)
3823 {
3824 if (SectionInformationLength < sizeof(SECTION_IMAGE_INFORMATION))
3825 {
3827 }
3828 }
3829 else
3830 {
3832 }
3833
3834 Status = ObReferenceObjectByHandle(SectionHandle,
3838 (PVOID*)(PVOID)&Section,
3839 NULL);
3840 if (!NT_SUCCESS(Status))
3841 {
3842 DPRINT1("Failed to reference section: 0x%lx\n", Status);
3843 return Status;
3844 }
3845
3846 switch(SectionInformationClass)
3847 {
3849 {
3851
3852 Sbi.Size = Section->SizeOfSection;
3853 Sbi.BaseAddress = (PVOID)Section->Address.StartingVpn;
3854
3855 Sbi.Attributes = 0;
3856 if (Section->u.Flags.File)
3857 Sbi.Attributes |= SEC_FILE;
3858 if (Section->u.Flags.Image)
3859 Sbi.Attributes |= SEC_IMAGE;
3860
3861 /* Those are not set *************
3862 if (Section->u.Flags.Commit)
3863 Sbi.Attributes |= SEC_COMMIT;
3864 if (Section->u.Flags.Reserve)
3865 Sbi.Attributes |= SEC_RESERVE;
3866 **********************************/
3867
3868 if (Section->u.Flags.Image)
3869 {
3870 if (MiIsRosSectionObject(Section))
3871 {
3872 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
3873 Sbi.BaseAddress = 0;
3874 Sbi.Size.QuadPart = ImageSectionObject->ImageInformation.ImageFileSize;
3875 }
3876 else
3877 {
3878 /* Not supported yet */
3879 ASSERT(FALSE);
3880 }
3881 }
3882 else if (MiIsRosSectionObject(Section))
3883 {
3884 Sbi.BaseAddress = (PVOID)((PMM_SECTION_SEGMENT)Section->Segment)->Image.VirtualAddress;
3885 Sbi.Size.QuadPart = ((PMM_SECTION_SEGMENT)Section->Segment)->RawLength.QuadPart;
3886 }
3887 else
3888 {
3889 DPRINT1("Unimplemented code path\n");
3890 }
3891
3892 _SEH2_TRY
3893 {
3894 *((SECTION_BASIC_INFORMATION*)SectionInformation) = Sbi;
3895 if (ResultLength != NULL)
3896 {
3897 *ResultLength = sizeof(Sbi);
3898 }
3899 }
3901 {
3903 }
3904 _SEH2_END;
3905 break;
3906 }
3908 {
3909 if (!Section->u.Flags.Image)
3910 {
3912 }
3913 else if (MiIsRosSectionObject(Section))
3914 {
3915 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
3916
3917 _SEH2_TRY
3918 {
3920 *Sii = ImageSectionObject->ImageInformation;
3921 if (ResultLength != NULL)
3922 {
3923 *ResultLength = sizeof(*Sii);
3924 }
3925 }
3927 {
3929 }
3930 _SEH2_END;
3931 }
3932 else
3933 {
3934 _SEH2_TRY
3935 {
3937 *Sii = *Section->Segment->u2.ImageInformation;
3938 if (ResultLength != NULL)
3939 *ResultLength = sizeof(*Sii);
3940 }
3942 {
3944 }
3945 _SEH2_END;
3946 }
3947 break;
3948 }
3949 default:
3950 DPRINT1("Unknown SectionInformationClass: %d\n", SectionInformationClass);
3952 }
3953
3954 ObDereferenceObject(Section);
3955
3956 return Status;
3957}
3958
3959/**********************************************************************
3960 * NAME EXPORTED
3961 * MmMapViewOfSection
3962 *
3963 * DESCRIPTION
3964 * Maps a view of a section into the virtual address space of a
3965 * process.
3966 *
3967 * ARGUMENTS
3968 * Section
3969 * Pointer to the section object.
3970 *
3971 * ProcessHandle
3972 * Pointer to the process.
3973 *
3974 * BaseAddress
3975 * Desired base address (or NULL) on entry;
3976 * Actual base address of the view on exit.
3977 *
3978 * ZeroBits
3979 * Number of high order address bits that must be zero.
3980 *
3981 * CommitSize
3982 * Size in bytes of the initially committed section of
3983 * the view.
3984 *
3985 * SectionOffset
3986 * Offset in bytes from the beginning of the section
3987 * to the beginning of the view.
3988 *
3989 * ViewSize
3990 * Desired length of map (or zero to map all) on entry
3991 * Actual length mapped on exit.
3992 *
3993 * InheritDisposition
3994 * Specified how the view is to be shared with
3995 * child processes.
3996 *
3997 * AllocationType
3998 * Type of allocation for the pages.
3999 *
4000 * Protect
4001 * Protection for the committed region of the view.
4002 *
4003 * RETURN VALUE
4004 * Status.
4005 *
4006 * @implemented
4007 */
4019{
4020 PSECTION Section;
4023 BOOLEAN NotAtBase = FALSE;
4024 BOOLEAN IsAttached = FALSE;
4026
4028 {
4029 DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
4031 Process,
4033 ZeroBits,
4034 CommitSize,
4036 ViewSize,
4039 Protect);
4040 }
4041
4042 ASSERT(Process);
4043
4045 {
4047 }
4048
4050 {
4052 IsAttached = TRUE;
4053 }
4054
4055 /* FIXME: We should keep this, but it would break code checking equality */
4056 Protect &= ~PAGE_NOCACHE;
4057
4058 Section = SectionObject;
4059 AddressSpace = &Process->Vm;
4060
4061 if (Section->u.Flags.NoChange)
4063
4065
4066 if (Section->u.Flags.Image)
4067 {
4068 ULONG i;
4069 ULONG NrSegments;
4070 ULONG_PTR ImageBase;
4071 SIZE_T ImageSize;
4072 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
4073 PMM_SECTION_SEGMENT SectionSegments;
4074
4075 ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
4076 SectionSegments = ImageSectionObject->Segments;
4077 NrSegments = ImageSectionObject->NrSegments;
4078
4079 ASSERT(ImageSectionObject->RefCount > 0);
4080
4081 ImageBase = (ULONG_PTR)*BaseAddress;
4082 if (ImageBase == 0)
4083 {
4084 ImageBase = (ULONG_PTR)ImageSectionObject->BasedAddress;
4085 }
4086
4087 ImageSize = 0;
4088 for (i = 0; i < NrSegments; i++)
4089 {
4090 ULONG_PTR MaxExtent;
4091 MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
4092 SectionSegments[i].Length.QuadPart);
4093 ImageSize = max(ImageSize, MaxExtent);
4094 }
4095
4096 ImageSectionObject->ImageInformation.ImageFileSize = (ULONG)ImageSize;
4097
4098 /* Check for an illegal base address */
4099 if (((ImageBase + ImageSize) > (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS) ||
4100 ((ImageBase + ImageSize) < ImageSize))
4101 {
4102 ASSERT(*BaseAddress == NULL);
4103 ImageBase = ALIGN_DOWN_BY((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - ImageSize,
4105 NotAtBase = TRUE;
4106 }
4107 else if (ImageBase != ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY))
4108 {
4109 ASSERT(*BaseAddress == NULL);
4110 ImageBase = ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY);
4111 NotAtBase = TRUE;
4112 }
4113
4114 /* Check there is enough space to map the section at that point. */
4115 if (!MmIsAddressRangeFree(AddressSpace, (PVOID)ImageBase, PAGE_ROUND_UP(ImageSize)))
4116 {
4117 /* Fail if the user requested a fixed base address. */
4118 if ((*BaseAddress) != NULL)
4119 {
4121 goto Exit;
4122 }
4123 /* Otherwise find a gap to map the image. */
4125 if (ImageBase == 0)
4126 {
4128 goto Exit;
4129 }
4130 /* Remember that we loaded image at a different base address */
4131 NotAtBase = TRUE;
4132 }
4133
4134 for (i = 0; i < NrSegments; i++)
4135 {
4136 PVOID SBaseAddress = (PVOID)
4137 ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4138 MmLockSectionSegment(&SectionSegments[i]);
4140 TRUE,
4141 &SectionSegments[i],
4142 &SBaseAddress,
4143 SectionSegments[i].Length.QuadPart,
4144 SectionSegments[i].Protection,
4145 0,
4146 0);
4147 MmUnlockSectionSegment(&SectionSegments[i]);
4148 if (!NT_SUCCESS(Status))
4149 {
4150 /* roll-back */
4151 while (i--)
4152 {
4153 SBaseAddress = ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4154 MmLockSectionSegment(&SectionSegments[i]);
4155 MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
4156 MmUnlockSectionSegment(&SectionSegments[i]);
4157 }
4158
4159 goto Exit;
4160 }
4161 }
4162
4163 *BaseAddress = (PVOID)ImageBase;
4164 *ViewSize = ImageSize;
4165
4166 DPRINT("Mapped %p for section pointer %p\n", ImageSectionObject, ImageSectionObject->FileObject->SectionObjectPointer);
4167
4168 /* One more map */
4169 InterlockedIncrement(&ImageSectionObject->MapCount);
4170 }
4171 else
4172 {
4174 LONGLONG ViewOffset;
4175
4176 ASSERT(Segment->RefCount > 0);
4177
4178 /* check for write access */
4181 {
4183 goto Exit;
4184 }
4185 /* check for read access */
4188 {
4190 goto Exit;
4191 }
4192 /* check for execute access */
4195 {
4197 goto Exit;
4198 }
4199
4200 if (SectionOffset == NULL)
4201 {
4202 ViewOffset = 0;
4203 }
4204 else
4205 {
4206 ViewOffset = SectionOffset->QuadPart;
4207 }
4208
4209 if ((ViewOffset % PAGE_SIZE) != 0)
4210 {
4212 goto Exit;
4213 }
4214
4215 if ((*ViewSize) == 0)
4216 {
4217 (*ViewSize) = Section->SizeOfSection.QuadPart - ViewOffset;
4218 }
4219 else if ((ExGetPreviousMode() == UserMode) &&
4220 (((*ViewSize)+ViewOffset) > Section->SizeOfSection.QuadPart) &&
4221 (!Section->u.Flags.Reserve))
4222 {
4223 /* Dubious */
4224 (*ViewSize) = MIN(Section->SizeOfSection.QuadPart - ViewOffset, SIZE_T_MAX - PAGE_SIZE);
4225 }
4226
4228
4231 FALSE,
4232 Segment,
4234 *ViewSize,
4235 Protect,
4236 ViewOffset,
4239 if (!NT_SUCCESS(Status))
4240 {
4241 goto Exit;
4242 }
4243 }
4244
4245 if (NotAtBase)
4247 else
4249
4250Exit:
4251
4253
4254 if (IsAttached)
4255 {
4257 }
4258
4259 return Status;
4260}
4261
4262/*
4263 * @unimplemented
4264 */
4265BOOLEAN
4266NTAPI
4270{
4271 BOOLEAN Ret;
4273
4274 /* Check whether an ImageSectionObject exists */
4275 if (SectionObjectPointer->ImageSectionObject != NULL)
4276 {
4277 DPRINT1("ERROR: File can't be truncated because it has an image section\n");
4278 return FALSE;
4279 }
4280
4282 if (!Segment)
4283 {
4284 /* There is no data section. It's fine to do anything. */
4285 return TRUE;
4286 }
4287
4289 if ((Segment->SectionCount == 0) ||
4290 ((Segment->SectionCount == 1) && (SectionObjectPointer->SharedCacheMap != NULL)))
4291 {
4292 /* If the cache is the only one holding a reference to the segment, then it's fine to resize */
4293 Ret = TRUE;
4294 }
4295 else if (NewFileSize != NULL)
4296 {
4297 /* We can't shrink, but we can extend */
4298 Ret = NewFileSize->QuadPart >= Segment->RawLength.QuadPart;
4299#if DBG
4300 if (!Ret)
4301 {
4302 DPRINT1("Cannot truncate data: New Size %I64d, Segment Size %I64d\n", NewFileSize->QuadPart, Segment->RawLength.QuadPart);
4303 }
4304#endif
4305 }
4306 else
4307 {
4308 DPRINT1("ERROR: File can't be truncated because it has references held to its data section\n");
4309 Ret = FALSE;
4310 }
4311
4313 MmDereferenceSegment(Segment);
4314
4315 DPRINT("FIXME: didn't check for outstanding write probes\n");
4316
4317 return Ret;
4318}
4319
4320static
4321BOOLEAN
4323{
4325
4327
4328 /* Loop over all entries */
4329 for (PageTable = RtlEnumerateGenericTable(&Segment->PageTable, TRUE);
4330 PageTable != NULL;
4332 {
4333 for (ULONG i = 0; i < _countof(PageTable->PageEntries); i++)
4334 {
4335 ULONG_PTR Entry = PageTable->PageEntries[i];
4337
4338 if (!Entry)
4339 continue;
4340
4342 {
4343 /* I/O ongoing or swap entry. Someone mapped this file as we were not looking */
4345 return FALSE;
4346 }
4347
4348 /* Regular entry */
4351
4352 /* Properly remove using the used API */
4353 Offset.QuadPart = PageTable->FileOffset.QuadPart + (i << PAGE_SHIFT);
4356 }
4357 }
4358
4360
4361 return TRUE;
4362}
4363
4364/*
4365 * @implemented
4366 */
4370{
4371 switch(FlushType)
4372 {
4373 case MmFlushForDelete:
4374 {
4375 /*
4376 * FIXME: Check for outstanding write probes on Data section.
4377 * How do we do that ?
4378 */
4379 }
4380 /* Fall-through */
4381 case MmFlushForWrite:
4382 {
4383 KIRQL OldIrql = MiAcquirePfnLock();
4384 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4385
4386 DPRINT("Deleting or modifying %p\n", SectionObjectPointer);
4387
4388 /* Wait for concurrent creation or deletion of image to be done */
4389 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4390 while (ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INCREATE | MM_SEGMENT_INDELETE)))
4391 {
4392 MiReleasePfnLock(OldIrql);
4394 OldIrql = MiAcquirePfnLock();
4395 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4396 }
4397
4398 if (!ImageSectionObject)
4399 {
4400 DPRINT("No image section object. Accepting\n");
4401 /* Nothing to do */
4402 MiReleasePfnLock(OldIrql);
4403 return TRUE;
4404 }
4405
4406 /* Do we have open sections or mappings on it ? */
4407 if ((ImageSectionObject->SectionCount) || (ImageSectionObject->MapCount))
4408 {
4409 /* We do. No way to delete it */
4410 MiReleasePfnLock(OldIrql);
4411 DPRINT("Denying. There are mappings open\n");
4412 return FALSE;
4413 }
4414
4415 /* There are no sections open on it, but we must still have pages around. Discard everything */
4416 ImageSectionObject->SegFlags |= MM_IMAGE_SECTION_FLUSH_DELETE;
4417 InterlockedIncrement64(&ImageSectionObject->RefCount);
4418 MiReleasePfnLock(OldIrql);
4419
4420 DPRINT("Purging\n");
4421
4422 for (ULONG i = 0; i < ImageSectionObject->NrSegments; i++)
4423 {
4424 if (!MiPurgeImageSegment(&ImageSectionObject->Segments[i]))
4425 break;
4426 }
4427
4428 /* Grab lock again */
4429 OldIrql = MiAcquirePfnLock();
4430
4431 if (!(ImageSectionObject->SegFlags & MM_IMAGE_SECTION_FLUSH_DELETE))
4432 {
4433 /*
4434 * Someone actually created a section while we were not looking.
4435 * Drop our ref and deny.
4436 * MmDereferenceSegmentWithLock releases Pfn lock
4437 */
4438 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4439 return FALSE;
4440 }
4441
4442 /* We should be the last one holding a ref here. */
4443 ASSERT(ImageSectionObject->RefCount == 1);
4444 ASSERT(ImageSectionObject->SectionCount == 0);
4445
4446 /* Dereference the first segment, this will free everything & release the lock */
4447 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4448 return TRUE;
4449 }
4450 }
4451 return FALSE;
4452}
4453
4454/*
4455 * @implemented
4456 */
4458NTAPI
4462{
4464
4465 SectionOffset.QuadPart = 0;
4466
4468}
4469
4471NTAPI
4478 )
4479{
4480 PSECTION Section = SectionObject;
4484
4486
4487 PAGED_CODE();
4488
4490 {
4492 &MmSession,
4493 MappedBase,
4494 ViewSize,
4496 }
4497
4498 DPRINT("MmMapViewInSystemSpaceEx() called\n");
4499
4500 /* unsupported for now */
4501 ASSERT(Section->u.Flags.Image == 0);
4502
4503 Section = SectionObject;
4505
4506 if (*ViewSize == 0)
4507 {
4508 LONGLONG MapSizeLL;
4509
4510 /* Page-align the mapping */
4511 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4512
4513 if (!NT_SUCCESS(RtlLongLongSub(Section->SizeOfSection.QuadPart, SectionOffset->QuadPart, &MapSizeLL)))
4515
4516 if (!NT_SUCCESS(RtlLongLongToSIZET(MapSizeLL, ViewSize)))
4518 }
4519 else
4520 {
4521 LONGLONG HelperLL;
4522
4523 /* Get the map end */
4524 if (!NT_SUCCESS(RtlLongLongAdd(SectionOffset->QuadPart, *ViewSize, &HelperLL)))
4526
4527 /* Round it up, if needed */
4528 if (HelperLL % PAGE_SIZE)
4529 {
4530 if (!NT_SUCCESS(RtlLongLongAdd(HelperLL, PAGE_SIZE - (HelperLL % PAGE_SIZE), &HelperLL)))
4532 }
4533
4534 /* Now that we have the mapping end, we can align down its start */
4535 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4536
4537 /* Get the new size */
4538 if (!NT_SUCCESS(RtlLongLongSub(HelperLL, SectionOffset->QuadPart, &HelperLL)))
4540
4541 if (!NT_SUCCESS(RtlLongLongToSIZET(HelperLL, ViewSize)))
4543 }
4544
4546
4548
4550
4552 Section->u.Flags.Image,
4553 Segment,
4554 MappedBase,
4555 *ViewSize,
4557 SectionOffset->QuadPart,
4558 SEC_RESERVE);
4559
4562
4563 return Status;
4564}
4565
4566/* This function must be called with address space lock held */
4568NTAPI
4570{
4571 DPRINT("MmUnmapViewInSystemSpace() called\n");
4572
4574}
4575
4576/**********************************************************************
4577 * NAME EXPORTED
4578 * MmCreateSection@
4579 *
4580 * DESCRIPTION
4581 * Creates a section object.
4582 *
4583 * ARGUMENTS
4584 * SectionObject (OUT)
4585 * Caller supplied storage for the resulting pointer
4586 * to a SECTION_OBJECT instance;
4587 *
4588 * DesiredAccess
4589 * Specifies the desired access to the section can be a
4590 * combination of:
4591 * STANDARD_RIGHTS_REQUIRED |
4592 * SECTION_QUERY |
4593 * SECTION_MAP_WRITE |
4594 * SECTION_MAP_READ |
4595 * SECTION_MAP_EXECUTE
4596 *
4597 * ObjectAttributes [OPTIONAL]
4598 * Initialized attributes for the object can be used
4599 * to create a named section;
4600 *
4601 * MaximumSize
4602 * Maximizes the size of the memory section. Must be
4603 * non-NULL for a page-file backed section.
4604 * If value specified for a mapped file and the file is
4605 * not large enough, file will be extended.
4606 *
4607 * SectionPageProtection
4608 * Can be a combination of:
4609 * PAGE_READONLY |
4610 * PAGE_READWRITE |
4611 * PAGE_WRITEONLY |
4612 * PAGE_WRITECOPY
4613 *
4614 * AllocationAttributes
4615 * Can be a combination of:
4616 * SEC_IMAGE |
4617 * SEC_RESERVE
4618 *
4619 * FileHandle
4620 * Handle to a file to create a section mapped to a file
4621 * instead of a memory backed section;
4622 *
4623 * File
4624 * Unknown.
4625 *
4626 * RETURN VALUE
4627 * Status.
4628 *
4629 * @implemented
4630 */
4640{
4642 ULONG Protection;
4643 PSECTION *SectionObject = (PSECTION *)Section;
4644 BOOLEAN FileLock = FALSE;
4645
4646 /* Check if an ARM3 section is being created instead */
4648 {
4649 if (!(FileObject) && !(FileHandle))
4650 {
4651 return MmCreateArm3Section(Section,
4657 FileHandle,
4658 FileObject);
4659 }
4660 }
4661
4662 /* Convert section flag to page flag */
4664
4665 /* Check to make sure the protection is correct. Nt* does this already */
4667 if (Protection == MM_INVALID_PROTECTION)
4668 {
4669 DPRINT1("Page protection is invalid\n");
4671 }
4672
4673 /* Check if this is going to be a data or image backed file section */
4674 if ((FileHandle) || (FileObject))
4675 {
4676 /* These cannot be mapped with large pages */
4678 {
4679 DPRINT1("Large pages cannot be used with an image mapping\n");
4681 }
4682
4683 /* Did the caller pass a file object ? */
4684 if (FileObject)
4685 {
4686 /* Reference the object directly */
4688
4689 /* We don't create image mappings with file objects */
4690 AllocationAttributes &= ~SEC_IMAGE;
4691 }
4692 else
4693 {
4694 /* Reference the file handle to get the object */
4696 MmMakeFileAccess[Protection],
4699 (PVOID*)&FileObject,
4700 NULL);
4701 if (!NT_SUCCESS(Status))
4702 {
4703 DPRINT1("Failed to get a handle to the FO: %lx\n", Status);
4704 return Status;
4705 }
4706
4707 /* Lock the file */
4709 if (!NT_SUCCESS(Status))
4710 {
4712 return Status;
4713 }
4714
4715 FileLock = TRUE;
4716
4717 /* Deny access if there are writes on the file */
4718#if 0
4720 {
4721 DPRINT1("Cannot create image maps with writers open on the file!\n");
4723 goto Quit;
4724 }
4725#else
4727 DPRINT1("Creating image map with writers open on the file!\n");
4728#endif
4729 }
4730 }
4731 else
4732 {
4733 /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
4735 }
4736
4738 {
4745 FileObject);
4746 }
4747#ifndef NEWCC
4748 else if (FileObject != NULL)
4749 {
4756 FileObject,
4757 FileHandle != NULL);
4758 }
4759#else
4760 else if (FileHandle != NULL || FileObject != NULL)
4761 {
4768 FileObject);
4769 }
4770#endif
4771 else
4772 {
4773 /* All cases should be handled above */
4775 }
4776
4777 if (FileLock)
4779 if (FileObject)
4781
4782 return Status;
4783}
4784
4785/* This function is not used. It is left for future use, when per-process
4786 * address space is considered. */
4787#if 0
4788BOOLEAN
4789NTAPI
4790MmArePagesResident(
4794{
4796 BOOLEAN Ret = TRUE;
4798 LARGE_INTEGER SegmentOffset, RangeEnd;
4800
4802
4804 if (MemoryArea == NULL)
4805 {
4807 return FALSE;
4808 }
4809
4810 /* Only supported in old Mm for now */
4812 /* For file mappings */
4814
4815 Segment = MemoryArea->SectionData.Segment;
4817
4819 + MemoryArea->SectionData.ViewOffset;
4821 + MemoryArea->SectionData.ViewOffset;
4822
4823 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
4824 {
4826 if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
4827 {
4828 Ret = FALSE;
4829 break;
4830 }
4831 SegmentOffset.QuadPart += PAGE_SIZE;
4832 }
4833
4835
4837 return Ret;
4838}
4839#endif
4840
4841/* Like CcPurgeCache but for the in-memory segment */
4842BOOLEAN
4843NTAPI
4848{
4849 LARGE_INTEGER PurgeStart, PurgeEnd;
4851
4852 PurgeStart.QuadPart = Offset ? Offset->QuadPart : 0LL;
4853 if (Length && Offset)
4854 {
4855 if (!NT_SUCCESS(RtlLongLongAdd(PurgeStart.QuadPart, Length, &PurgeEnd.QuadPart)))
4856 return FALSE;
4857 }
4858
4860 if (!Segment)
4861 {
4862 /* Nothing to purge */
4863 return TRUE;
4864 }
4865
4867
4868 if (!Length || !Offset)
4869 {
4870 /* We must calculate the length for ourselves */
4871 /* FIXME: All of this is suboptimal */
4872 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
4873 if (!ElemCount)
4874 {
4875 /* No page. Nothing to purge */
4877 MmDereferenceSegment(Segment);
4878 return TRUE;
4879 }
4880
4882 PurgeEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
4883 }
4884
4885 /* Find byte offset of the page to start */
4886 PurgeStart.QuadPart = PAGE_ROUND_DOWN_64(PurgeStart.QuadPart);
4887
4888 while (PurgeStart.QuadPart < PurgeEnd.QuadPart)
4889 {
4891
4892 if (Entry == 0)
4893 {
4894 PurgeStart.QuadPart += PAGE_SIZE;
4895 continue;
4896 }
4897
4899 {
4900 ASSERT(SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY);
4901 /* The page is currently being read. Meaning someone will need it soon. Bad luck */
4903 MmDereferenceSegment(Segment);
4904 return FALSE;
4905 }
4906
4907 if (IS_WRITE_SSE(Entry))
4908 {
4909 /* We're trying to purge an entry which is being written. Restart this loop iteration */
4913 continue;
4914 }
4915
4916 if (SHARE_COUNT_FROM_SSE(Entry) > 0)
4917 {
4918 /* This page is currently in use. Bad luck */
4920 MmDereferenceSegment(Segment);
4921 return FALSE;
4922 }
4923
4924 /* We can let this page go */
4925 MmSetPageEntrySectionSegment(Segment, &PurgeStart, 0);
4927
4928 PurgeStart.QuadPart += PAGE_SIZE;
4929 }
4930
4931 /* This page is currently in use. Bad luck */
4933 MmDereferenceSegment(Segment);
4934 return TRUE;
4935}
4936
4937BOOLEAN
4938NTAPI
4943{
4945 LARGE_INTEGER RangeStart, RangeEnd;
4946 BOOLEAN Ret = TRUE;
4947
4948 RangeStart.QuadPart = Offset;
4949 if (!NT_SUCCESS(RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart)))
4950 return FALSE;
4951
4953 if (!Segment)
4954 return FALSE;
4955
4956 /* Find byte offset of the page to start */
4957 RangeStart.QuadPart = PAGE_ROUND_DOWN_64(RangeStart.QuadPart);
4958
4960
4961 while (RangeStart.QuadPart < RangeEnd.QuadPart)
4962 {
4964 if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
4965 {
4966 Ret = FALSE;
4967 break;
4968 }
4969
4970 RangeStart.QuadPart += PAGE_SIZE;
4971 }
4972
4974 MmDereferenceSegment(Segment);
4975
4976 return Ret;
4977}
4978
4980NTAPI
4985 _In_ PLARGE_INTEGER ValidDataLength)
4986{
4988
4989 /* There must be a segment for this call */
4990 ASSERT(Segment);
4991
4993
4994 MmDereferenceSegment(Segment);
4995
4996 return Status;
4997}
4998
5000NTAPI
5005{
5007 LARGE_INTEGER RangeStart, RangeEnd;
5009
5010 RangeStart.QuadPart = Offset;
5011 Status = RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart);
5012 if (!NT_SUCCESS(Status))
5013 return Status;
5014
5016 if (!Segment)
5018
5019 /* Find byte offset of the page to start */
5020 RangeStart.QuadPart = PAGE_ROUND_DOWN_64(RangeStart.QuadPart);
5021
5023
5024 while (RangeStart.QuadPart < RangeEnd.QuadPart)
5025 {
5027
5028 /* Let any pending read proceed */
5029 while (MM_IS_WAIT_PTE(Entry))
5030 {
5035 }
5036
5037 /* We are called from Cc, this can't be backed by the page files */
5039
5040 /* If there is no page there, there is nothing to make dirty */
5041 if (Entry != 0)
5042 {
5043 /* Dirtify the entry */
5045 }
5046
5047 RangeStart.QuadPart += PAGE_SIZE;
5048 }
5049
5051 MmDereferenceSegment(Segment);
5052
5053 return STATUS_SUCCESS;
5054}
5055
5057NTAPI
5063{
5064 LARGE_INTEGER FlushStart, FlushEnd;
5066
5067 if (Offset)
5068 {
5069 FlushStart = *Offset;
5070 Status = RtlLongLongAdd(FlushStart.QuadPart, Length, &FlushEnd.QuadPart);
5071 if (!NT_SUCCESS(Status))
5072 return Status;
5073 }
5074
5075 if (Iosb)
5076 Iosb->Information = 0;
5077
5079 if (!Segment)
5080 {
5081 /* Nothing to flush */
5082 goto Quit;
5083 }
5084
5086
5088
5089 if (!Offset)
5090 {
5091 FlushStart.QuadPart = 0;
5092
5093 /* FIXME: All of this is suboptimal */
5094 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
5095 if (!ElemCount)
5096 {
5097 /* No page. Nothing to flush */
5099 MmDereferenceSegment(Segment);
5100 goto Quit;
5101 }
5102
5104 FlushEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
5105 }
5106
5107 /* Find byte offset of the page to start */
5108 FlushStart.QuadPart = PAGE_ROUND_DOWN_64(FlushStart.QuadPart);
5109
5110 while (FlushStart.QuadPart < FlushEnd.QuadPart)
5111 {
5113
5114 if (IS_DIRTY_SSE(Entry))
5115 {
5116 MmCheckDirtySegment(Segment, &FlushStart, FALSE, FALSE);
5117
5118 if (Iosb)
5119 Iosb->Information += PAGE_SIZE;
5120 }
5121
5122 FlushStart.QuadPart += PAGE_SIZE;
5123 }
5124
5126 MmDereferenceSegment(Segment);
5127
5128Quit:
5129 /* FIXME: Handle failures */
5130 if (Iosb)
5131 Iosb->Status = STATUS_SUCCESS;
5132
5133 return STATUS_SUCCESS;
5134}
5135
5137BOOLEAN
5138NTAPI
5144{
5148
5149 ASSERT(Segment->Locked);
5150
5151 ASSERT((Offset->QuadPart % PAGE_SIZE) == 0);
5152
5153 DPRINT("Checking segment for file %wZ at offset 0x%I64X.\n", &Segment->FileObject->FileName, Offset->QuadPart);
5154
5156 if (Entry == 0)
5157 return FALSE;
5158
5160 if ((IS_DIRTY_SSE(Entry)) || ForceDirty)
5161 {
5162 BOOLEAN DirtyAgain;
5163
5164 /*
5165 * We got a dirty entry. This path is for the shared data,
5166 * be-it regular file maps or shared sections of DLLs
5167 */
5169 FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5170
5171 /* Insert the cleaned entry back. Mark it as write in progress, and clear the dirty bit. */
5175
5177
5178 if (FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5179 {
5181 KIRQL OldIrql;
5182
5183 /* We have to write it back to the file. Tell the FS driver who we are */
5184 if (PageOut)
5185 {
5186 LARGE_INTEGER EndOffset = *Offset;
5187
5189
5190 /* We need to disable all APCs */
5192
5193 EndOffset.QuadPart += PAGE_SIZE;
5195 &EndOffset,
5197 if (NT_SUCCESS(Status))
5198 {
5200 }
5201 else
5202 {
5203 /* Make sure we will not try to release anything */
5205 }
5206 }
5207 else
5208 {
5209 /* We don't have to lock. Say this is success */
5211 }
5212
5213 /* Go ahead and write the page, if previous locking succeeded */
5214 if (NT_SUCCESS(Status))
5215 {
5216 DPRINT("Writing page at offset %I64d for file %wZ, Pageout: %s\n",
5217 Offset->QuadPart, &Segment->FileObject->FileName, PageOut ? "TRUE" : "FALSE");
5218 Status = MiWritePage(Segment, Offset->QuadPart, Page);
5219 }
5220
5221 if (PageOut)
5222 {
5224 if (ResourceToRelease != NULL)
5225 {
5227 }
5229 }
5230 }
5231 else
5232 {
5233 /* This must only be called by the page-out path */
5234 ASSERT(PageOut);
5235
5236 /* And this must be for a shared section in a DLL */
5237 ASSERT(FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5238
5240 if (!SwapEntry)
5241 {
5242 SwapEntry = MmAllocSwapPage();
5243 }
5244
5245 if (SwapEntry)
5246 {
5247 Status = MmWriteToSwapPage(SwapEntry, Page);
5248 if (NT_SUCCESS(Status))
5249 {
5250 MmSetSavedSwapEntryPage(Page, SwapEntry);
5251 }
5252 else
5253 {
5254 MmFreeSwapPage(SwapEntry);
5255 }
5256 }
5257 else
5258 {
5259 DPRINT1("Failed to allocate a swap page!\n");
5261 }
5262 }
5263
5265
5266 /* Get the entry again */
5269
5270 if (!NT_SUCCESS(Status))
5271 {
5272 /* Damn, this failed. Consider this page as still dirty */
5273 DPRINT1("MiWritePage FAILED: Status 0x%08x!\n", Status);
5274 DirtyAgain = TRUE;
5275 }
5276 else
5277 {
5278 /* Check if someone dirtified this page while we were not looking */
5279 DirtyAgain = IS_DIRTY_SSE(Entry);
5280 }
5281
5282 /* Drop the reference we got, deleting the write altogether. */
5284 if (DirtyAgain)
5285 {
5287 }
5289 }
5290
5291 /* Were this page hanging there just for the sake of being present ? */
5293 {
5294 ULONG_PTR NewEntry = 0;
5295 /* Restore the swap entry here */
5296 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5297 {
5299 if (SwapEntry)
5300 NewEntry = MAKE_SWAP_SSE(SwapEntry);
5301 }
5302
5303 /* Yes. Release it */
5306 /* Tell the caller we released the page */
5307 return TRUE;
5308 }
5309
5310 return FALSE;
5311}
5312
5313/* This function is not used. It is left for future use, when per-process
5314 * address space is considered. */
5315#if 0
5317NTAPI
5318MmMakePagesDirty(
5322{
5325 LARGE_INTEGER SegmentOffset, RangeEnd;
5327
5329
5331 if (MemoryArea == NULL)
5332 {
5333 DPRINT1("Unable to find memory area at address %p.\n", Address);
5336 }
5337
5338 /* Only supported in old Mm for now */
5340 /* For file mappings */
5342
5343 Segment = MemoryArea->SectionData.Segment;
5345
5347 + MemoryArea->SectionData.ViewOffset;
5349 + MemoryArea->SectionData.ViewOffset;
5350
5351 DPRINT("MmMakePagesResident: Segment %p, 0x%I64x -> 0x%I64x\n", Segment, SegmentOffset.QuadPart, RangeEnd.QuadPart);
5352
5353 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
5354 {
5356
5357 /* Let any pending read proceed */
5358 while (MM_IS_WAIT_PTE(Entry))
5359 {
5365 Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset);
5366 }
5367
5368 /* We are called from Cc, this can't be backed by the page files */
5370
5371 /* If there is no page there, there is nothing to make dirty */
5372 if (Entry != 0)
5373 {
5374 /* Dirtify the entry */
5376 }
5377
5378 SegmentOffset.QuadPart += PAGE_SIZE;
5379 }
5380
5382
5384 return STATUS_SUCCESS;
5385}
5386#endif
5387
5389NTAPI
5391 _In_ PVOID _Section,
5393{
5394 PSECTION Section = _Section;
5395
5396 /* It makes no sense to extend an image mapping */
5397 if (Section->u.Flags.Image)
5399
5400 /* Nor is it possible to extend a page file mapping */
5401 if (!Section->u.Flags.File)
5403
5404 if (!MiIsRosSectionObject(Section))
5406
5407 /* We just extend the sizes. Shrinking is a no-op ? */
5408 if (NewSize->QuadPart > Section->SizeOfSection.QuadPart)
5409 {
5411 Section->SizeOfSection = *NewSize;
5412
5413 if (!Section->u.Flags.Reserve)
5414 {
5416 if (Segment->RawLength.QuadPart < NewSize->QuadPart)
5417 {
5418 Segment->RawLength = *NewSize;
5419 Segment->Length.QuadPart = (NewSize->QuadPart + PAGE_SIZE - 1) & ~((LONGLONG)PAGE_SIZE);
5420 }
5422 }
5423 }
5424
5425 return STATUS_SUCCESS;
5426}
5427
5428/* 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:1039
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:2102
VOID NTAPI MiDeleteARM3Section(PVOID ObjectBody)
Definition: section.c:2951
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:2531
ACCESS_MASK MmMakeFileAccess[8]
Definition: section.c:32
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:140
#define PAGED_CODE()
#define CODE_SEG(...)
ULONG ReadLength
#define ALIGN_DOWN_BY(size, align)
#define ALIGN_UP_BY(size, align)
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG _In_ KPROCESSOR_MODE PreviousMode
ULONG_PTR PFN_NUMBER
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define __cdecl
Definition: accygwin.h:79
#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:1434
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
Definition: bufpool.h:45
Definition: File.h:16
#define _Requires_lock_held_(lock)
#define _Requires_lock_not_held_(lock)
#define _Releases_lock_(lock)
#define _Requires_exclusive_lock_held_(lock)
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
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 *))
_Out_ PKIRQL Irql
Definition: csq.h:179
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
VOID NTAPI DbgkUnMapViewOfSection(IN PVOID BaseAddress)
Definition: dbgkutil.c:436
#define BufferSize
Definition: mmc.h:75
LPWSTR Name
Definition: desk.c:124
#define SIZE_T_MAX
Definition: dhcpd.h:91
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define PAGE_READONLY
Definition: compat.h:138
#define SECTION_MAP_READ
Definition: compat.h:139
return Iosb
Definition: create.c:4403
#define ULONG_PTR
Definition: config.h:101
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define _IRQL_restores_
Definition: driverspecs.h:233
#define _IRQL_requires_(irql)
Definition: driverspecs.h:229
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define PagedPool
Definition: env_spec_w32.h:308
#define ExGetPreviousMode
Definition: ex.h:143
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1544
#define EXEFMT_LOAD_ASSUME_SEGMENTS_SORTED
Definition: exeformat.h:8
#define STATUS_ROS_EXEFMT_UNKNOWN_FORMAT
Definition: exeformat.h:72
#define PEFMT_FIELDS_EQUAL(TYPE1_, TYPE2_, FIELD_)
Definition: exeformat.h:165
#define EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED
Definition: exeformat.h:10
static __inline BOOLEAN IsPowerOf2(IN ULONG Number)
Definition: exeformat.h:134
static __inline BOOLEAN Intsafe_CanAddLong64(IN LONG64 Addend1, IN LONG64 Addend2)
Definition: exeformat.h:104
NTSTATUS(NTAPI * PEXEFMT_CB_READ_FILE)(IN PVOID File, IN PLARGE_INTEGER Offset, IN ULONG Length, OUT PVOID *Data, OUT PVOID *AllocBase, OUT PULONG ReadSize)
Definition: exeformat.h:36
#define EXEFMT_LOAD_ASSUME_SEGMENTS_NO_OVERLAP
Definition: exeformat.h:9
static __inline BOOLEAN Intsafe_CanMulULong32(IN ULONG Factor1, IN ULONG Factor2)
Definition: exeformat.h:123
NTSTATUS(NTAPI * PEXEFMT_LOADER)(IN CONST VOID *FileHeader, IN SIZE_T FileHeaderSize, IN PVOID File, OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, OUT PULONG Flags, IN PEXEFMT_CB_READ_FILE ReadFileCb, IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb)
Definition: exeformat.h:51
static __inline BOOLEAN Intsafe_CanAddULong32(IN ULONG Addend1, IN ULONG Addend2)
Definition: exeformat.h:109
#define EXEFMT_LOAD_HEADER_SIZE
Definition: exeformat.h:23
PMM_SECTION_SEGMENT(NTAPI * PEXEFMT_CB_ALLOCATE_SEGMENTS)(IN ULONG NrSegments)
Definition: exeformat.h:46
static __inline BOOLEAN IsAligned(IN ULONG Address, IN ULONG Alignment)
Definition: exeformat.h:147
static __inline BOOLEAN Intsafe_CanOffsetPointer(IN CONST VOID *Pointer, IN SIZE_T Offset)
Definition: exeformat.h:128
static __inline BOOLEAN Intsafe_AddULong32(OUT PULONG Result, IN ULONG Addend1, IN ULONG Addend2)
Definition: exeformat.h:114
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN PFCB IN FAT_FLUSH_TYPE FlushType
Definition: fatprocs.h:1083
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
@ 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 OBJ_OPENLINK
Definition: winternl.h:230
#define OBJ_PERMANENT
Definition: winternl.h:226
@ ProcessHandleCount
Definition: winternl.h:876
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#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
if(dx< 0)
Definition: linetemp.h:194
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
FORCEINLINE BOOLEAN MiIsRosSectionObject(IN PSECTION Section)
Definition: miarm.h:1101
#define _64K
Definition: miarm.h:23
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
NTSTATUS NTAPI MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:4569
NTSTATUS NTAPI MiRosUnmapViewOfSection(_In_ PEPROCESS Process, _In_ PMEMORY_AREA MemoryArea, _In_ PVOID BaseAddress, _In_ BOOLEAN SkipDebuggerNotify)
Definition: section.c:3602
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
FORCEINLINE PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define SECTION
Definition: profile.c:31
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
unsigned int UINT
Definition: ndis.h:50
#define MM_ALLOCATION_GRANULARITY
Definition: mmtypes.h:36
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize 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 _Outptr_result_bytebuffer_(s)
Definition: no_sal2.h:288
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _When_(c, a)
Definition: no_sal2.h:38
#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:683
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:680
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
_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:1858
VOID NTAPI FsRtlReleaseFileForModWrite(_In_ PFILE_OBJECT FileObject, _In_ PERESOURCE ResourceToRelease)
Unlock a file object after flushing pages to disk. To be called by the Modified Page Writer (MPW) aft...
Definition: fastio.c:1965
VOID NTAPI FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1665
VOID NTAPI FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1640
NTSTATUS NTAPI FsRtlAcquireToCreateMappedSection(_In_ PFILE_OBJECT FileObject, _In_ ULONG SectionPageProtection)
Definition: fastio.c:1653
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:46
#define MmGetPageEntrySectionSegment(S, O)
Definition: mm.h:1602
#define MI_SET_PROCESS2(x)
Definition: mm.h:330
#define MM_NOIRQL
Definition: mm.h:70
@ MI_USAGE_SECTION
Definition: mm.h:344
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1696
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
KSPIN_LOCK MmPfnLock
Definition: krnlinit.c:45
#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:379
#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:258
#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:61
#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:252
PFN_NUMBER NTAPI MmGetPfnForProcess(struct _EPROCESS *Process, PVOID Address)
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:251
#define PAGE_IS_WRITABLE
Definition: mm.h:160
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1709
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:328
#define MM_SEGMENT_INDELETE
Definition: mm.h:246
#define PAGE_FLAGS_VALID_FOR_SECTION
Definition: mm.h:141
#define MM_SEGMENT_INCREATE
Definition: mm.h:247
NTSTATUS NTAPI MmExtendSection(_In_ PVOID Section, _Inout_ PLARGE_INTEGER NewSize)
Definition: section.c:5390
BOOLEAN NTAPI MmIsAddressRangeFree(_In_ PMMSUPPORT AddressSpace, _In_ PVOID Address, _In_ ULONG_PTR Length)
Definition: marea.c:111
FORCEINLINE PEPROCESS MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
Definition: mm.h:1716
BOOLEAN NTAPI MmIsPagePresent(struct _EPROCESS *Process, PVOID Address)
VOID NTAPI MmFreeSwapPage(SWAPENTRY Entry)
Definition: pagefile.c:291
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1770
VOID NTAPI MmSetSavedSwapEntryPage(PFN_NUMBER Page, SWAPENTRY SavedSwapEntry)
Definition: freelist.c:484
NTSTATUS NTAPI MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID StartAddress, SIZE_T Length, ULONG NewType, ULONG NewProtect, PMM_ALTER_REGION_FUNC AlterFunc)
Definition: region.c:108
#define PAGE_IS_EXECUTABLE
Definition: mm.h:166
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:500
NTSTATUS NTAPI MmCreatePhysicalMapping(_Inout_opt_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG flProtect, _In_ PFN_NUMBER Page)
Definition: page.c:735
#define MM_IMAGE_SECTION_FLUSH_DELETE
Definition: mm.h:248
#define PAGE_ROUND_DOWN_64(x)
Definition: mm.h:138
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:190
#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:244
#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:1731
VOID NTAPI MmInsertRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
#define MM_DATAFILE_SEGMENT
Definition: mm.h:245
#define STATUS_MM_RESTART_OPERATION
Definition: mm.h:104
#define PAGE_IS_READABLE
Definition: mm.h:152
#define WRITE_SSE(E)
Definition: mm.h:1378
#define PAGE_IS_WRITECOPY
Definition: mm.h:172
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_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_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define STATUS_MAPPED_FILE_SIZE_ZERO
Definition: ntstatus.h:522
#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:181
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:184
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
static GENERIC_MAPPING MmpSectionMapping
Definition: section.c:223
PFN_NUMBER Page
Definition: section.c:5147
NTSTATUS NTAPI MmMapViewInSystemSpace(IN PVOID SectionObject, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:4459
BOOLEAN NTAPI MmCanFileBeTruncated(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
Definition: section.c:4267
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:2340
VOID NTAPI MmpDeleteSection(PVOID ObjectBody)
Definition: section.c:2151
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:4009
NTSTATUS NTAPI MmMakeSegmentDirty(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
Definition: section.c:5001
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
static PMM_SECTION_SEGMENT NTAPI ExeFmtpAllocateSegments(IN ULONG NrSegments)
Definition: section.c:2603
ULONG_PTR MmSubsectionBase
Definition: section.c:196
static BOOLEAN NTAPI MmspPageAlignSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2854
NTSTATUS NTAPI MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, MEMORY_AREA *MemoryArea, PVOID Address, BOOLEAN Locked)
Definition: section.c:1537
NTSTATUS MmspWaitForFileLock(PFILE_OBJECT File)
Definition: section.c:907
PLARGE_INTEGER BOOLEAN BOOLEAN PageOut
Definition: section.c:5144
static BOOLEAN NTAPI MmspCheckSegmentBounds(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2803
#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:4632
static BOOLEAN MiPurgeImageSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:4322
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:3538
BOOLEAN NTAPI MmPurgeSegment(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length)
Definition: section.c:4844
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:2112
NTSTATUS NTAPI MmProtectSectionView(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PVOID BaseAddress, SIZE_T Length, ULONG Protect, PULONG OldProtect)
Definition: section.c:2068
VOID NTAPI MmpCloseSection(IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG ProcessHandleCount, IN ULONG SystemHandleCount)
Definition: section.c:2204
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:4472
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:2742
static VOID NTAPI MmspSortSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2777
NTSTATUS NTAPI MmAccessFaultSectionView(PMMSUPPORT AddressSpace, MEMORY_AREA *MemoryArea, PVOID Address, BOOLEAN Locked)
Definition: section.c:1915
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4368
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:3781
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:2623
NTSTATUS MmCreateImageSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
Definition: section.c:3190
BOOLEAN NTAPI MmIsDataSectionResident(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
Definition: section.c:4939
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:5058
static VOID NTAPI MmspAssertSegmentsSorted(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2706
NTSTATUS NTAPI MmInitSectionImplementation(VOID)
Definition: section.c:2307
static PEXEFMT_LOADER ExeFmtpLoaders[]
Definition: section.c:2592
static VOID MmAlterViewAttributes(PMMSUPPORT AddressSpace, PVOID BaseAddress, SIZE_T RegionSize, ULONG OldType, ULONG OldProtect, ULONG NewType, ULONG NewProtect)
Definition: section.c:1446
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:4981
static int __cdecl MmspCompareSegments(const void *x, const void *y)
Definition: section.c:2757
KEVENT MmWaitPageEvent
Definition: section.c:66
static VOID NTAPI MmspAssertSegmentsNoOverlap(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2720
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:3037
PLARGE_INTEGER BOOLEAN ForceDirty
Definition: section.c:5142
static VOID MmFreeSectionPage(PVOID Context, MEMORY_AREA *MemoryArea, PVOID Address, PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
Definition: section.c:3454
NTSTATUS NTAPI MmCreatePhysicalMemorySection(VOID)
Definition: section.c:2216
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:3375
PLARGE_INTEGER Offset
Definition: section.c:5141
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:73
#define _countof(array)
Definition: sndvol32.h:70
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
union _IMAGE_SECTION_HEADER::@1611 Misc
DWORD PointerToRawData
Definition: pedump.c:290
Definition: typedefs.h:120
struct _MEMORY_AREA::@1840 SectionData
ULONG Flags
Definition: mm.h:259
BOOLEAN DeleteInProgress
Definition: mm.h:260
ULONG Type
Definition: mm.h:258
MMVAD VadNode
Definition: mm.h:256
ULONG_PTR StartingVpn
Definition: mmtypes.h:653
union _MMADDRESS_NODE::@2709 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
union _MMVAD::@2711 u
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:734
ULONG_PTR NumberGenericTableElements
Definition: mmtypes.h:668
MMADDRESS_NODE BalancedRoot
Definition: mmtypes.h:662
PMM_SECTION_SEGMENT Segments
Definition: mm.h:241
PFILE_OBJECT FileObject
Definition: mm.h:233
SECTION_IMAGE_INFORMATION ImageInformation
Definition: mm.h:238
Definition: mm.h:483
PULONG Flags
Definition: mm.h:212
LARGE_INTEGER RawLength
Definition: mm.h:207
struct _MM_SECTION_SEGMENT::@1839 Image
PLONG64 ReferenceCount
Definition: mm.h:209
FAST_MUTEX Lock
Definition: mm.h:206
PFILE_OBJECT FileObject
Definition: mm.h:204
BOOLEAN WriteCopy
Definition: mm.h:213
ULONG Protection
Definition: mm.h:211
LARGE_INTEGER Length
Definition: mm.h:208
OB_CLOSE_METHOD CloseProcedure
Definition: obtypes.h:368
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
OB_DELETE_METHOD DeleteProcedure
Definition: obtypes.h:369
LARGE_INTEGER Size
Definition: mmtypes.h:336
MMSECTION_FLAGS Flags
Definition: mmtypes.h:817
union _SECTION::@2720 u
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
PSECTION_IMAGE_INFORMATION ImageInformation
Definition: mmtypes.h:426
union _SEGMENT::@2703 u2
Definition: fci.c:127
Definition: parser.c:49
static PMEM_HOOK PageTable[TOTAL_PAGES]
Definition: memory.c:43
#define max(a, b)
Definition: svc.c:63
#define TAG_MM_SECTION_SEGMENT
Definition: tag.h:113
#define TAG_MM_REGION
Definition: tag.h:110
else
Definition: tritemp.h:161
#define LL
Definition: tui.h:166
#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:1572
_Must_inspect_result_ _Outptr_result_bytebuffer_ ViewSize PVOID * MappedBase
Definition: mmfuncs.h:492
#define MmInitializeMdl(_MemoryDescriptorList, _BaseVa, _Length)
#define BYTES_TO_PAGES(Size)
_Must_inspect_result_ _In_ ULONG NewProtect
Definition: mmfuncs.h:682
#define MmGetMdlPfnArray(_Mdl)
_In_opt_ PLARGE_INTEGER NewFileSize
Definition: mmfuncs.h:608
MMFLUSH_TYPE
Definition: mmtypes.h:183
MDL
Definition: mmtypes.h:117
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define MDL_IO_PAGE_READ
Definition: mmtypes.h:24
#define MDL_MAPPED_TO_SYSTEM_VA
Definition: mmtypes.h:18
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ BOOLEAN Restart)
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlGetElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ ULONG I)
NTSYSAPI ULONG NTAPI RtlNumberGenericTableElements(_In_ PRTL_GENERIC_TABLE Table)
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:20
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