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 if (!WaitForSingleObject(hPid
, INFINITE
))
368 GetExitCodeProcess(hPid
, &stat
);
373 doserrno
= GetLastError();
375 if (doserrno
== ERROR_INVALID_HANDLE
)
377 *MSVCRT__errno() = MSVCRT_ECHILD
;
378 *MSVCRT___doserrno() = doserrno
;
381 msvcrt_set_errno(doserrno
);
383 return status
? *status
= -1 : -1;
386 /*********************************************************************
389 * Unicode version of _execl
391 MSVCRT_intptr_t CDECL
_wexecl(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
394 MSVCRT_wchar_t
*args
;
397 __ms_va_start(ap
, arg0
);
398 args
= msvcrt_valisttos(arg0
, ap
, ' ');
401 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, name
, args
, NULL
, 0);
407 /*********************************************************************
410 * Like on Windows, this function does not handle arguments with spaces
413 MSVCRT_intptr_t CDECL
_execl(const char* name
, const char* arg0
, ...)
416 MSVCRT_wchar_t
*nameW
, *args
;
419 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
421 __ms_va_start(ap
, arg0
);
422 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
425 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, nameW
, args
, NULL
, 0);
432 /*********************************************************************
433 * _wexecle (MSVCRT.@)
435 * Unicode version of _execle
437 MSVCRT_intptr_t CDECL
_wexecle(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
440 MSVCRT_wchar_t
*args
, *envs
= NULL
;
441 const MSVCRT_wchar_t
* const *envp
;
444 __ms_va_start(ap
, arg0
);
445 args
= msvcrt_valisttos(arg0
, ap
, ' ');
448 __ms_va_start(ap
, arg0
);
449 while (va_arg( ap
, MSVCRT_wchar_t
* ) != NULL
) /*nothing*/;
450 envp
= va_arg( ap
, const MSVCRT_wchar_t
* const * );
451 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
454 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, name
, args
, envs
, 0);
461 /*********************************************************************
464 MSVCRT_intptr_t CDECL
_execle(const char* name
, const char* arg0
, ...)
467 MSVCRT_wchar_t
*nameW
, *args
, *envs
= NULL
;
468 const char * const *envp
;
471 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
473 __ms_va_start(ap
, arg0
);
474 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
477 __ms_va_start(ap
, arg0
);
478 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
479 envp
= va_arg( ap
, const char * const * );
480 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
483 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, nameW
, args
, envs
, 0);
491 /*********************************************************************
492 * _wexeclp (MSVCRT.@)
494 * Unicode version of _execlp
496 MSVCRT_intptr_t CDECL
_wexeclp(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
499 MSVCRT_wchar_t
*args
;
502 __ms_va_start(ap
, arg0
);
503 args
= msvcrt_valisttos(arg0
, ap
, ' ');
506 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, name
, args
, NULL
, 1);
512 /*********************************************************************
515 * Like on Windows, this function does not handle arguments with spaces
518 MSVCRT_intptr_t CDECL
_execlp(const char* name
, const char* arg0
, ...)
521 MSVCRT_wchar_t
*nameW
, *args
;
524 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
526 __ms_va_start(ap
, arg0
);
527 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
530 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, nameW
, args
, NULL
, 1);
537 /*********************************************************************
538 * _wexeclpe (MSVCRT.@)
540 * Unicode version of _execlpe
542 MSVCRT_intptr_t CDECL
_wexeclpe(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
545 MSVCRT_wchar_t
*args
, *envs
= NULL
;
546 const MSVCRT_wchar_t
* const *envp
;
549 __ms_va_start(ap
, arg0
);
550 args
= msvcrt_valisttos(arg0
, ap
, ' ');
553 __ms_va_start(ap
, arg0
);
554 while (va_arg( ap
, MSVCRT_wchar_t
* ) != NULL
) /*nothing*/;
555 envp
= va_arg( ap
, const MSVCRT_wchar_t
* const * );
556 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
559 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, name
, args
, envs
, 1);
566 /*********************************************************************
567 * _execlpe (MSVCRT.@)
569 MSVCRT_intptr_t CDECL
_execlpe(const char* name
, const char* arg0
, ...)
572 MSVCRT_wchar_t
*nameW
, *args
, *envs
= NULL
;
573 const char * const *envp
;
576 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
578 __ms_va_start(ap
, arg0
);
579 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
582 __ms_va_start(ap
, arg0
);
583 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
584 envp
= va_arg( ap
, const char * const * );
585 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
588 ret
= msvcrt_spawn(MSVCRT__P_OVERLAY
, nameW
, args
, envs
, 1);
596 /*********************************************************************
599 * Unicode version of _execv
601 MSVCRT_intptr_t CDECL
_wexecv(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
)
603 return MSVCRT__wspawnve(MSVCRT__P_OVERLAY
, name
, argv
, NULL
);
606 /*********************************************************************
609 * Like on Windows, this function does not handle arguments with spaces
612 MSVCRT_intptr_t CDECL
_execv(const char* name
, const char* const* argv
)
614 return MSVCRT__spawnve(MSVCRT__P_OVERLAY
, name
, argv
, NULL
);
617 /*********************************************************************
618 * _wexecve (MSVCRT.@)
620 * Unicode version of _execve
622 MSVCRT_intptr_t CDECL
_wexecve(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
, const MSVCRT_wchar_t
* const* envv
)
624 return MSVCRT__wspawnve(MSVCRT__P_OVERLAY
, name
, argv
, envv
);
627 /*********************************************************************
630 * Like on Windows, this function does not handle arguments with spaces
633 MSVCRT_intptr_t CDECL
MSVCRT__execve(const char* name
, const char* const* argv
, const char* const* envv
)
635 return MSVCRT__spawnve(MSVCRT__P_OVERLAY
, name
, argv
, envv
);
638 /*********************************************************************
639 * _wexecvpe (MSVCRT.@)
641 * Unicode version of _execvpe
643 MSVCRT_intptr_t CDECL
_wexecvpe(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
, const MSVCRT_wchar_t
* const* envv
)
645 return MSVCRT__wspawnvpe(MSVCRT__P_OVERLAY
, name
, argv
, envv
);
648 /*********************************************************************
649 * _execvpe (MSVCRT.@)
651 * Like on Windows, this function does not handle arguments with spaces
654 MSVCRT_intptr_t CDECL
_execvpe(const char* name
, const char* const* argv
, const char* const* envv
)
656 return MSVCRT__spawnvpe(MSVCRT__P_OVERLAY
, name
, argv
, envv
);
659 /*********************************************************************
660 * _wexecvp (MSVCRT.@)
662 * Unicode version of _execvp
664 MSVCRT_intptr_t CDECL
_wexecvp(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
)
666 return _wexecvpe(name
, argv
, NULL
);
669 /*********************************************************************
672 * Like on Windows, this function does not handle arguments with spaces
675 MSVCRT_intptr_t CDECL
_execvp(const char* name
, const char* const* argv
)
677 return _execvpe(name
, argv
, NULL
);
680 /*********************************************************************
681 * _wspawnl (MSVCRT.@)
683 * Unicode version of _spawnl
685 MSVCRT_intptr_t CDECL
_wspawnl(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
688 MSVCRT_wchar_t
*args
;
691 __ms_va_start(ap
, arg0
);
692 args
= msvcrt_valisttos(arg0
, ap
, ' ');
695 ret
= msvcrt_spawn(flags
, name
, args
, NULL
, 0);
701 /*********************************************************************
704 * Like on Windows, this function does not handle arguments with spaces
707 MSVCRT_intptr_t CDECL
_spawnl(int flags
, const char* name
, const char* arg0
, ...)
710 MSVCRT_wchar_t
*nameW
, *args
;
713 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
715 __ms_va_start(ap
, arg0
);
716 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
719 ret
= msvcrt_spawn(flags
, nameW
, args
, NULL
, 0);
726 /*********************************************************************
727 * _wspawnle (MSVCRT.@)
729 * Unicode version of _spawnle
731 MSVCRT_intptr_t CDECL
_wspawnle(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
734 MSVCRT_wchar_t
*args
, *envs
= NULL
;
735 const MSVCRT_wchar_t
* const *envp
;
738 __ms_va_start(ap
, arg0
);
739 args
= msvcrt_valisttos(arg0
, ap
, ' ');
742 __ms_va_start(ap
, arg0
);
743 while (va_arg( ap
, MSVCRT_wchar_t
* ) != NULL
) /*nothing*/;
744 envp
= va_arg( ap
, const MSVCRT_wchar_t
* const * );
745 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
748 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 0);
755 /*********************************************************************
756 * _spawnle (MSVCRT.@)
758 MSVCRT_intptr_t CDECL
_spawnle(int flags
, const char* name
, const char* arg0
, ...)
761 MSVCRT_wchar_t
*nameW
, *args
, *envs
= NULL
;
762 const char * const *envp
;
765 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
767 __ms_va_start(ap
, arg0
);
768 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
771 __ms_va_start(ap
, arg0
);
772 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
773 envp
= va_arg( ap
, const char * const * );
774 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
777 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 0);
785 /*********************************************************************
786 * _wspawnlp (MSVCRT.@)
788 * Unicode version of _spawnlp
790 MSVCRT_intptr_t CDECL
_wspawnlp(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
793 MSVCRT_wchar_t
*args
;
796 __ms_va_start(ap
, arg0
);
797 args
= msvcrt_valisttos(arg0
, ap
, ' ');
800 ret
= msvcrt_spawn(flags
, name
, args
, NULL
, 1);
806 /*********************************************************************
807 * _spawnlp (MSVCRT.@)
809 * Like on Windows, this function does not handle arguments with spaces
812 MSVCRT_intptr_t CDECL
_spawnlp(int flags
, const char* name
, const char* arg0
, ...)
815 MSVCRT_wchar_t
*nameW
, *args
;
818 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
820 __ms_va_start(ap
, arg0
);
821 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
824 ret
= msvcrt_spawn(flags
, nameW
, args
, NULL
, 1);
831 /*********************************************************************
832 * _wspawnlpe (MSVCRT.@)
834 * Unicode version of _spawnlpe
836 MSVCRT_intptr_t CDECL
_wspawnlpe(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* arg0
, ...)
839 MSVCRT_wchar_t
*args
, *envs
= NULL
;
840 const MSVCRT_wchar_t
* const *envp
;
843 __ms_va_start(ap
, arg0
);
844 args
= msvcrt_valisttos(arg0
, ap
, ' ');
847 __ms_va_start(ap
, arg0
);
848 while (va_arg( ap
, MSVCRT_wchar_t
* ) != NULL
) /*nothing*/;
849 envp
= va_arg( ap
, const MSVCRT_wchar_t
* const * );
850 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
853 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 1);
860 /*********************************************************************
861 * _spawnlpe (MSVCRT.@)
863 MSVCRT_intptr_t CDECL
_spawnlpe(int flags
, const char* name
, const char* arg0
, ...)
866 MSVCRT_wchar_t
*nameW
, *args
, *envs
= NULL
;
867 const char * const *envp
;
870 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
872 __ms_va_start(ap
, arg0
);
873 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
876 __ms_va_start(ap
, arg0
);
877 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
878 envp
= va_arg( ap
, const char * const * );
879 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
882 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 1);
890 /*********************************************************************
891 * _spawnve (MSVCRT.@)
893 * Like on Windows, this function does not handle arguments with spaces
896 MSVCRT_intptr_t CDECL
MSVCRT__spawnve(int flags
, const char* name
, const char* const* argv
,
897 const char* const* envv
)
899 MSVCRT_wchar_t
*nameW
, *args
, *envs
;
902 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
904 args
= msvcrt_argvtos_aw(argv
, ' ');
905 envs
= msvcrt_argvtos_aw(envv
, 0);
907 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 0);
915 /*********************************************************************
916 * _wspawnve (MSVCRT.@)
918 * Unicode version of _spawnve
920 MSVCRT_intptr_t CDECL
MSVCRT__wspawnve(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
,
921 const MSVCRT_wchar_t
* const* envv
)
923 MSVCRT_wchar_t
*args
, *envs
;
926 args
= msvcrt_argvtos(argv
, ' ');
927 envs
= msvcrt_argvtos(envv
, 0);
929 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 0);
936 /*********************************************************************
939 * Like on Windows, this function does not handle arguments with spaces
942 MSVCRT_intptr_t CDECL
_spawnv(int flags
, const char* name
, const char* const* argv
)
944 return MSVCRT__spawnve(flags
, name
, argv
, NULL
);
947 /*********************************************************************
948 * _wspawnv (MSVCRT.@)
950 * Unicode version of _spawnv
952 MSVCRT_intptr_t CDECL
_wspawnv(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
)
954 return MSVCRT__wspawnve(flags
, name
, argv
, NULL
);
957 /*********************************************************************
958 * _spawnvpe (MSVCRT.@)
960 * Like on Windows, this function does not handle arguments with spaces
963 MSVCRT_intptr_t CDECL
MSVCRT__spawnvpe(int flags
, const char* name
, const char* const* argv
,
964 const char* const* envv
)
966 MSVCRT_wchar_t
*nameW
, *args
, *envs
;
969 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
971 args
= msvcrt_argvtos_aw(argv
, ' ');
972 envs
= msvcrt_argvtos_aw(envv
, 0);
974 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 1);
982 /*********************************************************************
983 * _wspawnvpe (MSVCRT.@)
985 * Unicode version of _spawnvpe
987 MSVCRT_intptr_t CDECL
MSVCRT__wspawnvpe(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
,
988 const MSVCRT_wchar_t
* const* envv
)
990 MSVCRT_wchar_t
*args
, *envs
;
993 args
= msvcrt_argvtos(argv
, ' ');
994 envs
= msvcrt_argvtos(envv
, 0);
996 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 1);
1003 /*********************************************************************
1004 * _spawnvp (MSVCRT.@)
1006 * Like on Windows, this function does not handle arguments with spaces
1009 MSVCRT_intptr_t CDECL
_spawnvp(int flags
, const char* name
, const char* const* argv
)
1011 return MSVCRT__spawnvpe(flags
, name
, argv
, NULL
);
1014 /*********************************************************************
1015 * _wspawnvp (MSVCRT.@)
1017 * Unicode version of _spawnvp
1019 MSVCRT_intptr_t CDECL
_wspawnvp(int flags
, const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
)
1021 return MSVCRT__wspawnvpe(flags
, name
, argv
, NULL
);
1024 static struct popen_handle
{
1028 static DWORD popen_handles_size
;
1030 void msvcrt_free_popen_data(void)
1032 MSVCRT_free(popen_handles
);
1035 /*********************************************************************
1036 * _wpopen (MSVCRT.@)
1038 * Unicode version of _popen
1040 MSVCRT_FILE
* CDECL
MSVCRT__wpopen(const MSVCRT_wchar_t
* command
, const MSVCRT_wchar_t
* mode
)
1043 BOOL readPipe
= TRUE
;
1044 int textmode
, fds
[2], fdToDup
, fdToOpen
, fdStdHandle
= -1;
1045 const MSVCRT_wchar_t
*p
;
1046 MSVCRT_wchar_t
*comspec
, *fullcmd
;
1048 static const MSVCRT_wchar_t flag
[] = {' ','/','c',' ',0};
1049 struct popen_handle
*container
;
1052 TRACE("(command=%s, mode=%s)\n", debugstr_w(command
), debugstr_w(mode
));
1054 if (!command
|| !mode
)
1057 textmode
= *__p__fmode() & (MSVCRT__O_BINARY
| MSVCRT__O_TEXT
);
1058 for (p
= mode
; *p
; p
++)
1068 textmode
|= MSVCRT__O_BINARY
;
1069 textmode
&= ~MSVCRT__O_TEXT
;
1073 textmode
|= MSVCRT__O_TEXT
;
1074 textmode
&= ~MSVCRT__O_BINARY
;
1078 if (MSVCRT__pipe(fds
, 0, textmode
) == -1)
1081 fdToDup
= readPipe
? 1 : 0;
1082 fdToOpen
= readPipe
? 0 : 1;
1084 _mlock(_POPEN_LOCK
);
1085 for(i
=0; i
<popen_handles_size
; i
++)
1087 if (!popen_handles
[i
].f
)
1090 if (i
==popen_handles_size
)
1092 i
= (popen_handles_size
? popen_handles_size
*2 : 8);
1093 container
= MSVCRT_realloc(popen_handles
, i
*sizeof(*container
));
1094 if (!container
) goto error
;
1096 popen_handles
= container
;
1097 container
= popen_handles
+popen_handles_size
;
1098 memset(container
, 0, (i
-popen_handles_size
)*sizeof(*container
));
1099 popen_handles_size
= i
;
1101 else container
= popen_handles
+i
;
1103 if ((fdStdHandle
= MSVCRT__dup(fdToDup
)) == -1)
1105 if (MSVCRT__dup2(fds
[fdToDup
], fdToDup
) != 0)
1108 MSVCRT__close(fds
[fdToDup
]);
1110 if (!(comspec
= msvcrt_get_comspec())) goto error
;
1111 len
= strlenW(comspec
) + strlenW(flag
) + strlenW(command
) + 1;
1113 if (!(fullcmd
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(MSVCRT_wchar_t
))))
1115 HeapFree(GetProcessHeap(), 0, comspec
);
1119 strcpyW(fullcmd
, comspec
);
1120 strcatW(fullcmd
, flag
);
1121 strcatW(fullcmd
, command
);
1123 if ((container
->proc
= (HANDLE
)msvcrt_spawn(MSVCRT__P_NOWAIT
, comspec
, fullcmd
, NULL
, 1))
1124 == INVALID_HANDLE_VALUE
)
1126 MSVCRT__close(fds
[fdToOpen
]);
1131 ret
= MSVCRT__wfdopen(fds
[fdToOpen
], mode
);
1133 MSVCRT__close(fds
[fdToOpen
]);
1136 _munlock(_POPEN_LOCK
);
1137 HeapFree(GetProcessHeap(), 0, comspec
);
1138 HeapFree(GetProcessHeap(), 0, fullcmd
);
1139 MSVCRT__dup2(fdStdHandle
, fdToDup
);
1140 MSVCRT__close(fdStdHandle
);
1144 _munlock(_POPEN_LOCK
);
1145 if (fdStdHandle
!= -1) MSVCRT__close(fdStdHandle
);
1146 MSVCRT__close(fds
[0]);
1147 MSVCRT__close(fds
[1]);
1151 /*********************************************************************
1154 MSVCRT_FILE
* CDECL
MSVCRT__popen(const char* command
, const char* mode
)
1157 MSVCRT_wchar_t
*cmdW
, *modeW
;
1159 TRACE("(command=%s, mode=%s)\n", debugstr_a(command
), debugstr_a(mode
));
1161 if (!command
|| !mode
)
1164 if (!(cmdW
= msvcrt_wstrdupa(command
))) return NULL
;
1165 if (!(modeW
= msvcrt_wstrdupa(mode
)))
1167 HeapFree(GetProcessHeap(), 0, cmdW
);
1171 ret
= MSVCRT__wpopen(cmdW
, modeW
);
1173 HeapFree(GetProcessHeap(), 0, cmdW
);
1174 HeapFree(GetProcessHeap(), 0, modeW
);
1178 /*********************************************************************
1179 * _pclose (MSVCRT.@)
1181 int CDECL
MSVCRT__pclose(MSVCRT_FILE
* file
)
1186 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return -1;
1188 _mlock(_POPEN_LOCK
);
1189 for(i
=0; i
<popen_handles_size
; i
++)
1191 if (popen_handles
[i
].f
== file
)
1194 if(i
== popen_handles_size
)
1196 _munlock(_POPEN_LOCK
);
1197 *MSVCRT__errno() = MSVCRT_EBADF
;
1201 h
= popen_handles
[i
].proc
;
1202 popen_handles
[i
].f
= NULL
;
1203 _munlock(_POPEN_LOCK
);
1205 MSVCRT_fclose(file
);
1206 if(WaitForSingleObject(h
, INFINITE
)==WAIT_FAILED
|| !GetExitCodeProcess(h
, &i
))
1208 msvcrt_set_errno(GetLastError());
1217 /*********************************************************************
1218 * _wsystem (MSVCRT.@)
1220 * Unicode version of system
1222 int CDECL
_wsystem(const MSVCRT_wchar_t
* cmd
)
1225 MSVCRT_wchar_t
*comspec
, *fullcmd
;
1227 static const MSVCRT_wchar_t flag
[] = {' ','/','c',' ',0};
1229 comspec
= msvcrt_get_comspec();
1233 if (comspec
== NULL
)
1235 *MSVCRT__errno() = MSVCRT_ENOENT
;
1238 HeapFree(GetProcessHeap(), 0, comspec
);
1242 if ( comspec
== NULL
)
1245 len
= strlenW(comspec
) + strlenW(flag
) + strlenW(cmd
) + 1;
1247 if (!(fullcmd
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(MSVCRT_wchar_t
))))
1249 HeapFree(GetProcessHeap(), 0, comspec
);
1252 strcpyW(fullcmd
, comspec
);
1253 strcatW(fullcmd
, flag
);
1254 strcatW(fullcmd
, cmd
);
1256 res
= msvcrt_spawn(MSVCRT__P_WAIT
, comspec
, fullcmd
, NULL
, 1);
1258 HeapFree(GetProcessHeap(), 0, comspec
);
1259 HeapFree(GetProcessHeap(), 0, fullcmd
);
1263 /*********************************************************************
1266 int CDECL
MSVCRT_system(const char* cmd
)
1269 MSVCRT_wchar_t
*cmdW
;
1272 return _wsystem(NULL
);
1274 if ((cmdW
= msvcrt_wstrdupa(cmd
)))
1276 res
= _wsystem(cmdW
);
1277 HeapFree(GetProcessHeap(), 0, cmdW
);
1282 /*********************************************************************
1283 * _loaddll (MSVCRT.@)
1285 MSVCRT_intptr_t CDECL
_loaddll(const char* dllname
)
1287 return (MSVCRT_intptr_t
)LoadLibraryA(dllname
);
1290 /*********************************************************************
1291 * _unloaddll (MSVCRT.@)
1293 int CDECL
_unloaddll(MSVCRT_intptr_t dll
)
1295 if (FreeLibrary((HMODULE
)dll
))
1299 int err
= GetLastError();
1300 msvcrt_set_errno(err
);
1305 /*********************************************************************
1306 * _getdllprocaddr (MSVCRT.@)
1308 void * CDECL
_getdllprocaddr(MSVCRT_intptr_t dll
, const char *name
, int ordinal
)
1312 if (ordinal
!= -1) return NULL
;
1313 return GetProcAddress( (HMODULE
)dll
, name
);
1315 if (HIWORD(ordinal
)) return NULL
;
1316 return GetProcAddress( (HMODULE
)dll
, (LPCSTR
)(ULONG_PTR
)ordinal
);
1319 /*********************************************************************
1320 * _getpid (MSVCRT.@)
1322 int CDECL
_getpid(void)
1324 return GetCurrentProcessId();