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