[PATCH 7/7] kernel32/tests: Add some RtlGetUserInfoHeap tests.

Rémi Bernon rbernon at codeweavers.com
Tue Apr 19 12:33:35 CDT 2022


And corresponding RtlSetUserValueHeap and RtlSetUserFlagsHeap tests.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/kernel32/tests/heap.c | 103 +++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c
index 7195907ff03..a16084160d7 100644
--- a/dlls/kernel32/tests/heap.c
+++ b/dlls/kernel32/tests/heap.c
@@ -31,6 +31,7 @@
 #include "wine/test.h"
 
 /* some undocumented flags (names are made up) */
+#define HEAP_ADD_USER_INFO    0x00000100
 #define HEAP_PRIVATE          0x00001000
 #define HEAP_PAGE_ALLOCS      0x01000000
 #define HEAP_VALIDATE         0x10000000
@@ -44,6 +45,9 @@
 static LPVOID (WINAPI *pHeapAlloc)(HANDLE,DWORD,SIZE_T);
 static LPVOID (WINAPI *pHeapReAlloc)(HANDLE,DWORD,LPVOID,SIZE_T);
 static BOOL (WINAPI *pGetPhysicallyInstalledSystemMemory)( ULONGLONG * );
+static BOOLEAN (WINAPI *pRtlGetUserInfoHeap)(HANDLE,ULONG,void*,void**,ULONG*);
+static BOOLEAN (WINAPI *pRtlSetUserValueHeap)(HANDLE,ULONG,void*,void*);
+static BOOLEAN (WINAPI *pRtlSetUserFlagsHeap)(HANDLE,ULONG,void*,ULONG);
 
 #define MAKE_FUNC(f) static typeof(f) *p ## f
 MAKE_FUNC( HeapQueryInformation );
@@ -65,6 +69,9 @@ static void load_functions(void)
     LOAD_FUNC( kernel32, GetPhysicallyInstalledSystemMemory );
     LOAD_FUNC( kernel32, GlobalFlags );
     LOAD_FUNC( ntdll, RtlGetNtGlobalFlags );
+    LOAD_FUNC( ntdll, RtlGetUserInfoHeap );
+    LOAD_FUNC( ntdll, RtlSetUserValueHeap );
+    LOAD_FUNC( ntdll, RtlSetUserFlagsHeap );
 #undef LOAD_FUNC
 }
 
@@ -910,6 +917,7 @@ static void test_GlobalAlloc(void)
     SIZE_T size, alloc_size;
     HGLOBAL mem, tmp_mem;
     BYTE *ptr, *tmp_ptr;
+    ULONG tmp_flags;
     UINT i, flags;
     BOOL ret;
 
@@ -1029,6 +1037,25 @@ static void test_GlobalAlloc(void)
         todo_wine
         ok( size == alloc_size, "HeapSize returned %Iu\n", size );
 
+        tmp_mem = invalid_mem;
+        tmp_flags = 0xdeadbeef;
+        ret = pRtlGetUserInfoHeap( GetProcessHeap(), 0, entry->ptr, (void **)&tmp_mem, &tmp_flags );
+        ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
+        todo_wine
+        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 );
+        todo_wine
+        ok( ret, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() );
+        tmp_mem = GlobalHandle( entry->ptr );
+        todo_wine
+        ok( tmp_mem == invalid_mem, "GlobalHandle returned unexpected handle\n" );
+        ret = pRtlSetUserValueHeap( GetProcessHeap(), 0, entry->ptr, mem );
+        todo_wine
+        ok( ret, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() );
+
         ptr = GlobalLock( mem );
         ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
         ok( ptr != mem, "got unexpected ptr %p\n", ptr );
@@ -1738,6 +1765,8 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags
     SIZE_T expect_size, alloc_size, tail_size, extra_size;
     unsigned char *ptr0, *ptr1, *ptr2;
     char tail_buf[64], padd_buf[64];
+    ULONG tmp_flags;
+    void *tmp_ptr;
     BOOL ret;
 
     if (global_flags & (FLG_HEAP_DISABLE_COALESCING|FLG_HEAP_PAGE_ALLOCS|FLG_POOL_ENABLE_TAGGING|
@@ -1849,7 +1878,81 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags
         ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
         ret = HeapFree( heap, 0, ptr0 );
         ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
+        winetest_pop_context();
+    }
 
+    /* Undocumented HEAP_ADD_USER_INFO flag can be used to force an additional padding
+     * on small block sizes. It's possibly where the user info is stored, although it
+     * doesn't seem to be consistent and maybe has been moved elsewhere. Larger block
+     * seem to store the user flags and info in their header.
+     *
+     * RtlGetUserInfoHeap also requires the flag to work consistently, and otherwise
+     * causes crashes when heap flags are used, or on 32-bit.
+     */
+    if (!(heap_flags & padd_flags))
+    {
+        alloc_size = 0x1000;
+        winetest_push_context( "size %#Ix", alloc_size );
+        ptr0 = pHeapAlloc( heap, 0xe00|HEAP_ADD_USER_INFO, alloc_size );
+        ok( !!ptr0, "HeapAlloc failed, error %lu\n", GetLastError() );
+        ptr1 = HeapAlloc( heap, 0x200|HEAP_ADD_USER_INFO, alloc_size );
+        ok( !!ptr1, "HeapAlloc failed, error %lu\n", GetLastError() );
+        ptr2 = HeapAlloc( heap, HEAP_ADD_USER_INFO, alloc_size );
+        ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
+
+        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 );
+
+        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" );
+        ok( !memcmp( ptr2 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
+
+        todo_wine
+        ok( !memcmp( ptr0 + alloc_size + tail_size, padd_buf, 2 * sizeof(void *) ), "unexpected padding\n" );
+
+        tmp_ptr = (void *)0xdeadbeef;
+        tmp_flags = 0xdeadbeef;
+        ret = pRtlGetUserInfoHeap( heap, 0, ptr0, (void **)&tmp_ptr, &tmp_flags );
+        ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
+        ok( tmp_ptr == (void *)NULL, "got ptr %p\n", tmp_ptr );
+        todo_wine
+        ok( tmp_flags == 0xe00, "got flags %#lx\n", tmp_flags );
+
+        tmp_ptr = (void *)0xdeadbeef;
+        tmp_flags = 0xdeadbeef;
+        ret = pRtlGetUserInfoHeap( heap, 0, ptr1, (void **)&tmp_ptr, &tmp_flags );
+        ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
+        ok( tmp_ptr == (void *)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 );
+        todo_wine
+        ok( ret, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() );
+        ret = pRtlSetUserFlagsHeap( heap, 0, ptr0, 0xdeadbeef );
+        ok( !ret, "RtlSetUserFlagsHeap failed, error %lu\n", GetLastError() );
+        ret = pRtlSetUserFlagsHeap( heap, 0, ptr0, 0x200 );
+        ok( !ret, "RtlSetUserFlagsHeap failed, error %lu\n", GetLastError() );
+
+        tmp_ptr = NULL;
+        tmp_flags = 0;
+        ret = pRtlGetUserInfoHeap( heap, 0, ptr0, (void **)&tmp_ptr, &tmp_flags );
+        ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
+        todo_wine
+        ok( tmp_ptr == (void *)0xdeadbeef, "got ptr %p\n", tmp_ptr );
+        todo_wine
+        ok( tmp_flags == 0xe00, "got flags %#lx\n", tmp_flags );
+
+        ret = HeapFree( heap, 0, ptr2 );
+        ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
+        ret = HeapFree( heap, 0, ptr1 );
+        ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
+        ret = HeapFree( heap, 0, ptr0 );
+        ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
         winetest_pop_context();
     }
 }
-- 
2.35.1




More information about the wine-devel mailing list