[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, ¤theap->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