kernel: add CreateRemoteThread remote thread tests Thomas Kho --- dlls/kernel/tests/thread.c | 90 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 89 insertions(+), 1 deletions(-) diff --git a/dlls/kernel/tests/thread.c b/dlls/kernel/tests/thread.c index 00951b3..645730c 100644 --- a/dlls/kernel/tests/thread.c +++ b/dlls/kernel/tests/thread.c @@ -67,9 +67,10 @@ static SetThreadIdealProcessor_t pSetThr typedef BOOL (WINAPI *SetThreadPriorityBoost_t)(HANDLE,BOOL); static SetThreadPriorityBoost_t pSetThreadPriorityBoost=NULL; +extern HANDLE create_process(char *); + /* Functions not tested yet: AttachThreadInput - CreateRemoteThread SetThreadContext SwitchToThread @@ -175,6 +176,92 @@ static DWORD WINAPI threadFunc5(LPVOID p } #endif +static VOID test_CreateRemoteThread(void) +{ + HANDLE hNotepad, hThread, hEvent, hRemoteEvent; + HMODULE hkernel32; + FARPROC set_event, close_handle; + DWORD tid, ret, exitcode; + + hkernel32 = GetModuleHandle("kernel32.dll"); + ok(hkernel32 != NULL, "GetModuleHandle failed, err=%lu\n", GetLastError()); + set_event = GetProcAddress(hkernel32, "SetEvent"); + ok(set_event != NULL, "GetProcAddress failed err=%lu\n", GetLastError()); + close_handle = GetProcAddress(hkernel32, "CloseHandle"); + ok(close_handle != NULL, "GetProcAddress failed err=%lu\n", GetLastError()); + hNotepad = create_process("notepad.exe"); + ok(hNotepad != NULL, "Can't start notepad.exe\n"); + + hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + ok(hEvent != NULL, "Can't create event, err=%lu\n", GetLastError()); + ret = DuplicateHandle(GetCurrentProcess(), hEvent, hNotepad, &hRemoteEvent, + 0, FALSE, DUPLICATE_SAME_ACCESS); + ok(ret != 0, "DuplicateHandle failed, err=%lu\n", GetLastError()); + + /* create suspended remote thread with entry point SetEvent() */ + hThread = CreateRemoteThread(hNotepad, NULL, 0, + (LPTHREAD_START_ROUTINE) set_event, + hRemoteEvent, CREATE_SUSPENDED, &tid); + todo_wine ok(hThread != NULL, "CreateRemoteThread failed, err=%lu\n", + GetLastError()); + ok(tid != 0, "null tid\n"); + ret = SuspendThread(hThread); + todo_wine ok(ret == 1, "ret=%lu, err=%lu\n", ret, GetLastError()); + ret = ResumeThread(hThread); + todo_wine ok(ret == 2, "ret=%lu, err=%lu\n", ret, GetLastError()); + + /* thread still suspended, so wait times out */ + ret = WaitForSingleObject(hEvent, 100); + ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%lu\n", ret); + + ret = ResumeThread(hThread); + todo_wine ok(ret == 1, "ret=%lu, err=%lu\n", ret, GetLastError()); + + /* wait that doesn't time out */ + ret = WaitForSingleObject(hEvent, 100); + todo_wine ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%lu\n", ret); + + /* wait for thread end */ + ret = WaitForSingleObject(hThread, 100); + todo_wine ok(ret == WAIT_OBJECT_0, + "waiting for thread failed, ret=%lu\n", ret); + CloseHandle(hThread); + + /* create and wait for remote thread with entry point CloseHandle() */ + hThread = CreateRemoteThread(hNotepad, NULL, 0, + (LPTHREAD_START_ROUTINE) close_handle, + hRemoteEvent, 0, &tid); + todo_wine ok(hThread != NULL, + "CreateRemoteThread failed, err=%lu\n", GetLastError()); + ret = WaitForSingleObject(hThread, 100); + todo_wine ok(ret == WAIT_OBJECT_0, + "waiting for thread failed, ret=%lu\n", ret); + CloseHandle(hThread); + + /* create remote thread with entry point SetEvent() */ + hThread = CreateRemoteThread(hNotepad, NULL, 0, + (LPTHREAD_START_ROUTINE) set_event, + hRemoteEvent, 0, &tid); + todo_wine ok(hThread != NULL, + "CreateRemoteThread failed, err=%lu\n", GetLastError()); + + /* closed handle, so wait times out */ + ret = WaitForSingleObject(hEvent, 100); + ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%lu\n", ret); + + /* check that remote SetEvent() failed */ + ret = GetExitCodeThread(hThread, &exitcode); + todo_wine ok(ret != 0, + "GetExitCodeThread failed, err=%lu\n", GetLastError()); + todo_wine ok(exitcode == 0, + "SetEvent succeeded, expected to fail\n"); + CloseHandle(hThread); + + TerminateProcess(hNotepad, 0); + CloseHandle(hEvent); + CloseHandle(hNotepad); +} + /* Check basic funcationality of CreateThread and Tls* functions */ static VOID test_CreateThread_basic(void) { @@ -733,6 +820,7 @@ START_TEST(thread) pQueueUserWorkItem=(QueueUserWorkItem_t)GetProcAddress(lib,"QueueUserWorkItem"); pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor"); pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost"); + test_CreateRemoteThread(); test_CreateThread_basic(); test_CreateThread_suspended(); test_SuspendThread();