ReactOS 0.4.16-dev-2206-gc56950d
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#include "wine/heap.h"
40#ifdef __REACTOS__
41#include "winehacks.h"
42#endif
43
44/* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
45#define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)
46/* THREAD_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
47#define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
48
49#define expect_eq_d(expected, actual) \
50 do { \
51 int value = (actual); \
52 ok((expected) == value, "Expected " #actual " to be %d (" #expected ") is %d\n", \
53 (int)(expected), value); \
54 } while (0)
55#define expect_eq_s(expected, actual) \
56 do { \
57 LPCSTR value = (actual); \
58 ok(lstrcmpA((expected), value) == 0, "Expected " #actual " to be L\"%s\" (" #expected ") is L\"%s\"\n", \
59 expected, value); \
60 } while (0)
61#define expect_eq_ws_i(expected, actual) \
62 do { \
63 LPCWSTR value = (actual); \
64 ok(lstrcmpiW((expected), value) == 0, "Expected " #actual " to be L\"%s\" (" #expected ") is L\"%s\"\n", \
65 wine_dbgstr_w(expected), wine_dbgstr_w(value)); \
66 } while (0)
67
69static void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
70static BOOL (WINAPI *pGetSystemRegistryQuota)(PDWORD, PDWORD);
71static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
72static BOOL (WINAPI *pIsWow64Process2)(HANDLE, USHORT *, USHORT *);
73static BOOL (WINAPI *pQueryFullProcessImageNameA)(HANDLE hProcess, DWORD dwFlags, LPSTR lpExeName, PDWORD lpdwSize);
74static BOOL (WINAPI *pQueryFullProcessImageNameW)(HANDLE hProcess, DWORD dwFlags, LPWSTR lpExeName, PDWORD lpdwSize);
75static DWORD (WINAPI *pK32GetProcessImageFileNameA)(HANDLE,LPSTR,DWORD);
76static HANDLE (WINAPI *pCreateJobObjectW)(LPSECURITY_ATTRIBUTES sa, LPCWSTR name);
77static HANDLE (WINAPI *pOpenJobObjectA)(DWORD access, BOOL inherit, LPCSTR name);
78static BOOL (WINAPI *pAssignProcessToJobObject)(HANDLE job, HANDLE process);
79static BOOL (WINAPI *pIsProcessInJob)(HANDLE process, HANDLE job, PBOOL result);
80static BOOL (WINAPI *pTerminateJobObject)(HANDLE job, UINT exit_code);
81static BOOL (WINAPI *pQueryInformationJobObject)(HANDLE job, JOBOBJECTINFOCLASS class, LPVOID info, DWORD len, LPDWORD ret_len);
82static BOOL (WINAPI *pSetInformationJobObject)(HANDLE job, JOBOBJECTINFOCLASS class, LPVOID info, DWORD len);
83static HANDLE (WINAPI *pCreateIoCompletionPort)(HANDLE file, HANDLE existing_port, ULONG_PTR key, DWORD threads);
84static BOOL (WINAPI *pGetNumaProcessorNode)(UCHAR, PUCHAR);
85static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
86static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG);
87static NTSTATUS (WINAPI *pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS, void*, ULONG, void*, ULONG, ULONG*);
88static DWORD (WINAPI *pWTSGetActiveConsoleSessionId)(void);
89static HANDLE (WINAPI *pCreateToolhelp32Snapshot)(DWORD, DWORD);
90static BOOL (WINAPI *pProcess32First)(HANDLE, PROCESSENTRY32*);
91static BOOL (WINAPI *pProcess32Next)(HANDLE, PROCESSENTRY32*);
92static BOOL (WINAPI *pThread32First)(HANDLE, THREADENTRY32*);
93static BOOL (WINAPI *pThread32Next)(HANDLE, THREADENTRY32*);
95static SIZE_T (WINAPI *pGetLargePageMinimum)(void);
96static BOOL (WINAPI *pGetSystemCpuSetInformation)(SYSTEM_CPU_SET_INFORMATION*,ULONG,ULONG*,HANDLE,ULONG);
97static BOOL (WINAPI *pInitializeProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD, SIZE_T*);
98static BOOL (WINAPI *pUpdateProcThreadAttribute)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD_PTR, void *,SIZE_T,void*,SIZE_T*);
99static void (WINAPI *pDeleteProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*);
100static DWORD (WINAPI *pGetActiveProcessorCount)(WORD);
101static DWORD (WINAPI *pGetMaximumProcessorCount)(WORD);
102static BOOL (WINAPI *pGetProcessInformation)(HANDLE,PROCESS_INFORMATION_CLASS,void*,DWORD);
103
104/* ############################### */
105static char base[MAX_PATH];
106static char selfname[MAX_PATH];
107static char* exename;
108static char resfile[MAX_PATH];
109
110static int myARGC;
111static char** myARGV;
112
113/* As some environment variables get very long on Unix, we only test for
114 * the first 127 bytes.
115 * Note that increasing this value past 256 may exceed the buffer size
116 * limitations of the *Profile functions (at least on Wine).
117 */
118#define MAX_LISTED_ENV_VAR 128
119
120/* ---------------- portable memory allocation thingie */
121
122static char memory[1024*256];
123static char* memory_index = memory;
124
125static char* grab_memory(size_t len)
126{
127 char* ret = memory_index;
128 /* align on dword */
129 len = (len + 3) & ~3;
130 memory_index += len;
131 assert(memory_index <= memory + sizeof(memory));
132 return ret;
133}
134
135static void release_memory(void)
136{
138}
139
140/* ---------------- simplistic tool to encode/decode strings (to hide \ " ' and such) */
141
142static const char* encodeA(const char* str)
143{
144 char* ptr;
145 size_t len,i;
146
147 if (!str) return "";
148 len = strlen(str) + 1;
149 ptr = grab_memory(len * 2 + 1);
150 for (i = 0; i < len; i++)
151 sprintf(&ptr[i * 2], "%02x", (unsigned char)str[i]);
152 ptr[2 * len] = '\0';
153 return ptr;
154}
155
156static const char* encodeW(const WCHAR* str)
157{
158 char* ptr;
159 size_t len,i;
160
161 if (!str) return "";
162 len = lstrlenW(str) + 1;
163 ptr = grab_memory(len * 4 + 1);
164 assert(ptr);
165 for (i = 0; i < len; i++)
166 sprintf(&ptr[i * 4], "%04x", (unsigned int)(unsigned short)str[i]);
167 ptr[4 * len] = '\0';
168 return ptr;
169}
170
171static unsigned decode_char(char c)
172{
173 if (c >= '0' && c <= '9') return c - '0';
174 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
175 assert(c >= 'A' && c <= 'F');
176 return c - 'A' + 10;
177}
178
179static char* decodeA(const char* str)
180{
181 char* ptr;
182 size_t len,i;
183
184 len = strlen(str) / 2;
185 if (!len--) return NULL;
186 ptr = grab_memory(len + 1);
187 for (i = 0; i < len; i++)
188 ptr[i] = (decode_char(str[2 * i]) << 4) | decode_char(str[2 * i + 1]);
189 ptr[len] = '\0';
190 return ptr;
191}
192
193/* This will be needed to decode Unicode strings saved by the child process
194 * when we test Unicode functions.
195 */
196static WCHAR* decodeW(const char* str)
197{
198 size_t len;
199 WCHAR* ptr;
200 int i;
201
202 len = strlen(str) / 4;
203 if (!len--) return NULL;
204 ptr = (WCHAR*)grab_memory(len * 2 + 1);
205 for (i = 0; i < len; i++)
206 ptr[i] = (decode_char(str[4 * i]) << 12) |
207 (decode_char(str[4 * i + 1]) << 8) |
208 (decode_char(str[4 * i + 2]) << 4) |
209 (decode_char(str[4 * i + 3]) << 0);
210 ptr[len] = '\0';
211 return ptr;
212}
213
215{
219}
220
221static void reload_child_info(const char* resfile)
222{
223 /* This forces the profile functions to reload the resource file
224 * after the child process has modified it.
225 */
227}
228
229/******************************************************************
230 * init
231 *
232 * generates basic information like:
233 * base: absolute path to curr dir
234 * selfname: the way to reinvoke ourselves
235 * exename: executable without the path
236 * function-pointers, which are not implemented in all windows versions
237 */
238static BOOL init(void)
239{
240 char *p;
241
243 if (!GetCurrentDirectoryA(sizeof(base), base)) return FALSE;
244 GetModuleFileNameA( 0, selfname, sizeof(selfname) );
245
246 /* Strip the path of selfname */
247 if ((p = strrchr(selfname, '\\')) != NULL) exename = p + 1;
248 else exename = selfname;
249
250 if ((p = strrchr(exename, '/')) != NULL) exename = p + 1;
251
252 hkernel32 = GetModuleHandleA("kernel32");
253 hntdll = GetModuleHandleA("ntdll.dll");
254
255 pNtQueryInformationProcess = (void *)GetProcAddress(hntdll, "NtQueryInformationProcess");
256 pNtQueryInformationThread = (void *)GetProcAddress(hntdll, "NtQueryInformationThread");
257 pNtQuerySystemInformationEx = (void *)GetProcAddress(hntdll, "NtQuerySystemInformationEx");
258
259 pGetNativeSystemInfo = (void *) GetProcAddress(hkernel32, "GetNativeSystemInfo");
260 pGetSystemRegistryQuota = (void *) GetProcAddress(hkernel32, "GetSystemRegistryQuota");
261 pIsWow64Process = (void *) GetProcAddress(hkernel32, "IsWow64Process");
262 pIsWow64Process2 = (void *) GetProcAddress(hkernel32, "IsWow64Process2");
263 pQueryFullProcessImageNameA = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameA");
264 pQueryFullProcessImageNameW = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameW");
265 pK32GetProcessImageFileNameA = (void *) GetProcAddress(hkernel32, "K32GetProcessImageFileNameA");
266 pCreateJobObjectW = (void *)GetProcAddress(hkernel32, "CreateJobObjectW");
267 pOpenJobObjectA = (void *)GetProcAddress(hkernel32, "OpenJobObjectA");
268 pAssignProcessToJobObject = (void *)GetProcAddress(hkernel32, "AssignProcessToJobObject");
269 pIsProcessInJob = (void *)GetProcAddress(hkernel32, "IsProcessInJob");
270 pTerminateJobObject = (void *)GetProcAddress(hkernel32, "TerminateJobObject");
271 pQueryInformationJobObject = (void *)GetProcAddress(hkernel32, "QueryInformationJobObject");
272 pSetInformationJobObject = (void *)GetProcAddress(hkernel32, "SetInformationJobObject");
273 pCreateIoCompletionPort = (void *)GetProcAddress(hkernel32, "CreateIoCompletionPort");
274 pGetNumaProcessorNode = (void *)GetProcAddress(hkernel32, "GetNumaProcessorNode");
275 pWTSGetActiveConsoleSessionId = (void *)GetProcAddress(hkernel32, "WTSGetActiveConsoleSessionId");
276 pCreateToolhelp32Snapshot = (void *)GetProcAddress(hkernel32, "CreateToolhelp32Snapshot");
277 pProcess32First = (void *)GetProcAddress(hkernel32, "Process32First");
278 pProcess32Next = (void *)GetProcAddress(hkernel32, "Process32Next");
279 pThread32First = (void *)GetProcAddress(hkernel32, "Thread32First");
280 pThread32Next = (void *)GetProcAddress(hkernel32, "Thread32Next");
281 pGetLogicalProcessorInformationEx = (void *)GetProcAddress(hkernel32, "GetLogicalProcessorInformationEx");
282 pGetLargePageMinimum = (void *)GetProcAddress(hkernel32, "GetLargePageMinimum");
283 pGetSystemCpuSetInformation = (void *)GetProcAddress(hkernel32, "GetSystemCpuSetInformation");
284 pInitializeProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "InitializeProcThreadAttributeList");
285 pUpdateProcThreadAttribute = (void *)GetProcAddress(hkernel32, "UpdateProcThreadAttribute");
286 pDeleteProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "DeleteProcThreadAttributeList");
287 pGetActiveProcessorCount = (void *)GetProcAddress(hkernel32, "GetActiveProcessorCount");
288 pGetMaximumProcessorCount = (void *)GetProcAddress(hkernel32, "GetMaximumProcessorCount");
289 pGetProcessInformation = (void *)GetProcAddress(hkernel32, "GetProcessInformation");
290
291 return TRUE;
292}
293
294/******************************************************************
295 * get_file_name
296 *
297 * generates an absolute file_name for temporary file
298 *
299 */
300static void get_file_name(char* buf)
301{
302 char path[MAX_PATH];
303
304 buf[0] = '\0';
305 GetTempPathA(sizeof(path), path);
306 GetTempFileNameA(path, "wt", 0, buf);
307}
308
309/******************************************************************
310 * static void childPrintf
311 *
312 */
313static void WINAPIV __WINE_PRINTF_ATTR(2,3) childPrintf(HANDLE h, const char* fmt, ...)
314{
316 char buffer[1024+4*MAX_LISTED_ENV_VAR];
317 DWORD w;
318
321 va_end(valist);
323}
324
325/* bits 0..1 contains FILE_TYPE_{UNKNOWN, CHAR, PIPE, DISK} */
326#if defined(__REACTOS__) && defined(_WIN64)
327/* This appears to be what HATTR_NULL resolves to on Windows x64 for native (not WoW) processes.
328 * It may be:
329 * HATTR_NULL (x86) | HATTR_INVALID | 0x01 */
330#define HATTR_NULL 0x0d /* NULL handle value */
331#else
332#define HATTR_NULL 0x08 /* NULL handle value */
333#endif
334#define HATTR_INVALID 0x04 /* INVALID_HANDLE_VALUE */
335#define HATTR_TYPE 0x0c /* valid handle, with type set */
336#define HATTR_UNTOUCHED 0x10 /* Identify fields untouched by GetStartupInfoW */
337#define HATTR_INHERIT 0x20 /* inheritance flag set */
338#define HATTR_PROTECT 0x40 /* protect from close flag set */
339#define HATTR_DANGLING 0x80 /* a pseudo value to show that the handle value has been copied but not inherited */
340
341#define HANDLE_UNTOUCHEDW (HANDLE)(DWORD_PTR)(0x5050505050505050ull)
342
344{
345 DWORD dw;
346 unsigned result;
347
348 if (h == NULL)
350 else if (h == INVALID_HANDLE_VALUE)
352 else if (h == HANDLE_UNTOUCHEDW)
354 else
355 {
357 dw = GetFileType(h);
359 {
360 DWORD info;
362 {
367 }
368 }
369 else
371 result |= dw;
372 }
373 return result;
374}
375
376/******************************************************************
377 * doChild
378 *
379 * output most of the information in the child process
380 */
381static void doChild(const char* file, const char* option)
382{
383 RTL_USER_PROCESS_PARAMETERS *params = NtCurrentTeb()->Peb->ProcessParameters;
384 STARTUPINFOA siA;
385 STARTUPINFOW siW;
386 int i;
387 char *ptrA, *ptrA_save;
388 WCHAR *ptrW, *ptrW_save;
389 char bufA[MAX_PATH];
390 WCHAR bufW[MAX_PATH];
394 BOOL ret;
395
396 if (hFile == INVALID_HANDLE_VALUE) return;
397
398 /* output of startup info (Ansi) */
399 memset(&siA, 0xA0, sizeof(siA));
400 GetStartupInfoA(&siA);
401 childPrintf(hFile,
402 "[StartupInfoA]\ncb=%08lu\nlpDesktop=%s\nlpTitle=%s\n"
403 "dwX=%lu\ndwY=%lu\ndwXSize=%lu\ndwYSize=%lu\n"
404 "dwXCountChars=%lu\ndwYCountChars=%lu\ndwFillAttribute=%lu\n"
405 "dwFlags=%lu\nwShowWindow=%u\n"
406 "hStdInput=%Iu\nhStdOutput=%Iu\nhStdError=%Iu\n"
407 "hStdInputEncode=%u\nhStdOutputEncode=%u\nhStdErrorEncode=%u\n\n",
408 siA.cb, encodeA(siA.lpDesktop), encodeA(siA.lpTitle),
409 siA.dwX, siA.dwY, siA.dwXSize, siA.dwYSize,
411 siA.dwFlags, siA.wShowWindow,
415
416 /* check the console handles in the TEB */
417 childPrintf(hFile,
418 "[TEB]\nhStdInput=%Iu\nhStdOutput=%Iu\nhStdError=%Iu\n"
419 "hStdInputEncode=%u\nhStdOutputEncode=%u\nhStdErrorEncode=%u\n\n",
420 (DWORD_PTR)params->hStdInput, (DWORD_PTR)params->hStdOutput,
421 (DWORD_PTR)params->hStdError,
423 encode_handle_attributes(params->hStdError));
424
425 memset(&siW, 0x50, sizeof(siW));
426 GetStartupInfoW(&siW);
427 childPrintf(hFile,
428 "[StartupInfoW]\ncb=%08lu\nlpDesktop=%s\nlpTitle=%s\n"
429 "dwX=%lu\ndwY=%lu\ndwXSize=%lu\ndwYSize=%lu\n"
430 "dwXCountChars=%lu\ndwYCountChars=%lu\ndwFillAttribute=%lu\n"
431 "dwFlags=%lu\nwShowWindow=%u\n"
432 "hStdInput=%Iu\nhStdOutput=%Iu\nhStdError=%Iu\n"
433 "hStdInputEncode=%u\nhStdOutputEncode=%u\nhStdErrorEncode=%u\n\n",
434 siW.cb, encodeW(siW.lpDesktop), encodeW(siW.lpTitle),
435 siW.dwX, siW.dwY, siW.dwXSize, siW.dwYSize,
437 siW.dwFlags, siW.wShowWindow,
441
442 /* Arguments */
443 childPrintf(hFile, "[Arguments]\nargcA=%d\n", myARGC);
444 for (i = 0; i < myARGC; i++)
445 {
446 childPrintf(hFile, "argvA%d=%s\n", i, encodeA(myARGV[i]));
447 }
448 childPrintf(hFile, "CommandLineA=%s\n", encodeA(GetCommandLineA()));
449 childPrintf(hFile, "CommandLineW=%s\n\n", encodeW(GetCommandLineW()));
450
451 /* output toolhelp information */
452 snapshot = pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
453 ok(snapshot != INVALID_HANDLE_VALUE, "CreateToolhelp32Snapshot failed %lu\n", GetLastError());
454 memset(&pe, 0, sizeof(pe));
455 pe.dwSize = sizeof(pe);
456 if (pProcess32First(snapshot, &pe))
457 {
458 while (pe.th32ProcessID != GetCurrentProcessId())
459 if (!pProcess32Next(snapshot, &pe)) break;
460 }
462#if !defined(__REACTOS__) || !defined(_WIN64) // This doesn't work on x86_64, all Windows versions.
463 ok(pe.th32ProcessID == GetCurrentProcessId(), "failed to find current process in snapshot\n");
464#endif
465 childPrintf(hFile,
466 "[Toolhelp]\ncntUsage=%lu\nth32DefaultHeapID=%Iu\n"
467 "th32ModuleID=%lu\ncntThreads=%lu\nth32ParentProcessID=%lu\n"
468 "pcPriClassBase=%lu\ndwFlags=%lu\nszExeFile=%s\n\n",
471 pe.dwFlags, encodeA(pe.szExeFile));
472
473 /* output of environment (Ansi) */
474 ptrA_save = ptrA = GetEnvironmentStringsA();
475 if (ptrA)
476 {
478
479 childPrintf(hFile, "[EnvironmentA]\n");
480 i = 0;
481 while (*ptrA)
482 {
484 childPrintf(hFile, "env%d=%s\n", i, encodeA(env_var));
485 i++;
486 ptrA += strlen(ptrA) + 1;
487 }
488 childPrintf(hFile, "len=%d\n\n", i);
489 FreeEnvironmentStringsA(ptrA_save);
490 }
491
492 /* output of environment (Unicode) */
493 ptrW_save = ptrW = GetEnvironmentStringsW();
494 if (ptrW)
495 {
497
498 childPrintf(hFile, "[EnvironmentW]\n");
499 i = 0;
500 while (*ptrW)
501 {
503 env_var[MAX_LISTED_ENV_VAR - 1] = '\0';
504 childPrintf(hFile, "env%d=%s\n", i, encodeW(env_var));
505 i++;
506 ptrW += lstrlenW(ptrW) + 1;
507 }
508 childPrintf(hFile, "len=%d\n\n", i);
509 FreeEnvironmentStringsW(ptrW_save);
510 }
511
512 childPrintf(hFile, "[Misc]\n");
513 if (GetCurrentDirectoryA(sizeof(bufA), bufA))
514 childPrintf(hFile, "CurrDirA=%s\n", encodeA(bufA));
515 if (GetCurrentDirectoryW(ARRAY_SIZE(bufW), bufW))
516 childPrintf(hFile, "CurrDirW=%s\n", encodeW(bufW));
517 childPrintf(hFile, "\n");
518
519 if (option && strcmp(option, "console") == 0)
520 {
524 DWORD modeIn, modeOut;
525
526 childPrintf(hFile, "[Console]\n");
527 if (GetConsoleScreenBufferInfo(hConOut, &sbi))
528 {
529 childPrintf(hFile, "SizeX=%d\nSizeY=%d\nCursorX=%d\nCursorY=%d\nAttributes=%d\n",
531 childPrintf(hFile, "winLeft=%d\nwinTop=%d\nwinRight=%d\nwinBottom=%d\n",
533 childPrintf(hFile, "maxWinWidth=%d\nmaxWinHeight=%d\n",
535 }
536 childPrintf(hFile, "InputCP=%d\nOutputCP=%d\n",
538 if (GetConsoleMode(hConIn, &modeIn))
539 childPrintf(hFile, "InputMode=%lu\n", modeIn);
540 if (GetConsoleMode(hConOut, &modeOut))
541 childPrintf(hFile, "OutputMode=%lu\n", modeOut);
542
543 /* now that we have written all relevant information, let's change it */
544 SetLastError(0xdeadbeef);
545 ret = SetConsoleCP(1252);
547 {
548 win_skip("Setting the codepage is not implemented\n");
549 }
550 else
551 {
552 ok(ret, "Setting CP\n");
553 ok(SetConsoleOutputCP(1252), "Setting SB CP\n");
554 }
555
556 ret = SetConsoleMode(hConIn, modeIn ^ 1);
557 ok( ret, "Setting mode (%ld)\n", GetLastError());
558 ret = SetConsoleMode(hConOut, modeOut ^ 1);
559 ok( ret, "Setting mode (%ld)\n", GetLastError());
563 ok( ret, "Setting cursor position (%ld)\n", GetLastError());
564 }
565 if (option && strcmp(option, "stdhandle") == 0)
566 {
569
571 {
572 char buf[1024];
573 DWORD r, w;
574
575 ok(ReadFile(hStdIn, buf, sizeof(buf), &r, NULL) && r > 0, "Reading message from input pipe\n");
576 childPrintf(hFile, "[StdHandle]\nmsg=%s\n\n", encodeA(buf));
577 ok(WriteFile(hStdOut, buf, r, &w, NULL) && w == r, "Writing message to output pipe\n");
578 }
579 }
580
581 if (option && strcmp(option, "exit_code") == 0)
582 {
583 childPrintf(hFile, "[ExitCode]\nvalue=%d\n\n", 123);
585 ExitProcess(123);
586 }
587
589}
590
591static char* getChildString(const char* sect, const char* key)
592{
593 char buf[1024+4*MAX_LISTED_ENV_VAR];
594 char* ret;
595
596 GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), resfile);
597 if (buf[0] == '\0' || (buf[0] == '-' && buf[1] == '\0')) return NULL;
598 assert(!(strlen(buf) & 1));
599 ret = decodeA(buf);
600 return ret;
601}
602
603static WCHAR* getChildStringW(const char* sect, const char* key)
604{
605 char buf[1024+4*MAX_LISTED_ENV_VAR];
606 WCHAR* ret;
607
608 GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), resfile);
609 if (buf[0] == '\0' || (buf[0] == '-' && buf[1] == '\0')) return NULL;
610 assert(!(strlen(buf) & 1));
611 ret = decodeW(buf);
612 return ret;
613}
614
615static int strCmp(const char* s1, const char* s2, BOOL sensitive)
616{
617 if (!s1 && !s2) return 0;
618 if (!s2) return -1;
619 if (!s1) return 1;
620 return (sensitive) ? strcmp(s1, s2) : strcasecmp(s1, s2);
621}
622
623static void ok_child_string( int line, const char *sect, const char *key,
624 const char *expect, int sensitive )
625{
626 char* result = getChildString( sect, key );
627 ok_(__FILE__, line)( strCmp(result, expect, sensitive) == 0, "%s:%s expected '%s', got '%s'\n",
628 sect, key, expect ? expect : "(null)", result );
629}
630
631static void ok_child_stringWA( int line, const char *sect, const char *key,
632 const char *expect, int sensitive )
633{
634 WCHAR* expectW;
635 CHAR* resultA;
636 DWORD len;
637 WCHAR* result = getChildStringW( sect, key );
638
639 len = MultiByteToWideChar( CP_ACP, 0, expect, -1, NULL, 0);
640 expectW = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
641 MultiByteToWideChar( CP_ACP, 0, expect, -1, expectW, len);
642
644 resultA = HeapAlloc(GetProcessHeap(),0,len*sizeof(CHAR));
645 WideCharToMultiByte( CP_ACP, 0, result, -1, resultA, len, NULL, NULL);
646
647 if (sensitive)
648 ok_(__FILE__, line)( lstrcmpW(result, expectW) == 0, "%s:%s expected '%s', got '%s'\n",
649 sect, key, expect ? expect : "(null)", resultA );
650 else
651 ok_(__FILE__, line)( lstrcmpiW(result, expectW) == 0, "%s:%s expected '%s', got '%s'\n",
652 sect, key, expect ? expect : "(null)", resultA );
653 HeapFree(GetProcessHeap(),0,expectW);
654 HeapFree(GetProcessHeap(),0,resultA);
655}
656
657static void ok_child_int( int line, const char *sect, const char *key, UINT expect )
658{
660 ok_(__FILE__, line)( result == expect, "%s:%s expected %u, but got %u\n", sect, key, expect, result );
661}
662
663static void ok_child_hexint( int line, const char *sect, const char *key, UINT expect, UINT is_broken )
664{
666 ok_(__FILE__, line)( result == expect || broken( is_broken && result == is_broken ), "%s:%s expected %#x, but got %#x\n", sect, key, expect, result );
667}
668
669#define okChildString(sect, key, expect) ok_child_string(__LINE__, (sect), (key), (expect), 1 )
670#define okChildIString(sect, key, expect) ok_child_string(__LINE__, (sect), (key), (expect), 0 )
671#define okChildStringWA(sect, key, expect) ok_child_stringWA(__LINE__, (sect), (key), (expect), 1 )
672#define okChildInt(sect, key, expect) ok_child_int(__LINE__, (sect), (key), (expect))
673#define okChildHexInt(sect, key, expect, is_broken) ok_child_hexint(__LINE__, (sect), (key), (expect), (is_broken))
674
675static void test_Startup(void)
676{
677 char buffer[2 * MAX_PATH + 25];
680 char *result;
681 static CHAR title[] = "I'm the title string",
682 desktop[] = "winsta0\\default",
683 empty[] = "";
684
685 /* let's start simplistic */
686 memset(&startup, 0, sizeof(startup));
687 startup.cb = sizeof(startup);
689 startup.wShowWindow = SW_SHOWNORMAL;
690
692 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
693 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
695
698 okChildInt("StartupInfoA", "cb", startup.cb);
699 okChildString("StartupInfoA", "lpDesktop", si.lpDesktop);
700 okChildInt("StartupInfoA", "dwX", startup.dwX);
701 okChildInt("StartupInfoA", "dwY", startup.dwY);
702 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
703 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
704 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
705 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
706 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
707 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
708 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
711
712 /* not so simplistic now */
713 memset(&startup, 0, sizeof(startup));
714 startup.cb = sizeof(startup);
716 startup.wShowWindow = SW_SHOWNORMAL;
717 startup.lpTitle = title;
718 startup.lpDesktop = desktop;
719 startup.dwXCountChars = 0x12121212;
720 startup.dwYCountChars = 0x23232323;
721 startup.dwX = 0x34343434;
722 startup.dwY = 0x45454545;
723 startup.dwXSize = 0x56565656;
724 startup.dwYSize = 0x67676767;
725 startup.dwFillAttribute = 0xA55A;
726
728 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
729 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
731
733 okChildInt("StartupInfoA", "cb", startup.cb);
734 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
735 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
736 okChildInt("StartupInfoA", "dwX", startup.dwX);
737 okChildInt("StartupInfoA", "dwY", startup.dwY);
738 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
739 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
740 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
741 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
742 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
743 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
744 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
747
748 /* not so simplistic now */
749 memset(&startup, 0, sizeof(startup));
750 startup.cb = sizeof(startup);
752 startup.wShowWindow = SW_SHOWNORMAL;
753 startup.lpTitle = title;
754 startup.lpDesktop = NULL;
755 startup.dwXCountChars = 0x12121212;
756 startup.dwYCountChars = 0x23232323;
757 startup.dwX = 0x34343434;
758 startup.dwY = 0x45454545;
759 startup.dwXSize = 0x56565656;
760 startup.dwYSize = 0x67676767;
761 startup.dwFillAttribute = 0xA55A;
762
764 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
765 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
767
769 okChildInt("StartupInfoA", "cb", startup.cb);
770 okChildString("StartupInfoA", "lpDesktop", si.lpDesktop);
771 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
772 okChildInt("StartupInfoA", "dwX", startup.dwX);
773 okChildInt("StartupInfoA", "dwY", startup.dwY);
774 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
775 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
776 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
777 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
778 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
779 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
780 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
783
784 /* not so simplistic now */
785 memset(&startup, 0, sizeof(startup));
786 startup.cb = sizeof(startup);
788 startup.wShowWindow = SW_SHOWNORMAL;
789 startup.lpTitle = title;
790 startup.lpDesktop = empty;
791 startup.dwXCountChars = 0x12121212;
792 startup.dwYCountChars = 0x23232323;
793 startup.dwX = 0x34343434;
794 startup.dwY = 0x45454545;
795 startup.dwXSize = 0x56565656;
796 startup.dwYSize = 0x67676767;
797 startup.dwFillAttribute = 0xA55A;
798
800 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
801 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
803
805 okChildInt("StartupInfoA", "cb", startup.cb);
806 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
807 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
808 okChildInt("StartupInfoA", "dwX", startup.dwX);
809 okChildInt("StartupInfoA", "dwY", startup.dwY);
810 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
811 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
812 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
813 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
814 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
815 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
816 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
819
820 /* not so simplistic now */
821 memset(&startup, 0, sizeof(startup));
822 startup.cb = sizeof(startup);
824 startup.wShowWindow = SW_SHOWNORMAL;
825 startup.lpTitle = NULL;
826 startup.lpDesktop = desktop;
827 startup.dwXCountChars = 0x12121212;
828 startup.dwYCountChars = 0x23232323;
829 startup.dwX = 0x34343434;
830 startup.dwY = 0x45454545;
831 startup.dwXSize = 0x56565656;
832 startup.dwYSize = 0x67676767;
833 startup.dwFillAttribute = 0xA55A;
834
836 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
837 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
839
841 okChildInt("StartupInfoA", "cb", startup.cb);
842 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
843 result = getChildString( "StartupInfoA", "lpTitle" );
844 ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
845 "expected '%s' or null, got '%s'\n", selfname, result );
846 okChildInt("StartupInfoA", "dwX", startup.dwX);
847 okChildInt("StartupInfoA", "dwY", startup.dwY);
848 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
849 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
850 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
851 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
852 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
853 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
854 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
857
858 /* not so simplistic now */
859 memset(&startup, 0, sizeof(startup));
860 startup.cb = sizeof(startup);
862 startup.wShowWindow = SW_SHOWNORMAL;
863 startup.lpTitle = empty;
864 startup.lpDesktop = desktop;
865 startup.dwXCountChars = 0x12121212;
866 startup.dwYCountChars = 0x23232323;
867 startup.dwX = 0x34343434;
868 startup.dwY = 0x45454545;
869 startup.dwXSize = 0x56565656;
870 startup.dwYSize = 0x67676767;
871 startup.dwFillAttribute = 0xA55A;
872
874 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
875 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
877
879 okChildInt("StartupInfoA", "cb", startup.cb);
880 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
881 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
882 okChildInt("StartupInfoA", "dwX", startup.dwX);
883 okChildInt("StartupInfoA", "dwY", startup.dwY);
884 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
885 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
886 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
887 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
888 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
889 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
890 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
893
894 /* not so simplistic now */
895 memset(&startup, 0, sizeof(startup));
896 startup.cb = sizeof(startup);
898 startup.wShowWindow = SW_SHOWNORMAL;
899 startup.lpTitle = empty;
900 startup.lpDesktop = empty;
901 startup.dwXCountChars = 0x12121212;
902 startup.dwYCountChars = 0x23232323;
903 startup.dwX = 0x34343434;
904 startup.dwY = 0x45454545;
905 startup.dwXSize = 0x56565656;
906 startup.dwYSize = 0x67676767;
907 startup.dwFillAttribute = 0xA55A;
908
910 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
911 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
913
915 okChildInt("StartupInfoA", "cb", startup.cb);
916 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
917 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
918 okChildInt("StartupInfoA", "dwX", startup.dwX);
919 okChildInt("StartupInfoA", "dwY", startup.dwY);
920 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
921 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
922 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
923 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
924 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
925 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
926 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
929
930 /* TODO: test for A/W and W/A and W/W */
931}
932
933static void test_CommandLine(void)
934{
935 char buffer[2 * MAX_PATH + 65], fullpath[MAX_PATH], *lpFilePart, *p;
936 char buffer2[MAX_PATH + 44];
939 BOOL ret;
940 LPWSTR cmdline, cmdline_backup;
941
942 memset(&startup, 0, sizeof(startup));
943 startup.cb = sizeof(startup);
945 startup.wShowWindow = SW_SHOWNORMAL;
946
947 /* failure case */
948 strcpy(buffer, "\"t:\\NotADir\\NotAFile.exe\"");
949 memset(&info, 0xa, sizeof(info));
950 ok(!CreateProcessA(buffer, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess unexpectedly succeeded\n");
951 /* Check that the effective STARTUPINFOA parameters are not modified */
952 ok(startup.cb == sizeof(startup), "unexpected cb %ld\n", startup.cb);
953 ok(startup.lpDesktop == NULL, "lpDesktop is not NULL\n");
954 ok(startup.lpTitle == NULL, "lpTitle is not NULL\n");
955 ok(startup.dwFlags == STARTF_USESHOWWINDOW, "unexpected dwFlags %04lx\n", startup.dwFlags);
956 ok(startup.wShowWindow == SW_SHOWNORMAL, "unexpected wShowWindow %d\n", startup.wShowWindow);
957 ok(!info.hProcess, "unexpected hProcess %p\n", info.hProcess);
958 ok(!info.hThread, "unexpected hThread %p\n", info.hThread);
959 ok(!info.dwProcessId, "unexpected dwProcessId %04lx\n", info.dwProcessId);
960 ok(!info.dwThreadId, "unexpected dwThreadId %04lx\n", info.dwThreadId);
961
962 /* the basics; not getting confused by the leading and trailing " */
964 sprintf(buffer, "\"%s\" process dump \"%s\" \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
965 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
966 /* Check that the effective STARTUPINFOA parameters are not modified */
967 ok(startup.cb == sizeof(startup), "unexpected cb %ld\n", startup.cb);
968 ok(startup.lpDesktop == NULL, "lpDesktop is not NULL\n");
969 ok(startup.lpTitle == NULL, "lpTitle is not NULL\n");
970 ok(startup.dwFlags == STARTF_USESHOWWINDOW, "unexpected dwFlags %04lx\n", startup.dwFlags);
971 ok(startup.wShowWindow == SW_SHOWNORMAL, "unexpected wShowWindow %d\n", startup.wShowWindow);
973
975 okChildInt("Arguments", "argcA", 5);
976 okChildString("Arguments", "argvA4", "C:\\Program Files\\my nice app.exe");
977 okChildString("Arguments", "argvA5", NULL);
978 okChildString("Arguments", "CommandLineA", buffer);
981
982 /* test main()'s quotes handling */
984 sprintf(buffer, "\"%s\" process dump \"%s\" \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
985 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
987
989 okChildInt("Arguments", "argcA", 7);
990 okChildString("Arguments", "argvA4", "a\"b\\");
991 okChildString("Arguments", "argvA5", "c\"");
992 okChildString("Arguments", "argvA6", "d");
993 okChildString("Arguments", "argvA7", NULL);
994 okChildString("Arguments", "CommandLineA", buffer);
997
999 assert ( lpFilePart != 0);
1000 *(lpFilePart -1 ) = 0;
1001 SetCurrentDirectoryA( fullpath );
1002
1003 /* Test for Bug1330 to show that XP doesn't change '/' to '\\' in argv[0]
1004 * and " escaping.
1005 */
1007 /* Use exename to avoid buffer containing things like 'C:' */
1008 sprintf(buffer, "./%s process dump \"%s\" \"\"\"\"", exename, resfile);
1009 SetLastError(0xdeadbeef);
1011 ok(ret, "CreateProcess (%s) failed : %ld\n", buffer, GetLastError());
1013
1015 sprintf(buffer, "./%s", exename);
1016 okChildInt("Arguments", "argcA", 5);
1017 okChildString("Arguments", "argvA0", buffer);
1018 okChildString("Arguments", "argvA4", "\"");
1019 okChildString("Arguments", "argvA5", NULL);
1022
1024 /* Use exename to avoid buffer containing things like 'C:' */
1025 sprintf(buffer, ".\\%s process dump \"%s\"", exename, resfile);
1026 SetLastError(0xdeadbeef);
1028 ok(ret, "CreateProcess (%s) failed : %ld\n", buffer, GetLastError());
1030
1032 sprintf(buffer, ".\\%s", exename);
1033 okChildString("Arguments", "argvA0", buffer);
1036
1038 p = strrchr(fullpath, '\\');
1039 /* Use exename to avoid buffer containing things like 'C:' */
1040 if (p) sprintf(buffer, "..%s/%s process dump \"%s\"", p, exename, resfile);
1041 else sprintf(buffer, "./%s process dump \"%s\"", exename, resfile);
1042 SetLastError(0xdeadbeef);
1044 ok(ret, "CreateProcess (%s) failed : %ld\n", buffer, GetLastError());
1046
1048 if (p) sprintf(buffer, "..%s/%s", p, exename);
1049 else sprintf(buffer, "./%s", exename);
1050 okChildString("Arguments", "argvA0", buffer);
1053
1054 /* Using AppName */
1057 assert ( lpFilePart != 0);
1058 *(lpFilePart -1 ) = 0;
1059 p = strrchr(fullpath, '\\');
1060 /* Use exename to avoid buffer containing things like 'C:' */
1061 if (p) sprintf(buffer, "..%s/%s", p, exename);
1062 else sprintf(buffer, "./%s", exename);
1063 sprintf(buffer2, "dummy process dump \"%s\"", resfile);
1064 SetLastError(0xdeadbeef);
1065 ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
1066 ok(ret, "CreateProcess (%s) failed : %ld\n", buffer, GetLastError());
1068
1070 okChildString("Arguments", "argvA0", "dummy");
1071 okChildString("Arguments", "CommandLineA", buffer2);
1072 okChildStringWA("Arguments", "CommandLineW", buffer2);
1076
1077 if (0) /* Test crashes on NT-based Windows. */
1078 {
1079 /* Test NULL application name and command line parameters. */
1080 SetLastError(0xdeadbeef);
1082 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1084 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1085 }
1086
1087 buffer[0] = '\0';
1088
1089 /* Test empty application name parameter. */
1090 SetLastError(0xdeadbeef);
1092 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1094 broken(GetLastError() == ERROR_FILE_NOT_FOUND) /* Win9x/WinME */ ||
1095 broken(GetLastError() == ERROR_ACCESS_DENIED) /* Win98 */,
1096 "Expected ERROR_PATH_NOT_FOUND, got %ld\n", GetLastError());
1097
1098 buffer2[0] = '\0';
1099
1100 /* Test empty application name and command line parameters. */
1101 SetLastError(0xdeadbeef);
1102 ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
1103 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1105 broken(GetLastError() == ERROR_FILE_NOT_FOUND) /* Win9x/WinME */ ||
1106 broken(GetLastError() == ERROR_ACCESS_DENIED) /* Win98 */,
1107 "Expected ERROR_PATH_NOT_FOUND, got %ld\n", GetLastError());
1108
1109 /* Test empty command line parameter. */
1110 SetLastError(0xdeadbeef);
1111 ret = CreateProcessA(NULL, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
1112 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1114 GetLastError() == ERROR_PATH_NOT_FOUND /* NT4 */ ||
1115 GetLastError() == ERROR_BAD_PATHNAME /* Win98 */ ||
1116 GetLastError() == ERROR_INVALID_PARAMETER /* Win7 */,
1117 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
1118
1119 strcpy(buffer, "doesnotexist.exe");
1120 strcpy(buffer2, "does not exist.exe");
1121
1122 /* Test nonexistent application name. */
1123 SetLastError(0xdeadbeef);
1125 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1126 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
1127
1128 SetLastError(0xdeadbeef);
1129 ret = CreateProcessA(buffer2, NULL, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
1130 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1131 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
1132
1133 /* Test nonexistent command line parameter. */
1134 SetLastError(0xdeadbeef);
1136 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1137 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
1138
1139 SetLastError(0xdeadbeef);
1140 ret = CreateProcessA(NULL, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
1141 ok(!ret, "CreateProcessA unexpectedly succeeded\n");
1142 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
1143
1144 /* Test whether GetCommandLineW reads directly from TEB or from a cached address */
1146 ok(cmdline == NtCurrentTeb()->Peb->ProcessParameters->CommandLine.Buffer, "Expected address from TEB, got %p\n", cmdline);
1147
1148 cmdline_backup = cmdline;
1149 NtCurrentTeb()->Peb->ProcessParameters->CommandLine.Buffer = NULL;
1151 ok(cmdline == cmdline_backup, "Expected cached address from TEB, got %p\n", cmdline);
1152 NtCurrentTeb()->Peb->ProcessParameters->CommandLine.Buffer = cmdline_backup;
1153}
1154
1155static void test_Directory(void)
1156{
1157 char buffer[2 * MAX_PATH + 25];
1160 char windir[MAX_PATH];
1161 static CHAR cmdline[] = "winver.exe";
1162
1163 memset(&startup, 0, sizeof(startup));
1164 startup.cb = sizeof(startup);
1165 startup.dwFlags = STARTF_USESHOWWINDOW;
1166 startup.wShowWindow = SW_SHOWNORMAL;
1167
1168 /* the basics */
1170 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
1171 GetWindowsDirectoryA( windir, sizeof(windir) );
1172 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, windir, &startup, &info), "CreateProcess\n");
1174
1176 okChildIString("Misc", "CurrDirA", windir);
1179
1180 /* search PATH for the exe if directory is NULL */
1181 ok(CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
1182 ok(TerminateProcess(info.hProcess, 0), "Child process termination\n");
1183 CloseHandle(info.hThread);
1184 CloseHandle(info.hProcess);
1185
1186 /* if any directory is provided, don't search PATH, error on bad directory */
1187 SetLastError(0xdeadbeef);
1188 memset(&info, 0, sizeof(info));
1190 NULL, "non\\existent\\directory", &startup, &info), "CreateProcess\n");
1191 ok(GetLastError() == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %ld\n", GetLastError());
1192 ok(!TerminateProcess(info.hProcess, 0), "Child process should not exist\n");
1193}
1194
1195static void test_Toolhelp(void)
1196{
1197#if defined(__REACTOS__) && defined(_WIN64)
1198 skip("test_Toolhelp() times out on x86_64.\n");
1199#else
1200 char buffer[2 * MAX_PATH + 27];
1204 DWORD nested_pid;
1205 PROCESSENTRY32 pe;
1206 THREADENTRY32 te;
1207 DWORD ret;
1208 int i;
1209
1210 memset(&startup, 0, sizeof(startup));
1211 startup.cb = sizeof(startup);
1212 startup.dwFlags = STARTF_USESHOWWINDOW;
1213 startup.wShowWindow = SW_SHOWNORMAL;
1214
1216 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
1217 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess failed\n");
1219
1221 okChildInt("Toolhelp", "cntUsage", 0);
1222 okChildInt("Toolhelp", "th32DefaultHeapID", 0);
1223 okChildInt("Toolhelp", "th32ModuleID", 0);
1224 okChildInt("Toolhelp", "th32ParentProcessID", GetCurrentProcessId());
1225 /* pcPriClassBase differs between Windows versions (either 6 or 8) */
1226 okChildInt("Toolhelp", "dwFlags", 0);
1227
1230
1232 sprintf(buffer, "\"%s\" process nested \"%s\"", selfname, resfile);
1233 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess failed\n");
1234 wait_child_process(info.hProcess);
1235
1237 ok(process != NULL, "OpenProcess failed %lu\n", GetLastError());
1239
1240 CloseHandle(info.hProcess);
1241 CloseHandle(info.hThread);
1242
1243 for (i = 0; i < 20; i++)
1244 {
1245 SetLastError(0xdeadbeef);
1247 ok(process || GetLastError() == ERROR_INVALID_PARAMETER, "OpenProcess failed %lu\n", GetLastError());
1248 if (!process) break;
1250 Sleep(100);
1251 }
1252 /* The following test fails randomly on some Windows versions, but Gothic 2 depends on it */
1253 ok(i < 20 || broken(i == 20), "process object not released\n");
1254
1255 /* Look for the nested process by pid */
1257 nested_pid = GetPrivateProfileIntA("Nested", "Pid", 0, resfile);
1259
1260 snapshot = pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1261 ok(snapshot != INVALID_HANDLE_VALUE, "CreateToolhelp32Snapshot failed %lu\n", GetLastError());
1262 memset(&pe, 0, sizeof(pe));
1263 pe.dwSize = sizeof(pe);
1264 if (pProcess32First(snapshot, &pe))
1265 {
1266 while (pe.th32ProcessID != nested_pid)
1267 if (!pProcess32Next(snapshot, &pe)) break;
1268 }
1270 ok(pe.th32ProcessID == nested_pid, "failed to find nested child process\n");
1271 ok(pe.th32ParentProcessID == info.dwProcessId, "nested child process has parent %lu instead of %lu\n", pe.th32ParentProcessID, info.dwProcessId);
1272 ok(stricmp(pe.szExeFile, exename) == 0, "nested executable is %s instead of %s\n", pe.szExeFile, exename);
1273
1275 ok(process != NULL, "OpenProcess failed %lu\n", GetLastError());
1276
1277 snapshot = pCreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
1278 ok(snapshot != INVALID_HANDLE_VALUE, "CreateToolhelp32Snapshot failed %lu\n", GetLastError());
1279 memset(&te, 0, sizeof(te));
1280 te.dwSize = sizeof(te);
1281 if (pThread32First(snapshot, &te))
1282 {
1283 while (te.th32OwnerProcessID != pe.th32ProcessID)
1284 if (!pThread32Next(snapshot, &te)) break;
1285 }
1287 ok(te.th32OwnerProcessID == pe.th32ProcessID, "failed to find suspended thread\n");
1288
1290 ok(thread != NULL, "OpenThread failed %lu\n", GetLastError());
1292 ok(ret == 1, "expected 1, got %lu\n", ret);
1294
1297
1299 okChildInt("Toolhelp", "cntUsage", 0);
1300 okChildInt("Toolhelp", "th32DefaultHeapID", 0);
1301 okChildInt("Toolhelp", "th32ModuleID", 0);
1302 okChildInt("Toolhelp", "th32ParentProcessID", info.dwProcessId);
1303 /* pcPriClassBase differs between Windows versions (either 6 or 8) */
1304 okChildInt("Toolhelp", "dwFlags", 0);
1305
1308#endif
1309}
1310
1311static BOOL is_str_env_drive_dir(const char* str)
1312{
1313 return str[0] == '=' && str[1] >= 'A' && str[1] <= 'Z' && str[2] == ':' &&
1314 str[3] == '=' && str[4] == str[1];
1315}
1316
1317/* compared expected child's environment (in gesA) from actual
1318 * environment our child got
1319 */
1320static void cmpEnvironment(const char* gesA)
1321{
1322 int i, clen;
1323 const char* ptrA;
1324 char* res;
1325 char key[32];
1326 BOOL found;
1327
1328 clen = GetPrivateProfileIntA("EnvironmentA", "len", 0, resfile);
1329
1330 /* now look each parent env in child */
1331 if ((ptrA = gesA) != NULL)
1332 {
1333 while (*ptrA)
1334 {
1335 for (i = 0; i < clen; i++)
1336 {
1337 sprintf(key, "env%d", i);
1338 res = getChildString("EnvironmentA", key);
1339 if (strncmp(ptrA, res, MAX_LISTED_ENV_VAR - 1) == 0)
1340 break;
1341 }
1342 found = i < clen;
1343 ok(found, "Parent-env string %s isn't in child process\n", ptrA);
1344
1345 ptrA += strlen(ptrA) + 1;
1347 }
1348 }
1349 /* and each child env in parent */
1350 for (i = 0; i < clen; i++)
1351 {
1352 sprintf(key, "env%d", i);
1353 res = getChildString("EnvironmentA", key);
1354 if ((ptrA = gesA) != NULL)
1355 {
1356 while (*ptrA)
1357 {
1358 if (strncmp(res, ptrA, MAX_LISTED_ENV_VAR - 1) == 0)
1359 break;
1360 ptrA += strlen(ptrA) + 1;
1361 }
1362 if (!*ptrA) ptrA = NULL;
1363 }
1364
1366 {
1367 found = ptrA != NULL;
1368 ok(found, "Child-env string %s isn't in parent process\n", res);
1369 }
1370 /* else => should also test we get the right per drive default directory here... */
1371 }
1372}
1373
1374static void test_Environment(void)
1375{
1376 char buffer[2 * MAX_PATH + 25];
1379 char *child_env;
1380 int child_env_len;
1381 char *ptr;
1382 char *ptr2;
1383 char *env;
1384 int slen;
1385
1386 memset(&startup, 0, sizeof(startup));
1387 startup.cb = sizeof(startup);
1388 startup.dwFlags = STARTF_USESHOWWINDOW;
1389 startup.wShowWindow = SW_SHOWNORMAL;
1390
1391 /* the basics */
1393 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
1394 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
1396
1402
1403 memset(&startup, 0, sizeof(startup));
1404 startup.cb = sizeof(startup);
1405 startup.dwFlags = STARTF_USESHOWWINDOW;
1406 startup.wShowWindow = SW_SHOWNORMAL;
1407
1408 /* the basics */
1410 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
1411
1412 child_env_len = 0;
1413 ptr = env;
1414 while(*ptr)
1415 {
1416 slen = strlen(ptr)+1;
1417 child_env_len += slen;
1418 ptr += slen;
1419 }
1420 /* Add space for additional environment variables */
1421 child_env_len += 256;
1422 child_env = HeapAlloc(GetProcessHeap(), 0, child_env_len);
1423
1424 ptr = child_env;
1425 sprintf(ptr, "=%c:=%s", 'C', "C:\\FOO\\BAR");
1426 ptr += strlen(ptr) + 1;
1427 strcpy(ptr, "PATH=C:\\WINDOWS;C:\\WINDOWS\\SYSTEM;C:\\MY\\OWN\\DIR");
1428 ptr += strlen(ptr) + 1;
1429 strcpy(ptr, "FOO=BAR");
1430 ptr += strlen(ptr) + 1;
1431 strcpy(ptr, "BAR=FOOBAR");
1432 ptr += strlen(ptr) + 1;
1433 /* copy all existing variables except:
1434 * - PATH (already set above)
1435 * - the directory definitions (=[A-Z]:=)
1436 */
1437 for (ptr2 = env; *ptr2; ptr2 += strlen(ptr2) + 1)
1438 {
1439 if (strncmp(ptr2, "PATH=", 5) != 0 &&
1440 !is_str_env_drive_dir(ptr2))
1441 {
1442 strcpy(ptr, ptr2);
1443 ptr += strlen(ptr) + 1;
1444 }
1445 }
1446 *ptr = '\0';
1447 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, child_env, NULL, &startup, &info), "CreateProcess\n");
1449
1451 cmpEnvironment(child_env);
1452
1453 HeapFree(GetProcessHeap(), 0, child_env);
1457}
1458
1459static void test_SuspendFlag(void)
1460{
1461 char buffer[2 * MAX_PATH + 25];
1464 DWORD exit_status;
1465 char *result;
1466
1467 /* let's start simplistic */
1468 memset(&startup, 0, sizeof(startup));
1469 startup.cb = sizeof(startup);
1470 startup.dwFlags = STARTF_USESHOWWINDOW;
1471 startup.wShowWindow = SW_SHOWNORMAL;
1472
1474 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
1475 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startup, &info), "CreateProcess\n");
1476
1477 ok(GetExitCodeThread(info.hThread, &exit_status) && exit_status == STILL_ACTIVE, "thread still running\n");
1478 Sleep(100);
1479 ok(GetExitCodeThread(info.hThread, &exit_status) && exit_status == STILL_ACTIVE, "thread still running\n");
1480 ok(ResumeThread(info.hThread) == 1, "Resuming thread\n");
1481
1483
1485
1487 okChildInt("StartupInfoA", "cb", startup.cb);
1488 okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
1489 result = getChildString( "StartupInfoA", "lpTitle" );
1490 ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
1491 "expected '%s' or null, got '%s'\n", selfname, result );
1492 okChildInt("StartupInfoA", "dwX", startup.dwX);
1493 okChildInt("StartupInfoA", "dwY", startup.dwY);
1494 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
1495 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
1496 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
1497 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
1498 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
1499 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
1500 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
1503}
1504
1505static void test_DebuggingFlag(void)
1506{
1507 char buffer[2 * MAX_PATH + 25];
1508 void *processbase = NULL;
1511 DEBUG_EVENT de;
1512 unsigned dbg = 0;
1513 char *result;
1514
1515 /* let's start simplistic */
1516 memset(&startup, 0, sizeof(startup));
1517 startup.cb = sizeof(startup);
1518 startup.dwFlags = STARTF_USESHOWWINDOW;
1519 startup.wShowWindow = SW_SHOWNORMAL;
1520
1522 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, resfile);
1523 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n");
1524
1525 /* get all startup events up to the entry point break exception */
1526 do
1527 {
1528 ok(WaitForDebugEvent(&de, INFINITE), "reading debug event\n");
1530 if (!dbg)
1531 {
1533 "first event: %ld\n", de.dwDebugEventCode);
1534 processbase = de.u.CreateProcessInfo.lpBaseOfImage;
1535 }
1536 if (de.dwDebugEventCode != EXCEPTION_DEBUG_EVENT) dbg++;
1538 de.u.LoadDll.lpBaseOfDll != processbase, "got LOAD_DLL for main module\n");
1540
1541 ok(dbg, "I have seen a debug event\n");
1543
1545
1547 okChildInt("StartupInfoA", "cb", startup.cb);
1548 okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
1549 result = getChildString( "StartupInfoA", "lpTitle" );
1550 ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
1551 "expected '%s' or null, got '%s'\n", selfname, result );
1552 okChildInt("StartupInfoA", "dwX", startup.dwX);
1553 okChildInt("StartupInfoA", "dwY", startup.dwY);
1554 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
1555 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
1556 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
1557 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
1558 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
1559 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
1560 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
1563}
1564
1565static void test_Console(void)
1566{
1567 char buffer[2 * MAX_PATH + 35];
1572 DWORD modeIn, modeOut, modeInC, modeOutC;
1573 DWORD cpIn, cpOut, cpInC, cpOutC;
1574 DWORD w;
1575 HANDLE hChildIn, hChildInInh, hChildOut, hChildOutInh, hParentIn, hParentOut;
1576 const char* msg = "This is a std-handle inheritance test.";
1577 unsigned msg_len;
1579 char *result;
1580
1581 memset(&startup, 0, sizeof(startup));
1582 startup.cb = sizeof(startup);
1584 startup.wShowWindow = SW_SHOWNORMAL;
1585
1586 sa.nLength = sizeof(sa);
1587 sa.lpSecurityDescriptor = NULL;
1588 sa.bInheritHandle = TRUE;
1589
1590 startup.hStdInput = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
1591 startup.hStdOutput = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
1592
1593 /* first, we need to be sure we're attached to a console */
1594 if (startup.hStdInput == INVALID_HANDLE_VALUE || startup.hStdOutput == INVALID_HANDLE_VALUE)
1595 {
1596 /* this fails either when this test process is run detached from console
1597 * (unlikely, as this very process must be explicitly created with detached flag),
1598 * or is attached to a Wine's shell-no-window kind of console (if the later, detach from it)
1599 */
1600 FreeConsole();
1601 /* we're not attached to a console, let's do it */
1602 AllocConsole();
1603 startup.hStdInput = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
1604 startup.hStdOutput = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
1605 }
1606 /* now verify everything's ok */
1607 ok(startup.hStdInput != INVALID_HANDLE_VALUE, "Opening ConIn\n");
1608 ok(startup.hStdOutput != INVALID_HANDLE_VALUE, "Opening ConOut\n");
1609 startup.hStdError = startup.hStdOutput;
1610
1611 ok(GetConsoleScreenBufferInfo(startup.hStdOutput, &sbi), "Getting sb info\n");
1612 ok(GetConsoleMode(startup.hStdInput, &modeIn), "Getting console in mode\n");
1613 ok(GetConsoleMode(startup.hStdOutput, &modeOut), "Getting console out mode\n");
1614 cpIn = GetConsoleCP();
1615 cpOut = GetConsoleOutputCP();
1616
1618 sprintf(buffer, "\"%s\" process dump \"%s\" console", selfname, resfile);
1619 ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
1621
1623 /* now get the modification the child has made, and resets parents expected values */
1624 ok(GetConsoleScreenBufferInfo(startup.hStdOutput, &sbiC), "Getting sb info\n");
1625 ok(GetConsoleMode(startup.hStdInput, &modeInC), "Getting console in mode\n");
1626 ok(GetConsoleMode(startup.hStdOutput, &modeOutC), "Getting console out mode\n");
1627
1628 SetConsoleMode(startup.hStdInput, modeIn);
1629 SetConsoleMode(startup.hStdOutput, modeOut);
1630
1631 /* don't test flag that is changed at startup if WINETEST_COLOR is set */
1632 modeOut = (modeOut & ~ENABLE_VIRTUAL_TERMINAL_PROCESSING) |
1634
1635 cpInC = GetConsoleCP();
1636 cpOutC = GetConsoleOutputCP();
1637
1638 /* Try to set invalid CP */
1639 SetLastError(0xdeadbeef);
1640 ok(!SetConsoleCP(0), "Shouldn't succeed\n");
1643 "GetLastError: expecting %u got %lu\n",
1646 run_tests = FALSE;
1647
1648
1649 SetLastError(0xdeadbeef);
1650 ok(!SetConsoleOutputCP(0), "Shouldn't succeed\n");
1653 "GetLastError: expecting %u got %lu\n",
1655
1656 SetConsoleCP(cpIn);
1657 SetConsoleOutputCP(cpOut);
1658
1660
1661 okChildInt("StartupInfoA", "cb", startup.cb);
1662 okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
1663 result = getChildString( "StartupInfoA", "lpTitle" );
1664 ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
1665 "expected '%s' or null, got '%s'\n", selfname, result );
1666 okChildInt("StartupInfoA", "dwX", startup.dwX);
1667 okChildInt("StartupInfoA", "dwY", startup.dwY);
1668 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
1669 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
1670 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
1671 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
1672 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
1673 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
1674 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
1675
1676 /* check child correctly inherited the console */
1677 okChildInt("StartupInfoA", "hStdInput", (DWORD_PTR)startup.hStdInput);
1678 okChildInt("StartupInfoA", "hStdOutput", (DWORD_PTR)startup.hStdOutput);
1679 okChildInt("StartupInfoA", "hStdError", (DWORD_PTR)startup.hStdError);
1680 okChildInt("Console", "SizeX", (DWORD)sbi.dwSize.X);
1681 okChildInt("Console", "SizeY", (DWORD)sbi.dwSize.Y);
1682 okChildInt("Console", "CursorX", (DWORD)sbi.dwCursorPosition.X);
1683 okChildInt("Console", "CursorY", (DWORD)sbi.dwCursorPosition.Y);
1684 okChildInt("Console", "Attributes", sbi.wAttributes);
1685 okChildInt("Console", "winLeft", (DWORD)sbi.srWindow.Left);
1686 okChildInt("Console", "winTop", (DWORD)sbi.srWindow.Top);
1687 okChildInt("Console", "winRight", (DWORD)sbi.srWindow.Right);
1688 okChildInt("Console", "winBottom", (DWORD)sbi.srWindow.Bottom);
1689 okChildInt("Console", "maxWinWidth", (DWORD)sbi.dwMaximumWindowSize.X);
1690 okChildInt("Console", "maxWinHeight", (DWORD)sbi.dwMaximumWindowSize.Y);
1691 okChildInt("Console", "InputCP", cpIn);
1692 okChildInt("Console", "OutputCP", cpOut);
1693 okChildInt("Console", "InputMode", modeIn);
1694 okChildInt("Console", "OutputMode", modeOut);
1695
1696 if (run_tests)
1697 {
1698 ok(cpInC == 1252, "Wrong console CP (expected 1252 got %ld/%ld)\n", cpInC, cpIn);
1699 ok(cpOutC == 1252, "Wrong console-SB CP (expected 1252 got %ld/%ld)\n", cpOutC, cpOut);
1700 }
1701 else
1702 win_skip("Setting the codepage is not implemented\n");
1703
1704 ok(modeInC == (modeIn ^ 1), "Wrong console mode\n");
1705 ok(modeOutC == (modeOut ^ 1), "Wrong console-SB mode\n");
1706
1709
1710 ok(CreatePipe(&hParentIn, &hChildOut, NULL, 0), "Creating parent-input pipe\n");
1712 &hChildOutInh, 0, TRUE, DUPLICATE_SAME_ACCESS),
1713 "Duplicating as inheritable child-output pipe\n");
1714 CloseHandle(hChildOut);
1715
1716 ok(CreatePipe(&hChildIn, &hParentOut, NULL, 0), "Creating parent-output pipe\n");
1718 &hChildInInh, 0, TRUE, DUPLICATE_SAME_ACCESS),
1719 "Duplicating as inheritable child-input pipe\n");
1720 CloseHandle(hChildIn);
1721
1722 memset(&startup, 0, sizeof(startup));
1723 startup.cb = sizeof(startup);
1725 startup.wShowWindow = SW_SHOWNORMAL;
1726 startup.hStdInput = hChildInInh;
1727 startup.hStdOutput = hChildOutInh;
1728 startup.hStdError = hChildOutInh;
1729
1731 sprintf(buffer, "\"%s\" process dump \"%s\" stdhandle", selfname, resfile);
1732 ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n");
1733 ok(CloseHandle(hChildInInh), "Closing handle\n");
1734 ok(CloseHandle(hChildOutInh), "Closing handle\n");
1735
1736 msg_len = strlen(msg) + 1;
1737 ok(WriteFile(hParentOut, msg, msg_len, &w, NULL), "Writing to child\n");
1738 ok(w == msg_len, "Should have written %u bytes, actually wrote %lu\n", msg_len, w);
1739 memset(buffer, 0, sizeof(buffer));
1740 ok(ReadFile(hParentIn, buffer, sizeof(buffer), &w, NULL), "Reading from child\n");
1741 ok(strcmp(buffer, msg) == 0, "Should have received '%s'\n", msg);
1742
1743 /* the child may also send the final "n tests executed" string, so read it to avoid a deadlock */
1744 ReadFile(hParentIn, buffer, sizeof(buffer), &w, NULL);
1745
1747
1749 okChildString("StdHandle", "msg", msg);
1750
1753}
1754
1755static void test_ExitCode(void)
1756{
1757 char buffer[2 * MAX_PATH + 35];
1760 DWORD code;
1761
1762 /* let's start simplistic */
1763 memset(&startup, 0, sizeof(startup));
1764 startup.cb = sizeof(startup);
1765 startup.dwFlags = STARTF_USESHOWWINDOW;
1766 startup.wShowWindow = SW_SHOWNORMAL;
1767
1769 sprintf(buffer, "\"%s\" process dump \"%s\" exit_code", selfname, resfile);
1770 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
1771
1772 /* not wait_child_process() because of the exit code */
1773 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1774
1776 ok(GetExitCodeProcess(info.hProcess, &code), "Getting exit code\n");
1777 okChildInt("ExitCode", "value", code);
1778
1781}
1782
1783static void test_OpenProcess(void)
1784{
1785 HANDLE hproc;
1786 void *addr1;
1789 BOOL ret;
1790
1791 /* without PROCESS_VM_OPERATION */
1793 ok(hproc != NULL, "OpenProcess error %ld\n", GetLastError());
1794
1795 SetLastError(0xdeadbeef);
1796 addr1 = VirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
1797 ok(!addr1, "VirtualAllocEx should fail\n");
1799 { /* Win9x */
1800 CloseHandle(hproc);
1801 win_skip("VirtualAllocEx not implemented\n");
1802 return;
1803 }
1804 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %ld\n", GetLastError());
1805
1806 read_bytes = 0xdeadbeef;
1807 SetLastError(0xdeadbeef);
1809 ok(ret, "ReadProcessMemory error %ld\n", GetLastError());
1810 ok(read_bytes == sizeof(dummy), "wrong read bytes %Id\n", read_bytes);
1811
1812 CloseHandle(hproc);
1813
1815 ok(hproc != NULL, "OpenProcess error %ld\n", GetLastError());
1816
1817 addr1 = VirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
1818 ok(addr1 != NULL, "VirtualAllocEx error %ld\n", GetLastError());
1819
1820 /* without PROCESS_QUERY_INFORMATION */
1821 SetLastError(0xdeadbeef);
1822 ok(!VirtualQueryEx(hproc, addr1, &info, sizeof(info)),
1823 "VirtualQueryEx without PROCESS_QUERY_INFORMATION rights should fail\n");
1824 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %ld\n", GetLastError());
1825
1826 /* without PROCESS_VM_READ */
1827 read_bytes = 0xdeadbeef;
1828 SetLastError(0xdeadbeef);
1829 ok(!ReadProcessMemory(hproc, addr1, &dummy, sizeof(dummy), &read_bytes),
1830 "ReadProcessMemory without PROCESS_VM_READ rights should fail\n");
1831 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %ld\n", GetLastError());
1832 ok(read_bytes == 0, "wrong read bytes %Id\n", read_bytes);
1833
1834 CloseHandle(hproc);
1835
1837
1838 memset(&info, 0xcc, sizeof(info));
1839 read_bytes = VirtualQueryEx(hproc, addr1, &info, sizeof(info));
1840 ok(read_bytes == sizeof(info), "VirtualQueryEx error %ld\n", GetLastError());
1841
1842 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
1843 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
1844 ok(info.AllocationProtect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.AllocationProtect);
1845 ok(info.RegionSize == 0x10000, "%Ix != 0x10000\n", info.RegionSize);
1846 ok(info.State == MEM_RESERVE, "%lx != MEM_RESERVE\n", info.State);
1847 /* NT reports Protect == 0 for a not committed memory block */
1848 ok(info.Protect == 0 /* NT */ ||
1849 info.Protect == PAGE_NOACCESS, /* Win9x */
1850 "%lx != PAGE_NOACCESS\n", info.Protect);
1851 ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type);
1852
1853 SetLastError(0xdeadbeef);
1854 ok(!VirtualFreeEx(hproc, addr1, 0, MEM_RELEASE),
1855 "VirtualFreeEx without PROCESS_VM_OPERATION rights should fail\n");
1856 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %ld\n", GetLastError());
1857
1858 CloseHandle(hproc);
1859
1861 if (hproc)
1862 {
1863 SetLastError(0xdeadbeef);
1864 memset(&info, 0xcc, sizeof(info));
1865 read_bytes = VirtualQueryEx(hproc, addr1, &info, sizeof(info));
1866 if (read_bytes) /* win8 */
1867 {
1868 ok(read_bytes == sizeof(info), "VirtualQueryEx error %ld\n", GetLastError());
1869 ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
1870 ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
1871 ok(info.AllocationProtect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.AllocationProtect);
1872 ok(info.RegionSize == 0x10000, "%Ix != 0x10000\n", info.RegionSize);
1873 ok(info.State == MEM_RESERVE, "%lx != MEM_RESERVE\n", info.State);
1874 ok(info.Protect == 0, "%lx != PAGE_NOACCESS\n", info.Protect);
1875 ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type);
1876 }
1877 else /* before win8 */
1878 ok(broken(GetLastError() == ERROR_ACCESS_DENIED), "wrong error %ld\n", GetLastError());
1879
1880 SetLastError(0xdeadbeef);
1881 ok(!VirtualFreeEx(hproc, addr1, 0, MEM_RELEASE),
1882 "VirtualFreeEx without PROCESS_VM_OPERATION rights should fail\n");
1883 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %ld\n", GetLastError());
1884
1885 CloseHandle(hproc);
1886 }
1887
1888 ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
1889}
1890
1891static void test_GetProcessVersion(void)
1892{
1893 static char cmdline[] = "winver.exe";
1896 DWORD ret;
1897
1898 SetLastError(0xdeadbeef);
1900 ok(ret, "GetProcessVersion error %lu\n", GetLastError());
1901
1902 SetLastError(0xdeadbeef);
1904 ok(ret, "GetProcessVersion error %lu\n", GetLastError());
1905
1906 memset(&si, 0, sizeof(si));
1907 si.cb = sizeof(si);
1908 si.dwFlags = STARTF_USESHOWWINDOW;
1909 si.wShowWindow = SW_HIDE;
1910 SetLastError(0xdeadbeef);
1912 ok(ret, "CreateProcess error %lu\n", GetLastError());
1913
1914 SetLastError(0xdeadbeef);
1916 ok(ret, "GetProcessVersion error %lu\n", GetLastError());
1917
1918 SetLastError(0xdeadbeef);
1920 ok(ret, "TerminateProcess error %lu\n", GetLastError());
1921
1924}
1925
1927{
1928 DWORD rc;
1930 static const char harddisk[] = "\\Device\\HarddiskVolume";
1931
1932 if (!pK32GetProcessImageFileNameA)
1933 {
1934 win_skip("K32GetProcessImageFileNameA is unavailable\n");
1935 return;
1936 }
1937
1938 /* callers must guess the buffer size */
1939 SetLastError(0xdeadbeef);
1940 rc = pK32GetProcessImageFileNameA(GetCurrentProcess(), NULL, 0);
1942 "K32GetProcessImageFileNameA(no buffer): returned %lu, le=%lu\n", rc, GetLastError());
1943
1944 *process = '\0';
1945 rc = pK32GetProcessImageFileNameA(GetCurrentProcess(), process, sizeof(process));
1947 if (strncmp(process, harddisk, lstrlenA(harddisk)))
1948 {
1949 todo_wine win_skip("%s is probably on a network share, skipping tests\n", process);
1950 return;
1951 }
1952
1953 if (!pQueryFullProcessImageNameA)
1954 win_skip("QueryFullProcessImageNameA unavailable (added in Windows Vista)\n");
1955 else
1956 {
1958 DWORD length;
1959
1960 length = sizeof(image);
1961 expect_eq_d(TRUE, pQueryFullProcessImageNameA(GetCurrentProcess(), PROCESS_NAME_NATIVE, image, &length));
1963 ok(lstrcmpiA(process, image) == 0, "expected '%s' to be equal to '%s'\n", process, image);
1964 }
1965}
1966
1968{
1969#define INIT_STR "Just some words"
1970 DWORD length, size;
1972
1973 if (!pQueryFullProcessImageNameA)
1974 {
1975 win_skip("QueryFullProcessImageNameA unavailable (added in Windows Vista)\n");
1976 return;
1977 }
1978
1979 *module = '\0';
1980 SetLastError(0); /* old Windows don't reset it on success */
1982 ok(size && GetLastError() != ERROR_INSUFFICIENT_BUFFER, "GetModuleFileName failed: %lu le=%lu\n", size, GetLastError());
1983
1984 /* get the buffer length without \0 terminator */
1985 length = sizeof(buf);
1986 expect_eq_d(TRUE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, buf, &length));
1988 ok((buf[0] == '\\' && buf[1] == '\\') ||
1989 lstrcmpiA(buf, module) == 0, "expected %s to match %s\n", buf, module);
1990
1991 /* when the buffer is too small
1992 * - function fail with error ERROR_INSUFFICIENT_BUFFER
1993 * - the size variable is not modified
1994 * tested with the biggest too small size
1995 */
1996 size = length;
1998 expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, buf, &size));
2002
2003 /* retest with smaller buffer size
2004 */
2005 size = 4;
2007 expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, buf, &size));
2009 expect_eq_d(4, size);
2011
2012 /* this is a difference between the ansi and the unicode version
2013 * the unicode version crashes when the size is big enough to hold
2014 * the result while the ansi version throws an error
2015 */
2016 size = 1024;
2017 expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, NULL, &size));
2018 expect_eq_d(1024, size);
2020}
2021
2023{
2024 HANDLE hSelf;
2025 WCHAR module_name[1024], device[1024];
2026 WCHAR deviceW[] = {'\\','D', 'e','v','i','c','e',0};
2027 WCHAR buf[1024];
2028 DWORD size, len;
2029 DWORD flags;
2030
2031 if (!pQueryFullProcessImageNameW)
2032 {
2033 win_skip("QueryFullProcessImageNameW unavailable (added in Windows Vista)\n");
2034 return;
2035 }
2036
2037 ok(GetModuleFileNameW(NULL, module_name, 1024), "GetModuleFileNameW(NULL, ...) failed\n");
2038
2039 /* GetCurrentProcess pseudo-handle */
2040 size = ARRAY_SIZE(buf);
2041 expect_eq_d(TRUE, pQueryFullProcessImageNameW(GetCurrentProcess(), 0, buf, &size));
2044
2046 /* Real handle */
2047 size = ARRAY_SIZE(buf);
2048 expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
2051
2052 /* Buffer too small */
2055 SetLastError(0xdeadbeef);
2056 expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
2057 expect_eq_d(lstrlenW(module_name)/2, size); /* size not changed(!) */
2059 expect_eq_ws_i(deviceW, buf); /* buffer not changed */
2060
2061 /* Too small - not space for NUL terminator */
2063 SetLastError(0xdeadbeef);
2064 expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
2065 expect_eq_d(lstrlenW(module_name), size); /* size not changed(!) */
2067
2068 /* NULL buffer */
2069 size = 0;
2070 expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, NULL, &size));
2071 expect_eq_d(0, size);
2073
2074 /* Buffer too small */
2076 SetLastError(0xdeadbeef);
2078 expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
2079 expect_eq_d(lstrlenW(module_name)/2, size); /* size not changed(!) */
2081 expect_eq_ws_i(module_name, buf); /* buffer not changed */
2082
2083 /* Invalid flags - a few arbitrary values only */
2084 for (flags = 2; flags <= 15; ++flags)
2085 {
2086 size = ARRAY_SIZE(buf);
2087 SetLastError(0xdeadbeef);
2088 *(DWORD*)buf = 0x13579acf;
2089 todo_wine
2090 {
2091 expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, flags, buf, &size));
2092 expect_eq_d((DWORD)ARRAY_SIZE(buf), size); /* size not changed */
2094 expect_eq_d(0x13579acf, *(DWORD*)buf); /* buffer not changed */
2095 }
2096 }
2097 for (flags = 16; flags != 0; flags <<= 1)
2098 {
2099 size = ARRAY_SIZE(buf);
2100 SetLastError(0xdeadbeef);
2101 *(DWORD*)buf = 0x13579acf;
2102 todo_wine
2103 {
2104 expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, flags, buf, &size));
2105 expect_eq_d((DWORD)ARRAY_SIZE(buf), size); /* size not changed */
2107 expect_eq_d(0x13579acf, *(DWORD*)buf); /* buffer not changed */
2108 }
2109 }
2110
2111 /* native path */
2112 size = ARRAY_SIZE(buf);
2113 expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, PROCESS_NAME_NATIVE, buf, &size));
2115 ok(buf[0] == '\\', "NT path should begin with '\\'\n");
2116 ok(memcmp(buf, deviceW, sizeof(WCHAR)*lstrlenW(deviceW)) == 0, "NT path should begin with \\Device\n");
2117
2118 module_name[2] = '\0';
2119 *device = '\0';
2121 ok(size, "QueryDosDeviceW failed: le=%lu\n", GetLastError());
2122 len = lstrlenW(device);
2123 ok(size >= len+2, "expected %ld to be greater than %ld+2 = strlen(%s)\n", size, len, wine_dbgstr_w(device));
2124
2125 if (size >= lstrlenW(buf))
2126 {
2127 ok(0, "expected %s\\ to match the start of %s\n", wine_dbgstr_w(device), wine_dbgstr_w(buf));
2128 }
2129 else
2130 {
2131 ok(buf[len] == '\\', "expected '%c' to be a '\\' in %s\n", buf[len], wine_dbgstr_w(module_name));
2132 buf[len] = '\0';
2133 ok(lstrcmpiW(device, buf) == 0, "expected %s to match %s\n", wine_dbgstr_w(device), wine_dbgstr_w(buf));
2134 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));
2135 }
2136
2137 CloseHandle(hSelf);
2138}
2139
2140static void test_Handles(void)
2141{
2143 HANDLE h2, h3;
2144 BOOL ret;
2145 DWORD code;
2146
2147 ok( handle == (HANDLE)~(ULONG_PTR)0 ||
2148 handle == (HANDLE)(ULONG_PTR)0x7fffffff /* win9x */,
2149 "invalid current process handle %p\n", handle );
2151 ok( ret, "GetExitCodeProcess failed err %lu\n", GetLastError() );
2152#ifdef _WIN64
2153 /* truncated handle */
2154 SetLastError( 0xdeadbeef );
2155 handle = (HANDLE)((ULONG_PTR)handle & ~0u);
2157 ok( !ret, "GetExitCodeProcess succeeded for %p\n", handle );
2158 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %lu\n", GetLastError() );
2159 /* sign-extended handle */
2160 SetLastError( 0xdeadbeef );
2163 ok( ret, "GetExitCodeProcess failed err %lu\n", GetLastError() );
2164 /* invalid high-word */
2165 SetLastError( 0xdeadbeef );
2166 handle = (HANDLE)(((ULONG_PTR)handle & ~0u) + ((ULONG_PTR)1 << 32));
2168 ok( !ret, "GetExitCodeProcess succeeded for %p\n", handle );
2169 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %lu\n", GetLastError() );
2170#endif
2171
2173 ok( handle != 0, "handle %p\n", handle );
2179 ok( h2 == 0 ||
2180 broken( h2 == h3) || /* nt4, w2k */
2181 broken( h2 == INVALID_HANDLE_VALUE), /* win9x */
2182 "wrong handle %p/%p\n", h2, h3 );
2184}
2185
2186static void test_IsWow64Process(void)
2187{
2190 DWORD ret;
2191 BOOL is_wow64;
2192 static char cmdline[] = "C:\\Program Files\\Internet Explorer\\iexplore.exe";
2193 static char cmdline_wow64[] = "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe";
2194
2195 if (!pIsWow64Process)
2196 {
2197 win_skip("IsWow64Process is not available\n");
2198 return;
2199 }
2200
2201 memset(&si, 0, sizeof(si));
2202 si.cb = sizeof(si);
2203 si.dwFlags = STARTF_USESHOWWINDOW;
2204 si.wShowWindow = SW_HIDE;
2205 ret = CreateProcessA(NULL, cmdline_wow64, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2206 if (ret)
2207 {
2208 trace("Created process %s\n", cmdline_wow64);
2209 is_wow64 = FALSE;
2210 ret = pIsWow64Process(pi.hProcess, &is_wow64);
2211 ok(ret, "IsWow64Process failed.\n");
2212 ok(is_wow64, "is_wow64 returned FALSE.\n");
2213
2215 ok(ret, "TerminateProcess error\n");
2216
2219 }
2220
2221 memset(&si, 0, sizeof(si));
2222 si.cb = sizeof(si);
2223 si.dwFlags = STARTF_USESHOWWINDOW;
2224 si.wShowWindow = SW_HIDE;
2226 if (ret)
2227 {
2228 trace("Created process %s\n", cmdline);
2229 is_wow64 = TRUE;
2230 ret = pIsWow64Process(pi.hProcess, &is_wow64);
2231 ok(ret, "IsWow64Process failed.\n");
2232 ok(!is_wow64, "is_wow64 returned TRUE.\n");
2233
2235 ok(ret, "TerminateProcess error\n");
2236
2239 }
2240}
2241
2242static void test_IsWow64Process2(void)
2243{
2246 BOOL ret, is_wow64;
2247 USHORT machine, native_machine;
2248 static char cmdline[] = "C:\\Program Files\\Internet Explorer\\iexplore.exe";
2249 static char cmdline_wow64[] = "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe";
2250#ifdef __i386__
2251 USHORT expect_native = IMAGE_FILE_MACHINE_I386;
2252#elif defined __x86_64__
2253 USHORT expect_native = IMAGE_FILE_MACHINE_AMD64;
2254#elif defined __arm__
2255 USHORT expect_native = IMAGE_FILE_MACHINE_ARMNT;
2256#elif defined __aarch64__
2257 USHORT expect_native = IMAGE_FILE_MACHINE_ARM64;
2258#else
2259 USHORT expect_native = 0;
2260#endif
2261
2262 if (!pIsWow64Process2)
2263 {
2264 win_skip("IsWow64Process2 is not available\n");
2265 return;
2266 }
2267
2268 memset(&si, 0, sizeof(si));
2269 si.cb = sizeof(si);
2270 SetLastError(0xdeadbeef);
2271 ret = CreateProcessA(cmdline_wow64, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
2272 if (ret)
2273 {
2274 SetLastError(0xdeadbeef);
2275 machine = native_machine = 0xdead;
2276 ret = pIsWow64Process2(pi.hProcess, &machine, &native_machine);
2277 ok(ret, "IsWow64Process2 error %lu\n", GetLastError());
2278
2279#if defined(__i386__) || defined(__x86_64__)
2280 ok(machine == IMAGE_FILE_MACHINE_I386, "got %#x\n", machine);
2281 ok( native_machine == IMAGE_FILE_MACHINE_AMD64 ||
2282 native_machine == IMAGE_FILE_MACHINE_ARM64, "got %#x\n", native_machine);
2283 expect_native = native_machine;
2284#else
2285 skip("not supported architecture\n");
2286#endif
2288 ok(ret, "TerminateProcess error\n");
2289
2292 }
2293
2294 memset(&si, 0, sizeof(si));
2295 si.cb = sizeof(si);
2296 SetLastError(0xdeadbeef);
2298 ok(ret, "CreateProcess error %lu\n", GetLastError());
2299
2300 SetLastError(0xdeadbeef);
2301 ret = pIsWow64Process(pi.hProcess, &is_wow64);
2302 ok(ret, "IsWow64Process error %lu\n", GetLastError());
2303
2304 SetLastError(0xdeadbeef);
2305 machine = native_machine = 0xdead;
2306 ret = pIsWow64Process2(pi.hProcess, &machine, &native_machine);
2307 ok(ret, "IsWow64Process2 error %lu\n", GetLastError());
2308
2309 ok(machine == IMAGE_FILE_MACHINE_UNKNOWN, "got %#x\n", machine);
2310 ok(native_machine == expect_native, "got %#x\n", native_machine);
2311
2312 SetLastError(0xdeadbeef);
2313 machine = 0xdead;
2314 ret = pIsWow64Process2(pi.hProcess, &machine, NULL);
2315 ok(ret, "IsWow64Process2 error %lu\n", GetLastError());
2316 ok(machine == IMAGE_FILE_MACHINE_UNKNOWN, "got %#x\n", machine);
2317
2319 ok(ret, "TerminateProcess error\n");
2320
2323
2324 SetLastError(0xdeadbeef);
2325 ret = pIsWow64Process(GetCurrentProcess(), &is_wow64);
2326 ok(ret, "IsWow64Process error %lu\n", GetLastError());
2327
2328 SetLastError(0xdeadbeef);
2329 machine = native_machine = 0xdead;
2330 ret = pIsWow64Process2(GetCurrentProcess(), &machine, &native_machine);
2331 ok(ret, "IsWow64Process2 error %lu\n", GetLastError());
2332
2333 if (is_wow64)
2334 {
2335 ok(machine == IMAGE_FILE_MACHINE_I386, "got %#x\n", machine);
2336 ok(native_machine == expect_native, "got %#x\n", native_machine);
2337 }
2338 else
2339 {
2340 ok(machine == IMAGE_FILE_MACHINE_UNKNOWN, "got %#x\n", machine);
2341 ok(native_machine == expect_native, "got %#x\n", native_machine);
2342 }
2343
2344 SetLastError(0xdeadbeef);
2345 machine = 0xdead;
2346 ret = pIsWow64Process2(GetCurrentProcess(), &machine, NULL);
2347 ok(ret, "IsWow64Process2 error %lu\n", GetLastError());
2348 if (is_wow64)
2349 ok(machine == IMAGE_FILE_MACHINE_I386, "got %#x\n", machine);
2350 else
2351 ok(machine == IMAGE_FILE_MACHINE_UNKNOWN, "got %#x\n", machine);
2352}
2353
2354static void test_SystemInfo(void)
2355{
2356 SYSTEM_INFO si, nsi;
2357 BOOL is_wow64;
2358 USHORT machine, native_machine;
2359
2360 if (!pGetNativeSystemInfo)
2361 {
2362 win_skip("GetNativeSystemInfo is not available\n");
2363 return;
2364 }
2365
2366 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
2367
2368 GetSystemInfo(&si);
2369 pGetNativeSystemInfo(&nsi);
2370 if (is_wow64)
2371 {
2373 {
2375 "Expected PROCESSOR_ARCHITECTURE_AMD64, got %d\n",
2377 if (pIsWow64Process2 && pIsWow64Process2(GetCurrentProcess(), &machine, &native_machine) &&
2378 native_machine == IMAGE_FILE_MACHINE_ARM64)
2379 {
2381 ok(nsi.wProcessorLevel == 15, "got %d\n", nsi.wProcessorLevel);
2382 ok(nsi.wProcessorRevision == 0x40a, "got %d\n", nsi.wProcessorRevision);
2383 }
2384 else ok(nsi.dwProcessorType == PROCESSOR_AMD_X8664, "got %ld\n", nsi.dwProcessorType);
2385 }
2386 }
2387 else
2388 {
2390 "Expected no difference for wProcessorArchitecture, got %d and %d\n",
2393 "Expected no difference for dwProcessorType, got %ld and %ld\n",
2395 }
2396}
2397
2398static void test_ProcessorCount(void)
2399{
2400 DWORD active, maximum;
2401
2402 if (!pGetActiveProcessorCount || !pGetMaximumProcessorCount)
2403 {
2404 win_skip("GetActiveProcessorCount or GetMaximumProcessorCount is not available\n");
2405 return;
2406 }
2407
2408 active = pGetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
2409 maximum = pGetMaximumProcessorCount(ALL_PROCESSOR_GROUPS);
2410 ok(active <= maximum,
2411 "Number of active processors %li is greater than maximum number of processors %li\n",
2412 active, maximum);
2413}
2414
2415static void test_RegistryQuota(void)
2416{
2417 BOOL ret;
2418 DWORD max_quota, used_quota;
2419
2420 if (!pGetSystemRegistryQuota)
2421 {
2422 win_skip("GetSystemRegistryQuota is not available\n");
2423 return;
2424 }
2425
2426 ret = pGetSystemRegistryQuota(NULL, NULL);
2427 ok(ret == TRUE,
2428 "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
2429
2430 ret = pGetSystemRegistryQuota(&max_quota, NULL);
2431 ok(ret == TRUE,
2432 "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
2433
2434 ret = pGetSystemRegistryQuota(NULL, &used_quota);
2435 ok(ret == TRUE,
2436 "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
2437
2438 ret = pGetSystemRegistryQuota(&max_quota, &used_quota);
2439 ok(ret == TRUE,
2440 "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
2441}
2442
2443static void test_TerminateProcess(void)
2444{
2445 static char cmdline[] = "winver.exe";
2448 DWORD ret;
2450
2451 memset(&si, 0, sizeof(si));
2452 si.cb = sizeof(si);
2453 SetLastError(0xdeadbeef);
2455 ok(ret, "CreateProcess error %lu\n", GetLastError());
2456
2457 SetLastError(0xdeadbeef);
2458 thread = CreateRemoteThread(pi.hProcess, NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret);
2459 ok(thread != 0, "CreateRemoteThread error %ld\n", GetLastError());
2460
2461 /* create a not closed thread handle duplicate in the target process */
2462 SetLastError(0xdeadbeef);
2465 ok(ret, "DuplicateHandle error %lu\n", GetLastError());
2466
2467 SetLastError(0xdeadbeef);
2469 ok(ret, "TerminateThread error %lu\n", GetLastError());
2471
2472 SetLastError(0xdeadbeef);
2474 ok(ret, "TerminateProcess error %lu\n", GetLastError());
2475
2478}
2479
2480static void test_DuplicateHandle(void)
2481{
2483 HANDLE f, fmin, out;
2484 DWORD info;
2485 BOOL r;
2486
2487#if defined(__REACTOS__) && defined(_WIN64)
2488 if (is_reactos()) {
2489 ok(FALSE, "FIXME: test_DuplicateHandle() deadlocks on ReactOS x64!\n");
2490 return;
2491 }
2492#endif
2494 GetCurrentProcess(), &out, 0, FALSE,
2496 ok(r, "DuplicateHandle error %lu\n", GetLastError());
2498 ok(r, "GetHandleInformation error %lu\n", GetLastError());
2499 ok(info == 0, "info = %lx\n", info);
2500 ok(out != GetCurrentProcess(), "out = GetCurrentProcess()\n");
2502
2504 GetCurrentProcess(), &out, 0, TRUE,
2506 ok(r, "DuplicateHandle error %lu\n", GetLastError());
2508 ok(r, "GetHandleInformation error %lu\n", GetLastError());
2509 ok(info == HANDLE_FLAG_INHERIT, "info = %lx\n", info);
2510 ok(out != GetCurrentProcess(), "out = GetCurrentProcess()\n");
2512
2514 GetTempFileNameA(path, "wt", 0, file_name);
2516 if (f == INVALID_HANDLE_VALUE)
2517 {
2518 ok(0, "could not create %s\n", file_name);
2519 return;
2520 }
2521
2524 ok(r, "DuplicateHandle error %lu\n", GetLastError());
2525 ok(f == out, "f != out\n");
2527 ok(r, "GetHandleInformation error %lu\n", GetLastError());
2528 ok(info == 0, "info = %lx\n", info);
2529
2532 ok(r, "DuplicateHandle error %lu\n", GetLastError());
2533 ok(f == out, "f != out\n");
2535 ok(r, "GetHandleInformation error %lu\n", GetLastError());
2536 ok(info == HANDLE_FLAG_INHERIT, "info = %lx\n", info);
2537
2539 ok(r, "SetHandleInformation error %lu\n", GetLastError());
2542 ok(r, "DuplicateHandle error %lu\n", GetLastError());
2543 ok(f != out, "f == out\n");
2545 ok(r, "GetHandleInformation error %lu\n", GetLastError());
2546 ok(info == HANDLE_FLAG_INHERIT, "info = %lx\n", info);
2548 ok(r, "SetHandleInformation error %lu\n", GetLastError());
2549
2550 /* Test if DuplicateHandle allocates first free handle */
2551 if (f > out)
2552 {
2553 fmin = out;
2554 }
2555 else
2556 {
2557 fmin = f;
2558 f = out;
2559 }
2563 ok(r, "DuplicateHandle error %lu\n", GetLastError());
2564 ok(f == out, "f != out\n");
2567
2568 f = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
2569 ok(f != INVALID_HANDLE_VALUE, "Failed to open CONIN$ %lu\n", GetLastError());
2572 ok(r, "DuplicateHandle error %lu\n", GetLastError());
2573 ok(f == out || broken(/* Win7 */ (((ULONG_PTR)f & 3) == 3) && (f != out)), "f != out\n");
2575
2576 /* Test DUPLICATE_SAME_ATTRIBUTES */
2577 f = CreateFileA("NUL", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
2578 ok(f != INVALID_HANDLE_VALUE, "Failed to open NUL %lu\n", GetLastError());
2580 ok(r && info == 0, "Unexpected info %lx\n", info);
2581
2584 ok(r, "DuplicateHandle error %lu\n", GetLastError());
2586 ok(r && info == 0, "Unexpected info %lx\n", info);
2588
2591 ok(r, "SetHandleInformation error %lu\n", GetLastError());
2592 info = 0xdeabeef;
2594 ok(r && info == (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE), "Unexpected info %lx\n", info);
2595 ok(r, "SetHandleInformation error %lu\n", GetLastError());
2598 ok(r, "DuplicateHandle error %lu\n", GetLastError());
2599 info = 0xdeabeef;
2601 ok(r && info == (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE), "Unexpected info %lx\n", info);
2603 ok(r, "SetHandleInformation error %lu\n", GetLastError());
2606 ok(r, "SetHandleInformation error %lu\n", GetLastError());
2607 CloseHandle(f);
2608
2611 ok(r, "DuplicateHandle error %lu\n", GetLastError());
2612 info = 0xdeabeef;
2614 ok(r && info == 0, "Unexpected info %lx\n", info);
2616}
2617
2618#define test_completion(a, b, c, d, e) _test_completion(__LINE__, a, b, c, d, e)
2619static void _test_completion(int line, HANDLE port, DWORD ekey, ULONG_PTR evalue, ULONG_PTR eoverlapped, DWORD wait)
2620{
2623 DWORD key;
2624 BOOL ret;
2625
2627
2628 ok_(__FILE__, line)(ret, "GetQueuedCompletionStatus: %lx\n", GetLastError());
2629 if (ret)
2630 {
2631 ok_(__FILE__, line)(key == ekey, "unexpected key %lx\n", key);
2632 ok_(__FILE__, line)(value == evalue, "unexpected value %p\n", (void *)value);
2633 ok_(__FILE__, line)(overlapped == (LPOVERLAPPED)eoverlapped, "unexpected overlapped %p\n", overlapped);
2634 }
2635}
2636
2637#define create_process(cmd, pi) _create_process(__LINE__, cmd, pi)
2639{
2640 BOOL ret;
2641 char buffer[MAX_PATH + 19];
2642 STARTUPINFOA si = {0};
2643
2644 sprintf(buffer, "\"%s\" process %s", selfname, command);
2645
2647 ok_(__FILE__, line)(ret, "CreateProcess error %lu\n", GetLastError());
2648}
2649
2650#define test_assigned_proc(job, ...) _test_assigned_proc(__LINE__, job, __VA_ARGS__)
2651static void _test_assigned_proc(int line, HANDLE job, unsigned int count, ...)
2652{
2653 char buf[sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + sizeof(ULONG_PTR) * 20];
2655 unsigned int i, pid;
2657 DWORD size;
2658 BOOL ret;
2659
2660 memset(buf, 0, sizeof(buf));
2661 ret = pQueryInformationJobObject(job, JobObjectBasicProcessIdList, list, sizeof(buf), &size);
2662 ok_(__FILE__, line)(ret, "failed to get process id list, error %lu\n", GetLastError());
2663
2664 ok_(__FILE__, line)(list->NumberOfAssignedProcesses == count,
2665 "expected %u assigned processes, got %lu\n", count, list->NumberOfAssignedProcesses);
2666 ok_(__FILE__, line)(list->NumberOfProcessIdsInList == count,
2667 "expected %u process IDs, got %lu\n", count, list->NumberOfProcessIdsInList);
2668
2670 for (i = 0; i < min(count, list->NumberOfProcessIdsInList); ++i)
2671 {
2672 pid = va_arg(valist, unsigned int);
2673 ok_(__FILE__, line)(pid == list->ProcessIdList[i],
2674 "wrong pid %u: expected %#04x, got %#04Ix\n", i, pid, list->ProcessIdList[i]);
2675 }
2676 va_end(valist);
2677}
2678
2679#define test_accounting(a, b, c, d) _test_accounting(__LINE__, a, b, c, d)
2680static void _test_accounting(int line, HANDLE job, unsigned int total, unsigned int active, unsigned int terminated)
2681{
2683 DWORD size;
2684 BOOL ret;
2685
2686 memset(&info, 0, sizeof(info));
2687 ret = pQueryInformationJobObject(job, JobObjectBasicAccountingInformation, &info, sizeof(info), &size);
2688 ok_(__FILE__, line)(ret, "failed to get accounting information, error %lu\n", GetLastError());
2689
2690 ok_(__FILE__, line)(info.TotalProcesses == total,
2691 "expected %u total processes, got %lu\n", total, info.TotalProcesses);
2692 ok_(__FILE__, line)(info.ActiveProcesses == active,
2693 "expected %u active processes, got %lu\n", active, info.ActiveProcesses);
2694 ok_(__FILE__, line)(info.TotalTerminatedProcesses == terminated,
2695 "expected %u terminated processes, got %lu\n", terminated, info.TotalTerminatedProcesses);
2696}
2697
2698static void test_IsProcessInJob(void)
2699{
2700 HANDLE job, job2;
2702 BOOL ret, out;
2703
2704 if (!pIsProcessInJob)
2705 {
2706 win_skip("IsProcessInJob not available.\n");
2707 return;
2708 }
2709
2710 job = pCreateJobObjectW(NULL, NULL);
2711 ok(job != NULL, "CreateJobObject error %lu\n", GetLastError());
2712
2713 job2 = pCreateJobObjectW(NULL, NULL);
2714 ok(job2 != NULL, "CreateJobObject error %lu\n", GetLastError());
2715
2716 create_process("wait", &pi);
2717
2718 out = TRUE;
2719 ret = pIsProcessInJob(pi.hProcess, job, &out);
2720 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
2721 ok(!out, "IsProcessInJob returned out=%u\n", out);
2723 test_accounting(job, 0, 0, 0);
2724
2725 out = TRUE;
2726 ret = pIsProcessInJob(pi.hProcess, job2, &out);
2727 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
2728 ok(!out, "IsProcessInJob returned out=%u\n", out);
2729 test_assigned_proc(job2, 0);
2730 test_accounting(job2, 0, 0, 0);
2731
2732 ret = pAssignProcessToJobObject(job, pi.hProcess);
2733 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
2734
2735 out = FALSE;
2736 ret = pIsProcessInJob(pi.hProcess, job, &out);
2737 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
2738 ok(out, "IsProcessInJob returned out=%u\n", out);
2740 test_accounting(job, 1, 1, 0);
2741
2742 out = TRUE;
2743 ret = pIsProcessInJob(pi.hProcess, job2, &out);
2744 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
2745 ok(!out, "IsProcessInJob returned out=%u\n", out);
2746 test_assigned_proc(job2, 0);
2747 test_accounting(job2, 0, 0, 0);
2748
2749 out = FALSE;
2750 ret = pIsProcessInJob(pi.hProcess, NULL, &out);
2751 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
2752 ok(out, "IsProcessInJob returned out=%u\n", out);
2753
2756
2757 out = FALSE;
2758 ret = pIsProcessInJob(pi.hProcess, job, &out);
2759 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
2760 ok(out, "IsProcessInJob returned out=%u\n", out);
2761#ifdef __REACTOS__
2764 test_accounting(job, 1, 1, 0);
2765 } else {
2766#endif
2768 test_accounting(job, 1, 0, 0);
2769#ifdef __REACTOS__
2770 }
2771#endif
2772
2776 CloseHandle(job2);
2777}
2778
2780{
2781 HANDLE job;
2783 BOOL ret;
2784 DWORD dwret;
2785
2786 job = pCreateJobObjectW(NULL, NULL);
2787 ok(job != NULL, "CreateJobObject error %lu\n", GetLastError());
2789 test_accounting(job, 0, 0, 0);
2790
2791 create_process("wait", &pi);
2792
2793 ret = pAssignProcessToJobObject(job, pi.hProcess);
2794 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
2796 test_accounting(job, 1, 1, 0);
2797
2798 ret = pTerminateJobObject(job, 123);
2799 ok(ret, "TerminateJobObject error %lu\n", GetLastError());
2800
2801 /* not wait_child_process() because of the exit code */
2802 dwret = WaitForSingleObject(pi.hProcess, 1000);
2803 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", dwret);
2804 if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0);
2806 test_accounting(job, 1, 0, 0);
2807
2808 ret = GetExitCodeProcess(pi.hProcess, &dwret);
2809 ok(ret, "GetExitCodeProcess error %lu\n", GetLastError());
2810 ok(dwret == 123 || broken(dwret == 0) /* randomly fails on Win 2000 / XP */,
2811 "wrong exitcode %lu\n", dwret);
2812
2815
2816 /* Test adding an already terminated process to a job object */
2817 create_process("exit", &pi);
2819
2820 SetLastError(0xdeadbeef);
2821 ret = pAssignProcessToJobObject(job, pi.hProcess);
2822 ok(!ret, "AssignProcessToJobObject unexpectedly succeeded\n");
2825 test_accounting(job, 1, 0, 0);
2826
2829
2831}
2832
2834{
2835 char buf[sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + sizeof(ULONG_PTR) * 4];
2838 JOBOBJECT_BASIC_LIMIT_INFORMATION *basic_limit_info = &ext_limit_info.BasicLimitInformation;
2839 JOBOBJECT_BASIC_ACCOUNTING_INFORMATION basic_accounting_info;
2840 DWORD ret_len;
2842 char buffer[50];
2843 HANDLE job, sem;
2844 BOOL ret;
2845
2846 job = pCreateJobObjectW(NULL, NULL);
2847 ok(job != NULL, "CreateJobObject error %lu\n", GetLastError());
2848
2849 /* Only active processes are returned */
2850 sprintf(buffer, "sync kernel32-process-%lx", GetCurrentProcessId());
2851 sem = CreateSemaphoreA(NULL, 0, 1, buffer + 5);
2852 ok(sem != NULL, "CreateSemaphoreA failed le=%lu\n", GetLastError());
2853 create_process(buffer, &pi[0]);
2854
2855 ret = pAssignProcessToJobObject(job, pi[0].hProcess);
2856 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
2857
2860
2861 create_process("wait", &pi[0]);
2862 ret = pAssignProcessToJobObject(job, pi[0].hProcess);
2863 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
2864
2865 create_process("wait", &pi[1]);
2866 ret = pAssignProcessToJobObject(job, pi[1].hProcess);
2867 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
2868
2869 SetLastError(0xdeadbeef);
2872 ok(!ret, "QueryInformationJobObject expected failure\n");
2874
2875 SetLastError(0xdeadbeef);
2876 memset(buf, 0, sizeof(buf));
2877 pid_list->NumberOfAssignedProcesses = 42;
2878 pid_list->NumberOfProcessIdsInList = 42;
2881 ok(!ret, "QueryInformationJobObject expected failure\n");
2883 if (ret)
2884 {
2887 }
2888
2889 memset(buf, 0, sizeof(buf));
2890 ret = pQueryInformationJobObject(job, JobObjectBasicProcessIdList, pid_list, sizeof(buf), &ret_len);
2891 ok(ret, "QueryInformationJobObject error %lu\n", GetLastError());
2892 if(ret)
2893 {
2894 if (pid_list->NumberOfAssignedProcesses == 3) /* Win 8 */
2895 win_skip("Number of assigned processes broken on Win 8\n");
2896 else
2897 {
2898 ULONG_PTR *list = pid_list->ProcessIdList;
2899
2901 "QueryInformationJobObject returned ret_len=%lu\n", ret_len);
2902
2907 }
2908 }
2909
2910 /* test JobObjectBasicLimitInformation */
2911 ret = pQueryInformationJobObject(job, JobObjectBasicLimitInformation, basic_limit_info,
2912 sizeof(*basic_limit_info) - 1, &ret_len);
2913 ok(!ret, "QueryInformationJobObject expected failure\n");
2915
2916 ret_len = 0xdeadbeef;
2917 memset(basic_limit_info, 0x11, sizeof(*basic_limit_info));
2918 ret = pQueryInformationJobObject(job, JobObjectBasicLimitInformation, basic_limit_info,
2919 sizeof(*basic_limit_info), &ret_len);
2920 ok(ret, "QueryInformationJobObject error %lu\n", GetLastError());
2921 ok(ret_len == sizeof(*basic_limit_info), "QueryInformationJobObject returned ret_len=%lu\n", ret_len);
2922 expect_eq_d(0, basic_limit_info->LimitFlags);
2923
2924 /* test JobObjectExtendedLimitInformation */
2925 ret = pQueryInformationJobObject(job, JobObjectExtendedLimitInformation, &ext_limit_info,
2926 sizeof(ext_limit_info) - 1, &ret_len);
2927 ok(!ret, "QueryInformationJobObject expected failure\n");
2929
2930 ret_len = 0xdeadbeef;
2931 memset(&ext_limit_info, 0x11, sizeof(ext_limit_info));
2932 ret = pQueryInformationJobObject(job, JobObjectExtendedLimitInformation, &ext_limit_info,
2933 sizeof(ext_limit_info), &ret_len);
2934 ok(ret, "QueryInformationJobObject error %lu\n", GetLastError());
2935 ok(ret_len == sizeof(ext_limit_info), "QueryInformationJobObject returned ret_len=%lu\n", ret_len);
2936 expect_eq_d(0, basic_limit_info->LimitFlags);
2937
2938 /* test JobObjectBasicAccountingInformation */
2939 ret = pQueryInformationJobObject(job, JobObjectBasicAccountingInformation, &basic_accounting_info,
2940 sizeof(basic_accounting_info), &ret_len);
2941 ok(ret, "QueryInformationJobObject error %lu\n", GetLastError());
2942 ok(ret_len == sizeof(basic_accounting_info), "QueryInformationJobObject returned ret_len=%lu\n", ret_len);
2943 expect_eq_d(3, basic_accounting_info.TotalProcesses);
2944#if defined(__REACTOS__)
2945 ok(basic_accounting_info.ActiveProcesses == 2 || broken(basic_accounting_info.ActiveProcesses == 3) /* Win8+ */, "Expected %d == %d\n", basic_accounting_info.ActiveProcesses, 2);
2946#else
2947 expect_eq_d(2, basic_accounting_info.ActiveProcesses);
2948#endif
2949
2953
2957
2959}
2960
2961static void test_CompletionPort(void)
2962{
2965 HANDLE job, port;
2966 BOOL ret;
2967
2968 job = pCreateJobObjectW(NULL, NULL);
2969 ok(job != NULL, "CreateJobObject error %lu\n", GetLastError());
2970
2971 create_process("wait", &pi2);
2972 ret = pAssignProcessToJobObject(job, pi2.hProcess);
2973 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
2974
2975 port = pCreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
2976 ok(port != NULL, "CreateIoCompletionPort error %lu\n", GetLastError());
2977
2978 port_info.CompletionKey = job;
2979 port_info.CompletionPort = port;
2980 ret = pSetInformationJobObject(job, JobObjectAssociateCompletionPortInformation, &port_info, sizeof(port_info));
2981 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
2982
2983 create_process("wait", &pi);
2984
2985 ret = pAssignProcessToJobObject(job, pi.hProcess);
2986 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
2987
2990
2993
2995 TerminateProcess(pi2.hProcess, 0);
2997 CloseHandle(pi2.hProcess);
2998 CloseHandle(pi2.hThread);
2999
3002
3007}
3008
3009static void test_KillOnJobClose(void)
3010{
3013 DWORD dwret;
3014 HANDLE job;
3015 BOOL ret;
3016
3017 job = pCreateJobObjectW(NULL, NULL);
3018 ok(job != NULL, "CreateJobObject error %lu\n", GetLastError());
3019
3021 ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
3023 {
3024 win_skip("Kill on job close limit not available\n");
3025 return;
3026 }
3027 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
3029 test_accounting(job, 0, 0, 0);
3030
3031 create_process("wait", &pi);
3032
3033 ret = pAssignProcessToJobObject(job, pi.hProcess);
3034 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
3036 test_accounting(job, 1, 1, 0);
3037
3039
3040 /* not wait_child_process() for the kill */
3041 dwret = WaitForSingleObject(pi.hProcess, 1000);
3042 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", dwret);
3043 if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0);
3044
3047}
3048
3049static void test_WaitForJobObject(void)
3050{
3051 HANDLE job, sem;
3052 char buffer[50];
3054 BOOL ret;
3055 DWORD dwret;
3056
3057 /* test waiting for a job object when the process is killed */
3058 job = pCreateJobObjectW(NULL, NULL);
3059 ok(job != NULL, "CreateJobObject error %lu\n", GetLastError());
3060
3061 dwret = WaitForSingleObject(job, 100);
3062 ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", dwret);
3063
3064 create_process("wait", &pi);
3065
3066 ret = pAssignProcessToJobObject(job, pi.hProcess);
3067 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
3068
3069 dwret = WaitForSingleObject(job, 100);
3070 ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", dwret);
3071
3072 ret = pTerminateJobObject(job, 123);
3073 ok(ret, "TerminateJobObject error %lu\n", GetLastError());
3074
3075 dwret = WaitForSingleObject(job, 500);
3076 ok(dwret == WAIT_OBJECT_0 || broken(dwret == WAIT_TIMEOUT),
3077 "WaitForSingleObject returned %lu\n", dwret);
3078
3079 if (dwret == WAIT_TIMEOUT) /* Win 2000/XP */
3080 {
3084 win_skip("TerminateJobObject doesn't signal job, skipping tests\n");
3085 return;
3086 }
3087
3088 /* the object is not reset immediately */
3089 dwret = WaitForSingleObject(job, 100);
3090 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", dwret);
3091
3094
3095 /* creating a new process doesn't reset the signalled state */
3096 create_process("wait", &pi);
3097
3098 ret = pAssignProcessToJobObject(job, pi.hProcess);
3099 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
3100
3101 dwret = WaitForSingleObject(job, 100);
3102 ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", dwret);
3103
3104 ret = pTerminateJobObject(job, 123);
3105 ok(ret, "TerminateJobObject error %lu\n", GetLastError());
3106
3109
3111
3112 /* repeat the test, but this time the process terminates properly */
3113 job = pCreateJobObjectW(NULL, NULL);
3114 ok(job != NULL, "CreateJobObject error %lu\n", GetLastError());
3115
3116 dwret = WaitForSingleObject(job, 100);
3117 ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", dwret);
3118
3119 sprintf(buffer, "sync kernel32-process-%lx", GetCurrentProcessId());
3120 sem = CreateSemaphoreA(NULL, 0, 1, buffer + 5);
3121 ok(sem != NULL, "CreateSemaphoreA failed le=%lu\n", GetLastError());
3123
3124 ret = pAssignProcessToJobObject(job, pi.hProcess);
3125 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
3127
3128 dwret = WaitForSingleObject(job, 100);
3129 ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", dwret);
3130
3134}
3135
3137{
3138 HANDLE job;
3139 BOOL ret;
3140
3141 job = pCreateJobObjectW(NULL, NULL);
3142 ok(job != NULL, "CreateJobObject error %lu\n", GetLastError());
3143
3144 ret = pAssignProcessToJobObject(job, GetCurrentProcess());
3145 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
3147 test_accounting(job, 1, 1, 0);
3148
3149 return job;
3150}
3151
3153{
3155 BOOL ret, out;
3156
3157 if (!pIsProcessInJob)
3158 {
3159 win_skip("IsProcessInJob not available.\n");
3160 return;
3161 }
3162
3163 create_process("exit", &pi);
3164
3165 out = FALSE;
3166 ret = pIsProcessInJob(pi.hProcess, job, &out);
3167 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
3168 ok(out, "IsProcessInJob returned out=%u\n", out);
3170 test_accounting(job, 2, 2, 0);
3171
3173}
3174
3175static void test_BreakawayOk(HANDLE parent_job)
3176{
3179 STARTUPINFOA si = {0};
3180 char buffer[MAX_PATH + 23];
3181 BOOL ret, out, nested_jobs;
3182 HANDLE job;
3183
3184 if (!pIsProcessInJob)
3185 {
3186 win_skip("IsProcessInJob not available.\n");
3187 return;
3188 }
3189
3190 job = pCreateJobObjectW(NULL, NULL);
3191 ok(!!job, "CreateJobObjectW error %lu\n", GetLastError());
3192
3193 ret = pAssignProcessToJobObject(job, GetCurrentProcess());
3194 ok(ret || broken(!ret && GetLastError() == ERROR_ACCESS_DENIED) /* before Win 8. */,
3195 "AssignProcessToJobObject error %lu\n", GetLastError());
3196 nested_jobs = ret;
3197 if (!ret)
3198 win_skip("Nested jobs are not supported.\n");
3199
3200 sprintf(buffer, "\"%s\" process exit", selfname);
3202 ok(!ret, "CreateProcessA expected failure\n");
3204
3205 if (ret)
3206 {
3209 }
3210
3211 if (nested_jobs)
3212 {
3214 test_accounting(job, 1, 1, 0);
3215
3217 ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
3218 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
3219
3220 sprintf(buffer, "\"%s\" process exit", selfname);
3222 ok(ret, "CreateProcessA error %lu\n", GetLastError());
3223
3224 ret = pIsProcessInJob(pi.hProcess, job, &out);
3225 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
3226 ok(!out, "IsProcessInJob returned out=%u\n", out);
3227
3228 ret = pIsProcessInJob(pi.hProcess, parent_job, &out);
3229 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
3230 ok(out, "IsProcessInJob returned out=%u\n", out);
3231
3234 }
3235
3237 ret = pSetInformationJobObject(parent_job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
3238 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
3239
3241 ok(ret, "CreateProcessA error %lu\n", GetLastError());
3242
3243 ret = pIsProcessInJob(pi.hProcess, job, &out);
3244 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
3245 ok(!out, "IsProcessInJob returned out=%u\n", out);
3246 if (nested_jobs)
3247 {
3249 test_accounting(job, 1, 1, 0);
3250 }
3251
3252 ret = pIsProcessInJob(pi.hProcess, parent_job, &out);
3253 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
3254 ok(!out, "IsProcessInJob returned out=%u\n", out);
3255
3257
3259 ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
3260 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
3261
3263 ok(ret, "CreateProcess error %lu\n", GetLastError());
3264
3265 ret = pIsProcessInJob(pi.hProcess, job, &out);
3266 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
3267 ok(!out, "IsProcessInJob returned out=%u\n", out);
3268 if (nested_jobs)
3269 {
3271 test_accounting(job, 1, 1, 0);
3272 }
3273
3275
3276 /* unset breakaway ok */
3277 limit_info.BasicLimitInformation.LimitFlags = 0;
3278 ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
3279 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
3280}
3281
3282/* copy an executable, but changing its subsystem */
3283static void copy_change_subsystem(const char* in, const char* out, DWORD subsyst)
3284{
3285 BOOL ret;
3286 HANDLE hFile, hMap;
3287 void* mapping;
3288 IMAGE_NT_HEADERS *nthdr;
3289
3290 ret = CopyFileA(in, out, FALSE);
3291 ok(ret, "Failed to copy executable %s in %s (%lu)\n", in, out, GetLastError());
3292
3295 ok(hFile != INVALID_HANDLE_VALUE, "Couldn't open file %s (%lu)\n", out, GetLastError());
3297 ok(hMap != NULL, "Couldn't create map (%lu)\n", GetLastError());
3298 mapping = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
3299 ok(mapping != NULL, "Couldn't map (%lu)\n", GetLastError());
3300 nthdr = RtlImageNtHeader(mapping);
3301 ok(nthdr != NULL, "Cannot get NT headers out of %s\n", out);
3302 if (nthdr) nthdr->OptionalHeader.Subsystem = subsyst;
3304 ok(ret, "Couldn't unmap (%lu)\n", GetLastError());
3305 CloseHandle(hMap);
3307}
3308
3309#define H_CONSOLE 0
3310#define H_DISK 1
3311#define H_CHAR 2
3312#define H_PIPE 3
3313#define H_NULL 4
3314#define H_INVALID 5
3315#define H_DEVIL 6 /* unassigned handle */
3316
3317#define ARG_STD 0x80000000
3318#define ARG_STARTUPINFO 0x00000000
3319#define ARG_CP_INHERIT 0x40000000
3320#define ARG_HANDLE_INHERIT 0x20000000
3321#define ARG_HANDLE_PROTECT 0x10000000
3322#define ARG_HANDLE_MASK (~0xff000000)
3323
3324static BOOL check_run_child(const char *exec, DWORD flags, BOOL cp_inherit,
3326{
3328 char buffer[2 * MAX_PATH + 64];
3330 BOOL res;
3331 DWORD ret;
3332
3334 sprintf(buffer, "\"%s\" process dump \"%s\"", exec, resfile);
3335
3336 res = CreateProcessA(NULL, buffer, NULL, NULL, cp_inherit, flags, NULL, NULL, si, &info);
3337 ok(res, "CreateProcess failed: %lu %s\n", GetLastError(), buffer);
3338 CloseHandle(info.hThread);
3339 ret = WaitForSingleObject(info.hProcess, 30000);
3340 ok(ret == WAIT_OBJECT_0, "Could not wait for the child process: %ld le=%lu\n",
3341 ret, GetLastError());
3342 res = GetExitCodeProcess(info.hProcess, &exit_code);
3343 ok(res && exit_code == 0, "Couldn't get exit_code\n");
3344 CloseHandle(info.hProcess);
3345 return res;
3346}
3347
3349
3351{
3352 SECURITY_ATTRIBUTES inherit_sa = { sizeof(inherit_sa), NULL, TRUE };
3354 BOOL ret, needs_close = FALSE;
3355
3356 psa = (args & ARG_HANDLE_INHERIT) ? &inherit_sa : NULL;
3357
3358 memset(startup, 0, sizeof(*startup));
3359 startup->cb = sizeof(*startup);
3360
3361 switch (args & ARG_HANDLE_MASK)
3362 {
3363 case H_CONSOLE:
3364 hstd[0] = CreateFileA("CONIN$", GENERIC_READ, 0, psa, OPEN_EXISTING, 0, 0);
3365 ok(hstd[0] != INVALID_HANDLE_VALUE, "Couldn't create input to console\n");
3366 hstd[1] = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, psa, OPEN_EXISTING, 0, 0);
3367 ok(hstd[1] != INVALID_HANDLE_VALUE, "Couldn't create input to console\n");
3368 needs_close = TRUE;
3369 break;
3370 case H_DISK:
3372 ok(hstd[0] != INVALID_HANDLE_VALUE, "Couldn't create input to file %s\n", std_handle_file);
3374 ok(hstd[1] != INVALID_HANDLE_VALUE, "Couldn't create input to file %s\n", std_handle_file);
3375 needs_close = TRUE;
3376 break;
3377 case H_CHAR:
3378 hstd[0] = CreateFileA("NUL", GENERIC_READ, 0, psa, OPEN_EXISTING, 0, 0);
3379 ok(hstd[0] != INVALID_HANDLE_VALUE, "Couldn't create input to NUL\n");
3380 hstd[1] = CreateFileA("NUL", GENERIC_READ|GENERIC_WRITE, 0, psa, OPEN_EXISTING, 0, 0);
3381 ok(hstd[1] != INVALID_HANDLE_VALUE, "Couldn't create input to NUL\n");
3382 needs_close = TRUE;
3383 break;
3384 case H_PIPE:
3385 ret = CreatePipe(&hstd[0], &hstd[1], psa, 0);
3386 ok(ret, "Couldn't create anon pipe\n");
3387 needs_close = TRUE;
3388 break;
3389 case H_NULL:
3390 hstd[0] = hstd[1] = NULL;
3391 break;
3392 case H_INVALID:
3393 hstd[0] = hstd[1] = INVALID_HANDLE_VALUE;
3394 break;
3395 case H_DEVIL:
3396 hstd[0] = (HANDLE)(ULONG_PTR)0x066600;
3397 hstd[1] = (HANDLE)(ULONG_PTR)0x066610;
3398 break;
3399 default:
3400 ok(0, "Unsupported handle type %x\n", args & ARG_HANDLE_MASK);
3401 return FALSE;
3402 }
3403 if ((args & ARG_HANDLE_PROTECT) && needs_close)
3404 {
3406 ok(ret, "Couldn't set inherit flag to hstd[0]\n");
3408 ok(ret, "Couldn't set inherit flag to hstd[1]\n");
3409 }
3410
3411 if (args & ARG_STD)
3412 {
3415 }
3416 else /* through startup info */
3417 {
3418 startup->dwFlags |= STARTF_USESTDHANDLES;
3419 startup->hStdInput = hstd[0];
3420 startup->hStdOutput = hstd[1];
3421 }
3422 return needs_close;
3423}
3424
3426{
3427 /* input */
3428 unsigned args;
3429 /* output */
3431 DWORD is_broken; /* Win7 broken file types */
3432};
3433
3435{
3436 HANDLE hsavestd[3];
3437 static char guiexec[MAX_PATH];
3438 static char cuiexec[MAX_PATH];
3439 char **argv;
3440 BOOL ret;
3441 int i, j;
3442
3443 static const struct std_handle_test
3444 nothing_cui[] =
3445 {
3446 /* all others handles type behave as H_DISK */
3449
3450 /* all others handles type behave as H_DISK */
3453
3454 /* all others handles type behave as H_DISK */
3457
3458 /* all others handles type behave as H_DISK */
3461
3462 /* all others handles type behave as H_DISK */
3465
3466 /* all others handles type behave as H_DISK */
3472/*15*/ {ARG_STD | H_NULL, HATTR_NULL, .is_broken = HATTR_INVALID},
3473 },
3474 nothing_gui[] =
3475 {
3476 /* testing all types because of discrepancies */
3485
3486 /* all others handles type behave as H_DISK */
3489
3490 /* all others handles type behave as H_DISK */
3493
3494 /* all others handles type behave as H_DISK */
3497
3499/*15*/ {ARG_STD | H_DEVIL, HATTR_NULL},
3504 },
3505 detached_cui[] =
3506 {
3509 /* all others handles type behave as H_DISK */
3512 },
3513 detached_gui[] =
3514 {
3517 /* all others handles type behave as H_DISK */
3520 };
3521 static const struct
3522 {
3523 DWORD cp_flags;
3524 BOOL use_cui;
3525 const struct std_handle_test* tests;
3526 size_t count;
3527 const char* descr;
3528 }
3529 tests[] =
3530 {
3531#define X(d, cg, s) {(d), (cg), s, ARRAY_SIZE(s), #s}
3532 X(0, TRUE, nothing_cui),
3533 X(0, FALSE, nothing_gui),
3534 X(DETACHED_PROCESS, TRUE, detached_cui),
3535 X(DETACHED_PROCESS, FALSE, detached_gui),
3536#undef X
3537 };
3538
3539#ifdef __REACTOS__
3540 if (is_reactos()) {
3541 ok(FALSE, "FIXME: These std handle tests on ReactOS confuses rosautotest\n");
3542 return;
3543 }
3544#endif
3545 hsavestd[0] = GetStdHandle(STD_INPUT_HANDLE);
3546 hsavestd[1] = GetStdHandle(STD_OUTPUT_HANDLE);
3547 hsavestd[2] = GetStdHandle(STD_ERROR_HANDLE);
3548
3550
3551 GetTempPathA(ARRAY_SIZE(guiexec), guiexec);
3552 strcat(guiexec, "process_gui.exe");
3554 GetTempPathA(ARRAY_SIZE(cuiexec), cuiexec);
3555 strcat(cuiexec, "process_cui.exe");
3558
3559 for (j = 0; j < ARRAY_SIZE(tests); j++)
3560 {
3561 const struct std_handle_test* std_tests = tests[j].tests;
3562
3563 for (i = 0; i < tests[j].count; i++)
3564 {
3566#if defined(__REACTOS__) && defined(_MSC_VER)
3567 HANDLE hstd[2] = {0};
3568#else
3569 HANDLE hstd[2] = {};
3570#endif
3571 BOOL needs_close;
3572
3573 winetest_push_context("%s[%u] ", tests[j].descr, i);
3574 needs_close = build_startupinfo( &startup, std_tests[i].args, hstd );
3575
3576 ret = check_run_child(tests[j].use_cui ? cuiexec : guiexec,
3577 tests[j].cp_flags, !!(std_tests[i].args & ARG_CP_INHERIT),
3578 &startup);
3579 ok(ret, "Couldn't run child\n");
3581
3582 if (std_tests[i].expected & HATTR_DANGLING)
3583 {
3584 /* The value of the handle (in parent) has been copied in STARTUPINFO fields (in child),
3585 * but the object hasn't been inherited from parent to child.
3586 * There's no reliable way to test that the object hasn't been inherited, as the
3587 * entry in the child's handle table is free and could have been reused before
3588 * this test occurs.
3589 * So simply test that the value is passed untouched.
3590 */
3591 okChildHexInt("StartupInfoA", "hStdInput", (DWORD_PTR)((std_tests[i].args & ARG_STD) ? INVALID_HANDLE_VALUE : hstd[0]), std_tests[i].is_broken);
3592 okChildHexInt("StartupInfoA", "hStdOutput", (DWORD_PTR)((std_tests[i].args & ARG_STD) ? INVALID_HANDLE_VALUE : hstd[1]), std_tests[i].is_broken);
3593 if (!(std_tests[i].args & ARG_STD))
3594 {
3595 okChildHexInt("StartupInfoW", "hStdInput", (DWORD_PTR)hstd[0], std_tests[i].is_broken);
3596 okChildHexInt("StartupInfoW", "hStdOutput", (DWORD_PTR)hstd[1], std_tests[i].is_broken);
3597 }
3598
3599 okChildHexInt("TEB", "hStdInput", (DWORD_PTR)hstd[0], std_tests[i].is_broken);
3600 okChildHexInt("TEB", "hStdOutput", (DWORD_PTR)hstd[1], std_tests[i].is_broken);
3601 }
3602 else
3603 {
3604 unsigned startup_expected = (std_tests[i].args & ARG_STD) ? HATTR_INVALID : std_tests[i].expected;
3605
3606 okChildHexInt("StartupInfoA", "hStdInputEncode", startup_expected, std_tests[i].is_broken);
3607 okChildHexInt("StartupInfoA", "hStdOutputEncode", startup_expected, std_tests[i].is_broken);
3608
3609 startup_expected = (std_tests[i].args & ARG_STD) ? HATTR_UNTOUCHED : std_tests[i].expected;
3610
3611 okChildHexInt("StartupInfoW", "hStdInputEncode", startup_expected, std_tests[i].is_broken);
3612 okChildHexInt("StartupInfoW", "hStdOutputEncode", startup_expected, std_tests[i].is_broken);
3613
3614#ifdef __REACTOS__
3616#endif
3617 okChildHexInt("TEB", "hStdInputEncode", std_tests[i].expected, std_tests[i].is_broken);
3618 okChildHexInt("TEB", "hStdOutputEncode", std_tests[i].expected, std_tests[i].is_broken);
3619#ifdef __REACTOS__
3620 }
3621#endif
3622 }
3623
3626 if (needs_close)
3627 {
3629 CloseHandle(hstd[0]);
3631 CloseHandle(hstd[1]);
3632 }
3634 }
3635 }
3636
3637 DeleteFileA(guiexec);
3638 DeleteFileA(cuiexec);
3640
3641 SetStdHandle(STD_INPUT_HANDLE, hsavestd[0]);
3642 SetStdHandle(STD_OUTPUT_HANDLE, hsavestd[1]);
3643 SetStdHandle(STD_ERROR_HANDLE, hsavestd[2]);
3644}
3645
3646#if defined(__i386__) || defined(__x86_64__)
3647static BOOL read_nt_header(HANDLE process_handle, MEMORY_BASIC_INFORMATION *mbi,
3649{
3651
3652 if (!ReadProcessMemory(process_handle, mbi->BaseAddress, &dos_header, sizeof(dos_header), NULL))
3653 return FALSE;
3654
3656 ((ULONG)dos_header.e_lfanew > mbi->RegionSize) ||
3657 (dos_header.e_lfanew < sizeof(dos_header)))
3658 return FALSE;
3659
3660 if (!ReadProcessMemory(process_handle, (char *)mbi->BaseAddress + dos_header.e_lfanew,
3661 nt_header, sizeof(*nt_header), NULL))
3662 return FALSE;
3663
3665}
3666
3667static PVOID get_process_exe(HANDLE process_handle, IMAGE_NT_HEADERS *nt_header)
3668{
3669 PVOID exe_base, address;
3671
3672 /* Find the EXE base in the new process */
3673 exe_base = NULL;
3674 for (address = NULL ;
3675 VirtualQueryEx(process_handle, address, &mbi, sizeof(mbi)) ;
3676 address = (char *)mbi.BaseAddress + mbi.RegionSize) {
3677 if ((mbi.Type == SEC_IMAGE) &&
3678 read_nt_header(process_handle, &mbi, nt_header) &&
3680 exe_base = mbi.BaseAddress;
3681 break;
3682 }
3683 }
3684
3685 return exe_base;
3686}
3687
3688static BOOL are_imports_resolved(HANDLE process_handle, PVOID module_base, IMAGE_NT_HEADERS *nt_header)
3689{
3690 BOOL ret;
3692 ULONG_PTR orig_iat_entry_value, iat_entry_value;
3693
3696
3699 return FALSE;
3700
3701 /* Read the first IID */
3702 ret = ReadProcessMemory(process_handle,
3704 &iid, sizeof(iid), NULL);
3705 ok(ret, "Failed to read remote module IID (%ld)\n", GetLastError());
3706
3707 /* Validate the IID is present and not a bound import, and that we have
3708 an OriginalFirstThunk to compare with */
3709 ok(iid.Name, "Module first IID does not have a Name\n");
3710 ok(iid.FirstThunk, "Module first IID does not have a FirstThunk\n");
3711 ok(!iid.TimeDateStamp, "Module first IID is a bound import (UNSUPPORTED for current test)\n");
3712 ok(iid.OriginalFirstThunk, "Module first IID does not have an OriginalFirstThunk (UNSUPPORTED for current test)\n");
3713
3714 /* Read a single IAT entry from the FirstThunk */
3715 ret = ReadProcessMemory(process_handle, (char *)module_base + iid.FirstThunk,
3716 &iat_entry_value, sizeof(iat_entry_value), NULL);
3717 ok(ret, "Failed to read IAT entry from FirstThunk (%ld)\n", GetLastError());
3718 ok(iat_entry_value, "IAT entry in FirstThunk is NULL\n");
3719
3720 /* Read a single IAT entry from the OriginalFirstThunk */
3721 ret = ReadProcessMemory(process_handle, (char *)module_base + iid.OriginalFirstThunk,
3722 &orig_iat_entry_value, sizeof(orig_iat_entry_value), NULL);
3723 ok(ret, "Failed to read IAT entry from OriginalFirstThunk (%ld)\n", GetLastError());
3724 ok(orig_iat_entry_value, "IAT entry in OriginalFirstThunk is NULL\n");
3725
3726 return iat_entry_value != orig_iat_entry_value;
3727}
3728
3729static void test_SuspendProcessNewThread(void)
3730{
3731 BOOL ret;
3732 STARTUPINFOA si = {0};
3733 PROCESS_INFORMATION pi = {0};
3734 PVOID exe_base, exit_thread_ptr;
3736 HANDLE thread_handle = NULL;
3737 DWORD dret, exit_code = 0;
3738 CONTEXT ctx;
3739
3740 exit_thread_ptr = GetProcAddress(hkernel32, "ExitThread");
3741 ok(exit_thread_ptr != NULL, "GetProcAddress ExitThread failed\n");
3742
3743 si.cb = sizeof(si);
3745 ok(ret, "Failed to create process (%ld)\n", GetLastError());
3746
3747 exe_base = get_process_exe(pi.hProcess, &nt_header);
3748 ok(exe_base != NULL, "Could not find EXE in remote process\n");
3749
3750 ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
3751 ok(!ret, "IAT entry resolved prematurely\n");
3752
3753 thread_handle = CreateRemoteThread(pi.hProcess, NULL, 0,
3754 (LPTHREAD_START_ROUTINE)exit_thread_ptr,
3756 ok(thread_handle != NULL, "Could not create remote thread (%ld)\n", GetLastError());
3757
3758 ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
3759 ok(!ret, "IAT entry resolved prematurely\n");
3760
3761 ctx.ContextFlags = CONTEXT_ALL;
3762 ret = GetThreadContext( thread_handle, &ctx );
3763 ok( ret, "Failed retrieving remote thread context (%ld)\n", GetLastError() );
3764 ok( ctx.ContextFlags == CONTEXT_ALL, "wrong flags %lx\n", ctx.ContextFlags );
3765#ifdef __x86_64__
3766 ok( !ctx.Rax, "rax is not zero %Ix\n", ctx.Rax );
3767 ok( !ctx.Rbx, "rbx is not zero %Ix\n", ctx.Rbx );
3768 ok( ctx.Rcx == (ULONG_PTR)exit_thread_ptr, "wrong rcx %Ix/%p\n", ctx.Rcx, exit_thread_ptr );
3769 ok( ctx.Rdx == 0x1234, "wrong rdx %Ix\n", ctx.Rdx );
3770 ok( !ctx.Rsi, "rsi is not zero %Ix\n", ctx.Rsi );
3771 ok( !ctx.Rdi, "rdi is not zero %Ix\n", ctx.Rdi );
3772 ok( !ctx.Rbp, "rbp is not zero %Ix\n", ctx.Rbp );
3773 ok( !ctx.R8, "r8 is not zero %Ix\n", ctx.R8 );
3774 ok( !ctx.R9, "r9 is not zero %Ix\n", ctx.R9 );
3775 ok( !ctx.R10, "r10 is not zero %Ix\n", ctx.R10 );
3776 ok( !ctx.R11, "r11 is not zero %Ix\n", ctx.R11 );
3777 ok( !ctx.R12, "r12 is not zero %Ix\n", ctx.R12 );
3778 ok( !ctx.R13, "r13 is not zero %Ix\n", ctx.R13 );
3779 ok( !ctx.R14, "r14 is not zero %Ix\n", ctx.R14 );
3780 ok( !ctx.R15, "r15 is not zero %Ix\n", ctx.R15 );
3781 ok( ctx.EFlags == 0x200, "wrong flags %08lx\n", ctx.EFlags );
3782 ok( ctx.MxCsr == 0x1f80, "wrong mxcsr %08lx\n", ctx.MxCsr );
3783 ok( ctx.FltSave.ControlWord == 0x27f, "wrong control %08x\n", ctx.FltSave.ControlWord );
3784#else
3785 ok( !ctx.Ebp || broken(ctx.Ebp), /* winxp */ "ebp is not zero %08lx\n", ctx.Ebp );
3786 if (!ctx.Ebp) /* winxp is completely different */
3787 {
3788 ok( !ctx.Ecx, "ecx is not zero %08lx\n", ctx.Ecx );
3789 ok( !ctx.Edx, "edx is not zero %08lx\n", ctx.Edx );
3790 ok( !ctx.Esi, "esi is not zero %08lx\n", ctx.Esi );
3791 ok( !ctx.Edi, "edi is not zero %08lx\n", ctx.Edi );
3792 }
3793 ok( ctx.Eax == (ULONG_PTR)exit_thread_ptr, "wrong eax %08lx/%p\n", ctx.Eax, exit_thread_ptr );
3794 ok( ctx.Ebx == 0x1234, "wrong ebx %08lx\n", ctx.Ebx );
3795 ok( (ctx.EFlags & ~2) == 0x200, "wrong flags %08lx\n", ctx.EFlags );
3796 ok( (WORD)ctx.FloatSave.ControlWord == 0x27f, "wrong control %08lx\n", ctx.FloatSave.ControlWord );
3797 ok( *(WORD *)ctx.ExtendedRegisters == 0x27f, "wrong control %08x\n", *(WORD *)ctx.ExtendedRegisters );
3798#endif
3799
3800 ResumeThread( thread_handle );
3801 dret = WaitForSingleObject(thread_handle, 60000);
3802 ok(dret == WAIT_OBJECT_0, "Waiting for remote thread failed (%ld)\n", GetLastError());
3803 ret = GetExitCodeThread(thread_handle, &exit_code);
3804 ok(ret, "Failed to retrieve remote thread exit code (%ld)\n", GetLastError());
3805 ok(exit_code == 0x1234, "Invalid remote thread exit code\n");
3806
3807 ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
3808 ok(ret, "EXE IAT entry not resolved\n");
3809
3810 if (thread_handle)
3811 CloseHandle(thread_handle);
3812
3813 /* Note that the child's main thread is still suspended so the exit code
3814 * is set by the TerminateProcess() call.
3815 */
3818}
3819
3820static void test_SuspendProcessState(void)
3821{
3822 struct pipe_params
3823 {
3824 ULONG pipe_write_buf;
3825 ULONG pipe_read_buf;
3826 ULONG bytes_returned;
3827 CHAR pipe_name[MAX_PATH];
3828 };
3829
3830#ifdef __x86_64__
3831 struct remote_rop_chain
3832 {
3833 void *exit_process_ptr;
3834 ULONG_PTR home_rcx;
3835 ULONG_PTR home_rdx;
3836 ULONG_PTR home_r8;
3837 ULONG_PTR home_r9;
3838 ULONG_PTR pipe_read_buf_size;
3839 ULONG_PTR bytes_returned;
3841 };
3842#else
3843 struct remote_rop_chain
3844 {
3845 void *exit_process_ptr;
3846 ULONG_PTR pipe_name;
3847 ULONG_PTR pipe_write_buf;
3848 ULONG_PTR pipe_write_buf_size;
3849 ULONG_PTR pipe_read_buf;
3850 ULONG_PTR pipe_read_buf_size;
3851 ULONG_PTR bytes_returned;
3853 void *unreached_ret;
3855 };
3856#endif
3857
3858 static const char pipe_name[] = "\\\\.\\pipe\\TestPipe";
3859 static const ULONG pipe_write_magic = 0x454e4957;
3860 STARTUPINFOA si = {0};
3861 PROCESS_INFORMATION pi = {0};
3862 PVOID exe_base, remote_pipe_params, exit_process_ptr,
3863 call_named_pipe_a;
3865 struct pipe_params pipe_params;
3866 struct remote_rop_chain rop_chain;
3867 CONTEXT ctx;
3868 HANDLE server_pipe_handle;
3869 BOOL pipe_connected;
3870 ULONG pipe_magic, numb;
3871 BOOL ret;
3872 void *user_thread_start, *start_ptr, *entry_ptr, *peb_ptr;
3873 PEB child_peb, *peb = NtCurrentTeb()->Peb;
3874
3875 exit_process_ptr = GetProcAddress(hkernel32, "ExitProcess");
3876 ok(exit_process_ptr != NULL, "GetProcAddress ExitProcess failed\n");
3877
3878 call_named_pipe_a = GetProcAddress(hkernel32, "CallNamedPipeA");
3879 ok(call_named_pipe_a != NULL, "GetProcAddress CallNamedPipeA failed\n");
3880
3881 si.cb = sizeof(si);
3883 ok(ret, "Failed to create process (%ld)\n", GetLastError());
3884
3885 exe_base = get_process_exe(pi.hProcess, &nt_header);
3886 /* Make sure we found the EXE in the new process */
3887 ok(exe_base != NULL, "Could not find EXE in remote process\n");
3888
3889 ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
3890 ok(!ret, "IAT entry resolved prematurely\n");
3891
3892 server_pipe_handle = CreateNamedPipeA(pipe_name, PIPE_ACCESS_DUPLEX | FILE_FLAG_WRITE_THROUGH,
3893 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0x20000, 0x20000,
3894 0, NULL);
3895 ok(server_pipe_handle != INVALID_HANDLE_VALUE, "Failed to create communication pipe (%ld)\n", GetLastError());
3896
3897 /* Set up the remote process environment */
3898 ctx.ContextFlags = CONTEXT_ALL;
3900 ok(ret, "Failed retrieving remote thread context (%ld)\n", GetLastError());
3901 ok( ctx.ContextFlags == CONTEXT_ALL, "wrong flags %lx\n", ctx.ContextFlags );
3902
3903 remote_pipe_params = VirtualAllocEx(pi.hProcess, NULL, sizeof(pipe_params), MEM_COMMIT, PAGE_READWRITE);
3904 ok(remote_pipe_params != NULL, "Failed allocating memory in remote process (%ld)\n", GetLastError());
3905
3906 pipe_params.pipe_write_buf = pipe_write_magic;
3907 pipe_params.pipe_read_buf = 0;
3908 pipe_params.bytes_returned = 0;
3909 strcpy(pipe_params.pipe_name, pipe_name);
3910
3911 ret = WriteProcessMemory(pi.hProcess, remote_pipe_params,
3912 &pipe_params, sizeof(pipe_params), NULL);
3913 ok(ret, "Failed to write to remote process memory (%ld)\n", GetLastError());
3914
3915#ifdef __x86_64__
3916 ok( !ctx.Rax, "rax is not zero %Ix\n", ctx.Rax );
3917 ok( !ctx.Rbx, "rbx is not zero %Ix\n", ctx.Rbx );
3918 ok( !ctx.Rsi, "rsi is not zero %Ix\n", ctx.Rsi );
3919 ok( !ctx.Rdi, "rdi is not zero %Ix\n", ctx.Rdi );
3920 ok( !ctx.Rbp, "rbp is not zero %Ix\n", ctx.Rbp );
3921 ok( !ctx.R8, "r8 is not zero %Ix\n", ctx.R8 );
3922 ok( !ctx.R9, "r9 is not zero %Ix\n", ctx.R9 );
3923 ok( !ctx.R10, "r10 is not zero %Ix\n", ctx.R10 );
3924 ok( !ctx.R11, "r11 is not zero %Ix\n", ctx.R11 );
3925 ok( !ctx.R12, "r12 is not zero %Ix\n", ctx.R12 );
3926 ok( !ctx.R13, "r13 is not zero %Ix\n", ctx.R13 );
3927 ok( !ctx.R14, "r14 is not zero %Ix\n", ctx.R14 );
3928 ok( !ctx.R15, "r15 is not zero %Ix\n", ctx.R15 );
3929 ok( ctx.EFlags == 0x200, "wrong flags %08lx\n", ctx.EFlags );
3930 ok( ctx.MxCsr == 0x1f80, "wrong mxcsr %08lx\n", ctx.MxCsr );
3931 ok( ctx.FltSave.ControlWord == 0x27f, "wrong control %08x\n", ctx.FltSave.ControlWord );
3932 start_ptr = (void *)ctx.Rip;
3933 entry_ptr = (void *)ctx.Rcx;
3934 peb_ptr = (void *)ctx.Rdx;
3935
3936 rop_chain.exit_process_ptr = exit_process_ptr;
3937 ctx.Rcx = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_name);
3938 ctx.Rdx = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_write_buf);
3939 ctx.R8 = sizeof(pipe_params.pipe_write_buf);
3940 ctx.R9 = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_read_buf);
3941 rop_chain.pipe_read_buf_size = sizeof(pipe_params.pipe_read_buf);
3942 rop_chain.bytes_returned = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, bytes_returned);
3943 rop_chain.timeout = 10000;
3944
3945 ctx.Rip = (ULONG_PTR)call_named_pipe_a;
3946 ctx.Rsp -= sizeof(rop_chain);
3947 ret = WriteProcessMemory(pi.hProcess, (void *)ctx.Rsp, &rop_chain, sizeof(rop_chain), NULL);
3948 ok(ret, "Failed to write to remote process thread stack (%ld)\n", GetLastError());
3949#else
3950 ok( !ctx.Ebp || broken(ctx.Ebp), /* winxp */ "ebp is not zero %08lx\n", ctx.Ebp );
3951 if (!ctx.Ebp) /* winxp is completely different */
3952 {
3953 ok( !ctx.Ecx, "ecx is not zero %08lx\n", ctx.Ecx );
3954 ok( !ctx.Edx, "edx is not zero %08lx\n", ctx.Edx );
3955 ok( !ctx.Esi, "esi is not zero %08lx\n", ctx.Esi );
3956 ok( !ctx.Edi, "edi is not zero %08lx\n", ctx.Edi );
3957 }
3958 ok( (ctx.EFlags & ~2) == 0x200, "wrong flags %08lx\n", ctx.EFlags );
3959 ok( (WORD)ctx.FloatSave.ControlWord == 0x27f, "wrong control %08lx\n", ctx.FloatSave.ControlWord );
3960 ok( *(WORD *)ctx.ExtendedRegisters == 0x27f, "wrong control %08x\n", *(WORD *)ctx.ExtendedRegisters );
3961 start_ptr = (void *)ctx.Eip;
3962 entry_ptr = (void *)ctx.Eax;
3963 peb_ptr = (void *)ctx.Ebx;
3964
3965 rop_chain.exit_process_ptr = exit_process_ptr;
3966 rop_chain.pipe_name = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_name);
3967 rop_chain.pipe_write_buf = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_write_buf);
3968 rop_chain.pipe_write_buf_size = sizeof(pipe_params.pipe_write_buf);
3969 rop_chain.pipe_read_buf = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, pipe_read_buf);
3970 rop_chain.pipe_read_buf_size = sizeof(pipe_params.pipe_read_buf);
3971 rop_chain.bytes_returned = (ULONG_PTR)remote_pipe_params + offsetof(struct pipe_params, bytes_returned);
3972 rop_chain.timeout = 10000;
3973 rop_chain.exit_code = 0;
3974
3975 ctx.Eip = (ULONG_PTR)call_named_pipe_a;
3976 ctx.Esp -= sizeof(rop_chain);
3977 ret = WriteProcessMemory(pi.hProcess, (void *)ctx.Esp, &rop_chain, sizeof(rop_chain), NULL);
3978 ok(ret, "Failed to write to remote process thread stack (%ld)\n", GetLastError());
3979#endif
3980
3981 ret = ReadProcessMemory( pi.hProcess, peb_ptr, &child_peb, sizeof(child_peb), NULL );
3982 ok( ret, "Failed to read PEB (%lu)\n", GetLastError() );
3983 ok( child_peb.ImageBaseAddress == exe_base, "wrong base %p/%p\n",
3984 child_peb.ImageBaseAddress, exe_base );
3985 user_thread_start = GetProcAddress( GetModuleHandleA("ntdll.dll"), "RtlUserThreadStart" );
3986 if (user_thread_start)
3987 ok( start_ptr == user_thread_start,
3988 "wrong start addr %p / %p\n", start_ptr, user_thread_start );
3989 ok( entry_ptr == (char *)exe_base + nt_header.OptionalHeader.AddressOfEntryPoint,
3990 "wrong entry point %p/%p\n", entry_ptr,
3991 (char *)exe_base + nt_header.OptionalHeader.AddressOfEntryPoint );
3992
3993 ok( !child_peb.LdrData, "LdrData set %p\n", child_peb.LdrData );
3994 ok( !child_peb.FastPebLock, "FastPebLock set %p\n", child_peb.FastPebLock );
3995 ok( !child_peb.TlsBitmap, "TlsBitmap set %p\n", child_peb.TlsBitmap );
3996 ok( !child_peb.TlsExpansionBitmap, "TlsExpansionBitmap set %p\n", child_peb.TlsExpansionBitmap );
3997 ok( !child_peb.LoaderLock, "LoaderLock set %p\n", child_peb.LoaderLock );
3998 ok( !child_peb.ProcessHeap, "ProcessHeap set %p\n", child_peb.ProcessHeap );
3999 ok( !child_peb.CSDVersion.Buffer, "CSDVersion set %s\n", debugstr_w(child_peb.CSDVersion.Buffer) );
4000
4001 ok( child_peb.OSMajorVersion == peb->OSMajorVersion, "OSMajorVersion not set %lu\n", child_peb.OSMajorVersion );
4002 ok( child_peb.OSPlatformId == peb->OSPlatformId, "OSPlatformId not set %lu\n", child_peb.OSPlatformId );
4003 ok( child_peb.SessionId == peb->SessionId, "SessionId not set %lu\n", child_peb.SessionId );
4004 ok( child_peb.CriticalSectionTimeout.QuadPart, "CriticalSectionTimeout not set %s\n",
4006 ok( child_peb.HeapSegmentReserve == peb->HeapSegmentReserve,
4007 "HeapSegmentReserve not set %Iu\n", child_peb.HeapSegmentReserve );
4008 ok( child_peb.HeapSegmentCommit == peb->HeapSegmentCommit,
4009 "HeapSegmentCommit not set %Iu\n", child_peb.HeapSegmentCommit );
4011 "HeapDeCommitTotalFreeThreshold not set %Iu\n", child_peb.HeapDeCommitTotalFreeThreshold );
4013 "HeapDeCommitFreeBlockThreshold not set %Iu\n", child_peb.HeapDeCommitFreeBlockThreshold );
4014
4015 if (pNtQueryInformationThread)
4016 {
4017 TEB child_teb;
4019 NTSTATUS status = pNtQueryInformationThread( pi.hThread, ThreadBasicInformation,
4020 &info, sizeof(info), NULL );
4021 ok( !status, "NtQueryInformationProcess failed %lx\n", status );
4022 ret = ReadProcessMemory( pi.hProcess, info.TebBaseAddress, &child_teb, sizeof(child_teb), NULL );
4023 ok( ret, "Failed to read TEB (%lu)\n", GetLastError() );
4024
4025 ok( child_teb.Peb == peb_ptr, "wrong Peb %p / %p\n", child_teb.Peb, peb_ptr );
4026 ok( PtrToUlong(child_teb.ClientId.UniqueProcess) == pi.dwProcessId, "wrong pid %lx / %lx\n",
4028 ok( PtrToUlong(child_teb.ClientId.UniqueThread) == pi.dwThreadId, "wrong tid %lx / %lx\n",
4030 ok( PtrToUlong(child_teb.RealClientId.UniqueProcess) == pi.dwProcessId, "wrong real pid %lx / %lx\n",
4032 ok( PtrToUlong(child_teb.RealClientId.UniqueThread) == pi.dwThreadId, "wrong real tid %lx / %lx\n",
4034 ok( child_teb.StaticUnicodeString.MaximumLength == sizeof(child_teb.StaticUnicodeBuffer),
4035 "StaticUnicodeString.MaximumLength wrong %x\n", child_teb.StaticUnicodeString.MaximumLength );
4036 ok( (char *)child_teb.StaticUnicodeString.Buffer == (char *)info.TebBaseAddress + offsetof(TEB, StaticUnicodeBuffer),
4037 "StaticUnicodeString.Buffer wrong %p\n", child_teb.StaticUnicodeString.Buffer );
4038
4039 ok( !child_teb.CurrentLocale, "CurrentLocale set %lx\n", child_teb.CurrentLocale );
4040 ok( !child_teb.TlsLinks.Flink, "TlsLinks.Flink set %p\n", child_teb.TlsLinks.Flink );
4041 ok( !child_teb.TlsLinks.Blink, "TlsLinks.Blink set %p\n", child_teb.TlsLinks.Blink );
4042 ok( !child_teb.TlsExpansionSlots, "TlsExpansionSlots set %p\n", child_teb.TlsExpansionSlots );
4043 ok( !child_teb.FlsSlots, "FlsSlots set %p\n", child_teb.FlsSlots );
4044 }
4045
4047 ok(ret, "Failed to set remote thread context (%ld)\n", GetLastError());
4048
4050
4051 pipe_connected = ConnectNamedPipe(server_pipe_handle, NULL) || (GetLastError() == ERROR_PIPE_CONNECTED);
4052 ok(pipe_connected, "Pipe did not connect\n");
4053
4054 ret = ReadFile(server_pipe_handle, &pipe_magic, sizeof(pipe_magic), &numb, NULL);
4055 ok(ret, "Failed to read buffer from pipe (%ld)\n", GetLastError());
4056
4057 ok(pipe_magic == pipe_write_magic, "Did not get the correct magic from the remote process\n");
4058
4059 /* Validate the imports: at this point the thread in the new process
4060 * should have initialized the EXE module imports and called each dll's
4061 * DllMain(), notifying it of the new thread in the process.
4062 */
4063 ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
4064 ok(ret, "EXE IAT is not resolved\n");
4065
4066 ret = WriteFile(server_pipe_handle, &pipe_magic, sizeof(pipe_magic), &numb, NULL);
4067 ok(ret, "Failed to write the magic back to the pipe (%ld)\n", GetLastError());
4068 CloseHandle(server_pipe_handle);
4069
4070 /* Avoid wait_child_process() because the exit code results from a race
4071 * between the TerminateProcess() call and the child's ExitProcess() call
4072 * which uses a random value in the 64 bit case.
4073 */
4078}
4079#else
4081{
4082}
4084{
4085}
4086#endif
4087
4089{
4091 UCHAR node;
4092 BOOL ret;
4093 int i;
4094
4095 if (!pGetNumaProcessorNode)
4096 {
4097 win_skip("GetNumaProcessorNode is missing\n");
4098 return;
4099 }
4100
4101 GetSystemInfo(&si);
4102 for (i = 0; i < 256; i++)
4103 {
4104 SetLastError(0xdeadbeef);
4105 node = (i < si.dwNumberOfProcessors) ? 0xFF : 0xAA;
4106 ret = pGetNumaProcessorNode(i, &node);
4108 {
4109 ok(ret, "GetNumaProcessorNode returned FALSE for processor %d\n", i);
4110 ok(node != 0xFF, "expected node != 0xFF, but got 0xFF\n");
4111 }
4112 else
4113 {
4114 ok(!ret, "GetNumaProcessorNode returned TRUE for processor %d\n", i);
4115 ok(node == 0xFF || broken(node == 0xAA) /* WinXP */, "expected node 0xFF, got %x\n", node);
4116 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
4117 }
4118 }
4119}
4120
4121static void test_session_info(void)
4122{
4123 DWORD session_id, active_session;
4124 BOOL r;
4125
4126 r = ProcessIdToSessionId(GetCurrentProcessId(), &session_id);
4127 ok(r, "ProcessIdToSessionId failed: %lu\n", GetLastError());
4128 trace("session_id = %lx\n", session_id);
4129
4130 active_session = pWTSGetActiveConsoleSessionId();
4131 trace("active_session = %lx\n", active_session);
4132}
4133
4134static void test_process_info(HANDLE hproc)
4135{
4136 char buf[4096];
4137 static const ULONG info_size[] =
4138 {
4139 sizeof(PROCESS_BASIC_INFORMATION) /* ProcessBasicInformation */,
4140 sizeof(QUOTA_LIMITS) /* ProcessQuotaLimits */,
4141 sizeof(IO_COUNTERS) /* ProcessIoCounters */,
4142 sizeof(VM_COUNTERS) /* ProcessVmCounters */,
4143 sizeof(KERNEL_USER_TIMES) /* ProcessTimes */,
4144 sizeof(ULONG) /* ProcessBasePriority */,
4145 sizeof(ULONG) /* ProcessRaisePriority */,
4146 sizeof(HANDLE) /* ProcessDebugPort */,
4147 sizeof(HANDLE) /* ProcessExceptionPort */,
4148 0 /* FIXME: sizeof(PROCESS_ACCESS_TOKEN) ProcessAccessToken */,
4149 0 /* FIXME: sizeof(PROCESS_LDT_INFORMATION) ProcessLdtInformation */,
4150 0 /* FIXME: sizeof(PROCESS_LDT_SIZE) ProcessLdtSize */,
4151 sizeof(ULONG) /* ProcessDefaultHardErrorMode */,
4152 0 /* ProcessIoPortHandlers: kernel-mode only */,
4153 0 /* FIXME: sizeof(POOLED_USAGE_AND_LIMITS) ProcessPooledUsageAndLimits */,
4154 0 /* FIXME: sizeof(PROCESS_WS_WATCH_INFORMATION) ProcessWorkingSetWatch */,
4155 sizeof(ULONG) /* ProcessUserModeIOPL */,
4156 sizeof(BOOLEAN) /* ProcessEnableAlignmentFaultFixup */,
4157 sizeof(PROCESS_PRIORITY_CLASS) /* ProcessPriorityClass */,
4158 sizeof(ULONG) /* ProcessWx86Information */,
4159 sizeof(ULONG) /* ProcessHandleCount */,
4160 sizeof(ULONG_PTR) /* ProcessAffinityMask */,
4161 sizeof(ULONG) /* ProcessPriorityBoost */,
4162 0 /* sizeof(PROCESS_DEVICEMAP_INFORMATION) ProcessDeviceMap */,
4163 0 /* sizeof(PROCESS_SESSION_INFORMATION) ProcessSessionInformation */,
4164 0 /* sizeof(PROCESS_FOREGROUND_BACKGROUND) ProcessForegroundInformation */,
4165 sizeof(ULONG_PTR) /* ProcessWow64Information */,
4166 sizeof(buf) /* ProcessImageFileName */,
4167 sizeof(ULONG) /* ProcessLUIDDeviceMapsEnabled */,
4168 sizeof(ULONG) /* ProcessBreakOnTermination */,
4169 sizeof(HANDLE) /* ProcessDebugObjectHandle */,
4170 sizeof(ULONG) /* ProcessDebugFlags */,
4171 sizeof(buf) /* ProcessHandleTracing */,
4172 sizeof(ULONG) /* ProcessIoPriority */,
4173 sizeof(ULONG) /* ProcessExecuteFlags */,
4174 0 /* FIXME: sizeof(?) ProcessTlsInformation */,
4175 sizeof(ULONG) /* ProcessCookie */,
4176 sizeof(SECTION_IMAGE_INFORMATION) /* ProcessImageInformation */,
4177 sizeof(PROCESS_CYCLE_TIME_INFORMATION) /* ProcessCycleTime */,
4178 sizeof(ULONG) /* ProcessPagePriority */,
4179 40 /* ProcessInstrumentationCallback */,
4180 0 /* FIXME: sizeof(PROCESS_STACK_ALLOCATION_INFORMATION) ProcessThreadStackAllocation */,
4181 0 /* FIXME: sizeof(PROCESS_WS_WATCH_INFORMATION_EX[]) ProcessWorkingSetWatchEx */,
4182 sizeof(buf) /* ProcessImageFileNameWin32 */,
4183#if 0 /* FIXME: Add remaining classes */
4184 sizeof(HANDLE) /* ProcessImageFileMapping */,
4185 sizeof(PROCESS_AFFINITY_UPDATE_MODE) /* ProcessAffinityUpdateMode */,
4186 sizeof(PROCESS_MEMORY_ALLOCATION_MODE) /* ProcessMemoryAllocationMode */,
4187 sizeof(USHORT[]) /* ProcessGroupInformation */,
4188 sizeof(ULONG) /* ProcessTokenVirtualizationEnabled */,
4189 sizeof(ULONG_PTR) /* ProcessConsoleHostProcess */,
4190 sizeof(PROCESS_WINDOW_INFORMATION) /* ProcessWindowInformation */,
4191 sizeof(PROCESS_HANDLE_SNAPSHOT_INFORMATION) /* ProcessHandleInformation */,
4192 sizeof(PROCESS_MITIGATION_POLICY_INFORMATION) /* ProcessMitigationPolicy */,
4193 sizeof(ProcessDynamicFunctionTableInformation) /* ProcessDynamicFunctionTableInformation */,
4194 sizeof(?) /* ProcessHandleCheckingMode */,
4195 sizeof(PROCESS_KEEPALIVE_COUNT_INFORMATION) /* ProcessKeepAliveCount */,
4196 sizeof(PROCESS_REVOKE_FILE_HANDLES_INFORMATION) /* ProcessRevokeFileHandles */,
4197 sizeof(PROCESS_WORKING_SET_CONTROL) /* ProcessWorkingSetControl */,
4198 sizeof(?) /* ProcessHandleTable */,
4199 sizeof(?) /* ProcessCheckStackExtentsMode */,
4200 sizeof(buf) /* ProcessCommandLineInformation */,
4201 sizeof(PS_PROTECTION) /* ProcessProtectionInformation */,
4202 sizeof(PROCESS_MEMORY_EXHAUSTION_INFO) /* ProcessMemoryExhaustion */,
4203 sizeof(PROCESS_FAULT_INFORMATION) /* ProcessFaultInformation */,
4204 sizeof(PROCESS_TELEMETRY_ID_INFORMATION) /* ProcessTelemetryIdInformation */,
4205 sizeof(PROCESS_COMMIT_RELEASE_INFORMATION) /* ProcessCommitReleaseInformation */,
4206 sizeof(?) /* ProcessDefaultCpuSetsInformation */,
4207 sizeof(?) /* ProcessAllowedCpuSetsInformation */,
4208 0 /* ProcessReserved1Information */,
4209 0 /* ProcessReserved2Information */,
4210 sizeof(?) /* ProcessSubsystemProcess */,
4211 sizeof(PROCESS_JOB_MEMORY_INFO) /* ProcessJobMemoryInformation */,
4212#endif
4213 };
4215 BOOL is_current = hproc == GetCurrentProcess();
4216
4217 if (!pNtQueryInformationProcess)
4218 {
4219 win_skip("NtQueryInformationProcess is not available on this platform\n");
4220 return;
4221 }
4222
4223 for (i = 0; i < ARRAY_SIZE(info_size); i++)
4224 {
4225 ret_len = 0;
4226 status = pNtQueryInformationProcess(hproc, i, buf, info_size[i], &ret_len);
4227 if (status == STATUS_NOT_IMPLEMENTED) continue;
4228 if (status == STATUS_INVALID_INFO_CLASS) continue;
4229 if (status == STATUS_INFO_LENGTH_MISMATCH) continue;
4230
4231 switch (i)
4232 {
4234 case ProcessQuotaLimits:
4235 case ProcessTimes:
4239 case ProcessIoPriority:
4240 case ProcessIoCounters:
4241 case ProcessVmCounters:
4244 case ProcessHandleCount:
4247 case ProcessCycleTime:
4250#ifdef __REACTOS__
4251 ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_DENIED || status == STATUS_INVALID_PARAMETER) /* WS03 */, "for info %lu expected STATUS_SUCCESS, got %08lx (ret_len %lu)\n", i, status, ret_len);
4252#else
4253 ok(status == STATUS_SUCCESS, "for info %lu expected STATUS_SUCCESS, got %08lx (ret_len %lu)\n", i, status, ret_len);
4254#endif
4255 break;
4256
4259 ok(status == STATUS_ACCESS_DENIED /* before win8 */ || status == STATUS_SUCCESS /* win8 is less strict */,
4260 "for info %lu expected STATUS_SUCCESS, got %08lx (ret_len %lu)\n", i, status, ret_len);
4261 break;
4262
4265 "for info %lu expected STATUS_ACCESS_DENIED, got %08lx (ret_len %lu)\n", i, status, ret_len);
4266 break;
4267 case ProcessCookie:
4268 if (is_current)
4269 ok(status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER /* before win8 */,
4270 "for info %lu got %08lx (ret_len %lu)\n", i, status, ret_len);
4271 else
4273 "for info %lu got %08lx (ret_len %lu)\n", i, status, ret_len);
4274 break;
4276 case ProcessDebugPort:
4277 case ProcessDebugFlags:
4278 if (is_current)
4280 "for info %lu, got %08lx (ret_len %lu)\n", i, status, ret_len);
4281 else
4282 todo_wine
4283#ifdef __REACTOS__
4285#else
4287#endif
4288 "for info %lu expected STATUS_ACCESS_DENIED, got %08lx (ret_len %lu)\n", i, status, ret_len);
4289 break;
4290
4291 default:
4292 if (is_current)
4294 "for info %lu, got %08lx (ret_len %lu)\n", i, status, ret_len);
4295 else
4297 "for info %lu expected STATUS_ACCESS_DENIED, got %08lx (ret_len %lu)\n", i, status, ret_len);
4298 break;
4299 }
4300 }
4301}
4302
4304{
4306 DWORD len;
4307 BOOL ret;
4308
4309 if (!pGetLogicalProcessorInformationEx)
4310 {
4311 win_skip("GetLogicalProcessorInformationEx() is not supported\n");
4312 return;
4313 }
4314
4315 ret = pGetLogicalProcessorInformationEx(RelationAll, NULL, NULL);
4316 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %ld\n", ret, GetLastError());
4317
4318 len = 0;
4319 ret = pGetLogicalProcessorInformationEx(RelationProcessorCore, NULL, &len);
4320 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d, error %ld\n", ret, GetLastError());
4321 ok(len > 0, "got %lu\n", len);
4322
4323 len = 0;
4324 ret = pGetLogicalProcessorInformationEx(RelationAll, NULL, &len);
4325 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d, error %ld\n", ret, GetLastError());
4326 ok(len > 0, "got %lu\n", len);
4327
4329 ret = pGetLogicalProcessorInformationEx(RelationAll, info, &len);
4330 ok(ret, "got %d, error %ld\n", ret, GetLastError());
4331 ok(info->Size > 0, "got %lu\n", info->Size);
4333}
4334
4336{
4337#ifdef __REACTOS__
4338 skip("Cannot build test_GetSystemCpuSetInformation() until kernelbase is synced.\n");
4339#else
4342 ULONG size, expected_size;
4345 BOOL ret;
4346
4347 if (!pGetSystemCpuSetInformation)
4348 {
4349 win_skip("GetSystemCpuSetInformation() is not supported.\n");
4350 return;
4351 }
4352
4353 GetSystemInfo(&si);
4354
4355 expected_size = sizeof(*info) * si.dwNumberOfProcessors;
4356
4357 if (0)
4358 {
4359 /* Crashes on Windows with NULL return length. */
4360 pGetSystemCpuSetInformation(NULL, 0, NULL, process, 0);
4361 }
4362
4363 size = 0xdeadbeef;
4364 SetLastError(0xdeadbeef);
4365 ret = pGetSystemCpuSetInformation(NULL, size, &size, process, 0);
4366 ok(!ret && GetLastError() == ERROR_NOACCESS, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4367 ok(!size, "Got unexpected size %lu.\n", size);
4368
4369 size = 0xdeadbeef;
4370 SetLastError(0xdeadbeef);
4371 ret = pGetSystemCpuSetInformation(NULL, 0, &size, (HANDLE)0xdeadbeef, 0);
4372 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4373 ok(!size, "Got unexpected size %lu.\n", size);
4374
4375 size = 0xdeadbeef;
4376 SetLastError(0xdeadbeef);
4377 ret = pGetSystemCpuSetInformation(NULL, 0, &size, process, 0);
4378 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4379 ok(size == expected_size, "Got unexpected size %lu.\n", size);
4380
4381 info = heap_alloc(size);
4382 info_nt = heap_alloc(size);
4383
4384 status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), info_nt, expected_size, NULL);
4385 ok(!status, "Got unexpected status %#lx.\n", status);
4386
4387 size = 0xdeadbeef;
4388 SetLastError(0xdeadbeef);
4389 ret = pGetSystemCpuSetInformation(info, expected_size, &size, process, 0);
4390 ok(ret && GetLastError() == 0xdeadbeef, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4391 ok(size == expected_size, "Got unexpected size %lu.\n", size);
4392
4393 ok(!memcmp(info, info_nt, expected_size), "Info does not match NtQuerySystemInformationEx().\n");
4394
4395 heap_free(info_nt);
4396 heap_free(info);
4397#endif
4398}
4399
4400static void test_largepages(void)
4401{
4402 SIZE_T size;
4403
4404 if (!pGetLargePageMinimum) {
4405 win_skip("No GetLargePageMinimum support.\n");
4406 return;
4407 }
4408 size = pGetLargePageMinimum();
4409
4410 ok((size == 0) || (size == 2*1024*1024) || (size == 4*1024*1024), "GetLargePageMinimum reports %Id size\n", size);
4411}
4412
4413struct proc_thread_attr
4414{
4416 SIZE_T size;
4417 void *value;
4418};
4419
4421{
4422 DWORD mask; /* bitmask of items in list */
4423 DWORD size; /* max number of items in list */
4424 DWORD count; /* number of items in list */
4425 DWORD pad;
4426 DWORD_PTR unk;
4427 struct proc_thread_attr attrs[10];
4428};
4429
4431{
4432 BOOL ret;
4433 SIZE_T size, needed;
4434 int i;
4435 struct _PROC_THREAD_ATTRIBUTE_LIST list, expect_list;
4436 HANDLE handles[4];
4437
4438 if (!pInitializeProcThreadAttributeList)
4439 {
4440 win_skip("No support for ProcThreadAttributeList\n");
4441 return;
4442 }
4443
4444 for (i = 0; i <= 10; i++)
4445 {
4447 ret = pInitializeProcThreadAttributeList(NULL, i, 0, &size);
4448 ok(!ret, "got %d\n", ret);
4449 if(i >= 4 && GetLastError() == ERROR_INVALID_PARAMETER) /* Vista only allows a maximium of 3 slots */
4450 break;
4452 ok(size == needed, "%d: got %Id expect %Id\n", i, size, needed);
4453
4454 memset(&list, 0xcc, sizeof(list));
4455 ret = pInitializeProcThreadAttributeList(&list, i, 0, &size);
4456 ok(ret, "got %d\n", ret);
4457 ok(list.mask == 0, "%d: got %08lx\n", i, list.mask);
4458 ok(list.size == i, "%d: got %08lx\n", i, list.size);
4459 ok(list.count == 0, "%d: got %08lx\n", i, list.count);
4460 ok(list.unk == 0, "%d: got %08Ix\n", i, list.unk);
4461 }
4462
4463 memset(handles, 0, sizeof(handles));
4464 memset(&expect_list, 0xcc, sizeof(expect_list));
4465 expect_list.mask = 0;
4466 expect_list.size = i - 1;
4467 expect_list.count = 0;
4468 expect_list.unk = 0;
4469
4470 ret = pUpdateProcThreadAttribute(&list, 0, 0xcafe, handles, sizeof(PROCESSOR_NUMBER), NULL, NULL);
4471 ok(!ret, "got %d\n", ret);
4472 ok(GetLastError() == ERROR_NOT_SUPPORTED, "got %ld\n", GetLastError());
4473
4474 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]) / 2, NULL, NULL);
4475 ok(!ret, "got %d\n", ret);
4476 ok(GetLastError() == ERROR_BAD_LENGTH, "got %ld\n", GetLastError());
4477
4478 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]) * 2, NULL, NULL);
4479 ok(!ret, "got %d\n", ret);
4480 ok(GetLastError() == ERROR_BAD_LENGTH, "got %ld\n", GetLastError());
4481
4482 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]), NULL, NULL);
4483 ok(ret, "got %d\n", ret);
4484
4485 expect_list.mask |= 1 << ProcThreadAttributeParentProcess;
4486 expect_list.attrs[0].attr = PROC_THREAD_ATTRIBUTE_PARENT_PROCESS;
4487 expect_list.attrs[0].size = sizeof(handles[0]);
4488 expect_list.attrs[0].value = handles;
4489 expect_list.count++;
4490
4491 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]), NULL, NULL);
4492 ok(!ret, "got %d\n", ret);
4494
4495 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles) - 1, NULL, NULL);
4496 ok(!ret, "got %d\n", ret);
4497 ok(GetLastError() == ERROR_BAD_LENGTH, "got %ld\n", GetLastError());
4498
4499 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles), NULL, NULL);
4500 ok(ret, "got %d\n", ret);
4501
4502 expect_list.mask |= 1 << ProcThreadAttributeHandleList;
4503 expect_list.attrs[1].attr = PROC_THREAD_ATTRIBUTE_HANDLE_LIST;
4504 expect_list.attrs[1].size = sizeof(handles);
4505 expect_list.attrs[1].value = handles;
4506 expect_list.count++;
4507
4508 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles), NULL, NULL);
4509 ok(!ret, "got %d\n", ret);
4511
4512 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR, handles, sizeof(PROCESSOR_NUMBER), NULL, NULL);
4513 ok(ret || GetLastError() == ERROR_NOT_SUPPORTED, "got %d gle %ld\n", ret, GetLastError());
4514
4515 if (ret)
4516 {
4517 expect_list.mask |= 1 << ProcThreadAttributeIdealProcessor;
4518 expect_list.attrs[2].attr = PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR;
4519 expect_list.attrs[2].size = sizeof(PROCESSOR_NUMBER);
4520 expect_list.attrs[2].value = handles;
4521 expect_list.count++;
4522 }
4523
4524 ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, handles, sizeof(handles[0]), NULL, NULL);
4525 ok(ret || broken(GetLastError() == ERROR_NOT_SUPPORTED), "got %d gle %ld\n", ret, GetLastError());
4526
4527 if (ret)
4528 {
4529 unsigned int i = expect_list.count++;
4530 expect_list.mask |= 1 << ProcThreadAttributePseudoConsole;
4531 expect_list.attrs[i].attr = PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE;
4532 expect_list.attrs[i].size = sizeof(HPCON);
4533 expect_list.attrs[i].value = handles;
4534 }
4535
4536 ok(!memcmp(&list, &expect_list, size), "mismatch\n");
4537
4538 pDeleteProcThreadAttributeList(&list);
4539}
4540
4541/* level 0: Main test process
4542 * level 1: Process created by level 0 process without handle inheritance
4543 * level 2: Process created by level 1 process with handle inheritance and level 0
4544 * process parent substitute.
4545 * level 255: Process created by level 1 process during invalid parent handles testing. */
4547{
4549 char buffer[MAX_PATH + 64];
4550 HANDLE write_pipe = NULL;
4556 ULONG pbi_size;
4557 HANDLE parent;
4558 DWORD size;
4559 BOOL ret;
4560
4561 struct
4562 {
4563 HANDLE parent;
4565 }
4566 parent_data;
4567
4568 if (level == 255)
4569 return;
4570
4571 if (!pInitializeProcThreadAttributeList)
4572 {
4573 win_skip("No support for ProcThreadAttributeList.\n");
4574 return;
4575 }
4576
4577 memset(&sa, 0, sizeof(sa));
4578 sa.nLength = sizeof(sa);
4579 sa.bInheritHandle = TRUE;
4580
4581 if (!level)
4582 {
4583 ret = CreatePipe(&read_pipe, &write_pipe, &sa, 0);
4584 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4585
4587 parent_data.parent_id = GetCurrentProcessId();
4588 }
4589 else
4590 {
4591 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &pbi_size);
4592 ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status);
4593 parent_id = pbi.InheritedFromUniqueProcessId;
4594
4595 memset(&parent_data, 0, sizeof(parent_data));
4596 ret = ReadFile(read_pipe, &parent_data, sizeof(parent_data), &size, NULL);
4597 ok((level == 2 && ret) || (level == 1 && !ret && GetLastError() == ERROR_INVALID_HANDLE),
4598 "Got unexpected ret %#x, level %u, GetLastError() %lu.\n",
4599 ret, level, GetLastError());
4600 }
4601
4602 if (level == 2)
4603 {
4604 ok(parent_id == parent_data.parent_id, "Got parent id %lu, parent_data.parent_id %lu.\n",
4605 parent_id, parent_data.parent_id);
4606 return;
4607 }
4608
4609 memset(&si, 0, sizeof(si));
4610 si.StartupInfo.cb = sizeof(si);
4611
4612 if (level)
4613 {
4614 HANDLE handle;
4615 SIZE_T size;
4616
4617 ret = pInitializeProcThreadAttributeList(NULL, 1, 0, &size);
4619 "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4620
4621 sprintf(buffer, "\"%s\" process parent %u %p", selfname, 255, read_pipe);
4622
4623#if 0
4624 /* Crashes on some Windows installations, otherwise successfully creates process. */
4626 NULL, NULL, (STARTUPINFOA *)&si, &info);
4627 ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
4629#endif
4630 si.lpAttributeList = heap_alloc(size);
4631 ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
4632 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4634 ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
4635 &handle, sizeof(handle), NULL, NULL);
4636 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4638 NULL, NULL, (STARTUPINFOA *)&si, &info);
4639 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4642 pDeleteProcThreadAttributeList(si.lpAttributeList);
4643 heap_free(si.lpAttributeList);
4644
4645 si.lpAttributeList = heap_alloc(size);
4646 ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
4647 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4648 handle = (HANDLE)0xdeadbeef;
4649 ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
4650 &handle, sizeof(handle), NULL, NULL);
4651 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4653 NULL, NULL, (STARTUPINFOA *)&si, &info);
4654 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected ret %#x, GetLastError() %lu.\n",
4655 ret, GetLastError());
4656 pDeleteProcThreadAttributeList(si.lpAttributeList);
4657 heap_free(si.lpAttributeList);
4658
4659 si.lpAttributeList = heap_alloc(size);
4660 ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
4661 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4662 handle = NULL;
4663 ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
4664 &handle, sizeof(handle), NULL, NULL);
4665 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4667 NULL, NULL, (STARTUPINFOA *)&si, &info);
4668 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected ret %#x, GetLastError() %lu.\n",
4669 ret, GetLastError());
4670 pDeleteProcThreadAttributeList(si.lpAttributeList);
4671 heap_free(si.lpAttributeList);
4672
4673 si.lpAttributeList = heap_alloc(size);
4674 ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
4675 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4677 ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
4678 &handle, sizeof(handle), NULL, NULL);
4679 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4681 NULL, NULL, (STARTUPINFOA *)&si, &info);
4682 /* Broken on Vista / w7 / w10. */
4684 "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4685 if (ret)
4687 pDeleteProcThreadAttributeList(si.lpAttributeList);
4688 heap_free(si.lpAttributeList);
4689
4690 si.lpAttributeList = heap_alloc(size);
4691 ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
4692 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4693
4695
4696 ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
4697 &parent, sizeof(parent), NULL, NULL);
4698 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4699 }
4700
4701 sprintf(buffer, "\"%s\" process parent %u %p", selfname, level + 1, read_pipe);
4703 NULL, NULL, (STARTUPINFOA *)&si, &info);
4704 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4705
4706 if (level)
4707 {
4708 pDeleteProcThreadAttributeList(si.lpAttributeList);
4709 heap_free(si.lpAttributeList);
4711 }
4712 else
4713 {
4714 ret = WriteFile(write_pipe, &parent_data, sizeof(parent_data), &size, NULL);
4715 }
4716
4718
4719 if (!level)
4720 {
4722 CloseHandle(write_pipe);
4723 CloseHandle(parent_data.parent);
4724 }
4725}
4726
4727static void test_handle_list_attribute(BOOL child, HANDLE handle1, HANDLE handle2)
4728{
4729 char buffer[MAX_PATH + 64];
4730 HANDLE pipe[2];
4733 SIZE_T size;
4734 BOOL ret;
4736
4737 if (child)
4738 {
4739 char name1[256], name2[256];
4740 DWORD flags;
4741
4742 flags = 0;
4743 ret = GetHandleInformation(handle1, &flags);
4744 ok(ret, "Failed to get handle info, error %ld.\n", GetLastError());
4745 ok(flags == HANDLE_FLAG_INHERIT, "Unexpected flags %#lx.\n", flags);
4746#if !defined(__REACTOS__) || DLL_EXPORT_VERSION >= 0x600
4748 ok(ret, "Failed to get pipe name, error %ld\n", GetLastError());
4749#endif
4750 CloseHandle(handle1);
4751 flags = 0;
4752 ret = GetHandleInformation(handle2, &flags);
4753 if (ret)
4754 {
4755 ok(!(flags & HANDLE_FLAG_INHERIT), "Parent's handle shouldn't have been inherited\n");
4756#if !defined(__REACTOS__) || DLL_EXPORT_VERSION >= 0x600
4758 ok(!ret || strcmp(name1, name2), "Parent's handle shouldn't have been inherited\n");
4759#endif
4760 }
4761 else
4762 ok(GetLastError() == ERROR_INVALID_HANDLE, "Unexpected return value, error %ld.\n", GetLastError());
4763
4764 return;
4765 }
4766
4767#ifdef __REACTOS__
4769 skip("test_handle_list_attribute() crashes on WS03.\n");
4770 return;
4771 }
4772#endif
4773 ret = pInitializeProcThreadAttributeList(NULL, 1, 0, &size);
4775 "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4776
4777 memset(&si, 0, sizeof(si));
4778 si.StartupInfo.cb = sizeof(si);
4779 si.lpAttributeList = heap_alloc(size);
4780 ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
4781 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4782
4783 memset(&sa, 0, sizeof(sa));
4784 sa.nLength = sizeof(sa);
4785 sa.bInheritHandle = TRUE;
4786
4787 ret = CreatePipe(&pipe[0], &pipe[1], &sa, 1024);
4788 ok(ret, "Failed to create a pipe.\n");
4789
4790 ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &pipe[0],
4791 sizeof(pipe[0]), NULL, NULL);
4792 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4793
4794 sprintf(buffer, "\"%s\" process handlelist %p %p", selfname, pipe[0], pipe[1]);
4796 (STARTUPINFOA *)&si, &info);
4797 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4798
4800
4801 CloseHandle(pipe[0]);
4802 CloseHandle(pipe[1]);
4803}
4804
4805static void test_dead_process(void)
4806{
4807 DWORD_PTR data[256];
4813 BYTE *buffer = NULL;
4814 BOOL found;
4815 ULONG size = 0;
4816 DWORD offset = 0;
4818
4819#ifdef __REACTOS__
4821 skip("test_dead_process() crashes on WS03.\n");
4822 return;
4823 }
4824#endif
4825 create_process("exit", &pi);
4827 Sleep(100);
4828
4829 memset( data, 0, sizeof(data) );
4831 ok( !status, "ProcessImageFileName failed %lx\n", status );
4832 ok( ((UNICODE_STRING *)data)->Length, "ProcessImageFileName not set\n" );
4833 ok( ((UNICODE_STRING *)data)->Buffer[0] == '\\', "ProcessImageFileName not set\n" );
4834
4835 memset( prio, 0xcc, sizeof(*prio) );
4837 ok( !status, "ProcessPriorityClass failed %lx\n", status );
4838 ok( prio->PriorityClass != 0xcc, "ProcessPriorityClass not set\n" );
4839
4840 memset( &basic, 0xcc, sizeof(basic) );
4842 ok( !status, "ProcessBasicInformation failed %lx\n", status );
4843 ok( basic.ExitStatus == 0, "ProcessBasicInformation info modified\n" );
4844
4845 memset( &image, 0xcc, sizeof(image) );
4847 ok( status == STATUS_PROCESS_IS_TERMINATING, "ProcessImageInformation wrong error %lx\n", status );
4848 ok( image.Machine == 0xcccc, "ProcessImageInformation info modified\n" );
4849
4851 {
4852 free(buffer);
4853 buffer = malloc(size);
4854 }
4855 ok(status == STATUS_SUCCESS, "got %#lx\n", status);
4856 found = FALSE;
4857 do
4858 {
4861 {
4862 found = TRUE;
4863 break;
4864 }
4865 offset += spi->NextEntryOffset;
4866 } while (spi->NextEntryOffset);
4867 ok( !found, "process still enumerated\n" );
4870}
4871
4872static void test_nested_jobs_child(unsigned int index)
4873{
4875 HANDLE job, job_parent, job_other, port;
4878 char job_name[32];
4880 DWORD dead_pid;
4881 BOOL ret, out;
4882 DWORD key;
4883
4884 sprintf(job_name, "test_nested_jobs_%u", index);
4886 | JOB_OBJECT_TERMINATE, FALSE, job_name);
4887 ok(!!job, "OpenJobObjectA error %lu\n", GetLastError());
4888
4889 sprintf(job_name, "test_nested_jobs_%u", !index);
4891 | JOB_OBJECT_TERMINATE, FALSE, job_name);
4892 ok(!!job_other, "OpenJobObjectA error %lu\n", GetLastError());
4893
4894 job_parent = pCreateJobObjectW(NULL, NULL);
4895 ok(!!job_parent, "CreateJobObjectA error %lu\n", GetLastError());
4896
4897 ret = pAssignProcessToJobObject(job_parent, GetCurrentProcess());
4898 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
4899
4900 create_process("wait", &pi);
4901
4902 ret = pAssignProcessToJobObject(job_parent, pi.hProcess);
4903 ok(ret || broken(!ret && GetLastError() == ERROR_ACCESS_DENIED) /* Supported since Windows 8. */,
4904 "AssignProcessToJobObject error %lu\n", GetLastError());
4905 if (!ret)
4906 {
4907 win_skip("Nested jobs are not supported.\n");
4908 goto done;
4909 }
4910 ret = pAssignProcessToJobObject(job, pi.hProcess);
4911 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
4912
4913 out = FALSE;
4914 ret = pIsProcessInJob(pi.hProcess, NULL, &out);
4915 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
4916 ok(out, "IsProcessInJob returned out=%u\n", out);
4917
4918 out = FALSE;
4919 ret = pIsProcessInJob(pi.hProcess, job, &out);
4920 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
4921 ok(out, "IsProcessInJob returned out=%u\n", out);
4922
4923 out = TRUE;
4924 ret = pIsProcessInJob(GetCurrentProcess(), job, &out);
4925 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
4926 ok(!out, "IsProcessInJob returned out=%u\n", out);
4927
4928 out = FALSE;
4929 ret = pIsProcessInJob(pi.hProcess, job, &out);
4930 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
4931 ok(out, "IsProcessInJob returned out=%u\n", out);
4932
4933 ret = pAssignProcessToJobObject(job, GetCurrentProcess());
4934 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
4935
4940
4941 dead_pid = pi.dwProcessId;
4942
4943 port = pCreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
4944 ok(!!port, "CreateIoCompletionPort error %lu\n", GetLastError());
4945
4946 port_info.CompletionPort = port;
4947 port_info.CompletionKey = job;
4948 ret = pSetInformationJobObject(job, JobObjectAssociateCompletionPortInformation, &port_info, sizeof(port_info));
4949 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
4950 port_info.CompletionKey = job_parent;
4951 ret = pSetInformationJobObject(job_parent, JobObjectAssociateCompletionPortInformation,
4952 &port_info, sizeof(port_info));
4953 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
4954
4955 create_process("wait", &pi);
4956 out = FALSE;
4957 ret = pIsProcessInJob(pi.hProcess, job, &out);
4958 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
4959 ok(out, "IsProcessInJob returned out=%u\n", out);
4960
4961 out = FALSE;
4962 ret = pIsProcessInJob(pi.hProcess, job_parent, &out);
4963 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
4964 ok(out, "IsProcessInJob returned out=%u\n", out);
4965
4966 /* The first already dead child process still shows up randomly. */
4967 do
4968 {
4970 } while (ret && (ULONG_PTR)overlapped == dead_pid);
4971
4972 ok(ret, "GetQueuedCompletionStatus: %lx\n", GetLastError());
4973 ok(key == JOB_OBJECT_MSG_NEW_PROCESS, "unexpected key %lx\n", key);
4974 ok((HANDLE)value == job, "unexpected value %p\n", (void *)value);
4975 ok((ULONG_PTR)overlapped == GetCurrentProcessId(), "unexpected pid %#lx\n", (DWORD)(DWORD_PTR)overlapped);
4976
4977 do
4978 {
4980 } while (ret && (ULONG_PTR)overlapped == dead_pid);
4981
4982 ok(ret, "GetQueuedCompletionStatus: %lx\n", GetLastError());
4983 ok(key == JOB_OBJECT_MSG_NEW_PROCESS, "unexpected key %lx\n", key);
4984 ok((HANDLE)value == job_parent, "unexpected value %p\n", (void *)value);
4985 ok((ULONG_PTR)overlapped == GetCurrentProcessId(), "unexpected pid %#lx\n", (DWORD)(DWORD_PTR)overlapped);
4986
4989
4991 ok(!ret, "GetQueuedCompletionStatus succeeded.\n");
4992
4993 if (index)
4994 {
4995 ret = pAssignProcessToJobObject(job_other, GetCurrentProcess());
4996 ok(!ret, "AssignProcessToJobObject succeeded\n");
4997 ok(GetLastError() == ERROR_ACCESS_DENIED, "Got unexpected error %lu.\n", GetLastError());
4998 }
4999
5001
5002done:
5005
5008 CloseHandle(job_parent);
5010 CloseHandle(job_other);
5011}
5012
5013static void test_nested_jobs(void)
5014{
5015 BOOL ret, already_in_job = TRUE, create_succeeded = FALSE;
5017 char buffer[MAX_PATH + 26];
5018 STARTUPINFOA si = {0};
5019 HANDLE job1, job2;
5020 unsigned int i;
5021
5022 if (!pIsProcessInJob)
5023 {
5024 win_skip("IsProcessInJob not available.\n");
5025 return;
5026 }
5027
5028 job1 = pCreateJobObjectW(NULL, NULL);
5029 ok(!!job1, "CreateJobObjectW failed, error %lu.\n", GetLastError());
5030 job2 = pCreateJobObjectW(NULL, NULL);
5031 ok(!!job2, "CreateJobObjectW failed, error %lu.\n", GetLastError());
5032
5033 create_succeeded = TRUE;
5034 sprintf(buffer, "\"%s\" process wait", selfname);
5035 for (i = 0; i < 2; ++i)
5036 {
5039 {
5040 create_succeeded = FALSE;
5041 break;
5042 }
5043 ok(ret, "CreateProcessA error %lu\n", GetLastError());
5044 }
5045
5046 if (create_succeeded)
5047 {
5048 ret = pIsProcessInJob(info[0].hProcess, NULL, &already_in_job);
5049 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5050
5051 if (!already_in_job)
5052 {
5053 ret = pAssignProcessToJobObject(job2, info[1].hProcess);
5054 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
5055
5056 ret = pAssignProcessToJobObject(job1, info[0].hProcess);
5057 ok(ret, "AssignProcessToJobObject error %lu\n", GetLastError());
5058
5059 ret = pAssignProcessToJobObject(job2, info[0].hProcess);
5060 ok(!ret, "AssignProcessToJobObject succeeded\n");
5061 ok(GetLastError() == ERROR_ACCESS_DENIED, "Got unexpected error %lu.\n", GetLastError());
5062
5067
5068 ret = pAssignProcessToJobObject(job2, info[0].hProcess);
5069 ok(!ret, "AssignProcessToJobObject succeeded\n");
5070 ok(GetLastError() == ERROR_ACCESS_DENIED, "Got unexpected error %lu.\n", GetLastError());
5071 }
5072
5077 }
5078
5079 if (already_in_job)
5080 {
5081 win_skip("Test process is already in job, can't test parenting non-empty job.\n");
5082 }
5083
5084 CloseHandle(job1);
5085 CloseHandle(job2);
5086
5087 job1 = pCreateJobObjectW(NULL, L"test_nested_jobs_0");
5088 ok(!!job1, "CreateJobObjectW failed, error %lu.\n", GetLastError());
5089 job2 = pCreateJobObjectW(NULL, L"test_nested_jobs_1");
5090 ok(!!job2, "CreateJobObjectW failed, error %lu.\n", GetLastError());
5091
5092 sprintf(buffer, "\"%s\" process nested_jobs 0", selfname);
5094 "CreateProcess failed\n");
5096 sprintf(buffer, "\"%s\" process nested_jobs 1", selfname);
5098 "CreateProcess failed\n");
5100 for (i = 0; i < 2; ++i)
5101 {
5104 }
5105
5106 CloseHandle(job1);
5107 CloseHandle(job2);
5108}
5109
5110static void test_job_list_attribute(HANDLE parent_job)
5111{
5116 char buffer[MAX_PATH + 19];
5119 HANDLE jobs[2], port;
5122 BOOL ret, out;
5123 HANDLE tmp;
5124 SIZE_T size;
5125 DWORD key;
5126
5127 if (!pInitializeProcThreadAttributeList)
5128 {
5129 win_skip("No support for ProcThreadAttributeList\n");
5130 return;
5131 }
5132
5133 ret = pInitializeProcThreadAttributeList(NULL, 1, 0, &size);
5135 "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5137
5138
5139 jobs[0] = (HANDLE)0xdeadbeef;
5140 jobs[1] = NULL;
5141
5142 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5143 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5144 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs,
5145 sizeof(*jobs), NULL, NULL);
5147 {
5148 /* Supported since Win10. */
5149 win_skip("PROC_THREAD_ATTRIBUTE_JOB_LIST is not supported.\n");
5150 pDeleteProcThreadAttributeList(attrs);
5152 return;
5153 }
5154 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5155
5156 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5157 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5158 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs,
5159 3, NULL, NULL);
5160 ok(!ret && GetLastError() == ERROR_BAD_LENGTH, "Got unexpected ret %#x, GetLastError() %lu.\n",
5161 ret, GetLastError());
5162
5163 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5164 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5165 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs,
5166 sizeof(*jobs) * 2, NULL, NULL);
5167 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5168
5169 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5170 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5171 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs,
5172 sizeof(*jobs), NULL, NULL);
5173
5174 memset(&si, 0, sizeof(si));
5175 si.StartupInfo.cb = sizeof(si);
5176 si.lpAttributeList = attrs;
5177 sprintf(buffer, "\"%s\" process wait", selfname);
5178
5180 (STARTUPINFOA *)&si, &pi);
5181 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected ret %#x, GetLastError() %lu.\n",
5182 ret, GetLastError());
5183
5184 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5185 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5186 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs + 1,
5187 sizeof(*jobs), NULL, NULL);
5189 (STARTUPINFOA *)&si, &pi);
5190 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected ret %#x, GetLastError() %lu.\n",
5191 ret, GetLastError());
5192
5193 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5194 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5195 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, &parent_job,
5196 sizeof(parent_job), NULL, NULL);
5198 (STARTUPINFOA *)&si, &pi);
5199 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5200
5201 ret = pIsProcessInJob(pi.hProcess, parent_job, &out);
5202 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5203 ok(out, "IsProcessInJob returned out=%u\n", out);
5204
5207
5208 jobs[0] = pCreateJobObjectW(NULL, NULL);
5209 ok(!!jobs[0], "CreateJobObjectA error %lu\n", GetLastError());
5210 jobs[1] = pCreateJobObjectW(NULL, NULL);
5211 ok(!!jobs[1], "CreateJobObjectA error %lu\n", GetLastError());
5212
5213 /* Breakaway works for the inherited job only. */
5215 ret = pSetInformationJobObject(parent_job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
5216 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
5219 ret = pSetInformationJobObject(jobs[1], JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
5220 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
5221
5222 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5223 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5224 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs + 1,
5225 sizeof(*jobs), NULL, NULL);
5228 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5229
5230 ret = pIsProcessInJob(pi.hProcess, parent_job, &out);
5231 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5232 ok(!out, "IsProcessInJob returned out=%u\n", out);
5233
5234 ret = pIsProcessInJob(pi.hProcess, jobs[1], &out);
5235 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5236 ok(out, "IsProcessInJob returned out=%u\n", out);
5237
5238 ret = pIsProcessInJob(pi.hProcess, jobs[0], &out);
5239 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5240 ok(!out, "IsProcessInJob returned out=%u\n", out);
5241
5244
5245 CloseHandle(jobs[1]);
5246 jobs[1] = pCreateJobObjectW(NULL, NULL);
5247 ok(!!jobs[1], "CreateJobObjectA error %lu\n", GetLastError());
5248
5249 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5250 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5251 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs + 1,
5252 sizeof(*jobs), NULL, NULL);
5254 NULL, NULL, (STARTUPINFOA *)&si, &pi);
5255 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5256
5257 ret = pIsProcessInJob(pi.hProcess, parent_job, &out);
5258 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5259 ok(out, "IsProcessInJob returned out=%u\n", out);
5260
5261 ret = pIsProcessInJob(pi.hProcess, jobs[1], &out);
5262 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5263 ok(out, "IsProcessInJob returned out=%u\n", out);
5264
5265 ret = pIsProcessInJob(pi.hProcess, jobs[0], &out);
5266 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5267 ok(!out, "IsProcessInJob returned out=%u\n", out);
5268
5271
5272 ret = pQueryInformationJobObject(jobs[0], JobObjectBasicAccountingInformation, &job_info,
5273 sizeof(job_info), NULL);
5274 ok(ret, "QueryInformationJobObject error %lu\n", GetLastError());
5275 ok(!job_info.TotalProcesses, "Got unexpected TotalProcesses %lu.\n", job_info.TotalProcesses);
5276 ok(!job_info.ActiveProcesses, "Got unexpected ActiveProcesses %lu.\n", job_info.ActiveProcesses);
5277
5278 ret = pQueryInformationJobObject(jobs[1], JobObjectBasicAccountingInformation, &job_info,
5279 sizeof(job_info), NULL);
5280 ok(ret, "QueryInformationJobObject error %lu\n", GetLastError());
5281 ok(job_info.TotalProcesses == 1, "Got unexpected TotalProcesses %lu.\n", job_info.TotalProcesses);
5282 ok(!job_info.ActiveProcesses || job_info.ActiveProcesses == 1, "Got unexpected ActiveProcesses %lu.\n",
5283 job_info.ActiveProcesses);
5284
5285 /* Fails due to the second job already has the parent other than the first job in the list. */
5286 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5287 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5288 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs,
5289 2 * sizeof(*jobs), NULL, NULL);
5290
5291 port = pCreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
5292 ok(!!port, "CreateIoCompletionPort error %lu\n", GetLastError());
5293
5294 port_info.CompletionPort = port;
5295 port_info.CompletionKey = jobs[0];
5296 ret = pSetInformationJobObject(jobs[0], JobObjectAssociateCompletionPortInformation, &port_info, sizeof(port_info));
5297 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
5298
5300 ok(!ret, "GetQueuedCompletionStatus succeeded.\n");
5301
5303 (STARTUPINFOA *)&si, &pi);
5304 ok(!ret && GetLastError() == ERROR_ACCESS_DENIED, "Got unexpected ret %#x, GetLastError() %lu.\n",
5305 ret, GetLastError());
5306
5308 ok(ret, "GetQueuedCompletionStatus: %lx\n", GetLastError());
5309 ok(key == JOB_OBJECT_MSG_NEW_PROCESS, "unexpected key %lx\n", key);
5310 ok((HANDLE)value == jobs[0], "unexpected value %p\n", (void *)value);
5311 ok(!!overlapped, "Got zero pid.\n");
5312
5314 ok(ret, "GetQueuedCompletionStatus: %lx\n", GetLastError());
5315 ok(key == JOB_OBJECT_MSG_EXIT_PROCESS, "unexpected key %lx\n", key);
5316 ok((HANDLE)value == jobs[0], "unexpected value %p\n", (void *)value);
5317 ok(!!overlapped, "Got zero pid.\n");
5318
5320 ok(ret, "GetQueuedCompletionStatus: %lx\n", GetLastError());
5321 ok(key == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO, "unexpected key %lx\n", key);
5322 ok((HANDLE)value == jobs[0], "unexpected value %p\n", (void *)value);
5323 ok(!overlapped, "Got unexpected overlapped %p.\n", overlapped);
5324
5326 ok(!ret, "GetQueuedCompletionStatus succeeded.\n");
5327
5329
5330 /* The first job got updated even though the process creation failed. */
5331 ret = pQueryInformationJobObject(jobs[0], JobObjectBasicAccountingInformation, &job_info,
5332 sizeof(job_info), NULL);
5333 ok(ret, "QueryInformationJobObject error %lu\n", GetLastError());
5334 ok(job_info.TotalProcesses == 1, "Got unexpected TotalProcesses %lu.\n", job_info.TotalProcesses);
5335 ok(!job_info.ActiveProcesses, "Got unexpected ActiveProcesses %lu.\n", job_info.ActiveProcesses);
5336
5337 ret = pQueryInformationJobObject(jobs[1], JobObjectBasicAccountingInformation, &job_info,
5338 sizeof(job_info), NULL);
5339 ok(ret, "QueryInformationJobObject error %lu\n", GetLastError());
5340 ok(job_info.TotalProcesses == 1, "Got unexpected TotalProcesses %lu.\n", job_info.TotalProcesses);
5341 ok(!job_info.ActiveProcesses, "Got unexpected ActiveProcesses %lu.\n", job_info.ActiveProcesses);
5342
5343 /* Check that the first job actually got the job_parent as parent. */
5344 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5345 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5346 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs,
5347 sizeof(*jobs), NULL, NULL);
5350 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5351
5352 ret = pIsProcessInJob(pi.hProcess, parent_job, &out);
5353 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5354 ok(out, "IsProcessInJob returned out=%u\n", out);
5355
5356 ret = pIsProcessInJob(pi.hProcess, jobs[0], &out);
5357 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5358 ok(out, "IsProcessInJob returned out=%u\n", out);
5359
5362
5363 tmp = jobs[0];
5364 jobs[0] = jobs[1];
5365 jobs[1] = tmp;
5366
5367 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5368 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5369 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs,
5370 2 * sizeof(*jobs), NULL, NULL);
5372 (STARTUPINFOA *)&si, &pi);
5373 ok(!ret && GetLastError() == ERROR_ACCESS_DENIED, "Got unexpected ret %#x, GetLastError() %lu.\n",
5374 ret, GetLastError());
5375
5376 CloseHandle(jobs[0]);
5377 CloseHandle(jobs[1]);
5378
5379 jobs[0] = pCreateJobObjectW(NULL, NULL);
5380 ok(!!jobs[0], "CreateJobObjectA error %lu\n", GetLastError());
5381 jobs[1] = pCreateJobObjectW(NULL, NULL);
5382 ok(!!jobs[1], "CreateJobObjectA error %lu\n", GetLastError());
5383
5384 /* Create the job chain successfully and check the job chain. */
5385 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5386 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5387 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs,
5388 2 * sizeof(*jobs), NULL, NULL);
5390 NULL, NULL, (STARTUPINFOA *)&si, &pi);
5391 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5392
5393 ret = pIsProcessInJob(pi.hProcess, parent_job, &out);
5394 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5395 ok(out, "IsProcessInJob returned out=%u\n", out);
5396
5397 ret = pIsProcessInJob(pi.hProcess, jobs[0], &out);
5398 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5399 ok(out, "IsProcessInJob returned out=%u\n", out);
5400
5401 ret = pIsProcessInJob(pi.hProcess, jobs[1], &out);
5402 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5403 ok(out, "IsProcessInJob returned out=%u\n", out);
5404
5407
5408 ret = pInitializeProcThreadAttributeList(attrs, 1, 0, &size);
5409 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5410 ret = pUpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, jobs + 1,
5411 sizeof(*jobs), NULL, NULL);
5414 ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
5415
5416 ret = pIsProcessInJob(pi.hProcess, parent_job, &out);
5417 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5418 ok(out, "IsProcessInJob returned out=%u\n", out);
5419
5420 ret = pIsProcessInJob(pi.hProcess, jobs[0], &out);
5421 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5422 ok(out, "IsProcessInJob returned out=%u\n", out);
5423
5424 ret = pIsProcessInJob(pi.hProcess, jobs[1], &out);
5425 ok(ret, "IsProcessInJob error %lu\n", GetLastError());
5426 ok(out, "IsProcessInJob returned out=%u\n", out);
5427
5430
5431 CloseHandle(jobs[0]);
5432 CloseHandle(jobs[1]);
5433
5434 pDeleteProcThreadAttributeList(attrs);
5436
5437 limit_info.BasicLimitInformation.LimitFlags = 0;
5438 ret = pSetInformationJobObject(parent_job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
5439 ok(ret, "SetInformationJobObject error %lu\n", GetLastError());
5440}
5441
5442static void test_services_exe(void)
5443{
5445 ULONG size, offset, try;
5446 char *buf;
5448 ULONG services_pid = 0, services_session_id = ~0;
5449
5450 /* Check that passing a zero size returns a size suitable for the next call,
5451 * taking into account that in rare cases processes may start between the
5452 * two NtQuerySystemInformation() calls. So this may require a few tries.
5453 */
5454 for (try = 0; try < 3; try++)
5455 {
5457 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", status);
5458
5459 buf = malloc(size);
5461 if (status != STATUS_INFO_LENGTH_MISMATCH) break;
5462 free(buf);
5463 }
5464 ok(status == STATUS_SUCCESS, "got %#lx\n", status);
5465
5467 offset = 0;
5468
5469 do
5470 {
5472 if (!wcsnicmp(spi->ProcessName.Buffer, L"services.exe", spi->ProcessName.Length/sizeof(WCHAR)))
5473 {
5474 services_pid = HandleToUlong(spi->UniqueProcessId);
5475 services_session_id = spi->SessionId;
5476 }
5477 offset += spi->NextEntryOffset;
5478 } while (spi->NextEntryOffset != 0);
5479
5480 ok(services_pid != 0, "services.exe not found\n");
5481 todo_wine
5482 ok(services_session_id == 0, "got services.exe SessionId %lu\n", services_session_id);
5483}
5484
5485static void test_startupinfo( void )
5486{
5487 STARTUPINFOA startup_beforeA, startup_afterA;
5488 STARTUPINFOW startup_beforeW, startup_afterW;
5490
5492
5493 startup_beforeA.hStdInput = (HANDLE)0x56780000;
5494 GetStartupInfoA(&startup_beforeA);
5495
5496 startup_beforeW.hStdInput = (HANDLE)0x12340000;
5497 GetStartupInfoW(&startup_beforeW);
5498
5499 /* change a couple of fields in PEB */
5500 params->dwX = ~params->dwX;
5501 params->hStdInput = (HANDLE)~(DWORD_PTR)params->hStdInput;
5502
5503 startup_afterA.hStdInput = (HANDLE)0x87650000;
5504 GetStartupInfoA(&startup_afterA);
5505
5506 /* wharf... ansi version is cached... */
5507 ok(startup_beforeA.dwX == startup_afterA.dwX, "Unexpected field value\n");
5508 ok(startup_beforeA.dwFlags == startup_afterA.dwFlags, "Unexpected field value\n");
5509 ok(startup_beforeA.hStdInput == startup_afterA.hStdInput, "Unexpected field value\n");
5510
5511 if (startup_beforeW.dwFlags & STARTF_USESTDHANDLES)
5512 {
5513 ok(startup_beforeA.hStdInput != NULL && startup_beforeA.hStdInput != INVALID_HANDLE_VALUE,
5514 "Unexpected field value\n");
5515 ok(startup_afterA.hStdInput != NULL && startup_afterA.hStdInput != INVALID_HANDLE_VALUE,
5516 "Unexpected field value\n");
5517 }
5518 else
5519 {
5520 ok(startup_beforeA.hStdInput == INVALID_HANDLE_VALUE, "Unexpected field value %p\n", startup_beforeA.hStdInput);
5521 ok(startup_afterA.hStdInput == INVALID_HANDLE_VALUE, "Unexpected field value %p\n", startup_afterA.hStdInput);
5522 }
5523
5524 /* ... while unicode is not */
5525 startup_afterW.hStdInput = (HANDLE)0x43210000;
5526 GetStartupInfoW(&startup_afterW);
5527
5528 ok(~startup_beforeW.dwX == startup_afterW.dwX, "Unexpected field value\n");
5529 if (startup_beforeW.dwFlags & STARTF_USESTDHANDLES)
5530 {
5531 ok(params->hStdInput == startup_afterW.hStdInput, "Unexpected field value\n");
5532 ok((HANDLE)~(DWORD_PTR)startup_beforeW.hStdInput == startup_afterW.hStdInput, "Unexpected field value\n");
5533 }
5534 else
5535 {
5536 ok(startup_beforeW.hStdInput == (HANDLE)0x12340000, "Unexpected field value\n");
5537 ok(startup_afterW.hStdInput == (HANDLE)0x43210000, "Unexpected field value\n");
5538 }
5539
5540 /* check impact of STARTF_USESTDHANDLES bit */
5541 params->dwFlags ^= STARTF_USESTDHANDLES;
5542
5543 startup_afterW.hStdInput = (HANDLE)0x43210000;
5544 GetStartupInfoW(&startup_afterW);
5545
5546 ok((startup_beforeW.dwFlags ^ STARTF_USESTDHANDLES) == startup_afterW.dwFlags, "Unexpected field value\n");
5547 if (startup_afterW.dwFlags & STARTF_USESTDHANDLES)
5548 {
5549 ok(params->hStdInput == startup_afterW.hStdInput, "Unexpected field value\n");
5550 ok(startup_afterW.hStdInput != (HANDLE)0x43210000, "Unexpected field value\n");
5551 }
5552 else
5553 {
5554 ok(startup_afterW.hStdInput == (HANDLE)0x43210000, "Unexpected field value\n");
5555 }
5556
5557 /* FIXME add more tests to check whether the dwFlags controls the returned
5558 * values (as done for STARTF_USESTDHANDLES) in unicode case.
5559 */
5560
5561 /* reset the modified fields in PEB */
5562 params->dwX = ~params->dwX;
5563 params->hStdInput = (HANDLE)~(DWORD_PTR)params->hStdInput;
5564 params->dwFlags ^= STARTF_USESTDHANDLES;
5565}
5566
5568{
5573 unsigned int i;
5574 BOOL ret;
5575
5576 if (!pGetProcessInformation)
5577 {
5578 win_skip("GetProcessInformation() is not available.\n");
5579 return;
5580 }
5581
5582 SetLastError(0xdeadbeef);
5583 ret = pGetProcessInformation(GetCurrentProcess(), ProcessMachineTypeInfo, NULL, 0);
5585 {
5586 win_skip("GetProcessInformation(ProcessMachineTypeInfo) is not supported.\n"); /* < win11 */
5587 return;
5588 }
5589 ok(!ret, "Unexpected return value %d.\n", ret);
5590 ok(GetLastError() == ERROR_BAD_LENGTH, "Unexpected error %ld.\n", GetLastError());
5591 SetLastError(0xdeadbeef);
5592 ret = pGetProcessInformation(GetCurrentProcess(), ProcessMachineTypeInfo, &mi, 0);
5593 ok(!ret, "Unexpected return value %d.\n", ret);
5594 ok(GetLastError() == ERROR_BAD_LENGTH, "Unexpected error %ld.\n", GetLastError());
5595 SetLastError(0xdeadbeef);
5596 ret = pGetProcessInformation(GetCurrentProcess(), ProcessMachineTypeInfo, &mi, sizeof(mi) - 1);
5597 ok(!ret, "Unexpected return value %d.\n", ret);
5598 ok(GetLastError() == ERROR_BAD_LENGTH, "Unexpected error %ld.\n", GetLastError());
5599 SetLastError(0xdeadbeef);
5600 ret = pGetProcessInformation(GetCurrentProcess(), ProcessMachineTypeInfo, &mi, sizeof(mi) + 1);
5601 ok(!ret, "Unexpected return value %d.\n", ret);
5602 ok(GetLastError() == ERROR_BAD_LENGTH, "Unexpected error %ld.\n", GetLastError());
5603
5604 ret = pGetProcessInformation(GetCurrentProcess(), ProcessMachineTypeInfo, &mi, sizeof(mi));
5605 ok(ret, "Unexpected return value %d.\n", ret);
5606
5607#if !defined(__REACTOS__) || DLL_EXPORT_VERSION >= 0x601
5610 machines, sizeof(machines), NULL );
5611 ok(!status, "Failed to get architectures information.\n");
5612 for (i = 0; machines[i].Machine; i++)
5613 {
5614 if (machines[i].Process)
5615 {
5616 ok(mi.ProcessMachine == machines[i].Machine, "Unexpected process machine %#x.\n", mi.ProcessMachine);
5617 ok(!!(mi.MachineAttributes & UserEnabled) == machines[i].UserMode, "Unexpected attributes %#x.\n",
5618 mi.MachineAttributes);
5619 ok(!!(mi.MachineAttributes & KernelEnabled) == machines[i].KernelMode, "Unexpected attributes %#x.\n",
5620 mi.MachineAttributes);
5621 ok(!!(mi.MachineAttributes & Wow64Container) == machines[i].WoW64Container, "Unexpected attributes %#x.\n",
5622 mi.MachineAttributes);
5623 ok(!(mi.MachineAttributes & ~(UserEnabled | KernelEnabled | Wow64Container)), "Unexpected attributes %#x.\n",
5624 mi.MachineAttributes);
5625 break;
5626 }
5627 }
5628#endif
5629}
5630
5632{
5633 HANDLE job, hproc, h, h2;
5634 BOOL b = init();
5635 ok(b, "Basic init of CreateProcess test\n");
5636 if (!b) return;
5637
5638 if (myARGC >= 3)
5639 {
5640 if (!strcmp(myARGV[2], "dump") && myARGC >= 4)
5641 {
5642 doChild(myARGV[3], (myARGC >= 5) ? myARGV[4] : NULL);
5643 return;
5644 }
5645 else if (!strcmp(myARGV[2], "wait"))
5646 {
5647 Sleep(30000);
5648 ok(0, "Child process not killed\n");
5649 return;
5650 }
5651 else if (!strcmp(myARGV[2], "sync") && myARGC >= 4)
5652 {
5654 ok(sem != 0, "OpenSemaphoreA(%s) failed le=%lu\n", myARGV[3], GetLastError());
5655 if (sem)
5656 {
5657 DWORD ret = WaitForSingleObject(sem, 30000);
5658 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject(%s) returned %lu\n", myARGV[3], ret);
5660 }
5661 return;
5662 }
5663 else if (!strcmp(myARGV[2], "exit"))
5664 {
5665 return;
5666 }
5667 else if (!strcmp(myARGV[2], "nested") && myARGC >= 4)
5668 {
5669 char buffer[MAX_PATH + 26];
5672 HANDLE hFile;
5673
5674 memset(&startup, 0, sizeof(startup));
5675 startup.cb = sizeof(startup);
5676 startup.dwFlags = STARTF_USESHOWWINDOW;
5677 startup.wShowWindow = SW_SHOWNORMAL;
5678
5679 sprintf(buffer, "\"%s\" process dump \"%s\"", selfname, myARGV[3]);
5680 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startup, &info), "CreateProcess failed\n");
5681 CloseHandle(info.hProcess);
5682 CloseHandle(info.hThread);
5683
5684 /* The nested process is suspended so we can use the same resource
5685 * file and it's up to the parent to read it before resuming the
5686 * nested process.
5687 */
5689 childPrintf(hFile, "[Nested]\nPid=%08lu\n", info.dwProcessId);
5691 return;
5692 }
5693 else if (!strcmp(myARGV[2], "parent") && myARGC >= 5)
5694 {
5695 sscanf(myARGV[4], "%p", &h);
5697 return;
5698 }
5699 else if (!strcmp(myARGV[2], "handlelist") && myARGC >= 5)
5700 {
5701 sscanf(myARGV[3], "%p", &h);
5702 sscanf(myARGV[4], "%p", &h2);
5704 return;
5705 }
5706 else if (!strcmp(myARGV[2], "nested_jobs") && myARGC >= 4)
5707 {
5709 return;
5710 }
5711
5712 ok(0, "Unexpected command %s\n", myARGV[2]);
5713 return;
5714 }
5716 if (hproc)
5717 {
5718 test_process_info(hproc);
5719 CloseHandle(hproc);
5720 }
5721 else
5722 win_skip("PROCESS_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
5725 test_Startup();
5728 test_Toolhelp();
5732 test_Console();
5733 test_ExitCode();
5739 test_Handles();
5761
5762 /* things that can be tested:
5763 * lookup: check the way program to be executed is searched
5764 * handles: check the handle inheritance stuff (+sec options)
5765 * console: check if console creation parameters work
5766 */
5767
5768#ifdef __REACTOS__
5769 if (is_reactos()) {
5770 ok(FALSE, "FIXME: ReactOS's job support is too basic for these tests.\n");
5771 return;
5772 }
5773#endif
5774 if (!pCreateJobObjectW)
5775 {
5776 win_skip("No job object support\n");
5777 return;
5778 }
5779
5792}
BOOL WINAPI DECLSPEC_HOTPATCH GetFileInformationByHandleEx(HANDLE handle, FILE_INFO_BY_HANDLE_CLASS class, LPVOID info, DWORD size)
unsigned char BOOLEAN
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
static void startup(void)
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define GetNTVersion()
Definition: apitest.h:17
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define msg(x)
Definition: auth_time.c:54
LONG NTSTATUS
Definition: precomp.h:26
#define ARRAY_SIZE(A)
Definition: main.h:20
BOOL WINAPI SetConsoleOutputCP(IN UINT wCodepage)
Definition: console.c:695
BOOL WINAPI SetConsoleCursorPosition(IN HANDLE hConsoleOutput, IN COORD dwCursorPosition)
Definition: console.c:641
BOOL WINAPI GetConsoleScreenBufferInfo(IN HANDLE hConsoleOutput, OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
Definition: console.c:595
static HANDLE thread
Definition: service.c:33
#define HandleToUlong(h)
Definition: basetsd.h:73
#define ULongToHandle(h)
Definition: basetsd.h:75
@ ProcessDebugPort
Definition: cicbase.cpp:64
@ ProcessBreakOnTermination
Definition: cicbase.cpp:67
@ ProcessBasicInformation
Definition: cicbase.cpp:63
@ ProcessWow64Information
Definition: cicbase.cpp:65
@ ProcessImageFileName
Definition: cicbase.cpp:66
Definition: bufpool.h:45
Definition: list.h:37
size_type size() const
Definition: _list.h:379
SIZE_T LPPROCESS_INFORMATION
Definition: cordebug.idl:86
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
const char * env_var
Definition: db.cpp:881
static LPCWSTR LPCWSTR module_name
Definition: db.cpp:171
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:171
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
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:19
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 IMAGE_FILE_MACHINE_ARMNT
Definition: compat.h:127
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define wcsnicmp
Definition: compat.h:14
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define UnmapViewOfFile
Definition: compat.h:746
#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
@ ThreadBasicInformation
Definition: compat.h:935
#define CreateFileMappingW(a, b, c, d, e, f)
Definition: compat.h:744
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define GetCurrentProcess()
Definition: compat.h:759
#define GENERIC_READ
Definition: compat.h:135
#define stricmp(_String1, _String2)
Definition: compat.h:24
#define ERROR_NOT_SUPPORTED
Definition: compat.h:100
#define RtlImageNtHeader
Definition: compat.h:806
#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 IMAGE_FILE_MACHINE_ARM64
Definition: compat.h:129
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MapViewOfFile
Definition: compat.h:745
#define MultiByteToWideChar
Definition: compat.h:110
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1571
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCP(UINT wCodePageID)
Definition: console.c:2422
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1608
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
PPEB Peb
Definition: dllmain.c:27
DWORD WINAPI QueryDosDeviceW(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:542
BOOL WINAPI FreeEnvironmentStringsA(IN LPSTR EnvironmentStrings)
Definition: environ.c:380
BOOL WINAPI CopyFileA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:404
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
DWORD WINAPI GetFileType(HANDLE hFile)
Definition: fileinfo.c:269
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 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
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2206
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:2064
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1489
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1534
HANDLE WINAPI OpenProcess(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwProcessId)
Definition: proc.c:1227
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
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4246
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4265
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4227
BOOL WINAPI DECLSPEC_HOTPATCH FreeConsole(void)
Definition: console.c:663
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(void)
Definition: console.c:821
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(void)
Definition: console.c:957
BOOL WINAPI AllocConsole(void)
Definition: console.c:492
BOOL WINAPI DECLSPEC_HOTPATCH ProcessIdToSessionId(DWORD pid, DWORD *id)
Definition: process.c:1114
void WINAPI DECLSPEC_HOTPATCH GetStartupInfoW(STARTUPINFOW *info)
Definition: process.c:1347
BOOL WINAPI DECLSPEC_HOTPATCH GetHandleInformation(HANDLE handle, DWORD *flags)
Definition: process.c:802
DWORD WINAPI DECLSPEC_HOTPATCH GetProcessVersion(DWORD pid)
Definition: process.c:946
HANDLE WINAPI DECLSPEC_HOTPATCH GetStdHandle(DWORD std_handle)
Definition: process.c:1383
BOOL WINAPI DECLSPEC_HOTPATCH SetHandleInformation(HANDLE handle, DWORD mask, DWORD flags)
Definition: process.c:1171
BOOL WINAPI DECLSPEC_HOTPATCH FreeEnvironmentStringsW(LPWSTR ptr)
Definition: process.c:1685
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info)
Definition: process.c:686
LPWSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsW(void)
Definition: process.c:1538
BOOL WINAPI DECLSPEC_HOTPATCH DuplicateHandle(HANDLE source_process, HANDLE source, HANDLE dest_process, HANDLE *dest, DWORD access, BOOL inherit, DWORD options)
Definition: process.c:734
LPSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsA(void)
Definition: process.c:1518
BOOL WINAPI DECLSPEC_HOTPATCH GetExitCodeProcess(HANDLE process, LPDWORD exit_code)
Definition: process.c:788
LPWSTR WINAPI GetCommandLineW(void)
Definition: process.c:1338
LPSTR WINAPI GetCommandLineA(void)
Definition: process.c:1329
BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandle(DWORD std_handle, HANDLE handle)
Definition: process.c:1399
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
_ACRTIMP double __cdecl fmin(double, double)
#define va_end(v)
Definition: stdarg.h:28
#define va_arg(v, l)
Definition: stdarg.h:27
#define va_start(v, l)
Definition: stdarg.h:26
_ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl vsprintf(char *, const char *, va_list) __WINE_CRT_PRINTF_ATTR(2
_ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl sscanf(const char *, const char *,...) __WINE_CRT_SCANF_ATTR(2
_ACRTIMP int __cdecl atoi(const char *)
Definition: string.c:1715
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
_ACRTIMP int __cdecl strncmp(const char *, const char *, size_t)
Definition: string.c:3330
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
char * va_list
Definition: vadefs.h:50
USHORT port
Definition: uri.c:228
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
r parent
Definition: btrfs.c:3010
#define INFINITE
Definition: serial.h:102
#define ULONG_PTR
Definition: config.h:101
#define PtrToUlong(u)
Definition: config.h:107
#define strcasecmp
Definition: fake.h:9
UINT WINAPI GetTempFileNameA(IN LPCSTR lpPathName, IN LPCSTR lpPrefixString, IN UINT uUnique, OUT LPSTR lpTempFileName)
Definition: filename.c:26
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
@ SystemProcessInformation
Definition: ntddk_ex.h:16
enum _SYSTEM_INFORMATION_CLASS SYSTEM_INFORMATION_CLASS
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
size_t total
GLint level
Definition: gl.h:1546
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLeglImageOES image
Definition: gl.h:2204
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint res
Definition: glext.h:9613
GLuint address
Definition: glext.h:9393
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
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 in
Definition: glext.h:9616
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLuint64EXT * result
Definition: glext.h:11304
GLenum GLenum GLenum GLenum mapping
Definition: glext.h:9031
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
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
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 GLint GLint j
Definition: glfuncs.h:250
struct _PROCESS_PRIORITY_CLASS PROCESS_PRIORITY_CLASS
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:167
#define JOB_OBJECT_LIMIT_BREAKAWAY_OK
Definition: pstypes.h:224
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:226
#define PROCESS_VM_OPERATION
Definition: pstypes.h:161
#define JOB_OBJECT_TERMINATE
Definition: pstypes.h:204
@ JobObjectAssociateCompletionPortInformation
Definition: pstypes.h:473
@ JobObjectBasicLimitInformation
Definition: pstypes.h:468
@ JobObjectBasicAccountingInformation
Definition: pstypes.h:467
@ JobObjectExtendedLimitInformation
Definition: pstypes.h:475
@ JobObjectBasicProcessIdList
Definition: pstypes.h:469
#define JOB_OBJECT_ASSIGN_PROCESS
Definition: pstypes.h:201
#define PROCESS_CREATE_PROCESS
Definition: pstypes.h:164
#define JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK
Definition: pstypes.h:225
#define JOB_OBJECT_SET_ATTRIBUTES
Definition: pstypes.h:202
#define JOB_OBJECT_QUERY
Definition: pstypes.h:203
struct _PROCESS_BASIC_INFORMATION PROCESS_BASIC_INFORMATION
REFIID LPVOID DWORD_PTR dw
Definition: atlbase.h:40
NTSYSAPI NTSTATUS WINAPI NtQuerySystemInformationEx(SYSTEM_INFORMATION_CLASS, void *, ULONG, void *, ULONG, ULONG *)
struct _KERNEL_USER_TIMES KERNEL_USER_TIMES
struct _PROCESS_CYCLE_TIME_INFORMATION PROCESS_CYCLE_TIME_INFORMATION
@ ProcessPagePriority
Definition: winternl.h:1921
@ ProcessLUIDDeviceMapsEnabled
Definition: winternl.h:1910
@ ProcessDebugFlags
Definition: winternl.h:1913
@ ProcessAffinityMask
Definition: winternl.h:1903
@ ProcessVmCounters
Definition: winternl.h:1885
@ ProcessPriorityClass
Definition: winternl.h:1900
@ ProcessPriorityBoost
Definition: winternl.h:1904
@ ProcessDynamicFunctionTableInformation
Definition: winternl.h:1935
@ ProcessImageInformation
Definition: winternl.h:1919
@ ProcessExecuteFlags
Definition: winternl.h:1916
@ ProcessCookie
Definition: winternl.h:1918
@ ProcessIoCounters
Definition: winternl.h:1884
@ ProcessImageFileNameWin32
Definition: winternl.h:1925
@ ProcessDefaultHardErrorMode
Definition: winternl.h:1894
@ ProcessQuotaLimits
Definition: winternl.h:1883
@ ProcessCycleTime
Definition: winternl.h:1920
@ ProcessIoPriority
Definition: winternl.h:1915
@ ProcessTimes
Definition: winternl.h:1886
@ ProcessDebugObjectHandle
Definition: winternl.h:1912
@ ProcessHandleCount
Definition: winternl.h:1902
NTSYSAPI PEB *WINAPI RtlGetCurrentPeb(void)
Definition: libsupp.c:65
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 debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
BOOL is_wow64
Definition: main.c:38
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:71
struct S1 s1
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
#define win_skip
Definition: minitest.h:67
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
#define todo_wine
Definition: minitest.h:80
#define STILL_ACTIVE
Definition: minwinbase.h:43
#define CREATE_PROCESS_DEBUG_EVENT
Definition: minwinbase.h:35
#define LOAD_DLL_DEBUG_EVENT
Definition: minwinbase.h:38
#define EXIT_PROCESS_DEBUG_EVENT
Definition: minwinbase.h:37
PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE
Definition: minwinbase.h:124
@ FileNameInfo
Definition: minwinbase.h:306
#define EXCEPTION_DEBUG_EVENT
Definition: minwinbase.h:33
struct _OVERLAPPED * LPOVERLAPPED
BOOL * PBOOL
Definition: minwindef.h:137
#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
static struct test_info tests[]
#define sprintf
Definition: sprintf.c:45
#define PROCESS_QUERY_LIMITED_INFORMATION
Definition: security.c:45
static const BYTE us[]
Definition: encode.c:671
BOOL expected
Definition: store.c:2000
static WCHAR name1[]
Definition: record.c:34
static WCHAR name2[]
Definition: record.c:35
static BOOL run_tests(void)
Definition: run.c:2756
static PROCESS_INFORMATION pi
Definition: debugger.c:2303
static void test_nested_jobs(void)
Definition: process.c:5013
#define expect_eq_ws_i(expected, actual)
Definition: process.c:61
static void test_nested_jobs_child(unsigned int index)
Definition: process.c:4872
#define H_PIPE
Definition: process.c:3312
#define okChildHexInt(sect, key, expect, is_broken)
Definition: process.c:673
static void test_Toolhelp(void)
Definition: process.c:1195
static void _test_accounting(int line, HANDLE job, unsigned int total, unsigned int active, unsigned int terminated)
Definition: process.c:2680
static BOOL check_run_child(const char *exec, DWORD flags, BOOL cp_inherit, STARTUPINFOA *si)
Definition: process.c:3324
#define test_completion(a, b, c, d, e)
Definition: process.c:2618
#define HATTR_NULL
Definition: process.c:332
static void _test_assigned_proc(int line, HANDLE job, unsigned int count,...)
Definition: process.c:2651
static LPSTR
Definition: process.c:75
static SIZE_T *static DWORD_PTR
Definition: process.c:98
#define test_accounting(a, b, c, d)
Definition: process.c:2679
static void test_ExitCode(void)
Definition: process.c:1755
static HANDLE ULONG_PTR key
Definition: process.c:83
#define X(d, cg, s)
#define MAX_LISTED_ENV_VAR
Definition: process.c:118
static const char * encodeA(const char *str)
Definition: process.c:142
static void test_StdHandleInheritance(void)
Definition: process.c:3434
#define ARG_STD
Definition: process.c:3317
static HINSTANCE hkernel32
Definition: process.c:68
static PUCHAR
Definition: process.c:84
static char * memory_index
Definition: process.c:123
static void test_SuspendFlag(void)
Definition: process.c:1459
static HANDLE process
Definition: process.c:78
static void test_KillOnJobClose(void)
Definition: process.c:3009
static BOOL inherit
Definition: process.c:77
#define HATTR_DANGLING
Definition: process.c:339
static void ok_child_string(int line, const char *sect, const char *key, const char *expect, int sensitive)
Definition: process.c:623
static void _test_completion(int line, HANDLE port, DWORD ekey, ULONG_PTR evalue, ULONG_PTR eoverlapped, DWORD wait)
Definition: process.c:2619
#define HATTR_INVALID
Definition: process.c:334
#define ARG_CP_INHERIT
Definition: process.c:3319
static void test_CommandLine(void)
Definition: process.c:933
static void test_startupinfo(void)
Definition: process.c:5485
#define PROCESS_ALL_ACCESS_NT4
Definition: process.c:45
static void test_IsProcessInJob(void)
Definition: process.c:2698
static void test_SuspendProcessState(void)
Definition: process.c:4083
#define H_NULL
Definition: process.c:3313
static HANDLE test_AddSelfToJob(void)
Definition: process.c:3136
static unsigned encode_handle_attributes(HANDLE h)
Definition: process.c:343
static USHORT USHORT *static DWORD dwFlags
Definition: process.c:73
static int strCmp(const char *s1, const char *s2, BOOL sensitive)
Definition: process.c:615
#define ARG_HANDLE_PROTECT
Definition: process.c:3321
#define ARG_HANDLE_MASK
Definition: process.c:3322
static void doChild(const char *file, const char *option)
Definition: process.c:381
#define okChildString(sect, key, expect)
Definition: process.c:669
static void test_Directory(void)
Definition: process.c:1155
static UINT exit_code
Definition: process.c:80
static BOOL init(void)
Definition: process.c:238
#define okChildStringWA(sect, key, expect)
Definition: process.c:671
static void test_GetProcessVersion(void)
Definition: process.c:1891
#define test_assigned_proc(job,...)
Definition: process.c:2650
#define HATTR_TYPE
Definition: process.c:335
static JOBOBJECTINFOCLASS LPVOID DWORD LPDWORD ret_len
Definition: process.c:81
#define H_DISK
Definition: process.c:3310
#define H_CHAR
Definition: process.c:3311
static int myARGC
Definition: process.c:110
#define expect_eq_s(expected, actual)
Definition: process.c:55
static BOOL is_str_env_drive_dir(const char *str)
Definition: process.c:1311
#define HATTR_INHERIT
Definition: process.c:337
#define H_DEVIL
Definition: process.c:3315
#define expect_eq_d(expected, actual)
Definition: process.c:49
static unsigned decode_char(char c)
Definition: process.c:171
#define okChildIString(sect, key, expect)
Definition: process.c:670
static void test_job_list_attribute(HANDLE parent_job)
Definition: process.c:5110
static PROCESSINFOCLASS
Definition: process.c:85
static void test_services_exe(void)
Definition: process.c:5442
#define HANDLE_UNTOUCHEDW
Definition: process.c:341
static USHORT USHORT *static DWORD LPSTR PDWORD lpdwSize
Definition: process.c:73
static void test_SystemInfo(void)
Definition: process.c:2354
static HANDLE ULONG_PTR DWORD threads
Definition: process.c:83
static void test_DebuggingFlag(void)
Definition: process.c:1505
static char * decodeA(const char *str)
Definition: process.c:179
static void test_WaitForJobObject(void)
Definition: process.c:3049
static HANDLE existing_port
Definition: process.c:83
static void ok_child_int(int line, const char *sect, const char *key, UINT expect)
Definition: process.c:657
#define HATTR_PROTECT
Definition: process.c:338
#define THREAD_ALL_ACCESS_NT4
Definition: process.c:47
static HANDLE PBOOL result
Definition: process.c:79
static void test_CompletionPort(void)
Definition: process.c:2961
static void ok_child_stringWA(int line, const char *sect, const char *key, const char *expect, int sensitive)
Definition: process.c:631
static SIZE_T *static void SIZE_T
Definition: process.c:98
static void test_TerminateProcess(void)
Definition: process.c:2443
static ULONG
Definition: process.c:85
#define create_process(cmd, pi)
Definition: process.c:2637
static void test_jobInheritance(HANDLE job)
Definition: process.c:3152
#define H_CONSOLE
Definition: process.c:3309
static PBOOL
Definition: process.c:71
static void test_Handles(void)
Definition: process.c:2140
static void copy_change_subsystem(const char *in, const char *out, DWORD subsyst)
Definition: process.c:3283
static void test_DuplicateHandle(void)
Definition: process.c:2480
static USHORT USHORT *static DWORD LPSTR lpExeName
Definition: process.c:73
static BOOL build_startupinfo(STARTUPINFOA *startup, unsigned args, HANDLE hstd[2])
Definition: process.c:3350
static char ** myARGV
Definition: process.c:111
static PVOID
Definition: process.c:85
static void test_handle_list_attribute(BOOL child, HANDLE handle1, HANDLE handle2)
Definition: process.c:4727
#define HATTR_UNTOUCHED
Definition: process.c:336
static void test_QueryFullProcessImageNameW(void)
Definition: process.c:2022
static void ok_child_hexint(int line, const char *sect, const char *key, UINT expect, UINT is_broken)
Definition: process.c:663
#define ARG_STARTUPINFO
Definition: process.c:3318
static HINSTANCE hntdll
Definition: process.c:68
static WCHAR * decodeW(const char *str)
Definition: process.c:196
static void test_IsWow64Process(void)
Definition: process.c:2186
static void test_session_info(void)
Definition: process.c:4121
static void _create_process(int line, const char *command, LPPROCESS_INFORMATION pi)
Definition: process.c:2638
#define INIT_STR
static PROCESS_INFORMATION_CLASS
Definition: process.c:102
static void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
Definition: process.c:4546
static void test_Startup(void)
Definition: process.c:675
static void reload_child_info(const char *resfile)
Definition: process.c:221
static void test_dead_process(void)
Definition: process.c:4805
#define ARG_HANDLE_INHERIT
Definition: process.c:3320
static void test_OpenProcess(void)
Definition: process.c:1783
static void test_largepages(void)
Definition: process.c:4400
static void test_Console(void)
Definition: process.c:1565
static void release_memory(void)
Definition: process.c:135
static char memory[1024 *256]
Definition: process.c:122
static char * exename
Definition: process.c:107
static void test_process_info(HANDLE hproc)
Definition: process.c:4134
#define okChildInt(sect, key, expect)
Definition: process.c:672
static PDWORD
Definition: process.c:70
static char resfile[MAX_PATH]
Definition: process.c:108
static void test_QueryInformationJobObject(void)
Definition: process.c:2833
static WCHAR * getChildStringW(const char *sect, const char *key)
Definition: process.c:603
static DWORD
Definition: process.c:75
static void test_QueryFullProcessImageNameA(void)
Definition: process.c:1967
static void test_SuspendProcessNewThread(void)
Definition: process.c:4080
static char * grab_memory(size_t len)
Definition: process.c:125
static void test_GetProcessImageFileNameA(void)
Definition: process.c:1926
static void test_GetSystemCpuSetInformation(void)
Definition: process.c:4335
static void test_ProcThreadAttributeList(void)
Definition: process.c:4430
static void test_GetNumaProcessorNode(void)
Definition: process.c:4088
static void test_BreakawayOk(HANDLE parent_job)
Definition: process.c:3175
static void test_RegistryQuota(void)
Definition: process.c:2415
static JOBOBJECTINFOCLASS LPVOID info
Definition: process.c:81
static THREADINFOCLASS
Definition: process.c:86
static void cmpEnvironment(const char *gesA)
Definition: process.c:1320
static void test_GetLogicalProcessorInformationEx(void)
Definition: process.c:4303
static void test_TerminateJobObject(void)
Definition: process.c:2779
static void test_IsWow64Process2(void)
Definition: process.c:2242
static char selfname[MAX_PATH]
Definition: process.c:106
static void test_ProcessorCount(void)
Definition: process.c:2398
static void wait_and_close_child_process(PROCESS_INFORMATION *pi)
Definition: process.c:214
static void test_Environment(void)
Definition: process.c:1374
static char * getChildString(const char *sect, const char *key)
Definition: process.c:591
static PULONG
Definition: process.c:85
static HANDLE job
Definition: process.c:79
#define H_INVALID
Definition: process.c:3314
static void test_GetProcessInformation(void)
Definition: process.c:5567
static char std_handle_file[MAX_PATH]
Definition: process.c:3348
static const char * encodeW(const WCHAR *str)
Definition: process.c:156
static HANDLE sem
Definition: sync.c:799
static SYSTEM_INFO si
Definition: virtual.c:39
static DWORD CALLBACK read_pipe(void *arg)
Definition: virtual.c:1717
static const char machine[]
Definition: profile.c:104
#define __WINE_PRINTF_ATTR(fmt, args)
Definition: custom.c:42
static va_list valist
Definition: printf.c:46
static LPCWSTR file_name
Definition: protocol.c:147
static DWORD parent_id
Definition: cursoricon.c:2270
static HWND child
Definition: cursoricon.c:298
static MONITORINFO mi
Definition: win.c:7338
static SCRIPT_CACHE SCRIPT_ANALYSIS * psa
Definition: usp10.c:64
#define min(a, b)
Definition: monoChain.cc:55
HANDLE hStdOut
Definition: more.c:49
HANDLE hStdIn
Definition: more.c:49
#define argv
Definition: mplay32.c:18
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned int UINT
Definition: ndis.h:50
@ SystemSupportedProcessorArchitectures
Definition: extypes.h:414
@ SystemCpuSetInformation
Definition: extypes.h:408
#define PROCESSOR_ARCHITECTURE_AMD64
Definition: ketypes.h:114
#define PROCESSOR_ARCHITECTURE_INTEL
Definition: ketypes.h:105
#define SEC_IMAGE
Definition: mmtypes.h:97
#define DUPLICATE_SAME_ATTRIBUTES
Definition: obtypes.h:153
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 FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define PAGE_READWRITE
Definition: nt_native.h:1307
#define MEM_PRIVATE
Definition: nt_native.h:1321
#define BOOL
Definition: nt_native.h:43
#define MEM_RESERVE
Definition: nt_native.h:1317
#define MEM_RELEASE
Definition: nt_native.h:1319
#define GENERIC_WRITE
Definition: nt_native.h:90
#define MEM_COMMIT
Definition: nt_native.h:1316
#define PAGE_NOACCESS
Definition: nt_native.h:1305
PROCESSOR_NUMBER
Definition: ntbasedef.h:654
#define ALL_PROCESSOR_GROUPS
Definition: ntbasedef.h:656
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define IMAGE_SUBSYSTEM_WINDOWS_CUI
Definition: ntimage.h:438
#define IMAGE_SUBSYSTEM_WINDOWS_GUI
Definition: ntimage.h:437
#define IMAGE_FILE_MACHINE_AMD64
Definition: ntimage.h:17
NTSTATUS NTAPI NtQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_writes_bytes_to_opt_(ProcessInformationLength, *ReturnLength) PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: query.c:211
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:596
#define DBG_CONTINUE
Definition: ntstatus.h:98
#define STATUS_PORT_NOT_SET
Definition: ntstatus.h:1022
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:333
static BOOL read_bytes(parse_buffer *buf, LPVOID data, DWORD size)
Definition: parsing.c:168
#define IMAGE_DIRECTORY_ENTRY_IMPORT
Definition: pedump.c:260
#define IMAGE_FILE_MACHINE_I386
Definition: pedump.c:174
#define IMAGE_FILE_MACHINE_UNKNOWN
Definition: pedump.c:173
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
@ ProcessMachineTypeInfo
static char title[]
Definition: ps.c:92
_In_ DWORD dwProcessId
Definition: shlwapi.h:193
#define get_file_name
Definition: regproc.h:51
const WCHAR * str
#define WINAPIV
Definition: sdbpapi.h:64
#define offsetof(TYPE, MEMBER)
strcat
Definition: string.h:92
strcpy
Definition: string.h:131
#define is_reactos()
Definition: test.h:1041
int winetest_get_mainargs(char ***pargv)
#define wait_child_process
Definition: test.h:177
#define CONTEXT_ALL
const char * descr
Definition: boot.c:45
#define memset(x, y, z)
Definition: compat.h:39
#define _WIN32_WINNT_WIN8
Definition: sdkddkver.h:29
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25
PCWSTR s2
Definition: shell32_main.h:38
#define STATUS_SUCCESS
Definition: shellext.h:65
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED * overlapped
Definition: sock.c:81
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
TCHAR * cmdline
Definition: stretchblt.cpp:32
HANDLE UniqueThread
Definition: compat.h:826
HANDLE UniqueProcess
Definition: compat.h:825
union _DEBUG_EVENT::@3249 u
DWORD dwDebugEventCode
Definition: minwinbase.h:196
DWORD dwThreadId
Definition: minwinbase.h:198
DWORD dwProcessId
Definition: minwinbase.h:197
LOAD_DLL_DEBUG_INFO LoadDll
Definition: minwinbase.h:206
CREATE_PROCESS_DEBUG_INFO CreateProcessInfo
Definition: minwinbase.h:203
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:1691
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
UNICODE_STRING CSDVersion
Definition: winternl.h:545
ULONG HeapDeCommitTotalFreeThreshold
Definition: ntddk_ex.h:277
PPEB_LDR_DATA LdrData
Definition: winternl.h:481
ULONG HeapSegmentCommit
Definition: ntddk_ex.h:276
PVOID LoaderLock
Definition: ntddk_ex.h:295
PVOID ImageBaseAddress
Definition: ntddk_ex.h:245
PVOID ProcessHeap
Definition: ntddk_ex.h:249
ULONG SessionId
Definition: btrfs_drv.h:1919
PRTL_USER_PROCESS_PARAMETERS ProcessParameters
Definition: btrfs_drv.h:1913
LARGE_INTEGER CriticalSectionTimeout
Definition: ntddk_ex.h:274
ULONG HeapSegmentReserve
Definition: ntddk_ex.h:275
PVOID FastPebLock
Definition: ntddk_ex.h:250
PVOID TlsBitmap
Definition: ntddk_ex.h:259
ULONG OSMajorVersion
Definition: ntddk_ex.h:300
ULONG OSPlatformId
Definition: ntddk_ex.h:303
PRTL_BITMAP TlsExpansionBitmap
Definition: winternl.h:538
ULONG HeapDeCommitFreeBlockThreshold
Definition: ntddk_ex.h:278
struct proc_thread_attr attrs[1]
Definition: process.c:251
UNICODE_STRING CommandLine
Definition: btrfs_drv.h:1902
DWORD dwNumberOfProcessors
Definition: winbase.h:902
WORD wProcessorLevel
Definition: winbase.h:905
DWORD dwProcessorType
Definition: winbase.h:903
WORD wProcessorRevision
Definition: winbase.h:906
WORD wProcessorArchitecture
Definition: winbase.h:894
Definition: compat.h:836
WCHAR StaticUnicodeBuffer[261]
Definition: compat.h:877
ULONG CurrentLocale
Definition: compat.h:849
PVOID Peb
Definition: compat.h:842
PVOID * TlsExpansionSlots
Definition: compat.h:894
LIST_ENTRY TlsLinks
Definition: compat.h:880
UNICODE_STRING StaticUnicodeString
Definition: compat.h:876
CLIENT_ID ClientId
Definition: compat.h:839
CLIENT_ID RealClientId
Definition: compat.h:861
TEB_FLS_DATA * FlsSlots
Definition: winternl.h:690
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: match.c:390
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: name.c:39
Definition: getopt.h:109
DWORD_PTR attr
Definition: process.c:239
void * value
Definition: process.c:241
Definition: ps.c:97
DWORD is_broken
Definition: process.c:3431
unsigned args
Definition: process.c:3428
DWORD expected
Definition: process.c:3430
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:248
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
HANDLE WINAPI DECLSPEC_HOTPATCH CreateSemaphoreA(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, IN LONG lInitialCount, IN LONG lMaximumCount, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:430
BOOL WINAPI DECLSPEC_HOTPATCH ReleaseSemaphore(IN HANDLE hSemaphore, IN LONG lReleaseCount, IN LPLONG lpPreviousCount)
Definition: synch.c:542
HANDLE WINAPI DECLSPEC_HOTPATCH OpenSemaphoreA(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCSTR lpName)
Definition: synch.c:516
#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_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
static EFI_HANDLE * handles
Definition: uefidisk.c:117
LONGLONG QuadPart
Definition: typedefs.h:114
Definition: dlist.c:348
Definition: pdh_main.c:96
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
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
BOOL NTAPI VirtualFreeEx(IN HANDLE hProcess, IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD dwFreeType)
Definition: virtmem.c:83
#define PROCESS_NAME_NATIVE
Definition: winbase.h:34
#define STD_OUTPUT_HANDLE
Definition: winbase.h:292
#define STD_INPUT_HANDLE
Definition: winbase.h:291
#define PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
Definition: winbase.h:1187
#define CREATE_BREAKAWAY_FROM_JOB
Definition: winbase.h:213
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define PROC_THREAD_ATTRIBUTE_JOB_LIST
Definition: winbase.h:1173
#define STARTF_USESHOWWINDOW
Definition: winbase.h:468
@ ProcThreadAttributePseudoConsole
Definition: winbase.h:1144
@ ProcThreadAttributeIdealProcessor
Definition: winbase.h:1133
@ ProcThreadAttributeParentProcess
Definition: winbase.h:1129
@ ProcThreadAttributeHandleList
Definition: winbase.h:1130
#define PIPE_ACCESS_DUPLEX
Definition: winbase.h:166
#define HANDLE_FLAG_PROTECT_FROM_CLOSE
Definition: winbase.h:289
#define FILE_TYPE_UNKNOWN
Definition: winbase.h:282
#define FILE_MAP_ALL_ACCESS
Definition: winbase.h:158
#define HANDLE_FLAG_INHERIT
Definition: winbase.h:288
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158
#define STD_ERROR_HANDLE
Definition: winbase.h:293
struct _SYSTEM_INFO * LPSYSTEM_INFO
#define FILE_TYPE_CHAR
Definition: winbase.h:284
#define FILE_TYPE_PIPE
Definition: winbase.h:285
#define CREATE_SUSPENDED
Definition: winbase.h:182
#define PIPE_READMODE_MESSAGE
Definition: winbase.h:172
_In_ LPCSTR _In_opt_ LPCSTR _In_ DWORD _Out_opt_ LPSTR * lpFilePart
Definition: winbase.h:2828
#define PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
Definition: winbase.h:1156
#define EXTENDED_STARTUPINFO_PRESENT
Definition: winbase.h:204
#define PROC_THREAD_ATTRIBUTE_HANDLE_LIST
Definition: winbase.h:1155
#define WAIT_OBJECT_0
Definition: winbase.h:383
#define PIPE_TYPE_MESSAGE
Definition: winbase.h:170
#define STARTF_USESTDHANDLES
Definition: winbase.h:476
#define DETACHED_PROCESS
Definition: winbase.h:183
#define DEBUG_PROCESS
Definition: winbase.h:180
#define PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR
Definition: winbase.h:1154
#define FILE_TYPE_DISK
Definition: winbase.h:283
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING
Definition: wincon.h:128
_Inout_ PERBANDINFO * pbi
Definition: winddi.h:3917
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837
#define WINAPI
Definition: msvc.h:6
void * HPCON
Definition: winehacks.h:14
@ KernelEnabled
Definition: winehacks.h:19
@ Wow64Container
Definition: winehacks.h:20
@ UserEnabled
Definition: winehacks.h:18
#define ERROR_OBJECT_NAME_EXISTS
Definition: winerror.h:776
#define ERROR_BAD_LENGTH
Definition: winerror.h:249
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:228
#define ERROR_DIRECTORY
Definition: winerror.h:416
#define ERROR_BAD_PATHNAME
Definition: winerror.h:355
#define ERROR_NOACCESS
Definition: winerror.h:902
#define ERROR_PIPE_CONNECTED
Definition: winerror.h:624
#define JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO
Definition: winnt_old.h:3973
#define PROCESSOR_INTEL_PENTIUM
Definition: winnt_old.h:464
#define PROCESSOR_AMD_X8664
Definition: winnt_old.h:473
#define JOB_OBJECT_MSG_EXIT_PROCESS
Definition: winnt_old.h:3975
#define JOB_OBJECT_MSG_NEW_PROCESS
Definition: winnt_old.h:3974
#define SW_SHOWNORMAL
Definition: winuser.h:781
#define SW_HIDE
Definition: winuser.h:779
SYSTEM_CPU_SET_INFORMATION
Definition: ketypes.h:168
@ RelationProcessorCore
Definition: ketypes.h:82
@ RelationAll
Definition: ketypes.h:90
enum _LOGICAL_PROCESSOR_RELATIONSHIP LOGICAL_PROCESSOR_RELATIONSHIP
#define DUPLICATE_SAME_ACCESS
#define DUPLICATE_CLOSE_SOURCE
const char * LPCSTR
Definition: xmlstorage.h:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char * LPSTR
Definition: xmlstorage.h:182
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193
#define const
Definition: zconf.h:233