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 sal_uInt64 *pStack, sal_uInt32 nStackWords,
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 sal_uInt64 *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,sal_uInt64 * 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 sal_uInt64 *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 fprintf( stderr, "\nStack (%d): ", nStack );
86 for ( unsigned int i = 0; i < nStack; ++i )
87 fprintf( stderr, "0x%lx, ", pStack[i] );
88 fprintf( stderr, "\n" );
89 }
90 #endif
91
92 // The call instruction within callVirtualFunction may throw exceptions. So
93 // that the compiler handles this correctly, it is important that (a)
94 // callVirtualMethod might call dummy_can_throw_anything (although this never
95 // happens at runtime), which in turn can throw exceptions, and (b)
96 // callVirtualMethod is not inlined at its call site (so that any exceptions
97 // thrown across the call are caught):
98 if ( !pThis )
99 CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything( "xxx" ); // address something
100
101 // Should not happen, but...
102 if ( nFPR > aarch64::MAX_FPR_REGS )
103 nFPR = aarch64::MAX_FPR_REGS;
104 if ( nGPR > aarch64::MAX_GPR_REGS )
105 nGPR = aarch64::MAX_GPR_REGS;
106
107 // Get pointer to the C++ virtual method from the vtable.
108 sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
109 pMethod += 8 * nVtableIndex;
110 pMethod = *((sal_uInt64 *)pMethod);
111
112 // Return register save areas: x0,x1 and d0..d3 (HFA up to 4 elements).
113 sal_uInt64 gpReturn[2] = { 0, 0 };
114 double fpReturn[4] = { 0, 0, 0, 0 };
115
116 // Ensure the GPR/FPR arrays are the full register width even if fewer were
117 // filled (the trampoline always loads all 8 of each).
118 sal_uInt64 gpr[aarch64::MAX_GPR_REGS];
119 double fpr[aarch64::MAX_FPR_REGS];
120 for ( sal_uInt32 i = 0; i < aarch64::MAX_GPR_REGS; ++i )
121 gpr[i] = ( i < nGPR ) ? pGPR[i] : 0;
122 for ( sal_uInt32 i = 0; i < aarch64::MAX_FPR_REGS; ++i )
123 fpr[i] = ( i < nFPR ) ? pFPR[i] : 0;
124
125 callVirtualFunction(
126 pMethod,
127 reinterpret_cast<sal_uInt64>( pIndirectReturn ), // x8, 0 if none
128 gpr, fpr,
129 pStack, nStack,
130 gpReturn, fpReturn );
131
132 switch (pReturnTypeRef->eTypeClass)
133 {
134 case typelib_TypeClass_HYPER:
135 case typelib_TypeClass_UNSIGNED_HYPER:
136 *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = gpReturn[0];
137 break;
138 case typelib_TypeClass_LONG:
139 case typelib_TypeClass_UNSIGNED_LONG:
140 case typelib_TypeClass_ENUM:
141 *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &gpReturn[0] );
142 break;
143 case typelib_TypeClass_CHAR:
144 case typelib_TypeClass_SHORT:
145 case typelib_TypeClass_UNSIGNED_SHORT:
146 *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &gpReturn[0] );
147 break;
148 case typelib_TypeClass_BOOLEAN:
149 case typelib_TypeClass_BYTE:
150 *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &gpReturn[0] );
151 break;
152 case typelib_TypeClass_FLOAT:
153 case typelib_TypeClass_DOUBLE:
154 *reinterpret_cast<double *>( pRegisterReturn ) = fpReturn[0];
155 break;
156 default:
157 {
158 sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
159 if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
160 {
161 // Register-returned aggregate: an HFA arrives in d0..d3, a
162 // non-HFA <= 16 bytes in x0,x1. fill_struct picks the right one.
163 aarch64::fill_struct( pReturnTypeRef, &gpReturn[0], &fpReturn[0], pRegisterReturn);
164 }
165 break;
166 }
167 }
168 }
169
170 //==================================================================================================
171
172 // Macros for easier insertion of values to registers or stack
173 // pSV - pointer to the source
174 // nr - order of the value [will be increased if stored to register]
175 // pFPR, pGPR - pointer to the registers
176 // pDS - pointer to the stack [will be increased if stored here]
177
178 // The pFPR slot holds the value to be loaded into a v register; the trampoline
179 // loads it with LDR d<n>, so float and double are stored the same way here.
180 #define INSERT_FLOAT_DOUBLE( pSV, nr, pFPR, pDS ) \
181 if ( nr < aarch64::MAX_FPR_REGS ) \
182 pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
183 else \
184 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
185
186 #define INSERT_INT64( pSV, nr, pGPR, pDS ) \
187 if ( nr < aarch64::MAX_GPR_REGS ) \
188 pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
189 else \
190 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
191
192 #define INSERT_INT32( pSV, nr, pGPR, pDS ) \
193 if ( nr < aarch64::MAX_GPR_REGS ) \
194 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
195 else \
196 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
197
198 #define INSERT_INT16( pSV, nr, pGPR, pDS ) \
199 if ( nr < aarch64::MAX_GPR_REGS ) \
200 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
201 else \
202 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
203
204 #define INSERT_INT8( pSV, nr, pGPR, pDS ) \
205 if ( nr < aarch64::MAX_GPR_REGS ) \
206 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
207 else \
208 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
209
210 //==================================================================================================
211
212 namespace {
213
appendCString(OUStringBuffer & buffer,char const * text)214 void appendCString(OUStringBuffer & buffer, char const * text) {
215 if (text != 0) {
216 buffer.append(
217 OStringToOUString(OString(text), RTL_TEXTENCODING_ISO_8859_1));
218 // use 8859-1 to avoid conversion failure
219 }
220 }
221
222 }
223
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)224 static void cpp_call(
225 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
226 bridges::cpp_uno::shared::VtableSlot aVtableSlot,
227 typelib_TypeDescriptionReference * pReturnTypeRef,
228 sal_Int32 nParams, typelib_MethodParameter * pParams,
229 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
230 {
231 // Maxium space for [complex ret ptr], values | ptr ...
232 // (but will be used less - some of the values will be in pGPR and pFPR)
233 sal_uInt64 *pStack = (sal_uInt64 *)__builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) );
234 sal_uInt64 *pStackStart = pStack;
235
236 sal_uInt64 pGPR[aarch64::MAX_GPR_REGS];
237 sal_uInt32 nGPR = 0;
238
239 double pFPR[aarch64::MAX_FPR_REGS];
240 sal_uInt32 nFPR = 0;
241
242 // Return
243 typelib_TypeDescription * pReturnTypeDescr = 0;
244 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
245 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
246
247 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion (see below)
248
249 // Indirect-result pointer. On AArch64 this is passed in the dedicated x8
250 // register, NOT as the first general-purpose argument (unlike x86-64 SysV).
251 // So we do NOT insert it into pGPR here; it is threaded to the trampoline
252 // separately as pIndirectReturn.
253 void * pIndirectReturn = 0;
254
255 bool bSimpleReturn = true;
256 if ( pReturnTypeDescr )
257 {
258 if ( aarch64::return_in_hidden_param( pReturnTypeRef ) )
259 bSimpleReturn = false;
260
261 if ( bSimpleReturn )
262 pCppReturn = pUnoReturn; // direct way for simple types
263 else
264 {
265 // complex return via the x8 indirect-result buffer
266 pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
267 __builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn;
268 pIndirectReturn = pCppReturn;
269 }
270 }
271
272 // Push "this" pointer
273 void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
274 INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
275
276 // Args
277 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
278 // Indizes of values this have to be converted (interface conversion cpp<=>uno)
279 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
280 // Type descriptions for reconversions
281 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
282
283 sal_Int32 nTempIndizes = 0;
284
285 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
286 {
287 const typelib_MethodParameter & rParam = pParams[nPos];
288 typelib_TypeDescription * pParamTypeDescr = 0;
289 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
290
291 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
292 {
293 uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
294 pThis->getBridge()->getUno2Cpp() );
295
296 switch (pParamTypeDescr->eTypeClass)
297 {
298 case typelib_TypeClass_HYPER:
299 case typelib_TypeClass_UNSIGNED_HYPER:
300 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack );
301 break;
302 case typelib_TypeClass_LONG:
303 case typelib_TypeClass_UNSIGNED_LONG:
304 case typelib_TypeClass_ENUM:
305 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
306 break;
307 case typelib_TypeClass_SHORT:
308 case typelib_TypeClass_CHAR:
309 case typelib_TypeClass_UNSIGNED_SHORT:
310 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
311 break;
312 case typelib_TypeClass_BOOLEAN:
313 case typelib_TypeClass_BYTE:
314 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
315 break;
316 case typelib_TypeClass_FLOAT:
317 case typelib_TypeClass_DOUBLE:
318 INSERT_FLOAT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack );
319 break;
320 default:
321 break;
322 }
323
324 // no longer needed
325 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
326 }
327 else // ptr to complex value | ref
328 {
329 if (! rParam.bIn) // is pure out
330 {
331 // cpp out is constructed mem, uno out is not!
332 uno_constructData(
333 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
334 pParamTypeDescr );
335 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
336 // will be released at reconversion
337 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
338 }
339 // is in/inout
340 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
341 {
342 uno_copyAndConvertData(
343 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
344 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
345
346 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
347 // will be released at reconversion
348 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
349 }
350 else // direct way
351 {
352 pCppArgs[nPos] = pUnoArgs[nPos];
353 // no longer needed
354 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
355 }
356 INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
357 }
358 }
359
360 try
361 {
362 try {
363 callVirtualMethod(
364 pAdjustedThisPtr, aVtableSlot.index,
365 pCppReturn, pReturnTypeRef, bSimpleReturn,
366 pIndirectReturn,
367 pStackStart, ( pStack - pStackStart ),
368 pGPR, nGPR,
369 pFPR, nFPR );
370 } catch (Exception &) {
371 throw;
372 } catch (std::exception & e) {
373 OUStringBuffer buf;
374 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("C++ code threw "));
375 appendCString(buf, typeid(e).name());
376 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(": "));
377 appendCString(buf, e.what());
378 throw RuntimeException(
379 buf.makeStringAndClear(), Reference< XInterface >());
380 } catch (...) {
381 throw RuntimeException(
382 OUString(
383 RTL_CONSTASCII_USTRINGPARAM(
384 "C++ code threw unknown exception")),
385 Reference< XInterface >());
386 }
387
388 // NO exception occurred...
389 *ppUnoExc = 0;
390
391 // reconvert temporary params
392 for ( ; nTempIndizes--; )
393 {
394 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
395 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
396
397 if (pParams[nIndex].bIn)
398 {
399 if (pParams[nIndex].bOut) // inout
400 {
401 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
402 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
403 pThis->getBridge()->getCpp2Uno() );
404 }
405 }
406 else // pure out
407 {
408 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
409 pThis->getBridge()->getCpp2Uno() );
410 }
411 // destroy temp cpp param => cpp: every param was constructed
412 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
413
414 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
415 }
416 // return value
417 if (pCppReturn && pUnoReturn != pCppReturn)
418 {
419 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
420 pThis->getBridge()->getCpp2Uno() );
421 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
422 }
423 }
424 catch (...)
425 {
426 // fill uno exception
427 fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
428
429 // temporary params
430 for ( ; nTempIndizes--; )
431 {
432 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
433 // destroy temp cpp param => cpp: every param was constructed
434 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
435 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
436 }
437 // return type
438 if (pReturnTypeDescr)
439 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
440 }
441 }
442
443 //==================================================================================================
444
445 namespace bridges { namespace cpp_uno { namespace shared {
446
unoInterfaceProxyDispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberDescr,void * pReturn,void * pArgs[],uno_Any ** ppException)447 void unoInterfaceProxyDispatch(
448 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
449 void * pReturn, void * pArgs[], uno_Any ** ppException )
450 {
451 // is my surrogate
452 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
453 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
454 #if OSL_DEBUG_LEVEL > 0
455 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
456 #endif
457
458 switch (pMemberDescr->eTypeClass)
459 {
460 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
461 {
462 #if OSL_DEBUG_LEVEL > 0
463 // determine vtable call index
464 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
465 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
466 #endif
467 VtableSlot aVtableSlot(
468 getVtableSlot(
469 reinterpret_cast<
470 typelib_InterfaceAttributeTypeDescription const * >(
471 pMemberDescr)));
472
473 if (pReturn)
474 {
475 // dependent dispatch
476 cpp_call(
477 pThis, aVtableSlot,
478 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
479 0, 0, // no params
480 pReturn, pArgs, ppException );
481 }
482 else
483 {
484 // is SET
485 typelib_MethodParameter aParam;
486 aParam.pTypeRef =
487 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
488 aParam.bIn = sal_True;
489 aParam.bOut = sal_False;
490
491 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
492 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
493 typelib_typedescriptionreference_new(
494 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
495
496 // dependent dispatch
497 aVtableSlot.index += 1; // get, then set method
498 cpp_call(
499 pThis, aVtableSlot, // get, then set method
500 pReturnTypeRef,
501 1, &aParam,
502 pReturn, pArgs, ppException );
503
504 typelib_typedescriptionreference_release( pReturnTypeRef );
505 }
506
507 break;
508 }
509 case typelib_TypeClass_INTERFACE_METHOD:
510 {
511 #if OSL_DEBUG_LEVEL > 0
512 // determine vtable call index
513 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
514 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
515 #endif
516 VtableSlot aVtableSlot(
517 getVtableSlot(
518 reinterpret_cast<
519 typelib_InterfaceMethodTypeDescription const * >(
520 pMemberDescr)));
521
522 switch (aVtableSlot.index)
523 {
524 // standard calls
525 case 1: // acquire uno interface
526 (*pUnoI->acquire)( pUnoI );
527 *ppException = 0;
528 break;
529 case 2: // release uno interface
530 (*pUnoI->release)( pUnoI );
531 *ppException = 0;
532 break;
533 case 0: // queryInterface() opt
534 {
535 typelib_TypeDescription * pTD = 0;
536 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
537 if (pTD)
538 {
539 uno_Interface * pInterface = 0;
540 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
541 pThis->getBridge()->getUnoEnv(),
542 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
543
544 if (pInterface)
545 {
546 ::uno_any_construct(
547 reinterpret_cast< uno_Any * >( pReturn ),
548 &pInterface, pTD, 0 );
549 (*pInterface->release)( pInterface );
550 TYPELIB_DANGER_RELEASE( pTD );
551 *ppException = 0;
552 break;
553 }
554 TYPELIB_DANGER_RELEASE( pTD );
555 }
556 } // else perform queryInterface()
557 default:
558 // dependent dispatch
559 cpp_call(
560 pThis, aVtableSlot,
561 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
562 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
563 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
564 pReturn, pArgs, ppException );
565 }
566 break;
567 }
568 default:
569 {
570 ::com::sun::star::uno::RuntimeException aExc(
571 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
572 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
573
574 Type const & rExcType = ::getCppuType( &aExc );
575 // binary identical null reference
576 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
577 }
578 }
579 }
580
581 } } }
582