|  |  | @@ -63,6 +63,8 @@ namespace CodeDweller { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | void | 
		
	
		
			
			|  |  |  | Child::init() { | 
		
	
		
			
			|  |  |  | reader.exceptions(std::istream::failbit | std::istream::badbit); | 
		
	
		
			
			|  |  |  | writer.exceptions(std::ostream::failbit | std::ostream::badbit); | 
		
	
		
			
			|  |  |  | childStarted = false; | 
		
	
		
			
			|  |  |  | exitCodeObtainedFlag = false; | 
		
	
		
			
			|  |  |  | exitCode = 0; | 
		
	
	
		
			
			|  |  | @@ -77,112 +79,112 @@ namespace CodeDweller { | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Set the bInheritHandle flag so pipe handles are inherited. | 
		
	
		
			
			|  |  |  | SECURITY_ATTRIBUTES securityAttributes; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); | 
		
	
		
			
			|  |  |  | securityAttributes.bInheritHandle = true; | 
		
	
		
			
			|  |  |  | securityAttributes.lpSecurityDescriptor = NULL; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Create a pipe for the child process's STDOUT. | 
		
	
		
			
			|  |  |  | HANDLE childStdOutAtChild; | 
		
	
		
			
			|  |  |  | HANDLE childStdOutAtParent; | 
		
	
		
			
			|  |  |  | HANDLE childStdInAtChild; | 
		
	
		
			
			|  |  |  | HANDLE childStdInAtParent; | 
		
	
		
			
			|  |  |  | int bufferSize = 0; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (!CreatePipe(&childStdOutAtParent, | 
		
	
		
			
			|  |  |  | &childStdOutAtChild, | 
		
	
		
			
			|  |  |  | &securityAttributes, | 
		
	
		
			
			|  |  |  | bufferSize)) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error from CreatePipe for stdout:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Ensure the read handle to the pipe for STDOUT is not inherited. | 
		
	
		
			
			|  |  |  | int inheritFlag = 0; | 
		
	
		
			
			|  |  |  | if (!SetHandleInformation(childStdOutAtParent, | 
		
	
		
			
			|  |  |  | HANDLE_FLAG_INHERIT, | 
		
	
		
			
			|  |  |  | inheritFlag) ) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error from GetHandleInformation for stdout:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Create a pipe for the child process's STDIN. | 
		
	
		
			
			|  |  |  | if (! CreatePipe(&childStdInAtChild, | 
		
	
		
			
			|  |  |  | &childStdInAtParent, | 
		
	
		
			
			|  |  |  | SECURITY_ATTRIBUTES securityAttributes; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); | 
		
	
		
			
			|  |  |  | securityAttributes.bInheritHandle = true; | 
		
	
		
			
			|  |  |  | securityAttributes.lpSecurityDescriptor = NULL; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Create a pipe for the child process's STDOUT. | 
		
	
		
			
			|  |  |  | HANDLE childStdOutAtChild; | 
		
	
		
			
			|  |  |  | HANDLE childStdOutAtParent; | 
		
	
		
			
			|  |  |  | HANDLE childStdInAtChild; | 
		
	
		
			
			|  |  |  | HANDLE childStdInAtParent; | 
		
	
		
			
			|  |  |  | int bufferSize = 0; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (!CreatePipe(&childStdOutAtParent, | 
		
	
		
			
			|  |  |  | &childStdOutAtChild, | 
		
	
		
			
			|  |  |  | &securityAttributes, | 
		
	
		
			
			|  |  |  | bufferSize)) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error from CreatePipe for stdin:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Ensure the write handle to the pipe for STDIN is not inherited. | 
		
	
		
			
			|  |  |  | if (!SetHandleInformation(childStdInAtParent, | 
		
	
		
			
			|  |  |  | HANDLE_FLAG_INHERIT, | 
		
	
		
			
			|  |  |  | inheritFlag)) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error from GetHandleInformation for stdin:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error from CreatePipe for stdout:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Ensure the read handle to the pipe for STDOUT is not inherited. | 
		
	
		
			
			|  |  |  | int inheritFlag = 0; | 
		
	
		
			
			|  |  |  | if (!SetHandleInformation(childStdOutAtParent, | 
		
	
		
			
			|  |  |  | HANDLE_FLAG_INHERIT, | 
		
	
		
			
			|  |  |  | inheritFlag) ) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error from GetHandleInformation for stdout:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Create a pipe for the child process's STDIN. | 
		
	
		
			
			|  |  |  | if (! CreatePipe(&childStdInAtChild, | 
		
	
		
			
			|  |  |  | &childStdInAtParent, | 
		
	
		
			
			|  |  |  | &securityAttributes, | 
		
	
		
			
			|  |  |  | bufferSize)) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error from CreatePipe for stdin:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Ensure the write handle to the pipe for STDIN is not inherited. | 
		
	
		
			
			|  |  |  | if (!SetHandleInformation(childStdInAtParent, | 
		
	
		
			
			|  |  |  | HANDLE_FLAG_INHERIT, | 
		
	
		
			
			|  |  |  | inheritFlag)) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error from GetHandleInformation for stdin:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Set up members of the PROCESS_INFORMATION structure. | 
		
	
		
			
			|  |  |  | PROCESS_INFORMATION processInfo; | 
		
	
		
			
			|  |  |  | // Set up members of the PROCESS_INFORMATION structure. | 
		
	
		
			
			|  |  |  | PROCESS_INFORMATION processInfo; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | std::fill((char *) &processInfo, | 
		
	
		
			
			|  |  |  | ((char *) &processInfo) + sizeof(PROCESS_INFORMATION), | 
		
	
		
			
			|  |  |  | 0); | 
		
	
		
			
			|  |  |  | std::fill((char *) &processInfo, | 
		
	
		
			
			|  |  |  | ((char *) &processInfo) + sizeof(PROCESS_INFORMATION), | 
		
	
		
			
			|  |  |  | 0); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Set up members of the STARTUPINFO structure.  This structure | 
		
	
		
			
			|  |  |  | // specifies the STDIN and STDOUT handles for redirection. | 
		
	
		
			
			|  |  |  | STARTUPINFO startInfo; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | std::fill((char *) &startInfo, | 
		
	
		
			
			|  |  |  | ((char *) &startInfo) + sizeof(STARTUPINFO), | 
		
	
		
			
			|  |  |  | 0); | 
		
	
		
			
			|  |  |  | startInfo.cb = sizeof(STARTUPINFO); | 
		
	
		
			
			|  |  |  | startInfo.hStdError = childStdOutAtChild; | 
		
	
		
			
			|  |  |  | startInfo.hStdOutput = childStdOutAtChild; | 
		
	
		
			
			|  |  |  | startInfo.hStdInput = childStdInAtChild; | 
		
	
		
			
			|  |  |  | startInfo.dwFlags |= STARTF_USESTDHANDLES; | 
		
	
		
			
			|  |  |  | // Set up members of the STARTUPINFO structure.  This structure | 
		
	
		
			
			|  |  |  | // specifies the STDIN and STDOUT handles for redirection. | 
		
	
		
			
			|  |  |  | STARTUPINFO startInfo; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | std::fill((char *) &startInfo, | 
		
	
		
			
			|  |  |  | ((char *) &startInfo) + sizeof(STARTUPINFO), | 
		
	
		
			
			|  |  |  | 0); | 
		
	
		
			
			|  |  |  | startInfo.cb = sizeof(STARTUPINFO); | 
		
	
		
			
			|  |  |  | startInfo.hStdError = childStdOutAtChild; | 
		
	
		
			
			|  |  |  | startInfo.hStdOutput = childStdOutAtChild; | 
		
	
		
			
			|  |  |  | startInfo.hStdInput = childStdInAtChild; | 
		
	
		
			
			|  |  |  | startInfo.dwFlags |= STARTF_USESTDHANDLES; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Create the child process. | 
		
	
		
			
			|  |  |  | bool status; | 
		
	
		
			
			|  |  |  | // Create the child process. | 
		
	
		
			
			|  |  |  | bool status; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | status = CreateProcess(NULL, | 
		
	
		
			
			|  |  |  | (char *) cmdline.c_str(), // 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 | 
		
	
		
			
			|  |  |  | &startInfo,   	    // STARTUPINFO pointer | 
		
	
		
			
			|  |  |  | &processInfo);	    // receives PROCESS_INFORMATION | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // If an error occurs, exit the application. | 
		
	
		
			
			|  |  |  | if (!status ) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error from CreateProcess with " | 
		
	
		
			
			|  |  |  | "command line \"" + cmdline + "\":  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Provide the stream buffers with the handles for communicating | 
		
	
		
			
			|  |  |  | // with the child process. | 
		
	
		
			
			|  |  |  | readStreambuf.setInputHandle(childStdOutAtParent); | 
		
	
		
			
			|  |  |  | writeStreambuf.setOutputHandle(childStdInAtParent); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Save the handles to the child process and its primary thread. | 
		
	
		
			
			|  |  |  | childProcess = processInfo.hProcess; | 
		
	
		
			
			|  |  |  | childThread = processInfo.hThread; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | childStarted = true; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Close the child's end of the pipes. | 
		
	
		
			
			|  |  |  | if (!CloseHandle(childStdOutAtChild)) { | 
		
	
		
			
			|  |  |  | status = CreateProcess(NULL, | 
		
	
		
			
			|  |  |  | (char *) cmdline.c_str(), // 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 | 
		
	
		
			
			|  |  |  | &startInfo,   	    // STARTUPINFO pointer | 
		
	
		
			
			|  |  |  | &processInfo);	    // receives PROCESS_INFORMATION | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // If an error occurs, exit the application. | 
		
	
		
			
			|  |  |  | if (!status ) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error from CreateProcess with " | 
		
	
		
			
			|  |  |  | "command line \"" + cmdline + "\":  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Provide the stream buffers with the handles for communicating | 
		
	
		
			
			|  |  |  | // with the child process. | 
		
	
		
			
			|  |  |  | readStreambuf.setInputHandle(childStdOutAtParent); | 
		
	
		
			
			|  |  |  | writeStreambuf.setOutputHandle(childStdInAtParent); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Save the handles to the child process and its primary thread. | 
		
	
		
			
			|  |  |  | childProcess = processInfo.hProcess; | 
		
	
		
			
			|  |  |  | childThread = processInfo.hThread; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | childStarted = true; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Close the child's end of the pipes. | 
		
	
		
			
			|  |  |  | if (!CloseHandle(childStdOutAtChild)) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error closing the child process stdout handle:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (!CloseHandle(childStdInAtChild)) { | 
		
	
		
			
			|  |  |  | if (!CloseHandle(childStdInAtChild)) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error closing the child process stdin handle:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
	
		
			
			|  |  | @@ -199,38 +201,38 @@ namespace CodeDweller { | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (!TerminateProcess(childProcess, terminateExitCode)) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error terminating the child process:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error terminating the child process:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | bool | 
		
	
		
			
			|  |  |  | Child::isDone() { | 
		
	
		
			
			|  |  |  | bool | 
		
	
		
			
			|  |  |  | Child::isDone() { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (exitCodeObtainedFlag) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | return true; | 
		
	
		
			
			|  |  |  | return true; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (!childStarted) { | 
		
	
		
			
			|  |  |  | throw std::logic_error("Child process was not started " | 
		
	
		
			
			|  |  |  | "when isDone() was called"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | throw std::logic_error("Child process was not started " | 
		
	
		
			
			|  |  |  | "when isDone() was called"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | int result; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (!GetExitCodeProcess(childProcess, (LPDWORD) &result)) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error checking status of child process:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error checking status of child process:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (STILL_ACTIVE == result) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | return false; | 
		
	
		
			
			|  |  |  | return false; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Child process has exited.  Save the exit code. | 
		
	
		
			
			|  |  |  | exitCode = result; | 
		
	
	
		
			
			|  |  | @@ -240,32 +242,32 @@ namespace CodeDweller { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | int32_t | 
		
	
		
			
			|  |  |  | Child::result() { | 
		
	
		
			
			|  |  |  | int32_t | 
		
	
		
			
			|  |  |  | Child::result() { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (exitCodeObtainedFlag) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | return exitCode; | 
		
	
		
			
			|  |  |  | return exitCode; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (!childStarted) { | 
		
	
		
			
			|  |  |  | throw std::logic_error("Child process was not started " | 
		
	
		
			
			|  |  |  | "when result() was called"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | throw std::logic_error("Child process was not started " | 
		
	
		
			
			|  |  |  | "when result() was called"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | int result; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (!GetExitCodeProcess(childProcess, (LPDWORD) &result)) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error getting child process exit code:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error getting child process exit code:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Error if the process has not exited. | 
		
	
		
			
			|  |  |  | if (STILL_ACTIVE == result) { | 
		
	
		
			
			|  |  |  | throw std::logic_error("Child process was active when " | 
		
	
		
			
			|  |  |  | "result() was called"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | throw std::logic_error("Child process was active when " | 
		
	
		
			
			|  |  |  | "result() was called"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Child process has exited.  Save the exit code. | 
		
	
		
			
			|  |  |  | exitCode = result; | 
		
	
	
		
			
			|  |  | @@ -274,21 +276,21 @@ namespace CodeDweller { | 
		
	
		
			
			|  |  |  | return result; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | std::string | 
		
	
		
			
			|  |  |  | Child::getErrorText() { | 
		
	
		
			
			|  |  |  | std::string | 
		
	
		
			
			|  |  |  | Child::getErrorText() { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | LPVOID winMsgBuf; | 
		
	
		
			
			|  |  |  | DWORD lastError = GetLastError(); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | FormatMessage( | 
		
	
		
			
			|  |  |  | FORMAT_MESSAGE_ALLOCATE_BUFFER | | 
		
	
		
			
			|  |  |  | FORMAT_MESSAGE_FROM_SYSTEM | | 
		
	
		
			
			|  |  |  | FORMAT_MESSAGE_IGNORE_INSERTS, | 
		
	
		
			
			|  |  |  | NULL, | 
		
	
		
			
			|  |  |  | lastError, | 
		
	
		
			
			|  |  |  | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | 
		
	
		
			
			|  |  |  | (char *) &winMsgBuf, | 
		
	
		
			
			|  |  |  | 0, NULL ); | 
		
	
		
			
			|  |  |  | FORMAT_MESSAGE_ALLOCATE_BUFFER | | 
		
	
		
			
			|  |  |  | FORMAT_MESSAGE_FROM_SYSTEM | | 
		
	
		
			
			|  |  |  | FORMAT_MESSAGE_IGNORE_INSERTS, | 
		
	
		
			
			|  |  |  | NULL, | 
		
	
		
			
			|  |  |  | lastError, | 
		
	
		
			
			|  |  |  | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | 
		
	
		
			
			|  |  |  | (char *) &winMsgBuf, | 
		
	
		
			
			|  |  |  | 0, NULL ); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | std::string errMsg((char *) winMsgBuf); | 
		
	
		
			
			|  |  |  |  | 
		
	
	
		
			
			|  |  | @@ -296,9 +298,9 @@ namespace CodeDweller { | 
		
	
		
			
			|  |  |  | return errMsg; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | Child::ReadStreambuf::ReadStreambuf(std::size_t bufferSize) : | 
		
	
		
			
			|  |  |  | inputHandle(0), | 
		
	
		
			
			|  |  |  | buffer(bufferSize + 1) { | 
		
	
		
			
			|  |  |  | Child::ReadStreambuf::ReadStreambuf(std::size_t bufferSize) : | 
		
	
		
			
			|  |  |  | inputHandle(0), | 
		
	
		
			
			|  |  |  | buffer(bufferSize + 1) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | char *end = &(buffer.front()) + buffer.size(); | 
		
	
		
			
			|  |  |  |  | 
		
	
	
		
			
			|  |  | @@ -307,23 +309,23 @@ namespace CodeDweller { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | void | 
		
	
		
			
			|  |  |  | Child::ReadStreambuf::setInputHandle(HANDLE inHandle) { | 
		
	
		
			
			|  |  |  | void | 
		
	
		
			
			|  |  |  | Child::ReadStreambuf::setInputHandle(HANDLE inHandle) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | inputHandle = inHandle; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | std::streambuf::int_type | 
		
	
		
			
			|  |  |  | Child::ReadStreambuf::underflow() { | 
		
	
		
			
			|  |  |  | std::streambuf::int_type | 
		
	
		
			
			|  |  |  | Child::ReadStreambuf::underflow() { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Check for empty buffer. | 
		
	
		
			
			|  |  |  | if (gptr() < egptr()) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Not empty. | 
		
	
		
			
			|  |  |  | return traits_type::to_int_type(*gptr()); | 
		
	
		
			
			|  |  |  | // Not empty. | 
		
	
		
			
			|  |  |  | return traits_type::to_int_type(*gptr()); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Need to fill the buffer. | 
		
	
		
			
			|  |  |  | char *base = &(buffer.front()); | 
		
	
	
		
			
			|  |  | @@ -332,25 +334,26 @@ namespace CodeDweller { | 
		
	
		
			
			|  |  |  | // Check whether this is the first fill. | 
		
	
		
			
			|  |  |  | if (eback() == base) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Not the first fill.  Copy putback characters. | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | // Not the first fill.  Copy one putback character. | 
		
	
		
			
			|  |  |  | *(eback()) = *(egptr() - 1); | 
		
	
		
			
			|  |  |  | start++; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // start points to the start of the buffer.  Fill buffer. | 
		
	
		
			
			|  |  |  | DWORD nBytesRead; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (!ReadFile(inputHandle, | 
		
	
		
			
			|  |  |  | start, | 
		
	
		
			
			|  |  |  | buffer.size() - (start - base), | 
		
	
		
			
			|  |  |  | &nBytesRead, | 
		
	
		
			
			|  |  |  | NULL)) { | 
		
	
		
			
			|  |  |  | return traits_type::eof(); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | start, | 
		
	
		
			
			|  |  |  | buffer.size() - (start - base), | 
		
	
		
			
			|  |  |  | &nBytesRead, | 
		
	
		
			
			|  |  |  | NULL)) { | 
		
	
		
			
			|  |  |  | return traits_type::eof(); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Check for EOF. | 
		
	
		
			
			|  |  |  | if (0 == nBytesRead) { | 
		
	
		
			
			|  |  |  | return traits_type::eof(); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | return traits_type::eof(); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Update buffer pointers. | 
		
	
		
			
			|  |  |  | setg(base, start, start + nBytesRead); | 
		
	
	
		
			
			|  |  | @@ -359,9 +362,9 @@ namespace CodeDweller { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | Child::WriteStreambuf::WriteStreambuf(std::size_t bufferSize) : | 
		
	
		
			
			|  |  |  | outputHandle(0), | 
		
	
		
			
			|  |  |  | buffer(bufferSize + 1) { | 
		
	
		
			
			|  |  |  | Child::WriteStreambuf::WriteStreambuf(std::size_t bufferSize) : | 
		
	
		
			
			|  |  |  | outputHandle(0), | 
		
	
		
			
			|  |  |  | buffer(bufferSize + 1) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | char *base = &(buffer.front()); | 
		
	
		
			
			|  |  |  |  | 
		
	
	
		
			
			|  |  | @@ -370,63 +373,69 @@ namespace CodeDweller { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | void | 
		
	
		
			
			|  |  |  | Child::WriteStreambuf::setOutputHandle(HANDLE outHandle) { | 
		
	
		
			
			|  |  |  | void | 
		
	
		
			
			|  |  |  | Child::WriteStreambuf::setOutputHandle(HANDLE outHandle) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | outputHandle = outHandle; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | void | 
		
	
		
			
			|  |  |  | Child::WriteStreambuf::flushBuffer() { | 
		
	
		
			
			|  |  |  | void | 
		
	
		
			
			|  |  |  | Child::WriteStreambuf::flushBuffer() { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Write. | 
		
	
		
			
			|  |  |  | std::ptrdiff_t nBytes = pptr() - pbase(); | 
		
	
		
			
			|  |  |  | DWORD nBytesWritten; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (!WriteFile(outputHandle, | 
		
	
		
			
			|  |  |  | pbase(), | 
		
	
		
			
			|  |  |  | nBytes, | 
		
	
		
			
			|  |  |  | &nBytesWritten, | 
		
	
		
			
			|  |  |  | NULL)) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error writing to child process:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | pbase(), | 
		
	
		
			
			|  |  |  | nBytes, | 
		
	
		
			
			|  |  |  | &nBytesWritten, | 
		
	
		
			
			|  |  |  | NULL)) { | 
		
	
		
			
			|  |  |  | pbump(epptr() - pptr()); // Indicate failure. | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Error writing to child process:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | if (nBytes != nBytesWritten) { | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Not all data was written to to child process:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | pbump(epptr() - pptr()); // Indicate failure. | 
		
	
		
			
			|  |  |  | throw std::runtime_error("Not all data was written to to child process:  " + | 
		
	
		
			
			|  |  |  | getErrorText()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | pbump(-nBytes); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | return; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | std::streambuf::int_type | 
		
	
		
			
			|  |  |  | Child::WriteStreambuf::overflow(int_type ch) { | 
		
	
		
			
			|  |  |  | std::streambuf::int_type | 
		
	
		
			
			|  |  |  | Child::WriteStreambuf::overflow(int_type ch) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Check whether we're writing EOF. | 
		
	
		
			
			|  |  |  | if (traits_type::eof() != ch) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Not writing EOF. | 
		
	
		
			
			|  |  |  | *(pptr()) = ch; | 
		
	
		
			
			|  |  |  | pbump(1); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | // Not writing EOF. | 
		
	
		
			
			|  |  |  | *(pptr()) = ch; | 
		
	
		
			
			|  |  |  | pbump(1); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Write. | 
		
	
		
			
			|  |  |  | flushBuffer(); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Success. | 
		
	
		
			
			|  |  |  | return traits_type::not_eof('a'); | 
		
	
		
			
			|  |  |  | return ch; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | int | 
		
	
		
			
			|  |  |  | Child::WriteStreambuf::sync() { | 
		
	
		
			
			|  |  |  | return traits_type::eof(); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | flushBuffer(); | 
		
	
		
			
			|  |  |  | return 1; // Success. | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | int | 
		
	
		
			
			|  |  |  | Child::WriteStreambuf::sync() { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | flushBuffer(); // Throws exception on failure. | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Success. | 
		
	
		
			
			|  |  |  | return 1; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  |