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