From ab08d2a5ba3a5ac9778af269912151337b3e7b1c Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 5 Sep 2013 11:27:45 +0400 Subject: [PATCH] kernel32/tests: Some tests for initial thread activation context. --- dlls/kernel32/tests/thread.c | 201 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 185 insertions(+), 16 deletions(-) diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c index 9be048498de..0f3564f4bfc 100644 --- a/dlls/kernel32/tests/thread.c +++ b/dlls/kernel32/tests/thread.c @@ -30,6 +30,7 @@ #include #include #include +#include /* Specify the number of simultaneous threads to test */ #define NUM_THREADS 4 @@ -54,6 +55,14 @@ # endif #endif +#ifdef __i386__ +#define ARCH "x86" +#elif defined __x86_64__ +#define ARCH "amd64" +#else +#define ARCH "none" +#endif + static BOOL (WINAPI *pGetThreadPriorityBoost)(HANDLE,PBOOL); static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD); static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG); @@ -65,6 +74,11 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL); static BOOL (WINAPI *pSetThreadErrorMode)(DWORD,PDWORD); static DWORD (WINAPI *pGetThreadErrorMode)(void); static DWORD (WINAPI *pRtlGetThreadErrorMode)(void); +static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*); +static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW); +static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR); +static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *); +static void (WINAPI *pReleaseActCtx)(HANDLE); static HANDLE create_target_process(const char *arg) { @@ -258,6 +272,28 @@ static DWORD WINAPI threadFunc_CloseHandle(LPVOID p) return 0; } +struct thread_actctx_param +{ + HANDLE thread_context; + HANDLE handle; +}; + +static DWORD WINAPI thread_actctx_func(void *p) +{ + struct thread_actctx_param *param = (struct thread_actctx_param*)p; + HANDLE cur; + BOOL ret; + + cur = (void*)0xdeadbeef; + ret = pGetCurrentActCtx(&cur); + ok(ret, "thread GetCurrentActCtx failed, %u\n", GetLastError()); +todo_wine + ok(cur == param->handle, "got %p, expected %p\n", cur, param->handle); + param->thread_context = cur; + + return 0; +} + static void create_function_addr_events(HANDLE events[2]) { char buffer[256]; @@ -1432,28 +1468,160 @@ static void test_thread_fpu_cw(void) } #endif +static const char manifest_dep[] = +"" +"" +" " +""; + +static const char manifest_main[] = +"" +"" +"" +" " +" " +" " +"" +""; + +static void create_manifest_file(const char *filename, const char *manifest) +{ + WCHAR path[MAX_PATH]; + HANDLE file; + DWORD size; + + MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH ); + file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); + WriteFile(file, manifest, strlen(manifest), &size, NULL); + CloseHandle(file); +} + +static HANDLE test_create(const char *file) +{ + WCHAR path[MAX_PATH]; + ACTCTXW actctx; + HANDLE handle; + + MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH); + memset(&actctx, 0, sizeof(ACTCTXW)); + actctx.cbSize = sizeof(ACTCTXW); + actctx.lpSource = path; + + handle = pCreateActCtxW(&actctx); + ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError()); + + ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize); + ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags); + ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource); + ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture); + ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId); + ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory); + ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName); + ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName); + ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule); + + return handle; +} + +static void test_thread_actctx(void) +{ + struct thread_actctx_param param; + HANDLE thread, handle, context; + ULONG_PTR cookie; + DWORD tid, ret; + BOOL b; + + if (!pActivateActCtx) + { + win_skip("skipping activation context tests\n"); + return; + } + + create_manifest_file("testdep1.manifest", manifest_dep); + create_manifest_file("main.manifest", manifest_main); + + context = test_create("main.manifest"); + DeleteFileA("testdep1.manifest"); + DeleteFileA("main.manifest"); + + handle = (void*)0xdeadbeef; + b = pGetCurrentActCtx(&handle); + ok(b, "GetCurentActCtx failed: %u\n", GetLastError()); + ok(handle == 0, "active context %p\n", handle); + + b = pActivateActCtx(context, &cookie); + ok(b, "activation failed: %u\n", GetLastError()); + + handle = 0; + b = pGetCurrentActCtx(&handle); + ok(b, "GetCurentActCtx failed: %u\n", GetLastError()); + ok(handle != 0, "no active context\n"); + + param.handle = NULL; + b = pGetCurrentActCtx(¶m.handle); + ok(b && param.handle != NULL, "failed to get context, %u\n", GetLastError()); + + param.thread_context = (void*)0xdeadbeef; + thread = CreateThread(NULL, 0, thread_actctx_func, ¶m, 0, &tid); + ok(thread != NULL, "failed, got %u\n", GetLastError()); + + ret = WaitForSingleObject(thread, 1000); + ok(ret == WAIT_OBJECT_0, "wait timeout\n"); +todo_wine + ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context); + CloseHandle(thread); + + /* similar test for CreateRemoteThread() */ + param.thread_context = (void*)0xdeadbeef; + thread = CreateRemoteThread(GetCurrentProcess(), NULL, 0, thread_actctx_func, ¶m, 0, &tid); + ok(thread != NULL, "failed, got %u\n", GetLastError()); + + ret = WaitForSingleObject(thread, 1000); + ok(ret == WAIT_OBJECT_0, "wait timeout\n"); +todo_wine + ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context); + CloseHandle(thread); + + b = pDeactivateActCtx(0, cookie); + ok(b, "DeactivateActCtx failed: %u\n", GetLastError()); + pReleaseActCtx(context); +} + +static void init_funcs(void) +{ + HMODULE hKernel32 = GetModuleHandle("kernel32"); + +/* Neither Cygwin nor mingW export OpenThread, so do a dynamic check + so that the compile passes */ + +#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f) + X(GetThreadPriorityBoost); + X(OpenThread); + X(QueueUserWorkItem); + X(SetThreadIdealProcessor); + X(SetThreadPriorityBoost); + X(RegisterWaitForSingleObject); + X(UnregisterWait); + X(IsWow64Process); + X(SetThreadErrorMode); + X(GetThreadErrorMode); + X(ActivateActCtx); + X(CreateActCtxW); + X(DeactivateActCtx); + X(GetCurrentActCtx); + X(ReleaseActCtx); +#undef X +} + START_TEST(thread) { - HINSTANCE lib; HINSTANCE ntdll; int argc; char **argv; argc = winetest_get_mainargs( &argv ); -/* Neither Cygwin nor mingW export OpenThread, so do a dynamic check - so that the compile passes -*/ - lib=GetModuleHandleA("kernel32.dll"); - ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n"); - pGetThreadPriorityBoost=(void *)GetProcAddress(lib,"GetThreadPriorityBoost"); - pOpenThread=(void *)GetProcAddress(lib,"OpenThread"); - pQueueUserWorkItem=(void *)GetProcAddress(lib,"QueueUserWorkItem"); - pSetThreadIdealProcessor=(void *)GetProcAddress(lib,"SetThreadIdealProcessor"); - pSetThreadPriorityBoost=(void *)GetProcAddress(lib,"SetThreadPriorityBoost"); - pRegisterWaitForSingleObject=(void *)GetProcAddress(lib,"RegisterWaitForSingleObject"); - pUnregisterWait=(void *)GetProcAddress(lib,"UnregisterWait"); - pIsWow64Process=(void *)GetProcAddress(lib,"IsWow64Process"); - pSetThreadErrorMode=(void *)GetProcAddress(lib,"SetThreadErrorMode"); - pGetThreadErrorMode=(void *)GetProcAddress(lib,"GetThreadErrorMode"); + + init_funcs(); ntdll=GetModuleHandleA("ntdll.dll"); if (ntdll) @@ -1507,4 +1675,5 @@ START_TEST(thread) #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) test_thread_fpu_cw(); #endif + test_thread_actctx(); } -- 2.11.4.GIT