sl@0: /* sl@0: * stub16.c sl@0: * sl@0: * A helper program used for running 16-bit DOS applications under sl@0: * Windows 95. sl@0: * sl@0: * Copyright (c) 1996 by Sun Microsystems, Inc. sl@0: * sl@0: * See the file "license.terms" for information on usage and redistribution sl@0: * of this file, and for a DISCLAIMER OF ALL WARRANTIES. sl@0: * sl@0: * RCS: @(#) $Id: stub16.c,v 1.4 1999/04/21 21:50:34 rjohnson Exp $ sl@0: */ sl@0: sl@0: #define STRICT sl@0: sl@0: #include sl@0: #include sl@0: sl@0: static HANDLE CreateTempFile(void); sl@0: sl@0: /* sl@0: *--------------------------------------------------------------------------- sl@0: * sl@0: * main sl@0: * sl@0: * Entry point for the 32-bit console mode app used by Windows 95 to sl@0: * help run the 16-bit program specified on the command line. sl@0: * sl@0: * 1. EOF on a pipe that connects a detached 16-bit process and a sl@0: * 32-bit process is never seen. So, this process runs the 16-bit sl@0: * process _attached_, and then it is run detached from the calling sl@0: * 32-bit process. sl@0: * sl@0: * 2. If a 16-bit process blocks reading from or writing to a pipe, sl@0: * it never wakes up, and eventually brings the whole system down sl@0: * with it if you try to kill the process. This app simulates sl@0: * pipes. If any of the stdio handles is a pipe, this program sl@0: * accumulates information into temp files and forwards it to or sl@0: * from the DOS application as appropriate. This means that this sl@0: * program must receive EOF from a stdin pipe before it will actually sl@0: * start the DOS app, and the DOS app must finish generating stdout sl@0: * or stderr before the data will be sent to the next stage of the sl@0: * pipe. If the stdio handles are not pipes, no accumulation occurs sl@0: * and the data is passed straight through to and from the DOS sl@0: * application. sl@0: * sl@0: * Results: sl@0: * None. sl@0: * sl@0: * Side effects: sl@0: * The child process is created and this process waits for it to sl@0: * complete. sl@0: * sl@0: *--------------------------------------------------------------------------- sl@0: */ sl@0: sl@0: int sl@0: main() sl@0: { sl@0: DWORD dwRead, dwWrite; sl@0: char *cmdLine; sl@0: HANDLE hStdInput, hStdOutput, hStdError; sl@0: HANDLE hFileInput, hFileOutput, hFileError; sl@0: STARTUPINFO si; sl@0: PROCESS_INFORMATION pi; sl@0: char buf[8192]; sl@0: DWORD result; sl@0: sl@0: hFileInput = INVALID_HANDLE_VALUE; sl@0: hFileOutput = INVALID_HANDLE_VALUE; sl@0: hFileError = INVALID_HANDLE_VALUE; sl@0: result = 1; sl@0: sl@0: /* sl@0: * Don't get command line from argc, argv, because the command line sl@0: * tokenizer will have stripped off all the escape sequences needed sl@0: * for quotes and backslashes, and then we'd have to put them all sl@0: * back in again. Get the raw command line and parse off what we sl@0: * want ourselves. The command line should be of the form: sl@0: * sl@0: * stub16.exe program arg1 arg2 ... sl@0: */ sl@0: sl@0: cmdLine = strchr(GetCommandLine(), ' '); sl@0: if (cmdLine == NULL) { sl@0: return 1; sl@0: } sl@0: cmdLine++; sl@0: sl@0: hStdInput = GetStdHandle(STD_INPUT_HANDLE); sl@0: hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); sl@0: hStdError = GetStdHandle(STD_ERROR_HANDLE); sl@0: sl@0: if (GetFileType(hStdInput) == FILE_TYPE_PIPE) { sl@0: hFileInput = CreateTempFile(); sl@0: if (hFileInput == INVALID_HANDLE_VALUE) { sl@0: goto cleanup; sl@0: } sl@0: while (ReadFile(hStdInput, buf, sizeof(buf), &dwRead, NULL) != FALSE) { sl@0: if (dwRead == 0) { sl@0: break; sl@0: } sl@0: if (WriteFile(hFileInput, buf, dwRead, &dwWrite, NULL) == FALSE) { sl@0: goto cleanup; sl@0: } sl@0: } sl@0: SetFilePointer(hFileInput, 0, 0, FILE_BEGIN); sl@0: SetStdHandle(STD_INPUT_HANDLE, hFileInput); sl@0: } sl@0: if (GetFileType(hStdOutput) == FILE_TYPE_PIPE) { sl@0: hFileOutput = CreateTempFile(); sl@0: if (hFileOutput == INVALID_HANDLE_VALUE) { sl@0: goto cleanup; sl@0: } sl@0: SetStdHandle(STD_OUTPUT_HANDLE, hFileOutput); sl@0: } sl@0: if (GetFileType(hStdError) == FILE_TYPE_PIPE) { sl@0: hFileError = CreateTempFile(); sl@0: if (hFileError == INVALID_HANDLE_VALUE) { sl@0: goto cleanup; sl@0: } sl@0: SetStdHandle(STD_ERROR_HANDLE, hFileError); sl@0: } sl@0: sl@0: ZeroMemory(&si, sizeof(si)); sl@0: si.cb = sizeof(si); sl@0: if (CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, sl@0: &pi) == FALSE) { sl@0: goto cleanup; sl@0: } sl@0: sl@0: WaitForInputIdle(pi.hProcess, 5000); sl@0: WaitForSingleObject(pi.hProcess, INFINITE); sl@0: GetExitCodeProcess(pi.hProcess, &result); sl@0: CloseHandle(pi.hProcess); sl@0: CloseHandle(pi.hThread); sl@0: sl@0: if (hFileOutput != INVALID_HANDLE_VALUE) { sl@0: SetFilePointer(hFileOutput, 0, 0, FILE_BEGIN); sl@0: while (ReadFile(hFileOutput, buf, sizeof(buf), &dwRead, NULL) != FALSE) { sl@0: if (dwRead == 0) { sl@0: break; sl@0: } sl@0: if (WriteFile(hStdOutput, buf, dwRead, &dwWrite, NULL) == FALSE) { sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: if (hFileError != INVALID_HANDLE_VALUE) { sl@0: SetFilePointer(hFileError, 0, 0, FILE_BEGIN); sl@0: while (ReadFile(hFileError, buf, sizeof(buf), &dwRead, NULL) != FALSE) { sl@0: if (dwRead == 0) { sl@0: break; sl@0: } sl@0: if (WriteFile(hStdError, buf, dwRead, &dwWrite, NULL) == FALSE) { sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: cleanup: sl@0: if (hFileInput != INVALID_HANDLE_VALUE) { sl@0: CloseHandle(hFileInput); sl@0: } sl@0: if (hFileOutput != INVALID_HANDLE_VALUE) { sl@0: CloseHandle(hFileOutput); sl@0: } sl@0: if (hFileError != INVALID_HANDLE_VALUE) { sl@0: CloseHandle(hFileError); sl@0: } sl@0: CloseHandle(hStdInput); sl@0: CloseHandle(hStdOutput); sl@0: CloseHandle(hStdError); sl@0: ExitProcess(result); sl@0: return 1; sl@0: } sl@0: sl@0: static HANDLE sl@0: CreateTempFile() sl@0: { sl@0: char name[MAX_PATH]; sl@0: SECURITY_ATTRIBUTES sa; sl@0: sl@0: if (GetTempPath(sizeof(name), name) == 0) { sl@0: return INVALID_HANDLE_VALUE; sl@0: } sl@0: if (GetTempFileName(name, "tcl", 0, name) == 0) { sl@0: return INVALID_HANDLE_VALUE; sl@0: } sl@0: sl@0: sa.nLength = sizeof(sa); sl@0: sa.lpSecurityDescriptor = NULL; sl@0: sa.bInheritHandle = TRUE; sl@0: return CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, &sa, sl@0: CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, sl@0: NULL); sl@0: }