]> git.saurik.com Git - wxWidgets.git/blame - src/msw/utilsexc.cpp
1. wxBitmap copy ctor and operator=() taking wxIcon added
[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;
11c7d5b6 217 wxZeroMemory(si);
cf0b3979 218
cb6827a8
VZ
219 si.cb = sizeof(si);
220
221 PROCESS_INFORMATION pi;
222
223 if ( ::CreateProcess(
224 NULL, // application name (use only cmd line)
837e5743 225 (wxChar *)command.c_str(), // full command line
cb6827a8
VZ
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);
223d09f6 249 wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") );
e6045e08 250
cb6827a8
VZ
251 FARPROC ExecuteWindowInstance = MakeProcInstance((FARPROC)wxExecuteWindowCbk,
252 wxGetInstance());
e6045e08 253
cb6827a8 254 ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) ExecuteWindowInstance);
e6045e08 255
cb6827a8
VZ
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;
e6045e08
VZ
262 if ( sync )
263 {
223d09f6 264 wxASSERT_MSG( !handler, wxT("wxProcess param ignored for sync execution") );
e6045e08
VZ
265
266 data->handler = NULL;
267 }
268 else
269 {
270 // may be NULL or not
271 data->handler = handler;
272 }
cb6827a8
VZ
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 }
e6045e08 292
cb6827a8
VZ
293 if ( !sync )
294 {
295 // clean up will be done when the process terminates
e6045e08
VZ
296
297 // return the pid
cb6827a8
VZ
298 return pi.dwProcessId;
299 }
e6045e08 300
cb6827a8
VZ
301 // waiting until command executed
302 while ( data->state )
303 wxYield();
e6045e08
VZ
304
305 DWORD dwExitCode = data->dwExitCode;
cb6827a8
VZ
306 delete data;
307
e6045e08
VZ
308 // return the exit code
309 return dwExitCode;
cb6827a8
VZ
310#endif // 0/1
311#else // Win16
312 long instanceID = WinExec((LPCSTR) WXSTRINGCAST command, SW_SHOW);
313 if (instanceID < 32) return(0);
e6045e08 314
cb6827a8
VZ
315 if (sync) {
316 int running;
317 do {
318 wxYield();
27a9bd48 319 running = GetModuleUsage((HINSTANCE)instanceID);
cb6827a8
VZ
320 } while (running);
321 }
322
323 return(instanceID);
324#endif // Win16/32
32592631 325}
c740f496
GL
326
327long wxExecute(char **argv, bool sync, wxProcess *handler)
328{
cb6827a8 329 wxString command;
e6045e08 330
cb6827a8
VZ
331 while ( *argv != NULL )
332 {
333 command << *argv++ << ' ';
334 }
335
336 command.RemoveLast();
337
338 return wxExecute(command, sync, handler);
c740f496 339}
006162a9
VZ
340
341bool wxGetFullHostName(wxChar *buf, int maxSize)
342{
c0de7af4
PA
343#if defined(__WIN32__) && !defined(__TWIN32__)
344 DWORD nSize = maxSize ;
006162a9
VZ
345 if ( !::GetComputerName(buf, &nSize) )
346 {
347 wxLogLastError("GetComputerName");
348
349 return FALSE;
350 }
c0de7af4
PA
351#else
352 char *sysname;
353 const char *default_host = "noname";
354static const char WX_SECTION[] = "wxWindows";
355static 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");
006162a9 365
c0de7af4
PA
366 return FALSE;
367 }
368#endif
006162a9
VZ
369 return TRUE;
370}