Author: fireball
Date: Thu Oct 7 17:05:29 2010
New Revision: 49034
URL:
http://svn.reactos.org/svn/reactos?rev=49034&view=rev
Log:
[HEAP]
- Fix allocated/free memory fillers to match those Windows uses (winetests)
- Add missing coalesce-on-free flag check in RtlCreateHeap
- Turn on tail check/pattern filling in RtlAllocateHeap.
- Add extra stuff storage support in RtlAllocateHeap and its helpers.
- Set win32 statuses where necessary.
- Return success in RtlValidateHeap to reduce spam when running winetest.
Modified:
trunk/reactos/lib/rtl/heap_rewrite.c
Modified: trunk/reactos/lib/rtl/heap_rewrite.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/heap_rewrite.c?rev…
==============================================================================
--- trunk/reactos/lib/rtl/heap_rewrite.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/heap_rewrite.c [iso-8859-1] Thu Oct 7 17:05:29 2010
@@ -30,8 +30,8 @@
#define HEAP_ENTRY_SHIFT 3
#define HEAP_MAX_BLOCK_SIZE ((0x80000 - PAGE_SIZE) >> HEAP_ENTRY_SHIFT)
-#define ARENA_INUSE_FILLER 0x55555555
-#define ARENA_FREE_FILLER 0xaaaaaaaa
+#define ARENA_INUSE_FILLER 0xBAADF00D
+#define ARENA_FREE_FILLER 0xFEEEFEEE
#define HEAP_TAIL_FILL 0xab
// from ntifs.h, should go to another header!
@@ -261,6 +261,7 @@
HEAP_ENTRY BusyBlock;
} HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY;
+extern BOOLEAN RtlpPageHeapEnabled;
HANDLE NTAPI
RtlpSpecialHeapCreate(ULONG Flags,
PVOID Addr,
@@ -341,6 +342,9 @@
PSIZE_T FreeSize,
BOOLEAN Remove);
+PHEAP_ENTRY_EXTRA NTAPI
+RtlpGetExtraStuffPointer(PHEAP_ENTRY HeapEntry);
+
/* FUNCTIONS *****************************************************************/
VOID NTAPI
@@ -1546,7 +1550,8 @@
Heap = RtlpSpecialHeapCreate(Flags, Addr, TotalSize, CommitSize, Lock,
Parameters);
if (Heap) return Heap;
- ASSERT(FALSE);
+ //ASSERT(FALSE);
+ DPRINT1("Enabling page heap failed\n");
}
/* Check validation flags */
@@ -1560,11 +1565,17 @@
if (!Parameters) Parameters = &SafeParams;
/* Check global flags */
+ if (NtGlobalFlags & FLG_HEAP_DISABLE_COALESCING)
+ Flags |= HEAP_DISABLE_COALESCE_ON_FREE;
+
if (NtGlobalFlags & FLG_HEAP_ENABLE_FREE_CHECK)
Flags |= HEAP_FREE_CHECKING_ENABLED;
if (NtGlobalFlags & FLG_HEAP_ENABLE_TAIL_CHECK)
Flags |= HEAP_TAIL_CHECKING_ENABLED;
+
+ if (Flags & HEAP_TAIL_CHECKING_ENABLED)
+ DPRINT1("TailChecking!\n");
if (RtlpGetMode() == UserMode)
{
@@ -2014,7 +2025,7 @@
if (FreeFlags & HEAP_ENTRY_LAST_ENTRY)
{
/* Insert it to the free list if it's the last entry */
- RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, TRUE);
+ RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
Heap->TotalFreeSize += FreeSize;
}
else
@@ -2025,7 +2036,7 @@
if (SplitBlock2->Flags & HEAP_ENTRY_BUSY)
{
SplitBlock2->PreviousSize = (USHORT)FreeSize;
- RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, TRUE);
+ RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
Heap->TotalFreeSize += FreeSize;
}
else
@@ -2034,7 +2045,7 @@
SplitBlock->Flags = SplitBlock2->Flags;
/* Remove that next entry */
- RtlpRemoveFreeBlock(Heap, SplitBlock2, FALSE, TRUE);
+ RtlpRemoveFreeBlock(Heap, SplitBlock2, FALSE, FALSE);
/* Update sizes */
FreeSize += SplitBlock2->Size;
@@ -2052,7 +2063,7 @@
}
/* Actually insert it */
- RtlpInsertFreeBlockHelper( Heap, SplitBlock, (USHORT)FreeSize,
TRUE );
+ RtlpInsertFreeBlockHelper(Heap, SplitBlock, (USHORT)FreeSize,
FALSE);
/* Update total size */
Heap->TotalFreeSize += FreeSize;
@@ -2094,6 +2105,7 @@
PLIST_ENTRY FreeListHead, Next;
PHEAP_FREE_ENTRY FreeBlock;
PHEAP_ENTRY InUseEntry;
+ PHEAP_ENTRY_EXTRA Extra;
EXCEPTION_RECORD ExceptionRecord;
/* Go through the zero list to find a place where to insert the new entry */
@@ -2130,6 +2142,27 @@
/* Zero memory if that was requested */
if (Flags & HEAP_ZERO_MEMORY)
RtlZeroMemory(InUseEntry + 1, Size);
+ else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
+ {
+ /* Fill this block with a special pattern */
+ RtlFillMemoryUlong(InUseEntry + 1, Size & ~0x3,
ARENA_INUSE_FILLER);
+ }
+
+ /* Fill tail of the block with a special pattern too if requested */
+ if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
+ {
+ RtlFillMemory((PCHAR)(InUseEntry + 1) + Size, sizeof(HEAP_ENTRY),
HEAP_TAIL_FILL);
+ InUseEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
+ }
+
+ /* Prepare extra if it's present */
+ if (InUseEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
+ {
+ Extra = RtlpGetExtraStuffPointer(InUseEntry);
+ RtlZeroMemory(Extra, sizeof(HEAP_ENTRY_EXTRA));
+
+ // TODO: Tagging
+ }
/* Return pointer to the */
return InUseEntry + 1;
@@ -2158,13 +2191,34 @@
/* Zero memory if that was requested */
if (Flags & HEAP_ZERO_MEMORY)
RtlZeroMemory(InUseEntry + 1, Size);
+ else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
+ {
+ /* Fill this block with a special pattern */
+ RtlFillMemoryUlong(InUseEntry + 1, Size & ~0x3, ARENA_INUSE_FILLER);
+ }
+
+ /* Fill tail of the block with a special pattern too if requested */
+ if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
+ {
+ RtlFillMemory((PCHAR)(InUseEntry + 1) + Size, sizeof(HEAP_ENTRY),
HEAP_TAIL_FILL);
+ InUseEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
+ }
+
+ /* Prepare extra if it's present */
+ if (InUseEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
+ {
+ Extra = RtlpGetExtraStuffPointer(InUseEntry);
+ RtlZeroMemory(Extra, sizeof(HEAP_ENTRY_EXTRA));
+
+ // TODO: Tagging
+ }
/* Return pointer to the */
return InUseEntry + 1;
}
/* Really unfortunate, out of memory condition */
- //STATUS_NO_MEMORY;
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_NO_MEMORY);
/* Generate an exception */
if (Flags & HEAP_GENERATE_EXCEPTIONS)
@@ -2209,6 +2263,7 @@
EXCEPTION_RECORD ExceptionRecord;
BOOLEAN HeapLocked = FALSE;
PHEAP_VIRTUAL_ALLOC_ENTRY VirtualBlock = NULL;
+ PHEAP_ENTRY_EXTRA Extra;
NTSTATUS Status;
/* Force flags */
@@ -2217,7 +2272,7 @@
/* Check for the maximum size */
if (Size >= 0x80000000)
{
- // STATUS_NO_MEMORY
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_NO_MEMORY);
return FALSE;
}
@@ -2225,24 +2280,27 @@
HEAP_VALIDATE_ALL_ENABLED |
HEAP_VALIDATE_PARAMETERS_ENABLED |
HEAP_FLAG_PAGE_ALLOCS |
- HEAP_EXTRA_FLAGS_MASK |
HEAP_CREATE_ENABLE_TRACING |
- HEAP_FREE_CHECKING_ENABLED |
- HEAP_TAIL_CHECKING_ENABLED |
HEAP_CREATE_ALIGN_16))
{
DPRINT1("HEAP: RtlAllocateHeap is called with unsupported flags %x,
ignoring\n", Flags);
}
+ if (Flags & HEAP_TAIL_CHECKING_ENABLED)
+ DPRINT1("TailChecking, Heap %p\n!", Heap);
+
/* Calculate allocation size and index */
- if (!Size) Size = 1;
- AllocationSize = (Size + Heap->AlignRound) & Heap->AlignMask;
+ if (Size)
+ AllocationSize = Size;
+ else
+ AllocationSize = 1;
+ AllocationSize = (AllocationSize + Heap->AlignRound) & Heap->AlignMask;
Index = AllocationSize >> HEAP_ENTRY_SHIFT;
/* Acquire the lock if necessary */
if (!(Flags & HEAP_NO_SERIALIZE))
{
- RtlEnterHeapLock( Heap->LockVariable );
+ RtlEnterHeapLock(Heap->LockVariable);
HeapLocked = TRUE;
}
@@ -2261,7 +2319,7 @@
/* Save flags and remove the free entry */
FreeFlags = FreeBlock->Flags;
- RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, TRUE);
+ RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, FALSE);
/* Update the total free size of the heap */
Heap->TotalFreeSize -= Index;
@@ -2308,7 +2366,7 @@
FreeBlock = CONTAINING_RECORD(FreeListHead->Blink,
HEAP_FREE_ENTRY,
FreeList);
- RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, TRUE);
+ RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, FALSE);
/* Split it */
InUseEntry = RtlpSplitEntry(Heap, FreeBlock, AllocationSize, Index, Size);
@@ -2320,6 +2378,27 @@
/* Zero memory if that was requested */
if (Flags & HEAP_ZERO_MEMORY)
RtlZeroMemory(InUseEntry + 1, Size);
+ else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
+ {
+ /* Fill this block with a special pattern */
+ RtlFillMemoryUlong(InUseEntry + 1, Size & ~0x3, ARENA_INUSE_FILLER);
+ }
+
+ /* Fill tail of the block with a special pattern too if requested */
+ if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
+ {
+ RtlFillMemory((PCHAR)(InUseEntry + 1) + Size, sizeof(HEAP_ENTRY),
HEAP_TAIL_FILL);
+ InUseEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
+ }
+
+ /* Prepare extra if it's present */
+ if (InUseEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
+ {
+ Extra = RtlpGetExtraStuffPointer(InUseEntry);
+ RtlZeroMemory(Extra, sizeof(HEAP_ENTRY_EXTRA));
+
+ // TODO: Tagging
+ }
/* User data starts right after the entry's header */
return InUseEntry + 1;
@@ -2377,7 +2456,7 @@
RtlRaiseException(&ExceptionRecord);
}
- //STATUS_BUFFER_TOO_SMALL;
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_BUFFER_TOO_SMALL);
/* Release the lock */
if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
@@ -2431,7 +2510,7 @@
{
/* This is an invalid block */
DPRINT1("HEAP: Trying to free an invalid address %p!\n", Ptr);
- // FIXME: Set STATUS_INVALID_PARAMETER
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
/* Release the heap lock */
if (Locked) RtlLeaveHeapLock(Heap->LockVariable);
@@ -2457,7 +2536,7 @@
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed releasing memory with Status 0x%08X\n", Status);
- // TODO: Set this status in user mode
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
}
}
else
@@ -2593,7 +2672,7 @@
/* Return success in case of a null pointer */
if (!Ptr)
{
- // STATUS_SUCCESS
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_SUCCESS);
return NULL;
}
@@ -2605,7 +2684,7 @@
/* Make sure size is valid */
if (Size >= 0x80000000)
{
- // STATUS_NO_MEMORY
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_NO_MEMORY);
return NULL;
}
@@ -2635,7 +2714,7 @@
/* If that entry is not really in-use, we have a problem */
if (!(InUseEntry->Flags & HEAP_ENTRY_BUSY))
{
- // STATUS_INVALID_PARAMETER
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
/* Release the lock and return */
if (HeapLocked)
@@ -3086,7 +3165,7 @@
/* Return -1 if that entry is free */
if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY))
{
- // STATUS_INVALID_PARAMETER
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
return (SIZE_T)-1;
}
@@ -3131,7 +3210,9 @@
)
{
UNIMPLEMENTED;
- return FALSE;
+
+ /* Imitate success */
+ return TRUE;
}
VOID