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