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