ReactOS 0.4.16-dev-1946-g52006dd
section.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 *
19 * PROJECT: ReactOS kernel
20 * PURPOSE: Implements section objects
21 *
22 * PROGRAMMERS: Rex Jolliff
23 * David Welch
24 * Eric Kohl
25 * Emanuele Aliberti
26 * Eugene Ingerman
27 * Casper Hornstrup
28 * KJK::Hyperion
29 * Guido de Jong
30 * Ge van Geldorp
31 * Royce Mitchell III
32 * Filip Navara
33 * Aleksey Bragin
34 * Jason Filby
35 * Thomas Weidenmueller
36 * Gunnar Andre' Dalsnes
37 * Mike Nordell
38 * Alex Ionescu
39 * Gregor Anich
40 * Steven Edwards
41 * Herve Poussineau
42 */
43
44/* INCLUDES *****************************************************************/
45
46#include <ntoskrnl.h>
47#include <cache/newcc.h>
48#include <cache/section/newmm.h>
49#define NDEBUG
50#include <debug.h>
51#include <reactos/exeformat.h>
52
53#include "ARM3/miarm.h"
54
55#undef MmSetPageEntrySectionSegment
56#define MmSetPageEntrySectionSegment(S,O,E) \
57 _MmSetPageEntrySectionSegment((S),(O),(E),__FILE__,__LINE__)
58
59extern MMSESSION MmSession;
60
61static LARGE_INTEGER TinyTime = {{-1L, -1L}};
62
63#ifndef NEWCC
65
66VOID
69{
70 //DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line);
72 Segment->Locked = TRUE;
73}
74
75VOID
78{
79 ASSERT(Segment->Locked);
80 Segment->Locked = FALSE;
82 //DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line);
83}
84#endif
85
86static
89{
90 KIRQL OldIrql = MiAcquirePfnLock();
92
93 while (TRUE)
94 {
95 Segment = SectionObjectPointer->DataSectionObject;
96 if (!Segment)
97 break;
98
100 {
101 MiReleasePfnLock(OldIrql);
103 OldIrql = MiAcquirePfnLock();
104 continue;
105 }
106
109 break;
110 }
111
112 MiReleasePfnLock(OldIrql);
113
114 return Segment;
115}
116
117/* Somewhat grotesque, but eh... */
119{
120 ASSERT((Segment->SegFlags & MM_DATAFILE_SEGMENT) == 0);
121
122 return CONTAINING_RECORD(Segment->ReferenceCount, MM_IMAGE_SECTION_OBJECT, RefCount);
123}
124
127 IN PVOID Session,
131
133NTAPI
137 IN PLARGE_INTEGER InputMaximumSize,
142
144NTAPI
155
156//
157// PeFmtCreateSection depends on the following:
158//
161
165
175
176/* TYPES *********************************************************************/
177
178typedef struct
179{
187}
189
190/* GLOBALS *******************************************************************/
191
193
195
197{
198 PAGE_NOACCESS, /* 0 = NONE */
199 PAGE_NOACCESS, /* 1 = SHARED */
200 PAGE_EXECUTE, /* 2 = EXECUTABLE */
201 PAGE_EXECUTE, /* 3 = EXECUTABLE, SHARED */
202 PAGE_READONLY, /* 4 = READABLE */
203 PAGE_READONLY, /* 5 = READABLE, SHARED */
204 PAGE_EXECUTE_READ, /* 6 = READABLE, EXECUTABLE */
205 PAGE_EXECUTE_READ, /* 7 = READABLE, EXECUTABLE, SHARED */
206 /*
207 * FIXME? do we really need the WriteCopy field in segments? can't we use
208 * PAGE_WRITECOPY here?
209 */
210 PAGE_READWRITE, /* 8 = WRITABLE */
211 PAGE_READWRITE, /* 9 = WRITABLE, SHARED */
212 PAGE_EXECUTE_READWRITE, /* 10 = WRITABLE, EXECUTABLE */
213 PAGE_EXECUTE_READWRITE, /* 11 = WRITABLE, EXECUTABLE, SHARED */
214 PAGE_READWRITE, /* 12 = WRITABLE, READABLE */
215 PAGE_READWRITE, /* 13 = WRITABLE, READABLE, SHARED */
216 PAGE_EXECUTE_READWRITE, /* 14 = WRITABLE, READABLE, EXECUTABLE */
217 PAGE_EXECUTE_READWRITE, /* 15 = WRITABLE, READABLE, EXECUTABLE, SHARED */
218};
219
222{
227};
228
229
230/* FUNCTIONS *****************************************************************/
231
232
233
235NTAPI
237 LONGLONG SegOffset,
239/*
240 * FUNCTION: write a page for a section backed memory area.
241 * PARAMETERS:
242 * MemoryArea - Memory area to write the page for.
243 * Offset - Offset of the page to write.
244 * Page - Page which contains the data to write.
245 */
246{
250 UCHAR MdlBase[sizeof(MDL) + sizeof(PFN_NUMBER)];
251 PMDL Mdl = (PMDL)MdlBase;
252 PFILE_OBJECT FileObject = Segment->FileObject;
254
255 FileOffset.QuadPart = Segment->Image.FileOffset + SegOffset;
256
257 RtlZeroMemory(MdlBase, sizeof(MdlBase));
260 Mdl->MdlFlags |= MDL_PAGES_LOCKED;
261
264 if (Status == STATUS_PENDING)
265 {
267 Status = IoStatus.Status;
268 }
269 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
270 {
271 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
272 }
273
274 return Status;
275}
276
277
278/*
279 References:
280 [1] Microsoft Corporation, "Microsoft Portable Executable and Common Object
281 File Format Specification", revision 6.0 (February 1999)
282*/
284 IN SIZE_T FileHeaderSize,
285 IN PVOID File,
286 OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
288 IN PEXEFMT_CB_READ_FILE ReadFileCb,
289 IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb)
290{
291 NTSTATUS nStatus;
292 ULONG cbFileHeaderOffsetSize = 0;
293 ULONG cbSectionHeadersOffset = 0;
294 ULONG cbSectionHeadersSize;
295 ULONG cbSectionHeadersOffsetSize = 0;
296 ULONG cbOptHeaderSize;
297 ULONG cbHeadersSize = 0;
298 ULONG nSectionAlignment;
299 ULONG nFileAlignment;
300 ULONG_PTR ImageBase = 0;
301 const IMAGE_DOS_HEADER * pidhDosHeader;
302 const IMAGE_NT_HEADERS32 * pinhNtHeader;
303 const IMAGE_OPTIONAL_HEADER32 * piohOptHeader;
304 const IMAGE_SECTION_HEADER * pishSectionHeaders;
305 PMM_SECTION_SEGMENT pssSegments;
306 LARGE_INTEGER lnOffset;
308 SIZE_T nPrevVirtualEndOfSegment = 0;
309 ULONG nFileSizeOfHeaders = 0;
310 ULONG i;
311 ULONG AlignedLength;
312
313 ASSERT(FileHeader);
314 ASSERT(FileHeaderSize > 0);
315 ASSERT(File);
316 ASSERT(ImageSectionObject);
317 ASSERT(ReadFileCb);
318 ASSERT(AllocateSegmentsCb);
319
320 ASSERT(Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize));
321
322 ASSERT(((UINT_PTR)FileHeader % TYPE_ALIGNMENT(IMAGE_DOS_HEADER)) == 0);
323
324#define DIE(ARGS_) { DPRINT ARGS_; goto l_Return; }
325
326 pBuffer = NULL;
327 pidhDosHeader = FileHeader;
328
329 /* DOS HEADER */
331
332 /* image too small to be an MZ executable */
333 if(FileHeaderSize < sizeof(IMAGE_DOS_HEADER))
334 DIE(("Too small to be an MZ executable, size is %lu\n", FileHeaderSize));
335
336 /* no MZ signature */
337 if(pidhDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
338 DIE(("No MZ signature found, e_magic is %hX\n", pidhDosHeader->e_magic));
339
340 /* NT HEADER */
342
343 /* not a Windows executable */
344 if(pidhDosHeader->e_lfanew <= 0)
345 DIE(("Not a Windows executable, e_lfanew is %d\n", pidhDosHeader->e_lfanew));
346
347 if(!Intsafe_AddULong32(&cbFileHeaderOffsetSize, pidhDosHeader->e_lfanew, RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader)))
348 DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
349
350 if(FileHeaderSize < cbFileHeaderOffsetSize)
351 pinhNtHeader = NULL;
352 else
353 {
354 /*
355 * we already know that Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize),
356 * and FileHeaderSize >= cbFileHeaderOffsetSize, so this holds true too
357 */
358 ASSERT(Intsafe_CanOffsetPointer(FileHeader, pidhDosHeader->e_lfanew));
359 pinhNtHeader = (PVOID)((UINT_PTR)FileHeader + pidhDosHeader->e_lfanew);
360 }
361
362 /*
363 * the buffer doesn't contain the NT file header, or the alignment is wrong: we
364 * need to read the header from the file
365 */
366 if(FileHeaderSize < cbFileHeaderOffsetSize ||
367 (UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
368 {
369 ULONG cbNtHeaderSize;
370 ULONG cbReadSize;
371 PVOID pData;
372
373l_ReadHeaderFromFile:
374 cbNtHeaderSize = 0;
375 lnOffset.QuadPart = pidhDosHeader->e_lfanew;
376
377 /* read the header from the file */
378 nStatus = ReadFileCb(File, &lnOffset, sizeof(IMAGE_NT_HEADERS64), &pData, &pBuffer, &cbReadSize);
379
380 if(!NT_SUCCESS(nStatus))
381 {
382 NTSTATUS ReturnedStatus = nStatus;
383
384 /* If it attempted to read past the end of the file, it means e_lfanew is invalid */
385 if (ReturnedStatus == STATUS_END_OF_FILE) nStatus = STATUS_INVALID_IMAGE_PROTECT;
386
387 DIE(("ReadFile failed, status %08X\n", ReturnedStatus));
388 }
389
390 ASSERT(pData);
392 ASSERT(cbReadSize > 0);
393
395
396 /* the buffer doesn't contain the file header */
397 if(cbReadSize < RTL_SIZEOF_THROUGH_FIELD(IMAGE_NT_HEADERS32, FileHeader))
398 DIE(("The file doesn't contain the PE file header\n"));
399
400 pinhNtHeader = pData;
401
402 /* object still not aligned: copy it to the beginning of the buffer */
403 if((UINT_PTR)pinhNtHeader % TYPE_ALIGNMENT(IMAGE_NT_HEADERS32) != 0)
404 {
406 RtlMoveMemory(pBuffer, pData, cbReadSize);
407 pinhNtHeader = pBuffer;
408 }
409
410 /* invalid NT header */
412
413 if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
414 DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
415
417
418 if(!Intsafe_AddULong32(&cbNtHeaderSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
419 DIE(("The full NT header is too large\n"));
420
421 /* the buffer doesn't contain the whole NT header */
422 if(cbReadSize < cbNtHeaderSize)
423 DIE(("The file doesn't contain the full NT header\n"));
424 }
425 else
426 {
427 ULONG cbOptHeaderOffsetSize = 0;
428
430
431 /* don't trust an invalid NT header */
432 if(pinhNtHeader->Signature != IMAGE_NT_SIGNATURE)
433 DIE(("The file isn't a PE executable, Signature is %X\n", pinhNtHeader->Signature));
434
435 if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
436 DIE(("The DOS stub is too large, e_lfanew is %X\n", pidhDosHeader->e_lfanew));
437
439
440 if(!Intsafe_AddULong32(&cbOptHeaderOffsetSize, cbOptHeaderOffsetSize, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
441 DIE(("The NT header is too large, SizeOfOptionalHeader is %X\n", pinhNtHeader->FileHeader.SizeOfOptionalHeader));
442
443 /* the buffer doesn't contain the whole NT header: read it from the file */
444 if(cbOptHeaderOffsetSize > FileHeaderSize)
445 goto l_ReadHeaderFromFile;
446 }
447
448 /* read information from the NT header */
449 piohOptHeader = &pinhNtHeader->OptionalHeader;
450 cbOptHeaderSize = pinhNtHeader->FileHeader.SizeOfOptionalHeader;
451
453
454 if(!RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Magic))
455 DIE(("The optional header doesn't contain the Magic field, SizeOfOptionalHeader is %X\n", cbOptHeaderSize));
456
457 /* ASSUME: RtlZeroMemory(ImageSectionObject, sizeof(*ImageSectionObject)); */
458
459 switch(piohOptHeader->Magic)
460 {
462#ifndef _WIN64
464 DIE(("Win64 optional header, unsupported\n"));
465#else
466 // Fall through.
467#endif
469 break;
470 default:
471 DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
472 }
473
474 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SectionAlignment) &&
475 RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, FileAlignment))
476 {
477 /* See [1], section 3.4.2 */
478 if(piohOptHeader->SectionAlignment < PAGE_SIZE)
479 {
480 if(piohOptHeader->FileAlignment != piohOptHeader->SectionAlignment)
481 DIE(("Sections aren't page-aligned and the file alignment isn't the same\n"));
482 }
483 else if(piohOptHeader->SectionAlignment < piohOptHeader->FileAlignment)
484 DIE(("The section alignment is smaller than the file alignment\n"));
485
486 nSectionAlignment = piohOptHeader->SectionAlignment;
487 nFileAlignment = piohOptHeader->FileAlignment;
488
489 if(!IsPowerOf2(nSectionAlignment) || !IsPowerOf2(nFileAlignment))
490 DIE(("The section alignment (%u) and file alignment (%u) aren't both powers of 2\n", nSectionAlignment, nFileAlignment));
491 }
492 else
493 {
494 nSectionAlignment = PAGE_SIZE;
495 nFileAlignment = PAGE_SIZE;
496 }
497
498 ASSERT(IsPowerOf2(nSectionAlignment));
499 ASSERT(IsPowerOf2(nFileAlignment));
500
501 switch(piohOptHeader->Magic)
502 {
503 /* PE32 */
505 {
506 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, ImageBase))
507 ImageBase = piohOptHeader->ImageBase;
508
509 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfImage))
510 ImageSectionObject->ImageInformation.ImageFileSize = piohOptHeader->SizeOfImage;
511
512 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackReserve))
513 ImageSectionObject->ImageInformation.MaximumStackSize = piohOptHeader->SizeOfStackReserve;
514
515 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfStackCommit))
516 ImageSectionObject->ImageInformation.CommittedStackSize = piohOptHeader->SizeOfStackCommit;
517
518 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, Subsystem))
519 {
520 ImageSectionObject->ImageInformation.SubSystemType = piohOptHeader->Subsystem;
521
522 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
523 RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, MajorSubsystemVersion))
524 {
525 ImageSectionObject->ImageInformation.SubSystemMinorVersion = piohOptHeader->MinorSubsystemVersion;
526 ImageSectionObject->ImageInformation.SubSystemMajorVersion = piohOptHeader->MajorSubsystemVersion;
527 }
528 }
529
530 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
531 {
532 ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
533 piohOptHeader->AddressOfEntryPoint);
534 }
535
536 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfCode))
537 ImageSectionObject->ImageInformation.ImageContainsCode = piohOptHeader->SizeOfCode != 0;
538 else
539 ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
540
541 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
542 {
543 if (piohOptHeader->AddressOfEntryPoint == 0)
544 {
545 ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
546 }
547 }
548
549 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, LoaderFlags))
550 ImageSectionObject->ImageInformation.LoaderFlags = piohOptHeader->LoaderFlags;
551
552 if (RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, DllCharacteristics))
553 {
554 ImageSectionObject->ImageInformation.DllCharacteristics = piohOptHeader->DllCharacteristics;
555
556 /*
557 * Since we don't really implement SxS yet and LD doesn't supoprt /ALLOWISOLATION:NO, hard-code
558 * this flag here, which will prevent the loader and other code from doing any .manifest or SxS
559 * magic to any binary.
560 *
561 * This will break applications that depend on SxS when running with real Windows Kernel32/SxS/etc
562 * but honestly that's not tested. It will also break them when running no ReactOS once we implement
563 * the SxS support -- at which point, duh, this should be removed.
564 *
565 * But right now, any app depending on SxS is already broken anyway, so this flag only helps.
566 */
567 ImageSectionObject->ImageInformation.DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NO_ISOLATION;
568 }
569
570 break;
571 }
572#ifdef _WIN64
573 /* PE64 */
575 {
576 const IMAGE_OPTIONAL_HEADER64 * pioh64OptHeader;
577
578 pioh64OptHeader = (const IMAGE_OPTIONAL_HEADER64 *)piohOptHeader;
579
580 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, ImageBase))
581 {
582 ImageBase = pioh64OptHeader->ImageBase;
583 if(pioh64OptHeader->ImageBase > MAXULONG_PTR)
584 DIE(("ImageBase exceeds the address space\n"));
585 }
586
587 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfImage))
588 {
589 if(pioh64OptHeader->SizeOfImage > MAXULONG_PTR)
590 DIE(("SizeOfImage exceeds the address space\n"));
591
592 ImageSectionObject->ImageInformation.ImageFileSize = pioh64OptHeader->SizeOfImage;
593 }
594
595 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackReserve))
596 {
597 if(pioh64OptHeader->SizeOfStackReserve > MAXULONG_PTR)
598 DIE(("SizeOfStackReserve exceeds the address space\n"));
599
600 ImageSectionObject->ImageInformation.MaximumStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackReserve;
601 }
602
603 if(RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfStackCommit))
604 {
605 if(pioh64OptHeader->SizeOfStackCommit > MAXULONG_PTR)
606 DIE(("SizeOfStackCommit exceeds the address space\n"));
607
608 ImageSectionObject->ImageInformation.CommittedStackSize = (ULONG_PTR) pioh64OptHeader->SizeOfStackCommit;
609 }
610
611 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, Subsystem))
612 {
613 ImageSectionObject->ImageInformation.SubSystemType = pioh64OptHeader->Subsystem;
614
615 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MinorSubsystemVersion) &&
616 RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, MajorSubsystemVersion))
617 {
618 ImageSectionObject->ImageInformation.SubSystemMinorVersion = pioh64OptHeader->MinorSubsystemVersion;
619 ImageSectionObject->ImageInformation.SubSystemMajorVersion = pioh64OptHeader->MajorSubsystemVersion;
620 }
621 }
622
623 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
624 {
625 ImageSectionObject->ImageInformation.TransferAddress = (PVOID) (ImageBase +
626 pioh64OptHeader->AddressOfEntryPoint);
627 }
628
629 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, SizeOfCode))
630 ImageSectionObject->ImageInformation.ImageContainsCode = pioh64OptHeader->SizeOfCode != 0;
631 else
632 ImageSectionObject->ImageInformation.ImageContainsCode = TRUE;
633
634 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, AddressOfEntryPoint))
635 {
636 if (pioh64OptHeader->AddressOfEntryPoint == 0)
637 {
638 ImageSectionObject->ImageInformation.ImageContainsCode = FALSE;
639 }
640 }
641
642 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, LoaderFlags))
643 ImageSectionObject->ImageInformation.LoaderFlags = pioh64OptHeader->LoaderFlags;
644
645 if (RTL_CONTAINS_FIELD(pioh64OptHeader, cbOptHeaderSize, DllCharacteristics))
646 ImageSectionObject->ImageInformation.DllCharacteristics = pioh64OptHeader->DllCharacteristics;
647
648 break;
649 }
650#endif // _WIN64
651 }
652
653 /* [1], section 3.4.2 */
654 if((ULONG_PTR)ImageBase % 0x10000)
655 DIE(("ImageBase is not aligned on a 64KB boundary"));
656
657 ImageSectionObject->ImageInformation.ImageCharacteristics = pinhNtHeader->FileHeader.Characteristics;
658 ImageSectionObject->ImageInformation.Machine = pinhNtHeader->FileHeader.Machine;
659 ImageSectionObject->ImageInformation.GpValue = 0;
660 ImageSectionObject->ImageInformation.ZeroBits = 0;
661 ImageSectionObject->BasedAddress = (PVOID)ImageBase;
662
663 /* SECTION HEADERS */
665
666 /* see [1], section 3.3 */
667 if(pinhNtHeader->FileHeader.NumberOfSections > 96)
668 DIE(("Too many sections, NumberOfSections is %u\n", pinhNtHeader->FileHeader.NumberOfSections));
669
670 /*
671 * the additional segment is for the file's headers. They need to be present for
672 * the benefit of the dynamic loader (to locate exports, defaults for thread
673 * parameters, resources, etc.)
674 */
675 ImageSectionObject->NrSegments = pinhNtHeader->FileHeader.NumberOfSections + 1;
676
677 /* file offset for the section headers */
678 if(!Intsafe_AddULong32(&cbSectionHeadersOffset, pidhDosHeader->e_lfanew, FIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader)))
679 DIE(("Offset overflow\n"));
680
681 if(!Intsafe_AddULong32(&cbSectionHeadersOffset, cbSectionHeadersOffset, pinhNtHeader->FileHeader.SizeOfOptionalHeader))
682 DIE(("Offset overflow\n"));
683
684 /* size of the section headers */
686 cbSectionHeadersSize = pinhNtHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
687
688 if(!Intsafe_AddULong32(&cbSectionHeadersOffsetSize, cbSectionHeadersOffset, cbSectionHeadersSize))
689 DIE(("Section headers too large\n"));
690
691 /* size of the executable's headers */
692 if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, SizeOfHeaders))
693 {
694// if(!IsAligned(piohOptHeader->SizeOfHeaders, nFileAlignment))
695// DIE(("SizeOfHeaders is not aligned\n"));
696
697 if(cbSectionHeadersSize > piohOptHeader->SizeOfHeaders)
698 DIE(("The section headers overflow SizeOfHeaders\n"));
699
700 cbHeadersSize = piohOptHeader->SizeOfHeaders;
701 }
702 else if(!AlignUp(&cbHeadersSize, cbSectionHeadersOffsetSize, nFileAlignment))
703 DIE(("Overflow aligning the size of headers\n"));
704
705 if(pBuffer)
706 {
708 pBuffer = NULL;
709 }
710 /* WARNING: pinhNtHeader IS NO LONGER USABLE */
711 /* WARNING: piohOptHeader IS NO LONGER USABLE */
712 /* WARNING: pioh64OptHeader IS NO LONGER USABLE */
713
714 if(FileHeaderSize < cbSectionHeadersOffsetSize)
715 pishSectionHeaders = NULL;
716 else
717 {
718 /*
719 * we already know that Intsafe_CanOffsetPointer(FileHeader, FileHeaderSize),
720 * and FileHeaderSize >= cbSectionHeadersOffsetSize, so this holds true too
721 */
722 ASSERT(Intsafe_CanOffsetPointer(FileHeader, cbSectionHeadersOffset));
723 pishSectionHeaders = (PVOID)((UINT_PTR)FileHeader + cbSectionHeadersOffset);
724 }
725
726 /*
727 * the buffer doesn't contain the section headers, or the alignment is wrong:
728 * read the headers from the file
729 */
730 if(FileHeaderSize < cbSectionHeadersOffsetSize ||
731 (UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
732 {
733 PVOID pData;
734 ULONG cbReadSize;
735
736 lnOffset.QuadPart = cbSectionHeadersOffset;
737
738 /* read the header from the file */
739 nStatus = ReadFileCb(File, &lnOffset, cbSectionHeadersSize, &pData, &pBuffer, &cbReadSize);
740
741 if(!NT_SUCCESS(nStatus))
742 DIE(("ReadFile failed with status %08X\n", nStatus));
743
744 ASSERT(pData);
746 ASSERT(cbReadSize > 0);
747
749
750 /* the buffer doesn't contain all the section headers */
751 if(cbReadSize < cbSectionHeadersSize)
752 DIE(("The file doesn't contain all of the section headers\n"));
753
754 pishSectionHeaders = pData;
755
756 /* object still not aligned: copy it to the beginning of the buffer */
757 if((UINT_PTR)pishSectionHeaders % TYPE_ALIGNMENT(IMAGE_SECTION_HEADER) != 0)
758 {
760 RtlMoveMemory(pBuffer, pData, cbReadSize);
761 pishSectionHeaders = pBuffer;
762 }
763 }
764
765 /* SEGMENTS */
766 /* allocate the segments */
768 ImageSectionObject->Segments = AllocateSegmentsCb(ImageSectionObject->NrSegments);
769
770 if(ImageSectionObject->Segments == NULL)
771 DIE(("AllocateSegments failed\n"));
772
773 /* initialize the headers segment */
774 pssSegments = ImageSectionObject->Segments;
775
776// ASSERT(IsAligned(cbHeadersSize, nFileAlignment));
777
778 if(!AlignUp(&nFileSizeOfHeaders, cbHeadersSize, nFileAlignment))
779 DIE(("Cannot align the size of the section headers\n"));
780
781 nPrevVirtualEndOfSegment = ALIGN_UP_BY(cbHeadersSize, nSectionAlignment);
782 if (nPrevVirtualEndOfSegment < cbHeadersSize)
783 DIE(("Cannot align the size of the section headers\n"));
784
785 pssSegments[0].Image.FileOffset = 0;
786 pssSegments[0].Protection = PAGE_READONLY;
787 pssSegments[0].Length.QuadPart = nPrevVirtualEndOfSegment;
788 pssSegments[0].RawLength.QuadPart = nFileSizeOfHeaders;
789 pssSegments[0].Image.VirtualAddress = 0;
790 pssSegments[0].Image.Characteristics = 0;
791 pssSegments[0].WriteCopy = TRUE;
792
793 /* skip the headers segment */
794 ++ pssSegments;
795
797
798 ASSERT(ImageSectionObject->RefCount > 0);
799
800 /* convert the executable sections into segments. See also [1], section 4 */
801 for(i = 0; i < ImageSectionObject->NrSegments - 1; ++ i)
802 {
803 ULONG nCharacteristics;
804
805 /* validate the alignment */
806 if(!IsAligned(pishSectionHeaders[i].VirtualAddress, nSectionAlignment))
807 DIE(("Image.VirtualAddress[%u] is not aligned\n", i));
808
809 /* sections must be contiguous, ordered by base address and non-overlapping */
810 if(pishSectionHeaders[i].VirtualAddress != nPrevVirtualEndOfSegment)
811 DIE(("Memory gap between section %u and the previous\n", i));
812
813 /* ignore explicit BSS sections */
814 if(pishSectionHeaders[i].PointerToRawData != 0 && pishSectionHeaders[i].SizeOfRawData != 0)
815 {
816 /* validate the alignment */
817#if 0
818 /* Yes, this should be a multiple of FileAlignment, but there's
819 * stuff out there that isn't. We can cope with that
820 */
821 if(!IsAligned(pishSectionHeaders[i].SizeOfRawData, nFileAlignment))
822 DIE(("SizeOfRawData[%u] is not aligned\n", i));
823#endif
824
825// if(!IsAligned(pishSectionHeaders[i].PointerToRawData, nFileAlignment))
826// DIE(("PointerToRawData[%u] is not aligned\n", i));
827
828 if(!Intsafe_CanAddULong32(pishSectionHeaders[i].PointerToRawData, pishSectionHeaders[i].SizeOfRawData))
829 DIE(("SizeOfRawData[%u] too large\n", i));
830
831 /* conversion */
832 pssSegments[i].Image.FileOffset = pishSectionHeaders[i].PointerToRawData;
833 pssSegments[i].RawLength.QuadPart = pishSectionHeaders[i].SizeOfRawData;
834 }
835 else
836 {
837 /* FIXME: Should reset PointerToRawData to 0 in the image mapping */
838 ASSERT(pssSegments[i].Image.FileOffset == 0);
839 ASSERT(pssSegments[i].RawLength.QuadPart == 0);
840 }
841
842 ASSERT(Intsafe_CanAddLong64(pssSegments[i].Image.FileOffset, pssSegments[i].RawLength.QuadPart));
843
844 nCharacteristics = pishSectionHeaders[i].Characteristics;
845
846 /* no explicit protection */
847 if((nCharacteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)) == 0)
848 {
849 if(nCharacteristics & IMAGE_SCN_CNT_CODE)
850 nCharacteristics |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;
851
852 if(nCharacteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
853 nCharacteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
854
855 if(nCharacteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
856 nCharacteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
857 }
858
859 /* see table above */
860 pssSegments[i].Protection = SectionCharacteristicsToProtect[nCharacteristics >> 28];
861 pssSegments[i].WriteCopy = !(nCharacteristics & IMAGE_SCN_MEM_SHARED);
862
863 if(pishSectionHeaders[i].Misc.VirtualSize == 0)
864 pssSegments[i].Length.QuadPart = pishSectionHeaders[i].SizeOfRawData;
865 else
866 pssSegments[i].Length.QuadPart = pishSectionHeaders[i].Misc.VirtualSize;
867
868 AlignedLength = ALIGN_UP_BY(pssSegments[i].Length.LowPart, nSectionAlignment);
869 if(AlignedLength < pssSegments[i].Length.LowPart)
870 DIE(("Cannot align the virtual size of section %u\n", i));
871
872 pssSegments[i].Length.LowPart = AlignedLength;
873
874 if(pssSegments[i].Length.QuadPart == 0)
875 DIE(("Virtual size of section %u is null\n", i));
876
877 pssSegments[i].Image.VirtualAddress = pishSectionHeaders[i].VirtualAddress;
878 pssSegments[i].Image.Characteristics = pishSectionHeaders[i].Characteristics;
879
880 /* ensure the memory image is no larger than 4GB */
881 nPrevVirtualEndOfSegment = (ULONG_PTR)(pssSegments[i].Image.VirtualAddress + pssSegments[i].Length.QuadPart);
882 if (nPrevVirtualEndOfSegment < pssSegments[i].Image.VirtualAddress)
883 DIE(("The image is too large\n"));
884 }
885
886 if(nSectionAlignment >= PAGE_SIZE)
888
889 /* Success */
890 nStatus = STATUS_SUCCESS;// STATUS_ROS_EXEFMT_LOADED_FORMAT | EXEFMT_LOADED_PE32;
891
892l_Return:
893 if(pBuffer)
895
896 return nStatus;
897}
898
899/*
900 * FUNCTION: Waits in kernel mode indefinitely for a file object lock.
901 * ARGUMENTS: PFILE_OBJECT to wait for.
902 * RETURNS: Status of the wait.
903 */
906{
907 return STATUS_SUCCESS;
908 //return KeWaitForSingleObject(&File->Lock, 0, KernelMode, FALSE, NULL);
909}
910
911
912
913VOID
914NTAPI
916{
920 SWAPENTRY SavedSwapEntry;
922
923 Page = 0;
924
926
927 Length = PAGE_ROUND_UP(Segment->Length.QuadPart);
928 for (Offset.QuadPart = 0; Offset.QuadPart < Length; Offset.QuadPart += PAGE_SIZE)
929 {
931 if (Entry)
932 {
935 {
937 }
938 else
939 {
941 SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
942 if (SavedSwapEntry != 0)
943 {
945 MmFreeSwapPage(SavedSwapEntry);
946 }
948 }
949 }
950 }
951
953}
954
955static
956VOID
957NTAPI
959{
962
964
966
968
969 /* This must be either a valid entry or nothing */
971
972 /* There should be no reference anymore */
974
976 /* If there is a page, this must be because it's still dirty */
977 ASSERT(Page != 0);
978
979 /* Write the page */
980 if (IS_DIRTY_SSE(Entry))
981 MiWritePage(Segment, Offset->QuadPart, Page);
982
984}
985
991VOID
992NTAPI
993MmDereferenceSegmentWithLock(
996{
997 /* Lock the PFN lock because we mess around with SectionObjectPointers */
998 if (OldIrql == MM_NOIRQL)
999 {
1000 OldIrql = MiAcquirePfnLock();
1001 }
1002
1003 if (InterlockedDecrement64(Segment->ReferenceCount) > 0)
1004 {
1005 /* Nothing to do yet */
1006 MiReleasePfnLock(OldIrql);
1007 return;
1008 }
1009
1010 *Segment->Flags |= MM_SEGMENT_INDELETE;
1011
1012 /* Flush the segment */
1013 if (*Segment->Flags & MM_DATAFILE_SEGMENT)
1014 {
1015 MiReleasePfnLock(OldIrql);
1016 /* Free the page table. This will flush any remaining dirty data */
1018
1019 OldIrql = MiAcquirePfnLock();
1020 /* Delete the pointer on the file */
1021 ASSERT(Segment->FileObject->SectionObjectPointer->DataSectionObject == Segment);
1022 Segment->FileObject->SectionObjectPointer->DataSectionObject = NULL;
1023 MiReleasePfnLock(OldIrql);
1024 ObDereferenceObject(Segment->FileObject);
1025
1027 }
1028 else
1029 {
1030 /* Most grotesque thing ever */
1031 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = CONTAINING_RECORD(Segment->ReferenceCount, MM_IMAGE_SECTION_OBJECT, RefCount);
1032 PMM_SECTION_SEGMENT SectionSegments;
1033 ULONG NrSegments;
1034 ULONG i;
1035
1036 /* Delete the pointer on the file */
1037 ASSERT(ImageSectionObject->FileObject->SectionObjectPointer->ImageSectionObject == ImageSectionObject);
1038 ImageSectionObject->FileObject->SectionObjectPointer->ImageSectionObject = NULL;
1039 MiReleasePfnLock(OldIrql);
1040
1041 ObDereferenceObject(ImageSectionObject->FileObject);
1042
1043 NrSegments = ImageSectionObject->NrSegments;
1044 SectionSegments = ImageSectionObject->Segments;
1045 for (i = 0; i < NrSegments; i++)
1046 {
1047 if (SectionSegments[i].Image.Characteristics & IMAGE_SCN_MEM_SHARED)
1048 {
1049 MmpFreePageFileSegment(&SectionSegments[i]);
1050 }
1051
1052 MmFreePageTablesSectionSegment(&SectionSegments[i], NULL);
1053 }
1054
1056 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
1057 }
1058}
1059
1060VOID
1061NTAPI
1064{
1066
1068 if (Entry == 0)
1069 {
1070 DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
1071 KeBugCheck(MEMORY_MANAGEMENT);
1072 }
1074 {
1075 DPRINT1("Maximum share count reached\n");
1076 KeBugCheck(MEMORY_MANAGEMENT);
1077 }
1079 {
1080 KeBugCheck(MEMORY_MANAGEMENT);
1081 }
1083}
1084
1085BOOLEAN
1086NTAPI
1090 BOOLEAN Dirty,
1092 ULONG_PTR *InEntry)
1093{
1096 BOOLEAN IsDataMap = BooleanFlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT);
1097 SWAPENTRY SwapEntry;
1098
1099 if (Entry == 0)
1100 {
1101 DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
1102 KeBugCheck(MEMORY_MANAGEMENT);
1103 }
1104 if (SHARE_COUNT_FROM_SSE(Entry) == 0)
1105 {
1106 DPRINT1("Zero share count for unshare (Seg %p Offset %x Page %x)\n", Segment, Offset->LowPart, PFN_FROM_SSE(Entry));
1107 KeBugCheck(MEMORY_MANAGEMENT);
1108 }
1110 {
1111 KeBugCheck(MEMORY_MANAGEMENT);
1112 }
1114 if (Dirty) Entry = DIRTY_SSE(Entry);
1115
1116 /* If we are paging-out, pruning the page for real will be taken care of in MmCheckDirtySegment */
1117 if ((SHARE_COUNT_FROM_SSE(Entry) > 0) || PageOut)
1118 {
1119 /* Update the page mapping in the segment and we're done */
1121 return FALSE;
1122 }
1123
1124 /* We are pruning the last mapping on this page. See if we can keep it a bit more. */
1125 ASSERT(!PageOut);
1126
1127 if (IsDataMap)
1128 {
1129 /* We can always keep memory in for data maps */
1131 return FALSE;
1132 }
1133
1134 if (!FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED))
1135 {
1136 ASSERT(Segment->WriteCopy);
1139 /* So this must have been a read-only page. Keep it ! */
1141 return FALSE;
1142 }
1143
1144 /*
1145 * So this is a page for a shared section of a DLL.
1146 * We can keep it if it is not dirty.
1147 */
1148 SwapEntry = MmGetSavedSwapEntryPage(Page);
1149 if ((SwapEntry == 0) && !IS_DIRTY_SSE(Entry))
1150 {
1152 return FALSE;
1153 }
1154
1155 /* No more processes are referencing this shared dirty page. Ditch it. */
1156 if (SwapEntry)
1157 {
1159 MmFreeSwapPage(SwapEntry);
1160 }
1163 return TRUE;
1164}
1165
1166static
1168MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
1169{
1171 KIRQL Irql;
1172 PVOID DestAddress;
1173
1175 DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
1176 if (DestAddress == NULL)
1177 {
1178 return STATUS_NO_MEMORY;
1179 }
1180 ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
1181 ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
1182 RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
1183 MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
1184 return STATUS_SUCCESS;
1185}
1186
1187static
1189NTAPI
1194 _In_opt_ PLARGE_INTEGER ValidDataLength,
1195 _In_ BOOLEAN SetDirty)
1196{
1197 /* Let's use a 64K granularity. */
1198 LONGLONG RangeStart, RangeEnd;
1200 PFILE_OBJECT FileObject = Segment->FileObject;
1201
1202 /* Calculate our range, aligned on 64K if possible. */
1203 Status = RtlLongLongAdd(Offset, Length, &RangeEnd);
1205 if (!NT_SUCCESS(Status))
1206 return Status;
1207
1208 /* If the file is not random access and we are not the page out thread
1209 * read a 64K Chunk. */
1211 && !FlagOn(FileObject->Flags, FO_RANDOM_ACCESS))
1212 {
1213 RangeStart = Offset - (Offset % _64K);
1214 if (RangeEnd % _64K)
1215 RangeEnd += _64K - (RangeEnd % _64K);
1216 }
1217 else
1218 {
1219 RangeStart = Offset - (Offset % PAGE_SIZE);
1220 if (RangeEnd % PAGE_SIZE)
1221 RangeEnd += PAGE_SIZE - (RangeEnd % PAGE_SIZE);
1222 }
1223
1224 /* Clamp if needed */
1225 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
1226 {
1227 if (RangeEnd > Segment->RawLength.QuadPart)
1228 RangeEnd = Segment->RawLength.QuadPart;
1229 }
1230
1231 /* Let's gooooooooo */
1232 for ( ; RangeStart < RangeEnd; RangeStart += _64K)
1233 {
1234 /* First take a look at where we miss pages */
1235 ULONG ToReadPageBits = 0;
1236 LONGLONG ChunkEnd = RangeStart + _64K;
1237
1238 if (ChunkEnd > RangeEnd)
1239 ChunkEnd = RangeEnd;
1240
1242 for (LONGLONG ChunkOffset = RangeStart; ChunkOffset < ChunkEnd; ChunkOffset += PAGE_SIZE)
1243 {
1244 LARGE_INTEGER CurrentOffset;
1245
1246 CurrentOffset.QuadPart = ChunkOffset;
1248
1249 /* Let any pending read proceed */
1250 while (MM_IS_WAIT_PTE(Entry))
1251 {
1253
1255
1257 Entry = MmGetPageEntrySectionSegment(Segment, &CurrentOffset);
1258 }
1259
1260 if (Entry != 0)
1261 {
1262 /* Dirtify it if it's a resident page and we're asked to */
1263 if (SetDirty && !IS_SWAP_FROM_SSE(Entry))
1264 {
1266 }
1267 continue;
1268 }
1269
1270 ToReadPageBits |= 1UL << ((ChunkOffset - RangeStart) >> PAGE_SHIFT);
1271
1272 /* Put a wait entry here */
1273 Status = MmSetPageEntrySectionSegment(Segment, &CurrentOffset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
1274 if (!NT_SUCCESS(Status))
1275 {
1276 /* Failed, roll back! */
1277 DPRINT1("Failed to set wait entry for segment %p at offset %I64d\n", Segment, ChunkOffset);
1278 LARGE_INTEGER RollbackOffset;
1279 RollbackOffset.QuadPart = ChunkOffset;
1280 while (RollbackOffset.QuadPart > RangeStart)
1281 {
1282 RollbackOffset.QuadPart -= PAGE_SIZE;
1284 {
1286 }
1287 }
1288
1290 return Status;
1291 }
1293 }
1295
1296 if (ToReadPageBits == 0)
1297 {
1298 /* Nothing to do for this chunk */
1299 continue;
1300 }
1301
1302 /* Now perform the actual read */
1303 LONGLONG ChunkOffset = RangeStart;
1304 while (ChunkOffset < ChunkEnd)
1305 {
1306 /* Move forward if there is a hole */
1307 ULONG BitSet;
1308 if (!_BitScanForward(&BitSet, ToReadPageBits))
1309 {
1310 /* Nothing more to read */
1311 break;
1312 }
1313 ToReadPageBits >>= BitSet;
1314 ChunkOffset += BitSet * PAGE_SIZE;
1315 ASSERT(ChunkOffset < ChunkEnd);
1316
1317 /* Get the range we have to read */
1318 _BitScanForward(&BitSet, ~ToReadPageBits);
1319 ULONG ReadLength = BitSet * PAGE_SIZE;
1320
1322
1323 /* Clamp (This is for image mappings */
1324 if ((ChunkOffset + ReadLength) > ChunkEnd)
1325 ReadLength = ChunkEnd - ChunkOffset;
1326
1327 ASSERT(ReadLength != 0);
1328
1329 /* Allocate a MDL */
1331 if (!Mdl)
1332 {
1333 /* Damn. Roll-back. */
1335 while (ChunkOffset < ChunkEnd)
1336 {
1337 if (ToReadPageBits & 1)
1338 {
1339 LARGE_INTEGER CurrentOffset;
1340 CurrentOffset.QuadPart = ChunkOffset;
1342 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, 0);
1343 }
1344 ToReadPageBits >>= 1;
1345 ChunkOffset += PAGE_SIZE;
1346 }
1349 }
1350
1351 /* Get our pages */
1354 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1355 {
1357 if (!NT_SUCCESS(Status))
1358 {
1359 /* Damn. Roll-back. */
1360 for (UINT j = 0; j < i; j++)
1362 goto Failed;
1363 }
1364 }
1365
1366 Mdl->MdlFlags |= MDL_PAGES_LOCKED | MDL_IO_PAGE_READ;
1367
1369 FileOffset.QuadPart = Segment->Image.FileOffset + ChunkOffset;
1370
1371 /* Clamp to VDL */
1372 if (ValidDataLength && ((FileOffset.QuadPart + ReadLength) > ValidDataLength->QuadPart))
1373 {
1374 if (FileOffset.QuadPart > ValidDataLength->QuadPart)
1375 {
1376 /* Great, nothing to read. */
1377 goto AssignPagesToSegment;
1378 }
1379
1380 Mdl->Size = (FileOffset.QuadPart + ReadLength) - ValidDataLength->QuadPart;
1381 }
1382
1383 KEVENT Event;
1385
1386 /* Disable APCs */
1387 KIRQL OldIrql;
1389
1392 if (Status == STATUS_PENDING)
1393 {
1395 Status = Iosb.Status;
1396 }
1397
1398 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
1399 {
1400 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
1401 }
1402
1404
1406 {
1407 DPRINT1("Got STATUS_END_OF_FILE at offset %I64d for file %wZ.\n", FileOffset.QuadPart, &FileObject->FileName);
1409 }
1410
1411 if (!NT_SUCCESS(Status))
1412 {
1413 /* Damn. Roll back. */
1414 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1416
1417Failed:
1419 while (ChunkOffset < ChunkEnd)
1420 {
1421 if (ToReadPageBits & 1)
1422 {
1423 LARGE_INTEGER CurrentOffset;
1424 CurrentOffset.QuadPart = ChunkOffset;
1426 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, 0);
1427 }
1428 ToReadPageBits >>= 1;
1429 ChunkOffset += PAGE_SIZE;
1430 }
1432 IoFreeMdl(Mdl);;
1433 return Status;
1434 }
1435
1436AssignPagesToSegment:
1438
1439 for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
1440 {
1441 ULONG_PTR Entry = MAKE_SSE(Pages[i] << PAGE_SHIFT, 0);
1442 LARGE_INTEGER CurrentOffset;
1443 CurrentOffset.QuadPart = ChunkOffset + (i * PAGE_SIZE);
1444
1446
1447 if (SetDirty)
1449
1450 MmSetPageEntrySectionSegment(Segment, &CurrentOffset, Entry);
1451 }
1452
1454
1455 IoFreeMdl(Mdl);
1456 ToReadPageBits >>= BitSet;
1457 ChunkOffset += BitSet * PAGE_SIZE;
1458 }
1459 }
1460
1461 return STATUS_SUCCESS;
1462}
1463
1464static VOID
1468 ULONG OldType,
1469 ULONG OldProtect,
1470 ULONG NewType,
1472{
1475 BOOLEAN DoCOW = FALSE;
1476 ULONG i;
1478
1481 Segment = MemoryArea->SectionData.Segment;
1483
1484 if ((Segment->WriteCopy) &&
1486 {
1487 DoCOW = TRUE;
1488 }
1489
1490 if (OldProtect != NewProtect)
1491 {
1492 for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
1493 {
1494 SWAPENTRY SwapEntry;
1495 PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
1497
1498 /* Wait for a wait entry to disappear */
1499 do
1500 {
1501 MmGetPageFileMapping(Process, Address, &SwapEntry);
1502 if (SwapEntry != MM_WAIT_ENTRY)
1503 break;
1509 }
1510 while (TRUE);
1511
1512 /*
1513 * If we doing COW for this segment then check if the page is
1514 * already private.
1515 */
1517 {
1521
1523 + MemoryArea->SectionData.ViewOffset;
1525 /*
1526 * An MM_WAIT_ENTRY is ok in this case... It'll just count as
1527 * IS_SWAP_FROM_SSE and we'll do the right thing.
1528 */
1530
1531 /* Choose protection based on what was requested */
1534 else
1536
1538 {
1540 }
1541 }
1542
1544 {
1546 Protect);
1547 }
1548 }
1549 }
1550
1552}
1553
1555NTAPI
1558 PVOID Address,
1560{
1566 ULONG_PTR Entry1;
1569 BOOLEAN HasSwapEntry;
1570 PVOID PAddress;
1572 SWAPENTRY SwapEntry;
1573
1574 ASSERT(Locked);
1575
1576 /*
1577 * There is a window between taking the page fault and locking the
1578 * address space when another thread could load the page so we check
1579 * that.
1580 */
1582 {
1583 return STATUS_SUCCESS;
1584 }
1585
1587 {
1589 }
1590
1591 /*
1592 * Check for the virtual memory area being deleted.
1593 */
1595 {
1596 return STATUS_UNSUCCESSFUL;
1597 }
1598
1599 PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
1600 Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
1601 + MemoryArea->SectionData.ViewOffset;
1602
1603 Segment = MemoryArea->SectionData.Segment;
1605 &MemoryArea->SectionData.RegionListHead,
1606 Address, NULL);
1607 ASSERT(Region != NULL);
1608
1609 /* Check for a NOACCESS mapping */
1610 if (Region->Protect & PAGE_NOACCESS)
1611 {
1613 }
1614
1615 if (Region->Protect & PAGE_GUARD)
1616 {
1617 /* Remove it */
1619 &MemoryArea->SectionData.RegionListHead,
1620 Address, PAGE_SIZE, Region->Type, Region->Protect & ~PAGE_GUARD,
1622
1623 if (!NT_SUCCESS(Status))
1624 {
1625 DPRINT1("Removing PAGE_GUARD protection failed : 0x%08x.\n", Status);
1626 }
1627
1629 }
1630
1631 HasSwapEntry = MmIsPageSwapEntry(Process, Address);
1632
1633 /* See if we should use a private page */
1634 if (HasSwapEntry)
1635 {
1636 SWAPENTRY DummyEntry;
1637
1638 MmGetPageFileMapping(Process, Address, &SwapEntry);
1639 if (SwapEntry == MM_WAIT_ENTRY)
1640 {
1645 }
1646
1648 if (Process) MI_SET_PROCESS2(Process->ImageFileName);
1649 if (!Process) MI_SET_PROCESS2("Kernel Section");
1651 if (!NT_SUCCESS(Status))
1652 {
1653 return STATUS_NO_MEMORY;
1654 }
1655
1656 /*
1657 * Must be private page we have swapped out.
1658 */
1659
1660 /*
1661 * Sanity check
1662 */
1664 ASSERT(DummyEntry == SwapEntry);
1665
1666 /* Tell everyone else we are serving the fault. */
1667 MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
1668
1670
1671 Status = MmReadFromSwapPage(SwapEntry, Page);
1672 if (!NT_SUCCESS(Status))
1673 {
1674 DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
1675 KeBugCheck(MEMORY_MANAGEMENT);
1676 }
1677
1679 MmDeletePageFileMapping(Process, PAddress, &DummyEntry);
1680 ASSERT(DummyEntry == MM_WAIT_ENTRY);
1681
1683 PAddress,
1684 Region->Protect,
1685 Page);
1686 if (!NT_SUCCESS(Status))
1687 {
1688 DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
1689 KeBugCheck(MEMORY_MANAGEMENT);
1690 return Status;
1691 }
1692
1693 /*
1694 * Store the swap entry for later use.
1695 */
1696 MmSetSavedSwapEntryPage(Page, SwapEntry);
1697
1698 /*
1699 * Add the page to the process's working set
1700 */
1702 /*
1703 * Finish the operation
1704 */
1705 DPRINT("Address 0x%p\n", Address);
1706 return STATUS_SUCCESS;
1707 }
1708
1709 /*
1710 * Lock the segment
1711 */
1713
1714 /*
1715 * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
1716 */
1717 if ((*Segment->Flags) & MM_PHYSICALMEMORY_SEGMENT)
1718 {
1720 /*
1721 * Just map the desired physical page
1722 */
1723 Page = (PFN_NUMBER)(Offset.QuadPart >> PAGE_SHIFT);
1725 PAddress,
1726 Region->Protect,
1727 Page);
1728 if (!NT_SUCCESS(Status))
1729 {
1730 DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
1731 KeBugCheck(MEMORY_MANAGEMENT);
1732 return Status;
1733 }
1734
1735 /*
1736 * Cleanup and release locks
1737 */
1738 DPRINT("Address 0x%p\n", Address);
1739 return STATUS_SUCCESS;
1740 }
1741
1742 /*
1743 * Check if this page needs to be mapped COW
1744 */
1745 if ((Segment->WriteCopy) &&
1746 (Region->Protect == PAGE_READWRITE || Region->Protect == PAGE_EXECUTE_READWRITE))
1747 {
1749 }
1750 else
1751 {
1752 Attributes = Region->Protect;
1753 }
1754
1755
1756 /*
1757 * Get the entry corresponding to the offset within the section
1758 */
1760 if (Entry == 0)
1761 {
1762 /*
1763 * If the entry is zero, then we need to load the page.
1764 */
1765 if ((Offset.QuadPart >= (LONGLONG)PAGE_ROUND_UP(Segment->RawLength.QuadPart)) && (MemoryArea->VadNode.u.VadFlags.VadType == VadImageMap))
1766 {
1767 /* We are beyond the data which is on file. Just get a new page. */
1769 if (Process) MI_SET_PROCESS2(Process->ImageFileName);
1770 if (!Process) MI_SET_PROCESS2("Kernel Section");
1772 if (!NT_SUCCESS(Status))
1773 {
1775 return STATUS_NO_MEMORY;
1776 }
1779
1781 if (!NT_SUCCESS(Status))
1782 {
1783 DPRINT1("Unable to create virtual mapping\n");
1784 KeBugCheck(MEMORY_MANAGEMENT);
1785 }
1786 ASSERT(MmIsPagePresent(Process, PAddress));
1787 if (Process)
1789
1790 DPRINT("Address 0x%p\n", Address);
1791 return STATUS_SUCCESS;
1792 }
1793
1796
1797 /* The data must be paged in. Lock the file, so that the VDL doesn't get updated behind us. */
1799
1800 PFSRTL_COMMON_FCB_HEADER FcbHeader = Segment->FileObject->FsContext;
1801
1803
1804 FsRtlReleaseFile(Segment->FileObject);
1805
1806 /* Lock address space again */
1808 if (!NT_SUCCESS(Status))
1809 {
1810 if (Status == STATUS_NO_MEMORY)
1811 {
1812 return Status;
1813 }
1814 /* Damn */
1815 DPRINT1("Failed to page data in!\n");
1816 return STATUS_IN_PAGE_ERROR;
1817 }
1818
1819 /* Everything went fine. Restart the operation */
1821 }
1822 else if (IS_SWAP_FROM_SSE(Entry))
1823 {
1824 SWAPENTRY SwapEntry;
1825
1826 SwapEntry = SWAPENTRY_FROM_SSE(Entry);
1827
1828 /* See if a page op is running on this segment. */
1829 if (SwapEntry == MM_WAIT_ENTRY)
1830 {
1836 }
1837
1839 if (!NT_SUCCESS(Status))
1840 {
1842 return STATUS_NO_MEMORY;
1843 }
1844
1845 /*
1846 * Release all our locks and read in the page from disk
1847 */
1850
1852
1853 Status = MmReadFromSwapPage(SwapEntry, Page);
1854 if (!NT_SUCCESS(Status))
1855 {
1856 KeBugCheck(MEMORY_MANAGEMENT);
1857 }
1858
1859 /*
1860 * Relock the address space and segment
1861 */
1864
1865 /*
1866 * Check the entry. No one should change the status of a page
1867 * that has a pending page-in.
1868 */
1870 if (Entry1 != MAKE_SWAP_SSE(MM_WAIT_ENTRY))
1871 {
1872 DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
1873 KeBugCheck(MEMORY_MANAGEMENT);
1874 }
1875
1876 /*
1877 * Save the swap entry.
1878 */
1879 MmSetSavedSwapEntryPage(Page, SwapEntry);
1880
1881 /* Map the page into the process address space */
1883 PAddress,
1884 Attributes,
1885 Page);
1886 if (!NT_SUCCESS(Status))
1887 {
1888 DPRINT1("Unable to create virtual mapping\n");
1889 KeBugCheck(MEMORY_MANAGEMENT);
1890 }
1891 if (Process)
1893
1894 /*
1895 * Mark the offset within the section as having valid, in-memory
1896 * data
1897 */
1898 Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
1901
1902 DPRINT("Address 0x%p\n", Address);
1903 return STATUS_SUCCESS;
1904 }
1905 else
1906 {
1907 /* We already have a page on this section offset. Map it into the process address space. */
1909
1911 PAddress,
1912 Attributes,
1913 Page);
1914 if (!NT_SUCCESS(Status))
1915 {
1916 DPRINT1("Unable to create virtual mapping\n");
1917 KeBugCheck(MEMORY_MANAGEMENT);
1918 }
1919
1920 if (Process)
1922
1923 /* Take a reference on it */
1926
1927 DPRINT("Address 0x%p\n", Address);
1928 return STATUS_SUCCESS;
1929 }
1930}
1931
1933NTAPI
1936 PVOID Address,
1938{
1940 PFN_NUMBER OldPage;
1941 PFN_NUMBER NewPage;
1942 PFN_NUMBER UnmappedPage;
1943 PVOID PAddress;
1948 BOOLEAN Cow = FALSE;
1950 BOOLEAN Unmapped;
1952
1953 DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
1954
1955 /* Get the region for this address */
1957 &MemoryArea->SectionData.RegionListHead,
1958 Address, NULL);
1959 ASSERT(Region != NULL);
1960 if (!(Region->Protect & PAGE_IS_WRITABLE))
1962
1963 /* Make sure we have a page mapping for this address. */
1965 {
1967 if (!NT_SUCCESS(Status))
1968 {
1969 /* This is invalid access ! */
1970 return Status;
1971 }
1972 }
1973
1974 /*
1975 * Check if the page has already been set readwrite
1976 */
1978 {
1979 DPRINT("Address 0x%p\n", Address);
1980 return STATUS_SUCCESS;
1981 }
1982
1983 /* Check if we are doing Copy-On-Write */
1984 Segment = MemoryArea->SectionData.Segment;
1985 Cow = Segment->WriteCopy || (Region->Protect & PAGE_IS_WRITECOPY);
1986
1987 if (!Cow)
1988 {
1989 /* Simply update page protection and we're done */
1991 return STATUS_SUCCESS;
1992 }
1993
1994 /* Calculate the new protection & check if we should update the region */
1995 NewProtect = Region->Protect;
1997 {
1998 NewProtect &= ~PAGE_IS_WRITECOPY;
1999 if (Region->Protect & PAGE_IS_EXECUTABLE)
2001 else
2004 &MemoryArea->SectionData.RegionListHead,
2007 }
2008
2009 /*
2010 * Find the offset of the page
2011 */
2012 PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
2013 Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
2014 + MemoryArea->SectionData.ViewOffset;
2015
2016 /* Get the page mapping this section offset. */
2019
2020 /* Get the current page mapping for the process */
2021 ASSERT(MmIsPagePresent(Process, PAddress));
2022 OldPage = MmGetPfnForProcess(Process, PAddress);
2023 ASSERT(OldPage != 0);
2024
2025 if (IS_SWAP_FROM_SSE(Entry) ||
2026 PFN_FROM_SSE(Entry) != OldPage)
2027 {
2029 /* This is a private page. We must only change the page protection. */
2031 return STATUS_SUCCESS;
2032 }
2033
2034 /*
2035 * Allocate a page
2036 */
2038 if (!NT_SUCCESS(Status))
2039 {
2041 return STATUS_NO_MEMORY;
2042 }
2043
2044 /*
2045 * Copy the old page
2046 */
2047 NT_VERIFY(NT_SUCCESS(MiCopyFromUserPage(NewPage, PAddress)));
2048
2049 /*
2050 * Unshare the old page.
2051 */
2052 DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
2053 Unmapped = MmDeleteVirtualMapping(Process, PAddress, NULL, &UnmappedPage);
2054 if (!Unmapped || (UnmappedPage != OldPage))
2055 {
2056 /* Uh , we had a page just before, but suddenly it changes. Someone corrupted us. */
2057 KeBugCheckEx(MEMORY_MANAGEMENT,
2059 (ULONG_PTR)PAddress,
2060 (ULONG_PTR)__FILE__,
2061 __LINE__);
2062 }
2063
2064 if (Process)
2065 MmDeleteRmap(OldPage, Process, PAddress);
2068
2069 /*
2070 * Set the PTE to point to the new page
2071 */
2072 if (!NT_SUCCESS(MmCreateVirtualMapping(Process, PAddress, NewProtect, NewPage)))
2073 {
2074 DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
2075 KeBugCheck(MEMORY_MANAGEMENT);
2076 }
2077
2078 if (Process)
2079 MmInsertRmap(NewPage, Process, PAddress);
2080
2081 DPRINT("Address 0x%p\n", Address);
2082 return STATUS_SUCCESS;
2083}
2084
2086NTAPI
2090 SIZE_T Length,
2091 ULONG Protect,
2092 PULONG OldProtect)
2093{
2096 ULONG_PTR MaxLength;
2097
2099
2101 {
2102 return STATUS_UNSUCCESSFUL;
2103 }
2104
2106 if (Length > MaxLength)
2107 Length = (ULONG)MaxLength;
2108
2110 &MemoryArea->SectionData.RegionListHead,
2111 BaseAddress, NULL);
2112 ASSERT(Region != NULL);
2113
2114 if ((MemoryArea->Flags & SEC_NO_CHANGE) &&
2115 Region->Protect != Protect)
2116 {
2118 }
2119
2120 if (OldProtect != NULL)
2121 *OldProtect = Region->Protect;
2123 &MemoryArea->SectionData.RegionListHead,
2126
2127 return Status;
2128}
2129
2132 PVOID Address,
2135{
2137 PVOID RegionBaseAddress;
2139
2141 &MemoryArea->SectionData.RegionListHead,
2142 Address, &RegionBaseAddress);
2143 if (Region == NULL)
2144 {
2145 return STATUS_UNSUCCESSFUL;
2146 }
2147
2149 {
2150 Segment = MemoryArea->SectionData.Segment;
2151 Info->AllocationBase = (PUCHAR)MA_GetStartingAddress(MemoryArea) - Segment->Image.VirtualAddress;
2152 Info->Type = MEM_IMAGE;
2153 }
2154 else
2155 {
2156 Info->AllocationBase = (PVOID)MA_GetStartingAddress(MemoryArea);
2157 Info->Type = MEM_MAPPED;
2158 }
2159 Info->BaseAddress = RegionBaseAddress;
2161 Info->RegionSize = Region->Length;
2162 Info->State = MEM_COMMIT;
2163 Info->Protect = Region->Protect;
2164
2166 return STATUS_SUCCESS;
2167}
2168
2169VOID NTAPI
2171{
2172 PSECTION Section = ObjectBody;
2173
2174 /* Check if it's an ARM3, or ReactOS section */
2175 if (!MiIsRosSectionObject(Section))
2176 {
2177 MiDeleteARM3Section(ObjectBody);
2178 return;
2179 }
2180
2181 DPRINT("MmpDeleteSection(ObjectBody %p)\n", ObjectBody);
2182 if (Section->u.Flags.Image)
2183 {
2184 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT)Section->Segment;
2185
2186 /*
2187 * NOTE: Section->ImageSection can be NULL for short time
2188 * during the section creating. If we fail for some reason
2189 * until the image section is properly initialized we shouldn't
2190 * process further here.
2191 */
2192 if (Section->Segment == NULL)
2193 return;
2194
2195 KIRQL OldIrql = MiAcquirePfnLock();
2196 ImageSectionObject->SectionCount--;
2197
2198 /* We just dereference the first segment */
2199 ASSERT(ImageSectionObject->RefCount > 0);
2200 /* MmDereferenceSegmentWithLock releases PFN lock */
2201 MmDereferenceSegmentWithLock(ImageSectionObject->Segments, OldIrql);
2202 }
2203 else
2204 {
2206
2207 /*
2208 * NOTE: Section->Segment can be NULL for short time
2209 * during the section creating.
2210 */
2211 if (Segment == NULL)
2212 return;
2213
2214 KIRQL OldIrql = MiAcquirePfnLock();
2215 Segment->SectionCount--;
2216
2217 /* MmDereferenceSegmentWithLock releases PFN lock */
2218 MmDereferenceSegmentWithLock(Segment, OldIrql);
2219 }
2220}
2221
2222VOID NTAPI
2224 IN PVOID Object,
2227 IN ULONG SystemHandleCount)
2228{
2229 DPRINT("MmpCloseSection(OB %p, HC %lu)\n", Object, ProcessHandleCount);
2230}
2231
2232CODE_SEG("INIT")
2234NTAPI
2236{
2237 PSECTION PhysSection;
2240 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
2241 LARGE_INTEGER SectionSize;
2242 HANDLE Handle;
2244
2245 /*
2246 * Create the section mapping physical memory
2247 */
2250 &Name,
2252 NULL,
2253 NULL);
2254 /*
2255 * Create the Object
2256 */
2259 &Obj,
2261 NULL,
2262 sizeof(*PhysSection),
2263 0,
2264 0,
2265 (PVOID*)&PhysSection);
2266 if (!NT_SUCCESS(Status))
2267 {
2268 DPRINT1("MmCreatePhysicalMemorySection: failed to create object (0x%lx)\n", Status);
2269 return Status;
2270 }
2271
2272 /*
2273 * Initialize it
2274 */
2275 RtlZeroMemory(PhysSection, sizeof(*PhysSection));
2276
2277 /* Mark this as a "ROS Section" */
2278 PhysSection->u.Flags.filler = 1;
2280 PhysSection->u.Flags.PhysicalMemory = 1;
2281 PhysSection->SizeOfSection = SectionSize;
2284 if (Segment == NULL)
2285 {
2286 ObDereferenceObject(PhysSection);
2287 return STATUS_NO_MEMORY;
2288 }
2290 PhysSection->Segment = (PSEGMENT)Segment;
2291 Segment->RefCount = 1;
2292
2293 Segment->ReferenceCount = &Segment->RefCount;
2294 Segment->Flags = &Segment->SegFlags;
2295
2297 Segment->Image.FileOffset = 0;
2298 Segment->Protection = PAGE_EXECUTE_READWRITE;
2299 Segment->RawLength = SectionSize;
2300 Segment->Length = SectionSize;
2302 Segment->WriteCopy = FALSE;
2303 Segment->Image.VirtualAddress = 0;
2304 Segment->Image.Characteristics = 0;
2306
2307 Status = ObInsertObject(PhysSection,
2308 NULL,
2310 0,
2311 NULL,
2312 &Handle);
2313 if (!NT_SUCCESS(Status))
2314 {
2315 /* Note: ObInsertObject dereferences PhysSection on failure */
2316 return Status;
2317 }
2319
2320 return STATUS_SUCCESS;
2321}
2322
2323CODE_SEG("INIT")
2325NTAPI
2327{
2328 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
2330
2331 DPRINT("Creating Section Object Type\n");
2332
2333 /* Initialize the section based root */
2336
2337 /* Initialize the Section object type */
2338 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
2339 RtlInitUnicodeString(&Name, L"Section");
2340 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
2341 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(SECTION);
2342 ObjectTypeInitializer.PoolType = PagedPool;
2343 ObjectTypeInitializer.UseDefaultObject = TRUE;
2344 ObjectTypeInitializer.GenericMapping = MmpSectionMapping;
2345 ObjectTypeInitializer.DeleteProcedure = MmpDeleteSection;
2346 ObjectTypeInitializer.CloseProcedure = MmpCloseSection;
2347 ObjectTypeInitializer.ValidAccessMask = SECTION_ALL_ACCESS;
2348 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
2349 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &MmSectionObjectType);
2350
2352
2353 return STATUS_SUCCESS;
2354}
2355
2356static
2358NTAPI
2362 PLARGE_INTEGER UMaximumSize,
2366 BOOLEAN GotFileHandle)
2367/*
2368 * Create a section backed by a data file
2369 */
2370{
2371 PSECTION Section;
2375 KIRQL OldIrql;
2376
2377 /*
2378 * Create the section
2379 */
2384 NULL,
2385 sizeof(*Section),
2386 0,
2387 0,
2388 (PVOID*)&Section);
2389 if (!NT_SUCCESS(Status))
2390 {
2391 return Status;
2392 }
2393 /*
2394 * Initialize it
2395 */
2396 RtlZeroMemory(Section, sizeof(*Section));
2397
2398 /* Mark this as a "ROS" section */
2399 Section->u.Flags.filler = 1;
2401 Section->u.Flags.File = 1;
2402
2404 Section->u.Flags.NoChange = 1;
2405
2406 if (!GotFileHandle)
2407 {
2408 ASSERT(UMaximumSize != NULL);
2409 // ASSERT(UMaximumSize->QuadPart != 0);
2410 MaximumSize = *UMaximumSize;
2411 }
2412 else
2413 {
2416 if (!NT_SUCCESS(Status))
2417 {
2418 ObDereferenceObject(Section);
2419 return Status;
2420 }
2421
2422 /*
2423 * FIXME: Revise this once a locking order for file size changes is
2424 * decided
2425 */
2426 if ((UMaximumSize != NULL) && (UMaximumSize->QuadPart != 0))
2427 {
2428 MaximumSize = *UMaximumSize;
2429 }
2430 else
2431 {
2433 /* Mapping zero-sized files isn't allowed. */
2434 if (MaximumSize.QuadPart == 0)
2435 {
2436 ObDereferenceObject(Section);
2438 }
2439 }
2440
2441 if (MaximumSize.QuadPart > FileSize.QuadPart)
2442 {
2445 sizeof(LARGE_INTEGER),
2446 &MaximumSize);
2447 if (!NT_SUCCESS(Status))
2448 {
2449 ObDereferenceObject(Section);
2451 }
2452 }
2453 }
2454
2455 if (FileObject->SectionObjectPointer == NULL)
2456 {
2457 ObDereferenceObject(Section);
2459 }
2460
2461 /*
2462 * Lock the file
2463 */
2465 if (Status != STATUS_SUCCESS)
2466 {
2467 ObDereferenceObject(Section);
2468 return Status;
2469 }
2470
2471 /* Lock the PFN lock while messing with Section Object pointers */
2472grab_segment:
2473 OldIrql = MiAcquirePfnLock();
2474 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2475
2476 while (Segment && (Segment->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
2477 {
2478 MiReleasePfnLock(OldIrql);
2480 OldIrql = MiAcquirePfnLock();
2481 Segment = FileObject->SectionObjectPointer->DataSectionObject;
2482 }
2483
2484 /*
2485 * If this file hasn't been mapped as a data file before then allocate a
2486 * section segment to describe the data file mapping
2487 */
2488 if (Segment == NULL)
2489 {
2490 /* Release the lock. ExAllocatePoolWithTag might acquire it */
2491 MiReleasePfnLock(OldIrql);
2492
2495 if (Segment == NULL)
2496 {
2497 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2498 ObDereferenceObject(Section);
2499 return STATUS_NO_MEMORY;
2500 }
2501
2502 /* We are creating it */
2503 RtlZeroMemory(Segment, sizeof(*Segment));
2505 Segment->RefCount = 1;
2506
2507 /* Acquire lock again */
2508 OldIrql = MiAcquirePfnLock();
2509
2510 if (FileObject->SectionObjectPointer->DataSectionObject != NULL)
2511 {
2512 /* Well that's bad luck. Restart it all over */
2513 MiReleasePfnLock(OldIrql);
2515 goto grab_segment;
2516 }
2517
2518 FileObject->SectionObjectPointer->DataSectionObject = Segment;
2519
2520 /* We're safe to release the lock now */
2521 MiReleasePfnLock(OldIrql);
2522
2523 Section->Segment = (PSEGMENT)Segment;
2524
2525 /* Self-referencing segment */
2526 Segment->Flags = &Segment->SegFlags;
2527 Segment->ReferenceCount = &Segment->RefCount;
2528
2529 Segment->SectionCount = 1;
2530
2532 Segment->FileObject = FileObject;
2534
2535 Segment->Image.FileOffset = 0;
2536 Segment->Protection = SectionPageProtection;
2537
2538 Segment->Image.Characteristics = 0;
2541 {
2542 Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0;
2543 }
2544 else
2545 {
2546 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2547 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2548 }
2549 Segment->Image.VirtualAddress = 0;
2551
2552 /* We're good to use it now */
2553 OldIrql = MiAcquirePfnLock();
2554 Segment->SegFlags &= ~MM_SEGMENT_INCREATE;
2555 MiReleasePfnLock(OldIrql);
2556 }
2557 else
2558 {
2559 Section->Segment = (PSEGMENT)Segment;
2560 InterlockedIncrement64(&Segment->RefCount);
2561 InterlockedIncrementUL(&Segment->SectionCount);
2562
2563 MiReleasePfnLock(OldIrql);
2564
2566
2567 if (MaximumSize.QuadPart > Segment->RawLength.QuadPart &&
2569 {
2570 Segment->RawLength.QuadPart = MaximumSize.QuadPart;
2571 Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart);
2572 }
2573
2575 }
2576 Section->SizeOfSection = MaximumSize;
2577
2578 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
2579 *SectionObject = Section;
2580 return STATUS_SUCCESS;
2581}
2582
2583/*
2584 TODO: not that great (declaring loaders statically, having to declare all of
2585 them, having to keep them extern, etc.), will fix in the future
2586*/
2588(
2589 IN CONST VOID * FileHeader,
2590 IN SIZE_T FileHeaderSize,
2591 IN PVOID File,
2592 OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2594 IN PEXEFMT_CB_READ_FILE ReadFileCb,
2595 IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
2596);
2597
2599(
2600 IN CONST VOID * FileHeader,
2601 IN SIZE_T FileHeaderSize,
2602 IN PVOID File,
2603 OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2605 IN PEXEFMT_CB_READ_FILE ReadFileCb,
2606 IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
2607);
2608
2610{
2612#ifdef __ELF
2614#endif
2615};
2616
2617static
2619NTAPI
2621{
2622 SIZE_T SizeOfSegments;
2623 PMM_SECTION_SEGMENT Segments;
2624
2625 /* TODO: check for integer overflow */
2626 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * NrSegments;
2627
2629 SizeOfSegments,
2631
2632 if(Segments)
2633 RtlZeroMemory(Segments, SizeOfSegments);
2634
2635 return Segments;
2636}
2637static
2639NTAPI
2642 IN ULONG Length,
2643 OUT PVOID * Data,
2644 OUT PVOID * AllocBase,
2645 OUT PULONG ReadSize)
2646{
2649 ULONG AdjustOffset;
2650 ULONG OffsetAdjustment;
2652 ULONG UsedSize;
2653 PVOID Buffer;
2656
2658
2659 if(Length == 0)
2660 {
2661 KeBugCheck(MEMORY_MANAGEMENT);
2662 }
2663
2664 FileOffset = *Offset;
2665
2666 /* Negative/special offset: it cannot be used in this context */
2667 if(FileOffset.u.HighPart < 0)
2668 {
2669 KeBugCheck(MEMORY_MANAGEMENT);
2670 }
2671
2672 AdjustOffset = PAGE_ROUND_DOWN(FileOffset.u.LowPart);
2673 OffsetAdjustment = FileOffset.u.LowPart - AdjustOffset;
2674 FileOffset.u.LowPart = AdjustOffset;
2675
2676 BufferSize = Length + OffsetAdjustment;
2678
2679 /*
2680 * It's ok to use paged pool, because this is a temporary buffer only used in
2681 * the loading of executables. The assumption is that MmCreateSection is
2682 * always called at low IRQLs and that these buffers don't survive a brief
2683 * initialization phase
2684 */
2686 if (!Buffer)
2687 {
2689 }
2690
2692
2693 UsedSize = (ULONG)Iosb.Information;
2694
2695 if(NT_SUCCESS(Status) && UsedSize < OffsetAdjustment)
2696 {
2699 }
2700
2701 if(NT_SUCCESS(Status))
2702 {
2703 *Data = (PVOID)((ULONG_PTR)Buffer + OffsetAdjustment);
2704 *AllocBase = Buffer;
2705 *ReadSize = UsedSize - OffsetAdjustment;
2706 }
2707 else
2708 {
2709 ExFreePoolWithTag(Buffer, 'rXmM');
2710 }
2711
2712 return Status;
2713}
2714
2715#ifdef NASSERT
2716# define MmspAssertSegmentsSorted(OBJ_) ((void)0)
2717# define MmspAssertSegmentsNoOverlap(OBJ_) ((void)0)
2718# define MmspAssertSegmentsPageAligned(OBJ_) ((void)0)
2719#else
2720static
2721VOID
2722NTAPI
2724{
2725 ULONG i;
2726
2727 for( i = 1; i < ImageSectionObject->NrSegments; ++ i )
2728 {
2729 ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
2730 ImageSectionObject->Segments[i - 1].Image.VirtualAddress);
2731 }
2732}
2733
2734static
2735VOID
2736NTAPI
2738{
2739 ULONG i;
2740
2741 MmspAssertSegmentsSorted(ImageSectionObject);
2742
2743 for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2744 {
2745 ASSERT(ImageSectionObject->Segments[i].Length.QuadPart > 0);
2746
2747 if(i > 0)
2748 {
2749 ASSERT(ImageSectionObject->Segments[i].Image.VirtualAddress >=
2750 (ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
2751 ImageSectionObject->Segments[i - 1].Length.QuadPart));
2752 }
2753 }
2754}
2755
2756static
2757VOID
2758NTAPI
2760{
2761 ULONG i;
2762
2763 for( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2764 {
2765 ASSERT((ImageSectionObject->Segments[i].Image.VirtualAddress % PAGE_SIZE) == 0);
2766 ASSERT((ImageSectionObject->Segments[i].Length.QuadPart % PAGE_SIZE) == 0);
2767 }
2768}
2769#endif
2770
2771static
2772int
2773__cdecl
2775 const void * y)
2776{
2777 const MM_SECTION_SEGMENT *Segment1 = (const MM_SECTION_SEGMENT *)x;
2778 const MM_SECTION_SEGMENT *Segment2 = (const MM_SECTION_SEGMENT *)y;
2779
2780 if (Segment1->Image.VirtualAddress > Segment2->Image.VirtualAddress)
2781 return 1;
2782 else if (Segment1->Image.VirtualAddress < Segment2->Image.VirtualAddress)
2783 return -1;
2784 else
2785 return 0;
2786}
2787
2788/*
2789 * Ensures an image section's segments are sorted in memory
2790 */
2791static
2792VOID
2793NTAPI
2795 IN ULONG Flags)
2796{
2798 {
2799 MmspAssertSegmentsSorted(ImageSectionObject);
2800 }
2801 else
2802 {
2803 qsort(ImageSectionObject->Segments,
2804 ImageSectionObject->NrSegments,
2805 sizeof(ImageSectionObject->Segments[0]),
2807 }
2808}
2809
2810
2811/*
2812 * Ensures an image section's segments don't overlap in memory and don't have
2813 * gaps and don't have a null size. We let them map to overlapping file regions,
2814 * though - that's not necessarily an error
2815 */
2816static
2817BOOLEAN
2818NTAPI
2820(
2821 IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2822 IN ULONG Flags
2823)
2824{
2825 ULONG i;
2826
2828 {
2829 MmspAssertSegmentsNoOverlap(ImageSectionObject);
2830 return TRUE;
2831 }
2832
2833 ASSERT(ImageSectionObject->NrSegments >= 1);
2834
2835 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2836 {
2837 if(ImageSectionObject->Segments[i].Length.QuadPart == 0)
2838 {
2839 return FALSE;
2840 }
2841
2842 if(i > 0)
2843 {
2844 /*
2845 * TODO: relax the limitation on gaps. For example, gaps smaller than a
2846 * page could be OK (Windows seems to be OK with them), and larger gaps
2847 * could lead to image sections spanning several discontiguous regions
2848 * (NtMapViewOfSection could then refuse to map them, and they could
2849 * e.g. only be allowed as parameters to NtCreateProcess, like on UNIX)
2850 */
2851 if ((ImageSectionObject->Segments[i - 1].Image.VirtualAddress +
2852 ImageSectionObject->Segments[i - 1].Length.QuadPart) !=
2853 ImageSectionObject->Segments[i].Image.VirtualAddress)
2854 {
2855 return FALSE;
2856 }
2857 }
2858 }
2859
2860 return TRUE;
2861}
2862
2863/*
2864 * Merges and pads an image section's segments until they all are page-aligned
2865 * and have a size that is a multiple of the page size
2866 */
2867static
2868BOOLEAN
2869NTAPI
2871(
2872 IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject,
2873 IN ULONG Flags
2874)
2875{
2876 ULONG i;
2877 ULONG LastSegment;
2878 PMM_SECTION_SEGMENT EffectiveSegment;
2879
2881 {
2882 MmspAssertSegmentsPageAligned(ImageSectionObject);
2883 return TRUE;
2884 }
2885
2886 LastSegment = 0;
2887 EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
2888
2889 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
2890 {
2891 /*
2892 * The first segment requires special handling
2893 */
2894 if (i == 0)
2895 {
2897 ULONG_PTR VirtualOffset;
2898
2899 VirtualAddress = EffectiveSegment->Image.VirtualAddress;
2900
2901 /* Round down the virtual address to the nearest page */
2902 EffectiveSegment->Image.VirtualAddress = PAGE_ROUND_DOWN(VirtualAddress);
2903
2904 /* Round up the virtual size to the nearest page */
2905 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(VirtualAddress + EffectiveSegment->Length.QuadPart) -
2906 EffectiveSegment->Image.VirtualAddress;
2907
2908 /* Adjust the raw address and size */
2909 VirtualOffset = VirtualAddress - EffectiveSegment->Image.VirtualAddress;
2910
2911 if (EffectiveSegment->Image.FileOffset < VirtualOffset)
2912 {
2913 return FALSE;
2914 }
2915
2916 /*
2917 * Garbage in, garbage out: unaligned base addresses make the file
2918 * offset point in curious and odd places, but that's what we were
2919 * asked for
2920 */
2921 EffectiveSegment->Image.FileOffset -= VirtualOffset;
2922 EffectiveSegment->RawLength.QuadPart += VirtualOffset;
2923 }
2924 else
2925 {
2926 PMM_SECTION_SEGMENT Segment = &ImageSectionObject->Segments[i];
2927 ULONG_PTR EndOfEffectiveSegment;
2928
2929 EndOfEffectiveSegment = (ULONG_PTR)(EffectiveSegment->Image.VirtualAddress + EffectiveSegment->Length.QuadPart);
2930 ASSERT((EndOfEffectiveSegment % PAGE_SIZE) == 0);
2931
2932 /*
2933 * The current segment begins exactly where the current effective
2934 * segment ended, therefore beginning a new effective segment
2935 */
2936 if (EndOfEffectiveSegment == Segment->Image.VirtualAddress)
2937 {
2938 LastSegment ++;
2939 ASSERT(LastSegment <= i);
2940 ASSERT(LastSegment < ImageSectionObject->NrSegments);
2941
2942 EffectiveSegment = &ImageSectionObject->Segments[LastSegment];
2943
2944 if (LastSegment != i)
2945 {
2946 /*
2947 * Copy the current segment. If necessary, the effective segment
2948 * will be expanded later
2949 */
2950 *EffectiveSegment = *Segment;
2951 }
2952
2953 /*
2954 * Page-align the virtual size. We know for sure the virtual address
2955 * already is
2956 */
2957 ASSERT((EffectiveSegment->Image.VirtualAddress % PAGE_SIZE) == 0);
2958 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(EffectiveSegment->Length.QuadPart);
2959 }
2960 /*
2961 * The current segment is still part of the current effective segment:
2962 * extend the effective segment to reflect this
2963 */
2964 else if (EndOfEffectiveSegment > Segment->Image.VirtualAddress)
2965 {
2966 static const ULONG FlagsToProtection[16] =
2967 {
2984 };
2985
2986 unsigned ProtectionFlags;
2987
2988 /*
2989 * Extend the file size
2990 */
2991
2992 /* Unaligned segments must be contiguous within the file */
2993 if (Segment->Image.FileOffset != (EffectiveSegment->Image.FileOffset +
2994 EffectiveSegment->RawLength.QuadPart))
2995 {
2996 return FALSE;
2997 }
2998
2999 EffectiveSegment->RawLength.QuadPart += Segment->RawLength.QuadPart;
3000
3001 /*
3002 * Extend the virtual size
3003 */
3004 ASSERT(PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) >= EndOfEffectiveSegment);
3005
3006 EffectiveSegment->Length.QuadPart = PAGE_ROUND_UP(Segment->Image.VirtualAddress + Segment->Length.QuadPart) -
3007 EffectiveSegment->Image.VirtualAddress;
3008
3009 /*
3010 * Merge the protection
3011 */
3012 EffectiveSegment->Protection |= Segment->Protection;
3013
3014 /* Clean up redundance */
3015 ProtectionFlags = 0;
3016
3017 if(EffectiveSegment->Protection & PAGE_IS_READABLE)
3018 ProtectionFlags |= 1 << 0;
3019
3020 if(EffectiveSegment->Protection & PAGE_IS_WRITABLE)
3021 ProtectionFlags |= 1 << 1;
3022
3023 if(EffectiveSegment->Protection & PAGE_IS_EXECUTABLE)
3024 ProtectionFlags |= 1 << 2;
3025
3026 if(EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
3027 ProtectionFlags |= 1 << 3;
3028
3029 ASSERT(ProtectionFlags < 16);
3030 EffectiveSegment->Protection = FlagsToProtection[ProtectionFlags];
3031
3032 /* If a segment was required to be shared and cannot, fail */
3033 if(!(Segment->Protection & PAGE_IS_WRITECOPY) &&
3034 EffectiveSegment->Protection & PAGE_IS_WRITECOPY)
3035 {
3036 return FALSE;
3037 }
3038 }
3039 /*
3040 * We assume no holes between segments at this point
3041 */
3042 else
3043 {
3044 KeBugCheck(MEMORY_MANAGEMENT);
3045 }
3046 }
3047 }
3048 ImageSectionObject->NrSegments = LastSegment + 1;
3049
3050 return TRUE;
3051}
3052
3055 PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
3056{
3058 PVOID FileHeader;
3059 PVOID FileHeaderBuffer;
3060 ULONG FileHeaderSize;
3061 ULONG Flags;
3062 ULONG OldNrSegments;
3064 ULONG i;
3065
3066 /*
3067 * Read the beginning of the file (2 pages). Should be enough to contain
3068 * all (or most) of the headers
3069 */
3070 Offset.QuadPart = 0;
3071
3073 &Offset,
3074 PAGE_SIZE * 2,
3075 &FileHeader,
3076 &FileHeaderBuffer,
3077 &FileHeaderSize);
3078
3079 if (!NT_SUCCESS(Status))
3080 return Status;
3081
3082 if (FileHeaderSize == 0)
3083 {
3084 ExFreePool(FileHeaderBuffer);
3085 return STATUS_UNSUCCESSFUL;
3086 }
3087
3088 /*
3089 * Look for a loader that can handle this executable
3090 */
3091 for (i = 0; i < RTL_NUMBER_OF(ExeFmtpLoaders); ++ i)
3092 {
3093 Flags = 0;
3094
3095 Status = ExeFmtpLoaders[i](FileHeader,
3096 FileHeaderSize,
3097 FileObject,
3098 ImageSectionObject,
3099 &Flags,
3102
3103 if (!NT_SUCCESS(Status))
3104 {
3105 if (ImageSectionObject->Segments)
3106 {
3107 ExFreePool(ImageSectionObject->Segments);
3108 ImageSectionObject->Segments = NULL;
3109 }
3110 }
3111
3113 break;
3114 }
3115
3116 ExFreePoolWithTag(FileHeaderBuffer, 'rXmM');
3117
3118 /*
3119 * No loader handled the format
3120 */
3122 {
3125 }
3126
3127 if (!NT_SUCCESS(Status))
3128 return Status;
3129
3130 ASSERT(ImageSectionObject->Segments != NULL);
3131 ASSERT(ImageSectionObject->RefCount > 0);
3132
3133 /*
3134 * Some defaults
3135 */
3136 /* FIXME? are these values platform-dependent? */
3137 if (ImageSectionObject->ImageInformation.MaximumStackSize == 0)
3138 ImageSectionObject->ImageInformation.MaximumStackSize = 0x40000;
3139
3140 if(ImageSectionObject->ImageInformation.CommittedStackSize == 0)
3141 ImageSectionObject->ImageInformation.CommittedStackSize = 0x1000;
3142
3143 if(ImageSectionObject->BasedAddress == NULL)
3144 {
3145 if(ImageSectionObject->ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL)
3146 ImageSectionObject->BasedAddress = (PVOID)0x10000000;
3147 else
3148 ImageSectionObject->BasedAddress = (PVOID)0x00400000;
3149 }
3150
3151 /*
3152 * And now the fun part: fixing the segments
3153 */
3154
3155 /* Sort them by virtual address */
3156 MmspSortSegments(ImageSectionObject, Flags);
3157
3158 /* Ensure they don't overlap in memory */
3159 if (!MmspCheckSegmentBounds(ImageSectionObject, Flags))
3161
3162 /* Ensure they are aligned */
3163 OldNrSegments = ImageSectionObject->NrSegments;
3164
3165 if (!MmspPageAlignSegments(ImageSectionObject, Flags))
3167
3168 /* Trim them if the alignment phase merged some of them */
3169 if (ImageSectionObject->NrSegments < OldNrSegments)
3170 {
3171 PMM_SECTION_SEGMENT Segments;
3172 SIZE_T SizeOfSegments;
3173
3174 SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
3175
3177 SizeOfSegments,
3179
3180 if (Segments == NULL)
3182
3183 RtlCopyMemory(Segments, ImageSectionObject->Segments, SizeOfSegments);
3184 ExFreePool(ImageSectionObject->Segments);
3185 ImageSectionObject->Segments = Segments;
3186 }
3187
3188 /* And finish their initialization */
3189 for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
3190 {
3191 ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock);
3192 ImageSectionObject->Segments[i].ReferenceCount = &ImageSectionObject->RefCount;
3193 ImageSectionObject->Segments[i].Flags = &ImageSectionObject->SegFlags;
3194 MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]);
3195 ImageSectionObject->Segments[i].FileObject = FileObject;
3196 }
3197
3198 ASSERT(ImageSectionObject->RefCount > 0);
3199
3200 ImageSectionObject->FileObject = FileObject;
3201
3203 return Status;
3204}
3205
3210 PLARGE_INTEGER UMaximumSize,
3214{
3215 PSECTION Section;
3217 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3218 KIRQL OldIrql;
3219
3220
3221 if (FileObject == NULL)
3223
3224 if (FileObject->SectionObjectPointer == NULL)
3225 {
3226 DPRINT1("Denying section creation due to missing cache initialization\n");
3228 }
3229
3230 /*
3231 * Create the section
3232 */
3237 NULL,
3238 sizeof(*Section),
3239 0,
3240 0,
3241 (PVOID*)(PVOID)&Section);
3242 if (!NT_SUCCESS(Status))
3243 {
3244 return Status;
3245 }
3246
3247 /*
3248 * Initialize it
3249 */
3250 RtlZeroMemory(Section, sizeof(*Section));
3251
3252 /* Mark this as a "ROS" Section */
3253 Section->u.Flags.filler = 1;
3254
3256 Section->SizeOfSection = *UMaximumSize;
3257 Section->u.Flags.File = 1;
3258 Section->u.Flags.Image = 1;
3260 Section->u.Flags.NoChange = 1;
3261
3262grab_image_section_object:
3263 OldIrql = MiAcquirePfnLock();
3264
3265 /* Wait for it to be properly created or deleted */
3266 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3267 while(ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INDELETE | MM_SEGMENT_INCREATE)))
3268 {
3269 MiReleasePfnLock(OldIrql);
3270
3272
3273 OldIrql = MiAcquirePfnLock();
3274 ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
3275 }
3276
3277 if (ImageSectionObject == NULL)
3278 {
3279 NTSTATUS StatusExeFmt;
3280
3281 /* Release the lock because ExAllocatePoolWithTag could need to acquire it */
3282 MiReleasePfnLock(OldIrql);
3283
3285 if (ImageSectionObject == NULL)
3286 {
3287 ObDereferenceObject(Section);
3288 return STATUS_NO_MEMORY;
3289 }
3290
3291 ImageSectionObject->SegFlags = MM_SEGMENT_INCREATE;
3292 ImageSectionObject->RefCount = 1;
3293 ImageSectionObject->SectionCount = 1;
3294
3295 OldIrql = MiAcquirePfnLock();
3296 if (FileObject->SectionObjectPointer->ImageSectionObject != NULL)
3297 {
3298 MiReleasePfnLock(OldIrql);
3299 /* Bad luck. Start over */
3300 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3301 goto grab_image_section_object;
3302 }
3303
3304 FileObject->SectionObjectPointer->ImageSectionObject = ImageSectionObject;
3305
3306 MiReleasePfnLock(OldIrql);
3307
3308 /* Purge the cache */
3309 CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, NULL);
3310
3311 StatusExeFmt = ExeFmtpCreateImageSection(FileObject, ImageSectionObject);
3312
3313 if (!NT_SUCCESS(StatusExeFmt))
3314 {
3315 /* Unset */
3316 OldIrql = MiAcquirePfnLock();
3317 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3318 MiReleasePfnLock(OldIrql);
3319
3320 if(ImageSectionObject->Segments != NULL)
3321 ExFreePool(ImageSectionObject->Segments);
3322
3323 /*
3324 * If image file is empty, then return that the file is invalid for section
3325 */
3326 Status = StatusExeFmt;
3327 if (StatusExeFmt == STATUS_END_OF_FILE)
3328 {
3330 }
3331
3332 ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
3333 ObDereferenceObject(Section);
3334 return Status;
3335 }
3336
3337 Section->Segment = (PSEGMENT)ImageSectionObject;
3338 ASSERT(ImageSectionObject->Segments);
3339 ASSERT(ImageSectionObject->RefCount > 0);
3340
3341 /*
3342 * Lock the file
3343 */
3345 if (!NT_SUCCESS(Status))
3346 {
3347 /* Unset */
3348 OldIrql = MiAcquirePfnLock();
3349 FileObject->SectionObjectPointer->ImageSectionObject = NULL;
3350 MiReleasePfnLock(OldIrql);
3351
3352 ExFreePool(ImageSectionObject->Segments);
3353 ExFreePool(ImageSectionObject);
3354 ObDereferenceObject(Section);
3355 return Status;
3356 }
3357
3358 OldIrql = MiAcquirePfnLock();
3359 ImageSectionObject->SegFlags &= ~MM_SEGMENT_INCREATE;
3360
3361 /* Take a ref on the file on behalf of the newly created structure */
3363
3364 MiReleasePfnLock(OldIrql);
3365
3366 Status = StatusExeFmt;
3367 }
3368 else
3369 {
3370 /* If FS driver called for delete, tell them it's not possible anymore. */
3371 ImageSectionObject->SegFlags &= ~MM_IMAGE_SECTION_FLUSH_DELETE;
3372
3373 /* Take one ref */
3374 InterlockedIncrement64(&ImageSectionObject->RefCount);
3375 ImageSectionObject->SectionCount++;
3376
3377 MiReleasePfnLock(OldIrql);
3378
3379 Section->Segment = (PSEGMENT)ImageSectionObject;
3380
3382 }
3383
3384 if (Section->SizeOfSection.QuadPart == 0)
3385 {
3386 Section->SizeOfSection.QuadPart = ImageSectionObject->ImageInformation.ImageFileSize;
3387 }
3388
3389 //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE);
3390 *SectionObject = Section;
3391 ASSERT(ImageSectionObject->RefCount > 0);
3392
3393 return Status;
3394}
3395
3396
3397
3398static NTSTATUS
3401 BOOLEAN AsImage,
3405 ULONG Protect,
3406 LONGLONG ViewOffset,
3408{
3409 PMEMORY_AREA MArea;
3411 ULONG Granularity;
3412
3413 ASSERT(ViewSize != 0);
3414
3415 if (Segment->WriteCopy)
3416 {
3417 /* We have to do this because the not present fault
3418 * and access fault handlers depend on the protection
3419 * that should be granted AFTER the COW fault takes
3420 * place to be in Region->Protect. The not present fault
3421 * handler changes this to the correct protection for COW when
3422 * mapping the pages into the process's address space. If a COW
3423 * fault takes place, the access fault handler sets the page protection
3424 * to these values for the newly copied pages
3425 */
3426 if (Protect == PAGE_WRITECOPY)
3428 else if (Protect == PAGE_EXECUTE_WRITECOPY)
3430 }
3431
3432 if (*BaseAddress == NULL)
3433 Granularity = MM_ALLOCATION_GRANULARITY;
3434 else
3435 Granularity = PAGE_SIZE;
3436
3437#ifdef NEWCC
3438 if (Segment->Flags & MM_DATAFILE_SEGMENT)
3439 {
3441 FileOffset.QuadPart = ViewOffset;
3442 ObReferenceObject(Section);
3444 }
3445#endif
3449 ViewSize,
3450 Protect,
3451 &MArea,
3453 Granularity);
3454 if (!NT_SUCCESS(Status))
3455 {
3456 DPRINT1("Mapping between 0x%p and 0x%p failed (%X).\n",
3457 (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status);
3458 return Status;
3459 }
3460
3461 InterlockedIncrement64(Segment->ReferenceCount);
3462
3463 MArea->SectionData.Segment = Segment;
3464 MArea->SectionData.ViewOffset = ViewOffset;
3465 if (AsImage)
3466 {
3468 }
3469
3470 MmInitializeRegion(&MArea->SectionData.RegionListHead,
3471 ViewSize, 0, Protect);
3472
3473 return STATUS_SUCCESS;
3474}
3475
3476
3477static VOID
3479 PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
3480{
3483 SWAPENTRY SavedSwapEntry;
3487
3490
3492
3494 MemoryArea->SectionData.ViewOffset;
3495
3496 Segment = MemoryArea->SectionData.Segment;
3497
3499 while (Entry && MM_IS_WAIT_PTE(Entry))
3500 {
3503
3505
3509 }
3510
3511 /*
3512 * For a dirty, datafile, non-private page, there shoulkd be no swap entry
3513 */
3514 if (*Segment->Flags & MM_DATAFILE_SEGMENT)
3515 {
3516 if (Page == PFN_FROM_SSE(Entry) && Dirty)
3517 {
3518 ASSERT(SwapEntry == 0);
3519 }
3520 }
3521
3522 if (SwapEntry != 0)
3523 {
3524 /*
3525 * Sanity check
3526 */
3527 MmFreeSwapPage(SwapEntry);
3528 }
3529 else if (Page != 0)
3530 {
3531 if (IS_SWAP_FROM_SSE(Entry) ||
3533 {
3534 ASSERT(Process != NULL);
3535
3536 /*
3537 * Just dereference private pages
3538 */
3539 SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
3540 if (SavedSwapEntry != 0)
3541 {
3542 MmFreeSwapPage(SavedSwapEntry);
3544 }
3547 }
3548 else
3549 {
3550 if (Process)
3551 {
3553 }
3554
3555 /* We don't dirtify for System Space Maps. We let Cc manage that */
3557 }
3558 }
3559}
3560
3561static NTSTATUS
3564{
3568 PLIST_ENTRY CurrentEntry;
3569 PMM_REGION CurrentRegion;
3570 PLIST_ENTRY RegionListHead;
3571
3573 BaseAddress);
3574 if (MemoryArea == NULL)
3575 {
3576 return STATUS_UNSUCCESSFUL;
3577 }
3578
3579 Segment = MemoryArea->SectionData.Segment;
3580
3581#ifdef NEWCC
3582 if (Segment->Flags & MM_DATAFILE_SEGMENT)
3583 {
3587
3588 return Status;
3589 }
3590#endif
3591
3593
3595
3596 RegionListHead = &MemoryArea->SectionData.RegionListHead;
3597 while (!IsListEmpty(RegionListHead))
3598 {
3599 CurrentEntry = RemoveHeadList(RegionListHead);
3600 CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry);
3601 ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
3602 }
3603
3604 if ((*Segment->Flags) & MM_PHYSICALMEMORY_SEGMENT)
3605 {
3607 MemoryArea,
3608 NULL,
3609 NULL);
3610 }
3611 else
3612 {
3614 MemoryArea,
3616 AddressSpace);
3617 }
3619 MmDereferenceSegment(Segment);
3620 return Status;
3621}
3622
3623/* This functions must be called with a locked address space */
3625NTAPI
3630 _In_ BOOLEAN SkipDebuggerNotify)
3631{
3634 PVOID ImageBaseAddress = 0;
3635
3636 DPRINT("Opening memory area Process %p BaseAddress %p\n",
3638
3639 ASSERT(Process);
3641
3642 AddressSpace = &Process->Vm;
3643
3644 if (MemoryArea == NULL ||
3645#ifdef NEWCC
3646 ((MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) && (MemoryArea->Type != MEMORY_AREA_CACHE)) ||
3647#else
3649#endif
3651
3652 {
3654
3655 DPRINT1("Unable to find memory area at address %p.\n", BaseAddress);
3657 }
3658
3660 {
3661 ULONG i;
3662 ULONG NrSegments;
3663 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3664 PMM_SECTION_SEGMENT SectionSegments;
3666 ULONG MapCount;
3667
3668 Segment = MemoryArea->SectionData.Segment;
3669 ImageSectionObject = ImageSectionObjectFromSegment(Segment);
3670 SectionSegments = ImageSectionObject->Segments;
3671 NrSegments = ImageSectionObject->NrSegments;
3672
3674
3675 /* Search for the current segment within the section segments
3676 * and calculate the image base address */
3677 for (i = 0; i < NrSegments; i++)
3678 {
3679 if (Segment == &SectionSegments[i])
3680 {
3681 ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
3682 break;
3683 }
3684 }
3685 if (i >= NrSegments)
3686 {
3687 KeBugCheck(MEMORY_MANAGEMENT);
3688 }
3689
3690 for (i = 0; i < NrSegments; i++)
3691 {
3692 PVOID SBaseAddress = (PVOID)
3693 ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
3694
3695 Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
3696 if (!NT_SUCCESS(Status))
3697 {
3698 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3699 SBaseAddress, Process, Status);
3701 }
3702 }
3703 DPRINT("One mapping less for %p\n", ImageSectionObject->FileObject->SectionObjectPointer);
3704 MapCount = InterlockedDecrement(&ImageSectionObject->MapCount);
3705 if (MapCount != 0)
3706 ImageBaseAddress = NULL;
3707 }
3708 else
3709 {
3711 PMMVAD Vad = &MemoryArea->VadNode;
3712 PCONTROL_AREA ControlArea = Vad->ControlArea;
3715 LARGE_INTEGER ViewOffset;
3716 ViewOffset.QuadPart = MemoryArea->SectionData.ViewOffset;
3717
3718 InterlockedIncrement64(Segment->ReferenceCount);
3719
3720 ViewSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
3721
3723 if (!NT_SUCCESS(Status))
3724 {
3725 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3728 }
3729
3730 /* These might be deleted now */
3731 Vad = NULL;
3732 MemoryArea = NULL;
3733
3735 {
3736 /* Don't bother */
3737 MmDereferenceSegment(Segment);
3738 return STATUS_SUCCESS;
3739 }
3741
3742 FileObject = Segment->FileObject;
3744
3745 /* Don't bother for auto-delete closed file. */
3747 {
3749 MmDereferenceSegment(Segment);
3750 return STATUS_SUCCESS;
3751 }
3752
3753 /*
3754 * Flush only when last mapping is deleted.
3755 * FIXME: Why ControlArea == NULL? Or rather: is ControlArea ever not NULL here?
3756 */
3757 if (ControlArea == NULL || ControlArea->NumberOfMappedViews == 1)
3758 {
3759 while (ViewSize > 0)
3760 {
3761 ULONG FlushSize = min(ViewSize, PAGE_ROUND_DOWN(MAXULONG));
3762 MmFlushSegment(FileObject->SectionObjectPointer,
3763 &ViewOffset,
3764 FlushSize,
3765 NULL);
3766 ViewSize -= FlushSize;
3767 ViewOffset.QuadPart += FlushSize;
3768 }
3769 }
3770
3772 MmDereferenceSegment(Segment);
3773 }
3774
3775 /* Notify debugger */
3776 if (ImageBaseAddress && !SkipDebuggerNotify) DbgkUnMapViewOfSection(ImageBaseAddress);
3777
3778 return STATUS_SUCCESS;
3779}
3780
3781
3782
3783
3807NTAPI
3809 _In_ HANDLE SectionHandle,
3810 _In_ SECTION_INFORMATION_CLASS SectionInformationClass,
3811 _Out_ PVOID SectionInformation,
3812 _In_ SIZE_T SectionInformationLength,
3814{
3815 PSECTION Section;
3818 PAGED_CODE();
3819
3821 if (PreviousMode != KernelMode)
3822 {
3823 _SEH2_TRY
3824 {
3825 ProbeForWrite(SectionInformation,
3826 SectionInformationLength,
3827 __alignof(ULONG));
3828 if (ResultLength != NULL)
3829 {
3831 sizeof(*ResultLength),
3832 __alignof(SIZE_T));
3833 }
3834 }
3836 {
3838 }
3839 _SEH2_END;
3840 }
3841
3842 if (SectionInformationClass == SectionBasicInformation)
3843 {
3844 if (SectionInformationLength < sizeof(SECTION_BASIC_INFORMATION))
3845 {
3847 }
3848 }
3849 else if (SectionInformationClass == SectionImageInformation)
3850 {
3851 if (SectionInformationLength < sizeof(SECTION_IMAGE_INFORMATION))
3852 {
3854 }
3855 }
3856 else
3857 {
3859 }
3860
3861 Status = ObReferenceObjectByHandle(SectionHandle,
3865 (PVOID*)(PVOID)&Section,
3866 NULL);
3867 if (!NT_SUCCESS(Status))
3868 {
3869 DPRINT1("Failed to reference section: 0x%lx\n", Status);
3870 return Status;
3871 }
3872
3873 switch(SectionInformationClass)
3874 {
3876 {
3877 SECTION_BASIC_INFORMATION Sbi = { 0 };
3878
3879 Sbi.Size = Section->SizeOfSection;
3880 Sbi.BaseAddress = NULL;
3881
3882 if (Section->u.Flags.File)
3883 Sbi.Attributes |= SEC_FILE;
3884 if (Section->u.Flags.Image)
3885 Sbi.Attributes |= SEC_IMAGE;
3886 if (Section->u.Flags.Commit)
3887 Sbi.Attributes |= SEC_COMMIT;
3888 if (Section->u.Flags.Reserve)
3889 Sbi.Attributes |= SEC_RESERVE;
3890 if (Section->u.Flags.Based)
3891 Sbi.Attributes |= SEC_BASED;
3892
3893 if (Section->u.Flags.Image)
3894 {
3895 if (!MiIsRosSectionObject(Section))
3896 {
3897 /* Not supported yet */
3898 ASSERT(FALSE);
3899 }
3900 }
3901 else if (MiIsRosSectionObject(Section))
3902 {
3903 Sbi.BaseAddress = (PVOID)((PMM_SECTION_SEGMENT)Section->Segment)->Image.VirtualAddress;
3904 }
3905 else
3906 {
3907 Sbi.BaseAddress = Section->Segment->BasedAddress;
3908 }
3909
3910 _SEH2_TRY
3911 {
3912 *((SECTION_BASIC_INFORMATION*)SectionInformation) = Sbi;
3913 if (ResultLength != NULL)
3914 {
3915 *ResultLength = sizeof(Sbi);
3916 }
3917 }
3919 {
3921 }
3922 _SEH2_END;
3923 break;
3924 }
3926 {
3927 if (!Section->u.Flags.Image)
3928 {
3930 }
3931 else if (MiIsRosSectionObject(Section))
3932 {
3933 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
3934
3935 _SEH2_TRY
3936 {
3938 *Sii = ImageSectionObject->ImageInformation;
3939 if (ResultLength != NULL)
3940 {
3941 *ResultLength = sizeof(*Sii);
3942 }
3943 }
3945 {
3947 }
3948 _SEH2_END;
3949 }
3950 else
3951 {
3952 _SEH2_TRY
3953 {
3955 *Sii = *Section->Segment->u2.ImageInformation;
3956 if (ResultLength != NULL)
3957 *ResultLength = sizeof(*Sii);
3958 }
3960 {
3962 }
3963 _SEH2_END;
3964 }
3965 break;
3966 }
3967 default:
3968 DPRINT1("Unknown SectionInformationClass: %d\n", SectionInformationClass);
3970 }
3971
3972 ObDereferenceObject(Section);
3973
3974 return Status;
3975}
3976
3977/**********************************************************************
3978 * NAME EXPORTED
3979 * MmMapViewOfSection
3980 *
3981 * DESCRIPTION
3982 * Maps a view of a section into the virtual address space of a
3983 * process.
3984 *
3985 * ARGUMENTS
3986 * Section
3987 * Pointer to the section object.
3988 *
3989 * ProcessHandle
3990 * Pointer to the process.
3991 *
3992 * BaseAddress
3993 * Desired base address (or NULL) on entry;
3994 * Actual base address of the view on exit.
3995 *
3996 * ZeroBits
3997 * Number of high order address bits that must be zero.
3998 *
3999 * CommitSize
4000 * Size in bytes of the initially committed section of
4001 * the view.
4002 *
4003 * SectionOffset
4004 * Offset in bytes from the beginning of the section
4005 * to the beginning of the view.
4006 *
4007 * ViewSize
4008 * Desired length of map (or zero to map all) on entry
4009 * Actual length mapped on exit.
4010 *
4011 * InheritDisposition
4012 * Specified how the view is to be shared with
4013 * child processes.
4014 *
4015 * AllocationType
4016 * Type of allocation for the pages.
4017 *
4018 * Protect
4019 * Protection for the committed region of the view.
4020 *
4021 * RETURN VALUE
4022 * Status.
4023 *
4024 * @implemented
4025 */
4037{
4038 PSECTION Section;
4041 BOOLEAN NotAtBase = FALSE;
4042 BOOLEAN IsAttached = FALSE;
4044
4046 {
4047 DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
4049 Process,
4051 ZeroBits,
4052 CommitSize,
4054 ViewSize,
4057 Protect);
4058 }
4059
4060 ASSERT(Process);
4061
4063 {
4065 }
4066
4068 {
4070 IsAttached = TRUE;
4071 }
4072
4073 /* FIXME: We should keep this, but it would break code checking equality */
4074 Protect &= ~PAGE_NOCACHE;
4075
4076 Section = SectionObject;
4077 AddressSpace = &Process->Vm;
4078
4079 if (Section->u.Flags.NoChange)
4081
4083
4084 if (Section->u.Flags.Image)
4085 {
4086 ULONG i;
4087 ULONG NrSegments;
4088 ULONG_PTR ImageBase;
4089 SIZE_T ImageSize;
4090 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
4091 PMM_SECTION_SEGMENT SectionSegments;
4092
4093 ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
4094 SectionSegments = ImageSectionObject->Segments;
4095 NrSegments = ImageSectionObject->NrSegments;
4096
4097 ASSERT(ImageSectionObject->RefCount > 0);
4098
4099 ImageBase = (ULONG_PTR)*BaseAddress;
4100 if (ImageBase == 0)
4101 {
4102 ImageBase = (ULONG_PTR)ImageSectionObject->BasedAddress;
4103 }
4104
4105 ImageSize = 0;
4106 for (i = 0; i < NrSegments; i++)
4107 {
4108 ULONG_PTR MaxExtent;
4109 MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
4110 SectionSegments[i].Length.QuadPart);
4111 ImageSize = max(ImageSize, MaxExtent);
4112 }
4113
4114 ImageSectionObject->ImageInformation.ImageFileSize = (ULONG)ImageSize;
4115
4116 /* Check for an illegal base address */
4117 if (((ImageBase + ImageSize) > (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS) ||
4118 ((ImageBase + ImageSize) < ImageSize))
4119 {
4120 ASSERT(*BaseAddress == NULL);
4121 ImageBase = ALIGN_DOWN_BY((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - ImageSize,
4123 NotAtBase = TRUE;
4124 }
4125 else if (ImageBase != ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY))
4126 {
4127 ASSERT(*BaseAddress == NULL);
4128 ImageBase = ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY);
4129 NotAtBase = TRUE;
4130 }
4131
4132 /* Check there is enough space to map the section at that point. */
4133 if (!MmIsAddressRangeFree(AddressSpace, (PVOID)ImageBase, PAGE_ROUND_UP(ImageSize)))
4134 {
4135 /* Fail if the user requested a fixed base address. */
4136 if ((*BaseAddress) != NULL)
4137 {
4139 goto Exit;
4140 }
4141 /* Otherwise find a gap to map the image. */
4143 if (ImageBase == 0)
4144 {
4146 goto Exit;
4147 }
4148 /* Remember that we loaded image at a different base address */
4149 NotAtBase = TRUE;
4150 }
4151
4152 for (i = 0; i < NrSegments; i++)
4153 {
4154 PVOID SBaseAddress = (PVOID)
4155 ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4156 MmLockSectionSegment(&SectionSegments[i]);
4158 TRUE,
4159 &SectionSegments[i],
4160 &SBaseAddress,
4161 SectionSegments[i].Length.QuadPart,
4162 SectionSegments[i].Protection,
4163 0,
4164 0);
4165 MmUnlockSectionSegment(&SectionSegments[i]);
4166 if (!NT_SUCCESS(Status))
4167 {
4168 /* roll-back */
4169 while (i--)
4170 {
4171 SBaseAddress = ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4172 MmLockSectionSegment(&SectionSegments[i]);
4173 MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
4174 MmUnlockSectionSegment(&SectionSegments[i]);
4175 }
4176
4177 goto Exit;
4178 }
4179 }
4180
4181 *BaseAddress = (PVOID)ImageBase;
4182 *ViewSize = ImageSize;
4183
4184 DPRINT("Mapped %p for section pointer %p\n", ImageSectionObject, ImageSectionObject->FileObject->SectionObjectPointer);
4185
4186 /* One more map */
4187 InterlockedIncrement(&ImageSectionObject->MapCount);
4188 }
4189 else
4190 {
4192 LONGLONG ViewOffset;
4193
4194 ASSERT(Segment->RefCount > 0);
4195
4196 /* check for write access */
4199 {
4201 goto Exit;
4202 }
4203 /* check for read access */
4206 {
4208 goto Exit;
4209 }
4210 /* check for execute access */
4213 {
4215 goto Exit;
4216 }
4217
4218 if (SectionOffset == NULL)
4219 {
4220 ViewOffset = 0;
4221 }
4222 else
4223 {
4224 SectionOffset->QuadPart &= ~(PAGE_SIZE - 1);
4225 ViewOffset = SectionOffset->QuadPart;
4226 }
4227
4228 /* Check if the offset and size would cause an overflow */
4229 if (((ULONG64)ViewOffset + *ViewSize) < (ULONG64)ViewOffset)
4230 {
4231 DPRINT1("Section offset overflows\n");
4233 goto Exit;
4234 }
4235
4236 /* Check if the offset and size are bigger than the section itself */
4237 if (((ULONG64)ViewOffset + *ViewSize) > (ULONG64)Section->SizeOfSection.QuadPart)
4238 {
4239 /* This is allowed for physical memory sections and kernel mode callers */
4240 if (!Section->u.Flags.PhysicalMemory || (ExGetPreviousMode() == UserMode))
4241 {
4242 DPRINT1("Section offset and size are larger than section\n");
4244 goto Exit;
4245 }
4246 }
4247
4248 if ((*ViewSize) == 0)
4249 {
4250 /* Calculate a view size and make sure it doesn't overflow a SIZE_T */
4251 ULONG64 CalculatedSize = Section->SizeOfSection.QuadPart - ViewOffset;
4252 if (CalculatedSize > SIZE_T_MAX)
4253 {
4254 DPRINT1("ViewSize is larger than SIZE_T_MAX\n");
4256 goto Exit;
4257 }
4258
4259 *ViewSize = (SIZE_T)CalculatedSize;
4260 }
4261 else if ((ExGetPreviousMode() == UserMode) &&
4262 (((*ViewSize)+ViewOffset) > Section->SizeOfSection.QuadPart) &&
4263 (!Section->u.Flags.Reserve))
4264 {
4265 /* Dubious */
4266 (*ViewSize) = MIN(Section->SizeOfSection.QuadPart - ViewOffset, SIZE_T_MAX - PAGE_SIZE);
4267 }
4268
4270
4273 FALSE,
4274 Segment,
4276 *ViewSize,
4277 Protect,
4278 ViewOffset,
4281 if (!NT_SUCCESS(Status))
4282 {
4283 goto Exit;
4284 }
4285 }
4286
4287 if (NotAtBase)
4289 else
4291
4292Exit:
4293
4295
4296 if (IsAttached)
4297 {
4299 }
4300
4301 return Status;
4302}
4303
4304/*
4305 * @unimplemented
4306 */
4307BOOLEAN
4308NTAPI
4312{
4313 BOOLEAN Ret;
4315
4316 /* Check whether an ImageSectionObject exists */
4317 if (SectionObjectPointer->ImageSectionObject != NULL)
4318 {
4319 DPRINT1("ERROR: File can't be truncated because it has an image section\n");
4320 return FALSE;
4321 }
4322
4324 if (!Segment)
4325 {
4326 /* There is no data section. It's fine to do anything. */
4327 return TRUE;
4328 }
4329
4331 if ((Segment->SectionCount == 0) ||
4332 ((Segment->SectionCount == 1) && (SectionObjectPointer->SharedCacheMap != NULL)))
4333 {
4334 /* If the cache is the only one holding a reference to the segment, then it's fine to resize */
4335 Ret = TRUE;
4336 }
4337 else if (NewFileSize != NULL)
4338 {
4339 /* We can't shrink, but we can extend */
4340 Ret = NewFileSize->QuadPart >= Segment->RawLength.QuadPart;
4341#if DBG
4342 if (!Ret)
4343 {
4344 DPRINT1("Cannot truncate data: New Size %I64d, Segment Size %I64d\n", NewFileSize->QuadPart, Segment->RawLength.QuadPart);
4345 }
4346#endif
4347 }
4348 else
4349 {
4350 DPRINT1("ERROR: File can't be truncated because it has references held to its data section\n");
4351 Ret = FALSE;
4352 }
4353
4355 MmDereferenceSegment(Segment);
4356
4357 DPRINT("FIXME: didn't check for outstanding write probes\n");
4358
4359 return Ret;
4360}
4361
4362static
4363BOOLEAN
4365{
4367
4369
4370 /* Loop over all entries */
4371 for (PageTable = RtlEnumerateGenericTable(&Segment->PageTable, TRUE);
4372 PageTable != NULL;
4374 {
4375 for (ULONG i = 0; i < _countof(PageTable->PageEntries); i++)
4376 {
4377 ULONG_PTR Entry = PageTable->PageEntries[i];
4379
4380 if (!Entry)
4381 continue;
4382
4384 {
4385 /* I/O ongoing or swap entry. Someone mapped this file as we were not looking */
4387 return FALSE;
4388 }
4389
4390 /* Regular entry */
4393
4394 /* Properly remove using the used API */
4395 Offset.QuadPart = PageTable->FileOffset.QuadPart + (i << PAGE_SHIFT);
4398 }
4399 }
4400
4402
4403 return TRUE;
4404}
4405
4406/*
4407 * @implemented
4408 */
4412{
4413 switch(FlushType)
4414 {
4415 case MmFlushForDelete:
4416 {
4417 /*
4418 * FIXME: Check for outstanding write probes on Data section.
4419 * How do we do that ?
4420 */
4421 }
4422 /* Fall-through */
4423 case MmFlushForWrite:
4424 {
4425 KIRQL OldIrql = MiAcquirePfnLock();
4426 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4427
4428 DPRINT("Deleting or modifying %p\n", SectionObjectPointer);
4429
4430 /* Wait for concurrent creation or deletion of image to be done */
4431 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4432 while (ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INCREATE | MM_SEGMENT_INDELETE)))
4433 {
4434 MiReleasePfnLock(OldIrql);
4436 OldIrql = MiAcquirePfnLock();
4437 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4438 }
4439
4440 if (!ImageSectionObject)
4441 {
4442 DPRINT("No image section object. Accepting\n");
4443 /* Nothing to do */
4444 MiReleasePfnLock(OldIrql);
4445 return TRUE;
4446 }
4447
4448 /* Do we have open sections or mappings on it ? */
4449 if ((ImageSectionObject->SectionCount) || (ImageSectionObject->MapCount))
4450 {
4451 /* We do. No way to delete it */
4452 MiReleasePfnLock(OldIrql);
4453 DPRINT("Denying. There are mappings open\n");
4454 return FALSE;
4455 }
4456
4457 /* There are no sections open on it, but we must still have pages around. Discard everything */
4458 ImageSectionObject->SegFlags |= MM_IMAGE_SECTION_FLUSH_DELETE;
4459 InterlockedIncrement64(&ImageSectionObject->RefCount);
4460 MiReleasePfnLock(OldIrql);
4461
4462 DPRINT("Purging\n");
4463
4464 for (ULONG i = 0; i < ImageSectionObject->NrSegments; i++)
4465 {
4466 if (!MiPurgeImageSegment(&ImageSectionObject->Segments[i]))
4467 break;
4468 }
4469
4470 /* Grab lock again */
4471 OldIrql = MiAcquirePfnLock();
4472
4473 if (!(ImageSectionObject->SegFlags & MM_IMAGE_SECTION_FLUSH_DELETE))
4474 {
4475 /*
4476 * Someone actually created a section while we were not looking.
4477 * Drop our ref and deny.
4478 * MmDereferenceSegmentWithLock releases Pfn lock
4479 */
4480 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4481 return FALSE;
4482 }
4483
4484 /* We should be the last one holding a ref here. */
4485 ASSERT(ImageSectionObject->RefCount == 1);
4486 ASSERT(ImageSectionObject->SectionCount == 0);
4487
4488 /* Dereference the first segment, this will free everything & release the lock */
4489 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4490 return TRUE;
4491 }
4492 }
4493 return FALSE;
4494}
4495
4496/*
4497 * @implemented
4498 */
4500NTAPI
4504{
4506
4507 SectionOffset.QuadPart = 0;
4508
4510}
4511
4513NTAPI
4520 )
4521{
4522 PSECTION Section = SectionObject;
4526
4528
4529 PAGED_CODE();
4530
4532 {
4534 &MmSession,
4535 MappedBase,
4536 ViewSize,
4538 }
4539
4540 DPRINT("MmMapViewInSystemSpaceEx() called\n");
4541
4542 /* unsupported for now */
4543 ASSERT(Section->u.Flags.Image == 0);
4544
4545 Section = SectionObject;
4547
4548 if (*ViewSize == 0)
4549 {
4550 LONGLONG MapSizeLL;
4551
4552 /* Page-align the mapping */
4553 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4554
4555 if (!NT_SUCCESS(RtlLongLongSub(Section->SizeOfSection.QuadPart, SectionOffset->QuadPart, &MapSizeLL)))
4557
4558 if (!NT_SUCCESS(RtlLongLongToSIZET(MapSizeLL, ViewSize)))
4560 }
4561 else
4562 {
4563 LONGLONG HelperLL;
4564
4565 /* Get the map end */
4566 if (!NT_SUCCESS(RtlLongLongAdd(SectionOffset->QuadPart, *ViewSize, &HelperLL)))
4568
4569 /* Round it up, if needed */
4570 if (HelperLL % PAGE_SIZE)
4571 {
4572 if (!NT_SUCCESS(RtlLongLongAdd(HelperLL, PAGE_SIZE - (HelperLL % PAGE_SIZE), &HelperLL)))
4574 }
4575
4576 /* Now that we have the mapping end, we can align down its start */
4577 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4578
4579 /* Get the new size */
4580 if (!NT_SUCCESS(RtlLongLongSub(HelperLL, SectionOffset->QuadPart, &HelperLL)))
4582
4583 if (!NT_SUCCESS(RtlLongLongToSIZET(HelperLL, ViewSize)))
4585 }
4586
4588
4590
4592
4594 Section->u.Flags.Image,
4595 Segment,
4596 MappedBase,
4597 *ViewSize,
4599 SectionOffset->QuadPart,
4600 SEC_RESERVE);
4601
4604
4605 return Status;
4606}
4607
4608/* This function must be called with address space lock held */
4610NTAPI
4612{
4613 DPRINT("MmUnmapViewInSystemSpace() called\n");
4614
4616}
4617
4618/**********************************************************************
4619 * NAME EXPORTED
4620 * MmCreateSection@
4621 *
4622 * DESCRIPTION
4623 * Creates a section object.
4624 *
4625 * ARGUMENTS
4626 * SectionObject (OUT)
4627 * Caller supplied storage for the resulting pointer
4628 * to a SECTION_OBJECT instance;
4629 *
4630 * DesiredAccess
4631 * Specifies the desired access to the section can be a
4632 * combination of:
4633 * STANDARD_RIGHTS_REQUIRED |
4634 * SECTION_QUERY |
4635 * SECTION_MAP_WRITE |
4636 * SECTION_MAP_READ |
4637 * SECTION_MAP_EXECUTE
4638 *
4639 * ObjectAttributes [OPTIONAL]
4640 * Initialized attributes for the object can be used
4641 * to create a named section;
4642 *
4643 * MaximumSize
4644 * Maximizes the size of the memory section. Must be
4645 * non-NULL for a page-file backed section.
4646 * If value specified for a mapped file and the file is
4647 * not large enough, file will be extended.
4648 *
4649 * SectionPageProtection
4650 * Can be a combination of:
4651 * PAGE_READONLY |
4652 * PAGE_READWRITE |
4653 * PAGE_WRITEONLY |
4654 * PAGE_WRITECOPY
4655 *
4656 * AllocationAttributes
4657 * Can be a combination of:
4658 * SEC_IMAGE |
4659 * SEC_RESERVE
4660 *
4661 * FileHandle
4662 * Handle to a file to create a section mapped to a file
4663 * instead of a memory backed section;
4664 *
4665 * File
4666 * Unknown.
4667 *
4668 * RETURN VALUE
4669 * Status.
4670 *
4671 * @implemented
4672 */
4682{
4684 ULONG Protection;
4685 PSECTION *SectionObject = (PSECTION *)Section;
4686 BOOLEAN FileLock = FALSE;
4687 BOOLEAN HaveFileObject = FALSE;
4688
4689 // FIXME: Implement support for large pages
4691 {
4692 DPRINT1("SEC_LARGE_PAGES is not supported\n");
4694 }
4695
4696 /* Check if an ARM3 section is being created instead */
4698 {
4699 if (!(FileObject) && !(FileHandle))
4700 {
4701 return MmCreateArm3Section(Section,
4707 FileHandle,
4708 FileObject);
4709 }
4710 }
4711
4712 /* Convert section flag to page flag */
4714
4715 /* Check to make sure the protection is correct. Nt* does this already */
4717 if (Protection == MM_INVALID_PROTECTION)
4718 {
4719 DPRINT1("Page protection is invalid\n");
4721 }
4722
4723 /* Check if this is going to be a data or image backed file section */
4724 if ((FileHandle) || (FileObject))
4725 {
4726 /* These cannot be mapped with large pages */
4728 {
4729 DPRINT1("Large pages cannot be used with an image mapping\n");
4731 }
4732
4733 /* Did the caller pass a file object ? */
4734 if (FileObject)
4735 {
4736 /* Reference the object directly */
4738 HaveFileObject = TRUE;
4739 }
4740 else
4741 {
4742 /* Reference the file handle to get the object */
4744 MmMakeFileAccess[Protection],
4747 (PVOID*)&FileObject,
4748 NULL);
4749 if (!NT_SUCCESS(Status))
4750 {
4751 DPRINT1("Failed to get a handle to the FO: %lx\n", Status);
4752 return Status;
4753 }
4754
4755 /* Lock the file */
4757 if (!NT_SUCCESS(Status))
4758 {
4760 return Status;
4761 }
4762
4763 FileLock = TRUE;
4764
4765 /* Deny access if there are writes on the file */
4766#if 0
4768 {
4769 DPRINT1("Cannot create image maps with writers open on the file!\n");
4771 goto Quit;
4772 }
4773#else
4775 DPRINT1("Creating image map with writers open on the file!\n");
4776#endif
4777 }
4778 }
4779 else
4780 {
4781 /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
4783 }
4784
4785 if (FileObject == NULL)
4786 {
4788 goto Exit;
4789 }
4790
4792 {
4799 FileObject);
4800
4801 /* If the file was ivalid, and we got a FileObject passed, fall back to data section */
4802 if (!NT_SUCCESS(Status) && HaveFileObject)
4803 {
4804 AllocationAttributes &= ~SEC_IMAGE;
4805 }
4806 }
4807
4808#ifndef NEWCC
4810 {
4817 FileObject,
4818 FileHandle != NULL);
4819 }
4820#else
4821 else
4822 {
4829 FileObject);
4830 }
4831#endif
4832
4833Exit:
4834
4835 if (FileLock)
4837 if (FileObject)
4839
4840 return Status;
4841}
4842
4843/* This function is not used. It is left for future use, when per-process
4844 * address space is considered. */
4845#if 0
4846BOOLEAN
4847NTAPI
4848MmArePagesResident(
4852{
4854 BOOLEAN Ret = TRUE;
4856 LARGE_INTEGER SegmentOffset, RangeEnd;
4858
4860
4862 if (MemoryArea == NULL)
4863 {
4865 return FALSE;
4866 }
4867
4868 /* Only supported in old Mm for now */
4870 /* For file mappings */
4872
4873 Segment = MemoryArea->SectionData.Segment;
4875
4877 + MemoryArea->SectionData.ViewOffset;
4879 + MemoryArea->SectionData.ViewOffset;
4880
4881 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
4882 {
4884 if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
4885 {
4886 Ret = FALSE;
4887 break;
4888 }
4889 SegmentOffset.QuadPart += PAGE_SIZE;
4890 }
4891
4893
4895 return Ret;
4896}
4897#endif
4898
4899/* Like CcPurgeCache but for the in-memory segment */
4900BOOLEAN
4901NTAPI
4906{
4907 LARGE_INTEGER PurgeStart, PurgeEnd;
4909
4910 PurgeStart.QuadPart = Offset ? Offset->QuadPart : 0LL;
4911 if (Length && Offset)
4912 {
4913 if (!NT_SUCCESS(RtlLongLongAdd(PurgeStart.QuadPart, Length, &PurgeEnd.QuadPart)))
4914 return FALSE;
4915 }
4916
4918 if (!Segment)
4919 {
4920 /* Nothing to purge */
4921 return TRUE;
4922 }
4923
4925
4926 if (!Length || !Offset)
4927 {
4928 /* We must calculate the length for ourselves */
4929 /* FIXME: All of this is suboptimal */
4930 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
4931 if (!ElemCount)
4932 {
4933 /* No page. Nothing to purge */
4935 MmDereferenceSegment(Segment);
4936 return TRUE;
4937 }
4938
4940 PurgeEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
4941 }
4942
4943 /* Find byte offset of the page to start */
4944 PurgeStart.QuadPart = PAGE_ROUND_DOWN_64(PurgeStart.QuadPart);
4945
4946 while (PurgeStart.QuadPart < PurgeEnd.QuadPart)
4947 {
4949
4950 if (Entry == 0)
4951 {
4952 PurgeStart.QuadPart += PAGE_SIZE;
4953 continue;
4954 }
4955
4957 {
4958 ASSERT(SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY);
4959 /* The page is currently being read. Meaning someone will need it soon. Bad luck */
4961 MmDereferenceSegment(Segment);
4962 return FALSE;
4963 }
4964
4965 if (IS_WRITE_SSE(Entry))
4966 {
4967 /* We're trying to purge an entry which is being written. Restart this loop iteration */
4971 continue;
4972 }
4973
4974 if (SHARE_COUNT_FROM_SSE(Entry) > 0)
4975 {
4976 /* This page is currently in use. Bad luck */
4978 MmDereferenceSegment(Segment);
4979 return FALSE;
4980 }
4981
4982 /* We can let this page go */
4983 MmSetPageEntrySectionSegment(Segment, &PurgeStart, 0);
4985
4986 PurgeStart.QuadPart += PAGE_SIZE;
4987 }
4988
4989 /* This page is currently in use. Bad luck */
4991 MmDereferenceSegment(Segment);
4992 return TRUE;
4993}
4994
4995BOOLEAN
4996NTAPI
5001{
5003 LARGE_INTEGER RangeStart, RangeEnd;
5004 BOOLEAN Ret = TRUE;
5005
5006 RangeStart.QuadPart = Offset;
5007 if (!NT_SUCCESS(RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart)))
5008 return FALSE;
5009
5011 if (!Segment)
5012 return FALSE;
5013
5014 /* Find byte offset of the page to start */
5015 RangeStart.QuadPart = PAGE_ROUND_DOWN_64(RangeStart.QuadPart);
5016
5018
5019 while (RangeStart.QuadPart < RangeEnd.QuadPart)
5020 {
5022 if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
5023 {
5024 Ret = FALSE;
5025 break;
5026 }
5027
5028 RangeStart.QuadPart += PAGE_SIZE;
5029 }
5030
5032 MmDereferenceSegment(Segment);
5033
5034 return Ret;
5035}
5036
5038NTAPI
5043 _In_ PLARGE_INTEGER ValidDataLength)
5044{
5046
5047 /* There must be a segment for this call */
5048 ASSERT(Segment);
5049
5051
5052 MmDereferenceSegment(Segment);
5053
5054 return Status;
5055}
5056
5058NTAPI
5063{
5065 LARGE_INTEGER RangeStart, RangeEnd;
5067
5068 RangeStart.QuadPart = Offset;
5069 Status = RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart);
5070 if (!NT_SUCCESS(Status))
5071 return Status;
5072
5074 if (!Segment)
5076
5077 /* Find byte offset of the page to start */
5078 RangeStart.QuadPart = PAGE_ROUND_DOWN_64(RangeStart.QuadPart);
5079
5081
5082 while (RangeStart.QuadPart < RangeEnd.QuadPart)
5083 {
5085
5086 /* Let any pending read proceed */
5087 while (MM_IS_WAIT_PTE(Entry))
5088 {
5093 }
5094
5095 /* We are called from Cc, this can't be backed by the page files */
5097
5098 /* If there is no page there, there is nothing to make dirty */
5099 if (Entry != 0)
5100 {
5101 /* Dirtify the entry */
5103 }
5104
5105 RangeStart.QuadPart += PAGE_SIZE;
5106 }
5107
5109 MmDereferenceSegment(Segment);
5110
5111 return STATUS_SUCCESS;
5112}
5113
5115NTAPI
5121{
5122 LARGE_INTEGER FlushStart, FlushEnd;
5124
5125 if (Offset)
5126 {
5127 FlushStart = *Offset;
5128 Status = RtlLongLongAdd(FlushStart.QuadPart, Length, &FlushEnd.QuadPart);
5129 if (!NT_SUCCESS(Status))
5130 return Status;
5131 }
5132
5133 if (Iosb)
5134 Iosb->Information = 0;
5135
5137 if (!Segment)
5138 {
5139 /* Nothing to flush */
5140 goto Quit;
5141 }
5142
5144
5146
5147 if (!Offset)
5148 {
5149 FlushStart.QuadPart = 0;
5150
5151 /* FIXME: All of this is suboptimal */
5152 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
5153 if (!ElemCount)
5154 {
5155 /* No page. Nothing to flush */
5157 MmDereferenceSegment(Segment);
5158 goto Quit;
5159 }
5160
5162 FlushEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
5163 }
5164
5165 /* Find byte offset of the page to start */
5166 FlushStart.QuadPart = PAGE_ROUND_DOWN_64(FlushStart.QuadPart);
5167
5168 while (FlushStart.QuadPart < FlushEnd.QuadPart)
5169 {
5171
5172 if (IS_DIRTY_SSE(Entry))
5173 {
5174 MmCheckDirtySegment(Segment, &FlushStart, FALSE, FALSE);
5175
5176 if (Iosb)
5177 Iosb->Information += PAGE_SIZE;
5178 }
5179
5180 FlushStart.QuadPart += PAGE_SIZE;
5181 }
5182
5184 MmDereferenceSegment(Segment);
5185
5186Quit:
5187 /* FIXME: Handle failures */
5188 if (Iosb)
5189 Iosb->Status = STATUS_SUCCESS;
5190
5191 return STATUS_SUCCESS;
5192}
5193
5195BOOLEAN
5196NTAPI
5202{
5206
5207 ASSERT(Segment->Locked);
5208
5209 ASSERT((Offset->QuadPart % PAGE_SIZE) == 0);
5210
5211 DPRINT("Checking segment for file %wZ at offset 0x%I64X.\n", &Segment->FileObject->FileName, Offset->QuadPart);
5212
5214 if (Entry == 0)
5215 return FALSE;
5216
5218 if ((IS_DIRTY_SSE(Entry)) || ForceDirty)
5219 {
5220 BOOLEAN DirtyAgain;
5221
5222 /*
5223 * We got a dirty entry. This path is for the shared data,
5224 * be-it regular file maps or shared sections of DLLs
5225 */
5227 FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5228
5229 /* Insert the cleaned entry back. Mark it as write in progress, and clear the dirty bit. */
5233
5235
5236 if (FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5237 {
5239 KIRQL OldIrql;
5240
5241 /* We have to write it back to the file. Tell the FS driver who we are */
5242 if (PageOut)
5243 {
5244 LARGE_INTEGER EndOffset = *Offset;
5245
5247
5248 /* We need to disable all APCs */
5250
5251 EndOffset.QuadPart += PAGE_SIZE;
5253 &EndOffset,
5255 if (NT_SUCCESS(Status))
5256 {
5258 }
5259 else
5260 {
5261 /* Make sure we will not try to release anything */
5263 }
5264 }
5265 else
5266 {
5267 /* We don't have to lock. Say this is success */
5269 }
5270
5271 /* Go ahead and write the page, if previous locking succeeded */
5272 if (NT_SUCCESS(Status))
5273 {
5274 DPRINT("Writing page at offset %I64d for file %wZ, Pageout: %s\n",
5275 Offset->QuadPart, &Segment->FileObject->FileName, PageOut ? "TRUE" : "FALSE");
5276 Status = MiWritePage(Segment, Offset->QuadPart, Page);
5277 }
5278
5279 if (PageOut)
5280 {
5282 if (ResourceToRelease != NULL)
5283 {
5285 }
5287 }
5288 }
5289 else
5290 {
5291 /* This must only be called by the page-out path */
5292 ASSERT(PageOut);
5293
5294 /* And this must be for a shared section in a DLL */
5295 ASSERT(FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5296
5298 if (!SwapEntry)
5299 {
5300 SwapEntry = MmAllocSwapPage();
5301 }
5302
5303 if (SwapEntry)
5304 {
5305 Status = MmWriteToSwapPage(SwapEntry, Page);
5306 if (NT_SUCCESS(Status))
5307 {
5308 MmSetSavedSwapEntryPage(Page, SwapEntry);
5309 }
5310 else
5311 {
5312 MmFreeSwapPage(SwapEntry);
5313 }
5314 }
5315 else
5316 {
5317 DPRINT1("Failed to allocate a swap page!\n");
5319 }
5320 }
5321
5323
5324 /* Get the entry again */
5327
5328 if (!NT_SUCCESS(Status))
5329 {
5330 /* Damn, this failed. Consider this page as still dirty */
5331 DPRINT1("MiWritePage FAILED: Status 0x%08x!\n", Status);
5332 DirtyAgain = TRUE;
5333 }
5334 else
5335 {
5336 /* Check if someone dirtified this page while we were not looking */
5337 DirtyAgain = IS_DIRTY_SSE(Entry);
5338 }
5339
5340 /* Drop the reference we got, deleting the write altogether. */
5342 if (DirtyAgain)
5343 {
5345 }
5347 }
5348
5349 /* Were this page hanging there just for the sake of being present ? */
5351 {
5352 ULONG_PTR NewEntry = 0;
5353 /* Restore the swap entry here */
5354 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5355 {
5357 if (SwapEntry)
5358 NewEntry = MAKE_SWAP_SSE(SwapEntry);
5359 }
5360
5361 /* Yes. Release it */
5364 /* Tell the caller we released the page */
5365 return TRUE;
5366 }
5367
5368 return FALSE;
5369}
5370
5371/* This function is not used. It is left for future use, when per-process
5372 * address space is considered. */
5373#if 0
5375NTAPI
5376MmMakePagesDirty(
5380{
5383 LARGE_INTEGER SegmentOffset, RangeEnd;
5385
5387
5389 if (MemoryArea == NULL)
5390 {
5391 DPRINT1("Unable to find memory area at address %p.\n", Address);
5394 }
5395
5396 /* Only supported in old Mm for now */
5398 /* For file mappings */
5400
5401 Segment = MemoryArea->SectionData.Segment;
5403
5405 + MemoryArea->SectionData.ViewOffset;
5407 + MemoryArea->SectionData.ViewOffset;
5408
5409 DPRINT("MmMakePagesResident: Segment %p, 0x%I64x -> 0x%I64x\n", Segment, SegmentOffset.QuadPart, RangeEnd.QuadPart);
5410
5411 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
5412 {
5414
5415 /* Let any pending read proceed */
5416 while (MM_IS_WAIT_PTE(Entry))
5417 {
5423 Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset);
5424 }
5425
5426 /* We are called from Cc, this can't be backed by the page files */
5428
5429 /* If there is no page there, there is nothing to make dirty */
5430 if (Entry != 0)
5431 {
5432 /* Dirtify the entry */
5434 }
5435
5436 SegmentOffset.QuadPart += PAGE_SIZE;
5437 }
5438
5440
5442 return STATUS_SUCCESS;
5443}
5444#endif
5445
5447NTAPI
5449 _In_ PVOID _Section,
5451{
5452 PSECTION Section = _Section;
5453
5454 /* It makes no sense to extend an image mapping */
5455 if (Section->u.Flags.Image)
5457
5458 /* Nor is it possible to extend a page file mapping */
5459 if (!Section->u.Flags.File)
5461
5462 if (!MiIsRosSectionObject(Section))
5464
5465 /* We just extend the sizes. Shrinking is a no-op ? */
5466 if (NewSize->QuadPart > Section->SizeOfSection.QuadPart)
5467 {
5469 Section->SizeOfSection = *NewSize;
5470
5471 if (!Section->u.Flags.Reserve)
5472 {
5474 if (Segment->RawLength.QuadPart < NewSize->QuadPart)
5475 {
5476 Segment->RawLength = *NewSize;
5477 Segment->Length.QuadPart = (NewSize->QuadPart + PAGE_SIZE - 1) & ~((LONGLONG)PAGE_SIZE);
5478 }
5480 }
5481 }
5482
5483 return STATUS_SUCCESS;
5484}
5485
5486/* 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:97
#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_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
#define L(x)
Definition: resources.c:13
return Iosb
Definition: create.c:4403
#define ULONG_PTR
Definition: config.h:101
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define _IRQL_restores_
Definition: driverspecs.h:233
#define _IRQL_requires_(irql)
Definition: driverspecs.h:229
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define PagedPool
Definition: env_spec_w32.h:308
#define ExGetPreviousMode
Definition: ex.h:143
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1544
#define EXEFMT_LOAD_ASSUME_SEGMENTS_SORTED
Definition: exeformat.h:8
#define STATUS_ROS_EXEFMT_UNKNOWN_FORMAT
Definition: exeformat.h:72
#define PEFMT_FIELDS_EQUAL(TYPE1_, TYPE2_, FIELD_)
Definition: exeformat.h:165
#define EXEFMT_LOAD_ASSUME_SEGMENTS_PAGE_ALIGNED
Definition: exeformat.h:10
static __inline BOOLEAN IsPowerOf2(IN ULONG Number)
Definition: exeformat.h:134
static __inline BOOLEAN Intsafe_CanAddLong64(IN LONG64 Addend1, IN LONG64 Addend2)
Definition: exeformat.h:104
NTSTATUS(NTAPI * PEXEFMT_CB_READ_FILE)(IN PVOID File, IN PLARGE_INTEGER Offset, IN ULONG Length, OUT PVOID *Data, OUT PVOID *AllocBase, OUT PULONG ReadSize)
Definition: exeformat.h:36
#define EXEFMT_LOAD_ASSUME_SEGMENTS_NO_OVERLAP
Definition: exeformat.h:9
static __inline BOOLEAN Intsafe_CanMulULong32(IN ULONG Factor1, IN ULONG Factor2)
Definition: exeformat.h:123
NTSTATUS(NTAPI * PEXEFMT_LOADER)(IN CONST VOID *FileHeader, IN SIZE_T FileHeaderSize, IN PVOID File, OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, OUT PULONG Flags, IN PEXEFMT_CB_READ_FILE ReadFileCb, IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb)
Definition: exeformat.h:51
static __inline BOOLEAN Intsafe_CanAddULong32(IN ULONG Addend1, IN ULONG Addend2)
Definition: exeformat.h:109
#define EXEFMT_LOAD_HEADER_SIZE
Definition: exeformat.h:23
PMM_SECTION_SEGMENT(NTAPI * PEXEFMT_CB_ALLOCATE_SEGMENTS)(IN ULONG NrSegments)
Definition: exeformat.h:46
static __inline BOOLEAN IsAligned(IN ULONG Address, IN ULONG Alignment)
Definition: exeformat.h:147
static __inline BOOLEAN Intsafe_CanOffsetPointer(IN CONST VOID *Pointer, IN SIZE_T Offset)
Definition: exeformat.h:128
static __inline BOOLEAN Intsafe_AddULong32(OUT PULONG Result, IN ULONG Addend1, IN ULONG Addend2)
Definition: exeformat.h:114
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN PFCB IN FAT_FLUSH_TYPE FlushType
Definition: fatprocs.h:1083
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
#define STATUS_ACCESS_VIOLATION
@ FileEndOfFileInformation
Definition: from_kernel.h:81
_Must_inspect_result_ _In_ PDEVICE_OBJECT _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer
Definition: fsrtlfuncs.h:1369
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
#define FSRTL_MOD_WRITE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:61
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define OBJ_OPENLINK
Definition: winternl.h:230
#define OBJ_PERMANENT
Definition: winternl.h:226
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
@ ProcessHandleCount
Definition: winternl.h:1902
#define InterlockedDecrement64
Definition: interlocked.h:159
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:4611
NTSTATUS NTAPI MiRosUnmapViewOfSection(_In_ PEPROCESS Process, _In_ PMEMORY_AREA MemoryArea, _In_ PVOID BaseAddress, _In_ BOOLEAN SkipDebuggerNotify)
Definition: section.c:3626
VOID NTAPI MmUnmapLockedPages(IN PVOID BaseAddress, IN PMDL Mdl)
Definition: mdlsup.c:837
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
unsigned __int64 ULONG64
Definition: imports.h:198
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_COMMIT
Definition: mmtypes.h:100
#define SEC_IMAGE
Definition: mmtypes.h:97
struct _MMSUPPORT * PMMSUPPORT
#define SEC_FILE
Definition: mmtypes.h:96
#define SEC_LARGE_PAGES
Definition: mmtypes.h:103
#define SEC_NO_CHANGE
Definition: mmtypes.h:95
struct _MEMORY_BASIC_INFORMATION MEMORY_BASIC_INFORMATION
@ SectionBasicInformation
Definition: mmtypes.h:195
@ SectionImageInformation
Definition: mmtypes.h:196
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
#define OBJ_KERNEL_EXCLUSIVE
Definition: obtypes.h:91
NTSTATUS NTAPI MmCreateCacheSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
VOID NTAPI MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage)
Definition: sptab.c:321
_In_ PMEMORY_AREA MemoryArea
Definition: newmm.h:207
NTSTATUS NTAPI MmUnmapViewOfCacheSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
NTSTATUS NTAPI _MiMapViewOfSegment(PMMSUPPORT AddressSpace, PMM_SECTION_SEGMENT Segment, PVOID *BaseAddress, SIZE_T ViewSize, ULONG Protect, PLARGE_INTEGER ViewOffset, ULONG AllocationType, const char *file, int line)
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:209
VOID NTAPI MiInitializeSectionPageTable(PMM_SECTION_SEGMENT Segment)
Definition: sptab.c:165
#define _Outptr_result_bytebuffer_(s)
Definition: no_sal2.h:288
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _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:1324
#define SECTION_MAP_EXECUTE
Definition: nt_native.h:1293
#define PAGE_WRITECOPY
Definition: nt_native.h:1308
#define SECTION_MAP_WRITE
Definition: nt_native.h:1291
#define PAGE_NOCACHE
Definition: nt_native.h:1314
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define PAGE_READWRITE
Definition: nt_native.h:1307
#define PAGE_EXECUTE_READ
Definition: nt_native.h:1310
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1296
#define SECTION_QUERY
Definition: nt_native.h:1290
#define PAGE_EXECUTE
Definition: nt_native.h:1309
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define SEC_RESERVE
Definition: nt_native.h:1326
#define MEM_MAPPED
Definition: nt_native.h:1322
enum _SECTION_INHERIT SECTION_INHERIT
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define PAGE_EXECUTE_WRITECOPY
Definition: nt_native.h:1312
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
#define MEM_COMMIT
Definition: nt_native.h:1316
#define PAGE_NOACCESS
Definition: nt_native.h:1305
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1311
#define PAGE_GUARD
Definition: nt_native.h:1313
#define TYPE_ALIGNMENT(t)
Definition: ntbasedef.h:117
#define RTL_CONTAINS_FIELD(Struct, Size, Field)
Definition: ntbasedef.h:687
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:684
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
#define SEC_BASED
#define IMAGE_SCN_MEM_WRITE
Definition: ntimage.h:241
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC
Definition: ntimage.h:376
#define IMAGE_SCN_CNT_INITIALIZED_DATA
Definition: ntimage.h:231
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC
Definition: ntimage.h:377
#define IMAGE_SCN_CNT_CODE
Definition: ntimage.h:230
#define IMAGE_SCN_MEM_EXECUTE
Definition: ntimage.h:239
#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION
Definition: ntimage.h:458
#define IMAGE_SCN_MEM_READ
Definition: ntimage.h:240
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA
Definition: ntimage.h:232
#define IMAGE_SCN_MEM_SHARED
Definition: ntimage.h:238
NTSTATUS NTAPI MiSimpleRead(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PVOID Buffer, ULONG Length, BOOLEAN Paging, PIO_STATUS_BLOCK ReadStatus)
Definition: io.c:109
NTSTATUS NTAPI FsRtlGetFileSize(IN PFILE_OBJECT FileObject, IN OUT PLARGE_INTEGER FileSize)
Definition: fastio.c:815
_Check_return_ NTSTATUS NTAPI FsRtlAcquireFileForModWriteEx(_In_ PFILE_OBJECT FileObject, _In_ PLARGE_INTEGER EndingOffset, _Outptr_result_maybenull_ PERESOURCE *ResourceToRelease)
Lock a file object before flushing pages to disk. To be called by the Modified Page Writer (MPW)
Definition: fastio.c:1858
VOID NTAPI FsRtlReleaseFileForModWrite(_In_ PFILE_OBJECT FileObject, _In_ PERESOURCE ResourceToRelease)
Unlock a file object after flushing pages to disk. To be called by the Modified Page Writer (MPW) aft...
Definition: fastio.c:1965
VOID NTAPI FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1665
VOID NTAPI FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1640
NTSTATUS NTAPI FsRtlAcquireToCreateMappedSection(_In_ PFILE_OBJECT FileObject, _In_ ULONG SectionPageProtection)
Definition: fastio.c:1653
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:46
#define MmGetPageEntrySectionSegment(S, O)
Definition: mm.h:1600
#define MI_SET_PROCESS2(x)
Definition: mm.h:328
#define MM_NOIRQL
Definition: mm.h:70
@ MI_USAGE_SECTION
Definition: mm.h:342
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1694
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
KSPIN_LOCK MmPfnLock
Definition: krnlinit.c:45
#define DIRTY_SSE(E)
Definition: mm.h:1373
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:1395
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:1385
#define MAX_SHARE_COUNT
Definition: mm.h:1384
#define SHARE_COUNT_FROM_SSE(E)
Definition: mm.h:1383
#define MC_USER
Definition: mm.h:112
PVOID NTAPI MiMapPageInHyperSpace(IN PEPROCESS Process, IN PFN_NUMBER Page, IN PKIRQL OldIrql)
Definition: hypermap.c:28
#define MM_VIRTMEM_GRANULARITY
Definition: mm.h:102
NTSTATUS NTAPI MmFreeMemoryArea(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_FREE_PAGE_FUNC FreePage, PVOID FreePageContext)
Definition: marea.c:258
#define IS_WRITE_SSE(E)
Definition: mm.h:1377
#define MmUnlockSectionSegment(x)
Definition: mm.h:1403
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:1375
struct _MM_IMAGE_SECTION_OBJECT * PMM_IMAGE_SECTION_OBJECT
#define SWAPENTRY_FROM_SSE(E)
Definition: mm.h:1371
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:1372
ULONG_PTR SWAPENTRY
Definition: mm.h:57
#define MA_GetEndingAddress(_MemoryArea)
Definition: mm.h:250
PFN_NUMBER NTAPI MmGetPfnForProcess(struct _EPROCESS *Process, PVOID Address)
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:249
#define PAGE_IS_WRITABLE
Definition: mm.h:158
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1707
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:1381
#define MI_SET_USAGE(x)
Definition: mm.h:326
#define MM_SEGMENT_INDELETE
Definition: mm.h:244
#define PAGE_FLAGS_VALID_FOR_SECTION
Definition: mm.h:139
#define MM_SEGMENT_INCREATE
Definition: mm.h:245
NTSTATUS NTAPI MmExtendSection(_In_ PVOID Section, _Inout_ PLARGE_INTEGER NewSize)
Definition: section.c:5448
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:1714
BOOLEAN NTAPI MmIsPagePresent(struct _EPROCESS *Process, PVOID Address)
VOID NTAPI MmFreeSwapPage(SWAPENTRY Entry)
Definition: pagefile.c:291
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1768
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:164
NTSTATUS NTAPI MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN MyWait, PPFN_NUMBER AllocatedPage)
Definition: balance.c:313
#define PFN_FROM_SSE(E)
Definition: mm.h:1366
#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:246
#define PAGE_ROUND_DOWN_64(x)
Definition: mm.h:136
NTSTATUS NTAPI MmCreateVirtualMapping(struct _EPROCESS *Process, PVOID Address, ULONG flProtect, PFN_NUMBER Page)
NTSTATUS NTAPI MmCreatePageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY SwapEntry)
VOID NTAPI MmDeleteRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
struct _MM_SECTION_SEGMENT * PMM_SECTION_SEGMENT
PVOID NTAPI MmFindGap(PMMSUPPORT AddressSpace, SIZE_T Length, ULONG_PTR Granularity, BOOLEAN TopDown)
Definition: marea.c:190
#define DECREF_SSE(E)
Definition: mm.h:1387
#define MM_ROUND_DOWN(x, s)
Definition: mm.h:129
#define MM_IS_WAIT_PTE(E)
Definition: mm.h:1368
#define MM_PHYSICALMEMORY_SEGMENT
Definition: mm.h:242
#define BUMPREF_SSE(E)
Definition: mm.h:1386
#define IS_SWAP_FROM_SSE(E)
Definition: mm.h:1367
NTSTATUS NTAPI MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
Definition: balance.c:72
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1729
VOID NTAPI MmInsertRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
#define MM_DATAFILE_SEGMENT
Definition: mm.h:243
#define STATUS_MM_RESTART_OPERATION
Definition: mm.h:104
#define PAGE_IS_READABLE
Definition: mm.h:150
#define WRITE_SSE(E)
Definition: mm.h:1376
#define PAGE_IS_WRITECOPY
Definition: mm.h:170
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
const ULONG MmProtectToValue[32]
Definition: page.c:71
VOID NTAPI MmDeleteVirtualMapping(IN PEPROCESS Process, IN PVOID Address, OUT PBOOLEAN WasDirty, OUT PPFN_NUMBER Page)
Definition: page.c:177
#define STATUS_INVALID_VIEW_SIZE
Definition: ntstatus.h:361
#define STATUS_INVALID_IMAGE_WIN_64
Definition: ntstatus.h:1029
#define STATUS_SECTION_PROTECTION
Definition: ntstatus.h:408
#define STATUS_INVALID_IMAGE_FORMAT
Definition: ntstatus.h:453
#define STATUS_SECTION_NOT_IMAGE
Definition: ntstatus.h:403
#define STATUS_NOT_MAPPED_VIEW
Definition: ntstatus.h:355
#define STATUS_INVALID_IMAGE_NOT_MZ
Definition: ntstatus.h:633
#define STATUS_INVALID_IMAGE_PROTECT
Definition: ntstatus.h:634
#define STATUS_FILE_LOCKED_WITH_WRITERS
Definition: ntstatus.h:168
#define STATUS_INVALID_FILE_FOR_SECTION
Definition: ntstatus.h:362
#define STATUS_MAPPED_FILE_SIZE_ZERO
Definition: ntstatus.h:616
#define STATUS_INVALID_PARAMETER_6
Definition: ntstatus.h:574
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:336
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:354
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:399
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:333
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:262
#define STATUS_SECTION_NOT_EXTENDED
Definition: ntstatus.h:465
#define STATUS_IMAGE_NOT_AT_BASE
Definition: ntstatus.h:192
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1039
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1136
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define CONST
Definition: pedump.c:81
#define IMAGE_NT_SIGNATURE
Definition: pedump.c:93
#define IMAGE_FILE_DLL
Definition: pedump.c:169
#define IMAGE_DOS_SIGNATURE
Definition: pedump.c:89
struct _IMAGE_SECTION_HEADER IMAGE_SECTION_HEADER
static WCHAR Address[46]
Definition: ping.c:68
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
#define _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:88
#define ASSERT_IRQL_LESS(x)
Definition: debug.h:253
ULONG * PPFN_NUMBER
Definition: ke.h:9
static GENERIC_MAPPING MmpSectionMapping
Definition: section.c:221
PFN_NUMBER Page
Definition: section.c:5205
NTSTATUS NTAPI MmMapViewInSystemSpace(IN PVOID SectionObject, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:4501
BOOLEAN NTAPI MmCanFileBeTruncated(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
Definition: section.c:4309
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:2359
VOID NTAPI MmpDeleteSection(PVOID ObjectBody)
Definition: section.c:2170
static LARGE_INTEGER TinyTime
Definition: section.c:61
PMM_IMAGE_SECTION_OBJECT ImageSectionObjectFromSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:118
NTSTATUS NTAPI ElfFmtCreateSection(IN CONST VOID *FileHeader, IN SIZE_T FileHeaderSize, IN PVOID File, OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, OUT PULONG Flags, IN PEXEFMT_CB_READ_FILE ReadFileCb, IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb)
NTSTATUS NTAPI 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:4027
NTSTATUS NTAPI MmMakeSegmentDirty(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
Definition: section.c:5059
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:283
static PMM_SECTION_SEGMENT NTAPI ExeFmtpAllocateSegments(IN ULONG NrSegments)
Definition: section.c:2620
ULONG_PTR MmSubsectionBase
Definition: section.c:194
static BOOLEAN NTAPI MmspPageAlignSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2871
NTSTATUS NTAPI MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, MEMORY_AREA *MemoryArea, PVOID Address, BOOLEAN Locked)
Definition: section.c:1556
NTSTATUS MmspWaitForFileLock(PFILE_OBJECT File)
Definition: section.c:905
PLARGE_INTEGER BOOLEAN BOOLEAN PageOut
Definition: section.c:5202
static BOOLEAN NTAPI MmspCheckSegmentBounds(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2820
#define MmSetPageEntrySectionSegment(S, O, E)
Definition: section.c:56
static ULONG SectionCharacteristicsToProtect[16]
Definition: section.c:196
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:4674
static BOOLEAN MiPurgeImageSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:4364
POBJECT_TYPE MmSectionObjectType
Definition: section.c:192
VOID NTAPI _MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line)
Definition: section.c:77
static NTSTATUS MmUnmapViewOfSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
Definition: section.c:3562
BOOLEAN NTAPI MmPurgeSegment(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length)
Definition: section.c:4902
BOOLEAN NTAPI MmUnsharePageEntrySectionSegment(PMEMORY_AREA MemoryArea, PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, BOOLEAN Dirty, BOOLEAN PageOut, ULONG_PTR *InEntry)
Definition: section.c:1087
NTSTATUS NTAPI MmQuerySectionView(PMEMORY_AREA MemoryArea, PVOID Address, PMEMORY_BASIC_INFORMATION Info, PSIZE_T ResultLength)
Definition: section.c:2131
NTSTATUS NTAPI MmProtectSectionView(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PVOID BaseAddress, SIZE_T Length, ULONG Protect, PULONG OldProtect)
Definition: section.c:2087
VOID NTAPI MmpCloseSection(IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG ProcessHandleCount, IN ULONG SystemHandleCount)
Definition: section.c:2223
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:4514
static VOID NTAPI FreeSegmentPage(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
Definition: section.c:958
NTSTATUS NTAPI MiWritePage(PMM_SECTION_SEGMENT Segment, LONGLONG SegOffset, PFN_NUMBER Page)
Definition: section.c:236
VOID NTAPI MmpFreePageFileSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:915
static VOID NTAPI MmspAssertSegmentsPageAligned(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2759
static VOID NTAPI MmspSortSegments(IN OUT PMM_IMAGE_SECTION_OBJECT ImageSectionObject, IN ULONG Flags)
Definition: section.c:2794
NTSTATUS NTAPI MmAccessFaultSectionView(PMMSUPPORT AddressSpace, MEMORY_AREA *MemoryArea, PVOID Address, BOOLEAN Locked)
Definition: section.c:1934
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4410
static NTSTATUS MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
Definition: section.c:1168
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:3808
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:2640
NTSTATUS MmCreateImageSection(PSECTION *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER UMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, PFILE_OBJECT FileObject)
Definition: section.c:3207
BOOLEAN NTAPI MmIsDataSectionResident(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
Definition: section.c:4997
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:5116
static VOID NTAPI MmspAssertSegmentsSorted(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2723
NTSTATUS NTAPI MmInitSectionImplementation(VOID)
Definition: section.c:2326
static PEXEFMT_LOADER ExeFmtpLoaders[]
Definition: section.c:2609
static VOID MmAlterViewAttributes(PMMSUPPORT AddressSpace, PVOID BaseAddress, SIZE_T RegionSize, ULONG OldType, ULONG OldProtect, ULONG NewType, ULONG NewProtect)
Definition: section.c:1465
VOID NTAPI MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
Definition: section.c:1062
VOID NTAPI _MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line)
Definition: section.c:68
NTSTATUS NTAPI MmMakeDataSectionResident(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length, _In_ PLARGE_INTEGER ValidDataLength)
Definition: section.c:5039
static int __cdecl MmspCompareSegments(const void *x, const void *y)
Definition: section.c:2774
KEVENT MmWaitPageEvent
Definition: section.c:64
static VOID NTAPI MmspAssertSegmentsNoOverlap(IN PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:2737
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:1190
static PMM_SECTION_SEGMENT MiGrabDataSection(PSECTION_OBJECT_POINTERS SectionObjectPointer)
Definition: section.c:88
#define DIE(ARGS_)
NTSTATUS ExeFmtpCreateImageSection(PFILE_OBJECT FileObject, PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
Definition: section.c:3054
PLARGE_INTEGER BOOLEAN ForceDirty
Definition: section.c:5200
static VOID MmFreeSectionPage(PVOID Context, MEMORY_AREA *MemoryArea, PVOID Address, PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
Definition: section.c:3478
NTSTATUS NTAPI MmCreatePhysicalMemorySection(VOID)
Definition: section.c:2235
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:3399
PLARGE_INTEGER Offset
Definition: section.c:5199
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:181
PMEMORY_AREA MemoryArea
Definition: section.c:180
LARGE_INTEGER Offset
Definition: section.c:182
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::@1686 Misc
DWORD PointerToRawData
Definition: pedump.c:290
Definition: typedefs.h:120
struct _MEMORY_AREA::@1928 SectionData
ULONG Flags
Definition: mm.h:257
BOOLEAN DeleteInProgress
Definition: mm.h:258
ULONG Type
Definition: mm.h:256
MMVAD VadNode
Definition: mm.h:254
union _MMADDRESS_NODE::@2801 u1
struct _MMADDRESS_NODE * Parent
Definition: mmtypes.h:649
ULONG PhysicalMemory
Definition: mmtypes.h:473
ULONG NoChange
Definition: mmtypes.h:486
ULONG_PTR Protection
Definition: mmtypes.h:696
ULONG_PTR VadType
Definition: mmtypes.h:694
ULONG_PTR EndingVpn
Definition: mmtypes.h:730
PCONTROL_AREA ControlArea
Definition: mmtypes.h:736
ULONG_PTR StartingVpn
Definition: mmtypes.h:729
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:734
union _MMVAD::@2803 u
ULONG_PTR NumberGenericTableElements
Definition: mmtypes.h:668
MMADDRESS_NODE BalancedRoot
Definition: mmtypes.h:662
PMM_SECTION_SEGMENT Segments
Definition: mm.h:239
PFILE_OBJECT FileObject
Definition: mm.h:231
SECTION_IMAGE_INFORMATION ImageInformation
Definition: mm.h:236
Definition: mm.h:481
PULONG Flags
Definition: mm.h:210
LARGE_INTEGER RawLength
Definition: mm.h:205
PLONG64 ReferenceCount
Definition: mm.h:207
FAST_MUTEX Lock
Definition: mm.h:204
PFILE_OBJECT FileObject
Definition: mm.h:202
struct _MM_SECTION_SEGMENT::@1927 Image
BOOLEAN WriteCopy
Definition: mm.h:211
ULONG Protection
Definition: mm.h:209
LARGE_INTEGER Length
Definition: mm.h:206
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::@2812 u
PSEGMENT Segment
Definition: mmtypes.h:812
ULONG InitialPageProtection
Definition: mmtypes.h:819
LARGE_INTEGER SizeOfSection
Definition: mmtypes.h:813
PVOID BasedAddress
Definition: mmtypes.h:418
union _SEGMENT::@2795 u2
PSECTION_IMAGE_INFORMATION ImageInformation
Definition: mmtypes.h:426
Definition: fci.c:127
Definition: parser.c:49
static PMEM_HOOK PageTable[TOTAL_PAGES]
Definition: memory.c:43
#define max(a, b)
Definition: svc.c:63
#define TAG_MM_SECTION_SEGMENT
Definition: tag.h:113
#define TAG_MM_REGION
Definition: tag.h:110
#define STATUS_PENDING
Definition: telnetd.h:14
else
Definition: tritemp.h:161
#define LL
Definition: tui.h:166
#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_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:3782
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2664
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2274
_In_ PLARGE_INTEGER _Out_ struct _ERESOURCE ** ResourceToRelease
Definition: iotypes.h:1598
#define FO_RANDOM_ACCESS
Definition: iotypes.h:1796
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FO_DELETE_ON_CLOSE
Definition: iotypes.h:1792
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ WrPageIn
Definition: ketypes.h:476
@ Executive
Definition: ketypes.h:467
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
KAPC_STATE
Definition: ketypes.h:1711
_Must_inspect_result_ _Outptr_result_bytebuffer_ ViewSize PVOID * MappedBase
Definition: mmfuncs.h:492
#define MmInitializeMdl(_MemoryDescriptorList, _BaseVa, _Length)
#define BYTES_TO_PAGES(Size)
_Must_inspect_result_ _In_ ULONG NewProtect
Definition: mmfuncs.h:682
#define MmGetMdlPfnArray(_Mdl)
_In_opt_ PLARGE_INTEGER NewFileSize
Definition: mmfuncs.h:608
MMFLUSH_TYPE
Definition: mmtypes.h:183
MDL
Definition: mmtypes.h:117
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define MDL_IO_PAGE_READ
Definition: mmtypes.h:24
#define MDL_MAPPED_TO_SYSTEM_VA
Definition: mmtypes.h:18
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ BOOLEAN Restart)
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlGetElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ ULONG I)
NTSYSAPI ULONG NTAPI RtlNumberGenericTableElements(_In_ PRTL_GENERIC_TABLE Table)
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:20
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