diff options
Diffstat (limited to 'sal/osl/w32/procimpl.cxx')
-rw-r--r-- | sal/osl/w32/procimpl.cxx | 644 |
1 files changed, 0 insertions, 644 deletions
diff --git a/sal/osl/w32/procimpl.cxx b/sal/osl/w32/procimpl.cxx deleted file mode 100644 index 3ac82dcc9..000000000 --- a/sal/osl/w32/procimpl.cxx +++ /dev/null @@ -1,644 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_sal.hxx" - -#define UNICODE -#define _UNICODE - -#ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# ifdef _MSC_VER -# pragma warning(push,1) /* disable warnings within system headers */ -# endif -# include <windows.h> -# ifdef _MSC_VER -# pragma warning(pop) -# endif -# include <tchar.h> -# undef WIN32_LEAN_AND_MEAN -#endif -#include "procimpl.h" -#include <rtl/ustring.hxx> -#include <rtl/ustrbuf.hxx> -#include "secimpl.h" -#include "rtl/allocator.hxx" -#include <osl/file.hxx> - -#include <list> -#include <vector> -#include <algorithm> -#include <string> - -//################################################# -extern "C" oslFileHandle SAL_CALL osl_createFileHandleFromOSHandle( HANDLE hFile, sal_uInt32 uFlags ); - -//################################################# -const sal_Unicode NAME_VALUE_SEPARATOR = TEXT('='); -const sal_Char* SPACE = " "; -const rtl::OUString ENV_COMSPEC (RTL_CONSTASCII_USTRINGPARAM("COMSPEC")); -const rtl::OUString QUOTE(RTL_CONSTASCII_USTRINGPARAM("\"")); - -namespace /* private */ -{ - //################################################# - typedef std::list<rtl::OUString, rtl::Allocator<rtl::OUString> > string_container_t; - typedef string_container_t::iterator string_container_iterator_t; - typedef string_container_t::const_iterator string_container_const_iterator_t; - typedef std::pair<string_container_iterator_t, string_container_iterator_t> iterator_pair_t; - typedef std::vector<sal_Unicode, rtl::Allocator<sal_Unicode> > environment_container_t; - - //################################################# - /* Function object that compares two strings that are - expected to be environment variables in the form - "name=value". Only the 'name' part will be compared. - The comparison is in upper case and returns true - if the first of both strings is less than the - second one. */ - struct less_environment_variable : - public std::binary_function<rtl::OUString, rtl::OUString, bool> - { - bool operator() (const rtl::OUString& lhs, const rtl::OUString& rhs) const - { - OSL_ENSURE((lhs.indexOf(NAME_VALUE_SEPARATOR) > -1) && \ - (rhs.indexOf(NAME_VALUE_SEPARATOR) > -1), \ - "Malformed environment variable"); - - // Windows compares environment variables uppercase - // so we do it, too - return (rtl_ustr_compare_WithLength( - lhs.toAsciiUpperCase().pData->buffer, - lhs.indexOf(NAME_VALUE_SEPARATOR), - rhs.toAsciiUpperCase().pData->buffer, - rhs.indexOf(NAME_VALUE_SEPARATOR)) < 0); - } - }; - - //################################################# - /* Function object used by for_each algorithm to - calculate the sum of the length of all strings - in a string container. */ - class sum_of_string_lengths - { - public: - //-------------------------------- - sum_of_string_lengths() : sum_(0) {} - - //-------------------------------- - void operator() (const rtl::OUString& string) - { - OSL_ASSERT(string.getLength()); - - // always include the terminating '\0' - if (string.getLength()) - sum_ += string.getLength() + 1; - } - - //-------------------------------- - operator size_t () const - { - return sum_; - } - private: - size_t sum_; - }; - - //################################################# - inline size_t calc_sum_of_string_lengths(const string_container_t& string_cont) - { - return std::for_each( - string_cont.begin(), string_cont.end(), sum_of_string_lengths()); - } - - //################################################# - void read_environment(/*out*/ string_container_t* environment) - { - // GetEnvironmentStrings returns a sorted list, Windows - // sorts environment variables upper case - LPTSTR env = reinterpret_cast<LPTSTR>(GetEnvironmentStrings()); - LPTSTR p = env; - - while (size_t l = _tcslen(p)) - { - environment->push_back(reinterpret_cast<const sal_Unicode*>(p)); - p += l + 1; - } - FreeEnvironmentStrings(env); - } - - //################################################# - /* the environment list must be sorted, new values - should either replace existing ones or should be - added to the list, environment variables will - be handled case-insensitive */ - bool create_merged_environment( - rtl_uString* env_vars[], - sal_uInt32 env_vars_count, - /*in|out*/ string_container_t* merged_env) - { - OSL_ASSERT(env_vars && env_vars_count > 0 && merged_env); - - read_environment(merged_env); - - for (sal_uInt32 i = 0; i < env_vars_count; i++) - { - rtl::OUString env_var = rtl::OUString(env_vars[i]); - - if (env_var.getLength() == 0) - return false; - - iterator_pair_t iter_pair = std::equal_range( - merged_env->begin(), - merged_env->end(), - env_var, - less_environment_variable()); - - if (env_var.indexOf(NAME_VALUE_SEPARATOR) == -1) - { - merged_env->erase(iter_pair.first, iter_pair.second); - } - else - { - if (iter_pair.first != iter_pair.second) // found - *iter_pair.first = env_var; - else // not found - merged_env->insert(iter_pair.first, env_var); - } - } - return true; - } - - //################################################# - /* Create a merged environment */ - bool setup_process_environment( - rtl_uString* environment_vars[], - sal_uInt32 n_environment_vars, - /*in|out*/ environment_container_t& environment) - { - string_container_t merged_env; - if (!create_merged_environment(environment_vars, n_environment_vars, &merged_env)) - return false; - - // allocate enough space for the '\0'-separated environment strings and - // a final '\0' - environment.resize(calc_sum_of_string_lengths(merged_env) + 1); - - string_container_const_iterator_t iter = merged_env.begin(); - string_container_const_iterator_t iter_end = merged_env.end(); - - sal_uInt32 pos = 0; - for (/**/; iter != iter_end; ++iter) - { - rtl::OUString envv = *iter; - - OSL_ASSERT(envv.getLength()); - - sal_uInt32 n = envv.getLength() + 1; // copy the final '\0', too - rtl_copyMemory( - reinterpret_cast<void*>(&environment[pos]), - reinterpret_cast<const void*>(envv.getStr()), - n * sizeof(sal_Unicode)); - pos += n; - } - environment[pos] = 0; // append a final '\0' - - return true; - } - - //########################################################## - /* In contrast to the Win32 API function CreatePipe with - this function the caller is able to determine separately - which handle of the pipe is inheritable. */ - bool 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) - { - SECURITY_ATTRIBUTES sa; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = p_security_descriptor; - sa.bInheritHandle = b_read_pipe_inheritable || b_write_pipe_inheritable; - - BOOL bRet = FALSE; - HANDLE hTemp = NULL; - - if (!b_read_pipe_inheritable && b_write_pipe_inheritable) - { - bRet = CreatePipe(&hTemp, p_write_pipe, &sa, pipe_size); - - if (bRet && !DuplicateHandle(GetCurrentProcess(), hTemp, - GetCurrentProcess(), p_read_pipe, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) - { - CloseHandle(hTemp); - CloseHandle(*p_read_pipe); - return false; - } - } - else if (b_read_pipe_inheritable && !b_write_pipe_inheritable) - { - bRet = CreatePipe(p_read_pipe, &hTemp, &sa, pipe_size); - - if (bRet && !DuplicateHandle(GetCurrentProcess(), hTemp, - GetCurrentProcess(), p_write_pipe, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) - { - CloseHandle(hTemp); - CloseHandle(*p_write_pipe); - return false; - } - } - else - { - bRet = CreatePipe(p_read_pipe, p_write_pipe, &sa, pipe_size); - } - return bRet; - } - - //######################################################### - // Add a quote sign to the start and the end of a string - // if not already present - rtl::OUString quote_string(const rtl::OUString& string) - { - rtl::OUStringBuffer quoted; - if (string.indexOf(QUOTE) != 0) - quoted.append(QUOTE); - - quoted.append(string); - - if (string.lastIndexOf(QUOTE) != (string.getLength() - 1)) - quoted.append(QUOTE); - - return quoted.makeStringAndClear(); - } - - //The parameter path must be a system path. If it is longer than 260 characters - //then it is shortened using the GetShortPathName function. This function only - //works if the path exists. Because "path" can be the path to an executable, it - //may not have the file extension ".exe". However, if the file on disk has the - //".exe" extension, then the function will fail. In this case a second attempt - //is started by adding the parameter "extension" to "path". - rtl::OUString getShortPath(rtl::OUString const & path, rtl::OUString const & extension) - { - rtl::OUString ret(path); - if (path.getLength() > 260) - { - std::vector<sal_Unicode, rtl::Allocator<sal_Unicode> > vec(path.getLength() + 1); - //GetShortPathNameW only works if the file can be found! - const DWORD len = GetShortPathNameW( - reinterpret_cast<LPCWSTR>(path.getStr()), reinterpret_cast<LPWSTR>(&vec[0]), path.getLength() + 1); - - if (!len && GetLastError() == ERROR_FILE_NOT_FOUND - && extension.getLength()) - { - const rtl::OUString extPath(path + extension); - std::vector<sal_Unicode, rtl::Allocator<sal_Unicode> > vec2( - extPath.getLength() + 1); - const DWORD len2 = GetShortPathNameW( - reinterpret_cast<LPCWSTR>(extPath.getStr()), reinterpret_cast<LPWSTR>(&vec2[0]), extPath.getLength() + 1); - ret = rtl::OUString(&vec2[0], len2); - } - else - { - ret = rtl::OUString(&vec[0], len); - } - } - return ret; - } - //########################################################## - // Returns the system path of the executable which can either - // be provided via the strImageName parameter or as first - // element of the strArguments list. - // The returned path will be quoted if it contains spaces. - rtl::OUString get_executable_path( - rtl_uString* image_name, - rtl_uString* cmdline_args[], - sal_uInt32 n_cmdline_args, - bool search_path) - { - rtl::OUString exe_name; - - if (image_name) - exe_name = image_name; - else if (n_cmdline_args) - exe_name = rtl::OUString(cmdline_args[0]); - - rtl::OUString exe_url = exe_name; - if (search_path) - osl_searchFileURL(exe_name.pData, NULL, &exe_url.pData); - - rtl::OUString exe_path; - if (osl_File_E_None != osl::FileBase::getSystemPathFromFileURL(exe_url, exe_path)) - return rtl::OUString(); - - exe_path = getShortPath(exe_path, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".exe"))); - - if (exe_path.indexOf(' ') != -1) - exe_path = quote_string(exe_path); - - return exe_path; - } - - //########################################################## - rtl::OUString get_file_extension(const rtl::OUString& file_name) - { - sal_Int32 index = file_name.lastIndexOf('.'); - if ((index != -1) && ((index + 1) < file_name.getLength())) - return file_name.copy(index + 1); - - return rtl::OUString(); - } - - //########################################################## - bool is_batch_file(const rtl::OUString& file_name) - { - rtl::OUString ext = get_file_extension(file_name); - return (ext.equalsIgnoreAsciiCaseAscii("bat") || - ext.equalsIgnoreAsciiCaseAscii("cmd") || - ext.equalsIgnoreAsciiCaseAscii("btm")); - } - - //########################################################## - rtl::OUString get_batch_processor() - { - rtl::OUString comspec; - osl_getEnvironment(ENV_COMSPEC.pData, &comspec.pData); - - OSL_ASSERT(comspec.getLength()); - - /* check if comspec path contains blanks and quote it if any */ - if (comspec.indexOf(' ') != -1) - comspec = quote_string(comspec); - - return comspec; - } - -} // namespace private - - -//################################################# -oslProcessError SAL_CALL 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 -) -{ - return osl_executeProcess_WithRedirectedIO( - strImageName, - strArguments, - nArguments, - Options, - Security, - strDirectory, - strEnvironmentVars, - nEnvironmentVars, - pProcess, - NULL, NULL, NULL ); -} - -//################################################# -oslProcessError SAL_CALL 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) -{ - rtl::OUString exe_path = get_executable_path( - ustrImageName, ustrArguments, nArguments, (Options & osl_Process_SEARCHPATH)); - - if (0 == exe_path.getLength()) - return osl_Process_E_NotFound; - - if (pProcess == NULL) - return osl_Process_E_InvalidError; - - DWORD flags = NORMAL_PRIORITY_CLASS; - rtl::OUStringBuffer command_line; - - if (is_batch_file(exe_path)) - { - rtl::OUString batch_processor = get_batch_processor(); - - if (batch_processor.getLength()) - { - /* cmd.exe does not work without a console window */ - if (!(Options & osl_Process_WAIT) || (Options & osl_Process_DETACHED)) - flags |= CREATE_NEW_CONSOLE; - - command_line.append(batch_processor); - command_line.appendAscii(" /c "); - } - else - // should we return here in case of error? - return osl_Process_E_Unknown; - } - - command_line.append(exe_path); - - /* Add remaining arguments to command line. If ustrImageName is NULL - the first parameter is the name of the executable so we have to - start at 1 instead of 0 */ - for (sal_uInt32 n = (NULL != ustrImageName) ? 0 : 1; n < nArguments; n++) - { - command_line.appendAscii(SPACE); - - /* Quote arguments containing blanks */ - if (rtl::OUString(ustrArguments[n]).indexOf(' ') != -1) - command_line.append(quote_string(ustrArguments[n])); - else - command_line.append(ustrArguments[n]); - } - - environment_container_t environment; - LPVOID p_environment = NULL; - - if (nEnvironmentVars && ustrEnvironmentVars) - { - if (!setup_process_environment( - ustrEnvironmentVars, nEnvironmentVars, environment)) - return osl_Process_E_InvalidError; - - flags |= CREATE_UNICODE_ENVIRONMENT; - p_environment = &environment[0]; - } - - rtl::OUString cwd; - if (ustrDirectory && ustrDirectory->length && (osl_File_E_None != osl::FileBase::getSystemPathFromFileURL(ustrDirectory, cwd))) - return osl_Process_E_InvalidError; - - LPCWSTR p_cwd = (cwd.getLength()) ? reinterpret_cast<LPCWSTR>(cwd.getStr()) : NULL; - - if ((Options & osl_Process_DETACHED) && !(flags & CREATE_NEW_CONSOLE)) - flags |= DETACHED_PROCESS; - - STARTUPINFO startup_info; - memset(&startup_info, 0, sizeof(STARTUPINFO)); - - startup_info.cb = sizeof(STARTUPINFO); - startup_info.dwFlags = STARTF_USESHOWWINDOW; - startup_info.lpDesktop = L""; - - /* Create pipes for redirected IO */ - HANDLE hInputRead = NULL; - HANDLE hInputWrite = NULL; - if (pProcessInputWrite && create_pipe(&hInputRead, true, &hInputWrite, false)) - startup_info.hStdInput = hInputRead; - - HANDLE hOutputRead = NULL; - HANDLE hOutputWrite = NULL; - if (pProcessOutputRead && create_pipe(&hOutputRead, false, &hOutputWrite, true)) - startup_info.hStdOutput = hOutputWrite; - - HANDLE hErrorRead = NULL; - HANDLE hErrorWrite = NULL; - if (pProcessErrorRead && create_pipe(&hErrorRead, false, &hErrorWrite, true)) - startup_info.hStdError = hErrorWrite; - - bool b_inherit_handles = false; - if (pProcessInputWrite || pProcessOutputRead || pProcessErrorRead) - { - startup_info.dwFlags |= STARTF_USESTDHANDLES; - b_inherit_handles = true; - } - - switch(Options & (osl_Process_NORMAL | osl_Process_HIDDEN | osl_Process_MINIMIZED | osl_Process_MAXIMIZED | osl_Process_FULLSCREEN)) - { - case osl_Process_HIDDEN: - startup_info.wShowWindow = SW_HIDE; - flags |= CREATE_NO_WINDOW; // ignored for non-console - // applications; ignored on - // Win9x - break; - - case osl_Process_MINIMIZED: - startup_info.wShowWindow = SW_MINIMIZE; - break; - - case osl_Process_MAXIMIZED: - case osl_Process_FULLSCREEN: - startup_info.wShowWindow = SW_MAXIMIZE; - break; - - default: - startup_info.wShowWindow = SW_NORMAL; - } - - rtl::OUString cmdline = command_line.makeStringAndClear(); - PROCESS_INFORMATION process_info; - BOOL bRet = FALSE; - - if ((Security != NULL) && (((oslSecurityImpl*)Security)->m_hToken != NULL)) - { - bRet = CreateProcessAsUser( - ((oslSecurityImpl*)Security)->m_hToken, - NULL, const_cast<LPTSTR>(reinterpret_cast<LPCTSTR>(cmdline.getStr())), NULL, NULL, - b_inherit_handles, flags, p_environment, p_cwd, - &startup_info, &process_info); - } - else - { - bRet = CreateProcess( - NULL, const_cast<LPTSTR>(reinterpret_cast<LPCTSTR>(cmdline.getStr())), NULL, NULL, - b_inherit_handles, flags, p_environment, p_cwd, - &startup_info, &process_info); - } - - /* Now we can close the pipe ends that are used by the child process */ - - if (hInputRead) - CloseHandle(hInputRead); - - if (hOutputWrite) - CloseHandle(hOutputWrite); - - if (hErrorWrite) - CloseHandle(hErrorWrite); - - if (bRet) - { - CloseHandle(process_info.hThread); - - oslProcessImpl* pProcImpl = reinterpret_cast<oslProcessImpl*>( - rtl_allocateMemory(sizeof(oslProcessImpl))); - - if (pProcImpl != NULL) - { - pProcImpl->m_hProcess = process_info.hProcess; - pProcImpl->m_IdProcess = process_info.dwProcessId; - - *pProcess = (oslProcess)pProcImpl; - - if (Options & osl_Process_WAIT) - WaitForSingleObject(pProcImpl->m_hProcess, INFINITE); - - if (pProcessInputWrite) - *pProcessInputWrite = osl_createFileHandleFromOSHandle(hInputWrite, osl_File_OpenFlag_Write); - - if (pProcessOutputRead) - *pProcessOutputRead = osl_createFileHandleFromOSHandle(hOutputRead, osl_File_OpenFlag_Read); - - if (pProcessErrorRead) - *pProcessErrorRead = osl_createFileHandleFromOSHandle(hErrorRead, osl_File_OpenFlag_Read); - - return osl_Process_E_None; - } - } - - /* if an error occurred we have to close the server side pipe ends too */ - - if (hInputWrite) - CloseHandle(hInputWrite); - - if (hOutputRead) - CloseHandle(hOutputRead); - - if (hErrorRead) - CloseHandle(hErrorRead); - - return osl_Process_E_Unknown; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |