home *** CD-ROM | disk | FTP | other *** search
/ Programming Win32 Under the API / ProgrammingWin32UnderTheApiPatVillani.iso / Chapter7 / 7-3 / parent.c < prev    next >
C/C++ Source or Header  |  2000-09-10  |  6KB  |  218 lines

  1. //
  2. // Copyright (c) 2000
  3. // Pasquale J. Villani
  4. // All Rights reserved
  5. //
  6. // This is our parent process.  It reads data from standard input,
  7. // flips characters in the buffer from upper case to lower case and vice versa,
  8. // then write the buffer out.
  9. //
  10.  
  11. #include <windows.h>
  12.  
  13. #define BUFSIZE 4096
  14.  
  15. #ifndef SUCCESS
  16. # define SUCCESS 0
  17. #endif
  18. #ifndef FAILURE
  19. # define FAILURE 1
  20. #endif
  21.  
  22. HANDLE    hChildStdinRd,
  23.     hChildStdinWr,
  24.     hChildStdinWrDup,
  25.     hChildStdoutRd,
  26.     hChildStdoutWr,
  27.     hChildStdoutRdDup,
  28.     hInputFile,
  29.     hSaveStdin,
  30.     hSaveStdout;
  31.  
  32. BOOL SpawnChildProcess(CHAR *szChildName);
  33. VOID WriteToPipe(VOID);
  34. VOID ReadFromPipe(VOID);
  35. VOID ErrorExit(LPTSTR);
  36. VOID ErrMsg(LPTSTR, BOOL);
  37.  
  38. int main(int argc, char *argv[])
  39. {
  40.     SECURITY_ATTRIBUTES saAttr;
  41.     BOOL fSuccess;
  42.  
  43.     // First, create the child process.  
  44.     if (!SpawnChildProcess("reverse"))
  45.         ErrorExit("Create process failed");
  46.  
  47.     // Get a handle to the parent's input file.
  48.     if (argc > 1) 
  49.           hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL,
  50.                OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
  51.     else
  52.         hInputFile = hSaveStdin;
  53.  
  54.     if (hInputFile == INVALID_HANDLE_VALUE)
  55.         ErrorExit("no input file\n");
  56.  
  57.     // Write to pipe that is the standard input for a child process.  
  58.     WriteToPipe();
  59.  
  60.     // Read from pipe that is the standard output for child process.  
  61.     ReadFromPipe();
  62.  
  63.     return 0;
  64. }
  65.  
  66.  
  67. BOOL SpawnChildProcess(CHAR *szChildName)
  68. {
  69.     PROCESS_INFORMATION piProcInfo;
  70.     STARTUPINFO siStartInfo;
  71.     BOOL bRetVal;
  72.     SECURITY_ATTRIBUTES saAttr;
  73.     BOOL fSuccess;
  74.  
  75.     // Set the bInheritHandle flag so pipe handles are inherited.
  76.     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
  77.     saAttr.bInheritHandle = TRUE;
  78.     saAttr.lpSecurityDescriptor = NULL;
  79.  
  80.     // The steps for redirecting child process's STDOUT: 
  81.     //     1. Save current STDOUT, to be restored later. 
  82.     //     2. Create anonymous pipe to be STDOUT for child process. 
  83.     //     3. Set STDOUT of the parent process to be write handle of 
  84.     //        the pipe, so it is inherited by the child process. 
  85.     //     4. Create a noninheritable duplicate of the read handle and
  86.     //        close the inheritable read handle.  
  87.     // Save the handle to the current STDOUT.  
  88.     hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
  89.  
  90.     // Create a pipe for the child process's STDOUT.  
  91.     if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
  92.         ErrorExit("Stdout pipe creation failed\n");
  93.  
  94.     // Set a write handle to the pipe to be STDOUT.  
  95.     if (!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr))
  96.         ErrorExit("Redirecting STDOUT failed");
  97.  
  98.     // Create noninheritable read handle and close the inheritable read // handle. 
  99.     fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
  100.                GetCurrentProcess(), &hChildStdoutRdDup, 0, FALSE,
  101.                    DUPLICATE_SAME_ACCESS);
  102.     if (!fSuccess)
  103.         ErrorExit("DuplicateHandle failed");
  104.  
  105.     CloseHandle(hChildStdoutRd);
  106.  
  107.     // The steps for redirecting child process's STDIN: 
  108.     //     1.  Save current STDIN, to be restored later. 
  109.     //     2.  Create anonymous pipe to be STDIN for child process. 
  110.     //     3.  Set STDIN of the parent to be the read handle of the 
  111.     //         pipe, so it is inherited by the child process. 
  112.     //     4.  Create a noninheritable duplicate of the write handle, 
  113.     //         and close the inheritable write handle.  
  114.     // Save the handle to the current STDIN.  
  115.     hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
  116.  
  117.     // Create a pipe for the child process's STDIN.  
  118.     if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
  119.         ErrorExit("Stdin pipe creation failed\n");
  120.  
  121.     // Set a read handle to the pipe to be STDIN.  
  122.     if (!SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd))
  123.         ErrorExit("Redirecting Stdin failed");
  124.  
  125.     // Duplicate the write handle to the pipe so it is not inherited.  
  126.     fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
  127.                 GetCurrentProcess(), &hChildStdinWrDup, 0,
  128.                 FALSE,    // not inherited
  129.                 DUPLICATE_SAME_ACCESS);
  130.     if (!fSuccess)
  131.         ErrorExit("DuplicateHandle failed");
  132.  
  133.     CloseHandle(hChildStdinWr);
  134.  
  135.     // Set up members of STARTUPINFO structure.  
  136.     ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
  137.     siStartInfo.cb = sizeof(STARTUPINFO);    // Create the child process.  
  138.     bRetVal = CreateProcess(NULL,
  139.         szChildName,    // command line 
  140.         NULL,        // process security attributes 
  141.         NULL,        // primary thread security attributes 
  142.         TRUE,        // handles are inherited 
  143.         0,        // creation flags 
  144.         NULL,        // use parent's environment 
  145.         NULL,        // use parent's current directory 
  146.         &siStartInfo,    // STARTUPINFO pointer 
  147.         &piProcInfo);    // receives PROCESS_INFORMATION
  148.  
  149.     // After process creation, restore the saved STDIN and STDOUT.  
  150.     if (!SetStdHandle(STD_INPUT_HANDLE, hSaveStdin))
  151.         ErrorExit("Re-redirecting Stdin failed\n");
  152.     
  153.     if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout))
  154.         ErrorExit("Re-redirecting Stdout failed\n");
  155.  
  156.     return bRetVal;
  157. }
  158.  
  159. VOID WriteToPipe(VOID)
  160.     DWORD dwRead, dwWritten;
  161.     CHAR chBuf[BUFSIZE];
  162.  
  163.     // Read from a file and write its contents to a pipe.
  164.     for (;;)
  165.     { 
  166.         if (!ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) ||
  167.             dwRead == 0)
  168.                 break;
  169.         if (!WriteFile(hChildStdinWrDup, chBuf, dwRead,
  170.            &dwWritten, NULL))
  171.             break;
  172.     }
  173.  
  174.  
  175.     // Close the pipe handle so the child process stops reading.  
  176.     if (!CloseHandle(hChildStdinWrDup))
  177.         ErrorExit("Close pipe failed\n");
  178. }
  179.  
  180.  
  181. VOID ReadFromPipe(VOID)
  182. {
  183.     DWORD dwRead, dwWritten;
  184.     CHAR chBuf[BUFSIZE];
  185.     HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
  186.  
  187.     // Close the write end of the pipe before reading from the 
  188.     // read end of the pipe.
  189.     if (!CloseHandle(hChildStdoutWr)) 
  190.         ErrorExit("Closing handle failed");
  191.  
  192.     // Read output from the child process, and write to parent's STDOUT.  
  193.     for (;;)
  194.     {
  195.         if (!ReadFile(hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead,
  196.           NULL) || dwRead == 0)
  197.             break;
  198.         if (!WriteFile(hSaveStdout, chBuf, dwRead, &dwWritten, NULL))
  199.             break;
  200.     }
  201. }
  202.  
  203.  
  204. // Print an error message and abort.
  205. VOID ErrorExit(LPTSTR lpszMessage)
  206. {
  207.     DWORD dwCnt, dwWritten;
  208.     CHAR szString[BUFSIZE];
  209.     HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
  210.  
  211.     dwCnt = wsprintf(szString, "%s\n", lpszMessage);
  212.     WriteFile(hStderr, szString, dwCnt, &dwWritten, NULL);
  213.     ExitProcess(FAILURE);
  214. }
  215.  
  216.  
  217.