[CMAKE]
[reactos.git] / ntoskrnl / mm / marea.c
index 0dee681..cacf2ae 100644 (file)
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, MmInitMemoryAreas)
-#endif
-
-/* #define VALIDATE_MEMORY_AREAS */
+MEMORY_AREA MiStaticMemoryAreas[MI_STATIC_MEMORY_AREAS];
+ULONG MiStaticMemoryAreaCount;
 
 /* FUNCTIONS *****************************************************************/
 
@@ -159,68 +156,16 @@ static PMEMORY_AREA MmIteratePrevNode(PMEMORY_AREA Node)
    return Node;
 }
 
-#ifdef VALIDATE_MEMORY_AREAS
-static VOID MmVerifyMemoryAreas(PMM_AVL_TABLE AddressSpace)
-{
-   PMEMORY_AREA Node;
-
-   ASSERT(AddressSpace != NULL);
-
-   /* Special case for empty tree. */
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
-      return;
-
-   /* Traverse the tree from left to right. */
-   for (Node = MmIterateFirstNode(AddressSpace->BalancedRoot.u1.Parent);
-        Node != NULL;
-        Node = MmIterateNextNode(Node))
-   {
-      /* FiN: The starting address can be NULL if someone explicitely asks
-       * for NULL address. */
-      ASSERT(Node->StartingAddress == NULL);
-      ASSERT(Node->EndingAddress >= Node->StartingAddress);
-   }
-}
-#else
-#define MmVerifyMemoryAreas(x)
-#endif
-
-VOID STDCALL
-MmDumpMemoryAreas(PMM_AVL_TABLE AddressSpace)
-{
-   PMEMORY_AREA Node;
-
-   DbgPrint("MmDumpMemoryAreas()\n");
-
-   /* Special case for empty tree. */
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
-      return;
-
-   /* Traverse the tree from left to right. */
-   for (Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent);
-        Node != NULL;
-        Node = MmIterateNextNode(Node))
-   {
-      DbgPrint("Start %p End %p Protect %x Flags %x\n",
-               Node->StartingAddress, Node->EndingAddress,
-               Node->Protect, Node->Flags);
-   }
-
-   DbgPrint("Finished MmDumpMemoryAreas()\n");
-}
-
-PMEMORY_AREA STDCALL
+PMEMORY_AREA NTAPI
 MmLocateMemoryAreaByAddress(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PVOID Address)
 {
-   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent;
+   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
 
    DPRINT("MmLocateMemoryAreaByAddress(AddressSpace %p, Address %p)\n",
            AddressSpace, Address);
 
-   MmVerifyMemoryAreas(AddressSpace);
-
    while (Node != NULL)
    {
       if (Address < Node->StartingAddress)
@@ -239,23 +184,21 @@ MmLocateMemoryAreaByAddress(
    return NULL;
 }
 
-PMEMORY_AREA STDCALL
+PMEMORY_AREA NTAPI
 MmLocateMemoryAreaByRegion(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PVOID Address,
    ULONG_PTR Length)
 {
    PMEMORY_AREA Node;
    PVOID Extent = (PVOID)((ULONG_PTR)Address + Length);
 
-   MmVerifyMemoryAreas(AddressSpace);
-
    /* Special case for empty tree. */
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
       return NULL;
 
    /* Traverse the tree from left to right. */
-   for (Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent);
+   for (Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
         Node != NULL;
         Node = MmIterateNextNode(Node))
    {
@@ -302,11 +245,11 @@ MmLocateMemoryAreaByRegion(
 
 static VOID
 MmCompressHelper(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG Count)
 {
    PMEMORY_AREA Root = NULL;
-   PMEMORY_AREA Red = (PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent;
+   PMEMORY_AREA Red = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    PMEMORY_AREA Black = Red->LeftChild;
 
    while (Count--)
@@ -314,7 +257,7 @@ MmCompressHelper(
       if (Root)
          Root->LeftChild = Black;
       else
-         AddressSpace->BalancedRoot.u1.Parent = (PVOID)Black;
+         AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)Black;
       Black->Parent = Root;
       Red->LeftChild = Black->RightChild;
       if (Black->RightChild)
@@ -341,7 +284,7 @@ MmCompressHelper(
 
 static VOID
 MmRebalanceTree(
-   PMM_AVL_TABLE AddressSpace)
+   PMMSUPPORT AddressSpace)
 {
    PMEMORY_AREA PreviousNode;
    PMEMORY_AREA CurrentNode;
@@ -354,7 +297,7 @@ MmRebalanceTree(
    /* Transform the tree into Vine. */
 
    PreviousNode = NULL;
-   CurrentNode = (PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent;
+   CurrentNode = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    while (CurrentNode != NULL)
    {
       if (CurrentNode->RightChild == NULL)
@@ -379,7 +322,7 @@ MmRebalanceTree(
          if (PreviousNode != NULL)
             PreviousNode->LeftChild = TempNode;
          else
-            AddressSpace->BalancedRoot.u1.Parent = (PVOID)TempNode;
+            AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)TempNode;
          TempNode->Parent = PreviousNode;
       }
    }
@@ -408,25 +351,68 @@ MmRebalanceTree(
    }
 }
 
+VOID
+NTAPI
+MiInsertVad(IN PMMVAD Vad,
+IN PEPROCESS Process);
+
+ULONG
+NTAPI
+MiMakeProtectionMask(
+    IN ULONG Protect
+);
+
 static VOID
 MmInsertMemoryArea(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PMEMORY_AREA marea)
 {
    PMEMORY_AREA Node;
    PMEMORY_AREA PreviousNode;
    ULONG Depth = 0;
 
-   MmVerifyMemoryAreas(AddressSpace);
+   /* Build a lame VAD if this is a user-space allocation */
+   if ((marea->EndingAddress < MmSystemRangeStart) && (marea->Type != MEMORY_AREA_OWNED_BY_ARM3))
+   {
+       PMMVAD Vad;
+
+       ASSERT(marea->Type == MEMORY_AREA_VIRTUAL_MEMORY || marea->Type == MEMORY_AREA_SECTION_VIEW);
+       Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD), 'Fake');
+       ASSERT(Vad);
+       RtlZeroMemory(Vad, sizeof(MMVAD));
+       Vad->StartingVpn = PAGE_ROUND_DOWN(marea->StartingAddress) >> PAGE_SHIFT;
+       /*
+        * For some strange reason, it is perfectly valid to create a MAREA from 0x1000 to... 0x1000.
+        * In a normal OS/Memory Manager, this would be retarded, but ReactOS allows this (how it works
+        * I don't even want to know).
+        */
+        if (marea->EndingAddress != marea->StartingAddress)
+        {
+            Vad->EndingVpn = PAGE_ROUND_DOWN((ULONG_PTR)marea->EndingAddress - 1) >> PAGE_SHIFT;
+        }
+        else
+        {
+            Vad->EndingVpn = Vad->StartingVpn;
+        }
+       Vad->u.VadFlags.Spare = 1;
+       Vad->u.VadFlags.PrivateMemory = 1;
+       Vad->u.VadFlags.Protection = MiMakeProtectionMask(marea->Protect);
+       MiInsertVad(Vad, MmGetAddressSpaceOwner(AddressSpace));
+       marea->Vad = Vad;
+   }
+   else
+   {
+       marea->Vad = NULL;
+   }
 
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
    {
-      AddressSpace->BalancedRoot.u1.Parent = (PVOID)marea;
+      AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)marea;
       marea->LeftChild = marea->RightChild = marea->Parent = NULL;
       return;
    }
 
-   Node = (PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent;
+   Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    do
    {
       DPRINT("marea->EndingAddress: %p Node->StartingAddress: %p\n",
@@ -466,7 +452,7 @@ MmInsertMemoryArea(
 
 static PVOID
 MmFindGapBottomUp(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG_PTR Length,
    ULONG_PTR Granularity)
 {
@@ -478,15 +464,13 @@ MmFindGapBottomUp(
    PMEMORY_AREA FirstNode;
    PMEMORY_AREA PreviousNode;
 
-   MmVerifyMemoryAreas(AddressSpace);
-
    DPRINT("LowestAddress: %p HighestAddress: %p\n",
           LowestAddress, HighestAddress);
 
    AlignedAddress = MM_ROUND_UP(LowestAddress, Granularity);
 
    /* Special case for empty tree. */
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
    {
       if ((ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length)
       {
@@ -498,7 +482,7 @@ MmFindGapBottomUp(
    }
 
    /* Go to the node with lowest address in the tree. */
-   FirstNode = Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent);
+   FirstNode = Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
 
    /* Traverse the tree from left to right. */
    PreviousNode = Node;
@@ -509,13 +493,16 @@ MmFindGapBottomUp(
          break;
 
       AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity);
-      if (Node->StartingAddress > AlignedAddress &&
-          (ULONG_PTR)Node->StartingAddress - (ULONG_PTR)AlignedAddress >= Length)
+      if (AlignedAddress >= LowestAddress)
       {
-         DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
-         return AlignedAddress;
+          if (Node->StartingAddress > AlignedAddress &&
+              (ULONG_PTR)Node->StartingAddress - (ULONG_PTR)AlignedAddress >= Length)
+          {
+             DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
+             ASSERT(AlignedAddress >= LowestAddress);
+             return AlignedAddress;
+          }
       }
-
       PreviousNode = Node;
    }
 
@@ -525,6 +512,7 @@ MmFindGapBottomUp(
        (ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length)
    {
       DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
+      ASSERT(AlignedAddress >= LowestAddress);
       return AlignedAddress;
    }
 
@@ -534,6 +522,7 @@ MmFindGapBottomUp(
        (ULONG_PTR)FirstNode->StartingAddress - (ULONG_PTR)AlignedAddress >= Length)
    {
       DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
+      ASSERT(AlignedAddress >= LowestAddress);
       return AlignedAddress;
    }
 
@@ -544,7 +533,7 @@ MmFindGapBottomUp(
 
 static PVOID
 MmFindGapTopDown(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG_PTR Length,
    ULONG_PTR Granularity)
 {
@@ -555,8 +544,6 @@ MmFindGapTopDown(
    PMEMORY_AREA Node;
    PMEMORY_AREA PreviousNode;
 
-   MmVerifyMemoryAreas(AddressSpace);
-
    DPRINT("LowestAddress: %p HighestAddress: %p\n",
           LowestAddress, HighestAddress);
 
@@ -567,7 +554,7 @@ MmFindGapTopDown(
       return NULL;
 
    /* Special case for empty tree. */
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
    {
       if (AlignedAddress >= LowestAddress)
       {
@@ -579,7 +566,7 @@ MmFindGapTopDown(
    }
 
    /* Go to the node with highest address in the tree. */
-   Node = MmIterateLastNode((PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent);
+   Node = MmIterateLastNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
 
    /* Check if there is enough space after the last memory area. */
    if (Node->EndingAddress <= AlignedAddress)
@@ -628,9 +615,9 @@ MmFindGapTopDown(
 }
 
 
-PVOID STDCALL
+PVOID NTAPI
 MmFindGap(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG_PTR Length,
    ULONG_PTR Granularity,
    BOOLEAN TopDown)
@@ -641,19 +628,17 @@ MmFindGap(
    return MmFindGapBottomUp(AddressSpace, Length, Granularity);
 }
 
-ULONG_PTR STDCALL
+ULONG_PTR NTAPI
 MmFindGapAtAddress(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PVOID Address)
 {
-   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent;
+   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    PMEMORY_AREA RightNeighbour = NULL;
    PVOID LowestAddress  = MmGetAddressSpaceOwner(AddressSpace) ? MM_LOWEST_USER_ADDRESS : MmSystemRangeStart;
    PVOID HighestAddress = MmGetAddressSpaceOwner(AddressSpace) ?
                           (PVOID)((ULONG_PTR)MmSystemRangeStart - 1) : (PVOID)MAXULONG_PTR;
 
-   MmVerifyMemoryAreas(AddressSpace);
-
    Address = MM_ROUND_DOWN(Address, PAGE_SIZE);
 
    if (LowestAddress < MmSystemRangeStart)
@@ -703,21 +688,10 @@ MmFindGapAtAddress(
    }
 }
 
-/**
- * @name MmInitMemoryAreas
- *
- * Initialize the memory area list implementation.
- */
-
-NTSTATUS
-INIT_FUNCTION
+VOID
 NTAPI
-MmInitMemoryAreas(VOID)
-{
-   DPRINT("MmInitMemoryAreas()\n");
-   return(STATUS_SUCCESS);
-}
-
+MiRemoveNode(IN PMMADDRESS_NODE Node,
+IN PMM_AVL_TABLE Table);
 
 /**
  * @name MmFreeMemoryArea
@@ -738,9 +712,9 @@ MmInitMemoryAreas(VOID)
  * @remarks Lock the address space before calling this function.
  */
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 MmFreeMemoryArea(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PMEMORY_AREA MemoryArea,
    PMM_FREE_PAGE_FUNC FreePage,
    PVOID FreePageContext)
@@ -748,51 +722,64 @@ MmFreeMemoryArea(
    PMEMORY_AREA *ParentReplace;
    ULONG_PTR Address;
    PVOID EndAddress;
-   PEPROCESS CurrentProcess = PsGetCurrentProcess();
-   PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-    
-   if (Process != NULL &&
-       Process != CurrentProcess)
+   
+   if (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3)
    {
-      KeAttachProcess(&Process->Pcb);
-   }
-
-   EndAddress = MM_ROUND_UP(MemoryArea->EndingAddress, PAGE_SIZE);
-   for (Address = (ULONG_PTR)MemoryArea->StartingAddress;
-        Address < (ULONG_PTR)EndAddress;
-        Address += PAGE_SIZE)
-   {
-      if (MemoryArea->Type == MEMORY_AREA_IO_MAPPING)
-      {
-         MmRawDeleteVirtualMapping((PVOID)Address);
-      }
-      else
-      {
-         BOOLEAN Dirty = FALSE;
-         SWAPENTRY SwapEntry = 0;
-         PFN_TYPE Page = 0;
-
-         if (MmIsPageSwapEntry(Process, (PVOID)Address))
-         {
-            MmDeletePageFileMapping(Process, (PVOID)Address, &SwapEntry);
-         }
-         else
-         {
-            MmDeleteVirtualMapping(Process, (PVOID)Address, FALSE, &Dirty, &Page);
-         }
-         if (FreePage != NULL)
-         {
-            FreePage(FreePageContext, MemoryArea, (PVOID)Address,
-                     Page, SwapEntry, (BOOLEAN)Dirty);
-         }
-      }
-   }
-
-   if (Process != NULL &&
-       Process != CurrentProcess)
-   {
-      KeDetachProcess();
-   }
+       PEPROCESS CurrentProcess = PsGetCurrentProcess();
+       PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+        
+       if (Process != NULL &&
+           Process != CurrentProcess)
+       {
+          KeAttachProcess(&Process->Pcb);
+       }
+
+       EndAddress = MM_ROUND_UP(MemoryArea->EndingAddress, PAGE_SIZE);
+       for (Address = (ULONG_PTR)MemoryArea->StartingAddress;
+            Address < (ULONG_PTR)EndAddress;
+            Address += PAGE_SIZE)
+       {
+             BOOLEAN Dirty = FALSE;
+             SWAPENTRY SwapEntry = 0;
+             PFN_NUMBER Page = 0;
+
+             if (MmIsPageSwapEntry(Process, (PVOID)Address))
+             {
+                MmDeletePageFileMapping(Process, (PVOID)Address, &SwapEntry);
+             }
+             else
+             {
+                MmDeleteVirtualMapping(Process, (PVOID)Address, FALSE, &Dirty, &Page);
+             }
+             if (FreePage != NULL)
+             {
+                FreePage(FreePageContext, MemoryArea, (PVOID)Address,
+                         Page, SwapEntry, (BOOLEAN)Dirty);
+             }
+       }
+
+       if (Process != NULL &&
+           Process != CurrentProcess)
+       {
+          KeDetachProcess();
+       }
+
+       if (MemoryArea->Vad)
+       {
+           ASSERT(MemoryArea->EndingAddress < MmSystemRangeStart);
+           ASSERT(MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY || MemoryArea->Type == MEMORY_AREA_SECTION_VIEW);
+           
+           /* MmCleanProcessAddressSpace might have removed it (and this would be MmDeleteProcessAdressSpace) */
+           ASSERT(((PMMVAD)MemoryArea->Vad)->u.VadFlags.Spare != 0);
+           if (((PMMVAD)MemoryArea->Vad)->u.VadFlags.Spare == 1)
+           {
+               MiRemoveNode(MemoryArea->Vad, &Process->VadRoot);
+           }
+           
+           ExFreePool(MemoryArea->Vad);
+           MemoryArea->Vad = NULL;
+       }
+    }
 
    /* Remove the tree item. */
    {
@@ -804,7 +791,7 @@ MmFreeMemoryArea(
             ParentReplace = &MemoryArea->Parent->RightChild;
       }
       else
-         ParentReplace = (PMEMORY_AREA*)&AddressSpace->BalancedRoot.u1.Parent;
+         ParentReplace = (PMEMORY_AREA*)&AddressSpace->WorkingSetExpansionLinks.Flink;
 
       if (MemoryArea->RightChild == NULL)
       {
@@ -855,57 +842,6 @@ MmFreeMemoryArea(
    return STATUS_SUCCESS;
 }
 
-/**
- * @name MmFreeMemoryAreaByPtr
- *
- * Free an existing memory area given a pointer inside it.
- *
- * @param AddressSpace
- *        Address space to free the area from.
- * @param BaseAddress
- *        Address in the memory area we're about to free.
- * @param FreePage
- *        Callback function for each freed page.
- * @param FreePageContext
- *        Context passed to the callback function.
- *
- * @return Status
- *
- * @see MmFreeMemoryArea
- *
- * @todo Should we require the BaseAddress to be really the starting
- *       address of the memory area or is the current relaxed check
- *       (BaseAddress can point anywhere in the memory area) acceptable?
- *
- * @remarks Lock the address space before calling this function.
- */
-
-NTSTATUS STDCALL
-MmFreeMemoryAreaByPtr(
-   PMM_AVL_TABLE AddressSpace,
-   PVOID BaseAddress,
-   PMM_FREE_PAGE_FUNC FreePage,
-   PVOID FreePageContext)
-{
-   PMEMORY_AREA MemoryArea;
-
-   DPRINT("MmFreeMemoryArea(AddressSpace %p, BaseAddress %p, "
-          "FreePageContext %p)\n", AddressSpace, BaseAddress,
-          FreePageContext);
-
-   MmVerifyMemoryAreas(AddressSpace);
-
-   MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
-                                            BaseAddress);
-   if (MemoryArea == NULL)
-   {
-      KEBUGCHECK(0);
-      return(STATUS_UNSUCCESSFUL);
-   }
-
-   return MmFreeMemoryArea(AddressSpace, MemoryArea, FreePage, FreePageContext);
-}
-
 /**
  * @name MmCreateMemoryArea
  *
@@ -932,8 +868,8 @@ MmFreeMemoryAreaByPtr(
  * @remarks Lock the address space before calling this function.
  */
 
-NTSTATUS STDCALL
-MmCreateMemoryArea(PMM_AVL_TABLE AddressSpace,
+NTSTATUS NTAPI
+MmCreateMemoryArea(PMMSUPPORT AddressSpace,
                    ULONG Type,
                    PVOID *BaseAddress,
                    ULONG_PTR Length,
@@ -954,8 +890,6 @@ MmCreateMemoryArea(PMM_AVL_TABLE AddressSpace,
           Type, BaseAddress, *BaseAddress, Length, AllocationFlags,
           FixedAddress, Result);
 
-   MmVerifyMemoryAreas(AddressSpace);
-
    Granularity = (MEMORY_AREA_VIRTUAL_MEMORY == Type ? MM_VIRTMEM_GRANULARITY : PAGE_SIZE);
    if ((*BaseAddress) == 0 && !FixedAddress)
    {
@@ -978,14 +912,12 @@ MmCreateMemoryArea(PMM_AVL_TABLE AddressSpace,
 
       if (!MmGetAddressSpaceOwner(AddressSpace) && *BaseAddress < MmSystemRangeStart)
       {
-         CHECKPOINT;
          return STATUS_ACCESS_VIOLATION;
       }
 
       if (MmGetAddressSpaceOwner(AddressSpace) &&
           (ULONG_PTR)(*BaseAddress) + tmpLength > (ULONG_PTR)MmSystemRangeStart)
       {
-         CHECKPOINT;
          return STATUS_ACCESS_VIOLATION;
       }
 
@@ -1003,9 +935,31 @@ MmCreateMemoryArea(PMM_AVL_TABLE AddressSpace,
          return STATUS_CONFLICTING_ADDRESSES;
       }
    }
+    
+    //
+    // Is this a static memory area?
+    //
+    if (Type & MEMORY_AREA_STATIC)
+    {
+        //
+        // Use the static array instead of the pool
+        //
+        ASSERT(MiStaticMemoryAreaCount < MI_STATIC_MEMORY_AREAS);
+        MemoryArea = &MiStaticMemoryAreas[MiStaticMemoryAreaCount++];
+        Type &= ~MEMORY_AREA_STATIC;
+    }
+    else
+    {
+        //
+        // Allocate the memory area from nonpaged pool
+        //
+        MemoryArea = ExAllocatePoolWithTag(NonPagedPool,
+                                           sizeof(MEMORY_AREA),
+                                           TAG_MAREA);
+    }
+
+    if (!MemoryArea) return STATUS_NO_MEMORY;
 
-   MemoryArea = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
-                                      TAG_MAREA);
    RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA));
    MemoryArea->Type = Type;
    MemoryArea->StartingAddress = *BaseAddress;
@@ -1035,13 +989,13 @@ MmMapMemoryArea(PVOID BaseAddress,
 
    for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
    {
-      PFN_TYPE Page;
+      PFN_NUMBER Page;
 
       Status = MmRequestPageMemoryConsumer(Consumer, TRUE, &Page);
       if (!NT_SUCCESS(Status))
       {
          DPRINT1("Unable to allocate page\n");
-         KEBUGCHECK(0);
+         KeBugCheck(MEMORY_MANAGEMENT);
       }
       Status = MmCreateVirtualMapping (NULL,
                                        (PVOID)((ULONG_PTR)BaseAddress + (i * PAGE_SIZE)),
@@ -1051,41 +1005,56 @@ MmMapMemoryArea(PVOID BaseAddress,
       if (!NT_SUCCESS(Status))
       {
          DPRINT1("Unable to create virtual mapping\n");
-         KEBUGCHECK(0);
+         KeBugCheck(MEMORY_MANAGEMENT);
       }
    }
 }
 
-
-VOID STDCALL
-MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process,
-                                 PMM_AVL_TABLE AddressSpace,
-                                 PVOID BaseAddress)
+NTSTATUS
+NTAPI
+MmDeleteProcessAddressSpace(PEPROCESS Process)
 {
+   PVOID Address;
    PMEMORY_AREA MemoryArea;
-   PLIST_ENTRY Entry;
-   PMM_REGION Region;
-   BOOLEAN Reserved;
 
-   MmVerifyMemoryAreas(AddressSpace);
+   DPRINT("MmDeleteProcessAddressSpace(Process %x (%s))\n", Process,
+          Process->ImageFileName);
 
-   MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
-   if (MemoryArea != NULL)
-   {
-      Entry = MemoryArea->Data.VirtualMemoryData.RegionListHead.Flink;
-      Reserved = TRUE;
-      while (Reserved && Entry != &MemoryArea->Data.VirtualMemoryData.RegionListHead)
-      {
-         Region = CONTAINING_RECORD(Entry, MM_REGION, RegionListEntry);
-         Reserved = (MEM_RESERVE == Region->Type);
-         Entry = Entry->Flink;
-      }
+   RemoveEntryList(&Process->MmProcessLinks);
 
-      if (Reserved)
+   MmLockAddressSpace(&Process->Vm);
+
+   while ((MemoryArea = (PMEMORY_AREA)Process->Vm.WorkingSetExpansionLinks.Flink) != NULL)
+   {
+      switch (MemoryArea->Type)
       {
-         MmFreeVirtualMemory(Process, MemoryArea);
+         case MEMORY_AREA_SECTION_VIEW:
+             Address = (PVOID)MemoryArea->StartingAddress;
+             MmUnlockAddressSpace(&Process->Vm);
+             MmUnmapViewOfSection(Process, Address);
+             MmLockAddressSpace(&Process->Vm);
+             break;
+
+         case MEMORY_AREA_VIRTUAL_MEMORY:
+             MmFreeVirtualMemory(Process, MemoryArea);
+             break;
+
+         case MEMORY_AREA_OWNED_BY_ARM3:
+             MmFreeMemoryArea(&Process->Vm,
+                              MemoryArea,
+                              NULL,
+                              NULL);
+             break;
+
+         default:
+            KeBugCheck(MEMORY_MANAGEMENT);
       }
    }
+
+   MmUnlockAddressSpace(&Process->Vm);
+
+   DPRINT("Finished MmReleaseMmInfo()\n");
+   return(STATUS_SUCCESS);
 }
 
 /* EOF */