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

Last change on this file since 28760 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
Line 
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
39#include "text_t.h"
40#include "os_process_windows.h"
41
42
43osprocesswindows::osprocesswindows(OSProcessPipeMode mode,
44 char* prog_name, char* argv[],
45 char* envp[])
46 : child_stdout_read_(NULL), child_stdin_write_(NULL),
47 osprocess(mode,prog_name,argv,envp)
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;
89
90
91 // any error messages in the child process goes to same place as parent
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
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 }
105
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 }
117
118 text_t cmd_line = prog_name;
119 if (argv != NULL) {
120 int i=1;
121 while (argv[i] != NULL) {
122 cmd_line += " \"";
123 cmd_line += argv[i];
124 cmd_line += "\"";
125 i++;
126 }
127 }
128
129 char* cmd_line_cstr = cmd_line.getcstr();
130
131 int rv = CreateProcess(NULL, // no application name
132 cmd_line_cstr,
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
141
142 delete [] cmd_line_cstr;
143
144 if (!rv) {
145 cerr << "os_process_windows(): Error creating child process" << endl;
146 }
147
148 // close the handles that aren't used by the parent process
149
150 if (!CloseHandle(child_stdout_write)) {
151 cerr << "os_process_windows(): Error closing child's StdOut Write Handle" << endl;
152 }
153
154 if (!CloseHandle(child_stdin_read)) {
155 cerr << "os_process_windows(): Error closing child's StdIn Read Handle" << endl;
156 }
157}
158
159
160osprocesswindows::~osprocesswindows()
161{
162 // close any file handles that are still open
163 close();
164
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
175int osprocesswindows::write(char* buffer, const int buffer_len)
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
202void osprocesswindows::wait()
203{
204 WaitForSingleObject(pi_.hProcess, INFINITE);
205}
206
207
208bool osprocesswindows::close_write_pipe(OSProcessWarnStatus warn_status)
209{
210 bool write_close_ok = true;
211
212 if (child_stdin_write_ != NULL) {
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 }
223 }
224 else if (warn_status == withWarning) {
225 cerr << "osprocesswindows::close_write_pipe(): Warning - Tried to close already closed pipe" << endl;
226 }
227
228 return write_close_ok;
229}
230
231
232bool osprocesswindows::close_read_pipe(OSProcessWarnStatus warn_status)
233{
234 bool read_close_ok = true;
235
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}
253
254
255
256
257
258
259
260
261#endif
Note: See TracBrowser for help on using the repository browser.