[PATCH 5/5] ntdll: Rewrite RtlWalkHeap and enumerate large blocks.

Rémi Bernon wine at gitlab.winehq.org
Fri May 13 03:18:28 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 |  92 +------------
 dlls/kernelbase/memory.c   |  57 +++++++-
 dlls/ntdll/heap.c          | 276 ++++++++++++++++++-------------------
 3 files changed, 191 insertions(+), 234 deletions(-)

diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c
index 45a22adcf2e..1b8e019c0ec 100644
--- a/dlls/kernel32/tests/heap.c
+++ b/dlls/kernel32/tests/heap.c
@@ -526,7 +526,6 @@ static void test_HeapCreate(void)
     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;
@@ -536,16 +535,13 @@ static void test_HeapCreate(void)
     SetLastError( 0xdeadbeef );
     while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
     ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
-    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)
@@ -554,11 +550,8 @@ static void test_HeapCreate(void)
             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 );
@@ -574,13 +567,9 @@ static void test_HeapCreate(void)
         winetest_pop_context();
     }
 
-    todo_wine
     ok( entries[0].wFlags == PROCESS_HEAP_REGION, "got wFlags %#x\n", entries[0].wFlags );
-    todo_wine
     ok( entries[0].lpData == heap, "got lpData %p\n", entries[0].lpData );
-    todo_wine
     ok( entries[0].cbData <= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries[0].cbData );
-    todo_wine
     ok( entries[0].cbOverhead == 0, "got cbOverhead %#x\n", entries[0].cbOverhead );
     ok( entries[0].iRegionIndex == 0, "got iRegionIndex %d\n", entries[0].iRegionIndex );
     todo_wine
@@ -594,27 +583,20 @@ static void test_HeapCreate(void)
     ok( (BYTE *)entries[0].Region.lpFirstBlock == (BYTE *)entries[0].lpData + entries[0].cbData + 2 * sizeof(void *) ||
         (BYTE *)entries[0].Region.lpFirstBlock == (BYTE *)entries[0].lpData + entries[0].cbData + 4 * sizeof(void *),
         "got Region.lpFirstBlock %p\n", entries[0].Region.lpFirstBlock );
-    todo_wine
     ok( entries[0].Region.lpLastBlock == (BYTE *)entries[2].lpData + entries[2].cbData,
         "got Region.lpLastBlock %p\n", entries[0].Region.lpLastBlock );
 
     ok( entries[1].wFlags == 0, "got wFlags %#x\n", entries[1].wFlags );
-    todo_wine
     ok( entries[1].lpData != NULL, "got lpData %p\n", entries[1].lpData );
-    todo_wine
     ok( entries[1].cbData != 0, "got cbData %#lx\n", entries[1].cbData );
-    todo_wine
     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
     ok( entries[2].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[2].wFlags );
-    todo_wine
     ok( entries[2].lpData == (BYTE *)entries[0].lpData + entries[0].Region.dwCommittedSize,
         "got lpData %p\n", entries[2].lpData );
     ok( entries[2].lpData == (BYTE *)entries[1].lpData + entries[1].cbData + 2 * entries[1].cbOverhead,
         "got lpData %p\n", entries[2].lpData );
-    todo_wine
     ok( entries[2].cbData == entries[0].Region.dwUnCommittedSize - 0x1000 ||
         entries[2].cbData == entries[0].Region.dwUnCommittedSize /* win7 */,
         "got cbData %#lx\n", entries[2].cbData );
@@ -630,7 +612,6 @@ static void test_HeapCreate(void)
     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) );
@@ -640,7 +621,6 @@ static void test_HeapCreate(void)
     SetLastError( 0xdeadbeef );
     while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
     ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
-    todo_wine
     ok( count == 4, "got count %lu\n", count );
     ok( !memcmp( entries + 16, entries, 3 * sizeof(entry) ), "entries differ\n" );
 
@@ -648,9 +628,7 @@ static void test_HeapCreate(void)
     {
         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)
@@ -659,11 +637,8 @@ static void test_HeapCreate(void)
             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 );
@@ -679,17 +654,13 @@ static void test_HeapCreate(void)
         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 */,
         "got wFlags %#x\n", entries[3].wFlags );
-    todo_wine
     ok( entries[3].lpData == ptr, "got lpData %p\n", entries[3].lpData );
-    todo_wine
     ok( entries[3].cbData == 5 * alloc_size, "got cbData %#lx\n", entries[3].cbData );
     ok( entries[3].cbOverhead == 0 || entries[3].cbOverhead == 8 * sizeof(void *) /* win7 */,
         "got cbOverhead %#x\n", entries[3].cbOverhead );
-    todo_wine
     ok( entries[3].iRegionIndex == 64, "got iRegionIndex %d\n", entries[3].iRegionIndex );
 
     ptr1 = HeapAlloc( heap, HEAP_ZERO_MEMORY, 5 * alloc_size );
@@ -701,7 +672,6 @@ static void test_HeapCreate(void)
     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) );
@@ -711,7 +681,6 @@ static void test_HeapCreate(void)
     SetLastError( 0xdeadbeef );
     while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
     ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
-    todo_wine
     ok( count == 5, "got count %lu\n", count );
     ok( !memcmp( entries + 16, entries, 4 * sizeof(entry) ), "entries differ\n" );
 
@@ -719,9 +688,7 @@ static void test_HeapCreate(void)
     {
         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)
@@ -730,11 +697,8 @@ static void test_HeapCreate(void)
             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 );
@@ -750,17 +714,13 @@ static void test_HeapCreate(void)
         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 */,
         "got wFlags %#x\n", entries[4].wFlags );
-    todo_wine
     ok( entries[4].lpData == ptr1, "got lpData %p\n", entries[4].lpData );
-    todo_wine
     ok( entries[4].cbData == 5 * alloc_size, "got cbData %#lx\n", entries[4].cbData );
     ok( entries[4].cbOverhead == 0 || entries[4].cbOverhead == 8 * sizeof(void *) /* win7 */,
         "got cbOverhead %#x\n", entries[4].cbOverhead );
-    todo_wine
     ok( entries[4].iRegionIndex == 64, "got iRegionIndex %d\n", entries[4].iRegionIndex );
 
     ret = HeapFree( heap, 0, ptr1 );
@@ -775,7 +735,6 @@ static void test_HeapCreate(void)
     SetLastError( 0xdeadbeef );
     while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
     ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
-    todo_wine
     ok( count == 3, "got count %lu\n", count );
     ok( !memcmp( entries + 16, entries, 3 * sizeof(entry) ), "entries differ\n" );
 
@@ -789,40 +748,28 @@ static void test_HeapCreate(void)
     SetLastError( 0xdeadbeef );
     while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
     ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
-    todo_wine
     ok( count == 4, "got count %lu\n", count );
-    todo_wine
     ok( !memcmp( entries + 16, entries, 1 * sizeof(entry) ), "entries differ\n" );
-    todo_wine
     ok( memcmp( entries + 17, entries + 2, 2 * sizeof(entry) ), "entries differ\n" );
 
-    todo_wine
     ok( entries[1].wFlags == PROCESS_HEAP_ENTRY_BUSY, "got wFlags %#x\n", entries[1].wFlags );
-    todo_wine
     ok( entries[1].lpData == ptr, "got lpData %p\n", entries[1].lpData );
-    todo_wine
     ok( entries[1].cbData == 123, "got cbData %#lx\n", entries[1].cbData );
     ok( entries[1].cbOverhead != 0, "got cbOverhead %#x\n", entries[1].cbOverhead );
     ok( entries[1].iRegionIndex == 0, "got iRegionIndex %d\n", entries[1].iRegionIndex );
 
     ok( entries[2].wFlags == 0, "got wFlags %#x\n", entries[2].wFlags );
-    todo_wine
     ok( entries[2].lpData == (BYTE *)entries[1].lpData + entries[1].cbData + entries[1].cbOverhead + 2 * sizeof(void *),
         "got lpData %p\n", entries[2].lpData );
-    todo_wine
     ok( entries[2].cbData != 0, "got cbData %#lx\n", entries[2].cbData );
-    todo_wine
     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
     ok( entries[3].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[3].wFlags );
-    todo_wine
     ok( entries[3].lpData == (BYTE *)entries[0].lpData + entries[0].Region.dwCommittedSize,
         "got lpData %p\n", entries[3].lpData );
     ok( entries[3].lpData == (BYTE *)entries[2].lpData + entries[2].cbData + 2 * entries[2].cbOverhead,
         "got lpData %p\n", entries[3].lpData );
-    todo_wine
     ok( entries[3].cbData == entries[0].Region.dwUnCommittedSize - 0x1000 ||
         entries[3].cbData == entries[0].Region.dwUnCommittedSize /* win7 */,
         "got cbData %#lx\n", entries[3].cbData );
@@ -839,40 +786,28 @@ static void test_HeapCreate(void)
     SetLastError( 0xdeadbeef );
     while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
     ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
-    todo_wine
     ok( count == 5, "got count %lu\n", count );
-    todo_wine
     ok( !memcmp( entries + 16, entries, 2 * sizeof(entry) ), "entries differ\n" );
-    todo_wine
     ok( memcmp( entries + 18, entries + 3, 2 * sizeof(entry) ), "entries differ\n" );
 
-    todo_wine
     ok( entries[2].wFlags == PROCESS_HEAP_ENTRY_BUSY, "got wFlags %#x\n", entries[2].wFlags );
-    todo_wine
     ok( entries[2].lpData == ptr1, "got lpData %p\n", entries[2].lpData );
-    todo_wine
     ok( entries[2].cbData == 456, "got cbData %#lx\n", entries[2].cbData );
     ok( entries[2].cbOverhead != 0, "got cbOverhead %#x\n", entries[2].cbOverhead );
     ok( entries[2].iRegionIndex == 0, "got iRegionIndex %d\n", entries[2].iRegionIndex );
 
     ok( entries[3].wFlags == 0, "got wFlags %#x\n", entries[3].wFlags );
-    todo_wine
     ok( entries[3].lpData == (BYTE *)entries[2].lpData + entries[2].cbData + entries[2].cbOverhead + 2 * sizeof(void *),
         "got lpData %p\n", entries[3].lpData );
-    todo_wine
     ok( entries[3].cbData != 0, "got cbData %#lx\n", entries[3].cbData );
-    todo_wine
     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
     ok( entries[4].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[4].wFlags );
-    todo_wine
     ok( entries[4].lpData == (BYTE *)entries[0].lpData + entries[0].Region.dwCommittedSize,
         "got lpData %p\n", entries[4].lpData );
     ok( entries[4].lpData == (BYTE *)entries[3].lpData + entries[3].cbData + 2 * entries[3].cbOverhead,
         "got lpData %p\n", entries[4].lpData );
-    todo_wine
     ok( entries[4].cbData == entries[0].Region.dwUnCommittedSize - 0x1000 ||
         entries[4].cbData == entries[0].Region.dwUnCommittedSize /* win7 */,
         "got cbData %#lx\n", entries[4].cbData );
@@ -1004,21 +939,14 @@ static void test_HeapCreate(void)
     SetLastError( 0xdeadbeef );
     while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
     ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
-    todo_wine
     ok( count == 3, "got count %lu\n", count );
 
-    todo_wine
     ok( entries[0].wFlags == PROCESS_HEAP_REGION, "got wFlags %#x\n", entries[0].wFlags );
-    todo_wine
     ok( entries[0].lpData == heap, "got lpData %p\n", entries[0].lpData );
-    todo_wine
     ok( entries[0].cbData <= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries[0].cbData );
-    todo_wine
     ok( entries[0].cbOverhead == 0, "got cbOverhead %#x\n", entries[0].cbOverhead );
     ok( entries[0].iRegionIndex == 0, "got iRegionIndex %d\n", entries[0].iRegionIndex );
-    todo_wine
     ok( entries[1].wFlags == 0, "got wFlags %#x\n", entries[1].wFlags );
-    todo_wine
     ok( entries[2].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[2].wFlags );
 
     for (i = 0; i < 0x12; i++) ptrs[i] = pHeapAlloc( heap, 0, 24 + 2 * sizeof(void *) );
@@ -1035,16 +963,11 @@ static void test_HeapCreate(void)
     ok( count > 24, "got count %lu\n", count );
     if (count < 2) count = 2;
 
-    todo_wine
     ok( entries[0].wFlags == PROCESS_HEAP_REGION, "got wFlags %#x\n", entries[0].wFlags );
-    todo_wine
     ok( entries[0].lpData == heap, "got lpData %p\n", entries[0].lpData );
-    todo_wine
     ok( entries[0].cbData <= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries[0].cbData );
-    todo_wine
     ok( entries[0].cbOverhead == 0, "got cbOverhead %#x\n", entries[0].cbOverhead );
     ok( entries[0].iRegionIndex == 0, "got iRegionIndex %d\n", entries[0].iRegionIndex );
-    todo_wine
     ok( entries[1].wFlags == 0, "got wFlags %#x\n", entries[1].wFlags );
 
     for (i = 0; i < 0x12; i++)
@@ -1060,10 +983,7 @@ static void test_HeapCreate(void)
     if (entries[count - 1].wFlags == PROCESS_HEAP_REGION) /* > win7 */
         ok( entries[count - 2].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[count - 2].wFlags );
     else
-    {
-        todo_wine
         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) );
@@ -1079,9 +999,7 @@ static void test_HeapCreate(void)
     {
         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)
@@ -1120,12 +1038,9 @@ static void test_HeapCreate(void)
     ok( count > 24, "got count %lu\n", count );
     if (count < 2) count = 2;
 
-    todo_wine
     ok( entries[0].wFlags == PROCESS_HEAP_REGION, "got wFlags %#x\n", entries[0].wFlags );
-    todo_wine
     ok( entries[0].lpData == heap, "got lpData %p\n", entries[0].lpData );
     ok( entries[0].cbData <= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries[0].cbData );
-    todo_wine
     ok( entries[0].cbOverhead == 0, "got cbOverhead %#x\n", entries[0].cbOverhead );
     ok( entries[0].iRegionIndex == 0, "got iRegionIndex %d\n", entries[0].iRegionIndex );
     ok( entries[1].wFlags == 0 || entries[1].wFlags == PROCESS_HEAP_ENTRY_BUSY /* win7 */, "got wFlags %#x\n", entries[1].wFlags );
@@ -1133,8 +1048,8 @@ static void test_HeapCreate(void)
     for (i = 1; i < count - 2; i++)
     {
         if (entries[i].wFlags != PROCESS_HEAP_ENTRY_BUSY) continue;
-        todo_wine_if( sizeof(void *) == 8 )
         ok( entries[i].cbData == 0x18 + 2 * sizeof(void *), "got cbData %#lx\n", entries[i].cbData );
+        todo_wine_if(sizeof(void *) == 8)
         ok( entries[i].cbOverhead == 0x8, "got cbOverhead %#x\n", entries[i].cbOverhead );
     }
 
@@ -1157,9 +1072,7 @@ static void test_HeapCreate(void)
     {
         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)
@@ -1171,11 +1084,8 @@ static void test_HeapCreate(void)
                 "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 );
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c
index 35e6d4e3b8c..656569220fa 100644
--- a/dlls/kernelbase/memory.c
+++ b/dlls/kernelbase/memory.c
@@ -601,12 +601,67 @@ BOOL WINAPI DECLSPEC_HOTPATCH HeapValidate( HANDLE heap, DWORD flags, LPCVOID pt
 }
 
 
+/* 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
+
+
 /***********************************************************************
  *           HeapWalk   (kernelbase.@)
  */
 BOOL WINAPI DECLSPEC_HOTPATCH HeapWalk( HANDLE heap, PROCESS_HEAP_ENTRY *entry )
 {
-    return set_ntstatus( RtlWalkHeap( heap, entry ));
+    struct rtl_heap_entry rtl_entry = {.lpData = entry->lpData};
+    NTSTATUS status;
+
+    if (!(status = RtlWalkHeap( heap, &rtl_entry )))
+    {
+        entry->lpData = rtl_entry.lpData;
+        entry->cbData = rtl_entry.cbData;
+        entry->cbOverhead = rtl_entry.cbOverhead;
+        entry->iRegionIndex = rtl_entry.iRegionIndex;
+
+        if (rtl_entry.wFlags & RTL_HEAP_ENTRY_BUSY)
+            entry->wFlags = PROCESS_HEAP_ENTRY_BUSY;
+        else if (rtl_entry.wFlags & RTL_HEAP_ENTRY_REGION)
+            entry->wFlags = PROCESS_HEAP_REGION;
+        else if (rtl_entry.wFlags & RTL_HEAP_ENTRY_UNCOMMITTED)
+            entry->wFlags = PROCESS_HEAP_UNCOMMITTED_RANGE;
+        else
+            entry->wFlags = 0;
+
+        memcpy( &entry->u.Region, &rtl_entry.Region, sizeof(entry->u.Region) );
+    }
+
+    return set_ntstatus( status );
 }
 
 
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
index a917abe39af..255a3850c70 100644
--- a/dlls/ntdll/heap.c
+++ b/dlls/ntdll/heap.c
@@ -39,6 +39,39 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(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
+
+
 /* header for heap blocks */
 
 typedef struct block
@@ -517,46 +550,13 @@ static void heap_dump( const HEAP *heap )
     }
 }
 
-
-static void HEAP_DumpEntry( LPPROCESS_HEAP_ENTRY entry )
+static const char *debugstr_heap_entry( struct rtl_heap_entry *entry )
 {
-    WORD rem_flags;
-    TRACE( "Dumping entry %p\n", entry );
-    TRACE( "lpData\t\t: %p\n", entry->lpData );
-    TRACE( "cbData\t\t: %08x\n", entry->cbData);
-    TRACE( "cbOverhead\t: %08x\n", entry->cbOverhead);
-    TRACE( "iRegionIndex\t: %08x\n", entry->iRegionIndex);
-    TRACE( "WFlags\t\t: ");
-    if (entry->wFlags & PROCESS_HEAP_REGION)
-        TRACE( "PROCESS_HEAP_REGION ");
-    if (entry->wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE)
-        TRACE( "PROCESS_HEAP_UNCOMMITTED_RANGE ");
-    if (entry->wFlags & PROCESS_HEAP_ENTRY_BUSY)
-        TRACE( "PROCESS_HEAP_ENTRY_BUSY ");
-    if (entry->wFlags & PROCESS_HEAP_ENTRY_MOVEABLE)
-        TRACE( "PROCESS_HEAP_ENTRY_MOVEABLE ");
-    if (entry->wFlags & PROCESS_HEAP_ENTRY_DDESHARE)
-        TRACE( "PROCESS_HEAP_ENTRY_DDESHARE ");
-    rem_flags = entry->wFlags &
-        ~(PROCESS_HEAP_REGION | PROCESS_HEAP_UNCOMMITTED_RANGE |
-          PROCESS_HEAP_ENTRY_BUSY | PROCESS_HEAP_ENTRY_MOVEABLE|
-          PROCESS_HEAP_ENTRY_DDESHARE);
-    if (rem_flags)
-        TRACE( "Unknown %08x", rem_flags);
-    TRACE( "\n");
-    if ((entry->wFlags & PROCESS_HEAP_ENTRY_BUSY )
-        && (entry->wFlags & PROCESS_HEAP_ENTRY_MOVEABLE))
-    {
-        /* Treat as block */
-        TRACE( "BLOCK->hMem\t\t:%p\n", entry->u.Block.hMem);
-    }
-    if (entry->wFlags & PROCESS_HEAP_REGION)
-    {
-        TRACE( "Region.dwCommittedSize\t:%08x\n",entry->u.Region.dwCommittedSize);
-        TRACE( "Region.dwUnCommittedSize\t:%08x\n",entry->u.Region.dwUnCommittedSize);
-        TRACE( "Region.lpFirstBlock\t:%p\n",entry->u.Region.lpFirstBlock);
-        TRACE( "Region.lpLastBlock\t:%p\n",entry->u.Region.lpLastBlock);
-    }
+    const char *str = wine_dbg_sprintf( "data %p, size %#Ix, overhead %#x, region %#x, flags %#x", entry->lpData,
+                                        entry->cbData, entry->cbOverhead, entry->iRegionIndex, entry->wFlags );
+    if (!(entry->wFlags & RTL_HEAP_ENTRY_REGION)) return str;
+    return wine_dbg_sprintf( "%s, commit %#x, uncommit %#x, first %p, last %p", str, entry->Region.dwCommittedSize,
+                             entry->Region.dwUnCommittedSize, entry->Region.lpFirstBlock, entry->Region.lpLastBlock );
 }
 
 /***********************************************************************
@@ -916,7 +916,7 @@ static void *realloc_large_block( HEAP *heap, DWORD flags, void *ptr, SIZE_T siz
 /***********************************************************************
  *           find_large_block
  */
-static ARENA_LARGE *find_large_block( HEAP *heap, const void *ptr )
+static ARENA_LARGE *find_large_block( const HEAP *heap, const void *ptr )
 {
     ARENA_LARGE *arena;
 
@@ -2120,131 +2120,123 @@ BOOLEAN WINAPI RtlValidateHeap( HANDLE heap, ULONG flags, const void *ptr )
 }
 
 
-/***********************************************************************
- *           RtlWalkHeap    (NTDLL.@)
- *
- * FIXME
- *  The PROCESS_HEAP_ENTRY flag values seem different between this
- *  function and HeapWalk(). To be checked.
- */
-NTSTATUS WINAPI RtlWalkHeap( HANDLE heap, PVOID entry_ptr )
+static NTSTATUS heap_walk_blocks( const HEAP *heap, const SUBHEAP *subheap, struct rtl_heap_entry *entry )
 {
-    LPPROCESS_HEAP_ENTRY entry = entry_ptr; /* FIXME */
-    HEAP *heapPtr = HEAP_GetPtr(heap);
-    SUBHEAP *sub, *currentheap = NULL;
-    NTSTATUS ret;
-    char *ptr;
-    int region_index = 0;
-
-    if (!heapPtr || !entry) return STATUS_INVALID_PARAMETER;
-
-    heap_lock( heapPtr, 0 );
+    const char *base = subheap_base( subheap ), *commit_end = subheap_commit_end( subheap ), *end = base + subheap_size( subheap );
+    const struct block *block, *blocks = first_block( subheap );
 
-    /* FIXME: enumerate large blocks too */
+    if (entry->lpData == commit_end) return STATUS_NO_MORE_ENTRIES;
 
-    /* set ptr to the next arena to be examined */
+    if (entry->lpData == base) block = blocks;
+    else if (!(block = next_block( subheap, (struct block *)entry->lpData - 1 )))
+    {
+        entry->lpData = (void *)commit_end;
+        entry->cbData = end - commit_end;
+        entry->cbOverhead = 0;
+        entry->iRegionIndex = 0;
+        entry->wFlags = RTL_HEAP_ENTRY_UNCOMMITTED;
+        return STATUS_SUCCESS;
+    }
 
-    if (!entry->lpData) /* first call (init) ? */
+    if (block_get_flags( block ) & ARENA_FLAG_FREE)
     {
-        TRACE("begin walking of heap %p.\n", heap);
-        currentheap = &heapPtr->subheap;
-        ptr = (char*)currentheap->base + currentheap->headerSize;
+        entry->lpData = (char *)block + block_get_overhead( block );
+        entry->cbData = block_get_size( block ) - block_get_overhead( block );
+        /* FIXME: last free block should not include uncommitted range, which also has its own overhead */
+        if (!contains( blocks, commit_end - (char *)blocks, block, block_get_size( block ) ))
+            entry->cbData = commit_end - (char *)entry->lpData - 8 * sizeof(void *);
+        entry->cbOverhead = 4 * sizeof(void *);
+        entry->iRegionIndex = 0;
+        entry->wFlags = 0;
     }
     else
     {
-        ptr = entry->lpData;
-        LIST_FOR_EACH_ENTRY( sub, &heapPtr->subheap_list, SUBHEAP, entry )
-        {
-            if ((ptr >= (char *)sub->base) &&
-                (ptr < (char *)sub->base + sub->size))
-            {
-                currentheap = sub;
-                break;
-            }
-            region_index++;
-        }
-        if (currentheap == NULL)
-        {
-            ERR("no matching subheap found, shouldn't happen !\n");
-            ret = STATUS_NO_MORE_ENTRIES;
-            goto HW_end;
-        }
-
-        if (((ARENA_INUSE *)ptr - 1)->magic == ARENA_INUSE_MAGIC ||
-            ((ARENA_INUSE *)ptr - 1)->magic == ARENA_PENDING_MAGIC)
-        {
-            ARENA_INUSE *pArena = (ARENA_INUSE *)ptr - 1;
-            ptr += pArena->size & ARENA_SIZE_MASK;
-        }
-        else if (((ARENA_FREE *)ptr - 1)->magic == ARENA_FREE_MAGIC)
-        {
-            ARENA_FREE *pArena = (ARENA_FREE *)ptr - 1;
-            ptr += pArena->size & ARENA_SIZE_MASK;
-        }
-        else
-            ptr += entry->cbData; /* point to next arena */
-
-        if (ptr > (char *)currentheap->base + currentheap->size - 1)
-        {   /* proceed with next subheap */
-            struct list *next = list_next( &heapPtr->subheap_list, &currentheap->entry );
-            if (!next)
-            {  /* successfully finished */
-                TRACE("end reached.\n");
-                ret = STATUS_NO_MORE_ENTRIES;
-                goto HW_end;
-            }
-            currentheap = LIST_ENTRY( next, SUBHEAP, entry );
-            ptr = (char *)currentheap->base + currentheap->headerSize;
-        }
+        entry->lpData = (void *)(block + 1);
+        entry->cbData = block_get_size( block ) - block_get_overhead( block );
+        entry->cbOverhead = block_get_overhead( block );
+        entry->iRegionIndex = 0;
+        entry->wFlags = RTL_HEAP_ENTRY_COMMITTED|RTL_HEAP_ENTRY_BLOCK|RTL_HEAP_ENTRY_BUSY;
     }
 
-    entry->wFlags = 0;
-    if (*(DWORD *)ptr & ARENA_FLAG_FREE)
-    {
-        ARENA_FREE *pArena = (ARENA_FREE *)ptr;
+    return STATUS_SUCCESS;
+}
 
-        /*TRACE("free, magic: %04x\n", pArena->magic);*/
+static NTSTATUS heap_walk( const HEAP *heap, struct rtl_heap_entry *entry )
+{
+    const ARENA_LARGE *large;
+    const struct list *next;
+    const SUBHEAP *subheap;
+    NTSTATUS status;
+    char *base;
 
-        entry->lpData = pArena + 1;
-        entry->cbData = pArena->size & ARENA_SIZE_MASK;
-        entry->cbOverhead = sizeof(ARENA_FREE);
-        entry->wFlags = PROCESS_HEAP_UNCOMMITTED_RANGE;
+    if ((large = find_large_block( heap, entry->lpData )))
+        next = &large->entry;
+    else if ((subheap = find_subheap( heap, entry->lpData )))
+    {
+        if (!(status = heap_walk_blocks( heap, subheap, entry ))) return STATUS_SUCCESS;
+        else if (status != STATUS_NO_MORE_ENTRIES) return status;
+        next = &subheap->entry;
     }
     else
     {
-        ARENA_INUSE *pArena = (ARENA_INUSE *)ptr;
+        if (entry->lpData) return STATUS_INVALID_PARAMETER;
+        next = &heap->subheap_list;
+    }
 
-        /*TRACE("busy, magic: %04x\n", pArena->magic);*/
+    if (!large && (next = list_next( &heap->subheap_list, next )))
+    {
+        subheap = LIST_ENTRY( next, SUBHEAP, entry );
+        base = subheap_base( subheap );
+        entry->lpData = base;
+        entry->cbData = (char *)first_block( subheap ) - base;
+        entry->cbOverhead = 0;
+        entry->iRegionIndex = 0;
+        entry->wFlags = RTL_HEAP_ENTRY_REGION;
+        entry->Region.dwCommittedSize = (char *)subheap_commit_end( subheap ) - base;
+        entry->Region.dwUnCommittedSize = subheap_size( subheap ) - entry->Region.dwCommittedSize;
+        entry->Region.lpFirstBlock = base + entry->cbData;
+        entry->Region.lpLastBlock = base + subheap_size( subheap );
+        return STATUS_SUCCESS;
+    }
 
-        entry->lpData = pArena + 1;
-        entry->cbData = pArena->size & ARENA_SIZE_MASK;
-        entry->cbOverhead = sizeof(ARENA_INUSE);
-        entry->wFlags = (pArena->magic == ARENA_PENDING_MAGIC) ?
-                        PROCESS_HEAP_UNCOMMITTED_RANGE : PROCESS_HEAP_ENTRY_BUSY;
-        /* FIXME: can't handle PROCESS_HEAP_ENTRY_MOVEABLE
-        and PROCESS_HEAP_ENTRY_DDESHARE yet */
+    if (!next) next = &heap->large_list;
+    if ((next = list_next( &heap->large_list, next )))
+    {
+        large = LIST_ENTRY( next, ARENA_LARGE, entry );
+        entry->lpData = (void *)(large + 1);
+        entry->cbData = large->data_size;
+        entry->cbOverhead = 0;
+        entry->iRegionIndex = 64;
+        entry->wFlags = RTL_HEAP_ENTRY_COMMITTED|RTL_HEAP_ENTRY_BLOCK|RTL_HEAP_ENTRY_BUSY;
+        return STATUS_SUCCESS;
     }
 
-    entry->iRegionIndex = region_index;
+    return STATUS_NO_MORE_ENTRIES;
+}
+
+/***********************************************************************
+ *           RtlWalkHeap    (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlWalkHeap( HANDLE heap, void *entry_ptr )
+{
+    struct rtl_heap_entry *entry = entry_ptr;
+    NTSTATUS status;
+    HEAP *heapPtr;
 
-    /* first element of heap ? */
-    if (ptr == (char *)currentheap->base + currentheap->headerSize)
+    if (!entry) return STATUS_INVALID_PARAMETER;
+
+    if (!(heapPtr = HEAP_GetPtr(heap)))
+        status = STATUS_INVALID_HANDLE;
+    else
     {
-        entry->wFlags |= PROCESS_HEAP_REGION;
-        entry->u.Region.dwCommittedSize = currentheap->commitSize;
-        entry->u.Region.dwUnCommittedSize =
-                currentheap->size - currentheap->commitSize;
-        entry->u.Region.lpFirstBlock = /* first valid block */
-                (char *)currentheap->base + currentheap->headerSize;
-        entry->u.Region.lpLastBlock  = /* first invalid block */
-                (char *)currentheap->base + currentheap->size;
+        heap_lock( heapPtr, 0 );
+        status = heap_walk( heapPtr, entry );
+        heap_unlock( heapPtr, 0 );
     }
-    ret = STATUS_SUCCESS;
-    if (TRACE_ON(heap)) HEAP_DumpEntry(entry);
 
-HW_end:
-    heap_unlock( heapPtr, 0 );
-    return ret;
+    TRACE( "heap %p, entry %p %s, return %#x\n", heap, entry,
+           status ? "<empty>" : debugstr_heap_entry(entry), status );
+    return status;
 }
 
 
-- 
GitLab

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



More information about the wine-devel mailing list