]> git.saurik.com Git - wxWidgets.git/blame - src/msw/utilsexc.cpp
minor bug fixes
[wxWidgets.git] / src / msw / utilsexc.cpp
CommitLineData
32592631
GL
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
3f4a0c5b 9// Licence: wxWindows license
32592631
GL
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
cfe780fb 13#pragma implementation
32592631
GL
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"
2432b92d 27#include "wx/intl.h"
32592631
GL
28#endif
29
3e64d4e1 30#include "wx/log.h"
1044a386
JS
31
32#ifdef __WIN32__
dbeac4bd 33#include "wx/process.h"
1044a386 34#endif
dbeac4bd 35
32592631 36#include "wx/msw/private.h"
dbeac4bd 37
32592631
GL
38#include <windows.h>
39
40#include <ctype.h>
41
5ea105e0 42#if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__)
32592631 43#include <direct.h>
17dff81c 44#ifndef __MWERKS__
32592631
GL
45#include <dos.h>
46#endif
17dff81c 47#endif
32592631
GL
48
49#ifdef __GNUWIN32__
57c208c5 50#ifndef __TWIN32__
32592631
GL
51#include <sys/unistd.h>
52#include <sys/stat.h>
32592631 53#endif
57c208c5 54#endif
32592631 55
5ea105e0 56#if defined(__WIN32__) && !defined(__WXWINE__)
32592631
GL
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__
3f4a0c5b
VZ
68 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
69 #include <errno.h>
70 #endif
32592631
GL
71#endif
72#include <stdarg.h>
73
cb6827a8
VZ
74// this message is sent when the process we're waiting for terminates
75#define wxWM_PROC_TERMINATED (WM_USER + 10000)
32592631 76
cb6827a8
VZ
77// structure describing the process we're being waiting for
78struct wxExecuteData
79{
80public:
81 ~wxExecuteData()
82 {
750b78ba 83#ifndef __WIN16__
cb6827a8
VZ
84 if ( !::CloseHandle(hProcess) )
85 {
86 wxLogLastError("CloseHandle(hProcess)");
87 }
750b78ba 88#endif
cb6827a8
VZ
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
32592631
GL
97};
98
5260b1c5
JS
99
100#ifdef __WIN32__
32592631
GL
101static DWORD wxExecuteThread(wxExecuteData *data)
102{
cb6827a8
VZ
103 WaitForSingleObject(data->hProcess, INFINITE);
104
105 // get the exit code
106 if ( !GetExitCodeProcess(data->hProcess, &data->dwExitCode) )
107 {
108 wxLogLastError("GetExitCodeProcess");
109 }
32592631 110
cb6827a8 111 wxASSERT_MSG( data->dwExitCode != STILL_ACTIVE,
223d09f6 112 wxT("process should have terminated") );
32592631 113
cb6827a8
VZ
114 // send a message indicating process termination to the window
115 SendMessage(data->hWnd, wxWM_PROC_TERMINATED, 0, (LPARAM)data);
e6045e08 116
cb6827a8 117 return 0;
32592631 118}
5260b1c5 119
cb6827a8
VZ
120// window procedure of a hidden window which is created just to receive
121// the notification message when a process exits
32592631
GL
122LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message,
123 WPARAM wParam, LPARAM lParam)
124{
cb6827a8
VZ
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 }
e6045e08 135
cb6827a8
VZ
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;
32592631 150}
1044a386 151#endif
32592631 152
837e5743 153extern wxChar wxPanelClassName[];
32592631
GL
154
155long wxExecute(const wxString& command, bool sync, wxProcess *handler)
156{
223d09f6 157 wxCHECK_MSG( !!command, 0, wxT("empty command in wxExecute") );
32592631 158
57c208c5 159#if defined(__WIN32__) && !defined(__TWIN32__)
cb6827a8
VZ
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;
32592631 198#ifdef __GNUWIN32__
cb6827a8
VZ
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
e6045e08 209
cb6827a8
VZ
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;
cf0b3979
JS
217#ifdef __GNUWIN32__
218 memset(&si, 0, sizeof(si));
219#else
cb6827a8 220 ::ZeroMemory(&si, sizeof(si));
cf0b3979
JS
221#endif
222
cb6827a8
VZ
223 si.cb = sizeof(si);
224
225 PROCESS_INFORMATION pi;
226
227 if ( ::CreateProcess(
228 NULL, // application name (use only cmd line)
837e5743 229 (wxChar *)command.c_str(), // full command line
cb6827a8
VZ
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);
223d09f6 253 wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") );
e6045e08 254
cb6827a8
VZ
255 FARPROC ExecuteWindowInstance = MakeProcInstance((FARPROC)wxExecuteWindowCbk,
256 wxGetInstance());
e6045e08 257
cb6827a8 258 ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) ExecuteWindowInstance);
e6045e08 259
cb6827a8
VZ
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;
e6045e08
VZ
266 if ( sync )
267 {
223d09f6 268 wxASSERT_MSG( !handler, wxT("wxProcess param ignored for sync execution") );
e6045e08
VZ
269
270 data->handler = NULL;
271 }
272 else
273 {
274 // may be NULL or not
275 data->handler = handler;
276 }
cb6827a8
VZ
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 }
e6045e08 296
cb6827a8
VZ
297 if ( !sync )
298 {
299 // clean up will be done when the process terminates
e6045e08
VZ
300
301 // return the pid
cb6827a8
VZ
302 return pi.dwProcessId;
303 }
e6045e08 304
cb6827a8
VZ
305 // waiting until command executed
306 while ( data->state )
307 wxYield();
e6045e08
VZ
308
309 DWORD dwExitCode = data->dwExitCode;
cb6827a8
VZ
310 delete data;
311
e6045e08
VZ
312 // return the exit code
313 return dwExitCode;
cb6827a8
VZ
314#endif // 0/1
315#else // Win16
316 long instanceID = WinExec((LPCSTR) WXSTRINGCAST command, SW_SHOW);
317 if (instanceID < 32) return(0);
e6045e08 318
cb6827a8
VZ
319 if (sync) {
320 int running;
321 do {
322 wxYield();
27a9bd48 323 running = GetModuleUsage((HINSTANCE)instanceID);
cb6827a8
VZ
324 } while (running);
325 }
326
327 return(instanceID);
328#endif // Win16/32
32592631 329}
c740f496
GL
330
331long wxExecute(char **argv, bool sync, wxProcess *handler)
332{
cb6827a8 333 wxString command;
e6045e08 334
cb6827a8
VZ
335 while ( *argv != NULL )
336 {
337 command << *argv++ << ' ';
338 }
339
340 command.RemoveLast();
341
342 return wxExecute(command, sync, handler);
c740f496 343}
006162a9
VZ
344
345bool wxGetFullHostName(wxChar *buf, int maxSize)
346{
c0de7af4
PA
347#if defined(__WIN32__) && !defined(__TWIN32__)
348 DWORD nSize = maxSize ;
006162a9
VZ
349 if ( !::GetComputerName(buf, &nSize) )
350 {
351 wxLogLastError("GetComputerName");
352
353 return FALSE;
354 }
c0de7af4
PA
355#else
356 char *sysname;
357 const char *default_host = "noname";
358static const char WX_SECTION[] = "wxWindows";
359static 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");
006162a9 369
c0de7af4
PA
370 return FALSE;
371 }
372#endif
006162a9
VZ
373 return TRUE;
374}