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