[ros-dev] Memory Area Patch

Filip Navara xnavara at volny.cz
Sun Jan 2 03:31:10 CET 2005


Hi!

For the past few nights I've been working on a patch to convert 
MEMORY_AREAs from using lists to use binary search tree. The result of 
the work is attached. It's not optimized yet, but in the worst case it 
will be as slow as the list implementation. Since the patch is getting 
rather big I want to commit it in SVN before further working on it. So 
I'm hereby asking for review/testing in order to ensure that it will not 
break anything.

Thanks,
Filip

P.S. Many thanks to Royce Michell III and Mike Nordell for helping me to 
get this beast working.
-------------- next part --------------
Index: ps/w32call.c
===================================================================
--- ps/w32call.c	(revision 12712)
+++ ps/w32call.c	(working copy)
@@ -163,11 +163,10 @@
 PsFreeCallbackStack(PVOID StackLimit)
 {
   MmLockAddressSpace(MmGetKernelAddressSpace());
-  MmFreeMemoryArea(MmGetKernelAddressSpace(),
-		   StackLimit,
-		   MM_STACK_SIZE,
-		   PsFreeCallbackStackPage,
-		   NULL);
+  MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+		        StackLimit,
+		        PsFreeCallbackStackPage,
+		        NULL);
   MmUnlockAddressSpace(MmGetKernelAddressSpace());
 }
 
Index: include/internal/mm.h
===================================================================
--- include/internal/mm.h	(revision 12712)
+++ include/internal/mm.h	(working copy)
@@ -184,15 +184,17 @@
 
 #endif /* __USE_W32API */
 
-typedef struct
+typedef struct _MEMORY_AREA
 {
+  PVOID StartingAddress;
+  PVOID EndingAddress;
+  struct _MEMORY_AREA *Parent;
+  struct _MEMORY_AREA *LeftChild;
+  struct _MEMORY_AREA *RightChild;
   ULONG Type;
-  PVOID BaseAddress;
-  ULONG Length;
   ULONG Attributes;
-  LIST_ENTRY Entry;
   ULONG LockCount;
-  struct _EPROCESS* Process;
+  struct _EPROCESS* Process; /* FIXME: We don't need this! */
   BOOLEAN DeleteInProgress;
   ULONG PageOpCount;
   union
@@ -215,7 +217,7 @@
 
 typedef struct _MADDRESS_SPACE
 {
-  LIST_ENTRY MAreaListHead;
+  PMEMORY_AREA MemoryAreaRoot;
   FAST_MUTEX Lock;
   PVOID LowestAddress;
   struct _EPROCESS* Process;
@@ -333,6 +335,10 @@
    LIST_ENTRY RegionListEntry;
 } MM_REGION, *PMM_REGION;
 
+typedef VOID (*PMM_FREE_PAGE_FUNC)(PVOID Context, PMEMORY_AREA MemoryArea, 
+                                   PVOID Address, PFN_TYPE Page,
+                                   SWAPENTRY SwapEntry, BOOLEAN Dirty);
+
 /* FUNCTIONS */
 
 /* aspace.c ******************************************************************/
@@ -354,49 +360,68 @@
 
 /* marea.c *******************************************************************/
 
-NTSTATUS MmCreateMemoryArea(struct _EPROCESS* Process,
-			    PMADDRESS_SPACE AddressSpace,
-			    ULONG Type,
-			    PVOID* BaseAddress,
-			    ULONG Length,
-			    ULONG Attributes,
-			    MEMORY_AREA** Result,
-			    BOOL FixedAddress,
-			    BOOL TopDown,
-			    PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL);
+NTSTATUS INIT_FUNCTION
+MmInitMemoryAreas(VOID);
 
-MEMORY_AREA* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace, 
-				       PVOID Address);
+NTSTATUS STDCALL
+MmCreateMemoryArea(
+   struct _EPROCESS* Process,
+   PMADDRESS_SPACE AddressSpace,
+   ULONG Type,
+   PVOID *BaseAddress,
+   ULONG_PTR Length,
+   ULONG Attributes,
+   PMEMORY_AREA *Result,
+   BOOLEAN FixedAddress,
+   BOOLEAN TopDown,
+   PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL);
 
-ULONG MmFindGapAtAddress(PMADDRESS_SPACE AddressSpace, 
-			 PVOID Address);
+PMEMORY_AREA STDCALL
+MmOpenMemoryAreaByAddress(
+   PMADDRESS_SPACE AddressSpace, 
+   PVOID Address);
 
-NTSTATUS MmInitMemoryAreas(VOID);
+ULONG STDCALL
+MmFindGapAtAddress(
+   PMADDRESS_SPACE AddressSpace, 
+   PVOID Address);
 
-NTSTATUS MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
-			  PVOID BaseAddress,
-			  ULONG Length,
-			  VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea, 
-					   PVOID Address, PFN_TYPE Page, SWAPENTRY SwapEntry,
-					   BOOLEAN Dirty),
-			  PVOID FreePageContext);
+NTSTATUS STDCALL
+MmFreeMemoryArea(
+   PMADDRESS_SPACE AddressSpace,
+   PMEMORY_AREA MemoryArea,
+   PMM_FREE_PAGE_FUNC FreePage,
+   PVOID FreePageContext);
 
-VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead);
+NTSTATUS STDCALL
+MmFreeMemoryAreaByPtr(
+   PMADDRESS_SPACE AddressSpace,
+   PVOID BaseAddress,
+   PMM_FREE_PAGE_FUNC FreePage,
+   PVOID FreePageContext);
 
-NTSTATUS MmLockMemoryArea(MEMORY_AREA* MemoryArea);
+VOID STDCALL
+MmDumpMemoryAreas(PMADDRESS_SPACE AddressSpace);
 
-NTSTATUS MmUnlockMemoryArea(MEMORY_AREA* MemoryArea);
+PMEMORY_AREA STDCALL
+MmOpenMemoryAreaByRegion(
+   PMADDRESS_SPACE AddressSpace, 
+   PVOID Address,
+   ULONG_PTR Length);
 
-MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace, 
-				      PVOID Address,
-				      ULONG Length);
+PVOID STDCALL
+MmFindGap(
+   PMADDRESS_SPACE AddressSpace,
+   ULONG_PTR Length,
+   ULONG_PTR Granularity,
+   BOOLEAN TopDown);
 
-PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity, BOOL TopDown);
+VOID STDCALL
+MmReleaseMemoryAreaIfDecommitted(
+   PEPROCESS Process,
+   PMADDRESS_SPACE AddressSpace,
+   PVOID BaseAddress);
 
-void MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process,
-                                      PMADDRESS_SPACE AddressSpace,
-                                      PVOID BaseAddress);
-
 /* npool.c *******************************************************************/
 
 VOID MiDebugDumpNonPagedPool(BOOLEAN NewOnly);
Index: cc/view.c
===================================================================
--- cc/view.c	(revision 12712)
+++ cc/view.c	(working copy)
@@ -813,8 +813,7 @@
 #else
   MmLockAddressSpace(MmGetKernelAddressSpace());
   MmFreeMemoryArea(MmGetKernelAddressSpace(),
-		   CacheSeg->BaseAddress,
-		   CacheSeg->Bcb->CacheSegmentSize,
+		   CacheSeg->MemoryArea,
 		   CcFreeCachePage,
 		   NULL);
   MmUnlockAddressSpace(MmGetKernelAddressSpace());
Index: ke/i386/exp.c
===================================================================
--- ke/i386/exp.c	(revision 12712)
+++ ke/i386/exp.c	(working copy)
@@ -320,7 +320,7 @@
 	{
 	  KeRosPrintAddress((PVOID)Frame[1]);
 	  Frame = (PULONG)Frame[0];
-          DbgPrint(" ");
+          DbgPrint("\n");
 	}
 #else
       DbgPrint("Frames: ");
@@ -663,7 +663,7 @@
 				break;
 			StackBase = Frame;
 			Frame = (PULONG)Frame[0];
-			DbgPrint(" ");
+			DbgPrint("\n");
 		}
 	}
 	_SEH_HANDLE
Index: ke/bug.c
===================================================================
--- ke/bug.c	(revision 12712)
+++ ke/bug.c	(working copy)
@@ -116,6 +116,11 @@
   Ke386DisableInterrupts();
   DebugLogDumpMessages();
 
+  if (MmGetKernelAddressSpace()->Lock.Owner == KeGetCurrentThread())
+    {
+      MmUnlockAddressSpace(MmGetKernelAddressSpace());
+    }
+
   if (KeGetCurrentIrql() < DISPATCH_LEVEL)
     {
       KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
Index: ke/kthread.c
===================================================================
--- ke/kthread.c	(revision 12712)
+++ ke/kthread.c	(working copy)
@@ -90,11 +90,10 @@
   if (Thread->StackLimit != (ULONG_PTR)&init_stack)
     {       
       MmLockAddressSpace(MmGetKernelAddressSpace());
-      MmFreeMemoryArea(MmGetKernelAddressSpace(),
-		       (PVOID)Thread->StackLimit,
-		       MM_STACK_SIZE,
-		       KeFreeStackPage,
-		       NULL);
+      MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+                            (PVOID)Thread->StackLimit,
+                            KeFreeStackPage,
+                            NULL);
       MmUnlockAddressSpace(MmGetKernelAddressSpace());
     }
   Thread->StackLimit = 0;
Index: mm/section.c
===================================================================
--- mm/section.c	(revision 12712)
+++ mm/section.c	(working copy)
@@ -611,7 +611,7 @@
    ULONG Offset;
    PFN_TYPE Page;
    NTSTATUS Status;
-   ULONG PAddress;
+   PVOID PAddress;
    PSECTION_OBJECT Section;
    PMM_SECTION_SEGMENT Segment;
    ULONG Entry;
@@ -635,12 +635,12 @@
       return(STATUS_SUCCESS);
    }
 
-   PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
-   Offset = PAddress - (ULONG)MemoryArea->BaseAddress;
+   PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
+   Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress;
 
    Segment = MemoryArea->Data.SectionData.Segment;
    Section = MemoryArea->Data.SectionData.Section;
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.SectionData.RegionListHead,
                          Address, NULL);
    /*
@@ -1129,7 +1129,7 @@
    PFN_TYPE NewPage;
    PVOID NewAddress;
    NTSTATUS Status;
-   ULONG PAddress;
+   PVOID PAddress;
    ULONG Offset;
    PMM_PAGEOP PageOp;
    PMM_REGION Region;
@@ -1148,12 +1148,12 @@
    /*
     * Find the offset of the page
     */
-   PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
-   Offset = PAddress - (ULONG)MemoryArea->BaseAddress;
+   PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
+   Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress;
 
    Segment = MemoryArea->Data.SectionData.Segment;
    Section = MemoryArea->Data.SectionData.Section;
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.SectionData.RegionListHead,
                          Address, NULL);
    /*
@@ -1181,7 +1181,7 @@
        PFN_FROM_SSE(Entry) != OldPage)
    {
       /* This is a private page. We must only change the page protection. */
-      MmSetPageProtect(AddressSpace->Process, (PVOID)PAddress, Region->Protect);
+      MmSetPageProtect(AddressSpace->Process, PAddress, Region->Protect);
       return(STATUS_SUCCESS);
    }
 
@@ -1244,7 +1244,7 @@
     */
 
    NewAddress = ExAllocatePageWithPhysPage(NewPage);
-   memcpy(NewAddress, (PVOID)PAddress, PAGE_SIZE);
+   memcpy(NewAddress, PAddress, PAGE_SIZE);
    ExUnmapPage(NewAddress);
 
    /*
@@ -1267,7 +1267,7 @@
       KEBUGCHECK(0);
       return(Status);
    }
-   MmInsertRmap(NewPage, AddressSpace->Process, (PVOID)PAddress);
+   MmInsertRmap(NewPage, AddressSpace->Process, PAddress);
    if (!NT_SUCCESS(Status))
    {
       DbgPrint("Unable to create virtual mapping\n");
@@ -1282,7 +1282,7 @@
    /*
     * Unshare the old page.
     */
-   MmDeleteRmap(OldPage, AddressSpace->Process, (PVOID)PAddress);
+   MmDeleteRmap(OldPage, AddressSpace->Process, PAddress);
    MmLockSectionSegment(Segment);
    MmUnsharePageEntrySectionSegment(Section, Segment, Offset, FALSE, FALSE);
    MmUnlockSectionSegment(Segment);
@@ -1351,7 +1351,7 @@
    Context.Segment = MemoryArea->Data.SectionData.Segment;
    Context.Section = MemoryArea->Data.SectionData.Section;
 
-   Context.Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress);
+   Context.Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
    FileOffset = Context.Offset + Context.Segment->FileOffset;
 
    IsImageSection = Context.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE;
@@ -1691,7 +1691,7 @@
 
    Address = (PVOID)PAGE_ROUND_DOWN(Address);
 
-   Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress);
+   Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
 
    /*
     * Get the segment and section.
@@ -1855,7 +1855,7 @@
             ULONG Entry;
             PFN_TYPE Page;
 
-            Offset =  (ULONG)Address - (ULONG)MemoryArea->BaseAddress;
+            Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
             Entry = MmGetPageEntrySectionSegment(Segment, Offset);
             Page = MmGetPfnForProcess(AddressSpace->Process, Address);
 
@@ -1889,12 +1889,12 @@
    NTSTATUS Status;
 
    Length =
-      min(Length, (ULONG) ((char*)MemoryArea->BaseAddress + MemoryArea->Length - (char*)BaseAddress));
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+      min(Length, (ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)BaseAddress);
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.SectionData.RegionListHead,
                          BaseAddress, NULL);
    *OldProtect = Region->Protect;
-   Status = MmAlterRegion(AddressSpace, MemoryArea->BaseAddress,
+   Status = MmAlterRegion(AddressSpace, MemoryArea->StartingAddress,
                           &MemoryArea->Data.SectionData.RegionListHead,
                           BaseAddress, Length, Region->Type, Protect,
                           MmAlterViewAttributes);
@@ -1915,7 +1915,7 @@
    PMEMORY_AREA CurrentMArea;
    KIRQL oldIrql;
 
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion((PVOID)MemoryArea->StartingAddress,
                          &MemoryArea->Data.SectionData.RegionListHead,
                          Address, &RegionBaseAddress);
    if (Region == NULL)
@@ -1934,11 +1934,11 @@
          CurrentEntry = CurrentEntry->Flink;
          if (Info->AllocationBase == NULL)
          {
-            Info->AllocationBase = CurrentMArea->BaseAddress;
+            Info->AllocationBase = CurrentMArea->StartingAddress;
          }
-         else if (CurrentMArea->BaseAddress < Info->AllocationBase)
+         else if (CurrentMArea->StartingAddress < Info->AllocationBase)
          {
-            Info->AllocationBase = CurrentMArea->BaseAddress;
+            Info->AllocationBase = CurrentMArea->StartingAddress;
          }
       }
       KeReleaseSpinLock(&Section->ViewListLock, oldIrql);
@@ -1949,11 +1949,12 @@
    else
    {
       Info->BaseAddress = RegionBaseAddress;
-      Info->AllocationBase = MemoryArea->BaseAddress;
+      Info->AllocationBase = MemoryArea->StartingAddress;
       Info->AllocationProtect = MemoryArea->Attributes;
       Info->Type = MEM_MAPPED;
    }
-   Info->RegionSize = PAGE_ROUND_UP(MemoryArea->Length);
+   Info->RegionSize = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress -
+                                    (ULONG_PTR)MemoryArea->StartingAddress);
    Info->State = MEM_COMMIT;
    Info->Protect = Region->Protect;
 
@@ -3583,7 +3584,7 @@
 
    Address = (PVOID)PAGE_ROUND_DOWN(Address);
 
-   Offset = ((ULONG_PTR)Address - (ULONG_PTR)MArea->BaseAddress) +
+   Offset = ((ULONG_PTR)Address - (ULONG_PTR)MArea->StartingAddress) +
             MemoryArea->Data.SectionData.ViewOffset;
 
    Section = MArea->Data.SectionData.Section;
@@ -3711,16 +3712,14 @@
    if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
    {
       Status = MmFreeMemoryArea(AddressSpace,
-                                BaseAddress,
-                                0,
+                                MemoryArea,
                                 NULL,
                                 NULL);
    }
    else
    {
       Status = MmFreeMemoryArea(AddressSpace,
-                                BaseAddress,
-                                0,
+                                MemoryArea,
                                 MmFreeSectionPage,
                                 MemoryArea);
    }
@@ -4087,7 +4086,7 @@
          KEBUGCHECK(0);
       }
       Status = MmCreateVirtualMapping (NULL,
-                                       ((char*)Result + (i * PAGE_SIZE)),
+                                       (PVOID)(Result + (i * PAGE_SIZE)),
                                        PAGE_READWRITE,
                                        &Page,
                                        1);
@@ -4178,7 +4177,7 @@
    {
       ULONG i;
       ULONG NrSegments;
-      PVOID ImageBase;
+      ULONG_PTR ImageBase;
       ULONG ImageSize;
       PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
       PMM_SECTION_SEGMENT SectionSegments;
@@ -4188,10 +4187,10 @@
       NrSegments = ImageSectionObject->NrSegments;
 
 
-      ImageBase = *BaseAddress;
-      if (ImageBase == NULL)
+      ImageBase = (ULONG_PTR)*BaseAddress;
+      if (ImageBase == 0)
       {
-         ImageBase = (PVOID)ImageSectionObject->ImageBase;
+         ImageBase = ImageSectionObject->ImageBase;
       }
 
       ImageSize = 0;
@@ -4207,7 +4206,7 @@
       }
 
       /* Check there is enough space to map the section at that point. */
-      if (MmOpenMemoryAreaByRegion(AddressSpace, ImageBase,
+      if (MmOpenMemoryAreaByRegion(AddressSpace, (PVOID)ImageBase,
                                    PAGE_ROUND_UP(ImageSize)) != NULL)
       {
          /* Fail if the user requested a fixed base address. */
@@ -4217,8 +4216,8 @@
             return(STATUS_UNSUCCESSFUL);
          }
          /* Otherwise find a gap to map the image. */
-         ImageBase = MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), PAGE_SIZE, FALSE);
-         if (ImageBase == NULL)
+         ImageBase = (ULONG_PTR)MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), PAGE_SIZE, FALSE);
+         if (ImageBase == 0)
          {
             MmUnlockAddressSpace(AddressSpace);
             return(STATUS_UNSUCCESSFUL);
@@ -4250,7 +4249,7 @@
          }
       }
 
-      *BaseAddress = ImageBase;
+      *BaseAddress = (PVOID)ImageBase;
    }
    else
    {
Index: mm/mm.c
===================================================================
--- mm/mm.c	(revision 12712)
+++ mm/mm.c	(working copy)
@@ -99,13 +99,13 @@
    DPRINT("MmReleaseMemoryArea(Process %x, Marea %x)\n",Process,Marea);
 
    DPRINT("Releasing %x between %x %x (type %d)\n",
-          Marea, Marea->BaseAddress, (char*)Marea->BaseAddress + Marea->Length,
+          Marea, Marea->StartingAddress, Marea->EndingAddress,
           Marea->Type);
 
    switch (Marea->Type)
    {
       case MEMORY_AREA_SECTION_VIEW:
-         Status = MmUnmapViewOfSection(Process, Marea->BaseAddress);
+         Status = MmUnmapViewOfSection(Process, (PVOID)Marea->StartingAddress);
          ASSERT(Status == STATUS_SUCCESS);
          return(STATUS_SUCCESS);
 
@@ -116,8 +116,7 @@
       case MEMORY_AREA_SHARED_DATA:
       case MEMORY_AREA_NO_ACCESS:
          Status = MmFreeMemoryArea(&Process->AddressSpace,
-                                   Marea->BaseAddress,
-                                   0,
+                                   Marea,
                                    NULL,
                                    NULL);
          break;
@@ -135,20 +134,35 @@
 
 NTSTATUS MmReleaseMmInfo(PEPROCESS Process)
 {
-   PLIST_ENTRY CurrentEntry;
-   PMEMORY_AREA Current;
+/*   PMEMORY_AREA CurrentNode;*/
+/*   PMEMORY_AREA NextNode;*/
 
    DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process,
           Process->ImageFileName);
 
    MmLockAddressSpace(&Process->AddressSpace);
 
-   while(!IsListEmpty(&Process->AddressSpace.MAreaListHead))
+#if 0
+   for (CurrentNode = Process->AddressSpace.MemoryAreaRoot;
+        CurrentNode != NULL;
+        CurrentNode = NextNode)
    {
-      CurrentEntry = Process->AddressSpace.MAreaListHead.Flink;
-      Current = CONTAINING_RECORD(CurrentEntry, MEMORY_AREA, Entry);
-      MmReleaseMemoryArea(Process, Current);
+      if (CurrentNode->LeftChild == NULL) 
+      {
+         NextNode = CurrentNode->RightChild;
+         MmReleaseMemoryArea(Process, CurrentNode);
+      } 
+      else 
+      {
+         NextNode = CurrentNode->LeftChild;
+         CurrentNode->LeftChild = NextNode->RightChild;
+         NextNode->RightChild = CurrentNode;
+      }
    }
+#else
+   while (Process->AddressSpace.MemoryAreaRoot != NULL)
+      MmReleaseMemoryArea(Process, Process->AddressSpace.MemoryAreaRoot);
+#endif
 
    Mmi386ReleaseMmInfo(Process);
 
@@ -208,7 +222,7 @@
 }
 
 NTSTATUS MmAccessFault(KPROCESSOR_MODE Mode,
-                       ULONG Address,
+                       ULONG Address, /* FiN TODO: Should be ULONG_PTR! */
                        BOOLEAN FromMdl)
 {
    PMADDRESS_SPACE AddressSpace;
@@ -330,7 +344,7 @@
 }
 
 NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
-                           ULONG Address,
+                           ULONG Address, /* FiN TODO: Should be ULONG_PTR! */
                            BOOLEAN FromMdl)
 {
    PMADDRESS_SPACE AddressSpace;
Index: mm/mdl.c
===================================================================
--- mm/mdl.c	(revision 12712)
+++ mm/mdl.c	(working copy)
@@ -269,7 +269,7 @@
          KEBUGCHECK(0);
       }
 
-      Base = (char*)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE;
+      Base = (PVOID)((ULONG_PTR)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE);
 
       if (MiMdlMappingRegionHint == StartingOffset)
       {
@@ -384,7 +384,7 @@
                              NULL);
    }
 
-   if ((DWORD)BaseAddress >= KERNEL_BASE)
+   if ((ULONG_PTR)BaseAddress >= KERNEL_BASE)
    {
       ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
       
@@ -416,7 +416,7 @@
          KEBUGCHECK(0);
       }
 
-      MmFreeMemoryArea( &Mdl->Process->AddressSpace, Marea->BaseAddress, 0, NULL, NULL );
+      MmFreeMemoryArea( &Mdl->Process->AddressSpace, Marea, NULL, NULL );
 
       Mdl->Process = NULL;
    }
Index: mm/ncache.c
===================================================================
--- mm/ncache.c	(revision 12712)
+++ mm/ncache.c	(working copy)
@@ -129,11 +129,10 @@
                                     IN ULONG NumberOfBytes)
 {
    MmLockAddressSpace(MmGetKernelAddressSpace());
-   MmFreeMemoryArea (MmGetKernelAddressSpace(),
-                     BaseAddress,
-                     NumberOfBytes,
-                     MmFreeNonCachedPage,
-                     NULL);
+   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+                         BaseAddress,
+                         MmFreeNonCachedPage,
+                         NULL);
    MmUnlockAddressSpace(MmGetKernelAddressSpace());
 }
 
Index: mm/marea.c
===================================================================
--- mm/marea.c	(revision 12712)
+++ mm/marea.c	(working copy)
@@ -35,331 +35,465 @@
 
 #define TAG_MAREA   TAG('M', 'A', 'R', 'E')
 
+/* #define VALIDATE_MEMORY_AREAS */
+
 /* FUNCTIONS *****************************************************************/
 
-VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead)
+/**
+ * @name MmIterateFirstNode
+ *
+ * @param Head
+ *        Head node of the MEMORY_AREA tree.
+ *
+ * @return The leftmost MEMORY_AREA node (ie. the one with lowest
+ *         address)
+ */
+
+static PMEMORY_AREA MmIterateFirstNode(PMEMORY_AREA Head)
 {
-   PLIST_ENTRY current_entry;
-   MEMORY_AREA* current;
+   PMEMORY_AREA Node = Head;
 
+   while (Node->LeftChild != NULL)
+      Node = Node->LeftChild;
+
+   return Node;
+}
+
+/**
+ * @name MmIterateNextNode
+ *
+ * @param Node
+ *        Current node in the tree.
+ *
+ * @return Next node in the tree (sorted by address).
+ */
+
+static PMEMORY_AREA MmIterateNextNode(PMEMORY_AREA Node)
+{
+   if (Node->RightChild != NULL)
+   {
+      Node = Node->RightChild;
+      while (Node->LeftChild != NULL)
+         Node = Node->LeftChild;
+   }
+   else
+   {
+      PMEMORY_AREA TempNode = NULL;
+ 
+      do
+      {
+         /* Check if we're at the end of tree. */
+         if (Node->Parent == NULL)
+            return NULL;
+ 
+         TempNode = Node;
+         Node = Node->Parent;
+      }
+      while (TempNode == Node->RightChild);
+   }
+   return Node;
+}
+
+/**
+ * @name MmIterateFirstNode
+ *
+ * @param Head
+ *        Head node of the MEMORY_AREA tree.
+ *
+ * @return The rightmost MEMORY_AREA node (ie. the one with highest
+ *         address)
+ */
+
+static PMEMORY_AREA MmIterateLastNode(PMEMORY_AREA Head)
+{
+   PMEMORY_AREA Node = Head;
+
+   while (Node->RightChild != NULL)
+      Node = Node->RightChild;
+
+   return Node;
+}
+
+/**
+ * @name MmIterateNextNode
+ *
+ * @param Node
+ *        Current node in the tree.
+ *
+ * @return Previous node in the tree (sorted by address).
+ */
+
+static PMEMORY_AREA MmIteratePrevNode(PMEMORY_AREA Node)
+{
+   if (Node->LeftChild != NULL)
+   {
+      Node = Node->LeftChild;
+      while (Node->RightChild != NULL)
+         Node = Node->RightChild;
+   }
+   else
+   {
+      PMEMORY_AREA TempNode = NULL;
+ 
+      do
+      {
+         /* Check if we're at the end of tree. */
+         if (Node->Parent == NULL)
+            return NULL;
+ 
+         TempNode = Node;
+         Node = Node->Parent;
+      }
+      while (TempNode == Node->LeftChild);
+   }
+   return Node;
+}
+
+#ifdef VALIDATE_MEMORY_AREAS
+static VOID MmVerifyMemoryAreas(PMADDRESS_SPACE AddressSpace)
+{
+   PMEMORY_AREA Node;
+
+   ASSERT(AddressSpace != NULL);
+   
+   /* Special case for empty tree. */
+   if (AddressSpace->MemoryAreaRoot == NULL)
+      return;
+
+   /* Traverse the tree from left to right. */
+   for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
+        Node != NULL;
+        Node = MmIterateNextNode(Node))
+   {
+      /* FiN: The starting address can be NULL if someone explicitely asks
+       * for NULL address. */
+      ASSERT(Node->StartingAddress >= AddressSpace->LowestAddress ||
+             Node->StartingAddress == NULL);
+      ASSERT(Node->EndingAddress >= Node->StartingAddress);
+   }
+}
+#else
+#define MmVerifyMemoryAreas(x) 
+#endif
+
+VOID STDCALL
+MmDumpMemoryAreas(PMADDRESS_SPACE AddressSpace)
+{
+   PMEMORY_AREA Node;
+
    DbgPrint("MmDumpMemoryAreas()\n");
+   
+   /* Special case for empty tree. */
+   if (AddressSpace->MemoryAreaRoot == NULL)
+      return;
 
-   current_entry = ListHead->Flink;
-   while (current_entry!=ListHead)
+   /* Traverse the tree from left to right. */
+   for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
+        Node != NULL;
+        Node = MmIterateNextNode(Node))
    {
-      current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
-      DbgPrint("Base %x Length %x End %x Attributes %x Flink %x\n",
-               current->BaseAddress,current->Length,
-               (char*)current->BaseAddress+current->Length,current->Attributes,
-               current->Entry.Flink);
-      current_entry = current_entry->Flink;
+      DbgPrint("Start %x End %x Attributes %x\n",
+               Node->StartingAddress, Node->EndingAddress,
+               Node->Attributes);
    }
+
    DbgPrint("Finished MmDumpMemoryAreas()\n");
 }
 
-MEMORY_AREA* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace,
-                                       PVOID Address)
+PMEMORY_AREA STDCALL
+MmOpenMemoryAreaByAddress(
+   PMADDRESS_SPACE AddressSpace,
+   PVOID Address)
 {
-   PLIST_ENTRY current_entry;
-   MEMORY_AREA* current;
-   PLIST_ENTRY previous_entry;
+   PMEMORY_AREA Node = AddressSpace->MemoryAreaRoot;
 
    DPRINT("MmOpenMemoryAreaByAddress(AddressSpace %x, Address %x)\n",
-          AddressSpace, Address);
+           AddressSpace, Address);
 
-   previous_entry = &AddressSpace->MAreaListHead;
-   current_entry = AddressSpace->MAreaListHead.Flink;
-   while (current_entry != &AddressSpace->MAreaListHead)
+   if (!(KdDebugState & KD_DEBUG_SCREEN))
+      MmVerifyMemoryAreas(AddressSpace);
+
+   while (Node != NULL)
    {
-      current = CONTAINING_RECORD(current_entry,
-                                  MEMORY_AREA,
-                                  Entry);
-      ASSERT(current_entry->Blink->Flink == current_entry);
-      ASSERT(current_entry->Flink->Blink == current_entry);
-      ASSERT(previous_entry->Flink == current_entry);
-      if (current->BaseAddress <= Address &&
-            (PVOID)((char*)current->BaseAddress + current->Length) > Address)
+      if (Address < Node->StartingAddress)
+         Node = Node->LeftChild;
+      else if (Address >= Node->EndingAddress)
+         Node = Node->RightChild;
+      else
       {
-         DPRINT("%s() = %x\n",__FUNCTION__,current);
-         return(current);
+         DPRINT("MmOpenMemoryAreaByAddress(%x): %x [%x - %x]\n",
+                Address, Node, Node->StartingAddress, Node->EndingAddress);
+         return Node;
       }
-      if (current->BaseAddress > Address)
-      {
-         DPRINT("%s() = NULL\n",__FUNCTION__);
-         return(NULL);
-      }
-      previous_entry = current_entry;
-      current_entry = current_entry->Flink;
    }
-   DPRINT("%s() = NULL\n",__FUNCTION__);
-   return(NULL);
+
+   DPRINT("MmOpenMemoryAreaByAddress(%x): 0\n", Address);
+   return NULL;
 }
 
-MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
-                                      PVOID Address,
-                                      ULONG Length)
+PMEMORY_AREA STDCALL
+MmOpenMemoryAreaByRegion(
+   PMADDRESS_SPACE AddressSpace,
+   PVOID Address,
+   ULONG_PTR Length)
 {
-   PLIST_ENTRY current_entry;
-   MEMORY_AREA* current;
-   ULONG Extent;
+   PMEMORY_AREA Node;
+   PVOID Extent = (PVOID)((ULONG_PTR)Address + Length);
 
-   DPRINT("MmOpenMemoryByRegion(AddressSpace %x, Address %x, Length %x)\n",
-          AddressSpace, Address, Length);
+   MmVerifyMemoryAreas(AddressSpace);
 
-   current_entry = AddressSpace->MAreaListHead.Flink;
-   while (current_entry != &AddressSpace->MAreaListHead)
+   /* Special case for empty tree. */
+   if (AddressSpace->MemoryAreaRoot == NULL)
+      return NULL;
+
+   /* Traverse the tree from left to right. */
+   for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
+        Node != NULL;
+        Node = MmIterateNextNode(Node))
    {
-      current = CONTAINING_RECORD(current_entry,
-                                  MEMORY_AREA,
-                                  Entry);
-      DPRINT("current->BaseAddress %x current->Length %x\n",
-             current->BaseAddress,current->Length);
-      if (current->BaseAddress >= Address &&
-            current->BaseAddress < (PVOID)((char*)Address+Length))
+      if (Node->StartingAddress >= Address &&
+          Node->StartingAddress < Extent)
       {
-         DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
-                current);
-         return(current);
+         DPRINT("MmOpenMemoryAreaByRegion(%x - %x): %x - %x\n",
+                Address, Address + Length, Node->StartingAddress,
+                Node->EndingAddress);
+         return Node;
       }
-      Extent = (ULONG)current->BaseAddress + current->Length;
-      if (Extent > (ULONG)Address &&
-            Extent < (ULONG)((char*)Address+Length))
+      if (Node->EndingAddress > Address &&
+          Node->EndingAddress < Extent)
       {
-         DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
-                current);
-         return(current);
+         DPRINT("MmOpenMemoryAreaByRegion(%x - %x): %x - %x\n",
+                Address, Address + Length, Node->StartingAddress,
+                Node->EndingAddress);
+         return Node;
       }
-      if (current->BaseAddress <= Address &&
-            Extent >= (ULONG)((char*)Address+Length))
+      if (Node->StartingAddress <= Address &&
+          Node->EndingAddress >= Extent)
       {
-         DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
-                current);
-         return(current);
+         DPRINT("MmOpenMemoryAreaByRegion(%x - %x): %x - %x\n",
+                Address, Address + Length, Node->StartingAddress,
+                Node->EndingAddress);
+         return Node;
       }
-      if (current->BaseAddress >= (PVOID)((char*)Address+Length))
+      if (Node->StartingAddress >= Extent)
       {
-         DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0);
-         return(NULL);
+         DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n");
+         return NULL;
       }
-      current_entry = current_entry->Flink;
    }
-   DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n",0);
-   return(NULL);
+
+   return NULL;
 }
 
-static VOID MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace,
-                               MEMORY_AREA* marea)
+static VOID
+MmInsertMemoryArea(
+   PMADDRESS_SPACE AddressSpace,
+   PMEMORY_AREA marea)
 {
-   PLIST_ENTRY ListHead;
-   PLIST_ENTRY current_entry;
-   PLIST_ENTRY inserted_entry = &marea->Entry;
-   MEMORY_AREA* current;
-   MEMORY_AREA* next;
+   PMEMORY_AREA Node;
+   PMEMORY_AREA PreviousNode;
 
-   DPRINT("MmInsertMemoryArea(marea %x)\n", marea);
-   DPRINT("marea->BaseAddress %x\n", marea->BaseAddress);
-   DPRINT("marea->Length %x\n", marea->Length);
+   MmVerifyMemoryAreas(AddressSpace);
 
-   ListHead = &AddressSpace->MAreaListHead;
-
-   current_entry = ListHead->Flink;
-   if (IsListEmpty(ListHead))
+   if (AddressSpace->MemoryAreaRoot == NULL)
    {
-      InsertHeadList(ListHead,&marea->Entry);
+      AddressSpace->MemoryAreaRoot = marea;
+      marea->LeftChild = marea->RightChild = marea->Parent = NULL;
       return;
    }
-   current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
-   if (current->BaseAddress > marea->BaseAddress)
+
+   Node = AddressSpace->MemoryAreaRoot;
+   do
    {
-      InsertHeadList(ListHead,&marea->Entry);
-      return;
+      DPRINT("marea->EndingAddress: %x Node->StartingAddress: %x\n",
+             marea->EndingAddress, Node->StartingAddress);
+      DPRINT("marea->StartingAddress: %x Node->EndingAddress: %x\n",
+             marea->StartingAddress, Node->EndingAddress);
+      ASSERT(marea->EndingAddress <= Node->StartingAddress ||
+             marea->StartingAddress >= Node->EndingAddress);
+      PreviousNode = Node;
+      if (marea->StartingAddress < Node->StartingAddress)
+         Node = Node->LeftChild;
+      else
+         Node = Node->RightChild;
    }
-   while (current_entry->Flink!=ListHead)
-   {
-      current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
-      next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
-      if (current->BaseAddress < marea->BaseAddress &&
-            current->Entry.Flink==ListHead)
-      {
-         current_entry->Flink = inserted_entry;
-         inserted_entry->Flink=ListHead;
-         inserted_entry->Blink=current_entry;
-         ListHead->Blink = inserted_entry;
-         return;
-      }
-      if (current->BaseAddress < marea->BaseAddress &&
-            next->BaseAddress > marea->BaseAddress)
-      {
-         inserted_entry->Flink = current_entry->Flink;
-         inserted_entry->Blink = current_entry;
-         inserted_entry->Flink->Blink = inserted_entry;
-         current_entry->Flink=inserted_entry;
-         return;
-      }
-      current_entry = current_entry->Flink;
-   }
-   InsertTailList(ListHead,inserted_entry);
+   while (Node != NULL);
+
+   marea->LeftChild = marea->RightChild = NULL;
+   marea->Parent = PreviousNode;
+   if (marea->StartingAddress < PreviousNode->StartingAddress)
+      PreviousNode->LeftChild = marea;
+   else
+      PreviousNode->RightChild = marea;
 }
 
-static PVOID MmFindGapBottomUp(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity)
+static PVOID
+MmFindGapBottomUp(
+   PMADDRESS_SPACE AddressSpace,
+   ULONG_PTR Length,
+   ULONG_PTR Granularity)
 {
-   PLIST_ENTRY ListHead;
-   PLIST_ENTRY current_entry;
-   MEMORY_AREA* current;
-   MEMORY_AREA* next;
-   ULONG Gap;
-   PVOID Address;
+   PVOID HighestAddress = AddressSpace->LowestAddress < (PVOID)KERNEL_BASE ?
+                          (PVOID)KERNEL_BASE : (PVOID)MAXULONG_PTR;
+   PVOID AlignedAddress;
+   PMEMORY_AREA Node;
+   PMEMORY_AREA FirstNode;
+   PMEMORY_AREA PreviousNode;
 
-   DPRINT("MmFindGapBottomUp(Length %x)\n",Length);
+   MmVerifyMemoryAreas(AddressSpace);
 
-#ifdef DBG
-   Length += PAGE_SIZE; /* For a guard page following the area */
-#endif
+   DPRINT("LowestAddress: %x HighestAddress: %x\n",
+          AddressSpace->LowestAddress, HighestAddress);
 
-   ListHead = &AddressSpace->MAreaListHead;
+   AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity);
 
-   current_entry = ListHead->Flink;
-   while (current_entry->Flink!=ListHead)
+   /* Special case for empty tree. */
+   if (AddressSpace->MemoryAreaRoot == NULL)
    {
-      current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
-      next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
-      Address = (PVOID) ((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length));
-#ifdef DBG
-      Address = (PVOID) ((char *) Address + PAGE_SIZE); /* For a guard page preceding the area */
-#endif
-      Address = (PVOID) MM_ROUND_UP(Address, Granularity);
-      if (Address < next->BaseAddress)
+      if (HighestAddress - AlignedAddress >= Length)
       {
-         Gap = (char*)next->BaseAddress - ((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length));
-         if (Gap >= Length)
-         {
-            return Address;
-         }
+         DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress);
+         return AlignedAddress;
       }
-      current_entry = current_entry->Flink;
+      DPRINT("MmFindGapBottomUp: 0\n");
+      return 0;
    }
 
-   if (current_entry == ListHead)
+   /* Go to the node with lowest address in the tree. */
+   FirstNode = Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
+
+   /* Traverse the tree from left to right. */
+   PreviousNode = Node;
+   for (;;)
    {
-      Address = (PVOID) MM_ROUND_UP(AddressSpace->LowestAddress, Granularity);
+      Node = MmIterateNextNode(Node);
+      if (Node == NULL)
+         break;
+
+      AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity);
+      if (Node->StartingAddress > AlignedAddress &&
+          Node->StartingAddress - AlignedAddress >= Length)
+      {
+         DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress);
+         return AlignedAddress;
+      }
+
+      PreviousNode = Node;
    }
-   else
+
+   /* Check if there is enough space after the last memory area. */
+   AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity);
+   if (HighestAddress - AlignedAddress >= Length)
    {
-      current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
-      Address = (char*)current->BaseAddress + PAGE_ROUND_UP(current->Length);
-#ifdef DBG
-      Address = (PVOID) ((char *) Address + PAGE_SIZE); /* For a guard page preceding the area */
-#endif
-      Address = (PVOID) MM_ROUND_UP(Address, Granularity);
+      DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress);
+      return AlignedAddress;
    }
-   /* Check if enough space for the block */
-   if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE)
+
+   /* Check if there is enough space before the first memory area. */
+   AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity);
+   if (FirstNode->StartingAddress > AlignedAddress &&
+       FirstNode->StartingAddress - AlignedAddress >= Length)
    {
-      if ((ULONG_PTR) Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG_PTR) Address)
-      {
-         DPRINT1("Failed to find gap\n");
-         return NULL;
-      }
+      DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress);
+      return AlignedAddress;
    }
-   else
-   {
-      if (Length >= ~ ((ULONG_PTR) 0) - (ULONG_PTR) Address)
-      {
-         DPRINT1("Failed to find gap\n");
-         return NULL;
-      }
-   }
-   return Address;
+
+   DPRINT("MmFindGapBottomUp: 0\n");
+   return 0;
 }
 
 
-static PVOID MmFindGapTopDown(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity)
+static PVOID
+MmFindGapTopDown(
+   PMADDRESS_SPACE AddressSpace,
+   ULONG_PTR Length,
+   ULONG_PTR Granularity)
 {
-   PLIST_ENTRY ListHead;
-   PLIST_ENTRY current_entry;
-   MEMORY_AREA* current;
-   ULONG Gap;
-   PVOID Address;
-   PVOID TopAddress;
-   PVOID BottomAddress;
-   PVOID HighestAddress;
+   PVOID HighestAddress = AddressSpace->LowestAddress < (PVOID)KERNEL_BASE ?
+                          (PVOID)KERNEL_BASE : (PVOID)MAXULONG_PTR;
+   PVOID AlignedAddress;
+   PMEMORY_AREA Node;
+   PMEMORY_AREA PreviousNode;
 
-   DPRINT("MmFindGapTopDown(Length %lx)\n",Length);
+   MmVerifyMemoryAreas(AddressSpace);
 
-#ifdef DBG
-   Length += PAGE_SIZE; /* For a guard page following the area */
-#endif
+   DPRINT("LowestAddress: %x HighestAddress: %x\n",
+          AddressSpace->LowestAddress, HighestAddress);
 
-   if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE) //(ULONG_PTR)MmSystemRangeStart)
-   {
-      HighestAddress = MmHighestUserAddress;
-   }
-   else
-   {
-      HighestAddress = (PVOID)0xFFFFFFFF;
-   }
+   AlignedAddress = MM_ROUND_DOWN(HighestAddress - Length + 1, Granularity);
 
-   TopAddress = HighestAddress;
+   /* Check for overflow. */
+   if (AlignedAddress > HighestAddress)
+      return NULL;
 
-   ListHead = &AddressSpace->MAreaListHead;
-   current_entry = ListHead->Blink;
-   while (current_entry->Blink != ListHead)
+   /* Special case for empty tree. */
+   if (AddressSpace->MemoryAreaRoot == NULL)
    {
-      current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
-      BottomAddress = (char*)current->BaseAddress + PAGE_ROUND_UP(current->Length);
-#ifdef DBG
-      BottomAddress = (PVOID) ((char *) BottomAddress + PAGE_SIZE); /* For a guard page preceding the area */
-#endif
-      BottomAddress = (PVOID) MM_ROUND_UP(BottomAddress, Granularity);
-      DPRINT("Base %p  Length %lx\n", current->BaseAddress, PAGE_ROUND_UP(current->Length));
-
-      if (BottomAddress < TopAddress && BottomAddress < HighestAddress)
+      if (AlignedAddress >= (PVOID)AddressSpace->LowestAddress)
       {
-         Gap = (char*)TopAddress - (char*) BottomAddress + 1;
-         DPRINT("Bottom %p  Top %p  Gap %lx\n", BottomAddress, TopAddress, Gap);
-         if (Gap >= Length)
-         {
-            DPRINT("Found gap at %p\n", (char*) TopAddress - Length);
-            return (PVOID) MM_ROUND_DOWN((char*) TopAddress - Length + 1, Granularity);
-         }
+         DPRINT("MmFindGapTopDown: %x\n", AlignedAddress);
+         return AlignedAddress;
       }
-      TopAddress = (char*)current->BaseAddress - 1;
-      current_entry = current_entry->Blink;
+      DPRINT("MmFindGapTopDown: 0\n");
+      return 0;
    }
 
-   if (current_entry == ListHead)
+   /* Go to the node with lowest address in the tree. */
+   Node = MmIterateLastNode(AddressSpace->MemoryAreaRoot);
+
+   /* Check if there is enough space after the last memory area. */
+   if (Node->EndingAddress <= AlignedAddress)
    {
-      Address = (PVOID) MM_ROUND_DOWN((char*) HighestAddress - Length + 1, Granularity);
+      DPRINT("MmFindGapTopDown: %x\n", AlignedAddress);
+      return AlignedAddress;
    }
-   else
+
+   /* Traverse the tree from left to right. */
+   PreviousNode = Node;
+   for (;;)
    {
-      Address = (PVOID) MM_ROUND_DOWN((char*)TopAddress - Length + 1, Granularity);
-   }
+      Node = MmIteratePrevNode(Node);
+      if (Node == NULL)
+         break;
 
-   /* Check if enough space for the block */
-   if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE)
-   {
-      if ((ULONG_PTR) Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG_PTR) Address)
+      AlignedAddress = MM_ROUND_DOWN(PreviousNode->StartingAddress - Length + 1, Granularity);
+
+      /* Check for overflow. */
+      if (AlignedAddress > PreviousNode->StartingAddress)
+         return NULL;
+      
+      if (Node->EndingAddress <= AlignedAddress)
       {
-         DPRINT1("Failed to find gap\n");
-         return NULL;
+         DPRINT("MmFindGapTopDown: %x\n", AlignedAddress);
+         return AlignedAddress;
       }
+
+      PreviousNode = Node;
    }
-   else
+
+   AlignedAddress = MM_ROUND_DOWN(PreviousNode->StartingAddress - Length + 1, Granularity);
+
+   /* Check for overflow. */
+   if (AlignedAddress > PreviousNode->StartingAddress)
+      return NULL;
+
+   if (AlignedAddress >= (PVOID)AddressSpace->LowestAddress)
    {
-      if (Length >= ~ ((ULONG_PTR) 0) - (ULONG_PTR) Address)
-      {
-         DPRINT1("Failed to find gap\n");
-         return NULL;
-      }
+      DPRINT("MmFindGapTopDown: %x\n", AlignedAddress);
+      return AlignedAddress;
    }
 
-   DPRINT("Found gap at %p\n", Address);
-   return Address;
+   DPRINT("MmFindGapTopDown: 0\n");
+   return 0;
 }
 
 
-PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity, BOOL TopDown)
+PVOID STDCALL
+MmFindGap(
+   PMADDRESS_SPACE AddressSpace,
+   ULONG_PTR Length,
+   ULONG_PTR Granularity,
+   BOOLEAN TopDown)
 {
    if (TopDown)
       return MmFindGapTopDown(AddressSpace, Length, Granularity);
@@ -367,13 +501,20 @@
    return MmFindGapBottomUp(AddressSpace, Length, Granularity);
 }
 
-ULONG MmFindGapAtAddress(PMADDRESS_SPACE AddressSpace, PVOID Address)
+ULONG_PTR STDCALL
+MmFindGapAtAddress(
+   PMADDRESS_SPACE AddressSpace,
+   PVOID Address)
 {
-   PLIST_ENTRY current_entry, ListHead;
-   PMEMORY_AREA current;
+   PMEMORY_AREA Node = AddressSpace->MemoryAreaRoot;
+   PMEMORY_AREA RightNeighbour = NULL;
+   PVOID HighestAddress = AddressSpace->LowestAddress < (PVOID)KERNEL_BASE ?
+                          (PVOID)KERNEL_BASE : (PVOID)MAXULONG_PTR;
 
-   Address = (PVOID)PAGE_ROUND_DOWN(Address);
+   MmVerifyMemoryAreas(AddressSpace);
 
+   Address = MM_ROUND_DOWN(Address, PAGE_SIZE);
+
    if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE)
    {
       if (Address >= (PVOID)KERNEL_BASE)
@@ -383,159 +524,255 @@
    }
    else
    {
-      if ((ULONG_PTR)Address < (ULONG_PTR)AddressSpace->LowestAddress)
+      if (Address < AddressSpace->LowestAddress)
       {
          return 0;
       }
    }
 
-   ListHead = &AddressSpace->MAreaListHead;
-
-   current_entry = ListHead->Flink;
-   while (current_entry != ListHead)
+   while (Node != NULL)
    {
-      current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
-      if (current->BaseAddress <= Address && (char*)Address < (char*)current->BaseAddress + current->Length)
+      if (Address < Node->StartingAddress)
       {
-         return 0;
+         RightNeighbour = Node;
+         Node = Node->LeftChild;
       }
-      else if (current->BaseAddress > Address)
+      else if (Address >= Node->EndingAddress)
       {
-         return (ULONG_PTR)current->BaseAddress - (ULONG_PTR)Address;
+         Node = Node->RightChild;
       }
-      current_entry = current_entry->Flink;
+      else
+      {
+         DPRINT("MmFindGapAtAddress: 0\n");
+         return 0;
+      }
    }
-   if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE)
+
+   if (RightNeighbour)
    {
-      return KERNEL_BASE - (ULONG_PTR)Address;
+      DPRINT("MmFindGapAtAddress: %x [%x]\n", Address, RightNeighbour->StartingAddress - Address);
+      return RightNeighbour->StartingAddress - Address;
    }
    else
    {
-      return 0 - (ULONG_PTR)Address;
+      DPRINT("MmFindGapAtAddress: %x [%x]\n", Address, HighestAddress - Address);
+      return HighestAddress - Address;
    }
 }
 
+/**
+ * @name MmInitMemoryAreas
+ *
+ * Initialize the memory area list implementation.
+ */
+
 NTSTATUS INIT_FUNCTION
 MmInitMemoryAreas(VOID)
-/*
- * FUNCTION: Initialize the memory area list
- */
 {
    DPRINT("MmInitMemoryAreas()\n",0);
    return(STATUS_SUCCESS);
 }
 
-NTSTATUS
-MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
-                 PVOID BaseAddress,
-                 ULONG Length,
-                 VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea,
-                                  PVOID Address, PFN_TYPE Page,
-                                  SWAPENTRY SwapEntry, BOOLEAN Dirty),
-                 PVOID FreePageContext)
+
+NTSTATUS STDCALL
+MmFreeMemoryArea(
+   PMADDRESS_SPACE AddressSpace,
+   PMEMORY_AREA MemoryArea,
+   PMM_FREE_PAGE_FUNC FreePage,
+   PVOID FreePageContext)
 {
-   MEMORY_AREA* MemoryArea;
-   char* Address;
-   char* EndAddress;
+   PMEMORY_AREA *ParentReplace;
+   PVOID Address;
+   PVOID EndAddress;
    PEPROCESS CurrentProcess = PsGetCurrentProcess();
 
-   DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, Length %x,"
-          "FreePageContext %d)\n",AddressSpace,BaseAddress,Length,
-          FreePageContext);
-
-   MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
-                                          BaseAddress);
-   if (MemoryArea == NULL)
-   {
-      KEBUGCHECK(0);
-      return(STATUS_UNSUCCESSFUL);
-   }
    if (AddressSpace->Process != NULL &&
-         AddressSpace->Process != CurrentProcess)
+       AddressSpace->Process != CurrentProcess)
    {
       KeAttachProcess(&AddressSpace->Process->Pcb);
    }
-   EndAddress = (char*)MemoryArea->BaseAddress + PAGE_ROUND_UP(MemoryArea->Length); 
-   for (Address = MemoryArea->BaseAddress; Address < EndAddress; Address += PAGE_SIZE)
+
+   EndAddress = MM_ROUND_UP(MemoryArea->EndingAddress, PAGE_SIZE); 
+   for (Address = MemoryArea->StartingAddress; Address < EndAddress; Address += PAGE_SIZE)
    {
-
       if (MemoryArea->Type == MEMORY_AREA_IO_MAPPING)
       {
-         MmRawDeleteVirtualMapping(Address);
+         MmRawDeleteVirtualMapping((PVOID)Address);
       }
       else
       {
-	 BOOL Dirty = FALSE;
+         BOOL Dirty = FALSE;
          SWAPENTRY SwapEntry = 0;
-	 PFN_TYPE Page = 0;
+         PFN_TYPE Page = 0;
 
-
-         if (MmIsPageSwapEntry(AddressSpace->Process, Address))
+         if (MmIsPageSwapEntry(AddressSpace->Process, (PVOID)Address))
          {
-            MmDeletePageFileMapping(AddressSpace->Process, Address, &SwapEntry);
+            MmDeletePageFileMapping(AddressSpace->Process, (PVOID)Address, &SwapEntry);
          }
          else
          {
-            MmDeleteVirtualMapping(AddressSpace->Process, Address, FALSE, &Dirty, &Page);
+            MmDeleteVirtualMapping(AddressSpace->Process, (PVOID)Address, FALSE, &Dirty, &Page);
          }
          if (FreePage != NULL)
          {
-            FreePage(FreePageContext, MemoryArea, Address, 
-		     Page, SwapEntry, (BOOLEAN)Dirty);
+            FreePage(FreePageContext, MemoryArea, (PVOID)Address,
+                     Page, SwapEntry, (BOOLEAN)Dirty);
          }
       }
    }
+
    if (AddressSpace->Process != NULL &&
-         AddressSpace->Process != CurrentProcess)
+       AddressSpace->Process != CurrentProcess)
    {
       KeDetachProcess();
    }
-   RemoveEntryList(&MemoryArea->Entry);
+
+   /* Remove the tree item. */ 
+   {
+      if (MemoryArea->Parent != NULL)
+      {
+         if (MemoryArea->Parent->LeftChild == MemoryArea)
+            ParentReplace = &MemoryArea->Parent->LeftChild;
+         else
+            ParentReplace = &MemoryArea->Parent->RightChild;
+      }
+      else
+         ParentReplace = &AddressSpace->MemoryAreaRoot;
+
+      if (MemoryArea->RightChild == NULL)
+      {
+         *ParentReplace = MemoryArea->LeftChild;
+         if (MemoryArea->LeftChild)
+            MemoryArea->LeftChild->Parent = MemoryArea->Parent;
+      }
+      else
+      {
+         if (MemoryArea->RightChild->LeftChild == NULL)
+         {
+            MemoryArea->RightChild->LeftChild = MemoryArea->LeftChild;
+            if (MemoryArea->LeftChild)
+               MemoryArea->LeftChild->Parent = MemoryArea->RightChild;
+
+            *ParentReplace = MemoryArea->RightChild;
+            MemoryArea->RightChild->Parent = MemoryArea->Parent;
+         }
+         else
+         {
+            PMEMORY_AREA LowestNode;
+
+            LowestNode = MemoryArea->RightChild->LeftChild;
+            while (LowestNode->LeftChild != NULL)
+               LowestNode = LowestNode->LeftChild;
+
+            LowestNode->Parent->LeftChild = LowestNode->RightChild;
+            if (LowestNode->RightChild)
+               LowestNode->RightChild->Parent = LowestNode->Parent;
+
+            LowestNode->LeftChild = MemoryArea->LeftChild;
+            if (MemoryArea->LeftChild)
+               MemoryArea->LeftChild->Parent = LowestNode;
+
+            LowestNode->RightChild = MemoryArea->RightChild;
+            MemoryArea->RightChild->Parent = LowestNode;
+
+            *ParentReplace = LowestNode;
+            LowestNode->Parent = MemoryArea->Parent;
+         }
+      }
+   }
+
    ExFreePool(MemoryArea);
 
-   DPRINT("MmFreeMemoryArea() succeeded\n");
+   DPRINT("MmFreeMemoryAreaByNode() succeeded\n");
 
-   return(STATUS_SUCCESS);
+   return STATUS_SUCCESS;
 }
 
-NTSTATUS MmCreateMemoryArea(PEPROCESS Process,
-                            PMADDRESS_SPACE AddressSpace,
-                            ULONG Type,
-                            PVOID* BaseAddress,
-                            ULONG Length,
-                            ULONG Attributes,
-                            MEMORY_AREA** Result,
-                            BOOL FixedAddress,
-                            BOOL TopDown,
-                            PHYSICAL_ADDRESS BoundaryAddressMultiple)
+
+NTSTATUS STDCALL
+MmFreeMemoryAreaByPtr(
+   PMADDRESS_SPACE AddressSpace,
+   PVOID BaseAddress,
+   PMM_FREE_PAGE_FUNC FreePage,
+   PVOID FreePageContext)
+{
+   PMEMORY_AREA MemoryArea;
+
+   DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, Length %x,"
+          "FreePageContext %d)\n",AddressSpace,BaseAddress,Length,
+          FreePageContext);
+
+   MmVerifyMemoryAreas(AddressSpace);
+
+   MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
+                                          BaseAddress);
+   if (MemoryArea == NULL)
+   {
+      KEBUGCHECK(0);
+      return(STATUS_UNSUCCESSFUL);
+   }
+
+   return MmFreeMemoryArea(AddressSpace, MemoryArea, FreePage, FreePageContext);
+}
+
 /*
- * FUNCTION: Create a memory area
- * ARGUMENTS:
- *     AddressSpace = Address space to create the area in
- *     Type = Type of the address space
- *     BaseAddress = 
- *     Length = Length to allocate
- *     Attributes = Protection attributes for the memory area
- *     Result = Receives a pointer to the memory area on exit
- * RETURNS: Status
- * NOTES: Lock the address space before calling this function
+ * @name MmCreateMemoryArea
+ *
+ * Create a memory area.
+ *
+ * @param AddressSpace 
+ *        Address space to create the area in.
+ * @param Type
+ *        Type of the memory area.
+ * @param BaseAddress
+ *        Base address for the memory area we're about the create. On
+ *        input it contains either 0 (auto-assign address) or preferred
+ *        address. On output it contains the starting address of the
+ *        newly created area.
+ * @param Length
+ *        Length of the area to allocate.
+ * @param Attributes
+ *        Protection attributes for the memory area.
+ * @param Result
+ *        Receives a pointer to the memory area on successful exit.
+ *
+ * @return Status
+ *
+ * @remarks Lock the address space before calling this function.
  */
+
+NTSTATUS STDCALL
+MmCreateMemoryArea(PEPROCESS Process,
+                   PMADDRESS_SPACE AddressSpace,
+                   ULONG Type,
+                   PVOID *BaseAddress,
+                   ULONG_PTR Length,
+                   ULONG Attributes,
+                   PMEMORY_AREA *Result,
+                   BOOLEAN FixedAddress,
+                   BOOLEAN TopDown,
+                   PHYSICAL_ADDRESS BoundaryAddressMultiple)
 {
    PVOID EndAddress;
    ULONG Granularity;
    ULONG tmpLength;
-   DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x,"
-          "*BaseAddress %x, Length %x, Attributes %x, Result %x)\n",
-          Type,BaseAddress,*BaseAddress,Length,Attributes,Result);
 
+   DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x, "
+          "*BaseAddress %x, Length %x, Attributes %x, TopDown: %x, "
+          "FixedAddress %x, Result %x)\n",
+          Type, BaseAddress, *BaseAddress, Length, Attributes, TopDown,
+          FixedAddress, Result);
+
+   MmVerifyMemoryAreas(AddressSpace);
+
    Granularity = (MEMORY_AREA_VIRTUAL_MEMORY == Type ? MM_VIRTMEM_GRANULARITY : PAGE_SIZE);
    if ((*BaseAddress) == 0 && !FixedAddress)
    {
       tmpLength = PAGE_ROUND_UP(Length);
       *BaseAddress = MmFindGap(AddressSpace,
-                               PAGE_ROUND_UP(Length),
+                               tmpLength,
                                Granularity,
-                               TopDown);
+                               TopDown != 0);
       if ((*BaseAddress) == 0)
       {
          DPRINT("No suitable gap\n");
@@ -544,26 +781,28 @@
    }
    else
    {
-      tmpLength =  Length + ((ULONG_PTR) *BaseAddress
-                             - (ULONG_PTR) MM_ROUND_DOWN(*BaseAddress, Granularity));
+      tmpLength = Length + ((ULONG_PTR) *BaseAddress
+                         - (ULONG_PTR) MM_ROUND_DOWN(*BaseAddress, Granularity));
       *BaseAddress = MM_ROUND_DOWN(*BaseAddress, Granularity);
 
       if (AddressSpace->LowestAddress == (PVOID)KERNEL_BASE &&
-            (*BaseAddress) < (PVOID)KERNEL_BASE)
+          *BaseAddress < (PVOID)KERNEL_BASE)
       {
+         CHECKPOINT;
          return STATUS_ACCESS_VIOLATION;
       }
 
       if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE &&
-            (PVOID)((char*)(*BaseAddress) + tmpLength) > (PVOID)KERNEL_BASE)
+          (ULONG_PTR)(*BaseAddress) + tmpLength > KERNEL_BASE)
       {
+         CHECKPOINT;
          return STATUS_ACCESS_VIOLATION;
       }
 
       if (BoundaryAddressMultiple.QuadPart != 0)
       {
          EndAddress = ((char*)(*BaseAddress)) + tmpLength-1;
-         ASSERT(((DWORD_PTR)*BaseAddress/BoundaryAddressMultiple.QuadPart) == ((DWORD_PTR)EndAddress/BoundaryAddressMultiple.QuadPart));
+         ASSERT(((ULONG_PTR)*BaseAddress/BoundaryAddressMultiple.QuadPart) == ((DWORD_PTR)EndAddress/BoundaryAddressMultiple.QuadPart));
       }
 
       if (MmOpenMemoryAreaByRegion(AddressSpace,
@@ -579,8 +818,8 @@
                                    TAG_MAREA);
    RtlZeroMemory(*Result,sizeof(MEMORY_AREA));
    (*Result)->Type = Type;
-   (*Result)->BaseAddress = *BaseAddress;
-   (*Result)->Length = tmpLength;
+   (*Result)->StartingAddress = *BaseAddress;
+   (*Result)->EndingAddress = *BaseAddress + tmpLength;
    (*Result)->Attributes = Attributes;
    (*Result)->LockCount = 0;
    (*Result)->Process = Process;
@@ -589,38 +828,40 @@
 
    MmInsertMemoryArea(AddressSpace, *Result);
 
-   DPRINT("MmCreateMemoryArea() succeeded\n");
+   DPRINT("MmCreateMemoryArea() succeeded (%x)\n", *BaseAddress);
    return STATUS_SUCCESS;
 }
 
 
-void
+VOID STDCALL
 MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process,
                                  PMADDRESS_SPACE AddressSpace,
                                  PVOID BaseAddress)
 {
-  PMEMORY_AREA MemoryArea;
-  PLIST_ENTRY Entry;
-  PMM_REGION Region;
-  BOOLEAN Reserved;
+   PMEMORY_AREA MemoryArea;
+   PLIST_ENTRY Entry;
+   PMM_REGION Region;
+   BOOLEAN Reserved;
   
-  MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, BaseAddress);
-  if (NULL != MemoryArea)
-    {
+   MmVerifyMemoryAreas(AddressSpace);
+
+   MemoryArea = MmOpenMemoryAreaByAddress(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;
-        }
+      {
+         Region = CONTAINING_RECORD(Entry, MM_REGION, RegionListEntry);
+         Reserved = (MEM_RESERVE == Region->Type);
+         Entry = Entry->Flink;
+      }
 
       if (Reserved)
-        {
-          MmFreeVirtualMemory(Process, MemoryArea);
-        }
-    }
+      {
+         MmFreeVirtualMemory(Process, MemoryArea);
+      }
+   }
 }
 
 /* EOF */
Index: mm/virtual.c
===================================================================
--- mm/virtual.c	(revision 12712)
+++ mm/virtual.c	(working copy)
@@ -204,9 +204,10 @@
                      Info->State = MEM_FREE;
 	             Info->Protect = MemoryArea->Attributes;
 		     Info->AllocationProtect = MemoryArea->Attributes;
-                     Info->BaseAddress = MemoryArea->BaseAddress;
-	             Info->AllocationBase = MemoryArea->BaseAddress;
-	             Info->RegionSize = MemoryArea->Length;
+	             Info->BaseAddress = MemoryArea->StartingAddress;
+	             Info->AllocationBase = MemoryArea->StartingAddress;
+	             Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress - 
+	                                (ULONG_PTR)MemoryArea->StartingAddress;
                      Status = STATUS_SUCCESS;
                      *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
 	             break;
@@ -215,9 +216,10 @@
                      Info->State = MEM_COMMIT;
 	             Info->Protect = MemoryArea->Attributes;
 		     Info->AllocationProtect = MemoryArea->Attributes;
-                     Info->BaseAddress = MemoryArea->BaseAddress;
-	             Info->AllocationBase = MemoryArea->BaseAddress;
-	             Info->RegionSize = MemoryArea->Length;
+	             Info->BaseAddress = MemoryArea->StartingAddress;
+	             Info->AllocationBase = MemoryArea->StartingAddress;
+	             Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress - 
+	                                (ULONG_PTR)MemoryArea->StartingAddress;
                      Status = STATUS_SUCCESS;
                      *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
 		     break;
@@ -235,9 +237,10 @@
                      Info->State = MEM_COMMIT;
 	             Info->Protect = MemoryArea->Attributes;
 		     Info->AllocationProtect = MemoryArea->Attributes;
-                     Info->BaseAddress = MemoryArea->BaseAddress;
-	             Info->AllocationBase = MemoryArea->BaseAddress;
-	             Info->RegionSize = MemoryArea->Length;
+	             Info->BaseAddress = MemoryArea->StartingAddress;
+	             Info->AllocationBase = MemoryArea->StartingAddress;
+	             Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress - 
+	                                (ULONG_PTR)MemoryArea->StartingAddress;
                      Status = STATUS_SUCCESS;
                      *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
 		     break;
@@ -255,9 +258,10 @@
                      Info->State = MEM_COMMIT;
 	             Info->Protect = MemoryArea->Attributes;
 		     Info->AllocationProtect = MemoryArea->Attributes;
-                     Info->BaseAddress = MemoryArea->BaseAddress;
-	             Info->AllocationBase = MemoryArea->BaseAddress;
-	             Info->RegionSize = MemoryArea->Length;
+	             Info->BaseAddress = MemoryArea->StartingAddress;
+	             Info->AllocationBase = MemoryArea->StartingAddress;
+	             Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress - 
+	                                (ULONG_PTR)MemoryArea->StartingAddress;
                      Status = STATUS_SUCCESS;
                      *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
 		     break;
Index: mm/anonmem.c
===================================================================
--- mm/anonmem.c	(revision 12712)
+++ mm/anonmem.c	(working copy)
@@ -261,7 +261,7 @@
    /*
     * Get the segment corresponding to the virtual address
     */
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.VirtualMemoryData.RegionListHead,
                          Address, NULL);
    if (Region->Type == MEM_RESERVE || Region->Protect == PAGE_NOACCESS)
@@ -525,6 +525,7 @@
 {
    PEPROCESS Process;
    MEMORY_AREA* MemoryArea;
+   ULONG_PTR MemoryAreaLength;
    ULONG Type;
    NTSTATUS Status;
    PMADDRESS_SPACE AddressSpace;
@@ -582,40 +583,44 @@
       MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
                                              BaseAddress);
 
-      if (MemoryArea != NULL &&
-            MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY &&
-            MemoryArea->Length >= RegionSize)
+      if (MemoryArea != NULL)
       {
-         Status =
-            MmAlterRegion(AddressSpace,
-                          MemoryArea->BaseAddress,
-                          &MemoryArea->Data.VirtualMemoryData.RegionListHead,
-                          BaseAddress, RegionSize,
-                          Type, Protect, MmModifyAttributes);
-         MmUnlockAddressSpace(AddressSpace);
-         ObDereferenceObject(Process);
-         DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
-         return(Status);
+         MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress -
+                            (ULONG_PTR)MemoryArea->StartingAddress;
+         if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY &&
+             MemoryAreaLength >= RegionSize)
+         {
+            Status =
+               MmAlterRegion(AddressSpace,
+                             MemoryArea->StartingAddress,
+                             &MemoryArea->Data.VirtualMemoryData.RegionListHead,
+                             BaseAddress, RegionSize,
+                             Type, Protect, MmModifyAttributes);
+            MmUnlockAddressSpace(AddressSpace);
+            ObDereferenceObject(Process);
+            DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
+            return(Status);
+         }
+         else if (MemoryAreaLength >= RegionSize)
+         {
+            Status =
+               MmAlterRegion(AddressSpace,
+                             MemoryArea->StartingAddress,
+                             &MemoryArea->Data.SectionData.RegionListHead,
+                             BaseAddress, RegionSize,
+                             Type, Protect, MmModifyAttributes);
+            MmUnlockAddressSpace(AddressSpace);
+            ObDereferenceObject(Process);
+            DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
+            return(Status);
+         }
+         else
+         {
+            MmUnlockAddressSpace(AddressSpace);
+            ObDereferenceObject(Process);
+            return(STATUS_UNSUCCESSFUL);
+         }
       }
-      else if (MemoryArea != NULL && MemoryArea->Length >= RegionSize)
-      {
-         Status =
-            MmAlterRegion(AddressSpace,
-                          MemoryArea->BaseAddress,
-                          &MemoryArea->Data.SectionData.RegionListHead,
-                          BaseAddress, RegionSize,
-                          Type, Protect, MmModifyAttributes);
-         MmUnlockAddressSpace(AddressSpace);
-         ObDereferenceObject(Process);
-         DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
-         return(Status);
-      }
-      else if (MemoryArea != NULL)
-      {
-         MmUnlockAddressSpace(AddressSpace);
-         ObDereferenceObject(Process);
-         return(STATUS_UNSUCCESSFUL);
-      }
    }
 
    Status = MmCreateMemoryArea(Process,
@@ -626,7 +631,7 @@
                                Protect,
                                &MemoryArea,
                                PBaseAddress != 0,
-                               (AllocationType & MEM_TOP_DOWN),
+                               (AllocationType & MEM_TOP_DOWN) == MEM_TOP_DOWN,
                                BoundaryAddressMultiple);
    if (!NT_SUCCESS(Status))
    {
@@ -635,18 +640,22 @@
       DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
       return(Status);
    }
+
+   MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress -
+                      (ULONG_PTR)MemoryArea->StartingAddress;
+   
    MmInitialiseRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
-                      MemoryArea->Length, Type, Protect);
+                      MemoryAreaLength, Type, Protect);
 
    if ((AllocationType & MEM_COMMIT) &&
          ((Protect & PAGE_READWRITE) ||
           (Protect & PAGE_EXECUTE_READWRITE)))
    {
-      MmReserveSwapPages(MemoryArea->Length);
+      MmReserveSwapPages(MemoryAreaLength);
    }
 
    *UBaseAddress = BaseAddress;
-   *URegionSize = MemoryArea->Length;
+   *URegionSize = MemoryAreaLength;
    DPRINT("*UBaseAddress %x  *URegionSize %x\n", BaseAddress, RegionSize);
 
    MmUnlockAddressSpace(AddressSpace);
@@ -702,7 +711,11 @@
     */
    if (MemoryArea->PageOpCount > 0)
    {
-      for (i = 0; i < PAGE_ROUND_UP(MemoryArea->Length) / PAGE_SIZE; i++)
+      ULONG_PTR MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress -
+                                   (ULONG_PTR)MemoryArea->StartingAddress;
+
+      /* FiN TODO: Optimize loop counter! */
+      for (i = 0; i < PAGE_ROUND_UP(MemoryAreaLength) / PAGE_SIZE; i++)
       {
          PMM_PAGEOP PageOp;
 
@@ -712,7 +725,7 @@
          }
 
          PageOp = MmCheckForPageOp(MemoryArea, Process->UniqueProcessId,
-                                   (char*)MemoryArea->BaseAddress + (i * PAGE_SIZE),
+                                   (PVOID)((ULONG_PTR)MemoryArea->StartingAddress + (i * PAGE_SIZE)),
                                    NULL, 0);
          if (PageOp != NULL)
          {
@@ -745,8 +758,7 @@
 
    /* Actually free the memory area. */
    MmFreeMemoryArea(&Process->AddressSpace,
-                    MemoryArea->BaseAddress,
-                    0,
+                    MemoryArea,
                     MmFreeVirtualMemoryPage,
                     (PVOID)Process);
 }
@@ -814,7 +826,7 @@
    {
       case MEM_RELEASE:
          /* We can only free a memory area in one step. */
-         if (MemoryArea->BaseAddress != BaseAddress ||
+         if (MemoryArea->StartingAddress != BaseAddress ||
              MemoryArea->Type != MEMORY_AREA_VIRTUAL_MEMORY)
          {
             MmUnlockAddressSpace(AddressSpace);
@@ -829,7 +841,7 @@
       case MEM_DECOMMIT:
          Status =
             MmAlterRegion(AddressSpace,
-                          MemoryArea->BaseAddress,
+                          MemoryArea->StartingAddress,
                           &MemoryArea->Data.VirtualMemoryData.RegionListHead,
                           BaseAddress,
                           RegionSize,
@@ -856,11 +868,11 @@
    PMM_REGION Region;
    NTSTATUS Status;
 
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.VirtualMemoryData.RegionListHead,
                          BaseAddress, NULL);
    *OldProtect = Region->Protect;
-   Status = MmAlterRegion(AddressSpace, MemoryArea->BaseAddress,
+   Status = MmAlterRegion(AddressSpace, MemoryArea->StartingAddress,
                           &MemoryArea->Data.VirtualMemoryData.RegionListHead,
                           BaseAddress, Length, Region->Type, Protect,
                           MmModifyAttributes);
@@ -878,11 +890,11 @@
 
    Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
 
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.VirtualMemoryData.RegionListHead,
                          Address, &RegionBase);
    Info->BaseAddress = RegionBase;
-   Info->AllocationBase = MemoryArea->BaseAddress;
+   Info->AllocationBase = MemoryArea->StartingAddress;
    Info->AllocationProtect = MemoryArea->Attributes;
    Info->RegionSize = (char*)RegionBase + Region->Length - (char*)Info->BaseAddress;
    Info->State = Region->Type;
Index: mm/rmap.c
===================================================================
--- mm/rmap.c	(revision 12712)
+++ mm/rmap.c	(working copy)
@@ -91,7 +91,7 @@
    }
    Process = entry->Process;
    Address = entry->Address;
-   if ((((ULONG)Address) & 0xFFF) != 0)
+   if ((((ULONG_PTR)Address) & 0xFFF) != 0)
    {
       KEBUGCHECK(0);
    }
@@ -131,7 +131,7 @@
    Type = MemoryArea->Type;
    if (Type == MEMORY_AREA_SECTION_VIEW)
    {
-      Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress);
+      Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
 
       /*
        * Get or create a pageop
@@ -220,7 +220,7 @@
    }
    Process = entry->Process;
    Address = entry->Address;
-   if ((((ULONG)Address) & 0xFFF) != 0)
+   if ((((ULONG_PTR)Address) & 0xFFF) != 0)
    {
       KEBUGCHECK(0);
    }
@@ -255,7 +255,7 @@
    Type = MemoryArea->Type;
    if (Type == MEMORY_AREA_SECTION_VIEW)
    {
-      Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress);
+      Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
 
       /*
        * Get or create a pageop
Index: mm/cont.c
===================================================================
--- mm/cont.c	(revision 12712)
+++ mm/cont.c	(working copy)
@@ -42,7 +42,7 @@
 {
    PMEMORY_AREA MArea;
    NTSTATUS Status;
-   PVOID BaseAddress = 0;
+   PVOID BaseAddress = NULL;
    PFN_TYPE PBase;
    ULONG Attributes;
    ULONG i;
@@ -83,8 +83,7 @@
    {
       MmLockAddressSpace(MmGetKernelAddressSpace());
       MmFreeMemoryArea(MmGetKernelAddressSpace(),
-                       BaseAddress,
-                       0,
+                       MArea,
                        NULL,
                        NULL);
       MmUnlockAddressSpace(MmGetKernelAddressSpace());
@@ -174,11 +173,10 @@
 MmFreeContiguousMemory(IN PVOID BaseAddress)
 {
    MmLockAddressSpace(MmGetKernelAddressSpace());
-   MmFreeMemoryArea(MmGetKernelAddressSpace(),
-                    BaseAddress,
-                    0,
-                    MmFreeContinuousPage,
-                    NULL);
+   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+                         BaseAddress,
+                         MmFreeContinuousPage,
+                         NULL);
    MmUnlockAddressSpace(MmGetKernelAddressSpace());
 }
 
@@ -260,11 +258,10 @@
                                    IN MEMORY_CACHING_TYPE CacheType)
 {
    MmLockAddressSpace(MmGetKernelAddressSpace());
-   MmFreeMemoryArea(MmGetKernelAddressSpace(),
-                    BaseAddress,
-                    NumberOfBytes,
-                    MmFreeContinuousPage,
-                    NULL);
+   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+                         BaseAddress,
+                         MmFreeContinuousPage,
+                         NULL);
    MmUnlockAddressSpace(MmGetKernelAddressSpace());
 }
 
Index: mm/iospace.c
===================================================================
--- mm/iospace.c	(revision 12712)
+++ mm/iospace.c	(working copy)
@@ -127,7 +127,7 @@
          KEBUGCHECK(0);
       }
    }
-   return ((PVOID)((char*)Result + Offset));
+   return (PVOID)((ULONG_PTR)Result + Offset);
 }
 
 
@@ -160,16 +160,17 @@
                 IN ULONG NumberOfBytes)
 {
    ULONG Offset;
-   Offset = (ULONG_PTR)BaseAddress % PAGE_SIZE;
-   BaseAddress = (PVOID)((PUCHAR)BaseAddress - Offset);
+   PVOID Address = BaseAddress;
+
+   Offset = (ULONG_PTR)Address % PAGE_SIZE;
+   Address -= Offset;
    NumberOfBytes += Offset;
 
    MmLockAddressSpace(MmGetKernelAddressSpace());
-   MmFreeMemoryArea(MmGetKernelAddressSpace(),
-                    BaseAddress,
-                    NumberOfBytes,
-                    NULL,
-                    NULL);
+   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+                         Address,
+                         NULL,
+                         NULL);
    MmUnlockAddressSpace(MmGetKernelAddressSpace());
 }
 
Index: mm/drvlck.c
===================================================================
--- mm/drvlck.c	(revision 12712)
+++ mm/drvlck.c	(working copy)
@@ -64,7 +64,7 @@
 MmLockPagableDataSection(IN PVOID AddressWithinSection)
 {
    PVOID Handle;
-   Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection);
+   Handle = MmOpenMemoryAreaByAddress(NULL, AddressWithinSection);
    MmLockPagableSectionByHandle(Handle);
    return(Handle);
 }
Index: mm/aspace.c
===================================================================
--- mm/aspace.c	(revision 12712)
+++ mm/aspace.c	(working copy)
@@ -68,7 +68,7 @@
 MmInitializeAddressSpace(PEPROCESS Process,
                          PMADDRESS_SPACE AddressSpace)
 {
-   InitializeListHead(&AddressSpace->MAreaListHead);
+   AddressSpace->MemoryAreaRoot = NULL;
    ExInitializeFastMutex(&AddressSpace->Lock);
    if (Process != NULL)
    {
Index: mm/mminit.c
===================================================================
--- mm/mminit.c	(revision 12712)
+++ mm/mminit.c	(working copy)
@@ -480,10 +480,9 @@
 MiFreeInitMemory(VOID)
 {
    MmLockAddressSpace(MmGetKernelAddressSpace());
-   MmFreeMemoryArea(MmGetKernelAddressSpace(),
-                    (PVOID)&_init_start__,
-                    PAGE_ROUND_UP((ULONG)&_init_end__) - (ULONG)&_init_start__,
-                    MiFreeInitMemoryPage,
-                    NULL);
+   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+                         (PVOID)&_init_start__,
+                         MiFreeInitMemoryPage,
+                         NULL);
    MmUnlockAddressSpace(MmGetKernelAddressSpace());
 }


More information about the Ros-dev mailing list