]> git.saurik.com Git - wxWidgets.git/blob - src/msw/utilsexc.cpp
added a WXDLLEXPORT
[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 wxZeroMemory(si);
218
219 si.cb = sizeof(si);
220
221 PROCESS_INFORMATION pi;
222
223 if ( ::CreateProcess(
224 NULL, // application name (use only cmd line)
225 (wxChar *)command.c_str(), // full command line
226 NULL, // security attributes: defaults for both
227 NULL, // the process and its main thread
228 FALSE, // don't inherit handles
229 CREATE_DEFAULT_ERROR_MODE, // flags
230 NULL, // environment (use the same)
231 NULL, // current directory (use the same)
232 &si, // startup info (unused here)
233 &pi // process info
234 ) == 0 )
235 {
236 wxLogSysError(_("Execution of command '%s' failed"), command.c_str());
237
238 return 0;
239 }
240
241 // close unneeded handle
242 if ( !::CloseHandle(pi.hThread) )
243 wxLogLastError("CloseHandle(hThread)");
244
245 // create a hidden window to receive notification about process
246 // termination
247 HWND hwnd = ::CreateWindow(wxPanelClassName, NULL, 0, 0, 0, 0, 0, NULL,
248 (HMENU)NULL, wxGetInstance(), 0);
249 wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") );
250
251 FARPROC ExecuteWindowInstance = MakeProcInstance((FARPROC)wxExecuteWindowCbk,
252 wxGetInstance());
253
254 ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) ExecuteWindowInstance);
255
256 // Alloc data
257 wxExecuteData *data = new wxExecuteData;
258 data->hProcess = pi.hProcess;
259 data->dwProcessId = pi.dwProcessId;
260 data->hWnd = hwnd;
261 data->state = sync;
262 if ( sync )
263 {
264 wxASSERT_MSG( !handler, wxT("wxProcess param ignored for sync execution") );
265
266 data->handler = NULL;
267 }
268 else
269 {
270 // may be NULL or not
271 data->handler = handler;
272 }
273
274 DWORD tid;
275 HANDLE hThread = ::CreateThread(NULL,
276 0,
277 (LPTHREAD_START_ROUTINE)wxExecuteThread,
278 (void *)data,
279 0,
280 &tid);
281
282 if ( !hThread )
283 {
284 wxLogLastError("CreateThread in wxExecute");
285
286 DestroyWindow(hwnd);
287 delete data;
288
289 // the process still started up successfully...
290 return pi.dwProcessId;
291 }
292
293 if ( !sync )
294 {
295 // clean up will be done when the process terminates
296
297 // return the pid
298 return pi.dwProcessId;
299 }
300
301 // waiting until command executed
302 while ( data->state )
303 wxYield();
304
305 DWORD dwExitCode = data->dwExitCode;
306 delete data;
307
308 // return the exit code
309 return dwExitCode;
310 #endif // 0/1
311 #else // Win16
312 long instanceID = WinExec((LPCSTR) WXSTRINGCAST command, SW_SHOW);
313 if (instanceID < 32) return(0);
314
315 if (sync) {
316 int running;
317 do {
318 wxYield();
319 running = GetModuleUsage((HINSTANCE)instanceID);
320 } while (running);
321 }
322
323 return(instanceID);
324 #endif // Win16/32
325 }
326
327 long wxExecute(char **argv, bool sync, wxProcess *handler)
328 {
329 wxString command;
330
331 while ( *argv != NULL )
332 {
333 command << *argv++ << ' ';
334 }
335
336 command.RemoveLast();
337
338 return wxExecute(command, sync, handler);
339 }
340
341 bool wxGetFullHostName(wxChar *buf, int maxSize)
342 {
343 #if defined(__WIN32__) && !defined(__TWIN32__)
344 DWORD nSize = maxSize ;
345 if ( !::GetComputerName(buf, &nSize) )
346 {
347 wxLogLastError("GetComputerName");
348
349 return FALSE;
350 }
351 #else
352 char *sysname;
353 const char *default_host = "noname";
354 static const char WX_SECTION[] = "wxWindows";
355 static const char eHOSTNAME[] = "HostName";
356
357 if ((sysname = getenv("SYSTEM_NAME")) == NULL) {
358 GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
359 } else
360 strncpy(buf, sysname, maxSize - 1);
361 buf[maxSize] = '\0';
362 if ( *buf == '\0' )
363 {
364 wxLogLastError("GetComputerName");
365
366 return FALSE;
367 }
368 #endif
369 return TRUE;
370 }