Visualage fixes for Stefan's socket implementations, some scrolling fixes and dir...
[wxWidgets.git] / src / os2 / utilsexc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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 license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/setup.h"
17 #include "wx/utils.h"
18 #include "wx/app.h"
19 #include "wx/intl.h"
20 #endif
21
22 #include "wx/log.h"
23
24 #include "wx/process.h"
25
26 #include "wx/os2/private.h"
27
28 #define PURE_32
29 #ifndef __EMX__
30 #include <upm.h>
31 #include <netcons.h>
32 #include <netbios.h>
33 #endif
34
35 #include <ctype.h>
36 #ifdef __EMX__
37 #include <dirent.h>
38 #endif
39
40 #include <sys/stat.h>
41 #include <io.h>
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 //
47 // already defined via nerror.h in app.h so undef them
48 //
49 #ifdef EEXIST
50 #undef EEXIST
51 #endif
52 #ifdef ENOENT
53 #undef ENOENT
54 #endif
55 #ifdef EMFILE
56 #undef EMFILE
57 #endif
58 #ifdef EINTR
59 #undef EINTR
60 #endif
61 #ifdef EINVAL
62 #undef EINVAL
63 #endif
64 #ifdef ENOMEM
65 #undef ENOMEM
66 #endif
67 #ifdef EACCES
68 #undef EACCES
69 #endif
70 #include <errno.h>
71 #include <stdarg.h>
72
73
74 // this message is sent when the process we're waiting for terminates
75 #define wxWM_PROC_TERMINATED (WM_USER + 10000)
76
77 #ifndef NO_ERROR
78 # define NO_ERROR 0
79 #endif
80
81 // structure describing the process we're being waiting for
82 struct wxExecuteData
83 {
84 public:
85 ~wxExecuteData()
86 {
87 // cout << "Closing thread: " << endl;
88 DosExit(EXIT_PROCESS, 0);
89 }
90
91 HWND hWnd; // window to send wxWM_PROC_TERMINATED to [not used]
92 RESULTCODES vResultCodes;
93 wxProcess* pHandler;
94 ULONG ulExitCode; // the exit code of the process
95 bool bState; // set to FALSE when the process finishes
96 };
97
98 static ULONG wxExecuteThread(
99 wxExecuteData* pData
100 )
101 {
102 ULONG ulRc;
103 PID vPidChild;
104
105 // cout << "Executing thread: " << endl;
106
107 ulRc = ::DosWaitChild( DCWA_PROCESSTREE
108 ,DCWW_NOWAIT
109 ,&pData->vResultCodes
110 ,&vPidChild
111 ,pData->vResultCodes.codeTerminate // process PID to look at
112 );
113 if (ulRc != NO_ERROR)
114 {
115 wxLogLastError("DosWaitChild");
116 }
117 delete pData;
118 return 0;
119 }
120
121 // window procedure of a hidden window which is created just to receive
122 // the notification message when a process exits
123 MRESULT APIENTRY wxExecuteWindowCbk(
124 HWND hWnd
125 , ULONG ulMessage
126 , MPARAM wParam
127 , MPARAM lParam
128 )
129 {
130 if (ulMessage == wxWM_PROC_TERMINATED)
131 {
132 wxExecuteData* pData = (wxExecuteData *)lParam;
133
134 if (pData->pHandler)
135 {
136 pData->pHandler->OnTerminate( (int)pData->vResultCodes.codeTerminate
137 ,(int)pData->vResultCodes.codeResult
138 );
139 }
140
141 if (pData->bState)
142 {
143 // we're executing synchronously, tell the waiting thread
144 // that the process finished
145 pData->bState = 0;
146 }
147 else
148 {
149 // asynchronous execution - we should do the clean up
150 delete pData;
151 }
152 ::WinDestroyWindow(hWnd); // we don't need it any more
153 }
154 return 0;
155 }
156
157 extern wxChar wxPanelClassName[];
158
159 long wxExecute(
160 const wxString& rCommand
161 , bool bSync
162 , wxProcess* pHandler
163 )
164 {
165 if (rCommand.IsEmpty())
166 {
167 // cout << "empty command in wxExecute." << endl;
168 return 0;
169 }
170
171 // create the process
172 UCHAR vLoadError[CCHMAXPATH] = {0};
173 RESULTCODES vResultCodes = {0};
174 ULONG ulExecFlag;
175 PSZ zArgs = NULL;
176 PSZ zEnvs = NULL;
177 ULONG ulWindowId;
178 APIRET rc;
179 PFNWP pOldProc;
180 TID vTID;
181
182 if (bSync)
183 ulExecFlag = EXEC_SYNC;
184 else
185 ulExecFlag = EXEC_ASYNCRESULT;
186
187 rc = ::DosExecPgm( (PCHAR)vLoadError
188 ,sizeof(vLoadError)
189 ,ulExecFlag
190 ,zArgs
191 ,zEnvs
192 ,&vResultCodes
193 ,(PSZ)rCommand.c_str()
194 );
195 if (rc != NO_ERROR)
196 {
197 wxLogSysError(_("Execution of command '%s' failed with error: %ul"), rCommand.c_str(), rc);
198 return 0;
199 }
200 // cout << "Executing: " << rCommand.c_str() << endl;
201 // Alloc data
202 wxExecuteData* pData = new wxExecuteData;
203
204 pData->vResultCodes = vResultCodes;
205 pData->hWnd = NULLHANDLE;
206 pData->bState = bSync;
207 if (bSync)
208 {
209 wxASSERT_MSG(!pHandler, wxT("wxProcess param ignored for sync execution"));
210 pData->pHandler = NULL;
211 }
212 else
213 {
214 // may be NULL or not
215 pData->pHandler = pHandler;
216 }
217
218 rc = ::DosCreateThread( &vTID
219 ,(PFNTHREAD)&wxExecuteThread
220 ,(ULONG)pData
221 ,CREATE_READY|STACK_SPARSE
222 ,8192
223 );
224 if (rc != NO_ERROR)
225 {
226 wxLogLastError("CreateThread in wxExecute");
227 delete pData;
228
229 // the process still started up successfully...
230 return vResultCodes.codeTerminate;
231 }
232 if (!bSync)
233 {
234 // return the pid
235 // warning: don't exit your app unless you actively
236 // kill and cleanup you child processes
237 // Maybe detach the process here???
238 // If cmd.exe need to pass DETACH to detach the process here
239 return vResultCodes.codeTerminate;
240 }
241
242 // waiting until command executed
243 ::DosWaitThread(&vTID, DCWW_WAIT);
244
245 ULONG ulExitCode = pData->vResultCodes.codeResult;
246 delete pData;
247
248 // return the exit code
249 return (long)ulExitCode;
250 }
251
252 long wxExecute(
253 char** ppArgv
254 , bool bSync
255 , wxProcess* pHandler
256 )
257 {
258 wxString sCommand;
259
260 while (*ppArgv != NULL)
261 {
262 sCommand << *ppArgv++ << ' ';
263 }
264 sCommand.RemoveLast();
265 return wxExecute( sCommand
266 ,bSync
267 ,pHandler
268 );
269 }
270
271 bool wxGetFullHostName(
272 wxChar* zBuf
273 , int nMaxSize
274 )
275 {
276 #if wxUSE_NET_API
277 char zServer[256];
278 char zComputer[256];
279 unsigned long ulLevel = 0;
280 unsigned char* zBuffer = NULL;
281 unsigned long ulBuffer = 256;
282 unsigned long* pulTotalAvail = NULL;
283
284 NetBios32GetInfo( (const unsigned char*)zServer
285 ,(const unsigned char*)zComputer
286 ,ulLevel
287 ,zBuffer
288 ,ulBuffer
289 ,pulTotalAvail
290 );
291 strncpy(zBuf, zComputer, nMaxSize);
292 zBuf[nMaxSize] = _T('\0');
293 #else
294 strcpy(zBuf, "noname");
295 #endif
296 return *zBuf ? TRUE : FALSE;
297 return TRUE;
298 }
299