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 occurred...
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