]> git.saurik.com Git - wxWidgets.git/blob - src/os2/utilsexc.cpp
Applied patch [ 1428990 ] wxUniv: patch for toolbar button remain in pressed status
[wxWidgets.git] / src / os2 / utilsexc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/utilsexec.cpp
3 // Purpose: Various utilities
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/17/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/utils.h"
17 #include "wx/app.h"
18 #include "wx/intl.h"
19 #endif
20
21 #include "wx/log.h"
22
23 #include "wx/process.h"
24
25 #include "wx/os2/private.h"
26
27 #define PURE_32
28 #ifndef __EMX__
29 #include <upm.h>
30 #ifndef __WATCOMC__
31 #include <netcons.h>
32 #include <netbios.h>
33 #endif
34 #endif
35
36 #include <ctype.h>
37 #ifdef __EMX__
38 #include <dirent.h>
39 #endif
40
41 #include <sys/stat.h>
42 #include <io.h>
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <errno.h>
48 #include <stdarg.h>
49
50
51 // this message is sent when the process we're waiting for terminates
52 #define wxWM_PROC_TERMINATED (WM_USER + 10000)
53
54 #ifndef NO_ERROR
55 # define NO_ERROR 0
56 #endif
57
58 // structure describing the process we're being waiting for
59 struct wxExecuteData
60 {
61 public:
62 ~wxExecuteData()
63 {
64 // cout << "Closing thread: " << endl;
65 DosExit(EXIT_PROCESS, 0);
66 }
67
68 HWND hWnd; // window to send wxWM_PROC_TERMINATED to [not used]
69 RESULTCODES vResultCodes;
70 wxProcess* pHandler;
71 ULONG ulExitCode; // the exit code of the process
72 bool bState; // set to false when the process finishes
73 };
74
75 static ULONG wxExecuteThread(wxExecuteData* pData)
76 {
77 ULONG ulRc;
78 PID vPidChild;
79
80 // cout << "Executing thread: " << endl;
81
82 ulRc = ::DosWaitChild( DCWA_PROCESSTREE
83 ,DCWW_NOWAIT
84 ,&pData->vResultCodes
85 ,&vPidChild
86 ,pData->vResultCodes.codeTerminate // process PID to look at
87 );
88 if (ulRc != NO_ERROR)
89 {
90 wxLogLastError(wxT("DosWaitChild"));
91 }
92 delete pData;
93 return 0;
94 }
95
96 // window procedure of a hidden window which is created just to receive
97 // the notification message when a process exits
98 MRESULT APIENTRY wxExecuteWindowCbk( HWND hWnd,
99 ULONG ulMessage,
100 MPARAM WXUNUSED(wParam),
101 MPARAM lParam)
102 {
103 if (ulMessage == wxWM_PROC_TERMINATED)
104 {
105 wxExecuteData* pData = (wxExecuteData *)lParam;
106
107 if (pData->pHandler)
108 {
109 pData->pHandler->OnTerminate( (int)pData->vResultCodes.codeTerminate
110 ,(int)pData->vResultCodes.codeResult
111 );
112 }
113
114 if (pData->bState)
115 {
116 // we're executing synchronously, tell the waiting thread
117 // that the process finished
118 pData->bState = 0;
119 }
120 else
121 {
122 // asynchronous execution - we should do the clean up
123 delete pData;
124 }
125 ::WinDestroyWindow(hWnd); // we don't need it any more
126 }
127 return 0;
128 }
129
130 long wxExecute( const wxString& rCommand,
131 int flags,
132 wxProcess* pHandler)
133 {
134 if (rCommand.empty())
135 {
136 // cout << "empty command in wxExecute." << endl;
137 return 0;
138 }
139
140 // create the process
141 UCHAR vLoadError[CCHMAXPATH] = {0};
142 RESULTCODES vResultCodes = {0};
143 ULONG ulExecFlag;
144 PSZ zArgs = NULL;
145 PSZ zEnvs = NULL;
146 APIRET rc;
147 TID vTID;
148
149 if (flags & wxEXEC_SYNC)
150 ulExecFlag = EXEC_SYNC;
151 else
152 ulExecFlag = EXEC_ASYNCRESULT;
153
154 rc = ::DosExecPgm( (PCHAR)vLoadError
155 ,sizeof(vLoadError)
156 ,ulExecFlag
157 ,zArgs
158 ,zEnvs
159 ,&vResultCodes
160 ,(PSZ)rCommand.c_str()
161 );
162 if (rc != NO_ERROR)
163 {
164 wxLogSysError(_("Execution of command '%s' failed with error: %ul"), rCommand.c_str(), rc);
165 return 0;
166 }
167 // cout << "Executing: " << rCommand.c_str() << endl;
168 // Alloc data
169 wxExecuteData* pData = new wxExecuteData;
170
171 pData->vResultCodes = vResultCodes;
172 pData->hWnd = NULLHANDLE;
173 pData->bState = (flags & wxEXEC_SYNC) != 0;
174 if (flags & wxEXEC_SYNC)
175 {
176 wxASSERT_MSG(!pHandler, wxT("wxProcess param ignored for sync execution"));
177 pData->pHandler = NULL;
178 }
179 else
180 {
181 // may be NULL or not
182 pData->pHandler = pHandler;
183 }
184
185 rc = ::DosCreateThread( &vTID
186 ,(PFNTHREAD)&wxExecuteThread
187 ,(ULONG)pData
188 ,CREATE_READY|STACK_SPARSE
189 ,8192
190 );
191 if (rc != NO_ERROR)
192 {
193 wxLogLastError(wxT("CreateThread in wxExecute"));
194 delete pData;
195
196 // the process still started up successfully...
197 return vResultCodes.codeTerminate;
198 }
199 if (!(flags & wxEXEC_SYNC))
200 {
201 // return the pid
202 // warning: don't exit your app unless you actively
203 // kill and cleanup you child processes
204 // Maybe detach the process here???
205 // If cmd.exe need to pass DETACH to detach the process here
206 return vResultCodes.codeTerminate;
207 }
208
209 // waiting until command executed
210 ::DosWaitThread(&vTID, DCWW_WAIT);
211
212 ULONG ulExitCode = pData->vResultCodes.codeResult;
213 delete pData;
214
215 // return the exit code
216 return (long)ulExitCode;
217 }
218
219 long wxExecute(
220 char** ppArgv
221 , int flags
222 , wxProcess* pHandler
223 )
224 {
225 wxString sCommand;
226
227 while (*ppArgv != NULL)
228 {
229 wxString sArg((wxChar*)(*ppArgv++));
230
231
232 sCommand << sArg.c_str() << ' ';
233 }
234 sCommand.RemoveLast();
235 return wxExecute( sCommand
236 ,flags
237 ,pHandler
238 );
239 }
240
241 bool wxGetFullHostName( wxChar* zBuf, int nMaxSize)
242 {
243 return wxGetHostName( zBuf, nMaxSize );
244 }