ReactOS 0.4.16-dev-2224-g3637fd8
toolhelp.c File Reference
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include "ntstatus.h"
#include "windef.h"
#include "winbase.h"
#include "tlhelp32.h"
#include "wine/test.h"
#include "winuser.h"
#include "winternl.h"
Include dependency graph for toolhelp.c:

Go to the source code of this file.

Macros

#define WIN32_NO_STATUS
 
#define WAIT_TIME   (60 * 1000)
 
#define NUM_THREADS   4
 

Functions

static HANDLE (WINAPI *pCreateToolhelp32Snapshot)(DWORD
 
static BOOL (WINAPI *pModule32First)(HANDLE
 
static NTSTATUS (WINAPI *pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS
 
static DWORD WINAPI sub_thread (void *pmt)
 
static int init (void)
 
static void test_process (DWORD curr_pid, DWORD sub_pcs_pid)
 
static DWORD WINAPI get_id_thread (void *curr_pid)
 
static void test_main_thread (DWORD curr_pid, DWORD main_tid)
 
static void test_thread (DWORD curr_pid, DWORD sub_pcs_pid)
 
static void test_module (DWORD pid, const char *expected[], unsigned num_expected)
 
 START_TEST (toolhelp)
 

Variables

static char selfname [MAX_PATH]
 
static DWORD
 
static LPMODULEENTRY32
 
static LPPROCESSENTRY32
 
static LPTHREADENTRY32
 
static void ULONG
 
static const charcurr_expected_modules []
 
static const charsub_expected_modules []
 

Macro Definition Documentation

◆ NUM_THREADS

#define NUM_THREADS   4

Definition at line 49 of file toolhelp.c.

◆ WAIT_TIME

#define WAIT_TIME   (60 * 1000)

Definition at line 47 of file toolhelp.c.

◆ WIN32_NO_STATUS

#define WIN32_NO_STATUS

Definition at line 26 of file toolhelp.c.

Function Documentation

◆ BOOL()

static BOOL ( WINAPI pModule32First)
static

◆ get_id_thread()

static DWORD WINAPI get_id_thread ( void curr_pid)
static

Definition at line 167 of file toolhelp.c.

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}
#define ok(value,...)
Definition: atltest.h:57
LONG NTSTATUS
Definition: precomp.h:26
#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 CloseHandle
Definition: compat.h:739
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
#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
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
static HANDLE ULONG_PTR DWORD threads
Definition: process.c:83
#define NUM_THREADS
Definition: toolhelp.c:49
static DWORD WINAPI sub_thread(void *pmt)
Definition: toolhelp.c:51
#define WAIT_TIME
Definition: toolhelp.c:47
#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
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
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_SNAPTHREAD
Definition: tlhelp32.h:27
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
unsigned char BYTE
Definition: xxhash.c:193

Referenced by test_main_thread().

◆ HANDLE()

static HANDLE ( WINAPI pCreateToolhelp32Snapshot)
static

◆ init()

static int init ( void  )
static

Definition at line 67 of file toolhelp.c.

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}
static int argc
Definition: ServiceArgs.c:12
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1489
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:541
_ACRTIMP int __cdecl atoi(const char *)
Definition: string.c:1715
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
static char selfname[MAX_PATH]
Definition: toolhelp.c:34
#define argv
Definition: mplay32.c:18
HANDLE hThread
Definition: wizard.c:28
strcpy
Definition: string.h:131
int winetest_get_mainargs(char ***pargv)
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
int32_t INT_PTR
Definition: typedefs.h:64
PVOID HANDLE
Definition: typedefs.h:73
#define WAIT_ABANDONED
Definition: winbase.h:389
#define WAIT_OBJECT_0
Definition: winbase.h:383

Referenced by START_TEST().

◆ NTSTATUS()

static NTSTATUS ( WINAPI pNtQuerySystemInformation)
static

◆ START_TEST()

START_TEST ( toolhelp  )

Definition at line 448 of file toolhelp.c.

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 void startup(void)
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define ARRAY_SIZE(A)
Definition: main.h:20
#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
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
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
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint buffer
Definition: glext.h:5915
GLfloat GLfloat p
Definition: glext.h:8902
#define win_skip
Definition: minitest.h:67
#define sprintf
Definition: sprintf.c:45
static HINSTANCE hkernel32
Definition: process.c:68
static HINSTANCE hntdll
Definition: process.c:68
static void test_main_thread(DWORD curr_pid, DWORD main_tid)
Definition: toolhelp.c:303
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 void test_process(DWORD curr_pid, DWORD sub_pcs_pid)
Definition: toolhelp.c:107
static const char * sub_expected_modules[]
Definition: toolhelp.c:378
static int init(void)
Definition: toolhelp.c:67
#define wait_child_process
Definition: test.h:177
#define memset(x, y, z)
Definition: compat.h:39
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define STARTF_USESHOWWINDOW
Definition: winbase.h:468
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837
#define SW_SHOWNORMAL
Definition: winuser.h:781

◆ sub_thread()

static DWORD WINAPI sub_thread ( void pmt)
static

Definition at line 51 of file toolhelp.c.

52{
54 return w;
55}

Referenced by get_id_thread(), and init().

◆ test_main_thread()

static void test_main_thread ( DWORD  curr_pid,
DWORD  main_tid 
)
static

Definition at line 303 of file toolhelp.c.

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}
static HANDLE thread
Definition: service.c:33
#define ULongToPtr(ul)
Definition: basetsd.h:86
#define error(str)
Definition: mkdosfs.c:1605
static DWORD WINAPI get_id_thread(void *curr_pid)
Definition: toolhelp.c:167

Referenced by START_TEST().

◆ test_module()

static void test_module ( DWORD  pid,
const char expected[],
unsigned  num_expected 
)
static

Definition at line 386 of file toolhelp.c.

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}
#define trace
Definition: atltest.h:70
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4227
GLuint GLuint num
Definition: glext.h:9618
BOOL expected
Definition: store.c:2000
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
#define TH32CS_SNAPMODULE
Definition: tlhelp32.h:28

Referenced by START_TEST().

◆ test_process()

static void test_process ( DWORD  curr_pid,
DWORD  sub_pcs_pid 
)
static

Definition at line 107 of file toolhelp.c.

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}
#define broken(x)
Definition: atltest.h:178
CHAR szExeFile[MAX_PATH]
Definition: tlhelp32.h:70
DWORD th32ProcessID
Definition: tlhelp32.h:63
#define TH32CS_SNAPPROCESS
Definition: tlhelp32.h:26

Referenced by START_TEST().

◆ test_thread()

static void test_thread ( DWORD  curr_pid,
DWORD  sub_pcs_pid 
)
static

Definition at line 322 of file toolhelp.c.

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}
int winetest_debug

Referenced by START_TEST().

Variable Documentation

◆ curr_expected_modules

const char* curr_expected_modules[]
static
Initial value:
=
{
"kernel32_test.exe",
"kernel32.dll",
"ntdll.dll"
}

Definition at line 371 of file toolhelp.c.

Referenced by START_TEST().

◆ DWORD

Definition at line 37 of file toolhelp.c.

◆ LPMODULEENTRY32

Definition at line 38 of file toolhelp.c.

◆ LPPROCESSENTRY32

Definition at line 40 of file toolhelp.c.

◆ LPTHREADENTRY32

Definition at line 42 of file toolhelp.c.

◆ selfname

char selfname[MAX_PATH]
static

Definition at line 34 of file toolhelp.c.

Referenced by init(), and START_TEST().

◆ sub_expected_modules

const char* sub_expected_modules[]
static
Initial value:
=
{
"kernel32_test.exe",
"kernel32.dll",
"shell32.dll",
"ntdll.dll"
}

Definition at line 378 of file toolhelp.c.

Referenced by START_TEST().

◆ ULONG

Definition at line 44 of file toolhelp.c.