// // ConsoleCom.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "ConsoleCom.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // // The one and only application object // CWinApp theApp; HANDLE coutPipe, cinPipe, cerrPipe; #define CONNECTIMEOUT 1000 // // Create named pipes for stdin, stdout and stderr // Parameter: process id // BOOL CreateNamedPipes(DWORD pid) { TCHAR name[256]; _stprintf(name, _T("\\\\.\\pipe\\%dcout"), pid); if (INVALID_HANDLE_VALUE == (coutPipe = CreateNamedPipe(name, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, 1024, 1024, CONNECTIMEOUT, NULL))) return 0; _stprintf(name, _T("\\\\.\\pipe\\%dcin"), pid); if (INVALID_HANDLE_VALUE == (cinPipe = CreateNamedPipe(name, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, 1024, 1024, CONNECTIMEOUT, NULL))) return 0; _stprintf(name, _T("\\\\.\\pipe\\%dcerr"), pid); if (INVALID_HANDLE_VALUE == (cerrPipe = CreateNamedPipe(name, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, 1024, 1024, CONNECTIMEOUT, NULL))) return 0; return 1; } // // Close all named pipes // void CloseNamedPipes() { CloseHandle(coutPipe); CloseHandle(cerrPipe); CloseHandle(cinPipe); } // // Thread function that handles incoming bytesreams to be outputed // on stdout // void __cdecl OutPipeTh(void*) { TCHAR buffer[1024]; DWORD count = 0; ConnectNamedPipe(coutPipe, NULL); while(ReadFile(coutPipe, buffer, 1024, &count, NULL)) { buffer[count] = 0; cout << buffer << flush; } } // // Thread function that handles incoming bytesreams to be outputed // on stderr // void __cdecl ErrPipeTh(void*) { TCHAR buffer[1024]; DWORD count = 0; ConnectNamedPipe(cerrPipe, NULL); while(ReadFile(cerrPipe, buffer, 1024, &count, NULL)) { buffer[count] = 0; cerr << buffer << flush; } } // // Thread function that handles incoming bytesreams from stdin // void __cdecl InPipeTh(void*) { TCHAR buffer[1024]; DWORD countr = 0; DWORD countw = 0; ConnectNamedPipe(cinPipe, NULL); for(;;) { if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE), buffer, 1024, &countr, NULL)) break; if (!WriteFile(cinPipe, buffer, countr, &countw, NULL)) break; } } // // Start handler pipe handler threads // void RunPipeThreads() { _beginthread(InPipeTh, 0, NULL); _beginthread(OutPipeTh, 0, NULL); _beginthread(ErrPipeTh, 0, NULL); } int __cdecl _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { ULONG nRetCode = 0; // // initialize MFC and print and error on failure // if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { _tprintf(_T("Fatal Error: MFC initialization failed\n")); nRetCode = 1; } else { // // create command line string based on program name // TCHAR drive[_MAX_DRIVE]; TCHAR dir[_MAX_DIR]; TCHAR fname[_MAX_FNAME]; TCHAR ext[_MAX_EXT]; _tsplitpath(argv[0], drive, dir, fname, ext); TCHAR cParams[1024]; _tcscpy(cParams, GetCommandLine() + _tcslen(argv[0]) + 1); TCHAR cLine[2028]; _stprintf(cLine, _T("%s%s%s.exe %s"), drive, dir, fname, cParams); // // create process in suspended mode // PROCESS_INFORMATION pInfo; STARTUPINFO sInfo; memset(&sInfo, 0, sizeof(STARTUPINFO)); sInfo.cb = sizeof(STARTUPINFO); //cout << "Calling " << cLine << endl; if (!CreateProcess(NULL, cLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sInfo, &pInfo)) { cerr << _T("ERROR: Could not create process.") << endl; return 1; } if (!CreateNamedPipes(pInfo.dwProcessId)) { cerr << _T("ERROR: Could not create named pipes.") << endl; return 1; } RunPipeThreads(); // // resume process // ResumeThread(pInfo.hThread); WaitForSingleObject(pInfo.hProcess, INFINITE); CloseNamedPipes(); GetExitCodeProcess(pInfo.hProcess, (ULONG*)&nRetCode); } return (int)nRetCode; }