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 <sal/alloca.h>
32 
33 #include <com/sun/star/uno/genfunc.hxx>
34 #include "com/sun/star/uno/RuntimeException.hpp"
35 #include <uno/data.h>
36 
37 #include "bridges/cpp_uno/shared/bridge.hxx"
38 #include "bridges/cpp_uno/shared/types.hxx"
39 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
40 #include "bridges/cpp_uno/shared/vtables.hxx"
41 
42 #include "cc50_solaris_sparc.hxx"
43 
44 using namespace rtl;
45 using namespace com::sun::star::uno;
46 
47 namespace
48 {
49 
50 extern "C" void callVirtualMethod(
51 		void * pAdjustedThisPtr,
52 		sal_Int32 nVtableIndex,
53 		void * pRegisterReturn,
54 		typelib_TypeClass eReturnType,
55 		sal_Int32 * pStackLongs,
56 		sal_Int32 nStackLongs
57     );
58 
59 //==================================================================================================
60 static void cpp_call(
61 	bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
62 	bridges::cpp_uno::shared::VtableSlot aVtableSlot,
63 	typelib_TypeDescriptionReference * pReturnTypeRef,
64 	sal_Int32 nParams, typelib_MethodParameter * pParams,
65 	void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
66 {
67   	// pCppI is cc50_solaris_sparc this pointer
68   	OSL_ENSURE( pThis, "### no interface given!" );
69 
70   	// max space for: [complex ret ptr], values|ptr ...
71   	char * pCppStack		= (char *)alloca( ((nParams+3) * sizeof(sal_Int64)) );
72   	char * pCppStackStart	= pCppStack;
73 
74   	// return
75 	typelib_TypeDescription * pReturnTypeDescr = 0;
76 	TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
77 	OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
78 
79   	void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
80 
81 	if (pReturnTypeDescr)
82 	{
83 		if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
84 		{
85 			pCppReturn = pUnoReturn; // direct way for simple types
86 		}
87 		else
88 		{
89 			// complex return via ptr
90 			pCppReturn = *(void **)pCppStack
91                 = (bridges::cpp_uno::shared::relatesToInterfaceType(
92                        pReturnTypeDescr )
93                    ? alloca( pReturnTypeDescr->nSize )
94                    : pUnoReturn); // direct way
95 			pCppStack += sizeof(void *);
96 		}
97 	}
98 	// push this
99     void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
100         + aVtableSlot.offset;
101 	*(void**)pCppStack = pAdjustedThisPtr;
102 	pCppStack += sizeof( void* );
103 
104 	// args
105 	void ** pCppArgs  = (void **)alloca( 3 * sizeof(void *) * nParams );
106 	// indizes of values this have to be converted (interface conversion cpp<=>uno)
107 	sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
108 	// type descriptions for reconversions
109 	typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
110 
111   	sal_Int32 nTempIndizes   = 0;
112 
113   	for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
114   	{
115 		const typelib_MethodParameter & rParam = pParams[nPos];
116 		typelib_TypeDescription * pParamTypeDescr = 0;
117 		TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
118 
119 		if (!rParam.bOut
120             && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
121 		{
122 			pCppArgs[ nPos ] = CPPU_CURRENT_NAMESPACE::adjustPointer(
123                 pCppStack, pParamTypeDescr );
124 			uno_copyAndConvertData( pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr,
125 									pThis->getBridge()->getUno2Cpp() );
126 
127 			switch (pParamTypeDescr->eTypeClass)
128 			{
129 			case typelib_TypeClass_HYPER:
130 			case typelib_TypeClass_UNSIGNED_HYPER:
131 			case typelib_TypeClass_DOUBLE:
132 				pCppStack += sizeof(sal_Int32); // extra long
133 			}
134 			// no longer needed
135 			TYPELIB_DANGER_RELEASE( pParamTypeDescr );
136 		}
137 		else // ptr to complex value | ref
138 		{
139 			if (! rParam.bIn) // is pure out
140 			{
141 				// cpp out is constructed mem, uno out is not!
142 				uno_constructData(
143 					*(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
144 					pParamTypeDescr );
145 				pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
146 				// will be released at reconversion
147 				ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
148 			}
149 			// is in/inout
150 			else if (bridges::cpp_uno::shared::relatesToInterfaceType(
151                          pParamTypeDescr ))
152 			{
153 				uno_copyAndConvertData(
154 					*(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
155 					pUnoArgs[nPos], pParamTypeDescr,
156                     pThis->getBridge()->getUno2Cpp() );
157 
158 				pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
159 				// will be released at reconversion
160 				ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
161 			}
162 			else // direct way
163 			{
164 				*(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
165 				// no longer needed
166 				TYPELIB_DANGER_RELEASE( pParamTypeDescr );
167 			}
168 		}
169 		pCppStack += sizeof(sal_Int32); // standard parameter length
170   	}
171 
172 // seems that EH registration for callVirtualMethod is not really
173 // necessary
174 
175 // 	static unsigned long* pFrameInfo = NULL;
176 
177 // 	if( ! pFrameInfo )
178 // 	{
179 // 		pFrameInfo = new unsigned long[ 7 ];
180 // 		pFrameInfo[ 0 ] = 0x40000000 | (((unsigned long)__Crun::ex_rethrow_q) >> 2);
181 // 		pFrameInfo[ 1 ] = 0x01000000;
182 // 		pFrameInfo[ 2 ] = (unsigned long)callVirtualMethodExceptionHandler;
183 // 		pFrameInfo[ 3 ] = 0;
184 //     		pFrameInfo[ 4 ] = (unsigned long)pFrameInfo - (unsigned long)callVirtualMethodExceptionHandler;
185 // 		pFrameInfo[ 5 ] = 0;
186 // 		pFrameInfo[ 6 ] = 0;
187 // 		_ex_register( pFrameInfo+2, 1 );
188 // 	}
189 
190  	try
191   	{
192 		int nStackLongs = (pCppStack - pCppStackStart)/sizeof(sal_Int32);
193 		if( nStackLongs & 1 )
194 			// stack has to be 8 byte aligned
195 			nStackLongs++;
196 
197 		callVirtualMethod(
198 			pAdjustedThisPtr,
199 			aVtableSlot.index,
200 			pCppReturn,
201 			pReturnTypeDescr->eTypeClass,
202 			(sal_Int32 *)pCppStackStart,
203 			nStackLongs
204 			);
205 
206 		// NO exception occured...
207 		*ppUnoExc = 0;
208 
209 		// reconvert temporary params
210 		for ( ; nTempIndizes--; )
211 		{
212 			sal_Int32 nIndex = pTempIndizes[nTempIndizes];
213 			typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
214 
215 			if (pParams[nIndex].bIn)
216 			{
217 				if (pParams[nIndex].bOut) // inout
218 				{
219 					uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
220 					uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
221 											pThis->getBridge()->getCpp2Uno() );
222 				}
223 			}
224 			else // pure out
225 			{
226 				uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
227 										pThis->getBridge()->getCpp2Uno() );
228 			}
229 			// destroy temp cpp param => cpp: every param was constructed
230 			uno_destructData(
231                 pCppArgs[nIndex], pParamTypeDescr,
232                 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
233 
234 			TYPELIB_DANGER_RELEASE( pParamTypeDescr );
235 		}
236 		// return value
237 		if (pCppReturn && pUnoReturn != pCppReturn)
238 		{
239 			uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
240 									pThis->getBridge()->getCpp2Uno() );
241 			uno_destructData(
242                 pCppReturn, pReturnTypeDescr,
243                 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
244 		}
245  	}
246  	catch( ... )
247  	{
248         void* pExc = __Crun::ex_get();
249         const char* pName = __Cimpl::ex_name();
250 
251         // get exception
252         CPPU_CURRENT_NAMESPACE::cc50_solaris_sparc_fillUnoException(
253             pExc, pName, *ppUnoExc, pThis->getBridge()->getCpp2Uno());
254 
255 		// temporary params
256 		for ( ; nTempIndizes--; )
257 		{
258 			sal_Int32 nIndex = pTempIndizes[nTempIndizes];
259 			// destroy temp cpp param => cpp: every param was constructed
260 			uno_destructData(
261                 pCppArgs[nIndex],
262                 ppTempParamTypeDescr[nTempIndizes],
263                 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
264 			TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
265 		}
266 		// return type
267 		if (pReturnTypeDescr)
268 			TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
269   	}
270 }
271 
272 }
273 
274 namespace bridges { namespace cpp_uno { namespace shared {
275 
276 void unoInterfaceProxyDispatch(
277 	uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
278 	void * pReturn, void * pArgs[], uno_Any ** ppException )
279 {
280 	// is my surrogate
281 	bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
282         = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
283 	typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
284 
285 	switch (pMemberDescr->eTypeClass)
286 	{
287 	case typelib_TypeClass_INTERFACE_ATTRIBUTE:
288 	{
289         VtableSlot aVtableSlot(
290             getVtableSlot(
291                 reinterpret_cast<
292                     typelib_InterfaceAttributeTypeDescription const * >(
293                         pMemberDescr)));
294 		if (pReturn)
295 		{
296 			// dependent dispatch
297 			cpp_call(
298 				pThis, aVtableSlot,
299 				((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
300 				0, 0, // no params
301 				pReturn, pArgs, ppException );
302 		}
303 		else
304 		{
305 			// is SET
306 			typelib_MethodParameter aParam;
307 			aParam.pTypeRef =
308 				((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
309 			aParam.bIn		= sal_True;
310 			aParam.bOut		= sal_False;
311 
312 			typelib_TypeDescriptionReference * pReturnTypeRef = 0;
313 			OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
314 			typelib_typedescriptionreference_new(
315 				&pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
316 
317 			// dependent dispatch
318             aVtableSlot.index += 1; // get, then set method
319 			cpp_call(
320 				pThis, aVtableSlot,
321 				pReturnTypeRef,
322 				1, &aParam,
323 				pReturn, pArgs, ppException );
324 
325 			typelib_typedescriptionreference_release( pReturnTypeRef );
326 		}
327 
328 		break;
329 	}
330 	case typelib_TypeClass_INTERFACE_METHOD:
331 	{
332         VtableSlot aVtableSlot(
333             getVtableSlot(
334                 reinterpret_cast<
335                     typelib_InterfaceMethodTypeDescription const * >(
336                         pMemberDescr)));
337 		switch (aVtableSlot.index)
338 		{
339 			// standard calls
340 		case 1: // acquire uno interface
341 			(*pUnoI->acquire)( pUnoI );
342 			*ppException = 0;
343 			break;
344 		case 2: // release uno interface
345 			(*pUnoI->release)( pUnoI );
346 			*ppException = 0;
347 			break;
348 		case 0: // queryInterface() opt
349 		{
350 			typelib_TypeDescription * pTD = 0;
351 			TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
352 			if (pTD)
353 			{
354                 uno_Interface * pInterface = 0;
355                 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
356                     pThis->pBridge->getUnoEnv(),
357                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
358 
359                 if (pInterface)
360                 {
361                     ::uno_any_construct(
362                         reinterpret_cast< uno_Any * >( pReturn ),
363                         &pInterface, pTD, 0 );
364                     (*pInterface->release)( pInterface );
365                     TYPELIB_DANGER_RELEASE( pTD );
366                     *ppException = 0;
367                     break;
368                 }
369                 TYPELIB_DANGER_RELEASE( pTD );
370             }
371 		} // else perform queryInterface()
372 		default:
373 			// dependent dispatch
374 			cpp_call(
375 				pThis, aVtableSlot,
376 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
377 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
378 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
379 				pReturn, pArgs, ppException );
380 		}
381 		break;
382 	}
383 	default:
384 	{
385 		::com::sun::star::uno::RuntimeException aExc(
386 			OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
387 			::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
388 
389 		Type const & rExcType = ::getCppuType( &aExc );
390 		// binary identical null reference
391 		::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
392 	}
393 	}
394 }
395 
396 } } }
397