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 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * -File handles need some special handling. Sometimes children get
25 * open file handles, sometimes not. The docs are confusing
26 * -No check for maximum path/argument/environment size is done
33 #include "msvcrt/errno.h"
35 #include "msvcrt/process.h"
36 #include "msvcrt/stdlib.h"
37 #include "msvcrt/string.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
43 /* FIXME: Check file extensions for app to run */
44 static const unsigned int EXE
= 'e' << 16 | 'x' << 8 | 'e';
45 static const unsigned int BAT
= 'b' << 16 | 'a' << 8 | 't';
46 static const unsigned int CMD
= 'c' << 16 | 'm' << 8 | 'd';
47 static const unsigned int COM
= 'c' << 16 | 'o' << 8 | 'm';
49 /* INTERNAL: Spawn a child process */
50 static int msvcrt_spawn(int flags
, const char* exe
, char* cmdline
, char* env
)
53 PROCESS_INFORMATION pi
;
55 if (sizeof(HANDLE
) != sizeof(int))
56 WARN("This call is unsuitable for your architecture\n");
58 if ((unsigned)flags
> _P_DETACH
)
60 *MSVCRT__errno() = MSVCRT_EINVAL
;
64 FIXME(":must dup/kill streams for child process\n");
66 memset(&si
, 0, sizeof(si
));
69 if (!CreateProcessA(exe
, cmdline
, NULL
, NULL
, TRUE
,
70 flags
== _P_DETACH
? DETACHED_PROCESS
: 0,
73 MSVCRT__set_errno(GetLastError());
80 WaitForSingleObject(pi
.hProcess
,-1); /* wait forvever */
81 GetExitCodeProcess(pi
.hProcess
,&pi
.dwProcessId
);
82 CloseHandle(pi
.hProcess
);
83 CloseHandle(pi
.hThread
);
84 return (int)pi
.dwProcessId
;
86 CloseHandle(pi
.hProcess
);
91 CloseHandle(pi
.hThread
);
92 return (int)pi
.hProcess
;
96 return -1; /* can't reach here */
99 /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
100 * extra '\0' to terminate it
102 static char* msvcrt_argvtos(const char* const* arg
, char delim
)
104 const char* const* a
;
111 /* Return NULL for an empty environment list */
120 size
+= strlen(*a
) + 1;
124 ret
= (char*)MSVCRT_malloc(size
+ 1);
133 int len
= strlen(*a
);
139 if (delim
&& p
> ret
) p
[-1] = 0;
144 /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
145 * extra '\0' to terminate it
147 static char* msvcrt_valisttos(const char* arg0
, va_list alist
, char delim
)
156 va_copy(alist2
,alist
);
159 __va_copy(alist2
,alist
);
167 /* Return NULL for an empty environment list */
175 size
+= strlen(arg
) + 1;
176 arg
= va_arg(alist
, char*);
177 } while (arg
!= NULL
);
179 ret
= (char*)MSVCRT_malloc(size
+ 1);
187 int len
= strlen(arg
);
191 arg
= va_arg(alist2
, char*);
192 } while (arg
!= NULL
);
193 if (delim
&& p
> ret
) p
[-1] = 0;
198 /*********************************************************************
201 int _cwait(int *status
, int pid
, int action
)
203 HANDLE hPid
= (HANDLE
)pid
;
206 action
= action
; /* Remove warning */
208 if (!WaitForSingleObject(hPid
, -1)) /* wait forever */
213 GetExitCodeProcess(hPid
, &stat
);
218 doserrno
= GetLastError();
220 if (doserrno
== ERROR_INVALID_HANDLE
)
222 *MSVCRT__errno() = MSVCRT_ECHILD
;
223 *__doserrno() = doserrno
;
226 MSVCRT__set_errno(doserrno
);
228 return status
? *status
= -1 : -1;
231 /*********************************************************************
234 * Like on Windows, this function does not handle arguments with spaces
237 int _execl(const char* name
, const char* arg0
, ...)
244 args
= msvcrt_valisttos(arg0
, ap
, ' ');
247 ret
= msvcrt_spawn(_P_OVERLAY
, name
, args
, NULL
);
253 /*********************************************************************
256 * Like on Windows, this function does not handle arguments with spaces
259 int _execlp(const char* name
, const char* arg0
, ...)
264 char fullname
[MAX_PATH
];
266 _searchenv(name
, "PATH", fullname
);
269 args
= msvcrt_valisttos(arg0
, ap
, ' ');
272 ret
= msvcrt_spawn(_P_OVERLAY
, fullname
[0] ? fullname
: name
, args
, NULL
);
278 /*********************************************************************
281 * Like on Windows, this function does not handle arguments with spaces
284 int _execv(const char* name
, char* const* argv
)
286 return _spawnve(_P_OVERLAY
, name
, (const char* const*) argv
, NULL
);
289 /*********************************************************************
292 * Like on Windows, this function does not handle arguments with spaces
295 int _execve(const char* name
, char* const* argv
, const char* const* envv
)
297 return _spawnve(_P_OVERLAY
, name
, (const char* const*) argv
, envv
);
300 /*********************************************************************
301 * _execvpe (MSVCRT.@)
303 * Like on Windows, this function does not handle arguments with spaces
306 int _execvpe(const char* name
, char* const* argv
, const char* const* envv
)
308 char fullname
[MAX_PATH
];
310 _searchenv(name
, "PATH", fullname
);
311 return _spawnve(_P_OVERLAY
, fullname
[0] ? fullname
: name
,
312 (const char* const*) argv
, envv
);
315 /*********************************************************************
318 * Like on Windows, this function does not handle arguments with spaces
321 int _execvp(const char* name
, char* const* argv
)
323 return _execvpe(name
, argv
, NULL
);
326 /*********************************************************************
329 * Like on Windows, this function does not handle arguments with spaces
332 int _spawnl(int flags
, const char* name
, const char* arg0
, ...)
339 args
= msvcrt_valisttos(arg0
, ap
, ' ');
342 ret
= msvcrt_spawn(flags
, name
, args
, NULL
);
348 /*********************************************************************
349 * _spawnlp (MSVCRT.@)
351 * Like on Windows, this function does not handle arguments with spaces
354 int _spawnlp(int flags
, const char* name
, const char* arg0
, ...)
359 char fullname
[MAX_PATH
];
361 _searchenv(name
, "PATH", fullname
);
364 args
= msvcrt_valisttos(arg0
, ap
, ' ');
367 ret
= msvcrt_spawn(flags
, fullname
[0] ? fullname
: name
, args
, NULL
);
373 /*********************************************************************
374 * _spawnve (MSVCRT.@)
376 * Like on Windows, this function does not handle arguments with spaces
379 int _spawnve(int flags
, const char* name
, const char* const* argv
,
380 const char* const* envv
)
382 char * args
= msvcrt_argvtos(argv
,' ');
383 char * envs
= msvcrt_argvtos(envv
,0);
384 const char *fullname
= name
;
387 FIXME(":not translating name %s to locate program\n",fullname
);
388 TRACE(":call (%s), params (%s), env (%s)\n",name
,args
,envs
?"Custom":"Null");
392 ret
= msvcrt_spawn(flags
, fullname
, args
, envs
);
401 /*********************************************************************
404 * Like on Windows, this function does not handle arguments with spaces
407 int _spawnv(int flags
, const char* name
, const char* const* argv
)
409 return _spawnve(flags
, name
, argv
, NULL
);
412 /*********************************************************************
413 * _spawnvpe (MSVCRT.@)
415 * Like on Windows, this function does not handle arguments with spaces
418 int _spawnvpe(int flags
, const char* name
, const char* const* argv
,
419 const char* const* envv
)
421 char fullname
[MAX_PATH
];
422 _searchenv(name
, "PATH", fullname
);
423 return _spawnve(flags
, fullname
[0] ? fullname
: name
, argv
, envv
);
426 /*********************************************************************
427 * _spawnvp (MSVCRT.@)
429 * Like on Windows, this function does not handle arguments with spaces
432 int _spawnvp(int flags
, const char* name
, const char* const* argv
)
434 return _spawnvpe(flags
, name
, argv
, NULL
);
437 /*********************************************************************
440 int MSVCRT_system(const char* cmd
)
445 /* Make a writable copy for CreateProcess */
446 cmdcopy
=_strdup(cmd
);
447 /* FIXME: should probably launch cmd interpreter in COMSPEC */
448 res
=msvcrt_spawn(_P_WAIT
, NULL
, cmdcopy
, NULL
);
449 MSVCRT_free(cmdcopy
);
453 /*********************************************************************
454 * _loaddll (MSVCRT.@)
456 int _loaddll(const char* dllname
)
458 return (int)LoadLibraryA(dllname
);
461 /*********************************************************************
462 * _unloaddll (MSVCRT.@)
464 int _unloaddll(int dll
)
466 if (FreeLibrary((HMODULE
)dll
))
470 int err
= GetLastError();
471 MSVCRT__set_errno(err
);
476 /*********************************************************************
477 * _getdllprocaddr (MSVCRT.@)
479 void *_getdllprocaddr(int dll
, const char *name
, int ordinal
)
483 if (ordinal
!= -1) return NULL
;
484 return GetProcAddress( (HMODULE
)dll
, name
);
486 if (HIWORD(ordinal
)) return NULL
;
487 return GetProcAddress( (HMODULE
)dll
, (LPCSTR
)(ULONG_PTR
)ordinal
);