Advertisement
Guest User

Creating a Child Process with Redirected Input and Output

a guest
Feb 21st, 2019
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.99 KB | None | 0 0
  1. #include <windows.h>
  2. #include <tchar.h>
  3. #include <stdio.h>
  4. #include <strsafe.h>
  5.  
  6. #define BUFSIZE 4096
  7.  
  8. HANDLE g_hChildStd_IN_Rd = NULL;
  9. HANDLE g_hChildStd_IN_Wr = NULL;
  10. HANDLE g_hChildStd_OUT_Rd = NULL;
  11. HANDLE g_hChildStd_OUT_Wr = NULL;
  12.  
  13. char *dataToWrite = "ip config";
  14.  
  15. void CreateChildProcess(void);
  16. void WriteToPipe(void);
  17. void ReadFromPipe(void);
  18. void ErrorExit(PTSTR);
  19.  
  20. int main(int argc, char *argv[])
  21. {
  22.    SECURITY_ATTRIBUTES saAttr;
  23.  
  24.    printf("\n->Start of parent execution.\n");
  25.  
  26. // Set the bInheritHandle flag so pipe handles are inherited.
  27.  
  28.    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
  29.    saAttr.bInheritHandle = TRUE;
  30.    saAttr.lpSecurityDescriptor = NULL;
  31.  
  32. // Create a pipe for the child process's STDOUT.
  33.  
  34.    if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) )
  35.       ErrorExit(TEXT("StdoutRd CreatePipe"));
  36.  
  37. // Ensure the read handle to the pipe for STDOUT is not inherited.
  38.  
  39.    if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
  40.       ErrorExit(TEXT("Stdout SetHandleInformation"));
  41.  
  42. // Create a pipe for the child process's STDIN.
  43.  
  44.    if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
  45.       ErrorExit(TEXT("Stdin CreatePipe"));
  46.  
  47. // Ensure the write handle to the pipe for STDIN is not inherited.
  48.  
  49.    if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
  50.       ErrorExit(TEXT("Stdin SetHandleInformation"));
  51.  
  52. // Create the child process.
  53.  
  54.    CreateChildProcess();
  55.  
  56. // Write to the pipe that is the standard input for a child process.
  57. // Data is written to the pipe's buffers, so it is not necessary to wait
  58. // until the child process is running before writing data.
  59.  
  60.    WriteToPipe();
  61.    printf( "\n->Contents of %s written to child STDIN pipe.\n", dataToWrite);
  62.  
  63.    // Read from pipe that is the standard output for child process.
  64.  
  65.    printf( "\n->Contents of child process STDOUT:\n\n", dataToWrite);
  66.    ReadFromPipe();
  67.  
  68.    printf("\n->End of parent execution.\n");
  69.  
  70. // The remaining open handles are cleaned up when this process terminates.
  71. // To avoid resource leaks in a larger application, close handles explicitly.
  72.  
  73.    return 0;
  74. }
  75.  
  76. void CreateChildProcess()
  77. // Create a child process that uses the previously created pipes for STDIN and STDOUT.
  78. {
  79.    TCHAR szCmdline[]=TEXT("cmd");
  80.    PROCESS_INFORMATION piProcInfo;
  81.    STARTUPINFOA siStartInfo;
  82.    BOOL bSuccess = FALSE;
  83.  
  84. // Set up members of the PROCESS_INFORMATION structure.
  85.  
  86.    ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
  87.  
  88. // Set up members of the STARTUPINFO structure.
  89. // This structure specifies the STDIN and STDOUT handles for redirection.
  90.  
  91.    ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
  92.    siStartInfo.cb = sizeof(STARTUPINFO);
  93.    siStartInfo.hStdError = g_hChildStd_OUT_Wr;
  94.    siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
  95.    siStartInfo.hStdInput = g_hChildStd_IN_Rd;
  96.    siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
  97.  
  98. // Create the child process.
  99. /*
  100.    bSuccess = CreateProcess(NULL,
  101.       szCmdline,     // command line
  102.       NULL,          // process security attributes
  103.       NULL,          // primary thread security attributes
  104.       TRUE,          // handles are inherited
  105.       0,             // creation flags
  106.       NULL,          // use parent's environment
  107.       NULL,          // use parent's current directory
  108.       &siStartInfo,  // STARTUPINFO pointer
  109.       &piProcInfo);  // receives PROCESS_INFORMATION
  110.    */
  111.  
  112.    char cmd_exe[32767];
  113.    GetEnvironmentVariableA("COMSPEC", cmd_exe, 32767);
  114.    bSuccess = CreateProcessA(cmd_exe, (char *)"\k", NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &siStartInfo, &piProcInfo);
  115.  
  116.  
  117.    // If an error occurs, exit the application.
  118.    if ( ! bSuccess )
  119.       ErrorExit(TEXT("CreateProcess"));
  120.    else
  121.    {
  122.       // Close handles to the child process and its primary thread.
  123.       // Some applications might keep these handles to monitor the status
  124.       // of the child process, for example.
  125.  
  126.       CloseHandle(piProcInfo.hProcess);
  127.       CloseHandle(piProcInfo.hThread);
  128.    }
  129. }
  130.  
  131. void WriteToPipe(void)
  132.  
  133. // Read from a file and write its contents to the pipe for the child's STDIN.
  134. // Stop when there is no more data.
  135. {
  136.    DWORD dwRead, dwWritten;
  137.  
  138.    WriteFile(g_hChildStd_IN_Wr, dataToWrite, dwRead, &dwWritten, NULL);
  139.  
  140. // Close the pipe handle so the child process stops reading.
  141.  
  142.    if ( ! CloseHandle(g_hChildStd_IN_Wr) )
  143.       ErrorExit(TEXT("StdInWr CloseHandle"));
  144. }
  145.  
  146. void ReadFromPipe(void)
  147.  
  148. // Read output from the child process's pipe for STDOUT
  149. // and write to the parent process's pipe for STDOUT.
  150. // Stop when there is no more data.
  151. {
  152.    DWORD dwRead, dwWritten;
  153.    CHAR chBuf[BUFSIZE];
  154.    BOOL bSuccess = FALSE;
  155.    HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  156.  
  157.    for (;;)
  158.    {
  159.       bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
  160.       if( ! bSuccess || dwRead == 0 ) break;
  161.  
  162.       bSuccess = WriteFile(hParentStdOut, chBuf,
  163.                            dwRead, &dwWritten, NULL);
  164.       if (! bSuccess ) break;
  165.    }
  166. }
  167.  
  168. void ErrorExit(PTSTR lpszFunction)
  169.  
  170. // Format a readable error message, display a message box,
  171. // and exit from the application.
  172. {
  173.     LPVOID lpMsgBuf;
  174.     LPVOID lpDisplayBuf;
  175.     DWORD dw = GetLastError();
  176.  
  177.     FormatMessage(
  178.         FORMAT_MESSAGE_ALLOCATE_BUFFER |
  179.         FORMAT_MESSAGE_FROM_SYSTEM |
  180.         FORMAT_MESSAGE_IGNORE_INSERTS,
  181.         NULL,
  182.         dw,
  183.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  184.         (LPTSTR) &lpMsgBuf,
  185.         0, NULL );
  186.  
  187.     lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
  188.         (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
  189.     StringCchPrintf((LPTSTR)lpDisplayBuf,
  190.         LocalSize(lpDisplayBuf) / sizeof(TCHAR),
  191.         TEXT("%s failed with error %d: %s"),
  192.         lpszFunction, dw, lpMsgBuf);
  193.     MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
  194.  
  195.     LocalFree(lpMsgBuf);
  196.     LocalFree(lpDisplayBuf);
  197.     ExitProcess(1);
  198. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement