ReactOS 0.4.15-dev-6073-g59e7458
vadnode.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <mm/ARM3/miarm.h>
#include "miavl.h"
#include <sdk/lib/rtl/avlsupp.c>
Include dependency graph for vadnode.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 

Functions

PMMVAD NTAPI MiLocateAddress (IN PVOID VirtualAddress)
 
TABLE_SEARCH_RESULT NTAPI MiCheckForConflictingNode (IN ULONG_PTR StartVpn, IN ULONG_PTR EndVpn, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *NodeOrParent)
 
VOID NTAPI MiInsertNode (IN PMM_AVL_TABLE Table, IN PMMADDRESS_NODE NewNode, IN PMMADDRESS_NODE Parent, IN TABLE_SEARCH_RESULT Result)
 
VOID NTAPI MiInsertVad (IN PMMVAD Vad, IN PMM_AVL_TABLE VadRoot)
 
NTSTATUS NTAPI MiInsertVadEx (_Inout_ PMMVAD Vad, _In_ ULONG_PTR *BaseAddress, _In_ SIZE_T ViewSize, _In_ ULONG_PTR HighestAddress, _In_ ULONG_PTR Alignment, _In_ ULONG AllocationType)
 
VOID NTAPI MiInsertBasedSection (IN PSECTION Section)
 
VOID NTAPI MiRemoveNode (IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table)
 
PMMADDRESS_NODE NTAPI MiGetPreviousNode (IN PMMADDRESS_NODE Node)
 
PMMADDRESS_NODE NTAPI MiGetNextNode (IN PMMADDRESS_NODE Node)
 
TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeInTree (IN SIZE_T Length, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *PreviousVad, OUT PULONG_PTR Base)
 
TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeDownTree (IN SIZE_T Length, IN ULONG_PTR BoundaryAddress, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PULONG_PTR Base, OUT PMMADDRESS_NODE *Parent)
 
NTSTATUS NTAPI MiFindEmptyAddressRangeDownBasedTree (IN SIZE_T Length, IN ULONG_PTR BoundaryAddress, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PULONG_PTR Base)
 
NTSTATUS NTAPI MiCheckSecuredVad (IN PMMVAD Vad, IN PVOID Base, IN SIZE_T Size, IN ULONG ProtectionMask)
 

Variables

CHAR MmReadWrite [32]
 

Macro Definition Documentation

◆ MODULE_INVOLVED_IN_ARM3

#define MODULE_INVOLVED_IN_ARM3

Definition at line 16 of file vadnode.c.

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file vadnode.c.

Function Documentation

◆ MiCheckForConflictingNode()

TABLE_SEARCH_RESULT NTAPI MiCheckForConflictingNode ( IN ULONG_PTR  StartVpn,
IN ULONG_PTR  EndVpn,
IN PMM_AVL_TABLE  Table,
OUT PMMADDRESS_NODE NodeOrParent 
)

Definition at line 78 of file vadnode.c.

82{
83 PMMADDRESS_NODE ParentNode, CurrentNode;
84
85 /* If the tree is empty, there is no conflict */
86 if (Table->NumberGenericTableElements == 0) return TableEmptyTree;
87
88 /* Start looping from the root node */
89 CurrentNode = RtlRightChildAvl(&Table->BalancedRoot);
90 ASSERT(CurrentNode != NULL);
91 while (CurrentNode)
92 {
93 ParentNode = CurrentNode;
94
95 /* This address comes after */
96 if (StartVpn > CurrentNode->EndingVpn)
97 {
98 /* Keep searching on the right */
99 CurrentNode = RtlRightChildAvl(CurrentNode);
100 }
101 else if (EndVpn < CurrentNode->StartingVpn)
102 {
103 /* This address ends before the node starts, search on the left */
104 CurrentNode = RtlLeftChildAvl(CurrentNode);
105 }
106 else
107 {
108 /* This address is part of this node, return it */
109 *NodeOrParent = ParentNode;
110 return TableFoundNode;
111 }
112 }
113
114 /* There is no more child, save the current node as parent */
115 *NodeOrParent = ParentNode;
116 if (StartVpn > ParentNode->EndingVpn)
117 {
118 return TableInsertAsRight;
119 }
120 else
121 {
122 return TableInsertAsLeft;
123 }
124}
#define NULL
Definition: types.h:112
ASMGENDATA Table[]
Definition: genincdata.c:61
#define RtlRightChildAvl
Definition: miavl.h:45
#define RtlLeftChildAvl
Definition: miavl.h:46
#define ASSERT(a)
Definition: mode.c:44
ULONG_PTR EndingVpn
Definition: mmtypes.h:651
@ TableEmptyTree
Definition: rtltypes.h:363
@ TableInsertAsRight
Definition: rtltypes.h:366
@ TableFoundNode
Definition: rtltypes.h:364
@ TableInsertAsLeft
Definition: rtltypes.h:365

Referenced by MiInsertVadEx(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MmLocateMemoryAreaByAddress(), MmLocateMemoryAreaByRegion(), and NtAllocateVirtualMemory().

◆ MiCheckSecuredVad()

NTSTATUS NTAPI MiCheckSecuredVad ( IN PMMVAD  Vad,
IN PVOID  Base,
IN SIZE_T  Size,
IN ULONG  ProtectionMask 
)

Definition at line 815 of file vadnode.c.

819{
820 ULONG_PTR StartAddress, EndAddress;
821
822 /* Compute start and end address */
823 StartAddress = (ULONG_PTR)Base;
824 EndAddress = StartAddress + Size - 1;
825
826 /* Are we deleting/unmapping, or changing? */
827 if (ProtectionMask < MM_DELETE_CHECK)
828 {
829 /* Changing... are we allowed to do so? */
830 if ((Vad->u.VadFlags.NoChange == 1) &&
831 (Vad->u2.VadFlags2.SecNoChange == 1) &&
832 (Vad->u.VadFlags.Protection != ProtectionMask))
833 {
834 /* Nope, bail out */
835 DPRINT1("Trying to mess with a no-change VAD!\n");
837 }
838 }
839 else
840 {
841 /* This is allowed */
842 ProtectionMask = 0;
843 }
844
845 /* ARM3 doesn't support this yet */
846 ASSERT(Vad->u2.VadFlags2.MultipleSecured == 0);
847
848 /* Is this a one-secured VAD, like a TEB or PEB? */
849 if (Vad->u2.VadFlags2.OneSecured)
850 {
851 /* Is this allocation being described by the VAD? */
852 if ((StartAddress <= ((PMMVAD_LONG)Vad)->u3.Secured.EndVpn) &&
853 (EndAddress >= ((PMMVAD_LONG)Vad)->u3.Secured.StartVpn))
854 {
855 /* Guard page? */
856 if (ProtectionMask & MM_DECOMMIT)
857 {
858 DPRINT1("Not allowed to change protection on guard page!\n");
860 }
861
862 /* ARM3 doesn't have read-only VADs yet */
863 ASSERT(Vad->u2.VadFlags2.ReadOnly == 0);
864
865 /* Check if read-write protections are allowed */
866 if (MmReadWrite[ProtectionMask] < MM_READ_WRITE_ALLOWED)
867 {
868 DPRINT1("Invalid protection mask for RW access!\n");
870 }
871 }
872 }
873
874 /* All good, allow the change */
875 return STATUS_SUCCESS;
876}
#define DPRINT1
Definition: precomp.h:8
#define ULONG_PTR
Definition: config.h:101
#define MM_READ_WRITE_ALLOWED
Definition: miarm.h:253
#define MM_DELETE_CHECK
Definition: miarm.h:256
#define MM_DECOMMIT
Definition: miarm.h:64
static BYTE u3[]
Definition: msg.c:580
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2427
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:305
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG ReadOnly
Definition: mmtypes.h:707
union _MMVAD_LONG::@2592 u2
MMVAD_FLAGS2 VadFlags2
Definition: mmtypes.h:768
uint32_t ULONG_PTR
Definition: typedefs.h:65
CHAR MmReadWrite[32]
Definition: vadnode.c:25
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by MiUnmapViewOfSection(), and NtAllocateVirtualMemory().

◆ MiFindEmptyAddressRangeDownBasedTree()

NTSTATUS NTAPI MiFindEmptyAddressRangeDownBasedTree ( IN SIZE_T  Length,
IN ULONG_PTR  BoundaryAddress,
IN ULONG_PTR  Alignment,
IN PMM_AVL_TABLE  Table,
OUT PULONG_PTR  Base 
)

Definition at line 713 of file vadnode.c.

718{
719 PMMADDRESS_NODE Node, LowestNode;
720 ULONG_PTR LowVpn, BestVpn;
721
722 /* Sanity checks */
724 ASSERT(BoundaryAddress);
725 ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
726
727 /* Compute page length, make sure the boundary address is valid */
729 if ((BoundaryAddress + 1) < Length) return STATUS_NO_MEMORY;
730
731 /* Check if the table is empty */
732 BestVpn = ROUND_DOWN(BoundaryAddress + 1 - Length, Alignment);
733 if (Table->NumberGenericTableElements == 0)
734 {
735 /* Tree is empty, the candidate address is already the best one */
736 *Base = BestVpn;
737 return STATUS_SUCCESS;
738 }
739
740 /* Go to the right-most node which should be the biggest address */
741 Node = Table->BalancedRoot.RightChild;
743
744 /* Check if we can fit in here */
745 LowVpn = ROUND_UP(Node->EndingVpn + 1, Alignment);
746 if ((LowVpn < BoundaryAddress) && (Length <= (BoundaryAddress - LowVpn)))
747 {
748#if (NTDDI_VERSION >= NTDDI_VISTA)
749 /* Return the address. */
750 *Base = BestVpn;
751#else
752 /* Note: this is a compatibility hack that mimics a bug in the 2k3
753 kernel. It will can waste up to Alignment bytes of memory above
754 the allocation. This bug was fixed in Windows Vista */
755 *Base = ROUND_DOWN(BoundaryAddress - Length, Alignment);
756#endif
757 return STATUS_SUCCESS;
758 }
759
760 /* Now loop the Vad nodes */
761 do
762 {
763 /* Break out if we've reached the last node */
764 LowestNode = MiGetPreviousNode(Node);
765 if (!LowestNode) break;
766
767 /* Check if this node could contain the requested address */
768 LowVpn = ROUND_UP(LowestNode->EndingVpn + 1, Alignment);
769 if ((LowestNode->EndingVpn < BestVpn) &&
770 (LowVpn < Node->StartingVpn) &&
771 (Length <= (Node->StartingVpn - LowVpn)))
772 {
773 /* Check if we need to take BoundaryAddress into account */
774 if (BoundaryAddress < Node->StartingVpn)
775 {
776 /* Return the optimal VPN address */
777 *Base = BestVpn;
778 return STATUS_SUCCESS;
779 }
780 else
781 {
782 /* The upper margin is given by the Node's starting address */
783 *Base = ROUND_DOWN(Node->StartingVpn - Length, Alignment);
784 return STATUS_SUCCESS;
785 }
786 }
787
788 /* Move to the next node */
789 Node = LowestNode;
790 } while (TRUE);
791
792 /* Check if there's enough space before the lowest Vad */
793 if ((Node->StartingVpn > (ULONG_PTR)MI_LOWEST_VAD_ADDRESS) &&
794 ((Node->StartingVpn - (ULONG_PTR)MI_LOWEST_VAD_ADDRESS) >= Length))
795 {
796 /* Check if it fits in perfectly */
797 if (BoundaryAddress < Node->StartingVpn)
798 {
799 /* Return the optimal VPN address */
800 *Base = BestVpn;
801 return STATUS_SUCCESS;
802 }
803
804 /* Return an aligned base address within this node */
805 *Base = ROUND_DOWN(Node->StartingVpn - Length, Alignment);
806 return STATUS_SUCCESS;
807 }
808
809 /* No address space left at all */
810 return STATUS_NO_MEMORY;
811}
#define TRUE
Definition: types.h:120
union node Node
Definition: types.h:1255
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:33
#define MI_LOWEST_VAD_ADDRESS
Definition: miarm.h:15
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:46
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
Definition: dlist.c:348
PMMADDRESS_NODE NTAPI MiGetPreviousNode(IN PMMADDRESS_NODE Node)
Definition: vadnode.c:431
#define ROUND_TO_PAGES(Size)

Referenced by MmCreateArm3Section().

◆ MiFindEmptyAddressRangeDownTree()

TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeDownTree ( IN SIZE_T  Length,
IN ULONG_PTR  BoundaryAddress,
IN ULONG_PTR  Alignment,
IN PMM_AVL_TABLE  Table,
OUT PULONG_PTR  Base,
OUT PMMADDRESS_NODE Parent 
)

Definition at line 597 of file vadnode.c.

603{
604 PMMADDRESS_NODE Node, OldNode = NULL, Child;
605 ULONG_PTR LowVpn, HighVpn, AlignmentVpn;
606 PFN_NUMBER PageCount;
607
608 /* Sanity checks */
609 ASSERT(BoundaryAddress);
610 ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS));
611 ASSERT((Alignment & (PAGE_SIZE - 1)) == 0);
612
613 /* Calculate page numbers for the length and alignment */
615 PageCount = Length >> PAGE_SHIFT;
616 AlignmentVpn = Alignment / PAGE_SIZE;
617
618 /* Check for kernel mode table (memory areas) */
619 if (Table->Unused == 1)
620 {
621 LowVpn = ALIGN_UP_BY((ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT, AlignmentVpn);
622 }
623 else
624 {
626 }
627
628 /* Check if there is enough space below the boundary */
629 if ((LowVpn + Length) > (BoundaryAddress + 1))
630 {
631 return TableFoundNode;
632 }
633
634 /* Check if the table is empty */
635 if (Table->NumberGenericTableElements == 0)
636 {
637 /* Tree is empty, the candidate address is already the best one */
638 *Base = ALIGN_DOWN_BY(BoundaryAddress + 1 - Length, Alignment);
639 return TableEmptyTree;
640 }
641
642 /* Calculate the initial upper margin */
643 HighVpn = (BoundaryAddress + 1) >> PAGE_SHIFT;
644
645 /* Starting from the root, follow the right children until we found a node
646 that ends above the boundary */
647 Node = RtlRightChildAvl(&Table->BalancedRoot);
648 while ((Node->EndingVpn < HighVpn) &&
650
651 /* Now loop the Vad nodes */
652 while (Node)
653 {
654 /* Calculate the lower margin */
655 LowVpn = ALIGN_UP_BY(Node->EndingVpn + 1, AlignmentVpn);
656
657 /* Check if the current bounds are suitable */
658 if ((HighVpn > LowVpn) && ((HighVpn - LowVpn) >= PageCount))
659 {
660 /* There is enough space to add our node */
661 LowVpn = ALIGN_DOWN_BY(HighVpn - PageCount, AlignmentVpn);
662 *Base = LowVpn << PAGE_SHIFT;
663
664 /* Can we use the current node as parent? */
666 {
667 /* Node has no right child, so use it as parent */
668 *Parent = Node;
669 return TableInsertAsRight;
670 }
671 else
672 {
673 /* Node has a right child. This means we must have already
674 moved one node left from the right-most node we started
675 with, thus we already have an OldNode! */
676 ASSERT(OldNode != NULL);
677
678 /* The node we had before is the most left grandchild of
679 that right child, use it as parent. */
680 ASSERT(RtlLeftChildAvl(OldNode) == NULL);
681 *Parent = OldNode;
682 return TableInsertAsLeft;
683 }
684 }
685
686 /* Update the upper margin if necessary */
687 if (Node->StartingVpn < HighVpn) HighVpn = Node->StartingVpn;
688
689 /* Remember the current node and go to the previous node */
690 OldNode = Node;
692 }
693
694 /* Check if there's enough space before the lowest Vad */
696 if ((HighVpn > LowVpn) && ((HighVpn - LowVpn) >= PageCount))
697 {
698 /* There is enough space to add our address */
699 LowVpn = ALIGN_DOWN_BY(HighVpn - PageCount, Alignment >> PAGE_SHIFT);
700 *Base = LowVpn << PAGE_SHIFT;
701 *Parent = OldNode;
702 return TableInsertAsLeft;
703 }
704
705 /* No address space left at all */
706 *Base = 0;
707 *Parent = NULL;
708 return TableFoundNode;
709}
#define ALIGN_DOWN_BY(size, align)
#define ALIGN_UP_BY(size, align)
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:732
#define MM_LOWEST_USER_ADDRESS
Definition: armddk.h:20
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define MmSystemRangeStart
Definition: mm.h:32
ULONG PFN_NUMBER
Definition: ke.h:9
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536

Referenced by MiInsertVadEx(), and MmFindGap().

◆ MiFindEmptyAddressRangeInTree()

TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeInTree ( IN SIZE_T  Length,
IN ULONG_PTR  Alignment,
IN PMM_AVL_TABLE  Table,
OUT PMMADDRESS_NODE PreviousVad,
OUT PULONG_PTR  Base 
)

Definition at line 502 of file vadnode.c.

507{
508 PMMADDRESS_NODE Node, PreviousNode;
509 ULONG_PTR PageCount, AlignmentVpn, LowVpn, HighestVpn;
510 ASSERT(Length != 0);
511
512 /* Calculate page numbers for the length, alignment, and starting address */
513 PageCount = BYTES_TO_PAGES(Length);
514 AlignmentVpn = Alignment >> PAGE_SHIFT;
515 LowVpn = ALIGN_UP_BY((ULONG_PTR)MM_LOWEST_USER_ADDRESS >> PAGE_SHIFT, AlignmentVpn);
516
517 /* Check for kernel mode table (memory areas) */
518 if (Table->Unused == 1)
519 {
520 LowVpn = ALIGN_UP_BY((ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT, AlignmentVpn);
521 }
522
523 /* Check if the table is empty */
524 if (Table->NumberGenericTableElements == 0)
525 {
526 /* Tree is empty, the candidate address is already the best one */
527 *Base = LowVpn << PAGE_SHIFT;
528 return TableEmptyTree;
529 }
530
531 /* Otherwise, follow the leftmost child of the right root node's child */
532 Node = RtlRightChildAvl(&Table->BalancedRoot);
534
535 /* Start a search to find a gap */
536 PreviousNode = NULL;
537 while (Node != NULL)
538 {
539 /* Check if the gap below the current node is suitable */
540 if (Node->StartingVpn >= LowVpn + PageCount)
541 {
542 /* There is enough space to add our node */
543 *Base = LowVpn << PAGE_SHIFT;
544
545 /* Can we use the current node as parent? */
546 if (RtlLeftChildAvl(Node) == NULL)
547 {
548 /* Node has no left child, so use it as parent */
549 *PreviousVad = Node;
550 return TableInsertAsLeft;
551 }
552 else
553 {
554 /* Node has a left child, this means that the previous node is
555 the right-most child of it's left child and can be used as
556 the parent. In case we use the space before the left-most
557 node, it's left child must be NULL. */
558 ASSERT(PreviousNode != NULL);
559 ASSERT(RtlRightChildAvl(PreviousNode) == NULL);
560 *PreviousVad = PreviousNode;
561 return TableInsertAsRight;
562 }
563 }
564
565 /* The next candidate is above the current node */
566 if (Node->EndingVpn >= LowVpn)
567 LowVpn = ALIGN_UP_BY(Node->EndingVpn + 1, AlignmentVpn);
568
569 /* Remember the current node and go to the next node */
570 PreviousNode = Node;
572 }
573
574 /* We're up to the highest VAD, will this allocation fit above it? */
575 HighestVpn = ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1) / PAGE_SIZE;
576
577 /* Check for kernel mode table (memory areas) */
578 if (Table->Unused == 1)
579 {
580 HighestVpn = ALIGN_UP_BY((ULONG_PTR)(LONG_PTR)-1 >> PAGE_SHIFT, AlignmentVpn);
581 }
582
583 if (HighestVpn >= LowVpn + PageCount)
584 {
585 /* Yes! Use this VAD to store the allocation */
586 *PreviousVad = PreviousNode;
587 *Base = LowVpn << PAGE_SHIFT;
588 return TableInsertAsRight;
589 }
590
591 /* Nyet, there's no free address space for this allocation, so we'll fail */
592 return TableFoundNode;
593}
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
PMMADDRESS_NODE NTAPI MiGetNextNode(IN PMMADDRESS_NODE Node)
Definition: vadnode.c:467
#define BYTES_TO_PAGES(Size)

Referenced by MiInsertVadEx(), MiMapLockedPagesInUserSpace(), and MmFindGap().

◆ MiGetNextNode()

PMMADDRESS_NODE NTAPI MiGetNextNode ( IN PMMADDRESS_NODE  Node)

Definition at line 467 of file vadnode.c.

468{
470
471 /* Get the right child */
473 {
474 /* Get left-most child */
477 return Node;
478 }
479
481 ASSERT(Parent != NULL);
482 while (Parent != Node)
483 {
484 /* The parent should be a left child, return the real predecessor */
486 {
487 /* Return it */
488 return Parent;
489 }
490
491 /* Keep lopping until we find our parent */
492 Node = Parent;
494 }
495
496 /* Nothing found */
497 return NULL;
498}
#define RtlParentAvl
Definition: miavl.h:44
#define RtlIsLeftChildAvl
Definition: miavl.h:47

Referenced by MiFindEmptyAddressRangeInTree(), and MiQueryMemoryBasicInformation().

◆ MiGetPreviousNode()

PMMADDRESS_NODE NTAPI MiGetPreviousNode ( IN PMMADDRESS_NODE  Node)

Definition at line 431 of file vadnode.c.

432{
434
435 /* Get the left child */
437 {
438 /* Get right-most child */
441 return Node;
442 }
443
445 ASSERT(Parent != NULL);
446 while (Parent != Node)
447 {
448 /* The parent should be a right child, return the real predecessor */
450 {
451 /* Return it unless it's the root */
453 return Parent;
454 }
455
456 /* Keep lopping until we find our parent */
457 Node = Parent;
459 }
460
461 /* Nothing found */
462 return NULL;
463}
#define RtlIsRightChildAvl
Definition: miavl.h:48

Referenced by MiFindEmptyAddressRangeDownBasedTree(), and MiFindEmptyAddressRangeDownTree().

◆ MiInsertBasedSection()

VOID NTAPI MiInsertBasedSection ( IN PSECTION  Section)

Definition at line 345 of file vadnode.c.

346{
349 ASSERT(Section->Address.EndingVpn >= Section->Address.StartingVpn);
350
351 /* Find the parent VAD and where this child should be inserted */
352 Result = RtlpFindAvlTableNodeOrParent(&MmSectionBasedRoot, (PVOID)Section->Address.StartingVpn, &Parent);
354 ASSERT((Parent != NULL) || (Result == TableEmptyTree));
355 MiInsertNode(&MmSectionBasedRoot, &Section->Address, Parent, Result);
356}
#define RtlpFindAvlTableNodeOrParent
Definition: miavl.h:32
VOID NTAPI MiInsertNode(IN PMM_AVL_TABLE Table, IN PMMADDRESS_NODE NewNode, IN PMMADDRESS_NODE Parent, IN TABLE_SEARCH_RESULT Result)
Definition: vadnode.c:128
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
enum _TABLE_SEARCH_RESULT TABLE_SEARCH_RESULT

Referenced by MmCreateArm3Section().

◆ MiInsertNode()

VOID NTAPI MiInsertNode ( IN PMM_AVL_TABLE  Table,
IN PMMADDRESS_NODE  NewNode,
IN PMMADDRESS_NODE  Parent,
IN TABLE_SEARCH_RESULT  Result 
)

Definition at line 128 of file vadnode.c.

132{
133 PMMVAD_LONG Vad;
134
135 /* Insert it into the tree */
137
138 /* Now insert an ARM3 MEMORY_AREA for this node, unless the insert was already from the MEMORY_AREA code */
139 Vad = (PMMVAD_LONG)NewNode;
140 if (Vad->u.VadFlags.Spare == 0)
141 {
144 SIZE_T Size;
146 PVOID AllocatedBase = (PVOID)(Vad->StartingVpn << PAGE_SHIFT);
147
148 Size = ((Vad->EndingVpn + 1) - Vad->StartingVpn) << PAGE_SHIFT;
149
150 if (AllocatedBase == NULL)
151 {
152 AllocatedBase = (PVOID)(ULONG_PTR)1;
153 Size -= 1;
154 }
155
158 &AllocatedBase,
159 Size,
161 &MemoryArea,
162 0,
163 PAGE_SIZE);
165
166 /* Check if this is VM VAD */
167 if (Vad->ControlArea == NULL)
168 {
169 /* We store the reactos MEMORY_AREA here */
171 }
172 else
173 {
174 /* This is a section VAD. Store the MAREA here for now */
175 ASSERT(Vad->u4.Banked == (PVOID)(ULONG_PTR)0xDEADBABEDEADBABEULL);
176 Vad->u4.Banked = (PVOID)MemoryArea;
177 }
178 }
179}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
#define RtlpInsertAvlTreeNode
Definition: miavl.h:35
struct _MMPTE * PMMPTE
struct _MMVAD_LONG * PMMVAD_LONG
_In_ PMEMORY_AREA MemoryArea
Definition: newmm.h:207
#define PAGE_READWRITE
Definition: nt_native.h:1304
NTSTATUS NTAPI MmCreateMemoryArea(PMMSUPPORT AddressSpace, ULONG Type, PVOID *BaseAddress, SIZE_T Length, ULONG Protection, PMEMORY_AREA *Result, ULONG AllocationFlags, ULONG AllocationGranularity)
Definition: marea.c:404
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:97
ULONG_PTR Spare
Definition: mmtypes.h:694
PMMPTE FirstPrototypePte
Definition: mmtypes.h:763
PVOID Banked
Definition: mmtypes.h:777
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:760
ULONG_PTR EndingVpn
Definition: mmtypes.h:756
PCONTROL_AREA ControlArea
Definition: mmtypes.h:762
union _MMVAD_LONG::@2591 u
union _MMVAD_LONG::@2594 u4
ULONG_PTR StartingVpn
Definition: mmtypes.h:755
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by MiInsertBasedSection(), MiInsertVad(), and MiInsertVadEx().

◆ MiInsertVad()

VOID NTAPI MiInsertVad ( IN PMMVAD  Vad,
IN PMM_AVL_TABLE  VadRoot 
)

Definition at line 183 of file vadnode.c.

185{
188
189 /* Validate the VAD and set it as the current hint */
190 ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
191 VadRoot->NodeHint = Vad;
192
193 /* Find the parent VAD and where this child should be inserted */
194 Result = RtlpFindAvlTableNodeOrParent(VadRoot, (PVOID)Vad->StartingVpn, &Parent);
196 ASSERT((Parent != NULL) || (Result == TableEmptyTree));
197
198 /* Do the actual insert operation */
199 MiInsertNode(VadRoot, (PVOID)Vad, Parent, Result);
200}

Referenced by MmInsertMemoryArea().

◆ MiInsertVadEx()

NTSTATUS NTAPI MiInsertVadEx ( _Inout_ PMMVAD  Vad,
_In_ ULONG_PTR BaseAddress,
_In_ SIZE_T  ViewSize,
_In_ ULONG_PTR  HighestAddress,
_In_ ULONG_PTR  Alignment,
_In_ ULONG  AllocationType 
)

Definition at line 204 of file vadnode.c.

211{
212 ULONG_PTR StartingAddress, EndingAddress;
213 PEPROCESS CurrentProcess;
214 PETHREAD CurrentThread;
217
218 /* Align the view size to pages */
220
221 /* Get the current process */
222 CurrentProcess = PsGetCurrentProcess();
223
224 /* Acquire the address creation lock and make sure the process is alive */
226 if (CurrentProcess->VmDeleted)
227 {
229 DPRINT1("The process is dying\n");
231 }
232
233 /* Did the caller specify an address? */
234 if (*BaseAddress == 0)
235 {
236 /* Make sure HighestAddress is not too large */
237 HighestAddress = min(HighestAddress, (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS);
238
239 /* Which way should we search? */
240 if ((AllocationType & MEM_TOP_DOWN) || CurrentProcess->VmTopDown)
241 {
242 /* Find an address top-down */
244 HighestAddress,
245 Alignment,
246 &CurrentProcess->VadRoot,
247 &StartingAddress,
248 &Parent);
249 }
250 else
251 {
252 /* Find an address bottom-up */
254 Alignment,
255 &CurrentProcess->VadRoot,
256 &Parent,
257 &StartingAddress);
258 }
259
260 /* Get the ending address, which is the last piece we need for the VAD */
261 EndingAddress = StartingAddress + ViewSize - 1;
262
263 /* Check if we found a suitable location */
264 if ((Result == TableFoundNode) || (EndingAddress > HighestAddress))
265 {
266 DPRINT1("Not enough free space to insert this VAD node!\n");
268 return STATUS_NO_MEMORY;
269 }
270
271 ASSERT(StartingAddress != 0);
272 ASSERT(StartingAddress < (ULONG_PTR)HighestAddress);
273 ASSERT(EndingAddress > StartingAddress);
274 }
275 else
276 {
277 /* Calculate the starting and ending address */
278 StartingAddress = ALIGN_DOWN_BY(*BaseAddress, Alignment);
279 EndingAddress = StartingAddress + ViewSize - 1;
280
281 /* Make sure it doesn't conflict with an existing allocation */
282 Result = MiCheckForConflictingNode(StartingAddress >> PAGE_SHIFT,
283 EndingAddress >> PAGE_SHIFT,
284 &CurrentProcess->VadRoot,
285 &Parent);
286 if (Result == TableFoundNode)
287 {
288 DPRINT("Given address conflicts with existing node\n");
291 }
292 }
293
294 /* Now set the VAD address */
295 Vad->StartingVpn = StartingAddress >> PAGE_SHIFT;
296 Vad->EndingVpn = EndingAddress >> PAGE_SHIFT;
297
298 /* Check if we already need to charge for the pages */
299 if ((Vad->u.VadFlags.PrivateMemory && Vad->u.VadFlags.MemCommit) ||
300 (!Vad->u.VadFlags.PrivateMemory &&
301 (Vad->u.VadFlags.Protection & PAGE_WRITECOPY)))
302 {
303 /* Set the commit charge */
304 Vad->u.VadFlags.CommitCharge = ViewSize / PAGE_SIZE;
305 }
306
307 /* Check if the VAD is to be secured */
308 if (Vad->u2.VadFlags2.OneSecured)
309 {
310 /* This *must* be a long VAD! */
311 ASSERT(Vad->u2.VadFlags2.LongVad);
312
313 /* Yeah this is retarded, I didn't invent it! */
314 ((PMMVAD_LONG)Vad)->u3.Secured.StartVpn = StartingAddress;
315 ((PMMVAD_LONG)Vad)->u3.Secured.EndVpn = EndingAddress;
316 }
317
318 /* Lock the working set */
319 CurrentThread = PsGetCurrentThread();
320 MiLockProcessWorkingSetUnsafe(CurrentProcess, CurrentThread);
321
322 /* Insert the VAD */
323 CurrentProcess->VadRoot.NodeHint = Vad;
324 MiInsertNode(&CurrentProcess->VadRoot, (PVOID)Vad, Parent, Result);
325
326 /* Release the working set */
327 MiUnlockProcessWorkingSetUnsafe(CurrentProcess, CurrentThread);
328
329 /* Update the process' virtual size, and peak virtual size */
330 CurrentProcess->VirtualSize += ViewSize;
331 if (CurrentProcess->VirtualSize > CurrentProcess->PeakVirtualSize)
332 {
333 CurrentProcess->PeakVirtualSize = CurrentProcess->VirtualSize;
334 }
335
336 /* Unlock the address space */
338
339 *BaseAddress = StartingAddress;
340 return STATUS_SUCCESS;
341}
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1239
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1169
#define min(a, b)
Definition: monoChain.cc:55
_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 _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:408
#define MEM_TOP_DOWN
Definition: nt_native.h:1321
#define PAGE_WRITECOPY
Definition: nt_native.h:1305
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:502
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:261
#define DPRINT
Definition: sndvol32.h:71
MM_AVL_TABLE VadRoot
Definition: pstypes.h:1453
EX_PUSH_LOCK AddressCreationLock
Definition: pstypes.h:1290
SIZE_T PeakVirtualSize
Definition: pstypes.h:1272
SIZE_T VirtualSize
Definition: pstypes.h:1273
ULONG VmDeleted
Definition: pstypes.h:1398
ULONG VmTopDown
Definition: pstypes.h:1417
PVOID NodeHint
Definition: mmtypes.h:667
TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeDownTree(IN SIZE_T Length, IN ULONG_PTR BoundaryAddress, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PULONG_PTR Base, OUT PMMADDRESS_NODE *Parent)
Definition: vadnode.c:597
TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeInTree(IN SIZE_T Length, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *PreviousVad, OUT PULONG_PTR Base)
Definition: vadnode.c:502
TABLE_SEARCH_RESULT NTAPI MiCheckForConflictingNode(IN ULONG_PTR StartVpn, IN ULONG_PTR EndVpn, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *NodeOrParent)
Definition: vadnode.c:78
#define PsGetCurrentProcess
Definition: psfuncs.h:17

Referenced by MiCreatePebOrTeb(), MiMapViewOfDataSection(), and NtAllocateVirtualMemory().

◆ MiLocateAddress()

PMMVAD NTAPI MiLocateAddress ( IN PVOID  VirtualAddress)

Definition at line 48 of file vadnode.c.

49{
50 PMMVAD FoundVad;
51 ULONG_PTR Vpn;
53 TABLE_SEARCH_RESULT SearchResult;
54
55 /* Start with the the hint */
56 FoundVad = (PMMVAD)Table->NodeHint;
57 if (!FoundVad) return NULL;
58
59 /* Check if this VPN is in the hint, if so, use it */
61 if ((Vpn >= FoundVad->StartingVpn) && (Vpn <= FoundVad->EndingVpn)) return FoundVad;
62
63 /* VAD hint didn't work, go look for it */
65 (PVOID)Vpn,
66 (PMMADDRESS_NODE*)&FoundVad);
67 if (SearchResult != TableFoundNode) return NULL;
68
69 /* We found it, update the hint */
70 ASSERT(FoundVad != NULL);
71 ASSERT((Vpn >= FoundVad->StartingVpn) && (Vpn <= FoundVad->EndingVpn));
72 Table->NodeHint = FoundVad;
73 return FoundVad;
74}
if(dx< 0)
Definition: linetemp.h:194
struct _MMVAD * PMMVAD
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress

Referenced by MiCheckVadsForLockOperation(), MiCheckVirtualAddress(), MiGetFileObjectForSectionAddress(), MiUnmapLockedPagesInUserSpace(), MiUnmapViewOfSection(), MmDeleteTeb(), MmGetFileNameForAddress(), NtAreMappedFilesTheSame(), and NtFreeVirtualMemory().

◆ MiRemoveNode()

VOID NTAPI MiRemoveNode ( IN PMMADDRESS_NODE  Node,
IN PMM_AVL_TABLE  Table 
)

Definition at line 360 of file vadnode.c.

362{
363 PMMVAD_LONG Vad;
364
365 /* Call the AVL code */
367
368 /* Decrease element count */
369 Table->NumberGenericTableElements--;
370
371 /* Check if this node was the hint */
372 if (Table->NodeHint == Node)
373 {
374 /* Get a new hint, unless we're empty now, in which case nothing */
375 if (!Table->NumberGenericTableElements) Table->NodeHint = NULL;
376 else Table->NodeHint = Table->BalancedRoot.RightChild;
377 }
378
379 /* Free the node from ReactOS view as well */
380 Vad = (PMMVAD_LONG)Node;
381 if ((Table != &MmSectionBasedRoot) && (Vad->u.VadFlags.Spare == 0))
382 {
385
386 /* Check if this is VM VAD */
387 if (Vad->ControlArea == NULL)
388 {
389 /* We store the ReactOS MEMORY_AREA here */
391 }
392 else
393 {
394 /* This is a section VAD. We store the ReactOS MEMORY_AREA here */
396 }
397
398 /* Make sure one actually still exists */
399 if (MemoryArea)
400 {
401 /* Make sure we have not already freed it */
402 ASSERT(MemoryArea != (PVOID)(ULONG_PTR)0xDEADBAB1DEADBAB1ULL);
403
404 /* Get the process */
406
407 /* We only create fake memory-areas for ARM3 VADs */
410
411 /* Free it */
413
414 /* Check if this is VM VAD */
415 if (Vad->ControlArea == NULL)
416 {
417 /* Delete the pointer to it */
418 Vad->FirstPrototypePte = (PVOID)(ULONG_PTR)0xDEADBAB1DEADBAB1ULL;
419 }
420 else
421 {
422 /* Delete the pointer to it */
423 Vad->u4.Banked = (PVOID)(ULONG_PTR)0xDEADBAB1DEADBAB1ULL;
424 }
425 }
426 }
427}
#define RtlpDeleteAvlTreeNode
Definition: miavl.h:36
NTSTATUS NTAPI MmFreeMemoryArea(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_FREE_PAGE_FUNC FreePage, PVOID FreePageContext)
Definition: marea.c:283
struct _MEMORY_AREA * PMEMORY_AREA
PVOID Vad
Definition: mm.h:255
ULONG Type
Definition: mm.h:251

Referenced by MiDeleteARM3Section(), MiUnmapLockedPagesInUserSpace(), MiUnmapViewOfSection(), MmCleanProcessAddressSpace(), MmDeleteTeb(), MmFreeMemoryArea(), and NtFreeVirtualMemory().

Variable Documentation

◆ MmReadWrite