| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #define UNICODE |
| #include "system.h" |
| #ifdef _MSC_VER |
| #pragma warning(push,1) /* disable warnings within system headers */ |
| #endif |
| #include <shellapi.h> |
| #ifdef _MSC_VER |
| #pragma warning(pop) |
| #endif |
| |
| #include <osl/diagnose.h> |
| #include <osl/security.h> |
| #include <osl/nlsupport.h> |
| #include <osl/mutex.h> |
| #include <osl/thread.h> |
| |
| #include "procimpl.h" |
| #include "sockimpl.h" |
| #include "file_url.h" |
| #include "path_helper.hxx" |
| #include <rtl/ustrbuf.h> |
| #include <rtl/alloc.h> |
| |
| /*************************************************************************** |
| * Process. |
| ***************************************************************************/ |
| |
| oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process) |
| { |
| if (Process == NULL) |
| return osl_Process_E_Unknown; |
| |
| if (TerminateProcess(((oslProcessImpl*)Process)->m_hProcess, 0)) |
| return osl_Process_E_None; |
| |
| |
| return osl_Process_E_Unknown; |
| } |
| |
| /***************************************************************************/ |
| |
| oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident) |
| { |
| oslProcessImpl* pProcImpl; |
| HANDLE hProcess = OpenProcess( |
| STANDARD_RIGHTS_REQUIRED | PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, (DWORD)Ident); |
| |
| if (hProcess) |
| { |
| pProcImpl = reinterpret_cast< oslProcessImpl*>( rtl_allocateMemory(sizeof(oslProcessImpl)) ); |
| pProcImpl->m_hProcess = hProcess; |
| pProcImpl->m_IdProcess = Ident; |
| } |
| else |
| pProcImpl = NULL; |
| |
| return (pProcImpl); |
| } |
| |
| /***************************************************************************/ |
| |
| void SAL_CALL osl_freeProcessHandle(oslProcess Process) |
| { |
| if (Process != NULL) |
| { |
| CloseHandle(((oslProcessImpl*)Process)->m_hProcess); |
| |
| rtl_freeMemory((oslProcessImpl*)Process); |
| } |
| } |
| |
| /***************************************************************************/ |
| |
| oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields, |
| oslProcessInfo* pInfo) |
| { |
| HANDLE hProcess; |
| DWORD IdProcess; |
| |
| if (Process == NULL) |
| { |
| hProcess = GetCurrentProcess(); |
| IdProcess = GetCurrentProcessId(); |
| } |
| else |
| { |
| hProcess = ((oslProcessImpl*)Process)->m_hProcess; |
| IdProcess = ((oslProcessImpl*)Process)->m_IdProcess; |
| } |
| |
| if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo))) |
| return osl_Process_E_Unknown; |
| |
| pInfo->Fields = 0; |
| |
| if (Fields & osl_Process_IDENTIFIER) |
| { |
| pInfo->Ident = IdProcess; |
| pInfo->Fields |= osl_Process_IDENTIFIER; |
| } |
| |
| if (Fields & osl_Process_EXITCODE) |
| { |
| if (GetExitCodeProcess(hProcess, &(pInfo->Code)) && (pInfo->Code != STILL_ACTIVE)) |
| pInfo->Fields |= osl_Process_EXITCODE; |
| } |
| |
| if (Fields & osl_Process_HEAPUSAGE) |
| { |
| void* lpAddress=0; |
| MEMORY_BASIC_INFORMATION Info; |
| |
| pInfo->HeapUsage = 0; |
| |
| do |
| { |
| if (VirtualQueryEx(hProcess, lpAddress, &Info, sizeof(Info)) == 0) |
| break; |
| |
| if ((Info.State == MEM_COMMIT) && (Info.Type == MEM_PRIVATE)) |
| pInfo->HeapUsage += Info.RegionSize; |
| |
| lpAddress = (LPBYTE)lpAddress + Info.RegionSize; |
| } |
| while (lpAddress < (void *)0x80000000); // 2GB address space |
| |
| pInfo->Fields |= osl_Process_HEAPUSAGE; |
| } |
| |
| if (Fields & osl_Process_CPUTIMES) |
| { |
| FILETIME CreationTime, ExitTime, KernelTime, UserTime; |
| |
| if (GetProcessTimes(hProcess, &CreationTime, &ExitTime, |
| &KernelTime, &UserTime)) |
| { |
| __int64 Value; |
| |
| Value = *((__int64 *)&UserTime); |
| pInfo->UserTime.Seconds = (unsigned long) (Value / 10000000L); |
| pInfo->UserTime.Nanosec = (unsigned long)((Value % 10000000L) * 100); |
| |
| Value = *((__int64 *)&KernelTime); |
| pInfo->SystemTime.Seconds = (unsigned long) (Value / 10000000L); |
| pInfo->SystemTime.Nanosec = (unsigned long)((Value % 10000000L) * 100); |
| |
| pInfo->Fields |= osl_Process_CPUTIMES; |
| } |
| } |
| |
| return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown; |
| } |
| |
| /***************************************************************************/ |
| |
| oslProcessError SAL_CALL osl_joinProcess(oslProcess Process) |
| { |
| return osl_joinProcessWithTimeout(Process, NULL); |
| } |
| |
| /***************************************************************************/ |
| |
| oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout) |
| { |
| DWORD timeout = INFINITE; |
| oslProcessError osl_error = osl_Process_E_None; |
| DWORD ret; |
| |
| if (NULL == Process) |
| return osl_Process_E_Unknown; |
| |
| if (pTimeout) |
| timeout = pTimeout->Seconds * 1000 + pTimeout->Nanosec / 1000000L; |
| |
| ret = WaitForSingleObject(((oslProcessImpl*)Process)->m_hProcess, timeout); |
| |
| if (WAIT_FAILED == ret) |
| osl_error = osl_Process_E_Unknown; |
| else if (WAIT_TIMEOUT == ret) |
| osl_error = osl_Process_E_TimedOut; |
| |
| return osl_error; |
| } |
| |
| /*************************************************************************** |
| * osl_bootstrap_getExecutableFile_Impl(). |
| * |
| * @internal |
| * @see rtl_bootstrap |
| * @see #i37371# |
| * |
| ***************************************************************************/ |
| |
| extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl ( |
| rtl_uString ** ppFileURL |
| ) SAL_THROW_EXTERN_C() |
| { |
| oslProcessError result = osl_Process_E_NotFound; |
| |
| ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH ); |
| DWORD buflen = 0; |
| |
| if ((buflen = GetModuleFileNameW (0, ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), aBuffer.getBufSizeInSymbols())) > 0) |
| { |
| rtl_uString * pAbsPath = 0; |
| rtl_uString_newFromStr_WithLength (&(pAbsPath), aBuffer, buflen); |
| if (pAbsPath) |
| { |
| /* Convert from path to url. */ |
| if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None) |
| { |
| /* Success. */ |
| result = osl_Process_E_None; |
| } |
| rtl_uString_release (pAbsPath); |
| } |
| } |
| |
| return (result); |
| } |
| |
| /*************************************************************************** |
| * Command Line Arguments. |
| ***************************************************************************/ |
| |
| struct CommandArgs_Impl |
| { |
| sal_uInt32 m_nCount; |
| rtl_uString ** m_ppArgs; |
| }; |
| |
| static struct CommandArgs_Impl g_command_args = |
| { |
| 0, |
| 0 |
| }; |
| |
| #ifdef _MSC_VER |
| #pragma warning( push ) |
| #pragma warning( disable: 4100 ) |
| #endif |
| static rtl_uString ** osl_createCommandArgs_Impl (int argc, char ** argv) |
| { |
| rtl_uString ** ppArgs = |
| (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*)); |
| if (ppArgs != 0) |
| { |
| int i; |
| int nArgs; |
| LPWSTR *wargv = CommandLineToArgvW( GetCommandLineW(), &nArgs ); |
| OSL_ASSERT( nArgs == argc ); |
| for (i = 0; i < nArgs; i++) |
| { |
| /* Convert to unicode */ |
| rtl_uString_newFromStr( &(ppArgs[i]), reinterpret_cast<const sal_Unicode*>(wargv[i]) ); |
| } |
| if (ppArgs[0] != 0) |
| { |
| /* Ensure absolute path */ |
| ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH ); |
| DWORD dwResult = 0; |
| |
| dwResult = SearchPath ( |
| 0, reinterpret_cast<LPCWSTR>(ppArgs[0]->buffer), L".exe", aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), 0); |
| if ((0 < dwResult) && (dwResult < aBuffer.getBufSizeInSymbols())) |
| { |
| /* Replace argv[0] with it's absolute path */ |
| rtl_uString_newFromStr_WithLength( |
| &(ppArgs[0]), aBuffer, dwResult); |
| } |
| } |
| if (ppArgs[0] != 0) |
| { |
| /* Convert to FileURL, see @ osl_getExecutableFile() */ |
| rtl_uString * pResult = 0; |
| osl_getFileURLFromSystemPath (ppArgs[0], &pResult); |
| if (pResult != 0) |
| { |
| rtl_uString_assign (&(ppArgs[0]), pResult); |
| rtl_uString_release (pResult); |
| } |
| } |
| } |
| return (ppArgs); |
| |
| } |
| #ifdef _MSC_VER |
| #pragma warning( pop ) |
| #endif |
| |
| /***************************************************************************/ |
| |
| oslProcessError SAL_CALL osl_getExecutableFile( rtl_uString **ppustrFile ) |
| { |
| oslProcessError result = osl_Process_E_NotFound; |
| |
| osl_acquireMutex (*osl_getGlobalMutex()); |
| OSL_ASSERT(g_command_args.m_nCount > 0); |
| if (g_command_args.m_nCount > 0) |
| { |
| /* CommandArgs set. Obtain arv[0]. */ |
| rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]); |
| result = osl_Process_E_None; |
| } |
| osl_releaseMutex (*osl_getGlobalMutex()); |
| |
| return (result); |
| } |
| |
| /***************************************************************************/ |
| |
| sal_uInt32 SAL_CALL osl_getCommandArgCount(void) |
| { |
| sal_uInt32 result = 0; |
| |
| osl_acquireMutex (*osl_getGlobalMutex()); |
| OSL_ASSERT(g_command_args.m_nCount > 0); |
| if (g_command_args.m_nCount > 0) |
| { |
| /* We're not counting argv[0] here. */ |
| result = g_command_args.m_nCount - 1; |
| } |
| osl_releaseMutex (*osl_getGlobalMutex()); |
| |
| return (result); |
| } |
| |
| /***************************************************************************/ |
| |
| oslProcessError SAL_CALL osl_getCommandArg( sal_uInt32 nArg, rtl_uString **strCommandArg) |
| { |
| oslProcessError result = osl_Process_E_NotFound; |
| |
| osl_acquireMutex (*osl_getGlobalMutex()); |
| OSL_ASSERT(g_command_args.m_nCount > 0); |
| if (g_command_args.m_nCount > (nArg + 1)) |
| { |
| /* We're not counting argv[0] here. */ |
| rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]); |
| result = osl_Process_E_None; |
| } |
| osl_releaseMutex (*osl_getGlobalMutex()); |
| |
| return (result); |
| } |
| |
| /***************************************************************************/ |
| |
| void SAL_CALL osl_setCommandArgs (int argc, char ** argv) |
| { |
| OSL_ASSERT(argc > 0); |
| osl_acquireMutex (*osl_getGlobalMutex()); |
| if (g_command_args.m_nCount == 0) |
| { |
| rtl_uString** ppArgs = osl_createCommandArgs_Impl (argc, argv); |
| if (ppArgs != 0) |
| { |
| g_command_args.m_nCount = argc; |
| g_command_args.m_ppArgs = ppArgs; |
| } |
| } |
| osl_releaseMutex (*osl_getGlobalMutex()); |
| } |
| |
| /*************************************************************************** |
| * Environment |
| ***************************************************************************/ |
| #define ENV_BUFFER_SIZE (32*1024-1) |
| |
| oslProcessError SAL_CALL osl_getEnvironment(rtl_uString *ustrVar, rtl_uString **ustrValue) |
| { |
| WCHAR buff[ENV_BUFFER_SIZE]; |
| |
| if (GetEnvironmentVariableW(reinterpret_cast<LPCWSTR>(ustrVar->buffer), buff, ENV_BUFFER_SIZE) > 0) |
| { |
| rtl_uString_newFromStr(ustrValue, reinterpret_cast<const sal_Unicode*>(buff)); |
| return osl_Process_E_None; |
| } |
| return osl_Process_E_Unknown; |
| } |
| |
| oslProcessError SAL_CALL osl_setEnvironment(rtl_uString *ustrVar, rtl_uString *ustrValue) |
| { |
| // set Windows environment variable |
| LPCWSTR lpName = reinterpret_cast<LPCWSTR>(ustrVar->buffer); |
| LPCWSTR lpValue = reinterpret_cast<LPCWSTR>(ustrValue->buffer); |
| if( !SetEnvironmentVariableW( lpName, lpValue)) |
| return osl_Process_E_Unknown; |
| |
| // also set the variable in the crt environment |
| _wputenv_s( lpName, lpValue); |
| return osl_Process_E_None; |
| } |
| |
| oslProcessError SAL_CALL osl_clearEnvironment(rtl_uString *ustrVar) |
| { |
| // delete the variable from the current process environment |
| // by setting SetEnvironmentVariable's second parameter to NULL |
| LPCWSTR lpName = reinterpret_cast<LPCWSTR>(ustrVar->buffer); |
| if( !SetEnvironmentVariableW( lpName, NULL)) |
| return osl_Process_E_Unknown; |
| |
| // also remove the variable from the crt environment |
| wchar_t aEmptyName = 0; |
| _wputenv_s( lpName, &aEmptyName); |
| return osl_Process_E_None; |
| } |
| |
| /*************************************************************************** |
| * Current Working Directory. |
| ***************************************************************************/ |
| |
| extern "C" oslMutex g_CurrentDirectoryMutex; |
| |
| oslProcessError SAL_CALL osl_getProcessWorkingDir( rtl_uString **pustrWorkingDir ) |
| { |
| ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH ); |
| DWORD dwLen = 0; |
| |
| |
| osl_acquireMutex( g_CurrentDirectoryMutex ); |
| dwLen = GetCurrentDirectory( aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer) ); |
| osl_releaseMutex( g_CurrentDirectoryMutex ); |
| |
| if ( dwLen && dwLen < aBuffer.getBufSizeInSymbols() ) |
| { |
| oslFileError eError; |
| rtl_uString *ustrTemp = NULL;; |
| |
| rtl_uString_newFromStr_WithLength( &ustrTemp, aBuffer, dwLen ); |
| eError = osl_getFileURLFromSystemPath( ustrTemp, pustrWorkingDir ); |
| |
| rtl_uString_release( ustrTemp ); |
| |
| if ( osl_File_E_None != eError ) |
| return osl_Process_E_Unknown; |
| else |
| return osl_Process_E_None; |
| } |
| else |
| return osl_Process_E_Unknown; |
| } |
| |
| /*************************************************************************** |
| * Process Locale. |
| ***************************************************************************/ |
| |
| extern "C" void _imp_getProcessLocale( rtl_Locale ** ppLocale ); |
| |
| static rtl_Locale * g_theProcessLocale = NULL; |
| |
| /***************************************************************************/ |
| |
| oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale ) |
| { |
| osl_acquireMutex( *osl_getGlobalMutex() ); |
| |
| /* determine the users default locale */ |
| if( NULL == g_theProcessLocale ) |
| _imp_getProcessLocale( &g_theProcessLocale ); |
| |
| /* or return the cached value */ |
| *ppLocale = g_theProcessLocale; |
| |
| osl_releaseMutex( *osl_getGlobalMutex() ); |
| return osl_Process_E_None; |
| } |
| |
| /***************************************************************************/ |
| |
| oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale ) |
| { |
| osl_acquireMutex( *osl_getGlobalMutex() ); |
| |
| /* check if locale is supported */ |
| if( RTL_TEXTENCODING_DONTKNOW == osl_getTextEncodingFromLocale( pLocale ) ) |
| return osl_Process_E_Unknown; |
| |
| /* just remember the locale here */ |
| g_theProcessLocale = pLocale; |
| |
| osl_releaseMutex( *osl_getGlobalMutex() ); |
| return osl_Process_E_None; |
| } |
| |
| /************************************************ |
| * Portal send/receive interface implementation |
| ************************************************/ |
| |
| static sal_Bool ReadPipe(oslPipe hPipe, |
| void* pBuffer, |
| sal_Int32 BytesToRead, |
| sal_Int32* nBytes) |
| { |
| *nBytes = osl_receivePipe(hPipe, pBuffer, BytesToRead); |
| OSL_TRACE("tried to recieve %d, recieved %d.\n", |
| BytesToRead, *nBytes); |
| return (sal_Bool)((*nBytes >= 0) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None)); |
| } |
| |
| static sal_Bool WritePipe(oslPipe hPipe, |
| void* pBuffer, |
| sal_Int32 BytesToSend, |
| sal_Int32* nBytes) |
| { |
| *nBytes = osl_sendPipe(hPipe, pBuffer, BytesToSend); |
| OSL_TRACE("tried to send %d, sent %d\n", |
| BytesToSend, *nBytes); |
| return (sal_Bool)((*nBytes == BytesToSend) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None)); |
| } |
| |
| sal_Bool SAL_CALL osl_sendResourcePipe(oslPipe hPipe, oslSocket pSocket) |
| { |
| sal_Bool bRet = sal_False; |
| sal_Int32 bytes = 0; |
| |
| /* duplicate handle on this other side -> |
| receive remote process |
| duplicate handle and send it */ |
| DWORD remoteProcessID = 0; |
| HANDLE fd = (HANDLE)pSocket->m_Socket; |
| oslDescriptorType code = osl_Process_TypeSocket; |
| |
| OSL_TRACE("osl_sendResourcePipe: enter..."); |
| |
| if (ReadPipe(hPipe, &remoteProcessID, sizeof(remoteProcessID), &bytes)) |
| { |
| HANDLE hRemoteProc = OpenProcess(PROCESS_DUP_HANDLE, |
| FALSE, |
| remoteProcessID); |
| |
| if (hRemoteProc != (HANDLE)NULL) |
| { |
| HANDLE newFd; |
| |
| if (DuplicateHandle(GetCurrentProcess(), |
| fd, |
| hRemoteProc, |
| &newFd, |
| 0, FALSE, DUPLICATE_SAME_ACCESS)) |
| { |
| if ( |
| WritePipe(hPipe, &code, sizeof(code), &bytes) && |
| WritePipe(hPipe, &newFd, sizeof(fd), &bytes) |
| ) |
| bRet = sal_True; |
| } |
| |
| CloseHandle(hRemoteProc); |
| } |
| } |
| |
| if (bRet) |
| { |
| sal_Int32 commitCode; |
| OSL_TRACE("osl_sendResourcePipe: handle sent successfully, verify...\n"); |
| |
| if ( |
| !ReadPipe(hPipe, &commitCode, sizeof(commitCode), &bytes) || |
| (commitCode <= 0) |
| ) |
| bRet = sal_False; |
| } |
| |
| OSL_TRACE("osl_sendResourcePipe: exit... %d\n", bRet); |
| return(bRet); |
| } |
| |
| |
| oslSocket SAL_CALL osl_receiveResourcePipe(oslPipe hPipe) |
| { |
| sal_Bool bRet = sal_False; |
| sal_Int32 bytes = 0; |
| sal_Int32 commitCode; |
| oslSocket pSocket = NULL; |
| |
| /* duplicate handle on the other side -> |
| send my process id receive duplicated handle */ |
| HANDLE fd = INVALID_HANDLE_VALUE; |
| DWORD myProcessID = GetCurrentProcessId(); |
| oslDescriptorType code = osl_Process_TypeNone; |
| |
| OSL_TRACE("osl_receiveResourcePipe: enter...\n"); |
| |
| if ( |
| WritePipe(hPipe, &myProcessID, sizeof(myProcessID), &bytes) && |
| ReadPipe(hPipe, &code, sizeof(code), &bytes) && |
| ReadPipe(hPipe, &fd, sizeof(fd), &bytes) |
| ) |
| { |
| if (code == osl_Process_TypeSocket) |
| { |
| pSocket = __osl_createSocketImpl((SOCKET)fd); |
| bRet = sal_True; |
| } |
| else |
| { |
| OSL_TRACE("osl_receiveResourcePipe: UKNOWN\n"); |
| bRet = sal_False; |
| } |
| } |
| |
| if (bRet) |
| commitCode = 1; |
| else |
| commitCode = 0; |
| |
| WritePipe(hPipe, &commitCode, sizeof(commitCode), &bytes); |
| |
| OSL_TRACE("osl_receiveResourcePipe: exit... %d, %p\n", bRet, pSocket); |
| |
| return pSocket; |
| } |