]> git.saurik.com Git - wxWidgets.git/blob - src/msw/utilsexc.cpp
minor bug fixes
[wxWidgets.git] / src / msw / utilsexc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: utilsexec.cpp
3 // Purpose: Various utilities
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/setup.h"
25 #include "wx/utils.h"
26 #include "wx/app.h"
27 #include "wx/intl.h"
28 #endif
29
30 #include "wx/log.h"
31
32 #ifdef __WIN32__
33 #include "wx/process.h"
34 #endif
35
36 #include "wx/msw/private.h"
37
38 #include <windows.h>
39
40 #include <ctype.h>
41
42 #if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__)
43 #include <direct.h>
44 #ifndef __MWERKS__
45 #include <dos.h>
46 #endif
47 #endif
48
49 #ifdef __GNUWIN32__
50 #ifndef __TWIN32__
51 #include <sys/unistd.h>
52 #include <sys/stat.h>
53 #endif
54 #endif
55
56 #if defined(__WIN32__) && !defined(__WXWINE__)
57 #include <io.h>
58
59 #ifndef __GNUWIN32__
60 #include <shellapi.h>
61 #endif
62 #endif
63
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #ifndef __WATCOMC__
68 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
69 #include <errno.h>
70 #endif
71 #endif
72 #include <stdarg.h>
73
74 // this message is sent when the process we're waiting for terminates
75 #define wxWM_PROC_TERMINATED (WM_USER + 10000)
76
77 // structure describing the process we're being waiting for
78 struct wxExecuteData
79 {
80 public:
81 ~wxExecuteData()
82 {
83 #ifndef __WIN16__
84 if ( !::CloseHandle(hProcess) )
85 {
86 wxLogLastError("CloseHandle(hProcess)");
87 }
88 #endif
89 }
90
91 HWND hWnd; // window to send wxWM_PROC_TERMINATED to
92 HANDLE hProcess; // handle of the process
93 DWORD dwProcessId; // pid of the process
94 wxProcess *handler;
95 DWORD dwExitCode; // the exit code of the process
96 bool state; // set to FALSE when the process finishes
97 };
98
99
100 #ifdef __WIN32__
101 static DWORD wxExecuteThread(wxExecuteData *data)
102 {
103 WaitForSingleObject(data->hProcess, INFINITE);
104
105 // get the exit code
106 if ( !GetExitCodeProcess(data->hProcess, &data->dwExitCode) )
107 {
108 wxLogLastError("GetExitCodeProcess");
109 }
110
111 wxASSERT_MSG( data->dwExitCode != STILL_ACTIVE,
112 wxT("process should have terminated") );
113
114 // send a message indicating process termination to the window
115 SendMessage(data->hWnd, wxWM_PROC_TERMINATED, 0, (LPARAM)data);
116
117 return 0;
118 }
119
120 // window procedure of a hidden window which is created just to receive
121 // the notification message when a process exits
122 LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message,
123 WPARAM wParam, LPARAM lParam)
124 {
125 if ( message == wxWM_PROC_TERMINATED )
126 {
127 DestroyWindow(hWnd); // we don't need it any more
128
129 wxExecuteData *data = (wxExecuteData *)lParam;
130 if ( data->handler )
131 {
132 data->handler->OnTerminate((int)data->dwProcessId,
133 (int)data->dwExitCode);
134 }
135
136 if ( data->state )
137 {
138 // we're executing synchronously, tell the waiting thread
139 // that the process finished
140 data->state = 0;
141 }
142 else
143 {
144 // asynchronous execution - we should do the clean up
145 delete data;
146 }
147 }
148
149 return 0;
150 }
151 #endif
152
153 extern wxChar wxPanelClassName[];
154
155 long wxExecute(const wxString& command, bool sync, wxProcess *handler)
156 {
157 wxCHECK_MSG( !!command, 0, wxT("empty command in wxExecute") );
158
159 #if defined(__WIN32__) && !defined(__TWIN32__)
160 // the old code is disabled because we really need a process handle
161 // if we want to execute it asynchronously or even just get its
162 // return code and for this we must use CreateProcess() and not
163 // ShellExecute()
164 #if 0
165 // isolate command and arguments
166 wxString commandName;
167 bool insideQuotes = FALSE;
168 const char *pc;
169 for ( pc = command.c_str(); *pc != '\0'; pc++ )
170 {
171 switch ( *pc )
172 {
173 case ' ':
174 case '\t':
175 if ( !insideQuotes )
176 break;
177 // fall through
178
179 case '"':
180 insideQuotes = !insideQuotes;
181 // fall through
182
183 default:
184 commandName += *pc;
185 continue; // skip the next break
186 }
187
188 // only reached for space not inside quotes
189 break;
190 }
191
192 wxString commandArgs = pc;
193
194 wxWindow *winTop = wxTheApp->GetTopWindow();
195 HWND hwndTop = (HWND)(winTop ? winTop->GetHWND() : 0);
196
197 HANDLE result;
198 #ifdef __GNUWIN32__
199 result = ShellExecute(hwndTop,
200 (const wchar_t)"open",
201 (const wchar_t)commandName,
202 (const wchar_t)commandArgs,
203 (const wchar_t)NULL,
204 SW_SHOWNORMAL);
205 #else // !GNUWIN32
206 result = ShellExecute(hwndTop, "open", commandName,
207 commandArgs, NULL, SW_SHOWNORMAL);
208 #endif // GNUWIN32
209
210 if ( ((long)result) <= 32 )
211 wxLogSysError(_("Can't execute command '%s'"), command.c_str());
212
213 return result;
214 #else // 1
215 // create the process
216 STARTUPINFO si;
217 #ifdef __GNUWIN32__
218 memset(&si, 0, sizeof(si));
219 #else
220 ::ZeroMemory(&si, sizeof(si));
221 #endif
222
223 si.cb = sizeof(si);
224
225 PROCESS_INFORMATION pi;
226
227 if ( ::CreateProcess(
228 NULL, // application name (use only cmd line)
229 (wxChar *)command.c_str(), // full command line
230 NULL, // security attributes: defaults for both
231 NULL, // the process and its main thread
232 FALSE, // don't inherit handles
233 CREATE_DEFAULT_ERROR_MODE, // flags
234 NULL, // environment (use the same)
235 NULL, // current directory (use the same)
236 &si, // startup info (unused here)
237 &pi // process info
238 ) == 0 )
239 {
240 wxLogSysError(_("Execution of command '%s' failed"), command.c_str());
241
242 return 0;
243 }
244
245 // close unneeded handle
246 if ( !::CloseHandle(pi.hThread) )
247 wxLogLastError("CloseHandle(hThread)");
248
249 // create a hidden window to receive notification about process
250 // termination
251 HWND hwnd = ::CreateWindow(wxPanelClassName, NULL, 0, 0, 0, 0, 0, NULL,
252 (HMENU)NULL, wxGetInstance(), 0);
253 wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") );
254
255 FARPROC ExecuteWindowInstance = MakeProcInstance((FARPROC)wxExecuteWindowCbk,
256 wxGetInstance());
257
258 ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) ExecuteWindowInstance);
259
260 // Alloc data
261 wxExecuteData *data = new wxExecuteData;
262 data->hProcess = pi.hProcess;
263 data->dwProcessId = pi.dwProcessId;
264 data->hWnd = hwnd;
265 data->state = sync;
266 if ( sync )
267 {
268 wxASSERT_MSG( !handler, wxT("wxProcess param ignored for sync execution") );
269
270 data->handler = NULL;
271 }
272 else
273 {
274 // may be NULL or not
275 data->handler = handler;
276 }
277
278 DWORD tid;
279 HANDLE hThread = ::CreateThread(NULL,
280 0,
281 (LPTHREAD_START_ROUTINE)wxExecuteThread,
282 (void *)data,
283 0,
284 &tid);
285
286 if ( !hThread )
287 {
288 wxLogLastError("CreateThread in wxExecute");
289
290 DestroyWindow(hwnd);
291 delete data;
292
293 // the process still started up successfully...
294 return pi.dwProcessId;
295 }
296
297 if ( !sync )
298 {
299 // clean up will be done when the process terminates
300
301 // return the pid
302 return pi.dwProcessId;
303 }
304
305 // waiting until command executed
306 while ( data->state )
307 wxYield();
308
309 DWORD dwExitCode = data->dwExitCode;
310 delete data;
311
312 // return the exit code
313 return dwExitCode;
314 #endif // 0/1
315 #else // Win16
316 long instanceID = WinExec((LPCSTR) WXSTRINGCAST command, SW_SHOW);
317 if (instanceID < 32) return(0);
318
319 if (sync) {
320 int running;
321 do {
322 wxYield();
323 running = GetModuleUsage((HINSTANCE)instanceID);
324 } while (running);
325 }
326
327 return(instanceID);
328 #endif // Win16/32
329 }
330
331 long wxExecute(char **argv, bool sync, wxProcess *handler)
332 {
333 wxString command;
334
335 while ( *argv != NULL )
336 {
337 command << *argv++ << ' ';
338 }
339
340 command.RemoveLast();
341
342 return wxExecute(command, sync, handler);
343 }
344
345 bool wxGetFullHostName(wxChar *buf, int maxSize)
346 {
347 #if defined(__WIN32__) && !defined(__TWIN32__)
348 DWORD nSize = maxSize ;
349 if ( !::GetComputerName(buf, &nSize) )
350 {
351 wxLogLastError("GetComputerName");
352
353 return FALSE;
354 }
355 #else
356 char *sysname;
357 const char *default_host = "noname";
358 static const char WX_SECTION[] = "wxWindows";
359 static const char eHOSTNAME[] = "HostName";
360
361 if ((sysname = getenv("SYSTEM_NAME")) == NULL) {
362 GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
363 } else
364 strncpy(buf, sysname, maxSize - 1);
365 buf[maxSize] = '\0';
366 if ( *buf == '\0' )
367 {
368 wxLogLastError("GetComputerName");
369
370 return FALSE;
371 }
372 #endif
373 return TRUE;
374 }