merged tag ooo/DEV300_m102
[LibreOffice.git] / cli_ure / source / uno_bridge / cli_bridge.cxx
blobab78b2f9d95ba4d425d66616a92b0ac9dea46af8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cli_ure.hxx"
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"
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
52 namespace cssu= com::sun::star::uno;
55 namespace sri= System::Runtime::InteropServices;
56 using namespace rtl;
58 namespace cli_uno
61 extern "C"
63 void SAL_CALL Mapping_acquire( uno_Mapping * mapping )
64 SAL_THROW_EXTERN_C()
66 Mapping const * that = static_cast< Mapping const * >( mapping );
67 that->m_bridge->acquire();
69 //--------------------------------------------------------------------------------------------------
70 void SAL_CALL Mapping_release( uno_Mapping * mapping )
71 SAL_THROW_EXTERN_C()
73 Mapping const * that = static_cast< Mapping const * >( mapping );
74 that->m_bridge->release();
78 //--------------------------------------------------------------------------------------------------
79 void SAL_CALL Mapping_cli2uno(
80 uno_Mapping * mapping, void ** ppOut,
81 void * pIn, typelib_InterfaceTypeDescription * td )
82 SAL_THROW_EXTERN_C()
84 uno_Interface ** ppUnoI = (uno_Interface **)ppOut;
85 intptr_t cliI = (intptr_t)pIn;
87 OSL_ENSURE( ppUnoI && td, "### null ptr!" );
89 if (0 != *ppUnoI)
91 uno_Interface * pUnoI = *(uno_Interface **)ppUnoI;
92 (*pUnoI->release)( pUnoI );
93 *ppUnoI = 0;
95 try
97 Mapping const * that = static_cast< Mapping const * >( mapping );
98 Bridge * bridge = that->m_bridge;
100 if (0 != cliI)
102 System::Object* cliObj= sri::GCHandle::op_Explicit(cliI).Target;
103 (*ppOut)= bridge->map_cli2uno(cliObj, (typelib_TypeDescription*) td);
106 catch (BridgeRuntimeError & err)
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
118 //--------------------------------------------------------------------------------------------------
119 void SAL_CALL Mapping_uno2cli(
120 uno_Mapping * mapping, void ** ppOut,
121 void * pIn, typelib_InterfaceTypeDescription * td )
122 SAL_THROW_EXTERN_C()
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;
142 Mapping const * that = static_cast< Mapping const * >( mapping );
143 Bridge * bridge = that->m_bridge;
145 if (0 != *ppDNetI)
147 sri::GCHandle::op_Explicit(ppDNetI).Free();
150 if (0 != pUnoI)
152 System::Object* cliI= bridge->map_uno2cli(pUnoI, td);
153 intptr_t ptr= NULL;
154 if(cliI)
156 ptr= sri::GCHandle::op_Explicit(sri::GCHandle::Alloc(cliI))
157 #ifdef _WIN32
158 .ToInt32();
159 #else /* defined(_WIN64) */ .ToInt64();
160 #endif
162 (*ppOut)= reinterpret_cast<void*>(ptr);
165 catch (BridgeRuntimeError & err)
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
178 //__________________________________________________________________________________________________
179 void SAL_CALL Bridge_free( uno_Mapping * mapping )
180 SAL_THROW_EXTERN_C()
182 Mapping * that = static_cast< Mapping * >( mapping );
183 delete that->m_bridge;
186 } //extern C
187 } //namespace
189 namespace cli_uno
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.
202 void Bridge::acquire() const SAL_THROW( () )
204 if (1 == osl_incrementInterlockedCount( &m_ref ))
206 if (m_registered_cli2uno)
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 );
212 else
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 );
220 //__________________________________________________________________________________________________
221 void Bridge::release() const SAL_THROW( () )
223 if (! osl_decrementInterlockedCount( &m_ref ))
225 uno_revokeMapping(
226 m_registered_cli2uno
227 ? const_cast<Mapping*>(&m_cli2uno)
228 : const_cast<Mapping*>(&m_uno2cli) );
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 )
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 );
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;
257 //__________________________________________________________________________________________________
258 Bridge::~Bridge() SAL_THROW( () )
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 );
267 } //namespace cli_uno
269 extern "C"
272 namespace cli_uno
274 //--------------------------------------------------------------------------------------------------
275 void SAL_CALL cli_env_disposing( uno_Environment * uno_cli_env )
276 SAL_THROW_EXTERN_C()
278 uno_cli_env->pContext = 0;
281 //##################################################################################################
282 void SAL_CALL uno_initEnvironment( uno_Environment * uno_cli_env )
283 SAL_THROW_EXTERN_C()
285 //ToDo: remove when compiled with .NET 2
286 #if defined(_MSC_VER) && (_MSC_VER < 1400)
287 __crt_dll_initialize();
288 #endif
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 );
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();
307 //##################################################################################################
308 void SAL_CALL uno_ext_getMapping(
309 uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo )
310 SAL_THROW_EXTERN_C()
312 OSL_ASSERT( 0 != ppMapping && 0 != pFrom && 0 != pTo );
313 if (*ppMapping)
315 (*(*ppMapping)->release)( *ppMapping );
316 *ppMapping = 0;
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 );
325 uno_Mapping * mapping = 0;
329 if (from_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_CLI) ) &&
330 to_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ))
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 );
337 else if (from_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ) &&
338 to_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_CLI) ))
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 );
346 catch (BridgeRuntimeError & err)
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
357 *ppMapping = mapping;
361 //##################################################################################################
362 sal_Bool SAL_CALL component_canUnload( TimeValue * )
363 SAL_THROW_EXTERN_C()
365 return true;