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_bridges.hxx"
26
27 #include <exception>
28 #include <typeinfo>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "rtl/alloc.h"
34 #include "rtl/ustrbuf.hxx"
35
36 #include <com/sun/star/uno/genfunc.hxx>
37 #include "com/sun/star/uno/RuntimeException.hpp"
38 #include <uno/data.h>
39
40 #include <bridges/cpp_uno/shared/bridge.hxx>
41 #include <bridges/cpp_uno/shared/types.hxx>
42 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
43 #include "bridges/cpp_uno/shared/vtables.hxx"
44
45 #include "abi.hxx"
46 #include "share.hxx"
47
48 using namespace ::rtl;
49 using namespace ::com::sun::star::uno;
50
51 //==================================================================================================
52
53 // The AArch64 outgoing-call trampoline, implemented in call.s. It loads the
54 // argument registers from the caller-prepared arrays, copies overflow args to
55 // the outgoing stack, performs the indirect call, and returns x0/x1 and d0..d3.
56 extern "C" void callVirtualFunction(
57 sal_uInt64 pFunction, sal_uInt64 pIndirectRet,
58 sal_uInt64 *pGPR, double *pFPR,
59 unsigned char *pStack, sal_uInt32 nStackBytes,
60 sal_uInt64 *pGPRReturn, double *pFPRReturn );
61
62 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
63 void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
64 void * pIndirectReturn,
65 unsigned char *pStack, sal_uInt32 nStack,
66 sal_uInt64 *pGPR, sal_uInt32 nGPR,
67 double *pFPR, sal_uInt32 nFPR) __attribute__((noinline));
68
callVirtualMethod(void * pThis,sal_uInt32 nVtableIndex,void * pRegisterReturn,typelib_TypeDescriptionReference * pReturnTypeRef,bool bSimpleReturn,void * pIndirectReturn,unsigned char * pStack,sal_uInt32 nStack,sal_uInt64 * pGPR,sal_uInt32 nGPR,double * pFPR,sal_uInt32 nFPR)69 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
70 void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
71 void * pIndirectReturn,
72 unsigned char *pStack, sal_uInt32 nStack,
73 sal_uInt64 *pGPR, sal_uInt32 nGPR,
74 double *pFPR, sal_uInt32 nFPR)
75 {
76 #if OSL_DEBUG_LEVEL > 1
77 // Let's figure out what is really going on here
78 {
79 fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
80 for ( unsigned int i = 0; i < nGPR; ++i )
81 fprintf( stderr, "0x%lx, ", pGPR[i] );
82 fprintf( stderr, "\nFPR's (%d): ", nFPR );
83 for ( unsigned int i = 0; i < nFPR; ++i )
84 fprintf( stderr, "%f, ", pFPR[i] );
85 // The overflow area is a packed byte image, not an array of words.
86 fprintf( stderr, "\nStack (%d bytes): ", nStack );
87 for ( unsigned int i = 0; i < nStack; ++i )
88 fprintf( stderr, "%02x ", pStack[i] );
89 fprintf( stderr, "\n" );
90 }
91 #endif
92
93 // The call instruction within callVirtualFunction may throw exceptions. So
94 // that the compiler handles this correctly, it is important that (a)
95 // callVirtualMethod might call dummy_can_throw_anything (although this never
96 // happens at runtime), which in turn can throw exceptions, and (b)
97 // callVirtualMethod is not inlined at its call site (so that any exceptions
98 // thrown across the call are caught):
99 if ( !pThis )
100 CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything( "xxx" ); // address something
101
102 // Should not happen, but...
103 if ( nFPR > aarch64::MAX_FPR_REGS )
104 nFPR = aarch64::MAX_FPR_REGS;
105 if ( nGPR > aarch64::MAX_GPR_REGS )
106 nGPR = aarch64::MAX_GPR_REGS;
107
108 // Get pointer to the C++ virtual method from the vtable.
109 sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
110 pMethod += 8 * nVtableIndex;
111 pMethod = *((sal_uInt64 *)pMethod);
112
113 // Return register save areas: x0,x1 and d0..d3 (HFA up to 4 elements).
114 sal_uInt64 gpReturn[2] = { 0, 0 };
115 double fpReturn[4] = { 0, 0, 0, 0 };
116
117 // Ensure the GPR/FPR arrays are the full register width even if fewer were
118 // filled (the trampoline always loads all 8 of each).
119 sal_uInt64 gpr[aarch64::MAX_GPR_REGS];
120 double fpr[aarch64::MAX_FPR_REGS];
121 for ( sal_uInt32 i = 0; i < aarch64::MAX_GPR_REGS; ++i )
122 gpr[i] = ( i < nGPR ) ? pGPR[i] : 0;
123 for ( sal_uInt32 i = 0; i < aarch64::MAX_FPR_REGS; ++i )
124 fpr[i] = ( i < nFPR ) ? pFPR[i] : 0;
125
126 callVirtualFunction(
127 pMethod,
128 reinterpret_cast<sal_uInt64>( pIndirectReturn ), // x8, 0 if none
129 gpr, fpr,
130 pStack, nStack,
131 gpReturn, fpReturn );
132
133 switch (pReturnTypeRef->eTypeClass)
134 {
135 case typelib_TypeClass_HYPER:
136 case typelib_TypeClass_UNSIGNED_HYPER:
137 *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = gpReturn[0];
138 break;
139 case typelib_TypeClass_LONG:
140 *reinterpret_cast<sal_Int32 *>( pRegisterReturn ) =
141 *reinterpret_cast<sal_Int32 *>( &gpReturn[0] );
142 break;
143 case typelib_TypeClass_UNSIGNED_LONG:
144 case typelib_TypeClass_ENUM:
145 *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) =
146 *reinterpret_cast<sal_uInt32 *>( &gpReturn[0] );
147 break;
148 case typelib_TypeClass_CHAR:
149 case typelib_TypeClass_UNSIGNED_SHORT:
150 *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &gpReturn[0] );
151 break;
152 case typelib_TypeClass_SHORT:
153 *reinterpret_cast<sal_Int16 *>( pRegisterReturn ) =
154 *reinterpret_cast<sal_Int16 *>( &gpReturn[0] );
155 break;
156 case typelib_TypeClass_BOOLEAN:
157 *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &gpReturn[0] );
158 break;
159 case typelib_TypeClass_BYTE:
160 *reinterpret_cast<sal_Int8 *>( pRegisterReturn ) =
161 *reinterpret_cast<sal_Int8 *>( &gpReturn[0] );
162 break;
163 case typelib_TypeClass_FLOAT:
164 *reinterpret_cast<float *>( pRegisterReturn ) =
165 *reinterpret_cast<float *>( &fpReturn[0] );
166 break;
167 case typelib_TypeClass_DOUBLE:
168 *reinterpret_cast<double *>( pRegisterReturn ) = fpReturn[0];
169 break;
170 default:
171 {
172 sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
173 if (bSimpleReturn && nRetSize > 0)
174 {
175 // Register-returned aggregate: an HFA arrives in d0..d3, a
176 // non-HFA <= 16 bytes in x0,x1. fill_struct picks the right one.
177 aarch64::fill_struct( pReturnTypeRef, &gpReturn[0], &fpReturn[0], pRegisterReturn);
178 }
179 break;
180 }
181 }
182 }
183
184 //==================================================================================================
185
186 // Macros for inserting values into registers. Stack arguments are handled
187 // separately with a byte cursor because Apple packs them by size/alignment.
188 // pSV - pointer to the source
189 // nr - order of the value [will be increased if stored to register]
190 // pFPR, pGPR - pointer to the registers
191
192 // Each pFPR slot is the low 64 bits of a v register. A float occupies only
193 // the low 32 bits, while a double occupies all 64 bits.
194 #define INSERT_FLOAT( pSV, nr, pFPR ) \
195 if ( nr < aarch64::MAX_FPR_REGS ) \
196 { \
197 pFPR[nr] = 0; \
198 *reinterpret_cast<float *>( pFPR + nr++ ) = *reinterpret_cast<const float *>( pSV ); \
199 }
200
201 #define INSERT_DOUBLE( pSV, nr, pFPR ) \
202 if ( nr < aarch64::MAX_FPR_REGS ) \
203 pFPR[nr++] = *reinterpret_cast<const double *>( pSV );
204
205 #define INSERT_INT64( pSV, nr, pGPR ) \
206 if ( nr < aarch64::MAX_GPR_REGS ) \
207 pGPR[nr++] = *reinterpret_cast<const sal_uInt64 *>( pSV );
208
209 #define INSERT_INT32( pSV, nr, pGPR ) \
210 if ( nr < aarch64::MAX_GPR_REGS ) \
211 pGPR[nr++] = *reinterpret_cast<const sal_uInt32 *>( pSV );
212
213 #define INSERT_SIGNED_INT32( pSV, nr, pGPR ) \
214 if ( nr < aarch64::MAX_GPR_REGS ) \
215 pGPR[nr++] = static_cast<sal_Int64>( *reinterpret_cast<const sal_Int32 *>( pSV ) );
216
217 #define INSERT_INT16( pSV, nr, pGPR ) \
218 if ( nr < aarch64::MAX_GPR_REGS ) \
219 pGPR[nr++] = *reinterpret_cast<const sal_uInt16 *>( pSV );
220
221 #define INSERT_SIGNED_INT16( pSV, nr, pGPR ) \
222 if ( nr < aarch64::MAX_GPR_REGS ) \
223 pGPR[nr++] = static_cast<sal_Int64>( *reinterpret_cast<const sal_Int16 *>( pSV ) );
224
225 #define INSERT_INT8( pSV, nr, pGPR ) \
226 if ( nr < aarch64::MAX_GPR_REGS ) \
227 pGPR[nr++] = *reinterpret_cast<const sal_uInt8 *>( pSV );
228
229 #define INSERT_SIGNED_INT8( pSV, nr, pGPR ) \
230 if ( nr < aarch64::MAX_GPR_REGS ) \
231 pGPR[nr++] = static_cast<sal_Int64>( *reinterpret_cast<const sal_Int8 *>( pSV ) );
232
233 //==================================================================================================
234
235 namespace {
236
appendCString(OUStringBuffer & buffer,char const * text)237 void appendCString(OUStringBuffer & buffer, char const * text) {
238 if (text != 0) {
239 buffer.append(
240 OStringToOUString(OString(text), RTL_TEXTENCODING_ISO_8859_1));
241 // use 8859-1 to avoid conversion failure
242 }
243 }
244
245 }
246
cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,bridges::cpp_uno::shared::VtableSlot aVtableSlot,typelib_TypeDescriptionReference * pReturnTypeRef,sal_Int32 nParams,typelib_MethodParameter * pParams,void * pUnoReturn,void * pUnoArgs[],uno_Any ** ppUnoExc)247 static void cpp_call(
248 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
249 bridges::cpp_uno::shared::VtableSlot aVtableSlot,
250 typelib_TypeDescriptionReference * pReturnTypeRef,
251 sal_Int32 nParams, typelib_MethodParameter * pParams,
252 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
253 {
254 unsigned char *pStackStart = static_cast<unsigned char *>(
255 __builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) ) );
256 sal_uInt32 nStack = 0;
257
258 sal_uInt64 pGPR[aarch64::MAX_GPR_REGS];
259 sal_uInt32 nGPR = 0;
260
261 double pFPR[aarch64::MAX_FPR_REGS];
262 sal_uInt32 nFPR = 0;
263
264 // Return
265 typelib_TypeDescription * pReturnTypeDescr = 0;
266 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
267 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
268
269 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion (see below)
270
271 // Indirect-result pointer. On AArch64 this is passed in the dedicated x8
272 // register, NOT as the first general-purpose argument (unlike x86-64 SysV).
273 // So we do NOT insert it into pGPR here; it is threaded to the trampoline
274 // separately as pIndirectReturn.
275 void * pIndirectReturn = 0;
276
277 bool bSimpleReturn = true;
278 if ( pReturnTypeDescr )
279 {
280 if ( aarch64::return_in_hidden_param( pReturnTypeRef ) )
281 bSimpleReturn = false;
282
283 if ( bSimpleReturn )
284 pCppReturn = pUnoReturn; // direct way for simple types
285 else
286 {
287 // complex return via the x8 indirect-result buffer
288 pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
289 __builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn;
290 pIndirectReturn = pCppReturn;
291 }
292 }
293
294 // Push "this" pointer
295 void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
296 INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR );
297
298 // Args
299 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
300 // Indizes of values this have to be converted (interface conversion cpp<=>uno)
301 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
302 // Type descriptions for reconversions
303 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
304
305 sal_Int32 nTempIndizes = 0;
306
307 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
308 {
309 const typelib_MethodParameter & rParam = pParams[nPos];
310 typelib_TypeDescription * pParamTypeDescr = 0;
311 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
312
313 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
314 {
315 uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
316 pThis->getBridge()->getUno2Cpp() );
317 bool onStack = false;
318
319 switch (pParamTypeDescr->eTypeClass)
320 {
321 case typelib_TypeClass_HYPER:
322 case typelib_TypeClass_UNSIGNED_HYPER:
323 onStack = nGPR >= aarch64::MAX_GPR_REGS;
324 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR );
325 break;
326 case typelib_TypeClass_LONG:
327 onStack = nGPR >= aarch64::MAX_GPR_REGS;
328 INSERT_SIGNED_INT32( pCppArgs[nPos], nGPR, pGPR );
329 break;
330 case typelib_TypeClass_UNSIGNED_LONG:
331 case typelib_TypeClass_ENUM:
332 onStack = nGPR >= aarch64::MAX_GPR_REGS;
333 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR );
334 break;
335 case typelib_TypeClass_SHORT:
336 onStack = nGPR >= aarch64::MAX_GPR_REGS;
337 INSERT_SIGNED_INT16( pCppArgs[nPos], nGPR, pGPR );
338 break;
339 case typelib_TypeClass_CHAR:
340 case typelib_TypeClass_UNSIGNED_SHORT:
341 onStack = nGPR >= aarch64::MAX_GPR_REGS;
342 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR );
343 break;
344 case typelib_TypeClass_BYTE:
345 onStack = nGPR >= aarch64::MAX_GPR_REGS;
346 INSERT_SIGNED_INT8( pCppArgs[nPos], nGPR, pGPR );
347 break;
348 case typelib_TypeClass_BOOLEAN:
349 onStack = nGPR >= aarch64::MAX_GPR_REGS;
350 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR );
351 break;
352 case typelib_TypeClass_FLOAT:
353 onStack = nFPR >= aarch64::MAX_FPR_REGS;
354 INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR );
355 break;
356 case typelib_TypeClass_DOUBLE:
357 onStack = nFPR >= aarch64::MAX_FPR_REGS;
358 INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR );
359 break;
360 default:
361 break;
362 }
363 if ( onStack )
364 {
365 nStack = aarch64::align_stack_offset( nStack, rParam.pTypeRef );
366 sal_uInt32 size = aarch64::stack_size( rParam.pTypeRef );
367 memcpy( pStackStart + nStack, pCppArgs[nPos], size );
368 nStack += size;
369 }
370
371 // no longer needed
372 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
373 }
374 else // ptr to complex value | ref
375 {
376 if (! rParam.bIn) // is pure out
377 {
378 // cpp out is constructed mem, uno out is not!
379 uno_constructData(
380 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
381 pParamTypeDescr );
382 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
383 // will be released at reconversion
384 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
385 }
386 // is in/inout
387 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
388 {
389 uno_copyAndConvertData(
390 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
391 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
392
393 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
394 // will be released at reconversion
395 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
396 }
397 else // direct way
398 {
399 pCppArgs[nPos] = pUnoArgs[nPos];
400 // no longer needed
401 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
402 }
403 if ( nGPR < aarch64::MAX_GPR_REGS )
404 {
405 INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR );
406 }
407 else
408 {
409 nStack = (nStack + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
410 memcpy( pStackStart + nStack, &pCppArgs[nPos], sizeof(void *) );
411 nStack += sizeof(void *);
412 }
413 }
414 }
415
416 try
417 {
418 try {
419 callVirtualMethod(
420 pAdjustedThisPtr, aVtableSlot.index,
421 pCppReturn, pReturnTypeRef, bSimpleReturn,
422 pIndirectReturn,
423 pStackStart, nStack,
424 pGPR, nGPR,
425 pFPR, nFPR );
426 } catch (Exception &) {
427 throw;
428 } catch (std::exception & e) {
429 OUStringBuffer buf;
430 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("C++ code threw "));
431 appendCString(buf, typeid(e).name());
432 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(": "));
433 appendCString(buf, e.what());
434 throw RuntimeException(
435 buf.makeStringAndClear(), Reference< XInterface >());
436 } catch (...) {
437 throw RuntimeException(
438 OUString(
439 RTL_CONSTASCII_USTRINGPARAM(
440 "C++ code threw unknown exception")),
441 Reference< XInterface >());
442 }
443
444 // NO exception occurred...
445 *ppUnoExc = 0;
446
447 // reconvert temporary params
448 for ( ; nTempIndizes--; )
449 {
450 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
451 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
452
453 if (pParams[nIndex].bIn)
454 {
455 if (pParams[nIndex].bOut) // inout
456 {
457 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
458 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
459 pThis->getBridge()->getCpp2Uno() );
460 }
461 }
462 else // pure out
463 {
464 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
465 pThis->getBridge()->getCpp2Uno() );
466 }
467 // destroy temp cpp param => cpp: every param was constructed
468 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
469
470 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
471 }
472 // return value
473 if (pCppReturn && pUnoReturn != pCppReturn)
474 {
475 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
476 pThis->getBridge()->getCpp2Uno() );
477 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
478 }
479 }
480 catch (Exception & e)
481 {
482 // fill uno exception
483 std::type_info * type = CPPU_CURRENT_NAMESPACE::__cxa_current_exception_type();
484 CPPU_CURRENT_NAMESPACE::fillUnoException(
485 type ? *type : typeid(e), &e, *ppUnoExc,
486 pThis->getBridge()->getCpp2Uno() );
487
488 // temporary params
489 for ( ; nTempIndizes--; )
490 {
491 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
492 // destroy temp cpp param => cpp: every param was constructed
493 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
494 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
495 }
496 // return type
497 if (pReturnTypeDescr)
498 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
499 }
500 catch (...)
501 {
502 RuntimeException e(
503 OUString( RTL_CONSTASCII_USTRINGPARAM("C++ code threw unknown exception") ),
504 Reference< XInterface >() );
505 uno_type_any_constructAndConvert(
506 *ppUnoExc, &e, ::getCppuType( &e ).getTypeLibType(),
507 pThis->getBridge()->getCpp2Uno() );
508 for ( ; nTempIndizes--; )
509 {
510 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
511 uno_destructData(
512 pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
513 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
514 }
515 if (pReturnTypeDescr)
516 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
517 }
518 }
519
520 //==================================================================================================
521
522 namespace bridges { namespace cpp_uno { namespace shared {
523
unoInterfaceProxyDispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberDescr,void * pReturn,void * pArgs[],uno_Any ** ppException)524 void unoInterfaceProxyDispatch(
525 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
526 void * pReturn, void * pArgs[], uno_Any ** ppException )
527 {
528 // is my surrogate
529 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
530 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
531 #if OSL_DEBUG_LEVEL > 0
532 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
533 #endif
534
535 switch (pMemberDescr->eTypeClass)
536 {
537 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
538 {
539 #if OSL_DEBUG_LEVEL > 0
540 // determine vtable call index
541 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
542 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
543 #endif
544 VtableSlot aVtableSlot(
545 getVtableSlot(
546 reinterpret_cast<
547 typelib_InterfaceAttributeTypeDescription const * >(
548 pMemberDescr)));
549
550 if (pReturn)
551 {
552 // dependent dispatch
553 cpp_call(
554 pThis, aVtableSlot,
555 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
556 0, 0, // no params
557 pReturn, pArgs, ppException );
558 }
559 else
560 {
561 // is SET
562 typelib_MethodParameter aParam;
563 aParam.pTypeRef =
564 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
565 aParam.bIn = sal_True;
566 aParam.bOut = sal_False;
567
568 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
569 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
570 typelib_typedescriptionreference_new(
571 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
572
573 // dependent dispatch
574 aVtableSlot.index += 1; // get, then set method
575 cpp_call(
576 pThis, aVtableSlot, // get, then set method
577 pReturnTypeRef,
578 1, &aParam,
579 pReturn, pArgs, ppException );
580
581 typelib_typedescriptionreference_release( pReturnTypeRef );
582 }
583
584 break;
585 }
586 case typelib_TypeClass_INTERFACE_METHOD:
587 {
588 #if OSL_DEBUG_LEVEL > 0
589 // determine vtable call index
590 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
591 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
592 #endif
593 VtableSlot aVtableSlot(
594 getVtableSlot(
595 reinterpret_cast<
596 typelib_InterfaceMethodTypeDescription const * >(
597 pMemberDescr)));
598
599 switch (aVtableSlot.index)
600 {
601 // standard calls
602 case 1: // acquire uno interface
603 (*pUnoI->acquire)( pUnoI );
604 *ppException = 0;
605 break;
606 case 2: // release uno interface
607 (*pUnoI->release)( pUnoI );
608 *ppException = 0;
609 break;
610 case 0: // queryInterface() opt
611 {
612 typelib_TypeDescription * pTD = 0;
613 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
614 if (pTD)
615 {
616 uno_Interface * pInterface = 0;
617 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
618 pThis->getBridge()->getUnoEnv(),
619 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
620
621 if (pInterface)
622 {
623 ::uno_any_construct(
624 reinterpret_cast< uno_Any * >( pReturn ),
625 &pInterface, pTD, 0 );
626 (*pInterface->release)( pInterface );
627 TYPELIB_DANGER_RELEASE( pTD );
628 *ppException = 0;
629 break;
630 }
631 TYPELIB_DANGER_RELEASE( pTD );
632 }
633 } // else perform queryInterface()
634 default:
635 // dependent dispatch
636 cpp_call(
637 pThis, aVtableSlot,
638 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
639 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
640 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
641 pReturn, pArgs, ppException );
642 }
643 break;
644 }
645 default:
646 {
647 ::com::sun::star::uno::RuntimeException aExc(
648 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
649 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
650
651 Type const & rExcType = ::getCppuType( &aExc );
652 // binary identical null reference
653 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
654 }
655 }
656 }
657
658 } } }
659