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
36 #include "wine/debug.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
, *end
;
48 unsigned int i
, name_len
, path_len
;
52 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
54 end
= name
+ MAX_PATH
- 1;
55 for(p
= name
; p
< end
; p
++)
59 /* FIXME extra-long names are silently truncated */
60 memcpy(buffer
, name
, name_len
* sizeof(MSVCRT_wchar_t
));
61 buffer
[name_len
] = '\0';
63 /* try current dir first */
64 if (GetFileAttributesW(buffer
) != INVALID_FILE_ATTRIBUTES
)
66 MSVCRT_wcscpy(fullname
, buffer
);
70 for (p
--; p
>= name
; p
--)
71 if (*p
== '\\' || *p
== '/' || *p
== ':' || *p
== '.') break;
73 /* if there's no extension, try some well-known extensions */
74 if ((p
< name
|| *p
!= '.') && name_len
<= MAX_PATH
- 5)
76 for (i
= 0; i
< 4; i
++)
78 memcpy(buffer
+ name_len
, suffix
[i
], 5 * sizeof(MSVCRT_wchar_t
));
79 if (GetFileAttributesW(buffer
) != INVALID_FILE_ATTRIBUTES
)
81 MSVCRT_wcscpy(fullname
, buffer
);
88 if (!use_path
|| !(env
= MSVCRT__wgetenv(path
))) return;
90 /* now try search path */
94 while (*p
&& *p
!= ';') p
++;
98 if (path_len
+ name_len
<= MAX_PATH
- 2)
100 memcpy(buffer
, env
, path_len
* sizeof(MSVCRT_wchar_t
));
101 if (buffer
[path_len
] != '/' && buffer
[path_len
] != '\\')
103 buffer
[path_len
++] = '\\';
104 buffer
[path_len
] = '\0';
106 else buffer
[path_len
] = '\0';
108 MSVCRT_wcscat(buffer
, name
);
109 if (GetFileAttributesW(buffer
) != INVALID_FILE_ATTRIBUTES
)
111 MSVCRT_wcscpy(fullname
, buffer
);
115 /* again, if there's no extension, try some well-known extensions */
116 if (!extension
&& path_len
+ name_len
<= MAX_PATH
- 5)
118 for (i
= 0; i
< 4; i
++)
120 memcpy(buffer
+ path_len
+ name_len
, suffix
[i
], 5 * sizeof(MSVCRT_wchar_t
));
121 if (GetFileAttributesW(buffer
) != INVALID_FILE_ATTRIBUTES
)
123 MSVCRT_wcscpy(fullname
, buffer
);
128 env
= *p
? p
+ 1 : p
;
132 static MSVCRT_intptr_t
msvcrt_spawn(int flags
, const MSVCRT_wchar_t
* exe
, MSVCRT_wchar_t
* cmdline
,
133 MSVCRT_wchar_t
* env
, int use_path
)
136 PROCESS_INFORMATION pi
;
137 MSVCRT_wchar_t fullname
[MAX_PATH
];
138 DWORD create_flags
= CREATE_UNICODE_ENVIRONMENT
;
140 TRACE("%x %s %s %s %d\n", flags
, debugstr_w(exe
), debugstr_w(cmdline
), debugstr_w(env
), use_path
);
142 if ((unsigned)flags
> MSVCRT__P_DETACH
)
144 *MSVCRT__errno() = MSVCRT_EINVAL
;
148 msvcrt_search_executable(exe
, fullname
, use_path
);
150 memset(&si
, 0, sizeof(si
));
152 msvcrt_create_io_inherit_block(&si
.cbReserved2
, &si
.lpReserved2
);
153 if (flags
== MSVCRT__P_DETACH
) create_flags
|= DETACHED_PROCESS
;
154 if (!CreateProcessW(fullname
, cmdline
, NULL
, NULL
, TRUE
,
155 create_flags
, env
, NULL
, &si
, &pi
))
157 msvcrt_set_errno(GetLastError());
158 MSVCRT_free(si
.lpReserved2
);
162 MSVCRT_free(si
.lpReserved2
);
166 WaitForSingleObject(pi
.hProcess
, INFINITE
);
167 GetExitCodeProcess(pi
.hProcess
,&pi
.dwProcessId
);
168 CloseHandle(pi
.hProcess
);
169 CloseHandle(pi
.hThread
);
170 return pi
.dwProcessId
;
171 case MSVCRT__P_DETACH
:
172 CloseHandle(pi
.hProcess
);
175 case MSVCRT__P_NOWAIT
:
176 case MSVCRT__P_NOWAITO
:
177 CloseHandle(pi
.hThread
);
178 return (MSVCRT_intptr_t
)pi
.hProcess
;
179 case MSVCRT__P_OVERLAY
:
182 return -1; /* can't reach here */
185 /* INTERNAL: Convert wide argv list to a single 'delim'-separated wide string, with an
186 * extra '\0' to terminate it.
188 static MSVCRT_wchar_t
* msvcrt_argvtos(const MSVCRT_wchar_t
* const* arg
, MSVCRT_wchar_t delim
)
190 const MSVCRT_wchar_t
* const* a
;
197 /* Return NULL for an empty environment list */
206 size
+= MSVCRT_wcslen(*a
) + 1;
210 ret
= MSVCRT_malloc((size
+ 1) * sizeof(MSVCRT_wchar_t
));
219 int len
= MSVCRT_wcslen(*a
);
220 memcpy(p
,*a
,len
* sizeof(MSVCRT_wchar_t
));
225 if (delim
&& p
> ret
) p
[-1] = 0;
230 /* INTERNAL: Convert ansi argv list to a single 'delim'-separated wide string, with an
231 * extra '\0' to terminate it.
233 static MSVCRT_wchar_t
*msvcrt_argvtos_aw(const char * const *arg
, MSVCRT_wchar_t delim
)
235 const char * const *a
;
237 MSVCRT_wchar_t
*p
, *ret
;
241 /* Return NULL for an empty environment list */
250 len
+= MultiByteToWideChar(CP_ACP
, 0, *a
, -1, NULL
, 0);
254 ret
= MSVCRT_malloc((len
+ 1) * sizeof(MSVCRT_wchar_t
));
263 p
+= MultiByteToWideChar(CP_ACP
, 0, *a
, strlen(*a
), p
, len
- (p
- ret
));
267 if (delim
&& p
> ret
) p
[-1] = 0;
272 /* INTERNAL: Convert wide va_list to a single 'delim'-separated wide string, with an
273 * extra '\0' to terminate it.
275 static MSVCRT_wchar_t
*msvcrt_valisttos(const MSVCRT_wchar_t
*arg0
, __ms_va_list alist
, MSVCRT_wchar_t delim
)
277 unsigned int size
= 0, pos
= 0;
278 const MSVCRT_wchar_t
*arg
;
279 MSVCRT_wchar_t
*new, *ret
= NULL
;
281 for (arg
= arg0
; arg
; arg
= va_arg( alist
, MSVCRT_wchar_t
* ))
283 unsigned int len
= MSVCRT_wcslen( arg
) + 1;
284 if (pos
+ len
>= size
)
286 size
= max( 256, size
* 2 );
287 size
= max( size
, pos
+ len
+ 1 );
288 if (!(new = MSVCRT_realloc( ret
, size
* sizeof(MSVCRT_wchar_t
) )))
295 MSVCRT_wcscpy( ret
+ pos
, arg
);
297 ret
[pos
- 1] = delim
;
301 if (delim
) ret
[pos
- 1] = 0;
307 /* INTERNAL: Convert ansi va_list to a single 'delim'-separated wide string, with an
308 * extra '\0' to terminate it.
310 static MSVCRT_wchar_t
*msvcrt_valisttos_aw(const char *arg0
, __ms_va_list alist
, MSVCRT_wchar_t delim
)
312 unsigned int size
= 0, pos
= 0;
314 MSVCRT_wchar_t
*new, *ret
= NULL
;
316 for (arg
= arg0
; arg
; arg
= va_arg( alist
, char * ))
318 unsigned int len
= MultiByteToWideChar( CP_ACP
, 0, arg
, -1, NULL
, 0 );
319 if (pos
+ len
>= size
)
321 size
= max( 256, size
* 2 );
322 size
= max( size
, pos
+ len
+ 1 );
323 if (!(new = MSVCRT_realloc( ret
, size
* sizeof(MSVCRT_wchar_t
) )))
330 pos
+= MultiByteToWideChar( CP_ACP
, 0, arg
, -1, ret
+ pos
, size
- pos
);
331 ret
[pos
- 1] = delim
;
335 if (delim
) ret
[pos
- 1] = 0;
341 /* INTERNAL: retrieve COMSPEC environment variable */
342 static MSVCRT_wchar_t
*msvcrt_get_comspec(void)
344 static const MSVCRT_wchar_t cmd
[] = {'c','m','d',0};
345 static const MSVCRT_wchar_t comspec
[] = {'C','O','M','S','P','E','C',0};
349 if (!(len
= GetEnvironmentVariableW(comspec
, NULL
, 0))) len
= ARRAY_SIZE(cmd
);
350 if ((ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(MSVCRT_wchar_t
))))
352 if (!GetEnvironmentVariableW(comspec
, ret
, len
)) MSVCRT_wcscpy(ret
, cmd
);
357 /*********************************************************************
360 MSVCRT_intptr_t CDECL
_cwait(int *status
, MSVCRT_intptr_t pid
, int action
)
362 HANDLE hPid
= (HANDLE
)pid
;
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 WINAPIV
_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 WINAPIV
_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 WINAPIV
_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 WINAPIV
_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 WINAPIV
_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 WINAPIV
_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 WINAPIV
_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 WINAPIV
_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
, const MSVCRT_wchar_t
* const* argv
)
605 return MSVCRT__wspawnve(MSVCRT__P_OVERLAY
, name
, argv
, NULL
);
608 /*********************************************************************
611 * Like on Windows, this function does not handle arguments with spaces
614 MSVCRT_intptr_t CDECL
_execv(const char* name
, const char* const* argv
)
616 return MSVCRT__spawnve(MSVCRT__P_OVERLAY
, name
, argv
, NULL
);
619 /*********************************************************************
620 * _wexecve (MSVCRT.@)
622 * Unicode version of _execve
624 MSVCRT_intptr_t CDECL
_wexecve(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
, const MSVCRT_wchar_t
* const* envv
)
626 return MSVCRT__wspawnve(MSVCRT__P_OVERLAY
, name
, 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
, const char* const* argv
, const char* const* envv
)
637 return MSVCRT__spawnve(MSVCRT__P_OVERLAY
, name
, argv
, envv
);
640 /*********************************************************************
641 * _wexecvpe (MSVCRT.@)
643 * Unicode version of _execvpe
645 MSVCRT_intptr_t CDECL
_wexecvpe(const MSVCRT_wchar_t
* name
, const MSVCRT_wchar_t
* const* argv
, const MSVCRT_wchar_t
* const* envv
)
647 return MSVCRT__wspawnvpe(MSVCRT__P_OVERLAY
, name
, 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
, const char* const* argv
, const char* const* envv
)
658 return MSVCRT__spawnvpe(MSVCRT__P_OVERLAY
, name
, argv
, envv
);
661 /*********************************************************************
662 * _wexecvp (MSVCRT.@)
664 * Unicode version of _execvp
666 MSVCRT_intptr_t CDECL
_wexecvp(const MSVCRT_wchar_t
* name
, const 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
, const char* const* argv
)
679 return _execvpe(name
, argv
, NULL
);
682 /*********************************************************************
683 * _wspawnl (MSVCRT.@)
685 * Unicode version of _spawnl
687 MSVCRT_intptr_t WINAPIV
MSVCRT__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 WINAPIV
MSVCRT__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 WINAPIV
MSVCRT__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 WINAPIV
MSVCRT__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 WINAPIV
MSVCRT__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 WINAPIV
MSVCRT__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 WINAPIV
MSVCRT__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 WINAPIV
MSVCRT__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
MSVCRT__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
MSVCRT__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
MSVCRT__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
MSVCRT__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
= *MSVCRT___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
= MSVCRT_wcslen(comspec
) + MSVCRT_wcslen(flag
) + MSVCRT_wcslen(command
) + 1;
1115 if (!(fullcmd
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(MSVCRT_wchar_t
))))
1117 HeapFree(GetProcessHeap(), 0, comspec
);
1121 MSVCRT_wcscpy(fullcmd
, comspec
);
1122 MSVCRT_wcscat(fullcmd
, flag
);
1123 MSVCRT_wcscat(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
= MSVCRT_wcslen(comspec
) + MSVCRT_wcslen(flag
) + MSVCRT_wcslen(cmd
) + 1;
1249 if (!(fullcmd
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(MSVCRT_wchar_t
))))
1251 HeapFree(GetProcessHeap(), 0, comspec
);
1254 MSVCRT_wcscpy(fullcmd
, comspec
);
1255 MSVCRT_wcscat(fullcmd
, flag
);
1256 MSVCRT_wcscat(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
);
1321 /*********************************************************************
1322 * _getpid (MSVCRT.@)
1324 int CDECL
_getpid(void)
1326 return GetCurrentProcessId();
1330 /*********************************************************************
1331 * __crtTerminateProcess (MSVCR110.@)
1333 int CDECL
MSVCR110__crtTerminateProcess(UINT exit_code
)
1335 return TerminateProcess(GetCurrentProcess(), exit_code
);