[25] | 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 | } |
---|