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