From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/heap.c | 63 +++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 28 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index fded1c69f1e..586c9a1ed0b 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -1762,17 +1762,18 @@ static void test_LocalAlloc(void) static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags ) { DWORD padd_flags = HEAP_VALIDATE | HEAP_VALIDATE_ALL | HEAP_VALIDATE_PARAMS; - SIZE_T expect_size, alloc_size, extra_size, tail_size = 0; - unsigned char *ptr0, *ptr1, *ptr2; + SIZE_T expect_size, diff, alloc_size, extra_size, tail_size = 0; + unsigned char *ptr0, *ptr1, *ptr2, tail; char tail_buf[64], padd_buf[64]; void *tmp_ptr, **user_ptr; ULONG tmp_flags; + UINT_PTR align; BOOL ret;
if (global_flags & (FLG_HEAP_DISABLE_COALESCING|FLG_HEAP_PAGE_ALLOCS|FLG_POOL_ENABLE_TAGGING| FLG_HEAP_ENABLE_TAGGING|FLG_HEAP_ENABLE_TAG_BY_DLL)) { - skip( "skipping not yet implemented block layout tests\n" ); + skip( "skipping block tests\n" ); return; }
@@ -1796,16 +1797,17 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags ptr2 = pHeapAlloc( heap, HEAP_ZERO_MEMORY, alloc_size ); ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
- ok( !((UINT_PTR)ptr0 & (2 * sizeof(void *) - 1)), "got unexpected ptr align\n" ); - ok( !((UINT_PTR)ptr1 & (2 * sizeof(void *) - 1)), "got unexpected ptr align\n" ); - ok( !((UINT_PTR)ptr2 & (2 * sizeof(void *) - 1)), "got unexpected ptr align\n" ); + align = (UINT_PTR)ptr0 | (UINT_PTR)ptr1 | (UINT_PTR)ptr2; + ok( !(align & (2 * sizeof(void *) - 1)), "wrong align\n" );
expect_size = max( alloc_size, 2 * sizeof(void *) ); expect_size = ALIGN_BLOCK_SIZE( expect_size + extra_size ); - todo_wine_if( heap_flags & (HEAP_VALIDATE_PARAMS|HEAP_VALIDATE_ALL) || - min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) ) != expect_size ) - ok( min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) ) == expect_size, "got diff %#I64x\n", - min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) ) ); + diff = min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) ); + todo_wine_if( (heap_flags & (HEAP_VALIDATE_PARAMS|HEAP_VALIDATE_ALL)) || + ((global_flags & ~FLG_HEAP_ENABLE_TAIL_CHECK) && alloc_size < 0x10000) || + (!global_flags && alloc_size < 2 * sizeof(void *)) || + (alloc_size == 0xfd000 && sizeof(void *) == 8) ) + ok( diff == expect_size, "got diff %#Ix exp %#Ix\n", diff, expect_size );
ok( !memcmp( ptr0 + alloc_size, tail_buf, tail_size ), "missing block tail\n" ); ok( !memcmp( ptr1 + alloc_size, tail_buf, tail_size ), "missing block tail\n" ); @@ -1819,6 +1821,13 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
winetest_pop_context(); + + if (diff != expect_size) + { + todo_wine + win_skip("skipping sizes\n"); + break; + } }
@@ -1850,25 +1859,19 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags ptr2 = pHeapAlloc( heap, 0, alloc_size ); ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
+ align = (UINT_PTR)ptr0 | (UINT_PTR)ptr1 | (UINT_PTR)ptr2; todo_wine_if( sizeof(void *) == 8 || alloc_size == 0x7efe9 ) - ok( !((UINT_PTR)ptr0 & (8 * sizeof(void *) - 1)), "got unexpected ptr align\n" ); - todo_wine_if( sizeof(void *) == 8 || alloc_size == 0x7efe9 ) - ok( !((UINT_PTR)ptr1 & (8 * sizeof(void *) - 1)), "got unexpected ptr align\n" ); - todo_wine_if( sizeof(void *) == 8 || alloc_size == 0x7efe9 ) - ok( !((UINT_PTR)ptr2 & (8 * sizeof(void *) - 1)), "got unexpected ptr align\n" ); + ok( !(align & (8 * sizeof(void *) - 1)), "wrong align\n" );
expect_size = max( alloc_size, 2 * sizeof(void *) ); expect_size = ALIGN_BLOCK_SIZE( expect_size + extra_size ); + diff = min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) ); todo_wine_if( alloc_size == 0x7efe9 ) - ok( min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) ) > expect_size, "got diff %#I64x\n", - min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) ) ); + ok( diff > expect_size, "got diff %#Ix\n", diff );
+ tail = ptr0[alloc_size] | ptr1[alloc_size] | ptr2[alloc_size]; todo_wine_if( heap_flags & HEAP_TAIL_CHECKING_ENABLED ) - ok( !ptr0[alloc_size], "got block tail\n" ); - todo_wine_if( heap_flags & HEAP_TAIL_CHECKING_ENABLED ) - ok( !ptr1[alloc_size], "got block tail\n" ); - todo_wine_if( heap_flags & HEAP_TAIL_CHECKING_ENABLED ) - ok( !ptr2[alloc_size], "got block tail\n" ); + ok( !tail, "got tail\n" );
ret = HeapFree( heap, 0, ptr2 ); ok( ret, "HeapFree failed, error %lu\n", GetLastError() ); @@ -1877,6 +1880,13 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags ret = HeapFree( heap, 0, ptr0 ); ok( ret, "HeapFree failed, error %lu\n", GetLastError() ); winetest_pop_context(); + + if (diff == expect_size || (align & (8 * sizeof(void *) - 1)) || tail) + { + todo_wine + win_skip("skipping sizes\n"); + break; + } }
/* Undocumented HEAP_ADD_USER_INFO flag can be used to force an additional padding @@ -1899,10 +1909,9 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags
expect_size = max( alloc_size, 2 * sizeof(void *) ); expect_size = ALIGN_BLOCK_SIZE( expect_size + extra_size + 2 * sizeof(void *) ); - todo_wine_if( heap_flags & (HEAP_VALIDATE_PARAMS|HEAP_VALIDATE_ALL) || - (ptr2 - ptr1 != expect_size && ptr1 - ptr0 != expect_size) ) - ok( ptr2 - ptr1 == expect_size || ptr1 - ptr0 == expect_size, - "got diff %#Ix %#Ix\n", ptr2 - ptr1, ptr1 - ptr0 ); + diff = min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) ); + todo_wine + ok( diff == expect_size, "got diff %#Ix\n", diff );
ok( !memcmp( ptr0 + alloc_size, tail_buf, tail_size ), "missing block tail\n" ); ok( !memcmp( ptr1 + alloc_size, tail_buf, tail_size ), "missing block tail\n" ); @@ -1956,8 +1965,6 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags
user_ptr = (void **)(ptr0 + alloc_size + tail_size); todo_wine - ok( user_ptr[0] == 0, "unexpected padding\n" ); - todo_wine ok( user_ptr[1] == (void *)0xdeadbeef, "unexpected user value\n" ); if (user_ptr[1] == (void *)0xdeadbeef) {
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/heap.c | 202 ++++++++++++++++++++++++++++++++++++- 1 file changed, 201 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 586c9a1ed0b..d40549e999b 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -88,18 +88,76 @@ struct heap };
+struct heap_thread_params +{ + HANDLE ready_event; + HANDLE start_event; + BOOL done; + + HANDLE heap; + DWORD flags; + BOOL lock; +}; + +DWORD WINAPI heap_thread_proc( void *arg ) +{ + struct heap_thread_params *params = arg; + void *ptr; + DWORD res; + BOOL ret; + + SetEvent( params->ready_event ); + + while (!(res = WaitForSingleObject( params->start_event, INFINITE )) && !params->done) + { + if (params->lock) + { + ret = HeapLock( params->heap ); + ok( ret, "HeapLock failed, error %lu\n", GetLastError() ); + } + + ptr = HeapAlloc( params->heap, params->flags, 0 ); + ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() ); + ret = HeapFree( params->heap, params->flags, ptr ); + ok( ret, "HeapFree failed, error %lu\n", GetLastError() ); + + if (params->lock) + { + ret = HeapUnlock( params->heap ); + ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() ); + } + + SetEvent( params->ready_event ); + } + ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + + return 0; +} + + static void test_HeapCreate(void) { static const BYTE buffer[512] = {0}; SIZE_T alloc_size = 0x8000 * sizeof(void *), size, i; + struct heap_thread_params thread_params = {0}; PROCESS_HEAP_ENTRY entry, entries[256]; - HANDLE heap, heap1, heaps[8]; + HANDLE heap, heap1, heaps[8], thread; BYTE *ptr, *ptr1, *ptrs[128]; DWORD heap_count, count; ULONG compat_info; UINT_PTR align; + DWORD res; BOOL ret;
+ thread_params.ready_event = CreateEventW( NULL, FALSE, FALSE, NULL ); + ok( !!thread_params.ready_event, "CreateEventW failed, error %lu\n", GetLastError() ); + thread_params.start_event = CreateEventW( NULL, FALSE, FALSE, NULL ); + ok( !!thread_params.start_event, "CreateEventW failed, error %lu\n", GetLastError() ); + thread = CreateThread( NULL, 0, heap_thread_proc, &thread_params, 0, NULL ); + ok( !!thread, "CreateThread failed, error %lu\n", GetLastError() ); + res = WaitForSingleObject( thread_params.ready_event, INFINITE ); + ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + heap_count = GetProcessHeaps( 0, NULL ); ok( heap_count <= 6, "GetProcessHeaps returned %lu\n", heap_count );
@@ -879,6 +937,148 @@ static void test_HeapCreate(void)
ret = HeapDestroy( heap ); ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() ); + + + /* check HEAP_NO_SERIALIZE HeapCreate flag effect */ + + heap = HeapCreate( HEAP_NO_SERIALIZE, 0, 0 ); + ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() ); + ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" ); + + ret = HeapLock( heap ); + ok( ret, "HeapLock failed, error %lu\n", GetLastError() ); + thread_params.heap = heap; + thread_params.lock = TRUE; + thread_params.flags = 0; + SetEvent( thread_params.start_event ); + res = WaitForSingleObject( thread_params.ready_event, 100 ); + todo_wine + ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + ret = HeapUnlock( heap ); + ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() ); + if (res) WaitForSingleObject( thread_params.ready_event, 100 ); + + ret = HeapLock( heap ); + ok( ret, "HeapLock failed, error %lu\n", GetLastError() ); + thread_params.heap = heap; + thread_params.lock = FALSE; + thread_params.flags = 0; + SetEvent( thread_params.start_event ); + res = WaitForSingleObject( thread_params.ready_event, 100 ); + ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + ret = HeapUnlock( heap ); + ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() ); + + ret = HeapDestroy( heap ); + ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() ); + + + /* check HEAP_NO_SERIALIZE HeapAlloc / HeapFree flag effect */ + + heap = HeapCreate( 0, 0, 0 ); + ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() ); + ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" ); + + ret = HeapLock( heap ); + ok( ret, "HeapLock failed, error %lu\n", GetLastError() ); + thread_params.heap = heap; + thread_params.lock = TRUE; + thread_params.flags = 0; + SetEvent( thread_params.start_event ); + res = WaitForSingleObject( thread_params.ready_event, 100 ); + ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + ret = HeapUnlock( heap ); + ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() ); + res = WaitForSingleObject( thread_params.ready_event, 100 ); + ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + + ret = HeapLock( heap ); + ok( ret, "HeapLock failed, error %lu\n", GetLastError() ); + thread_params.heap = heap; + thread_params.lock = FALSE; + thread_params.flags = 0; + SetEvent( thread_params.start_event ); + res = WaitForSingleObject( thread_params.ready_event, 100 ); + ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + ret = HeapUnlock( heap ); + ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() ); + res = WaitForSingleObject( thread_params.ready_event, 100 ); + ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + + ret = HeapLock( heap ); + ok( ret, "HeapLock failed, error %lu\n", GetLastError() ); + thread_params.heap = heap; + thread_params.lock = FALSE; + thread_params.flags = HEAP_NO_SERIALIZE; + SetEvent( thread_params.start_event ); + res = WaitForSingleObject( thread_params.ready_event, 100 ); + ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + ret = HeapUnlock( heap ); + ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() ); + + ret = HeapDestroy( heap ); + ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() ); + + + /* check LFH heap locking */ + + heap = HeapCreate( 0, 0, 0 ); + ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() ); + ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" ); + + ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size ); + ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() ); + ok( compat_info == 0, "got HeapCompatibilityInformation %lu\n", compat_info ); + + for (i = 0; i < 0x12; i++) ptrs[i] = pHeapAlloc( heap, 0, 0 ); + for (i = 0; i < 0x12; i++) HeapFree( heap, 0, ptrs[i] ); + + ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size ); + ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() ); + todo_wine + ok( compat_info == 2, "got HeapCompatibilityInformation %lu\n", compat_info ); + + /* locking is serialized */ + + ret = HeapLock( heap ); + ok( ret, "HeapLock failed, error %lu\n", GetLastError() ); + thread_params.heap = heap; + thread_params.lock = TRUE; + thread_params.flags = 0; + SetEvent( thread_params.start_event ); + res = WaitForSingleObject( thread_params.ready_event, 100 ); + ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + ret = HeapUnlock( heap ); + ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() ); + res = WaitForSingleObject( thread_params.ready_event, 100 ); + ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + + /* but allocation is not */ + + ret = HeapLock( heap ); + ok( ret, "HeapLock failed, error %lu\n", GetLastError() ); + thread_params.heap = heap; + thread_params.lock = FALSE; + thread_params.flags = 0; + SetEvent( thread_params.start_event ); + res = WaitForSingleObject( thread_params.ready_event, 100 ); + todo_wine + ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + ret = HeapUnlock( heap ); + ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() ); + if (res) res = WaitForSingleObject( thread_params.ready_event, 100 ); + + ret = HeapDestroy( heap ); + ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() ); + + + thread_params.done = TRUE; + SetEvent( thread_params.start_event ); + res = WaitForSingleObject( thread, INFINITE ); + ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); + CloseHandle( thread_params.start_event ); + CloseHandle( thread_params.ready_event ); + CloseHandle( thread ); }
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/heap.c | 119 +++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 54 deletions(-)
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 7f41088347d..89f59440edf 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -162,7 +162,7 @@ typedef struct tagHEAP DWORD magic; /* Magic number */ DWORD pending_pos; /* Position in pending free requests ring */ ARENA_INUSE **pending_free; /* Ring buffer for pending free requests */ - RTL_CRITICAL_SECTION critSection; /* Critical section for serialization */ + RTL_CRITICAL_SECTION cs; FREE_LIST_ENTRY *freeList; /* Free lists */ } HEAP;
@@ -324,13 +324,30 @@ static inline ULONG get_protection_type( DWORD flags ) return (flags & HEAP_CREATE_ENABLE_EXECUTE) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; }
-static RTL_CRITICAL_SECTION_DEBUG process_heap_critsect_debug = +static RTL_CRITICAL_SECTION_DEBUG process_heap_cs_debug = { 0, 0, NULL, /* will be set later */ - { &process_heap_critsect_debug.ProcessLocksList, &process_heap_critsect_debug.ProcessLocksList }, + { &process_heap_cs_debug.ProcessLocksList, &process_heap_cs_debug.ProcessLocksList }, 0, 0, { (DWORD_PTR)(__FILE__ ": main process heap section") } };
+static inline ULONG heap_get_flags( const HEAP *heap, ULONG flags ) +{ + flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY; + return heap->flags | flags; +} + +static void heap_lock( HEAP *heap, ULONG flags ) +{ + if (heap_get_flags( heap, flags ) & HEAP_NO_SERIALIZE) return; + RtlEnterCriticalSection( &heap->cs ); +} + +static void heap_unlock( HEAP *heap, ULONG flags ) +{ + if (heap_get_flags( heap, flags ) & HEAP_NO_SERIALIZE) return; + RtlLeaveCriticalSection( &heap->cs ); +}
/*********************************************************************** * HEAP_Dump @@ -748,7 +765,7 @@ static void *allocate_large_block( HEAP *heap, DWORD flags, SIZE_T size ) /*********************************************************************** * free_large_block */ -static void free_large_block( HEAP *heap, DWORD flags, void *ptr ) +static void free_large_block( HEAP *heap, void *ptr ) { ARENA_LARGE *arena = (ARENA_LARGE *)ptr - 1; LPVOID address = arena; @@ -791,7 +808,7 @@ static void *realloc_large_block( HEAP *heap, DWORD flags, void *ptr, SIZE_T siz return NULL; } memcpy( new_ptr, ptr, arena->data_size ); - free_large_block( heap, flags, ptr ); + free_large_block( heap, ptr ); notify_free( ptr ); return new_ptr; } @@ -958,31 +975,31 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags,
if (!processHeap) /* do it by hand to avoid memory allocations */ { - heap->critSection.DebugInfo = &process_heap_critsect_debug; - heap->critSection.LockCount = -1; - heap->critSection.RecursionCount = 0; - heap->critSection.OwningThread = 0; - heap->critSection.LockSemaphore = 0; - heap->critSection.SpinCount = 0; - process_heap_critsect_debug.CriticalSection = &heap->critSection; + heap->cs.DebugInfo = &process_heap_cs_debug; + heap->cs.LockCount = -1; + heap->cs.RecursionCount = 0; + heap->cs.OwningThread = 0; + heap->cs.LockSemaphore = 0; + heap->cs.SpinCount = 0; + process_heap_cs_debug.CriticalSection = &heap->cs; } else { - RtlInitializeCriticalSection( &heap->critSection ); - heap->critSection.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": HEAP.critSection"); + RtlInitializeCriticalSection( &heap->cs ); + heap->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": heap.cs"); }
if (heap->shared) { /* let's assume that only one thread at a time will try to do this */ - HANDLE sem = heap->critSection.LockSemaphore; + HANDLE sem = heap->cs.LockSemaphore; if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
NtDuplicateObject( NtCurrentProcess(), sem, NtCurrentProcess(), &sem, 0, 0, DUPLICATE_MAKE_GLOBAL | DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE ); - heap->critSection.LockSemaphore = sem; - RtlFreeHeap( processHeap, 0, heap->critSection.DebugInfo ); - heap->critSection.DebugInfo = NULL; + heap->cs.LockSemaphore = sem; + RtlFreeHeap( processHeap, 0, heap->cs.DebugInfo ); + heap->cs.DebugInfo = NULL; } }
@@ -1339,11 +1356,7 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr, /* [in] ptr to the heap */ BOOL ret = FALSE; const ARENA_LARGE *large_arena;
- flags &= HEAP_NO_SERIALIZE; - flags |= heapPtr->flags; - /* calling HeapLock may result in infinite recursion, so do the critsect directly */ - if (!(flags & HEAP_NO_SERIALIZE)) - RtlEnterCriticalSection( &heapPtr->critSection ); + heap_lock( heapPtr, flags );
if (block) /* only check this single memory block */ { @@ -1389,7 +1402,7 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr, /* [in] ptr to the heap */ ret = TRUE;
done: - if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + heap_unlock( heapPtr, flags ); return ret; }
@@ -1569,9 +1582,9 @@ HANDLE WINAPI RtlCreateHeap( ULONG flags, PVOID addr, SIZE_T totalSize, SIZE_T c if (processHeap) { HEAP *heapPtr = subheap->heap; - RtlEnterCriticalSection( &processHeap->critSection ); + RtlEnterCriticalSection( &processHeap->cs ); list_add_head( &processHeap->entry, &heapPtr->entry ); - RtlLeaveCriticalSection( &processHeap->critSection ); + RtlLeaveCriticalSection( &processHeap->cs ); } else if (!addr) { @@ -1615,12 +1628,12 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap ) if (heap == processHeap) return heap; /* cannot delete the main process heap */
/* remove it from the per-process list */ - RtlEnterCriticalSection( &processHeap->critSection ); + RtlEnterCriticalSection( &processHeap->cs ); list_remove( &heapPtr->entry ); - RtlLeaveCriticalSection( &processHeap->critSection ); + RtlLeaveCriticalSection( &processHeap->cs );
- heapPtr->critSection.DebugInfo->Spare[0] = 0; - RtlDeleteCriticalSection( &heapPtr->critSection ); + heapPtr->cs.DebugInfo->Spare[0] = 0; + RtlDeleteCriticalSection( &heapPtr->cs );
LIST_FOR_EACH_ENTRY_SAFE( arena, arena_next, &heapPtr->large_list, ARENA_LARGE, entry ) { @@ -1685,12 +1698,12 @@ void * WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_ } if (rounded_size < HEAP_MIN_DATA_SIZE) rounded_size = HEAP_MIN_DATA_SIZE;
- if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); + heap_lock( heapPtr, flags );
if (rounded_size >= HEAP_MIN_LARGE_BLOCK_SIZE && (flags & HEAP_GROWABLE)) { void *ret = allocate_large_block( heap, flags, size ); - if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + heap_unlock( heapPtr, flags ); if (!ret && (flags & HEAP_GENERATE_EXCEPTIONS)) RtlRaiseStatus( STATUS_NO_MEMORY ); TRACE("(%p,%08x,%08lx): returning %p\n", heap, flags, size, ret ); return ret; @@ -1702,7 +1715,7 @@ void * WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_ { TRACE("(%p,%08x,%08lx): returning NULL\n", heap, flags, size ); - if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + heap_unlock( heapPtr, flags ); if (flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY ); return NULL; } @@ -1728,7 +1741,7 @@ void * WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_ notify_alloc( pInUse + 1, size, flags & HEAP_ZERO_MEMORY ); initialize_block( pInUse + 1, size, pInUse->unused_bytes, flags );
- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + heap_unlock( heapPtr, flags );
TRACE("(%p,%08x,%08lx): returning %p\n", heap, flags, size, pInUse + 1 ); return pInUse + 1; @@ -1766,9 +1779,7 @@ BOOLEAN WINAPI DECLSPEC_HOTPATCH RtlFreeHeap( HANDLE heap, ULONG flags, void *pt return FALSE; }
- flags &= HEAP_NO_SERIALIZE; - flags |= heapPtr->flags; - if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); + heap_lock( heapPtr, flags );
/* Inform valgrind we are trying to free memory, so it can throw up an error message */ notify_free( ptr ); @@ -1778,16 +1789,16 @@ BOOLEAN WINAPI DECLSPEC_HOTPATCH RtlFreeHeap( HANDLE heap, ULONG flags, void *pt if (!validate_block_pointer( heapPtr, &subheap, pInUse )) goto error;
if (!subheap) - free_large_block( heapPtr, flags, ptr ); + free_large_block( heapPtr, ptr ); else HEAP_MakeInUseBlockFree( subheap, pInUse );
- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + heap_unlock( heapPtr, flags ); TRACE("(%p,%08x,%p): returning TRUE\n", heap, flags, ptr ); return TRUE;
error: - if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + heap_unlock( heapPtr, flags ); RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER ); TRACE("(%p,%08x,%p): returning FALSE\n", heap, flags, ptr ); return FALSE; @@ -1829,7 +1840,7 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, SIZE_T size flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY | HEAP_REALLOC_IN_PLACE_ONLY; flags |= heapPtr->flags; - if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); + heap_lock( heapPtr, flags );
rounded_size = ROUND_SIZE(size) + HEAP_TAIL_EXTRA_SIZE(flags); if (rounded_size < size) goto oom; /* overflow */ @@ -1923,19 +1934,19 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, SIZE_T size
ret = pArena + 1; done: - if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + heap_unlock( heapPtr, flags ); TRACE("(%p,%08x,%p,%08lx): returning %p\n", heap, flags, ptr, size, ret ); return ret;
oom: - if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + heap_unlock( heapPtr, flags ); if (flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY ); RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_NO_MEMORY ); TRACE("(%p,%08x,%p,%08lx): returning NULL\n", heap, flags, ptr, size ); return NULL;
error: - if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + heap_unlock( heapPtr, flags ); RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER ); TRACE("(%p,%08x,%p,%08lx): returning NULL\n", heap, flags, ptr, size ); return NULL; @@ -1981,7 +1992,7 @@ BOOLEAN WINAPI RtlLockHeap( HANDLE heap ) { HEAP *heapPtr = HEAP_GetPtr( heap ); if (!heapPtr) return FALSE; - RtlEnterCriticalSection( &heapPtr->critSection ); + RtlEnterCriticalSection( &heapPtr->cs ); return TRUE; }
@@ -2002,7 +2013,7 @@ BOOLEAN WINAPI RtlUnlockHeap( HANDLE heap ) { HEAP *heapPtr = HEAP_GetPtr( heap ); if (!heapPtr) return FALSE; - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveCriticalSection( &heapPtr->cs ); return TRUE; }
@@ -2036,9 +2047,8 @@ SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr ) RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_HANDLE ); return ~(SIZE_T)0; } - flags &= HEAP_NO_SERIALIZE; - flags |= heapPtr->flags; - if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); + + heap_lock( heapPtr, flags );
pArena = (const ARENA_INUSE *)ptr - 1; if (!validate_block_pointer( heapPtr, &subheap, pArena )) @@ -2055,7 +2065,8 @@ SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr ) { ret = (pArena->size & ARENA_SIZE_MASK) - pArena->unused_bytes; } - if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + + heap_unlock( heapPtr, flags );
TRACE("(%p,%08x,%p): returning %08lx\n", heap, flags, ptr, ret ); return ret; @@ -2102,7 +2113,7 @@ NTSTATUS WINAPI RtlWalkHeap( HANDLE heap, PVOID entry_ptr )
if (!heapPtr || !entry) return STATUS_INVALID_PARAMETER;
- if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); + heap_lock( heapPtr, 0 );
/* FIXME: enumerate large blocks too */
@@ -2207,7 +2218,7 @@ NTSTATUS WINAPI RtlWalkHeap( HANDLE heap, PVOID entry_ptr ) if (TRACE_ON(heap)) HEAP_DumpEntry(entry);
HW_end: - if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + heap_unlock( heapPtr, 0 ); return ret; }
@@ -2230,7 +2241,7 @@ ULONG WINAPI RtlGetProcessHeaps( ULONG count, HANDLE *heaps ) ULONG total = 1; /* main heap */ struct list *ptr;
- RtlEnterCriticalSection( &processHeap->critSection ); + RtlEnterCriticalSection( &processHeap->cs ); LIST_FOR_EACH( ptr, &processHeap->entry ) total++; if (total <= count) { @@ -2238,7 +2249,7 @@ ULONG WINAPI RtlGetProcessHeaps( ULONG count, HANDLE *heaps ) LIST_FOR_EACH( ptr, &processHeap->entry ) *heaps++ = LIST_ENTRY( ptr, HEAP, entry ); } - RtlLeaveCriticalSection( &processHeap->critSection ); + RtlLeaveCriticalSection( &processHeap->cs ); return total; }
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/heap.c | 2 -- dlls/ntdll/heap.c | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index d40549e999b..4f808c8c7e6 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -952,11 +952,9 @@ static void test_HeapCreate(void) thread_params.flags = 0; SetEvent( thread_params.start_event ); res = WaitForSingleObject( thread_params.ready_event, 100 ); - todo_wine ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() ); ret = HeapUnlock( heap ); ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() ); - if (res) WaitForSingleObject( thread_params.ready_event, 100 );
ret = HeapLock( heap ); ok( ret, "HeapLock failed, error %lu\n", GetLastError() ); diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 89f59440edf..1aa064723a8 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -1992,7 +1992,7 @@ BOOLEAN WINAPI RtlLockHeap( HANDLE heap ) { HEAP *heapPtr = HEAP_GetPtr( heap ); if (!heapPtr) return FALSE; - RtlEnterCriticalSection( &heapPtr->cs ); + heap_lock( heapPtr, 0 ); return TRUE; }
@@ -2013,7 +2013,7 @@ BOOLEAN WINAPI RtlUnlockHeap( HANDLE heap ) { HEAP *heapPtr = HEAP_GetPtr( heap ); if (!heapPtr) return FALSE; - RtlLeaveCriticalSection( &heapPtr->cs ); + heap_unlock( heapPtr, 0 ); return TRUE; }
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/heap.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 4f808c8c7e6..f437a13a63e 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -2435,7 +2435,9 @@ static void test_heap_layout( HANDLE handle, DWORD global_flag, DWORD heap_flags if (global_flag & FLG_HEAP_ENABLE_TAGGING) heap_flags |= HEAP_SHARED; if (!(global_flag & FLG_HEAP_PAGE_ALLOCS)) force_flags &= ~(HEAP_GROWABLE|HEAP_PRIVATE);
+ todo_wine_if( (heap->force_flags & ~heap_flags) & (HEAP_TAIL_CHECKING_ENABLED|HEAP_FREE_CHECKING_ENABLED) ) ok( heap->force_flags == force_flags, "got force_flags %#x\n", heap->force_flags ); + todo_wine_if( (heap->flags & ~heap_flags) & (HEAP_TAIL_CHECKING_ENABLED|HEAP_FREE_CHECKING_ENABLED) ) ok( heap->flags == heap_flags, "got flags %#x\n", heap->flags );
if (heap->flags & HEAP_PAGE_ALLOCS) @@ -2508,6 +2510,12 @@ static void test_child_heap( const char *arg ) ret = HeapDestroy( heap ); ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
+ heap = HeapCreate( HEAP_TAIL_CHECKING_ENABLED|HEAP_FREE_CHECKING_ENABLED|HEAP_NO_SERIALIZE, 0, 0 ); + ok( heap != GetProcessHeap(), "got unexpected heap\n" ); + test_heap_layout( heap, global_flags, heap_flags|HEAP_NO_SERIALIZE|HEAP_GROWABLE|HEAP_PRIVATE ); + ret = HeapDestroy( heap ); + ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() ); + heap = HeapCreate( 0, 0x1000, 0x10000 ); ok( heap != GetProcessHeap(), "got unexpected heap\n" ); test_heap_layout( heap, global_flags, heap_flags|HEAP_PRIVATE );
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/heap.c | 2 -- dlls/ntdll/heap.c | 1 + 2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index f437a13a63e..5b7b0aacfc0 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -2435,9 +2435,7 @@ static void test_heap_layout( HANDLE handle, DWORD global_flag, DWORD heap_flags if (global_flag & FLG_HEAP_ENABLE_TAGGING) heap_flags |= HEAP_SHARED; if (!(global_flag & FLG_HEAP_PAGE_ALLOCS)) force_flags &= ~(HEAP_GROWABLE|HEAP_PRIVATE);
- todo_wine_if( (heap->force_flags & ~heap_flags) & (HEAP_TAIL_CHECKING_ENABLED|HEAP_FREE_CHECKING_ENABLED) ) ok( heap->force_flags == force_flags, "got force_flags %#x\n", heap->force_flags ); - todo_wine_if( (heap->flags & ~heap_flags) & (HEAP_TAIL_CHECKING_ENABLED|HEAP_FREE_CHECKING_ENABLED) ) ok( heap->flags == heap_flags, "got flags %#x\n", heap->flags );
if (heap->flags & HEAP_PAGE_ALLOCS) diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 1aa064723a8..d7ac44a4247 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -1570,6 +1570,7 @@ HANDLE WINAPI RtlCreateHeap( ULONG flags, PVOID addr, SIZE_T totalSize, SIZE_T c
/* Allocate the heap block */
+ flags &= ~(HEAP_TAIL_CHECKING_ENABLED|HEAP_FREE_CHECKING_ENABLED); if (processHeap) flags |= HEAP_PRIVATE; if (!processHeap || !totalSize || (flags & HEAP_SHARED)) flags |= HEAP_GROWABLE; if (!totalSize) totalSize = HEAP_DEF_SIZE;
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/heap.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 5b7b0aacfc0..83705b2b288 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -1957,7 +1957,7 @@ static void test_LocalAlloc(void) } }
-static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags ) +static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags, DWORD alloc_flags ) { DWORD padd_flags = HEAP_VALIDATE | HEAP_VALIDATE_ALL | HEAP_VALIDATE_PARAMS; SIZE_T expect_size, diff, alloc_size, extra_size, tail_size = 0; @@ -1975,7 +1975,7 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags return; }
- if (!global_flags) extra_size = 8; + if (!global_flags && !alloc_flags) extra_size = 8; else extra_size = 2 * sizeof(void *); if (heap_flags & HEAP_TAIL_CHECKING_ENABLED) extra_size += 2 * sizeof(void *); if (heap_flags & padd_flags) extra_size += 2 * sizeof(void *); @@ -1988,11 +1988,11 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags { winetest_push_context( "size %#Ix", alloc_size );
- ptr0 = pHeapAlloc( heap, HEAP_ZERO_MEMORY, alloc_size ); + ptr0 = pHeapAlloc( heap, alloc_flags|HEAP_ZERO_MEMORY, alloc_size ); ok( !!ptr0, "HeapAlloc failed, error %lu\n", GetLastError() ); - ptr1 = pHeapAlloc( heap, HEAP_ZERO_MEMORY, alloc_size ); + ptr1 = pHeapAlloc( heap, alloc_flags|HEAP_ZERO_MEMORY, alloc_size ); ok( !!ptr1, "HeapAlloc failed, error %lu\n", GetLastError() ); - ptr2 = pHeapAlloc( heap, HEAP_ZERO_MEMORY, alloc_size ); + ptr2 = pHeapAlloc( heap, alloc_flags|HEAP_ZERO_MEMORY, alloc_size ); ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
align = (UINT_PTR)ptr0 | (UINT_PTR)ptr1 | (UINT_PTR)ptr2; @@ -2034,7 +2034,7 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags alloc_size = 0x20000 * sizeof(void *) - 0x2000; winetest_push_context( "size %#Ix", alloc_size );
- ptr0 = pHeapAlloc( heap, HEAP_ZERO_MEMORY, alloc_size ); + ptr0 = pHeapAlloc( heap, alloc_flags|HEAP_ZERO_MEMORY, alloc_size ); ok( !!ptr0, "HeapAlloc failed, error %lu\n", GetLastError() ); ok( !((UINT_PTR)ptr0 & (2 * sizeof(void *) - 1)), "got unexpected ptr align\n" );
@@ -2050,11 +2050,11 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags { winetest_push_context( "size %#Ix", alloc_size );
- ptr0 = pHeapAlloc( heap, HEAP_ZERO_MEMORY, alloc_size ); + ptr0 = pHeapAlloc( heap, alloc_flags|HEAP_ZERO_MEMORY, alloc_size ); ok( !!ptr0, "HeapAlloc failed, error %lu\n", GetLastError() ); - ptr1 = pHeapAlloc( heap, 0, alloc_size ); + ptr1 = pHeapAlloc( heap, alloc_flags, alloc_size ); ok( !!ptr1, "HeapAlloc failed, error %lu\n", GetLastError() ); - ptr2 = pHeapAlloc( heap, 0, alloc_size ); + ptr2 = pHeapAlloc( heap, alloc_flags, alloc_size ); ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
align = (UINT_PTR)ptr0 | (UINT_PTR)ptr1 | (UINT_PTR)ptr2; @@ -2504,7 +2504,7 @@ static void test_child_heap( const char *arg ) heap = HeapCreate( HEAP_NO_SERIALIZE, 0, 0 ); ok( heap != GetProcessHeap(), "got unexpected heap\n" ); test_heap_layout( heap, global_flags, heap_flags|HEAP_NO_SERIALIZE|HEAP_GROWABLE|HEAP_PRIVATE ); - test_block_layout( heap, global_flags, heap_flags|HEAP_NO_SERIALIZE|HEAP_GROWABLE|HEAP_PRIVATE ); + test_block_layout( heap, global_flags, heap_flags|HEAP_NO_SERIALIZE|HEAP_GROWABLE|HEAP_PRIVATE, 0 ); ret = HeapDestroy( heap ); ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
@@ -2514,6 +2514,13 @@ static void test_child_heap( const char *arg ) ret = HeapDestroy( heap ); ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
+ heap = HeapCreate( HEAP_NO_SERIALIZE, 0, 0 ); + ok( heap != GetProcessHeap(), "got unexpected heap\n" ); + test_block_layout( heap, global_flags, heap_flags|HEAP_NO_SERIALIZE|HEAP_GROWABLE|HEAP_PRIVATE, + HEAP_TAIL_CHECKING_ENABLED|HEAP_FREE_CHECKING_ENABLED ); + ret = HeapDestroy( heap ); + ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() ); + heap = HeapCreate( 0, 0x1000, 0x10000 ); ok( heap != GetProcessHeap(), "got unexpected heap\n" ); test_heap_layout( heap, global_flags, heap_flags|HEAP_PRIVATE );
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/heap.c | 262 ++++++++++++++++++++++++++++++++++++- 1 file changed, 259 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 83705b2b288..b039bf524b2 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -88,6 +88,39 @@ struct heap };
+/* undocumented RtlWalkHeap structure */ + +struct rtl_heap_entry +{ + LPVOID lpData; + SIZE_T cbData; /* differs from PROCESS_HEAP_ENTRY */ + BYTE cbOverhead; + BYTE iRegionIndex; + WORD wFlags; /* value differs from PROCESS_HEAP_ENTRY */ + union { + struct { + HANDLE hMem; + DWORD dwReserved[3]; + } Block; + struct { + DWORD dwCommittedSize; + DWORD dwUnCommittedSize; + LPVOID lpFirstBlock; + LPVOID lpLastBlock; + } Region; + }; +}; + +/* rtl_heap_entry flags, names made up */ + +#define RTL_HEAP_ENTRY_BUSY 0x0001 +#define RTL_HEAP_ENTRY_REGION 0x0002 +#define RTL_HEAP_ENTRY_BLOCK 0x0010 +#define RTL_HEAP_ENTRY_UNCOMMITTED 0x1000 +#define RTL_HEAP_ENTRY_COMMITTED 0x4000 +#define RTL_HEAP_ENTRY_LFH 0x8000 + + struct heap_thread_params { HANDLE ready_event; @@ -139,6 +172,7 @@ static void test_HeapCreate(void) { static const BYTE buffer[512] = {0}; SIZE_T alloc_size = 0x8000 * sizeof(void *), size, i; + struct rtl_heap_entry rtl_entry, rtl_entries[256]; struct heap_thread_params thread_params = {0}; PROCESS_HEAP_ENTRY entry, entries[256]; HANDLE heap, heap1, heaps[8], thread; @@ -484,6 +518,15 @@ static void test_HeapCreate(void) ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() ); ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
+ count = 0; + memset( &rtl_entries, 0, sizeof(rtl_entries) ); + memset( &rtl_entry, 0xcd, sizeof(rtl_entry) ); + rtl_entry.lpData = NULL; + SetLastError( 0xdeadbeef ); + while (!RtlWalkHeap( heap, &rtl_entry )) rtl_entries[count++] = rtl_entry; + todo_wine + ok( count == 3, "got count %lu\n", count ); + count = 0; memset( &entries, 0, sizeof(entries) ); memset( &entry, 0xcd, sizeof(entry) ); @@ -494,6 +537,41 @@ static void test_HeapCreate(void) todo_wine ok( count == 3, "got count %lu\n", count );
+ for (i = 0; i < count; ++i) + { + winetest_push_context( "%Iu", i ); + ok( rtl_entries[i].lpData == entries[i].lpData, "got lpData %p\n", rtl_entries[i].lpData ); + todo_wine_if(sizeof(void *) == 8) + ok( rtl_entries[i].cbData == entries[i].cbData, "got cbData %#Ix\n", rtl_entries[i].cbData ); + todo_wine_if(sizeof(void *) == 8) + ok( rtl_entries[i].cbOverhead == entries[i].cbOverhead, "got cbOverhead %#x\n", rtl_entries[i].cbOverhead ); + ok( rtl_entries[i].iRegionIndex == entries[i].iRegionIndex, "got iRegionIndex %#x\n", rtl_entries[i].iRegionIndex ); + if (!entries[i].wFlags) + ok( rtl_entries[i].wFlags == 0, "got wFlags %#x\n", rtl_entries[i].wFlags ); + else if (entries[i].wFlags & PROCESS_HEAP_ENTRY_BUSY) + ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_COMMITTED|RTL_HEAP_ENTRY_BLOCK|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 0x411) /* win7 */, + "got wFlags %#x\n", rtl_entries[i].wFlags ); + else if (entries[i].wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) + { + todo_wine + ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_UNCOMMITTED || broken(rtl_entries[i].wFlags == 0x100) /* win7 */, + "got wFlags %#x\n", rtl_entries[i].wFlags ); + } + else if (entries[i].wFlags & PROCESS_HEAP_REGION) + { + ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_REGION, "got wFlags %#x\n", rtl_entries[i].wFlags ); + ok( rtl_entries[i].Region.dwCommittedSize == entries[i].Region.dwCommittedSize, + "got Region.dwCommittedSize %#lx\n", rtl_entries[i].Region.dwCommittedSize ); + ok( rtl_entries[i].Region.dwUnCommittedSize == entries[i].Region.dwUnCommittedSize, + "got Region.dwUnCommittedSize %#lx\n", rtl_entries[i].Region.dwUnCommittedSize ); + ok( rtl_entries[i].Region.lpFirstBlock == entries[i].Region.lpFirstBlock, + "got Region.lpFirstBlock %p\n", rtl_entries[i].Region.lpFirstBlock ); + ok( rtl_entries[i].Region.lpLastBlock == entries[i].Region.lpLastBlock, + "got Region.lpLastBlock %p\n", rtl_entries[i].Region.lpLastBlock ); + } + winetest_pop_context(); + } + todo_wine ok( entries[0].wFlags == PROCESS_HEAP_REGION, "got wFlags %#x\n", entries[0].wFlags ); todo_wine @@ -524,7 +602,7 @@ static void test_HeapCreate(void) todo_wine ok( entries[1].cbData != 0, "got cbData %#lx\n", entries[1].cbData ); todo_wine - ok( entries[1].cbOverhead != 0, "got cbOverhead %#x\n", entries[1].cbOverhead ); + ok( entries[1].cbOverhead == 4 * sizeof(void *), "got cbOverhead %#x\n", entries[1].cbOverhead ); ok( entries[1].iRegionIndex == 0, "got iRegionIndex %d\n", entries[1].iRegionIndex );
todo_wine @@ -544,6 +622,15 @@ static void test_HeapCreate(void) ptr = HeapAlloc( heap, HEAP_ZERO_MEMORY, 5 * alloc_size ); ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
+ count = 0; + memset( &rtl_entries, 0, sizeof(rtl_entries) ); + memset( &rtl_entry, 0xcd, sizeof(rtl_entry) ); + rtl_entry.lpData = NULL; + SetLastError( 0xdeadbeef ); + while (!RtlWalkHeap( heap, &rtl_entry )) rtl_entries[count++] = rtl_entry; + todo_wine + ok( count == 4, "got count %lu\n", count ); + memmove( entries + 16, entries, 3 * sizeof(entry) ); count = 0; memset( &entry, 0xcd, sizeof(entry) ); @@ -555,6 +642,41 @@ static void test_HeapCreate(void) ok( count == 4, "got count %lu\n", count ); ok( !memcmp( entries + 16, entries, 3 * sizeof(entry) ), "entries differ\n" );
+ for (i = 0; i < count; ++i) + { + winetest_push_context( "%Iu", i ); + ok( rtl_entries[i].lpData == entries[i].lpData, "got lpData %p\n", rtl_entries[i].lpData ); + todo_wine_if(sizeof(void *) == 8) + ok( rtl_entries[i].cbData == entries[i].cbData, "got cbData %#Ix\n", rtl_entries[i].cbData ); + todo_wine_if(sizeof(void *) == 8) + ok( rtl_entries[i].cbOverhead == entries[i].cbOverhead, "got cbOverhead %#x\n", rtl_entries[i].cbOverhead ); + ok( rtl_entries[i].iRegionIndex == entries[i].iRegionIndex, "got iRegionIndex %#x\n", rtl_entries[i].iRegionIndex ); + if (!entries[i].wFlags) + ok( rtl_entries[i].wFlags == 0, "got wFlags %#x\n", rtl_entries[i].wFlags ); + else if (entries[i].wFlags & PROCESS_HEAP_ENTRY_BUSY) + ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_COMMITTED|RTL_HEAP_ENTRY_BLOCK|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 0x411) /* win7 */, + "got wFlags %#x\n", rtl_entries[i].wFlags ); + else if (entries[i].wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) + { + todo_wine + ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_UNCOMMITTED || broken(rtl_entries[i].wFlags == 0x100) /* win7 */, + "got wFlags %#x\n", rtl_entries[i].wFlags ); + } + else if (entries[i].wFlags & PROCESS_HEAP_REGION) + { + ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_REGION, "got wFlags %#x\n", rtl_entries[i].wFlags ); + ok( rtl_entries[i].Region.dwCommittedSize == entries[i].Region.dwCommittedSize, + "got Region.dwCommittedSize %#lx\n", rtl_entries[i].Region.dwCommittedSize ); + ok( rtl_entries[i].Region.dwUnCommittedSize == entries[i].Region.dwUnCommittedSize, + "got Region.dwUnCommittedSize %#lx\n", rtl_entries[i].Region.dwUnCommittedSize ); + ok( rtl_entries[i].Region.lpFirstBlock == entries[i].Region.lpFirstBlock, + "got Region.lpFirstBlock %p\n", rtl_entries[i].Region.lpFirstBlock ); + ok( rtl_entries[i].Region.lpLastBlock == entries[i].Region.lpLastBlock, + "got Region.lpLastBlock %p\n", rtl_entries[i].Region.lpLastBlock ); + } + winetest_pop_context(); + } + todo_wine ok( entries[3].wFlags == PROCESS_HEAP_ENTRY_BUSY || broken(entries[3].wFlags == (PROCESS_HEAP_ENTRY_BUSY | PROCESS_HEAP_ENTRY_DDESHARE)) /* win7 */, @@ -571,6 +693,15 @@ static void test_HeapCreate(void) ptr1 = HeapAlloc( heap, HEAP_ZERO_MEMORY, 5 * alloc_size ); ok( !!ptr1, "HeapAlloc failed, error %lu\n", GetLastError() );
+ count = 0; + memset( &rtl_entries, 0, sizeof(rtl_entries) ); + memset( &rtl_entry, 0xcd, sizeof(rtl_entry) ); + rtl_entry.lpData = NULL; + SetLastError( 0xdeadbeef ); + while (!RtlWalkHeap( heap, &rtl_entry )) rtl_entries[count++] = rtl_entry; + todo_wine + ok( count == 5, "got count %lu\n", count ); + memmove( entries + 16, entries, 4 * sizeof(entry) ); count = 0; memset( &entry, 0xcd, sizeof(entry) ); @@ -582,6 +713,41 @@ static void test_HeapCreate(void) ok( count == 5, "got count %lu\n", count ); ok( !memcmp( entries + 16, entries, 4 * sizeof(entry) ), "entries differ\n" );
+ for (i = 0; i < count; ++i) + { + winetest_push_context( "%Iu", i ); + ok( rtl_entries[i].lpData == entries[i].lpData, "got lpData %p\n", rtl_entries[i].lpData ); + todo_wine_if(sizeof(void *) == 8) + ok( rtl_entries[i].cbData == entries[i].cbData, "got cbData %#Ix\n", rtl_entries[i].cbData ); + todo_wine_if(sizeof(void *) == 8) + ok( rtl_entries[i].cbOverhead == entries[i].cbOverhead, "got cbOverhead %#x\n", rtl_entries[i].cbOverhead ); + ok( rtl_entries[i].iRegionIndex == entries[i].iRegionIndex, "got iRegionIndex %#x\n", rtl_entries[i].iRegionIndex ); + if (!entries[i].wFlags) + ok( rtl_entries[i].wFlags == 0, "got wFlags %#x\n", rtl_entries[i].wFlags ); + else if (entries[i].wFlags & PROCESS_HEAP_ENTRY_BUSY) + ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_COMMITTED|RTL_HEAP_ENTRY_BLOCK|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 0x411) /* win7 */, + "got wFlags %#x\n", rtl_entries[i].wFlags ); + else if (entries[i].wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) + { + todo_wine + ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_UNCOMMITTED || broken(rtl_entries[i].wFlags == 0x100) /* win7 */, + "got wFlags %#x\n", rtl_entries[i].wFlags ); + } + else if (entries[i].wFlags & PROCESS_HEAP_REGION) + { + ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_REGION, "got wFlags %#x\n", rtl_entries[i].wFlags ); + ok( rtl_entries[i].Region.dwCommittedSize == entries[i].Region.dwCommittedSize, + "got Region.dwCommittedSize %#lx\n", rtl_entries[i].Region.dwCommittedSize ); + ok( rtl_entries[i].Region.dwUnCommittedSize == entries[i].Region.dwUnCommittedSize, + "got Region.dwUnCommittedSize %#lx\n", rtl_entries[i].Region.dwUnCommittedSize ); + ok( rtl_entries[i].Region.lpFirstBlock == entries[i].Region.lpFirstBlock, + "got Region.lpFirstBlock %p\n", rtl_entries[i].Region.lpFirstBlock ); + ok( rtl_entries[i].Region.lpLastBlock == entries[i].Region.lpLastBlock, + "got Region.lpLastBlock %p\n", rtl_entries[i].Region.lpLastBlock ); + } + winetest_pop_context(); + } + todo_wine ok( entries[4].wFlags == PROCESS_HEAP_ENTRY_BUSY || broken(entries[4].wFlags == (PROCESS_HEAP_ENTRY_BUSY | PROCESS_HEAP_ENTRY_DDESHARE)) /* win7 */, @@ -644,7 +810,7 @@ static void test_HeapCreate(void) todo_wine ok( entries[2].cbData != 0, "got cbData %#lx\n", entries[2].cbData ); todo_wine - ok( entries[2].cbOverhead != 0, "got cbOverhead %#x\n", entries[2].cbOverhead ); + ok( entries[2].cbOverhead == 4 * sizeof(void *), "got cbOverhead %#x\n", entries[2].cbOverhead ); ok( entries[2].iRegionIndex == 0, "got iRegionIndex %d\n", entries[2].iRegionIndex );
todo_wine @@ -694,7 +860,7 @@ static void test_HeapCreate(void) todo_wine ok( entries[3].cbData != 0, "got cbData %#lx\n", entries[3].cbData ); todo_wine - ok( entries[3].cbOverhead != 0, "got cbOverhead %#x\n", entries[3].cbOverhead ); + ok( entries[3].cbOverhead == 4 * sizeof(void *), "got cbOverhead %#x\n", entries[3].cbOverhead ); ok( entries[3].iRegionIndex == 0, "got iRegionIndex %d\n", entries[3].iRegionIndex );
todo_wine @@ -897,6 +1063,48 @@ static void test_HeapCreate(void) ok( entries[count - 1].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[count - 2].wFlags ); }
+ count = 0; + memset( &rtl_entries, 0, sizeof(rtl_entries) ); + memset( &rtl_entry, 0xcd, sizeof(rtl_entry) ); + rtl_entry.lpData = NULL; + SetLastError( 0xdeadbeef ); + while (!RtlWalkHeap( heap, &rtl_entry )) rtl_entries[count++] = rtl_entry; + todo_wine + ok( count > 24, "got count %lu\n", count ); + if (count < 2) count = 2; + + for (i = 3; i < count; ++i) + { + winetest_push_context( "%Iu", i ); + ok( rtl_entries[i].lpData == entries[i].lpData, "got lpData %p\n", rtl_entries[i].lpData ); + todo_wine_if(sizeof(void *) == 8) + ok( rtl_entries[i].cbData == entries[i].cbData, "got cbData %#Ix\n", rtl_entries[i].cbData ); + todo_wine_if(sizeof(void *) == 8) + ok( rtl_entries[i].cbOverhead == entries[i].cbOverhead, "got cbOverhead %#x\n", rtl_entries[i].cbOverhead ); + ok( rtl_entries[i].iRegionIndex == entries[i].iRegionIndex, "got iRegionIndex %#x\n", rtl_entries[i].iRegionIndex ); + if (!entries[i].wFlags) + ok( rtl_entries[i].wFlags == 0 || rtl_entries[i].wFlags == RTL_HEAP_ENTRY_LFH, "got wFlags %#x\n", rtl_entries[i].wFlags ); + else if (entries[i].wFlags & PROCESS_HEAP_ENTRY_BUSY) + ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_LFH|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 1) /* win7 */, + "got wFlags %#x\n", rtl_entries[i].wFlags ); + else if (entries[i].wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) + ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_UNCOMMITTED || broken(rtl_entries[i].wFlags == 0x100) /* win7 */, + "got wFlags %#x\n", rtl_entries[i].wFlags ); + else if (entries[i].wFlags & PROCESS_HEAP_REGION) + { + ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_LFH|RTL_HEAP_ENTRY_REGION), "got wFlags %#x\n", rtl_entries[i].wFlags ); + ok( rtl_entries[i].Region.dwCommittedSize == entries[i].Region.dwCommittedSize, + "got Region.dwCommittedSize %#lx\n", rtl_entries[i].Region.dwCommittedSize ); + ok( rtl_entries[i].Region.dwUnCommittedSize == entries[i].Region.dwUnCommittedSize, + "got Region.dwUnCommittedSize %#lx\n", rtl_entries[i].Region.dwUnCommittedSize ); + ok( rtl_entries[i].Region.lpFirstBlock == entries[i].Region.lpFirstBlock, + "got Region.lpFirstBlock %p\n", rtl_entries[i].Region.lpFirstBlock ); + ok( rtl_entries[i].Region.lpLastBlock == entries[i].Region.lpLastBlock, + "got Region.lpLastBlock %p\n", rtl_entries[i].Region.lpLastBlock ); + } + winetest_pop_context(); + } + for (i = 0; i < 0x12; i++) ptrs[i] = pHeapAlloc( heap, 0, 24 + 2 * sizeof(void *) );
count = 0; @@ -933,6 +1141,54 @@ static void test_HeapCreate(void) else ok( entries[count - 1].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[count - 2].wFlags );
+ count = 0; + memset( &rtl_entries, 0, sizeof(rtl_entries) ); + memset( &rtl_entry, 0xcd, sizeof(rtl_entry) ); + rtl_entry.lpData = NULL; + SetLastError( 0xdeadbeef ); + while (!RtlWalkHeap( heap, &rtl_entry )) rtl_entries[count++] = rtl_entry; + todo_wine + ok( count > 24, "got count %lu\n", count ); + if (count < 2) count = 2; + + for (i = 3; i < count; ++i) + { + winetest_push_context( "%Iu", i ); + ok( rtl_entries[i].lpData == entries[i].lpData, "got lpData %p\n", rtl_entries[i].lpData ); + todo_wine_if(sizeof(void *) == 8) + ok( rtl_entries[i].cbData == entries[i].cbData, "got cbData %#Ix\n", rtl_entries[i].cbData ); + todo_wine_if(sizeof(void *) == 8) + ok( rtl_entries[i].cbOverhead == entries[i].cbOverhead, "got cbOverhead %#x\n", rtl_entries[i].cbOverhead ); + ok( rtl_entries[i].iRegionIndex == entries[i].iRegionIndex, "got iRegionIndex %#x\n", rtl_entries[i].iRegionIndex ); + if (!entries[i].wFlags) + ok( rtl_entries[i].wFlags == 0 || rtl_entries[i].wFlags == RTL_HEAP_ENTRY_LFH, "got wFlags %#x\n", rtl_entries[i].wFlags ); + else if (entries[i].wFlags & PROCESS_HEAP_ENTRY_BUSY) + { + todo_wine + ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_LFH|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 1) /* win7 */, + "got wFlags %#x\n", rtl_entries[i].wFlags ); + } + else if (entries[i].wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) + { + todo_wine + ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_UNCOMMITTED || broken(rtl_entries[i].wFlags == 0x100) /* win7 */, + "got wFlags %#x\n", rtl_entries[i].wFlags ); + } + else if (entries[i].wFlags & PROCESS_HEAP_REGION) + { + ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_LFH|RTL_HEAP_ENTRY_REGION), "got wFlags %#x\n", rtl_entries[i].wFlags ); + ok( rtl_entries[i].Region.dwCommittedSize == entries[i].Region.dwCommittedSize, + "got Region.dwCommittedSize %#lx\n", rtl_entries[i].Region.dwCommittedSize ); + ok( rtl_entries[i].Region.dwUnCommittedSize == entries[i].Region.dwUnCommittedSize, + "got Region.dwUnCommittedSize %#lx\n", rtl_entries[i].Region.dwUnCommittedSize ); + ok( rtl_entries[i].Region.lpFirstBlock == entries[i].Region.lpFirstBlock, + "got Region.lpFirstBlock %p\n", rtl_entries[i].Region.lpFirstBlock ); + ok( rtl_entries[i].Region.lpLastBlock == entries[i].Region.lpLastBlock, + "got Region.lpLastBlock %p\n", rtl_entries[i].Region.lpLastBlock ); + } + winetest_pop_context(); + } + for (i = 0; i < 0x12; i++) HeapFree( heap, 0, ptrs[i] );
ret = HeapDestroy( heap );