1 |
578 |
markom |
/*
|
2 |
|
|
* tclWin16.c --
|
3 |
|
|
*
|
4 |
|
|
* This file contains code for a 16-bit DLL to handle 32-to-16 bit
|
5 |
|
|
* thunking. This is necessary for the Win32s SynchSpawn() call.
|
6 |
|
|
*
|
7 |
|
|
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
|
8 |
|
|
*
|
9 |
|
|
* See the file "license.terms" for information on usage and redistribution
|
10 |
|
|
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
11 |
|
|
*
|
12 |
|
|
* RCS: @(#) $Id: tclWin16.c,v 1.1.1.1 2002-01-16 10:25:38 markom Exp $
|
13 |
|
|
*/
|
14 |
|
|
|
15 |
|
|
#define STRICT
|
16 |
|
|
|
17 |
|
|
#include <windows.h>
|
18 |
|
|
#include <toolhelp.h>
|
19 |
|
|
|
20 |
|
|
#include <stdio.h>
|
21 |
|
|
#include <string.h>
|
22 |
|
|
|
23 |
|
|
static int WinSpawn(char *command);
|
24 |
|
|
static int DosSpawn(char *command, char *fromFileName,
|
25 |
|
|
char *toFileName);
|
26 |
|
|
static int WaitForExit(int inst);
|
27 |
|
|
|
28 |
|
|
/*
|
29 |
|
|
* The following data is used to construct a .pif file that wraps the
|
30 |
|
|
* .bat file that runs the 16-bit application (that Jack built).
|
31 |
|
|
* The .pif file causes the .bat file to run in an iconified window.
|
32 |
|
|
* Otherwise, when we try to exec something, a DOS box pops up,
|
33 |
|
|
* obscuring everything, and then almost immediately flickers out of
|
34 |
|
|
* existence, which is rather disconcerting.
|
35 |
|
|
*/
|
36 |
|
|
|
37 |
|
|
static char pifData[545] = {
|
38 |
|
|
'\000', '\013', '\040', '\040', '\040', '\040', '\040', '\040',
|
39 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
40 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
41 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
42 |
|
|
'\200', '\000', '\200', '\000', '\103', '\117', '\115', '\115',
|
43 |
|
|
'\101', '\116', '\104', '\056', '\103', '\117', '\115', '\000',
|
44 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
45 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
46 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
47 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
48 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
49 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
50 |
|
|
'\040', '\040', '\040', '\020', '\000', '\000', '\040', '\040',
|
51 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
52 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
53 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
54 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
55 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
56 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
57 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
58 |
|
|
'\040', '\040', '\040', '\040', '\040', '\000', '\000', '\000',
|
59 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
60 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
61 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
62 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
63 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
64 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
65 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
66 |
|
|
'\000', '\000', '\000', '\000', '\000', '\177', '\001', '\000',
|
67 |
|
|
'\377', '\031', '\120', '\000', '\000', '\007', '\000', '\000',
|
68 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
69 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
70 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
71 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
72 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
73 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
74 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
75 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
76 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
77 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
78 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
79 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
80 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
81 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
82 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
83 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\340',
|
84 |
|
|
'\040', '\115', '\111', '\103', '\122', '\117', '\123', '\117',
|
85 |
|
|
'\106', '\124', '\040', '\120', '\111', '\106', '\105', '\130',
|
86 |
|
|
'\000', '\207', '\001', '\000', '\000', '\161', '\001', '\127',
|
87 |
|
|
'\111', '\116', '\104', '\117', '\127', '\123', '\040', '\063',
|
88 |
|
|
'\070', '\066', '\040', '\063', '\056', '\060', '\000', '\005',
|
89 |
|
|
'\002', '\235', '\001', '\150', '\000', '\200', '\002', '\200',
|
90 |
|
|
'\000', '\144', '\000', '\062', '\000', '\000', '\004', '\000',
|
91 |
|
|
'\000', '\000', '\004', '\000', '\000', '\002', '\020', '\002',
|
92 |
|
|
'\000', '\037', '\000', '\000', '\000', '\000', '\000', '\000',
|
93 |
|
|
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
|
94 |
|
|
'\000', '\000', '\000', '\000', '\000', '\057', '\143', '\040',
|
95 |
|
|
'\146', '\157', '\157', '\056', '\142', '\141', '\164', '\000',
|
96 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
97 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
98 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
99 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
100 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
101 |
|
|
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
|
102 |
|
|
'\040', '\040', '\040', '\040', '\040', '\127', '\111', '\116',
|
103 |
|
|
'\104', '\117', '\127', '\123', '\040', '\062', '\070', '\066',
|
104 |
|
|
'\040', '\063', '\056', '\060', '\000', '\377', '\377', '\033',
|
105 |
|
|
'\002', '\006', '\000', '\000', '\000', '\000', '\000', '\000',
|
106 |
|
|
'\000'
|
107 |
|
|
};
|
108 |
|
|
|
109 |
|
|
static HINSTANCE hInstance;
|
110 |
|
|
|
111 |
|
|
|
112 |
|
|
/*
|
113 |
|
|
*----------------------------------------------------------------------
|
114 |
|
|
*
|
115 |
|
|
* LibMain --
|
116 |
|
|
*
|
117 |
|
|
* 16-bit DLL entry point.
|
118 |
|
|
*
|
119 |
|
|
* Results:
|
120 |
|
|
* Returns 1.
|
121 |
|
|
*
|
122 |
|
|
* Side effects:
|
123 |
|
|
* None.
|
124 |
|
|
*
|
125 |
|
|
*----------------------------------------------------------------------
|
126 |
|
|
*/
|
127 |
|
|
|
128 |
|
|
int CALLBACK
|
129 |
|
|
LibMain(
|
130 |
|
|
HINSTANCE hinst,
|
131 |
|
|
WORD wDS,
|
132 |
|
|
WORD cbHeap,
|
133 |
|
|
LPSTR unused)
|
134 |
|
|
{
|
135 |
|
|
hInstance = hinst;
|
136 |
|
|
wDS = wDS; /* lint. */
|
137 |
|
|
cbHeap = cbHeap; /* lint. */
|
138 |
|
|
unused = unused; /* lint. */
|
139 |
|
|
|
140 |
|
|
return TRUE;
|
141 |
|
|
}
|
142 |
|
|
|
143 |
|
|
/*
|
144 |
|
|
*----------------------------------------------------------------------
|
145 |
|
|
*
|
146 |
|
|
* UTProc --
|
147 |
|
|
*
|
148 |
|
|
* Universal Thunk dispatch routine. Executes a 16-bit DOS
|
149 |
|
|
* application or a 16-bit or 32-bit Windows application and
|
150 |
|
|
* waits for it to complete.
|
151 |
|
|
*
|
152 |
|
|
* Results:
|
153 |
|
|
* 1 if the application could be run, 0 or -1 on failure.
|
154 |
|
|
*
|
155 |
|
|
* Side effects:
|
156 |
|
|
* Executes 16-bit code.
|
157 |
|
|
*
|
158 |
|
|
*----------------------------------------------------------------------
|
159 |
|
|
*/
|
160 |
|
|
|
161 |
|
|
int WINAPI
|
162 |
|
|
UTProc(buf, func)
|
163 |
|
|
void *buf;
|
164 |
|
|
DWORD func;
|
165 |
|
|
{
|
166 |
|
|
char **args;
|
167 |
|
|
|
168 |
|
|
args = (char **) buf;
|
169 |
|
|
if (func == 0) {
|
170 |
|
|
return DosSpawn(args[0], args[1], args[2]);
|
171 |
|
|
} else {
|
172 |
|
|
return WinSpawn(args[0]);
|
173 |
|
|
}
|
174 |
|
|
}
|
175 |
|
|
|
176 |
|
|
/*
|
177 |
|
|
*-------------------------------------------------------------------------
|
178 |
|
|
*
|
179 |
|
|
* WinSpawn --
|
180 |
|
|
*
|
181 |
|
|
* Start a 16-bit or 32-bit Windows application with optional
|
182 |
|
|
* command line arguments and wait for it to finish. Windows
|
183 |
|
|
* applications do not handle input/output redirection.
|
184 |
|
|
*
|
185 |
|
|
* Results:
|
186 |
|
|
* The return value is 1 if the application could be run, 0 otherwise.
|
187 |
|
|
*
|
188 |
|
|
* Side effects:
|
189 |
|
|
* Whatever the application does.
|
190 |
|
|
*
|
191 |
|
|
*-------------------------------------------------------------------------
|
192 |
|
|
*/
|
193 |
|
|
|
194 |
|
|
static int
|
195 |
|
|
WinSpawn(command)
|
196 |
|
|
char *command; /* The command line, consisting of the name
|
197 |
|
|
* of the executable to run followed by any
|
198 |
|
|
* number of arguments to the executable. */
|
199 |
|
|
{
|
200 |
|
|
return WaitForExit(WinExec(command, SW_SHOW));
|
201 |
|
|
}
|
202 |
|
|
|
203 |
|
|
/*
|
204 |
|
|
*---------------------------------------------------------------------------
|
205 |
|
|
*
|
206 |
|
|
* DosSpawn --
|
207 |
|
|
*
|
208 |
|
|
* Start a 16-bit DOS program with optional command line arguments
|
209 |
|
|
* and wait for it to finish. Input and output can be redirected
|
210 |
|
|
* from the specified files, but there is no such thing as stderr
|
211 |
|
|
* under Win32s.
|
212 |
|
|
*
|
213 |
|
|
* This procedure to constructs a temporary .pif file that wraps a
|
214 |
|
|
* temporary .bat file that runs the 16-bit application. The .bat
|
215 |
|
|
* file is necessary to get the redirection symbols '<' and '>' to
|
216 |
|
|
* work, because WinExec() doesn't accept them. The .pif file is
|
217 |
|
|
* necessary to cause the .bat file to run in an iconified window,
|
218 |
|
|
* to avoid having a large DOS box pop up, obscuring everything, and
|
219 |
|
|
* then almost immediately flicker out of existence, which is rather
|
220 |
|
|
* disconcerting.
|
221 |
|
|
*
|
222 |
|
|
* Results:
|
223 |
|
|
* The return value is 1 if the application could be run, 0 otherwise.
|
224 |
|
|
*
|
225 |
|
|
* Side effects:
|
226 |
|
|
* Whatever the application does.
|
227 |
|
|
*
|
228 |
|
|
*---------------------------------------------------------------------------
|
229 |
|
|
*/
|
230 |
|
|
|
231 |
|
|
static int
|
232 |
|
|
DosSpawn(command, fromFileName, toFileName)
|
233 |
|
|
char *command; /* The name of the program, plus any
|
234 |
|
|
* arguments, to be run. */
|
235 |
|
|
char *fromFileName; /* Standard input for the program is to be
|
236 |
|
|
* redirected from this file, or NULL for no
|
237 |
|
|
* standard input. */
|
238 |
|
|
char *toFileName; /* Standard output for the program is to be
|
239 |
|
|
* redirected to this file, or NULL to
|
240 |
|
|
* discard standard output. */
|
241 |
|
|
{
|
242 |
|
|
int result;
|
243 |
|
|
HFILE batFile, pifFile;
|
244 |
|
|
char batFileName[144], pifFileName[144];
|
245 |
|
|
|
246 |
|
|
GetTempFileName(0, "tcl", 0, batFileName);
|
247 |
|
|
unlink(batFileName);
|
248 |
|
|
strcpy(strrchr(batFileName, '.'), ".bat");
|
249 |
|
|
batFile = _lcreat(batFileName, 0);
|
250 |
|
|
|
251 |
|
|
GetTempFileName(0, "tcl", 0, pifFileName);
|
252 |
|
|
unlink(pifFileName);
|
253 |
|
|
strcpy(strrchr(pifFileName, '.'), ".pif");
|
254 |
|
|
pifFile = _lcreat(pifFileName, 0);
|
255 |
|
|
|
256 |
|
|
_lwrite(batFile, command, strlen(command));
|
257 |
|
|
if (fromFileName == NULL) {
|
258 |
|
|
_lwrite(batFile, " < nul", 6);
|
259 |
|
|
} else {
|
260 |
|
|
_lwrite(batFile, " < ", 3);
|
261 |
|
|
_lwrite(batFile, fromFileName, strlen(fromFileName));
|
262 |
|
|
}
|
263 |
|
|
if (toFileName == NULL) {
|
264 |
|
|
_lwrite(batFile, " > nul", 6);
|
265 |
|
|
} else {
|
266 |
|
|
_lwrite(batFile, " > ", 3);
|
267 |
|
|
_lwrite(batFile, toFileName, strlen(toFileName));
|
268 |
|
|
}
|
269 |
|
|
_lwrite(batFile, "\r\n\032", 3);
|
270 |
|
|
_lclose(batFile);
|
271 |
|
|
|
272 |
|
|
strcpy(pifData + 0x1c8, batFileName);
|
273 |
|
|
_lwrite(pifFile, pifData, sizeof(pifData));
|
274 |
|
|
_lclose(pifFile);
|
275 |
|
|
|
276 |
|
|
result = WaitForExit(WinExec(pifFileName, SW_MINIMIZE));
|
277 |
|
|
|
278 |
|
|
unlink(pifFileName);
|
279 |
|
|
unlink(batFileName);
|
280 |
|
|
|
281 |
|
|
return result;
|
282 |
|
|
}
|
283 |
|
|
|
284 |
|
|
/*
|
285 |
|
|
*-------------------------------------------------------------------------
|
286 |
|
|
*
|
287 |
|
|
* WaitForExit --
|
288 |
|
|
*
|
289 |
|
|
* Wait until the application with the given instance handle has
|
290 |
|
|
* finished. PeekMessage() is used to yield the processor;
|
291 |
|
|
* otherwise, nothing else could execute on the system.
|
292 |
|
|
*
|
293 |
|
|
* Results:
|
294 |
|
|
* The return value is 1 if the process exited successfully,
|
295 |
|
|
* or 0 otherwise.
|
296 |
|
|
*
|
297 |
|
|
* Side effects:
|
298 |
|
|
* None.
|
299 |
|
|
*
|
300 |
|
|
*---------------------------------------------------------------------------
|
301 |
|
|
*/
|
302 |
|
|
|
303 |
|
|
static int
|
304 |
|
|
WaitForExit(inst)
|
305 |
|
|
int inst; /* Identifies the instance handle of the
|
306 |
|
|
* process to wait for. */
|
307 |
|
|
{
|
308 |
|
|
TASKENTRY te;
|
309 |
|
|
MSG msg;
|
310 |
|
|
UINT timer;
|
311 |
|
|
|
312 |
|
|
if (inst < 32) {
|
313 |
|
|
return 0;
|
314 |
|
|
}
|
315 |
|
|
|
316 |
|
|
te.dwSize = sizeof(te);
|
317 |
|
|
te.hInst = 0;
|
318 |
|
|
TaskFirst(&te);
|
319 |
|
|
do {
|
320 |
|
|
if (te.hInst == (HINSTANCE) inst) {
|
321 |
|
|
break;
|
322 |
|
|
}
|
323 |
|
|
} while (TaskNext(&te) != FALSE);
|
324 |
|
|
|
325 |
|
|
if (te.hInst != (HINSTANCE) inst) {
|
326 |
|
|
return 0;
|
327 |
|
|
}
|
328 |
|
|
|
329 |
|
|
timer = SetTimer(NULL, 0, 0, NULL);
|
330 |
|
|
while (1) {
|
331 |
|
|
if (GetMessage(&msg, NULL, 0, 0) != 0) {
|
332 |
|
|
TranslateMessage(&msg);
|
333 |
|
|
DispatchMessage(&msg);
|
334 |
|
|
}
|
335 |
|
|
TaskFirst(&te);
|
336 |
|
|
do {
|
337 |
|
|
if (te.hInst == (HINSTANCE) inst) {
|
338 |
|
|
break;
|
339 |
|
|
}
|
340 |
|
|
} while (TaskNext(&te) != FALSE);
|
341 |
|
|
|
342 |
|
|
if (te.hInst != (HINSTANCE) inst) {
|
343 |
|
|
KillTimer(NULL, timer);
|
344 |
|
|
return 1;
|
345 |
|
|
}
|
346 |
|
|
}
|
347 |
|
|
}
|