1 | /* |
---|
2 | * stub16.c |
---|
3 | * |
---|
4 | * A helper program used for running 16-bit DOS applications under |
---|
5 | * Windows 95. |
---|
6 | * |
---|
7 | * Copyright (c) 1996 by Sun Microsystems, Inc. |
---|
8 | * |
---|
9 | * See the file "license.terms" for information on usage and redistribution of |
---|
10 | * this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
11 | * |
---|
12 | * RCS: @(#) $Id: stub16.c,v 1.5 2005/11/04 00:06:50 dkf Exp $ |
---|
13 | */ |
---|
14 | |
---|
15 | #define STRICT |
---|
16 | |
---|
17 | #include <windows.h> |
---|
18 | #include <stdio.h> |
---|
19 | |
---|
20 | static HANDLE CreateTempFile(void); |
---|
21 | |
---|
22 | /* |
---|
23 | *--------------------------------------------------------------------------- |
---|
24 | * |
---|
25 | * main |
---|
26 | * |
---|
27 | * Entry point for the 32-bit console mode app used by Windows 95 to help |
---|
28 | * run the 16-bit program specified on the command line. |
---|
29 | * |
---|
30 | * 1. EOF on a pipe that connects a detached 16-bit process and a 32-bit |
---|
31 | * process is never seen. So, this process runs the 16-bit process |
---|
32 | * _attached_, and then it is run detached from the calling 32-bit |
---|
33 | * process. |
---|
34 | * |
---|
35 | * 2. If a 16-bit process blocks reading from or writing to a pipe, it |
---|
36 | * never wakes up, and eventually brings the whole system down with it if |
---|
37 | * you try to kill the process. This app simulates pipes. If any of the |
---|
38 | * stdio handles is a pipe, this program accumulates information into |
---|
39 | * temp files and forwards it to or from the DOS application as |
---|
40 | * appropriate. This means that this program must receive EOF from a |
---|
41 | * stdin pipe before it will actually start the DOS app, and the DOS app |
---|
42 | * must finish generating stdout or stderr before the data will be sent |
---|
43 | * to the next stage of the pipe. If the stdio handles are not pipes, no |
---|
44 | * accumulation occurs and the data is passed straight through to and |
---|
45 | * from the DOS application. |
---|
46 | * |
---|
47 | * Results: |
---|
48 | * None. |
---|
49 | * |
---|
50 | * Side effects: |
---|
51 | * The child process is created and this process waits for it to |
---|
52 | * complete. |
---|
53 | * |
---|
54 | *--------------------------------------------------------------------------- |
---|
55 | */ |
---|
56 | |
---|
57 | int |
---|
58 | main(void) |
---|
59 | { |
---|
60 | DWORD dwRead, dwWrite; |
---|
61 | char *cmdLine; |
---|
62 | HANDLE hStdInput, hStdOutput, hStdError; |
---|
63 | HANDLE hFileInput, hFileOutput, hFileError; |
---|
64 | STARTUPINFO si; |
---|
65 | PROCESS_INFORMATION pi; |
---|
66 | char buf[8192]; |
---|
67 | DWORD result; |
---|
68 | |
---|
69 | hFileInput = INVALID_HANDLE_VALUE; |
---|
70 | hFileOutput = INVALID_HANDLE_VALUE; |
---|
71 | hFileError = INVALID_HANDLE_VALUE; |
---|
72 | result = 1; |
---|
73 | |
---|
74 | /* |
---|
75 | * Don't get command line from argc, argv, because the command line |
---|
76 | * tokenizer will have stripped off all the escape sequences needed for |
---|
77 | * quotes and backslashes, and then we'd have to put them all back in |
---|
78 | * again. Get the raw command line and parse off what we want ourselves. |
---|
79 | * The command line should be of the form: |
---|
80 | * |
---|
81 | * stub16.exe program arg1 arg2 ... |
---|
82 | */ |
---|
83 | |
---|
84 | cmdLine = strchr(GetCommandLine(), ' '); |
---|
85 | if (cmdLine == NULL) { |
---|
86 | return 1; |
---|
87 | } |
---|
88 | cmdLine++; |
---|
89 | |
---|
90 | hStdInput = GetStdHandle(STD_INPUT_HANDLE); |
---|
91 | hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); |
---|
92 | hStdError = GetStdHandle(STD_ERROR_HANDLE); |
---|
93 | |
---|
94 | if (GetFileType(hStdInput) == FILE_TYPE_PIPE) { |
---|
95 | hFileInput = CreateTempFile(); |
---|
96 | if (hFileInput == INVALID_HANDLE_VALUE) { |
---|
97 | goto cleanup; |
---|
98 | } |
---|
99 | while (ReadFile(hStdInput, buf, sizeof(buf), &dwRead, NULL) != FALSE) { |
---|
100 | if (dwRead == 0) { |
---|
101 | break; |
---|
102 | } |
---|
103 | if (WriteFile(hFileInput, buf, dwRead, &dwWrite, NULL) == FALSE) { |
---|
104 | goto cleanup; |
---|
105 | } |
---|
106 | } |
---|
107 | SetFilePointer(hFileInput, 0, 0, FILE_BEGIN); |
---|
108 | SetStdHandle(STD_INPUT_HANDLE, hFileInput); |
---|
109 | } |
---|
110 | if (GetFileType(hStdOutput) == FILE_TYPE_PIPE) { |
---|
111 | hFileOutput = CreateTempFile(); |
---|
112 | if (hFileOutput == INVALID_HANDLE_VALUE) { |
---|
113 | goto cleanup; |
---|
114 | } |
---|
115 | SetStdHandle(STD_OUTPUT_HANDLE, hFileOutput); |
---|
116 | } |
---|
117 | if (GetFileType(hStdError) == FILE_TYPE_PIPE) { |
---|
118 | hFileError = CreateTempFile(); |
---|
119 | if (hFileError == INVALID_HANDLE_VALUE) { |
---|
120 | goto cleanup; |
---|
121 | } |
---|
122 | SetStdHandle(STD_ERROR_HANDLE, hFileError); |
---|
123 | } |
---|
124 | |
---|
125 | ZeroMemory(&si, sizeof(si)); |
---|
126 | si.cb = sizeof(si); |
---|
127 | if (CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, |
---|
128 | &pi) == FALSE) { |
---|
129 | goto cleanup; |
---|
130 | } |
---|
131 | |
---|
132 | WaitForInputIdle(pi.hProcess, 5000); |
---|
133 | WaitForSingleObject(pi.hProcess, INFINITE); |
---|
134 | GetExitCodeProcess(pi.hProcess, &result); |
---|
135 | CloseHandle(pi.hProcess); |
---|
136 | CloseHandle(pi.hThread); |
---|
137 | |
---|
138 | if (hFileOutput != INVALID_HANDLE_VALUE) { |
---|
139 | SetFilePointer(hFileOutput, 0, 0, FILE_BEGIN); |
---|
140 | while (ReadFile(hFileOutput, buf, sizeof(buf), &dwRead, NULL) != FALSE) { |
---|
141 | if (dwRead == 0) { |
---|
142 | break; |
---|
143 | } |
---|
144 | if (WriteFile(hStdOutput, buf, dwRead, &dwWrite, NULL) == FALSE) { |
---|
145 | break; |
---|
146 | } |
---|
147 | } |
---|
148 | } |
---|
149 | if (hFileError != INVALID_HANDLE_VALUE) { |
---|
150 | SetFilePointer(hFileError, 0, 0, FILE_BEGIN); |
---|
151 | while (ReadFile(hFileError, buf, sizeof(buf), &dwRead, NULL) != FALSE) { |
---|
152 | if (dwRead == 0) { |
---|
153 | break; |
---|
154 | } |
---|
155 | if (WriteFile(hStdError, buf, dwRead, &dwWrite, NULL) == FALSE) { |
---|
156 | break; |
---|
157 | } |
---|
158 | } |
---|
159 | } |
---|
160 | |
---|
161 | cleanup: |
---|
162 | if (hFileInput != INVALID_HANDLE_VALUE) { |
---|
163 | CloseHandle(hFileInput); |
---|
164 | } |
---|
165 | if (hFileOutput != INVALID_HANDLE_VALUE) { |
---|
166 | CloseHandle(hFileOutput); |
---|
167 | } |
---|
168 | if (hFileError != INVALID_HANDLE_VALUE) { |
---|
169 | CloseHandle(hFileError); |
---|
170 | } |
---|
171 | CloseHandle(hStdInput); |
---|
172 | CloseHandle(hStdOutput); |
---|
173 | CloseHandle(hStdError); |
---|
174 | ExitProcess(result); |
---|
175 | return 1; |
---|
176 | } |
---|
177 | |
---|
178 | static HANDLE |
---|
179 | CreateTempFile(void) |
---|
180 | { |
---|
181 | char name[MAX_PATH]; |
---|
182 | SECURITY_ATTRIBUTES sa; |
---|
183 | |
---|
184 | if (GetTempPath(sizeof(name), name) == 0) { |
---|
185 | return INVALID_HANDLE_VALUE; |
---|
186 | } |
---|
187 | if (GetTempFileName(name, "tcl", 0, name) == 0) { |
---|
188 | return INVALID_HANDLE_VALUE; |
---|
189 | } |
---|
190 | |
---|
191 | sa.nLength = sizeof(sa); |
---|
192 | sa.lpSecurityDescriptor = NULL; |
---|
193 | sa.bInheritHandle = TRUE; |
---|
194 | return CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, &sa, |
---|
195 | CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, |
---|
196 | NULL); |
---|
197 | } |
---|