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
25 #include "wine/test.h"
29 static char base[MAX_PATH];
30 static char selfname[MAX_PATH];
31 static char resfile[MAX_PATH];
36 /* ---------------- portable memory allocation thingie */
38 static char memory[16384];
39 static char* memory_index = memory;
41 static char* grab_memory(size_t len)
43 char* ret = memory_index;
47 assert(memory_index <= memory + sizeof(memory));
51 static void release_memory(void)
53 memory_index = memory;
56 /* ---------------- simplistic tool to encode/decode strings (to hide \ " ' and such) */
58 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)
78 len = lstrlenW(str) + 1;
79 ptr = grab_memory(len * 4 + 1);
81 for (i = 0; i < len; i++)
82 sprintf(&ptr[i * 4], "%04x", (unsigned int)(unsigned short)str[i]);
87 static unsigned decode_char(char c)
89 if (c >= '0' && c <= '9') return c - '0';
90 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
91 assert(c >= 'A' && c <= 'F');
95 static char* decodeA(const char* str)
100 len = strlen(str) / 2;
101 if (!len--) return NULL;
102 ptr = grab_memory(len + 1);
103 for (i = 0; i < len; i++)
104 ptr[i] = (decode_char(str[2 * i]) << 4) | decode_char(str[2 * i + 1]);
110 /* This will be needed to decode Unicode strings saved by the child process
111 * when we test Unicode functions.
113 static WCHAR* decodeW(const char* str)
119 len = strlen(str) / 4;
120 if (!len--) return NULL;
121 ptr = (WCHAR*)grab_memory(len * 2 + 1);
122 for (i = 0; i < len; i++)
123 ptr[i] = (decode_char(str[4 * i]) << 12) |
124 (decode_char(str[4 * i + 1]) << 8) |
125 (decode_char(str[4 * i + 2]) << 4) |
126 (decode_char(str[4 * i + 3]) << 0);
132 /******************************************************************
135 * generates basic information like:
136 * base: absolute path to curr dir
137 * selfname: the way to reinvoke ourselves
139 static int init(void)
141 myARGC = winetest_get_mainargs( &myARGV );
142 if (!GetCurrentDirectoryA(sizeof(base), base)) return 0;
143 strcpy(selfname, myARGV[0]);
147 /******************************************************************
150 * generates an absolute file_name for temporary file
153 static void get_file_name(char* buf)
158 GetTempPathA(sizeof(path), path);
159 GetTempFileNameA(path, "wt", 0, buf);
162 /******************************************************************
163 * static void childPrintf
166 static void childPrintf(HANDLE h, const char* fmt, ...)
172 va_start(valist, fmt);
173 vsprintf(buffer, fmt, valist);
175 WriteFile(h, buffer, strlen(buffer), &w, NULL);
179 /******************************************************************
182 * output most of the information in the child process
184 static void doChild(const char* file)
192 WCHAR bufW[MAX_PATH];
193 HANDLE hFile = CreateFileA(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
195 if (hFile == INVALID_HANDLE_VALUE) return;
197 /* output of startup info (Ansi) */
198 GetStartupInfoA(&siA);
200 "[StartupInfoA]\ncb=%08ld\nlpDesktop=%s\nlpTitle=%s\n"
201 "dwX=%lu\ndwY=%lu\ndwXSize=%lu\ndwYSize=%lu\n"
202 "dwXCountChars=%lu\ndwYCountChars=%lu\ndwFillAttribute=%lu\n"
203 "dwFlags=%lu\nwShowWindow=%u\n"
204 "hStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
205 siA.cb, encodeA(siA.lpDesktop), encodeA(siA.lpTitle),
206 siA.dwX, siA.dwY, siA.dwXSize, siA.dwYSize,
207 siA.dwXCountChars, siA.dwYCountChars, siA.dwFillAttribute,
208 siA.dwFlags, siA.wShowWindow,
209 (DWORD)siA.hStdInput, (DWORD)siA.hStdOutput, (DWORD)siA.hStdError);
211 /* since GetStartupInfoW is only implemented in win2k,
212 * zero out before calling so we can notice the difference
214 memset(&siW, 0, sizeof(siW));
215 GetStartupInfoW(&siW);
217 "[StartupInfoW]\ncb=%08ld\nlpDesktop=%s\nlpTitle=%s\n"
218 "dwX=%lu\ndwY=%lu\ndwXSize=%lu\ndwYSize=%lu\n"
219 "dwXCountChars=%lu\ndwYCountChars=%lu\ndwFillAttribute=%lu\n"
220 "dwFlags=%lu\nwShowWindow=%u\n"
221 "hStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
222 siW.cb, encodeW(siW.lpDesktop), encodeW(siW.lpTitle),
223 siW.dwX, siW.dwY, siW.dwXSize, siW.dwYSize,
224 siW.dwXCountChars, siW.dwYCountChars, siW.dwFillAttribute,
225 siW.dwFlags, siW.wShowWindow,
226 (DWORD)siW.hStdInput, (DWORD)siW.hStdOutput, (DWORD)siW.hStdError);
229 childPrintf(hFile, "[Arguments]\nargcA=%d\n", myARGC);
230 for (i = 0; i < myARGC; i++)
232 childPrintf(hFile, "argvA%d=%s\n", i, encodeA(myARGV[i]));
234 childPrintf(hFile, "CommandLineA=%s\n", encodeA(GetCommandLineA()));
240 /* this is part of shell32... and should be tested there */
241 argvW = CommandLineToArgvW(GetCommandLineW(), &argcW);
242 for (i = 0; i < argcW; i++)
244 childPrintf(hFile, "argvW%d=%s\n", i, encodeW(argvW[i]));
247 childPrintf(hFile, "CommandLineW=%s\n\n", encodeW(GetCommandLineW()));
249 /* output of environment (Ansi) */
250 ptrA = GetEnvironmentStringsA();
253 childPrintf(hFile, "[EnvironmentA]\n");
257 if (strlen(ptrA) < 128)
259 childPrintf(hFile, "env%d=%s\n", i, encodeA(ptrA));
262 ptrA += strlen(ptrA) + 1;
264 childPrintf(hFile, "\n");
267 /* output of environment (Unicode) */
268 ptrW = GetEnvironmentStringsW();
271 childPrintf(hFile, "[EnvironmentW]\n");
275 if (lstrlenW(ptrW) < 128)
277 childPrintf(hFile, "env%d=%s\n", i, encodeW(ptrW));
280 ptrW += lstrlenW(ptrW) + 1;
282 childPrintf(hFile, "\n");
285 childPrintf(hFile, "[Misc]\n");
286 if (GetCurrentDirectoryA(sizeof(bufA), bufA))
287 childPrintf(hFile, "CurrDirA=%s\n", encodeA(bufA));
288 if (GetCurrentDirectoryW(sizeof(bufW) / sizeof(bufW[0]), bufW))
289 childPrintf(hFile, "CurrDirW=%s\n", encodeW(bufW));
290 childPrintf(hFile, "\n");
295 static char* getChildString(const char* sect, const char* key)
300 GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), resfile);
301 if (buf[0] == '\0' || (buf[0] == '-' && buf[1] == '\0')) return NULL;
302 assert(!(strlen(buf) & 1));
307 /* FIXME: this may be moved to the wtmain.c file, because it may be needed by
308 * others... (windows uses stricmp while Un*x uses strcasecmp...)
310 static int wtstrcasecmp(const char* p1, const char* p2)
315 while (c1 == c2 && c1)
317 c1 = *p1++; c2 = *p2++;
320 c1 = toupper(c1); c2 = toupper(c2);
326 static int strCmp(const char* s1, const char* s2, BOOL sensitive)
328 if (!s1 && !s2) return 0;
331 return (sensitive) ? strcmp(s1, s2) : wtstrcasecmp(s1, s2);
334 #define okChildString(sect, key, expect) \
336 char* result = getChildString((sect), (key)); \
337 ok(strCmp(result, expect, 1) == 0, "%s:%s expected %s, got %s", (sect), (key), (expect)?(expect):"(null)", result); \
340 #define okChildIString(sect, key, expect) \
342 char* result = getChildString(sect, key); \
343 ok(strCmp(result, expect, 0) == 0, "%s:%s expected %s, got %s", sect, key, expect, result); \
346 /* using !expect insures that the test will fail if the sect/key isn't present
349 #define okChildInt(sect, key, expect) \
351 UINT result = GetPrivateProfileIntA((sect), (key), !(expect), resfile); \
352 ok(result == expect, "%s:%s expected %d, but got %d\n", (sect), (key), (int)(expect), result); \
355 static void test_Startup(void)
357 char buffer[MAX_PATH];
358 PROCESS_INFORMATION info;
359 STARTUPINFOA startup,si;
361 /* let's start simplistic */
362 memset(&startup, 0, sizeof(startup));
363 startup.cb = sizeof(startup);
364 startup.dwFlags = STARTF_USESHOWWINDOW;
365 startup.wShowWindow = SW_SHOWNORMAL;
367 get_file_name(resfile);
368 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
369 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
370 /* wait for child to terminate */
371 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
372 /* child process has changed result file, so let profile functions know about it */
373 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
375 GetStartupInfoA(&si);
376 okChildInt("StartupInfoA", "cb", startup.cb);
377 okChildString("StartupInfoA", "lpDesktop", si.lpDesktop);
378 okChildString("StartupInfoA", "lpTitle", si.lpTitle);
379 okChildInt("StartupInfoA", "dwX", startup.dwX);
380 okChildInt("StartupInfoA", "dwY", startup.dwY);
381 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
382 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
383 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
384 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
385 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
386 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
387 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
389 assert(DeleteFileA(resfile) != 0);
391 /* not so simplistic now */
392 memset(&startup, 0, sizeof(startup));
393 startup.cb = sizeof(startup);
394 startup.dwFlags = STARTF_USESHOWWINDOW;
395 startup.wShowWindow = SW_SHOWNORMAL;
396 startup.lpTitle = "I'm the title string";
397 startup.lpDesktop = "I'm the desktop string";
398 startup.dwXCountChars = 0x12121212;
399 startup.dwYCountChars = 0x23232323;
400 startup.dwX = 0x34343434;
401 startup.dwY = 0x45454545;
402 startup.dwXSize = 0x56565656;
403 startup.dwYSize = 0x67676767;
404 startup.dwFillAttribute = 0xA55A;
406 get_file_name(resfile);
407 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
408 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
409 /* wait for child to terminate */
410 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
411 /* child process has changed result file, so let profile functions know about it */
412 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
414 okChildInt("StartupInfoA", "cb", startup.cb);
415 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
416 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
417 okChildInt("StartupInfoA", "dwX", startup.dwX);
418 okChildInt("StartupInfoA", "dwY", startup.dwY);
419 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
420 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
421 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
422 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
423 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
424 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
425 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
427 assert(DeleteFileA(resfile) != 0);
429 /* not so simplistic now */
430 memset(&startup, 0, sizeof(startup));
431 startup.cb = sizeof(startup);
432 startup.dwFlags = STARTF_USESHOWWINDOW;
433 startup.wShowWindow = SW_SHOWNORMAL;
434 startup.lpTitle = "I'm the title string";
435 startup.lpDesktop = NULL;
436 startup.dwXCountChars = 0x12121212;
437 startup.dwYCountChars = 0x23232323;
438 startup.dwX = 0x34343434;
439 startup.dwY = 0x45454545;
440 startup.dwXSize = 0x56565656;
441 startup.dwYSize = 0x67676767;
442 startup.dwFillAttribute = 0xA55A;
444 get_file_name(resfile);
445 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
446 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
447 /* wait for child to terminate */
448 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
449 /* child process has changed result file, so let profile functions know about it */
450 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
452 okChildInt("StartupInfoA", "cb", startup.cb);
453 okChildString("StartupInfoA", "lpDesktop", si.lpDesktop);
454 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
455 okChildInt("StartupInfoA", "dwX", startup.dwX);
456 okChildInt("StartupInfoA", "dwY", startup.dwY);
457 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
458 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
459 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
460 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
461 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
462 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
463 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
465 assert(DeleteFileA(resfile) != 0);
467 /* not so simplistic now */
468 memset(&startup, 0, sizeof(startup));
469 startup.cb = sizeof(startup);
470 startup.dwFlags = STARTF_USESHOWWINDOW;
471 startup.wShowWindow = SW_SHOWNORMAL;
472 startup.lpTitle = "I'm the title string";
473 startup.lpDesktop = "";
474 startup.dwXCountChars = 0x12121212;
475 startup.dwYCountChars = 0x23232323;
476 startup.dwX = 0x34343434;
477 startup.dwY = 0x45454545;
478 startup.dwXSize = 0x56565656;
479 startup.dwYSize = 0x67676767;
480 startup.dwFillAttribute = 0xA55A;
482 get_file_name(resfile);
483 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
484 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
485 /* wait for child to terminate */
486 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
487 /* child process has changed result file, so let profile functions know about it */
488 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
490 okChildInt("StartupInfoA", "cb", startup.cb);
491 todo_wine okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
492 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
493 okChildInt("StartupInfoA", "dwX", startup.dwX);
494 okChildInt("StartupInfoA", "dwY", startup.dwY);
495 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
496 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
497 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
498 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
499 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
500 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
501 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
503 assert(DeleteFileA(resfile) != 0);
505 /* not so simplistic now */
506 memset(&startup, 0, sizeof(startup));
507 startup.cb = sizeof(startup);
508 startup.dwFlags = STARTF_USESHOWWINDOW;
509 startup.wShowWindow = SW_SHOWNORMAL;
510 startup.lpTitle = NULL;
511 startup.lpDesktop = "I'm the desktop string";
512 startup.dwXCountChars = 0x12121212;
513 startup.dwYCountChars = 0x23232323;
514 startup.dwX = 0x34343434;
515 startup.dwY = 0x45454545;
516 startup.dwXSize = 0x56565656;
517 startup.dwYSize = 0x67676767;
518 startup.dwFillAttribute = 0xA55A;
520 get_file_name(resfile);
521 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
522 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
523 /* wait for child to terminate */
524 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
525 /* child process has changed result file, so let profile functions know about it */
526 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
528 okChildInt("StartupInfoA", "cb", startup.cb);
529 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
530 okChildString("StartupInfoA", "lpTitle", si.lpTitle);
531 okChildInt("StartupInfoA", "dwX", startup.dwX);
532 okChildInt("StartupInfoA", "dwY", startup.dwY);
533 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
534 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
535 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
536 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
537 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
538 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
539 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
541 assert(DeleteFileA(resfile) != 0);
543 /* not so simplistic now */
544 memset(&startup, 0, sizeof(startup));
545 startup.cb = sizeof(startup);
546 startup.dwFlags = STARTF_USESHOWWINDOW;
547 startup.wShowWindow = SW_SHOWNORMAL;
548 startup.lpTitle = "";
549 startup.lpDesktop = "I'm the desktop string";
550 startup.dwXCountChars = 0x12121212;
551 startup.dwYCountChars = 0x23232323;
552 startup.dwX = 0x34343434;
553 startup.dwY = 0x45454545;
554 startup.dwXSize = 0x56565656;
555 startup.dwYSize = 0x67676767;
556 startup.dwFillAttribute = 0xA55A;
558 get_file_name(resfile);
559 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
560 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
561 /* wait for child to terminate */
562 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
563 /* child process has changed result file, so let profile functions know about it */
564 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
566 okChildInt("StartupInfoA", "cb", startup.cb);
567 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
568 todo_wine okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
569 okChildInt("StartupInfoA", "dwX", startup.dwX);
570 okChildInt("StartupInfoA", "dwY", startup.dwY);
571 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
572 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
573 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
574 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
575 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
576 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
577 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
579 assert(DeleteFileA(resfile) != 0);
581 /* not so simplistic now */
582 memset(&startup, 0, sizeof(startup));
583 startup.cb = sizeof(startup);
584 startup.dwFlags = STARTF_USESHOWWINDOW;
585 startup.wShowWindow = SW_SHOWNORMAL;
586 startup.lpTitle = "";
587 startup.lpDesktop = "";
588 startup.dwXCountChars = 0x12121212;
589 startup.dwYCountChars = 0x23232323;
590 startup.dwX = 0x34343434;
591 startup.dwY = 0x45454545;
592 startup.dwXSize = 0x56565656;
593 startup.dwYSize = 0x67676767;
594 startup.dwFillAttribute = 0xA55A;
596 get_file_name(resfile);
597 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
598 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
599 /* wait for child to terminate */
600 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
601 /* child process has changed result file, so let profile functions know about it */
602 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
604 okChildInt("StartupInfoA", "cb", startup.cb);
605 todo_wine okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
606 todo_wine okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
607 okChildInt("StartupInfoA", "dwX", startup.dwX);
608 okChildInt("StartupInfoA", "dwY", startup.dwY);
609 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
610 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
611 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
612 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
613 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
614 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
615 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
617 assert(DeleteFileA(resfile) != 0);
619 /* TODO: test for A/W and W/A and W/W */
622 static void test_CommandLine(void)
624 char buffer[MAX_PATH];
625 PROCESS_INFORMATION info;
626 STARTUPINFOA startup;
628 memset(&startup, 0, sizeof(startup));
629 startup.cb = sizeof(startup);
630 startup.dwFlags = STARTF_USESHOWWINDOW;
631 startup.wShowWindow = SW_SHOWNORMAL;
634 get_file_name(resfile);
635 sprintf(buffer, "%s tests/process.c %s \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
636 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
637 /* wait for child to terminate */
638 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
639 /* child process has changed result file, so let profile functions know about it */
640 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
642 okChildInt("Arguments", "argcA", 4);
643 okChildString("Arguments", "argvA3", "C:\\Program Files\\my nice app.exe");
644 okChildString("Arguments", "argvA4", NULL);
645 okChildString("Arguments", "CommandLineA", buffer);
647 assert(DeleteFileA(resfile) != 0);
649 memset(&startup, 0, sizeof(startup));
650 startup.cb = sizeof(startup);
651 startup.dwFlags = STARTF_USESHOWWINDOW;
652 startup.wShowWindow = SW_SHOWNORMAL;
655 get_file_name(resfile);
656 sprintf(buffer, "%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
657 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
658 /* wait for child to terminate */
659 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
660 /* child process has changed result file, so let profile functions know about it */
661 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
663 okChildInt("Arguments", "argcA", 6);
664 okChildString("Arguments", "argvA3", "a\"b\\");
665 okChildString("Arguments", "argvA4", "c\"");
666 okChildString("Arguments", "argvA5", "d");
667 okChildString("Arguments", "argvA6", NULL);
668 okChildString("Arguments", "CommandLineA", buffer);
670 assert(DeleteFileA(resfile) != 0);
673 static void test_Directory(void)
675 char buffer[MAX_PATH];
676 PROCESS_INFORMATION info;
677 STARTUPINFOA startup;
678 char windir[MAX_PATH];
680 memset(&startup, 0, sizeof(startup));
681 startup.cb = sizeof(startup);
682 startup.dwFlags = STARTF_USESHOWWINDOW;
683 startup.wShowWindow = SW_SHOWNORMAL;
686 get_file_name(resfile);
687 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
688 GetWindowsDirectoryA( windir, sizeof(windir) );
689 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, windir, &startup, &info), "CreateProcess");
690 /* wait for child to terminate */
691 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
692 /* child process has changed result file, so let profile functions know about it */
693 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
695 okChildIString("Misc", "CurrDirA", windir);
697 assert(DeleteFileA(resfile) != 0);
703 ok(b, "Basic init of CreateProcess test");
715 /* things that can be tested:
716 * lookup: check the way program to be executed is searched
717 * environment: check environment string passing
718 * handles: check the handle inheritance stuff (+sec options)
719 * console: check if console creation parameters work