kernel32/tests: Fix tls callback tests on Windows 7.

Also add a few more so the full set of callbacks is tested.

Fixes: 2203a8564c
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54657
This commit is contained in:
Evan Tang 2023-03-10 20:39:38 -06:00 committed by Alexandre Julliard
parent 67f992c831
commit a7b49b0e86

View file

@ -2144,6 +2144,19 @@ static void check_tls_index(HANDLE dll, BOOL tls_initialized)
ok(found_dll, "Couldn't find dll %p in module list\n", dll);
}
static int tls_init_fn_output;
static DWORD WINAPI tls_thread_fn(void* tlsidx_v)
{
int tls_index = (int)(DWORD_PTR)(tlsidx_v);
const char* str = ((char **)NtCurrentTeb()->ThreadLocalStoragePointer)[tls_index];
ok( !strcmp( str, "hello world" ), "wrong tls data '%s' at %p\n", str, str );
ok( tls_init_fn_output == DLL_THREAD_ATTACH,
"tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_THREAD_ATTACH );
tls_init_fn_output = 9999;
return 0;
}
static void test_import_resolution(void)
{
char temp_path[MAX_PATH];
@ -2165,31 +2178,41 @@ static void test_import_resolution(void)
char tls_data[16];
SHORT tls_index;
SHORT tls_index_hi;
UCHAR tls_init_fn[64]; /* Note: Uses rip-relative address of tls_index, don't separate */
int* tls_init_fn_output;
UCHAR tls_init_fn[64]; /* Note: Uses rip-relative address of tls_init_fn_output, don't separate */
UCHAR entry_point_fn[16];
} data, *ptr;
IMAGE_NT_HEADERS nt;
IMAGE_SECTION_HEADER section;
int test;
int test, tls_index_save;
#if defined(__i386__)
static const UCHAR tls_init_code[] = {
0xE8, 0x00, 0x00, 0x00, 0x00, /* call 1f */
0x59, /* 1: pop ecx */
0x8B, 0x49, 0xF7, /* mov ecx, [ecx - 9] ; mov ecx, [tls_index] */
0x64, 0x8B, 0x15, 0x2C, 0x00, 0x00, 0x00, /* mov edx, fs:0x2c */
0x8B, 0x14, 0x8A, /* mov edx, [edx + edx * 4] */
0xC6, 0x42, 0x05, 0x21, /* mov byte [edx + 5], 0x21 */
0xC2, 0x0C, 0x00, /* ret 12 */
0xE8, 0x00, 0x00, 0x00, 0x00, /* call 1f */
0x59, /* 1: pop ecx */
0x8B, 0x49, 0xF7, /* mov ecx, [ecx - 9] ; mov ecx, [tls_init_fn_output] */
0x8B, 0x54, 0x24, 0x08, /* mov edx, [esp + 8] */
0x89, 0x11, /* mov [ecx], edx */
0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */
0xC2, 0x0C, 0x00, /* ret 12 */
};
static const UCHAR entry_point_code[] = {
0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */
0xC2, 0x0C, 0x00, /* ret 12 */
};
#elif defined(__x86_64__)
static const UCHAR tls_init_code[] = {
0x8B, 0x0D, 0xF6, 0xFF, 0xFF, 0xFF, /* mov ecx, [rip + tls_index] */
0x65, 0x48, 0x8B, 0x14, 0x25, 0x58, 0x00, 0x00, 0x00, /* mov rdx, gs:0x58 */
0x48, 0x8B, 0x14, 0xCA, /* mov rdx, [rdx + rcx * 8] */
0xC6, 0x42, 0x05, 0x21, /* mov byte [rdx + 5], 0x21 */
0xC3, /* ret */
0x48, 0x8B, 0x0D, 0xF1, 0xFF, 0xFF, 0xFF, /* mov rcx, [rip + tls_init_fn_output] */
0x89, 0x11, /* mov [rcx], edx */
0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */
0xC3, /* ret */
};
static const UCHAR entry_point_code[] = {
0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */
0xC3, /* ret */
};
#else
static const UCHAR tls_init_code[] = { 0x00 };
static const UCHAR entry_point_code[] = { 0x00 };
#endif
for (test = 0; test < 4; test++)
@ -2230,10 +2253,16 @@ static void test_import_resolution(void)
if (test == 3 && sizeof(tls_init_code) > 1)
{
/* Windows doesn't consistently call tls init functions on dlls without entry points */
assert(sizeof(tls_init_code) <= sizeof(data.tls_init_fn));
assert(sizeof(entry_point_code) <= sizeof(data.entry_point_fn));
memcpy(data.tls_init_fn, tls_init_code, sizeof(tls_init_code));
memcpy(data.entry_point_fn, entry_point_code, sizeof(entry_point_code));
tls_init_fn_output = 9999;
data.tls_init_fn_output = &tls_init_fn_output;
data.tls_init_fn_list[0] = nt.OptionalHeader.ImageBase + DATA_RVA(&data.tls_init_fn);
data.tls.AddressOfCallBacks = nt.OptionalHeader.ImageBase + DATA_RVA(&data.tls_init_fn_list);
nt.OptionalHeader.AddressOfEntryPoint = DATA_RVA(&data.entry_point_fn);
}
GetTempPathA(MAX_PATH, temp_path);
@ -2315,16 +2344,27 @@ static void test_import_resolution(void)
ok( mod != NULL, "failed to load err %lu\n", GetLastError() );
if (!mod) break;
ptr = (struct imports *)((char *)mod + page_size);
tls_index_save = ptr->tls_index;
ok( ptr->tls_index < 32 || broken(ptr->tls_index == 9999), /* before vista */
"wrong tls index %d\n", ptr->tls_index );
if (ptr->tls_index != 9999 && sizeof(tls_init_code) > 1)
{
/* tls init function will write an '!' over the space in "hello world" */
str = ((char **)NtCurrentTeb()->ThreadLocalStoragePointer)[ptr->tls_index];
ok( !strcmp( str, "hello!world" ), "wrong tls data '%s' at %p\n", str, str );
ok( !strcmp( str, "hello world" ), "wrong tls data '%s' at %p\n", str, str );
/* tls init function will write the reason to *tls_init_fn_output */
ok( tls_init_fn_output == DLL_PROCESS_ATTACH,
"tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_PROCESS_ATTACH );
tls_init_fn_output = 9999;
WaitForSingleObject(CreateThread(NULL, 0, tls_thread_fn, (void*)(DWORD_PTR)ptr->tls_index, 0, NULL), INFINITE);
ok( tls_init_fn_output == DLL_THREAD_DETACH,
"tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_THREAD_DETACH );
}
check_tls_index(mod, ptr->tls_index != 9999);
tls_init_fn_output = 9999;
FreeLibrary( mod );
if (tls_index_save != 9999 && sizeof(tls_init_code) > 1)
ok( tls_init_fn_output == DLL_PROCESS_DETACH,
"tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_PROCESS_DETACH );
}
DeleteFileA( dll_name );
#undef DATA_RVA