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]);
109 static WCHAR* decodeW(const char* str)
115 len = strlen(str) / 4;
116 if (!len--) return NULL;
117 ptr = (WCHAR*)grab_memory(len * 2 + 1);
118 for (i = 0; i < len; i++)
119 ptr[i] = (decode_char(str[4 * i]) << 12) |
120 (decode_char(str[4 * i + 1]) << 8) |
121 (decode_char(str[4 * i + 2]) << 4) |
122 (decode_char(str[4 * i + 3]) << 0);
127 /******************************************************************
130 * generates basic information like:
131 * base: absolute path to curr dir
132 * selfname: the way to reinvoke ourselves
134 static int init(void)
136 myARGC = winetest_get_mainargs( &myARGV );
137 if (!GetCurrentDirectoryA(sizeof(base), base)) return 0;
138 strcpy(selfname, myARGV[0]);
142 /******************************************************************
145 * generates an absolute file_name for temporary file
148 static void get_file_name(char* buf)
153 GetTempPathA(sizeof(path), path);
154 GetTempFileNameA(path, "wt", 0, buf);
157 /******************************************************************
158 * static void childPrintf
161 static void childPrintf(HANDLE h, const char* fmt, ...)
167 va_start(valist, fmt);
168 vsprintf(buffer, fmt, valist);
170 WriteFile(h, buffer, strlen(buffer), &w, NULL);
174 /******************************************************************
177 * output most of the information in the child process
179 static void doChild(const char* file)
187 WCHAR bufW[MAX_PATH];
188 HANDLE hFile = CreateFileA(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
190 if (hFile == INVALID_HANDLE_VALUE) return;
192 /* output of startup info (Ansi) */
193 GetStartupInfoA(&siA);
195 "[StartupInfoA]\ncb=%08ld\nlpDesktop=%s\nlpTitle=%s\n"
196 "dwX=%lu\ndwY=%lu\ndwXSize=%lu\ndwYSize=%lu\n"
197 "dwXCountChars=%lu\ndwYCountChars=%lu\ndwFillAttribute=%lu\n"
198 "dwFlags=%lu\nwShowWindow=%u\n"
199 "hStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
200 siA.cb, encodeA(siA.lpDesktop), encodeA(siA.lpTitle),
201 siA.dwX, siA.dwY, siA.dwXSize, siA.dwYSize,
202 siA.dwXCountChars, siA.dwYCountChars, siA.dwFillAttribute,
203 siA.dwFlags, siA.wShowWindow,
204 (DWORD)siA.hStdInput, (DWORD)siA.hStdOutput, (DWORD)siA.hStdError);
206 /* since GetStartupInfoW is only implemented in win2k,
207 * zero out before calling so we can notice the difference
209 memset(&siW, 0, sizeof(siW));
210 GetStartupInfoW(&siW);
212 "[StartupInfoW]\ncb=%08ld\nlpDesktop=%s\nlpTitle=%s\n"
213 "dwX=%lu\ndwY=%lu\ndwXSize=%lu\ndwYSize=%lu\n"
214 "dwXCountChars=%lu\ndwYCountChars=%lu\ndwFillAttribute=%lu\n"
215 "dwFlags=%lu\nwShowWindow=%u\n"
216 "hStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
217 siW.cb, encodeW(siW.lpDesktop), encodeW(siW.lpTitle),
218 siW.dwX, siW.dwY, siW.dwXSize, siW.dwYSize,
219 siW.dwXCountChars, siW.dwYCountChars, siW.dwFillAttribute,
220 siW.dwFlags, siW.wShowWindow,
221 (DWORD)siW.hStdInput, (DWORD)siW.hStdOutput, (DWORD)siW.hStdError);
224 childPrintf(hFile, "[Arguments]\nargcA=%d\n", myARGC);
225 for (i = 0; i < myARGC; i++)
227 childPrintf(hFile, "argvA%d=%s\n", i, encodeA(myARGV[i]));
229 childPrintf(hFile, "CommandLineA=%s\n", encodeA(GetCommandLineA()));
235 /* this is part of shell32... and should be tested there */
236 argvW = CommandLineToArgvW(GetCommandLineW(), &argcW);
237 for (i = 0; i < argcW; i++)
239 childPrintf(hFile, "argvW%d=%s\n", i, encodeW(argvW[i]));
242 childPrintf(hFile, "CommandLineW=%s\n\n", encodeW(GetCommandLineW()));
244 /* output of environment (Ansi) */
245 ptrA = GetEnvironmentStringsA();
248 childPrintf(hFile, "[EnvironmentA]\n");
252 if (strlen(ptrA) < 128)
254 childPrintf(hFile, "env%d=%s\n", i, encodeA(ptrA));
257 ptrA += strlen(ptrA) + 1;
259 childPrintf(hFile, "\n");
262 /* output of environment (Unicode) */
263 ptrW = GetEnvironmentStringsW();
266 childPrintf(hFile, "[EnvironmentW]\n");
270 if (lstrlenW(ptrW) < 128)
272 childPrintf(hFile, "env%d=%s\n", i, encodeW(ptrW));
275 ptrW += lstrlenW(ptrW) + 1;
277 childPrintf(hFile, "\n");
280 childPrintf(hFile, "[Misc]\n");
281 if (GetCurrentDirectoryA(sizeof(bufA), bufA))
282 childPrintf(hFile, "CurrDirA=%s\n", encodeA(bufA));
283 if (GetCurrentDirectoryW(sizeof(bufW) / sizeof(bufW[0]), bufW))
284 childPrintf(hFile, "CurrDirW=%s\n", encodeW(bufW));
285 childPrintf(hFile, "\n");
290 static char* getChildString(const char* sect, const char* key)
295 GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), resfile);
296 if (buf[0] == '\0' || (buf[0] == '-' && buf[1] == '\0')) return NULL;
297 assert(!(strlen(buf) & 1));
302 /* FIXME: this may be moved to the wtmain.c file, because it may be needed by
303 * others... (windows uses stricmp while Un*x uses strcasecmp...)
305 static int wtstrcasecmp(const char* p1, const char* p2)
310 while (c1 == c2 && c1)
312 c1 = *p1++; c2 = *p2++;
315 c1 = toupper(c1); c2 = toupper(c2);
321 static int strCmp(const char* s1, const char* s2, BOOL sensitive)
323 if (!s1 && !s2) return 0;
326 return (sensitive) ? strcmp(s1, s2) : wtstrcasecmp(s1, s2);
329 #define okChildString(sect, key, expect) \
331 char* result = getChildString((sect), (key)); \
332 ok(strCmp(result, expect, 1) == 0, "%s:%s expected %s, got %s", (sect), (key), (expect)?(expect):"(null)", result); \
335 #define okChildIString(sect, key, expect) \
337 char* result = getChildString(sect, key); \
338 ok(strCmp(result, expect, 0) == 0, "%s:%s expected %s, got %s", sect, key, expect, result); \
341 /* using !expect insures that the test will fail if the sect/key isn't present
344 #define okChildInt(sect, key, expect) \
346 UINT result = GetPrivateProfileIntA((sect), (key), !(expect), resfile); \
347 ok(result == expect, "%s:%s expected %d, but got %d\n", (sect), (key), (int)(expect), result); \
350 static void test_Startup(void)
352 char buffer[MAX_PATH];
353 PROCESS_INFORMATION info;
354 STARTUPINFOA startup;
356 /* let's start simplistic */
357 memset(&startup, 0, sizeof(startup));
358 startup.cb = sizeof(startup);
359 startup.dwFlags = STARTF_USESHOWWINDOW;
360 startup.wShowWindow = SW_SHOWNORMAL;
362 get_file_name(resfile);
363 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
364 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
365 /* wait for child to terminate */
366 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
367 /* child process has changed result file, so let profile functions know about it */
368 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
370 okChildInt("StartupInfoA", "cb", startup.cb);
371 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
372 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
373 okChildInt("StartupInfoA", "dwX", startup.dwX);
374 okChildInt("StartupInfoA", "dwY", startup.dwY);
375 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
376 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
377 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
378 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
379 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
380 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
381 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
383 assert(DeleteFileA(resfile) != 0);
385 /* not so simplistic now */
386 memset(&startup, 0, sizeof(startup));
387 startup.cb = sizeof(startup);
388 startup.dwFlags = STARTF_USESHOWWINDOW;
389 startup.wShowWindow = SW_SHOWNORMAL;
390 startup.lpTitle = "I'm the title string";
391 startup.lpDesktop = "I'm the desktop string";
392 startup.dwXCountChars = 0x12121212;
393 startup.dwYCountChars = 0x23232323;
394 startup.dwX = 0x34343434;
395 startup.dwY = 0x45454545;
396 startup.dwXSize = 0x56565656;
397 startup.dwYSize = 0x67676767;
398 startup.dwFillAttribute = 0xA55A;
400 get_file_name(resfile);
401 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
402 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
403 /* wait for child to terminate */
404 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
405 /* child process has changed result file, so let profile functions know about it */
406 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
408 okChildInt("StartupInfoA", "cb", startup.cb);
409 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
410 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
411 okChildInt("StartupInfoA", "dwX", startup.dwX);
412 okChildInt("StartupInfoA", "dwY", startup.dwY);
413 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
414 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
415 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
416 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
417 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
418 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
419 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
421 assert(DeleteFileA(resfile) != 0);
423 /* not so simplistic now */
424 memset(&startup, 0, sizeof(startup));
425 startup.cb = sizeof(startup);
426 startup.dwFlags = STARTF_USESHOWWINDOW;
427 startup.wShowWindow = SW_SHOWNORMAL;
428 startup.lpTitle = "I'm the title string";
429 startup.lpDesktop = NULL;
430 startup.dwXCountChars = 0x12121212;
431 startup.dwYCountChars = 0x23232323;
432 startup.dwX = 0x34343434;
433 startup.dwY = 0x45454545;
434 startup.dwXSize = 0x56565656;
435 startup.dwYSize = 0x67676767;
436 startup.dwFillAttribute = 0xA55A;
438 get_file_name(resfile);
439 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
440 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
441 /* wait for child to terminate */
442 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
443 /* child process has changed result file, so let profile functions know about it */
444 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
446 okChildInt("StartupInfoA", "cb", startup.cb);
447 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
448 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
449 okChildInt("StartupInfoA", "dwX", startup.dwX);
450 okChildInt("StartupInfoA", "dwY", startup.dwY);
451 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
452 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
453 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
454 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
455 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
456 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
457 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
459 assert(DeleteFileA(resfile) != 0);
461 /* not so simplistic now */
462 memset(&startup, 0, sizeof(startup));
463 startup.cb = sizeof(startup);
464 startup.dwFlags = STARTF_USESHOWWINDOW;
465 startup.wShowWindow = SW_SHOWNORMAL;
466 startup.lpTitle = "I'm the title string";
467 startup.lpDesktop = "";
468 startup.dwXCountChars = 0x12121212;
469 startup.dwYCountChars = 0x23232323;
470 startup.dwX = 0x34343434;
471 startup.dwY = 0x45454545;
472 startup.dwXSize = 0x56565656;
473 startup.dwYSize = 0x67676767;
474 startup.dwFillAttribute = 0xA55A;
476 get_file_name(resfile);
477 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
478 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
479 /* wait for child to terminate */
480 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
481 /* child process has changed result file, so let profile functions know about it */
482 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
484 okChildInt("StartupInfoA", "cb", startup.cb);
485 todo_wine okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
486 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
487 okChildInt("StartupInfoA", "dwX", startup.dwX);
488 okChildInt("StartupInfoA", "dwY", startup.dwY);
489 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
490 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
491 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
492 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
493 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
494 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
495 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
497 assert(DeleteFileA(resfile) != 0);
499 /* not so simplistic now */
500 memset(&startup, 0, sizeof(startup));
501 startup.cb = sizeof(startup);
502 startup.dwFlags = STARTF_USESHOWWINDOW;
503 startup.wShowWindow = SW_SHOWNORMAL;
504 startup.lpTitle = NULL;
505 startup.lpDesktop = "I'm the desktop string";
506 startup.dwXCountChars = 0x12121212;
507 startup.dwYCountChars = 0x23232323;
508 startup.dwX = 0x34343434;
509 startup.dwY = 0x45454545;
510 startup.dwXSize = 0x56565656;
511 startup.dwYSize = 0x67676767;
512 startup.dwFillAttribute = 0xA55A;
514 get_file_name(resfile);
515 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
516 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
517 /* wait for child to terminate */
518 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
519 /* child process has changed result file, so let profile functions know about it */
520 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
522 okChildInt("StartupInfoA", "cb", startup.cb);
523 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
524 okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
525 okChildInt("StartupInfoA", "dwX", startup.dwX);
526 okChildInt("StartupInfoA", "dwY", startup.dwY);
527 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
528 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
529 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
530 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
531 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
532 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
533 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
535 assert(DeleteFileA(resfile) != 0);
537 /* not so simplistic now */
538 memset(&startup, 0, sizeof(startup));
539 startup.cb = sizeof(startup);
540 startup.dwFlags = STARTF_USESHOWWINDOW;
541 startup.wShowWindow = SW_SHOWNORMAL;
542 startup.lpTitle = "";
543 startup.lpDesktop = "I'm the desktop string";
544 startup.dwXCountChars = 0x12121212;
545 startup.dwYCountChars = 0x23232323;
546 startup.dwX = 0x34343434;
547 startup.dwY = 0x45454545;
548 startup.dwXSize = 0x56565656;
549 startup.dwYSize = 0x67676767;
550 startup.dwFillAttribute = 0xA55A;
552 get_file_name(resfile);
553 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
554 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
555 /* wait for child to terminate */
556 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
557 /* child process has changed result file, so let profile functions know about it */
558 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
560 okChildInt("StartupInfoA", "cb", startup.cb);
561 okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
562 todo_wine okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
563 okChildInt("StartupInfoA", "dwX", startup.dwX);
564 okChildInt("StartupInfoA", "dwY", startup.dwY);
565 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
566 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
567 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
568 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
569 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
570 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
571 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
573 assert(DeleteFileA(resfile) != 0);
575 /* not so simplistic now */
576 memset(&startup, 0, sizeof(startup));
577 startup.cb = sizeof(startup);
578 startup.dwFlags = STARTF_USESHOWWINDOW;
579 startup.wShowWindow = SW_SHOWNORMAL;
580 startup.lpTitle = "";
581 startup.lpDesktop = "";
582 startup.dwXCountChars = 0x12121212;
583 startup.dwYCountChars = 0x23232323;
584 startup.dwX = 0x34343434;
585 startup.dwY = 0x45454545;
586 startup.dwXSize = 0x56565656;
587 startup.dwYSize = 0x67676767;
588 startup.dwFillAttribute = 0xA55A;
590 get_file_name(resfile);
591 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
592 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
593 /* wait for child to terminate */
594 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
595 /* child process has changed result file, so let profile functions know about it */
596 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
598 okChildInt("StartupInfoA", "cb", startup.cb);
599 todo_wine okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
600 todo_wine okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
601 okChildInt("StartupInfoA", "dwX", startup.dwX);
602 okChildInt("StartupInfoA", "dwY", startup.dwY);
603 okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
604 okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
605 okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
606 okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
607 okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
608 okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
609 okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
611 assert(DeleteFileA(resfile) != 0);
613 /* TODO: test for A/W and W/A and W/W */
616 static void test_CommandLine(void)
618 char buffer[MAX_PATH];
619 PROCESS_INFORMATION info;
620 STARTUPINFOA startup;
622 memset(&startup, 0, sizeof(startup));
623 startup.cb = sizeof(startup);
624 startup.dwFlags = STARTF_USESHOWWINDOW;
625 startup.wShowWindow = SW_SHOWNORMAL;
628 get_file_name(resfile);
629 sprintf(buffer, "%s tests/process.c %s \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
630 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
631 /* wait for child to terminate */
632 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
633 /* child process has changed result file, so let profile functions know about it */
634 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
636 okChildInt("Arguments", "argcA", 4);
637 okChildString("Arguments", "argvA3", "C:\\Program Files\\my nice app.exe");
638 okChildString("Arguments", "argvA4", NULL);
639 okChildString("Arguments", "CommandLineA", buffer);
641 assert(DeleteFileA(resfile) != 0);
643 memset(&startup, 0, sizeof(startup));
644 startup.cb = sizeof(startup);
645 startup.dwFlags = STARTF_USESHOWWINDOW;
646 startup.wShowWindow = SW_SHOWNORMAL;
649 get_file_name(resfile);
650 sprintf(buffer, "%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
651 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess");
652 /* wait for child to terminate */
653 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
654 /* child process has changed result file, so let profile functions know about it */
655 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
657 okChildInt("Arguments", "argcA", 6);
658 okChildString("Arguments", "argvA3", "a\"b\\");
659 okChildString("Arguments", "argvA4", "c\"");
660 okChildString("Arguments", "argvA5", "d");
661 okChildString("Arguments", "argvA6", NULL);
662 okChildString("Arguments", "CommandLineA", buffer);
664 assert(DeleteFileA(resfile) != 0);
667 static void test_Directory(void)
669 char buffer[MAX_PATH];
670 PROCESS_INFORMATION info;
671 STARTUPINFOA startup;
672 char windir[MAX_PATH];
674 memset(&startup, 0, sizeof(startup));
675 startup.cb = sizeof(startup);
676 startup.dwFlags = STARTF_USESHOWWINDOW;
677 startup.wShowWindow = SW_SHOWNORMAL;
680 get_file_name(resfile);
681 sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
682 GetWindowsDirectoryA( windir, sizeof(windir) );
683 ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, windir, &startup, &info), "CreateProcess");
684 /* wait for child to terminate */
685 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination");
686 /* child process has changed result file, so let profile functions know about it */
687 WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
689 okChildIString("Misc", "CurrDirA", windir);
691 assert(DeleteFileA(resfile) != 0);
697 ok(b, "Basic init of CreateProcess test");
709 /* things that can be tested:
710 * lookup: check the way program to be executed is searched
711 * environment: check environment string passing
712 * handles: check the handle inheritance stuff (+sec options)
713 * console: check if console creation parameters work