msvcrt: Use WINAPIV calling convention for variadic functions.
[wine.git] / dlls / msvcrt / process.c
blob1a183bc19b21374bec57046acc0bacbc82e380c7
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
8 * Copyright 2007 Hans Leidekker
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * FIXME:
25 * -File handles need some special handling. Sometimes children get
26 * open file handles, sometimes not. The docs are confusing
27 * -No check for maximum path/argument/environment size is done
29 #include "config.h"
31 #include <stdarg.h>
33 #include "msvcrt.h"
34 #include "mtdll.h"
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
40 static void msvcrt_search_executable(const MSVCRT_wchar_t *name, MSVCRT_wchar_t *fullname, int use_path)
42 static const MSVCRT_wchar_t path[] = {'P','A','T','H',0};
43 static const MSVCRT_wchar_t suffix[][5] =
44 {{'.','c','o','m',0}, {'.','e','x','e',0}, {'.','b','a','t',0}, {'.','c','m','d',0}};
46 MSVCRT_wchar_t buffer[MAX_PATH];
47 const MSVCRT_wchar_t *env, *p;
48 unsigned int i, name_len, path_len;
49 int extension = 1;
51 *fullname = '\0';
52 msvcrt_set_errno(ERROR_FILE_NOT_FOUND);
54 p = memchrW(name, '\0', MAX_PATH);
55 if (!p) p = name + MAX_PATH - 1;
56 name_len = p - name;
58 /* FIXME extra-long names are silently truncated */
59 memcpy(buffer, name, name_len * sizeof(MSVCRT_wchar_t));
60 buffer[name_len] = '\0';
62 /* try current dir first */
63 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
65 strcpyW(fullname, buffer);
66 return;
69 for (p--; p >= name; p--)
70 if (*p == '\\' || *p == '/' || *p == ':' || *p == '.') break;
72 /* if there's no extension, try some well-known extensions */
73 if ((p < name || *p != '.') && name_len <= MAX_PATH - 5)
75 for (i = 0; i < 4; i++)
77 memcpy(buffer + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t));
78 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
80 strcpyW(fullname, buffer);
81 return;
84 extension = 0;
87 if (!use_path || !(env = MSVCRT__wgetenv(path))) return;
89 /* now try search path */
92 p = env;
93 while (*p && *p != ';') p++;
94 if (p == env) return;
96 path_len = p - env;
97 if (path_len + name_len <= MAX_PATH - 2)
99 memcpy(buffer, env, path_len * sizeof(MSVCRT_wchar_t));
100 if (buffer[path_len] != '/' && buffer[path_len] != '\\')
102 buffer[path_len++] = '\\';
103 buffer[path_len] = '\0';
105 else buffer[path_len] = '\0';
107 strcatW(buffer, name);
108 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
110 strcpyW(fullname, buffer);
111 return;
114 /* again, if there's no extension, try some well-known extensions */
115 if (!extension && path_len + name_len <= MAX_PATH - 5)
117 for (i = 0; i < 4; i++)
119 memcpy(buffer + path_len + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t));
120 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
122 strcpyW(fullname, buffer);
123 return;
127 env = *p ? p + 1 : p;
128 } while(1);
131 static MSVCRT_intptr_t msvcrt_spawn(int flags, const MSVCRT_wchar_t* exe, MSVCRT_wchar_t* cmdline,
132 MSVCRT_wchar_t* env, int use_path)
134 STARTUPINFOW si;
135 PROCESS_INFORMATION pi;
136 MSVCRT_wchar_t fullname[MAX_PATH];
137 DWORD create_flags = CREATE_UNICODE_ENVIRONMENT;
139 TRACE("%x %s %s %s %d\n", flags, debugstr_w(exe), debugstr_w(cmdline), debugstr_w(env), use_path);
141 if ((unsigned)flags > MSVCRT__P_DETACH)
143 *MSVCRT__errno() = MSVCRT_EINVAL;
144 return -1;
147 msvcrt_search_executable(exe, fullname, use_path);
149 memset(&si, 0, sizeof(si));
150 si.cb = sizeof(si);
151 msvcrt_create_io_inherit_block(&si.cbReserved2, &si.lpReserved2);
152 if (flags == MSVCRT__P_DETACH) create_flags |= DETACHED_PROCESS;
153 if (!CreateProcessW(fullname, cmdline, NULL, NULL, TRUE,
154 create_flags, env, NULL, &si, &pi))
156 msvcrt_set_errno(GetLastError());
157 MSVCRT_free(si.lpReserved2);
158 return -1;
161 MSVCRT_free(si.lpReserved2);
162 switch(flags)
164 case MSVCRT__P_WAIT:
165 WaitForSingleObject(pi.hProcess, INFINITE);
166 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
167 CloseHandle(pi.hProcess);
168 CloseHandle(pi.hThread);
169 return pi.dwProcessId;
170 case MSVCRT__P_DETACH:
171 CloseHandle(pi.hProcess);
172 pi.hProcess = 0;
173 /* fall through */
174 case MSVCRT__P_NOWAIT:
175 case MSVCRT__P_NOWAITO:
176 CloseHandle(pi.hThread);
177 return (MSVCRT_intptr_t)pi.hProcess;
178 case MSVCRT__P_OVERLAY:
179 MSVCRT__exit(0);
181 return -1; /* can't reach here */
184 /* INTERNAL: Convert wide argv list to a single 'delim'-separated wide string, with an
185 * extra '\0' to terminate it.
187 static MSVCRT_wchar_t* msvcrt_argvtos(const MSVCRT_wchar_t* const* arg, MSVCRT_wchar_t delim)
189 const MSVCRT_wchar_t* const* a;
190 int size;
191 MSVCRT_wchar_t* p;
192 MSVCRT_wchar_t* ret;
194 if (!arg)
196 /* Return NULL for an empty environment list */
197 return NULL;
200 /* get length */
201 a = arg;
202 size = 0;
203 while (*a)
205 size += strlenW(*a) + 1;
206 a++;
209 ret = MSVCRT_malloc((size + 1) * sizeof(MSVCRT_wchar_t));
210 if (!ret)
211 return NULL;
213 /* fill string */
214 a = arg;
215 p = ret;
216 while (*a)
218 int len = strlenW(*a);
219 memcpy(p,*a,len * sizeof(MSVCRT_wchar_t));
220 p += len;
221 *p++ = delim;
222 a++;
224 if (delim && p > ret) p[-1] = 0;
225 else *p = 0;
226 return ret;
229 /* INTERNAL: Convert ansi argv list to a single 'delim'-separated wide string, with an
230 * extra '\0' to terminate it.
232 static MSVCRT_wchar_t *msvcrt_argvtos_aw(const char * const *arg, MSVCRT_wchar_t delim)
234 const char * const *a;
235 unsigned int len;
236 MSVCRT_wchar_t *p, *ret;
238 if (!arg)
240 /* Return NULL for an empty environment list */
241 return NULL;
244 /* get length */
245 a = arg;
246 len = 0;
247 while (*a)
249 len += MultiByteToWideChar(CP_ACP, 0, *a, -1, NULL, 0);
250 a++;
253 ret = MSVCRT_malloc((len + 1) * sizeof(MSVCRT_wchar_t));
254 if (!ret)
255 return NULL;
257 /* fill string */
258 a = arg;
259 p = ret;
260 while (*a)
262 p += MultiByteToWideChar(CP_ACP, 0, *a, strlen(*a), p, len - (p - ret));
263 *p++ = delim;
264 a++;
266 if (delim && p > ret) p[-1] = 0;
267 else *p = 0;
268 return ret;
271 /* INTERNAL: Convert wide va_list to a single 'delim'-separated wide string, with an
272 * extra '\0' to terminate it.
274 static MSVCRT_wchar_t *msvcrt_valisttos(const MSVCRT_wchar_t *arg0, __ms_va_list alist, MSVCRT_wchar_t delim)
276 unsigned int size = 0, pos = 0;
277 const MSVCRT_wchar_t *arg;
278 MSVCRT_wchar_t *new, *ret = NULL;
280 for (arg = arg0; arg; arg = va_arg( alist, MSVCRT_wchar_t * ))
282 unsigned int len = strlenW( arg ) + 1;
283 if (pos + len >= size)
285 size = max( 256, size * 2 );
286 size = max( size, pos + len + 1 );
287 if (!(new = MSVCRT_realloc( ret, size * sizeof(MSVCRT_wchar_t) )))
289 MSVCRT_free( ret );
290 return NULL;
292 ret = new;
294 strcpyW( ret + pos, arg );
295 pos += len;
296 ret[pos - 1] = delim;
298 if (pos)
300 if (delim) ret[pos - 1] = 0;
301 else ret[pos] = 0;
303 return ret;
306 /* INTERNAL: Convert ansi va_list to a single 'delim'-separated wide string, with an
307 * extra '\0' to terminate it.
309 static MSVCRT_wchar_t *msvcrt_valisttos_aw(const char *arg0, __ms_va_list alist, MSVCRT_wchar_t delim)
311 unsigned int size = 0, pos = 0;
312 const char *arg;
313 MSVCRT_wchar_t *new, *ret = NULL;
315 for (arg = arg0; arg; arg = va_arg( alist, char * ))
317 unsigned int len = MultiByteToWideChar( CP_ACP, 0, arg, -1, NULL, 0 );
318 if (pos + len >= size)
320 size = max( 256, size * 2 );
321 size = max( size, pos + len + 1 );
322 if (!(new = MSVCRT_realloc( ret, size * sizeof(MSVCRT_wchar_t) )))
324 MSVCRT_free( ret );
325 return NULL;
327 ret = new;
329 pos += MultiByteToWideChar( CP_ACP, 0, arg, -1, ret + pos, size - pos );
330 ret[pos - 1] = delim;
332 if (pos)
334 if (delim) ret[pos - 1] = 0;
335 else ret[pos] = 0;
337 return ret;
340 /* INTERNAL: retrieve COMSPEC environment variable */
341 static MSVCRT_wchar_t *msvcrt_get_comspec(void)
343 static const MSVCRT_wchar_t cmd[] = {'c','m','d',0};
344 static const MSVCRT_wchar_t comspec[] = {'C','O','M','S','P','E','C',0};
345 MSVCRT_wchar_t *ret;
346 unsigned int len;
348 if (!(len = GetEnvironmentVariableW(comspec, NULL, 0))) len = sizeof(cmd)/sizeof(MSVCRT_wchar_t);
349 if ((ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
351 if (!GetEnvironmentVariableW(comspec, ret, len)) strcpyW(ret, cmd);
353 return ret;
356 /*********************************************************************
357 * _cwait (MSVCRT.@)
359 MSVCRT_intptr_t CDECL _cwait(int *status, MSVCRT_intptr_t pid, int action)
361 HANDLE hPid = (HANDLE)pid;
362 int doserrno;
364 if (!WaitForSingleObject(hPid, INFINITE))
366 if (status)
368 DWORD stat;
369 GetExitCodeProcess(hPid, &stat);
370 *status = (int)stat;
372 return pid;
374 doserrno = GetLastError();
376 if (doserrno == ERROR_INVALID_HANDLE)
378 *MSVCRT__errno() = MSVCRT_ECHILD;
379 *MSVCRT___doserrno() = doserrno;
381 else
382 msvcrt_set_errno(doserrno);
384 return status ? *status = -1 : -1;
387 /*********************************************************************
388 * _wexecl (MSVCRT.@)
390 * Unicode version of _execl
392 MSVCRT_intptr_t WINAPIV _wexecl(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
394 __ms_va_list ap;
395 MSVCRT_wchar_t *args;
396 MSVCRT_intptr_t ret;
398 __ms_va_start(ap, arg0);
399 args = msvcrt_valisttos(arg0, ap, ' ');
400 __ms_va_end(ap);
402 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 0);
404 MSVCRT_free(args);
405 return ret;
408 /*********************************************************************
409 * _execl (MSVCRT.@)
411 * Like on Windows, this function does not handle arguments with spaces
412 * or double-quotes.
414 MSVCRT_intptr_t WINAPIV _execl(const char* name, const char* arg0, ...)
416 __ms_va_list ap;
417 MSVCRT_wchar_t *nameW, *args;
418 MSVCRT_intptr_t ret;
420 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
422 __ms_va_start(ap, arg0);
423 args = msvcrt_valisttos_aw(arg0, ap, ' ');
424 __ms_va_end(ap);
426 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 0);
428 MSVCRT_free(nameW);
429 MSVCRT_free(args);
430 return ret;
433 /*********************************************************************
434 * _wexecle (MSVCRT.@)
436 * Unicode version of _execle
438 MSVCRT_intptr_t WINAPIV _wexecle(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
440 __ms_va_list ap;
441 MSVCRT_wchar_t *args, *envs = NULL;
442 const MSVCRT_wchar_t * const *envp;
443 MSVCRT_intptr_t ret;
445 __ms_va_start(ap, arg0);
446 args = msvcrt_valisttos(arg0, ap, ' ');
447 __ms_va_end(ap);
449 __ms_va_start(ap, arg0);
450 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
451 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
452 if (envp) envs = msvcrt_argvtos(envp, 0);
453 __ms_va_end(ap);
455 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 0);
457 MSVCRT_free(args);
458 MSVCRT_free(envs);
459 return ret;
462 /*********************************************************************
463 * _execle (MSVCRT.@)
465 MSVCRT_intptr_t WINAPIV _execle(const char* name, const char* arg0, ...)
467 __ms_va_list ap;
468 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
469 const char * const *envp;
470 MSVCRT_intptr_t ret;
472 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
474 __ms_va_start(ap, arg0);
475 args = msvcrt_valisttos_aw(arg0, ap, ' ');
476 __ms_va_end(ap);
478 __ms_va_start(ap, arg0);
479 while (va_arg( ap, char * ) != NULL) /*nothing*/;
480 envp = va_arg( ap, const char * const * );
481 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
482 __ms_va_end(ap);
484 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 0);
486 MSVCRT_free(nameW);
487 MSVCRT_free(args);
488 MSVCRT_free(envs);
489 return ret;
492 /*********************************************************************
493 * _wexeclp (MSVCRT.@)
495 * Unicode version of _execlp
497 MSVCRT_intptr_t WINAPIV _wexeclp(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
499 __ms_va_list ap;
500 MSVCRT_wchar_t *args;
501 MSVCRT_intptr_t ret;
503 __ms_va_start(ap, arg0);
504 args = msvcrt_valisttos(arg0, ap, ' ');
505 __ms_va_end(ap);
507 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 1);
509 MSVCRT_free(args);
510 return ret;
513 /*********************************************************************
514 * _execlp (MSVCRT.@)
516 * Like on Windows, this function does not handle arguments with spaces
517 * or double-quotes.
519 MSVCRT_intptr_t WINAPIV _execlp(const char* name, const char* arg0, ...)
521 __ms_va_list ap;
522 MSVCRT_wchar_t *nameW, *args;
523 MSVCRT_intptr_t ret;
525 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
527 __ms_va_start(ap, arg0);
528 args = msvcrt_valisttos_aw(arg0, ap, ' ');
529 __ms_va_end(ap);
531 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 1);
533 MSVCRT_free(nameW);
534 MSVCRT_free(args);
535 return ret;
538 /*********************************************************************
539 * _wexeclpe (MSVCRT.@)
541 * Unicode version of _execlpe
543 MSVCRT_intptr_t WINAPIV _wexeclpe(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
545 __ms_va_list ap;
546 MSVCRT_wchar_t *args, *envs = NULL;
547 const MSVCRT_wchar_t * const *envp;
548 MSVCRT_intptr_t ret;
550 __ms_va_start(ap, arg0);
551 args = msvcrt_valisttos(arg0, ap, ' ');
552 __ms_va_end(ap);
554 __ms_va_start(ap, arg0);
555 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
556 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
557 if (envp) envs = msvcrt_argvtos(envp, 0);
558 __ms_va_end(ap);
560 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 1);
562 MSVCRT_free(args);
563 MSVCRT_free(envs);
564 return ret;
567 /*********************************************************************
568 * _execlpe (MSVCRT.@)
570 MSVCRT_intptr_t WINAPIV _execlpe(const char* name, const char* arg0, ...)
572 __ms_va_list ap;
573 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
574 const char * const *envp;
575 MSVCRT_intptr_t ret;
577 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
579 __ms_va_start(ap, arg0);
580 args = msvcrt_valisttos_aw(arg0, ap, ' ');
581 __ms_va_end(ap);
583 __ms_va_start(ap, arg0);
584 while (va_arg( ap, char * ) != NULL) /*nothing*/;
585 envp = va_arg( ap, const char * const * );
586 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
587 __ms_va_end(ap);
589 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 1);
591 MSVCRT_free(nameW);
592 MSVCRT_free(args);
593 MSVCRT_free(envs);
594 return ret;
597 /*********************************************************************
598 * _wexecv (MSVCRT.@)
600 * Unicode version of _execv
602 MSVCRT_intptr_t CDECL _wexecv(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
604 return MSVCRT__wspawnve(MSVCRT__P_OVERLAY, name, argv, NULL);
607 /*********************************************************************
608 * _execv (MSVCRT.@)
610 * Like on Windows, this function does not handle arguments with spaces
611 * or double-quotes.
613 MSVCRT_intptr_t CDECL _execv(const char* name, const char* const* argv)
615 return MSVCRT__spawnve(MSVCRT__P_OVERLAY, name, argv, NULL);
618 /*********************************************************************
619 * _wexecve (MSVCRT.@)
621 * Unicode version of _execve
623 MSVCRT_intptr_t CDECL _wexecve(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
625 return MSVCRT__wspawnve(MSVCRT__P_OVERLAY, name, argv, envv);
628 /*********************************************************************
629 * _execve (MSVCRT.@)
631 * Like on Windows, this function does not handle arguments with spaces
632 * or double-quotes.
634 MSVCRT_intptr_t CDECL MSVCRT__execve(const char* name, const char* const* argv, const char* const* envv)
636 return MSVCRT__spawnve(MSVCRT__P_OVERLAY, name, argv, envv);
639 /*********************************************************************
640 * _wexecvpe (MSVCRT.@)
642 * Unicode version of _execvpe
644 MSVCRT_intptr_t CDECL _wexecvpe(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
646 return MSVCRT__wspawnvpe(MSVCRT__P_OVERLAY, name, argv, envv);
649 /*********************************************************************
650 * _execvpe (MSVCRT.@)
652 * Like on Windows, this function does not handle arguments with spaces
653 * or double-quotes.
655 MSVCRT_intptr_t CDECL _execvpe(const char* name, const char* const* argv, const char* const* envv)
657 return MSVCRT__spawnvpe(MSVCRT__P_OVERLAY, name, argv, envv);
660 /*********************************************************************
661 * _wexecvp (MSVCRT.@)
663 * Unicode version of _execvp
665 MSVCRT_intptr_t CDECL _wexecvp(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
667 return _wexecvpe(name, argv, NULL);
670 /*********************************************************************
671 * _execvp (MSVCRT.@)
673 * Like on Windows, this function does not handle arguments with spaces
674 * or double-quotes.
676 MSVCRT_intptr_t CDECL _execvp(const char* name, const char* const* argv)
678 return _execvpe(name, argv, NULL);
681 /*********************************************************************
682 * _wspawnl (MSVCRT.@)
684 * Unicode version of _spawnl
686 MSVCRT_intptr_t WINAPIV _wspawnl(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
688 __ms_va_list ap;
689 MSVCRT_wchar_t *args;
690 MSVCRT_intptr_t ret;
692 __ms_va_start(ap, arg0);
693 args = msvcrt_valisttos(arg0, ap, ' ');
694 __ms_va_end(ap);
696 ret = msvcrt_spawn(flags, name, args, NULL, 0);
698 MSVCRT_free(args);
699 return ret;
702 /*********************************************************************
703 * _spawnl (MSVCRT.@)
705 * Like on Windows, this function does not handle arguments with spaces
706 * or double-quotes.
708 MSVCRT_intptr_t WINAPIV _spawnl(int flags, const char* name, const char* arg0, ...)
710 __ms_va_list ap;
711 MSVCRT_wchar_t *nameW, *args;
712 MSVCRT_intptr_t ret;
714 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
716 __ms_va_start(ap, arg0);
717 args = msvcrt_valisttos_aw(arg0, ap, ' ');
718 __ms_va_end(ap);
720 ret = msvcrt_spawn(flags, nameW, args, NULL, 0);
722 MSVCRT_free(nameW);
723 MSVCRT_free(args);
724 return ret;
727 /*********************************************************************
728 * _wspawnle (MSVCRT.@)
730 * Unicode version of _spawnle
732 MSVCRT_intptr_t WINAPIV _wspawnle(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
734 __ms_va_list ap;
735 MSVCRT_wchar_t *args, *envs = NULL;
736 const MSVCRT_wchar_t * const *envp;
737 MSVCRT_intptr_t ret;
739 __ms_va_start(ap, arg0);
740 args = msvcrt_valisttos(arg0, ap, ' ');
741 __ms_va_end(ap);
743 __ms_va_start(ap, arg0);
744 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
745 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
746 if (envp) envs = msvcrt_argvtos(envp, 0);
747 __ms_va_end(ap);
749 ret = msvcrt_spawn(flags, name, args, envs, 0);
751 MSVCRT_free(args);
752 MSVCRT_free(envs);
753 return ret;
756 /*********************************************************************
757 * _spawnle (MSVCRT.@)
759 MSVCRT_intptr_t WINAPIV _spawnle(int flags, const char* name, const char* arg0, ...)
761 __ms_va_list ap;
762 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
763 const char * const *envp;
764 MSVCRT_intptr_t ret;
766 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
768 __ms_va_start(ap, arg0);
769 args = msvcrt_valisttos_aw(arg0, ap, ' ');
770 __ms_va_end(ap);
772 __ms_va_start(ap, arg0);
773 while (va_arg( ap, char * ) != NULL) /*nothing*/;
774 envp = va_arg( ap, const char * const * );
775 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
776 __ms_va_end(ap);
778 ret = msvcrt_spawn(flags, nameW, args, envs, 0);
780 MSVCRT_free(nameW);
781 MSVCRT_free(args);
782 MSVCRT_free(envs);
783 return ret;
786 /*********************************************************************
787 * _wspawnlp (MSVCRT.@)
789 * Unicode version of _spawnlp
791 MSVCRT_intptr_t WINAPIV _wspawnlp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
793 __ms_va_list ap;
794 MSVCRT_wchar_t *args;
795 MSVCRT_intptr_t ret;
797 __ms_va_start(ap, arg0);
798 args = msvcrt_valisttos(arg0, ap, ' ');
799 __ms_va_end(ap);
801 ret = msvcrt_spawn(flags, name, args, NULL, 1);
803 MSVCRT_free(args);
804 return ret;
807 /*********************************************************************
808 * _spawnlp (MSVCRT.@)
810 * Like on Windows, this function does not handle arguments with spaces
811 * or double-quotes.
813 MSVCRT_intptr_t WINAPIV _spawnlp(int flags, const char* name, const char* arg0, ...)
815 __ms_va_list ap;
816 MSVCRT_wchar_t *nameW, *args;
817 MSVCRT_intptr_t ret;
819 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
821 __ms_va_start(ap, arg0);
822 args = msvcrt_valisttos_aw(arg0, ap, ' ');
823 __ms_va_end(ap);
825 ret = msvcrt_spawn(flags, nameW, args, NULL, 1);
827 MSVCRT_free(nameW);
828 MSVCRT_free(args);
829 return ret;
832 /*********************************************************************
833 * _wspawnlpe (MSVCRT.@)
835 * Unicode version of _spawnlpe
837 MSVCRT_intptr_t WINAPIV _wspawnlpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
839 __ms_va_list ap;
840 MSVCRT_wchar_t *args, *envs = NULL;
841 const MSVCRT_wchar_t * const *envp;
842 MSVCRT_intptr_t ret;
844 __ms_va_start(ap, arg0);
845 args = msvcrt_valisttos(arg0, ap, ' ');
846 __ms_va_end(ap);
848 __ms_va_start(ap, arg0);
849 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
850 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
851 if (envp) envs = msvcrt_argvtos(envp, 0);
852 __ms_va_end(ap);
854 ret = msvcrt_spawn(flags, name, args, envs, 1);
856 MSVCRT_free(args);
857 MSVCRT_free(envs);
858 return ret;
861 /*********************************************************************
862 * _spawnlpe (MSVCRT.@)
864 MSVCRT_intptr_t WINAPIV _spawnlpe(int flags, const char* name, const char* arg0, ...)
866 __ms_va_list ap;
867 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
868 const char * const *envp;
869 MSVCRT_intptr_t ret;
871 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
873 __ms_va_start(ap, arg0);
874 args = msvcrt_valisttos_aw(arg0, ap, ' ');
875 __ms_va_end(ap);
877 __ms_va_start(ap, arg0);
878 while (va_arg( ap, char * ) != NULL) /*nothing*/;
879 envp = va_arg( ap, const char * const * );
880 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
881 __ms_va_end(ap);
883 ret = msvcrt_spawn(flags, nameW, args, envs, 1);
885 MSVCRT_free(nameW);
886 MSVCRT_free(args);
887 MSVCRT_free(envs);
888 return ret;
891 /*********************************************************************
892 * _spawnve (MSVCRT.@)
894 * Like on Windows, this function does not handle arguments with spaces
895 * or double-quotes.
897 MSVCRT_intptr_t CDECL MSVCRT__spawnve(int flags, const char* name, const char* const* argv,
898 const char* const* envv)
900 MSVCRT_wchar_t *nameW, *args, *envs;
901 MSVCRT_intptr_t ret;
903 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
905 args = msvcrt_argvtos_aw(argv, ' ');
906 envs = msvcrt_argvtos_aw(envv, 0);
908 ret = msvcrt_spawn(flags, nameW, args, envs, 0);
910 MSVCRT_free(nameW);
911 MSVCRT_free(args);
912 MSVCRT_free(envs);
913 return ret;
916 /*********************************************************************
917 * _wspawnve (MSVCRT.@)
919 * Unicode version of _spawnve
921 MSVCRT_intptr_t CDECL MSVCRT__wspawnve(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
922 const MSVCRT_wchar_t* const* envv)
924 MSVCRT_wchar_t *args, *envs;
925 MSVCRT_intptr_t ret;
927 args = msvcrt_argvtos(argv, ' ');
928 envs = msvcrt_argvtos(envv, 0);
930 ret = msvcrt_spawn(flags, name, args, envs, 0);
932 MSVCRT_free(args);
933 MSVCRT_free(envs);
934 return ret;
937 /*********************************************************************
938 * _spawnv (MSVCRT.@)
940 * Like on Windows, this function does not handle arguments with spaces
941 * or double-quotes.
943 MSVCRT_intptr_t CDECL _spawnv(int flags, const char* name, const char* const* argv)
945 return MSVCRT__spawnve(flags, name, argv, NULL);
948 /*********************************************************************
949 * _wspawnv (MSVCRT.@)
951 * Unicode version of _spawnv
953 MSVCRT_intptr_t CDECL _wspawnv(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
955 return MSVCRT__wspawnve(flags, name, argv, NULL);
958 /*********************************************************************
959 * _spawnvpe (MSVCRT.@)
961 * Like on Windows, this function does not handle arguments with spaces
962 * or double-quotes.
964 MSVCRT_intptr_t CDECL MSVCRT__spawnvpe(int flags, const char* name, const char* const* argv,
965 const char* const* envv)
967 MSVCRT_wchar_t *nameW, *args, *envs;
968 MSVCRT_intptr_t ret;
970 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
972 args = msvcrt_argvtos_aw(argv, ' ');
973 envs = msvcrt_argvtos_aw(envv, 0);
975 ret = msvcrt_spawn(flags, nameW, args, envs, 1);
977 MSVCRT_free(nameW);
978 MSVCRT_free(args);
979 MSVCRT_free(envs);
980 return ret;
983 /*********************************************************************
984 * _wspawnvpe (MSVCRT.@)
986 * Unicode version of _spawnvpe
988 MSVCRT_intptr_t CDECL MSVCRT__wspawnvpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
989 const MSVCRT_wchar_t* const* envv)
991 MSVCRT_wchar_t *args, *envs;
992 MSVCRT_intptr_t ret;
994 args = msvcrt_argvtos(argv, ' ');
995 envs = msvcrt_argvtos(envv, 0);
997 ret = msvcrt_spawn(flags, name, args, envs, 1);
999 MSVCRT_free(args);
1000 MSVCRT_free(envs);
1001 return ret;
1004 /*********************************************************************
1005 * _spawnvp (MSVCRT.@)
1007 * Like on Windows, this function does not handle arguments with spaces
1008 * or double-quotes.
1010 MSVCRT_intptr_t CDECL _spawnvp(int flags, const char* name, const char* const* argv)
1012 return MSVCRT__spawnvpe(flags, name, argv, NULL);
1015 /*********************************************************************
1016 * _wspawnvp (MSVCRT.@)
1018 * Unicode version of _spawnvp
1020 MSVCRT_intptr_t CDECL _wspawnvp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
1022 return MSVCRT__wspawnvpe(flags, name, argv, NULL);
1025 static struct popen_handle {
1026 MSVCRT_FILE *f;
1027 HANDLE proc;
1028 } *popen_handles;
1029 static DWORD popen_handles_size;
1031 void msvcrt_free_popen_data(void)
1033 MSVCRT_free(popen_handles);
1036 /*********************************************************************
1037 * _wpopen (MSVCRT.@)
1039 * Unicode version of _popen
1041 MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wchar_t* mode)
1043 MSVCRT_FILE *ret;
1044 BOOL readPipe = TRUE;
1045 int textmode, fds[2], fdToDup, fdToOpen, fdStdHandle = -1;
1046 const MSVCRT_wchar_t *p;
1047 MSVCRT_wchar_t *comspec, *fullcmd;
1048 unsigned int len;
1049 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1050 struct popen_handle *container;
1051 DWORD i;
1053 TRACE("(command=%s, mode=%s)\n", debugstr_w(command), debugstr_w(mode));
1055 if (!command || !mode)
1056 return NULL;
1058 textmode = *__p__fmode() & (MSVCRT__O_BINARY | MSVCRT__O_TEXT);
1059 for (p = mode; *p; p++)
1061 switch (*p)
1063 case 'W':
1064 case 'w':
1065 readPipe = FALSE;
1066 break;
1067 case 'B':
1068 case 'b':
1069 textmode |= MSVCRT__O_BINARY;
1070 textmode &= ~MSVCRT__O_TEXT;
1071 break;
1072 case 'T':
1073 case 't':
1074 textmode |= MSVCRT__O_TEXT;
1075 textmode &= ~MSVCRT__O_BINARY;
1076 break;
1079 if (MSVCRT__pipe(fds, 0, textmode) == -1)
1080 return NULL;
1082 fdToDup = readPipe ? 1 : 0;
1083 fdToOpen = readPipe ? 0 : 1;
1085 _mlock(_POPEN_LOCK);
1086 for(i=0; i<popen_handles_size; i++)
1088 if (!popen_handles[i].f)
1089 break;
1091 if (i==popen_handles_size)
1093 i = (popen_handles_size ? popen_handles_size*2 : 8);
1094 container = MSVCRT_realloc(popen_handles, i*sizeof(*container));
1095 if (!container) goto error;
1097 popen_handles = container;
1098 container = popen_handles+popen_handles_size;
1099 memset(container, 0, (i-popen_handles_size)*sizeof(*container));
1100 popen_handles_size = i;
1102 else container = popen_handles+i;
1104 if ((fdStdHandle = MSVCRT__dup(fdToDup)) == -1)
1105 goto error;
1106 if (MSVCRT__dup2(fds[fdToDup], fdToDup) != 0)
1107 goto error;
1109 MSVCRT__close(fds[fdToDup]);
1111 if (!(comspec = msvcrt_get_comspec())) goto error;
1112 len = strlenW(comspec) + strlenW(flag) + strlenW(command) + 1;
1114 if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
1116 HeapFree(GetProcessHeap(), 0, comspec);
1117 goto error;
1120 strcpyW(fullcmd, comspec);
1121 strcatW(fullcmd, flag);
1122 strcatW(fullcmd, command);
1124 if ((container->proc = (HANDLE)msvcrt_spawn(MSVCRT__P_NOWAIT, comspec, fullcmd, NULL, 1))
1125 == INVALID_HANDLE_VALUE)
1127 MSVCRT__close(fds[fdToOpen]);
1128 ret = NULL;
1130 else
1132 ret = MSVCRT__wfdopen(fds[fdToOpen], mode);
1133 if (!ret)
1134 MSVCRT__close(fds[fdToOpen]);
1135 container->f = ret;
1137 _munlock(_POPEN_LOCK);
1138 HeapFree(GetProcessHeap(), 0, comspec);
1139 HeapFree(GetProcessHeap(), 0, fullcmd);
1140 MSVCRT__dup2(fdStdHandle, fdToDup);
1141 MSVCRT__close(fdStdHandle);
1142 return ret;
1144 error:
1145 _munlock(_POPEN_LOCK);
1146 if (fdStdHandle != -1) MSVCRT__close(fdStdHandle);
1147 MSVCRT__close(fds[0]);
1148 MSVCRT__close(fds[1]);
1149 return NULL;
1152 /*********************************************************************
1153 * _popen (MSVCRT.@)
1155 MSVCRT_FILE* CDECL MSVCRT__popen(const char* command, const char* mode)
1157 MSVCRT_FILE *ret;
1158 MSVCRT_wchar_t *cmdW, *modeW;
1160 TRACE("(command=%s, mode=%s)\n", debugstr_a(command), debugstr_a(mode));
1162 if (!command || !mode)
1163 return NULL;
1165 if (!(cmdW = msvcrt_wstrdupa(command))) return NULL;
1166 if (!(modeW = msvcrt_wstrdupa(mode)))
1168 HeapFree(GetProcessHeap(), 0, cmdW);
1169 return NULL;
1172 ret = MSVCRT__wpopen(cmdW, modeW);
1174 HeapFree(GetProcessHeap(), 0, cmdW);
1175 HeapFree(GetProcessHeap(), 0, modeW);
1176 return ret;
1179 /*********************************************************************
1180 * _pclose (MSVCRT.@)
1182 int CDECL MSVCRT__pclose(MSVCRT_FILE* file)
1184 HANDLE h;
1185 DWORD i;
1187 if (!MSVCRT_CHECK_PMT(file != NULL)) return -1;
1189 _mlock(_POPEN_LOCK);
1190 for(i=0; i<popen_handles_size; i++)
1192 if (popen_handles[i].f == file)
1193 break;
1195 if(i == popen_handles_size)
1197 _munlock(_POPEN_LOCK);
1198 *MSVCRT__errno() = MSVCRT_EBADF;
1199 return -1;
1202 h = popen_handles[i].proc;
1203 popen_handles[i].f = NULL;
1204 _munlock(_POPEN_LOCK);
1206 MSVCRT_fclose(file);
1207 if(WaitForSingleObject(h, INFINITE)==WAIT_FAILED || !GetExitCodeProcess(h, &i))
1209 msvcrt_set_errno(GetLastError());
1210 CloseHandle(h);
1211 return -1;
1214 CloseHandle(h);
1215 return i;
1218 /*********************************************************************
1219 * _wsystem (MSVCRT.@)
1221 * Unicode version of system
1223 int CDECL _wsystem(const MSVCRT_wchar_t* cmd)
1225 int res;
1226 MSVCRT_wchar_t *comspec, *fullcmd;
1227 unsigned int len;
1228 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1230 comspec = msvcrt_get_comspec();
1232 if (cmd == NULL)
1234 if (comspec == NULL)
1236 *MSVCRT__errno() = MSVCRT_ENOENT;
1237 return 0;
1239 HeapFree(GetProcessHeap(), 0, comspec);
1240 return 1;
1243 if ( comspec == NULL)
1244 return -1;
1246 len = strlenW(comspec) + strlenW(flag) + strlenW(cmd) + 1;
1248 if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
1250 HeapFree(GetProcessHeap(), 0, comspec);
1251 return -1;
1253 strcpyW(fullcmd, comspec);
1254 strcatW(fullcmd, flag);
1255 strcatW(fullcmd, cmd);
1257 res = msvcrt_spawn(MSVCRT__P_WAIT, comspec, fullcmd, NULL, 1);
1259 HeapFree(GetProcessHeap(), 0, comspec);
1260 HeapFree(GetProcessHeap(), 0, fullcmd);
1261 return res;
1264 /*********************************************************************
1265 * system (MSVCRT.@)
1267 int CDECL MSVCRT_system(const char* cmd)
1269 int res = -1;
1270 MSVCRT_wchar_t *cmdW;
1272 if (cmd == NULL)
1273 return _wsystem(NULL);
1275 if ((cmdW = msvcrt_wstrdupa(cmd)))
1277 res = _wsystem(cmdW);
1278 HeapFree(GetProcessHeap(), 0, cmdW);
1280 return res;
1283 /*********************************************************************
1284 * _loaddll (MSVCRT.@)
1286 MSVCRT_intptr_t CDECL _loaddll(const char* dllname)
1288 return (MSVCRT_intptr_t)LoadLibraryA(dllname);
1291 /*********************************************************************
1292 * _unloaddll (MSVCRT.@)
1294 int CDECL _unloaddll(MSVCRT_intptr_t dll)
1296 if (FreeLibrary((HMODULE)dll))
1297 return 0;
1298 else
1300 int err = GetLastError();
1301 msvcrt_set_errno(err);
1302 return err;
1306 /*********************************************************************
1307 * _getdllprocaddr (MSVCRT.@)
1309 void * CDECL _getdllprocaddr(MSVCRT_intptr_t dll, const char *name, int ordinal)
1311 if (name)
1313 if (ordinal != -1) return NULL;
1314 return GetProcAddress( (HMODULE)dll, name );
1316 if (HIWORD(ordinal)) return NULL;
1317 return GetProcAddress( (HMODULE)dll, (LPCSTR)(ULONG_PTR)ordinal );
1320 /*********************************************************************
1321 * _getpid (MSVCRT.@)
1323 int CDECL _getpid(void)
1325 return GetCurrentProcessId();
1328 /*********************************************************************
1329 * __crtTerminateProcess (MSVCR110.@)
1331 int CDECL MSVCR110__crtTerminateProcess(UINT exit_code)
1333 return TerminateProcess(GetCurrentProcess(), exit_code);