1 /* 2 * Unit test suite for process functions 3 * 4 * Copyright 2017 Michael Müller 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "ntdll_test.h" 22 23 static NTSTATUS (WINAPI *pNtResumeProcess)(HANDLE); 24 static NTSTATUS (WINAPI *pNtSuspendProcess)(HANDLE); 25 static NTSTATUS (WINAPI *pNtSuspendThread)(HANDLE,PULONG); 26 static NTSTATUS (WINAPI *pNtResumeThread)(HANDLE); 27 28 static void test_NtSuspendProcess(char *process_name) 29 { 30 PROCESS_INFORMATION info; 31 DEBUG_EVENT ev; 32 STARTUPINFOA startup; 33 NTSTATUS status; 34 HANDLE event; 35 char buffer[MAX_PATH]; 36 ULONG count; 37 DWORD ret; 38 39 status = pNtResumeProcess(GetCurrentProcess()); 40 ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); 41 42 event = CreateEventA(NULL, TRUE, FALSE, "wine_suspend_event"); 43 ok(!!event, "Failed to create event: %u\n", GetLastError()); 44 45 memset(&startup, 0, sizeof(startup)); 46 startup.cb = sizeof(startup); 47 48 sprintf(buffer, "%s tests/process.c dummy_process wine_suspend_event", process_name); 49 ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info); 50 ok(ret, "CreateProcess failed with error %u\n", GetLastError()); 51 52 ret = WaitForSingleObject(event, 500); 53 ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret); 54 55 status = pNtSuspendProcess(info.hProcess); 56 ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); 57 58 ResetEvent(event); 59 60 ret = WaitForSingleObject(event, 200); 61 ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); 62 63 status = NtResumeThread(info.hThread, &count); 64 ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); 65 ok(count == 1, "Expected count 1, got %d\n", count); 66 67 ret = WaitForSingleObject(event, 200); 68 ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret); 69 70 status = pNtResumeProcess(info.hProcess); 71 ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); 72 73 status = pNtSuspendThread(info.hThread, &count); 74 ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status); 75 ok(count == 0, "Expected count 0, got %d\n", count); 76 77 ResetEvent(event); 78 79 ret = WaitForSingleObject(event, 200); 80 ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); 81 82 status = pNtResumeProcess(info.hProcess); 83 ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); 84 85 ret = WaitForSingleObject(event, 200); 86 ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret); 87 88 status = pNtSuspendThread(info.hThread, &count); 89 ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status); 90 ok(count == 0, "Expected count 0, got %d\n", count); 91 92 status = pNtSuspendThread(info.hThread, &count); 93 ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status); 94 ok(count == 1, "Expected count 1, got %d\n", count); 95 96 ResetEvent(event); 97 98 ret = WaitForSingleObject(event, 200); 99 ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); 100 101 status = pNtResumeProcess(info.hProcess); 102 ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); 103 104 ret = WaitForSingleObject(event, 200); 105 ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); 106 107 status = pNtResumeProcess(info.hProcess); 108 ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); 109 110 ret = WaitForSingleObject(event, 200); 111 ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret); 112 113 ret = DebugActiveProcess(info.dwProcessId); 114 ok(ret, "Failed to debug process: %d\n", GetLastError()); 115 116 ResetEvent(event); 117 118 ret = WaitForSingleObject(event, 200); 119 ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); 120 121 for (;;) 122 { 123 ret = WaitForDebugEvent(&ev, INFINITE); 124 ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError()); 125 if (!ret) break; 126 127 if (ev.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) break; 128 129 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE); 130 ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError()); 131 if (!ret) break; 132 } 133 134 ResetEvent(event); 135 136 ret = WaitForSingleObject(event, 200); 137 ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); 138 139 status = pNtResumeProcess(info.hProcess); 140 ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); 141 142 ret = WaitForSingleObject(event, 200); 143 ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); 144 145 status = NtResumeThread(info.hThread, &count); 146 ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); 147 ok(count == 0, "Expected count 0, got %d\n", count); 148 149 ret = WaitForSingleObject(event, 200); 150 ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); 151 152 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE); 153 ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError()); 154 155 ret = WaitForSingleObject(event, 200); 156 ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret); 157 158 TerminateProcess(info.hProcess, 0); 159 160 CloseHandle(info.hProcess); 161 CloseHandle(info.hThread); 162 } 163 164 static void dummy_process(char *event_name) 165 { 166 HANDLE event = OpenEventA(EVENT_ALL_ACCESS, FALSE, event_name); 167 168 while (TRUE) 169 { 170 SetEvent(event); 171 OutputDebugStringA("test"); 172 Sleep(5); 173 } 174 } 175 176 START_TEST(process) 177 { 178 HMODULE mod; 179 char **argv; 180 int argc; 181 182 argc = winetest_get_mainargs(&argv); 183 if (argc >= 4 && strcmp(argv[2], "dummy_process") == 0) 184 { 185 dummy_process(argv[3]); 186 return; 187 } 188 189 mod = GetModuleHandleA("ntdll.dll"); 190 if (!mod) 191 { 192 win_skip("Not running on NT, skipping tests\n"); 193 return; 194 } 195 196 pNtResumeProcess = (void*)GetProcAddress(mod, "NtResumeProcess"); 197 pNtSuspendProcess = (void*)GetProcAddress(mod, "NtSuspendProcess"); 198 pNtResumeThread = (void*)GetProcAddress(mod, "NtResumeThread"); 199 pNtSuspendThread = (void*)GetProcAddress(mod, "NtSuspendThread"); 200 201 test_NtSuspendProcess(argv[0]); 202 } 203