mirror of
https://github.com/decompals/wibo.git
synced 2025-12-12 14:46:09 +00:00
Rework thread TIB handling & DLL initialization handling
This commit is contained in:
87
test/test_thread_notifications.c
Normal file
87
test/test_thread_notifications.c
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "test_assert.h"
|
||||
|
||||
static DWORD WINAPI workerProc(LPVOID param) {
|
||||
(void)param;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FARPROC loadExport(HMODULE module, const char *name) {
|
||||
FARPROC proc = GetProcAddress(module, name);
|
||||
#if defined(__i386__) || defined(_M_IX86)
|
||||
if (!proc) {
|
||||
char decorated[64];
|
||||
snprintf(decorated, sizeof(decorated), "_%s@0", name);
|
||||
proc = GetProcAddress(module, decorated);
|
||||
}
|
||||
#endif
|
||||
return proc;
|
||||
}
|
||||
|
||||
static BOOL isRunningUnderWine(void) {
|
||||
HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
|
||||
return hNtdll != NULL && GetProcAddress(hNtdll, "wine_get_version") != NULL;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
typedef LONG (*get_count_fn)(void);
|
||||
typedef void (*reset_counts_fn)(void);
|
||||
typedef BOOL (*disable_fn)(void);
|
||||
|
||||
HMODULE mod = LoadLibraryA("thread_notifications.dll");
|
||||
TEST_CHECK_MSG(mod != NULL, "LoadLibraryA failed: %lu", (unsigned long)GetLastError());
|
||||
|
||||
get_count_fn getAttach = (get_count_fn)(uintptr_t)loadExport(mod, "get_thread_attach_count");
|
||||
get_count_fn getDetach = (get_count_fn)(uintptr_t)loadExport(mod, "get_thread_detach_count");
|
||||
reset_counts_fn resetCounts = (reset_counts_fn)(uintptr_t)loadExport(mod, "reset_thread_counts");
|
||||
disable_fn disableNotifications = (disable_fn)(uintptr_t)loadExport(mod, "disable_thread_notifications");
|
||||
|
||||
TEST_CHECK_MSG(getAttach != NULL, "Missing get_thread_attach_count: %lu", (unsigned long)GetLastError());
|
||||
TEST_CHECK_MSG(getDetach != NULL, "Missing get_thread_detach_count: %lu", (unsigned long)GetLastError());
|
||||
TEST_CHECK_MSG(resetCounts != NULL, "Missing reset_thread_counts: %lu", (unsigned long)GetLastError());
|
||||
TEST_CHECK_MSG(disableNotifications != NULL, "Missing disable_thread_notifications: %lu",
|
||||
(unsigned long)GetLastError());
|
||||
|
||||
resetCounts();
|
||||
TEST_CHECK_EQ(0, getAttach());
|
||||
TEST_CHECK_EQ(0, getDetach());
|
||||
|
||||
HANDLE thread = CreateThread(NULL, 0, workerProc, NULL, 0, NULL);
|
||||
TEST_CHECK_MSG(thread != NULL, "CreateThread failed: %lu", (unsigned long)GetLastError());
|
||||
DWORD wait_result = WaitForSingleObject(thread, INFINITE);
|
||||
TEST_CHECK_EQ(WAIT_OBJECT_0, wait_result);
|
||||
TEST_CHECK_MSG(CloseHandle(thread) != 0, "CloseHandle(thread) failed: %lu", (unsigned long)GetLastError());
|
||||
|
||||
TEST_CHECK_EQ(1, getAttach());
|
||||
TEST_CHECK_EQ(1, getDetach());
|
||||
|
||||
resetCounts();
|
||||
|
||||
// Wine throws ERR_MOD_NOT_FOUND from DisableThreadLibraryCalls, even if we pass in hinstDLL from DllMain
|
||||
// DLL_PROCESS_ATTACH, which is strange.
|
||||
TEST_CHECK_MSG(disableNotifications() || isRunningUnderWine(), "DisableThreadLibraryCalls failed: %lu",
|
||||
(unsigned long)GetLastError());
|
||||
|
||||
thread = CreateThread(NULL, 0, workerProc, NULL, 0, NULL);
|
||||
TEST_CHECK_MSG(thread != NULL, "CreateThread after disable failed: %lu", (unsigned long)GetLastError());
|
||||
wait_result = WaitForSingleObject(thread, INFINITE);
|
||||
TEST_CHECK_EQ(WAIT_OBJECT_0, wait_result);
|
||||
TEST_CHECK_MSG(CloseHandle(thread) != 0, "CloseHandle(second thread) failed: %lu", (unsigned long)GetLastError());
|
||||
|
||||
if (!isRunningUnderWine()) {
|
||||
TEST_CHECK_EQ(0, getAttach());
|
||||
TEST_CHECK_EQ(0, getDetach());
|
||||
}
|
||||
|
||||
LONG final_attach = getAttach();
|
||||
LONG final_detach = getDetach();
|
||||
|
||||
TEST_CHECK_MSG(FreeLibrary(mod) != 0, "FreeLibrary failed: %lu", (unsigned long)GetLastError());
|
||||
|
||||
printf("thread_notifications: attach=%ld detach=%ld\n", (long)final_attach, (long)final_detach);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user