ReactOS 0.4.15-dev-7788-g1ad9096
process.c
Go to the documentation of this file.
1/*
2 * Unit test suite for process functions
3 *
4 * Copyright 2002 Eric Pouech
5 * Copyright 2006 Dmitry Timoshkov
6 * Copyright 2014 Michael Müller
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23#include <assert.h>
24#include <stdarg.h>
25#include <stdio.h>
26#include <stdlib.h>
27
28#include "ntstatus.h"
29#define WIN32_NO_STATUS
30#include "windef.h"
31#include "winbase.h"
32#include "winuser.h"
33#include "wincon.h"
34#include "winnls.h"
35#include "winternl.h"
36#include "tlhelp32.h"
37
38#include "wine/test.h"
39
40#include "winnt.h"
41
42/* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
43#define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)
44/* THREAD_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
45#define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
46
47#define expect_eq_d(expected, actual) \
48 do { \
49 int value = (actual); \
50 ok((expected) == value, "Expected " #actual " to be %d (" #expected ") is %d\n", \
51 (expected), value); \
52 } while (0)
53#define expect_eq_s(expected, actual) \
54 do { \
55 LPCSTR value = (actual); \
56 ok(lstrcmpA((expected), value) == 0, "Expected " #actual " to be L\"%s\" (" #expected ") is L\"%s\"\n", \
57 expected, value); \
58 } while (0)
59#define expect_eq_ws_i(expected, actual) \
60 do { \
61 LPCWSTR value = (actual); \
62 ok(lstrcmpiW((expected), value) == 0, "Expected " #actual " to be L\"%s\" (" #expected ") is L\"%s\"\n", \
63 wine_dbgstr_w(expected), wine_dbgstr_w(value)); \
64 } while (0)
65
67static void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
68static BOOL (WINAPI *pGetSystemRegistryQuota)(PDWORD, PDWORD);
69static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
70static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
71static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
72static BOOL (WINAPI *pQueryFullProcessImageNameA)(HANDLE hProcess, DWORD dwFlags, LPSTR lpExeName, PDWORD lpdwSize);
73static BOOL (WINAPI *pQueryFullProcessImageNameW)(HANDLE hProcess, DWORD dwFlags, LPWSTR lpExeName, PDWORD lpdwSize);
74static DWORD (WINAPI *pK32GetProcessImageFileNameA)(HANDLE,LPSTR,DWORD);
75static HANDLE (WINAPI *pCreateJobObjectW)(LPSECURITY_ATTRIBUTES sa, LPCWSTR name);
76static BOOL (WINAPI *pAssignProcessToJobObject)(HANDLE job, HANDLE process);
77static BOOL (WINAPI *pIsProcessInJob)(HANDLE process, HANDLE job, PBOOL result);
78static BOOL (WINAPI *pTerminateJobObject)(HANDLE job, UINT exit_code);
79static BOOL (WINAPI *pQueryInformationJobObject)(HANDLE job, JOBOBJECTINFOCLASS class, LPVOID info, DWORD len, LPDWORD ret_len);
80static BOOL (WINAPI *pSetInformationJobObject)(HANDLE job, JOBOBJECTINFOCLASS class, LPVOID info, DWORD len);
81static HANDLE (WINAPI *pCreateIoCompletionPort)(HANDLE file, HANDLE existing_port, ULONG_PTR key, DWORD threads);
82static BOOL (WINAPI *pGetNumaProcessorNode)(UCHAR, PUCHAR);
83static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
84static BOOL (WINAPI *pProcessIdToSessionId)(DWORD,DWORD*);
85static DWORD (WINAPI *pWTSGetActiveConsoleSessionId)(void);
86static HANDLE (WINAPI *pCreateToolhelp32Snapshot)(DWORD, DWORD);
87static BOOL (WINAPI *pProcess32First)(HANDLE, PROCESSENTRY32*);
88static BOOL (WINAPI *pProcess32Next)(HANDLE, PROCESSENTRY32*);
89static BOOL (WINAPI *pThread32First)(HANDLE, THREADENTRY32*);
90static BOOL (WINAPI *pThread32Next)(HANDLE, THREADENTRY32*);
92static SIZE_T (WINAPI *pGetLargePageMinimum)(void);
93static BOOL (WINAPI *pInitializeProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD, SIZE_T*);
94static BOOL (WINAPI *pUpdateProcThreadAttribute)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD_PTR, void *,SIZE_T,void*,SIZE_T*);
95static void (WINAPI *pDeleteProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*);
96static DWORD (WINAPI *pGetActiveProcessorCount)(WORD);
97
98/* ############################### */
99static char base[MAX_PATH];
100static char selfname[MAX_PATH];
101static char* exename;
102static char resfile[MAX_PATH];
103
104static int myARGC;
105static char** myARGV;
106
107/* As some environment variables get very long on Unix, we only test for
108 * the first 127 bytes.
109 * Note that increasing this value past 256 may exceed the buffer size
110 * limitations of the *Profile functions (at least on Wine).
111 */
112#define MAX_LISTED_ENV_VAR 128
113
114/* ---------------- portable memory allocation thingie */
115
116static char memory[1024*256];
117static char* memory_index = memory;
118
119static char* grab_memory(size_t len)
120{
121 char* ret = memory_index;
122 /* align on dword */
123 len = (len + 3) & ~3;
124 memory_index += len;
125 assert(memory_index <= memory + sizeof(memory));
126 return ret;
127}
128
129static void release_memory(void)
130{
132}
133
134/* ---------------- simplistic tool to encode/decode strings (to hide \ " ' and such) */
135
136static const char* encodeA(const char* str)
137{
138 char* ptr;
139 size_t len,i;
140
141 if (!str) return "";
142 len = strlen(str) + 1;
143 ptr = grab_memory(len * 2 + 1);
144 for (i = 0; i < len; i++)
145 sprintf(&ptr[i * 2], "%02x", (unsigned char)str[i]);
146 ptr[2 * len] = '\0';
147 return ptr;
148}
149
150static const char* encodeW(const WCHAR* str)
151{
152 char* ptr;
153 size_t len,i;
154
155 if (!str) return "";
156 len = lstrlenW(str) + 1;
157 ptr = grab_memory(len * 4 + 1);
158 assert(ptr);
159 for (i = 0; i < len; i++)
160 sprintf(&ptr[i * 4], "%04x", (unsigned int)(unsigned short)str[i]);
161 ptr[4 * len] = '\0';
162 return ptr;
163}
164
165static unsigned decode_char(char c)
166{
167 if (c >= '0' && c <= '9') return c - '0';
168 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
169 assert(c >= 'A' && c <= 'F');
170 return c - 'A' + 10;
171}
172
173static char* decodeA(const char* str)
174{
175 char* ptr;
176 size_t len,i;
177
178 len = strlen(str) / 2;
179 if (!len--) return NULL;
180 ptr = grab_memory(len + 1);
181 for (i = 0; i < len; i++)
182 ptr[i] = (decode_char(str[2 * i]) << 4) | decode_char(str[2 * i + 1]);
183 ptr[len] = '\0';
184 return ptr;
185}
186
187/* This will be needed to decode Unicode strings saved by the child process
188 * when we test Unicode functions.
189 */
190static WCHAR* decodeW(const char* str)
191{
192 size_t len;
193 WCHAR* ptr;
194 int i;
195
196 len = strlen(str) / 4;
197 if (!len--) return NULL;
198 ptr = (WCHAR*)grab_memory(len * 2 + 1);
199 for (i = 0; i < len; i++)
200 ptr[i] = (decode_char(str[4 * i]) << 12) |
201 (decode_char(str[4 * i + 1]) << 8) |
202 (decode_char(str[4 * i + 2]) << 4) |
203 (decode_char(str[4 * i + 3]) << 0);
204 ptr[len] = '\0';
205 return ptr;
206}
207
208/******************************************************************
209 * init
210 *
211 * generates basic information like:
212 * base: absolute path to curr dir
213 * selfname: the way to reinvoke ourselves
214 * exename: executable without the path
215 * function-pointers, which are not implemented in all windows versions
216 */
217static BOOL init(void)
218{
219 char *p;
220
222 if (!GetCurrentDirectoryA(sizeof(base), base)) return FALSE;
224
225 /* Strip the path of selfname */
226 if ((p = strrchr(selfname, '\\')) != NULL) exename = p + 1;
227 else exename = selfname;
228
229 if ((p = strrchr(exename, '/')) != NULL) exename = p + 1;
230
231 hkernel32 = GetModuleHandleA("kernel32");
232 hntdll = GetModuleHandleA("ntdll.dll");
233
234 pNtQueryInformationProcess = (void *)GetProcAddress(hntdll, "NtQueryInformationProcess");
235
236 pGetNativeSystemInfo = (void *) GetProcAddress(hkernel32, "GetNativeSystemInfo");
237 pGetSystemRegistryQuota = (void *) GetProcAddress(hkernel32, "GetSystemRegistryQuota");
238 pIsWow64Process = (void *) GetProcAddress(hkernel32, "IsWow64Process");
239 pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
240 pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
241 pQueryFullProcessImageNameA = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameA");
242 pQueryFullProcessImageNameW = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameW");
243 pK32GetProcessImageFileNameA = (void *) GetProcAddress(hkernel32, "K32GetProcessImageFileNameA");
244 pCreateJobObjectW = (void *)GetProcAddress(hkernel32, "CreateJobObjectW");
245 pAssignProcessToJobObject = (void *)GetProcAddress(hkernel32, "AssignProcessToJobObject");
246 pIsProcessInJob = (void *)GetProcAddress(hkernel32, "IsProcessInJob");
247 pTerminateJobObject = (void *)GetProcAddress(hkernel32, "TerminateJobObject");
248 pQueryInformationJobObject = (void *)GetProcAddress(hkernel32, "QueryInformationJobObject");
249 pSetInformationJobObject = (void *)GetProcAddress(hkernel32, "SetInformationJobObject");
250 pCreateIoCompletionPort = (void *)GetProcAddress(hkernel32, "CreateIoCompletionPort");
251 pGetNumaProcessorNode = (void *)GetProcAddress(hkernel32, "GetNumaProcessorNode");
252 pProcessIdToSessionId = (void *)GetProcAddress(hkernel32, "ProcessIdToSessionId");
253 pWTSGetActiveConsoleSessionId = (void *)GetProcAddress(hkernel32, "WTSGetActiveConsoleSessionId");
254 pCreateToolhelp32Snapshot = (void *)GetProcAddress(hkernel32, "CreateToolhelp32Snapshot");
255 pProcess32First = (void *)GetProcAddress(hkernel32, "Process32First");
256 pProcess32Next = (void *)GetProcAddress(hkernel32, "Process32Next");
257 pThread32First = (void *)GetProcAddress(hkernel32, "Thread32First");
258 pThread32Next = (void *)GetProcAddress(hkernel32, "Thread32Next");
259 pGetLogicalProcessorInformationEx = (void *)GetProcAddress(hkernel32, "GetLogicalProcessorInformationEx");
260 pGetLargePageMinimum = (void *)GetProcAddress(hkernel32, "GetLargePageMinimum");
261 pInitializeProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "InitializeProcThreadAttributeList");
262 pUpdateProcThreadAttribute = (void *)GetProcAddress(hkernel32, "UpdateProcThreadAttribute");
263 pDeleteProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "DeleteProcThreadAttributeList");
264 pGetActiveProcessorCount = (void *)GetProcAddress(hkernel32, "GetActiveProcessorCount");
265
266 return TRUE;
267}
268
269/******************************************************************
270 * get_file_name
271 *
272 * generates an absolute file_name for temporary file
273 *
274 */
275static void get_file_name(char* buf)
276{
277 char path[MAX_PATH];
278
279 buf[0] = '\0';
280 GetTempPathA(sizeof(path), path);
281 GetTempFileNameA(path, "wt", 0, buf);
282}
283
284/******************************************************************
285 * static void childPrintf
286 *
287 */
288static void WINETEST_PRINTF_ATTR(2,3) childPrintf(HANDLE h, const char* fmt, ...)
289{
291 char buffer[1024+4*MAX_LISTED_ENV_VAR];
292 DWORD w;
293
296 va_end(valist);
298}
299
300
301/******************************************************************
302 * doChild
303 *
304 * output most of the information in the child process
305 */
306static void doChild(const char* file, const char* option)
307{
308 RTL_USER_PROCESS_PARAMETERS *params = NtCurrentTeb()->Peb->ProcessParameters;
309 STARTUPINFOA siA;
310 STARTUPINFOW siW;
311 int i;
312 char *ptrA, *ptrA_save;
313 WCHAR *ptrW, *ptrW_save;
314 char bufA[MAX_PATH];
315 WCHAR bufW[MAX_PATH];
319 BOOL ret;
320
321 if (hFile == INVALID_HANDLE_VALUE) return;
322
323 /* output of startup info (Ansi) */
324 GetStartupInfoA(&siA);
325 childPrintf(hFile,
326 "[StartupInfoA]\ncb=%08u\nlpDesktop=%s\nlpTitle=%s\n"
327 "dwX=%u\ndwY=%u\ndwXSize=%u\ndwYSize=%u\n"
328 "dwXCountChars=%u\ndwYCountChars=%u\ndwFillAttribute=%u\n"
329 "dwFlags=%u\nwShowWindow=%u\n"
330 "hStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
331 siA.cb, encodeA(siA.lpDesktop), encodeA(siA.lpTitle),
332 siA.dwX, siA.dwY, siA.dwXSize, siA.dwYSize,
334 siA.dwFlags, siA.wShowWindow,
336
337 /* check the console handles in the TEB */
338 childPrintf(hFile, "[TEB]\nhStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
339 (DWORD_PTR)params->hStdInput, (DWORD_PTR)params->hStdOutput,
340 (DWORD_PTR)params->hStdError);
341
342 /* since GetStartupInfoW is only implemented in win2k,
343 * zero out before calling so we can notice the difference
344 */
345 memset(&siW, 0, sizeof(siW));
346 GetStartupInfoW(&siW);
347 childPrintf(hFile,
348 "[StartupInfoW]\ncb=%08u\nlpDesktop=%s\nlpTitle=%s\n"
349 "dwX=%u\ndwY=%u\ndwXSize=%u\ndwYSize=%u\n"
350 "dwXCountChars=%u\ndwYCountChars=%u\ndwFillAttribute=%u\n"
351 "dwFlags=%u\nwShowWindow=%u\n"
352 "hStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
353 siW.cb, encodeW(siW.lpDesktop), encodeW(siW.lpTitle),
354 siW.dwX, siW.dwY, siW.dwXSize, siW.dwYSize,
356 siW.dwFlags, siW.wShowWindow,
358
359 /* Arguments */
360 childPrintf(hFile, "[Arguments]\nargcA=%d\n", myARGC);
361 for (i = 0; i < myARGC; i++)
362 {
363 childPrintf(hFile, "argvA%d=%s\n", i, encodeA(myARGV[i]));
364 }
365 childPrintf(hFile, "CommandLineA=%s\n", encodeA(GetCommandLineA()));
366 childPrintf(hFile, "CommandLineW=%s\n\n", encodeW(GetCommandLineW()));
367
368 /* output toolhelp information */
369 snapshot = pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
370 ok(snapshot != INVALID_HANDLE_VALUE, "CreateToolhelp32Snapshot failed %u\n", GetLastError());
371 memset(&pe, 0, sizeof(pe));
372 pe.dwSize = sizeof(pe);
373 if (pProcess32First(snapshot, &pe))
374 {
375 while (pe.th32ProcessID != GetCurrentProcessId())
376 if (!pProcess32Next(snapshot, &pe)) break;
377 }
379 ok(pe.th32ProcessID == GetCurrentProcessId(), "failed to find current process in snapshot\n");
380 childPrintf(hFile,
381 "[Toolhelp]\ncntUsage=%u\nth32DefaultHeapID=%lu\n"
382 "th32ModuleID=%u\ncntThreads=%u\nth32ParentProcessID=%u\n"
383 "pcPriClassBase=%u\ndwFlags=%u\nszExeFile=%s\n\n",
386 pe.dwFlags, encodeA(pe.szExeFile));
387
388 /* output of environment (Ansi) */
389 ptrA_save = ptrA = GetEnvironmentStringsA();
390 if (ptrA)
391 {
393
394 childPrintf(hFile, "[EnvironmentA]\n");
395 i = 0;
396 while (*ptrA)
397 {
399 childPrintf(hFile, "env%d=%s\n", i, encodeA(env_var));
400 i++;
401 ptrA += strlen(ptrA) + 1;
402 }
403 childPrintf(hFile, "len=%d\n\n", i);
404 FreeEnvironmentStringsA(ptrA_save);
405 }
406
407 /* output of environment (Unicode) */
408 ptrW_save = ptrW = GetEnvironmentStringsW();
409 if (ptrW)
410 {
412
413 childPrintf(hFile, "[EnvironmentW]\n");
414 i = 0;
415 while (*ptrW)
416 {
418 env_var[MAX_LISTED_ENV_VAR - 1] = '\0';
419 childPrintf(hFile, "env%d=%s\n", i, encodeW(env_var));
420 i++;
421 ptrW += lstrlenW(ptrW) + 1;
422 }
423 childPrintf(hFile, "len=%d\n\n", i);
424 FreeEnvironmentStringsW(ptrW_save);
425 }
426
427 childPrintf(hFile, "[Misc]\n");
428 if (GetCurrentDirectoryA(sizeof(bufA), bufA))
429 childPrintf(hFile, "CurrDirA=%s\n", encodeA(bufA));
430 if (GetCurrentDirectoryW(sizeof(bufW) / sizeof(bufW[0]), bufW))
431 childPrintf(hFile, "CurrDirW=%s\n", encodeW(bufW));
432 childPrintf(hFile, "\n");
433
434 if (option && strcmp(option, "console") == 0)
435 {
439 DWORD modeIn, modeOut;
440
441 childPrintf(hFile, "[Console]\n");
442 if (GetConsoleScreenBufferInfo(hConOut, &sbi))
443 {
444 childPrintf(hFile, "SizeX=%d\nSizeY=%d\nCursorX=%d\nCursorY=%d\nAttributes=%d\n",
446 childPrintf(hFile, "winLeft=%d\nwinTop=%d\nwinRight=%d\nwinBottom=%d\n",
448 childPrintf(hFile, "maxWinWidth=%d\nmaxWinHeight=%d\n",
450 }
451 childPrintf(hFile, "InputCP=%d\nOutputCP=%d\n",
453 if (GetConsoleMode(hConIn, &modeIn))
454 childPrintf(hFile, "InputMode=%u\n", modeIn);
455 if (GetConsoleMode(hConOut, &modeOut))
456 childPrintf(hFile, "OutputMode=%u\n", modeOut);
457
458 /* now that we have written all relevant information, let's change it */
459 SetLastError(0xdeadbeef);
460 ret = SetConsoleCP(1252);
462 {
463 win_skip("Setting the codepage is not implemented\n");
464 }
465 else
466 {
467 ok(ret, "Setting CP\n");
468 ok(SetConsoleOutputCP(1252), "Setting SB CP\n");
469 }
470
471 ret = SetConsoleMode(hConIn, modeIn ^ 1);
472 ok( ret, "Setting mode (%d)\n", GetLastError());
473 ret = SetConsoleMode(hConOut, modeOut ^ 1);
474 ok( ret, "Setting mode (%d)\n", GetLastError());
475 sbi.dwCursorPosition.X ^= 1;
476 sbi.dwCursorPosition.Y ^= 1;
478 ok( ret, "Setting cursor position (%d)\n", GetLastError());
479 }
480 if (option && strcmp(option, "stdhandle") == 0)
481 {
484
486 {
487 char buf[1024];
488 DWORD r, w;
489
490 ok(ReadFile(hStdIn, buf, sizeof(buf), &r, NULL) && r > 0, "Reading message from input pipe\n");
491 childPrintf(hFile, "[StdHandle]\nmsg=%s\n\n", encodeA(buf));
492 ok(WriteFile(hStdOut, buf, r, &w, NULL) && w == r, "Writing message to output pipe\n");
493 }
494 }
495
496 if (option && strcmp(option, "exit_code") == 0)
497 {
498 childPrintf(hFile, "[ExitCode]\nvalue=%d\n\n", 123);
500 ExitProcess(123);
501 }
502
504}
505
506static char* getChildString(const char* sect, const char* key)
507{
508 char buf[1024+4*MAX_LISTED_ENV_VAR];
509 char* ret;
510
511 GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), resfile);
512 if (buf[0] == '\0' || (buf[0] == '-' && buf[1] == '\0')) return NULL;
513 assert(!(strlen(buf) & 1));
514 ret = decodeA(buf);
515 return ret;
516}
517
518static WCHAR* getChildStringW(const char* sect, const char* key)
519{
520 char buf[1024+4*MAX_LISTED_ENV_VAR];
521 WCHAR* ret;
522
523 GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), resfile);
524 if (buf[0] == '\0' || (buf[0] == '-' && buf[1] == '\0')) return NULL;
525 assert(!(strlen(buf) & 1));
526 ret = decodeW(buf);
527 return ret;
528}
529
530/* FIXME: this may be moved to the wtmain.c file, because it may be needed by
531 * others... (windows uses stricmp while Un*x uses strcasecmp...)
532 */
533static int wtstrcasecmp(const char* p1, const char* p2)
534{
535 char c1, c2;
536
537 c1 = c2 = '@';
538 while (c1 == c2 && c1)
539 {
540 c1 = *p1++; c2 = *p2++;
541 if (c1 != c2)
542 {
543 c1 = toupper(c1); c2 = toupper(c2);
544 }
545 }
546 return c1 - c2;
547}
548
549static int strCmp(const char* s1, const char* s2, BOOL sensitive)
550{
551 if (!s1 && !s2) return 0;
552 if (!s2) return -1;
553 if (!s1) return 1;
554 return (sensitive) ? strcmp(s1, s2) : wtstrcasecmp(s1, s2);
555}
556
557static void ok_child_string( int line, const char *sect, const char *key,
558 const char *expect, int sensitive )
559{
560 char* result = getChildString( sect, key );
561 ok_(__FILE__, line)( strCmp(result, expect, sensitive) == 0, "%s:%s expected '%s', got '%s'\n",
562 sect, key, expect ? expect : "(null)", result );
563}
564
565static void ok_child_stringWA( int line, const char *sect, const char *key,
566 const char *expect, int sensitive )
567{
568 WCHAR* expectW;
569 CHAR* resultA;
570 DWORD len;
571 WCHAR* result = getChildStringW( sect, key );
572
573 len = MultiByteToWideChar( CP_ACP, 0, expect, -1, NULL, 0);
574 expectW = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
575 MultiByteToWideChar( CP_ACP, 0, expect, -1, expectW, len);
576
578 resultA = HeapAlloc(GetProcessHeap(),0,len*sizeof(CHAR));
579 WideCharToMultiByte( CP_ACP, 0, result, -1, resultA, len, NULL, NULL);
580
581 if (sensitive)
582 ok_(__FILE__, line)( lstrcmpW(result, expectW) == 0, "%s:%s expected '%s', got '%s'\n",
583 sect, key, expect ? expect : "(null)", resultA );
584 else
585 ok_(__FILE__, line)( lstrcmpiW(result, expectW) == 0, "%s:%s expected '%s', got '%s'\n",
586 sect, key, expect ? expect : "(null)", resultA );
587 HeapFree(GetProcessHeap(),0,expectW);
588 HeapFree(GetProcessHeap(),0,resultA);
589}
590
591static void ok_child_int( int line, const char *sect, const char *key, UINT expect )
592{
594 ok_(__FILE__, line)( result == expect, "%s:%s expected %u, but got %u\n", sect, key, expect, result );
595}
596
597#define okChildString(sect, key, expect) ok_child_string(__LINE__, (sect), (key), (expect), 1 )
598#define okChildIString(sect, key, expect) ok_child_string(__LINE__, (sect), (key), (expect), 0 )
599#define okChildStringWA(sect, key, expect) ok_child_stringWA(__LINE__, (sect), (key), (expect), 1 )
600#define okChildInt(sect, key, expect) ok_child_int(__LINE__, (sect), (key), (expect))
601
602static void test_Startup(void)
603{
604 char buffer[MAX_PATH];
607 char *result;
608 static CHAR title[] = "I'm the title string",
609 desktop[] = "winsta0\\default",
610 empty[] = "";
611
612 /* let's start simplistic */
613 memset(&startup, 0, sizeof(startup));
614 startup.cb = sizeof(startup);
616 startup.wShowWindow = SW_SHOWNORMAL;
617
619 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
620 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
621 /* wait for child to terminate */
622 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
623 /* child process has changed result file, so let profile functions know about it */
625 CloseHandle(info.hThread);
626 CloseHandle(info.hProcess);
627
628 GetStartupInfoA(&si);
629 okChildInt("StartupInfoA", "cb", startup.cb);
630 okChildString("StartupInfoA", "lpDesktop", si.lpDesktop);
631 okChildInt("StartupInfoA", "dwX", startup.dwX);
632 okChildInt("StartupInfoA", "dwY", startup.dwY);
633 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
634 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
635 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
636 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
637 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
638 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
639 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
642
643 /* not so simplistic now */
644 memset(&startup, 0, sizeof(startup));
645 startup.cb = sizeof(startup);
647 startup.wShowWindow = SW_SHOWNORMAL;
648 startup.lpTitle = title;
649 startup.lpDesktop = desktop;
650 startup.dwXCountChars = 0x12121212;
651 startup.dwYCountChars = 0x23232323;
652 startup.dwX = 0x34343434;
653 startup.dwY = 0x45454545;
654 startup.dwXSize = 0x56565656;
655 startup.dwYSize = 0x67676767;
656 startup.dwFillAttribute = 0xA55A;
657
659 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
660 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
661 /* wait for child to terminate */
662 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
663 /* child process has changed result file, so let profile functions know about it */
665 CloseHandle(info.hThread);
666 CloseHandle(info.hProcess);
667
668 okChildInt("StartupInfoA", "cb", startup.cb);
669 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
670 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
671 okChildInt("StartupInfoA", "dwX", startup.dwX);
672 okChildInt("StartupInfoA", "dwY", startup.dwY);
673 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
674 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
675 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
676 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
677 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
678 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
679 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
682
683 /* not so simplistic now */
684 memset(&startup, 0, sizeof(startup));
685 startup.cb = sizeof(startup);
687 startup.wShowWindow = SW_SHOWNORMAL;
688 startup.lpTitle = title;
689 startup.lpDesktop = NULL;
690 startup.dwXCountChars = 0x12121212;
691 startup.dwYCountChars = 0x23232323;
692 startup.dwX = 0x34343434;
693 startup.dwY = 0x45454545;
694 startup.dwXSize = 0x56565656;
695 startup.dwYSize = 0x67676767;
696 startup.dwFillAttribute = 0xA55A;
697
699 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
700 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
701 /* wait for child to terminate */
702 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
703 /* child process has changed result file, so let profile functions know about it */
705 CloseHandle(info.hThread);
706 CloseHandle(info.hProcess);
707
708 okChildInt("StartupInfoA", "cb", startup.cb);
709 okChildString("StartupInfoA", "lpDesktop", si.lpDesktop);
710 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
711 okChildInt("StartupInfoA", "dwX", startup.dwX);
712 okChildInt("StartupInfoA", "dwY", startup.dwY);
713 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
714 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
715 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
716 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
717 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
718 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
719 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
722
723 /* not so simplistic now */
724 memset(&startup, 0, sizeof(startup));
725 startup.cb = sizeof(startup);
727 startup.wShowWindow = SW_SHOWNORMAL;
728 startup.lpTitle = title;
729 startup.lpDesktop = empty;
730 startup.dwXCountChars = 0x12121212;
731 startup.dwYCountChars = 0x23232323;
732 startup.dwX = 0x34343434;
733 startup.dwY = 0x45454545;
734 startup.dwXSize = 0x56565656;
735 startup.dwYSize = 0x67676767;
736 startup.dwFillAttribute = 0xA55A;
737
739 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
740 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
741 /* wait for child to terminate */
742 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
743 /* child process has changed result file, so let profile functions know about it */
745 CloseHandle(info.hThread);
746 CloseHandle(info.hProcess);
747
748 okChildInt("StartupInfoA", "cb", startup.cb);
749 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
750 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
751 okChildInt("StartupInfoA", "dwX", startup.dwX);
752 okChildInt("StartupInfoA", "dwY", startup.dwY);
753 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
754 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
755 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
756 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
757 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
758 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
759 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
762
763 /* not so simplistic now */
764 memset(&startup, 0, sizeof(startup));
765 startup.cb = sizeof(startup);
767 startup.wShowWindow = SW_SHOWNORMAL;
768 startup.lpTitle = NULL;
769 startup.lpDesktop = desktop;
770 startup.dwXCountChars = 0x12121212;
771 startup.dwYCountChars = 0x23232323;
772 startup.dwX = 0x34343434;
773 startup.dwY = 0x45454545;
774 startup.dwXSize = 0x56565656;
775 startup.dwYSize = 0x67676767;
776 startup.dwFillAttribute = 0xA55A;
777
779 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
780 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
781 /* wait for child to terminate */
782 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
783 /* child process has changed result file, so let profile functions know about it */
785 CloseHandle(info.hThread);
786 CloseHandle(info.hProcess);
787
788 okChildInt("StartupInfoA", "cb", startup.cb);
789 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
790 result = getChildString( "StartupInfoA", "lpTitle" );
791 ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
792 "expected '%s' or null, got '%s'\n", selfname, result );
793 okChildInt("StartupInfoA", "dwX", startup.dwX);
794 okChildInt("StartupInfoA", "dwY", startup.dwY);
795 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
796 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
797 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
798 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
799 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
800 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
801 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
804
805 /* not so simplistic now */
806 memset(&startup, 0, sizeof(startup));
807 startup.cb = sizeof(startup);
809 startup.wShowWindow = SW_SHOWNORMAL;
810 startup.lpTitle = empty;
811 startup.lpDesktop = desktop;
812 startup.dwXCountChars = 0x12121212;
813 startup.dwYCountChars = 0x23232323;
814 startup.dwX = 0x34343434;
815 startup.dwY = 0x45454545;
816 startup.dwXSize = 0x56565656;
817 startup.dwYSize = 0x67676767;
818 startup.dwFillAttribute = 0xA55A;
819
821 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
822 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
823 /* wait for child to terminate */
824 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
825 /* child process has changed result file, so let profile functions know about it */
827 CloseHandle(info.hThread);
828 CloseHandle(info.hProcess);
829
830 okChildInt("StartupInfoA", "cb", startup.cb);
831 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
832 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
833 okChildInt("StartupInfoA", "dwX", startup.dwX);
834 okChildInt("StartupInfoA", "dwY", startup.dwY);
835 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
836 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
837 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
838 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
839 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
840 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
841 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
844
845 /* not so simplistic now */
846 memset(&startup, 0, sizeof(startup));
847 startup.cb = sizeof(startup);
849 startup.wShowWindow = SW_SHOWNORMAL;
850 startup.lpTitle = empty;
851 startup.lpDesktop = empty;
852 startup.dwXCountChars = 0x12121212;
853 startup.dwYCountChars = 0x23232323;
854 startup.dwX = 0x34343434;
855 startup.dwY = 0x45454545;
856 startup.dwXSize = 0x56565656;
857 startup.dwYSize = 0x67676767;
858 startup.dwFillAttribute = 0xA55A;
859
861 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
862 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
863 /* wait for child to terminate */
864 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
865 /* child process has changed result file, so let profile functions know about it */
867 CloseHandle(info.hThread);
868 CloseHandle(info.hProcess);
869
870 okChildInt("StartupInfoA", "cb", startup.cb);
871 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
872 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
873 okChildInt("StartupInfoA", "dwX", startup.dwX);
874 okChildInt("StartupInfoA", "dwY", startup.dwY);
875 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
876 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
877 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
878 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
879 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
880 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
881 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
884
885 /* TODO: test for A/W and W/A and W/W */
886}
887
888static void test_CommandLine(void)
889{
890 char buffer[MAX_PATH], fullpath[MAX_PATH], *lpFilePart, *p;
891 char buffer2[MAX_PATH];
894 BOOL ret;
895
896 memset(&startup, 0, sizeof(startup));
897 startup.cb = sizeof(startup);
899 startup.wShowWindow = SW_SHOWNORMAL;
900
901 /* the basics */
903 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
904 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
905 /* wait for child to terminate */
906 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
907 /* child process has changed result file, so let profile functions know about it */
909 CloseHandle(info.hThread);
910 CloseHandle(info.hProcess);
911
912 okChildInt("Arguments", "argcA", 5);
913 okChildString("Arguments", "argvA4", "C:\\Program Files\\my nice app.exe");
914 okChildString("Arguments", "argvA5", NULL);
915 okChildString("Arguments", "CommandLineA", buffer);
918
919 memset(&startup, 0, sizeof(startup));
920 startup.cb = sizeof(startup);
922 startup.wShowWindow = SW_SHOWNORMAL;
923
924 /* from François */
926 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
927 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
928 /* wait for child to terminate */
929 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
930 /* child process has changed result file, so let profile functions know about it */
932 CloseHandle(info.hThread);
933 CloseHandle(info.hProcess);
934
935 okChildInt("Arguments", "argcA", 7);
936 okChildString("Arguments", "argvA4", "a\"b\\");
937 okChildString("Arguments", "argvA5", "c\"");
938 okChildString("Arguments", "argvA6", "d");
939 okChildString("Arguments", "argvA7", NULL);
940 okChildString("Arguments", "CommandLineA", buffer);
943
944 /* Test for Bug1330 to show that XP doesn't change '/' to '\\' in argv[0]*/
946 /* Use exename to avoid buffer containing things like 'C:' */
947 sprintf(buffer, "./%s tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
948 SetLastError(0xdeadbeef);
950 ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
951 /* wait for child to terminate */
952 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
953 /* child process has changed result file, so let profile functions know about it */
955 CloseHandle(info.hThread);
956 CloseHandle(info.hProcess);
957 sprintf(buffer, "./%s", exename);
958 okChildString("Arguments", "argvA0", buffer);
961
963 /* Use exename to avoid buffer containing things like 'C:' */
964 sprintf(buffer, ".\\%s tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
965 SetLastError(0xdeadbeef);
967 ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
968 /* wait for child to terminate */
969 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
970 /* child process has changed result file, so let profile functions know about it */
972 CloseHandle(info.hThread);
973 CloseHandle(info.hProcess);
974 sprintf(buffer, ".\\%s", exename);
975 okChildString("Arguments", "argvA0", buffer);
978
981 assert ( lpFilePart != 0);
982 *(lpFilePart -1 ) = 0;
983 p = strrchr(fullpath, '\\');
984 /* Use exename to avoid buffer containing things like 'C:' */
985 if (p) sprintf(buffer, "..%s/%s tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", p, exename, resfile);
986 else sprintf(buffer, "./%s tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
987 SetLastError(0xdeadbeef);
989 ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
990 /* wait for child to terminate */
991 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
992 /* child process has changed result file, so let profile functions know about it */
994 CloseHandle(info.hThread);
995 CloseHandle(info.hProcess);
996 if (p) sprintf(buffer, "..%s/%s", p, exename);
997 else sprintf(buffer, "./%s", exename);
998 okChildString("Arguments", "argvA0", buffer);
1001
1002 /* Using AppName */
1005 assert ( lpFilePart != 0);
1006 *(lpFilePart -1 ) = 0;
1007 p = strrchr(fullpath, '\\');
1008 /* Use exename to avoid buffer containing things like 'C:' */
1009 if (p) sprintf(buffer, "..%s/%s", p, exename);
1010 else sprintf(buffer, "./%s", exename);
1011 sprintf(buffer2, "dummy tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", resfile);
1012 SetLastError(0xdeadbeef);
1013 ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
1014 ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
1015 /* wait for child to terminate */
1016 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1017 /* child process has changed result file, so let profile functions know about it */
1019 CloseHandle(info.hThread);
1020 CloseHandle(info.hProcess);
1021 sprintf(buffer, "tests/process.c dump %s", resfile);
1022 okChildString("Arguments", "argvA0", "dummy");
1023 okChildString("Arguments", "CommandLineA", buffer2);
1024 okChildStringWA("Arguments", "CommandLineW", buffer2);
1027
1028 if (0) /* Test crashes on NT-based Windows. */
1029 {
1030 /* Test NULL application name and command line parameters. */
1031 SetLastError(0xdeadbeef);
1033 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1035 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1036 }
1037
1038 buffer[0] = '\0';
1039
1040 /* Test empty application name parameter. */
1041 SetLastError(0xdeadbeef);
1043 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1045 broken(GetLastError() == ERROR_FILE_NOT_FOUND) /* Win9x/WinME */ ||
1046 broken(GetLastError() == ERROR_ACCESS_DENIED) /* Win98 */,
1047 "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1048
1049 buffer2[0] = '\0';
1050
1051 /* Test empty application name and command line parameters. */
1052 SetLastError(0xdeadbeef);
1053 ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
1054 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1056 broken(GetLastError() == ERROR_FILE_NOT_FOUND) /* Win9x/WinME */ ||
1057 broken(GetLastError() == ERROR_ACCESS_DENIED) /* Win98 */,
1058 "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1059
1060 /* Test empty command line parameter. */
1061 SetLastError(0xdeadbeef);
1062 ret = CreateProcessA(NULL, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
1063 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1065 GetLastError() == ERROR_PATH_NOT_FOUND /* NT4 */ ||
1066 GetLastError() == ERROR_BAD_PATHNAME /* Win98 */ ||
1067 GetLastError() == ERROR_INVALID_PARAMETER /* Win7 */,
1068 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1069
1070 strcpy(buffer, "doesnotexist.exe");
1071 strcpy(buffer2, "does not exist.exe");
1072
1073 /* Test nonexistent application name. */
1074 SetLastError(0xdeadbeef);
1076 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1077 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1078
1079 SetLastError(0xdeadbeef);
1080 ret = CreateProcessA(buffer2, NULL, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
1081 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1082 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1083
1084 /* Test nonexistent command line parameter. */
1085 SetLastError(0xdeadbeef);
1087 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1088 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1089
1090 SetLastError(0xdeadbeef);
1091 ret = CreateProcessA(NULL, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
1092 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1093 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1094}
1095
1096static void test_Directory(void)
1097{
1098 char buffer[MAX_PATH];
1101 char windir[MAX_PATH];
1102 static CHAR cmdline[] = "winver.exe";
1103
1104 memset(&startup, 0, sizeof(startup));
1105 startup.cb = sizeof(startup);
1106 startup.dwFlags = STARTF_USESHOWWINDOW;
1107 startup.wShowWindow = SW_SHOWNORMAL;
1108
1109 /* the basics */
1111 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
1112 GetWindowsDirectoryA( windir, sizeof(windir) );
1113 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, windir, &startup, &info), "CreateProcess\n");
1114 /* wait for child to terminate */
1115 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1116 /* child process has changed result file, so let profile functions know about it */
1118 CloseHandle(info.hThread);
1119 CloseHandle(info.hProcess);
1120
1121 okChildIString("Misc", "CurrDirA", windir);
1124
1125 /* search PATH for the exe if directory is NULL */
1126 ok(CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
1127 ok(TerminateProcess(info.hProcess, 0), "Child process termination\n");
1128 CloseHandle(info.hThread);
1129 CloseHandle(info.hProcess);
1130
1131 /* if any directory is provided, don't search PATH, error on bad directory */
1132 SetLastError(0xdeadbeef);
1133 memset(&info, 0, sizeof(info));
1135 NULL, "non\\existent\\directory", &startup, &info), "CreateProcess\n");
1136 ok(GetLastError() == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", GetLastError());
1137 ok(!TerminateProcess(info.hProcess, 0), "Child process should not exist\n");
1138}
1139
1140static void test_Toolhelp(void)
1141{
1142 char buffer[MAX_PATH];
1146 PROCESSENTRY32 pe;
1147 THREADENTRY32 te;
1148 DWORD ret;
1149 int i;
1150
1151#if defined(__REACTOS__) && defined(_M_AMD64)
1153 {
1154 skip("ROSTESTS-372: Skipping test in kernel32_winetest:process test_Toolhelp because it leaves a process behind on Windows Server 2003 x64-Testbot. Set winetest_interactive to run it anyway.\n");
1155 //return;
1156 }
1157#endif
1158
1159 memset(&startup, 0, sizeof(startup));
1160 startup.cb = sizeof(startup);
1161 startup.dwFlags = STARTF_USESHOWWINDOW;
1162 startup.wShowWindow = SW_SHOWNORMAL;
1163
1165 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
1166 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess failed\n");
1167 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1168 CloseHandle(info.hProcess);
1169 CloseHandle(info.hThread);
1170
1172 okChildInt("Toolhelp", "cntUsage", 0);
1173 okChildInt("Toolhelp", "th32DefaultHeapID", 0);
1174 okChildInt("Toolhelp", "th32ModuleID", 0);
1175 okChildInt("Toolhelp", "th32ParentProcessID", GetCurrentProcessId());
1176 /* pcPriClassBase differs between Windows versions (either 6 or 8) */
1177 okChildInt("Toolhelp", "dwFlags", 0);
1178
1181
1182#if defined(__REACTOS__) && defined(_M_AMD64)
1184 {
1185 skip("ROSTESTS-371: Skipping kernel32_winetest:sync test_apc_deadlock because it fails on Windows Server 2003 x64-Testbot. Set winetest_interactive to run it anyway.\n");
1186 }
1187 else
1188 {
1189#endif
1190
1192 sprintf(buffer, "\"%s\" tests/process.c nested \"%s\"", selfname, resfile);
1193 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess failed\n");
1194 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1195
1197 ok(process != NULL, "OpenProcess failed %u\n", GetLastError());
1199
1200 CloseHandle(info.hProcess);
1201 CloseHandle(info.hThread);
1202#if defined(__REACTOS__) && defined(_M_AMD64)
1203 }
1204#endif
1205
1206 for (i = 0; i < 20; i++)
1207 {
1208 SetLastError(0xdeadbeef);
1210 ok(process || GetLastError() == ERROR_INVALID_PARAMETER, "OpenProcess failed %u\n", GetLastError());
1211 if (!process) break;
1213 Sleep(100);
1214 }
1215 /* The following test fails randomly on some Windows versions, but Gothic 2 depends on it */
1216 ok(i < 20 || broken(i == 20), "process object not released\n");
1217
1218 snapshot = pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1219 ok(snapshot != INVALID_HANDLE_VALUE, "CreateToolhelp32Snapshot failed %u\n", GetLastError());
1220 memset(&pe, 0, sizeof(pe));
1221 pe.dwSize = sizeof(pe);
1222 if (pProcess32First(snapshot, &pe))
1223 {
1224 while (pe.th32ParentProcessID != info.dwProcessId)
1225 if (!pProcess32Next(snapshot, &pe)) break;
1226 }
1228 ok(pe.th32ParentProcessID == info.dwProcessId, "failed to find nested child process\n");
1229
1231 ok(process != NULL, "OpenProcess failed %u\n", GetLastError());
1232
1233 snapshot = pCreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
1234 ok(snapshot != INVALID_HANDLE_VALUE, "CreateToolhelp32Snapshot failed %u\n", GetLastError());
1235 memset(&te, 0, sizeof(te));
1236 te.dwSize = sizeof(te);
1237 if (pThread32First(snapshot, &te))
1238 {
1239 while (te.th32OwnerProcessID != pe.th32ProcessID)
1240 if (!pThread32Next(snapshot, &te)) break;
1241 }
1243 ok(te.th32OwnerProcessID == pe.th32ProcessID, "failed to find suspended thread\n");
1244
1246 ok(thread != NULL, "OpenThread failed %u\n", GetLastError());
1248 ok(ret == 1, "expected 1, got %u\n", ret);
1250
1251 ok(WaitForSingleObject(process, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1253
1255 okChildInt("Toolhelp", "cntUsage", 0);
1256 okChildInt("Toolhelp", "th32DefaultHeapID", 0);
1257 okChildInt("Toolhelp", "th32ModuleID", 0);
1258 okChildInt("Toolhelp", "th32ParentProcessID", info.dwProcessId);
1259 /* pcPriClassBase differs between Windows versions (either 6 or 8) */
1260 okChildInt("Toolhelp", "dwFlags", 0);
1261
1264}
1265
1266static BOOL is_str_env_drive_dir(const char* str)
1267{
1268 return str[0] == '=' && str[1] >= 'A' && str[1] <= 'Z' && str[2] == ':' &&
1269 str[3] == '=' && str[4] == str[1];
1270}
1271
1272/* compared expected child's environment (in gesA) from actual
1273 * environment our child got
1274 */
1275static void cmpEnvironment(const char* gesA)
1276{
1277 int i, clen;
1278 const char* ptrA;
1279 char* res;
1280 char key[32];
1281 BOOL found;
1282
1283 clen = GetPrivateProfileIntA("EnvironmentA", "len", 0, resfile);
1284
1285 /* now look each parent env in child */
1286 if ((ptrA = gesA) != NULL)
1287 {
1288 while (*ptrA)
1289 {
1290 for (i = 0; i < clen; i++)
1291 {
1292 sprintf(key, "env%d", i);
1293 res = getChildString("EnvironmentA", key);
1294 if (strncmp(ptrA, res, MAX_LISTED_ENV_VAR - 1) == 0)
1295 break;
1296 }
1297 found = i < clen;
1298 ok(found, "Parent-env string %s isn't in child process\n", ptrA);
1299
1300 ptrA += strlen(ptrA) + 1;
1302 }
1303 }
1304 /* and each child env in parent */
1305 for (i = 0; i < clen; i++)
1306 {
1307 sprintf(key, "env%d", i);
1308 res = getChildString("EnvironmentA", key);
1309 if ((ptrA = gesA) != NULL)
1310 {
1311 while (*ptrA)
1312 {
1313 if (strncmp(res, ptrA, MAX_LISTED_ENV_VAR - 1) == 0)
1314 break;
1315 ptrA += strlen(ptrA) + 1;
1316 }
1317 if (!*ptrA) ptrA = NULL;
1318 }
1319
1321 {
1322 found = ptrA != NULL;
1323 ok(found, "Child-env string %s isn't in parent process\n", res);
1324 }
1325 /* else => should also test we get the right per drive default directory here... */
1326 }
1327}
1328
1329static void test_Environment(void)
1330{
1331 char buffer[MAX_PATH];
1334 char *child_env;
1335 int child_env_len;
1336 char *ptr;
1337 char *ptr2;
1338 char *env;
1339 int slen;
1340
1341 memset(&startup, 0, sizeof(startup));
1342 startup.cb = sizeof(startup);
1343 startup.dwFlags = STARTF_USESHOWWINDOW;
1344 startup.wShowWindow = SW_SHOWNORMAL;
1345
1346 /* the basics */
1348 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
1349 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
1350 /* wait for child to terminate */
1351 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1352 /* child process has changed result file, so let profile functions know about it */
1354
1359
1360 memset(&startup, 0, sizeof(startup));
1361 startup.cb = sizeof(startup);
1362 startup.dwFlags = STARTF_USESHOWWINDOW;
1363 startup.wShowWindow = SW_SHOWNORMAL;
1364
1365 /* the basics */
1367 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
1368
1369 child_env_len = 0;
1370 ptr = env;
1371 while(*ptr)
1372 {
1373 slen = strlen(ptr)+1;
1374 child_env_len += slen;
1375 ptr += slen;
1376 }
1377 /* Add space for additional environment variables */
1378 child_env_len += 256;
1379 child_env = HeapAlloc(GetProcessHeap(), 0, child_env_len);
1380
1381 ptr = child_env;
1382 sprintf(ptr, "=%c:=%s", 'C', "C:\\FOO\\BAR");
1383 ptr += strlen(ptr) + 1;
1384 strcpy(ptr, "PATH=C:\\WINDOWS;C:\\WINDOWS\\SYSTEM;C:\\MY\\OWN\\DIR");
1385 ptr += strlen(ptr) + 1;
1386 strcpy(ptr, "FOO=BAR");
1387 ptr += strlen(ptr) + 1;
1388 strcpy(ptr, "BAR=FOOBAR");
1389 ptr += strlen(ptr) + 1;
1390 /* copy all existing variables except:
1391 * - WINELOADER
1392 * - PATH (already set above)
1393 * - the directory definitions (=[A-Z]:=)
1394 */
1395 for (ptr2 = env; *ptr2; ptr2 += strlen(ptr2) + 1)
1396 {
1397 if (strncmp(ptr2, "PATH=", 5) != 0 &&
1398 strncmp(ptr2, "WINELOADER=", 11) != 0 &&
1399 !is_str_env_drive_dir(ptr2))
1400 {
1401 strcpy(ptr, ptr2);
1402 ptr += strlen(ptr) + 1;
1403 }
1404 }
1405 *ptr = '\0';
1406 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, child_env, NULL, &startup, &info), "CreateProcess\n");
1407 /* wait for child to terminate */
1408 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1409 /* child process has changed result file, so let profile functions know about it */
1411
1412 cmpEnvironment(child_env);
1413
1414 HeapFree(GetProcessHeap(), 0, child_env);
1418}
1419
1420static void test_SuspendFlag(void)
1421{
1422 char buffer[MAX_PATH];
1425 DWORD exit_status;
1426 char *result;
1427
1428 /* let's start simplistic */
1429 memset(&startup, 0, sizeof(startup));
1430 startup.cb = sizeof(startup);
1431 startup.dwFlags = STARTF_USESHOWWINDOW;
1432 startup.wShowWindow = SW_SHOWNORMAL;
1433
1435 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
1436 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startup, &info), "CreateProcess\n");
1437
1438 ok(GetExitCodeThread(info.hThread, &exit_status) && exit_status == STILL_ACTIVE, "thread still running\n");
1439 Sleep(1000);
1440 ok(GetExitCodeThread(info.hThread, &exit_status) && exit_status == STILL_ACTIVE, "thread still running\n");
1441 ok(ResumeThread(info.hThread) == 1, "Resuming thread\n");
1442
1443 /* wait for child to terminate */
1444 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1445 /* child process has changed result file, so let profile functions know about it */
1447
1449
1450 okChildInt("StartupInfoA", "cb", startup.cb);
1451 okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
1452 result = getChildString( "StartupInfoA", "lpTitle" );
1453 ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
1454 "expected '%s' or null, got '%s'\n", selfname, result );
1455 okChildInt("StartupInfoA", "dwX", startup.dwX);
1456 okChildInt("StartupInfoA", "dwY", startup.dwY);
1457 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
1458 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
1459 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
1460 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
1461 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
1462 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
1463 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
1466}
1467
1468static void test_DebuggingFlag(void)
1469{
1470 char buffer[MAX_PATH];
1471 void *processbase = NULL;
1474 DEBUG_EVENT de;
1475 unsigned dbg = 0;
1476 char *result;
1477
1478 /* let's start simplistic */
1479 memset(&startup, 0, sizeof(startup));
1480 startup.cb = sizeof(startup);
1481 startup.dwFlags = STARTF_USESHOWWINDOW;
1482 startup.wShowWindow = SW_SHOWNORMAL;
1483
1485 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
1486 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n");
1487
1488 /* get all startup events up to the entry point break exception */
1489 do
1490 {
1491 ok(WaitForDebugEvent(&de, INFINITE), "reading debug event\n");
1493 if (!dbg)
1494 {
1496 "first event: %d\n", de.dwDebugEventCode);
1497 processbase = de.u.CreateProcessInfo.lpBaseOfImage;
1498 }
1499 if (de.dwDebugEventCode != EXCEPTION_DEBUG_EVENT) dbg++;
1501 de.u.LoadDll.lpBaseOfDll != processbase, "got LOAD_DLL for main module\n");
1503
1504 ok(dbg, "I have seen a debug event\n");
1505 /* wait for child to terminate */
1506 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1507 /* child process has changed result file, so let profile functions know about it */
1509
1511
1512 okChildInt("StartupInfoA", "cb", startup.cb);
1513 okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
1514 result = getChildString( "StartupInfoA", "lpTitle" );
1515 ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
1516 "expected '%s' or null, got '%s'\n", selfname, result );
1517 okChildInt("StartupInfoA", "dwX", startup.dwX);
1518 okChildInt("StartupInfoA", "dwY", startup.dwY);
1519 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
1520 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
1521 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
1522 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
1523 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
1524 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
1525 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
1528}
1529
1531{
1532 return h != INVALID_HANDLE_VALUE && ((ULONG_PTR)h & 3) == 3;
1533}
1534
1535static void test_Console(void)
1536{
1537 char buffer[MAX_PATH];
1542 DWORD modeIn, modeOut, modeInC, modeOutC;
1543 DWORD cpIn, cpOut, cpInC, cpOutC;
1544 DWORD w;
1545 HANDLE hChildIn, hChildInInh, hChildOut, hChildOutInh, hParentIn, hParentOut;
1546 const char* msg = "This is a std-handle inheritance test.";
1547 unsigned msg_len;
1549 char *result;
1550
1551 memset(&startup, 0, sizeof(startup));
1552 startup.cb = sizeof(startup);
1554 startup.wShowWindow = SW_SHOWNORMAL;
1555
1556 sa.nLength = sizeof(sa);
1557 sa.lpSecurityDescriptor = NULL;
1558 sa.bInheritHandle = TRUE;
1559
1560 startup.hStdInput = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
1561 startup.hStdOutput = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
1562
1563 /* first, we need to be sure we're attached to a console */
1564 if (!is_console(startup.hStdInput) || !is_console(startup.hStdOutput))
1565 {
1566 /* we're not attached to a console, let's do it */
1567 AllocConsole();
1568 startup.hStdInput = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
1569 startup.hStdOutput = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
1570 }
1571 /* now verify everything's ok */
1572 ok(startup.hStdInput != INVALID_HANDLE_VALUE, "Opening ConIn\n");
1573 ok(startup.hStdOutput != INVALID_HANDLE_VALUE, "Opening ConOut\n");
1574 startup.hStdError = startup.hStdOutput;
1575
1576 ok(GetConsoleScreenBufferInfo(startup.hStdOutput, &sbi), "Getting sb info\n");
1577 ok(GetConsoleMode(startup.hStdInput, &modeIn), "Getting console in mode\n");
1578 ok(GetConsoleMode(startup.hStdOutput, &modeOut), "Getting console out mode\n");
1579 cpIn = GetConsoleCP();
1580 cpOut = GetConsoleOutputCP();
1581
1583 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" console", selfname, resfile);
1584 ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
1585
1586 /* wait for child to terminate */
1587 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1588 /* child process has changed result file, so let profile functions know about it */
1590
1591 /* now get the modification the child has made, and resets parents expected values */
1592 ok(GetConsoleScreenBufferInfo(startup.hStdOutput, &sbiC), "Getting sb info\n");
1593 ok(GetConsoleMode(startup.hStdInput, &modeInC), "Getting console in mode\n");
1594 ok(GetConsoleMode(startup.hStdOutput, &modeOutC), "Getting console out mode\n");
1595
1596 SetConsoleMode(startup.hStdInput, modeIn);
1597 SetConsoleMode(startup.hStdOutput, modeOut);
1598
1599 cpInC = GetConsoleCP();
1600 cpOutC = GetConsoleOutputCP();
1601
1602 /* Try to set invalid CP */
1603 SetLastError(0xdeadbeef);
1604 ok(!SetConsoleCP(0), "Shouldn't succeed\n");
1607 "GetLastError: expecting %u got %u\n",
1610 run_tests = FALSE;
1611
1612
1613 SetLastError(0xdeadbeef);
1614 ok(!SetConsoleOutputCP(0), "Shouldn't succeed\n");
1617 "GetLastError: expecting %u got %u\n",
1619
1620 SetConsoleCP(cpIn);
1621 SetConsoleOutputCP(cpOut);
1622
1624
1625 okChildInt("StartupInfoA", "cb", startup.cb);
1626 okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
1627 result = getChildString( "StartupInfoA", "lpTitle" );
1628 ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
1629 "expected '%s' or null, got '%s'\n", selfname, result );
1630 okChildInt("StartupInfoA", "dwX", startup.dwX);
1631 okChildInt("StartupInfoA", "dwY", startup.dwY);
1632 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
1633 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
1634 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
1635 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
1636 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
1637 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
1638 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
1639
1640 /* check child correctly inherited the console */
1641 okChildInt("StartupInfoA", "hStdInput", (DWORD_PTR)startup.hStdInput);
1642 okChildInt("StartupInfoA", "hStdOutput", (DWORD_PTR)startup.hStdOutput);
1643 okChildInt("StartupInfoA", "hStdError", (DWORD_PTR)startup.hStdError);
1644 okChildInt("Console", "SizeX", (DWORD)sbi.dwSize.X);
1645 okChildInt("Console", "SizeY", (DWORD)sbi.dwSize.Y);
1646 okChildInt("Console", "CursorX", (DWORD)sbi.dwCursorPosition.X);
1647 okChildInt("Console", "CursorY", (DWORD)sbi.dwCursorPosition.Y);
1648 okChildInt("Console", "Attributes", sbi.wAttributes);
1649 okChildInt("Console", "winLeft", (DWORD)sbi.srWindow.Left);
1650 okChildInt("Console", "winTop", (DWORD)sbi.srWindow.Top);
1651 okChildInt("Console", "winRight", (DWORD)sbi.srWindow.Right);
1652 okChildInt("Console", "winBottom", (DWORD)sbi.srWindow.Bottom);
1653 okChildInt("Console", "maxWinWidth", (DWORD)sbi.dwMaximumWindowSize.X);
1654 okChildInt("Console", "maxWinHeight", (DWORD)sbi.dwMaximumWindowSize.Y);
1655 okChildInt("Console", "InputCP", cpIn);
1656 okChildInt("Console", "OutputCP", cpOut);
1657 okChildInt("Console", "InputMode", modeIn);
1658 okChildInt("Console", "OutputMode", modeOut);
1659
1660 if (run_tests)
1661 {
1662 ok(cpInC == 1252, "Wrong console CP (expected 1252 got %d/%d)\n", cpInC, cpIn);
1663 ok(cpOutC == 1252, "Wrong console-SB CP (expected 1252 got %d/%d)\n", cpOutC, cpOut);
1664 }
1665 else
1666 win_skip("Setting the codepage is not implemented\n");
1667
1668 ok(modeInC == (modeIn ^ 1), "Wrong console mode\n");
1669 ok(modeOutC == (modeOut ^ 1), "Wrong console-SB mode\n");
1670 trace("cursor position(X): %d/%d\n",sbi.dwCursorPosition.X, sbiC.dwCursorPosition.X);
1671 ok(sbiC.dwCursorPosition.Y == (sbi.dwCursorPosition.Y ^ 1), "Wrong cursor position\n");
1672
1675
1676 ok(CreatePipe(&hParentIn, &hChildOut, NULL, 0), "Creating parent-input pipe\n");
1678 &hChildOutInh, 0, TRUE, DUPLICATE_SAME_ACCESS),
1679 "Duplicating as inheritable child-output pipe\n");
1680 CloseHandle(hChildOut);
1681
1682 ok(CreatePipe(&hChildIn, &hParentOut, NULL, 0), "Creating parent-output pipe\n");
1684 &hChildInInh, 0, TRUE, DUPLICATE_SAME_ACCESS),
1685 "Duplicating as inheritable child-input pipe\n");
1686 CloseHandle(hChildIn);
1687
1688 memset(&startup, 0, sizeof(startup));
1689 startup.cb = sizeof(startup);
1691 startup.wShowWindow = SW_SHOWNORMAL;
1692 startup.hStdInput = hChildInInh;
1693 startup.hStdOutput = hChildOutInh;
1694 startup.hStdError = hChildOutInh;
1695
1697 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" stdhandle", selfname, resfile);
1698 ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n");
1699 ok(CloseHandle(hChildInInh), "Closing handle\n");
1700 ok(CloseHandle(hChildOutInh), "Closing handle\n");
1701
1702 msg_len = strlen(msg) + 1;
1703 ok(WriteFile(hParentOut, msg, msg_len, &w, NULL), "Writing to child\n");
1704 ok(w == msg_len, "Should have written %u bytes, actually wrote %u\n", msg_len, w);
1705 memset(buffer, 0, sizeof(buffer));
1706 ok(ReadFile(hParentIn, buffer, sizeof(buffer), &w, NULL), "Reading from child\n");
1707 ok(strcmp(buffer, msg) == 0, "Should have received '%s'\n", msg);
1708
1709 /* the child may also send the final "n tests executed" string, so read it to avoid a deadlock */
1710 ReadFile(hParentIn, buffer, sizeof(buffer), &w, NULL);
1711
1712 /* wait for child to terminate */
1713 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1714 /* child process has changed result file, so let profile functions know about it */
1716
1717 okChildString("StdHandle", "msg", msg);
1718
1721}
1722
1723static void test_ExitCode(void)
1724{
1725 char buffer[MAX_PATH];
1728 DWORD code;
1729
1730 /* let's start simplistic */
1731 memset(&startup, 0, sizeof(startup));
1732 startup.cb = sizeof(startup);
1733 startup.dwFlags = STARTF_USESHOWWINDOW;
1734 startup.wShowWindow = SW_SHOWNORMAL;
1735
1737 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" exit_code", selfname, resfile);
1738 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
1739
1740 /* wait for child to terminate */
1741 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1742 /* child process has changed result file, so let profile functions know about it */
1744
1745 ok(GetExitCodeProcess(info.hProcess, &code), "Getting exit code\n");
1746 okChildInt("ExitCode", "value", code);
1747
1750}
1751
1752static void test_OpenProcess(void)
1753{
1754 HANDLE hproc;
1755 void *addr1;
1758 BOOL ret;
1759
1760 /* not exported in all windows versions */
1761 if ((!pVirtualAllocEx) || (!pVirtualFreeEx)) {
1762 win_skip("VirtualAllocEx not found\n");
1763 return;
1764 }
1765
1766 /* without PROCESS_VM_OPERATION */
1768 ok(hproc != NULL, "OpenProcess error %d\n", GetLastError());
1769
1770 SetLastError(0xdeadbeef);
1771 addr1 = pVirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
1772 ok(!addr1, "VirtualAllocEx should fail\n");
1774 { /* Win9x */
1775 CloseHandle(hproc);
1776 win_skip("VirtualAllocEx not implemented\n");
1777 return;
1778 }
1779 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
1780
1781 read_bytes = 0xdeadbeef;
1782 SetLastError(0xdeadbeef);
1784 ok(ret, "ReadProcessMemory error %d\n", GetLastError());
1785 ok(read_bytes == sizeof(dummy), "wrong read bytes %ld\n", read_bytes);
1786
1787 CloseHandle(hproc);
1788
1790 ok(hproc != NULL, "OpenProcess error %d\n", GetLastError());
1791
1792 addr1 = pVirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
1793 ok(addr1 != NULL, "VirtualAllocEx error %d\n", GetLastError());
1794
1795 /* without PROCESS_QUERY_INFORMATION */
1796 SetLastError(0xdeadbeef);
1797 ok(!VirtualQueryEx(hproc, addr1, &info, sizeof(info)),
1798 "VirtualQueryEx without PROCESS_QUERY_INFORMATION rights should fail\n");
1799 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
1800
1801 /* without PROCESS_VM_READ */
1802 read_bytes = 0xdeadbeef;
1803 SetLastError(0xdeadbeef);
1804 ok(!ReadProcessMemory(hproc, addr1, &dummy, sizeof(dummy), &read_bytes),
1805 "ReadProcessMemory without PROCESS_VM_READ rights should fail\n");
1806 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
1807 ok(read_bytes == 0, "wrong read bytes %ld\n", read_bytes);
1808
1809 CloseHandle(hproc);
1810
1812
1813 memset(&info, 0xcc, sizeof(info));
1814 read_bytes = VirtualQueryEx(hproc, addr1, &info, sizeof(info));
1815 ok(read_bytes == sizeof(info), "VirtualQueryEx error %d\n", GetLastError());
1816
1817 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
1818 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
1819 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
1820 ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
1821 ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
1822 /* NT reports Protect == 0 for a not committed memory block */
1823 ok(info.Protect == 0 /* NT */ ||
1824 info.Protect == PAGE_NOACCESS, /* Win9x */
1825 "%x != PAGE_NOACCESS\n", info.Protect);
1826 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
1827
1828 SetLastError(0xdeadbeef);
1829 ok(!pVirtualFreeEx(hproc, addr1, 0, MEM_RELEASE),
1830 "VirtualFreeEx without PROCESS_VM_OPERATION rights should fail\n");
1831 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
1832
1833 CloseHandle(hproc);
1834
1836 if (hproc)
1837 {
1838 SetLastError(0xdeadbeef);
1839 memset(&info, 0xcc, sizeof(info));
1840 read_bytes = VirtualQueryEx(hproc, addr1, &info, sizeof(info));
1841 if (read_bytes) /* win8 */
1842 {
1843 ok(read_bytes == sizeof(info), "VirtualQueryEx error %d\n", GetLastError());
1844 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
1845 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
1846 ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
1847 ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
1848 ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
1849 ok(info.Protect == 0, "%x != PAGE_NOACCESS\n", info.Protect);
1850 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
1851 }
1852 else /* before win8 */
1853 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
1854
1855 SetLastError(0xdeadbeef);
1856 ok(!pVirtualFreeEx(hproc, addr1, 0, MEM_RELEASE),
1857 "VirtualFreeEx without PROCESS_VM_OPERATION rights should fail\n");
1858 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
1859
1860 CloseHandle(hproc);
1861 }
1862
1863 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
1864}
1865
1866static void test_GetProcessVersion(void)
1867{
1868 static char cmdline[] = "winver.exe";
1870 STARTUPINFOA si;
1871 DWORD ret;
1872
1873 SetLastError(0xdeadbeef);
1875 ok(ret, "GetProcessVersion error %u\n", GetLastError());
1876
1877 SetLastError(0xdeadbeef);
1879 ok(ret, "GetProcessVersion error %u\n", GetLastError());
1880
1881 memset(&si, 0, sizeof(si));
1882 si.cb = sizeof(si);
1884 si.wShowWindow = SW_HIDE;
1885 SetLastError(0xdeadbeef);
1886 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
1887 ok(ret, "CreateProcess error %u\n", GetLastError());
1888
1889 SetLastError(0xdeadbeef);
1890 ret = GetProcessVersion(pi.dwProcessId);
1891 ok(ret, "GetProcessVersion error %u\n", GetLastError());
1892
1893 SetLastError(0xdeadbeef);
1894 ret = TerminateProcess(pi.hProcess, 0);
1895 ok(ret, "TerminateProcess error %u\n", GetLastError());
1896
1897 CloseHandle(pi.hProcess);
1898 CloseHandle(pi.hThread);
1899}
1900
1902{
1903 DWORD rc;
1905 static const char harddisk[] = "\\Device\\HarddiskVolume";
1906
1907 if (!pK32GetProcessImageFileNameA)
1908 {
1909 win_skip("K32GetProcessImageFileNameA is unavailable\n");
1910 return;
1911 }
1912
1913 /* callers must guess the buffer size */
1914 SetLastError(0xdeadbeef);
1915 rc = pK32GetProcessImageFileNameA(GetCurrentProcess(), NULL, 0);
1917 "K32GetProcessImageFileNameA(no buffer): returned %u, le=%u\n", rc, GetLastError());
1918
1919 *process = '\0';
1920 rc = pK32GetProcessImageFileNameA(GetCurrentProcess(), process, sizeof(process));
1922 if (strncmp(process, harddisk, lstrlenA(harddisk)))
1923 {
1924 todo_wine win_skip("%s is probably on a network share, skipping tests\n", process);
1925 return;
1926 }
1927
1928 if (!pQueryFullProcessImageNameA)
1929 win_skip("QueryFullProcessImageNameA unavailable (added in Windows Vista)\n");
1930 else
1931 {
1933 DWORD length;
1934
1935 length = sizeof(image);
1936 expect_eq_d(TRUE, pQueryFullProcessImageNameA(GetCurrentProcess(), PROCESS_NAME_NATIVE, image, &length));
1938 ok(lstrcmpiA(process, image) == 0, "expected '%s' to be equal to '%s'\n", process, image);
1939 }
1940}
1941
1943{
1944#define INIT_STR "Just some words"
1945 DWORD length, size;
1947
1948 if (!pQueryFullProcessImageNameA)
1949 {
1950 win_skip("QueryFullProcessImageNameA unavailable (added in Windows Vista)\n");
1951 return;
1952 }
1953
1954 *module = '\0';
1955 SetLastError(0); /* old Windows don't reset it on success */
1957 ok(size && GetLastError() != ERROR_INSUFFICIENT_BUFFER, "GetModuleFileName failed: %u le=%u\n", size, GetLastError());
1958
1959 /* get the buffer length without \0 terminator */
1960 length = sizeof(buf);
1961 expect_eq_d(TRUE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, buf, &length));
1963 ok((buf[0] == '\\' && buf[1] == '\\') ||
1964 lstrcmpiA(buf, module) == 0, "expected %s to match %s\n", buf, module);
1965
1966 /* when the buffer is too small
1967 * - function fail with error ERROR_INSUFFICIENT_BUFFER
1968 * - the size variable is not modified
1969 * tested with the biggest too small size
1970 */
1971 size = length;
1973 expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, buf, &size));
1977
1978 /* retest with smaller buffer size
1979 */
1980 size = 4;
1982 expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, buf, &size));
1984 expect_eq_d(4, size);
1986
1987 /* this is a difference between the ascii and the unicode version
1988 * the unicode version crashes when the size is big enough to hold
1989 * the result while the ascii version throws an error
1990 */
1991 size = 1024;
1992 expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, NULL, &size));
1993 expect_eq_d(1024, size);
1995}
1996
1998{
1999 HANDLE hSelf;
2000 WCHAR module_name[1024], device[1024];
2001 WCHAR deviceW[] = {'\\','D', 'e','v','i','c','e',0};
2002 WCHAR buf[1024];
2003 DWORD size, len;
2004
2005 if (!pQueryFullProcessImageNameW)
2006 {
2007 win_skip("QueryFullProcessImageNameW unavailable (added in Windows Vista)\n");
2008 return;
2009 }
2010
2011 ok(GetModuleFileNameW(NULL, module_name, 1024), "GetModuleFileNameW(NULL, ...) failed\n");
2012
2013 /* GetCurrentProcess pseudo-handle */
2014 size = sizeof(buf) / sizeof(buf[0]);
2015 expect_eq_d(TRUE, pQueryFullProcessImageNameW(GetCurrentProcess(), 0, buf, &size));
2018
2020 /* Real handle */
2021 size = sizeof(buf) / sizeof(buf[0]);
2022 expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
2025
2026 /* Buffer too small */
2029 SetLastError(0xdeadbeef);
2030 expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
2031 expect_eq_d(lstrlenW(module_name)/2, size); /* size not changed(!) */
2033 expect_eq_ws_i(deviceW, buf); /* buffer not changed */
2034
2035 /* Too small - not space for NUL terminator */
2037 SetLastError(0xdeadbeef);
2038 expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
2039 expect_eq_d(lstrlenW(module_name), size); /* size not changed(!) */
2041
2042 /* NULL buffer */
2043 size = 0;
2044 expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, NULL, &size));
2045 expect_eq_d(0, size);
2047
2048 /* Buffer too small */
2050 SetLastError(0xdeadbeef);
2052 expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
2053 expect_eq_d(lstrlenW(module_name)/2, size); /* size not changed(!) */
2055 expect_eq_ws_i(module_name, buf); /* buffer not changed */
2056
2057
2058 /* native path */
2059 size = sizeof(buf) / sizeof(buf[0]);
2060 expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, PROCESS_NAME_NATIVE, buf, &size));
2062 ok(buf[0] == '\\', "NT path should begin with '\\'\n");
2063 ok(memcmp(buf, deviceW, sizeof(WCHAR)*lstrlenW(deviceW)) == 0, "NT path should begin with \\Device\n");
2064
2065 module_name[2] = '\0';
2066 *device = '\0';
2067 size = QueryDosDeviceW(module_name, device, sizeof(device)/sizeof(device[0]));
2068 ok(size, "QueryDosDeviceW failed: le=%u\n", GetLastError());
2069 len = lstrlenW(device);
2070 ok(size >= len+2, "expected %d to be greater than %d+2 = strlen(%s)\n", size, len, wine_dbgstr_w(device));
2071
2072 if (size >= lstrlenW(buf))
2073 {
2074 ok(0, "expected %s\\ to match the start of %s\n", wine_dbgstr_w(device), wine_dbgstr_w(buf));
2075 }
2076 else
2077 {
2078 ok(buf[len] == '\\', "expected '%c' to be a '\\' in %s\n", buf[len], wine_dbgstr_w(module_name));
2079 buf[len] = '\0';
2080 ok(lstrcmpiW(device, buf) == 0, "expected %s to match %s\n", wine_dbgstr_w(device), wine_dbgstr_w(buf));
2081 ok(lstrcmpiW(module_name+3, buf+len+1) == 0, "expected '%s' to match '%s'\n", wine_dbgstr_w(module_name+3), wine_dbgstr_w(buf+len+1));
2082 }
2083
2084 CloseHandle(hSelf);
2085}
2086
2087static void test_Handles(void)
2088{
2090 HANDLE h2, h3;
2091 BOOL ret;
2092 DWORD code;
2093
2094 ok( handle == (HANDLE)~(ULONG_PTR)0 ||
2095 handle == (HANDLE)(ULONG_PTR)0x7fffffff /* win9x */,
2096 "invalid current process handle %p\n", handle );
2098 ok( ret, "GetExitCodeProcess failed err %u\n", GetLastError() );
2099#ifdef _WIN64
2100 /* truncated handle */
2101 SetLastError( 0xdeadbeef );
2102 handle = (HANDLE)((ULONG_PTR)handle & ~0u);
2104 ok( !ret, "GetExitCodeProcess succeeded for %p\n", handle );
2105 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
2106 /* sign-extended handle */
2107 SetLastError( 0xdeadbeef );
2110 ok( ret, "GetExitCodeProcess failed err %u\n", GetLastError() );
2111 /* invalid high-word */
2112 SetLastError( 0xdeadbeef );
2113 handle = (HANDLE)(((ULONG_PTR)handle & ~0u) + ((ULONG_PTR)1 << 32));
2115 ok( !ret, "GetExitCodeProcess succeeded for %p\n", handle );
2116 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
2117#endif
2118
2120 ok( handle != 0, "handle %p\n", handle );
2126 ok( h2 == 0 ||
2127 broken( h2 == h3) || /* nt4, w2k */
2128 broken( h2 == INVALID_HANDLE_VALUE), /* win9x */
2129 "wrong handle %p/%p\n", h2, h3 );
2131}
2132
2133static void test_IsWow64Process(void)
2134{
2136 STARTUPINFOA si;
2137 DWORD ret;
2138 BOOL is_wow64;
2139 static char cmdline[] = "C:\\Program Files\\Internet Explorer\\iexplore.exe";
2140 static char cmdline_wow64[] = "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe";
2141
2142 if (!pIsWow64Process)
2143 {
2144 skip("IsWow64Process is not available\n");
2145 return;
2146 }
2147
2148 memset(&si, 0, sizeof(si));
2149 si.cb = sizeof(si);
2151 si.wShowWindow = SW_HIDE;
2152 ret = CreateProcessA(NULL, cmdline_wow64, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2153 if (ret)
2154 {
2155 trace("Created process %s\n", cmdline_wow64);
2156 is_wow64 = FALSE;
2157 ret = pIsWow64Process(pi.hProcess, &is_wow64);
2158 ok(ret, "IsWow64Process failed.\n");
2159 ok(is_wow64, "is_wow64 returned FALSE.\n");
2160
2161 ret = TerminateProcess(pi.hProcess, 0);
2162 ok(ret, "TerminateProcess error\n");
2163
2164 CloseHandle(pi.hProcess);
2165 CloseHandle(pi.hThread);
2166 }
2167
2168 memset(&si, 0, sizeof(si));
2169 si.cb = sizeof(si);
2171 si.wShowWindow = SW_HIDE;
2172 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2173 if (ret)
2174 {
2175 trace("Created process %s\n", cmdline);
2176 is_wow64 = TRUE;
2177 ret = pIsWow64Process(pi.hProcess, &is_wow64);
2178 ok(ret, "IsWow64Process failed.\n");
2179 ok(!is_wow64, "is_wow64 returned TRUE.\n");
2180
2181 ret = TerminateProcess(pi.hProcess, 0);
2182 ok(ret, "TerminateProcess error\n");
2183
2184 CloseHandle(pi.hProcess);
2185 CloseHandle(pi.hThread);
2186 }
2187}
2188
2189static void test_SystemInfo(void)
2190{
2191 SYSTEM_INFO si, nsi;
2192 BOOL is_wow64;
2193
2194 if (!pGetNativeSystemInfo)
2195 {
2196 win_skip("GetNativeSystemInfo is not available\n");
2197 return;
2198 }
2199
2200 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
2201
2202 GetSystemInfo(&si);
2203 pGetNativeSystemInfo(&nsi);
2204 if (is_wow64)
2205 {
2206 if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
2207 {
2208 ok(S(U(nsi)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64,
2209 "Expected PROCESSOR_ARCHITECTURE_AMD64, got %d\n",
2210 S(U(nsi)).wProcessorArchitecture);
2212 "Expected PROCESSOR_AMD_X8664, got %d\n",
2213 nsi.dwProcessorType);
2214 }
2215 }
2216 else
2217 {
2218 ok(S(U(si)).wProcessorArchitecture == S(U(nsi)).wProcessorArchitecture,
2219 "Expected no difference for wProcessorArchitecture, got %d and %d\n",
2220 S(U(si)).wProcessorArchitecture, S(U(nsi)).wProcessorArchitecture);
2222 "Expected no difference for dwProcessorType, got %d and %d\n",
2224 }
2225}
2226
2227static void test_RegistryQuota(void)
2228{
2229 BOOL ret;
2230 DWORD max_quota, used_quota;
2231
2232 if (!pGetSystemRegistryQuota)
2233 {
2234 win_skip("GetSystemRegistryQuota is not available\n");
2235 return;
2236 }
2237
2238 ret = pGetSystemRegistryQuota(NULL, NULL);
2239 ok(ret == TRUE,
2240 "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
2241
2242 ret = pGetSystemRegistryQuota(&max_quota, NULL);
2243 ok(ret == TRUE,
2244 "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
2245
2246 ret = pGetSystemRegistryQuota(NULL, &used_quota);
2247 ok(ret == TRUE,
2248 "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
2249
2250 ret = pGetSystemRegistryQuota(&max_quota, &used_quota);
2251 ok(ret == TRUE,
2252 "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
2253}
2254
2255static void test_TerminateProcess(void)
2256{
2257 static char cmdline[] = "winver.exe";
2259 STARTUPINFOA si;
2260 DWORD ret;
2262
2263 memset(&si, 0, sizeof(si));
2264 si.cb = sizeof(si);
2265 SetLastError(0xdeadbeef);
2267 ok(ret, "CreateProcess error %u\n", GetLastError());
2268
2269 SetLastError(0xdeadbeef);
2270 thread = CreateRemoteThread(pi.hProcess, NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret);
2271 ok(thread != 0, "CreateRemoteThread error %d\n", GetLastError());
2272
2273 /* create a not closed thread handle duplicate in the target process */
2274 SetLastError(0xdeadbeef);
2277 ok(ret, "DuplicateHandle error %u\n", GetLastError());
2278
2279 SetLastError(0xdeadbeef);
2281 ok(ret, "TerminateThread error %u\n", GetLastError());
2283
2284 SetLastError(0xdeadbeef);
2285 ret = TerminateProcess(pi.hProcess, 0);
2286 ok(ret, "TerminateProcess error %u\n", GetLastError());
2287
2288 CloseHandle(pi.hProcess);
2289 CloseHandle(pi.hThread);
2290}
2291
2292static void test_DuplicateHandle(void)
2293{
2295 HANDLE f, fmin, out;
2296 DWORD info;
2297 BOOL r;
2298
2300 GetCurrentProcess(), &out, 0, FALSE,
2302 ok(r, "DuplicateHandle error %u\n", GetLastError());
2304 ok(r, "GetHandleInformation error %u\n", GetLastError());
2305 ok(info == 0, "info = %x\n", info);
2306 ok(out != GetCurrentProcess(), "out = GetCurrentProcess()\n");
2308
2310 GetCurrentProcess(), &out, 0, TRUE,
2312 ok(r, "DuplicateHandle error %u\n", GetLastError());
2314 ok(r, "GetHandleInformation error %u\n", GetLastError());
2315 ok(info == HANDLE_FLAG_INHERIT, "info = %x\n", info);
2316 ok(out != GetCurrentProcess(), "out = GetCurrentProcess()\n");
2318
2320 GetTempFileNameA(path, "wt", 0, file_name);
2322 if (f == INVALID_HANDLE_VALUE)
2323 {
2324 ok(0, "could not create %s\n", file_name);
2325 return;
2326 }
2327
2330 ok(r, "DuplicateHandle error %u\n", GetLastError());
2331 ok(f == out, "f != out\n");
2333 ok(r, "GetHandleInformation error %u\n", GetLastError());
2334 ok(info == 0, "info = %x\n", info);
2335
2338 ok(r, "DuplicateHandle error %u\n", GetLastError());
2339 ok(f == out, "f != out\n");
2341 ok(r, "GetHandleInformation error %u\n", GetLastError());
2342 ok(info == HANDLE_FLAG_INHERIT, "info = %x\n", info);
2343
2345 ok(r, "SetHandleInformation error %u\n", GetLastError());
2348 ok(r, "DuplicateHandle error %u\n", GetLastError());
2349 ok(f != out, "f == out\n");
2351 ok(r, "GetHandleInformation error %u\n", GetLastError());
2352 ok(info == HANDLE_FLAG_INHERIT, "info = %x\n", info);
2354 ok(r, "SetHandleInformation error %u\n", GetLastError());
2355
2356 /* Test if DuplicateHandle allocates first free handle */
2357 if (f > out)
2358 {
2359 fmin = out;
2360 }
2361 else
2362 {
2363 fmin = f;
2364 f = out;
2365 }
2369 ok(r, "DuplicateHandle error %u\n", GetLastError());
2370 ok(f == out, "f != out\n");
2373
2374 f = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
2375 if (!is_console(f))
2376 {
2377 skip("DuplicateHandle on console handle\n");
2378 CloseHandle(f);
2379 return;
2380 }
2381
2384 ok(r, "DuplicateHandle error %u\n", GetLastError());
2385 todo_wine ok(f != out, "f == out\n");
2387}
2388
2389#define test_completion(a, b, c, d, e) _test_completion(__LINE__, a, b, c, d, e)
2390static void _test_completion(int line, HANDLE port, DWORD ekey, ULONG_PTR evalue, ULONG_PTR eoverlapped, DWORD wait)
2391{
2394 DWORD key;
2395 BOOL ret;
2396
2398
2399 ok_(__FILE__, line)(ret, "GetQueuedCompletionStatus: %x\n", GetLastError());
2400 if (ret)
2401 {
2402 ok_(__FILE__, line)(key == ekey, "unexpected key %x\n", key);
2403 ok_(__FILE__, line)(value == evalue, "unexpected value %p\n", (void *)value);
2404 ok_(__FILE__, line)(overlapped == (LPOVERLAPPED)eoverlapped, "unexpected overlapped %p\n", overlapped);
2405 }
2406}
2407
2408#define create_process(cmd, pi) _create_process(__LINE__, cmd, pi)
2410{
2411 BOOL ret;
2412 char buffer[MAX_PATH];
2413 STARTUPINFOA si = {0};
2414
2415 sprintf(buffer, "\"%s\" tests/process.c %s", selfname, command);
2416
2417 ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, pi);
2418 ok_(__FILE__, line)(ret, "CreateProcess error %u\n", GetLastError());
2419}
2420
2421#define test_assigned_proc(job, ...) _test_assigned_proc(__LINE__, job, __VA_ARGS__)
2423{
2424 char buf[sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + sizeof(ULONG_PTR) * 20];
2426 DWORD ret_len, pid;
2428 int n;
2429 BOOL ret;
2430
2431 memset(buf, 0, sizeof(buf));
2432 ret = pQueryInformationJobObject(job, JobObjectBasicProcessIdList, pid_list, sizeof(buf), &ret_len);
2433 ok_(__FILE__, line)(ret, "QueryInformationJobObject error %u\n", GetLastError());
2434 if (ret)
2435 {
2437 ok_(__FILE__, line)(expected_count == pid_list->NumberOfAssignedProcesses,
2438 "Expected NumberOfAssignedProcesses to be %d (expected_count) is %d\n",
2441 ok_(__FILE__, line)(expected_count == pid_list->NumberOfProcessIdsInList,
2442 "Expected NumberOfProcessIdsInList to be %d (expected_count) is %d\n",
2444
2446 for (n = 0; n < min(expected_count, pid_list->NumberOfProcessIdsInList); ++n)
2447 {
2448 pid = va_arg(valist, DWORD);
2449 ok_(__FILE__, line)(pid == pid_list->ProcessIdList[n],
2450 "Expected pid_list->ProcessIdList[%d] to be %x is %lx\n",
2451 n, pid, pid_list->ProcessIdList[n]);
2452 }
2453 va_end(valist);
2454 }
2455}
2456
2457#define test_accounting(job, total_proc, active_proc, terminated_proc) _test_accounting(__LINE__, job, total_proc, active_proc, terminated_proc)
2458static void _test_accounting(int line, HANDLE job, int total_proc, int active_proc, int terminated_proc)
2459{
2461 DWORD ret_len;
2462 BOOL ret;
2463
2464 memset(&basic_accounting, 0, sizeof(basic_accounting));
2465 ret = pQueryInformationJobObject(job, JobObjectBasicAccountingInformation, &basic_accounting, sizeof(basic_accounting), &ret_len);
2466 ok_(__FILE__, line)(ret, "QueryInformationJobObject error %u\n", GetLastError());
2467 if (ret)
2468 {
2469 /* Not going to check process times or page faults */
2470
2471 todo_wine_if(total_proc)
2472 ok_(__FILE__, line)(total_proc == basic_accounting.TotalProcesses,
2473 "Expected basic_accounting.TotalProcesses to be %d (total_proc) is %d\n",
2474 total_proc, basic_accounting.TotalProcesses);
2475 todo_wine_if(active_proc)
2476 ok_(__FILE__, line)(active_proc == basic_accounting.ActiveProcesses,
2477 "Expected basic_accounting.ActiveProcesses to be %d (active_proc) is %d\n",
2478 active_proc, basic_accounting.ActiveProcesses);
2479 ok_(__FILE__, line)(terminated_proc == basic_accounting.TotalTerminatedProcesses,
2480 "Expected basic_accounting.TotalTerminatedProcesses to be %d (terminated_proc) is %d\n",
2481 terminated_proc, basic_accounting.TotalTerminatedProcesses);
2482 }
2483}
2484
2485static void test_IsProcessInJob(void)
2486{
2487 HANDLE job, job2;
2489 BOOL ret, out;
2490 DWORD dwret;
2491
2492 if (!pIsProcessInJob)
2493 {
2494 win_skip("IsProcessInJob not available.\n");
2495 return;
2496 }
2497
2498 job = pCreateJobObjectW(NULL, NULL);
2499 ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
2500
2501 job2 = pCreateJobObjectW(NULL, NULL);
2502 ok(job2 != NULL, "CreateJobObject error %u\n", GetLastError());
2503
2504 create_process("wait", &pi);
2505
2506 out = TRUE;
2507 ret = pIsProcessInJob(pi.hProcess, job, &out);
2508 ok(ret, "IsProcessInJob error %u\n", GetLastError());
2509 ok(!out, "IsProcessInJob returned out=%u\n", out);
2511 test_accounting(job, 0, 0, 0);
2512
2513 out = TRUE;
2514 ret = pIsProcessInJob(pi.hProcess, job2, &out);
2515 ok(ret, "IsProcessInJob error %u\n", GetLastError());
2516 ok(!out, "IsProcessInJob returned out=%u\n", out);
2517 test_assigned_proc(job2, 0);
2518 test_accounting(job2, 0, 0, 0);
2519
2520 out = TRUE;
2521 ret = pIsProcessInJob(pi.hProcess, NULL, &out);
2522 ok(ret, "IsProcessInJob error %u\n", GetLastError());
2523 ok(!out, "IsProcessInJob returned out=%u\n", out);
2524
2525 ret = pAssignProcessToJobObject(job, pi.hProcess);
2526 ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
2527
2528 out = FALSE;
2529 ret = pIsProcessInJob(pi.hProcess, job, &out);
2530 ok(ret, "IsProcessInJob error %u\n", GetLastError());
2531 ok(out, "IsProcessInJob returned out=%u\n", out);
2532 test_assigned_proc(job, 1, pi.dwProcessId);
2533 test_accounting(job, 1, 1, 0);
2534
2535 out = TRUE;
2536 ret = pIsProcessInJob(pi.hProcess, job2, &out);
2537 ok(ret, "IsProcessInJob error %u\n", GetLastError());
2538 ok(!out, "IsProcessInJob returned out=%u\n", out);
2539 test_assigned_proc(job2, 0);
2540 test_accounting(job2, 0, 0, 0);
2541
2542 out = FALSE;
2543 ret = pIsProcessInJob(pi.hProcess, NULL, &out);
2544 ok(ret, "IsProcessInJob error %u\n", GetLastError());
2545 ok(out, "IsProcessInJob returned out=%u\n", out);
2546
2547 TerminateProcess(pi.hProcess, 0);
2548
2549 dwret = WaitForSingleObject(pi.hProcess, 1000);
2550 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
2551
2552 out = FALSE;
2553 ret = pIsProcessInJob(pi.hProcess, job, &out);
2554 ok(ret, "IsProcessInJob error %u\n", GetLastError());
2555 ok(out, "IsProcessInJob returned out=%u\n", out);
2557 test_accounting(job, 1, 0, 0);
2558
2559 CloseHandle(pi.hProcess);
2560 CloseHandle(pi.hThread);
2562 CloseHandle(job2);
2563}
2564
2566{
2567 HANDLE job;
2569 BOOL ret;
2570 DWORD dwret;
2571
2572 job = pCreateJobObjectW(NULL, NULL);
2573 ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
2575 test_accounting(job, 0, 0, 0);
2576
2577 create_process("wait", &pi);
2578
2579 ret = pAssignProcessToJobObject(job, pi.hProcess);
2580 ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
2581 test_assigned_proc(job, 1, pi.dwProcessId);
2582 test_accounting(job, 1, 1, 0);
2583
2584 ret = pTerminateJobObject(job, 123);
2585 ok(ret, "TerminateJobObject error %u\n", GetLastError());
2586
2587 dwret = WaitForSingleObject(pi.hProcess, 1000);
2588 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
2589 if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0);
2591 test_accounting(job, 1, 0, 0);
2592
2593 ret = GetExitCodeProcess(pi.hProcess, &dwret);
2594 ok(ret, "GetExitCodeProcess error %u\n", GetLastError());
2595 ok(dwret == 123 || broken(dwret == 0) || broken(dwret == 259) /* randomly fails on Win 2000 / XP */,
2596 "wrong exitcode %u\n", dwret);
2597
2598 CloseHandle(pi.hProcess);
2599 CloseHandle(pi.hThread);
2600
2601 /* Test adding an already terminated process to a job object */
2602 create_process("exit", &pi);
2603
2604 dwret = WaitForSingleObject(pi.hProcess, 1000);
2605 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
2606
2607 SetLastError(0xdeadbeef);
2608 ret = pAssignProcessToJobObject(job, pi.hProcess);
2609 ok(!ret, "AssignProcessToJobObject unexpectedly succeeded\n");
2612 test_accounting(job, 1, 0, 0);
2613
2614 CloseHandle(pi.hProcess);
2615 CloseHandle(pi.hThread);
2616
2618}
2619
2621{
2622 char buf[sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + sizeof(ULONG_PTR) * 4];
2625 JOBOBJECT_BASIC_LIMIT_INFORMATION *basic_limit_info = &ext_limit_info.BasicLimitInformation;
2626 DWORD dwret, ret_len;
2628 HANDLE job;
2629 BOOL ret;
2630
2631 job = pCreateJobObjectW(NULL, NULL);
2632 ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
2633
2634 /* Only active processes are returned */
2635 create_process("exit", &pi[0]);
2636 ret = pAssignProcessToJobObject(job, pi[0].hProcess);
2637 ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
2638 dwret = WaitForSingleObject(pi[0].hProcess, 1000);
2639 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
2640
2643
2644 create_process("wait", &pi[0]);
2645 ret = pAssignProcessToJobObject(job, pi[0].hProcess);
2646 ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
2647
2648 create_process("wait", &pi[1]);
2649 ret = pAssignProcessToJobObject(job, pi[1].hProcess);
2650 ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
2651
2652 SetLastError(0xdeadbeef);
2655 ok(!ret, "QueryInformationJobObject expected failure\n");
2657
2658 SetLastError(0xdeadbeef);
2659 memset(buf, 0, sizeof(buf));
2660 pid_list->NumberOfAssignedProcesses = 42;
2661 pid_list->NumberOfProcessIdsInList = 42;
2664 todo_wine
2665 ok(!ret, "QueryInformationJobObject expected failure\n");
2666 todo_wine
2668 if (ret)
2669 {
2670 todo_wine
2672 todo_wine
2674 }
2675
2676 memset(buf, 0, sizeof(buf));
2677 ret = pQueryInformationJobObject(job, JobObjectBasicProcessIdList, pid_list, sizeof(buf), &ret_len);
2678 ok(ret, "QueryInformationJobObject error %u\n", GetLastError());
2679 if(ret)
2680 {
2681 if (pid_list->NumberOfAssignedProcesses == 3) /* Win 8 */
2682 win_skip("Number of assigned processes broken on Win 8\n");
2683 else
2684 {
2685 ULONG_PTR *list = pid_list->ProcessIdList;
2686
2687 todo_wine
2689 "QueryInformationJobObject returned ret_len=%u\n", ret_len);
2690
2691 todo_wine
2693 todo_wine
2695 todo_wine
2696 expect_eq_d(pi[0].dwProcessId, list[0]);
2697 todo_wine
2698 expect_eq_d(pi[1].dwProcessId, list[1]);
2699 }
2700 }
2701
2702 /* test JobObjectBasicLimitInformation */
2703 ret = pQueryInformationJobObject(job, JobObjectBasicLimitInformation, basic_limit_info,
2704 sizeof(*basic_limit_info) - 1, &ret_len);
2705 ok(!ret, "QueryInformationJobObject expected failure\n");
2707
2708 ret_len = 0xdeadbeef;
2709 memset(basic_limit_info, 0x11, sizeof(*basic_limit_info));
2710 ret = pQueryInformationJobObject(job, JobObjectBasicLimitInformation, basic_limit_info,
2711 sizeof(*basic_limit_info), &ret_len);
2712 ok(ret, "QueryInformationJobObject error %u\n", GetLastError());
2713 ok(ret_len == sizeof(*basic_limit_info), "QueryInformationJobObject returned ret_len=%u\n", ret_len);
2714 expect_eq_d(0, basic_limit_info->LimitFlags);
2715
2716 /* test JobObjectExtendedLimitInformation */
2717 ret = pQueryInformationJobObject(job, JobObjectExtendedLimitInformation, &ext_limit_info,
2718 sizeof(ext_limit_info) - 1, &ret_len);
2719 ok(!ret, "QueryInformationJobObject expected failure\n");
2721
2722 ret_len = 0xdeadbeef;
2723 memset(&ext_limit_info, 0x11, sizeof(ext_limit_info));
2724 ret = pQueryInformationJobObject(job, JobObjectExtendedLimitInformation, &ext_limit_info,
2725 sizeof(ext_limit_info), &ret_len);
2726 ok(ret, "QueryInformationJobObject error %u\n", GetLastError());
2727 ok(ret_len == sizeof(ext_limit_info), "QueryInformationJobObject returned ret_len=%u\n", ret_len);
2728 expect_eq_d(0, basic_limit_info->LimitFlags);
2729
2733
2737
2739}
2740
2741static void test_CompletionPort(void)
2742{
2745 HANDLE job, port;
2746 DWORD dwret;
2747 BOOL ret;
2748
2749 job = pCreateJobObjectW(NULL, NULL);
2750 ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
2751
2752 port = pCreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
2753 ok(port != NULL, "CreateIoCompletionPort error %u\n", GetLastError());
2754
2755 port_info.CompletionKey = job;
2756 port_info.CompletionPort = port;
2757 ret = pSetInformationJobObject(job, JobObjectAssociateCompletionPortInformation, &port_info, sizeof(port_info));
2758 ok(ret, "SetInformationJobObject error %u\n", GetLastError());
2759
2760 create_process("wait", &pi);
2761
2762 ret = pAssignProcessToJobObject(job, pi.hProcess);
2763 ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
2764
2766
2767 TerminateProcess(pi.hProcess, 0);
2768 dwret = WaitForSingleObject(pi.hProcess, 1000);
2769 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
2770
2773
2774 CloseHandle(pi.hProcess);
2775 CloseHandle(pi.hThread);
2778}
2779
2780static void test_KillOnJobClose(void)
2781{
2784 DWORD dwret;
2785 HANDLE job;
2786 BOOL ret;
2787
2788 job = pCreateJobObjectW(NULL, NULL);
2789 ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
2790
2792 ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
2794 {
2795 win_skip("Kill on job close limit not available\n");
2796 return;
2797 }
2798 ok(ret, "SetInformationJobObject error %u\n", GetLastError());
2800 test_accounting(job, 0, 0, 0);
2801
2802 create_process("wait", &pi);
2803
2804 ret = pAssignProcessToJobObject(job, pi.hProcess);
2805 ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
2806 test_assigned_proc(job, 1, pi.dwProcessId);
2807 test_accounting(job, 1, 1, 0);
2808
2810
2811 dwret = WaitForSingleObject(pi.hProcess, 1000);
2812 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
2813 if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0);
2814
2815 CloseHandle(pi.hProcess);
2816 CloseHandle(pi.hThread);
2817}
2818
2819static void test_WaitForJobObject(void)
2820{
2821 HANDLE job;
2823 BOOL ret;
2824 DWORD dwret;
2825
2826 /* test waiting for a job object when the process is killed */
2827 job = pCreateJobObjectW(NULL, NULL);
2828 ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
2829
2830 dwret = WaitForSingleObject(job, 100);
2831 ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", dwret);
2832
2833 create_process("wait", &pi);
2834
2835 ret = pAssignProcessToJobObject(job, pi.hProcess);
2836 ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
2837
2838 dwret = WaitForSingleObject(job, 100);
2839 ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", dwret);
2840
2841 ret = pTerminateJobObject(job, 123);
2842 ok(ret, "TerminateJobObject error %u\n", GetLastError());
2843
2844 dwret = WaitForSingleObject(job, 500);
2845 ok(dwret == WAIT_OBJECT_0 || broken(dwret == WAIT_TIMEOUT),
2846 "WaitForSingleObject returned %u\n", dwret);
2847
2848 if (dwret == WAIT_TIMEOUT) /* Win 2000/XP */
2849 {
2850#ifdef __REACTOS__
2851 if (!ret)
2852 {
2853 ok(0, "HACK: Killing process to speed up the test\n");
2854 TerminateProcess(pi.hProcess, 0);
2855 }
2856#endif
2857 CloseHandle(pi.hProcess);
2858 CloseHandle(pi.hThread);
2860 win_skip("TerminateJobObject doesn't signal job, skipping tests\n");
2861 return;
2862 }
2863
2864 /* the object is not reset immediately */
2865 dwret = WaitForSingleObject(job, 100);
2866 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
2867
2868 CloseHandle(pi.hProcess);
2869 CloseHandle(pi.hThread);
2870
2871 /* creating a new process doesn't reset the signalled state */
2872 create_process("wait", &pi);
2873
2874 ret = pAssignProcessToJobObject(job, pi.hProcess);
2875 ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
2876
2877 dwret = WaitForSingleObject(job, 100);
2878 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
2879
2880 ret = pTerminateJobObject(job, 123);
2881 ok(ret, "TerminateJobObject error %u\n", GetLastError());
2882
2883 CloseHandle(pi.hProcess);
2884 CloseHandle(pi.hThread);
2885
2887
2888 /* repeat the test, but this time the process terminates properly */
2889 job = pCreateJobObjectW(NULL, NULL);
2890 ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
2891
2892 dwret = WaitForSingleObject(job, 100);
2893 ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", dwret);
2894
2895 create_process("exit", &pi);
2896
2897 ret = pAssignProcessToJobObject(job, pi.hProcess);
2898 ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
2899
2900 dwret = WaitForSingleObject(job, 100);
2901 ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", dwret);
2902
2903 CloseHandle(pi.hProcess);
2904 CloseHandle(pi.hThread);
2906}
2907
2909{
2910 HANDLE job;
2911 BOOL ret;
2912
2913 job = pCreateJobObjectW(NULL, NULL);
2914 ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
2915
2916 ret = pAssignProcessToJobObject(job, GetCurrentProcess());
2917 ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
2919 test_accounting(job, 1, 1, 0);
2920
2921 return job;
2922}
2923
2925{
2926 char buffer[MAX_PATH];
2928 STARTUPINFOA si = {0};
2929 DWORD dwret;
2930 BOOL ret, out;
2931
2932 if (!pIsProcessInJob)
2933 {
2934 win_skip("IsProcessInJob not available.\n");
2935 return;
2936 }
2937
2938 sprintf(buffer, "\"%s\" tests/process.c %s", selfname, "exit");
2939
2940 ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2941 ok(ret, "CreateProcessA error %u\n", GetLastError());
2942
2943 out = FALSE;
2944 ret = pIsProcessInJob(pi.hProcess, job, &out);
2945 ok(ret, "IsProcessInJob error %u\n", GetLastError());
2946 ok(out, "IsProcessInJob returned out=%u\n", out);
2947 test_assigned_proc(job, 2, GetCurrentProcessId(), pi.dwProcessId);
2948 test_accounting(job, 2, 2, 0);
2949
2950 dwret = WaitForSingleObject(pi.hProcess, 1000);
2951 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
2952
2953 CloseHandle(pi.hProcess);
2954 CloseHandle(pi.hThread);
2955}
2956
2958{
2961 STARTUPINFOA si = {0};
2962 char buffer[MAX_PATH];
2963 BOOL ret, out;
2964 DWORD dwret;
2965
2966 if (!pIsProcessInJob)
2967 {
2968 win_skip("IsProcessInJob not available.\n");
2969 return;
2970 }
2971
2972 sprintf(buffer, "\"%s\" tests/process.c %s", selfname, "exit");
2973
2975 ok(!ret, "CreateProcessA expected failure\n");
2978 test_accounting(job, 2, 1, 0);
2979
2980 if (ret)
2981 {
2982 TerminateProcess(pi.hProcess, 0);
2983
2984 dwret = WaitForSingleObject(pi.hProcess, 1000);
2985 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
2986
2987 CloseHandle(pi.hProcess);
2988 CloseHandle(pi.hThread);
2989 }
2990
2992 ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
2993 ok(ret, "SetInformationJobObject error %u\n", GetLastError());
2994
2996 ok(ret, "CreateProcessA error %u\n", GetLastError());
2997
2998 ret = pIsProcessInJob(pi.hProcess, job, &out);
2999 ok(ret, "IsProcessInJob error %u\n", GetLastError());
3000 ok(!out, "IsProcessInJob returned out=%u\n", out);
3002 test_accounting(job, 2, 1, 0);
3003
3004 dwret = WaitForSingleObject(pi.hProcess, 1000);
3005 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
3006
3007 CloseHandle(pi.hProcess);
3008 CloseHandle(pi.hThread);
3009
3011 ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
3012 ok(ret, "SetInformationJobObject error %u\n", GetLastError());
3013
3014 ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
3015 ok(ret, "CreateProcess error %u\n", GetLastError());
3016
3017 ret = pIsProcessInJob(pi.hProcess, job, &out);
3018 ok(ret, "IsProcessInJob error %u\n", GetLastError());
3019 ok(!out, "IsProcessInJob returned out=%u\n", out);
3021 test_accounting(job, 2, 1, 0);
3022
3023 dwret = WaitForSingleObject(pi.hProcess, 1000);
3024 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
3025
3026 CloseHandle(pi.hProcess);
3027 CloseHandle(pi.hThread);
3028
3029 /* unset breakaway ok */
3030 limit_info.BasicLimitInformation.LimitFlags = 0;
3031 ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
3032 ok(ret, "SetInformationJobObject error %u\n", GetLastError());
3033}
3034
3035static void test_StartupNoConsole(void)
3036{
3037#ifndef _WIN64
3038 char buffer[MAX_PATH];
3041
3042 memset(&startup, 0, sizeof(startup));
3043 startup.cb = sizeof(startup);
3044 startup.dwFlags = STARTF_USESHOWWINDOW;
3045 startup.wShowWindow = SW_SHOWNORMAL;
3047 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
3049 &info), "CreateProcess\n");
3050 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
3052 okChildInt("StartupInfoA", "hStdInput", (UINT)INVALID_HANDLE_VALUE);
3053 okChildInt("StartupInfoA", "hStdOutput", (UINT)INVALID_HANDLE_VALUE);
3054 okChildInt("StartupInfoA", "hStdError", (UINT)INVALID_HANDLE_VALUE);
3055 okChildInt("TEB", "hStdInput", 0);
3056 okChildInt("TEB", "hStdOutput", 0);
3057 okChildInt("TEB", "hStdError", 0);
3060#endif
3061}
3062
3064{
3065#ifndef _WIN64
3066 char buffer[MAX_PATH];
3069 UINT result;
3070
3071 memset(&startup, 0, sizeof(startup));
3072 startup.cb = sizeof(startup);
3074 startup.wShowWindow = SW_SHOWNORMAL;
3079 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
3081 &info), "CreateProcess\n");
3082 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
3084
3085 result = GetPrivateProfileIntA("StartupInfoA", "hStdInput", 0, resfile);
3086 ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
3087 result = GetPrivateProfileIntA("StartupInfoA", "hStdOutput", 0, resfile);
3088 ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
3089 result = GetPrivateProfileIntA("StartupInfoA", "hStdError", 0, resfile);
3090 ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
3091 result = GetPrivateProfileIntA("TEB", "hStdInput", 0, resfile);
3092 ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
3093 result = GetPrivateProfileIntA("TEB", "hStdOutput", 0, resfile);
3094 ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
3095 result = GetPrivateProfileIntA("TEB", "hStdError", 0, resfile);
3096 ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
3097
3100#endif
3101}
3102
3103#if defined(__i386__) || defined(__x86_64__)
3104static BOOL read_nt_header(HANDLE process_handle, MEMORY_BASIC_INFORMATION *mbi,
3106{
3108
3109 if (!ReadProcessMemory(process_handle, mbi->BaseAddress, &dos_header, sizeof(dos_header), NULL))
3110 return FALSE;
3111
3113 ((ULONG)dos_header.e_lfanew > mbi->RegionSize) ||
3114 (dos_header.e_lfanew < sizeof(dos_header)))
3115 return FALSE;
3116
3117 if (!ReadProcessMemory(process_handle, (char *)mbi->BaseAddress + dos_header.e_lfanew,
3118 nt_header, sizeof(*nt_header), NULL))
3119 return FALSE;
3120
3122}
3123
3124static PVOID get_process_exe(HANDLE process_handle, IMAGE_NT_HEADERS *nt_header)
3125{
3126 PVOID exe_base, address;
3128
3129 /* Find the EXE base in the new process */
3130 exe_base = NULL;
3131 for (address = NULL ;
3132 VirtualQueryEx(process_handle, address, &mbi, sizeof(mbi)) ;
3133 address = (char *)mbi.BaseAddress + mbi.RegionSize) {
3134 if ((mbi.Type == SEC_IMAGE) &&
3135 read_nt_header(process_handle, &mbi, nt_header) &&
3137 exe_base = mbi.BaseAddress;
3138 break;
3139 }
3140 }
3141
3142 return exe_base;
3143}
3144
3145static BOOL are_imports_resolved(HANDLE process_handle, PVOID module_base, IMAGE_NT_HEADERS *nt_header)
3146{
3147 BOOL ret;
3149 ULONG_PTR orig_iat_entry_value, iat_entry_value;
3150
3153
3156 return FALSE;
3157
3158 /* Read the first IID */
3159 ret = ReadProcessMemory(process_handle,
3161 &iid, sizeof(iid), NULL);
3162 ok(ret, "Failed to read remote module IID (%d)\n", GetLastError());
3163
3164 /* Validate the IID is present and not a bound import, and that we have
3165 an OriginalFirstThunk to compare with */
3166 ok(iid.Name, "Module first IID does not have a Name\n");
3167 ok(iid.FirstThunk, "Module first IID does not have a FirstThunk\n");
3168 ok(!iid.TimeDateStamp, "Module first IID is a bound import (UNSUPPORTED for current test)\n");
3169 ok(iid.OriginalFirstThunk, "Module first IID does not have an OriginalFirstThunk (UNSUPPORTED for current test)\n");
3170
3171 /* Read a single IAT entry from the FirstThunk */
3172 ret = ReadProcessMemory(process_handle, (char *)module_base + iid.FirstThunk,
3173 &iat_entry_value, sizeof(iat_entry_value), NULL);
3174 ok(ret, "Failed to read IAT entry from FirstThunk (%d)\n", GetLastError());
3175 ok(iat_entry_value, "IAT entry in FirstThunk is NULL\n");
3176
3177 /* Read a single IAT entry from the OriginalFirstThunk */
3178 ret = ReadProcessMemory(process_handle, (char *)module_base + iid.OriginalFirstThunk,
3179 &orig_iat_entry_value, sizeof(orig_iat_entry_value), NULL);
3180 ok(ret, "Failed to read IAT entry from OriginalFirstThunk (%d)\n", GetLastError());
3181 ok(orig_iat_entry_value, "IAT entry in OriginalFirstThunk is NULL\n");
3182
3183 return iat_entry_value != orig_iat_entry_value;
3184}
3185
3186static void test_SuspendProcessNewThread(void)
3187{
3188 BOOL ret;
3189 STARTUPINFOA si = {0};
3190 PROCESS_INFORMATION pi = {0};
3191 PVOID exe_base, exit_thread_ptr;
3193 HANDLE thread_handle = NULL;
3194 DWORD dret, exit_code = 0;
3195 CONTEXT ctx;
3196
3197 exit_thread_ptr = GetProcAddress(hkernel32, "ExitThread");
3198 ok(exit_thread_ptr != NULL, "GetProcAddress ExitThread failed\n");
3199
3200 si.cb = sizeof(si);
3202 ok(ret, "Failed to create process (%d)\n", GetLastError());
3203
3204 exe_base = get_process_exe(pi.hProcess, &nt_header);
3205 ok(exe_base != NULL, "Could not find EXE in remote process\n");
3206
3207 ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
3208 ok(!ret, "IAT entry resolved prematurely\n");
3209
3210 thread_handle = CreateRemoteThread(pi.hProcess, NULL, 0,
3211 (LPTHREAD_START_ROUTINE)exit_thread_ptr,
3213 ok(thread_handle != NULL, "Could not create remote thread (%d)\n", GetLastError());
3214
3215 ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
3216 ok(!ret, "IAT entry resolved prematurely\n");
3217
3218 ctx.ContextFlags = CONTEXT_ALL;
3219 ret = GetThreadContext( thread_handle, &ctx );
3220 ok( ret, "Failed retrieving remote thread context (%d)\n", GetLastError() );
3221 ok( ctx.ContextFlags == CONTEXT_ALL, "wrong flags %x\n", ctx.ContextFlags );
3222#ifdef __x86_64__
3223 ok( !ctx.Rax, "rax is not zero %lx\n", ctx.Rax );
3224 ok( !ctx.Rbx, "rbx is not zero %lx\n", ctx.Rbx );
3225 ok( ctx.Rcx == (ULONG_PTR)exit_thread_ptr, "wrong rcx %lx/%p\n", ctx.Rcx, exit_thread_ptr );
3226 ok( ctx.Rdx == 0x1234, "wrong rdx %lx\n", ctx.Rdx );
3227 ok( !ctx.Rsi, "rsi is not zero %lx\n", ctx.Rsi );
3228 ok( !ctx.Rdi, "rdi is not zero %lx\n", ctx.Rdi );
3229 ok( !ctx.Rbp, "rbp is not zero %lx\n", ctx.Rbp );
3230 ok( !ctx.R8, "r8 is not zero %lx\n", ctx.R8 );
3231 ok( !ctx.R9, "r9 is not zero %lx\n", ctx.R9 );
3232 ok( !ctx.R10, "r10 is not zero %lx\n", ctx.R10 );
3233 ok( !ctx.R11, "r11 is not zero %lx\n", ctx.R11 );
3234 ok( !ctx.R12, "r12 is not zero %lx\n", ctx.R12 );
3235 ok( !ctx.R13, "r13 is not zero %lx\n", ctx.R13 );
3236 ok( !ctx.R14, "r14 is not zero %lx\n", ctx.R14 );
3237 ok( !ctx.R15, "r15 is not zero %lx\n", ctx.R15 );
3238 ok( !((ctx.Rsp + 0x28) & 0xfff), "rsp is not at top of stack page %lx\n", ctx.Rsp );
3239 ok( ctx.EFlags == 0x200, "wrong flags %08x\n", ctx.EFlags );
3240 ok( ctx.MxCsr == 0x1f80, "wrong mxcsr %08x\n", ctx.MxCsr );
3241 ok( ctx.FltSave.ControlWord == 0x27f, "wrong control %08x\n", ctx.FltSave.ControlWord );
3242#else
3243 ok( !ctx.Ebp || broken(ctx.Ebp), /* winxp */ "ebp is not zero %08x\n", ctx.Ebp );
3244 if (!ctx.Ebp) /* winxp is completely different */
3245 {
3246 ok( !ctx.Ecx, "ecx is not zero %08x\n", ctx.Ecx );
3247 ok( !ctx.Edx, "edx is not zero %08x\n", ctx.Edx );
3248 ok( !ctx.Esi, "esi is not zero %08x\n", ctx.Esi );
3249 ok( !ctx.Edi, "edi is not zero %08x\n", ctx.Edi );
3250 }
3251 ok( ctx.Eax == (ULONG_PTR)exit_thread_ptr, "wrong eax %08x/%p\n", ctx.Eax, exit_thread_ptr );
3252 ok( ctx.Ebx == 0x1234, "wrong ebx %08x\n", ctx.Ebx );
3253 ok( !((ctx.Esp + 0x10) & 0xfff) || broken( !((ctx.Esp + 4) & 0xfff) ), /* winxp, w2k3 */
3254 "esp is not at top of stack page or properly aligned: %08x\n", ctx.Esp );
3255 ok( (ctx.EFlags & ~2) == 0x200, "wrong flags %08x\n", ctx.EFlags );
3256 ok( (WORD)ctx.FloatSave.ControlWord == 0x27f, "wrong control %08x\n", ctx.FloatSave.ControlWord );
3257 ok( *(WORD *)ctx.ExtendedRegisters == 0x27f, "wrong control %08x\n", *(WORD *)ctx.ExtendedRegisters );
3258#endif
3259
3260 ResumeThread( thread_handle );
3261 dret = WaitForSingleObject(thread_handle, 60000);
3262 ok(dret == WAIT_OBJECT_0, "Waiting for remote thread failed (%d)\n", GetLastError());
3263 ret = GetExitCodeThread(thread_handle, &exit_code);
3264 ok(ret, "Failed to retrieve remote thread exit code (%d)\n", GetLastError());
3265 ok(exit_code == 0x1234, "Invalid remote thread exit code\n");
3266
3267 ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
3268 ok(ret, "EXE IAT entry not resolved\n");
3269
3270 if (thread_handle)
3271 CloseHandle(thread_handle);
3272
3273 TerminateProcess(pi.hProcess, 0);
3274 WaitForSingleObject(pi.hProcess, 10000);
3275 CloseHandle(pi.hProcess);
3276 CloseHandle(pi.hThread);
3277}
3278
3279static void test_SuspendProcessState(void)
3280{
3281 struct pipe_params
3282 {
3283 ULONG pipe_write_buf;
3284 ULONG pipe_read_buf;
3285 ULONG bytes_returned;
3286 CHAR pipe_name[MAX_PATH];
3287 };
3288
3289#ifdef __x86_64__
3290 struct remote_rop_chain
3291 {
3292 void *exit_process_ptr;
3293 ULONG_PTR home_rcx;
3294 ULONG_PTR home_rdx;
3295 ULONG_PTR home_r8;
3296 ULONG_PTR home_r9;
3297 ULONG_PTR pipe_read_buf_size;
3298 ULONG_PTR bytes_returned;
3300 };
3301#else
3302 struct remote_rop_chain
3303 {
3304 void *exit_process_ptr;
3305 ULONG_PTR pipe_name;
3306 ULONG_PTR pipe_write_buf;
3307 ULONG_PTR pipe_write_buf_size;
3308 ULONG_PTR pipe_read_buf;
3309 ULONG_PTR pipe_read_buf_size;
3310 ULONG_PTR bytes_returned;
3312 void *unreached_ret;
3314 };
3315#endif
3316
3317 static const char pipe_name[] = "\\\\.\\pipe\\TestPipe";
3318 static const ULONG pipe_write_magic = 0x454e4957;
3319 STARTUPINFOA si = {0};
3320 PROCESS_INFORMATION pi = {0};
3321 PVOID exe_base, remote_pipe_params, exit_process_ptr,
3322 call_named_pipe_a;
3324 struct pipe_params pipe_params;
3325 struct remote_rop_chain rop_chain;
3326 CONTEXT ctx;
3327 HANDLE server_pipe_handle;
3328 BOOL pipe_connected;
3329 ULONG pipe_magic, numb;
3330 BOOL ret;
3331 void *entry_ptr, *peb_ptr;
3332 PEB child_peb;
3333
3334 exit_process_ptr = GetProcAddress(hkernel32, "ExitProcess");
3335 ok(exit_process_ptr != NULL, "GetProcAddress ExitProcess failed\n");
3336
3337 call_named_pipe_a = GetProcAddress(hkernel32, "CallNamedPipeA");
3338 ok(call_named_pipe_a != NULL, "GetProcAddress CallNamedPipeA failed\n");
3339
3340 si.cb = sizeof(si);
3342 ok(ret, "Failed to create process (%d)\n", GetLastError());
3343
3344 exe_base = get_process_exe(pi.hProcess, &nt_header);
3345 /* Make sure we found the EXE in the new process */
3346 ok(exe_base != NULL, "Could not find EXE in remote process\n");
3347
3348 ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
3349 ok(!ret, "IAT entry resolved prematurely\n");
3350
3351 server_pipe_handle = CreateNamedPipeA(pipe_name, PIPE_ACCESS_DUPLEX | FILE_FLAG_WRITE_THROUGH,
3352 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0x20000, 0x20000,
3353 0, NULL);
3354 ok(server_pipe_handle != INVALID_HANDLE_VALUE, "Failed to create communication pipe (%d)\n", GetLastError());
3355
3356 /* Set up the remote process environment */
3357 ctx.ContextFlags = CONTEXT_ALL;
3358 ret = GetThreadContext(pi.hThread, &ctx);
3359 ok(ret, "Failed retrieving remote thread context (%d)\n", GetLastError());
3360 ok( ctx.ContextFlags == CONTEXT_ALL, "wrong flags %x\n", ctx.ContextFlags );
3361
3362 remote_pipe_params = VirtualAllocEx(pi.hProcess, NULL, sizeof(pipe_params), MEM_COMMIT, PAGE_READWRITE);
3363 ok(remote_pipe_params != NULL, "Failed allocating memory in remote process (%d)\n", GetLastError());
3364
3365 pipe_params.pipe_write_buf = pipe_write_magic;
3366 pipe_params.pipe_read_buf = 0;
3367 pipe_params.bytes_returned = 0;
3368 strcpy(pipe_params.pipe_name, pipe_name);
3369
3370 ret = WriteProcessMemory(pi.hProcess, remote_pipe_params,
3371 &pipe_params, sizeof(pipe_params), NULL);
3372 ok(ret, "Failed to write to remote process memory (%d)\n", GetLastError());
3373
3374#ifdef __x86_64__
3375 ok( !ctx.Rax, "rax is not zero %lx\n", ctx.Rax );
3376 ok( !ctx.Rbx, "rbx is not zero %lx\n", ctx.Rbx );
3377 ok( !ctx.Rsi, "rsi is not zero %lx\n", ctx.Rsi );
3378 ok( !ctx.Rdi, "rdi is not zero %lx\n", ctx.Rdi );
3379 ok( !ctx.Rbp, "rbp is not zero %lx\n", ctx.Rbp );
3380 ok( !ctx.R8, "r8 is not zero %lx\n", ctx.R8 );
3381 ok( !ctx.R9, "r9 is not zero %lx\n", ctx.R9 );
3382 ok( !ctx.R10, "r10 is not zero %lx\n", ctx.R10 );
3383 ok( !ctx.R11, "r11 is not zero %lx\n", ctx.R11 );
3384 ok( !ctx.R12, "r12 is not zero %lx\n", ctx.R12 );
3385 ok( !ctx.R13, "r13 is not zero %lx\n", ctx.R13 );
3386 ok( !ctx.R14, "r14 is not zero %lx\n", ctx.R14 );
3387 ok( !ctx.R15, "r15 is not zero %lx\n", ctx.R15 );
3388 ok( !((ctx.Rsp + 0x28) & 0xfff), "rsp is not at top of stack page %lx\n", ctx.Rsp );
3389 ok( ctx.EFlags == 0x200, "wrong flags %08x\n", ctx.EFlags );
3390 ok( ctx.MxCsr == 0x1f80, "wrong mxcsr %08x\n", ctx.MxCsr );
3391 ok( ctx.FltSave.ControlWord == 0x27f, "wrong control %08x\n", ctx.FltSave.ControlWord );
3392 entry_ptr = (void *)ctx.Rcx;
3393 peb_ptr = (void *)ctx.Rdx;
3394
3395 rop_chain.exit_process_ptr = exit_process_ptr;
3396 ctx.Rcx = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_name);
3397 ctx.Rdx = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_write_buf);
3398 ctx.R8 = sizeof(pipe_params.pipe_write_buf);
3399 ctx.R9 = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_read_buf);
3400 rop_chain.pipe_read_buf_size = sizeof(pipe_params.pipe_read_buf);
3401 rop_chain.bytes_returned = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, bytes_returned);
3402 rop_chain.timeout = 10000;
3403
3404 ctx.Rip = (ULONG_PTR)call_named_pipe_a;
3405 ctx.Rsp -= sizeof(rop_chain);
3406 ret = WriteProcessMemory(pi.hProcess, (void *)ctx.Rsp, &rop_chain, sizeof(rop_chain), NULL);
3407 ok(ret, "Failed to write to remote process thread stack (%d)\n", GetLastError());
3408#else
3409 ok( !ctx.Ebp || broken(ctx.Ebp), /* winxp */ "ebp is not zero %08x\n", ctx.Ebp );
3410 if (!ctx.Ebp) /* winxp is completely different */
3411 {
3412 ok( !ctx.Ecx, "ecx is not zero %08x\n", ctx.Ecx );
3413 ok( !ctx.Edx, "edx is not zero %08x\n", ctx.Edx );
3414 ok( !ctx.Esi, "esi is not zero %08x\n", ctx.Esi );
3415 ok( !ctx.Edi, "edi is not zero %08x\n", ctx.Edi );
3416 }
3417 ok( !((ctx.Esp + 0x10) & 0xfff) || broken( !((ctx.Esp + 4) & 0xfff) ), /* winxp, w2k3 */
3418 "esp is not at top of stack page or properly aligned: %08x\n", ctx.Esp );
3419 ok( (ctx.EFlags & ~2) == 0x200, "wrong flags %08x\n", ctx.EFlags );
3420 ok( (WORD)ctx.FloatSave.ControlWord == 0x27f, "wrong control %08x\n", ctx.FloatSave.ControlWord );
3421 ok( *(WORD *)ctx.ExtendedRegisters == 0x27f, "wrong control %08x\n", *(WORD *)ctx.ExtendedRegisters );
3422 entry_ptr = (void *)ctx.Eax;
3423 peb_ptr = (void *)ctx.Ebx;
3424
3425 rop_chain.exit_process_ptr = exit_process_ptr;
3426 rop_chain.pipe_name = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_name);
3427 rop_chain.pipe_write_buf = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_write_buf);
3428 rop_chain.pipe_write_buf_size = sizeof(pipe_params.pipe_write_buf);
3429 rop_chain.pipe_read_buf = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_read_buf);
3430 rop_chain.pipe_read_buf_size = sizeof(pipe_params.pipe_read_buf);
3431 rop_chain.bytes_returned = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, bytes_returned);
3432 rop_chain.timeout = 10000;
3433 rop_chain.exit_code = 0;
3434
3435 ctx.Eip = (ULONG_PTR)call_named_pipe_a;
3436 ctx.Esp -= sizeof(rop_chain);
3437 ret = WriteProcessMemory(pi.hProcess, (void *)ctx.Esp, &rop_chain, sizeof(rop_chain), NULL);
3438 ok(ret, "Failed to write to remote process thread stack (%d)\n", GetLastError());
3439#endif
3440
3441 ret = ReadProcessMemory( pi.hProcess, peb_ptr, &child_peb, sizeof(child_peb), NULL );
3442 ok( ret, "Failed to read PEB (%u)\n", GetLastError() );
3443 ok( child_peb.ImageBaseAddress == exe_base, "wrong base %p/%p\n",
3444 child_peb.ImageBaseAddress, exe_base );
3445 ok( entry_ptr == (char *)exe_base + nt_header.OptionalHeader.AddressOfEntryPoint,
3446 "wrong entry point %p/%p\n", entry_ptr,
3447 (char *)exe_base + nt_header.OptionalHeader.AddressOfEntryPoint );
3448
3449 ret = SetThreadContext(pi.hThread, &ctx);
3450 ok(ret, "Failed to set remote thread context (%d)\n", GetLastError());
3451
3452 ResumeThread(pi.hThread);
3453
3454 pipe_connected = ConnectNamedPipe(server_pipe_handle, NULL) || (GetLastError() == ERROR_PIPE_CONNECTED);
3455 ok(pipe_connected, "Pipe did not connect\n");
3456
3457 ret = ReadFile(server_pipe_handle, &pipe_magic, sizeof(pipe_magic), &numb, NULL);
3458 ok(ret, "Failed to read buffer from pipe (%d)\n", GetLastError());
3459
3460 ok(pipe_magic == pipe_write_magic, "Did not get the correct magic from the remote process\n");
3461
3462 /* Validate the Imports, at this point the thread in the new process should have
3463 initialized the EXE module imports and call each dll DllMain notifying it on
3464 the new thread in the process. */
3465 ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
3466 ok(ret, "EXE IAT is not resolved\n");
3467
3468 ret = WriteFile(server_pipe_handle, &pipe_magic, sizeof(pipe_magic), &numb, NULL);
3469 ok(ret, "Failed to write the magic back to the pipe (%d)\n", GetLastError());
3470
3471 CloseHandle(server_pipe_handle);
3472 TerminateProcess(pi.hProcess, 0);
3473 WaitForSingleObject(pi.hProcess, 10000);
3474 CloseHandle(pi.hProcess);
3475 CloseHandle(pi.hThread);
3476}
3477#else
3479{
3480}
3482{
3483}
3484#endif
3485
3486static void test_DetachStdHandles(void)
3487{
3488#ifndef _WIN64
3489 char buffer[MAX_PATH], tempfile[MAX_PATH];
3492 HANDLE hstdin, hstdout, hstderr, htemp;
3493 BOOL res;
3494
3497 hstderr = GetStdHandle(STD_ERROR_HANDLE);
3498
3499 get_file_name(tempfile);
3500 htemp = CreateFileA(tempfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3501 ok(htemp != INVALID_HANDLE_VALUE, "failed opening temporary file\n");
3502
3503 memset(&startup, 0, sizeof(startup));
3504 startup.cb = sizeof(startup);
3505 startup.dwFlags = STARTF_USESHOWWINDOW;
3506 startup.wShowWindow = SW_SHOWNORMAL;
3508 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
3509
3513
3515 &info);
3516
3520
3521 ok(res, "CreateProcess failed\n");
3522 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
3524 okChildInt("StartupInfoA", "hStdInput", (UINT)INVALID_HANDLE_VALUE);
3525 okChildInt("StartupInfoA", "hStdOutput", (UINT)INVALID_HANDLE_VALUE);
3526 okChildInt("StartupInfoA", "hStdError", (UINT)INVALID_HANDLE_VALUE);
3527 okChildInt("TEB", "hStdInput", 0);
3528 okChildInt("TEB", "hStdOutput", 0);
3529 okChildInt("TEB", "hStdError", 0);
3532
3533 CloseHandle(htemp);
3534 DeleteFileA(tempfile);
3535#endif
3536}
3537
3539{
3540 SYSTEM_INFO si;
3541 UCHAR node;
3542 BOOL ret;
3543 int i;
3544
3545 if (!pGetNumaProcessorNode)
3546 {
3547 win_skip("GetNumaProcessorNode is missing\n");
3548 return;
3549 }
3550
3551 GetSystemInfo(&si);
3552 for (i = 0; i < 256; i++)
3553 {
3554 SetLastError(0xdeadbeef);
3555 node = (i < si.dwNumberOfProcessors) ? 0xFF : 0xAA;
3556 ret = pGetNumaProcessorNode(i, &node);
3557 if (i < si.dwNumberOfProcessors)
3558 {
3559 ok(ret, "GetNumaProcessorNode returned FALSE for processor %d\n", i);
3560 ok(node != 0xFF, "expected node != 0xFF, but got 0xFF\n");
3561 }
3562 else
3563 {
3564 ok(!ret, "GetNumaProcessorNode returned TRUE for processor %d\n", i);
3565 ok(node == 0xFF || broken(node == 0xAA) /* WinXP */, "expected node 0xFF, got %x\n", node);
3566 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3567 }
3568 }
3569}
3570
3571static void test_session_info(void)
3572{
3573 DWORD session_id, active_session;
3574 BOOL r;
3575
3576 if (!pProcessIdToSessionId)
3577 {
3578 win_skip("ProcessIdToSessionId is missing\n");
3579 return;
3580 }
3581
3582 r = pProcessIdToSessionId(GetCurrentProcessId(), &session_id);
3583 ok(r, "ProcessIdToSessionId failed: %u\n", GetLastError());
3584 trace("session_id = %x\n", session_id);
3585
3586 active_session = pWTSGetActiveConsoleSessionId();
3587 trace("active_session = %x\n", active_session);
3588}
3589
3590static void test_process_info(void)
3591{
3592 char buf[4096];
3593 static const ULONG info_size[] =
3594 {
3595 sizeof(PROCESS_BASIC_INFORMATION) /* ProcessBasicInformation */,
3596 sizeof(QUOTA_LIMITS) /* ProcessQuotaLimits */,
3597 sizeof(IO_COUNTERS) /* ProcessIoCounters */,
3598 sizeof(VM_COUNTERS) /* ProcessVmCounters */,
3599 sizeof(KERNEL_USER_TIMES) /* ProcessTimes */,
3600 sizeof(ULONG) /* ProcessBasePriority */,
3601 sizeof(ULONG) /* ProcessRaisePriority */,
3602 sizeof(HANDLE) /* ProcessDebugPort */,
3603 sizeof(HANDLE) /* ProcessExceptionPort */,
3604 0 /* FIXME: sizeof(PROCESS_ACCESS_TOKEN) ProcessAccessToken */,
3605 0 /* FIXME: sizeof(PROCESS_LDT_INFORMATION) ProcessLdtInformation */,
3606 0 /* FIXME: sizeof(PROCESS_LDT_SIZE) ProcessLdtSize */,
3607 sizeof(ULONG) /* ProcessDefaultHardErrorMode */,
3608 0 /* ProcessIoPortHandlers: kernel-mode only */,
3609 0 /* FIXME: sizeof(POOLED_USAGE_AND_LIMITS) ProcessPooledUsageAndLimits */,
3610 0 /* FIXME: sizeof(PROCESS_WS_WATCH_INFORMATION) ProcessWorkingSetWatch */,
3611 sizeof(ULONG) /* ProcessUserModeIOPL */,
3612 sizeof(BOOLEAN) /* ProcessEnableAlignmentFaultFixup */,
3613 sizeof(PROCESS_PRIORITY_CLASS) /* ProcessPriorityClass */,
3614 sizeof(ULONG) /* ProcessWx86Information */,
3615 sizeof(ULONG) /* ProcessHandleCount */,
3616 sizeof(ULONG_PTR) /* ProcessAffinityMask */,
3617 sizeof(ULONG) /* ProcessPriorityBoost */,
3618 0 /* sizeof(PROCESS_DEVICEMAP_INFORMATION) ProcessDeviceMap */,
3619 0 /* sizeof(PROCESS_SESSION_INFORMATION) ProcessSessionInformation */,
3620 0 /* sizeof(PROCESS_FOREGROUND_BACKGROUND) ProcessForegroundInformation */,
3621 sizeof(ULONG_PTR) /* ProcessWow64Information */,
3622 sizeof(buf) /* ProcessImageFileName */,
3623 sizeof(ULONG) /* ProcessLUIDDeviceMapsEnabled */,
3624 sizeof(ULONG) /* ProcessBreakOnTermination */,
3625 sizeof(HANDLE) /* ProcessDebugObjectHandle */,
3626 sizeof(ULONG) /* ProcessDebugFlags */,
3627 sizeof(buf) /* ProcessHandleTracing */,
3628 sizeof(ULONG) /* ProcessIoPriority */,
3629 sizeof(ULONG) /* ProcessExecuteFlags */,
3630 0 /* FIXME: sizeof(?) ProcessTlsInformation */,
3631 0 /* FIXME: sizeof(?) ProcessCookie */,
3632 sizeof(SECTION_IMAGE_INFORMATION) /* ProcessImageInformation */,
3633 0 /* FIXME: sizeof(PROCESS_CYCLE_TIME_INFORMATION) ProcessCycleTime */,
3634 sizeof(ULONG) /* ProcessPagePriority */,
3635 40 /* ProcessInstrumentationCallback */,
3636 0 /* FIXME: sizeof(PROCESS_STACK_ALLOCATION_INFORMATION) ProcessThreadStackAllocation */,
3637 0 /* FIXME: sizeof(PROCESS_WS_WATCH_INFORMATION_EX[]) ProcessWorkingSetWatchEx */,
3638 sizeof(buf) /* ProcessImageFileNameWin32 */,
3639 sizeof(HANDLE) /* ProcessImageFileMapping */,
3640 0 /* FIXME: sizeof(PROCESS_AFFINITY_UPDATE_MODE) ProcessAffinityUpdateMode */,
3641 0 /* FIXME: sizeof(PROCESS_MEMORY_ALLOCATION_MODE) ProcessMemoryAllocationMode */,
3642 sizeof(USHORT) /* ProcessGroupInformation */,
3643 sizeof(ULONG) /* ProcessTokenVirtualizationEnabled */,
3644 sizeof(ULONG_PTR) /* ProcessConsoleHostProcess */,
3645 0 /* FIXME: sizeof(PROCESS_WINDOW_INFORMATION) ProcessWindowInformation */,
3646#if 0 /* FIXME: Add remaining classes */
3647 sizeof(PROCESS_HANDLE_SNAPSHOT_INFORMATION) /* ProcessHandleInformation */,
3648 sizeof(PROCESS_MITIGATION_POLICY_INFORMATION) /* ProcessMitigationPolicy */,
3649 sizeof(ProcessDynamicFunctionTableInformation) /* ProcessDynamicFunctionTableInformation */,
3650 sizeof(?) /* ProcessHandleCheckingMode */,
3651 sizeof(PROCESS_KEEPALIVE_COUNT_INFORMATION) /* ProcessKeepAliveCount */,
3652 sizeof(PROCESS_REVOKE_FILE_HANDLES_INFORMATION) /* ProcessRevokeFileHandles */,
3653 sizeof(PROCESS_WORKING_SET_CONTROL) /* ProcessWorkingSetControl */,
3654 sizeof(?) /* ProcessHandleTable */,
3655 sizeof(?) /* ProcessCheckStackExtentsMode */,
3656 sizeof(buf) /* ProcessCommandLineInformation */,
3657 sizeof(PS_PROTECTION) /* ProcessProtectionInformation */,
3658 sizeof(PROCESS_MEMORY_EXHAUSTION_INFO) /* ProcessMemoryExhaustion */,
3659 sizeof(PROCESS_FAULT_INFORMATION) /* ProcessFaultInformation */,
3660 sizeof(PROCESS_TELEMETRY_ID_INFORMATION) /* ProcessTelemetryIdInformation */,
3661 sizeof(PROCESS_COMMIT_RELEASE_INFORMATION) /* ProcessCommitReleaseInformation */,
3662 sizeof(?) /* ProcessDefaultCpuSetsInformation */,
3663 sizeof(?) /* ProcessAllowedCpuSetsInformation */,
3664 0 /* ProcessReserved1Information */,
3665 0 /* ProcessReserved2Information */,
3666 sizeof(?) /* ProcessSubsystemProcess */,
3667 sizeof(PROCESS_JOB_MEMORY_INFO) /* ProcessJobMemoryInformation */,
3668#endif
3669 };
3670 HANDLE hproc;
3672
3673 if (!pNtQueryInformationProcess)
3674 {
3675 win_skip("NtQueryInformationProcess is not available on this platform\n");
3676 return;
3677 }
3678
3680 if (!hproc)
3681 {
3682 win_skip("PROCESS_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
3683 return;
3684 }
3685
3686 for (i = 0; i < MaxProcessInfoClass; i++)
3687 {
3688 size = info_size[i];
3689 if (!size) size = sizeof(buf);
3690 ret_len = 0;
3691 status = pNtQueryInformationProcess(hproc, i, buf, info_size[i], &ret_len);
3692 if (status == STATUS_NOT_IMPLEMENTED) continue;
3693 if (status == STATUS_INVALID_INFO_CLASS) continue;
3694 if (status == STATUS_INFO_LENGTH_MISMATCH) continue;
3695
3696 switch (i)
3697 {
3699 case ProcessQuotaLimits:
3700 case ProcessTimes:
3704 case 33 /* ProcessIoPriority */:
3705 case ProcessIoCounters:
3706 case ProcessVmCounters:
3709 case ProcessHandleCount:
3714 ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
3715 break;
3716
3721 ok(status == STATUS_ACCESS_DENIED /* before win8 */ || status == STATUS_SUCCESS /* win8 is less strict */,
3722 "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
3723 break;
3724
3727 "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
3728 break;
3729
3731 case ProcessDebugPort:
3732 case ProcessDebugFlags:
3733 case ProcessCookie:
3735 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
3736 break;
3737
3738 default:
3739 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
3740 break;
3741 }
3742 }
3743
3744 CloseHandle(hproc);
3745}
3746
3748{
3750 DWORD len;
3751 BOOL ret;
3752
3753 if (!pGetLogicalProcessorInformationEx)
3754 {
3755 win_skip("GetLogicalProcessorInformationEx() is not supported\n");
3756 return;
3757 }
3758
3759 ret = pGetLogicalProcessorInformationEx(RelationAll, NULL, NULL);
3760 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
3761
3762 len = 0;
3763 ret = pGetLogicalProcessorInformationEx(RelationProcessorCore, NULL, &len);
3764 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d, error %d\n", ret, GetLastError());
3765 ok(len > 0, "got %u\n", len);
3766
3767 len = 0;
3768 ret = pGetLogicalProcessorInformationEx(RelationAll, NULL, &len);
3769 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d, error %d\n", ret, GetLastError());
3770 ok(len > 0, "got %u\n", len);
3771
3773 ret = pGetLogicalProcessorInformationEx(RelationAll, info, &len);
3774 ok(ret, "got %d, error %d\n", ret, GetLastError());
3775 ok(info->Size > 0, "got %u\n", info->Size);
3777}
3778
3779static void test_largepages(void)
3780{
3781 SIZE_T size;
3782
3783 if (!pGetLargePageMinimum) {
3784 skip("No GetLargePageMinimum support.\n");
3785 return;
3786 }
3787 size = pGetLargePageMinimum();
3788
3789 ok((size == 0) || (size == 2*1024*1024) || (size == 4*1024*1024), "GetLargePageMinimum reports %ld size\n", size);
3790}
3791
3793{
3796 void *value;
3797};
3798
3800{
3801 DWORD mask; /* bitmask of items in list */
3802 DWORD size; /* max number of items in list */
3803 DWORD count; /* number of items in list */
3807};
3808
3810{
3811 BOOL ret;
3812 SIZE_T size, needed;
3813 int i;
3814 struct _PROC_THREAD_ATTRIBUTE_LIST list, expect_list;
3815 HANDLE handles[4];
3816
3817 if (!pInitializeProcThreadAttributeList)
3818 {
3819 win_skip("No support for ProcThreadAttributeList\n");
3820 return;
3821 }
3822
3823 for (i = 0; i <= 10; i++)
3824 {
3826 ret = pInitializeProcThreadAttributeList(NULL, i, 0, &size);
3827 ok(!ret, "got %d\n", ret);
3828 if(i >= 4 && GetLastError() == ERROR_INVALID_PARAMETER) /* Vista only allows a maximium of 3 slots */
3829 break;
3831 ok(size == needed, "%d: got %ld expect %ld\n", i, size, needed);
3832
3833 memset(&list, 0xcc, sizeof(list));
3834 ret = pInitializeProcThreadAttributeList(&list, i, 0, &size);
3835 ok(ret, "got %d\n", ret);
3836 ok(list.mask == 0, "%d: got %08x\n", i, list.mask);
3837 ok(list.size == i, "%d: got %08x\n", i, list.size);
3838 ok(list.count == 0, "%d: got %08x\n", i, list.count);
3839 ok(list.unk == 0, "%d: got %08lx\n", i, list.unk);
3840 }
3841
3842 memset(handles, 0, sizeof(handles));
3843 memset(&expect_list, 0xcc, sizeof(expect_list));
3844 expect_list.mask = 0;
3845 expect_list.size = i - 1;
3846 expect_list.count = 0;
3847 expect_list.unk = 0;
3848
3849 ret = pUpdateProcThreadAttribute(&list, 0, 0xcafe, handles, sizeof(PROCESSOR_NUMBER), NULL, NULL);
3850 ok(!ret, "got %d\n", ret);
3851 ok(GetLastError() == ERROR_NOT_SUPPORTED, "got %d\n", GetLastError());
3852
3853 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]) / 2, NULL, NULL);
3854 ok(!ret, "got %d\n", ret);
3855 ok(GetLastError() == ERROR_BAD_LENGTH, "got %d\n", GetLastError());
3856
3857 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]) * 2, NULL, NULL);
3858 ok(!ret, "got %d\n", ret);
3859 ok(GetLastError() == ERROR_BAD_LENGTH, "got %d\n", GetLastError());
3860
3861 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]), NULL, NULL);
3862 ok(ret, "got %d\n", ret);
3863
3864 expect_list.mask |= 1 << ProcThreadAttributeParentProcess;
3865 expect_list.attrs[0].attr = PROC_THREAD_ATTRIBUTE_PARENT_PROCESS;
3866 expect_list.attrs[0].size = sizeof(handles[0]);
3867 expect_list.attrs[0].value = handles;
3868 expect_list.count++;
3869
3870 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]), NULL, NULL);
3871 ok(!ret, "got %d\n", ret);
3873
3874 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles) - 1, NULL, NULL);
3875 ok(!ret, "got %d\n", ret);
3876 ok(GetLastError() == ERROR_BAD_LENGTH, "got %d\n", GetLastError());
3877
3878 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles), NULL, NULL);
3879 ok(ret, "got %d\n", ret);
3880
3881 expect_list.mask |= 1 << ProcThreadAttributeHandleList;
3882 expect_list.attrs[1].attr = PROC_THREAD_ATTRIBUTE_HANDLE_LIST;
3883 expect_list.attrs[1].size = sizeof(handles);
3884 expect_list.attrs[1].value = handles;
3885 expect_list.count++;
3886
3887 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles), NULL, NULL);
3888 ok(!ret, "got %d\n", ret);
3890
3891 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR, handles, sizeof(PROCESSOR_NUMBER), NULL, NULL);
3892 ok(ret || GetLastError() == ERROR_NOT_SUPPORTED, "got %d gle %d\n", ret, GetLastError());
3893
3894 if (ret)
3895 {
3896 expect_list.mask |= 1 << ProcThreadAttributeIdealProcessor;
3897 expect_list.attrs[2].attr = PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR;
3898 expect_list.attrs[2].size = sizeof(PROCESSOR_NUMBER);
3899 expect_list.attrs[2].value = handles;
3900 expect_list.count++;
3901 }
3902
3903 ok(!memcmp(&list, &expect_list, size), "mismatch\n");
3904
3905 pDeleteProcThreadAttributeList(&list);
3906}
3907
3909{
3910 DWORD count;
3911
3912 if (!pGetActiveProcessorCount)
3913 {
3914 win_skip("GetActiveProcessorCount not available, skipping test\n");
3915 return;
3916 }
3917
3918 count = pGetActiveProcessorCount(0);
3919 ok(count, "GetActiveProcessorCount failed, error %u\n", GetLastError());
3920
3921 /* Test would fail on systems with more than 6400 processors */
3922 SetLastError(0xdeadbeef);
3923 count = pGetActiveProcessorCount(101);
3924 ok(count == 0, "Expeced GetActiveProcessorCount to fail\n");
3925 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3926}
3927
3929{
3930 HANDLE job;
3931 BOOL b = init();
3932 ok(b, "Basic init of CreateProcess test\n");
3933 if (!b) return;
3934
3935 if (myARGC >= 3)
3936 {
3937 if (!strcmp(myARGV[2], "dump") && myARGC >= 4)
3938 {
3939 doChild(myARGV[3], (myARGC >= 5) ? myARGV[4] : NULL);
3940 return;
3941 }
3942 else if (!strcmp(myARGV[2], "wait"))
3943 {
3944 Sleep(30000);
3945 ok(0, "Child process not killed\n");
3946 return;
3947 }
3948 else if (!strcmp(myARGV[2], "exit"))
3949 {
3950 Sleep(100);
3951 return;
3952 }
3953 else if (!strcmp(myARGV[2], "nested") && myARGC >= 4)
3954 {
3955 char buffer[MAX_PATH];
3958
3959 memset(&startup, 0, sizeof(startup));
3960 startup.cb = sizeof(startup);
3961 startup.dwFlags = STARTF_USESHOWWINDOW;
3962 startup.wShowWindow = SW_SHOWNORMAL;
3963
3964 sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, myARGV[3]);
3965 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startup, &info), "CreateProcess failed\n");
3966 CloseHandle(info.hProcess);
3967 CloseHandle(info.hThread);
3968 return;
3969 }
3970
3971 ok(0, "Unexpected command %s\n", myARGV[2]);
3972 return;
3973 }
3974
3977 test_Startup();
3980 test_Toolhelp(); //
3984 test_Console();
3985 test_ExitCode();
3991 test_Handles();
4007
4008 /* things that can be tested:
4009 * lookup: check the way program to be executed is searched
4010 * handles: check the handle inheritance stuff (+sec options)
4011 * console: check if console creation parameters work
4012 */
4013
4014 if (!pCreateJobObjectW)
4015 {
4016 win_skip("No job object support\n");
4017 return;
4018 }
4019
4030}
unsigned char BOOLEAN
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
#define broken(x)
Definition: _sntprintf.h:21
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
int toupper(int c)
Definition: utclib.c:881
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define va_arg(ap, T)
Definition: acmsvcex.h:89
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 skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define msg(x)
Definition: auth_time.c:54
#define U(x)
Definition: wordpad.c:45
BOOL WINAPI SetConsoleOutputCP(IN UINT wCodepage)
Definition: console.c:695
BOOL WINAPI SetConsoleCursorPosition(IN HANDLE hConsoleOutput, IN COORD dwCursorPosition)
Definition: console.c:641
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
BOOL WINAPI AllocConsole(VOID)
Definition: console.c:74
BOOL WINAPI GetConsoleScreenBufferInfo(IN HANDLE hConsoleOutput, OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
Definition: console.c:595
static HANDLE thread
Definition: service.c:33
Definition: list.h:37
size_type size() const
Definition: _list.h:379
SIZE_T LPPROCESS_INFORMATION
Definition: cordebug.idl:86
const char * env_var
Definition: db.cpp:880
static LPCWSTR LPCWSTR module_name
Definition: db.cpp:170
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:170
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
static const WCHAR deviceW[]
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NTSTATUS
Definition: precomp.h:21
static const WCHAR empty[]
Definition: main.c:47
#define CloseHandle
Definition: compat.h:739
#define ReadProcessMemory(a, b, c, d, e)
Definition: compat.h:758
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define lstrcpynA
Definition: compat.h:751
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GetCurrentProcess()
Definition: compat.h:759
#define GENERIC_READ
Definition: compat.h:135
#define ERROR_NOT_SUPPORTED
Definition: compat.h:100
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID)
Definition: console.c:2451
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1569
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCP(UINT wCodePageID)
Definition: console.c:2420
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1606
BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandle(DWORD nStdHandle, HANDLE hHandle)
Definition: console.c:1213
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(VOID)
Definition: console.c:2391
BOOL WINAPI ContinueDebugEvent(IN DWORD dwProcessId, IN DWORD dwThreadId, IN DWORD dwContinueStatus)
Definition: debugger.c:413
BOOL WINAPI WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent, IN DWORD dwMilliseconds)
Definition: debugger.c:590
DWORD WINAPI QueryDosDeviceW(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:542
BOOL WINAPI FreeEnvironmentStringsA(IN LPSTR EnvironmentStrings)
Definition: environ.c:379
BOOL WINAPI FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings)
Definition: environ.c:389
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
BOOL WINAPI SetHandleInformation(IN HANDLE hObject, IN DWORD dwMask, IN DWORD dwFlags)
Definition: handle.c:78
BOOL WINAPI GetHandleInformation(IN HANDLE hObject, OUT LPDWORD lpdwFlags)
Definition: handle.c:40
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
BOOL WINAPI QueryInformationJobObject(IN HANDLE hJob, IN JOBOBJECTINFOCLASS JobObjectInformationClass, IN LPVOID lpJobObjectInformation, IN DWORD cbJobObjectInformationLength, OUT LPDWORD lpReturnLength)
Definition: job.c:119
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2146
UINT WINAPI GetWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2337
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:993
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
BOOL NTAPI WriteProcessMemory(IN HANDLE hProcess, IN LPVOID lpBaseAddress, IN LPCVOID lpBuffer, IN SIZE_T nSize, OUT SIZE_T *lpNumberOfBytesWritten)
Definition: proc.c:2056
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1168
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1487
DWORD WINAPI GetProcessVersion(IN DWORD ProcessId)
Definition: proc.c:1760
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:4741
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1532
HANDLE WINAPI OpenProcess(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwProcessId)
Definition: proc.c:1227
LPSTR WINAPI GetCommandLineA(VOID)
Definition: proc.c:2003
LPWSTR WINAPI GetCommandLineW(VOID)
Definition: proc.c:2013
VOID WINAPI GetStartupInfoW(IN LPSTARTUPINFOW lpStartupInfo)
Definition: proc.c:1279
VOID WINAPI GetStartupInfoA(IN LPSTARTUPINFOA lpStartupInfo)
Definition: proc.c:1320
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:143
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
HANDLE WINAPI CreateRemoteThread(IN HANDLE hProcess, IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:159
BOOL WINAPI SetThreadContext(IN HANDLE hThread, IN CONST CONTEXT *lpContext)
Definition: thread.c:521
HANDLE WINAPI OpenThread(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwThreadId)
Definition: thread.c:403
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:587
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:541
BOOL WINAPI GetThreadContext(IN HANDLE hThread, OUT LPCONTEXT lpContext)
Definition: thread.c:501
INT WINAPI GetPrivateProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR def_val, LPSTR buffer, UINT len, LPCSTR filename)
Definition: profile.c:1204
UINT WINAPI GetPrivateProfileIntA(LPCSTR section, LPCSTR entry, INT def_val, LPCSTR filename)
Definition: profile.c:1326
BOOL WINAPI DECLSPEC_HOTPATCH WritePrivateProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR string, LPCSTR filename)
Definition: profile.c:1484
BOOL is_wow64
Definition: msi.c:54
USHORT port
Definition: uri.c:228
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define assert(x)
Definition: debug.h:53
#define INFINITE
Definition: serial.h:102
#define ULONG_PTR
Definition: config.h:101
UINT WINAPI GetTempFileNameA(IN LPCSTR lpPathName, IN LPCSTR lpPrefixString, IN UINT uUnique, OUT LPSTR lpTempFileName)
Definition: filename.c:26
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLeglImageOES image
Definition: gl.h:2204
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint res
Definition: glext.h:9613
GLuint address
Definition: glext.h:9393
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum const GLfloat * params
Definition: glext.h:5645
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
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
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 * u
Definition: glfuncs.h:240
int __cdecl vsprintf(char *_Dest, const char *_Format, va_list _Args)
Definition: sprintf.c:733
struct _PROCESS_PRIORITY_CLASS PROCESS_PRIORITY_CLASS
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:166
#define JOB_OBJECT_LIMIT_BREAKAWAY_OK
Definition: pstypes.h:223
struct _JOBOBJECT_BASIC_PROCESS_ID_LIST JOBOBJECT_BASIC_PROCESS_ID_LIST
enum _JOBOBJECTINFOCLASS JOBOBJECTINFOCLASS
#define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
Definition: pstypes.h:225
#define PROCESS_VM_OPERATION
Definition: pstypes.h:160
@ JobObjectAssociateCompletionPortInformation
Definition: pstypes.h:434
@ JobObjectBasicLimitInformation
Definition: pstypes.h:429
@ JobObjectBasicAccountingInformation
Definition: pstypes.h:428
@ JobObjectExtendedLimitInformation
Definition: pstypes.h:436
@ JobObjectBasicProcessIdList
Definition: pstypes.h:430
#define JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK
Definition: pstypes.h:224
@ ProcessDebugPort
Definition: winternl.h:395
@ ProcessBreakOnTermination
Definition: winternl.h:398
@ ProcessBasicInformation
Definition: winternl.h:394
@ ProcessWow64Information
Definition: winternl.h:396
@ ProcessImageFileName
Definition: winternl.h:397
struct _PROCESS_BASIC_INFORMATION PROCESS_BASIC_INFORMATION
struct _KERNEL_USER_TIMES KERNEL_USER_TIMES
@ ProcessPagePriority
Definition: winternl.h:894
@ ProcessLUIDDeviceMapsEnabled
Definition: winternl.h:884
@ ProcessDebugFlags
Definition: winternl.h:887
@ MaxProcessInfoClass
Definition: winternl.h:906
@ ProcessConsoleHostProcess
Definition: winternl.h:904
@ ProcessAffinityMask
Definition: winternl.h:877
@ ProcessVmCounters
Definition: winternl.h:859
@ ProcessPriorityClass
Definition: winternl.h:874
@ ProcessPriorityBoost
Definition: winternl.h:878
@ ProcessImageInformation
Definition: winternl.h:892
@ ProcessExecuteFlags
Definition: winternl.h:889
@ ProcessCookie
Definition: winternl.h:891
@ ProcessIoCounters
Definition: winternl.h:858
@ ProcessImageFileNameWin32
Definition: winternl.h:898
@ ProcessDefaultHardErrorMode
Definition: winternl.h:868
@ ProcessQuotaLimits
Definition: winternl.h:857
@ ProcessTimes
Definition: winternl.h:860
@ ProcessDebugObjectHandle
Definition: winternl.h:886
@ ProcessGroupInformation
Definition: winternl.h:902
@ ProcessHandleCount
Definition: winternl.h:876
struct _IO_COUNTERS IO_COUNTERS
BOOL WINAPI GetQueuedCompletionStatus(IN HANDLE CompletionHandle, IN LPDWORD lpNumberOfBytesTransferred, OUT PULONG_PTR lpCompletionKey, OUT LPOVERLAPPED *lpOverlapped, IN DWORD dwMilliseconds)
Definition: iocompl.c:131
#define NtCurrentTeb
#define f
Definition: ke_i.h:83
#define wine_dbgstr_w
Definition: kernel32.h:34
int WINAPI lstrcmpiA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:42
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:71
struct S1 s1
struct S2 s2
double __cdecl fmin(double, double)
#define CREATE_ALWAYS
Definition: disk.h:72
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define FILE_FLAG_WRITE_THROUGH
Definition: disk.h:47
static IMAGE_DOS_HEADER dos_header
Definition: data.c:13
static IMAGE_NT_HEADERS32 nt_header
Definition: data.c:36
static PVOID ptr
Definition: dispmode.c:27
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define PROCESS_QUERY_LIMITED_INFORMATION
Definition: security.c:45
static const BYTE us[]
Definition: encode.c:689
static BOOL run_tests(void)
Definition: run.c:2756
#define expect_eq_ws_i(expected, actual)
Definition: process.c:59
static void test_Toolhelp(void)
Definition: process.c:1140
static void test_StartupNoConsole(void)
Definition: process.c:3035
#define test_completion(a, b, c, d, e)
Definition: process.c:2389
static LPSTR
Definition: process.c:74
static SIZE_T *static DWORD_PTR
Definition: process.c:94
static void test_ExitCode(void)
Definition: process.c:1723
static HANDLE ULONG_PTR key
Definition: process.c:81
#define MAX_LISTED_ENV_VAR
Definition: process.c:112
static const char * encodeA(const char *str)
Definition: process.c:136
static void _test_assigned_proc(int line, HANDLE job, int expected_count,...)
Definition: process.c:2422
static HINSTANCE hkernel32
Definition: process.c:66
static void _test_accounting(int line, HANDLE job, int total_proc, int active_proc, int terminated_proc)
Definition: process.c:2458
static PUCHAR
Definition: process.c:82
static DWORD
Definition: process.c:70
static char * memory_index
Definition: process.c:117
static void test_SuspendFlag(void)
Definition: process.c:1420
static HANDLE process
Definition: process.c:76
static void test_KillOnJobClose(void)
Definition: process.c:2780
static void ok_child_string(int line, const char *sect, const char *key, const char *expect, int sensitive)
Definition: process.c:557
static void _test_completion(int line, HANDLE port, DWORD ekey, ULONG_PTR evalue, ULONG_PTR eoverlapped, DWORD wait)
Definition: process.c:2390
static void test_CommandLine(void)
Definition: process.c:888
#define PROCESS_ALL_ACCESS_NT4
Definition: process.c:43
static void test_IsProcessInJob(void)
Definition: process.c:2485
static void test_SuspendProcessState(void)
Definition: process.c:3481
static HANDLE test_AddSelfToJob(void)
Definition: process.c:2908
static DWORD dwFlags
Definition: process.c:72
static int strCmp(const char *s1, const char *s2, BOOL sensitive)
Definition: process.c:549
static void doChild(const char *file, const char *option)
Definition: process.c:306
#define okChildString(sect, key, expect)
Definition: process.c:597
static void test_Directory(void)
Definition: process.c:1096
static UINT exit_code
Definition: process.c:78
static BOOL init(void)
Definition: process.c:217
#define okChildStringWA(sect, key, expect)
Definition: process.c:599
static void test_GetProcessVersion(void)
Definition: process.c:1866
#define test_assigned_proc(job,...)
Definition: process.c:2421
static JOBOBJECTINFOCLASS LPVOID DWORD LPDWORD ret_len
Definition: process.c:79
static int myARGC
Definition: process.c:104
#define expect_eq_s(expected, actual)
Definition: process.c:53
static BOOL is_str_env_drive_dir(const char *str)
Definition: process.c:1266
#define expect_eq_d(expected, actual)
Definition: process.c:47
static unsigned decode_char(char c)
Definition: process.c:165
#define okChildIString(sect, key, expect)
Definition: process.c:598
static JOBOBJECTINFOCLASS LPVOID info
Definition: process.c:79
static PROCESSINFOCLASS
Definition: process.c:83
static ULONG
Definition: process.c:83
static DWORD LPSTR PDWORD lpdwSize
Definition: process.c:72
static void test_SystemInfo(void)
Definition: process.c:2189
static HANDLE ULONG_PTR DWORD threads
Definition: process.c:81
static void test_DebuggingFlag(void)
Definition: process.c:1468
static char * decodeA(const char *str)
Definition: process.c:173
static void test_WaitForJobObject(void)
Definition: process.c:2819
static HANDLE existing_port
Definition: process.c:81
static void ok_child_int(int line, const char *sect, const char *key, UINT expect)
Definition: process.c:591
#define THREAD_ALL_ACCESS_NT4
Definition: process.c:45
static HANDLE PBOOL result
Definition: process.c:77
static void test_CompletionPort(void)
Definition: process.c:2741
static void test_BreakawayOk(HANDLE job)
Definition: process.c:2957
static void ok_child_stringWA(int line, const char *sect, const char *key, const char *expect, int sensitive)
Definition: process.c:565
static SIZE_T
Definition: process.c:70
static void test_TerminateProcess(void)
Definition: process.c:2255
#define create_process(cmd, pi)
Definition: process.c:2408
static void test_jobInheritance(HANDLE job)
Definition: process.c:2924
static PBOOL
Definition: process.c:69
static void test_Handles(void)
Definition: process.c:2087
static void test_DuplicateHandle(void)
Definition: process.c:2292
static DWORD LPSTR lpExeName
Definition: process.c:72
static char ** myARGV
Definition: process.c:105
static void test_DetachConsoleHandles(void)
Definition: process.c:3063
static PVOID
Definition: process.c:83
static BOOL is_console(HANDLE h)
Definition: process.c:1530
static void test_QueryFullProcessImageNameW(void)
Definition: process.c:1997
static HINSTANCE hntdll
Definition: process.c:66
static WCHAR * decodeW(const char *str)
Definition: process.c:190
static void test_IsWow64Process(void)
Definition: process.c:2133
static void test_session_info(void)
Definition: process.c:3571
static void _create_process(int line, const char *command, LPPROCESS_INFORMATION pi)
Definition: process.c:2409
#define INIT_STR
static LPVOID
Definition: process.c:70
static void test_Startup(void)
Definition: process.c:602
static LPCWSTR name
Definition: process.c:75
#define test_accounting(job, total_proc, active_proc, terminated_proc)
Definition: process.c:2457
static void test_OpenProcess(void)
Definition: process.c:1752
static void test_largepages(void)
Definition: process.c:3779
static void test_Console(void)
Definition: process.c:1535
static void release_memory(void)
Definition: process.c:129
static char memory[1024 *256]
Definition: process.c:116
static char * exename
Definition: process.c:101
static void test_DetachStdHandles(void)
Definition: process.c:3486
#define okChildInt(sect, key, expect)
Definition: process.c:600
static PDWORD
Definition: process.c:68
static char resfile[MAX_PATH]
Definition: process.c:102
static void test_QueryInformationJobObject(void)
Definition: process.c:2620
static WCHAR * getChildStringW(const char *sect, const char *key)
Definition: process.c:518
static void test_QueryFullProcessImageNameA(void)
Definition: process.c:1942
static void test_SuspendProcessNewThread(void)
Definition: process.c:3478
static char * grab_memory(size_t len)
Definition: process.c:119
static void test_GetProcessImageFileNameA(void)
Definition: process.c:1901
static void test_ProcThreadAttributeList(void)
Definition: process.c:3809
static void test_GetActiveProcessorCount(void)
Definition: process.c:3908
static void test_GetNumaProcessorNode(void)
Definition: process.c:3538
static void test_RegistryQuota(void)
Definition: process.c:2227
static void cmpEnvironment(const char *gesA)
Definition: process.c:1275
static void test_GetLogicalProcessorInformationEx(void)
Definition: process.c:3747
static void test_TerminateJobObject(void)
Definition: process.c:2565
static char selfname[MAX_PATH]
Definition: process.c:100
static void test_process_info(void)
Definition: process.c:3590
static void test_Environment(void)
Definition: process.c:1329
static char * getChildString(const char *sect, const char *key)
Definition: process.c:506
static PULONG
Definition: process.c:83
static int wtstrcasecmp(const char *p1, const char *p2)
Definition: process.c:533
static HANDLE job
Definition: process.c:77
static const char * encodeW(const WCHAR *str)
Definition: process.c:150
static int expected_count(int *sink)
#define todo_wine_if(is_todo)
Definition: custom.c:76
#define todo_wine
Definition: custom.c:79
static __ms_va_list valist
Definition: printf.c:66
static refpint_t pi[]
Definition: server.c:96
static LPCWSTR file_name
Definition: protocol.c:147
#define min(a, b)
Definition: monoChain.cc:55
HANDLE hStdOut
Definition: more.c:49
HANDLE hStdIn
Definition: more.c:49
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned int UINT
Definition: ndis.h:50
#define PROCESSOR_ARCHITECTURE_AMD64
Definition: ketypes.h:114
#define PROCESSOR_ARCHITECTURE_INTEL
Definition: ketypes.h:105
struct _SECTION_IMAGE_INFORMATION SECTION_IMAGE_INFORMATION
#define SEC_IMAGE
Definition: mmtypes.h:97
HANDLE hThread
Definition: wizard.c:28
BOOL WINAPI ConnectNamedPipe(IN HANDLE hNamedPipe, IN LPOVERLAPPED lpOverlapped)
Definition: npipe.c:701
HANDLE WINAPI CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: npipe.c:220
BOOL WINAPI CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize)
Definition: npipe.c:117
#define BOOL
Definition: nt_native.h:43
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define MEM_PRIVATE
Definition: nt_native.h:1318
#define MEM_RESERVE
Definition: nt_native.h:1314
#define MEM_RELEASE
Definition: nt_native.h:1316
#define GENERIC_WRITE
Definition: nt_native.h:90
#define MEM_COMMIT
Definition: nt_native.h:1313
#define PAGE_NOACCESS
Definition: nt_native.h:1302
PROCESSOR_NUMBER
Definition: ntbasedef.h:642
#define DBG_CONTINUE
Definition: ntstatus.h:47
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_PORT_NOT_SET
Definition: ntstatus.h:894
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
#define L(x)
Definition: ntvdm.h:50
static BOOL read_bytes(parse_buffer *buf, LPVOID data, DWORD size)
Definition: parsing.c:168
#define IMAGE_DIRECTORY_ENTRY_IMPORT
Definition: pedump.c:260
DWORD * PDWORD
Definition: pedump.c:68
#define IMAGE_NT_SIGNATURE
Definition: pedump.c:93
#define IMAGE_FILE_DLL
Definition: pedump.c:169
unsigned short USHORT
Definition: pedump.c:61
#define IMAGE_DOS_SIGNATURE
Definition: pedump.c:89
static char title[]
Definition: ps.c:92
#define get_file_name
Definition: regproc.h:51
static FILE * out
Definition: regtests2xml.c:44
const WCHAR * str
#define offsetof(TYPE, MEMBER)
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#define win_skip
Definition: test.h:160
int winetest_interactive
int winetest_get_mainargs(char ***pargv)
#define S(x)
Definition: test.h:217
#define WINETEST_PRINTF_ATTR(fmt, args)
Definition: test.h:140
#define CONTEXT_ALL
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED * overlapped
Definition: sock.c:81
TCHAR * cmdline
Definition: stretchblt.cpp:32
union _DEBUG_EVENT::@3274 u
DWORD dwDebugEventCode
Definition: winbase.h:788
DWORD dwThreadId
Definition: winbase.h:790
DWORD dwProcessId
Definition: winbase.h:789
LOAD_DLL_DEBUG_INFO LoadDll
Definition: winbase.h:797
CREATE_PROCESS_DEBUG_INFO CreateProcessInfo
Definition: winbase.h:794
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]
Definition: ntddk_ex.h:178
JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation
Definition: pstypes.h:1602
PVOID ImageBaseAddress
Definition: ntddk_ex.h:245
struct proc_thread_attr attrs[10]
Definition: process.c:3806
DWORD dwX
Definition: winbase.h:835
HANDLE hStdOutput
Definition: winbase.h:847
DWORD dwXSize
Definition: winbase.h:837
LPSTR lpTitle
Definition: winbase.h:834
DWORD dwXCountChars
Definition: winbase.h:839
HANDLE hStdError
Definition: winbase.h:848
DWORD dwFlags
Definition: winbase.h:842
DWORD cb
Definition: winbase.h:831
HANDLE hStdInput
Definition: winbase.h:846
DWORD dwYSize
Definition: winbase.h:838
WORD wShowWindow
Definition: winbase.h:843
DWORD dwYCountChars
Definition: winbase.h:840
DWORD dwY
Definition: winbase.h:836
DWORD dwFillAttribute
Definition: winbase.h:841
LPSTR lpDesktop
Definition: winbase.h:833
LPWSTR lpDesktop
Definition: winbase.h:854
DWORD cb
Definition: winbase.h:852
DWORD dwXCountChars
Definition: winbase.h:860
DWORD dwYSize
Definition: winbase.h:859
HANDLE hStdError
Definition: winbase.h:869
DWORD dwFillAttribute
Definition: winbase.h:862
DWORD dwX
Definition: winbase.h:856
DWORD dwXSize
Definition: winbase.h:858
DWORD dwFlags
Definition: winbase.h:863
HANDLE hStdOutput
Definition: winbase.h:868
LPWSTR lpTitle
Definition: winbase.h:855
HANDLE hStdInput
Definition: winbase.h:867
DWORD dwY
Definition: winbase.h:857
WORD wShowWindow
Definition: winbase.h:864
DWORD dwYCountChars
Definition: winbase.h:861
DWORD dwNumberOfProcessors
Definition: winbase.h:1177
DWORD dwProcessorType
Definition: winbase.h:1178
Definition: inflate.c:139
Definition: devices.h:37
Definition: fci.c:127
Definition: dsound.c:943
Definition: copy.c:22
Definition: parser.c:49
Definition: getopt.h:109
DWORD_PTR attr
Definition: process.c:3794
Definition: ps.c:97
SHORT Y
Definition: blue.h:27
SHORT X
Definition: blue.h:26
DWORD th32ParentProcessID
Definition: tlhelp32.h:67
DWORD th32DefaultHeapID
Definition: tlhelp32.h:64
CHAR szExeFile[MAX_PATH]
Definition: tlhelp32.h:70
DWORD th32ModuleID
Definition: tlhelp32.h:65
LONG pcPriClassBase
Definition: tlhelp32.h:68
DWORD cntThreads
Definition: tlhelp32.h:66
DWORD th32ProcessID
Definition: tlhelp32.h:63
SHORT Right
Definition: blue.h:34
SHORT Left
Definition: blue.h:32
SHORT Top
Definition: blue.h:33
SHORT Bottom
Definition: blue.h:35
DWORD th32ThreadID
Definition: tlhelp32.h:75
DWORD th32OwnerProcessID
Definition: tlhelp32.h:76
Definition: dhcpd.h:245
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
#define TH32CS_SNAPPROCESS
Definition: tlhelp32.h:26
#define TH32CS_SNAPTHREAD
Definition: tlhelp32.h:27
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
PVOID HANDLE
Definition: typedefs.h:73
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t * LPDWORD
Definition: typedefs.h:59
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
static EFI_HANDLE * handles
Definition: uefidisk.c:62
Definition: dlist.c:348
Definition: pdh_main.c:94
int ret
LPVOID NTAPI VirtualAllocEx(IN HANDLE hProcess, IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
Definition: virtmem.c:23
BOOL NTAPI VirtualFree(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD dwFreeType)
Definition: virtmem.c:119
SIZE_T NTAPI VirtualQueryEx(IN HANDLE hProcess, IN LPCVOID lpAddress, OUT PMEMORY_BASIC_INFORMATION lpBuffer, IN SIZE_T dwLength)
Definition: virtmem.c:227
#define PROCESS_NAME_NATIVE
Definition: winbase.h:23
#define STD_OUTPUT_HANDLE
Definition: winbase.h:268
#define STD_INPUT_HANDLE
Definition: winbase.h:267
#define CREATE_BREAKAWAY_FROM_JOB
Definition: winbase.h:192
#define STILL_ACTIVE
Definition: winbase.h:233
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define STARTF_USESHOWWINDOW
Definition: winbase.h:491
@ ProcThreadAttributeIdealProcessor
Definition: winbase.h:1417
@ ProcThreadAttributeParentProcess
Definition: winbase.h:1414
@ ProcThreadAttributeHandleList
Definition: winbase.h:1415
#define CREATE_PROCESS_DEBUG_EVENT
Definition: winbase.h:104
#define PIPE_ACCESS_DUPLEX
Definition: winbase.h:164
#define HANDLE_FLAG_PROTECT_FROM_CLOSE
Definition: winbase.h:265
#define LOAD_DLL_DEBUG_EVENT
Definition: winbase.h:107
#define HANDLE_FLAG_INHERIT
Definition: winbase.h:264
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158
#define EXIT_PROCESS_DEBUG_EVENT
Definition: winbase.h:106
#define STD_ERROR_HANDLE
Definition: winbase.h:269
struct _SYSTEM_INFO * LPSYSTEM_INFO
LPWSTR WINAPI GetEnvironmentStringsW(void)
Definition: environ.c:344
#define CREATE_SUSPENDED
Definition: winbase.h:178
#define PIPE_READMODE_MESSAGE
Definition: winbase.h:170
#define GetEnvironmentStringsA
Definition: winbase.h:3748
#define EXCEPTION_DEBUG_EVENT
Definition: winbase.h:102
_In_ LPCSTR _In_opt_ LPCSTR _In_ DWORD _Out_opt_ LPSTR * lpFilePart
Definition: winbase.h:3075
#define PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
Definition: winbase.h:1431
#define PROC_THREAD_ATTRIBUTE_HANDLE_LIST
Definition: winbase.h:1430
#define WAIT_OBJECT_0
Definition: winbase.h:406
#define PIPE_TYPE_MESSAGE
Definition: winbase.h:168
#define STARTF_USESTDHANDLES
Definition: winbase.h:499
#define DETACHED_PROCESS
Definition: winbase.h:179
DWORD(WINAPI * LPTHREAD_START_ROUTINE)(LPVOID)
Definition: winbase.h:729
struct _OVERLAPPED * LPOVERLAPPED
#define DEBUG_PROCESS
Definition: winbase.h:176
#define PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR
Definition: winbase.h:1429
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837
BOOL * PBOOL
Definition: windef.h:161
#define WINAPI
Definition: msvc.h:6
#define ERROR_OBJECT_NAME_EXISTS
Definition: winerror.h:479
#define ERROR_BAD_LENGTH
Definition: winerror.h:127
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define ERROR_DIRECTORY
Definition: winerror.h:295
#define ERROR_BAD_PATHNAME
Definition: winerror.h:233
#define ERROR_PIPE_CONNECTED
Definition: winerror.h:352
#define JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO
Definition: winnt_old.h:3742
#define PROCESSOR_AMD_X8664
Definition: winnt_old.h:434
#define JOB_OBJECT_MSG_EXIT_PROCESS
Definition: winnt_old.h:3744
#define JOB_OBJECT_MSG_NEW_PROCESS
Definition: winnt_old.h:3743
#define SW_SHOWNORMAL
Definition: winuser.h:770
#define SW_HIDE
Definition: winuser.h:768
@ RelationProcessorCore
Definition: ketypes.h:82
@ RelationAll
Definition: ketypes.h:87
enum _LOGICAL_PROCESSOR_RELATIONSHIP LOGICAL_PROCESSOR_RELATIONSHIP
#define DUPLICATE_SAME_ACCESS
#define DUPLICATE_CLOSE_SOURCE
char * LPSTR
Definition: xmlstorage.h:182
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175
#define const
Definition: zconf.h:233