ReactOS 0.4.16-dev-2207-geb15453
toolhelp.c
Go to the documentation of this file.
1/*
2 * Toolhelp
3 *
4 * Copyright 2005 Eric Pouech
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 <stdarg.h>
22#include <stdlib.h>
23#include <stdio.h>
24
25#include "ntstatus.h"
26#define WIN32_NO_STATUS
27#include "windef.h"
28#include "winbase.h"
29#include "tlhelp32.h"
30#include "wine/test.h"
31#include "winuser.h"
32#include "winternl.h"
33
34static char selfname[MAX_PATH];
35
36/* Some functions are only in later versions of kernel32.dll */
37static HANDLE (WINAPI *pCreateToolhelp32Snapshot)(DWORD, DWORD);
38static BOOL (WINAPI *pModule32First)(HANDLE, LPMODULEENTRY32);
39static BOOL (WINAPI *pModule32Next)(HANDLE, LPMODULEENTRY32);
40static BOOL (WINAPI *pProcess32First)(HANDLE, LPPROCESSENTRY32);
41static BOOL (WINAPI *pProcess32Next)(HANDLE, LPPROCESSENTRY32);
42static BOOL (WINAPI *pThread32First)(HANDLE, LPTHREADENTRY32);
43static BOOL (WINAPI *pThread32Next)(HANDLE, LPTHREADENTRY32);
44static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, void *, ULONG, ULONG *);
45
46/* 1 minute should be more than enough */
47#define WAIT_TIME (60 * 1000)
48/* Specify the number of simultaneous threads to test */
49#define NUM_THREADS 4
50
51static DWORD WINAPI sub_thread(void* pmt)
52{
54 return w;
55}
56
57/******************************************************************
58 * init
59 *
60 * generates basic information like:
61 * selfname: the way to reinvoke ourselves
62 * returns:
63 * -1 on error
64 * 0 if parent
65 * doesn't return if child
66 */
67static int init(void)
68{
69 int argc;
70 char** argv;
71 HANDLE ev1, ev2, ev3, hThread;
72 DWORD w, tid;
73
75 strcpy(selfname, argv[0]);
76
77 switch (argc)
78 {
79 case 2: /* the test program */
80 return 0;
81 case 4: /* the sub-process */
82 ev1 = (HANDLE)(INT_PTR)atoi(argv[2]);
83 ev2 = (HANDLE)(INT_PTR)atoi(argv[3]);
85
86 if (ev3 == NULL) ExitProcess(WAIT_ABANDONED);
87 hThread = CreateThread(NULL, 0, sub_thread, ev3, 0, &tid);
89 if (!LoadLibraryA("shell32.dll")) ExitProcess(WAIT_ABANDONED);
90
91 /* signal init of sub-process is done */
92 SetEvent(ev1);
93 /* wait for parent to have done all its queries */
96 /* signal sub-thread to terminate */
97 SetEvent(ev3);
101 ExitProcess(w);
102 default:
103 return -1;
104 }
105}
106
107static void test_process(DWORD curr_pid, DWORD sub_pcs_pid)
108{
109 HANDLE hSnapshot;
111 MODULEENTRY32 me;
112 unsigned found = 0;
113 int num = 0;
114 int childpos = -1;
115
116 hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
117 ok(hSnapshot != NULL, "Cannot create snapshot\n");
118
119 /* check that this current process is enumerated */
120 pe.dwSize = sizeof(pe);
121 if (pProcess32First( hSnapshot, &pe ))
122 {
123 do
124 {
125 if (pe.th32ProcessID == curr_pid) found++;
126 if (pe.th32ProcessID == sub_pcs_pid) { childpos = num; found++; }
127 trace("PID=%lx %s\n", pe.th32ProcessID, pe.szExeFile);
128 num++;
129 } while (pProcess32Next( hSnapshot, &pe ));
130 }
131#if defined(__REACTOS__) && defined(_WIN64)
132 ok(found == 2 || broken(found == 0) /* x86_64 */, "couldn't find self and/or sub-process in process list\n");
133#else
134 ok(found == 2, "couldn't find self and/or sub-process in process list\n");
135#endif
136
137 /* check that first really resets the enumeration */
138 found = 0;
139 if (pProcess32First( hSnapshot, &pe ))
140 {
141 do
142 {
143 if (pe.th32ProcessID == curr_pid) found++;
144 if (pe.th32ProcessID == sub_pcs_pid) found++;
145 trace("PID=%lx %s\n", pe.th32ProcessID, pe.szExeFile);
146 num--;
147 } while (pProcess32Next( hSnapshot, &pe ));
148 }
149#if defined(__REACTOS__) && defined(_WIN64)
150 ok(found == 2 || broken(found == 0) /* x86_64 */, "couldn't find self and/or sub-process in process list\n");
151#else
152 ok(found == 2, "couldn't find self and/or sub-process in process list\n");
153#endif
154 ok(!num, "mismatch in counting\n");
155
156 /* one broken program does Process32First() and does not expect anything
157 * interesting to be there, especially not the just forked off child */
158 ok (childpos !=0, "child is not expected to be at position 0.\n");
159
160 me.dwSize = sizeof(me);
161 ok(!pModule32First( hSnapshot, &me ), "shouldn't return a module\n");
162
163 CloseHandle(hSnapshot);
164 ok(!pProcess32First( hSnapshot, &pe ), "shouldn't return a process\n");
165}
166
167static DWORD WINAPI get_id_thread(void* curr_pid)
168{
169 HANDLE hSnapshot;
170 THREADENTRY32 te;
172 DWORD thread_ids[NUM_THREADS];
173 DWORD thread_traversed[NUM_THREADS];
174 DWORD tid, first_tid = 0;
175 BOOL found = FALSE;
176 int i, matched_idx = -1;
177 ULONG buf_size = 0;
179 BYTE* pcs_buffer = NULL;
180 DWORD pcs_offset = 0;
182
184 ok(ev != NULL, "Cannot create event\n");
185
186 for (i = 0; i < NUM_THREADS; i++)
187 {
188 threads[i] = CreateThread(NULL, 0, sub_thread, ev, 0, &tid);
189 ok(threads[i] != NULL, "Cannot create thread\n");
190 thread_ids[i] = tid;
191 }
192
193 hSnapshot = pCreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
194 ok(hSnapshot != NULL, "Cannot create snapshot\n");
195
196 /* Check that this current process is enumerated */
197 te.dwSize = sizeof(te);
198 ok(pThread32First(hSnapshot, &te), "Thread cannot traverse\n");
199 do
200 {
201 if (found)
202 {
203 if (te.th32OwnerProcessID != PtrToUlong(curr_pid)) break;
204
205 if (matched_idx >= 0)
206 {
207 thread_traversed[matched_idx++] = te.th32ThreadID;
208 if (matched_idx >= NUM_THREADS) break;
209 }
210 else if (thread_ids[0] == te.th32ThreadID)
211 {
212 matched_idx = 0;
213 thread_traversed[matched_idx++] = te.th32ThreadID;
214 }
215 }
216 else if (te.th32OwnerProcessID == PtrToUlong(curr_pid))
217 {
218 found = TRUE;
219 first_tid = te.th32ThreadID;
220 }
221 }
222 while (pThread32Next(hSnapshot, &te));
223
224 ok(found, "Couldn't find self and/or sub-process in process list\n");
225
226 /* Check if the thread order is strictly consistent */
227 found = FALSE;
228 for (i = 0; i < NUM_THREADS; i++)
229 {
230 if (thread_traversed[i] != thread_ids[i])
231 {
232 found = TRUE;
233 break;
234 }
235 /* Reset data */
236 thread_traversed[i] = 0;
237 }
238 ok(found == FALSE, "The thread order is not strictly consistent\n");
239
240 /* Determine the order by NtQuerySystemInformation function */
241
243 pcs_buffer, buf_size, &buf_size)) == STATUS_INFO_LENGTH_MISMATCH)
244 {
245 free(pcs_buffer);
246 pcs_buffer = malloc(buf_size);
247 }
248 ok(status == STATUS_SUCCESS, "got %#lx\n", status);
249 found = FALSE;
250 matched_idx = -1;
251
252 do
253 {
254 spi = (SYSTEM_PROCESS_INFORMATION*)&pcs_buffer[pcs_offset];
255 if (spi->UniqueProcessId == curr_pid)
256 {
257 found = TRUE;
258 break;
259 }
260 pcs_offset += spi->NextEntryOffset;
261 } while (spi->NextEntryOffset != 0);
262
263 ok(found && spi, "No process found\n");
264 for (i = 0; i < spi->dwThreadCount; i++)
265 {
266 tid = HandleToULong(spi->ti[i].ClientId.UniqueThread);
267 if (matched_idx > 0)
268 {
269 thread_traversed[matched_idx++] = tid;
270 if (matched_idx >= NUM_THREADS) break;
271 }
272 else if (tid == thread_ids[0])
273 {
274 matched_idx = 0;
275 thread_traversed[matched_idx++] = tid;
276 }
277 }
278 free(pcs_buffer);
279
280 ok(matched_idx > 0, "No thread id match found\n");
281
282 found = FALSE;
283 for (i = 0; i < NUM_THREADS; i++)
284 {
285 if (thread_traversed[i] != thread_ids[i])
286 {
287 found = TRUE;
288 break;
289 }
290 }
291 ok(found == FALSE, "wrong order in NtQuerySystemInformation function\n");
292
293 SetEvent(ev);
295 for (i = 0; i < NUM_THREADS; i++)
297 CloseHandle(ev);
298 CloseHandle(hSnapshot);
299
300 return first_tid;
301}
302
303static void test_main_thread(DWORD curr_pid, DWORD main_tid)
304{
306 DWORD tid = 0;
307 int error;
308
309 /* Check that the main thread id is first one in this thread. */
310 tid = get_id_thread(ULongToPtr(curr_pid));
311 ok(tid == main_tid, "The first thread id returned is not the main thread id\n");
312
313 /* Check that the main thread id is first one in other thread. */
314 thread = CreateThread(NULL, 0, get_id_thread, ULongToPtr(curr_pid), 0, NULL);
316 ok(error == WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
317
318 ok(GetExitCodeThread(thread, &tid), "Could not retrieve exit code\n");
319 ok(tid == main_tid, "The first thread id returned is not the main thread id\n");
320}
321
322static void test_thread(DWORD curr_pid, DWORD sub_pcs_pid)
323{
324 HANDLE hSnapshot;
325 THREADENTRY32 te;
326 MODULEENTRY32 me;
327 unsigned curr_found = 0;
328 unsigned sub_found = 0;
329
330 hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
331 ok(hSnapshot != NULL, "Cannot create snapshot\n");
332
333 /* check that this current process is enumerated */
334 te.dwSize = sizeof(te);
335 if (pThread32First( hSnapshot, &te ))
336 {
337 do
338 {
339 if (te.th32OwnerProcessID == curr_pid) curr_found++;
340 if (te.th32OwnerProcessID == sub_pcs_pid) sub_found++;
341 if (winetest_debug > 1)
342 trace("PID=%lx TID=%lx %ld\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
343 } while (pThread32Next( hSnapshot, &te ));
344 }
345 ok(curr_found, "couldn't find self in thread list\n");
346 ok(sub_found >= 2, "couldn't find sub-process threads in thread list\n");
347
348 /* check that first really resets enumeration */
349 curr_found = 0;
350 sub_found = 0;
351 if (pThread32First( hSnapshot, &te ))
352 {
353 do
354 {
355 if (te.th32OwnerProcessID == curr_pid) curr_found++;
356 if (te.th32OwnerProcessID == sub_pcs_pid) sub_found++;
357 if (winetest_debug > 1)
358 trace("PID=%lx TID=%lx %ld\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
359 } while (pThread32Next( hSnapshot, &te ));
360 }
361 ok(curr_found, "couldn't find self in thread list\n");
362 ok(sub_found >= 2, "couldn't find sub-process threads in thread list\n");
363
364 me.dwSize = sizeof(me);
365 ok(!pModule32First( hSnapshot, &me ), "shouldn't return a module\n");
366
367 CloseHandle(hSnapshot);
368 ok(!pThread32First( hSnapshot, &te ), "shouldn't return a thread\n");
369}
370
371static const char* curr_expected_modules[] =
372{
373 "kernel32_test.exe",
374 "kernel32.dll",
375 "ntdll.dll"
376};
377
378static const char* sub_expected_modules[] =
379{
380 "kernel32_test.exe",
381 "kernel32.dll",
382 "shell32.dll",
383 "ntdll.dll"
384};
385
386static void test_module(DWORD pid, const char* expected[], unsigned num_expected)
387{
388 HANDLE hSnapshot;
390 THREADENTRY32 te;
391 MODULEENTRY32 me;
392 unsigned found[32];
393 unsigned i;
394 int num = 0;
395
396 ok(ARRAY_SIZE(found) >= num_expected, "Internal: bump found[] size\n");
397
398 hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pid );
399 ok(hSnapshot != NULL, "Cannot create snapshot\n");
400
401 for (i = 0; i < num_expected; i++) found[i] = 0;
402 me.dwSize = sizeof(me);
403 if (pModule32First( hSnapshot, &me ))
404 {
405 do
406 {
407 trace("PID=%lx base=%p size=%lx %s %s\n",
409 ok(me.th32ProcessID == pid, "wrong returned process id\n");
410 for (i = 0; i < num_expected; i++)
411 if (!lstrcmpiA(expected[i], me.szModule)) found[i]++;
412 num++;
413 } while (pModule32Next( hSnapshot, &me ));
414 }
415 for (i = 0; i < num_expected; i++)
416 ok(found[i] == 1, "Module %s is %s\n",
417 expected[i], found[i] ? "listed more than once" : "not listed");
418
419 /* check that first really resets the enumeration */
420 for (i = 0; i < num_expected; i++) found[i] = 0;
421 me.dwSize = sizeof(me);
422 if (pModule32First( hSnapshot, &me ))
423 {
424 do
425 {
426 trace("PID=%lx base=%p size=%lx %s %s\n",
428 for (i = 0; i < num_expected; i++)
429 if (!lstrcmpiA(expected[i], me.szModule)) found[i]++;
430 num--;
431 } while (pModule32Next( hSnapshot, &me ));
432 }
433 for (i = 0; i < num_expected; i++)
434 ok(found[i] == 1, "Module %s is %s\n",
435 expected[i], found[i] ? "listed more than once" : "not listed");
436 ok(!num, "mismatch in counting\n");
437
438 pe.dwSize = sizeof(pe);
439 ok(!pProcess32First( hSnapshot, &pe ), "shouldn't return a process\n");
440
441 te.dwSize = sizeof(te);
442 ok(!pThread32First( hSnapshot, &te ), "shouldn't return a thread\n");
443
444 CloseHandle(hSnapshot);
445 ok(!pModule32First( hSnapshot, &me ), "shouldn't return a module\n");
446}
447
448START_TEST(toolhelp)
449{
451 int r;
452 char *p, module[MAX_PATH];
453 char buffer[MAX_PATH + 21];
457 HANDLE ev1, ev2;
458 DWORD w;
459 HANDLE hkernel32 = GetModuleHandleA("kernel32");
460 HANDLE hntdll = GetModuleHandleA("ntdll.dll");
461
462 pCreateToolhelp32Snapshot = (VOID *) GetProcAddress(hkernel32, "CreateToolhelp32Snapshot");
463 pModule32First = (VOID *) GetProcAddress(hkernel32, "Module32First");
464 pModule32Next = (VOID *) GetProcAddress(hkernel32, "Module32Next");
465 pProcess32First = (VOID *) GetProcAddress(hkernel32, "Process32First");
466 pProcess32Next = (VOID *) GetProcAddress(hkernel32, "Process32Next");
467 pThread32First = (VOID *) GetProcAddress(hkernel32, "Thread32First");
468 pThread32Next = (VOID *) GetProcAddress(hkernel32, "Thread32Next");
469 pNtQuerySystemInformation = (VOID *) GetProcAddress(hntdll, "NtQuerySystemInformation");
470
471 if (!pCreateToolhelp32Snapshot ||
472 !pModule32First || !pModule32Next ||
473 !pProcess32First || !pProcess32Next ||
474 !pThread32First || !pThread32Next ||
475 !pNtQuerySystemInformation)
476 {
477 win_skip("Needed functions are not available, most likely running on Windows NT\n");
478 return;
479 }
480
481 r = init();
482 ok(r == 0, "Basic init of sub-process test\n");
483 if (r != 0) return;
484
485 sa.nLength = sizeof(sa);
486 sa.lpSecurityDescriptor = NULL;
487 sa.bInheritHandle = TRUE;
488
489 ev1 = CreateEventW(&sa, FALSE, FALSE, NULL);
490 ev2 = CreateEventW(&sa, FALSE, FALSE, NULL);
491 ok (ev1 != NULL && ev2 != NULL, "Couldn't create events\n");
492 memset(&startup, 0, sizeof(startup));
493 startup.cb = sizeof(startup);
495 startup.wShowWindow = SW_SHOWNORMAL;
496
497 sprintf(buffer, "%s toolhelp %Iu %Iu", selfname, (DWORD_PTR)ev1, (DWORD_PTR)ev2);
498 ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
499 /* wait for child to be initialized */
501 ok(w == WAIT_OBJECT_0, "Failed to wait on sub-process startup\n");
502
503 GetModuleFileNameA( 0, module, sizeof(module) );
504 if (!(p = strrchr( module, '\\' ))) p = module;
505 else p++;
508
509 test_process(pid, info.dwProcessId);
510 test_thread(pid, info.dwProcessId);
514
515 SetEvent(ev2);
516 wait_child_process( info.hProcess );
517}
static int argc
Definition: ServiceArgs.c:12
static void startup(void)
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
#define ARRAY_SIZE(A)
Definition: main.h:20
static HANDLE thread
Definition: service.c:33
#define ULongToPtr(ul)
Definition: basetsd.h:86
#define HandleToULong(h)
Definition: basetsd.h:89
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NTSTATUS
Definition: precomp.h:19
#define CloseHandle
Definition: compat.h:739
#define GetProcAddress(x, y)
Definition: compat.h:753
#define MAX_PATH
Definition: compat.h:34
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1489
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4749
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:541
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4227
_ACRTIMP int __cdecl atoi(const char *)
Definition: string.c:1715
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
#define PtrToUlong(u)
Definition: config.h:107
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
@ SystemProcessInformation
Definition: ntddk_ex.h:16
enum _SYSTEM_INFORMATION_CLASS SYSTEM_INFORMATION_CLASS
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint buffer
Definition: glext.h:5915
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLuint num
Definition: glext.h:9618
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static TfClientId tid
int winetest_debug
#define win_skip
Definition: minitest.h:67
#define error(str)
Definition: mkdosfs.c:1605
#define sprintf
Definition: sprintf.c:45
BOOL expected
Definition: store.c:2000
static HINSTANCE hkernel32
Definition: process.c:68
static HANDLE ULONG_PTR DWORD threads
Definition: process.c:83
static HINSTANCE hntdll
Definition: process.c:68
static LPMODULEENTRY32
Definition: toolhelp.c:38
static void test_main_thread(DWORD curr_pid, DWORD main_tid)
Definition: toolhelp.c:303
static DWORD WINAPI get_id_thread(void *curr_pid)
Definition: toolhelp.c:167
static LPPROCESSENTRY32
Definition: toolhelp.c:40
#define NUM_THREADS
Definition: toolhelp.c:49
static void ULONG
Definition: toolhelp.c:44
static DWORD
Definition: toolhelp.c:37
static void test_module(DWORD pid, const char *expected[], unsigned num_expected)
Definition: toolhelp.c:386
static const char * curr_expected_modules[]
Definition: toolhelp.c:371
static void test_thread(DWORD curr_pid, DWORD sub_pcs_pid)
Definition: toolhelp.c:322
static DWORD WINAPI sub_thread(void *pmt)
Definition: toolhelp.c:51
static void test_process(DWORD curr_pid, DWORD sub_pcs_pid)
Definition: toolhelp.c:107
static const char * sub_expected_modules[]
Definition: toolhelp.c:378
#define WAIT_TIME
Definition: toolhelp.c:47
static char selfname[MAX_PATH]
Definition: toolhelp.c:34
static int init(void)
Definition: toolhelp.c:67
#define argv
Definition: mplay32.c:18
HANDLE hThread
Definition: wizard.c:28
#define BOOL
Definition: nt_native.h:43
strcpy
Definition: string.h:131
int winetest_get_mainargs(char ***pargv)
#define wait_child_process
Definition: test.h:177
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
Definition: ps.c:97
BYTE * modBaseAddr
Definition: tlhelp32.h:99
char szModule[MAX_MODULE_NAME32+1]
Definition: tlhelp32.h:102
DWORD th32ProcessID
Definition: tlhelp32.h:96
DWORD modBaseSize
Definition: tlhelp32.h:100
char szExePath[MAX_PATH]
Definition: tlhelp32.h:103
CHAR szExeFile[MAX_PATH]
Definition: tlhelp32.h:70
DWORD th32ProcessID
Definition: tlhelp32.h:63
DWORD th32ThreadID
Definition: tlhelp32.h:75
DWORD th32OwnerProcessID
Definition: tlhelp32.h:76
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
#define TH32CS_SNAPPROCESS
Definition: tlhelp32.h:26
struct tagTHREADENTRY32 * LPTHREADENTRY32
Definition: toolhelp.c:43
#define TH32CS_SNAPTHREAD
Definition: tlhelp32.h:27
#define TH32CS_SNAPMODULE
Definition: tlhelp32.h:28
int32_t INT_PTR
Definition: typedefs.h:64
uint32_t DWORD_PTR
Definition: typedefs.h:65
PVOID HANDLE
Definition: typedefs.h:73
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define WAIT_ABANDONED
Definition: winbase.h:389
#define STARTF_USESHOWWINDOW
Definition: winbase.h:468
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158
#define WAIT_OBJECT_0
Definition: winbase.h:383
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837
#define WINAPI
Definition: msvc.h:6
#define SW_SHOWNORMAL
Definition: winuser.h:781
unsigned char BYTE
Definition: xxhash.c:193