ReactOS 0.4.16-dev-1493-ge7358c5
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 ObDereferenceObject(PhysSection);
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
3667 Segment = MemoryArea->SectionData.Segment;
3668 ImageSectionObject = ImageSectionObjectFromSegment(Segment);
3669 SectionSegments = ImageSectionObject->Segments;
3670 NrSegments = ImageSectionObject->NrSegments;
3671
3673
3674 /* Search for the current segment within the section segments
3675 * and calculate the image base address */
3676 for (i = 0; i < NrSegments; i++)
3677 {
3678 if (Segment == &SectionSegments[i])
3679 {
3680 ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
3681 break;
3682 }
3683 }
3684 if (i >= NrSegments)
3685 {
3686 KeBugCheck(MEMORY_MANAGEMENT);
3687 }
3688
3689 for (i = 0; i < NrSegments; i++)
3690 {
3691 PVOID SBaseAddress = (PVOID)
3692 ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
3693
3694 Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
3695 if (!NT_SUCCESS(Status))
3696 {
3697 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3698 SBaseAddress, Process, Status);
3700 }
3701 }
3702 DPRINT("One mapping less for %p\n", ImageSectionObject->FileObject->SectionObjectPointer);
3703 InterlockedDecrement(&ImageSectionObject->MapCount);
3704 }
3705 else
3706 {
3708 PMMVAD Vad = &MemoryArea->VadNode;
3709 PCONTROL_AREA ControlArea = Vad->ControlArea;
3712 LARGE_INTEGER ViewOffset;
3713 ViewOffset.QuadPart = MemoryArea->SectionData.ViewOffset;
3714
3715 InterlockedIncrement64(Segment->ReferenceCount);
3716
3717 ViewSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
3718
3720 if (!NT_SUCCESS(Status))
3721 {
3722 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3725 }
3726
3727 /* These might be deleted now */
3728 Vad = NULL;
3729 MemoryArea = NULL;
3730
3732 {
3733 /* Don't bother */
3734 MmDereferenceSegment(Segment);
3735 return STATUS_SUCCESS;
3736 }
3738
3739 FileObject = Segment->FileObject;
3741
3742 /* Don't bother for auto-delete closed file. */
3744 {
3746 MmDereferenceSegment(Segment);
3747 return STATUS_SUCCESS;
3748 }
3749
3750 /*
3751 * Flush only when last mapping is deleted.
3752 * FIXME: Why ControlArea == NULL? Or rather: is ControlArea ever not NULL here?
3753 */
3754 if (ControlArea == NULL || ControlArea->NumberOfMappedViews == 1)
3755 {
3756 while (ViewSize > 0)
3757 {
3758 ULONG FlushSize = min(ViewSize, PAGE_ROUND_DOWN(MAXULONG));
3759 MmFlushSegment(FileObject->SectionObjectPointer,
3760 &ViewOffset,
3761 FlushSize,
3762 NULL);
3763 ViewSize -= FlushSize;
3764 ViewOffset.QuadPart += FlushSize;
3765 }
3766 }
3767
3769 MmDereferenceSegment(Segment);
3770 }
3771
3772 /* Notify debugger */
3773 if (ImageBaseAddress && !SkipDebuggerNotify) DbgkUnMapViewOfSection(ImageBaseAddress);
3774
3775 return STATUS_SUCCESS;
3776}
3777
3778
3779
3780
3804NTAPI
3806 _In_ HANDLE SectionHandle,
3807 _In_ SECTION_INFORMATION_CLASS SectionInformationClass,
3808 _Out_ PVOID SectionInformation,
3809 _In_ SIZE_T SectionInformationLength,
3811{
3812 PSECTION Section;
3815 PAGED_CODE();
3816
3818 if (PreviousMode != KernelMode)
3819 {
3820 _SEH2_TRY
3821 {
3822 ProbeForWrite(SectionInformation,
3823 SectionInformationLength,
3824 __alignof(ULONG));
3825 if (ResultLength != NULL)
3826 {
3828 sizeof(*ResultLength),
3829 __alignof(SIZE_T));
3830 }
3831 }
3833 {
3835 }
3836 _SEH2_END;
3837 }
3838
3839 if (SectionInformationClass == SectionBasicInformation)
3840 {
3841 if (SectionInformationLength < sizeof(SECTION_BASIC_INFORMATION))
3842 {
3844 }
3845 }
3846 else if (SectionInformationClass == SectionImageInformation)
3847 {
3848 if (SectionInformationLength < sizeof(SECTION_IMAGE_INFORMATION))
3849 {
3851 }
3852 }
3853 else
3854 {
3856 }
3857
3858 Status = ObReferenceObjectByHandle(SectionHandle,
3862 (PVOID*)(PVOID)&Section,
3863 NULL);
3864 if (!NT_SUCCESS(Status))
3865 {
3866 DPRINT1("Failed to reference section: 0x%lx\n", Status);
3867 return Status;
3868 }
3869
3870 switch(SectionInformationClass)
3871 {
3873 {
3874 SECTION_BASIC_INFORMATION Sbi = { 0 };
3875
3876 Sbi.Size = Section->SizeOfSection;
3877 Sbi.BaseAddress = NULL;
3878
3879 if (Section->u.Flags.File)
3880 Sbi.Attributes |= SEC_FILE;
3881 if (Section->u.Flags.Image)
3882 Sbi.Attributes |= SEC_IMAGE;
3883 if (Section->u.Flags.Commit)
3884 Sbi.Attributes |= SEC_COMMIT;
3885 if (Section->u.Flags.Reserve)
3886 Sbi.Attributes |= SEC_RESERVE;
3887 if (Section->u.Flags.Based)
3888 Sbi.Attributes |= SEC_BASED;
3889
3890 if (Section->u.Flags.Image)
3891 {
3892 if (!MiIsRosSectionObject(Section))
3893 {
3894 /* Not supported yet */
3895 ASSERT(FALSE);
3896 }
3897 }
3898 else if (MiIsRosSectionObject(Section))
3899 {
3900 Sbi.BaseAddress = (PVOID)((PMM_SECTION_SEGMENT)Section->Segment)->Image.VirtualAddress;
3901 }
3902 else
3903 {
3904 Sbi.BaseAddress = Section->Segment->BasedAddress;
3905 }
3906
3907 _SEH2_TRY
3908 {
3909 *((SECTION_BASIC_INFORMATION*)SectionInformation) = Sbi;
3910 if (ResultLength != NULL)
3911 {
3912 *ResultLength = sizeof(Sbi);
3913 }
3914 }
3916 {
3918 }
3919 _SEH2_END;
3920 break;
3921 }
3923 {
3924 if (!Section->u.Flags.Image)
3925 {
3927 }
3928 else if (MiIsRosSectionObject(Section))
3929 {
3930 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
3931
3932 _SEH2_TRY
3933 {
3935 *Sii = ImageSectionObject->ImageInformation;
3936 if (ResultLength != NULL)
3937 {
3938 *ResultLength = sizeof(*Sii);
3939 }
3940 }
3942 {
3944 }
3945 _SEH2_END;
3946 }
3947 else
3948 {
3949 _SEH2_TRY
3950 {
3952 *Sii = *Section->Segment->u2.ImageInformation;
3953 if (ResultLength != NULL)
3954 *ResultLength = sizeof(*Sii);
3955 }
3957 {
3959 }
3960 _SEH2_END;
3961 }
3962 break;
3963 }
3964 default:
3965 DPRINT1("Unknown SectionInformationClass: %d\n", SectionInformationClass);
3967 }
3968
3969 ObDereferenceObject(Section);
3970
3971 return Status;
3972}
3973
3974/**********************************************************************
3975 * NAME EXPORTED
3976 * MmMapViewOfSection
3977 *
3978 * DESCRIPTION
3979 * Maps a view of a section into the virtual address space of a
3980 * process.
3981 *
3982 * ARGUMENTS
3983 * Section
3984 * Pointer to the section object.
3985 *
3986 * ProcessHandle
3987 * Pointer to the process.
3988 *
3989 * BaseAddress
3990 * Desired base address (or NULL) on entry;
3991 * Actual base address of the view on exit.
3992 *
3993 * ZeroBits
3994 * Number of high order address bits that must be zero.
3995 *
3996 * CommitSize
3997 * Size in bytes of the initially committed section of
3998 * the view.
3999 *
4000 * SectionOffset
4001 * Offset in bytes from the beginning of the section
4002 * to the beginning of the view.
4003 *
4004 * ViewSize
4005 * Desired length of map (or zero to map all) on entry
4006 * Actual length mapped on exit.
4007 *
4008 * InheritDisposition
4009 * Specified how the view is to be shared with
4010 * child processes.
4011 *
4012 * AllocationType
4013 * Type of allocation for the pages.
4014 *
4015 * Protect
4016 * Protection for the committed region of the view.
4017 *
4018 * RETURN VALUE
4019 * Status.
4020 *
4021 * @implemented
4022 */
4034{
4035 PSECTION Section;
4038 BOOLEAN NotAtBase = FALSE;
4039 BOOLEAN IsAttached = FALSE;
4041
4043 {
4044 DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
4046 Process,
4048 ZeroBits,
4049 CommitSize,
4051 ViewSize,
4054 Protect);
4055 }
4056
4057 ASSERT(Process);
4058
4060 {
4062 }
4063
4065 {
4067 IsAttached = TRUE;
4068 }
4069
4070 /* FIXME: We should keep this, but it would break code checking equality */
4071 Protect &= ~PAGE_NOCACHE;
4072
4073 Section = SectionObject;
4074 AddressSpace = &Process->Vm;
4075
4076 if (Section->u.Flags.NoChange)
4078
4080
4081 if (Section->u.Flags.Image)
4082 {
4083 ULONG i;
4084 ULONG NrSegments;
4085 ULONG_PTR ImageBase;
4086 SIZE_T ImageSize;
4087 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
4088 PMM_SECTION_SEGMENT SectionSegments;
4089
4090 ImageSectionObject = ((PMM_IMAGE_SECTION_OBJECT)Section->Segment);
4091 SectionSegments = ImageSectionObject->Segments;
4092 NrSegments = ImageSectionObject->NrSegments;
4093
4094 ASSERT(ImageSectionObject->RefCount > 0);
4095
4096 ImageBase = (ULONG_PTR)*BaseAddress;
4097 if (ImageBase == 0)
4098 {
4099 ImageBase = (ULONG_PTR)ImageSectionObject->BasedAddress;
4100 }
4101
4102 ImageSize = 0;
4103 for (i = 0; i < NrSegments; i++)
4104 {
4105 ULONG_PTR MaxExtent;
4106 MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
4107 SectionSegments[i].Length.QuadPart);
4108 ImageSize = max(ImageSize, MaxExtent);
4109 }
4110
4111 ImageSectionObject->ImageInformation.ImageFileSize = (ULONG)ImageSize;
4112
4113 /* Check for an illegal base address */
4114 if (((ImageBase + ImageSize) > (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS) ||
4115 ((ImageBase + ImageSize) < ImageSize))
4116 {
4117 ASSERT(*BaseAddress == NULL);
4118 ImageBase = ALIGN_DOWN_BY((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - ImageSize,
4120 NotAtBase = TRUE;
4121 }
4122 else if (ImageBase != ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY))
4123 {
4124 ASSERT(*BaseAddress == NULL);
4125 ImageBase = ALIGN_DOWN_BY(ImageBase, MM_VIRTMEM_GRANULARITY);
4126 NotAtBase = TRUE;
4127 }
4128
4129 /* Check there is enough space to map the section at that point. */
4130 if (!MmIsAddressRangeFree(AddressSpace, (PVOID)ImageBase, PAGE_ROUND_UP(ImageSize)))
4131 {
4132 /* Fail if the user requested a fixed base address. */
4133 if ((*BaseAddress) != NULL)
4134 {
4136 goto Exit;
4137 }
4138 /* Otherwise find a gap to map the image. */
4140 if (ImageBase == 0)
4141 {
4143 goto Exit;
4144 }
4145 /* Remember that we loaded image at a different base address */
4146 NotAtBase = TRUE;
4147 }
4148
4149 for (i = 0; i < NrSegments; i++)
4150 {
4151 PVOID SBaseAddress = (PVOID)
4152 ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4153 MmLockSectionSegment(&SectionSegments[i]);
4155 TRUE,
4156 &SectionSegments[i],
4157 &SBaseAddress,
4158 SectionSegments[i].Length.QuadPart,
4159 SectionSegments[i].Protection,
4160 0,
4161 0);
4162 MmUnlockSectionSegment(&SectionSegments[i]);
4163 if (!NT_SUCCESS(Status))
4164 {
4165 /* roll-back */
4166 while (i--)
4167 {
4168 SBaseAddress = ((char*)ImageBase + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
4169 MmLockSectionSegment(&SectionSegments[i]);
4170 MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
4171 MmUnlockSectionSegment(&SectionSegments[i]);
4172 }
4173
4174 goto Exit;
4175 }
4176 }
4177
4178 *BaseAddress = (PVOID)ImageBase;
4179 *ViewSize = ImageSize;
4180
4181 DPRINT("Mapped %p for section pointer %p\n", ImageSectionObject, ImageSectionObject->FileObject->SectionObjectPointer);
4182
4183 /* One more map */
4184 InterlockedIncrement(&ImageSectionObject->MapCount);
4185 }
4186 else
4187 {
4189 LONGLONG ViewOffset;
4190
4191 ASSERT(Segment->RefCount > 0);
4192
4193 /* check for write access */
4196 {
4198 goto Exit;
4199 }
4200 /* check for read access */
4203 {
4205 goto Exit;
4206 }
4207 /* check for execute access */
4210 {
4212 goto Exit;
4213 }
4214
4215 if (SectionOffset == NULL)
4216 {
4217 ViewOffset = 0;
4218 }
4219 else
4220 {
4221 SectionOffset->QuadPart &= ~(PAGE_SIZE - 1);
4222 ViewOffset = SectionOffset->QuadPart;
4223 }
4224
4225 /* Check if the offset and size would cause an overflow */
4226 if (((ULONG64)ViewOffset + *ViewSize) < (ULONG64)ViewOffset)
4227 {
4228 DPRINT1("Section offset overflows\n");
4230 goto Exit;
4231 }
4232
4233 /* Check if the offset and size are bigger than the section itself */
4234 if (((ULONG64)ViewOffset + *ViewSize) > (ULONG64)Section->SizeOfSection.QuadPart)
4235 {
4236 /* This is allowed for physical memory sections and kernel mode callers */
4237 if (!Section->u.Flags.PhysicalMemory || (ExGetPreviousMode() == UserMode))
4238 {
4239 DPRINT1("Section offset and size are larger than section\n");
4241 goto Exit;
4242 }
4243 }
4244
4245 if ((*ViewSize) == 0)
4246 {
4247 /* Calculate a view size and make sure it doesn't overflow a SIZE_T */
4248 ULONG64 CalculatedSize = Section->SizeOfSection.QuadPart - ViewOffset;
4249 if (CalculatedSize > SIZE_T_MAX)
4250 {
4251 DPRINT1("ViewSize is larger than SIZE_T_MAX\n");
4253 goto Exit;
4254 }
4255
4256 *ViewSize = (SIZE_T)CalculatedSize;
4257 }
4258 else if ((ExGetPreviousMode() == UserMode) &&
4259 (((*ViewSize)+ViewOffset) > Section->SizeOfSection.QuadPart) &&
4260 (!Section->u.Flags.Reserve))
4261 {
4262 /* Dubious */
4263 (*ViewSize) = MIN(Section->SizeOfSection.QuadPart - ViewOffset, SIZE_T_MAX - PAGE_SIZE);
4264 }
4265
4267
4270 FALSE,
4271 Segment,
4273 *ViewSize,
4274 Protect,
4275 ViewOffset,
4278 if (!NT_SUCCESS(Status))
4279 {
4280 goto Exit;
4281 }
4282 }
4283
4284 if (NotAtBase)
4286 else
4288
4289Exit:
4290
4292
4293 if (IsAttached)
4294 {
4296 }
4297
4298 return Status;
4299}
4300
4301/*
4302 * @unimplemented
4303 */
4304BOOLEAN
4305NTAPI
4309{
4310 BOOLEAN Ret;
4312
4313 /* Check whether an ImageSectionObject exists */
4314 if (SectionObjectPointer->ImageSectionObject != NULL)
4315 {
4316 DPRINT1("ERROR: File can't be truncated because it has an image section\n");
4317 return FALSE;
4318 }
4319
4321 if (!Segment)
4322 {
4323 /* There is no data section. It's fine to do anything. */
4324 return TRUE;
4325 }
4326
4328 if ((Segment->SectionCount == 0) ||
4329 ((Segment->SectionCount == 1) && (SectionObjectPointer->SharedCacheMap != NULL)))
4330 {
4331 /* If the cache is the only one holding a reference to the segment, then it's fine to resize */
4332 Ret = TRUE;
4333 }
4334 else if (NewFileSize != NULL)
4335 {
4336 /* We can't shrink, but we can extend */
4337 Ret = NewFileSize->QuadPart >= Segment->RawLength.QuadPart;
4338#if DBG
4339 if (!Ret)
4340 {
4341 DPRINT1("Cannot truncate data: New Size %I64d, Segment Size %I64d\n", NewFileSize->QuadPart, Segment->RawLength.QuadPart);
4342 }
4343#endif
4344 }
4345 else
4346 {
4347 DPRINT1("ERROR: File can't be truncated because it has references held to its data section\n");
4348 Ret = FALSE;
4349 }
4350
4352 MmDereferenceSegment(Segment);
4353
4354 DPRINT("FIXME: didn't check for outstanding write probes\n");
4355
4356 return Ret;
4357}
4358
4359static
4360BOOLEAN
4362{
4364
4366
4367 /* Loop over all entries */
4368 for (PageTable = RtlEnumerateGenericTable(&Segment->PageTable, TRUE);
4369 PageTable != NULL;
4371 {
4372 for (ULONG i = 0; i < _countof(PageTable->PageEntries); i++)
4373 {
4374 ULONG_PTR Entry = PageTable->PageEntries[i];
4376
4377 if (!Entry)
4378 continue;
4379
4381 {
4382 /* I/O ongoing or swap entry. Someone mapped this file as we were not looking */
4384 return FALSE;
4385 }
4386
4387 /* Regular entry */
4390
4391 /* Properly remove using the used API */
4392 Offset.QuadPart = PageTable->FileOffset.QuadPart + (i << PAGE_SHIFT);
4395 }
4396 }
4397
4399
4400 return TRUE;
4401}
4402
4403/*
4404 * @implemented
4405 */
4409{
4410 switch(FlushType)
4411 {
4412 case MmFlushForDelete:
4413 {
4414 /*
4415 * FIXME: Check for outstanding write probes on Data section.
4416 * How do we do that ?
4417 */
4418 }
4419 /* Fall-through */
4420 case MmFlushForWrite:
4421 {
4422 KIRQL OldIrql = MiAcquirePfnLock();
4423 PMM_IMAGE_SECTION_OBJECT ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4424
4425 DPRINT("Deleting or modifying %p\n", SectionObjectPointer);
4426
4427 /* Wait for concurrent creation or deletion of image to be done */
4428 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4429 while (ImageSectionObject && (ImageSectionObject->SegFlags & (MM_SEGMENT_INCREATE | MM_SEGMENT_INDELETE)))
4430 {
4431 MiReleasePfnLock(OldIrql);
4433 OldIrql = MiAcquirePfnLock();
4434 ImageSectionObject = SectionObjectPointer->ImageSectionObject;
4435 }
4436
4437 if (!ImageSectionObject)
4438 {
4439 DPRINT("No image section object. Accepting\n");
4440 /* Nothing to do */
4441 MiReleasePfnLock(OldIrql);
4442 return TRUE;
4443 }
4444
4445 /* Do we have open sections or mappings on it ? */
4446 if ((ImageSectionObject->SectionCount) || (ImageSectionObject->MapCount))
4447 {
4448 /* We do. No way to delete it */
4449 MiReleasePfnLock(OldIrql);
4450 DPRINT("Denying. There are mappings open\n");
4451 return FALSE;
4452 }
4453
4454 /* There are no sections open on it, but we must still have pages around. Discard everything */
4455 ImageSectionObject->SegFlags |= MM_IMAGE_SECTION_FLUSH_DELETE;
4456 InterlockedIncrement64(&ImageSectionObject->RefCount);
4457 MiReleasePfnLock(OldIrql);
4458
4459 DPRINT("Purging\n");
4460
4461 for (ULONG i = 0; i < ImageSectionObject->NrSegments; i++)
4462 {
4463 if (!MiPurgeImageSegment(&ImageSectionObject->Segments[i]))
4464 break;
4465 }
4466
4467 /* Grab lock again */
4468 OldIrql = MiAcquirePfnLock();
4469
4470 if (!(ImageSectionObject->SegFlags & MM_IMAGE_SECTION_FLUSH_DELETE))
4471 {
4472 /*
4473 * Someone actually created a section while we were not looking.
4474 * Drop our ref and deny.
4475 * MmDereferenceSegmentWithLock releases Pfn lock
4476 */
4477 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4478 return FALSE;
4479 }
4480
4481 /* We should be the last one holding a ref here. */
4482 ASSERT(ImageSectionObject->RefCount == 1);
4483 ASSERT(ImageSectionObject->SectionCount == 0);
4484
4485 /* Dereference the first segment, this will free everything & release the lock */
4486 MmDereferenceSegmentWithLock(&ImageSectionObject->Segments[0], OldIrql);
4487 return TRUE;
4488 }
4489 }
4490 return FALSE;
4491}
4492
4493/*
4494 * @implemented
4495 */
4497NTAPI
4501{
4503
4504 SectionOffset.QuadPart = 0;
4505
4507}
4508
4510NTAPI
4517 )
4518{
4519 PSECTION Section = SectionObject;
4523
4525
4526 PAGED_CODE();
4527
4529 {
4531 &MmSession,
4532 MappedBase,
4533 ViewSize,
4535 }
4536
4537 DPRINT("MmMapViewInSystemSpaceEx() called\n");
4538
4539 /* unsupported for now */
4540 ASSERT(Section->u.Flags.Image == 0);
4541
4542 Section = SectionObject;
4544
4545 if (*ViewSize == 0)
4546 {
4547 LONGLONG MapSizeLL;
4548
4549 /* Page-align the mapping */
4550 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4551
4552 if (!NT_SUCCESS(RtlLongLongSub(Section->SizeOfSection.QuadPart, SectionOffset->QuadPart, &MapSizeLL)))
4554
4555 if (!NT_SUCCESS(RtlLongLongToSIZET(MapSizeLL, ViewSize)))
4557 }
4558 else
4559 {
4560 LONGLONG HelperLL;
4561
4562 /* Get the map end */
4563 if (!NT_SUCCESS(RtlLongLongAdd(SectionOffset->QuadPart, *ViewSize, &HelperLL)))
4565
4566 /* Round it up, if needed */
4567 if (HelperLL % PAGE_SIZE)
4568 {
4569 if (!NT_SUCCESS(RtlLongLongAdd(HelperLL, PAGE_SIZE - (HelperLL % PAGE_SIZE), &HelperLL)))
4571 }
4572
4573 /* Now that we have the mapping end, we can align down its start */
4574 SectionOffset->LowPart = PAGE_ROUND_DOWN(SectionOffset->LowPart);
4575
4576 /* Get the new size */
4577 if (!NT_SUCCESS(RtlLongLongSub(HelperLL, SectionOffset->QuadPart, &HelperLL)))
4579
4580 if (!NT_SUCCESS(RtlLongLongToSIZET(HelperLL, ViewSize)))
4582 }
4583
4585
4587
4589
4591 Section->u.Flags.Image,
4592 Segment,
4593 MappedBase,
4594 *ViewSize,
4596 SectionOffset->QuadPart,
4597 SEC_RESERVE);
4598
4601
4602 return Status;
4603}
4604
4605/* This function must be called with address space lock held */
4607NTAPI
4609{
4610 DPRINT("MmUnmapViewInSystemSpace() called\n");
4611
4613}
4614
4615/**********************************************************************
4616 * NAME EXPORTED
4617 * MmCreateSection@
4618 *
4619 * DESCRIPTION
4620 * Creates a section object.
4621 *
4622 * ARGUMENTS
4623 * SectionObject (OUT)
4624 * Caller supplied storage for the resulting pointer
4625 * to a SECTION_OBJECT instance;
4626 *
4627 * DesiredAccess
4628 * Specifies the desired access to the section can be a
4629 * combination of:
4630 * STANDARD_RIGHTS_REQUIRED |
4631 * SECTION_QUERY |
4632 * SECTION_MAP_WRITE |
4633 * SECTION_MAP_READ |
4634 * SECTION_MAP_EXECUTE
4635 *
4636 * ObjectAttributes [OPTIONAL]
4637 * Initialized attributes for the object can be used
4638 * to create a named section;
4639 *
4640 * MaximumSize
4641 * Maximizes the size of the memory section. Must be
4642 * non-NULL for a page-file backed section.
4643 * If value specified for a mapped file and the file is
4644 * not large enough, file will be extended.
4645 *
4646 * SectionPageProtection
4647 * Can be a combination of:
4648 * PAGE_READONLY |
4649 * PAGE_READWRITE |
4650 * PAGE_WRITEONLY |
4651 * PAGE_WRITECOPY
4652 *
4653 * AllocationAttributes
4654 * Can be a combination of:
4655 * SEC_IMAGE |
4656 * SEC_RESERVE
4657 *
4658 * FileHandle
4659 * Handle to a file to create a section mapped to a file
4660 * instead of a memory backed section;
4661 *
4662 * File
4663 * Unknown.
4664 *
4665 * RETURN VALUE
4666 * Status.
4667 *
4668 * @implemented
4669 */
4679{
4681 ULONG Protection;
4682 PSECTION *SectionObject = (PSECTION *)Section;
4683 BOOLEAN FileLock = FALSE;
4684 BOOLEAN HaveFileObject = FALSE;
4685
4686 // FIXME: Implement support for large pages
4688 {
4689 DPRINT1("SEC_LARGE_PAGES is not supported\n");
4691 }
4692
4693 /* Check if an ARM3 section is being created instead */
4695 {
4696 if (!(FileObject) && !(FileHandle))
4697 {
4698 return MmCreateArm3Section(Section,
4704 FileHandle,
4705 FileObject);
4706 }
4707 }
4708
4709 /* Convert section flag to page flag */
4711
4712 /* Check to make sure the protection is correct. Nt* does this already */
4714 if (Protection == MM_INVALID_PROTECTION)
4715 {
4716 DPRINT1("Page protection is invalid\n");
4718 }
4719
4720 /* Check if this is going to be a data or image backed file section */
4721 if ((FileHandle) || (FileObject))
4722 {
4723 /* These cannot be mapped with large pages */
4725 {
4726 DPRINT1("Large pages cannot be used with an image mapping\n");
4728 }
4729
4730 /* Did the caller pass a file object ? */
4731 if (FileObject)
4732 {
4733 /* Reference the object directly */
4735 HaveFileObject = TRUE;
4736 }
4737 else
4738 {
4739 /* Reference the file handle to get the object */
4741 MmMakeFileAccess[Protection],
4744 (PVOID*)&FileObject,
4745 NULL);
4746 if (!NT_SUCCESS(Status))
4747 {
4748 DPRINT1("Failed to get a handle to the FO: %lx\n", Status);
4749 return Status;
4750 }
4751
4752 /* Lock the file */
4754 if (!NT_SUCCESS(Status))
4755 {
4757 return Status;
4758 }
4759
4760 FileLock = TRUE;
4761
4762 /* Deny access if there are writes on the file */
4763#if 0
4765 {
4766 DPRINT1("Cannot create image maps with writers open on the file!\n");
4768 goto Quit;
4769 }
4770#else
4772 DPRINT1("Creating image map with writers open on the file!\n");
4773#endif
4774 }
4775 }
4776 else
4777 {
4778 /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
4780 }
4781
4782 if (FileObject == NULL)
4783 {
4785 goto Exit;
4786 }
4787
4789 {
4796 FileObject);
4797
4798 /* If the file was ivalid, and we got a FileObject passed, fall back to data section */
4799 if (!NT_SUCCESS(Status) && HaveFileObject)
4800 {
4801 AllocationAttributes &= ~SEC_IMAGE;
4802 }
4803 }
4804
4805#ifndef NEWCC
4807 {
4814 FileObject,
4815 FileHandle != NULL);
4816 }
4817#else
4818 else
4819 {
4826 FileObject);
4827 }
4828#endif
4829
4830Exit:
4831
4832 if (FileLock)
4834 if (FileObject)
4836
4837 return Status;
4838}
4839
4840/* This function is not used. It is left for future use, when per-process
4841 * address space is considered. */
4842#if 0
4843BOOLEAN
4844NTAPI
4845MmArePagesResident(
4849{
4851 BOOLEAN Ret = TRUE;
4853 LARGE_INTEGER SegmentOffset, RangeEnd;
4855
4857
4859 if (MemoryArea == NULL)
4860 {
4862 return FALSE;
4863 }
4864
4865 /* Only supported in old Mm for now */
4867 /* For file mappings */
4869
4870 Segment = MemoryArea->SectionData.Segment;
4872
4874 + MemoryArea->SectionData.ViewOffset;
4876 + MemoryArea->SectionData.ViewOffset;
4877
4878 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
4879 {
4881 if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
4882 {
4883 Ret = FALSE;
4884 break;
4885 }
4886 SegmentOffset.QuadPart += PAGE_SIZE;
4887 }
4888
4890
4892 return Ret;
4893}
4894#endif
4895
4896/* Like CcPurgeCache but for the in-memory segment */
4897BOOLEAN
4898NTAPI
4903{
4904 LARGE_INTEGER PurgeStart, PurgeEnd;
4906
4907 PurgeStart.QuadPart = Offset ? Offset->QuadPart : 0LL;
4908 if (Length && Offset)
4909 {
4910 if (!NT_SUCCESS(RtlLongLongAdd(PurgeStart.QuadPart, Length, &PurgeEnd.QuadPart)))
4911 return FALSE;
4912 }
4913
4915 if (!Segment)
4916 {
4917 /* Nothing to purge */
4918 return TRUE;
4919 }
4920
4922
4923 if (!Length || !Offset)
4924 {
4925 /* We must calculate the length for ourselves */
4926 /* FIXME: All of this is suboptimal */
4927 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
4928 if (!ElemCount)
4929 {
4930 /* No page. Nothing to purge */
4932 MmDereferenceSegment(Segment);
4933 return TRUE;
4934 }
4935
4937 PurgeEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
4938 }
4939
4940 /* Find byte offset of the page to start */
4941 PurgeStart.QuadPart = PAGE_ROUND_DOWN_64(PurgeStart.QuadPart);
4942
4943 while (PurgeStart.QuadPart < PurgeEnd.QuadPart)
4944 {
4946
4947 if (Entry == 0)
4948 {
4949 PurgeStart.QuadPart += PAGE_SIZE;
4950 continue;
4951 }
4952
4954 {
4955 ASSERT(SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY);
4956 /* The page is currently being read. Meaning someone will need it soon. Bad luck */
4958 MmDereferenceSegment(Segment);
4959 return FALSE;
4960 }
4961
4962 if (IS_WRITE_SSE(Entry))
4963 {
4964 /* We're trying to purge an entry which is being written. Restart this loop iteration */
4968 continue;
4969 }
4970
4971 if (SHARE_COUNT_FROM_SSE(Entry) > 0)
4972 {
4973 /* This page is currently in use. Bad luck */
4975 MmDereferenceSegment(Segment);
4976 return FALSE;
4977 }
4978
4979 /* We can let this page go */
4980 MmSetPageEntrySectionSegment(Segment, &PurgeStart, 0);
4982
4983 PurgeStart.QuadPart += PAGE_SIZE;
4984 }
4985
4986 /* This page is currently in use. Bad luck */
4988 MmDereferenceSegment(Segment);
4989 return TRUE;
4990}
4991
4992BOOLEAN
4993NTAPI
4998{
5000 LARGE_INTEGER RangeStart, RangeEnd;
5001 BOOLEAN Ret = TRUE;
5002
5003 RangeStart.QuadPart = Offset;
5004 if (!NT_SUCCESS(RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart)))
5005 return FALSE;
5006
5008 if (!Segment)
5009 return FALSE;
5010
5011 /* Find byte offset of the page to start */
5012 RangeStart.QuadPart = PAGE_ROUND_DOWN_64(RangeStart.QuadPart);
5013
5015
5016 while (RangeStart.QuadPart < RangeEnd.QuadPart)
5017 {
5019 if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
5020 {
5021 Ret = FALSE;
5022 break;
5023 }
5024
5025 RangeStart.QuadPart += PAGE_SIZE;
5026 }
5027
5029 MmDereferenceSegment(Segment);
5030
5031 return Ret;
5032}
5033
5035NTAPI
5040 _In_ PLARGE_INTEGER ValidDataLength)
5041{
5043
5044 /* There must be a segment for this call */
5045 ASSERT(Segment);
5046
5048
5049 MmDereferenceSegment(Segment);
5050
5051 return Status;
5052}
5053
5055NTAPI
5060{
5062 LARGE_INTEGER RangeStart, RangeEnd;
5064
5065 RangeStart.QuadPart = Offset;
5066 Status = RtlLongLongAdd(RangeStart.QuadPart, Length, &RangeEnd.QuadPart);
5067 if (!NT_SUCCESS(Status))
5068 return Status;
5069
5071 if (!Segment)
5073
5074 /* Find byte offset of the page to start */
5075 RangeStart.QuadPart = PAGE_ROUND_DOWN_64(RangeStart.QuadPart);
5076
5078
5079 while (RangeStart.QuadPart < RangeEnd.QuadPart)
5080 {
5082
5083 /* Let any pending read proceed */
5084 while (MM_IS_WAIT_PTE(Entry))
5085 {
5090 }
5091
5092 /* We are called from Cc, this can't be backed by the page files */
5094
5095 /* If there is no page there, there is nothing to make dirty */
5096 if (Entry != 0)
5097 {
5098 /* Dirtify the entry */
5100 }
5101
5102 RangeStart.QuadPart += PAGE_SIZE;
5103 }
5104
5106 MmDereferenceSegment(Segment);
5107
5108 return STATUS_SUCCESS;
5109}
5110
5112NTAPI
5118{
5119 LARGE_INTEGER FlushStart, FlushEnd;
5121
5122 if (Offset)
5123 {
5124 FlushStart = *Offset;
5125 Status = RtlLongLongAdd(FlushStart.QuadPart, Length, &FlushEnd.QuadPart);
5126 if (!NT_SUCCESS(Status))
5127 return Status;
5128 }
5129
5130 if (Iosb)
5131 Iosb->Information = 0;
5132
5134 if (!Segment)
5135 {
5136 /* Nothing to flush */
5137 goto Quit;
5138 }
5139
5141
5143
5144 if (!Offset)
5145 {
5146 FlushStart.QuadPart = 0;
5147
5148 /* FIXME: All of this is suboptimal */
5149 ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable);
5150 if (!ElemCount)
5151 {
5152 /* No page. Nothing to flush */
5154 MmDereferenceSegment(Segment);
5155 goto Quit;
5156 }
5157
5159 FlushEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE;
5160 }
5161
5162 /* Find byte offset of the page to start */
5163 FlushStart.QuadPart = PAGE_ROUND_DOWN_64(FlushStart.QuadPart);
5164
5165 while (FlushStart.QuadPart < FlushEnd.QuadPart)
5166 {
5168
5169 if (IS_DIRTY_SSE(Entry))
5170 {
5171 MmCheckDirtySegment(Segment, &FlushStart, FALSE, FALSE);
5172
5173 if (Iosb)
5174 Iosb->Information += PAGE_SIZE;
5175 }
5176
5177 FlushStart.QuadPart += PAGE_SIZE;
5178 }
5179
5181 MmDereferenceSegment(Segment);
5182
5183Quit:
5184 /* FIXME: Handle failures */
5185 if (Iosb)
5186 Iosb->Status = STATUS_SUCCESS;
5187
5188 return STATUS_SUCCESS;
5189}
5190
5192BOOLEAN
5193NTAPI
5199{
5203
5204 ASSERT(Segment->Locked);
5205
5206 ASSERT((Offset->QuadPart % PAGE_SIZE) == 0);
5207
5208 DPRINT("Checking segment for file %wZ at offset 0x%I64X.\n", &Segment->FileObject->FileName, Offset->QuadPart);
5209
5211 if (Entry == 0)
5212 return FALSE;
5213
5215 if ((IS_DIRTY_SSE(Entry)) || ForceDirty)
5216 {
5217 BOOLEAN DirtyAgain;
5218
5219 /*
5220 * We got a dirty entry. This path is for the shared data,
5221 * be-it regular file maps or shared sections of DLLs
5222 */
5224 FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5225
5226 /* Insert the cleaned entry back. Mark it as write in progress, and clear the dirty bit. */
5230
5232
5233 if (FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5234 {
5236 KIRQL OldIrql;
5237
5238 /* We have to write it back to the file. Tell the FS driver who we are */
5239 if (PageOut)
5240 {
5241 LARGE_INTEGER EndOffset = *Offset;
5242
5244
5245 /* We need to disable all APCs */
5247
5248 EndOffset.QuadPart += PAGE_SIZE;
5250 &EndOffset,
5252 if (NT_SUCCESS(Status))
5253 {
5255 }
5256 else
5257 {
5258 /* Make sure we will not try to release anything */
5260 }
5261 }
5262 else
5263 {
5264 /* We don't have to lock. Say this is success */
5266 }
5267
5268 /* Go ahead and write the page, if previous locking succeeded */
5269 if (NT_SUCCESS(Status))
5270 {
5271 DPRINT("Writing page at offset %I64d for file %wZ, Pageout: %s\n",
5272 Offset->QuadPart, &Segment->FileObject->FileName, PageOut ? "TRUE" : "FALSE");
5273 Status = MiWritePage(Segment, Offset->QuadPart, Page);
5274 }
5275
5276 if (PageOut)
5277 {
5279 if (ResourceToRelease != NULL)
5280 {
5282 }
5284 }
5285 }
5286 else
5287 {
5288 /* This must only be called by the page-out path */
5289 ASSERT(PageOut);
5290
5291 /* And this must be for a shared section in a DLL */
5292 ASSERT(FlagOn(Segment->Image.Characteristics, IMAGE_SCN_MEM_SHARED));
5293
5295 if (!SwapEntry)
5296 {
5297 SwapEntry = MmAllocSwapPage();
5298 }
5299
5300 if (SwapEntry)
5301 {
5302 Status = MmWriteToSwapPage(SwapEntry, Page);
5303 if (NT_SUCCESS(Status))
5304 {
5305 MmSetSavedSwapEntryPage(Page, SwapEntry);
5306 }
5307 else
5308 {
5309 MmFreeSwapPage(SwapEntry);
5310 }
5311 }
5312 else
5313 {
5314 DPRINT1("Failed to allocate a swap page!\n");
5316 }
5317 }
5318
5320
5321 /* Get the entry again */
5324
5325 if (!NT_SUCCESS(Status))
5326 {
5327 /* Damn, this failed. Consider this page as still dirty */
5328 DPRINT1("MiWritePage FAILED: Status 0x%08x!\n", Status);
5329 DirtyAgain = TRUE;
5330 }
5331 else
5332 {
5333 /* Check if someone dirtified this page while we were not looking */
5334 DirtyAgain = IS_DIRTY_SSE(Entry);
5335 }
5336
5337 /* Drop the reference we got, deleting the write altogether. */
5339 if (DirtyAgain)
5340 {
5342 }
5344 }
5345
5346 /* Were this page hanging there just for the sake of being present ? */
5348 {
5349 ULONG_PTR NewEntry = 0;
5350 /* Restore the swap entry here */
5351 if (!FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT))
5352 {
5354 if (SwapEntry)
5355 NewEntry = MAKE_SWAP_SSE(SwapEntry);
5356 }
5357
5358 /* Yes. Release it */
5361 /* Tell the caller we released the page */
5362 return TRUE;
5363 }
5364
5365 return FALSE;
5366}
5367
5368/* This function is not used. It is left for future use, when per-process
5369 * address space is considered. */
5370#if 0
5372NTAPI
5373MmMakePagesDirty(
5377{
5380 LARGE_INTEGER SegmentOffset, RangeEnd;
5382
5384
5386 if (MemoryArea == NULL)
5387 {
5388 DPRINT1("Unable to find memory area at address %p.\n", Address);
5391 }
5392
5393 /* Only supported in old Mm for now */
5395 /* For file mappings */
5397
5398 Segment = MemoryArea->SectionData.Segment;
5400
5402 + MemoryArea->SectionData.ViewOffset;
5404 + MemoryArea->SectionData.ViewOffset;
5405
5406 DPRINT("MmMakePagesResident: Segment %p, 0x%I64x -> 0x%I64x\n", Segment, SegmentOffset.QuadPart, RangeEnd.QuadPart);
5407
5408 while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
5409 {
5411
5412 /* Let any pending read proceed */
5413 while (MM_IS_WAIT_PTE(Entry))
5414 {
5420 Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset);
5421 }
5422
5423 /* We are called from Cc, this can't be backed by the page files */
5425
5426 /* If there is no page there, there is nothing to make dirty */
5427 if (Entry != 0)
5428 {
5429 /* Dirtify the entry */
5431 }
5432
5433 SegmentOffset.QuadPart += PAGE_SIZE;
5434 }
5435
5437
5439 return STATUS_SUCCESS;
5440}
5441#endif
5442
5444NTAPI
5446 _In_ PVOID _Section,
5448{
5449 PSECTION Section = _Section;
5450
5451 /* It makes no sense to extend an image mapping */
5452 if (Section->u.Flags.Image)
5454
5455 /* Nor is it possible to extend a page file mapping */
5456 if (!Section->u.Flags.File)
5458
5459 if (!MiIsRosSectionObject(Section))
5461
5462 /* We just extend the sizes. Shrinking is a no-op ? */
5463 if (NewSize->QuadPart > Section->SizeOfSection.QuadPart)
5464 {
5466 Section->SizeOfSection = *NewSize;
5467
5468 if (!Section->u.Flags.Reserve)
5469 {
5471 if (Segment->RawLength.QuadPart < NewSize->QuadPart)
5472 {
5473 Segment->RawLength = *NewSize;
5474 Segment->Length.QuadPart = (NewSize->QuadPart + PAGE_SIZE - 1) & ~((LONGLONG)PAGE_SIZE);
5475 }
5477 }
5478 }
5479
5480 return STATUS_SUCCESS;
5481}
5482
5483/* EOF */
NTSTATUS MiMapViewInSystemSpace(_In_ PVOID Section, _In_ PMMSESSION Session, _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, _Inout_ PSIZE_T ViewSize, _Inout_ PLARGE_INTEGER SectionOffset)
Definition: section.c:1039
MMSESSION MmSession
Definition: section.c:107
NTSTATUS NTAPI MmCreateArm3Section(OUT PVOID *SectionObject, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER InputMaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: section.c:2102
VOID NTAPI MiDeleteARM3Section(PVOID ObjectBody)
Definition: section.c:2951
NTSTATUS NTAPI MmMapViewOfArm3Section(IN PVOID SectionObject, IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:2531
ACCESS_MASK MmMakeFileAccess[8]
Definition: section.c:32
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:140
#define PAGED_CODE()
#define CODE_SEG(...)
ULONG ReadLength
#define ALIGN_DOWN_BY(size, align)
#define ALIGN_UP_BY(size, align)
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG _In_ KPROCESSOR_MODE PreviousMode
ULONG_PTR PFN_NUMBER
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define __cdecl
Definition: accygwin.h:79
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define MIN(x, y)
Definition: rdesktop.h:171
#define DPRINT1
Definition: precomp.h:8
#define MAXULONG_PTR
Definition: basetsd.h:103
#define InterlockedIncrement64(a)
Definition: btrfs_drv.h:143
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1434
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
Definition: bufpool.h:45
Definition: File.h:16
#define _Requires_lock_held_(lock)
#define _Requires_lock_not_held_(lock)
#define _Releases_lock_(lock)
#define _Requires_exclusive_lock_held_(lock)
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))
_Out_ PKIRQL Irql
Definition: csq.h:179
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
VOID NTAPI DbgkUnMapViewOfSection(IN PVOID BaseAddress)
Definition: dbgkutil.c:436
#define BufferSize
Definition: mmc.h:75
LPWSTR Name
Definition: desk.c:124
#define SIZE_T_MAX
Definition: dhcpd.h:91
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define PAGE_READONLY
Definition: compat.h:138
#define SECTION_MAP_READ
Definition: compat.h:139
#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
@ FileEndOfFileInformation
Definition: from_kernel.h:81
_Must_inspect_result_ _In_ PDEVICE_OBJECT _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer
Definition: fsrtlfuncs.h:1369
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
#define FSRTL_MOD_WRITE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:61
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define OBJ_OPENLINK
Definition: winternl.h:230
#define OBJ_PERMANENT
Definition: winternl.h:226
@ ProcessHandleCount
Definition: winternl.h:1902
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#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:4608
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:1321
#define SECTION_MAP_EXECUTE
Definition: nt_native.h:1290
#define PAGE_WRITECOPY
Definition: nt_native.h:1305
#define SECTION_MAP_WRITE
Definition: nt_native.h:1288
#define PAGE_NOCACHE
Definition: nt_native.h:1311
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define PAGE_EXECUTE_READ
Definition: nt_native.h:1307
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
#define SECTION_QUERY
Definition: nt_native.h:1287
#define PAGE_EXECUTE
Definition: nt_native.h:1306
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define SEC_RESERVE
Definition: nt_native.h:1323
#define MEM_MAPPED
Definition: nt_native.h:1319
enum _SECTION_INHERIT SECTION_INHERIT
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define PAGE_EXECUTE_WRITECOPY
Definition: nt_native.h:1309
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
#define MEM_COMMIT
Definition: nt_native.h:1313
#define PAGE_NOACCESS
Definition: nt_native.h:1302
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
#define PAGE_GUARD
Definition: nt_native.h:1310
#define TYPE_ALIGNMENT(t)
Definition: ntbasedef.h:117
#define RTL_CONTAINS_FIELD(Struct, Size, Field)
Definition: ntbasedef.h: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:5445
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:268
#define STATUS_INVALID_IMAGE_WIN_64
Definition: ntstatus.h:901
#define STATUS_SECTION_PROTECTION
Definition: ntstatus.h:314
#define STATUS_INVALID_IMAGE_FORMAT
Definition: ntstatus.h:359
#define STATUS_SECTION_NOT_IMAGE
Definition: ntstatus.h:309
#define STATUS_NOT_MAPPED_VIEW
Definition: ntstatus.h:262
#define STATUS_INVALID_IMAGE_NOT_MZ
Definition: ntstatus.h:539
#define STATUS_INVALID_IMAGE_PROTECT
Definition: ntstatus.h:540
#define STATUS_FILE_LOCKED_WITH_WRITERS
Definition: ntstatus.h:112
#define STATUS_INVALID_FILE_FOR_SECTION
Definition: ntstatus.h:269
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define STATUS_MAPPED_FILE_SIZE_ZERO
Definition: ntstatus.h:522
#define STATUS_INVALID_PARAMETER_6
Definition: ntstatus.h:480
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:243
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:261
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:305
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:182
#define STATUS_SECTION_NOT_EXTENDED
Definition: ntstatus.h:371
#define STATUS_IMAGE_NOT_AT_BASE
Definition: ntstatus.h:117
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1039
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1136
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define CONST
Definition: pedump.c:81
#define IMAGE_NT_SIGNATURE
Definition: pedump.c:93
#define IMAGE_FILE_DLL
Definition: pedump.c:169
#define IMAGE_DOS_SIGNATURE
Definition: pedump.c:89
struct _IMAGE_SECTION_HEADER IMAGE_SECTION_HEADER
static WCHAR Address[46]
Definition: ping.c:68
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:181
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:184
PVOID pBuffer
VOID NTAPI MmBuildMdlFromPages(PMDL Mdl, PPFN_NUMBER Pages)
Definition: pagefile.c:111
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
@ Failed
Definition: arc.h:79
#define ASSERT_IRQL_LESS(x)
Definition: debug.h:253
ULONG * PPFN_NUMBER
Definition: ke.h:9
static GENERIC_MAPPING MmpSectionMapping
Definition: section.c:221
PFN_NUMBER Page
Definition: section.c:5202
NTSTATUS NTAPI MmMapViewInSystemSpace(IN PVOID SectionObject, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:4498
BOOLEAN NTAPI MmCanFileBeTruncated(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
Definition: section.c:4306
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:4024
NTSTATUS NTAPI MmMakeSegmentDirty(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
Definition: section.c:5056
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:5199
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:4671
static BOOLEAN MiPurgeImageSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:4361
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:4899
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:4511
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:4407
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:3805
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:4994
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:5113
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:5036
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:5197
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:5196
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::@1693 Misc
DWORD PointerToRawData
Definition: pedump.c:290
Definition: typedefs.h:120
ULONG Flags
Definition: mm.h:257
BOOLEAN DeleteInProgress
Definition: mm.h:258
ULONG Type
Definition: mm.h:256
MMVAD VadNode
Definition: mm.h:254
struct _MEMORY_AREA::@1927 SectionData
union _MMADDRESS_NODE::@2796 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::@2798 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
struct _MM_SECTION_SEGMENT::@1926 Image
PLONG64 ReferenceCount
Definition: mm.h:207
FAST_MUTEX Lock
Definition: mm.h:204
PFILE_OBJECT FileObject
Definition: mm.h:202
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::@2807 u
PSEGMENT Segment
Definition: mmtypes.h:812
ULONG InitialPageProtection
Definition: mmtypes.h:819
LARGE_INTEGER SizeOfSection
Definition: mmtypes.h:813
union _SEGMENT::@2790 u2
PVOID BasedAddress
Definition: mmtypes.h:418
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
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:3776
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2274
_In_ PLARGE_INTEGER _Out_ struct _ERESOURCE ** ResourceToRelease
Definition: iotypes.h:1598
#define FO_RANDOM_ACCESS
Definition: iotypes.h:1796
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FO_DELETE_ON_CLOSE
Definition: iotypes.h:1792
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ WrPageIn
Definition: ketypes.h:424
@ Executive
Definition: ketypes.h:415
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
KAPC_STATE
Definition: ketypes.h:1589
_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