Last active
November 15, 2021 04:50
-
-
Save tkojitu/0fdae83d9c74a9c11ca6454f0a337714 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <stdio.h> | |
int main() | |
{ | |
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE); | |
HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE); | |
if (hstdout == INVALID_HANDLE_VALUE || hstdin == INVALID_HANDLE_VALUE) | |
ExitProcess(1); | |
for (;;) { | |
CHAR buf[4096]; | |
DWORD nread = 0; | |
BOOL ret = ReadFile(hstdin, buf, sizeof(buf), &nread, NULL); | |
if (!ret || nread == 0) | |
break; | |
DWORD nwrite = 0; | |
if (!WriteFile(hstdout, buf, nread, &nwrite, NULL)) | |
break; | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <tchar.h> | |
#include <stdio.h> | |
#include <strsafe.h> | |
class App { | |
public: | |
App() { | |
InitSecAttr(); | |
} | |
virtual ~App() {} | |
virtual void Demo(const wchar_t* argv) { | |
if (!argv) | |
ErrorExit(L"Please specify an input file.\n"); | |
CreatePipeForChildStdout(); | |
CreatePipeForChildStdin(); | |
CreateChildProcess(); | |
GetHandleInputFileForParent(argv); | |
WriteToPipe(); | |
ReadFromPipe(); | |
} | |
virtual void InitSecAttr() { | |
m_sec_attr.nLength = sizeof(m_sec_attr); | |
m_sec_attr.bInheritHandle = TRUE; | |
m_sec_attr.lpSecurityDescriptor = NULL; | |
} | |
virtual void CreatePipeForChildStdout() { | |
if (!CreatePipe(&m_child_stdout_rd, &m_child_stdout_wr, &m_sec_attr, 0)) | |
ErrorExit(L"StdoutRd CreatePipe"); | |
if (!SetHandleInformation(m_child_stdout_rd, HANDLE_FLAG_INHERIT, 0)) | |
ErrorExit(L"Stdout SetHandleInformation"); | |
} | |
virtual void CreatePipeForChildStdin() { | |
if (!CreatePipe(&m_child_stdin_rd, &m_child_stdin_wr, &m_sec_attr, 0)) | |
ErrorExit(L"Stdin CreatePipe"); | |
if (!SetHandleInformation(m_child_stdin_wr, HANDLE_FLAG_INHERIT, 0)) | |
ErrorExit(L"Stdin SetHandleInformation"); | |
} | |
virtual void CreateChildProcess() { | |
TCHAR cmdline[] = L"child"; | |
PROCESS_INFORMATION pinfo; | |
ZeroMemory(&pinfo, sizeof(pinfo)); | |
STARTUPINFO sinfo; | |
ZeroMemory(&sinfo, sizeof(sinfo)); | |
sinfo.cb = sizeof(sinfo); | |
sinfo.hStdError = m_child_stdout_wr; | |
sinfo.hStdOutput = m_child_stdout_wr; | |
sinfo.hStdInput = m_child_stdin_rd; | |
sinfo.dwFlags |= STARTF_USESTDHANDLES; | |
BOOL ret = CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, &pinfo); | |
if (!ret) | |
ErrorExit(L"CreateProcess"); | |
CloseHandle(pinfo.hProcess); | |
CloseHandle(pinfo.hThread); | |
CloseHandle(m_child_stdout_wr); | |
CloseHandle(m_child_stdin_rd); | |
} | |
virtual void GetHandleInputFileForParent(const wchar_t* filepath) { | |
m_input_file = CreateFile(filepath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); | |
if (m_input_file == INVALID_HANDLE_VALUE) | |
ErrorExit(L"CreateFile"); | |
} | |
virtual void WriteToPipe() { | |
for (;;) { | |
CHAR buf[BUFSIZE] = { 0 }; | |
DWORD nread = 0; | |
BOOL ret = ReadFile(m_input_file, buf, BUFSIZE, &nread, NULL); | |
if (!ret || nread == 0) | |
break; | |
DWORD nwrite = 0; | |
if (!WriteFile(m_child_stdin_wr, buf, nread, &nwrite, NULL)) | |
break; | |
} | |
if (!CloseHandle(m_child_stdin_wr)) | |
ErrorExit(L"StdInWr CloseHandle"); | |
} | |
virtual void ReadFromPipe() { | |
HANDLE parent_stdout = GetStdHandle(STD_OUTPUT_HANDLE); | |
for (;;) { | |
CHAR buf[BUFSIZE] = { 0 }; | |
DWORD nread = 0; | |
BOOL ret = ReadFile(m_child_stdout_rd, buf, BUFSIZE, &nread, NULL); | |
if (!ret || nread == 0) | |
break; | |
DWORD nwrite = 0; | |
if (!WriteFile(parent_stdout, buf, nread, &nwrite, NULL)) | |
break; | |
} | |
} | |
virtual void ErrorExit(const wchar_t* lpszFunction) { | |
LPVOID msg = nullptr; | |
DWORD dw = GetLastError(); | |
FormatMessage( | |
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, | |
NULL, | |
dw, | |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | |
(LPTSTR)&msg, | |
0, NULL); | |
LPVOID disp = LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)msg) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); | |
StringCchPrintf((LPTSTR)disp, LocalSize(disp) / sizeof(TCHAR), L"%s failed with error %d: %s", lpszFunction, dw, msg); | |
MessageBox(NULL, (LPCTSTR)disp, L"Error", MB_OK); | |
LocalFree(msg); | |
LocalFree(disp); | |
ExitProcess(1); | |
} | |
private: | |
enum { | |
BUFSIZE = 4096 | |
}; | |
SECURITY_ATTRIBUTES m_sec_attr; | |
HANDLE m_child_stdin_rd = NULL; | |
HANDLE m_child_stdin_wr = NULL; | |
HANDLE m_child_stdout_rd = NULL; | |
HANDLE m_child_stdout_wr = NULL; | |
HANDLE m_input_file = NULL; | |
}; | |
int _tmain(int argc, TCHAR* argv[]) | |
{ | |
App app; | |
app.Demo(argv[1]); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "pch.h" | |
#include "StringPipe.h" | |
#define ERR_EXIT(msg) do { \ | |
OutputDebugStringA(msg); \ | |
exit(1); \ | |
} while (0); | |
CStringPipe::CStringPipe() { | |
InitSecAttr(); | |
} | |
CStringPipe::~CStringPipe() {} | |
void CStringPipe::Doit(CString cmdline, CStringA& input, CStringA& output) { | |
CreatePipeForChildStdout(); | |
CreatePipeForChildStdin(); | |
CreateChildProcess(cmdline); | |
WriteToPipe(input); | |
ReadFromPipe(output); | |
} | |
void CStringPipe::InitSecAttr() { | |
m_sec_attr.nLength = sizeof(m_sec_attr); | |
m_sec_attr.bInheritHandle = TRUE; | |
m_sec_attr.lpSecurityDescriptor = NULL; | |
} | |
void CStringPipe::CreatePipeForChildStdout() { | |
if (!CreatePipe(&m_child_stdout_rd, &m_child_stdout_wr, &m_sec_attr, 0)) | |
ERR_EXIT("StdoutRd CreatePipe"); | |
if (!SetHandleInformation(m_child_stdout_rd, HANDLE_FLAG_INHERIT, 0)) | |
ERR_EXIT("Stdout SetHandleInformation"); | |
} | |
void CStringPipe::CreatePipeForChildStdin() { | |
if (!CreatePipe(&m_child_stdin_rd, &m_child_stdin_wr, &m_sec_attr, 0)) | |
ERR_EXIT("Stdin CreatePipe"); | |
if (!SetHandleInformation(m_child_stdin_wr, HANDLE_FLAG_INHERIT, 0)) | |
ERR_EXIT("Stdin SetHandleInformation"); | |
} | |
void CStringPipe::CreateChildProcess(CString cmdline) { | |
PROCESS_INFORMATION pinfo; | |
ZeroMemory(&pinfo, sizeof(pinfo)); | |
STARTUPINFO sinfo; | |
ZeroMemory(&sinfo, sizeof(sinfo)); | |
sinfo.cb = sizeof(sinfo); | |
sinfo.hStdError = m_child_stdout_wr; | |
sinfo.hStdOutput = m_child_stdout_wr; | |
sinfo.hStdInput = m_child_stdin_rd; | |
sinfo.dwFlags |= STARTF_USESTDHANDLES; | |
if (!CreateProcess(NULL, _bstr_t(cmdline), NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, &pinfo)) | |
ERR_EXIT("CreateProcess"); | |
CloseHandle(pinfo.hProcess); | |
CloseHandle(pinfo.hThread); | |
CloseHandle(m_child_stdout_wr); | |
CloseHandle(m_child_stdin_rd); | |
} | |
void CStringPipe::WriteToPipe(CStringA& input) { | |
for (int i = 0; i < input.GetLength(); ++i) { | |
char ch = input.GetAt(i); | |
DWORD nwritten = 0; | |
BOOL ret = WriteFile(m_child_stdin_wr, &ch, 1, &nwritten, NULL); | |
if (!ret || nwritten != 1) | |
ERR_EXIT("WriteFile"); | |
} | |
if (!CloseHandle(m_child_stdin_wr)) | |
ERR_EXIT("StdInWr CloseHandle"); | |
} | |
void CStringPipe::ReadFromPipe(CStringA& output) { | |
for (;;) { | |
CHAR ch = 0; | |
DWORD nread = 0; | |
if (!ReadFile(m_child_stdout_rd, &ch, 1, &nread, NULL)) { | |
DWORD err = GetLastError(); | |
if (err == ERROR_SUCCESS || err == ERROR_BROKEN_PIPE || err == ERROR_HANDLE_EOF) | |
break; | |
ERR_EXIT("ReadFile"); | |
} | |
if (nread == 0) | |
break; | |
output.AppendChar(ch); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
class CStringPipe { | |
public: | |
CStringPipe(); | |
virtual ~CStringPipe(); | |
virtual void Doit(CString cmdline, CStringA& input, CStringA& output); | |
virtual void InitSecAttr(); | |
virtual void CreatePipeForChildStdout(); | |
virtual void CreatePipeForChildStdin(); | |
virtual void CreateChildProcess(CString cmdline); | |
virtual void WriteToPipe(CStringA& input); | |
virtual void ReadFromPipe(CStringA& output); | |
private: | |
enum { | |
BUFSIZE = 4096 | |
}; | |
SECURITY_ATTRIBUTES m_sec_attr; | |
HANDLE m_child_stdin_rd = NULL; | |
HANDLE m_child_stdin_wr = NULL; | |
HANDLE m_child_stdout_rd = NULL; | |
HANDLE m_child_stdout_wr = NULL; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment