Compile fix for building wine outside the source tree.
[wine/testsucceed.git] / dlls / crtdll / spawn.c
blob5768469dedfedb6fe5b796ef68d3169f139a9f51
1 /*
2 * CRTDLL spawn functions
3 *
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
9 * These functions differ in whether they pass arguments as an array
10 * (v in the name) or as varags (l in the name), whether they
11 * seach the path (p in the name) and/or whether they take an
12 * environment (e in the name) or pass the parents environment.
13 * Args as Search Take
14 * Name varargs? path? environment?
15 * spawnl N N N
16 * spawnle N N Y
17 * spawnlp N Y N
18 * spawnlpe N Y Y
19 * spawnv Y N N
20 * spawnve Y N Y
21 * spawnvp Y Y N
22 * spawnvpe Y Y Y
24 * Implementation Notes:
25 * MT Safe - But only because of missing functionality.
27 * After translating input arguments into the required format for
28 * CreateProcess(), the internal function __CRTDLL__spawn() is
29 * called to perform the actual spawning.
31 * FIXME:
32 * -File handles need some special handling. Sometimes children get
33 * open file handles, sometimes not. The docs are confusing.
34 * -No check for maximum path/argument/environment size is done.
35 * -Wine has a "process.h" which is not the same as any crt version.
36 * Unresolved issues Uwe Bonnes 970904:
37 * -system-call calls another wine process, but without debugging arguments
38 * and uses the first wine executable in the path
41 #include "crtdll.h"
42 #include <errno.h>
43 #include "process.h"
44 #include <stdlib.h>
47 DEFAULT_DEBUG_CHANNEL(crtdll);
49 /* Process creation flags */
50 #define _P_WAIT 0
51 #define _P_NOWAIT 1
52 #define _P_OVERLAY 2
53 #define _P_NOWAITO 3
54 #define _P_DETACH 4
57 extern void __CRTDLL__set_errno(ULONG err);
58 extern LPVOID __cdecl CRTDLL_calloc(DWORD size, DWORD count);
59 extern VOID __cdecl CRTDLL_free(void *ptr);
60 extern VOID __cdecl CRTDLL__exit(LONG ret);
61 extern INT CRTDLL_doserrno;
64 /* INTERNAL: Spawn a child process */
65 static int __CRTDLL__spawn(INT flags, LPSTR exe, LPSTR args, LPSTR env);
66 static int __CRTDLL__spawn(INT flags, LPSTR exe, LPSTR args, LPSTR env)
68 STARTUPINFOA si;
69 PROCESS_INFORMATION pi;
71 if ((unsigned)flags > _P_DETACH)
73 CRTDLL_errno = EINVAL;
74 return -1;
77 FIXME(":must dup/kill streams for child process\n");
79 memset(&si, 0, sizeof(si));
80 si.cb = sizeof(si);
82 if (!CreateProcessA(exe, args, NULL, NULL, TRUE,
83 flags == _P_DETACH ? DETACHED_PROCESS : 0,
84 env, NULL, &si, &pi))
86 __CRTDLL__set_errno(GetLastError());
87 return -1;
90 switch(flags)
92 case _P_WAIT:
93 WaitForSingleObject(pi.hProcess,-1); /* wait forvever */
94 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
95 CloseHandle(pi.hProcess);
96 CloseHandle(pi.hThread);
97 return pi.dwProcessId;
98 case _P_DETACH:
99 CloseHandle(pi.hProcess);
100 pi.hProcess = 0;
101 /* fall through */
102 case _P_NOWAIT:
103 case _P_NOWAITO:
104 CloseHandle(pi.hThread);
105 return pi.hProcess;
106 case _P_OVERLAY:
107 CRTDLL__exit(0);
109 return -1; /* cant reach here */
113 /* INTERNAL: Convert argv list to a single 'delim'-seperated string */
114 static LPSTR __CRTDLL__argvtos(LPSTR *arg, CHAR delim);
115 static LPSTR __CRTDLL__argvtos(LPSTR *arg, CHAR delim)
117 LPSTR *search = arg;
118 LONG size = 0;
119 LPSTR ret;
121 if (!arg && !delim)
122 return NULL;
124 /* get length */
125 while(*search)
127 size += strlen(*search) + 1;
128 search++;
131 if (!(ret = (LPSTR)CRTDLL_calloc(size + 1, 1)))
132 return NULL;
134 /* fill string */
135 search = arg;
136 size = 0;
137 while(*search)
139 int strsize = strlen(*search);
140 memcpy(ret+size,*search,strsize);
141 ret[size+strsize] = delim;
142 size += strsize + 1;
143 search++;
145 return ret;
149 /*********************************************************************
150 * _spawnve (CRTDLL.274)
152 * Spawn a process.
155 HANDLE __cdecl CRTDLL__spawnve(INT flags, LPSTR name, LPSTR *argv, LPSTR *envv)
157 LPSTR args = __CRTDLL__argvtos(argv,' ');
158 LPSTR envs = __CRTDLL__argvtos(envv,0);
159 LPSTR fullname = name;
161 FIXME(":not translating name %s to locate program\n",fullname);
162 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
164 if (args)
166 HANDLE ret = __CRTDLL__spawn(flags, fullname, args, envs);
167 CRTDLL_free(args);
168 CRTDLL_free(envs);
169 return ret;
171 if (envs)
172 CRTDLL_free(envs);
174 WARN(":No argv[0] passed - process will not be executed");
175 return -1;
179 /*********************************************************************
180 * system (CRTDLL.485)
182 INT __cdecl CRTDLL_system(LPSTR x)
184 /* FIXME: should probably launch cmd interpreter in COMSPEC */
185 return __CRTDLL__spawn(_P_WAIT, NULL, x, NULL);