a715e1b3d0
Fixes #fdo30794 Based on bin/add-modelines script (originally posted in mail 1286706307.1871.1399280959@webmail.messagingengine.com) Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
1189 lines
38 KiB
C++
1189 lines
38 KiB
C++
/* -*- 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_cppu.hxx"
|
|
|
|
#include "cppu/EnvDcp.hxx"
|
|
|
|
#include "sal/alloca.h"
|
|
#include "osl/diagnose.h"
|
|
#include "osl/interlck.h"
|
|
#include "osl/mutex.hxx"
|
|
#include "osl/module.h"
|
|
#include "osl/process.h"
|
|
#include "rtl/process.h"
|
|
#include "rtl/unload.h"
|
|
#include "rtl/string.hxx"
|
|
#include "rtl/ustring.hxx"
|
|
#include "rtl/ustrbuf.hxx"
|
|
#include "rtl/instance.hxx"
|
|
#include "typelib/typedescription.h"
|
|
#include "uno/dispatcher.h"
|
|
#include "uno/environment.h"
|
|
#include "uno/lbnames.h"
|
|
#include "prim.hxx"
|
|
#include "destr.hxx"
|
|
#include "loadmodule.hxx"
|
|
|
|
#include <hash_map>
|
|
#include <vector>
|
|
#include <stdio.h>
|
|
|
|
|
|
using ::rtl::OUString;
|
|
|
|
namespace
|
|
{
|
|
|
|
//------------------------------------------------------------------------------
|
|
inline static bool td_equals( typelib_InterfaceTypeDescription * pTD1,
|
|
typelib_InterfaceTypeDescription * pTD2 )
|
|
{
|
|
return (pTD1 == pTD2 ||
|
|
(((typelib_TypeDescription *)pTD1)->pTypeName->length ==
|
|
((typelib_TypeDescription *)pTD2)->pTypeName->length &&
|
|
::rtl_ustr_compare(
|
|
((typelib_TypeDescription *) pTD1)->pTypeName->buffer,
|
|
((typelib_TypeDescription *) pTD2)->pTypeName->buffer ) == 0));
|
|
}
|
|
|
|
struct ObjectEntry;
|
|
struct uno_DefaultEnvironment;
|
|
|
|
//------------------------------------------------------------------------------
|
|
struct InterfaceEntry
|
|
{
|
|
sal_Int32 refCount;
|
|
void * pInterface;
|
|
uno_freeProxyFunc fpFreeProxy;
|
|
typelib_InterfaceTypeDescription * pTypeDescr;
|
|
};
|
|
|
|
struct ObjectEntry
|
|
{
|
|
OUString oid;
|
|
sal_Int32 nRef;
|
|
::std::vector< InterfaceEntry > aInterfaces;
|
|
bool mixedObject;
|
|
|
|
inline ObjectEntry( const OUString & rOId_ );
|
|
|
|
inline void append(
|
|
uno_DefaultEnvironment * pEnv,
|
|
void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
|
|
uno_freeProxyFunc fpFreeProxy );
|
|
inline InterfaceEntry * find(
|
|
typelib_InterfaceTypeDescription * pTypeDescr );
|
|
inline sal_Int32 find( void * iface_ptr, ::std::size_t pos );
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
struct FctPtrHash :
|
|
public ::std::unary_function< const void *, ::std::size_t >
|
|
{
|
|
::std::size_t operator () ( const void * pKey ) const
|
|
{ return (::std::size_t) pKey; }
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
struct FctOUStringHash :
|
|
public ::std::unary_function< const OUString &, ::std::size_t >
|
|
{
|
|
::std::size_t operator () ( const OUString & rKey ) const
|
|
{ return rKey.hashCode(); }
|
|
};
|
|
|
|
// mapping from environment name to environment
|
|
typedef ::std::hash_map<
|
|
OUString, uno_Environment *, FctOUStringHash,
|
|
::std::equal_to< OUString > > OUString2EnvironmentMap;
|
|
|
|
// mapping from ptr to object entry
|
|
typedef ::std::hash_map<
|
|
void *, ObjectEntry *, FctPtrHash,
|
|
::std::equal_to< void * > > Ptr2ObjectMap;
|
|
// mapping from oid to object entry
|
|
typedef ::std::hash_map<
|
|
OUString, ObjectEntry *, FctOUStringHash,
|
|
::std::equal_to< OUString > > OId2ObjectMap;
|
|
|
|
|
|
//==============================================================================
|
|
struct EnvironmentsData
|
|
{
|
|
::osl::Mutex mutex;
|
|
OUString2EnvironmentMap aName2EnvMap;
|
|
|
|
EnvironmentsData() : isDisposing(false) {}
|
|
~EnvironmentsData();
|
|
|
|
inline void getEnvironment(
|
|
uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext );
|
|
inline void registerEnvironment( uno_Environment ** ppEnv );
|
|
inline void getRegisteredEnvironments(
|
|
uno_Environment *** pppEnvs, sal_Int32 * pnLen,
|
|
uno_memAlloc memAlloc, const OUString & rEnvDcp );
|
|
|
|
bool isDisposing;
|
|
};
|
|
|
|
namespace
|
|
{
|
|
struct theEnvironmentsData : public rtl::Static< EnvironmentsData, theEnvironmentsData > {};
|
|
}
|
|
|
|
//==============================================================================
|
|
struct uno_DefaultEnvironment : public uno_ExtEnvironment
|
|
{
|
|
sal_Int32 nRef;
|
|
sal_Int32 nWeakRef;
|
|
|
|
::osl::Mutex mutex;
|
|
Ptr2ObjectMap aPtr2ObjectMap;
|
|
OId2ObjectMap aOId2ObjectMap;
|
|
|
|
uno_DefaultEnvironment(
|
|
const OUString & rEnvDcp_, void * pContext_ );
|
|
~uno_DefaultEnvironment();
|
|
};
|
|
|
|
//______________________________________________________________________________
|
|
inline ObjectEntry::ObjectEntry( OUString const & rOId_ )
|
|
: oid( rOId_ ),
|
|
nRef( 0 ),
|
|
mixedObject( false )
|
|
{
|
|
aInterfaces.reserve( 2 );
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
inline void ObjectEntry::append(
|
|
uno_DefaultEnvironment * pEnv,
|
|
void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
|
|
uno_freeProxyFunc fpFreeProxy )
|
|
{
|
|
InterfaceEntry aNewEntry;
|
|
if (! fpFreeProxy)
|
|
(*pEnv->acquireInterface)( pEnv, pInterface );
|
|
aNewEntry.refCount = 1;
|
|
aNewEntry.pInterface = pInterface;
|
|
aNewEntry.fpFreeProxy = fpFreeProxy;
|
|
typelib_typedescription_acquire( (typelib_TypeDescription *) pTypeDescr );
|
|
aNewEntry.pTypeDescr = pTypeDescr;
|
|
|
|
::std::pair< Ptr2ObjectMap::iterator, bool > insertion(
|
|
pEnv->aPtr2ObjectMap.insert( Ptr2ObjectMap::value_type(
|
|
pInterface, this ) ) );
|
|
OSL_ASSERT( insertion.second ||
|
|
(find( pInterface, 0 ) >= 0 &&
|
|
// points to the same object entry:
|
|
insertion.first->second == this) );
|
|
aInterfaces.push_back( aNewEntry );
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
inline InterfaceEntry * ObjectEntry::find(
|
|
typelib_InterfaceTypeDescription * pTypeDescr_ )
|
|
{
|
|
OSL_ASSERT( ! aInterfaces.empty() );
|
|
if (aInterfaces.empty())
|
|
return 0;
|
|
|
|
// shortcut common case:
|
|
OUString const & type_name =
|
|
OUString::unacquired(
|
|
&((typelib_TypeDescription *) pTypeDescr_)->pTypeName );
|
|
if (type_name.equalsAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ))
|
|
{
|
|
return &aInterfaces[ 0 ];
|
|
}
|
|
|
|
::std::size_t nSize = aInterfaces.size();
|
|
for ( ::std::size_t nPos = 0; nPos < nSize; ++nPos )
|
|
{
|
|
typelib_InterfaceTypeDescription * pITD =
|
|
aInterfaces[ nPos ].pTypeDescr;
|
|
while (pITD)
|
|
{
|
|
if (td_equals( pITD, pTypeDescr_ ))
|
|
return &aInterfaces[ nPos ];
|
|
pITD = pITD->pBaseTypeDescription;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
inline sal_Int32 ObjectEntry::find(
|
|
void * iface_ptr, ::std::size_t pos )
|
|
{
|
|
::std::size_t size = aInterfaces.size();
|
|
for ( ; pos < size; ++pos )
|
|
{
|
|
if (aInterfaces[ pos ].pInterface == iface_ptr)
|
|
return pos;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL defenv_registerInterface(
|
|
uno_ExtEnvironment * pEnv, void ** ppInterface,
|
|
rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
|
|
{
|
|
OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
|
|
OUString const & rOId = OUString::unacquired( &pOId );
|
|
|
|
uno_DefaultEnvironment * that =
|
|
static_cast< uno_DefaultEnvironment * >( pEnv );
|
|
::osl::ClearableMutexGuard guard( that->mutex );
|
|
|
|
// try to insert dummy 0:
|
|
std::pair<OId2ObjectMap::iterator, bool> const insertion(
|
|
that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, 0 ) ) );
|
|
if (insertion.second)
|
|
{
|
|
ObjectEntry * pOEntry = new ObjectEntry( rOId );
|
|
insertion.first->second = pOEntry;
|
|
++pOEntry->nRef; // another register call on object
|
|
pOEntry->append( that, *ppInterface, pTypeDescr, 0 );
|
|
}
|
|
else // object entry exists
|
|
{
|
|
ObjectEntry * pOEntry = insertion.first->second;
|
|
++pOEntry->nRef; // another register call on object
|
|
InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
|
|
|
|
if (pIEntry) // type entry exists
|
|
{
|
|
++pIEntry->refCount;
|
|
if (pIEntry->pInterface != *ppInterface)
|
|
{
|
|
void * pInterface = pIEntry->pInterface;
|
|
(*pEnv->acquireInterface)( pEnv, pInterface );
|
|
guard.clear();
|
|
(*pEnv->releaseInterface)( pEnv, *ppInterface );
|
|
*ppInterface = pInterface;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pOEntry->append( that, *ppInterface, pTypeDescr, 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL defenv_registerProxyInterface(
|
|
uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy,
|
|
rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
|
|
{
|
|
OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy,
|
|
"### null ptr!" );
|
|
OUString const & rOId = OUString::unacquired( &pOId );
|
|
|
|
uno_DefaultEnvironment * that =
|
|
static_cast< uno_DefaultEnvironment * >( pEnv );
|
|
::osl::ClearableMutexGuard guard( that->mutex );
|
|
|
|
// try to insert dummy 0:
|
|
std::pair<OId2ObjectMap::iterator, bool> const insertion(
|
|
that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, 0 ) ) );
|
|
if (insertion.second)
|
|
{
|
|
ObjectEntry * pOEntry = new ObjectEntry( rOId );
|
|
insertion.first->second = pOEntry;
|
|
++pOEntry->nRef; // another register call on object
|
|
pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
|
|
}
|
|
else // object entry exists
|
|
{
|
|
ObjectEntry * pOEntry = insertion.first->second;
|
|
|
|
// first registration was an original, then registerProxyInterface():
|
|
pOEntry->mixedObject |=
|
|
(!pOEntry->aInterfaces.empty() &&
|
|
pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0);
|
|
|
|
++pOEntry->nRef; // another register call on object
|
|
InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
|
|
|
|
if (pIEntry) // type entry exists
|
|
{
|
|
if (pIEntry->pInterface == *ppInterface)
|
|
{
|
|
++pIEntry->refCount;
|
|
}
|
|
else
|
|
{
|
|
void * pInterface = pIEntry->pInterface;
|
|
(*pEnv->acquireInterface)( pEnv, pInterface );
|
|
--pOEntry->nRef; // manual revoke of proxy to be freed
|
|
guard.clear();
|
|
(*freeProxy)( pEnv, *ppInterface );
|
|
*ppInterface = pInterface;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL s_stub_defenv_revokeInterface(va_list * pParam)
|
|
{
|
|
uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
|
|
void * pInterface = va_arg(*pParam, void *);
|
|
|
|
OSL_ENSURE( pEnv && pInterface, "### null ptr!" );
|
|
uno_DefaultEnvironment * that =
|
|
static_cast< uno_DefaultEnvironment * >( pEnv );
|
|
::osl::ClearableMutexGuard guard( that->mutex );
|
|
|
|
Ptr2ObjectMap::const_iterator const iFind(
|
|
that->aPtr2ObjectMap.find( pInterface ) );
|
|
OSL_ASSERT( iFind != that->aPtr2ObjectMap.end() );
|
|
ObjectEntry * pOEntry = iFind->second;
|
|
if (! --pOEntry->nRef)
|
|
{
|
|
// cleanup maps
|
|
that->aOId2ObjectMap.erase( pOEntry->oid );
|
|
sal_Int32 nPos;
|
|
for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
|
|
{
|
|
that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface );
|
|
}
|
|
|
|
// the last proxy interface of the environment might kill this
|
|
// environment, because of releasing its language binding!!!
|
|
guard.clear();
|
|
|
|
// release interfaces
|
|
for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
|
|
{
|
|
InterfaceEntry const & rEntry = pOEntry->aInterfaces[nPos];
|
|
typelib_typedescription_release(
|
|
(typelib_TypeDescription *) rEntry.pTypeDescr );
|
|
if (rEntry.fpFreeProxy) // is proxy or used interface?
|
|
{
|
|
(*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface );
|
|
}
|
|
else
|
|
{
|
|
(*pEnv->releaseInterface)( pEnv, rEntry.pInterface );
|
|
}
|
|
}
|
|
|
|
delete pOEntry;
|
|
}
|
|
else if (pOEntry->mixedObject)
|
|
{
|
|
OSL_ASSERT( !pOEntry->aInterfaces.empty() &&
|
|
pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0 );
|
|
|
|
sal_Int32 index = pOEntry->find( pInterface, 1 );
|
|
OSL_ASSERT( index > 0 );
|
|
if (index > 0)
|
|
{
|
|
InterfaceEntry & entry = pOEntry->aInterfaces[ index ];
|
|
OSL_ASSERT( entry.pInterface == pInterface );
|
|
if (entry.fpFreeProxy != 0)
|
|
{
|
|
--entry.refCount;
|
|
if (entry.refCount == 0)
|
|
{
|
|
uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy;
|
|
typelib_TypeDescription * pTypeDescr =
|
|
reinterpret_cast< typelib_TypeDescription * >(
|
|
entry.pTypeDescr );
|
|
|
|
pOEntry->aInterfaces.erase(
|
|
pOEntry->aInterfaces.begin() + index );
|
|
if (pOEntry->find( pInterface, index ) < 0)
|
|
{
|
|
// proxy ptr not registered for another interface:
|
|
// remove from ptr map
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
::std::size_t erased =
|
|
#endif
|
|
that->aPtr2ObjectMap.erase( pInterface );
|
|
OSL_ASSERT( erased == 1 );
|
|
}
|
|
|
|
guard.clear();
|
|
|
|
typelib_typedescription_release( pTypeDescr );
|
|
(*fpFreeProxy)( pEnv, pInterface );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void SAL_CALL defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface)
|
|
{
|
|
uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL defenv_getObjectIdentifier(
|
|
uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
|
|
{
|
|
OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
|
|
if (*ppOId)
|
|
{
|
|
::rtl_uString_release( *ppOId );
|
|
*ppOId = 0;
|
|
}
|
|
|
|
uno_DefaultEnvironment * that =
|
|
static_cast< uno_DefaultEnvironment * >( pEnv );
|
|
::osl::ClearableMutexGuard guard( that->mutex );
|
|
|
|
Ptr2ObjectMap::const_iterator const iFind(
|
|
that->aPtr2ObjectMap.find( pInterface ) );
|
|
if (iFind == that->aPtr2ObjectMap.end())
|
|
{
|
|
guard.clear();
|
|
(*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface );
|
|
}
|
|
else
|
|
{
|
|
rtl_uString * hstr = iFind->second->oid.pData;
|
|
rtl_uString_acquire( hstr );
|
|
*ppOId = hstr;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL defenv_getRegisteredInterface(
|
|
uno_ExtEnvironment * pEnv, void ** ppInterface,
|
|
rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
|
|
{
|
|
OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
|
|
if (*ppInterface)
|
|
{
|
|
(*pEnv->releaseInterface)( pEnv, *ppInterface );
|
|
*ppInterface = 0;
|
|
}
|
|
|
|
OUString const & rOId = OUString::unacquired( &pOId );
|
|
uno_DefaultEnvironment * that =
|
|
static_cast< uno_DefaultEnvironment * >( pEnv );
|
|
::osl::MutexGuard guard( that->mutex );
|
|
|
|
OId2ObjectMap::const_iterator const iFind
|
|
( that->aOId2ObjectMap.find( rOId ) );
|
|
if (iFind != that->aOId2ObjectMap.end())
|
|
{
|
|
InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr );
|
|
if (pIEntry)
|
|
{
|
|
(*pEnv->acquireInterface)( pEnv, pIEntry->pInterface );
|
|
*ppInterface = pIEntry->pInterface;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL defenv_getRegisteredInterfaces(
|
|
uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen,
|
|
uno_memAlloc memAlloc )
|
|
{
|
|
OSL_ENSURE( pEnv && pppInterfaces && pnLen && memAlloc, "### null ptr!" );
|
|
uno_DefaultEnvironment * that =
|
|
static_cast< uno_DefaultEnvironment * >( pEnv );
|
|
::osl::MutexGuard guard( that->mutex );
|
|
|
|
sal_Int32 nLen = that->aPtr2ObjectMap.size();
|
|
sal_Int32 nPos = 0;
|
|
void ** ppInterfaces = (void **) (*memAlloc)( nLen * sizeof (void *) );
|
|
|
|
Ptr2ObjectMap::const_iterator iPos( that->aPtr2ObjectMap.begin() );
|
|
Ptr2ObjectMap::const_iterator const iEnd( that->aPtr2ObjectMap.end() );
|
|
while (iPos != iEnd)
|
|
{
|
|
(*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos++] = (*iPos).first );
|
|
++iPos;
|
|
}
|
|
|
|
*pppInterfaces = ppInterfaces;
|
|
*pnLen = nLen;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL defenv_acquire( uno_Environment * pEnv )
|
|
{
|
|
uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
|
|
::osl_incrementInterlockedCount( &that->nWeakRef );
|
|
::osl_incrementInterlockedCount( &that->nRef );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL defenv_release( uno_Environment * pEnv )
|
|
{
|
|
uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
|
|
if (! ::osl_decrementInterlockedCount( &that->nRef ))
|
|
{
|
|
// invoke dispose callback
|
|
if (pEnv->environmentDisposing)
|
|
{
|
|
(*pEnv->environmentDisposing)( pEnv );
|
|
}
|
|
|
|
OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" );
|
|
}
|
|
// free memory if no weak refs left
|
|
if (! ::osl_decrementInterlockedCount( &that->nWeakRef ))
|
|
{
|
|
delete that;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL defenv_acquireWeak( uno_Environment * pEnv )
|
|
{
|
|
uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
|
|
::osl_incrementInterlockedCount( &that->nWeakRef );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL defenv_releaseWeak( uno_Environment * pEnv )
|
|
{
|
|
uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
|
|
if (! ::osl_decrementInterlockedCount( &that->nWeakRef ))
|
|
{
|
|
delete that;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL defenv_harden(
|
|
uno_Environment ** ppHardEnv, uno_Environment * pEnv )
|
|
{
|
|
if (*ppHardEnv)
|
|
{
|
|
(*(*ppHardEnv)->release)( *ppHardEnv );
|
|
*ppHardEnv = 0;
|
|
}
|
|
|
|
EnvironmentsData & rData = theEnvironmentsData::get();
|
|
|
|
if (rData.isDisposing)
|
|
return;
|
|
|
|
uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
|
|
{
|
|
::osl::MutexGuard guard( rData.mutex );
|
|
if (1 == ::osl_incrementInterlockedCount( &that->nRef )) // is dead
|
|
{
|
|
that->nRef = 0;
|
|
return;
|
|
}
|
|
}
|
|
::osl_incrementInterlockedCount( &that->nWeakRef );
|
|
*ppHardEnv = pEnv;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL defenv_dispose( uno_Environment * )
|
|
{
|
|
}
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
uno_DefaultEnvironment::uno_DefaultEnvironment(
|
|
const OUString & rEnvDcp_, void * pContext_ )
|
|
: nRef( 0 ),
|
|
nWeakRef( 0 )
|
|
{
|
|
uno_Environment * that = reinterpret_cast< uno_Environment * >(this);
|
|
that->pReserved = 0;
|
|
// functions
|
|
that->acquire = defenv_acquire;
|
|
that->release = defenv_release;
|
|
that->acquireWeak = defenv_acquireWeak;
|
|
that->releaseWeak = defenv_releaseWeak;
|
|
that->harden = defenv_harden;
|
|
that->dispose = defenv_dispose;
|
|
that->pExtEnv = this;
|
|
// identifier
|
|
::rtl_uString_acquire( rEnvDcp_.pData );
|
|
that->pTypeName = rEnvDcp_.pData;
|
|
that->pContext = pContext_;
|
|
|
|
// will be late initialized
|
|
that->environmentDisposing = 0;
|
|
|
|
uno_ExtEnvironment::registerInterface = defenv_registerInterface;
|
|
uno_ExtEnvironment::registerProxyInterface = defenv_registerProxyInterface;
|
|
uno_ExtEnvironment::revokeInterface = defenv_revokeInterface;
|
|
uno_ExtEnvironment::getObjectIdentifier = defenv_getObjectIdentifier;
|
|
uno_ExtEnvironment::getRegisteredInterface = defenv_getRegisteredInterface;
|
|
uno_ExtEnvironment::getRegisteredInterfaces =
|
|
defenv_getRegisteredInterfaces;
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
uno_DefaultEnvironment::~uno_DefaultEnvironment()
|
|
{
|
|
::rtl_uString_release( ((uno_Environment *) this)->pTypeName );
|
|
}
|
|
|
|
//==============================================================================
|
|
static void writeLine(
|
|
void * stream, const sal_Char * pLine, const sal_Char * pFilter )
|
|
{
|
|
if (pFilter && *pFilter)
|
|
{
|
|
// lookup pFilter in pLine
|
|
while (*pLine)
|
|
{
|
|
if (*pLine == *pFilter)
|
|
{
|
|
sal_Int32 nPos = 1;
|
|
while (pLine[nPos] && pFilter[nPos] == pLine[nPos])
|
|
{
|
|
++nPos;
|
|
}
|
|
if (! pFilter[nPos])
|
|
{
|
|
if (stream)
|
|
{
|
|
fprintf( (FILE *) stream, "%s\n", pLine );
|
|
}
|
|
else
|
|
{
|
|
OSL_TRACE( pLine );
|
|
OSL_TRACE( "\n" );
|
|
}
|
|
}
|
|
}
|
|
++pLine;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (stream)
|
|
{
|
|
fprintf( (FILE *) stream, "%s\n", pLine );
|
|
}
|
|
else
|
|
{
|
|
fprintf( stderr, "%s\n", pLine );
|
|
}
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
static void writeLine(
|
|
void * stream, const OUString & rLine, const sal_Char * pFilter )
|
|
{
|
|
::rtl::OString aLine( ::rtl::OUStringToOString(
|
|
rLine, RTL_TEXTENCODING_ASCII_US ) );
|
|
writeLine( stream, aLine.getStr(), pFilter );
|
|
}
|
|
|
|
//##############################################################################
|
|
extern "C" void SAL_CALL uno_dumpEnvironment(
|
|
void * stream, uno_Environment * pEnv, const sal_Char * pFilter )
|
|
SAL_THROW_EXTERN_C()
|
|
{
|
|
OSL_ENSURE( pEnv, "### null ptr!" );
|
|
::rtl::OUStringBuffer buf;
|
|
|
|
if (! pEnv->pExtEnv)
|
|
{
|
|
writeLine( stream, "###################################"
|
|
"###########################################", pFilter );
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment: ") );
|
|
buf.append( pEnv->pTypeName );
|
|
writeLine( stream, buf.makeStringAndClear(), pFilter );
|
|
writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter );
|
|
return;
|
|
}
|
|
|
|
writeLine( stream, "########################################"
|
|
"######################################", pFilter );
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment dump: ") );
|
|
buf.append( pEnv->pTypeName );
|
|
writeLine( stream, buf.makeStringAndClear(), pFilter );
|
|
|
|
uno_DefaultEnvironment * that =
|
|
reinterpret_cast< uno_DefaultEnvironment * >(pEnv);
|
|
::osl::MutexGuard guard( that->mutex );
|
|
|
|
Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap );
|
|
OId2ObjectMap::const_iterator iPos( that->aOId2ObjectMap.begin() );
|
|
while (iPos != that->aOId2ObjectMap.end())
|
|
{
|
|
ObjectEntry * pOEntry = iPos->second;
|
|
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("+ ") );
|
|
if (pOEntry->mixedObject)
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("mixed ") );
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("object entry: nRef=") );
|
|
buf.append( pOEntry->nRef, 10 );
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; oid=\"") );
|
|
buf.append( pOEntry->oid );
|
|
buf.append( (sal_Unicode) '\"' );
|
|
writeLine( stream, buf.makeStringAndClear(), pFilter );
|
|
|
|
for ( ::std::size_t nPos = 0;
|
|
nPos < pOEntry->aInterfaces.size(); ++nPos )
|
|
{
|
|
const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos];
|
|
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" - ") );
|
|
buf.append(
|
|
((typelib_TypeDescription *) rIEntry.pTypeDescr)->pTypeName );
|
|
if (rIEntry.fpFreeProxy)
|
|
{
|
|
buf.appendAscii(
|
|
RTL_CONSTASCII_STRINGPARAM("; proxy free=0x") );
|
|
buf.append(
|
|
reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 );
|
|
}
|
|
else
|
|
{
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; original") );
|
|
}
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; ptr=0x") );
|
|
buf.append(
|
|
reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 );
|
|
|
|
if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0)
|
|
{
|
|
::std::size_t erased = ptr2obj.erase( rIEntry.pInterface );
|
|
if (erased != 1)
|
|
{
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
|
|
" (ptr not found in map!)") );
|
|
}
|
|
}
|
|
writeLine( stream, buf.makeStringAndClear(), pFilter );
|
|
}
|
|
++iPos;
|
|
}
|
|
if (! ptr2obj.empty())
|
|
writeLine( stream, "ptr map inconsistency!!!", pFilter );
|
|
writeLine( stream, "#####################################"
|
|
"#########################################", pFilter );
|
|
}
|
|
|
|
//##############################################################################
|
|
extern "C" void SAL_CALL uno_dumpEnvironmentByName(
|
|
void * stream, rtl_uString * pEnvDcp, const sal_Char * pFilter )
|
|
SAL_THROW_EXTERN_C()
|
|
{
|
|
uno_Environment * pEnv = 0;
|
|
uno_getEnvironment( &pEnv, pEnvDcp, 0 );
|
|
if (pEnv)
|
|
{
|
|
::uno_dumpEnvironment( stream, pEnv, pFilter );
|
|
(*pEnv->release)( pEnv );
|
|
}
|
|
else
|
|
{
|
|
::rtl::OUStringBuffer buf( 32 );
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment \"") );
|
|
buf.append( pEnvDcp );
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" does not exist!") );
|
|
writeLine( stream, buf.makeStringAndClear(), pFilter );
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
inline static const OUString & unoenv_getStaticOIdPart()
|
|
{
|
|
static OUString * s_pStaticOidPart = 0;
|
|
if (! s_pStaticOidPart)
|
|
{
|
|
::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
|
|
if (! s_pStaticOidPart)
|
|
{
|
|
::rtl::OUStringBuffer aRet( 64 );
|
|
aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") );
|
|
// pid
|
|
oslProcessInfo info;
|
|
info.Size = sizeof(oslProcessInfo);
|
|
if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER, &info ) ==
|
|
osl_Process_E_None)
|
|
{
|
|
aRet.append( (sal_Int64)info.Ident, 16 );
|
|
}
|
|
else
|
|
{
|
|
aRet.appendAscii(
|
|
RTL_CONSTASCII_STRINGPARAM("unknown process id") );
|
|
}
|
|
// good guid
|
|
sal_uInt8 ar[16];
|
|
::rtl_getGlobalProcessId( ar );
|
|
aRet.append( (sal_Unicode)';' );
|
|
for ( sal_Int32 i = 0; i < 16; ++i )
|
|
aRet.append( (sal_Int32)ar[i], 16 );
|
|
|
|
static OUString s_aStaticOidPart( aRet.makeStringAndClear() );
|
|
s_pStaticOidPart = &s_aStaticOidPart;
|
|
}
|
|
}
|
|
return *s_pStaticOidPart;
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
|
|
//------------------------------------------------------------------------------
|
|
static void SAL_CALL unoenv_computeObjectIdentifier(
|
|
uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
|
|
{
|
|
OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
|
|
if (*ppOId)
|
|
{
|
|
::rtl_uString_release( *ppOId );
|
|
*ppOId = 0;
|
|
}
|
|
|
|
uno_Interface * pUnoI = (uno_Interface *)
|
|
::cppu::binuno_queryInterface(
|
|
pInterface, *typelib_static_type_getByTypeClass(
|
|
typelib_TypeClass_INTERFACE ) );
|
|
if (0 != pUnoI)
|
|
{
|
|
(*pUnoI->release)( pUnoI );
|
|
// interface
|
|
::rtl::OUStringBuffer oid( 64 );
|
|
oid.append( reinterpret_cast< sal_Int64 >(pUnoI), 16 );
|
|
oid.append( static_cast< sal_Unicode >(';') );
|
|
// environment[context]
|
|
oid.append( ((uno_Environment *) pEnv)->pTypeName );
|
|
oid.append( static_cast< sal_Unicode >('[') );
|
|
oid.append( reinterpret_cast< sal_Int64 >(
|
|
reinterpret_cast<
|
|
uno_Environment * >(pEnv)->pContext ), 16 );
|
|
// process;good guid
|
|
oid.append( unoenv_getStaticOIdPart() );
|
|
OUString aStr( oid.makeStringAndClear() );
|
|
::rtl_uString_acquire( *ppOId = aStr.pData );
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
static void SAL_CALL unoenv_acquireInterface(
|
|
uno_ExtEnvironment *, void * pUnoI_ )
|
|
{
|
|
uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_);
|
|
(*pUnoI->acquire)( pUnoI );
|
|
}
|
|
|
|
//==============================================================================
|
|
static void SAL_CALL unoenv_releaseInterface(
|
|
uno_ExtEnvironment *, void * pUnoI_ )
|
|
{
|
|
uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_);
|
|
(*pUnoI->release)( pUnoI );
|
|
}
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
EnvironmentsData::~EnvironmentsData()
|
|
{
|
|
::osl::MutexGuard guard( mutex );
|
|
isDisposing = true;
|
|
|
|
for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
|
|
iPos != aName2EnvMap.end(); ++iPos )
|
|
{
|
|
uno_Environment * pWeak = iPos->second;
|
|
uno_Environment * pHard = 0;
|
|
(*pWeak->harden)( &pHard, pWeak );
|
|
(*pWeak->releaseWeak)( pWeak );
|
|
|
|
if (pHard)
|
|
{
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
::uno_dumpEnvironment( 0, pHard, 0 );
|
|
#endif
|
|
(*pHard->dispose)( pHard ); // send explicit dispose
|
|
(*pHard->release)( pHard );
|
|
}
|
|
}
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
inline void EnvironmentsData::getEnvironment(
|
|
uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext )
|
|
{
|
|
if (*ppEnv)
|
|
{
|
|
(*(*ppEnv)->release)( *ppEnv );
|
|
*ppEnv = 0;
|
|
}
|
|
|
|
OUString aKey(
|
|
OUString::valueOf( reinterpret_cast< sal_IntPtr >(pContext) ) );
|
|
aKey += rEnvDcp;
|
|
|
|
// try to find registered mapping
|
|
OUString2EnvironmentMap::const_iterator const iFind(
|
|
aName2EnvMap.find( aKey ) );
|
|
if (iFind != aName2EnvMap.end())
|
|
{
|
|
uno_Environment * pWeak = iFind->second;
|
|
(*pWeak->harden)( ppEnv, pWeak );
|
|
}
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
inline void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv )
|
|
{
|
|
OSL_ENSURE( ppEnv, "### null ptr!" );
|
|
uno_Environment * pEnv = *ppEnv;
|
|
|
|
OUString aKey(
|
|
OUString::valueOf( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) );
|
|
aKey += pEnv->pTypeName;
|
|
|
|
// try to find registered environment
|
|
OUString2EnvironmentMap::const_iterator const iFind(
|
|
aName2EnvMap.find( aKey ) );
|
|
if (iFind == aName2EnvMap.end())
|
|
{
|
|
(*pEnv->acquireWeak)( pEnv );
|
|
::std::pair< OUString2EnvironmentMap::iterator, bool > insertion(
|
|
aName2EnvMap.insert(
|
|
OUString2EnvironmentMap::value_type( aKey, pEnv ) ) );
|
|
OSL_ENSURE(
|
|
insertion.second, "### insertion of env into map failed?!" );
|
|
}
|
|
else
|
|
{
|
|
uno_Environment * pHard = 0;
|
|
uno_Environment * pWeak = iFind->second;
|
|
(*pWeak->harden)( &pHard, pWeak );
|
|
if (pHard)
|
|
{
|
|
if (pEnv)
|
|
(*pEnv->release)( pEnv );
|
|
*ppEnv = pHard;
|
|
}
|
|
else // registered one is dead
|
|
{
|
|
(*pWeak->releaseWeak)( pWeak );
|
|
(*pEnv->acquireWeak)( pEnv );
|
|
aName2EnvMap[ aKey ] = pEnv;
|
|
}
|
|
}
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
inline void EnvironmentsData::getRegisteredEnvironments(
|
|
uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
|
|
const OUString & rEnvDcp )
|
|
{
|
|
OSL_ENSURE( pppEnvs && pnLen && memAlloc, "### null ptr!" );
|
|
|
|
// max size
|
|
uno_Environment ** ppFound = (uno_Environment **)alloca(
|
|
sizeof(uno_Environment *) * aName2EnvMap.size() );
|
|
sal_Int32 nSize = 0;
|
|
|
|
// find matching environment
|
|
for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
|
|
iPos != aName2EnvMap.end(); ++iPos )
|
|
{
|
|
uno_Environment * pWeak = iPos->second;
|
|
if (!rEnvDcp.getLength() ||
|
|
rEnvDcp.equals( pWeak->pTypeName ))
|
|
{
|
|
ppFound[nSize] = 0;
|
|
(*pWeak->harden)( &ppFound[nSize], pWeak );
|
|
if (ppFound[nSize])
|
|
++nSize;
|
|
}
|
|
}
|
|
|
|
*pnLen = nSize;
|
|
if (nSize)
|
|
{
|
|
*pppEnvs = (uno_Environment **) (*memAlloc)(
|
|
sizeof (uno_Environment *) * nSize );
|
|
OSL_ASSERT( *pppEnvs );
|
|
while (nSize--)
|
|
{
|
|
(*pppEnvs)[nSize] = ppFound[nSize];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pppEnvs = 0;
|
|
}
|
|
}
|
|
|
|
static bool loadEnv(OUString const & cLibStem,
|
|
uno_Environment * pEnv,
|
|
void * /*pContext*/)
|
|
{
|
|
// late init with some code from matching uno language binding
|
|
// will be unloaded by environment
|
|
oslModule hMod = cppu::detail::loadModule( cLibStem );
|
|
|
|
if (!hMod)
|
|
return false;
|
|
|
|
OUString aSymbolName(RTL_CONSTASCII_USTRINGPARAM(UNO_INIT_ENVIRONMENT));
|
|
uno_initEnvironmentFunc fpInit = (uno_initEnvironmentFunc)
|
|
::osl_getFunctionSymbol( hMod, aSymbolName.pData );
|
|
if (!fpInit)
|
|
{
|
|
::osl_unloadModule( hMod );
|
|
return false;
|
|
}
|
|
|
|
(*fpInit)( pEnv ); // init of environment
|
|
::rtl_registerModuleForUnloading( hMod );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
{
|
|
|
|
//------------------------------------------------------------------------------
|
|
static uno_Environment * initDefaultEnvironment(
|
|
const OUString & rEnvDcp, void * pContext )
|
|
{
|
|
uno_Environment * pEnv = &(new uno_DefaultEnvironment( rEnvDcp, pContext ))->aBase;
|
|
(*pEnv->acquire)( pEnv );
|
|
|
|
OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp);
|
|
|
|
// create default environment
|
|
if (envTypeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ))
|
|
{
|
|
uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
|
|
that->computeObjectIdentifier = unoenv_computeObjectIdentifier;
|
|
that->acquireInterface = unoenv_acquireInterface;
|
|
that->releaseInterface = unoenv_releaseInterface;
|
|
|
|
OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp);
|
|
if (envPurpose.getLength())
|
|
{
|
|
rtl::OUString libStem = envPurpose.copy(envPurpose.lastIndexOf(':') + 1);
|
|
libStem += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_uno_uno") );
|
|
|
|
if(!loadEnv(libStem, pEnv, pContext))
|
|
{
|
|
pEnv->release(pEnv);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// late init with some code from matching uno language binding
|
|
::rtl::OUStringBuffer aLibName( 16 );
|
|
aLibName.append( envTypeName );
|
|
aLibName.appendAscii( RTL_CONSTASCII_STRINGPARAM("_uno" ) );
|
|
OUString aStr( aLibName.makeStringAndClear() );
|
|
|
|
if (!loadEnv(aStr, pEnv, pContext))
|
|
{
|
|
pEnv->release(pEnv);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return pEnv;
|
|
}
|
|
|
|
//##############################################################################
|
|
void SAL_CALL uno_createEnvironment(
|
|
uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
|
|
SAL_THROW_EXTERN_C()
|
|
{
|
|
OSL_ENSURE( ppEnv, "### null ptr!" );
|
|
if (*ppEnv)
|
|
(*(*ppEnv)->release)( *ppEnv );
|
|
|
|
OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
|
|
*ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
|
|
}
|
|
|
|
//##############################################################################
|
|
void SAL_CALL uno_direct_getEnvironment(
|
|
uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
|
|
SAL_THROW_EXTERN_C()
|
|
{
|
|
OSL_ENSURE( ppEnv, "### null ptr!" );
|
|
OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
|
|
|
|
EnvironmentsData & rData = theEnvironmentsData::get();
|
|
|
|
::osl::MutexGuard guard( rData.mutex );
|
|
rData.getEnvironment( ppEnv, rEnvDcp, pContext );
|
|
if (! *ppEnv)
|
|
{
|
|
*ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
|
|
if (*ppEnv)
|
|
{
|
|
// register new environment:
|
|
rData.registerEnvironment( ppEnv );
|
|
}
|
|
}
|
|
}
|
|
|
|
//##############################################################################
|
|
void SAL_CALL uno_getRegisteredEnvironments(
|
|
uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
|
|
rtl_uString * pEnvDcp )
|
|
SAL_THROW_EXTERN_C()
|
|
{
|
|
EnvironmentsData & rData = theEnvironmentsData::get();
|
|
|
|
::osl::MutexGuard guard( rData.mutex );
|
|
rData.getRegisteredEnvironments(
|
|
pppEnvs, pnLen, memAlloc,
|
|
(pEnvDcp ? OUString(pEnvDcp) : OUString()) );
|
|
}
|
|
|
|
} // extern "C"
|
|
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|