From 7e1b131a85f92721a6cc367a63266eed177fd328 Mon Sep 17 00:00:00 2001 From: Francois Gouget Date: Tue, 24 Mar 2020 13:50:37 +0100 Subject: [PATCH] kernel32/tests: Add a couple of process helper functions. wait_and_close_child_process() simplifies waiting for the child process and closing its handles. And because it uses wait_child_process() this ensures that any error happening in the child process is detected. reload_child_dump() wraps a cryptic WritePrivateProfileStringA() call and avoids having to add a comment every time. Signed-off-by: Francois Gouget Signed-off-by: Alexandre Julliard --- dlls/kernel32/tests/process.c | 284 +++++++++++++++--------------------------- 1 file changed, 99 insertions(+), 185 deletions(-) diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index 0f0889073b0..7f7c0159473 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -203,6 +203,21 @@ static WCHAR* decodeW(const char* str) return ptr; } +static void wait_and_close_child_process(PROCESS_INFORMATION *pi) +{ + wait_child_process(pi->hProcess); + CloseHandle(pi->hThread); + CloseHandle(pi->hProcess); +} + +static void reload_child_info(const char* resfile) +{ + /* This forces the profile functions to reload the resource file + * after the child process has modified it. + */ + WritePrivateProfileStringA(NULL, NULL, NULL, resfile); +} + /****************************************************************** * init * @@ -615,13 +630,9 @@ static void test_Startup(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + reload_child_info(resfile); GetStartupInfoA(&si); okChildInt("StartupInfoA", "cb", startup.cb); okChildString("StartupInfoA", "lpDesktop", si.lpDesktop); @@ -655,13 +666,9 @@ static void test_Startup(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + reload_child_info(resfile); okChildInt("StartupInfoA", "cb", startup.cb); okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop); okChildString("StartupInfoA", "lpTitle", startup.lpTitle); @@ -695,13 +702,9 @@ static void test_Startup(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + reload_child_info(resfile); okChildInt("StartupInfoA", "cb", startup.cb); okChildString("StartupInfoA", "lpDesktop", si.lpDesktop); okChildString("StartupInfoA", "lpTitle", startup.lpTitle); @@ -735,13 +738,9 @@ static void test_Startup(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + reload_child_info(resfile); okChildInt("StartupInfoA", "cb", startup.cb); okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop); okChildString("StartupInfoA", "lpTitle", startup.lpTitle); @@ -775,13 +774,9 @@ static void test_Startup(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + reload_child_info(resfile); okChildInt("StartupInfoA", "cb", startup.cb); okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop); result = getChildString( "StartupInfoA", "lpTitle" ); @@ -817,13 +812,9 @@ static void test_Startup(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + reload_child_info(resfile); okChildInt("StartupInfoA", "cb", startup.cb); okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop); okChildString("StartupInfoA", "lpTitle", startup.lpTitle); @@ -857,13 +848,9 @@ static void test_Startup(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + reload_child_info(resfile); okChildInt("StartupInfoA", "cb", startup.cb); okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop); okChildString("StartupInfoA", "lpTitle", startup.lpTitle); @@ -920,13 +907,9 @@ static void test_CommandLine(void) ok(startup.lpTitle == NULL, "lpTitle is not NULL\n"); ok(startup.dwFlags == STARTF_USESHOWWINDOW, "unexpected dwFlags %04x\n", startup.dwFlags); ok(startup.wShowWindow == SW_SHOWNORMAL, "unexpected wShowWindow %d\n", startup.wShowWindow); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + reload_child_info(resfile); okChildInt("Arguments", "argcA", 5); okChildString("Arguments", "argvA4", "C:\\Program Files\\my nice app.exe"); okChildString("Arguments", "argvA5", NULL); @@ -938,13 +921,9 @@ static void test_CommandLine(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process dump \"%s\" \"a\\\"b\\\\\" c\\\" d", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + reload_child_info(resfile); okChildInt("Arguments", "argcA", 7); okChildString("Arguments", "argvA4", "a\"b\\"); okChildString("Arguments", "argvA5", "c\""); @@ -963,12 +942,9 @@ static void test_CommandLine(void) SetLastError(0xdeadbeef); ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info); ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError()); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + + reload_child_info(resfile); sprintf(buffer, "./%s", exename); okChildInt("Arguments", "argcA", 5); okChildString("Arguments", "argvA0", buffer); @@ -983,12 +959,9 @@ static void test_CommandLine(void) SetLastError(0xdeadbeef); ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info); ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError()); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + + reload_child_info(resfile); sprintf(buffer, ".\\%s", exename); okChildString("Arguments", "argvA0", buffer); release_memory(); @@ -1005,12 +978,9 @@ static void test_CommandLine(void) SetLastError(0xdeadbeef); ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info); ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError()); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + + reload_child_info(resfile); if (p) sprintf(buffer, "..%s/%s", p, exename); else sprintf(buffer, "./%s", exename); okChildString("Arguments", "argvA0", buffer); @@ -1030,12 +1000,9 @@ static void test_CommandLine(void) SetLastError(0xdeadbeef); ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info); ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError()); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + + reload_child_info(resfile); okChildString("Arguments", "argvA0", "dummy"); okChildString("Arguments", "CommandLineA", buffer2); okChildStringWA("Arguments", "CommandLineW", buffer2); @@ -1128,13 +1095,9 @@ static void test_Directory(void) sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); GetWindowsDirectoryA( windir, sizeof(windir) ); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, windir, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); + reload_child_info(resfile); okChildIString("Misc", "CurrDirA", windir); release_memory(); DeleteFileA(resfile); @@ -1174,11 +1137,9 @@ static void test_Toolhelp(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess failed\n"); - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - CloseHandle(info.hProcess); - CloseHandle(info.hThread); + wait_and_close_child_process(&info); - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + reload_child_info(resfile); okChildInt("Toolhelp", "cntUsage", 0); okChildInt("Toolhelp", "th32DefaultHeapID", 0); okChildInt("Toolhelp", "th32ModuleID", 0); @@ -1192,7 +1153,7 @@ static void test_Toolhelp(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process nested \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess failed\n"); - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); + wait_child_process(info.hProcess); process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, info.dwProcessId); ok(process != NULL, "OpenProcess failed %u\n", GetLastError()); @@ -1214,7 +1175,7 @@ static void test_Toolhelp(void) ok(i < 20 || broken(i == 20), "process object not released\n"); /* Look for the nested process by pid */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + reload_child_info(resfile); nested_pid = GetPrivateProfileIntA("Nested", "Pid", 0, resfile); DeleteFileA(resfile); @@ -1253,11 +1214,10 @@ static void test_Toolhelp(void) ok(ret == 1, "expected 1, got %u\n", ret); CloseHandle(thread); - ret = WaitForSingleObject(process, 30000); - ok(ret == WAIT_OBJECT_0, "Child process termination got %u le=%u\n", ret, GetLastError()); + wait_child_process(process); CloseHandle(process); - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + reload_child_info(resfile); okChildInt("Toolhelp", "cntUsage", 0); okChildInt("Toolhelp", "th32DefaultHeapID", 0); okChildInt("Toolhelp", "th32ModuleID", 0); @@ -1353,11 +1313,9 @@ static void test_Environment(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + wait_and_close_child_process(&info); + reload_child_info(resfile); env = GetEnvironmentStringsA(); cmpEnvironment(env); release_memory(); @@ -1410,11 +1368,9 @@ static void test_Environment(void) } *ptr = '\0'; ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, child_env, NULL, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + wait_and_close_child_process(&info); + reload_child_info(resfile); cmpEnvironment(child_env); HeapFree(GetProcessHeap(), 0, child_env); @@ -1446,13 +1402,11 @@ static void test_SuspendFlag(void) ok(GetExitCodeThread(info.hThread, &exit_status) && exit_status == STILL_ACTIVE, "thread still running\n"); ok(ResumeThread(info.hThread) == 1, "Resuming thread\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + wait_and_close_child_process(&info); GetStartupInfoA(&us); + reload_child_info(resfile); okChildInt("StartupInfoA", "cb", startup.cb); okChildString("StartupInfoA", "lpDesktop", us.lpDesktop); result = getChildString( "StartupInfoA", "lpTitle" ); @@ -1508,13 +1462,11 @@ static void test_DebuggingFlag(void) } while (de.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT); ok(dbg, "I have seen a debug event\n"); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + wait_and_close_child_process(&info); GetStartupInfoA(&us); + reload_child_info(resfile); okChildInt("StartupInfoA", "cb", startup.cb); okChildString("StartupInfoA", "lpDesktop", us.lpDesktop); result = getChildString( "StartupInfoA", "lpTitle" ); @@ -1588,12 +1540,9 @@ static void test_Console(void) get_file_name(resfile); sprintf(buffer, "\"%s\" process dump \"%s\" console", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &info), "CreateProcess\n"); + wait_and_close_child_process(&info); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); - + reload_child_info(resfile); /* now get the modification the child has made, and resets parents expected values */ ok(GetConsoleScreenBufferInfo(startup.hStdOutput, &sbiC), "Getting sb info\n"); ok(GetConsoleMode(startup.hStdInput, &modeInC), "Getting console in mode\n"); @@ -1715,11 +1664,9 @@ static void test_Console(void) /* the child may also send the final "n tests executed" string, so read it to avoid a deadlock */ ReadFile(hParentIn, buffer, sizeof(buffer), &w, NULL); - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + wait_and_close_child_process(&info); + reload_child_info(resfile); okChildString("StdHandle", "msg", msg); release_memory(); @@ -1743,11 +1690,10 @@ static void test_ExitCode(void) sprintf(buffer, "\"%s\" process dump \"%s\" exit_code", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info), "CreateProcess\n"); - /* wait for child to terminate */ + /* not wait_child_process() because of the exit code */ ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - /* child process has changed result file, so let profile functions know about it */ - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + reload_child_info(resfile); ok(GetExitCodeProcess(info.hProcess, &code), "Getting exit code\n"); okChildInt("ExitCode", "value", code); @@ -2458,7 +2404,6 @@ static void test_IsProcessInJob(void) HANDLE job, job2; PROCESS_INFORMATION pi; BOOL ret, out; - DWORD dwret; if (!pIsProcessInJob) { @@ -2503,9 +2448,7 @@ static void test_IsProcessInJob(void) ok(out, "IsProcessInJob returned out=%u\n", out); TerminateProcess(pi.hProcess, 0); - - dwret = WaitForSingleObject(pi.hProcess, 1000); - ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret); + wait_child_process(pi.hProcess); out = FALSE; ret = pIsProcessInJob(pi.hProcess, job, &out); @@ -2536,6 +2479,7 @@ static void test_TerminateJobObject(void) ret = pTerminateJobObject(job, 123); ok(ret, "TerminateJobObject error %u\n", GetLastError()); + /* not wait_child_process() because of the exit code */ dwret = WaitForSingleObject(pi.hProcess, 1000); ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret); if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0); @@ -2550,9 +2494,7 @@ static void test_TerminateJobObject(void) /* Test adding an already terminated process to a job object */ create_process("exit", &pi); - - dwret = WaitForSingleObject(pi.hProcess, 1000); - ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret); + wait_child_process(pi.hProcess); SetLastError(0xdeadbeef); ret = pAssignProcessToJobObject(job, pi.hProcess); @@ -2590,9 +2532,7 @@ static void test_QueryInformationJobObject(void) ok(ret, "AssignProcessToJobObject error %u\n", GetLastError()); ReleaseSemaphore(sem, 1, NULL); - wait_child_process(pi[0].hProcess); - CloseHandle(pi[0].hProcess); - CloseHandle(pi[0].hThread); + wait_and_close_child_process(&pi[0]); create_process("wait", &pi[0]); ret = pAssignProcessToJobObject(job, pi[0].hProcess); @@ -2696,7 +2636,6 @@ static void test_CompletionPort(void) JOBOBJECT_ASSOCIATE_COMPLETION_PORT port_info; PROCESS_INFORMATION pi; HANDLE job, port; - DWORD dwret; BOOL ret; job = pCreateJobObjectW(NULL, NULL); @@ -2718,8 +2657,7 @@ static void test_CompletionPort(void) test_completion(port, JOB_OBJECT_MSG_NEW_PROCESS, (DWORD_PTR)job, pi.dwProcessId, 0); TerminateProcess(pi.hProcess, 0); - dwret = WaitForSingleObject(pi.hProcess, 1000); - ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret); + wait_child_process(pi.hProcess); test_completion(port, JOB_OBJECT_MSG_EXIT_PROCESS, (DWORD_PTR)job, pi.dwProcessId, 0); test_completion(port, JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO, (DWORD_PTR)job, 0, 100); @@ -2757,6 +2695,7 @@ static void test_KillOnJobClose(void) CloseHandle(job); + /* not wait_child_process() for the kill */ dwret = WaitForSingleObject(pi.hProcess, 1000); ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret); if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0); @@ -2847,9 +2786,7 @@ static void test_WaitForJobObject(void) dwret = WaitForSingleObject(job, 100); ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", dwret); - wait_child_process(pi.hProcess); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + wait_and_close_child_process(&pi); CloseHandle(job); CloseHandle(sem); } @@ -2871,7 +2808,6 @@ static HANDLE test_AddSelfToJob(void) static void test_jobInheritance(HANDLE job) { PROCESS_INFORMATION pi; - DWORD dwret; BOOL ret, out; if (!pIsProcessInJob) @@ -2887,11 +2823,7 @@ static void test_jobInheritance(HANDLE job) ok(ret, "IsProcessInJob error %u\n", GetLastError()); ok(out, "IsProcessInJob returned out=%u\n", out); - dwret = WaitForSingleObject(pi.hProcess, 1000); - ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret); - - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + wait_and_close_child_process(&pi); } static void test_BreakawayOk(HANDLE job) @@ -2901,7 +2833,6 @@ static void test_BreakawayOk(HANDLE job) STARTUPINFOA si = {0}; char buffer[MAX_PATH + 23]; BOOL ret, out; - DWORD dwret; if (!pIsProcessInJob) { @@ -2917,12 +2848,7 @@ static void test_BreakawayOk(HANDLE job) if (ret) { TerminateProcess(pi.hProcess, 0); - - dwret = WaitForSingleObject(pi.hProcess, 1000); - ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret); - - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + wait_and_close_child_process(&pi); } limit_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_BREAKAWAY_OK; @@ -2936,11 +2862,7 @@ static void test_BreakawayOk(HANDLE job) ok(ret, "IsProcessInJob error %u\n", GetLastError()); ok(!out, "IsProcessInJob returned out=%u\n", out); - dwret = WaitForSingleObject(pi.hProcess, 1000); - ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret); - - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + wait_and_close_child_process(&pi); limit_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK; ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info)); @@ -2953,11 +2875,7 @@ static void test_BreakawayOk(HANDLE job) ok(ret, "IsProcessInJob error %u\n", GetLastError()); ok(!out, "IsProcessInJob returned out=%u\n", out); - dwret = WaitForSingleObject(pi.hProcess, 1000); - ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret); - - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + wait_and_close_child_process(&pi); /* unset breakaway ok */ limit_info.BasicLimitInformation.LimitFlags = 0; @@ -2980,8 +2898,9 @@ static void test_StartupNoConsole(void) sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n"); - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + wait_and_close_child_process(&info); + + reload_child_info(resfile); okChildInt("StartupInfoA", "hStdInput", (UINT)INVALID_HANDLE_VALUE); okChildInt("StartupInfoA", "hStdOutput", (UINT)INVALID_HANDLE_VALUE); okChildInt("StartupInfoA", "hStdError", (UINT)INVALID_HANDLE_VALUE); @@ -3012,9 +2931,9 @@ static void test_DetachConsoleHandles(void) sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile); ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n"); - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + wait_and_close_child_process(&info); + reload_child_info(resfile); result = GetPrivateProfileIntA("StartupInfoA", "hStdInput", 0, resfile); ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result); result = GetPrivateProfileIntA("StartupInfoA", "hStdOutput", 0, resfile); @@ -3203,10 +3122,11 @@ static void test_SuspendProcessNewThread(void) if (thread_handle) CloseHandle(thread_handle); + /* Note that the child's main thread is still suspended so the exit code + * is set by the TerminateProcess() call. + */ TerminateProcess(pi.hProcess, 0); - WaitForSingleObject(pi.hProcess, 10000); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + wait_and_close_child_process(&pi); } static void test_SuspendProcessState(void) @@ -3400,8 +3320,12 @@ static void test_SuspendProcessState(void) ret = WriteFile(server_pipe_handle, &pipe_magic, sizeof(pipe_magic), &numb, NULL); ok(ret, "Failed to write the magic back to the pipe (%d)\n", GetLastError()); - CloseHandle(server_pipe_handle); + + /* Avoid wait_child_process() because the exit code results from a race + * between the TerminateProcess() call and the child's ExitProcess() call + * which uses a random value in the 64 bit case. + */ TerminateProcess(pi.hProcess, 0); WaitForSingleObject(pi.hProcess, 10000); CloseHandle(pi.hProcess); @@ -3452,8 +3376,9 @@ static void test_DetachStdHandles(void) SetStdHandle(STD_ERROR_HANDLE, hstderr); ok(res, "CreateProcess failed\n"); - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - WritePrivateProfileStringA(NULL, NULL, NULL, resfile); + wait_and_close_child_process(&info); + + reload_child_info(resfile); okChildInt("StartupInfoA", "hStdInput", (UINT)INVALID_HANDLE_VALUE); okChildInt("StartupInfoA", "hStdOutput", (UINT)INVALID_HANDLE_VALUE); okChildInt("StartupInfoA", "hStdError", (UINT)INVALID_HANDLE_VALUE); @@ -3930,9 +3855,7 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe) ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, (STARTUPINFOA *)&si, &info); ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); #endif si.lpAttributeList = heap_alloc(size); ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size); @@ -3944,9 +3867,7 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe) ret = CreateProcessA(NULL, buffer, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, (STARTUPINFOA *)&si, &info); ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); CloseHandle(handle); pDeleteProcThreadAttributeList(si.lpAttributeList); heap_free(si.lpAttributeList); @@ -3992,11 +3913,7 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe) ok(ret || broken(!ret && GetLastError() == ERROR_INVALID_HANDLE), "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); if (ret) - { - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); - } + wait_and_close_child_process(&info); pDeleteProcThreadAttributeList(si.lpAttributeList); heap_free(si.lpAttributeList); @@ -4027,10 +3944,7 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe) ret = WriteFile(write_pipe, &parent_data, sizeof(parent_data), &size, NULL); } - /* wait for child to terminate */ - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - CloseHandle(info.hThread); - CloseHandle(info.hProcess); + wait_and_close_child_process(&info); if (!level) { -- 2.11.4.GIT