user32/tests: Prevent writing to not allocated memory.
[wine.git] / dlls / msvcrt / process.c
blob87a29f47a3b8b32f645eb78f6aeff7b8abaccb9a
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 "wine/debug.h"
35 #include "wine/unicode.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
39 static void msvcrt_search_executable(const MSVCRT_wchar_t *name, MSVCRT_wchar_t *fullname, int use_path)
41 static const MSVCRT_wchar_t path[] = {'P','A','T','H',0};
42 static const MSVCRT_wchar_t suffix[][5] =
43 {{'.','c','o','m',0}, {'.','e','x','e',0}, {'.','b','a','t',0}, {'.','c','m','d',0}};
45 MSVCRT_wchar_t buffer[MAX_PATH];
46 const MSVCRT_wchar_t *env, *p;
47 unsigned int i, name_len, path_len;
48 int extension = 1;
50 *fullname = '\0';
51 msvcrt_set_errno(ERROR_FILE_NOT_FOUND);
53 p = memchrW(name, '\0', MAX_PATH);
54 if (!p) p = name + MAX_PATH - 1;
55 name_len = p - name;
57 /* FIXME extra-long names are silently truncated */
58 memcpy(buffer, name, name_len * sizeof(MSVCRT_wchar_t));
59 buffer[name_len] = '\0';
61 /* try current dir first */
62 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
64 strcpyW(fullname, buffer);
65 return;
68 for (p--; p >= name; p--)
69 if (*p == '\\' || *p == '/' || *p == ':' || *p == '.') break;
71 /* if there's no extension, try some well-known extensions */
72 if ((p < name || *p != '.') && name_len <= MAX_PATH - 5)
74 for (i = 0; i < 4; i++)
76 memcpy(buffer + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t));
77 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
79 strcpyW(fullname, buffer);
80 return;
83 extension = 0;
86 if (!use_path || !(env = _wgetenv(path))) return;
88 /* now try search path */
91 p = env;
92 while (*p && *p != ';') p++;
93 if (p == env) return;
95 path_len = p - env;
96 if (path_len + name_len <= MAX_PATH - 2)
98 memcpy(buffer, env, path_len * sizeof(MSVCRT_wchar_t));
99 if (buffer[path_len] != '/' || buffer[path_len] != '\\')
101 buffer[path_len++] = '\\';
102 buffer[path_len] = '\0';
104 else buffer[path_len] = '\0';
106 strcatW(buffer, name);
107 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
109 strcpyW(fullname, buffer);
110 return;
113 /* again, if there's no extension, try some well-known extensions */
114 if (!extension && path_len + name_len <= MAX_PATH - 5)
116 for (i = 0; i < 4; i++)
118 memcpy(buffer + path_len + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t));
119 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
121 strcpyW(fullname, buffer);
122 return;
126 env = *p ? p + 1 : p;
127 } while(1);
130 static MSVCRT_intptr_t msvcrt_spawn(int flags, const MSVCRT_wchar_t* exe, MSVCRT_wchar_t* cmdline,
131 MSVCRT_wchar_t* env, int use_path)
133 STARTUPINFOW si;
134 PROCESS_INFORMATION pi;
135 MSVCRT_wchar_t fullname[MAX_PATH];
137 TRACE("%x %s %s %s %d\n", flags, debugstr_w(exe), debugstr_w(cmdline), debugstr_w(env), use_path);
139 if ((unsigned)flags > MSVCRT__P_DETACH)
141 *MSVCRT__errno() = MSVCRT_EINVAL;
142 return -1;
145 msvcrt_search_executable(exe, fullname, use_path);
147 memset(&si, 0, sizeof(si));
148 si.cb = sizeof(si);
149 msvcrt_create_io_inherit_block(&si.cbReserved2, &si.lpReserved2);
150 if (!CreateProcessW(fullname, cmdline, NULL, NULL, TRUE,
151 flags == MSVCRT__P_DETACH ? DETACHED_PROCESS : 0,
152 env, NULL, &si, &pi))
154 msvcrt_set_errno(GetLastError());
155 MSVCRT_free(si.lpReserved2);
156 return -1;
159 MSVCRT_free(si.lpReserved2);
160 switch(flags)
162 case MSVCRT__P_WAIT:
163 WaitForSingleObject(pi.hProcess, INFINITE);
164 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
165 CloseHandle(pi.hProcess);
166 CloseHandle(pi.hThread);
167 return pi.dwProcessId;
168 case MSVCRT__P_DETACH:
169 CloseHandle(pi.hProcess);
170 pi.hProcess = 0;
171 /* fall through */
172 case MSVCRT__P_NOWAIT:
173 case MSVCRT__P_NOWAITO:
174 CloseHandle(pi.hThread);
175 return (MSVCRT_intptr_t)pi.hProcess;
176 case MSVCRT__P_OVERLAY:
177 MSVCRT__exit(0);
179 return -1; /* can't reach here */
182 /* INTERNAL: Convert wide argv list to a single 'delim'-separated wide string, with an
183 * extra '\0' to terminate it.
185 static MSVCRT_wchar_t* msvcrt_argvtos(const MSVCRT_wchar_t* const* arg, MSVCRT_wchar_t delim)
187 const MSVCRT_wchar_t* const* a;
188 long size;
189 MSVCRT_wchar_t* p;
190 MSVCRT_wchar_t* ret;
192 if (!arg)
194 /* Return NULL for an empty environment list */
195 return NULL;
198 /* get length */
199 a = arg;
200 size = 0;
201 while (*a)
203 size += strlenW(*a) + 1;
204 a++;
207 ret = MSVCRT_malloc((size + 1) * sizeof(MSVCRT_wchar_t));
208 if (!ret)
209 return NULL;
211 /* fill string */
212 a = arg;
213 p = ret;
214 while (*a)
216 int len = strlenW(*a);
217 memcpy(p,*a,len * sizeof(MSVCRT_wchar_t));
218 p += len;
219 *p++ = delim;
220 a++;
222 if (delim && p > ret) p[-1] = 0;
223 else *p = 0;
224 return ret;
227 /* INTERNAL: Convert ansi argv list to a single 'delim'-separated wide string, with an
228 * extra '\0' to terminate it.
230 static MSVCRT_wchar_t *msvcrt_argvtos_aw(const char * const *arg, MSVCRT_wchar_t delim)
232 const char * const *a;
233 unsigned long len;
234 MSVCRT_wchar_t *p, *ret;
236 if (!arg)
238 /* Return NULL for an empty environment list */
239 return NULL;
242 /* get length */
243 a = arg;
244 len = 0;
245 while (*a)
247 len += MultiByteToWideChar(CP_ACP, 0, *a, -1, NULL, 0);
248 a++;
251 ret = MSVCRT_malloc((len + 1) * sizeof(MSVCRT_wchar_t));
252 if (!ret)
253 return NULL;
255 /* fill string */
256 a = arg;
257 p = ret;
258 while (*a)
260 p += MultiByteToWideChar(CP_ACP, 0, *a, strlen(*a), p, len - (p - ret));
261 *p++ = delim;
262 a++;
264 if (delim && p > ret) p[-1] = 0;
265 else *p = 0;
266 return ret;
269 /* INTERNAL: Convert wide va_list to a single 'delim'-separated wide string, with an
270 * extra '\0' to terminate it.
272 static MSVCRT_wchar_t *msvcrt_valisttos(const MSVCRT_wchar_t *arg0, va_list alist, MSVCRT_wchar_t delim)
274 va_list alist2;
275 unsigned long len;
276 const MSVCRT_wchar_t *arg;
277 MSVCRT_wchar_t *p, *ret;
279 #ifdef HAVE_VA_COPY
280 va_copy(alist2,alist);
281 #else
282 # ifdef HAVE___VA_COPY
283 __va_copy(alist2,alist);
284 # else
285 alist2 = alist;
286 # endif
287 #endif
289 if (!arg0)
291 /* Return NULL for an empty environment list */
292 return NULL;
295 /* get length */
296 arg = arg0;
297 len = 0;
298 do {
299 len += strlenW(arg) + 1;
300 arg = va_arg(alist, MSVCRT_wchar_t*);
301 } while (arg != NULL);
303 ret = MSVCRT_malloc((len + 1) * sizeof(MSVCRT_wchar_t));
304 if (!ret)
305 return NULL;
307 /* fill string */
308 arg = arg0;
309 p = ret;
310 do {
311 len = strlenW(arg);
312 memcpy(p, arg, len * sizeof(MSVCRT_wchar_t));
313 p += len;
314 *p++ = delim;
315 arg = va_arg(alist2, MSVCRT_wchar_t*);
316 } while (arg != NULL);
317 if (delim && p > ret) p[-1] = 0;
318 else *p = 0;
319 return ret;
322 /* INTERNAL: Convert ansi va_list to a single 'delim'-separated wide string, with an
323 * extra '\0' to terminate it.
325 static MSVCRT_wchar_t *msvcrt_valisttos_aw(const char *arg0, va_list alist, MSVCRT_wchar_t delim)
327 va_list alist2;
328 unsigned long len;
329 const char *arg;
330 MSVCRT_wchar_t *p, *ret;
332 #ifdef HAVE_VA_COPY
333 va_copy(alist2,alist);
334 #else
335 # ifdef HAVE___VA_COPY
336 __va_copy(alist2,alist);
337 # else
338 alist2 = alist;
339 # endif
340 #endif
342 if (!arg0)
344 /* Return NULL for an empty environment list */
345 return NULL;
348 /* get length */
349 arg = arg0;
350 len = 0;
351 do {
352 len += MultiByteToWideChar(CP_ACP, 0, arg, -1, NULL, 0);
353 arg = va_arg(alist, char*);
354 } while (arg != NULL);
356 ret = MSVCRT_malloc((len + 1) * sizeof(MSVCRT_wchar_t));
357 if (!ret)
358 return NULL;
360 /* fill string */
361 arg = arg0;
362 p = ret;
363 do {
364 p += MultiByteToWideChar(CP_ACP, 0, arg, strlen(arg), p, len - (p - ret));
365 *p++ = delim;
366 arg = va_arg(alist2, char*);
367 } while (arg != NULL);
368 if (delim && p > ret) p[-1] = 0;
369 else *p = 0;
370 return ret;
373 /* INTERNAL: retrieve COMSPEC environment variable */
374 static MSVCRT_wchar_t *msvcrt_get_comspec(void)
376 static const MSVCRT_wchar_t cmd[] = {'c','m','d',0};
377 static const MSVCRT_wchar_t comspec[] = {'C','O','M','S','P','E','C',0};
378 MSVCRT_wchar_t *ret;
379 unsigned int len;
381 if (!(len = GetEnvironmentVariableW(comspec, NULL, 0))) len = sizeof(cmd)/sizeof(MSVCRT_wchar_t);
382 if ((ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
384 if (!GetEnvironmentVariableW(comspec, ret, len)) strcpyW(ret, cmd);
386 return ret;
389 /*********************************************************************
390 * _cwait (MSVCRT.@)
392 MSVCRT_intptr_t CDECL _cwait(int *status, MSVCRT_intptr_t pid, int action)
394 HANDLE hPid = (HANDLE)pid;
395 int doserrno;
397 action = action; /* Remove warning */
399 if (!WaitForSingleObject(hPid, INFINITE))
401 if (status)
403 DWORD stat;
404 GetExitCodeProcess(hPid, &stat);
405 *status = (int)stat;
407 return pid;
409 doserrno = GetLastError();
411 if (doserrno == ERROR_INVALID_HANDLE)
413 *MSVCRT__errno() = MSVCRT_ECHILD;
414 *MSVCRT___doserrno() = doserrno;
416 else
417 msvcrt_set_errno(doserrno);
419 return status ? *status = -1 : -1;
422 /*********************************************************************
423 * _wexecl (MSVCRT.@)
425 * Unicode version of _execl
427 MSVCRT_intptr_t CDECL _wexecl(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
429 va_list ap;
430 MSVCRT_wchar_t *args;
431 MSVCRT_intptr_t ret;
433 va_start(ap, arg0);
434 args = msvcrt_valisttos(arg0, ap, ' ');
435 va_end(ap);
437 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 0);
439 MSVCRT_free(args);
440 return ret;
443 /*********************************************************************
444 * _execl (MSVCRT.@)
446 * Like on Windows, this function does not handle arguments with spaces
447 * or double-quotes.
449 MSVCRT_intptr_t CDECL _execl(const char* name, const char* arg0, ...)
451 va_list ap;
452 MSVCRT_wchar_t *nameW, *args;
453 MSVCRT_intptr_t ret;
455 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
457 va_start(ap, arg0);
458 args = msvcrt_valisttos_aw(arg0, ap, ' ');
459 va_end(ap);
461 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 0);
463 MSVCRT_free(nameW);
464 MSVCRT_free(args);
465 return ret;
468 /*********************************************************************
469 * _wexecle (MSVCRT.@)
471 * Unicode version of _execle
473 MSVCRT_intptr_t CDECL _wexecle(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
475 va_list ap;
476 MSVCRT_wchar_t *args, *envs = NULL;
477 const MSVCRT_wchar_t * const *envp;
478 MSVCRT_intptr_t ret;
480 va_start(ap, arg0);
481 args = msvcrt_valisttos(arg0, ap, ' ');
482 va_end(ap);
484 va_start(ap, arg0);
485 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
486 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
487 if (envp) envs = msvcrt_argvtos(envp, 0);
488 va_end(ap);
490 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 0);
492 MSVCRT_free(args);
493 MSVCRT_free(envs);
494 return ret;
497 /*********************************************************************
498 * _execle (MSVCRT.@)
500 MSVCRT_intptr_t CDECL _execle(const char* name, const char* arg0, ...)
502 va_list ap;
503 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
504 const char * const *envp;
505 MSVCRT_intptr_t ret;
507 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
509 va_start(ap, arg0);
510 args = msvcrt_valisttos_aw(arg0, ap, ' ');
511 va_end(ap);
513 va_start(ap, arg0);
514 while (va_arg( ap, char * ) != NULL) /*nothing*/;
515 envp = va_arg( ap, const char * const * );
516 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
517 va_end(ap);
519 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 0);
521 MSVCRT_free(nameW);
522 MSVCRT_free(args);
523 MSVCRT_free(envs);
524 return ret;
527 /*********************************************************************
528 * _wexeclp (MSVCRT.@)
530 * Unicode version of _execlp
532 MSVCRT_intptr_t CDECL _wexeclp(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
534 va_list ap;
535 MSVCRT_wchar_t *args;
536 MSVCRT_intptr_t ret;
538 va_start(ap, arg0);
539 args = msvcrt_valisttos(arg0, ap, ' ');
540 va_end(ap);
542 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 1);
544 MSVCRT_free(args);
545 return ret;
548 /*********************************************************************
549 * _execlp (MSVCRT.@)
551 * Like on Windows, this function does not handle arguments with spaces
552 * or double-quotes.
554 MSVCRT_intptr_t CDECL _execlp(const char* name, const char* arg0, ...)
556 va_list ap;
557 MSVCRT_wchar_t *nameW, *args;
558 MSVCRT_intptr_t ret;
560 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
562 va_start(ap, arg0);
563 args = msvcrt_valisttos_aw(arg0, ap, ' ');
564 va_end(ap);
566 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 1);
568 MSVCRT_free(nameW);
569 MSVCRT_free(args);
570 return ret;
573 /*********************************************************************
574 * _wexeclpe (MSVCRT.@)
576 * Unicode version of _execlpe
578 MSVCRT_intptr_t CDECL _wexeclpe(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
580 va_list ap;
581 MSVCRT_wchar_t *args, *envs = NULL;
582 const MSVCRT_wchar_t * const *envp;
583 MSVCRT_intptr_t ret;
585 va_start(ap, arg0);
586 args = msvcrt_valisttos(arg0, ap, ' ');
587 va_end(ap);
589 va_start(ap, arg0);
590 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
591 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
592 if (envp) envs = msvcrt_argvtos(envp, 0);
593 va_end(ap);
595 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 1);
597 MSVCRT_free(args);
598 MSVCRT_free(envs);
599 return ret;
602 /*********************************************************************
603 * _execlpe (MSVCRT.@)
605 MSVCRT_intptr_t CDECL _execlpe(const char* name, const char* arg0, ...)
607 va_list ap;
608 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
609 const char * const *envp;
610 MSVCRT_intptr_t ret;
612 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
614 va_start(ap, arg0);
615 args = msvcrt_valisttos_aw(arg0, ap, ' ');
616 va_end(ap);
618 va_start(ap, arg0);
619 while (va_arg( ap, char * ) != NULL) /*nothing*/;
620 envp = va_arg( ap, const char * const * );
621 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
622 va_end(ap);
624 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 1);
626 MSVCRT_free(nameW);
627 MSVCRT_free(args);
628 MSVCRT_free(envs);
629 return ret;
632 /*********************************************************************
633 * _wexecv (MSVCRT.@)
635 * Unicode version of _execv
637 MSVCRT_intptr_t CDECL _wexecv(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv)
639 return _wspawnve(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, NULL);
642 /*********************************************************************
643 * _execv (MSVCRT.@)
645 * Like on Windows, this function does not handle arguments with spaces
646 * or double-quotes.
648 MSVCRT_intptr_t CDECL _execv(const char* name, char* const* argv)
650 return _spawnve(MSVCRT__P_OVERLAY, name, (const char* const*) argv, NULL);
653 /*********************************************************************
654 * _wexecve (MSVCRT.@)
656 * Unicode version of _execve
658 MSVCRT_intptr_t CDECL _wexecve(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
660 return _wspawnve(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, envv);
663 /*********************************************************************
664 * _execve (MSVCRT.@)
666 * Like on Windows, this function does not handle arguments with spaces
667 * or double-quotes.
669 MSVCRT_intptr_t CDECL MSVCRT__execve(const char* name, char* const* argv, const char* const* envv)
671 return _spawnve(MSVCRT__P_OVERLAY, name, (const char* const*) argv, envv);
674 /*********************************************************************
675 * _wexecvpe (MSVCRT.@)
677 * Unicode version of _execvpe
679 MSVCRT_intptr_t CDECL _wexecvpe(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
681 return _wspawnvpe(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, envv);
684 /*********************************************************************
685 * _execvpe (MSVCRT.@)
687 * Like on Windows, this function does not handle arguments with spaces
688 * or double-quotes.
690 MSVCRT_intptr_t CDECL _execvpe(const char* name, char* const* argv, const char* const* envv)
692 return _spawnvpe(MSVCRT__P_OVERLAY, name, (const char* const*) argv, envv);
695 /*********************************************************************
696 * _wexecvp (MSVCRT.@)
698 * Unicode version of _execvp
700 MSVCRT_intptr_t CDECL _wexecvp(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv)
702 return _wexecvpe(name, argv, NULL);
705 /*********************************************************************
706 * _execvp (MSVCRT.@)
708 * Like on Windows, this function does not handle arguments with spaces
709 * or double-quotes.
711 MSVCRT_intptr_t CDECL _execvp(const char* name, char* const* argv)
713 return _execvpe(name, argv, NULL);
716 /*********************************************************************
717 * _wspawnl (MSVCRT.@)
719 * Unicode version of _spawnl
721 MSVCRT_intptr_t CDECL _wspawnl(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
723 va_list ap;
724 MSVCRT_wchar_t *args;
725 MSVCRT_intptr_t ret;
727 va_start(ap, arg0);
728 args = msvcrt_valisttos(arg0, ap, ' ');
729 va_end(ap);
731 ret = msvcrt_spawn(flags, name, args, NULL, 0);
733 MSVCRT_free(args);
734 return ret;
737 /*********************************************************************
738 * _spawnl (MSVCRT.@)
740 * Like on Windows, this function does not handle arguments with spaces
741 * or double-quotes.
743 MSVCRT_intptr_t CDECL _spawnl(int flags, const char* name, const char* arg0, ...)
745 va_list ap;
746 MSVCRT_wchar_t *nameW, *args;
747 MSVCRT_intptr_t ret;
749 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
751 va_start(ap, arg0);
752 args = msvcrt_valisttos_aw(arg0, ap, ' ');
753 va_end(ap);
755 ret = msvcrt_spawn(flags, nameW, args, NULL, 0);
757 MSVCRT_free(nameW);
758 MSVCRT_free(args);
759 return ret;
762 /*********************************************************************
763 * _wspawnle (MSVCRT.@)
765 * Unicode version of _spawnle
767 MSVCRT_intptr_t CDECL _wspawnle(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
769 va_list ap;
770 MSVCRT_wchar_t *args, *envs = NULL;
771 const MSVCRT_wchar_t * const *envp;
772 MSVCRT_intptr_t ret;
774 va_start(ap, arg0);
775 args = msvcrt_valisttos(arg0, ap, ' ');
776 va_end(ap);
778 va_start(ap, arg0);
779 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
780 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
781 if (envp) envs = msvcrt_argvtos(envp, 0);
782 va_end(ap);
784 ret = msvcrt_spawn(flags, name, args, envs, 0);
786 MSVCRT_free(args);
787 MSVCRT_free(envs);
788 return ret;
791 /*********************************************************************
792 * _spawnle (MSVCRT.@)
794 MSVCRT_intptr_t CDECL _spawnle(int flags, const char* name, const char* arg0, ...)
796 va_list ap;
797 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
798 const char * const *envp;
799 MSVCRT_intptr_t ret;
801 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
803 va_start(ap, arg0);
804 args = msvcrt_valisttos_aw(arg0, ap, ' ');
805 va_end(ap);
807 va_start(ap, arg0);
808 while (va_arg( ap, char * ) != NULL) /*nothing*/;
809 envp = va_arg( ap, const char * const * );
810 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
811 va_end(ap);
813 ret = msvcrt_spawn(flags, nameW, args, envs, 0);
815 MSVCRT_free(nameW);
816 MSVCRT_free(args);
817 MSVCRT_free(envs);
818 return ret;
821 /*********************************************************************
822 * _wspawnlp (MSVCRT.@)
824 * Unicode version of _spawnlp
826 MSVCRT_intptr_t CDECL _wspawnlp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
828 va_list ap;
829 MSVCRT_wchar_t *args;
830 MSVCRT_intptr_t ret;
832 va_start(ap, arg0);
833 args = msvcrt_valisttos(arg0, ap, ' ');
834 va_end(ap);
836 ret = msvcrt_spawn(flags, name, args, NULL, 1);
838 MSVCRT_free(args);
839 return ret;
842 /*********************************************************************
843 * _spawnlp (MSVCRT.@)
845 * Like on Windows, this function does not handle arguments with spaces
846 * or double-quotes.
848 MSVCRT_intptr_t CDECL _spawnlp(int flags, const char* name, const char* arg0, ...)
850 va_list ap;
851 MSVCRT_wchar_t *nameW, *args;
852 MSVCRT_intptr_t ret;
854 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
856 va_start(ap, arg0);
857 args = msvcrt_valisttos_aw(arg0, ap, ' ');
858 va_end(ap);
860 ret = msvcrt_spawn(flags, nameW, args, NULL, 1);
862 MSVCRT_free(nameW);
863 MSVCRT_free(args);
864 return ret;
867 /*********************************************************************
868 * _wspawnlpe (MSVCRT.@)
870 * Unicode version of _spawnlpe
872 MSVCRT_intptr_t CDECL _wspawnlpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
874 va_list ap;
875 MSVCRT_wchar_t *args, *envs = NULL;
876 const MSVCRT_wchar_t * const *envp;
877 MSVCRT_intptr_t ret;
879 va_start(ap, arg0);
880 args = msvcrt_valisttos(arg0, ap, ' ');
881 va_end(ap);
883 va_start(ap, arg0);
884 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
885 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
886 if (envp) envs = msvcrt_argvtos(envp, 0);
887 va_end(ap);
889 ret = msvcrt_spawn(flags, name, args, envs, 1);
891 MSVCRT_free(args);
892 MSVCRT_free(envs);
893 return ret;
896 /*********************************************************************
897 * _spawnlpe (MSVCRT.@)
899 MSVCRT_intptr_t CDECL _spawnlpe(int flags, const char* name, const char* arg0, ...)
901 va_list ap;
902 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
903 const char * const *envp;
904 MSVCRT_intptr_t ret;
906 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
908 va_start(ap, arg0);
909 args = msvcrt_valisttos_aw(arg0, ap, ' ');
910 va_end(ap);
912 va_start(ap, arg0);
913 while (va_arg( ap, char * ) != NULL) /*nothing*/;
914 envp = va_arg( ap, const char * const * );
915 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
916 va_end(ap);
918 ret = msvcrt_spawn(flags, nameW, args, envs, 1);
920 MSVCRT_free(nameW);
921 MSVCRT_free(args);
922 MSVCRT_free(envs);
923 return ret;
926 /*********************************************************************
927 * _spawnve (MSVCRT.@)
929 * Like on Windows, this function does not handle arguments with spaces
930 * or double-quotes.
932 MSVCRT_intptr_t CDECL _spawnve(int flags, const char* name, const char* const* argv,
933 const char* const* envv)
935 MSVCRT_wchar_t *nameW, *args, *envs;
936 MSVCRT_intptr_t ret;
938 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
940 args = msvcrt_argvtos_aw(argv, ' ');
941 envs = msvcrt_argvtos_aw(envv, 0);
943 ret = msvcrt_spawn(flags, nameW, args, envs, 0);
945 MSVCRT_free(nameW);
946 MSVCRT_free(args);
947 MSVCRT_free(envs);
948 return ret;
951 /*********************************************************************
952 * _wspawnve (MSVCRT.@)
954 * Unicode version of _spawnve
956 MSVCRT_intptr_t CDECL _wspawnve(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
957 const MSVCRT_wchar_t* const* envv)
959 MSVCRT_wchar_t *args, *envs;
960 MSVCRT_intptr_t ret;
962 args = msvcrt_argvtos(argv, ' ');
963 envs = msvcrt_argvtos(envv, 0);
965 ret = msvcrt_spawn(flags, name, args, envs, 0);
967 MSVCRT_free(args);
968 MSVCRT_free(envs);
969 return ret;
972 /*********************************************************************
973 * _spawnv (MSVCRT.@)
975 * Like on Windows, this function does not handle arguments with spaces
976 * or double-quotes.
978 MSVCRT_intptr_t CDECL _spawnv(int flags, const char* name, const char* const* argv)
980 return _spawnve(flags, name, argv, NULL);
983 /*********************************************************************
984 * _wspawnv (MSVCRT.@)
986 * Unicode version of _spawnv
988 MSVCRT_intptr_t CDECL _wspawnv(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
990 return _wspawnve(flags, name, argv, NULL);
993 /*********************************************************************
994 * _spawnvpe (MSVCRT.@)
996 * Like on Windows, this function does not handle arguments with spaces
997 * or double-quotes.
999 MSVCRT_intptr_t CDECL _spawnvpe(int flags, const char* name, const char* const* argv,
1000 const char* const* envv)
1002 MSVCRT_wchar_t *nameW, *args, *envs;
1003 MSVCRT_intptr_t ret;
1005 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
1007 args = msvcrt_argvtos_aw(argv, ' ');
1008 envs = msvcrt_argvtos_aw(envv, 0);
1010 ret = msvcrt_spawn(flags, nameW, args, envs, 1);
1012 MSVCRT_free(nameW);
1013 MSVCRT_free(args);
1014 MSVCRT_free(envs);
1015 return ret;
1018 /*********************************************************************
1019 * _wspawnvpe (MSVCRT.@)
1021 * Unicode version of _spawnvpe
1023 MSVCRT_intptr_t CDECL _wspawnvpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
1024 const MSVCRT_wchar_t* const* envv)
1026 MSVCRT_wchar_t *args, *envs;
1027 MSVCRT_intptr_t ret;
1029 args = msvcrt_argvtos(argv, ' ');
1030 envs = msvcrt_argvtos(envv, 0);
1032 ret = msvcrt_spawn(flags, name, args, envs, 1);
1034 MSVCRT_free(args);
1035 MSVCRT_free(envs);
1036 return ret;
1039 /*********************************************************************
1040 * _spawnvp (MSVCRT.@)
1042 * Like on Windows, this function does not handle arguments with spaces
1043 * or double-quotes.
1045 MSVCRT_intptr_t CDECL _spawnvp(int flags, const char* name, const char* const* argv)
1047 return _spawnvpe(flags, name, argv, NULL);
1050 /*********************************************************************
1051 * _wspawnvp (MSVCRT.@)
1053 * Unicode version of _spawnvp
1055 MSVCRT_intptr_t CDECL _wspawnvp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
1057 return _wspawnvpe(flags, name, argv, NULL);
1060 /*********************************************************************
1061 * _wpopen (MSVCRT.@)
1063 * Unicode version of _popen
1065 MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wchar_t* mode)
1067 MSVCRT_FILE *ret;
1068 BOOL readPipe = TRUE;
1069 int textmode, fds[2], fdToDup, fdToOpen, fdStdHandle = -1, fdStdErr = -1;
1070 const MSVCRT_wchar_t *p;
1071 MSVCRT_wchar_t *comspec, *fullcmd;
1072 unsigned int len;
1073 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1075 TRACE("(command=%s, mode=%s)\n", debugstr_w(command), debugstr_w(mode));
1077 if (!command || !mode)
1078 return NULL;
1080 textmode = *__p__fmode() & (MSVCRT__O_BINARY | MSVCRT__O_TEXT);
1081 for (p = mode; *p; p++)
1083 switch (*p)
1085 case 'W':
1086 case 'w':
1087 readPipe = FALSE;
1088 break;
1089 case 'B':
1090 case 'b':
1091 textmode |= MSVCRT__O_BINARY;
1092 textmode &= ~MSVCRT__O_TEXT;
1093 break;
1094 case 'T':
1095 case 't':
1096 textmode |= MSVCRT__O_TEXT;
1097 textmode &= ~MSVCRT__O_BINARY;
1098 break;
1101 if (MSVCRT__pipe(fds, 0, textmode) == -1)
1102 return NULL;
1104 fdToDup = readPipe ? 1 : 0;
1105 fdToOpen = readPipe ? 0 : 1;
1107 if ((fdStdHandle = MSVCRT__dup(fdToDup)) == -1)
1108 goto error;
1109 if (MSVCRT__dup2(fds[fdToDup], fdToDup) != 0)
1110 goto error;
1111 if (readPipe)
1113 if ((fdStdErr = MSVCRT__dup(MSVCRT_STDERR_FILENO)) == -1)
1114 goto error;
1115 if (MSVCRT__dup2(fds[fdToDup], MSVCRT_STDERR_FILENO) != 0)
1116 goto error;
1119 MSVCRT__close(fds[fdToDup]);
1121 if (!(comspec = msvcrt_get_comspec())) goto error;
1122 len = strlenW(comspec) + strlenW(flag) + strlenW(command) + 1;
1124 if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t)))) goto error;
1125 strcpyW(fullcmd, comspec);
1126 strcatW(fullcmd, flag);
1127 strcatW(fullcmd, command);
1128 HeapFree(GetProcessHeap(), 0, comspec);
1130 if (msvcrt_spawn(MSVCRT__P_NOWAIT, NULL, fullcmd, NULL, 1) == -1)
1132 MSVCRT__close(fds[fdToOpen]);
1133 ret = NULL;
1135 else
1137 ret = MSVCRT__wfdopen(fds[fdToOpen], mode);
1138 if (!ret)
1139 MSVCRT__close(fds[fdToOpen]);
1141 HeapFree(GetProcessHeap(), 0, fullcmd);
1142 MSVCRT__dup2(fdStdHandle, fdToDup);
1143 MSVCRT__close(fdStdHandle);
1144 if (readPipe)
1146 MSVCRT__dup2(fdStdErr, MSVCRT_STDERR_FILENO);
1147 MSVCRT__close(fdStdErr);
1149 return ret;
1151 error:
1152 if (fdStdHandle != -1) MSVCRT__close(fdStdHandle);
1153 if (fdStdErr != -1) MSVCRT__close(fdStdErr);
1154 MSVCRT__close(fds[0]);
1155 MSVCRT__close(fds[1]);
1156 return NULL;
1159 /*********************************************************************
1160 * _popen (MSVCRT.@)
1162 MSVCRT_FILE* CDECL MSVCRT__popen(const char* command, const char* mode)
1164 MSVCRT_FILE *ret;
1165 MSVCRT_wchar_t *cmdW, *modeW;
1167 TRACE("(command=%s, mode=%s)\n", debugstr_a(command), debugstr_a(mode));
1169 if (!command || !mode)
1170 return NULL;
1172 if (!(cmdW = msvcrt_wstrdupa(command))) return NULL;
1173 if (!(modeW = msvcrt_wstrdupa(mode)))
1175 HeapFree(GetProcessHeap(), 0, cmdW);
1176 return NULL;
1179 ret = MSVCRT__wpopen(cmdW, modeW);
1181 HeapFree(GetProcessHeap(), 0, cmdW);
1182 HeapFree(GetProcessHeap(), 0, modeW);
1183 return ret;
1186 /*********************************************************************
1187 * _pclose (MSVCRT.@)
1189 int CDECL MSVCRT__pclose(MSVCRT_FILE* file)
1191 return MSVCRT_fclose(file);
1194 /*********************************************************************
1195 * _wsystem (MSVCRT.@)
1197 * Unicode version of system
1199 int CDECL _wsystem(const MSVCRT_wchar_t* cmd)
1201 int res;
1202 MSVCRT_wchar_t *comspec, *fullcmd;
1203 unsigned int len;
1204 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1206 if (!(comspec = msvcrt_get_comspec())) return -1;
1207 len = strlenW(comspec) + strlenW(flag) + strlenW(cmd) + 1;
1209 if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
1211 HeapFree(GetProcessHeap(), 0, comspec);
1212 return -1;
1214 strcpyW(fullcmd, comspec);
1215 strcatW(fullcmd, flag);
1216 strcatW(fullcmd, cmd);
1218 res = msvcrt_spawn(MSVCRT__P_WAIT, comspec, fullcmd, NULL, 1);
1220 HeapFree(GetProcessHeap(), 0, comspec);
1221 HeapFree(GetProcessHeap(), 0, fullcmd);
1222 return res;
1225 /*********************************************************************
1226 * system (MSVCRT.@)
1228 int CDECL MSVCRT_system(const char* cmd)
1230 int res = -1;
1231 MSVCRT_wchar_t *cmdW;
1233 if ((cmdW = msvcrt_wstrdupa(cmd)))
1235 res = _wsystem(cmdW);
1236 HeapFree(GetProcessHeap(), 0, cmdW);
1238 return res;
1241 /*********************************************************************
1242 * _loaddll (MSVCRT.@)
1244 MSVCRT_intptr_t CDECL _loaddll(const char* dllname)
1246 return (MSVCRT_intptr_t)LoadLibraryA(dllname);
1249 /*********************************************************************
1250 * _unloaddll (MSVCRT.@)
1252 int CDECL _unloaddll(MSVCRT_intptr_t dll)
1254 if (FreeLibrary((HMODULE)dll))
1255 return 0;
1256 else
1258 int err = GetLastError();
1259 msvcrt_set_errno(err);
1260 return err;
1264 /*********************************************************************
1265 * _getdllprocaddr (MSVCRT.@)
1267 void * CDECL _getdllprocaddr(MSVCRT_intptr_t dll, const char *name, int ordinal)
1269 if (name)
1271 if (ordinal != -1) return NULL;
1272 return GetProcAddress( (HMODULE)dll, name );
1274 if (HIWORD(ordinal)) return NULL;
1275 return GetProcAddress( (HMODULE)dll, (LPCSTR)(ULONG_PTR)ordinal );