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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_bridges.hxx"
30 #include <malloc.h>
31 #include <com/sun/star/uno/genfunc.hxx>
32 #include <uno/data.h>
33 
34 #include "bridges/cpp_uno/shared/bridge.hxx"
35 #include "bridges/cpp_uno/shared/types.hxx"
36 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
37 #include "bridges/cpp_uno/shared/vtables.hxx"
38 
39 #include "share.hxx"
40 
41 #include <sal/alloca.h>
42 
43 using namespace rtl;
44 using namespace com::sun::star::uno;
45 
46 namespace
47 {
48 //==================================================================================================
49 // The call instruction within the asm section of callVirtualMethod may throw
50 // exceptions.  So that the compiler handles this correctly, it is important
51 // that (a) callVirtualMethod might call dummy_can_throw_anything (although this
52 // never happens at runtime), which in turn can throw exceptions, and (b)
53 // callVirtualMethod is not inlined at its call site (so that any exceptions are
54 // caught which are thrown from the instruction calling callVirtualMethod):
55 
56 void callVirtualMethod( void * pAdjustedThisPtr,
57                         sal_Int32 nVtableIndex,
58                         void * pRegisterReturn,
59                         typelib_TypeClass eReturnType,
60                         sal_Int32 * pStackLongs,
61                         sal_Int32 nStackLongs ) __attribute__((noinline));
62 
63 void callVirtualMethod( void * pAdjustedThisPtr,
64                         sal_Int32 nVtableIndex,
65                         void * pRegisterReturn,
66                         typelib_TypeClass eReturnType,
67                         sal_Int32 * pStackLongs,
68                         sal_Int32 nStackLongs )
69 {
70 	// parameter list is mixed list of * and values
71 	// reference parameters are pointers
72 
73 	OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" );
74 	OSL_ENSURE( (sizeof(void *) == 4) &&
75 				 (sizeof(sal_Int32) == 4), "### unexpected size of int!" );
76 	OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" );
77 
78     // never called
79     if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
80 
81 	volatile long o0 = 0, o1 = 0; // for register returns
82 	volatile double f0d = 0;
83 	volatile float f0f = 0;
84 	volatile long long saveReg[7];
85 
86 	__asm__ (
87 		// save registers
88 		"std %%l0, [%4]\n\t"
89 		"mov %4, %%l0\n\t"
90 		"mov %%l0, %%l1\n\t"
91 		"add %%l0, 8, %%l0\n\t"
92 		"std %%l2, [%%l0]\n\t"
93 		"add %%l0, 8, %%l0\n\t"
94 		"std %%l4, [%%l0]\n\t"
95 		"add %%l0, 8, %%l0\n\t"
96 		"std %%o0, [%%l0]\n\t"
97 		"add %%l0, 8, %%l0\n\t"
98 		"std %%o2, [%%l0]\n\t"
99 		"add %%l0, 8, %%l0\n\t"
100 		"std %%o4, [%%l0]\n\t"
101 		"add %%l0, 8, %%l0\n\t"
102 		"std %%l6, [%%l0]\n\t"
103 		"mov %%l1, %%l7\n\t"
104 
105 		// increase our own stackframe if necessary
106 		"mov %%sp, %%l3\n\t"		// save stack ptr for readjustment
107 
108 		"subcc %%i5, 7, %%l0\n\t"
109 		"ble .LmoveOn\n\t"
110 		"nop\n\t"
111 
112 		"sll %%l0, 2, %%l0\n\t"
113 		"add %%l0, 96, %%l0\n\t"
114 		"mov %%sp, %%l1\n\t"		// old stack ptr
115 		"sub %%sp, %%l0, %%l0\n\t"	// future stack ptr
116 		"andcc %%l0, 7, %%g0\n\t"	// align stack to 8
117 		"be .LisAligned\n\t"
118 		"nop\n\t"
119 		"sub %%l0, 4, %%l0\n"
120 	".LisAligned:\n\t"
121 		"mov %%l0, %%o5\n\t"			// save newly computed stack ptr
122 		"add %%g0, 16, %%o4\n"
123 
124 		// now copy longs down to save register window
125 		// and local variables
126 	".LcopyDown:\n\t"
127 		"ld [%%l1], %%l2\n\t"
128 		"st %%l2,[%%l0]\n\t"
129 		"add %%l0, 4, %%l0\n\t"
130 		"add %%l1, 4, %%l1\n\t"
131 		"subcc %%o4, 1, %%o4\n\t"
132 		"bne .LcopyDown\n\t"
133 
134 		"mov %%o5, %%sp\n\t"		// move new stack ptr (hopefully) atomically
135 		// while register window is valid in both spaces
136 		// (scheduling might hit in copyDown loop)
137 
138 		"sub %%i5, 7, %%l0\n\t"		// copy parameters past the sixth to stack
139 		"add %%i4, 28, %%l1\n\t"
140 		"add %%sp, 92, %%l2\n"
141 	".LcopyLong:\n\t"
142 		"ld [%%l1], %%o0\n\t"
143 		"st %%o0, [%%l2]\n\t"
144 		"add %%l1, 4, %%l1\n\t"
145 		"add %%l2, 4, %%l2\n\t"
146 		"subcc %%l0, 1, %%l0\n\t"
147 		"bne .LcopyLong\n\t"
148 		"nop\n"
149 
150 	".LmoveOn:\n\t"
151 		"mov %%i5, %%l0\n\t"		// prepare out registers
152 		"mov %%i4, %%l1\n\t"
153 
154 		"ld [%%l1], %%o0\n\t"		// prepare complex return ptr
155 		"st %%o0, [%%sp+64]\n\t"
156 		"sub %%l0, 1, %%l0\n\t"
157 		"add %%l1, 4, %%l1\n\t"
158 
159 		"ld [%%l1], %%o0\n\t"
160 		"subcc %%l0, 1, %%l0\n\t"
161 		"be .LdoCall\n\t"
162 		"nop\n\t"
163 
164 		"add %%l1, 4, %%l1\n\t"
165 		"ld [%%l1], %%o1\n\t"
166 		"subcc %%l0, 1, %%l0\n\t"
167 		"be .LdoCall\n\t"
168 		"nop\n\t"
169 
170 		"add %%l1, 4, %%l1\n\t"
171 		"ld [%%l1], %%o2\n\t"
172 		"subcc %%l0, 1, %%l0\n\t"
173 		"be .LdoCall\n\t"
174 		"nop\n\t"
175 
176 		"add %%l1, 4, %%l1\n\t"
177 		"ld [%%l1], %%o3\n\t"
178 		"subcc %%l0, 1, %%l0\n\t"
179 		"be .LdoCall\n\t"
180 		"nop\n\t"
181 
182 		"add %%l1, 4, %%l1\n\t"
183 		"ld [%%l1], %%o4\n\t"
184 		"subcc %%l0, 1, %%l0\n\t"
185 		"be .LdoCall\n\t"
186 		"nop\n\t"
187 
188 		"add %%l1, 4, %%l1\n\t"
189 		"ld [%%l1], %%o5\n"
190 
191 	".LdoCall:\n\t"
192 		"ld [%%i0], %%l0\n\t"		// get vtable ptr
193 
194 "sll %%i1, 2, %%l6\n\t"
195 //        "add %%l6, 8, %%l6\n\t"
196 		"add %%l6, %%l0, %%l0\n\t"
197 // 		// vtable has 8byte wide entries,
198 // 		// upper half contains 2 half words, of which the first
199 // 		// is the this ptr patch !
200 // 		// first entry is (or __tf)
201 
202 // 		"ldsh [%%l0], %%l6\n\t"		// load this ptr patch
203 // 		"add %%l6, %%o0, %%o0\n\t"	// patch this ptr
204 
205 // 		"add %%l0, 4, %%l0\n\t"		// get virtual function ptr
206 		"ld [%%l0], %%l0\n\t"
207 
208 		"ld [%%i4], %%l2\n\t"
209 		"subcc %%l2, %%g0, %%l2\n\t"
210 		"bne .LcomplexCall\n\t"
211 		"nop\n\t"
212 		"call %%l0\n\t"
213 		"nop\n\t"
214 		"ba .LcallReturned\n\t"
215 		"nop\n"
216 	".LcomplexCall:\n\t"
217 		"call %%l0\n\t"
218 		"nop\n\t"
219 		"unimp\n"
220 
221 	".LcallReturned:\n\t"
222 		"mov %%l3, %%sp\n\t"		// readjust stack so that our locals are where they belong
223 		"st %%o0, %0\n\t"			// save possible return registers into our locals
224 		"st %%o1, %1\n\t"
225 		"std %%f0, %2\n\t"
226 		"st %%f0, %3\n\t"
227 
228 		// restore registers
229 		"ldd [%%l7], %%l0\n\t"
230 		"add %%l7, 8, %%l7\n\t"
231 		"ldd [%%l7], %%l2\n\t"
232 		"add %%l7, 8, %%l7\n\t"
233 		"ldd [%%l7], %%l4\n\t"
234 		"add %%l7, 8, %%l7\n\t"
235 		"ldd [%%l7], %%o0\n\t"
236 		"add %%l7, 8, %%l7\n\t"
237 		"ldd [%%l7], %%o2\n\t"
238 		"add %%l7, 8, %%l7\n\t"
239 		"ldd [%%l7], %%o4\n\t"
240 		"add %%l7, 8, %%l7\n\t"
241 		"ldd [%%l7], %%l6\n\t"
242 		: :
243 		"m"(o0),
244 		"m"(o1),
245 		"m"(f0d),
246 		"m"(f0f),
247 		"r"(&saveReg[0])
248 		);
249 	switch( eReturnType )
250 	{
251 		case typelib_TypeClass_HYPER:
252 		case typelib_TypeClass_UNSIGNED_HYPER:
253 			((long*)pRegisterReturn)[1] = o1;
254 		case typelib_TypeClass_LONG:
255 		case typelib_TypeClass_UNSIGNED_LONG:
256 		case typelib_TypeClass_ENUM:
257 			((long*)pRegisterReturn)[0] = o0;
258 			break;
259 		case typelib_TypeClass_CHAR:
260 		case typelib_TypeClass_SHORT:
261 		case typelib_TypeClass_UNSIGNED_SHORT:
262 			*(unsigned short*)pRegisterReturn = (unsigned short)o0;
263 			break;
264 		case typelib_TypeClass_BOOLEAN:
265 		case typelib_TypeClass_BYTE:
266 			*(unsigned char*)pRegisterReturn = (unsigned char)o0;
267 			break;
268 		case typelib_TypeClass_FLOAT:
269 			*(float*)pRegisterReturn = f0f;
270 			break;
271 		case typelib_TypeClass_DOUBLE:
272 			*(double*)pRegisterReturn = f0d;
273 			break;
274 	}
275 }
276 
277 //=================================================================================================
278 static void cpp_call(
279 	bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
280 	bridges::cpp_uno::shared::VtableSlot aVtableSlot,
281 	typelib_TypeDescriptionReference * pReturnTypeRef,
282 	sal_Int32 nParams, typelib_MethodParameter * pParams,
283 	void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
284 {
285   	// max space for: complex ret ptr, this, values|ptr ...
286   	char * pCppStack	=
287   		(char *)alloca( (nParams+2) * sizeof(sal_Int64) );
288   	char * pCppStackStart	= pCppStack;
289 
290 	// return
291 	typelib_TypeDescription * pReturnTypeDescr = 0;
292 	TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
293 	OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
294 
295 	void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
296 
297 	if (pReturnTypeDescr)
298 	{
299 		if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
300 		{
301 			pCppReturn = pUnoReturn; // direct way for simple types
302 			*(void**)pCppStack = NULL;
303 		}
304 		else
305 		{
306 			// complex return via ptr
307 			pCppReturn = *(void **)pCppStack = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr )
308 												? alloca( pReturnTypeDescr->nSize )
309 												: pUnoReturn); // direct way
310 		}
311 		pCppStack += sizeof(void*);
312 	}
313 	// push this
314 	void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
315   	       + aVtableSlot.offset;
316   	       *(void**)pCppStack = pAdjustedThisPtr;
317 	pCppStack += sizeof( void* );
318 
319 	// stack space
320 	OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
321 	// args
322 	void ** pCppArgs  = (void **)alloca( 3 * sizeof(void *) * nParams );
323 	// indizes of values this have to be converted (interface conversion cpp<=>uno)
324 	sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
325 	// type descriptions for reconversions
326 	typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
327 
328 	sal_Int32 nTempIndizes   = 0;
329 
330 	for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
331 	{
332 		const typelib_MethodParameter & rParam = pParams[nPos];
333 		typelib_TypeDescription * pParamTypeDescr = 0;
334 		TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
335 		if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
336 		{
337 			pCppArgs[ nPos ] = CPPU_CURRENT_NAMESPACE::adjustPointer(pCppStack, pParamTypeDescr );
338 
339 			switch (pParamTypeDescr->eTypeClass)
340 			{
341 			case typelib_TypeClass_HYPER:
342 			case typelib_TypeClass_UNSIGNED_HYPER:
343 			case typelib_TypeClass_DOUBLE:
344                         OSL_ASSERT( sizeof (double) == sizeof (sal_Int64) );
345                           *reinterpret_cast< sal_Int32 * >(pCppStack) =
346                           *reinterpret_cast< sal_Int32 const * >(pUnoArgs[ nPos ]);
347                           pCppStack += sizeof (sal_Int32);
348                           *reinterpret_cast< sal_Int32 * >(pCppStack) =
349                           *(reinterpret_cast< sal_Int32 const * >(pUnoArgs[ nPos ] ) + 1);
350                           break;
351             		default:
352                           uno_copyAndConvertData(
353                              pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr,
354                             pThis->getBridge()->getUno2Cpp() );
355                           break;
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 					*(void **)pCppStack = 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(
374   	                        pParamTypeDescr ))
375 			{
376 				uno_copyAndConvertData(
377 					*(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
378                                 	pUnoArgs[nPos], pParamTypeDescr,
379 					pThis->getBridge()->getUno2Cpp() );
380 
381 				pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
382 				// will be released at reconversion
383 				ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
384 			}
385 			else // direct way
386 			{
387 				*(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
388 				// no longer needed
389 				TYPELIB_DANGER_RELEASE( pParamTypeDescr );
390 			}
391 		}
392 		pCppStack += sizeof(sal_Int32); // standard parameter length
393 	}
394 
395 	try
396 	{
397 		int nStackLongs = (pCppStack - pCppStackStart)/sizeof(sal_Int32);
398 		OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic" );
399 
400 		if( nStackLongs & 1 )
401 			// stack has to be 8 byte aligned
402 			nStackLongs++;
403 		callVirtualMethod(
404 			pAdjustedThisPtr,
405 			aVtableSlot.index,
406 			pCppReturn,
407 			pReturnTypeDescr->eTypeClass,
408 			(sal_Int32 *)pCppStackStart,
409 			 nStackLongs);
410 		// NO exception occured...
411 		*ppUnoExc = 0;
412 
413 		// reconvert temporary params
414 		for ( ; nTempIndizes--; )
415 		{
416 			sal_Int32 nIndex = pTempIndizes[nTempIndizes];
417 			typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
418 
419 			if (pParams[nIndex].bIn)
420 			{
421 				if (pParams[nIndex].bOut) // inout
422 				{
423 					uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
424 					uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
425 											pThis->getBridge()->getCpp2Uno() );
426 				}
427 			}
428 			else // pure out
429 			{
430 				uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
431 										pThis->getBridge()->getCpp2Uno() );
432 			}
433 			// destroy temp cpp param => cpp: every param was constructed
434 			uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
435 
436 			TYPELIB_DANGER_RELEASE( pParamTypeDescr );
437 		}
438 		// return value
439 		if (pCppReturn && pUnoReturn != pCppReturn)
440 		{
441 			uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
442 									pThis->getBridge()->getCpp2Uno() );
443 			uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
444 		}
445 	}
446  	catch( ... )
447  	{
448  		// get exception
449 		   fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions,
450 								*ppUnoExc, pThis->getBridge()->getCpp2Uno() );
451 
452 		// temporary params
453 		for ( ; nTempIndizes--; )
454 		{
455 			sal_Int32 nIndex = pTempIndizes[nTempIndizes];
456 			// destroy temp cpp param => cpp: every param was constructed
457 			uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
458 			TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
459 		}
460 		// return type
461 		if (pReturnTypeDescr)
462 			TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
463 	}
464 }
465 
466 }
467 
468 namespace bridges { namespace cpp_uno { namespace shared {
469 
470 void unoInterfaceProxyDispatch(
471 	uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
472     void * pReturn, void * pArgs[], uno_Any ** ppException )
473 {
474 #if defined BRIDGES_DEBUG
475     OString cstr( OUStringToOString( pMemberDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
476     fprintf( stderr, "received dispatch( %s )\n", cstr.getStr() );
477 #endif
478 
479 	// is my surrogate
480 	bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
481        = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
482 	typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
483 
484 	switch (pMemberDescr->eTypeClass)
485 	{
486 	case typelib_TypeClass_INTERFACE_ATTRIBUTE:
487 	{
488 	 VtableSlot aVtableSlot(
489   	           getVtableSlot(
490   	               reinterpret_cast<
491   	                   typelib_InterfaceAttributeTypeDescription const * >(
492   	                       pMemberDescr)));
493 		if (pReturn)
494 		{
495 			// dependent dispatch
496 			cpp_call(
497 				pThis, aVtableSlot,
498 				((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
499 				0, 0, // no params
500 				pReturn, pArgs, ppException );
501 		}
502 		else
503 		{
504 			// is SET
505 			typelib_MethodParameter aParam;
506 			aParam.pTypeRef =
507 				((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
508 			aParam.bIn		= sal_True;
509 			aParam.bOut		= sal_False;
510 
511 			typelib_TypeDescriptionReference * pReturnTypeRef = 0;
512 			OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
513 			typelib_typedescriptionreference_new(
514 				&pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
515 
516 			// dependent dispatch
517 			aVtableSlot.index += 1; // get, then set method
518 			cpp_call(
519 				pThis, aVtableSlot,
520 				pReturnTypeRef,
521 				1, &aParam,
522 				pReturn, pArgs, ppException );
523 
524 			typelib_typedescriptionreference_release( pReturnTypeRef );
525 		}
526 
527 		break;
528 	}
529 	case typelib_TypeClass_INTERFACE_METHOD:
530 	{
531 		VtableSlot aVtableSlot(
532 		getVtableSlot(
533 		 reinterpret_cast<
534 		  typelib_InterfaceMethodTypeDescription const * >(
535 		  pMemberDescr)));
536 		switch (aVtableSlot.index)
537 		{
538 			// standard calls
539 		case 1: // acquire uno interface
540 			(*pUnoI->acquire)( pUnoI );
541 			*ppException = 0;
542 			break;
543 		case 2: // release uno interface
544 			(*pUnoI->release)( pUnoI );
545 			*ppException = 0;
546 			break;
547 		case 0: // queryInterface() opt
548 		{
549 			typelib_TypeDescription * pTD = 0;
550 			TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
551 			if (pTD)
552 			{
553                 uno_Interface * pInterface = 0;
554  		(*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
555  		  pThis->pBridge->getUnoEnv(),
556 				   (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
557 
558                 if (pInterface)
559                 {
560                     ::uno_any_construct(
561                         reinterpret_cast< uno_Any * >( pReturn ),
562                         &pInterface, pTD, 0 );
563                     (*pInterface->release)( pInterface );
564                     TYPELIB_DANGER_RELEASE( pTD );
565                     *ppException = 0;
566                     break;
567                 }
568                 TYPELIB_DANGER_RELEASE( pTD );
569             }
570 		} // else perform queryInterface()
571 		default:
572 			// dependent dispatch
573 			cpp_call(
574 				pThis, aVtableSlot,
575 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
576 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
577 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
578 				pReturn, pArgs, ppException );
579 		}
580 		break;
581 	}
582 	default:
583 	{
584 		::com::sun::star::uno::RuntimeException aExc(
585 			OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
586 			::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
587 
588 		Type const & rExcType = ::getCppuType( &aExc );
589 		// binary identical null reference
590 		::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
591 	}
592 	}
593 }
594 
595 } } }
596