[PATCH v2 4/5] ntdll: Implement RtlSetUserValueHeap.

Rémi Bernon wine at gitlab.winehq.org
Thu Jun 9 07:16:01 CDT 2022


From: Rémi Bernon <rbernon at codeweavers.com>

Signed-off-by: Rémi Bernon <rbernon at 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 97f4d9c9fe3..4221fd39c0f 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)
     {
@@ -2228,7 +2226,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 *) );
@@ -2303,7 +2301,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 );
@@ -2330,13 +2327,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;
 }
 
 /***********************************************************************
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/201



More information about the wine-devel mailing list