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
, va_list alist
, MSVCRT_wchar_t delim
)
276 const MSVCRT_wchar_t
*arg
;
277 MSVCRT_wchar_t
*p
, *ret
;
280 va_copy(alist2
,alist
);
282 # ifdef HAVE___VA_COPY
283 __va_copy(alist2
,alist
);
291 /* Return NULL for an empty environment list */
299 len
+= strlenW(arg
) + 1;
300 arg
= va_arg(alist
, MSVCRT_wchar_t
*);
301 } while (arg
!= NULL
);
303 ret
= MSVCRT_malloc((len
+ 1) * sizeof(MSVCRT_wchar_t
));
312 memcpy(p
, arg
, len
* sizeof(MSVCRT_wchar_t
));
315 arg
= va_arg(alist2
, MSVCRT_wchar_t
*);
316 } while (arg
!= NULL
);
317 if (delim
&& p
> ret
) p
[-1] = 0;
322 /* INTERNAL: Convert ansi va_list to a single 'delim'-separated wide string, with an
323 * extra '\0' to terminate it.
325 static MSVCRT_wchar_t
*msvcrt_valisttos_aw(const char *arg0
, va_list alist
, MSVCRT_wchar_t delim
)
330 MSVCRT_wchar_t
*p
, *ret
;
333 va_copy(alist2
,alist
);
335 # ifdef HAVE___VA_COPY
336 __va_copy(alist2
,alist
);
344 /* Return NULL for an empty environment list */
352 len
+= MultiByteToWideChar(CP_ACP
, 0, arg
, -1, NULL
, 0);
353 arg
= va_arg(alist
, char*);
354 } while (arg
!= NULL
);
356 ret
= MSVCRT_malloc((len
+ 1) * sizeof(MSVCRT_wchar_t
));
364 p
+= MultiByteToWideChar(CP_ACP
, 0, arg
, strlen(arg
), p
, len
- (p
- ret
));
366 arg
= va_arg(alist2
, char*);
367 } while (arg
!= NULL
);
368 if (delim
&& p
> ret
) p
[-1] = 0;
373 /* INTERNAL: retrieve COMSPEC environment variable */
374 static MSVCRT_wchar_t
*msvcrt_get_comspec(void)
376 static const MSVCRT_wchar_t cmd
[] = {'c','m','d',0};
377 static const MSVCRT_wchar_t comspec
[] = {'C','O','M','S','P','E','C',0};
381 if (!(len
= GetEnvironmentVariableW(comspec
, NULL
, 0))) len
= sizeof(cmd
)/sizeof(MSVCRT_wchar_t
);
382 if ((ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(MSVCRT_wchar_t
))))
384 if (!GetEnvironmentVariableW(comspec
, ret
, len
)) strcpyW(ret
, cmd
);
389 /*********************************************************************
392 MSVCRT_intptr_t CDECL
_cwait(int *status
, MSVCRT_intptr_t pid
, int action
)
394 HANDLE hPid
= (HANDLE
)pid
;
397 action
= action
; /* Remove warning */
399 if (!WaitForSingleObject(hPid
, INFINITE
))
404 GetExitCodeProcess(hPid
, &stat
);
409 doserrno
= GetLastError();
411 if (doserrno
== ERROR_INVALID_HANDLE
)
413 *MSVCRT__errno() = MSVCRT_ECHILD
;
414 *MSVCRT___doserrno() = doserrno
;
417 msvcrt_set_errno(doserrno
);
419 return status
? *status
= -1 : -1;
422 /*********************************************************************
425 * Unicode version of _execl
427 MSVCRT_intptr_t CDECL
_wexecl(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
430 MSVCRT_wchar_t
*args
;
434 args
= msvcrt_valisttos(arg0
, ap
, ' ');
437 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, name
, args
, NULL
, 0);
443 /*********************************************************************
446 * Like on Windows, this function does not handle arguments with spaces
449 MSVCRT_intptr_t CDECL
_execl(const char* name
, const char* arg0
, ...)
452 MSVCRT_wchar_t
*nameW
, *args
;
455 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
458 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
461 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, nameW
, args
, NULL
, 0);
468 /*********************************************************************
469 * _wexecle (MSVCRT.@)
471 * Unicode version of _execle
473 MSVCRT_intptr_t CDECL
_wexecle(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
476 MSVCRT_wchar_t
*args
, *envs
= NULL
;
477 const MSVCRT_wchar_t
* const *envp
;
481 args
= msvcrt_valisttos(arg0
, ap
, ' ');
485 while (va_arg( ap
, MSVCRT_wchar_t
* ) != NULL
) /*nothing*/;
486 envp
= va_arg( ap
, const MSVCRT_wchar_t
* const * );
487 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
490 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, name
, args
, envs
, 0);
497 /*********************************************************************
500 MSVCRT_intptr_t CDECL
_execle(const char* name
, const char* arg0
, ...)
503 MSVCRT_wchar_t
*nameW
, *args
, *envs
= NULL
;
504 const char * const *envp
;
507 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
510 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
514 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
515 envp
= va_arg( ap
, const char * const * );
516 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
519 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, nameW
, args
, envs
, 0);
527 /*********************************************************************
528 * _wexeclp (MSVCRT.@)
530 * Unicode version of _execlp
532 MSVCRT_intptr_t CDECL
_wexeclp(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
535 MSVCRT_wchar_t
*args
;
539 args
= msvcrt_valisttos(arg0
, ap
, ' ');
542 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, name
, args
, NULL
, 1);
548 /*********************************************************************
551 * Like on Windows, this function does not handle arguments with spaces
554 MSVCRT_intptr_t CDECL
_execlp(const char* name
, const char* arg0
, ...)
557 MSVCRT_wchar_t
*nameW
, *args
;
560 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
563 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
566 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, nameW
, args
, NULL
, 1);
573 /*********************************************************************
574 * _wexeclpe (MSVCRT.@)
576 * Unicode version of _execlpe
578 MSVCRT_intptr_t CDECL
_wexeclpe(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
581 MSVCRT_wchar_t
*args
, *envs
= NULL
;
582 const MSVCRT_wchar_t
* const *envp
;
586 args
= msvcrt_valisttos(arg0
, ap
, ' ');
590 while (va_arg( ap
, MSVCRT_wchar_t
* ) != NULL
) /*nothing*/;
591 envp
= va_arg( ap
, const MSVCRT_wchar_t
* const * );
592 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
595 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, name
, args
, envs
, 1);
602 /*********************************************************************
603 * _execlpe (MSVCRT.@)
605 MSVCRT_intptr_t CDECL
_execlpe(const char* name
, const char* arg0
, ...)
608 MSVCRT_wchar_t
*nameW
, *args
, *envs
= NULL
;
609 const char * const *envp
;
612 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
615 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
619 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
620 envp
= va_arg( ap
, const char * const * );
621 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
624 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, nameW
, args
, envs
, 1);
632 /*********************************************************************
635 * Unicode version of _execv
637 MSVCRT_intptr_t CDECL
_wexecv(const MSVCRT_wchar_t
* name
, MSVCRT_wchar_t
* const* argv
)
639 return _wspawnve(MSVCRT__P_OVERLAY
, name
, (const MSVCRT_wchar_t
* const*) argv
, NULL
);
642 /*********************************************************************
645 * Like on Windows, this function does not handle arguments with spaces
648 MSVCRT_intptr_t CDECL
_execv(const char* name
, char* const* argv
)
650 return _spawnve(MSVCRT__P_OVERLAY
, name
, (const char* const*) argv
, NULL
);
653 /*********************************************************************
654 * _wexecve (MSVCRT.@)
656 * Unicode version of _execve
658 MSVCRT_intptr_t CDECL
_wexecve(const MSVCRT_wchar_t
* name
, MSVCRT_wchar_t
* const* argv
, const MSVCRT_wchar_t
* const* envv
)
660 return _wspawnve(MSVCRT__P_OVERLAY
, name
, (const MSVCRT_wchar_t
* const*) argv
, envv
);
663 /*********************************************************************
666 * Like on Windows, this function does not handle arguments with spaces
669 MSVCRT_intptr_t CDECL
MSVCRT__execve(const char* name
, char* const* argv
, const char* const* envv
)
671 return _spawnve(MSVCRT__P_OVERLAY
, name
, (const char* const*) argv
, envv
);
674 /*********************************************************************
675 * _wexecvpe (MSVCRT.@)
677 * Unicode version of _execvpe
679 MSVCRT_intptr_t CDECL
_wexecvpe(const MSVCRT_wchar_t
* name
, MSVCRT_wchar_t
* const* argv
, const MSVCRT_wchar_t
* const* envv
)
681 return _wspawnvpe(MSVCRT__P_OVERLAY
, name
, (const MSVCRT_wchar_t
* const*) argv
, envv
);
684 /*********************************************************************
685 * _execvpe (MSVCRT.@)
687 * Like on Windows, this function does not handle arguments with spaces
690 MSVCRT_intptr_t CDECL
_execvpe(const char* name
, char* const* argv
, const char* const* envv
)
692 return _spawnvpe(MSVCRT__P_OVERLAY
, name
, (const char* const*) argv
, envv
);
695 /*********************************************************************
696 * _wexecvp (MSVCRT.@)
698 * Unicode version of _execvp
700 MSVCRT_intptr_t CDECL
_wexecvp(const MSVCRT_wchar_t
* name
, MSVCRT_wchar_t
* const* argv
)
702 return _wexecvpe(name
, argv
, NULL
);
705 /*********************************************************************
708 * Like on Windows, this function does not handle arguments with spaces
711 MSVCRT_intptr_t CDECL
_execvp(const char* name
, char* const* argv
)
713 return _execvpe(name
, argv
, NULL
);
716 /*********************************************************************
717 * _wspawnl (MSVCRT.@)
719 * Unicode version of _spawnl
721 MSVCRT_intptr_t CDECL
_wspawnl(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
724 MSVCRT_wchar_t
*args
;
728 args
= msvcrt_valisttos(arg0
, ap
, ' ');
731 ret
= msvcrt_spawn(flags
, name
, args
, NULL
, 0);
737 /*********************************************************************
740 * Like on Windows, this function does not handle arguments with spaces
743 MSVCRT_intptr_t CDECL
_spawnl(int flags
, const char* name
, const char* arg0
, ...)
746 MSVCRT_wchar_t
*nameW
, *args
;
749 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
752 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
755 ret
= msvcrt_spawn(flags
, nameW
, args
, NULL
, 0);
762 /*********************************************************************
763 * _wspawnle (MSVCRT.@)
765 * Unicode version of _spawnle
767 MSVCRT_intptr_t CDECL
_wspawnle(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
770 MSVCRT_wchar_t
*args
, *envs
= NULL
;
771 const MSVCRT_wchar_t
* const *envp
;
775 args
= msvcrt_valisttos(arg0
, ap
, ' ');
779 while (va_arg( ap
, MSVCRT_wchar_t
* ) != NULL
) /*nothing*/;
780 envp
= va_arg( ap
, const MSVCRT_wchar_t
* const * );
781 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
784 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 0);
791 /*********************************************************************
792 * _spawnle (MSVCRT.@)
794 MSVCRT_intptr_t CDECL
_spawnle(int flags
, const char* name
, const char* arg0
, ...)
797 MSVCRT_wchar_t
*nameW
, *args
, *envs
= NULL
;
798 const char * const *envp
;
801 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
804 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
808 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
809 envp
= va_arg( ap
, const char * const * );
810 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
813 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 0);
821 /*********************************************************************
822 * _wspawnlp (MSVCRT.@)
824 * Unicode version of _spawnlp
826 MSVCRT_intptr_t CDECL
_wspawnlp(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
829 MSVCRT_wchar_t
*args
;
833 args
= msvcrt_valisttos(arg0
, ap
, ' ');
836 ret
= msvcrt_spawn(flags
, name
, args
, NULL
, 1);
842 /*********************************************************************
843 * _spawnlp (MSVCRT.@)
845 * Like on Windows, this function does not handle arguments with spaces
848 MSVCRT_intptr_t CDECL
_spawnlp(int flags
, const char* name
, const char* arg0
, ...)
851 MSVCRT_wchar_t
*nameW
, *args
;
854 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
857 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
860 ret
= msvcrt_spawn(flags
, nameW
, args
, NULL
, 1);
867 /*********************************************************************
868 * _wspawnlpe (MSVCRT.@)
870 * Unicode version of _spawnlpe
872 MSVCRT_intptr_t CDECL
_wspawnlpe(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
875 MSVCRT_wchar_t
*args
, *envs
= NULL
;
876 const MSVCRT_wchar_t
* const *envp
;
880 args
= msvcrt_valisttos(arg0
, ap
, ' ');
884 while (va_arg( ap
, MSVCRT_wchar_t
* ) != NULL
) /*nothing*/;
885 envp
= va_arg( ap
, const MSVCRT_wchar_t
* const * );
886 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
889 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 1);
896 /*********************************************************************
897 * _spawnlpe (MSVCRT.@)
899 MSVCRT_intptr_t CDECL
_spawnlpe(int flags
, const char* name
, const char* arg0
, ...)
902 MSVCRT_wchar_t
*nameW
, *args
, *envs
= NULL
;
903 const char * const *envp
;
906 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
909 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
913 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
914 envp
= va_arg( ap
, const char * const * );
915 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
918 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 1);
926 /*********************************************************************
927 * _spawnve (MSVCRT.@)
929 * Like on Windows, this function does not handle arguments with spaces
932 MSVCRT_intptr_t CDECL
_spawnve(int flags
, const char* name
, const char* const* argv
,
933 const char* const* envv
)
935 MSVCRT_wchar_t
*nameW
, *args
, *envs
;
938 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
940 args
= msvcrt_argvtos_aw(argv
, ' ');
941 envs
= msvcrt_argvtos_aw(envv
, 0);
943 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 0);
951 /*********************************************************************
952 * _wspawnve (MSVCRT.@)
954 * Unicode version of _spawnve
956 MSVCRT_intptr_t CDECL
_wspawnve(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
,
957 const MSVCRT_wchar_t
* const* envv
)
959 MSVCRT_wchar_t
*args
, *envs
;
962 args
= msvcrt_argvtos(argv
, ' ');
963 envs
= msvcrt_argvtos(envv
, 0);
965 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 0);
972 /*********************************************************************
975 * Like on Windows, this function does not handle arguments with spaces
978 MSVCRT_intptr_t CDECL
_spawnv(int flags
, const char* name
, const char* const* argv
)
980 return _spawnve(flags
, name
, argv
, NULL
);
983 /*********************************************************************
984 * _wspawnv (MSVCRT.@)
986 * Unicode version of _spawnv
988 MSVCRT_intptr_t CDECL
_wspawnv(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
)
990 return _wspawnve(flags
, name
, argv
, NULL
);
993 /*********************************************************************
994 * _spawnvpe (MSVCRT.@)
996 * Like on Windows, this function does not handle arguments with spaces
999 MSVCRT_intptr_t CDECL
_spawnvpe(int flags
, const char* name
, const char* const* argv
,
1000 const char* const* envv
)
1002 MSVCRT_wchar_t
*nameW
, *args
, *envs
;
1003 MSVCRT_intptr_t ret
;
1005 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
1007 args
= msvcrt_argvtos_aw(argv
, ' ');
1008 envs
= msvcrt_argvtos_aw(envv
, 0);
1010 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 1);
1018 /*********************************************************************
1019 * _wspawnvpe (MSVCRT.@)
1021 * Unicode version of _spawnvpe
1023 MSVCRT_intptr_t CDECL
_wspawnvpe(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
,
1024 const MSVCRT_wchar_t
* const* envv
)
1026 MSVCRT_wchar_t
*args
, *envs
;
1027 MSVCRT_intptr_t ret
;
1029 args
= msvcrt_argvtos(argv
, ' ');
1030 envs
= msvcrt_argvtos(envv
, 0);
1032 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 1);
1039 /*********************************************************************
1040 * _spawnvp (MSVCRT.@)
1042 * Like on Windows, this function does not handle arguments with spaces
1045 MSVCRT_intptr_t CDECL
_spawnvp(int flags
, const char* name
, const char* const* argv
)
1047 return _spawnvpe(flags
, name
, argv
, NULL
);
1050 /*********************************************************************
1051 * _wspawnvp (MSVCRT.@)
1053 * Unicode version of _spawnvp
1055 MSVCRT_intptr_t CDECL
_wspawnvp(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
)
1057 return _wspawnvpe(flags
, name
, argv
, NULL
);
1060 /*********************************************************************
1061 * _wpopen (MSVCRT.@)
1063 * Unicode version of _popen
1065 MSVCRT_FILE
* CDECL
MSVCRT__wpopen(const MSVCRT_wchar_t
* command
, const MSVCRT_wchar_t
* mode
)
1068 BOOL readPipe
= TRUE
;
1069 int textmode
, fds
[2], fdToDup
, fdToOpen
, fdStdHandle
= -1, fdStdErr
= -1;
1070 const MSVCRT_wchar_t
*p
;
1071 MSVCRT_wchar_t
*comspec
, *fullcmd
;
1073 static const MSVCRT_wchar_t flag
[] = {' ','/','c',' ',0};
1075 TRACE("(command=%s, mode=%s)\n", debugstr_w(command
), debugstr_w(mode
));
1077 if (!command
|| !mode
)
1080 textmode
= *__p__fmode() & (MSVCRT__O_BINARY
| MSVCRT__O_TEXT
);
1081 for (p
= mode
; *p
; p
++)
1091 textmode
|= MSVCRT__O_BINARY
;
1092 textmode
&= ~MSVCRT__O_TEXT
;
1096 textmode
|= MSVCRT__O_TEXT
;
1097 textmode
&= ~MSVCRT__O_BINARY
;
1101 if (MSVCRT__pipe(fds
, 0, textmode
) == -1)
1104 fdToDup
= readPipe
? 1 : 0;
1105 fdToOpen
= readPipe
? 0 : 1;
1107 if ((fdStdHandle
= MSVCRT__dup(fdToDup
)) == -1)
1109 if (MSVCRT__dup2(fds
[fdToDup
], fdToDup
) != 0)
1113 if ((fdStdErr
= MSVCRT__dup(MSVCRT_STDERR_FILENO
)) == -1)
1115 if (MSVCRT__dup2(fds
[fdToDup
], MSVCRT_STDERR_FILENO
) != 0)
1119 MSVCRT__close(fds
[fdToDup
]);
1121 if (!(comspec
= msvcrt_get_comspec())) goto error
;
1122 len
= strlenW(comspec
) + strlenW(flag
) + strlenW(command
) + 1;
1124 if (!(fullcmd
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(MSVCRT_wchar_t
)))) goto error
;
1125 strcpyW(fullcmd
, comspec
);
1126 strcatW(fullcmd
, flag
);
1127 strcatW(fullcmd
, command
);
1128 HeapFree(GetProcessHeap(), 0, comspec
);
1130 if (msvcrt_spawn(MSVCRT__P_NOWAIT
, NULL
, fullcmd
, NULL
, 1) == -1)
1132 MSVCRT__close(fds
[fdToOpen
]);
1137 ret
= MSVCRT__wfdopen(fds
[fdToOpen
], mode
);
1139 MSVCRT__close(fds
[fdToOpen
]);
1141 HeapFree(GetProcessHeap(), 0, fullcmd
);
1142 MSVCRT__dup2(fdStdHandle
, fdToDup
);
1143 MSVCRT__close(fdStdHandle
);
1146 MSVCRT__dup2(fdStdErr
, MSVCRT_STDERR_FILENO
);
1147 MSVCRT__close(fdStdErr
);
1152 if (fdStdHandle
!= -1) MSVCRT__close(fdStdHandle
);
1153 if (fdStdErr
!= -1) MSVCRT__close(fdStdErr
);
1154 MSVCRT__close(fds
[0]);
1155 MSVCRT__close(fds
[1]);
1159 /*********************************************************************
1162 MSVCRT_FILE
* CDECL
MSVCRT__popen(const char* command
, const char* mode
)
1165 MSVCRT_wchar_t
*cmdW
, *modeW
;
1167 TRACE("(command=%s, mode=%s)\n", debugstr_a(command
), debugstr_a(mode
));
1169 if (!command
|| !mode
)
1172 if (!(cmdW
= msvcrt_wstrdupa(command
))) return NULL
;
1173 if (!(modeW
= msvcrt_wstrdupa(mode
)))
1175 HeapFree(GetProcessHeap(), 0, cmdW
);
1179 ret
= MSVCRT__wpopen(cmdW
, modeW
);
1181 HeapFree(GetProcessHeap(), 0, cmdW
);
1182 HeapFree(GetProcessHeap(), 0, modeW
);
1186 /*********************************************************************
1187 * _pclose (MSVCRT.@)
1189 int CDECL
MSVCRT__pclose(MSVCRT_FILE
* file
)
1191 return MSVCRT_fclose(file
);
1194 /*********************************************************************
1195 * _wsystem (MSVCRT.@)
1197 * Unicode version of system
1199 int CDECL
_wsystem(const MSVCRT_wchar_t
* cmd
)
1202 MSVCRT_wchar_t
*comspec
, *fullcmd
;
1204 static const MSVCRT_wchar_t flag
[] = {' ','/','c',' ',0};
1206 if (!(comspec
= msvcrt_get_comspec())) return -1;
1207 len
= strlenW(comspec
) + strlenW(flag
) + strlenW(cmd
) + 1;
1209 if (!(fullcmd
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(MSVCRT_wchar_t
))))
1211 HeapFree(GetProcessHeap(), 0, comspec
);
1214 strcpyW(fullcmd
, comspec
);
1215 strcatW(fullcmd
, flag
);
1216 strcatW(fullcmd
, cmd
);
1218 res
= msvcrt_spawn(MSVCRT__P_WAIT
, comspec
, fullcmd
, NULL
, 1);
1220 HeapFree(GetProcessHeap(), 0, comspec
);
1221 HeapFree(GetProcessHeap(), 0, fullcmd
);
1225 /*********************************************************************
1228 int CDECL
MSVCRT_system(const char* cmd
)
1231 MSVCRT_wchar_t
*cmdW
;
1233 if ((cmdW
= msvcrt_wstrdupa(cmd
)))
1235 res
= _wsystem(cmdW
);
1236 HeapFree(GetProcessHeap(), 0, cmdW
);
1241 /*********************************************************************
1242 * _loaddll (MSVCRT.@)
1244 MSVCRT_intptr_t CDECL
_loaddll(const char* dllname
)
1246 return (MSVCRT_intptr_t
)LoadLibraryA(dllname
);
1249 /*********************************************************************
1250 * _unloaddll (MSVCRT.@)
1252 int CDECL
_unloaddll(MSVCRT_intptr_t dll
)
1254 if (FreeLibrary((HMODULE
)dll
))
1258 int err
= GetLastError();
1259 msvcrt_set_errno(err
);
1264 /*********************************************************************
1265 * _getdllprocaddr (MSVCRT.@)
1267 void * CDECL
_getdllprocaddr(MSVCRT_intptr_t dll
, const char *name
, int ordinal
)
1271 if (ordinal
!= -1) return NULL
;
1272 return GetProcAddress( (HMODULE
)dll
, name
);
1274 if (HIWORD(ordinal
)) return NULL
;
1275 return GetProcAddress( (HMODULE
)dll
, (LPCSTR
)(ULONG_PTR
)ordinal
);