From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53741 --- dlls/kernel32/tests/heap.c | 14 -------------- dlls/ntdll/heap.c | 20 ++++++++++++++++---- 2 files changed, 16 insertions(+), 18 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 526a898209d..7cecc4a319a 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -1411,7 +1411,6 @@ static void test_GlobalAlloc(void) ret = pRtlGetUserInfoHeap( GetProcessHeap(), 0, entry->ptr, (void **)&tmp_mem, &tmp_flags ); ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() ); ok( tmp_mem == mem, "got user ptr %p\n", tmp_mem ); - todo_wine ok( tmp_flags == 0x200, "got user flags %#lx\n", tmp_flags );
ret = pRtlSetUserValueHeap( GetProcessHeap(), 0, entry->ptr, invalid_mem ); @@ -1568,7 +1567,6 @@ static void test_GlobalAlloc(void) SetLastError( 0xdeadbeef ); tmp_mem = GlobalHandle( mem ); ok( !tmp_mem, "GlobalHandle succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() ); }
@@ -1603,13 +1601,10 @@ static void test_GlobalAlloc(void) SetLastError( 0xdeadbeef ); tmp_mem = GlobalHandle( invalid_mem ); ok( !tmp_mem, "GlobalHandle succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() ); SetLastError( 0xdeadbeef ); ret = pRtlGetUserInfoHeap( GetProcessHeap(), 0, invalid_mem, (void **)&tmp_ptr, &tmp_flags ); - todo_wine ok( !ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() ); - todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); }
@@ -1647,7 +1642,6 @@ static void test_GlobalAlloc(void) SetLastError( 0xdeadbeef ); tmp_mem = GlobalHandle( invalid_ptr ); ok( !tmp_mem, "GlobalHandle succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() ); if (0) /* crashes */ { @@ -1819,13 +1813,11 @@ static void test_GlobalAlloc(void) SetLastError( 0xdeadbeef ); tmp_mem = GlobalHandle( ptr ); ok( !!tmp_mem, "GlobalHandle failed, error %lu\n", GetLastError() ); - todo_wine ok( tmp_mem == ptr, "GlobalHandle returned unexpected handle\n" ); tmp_ptr = (void *)0xdeadbeef; tmp_flags = 0xdeadbeef; ret = pRtlGetUserInfoHeap( GetProcessHeap(), 0, ptr, (void **)&tmp_ptr, &tmp_flags ); ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() ); - todo_wine ok( tmp_ptr == (void *)0xdeadbeef, "got user value %p\n", tmp_ptr ); ok( tmp_flags == 0, "got user flags %#lx\n", tmp_flags ); ret = HeapFree( GetProcessHeap(), 0, ptr ); @@ -1971,7 +1963,6 @@ static void test_LocalAlloc(void) SetLastError( 0xdeadbeef ); tmp_mem = LocalHandle( mem ); ok( !tmp_mem, "LocalHandle succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() ); }
@@ -2005,7 +1996,6 @@ static void test_LocalAlloc(void) SetLastError( 0xdeadbeef ); tmp_mem = LocalHandle( invalid_mem ); ok( !tmp_mem, "LocalHandle succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() ); }
@@ -2186,13 +2176,11 @@ static void test_LocalAlloc(void) SetLastError( 0xdeadbeef ); tmp_mem = LocalHandle( ptr ); ok( !!tmp_mem, "LocalHandle failed, error %lu\n", GetLastError() ); - todo_wine ok( tmp_mem == ptr, "LocalHandle returned unexpected handle\n" ); tmp_ptr = (void *)0xdeadbeef; tmp_flags = 0xdeadbeef; ret = pRtlGetUserInfoHeap( GetProcessHeap(), 0, ptr, (void **)&tmp_ptr, &tmp_flags ); ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() ); - todo_wine ok( tmp_ptr == (void *)0xdeadbeef, "got user value %p\n", tmp_ptr ); ok( tmp_flags == 0, "got user flags %#lx\n", tmp_flags ); ret = HeapFree( GetProcessHeap(), 0, ptr ); @@ -2359,7 +2347,6 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags ret = pRtlGetUserInfoHeap( heap, 0, ptr0, (void **)&tmp_ptr, &tmp_flags ); ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() ); ok( tmp_ptr == NULL, "got ptr %p\n", tmp_ptr ); - todo_wine ok( tmp_flags == 0xc00, "got flags %#lx\n", tmp_flags );
tmp_ptr = (void *)0xdeadbeef; @@ -2367,7 +2354,6 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags ret = pRtlGetUserInfoHeap( heap, 0, ptr1, (void **)&tmp_ptr, &tmp_flags ); ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() ); ok( tmp_ptr == NULL, "got ptr %p\n", tmp_ptr ); - todo_wine ok( tmp_flags == 0x200, "got flags %#lx\n", tmp_flags );
ret = pRtlSetUserValueHeap( heap, 0, ptr0, (void *)0xdeadbeef ); diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index e0af0e72925..4b8f45f82cd 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -96,6 +96,7 @@ C_ASSERT( sizeof(struct block) == 8 ); #define BLOCK_FLAG_USER_MASK 0x000000f0
#define BLOCK_USER_FLAGS( heap_flags ) (((heap_flags) >> 4) & BLOCK_FLAG_USER_MASK) +#define HEAP_USER_FLAGS( block_flags ) (((block_flags) & BLOCK_FLAG_USER_MASK) << 4)
/* entry to link free blocks in free lists */
@@ -2008,6 +2009,7 @@ NTSTATUS WINAPI RtlSetHeapInformation( HANDLE handle, HEAP_INFORMATION_CLASS inf */ BOOLEAN WINAPI RtlGetUserInfoHeap( HANDLE handle, ULONG flags, void *ptr, void **user_value, ULONG *user_flags ) { + NTSTATUS status = STATUS_SUCCESS; struct block *block; struct heap *heap; SUBHEAP *subheap; @@ -2016,26 +2018,36 @@ BOOLEAN WINAPI RtlGetUserInfoHeap( HANDLE handle, ULONG flags, void *ptr, void * TRACE( "handle %p, flags %#x, ptr %p, user_value %p, user_flags %p semi-stub!\n", handle, flags, ptr, user_value, user_flags );
- *user_value = 0; *user_flags = 0;
if (!(heap = unsafe_heap_from_handle( handle ))) return TRUE;
heap_lock( heap, flags ); - if ((block = unsafe_block_from_ptr( heap, ptr, &subheap )) && !subheap) + if (!(block = unsafe_block_from_ptr( heap, ptr, &subheap ))) + { + WARN( "Failed to find block %p in heap %p\n", ptr, handle ); + status = STATUS_INVALID_PARAMETER; + *user_value = 0; + } + else if (!(*user_flags = HEAP_USER_FLAGS(block_get_flags( block )))) + WARN( "Block %p wasn't allocated with user info\n", ptr ); + else if (!subheap) { const ARENA_LARGE *large = CONTAINING_RECORD( block, ARENA_LARGE, block ); + *user_flags = *user_flags & ~HEAP_ADD_USER_INFO; *user_value = large->user_value; } - else if (block) + else { tmp = (char *)block + block_get_size( block ) - block->tail_size + sizeof(void *); if ((heap_get_flags( heap, flags ) & HEAP_TAIL_CHECKING_ENABLED) || RUNNING_ON_VALGRIND) tmp += ALIGNMENT; + *user_flags = *user_flags & ~HEAP_ADD_USER_INFO; *user_value = *(void **)tmp; } heap_unlock( heap, flags );
- return TRUE; + heap_set_status( heap, flags, status ); + return !status; }
/***********************************************************************