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 20static 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 57int 58main(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 178static HANDLE 179CreateTempFile(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} 198