1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include <malloc.h>
29 #include <rtl/alloc.h>
30 
31 #include <com/sun/star/uno/genfunc.hxx>
32 #include "com/sun/star/uno/RuntimeException.hpp"
33 #include <uno/data.h>
34 
35 #include <bridges/cpp_uno/shared/bridge.hxx>
36 #include <bridges/cpp_uno/shared/types.hxx>
37 #include <bridges/cpp_uno/shared/unointerfaceproxy.hxx>
38 #include <bridges/cpp_uno/shared/vtables.hxx>
39 
40 #include "share.hxx"
41 
42 #include <stdio.h>
43 #include <string.h>
44 
45 /*
46  * Based on http://gcc.gnu.org/PR41443
47  * References to __SOFTFP__ are incorrect for EABI; the __SOFTFP__ code
48  * should be used for *soft-float ABI* whether or not VFP is enabled,
49  * and __SOFTFP__ does specifically mean soft-float not soft-float ABI.
50  *
51  * Changing the conditionals to __SOFTFP__ || __ARM_EABI__ then
52  * -mfloat-abi=softfp should work.  -mfloat-abi=hard won't; that would
53  * need both a new macro to identify the hard-VFP ABI.
54  */
55 #if !defined(__ARM_EABI__) && !defined(__SOFTFP__)
56 #error Not Implemented
57 
58 /*
59  some possibly handy code to detect that we have VFP registers
60  */
61 
62 #include <sys/types.h>
63 #include <sys/stat.h>
64 #include <fcntl.h>
65 #include <unistd.h>
66 #include <elf.h>
67 
68 #define HWCAP_ARM_VFP 64
69 
70 int hasVFP(void)
71 {
72     int fd = open ("/proc/self/auxv", O_RDONLY);
73     if (fd == -1)
74         return -1;
75 
76     int ret = -1;
77 
78     Elf32_auxv_t buf[128];
79     ssize_t n;
80     while ((ret == -1) && ((n = read(fd, buf, sizeof (buf))) > 0))
81     {
82         for (int i = 0; i < 128; ++i)
83         {
84 	    if (buf[i].a_type == AT_HWCAP)
85 	    {
86                 ret = (buf[i].a_un.a_val & HWCAP_ARM_VFP) ? true : false;
87                 break;
88 	    }
89             else if (buf[i].a_type == AT_NULL)
90             {
91                 ret = -2;
92                 break;
93             }
94         }
95     }
96 
97     close (fd);
98     return ret;
99 }
100 
101 #endif
102 
103 using namespace ::rtl;
104 using namespace ::com::sun::star::uno;
105 
106 namespace arm
107 {
108     bool is_complex_struct(const typelib_TypeDescription * type)
109     {
110         const typelib_CompoundTypeDescription * p
111             = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
112         for (sal_Int32 i = 0; i < p->nMembers; ++i)
113         {
114             if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT ||
115                 p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
116             {
117                 typelib_TypeDescription * t = 0;
118                 TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
119                 bool b = is_complex_struct(t);
120                 TYPELIB_DANGER_RELEASE(t);
121                 if (b) {
122                     return true;
123                 }
124             }
125             else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
126                 return true;
127         }
128         if (p->pBaseTypeDescription != 0)
129             return is_complex_struct(&p->pBaseTypeDescription->aBase);
130         return false;
131     }
132 
133     bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
134     {
135         if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
136             return false;
137         else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
138         {
139             typelib_TypeDescription * pTypeDescr = 0;
140             TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
141 
142             //A Composite Type not larger than 4 bytes is returned in r0
143             bool bRet = pTypeDescr->nSize > 4 || is_complex_struct(pTypeDescr);
144 
145             TYPELIB_DANGER_RELEASE( pTypeDescr );
146             return bRet;
147         }
148         return true;
149     }
150 }
151 
152 void MapReturn(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference * pReturnType, sal_uInt32* pRegisterReturn)
153 {
154 #if !defined(__ARM_EABI__) && !defined(__SOFTFP__)
155     register float fret asm("f0");
156     register double dret asm("f0");
157 #endif
158 
159     switch( pReturnType->eTypeClass )
160     {
161         case typelib_TypeClass_HYPER:
162         case typelib_TypeClass_UNSIGNED_HYPER:
163             pRegisterReturn[1] = r1;
164         case typelib_TypeClass_LONG:
165         case typelib_TypeClass_UNSIGNED_LONG:
166         case typelib_TypeClass_ENUM:
167         case typelib_TypeClass_CHAR:
168         case typelib_TypeClass_SHORT:
169         case typelib_TypeClass_UNSIGNED_SHORT:
170         case typelib_TypeClass_BOOLEAN:
171         case typelib_TypeClass_BYTE:
172             pRegisterReturn[0] = r0;
173             break;
174         case typelib_TypeClass_FLOAT:
175 #if defined(__ARM_EABI__) || defined(__SOFTFP__)
176             pRegisterReturn[0] = r0;
177 #else
178             *(float*)pRegisterReturn = fret;
179 #endif
180 	    break;
181         case typelib_TypeClass_DOUBLE:
182 #if defined(__ARM_EABI__) || defined(__SOFTFP__)
183             pRegisterReturn[1] = r1;
184             pRegisterReturn[0] = r0;
185 #else
186             *(double*)pRegisterReturn = dret;
187 #endif
188             break;
189         case typelib_TypeClass_STRUCT:
190         case typelib_TypeClass_EXCEPTION:
191         {
192             if (!arm::return_in_hidden_param(pReturnType))
193                 pRegisterReturn[0] = r0;
194             break;
195         }
196         default:
197             break;
198     }
199 }
200 
201 namespace
202 {
203 //================================================================
204 
205 void callVirtualMethod(
206     void * pThis,
207     sal_Int32 nVtableIndex,
208     void * pRegisterReturn,
209     typelib_TypeDescriptionReference * pReturnType,
210     sal_uInt32 *pStack,
211     sal_uInt32 nStack,
212     sal_uInt32 *pGPR,
213     sal_uInt32 nGPR) __attribute__((noinline));
214 
215 void callVirtualMethod(
216     void * pThis,
217     sal_Int32 nVtableIndex,
218     void * pRegisterReturn,
219     typelib_TypeDescriptionReference * pReturnType,
220     sal_uInt32 *pStack,
221     sal_uInt32 nStack,
222     sal_uInt32 *pGPR,
223     sal_uInt32 nGPR)
224 {
225     // never called
226     if (! pThis)
227         CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
228 
229     if ( nStack )
230     {
231         // 8-bytes aligned
232         sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 8;
233         sal_uInt32 *stack = (sal_uInt32 *) __builtin_alloca( nStackBytes );
234         memcpy( stack, pStack, nStackBytes );
235     }
236 
237     // Should not happen, but...
238     if ( nGPR > arm::MAX_GPR_REGS )
239         nGPR = arm::MAX_GPR_REGS;
240 
241     sal_uInt32 pMethod = *((sal_uInt32*)pThis);
242     pMethod += 4 * nVtableIndex;
243     pMethod = *((sal_uInt32 *)pMethod);
244 
245     typedef void (*FunctionCall )( sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32);
246     FunctionCall pFunc = (FunctionCall)pMethod;
247 
248     (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3]);
249 
250     sal_uInt32 r0;
251     sal_uInt32 r1;
252 
253     // get return value
254     __asm__ __volatile__ (
255         "mov %0, r0\n\t"
256         "mov %1, r1\n\t"
257         : "=r" (r0), "=r" (r1) : );
258 
259     MapReturn(r0, r1, pReturnType, (sal_uInt32*)pRegisterReturn);
260 }
261 }
262 
263 #define INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow ) \
264         if ( nr < arm::MAX_GPR_REGS ) \
265                 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
266         else \
267                 bOverFlow = true; \
268         if (bOverFlow) \
269                 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
270 
271 #ifdef __ARM_EABI__
272 #define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \
273         if ( (nr < arm::MAX_GPR_REGS) && (nr % 2) ) \
274         { \
275             	++nr; \
276         } \
277         if ( nr < arm::MAX_GPR_REGS ) \
278         { \
279                 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
280                 pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \
281         } \
282         else \
283                 bOverFlow = true; \
284         if (bOverFlow) \
285 	{ \
286 		if ( (pDS - pStart) % 2) \
287                 { \
288                 	++pDS; \
289                 } \
290                 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \
291                 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \
292 	}
293 #else
294 #define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \
295         INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow) \
296         INSERT_INT32( ((sal_uInt32*)pSV)+1, nr, pGPR, pDS, bOverflow)
297 #endif
298 
299 #define INSERT_FLOAT( pSV, nr, pFPR, pDS, bOverflow ) \
300         INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow)
301 
302 #define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart, bOverflow ) \
303         INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow )
304 
305 #define INSERT_INT16( pSV, nr, pGPR, pDS, bOverflow ) \
306         if ( nr < arm::MAX_GPR_REGS ) \
307                 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
308         else \
309                 bOverFlow = true; \
310         if (bOverFlow) \
311                 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
312 
313 #define INSERT_INT8( pSV, nr, pGPR, pDS, bOverflow ) \
314         if ( nr < arm::MAX_GPR_REGS ) \
315                 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
316         else \
317                 bOverFlow = true; \
318         if (bOverFlow) \
319                 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
320 
321 namespace {
322 //=======================================================================
323 static void cpp_call(
324     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
325     bridges::cpp_uno::shared::VtableSlot aVtableSlot,
326     typelib_TypeDescriptionReference * pReturnTypeRef,
327     sal_Int32 nParams, typelib_MethodParameter * pParams,
328     void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
329 {
330     // max space for: [complex ret ptr], values|ptr ...
331     sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca(
332         sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
333     sal_uInt32 * pStackStart = pStack;
334 
335     sal_uInt32 pGPR[arm::MAX_GPR_REGS];
336     sal_uInt32 nGPR = 0;
337 
338     // return
339     typelib_TypeDescription * pReturnTypeDescr = 0;
340     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
341     OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
342 
343     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
344 
345     bool bOverFlow = false;
346     bool bSimpleReturn = true;
347     if (pReturnTypeDescr)
348     {
349         if (arm::return_in_hidden_param( pReturnTypeRef ) )
350             bSimpleReturn = false;
351 
352         if (bSimpleReturn)
353             pCppReturn = pUnoReturn; // direct way for simple types
354         else
355         {
356             // complex return via ptr
357             pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
358                     ? __builtin_alloca( pReturnTypeDescr->nSize )
359                     : pUnoReturn); // direct way
360 
361             INSERT_INT32( &pCppReturn, nGPR, pGPR, pStack, bOverFlow );
362         }
363     }
364     // push this
365     void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
366         + aVtableSlot.offset;
367     INSERT_INT32( &pAdjustedThisPtr, nGPR, pGPR, pStack, bOverFlow );
368 
369     // stack space
370     OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
371     // args
372     void ** pCppArgs  = (void **)alloca( 3 * sizeof(void *) * nParams );
373     // indizes of values this have to be converted (interface conversion cpp<=>uno)
374     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
375     // type descriptions for reconversions
376     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
377 
378     sal_Int32 nTempIndizes   = 0;
379 
380     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
381     {
382         const typelib_MethodParameter & rParam = pParams[nPos];
383         typelib_TypeDescription * pParamTypeDescr = 0;
384         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
385 
386         if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
387         {
388 //            uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos],
389             uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos],
390                 pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
391 
392             switch (pParamTypeDescr->eTypeClass)
393             {
394             case typelib_TypeClass_HYPER:
395             case typelib_TypeClass_UNSIGNED_HYPER:
396 #ifdef CMC_DEBUG
397 			    fprintf(stderr, "hyper is %lx\n", pCppArgs[nPos]);
398 #endif
399                 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart, bOverFlow );
400                 break;
401             case typelib_TypeClass_LONG:
402             case typelib_TypeClass_UNSIGNED_LONG:
403             case typelib_TypeClass_ENUM:
404 #ifdef CMC_DEBUG
405 			    fprintf(stderr, "long is %x\n", pCppArgs[nPos]);
406 #endif
407                 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
408                 break;
409             case typelib_TypeClass_SHORT:
410             case typelib_TypeClass_CHAR:
411             case typelib_TypeClass_UNSIGNED_SHORT:
412                 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
413                 break;
414             case typelib_TypeClass_BOOLEAN:
415             case typelib_TypeClass_BYTE:
416                 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
417                 break;
418             case typelib_TypeClass_FLOAT:
419                 INSERT_FLOAT( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
420 			    break;
421             case typelib_TypeClass_DOUBLE:
422                 INSERT_DOUBLE( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart, bOverFlow );
423                 break;
424             default:
425                 break;
426             }
427             // no longer needed
428             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
429         }
430         else // ptr to complex value | ref
431         {
432             if (! rParam.bIn) // is pure out
433             {
434                 // cpp out is constructed mem, uno out is not!
435                 uno_constructData(
436                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
437                     pParamTypeDescr );
438                 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
439                 // will be released at reconversion
440                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
441             }
442             // is in/inout
443             else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
444             {
445                 uno_copyAndConvertData(
446                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
447                     pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
448 
449                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
450                 // will be released at reconversion
451                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
452             }
453             else // direct way
454             {
455                 pCppArgs[nPos] = pUnoArgs[nPos];
456                 // no longer needed
457                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
458             }
459             INSERT_INT32( &(pCppArgs[nPos]), nGPR, pGPR, pStack, bOverFlow );
460         }
461     }
462 
463     try
464     {
465         callVirtualMethod(
466             pAdjustedThisPtr, aVtableSlot.index,
467             pCppReturn, pReturnTypeRef,
468             pStackStart,
469             (pStack - pStackStart),
470             pGPR, nGPR);
471 
472         // NO exception occured...
473         *ppUnoExc = 0;
474 
475         // reconvert temporary params
476         for ( ; nTempIndizes--; )
477         {
478             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
479             typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
480 
481             if (pParams[nIndex].bIn)
482             {
483                 if (pParams[nIndex].bOut) // inout
484                 {
485                     uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
486                     uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
487                                             pThis->getBridge()->getCpp2Uno() );
488                 }
489             }
490             else // pure out
491             {
492                 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
493                                         pThis->getBridge()->getCpp2Uno() );
494             }
495             // destroy temp cpp param => cpp: every param was constructed
496             uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
497 
498             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
499         }
500         // return value
501         if (pCppReturn && pUnoReturn != pCppReturn)
502         {
503             uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
504                                     pThis->getBridge()->getCpp2Uno() );
505             uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
506         }
507     }
508     catch (...)
509     {
510 //        __asm__ __volatile__ ("sub sp, sp, #2048\n");
511 
512         // fill uno exception
513         fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
514 
515         // temporary params
516         for ( ; nTempIndizes--; )
517         {
518             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
519             // destroy temp cpp param => cpp: every param was constructed
520             uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
521             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
522         }
523 
524         // return type
525         if (pReturnTypeDescr)
526             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
527     }
528 }
529 }
530 
531 namespace bridges { namespace cpp_uno { namespace shared {
532 
533 void unoInterfaceProxyDispatch(
534     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
535     void * pReturn, void * pArgs[], uno_Any ** ppException )
536 {
537     // is my surrogate
538     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
539           = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
540 #if OSL_DEBUG_LEVEL > 0
541     typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
542 #endif
543 
544     switch (pMemberDescr->eTypeClass)
545     {
546     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
547     {
548 #if OSL_DEBUG_LEVEL > 0
549         // determine vtable call index
550         sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
551         OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
552 #endif
553 
554         VtableSlot aVtableSlot(
555             getVtableSlot(
556             reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>
557               (pMemberDescr)));
558 
559         if (pReturn)
560         {
561             // dependent dispatch
562             cpp_call(
563                 pThis, aVtableSlot,
564                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
565                 0, 0, // no params
566                 pReturn, pArgs, ppException );
567         }
568         else
569         {
570             // is SET
571             typelib_MethodParameter aParam;
572             aParam.pTypeRef =
573                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
574             aParam.bIn      = sal_True;
575             aParam.bOut     = sal_False;
576 
577             typelib_TypeDescriptionReference * pReturnTypeRef = 0;
578             OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
579             typelib_typedescriptionreference_new(
580                 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
581 
582             // dependent dispatch
583             aVtableSlot.index += 1;
584             cpp_call(
585                 pThis, aVtableSlot, // get, then set method
586                 pReturnTypeRef,
587                 1, &aParam,
588                 pReturn, pArgs, ppException );
589 
590             typelib_typedescriptionreference_release( pReturnTypeRef );
591         }
592 
593         break;
594     }
595     case typelib_TypeClass_INTERFACE_METHOD:
596     {
597 #if OSL_DEBUG_LEVEL > 0
598         // determine vtable call index
599         sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
600         OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
601 #endif
602 
603         VtableSlot aVtableSlot(
604             getVtableSlot(
605             reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>
606               (pMemberDescr)));
607 
608         switch (aVtableSlot.index)
609         {
610             // standard calls
611         case 1: // acquire uno interface
612             (*pUnoI->acquire)( pUnoI );
613             *ppException = 0;
614             break;
615         case 2: // release uno interface
616             (*pUnoI->release)( pUnoI );
617             *ppException = 0;
618             break;
619         case 0: // queryInterface() opt
620         {
621             typelib_TypeDescription * pTD = 0;
622             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
623             if (pTD)
624             {
625                 uno_Interface * pInterface = 0;
626                 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
627                     pThis->getBridge()->getUnoEnv(),
628                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
629 
630                 if (pInterface)
631                 {
632                     ::uno_any_construct(
633                         reinterpret_cast< uno_Any * >( pReturn ),
634                         &pInterface, pTD, 0 );
635                     (*pInterface->release)( pInterface );
636                     TYPELIB_DANGER_RELEASE( pTD );
637                     *ppException = 0;
638                     break;
639                 }
640                 TYPELIB_DANGER_RELEASE( pTD );
641             }
642         } // else perform queryInterface()
643         default:
644             // dependent dispatch
645             cpp_call(
646                 pThis, aVtableSlot,
647                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
648                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
649                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
650                 pReturn, pArgs, ppException );
651         }
652         break;
653     }
654     default:
655     {
656         ::com::sun::star::uno::RuntimeException aExc(
657             OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
658             ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
659 
660         Type const & rExcType = ::getCppuType( &aExc );
661         // binary identical null reference
662         ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
663     }
664     }
665 }
666 
667 } } }
668 
669 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
670