wined3d: Support getdc with user memory.
[wine.git] / dlls / msvcrt / process.c
blob4505b67e80409aee6114ce8892fb5a9b574e49e4
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 "mtdll.h"
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;
49 int extension = 1;
51 *fullname = '\0';
52 msvcrt_set_errno(ERROR_FILE_NOT_FOUND);
54 p = memchrW(name, '\0', MAX_PATH);
55 if (!p) p = name + MAX_PATH - 1;
56 name_len = p - name;
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);
66 return;
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);
81 return;
84 extension = 0;
87 if (!use_path || !(env = MSVCRT__wgetenv(path))) return;
89 /* now try search path */
92 p = env;
93 while (*p && *p != ';') p++;
94 if (p == env) return;
96 path_len = p - env;
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);
111 return;
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);
123 return;
127 env = *p ? p + 1 : p;
128 } while(1);
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)
134 STARTUPINFOW si;
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;
143 return -1;
146 msvcrt_search_executable(exe, fullname, use_path);
148 memset(&si, 0, sizeof(si));
149 si.cb = 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);
157 return -1;
160 MSVCRT_free(si.lpReserved2);
161 switch(flags)
163 case MSVCRT__P_WAIT:
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);
171 pi.hProcess = 0;
172 /* fall through */
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:
178 MSVCRT__exit(0);
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;
189 int size;
190 MSVCRT_wchar_t* p;
191 MSVCRT_wchar_t* ret;
193 if (!arg)
195 /* Return NULL for an empty environment list */
196 return NULL;
199 /* get length */
200 a = arg;
201 size = 0;
202 while (*a)
204 size += strlenW(*a) + 1;
205 a++;
208 ret = MSVCRT_malloc((size + 1) * sizeof(MSVCRT_wchar_t));
209 if (!ret)
210 return NULL;
212 /* fill string */
213 a = arg;
214 p = ret;
215 while (*a)
217 int len = strlenW(*a);
218 memcpy(p,*a,len * sizeof(MSVCRT_wchar_t));
219 p += len;
220 *p++ = delim;
221 a++;
223 if (delim && p > ret) p[-1] = 0;
224 else *p = 0;
225 return ret;
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;
234 unsigned int len;
235 MSVCRT_wchar_t *p, *ret;
237 if (!arg)
239 /* Return NULL for an empty environment list */
240 return NULL;
243 /* get length */
244 a = arg;
245 len = 0;
246 while (*a)
248 len += MultiByteToWideChar(CP_ACP, 0, *a, -1, NULL, 0);
249 a++;
252 ret = MSVCRT_malloc((len + 1) * sizeof(MSVCRT_wchar_t));
253 if (!ret)
254 return NULL;
256 /* fill string */
257 a = arg;
258 p = ret;
259 while (*a)
261 p += MultiByteToWideChar(CP_ACP, 0, *a, strlen(*a), p, len - (p - ret));
262 *p++ = delim;
263 a++;
265 if (delim && p > ret) p[-1] = 0;
266 else *p = 0;
267 return ret;
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) )))
288 MSVCRT_free( ret );
289 return NULL;
291 ret = new;
293 strcpyW( ret + pos, arg );
294 pos += len;
295 ret[pos - 1] = delim;
297 if (pos)
299 if (delim) ret[pos - 1] = 0;
300 else ret[pos] = 0;
302 return ret;
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;
311 const char *arg;
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) )))
323 MSVCRT_free( ret );
324 return NULL;
326 ret = new;
328 pos += MultiByteToWideChar( CP_ACP, 0, arg, -1, ret + pos, size - pos );
329 ret[pos - 1] = delim;
331 if (pos)
333 if (delim) ret[pos - 1] = 0;
334 else ret[pos] = 0;
336 return ret;
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};
344 MSVCRT_wchar_t *ret;
345 unsigned int len;
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);
352 return ret;
355 /*********************************************************************
356 * _cwait (MSVCRT.@)
358 MSVCRT_intptr_t CDECL _cwait(int *status, MSVCRT_intptr_t pid, int action)
360 HANDLE hPid = (HANDLE)pid;
361 int doserrno;
363 if (!WaitForSingleObject(hPid, INFINITE))
365 if (status)
367 DWORD stat;
368 GetExitCodeProcess(hPid, &stat);
369 *status = (int)stat;
371 return pid;
373 doserrno = GetLastError();
375 if (doserrno == ERROR_INVALID_HANDLE)
377 *MSVCRT__errno() = MSVCRT_ECHILD;
378 *MSVCRT___doserrno() = doserrno;
380 else
381 msvcrt_set_errno(doserrno);
383 return status ? *status = -1 : -1;
386 /*********************************************************************
387 * _wexecl (MSVCRT.@)
389 * Unicode version of _execl
391 MSVCRT_intptr_t CDECL _wexecl(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
393 __ms_va_list ap;
394 MSVCRT_wchar_t *args;
395 MSVCRT_intptr_t ret;
397 __ms_va_start(ap, arg0);
398 args = msvcrt_valisttos(arg0, ap, ' ');
399 __ms_va_end(ap);
401 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 0);
403 MSVCRT_free(args);
404 return ret;
407 /*********************************************************************
408 * _execl (MSVCRT.@)
410 * Like on Windows, this function does not handle arguments with spaces
411 * or double-quotes.
413 MSVCRT_intptr_t CDECL _execl(const char* name, const char* arg0, ...)
415 __ms_va_list ap;
416 MSVCRT_wchar_t *nameW, *args;
417 MSVCRT_intptr_t ret;
419 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
421 __ms_va_start(ap, arg0);
422 args = msvcrt_valisttos_aw(arg0, ap, ' ');
423 __ms_va_end(ap);
425 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 0);
427 MSVCRT_free(nameW);
428 MSVCRT_free(args);
429 return ret;
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, ...)
439 __ms_va_list ap;
440 MSVCRT_wchar_t *args, *envs = NULL;
441 const MSVCRT_wchar_t * const *envp;
442 MSVCRT_intptr_t ret;
444 __ms_va_start(ap, arg0);
445 args = msvcrt_valisttos(arg0, ap, ' ');
446 __ms_va_end(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);
452 __ms_va_end(ap);
454 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 0);
456 MSVCRT_free(args);
457 MSVCRT_free(envs);
458 return ret;
461 /*********************************************************************
462 * _execle (MSVCRT.@)
464 MSVCRT_intptr_t CDECL _execle(const char* name, const char* arg0, ...)
466 __ms_va_list ap;
467 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
468 const char * const *envp;
469 MSVCRT_intptr_t ret;
471 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
473 __ms_va_start(ap, arg0);
474 args = msvcrt_valisttos_aw(arg0, ap, ' ');
475 __ms_va_end(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);
481 __ms_va_end(ap);
483 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 0);
485 MSVCRT_free(nameW);
486 MSVCRT_free(args);
487 MSVCRT_free(envs);
488 return ret;
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, ...)
498 __ms_va_list ap;
499 MSVCRT_wchar_t *args;
500 MSVCRT_intptr_t ret;
502 __ms_va_start(ap, arg0);
503 args = msvcrt_valisttos(arg0, ap, ' ');
504 __ms_va_end(ap);
506 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 1);
508 MSVCRT_free(args);
509 return ret;
512 /*********************************************************************
513 * _execlp (MSVCRT.@)
515 * Like on Windows, this function does not handle arguments with spaces
516 * or double-quotes.
518 MSVCRT_intptr_t CDECL _execlp(const char* name, const char* arg0, ...)
520 __ms_va_list ap;
521 MSVCRT_wchar_t *nameW, *args;
522 MSVCRT_intptr_t ret;
524 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
526 __ms_va_start(ap, arg0);
527 args = msvcrt_valisttos_aw(arg0, ap, ' ');
528 __ms_va_end(ap);
530 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 1);
532 MSVCRT_free(nameW);
533 MSVCRT_free(args);
534 return ret;
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, ...)
544 __ms_va_list ap;
545 MSVCRT_wchar_t *args, *envs = NULL;
546 const MSVCRT_wchar_t * const *envp;
547 MSVCRT_intptr_t ret;
549 __ms_va_start(ap, arg0);
550 args = msvcrt_valisttos(arg0, ap, ' ');
551 __ms_va_end(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);
557 __ms_va_end(ap);
559 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 1);
561 MSVCRT_free(args);
562 MSVCRT_free(envs);
563 return ret;
566 /*********************************************************************
567 * _execlpe (MSVCRT.@)
569 MSVCRT_intptr_t CDECL _execlpe(const char* name, const char* arg0, ...)
571 __ms_va_list ap;
572 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
573 const char * const *envp;
574 MSVCRT_intptr_t ret;
576 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
578 __ms_va_start(ap, arg0);
579 args = msvcrt_valisttos_aw(arg0, ap, ' ');
580 __ms_va_end(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);
586 __ms_va_end(ap);
588 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 1);
590 MSVCRT_free(nameW);
591 MSVCRT_free(args);
592 MSVCRT_free(envs);
593 return ret;
596 /*********************************************************************
597 * _wexecv (MSVCRT.@)
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 /*********************************************************************
607 * _execv (MSVCRT.@)
609 * Like on Windows, this function does not handle arguments with spaces
610 * or double-quotes.
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 /*********************************************************************
628 * _execve (MSVCRT.@)
630 * Like on Windows, this function does not handle arguments with spaces
631 * or double-quotes.
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
652 * or double-quotes.
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 /*********************************************************************
670 * _execvp (MSVCRT.@)
672 * Like on Windows, this function does not handle arguments with spaces
673 * or double-quotes.
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, ...)
687 __ms_va_list ap;
688 MSVCRT_wchar_t *args;
689 MSVCRT_intptr_t ret;
691 __ms_va_start(ap, arg0);
692 args = msvcrt_valisttos(arg0, ap, ' ');
693 __ms_va_end(ap);
695 ret = msvcrt_spawn(flags, name, args, NULL, 0);
697 MSVCRT_free(args);
698 return ret;
701 /*********************************************************************
702 * _spawnl (MSVCRT.@)
704 * Like on Windows, this function does not handle arguments with spaces
705 * or double-quotes.
707 MSVCRT_intptr_t CDECL _spawnl(int flags, const char* name, const char* arg0, ...)
709 __ms_va_list ap;
710 MSVCRT_wchar_t *nameW, *args;
711 MSVCRT_intptr_t ret;
713 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
715 __ms_va_start(ap, arg0);
716 args = msvcrt_valisttos_aw(arg0, ap, ' ');
717 __ms_va_end(ap);
719 ret = msvcrt_spawn(flags, nameW, args, NULL, 0);
721 MSVCRT_free(nameW);
722 MSVCRT_free(args);
723 return ret;
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, ...)
733 __ms_va_list ap;
734 MSVCRT_wchar_t *args, *envs = NULL;
735 const MSVCRT_wchar_t * const *envp;
736 MSVCRT_intptr_t ret;
738 __ms_va_start(ap, arg0);
739 args = msvcrt_valisttos(arg0, ap, ' ');
740 __ms_va_end(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);
746 __ms_va_end(ap);
748 ret = msvcrt_spawn(flags, name, args, envs, 0);
750 MSVCRT_free(args);
751 MSVCRT_free(envs);
752 return ret;
755 /*********************************************************************
756 * _spawnle (MSVCRT.@)
758 MSVCRT_intptr_t CDECL _spawnle(int flags, const char* name, const char* arg0, ...)
760 __ms_va_list ap;
761 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
762 const char * const *envp;
763 MSVCRT_intptr_t ret;
765 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
767 __ms_va_start(ap, arg0);
768 args = msvcrt_valisttos_aw(arg0, ap, ' ');
769 __ms_va_end(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);
775 __ms_va_end(ap);
777 ret = msvcrt_spawn(flags, nameW, args, envs, 0);
779 MSVCRT_free(nameW);
780 MSVCRT_free(args);
781 MSVCRT_free(envs);
782 return ret;
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, ...)
792 __ms_va_list ap;
793 MSVCRT_wchar_t *args;
794 MSVCRT_intptr_t ret;
796 __ms_va_start(ap, arg0);
797 args = msvcrt_valisttos(arg0, ap, ' ');
798 __ms_va_end(ap);
800 ret = msvcrt_spawn(flags, name, args, NULL, 1);
802 MSVCRT_free(args);
803 return ret;
806 /*********************************************************************
807 * _spawnlp (MSVCRT.@)
809 * Like on Windows, this function does not handle arguments with spaces
810 * or double-quotes.
812 MSVCRT_intptr_t CDECL _spawnlp(int flags, const char* name, const char* arg0, ...)
814 __ms_va_list ap;
815 MSVCRT_wchar_t *nameW, *args;
816 MSVCRT_intptr_t ret;
818 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
820 __ms_va_start(ap, arg0);
821 args = msvcrt_valisttos_aw(arg0, ap, ' ');
822 __ms_va_end(ap);
824 ret = msvcrt_spawn(flags, nameW, args, NULL, 1);
826 MSVCRT_free(nameW);
827 MSVCRT_free(args);
828 return ret;
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, ...)
838 __ms_va_list ap;
839 MSVCRT_wchar_t *args, *envs = NULL;
840 const MSVCRT_wchar_t * const *envp;
841 MSVCRT_intptr_t ret;
843 __ms_va_start(ap, arg0);
844 args = msvcrt_valisttos(arg0, ap, ' ');
845 __ms_va_end(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);
851 __ms_va_end(ap);
853 ret = msvcrt_spawn(flags, name, args, envs, 1);
855 MSVCRT_free(args);
856 MSVCRT_free(envs);
857 return ret;
860 /*********************************************************************
861 * _spawnlpe (MSVCRT.@)
863 MSVCRT_intptr_t CDECL _spawnlpe(int flags, const char* name, const char* arg0, ...)
865 __ms_va_list ap;
866 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
867 const char * const *envp;
868 MSVCRT_intptr_t ret;
870 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
872 __ms_va_start(ap, arg0);
873 args = msvcrt_valisttos_aw(arg0, ap, ' ');
874 __ms_va_end(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);
880 __ms_va_end(ap);
882 ret = msvcrt_spawn(flags, nameW, args, envs, 1);
884 MSVCRT_free(nameW);
885 MSVCRT_free(args);
886 MSVCRT_free(envs);
887 return ret;
890 /*********************************************************************
891 * _spawnve (MSVCRT.@)
893 * Like on Windows, this function does not handle arguments with spaces
894 * or double-quotes.
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;
900 MSVCRT_intptr_t ret;
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);
909 MSVCRT_free(nameW);
910 MSVCRT_free(args);
911 MSVCRT_free(envs);
912 return ret;
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;
924 MSVCRT_intptr_t ret;
926 args = msvcrt_argvtos(argv, ' ');
927 envs = msvcrt_argvtos(envv, 0);
929 ret = msvcrt_spawn(flags, name, args, envs, 0);
931 MSVCRT_free(args);
932 MSVCRT_free(envs);
933 return ret;
936 /*********************************************************************
937 * _spawnv (MSVCRT.@)
939 * Like on Windows, this function does not handle arguments with spaces
940 * or double-quotes.
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
961 * or double-quotes.
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;
967 MSVCRT_intptr_t ret;
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);
976 MSVCRT_free(nameW);
977 MSVCRT_free(args);
978 MSVCRT_free(envs);
979 return ret;
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;
991 MSVCRT_intptr_t ret;
993 args = msvcrt_argvtos(argv, ' ');
994 envs = msvcrt_argvtos(envv, 0);
996 ret = msvcrt_spawn(flags, name, args, envs, 1);
998 MSVCRT_free(args);
999 MSVCRT_free(envs);
1000 return ret;
1003 /*********************************************************************
1004 * _spawnvp (MSVCRT.@)
1006 * Like on Windows, this function does not handle arguments with spaces
1007 * or double-quotes.
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 {
1025 MSVCRT_FILE *f;
1026 HANDLE proc;
1027 } *popen_handles;
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)
1042 MSVCRT_FILE *ret;
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;
1047 unsigned int len;
1048 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1049 struct popen_handle *container;
1050 DWORD i;
1052 TRACE("(command=%s, mode=%s)\n", debugstr_w(command), debugstr_w(mode));
1054 if (!command || !mode)
1055 return NULL;
1057 textmode = *__p__fmode() & (MSVCRT__O_BINARY | MSVCRT__O_TEXT);
1058 for (p = mode; *p; p++)
1060 switch (*p)
1062 case 'W':
1063 case 'w':
1064 readPipe = FALSE;
1065 break;
1066 case 'B':
1067 case 'b':
1068 textmode |= MSVCRT__O_BINARY;
1069 textmode &= ~MSVCRT__O_TEXT;
1070 break;
1071 case 'T':
1072 case 't':
1073 textmode |= MSVCRT__O_TEXT;
1074 textmode &= ~MSVCRT__O_BINARY;
1075 break;
1078 if (MSVCRT__pipe(fds, 0, textmode) == -1)
1079 return NULL;
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)
1088 break;
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)
1104 goto error;
1105 if (MSVCRT__dup2(fds[fdToDup], fdToDup) != 0)
1106 goto error;
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);
1116 goto error;
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]);
1127 ret = NULL;
1129 else
1131 ret = MSVCRT__wfdopen(fds[fdToOpen], mode);
1132 if (!ret)
1133 MSVCRT__close(fds[fdToOpen]);
1134 container->f = ret;
1136 _munlock(_POPEN_LOCK);
1137 HeapFree(GetProcessHeap(), 0, comspec);
1138 HeapFree(GetProcessHeap(), 0, fullcmd);
1139 MSVCRT__dup2(fdStdHandle, fdToDup);
1140 MSVCRT__close(fdStdHandle);
1141 return ret;
1143 error:
1144 _munlock(_POPEN_LOCK);
1145 if (fdStdHandle != -1) MSVCRT__close(fdStdHandle);
1146 MSVCRT__close(fds[0]);
1147 MSVCRT__close(fds[1]);
1148 return NULL;
1151 /*********************************************************************
1152 * _popen (MSVCRT.@)
1154 MSVCRT_FILE* CDECL MSVCRT__popen(const char* command, const char* mode)
1156 MSVCRT_FILE *ret;
1157 MSVCRT_wchar_t *cmdW, *modeW;
1159 TRACE("(command=%s, mode=%s)\n", debugstr_a(command), debugstr_a(mode));
1161 if (!command || !mode)
1162 return NULL;
1164 if (!(cmdW = msvcrt_wstrdupa(command))) return NULL;
1165 if (!(modeW = msvcrt_wstrdupa(mode)))
1167 HeapFree(GetProcessHeap(), 0, cmdW);
1168 return NULL;
1171 ret = MSVCRT__wpopen(cmdW, modeW);
1173 HeapFree(GetProcessHeap(), 0, cmdW);
1174 HeapFree(GetProcessHeap(), 0, modeW);
1175 return ret;
1178 /*********************************************************************
1179 * _pclose (MSVCRT.@)
1181 int CDECL MSVCRT__pclose(MSVCRT_FILE* file)
1183 HANDLE h;
1184 DWORD i;
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)
1192 break;
1194 if(i == popen_handles_size)
1196 _munlock(_POPEN_LOCK);
1197 *MSVCRT__errno() = MSVCRT_EBADF;
1198 return -1;
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());
1209 CloseHandle(h);
1210 return -1;
1213 CloseHandle(h);
1214 return i;
1217 /*********************************************************************
1218 * _wsystem (MSVCRT.@)
1220 * Unicode version of system
1222 int CDECL _wsystem(const MSVCRT_wchar_t* cmd)
1224 int res;
1225 MSVCRT_wchar_t *comspec, *fullcmd;
1226 unsigned int len;
1227 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1229 comspec = msvcrt_get_comspec();
1231 if (cmd == NULL)
1233 if (comspec == NULL)
1235 *MSVCRT__errno() = MSVCRT_ENOENT;
1236 return 0;
1238 HeapFree(GetProcessHeap(), 0, comspec);
1239 return 1;
1242 if ( comspec == NULL)
1243 return -1;
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);
1250 return -1;
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);
1260 return res;
1263 /*********************************************************************
1264 * system (MSVCRT.@)
1266 int CDECL MSVCRT_system(const char* cmd)
1268 int res = -1;
1269 MSVCRT_wchar_t *cmdW;
1271 if (cmd == NULL)
1272 return _wsystem(NULL);
1274 if ((cmdW = msvcrt_wstrdupa(cmd)))
1276 res = _wsystem(cmdW);
1277 HeapFree(GetProcessHeap(), 0, cmdW);
1279 return res;
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))
1296 return 0;
1297 else
1299 int err = GetLastError();
1300 msvcrt_set_errno(err);
1301 return err;
1305 /*********************************************************************
1306 * _getdllprocaddr (MSVCRT.@)
1308 void * CDECL _getdllprocaddr(MSVCRT_intptr_t dll, const char *name, int ordinal)
1310 if (name)
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();