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