directmanipulation: Return S_OK form viewport_SetViewportOptions stub.
[wine/zf.git] / dlls / msvcrt / process.c
blob82f1a1ac59489ade27d39890710688bbaa0b6fa1
1 /*
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
24 * FIXME:
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
29 #include "config.h"
31 #include <stdarg.h>
33 #include "msvcrt.h"
34 #include <winnls.h>
35 #include "mtdll.h"
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;
49 int extension = 1;
51 *fullname = '\0';
52 msvcrt_set_errno(ERROR_FILE_NOT_FOUND);
54 end = name + MAX_PATH - 1;
55 for(p = name; p < end; p++)
56 if(!*p) break;
57 name_len = p - name;
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);
67 return;
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);
82 return;
85 extension = 0;
88 if (!use_path || !(env = MSVCRT__wgetenv(path))) return;
90 /* now try search path */
93 p = env;
94 while (*p && *p != ';') p++;
95 if (p == env) return;
97 path_len = p - env;
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);
112 return;
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);
124 return;
128 env = *p ? p + 1 : p;
129 } while(1);
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)
135 STARTUPINFOW si;
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;
145 return -1;
148 msvcrt_search_executable(exe, fullname, use_path);
150 memset(&si, 0, sizeof(si));
151 si.cb = 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);
159 return -1;
162 MSVCRT_free(si.lpReserved2);
163 switch(flags)
165 case MSVCRT__P_WAIT:
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);
173 pi.hProcess = 0;
174 /* fall through */
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:
180 MSVCRT__exit(0);
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;
191 int size;
192 MSVCRT_wchar_t* p;
193 MSVCRT_wchar_t* ret;
195 if (!arg)
197 /* Return NULL for an empty environment list */
198 return NULL;
201 /* get length */
202 a = arg;
203 size = 0;
204 while (*a)
206 size += MSVCRT_wcslen(*a) + 1;
207 a++;
210 ret = MSVCRT_malloc((size + 1) * sizeof(MSVCRT_wchar_t));
211 if (!ret)
212 return NULL;
214 /* fill string */
215 a = arg;
216 p = ret;
217 while (*a)
219 int len = MSVCRT_wcslen(*a);
220 memcpy(p,*a,len * sizeof(MSVCRT_wchar_t));
221 p += len;
222 *p++ = delim;
223 a++;
225 if (delim && p > ret) p[-1] = 0;
226 else *p = 0;
227 return ret;
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;
236 unsigned int len;
237 MSVCRT_wchar_t *p, *ret;
239 if (!arg)
241 /* Return NULL for an empty environment list */
242 return NULL;
245 /* get length */
246 a = arg;
247 len = 0;
248 while (*a)
250 len += MultiByteToWideChar(CP_ACP, 0, *a, -1, NULL, 0);
251 a++;
254 ret = MSVCRT_malloc((len + 1) * sizeof(MSVCRT_wchar_t));
255 if (!ret)
256 return NULL;
258 /* fill string */
259 a = arg;
260 p = ret;
261 while (*a)
263 p += MultiByteToWideChar(CP_ACP, 0, *a, strlen(*a), p, len - (p - ret));
264 *p++ = delim;
265 a++;
267 if (delim && p > ret) p[-1] = 0;
268 else *p = 0;
269 return ret;
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) )))
290 MSVCRT_free( ret );
291 return NULL;
293 ret = new;
295 MSVCRT_wcscpy( ret + pos, arg );
296 pos += len;
297 ret[pos - 1] = delim;
299 if (pos)
301 if (delim) ret[pos - 1] = 0;
302 else ret[pos] = 0;
304 return ret;
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;
313 const char *arg;
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) )))
325 MSVCRT_free( ret );
326 return NULL;
328 ret = new;
330 pos += MultiByteToWideChar( CP_ACP, 0, arg, -1, ret + pos, size - pos );
331 ret[pos - 1] = delim;
333 if (pos)
335 if (delim) ret[pos - 1] = 0;
336 else ret[pos] = 0;
338 return ret;
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};
346 MSVCRT_wchar_t *ret;
347 unsigned int len;
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);
354 return ret;
357 /*********************************************************************
358 * _cwait (MSVCRT.@)
360 MSVCRT_intptr_t CDECL _cwait(int *status, MSVCRT_intptr_t pid, int action)
362 HANDLE hPid = (HANDLE)pid;
363 int doserrno;
365 if (!WaitForSingleObject(hPid, INFINITE))
367 if (status)
369 DWORD stat;
370 GetExitCodeProcess(hPid, &stat);
371 *status = (int)stat;
373 return pid;
375 doserrno = GetLastError();
377 if (doserrno == ERROR_INVALID_HANDLE)
379 *MSVCRT__errno() = MSVCRT_ECHILD;
380 *MSVCRT___doserrno() = doserrno;
382 else
383 msvcrt_set_errno(doserrno);
385 return status ? *status = -1 : -1;
388 /*********************************************************************
389 * _wexecl (MSVCRT.@)
391 * Unicode version of _execl
393 MSVCRT_intptr_t WINAPIV _wexecl(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
395 __ms_va_list ap;
396 MSVCRT_wchar_t *args;
397 MSVCRT_intptr_t ret;
399 __ms_va_start(ap, arg0);
400 args = msvcrt_valisttos(arg0, ap, ' ');
401 __ms_va_end(ap);
403 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 0);
405 MSVCRT_free(args);
406 return ret;
409 /*********************************************************************
410 * _execl (MSVCRT.@)
412 * Like on Windows, this function does not handle arguments with spaces
413 * or double-quotes.
415 MSVCRT_intptr_t WINAPIV _execl(const char* name, const char* arg0, ...)
417 __ms_va_list ap;
418 MSVCRT_wchar_t *nameW, *args;
419 MSVCRT_intptr_t ret;
421 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
423 __ms_va_start(ap, arg0);
424 args = msvcrt_valisttos_aw(arg0, ap, ' ');
425 __ms_va_end(ap);
427 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 0);
429 MSVCRT_free(nameW);
430 MSVCRT_free(args);
431 return ret;
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, ...)
441 __ms_va_list ap;
442 MSVCRT_wchar_t *args, *envs = NULL;
443 const MSVCRT_wchar_t * const *envp;
444 MSVCRT_intptr_t ret;
446 __ms_va_start(ap, arg0);
447 args = msvcrt_valisttos(arg0, ap, ' ');
448 __ms_va_end(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);
454 __ms_va_end(ap);
456 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 0);
458 MSVCRT_free(args);
459 MSVCRT_free(envs);
460 return ret;
463 /*********************************************************************
464 * _execle (MSVCRT.@)
466 MSVCRT_intptr_t WINAPIV _execle(const char* name, const char* arg0, ...)
468 __ms_va_list ap;
469 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
470 const char * const *envp;
471 MSVCRT_intptr_t ret;
473 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
475 __ms_va_start(ap, arg0);
476 args = msvcrt_valisttos_aw(arg0, ap, ' ');
477 __ms_va_end(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);
483 __ms_va_end(ap);
485 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 0);
487 MSVCRT_free(nameW);
488 MSVCRT_free(args);
489 MSVCRT_free(envs);
490 return ret;
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, ...)
500 __ms_va_list ap;
501 MSVCRT_wchar_t *args;
502 MSVCRT_intptr_t ret;
504 __ms_va_start(ap, arg0);
505 args = msvcrt_valisttos(arg0, ap, ' ');
506 __ms_va_end(ap);
508 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 1);
510 MSVCRT_free(args);
511 return ret;
514 /*********************************************************************
515 * _execlp (MSVCRT.@)
517 * Like on Windows, this function does not handle arguments with spaces
518 * or double-quotes.
520 MSVCRT_intptr_t WINAPIV _execlp(const char* name, const char* arg0, ...)
522 __ms_va_list ap;
523 MSVCRT_wchar_t *nameW, *args;
524 MSVCRT_intptr_t ret;
526 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
528 __ms_va_start(ap, arg0);
529 args = msvcrt_valisttos_aw(arg0, ap, ' ');
530 __ms_va_end(ap);
532 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 1);
534 MSVCRT_free(nameW);
535 MSVCRT_free(args);
536 return ret;
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, ...)
546 __ms_va_list ap;
547 MSVCRT_wchar_t *args, *envs = NULL;
548 const MSVCRT_wchar_t * const *envp;
549 MSVCRT_intptr_t ret;
551 __ms_va_start(ap, arg0);
552 args = msvcrt_valisttos(arg0, ap, ' ');
553 __ms_va_end(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);
559 __ms_va_end(ap);
561 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 1);
563 MSVCRT_free(args);
564 MSVCRT_free(envs);
565 return ret;
568 /*********************************************************************
569 * _execlpe (MSVCRT.@)
571 MSVCRT_intptr_t WINAPIV _execlpe(const char* name, const char* arg0, ...)
573 __ms_va_list ap;
574 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
575 const char * const *envp;
576 MSVCRT_intptr_t ret;
578 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
580 __ms_va_start(ap, arg0);
581 args = msvcrt_valisttos_aw(arg0, ap, ' ');
582 __ms_va_end(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);
588 __ms_va_end(ap);
590 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 1);
592 MSVCRT_free(nameW);
593 MSVCRT_free(args);
594 MSVCRT_free(envs);
595 return ret;
598 /*********************************************************************
599 * _wexecv (MSVCRT.@)
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 /*********************************************************************
609 * _execv (MSVCRT.@)
611 * Like on Windows, this function does not handle arguments with spaces
612 * or double-quotes.
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 /*********************************************************************
630 * _execve (MSVCRT.@)
632 * Like on Windows, this function does not handle arguments with spaces
633 * or double-quotes.
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
654 * or double-quotes.
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 /*********************************************************************
672 * _execvp (MSVCRT.@)
674 * Like on Windows, this function does not handle arguments with spaces
675 * or double-quotes.
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, ...)
689 __ms_va_list ap;
690 MSVCRT_wchar_t *args;
691 MSVCRT_intptr_t ret;
693 __ms_va_start(ap, arg0);
694 args = msvcrt_valisttos(arg0, ap, ' ');
695 __ms_va_end(ap);
697 ret = msvcrt_spawn(flags, name, args, NULL, 0);
699 MSVCRT_free(args);
700 return ret;
703 /*********************************************************************
704 * _spawnl (MSVCRT.@)
706 * Like on Windows, this function does not handle arguments with spaces
707 * or double-quotes.
709 MSVCRT_intptr_t WINAPIV MSVCRT__spawnl(int flags, const char* name, const char* arg0, ...)
711 __ms_va_list ap;
712 MSVCRT_wchar_t *nameW, *args;
713 MSVCRT_intptr_t ret;
715 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
717 __ms_va_start(ap, arg0);
718 args = msvcrt_valisttos_aw(arg0, ap, ' ');
719 __ms_va_end(ap);
721 ret = msvcrt_spawn(flags, nameW, args, NULL, 0);
723 MSVCRT_free(nameW);
724 MSVCRT_free(args);
725 return ret;
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, ...)
735 __ms_va_list ap;
736 MSVCRT_wchar_t *args, *envs = NULL;
737 const MSVCRT_wchar_t * const *envp;
738 MSVCRT_intptr_t ret;
740 __ms_va_start(ap, arg0);
741 args = msvcrt_valisttos(arg0, ap, ' ');
742 __ms_va_end(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);
748 __ms_va_end(ap);
750 ret = msvcrt_spawn(flags, name, args, envs, 0);
752 MSVCRT_free(args);
753 MSVCRT_free(envs);
754 return ret;
757 /*********************************************************************
758 * _spawnle (MSVCRT.@)
760 MSVCRT_intptr_t WINAPIV MSVCRT__spawnle(int flags, const char* name, const char* arg0, ...)
762 __ms_va_list ap;
763 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
764 const char * const *envp;
765 MSVCRT_intptr_t ret;
767 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
769 __ms_va_start(ap, arg0);
770 args = msvcrt_valisttos_aw(arg0, ap, ' ');
771 __ms_va_end(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);
777 __ms_va_end(ap);
779 ret = msvcrt_spawn(flags, nameW, args, envs, 0);
781 MSVCRT_free(nameW);
782 MSVCRT_free(args);
783 MSVCRT_free(envs);
784 return ret;
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, ...)
794 __ms_va_list ap;
795 MSVCRT_wchar_t *args;
796 MSVCRT_intptr_t ret;
798 __ms_va_start(ap, arg0);
799 args = msvcrt_valisttos(arg0, ap, ' ');
800 __ms_va_end(ap);
802 ret = msvcrt_spawn(flags, name, args, NULL, 1);
804 MSVCRT_free(args);
805 return ret;
808 /*********************************************************************
809 * _spawnlp (MSVCRT.@)
811 * Like on Windows, this function does not handle arguments with spaces
812 * or double-quotes.
814 MSVCRT_intptr_t WINAPIV MSVCRT__spawnlp(int flags, const char* name, const char* arg0, ...)
816 __ms_va_list ap;
817 MSVCRT_wchar_t *nameW, *args;
818 MSVCRT_intptr_t ret;
820 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
822 __ms_va_start(ap, arg0);
823 args = msvcrt_valisttos_aw(arg0, ap, ' ');
824 __ms_va_end(ap);
826 ret = msvcrt_spawn(flags, nameW, args, NULL, 1);
828 MSVCRT_free(nameW);
829 MSVCRT_free(args);
830 return ret;
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, ...)
840 __ms_va_list ap;
841 MSVCRT_wchar_t *args, *envs = NULL;
842 const MSVCRT_wchar_t * const *envp;
843 MSVCRT_intptr_t ret;
845 __ms_va_start(ap, arg0);
846 args = msvcrt_valisttos(arg0, ap, ' ');
847 __ms_va_end(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);
853 __ms_va_end(ap);
855 ret = msvcrt_spawn(flags, name, args, envs, 1);
857 MSVCRT_free(args);
858 MSVCRT_free(envs);
859 return ret;
862 /*********************************************************************
863 * _spawnlpe (MSVCRT.@)
865 MSVCRT_intptr_t WINAPIV MSVCRT__spawnlpe(int flags, const char* name, const char* arg0, ...)
867 __ms_va_list ap;
868 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
869 const char * const *envp;
870 MSVCRT_intptr_t ret;
872 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
874 __ms_va_start(ap, arg0);
875 args = msvcrt_valisttos_aw(arg0, ap, ' ');
876 __ms_va_end(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);
882 __ms_va_end(ap);
884 ret = msvcrt_spawn(flags, nameW, args, envs, 1);
886 MSVCRT_free(nameW);
887 MSVCRT_free(args);
888 MSVCRT_free(envs);
889 return ret;
892 /*********************************************************************
893 * _spawnve (MSVCRT.@)
895 * Like on Windows, this function does not handle arguments with spaces
896 * or double-quotes.
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;
902 MSVCRT_intptr_t ret;
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);
911 MSVCRT_free(nameW);
912 MSVCRT_free(args);
913 MSVCRT_free(envs);
914 return ret;
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;
926 MSVCRT_intptr_t ret;
928 args = msvcrt_argvtos(argv, ' ');
929 envs = msvcrt_argvtos(envv, 0);
931 ret = msvcrt_spawn(flags, name, args, envs, 0);
933 MSVCRT_free(args);
934 MSVCRT_free(envs);
935 return ret;
938 /*********************************************************************
939 * _spawnv (MSVCRT.@)
941 * Like on Windows, this function does not handle arguments with spaces
942 * or double-quotes.
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
963 * or double-quotes.
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;
969 MSVCRT_intptr_t ret;
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);
978 MSVCRT_free(nameW);
979 MSVCRT_free(args);
980 MSVCRT_free(envs);
981 return ret;
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;
993 MSVCRT_intptr_t ret;
995 args = msvcrt_argvtos(argv, ' ');
996 envs = msvcrt_argvtos(envv, 0);
998 ret = msvcrt_spawn(flags, name, args, envs, 1);
1000 MSVCRT_free(args);
1001 MSVCRT_free(envs);
1002 return ret;
1005 /*********************************************************************
1006 * _spawnvp (MSVCRT.@)
1008 * Like on Windows, this function does not handle arguments with spaces
1009 * or double-quotes.
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 {
1027 MSVCRT_FILE *f;
1028 HANDLE proc;
1029 } *popen_handles;
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)
1044 MSVCRT_FILE *ret;
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;
1049 unsigned int len;
1050 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1051 struct popen_handle *container;
1052 DWORD i;
1054 TRACE("(command=%s, mode=%s)\n", debugstr_w(command), debugstr_w(mode));
1056 if (!command || !mode)
1057 return NULL;
1059 textmode = *MSVCRT___p__fmode() & (MSVCRT__O_BINARY | MSVCRT__O_TEXT);
1060 for (p = mode; *p; p++)
1062 switch (*p)
1064 case 'W':
1065 case 'w':
1066 readPipe = FALSE;
1067 break;
1068 case 'B':
1069 case 'b':
1070 textmode |= MSVCRT__O_BINARY;
1071 textmode &= ~MSVCRT__O_TEXT;
1072 break;
1073 case 'T':
1074 case 't':
1075 textmode |= MSVCRT__O_TEXT;
1076 textmode &= ~MSVCRT__O_BINARY;
1077 break;
1080 if (MSVCRT__pipe(fds, 0, textmode) == -1)
1081 return NULL;
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)
1090 break;
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)
1106 goto error;
1107 if (MSVCRT__dup2(fds[fdToDup], fdToDup) != 0)
1108 goto error;
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);
1118 goto error;
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]);
1129 ret = NULL;
1131 else
1133 ret = MSVCRT__wfdopen(fds[fdToOpen], mode);
1134 if (!ret)
1135 MSVCRT__close(fds[fdToOpen]);
1136 container->f = ret;
1138 _munlock(_POPEN_LOCK);
1139 HeapFree(GetProcessHeap(), 0, comspec);
1140 HeapFree(GetProcessHeap(), 0, fullcmd);
1141 MSVCRT__dup2(fdStdHandle, fdToDup);
1142 MSVCRT__close(fdStdHandle);
1143 return ret;
1145 error:
1146 _munlock(_POPEN_LOCK);
1147 if (fdStdHandle != -1) MSVCRT__close(fdStdHandle);
1148 MSVCRT__close(fds[0]);
1149 MSVCRT__close(fds[1]);
1150 return NULL;
1153 /*********************************************************************
1154 * _popen (MSVCRT.@)
1156 MSVCRT_FILE* CDECL MSVCRT__popen(const char* command, const char* mode)
1158 MSVCRT_FILE *ret;
1159 MSVCRT_wchar_t *cmdW, *modeW;
1161 TRACE("(command=%s, mode=%s)\n", debugstr_a(command), debugstr_a(mode));
1163 if (!command || !mode)
1164 return NULL;
1166 if (!(cmdW = msvcrt_wstrdupa(command))) return NULL;
1167 if (!(modeW = msvcrt_wstrdupa(mode)))
1169 HeapFree(GetProcessHeap(), 0, cmdW);
1170 return NULL;
1173 ret = MSVCRT__wpopen(cmdW, modeW);
1175 HeapFree(GetProcessHeap(), 0, cmdW);
1176 HeapFree(GetProcessHeap(), 0, modeW);
1177 return ret;
1180 /*********************************************************************
1181 * _pclose (MSVCRT.@)
1183 int CDECL MSVCRT__pclose(MSVCRT_FILE* file)
1185 HANDLE h;
1186 DWORD i;
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)
1194 break;
1196 if(i == popen_handles_size)
1198 _munlock(_POPEN_LOCK);
1199 *MSVCRT__errno() = MSVCRT_EBADF;
1200 return -1;
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());
1211 CloseHandle(h);
1212 return -1;
1215 CloseHandle(h);
1216 return i;
1219 /*********************************************************************
1220 * _wsystem (MSVCRT.@)
1222 * Unicode version of system
1224 int CDECL _wsystem(const MSVCRT_wchar_t* cmd)
1226 int res;
1227 MSVCRT_wchar_t *comspec, *fullcmd;
1228 unsigned int len;
1229 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1231 comspec = msvcrt_get_comspec();
1233 if (cmd == NULL)
1235 if (comspec == NULL)
1237 *MSVCRT__errno() = MSVCRT_ENOENT;
1238 return 0;
1240 HeapFree(GetProcessHeap(), 0, comspec);
1241 return 1;
1244 if ( comspec == NULL)
1245 return -1;
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);
1252 return -1;
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);
1262 return res;
1265 /*********************************************************************
1266 * system (MSVCRT.@)
1268 int CDECL MSVCRT_system(const char* cmd)
1270 int res = -1;
1271 MSVCRT_wchar_t *cmdW;
1273 if (cmd == NULL)
1274 return _wsystem(NULL);
1276 if ((cmdW = msvcrt_wstrdupa(cmd)))
1278 res = _wsystem(cmdW);
1279 HeapFree(GetProcessHeap(), 0, cmdW);
1281 return res;
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))
1298 return 0;
1299 else
1301 int err = GetLastError();
1302 msvcrt_set_errno(err);
1303 return err;
1307 /*********************************************************************
1308 * _getdllprocaddr (MSVCRT.@)
1310 void * CDECL _getdllprocaddr(MSVCRT_intptr_t dll, const char *name, int ordinal)
1312 if (name)
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();
1329 #if _MSVCR_VER>=110
1330 /*********************************************************************
1331 * __crtTerminateProcess (MSVCR110.@)
1333 int CDECL MSVCR110__crtTerminateProcess(UINT exit_code)
1335 return TerminateProcess(GetCurrentProcess(), exit_code);
1337 #endif