home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Win32 Under the API
/
ProgrammingWin32UnderTheApiPatVillani.iso
/
Chapter7
/
7-3
/
parent.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-09-10
|
6KB
|
218 lines
//
// Copyright (c) 2000
// Pasquale J. Villani
// All Rights reserved
//
// This is our parent process. It reads data from standard input,
// flips characters in the buffer from upper case to lower case and vice versa,
// then write the buffer out.
//
#include <windows.h>
#define BUFSIZE 4096
#ifndef SUCCESS
# define SUCCESS 0
#endif
#ifndef FAILURE
# define FAILURE 1
#endif
HANDLE hChildStdinRd,
hChildStdinWr,
hChildStdinWrDup,
hChildStdoutRd,
hChildStdoutWr,
hChildStdoutRdDup,
hInputFile,
hSaveStdin,
hSaveStdout;
BOOL SpawnChildProcess(CHAR *szChildName);
VOID WriteToPipe(VOID);
VOID ReadFromPipe(VOID);
VOID ErrorExit(LPTSTR);
VOID ErrMsg(LPTSTR, BOOL);
int main(int argc, char *argv[])
{
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;
// First, create the child process.
if (!SpawnChildProcess("reverse"))
ErrorExit("Create process failed");
// Get a handle to the parent's input file.
if (argc > 1)
hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
else
hInputFile = hSaveStdin;
if (hInputFile == INVALID_HANDLE_VALUE)
ErrorExit("no input file\n");
// Write to pipe that is the standard input for a child process.
WriteToPipe();
// Read from pipe that is the standard output for child process.
ReadFromPipe();
return 0;
}
BOOL SpawnChildProcess(CHAR *szChildName)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bRetVal;
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// The steps for redirecting child process's STDOUT:
// 1. Save current STDOUT, to be restored later.
// 2. Create anonymous pipe to be STDOUT for child process.
// 3. Set STDOUT of the parent process to be write handle of
// the pipe, so it is inherited by the child process.
// 4. Create a noninheritable duplicate of the read handle and
// close the inheritable read handle.
// Save the handle to the current STDOUT.
hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Create a pipe for the child process's STDOUT.
if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
ErrorExit("Stdout pipe creation failed\n");
// Set a write handle to the pipe to be STDOUT.
if (!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr))
ErrorExit("Redirecting STDOUT failed");
// Create noninheritable read handle and close the inheritable read // handle.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup, 0, FALSE,
DUPLICATE_SAME_ACCESS);
if (!fSuccess)
ErrorExit("DuplicateHandle failed");
CloseHandle(hChildStdoutRd);
// The steps for redirecting child process's STDIN:
// 1. Save current STDIN, to be restored later.
// 2. Create anonymous pipe to be STDIN for child process.
// 3. Set STDIN of the parent to be the read handle of the
// pipe, so it is inherited by the child process.
// 4. Create a noninheritable duplicate of the write handle,
// and close the inheritable write handle.
// Save the handle to the current STDIN.
hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
// Create a pipe for the child process's STDIN.
if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
ErrorExit("Stdin pipe creation failed\n");
// Set a read handle to the pipe to be STDIN.
if (!SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd))
ErrorExit("Redirecting Stdin failed");
// Duplicate the write handle to the pipe so it is not inherited.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup, 0,
FALSE, // not inherited
DUPLICATE_SAME_ACCESS);
if (!fSuccess)
ErrorExit("DuplicateHandle failed");
CloseHandle(hChildStdinWr);
// Set up members of STARTUPINFO structure.
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO); // Create the child process.
bRetVal = CreateProcess(NULL,
szChildName, // 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
// After process creation, restore the saved STDIN and STDOUT.
if (!SetStdHandle(STD_INPUT_HANDLE, hSaveStdin))
ErrorExit("Re-redirecting Stdin failed\n");
if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout))
ErrorExit("Re-redirecting Stdout failed\n");
return bRetVal;
}
VOID WriteToPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
// Read from a file and write its contents to a pipe.
for (;;)
{
if (!ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) ||
dwRead == 0)
break;
if (!WriteFile(hChildStdinWrDup, chBuf, dwRead,
&dwWritten, NULL))
break;
}
// Close the pipe handle so the child process stops reading.
if (!CloseHandle(hChildStdinWrDup))
ErrorExit("Close pipe failed\n");
}
VOID ReadFromPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Close the write end of the pipe before reading from the
// read end of the pipe.
if (!CloseHandle(hChildStdoutWr))
ErrorExit("Closing handle failed");
// Read output from the child process, and write to parent's STDOUT.
for (;;)
{
if (!ReadFile(hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead,
NULL) || dwRead == 0)
break;
if (!WriteFile(hSaveStdout, chBuf, dwRead, &dwWritten, NULL))
break;
}
}
// Print an error message and abort.
VOID ErrorExit(LPTSTR lpszMessage)
{
DWORD dwCnt, dwWritten;
CHAR szString[BUFSIZE];
HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
dwCnt = wsprintf(szString, "%s\n", lpszMessage);
WriteFile(hStderr, szString, dwCnt, &dwWritten, NULL);
ExitProcess(FAILURE);
}