2 * CRTDLL spawn functions
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
9 * These functions differ in whether they pass arguments as an array
10 * (v in the name) or as varags (l in the name), whether they
11 * seach the path (p in the name) and/or whether they take an
12 * environment (e in the name) or pass the parents environment.
14 * Name varargs? path? environment?
24 * Implementation Notes:
25 * MT Safe - But only because of missing functionality.
27 * After translating input arguments into the required format for
28 * CreateProcess(), the internal function __CRTDLL__spawn() is
29 * called to perform the actual spawning.
32 * -File handles need some special handling. Sometimes children get
33 * open file handles, sometimes not. The docs are confusing.
34 * -No check for maximum path/argument/environment size is done.
35 * Unresolved issues Uwe Bonnes 970904:
36 * -system-call calls another wine process, but without debugging arguments
37 * and uses the first wine executable in the path
45 DEFAULT_DEBUG_CHANNEL(crtdll
);
47 /* Process creation flags */
55 extern void __CRTDLL__set_errno(ULONG err
);
56 extern LPVOID __cdecl
CRTDLL_calloc(DWORD size
, DWORD count
);
57 extern VOID __cdecl
CRTDLL_free(void *ptr
);
58 extern VOID __cdecl
CRTDLL__exit(LONG ret
);
59 extern INT CRTDLL_doserrno
;
62 /* INTERNAL: Spawn a child process */
63 static int __CRTDLL__spawn(INT flags
, LPCSTR exe
, LPSTR args
, LPSTR env
)
66 PROCESS_INFORMATION pi
;
68 if ((unsigned)flags
> _P_DETACH
)
70 CRTDLL_errno
= EINVAL
;
74 FIXME(":must dup/kill streams for child process\n");
76 memset(&si
, 0, sizeof(si
));
79 if (!CreateProcessA(exe
, args
, NULL
, NULL
, TRUE
,
80 flags
== _P_DETACH
? DETACHED_PROCESS
: 0,
83 __CRTDLL__set_errno(GetLastError());
90 WaitForSingleObject(pi
.hProcess
,-1); /* wait forvever */
91 GetExitCodeProcess(pi
.hProcess
,&pi
.dwProcessId
);
92 CloseHandle(pi
.hProcess
);
93 CloseHandle(pi
.hThread
);
94 return pi
.dwProcessId
;
96 CloseHandle(pi
.hProcess
);
101 CloseHandle(pi
.hThread
);
106 return -1; /* cant reach here */
110 /* INTERNAL: Convert argv list to a single 'delim'-seperated string */
111 static LPSTR
__CRTDLL__argvtos(LPCSTR
*arg
, CHAR delim
)
113 LPCSTR
*search
= arg
;
123 size
+= strlen(*search
) + 1;
127 if (!(ret
= (LPSTR
)CRTDLL_calloc(size
+ 1, 1)))
135 int strsize
= strlen(*search
);
136 memcpy(ret
+size
,*search
,strsize
);
137 ret
[size
+strsize
] = delim
;
145 /*********************************************************************
146 * _cwait (CRTDLL.069)
148 * Wait for a spawned process to finish.
150 INT __cdecl
CRTDLL__cwait(PINT status
, INT pid
, INT action
)
152 HANDLE hPid
= (HANDLE
)pid
;
154 action
= action
; /* Remove warning */
156 if (!WaitForSingleObject(hPid
, -1)) /* wait forvever */
161 GetExitCodeProcess(hPid
, &stat
);
166 CRTDLL_doserrno
= GetLastError();
168 if (CRTDLL_doserrno
== ERROR_INVALID_HANDLE
)
169 CRTDLL_errno
= ECHILD
;
171 __CRTDLL__set_errno(CRTDLL_doserrno
);
173 return status
? *status
= -1 : -1;
177 /*********************************************************************
178 * _spawnv (CRTDLL.273)
182 HANDLE __cdecl
CRTDLL__spawnv(INT flags
, LPCSTR name
, LPCSTR
*argv
)
184 return CRTDLL__spawnve(flags
, name
, argv
, NULL
);
188 /*********************************************************************
189 * _spawnve (CRTDLL.274)
193 HANDLE __cdecl
CRTDLL__spawnve(INT flags
, LPCSTR name
, LPCSTR
*argv
, LPCSTR
*envv
)
195 LPSTR args
= __CRTDLL__argvtos(argv
,' ');
196 LPSTR envs
= __CRTDLL__argvtos(envv
,0);
197 LPCSTR fullname
= name
;
200 FIXME(":not translating name %s to locate program\n",fullname
);
201 TRACE(":call (%s), params (%s), env (%s)\n",name
,args
,envs
?"Custom":"Null");
205 ret
= __CRTDLL__spawn(flags
, fullname
, args
, envs
);
215 /*********************************************************************
216 * _spawnvp (CRTDLL.275)
220 HANDLE __cdecl
CRTDLL__spawnvp(INT flags
, LPCSTR name
, LPCSTR
*argv
)
222 return CRTDLL__spawnvpe(flags
, name
, argv
, NULL
);
226 /*********************************************************************
227 * _spawnvpe (CRTDLL.276)
231 HANDLE __cdecl
CRTDLL__spawnvpe(INT flags
, LPCSTR name
, LPCSTR
*argv
, LPCSTR
*envv
)
233 char fullname
[MAX_PATH
];
235 CRTDLL__searchenv(name
, "PATH", fullname
);
236 return CRTDLL__spawnve(flags
, fullname
[0] ? fullname
: name
, argv
, envv
);
240 /*********************************************************************
241 * system (CRTDLL.485)
243 * Spawn an O/S process.
245 INT __cdecl
CRTDLL_system(LPCSTR cmd
)
247 /* FIXME: should probably launch cmd interpreter in COMSPEC */
248 return __CRTDLL__spawn(_P_WAIT
, cmd
, NULL
, NULL
);