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