1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <sal/config.h>
21
22 #include <exception>
23 #if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(DRAGONFLY)
24 #include <stdlib.h>
25 #else
26 #include <malloc.h>
27 #endif
28 #include <typeinfo>
29
30 #include <com/sun/star/uno/Exception.hpp>
31 #include <com/sun/star/uno/RuntimeException.hpp>
32 #include <com/sun/star/uno/genfunc.hxx>
33 #include <o3tl/runtimetooustring.hxx>
34 #include <uno/data.h>
35
36 #include "bridge.hxx"
37 #include "types.hxx"
38 #include "unointerfaceproxy.hxx"
39 #include "vtables.hxx"
40
41 #include "share.hxx"
42
43
44 using namespace ::com::sun::star::uno;
45
46 namespace
47 {
48
49
callVirtualMethod(void * pAdjustedThisPtr,sal_Int32 nVtableIndex,void * pRegisterReturn,typelib_TypeClass eReturnType,char * pPT,sal_Int32 * pStackLongs,sal_Int32 nStackLongs)50 static void callVirtualMethod(
51 void * pAdjustedThisPtr,
52 sal_Int32 nVtableIndex,
53 void * pRegisterReturn,
54 typelib_TypeClass eReturnType,
55 char * pPT,
56 sal_Int32 * pStackLongs,
57 sal_Int32 nStackLongs)
58 {
59
60 // parameter list is mixed list of * and values
61 // reference parameters are pointers
62
63 // the basic idea here is to use gpr[8] as a storage area for
64 // the future values of registers r3 to r10 needed for the call,
65 // and similarly fpr[8] as a storage area for the future values
66 // of floating point registers f1 to f8
67
68 unsigned long * mfunc; // actual function to be invoked
69 int gpr[8]; // storage for gpregisters, map to r3-r10
70 int off; // offset used to find function
71 #ifndef __NO_FPRS__
72 double fpr[8]; // storage for fpregisters, map to f1-f8
73 int f; // number of fprs mapped so far
74 double dret; // temporary function return values
75 #endif
76 int n; // number of gprs mapped so far
77 long *p; // pointer to parameter overflow area
78 int c; // character of parameter type being decoded
79 int iret, iret2;
80
81 // Because of the Power PC calling conventions we could be passing
82 // parameters in both register types and on the stack. To create the
83 // stack parameter area we need we now simply allocate local
84 // variable storage param[] that is at least the size of the parameter stack
85 // (more than enough space) which we can overwrite the parameters into.
86
87 // Note: This keeps us from having to decode the signature twice and
88 // prevents problems with later local variables.
89
90 // Note: could require up to 2*nStackLongs words of parameter stack area
91 // if the call has many float parameters (i.e. floats take up only 1
92 // word on the stack but double takes 2 words in parameter area in the
93 // stack frame.
94
95 // Update! Floats on the outgoing parameter stack only take up 1 word
96 // (stfs is used) which is not correct according to the ABI but we
97 // will match what the compiler does until this is figured out
98
99 // this grows the current stack to the appropriate size
100 // and sets the outgoing stack pointer p to the right place
101 __asm__ __volatile__ (
102 "rlwinm %0,%0,3,3,28\n\t"
103 "addi %0,%0,22\n\t"
104 "rlwinm %0,%0,0,4,28\n\t"
105 "lwz 0,0(1)\n\t"
106 "subf 1,%0,1\n\t"
107 "stw 0,0(1)\n\t"
108 : : "r" (nStackLongs) : "0" );
109
110 __asm__ __volatile__ ( "addi %0,1,8" : "=r" (p) : );
111
112 // never called
113 // if (! pAdjustedThisPtr ) dummy_can_throw_anything("xxx"); // address something
114
115
116 // now begin to load the C++ function arguments into storage
117 n = 0;
118 #ifndef __NO_FPRS__
119 f = 0;
120 #endif
121
122 // now we need to parse the entire signature string */
123 // until we get the END indicator */
124
125 // treat complex return pointer like any other parameter
126
127 #if 0
128 /* Let's figure out what is really going on here*/
129 fprintf(stderr,"callVirtualMethod parameters string is %s\n",pPT);
130 int k = nStackLongs;
131 long * q = (long *)pStackLongs;
132 while (k > 0) {
133 fprintf(stderr,"uno stack is: %x\n",*q);
134 k--;
135 q++;
136 }
137 #endif
138
139 /* parse the argument list up to the ending ) */
140 while (*pPT != 'X') {
141 c = *pPT;
142 switch (c) {
143 case 'D': /* type is double */
144 #ifndef __NO_FPRS__
145 if (f < 8) {
146 fpr[f++] = *((double *)pStackLongs); /* store in register */
147 #else
148 if (n & 1)
149 n++;
150 if (n < 8) {
151 gpr[n++] = *pStackLongs;
152 gpr[n++] = *(pStackLongs+1);
153 #endif
154 } else {
155 if (((long) p) & 4)
156 p++;
157 *p++ = *pStackLongs; /* or on the parameter stack */
158 *p++ = *(pStackLongs + 1);
159 }
160 pStackLongs += 2;
161 break;
162
163 case 'F': /* type is float */
164 /* this assumes that floats are stored as 1 32 bit word on param
165 stack and that if passed in parameter stack to C, should be
166 as double word.
167
168 Whoops: the abi is not actually followed by gcc, need to
169 store floats as a *single* word on outgoing parameter stack
170 to match what gcc actually does
171 */
172 #ifndef __NO_FPRS__
173 if (f < 8) {
174 fpr[f++] = *((float *)pStackLongs);
175 #else
176 if (n < 8) {
177 gpr[n++] = *pStackLongs;
178 #endif
179 } else {
180 #if 0 /* if abi were followed */
181 if (((long) p) & 4)
182 p++;
183 *((double *)p) = *((float *)pStackLongs);
184 p += 2;
185 #else
186 *((float *)p) = *((float *)pStackLongs);
187 p += 1;
188 #endif
189 }
190 pStackLongs += 1;
191 break;
192
193 case 'H': /* type is long long */
194 if (n & 1) n++; /* note even elements gpr[] will map to
195 odd registers*/
196 if (n <= 6) {
197 gpr[n++] = *pStackLongs;
198 gpr[n++] = *(pStackLongs+1);
199 } else {
200 if (((long) p) & 4)
201 p++;
202 *p++ = *pStackLongs;
203 *p++ = *(pStackLongs+1);
204 }
205 pStackLongs += 2;
206 break;
207
208 case 'S':
209 if (n < 8) {
210 gpr[n++] = *((unsigned short*)pStackLongs);
211 } else {
212 *p++ = *((unsigned short *)pStackLongs);
213 }
214 pStackLongs += 1;
215 break;
216
217 case 'B':
218 if (n < 8) {
219 gpr[n++] = *((char *)pStackLongs);
220 } else {
221 *p++ = *((char *)pStackLongs);
222 }
223 pStackLongs += 1;
224 break;
225
226 default:
227 if (n < 8) {
228 gpr[n++] = *pStackLongs;
229 } else {
230 *p++ = *pStackLongs;
231 }
232 pStackLongs += 1;
233 break;
234 }
235 pPT++;
236 }
237
238 /* figure out the address of the function we need to invoke */
239 off = nVtableIndex;
240 off = off * 4; // 4 bytes per slot
241 mfunc = *((unsigned long **)pAdjustedThisPtr); // get the address of the vtable
242 mfunc = (unsigned long *)((char *)mfunc + off); // get the address from the vtable entry at offset
243 mfunc = *((unsigned long **)mfunc); // the function is stored at the address
244 typedef void (*FunctionCall)(sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32);
245 FunctionCall ptr = (FunctionCall)mfunc;
246
247 /* Set up the machine registers and invoke the function */
248
249 __asm__ __volatile__ (
250 "lwz 3, 0(%0)\n\t"
251 "lwz 4, 4(%0)\n\t"
252 "lwz 5, 8(%0)\n\t"
253 "lwz 6, 12(%0)\n\t"
254 "lwz 7, 16(%0)\n\t"
255 "lwz 8, 20(%0)\n\t"
256 "lwz 9, 24(%0)\n\t"
257 "lwz 10, 28(%0)\n\t"
258 #ifndef __NO_FPRS__
259 "lfd 1, 0(%1)\n\t"
260 "lfd 2, 8(%1)\n\t"
261 "lfd 3, 16(%1)\n\t"
262 "lfd 4, 24(%1)\n\t"
263 "lfd 5, 32(%1)\n\t"
264 "lfd 6, 40(%1)\n\t"
265 "lfd 7, 48(%1)\n\t"
266 "lfd 8, 56(%1)\n\t"
267 : : "r" (gpr), "r" (fpr)
268 #else
269 : : "r" (gpr)
270 #endif
271 : "0", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"
272 );
273
274 // tell gcc that r3 to r10 are not available to it for doing the TOC and exception munge on the func call
275 register sal_uInt32 r3 __asm__("r3");
276 register sal_uInt32 r4 __asm__("r4");
277 register sal_uInt32 r5 __asm__("r5");
278 register sal_uInt32 r6 __asm__("r6");
279 register sal_uInt32 r7 __asm__("r7");
280 register sal_uInt32 r8 __asm__("r8");
281 register sal_uInt32 r9 __asm__("r9");
282 register sal_uInt32 r10 __asm__("r10");
283
284 (*ptr)(r3, r4, r5, r6, r7, r8, r9, r10);
285
286 __asm__ __volatile__ (
287 "mr %0, 3\n\t"
288 "mr %1, 4\n\t"
289 #ifndef __NO_FPRS__
290 "fmr %2, 1\n\t"
291 : "=r" (iret), "=r" (iret2), "=f" (dret)
292 #else
293 : "=r" (iret), "=r" (iret2)
294 #endif
295 : );
296
297 switch( eReturnType )
298 {
299 case typelib_TypeClass_HYPER:
300 case typelib_TypeClass_UNSIGNED_HYPER:
301 ((long*)pRegisterReturn)[0] = iret;
302 ((long*)pRegisterReturn)[1] = iret2;
303 case typelib_TypeClass_LONG:
304 case typelib_TypeClass_UNSIGNED_LONG:
305 case typelib_TypeClass_ENUM:
306 ((long*)pRegisterReturn)[0] = iret;
307 break;
308 case typelib_TypeClass_CHAR:
309 case typelib_TypeClass_SHORT:
310 case typelib_TypeClass_UNSIGNED_SHORT:
311 *(unsigned short*)pRegisterReturn = (unsigned short)iret;
312 break;
313 case typelib_TypeClass_BOOLEAN:
314 case typelib_TypeClass_BYTE:
315 *(unsigned char*)pRegisterReturn = (unsigned char)iret;
316 break;
317 case typelib_TypeClass_FLOAT:
318 #ifndef __NO_FPRS__
319 *(float*)pRegisterReturn = (float)dret;
320 #else
321 ((unsigned int*)pRegisterReturn)[0] = iret;
322 #endif
323 break;
324 case typelib_TypeClass_DOUBLE:
325 #ifndef __NO_FPRS__
326 *(double*)pRegisterReturn = dret;
327 #else
328 ((unsigned int*)pRegisterReturn)[0] = iret;
329 ((unsigned int*)pRegisterReturn)[1] = iret2;
330 #endif
331 break;
332 default:
333 break;
334 }
335 }
336
337
338 static void cpp_call(
339 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
340 bridges::cpp_uno::shared::VtableSlot aVtableSlot,
341 typelib_TypeDescriptionReference * pReturnTypeRef,
342 sal_Int32 nParams, typelib_MethodParameter * pParams,
343 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
344 {
345 // max space for: [complex ret ptr], values|ptr ...
346 char * pCppStack =
347 (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
348 char * pCppStackStart = pCppStack;
349
350 // need to know parameter types for callVirtualMethod so generate a signature string
351 char * pParamType = (char *) alloca(nParams+2);
352 char * pPT = pParamType;
353
354 // return
355 typelib_TypeDescription * pReturnTypeDescr = 0;
356 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
357 // assert(pReturnTypeDescr);
358
359 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
360
361 if (pReturnTypeDescr)
362 {
363 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
364 {
365 pCppReturn = pUnoReturn; // direct way for simple types
366 }
367 else
368 {
369 // complex return via ptr
370 pCppReturn = *(void **)pCppStack =
371 (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
372 ? alloca( pReturnTypeDescr->nSize ): pUnoReturn); // direct way
373 *pPT++ = 'I'; //signify that a complex return type on stack
374 pCppStack += sizeof(void *);
375 }
376 }
377 // push this
378 void* pAdjustedThisPtr = reinterpret_cast< void **>(pThis->getCppI()) + aVtableSlot.offset;
379 *(void**)pCppStack = pAdjustedThisPtr;
380 pCppStack += sizeof( void* );
381 *pPT++ = 'I';
382
383 // stack space
384 // static_assert(sizeof(void *) == sizeof(sal_Int32), "### unexpected size!");
385 // args
386 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
387 // indices of values this have to be converted (interface conversion cpp<=>uno)
388 sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams);
389 // type descriptions for reconversions
390 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
391
392 sal_Int32 nTempIndices = 0;
393
394 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
395 {
396 const typelib_MethodParameter & rParam = pParams[nPos];
397 typelib_TypeDescription * pParamTypeDescr = 0;
398 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
399
400 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
401 {
402 uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr,
403 pThis->getBridge()->getUno2Cpp() );
404
405 switch (pParamTypeDescr->eTypeClass)
406 {
407
408 // we need to know type of each param so that we know whether to use
409 // gpr or fpr to pass in parameters:
410 // Key: I - int, long, pointer, etc means pass in gpr
411 // B - byte value passed in gpr
412 // S - short value passed in gpr
413 // F - float value pass in fpr
414 // D - double value pass in fpr
415 // H - long long int pass in proper pairs of gpr (3,4) (5,6), etc
416 // X - indicates end of parameter description string
417
418 case typelib_TypeClass_LONG:
419 case typelib_TypeClass_UNSIGNED_LONG:
420 case typelib_TypeClass_ENUM:
421 *pPT++ = 'I';
422 break;
423 case typelib_TypeClass_SHORT:
424 case typelib_TypeClass_CHAR:
425 case typelib_TypeClass_UNSIGNED_SHORT:
426 *pPT++ = 'S';
427 break;
428 case typelib_TypeClass_BOOLEAN:
429 case typelib_TypeClass_BYTE:
430 *pPT++ = 'B';
431 break;
432 case typelib_TypeClass_FLOAT:
433 *pPT++ = 'F';
434 break;
435 case typelib_TypeClass_DOUBLE:
436 *pPT++ = 'D';
437 pCppStack += sizeof(sal_Int32); // extra long
438 break;
439 case typelib_TypeClass_HYPER:
440 case typelib_TypeClass_UNSIGNED_HYPER:
441 *pPT++ = 'H';
442 pCppStack += sizeof(sal_Int32); // extra long
443 default:
444 break;
445 }
446
447 // no longer needed
448 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
449 }
450 else // ptr to complex value | ref
451 {
452 if (! rParam.bIn) // is pure out
453 {
454 // cpp out is constructed mem, uno out is not!
455 uno_constructData(
456 *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
457 pParamTypeDescr );
458 pTempIndices[nTempIndices] = nPos; // default constructed for cpp call
459 // will be released at reconversion
460 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
461 }
462 // is in/inout
463 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
464 {
465 uno_copyAndConvertData(
466 *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
467 pUnoArgs[nPos], pParamTypeDescr,
468 pThis->getBridge()->getUno2Cpp() );
469
470 pTempIndices[nTempIndices] = nPos; // has to be reconverted
471 // will be released at reconversion
472 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
473 }
474 else // direct way
475 {
476 *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
477 // no longer needed
478 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
479 }
480 // KBH: FIXME: is this the right way to pass these
481 *pPT++='I';
482 }
483 pCppStack += sizeof(sal_Int32); // standard parameter length
484 }
485
486 // terminate the signature string
487 *pPT++='X';
488 *pPT=0;
489
490 try
491 {
492 assert( !( (pCppStack - pCppStackStart ) & 3) && "UNALIGNED STACK !!! (Please DO panic)");
493 try {
494 callVirtualMethod(
495 pAdjustedThisPtr, aVtableSlot.index,
496 pCppReturn, pReturnTypeDescr->eTypeClass, pParamType,
497 (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) );
498 } catch (css::uno::Exception &) {
499 throw;
500 } catch (std::exception & e) {
501 throw css::uno::RuntimeException(
502 "C++ code threw " + o3tl::runtimeToOUString(typeid(e).name()) + ": "
503 + o3tl::runtimeToOUString(e.what()));
504 } catch (...) {
505 throw css::uno::RuntimeException("C++ code threw unknown exception");
506 }
507 // NO exception occurred...
508 *ppUnoExc = 0;
509
510 // reconvert temporary params
511 for ( ; nTempIndices--; )
512 {
513 sal_Int32 nIndex = pTempIndices[nTempIndices];
514 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
515
516 if (pParams[nIndex].bIn)
517 {
518 if (pParams[nIndex].bOut) // inout
519 {
520 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
521 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
522 pThis->getBridge()->getCpp2Uno() );
523 }
524 }
525 else // pure out
526 {
527 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
528 pThis->getBridge()->getCpp2Uno() );
529 }
530 // destroy temp cpp param => cpp: every param was constructed
531 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
532
533 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
534 }
535 // return value
536 if (pCppReturn && pUnoReturn != pCppReturn)
537 {
538 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
539 pThis->getBridge()->getCpp2Uno() );
540 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
541 }
542 }
543 catch (...)
544 {
545 // fill uno exception
546 CPPU_CURRENT_NAMESPACE::fillUnoException(*ppUnoExc, pThis->getBridge()->getCpp2Uno());
547
548 // temporary params
549 for ( ; nTempIndices--; )
550 {
551 sal_Int32 nIndex = pTempIndices[nTempIndices];
552 // destroy temp cpp param => cpp: every param was constructed
553 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release );
554 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
555 }
556 // return type
557 if (pReturnTypeDescr)
558 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
559 }
560 }
561
562 }
563
564 namespace bridges { namespace cpp_uno { namespace shared {
565
566 void unoInterfaceProxyDispatch(
567 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
568 void * pReturn, void * pArgs[], uno_Any ** ppException )
569 {
570 // is my surrogate
571 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
572 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI);
573
574 switch (pMemberDescr->eTypeClass)
575 {
576 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
577 {
578
579 VtableSlot aVtableSlot(
580 getVtableSlot(
581 reinterpret_cast<
582 typelib_InterfaceAttributeTypeDescription const * >(
583 pMemberDescr)));
584
585 if (pReturn)
586 {
587 // dependent dispatch
588 cpp_call(
589 pThis, aVtableSlot,
590 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
591 0, 0, // no params
592 pReturn, pArgs, ppException );
593 }
594 else
595 {
596 // is SET
597 typelib_MethodParameter aParam;
598 aParam.pTypeRef =
599 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
600 aParam.bIn = sal_True;
601 aParam.bOut = sal_False;
602
603 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
604 OUString aVoidName("void");
605 typelib_typedescriptionreference_new(
606 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
607
608 // dependent dispatch
609 aVtableSlot.index += 1; //get then set method
610 cpp_call(
611 pThis, aVtableSlot,
612 pReturnTypeRef,
613 1, &aParam,
614 pReturn, pArgs, ppException );
615
616 typelib_typedescriptionreference_release( pReturnTypeRef );
617 }
618
619 break;
620 }
621 case typelib_TypeClass_INTERFACE_METHOD:
622 {
623
624 VtableSlot aVtableSlot(
625 getVtableSlot(
626 reinterpret_cast<
627 typelib_InterfaceMethodTypeDescription const * >(
628 pMemberDescr)));
629 switch (aVtableSlot.index)
630 {
631 // standard calls
632 case 1: // acquire uno interface
633 (*pUnoI->acquire)( pUnoI );
634 *ppException = 0;
635 break;
636 case 2: // release uno interface
637 (*pUnoI->release)( pUnoI );
638 *ppException = 0;
639 break;
640 case 0: // queryInterface() opt
641 {
642 typelib_TypeDescription * pTD = 0;
643 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
644 if (pTD)
645 {
646 uno_Interface * pInterface = 0;
647 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
648 pThis->pBridge->getUnoEnv(),
649 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
650
651 if (pInterface)
652 {
653 ::uno_any_construct(
654 reinterpret_cast< uno_Any * >( pReturn ),
655 &pInterface, pTD, 0 );
656 (*pInterface->release)( pInterface );
657 TYPELIB_DANGER_RELEASE( pTD );
658 *ppException = 0;
659 break;
660 }
661 TYPELIB_DANGER_RELEASE( pTD );
662 }
663 } // else perform queryInterface()
664 default:
665 // dependent dispatch
666 cpp_call(
667 pThis, aVtableSlot,
668 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
669 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
670 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
671 pReturn, pArgs, ppException );
672 }
673 break;
674 }
675 default:
676 {
677 ::com::sun::star::uno::RuntimeException aExc(
678 "illegal member type description!",
679 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
680
681 Type const & rExcType = cppu::UnoType<decltype(aExc)>::get();
682 // binary identical null reference
683 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
684 }
685 }
686 }
687
688 } } }
689
690 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
691