blob: 72e8485c2afd1387a072bc603db2f86f74e94355 [file] [log] [blame]
/**************************************************************
*
* 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;
}