Created
May 20, 2015 21:04
-
-
Save scytacki/fca2bd7568abb1b003f9 to your computer and use it in GitHub Desktop.
ConsoleApp.cpp
This file contains hidden or 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
// ConsoleApplication2.cpp : Defines the entry point for the console application. | |
// | |
#include <windows.h> | |
#include <tchar.h> | |
#include <stdio.h> | |
#include <strsafe.h> | |
#define BUFSIZE 4096 | |
HANDLE g_hChildStd_OUT_Rd = NULL; | |
HANDLE g_hChildStd_OUT_Wr = NULL; | |
HANDLE g_hInputFile = NULL; | |
HANDLE CreateChildProcess(void); | |
void ReadFromPipe(void); | |
void ErrorExit(PTSTR); | |
int _tmain(int argc, TCHAR *argv[]) | |
{ | |
SECURITY_ATTRIBUTES saAttr; | |
HANDLE hProcess; | |
printf("\n->Start of parent execution.\n"); | |
// Set the bInheritHandle flag so pipe handles are inherited. | |
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); | |
saAttr.bInheritHandle = TRUE; | |
saAttr.lpSecurityDescriptor = NULL; | |
// Create a pipe for the child process's STDOUT. | |
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) | |
ErrorExit(TEXT("StdoutRd CreatePipe")); | |
// Ensure the read handle to the pipe for STDOUT is not inherited. | |
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) | |
ErrorExit(TEXT("Stdout SetHandleInformation")); | |
// Create the child process. | |
hProcess = CreateChildProcess(); | |
// Read from pipe that is the standard output for child process. | |
printf("\n->Contents of child process STDOUT:\n\n", argv[1]); | |
ReadFromPipe(); | |
// Close handles to the child process and its primary thread. | |
// Some applications might keep these handles to monitor the status | |
// of the child process, for example. | |
WaitForSingleObject(hProcess, INFINITE); | |
printf("ChildExitCode: %d\n", GetLastError()); | |
CloseHandle(hProcess); | |
// TODO figure out how to handle this | |
// CloseHandle(piProcInfo.hThread); | |
printf("\n->End of parent execution.\n"); | |
// The remaining open handles are cleaned up when this process terminates. | |
// To avoid resource leaks in a larger application, close handles explicitly. | |
return 0; | |
} | |
HANDLE CreateChildProcess() | |
// Create a child process that uses the previously created pipes for STDIN and STDOUT. | |
{ | |
TCHAR szCmdline[] = TEXT("child"); | |
PROCESS_INFORMATION piProcInfo; | |
STARTUPINFO siStartInfo; | |
BOOL bSuccess = FALSE; | |
// Set up members of the PROCESS_INFORMATION structure. | |
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); | |
// Set up members of the STARTUPINFO structure. | |
// This structure specifies the STDIN and STDOUT handles for redirection. | |
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); | |
siStartInfo.cb = sizeof(STARTUPINFO); | |
siStartInfo.hStdError = g_hChildStd_OUT_Wr; | |
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; | |
siStartInfo.dwFlags |= STARTF_USESTDHANDLES; | |
// Create the child process. | |
bSuccess = CreateProcess(NULL, | |
szCmdline, // command line | |
NULL, // process security attributes | |
NULL, // primary thread security attributes | |
TRUE, // handles are inherited | |
0, // creation flags | |
NULL, // use parent's environment | |
NULL, // use parent's current directory | |
&siStartInfo, // STARTUPINFO pointer | |
&piProcInfo); // receives PROCESS_INFORMATION | |
// If an error occurs, exit the application. | |
if (!bSuccess) { | |
ErrorExit(TEXT("CreateProcess")); | |
return 0; | |
} | |
else | |
{ | |
return piProcInfo.hProcess; | |
} | |
} | |
void ReadFromPipe(void) | |
// Read output from the child process's pipe for STDOUT | |
// and write to the parent process's pipe for STDOUT. | |
// Stop when there is no more data. | |
{ | |
DWORD dwRead, dwWritten; | |
CHAR chBuf[BUFSIZE]; | |
BOOL bSuccess = FALSE; | |
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE); | |
for (;;) | |
{ | |
bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL); | |
printf("\nFinished ReadFile\n"); | |
if (!bSuccess || dwRead == 0) { | |
printf("\nReadFile return 0 bytes or !bSuccess\n"); | |
break; | |
} | |
bSuccess = WriteFile(hParentStdOut, chBuf, | |
dwRead, &dwWritten, NULL); | |
if (!bSuccess) break; | |
if (chBuf[0] == 'D' && chBuf[1] == 'o' && chBuf[2] == 'n' && chBuf[3] == 'e') { | |
break; | |
} | |
} | |
} | |
void ErrorExit(PTSTR lpszFunction) | |
// Format a readable error message, display a message box, | |
// and exit from the application. | |
{ | |
LPVOID lpMsgBuf; | |
LPVOID lpDisplayBuf; | |
DWORD dw = GetLastError(); | |
FormatMessage( | |
FORMAT_MESSAGE_ALLOCATE_BUFFER | | |
FORMAT_MESSAGE_FROM_SYSTEM | | |
FORMAT_MESSAGE_IGNORE_INSERTS, | |
NULL, | |
dw, | |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | |
(LPTSTR)&lpMsgBuf, | |
0, NULL); | |
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, | |
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40)*sizeof(TCHAR)); | |
StringCchPrintf((LPTSTR)lpDisplayBuf, | |
LocalSize(lpDisplayBuf) / sizeof(TCHAR), | |
TEXT("%s failed with error %d: %s"), | |
lpszFunction, dw, lpMsgBuf); | |
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); | |
LocalFree(lpMsgBuf); | |
LocalFree(lpDisplayBuf); | |
ExitProcess(1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment