- New msvcrt unicode functions, winapi_check/-Wall/-W clean.
[wine.git] / dlls / msvcrt / process.c
blob94efbafb8d39d810e8d62de20673044ac2a2aa3a
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
9 * FIXME:
10 * -File handles need some special handling. Sometimes children get
11 * open file handles, sometimes not. The docs are confusing
12 * -No check for maximum path/argument/environment size is done
14 #include "msvcrt.h"
15 #include "ms_errno.h"
17 DEFAULT_DEBUG_CHANNEL(msvcrt);
19 /* Process creation flags */
20 #define _P_WAIT 0
21 #define _P_NOWAIT 1
22 #define _P_OVERLAY 2
23 #define _P_NOWAITO 3
24 #define _P_DETACH 4
26 void __cdecl MSVCRT__exit(int);
27 void __cdecl MSVCRT__searchenv(const char* file, const char* env, char *buf);
29 /* FIXME: Check file extenstions for app to run */
30 static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
31 static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
32 static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
33 static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
35 /* INTERNAL: Spawn a child process */
36 static int __MSVCRT__spawn(int flags, const char *exe, char * args, char *env)
38 STARTUPINFOA si;
39 PROCESS_INFORMATION pi;
41 if (sizeof(HANDLE) != sizeof(int))
42 WARN("This call is unsuitable for your architecture\n");
44 if ((unsigned)flags > _P_DETACH)
46 SET_THREAD_VAR(errno,MSVCRT_EINVAL);
47 return -1;
50 FIXME(":must dup/kill streams for child process\n");
52 memset(&si, 0, sizeof(si));
53 si.cb = sizeof(si);
55 if (!CreateProcessA(exe, args, NULL, NULL, TRUE,
56 flags == _P_DETACH ? DETACHED_PROCESS : 0,
57 env, NULL, &si, &pi))
59 MSVCRT__set_errno(GetLastError());
60 return -1;
63 switch(flags)
65 case _P_WAIT:
66 WaitForSingleObject(pi.hProcess,-1); /* wait forvever */
67 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
68 CloseHandle(pi.hProcess);
69 CloseHandle(pi.hThread);
70 return (int)pi.dwProcessId;
71 case _P_DETACH:
72 CloseHandle(pi.hProcess);
73 pi.hProcess = 0;
74 /* fall through */
75 case _P_NOWAIT:
76 case _P_NOWAITO:
77 CloseHandle(pi.hThread);
78 return (int)pi.hProcess;
79 case _P_OVERLAY:
80 MSVCRT__exit(0);
82 return -1; /* can't reach here */
85 /* INTERNAL: Convert argv list to a single 'delim'-seperated string */
86 static char * __MSVCRT__argvtos(const char * *arg, char delim)
88 const char **search = arg;
89 long size = 0;
90 char *ret;
92 if (!arg && !delim)
93 return NULL;
95 /* get length */
96 while(*search)
98 size += strlen(*search) + 1;
99 search++;
102 if (!(ret = (char *)MSVCRT_calloc(size + 1, 1)))
103 return NULL;
105 /* fill string */
106 search = arg;
107 size = 0;
108 while(*search)
110 int strsize = strlen(*search);
111 memcpy(ret+size,*search,strsize);
112 ret[size+strsize] = delim;
113 size += strsize + 1;
114 search++;
116 return ret;
119 /*********************************************************************
120 * _cwait (MSVCRT.@)
122 int __cdecl MSVCRT__cwait(int *status, int pid, int action)
124 HANDLE hPid = (HANDLE)pid;
125 int doserrno;
127 action = action; /* Remove warning */
129 if (!WaitForSingleObject(hPid, -1)) /* wait forever */
131 if (status)
133 DWORD stat;
134 GetExitCodeProcess(hPid, &stat);
135 *status = (int)stat;
137 return (int)pid;
139 doserrno = GetLastError();
141 if (doserrno == ERROR_INVALID_HANDLE)
143 SET_THREAD_VAR(errno, MSVCRT_ECHILD);
144 SET_THREAD_VAR(doserrno,doserrno);
146 else
147 MSVCRT__set_errno(doserrno);
149 return status ? *status = -1 : -1;
152 /*********************************************************************
153 * _spawnve (MSVCRT.@)
155 int __cdecl MSVCRT__spawnve(int flags, const char *name, const char **argv,
156 const char **envv)
158 char * args = __MSVCRT__argvtos(argv,' ');
159 char * envs = __MSVCRT__argvtos(envv,0);
160 const char *fullname = name;
161 int ret = -1;
163 FIXME(":not translating name %s to locate program\n",fullname);
164 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
166 if (args)
168 ret = __MSVCRT__spawn(flags, fullname, args, envs);
169 MSVCRT_free(args);
171 if (envs)
172 MSVCRT_free(envs);
174 return ret;
177 /*********************************************************************
178 * _spawnv (MSVCRT.@)
180 int __cdecl MSVCRT__spawnv(int flags, const char *name, const char **argv)
182 return MSVCRT__spawnve(flags, name, argv, NULL);
185 /*********************************************************************
186 * _spawnvpe (MSVCRT.@)
188 int __cdecl MSVCRT__spawnvpe(int flags, const char *name, const char **argv,
189 const char **envv)
191 char fullname[MAX_PATH];
192 MSVCRT__searchenv(name, "PATH", fullname);
193 return MSVCRT__spawnve(flags, fullname[0] ? fullname : name, argv, envv);
196 /*********************************************************************
197 * _spawnvp (MSVCRT.@)
199 int __cdecl MSVCRT__spawnvp(int flags, const char *name, const char **argv)
201 return MSVCRT__spawnvpe(flags, name, argv, NULL);
204 /*********************************************************************
205 * system (MSVCRT.@)
207 int __cdecl MSVCRT_system(const char *cmd)
209 /* FIXME: should probably launch cmd interpreter in COMSPEC */
210 return __MSVCRT__spawn(_P_WAIT, cmd, NULL, NULL);
213 /*********************************************************************
214 * _loaddll (MSVCRT.@)
216 int __cdecl MSVCRT__loaddll(const char *dllname)
218 return LoadLibraryA(dllname);
221 /*********************************************************************
222 * _unloaddll (MSVCRT.@)
224 int __cdecl MSVCRT__unloaddll(int dll)
226 if (FreeLibrary((HANDLE)dll))
227 return 0;
228 else
230 int err = GetLastError();
231 MSVCRT__set_errno(err);
232 return err;