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
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
42 static void msvcrt_search_executable(const wchar_t *name
, wchar_t *fullname
, int use_path
)
44 static const wchar_t suffix
[][5] =
45 {L
".com", L
".exe", L
".bat", L
".cmd"};
47 wchar_t buffer
[MAX_PATH
];
48 const wchar_t *env
, *p
, *end
;
49 unsigned int i
, name_len
, path_len
;
53 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
55 end
= name
+ MAX_PATH
- 1;
56 for(p
= name
; p
< end
; p
++)
60 /* FIXME extra-long names are silently truncated */
61 memcpy(buffer
, name
, name_len
* sizeof(wchar_t));
62 buffer
[name_len
] = '\0';
64 /* try current dir first */
65 if (GetFileAttributesW(buffer
) != INVALID_FILE_ATTRIBUTES
)
67 wcscpy(fullname
, buffer
);
71 for (p
--; p
>= name
; p
--)
72 if (*p
== '\\' || *p
== '/' || *p
== ':' || *p
== '.') break;
74 /* if there's no extension, try some well-known extensions */
75 if ((p
< name
|| *p
!= '.') && name_len
<= MAX_PATH
- 5)
77 for (i
= 0; i
< 4; i
++)
79 memcpy(buffer
+ name_len
, suffix
[i
], 5 * sizeof(wchar_t));
80 if (GetFileAttributesW(buffer
) != INVALID_FILE_ATTRIBUTES
)
82 wcscpy(fullname
, buffer
);
89 if (!use_path
|| !(env
= _wgetenv(L
"PATH"))) return;
91 /* now try search path */
95 while (*p
&& *p
!= ';') p
++;
99 if (path_len
+ name_len
<= MAX_PATH
- 2)
101 memcpy(buffer
, env
, path_len
* sizeof(wchar_t));
102 if (buffer
[path_len
] != '/' && buffer
[path_len
] != '\\')
104 buffer
[path_len
++] = '\\';
105 buffer
[path_len
] = '\0';
107 else buffer
[path_len
] = '\0';
109 wcscat(buffer
, name
);
110 if (GetFileAttributesW(buffer
) != INVALID_FILE_ATTRIBUTES
)
112 wcscpy(fullname
, buffer
);
116 /* again, if there's no extension, try some well-known extensions */
117 if (!extension
&& path_len
+ name_len
<= MAX_PATH
- 5)
119 for (i
= 0; i
< 4; i
++)
121 memcpy(buffer
+ path_len
+ name_len
, suffix
[i
], 5 * sizeof(wchar_t));
122 if (GetFileAttributesW(buffer
) != INVALID_FILE_ATTRIBUTES
)
124 wcscpy(fullname
, buffer
);
129 env
= *p
? p
+ 1 : p
;
133 static intptr_t msvcrt_spawn(int flags
, const wchar_t* exe
, wchar_t* cmdline
,
134 wchar_t* env
, int use_path
)
137 PROCESS_INFORMATION pi
;
138 wchar_t fullname
[MAX_PATH
];
139 DWORD create_flags
= CREATE_UNICODE_ENVIRONMENT
;
141 TRACE("%x %s %s %s %d\n", flags
, debugstr_w(exe
), debugstr_w(cmdline
), debugstr_w(env
), use_path
);
143 if ((unsigned)flags
> _P_DETACH
)
149 msvcrt_search_executable(exe
, fullname
, use_path
);
151 memset(&si
, 0, sizeof(si
));
153 msvcrt_create_io_inherit_block(&si
.cbReserved2
, &si
.lpReserved2
);
154 if (flags
== _P_DETACH
) create_flags
|= DETACHED_PROCESS
;
155 if (!CreateProcessW(fullname
, cmdline
, NULL
, NULL
, TRUE
,
156 create_flags
, env
, NULL
, &si
, &pi
))
158 msvcrt_set_errno(GetLastError());
159 free(si
.lpReserved2
);
163 free(si
.lpReserved2
);
167 WaitForSingleObject(pi
.hProcess
, INFINITE
);
168 GetExitCodeProcess(pi
.hProcess
,&pi
.dwProcessId
);
169 CloseHandle(pi
.hProcess
);
170 CloseHandle(pi
.hThread
);
171 return pi
.dwProcessId
;
173 CloseHandle(pi
.hProcess
);
178 CloseHandle(pi
.hThread
);
179 return (intptr_t)pi
.hProcess
;
183 return -1; /* can't reach here */
186 /* INTERNAL: Convert wide argv list to a single 'delim'-separated wide string, with an
187 * extra '\0' to terminate it.
189 static wchar_t* msvcrt_argvtos(const wchar_t* const* arg
, wchar_t delim
)
191 const wchar_t* const* a
;
198 /* Return NULL for an empty environment list */
207 size
+= wcslen(*a
) + 1;
211 ret
= malloc((size
+ 1) * sizeof(wchar_t));
220 int len
= wcslen(*a
);
221 memcpy(p
,*a
,len
* sizeof(wchar_t));
226 if (delim
&& p
> ret
) p
[-1] = 0;
231 /* INTERNAL: Convert ansi argv list to a single 'delim'-separated wide string, with an
232 * extra '\0' to terminate it.
234 static wchar_t *msvcrt_argvtos_aw(const char * const *arg
, wchar_t delim
)
236 const char * const *a
;
242 /* Return NULL for an empty environment list */
251 len
+= MultiByteToWideChar(CP_ACP
, 0, *a
, -1, NULL
, 0);
255 ret
= malloc((len
+ 1) * sizeof(wchar_t));
264 p
+= MultiByteToWideChar(CP_ACP
, 0, *a
, strlen(*a
), p
, len
- (p
- ret
));
268 if (delim
&& p
> ret
) p
[-1] = 0;
273 /* INTERNAL: Convert wide va_list to a single 'delim'-separated wide string, with an
274 * extra '\0' to terminate it.
276 static wchar_t *msvcrt_valisttos(const wchar_t *arg0
, va_list alist
, wchar_t delim
)
278 unsigned int size
= 0, pos
= 0;
280 wchar_t *new, *ret
= NULL
;
282 for (arg
= arg0
; arg
; arg
= va_arg( alist
, wchar_t * ))
284 unsigned int len
= wcslen( arg
) + 1;
285 if (pos
+ len
>= size
)
287 size
= max( 256, size
* 2 );
288 size
= max( size
, pos
+ len
+ 1 );
289 if (!(new = realloc( ret
, size
* sizeof(wchar_t) )))
296 wcscpy( ret
+ pos
, arg
);
298 ret
[pos
- 1] = delim
;
302 if (delim
) ret
[pos
- 1] = 0;
308 /* INTERNAL: Convert ansi va_list to a single 'delim'-separated wide string, with an
309 * extra '\0' to terminate it.
311 static wchar_t *msvcrt_valisttos_aw(const char *arg0
, va_list alist
, wchar_t delim
)
313 unsigned int size
= 0, pos
= 0;
315 wchar_t *new, *ret
= NULL
;
317 for (arg
= arg0
; arg
; arg
= va_arg( alist
, char * ))
319 unsigned int len
= MultiByteToWideChar( CP_ACP
, 0, arg
, -1, NULL
, 0 );
320 if (pos
+ len
>= size
)
322 size
= max( 256, size
* 2 );
323 size
= max( size
, pos
+ len
+ 1 );
324 if (!(new = realloc( ret
, size
* sizeof(wchar_t) )))
331 pos
+= MultiByteToWideChar( CP_ACP
, 0, arg
, -1, ret
+ pos
, size
- pos
);
332 ret
[pos
- 1] = delim
;
336 if (delim
) ret
[pos
- 1] = 0;
342 /* INTERNAL: retrieve COMSPEC environment variable */
343 static wchar_t *msvcrt_get_comspec(void)
348 if (!(len
= GetEnvironmentVariableW(L
"COMSPEC", NULL
, 0))) len
= 4;
349 if ((ret
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(wchar_t))))
351 if (!GetEnvironmentVariableW(L
"COMSPEC", ret
, len
)) wcscpy(ret
, L
"cmd");
356 /*********************************************************************
359 intptr_t CDECL
_cwait(int *status
, intptr_t pid
, int action
)
361 HANDLE hPid
= (HANDLE
)pid
;
364 if (!WaitForSingleObject(hPid
, INFINITE
))
369 GetExitCodeProcess(hPid
, &stat
);
374 doserrno
= GetLastError();
376 if (doserrno
== ERROR_INVALID_HANDLE
)
379 *__doserrno() = doserrno
;
382 msvcrt_set_errno(doserrno
);
384 return status
? *status
= -1 : -1;
387 /*********************************************************************
390 * Unicode version of _execl
392 intptr_t WINAPIV
_wexecl(const wchar_t* name
, const wchar_t* arg0
, ...)
399 args
= msvcrt_valisttos(arg0
, ap
, ' ');
402 ret
= msvcrt_spawn(_P_OVERLAY
, name
, args
, NULL
, 0);
408 /*********************************************************************
411 * Like on Windows, this function does not handle arguments with spaces
414 intptr_t WINAPIV
_execl(const char* name
, const char* arg0
, ...)
417 wchar_t *nameW
, *args
;
420 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
423 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
426 ret
= msvcrt_spawn(_P_OVERLAY
, nameW
, args
, NULL
, 0);
433 /*********************************************************************
434 * _wexecle (MSVCRT.@)
436 * Unicode version of _execle
438 intptr_t WINAPIV
_wexecle(const wchar_t* name
, const wchar_t* arg0
, ...)
441 wchar_t *args
, *envs
= NULL
;
442 const wchar_t * const *envp
;
446 args
= msvcrt_valisttos(arg0
, ap
, ' ');
450 while (va_arg( ap
, wchar_t * ) != NULL
) /*nothing*/;
451 envp
= va_arg( ap
, const wchar_t * const * );
452 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
455 ret
= msvcrt_spawn(_P_OVERLAY
, name
, args
, envs
, 0);
462 /*********************************************************************
465 intptr_t WINAPIV
_execle(const char* name
, const char* arg0
, ...)
468 wchar_t *nameW
, *args
, *envs
= NULL
;
469 const char * const *envp
;
472 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
475 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
479 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
480 envp
= va_arg( ap
, const char * const * );
481 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
484 ret
= msvcrt_spawn(_P_OVERLAY
, nameW
, args
, envs
, 0);
492 /*********************************************************************
493 * _wexeclp (MSVCRT.@)
495 * Unicode version of _execlp
497 intptr_t WINAPIV
_wexeclp(const wchar_t* name
, const wchar_t* arg0
, ...)
504 args
= msvcrt_valisttos(arg0
, ap
, ' ');
507 ret
= msvcrt_spawn(_P_OVERLAY
, name
, args
, NULL
, 1);
513 /*********************************************************************
516 * Like on Windows, this function does not handle arguments with spaces
519 intptr_t WINAPIV
_execlp(const char* name
, const char* arg0
, ...)
522 wchar_t *nameW
, *args
;
525 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
528 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
531 ret
= msvcrt_spawn(_P_OVERLAY
, nameW
, args
, NULL
, 1);
538 /*********************************************************************
539 * _wexeclpe (MSVCRT.@)
541 * Unicode version of _execlpe
543 intptr_t WINAPIV
_wexeclpe(const wchar_t* name
, const wchar_t* arg0
, ...)
546 wchar_t *args
, *envs
= NULL
;
547 const wchar_t * const *envp
;
551 args
= msvcrt_valisttos(arg0
, ap
, ' ');
555 while (va_arg( ap
, wchar_t * ) != NULL
) /*nothing*/;
556 envp
= va_arg( ap
, const wchar_t * const * );
557 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
560 ret
= msvcrt_spawn(_P_OVERLAY
, name
, args
, envs
, 1);
567 /*********************************************************************
568 * _execlpe (MSVCRT.@)
570 intptr_t WINAPIV
_execlpe(const char* name
, const char* arg0
, ...)
573 wchar_t *nameW
, *args
, *envs
= NULL
;
574 const char * const *envp
;
577 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
580 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
584 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
585 envp
= va_arg( ap
, const char * const * );
586 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
589 ret
= msvcrt_spawn(_P_OVERLAY
, nameW
, args
, envs
, 1);
597 /*********************************************************************
600 * Unicode version of _execv
602 intptr_t CDECL
_wexecv(const wchar_t* name
, const wchar_t* const* argv
)
604 return _wspawnve(_P_OVERLAY
, name
, argv
, NULL
);
607 /*********************************************************************
610 * Like on Windows, this function does not handle arguments with spaces
613 intptr_t CDECL
_execv(const char* name
, const char* const* argv
)
615 return _spawnve(_P_OVERLAY
, name
, argv
, NULL
);
618 /*********************************************************************
619 * _wexecve (MSVCRT.@)
621 * Unicode version of _execve
623 intptr_t CDECL
_wexecve(const wchar_t* name
, const wchar_t* const* argv
, const wchar_t* const* envv
)
625 return _wspawnve(_P_OVERLAY
, name
, argv
, envv
);
628 /*********************************************************************
631 * Like on Windows, this function does not handle arguments with spaces
634 intptr_t CDECL
_execve(const char* name
, const char* const* argv
, const char* const* envv
)
636 return _spawnve(_P_OVERLAY
, name
, argv
, envv
);
639 /*********************************************************************
640 * _wexecvpe (MSVCRT.@)
642 * Unicode version of _execvpe
644 intptr_t CDECL
_wexecvpe(const wchar_t* name
, const wchar_t* const* argv
, const wchar_t* const* envv
)
646 return _wspawnvpe(_P_OVERLAY
, name
, argv
, envv
);
649 /*********************************************************************
650 * _execvpe (MSVCRT.@)
652 * Like on Windows, this function does not handle arguments with spaces
655 intptr_t CDECL
_execvpe(const char* name
, const char* const* argv
, const char* const* envv
)
657 return _spawnvpe(_P_OVERLAY
, name
, argv
, envv
);
660 /*********************************************************************
661 * _wexecvp (MSVCRT.@)
663 * Unicode version of _execvp
665 intptr_t CDECL
_wexecvp(const wchar_t* name
, const wchar_t* const* argv
)
667 return _wexecvpe(name
, argv
, NULL
);
670 /*********************************************************************
673 * Like on Windows, this function does not handle arguments with spaces
676 intptr_t CDECL
_execvp(const char* name
, const char* const* argv
)
678 return _execvpe(name
, argv
, NULL
);
681 /*********************************************************************
682 * _wspawnl (MSVCRT.@)
684 * Unicode version of _spawnl
686 intptr_t WINAPIV
_wspawnl(int flags
, const wchar_t* name
, const wchar_t* arg0
, ...)
693 args
= msvcrt_valisttos(arg0
, ap
, ' ');
696 ret
= msvcrt_spawn(flags
, name
, args
, NULL
, 0);
702 /*********************************************************************
705 * Like on Windows, this function does not handle arguments with spaces
708 intptr_t WINAPIV
_spawnl(int flags
, const char* name
, const char* arg0
, ...)
711 wchar_t *nameW
, *args
;
714 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
717 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
720 ret
= msvcrt_spawn(flags
, nameW
, args
, NULL
, 0);
727 /*********************************************************************
728 * _wspawnle (MSVCRT.@)
730 * Unicode version of _spawnle
732 intptr_t WINAPIV
_wspawnle(int flags
, const wchar_t* name
, const wchar_t* arg0
, ...)
735 wchar_t *args
, *envs
= NULL
;
736 const wchar_t * const *envp
;
740 args
= msvcrt_valisttos(arg0
, ap
, ' ');
744 while (va_arg( ap
, wchar_t * ) != NULL
) /*nothing*/;
745 envp
= va_arg( ap
, const wchar_t * const * );
746 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
749 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 0);
756 /*********************************************************************
757 * _spawnle (MSVCRT.@)
759 intptr_t WINAPIV
_spawnle(int flags
, const char* name
, const char* arg0
, ...)
762 wchar_t *nameW
, *args
, *envs
= NULL
;
763 const char * const *envp
;
766 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
769 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
773 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
774 envp
= va_arg( ap
, const char * const * );
775 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
778 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 0);
786 /*********************************************************************
787 * _wspawnlp (MSVCRT.@)
789 * Unicode version of _spawnlp
791 intptr_t WINAPIV
_wspawnlp(int flags
, const wchar_t* name
, const wchar_t* arg0
, ...)
798 args
= msvcrt_valisttos(arg0
, ap
, ' ');
801 ret
= msvcrt_spawn(flags
, name
, args
, NULL
, 1);
807 /*********************************************************************
808 * _spawnlp (MSVCRT.@)
810 * Like on Windows, this function does not handle arguments with spaces
813 intptr_t WINAPIV
_spawnlp(int flags
, const char* name
, const char* arg0
, ...)
816 wchar_t *nameW
, *args
;
819 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
822 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
825 ret
= msvcrt_spawn(flags
, nameW
, args
, NULL
, 1);
832 /*********************************************************************
833 * _wspawnlpe (MSVCRT.@)
835 * Unicode version of _spawnlpe
837 intptr_t WINAPIV
_wspawnlpe(int flags
, const wchar_t* name
, const wchar_t* arg0
, ...)
840 wchar_t *args
, *envs
= NULL
;
841 const wchar_t * const *envp
;
845 args
= msvcrt_valisttos(arg0
, ap
, ' ');
849 while (va_arg( ap
, wchar_t * ) != NULL
) /*nothing*/;
850 envp
= va_arg( ap
, const wchar_t * const * );
851 if (envp
) envs
= msvcrt_argvtos(envp
, 0);
854 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 1);
861 /*********************************************************************
862 * _spawnlpe (MSVCRT.@)
864 intptr_t WINAPIV
_spawnlpe(int flags
, const char* name
, const char* arg0
, ...)
867 wchar_t *nameW
, *args
, *envs
= NULL
;
868 const char * const *envp
;
871 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
874 args
= msvcrt_valisttos_aw(arg0
, ap
, ' ');
878 while (va_arg( ap
, char * ) != NULL
) /*nothing*/;
879 envp
= va_arg( ap
, const char * const * );
880 if (envp
) envs
= msvcrt_argvtos_aw(envp
, 0);
883 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 1);
891 /*********************************************************************
892 * _spawnve (MSVCRT.@)
894 * Like on Windows, this function does not handle arguments with spaces
897 intptr_t CDECL
_spawnve(int flags
, const char* name
, const char* const* argv
,
898 const char* const* envv
)
900 wchar_t *nameW
, *args
, *envs
;
903 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
905 args
= msvcrt_argvtos_aw(argv
, ' ');
906 envs
= msvcrt_argvtos_aw(envv
, 0);
908 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 0);
916 /*********************************************************************
917 * _wspawnve (MSVCRT.@)
919 * Unicode version of _spawnve
921 intptr_t CDECL
_wspawnve(int flags
, const wchar_t* name
, const wchar_t* const* argv
,
922 const wchar_t* const* envv
)
924 wchar_t *args
, *envs
;
927 args
= msvcrt_argvtos(argv
, ' ');
928 envs
= msvcrt_argvtos(envv
, 0);
930 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 0);
937 /*********************************************************************
940 * Like on Windows, this function does not handle arguments with spaces
943 intptr_t CDECL
_spawnv(int flags
, const char* name
, const char* const* argv
)
945 return _spawnve(flags
, name
, argv
, NULL
);
948 /*********************************************************************
949 * _wspawnv (MSVCRT.@)
951 * Unicode version of _spawnv
953 intptr_t CDECL
_wspawnv(int flags
, const wchar_t* name
, const wchar_t* const* argv
)
955 return _wspawnve(flags
, name
, argv
, NULL
);
958 /*********************************************************************
959 * _spawnvpe (MSVCRT.@)
961 * Like on Windows, this function does not handle arguments with spaces
964 intptr_t CDECL
_spawnvpe(int flags
, const char* name
, const char* const* argv
,
965 const char* const* envv
)
967 wchar_t *nameW
, *args
, *envs
;
970 if (!(nameW
= msvcrt_wstrdupa(name
))) return -1;
972 args
= msvcrt_argvtos_aw(argv
, ' ');
973 envs
= msvcrt_argvtos_aw(envv
, 0);
975 ret
= msvcrt_spawn(flags
, nameW
, args
, envs
, 1);
983 /*********************************************************************
984 * _wspawnvpe (MSVCRT.@)
986 * Unicode version of _spawnvpe
988 intptr_t CDECL
_wspawnvpe(int flags
, const wchar_t* name
, const wchar_t* const* argv
,
989 const wchar_t* const* envv
)
991 wchar_t *args
, *envs
;
994 args
= msvcrt_argvtos(argv
, ' ');
995 envs
= msvcrt_argvtos(envv
, 0);
997 ret
= msvcrt_spawn(flags
, name
, args
, envs
, 1);
1004 /*********************************************************************
1005 * _spawnvp (MSVCRT.@)
1007 * Like on Windows, this function does not handle arguments with spaces
1010 intptr_t CDECL
_spawnvp(int flags
, const char* name
, const char* const* argv
)
1012 return _spawnvpe(flags
, name
, argv
, NULL
);
1015 /*********************************************************************
1016 * _wspawnvp (MSVCRT.@)
1018 * Unicode version of _spawnvp
1020 intptr_t CDECL
_wspawnvp(int flags
, const wchar_t* name
, const wchar_t* const* argv
)
1022 return _wspawnvpe(flags
, name
, argv
, NULL
);
1025 static struct popen_handle
{
1029 static DWORD popen_handles_size
;
1031 void msvcrt_free_popen_data(void)
1033 free(popen_handles
);
1036 /*********************************************************************
1037 * _wpopen (MSVCRT.@)
1039 * Unicode version of _popen
1041 FILE* CDECL
_wpopen(const wchar_t* command
, const wchar_t* mode
)
1043 wchar_t *comspec
, *fullcmd
, fullname
[MAX_PATH
];
1044 int textmode
, fds
[2], fd_parent
, fd_child
;
1045 struct popen_handle
*container
;
1046 PROCESS_INFORMATION pi
;
1047 BOOL read_pipe
= TRUE
;
1055 TRACE("(command=%s, mode=%s)\n", debugstr_w(command
), debugstr_w(mode
));
1057 if (!command
|| !mode
)
1060 _get_fmode(&textmode
);
1061 textmode
&= _O_BINARY
| _O_TEXT
;
1062 textmode
|= _O_NOINHERIT
;
1063 for (p
= mode
; *p
; p
++)
1073 textmode
|= _O_BINARY
;
1074 textmode
&= ~_O_TEXT
;
1078 textmode
|= _O_TEXT
;
1079 textmode
&= ~_O_BINARY
;
1083 if (_pipe(fds
, 0, textmode
) == -1)
1089 fd_child
= _dup(fds
[1]);
1095 fd_child
= _dup(fds
[0]);
1103 ret
= _wfdopen(fd_parent
, mode
);
1111 for (i
= 0; i
< popen_handles_size
; i
++)
1113 if (!popen_handles
[i
].f
)
1116 if (i
== popen_handles_size
)
1118 i
= (popen_handles_size
? popen_handles_size
* 2 : 8);
1119 container
= realloc(popen_handles
, i
* sizeof(*container
));
1120 if (!container
) goto error
;
1122 popen_handles
= container
;
1123 container
= popen_handles
+ popen_handles_size
;
1124 memset(container
, 0, (i
- popen_handles_size
) * sizeof(*container
));
1125 popen_handles_size
= i
;
1127 else container
= popen_handles
+ i
;
1129 if (!(comspec
= msvcrt_get_comspec())) goto error
;
1130 len
= wcslen(comspec
) + wcslen(command
) + 5;
1132 if (!(fullcmd
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(wchar_t))))
1134 HeapFree(GetProcessHeap(), 0, comspec
);
1138 wcscpy(fullcmd
, comspec
);
1139 wcscat(fullcmd
, L
" /c ");
1140 wcscat(fullcmd
, command
);
1141 msvcrt_search_executable(comspec
, fullname
, 1);
1143 memset(&si
, 0, sizeof(si
));
1145 si
.dwFlags
= STARTF_USESTDHANDLES
;
1148 si
.hStdInput
= (HANDLE
)_get_osfhandle(STDIN_FILENO
);
1149 si
.hStdOutput
= (HANDLE
)_get_osfhandle(fd_child
);
1153 si
.hStdInput
= (HANDLE
)_get_osfhandle(fd_child
);
1154 si
.hStdOutput
= (HANDLE
)_get_osfhandle(STDOUT_FILENO
);
1156 si
.hStdError
= (HANDLE
)_get_osfhandle(STDERR_FILENO
);
1157 r
= CreateProcessW(fullname
, fullcmd
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &si
, &pi
);
1158 HeapFree(GetProcessHeap(), 0, comspec
);
1159 HeapFree(GetProcessHeap(), 0, fullcmd
);
1162 msvcrt_set_errno(GetLastError());
1165 CloseHandle(pi
.hThread
);
1167 container
->proc
= pi
.hProcess
;
1169 _unlock(_POPEN_LOCK
);
1173 _unlock(_POPEN_LOCK
);
1179 /*********************************************************************
1182 FILE* CDECL
_popen(const char* command
, const char* mode
)
1185 wchar_t *cmdW
, *modeW
;
1187 TRACE("(command=%s, mode=%s)\n", debugstr_a(command
), debugstr_a(mode
));
1189 if (!command
|| !mode
)
1192 if (!(cmdW
= msvcrt_wstrdupa(command
))) return NULL
;
1193 if (!(modeW
= msvcrt_wstrdupa(mode
)))
1199 ret
= _wpopen(cmdW
, modeW
);
1206 /*********************************************************************
1207 * _pclose (MSVCRT.@)
1209 int CDECL
_pclose(FILE* file
)
1214 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return -1;
1217 for(i
=0; i
<popen_handles_size
; i
++)
1219 if (popen_handles
[i
].f
== file
)
1222 if(i
== popen_handles_size
)
1224 _unlock(_POPEN_LOCK
);
1229 h
= popen_handles
[i
].proc
;
1230 popen_handles
[i
].f
= NULL
;
1231 _unlock(_POPEN_LOCK
);
1234 if(WaitForSingleObject(h
, INFINITE
)==WAIT_FAILED
|| !GetExitCodeProcess(h
, &i
))
1236 msvcrt_set_errno(GetLastError());
1245 /*********************************************************************
1246 * _wsystem (MSVCRT.@)
1248 * Unicode version of system
1250 int CDECL
_wsystem(const wchar_t* cmd
)
1253 wchar_t *comspec
, *fullcmd
;
1256 comspec
= msvcrt_get_comspec();
1260 if (comspec
== NULL
)
1265 HeapFree(GetProcessHeap(), 0, comspec
);
1269 if (comspec
== NULL
)
1272 len
= wcslen(comspec
) + wcslen(cmd
) + 5;
1274 if (!(fullcmd
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(wchar_t))))
1276 HeapFree(GetProcessHeap(), 0, comspec
);
1279 wcscpy(fullcmd
, comspec
);
1280 wcscat(fullcmd
, L
" /c ");
1281 wcscat(fullcmd
, cmd
);
1283 res
= msvcrt_spawn(_P_WAIT
, comspec
, fullcmd
, NULL
, 1);
1285 HeapFree(GetProcessHeap(), 0, comspec
);
1286 HeapFree(GetProcessHeap(), 0, fullcmd
);
1290 /*********************************************************************
1293 int CDECL
system(const char* cmd
)
1299 return _wsystem(NULL
);
1301 if ((cmdW
= msvcrt_wstrdupa(cmd
)))
1303 res
= _wsystem(cmdW
);
1309 /*********************************************************************
1310 * _loaddll (MSVCRT.@)
1312 intptr_t CDECL
_loaddll(const char* dllname
)
1314 return (intptr_t)LoadLibraryA(dllname
);
1317 /*********************************************************************
1318 * _unloaddll (MSVCRT.@)
1320 int CDECL
_unloaddll(intptr_t dll
)
1322 if (FreeLibrary((HMODULE
)dll
))
1326 int err
= GetLastError();
1327 msvcrt_set_errno(err
);
1332 /*********************************************************************
1333 * _getdllprocaddr (MSVCRT.@)
1335 void * CDECL
_getdllprocaddr(intptr_t dll
, const char *name
, int ordinal
)
1339 if (ordinal
!= -1) return NULL
;
1340 return GetProcAddress( (HMODULE
)dll
, name
);
1342 if (HIWORD(ordinal
)) return NULL
;
1343 return GetProcAddress( (HMODULE
)dll
, (LPCSTR
)(ULONG_PTR
)ordinal
);
1346 /*********************************************************************
1347 * _getpid (MSVCRT.@)
1349 int CDECL
_getpid(void)
1351 return GetCurrentProcessId();
1355 /*********************************************************************
1356 * __crtTerminateProcess (MSVCR110.@)
1358 int CDECL
__crtTerminateProcess(UINT exit_code
)
1360 return TerminateProcess(GetCurrentProcess(), exit_code
);