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