/************************************************************** * * 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 #ifdef _MSC_VER #pragma warning(pop) #endif #include #include #include #include #include #include "procimpl.h" #include "sockimpl.h" #include "file_url.h" #include "path_helper.hxx" #include #include /*************************************************************************** * 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(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(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(ppArgs[0]->buffer), L".exe", aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast(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(ustrVar->buffer), buff, ENV_BUFFER_SIZE) > 0) { rtl_uString_newFromStr(ustrValue, reinterpret_cast(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(ustrVar->buffer); LPCWSTR lpValue = reinterpret_cast(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(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(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 receive %d, received %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; }