xref: /AOO41X/main/bridges/source/cpp_uno/gcc3_linux_ia64/uno2cpp.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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 
31 #include <malloc.h>
32 
33 #include <com/sun/star/uno/genfunc.hxx>
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 "share.hxx"
42 
43 #include <stdio.h>
44 #include <string.h>
45 
46 
47 using namespace ::rtl;
48 using namespace ::com::sun::star::uno;
49 
50 void MapReturn(const ia64::RegReturn &rRet, double dret, typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn, sal_uInt64 *pRegisterReturn)
51 {
52     switch (pReturnTypeDescr->eTypeClass)
53     {
54     case typelib_TypeClass_HYPER:
55     case typelib_TypeClass_UNSIGNED_HYPER:
56     case typelib_TypeClass_LONG:
57     case typelib_TypeClass_UNSIGNED_LONG:
58     case typelib_TypeClass_ENUM:
59             *pRegisterReturn = rRet.r8;
60             break;
61     case typelib_TypeClass_CHAR:
62     case typelib_TypeClass_SHORT:
63     case typelib_TypeClass_UNSIGNED_SHORT:
64             *pRegisterReturn = (unsigned short)rRet.r8;
65             break;
66     case typelib_TypeClass_BOOLEAN:
67     case typelib_TypeClass_BYTE:
68             *pRegisterReturn = (unsigned char)rRet.r8;
69             break;
70     case typelib_TypeClass_FLOAT:
71             *reinterpret_cast<float *>( pRegisterReturn ) = dret;
72 	    break;
73     case typelib_TypeClass_DOUBLE:
74             *reinterpret_cast<double *>( pRegisterReturn ) = dret;
75             break;
76     case typelib_TypeClass_STRUCT:
77     case typelib_TypeClass_EXCEPTION:
78         {
79             sal_uInt32 nRetSize = pReturnTypeDescr->nSize;
80             if (bSimpleReturn && nRetSize <= 32 && nRetSize > 0)
81                 memcpy(pRegisterReturn, (void*)&rRet, nRetSize);
82             break;
83         }
84     default:
85 	break;
86     }
87 }
88 
89 namespace ia64
90 {
91     bool is_complex_struct(const typelib_TypeDescription * type)
92     {
93         const typelib_CompoundTypeDescription * p
94             = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
95         for (sal_Int32 i = 0; i < p->nMembers; ++i)
96         {
97             if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT ||
98                 p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
99             {
100                 typelib_TypeDescription * t = 0;
101                 TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
102                 bool b = is_complex_struct(t);
103                 TYPELIB_DANGER_RELEASE(t);
104                 if (b) {
105                     return true;
106                 }
107             }
108             else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
109                 return true;
110         }
111         if (p->pBaseTypeDescription != 0)
112             return is_complex_struct(&p->pBaseTypeDescription->aBase);
113         return false;
114     }
115 
116     bool is_complex_struct( typelib_TypeDescriptionReference *pTypeRef )
117     {
118         if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
119 	{
120             typelib_TypeDescription * pTypeDescr = 0;
121             TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
122 
123             bool bRet = is_complex_struct( pTypeDescr );
124             TYPELIB_DANGER_RELEASE( pTypeDescr );
125 
126             return bRet;
127        }
128        return false;
129     }
130 
131     bool return_via_r8_buffer( typelib_TypeDescriptionReference *pTypeRef )
132     {
133         if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
134 	{
135             if (is_complex_struct( pTypeRef )) return false;
136 
137             typelib_TypeDescription * pTypeDescr = 0;
138             TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
139 
140             /* If the struct is larger than 32 bytes, then there is a buffer at r8 to stick the return value into  */
141             bool bRet = pTypeDescr->nSize > 32;
142             TYPELIB_DANGER_RELEASE( pTypeDescr );
143             return bRet;
144        }
145        return false;
146     }
147 
148     bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
149     {
150         if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
151             return false;
152         else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
153             return is_complex_struct( pTypeRef );
154         return true;
155     }
156 
157 
158 }
159 
160 namespace
161 {
162 //==================================================================================================
163 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
164 	void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn,
165         sal_uInt64 *pStack, sal_uInt32 nStack,
166         sal_uInt64 *pGPR, sal_uInt32 nGPR,
167         double *pFPR, sal_uInt32 nFPR)
168 {
169     // Stack, if used, must be 16-bytes aligned
170     if ( nStack )
171         nStack = ( nStack + 1 ) & ~1;
172 
173     // Should not happen, but...
174     if ( nFPR > ia64::MAX_SSE_REGS )
175         nFPR = ia64::MAX_SSE_REGS;
176     if ( nGPR > ia64::MAX_GPR_REGS )
177         nGPR = ia64::MAX_GPR_REGS;
178 
179 #ifdef CMC_DEBUG
180         // Let's figure out what is really going on here
181         {
182                 fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
183                 for ( unsigned int i = 0; i < nGPR; ++i )
184                         fprintf( stderr, "0x%lx, ", pGPR[i] );
185                 fprintf( stderr, "\nFPR's (%d): ", nFPR );
186                 for ( unsigned int i = 0; i < nFPR; ++i )
187                         fprintf( stderr, "0x%lx (%f), ", pFPR[i], pFPR[i] );
188                 fprintf( stderr, "\nStack (%d): ", nStack );
189                 for ( unsigned int i = 0; i < nStack; ++i )
190                         fprintf( stderr, "0x%lx, ", pStack[i] );
191                 fprintf( stderr, "\n" );
192 		fprintf( stderr, "pRegisterReturn is %p\n", pRegisterReturn);
193         }
194 #endif
195 
196     // Load parameters to stack, if necessary
197     sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca( nStack * 8 );
198     memcpy( stack, pStack, nStack * 8 );
199 
200     // To get pointer to method
201     // a) get the address of the vtable
202     sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
203     // b) get the address from the vtable entry at offset, each entry is 16bytes,
204     // 8 for function pointer, and 8 for global pointer
205     pMethod += 16 * nVtableIndex;
206 
207     typedef void (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 );
208     FunctionCall pFunc = (FunctionCall)pMethod;
209 
210     switch (nFPR) //deliberate fall through
211     {
212         case 8:
213             asm volatile("ldfd f15=%0" : : "m"(pFPR[7]) : "f15");
214         case 7:
215             asm volatile("ldfd f14=%0" : : "m"(pFPR[6]) : "f14");
216         case 6:
217             asm volatile("ldfd f13=%0" : : "m"(pFPR[5]) : "f13");
218         case 5:
219             asm volatile("ldfd f12=%0" : : "m"(pFPR[4]) : "f12");
220         case 4:
221             asm volatile("ldfd f11=%0" : : "m"(pFPR[3]) : "f11");
222         case 3:
223             asm volatile("ldfd f10=%0" : : "m"(pFPR[2]) : "f10");
224         case 2:
225             asm volatile("ldfd f9=%0" : : "m"(pFPR[1]) : "f9");
226         case 1:
227             asm volatile("ldfd f8=%0" : : "m"(pFPR[0]) : "f8");
228         default:
229             break;
230     }
231 
232     //stick the return area into r8 for big struct returning
233     asm volatile("ld8 r8=%0" : : "m"(pRegisterReturn) : "r8");
234 
235     (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3], pGPR[4], pGPR[5], pGPR[6], pGPR[7]);
236 
237     register double f8 asm("f8");
238     ia64::RegReturn ret;
239     {
240         register long r8 asm("r8"); ret.r8 = r8;
241         register long r9 asm("r9"); ret.r9 = r9;
242         register long r10 asm("r10"); ret.r10 = r10;
243         register long r11 asm("r11"); ret.r11 = r11;
244     }
245 
246     MapReturn(ret, f8, pReturnTypeDescr, bSimpleReturn, (sal_uInt64*)pRegisterReturn);
247 }
248 
249 // Macros for easier insertion of values to registers or stack
250 // pSV - pointer to the source
251 // nr - order of the value [will be increased if stored to register]
252 // pFPR, pGPR - pointer to the registers
253 // pDS - pointer to the stack [will be increased if stored here]
254 
255 // The value in %xmm register is already prepared to be retrieved as a float,
256 // thus we treat float and double the same
257 #define INSERT_FLOAT( pSV, nfr, pFPR, ngr, pGPR, pDS, bOverflow ) \
258         if ( nfr < ia64::MAX_SSE_REGS && ngr < ia64::MAX_GPR_REGS ) \
259                 pFPR[nfr++] = *reinterpret_cast<float *>( pSV ); \
260         if ( ngr < ia64::MAX_GPR_REGS ) \
261                 pGPR[ngr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
262         else \
263         	bOverFlow = true; \
264         if (bOverFlow) \
265                 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
266 
267 #define INSERT_DOUBLE( pSV, nfr, pFPR, ngr, pGPR, pDS, bOverflow ) \
268         if ( nfr < ia64::MAX_SSE_REGS && ngr < ia64::MAX_GPR_REGS ) \
269                 pFPR[nfr++] = *reinterpret_cast<double *>( pSV ); \
270         if ( ngr < ia64::MAX_GPR_REGS ) \
271                 pGPR[ngr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
272         else \
273         	bOverFlow = true; \
274         if (bOverFlow) \
275                 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
276 
277 #define INSERT_INT64( pSV, nr, pGPR, pDS, bOverflow ) \
278         if ( nr < ia64::MAX_GPR_REGS ) \
279                 pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
280         else \
281 		bOverFlow = true; \
282 	if (bOverFlow) \
283                 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
284 
285 #define INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow ) \
286         if ( nr < ia64::MAX_GPR_REGS ) \
287                 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
288         else \
289                 bOverFlow = true; \
290         if (bOverFlow) \
291                 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
292 
293 #define INSERT_INT16( pSV, nr, pGPR, pDS, bOverflow ) \
294         if ( nr < ia64::MAX_GPR_REGS ) \
295                 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
296         else \
297                 bOverFlow = true; \
298         if (bOverFlow) \
299                 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
300 
301 #define INSERT_INT8( pSV, nr, pGPR, pDS, bOverflow ) \
302         if ( nr < ia64::MAX_GPR_REGS ) \
303                 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
304         else \
305                 bOverFlow = true; \
306         if (bOverFlow) \
307                 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
308 
309 //==================================================================================================
310 static void cpp_call(
311 	bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
312 	bridges::cpp_uno::shared::VtableSlot  aVtableSlot,
313 	typelib_TypeDescriptionReference * pReturnTypeRef,
314 	sal_Int32 nParams, typelib_MethodParameter * pParams,
315 	void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
316 {
317   	// max space for: [complex ret ptr], values|ptr ...
318   	sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+3) * sizeof(sal_Int64) );
319   	sal_uInt64 * pStackStart = pStack;
320 
321 	sal_uInt64 pGPR[ia64::MAX_GPR_REGS];
322 	sal_uInt32 nGPR = 0;
323 
324 	double pFPR[ia64::MAX_SSE_REGS];
325 	sal_uInt32 nFPR = 0;
326 
327 	// return
328 	typelib_TypeDescription * pReturnTypeDescr = 0;
329 	TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
330 	OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
331 
332 	void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
333 
334         bool bOverFlow = false;
335 
336 	bool bSimpleReturn = true;
337 	if (pReturnTypeDescr)
338 	{
339 #ifdef CMC_DEBUG
340 		fprintf(stderr, "return type is %d\n", pReturnTypeDescr->eTypeClass);
341 #endif
342 		if ( ia64::return_in_hidden_param(pReturnTypeRef) || ia64::return_via_r8_buffer(pReturnTypeRef) )
343                         bSimpleReturn = false;
344 
345                 if ( bSimpleReturn )
346 		{
347 			pCppReturn = pUnoReturn; // direct way for simple types
348 #ifdef CMC_DEBUG
349 			fprintf(stderr, "simple return\n");
350 #endif
351 		}
352 		else
353 		{
354 			// complex return via ptr
355 			pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
356 			       ? alloca( pReturnTypeDescr->nSize ) : pUnoReturn);
357 #ifdef CMC_DEBUG
358 			fprintf(stderr, "pCppReturn/pUnoReturn is %lx/%lx", pCppReturn, pUnoReturn);
359 #endif
360                         if (!ia64::return_via_r8_buffer(pReturnTypeRef))
361 			    INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack, bOverFlow );
362 		}
363 	}
364 	// push "this" pointer
365         void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
366 
367 #ifdef CMC_DEBUG
368 	fprintf(stderr, "this pointer is %p\n", pAdjustedThisPtr);
369 #endif
370 	INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack, bOverFlow );
371 
372         // Args
373         void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
374 	// indizes of values this have to be converted (interface conversion cpp<=>uno)
375 	sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
376 	// type descriptions for reconversions
377 	typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
378 
379 	sal_Int32 nTempIndizes   = 0;
380 
381 #ifdef CMC_DEBUG
382 	fprintf(stderr, "n params is %d\n", nParams);
383 #endif
384 
385 	for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
386 	{
387 		const typelib_MethodParameter & rParam = pParams[nPos];
388 		typelib_TypeDescription * pParamTypeDescr = 0;
389 		TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
390 
391 #ifdef CMC_DEBUG
392 		fprintf(stderr, "param %d is %d %d %d\n", nPos, rParam.bOut, bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ),
393 			pParamTypeDescr->eTypeClass);
394 #endif
395 
396 		if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
397 		{
398 //			uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
399 			uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos], pParamTypeDescr,
400 									pThis->getBridge()->getUno2Cpp() );
401 		        switch (pParamTypeDescr->eTypeClass)
402                         {
403                         case typelib_TypeClass_HYPER:
404                         case typelib_TypeClass_UNSIGNED_HYPER:
405 #ifdef CMC_DEBUG
406 				fprintf(stderr, "hyper is %lx\n", *(unsigned long*)(pCppArgs[nPos]));
407 #endif
408                                 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
409                                 break;
410                         case typelib_TypeClass_LONG:
411                         case typelib_TypeClass_UNSIGNED_LONG:
412                         case typelib_TypeClass_ENUM:
413 #ifdef CMC_DEBUG
414 				fprintf(stderr, "long is %lx\n", *(unsigned int*)(pCppArgs[nPos]));
415 #endif
416                                 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
417                                 break;
418                         case typelib_TypeClass_SHORT:
419                         case typelib_TypeClass_CHAR:
420                         case typelib_TypeClass_UNSIGNED_SHORT:
421 #ifdef CMC_DEBUG
422 				fprintf(stderr, "short is %x\n", *(unsigned short*)(pCppArgs[nPos]));
423 #endif
424                                 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
425                                 break;
426                         case typelib_TypeClass_BOOLEAN:
427                         case typelib_TypeClass_BYTE:
428 #ifdef CMC_DEBUG
429 				fprintf(stderr, "byte is %x\n", *(unsigned char*)(pCppArgs[nPos]));
430 #endif
431                                 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
432                                 break;
433                         case typelib_TypeClass_FLOAT:
434 #ifdef CMC_DEBUG
435 				fprintf(stderr, "a float is %f\n", *(float*)(pCppArgs[nPos]));
436 				fprintf(stderr, "b float is %f\n", *(double*)(pCppArgs[nPos]));
437 #endif
438                                 INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR, nGPR, pGPR, pStack, bOverFlow );
439 				break;
440                         case typelib_TypeClass_DOUBLE:
441 #ifdef CMC_DEBUG
442 				fprintf(stderr, "double is %f\n", *(double*)(pCppArgs[nPos]));
443 #endif
444                                 INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, nGPR, pGPR, pStack, bOverFlow );
445                                 break;
446 			default:
447 				break;
448                         }
449 
450                         // no longer needed
451                         TYPELIB_DANGER_RELEASE( pParamTypeDescr );
452 
453 		}
454 		else // ptr to complex value | ref
455 		{
456 #ifdef CMC_DEBUG
457 			fprintf(stderr, "complex type again %d\n", rParam.bIn);
458 #endif
459                         if (! rParam.bIn) // is pure out
460                         {
461 #ifdef CMC_DEBUG
462 				fprintf(stderr, "complex size is %d\n", pParamTypeDescr->nSize );
463 #endif
464                                 // cpp out is constructed mem, uno out is not!
465                                 uno_constructData(
466                                         pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
467                                         pParamTypeDescr );
468                                 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
469                                 // will be released at reconversion
470                                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
471                         }
472                         // is in/inout
473                         else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
474                         {
475 #ifdef CMC_DEBUG
476 				fprintf(stderr, "this one\n");
477 #endif
478                                 uno_copyAndConvertData(
479                                         pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
480                                         pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
481 
482                                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
483                                 // will be released at reconversion
484                                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
485                         }
486                         else // direct way
487                         {
488 #ifdef CMC_DEBUG
489 				fprintf(stderr, "that one, passing %lx through\n", pUnoArgs[nPos]);
490 #endif
491                                 pCppArgs[nPos] = pUnoArgs[nPos];
492                                 // no longer needed
493                                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
494                         }
495                         INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack, bOverFlow );
496 		}
497 	}
498 
499 	try
500 	{
501                callVirtualMethod(
502                         pAdjustedThisPtr, aVtableSlot.index,
503                         pCppReturn, pReturnTypeDescr, bSimpleReturn,
504                         pStackStart, ( pStack - pStackStart ),
505                         pGPR, nGPR,
506                         pFPR, nFPR );
507 		// NO exception occured...
508 		*ppUnoExc = 0;
509 
510 		// reconvert temporary params
511 		for ( ; nTempIndizes--; )
512 		{
513 			sal_Int32 nIndex = pTempIndizes[nTempIndizes];
514 			typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
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 		fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions,
547                                   *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
548 
549 		// temporary params
550 		for ( ; nTempIndizes--; )
551 		{
552 			sal_Int32 nIndex = pTempIndizes[nTempIndizes];
553 			// destroy temp cpp param => cpp: every param was constructed
554 			uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
555 			TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
556 		}
557 		// return type
558 		if (pReturnTypeDescr)
559 			TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
560 	}
561 }
562 
563 }
564 
565 namespace bridges { namespace cpp_uno { namespace shared {
566 
567 void unoInterfaceProxyDispatch(
568 	uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
569 	void * pReturn, void * pArgs[], uno_Any ** ppException )
570 {
571 	// is my surrogate
572         bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
573             = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI);
574 
575 	switch (pMemberDescr->eTypeClass)
576 	{
577 	case typelib_TypeClass_INTERFACE_ATTRIBUTE:
578 	{
579 
580         VtableSlot aVtableSlot(
581             getVtableSlot(
582                 reinterpret_cast<
583                     typelib_InterfaceAttributeTypeDescription const * >(
584                         pMemberDescr)));
585 
586 		if (pReturn)
587 		{
588 			// dependent dispatch
589 			cpp_call(
590 				pThis, aVtableSlot,
591 				((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
592 				0, 0, // no params
593 				pReturn, pArgs, ppException );
594 		}
595 		else
596 		{
597 			// is SET
598 			typelib_MethodParameter aParam;
599 			aParam.pTypeRef =
600 				((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
601 			aParam.bIn		= sal_True;
602 			aParam.bOut		= sal_False;
603 
604 			typelib_TypeDescriptionReference * pReturnTypeRef = 0;
605 			OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
606 			typelib_typedescriptionreference_new(
607 				&pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
608 
609 			// dependent dispatch
610                         aVtableSlot.index += 1; //get then set method
611 			cpp_call(
612 				pThis, aVtableSlot,
613 				pReturnTypeRef,
614 				1, &aParam,
615 				pReturn, pArgs, ppException );
616 
617 			typelib_typedescriptionreference_release( pReturnTypeRef );
618 		}
619 
620 		break;
621 	}
622 	case typelib_TypeClass_INTERFACE_METHOD:
623 	{
624 
625         VtableSlot aVtableSlot(
626             getVtableSlot(
627                 reinterpret_cast<
628                     typelib_InterfaceMethodTypeDescription const * >(
629                         pMemberDescr)));
630 		switch (aVtableSlot.index)
631 		{
632 			// standard calls
633 		case 1: // acquire uno interface
634 			(*pUnoI->acquire)( pUnoI );
635 			*ppException = 0;
636 			break;
637 		case 2: // release uno interface
638 			(*pUnoI->release)( pUnoI );
639 			*ppException = 0;
640 			break;
641 		case 0: // queryInterface() opt
642 		{
643 			typelib_TypeDescription * pTD = 0;
644 			TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
645 			if (pTD)
646 			{
647                 uno_Interface * pInterface = 0;
648                 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
649                     pThis->pBridge->getUnoEnv(),
650                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
651 
652                 if (pInterface)
653                 {
654                     ::uno_any_construct(
655                         reinterpret_cast< uno_Any * >( pReturn ),
656                         &pInterface, pTD, 0 );
657                     (*pInterface->release)( pInterface );
658                     TYPELIB_DANGER_RELEASE( pTD );
659                     *ppException = 0;
660                     break;
661                 }
662                 TYPELIB_DANGER_RELEASE( pTD );
663             }
664 		} // else perform queryInterface()
665 		default:
666 			// dependent dispatch
667 			cpp_call(
668 				pThis, aVtableSlot,
669 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
670 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
671 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
672 				pReturn, pArgs, ppException );
673 		}
674 		break;
675 	}
676 	default:
677 	{
678 		::com::sun::star::uno::RuntimeException aExc(
679 			OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
680 			::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
681 
682 		Type const & rExcType = ::getCppuType( &aExc );
683 		// binary identical null reference
684 		::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
685 	}
686 	}
687 }
688 
689 } } }
690 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
691