]>
Commit | Line | Data |
---|---|---|
0e320a79 DW |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: utilsexec.cpp | |
d90895ac DW |
3 | // Purpose: Various utilities |
4 | // Author: David Webster | |
0e320a79 | 5 | // Modified by: |
d90895ac | 6 | // Created: 10/17/99 |
0e320a79 | 7 | // RCS-ID: $Id$ |
d90895ac DW |
8 | // Copyright: (c) David Webster |
9 | // Licence: wxWindows license | |
0e320a79 DW |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
d90895ac DW |
12 | // For compilers that support precompilation, includes "wx.h". |
13 | #include "wx/wxprec.h" | |
0e320a79 | 14 | |
d90895ac DW |
15 | #ifndef WX_PRECOMP |
16 | #include "wx/setup.h" | |
0e320a79 | 17 | #include "wx/utils.h" |
d90895ac DW |
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 INCL_DOS | |
29 | #include <os2.h> | |
30 | ||
31 | #include <ctype.h> | |
32 | #include <direct.h> | |
33 | ||
34 | #include <sys/stat.h> | |
35 | #include <io.h> | |
0e320a79 DW |
36 | |
37 | #include <stdio.h> | |
38 | #include <stdlib.h> | |
39 | #include <string.h> | |
d90895ac DW |
40 | #include <errno.h> |
41 | #include <stdarg.h> | |
42 | ||
43 | // this message is sent when the process we're waiting for terminates | |
44 | #define wxWM_PROC_TERMINATED (WM_USER + 10000) | |
45 | ||
46 | // structure describing the process we're being waiting for | |
47 | struct wxExecuteData | |
48 | { | |
49 | public: | |
50 | ~wxExecuteData() | |
51 | { | |
52 | // TODO: | |
53 | /* | |
54 | if ( !::CloseHandle(hProcess) ) | |
55 | { | |
56 | wxLogLastError("CloseHandle(hProcess)"); | |
57 | } | |
58 | */ | |
59 | } | |
60 | ||
61 | HWND hWnd; // window to send wxWM_PROC_TERMINATED to | |
62 | HANDLE hProcess; // handle of the process | |
63 | DWORD dwProcessId; // pid of the process | |
64 | wxProcess *handler; | |
65 | DWORD dwExitCode; // the exit code of the process | |
66 | bool state; // set to FALSE when the process finishes | |
67 | }; | |
68 | ||
69 | ||
70 | static DWORD wxExecuteThread(wxExecuteData *data) | |
71 | { | |
72 | // TODO: | |
73 | /* | |
74 | WaitForSingleObject(data->hProcess, INFINITE); | |
0e320a79 | 75 | |
d90895ac DW |
76 | // get the exit code |
77 | if ( !GetExitCodeProcess(data->hProcess, &data->dwExitCode) ) | |
78 | { | |
79 | wxLogLastError("GetExitCodeProcess"); | |
80 | } | |
81 | ||
82 | wxASSERT_MSG( data->dwExitCode != STILL_ACTIVE, | |
83 | wxT("process should have terminated") ); | |
84 | ||
85 | // send a message indicating process termination to the window | |
86 | SendMessage(data->hWnd, wxWM_PROC_TERMINATED, 0, (LPARAM)data); | |
87 | */ | |
88 | return 0; | |
89 | } | |
90 | ||
91 | // window procedure of a hidden window which is created just to receive | |
92 | // the notification message when a process exits | |
93 | MRESULT APIENTRY wxExecuteWindowCbk(HWND hWnd, UINT message, | |
94 | MPARAM wParam, MPARAM lParam) | |
95 | { | |
96 | if ( message == wxWM_PROC_TERMINATED ) | |
97 | { | |
98 | // DestroyWindow(hWnd); // we don't need it any more | |
99 | ||
100 | wxExecuteData *data = (wxExecuteData *)lParam; | |
101 | if ( data->handler ) | |
102 | { | |
103 | data->handler->OnTerminate((int)data->dwProcessId, | |
104 | (int)data->dwExitCode); | |
105 | } | |
106 | ||
107 | if ( data->state ) | |
108 | { | |
109 | // we're executing synchronously, tell the waiting thread | |
110 | // that the process finished | |
111 | data->state = 0; | |
112 | } | |
113 | else | |
114 | { | |
115 | // asynchronous execution - we should do the clean up | |
116 | delete data; | |
117 | } | |
118 | } | |
119 | ||
120 | return 0; | |
121 | } | |
122 | ||
123 | extern wxChar wxPanelClassName[]; | |
0e320a79 DW |
124 | |
125 | long wxExecute(const wxString& command, bool sync, wxProcess *handler) | |
126 | { | |
d90895ac DW |
127 | wxCHECK_MSG( !!command, 0, wxT("empty command in wxExecute") ); |
128 | ||
129 | // the old code is disabled because we really need a process handle | |
130 | // if we want to execute it asynchronously or even just get its | |
131 | // return code and for this we must use CreateProcess() and not | |
132 | // ShellExecute() | |
133 | ||
134 | // create the process | |
135 | // TODO: | |
136 | /* | |
137 | STARTUPINFO si; | |
138 | memset(&si, 0, sizeof(si)); | |
139 | si.cb = sizeof(si); | |
140 | ||
141 | PROCESS_INFORMATION pi; | |
142 | ||
143 | if ( ::CreateProcess( | |
144 | NULL, // application name (use only cmd line) | |
145 | (wxChar *)command.c_str(), // full command line | |
146 | NULL, // security attributes: defaults for both | |
147 | NULL, // the process and its main thread | |
148 | FALSE, // don't inherit handles | |
149 | CREATE_DEFAULT_ERROR_MODE, // flags | |
150 | NULL, // environment (use the same) | |
151 | NULL, // current directory (use the same) | |
152 | &si, // startup info (unused here) | |
153 | &pi // process info | |
154 | ) == 0 ) | |
155 | { | |
156 | wxLogSysError(_("Execution of command '%s' failed"), command.c_str()); | |
157 | ||
158 | return 0; | |
159 | } | |
160 | ||
161 | // close unneeded handle | |
162 | if ( !::CloseHandle(pi.hThread) ) | |
163 | wxLogLastError("CloseHandle(hThread)"); | |
164 | ||
165 | // create a hidden window to receive notification about process | |
166 | // termination | |
167 | HWND hwnd = ::CreateWindow(wxPanelClassName, NULL, 0, 0, 0, 0, 0, NULL, | |
168 | (HMENU)NULL, wxGetInstance(), 0); | |
169 | wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") ); | |
170 | ||
171 | FARPROC ExecuteWindowInstance = MakeProcInstance((FARPROC)wxExecuteWindowCbk, | |
172 | wxGetInstance()); | |
173 | ||
174 | ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) ExecuteWindowInstance); | |
175 | ||
176 | // Alloc data | |
177 | wxExecuteData *data = new wxExecuteData; | |
178 | data->hProcess = pi.hProcess; | |
179 | data->dwProcessId = pi.dwProcessId; | |
180 | data->hWnd = hwnd; | |
181 | data->state = sync; | |
182 | if ( sync ) | |
183 | { | |
184 | wxASSERT_MSG( !handler, wxT("wxProcess param ignored for sync execution") ); | |
185 | ||
186 | data->handler = NULL; | |
187 | } | |
188 | else | |
189 | { | |
190 | // may be NULL or not | |
191 | data->handler = handler; | |
192 | } | |
193 | ||
194 | DWORD tid; | |
195 | HANDLE hThread = ::CreateThread(NULL, | |
196 | 0, | |
197 | (LPTHREAD_START_ROUTINE)wxExecuteThread, | |
198 | (void *)data, | |
199 | 0, | |
200 | &tid); | |
201 | ||
202 | if ( !hThread ) | |
203 | { | |
204 | wxLogLastError("CreateThread in wxExecute"); | |
205 | ||
206 | DestroyWindow(hwnd); | |
207 | delete data; | |
208 | ||
209 | // the process still started up successfully... | |
210 | return pi.dwProcessId; | |
211 | } | |
212 | ||
213 | if ( !sync ) | |
214 | { | |
215 | // clean up will be done when the process terminates | |
216 | ||
217 | // return the pid | |
218 | return pi.dwProcessId; | |
219 | } | |
220 | ||
221 | // waiting until command executed | |
222 | while ( data->state ) | |
223 | wxYield(); | |
224 | ||
225 | DWORD dwExitCode = data->dwExitCode; | |
226 | delete data; | |
227 | ||
228 | // return the exit code | |
229 | return dwExitCode; | |
230 | */ | |
0e320a79 DW |
231 | return 0; |
232 | } | |
d90895ac DW |
233 | |
234 | long wxExecute(char **argv, bool sync, wxProcess *handler) | |
235 | { | |
236 | wxString command; | |
237 | ||
238 | while ( *argv != NULL ) | |
239 | { | |
240 | command << *argv++ << ' '; | |
241 | } | |
242 | ||
243 | command.RemoveLast(); | |
244 | ||
245 | return wxExecute(command, sync, handler); | |
246 | } | |
247 | ||
248 | bool wxGetFullHostName(wxChar *buf, int maxSize) | |
249 | { | |
250 | DWORD nSize = maxSize ; | |
251 | // TODO: | |
252 | /* | |
253 | if ( !::GetComputerName(buf, &nSize) ) | |
254 | { | |
255 | wxLogLastError("GetComputerName"); | |
256 | ||
257 | return FALSE; | |
258 | } | |
259 | */ | |
260 | return TRUE; | |
261 | } | |
262 |