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
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;
52 msvcrt_set_errno(ERROR_FILE_NOT_FOUND);
54 p = memchrW(name, '\0', MAX_PATH);
55 if (!p) p = name + MAX_PATH - 1;
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);
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);
87 if (!use_path || !(env = MSVCRT__wgetenv(path))) return;
89 /* now try search path */
93 while (*p && *p != ';') p++;
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);
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);
127 env = *p ? p + 1 : p;
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)
135 PROCESS_INFORMATION pi;
136 MSVCRT_wchar_t fullname[MAX_PATH];
138 TRACE("%x %s %s %s %d\n", flags, debugstr_w(exe), debugstr_w(cmdline), debugstr_w(env), use_path);
140 if ((unsigned)flags > MSVCRT__P_DETACH)
142 *MSVCRT__errno() = MSVCRT_EINVAL;
146 msvcrt_search_executable(exe, fullname, use_path);
148 memset(&si, 0, sizeof(si));
150 msvcrt_create_io_inherit_block(&si.cbReserved2, &si.lpReserved2);
151 if (!CreateProcessW(fullname, cmdline, NULL, NULL, TRUE,
152 flags == MSVCRT__P_DETACH ? DETACHED_PROCESS : 0,
153 env, NULL, &si, &pi))
155 msvcrt_set_errno(GetLastError());
156 MSVCRT_free(si.lpReserved2);
160 MSVCRT_free(si.lpReserved2);
164 WaitForSingleObject(pi.hProcess, INFINITE);
165 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
166 CloseHandle(pi.hProcess);
167 CloseHandle(pi.hThread);
168 return pi.dwProcessId;
169 case MSVCRT__P_DETACH:
170 CloseHandle(pi.hProcess);
173 case MSVCRT__P_NOWAIT:
174 case MSVCRT__P_NOWAITO:
175 CloseHandle(pi.hThread);
176 return (MSVCRT_intptr_t)pi.hProcess;
177 case MSVCRT__P_OVERLAY:
180 return -1; /* can't reach here */
183 /* INTERNAL: Convert wide argv list to a single 'delim'-separated wide string, with an
184 * extra '\0' to terminate it.
186 static MSVCRT_wchar_t* msvcrt_argvtos(const MSVCRT_wchar_t* const* arg, MSVCRT_wchar_t delim)
188 const MSVCRT_wchar_t* const* a;
195 /* Return NULL for an empty environment list */
204 size += strlenW(*a) + 1;
208 ret = MSVCRT_malloc((size + 1) * sizeof(MSVCRT_wchar_t));
217 int len = strlenW(*a);
218 memcpy(p,*a,len * sizeof(MSVCRT_wchar_t));
223 if (delim && p > ret) p[-1] = 0;
228 /* INTERNAL: Convert ansi argv list to a single 'delim'-separated wide string, with an
229 * extra '\0' to terminate it.
231 static MSVCRT_wchar_t *msvcrt_argvtos_aw(const char * const *arg, MSVCRT_wchar_t delim)
233 const char * const *a;
235 MSVCRT_wchar_t *p, *ret;
239 /* Return NULL for an empty environment list */
248 len += MultiByteToWideChar(CP_ACP, 0, *a, -1, NULL, 0);
252 ret = MSVCRT_malloc((len + 1) * sizeof(MSVCRT_wchar_t));
261 p += MultiByteToWideChar(CP_ACP, 0, *a, strlen(*a), p, len - (p - ret));
265 if (delim && p > ret) p[-1] = 0;
270 /* INTERNAL: Convert wide va_list to a single 'delim'-separated wide string, with an
271 * extra '\0' to terminate it.
273 static MSVCRT_wchar_t *msvcrt_valisttos(const MSVCRT_wchar_t *arg0, __ms_va_list alist, MSVCRT_wchar_t delim)
275 unsigned int size = 0, pos = 0;
276 const MSVCRT_wchar_t *arg;
277 MSVCRT_wchar_t *new, *ret = NULL;
279 for (arg = arg0; arg; arg = va_arg( alist, MSVCRT_wchar_t * ))
281 unsigned int len = strlenW( arg ) + 1;
282 if (pos + len >= size)
284 size = max( 256, size * 2 );
285 size = max( size, pos + len + 1 );
286 if (!(new = MSVCRT_realloc( ret, size * sizeof(MSVCRT_wchar_t) )))
293 strcpyW( ret + pos, arg );
295 ret[pos - 1] = delim;
299 if (delim) ret[pos - 1] = 0;
305 /* INTERNAL: Convert ansi va_list to a single 'delim'-separated wide string, with an
306 * extra '\0' to terminate it.
308 static MSVCRT_wchar_t *msvcrt_valisttos_aw(const char *arg0, __ms_va_list alist, MSVCRT_wchar_t delim)
310 unsigned int size = 0, pos = 0;
312 MSVCRT_wchar_t *new, *ret = NULL;
314 for (arg = arg0; arg; arg = va_arg( alist, char * ))
316 unsigned int len = MultiByteToWideChar( CP_ACP, 0, arg, -1, NULL, 0 );
317 if (pos + len >= size)
319 size = max( 256, size * 2 );
320 size = max( size, pos + len + 1 );
321 if (!(new = MSVCRT_realloc( ret, size * sizeof(MSVCRT_wchar_t) )))
328 pos += MultiByteToWideChar( CP_ACP, 0, arg, -1, ret + pos, size - pos );
329 ret[pos - 1] = delim;
333 if (delim) ret[pos - 1] = 0;
339 /* INTERNAL: retrieve COMSPEC environment variable */
340 static MSVCRT_wchar_t *msvcrt_get_comspec(void)
342 static const MSVCRT_wchar_t cmd[] = {'c','m','d',0};
343 static const MSVCRT_wchar_t comspec[] = {'C','O','M','S','P','E','C',0};
347 if (!(len = GetEnvironmentVariableW(comspec, NULL, 0))) len = sizeof(cmd)/sizeof(MSVCRT_wchar_t);
348 if ((ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
350 if (!GetEnvironmentVariableW(comspec, ret, len)) strcpyW(ret, cmd);
355 /*********************************************************************
358 MSVCRT_intptr_t CDECL _cwait(int *status, MSVCRT_intptr_t pid, int action)
360 HANDLE hPid = (HANDLE)pid;
363 action = action; /* Remove warning */
365 if (!WaitForSingleObject(hPid, INFINITE))
370 GetExitCodeProcess(hPid, &stat);
375 doserrno = GetLastError();
377 if (doserrno == ERROR_INVALID_HANDLE)
379 *MSVCRT__errno() = MSVCRT_ECHILD;
380 *MSVCRT___doserrno() = doserrno;
383 msvcrt_set_errno(doserrno);
385 return status ? *status = -1 : -1;
388 /*********************************************************************
391 * Unicode version of _execl
393 MSVCRT_intptr_t CDECL _wexecl(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
396 MSVCRT_wchar_t *args;
399 __ms_va_start(ap, arg0);
400 args = msvcrt_valisttos(arg0, ap, ' ');
403 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 0);
409 /*********************************************************************
412 * Like on Windows, this function does not handle arguments with spaces
415 MSVCRT_intptr_t CDECL _execl(const char* name, const char* arg0, ...)
418 MSVCRT_wchar_t *nameW, *args;
421 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
423 __ms_va_start(ap, arg0);
424 args = msvcrt_valisttos_aw(arg0, ap, ' ');
427 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 0);
434 /*********************************************************************
435 * _wexecle (MSVCRT.@)
437 * Unicode version of _execle
439 MSVCRT_intptr_t CDECL _wexecle(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
442 MSVCRT_wchar_t *args, *envs = NULL;
443 const MSVCRT_wchar_t * const *envp;
446 __ms_va_start(ap, arg0);
447 args = msvcrt_valisttos(arg0, ap, ' ');
450 __ms_va_start(ap, arg0);
451 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
452 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
453 if (envp) envs = msvcrt_argvtos(envp, 0);
456 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 0);
463 /*********************************************************************
466 MSVCRT_intptr_t CDECL _execle(const char* name, const char* arg0, ...)
469 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
470 const char * const *envp;
473 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
475 __ms_va_start(ap, arg0);
476 args = msvcrt_valisttos_aw(arg0, ap, ' ');
479 __ms_va_start(ap, arg0);
480 while (va_arg( ap, char * ) != NULL) /*nothing*/;
481 envp = va_arg( ap, const char * const * );
482 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
485 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 0);
493 /*********************************************************************
494 * _wexeclp (MSVCRT.@)
496 * Unicode version of _execlp
498 MSVCRT_intptr_t CDECL _wexeclp(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
501 MSVCRT_wchar_t *args;
504 __ms_va_start(ap, arg0);
505 args = msvcrt_valisttos(arg0, ap, ' ');
508 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 1);
514 /*********************************************************************
517 * Like on Windows, this function does not handle arguments with spaces
520 MSVCRT_intptr_t CDECL _execlp(const char* name, const char* arg0, ...)
523 MSVCRT_wchar_t *nameW, *args;
526 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
528 __ms_va_start(ap, arg0);
529 args = msvcrt_valisttos_aw(arg0, ap, ' ');
532 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 1);
539 /*********************************************************************
540 * _wexeclpe (MSVCRT.@)
542 * Unicode version of _execlpe
544 MSVCRT_intptr_t CDECL _wexeclpe(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
547 MSVCRT_wchar_t *args, *envs = NULL;
548 const MSVCRT_wchar_t * const *envp;
551 __ms_va_start(ap, arg0);
552 args = msvcrt_valisttos(arg0, ap, ' ');
555 __ms_va_start(ap, arg0);
556 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
557 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
558 if (envp) envs = msvcrt_argvtos(envp, 0);
561 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 1);
568 /*********************************************************************
569 * _execlpe (MSVCRT.@)
571 MSVCRT_intptr_t CDECL _execlpe(const char* name, const char* arg0, ...)
574 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
575 const char * const *envp;
578 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
580 __ms_va_start(ap, arg0);
581 args = msvcrt_valisttos_aw(arg0, ap, ' ');
584 __ms_va_start(ap, arg0);
585 while (va_arg( ap, char * ) != NULL) /*nothing*/;
586 envp = va_arg( ap, const char * const * );
587 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
590 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 1);
598 /*********************************************************************
601 * Unicode version of _execv
603 MSVCRT_intptr_t CDECL _wexecv(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv)
605 return MSVCRT__wspawnve(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, NULL);
608 /*********************************************************************
611 * Like on Windows, this function does not handle arguments with spaces
614 MSVCRT_intptr_t CDECL _execv(const char* name, char* const* argv)
616 return MSVCRT__spawnve(MSVCRT__P_OVERLAY, name, (const char* const*) argv, NULL);
619 /*********************************************************************
620 * _wexecve (MSVCRT.@)
622 * Unicode version of _execve
624 MSVCRT_intptr_t CDECL _wexecve(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
626 return MSVCRT__wspawnve(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, envv);
629 /*********************************************************************
632 * Like on Windows, this function does not handle arguments with spaces
635 MSVCRT_intptr_t CDECL MSVCRT__execve(const char* name, char* const* argv, const char* const* envv)
637 return MSVCRT__spawnve(MSVCRT__P_OVERLAY, name, (const char* const*) argv, envv);
640 /*********************************************************************
641 * _wexecvpe (MSVCRT.@)
643 * Unicode version of _execvpe
645 MSVCRT_intptr_t CDECL _wexecvpe(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
647 return MSVCRT__wspawnvpe(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, envv);
650 /*********************************************************************
651 * _execvpe (MSVCRT.@)
653 * Like on Windows, this function does not handle arguments with spaces
656 MSVCRT_intptr_t CDECL _execvpe(const char* name, char* const* argv, const char* const* envv)
658 return MSVCRT__spawnvpe(MSVCRT__P_OVERLAY, name, (const char* const*) argv, envv);
661 /*********************************************************************
662 * _wexecvp (MSVCRT.@)
664 * Unicode version of _execvp
666 MSVCRT_intptr_t CDECL _wexecvp(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv)
668 return _wexecvpe(name, argv, NULL);
671 /*********************************************************************
674 * Like on Windows, this function does not handle arguments with spaces
677 MSVCRT_intptr_t CDECL _execvp(const char* name, char* const* argv)
679 return _execvpe(name, argv, NULL);
682 /*********************************************************************
683 * _wspawnl (MSVCRT.@)
685 * Unicode version of _spawnl
687 MSVCRT_intptr_t CDECL _wspawnl(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
690 MSVCRT_wchar_t *args;
693 __ms_va_start(ap, arg0);
694 args = msvcrt_valisttos(arg0, ap, ' ');
697 ret = msvcrt_spawn(flags, name, args, NULL, 0);
703 /*********************************************************************
706 * Like on Windows, this function does not handle arguments with spaces
709 MSVCRT_intptr_t CDECL _spawnl(int flags, const char* name, const char* arg0, ...)
712 MSVCRT_wchar_t *nameW, *args;
715 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
717 __ms_va_start(ap, arg0);
718 args = msvcrt_valisttos_aw(arg0, ap, ' ');
721 ret = msvcrt_spawn(flags, nameW, args, NULL, 0);
728 /*********************************************************************
729 * _wspawnle (MSVCRT.@)
731 * Unicode version of _spawnle
733 MSVCRT_intptr_t CDECL _wspawnle(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
736 MSVCRT_wchar_t *args, *envs = NULL;
737 const MSVCRT_wchar_t * const *envp;
740 __ms_va_start(ap, arg0);
741 args = msvcrt_valisttos(arg0, ap, ' ');
744 __ms_va_start(ap, arg0);
745 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
746 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
747 if (envp) envs = msvcrt_argvtos(envp, 0);
750 ret = msvcrt_spawn(flags, name, args, envs, 0);
757 /*********************************************************************
758 * _spawnle (MSVCRT.@)
760 MSVCRT_intptr_t CDECL _spawnle(int flags, const char* name, const char* arg0, ...)
763 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
764 const char * const *envp;
767 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
769 __ms_va_start(ap, arg0);
770 args = msvcrt_valisttos_aw(arg0, ap, ' ');
773 __ms_va_start(ap, arg0);
774 while (va_arg( ap, char * ) != NULL) /*nothing*/;
775 envp = va_arg( ap, const char * const * );
776 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
779 ret = msvcrt_spawn(flags, nameW, args, envs, 0);
787 /*********************************************************************
788 * _wspawnlp (MSVCRT.@)
790 * Unicode version of _spawnlp
792 MSVCRT_intptr_t CDECL _wspawnlp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
795 MSVCRT_wchar_t *args;
798 __ms_va_start(ap, arg0);
799 args = msvcrt_valisttos(arg0, ap, ' ');
802 ret = msvcrt_spawn(flags, name, args, NULL, 1);
808 /*********************************************************************
809 * _spawnlp (MSVCRT.@)
811 * Like on Windows, this function does not handle arguments with spaces
814 MSVCRT_intptr_t CDECL _spawnlp(int flags, const char* name, const char* arg0, ...)
817 MSVCRT_wchar_t *nameW, *args;
820 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
822 __ms_va_start(ap, arg0);
823 args = msvcrt_valisttos_aw(arg0, ap, ' ');
826 ret = msvcrt_spawn(flags, nameW, args, NULL, 1);
833 /*********************************************************************
834 * _wspawnlpe (MSVCRT.@)
836 * Unicode version of _spawnlpe
838 MSVCRT_intptr_t CDECL _wspawnlpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
841 MSVCRT_wchar_t *args, *envs = NULL;
842 const MSVCRT_wchar_t * const *envp;
845 __ms_va_start(ap, arg0);
846 args = msvcrt_valisttos(arg0, ap, ' ');
849 __ms_va_start(ap, arg0);
850 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
851 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
852 if (envp) envs = msvcrt_argvtos(envp, 0);
855 ret = msvcrt_spawn(flags, name, args, envs, 1);
862 /*********************************************************************
863 * _spawnlpe (MSVCRT.@)
865 MSVCRT_intptr_t CDECL _spawnlpe(int flags, const char* name, const char* arg0, ...)
868 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
869 const char * const *envp;
872 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
874 __ms_va_start(ap, arg0);
875 args = msvcrt_valisttos_aw(arg0, ap, ' ');
878 __ms_va_start(ap, arg0);
879 while (va_arg( ap, char * ) != NULL) /*nothing*/;
880 envp = va_arg( ap, const char * const * );
881 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
884 ret = msvcrt_spawn(flags, nameW, args, envs, 1);
892 /*********************************************************************
893 * _spawnve (MSVCRT.@)
895 * Like on Windows, this function does not handle arguments with spaces
898 MSVCRT_intptr_t CDECL MSVCRT__spawnve(int flags, const char* name, const char* const* argv,
899 const char* const* envv)
901 MSVCRT_wchar_t *nameW, *args, *envs;
904 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
906 args = msvcrt_argvtos_aw(argv, ' ');
907 envs = msvcrt_argvtos_aw(envv, 0);
909 ret = msvcrt_spawn(flags, nameW, args, envs, 0);
917 /*********************************************************************
918 * _wspawnve (MSVCRT.@)
920 * Unicode version of _spawnve
922 MSVCRT_intptr_t CDECL MSVCRT__wspawnve(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
923 const MSVCRT_wchar_t* const* envv)
925 MSVCRT_wchar_t *args, *envs;
928 args = msvcrt_argvtos(argv, ' ');
929 envs = msvcrt_argvtos(envv, 0);
931 ret = msvcrt_spawn(flags, name, args, envs, 0);
938 /*********************************************************************
941 * Like on Windows, this function does not handle arguments with spaces
944 MSVCRT_intptr_t CDECL _spawnv(int flags, const char* name, const char* const* argv)
946 return MSVCRT__spawnve(flags, name, argv, NULL);
949 /*********************************************************************
950 * _wspawnv (MSVCRT.@)
952 * Unicode version of _spawnv
954 MSVCRT_intptr_t CDECL _wspawnv(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
956 return MSVCRT__wspawnve(flags, name, argv, NULL);
959 /*********************************************************************
960 * _spawnvpe (MSVCRT.@)
962 * Like on Windows, this function does not handle arguments with spaces
965 MSVCRT_intptr_t CDECL MSVCRT__spawnvpe(int flags, const char* name, const char* const* argv,
966 const char* const* envv)
968 MSVCRT_wchar_t *nameW, *args, *envs;
971 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
973 args = msvcrt_argvtos_aw(argv, ' ');
974 envs = msvcrt_argvtos_aw(envv, 0);
976 ret = msvcrt_spawn(flags, nameW, args, envs, 1);
984 /*********************************************************************
985 * _wspawnvpe (MSVCRT.@)
987 * Unicode version of _spawnvpe
989 MSVCRT_intptr_t CDECL MSVCRT__wspawnvpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
990 const MSVCRT_wchar_t* const* envv)
992 MSVCRT_wchar_t *args, *envs;
995 args = msvcrt_argvtos(argv, ' ');
996 envs = msvcrt_argvtos(envv, 0);
998 ret = msvcrt_spawn(flags, name, args, envs, 1);
1005 /*********************************************************************
1006 * _spawnvp (MSVCRT.@)
1008 * Like on Windows, this function does not handle arguments with spaces
1011 MSVCRT_intptr_t CDECL _spawnvp(int flags, const char* name, const char* const* argv)
1013 return MSVCRT__spawnvpe(flags, name, argv, NULL);
1016 /*********************************************************************
1017 * _wspawnvp (MSVCRT.@)
1019 * Unicode version of _spawnvp
1021 MSVCRT_intptr_t CDECL _wspawnvp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
1023 return MSVCRT__wspawnvpe(flags, name, argv, NULL);
1026 static struct popen_handle {
1030 static DWORD popen_handles_size;
1032 void msvcrt_free_popen_data(void)
1034 MSVCRT_free(popen_handles);
1037 /*********************************************************************
1038 * _wpopen (MSVCRT.@)
1040 * Unicode version of _popen
1042 MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wchar_t* mode)
1045 BOOL readPipe = TRUE;
1046 int textmode, fds[2], fdToDup, fdToOpen, fdStdHandle = -1;
1047 const MSVCRT_wchar_t *p;
1048 MSVCRT_wchar_t *comspec, *fullcmd;
1050 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1051 struct popen_handle *container;
1054 TRACE("(command=%s, mode=%s)\n", debugstr_w(command), debugstr_w(mode));
1056 if (!command || !mode)
1059 textmode = *__p__fmode() & (MSVCRT__O_BINARY | MSVCRT__O_TEXT);
1060 for (p = mode; *p; p++)
1070 textmode |= MSVCRT__O_BINARY;
1071 textmode &= ~MSVCRT__O_TEXT;
1075 textmode |= MSVCRT__O_TEXT;
1076 textmode &= ~MSVCRT__O_BINARY;
1080 if (MSVCRT__pipe(fds, 0, textmode) == -1)
1083 fdToDup = readPipe ? 1 : 0;
1084 fdToOpen = readPipe ? 0 : 1;
1086 _mlock(_POPEN_LOCK);
1087 for(i=0; i<popen_handles_size; i++)
1089 if (!popen_handles[i].f)
1092 if (i==popen_handles_size)
1094 i = (popen_handles_size ? popen_handles_size*2 : 8);
1095 container = MSVCRT_realloc(popen_handles, i*sizeof(*container));
1096 if (!container) goto error;
1098 popen_handles = container;
1099 container = popen_handles+popen_handles_size;
1100 memset(container, 0, (i-popen_handles_size)*sizeof(*container));
1101 popen_handles_size = i;
1103 else container = popen_handles+i;
1105 if ((fdStdHandle = MSVCRT__dup(fdToDup)) == -1)
1107 if (MSVCRT__dup2(fds[fdToDup], fdToDup) != 0)
1110 MSVCRT__close(fds[fdToDup]);
1112 if (!(comspec = msvcrt_get_comspec())) goto error;
1113 len = strlenW(comspec) + strlenW(flag) + strlenW(command) + 1;
1115 if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
1117 HeapFree(GetProcessHeap(), 0, comspec);
1121 strcpyW(fullcmd, comspec);
1122 strcatW(fullcmd, flag);
1123 strcatW(fullcmd, command);
1125 if ((container->proc = (HANDLE)msvcrt_spawn(MSVCRT__P_NOWAIT, comspec, fullcmd, NULL, 1))
1126 == INVALID_HANDLE_VALUE)
1128 MSVCRT__close(fds[fdToOpen]);
1133 ret = MSVCRT__wfdopen(fds[fdToOpen], mode);
1135 MSVCRT__close(fds[fdToOpen]);
1138 _munlock(_POPEN_LOCK);
1139 HeapFree(GetProcessHeap(), 0, comspec);
1140 HeapFree(GetProcessHeap(), 0, fullcmd);
1141 MSVCRT__dup2(fdStdHandle, fdToDup);
1142 MSVCRT__close(fdStdHandle);
1146 _munlock(_POPEN_LOCK);
1147 if (fdStdHandle != -1) MSVCRT__close(fdStdHandle);
1148 MSVCRT__close(fds[0]);
1149 MSVCRT__close(fds[1]);
1153 /*********************************************************************
1156 MSVCRT_FILE* CDECL MSVCRT__popen(const char* command, const char* mode)
1159 MSVCRT_wchar_t *cmdW, *modeW;
1161 TRACE("(command=%s, mode=%s)\n", debugstr_a(command), debugstr_a(mode));
1163 if (!command || !mode)
1166 if (!(cmdW = msvcrt_wstrdupa(command))) return NULL;
1167 if (!(modeW = msvcrt_wstrdupa(mode)))
1169 HeapFree(GetProcessHeap(), 0, cmdW);
1173 ret = MSVCRT__wpopen(cmdW, modeW);
1175 HeapFree(GetProcessHeap(), 0, cmdW);
1176 HeapFree(GetProcessHeap(), 0, modeW);
1180 /*********************************************************************
1181 * _pclose (MSVCRT.@)
1183 int CDECL MSVCRT__pclose(MSVCRT_FILE* file)
1188 if (!MSVCRT_CHECK_PMT(file != NULL)) return -1;
1190 _mlock(_POPEN_LOCK);
1191 for(i=0; i<popen_handles_size; i++)
1193 if (popen_handles[i].f == file)
1196 if(i == popen_handles_size)
1198 _munlock(_POPEN_LOCK);
1199 *MSVCRT__errno() = MSVCRT_EBADF;
1203 h = popen_handles[i].proc;
1204 popen_handles[i].f = NULL;
1205 _munlock(_POPEN_LOCK);
1207 MSVCRT_fclose(file);
1208 if(WaitForSingleObject(h, INFINITE)==WAIT_FAILED || !GetExitCodeProcess(h, &i))
1210 msvcrt_set_errno(GetLastError());
1219 /*********************************************************************
1220 * _wsystem (MSVCRT.@)
1222 * Unicode version of system
1224 int CDECL _wsystem(const MSVCRT_wchar_t* cmd)
1227 MSVCRT_wchar_t *comspec, *fullcmd;
1229 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1231 comspec = msvcrt_get_comspec();
1235 if (comspec == NULL)
1237 *MSVCRT__errno() = MSVCRT_ENOENT;
1240 HeapFree(GetProcessHeap(), 0, comspec);
1244 if ( comspec == NULL)
1247 len = strlenW(comspec) + strlenW(flag) + strlenW(cmd) + 1;
1249 if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
1251 HeapFree(GetProcessHeap(), 0, comspec);
1254 strcpyW(fullcmd, comspec);
1255 strcatW(fullcmd, flag);
1256 strcatW(fullcmd, cmd);
1258 res = msvcrt_spawn(MSVCRT__P_WAIT, comspec, fullcmd, NULL, 1);
1260 HeapFree(GetProcessHeap(), 0, comspec);
1261 HeapFree(GetProcessHeap(), 0, fullcmd);
1265 /*********************************************************************
1268 int CDECL MSVCRT_system(const char* cmd)
1271 MSVCRT_wchar_t *cmdW;
1274 return _wsystem(NULL);
1276 if ((cmdW = msvcrt_wstrdupa(cmd)))
1278 res = _wsystem(cmdW);
1279 HeapFree(GetProcessHeap(), 0, cmdW);
1284 /*********************************************************************
1285 * _loaddll (MSVCRT.@)
1287 MSVCRT_intptr_t CDECL _loaddll(const char* dllname)
1289 return (MSVCRT_intptr_t)LoadLibraryA(dllname);
1292 /*********************************************************************
1293 * _unloaddll (MSVCRT.@)
1295 int CDECL _unloaddll(MSVCRT_intptr_t dll)
1297 if (FreeLibrary((HMODULE)dll))
1301 int err = GetLastError();
1302 msvcrt_set_errno(err);
1307 /*********************************************************************
1308 * _getdllprocaddr (MSVCRT.@)
1310 void * CDECL _getdllprocaddr(MSVCRT_intptr_t dll, const char *name, int ordinal)
1314 if (ordinal != -1) return NULL;
1315 return GetProcAddress( (HMODULE)dll, name );
1317 if (HIWORD(ordinal)) return NULL;
1318 return GetProcAddress( (HMODULE)dll, (LPCSTR)(ULONG_PTR)ordinal );