1*54c06456SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*54c06456SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*54c06456SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*54c06456SAndrew Rist * distributed with this work for additional information 6*54c06456SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*54c06456SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*54c06456SAndrew Rist * "License"); you may not use this file except in compliance 9*54c06456SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*54c06456SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*54c06456SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*54c06456SAndrew Rist * software distributed under the License is distributed on an 15*54c06456SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*54c06456SAndrew Rist * KIND, either express or implied. See the License for the 17*54c06456SAndrew Rist * specific language governing permissions and limitations 18*54c06456SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*54c06456SAndrew Rist *************************************************************/ 21*54c06456SAndrew Rist 22*54c06456SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_cli_ure.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <vcclr.h> 28cdf0e10cSrcweir //ToDo: remove when build with .NET 2 29cdf0e10cSrcweir #pragma warning(push, 1) 30cdf0e10cSrcweir #include <windows.h> 31cdf0e10cSrcweir #include "uno/environment.hxx" 32cdf0e10cSrcweir #pragma warning(pop) 33cdf0e10cSrcweir #include "rtl/unload.h" 34cdf0e10cSrcweir #include "uno/lbnames.h" 35cdf0e10cSrcweir #include "uno/mapping.hxx" 36cdf0e10cSrcweir #include "typelib/typedescription.hxx" 37cdf0e10cSrcweir #include "rtl/ustring.hxx" 38cdf0e10cSrcweir 39cdf0e10cSrcweir #include "cli_bridge.h" 40cdf0e10cSrcweir #include "cli_proxy.h" 41cdf0e10cSrcweir namespace srr= System::Runtime::Remoting; 42cdf0e10cSrcweir namespace srrp= System::Runtime::Remoting::Proxies; 43cdf0e10cSrcweir #using <mscorlib.dll> 44cdf0e10cSrcweir #if defined(_MSC_VER) && (_MSC_VER < 1400) 45cdf0e10cSrcweir #include <_vcclrit.h> 46cdf0e10cSrcweir #endif 47cdf0e10cSrcweir 48cdf0e10cSrcweir namespace cssu= com::sun::star::uno; 49cdf0e10cSrcweir 50cdf0e10cSrcweir 51cdf0e10cSrcweir namespace sri= System::Runtime::InteropServices; 52cdf0e10cSrcweir using namespace rtl; 53cdf0e10cSrcweir 54cdf0e10cSrcweir namespace cli_uno 55cdf0e10cSrcweir { 56cdf0e10cSrcweir 57cdf0e10cSrcweir extern "C" 58cdf0e10cSrcweir { 59cdf0e10cSrcweir void SAL_CALL Mapping_acquire( uno_Mapping * mapping ) 60cdf0e10cSrcweir SAL_THROW_EXTERN_C() 61cdf0e10cSrcweir { 62cdf0e10cSrcweir Mapping const * that = static_cast< Mapping const * >( mapping ); 63cdf0e10cSrcweir that->m_bridge->acquire(); 64cdf0e10cSrcweir } 65cdf0e10cSrcweir //-------------------------------------------------------------------------------------------------- 66cdf0e10cSrcweir void SAL_CALL Mapping_release( uno_Mapping * mapping ) 67cdf0e10cSrcweir SAL_THROW_EXTERN_C() 68cdf0e10cSrcweir { 69cdf0e10cSrcweir Mapping const * that = static_cast< Mapping const * >( mapping ); 70cdf0e10cSrcweir that->m_bridge->release(); 71cdf0e10cSrcweir } 72cdf0e10cSrcweir 73cdf0e10cSrcweir 74cdf0e10cSrcweir //-------------------------------------------------------------------------------------------------- 75cdf0e10cSrcweir void SAL_CALL Mapping_cli2uno( 76cdf0e10cSrcweir uno_Mapping * mapping, void ** ppOut, 77cdf0e10cSrcweir void * pIn, typelib_InterfaceTypeDescription * td ) 78cdf0e10cSrcweir SAL_THROW_EXTERN_C() 79cdf0e10cSrcweir { 80cdf0e10cSrcweir uno_Interface ** ppUnoI = (uno_Interface **)ppOut; 81cdf0e10cSrcweir intptr_t cliI = (intptr_t)pIn; 82cdf0e10cSrcweir 83cdf0e10cSrcweir OSL_ENSURE( ppUnoI && td, "### null ptr!" ); 84cdf0e10cSrcweir 85cdf0e10cSrcweir if (0 != *ppUnoI) 86cdf0e10cSrcweir { 87cdf0e10cSrcweir uno_Interface * pUnoI = *(uno_Interface **)ppUnoI; 88cdf0e10cSrcweir (*pUnoI->release)( pUnoI ); 89cdf0e10cSrcweir *ppUnoI = 0; 90cdf0e10cSrcweir } 91cdf0e10cSrcweir try 92cdf0e10cSrcweir { 93cdf0e10cSrcweir Mapping const * that = static_cast< Mapping const * >( mapping ); 94cdf0e10cSrcweir Bridge * bridge = that->m_bridge; 95cdf0e10cSrcweir 96cdf0e10cSrcweir if (0 != cliI) 97cdf0e10cSrcweir { 98cdf0e10cSrcweir System::Object* cliObj= sri::GCHandle::op_Explicit(cliI).Target; 99cdf0e10cSrcweir (*ppOut)= bridge->map_cli2uno(cliObj, (typelib_TypeDescription*) td); 100cdf0e10cSrcweir } 101cdf0e10cSrcweir } 102cdf0e10cSrcweir catch (BridgeRuntimeError & err) 103cdf0e10cSrcweir { 104cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 1 105cdf0e10cSrcweir OString cstr_msg( 106cdf0e10cSrcweir OUStringToOString( 107cdf0e10cSrcweir OUSTR("[cli_uno bridge error] ") + err.m_message, RTL_TEXTENCODING_ASCII_US ) ); 108cdf0e10cSrcweir OSL_ENSURE( 0, cstr_msg.getStr() ); 109cdf0e10cSrcweir #else 110cdf0e10cSrcweir (void) err; // unused 111cdf0e10cSrcweir #endif 112cdf0e10cSrcweir } 113cdf0e10cSrcweir } 114cdf0e10cSrcweir //-------------------------------------------------------------------------------------------------- 115cdf0e10cSrcweir void SAL_CALL Mapping_uno2cli( 116cdf0e10cSrcweir uno_Mapping * mapping, void ** ppOut, 117cdf0e10cSrcweir void * pIn, typelib_InterfaceTypeDescription * td ) 118cdf0e10cSrcweir SAL_THROW_EXTERN_C() 119cdf0e10cSrcweir { 120cdf0e10cSrcweir try 121cdf0e10cSrcweir { 122cdf0e10cSrcweir OSL_ENSURE( td && ppOut, "### null ptr!" ); 123cdf0e10cSrcweir OSL_ENSURE( (sizeof(System::Char) == sizeof(sal_Unicode)) 124cdf0e10cSrcweir && (sizeof(System::Boolean) == sizeof(sal_Bool)) 125cdf0e10cSrcweir && (sizeof(System::SByte) == sizeof(sal_Int8)) 126cdf0e10cSrcweir && (sizeof(System::Int16) == sizeof(sal_Int16)) 127cdf0e10cSrcweir && (sizeof(System::UInt16) == sizeof(sal_uInt16)) 128cdf0e10cSrcweir && (sizeof(System::Int32) == sizeof(sal_Int32)) 129cdf0e10cSrcweir && (sizeof(System::UInt32) == sizeof(sal_uInt32)) 130cdf0e10cSrcweir && (sizeof(System::Int64) == sizeof(sal_Int64)) 131cdf0e10cSrcweir && (sizeof(System::UInt64) == sizeof(sal_uInt64)) 132cdf0e10cSrcweir && (sizeof(System::Single) == sizeof(float)) 133cdf0e10cSrcweir && (sizeof(System::Double) == sizeof(double)), 134cdf0e10cSrcweir "[cli_uno bridge] incompatible .NET data types"); 135cdf0e10cSrcweir intptr_t * ppDNetI = (intptr_t *)ppOut; 136cdf0e10cSrcweir uno_Interface * pUnoI = (uno_Interface *)pIn; 137cdf0e10cSrcweir 138cdf0e10cSrcweir Mapping const * that = static_cast< Mapping const * >( mapping ); 139cdf0e10cSrcweir Bridge * bridge = that->m_bridge; 140cdf0e10cSrcweir 141cdf0e10cSrcweir if (0 != *ppDNetI) 142cdf0e10cSrcweir { 143cdf0e10cSrcweir sri::GCHandle::op_Explicit(ppDNetI).Free(); 144cdf0e10cSrcweir } 145cdf0e10cSrcweir 146cdf0e10cSrcweir if (0 != pUnoI) 147cdf0e10cSrcweir { 148cdf0e10cSrcweir System::Object* cliI= bridge->map_uno2cli(pUnoI, td); 149cdf0e10cSrcweir intptr_t ptr= NULL; 150cdf0e10cSrcweir if(cliI) 151cdf0e10cSrcweir { 152cdf0e10cSrcweir ptr= sri::GCHandle::op_Explicit(sri::GCHandle::Alloc(cliI)) 153cdf0e10cSrcweir #ifdef _WIN32 154cdf0e10cSrcweir .ToInt32(); 155cdf0e10cSrcweir #else /* defined(_WIN64) */ .ToInt64(); 156cdf0e10cSrcweir #endif 157cdf0e10cSrcweir } 158cdf0e10cSrcweir (*ppOut)= reinterpret_cast<void*>(ptr); 159cdf0e10cSrcweir } 160cdf0e10cSrcweir } 161cdf0e10cSrcweir catch (BridgeRuntimeError & err) 162cdf0e10cSrcweir { 163cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 1 164cdf0e10cSrcweir rtl::OString cstr_msg( 165cdf0e10cSrcweir rtl::OUStringToOString( 166cdf0e10cSrcweir OUSTR("[cli_uno bridge error] ") + err.m_message, RTL_TEXTENCODING_ASCII_US ) ); 167cdf0e10cSrcweir OSL_ENSURE( 0, cstr_msg.getStr() ); 168cdf0e10cSrcweir #else 169cdf0e10cSrcweir (void) err; // unused 170cdf0e10cSrcweir #endif 171cdf0e10cSrcweir } 172cdf0e10cSrcweir } 173cdf0e10cSrcweir 174cdf0e10cSrcweir //__________________________________________________________________________________________________ 175cdf0e10cSrcweir void SAL_CALL Bridge_free( uno_Mapping * mapping ) 176cdf0e10cSrcweir SAL_THROW_EXTERN_C() 177cdf0e10cSrcweir { 178cdf0e10cSrcweir Mapping * that = static_cast< Mapping * >( mapping ); 179cdf0e10cSrcweir delete that->m_bridge; 180cdf0e10cSrcweir } 181cdf0e10cSrcweir 182cdf0e10cSrcweir } //extern C 183cdf0e10cSrcweir } //namespace 184cdf0e10cSrcweir 185cdf0e10cSrcweir namespace cli_uno 186cdf0e10cSrcweir { 187cdf0e10cSrcweir 188cdf0e10cSrcweir //__________________________________________________________________________________________________ 189cdf0e10cSrcweir /** ToDo 190cdf0e10cSrcweir I doubt that the the case that the ref count raises from 0 to 1 191cdf0e10cSrcweir can occur. uno_ext_getMapping returns an acquired mapping. Every time 192cdf0e10cSrcweir that function is called then a new mapping is created. Following the 193cdf0e10cSrcweir rules of ref counted objects, then if the ref count is null noone has 194cdf0e10cSrcweir a reference to the object anymore. Hence noone can call acquire. If someone 195cdf0e10cSrcweir calls acquire then they must have kept an unacquired pointer which is 196cdf0e10cSrcweir illegal. 197cdf0e10cSrcweir */ 198cdf0e10cSrcweir void Bridge::acquire() const SAL_THROW( () ) 199cdf0e10cSrcweir { 200cdf0e10cSrcweir if (1 == osl_incrementInterlockedCount( &m_ref )) 201cdf0e10cSrcweir { 202cdf0e10cSrcweir if (m_registered_cli2uno) 203cdf0e10cSrcweir { 204cdf0e10cSrcweir uno_Mapping * mapping = const_cast<Mapping*>(&m_cli2uno); 205cdf0e10cSrcweir uno_registerMapping( 206cdf0e10cSrcweir & const_cast<uno_Mapping*>(mapping), Bridge_free, m_uno_cli_env, (uno_Environment *)m_uno_env, 0 ); 207cdf0e10cSrcweir } 208cdf0e10cSrcweir else 209cdf0e10cSrcweir { 210cdf0e10cSrcweir uno_Mapping * mapping = const_cast<Mapping*>(&m_uno2cli); 211cdf0e10cSrcweir uno_registerMapping( 212cdf0e10cSrcweir &mapping, Bridge_free, (uno_Environment *)m_uno_env, m_uno_cli_env, 0 ); 213cdf0e10cSrcweir } 214cdf0e10cSrcweir } 215cdf0e10cSrcweir } 216cdf0e10cSrcweir //__________________________________________________________________________________________________ 217cdf0e10cSrcweir void Bridge::release() const SAL_THROW( () ) 218cdf0e10cSrcweir { 219cdf0e10cSrcweir if (! osl_decrementInterlockedCount( &m_ref )) 220cdf0e10cSrcweir { 221cdf0e10cSrcweir uno_revokeMapping( 222cdf0e10cSrcweir m_registered_cli2uno 223cdf0e10cSrcweir ? const_cast<Mapping*>(&m_cli2uno) 224cdf0e10cSrcweir : const_cast<Mapping*>(&m_uno2cli) ); 225cdf0e10cSrcweir } 226cdf0e10cSrcweir } 227cdf0e10cSrcweir //__________________________________________________________________________________________________ 228cdf0e10cSrcweir Bridge::Bridge( 229cdf0e10cSrcweir uno_Environment * uno_cli_env, uno_ExtEnvironment * uno_env, 230cdf0e10cSrcweir bool registered_cli2uno ) 231cdf0e10cSrcweir : m_ref( 1 ), 232cdf0e10cSrcweir m_uno_env( uno_env ), 233cdf0e10cSrcweir m_uno_cli_env( uno_cli_env ), 234cdf0e10cSrcweir m_registered_cli2uno( registered_cli2uno ) 235cdf0e10cSrcweir { 236cdf0e10cSrcweir OSL_ASSERT( 0 != m_uno_cli_env && 0 != m_uno_env ); 237cdf0e10cSrcweir (*((uno_Environment *)m_uno_env)->acquire)( (uno_Environment *)m_uno_env ); 238cdf0e10cSrcweir (*m_uno_cli_env->acquire)( m_uno_cli_env ); 239cdf0e10cSrcweir 240cdf0e10cSrcweir // cli2uno 241cdf0e10cSrcweir m_cli2uno.acquire = Mapping_acquire; 242cdf0e10cSrcweir m_cli2uno.release = Mapping_release; 243cdf0e10cSrcweir m_cli2uno.mapInterface = Mapping_cli2uno; 244cdf0e10cSrcweir m_cli2uno.m_bridge = this; 245cdf0e10cSrcweir // uno2cli 246cdf0e10cSrcweir m_uno2cli.acquire = Mapping_acquire; 247cdf0e10cSrcweir m_uno2cli.release = Mapping_release; 248cdf0e10cSrcweir m_uno2cli.mapInterface = Mapping_uno2cli; 249cdf0e10cSrcweir m_uno2cli.m_bridge = this; 250cdf0e10cSrcweir 251cdf0e10cSrcweir } 252cdf0e10cSrcweir 253cdf0e10cSrcweir //__________________________________________________________________________________________________ 254cdf0e10cSrcweir Bridge::~Bridge() SAL_THROW( () ) 255cdf0e10cSrcweir { 256cdf0e10cSrcweir //System::GC::Collect(); 257cdf0e10cSrcweir (*m_uno_cli_env->release)( m_uno_cli_env ); 258cdf0e10cSrcweir (*((uno_Environment *)m_uno_env)->release)( (uno_Environment *)m_uno_env ); 259cdf0e10cSrcweir } 260cdf0e10cSrcweir 261cdf0e10cSrcweir 262cdf0e10cSrcweir 263cdf0e10cSrcweir } //namespace cli_uno 264cdf0e10cSrcweir 265cdf0e10cSrcweir extern "C" 266cdf0e10cSrcweir { 267cdf0e10cSrcweir 268cdf0e10cSrcweir namespace cli_uno 269cdf0e10cSrcweir { 270cdf0e10cSrcweir //-------------------------------------------------------------------------------------------------- 271cdf0e10cSrcweir void SAL_CALL cli_env_disposing( uno_Environment * uno_cli_env ) 272cdf0e10cSrcweir SAL_THROW_EXTERN_C() 273cdf0e10cSrcweir { 274cdf0e10cSrcweir uno_cli_env->pContext = 0; 275cdf0e10cSrcweir } 276cdf0e10cSrcweir 277cdf0e10cSrcweir //################################################################################################## 278cdf0e10cSrcweir void SAL_CALL uno_initEnvironment( uno_Environment * uno_cli_env ) 279cdf0e10cSrcweir SAL_THROW_EXTERN_C() 280cdf0e10cSrcweir { 281cdf0e10cSrcweir //ToDo: remove when compiled with .NET 2 282cdf0e10cSrcweir #if defined(_MSC_VER) && (_MSC_VER < 1400) 283cdf0e10cSrcweir __crt_dll_initialize(); 284cdf0e10cSrcweir #endif 285cdf0e10cSrcweir 286cdf0e10cSrcweir uno_cli_env->environmentDisposing= cli_env_disposing; 287cdf0e10cSrcweir uno_cli_env->pExtEnv = 0; 288cdf0e10cSrcweir //Set the console to print Trace messages 289cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 1 290cdf0e10cSrcweir System::Diagnostics::Trace::get_Listeners()-> 291cdf0e10cSrcweir Add( new System::Diagnostics::TextWriterTraceListener(System::Console::get_Out())); 292cdf0e10cSrcweir #endif 293cdf0e10cSrcweir OSL_ASSERT( 0 == uno_cli_env->pContext ); 294cdf0e10cSrcweir 295cdf0e10cSrcweir // We let the Cli_environment leak, since there is no good point where we could destruct it. 296cdf0e10cSrcweir //dispose is not used because we would have then also synchronize the calls to proxies. If the 297cdf0e10cSrcweir //Cli_environment is disposed, we must prevent all calls, otherwise we may crash at points 298cdf0e10cSrcweir //where g_cli_env is accessed. 299cdf0e10cSrcweir //When we compile the bridge with .NET 2 then we can again hold g_cli_env as a static gcroot 300cdf0e10cSrcweir //member in a unmanaged class, such as Bridge. 301cdf0e10cSrcweir CliEnvHolder::g_cli_env = new Cli_environment(); 302cdf0e10cSrcweir } 303cdf0e10cSrcweir //################################################################################################## 304cdf0e10cSrcweir void SAL_CALL uno_ext_getMapping( 305cdf0e10cSrcweir uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo ) 306cdf0e10cSrcweir SAL_THROW_EXTERN_C() 307cdf0e10cSrcweir { 308cdf0e10cSrcweir OSL_ASSERT( 0 != ppMapping && 0 != pFrom && 0 != pTo ); 309cdf0e10cSrcweir if (*ppMapping) 310cdf0e10cSrcweir { 311cdf0e10cSrcweir (*(*ppMapping)->release)( *ppMapping ); 312cdf0e10cSrcweir *ppMapping = 0; 313cdf0e10cSrcweir } 314cdf0e10cSrcweir 315cdf0e10cSrcweir 316cdf0e10cSrcweir OUString const & from_env_typename = *reinterpret_cast< OUString const * >( 317cdf0e10cSrcweir &pFrom->pTypeName ); 318cdf0e10cSrcweir OUString const & to_env_typename = *reinterpret_cast< OUString const * >( 319cdf0e10cSrcweir &pTo->pTypeName ); 320cdf0e10cSrcweir 321cdf0e10cSrcweir uno_Mapping * mapping = 0; 322cdf0e10cSrcweir 323cdf0e10cSrcweir try 324cdf0e10cSrcweir { 325cdf0e10cSrcweir if (from_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_CLI) ) && 326cdf0e10cSrcweir to_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) )) 327cdf0e10cSrcweir { 328cdf0e10cSrcweir Bridge * bridge = new Bridge( pFrom, pTo->pExtEnv, true ); // ref count = 1 329cdf0e10cSrcweir mapping = &bridge->m_cli2uno; 330cdf0e10cSrcweir uno_registerMapping( 331cdf0e10cSrcweir &mapping, Bridge_free, pFrom, (uno_Environment *)pTo->pExtEnv, 0 ); 332cdf0e10cSrcweir } 333cdf0e10cSrcweir else if (from_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ) && 334cdf0e10cSrcweir to_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_CLI) )) 335cdf0e10cSrcweir { 336cdf0e10cSrcweir Bridge * bridge = new Bridge( pTo, pFrom->pExtEnv, false ); // ref count = 1 337cdf0e10cSrcweir mapping = &bridge->m_uno2cli; 338cdf0e10cSrcweir uno_registerMapping( 339cdf0e10cSrcweir &mapping, Bridge_free, (uno_Environment *)pFrom->pExtEnv, pTo, 0 ); 340cdf0e10cSrcweir } 341cdf0e10cSrcweir } 342cdf0e10cSrcweir catch (BridgeRuntimeError & err) 343cdf0e10cSrcweir { 344cdf0e10cSrcweir #if OSL_DEBUG_LEVEL >= 1 345cdf0e10cSrcweir OString cstr_msg( 346cdf0e10cSrcweir OUStringToOString( 347cdf0e10cSrcweir OUSTR("[cli_uno bridge error] ") + err.m_message, RTL_TEXTENCODING_ASCII_US ) ); 348cdf0e10cSrcweir OSL_ENSURE( 0, cstr_msg.getStr() ); 349cdf0e10cSrcweir #else 350cdf0e10cSrcweir (void) err; // unused 351cdf0e10cSrcweir #endif 352cdf0e10cSrcweir } 353cdf0e10cSrcweir *ppMapping = mapping; 354cdf0e10cSrcweir } 355cdf0e10cSrcweir 356cdf0e10cSrcweir 357cdf0e10cSrcweir //################################################################################################## 358cdf0e10cSrcweir sal_Bool SAL_CALL component_canUnload( TimeValue * ) 359cdf0e10cSrcweir SAL_THROW_EXTERN_C() 360cdf0e10cSrcweir { 361cdf0e10cSrcweir return true; 362cdf0e10cSrcweir } 363cdf0e10cSrcweir 364cdf0e10cSrcweir } 365cdf0e10cSrcweir } 366