2 * Unit test suite for CreateProcess function.
4 * Copyright 2002 Eric Pouech
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "wine/test.h"
28 static char base[MAX_PATH];
29 static char selfname[MAX_PATH];
30 static char resfile[MAX_PATH];
35 /* ---------------- portable memory allocation thingie */
37 static char memory[16384];
38 static char* memory_index = memory;
40 static char* grab_memory(size_t len)
42 char* ret = memory_index;
46 assert(memory_index <= memory + sizeof(memory));
50 static void release_memory(void)
52 memory_index = memory;
55 /* ---------------- simplistic tool to encode/decode strings (to hide \ " ' and such) */
57 static char* encodeA(const char* str)
64 len = strlen(str) + 1;
65 ptr = grab_memory(len * 2 + 1);
66 for (i = 0; i < len; i++)
67 sprintf(&ptr[i * 2], "%02x", (unsigned char)str[i]);
72 static char* encodeW(const WCHAR* str)
79 len = lstrlenW(str) + 1;
80 ptr = grab_memory(len * 4 + 1);
82 for (i = 0; i < len; i++)
83 sprintf(&ptr[i * 4], "%04x", (unsigned int)(unsigned short)str[i]);
88 static unsigned decode_char(char c)
90 if (c >= '0' && c <= '9') return c - '0';
91 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
92 assert(c >= 'A' && c <= 'F');
96 static char* decodeA(const char* str)
102 len = strlen(str) / 2;
103 if (!len--) return NULL;
104 ptr = grab_memory(len + 1);
105 for (i = 0; i < len; i++)
106 ptr[i] = (decode_char(str[2 * i]) << 4) | decode_char(str[2 * i + 1]);
111 static WCHAR* decodeW(const char* str)
117 len = strlen(str) / 4;
118 if (!len--) return NULL;
119 ptr = (WCHAR*)grab_memory(len * 2 + 1);
120 for (i = 0; i < len; i++)
121 ptr[i] = (decode_char(str[4 * i]) << 12) |
122 (decode_char(str[4 * i + 1]) << 8) |
123 (decode_char(str[4 * i + 2]) << 4) |
124 (decode_char(str[4 * i + 3]) << 0);
129 /******************************************************************
132 * generates basic information like:
133 * base: absolute path to curr dir
134 * selfname: the way to reinvoke ourselves
136 static int init(void)
138 myARGC = winetest_get_mainargs( &myARGV );
139 if (!GetCurrentDirectoryA(sizeof(base), base)) return 0;
141 if (strcmp(winetest_platform, "windows"))
143 char* ptr = getenv("WINELOADER");
147 root = grab_memory(strlen(ptr) + 1);
149 ptr = strrchr(root, '/');
153 /* be sure to use absolute pathnames so we can change dirs whenever we want */
155 "%s/programs/winetest/runtest -q -P wine -M kernel32.dll -T %s -p %s/dlls/kernel/tests/kernel32_test",
160 strcpy(selfname, myARGV[0]);
166 /******************************************************************
169 * generates an absolute file_name for temporary file
172 static void get_file_name(char* buf)
177 GetTempPathA(sizeof(path), path);
178 GetTempFileNameA(path, "wt", 0, buf);
181 /******************************************************************
182 * static void childPrintf
185 static void childPrintf(HANDLE h, const char* fmt, ...)
191 va_start(valist, fmt);
192 vsprintf(buffer, fmt, valist);
194 WriteFile(h, buffer, strlen(buffer), &w, NULL);
198 /******************************************************************
201 * output most of the information in the child process
203 static void doChild(const char* file)
211 WCHAR bufW[MAX_PATH];
212 HANDLE hFile = CreateFileA(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
214 if (hFile == INVALID_HANDLE_VALUE) return;
216 /* output of startup info (Ansi) */
217 GetStartupInfoA(&siA);
219 "[StartupInfoA]\ncb=%08ld\nlpDesktop=%s\nlpTitle=%s\n"
220 "dwX=%lu\ndwY=%lu\ndwXSize=%lu\ndwYSize=%lu\n"
221 "dwXCountChars=%lu\ndwYCountChars=%lu\ndwFillAttribute=%lu\n"
222 "dwFlags=%lu\nwShowWindow=%u\n"
223 "hStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
224 siA.cb, encodeA(siA.lpDesktop), encodeA(siA.lpTitle),
225 siA.dwX, siA.dwY, siA.dwXSize, siA.dwYSize,
226 siA.dwXCountChars, siA.dwYCountChars, siA.dwFillAttribute,
227 siA.dwFlags, siA.wShowWindow,
228 (DWORD)siA.hStdInput, (DWORD)siA.hStdOutput, (DWORD)siA.hStdError);
230 /* since GetStartupInfoW is only implemented in win2k,
231 * zero out before calling so we can notice the difference
233 memset(&siW, 0, sizeof(siW));
234 GetStartupInfoW(&siW);
236 "[StartupInfoW]\ncb=%08ld\nlpDesktop=%s\nlpTitle=%s\n"
237 "dwX=%lu\ndwY=%lu\ndwXSize=%lu\ndwYSize=%lu\n"
238 "dwXCountChars=%lu\ndwYCountChars=%lu\ndwFillAttribute=%lu\n"
239 "dwFlags=%lu\nwShowWindow=%u\n"
240 "hStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
241 siW.cb, encodeW(siW.lpDesktop), encodeW(siW.lpTitle),
242 siW.dwX, siW.dwY, siW.dwXSize, siW.dwYSize,
243 siW.dwXCountChars, siW.dwYCountChars, siW.dwFillAttribute,
244 siW.dwFlags, siW.wShowWindow,
245 (DWORD)siW.hStdInput, (DWORD)siW.hStdOutput, (DWORD)siW.hStdError);
248 childPrintf(hFile, "[Arguments]\nargcA=%d\n", myARGC);
249 for (i = 0; i < myARGC; i++)
251 childPrintf(hFile, "argvA%d=%s\n", i, encodeA(myARGV[i]));
253 childPrintf(hFile, "CommandLineA=%s\n", encodeA(GetCommandLineA()));
259 /* this is part of shell32... and should be tested there */
260 argvW = CommandLineToArgvW(GetCommandLineW(), &argcW);
261 for (i = 0; i < argcW; i++)
263 childPrintf(hFile, "argvW%d=%s\n", i, encodeW(argvW[i]));
266 childPrintf(hFile, "CommandLineW=%s\n\n", encodeW(GetCommandLineW()));
268 /* output of environment (Ansi) */
269 ptrA = GetEnvironmentStringsA();
272 childPrintf(hFile, "[EnvironmentA]\n");
276 if (strlen(ptrA) < 128)
278 childPrintf(hFile, "env%d=%s\n", i, encodeA(ptrA));
281 ptrA += strlen(ptrA) + 1;
283 childPrintf(hFile, "\n");
286 /* output of environment (Unicode) */
287 ptrW = GetEnvironmentStringsW();
290 childPrintf(hFile, "[EnvironmentW]\n");
294 if (lstrlenW(ptrW) < 128)
296 childPrintf(hFile, "env%d=%s\n", i, encodeW(ptrW));
299 ptrW += lstrlenW(ptrW) + 1;
301 childPrintf(hFile, "\n");
304 childPrintf(hFile, "[Misc]\n");
305 if (GetCurrentDirectoryA(sizeof(bufA), bufA))
306 childPrintf(hFile, "CurrDirA=%s\n", encodeA(bufA));
307 if (GetCurrentDirectoryW(sizeof(bufW) / sizeof(bufW[0]), bufW))
308 childPrintf(hFile, "CurrDirW=%s\n", encodeW(bufW));
309 childPrintf(hFile, "\n");
314 static char* getChildString(const char* sect, const char* key)
319 GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), resfile);
320 if (buf[0] == '\0' || (buf[0] == '-' && buf[1] == '\0')) return NULL;
321 assert(!(strlen(buf) & 1));
326 /* FIXME: this may be moved to the wtmain.c file, because it may be needed by
327 * others... (windows uses stricmp while Un*x uses strcasecmp...)
329 static int wtstrcasecmp(const char* p1, const char* p2)
334 while (c1 == c2 && c1)
336 c1 = *p1++; c2 = *p2++;
339 c1 = toupper(c1); c2 = toupper(c2);
345 static int strCmp(const char* s1, const char* s2, BOOL sensitive)
347 if (!s1 && !s2) return 0;
350 return (sensitive) ? strcmp(s1, s2) : wtstrcasecmp(s1, s2);
353 #define okChildString(sect, key, expect) \
355 char* result = getChildString(sect, key); \
356 ok(strCmp(result, expect, 1) == 0, "%s:%s expected %s, got %s", sect, key, expect, result); \
359 #define okChildIString(sect, key, expect) \
361 char* result = getChildString(sect, key); \
362 ok(strCmp(result, expect, 0) == 0, "%s:%s expected %s, got %s", sect, key, expect, result); \
365 /* using !expect insures that the test will fail if the sect/key isn't present
368 #define okChildInt(sect, key, expect) \
370 int result = GetPrivateProfileIntA(sect, key, !expect, resfile); \
371 ok(result == expect, "%s:%s expected %d, but got %d\n", sect, key, expect, result); \
374 static void test_Startup(void)
376 char buffer[MAX_PATH];
377 PROCESS_INFORMATION info;
378 STARTUPINFOA startup;
380 /* let's start simplistic */
381 memset(&startup, 0, sizeof(startup));
382 startup.cb = sizeof(startup);
383 startup.dwFlags = STARTF_USESHOWWINDOW;
384 startup.wShowWindow = SW_SHOWNORMAL;
386 get_file_name(resfile);
387 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
388 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
389 /* wait for child to terminate */
390 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
391 /* child process has changed result file, so let profile functions know about it */
392 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
394 okChildInt("StartupInfoA", "cb", startup.cb);
395 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
396 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
397 okChildInt("StartupInfoA", "dwX", startup.dwX);
398 okChildInt("StartupInfoA", "dwY", startup.dwY);
399 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
400 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
401 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
402 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
403 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
404 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
405 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
407 assert(DeleteFileA(resfile) != 0);
409 /* not so simplistic now */
410 memset(&startup, 0, sizeof(startup));
411 startup.cb = sizeof(startup);
412 startup.dwFlags = STARTF_USESHOWWINDOW;
413 startup.wShowWindow = SW_SHOWNORMAL;
414 startup.lpTitle = "I'm the title string";
415 startup.lpDesktop = "I'm the desktop string";
416 startup.dwXCountChars = 0x12121212;
417 startup.dwYCountChars = 0x23232323;
418 startup.dwX = 0x34343434;
419 startup.dwY = 0x45454545;
420 startup.dwXSize = 0x56565656;
421 startup.dwYSize = 0x67676767;
422 startup.dwFillAttribute = 0xA55A;
424 get_file_name(resfile);
425 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
426 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
427 /* wait for child to terminate */
428 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
429 /* child process has changed result file, so let profile functions know about it */
430 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
432 okChildInt("StartupInfoA", "cb", startup.cb);
433 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
434 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
435 okChildInt("StartupInfoA", "dwX", startup.dwX);
436 okChildInt("StartupInfoA", "dwY", startup.dwY);
437 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
438 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
439 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
440 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
441 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
442 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
443 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
445 assert(DeleteFileA(resfile) != 0);
447 /* not so simplistic now */
448 memset(&startup, 0, sizeof(startup));
449 startup.cb = sizeof(startup);
450 startup.dwFlags = STARTF_USESHOWWINDOW;
451 startup.wShowWindow = SW_SHOWNORMAL;
452 startup.lpTitle = "I'm the title string";
453 startup.lpDesktop = NULL;
454 startup.dwXCountChars = 0x12121212;
455 startup.dwYCountChars = 0x23232323;
456 startup.dwX = 0x34343434;
457 startup.dwY = 0x45454545;
458 startup.dwXSize = 0x56565656;
459 startup.dwYSize = 0x67676767;
460 startup.dwFillAttribute = 0xA55A;
462 get_file_name(resfile);
463 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
464 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
465 /* wait for child to terminate */
466 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
467 /* child process has changed result file, so let profile functions know about it */
468 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
470 okChildInt("StartupInfoA", "cb", startup.cb);
471 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
472 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
473 okChildInt("StartupInfoA", "dwX", startup.dwX);
474 okChildInt("StartupInfoA", "dwY", startup.dwY);
475 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
476 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
477 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
478 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
479 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
480 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
481 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
483 assert(DeleteFileA(resfile) != 0);
485 /* not so simplistic now */
486 memset(&startup, 0, sizeof(startup));
487 startup.cb = sizeof(startup);
488 startup.dwFlags = STARTF_USESHOWWINDOW;
489 startup.wShowWindow = SW_SHOWNORMAL;
490 startup.lpTitle = "I'm the title string";
491 startup.lpDesktop = "";
492 startup.dwXCountChars = 0x12121212;
493 startup.dwYCountChars = 0x23232323;
494 startup.dwX = 0x34343434;
495 startup.dwY = 0x45454545;
496 startup.dwXSize = 0x56565656;
497 startup.dwYSize = 0x67676767;
498 startup.dwFillAttribute = 0xA55A;
500 get_file_name(resfile);
501 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
502 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
503 /* wait for child to terminate */
504 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
505 /* child process has changed result file, so let profile functions know about it */
506 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
508 okChildInt("StartupInfoA", "cb", startup.cb);
509 todo_wine okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
510 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
511 okChildInt("StartupInfoA", "dwX", startup.dwX);
512 okChildInt("StartupInfoA", "dwY", startup.dwY);
513 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
514 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
515 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
516 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
517 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
518 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
519 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
521 assert(DeleteFileA(resfile) != 0);
523 /* not so simplistic now */
524 memset(&startup, 0, sizeof(startup));
525 startup.cb = sizeof(startup);
526 startup.dwFlags = STARTF_USESHOWWINDOW;
527 startup.wShowWindow = SW_SHOWNORMAL;
528 startup.lpTitle = NULL;
529 startup.lpDesktop = "I'm the desktop string";
530 startup.dwXCountChars = 0x12121212;
531 startup.dwYCountChars = 0x23232323;
532 startup.dwX = 0x34343434;
533 startup.dwY = 0x45454545;
534 startup.dwXSize = 0x56565656;
535 startup.dwYSize = 0x67676767;
536 startup.dwFillAttribute = 0xA55A;
538 get_file_name(resfile);
539 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
540 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
541 /* wait for child to terminate */
542 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
543 /* child process has changed result file, so let profile functions know about it */
544 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
546 okChildInt("StartupInfoA", "cb", startup.cb);
547 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
548 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
549 okChildInt("StartupInfoA", "dwX", startup.dwX);
550 okChildInt("StartupInfoA", "dwY", startup.dwY);
551 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
552 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
553 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
554 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
555 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
556 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
557 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
559 assert(DeleteFileA(resfile) != 0);
561 /* not so simplistic now */
562 memset(&startup, 0, sizeof(startup));
563 startup.cb = sizeof(startup);
564 startup.dwFlags = STARTF_USESHOWWINDOW;
565 startup.wShowWindow = SW_SHOWNORMAL;
566 startup.lpTitle = "";
567 startup.lpDesktop = "I'm the desktop string";
568 startup.dwXCountChars = 0x12121212;
569 startup.dwYCountChars = 0x23232323;
570 startup.dwX = 0x34343434;
571 startup.dwY = 0x45454545;
572 startup.dwXSize = 0x56565656;
573 startup.dwYSize = 0x67676767;
574 startup.dwFillAttribute = 0xA55A;
576 get_file_name(resfile);
577 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
578 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
579 /* wait for child to terminate */
580 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
581 /* child process has changed result file, so let profile functions know about it */
582 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
584 okChildInt("StartupInfoA", "cb", startup.cb);
585 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
586 todo_wine okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
587 okChildInt("StartupInfoA", "dwX", startup.dwX);
588 okChildInt("StartupInfoA", "dwY", startup.dwY);
589 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
590 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
591 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
592 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
593 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
594 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
595 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
597 assert(DeleteFileA(resfile) != 0);
599 /* not so simplistic now */
600 memset(&startup, 0, sizeof(startup));
601 startup.cb = sizeof(startup);
602 startup.dwFlags = STARTF_USESHOWWINDOW;
603 startup.wShowWindow = SW_SHOWNORMAL;
604 startup.lpTitle = "";
605 startup.lpDesktop = "";
606 startup.dwXCountChars = 0x12121212;
607 startup.dwYCountChars = 0x23232323;
608 startup.dwX = 0x34343434;
609 startup.dwY = 0x45454545;
610 startup.dwXSize = 0x56565656;
611 startup.dwYSize = 0x67676767;
612 startup.dwFillAttribute = 0xA55A;
614 get_file_name(resfile);
615 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
616 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
617 /* wait for child to terminate */
618 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
619 /* child process has changed result file, so let profile functions know about it */
620 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
622 okChildInt("StartupInfoA", "cb", startup.cb);
623 todo_wine okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
624 todo_wine okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
625 okChildInt("StartupInfoA", "dwX", startup.dwX);
626 okChildInt("StartupInfoA", "dwY", startup.dwY);
627 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
628 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
629 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
630 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
631 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
632 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
633 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
635 assert(DeleteFileA(resfile) != 0);
637 /* TODO: test for A/W and W/A and W/W */
640 static void test_CommandLine(void)
642 char buffer[MAX_PATH];
643 PROCESS_INFORMATION info;
644 STARTUPINFOA startup;
646 memset(&startup, 0, sizeof(startup));
647 startup.cb = sizeof(startup);
648 startup.dwFlags = STARTF_USESHOWWINDOW;
649 startup.wShowWindow = SW_SHOWNORMAL;
652 get_file_name(resfile);
653 sprintf(buffer, "%s tests/process.c %s \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
654 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
655 /* wait for child to terminate */
656 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
657 /* child process has changed result file, so let profile functions know about it */
658 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
660 okChildInt("Arguments", "argcA", 4);
661 okChildString("Arguments", "argvA3", "C:\\Program Files\\my nice app.exe");
662 okChildString("Arguments", "argvA4", NULL);
663 okChildString("Arguments", "CommandLineA", buffer);
665 assert(DeleteFileA(resfile) != 0);
667 memset(&startup, 0, sizeof(startup));
668 startup.cb = sizeof(startup);
669 startup.dwFlags = STARTF_USESHOWWINDOW;
670 startup.wShowWindow = SW_SHOWNORMAL;
673 get_file_name(resfile);
674 sprintf(buffer, "%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
675 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
676 /* wait for child to terminate */
677 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
678 /* child process has changed result file, so let profile functions know about it */
679 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
681 okChildInt("Arguments", "argcA", 6);
682 okChildString("Arguments", "argvA3", "a\"b\\");
683 okChildString("Arguments", "argvA4", "c\"");
684 okChildString("Arguments", "argvA5", "d");
685 okChildString("Arguments", "argvA6", NULL);
686 okChildString("Arguments", "CommandLineA", buffer);
688 assert(DeleteFileA(resfile) != 0);
691 static void test_Directory(void)
693 char buffer[MAX_PATH];
694 PROCESS_INFORMATION info;
695 STARTUPINFOA startup;
696 char windir[MAX_PATH];
698 memset(&startup, 0, sizeof(startup));
699 startup.cb = sizeof(startup);
700 startup.dwFlags = STARTF_USESHOWWINDOW;
701 startup.wShowWindow = SW_SHOWNORMAL;
704 get_file_name(resfile);
705 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
706 GetWindowsDirectoryA( windir, sizeof(windir) );
707 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, windir, &startup, &info), "CreateProcess");
708 /* wait for child to terminate */
709 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
710 /* child process has changed result file, so let profile functions know about it */
711 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
713 okChildIString("Misc", "CurrDirA", windir);
715 assert(DeleteFileA(resfile) != 0);
721 ok(b, "Basic init of CreateProcess test");
733 /* things that can be tested:
734 * lookup: check the way program to be executed is searched
735 * environment: check environment string passing
736 * handles: check the handle inheritance stuff (+sec options)
737 * console: check if console creation parameters work