kernel32/tests: Some tests for initial thread activation context.
This commit is contained in:
parent
bb50d6fd95
commit
ab08d2a5ba
@ -30,6 +30,7 @@
|
|||||||
#include <winbase.h>
|
#include <winbase.h>
|
||||||
#include <winnt.h>
|
#include <winnt.h>
|
||||||
#include <winerror.h>
|
#include <winerror.h>
|
||||||
|
#include <winnls.h>
|
||||||
|
|
||||||
/* Specify the number of simultaneous threads to test */
|
/* Specify the number of simultaneous threads to test */
|
||||||
#define NUM_THREADS 4
|
#define NUM_THREADS 4
|
||||||
@ -54,6 +55,14 @@
|
|||||||
# endif
|
# endif
|
||||||
#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 BOOL (WINAPI *pGetThreadPriorityBoost)(HANDLE,PBOOL);
|
||||||
static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD);
|
static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD);
|
||||||
static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
|
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 BOOL (WINAPI *pSetThreadErrorMode)(DWORD,PDWORD);
|
||||||
static DWORD (WINAPI *pGetThreadErrorMode)(void);
|
static DWORD (WINAPI *pGetThreadErrorMode)(void);
|
||||||
static DWORD (WINAPI *pRtlGetThreadErrorMode)(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)
|
static HANDLE create_target_process(const char *arg)
|
||||||
{
|
{
|
||||||
@ -258,6 +272,28 @@ static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
|
|||||||
return 0;
|
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])
|
static void create_function_addr_events(HANDLE events[2])
|
||||||
{
|
{
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
@ -1432,28 +1468,160 @@ static void test_thread_fpu_cw(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#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(¶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)
|
START_TEST(thread)
|
||||||
{
|
{
|
||||||
HINSTANCE lib;
|
|
||||||
HINSTANCE ntdll;
|
HINSTANCE ntdll;
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
argc = winetest_get_mainargs( &argv );
|
argc = winetest_get_mainargs( &argv );
|
||||||
/* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
|
|
||||||
so that the compile passes
|
init_funcs();
|
||||||
*/
|
|
||||||
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");
|
|
||||||
|
|
||||||
ntdll=GetModuleHandleA("ntdll.dll");
|
ntdll=GetModuleHandleA("ntdll.dll");
|
||||||
if (ntdll)
|
if (ntdll)
|
||||||
@ -1507,4 +1675,5 @@ START_TEST(thread)
|
|||||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||||
test_thread_fpu_cw();
|
test_thread_fpu_cw();
|
||||||
#endif
|
#endif
|
||||||
|
test_thread_actctx();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user