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