1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/utilsexec.cpp
3 // Purpose: Various utilities
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
40 #include "wx/process.h"
43 #include "wx/msw/private.h"
47 #if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__)
54 #if defined(__GNUWIN32__) && !defined(__TWIN32__)
55 #include <sys/unistd.h>
59 #if defined(__WIN32__) && !defined(__WXWINE__)
71 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
81 // this message is sent when the process we're waiting for terminates
82 #define wxWM_PROC_TERMINATED (WM_USER + 10000)
84 // ----------------------------------------------------------------------------
85 // this module globals
86 // ----------------------------------------------------------------------------
88 // we need to create a hidden window to receive the process termination
89 // notifications and for this we need a (Win) class name for it which we will
90 // register the first time it's needed
91 static const wxChar
*gs_classForHiddenWindow
= NULL
;
93 // ----------------------------------------------------------------------------
95 // ----------------------------------------------------------------------------
97 // structure describing the process we're being waiting for
104 if ( !::CloseHandle(hProcess
) )
106 wxLogLastError("CloseHandle(hProcess)");
111 HWND hWnd
; // window to send wxWM_PROC_TERMINATED to
112 HANDLE hProcess
; // handle of the process
113 DWORD dwProcessId
; // pid of the process
115 DWORD dwExitCode
; // the exit code of the process
116 bool state
; // set to FALSE when the process finishes
119 // ============================================================================
121 // ============================================================================
124 static DWORD
wxExecuteThread(wxExecuteData
*data
)
126 WaitForSingleObject(data
->hProcess
, INFINITE
);
129 if ( !GetExitCodeProcess(data
->hProcess
, &data
->dwExitCode
) )
131 wxLogLastError("GetExitCodeProcess");
134 wxASSERT_MSG( data
->dwExitCode
!= STILL_ACTIVE
,
135 wxT("process should have terminated") );
137 // send a message indicating process termination to the window
138 SendMessage(data
->hWnd
, wxWM_PROC_TERMINATED
, 0, (LPARAM
)data
);
143 // window procedure of a hidden window which is created just to receive
144 // the notification message when a process exits
145 LRESULT APIENTRY _EXPORT
wxExecuteWindowCbk(HWND hWnd
, UINT message
,
146 WPARAM wParam
, LPARAM lParam
)
148 if ( message
== wxWM_PROC_TERMINATED
)
150 DestroyWindow(hWnd
); // we don't need it any more
152 wxExecuteData
*data
= (wxExecuteData
*)lParam
;
155 data
->handler
->OnTerminate((int)data
->dwProcessId
,
156 (int)data
->dwExitCode
);
161 // we're executing synchronously, tell the waiting thread
162 // that the process finished
167 // asynchronous execution - we should do the clean up
175 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
180 long wxExecute(const wxString
& command
, bool sync
, wxProcess
*handler
)
182 wxCHECK_MSG( !!command
, 0, wxT("empty command in wxExecute") );
184 #if defined(__WIN32__) && !defined(__TWIN32__)
185 // the old code is disabled because we really need a process handle
186 // if we want to execute it asynchronously or even just get its
187 // return code and for this we must use CreateProcess() and not
190 // isolate command and arguments
191 wxString commandName
;
192 bool insideQuotes
= FALSE
;
194 for ( pc
= command
.c_str(); *pc
!= '\0'; pc
++ )
205 insideQuotes
= !insideQuotes
;
210 continue; // skip the next break
213 // only reached for space not inside quotes
217 wxString commandArgs
= pc
;
219 wxWindow
*winTop
= wxTheApp
->GetTopWindow();
220 HWND hwndTop
= (HWND
)(winTop
? winTop
->GetHWND() : 0);
224 result
= ShellExecute(hwndTop
,
225 (const wchar_t)"open",
226 (const wchar_t)commandName
,
227 (const wchar_t)commandArgs
,
231 result
= ShellExecute(hwndTop
, "open", commandName
,
232 commandArgs
, NULL
, SW_SHOWNORMAL
);
235 if ( ((long)result
) <= 32 )
236 wxLogSysError(_("Can't execute command '%s'"), command
.c_str());
240 // create the process
246 PROCESS_INFORMATION pi
;
248 if ( ::CreateProcess(
249 NULL
, // application name (use only cmd line)
250 (wxChar
*)command
.c_str(), // full command line
251 NULL
, // security attributes: defaults for both
252 NULL
, // the process and its main thread
253 FALSE
, // don't inherit handles
254 CREATE_DEFAULT_ERROR_MODE
|
255 CREATE_SUSPENDED
, // flags
256 NULL
, // environment (use the same)
257 NULL
, // current directory (use the same)
258 &si
, // startup info (unused here)
262 wxLogSysError(_("Execution of command '%s' failed"), command
.c_str());
267 // register the class for the hidden window used for the notifications
268 if ( !gs_classForHiddenWindow
)
270 gs_classForHiddenWindow
= _T("wxHiddenWindow");
273 wxZeroMemory(wndclass
);
274 wndclass
.lpfnWndProc
= (WNDPROC
)wxExecuteWindowCbk
;
275 wndclass
.hInstance
= wxGetInstance();
276 wndclass
.lpszClassName
= gs_classForHiddenWindow
;
278 if ( !::RegisterClass(&wndclass
) )
280 wxLogLastError("RegisterClass(hidden window)");
284 // create a hidden window to receive notification about process
286 HWND hwnd
= ::CreateWindow(gs_classForHiddenWindow
, NULL
,
289 (HMENU
)NULL
, wxGetInstance(), 0);
290 wxASSERT_MSG( hwnd
, wxT("can't create a hidden window for wxExecute") );
293 wxExecuteData
*data
= new wxExecuteData
;
294 data
->hProcess
= pi
.hProcess
;
295 data
->dwProcessId
= pi
.dwProcessId
;
300 wxASSERT_MSG( !handler
, wxT("wxProcess param ignored for sync execution") );
302 data
->handler
= NULL
;
306 // may be NULL or not
307 data
->handler
= handler
;
311 HANDLE hThread
= ::CreateThread(NULL
,
313 (LPTHREAD_START_ROUTINE
)wxExecuteThread
,
318 // resume process we created now - whether the thread creation succeeded or
320 if ( ::ResumeThread(pi
.hThread
) == (DWORD
)-1 )
322 // ignore it - what can we do?
323 wxLogLastError("ResumeThread in wxExecute");
326 // close unneeded handle
327 if ( !::CloseHandle(pi
.hThread
) )
328 wxLogLastError("CloseHandle(hThread)");
332 wxLogLastError("CreateThread in wxExecute");
337 // the process still started up successfully...
338 return pi
.dwProcessId
;
343 // clean up will be done when the process terminates
346 return pi
.dwProcessId
;
349 // waiting until command executed (disable everything while doing it)
352 wxEnableTopLevelWindows(FALSE
);
355 while ( data
->state
)
359 wxEnableTopLevelWindows(TRUE
);
363 DWORD dwExitCode
= data
->dwExitCode
;
366 // return the exit code
370 long instanceID
= WinExec((LPCSTR
) WXSTRINGCAST command
, SW_SHOW
);
371 if (instanceID
< 32) return(0);
377 running
= GetModuleUsage((HINSTANCE
)instanceID
);
385 long wxExecute(char **argv
, bool sync
, wxProcess
*handler
)
389 while ( *argv
!= NULL
)
391 command
<< *argv
++ << ' ';
394 command
.RemoveLast();
396 return wxExecute(command
, sync
, handler
);
399 // ----------------------------------------------------------------------------
401 // ----------------------------------------------------------------------------
403 extern void PixelToHIMETRIC(LONG
*x
, LONG
*y
)
407 int iWidthMM
= GetDeviceCaps(hdcRef
, HORZSIZE
),
408 iHeightMM
= GetDeviceCaps(hdcRef
, VERTSIZE
),
409 iWidthPels
= GetDeviceCaps(hdcRef
, HORZRES
),
410 iHeightPels
= GetDeviceCaps(hdcRef
, VERTRES
);
412 *x
*= (iWidthMM
* 100);
414 *y
*= (iHeightMM
* 100);
418 extern void HIMETRICToPixel(LONG
*x
, LONG
*y
)
422 int iWidthMM
= GetDeviceCaps(hdcRef
, HORZSIZE
),
423 iHeightMM
= GetDeviceCaps(hdcRef
, VERTSIZE
),
424 iWidthPels
= GetDeviceCaps(hdcRef
, HORZRES
),
425 iHeightPels
= GetDeviceCaps(hdcRef
, VERTRES
);
428 *x
/= (iWidthMM
* 100);
430 *y
/= (iHeightMM
* 100);