Commit ab08d2a5 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

kernel32/tests: Some tests for initial thread activation context.

parent bb50d6fd
......@@ -30,6 +30,7 @@
#include <winbase.h>
#include <winnt.h>
#include <winerror.h>
#include <winnls.h>
/* 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[] =
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
"<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
" <file name=\"testdep.dll\" />"
"</assembly>";
static const char manifest_main[] =
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
"<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
"<dependency>"
" <dependentAssembly>"
" <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
" </dependentAssembly>"
"</dependency>"
"</assembly>";
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(&param.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, &param, 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, &param, 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();
}
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