From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/heap.c | 13 +++---------- dlls/ntdll/heap.c | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index c237d515648..d4022b0d949 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -354,9 +354,7 @@ static void test_HeapCreate(void) ok( !!ptrs[i], "HeapAlloc failed, error %lu\n", GetLastError() ); align |= (UINT_PTR)ptrs[i]; } - todo_wine_if( sizeof(void *) == 8 ) ok( !(align & (8 * sizeof(void *) - 1)), "got wrong alignment\n" ); - todo_wine_if( sizeof(void *) == 8 ) ok( align & (8 * sizeof(void *)), "got wrong alignment\n" ); for (i = 0; i < ARRAY_SIZE(ptrs); ++i) { @@ -2217,7 +2215,7 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags 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 ) + todo_wine_if( alloc_size == 0x7efe9 ) ok( !(align & (8 * sizeof(void *) - 1)), "wrong align\n" );
expect_size = max( alloc_size, 2 * sizeof(void *) ); @@ -2292,7 +2290,6 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags ok( tmp_flags == 0x200, "got flags %#lx\n", tmp_flags );
ret = pRtlSetUserValueHeap( heap, 0, ptr0, (void *)0xdeadbeef ); - todo_wine ok( ret, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() ); SetLastError( 0xdeadbeef ); ret = pRtlSetUserFlagsHeap( heap, 0, ptr0, 0, 0x1000 ); @@ -2319,13 +2316,9 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags "got flags %#lx\n", tmp_flags );
user_ptr = (void **)(ptr0 + alloc_size + tail_size); - todo_wine ok( user_ptr[1] == (void *)0xdeadbeef, "unexpected user value\n" ); - if (user_ptr[1] == (void *)0xdeadbeef) - { - user_ptr[0] = (void *)0xdeadbeef; - user_ptr[1] = (void *)0xdeadbee0; - } + user_ptr[0] = (void *)0xdeadbeef; + user_ptr[1] = (void *)0xdeadbee0;
tmp_ptr = NULL; tmp_flags = 0; diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 6d9f949b6a9..64d4f6644af 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -105,10 +105,11 @@ C_ASSERT( sizeof(struct entry) == 2 * ALIGNMENT );
typedef struct { + SIZE_T __pad[sizeof(SIZE_T) / sizeof(DWORD)]; struct list entry; /* entry in heap large blocks list */ SIZE_T data_size; /* size of user data */ SIZE_T block_size; /* total size of virtual memory block */ - DWORD pad[2]; /* padding to ensure 16-byte alignment of data */ + void *user_value; DWORD size; /* fields for compatibility with normal arenas */ DWORD magic; /* these must remain at the end of the structure */ } ARENA_LARGE; @@ -362,6 +363,12 @@ static inline void mark_block_tail( struct block *block, DWORD flags ) memset( tail, ARENA_TAIL_FILLER, ALIGNMENT ); } valgrind_make_noaccess( tail, ALIGNMENT ); + if (flags & HEAP_ADD_USER_INFO) + { + if (flags & HEAP_TAIL_CHECKING_ENABLED || RUNNING_ON_VALGRIND) tail += ALIGNMENT; + valgrind_make_writable( tail + sizeof(void *), sizeof(void *) ); + memset( tail + sizeof(void *), 0, sizeof(void *) ); + } }
/* initialize contents of a newly created block of memory */ @@ -2001,10 +2008,31 @@ BOOLEAN WINAPI RtlGetUserInfoHeap( HANDLE heap, ULONG flags, void *ptr, void **u /*********************************************************************** * RtlSetUserValueHeap (NTDLL.@) */ -BOOLEAN WINAPI RtlSetUserValueHeap( HANDLE heap, ULONG flags, void *ptr, void *user_value ) +BOOLEAN WINAPI RtlSetUserValueHeap( HANDLE handle, ULONG flags, void *ptr, void *user_value ) { - FIXME( "heap %p, flags %#x, ptr %p, user_value %p stub!\n", heap, flags, ptr, user_value ); - return FALSE; + ARENA_LARGE *large = (ARENA_LARGE *)ptr - 1; + struct block *block; + BOOLEAN ret = TRUE; + SUBHEAP *subheap; + HEAP *heap; + char *tmp; + + TRACE( "handle %p, flags %#x, ptr %p, user_value %p.\n", handle, flags, ptr, user_value ); + + if (!(heap = HEAP_GetPtr( handle ))) return TRUE; + + heap_lock( heap, flags ); + if (!(block = unsafe_block_from_ptr( heap, ptr, &subheap ))) ret = FALSE; + else if (!subheap) large->user_value = user_value; + 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; + *(void **)tmp = user_value; + } + heap_unlock( heap, flags ); + + return ret; }
/***********************************************************************