- 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.

svn path=/trunk/; revision=49034
This commit is contained in:
Aleksey Bragin 2010-10-07 17:05:29 +00:00
parent 41b74ee1f9
commit 9dabd64349

View file

@ -30,8 +30,8 @@
#define HEAP_ENTRY_SHIFT 3 #define HEAP_ENTRY_SHIFT 3
#define HEAP_MAX_BLOCK_SIZE ((0x80000 - PAGE_SIZE) >> HEAP_ENTRY_SHIFT) #define HEAP_MAX_BLOCK_SIZE ((0x80000 - PAGE_SIZE) >> HEAP_ENTRY_SHIFT)
#define ARENA_INUSE_FILLER 0x55555555 #define ARENA_INUSE_FILLER 0xBAADF00D
#define ARENA_FREE_FILLER 0xaaaaaaaa #define ARENA_FREE_FILLER 0xFEEEFEEE
#define HEAP_TAIL_FILL 0xab #define HEAP_TAIL_FILL 0xab
// from ntifs.h, should go to another header! // from ntifs.h, should go to another header!
@ -261,6 +261,7 @@ typedef struct _HEAP_VIRTUAL_ALLOC_ENTRY
HEAP_ENTRY BusyBlock; HEAP_ENTRY BusyBlock;
} HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY; } HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY;
extern BOOLEAN RtlpPageHeapEnabled;
HANDLE NTAPI HANDLE NTAPI
RtlpSpecialHeapCreate(ULONG Flags, RtlpSpecialHeapCreate(ULONG Flags,
PVOID Addr, PVOID Addr,
@ -341,6 +342,9 @@ RtlpCoalesceFreeBlocks (PHEAP Heap,
PSIZE_T FreeSize, PSIZE_T FreeSize,
BOOLEAN Remove); BOOLEAN Remove);
PHEAP_ENTRY_EXTRA NTAPI
RtlpGetExtraStuffPointer(PHEAP_ENTRY HeapEntry);
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
VOID NTAPI VOID NTAPI
@ -1546,7 +1550,8 @@ RtlCreateHeap(ULONG Flags,
Heap = RtlpSpecialHeapCreate(Flags, Addr, TotalSize, CommitSize, Lock, Parameters); Heap = RtlpSpecialHeapCreate(Flags, Addr, TotalSize, CommitSize, Lock, Parameters);
if (Heap) return Heap; if (Heap) return Heap;
ASSERT(FALSE); //ASSERT(FALSE);
DPRINT1("Enabling page heap failed\n");
} }
/* Check validation flags */ /* Check validation flags */
@ -1560,12 +1565,18 @@ RtlCreateHeap(ULONG Flags,
if (!Parameters) Parameters = &SafeParams; if (!Parameters) Parameters = &SafeParams;
/* Check global flags */ /* Check global flags */
if (NtGlobalFlags & FLG_HEAP_DISABLE_COALESCING)
Flags |= HEAP_DISABLE_COALESCE_ON_FREE;
if (NtGlobalFlags & FLG_HEAP_ENABLE_FREE_CHECK) if (NtGlobalFlags & FLG_HEAP_ENABLE_FREE_CHECK)
Flags |= HEAP_FREE_CHECKING_ENABLED; Flags |= HEAP_FREE_CHECKING_ENABLED;
if (NtGlobalFlags & FLG_HEAP_ENABLE_TAIL_CHECK) if (NtGlobalFlags & FLG_HEAP_ENABLE_TAIL_CHECK)
Flags |= HEAP_TAIL_CHECKING_ENABLED; Flags |= HEAP_TAIL_CHECKING_ENABLED;
if (Flags & HEAP_TAIL_CHECKING_ENABLED)
DPRINT1("TailChecking!\n");
if (RtlpGetMode() == UserMode) if (RtlpGetMode() == UserMode)
{ {
/* Also check these flags if in usermode */ /* Also check these flags if in usermode */
@ -2014,7 +2025,7 @@ RtlpSplitEntry(PHEAP Heap,
if (FreeFlags & HEAP_ENTRY_LAST_ENTRY) if (FreeFlags & HEAP_ENTRY_LAST_ENTRY)
{ {
/* Insert it to the free list if it's the 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; Heap->TotalFreeSize += FreeSize;
} }
else else
@ -2025,7 +2036,7 @@ RtlpSplitEntry(PHEAP Heap,
if (SplitBlock2->Flags & HEAP_ENTRY_BUSY) if (SplitBlock2->Flags & HEAP_ENTRY_BUSY)
{ {
SplitBlock2->PreviousSize = (USHORT)FreeSize; SplitBlock2->PreviousSize = (USHORT)FreeSize;
RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, TRUE); RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
Heap->TotalFreeSize += FreeSize; Heap->TotalFreeSize += FreeSize;
} }
else else
@ -2034,7 +2045,7 @@ RtlpSplitEntry(PHEAP Heap,
SplitBlock->Flags = SplitBlock2->Flags; SplitBlock->Flags = SplitBlock2->Flags;
/* Remove that next entry */ /* Remove that next entry */
RtlpRemoveFreeBlock(Heap, SplitBlock2, FALSE, TRUE); RtlpRemoveFreeBlock(Heap, SplitBlock2, FALSE, FALSE);
/* Update sizes */ /* Update sizes */
FreeSize += SplitBlock2->Size; FreeSize += SplitBlock2->Size;
@ -2052,7 +2063,7 @@ RtlpSplitEntry(PHEAP Heap,
} }
/* Actually insert it */ /* Actually insert it */
RtlpInsertFreeBlockHelper( Heap, SplitBlock, (USHORT)FreeSize, TRUE ); RtlpInsertFreeBlockHelper(Heap, SplitBlock, (USHORT)FreeSize, FALSE);
/* Update total size */ /* Update total size */
Heap->TotalFreeSize += FreeSize; Heap->TotalFreeSize += FreeSize;
@ -2094,6 +2105,7 @@ RtlpAllocateNonDedicated(PHEAP Heap,
PLIST_ENTRY FreeListHead, Next; PLIST_ENTRY FreeListHead, Next;
PHEAP_FREE_ENTRY FreeBlock; PHEAP_FREE_ENTRY FreeBlock;
PHEAP_ENTRY InUseEntry; PHEAP_ENTRY InUseEntry;
PHEAP_ENTRY_EXTRA Extra;
EXCEPTION_RECORD ExceptionRecord; EXCEPTION_RECORD ExceptionRecord;
/* Go through the zero list to find a place where to insert the new entry */ /* Go through the zero list to find a place where to insert the new entry */
@ -2130,6 +2142,27 @@ RtlpAllocateNonDedicated(PHEAP Heap,
/* Zero memory if that was requested */ /* Zero memory if that was requested */
if (Flags & HEAP_ZERO_MEMORY) if (Flags & HEAP_ZERO_MEMORY)
RtlZeroMemory(InUseEntry + 1, Size); 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 pointer to the */
return InUseEntry + 1; return InUseEntry + 1;
@ -2158,13 +2191,34 @@ RtlpAllocateNonDedicated(PHEAP Heap,
/* Zero memory if that was requested */ /* Zero memory if that was requested */
if (Flags & HEAP_ZERO_MEMORY) if (Flags & HEAP_ZERO_MEMORY)
RtlZeroMemory(InUseEntry + 1, Size); 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 pointer to the */
return InUseEntry + 1; return InUseEntry + 1;
} }
/* Really unfortunate, out of memory condition */ /* Really unfortunate, out of memory condition */
//STATUS_NO_MEMORY; RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_NO_MEMORY);
/* Generate an exception */ /* Generate an exception */
if (Flags & HEAP_GENERATE_EXCEPTIONS) if (Flags & HEAP_GENERATE_EXCEPTIONS)
@ -2209,6 +2263,7 @@ RtlAllocateHeap(IN PVOID HeapPtr,
EXCEPTION_RECORD ExceptionRecord; EXCEPTION_RECORD ExceptionRecord;
BOOLEAN HeapLocked = FALSE; BOOLEAN HeapLocked = FALSE;
PHEAP_VIRTUAL_ALLOC_ENTRY VirtualBlock = NULL; PHEAP_VIRTUAL_ALLOC_ENTRY VirtualBlock = NULL;
PHEAP_ENTRY_EXTRA Extra;
NTSTATUS Status; NTSTATUS Status;
/* Force flags */ /* Force flags */
@ -2217,7 +2272,7 @@ RtlAllocateHeap(IN PVOID HeapPtr,
/* Check for the maximum size */ /* Check for the maximum size */
if (Size >= 0x80000000) if (Size >= 0x80000000)
{ {
// STATUS_NO_MEMORY RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_NO_MEMORY);
return FALSE; return FALSE;
} }
@ -2225,24 +2280,27 @@ RtlAllocateHeap(IN PVOID HeapPtr,
HEAP_VALIDATE_ALL_ENABLED | HEAP_VALIDATE_ALL_ENABLED |
HEAP_VALIDATE_PARAMETERS_ENABLED | HEAP_VALIDATE_PARAMETERS_ENABLED |
HEAP_FLAG_PAGE_ALLOCS | HEAP_FLAG_PAGE_ALLOCS |
HEAP_EXTRA_FLAGS_MASK |
HEAP_CREATE_ENABLE_TRACING | HEAP_CREATE_ENABLE_TRACING |
HEAP_FREE_CHECKING_ENABLED |
HEAP_TAIL_CHECKING_ENABLED |
HEAP_CREATE_ALIGN_16)) HEAP_CREATE_ALIGN_16))
{ {
DPRINT1("HEAP: RtlAllocateHeap is called with unsupported flags %x, ignoring\n", Flags); 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 */ /* Calculate allocation size and index */
if (!Size) Size = 1; if (Size)
AllocationSize = (Size + Heap->AlignRound) & Heap->AlignMask; AllocationSize = Size;
else
AllocationSize = 1;
AllocationSize = (AllocationSize + Heap->AlignRound) & Heap->AlignMask;
Index = AllocationSize >> HEAP_ENTRY_SHIFT; Index = AllocationSize >> HEAP_ENTRY_SHIFT;
/* Acquire the lock if necessary */ /* Acquire the lock if necessary */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock( Heap->LockVariable ); RtlEnterHeapLock(Heap->LockVariable);
HeapLocked = TRUE; HeapLocked = TRUE;
} }
@ -2261,7 +2319,7 @@ RtlAllocateHeap(IN PVOID HeapPtr,
/* Save flags and remove the free entry */ /* Save flags and remove the free entry */
FreeFlags = FreeBlock->Flags; FreeFlags = FreeBlock->Flags;
RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, TRUE); RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, FALSE);
/* Update the total free size of the heap */ /* Update the total free size of the heap */
Heap->TotalFreeSize -= Index; Heap->TotalFreeSize -= Index;
@ -2308,7 +2366,7 @@ RtlAllocateHeap(IN PVOID HeapPtr,
FreeBlock = CONTAINING_RECORD(FreeListHead->Blink, FreeBlock = CONTAINING_RECORD(FreeListHead->Blink,
HEAP_FREE_ENTRY, HEAP_FREE_ENTRY,
FreeList); FreeList);
RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, TRUE); RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, FALSE);
/* Split it */ /* Split it */
InUseEntry = RtlpSplitEntry(Heap, FreeBlock, AllocationSize, Index, Size); InUseEntry = RtlpSplitEntry(Heap, FreeBlock, AllocationSize, Index, Size);
@ -2320,6 +2378,27 @@ RtlAllocateHeap(IN PVOID HeapPtr,
/* Zero memory if that was requested */ /* Zero memory if that was requested */
if (Flags & HEAP_ZERO_MEMORY) if (Flags & HEAP_ZERO_MEMORY)
RtlZeroMemory(InUseEntry + 1, Size); 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 */ /* User data starts right after the entry's header */
return InUseEntry + 1; return InUseEntry + 1;
@ -2377,7 +2456,7 @@ RtlAllocateHeap(IN PVOID HeapPtr,
RtlRaiseException(&ExceptionRecord); RtlRaiseException(&ExceptionRecord);
} }
//STATUS_BUFFER_TOO_SMALL; RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_BUFFER_TOO_SMALL);
/* Release the lock */ /* Release the lock */
if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable); if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
@ -2431,7 +2510,7 @@ BOOLEAN NTAPI RtlFreeHeap(
{ {
/* This is an invalid block */ /* This is an invalid block */
DPRINT1("HEAP: Trying to free an invalid address %p!\n", Ptr); DPRINT1("HEAP: Trying to free an invalid address %p!\n", Ptr);
// FIXME: Set STATUS_INVALID_PARAMETER RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
/* Release the heap lock */ /* Release the heap lock */
if (Locked) RtlLeaveHeapLock(Heap->LockVariable); if (Locked) RtlLeaveHeapLock(Heap->LockVariable);
@ -2457,7 +2536,7 @@ BOOLEAN NTAPI RtlFreeHeap(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failed releasing memory with Status 0x%08X\n", Status); DPRINT1("Failed releasing memory with Status 0x%08X\n", Status);
// TODO: Set this status in user mode RtlSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
} }
} }
else else
@ -2593,7 +2672,7 @@ RtlReAllocateHeap(HANDLE HeapPtr,
/* Return success in case of a null pointer */ /* Return success in case of a null pointer */
if (!Ptr) if (!Ptr)
{ {
// STATUS_SUCCESS RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_SUCCESS);
return NULL; return NULL;
} }
@ -2605,7 +2684,7 @@ RtlReAllocateHeap(HANDLE HeapPtr,
/* Make sure size is valid */ /* Make sure size is valid */
if (Size >= 0x80000000) if (Size >= 0x80000000)
{ {
// STATUS_NO_MEMORY RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_NO_MEMORY);
return NULL; return NULL;
} }
@ -2635,7 +2714,7 @@ RtlReAllocateHeap(HANDLE HeapPtr,
/* If that entry is not really in-use, we have a problem */ /* If that entry is not really in-use, we have a problem */
if (!(InUseEntry->Flags & HEAP_ENTRY_BUSY)) if (!(InUseEntry->Flags & HEAP_ENTRY_BUSY))
{ {
// STATUS_INVALID_PARAMETER RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
/* Release the lock and return */ /* Release the lock and return */
if (HeapLocked) if (HeapLocked)
@ -3086,7 +3165,7 @@ RtlSizeHeap(
/* Return -1 if that entry is free */ /* Return -1 if that entry is free */
if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY)) if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY))
{ {
// STATUS_INVALID_PARAMETER RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
return (SIZE_T)-1; return (SIZE_T)-1;
} }
@ -3131,7 +3210,9 @@ BOOLEAN NTAPI RtlValidateHeap(
) )
{ {
UNIMPLEMENTED; UNIMPLEMENTED;
return FALSE;
/* Imitate success */
return TRUE;
} }
VOID VOID