187d2adbcSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
387d2adbcSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
487d2adbcSAndrew Rist * or more contributor license agreements. See the NOTICE file
587d2adbcSAndrew Rist * distributed with this work for additional information
687d2adbcSAndrew Rist * regarding copyright ownership. The ASF licenses this file
787d2adbcSAndrew Rist * to you under the Apache License, Version 2.0 (the
887d2adbcSAndrew Rist * "License"); you may not use this file except in compliance
987d2adbcSAndrew Rist * with the License. You may obtain a copy of the License at
1087d2adbcSAndrew Rist *
1187d2adbcSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
1287d2adbcSAndrew Rist *
1387d2adbcSAndrew Rist * Unless required by applicable law or agreed to in writing,
1487d2adbcSAndrew Rist * software distributed under the License is distributed on an
1587d2adbcSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1687d2adbcSAndrew Rist * KIND, either express or implied. See the License for the
1787d2adbcSAndrew Rist * specific language governing permissions and limitations
1887d2adbcSAndrew Rist * under the License.
1987d2adbcSAndrew Rist *
2087d2adbcSAndrew Rist *************************************************************/
2187d2adbcSAndrew Rist
2287d2adbcSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sal.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #define UNICODE
28cdf0e10cSrcweir #define _UNICODE
29cdf0e10cSrcweir
30cdf0e10cSrcweir #ifndef WIN32_LEAN_AND_MEAN
31cdf0e10cSrcweir # define WIN32_LEAN_AND_MEAN
32cdf0e10cSrcweir # ifdef _MSC_VER
33cdf0e10cSrcweir # pragma warning(push,1) /* disable warnings within system headers */
34cdf0e10cSrcweir # endif
35cdf0e10cSrcweir # include <windows.h>
36cdf0e10cSrcweir # ifdef _MSC_VER
37cdf0e10cSrcweir # pragma warning(pop)
38cdf0e10cSrcweir # endif
39cdf0e10cSrcweir # include <tchar.h>
40cdf0e10cSrcweir # undef WIN32_LEAN_AND_MEAN
41cdf0e10cSrcweir #endif
42cdf0e10cSrcweir #include "procimpl.h"
43cdf0e10cSrcweir #include <rtl/ustring.hxx>
44cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
45cdf0e10cSrcweir #include "secimpl.h"
46cdf0e10cSrcweir #include <osl/file.hxx>
47cdf0e10cSrcweir
48cdf0e10cSrcweir #include <list>
49cdf0e10cSrcweir #include <vector>
50cdf0e10cSrcweir #include <algorithm>
51cdf0e10cSrcweir #include <string>
52cdf0e10cSrcweir
53cdf0e10cSrcweir //#################################################
54cdf0e10cSrcweir extern "C" oslFileHandle SAL_CALL osl_createFileHandleFromOSHandle( HANDLE hFile, sal_uInt32 uFlags );
55cdf0e10cSrcweir
56cdf0e10cSrcweir //#################################################
57cdf0e10cSrcweir const sal_Unicode NAME_VALUE_SEPARATOR = TEXT('=');
58cdf0e10cSrcweir const sal_Char* SPACE = " ";
59cdf0e10cSrcweir const rtl::OUString ENV_COMSPEC = rtl::OUString::createFromAscii("COMSPEC");
60cdf0e10cSrcweir const rtl::OUString QUOTE = rtl::OUString::createFromAscii("\"");
61cdf0e10cSrcweir
62cdf0e10cSrcweir namespace /* private */
63cdf0e10cSrcweir {
64cdf0e10cSrcweir //#################################################
65*22076bf1SHerbert Dürr typedef std::list<rtl::OUString> string_container_t;
66cdf0e10cSrcweir typedef string_container_t::iterator string_container_iterator_t;
67cdf0e10cSrcweir typedef string_container_t::const_iterator string_container_const_iterator_t;
68cdf0e10cSrcweir typedef std::pair<string_container_iterator_t, string_container_iterator_t> iterator_pair_t;
69*22076bf1SHerbert Dürr typedef std::vector<sal_Unicode > environment_container_t;
70cdf0e10cSrcweir
71cdf0e10cSrcweir //#################################################
72cdf0e10cSrcweir /* Function object that compares two strings that are
73cdf0e10cSrcweir expected to be environment variables in the form
74cdf0e10cSrcweir "name=value". Only the 'name' part will be compared.
75cdf0e10cSrcweir The comparison is in upper case and returns true
76cdf0e10cSrcweir if the first of both strings is less than the
77cdf0e10cSrcweir second one. */
78cdf0e10cSrcweir struct less_environment_variable :
79cdf0e10cSrcweir public std::binary_function<rtl::OUString, rtl::OUString, bool>
80cdf0e10cSrcweir {
operator ()__anona70d8a550111::less_environment_variable81cdf0e10cSrcweir bool operator() (const rtl::OUString& lhs, const rtl::OUString& rhs) const
82cdf0e10cSrcweir {
83cdf0e10cSrcweir OSL_ENSURE((lhs.indexOf(NAME_VALUE_SEPARATOR) > -1) && \
84cdf0e10cSrcweir (rhs.indexOf(NAME_VALUE_SEPARATOR) > -1), \
85cdf0e10cSrcweir "Malformed environment variable");
86cdf0e10cSrcweir
87cdf0e10cSrcweir // Windows compares environment variables uppercase
88cdf0e10cSrcweir // so we do it, too
89cdf0e10cSrcweir return (rtl_ustr_compare_WithLength(
90cdf0e10cSrcweir lhs.toAsciiUpperCase().pData->buffer,
91cdf0e10cSrcweir lhs.indexOf(NAME_VALUE_SEPARATOR),
92cdf0e10cSrcweir rhs.toAsciiUpperCase().pData->buffer,
93cdf0e10cSrcweir rhs.indexOf(NAME_VALUE_SEPARATOR)) < 0);
94cdf0e10cSrcweir }
95cdf0e10cSrcweir };
96cdf0e10cSrcweir
97cdf0e10cSrcweir //#################################################
98cdf0e10cSrcweir /* Function object used by for_each algorithm to
99cdf0e10cSrcweir calculate the sum of the length of all strings
100cdf0e10cSrcweir in a string container. */
101cdf0e10cSrcweir class sum_of_string_lengths
102cdf0e10cSrcweir {
103cdf0e10cSrcweir public:
104cdf0e10cSrcweir //--------------------------------
sum_of_string_lengths()105cdf0e10cSrcweir sum_of_string_lengths() : sum_(0) {}
106cdf0e10cSrcweir
107cdf0e10cSrcweir //--------------------------------
operator ()(const rtl::OUString & string)108cdf0e10cSrcweir void operator() (const rtl::OUString& string)
109cdf0e10cSrcweir {
110cdf0e10cSrcweir OSL_ASSERT(string.getLength());
111cdf0e10cSrcweir
112cdf0e10cSrcweir // always include the terminating '\0'
113cdf0e10cSrcweir if (string.getLength())
114cdf0e10cSrcweir sum_ += string.getLength() + 1;
115cdf0e10cSrcweir }
116cdf0e10cSrcweir
117cdf0e10cSrcweir //--------------------------------
operator size_t() const118cdf0e10cSrcweir operator size_t () const
119cdf0e10cSrcweir {
120cdf0e10cSrcweir return sum_;
121cdf0e10cSrcweir }
122cdf0e10cSrcweir private:
123cdf0e10cSrcweir size_t sum_;
124cdf0e10cSrcweir };
125cdf0e10cSrcweir
126cdf0e10cSrcweir //#################################################
calc_sum_of_string_lengths(const string_container_t & string_cont)127cdf0e10cSrcweir inline size_t calc_sum_of_string_lengths(const string_container_t& string_cont)
128cdf0e10cSrcweir {
129cdf0e10cSrcweir return std::for_each(
130cdf0e10cSrcweir string_cont.begin(), string_cont.end(), sum_of_string_lengths());
131cdf0e10cSrcweir }
132cdf0e10cSrcweir
133cdf0e10cSrcweir //#################################################
read_environment(string_container_t * environment)134cdf0e10cSrcweir void read_environment(/*out*/ string_container_t* environment)
135cdf0e10cSrcweir {
136cdf0e10cSrcweir // GetEnvironmentStrings returns a sorted list, Windows
137cdf0e10cSrcweir // sorts environment variables upper case
138cdf0e10cSrcweir LPTSTR env = reinterpret_cast<LPTSTR>(GetEnvironmentStrings());
139cdf0e10cSrcweir LPTSTR p = env;
140cdf0e10cSrcweir
141cdf0e10cSrcweir while (size_t l = _tcslen(p))
142cdf0e10cSrcweir {
143cdf0e10cSrcweir environment->push_back(reinterpret_cast<const sal_Unicode*>(p));
144cdf0e10cSrcweir p += l + 1;
145cdf0e10cSrcweir }
146cdf0e10cSrcweir FreeEnvironmentStrings(env);
147cdf0e10cSrcweir }
148cdf0e10cSrcweir
149cdf0e10cSrcweir //#################################################
150cdf0e10cSrcweir /* the environment list must be sorted, new values
151cdf0e10cSrcweir should either replace existing ones or should be
152cdf0e10cSrcweir added to the list, environment variables will
153cdf0e10cSrcweir be handled case-insensitive */
create_merged_environment(rtl_uString * env_vars[],sal_uInt32 env_vars_count,string_container_t * merged_env)154cdf0e10cSrcweir bool create_merged_environment(
155cdf0e10cSrcweir rtl_uString* env_vars[],
156cdf0e10cSrcweir sal_uInt32 env_vars_count,
157cdf0e10cSrcweir /*in|out*/ string_container_t* merged_env)
158cdf0e10cSrcweir {
159cdf0e10cSrcweir OSL_ASSERT(env_vars && env_vars_count > 0 && merged_env);
160cdf0e10cSrcweir
161cdf0e10cSrcweir read_environment(merged_env);
162cdf0e10cSrcweir
163cdf0e10cSrcweir for (sal_uInt32 i = 0; i < env_vars_count; i++)
164cdf0e10cSrcweir {
165cdf0e10cSrcweir rtl::OUString env_var = rtl::OUString(env_vars[i]);
166cdf0e10cSrcweir
167cdf0e10cSrcweir if (env_var.getLength() == 0)
168cdf0e10cSrcweir return false;
169cdf0e10cSrcweir
170cdf0e10cSrcweir iterator_pair_t iter_pair = std::equal_range(
171cdf0e10cSrcweir merged_env->begin(),
172cdf0e10cSrcweir merged_env->end(),
173cdf0e10cSrcweir env_var,
174cdf0e10cSrcweir less_environment_variable());
175cdf0e10cSrcweir
176cdf0e10cSrcweir if (env_var.indexOf(NAME_VALUE_SEPARATOR) == -1)
177cdf0e10cSrcweir {
178cdf0e10cSrcweir merged_env->erase(iter_pair.first, iter_pair.second);
179cdf0e10cSrcweir }
180cdf0e10cSrcweir else
181cdf0e10cSrcweir {
182cdf0e10cSrcweir if (iter_pair.first != iter_pair.second) // found
183cdf0e10cSrcweir *iter_pair.first = env_var;
184cdf0e10cSrcweir else // not found
185cdf0e10cSrcweir merged_env->insert(iter_pair.first, env_var);
186cdf0e10cSrcweir }
187cdf0e10cSrcweir }
188cdf0e10cSrcweir return true;
189cdf0e10cSrcweir }
190cdf0e10cSrcweir
191cdf0e10cSrcweir //#################################################
192cdf0e10cSrcweir /* Create a merged environment */
setup_process_environment(rtl_uString * environment_vars[],sal_uInt32 n_environment_vars,environment_container_t & environment)193cdf0e10cSrcweir bool setup_process_environment(
194cdf0e10cSrcweir rtl_uString* environment_vars[],
195cdf0e10cSrcweir sal_uInt32 n_environment_vars,
196cdf0e10cSrcweir /*in|out*/ environment_container_t& environment)
197cdf0e10cSrcweir {
198cdf0e10cSrcweir string_container_t merged_env;
199cdf0e10cSrcweir if (!create_merged_environment(environment_vars, n_environment_vars, &merged_env))
200cdf0e10cSrcweir return false;
201cdf0e10cSrcweir
202cdf0e10cSrcweir // allocate enough space for the '\0'-separated environment strings and
203cdf0e10cSrcweir // a final '\0'
204cdf0e10cSrcweir environment.resize(calc_sum_of_string_lengths(merged_env) + 1);
205cdf0e10cSrcweir
206cdf0e10cSrcweir string_container_const_iterator_t iter = merged_env.begin();
207cdf0e10cSrcweir string_container_const_iterator_t iter_end = merged_env.end();
208cdf0e10cSrcweir
209cdf0e10cSrcweir sal_uInt32 pos = 0;
210cdf0e10cSrcweir for (/**/; iter != iter_end; ++iter)
211cdf0e10cSrcweir {
212cdf0e10cSrcweir rtl::OUString envv = *iter;
213cdf0e10cSrcweir
214cdf0e10cSrcweir OSL_ASSERT(envv.getLength());
215cdf0e10cSrcweir
216cdf0e10cSrcweir sal_uInt32 n = envv.getLength() + 1; // copy the final '\0', too
217cdf0e10cSrcweir rtl_copyMemory(
218cdf0e10cSrcweir reinterpret_cast<void*>(&environment[pos]),
219cdf0e10cSrcweir reinterpret_cast<const void*>(envv.getStr()),
220cdf0e10cSrcweir n * sizeof(sal_Unicode));
221cdf0e10cSrcweir pos += n;
222cdf0e10cSrcweir }
223cdf0e10cSrcweir environment[pos] = 0; // append a final '\0'
224cdf0e10cSrcweir
225cdf0e10cSrcweir return true;
226cdf0e10cSrcweir }
227cdf0e10cSrcweir
228cdf0e10cSrcweir //##########################################################
229cdf0e10cSrcweir /* In contrast to the Win32 API function CreatePipe with
230cdf0e10cSrcweir this function the caller is able to determine separately
231cdf0e10cSrcweir which handle of the pipe is inheritable. */
create_pipe(PHANDLE p_read_pipe,bool b_read_pipe_inheritable,PHANDLE p_write_pipe,bool b_write_pipe_inheritable,LPVOID p_security_descriptor=NULL,DWORD pipe_size=0)232cdf0e10cSrcweir bool create_pipe(
233cdf0e10cSrcweir PHANDLE p_read_pipe,
234cdf0e10cSrcweir bool b_read_pipe_inheritable,
235cdf0e10cSrcweir PHANDLE p_write_pipe,
236cdf0e10cSrcweir bool b_write_pipe_inheritable,
237cdf0e10cSrcweir LPVOID p_security_descriptor = NULL,
238cdf0e10cSrcweir DWORD pipe_size = 0)
239cdf0e10cSrcweir {
240cdf0e10cSrcweir SECURITY_ATTRIBUTES sa;
241cdf0e10cSrcweir sa.nLength = sizeof(SECURITY_ATTRIBUTES);
242cdf0e10cSrcweir sa.lpSecurityDescriptor = p_security_descriptor;
243cdf0e10cSrcweir sa.bInheritHandle = b_read_pipe_inheritable || b_write_pipe_inheritable;
244cdf0e10cSrcweir
245cdf0e10cSrcweir BOOL bRet = FALSE;
246cdf0e10cSrcweir HANDLE hTemp = NULL;
247cdf0e10cSrcweir
248cdf0e10cSrcweir if (!b_read_pipe_inheritable && b_write_pipe_inheritable)
249cdf0e10cSrcweir {
250cdf0e10cSrcweir bRet = CreatePipe(&hTemp, p_write_pipe, &sa, pipe_size);
251cdf0e10cSrcweir
252cdf0e10cSrcweir if (bRet && !DuplicateHandle(GetCurrentProcess(), hTemp,
253cdf0e10cSrcweir GetCurrentProcess(), p_read_pipe, 0, FALSE,
254cdf0e10cSrcweir DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
255cdf0e10cSrcweir {
256cdf0e10cSrcweir CloseHandle(hTemp);
257cdf0e10cSrcweir CloseHandle(*p_read_pipe);
258cdf0e10cSrcweir return false;
259cdf0e10cSrcweir }
260cdf0e10cSrcweir }
261cdf0e10cSrcweir else if (b_read_pipe_inheritable && !b_write_pipe_inheritable)
262cdf0e10cSrcweir {
263cdf0e10cSrcweir bRet = CreatePipe(p_read_pipe, &hTemp, &sa, pipe_size);
264cdf0e10cSrcweir
265cdf0e10cSrcweir if (bRet && !DuplicateHandle(GetCurrentProcess(), hTemp,
266cdf0e10cSrcweir GetCurrentProcess(), p_write_pipe, 0, FALSE,
267cdf0e10cSrcweir DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
268cdf0e10cSrcweir {
269cdf0e10cSrcweir CloseHandle(hTemp);
270cdf0e10cSrcweir CloseHandle(*p_write_pipe);
271cdf0e10cSrcweir return false;
272cdf0e10cSrcweir }
273cdf0e10cSrcweir }
274cdf0e10cSrcweir else
275cdf0e10cSrcweir {
276cdf0e10cSrcweir bRet = CreatePipe(p_read_pipe, p_write_pipe, &sa, pipe_size);
277cdf0e10cSrcweir }
278cdf0e10cSrcweir return bRet;
279cdf0e10cSrcweir }
280cdf0e10cSrcweir
281cdf0e10cSrcweir //#########################################################
282cdf0e10cSrcweir // Add a quote sign to the start and the end of a string
283cdf0e10cSrcweir // if not already present
quote_string(const rtl::OUString & string)284cdf0e10cSrcweir rtl::OUString quote_string(const rtl::OUString& string)
285cdf0e10cSrcweir {
286cdf0e10cSrcweir rtl::OUStringBuffer quoted;
287cdf0e10cSrcweir if (string.indexOf(QUOTE) != 0)
288cdf0e10cSrcweir quoted.append(QUOTE);
289cdf0e10cSrcweir
290cdf0e10cSrcweir quoted.append(string);
291cdf0e10cSrcweir
292cdf0e10cSrcweir if (string.lastIndexOf(QUOTE) != (string.getLength() - 1))
293cdf0e10cSrcweir quoted.append(QUOTE);
294cdf0e10cSrcweir
295cdf0e10cSrcweir return quoted.makeStringAndClear();
296cdf0e10cSrcweir }
297cdf0e10cSrcweir
298cdf0e10cSrcweir //The parameter path must be a system path. If it is longer than 260 characters
299cdf0e10cSrcweir //then it is shortened using the GetShortPathName function. This function only
300cdf0e10cSrcweir //works if the path exists. Because "path" can be the path to an executable, it
301cdf0e10cSrcweir //may not have the file extension ".exe". However, if the file on disk has the
302cdf0e10cSrcweir //".exe" extension, then the function will fail. In this case a second attempt
303cdf0e10cSrcweir //is started by adding the parameter "extension" to "path".
getShortPath(rtl::OUString const & path,rtl::OUString const & extension)304cdf0e10cSrcweir rtl::OUString getShortPath(rtl::OUString const & path, rtl::OUString const & extension)
305cdf0e10cSrcweir {
306cdf0e10cSrcweir rtl::OUString ret(path);
307cdf0e10cSrcweir if (path.getLength() > 260)
308cdf0e10cSrcweir {
309*22076bf1SHerbert Dürr std::vector<sal_Unicode> vec(path.getLength() + 1);
310cdf0e10cSrcweir //GetShortPathNameW only works if the file can be found!
311cdf0e10cSrcweir const DWORD len = GetShortPathNameW(
312cdf0e10cSrcweir reinterpret_cast<LPCWSTR>(path.getStr()), reinterpret_cast<LPWSTR>(&vec[0]), path.getLength() + 1);
313cdf0e10cSrcweir
314cdf0e10cSrcweir if (!len && GetLastError() == ERROR_FILE_NOT_FOUND
315cdf0e10cSrcweir && extension.getLength())
316cdf0e10cSrcweir {
317cdf0e10cSrcweir const rtl::OUString extPath(path + extension);
318*22076bf1SHerbert Dürr std::vector<sal_Unicode > vec2( extPath.getLength() + 1);
319cdf0e10cSrcweir const DWORD len2 = GetShortPathNameW(
320cdf0e10cSrcweir reinterpret_cast<LPCWSTR>(extPath.getStr()), reinterpret_cast<LPWSTR>(&vec2[0]), extPath.getLength() + 1);
321cdf0e10cSrcweir ret = rtl::OUString(&vec2[0], len2);
322cdf0e10cSrcweir }
323cdf0e10cSrcweir else
324cdf0e10cSrcweir {
325cdf0e10cSrcweir ret = rtl::OUString(&vec[0], len);
326cdf0e10cSrcweir }
327cdf0e10cSrcweir }
328cdf0e10cSrcweir return ret;
329cdf0e10cSrcweir }
330cdf0e10cSrcweir //##########################################################
331cdf0e10cSrcweir // Returns the system path of the executable which can either
332cdf0e10cSrcweir // be provided via the strImageName parameter or as first
333cdf0e10cSrcweir // element of the strArguments list.
334cdf0e10cSrcweir // The returned path will be quoted if it contains spaces.
get_executable_path(rtl_uString * image_name,rtl_uString * cmdline_args[],sal_uInt32 n_cmdline_args,bool search_path)335cdf0e10cSrcweir rtl::OUString get_executable_path(
336cdf0e10cSrcweir rtl_uString* image_name,
337cdf0e10cSrcweir rtl_uString* cmdline_args[],
338cdf0e10cSrcweir sal_uInt32 n_cmdline_args,
339cdf0e10cSrcweir bool search_path)
340cdf0e10cSrcweir {
341cdf0e10cSrcweir rtl::OUString exe_name;
342cdf0e10cSrcweir
343cdf0e10cSrcweir if (image_name)
344cdf0e10cSrcweir exe_name = image_name;
345cdf0e10cSrcweir else if (n_cmdline_args)
346cdf0e10cSrcweir exe_name = rtl::OUString(cmdline_args[0]);
347cdf0e10cSrcweir
348cdf0e10cSrcweir rtl::OUString exe_url = exe_name;
349cdf0e10cSrcweir if (search_path)
350cdf0e10cSrcweir osl_searchFileURL(exe_name.pData, NULL, &exe_url.pData);
351cdf0e10cSrcweir
352cdf0e10cSrcweir rtl::OUString exe_path;
353cdf0e10cSrcweir if (osl_File_E_None != osl::FileBase::getSystemPathFromFileURL(exe_url, exe_path))
354cdf0e10cSrcweir return rtl::OUString();
355cdf0e10cSrcweir
356cdf0e10cSrcweir exe_path = getShortPath(exe_path, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".exe")));
357cdf0e10cSrcweir
358cdf0e10cSrcweir if (exe_path.indexOf(' ') != -1)
359cdf0e10cSrcweir exe_path = quote_string(exe_path);
360cdf0e10cSrcweir
361cdf0e10cSrcweir return exe_path;
362cdf0e10cSrcweir }
363cdf0e10cSrcweir
364cdf0e10cSrcweir //##########################################################
get_file_extension(const rtl::OUString & file_name)365cdf0e10cSrcweir rtl::OUString get_file_extension(const rtl::OUString& file_name)
366cdf0e10cSrcweir {
367cdf0e10cSrcweir sal_Int32 index = file_name.lastIndexOf('.');
368cdf0e10cSrcweir if ((index != -1) && ((index + 1) < file_name.getLength()))
369cdf0e10cSrcweir return file_name.copy(index + 1);
370cdf0e10cSrcweir
371cdf0e10cSrcweir return rtl::OUString();
372cdf0e10cSrcweir }
373cdf0e10cSrcweir
374cdf0e10cSrcweir //##########################################################
is_batch_file(const rtl::OUString & file_name)375cdf0e10cSrcweir bool is_batch_file(const rtl::OUString& file_name)
376cdf0e10cSrcweir {
377cdf0e10cSrcweir rtl::OUString ext = get_file_extension(file_name);
378cdf0e10cSrcweir return (ext.equalsIgnoreAsciiCaseAscii("bat") ||
379cdf0e10cSrcweir ext.equalsIgnoreAsciiCaseAscii("cmd") ||
380cdf0e10cSrcweir ext.equalsIgnoreAsciiCaseAscii("btm"));
381cdf0e10cSrcweir }
382cdf0e10cSrcweir
383cdf0e10cSrcweir //##########################################################
get_batch_processor()384cdf0e10cSrcweir rtl::OUString get_batch_processor()
385cdf0e10cSrcweir {
386cdf0e10cSrcweir rtl::OUString comspec;
387cdf0e10cSrcweir osl_getEnvironment(ENV_COMSPEC.pData, &comspec.pData);
388cdf0e10cSrcweir
389cdf0e10cSrcweir OSL_ASSERT(comspec.getLength());
390cdf0e10cSrcweir
391cdf0e10cSrcweir /* check if comspec path contains blanks and quote it if any */
392cdf0e10cSrcweir if (comspec.indexOf(' ') != -1)
393cdf0e10cSrcweir comspec = quote_string(comspec);
394cdf0e10cSrcweir
395cdf0e10cSrcweir return comspec;
396cdf0e10cSrcweir }
397cdf0e10cSrcweir
398cdf0e10cSrcweir } // namespace private
399cdf0e10cSrcweir
400cdf0e10cSrcweir
401cdf0e10cSrcweir //#################################################
osl_executeProcess(rtl_uString * strImageName,rtl_uString * strArguments[],sal_uInt32 nArguments,oslProcessOption Options,oslSecurity Security,rtl_uString * strDirectory,rtl_uString * strEnvironmentVars[],sal_uInt32 nEnvironmentVars,oslProcess * pProcess)402cdf0e10cSrcweir oslProcessError SAL_CALL osl_executeProcess(
403cdf0e10cSrcweir rtl_uString *strImageName,
404cdf0e10cSrcweir rtl_uString *strArguments[],
405cdf0e10cSrcweir sal_uInt32 nArguments,
406cdf0e10cSrcweir oslProcessOption Options,
407cdf0e10cSrcweir oslSecurity Security,
408cdf0e10cSrcweir rtl_uString *strDirectory,
409cdf0e10cSrcweir rtl_uString *strEnvironmentVars[],
410cdf0e10cSrcweir sal_uInt32 nEnvironmentVars,
411cdf0e10cSrcweir oslProcess *pProcess
412cdf0e10cSrcweir )
413cdf0e10cSrcweir {
414cdf0e10cSrcweir return osl_executeProcess_WithRedirectedIO(
415cdf0e10cSrcweir strImageName,
416cdf0e10cSrcweir strArguments,
417cdf0e10cSrcweir nArguments,
418cdf0e10cSrcweir Options,
419cdf0e10cSrcweir Security,
420cdf0e10cSrcweir strDirectory,
421cdf0e10cSrcweir strEnvironmentVars,
422cdf0e10cSrcweir nEnvironmentVars,
423cdf0e10cSrcweir pProcess,
424cdf0e10cSrcweir NULL, NULL, NULL );
425cdf0e10cSrcweir }
426cdf0e10cSrcweir
427cdf0e10cSrcweir //#################################################
osl_executeProcess_WithRedirectedIO(rtl_uString * ustrImageName,rtl_uString * ustrArguments[],sal_uInt32 nArguments,oslProcessOption Options,oslSecurity Security,rtl_uString * ustrDirectory,rtl_uString * ustrEnvironmentVars[],sal_uInt32 nEnvironmentVars,oslProcess * pProcess,oslFileHandle * pProcessInputWrite,oslFileHandle * pProcessOutputRead,oslFileHandle * pProcessErrorRead)428cdf0e10cSrcweir oslProcessError SAL_CALL osl_executeProcess_WithRedirectedIO(
429cdf0e10cSrcweir rtl_uString *ustrImageName,
430cdf0e10cSrcweir rtl_uString *ustrArguments[],
431cdf0e10cSrcweir sal_uInt32 nArguments,
432cdf0e10cSrcweir oslProcessOption Options,
433cdf0e10cSrcweir oslSecurity Security,
434cdf0e10cSrcweir rtl_uString *ustrDirectory,
435cdf0e10cSrcweir rtl_uString *ustrEnvironmentVars[],
436cdf0e10cSrcweir sal_uInt32 nEnvironmentVars,
437cdf0e10cSrcweir oslProcess *pProcess,
438cdf0e10cSrcweir oslFileHandle *pProcessInputWrite,
439cdf0e10cSrcweir oslFileHandle *pProcessOutputRead,
440cdf0e10cSrcweir oslFileHandle *pProcessErrorRead)
441cdf0e10cSrcweir {
442cdf0e10cSrcweir rtl::OUString exe_path = get_executable_path(
443cdf0e10cSrcweir ustrImageName, ustrArguments, nArguments, (Options & osl_Process_SEARCHPATH));
444cdf0e10cSrcweir
445cdf0e10cSrcweir if (0 == exe_path.getLength())
446cdf0e10cSrcweir return osl_Process_E_NotFound;
447cdf0e10cSrcweir
448cdf0e10cSrcweir if (pProcess == NULL)
449cdf0e10cSrcweir return osl_Process_E_InvalidError;
450cdf0e10cSrcweir
451cdf0e10cSrcweir DWORD flags = NORMAL_PRIORITY_CLASS;
452cdf0e10cSrcweir rtl::OUStringBuffer command_line;
453cdf0e10cSrcweir
454cdf0e10cSrcweir if (is_batch_file(exe_path))
455cdf0e10cSrcweir {
456cdf0e10cSrcweir rtl::OUString batch_processor = get_batch_processor();
457cdf0e10cSrcweir
458cdf0e10cSrcweir if (batch_processor.getLength())
459cdf0e10cSrcweir {
460cdf0e10cSrcweir /* cmd.exe does not work without a console window */
461cdf0e10cSrcweir if (!(Options & osl_Process_WAIT) || (Options & osl_Process_DETACHED))
462cdf0e10cSrcweir flags |= CREATE_NEW_CONSOLE;
463cdf0e10cSrcweir
464cdf0e10cSrcweir command_line.append(batch_processor);
465cdf0e10cSrcweir command_line.appendAscii(" /c ");
466cdf0e10cSrcweir }
467cdf0e10cSrcweir else
468cdf0e10cSrcweir // should we return here in case of error?
469cdf0e10cSrcweir return osl_Process_E_Unknown;
470cdf0e10cSrcweir }
471cdf0e10cSrcweir
472cdf0e10cSrcweir command_line.append(exe_path);
473cdf0e10cSrcweir
474cdf0e10cSrcweir /* Add remaining arguments to command line. If ustrImageName is NULL
475cdf0e10cSrcweir the first parameter is the name of the executable so we have to
476cdf0e10cSrcweir start at 1 instead of 0 */
477cdf0e10cSrcweir for (sal_uInt32 n = (NULL != ustrImageName) ? 0 : 1; n < nArguments; n++)
478cdf0e10cSrcweir {
479cdf0e10cSrcweir command_line.appendAscii(SPACE);
480cdf0e10cSrcweir
481cdf0e10cSrcweir /* Quote arguments containing blanks */
482cdf0e10cSrcweir if (rtl::OUString(ustrArguments[n]).indexOf(' ') != -1)
483cdf0e10cSrcweir command_line.append(quote_string(ustrArguments[n]));
484cdf0e10cSrcweir else
485cdf0e10cSrcweir command_line.append(ustrArguments[n]);
486cdf0e10cSrcweir }
487cdf0e10cSrcweir
488cdf0e10cSrcweir environment_container_t environment;
489cdf0e10cSrcweir LPVOID p_environment = NULL;
490cdf0e10cSrcweir
491cdf0e10cSrcweir if (nEnvironmentVars && ustrEnvironmentVars)
492cdf0e10cSrcweir {
493cdf0e10cSrcweir if (!setup_process_environment(
494cdf0e10cSrcweir ustrEnvironmentVars, nEnvironmentVars, environment))
495cdf0e10cSrcweir return osl_Process_E_InvalidError;
496cdf0e10cSrcweir
497cdf0e10cSrcweir flags |= CREATE_UNICODE_ENVIRONMENT;
498cdf0e10cSrcweir p_environment = &environment[0];
499cdf0e10cSrcweir }
500cdf0e10cSrcweir
501cdf0e10cSrcweir rtl::OUString cwd;
502cdf0e10cSrcweir if (ustrDirectory && ustrDirectory->length && (osl_File_E_None != osl::FileBase::getSystemPathFromFileURL(ustrDirectory, cwd)))
503cdf0e10cSrcweir return osl_Process_E_InvalidError;
504cdf0e10cSrcweir
505cdf0e10cSrcweir LPCWSTR p_cwd = (cwd.getLength()) ? reinterpret_cast<LPCWSTR>(cwd.getStr()) : NULL;
506cdf0e10cSrcweir
507cdf0e10cSrcweir if ((Options & osl_Process_DETACHED) && !(flags & CREATE_NEW_CONSOLE))
508cdf0e10cSrcweir flags |= DETACHED_PROCESS;
509cdf0e10cSrcweir
510cdf0e10cSrcweir STARTUPINFO startup_info;
511cdf0e10cSrcweir memset(&startup_info, 0, sizeof(STARTUPINFO));
512cdf0e10cSrcweir
513cdf0e10cSrcweir startup_info.cb = sizeof(STARTUPINFO);
514cdf0e10cSrcweir startup_info.dwFlags = STARTF_USESHOWWINDOW;
515cdf0e10cSrcweir startup_info.lpDesktop = L"";
516cdf0e10cSrcweir
517cdf0e10cSrcweir /* Create pipes for redirected IO */
518cdf0e10cSrcweir HANDLE hInputRead = NULL;
519cdf0e10cSrcweir HANDLE hInputWrite = NULL;
520cdf0e10cSrcweir if (pProcessInputWrite && create_pipe(&hInputRead, true, &hInputWrite, false))
521cdf0e10cSrcweir startup_info.hStdInput = hInputRead;
522cdf0e10cSrcweir
523cdf0e10cSrcweir HANDLE hOutputRead = NULL;
524cdf0e10cSrcweir HANDLE hOutputWrite = NULL;
525cdf0e10cSrcweir if (pProcessOutputRead && create_pipe(&hOutputRead, false, &hOutputWrite, true))
526cdf0e10cSrcweir startup_info.hStdOutput = hOutputWrite;
527cdf0e10cSrcweir
528cdf0e10cSrcweir HANDLE hErrorRead = NULL;
529cdf0e10cSrcweir HANDLE hErrorWrite = NULL;
530cdf0e10cSrcweir if (pProcessErrorRead && create_pipe(&hErrorRead, false, &hErrorWrite, true))
531cdf0e10cSrcweir startup_info.hStdError = hErrorWrite;
532cdf0e10cSrcweir
533cdf0e10cSrcweir bool b_inherit_handles = false;
534cdf0e10cSrcweir if (pProcessInputWrite || pProcessOutputRead || pProcessErrorRead)
535cdf0e10cSrcweir {
536cdf0e10cSrcweir startup_info.dwFlags |= STARTF_USESTDHANDLES;
537cdf0e10cSrcweir b_inherit_handles = true;
538cdf0e10cSrcweir }
539cdf0e10cSrcweir
540cdf0e10cSrcweir switch(Options & (osl_Process_NORMAL | osl_Process_HIDDEN | osl_Process_MINIMIZED | osl_Process_MAXIMIZED | osl_Process_FULLSCREEN))
541cdf0e10cSrcweir {
542cdf0e10cSrcweir case osl_Process_HIDDEN:
543cdf0e10cSrcweir startup_info.wShowWindow = SW_HIDE;
544cdf0e10cSrcweir flags |= CREATE_NO_WINDOW; // ignored for non-console
545cdf0e10cSrcweir // applications; ignored on
546cdf0e10cSrcweir // Win9x
547cdf0e10cSrcweir break;
548cdf0e10cSrcweir
549cdf0e10cSrcweir case osl_Process_MINIMIZED:
550cdf0e10cSrcweir startup_info.wShowWindow = SW_MINIMIZE;
551cdf0e10cSrcweir break;
552cdf0e10cSrcweir
553cdf0e10cSrcweir case osl_Process_MAXIMIZED:
554cdf0e10cSrcweir case osl_Process_FULLSCREEN:
555cdf0e10cSrcweir startup_info.wShowWindow = SW_MAXIMIZE;
556cdf0e10cSrcweir break;
557cdf0e10cSrcweir
558cdf0e10cSrcweir default:
559cdf0e10cSrcweir startup_info.wShowWindow = SW_NORMAL;
560cdf0e10cSrcweir }
561cdf0e10cSrcweir
562cdf0e10cSrcweir rtl::OUString cmdline = command_line.makeStringAndClear();
563cdf0e10cSrcweir PROCESS_INFORMATION process_info;
564cdf0e10cSrcweir BOOL bRet = FALSE;
565cdf0e10cSrcweir
566cdf0e10cSrcweir if ((Security != NULL) && (((oslSecurityImpl*)Security)->m_hToken != NULL))
567cdf0e10cSrcweir {
568cdf0e10cSrcweir bRet = CreateProcessAsUser(
569cdf0e10cSrcweir ((oslSecurityImpl*)Security)->m_hToken,
570cdf0e10cSrcweir NULL, const_cast<LPTSTR>(reinterpret_cast<LPCTSTR>(cmdline.getStr())), NULL, NULL,
571cdf0e10cSrcweir b_inherit_handles, flags, p_environment, p_cwd,
572cdf0e10cSrcweir &startup_info, &process_info);
573cdf0e10cSrcweir }
574cdf0e10cSrcweir else
575cdf0e10cSrcweir {
576cdf0e10cSrcweir bRet = CreateProcess(
577cdf0e10cSrcweir NULL, const_cast<LPTSTR>(reinterpret_cast<LPCTSTR>(cmdline.getStr())), NULL, NULL,
578cdf0e10cSrcweir b_inherit_handles, flags, p_environment, p_cwd,
579cdf0e10cSrcweir &startup_info, &process_info);
580cdf0e10cSrcweir }
581cdf0e10cSrcweir
582cdf0e10cSrcweir /* Now we can close the pipe ends that are used by the child process */
583cdf0e10cSrcweir
584cdf0e10cSrcweir if (hInputRead)
585cdf0e10cSrcweir CloseHandle(hInputRead);
586cdf0e10cSrcweir
587cdf0e10cSrcweir if (hOutputWrite)
588cdf0e10cSrcweir CloseHandle(hOutputWrite);
589cdf0e10cSrcweir
590cdf0e10cSrcweir if (hErrorWrite)
591cdf0e10cSrcweir CloseHandle(hErrorWrite);
592cdf0e10cSrcweir
593cdf0e10cSrcweir if (bRet)
594cdf0e10cSrcweir {
595cdf0e10cSrcweir CloseHandle(process_info.hThread);
596cdf0e10cSrcweir
597cdf0e10cSrcweir oslProcessImpl* pProcImpl = reinterpret_cast<oslProcessImpl*>(
598cdf0e10cSrcweir rtl_allocateMemory(sizeof(oslProcessImpl)));
599cdf0e10cSrcweir
600cdf0e10cSrcweir if (pProcImpl != NULL)
601cdf0e10cSrcweir {
602cdf0e10cSrcweir pProcImpl->m_hProcess = process_info.hProcess;
603cdf0e10cSrcweir pProcImpl->m_IdProcess = process_info.dwProcessId;
604cdf0e10cSrcweir
605cdf0e10cSrcweir *pProcess = (oslProcess)pProcImpl;
606cdf0e10cSrcweir
607cdf0e10cSrcweir if (Options & osl_Process_WAIT)
608cdf0e10cSrcweir WaitForSingleObject(pProcImpl->m_hProcess, INFINITE);
609cdf0e10cSrcweir
610cdf0e10cSrcweir if (pProcessInputWrite)
611cdf0e10cSrcweir *pProcessInputWrite = osl_createFileHandleFromOSHandle(hInputWrite, osl_File_OpenFlag_Write);
612cdf0e10cSrcweir
613cdf0e10cSrcweir if (pProcessOutputRead)
614cdf0e10cSrcweir *pProcessOutputRead = osl_createFileHandleFromOSHandle(hOutputRead, osl_File_OpenFlag_Read);
615cdf0e10cSrcweir
616cdf0e10cSrcweir if (pProcessErrorRead)
617cdf0e10cSrcweir *pProcessErrorRead = osl_createFileHandleFromOSHandle(hErrorRead, osl_File_OpenFlag_Read);
618cdf0e10cSrcweir
619cdf0e10cSrcweir return osl_Process_E_None;
620cdf0e10cSrcweir }
621cdf0e10cSrcweir }
622cdf0e10cSrcweir
62386e1cf34SPedro Giffuni /* if an error occurred we have to close the server side pipe ends too */
624cdf0e10cSrcweir
625cdf0e10cSrcweir if (hInputWrite)
626cdf0e10cSrcweir CloseHandle(hInputWrite);
627cdf0e10cSrcweir
628cdf0e10cSrcweir if (hOutputRead)
629cdf0e10cSrcweir CloseHandle(hOutputRead);
630cdf0e10cSrcweir
631cdf0e10cSrcweir if (hErrorRead)
632cdf0e10cSrcweir CloseHandle(hErrorRead);
633cdf0e10cSrcweir
634cdf0e10cSrcweir return osl_Process_E_Unknown;
635cdf0e10cSrcweir }
636