Make FIXMEs more grep-able.
[wine/multimedia.git] / dlls / msvcrt / process.c
blob3d0e4d21bbe61a911210245e3f1ff578ae7224c6
1 /*
2 * msvcrt.dll spawn/exec functions
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
9 * FIXME:
10 * -File handles need some special handling. Sometimes children get
11 * open file handles, sometimes not. The docs are confusing
12 * -No check for maximum path/argument/environment size is done
14 #include "msvcrt.h"
15 #include "ms_errno.h"
17 #include "msvcrt/process.h"
18 #include "msvcrt/stdlib.h"
19 #include "msvcrt/string.h"
21 #include "wine/debug.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
25 /* FIXME: Check file extensions for app to run */
26 static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
27 static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
28 static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
29 static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
31 /* INTERNAL: Spawn a child process */
32 static int msvcrt_spawn(int flags, const char* exe, char* cmdline, char* env)
34 STARTUPINFOA si;
35 PROCESS_INFORMATION pi;
37 if (sizeof(HANDLE) != sizeof(int))
38 WARN("This call is unsuitable for your architecture\n");
40 if ((unsigned)flags > _P_DETACH)
42 SET_THREAD_VAR(errno,MSVCRT_EINVAL);
43 return -1;
46 FIXME(":must dup/kill streams for child process\n");
48 memset(&si, 0, sizeof(si));
49 si.cb = sizeof(si);
51 if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE,
52 flags == _P_DETACH ? DETACHED_PROCESS : 0,
53 env, NULL, &si, &pi))
55 MSVCRT__set_errno(GetLastError());
56 return -1;
59 switch(flags)
61 case _P_WAIT:
62 WaitForSingleObject(pi.hProcess,-1); /* wait forvever */
63 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
64 CloseHandle(pi.hProcess);
65 CloseHandle(pi.hThread);
66 return (int)pi.dwProcessId;
67 case _P_DETACH:
68 CloseHandle(pi.hProcess);
69 pi.hProcess = 0;
70 /* fall through */
71 case _P_NOWAIT:
72 case _P_NOWAITO:
73 CloseHandle(pi.hThread);
74 return (int)pi.hProcess;
75 case _P_OVERLAY:
76 MSVCRT__exit(0);
78 return -1; /* can't reach here */
81 /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
82 * extra '\0' to terminate it
84 static char* msvcrt_argvtos(const char* const* arg, char delim)
86 const char* const* a;
87 long size;
88 char* p;
89 char* ret;
91 if (!arg && !delim)
93 /* Return NULL for an empty environment list */
94 return NULL;
97 /* get length */
98 a = arg;
99 size = 0;
100 while (*a)
102 size += strlen(*a) + 1;
103 a++;
106 ret = (char*)MSVCRT_malloc(size + 1);
107 if (!ret)
108 return NULL;
110 /* fill string */
111 a = arg;
112 p = ret;
113 while (*a)
115 int len = strlen(*a);
116 memcpy(ret+size,*a,len);
117 p += len;
118 *p++ = delim;
119 a++;
121 *p='\0';
122 return ret;
125 /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
126 * extra '\0' to terminate it
128 static char* msvcrt_valisttos(const char* arg0, va_list alist, char delim)
130 va_list alist2 = alist;
131 long size;
132 const char *arg;
133 char* p;
134 char *ret;
136 if (!arg0 && !delim)
138 /* Return NULL for an empty environment list */
139 return NULL;
142 /* get length */
143 arg = arg0;
144 size = 0;
145 do {
146 size += strlen(arg) + 1;
147 arg = va_arg(alist, char*);
148 } while (arg != NULL);
150 ret = (char*)MSVCRT_malloc(size + 1);
151 if (!ret)
152 return NULL;
154 /* fill string */
155 arg = arg0;
156 p = ret;
157 do {
158 int len = strlen(arg);
159 memcpy(p,arg,len);
160 p += len;
161 *p++ = delim;
162 arg = va_arg(alist2, char*);
163 } while (arg != NULL);
164 *p = '\0';
165 return ret;
168 /*********************************************************************
169 * _cwait (MSVCRT.@)
171 int _cwait(int *status, int pid, int action)
173 HANDLE hPid = (HANDLE)pid;
174 int doserrno;
176 action = action; /* Remove warning */
178 if (!WaitForSingleObject(hPid, -1)) /* wait forever */
180 if (status)
182 DWORD stat;
183 GetExitCodeProcess(hPid, &stat);
184 *status = (int)stat;
186 return (int)pid;
188 doserrno = GetLastError();
190 if (doserrno == ERROR_INVALID_HANDLE)
192 SET_THREAD_VAR(errno, MSVCRT_ECHILD);
193 SET_THREAD_VAR(doserrno,doserrno);
195 else
196 MSVCRT__set_errno(doserrno);
198 return status ? *status = -1 : -1;
201 /*********************************************************************
202 * _execl (MSVCRT.@)
204 * Like on Windows, this function does not handle arguments with spaces
205 * or double-quotes.
207 int _execl(const char* name, const char* arg0, ...)
209 va_list ap;
210 char * args;
211 int ret;
213 va_start(ap, arg0);
214 args = msvcrt_valisttos(arg0, ap, ' ');
215 va_end(ap);
217 ret = msvcrt_spawn(_P_OVERLAY, name, args, NULL);
218 MSVCRT_free(args);
220 return ret;
223 /*********************************************************************
224 * _execlp (MSVCRT.@)
226 * Like on Windows, this function does not handle arguments with spaces
227 * or double-quotes.
229 int _execlp(const char* name, const char* arg0, ...)
231 va_list ap;
232 char * args;
233 int ret;
234 char fullname[MAX_PATH];
236 _searchenv(name, "PATH", fullname);
238 va_start(ap, arg0);
239 args = msvcrt_valisttos(arg0, ap, ' ');
240 va_end(ap);
242 ret = msvcrt_spawn(_P_OVERLAY, fullname[0] ? fullname : name, args, NULL);
243 MSVCRT_free(args);
245 return ret;
248 /*********************************************************************
249 * _execv (MSVCRT.@)
251 * Like on Windows, this function does not handle arguments with spaces
252 * or double-quotes.
254 int _execv(const char* name, char* const* argv)
256 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, NULL);
259 /*********************************************************************
260 * _execve (MSVCRT.@)
262 * Like on Windows, this function does not handle arguments with spaces
263 * or double-quotes.
265 int _execve(const char* name, char* const* argv, const char* const* envv)
267 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, envv);
270 /*********************************************************************
271 * _execvpe (MSVCRT.@)
273 * Like on Windows, this function does not handle arguments with spaces
274 * or double-quotes.
276 int _execvpe(const char* name, char* const* argv, const char* const* envv)
278 char fullname[MAX_PATH];
280 _searchenv(name, "PATH", fullname);
281 return _spawnve(_P_OVERLAY, fullname[0] ? fullname : name,
282 (const char* const*) argv, envv);
285 /*********************************************************************
286 * _execvp (MSVCRT.@)
288 * Like on Windows, this function does not handle arguments with spaces
289 * or double-quotes.
291 int _execvp(const char* name, char* const* argv)
293 return _execvpe(name, argv, NULL);
296 /*********************************************************************
297 * _spawnl (MSVCRT.@)
299 * Like on Windows, this function does not handle arguments with spaces
300 * or double-quotes.
302 int _spawnl(int flags, const char* name, const char* arg0, ...)
304 va_list ap;
305 char * args;
306 int ret;
308 va_start(ap, arg0);
309 args = msvcrt_valisttos(arg0, ap, ' ');
310 va_end(ap);
312 ret = msvcrt_spawn(flags, name, args, NULL);
313 MSVCRT_free(args);
315 return ret;
318 /*********************************************************************
319 * _spawnlp (MSVCRT.@)
321 * Like on Windows, this function does not handle arguments with spaces
322 * or double-quotes.
324 int _spawnlp(int flags, const char* name, const char* arg0, ...)
326 va_list ap;
327 char * args;
328 int ret;
329 char fullname[MAX_PATH];
331 _searchenv(name, "PATH", fullname);
333 va_start(ap, arg0);
334 args = msvcrt_valisttos(arg0, ap, ' ');
335 va_end(ap);
337 ret = msvcrt_spawn(flags, fullname[0] ? fullname : name, args, NULL);
338 MSVCRT_free(args);
340 return ret;
343 /*********************************************************************
344 * _spawnve (MSVCRT.@)
346 * Like on Windows, this function does not handle arguments with spaces
347 * or double-quotes.
349 int _spawnve(int flags, const char* name, const char* const* argv,
350 const char* const* envv)
352 char * args = msvcrt_argvtos(argv,' ');
353 char * envs = msvcrt_argvtos(envv,0);
354 const char *fullname = name;
355 int ret = -1;
357 FIXME(":not translating name %s to locate program\n",fullname);
358 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
360 if (args)
362 ret = msvcrt_spawn(flags, fullname, args, envs);
363 MSVCRT_free(args);
365 if (envs)
366 MSVCRT_free(envs);
368 return ret;
371 /*********************************************************************
372 * _spawnv (MSVCRT.@)
374 * Like on Windows, this function does not handle arguments with spaces
375 * or double-quotes.
377 int _spawnv(int flags, const char* name, const char* const* argv)
379 return _spawnve(flags, name, argv, NULL);
382 /*********************************************************************
383 * _spawnvpe (MSVCRT.@)
385 * Like on Windows, this function does not handle arguments with spaces
386 * or double-quotes.
388 int _spawnvpe(int flags, const char* name, const char* const* argv,
389 const char* const* envv)
391 char fullname[MAX_PATH];
392 _searchenv(name, "PATH", fullname);
393 return _spawnve(flags, fullname[0] ? fullname : name, argv, envv);
396 /*********************************************************************
397 * _spawnvp (MSVCRT.@)
399 * Like on Windows, this function does not handle arguments with spaces
400 * or double-quotes.
402 int _spawnvp(int flags, const char* name, const char* const* argv)
404 return _spawnvpe(flags, name, argv, NULL);
407 /*********************************************************************
408 * system (MSVCRT.@)
410 int MSVCRT_system(const char* cmd)
412 char* cmdcopy;
413 int res;
415 /* Make a writable copy for CreateProcess */
416 cmdcopy=_strdup(cmd);
417 /* FIXME: should probably launch cmd interpreter in COMSPEC */
418 res=msvcrt_spawn(_P_WAIT, NULL, cmdcopy, NULL);
419 MSVCRT_free(cmdcopy);
420 return res;
423 /*********************************************************************
424 * _loaddll (MSVCRT.@)
426 int _loaddll(const char* dllname)
428 return LoadLibraryA(dllname);
431 /*********************************************************************
432 * _unloaddll (MSVCRT.@)
434 int _unloaddll(int dll)
436 if (FreeLibrary((HANDLE)dll))
437 return 0;
438 else
440 int err = GetLastError();
441 MSVCRT__set_errno(err);
442 return err;