summaryrefslogtreecommitdiff
path: root/sal/osl/w32/procimpl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/w32/procimpl.cxx')
-rw-r--r--sal/osl/w32/procimpl.cxx644
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: */