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