Mercurial > hg > xemacs-beta
comparison src/process-nt.c @ 278:90d73dddcdc4 r21-0b37
Import from CVS: tag r21-0b37
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:31:29 +0200 |
parents | 6330739388db |
children | 7df0dd720c89 |
comparison
equal
deleted
inserted
replaced
277:cfdf3ff11843 | 278:90d73dddcdc4 |
---|---|
28 | 28 |
29 #include "hash.h" | 29 #include "hash.h" |
30 #include "lstream.h" | 30 #include "lstream.h" |
31 #include "process.h" | 31 #include "process.h" |
32 #include "procimpl.h" | 32 #include "procimpl.h" |
33 #include "sysdep.h" | |
33 | 34 |
34 #include <windows.h> | 35 #include <windows.h> |
36 #include <shellapi.h> | |
35 | 37 |
36 /* Implemenation-specific data. Pointed to by Lisp_Process->process_data */ | 38 /* Implemenation-specific data. Pointed to by Lisp_Process->process_data */ |
37 struct nt_process_data | 39 struct nt_process_data |
38 { | 40 { |
39 HANDLE h_process; | 41 HANDLE h_process; |
122 * must signal an error instead. | 124 * must signal an error instead. |
123 */ | 125 */ |
124 | 126 |
125 /* #### This function completely ignores Vprocess_environment */ | 127 /* #### This function completely ignores Vprocess_environment */ |
126 | 128 |
129 static void | |
130 signal_cannot_launch (char* image_file, DWORD err) | |
131 { | |
132 mswindows_set_errno (err); | |
133 error ("Starting \"%s\": %s", image_file, strerror (errno)); | |
134 } | |
135 | |
127 static int | 136 static int |
128 nt_create_process (struct Lisp_Process *p, | 137 nt_create_process (struct Lisp_Process *p, |
129 char **argv, CONST char *current_dir) | 138 char **argv, CONST char *current_dir) |
130 { | 139 { |
131 HANDLE hmyshove, hmyslurp, hprocin, hprocout; | 140 HANDLE hmyshove, hmyslurp, hprocin, hprocout; |
132 LPTSTR command_line; | 141 LPTSTR command_line; |
142 BOOL do_io, windowed; | |
143 | |
144 /* Find out whether the application is windowed or not */ | |
145 { | |
146 /* SHGetFileInfo tends to return ERROR_FILE_NOT_FOUND on most | |
147 errors. This leads to bogus error message. */ | |
148 DWORD image_type = SHGetFileInfo (argv[0], 0, NULL, 0, SHGFI_EXETYPE); | |
149 if (image_type == 0) | |
150 signal_cannot_launch (argv[0], (GetLastError () == ERROR_FILE_NOT_FOUND | |
151 ? ERROR_BAD_FORMAT : GetLastError ())); | |
152 windowed = HIWORD (image_type) != 0; | |
153 } | |
154 | |
155 /* Decide whether to do I/O on process handles, or just mark the | |
156 process exited immediately upon successful launching. We do I/O if the | |
157 process is a console one, or if it is windowed but windowed_process_io | |
158 is non-zero */ | |
159 do_io = !windowed || windowed_process_io ; | |
133 | 160 |
134 /* Create two unidirectional named pipes */ | 161 if (do_io) |
135 { | 162 { |
136 HANDLE htmp; | 163 /* Create two unidirectional named pipes */ |
137 SECURITY_ATTRIBUTES sa; | 164 HANDLE htmp; |
138 | 165 SECURITY_ATTRIBUTES sa; |
139 sa.nLength = sizeof(sa); | 166 |
140 sa.bInheritHandle = TRUE; | 167 sa.nLength = sizeof(sa); |
141 sa.lpSecurityDescriptor = NULL; | 168 sa.bInheritHandle = TRUE; |
142 | 169 sa.lpSecurityDescriptor = NULL; |
143 CreatePipe (&hprocin, &hmyshove, &sa, 0); | 170 |
144 CreatePipe (&hmyslurp, &hprocout, &sa, 0); | 171 CreatePipe (&hprocin, &hmyshove, &sa, 0); |
145 | 172 CreatePipe (&hmyslurp, &hprocout, &sa, 0); |
146 /* Stupid Win32 allows to create a pipe with *both* ends either | 173 |
147 inheritable or not. We need process ends inheritable, and local | 174 /* Stupid Win32 allows to create a pipe with *both* ends either |
148 ends not inheritable. */ | 175 inheritable or not. We need process ends inheritable, and local |
149 /* #### Perhaps even stupider me does not know how to do this better */ | 176 ends not inheritable. */ |
150 DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(), &htmp, | 177 DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(), &htmp, |
151 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS); | 178 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS); |
152 hmyshove = htmp; | 179 hmyshove = htmp; |
153 DuplicateHandle (GetCurrentProcess(), hmyslurp, GetCurrentProcess(), &htmp, | 180 DuplicateHandle (GetCurrentProcess(), hmyslurp, GetCurrentProcess(), &htmp, |
154 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS); | 181 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS); |
155 hmyslurp = htmp; | 182 hmyslurp = htmp; |
156 } | 183 } |
157 | 184 |
158 /* Convert an argv vector into Win32 style command line. | 185 /* Convert an argv vector into Win32 style command line. |
159 | 186 |
160 #### This works only for cmd, and not for cygwin bash. Perhaps, | 187 #### This works only for cmd, and not for cygwin bash. Perhaps, |
161 instead of ad-hoc fiddling with different methods for quoting | 188 instead of ad-hoc fiddling with different methods for quoting |
184 /* Create process */ | 211 /* Create process */ |
185 { | 212 { |
186 STARTUPINFO si; | 213 STARTUPINFO si; |
187 PROCESS_INFORMATION pi; | 214 PROCESS_INFORMATION pi; |
188 DWORD err; | 215 DWORD err; |
189 BOOL windowed; | |
190 | 216 |
191 xzero (si); | 217 xzero (si); |
192 si.hStdInput = hprocin; | 218 si.dwFlags = STARTF_USESHOWWINDOW; |
193 si.hStdOutput = hprocout; | 219 si.wShowWindow = windowed ? SW_SHOWNORMAL : SW_HIDE; |
194 si.hStdError = hprocout; | 220 if (do_io) |
195 si.wShowWindow = SW_HIDE; | 221 { |
196 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; | 222 si.hStdInput = hprocin; |
197 | 223 si.hStdOutput = hprocout; |
224 si.hStdError = hprocout; | |
225 si.dwFlags |= STARTF_USESTDHANDLES; | |
226 } | |
227 | |
198 err = (CreateProcess (NULL, command_line, NULL, NULL, TRUE, | 228 err = (CreateProcess (NULL, command_line, NULL, NULL, TRUE, |
199 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP | CREATE_SUSPENDED, | 229 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, |
200 NULL, current_dir, &si, &pi) | 230 NULL, current_dir, &si, &pi) |
201 ? 0 : GetLastError ()); | 231 ? 0 : GetLastError ()); |
202 | 232 |
203 CloseHandle (hprocin); | 233 if (do_io) |
204 CloseHandle (hprocout); | 234 { |
205 | 235 /* These just have been inherited; we do not need a copy */ |
206 /* See if we succeeded with process creation */ | 236 CloseHandle (hprocin); |
237 CloseHandle (hprocout); | |
238 } | |
239 | |
240 /* Handle process creation failure */ | |
207 if (err) | 241 if (err) |
208 { | 242 { |
209 process_error__One_of_those_nasty_uses_for_goto_statement: | 243 if (do_io) |
210 CloseHandle (hmyshove); | |
211 CloseHandle (hmyslurp); | |
212 error ("Cannot start \"%s\": error code was %lu", argv[0], err); | |
213 } | |
214 | |
215 /* Determine if the new process is a windowed one */ | |
216 windowed = WaitForInputIdle (pi.hProcess, 100) == WAIT_TIMEOUT; | |
217 if (windowed) | |
218 { | |
219 /* We restart windowed process fire-and forget style, and | |
220 indicate successful process creation, just as if the | |
221 process ended instantly upon launching */ | |
222 CloseHandle (hmyshove); | |
223 CloseHandle (hmyslurp); | |
224 /* TerminateProcess is safe becuase the process is not yet | |
225 running */ | |
226 TerminateProcess (pi.hProcess, 0); | |
227 si.dwFlags = STARTF_USESHOWWINDOW; | |
228 si.wShowWindow = SW_SHOWNORMAL; | |
229 if (!CreateProcess (NULL, command_line, NULL, NULL, FALSE, | |
230 DETACHED_PROCESS , NULL, current_dir, &si, &pi)) | |
231 { | 244 { |
232 err = GetLastError (); | 245 CloseHandle (hmyshove); |
233 goto process_error__One_of_those_nasty_uses_for_goto_statement; | 246 CloseHandle (hmyslurp); |
234 } | 247 } |
235 | 248 signal_cannot_launch (argv[0], GetLastError ()); |
236 /* We just launched a windowed process. Fake it as if a | 249 } |
237 process launched has already ended */ | 250 |
251 /* The process started successfully */ | |
252 if (do_io) | |
253 { | |
254 NT_DATA(p)->h_process = pi.hProcess; | |
255 init_process_io_handles (p, (void*)hmyslurp, (void*)hmyshove, 0); | |
256 } | |
257 else | |
258 { | |
259 /* Indicate as if the process has exited immediately. */ | |
238 p->status_symbol = Qexit; | 260 p->status_symbol = Qexit; |
239 | |
240 /* Get rid of process and thread handles */ | |
241 CloseHandle (pi.hThread); | |
242 CloseHandle (pi.hProcess); | 261 CloseHandle (pi.hProcess); |
243 } | 262 } |
244 else | 263 |
245 { | 264 CloseHandle (pi.hThread); |
246 /* Just started a console subprocess */ | 265 |
247 | 266 /* Hack to support Windows 95 negative pids */ |
248 NT_DATA(p)->h_process = pi.hProcess; | |
249 | |
250 init_process_io_handles (p, (void*)hmyslurp, (void*)hmyshove, 0); | |
251 | |
252 /* We created it suspended. Resume the only thread */ | |
253 ResumeThread (pi.hThread); | |
254 CloseHandle (pi.hThread); | |
255 } | |
256 | |
257 return ((int)pi.dwProcessId < 0 | 267 return ((int)pi.dwProcessId < 0 |
258 ? -(int)pi.dwProcessId : (int)pi.dwProcessId); | 268 ? -(int)pi.dwProcessId : (int)pi.dwProcessId); |
259 } | 269 } |
260 } | 270 } |
261 | 271 |