Commit dabda7e3 authored by Alexandre Julliard's avatar Alexandre Julliard

kernel32/tests: Add tests for the global flag and its influence on the heap flags.

parent 9055e9e3
...@@ -21,14 +21,25 @@ ...@@ -21,14 +21,25 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "winreg.h"
#include "winternl.h"
#include "wine/test.h" #include "wine/test.h"
#define MAGIC_DEAD 0xdeadbeef #define MAGIC_DEAD 0xdeadbeef
static BOOL (WINAPI *pHeapQueryInformation)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T); static BOOL (WINAPI *pHeapQueryInformation)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T);
static ULONG (WINAPI *pRtlGetNtGlobalFlags)(void);
struct heap_layout
{
DWORD unknown[3];
DWORD flags;
DWORD force_flags;
};
static SIZE_T resize_9x(SIZE_T size) static SIZE_T resize_9x(SIZE_T size)
{ {
...@@ -467,8 +478,132 @@ static void test_HeapQueryInformation(void) ...@@ -467,8 +478,132 @@ static void test_HeapQueryInformation(void)
ok(info == 0 || info == 1 || info == 2, "expected 0, 1 or 2, got %u\n", info); ok(info == 0 || info == 1 || info == 2, "expected 0, 1 or 2, got %u\n", info);
} }
static void test_debug_heap( const char *argv0, DWORD flags )
{
char keyname[MAX_PATH];
char buffer[MAX_PATH];
PROCESS_INFORMATION info;
STARTUPINFOA startup;
BOOL ret;
DWORD err;
HKEY hkey;
const char *basename;
if ((basename = strrchr( argv0, '\\' ))) basename++;
else basename = argv0;
sprintf( keyname, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
basename );
if (!strcmp( keyname + strlen(keyname) - 3, ".so" )) keyname[strlen(keyname) - 3] = 0;
err = RegCreateKeyA( HKEY_LOCAL_MACHINE, keyname, &hkey );
ok( !err, "failed to create '%s' error %u\n", keyname, err );
if (err) return;
if (flags == 0xdeadbeef) /* magic value for unsetting it */
RegDeleteValueA( hkey, "GlobalFlag" );
else
RegSetValueExA( hkey, "GlobalFlag", 0, REG_DWORD, (BYTE *)&flags, sizeof(flags) );
memset( &startup, 0, sizeof(startup) );
startup.cb = sizeof(startup);
sprintf( buffer, "%s heap.c 0x%x", argv0, flags );
ret = CreateProcessA( NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info );
ok( ret, "failed to create child process error %u\n", GetLastError() );
if (ret)
{
winetest_wait_child_process( info.hProcess );
CloseHandle( info.hThread );
CloseHandle( info.hProcess );
}
RegDeleteValueA( hkey, "GlobalFlag" );
RegCloseKey( hkey );
RegDeleteKeyA( HKEY_LOCAL_MACHINE, keyname );
}
static DWORD heap_flags_from_global_flag( DWORD flag )
{
DWORD ret = 0;
if (flag & FLG_HEAP_ENABLE_TAIL_CHECK)
ret |= HEAP_TAIL_CHECKING_ENABLED;
if (flag & FLG_HEAP_ENABLE_FREE_CHECK)
ret |= HEAP_FREE_CHECKING_ENABLED;
if (flag & FLG_HEAP_VALIDATE_PARAMETERS)
ret |= 0x50000000 | HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED;
if (flag & FLG_HEAP_VALIDATE_ALL)
ret |= 0x30000000 | HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED;
if (flag & FLG_HEAP_DISABLE_COALESCING)
ret |= HEAP_DISABLE_COALESCE_ON_FREE;
if (flag & FLG_HEAP_PAGE_ALLOCS)
ret |= 0x01000000 | HEAP_GROWABLE;
return ret;
}
static void test_child_heap( const char *arg )
{
struct heap_layout *heap = GetProcessHeap();
DWORD expected = strtoul( arg, 0, 16 );
if (expected == 0xdeadbeef) /* expected value comes from Session Manager global flags */
{
HKEY hkey;
expected = 0;
if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager", &hkey ))
{
char buffer[32];
DWORD type, size = sizeof(buffer);
if (!RegQueryValueExA( hkey, "GlobalFlag", 0, &type, (BYTE *)buffer, &size ))
{
if (type == REG_DWORD) expected = *(DWORD *)buffer;
else if (type == REG_SZ) expected = strtoul( buffer, 0, 16 );
}
RegCloseKey( hkey );
}
}
if (expected && !pRtlGetNtGlobalFlags()) /* not working on NT4 */
{
win_skip( "global flags not set\n" );
return;
}
ok( pRtlGetNtGlobalFlags() == expected,
"%s: got global flags %08x expected %08x\n", arg, pRtlGetNtGlobalFlags(), expected );
if (!(heap->flags & HEAP_GROWABLE) || heap->flags == 0xeeeeeeee) /* vista layout */
{
if (expected & FLG_HEAP_PAGE_ALLOCS)
ok( heap->flags == 0xeeeeeeee, "%s: got heap flags %08x expected 0xeeeeeeee\n",
arg, heap->flags );
else
ok( heap->flags == 0, "%s: got heap flags %08x expected 0\n", arg, heap->flags );
}
else
{
expected = heap_flags_from_global_flag( expected );
ok( heap->flags == (expected | HEAP_GROWABLE),
"%s: got heap flags %08x expected %08x\n", arg, heap->flags, expected );
ok( heap->force_flags == (expected & ~0x18000080),
"%s: got heap force flags %08x expected %08x\n", arg, heap->force_flags, expected );
}
}
START_TEST(heap) START_TEST(heap)
{ {
int argc;
char **argv;
pRtlGetNtGlobalFlags = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "RtlGetNtGlobalFlags" );
argc = winetest_get_mainargs( &argv );
if (argc >= 3)
{
test_child_heap( argv[2] );
return;
}
test_heap(); test_heap();
test_obsolete_flags(); test_obsolete_flags();
...@@ -480,4 +615,20 @@ START_TEST(heap) ...@@ -480,4 +615,20 @@ START_TEST(heap)
test_sized_HeapReAlloc((1 << 20), (2 << 20)); test_sized_HeapReAlloc((1 << 20), (2 << 20));
test_sized_HeapReAlloc((1 << 20), 1); test_sized_HeapReAlloc((1 << 20), 1);
test_HeapQueryInformation(); test_HeapQueryInformation();
if (pRtlGetNtGlobalFlags)
{
test_debug_heap( argv[0], 0 );
test_debug_heap( argv[0], FLG_HEAP_ENABLE_TAIL_CHECK );
test_debug_heap( argv[0], FLG_HEAP_ENABLE_FREE_CHECK );
test_debug_heap( argv[0], FLG_HEAP_VALIDATE_PARAMETERS );
test_debug_heap( argv[0], FLG_HEAP_VALIDATE_ALL );
test_debug_heap( argv[0], FLG_POOL_ENABLE_TAGGING );
test_debug_heap( argv[0], FLG_HEAP_ENABLE_TAGGING );
test_debug_heap( argv[0], FLG_HEAP_ENABLE_TAG_BY_DLL );
test_debug_heap( argv[0], FLG_HEAP_DISABLE_COALESCING );
test_debug_heap( argv[0], FLG_HEAP_PAGE_ALLOCS );
test_debug_heap( argv[0], 0xdeadbeef );
}
else win_skip( "RtlGetNtGlobalFlags not found, skipping heap debug tests\n" );
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment