source: main/trunk/greenstone2/runtime-src/src/recpt/os_process_windows.cpp@ 24226

Last change on this file since 24226 was 22188, checked in by davidb, 14 years ago

Some refinement of the testing framework for the os_process class

  • Property svn:executable set to *
File size: 7.4 KB
RevLine 
[22173]1/**********************************************************************
2 *
3 * os_process_windows.c -- Windows version of osprocess. See os_process.h
4 * for more details
5 *
6 * Copyright (C) 2010 The New Zealand Digital Library Project
7 *
8 * A component of the Greenstone digital library software
9 * from the New Zealand Digital Library Project at the
10 * University of Waikato, New Zealand.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 *********************************************************************/
27
28#ifdef __WIN32__
29
30#if defined(GSDL_USE_OBJECTSPACE)
31# include <ospace/std/iostream>
32#elif defined(GSDL_USE_IOS_H)
33# include <iostream.h>
34#else
35# include <iostream>
36using namespace std;
37#endif
38
[22188]39#include "text_t.h"
[22173]40#include "os_process_windows.h"
41
42
[22183]43osprocesswindows::osprocesswindows(OSProcessPipeMode mode,
[22188]44 char* prog_name, char* argv[],
[22183]45 char* envp[])
[22173]46 : child_stdout_read_(NULL), child_stdin_write_(NULL),
[22183]47 osprocess(mode,prog_name,argv,envp)
[22173]48{
49 HANDLE child_stdin_read = NULL;
50 HANDLE child_stdout_write = NULL;
51
52 SECURITY_ATTRIBUTES saAttr;
53 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
54 saAttr.bInheritHandle = TRUE;
55 saAttr.lpSecurityDescriptor = NULL;
56
57 // Create a pipe for the child process's STDOUT.
58 if (!CreatePipe(&child_stdout_read_, &child_stdout_write, &saAttr, 0)) {
59 cerr << "osprocesswindows::osprocesswindows(): Failed to create stdout pipe for child process" << endl;
60 }
61
62 // Ensure the read handle to the pipe for STDOUT is not inherited.
63 if (!SetHandleInformation(child_stdout_read_, HANDLE_FLAG_INHERIT, 0)) {
64 cerr << "osprocesswindows::osprocesswindows(): Failed to set handle information for stdout pipe for child process" << endl;
65 }
66
67 // Create a pipe for the child process's STDIN.
68 if (!CreatePipe(&child_stdin_read, &child_stdin_write_, &saAttr, 0)) {
69 cerr << "osprocesswindows::osprocesswindows(): Failed to create stdin pipe for child process" << endl;
70 }
71
72 // Ensure the write handle to the pipe for STDIN is not inherited.
73 if (!SetHandleInformation(child_stdin_write_, HANDLE_FLAG_INHERIT, 0)) {
74 cerr << "osprocesswindows::osprocesswindows(): Failed to set handle information for stdin pipe for child process" << endl;
75 }
76
77 STARTUPINFOA si;
78 memset(&si, 0, sizeof(si));
79 memset(&pi_, 0, sizeof(pi_));
80
81 si.cb = sizeof(si);
82
83 // These two lines help prevent a DOS window popping up
84 // when the process is created
85 si.dwFlags |= STARTF_USESHOWWINDOW;
86 si.wShowWindow = SW_HIDE;
87
88 si.dwFlags |= STARTF_USESTDHANDLES;
[22188]89
[22173]90
[22188]91 // any error messages in the child process goes to same place as parent
[22173]92 // e.g. in the case of running as a CGI script, the Web server error log
93 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
94
[22188]95 if ((mode==uniRead) || (mode==biReadWrite)) {
96 // Output from the child process comes to the parent process, down the
97 // OUT pipe
98 si.hStdOutput = child_stdout_write;
99 }
100 else {
101 // uniWrite
102 // Output from the chlid process goes to the same place as parent
103 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
104 }
[22173]105
[22188]106 if ((mode==uniWrite) || (mode==biReadWrite)) {
107 // Input to the child process can be sent from the parent process, down the
108 // In pipe
109 si.hStdInput = child_stdin_read;
110 }
111 else {
112 // uniRead
113
114 // Input to the child process comes from same place as parent ?!?
115 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
116 }
[22173]117
[22188]118 text_t cmd_line = prog_name;
[22183]119 if (argv != NULL) {
[22188]120 int i=1;
[22183]121 while (argv[i] != NULL) {
[22188]122 cmd_line += " \"";
123 cmd_line += argv[i];
124 cmd_line += "\"";
[22183]125 i++;
126 }
127 }
128
129 char* cmd_line_cstr = cmd_line.getcstr();
130
[22173]131 int rv = CreateProcess(NULL, // no application name
[22183]132 cmd_line_cstr,
[22173]133 NULL,
134 NULL, // no process or thread security attribues
135 TRUE, // Inherit handles
136 0, // Creation flag
137 NULL, // No environment block
138 ".", // current working directory
139 &si,
140 &pi_); // process info filled out as a result
[22183]141
142 delete [] cmd_line_cstr;
143
[22173]144 if (!rv) {
[22183]145 cerr << "os_process_windows(): Error creating child process" << endl;
[22173]146 }
147
148 // close the handles that aren't used by the parent process
149
150 if (!CloseHandle(child_stdout_write)) {
[22183]151 cerr << "os_process_windows(): Error closing child's StdOut Write Handle" << endl;
[22173]152 }
153
154 if (!CloseHandle(child_stdin_read)) {
[22183]155 cerr << "os_process_windows(): Error closing child's StdIn Read Handle" << endl;
[22173]156 }
157}
158
159
160osprocesswindows::~osprocesswindows()
161{
[22177]162 // close any file handles that are still open
163 close();
164
[22173]165 // Close process and thread handles
166 CloseHandle( pi_.hProcess );
167 pi_.hProcess = NULL;
168
169 CloseHandle( pi_.hThread );
170 pi_.hThread = NULL;
171}
172
173
174
[22188]175int osprocesswindows::write(char* buffer, const int buffer_len)
[22173]176{
177 DWORD actual_write_len;
178
179 bool write_ok
180 = WriteFile(child_stdin_write_, buffer, buffer_len, &actual_write_len, NULL);
181 if (!write_ok) {
182 cerr << "osproesswindows::write() Error: failed to write data" << endl;
183 }
184 return actual_write_len;
185}
186
187
188int osprocesswindows::read(char* buffer, const int buffer_len)
189{
190 DWORD actual_read_len;
191
192 bool read_ok
193 = ReadFile(child_stdout_read_, buffer, buffer_len, &actual_read_len, NULL);
194 if (!read_ok) {
195 cerr << "osproesswindows::read() Error: failed to read data" << endl;
196 }
197
198 return actual_read_len;
199}
200
201
[22183]202void osprocesswindows::wait()
203{
204 WaitForSingleObject(pi_.hProcess, INFINITE);
205}
[22173]206
[22177]207
[22188]208bool osprocesswindows::close_write_pipe(OSProcessWarnStatus warn_status)
[22173]209{
[22177]210 bool write_close_ok = true;
[22173]211
[22188]212 if (child_stdin_write_ != NULL) {
[22177]213
214 write_close_ok = CloseHandle(child_stdin_write_);
215
216 if (write_close_ok) {
217 child_stdin_write_ = NULL;
218 }
219 else {
220 // not OK
221 cerr << "osprocesswindows::close(): Error - Failed to close stdin write handle on pipe to child process" << endl;
222 }
[22173]223 }
[22188]224 else if (warn_status == withWarning) {
[22177]225 cerr << "osprocesswindows::close_write_pipe(): Warning - Tried to close already closed pipe" << endl;
226 }
[22173]227
[22177]228 return write_close_ok;
[22173]229}
230
231
[22188]232bool osprocesswindows::close_read_pipe(OSProcessWarnStatus warn_status)
[22173]233{
[22177]234 bool read_close_ok = true;
[22173]235
[22177]236 if (child_stdout_read_ != NULL) {
237
238 read_close_ok = CloseHandle(child_stdout_read_);
239
240 if (read_close_ok) {
241 child_stdout_read_ = NULL;
242 }
243 else {
244 cerr << "osprocesswindows::close(): Error - Failed to close handle stdout read on pipe to chlild process" << endl;
245 }
246 }
247 else if (warn_status == withWarning) {
248 cerr << "osprocesswindows::close_read_pipe(): Warning - Tried to close already closed pipe" << endl;
249 }
250
251 return read_close_ok;
252}
[22173]253
254
255
256
257
258
259
260
261#endif
Note: See TracBrowser for help on using the repository browser.