[2/5] kernel: add CreateRemoteThread remote thread conformance tests (updated)

Thomas Kho tkho at ucla.edu
Wed Aug 16 03:56:07 CDT 2006


[2/5] kernel: add CreateRemoteThread remote thread conformance tests (updated)

This patch updates
http://www.winehq.org/pipermail/wine-patches/2006-July/029260.html and adds a
small stress test (0.5 seconds or until user input in interactive mode) on top
of the correctness tests. It also changes the entry-point in the remote process
to ntdll!NtQuerySystemTime as kernel32 is often times not mapped to the same
place in different processes. This patch depends on part 1 (VirtualAllocEx
tests) for some functions.

Thomas Kho

---

 dlls/kernel/tests/thread.c |  108 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 107 insertions(+), 1 deletions(-)

diff --git a/dlls/kernel/tests/thread.c b/dlls/kernel/tests/thread.c
index 00951b3..b631d79 100644
--- a/dlls/kernel/tests/thread.c
+++ b/dlls/kernel/tests/thread.c
@@ -22,6 +22,7 @@
 #define _WIN32_WINNT 0x0500
 
 #include <stdarg.h>
+#include <stdio.h>
 
 #include "wine/test.h"
 #include <windef.h>
@@ -67,9 +68,14 @@ static SetThreadIdealProcessor_t pSetThr
 typedef BOOL (WINAPI *SetThreadPriorityBoost_t)(HANDLE,BOOL);
 static SetThreadPriorityBoost_t pSetThreadPriorityBoost=NULL;
 
+/* from virtual.c */
+extern HANDLE hStressTestProcess;
+extern HANDLE hStressTestQuitEvent;
+extern HANDLE create_process(char *);
+extern void mini_stress_test(LPTHREAD_START_ROUTINE worker, char *name);
+
 /* Functions not tested yet:
   AttachThreadInput
-  CreateRemoteThread
   SetThreadContext
   SwitchToThread
 
@@ -175,6 +181,104 @@ static DWORD WINAPI threadFunc5(LPVOID p
 }
 #endif
 
+/* check CreateRemoteThread */
+static VOID test_CreateRemoteThread(void)
+{
+    HANDLE hNotepad, hThread;
+    HMODULE hntdll;
+    FARPROC nt_query_system_time;
+    DWORD tid, ret;
+    LARGE_INTEGER *pli, li;
+
+    /* necessary as the test is statically linked  */
+    hntdll = GetModuleHandle("ntdll.dll");
+    ok(hntdll != NULL, "GetModuleHandle failed, err=%lu\n", GetLastError());
+    nt_query_system_time = GetProcAddress(hntdll, "NtQuerySystemTime");
+    ok(nt_query_system_time != NULL, "GetProcAddress failed err=%lu\n",
+       GetLastError());
+
+    hNotepad = create_process("notepad.exe");
+    ok(hNotepad != NULL, "Can't start notepad.exe\n");
+
+    pli = VirtualAllocEx(hNotepad, NULL, sizeof(li), MEM_COMMIT|MEM_RESERVE,
+                         PAGE_EXECUTE_READWRITE);
+    todo_wine ok(pli != NULL, "VirtualAllocEx failed %lu\n", GetLastError());
+
+    li.QuadPart = 0;
+    WriteProcessMemory(hNotepad, pli, &li, sizeof(li), NULL);
+
+    /* create suspended remote thread with entry point NtQuerySystemTime() */
+    hThread = CreateRemoteThread(hNotepad, NULL, 0,
+                                 (LPTHREAD_START_ROUTINE) nt_query_system_time,
+                                 pli, 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 data not changed */
+    ReadProcessMemory(hNotepad, pli, &li, sizeof(li), NULL);
+    ok(li.QuadPart == 0, "li is (%llu)\n", li.QuadPart);
+
+    ret = ResumeThread(hThread);
+    todo_wine ok(ret == 1, "ret=%lu, err=%lu\n", ret, GetLastError());
+
+    /* 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);
+
+    /* read data again, check non-zero */
+    ReadProcessMemory(hNotepad, pli, &li, sizeof(li), NULL);
+    todo_wine ok(li.QuadPart != 0, "li is (%llu)\n", li.QuadPart);
+
+    TerminateProcess(hNotepad, 0);
+    CloseHandle(hNotepad);
+}
+
+static DWORD WINAPI create_remote_thread_worker(LPVOID lpParameter)
+{
+    HMODULE hntdll;
+    FARPROC nt_query_system_time;
+    LARGE_INTEGER *pli;
+
+    hntdll = GetModuleHandle("ntdll.dll");
+    ok(hntdll != NULL, "GetModuleHandle failed, err=%lu\n", GetLastError());
+    nt_query_system_time = GetProcAddress(hntdll, "NtQuerySystemTime");
+    ok(nt_query_system_time != NULL, "GetProcAddress failed err=%lu\n",
+       GetLastError());
+
+    pli = VirtualAllocEx(hStressTestProcess, NULL, sizeof(*pli),
+                         MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+    todo_wine ok(pli != NULL, "VirtualAllocEx failed %lu\n", GetLastError());
+
+    while (WaitForSingleObject(hStressTestQuitEvent, 0) != WAIT_OBJECT_0)
+    {
+        HANDLE hThread;
+        hThread = CreateRemoteThread(hStressTestProcess, NULL, 0,
+                                     (LPTHREAD_START_ROUTINE)
+                                     nt_query_system_time, pli, 0,
+                                     NULL);
+        todo_wine ok(hThread != NULL, "CreateRemoteThread failed, error %lu\n",
+                     GetLastError());
+        todo_wine ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
+                     "Remote thread did not exit in time\n");
+        if (hThread == NULL) break;
+        CloseHandle(hThread);
+    }
+    return 0;
+}
+
+/* mini stress test for CreateRemoteThread */
+static VOID test_CreateRemoteThread_ministress(void)
+{
+    mini_stress_test(create_remote_thread_worker, "remote thread");
+}
+
 /* Check basic funcationality of CreateThread and Tls* functions */
 static VOID test_CreateThread_basic(void)
 {
@@ -733,6 +837,8 @@ START_TEST(thread)
    pQueueUserWorkItem=(QueueUserWorkItem_t)GetProcAddress(lib,"QueueUserWorkItem");
    pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
    pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
+   test_CreateRemoteThread();
+   test_CreateRemoteThread_ministress();
    test_CreateThread_basic();
    test_CreateThread_suspended();
    test_SuspendThread();



More information about the wine-patches mailing list