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