/********************************************************************** * * os_process_windows.c -- Windows version of osprocess. See os_process.h * for more details * * Copyright (C) 2010 The New Zealand Digital Library Project * * A component of the Greenstone digital library software * from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *********************************************************************/ #ifdef __WIN32__ #if defined(GSDL_USE_OBJECTSPACE) # include #elif defined(GSDL_USE_IOS_H) # include #else # include using namespace std; #endif #include "os_process_windows.h" //#include osprocesswindows::osprocesswindows(char* cmdline) : osprocess(cmdline) {} osprocesswindows::osprocesswindows(char* cmdline, OSProcessPipeMode mode) : child_stdout_read_(NULL), child_stdin_write_(NULL), osprocess(cmdline,mode) { HANDLE child_stdin_read = NULL; HANDLE child_stdout_write = NULL; SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // Create a pipe for the child process's STDOUT. if (!CreatePipe(&child_stdout_read_, &child_stdout_write, &saAttr, 0)) { cerr << "osprocesswindows::osprocesswindows(): Failed to create stdout pipe for child process" << endl; } // Ensure the read handle to the pipe for STDOUT is not inherited. if (!SetHandleInformation(child_stdout_read_, HANDLE_FLAG_INHERIT, 0)) { cerr << "osprocesswindows::osprocesswindows(): Failed to set handle information for stdout pipe for child process" << endl; } // Create a pipe for the child process's STDIN. if (!CreatePipe(&child_stdin_read, &child_stdin_write_, &saAttr, 0)) { cerr << "osprocesswindows::osprocesswindows(): Failed to create stdin pipe for child process" << endl; } // Ensure the write handle to the pipe for STDIN is not inherited. if (!SetHandleInformation(child_stdin_write_, HANDLE_FLAG_INHERIT, 0)) { cerr << "osprocesswindows::osprocesswindows(): Failed to set handle information for stdin pipe for child process" << endl; } STARTUPINFOA si; memset(&si, 0, sizeof(si)); memset(&pi_, 0, sizeof(pi_)); si.cb = sizeof(si); // These two lines help prevent a DOS window popping up // when the process is created si.dwFlags |= STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; si.dwFlags |= STARTF_USESTDHANDLES; // any error messages in child process to to same place as parent process // e.g. in the case of running as a CGI script, the Web server error log si.hStdError = GetStdHandle(STD_ERROR_HANDLE); // Output from the child process comes to the parent process, down the // OUT pipe si.hStdOutput = child_stdout_write; // Input to the child process can be sent from the parent process, down the // In pipe si.hStdInput = child_stdin_read; int rv = CreateProcess(NULL, // no application name cmdline, NULL, NULL, // no process or thread security attribues TRUE, // Inherit handles 0, // Creation flag NULL, // No environment block ".", // current working directory &si, &pi_); // process info filled out as a result if (!rv) { cerr << "os_process_windows(): Error creating process" << endl; } // close the handles that aren't used by the parent process if (!CloseHandle(child_stdout_write)) { cerr << "os_process_windows(): Error closing StdOutWr Handle" << endl; } if (!CloseHandle(child_stdin_read)) { cerr << "os_process_windows(): Error closing StdInRd Handle" << endl; } } osprocesswindows::~osprocesswindows() { // Close process and thread handles CloseHandle( pi_.hProcess ); pi_.hProcess = NULL; CloseHandle( pi_.hThread ); pi_.hThread = NULL; } /* bool osprocesswindows::eop() { } bool osprocesswindows::eop(OSProcessPipeMode) { } */ int osprocesswindows::write(const char* buffer, const int buffer_len) { DWORD actual_write_len; bool write_ok = WriteFile(child_stdin_write_, buffer, buffer_len, &actual_write_len, NULL); if (!write_ok) { cerr << "osproesswindows::write() Error: failed to write data" << endl; } return actual_write_len; } int osprocesswindows::read(char* buffer, const int buffer_len) { DWORD actual_read_len; bool read_ok = ReadFile(child_stdout_read_, buffer, buffer_len, &actual_read_len, NULL); if (!read_ok) { cerr << "osproesswindows::read() Error: failed to read data" << endl; } return actual_read_len; } bool osprocesswindows::close() { return true; } bool osprocesswindows::close(OSProcessPipeMode mode) { // Close the pipe handle so the child process stops reading. if (!CloseHandle(child_stdin_write_)) { cerr << "osprocesswindows::close(): Failed to close stdin write handle on pipe to child process" << endl; return false; } if (!CloseHandle(child_stdout_read_)) { cerr << "osprocesswindows::close(): Failed to close handle stdout read on pipe to chlild process" << endl; return false; } return true; } //#ifdef TEST_OS_PROCESS_WINDOWS #if 0 int main () { char* input_line = NULL; char* prog_name = "c:\\Windows\\system32\\java.exe"; char* cmd_line = "java"; //char* input_line = "echo hi there\n"; //char* prog_name = "c:\\cygwin\\bin\\cat.exe"; //char* cmd_line = "cat"; osprocesswindows osprocess(cmd_line,uniRead); printf("Content-type: text/html\n\n"); printf( "\n"); printf( " \n"); printf( " Testing\n"); printf( " \n"); printf( " \n"); const int BufferSize = 1024; char buffer[BufferSize]; int bytes_read = 0; do { bytes_read = osprocess.read(buffer,BufferSize); if (bytes_read>0) { fwrite(buffer,1,bytes_read,stdout); } } while (bytes_read==BufferSize); printf( " \n"); printf( "\n"); return 0; } #endif #endif