https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c4f736e8f4e05c214d74c…
commit c4f736e8f4e05c214d74c0751189f38305583be0
Author:     Thomas Faber <thomas.faber(a)reactos.org>
AuthorDate: Sun Feb 2 12:53:57 2020 +0100
Commit:     Thomas Faber <thomas.faber(a)reactos.org>
CommitDate: Sun Jun 14 09:10:31 2020 +0200
    [RTL] Add and populate LastEntryInSegment. CORE-14588
---
 sdk/lib/rtl/heap.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 sdk/lib/rtl/heap.h |  3 ++-
 2 files changed, 69 insertions(+), 2 deletions(-)
diff --git a/sdk/lib/rtl/heap.c b/sdk/lib/rtl/heap.c
index ad4f6a1513d..962d5b079b6 100644
--- a/sdk/lib/rtl/heap.c
+++ b/sdk/lib/rtl/heap.c
@@ -702,10 +702,12 @@ RtlpFindAndCommitPages(PHEAP Heap,
                 if(UcrDescriptor->Address == Segment->LastValidEntry)
                 {
                     FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
+                    Segment->LastEntryInSegment = FirstEntry;
                 }
                 else
                 {
                     FirstEntry->Flags = 0;
+                    Segment->LastEntryInSegment = Segment->FirstEntry;
                     /* Update field of next entry */
                     ASSERT((FirstEntry + FirstEntry->Size)->PreviousSize == 0);
                     (FirstEntry + FirstEntry->Size)->PreviousSize =
FirstEntry->Size;
@@ -720,6 +722,7 @@ RtlpFindAndCommitPages(PHEAP Heap,
             else
             {
                 FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
+                Segment->LastEntryInSegment = FirstEntry;
             }
             /* We're done */
@@ -841,6 +844,7 @@ RtlpDeCommitFreeBlock(PHEAP Heap,
         FreeEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
         FreeEntry->Size = (USHORT)PrecedingSize;
         Heap->TotalFreeSize += PrecedingSize;
+        Segment->LastEntryInSegment = FreeEntry;
         /* Insert it into the free list */
         RtlpInsertFreeBlockHelper(Heap, FreeEntry, PrecedingSize, FALSE);
@@ -849,6 +853,13 @@ RtlpDeCommitFreeBlock(PHEAP Heap,
     {
         /* Adjust preceding in use entry */
         PrecedingInUseEntry->Flags |= HEAP_ENTRY_LAST_ENTRY;
+        Segment->LastEntryInSegment = PrecedingInUseEntry;
+    }
+    else if ((ULONG_PTR)Segment->LastEntryInSegment >= DecommitBase &&
+             (ULONG_PTR)Segment->LastEntryInSegment < DecommitBase + DecommitSize)
+    {
+        /* Invalidate last entry */
+        Segment->LastEntryInSegment = Segment->FirstEntry;
     }
     /* Now the next one */
@@ -933,6 +944,9 @@ RtlpInitializeHeapSegment(IN OUT PHEAP Heap,
         RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY) HeapEntry, (SegmentCommit >>
HEAP_ENTRY_SHIFT) - Segment->Entry.Size);
     }
+    /* Always point to a valid entry */
+    Segment->LastEntryInSegment = Segment->FirstEntry;
+
     /* Initialise the Heap Segment UnCommitted Range information */
     Segment->NumberOfUnCommittedPages = (ULONG)((SegmentReserve - SegmentCommit)
>> PAGE_SHIFT);
     Segment->NumberOfUnCommittedRanges = 0;
@@ -984,6 +998,7 @@ RtlpCoalesceFreeBlocks (PHEAP Heap,
                         BOOLEAN Remove)
 {
     PHEAP_FREE_ENTRY CurrentEntry, NextEntry;
+    UCHAR SegmentOffset;
     /* Get the previous entry */
     CurrentEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry -
FreeEntry->PreviousSize);
@@ -1022,6 +1037,12 @@ RtlpCoalesceFreeBlocks (PHEAP Heap,
         {
             ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize);
         }
+        else
+        {
+            SegmentOffset = FreeEntry->SegmentOffset;
+            ASSERT(SegmentOffset < HEAP_SEGMENTS);
+            Heap->Segments[SegmentOffset]->LastEntryInSegment = FreeEntry;
+        }
     }
     /* Check the next block if it exists */
@@ -1057,6 +1078,12 @@ RtlpCoalesceFreeBlocks (PHEAP Heap,
             {
                 ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize =
(USHORT)(*FreeSize);
             }
+            else
+            {
+                SegmentOffset = FreeEntry->SegmentOffset;
+                ASSERT(SegmentOffset < HEAP_SEGMENTS);
+                Heap->Segments[SegmentOffset]->LastEntryInSegment = FreeEntry;
+            }
         }
     }
     return FreeEntry;
@@ -1637,6 +1664,7 @@ RtlpSplitEntry(PHEAP Heap,
     UCHAR FreeFlags, EntryFlags = HEAP_ENTRY_BUSY;
     PHEAP_ENTRY InUseEntry;
     SIZE_T FreeSize;
+    UCHAR SegmentOffset;
     /* Add extra flags in case of settable user value feature is requested,
        or there is a tag (small or normal) or there is a request to
@@ -1748,6 +1776,12 @@ RtlpSplitEntry(PHEAP Heap,
             /* Reset flags of the free entry */
             FreeFlags = 0;
+            if (SplitBlock->Flags & HEAP_ENTRY_LAST_ENTRY)
+            {
+                SegmentOffset = SplitBlock->SegmentOffset;
+                ASSERT(SegmentOffset < HEAP_SEGMENTS);
+                Heap->Segments[SegmentOffset]->LastEntryInSegment = SplitBlock;
+            }
         }
     }
@@ -2311,6 +2345,7 @@ RtlpGrowBlockInPlace (IN PHEAP Heap,
     PHEAP_FREE_ENTRY FreeEntry, UnusedEntry, FollowingEntry;
     SIZE_T FreeSize, PrevSize, TailPart, AddedSize = 0;
     PHEAP_ENTRY_EXTRA OldExtra, NewExtra;
+    UCHAR SegmentOffset;
     /* We can't grow beyond specified threshold */
     if (Index > Heap->VirtualMemoryThreshold)
@@ -2407,9 +2442,17 @@ RtlpGrowBlockInPlace (IN PHEAP Heap,
         InUseEntry->Flags |= RememberFlags & HEAP_ENTRY_LAST_ENTRY;
         /* Either update previous size of the next entry or mark it as a last
-           entry in the segment*/
+           entry in the segment */
         if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY))
+        {
             (InUseEntry + InUseEntry->Size)->PreviousSize = InUseEntry->Size;
+        }
+        else
+        {
+            SegmentOffset = InUseEntry->SegmentOffset;
+            ASSERT(SegmentOffset < HEAP_SEGMENTS);
+            Heap->Segments[SegmentOffset]->LastEntryInSegment = InUseEntry;
+        }
     }
     else
     {
@@ -2422,6 +2465,10 @@ RtlpGrowBlockInPlace (IN PHEAP Heap,
         /* Update the following block or set the last entry in the segment */
         if (RememberFlags & HEAP_ENTRY_LAST_ENTRY)
         {
+            SegmentOffset = UnusedEntry->SegmentOffset;
+            ASSERT(SegmentOffset < HEAP_SEGMENTS);
+            Heap->Segments[SegmentOffset]->LastEntryInSegment = UnusedEntry;
+
             /* Set flags and size */
             UnusedEntry->Flags = RememberFlags;
             UnusedEntry->Size = (USHORT)FreeSize;
@@ -2468,7 +2515,15 @@ RtlpGrowBlockInPlace (IN PHEAP Heap,
                     UnusedEntry->Size = (USHORT)FreeSize;
                     if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY))
+                    {
                         ((PHEAP_ENTRY)UnusedEntry + FreeSize)->PreviousSize =
(USHORT)FreeSize;
+                    }
+                    else
+                    {
+                        SegmentOffset = UnusedEntry->SegmentOffset;
+                        ASSERT(SegmentOffset < HEAP_SEGMENTS);
+                        Heap->Segments[SegmentOffset]->LastEntryInSegment =
UnusedEntry;
+                    }
                     /* Insert it back and update total size */
                     RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE);
@@ -2578,6 +2633,7 @@ RtlReAllocateHeap(HANDLE HeapPtr,
     SIZE_T RemainderBytes, ExtraSize;
     PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock;
     EXCEPTION_RECORD ExceptionRecord;
+    UCHAR SegmentOffset;
     /* Return success in case of a null pointer */
     if (!Ptr)
@@ -2787,6 +2843,10 @@ RtlReAllocateHeap(HANDLE HeapPtr,
                 /* Is that the last entry */
                 if (FreeFlags & HEAP_ENTRY_LAST_ENTRY)
                 {
+                    SegmentOffset = SplitBlock->SegmentOffset;
+                    ASSERT(SegmentOffset < HEAP_SEGMENTS);
+                    Heap->Segments[SegmentOffset]->LastEntryInSegment = SplitBlock;
+
                     /* Set its size and insert it to the list */
                     SplitBlock->Size = (USHORT)FreeSize;
                     RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
@@ -2834,6 +2894,12 @@ RtlReAllocateHeap(HANDLE HeapPtr,
                                 /* Update previous size of the next entry */
                                 ((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock +
FreeSize))->PreviousSize = (USHORT)FreeSize;
                             }
+                            else
+                            {
+                                SegmentOffset = SplitBlock->SegmentOffset;
+                                ASSERT(SegmentOffset < HEAP_SEGMENTS);
+                                Heap->Segments[SegmentOffset]->LastEntryInSegment =
SplitBlock;
+                            }
                             /* Insert the new one back and update total size */
                             RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
diff --git a/sdk/lib/rtl/heap.h b/sdk/lib/rtl/heap.h
index 8fb9bc7ae0d..aef68e5edcd 100644
--- a/sdk/lib/rtl/heap.h
+++ b/sdk/lib/rtl/heap.h
@@ -217,7 +217,8 @@ typedef struct _HEAP_LIST_LOOKUP
     ULONG NumberOfUnCommittedRanges;        \
     USHORT SegmentAllocatorBackTraceIndex;  \
     USHORT Reserved;                        \
-    LIST_ENTRY UCRSegmentList
+    LIST_ENTRY UCRSegmentList;              \
+    PVOID LastEntryInSegment //FIXME: non-Vista
 typedef struct _HEAP
 {