1 /*
2 * msvcrt.dll spawn/exec functions
3 *
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
9 *
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.
14 *
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.
19 *
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
23 *
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
28 */
29 #include "config.h"
30
31 #include <stdarg.h>
32
33 #include "msvcrt.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
38
39 static void msvcrt_search_executable(const MSVCRT_wchar_t *name, MSVCRT_wchar_t *fullname, int use_path)
40 {
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}};
44
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;
49
50 *fullname = '\0';
51 msvcrt_set_errno(ERROR_FILE_NOT_FOUND);
52
53 p = memchrW(name, '\0', MAX_PATH);
54 if (!p) p = name + MAX_PATH - 1;
55 name_len = p - name;
56
57 /* FIXME extra-long names are silently truncated */
58 memcpy(buffer, name, name_len * sizeof(MSVCRT_wchar_t));
59 buffer[name_len] = '\0';
60
61 /* try current dir first */
62 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
63 {
64 strcpyW(fullname, buffer);
65 return;
66 }
67
68 for (p--; p >= name; p--)
69 if (*p == '\\' || *p == '/' || *p == ':' || *p == '.') break;
70
71 /* if there's no extension, try some well-known extensions */
72 if ((p < name || *p != '.') && name_len <= MAX_PATH - 5)
73 {
74 for (i = 0; i < 4; i++)
75 {
76 memcpy(buffer + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t));
77 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
78 {
79 strcpyW(fullname, buffer);
80 return;
81 }
82 }
83 extension = 0;
84 }
85
86 if (!use_path || !(env = _wgetenv(path))) return;
87
88 /* now try search path */
89 do
90 {
91 p = env;
92 while (*p && *p != ';') p++;
93 if (p == env) return;
94
95 path_len = p - env;
96 if (path_len + name_len <= MAX_PATH - 2)
97 {
98 memcpy(buffer, env, path_len * sizeof(MSVCRT_wchar_t));
99 if (buffer[path_len] != '/' && buffer[path_len] != '\\')
100 {
101 buffer[path_len++] = '\\';
102 buffer[path_len] = '\0';
103 }
104 else buffer[path_len] = '\0';
105
106 strcatW(buffer, name);
107 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
108 {
109 strcpyW(fullname, buffer);
110 return;
111 }
112 }
113 /* again, if there's no extension, try some well-known extensions */
114 if (!extension && path_len + name_len <= MAX_PATH - 5)
115 {
116 for (i = 0; i < 4; i++)
117 {
118 memcpy(buffer + path_len + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t));
119 if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
120 {
121 strcpyW(fullname, buffer);
122 return;
123 }
124 }
125 }
126 env = *p ? p + 1 : p;
127 } while(1);
128 }
129
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)
132 {
133 STARTUPINFOW si;
134 PROCESS_INFORMATION pi;
135 MSVCRT_wchar_t fullname[MAX_PATH];
136
137 TRACE("%x %s %s %s %d\n", flags, debugstr_w(exe), debugstr_w(cmdline), debugstr_w(env), use_path);
138
139 if ((unsigned)flags > MSVCRT__P_DETACH)
140 {
141 *MSVCRT__errno() = MSVCRT_EINVAL;
142 return -1;
143 }
144
145 msvcrt_search_executable(exe, fullname, use_path);
146
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))
153 {
154 msvcrt_set_errno(GetLastError());
155 MSVCRT_free(si.lpReserved2);
156 return -1;
157 }
158
159 MSVCRT_free(si.lpReserved2);
160 switch(flags)
161 {
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);
178 }
179 return -1; /* can't reach here */
180 }
181
182 /* INTERNAL: Convert wide argv list to a single 'delim'-separated wide string, with an
183 * extra '\0' to terminate it.
184 */
185 static MSVCRT_wchar_t* msvcrt_argvtos(const MSVCRT_wchar_t* const* arg, MSVCRT_wchar_t delim)
186 {
187 const MSVCRT_wchar_t* const* a;
188 int size;
189 MSVCRT_wchar_t* p;
190 MSVCRT_wchar_t* ret;
191
192 if (!arg)
193 {
194 /* Return NULL for an empty environment list */
195 return NULL;
196 }
197
198 /* get length */
199 a = arg;
200 size = 0;
201 while (*a)
202 {
203 size += strlenW(*a) + 1;
204 a++;
205 }
206
207 ret = MSVCRT_malloc((size + 1) * sizeof(MSVCRT_wchar_t));
208 if (!ret)
209 return NULL;
210
211 /* fill string */
212 a = arg;
213 p = ret;
214 while (*a)
215 {
216 int len = strlenW(*a);
217 memcpy(p,*a,len * sizeof(MSVCRT_wchar_t));
218 p += len;
219 *p++ = delim;
220 a++;
221 }
222 if (delim && p > ret) p[-1] = 0;
223 else *p = 0;
224 return ret;
225 }
226
227 /* INTERNAL: Convert ansi argv list to a single 'delim'-separated wide string, with an
228 * extra '\0' to terminate it.
229 */
230 static MSVCRT_wchar_t *msvcrt_argvtos_aw(const char * const *arg, MSVCRT_wchar_t delim)
231 {
232 const char * const *a;
233 unsigned int len;
234 MSVCRT_wchar_t *p, *ret;
235
236 if (!arg)
237 {
238 /* Return NULL for an empty environment list */
239 return NULL;
240 }
241
242 /* get length */
243 a = arg;
244 len = 0;
245 while (*a)
246 {
247 len += MultiByteToWideChar(CP_ACP, 0, *a, -1, NULL, 0);
248 a++;
249 }
250
251 ret = MSVCRT_malloc((len + 1) * sizeof(MSVCRT_wchar_t));
252 if (!ret)
253 return NULL;
254
255 /* fill string */
256 a = arg;
257 p = ret;
258 while (*a)
259 {
260 p += MultiByteToWideChar(CP_ACP, 0, *a, strlen(*a), p, len - (p - ret));
261 *p++ = delim;
262 a++;
263 }
264 if (delim && p > ret) p[-1] = 0;
265 else *p = 0;
266 return ret;
267 }
268
269 /* INTERNAL: Convert wide va_list to a single 'delim'-separated wide string, with an
270 * extra '\0' to terminate it.
271 */
272 static MSVCRT_wchar_t *msvcrt_valisttos(const MSVCRT_wchar_t *arg0, __ms_va_list alist, MSVCRT_wchar_t delim)
273 {
274 unsigned int size = 0, pos = 0;
275 const MSVCRT_wchar_t *arg;
276 MSVCRT_wchar_t *new, *ret = NULL;
277
278 for (arg = arg0; arg; arg = va_arg( alist, MSVCRT_wchar_t * ))
279 {
280 unsigned int len = strlenW( arg ) + 1;
281 if (pos + len >= size)
282 {
283 size = max( 256, size * 2 );
284 size = max( size, pos + len + 1 );
285 if (!(new = MSVCRT_realloc( ret, size * sizeof(MSVCRT_wchar_t) )))
286 {
287 MSVCRT_free( ret );
288 return NULL;
289 }
290 ret = new;
291 }
292 strcpyW( ret + pos, arg );
293 pos += len;
294 ret[pos - 1] = delim;
295 }
296 if (pos)
297 {
298 if (delim) ret[pos - 1] = 0;
299 else ret[pos] = 0;
300 }
301 return ret;
302 }
303
304 /* INTERNAL: Convert ansi va_list to a single 'delim'-separated wide string, with an
305 * extra '\0' to terminate it.
306 */
307 static MSVCRT_wchar_t *msvcrt_valisttos_aw(const char *arg0, __ms_va_list alist, MSVCRT_wchar_t delim)
308 {
309 unsigned int size = 0, pos = 0;
310 const char *arg;
311 MSVCRT_wchar_t *new, *ret = NULL;
312
313 for (arg = arg0; arg; arg = va_arg( alist, char * ))
314 {
315 unsigned int len = MultiByteToWideChar( CP_ACP, 0, arg, -1, NULL, 0 );
316 if (pos + len >= size)
317 {
318 size = max( 256, size * 2 );
319 size = max( size, pos + len + 1 );
320 if (!(new = MSVCRT_realloc( ret, size * sizeof(MSVCRT_wchar_t) )))
321 {
322 MSVCRT_free( ret );
323 return NULL;
324 }
325 ret = new;
326 }
327 pos += MultiByteToWideChar( CP_ACP, 0, arg, -1, ret + pos, size - pos );
328 ret[pos - 1] = delim;
329 }
330 if (pos)
331 {
332 if (delim) ret[pos - 1] = 0;
333 else ret[pos] = 0;
334 }
335 return ret;
336 }
337
338 /* INTERNAL: retrieve COMSPEC environment variable */
339 static MSVCRT_wchar_t *msvcrt_get_comspec(void)
340 {
341 static const MSVCRT_wchar_t cmd[] = {'c','m','d',0};
342 static const MSVCRT_wchar_t comspec[] = {'C','O','M','S','P','E','C',0};
343 MSVCRT_wchar_t *ret;
344 unsigned int len;
345
346 if (!(len = GetEnvironmentVariableW(comspec, NULL, 0))) len = sizeof(cmd)/sizeof(MSVCRT_wchar_t);
347 if ((ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
348 {
349 if (!GetEnvironmentVariableW(comspec, ret, len)) strcpyW(ret, cmd);
350 }
351 return ret;
352 }
353
354 /*********************************************************************
355 * _cwait (MSVCRT.@)
356 */
357 MSVCRT_intptr_t CDECL _cwait(int *status, MSVCRT_intptr_t pid, int action)
358 {
359 HANDLE hPid = (HANDLE)pid;
360 int doserrno;
361
362 action = action; /* Remove warning */
363
364 if (!WaitForSingleObject(hPid, INFINITE))
365 {
366 if (status)
367 {
368 DWORD stat;
369 GetExitCodeProcess(hPid, &stat);
370 *status = (int)stat;
371 }
372 return pid;
373 }
374 doserrno = GetLastError();
375
376 if (doserrno == ERROR_INVALID_HANDLE)
377 {
378 *MSVCRT__errno() = MSVCRT_ECHILD;
379 *MSVCRT___doserrno() = doserrno;
380 }
381 else
382 msvcrt_set_errno(doserrno);
383
384 return status ? *status = -1 : -1;
385 }
386
387 /*********************************************************************
388 * _wexecl (MSVCRT.@)
389 *
390 * Unicode version of _execl
391 */
392 MSVCRT_intptr_t CDECL _wexecl(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
393 {
394 __ms_va_list ap;
395 MSVCRT_wchar_t *args;
396 MSVCRT_intptr_t ret;
397
398 __ms_va_start(ap, arg0);
399 args = msvcrt_valisttos(arg0, ap, ' ');
400 __ms_va_end(ap);
401
402 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 0);
403
404 MSVCRT_free(args);
405 return ret;
406 }
407
408 /*********************************************************************
409 * _execl (MSVCRT.@)
410 *
411 * Like on Windows, this function does not handle arguments with spaces
412 * or double-quotes.
413 */
414 MSVCRT_intptr_t CDECL _execl(const char* name, const char* arg0, ...)
415 {
416 __ms_va_list ap;
417 MSVCRT_wchar_t *nameW, *args;
418 MSVCRT_intptr_t ret;
419
420 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
421
422 __ms_va_start(ap, arg0);
423 args = msvcrt_valisttos_aw(arg0, ap, ' ');
424 __ms_va_end(ap);
425
426 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 0);
427
428 MSVCRT_free(nameW);
429 MSVCRT_free(args);
430 return ret;
431 }
432
433 /*********************************************************************
434 * _wexecle (MSVCRT.@)
435 *
436 * Unicode version of _execle
437 */
438 MSVCRT_intptr_t CDECL _wexecle(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
439 {
440 __ms_va_list ap;
441 MSVCRT_wchar_t *args, *envs = NULL;
442 const MSVCRT_wchar_t * const *envp;
443 MSVCRT_intptr_t ret;
444
445 __ms_va_start(ap, arg0);
446 args = msvcrt_valisttos(arg0, ap, ' ');
447 __ms_va_end(ap);
448
449 __ms_va_start(ap, arg0);
450 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
451 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
452 if (envp) envs = msvcrt_argvtos(envp, 0);
453 __ms_va_end(ap);
454
455 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 0);
456
457 MSVCRT_free(args);
458 MSVCRT_free(envs);
459 return ret;
460 }
461
462 /*********************************************************************
463 * _execle (MSVCRT.@)
464 */
465 MSVCRT_intptr_t CDECL _execle(const char* name, const char* arg0, ...)
466 {
467 __ms_va_list ap;
468 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
469 const char * const *envp;
470 MSVCRT_intptr_t ret;
471
472 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
473
474 __ms_va_start(ap, arg0);
475 args = msvcrt_valisttos_aw(arg0, ap, ' ');
476 __ms_va_end(ap);
477
478 __ms_va_start(ap, arg0);
479 while (va_arg( ap, char * ) != NULL) /*nothing*/;
480 envp = va_arg( ap, const char * const * );
481 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
482 __ms_va_end(ap);
483
484 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 0);
485
486 MSVCRT_free(nameW);
487 MSVCRT_free(args);
488 MSVCRT_free(envs);
489 return ret;
490 }
491
492 /*********************************************************************
493 * _wexeclp (MSVCRT.@)
494 *
495 * Unicode version of _execlp
496 */
497 MSVCRT_intptr_t CDECL _wexeclp(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
498 {
499 __ms_va_list ap;
500 MSVCRT_wchar_t *args;
501 MSVCRT_intptr_t ret;
502
503 __ms_va_start(ap, arg0);
504 args = msvcrt_valisttos(arg0, ap, ' ');
505 __ms_va_end(ap);
506
507 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 1);
508
509 MSVCRT_free(args);
510 return ret;
511 }
512
513 /*********************************************************************
514 * _execlp (MSVCRT.@)
515 *
516 * Like on Windows, this function does not handle arguments with spaces
517 * or double-quotes.
518 */
519 MSVCRT_intptr_t CDECL _execlp(const char* name, const char* arg0, ...)
520 {
521 __ms_va_list ap;
522 MSVCRT_wchar_t *nameW, *args;
523 MSVCRT_intptr_t ret;
524
525 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
526
527 __ms_va_start(ap, arg0);
528 args = msvcrt_valisttos_aw(arg0, ap, ' ');
529 __ms_va_end(ap);
530
531 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 1);
532
533 MSVCRT_free(nameW);
534 MSVCRT_free(args);
535 return ret;
536 }
537
538 /*********************************************************************
539 * _wexeclpe (MSVCRT.@)
540 *
541 * Unicode version of _execlpe
542 */
543 MSVCRT_intptr_t CDECL _wexeclpe(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
544 {
545 __ms_va_list ap;
546 MSVCRT_wchar_t *args, *envs = NULL;
547 const MSVCRT_wchar_t * const *envp;
548 MSVCRT_intptr_t ret;
549
550 __ms_va_start(ap, arg0);
551 args = msvcrt_valisttos(arg0, ap, ' ');
552 __ms_va_end(ap);
553
554 __ms_va_start(ap, arg0);
555 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
556 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
557 if (envp) envs = msvcrt_argvtos(envp, 0);
558 __ms_va_end(ap);
559
560 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 1);
561
562 MSVCRT_free(args);
563 MSVCRT_free(envs);
564 return ret;
565 }
566
567 /*********************************************************************
568 * _execlpe (MSVCRT.@)
569 */
570 MSVCRT_intptr_t CDECL _execlpe(const char* name, const char* arg0, ...)
571 {
572 __ms_va_list ap;
573 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
574 const char * const *envp;
575 MSVCRT_intptr_t ret;
576
577 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
578
579 __ms_va_start(ap, arg0);
580 args = msvcrt_valisttos_aw(arg0, ap, ' ');
581 __ms_va_end(ap);
582
583 __ms_va_start(ap, arg0);
584 while (va_arg( ap, char * ) != NULL) /*nothing*/;
585 envp = va_arg( ap, const char * const * );
586 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
587 __ms_va_end(ap);
588
589 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 1);
590
591 MSVCRT_free(nameW);
592 MSVCRT_free(args);
593 MSVCRT_free(envs);
594 return ret;
595 }
596
597 /*********************************************************************
598 * _wexecv (MSVCRT.@)
599 *
600 * Unicode version of _execv
601 */
602 MSVCRT_intptr_t CDECL _wexecv(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv)
603 {
604 return _wspawnve(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, NULL);
605 }
606
607 /*********************************************************************
608 * _execv (MSVCRT.@)
609 *
610 * Like on Windows, this function does not handle arguments with spaces
611 * or double-quotes.
612 */
613 MSVCRT_intptr_t CDECL _execv(const char* name, char* const* argv)
614 {
615 return _spawnve(MSVCRT__P_OVERLAY, name, (const char* const*) argv, NULL);
616 }
617
618 /*********************************************************************
619 * _wexecve (MSVCRT.@)
620 *
621 * Unicode version of _execve
622 */
623 MSVCRT_intptr_t CDECL _wexecve(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
624 {
625 return _wspawnve(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, envv);
626 }
627
628 /*********************************************************************
629 * _execve (MSVCRT.@)
630 *
631 * Like on Windows, this function does not handle arguments with spaces
632 * or double-quotes.
633 */
634 MSVCRT_intptr_t CDECL MSVCRT__execve(const char* name, char* const* argv, const char* const* envv)
635 {
636 return _spawnve(MSVCRT__P_OVERLAY, name, (const char* const*) argv, envv);
637 }
638
639 /*********************************************************************
640 * _wexecvpe (MSVCRT.@)
641 *
642 * Unicode version of _execvpe
643 */
644 MSVCRT_intptr_t CDECL _wexecvpe(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
645 {
646 return _wspawnvpe(MSVCRT__P_OVERLAY, name, (const MSVCRT_wchar_t* const*) argv, envv);
647 }
648
649 /*********************************************************************
650 * _execvpe (MSVCRT.@)
651 *
652 * Like on Windows, this function does not handle arguments with spaces
653 * or double-quotes.
654 */
655 MSVCRT_intptr_t CDECL _execvpe(const char* name, char* const* argv, const char* const* envv)
656 {
657 return _spawnvpe(MSVCRT__P_OVERLAY, name, (const char* const*) argv, envv);
658 }
659
660 /*********************************************************************
661 * _wexecvp (MSVCRT.@)
662 *
663 * Unicode version of _execvp
664 */
665 MSVCRT_intptr_t CDECL _wexecvp(const MSVCRT_wchar_t* name, MSVCRT_wchar_t* const* argv)
666 {
667 return _wexecvpe(name, argv, NULL);
668 }
669
670 /*********************************************************************
671 * _execvp (MSVCRT.@)
672 *
673 * Like on Windows, this function does not handle arguments with spaces
674 * or double-quotes.
675 */
676 MSVCRT_intptr_t CDECL _execvp(const char* name, char* const* argv)
677 {
678 return _execvpe(name, argv, NULL);
679 }
680
681 /*********************************************************************
682 * _wspawnl (MSVCRT.@)
683 *
684 * Unicode version of _spawnl
685 */
686 MSVCRT_intptr_t CDECL _wspawnl(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
687 {
688 __ms_va_list ap;
689 MSVCRT_wchar_t *args;
690 MSVCRT_intptr_t ret;
691
692 __ms_va_start(ap, arg0);
693 args = msvcrt_valisttos(arg0, ap, ' ');
694 __ms_va_end(ap);
695
696 ret = msvcrt_spawn(flags, name, args, NULL, 0);
697
698 MSVCRT_free(args);
699 return ret;
700 }
701
702 /*********************************************************************
703 * _spawnl (MSVCRT.@)
704 *
705 * Like on Windows, this function does not handle arguments with spaces
706 * or double-quotes.
707 */
708 MSVCRT_intptr_t CDECL _spawnl(int flags, const char* name, const char* arg0, ...)
709 {
710 __ms_va_list ap;
711 MSVCRT_wchar_t *nameW, *args;
712 MSVCRT_intptr_t ret;
713
714 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
715
716 __ms_va_start(ap, arg0);
717 args = msvcrt_valisttos_aw(arg0, ap, ' ');
718 __ms_va_end(ap);
719
720 ret = msvcrt_spawn(flags, nameW, args, NULL, 0);
721
722 MSVCRT_free(nameW);
723 MSVCRT_free(args);
724 return ret;
725 }
726
727 /*********************************************************************
728 * _wspawnle (MSVCRT.@)
729 *
730 * Unicode version of _spawnle
731 */
732 MSVCRT_intptr_t CDECL _wspawnle(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
733 {
734 __ms_va_list ap;
735 MSVCRT_wchar_t *args, *envs = NULL;
736 const MSVCRT_wchar_t * const *envp;
737 MSVCRT_intptr_t ret;
738
739 __ms_va_start(ap, arg0);
740 args = msvcrt_valisttos(arg0, ap, ' ');
741 __ms_va_end(ap);
742
743 __ms_va_start(ap, arg0);
744 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
745 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
746 if (envp) envs = msvcrt_argvtos(envp, 0);
747 __ms_va_end(ap);
748
749 ret = msvcrt_spawn(flags, name, args, envs, 0);
750
751 MSVCRT_free(args);
752 MSVCRT_free(envs);
753 return ret;
754 }
755
756 /*********************************************************************
757 * _spawnle (MSVCRT.@)
758 */
759 MSVCRT_intptr_t CDECL _spawnle(int flags, const char* name, const char* arg0, ...)
760 {
761 __ms_va_list ap;
762 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
763 const char * const *envp;
764 MSVCRT_intptr_t ret;
765
766 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
767
768 __ms_va_start(ap, arg0);
769 args = msvcrt_valisttos_aw(arg0, ap, ' ');
770 __ms_va_end(ap);
771
772 __ms_va_start(ap, arg0);
773 while (va_arg( ap, char * ) != NULL) /*nothing*/;
774 envp = va_arg( ap, const char * const * );
775 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
776 __ms_va_end(ap);
777
778 ret = msvcrt_spawn(flags, nameW, args, envs, 0);
779
780 MSVCRT_free(nameW);
781 MSVCRT_free(args);
782 MSVCRT_free(envs);
783 return ret;
784 }
785
786 /*********************************************************************
787 * _wspawnlp (MSVCRT.@)
788 *
789 * Unicode version of _spawnlp
790 */
791 MSVCRT_intptr_t CDECL _wspawnlp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
792 {
793 __ms_va_list ap;
794 MSVCRT_wchar_t *args;
795 MSVCRT_intptr_t ret;
796
797 __ms_va_start(ap, arg0);
798 args = msvcrt_valisttos(arg0, ap, ' ');
799 __ms_va_end(ap);
800
801 ret = msvcrt_spawn(flags, name, args, NULL, 1);
802
803 MSVCRT_free(args);
804 return ret;
805 }
806
807 /*********************************************************************
808 * _spawnlp (MSVCRT.@)
809 *
810 * Like on Windows, this function does not handle arguments with spaces
811 * or double-quotes.
812 */
813 MSVCRT_intptr_t CDECL _spawnlp(int flags, const char* name, const char* arg0, ...)
814 {
815 __ms_va_list ap;
816 MSVCRT_wchar_t *nameW, *args;
817 MSVCRT_intptr_t ret;
818
819 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
820
821 __ms_va_start(ap, arg0);
822 args = msvcrt_valisttos_aw(arg0, ap, ' ');
823 __ms_va_end(ap);
824
825 ret = msvcrt_spawn(flags, nameW, args, NULL, 1);
826
827 MSVCRT_free(nameW);
828 MSVCRT_free(args);
829 return ret;
830 }
831
832 /*********************************************************************
833 * _wspawnlpe (MSVCRT.@)
834 *
835 * Unicode version of _spawnlpe
836 */
837 MSVCRT_intptr_t CDECL _wspawnlpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
838 {
839 __ms_va_list ap;
840 MSVCRT_wchar_t *args, *envs = NULL;
841 const MSVCRT_wchar_t * const *envp;
842 MSVCRT_intptr_t ret;
843
844 __ms_va_start(ap, arg0);
845 args = msvcrt_valisttos(arg0, ap, ' ');
846 __ms_va_end(ap);
847
848 __ms_va_start(ap, arg0);
849 while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
850 envp = va_arg( ap, const MSVCRT_wchar_t * const * );
851 if (envp) envs = msvcrt_argvtos(envp, 0);
852 __ms_va_end(ap);
853
854 ret = msvcrt_spawn(flags, name, args, envs, 1);
855
856 MSVCRT_free(args);
857 MSVCRT_free(envs);
858 return ret;
859 }
860
861 /*********************************************************************
862 * _spawnlpe (MSVCRT.@)
863 */
864 MSVCRT_intptr_t CDECL _spawnlpe(int flags, const char* name, const char* arg0, ...)
865 {
866 __ms_va_list ap;
867 MSVCRT_wchar_t *nameW, *args, *envs = NULL;
868 const char * const *envp;
869 MSVCRT_intptr_t ret;
870
871 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
872
873 __ms_va_start(ap, arg0);
874 args = msvcrt_valisttos_aw(arg0, ap, ' ');
875 __ms_va_end(ap);
876
877 __ms_va_start(ap, arg0);
878 while (va_arg( ap, char * ) != NULL) /*nothing*/;
879 envp = va_arg( ap, const char * const * );
880 if (envp) envs = msvcrt_argvtos_aw(envp, 0);
881 __ms_va_end(ap);
882
883 ret = msvcrt_spawn(flags, nameW, args, envs, 1);
884
885 MSVCRT_free(nameW);
886 MSVCRT_free(args);
887 MSVCRT_free(envs);
888 return ret;
889 }
890
891 /*********************************************************************
892 * _spawnve (MSVCRT.@)
893 *
894 * Like on Windows, this function does not handle arguments with spaces
895 * or double-quotes.
896 */
897 MSVCRT_intptr_t CDECL _spawnve(int flags, const char* name, const char* const* argv,
898 const char* const* envv)
899 {
900 MSVCRT_wchar_t *nameW, *args, *envs;
901 MSVCRT_intptr_t ret;
902
903 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
904
905 args = msvcrt_argvtos_aw(argv, ' ');
906 envs = msvcrt_argvtos_aw(envv, 0);
907
908 ret = msvcrt_spawn(flags, nameW, args, envs, 0);
909
910 MSVCRT_free(nameW);
911 MSVCRT_free(args);
912 MSVCRT_free(envs);
913 return ret;
914 }
915
916 /*********************************************************************
917 * _wspawnve (MSVCRT.@)
918 *
919 * Unicode version of _spawnve
920 */
921 MSVCRT_intptr_t CDECL _wspawnve(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
922 const MSVCRT_wchar_t* const* envv)
923 {
924 MSVCRT_wchar_t *args, *envs;
925 MSVCRT_intptr_t ret;
926
927 args = msvcrt_argvtos(argv, ' ');
928 envs = msvcrt_argvtos(envv, 0);
929
930 ret = msvcrt_spawn(flags, name, args, envs, 0);
931
932 MSVCRT_free(args);
933 MSVCRT_free(envs);
934 return ret;
935 }
936
937 /*********************************************************************
938 * _spawnv (MSVCRT.@)
939 *
940 * Like on Windows, this function does not handle arguments with spaces
941 * or double-quotes.
942 */
943 MSVCRT_intptr_t CDECL _spawnv(int flags, const char* name, const char* const* argv)
944 {
945 return _spawnve(flags, name, argv, NULL);
946 }
947
948 /*********************************************************************
949 * _wspawnv (MSVCRT.@)
950 *
951 * Unicode version of _spawnv
952 */
953 MSVCRT_intptr_t CDECL _wspawnv(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
954 {
955 return _wspawnve(flags, name, argv, NULL);
956 }
957
958 /*********************************************************************
959 * _spawnvpe (MSVCRT.@)
960 *
961 * Like on Windows, this function does not handle arguments with spaces
962 * or double-quotes.
963 */
964 MSVCRT_intptr_t CDECL _spawnvpe(int flags, const char* name, const char* const* argv,
965 const char* const* envv)
966 {
967 MSVCRT_wchar_t *nameW, *args, *envs;
968 MSVCRT_intptr_t ret;
969
970 if (!(nameW = msvcrt_wstrdupa(name))) return -1;
971
972 args = msvcrt_argvtos_aw(argv, ' ');
973 envs = msvcrt_argvtos_aw(envv, 0);
974
975 ret = msvcrt_spawn(flags, nameW, args, envs, 1);
976
977 MSVCRT_free(nameW);
978 MSVCRT_free(args);
979 MSVCRT_free(envs);
980 return ret;
981 }
982
983 /*********************************************************************
984 * _wspawnvpe (MSVCRT.@)
985 *
986 * Unicode version of _spawnvpe
987 */
988 MSVCRT_intptr_t CDECL _wspawnvpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
989 const MSVCRT_wchar_t* const* envv)
990 {
991 MSVCRT_wchar_t *args, *envs;
992 MSVCRT_intptr_t ret;
993
994 args = msvcrt_argvtos(argv, ' ');
995 envs = msvcrt_argvtos(envv, 0);
996
997 ret = msvcrt_spawn(flags, name, args, envs, 1);
998
999 MSVCRT_free(args);
1000 MSVCRT_free(envs);
1001 return ret;
1002 }
1003
1004 /*********************************************************************
1005 * _spawnvp (MSVCRT.@)
1006 *
1007 * Like on Windows, this function does not handle arguments with spaces
1008 * or double-quotes.
1009 */
1010 MSVCRT_intptr_t CDECL _spawnvp(int flags, const char* name, const char* const* argv)
1011 {
1012 return _spawnvpe(flags, name, argv, NULL);
1013 }
1014
1015 /*********************************************************************
1016 * _wspawnvp (MSVCRT.@)
1017 *
1018 * Unicode version of _spawnvp
1019 */
1020 MSVCRT_intptr_t CDECL _wspawnvp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
1021 {
1022 return _wspawnvpe(flags, name, argv, NULL);
1023 }
1024
1025 /*********************************************************************
1026 * _wpopen (MSVCRT.@)
1027 *
1028 * Unicode version of _popen
1029 */
1030 MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wchar_t* mode)
1031 {
1032 MSVCRT_FILE *ret;
1033 BOOL readPipe = TRUE;
1034 int textmode, fds[2], fdToDup, fdToOpen, fdStdHandle = -1, fdStdErr = -1;
1035 const MSVCRT_wchar_t *p;
1036 MSVCRT_wchar_t *comspec, *fullcmd;
1037 unsigned int len;
1038 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1039
1040 TRACE("(command=%s, mode=%s)\n", debugstr_w(command), debugstr_w(mode));
1041
1042 if (!command || !mode)
1043 return NULL;
1044
1045 textmode = *__p__fmode() & (MSVCRT__O_BINARY | MSVCRT__O_TEXT);
1046 for (p = mode; *p; p++)
1047 {
1048 switch (*p)
1049 {
1050 case 'W':
1051 case 'w':
1052 readPipe = FALSE;
1053 break;
1054 case 'B':
1055 case 'b':
1056 textmode |= MSVCRT__O_BINARY;
1057 textmode &= ~MSVCRT__O_TEXT;
1058 break;
1059 case 'T':
1060 case 't':
1061 textmode |= MSVCRT__O_TEXT;
1062 textmode &= ~MSVCRT__O_BINARY;
1063 break;
1064 }
1065 }
1066 if (MSVCRT__pipe(fds, 0, textmode) == -1)
1067 return NULL;
1068
1069 fdToDup = readPipe ? 1 : 0;
1070 fdToOpen = readPipe ? 0 : 1;
1071
1072 if ((fdStdHandle = MSVCRT__dup(fdToDup)) == -1)
1073 goto error;
1074 if (MSVCRT__dup2(fds[fdToDup], fdToDup) != 0)
1075 goto error;
1076 if (readPipe)
1077 {
1078 if ((fdStdErr = MSVCRT__dup(MSVCRT_STDERR_FILENO)) == -1)
1079 goto error;
1080 if (MSVCRT__dup2(fds[fdToDup], MSVCRT_STDERR_FILENO) != 0)
1081 goto error;
1082 }
1083
1084 MSVCRT__close(fds[fdToDup]);
1085
1086 if (!(comspec = msvcrt_get_comspec())) goto error;
1087 len = strlenW(comspec) + strlenW(flag) + strlenW(command) + 1;
1088
1089 if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t)))) goto error;
1090 strcpyW(fullcmd, comspec);
1091 strcatW(fullcmd, flag);
1092 strcatW(fullcmd, command);
1093
1094 if (msvcrt_spawn(MSVCRT__P_NOWAIT, comspec, fullcmd, NULL, 1) == -1)
1095 {
1096 MSVCRT__close(fds[fdToOpen]);
1097 ret = NULL;
1098 }
1099 else
1100 {
1101 ret = MSVCRT__wfdopen(fds[fdToOpen], mode);
1102 if (!ret)
1103 MSVCRT__close(fds[fdToOpen]);
1104 }
1105 HeapFree(GetProcessHeap(), 0, comspec);
1106 HeapFree(GetProcessHeap(), 0, fullcmd);
1107 MSVCRT__dup2(fdStdHandle, fdToDup);
1108 MSVCRT__close(fdStdHandle);
1109 if (readPipe)
1110 {
1111 MSVCRT__dup2(fdStdErr, MSVCRT_STDERR_FILENO);
1112 MSVCRT__close(fdStdErr);
1113 }
1114 return ret;
1115
1116 error:
1117 if (fdStdHandle != -1) MSVCRT__close(fdStdHandle);
1118 if (fdStdErr != -1) MSVCRT__close(fdStdErr);
1119 MSVCRT__close(fds[0]);
1120 MSVCRT__close(fds[1]);
1121 return NULL;
1122 }
1123
1124 /*********************************************************************
1125 * _popen (MSVCRT.@)
1126 */
1127 MSVCRT_FILE* CDECL MSVCRT__popen(const char* command, const char* mode)
1128 {
1129 MSVCRT_FILE *ret;
1130 MSVCRT_wchar_t *cmdW, *modeW;
1131
1132 TRACE("(command=%s, mode=%s)\n", debugstr_a(command), debugstr_a(mode));
1133
1134 if (!command || !mode)
1135 return NULL;
1136
1137 if (!(cmdW = msvcrt_wstrdupa(command))) return NULL;
1138 if (!(modeW = msvcrt_wstrdupa(mode)))
1139 {
1140 HeapFree(GetProcessHeap(), 0, cmdW);
1141 return NULL;
1142 }
1143
1144 ret = MSVCRT__wpopen(cmdW, modeW);
1145
1146 HeapFree(GetProcessHeap(), 0, cmdW);
1147 HeapFree(GetProcessHeap(), 0, modeW);
1148 return ret;
1149 }
1150
1151 /*********************************************************************
1152 * _pclose (MSVCRT.@)
1153 */
1154 int CDECL MSVCRT__pclose(MSVCRT_FILE* file)
1155 {
1156 return MSVCRT_fclose(file);
1157 }
1158
1159 /*********************************************************************
1160 * _wsystem (MSVCRT.@)
1161 *
1162 * Unicode version of system
1163 */
1164 int CDECL _wsystem(const MSVCRT_wchar_t* cmd)
1165 {
1166 int res;
1167 MSVCRT_wchar_t *comspec, *fullcmd;
1168 unsigned int len;
1169 static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1170
1171 if (!(comspec = msvcrt_get_comspec())) return -1;
1172 len = strlenW(comspec) + strlenW(flag) + strlenW(cmd) + 1;
1173
1174 if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
1175 {
1176 HeapFree(GetProcessHeap(), 0, comspec);
1177 return -1;
1178 }
1179 strcpyW(fullcmd, comspec);
1180 strcatW(fullcmd, flag);
1181 strcatW(fullcmd, cmd);
1182
1183 res = msvcrt_spawn(MSVCRT__P_WAIT, comspec, fullcmd, NULL, 1);
1184
1185 HeapFree(GetProcessHeap(), 0, comspec);
1186 HeapFree(GetProcessHeap(), 0, fullcmd);
1187 return res;
1188 }
1189
1190 /*********************************************************************
1191 * system (MSVCRT.@)
1192 */
1193 int CDECL MSVCRT_system(const char* cmd)
1194 {
1195 int res = -1;
1196 MSVCRT_wchar_t *cmdW;
1197
1198 if ((cmdW = msvcrt_wstrdupa(cmd)))
1199 {
1200 res = _wsystem(cmdW);
1201 HeapFree(GetProcessHeap(), 0, cmdW);
1202 }
1203 return res;
1204 }
1205
1206 /*********************************************************************
1207 * _loaddll (MSVCRT.@)
1208 */
1209 MSVCRT_intptr_t CDECL _loaddll(const char* dllname)
1210 {
1211 return (MSVCRT_intptr_t)LoadLibraryA(dllname);
1212 }
1213
1214 /*********************************************************************
1215 * _unloaddll (MSVCRT.@)
1216 */
1217 int CDECL _unloaddll(MSVCRT_intptr_t dll)
1218 {
1219 if (FreeLibrary((HMODULE)dll))
1220 return 0;
1221 else
1222 {
1223 int err = GetLastError();
1224 msvcrt_set_errno(err);
1225 return err;
1226 }
1227 }
1228
1229 /*********************************************************************
1230 * _getdllprocaddr (MSVCRT.@)
1231 */
1232 void * CDECL _getdllprocaddr(MSVCRT_intptr_t dll, const char *name, int ordinal)
1233 {
1234 if (name)
1235 {
1236 if (ordinal != -1) return NULL;
1237 return GetProcAddress( (HMODULE)dll, name );
1238 }
1239 if (HIWORD(ordinal)) return NULL;
1240 return GetProcAddress( (HMODULE)dll, (LPCSTR)(ULONG_PTR)ordinal );
1241 }
1242
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.