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
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
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
39 static void msvcrt_search_executable(const MSVCRT_wchar_t *name, MSVCRT_wchar_t *fullname, int use_path)
41 static const MSVCRT_wchar_t path[] = {'P','A','T','H',0};
42 static const MSVCRT_wchar_t suffix[][5] =
43 {{'.','c','o','m',0}, {'.','e','x','e',0}, {'.','b','a','t',0}, {'.','c','m','d',0}};
45 MSVCRT_wchar_t buffer[MAX_PATH];
46 const MSVCRT_wchar_t *env, *p;
47 unsigned int i, name_len, path_len;
51 msvcrt_set_errno(ERROR_FILE_NOT_FOUND);
53 p = memchrW(name, '\0', MAX_PATH);
54 if (!p) p = name + MAX_PATH - 1;
57 /* FIXME extra-long names are silently truncated */
58 memcpy(buffer, name, name_len * sizeof(MSVCRT_wchar_t));
59 buffer[name_len] = '\0';
61 /* try current dir first */
62 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
64 strcpyW(fullname, buffer);
68 for (p--; p >= name; p--)
69 if (*p == '\\' || *p == '/' || *p == ':' || *p == '.') break;
71 /* if there's no extension, try some well-known extensions */
72 if ((p < name || *p != '.') && name_len <= MAX_PATH - 5)
74 for (i = 0; i < 4; i++)
76 memcpy(buffer + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t));
77 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
79 strcpyW(fullname, buffer);
86 if (!use_path || !(env = _wgetenv(path))) return;
88 /* now try search path */
92 while (*p && *p != ';') p++;
96 if (path_len + name_len <= MAX_PATH - 2)
98 memcpy(buffer, env, path_len * sizeof(MSVCRT_wchar_t));
99 if (buffer[path_len] != '/' && buffer[path_len] != '\\')
101 buffer[path_len++] = '\\';
102 buffer[path_len] = '\0';
104 else buffer[path_len] = '\0';
106 strcatW(buffer, name);
107 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
109 strcpyW(fullname, buffer);
113 /* again, if there's no extension, try some well-known extensions */
114 if (!extension && path_len + name_len <= MAX_PATH - 5)
116 for (i = 0; i < 4; i++)
118 memcpy(buffer + path_len + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t));
119 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
121 strcpyW(fullname, buffer);
126 env = *p ? p + 1 : p;
130 static MSVCRT_intptr_t msvcrt_spawn(int flags, const MSVCRT_wchar_t* exe, MSVCRT_wchar_t* cmdline,
131 MSVCRT_wchar_t* env, int use_path)
134 PROCESS_INFORMATION pi;
135 MSVCRT_wchar_t fullname[MAX_PATH];
137 TRACE("%x %s %s %s %d\n", flags, debugstr_w(exe), debugstr_w(cmdline), debugstr_w(env), use_path);
139 if ((unsigned)flags > MSVCRT__P_DETACH)
141 *MSVCRT__errno() = MSVCRT_EINVAL;
145 msvcrt_search_executable(exe, fullname, use_path);
147 memset(&si, 0, sizeof(si));
149 msvcrt_create_io_inherit_block(&si.cbReserved2, &si.lpReserved2);
150 if (!CreateProcessW(fullname, cmdline, NULL, NULL, TRUE,
151 flags == MSVCRT__P_DETACH ? DETACHED_PROCESS : 0,
152 env, NULL, &si, &pi))
154 msvcrt_set_errno(GetLastError());
155 MSVCRT_free(si.lpReserved2);
159 MSVCRT_free(si.lpReserved2);
163 WaitForSingleObject(pi.hProcess, INFINITE);
164 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
165 CloseHandle(pi.hProcess);
166 CloseHandle(pi.hThread);
167 return pi.dwProcessId;
168 case MSVCRT__P_DETACH:
169 CloseHandle(pi.hProcess);
172 case MSVCRT__P_NOWAIT:
173 case MSVCRT__P_NOWAITO:
174 CloseHandle(pi.hThread);
175 return (MSVCRT_intptr_t)pi.hProcess;
176 case MSVCRT__P_OVERLAY:
179 return -1; /* can't reach here */
182 /* INTERNAL: Convert wide argv list to a single 'delim'-separated wide string, with an
183 * extra '\0' to terminate it.
185 static MSVCRT_wchar_t* msvcrt_argvtos(const MSVCRT_wchar_t* const* arg, MSVCRT_wchar_t delim)
187 const MSVCRT_wchar_t* const* a;
194 /* Return NULL for an empty environment list */
203 size += strlenW(*a) + 1;
207 ret = MSVCRT_malloc((size + 1) * sizeof(MSVCRT_wchar_t));
216 int len = strlenW(*a);
217 memcpy(p,*a,len * sizeof(MSVCRT_wchar_t));
222 if (delim && p > ret) p[-1] = 0;
227 /* INTERNAL: Convert ansi argv list to a single 'delim'-separated wide string, with an
228 * extra '\0' to terminate it.
230 static MSVCRT_wchar_t *msvcrt_argvtos_aw(const char * const *arg, MSVCRT_wchar_t delim)
232 const char * const *a;
234 MSVCRT_wchar_t *p, *ret;
238 /* Return NULL for an empty environment list */
247 len += MultiByteToWideChar(CP_ACP, 0, *a, -1, NULL, 0);
251 ret = MSVCRT_malloc((len + 1) * sizeof(MSVCRT_wchar_t));
260 p += MultiByteToWideChar(CP_ACP, 0, *a, strlen(*a), p, len - (p - ret));
264 if (delim && p > ret) p[-1] = 0;
269 /* INTERNAL: Convert wide va_list to a single 'delim'-separated wide string, with an
270 * extra '\0' to terminate it.
272 static MSVCRT_wchar_t *msvcrt_valisttos(const MSVCRT_wchar_t *arg0, __ms_va_list alist, MSVCRT_wchar_t delim)
274 unsigned int size = 0, pos = 0;
275 const MSVCRT_wchar_t *arg;
276 MSVCRT_wchar_t *new, *ret = NULL;
278 for (arg = arg0; arg; arg = va_arg( alist, MSVCRT_wchar_t * ))
280 unsigned int len = strlenW( arg ) + 1;
281 if (pos + len >= size)
283 size = max( 256, size * 2 );
284 size = max( size, pos + len + 1 );
285 if (!(new = MSVCRT_realloc( ret, size * sizeof(MSVCRT_wchar_t) )))
292 strcpyW( ret + pos, arg );
294 ret[pos - 1] = delim;
298 if (delim) ret[pos - 1] = 0;
304 /* INTERNAL: Convert ansi va_list to a single 'delim'-separated wide string, with an
305 * extra '\0' to terminate it.
307 static MSVCRT_wchar_t *msvcrt_valisttos_aw(const char *arg0, __ms_va_list alist, MSVCRT_wchar_t delim)
309 unsigned int size = 0, pos = 0;
311 MSVCRT_wchar_t *new, *ret = NULL;
313 for (arg = arg0; arg; arg = va_arg( alist, char * ))
315 unsigned int len = MultiByteToWideChar( CP_ACP, 0, arg, -1, NULL, 0 );
316 if (pos + len >= size)
318 size = max( 256, size * 2 );
319 size = max( size, pos + len + 1 );
320 if (!(new = MSVCRT_realloc( ret, size * sizeof(MSVCRT_wchar_t) )))
327 pos += MultiByteToWideChar( CP_ACP, 0, arg, -1, ret + pos, size - pos );
328 ret[pos - 1] = delim;
332 if (delim) ret[pos - 1] = 0;
338 /* INTERNAL: retrieve COMSPEC environment variable */
339 static MSVCRT_wchar_t *msvcrt_get_comspec(void)
341 static const MSVCRT_wchar_t cmd[] = {'c','m','d',0};
342 static const MSVCRT_wchar_t comspec[] = {'C','O','M','S','P','E','C',0};
346 if (!(len = GetEnvironmentVariableW(comspec, NULL, 0))) len = sizeof(cmd)/sizeof(MSVCRT_wchar_t);
347 if ((ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
349 if (!GetEnvironmentVariableW(comspec, ret, len)) strcpyW(ret, cmd);
354 /*********************************************************************
357 MSVCRT_intptr_t CDECL _cwait(int *status, MSVCRT_intptr_t pid, int action)
359 HANDLE hPid = (HANDLE)pid;
362 action = action; /* Remove warning */
364 if (!WaitForSingleObject(hPid, INFINITE))
369 GetExitCodeProcess(hPid, &stat);
374 doserrno = GetLastError();
376 if (doserrno == ERROR_INVALID_HANDLE)
378 *MSVCRT__errno() = MSVCRT_ECHILD;
379 *MSVCRT___doserrno() = doserrno;
382 msvcrt_set_errno(doserrno);
384 return status ? *status = -1 : -1;
387 /*********************************************************************
390 * Unicode version of _execl
392 MSVCRT_intptr_t CDECL _wexecl(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
395 MSVCRT_wchar_t *args;
398 __ms_va_start(ap, arg0);
399 args = msvcrt_valisttos(arg0, ap, ' ');
402 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 0);
408 /*********************************************************************
411 * Like on Windows, this function does not handle arguments with spaces
414 MSVCRT_intptr_t CDECL _execl(const char* name, const char* arg0, ...)
417 MSVCRT_wchar_t *nameW, *args;
420 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
422 __ms_va_start(ap, arg0);
423 args = msvcrt_valisttos_aw(arg0, ap, ' ');
426 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 0);
433 /*********************************************************************
434 * _wexecle (MSVCRT.@)
436 * Unicode version of _execle
438 MSVCRT_intptr_t CDECL _wexecle(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
441 MSVCRT_wchar_t *args, *envs = NULL;
442 const MSVCRT_wchar_t * const *envp;
445 __ms_va_start(ap, arg0);
446 args = msvcrt_valisttos(arg0, 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);
455 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 0);
462 /*********************************************************************
465 MSVCRT_intptr_t CDECL _execle(const char* name, const char* arg0, ...)
468 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
469 const char * const *envp;
472 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
474 __ms_va_start(ap, arg0);
475 args = msvcrt_valisttos_aw(arg0, 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);
484 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 0);
492 /*********************************************************************
493 * _wexeclp (MSVCRT.@)
495 * Unicode version of _execlp
497 MSVCRT_intptr_t CDECL _wexeclp(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
500 MSVCRT_wchar_t *args;
503 __ms_va_start(ap, arg0);
504 args = msvcrt_valisttos(arg0, ap, ' ');
507 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 1);
513 /*********************************************************************
516 * Like on Windows, this function does not handle arguments with spaces
519 MSVCRT_intptr_t CDECL _execlp(const char* name, const char* arg0, ...)
522 MSVCRT_wchar_t *nameW, *args;
525 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
527 __ms_va_start(ap, arg0);
528 args = msvcrt_valisttos_aw(arg0, ap, ' ');
531 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 1);
538 /*********************************************************************
539 * _wexeclpe (MSVCRT.@)
541 * Unicode version of _execlpe
543 MSVCRT_intptr_t CDECL _wexeclpe(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
546 MSVCRT_wchar_t *args, *envs = NULL;
547 const MSVCRT_wchar_t * const *envp;
550 __ms_va_start(ap, arg0);
551 args = msvcrt_valisttos(arg0, 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);
560 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 1);
567 /*********************************************************************
568 * _execlpe (MSVCRT.@)
570 MSVCRT_intptr_t CDECL _execlpe(const char* name, const char* arg0, ...)
573 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
574 const char * const *envp;
577 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
579 __ms_va_start(ap, arg0);
580 args = msvcrt_valisttos_aw(arg0, 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);
589 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 1);
597 /*********************************************************************
600 * Unicode version of _execv
602 MSVCRT_intptr_t CDECL _wexecv(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv)
604 return _wspawnve(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, NULL);
607 /*********************************************************************
610 * Like on Windows, this function does not handle arguments with spaces
613 MSVCRT_intptr_t CDECL _execv(const char* name, char* const* argv)
615 return MSVCRT__spawnve(MSVCRT__P_OVERLAY, name, (const char* const*) argv, NULL);
618 /*********************************************************************
619 * _wexecve (MSVCRT.@)
621 * Unicode version of _execve
623 MSVCRT_intptr_t CDECL _wexecve(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
625 return _wspawnve(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, envv);
628 /*********************************************************************
631 * Like on Windows, this function does not handle arguments with spaces
634 MSVCRT_intptr_t CDECL MSVCRT__execve(const char* name, char* const* argv, const char* const* envv)
636 return MSVCRT__spawnve(MSVCRT__P_OVERLAY, name, (const char* const*) argv, envv);
639 /*********************************************************************
640 * _wexecvpe (MSVCRT.@)
642 * Unicode version of _execvpe
644 MSVCRT_intptr_t CDECL _wexecvpe(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
646 return _wspawnvpe(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, envv);
649 /*********************************************************************
650 * _execvpe (MSVCRT.@)
652 * Like on Windows, this function does not handle arguments with spaces
655 MSVCRT_intptr_t CDECL _execvpe(const char* name, char* const* argv, const char* const* envv)
657 return MSVCRT__spawnvpe(MSVCRT__P_OVERLAY, name, (const char* const*) argv, envv);
660 /*********************************************************************
661 * _wexecvp (MSVCRT.@)
663 * Unicode version of _execvp
665 MSVCRT_intptr_t CDECL _wexecvp(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv)
667 return _wexecvpe(name, argv, NULL);
670 /*********************************************************************
673 * Like on Windows, this function does not handle arguments with spaces
676 MSVCRT_intptr_t CDECL _execvp(const char* name, char* const* argv)
678 return _execvpe(name, argv, NULL);
681 /*********************************************************************
682 * _wspawnl (MSVCRT.@)
684 * Unicode version of _spawnl
686 MSVCRT_intptr_t CDECL _wspawnl(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
689 MSVCRT_wchar_t *args;
692 __ms_va_start(ap, arg0);
693 args = msvcrt_valisttos(arg0, ap, ' ');
696 ret = msvcrt_spawn(flags, name, args, NULL, 0);
702 /*********************************************************************
705 * Like on Windows, this function does not handle arguments with spaces
708 MSVCRT_intptr_t CDECL _spawnl(int flags, const char* name, const char* arg0, ...)
711 MSVCRT_wchar_t *nameW, *args;
714 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
716 __ms_va_start(ap, arg0);
717 args = msvcrt_valisttos_aw(arg0, ap, ' ');
720 ret = msvcrt_spawn(flags, nameW, args, NULL, 0);
727 /*********************************************************************
728 * _wspawnle (MSVCRT.@)
730 * Unicode version of _spawnle
732 MSVCRT_intptr_t CDECL _wspawnle(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
735 MSVCRT_wchar_t *args, *envs = NULL;
736 const MSVCRT_wchar_t * const *envp;
739 __ms_va_start(ap, arg0);
740 args = msvcrt_valisttos(arg0, 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);
749 ret = msvcrt_spawn(flags, name, args, envs, 0);
756 /*********************************************************************
757 * _spawnle (MSVCRT.@)
759 MSVCRT_intptr_t CDECL _spawnle(int flags, const char* name, const char* arg0, ...)
762 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
763 const char * const *envp;
766 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
768 __ms_va_start(ap, arg0);
769 args = msvcrt_valisttos_aw(arg0, 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);
778 ret = msvcrt_spawn(flags, nameW, args, envs, 0);
786 /*********************************************************************
787 * _wspawnlp (MSVCRT.@)
789 * Unicode version of _spawnlp
791 MSVCRT_intptr_t CDECL _wspawnlp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
794 MSVCRT_wchar_t *args;
797 __ms_va_start(ap, arg0);
798 args = msvcrt_valisttos(arg0, ap, ' ');
801 ret = msvcrt_spawn(flags, name, args, NULL, 1);
807 /*********************************************************************
808 * _spawnlp (MSVCRT.@)
810 * Like on Windows, this function does not handle arguments with spaces
813 MSVCRT_intptr_t CDECL _spawnlp(int flags, const char* name, const char* arg0, ...)
816 MSVCRT_wchar_t *nameW, *args;
819 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
821 __ms_va_start(ap, arg0);
822 args = msvcrt_valisttos_aw(arg0, ap, ' ');
825 ret = msvcrt_spawn(flags, nameW, args, NULL, 1);
832 /*********************************************************************
833 * _wspawnlpe (MSVCRT.@)
835 * Unicode version of _spawnlpe
837 MSVCRT_intptr_t CDECL _wspawnlpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
840 MSVCRT_wchar_t *args, *envs = NULL;
841 const MSVCRT_wchar_t * const *envp;
844 __ms_va_start(ap, arg0);
845 args = msvcrt_valisttos(arg0, 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);
854 ret = msvcrt_spawn(flags, name, args, envs, 1);
861 /*********************************************************************
862 * _spawnlpe (MSVCRT.@)
864 MSVCRT_intptr_t CDECL _spawnlpe(int flags, const char* name, const char* arg0, ...)
867 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
868 const char * const *envp;
871 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
873 __ms_va_start(ap, arg0);
874 args = msvcrt_valisttos_aw(arg0, 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);
883 ret = msvcrt_spawn(flags, nameW, args, envs, 1);
891 /*********************************************************************
892 * _spawnve (MSVCRT.@)
894 * Like on Windows, this function does not handle arguments with spaces
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;
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);
916 /*********************************************************************
917 * _wspawnve (MSVCRT.@)
919 * Unicode version of _spawnve
921 MSVCRT_intptr_t CDECL _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;
927 args = msvcrt_argvtos(argv, ' ');
928 envs = msvcrt_argvtos(envv, 0);
930 ret = msvcrt_spawn(flags, name, args, envs, 0);
937 /*********************************************************************
940 * Like on Windows, this function does not handle arguments with spaces
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 _wspawnve(flags, name, argv, NULL);
958 /*********************************************************************
959 * _spawnvpe (MSVCRT.@)
961 * Like on Windows, this function does not handle arguments with spaces
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;
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);
983 /*********************************************************************
984 * _wspawnvpe (MSVCRT.@)
986 * Unicode version of _spawnvpe
988 MSVCRT_intptr_t CDECL _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;
994 args = msvcrt_argvtos(argv, ' ');
995 envs = msvcrt_argvtos(envv, 0);
997 ret = msvcrt_spawn(flags, name, args, envs, 1);
1004 /*********************************************************************
1005 * _spawnvp (MSVCRT.@)
1007 * Like on Windows, this function does not handle arguments with spaces
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 _wspawnvpe(flags, name, argv, NULL);
1025 /*********************************************************************
1026 * _wpopen (MSVCRT.@)
1028 * Unicode version of _popen
1030 MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wchar_t* mode)
1033 BOOL readPipe = TRUE;
1034 int textmode, fds[2], fdToDup, fdToOpen, fdStdHandle = -1;
1035 const MSVCRT_wchar_t *p;
1036 MSVCRT_wchar_t *comspec, *fullcmd;
1038 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1040 TRACE("(command=%s, mode=%s)\n", debugstr_w(command), debugstr_w(mode));
1042 if (!command || !mode)
1045 textmode = *__p__fmode() & (MSVCRT__O_BINARY | MSVCRT__O_TEXT);
1046 for (p = mode; *p; p++)
1056 textmode |= MSVCRT__O_BINARY;
1057 textmode &= ~MSVCRT__O_TEXT;
1061 textmode |= MSVCRT__O_TEXT;
1062 textmode &= ~MSVCRT__O_BINARY;
1066 if (MSVCRT__pipe(fds, 0, textmode) == -1)
1069 fdToDup = readPipe ? 1 : 0;
1070 fdToOpen = readPipe ? 0 : 1;
1072 if ((fdStdHandle = MSVCRT__dup(fdToDup)) == -1)
1074 if (MSVCRT__dup2(fds[fdToDup], fdToDup) != 0)
1077 MSVCRT__close(fds[fdToDup]);
1079 if (!(comspec = msvcrt_get_comspec())) goto error;
1080 len = strlenW(comspec) + strlenW(flag) + strlenW(command) + 1;
1082 if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
1084 HeapFree(GetProcessHeap(), 0, comspec);
1088 strcpyW(fullcmd, comspec);
1089 strcatW(fullcmd, flag);
1090 strcatW(fullcmd, command);
1092 if (msvcrt_spawn(MSVCRT__P_NOWAIT, comspec, fullcmd, NULL, 1) == -1)
1094 MSVCRT__close(fds[fdToOpen]);
1099 ret = MSVCRT__wfdopen(fds[fdToOpen], mode);
1101 MSVCRT__close(fds[fdToOpen]);
1103 HeapFree(GetProcessHeap(), 0, comspec);
1104 HeapFree(GetProcessHeap(), 0, fullcmd);
1105 MSVCRT__dup2(fdStdHandle, fdToDup);
1106 MSVCRT__close(fdStdHandle);
1110 if (fdStdHandle != -1) MSVCRT__close(fdStdHandle);
1111 MSVCRT__close(fds[0]);
1112 MSVCRT__close(fds[1]);
1116 /*********************************************************************
1119 MSVCRT_FILE* CDECL MSVCRT__popen(const char* command, const char* mode)
1122 MSVCRT_wchar_t *cmdW, *modeW;
1124 TRACE("(command=%s, mode=%s)\n", debugstr_a(command), debugstr_a(mode));
1126 if (!command || !mode)
1129 if (!(cmdW = msvcrt_wstrdupa(command))) return NULL;
1130 if (!(modeW = msvcrt_wstrdupa(mode)))
1132 HeapFree(GetProcessHeap(), 0, cmdW);
1136 ret = MSVCRT__wpopen(cmdW, modeW);
1138 HeapFree(GetProcessHeap(), 0, cmdW);
1139 HeapFree(GetProcessHeap(), 0, modeW);
1143 /*********************************************************************
1144 * _pclose (MSVCRT.@)
1146 int CDECL MSVCRT__pclose(MSVCRT_FILE* file)
1148 return MSVCRT_fclose(file);
1151 /*********************************************************************
1152 * _wsystem (MSVCRT.@)
1154 * Unicode version of system
1156 int CDECL _wsystem(const MSVCRT_wchar_t* cmd)
1159 MSVCRT_wchar_t *comspec, *fullcmd;
1161 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1163 comspec = msvcrt_get_comspec();
1167 if (comspec == NULL)
1169 *MSVCRT__errno() = MSVCRT_ENOENT;
1172 HeapFree(GetProcessHeap(), 0, comspec);
1176 if ( comspec == NULL)
1179 len = strlenW(comspec) + strlenW(flag) + strlenW(cmd) + 1;
1181 if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
1183 HeapFree(GetProcessHeap(), 0, comspec);
1186 strcpyW(fullcmd, comspec);
1187 strcatW(fullcmd, flag);
1188 strcatW(fullcmd, cmd);
1190 res = msvcrt_spawn(MSVCRT__P_WAIT, comspec, fullcmd, NULL, 1);
1192 HeapFree(GetProcessHeap(), 0, comspec);
1193 HeapFree(GetProcessHeap(), 0, fullcmd);
1197 /*********************************************************************
1200 int CDECL MSVCRT_system(const char* cmd)
1203 MSVCRT_wchar_t *cmdW;
1206 return _wsystem(NULL);
1208 if ((cmdW = msvcrt_wstrdupa(cmd)))
1210 res = _wsystem(cmdW);
1211 HeapFree(GetProcessHeap(), 0, cmdW);
1216 /*********************************************************************
1217 * _loaddll (MSVCRT.@)
1219 MSVCRT_intptr_t CDECL _loaddll(const char* dllname)
1221 return (MSVCRT_intptr_t)LoadLibraryA(dllname);
1224 /*********************************************************************
1225 * _unloaddll (MSVCRT.@)
1227 int CDECL _unloaddll(MSVCRT_intptr_t dll)
1229 if (FreeLibrary((HMODULE)dll))
1233 int err = GetLastError();
1234 msvcrt_set_errno(err);
1239 /*********************************************************************
1240 * _getdllprocaddr (MSVCRT.@)
1242 void * CDECL _getdllprocaddr(MSVCRT_intptr_t dll, const char *name, int ordinal)
1246 if (ordinal != -1) return NULL;
1247 return GetProcAddress( (HMODULE)dll, name );
1249 if (HIWORD(ordinal)) return NULL;
1250 return GetProcAddress( (HMODULE)dll, (LPCSTR)(ULONG_PTR)ordinal );