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 "abi.hxx"
38 #include "mscx.hxx"
39
40 using namespace ::rtl;
41 using namespace ::com::sun::star::uno;
42
43 namespace
44 {
45
46 //==================================================================================================
47 extern "C" void callVirtualMethod(
48 void * pAdjustedThisPtr, sal_Int32 nVtableIndex,
49 void * pRegisterReturn, typelib_TypeClass eReturnTypeClass,
50 sal_uInt64 * pStackLongs, sal_uInt32 nStackLongs );
51
52 //==================================================================================================
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)53 static void cpp_call(
54 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
55 bridges::cpp_uno::shared::VtableSlot aVtableSlot,
56 typelib_TypeDescriptionReference * pReturnTypeRef,
57 sal_Int32 nParams, typelib_MethodParameter * pParams,
58 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) throw ()
59 {
60 // max space for: [complex ret ptr], values|ptr ...
61 sal_uInt64 *pStack = (sal_uInt64 *)alloca( (nParams + 3) * sizeof(sal_uInt64) );
62 sal_uInt64 *pStackStart = pStack;
63
64 // Push "this" pointer
65 void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
66 *pStack++ = *(sal_uInt64*)&pAdjustedThisPtr;
67
68 // return
69 typelib_TypeDescription * pReturnTypeDescr = 0;
70 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
71 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
72
73 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
74
75 if ( pReturnTypeDescr )
76 {
77 if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
78 {
79 // complex return via ptr
80 pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
81 alloca( pReturnTypeDescr->nSize ) : pUnoReturn; // direct way
82 *pStack++ = *(sal_uInt64*)&pCppReturn;
83 }
84 else
85 pCppReturn = pUnoReturn; // direct way for simple types
86 }
87
88 // Args
89 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
90 // Indices of values this have to be converted (interface conversion cpp<=>uno)
91 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
92 // Type descriptions for reconversions
93 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
94
95 sal_Int32 nTempIndizes = 0;
96
97 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
98 {
99 const typelib_MethodParameter & rParam = pParams[nPos];
100 typelib_TypeDescription * pParamTypeDescr = 0;
101 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
102
103 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
104 {
105 uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
106 pThis->getBridge()->getUno2Cpp() );
107
108 // pCppArgs[nPos] is the alloca(8) temp above, i.e. a POINTER to the
109 // converted value -- the value is *pCppArgs[nPos]. Using
110 // &pCppArgs[nPos] would read the array slot instead, passing the
111 // temp's address as the argument. (That form is correct only in the
112 // complex/ref branch below, where the pointer IS the argument.)
113 switch (pParamTypeDescr->eTypeClass)
114 {
115 case typelib_TypeClass_HYPER:
116 case typelib_TypeClass_UNSIGNED_HYPER:
117 *pStack++ = *(sal_uInt64*)pCppArgs[nPos];
118 break;
119 case typelib_TypeClass_LONG:
120 case typelib_TypeClass_UNSIGNED_LONG:
121 case typelib_TypeClass_ENUM:
122 *pStack++ = *(sal_uInt32*)pCppArgs[nPos];
123 break;
124 case typelib_TypeClass_SHORT:
125 case typelib_TypeClass_UNSIGNED_SHORT:
126 case typelib_TypeClass_CHAR:
127 *pStack++ = *(sal_uInt16*)pCppArgs[nPos];
128 break;
129 case typelib_TypeClass_BOOLEAN:
130 case typelib_TypeClass_BYTE:
131 *pStack++ = *(sal_uInt8*)pCppArgs[nPos];
132 break;
133 case typelib_TypeClass_FLOAT:
134 case typelib_TypeClass_DOUBLE:
135 *pStack++ = *(sal_uInt64*)pCppArgs[nPos]; // verbatim!
136 break;
137 default:
138 break;
139 }
140 // no longer needed
141 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
142 }
143 else // ptr to complex value | ref
144 {
145 if (! rParam.bIn) // is pure out
146 {
147 // cpp out is constructed mem, uno out is not!
148 uno_constructData(
149 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
150 pParamTypeDescr );
151 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
152 // will be released at reconversion
153 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
154 }
155 // is in/inout
156 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
157 {
158 uno_copyAndConvertData(
159 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
160 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
161
162 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
163 // will be released at reconversion
164 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
165 }
166 else // direct way
167 {
168 pCppArgs[nPos] = pUnoArgs[nPos];
169 // no longer needed
170 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
171 }
172 // here the POINTER is the argument (complex value passed by ref)
173 *pStack++ = (sal_uInt64)pCppArgs[nPos];
174 }
175 }
176
177 __try
178 {
179 // pCppI is mscx this pointer
180 callVirtualMethod(
181 pAdjustedThisPtr,
182 aVtableSlot.index,
183 pCppReturn, pReturnTypeDescr->eTypeClass,
184 pStackStart, (pStack - pStackStart) );
185 }
186 __except (CPPU_CURRENT_NAMESPACE::mscx_filterCppException(
187 GetExceptionInformation(),
188 *ppUnoExc, pThis->getBridge()->getCpp2Uno() ))
189 {
190 // *ppUnoExc was constructed by filter function
191 // temporary params
192 for ( ; nTempIndizes--; )
193 {
194 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
195 // destroy temp cpp param => cpp: every param was constructed
196 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
197 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
198 }
199 // return type
200 if (pReturnTypeDescr)
201 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
202 // end here
203 return;
204 }
205
206 // NO exception occurred
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( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
231
232 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
233 }
234 // return value
235 if (pCppReturn && pUnoReturn != pCppReturn)
236 {
237 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
238 pThis->getBridge()->getCpp2Uno() );
239 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
240 }
241 // return type
242 if (pReturnTypeDescr)
243 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
244 }
245
246 }
247
248 namespace bridges { namespace cpp_uno { namespace shared {
249
unoInterfaceProxyDispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberDescr,void * pReturn,void * pArgs[],uno_Any ** ppException)250 void unoInterfaceProxyDispatch(
251 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
252 void * pReturn, void * pArgs[], uno_Any ** ppException )
253 {
254 // is my surrogate
255 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
256 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
257
258 switch (pMemberDescr->eTypeClass)
259 {
260 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
261 {
262 VtableSlot aVtableSlot(
263 getVtableSlot(
264 reinterpret_cast<
265 typelib_InterfaceAttributeTypeDescription const * >(
266 pMemberDescr)));
267
268 if (pReturn)
269 {
270 // dependent dispatch
271 cpp_call(
272 pThis, aVtableSlot,
273 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
274 0, 0, // no params
275 pReturn, pArgs, ppException );
276 }
277 else
278 {
279 // is SET
280 typelib_MethodParameter aParam;
281 aParam.pTypeRef =
282 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
283 aParam.bIn = sal_True;
284 aParam.bOut = sal_False;
285
286 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
287 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
288 typelib_typedescriptionreference_new(
289 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
290
291 // dependent dispatch
292 aVtableSlot.index += 1; // get, then set method
293 cpp_call(
294 pThis, aVtableSlot, // get, then set method
295 pReturnTypeRef,
296 1, &aParam,
297 pReturn, pArgs, ppException );
298
299 typelib_typedescriptionreference_release( pReturnTypeRef );
300 }
301
302 break;
303 }
304 case typelib_TypeClass_INTERFACE_METHOD:
305 {
306 VtableSlot aVtableSlot(
307 getVtableSlot(
308 reinterpret_cast<
309 typelib_InterfaceMethodTypeDescription const * >(
310 pMemberDescr)));
311
312 switch (aVtableSlot.index)
313 {
314 // standard calls
315 case 1: // acquire uno interface
316 (*pUnoI->acquire)( pUnoI );
317 *ppException = 0;
318 break;
319 case 2: // release uno interface
320 (*pUnoI->release)( pUnoI );
321 *ppException = 0;
322 break;
323 case 0: // queryInterface() opt
324 {
325 typelib_TypeDescription * pTD = 0;
326 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
327 if (pTD)
328 {
329 uno_Interface * pInterface = 0;
330 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
331 pThis->getBridge()->getUnoEnv(),
332 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
333
334 if (pInterface)
335 {
336 ::uno_any_construct(
337 reinterpret_cast< uno_Any * >( pReturn ),
338 &pInterface, pTD, 0 );
339 (*pInterface->release)( pInterface );
340 TYPELIB_DANGER_RELEASE( pTD );
341 *ppException = 0;
342 break;
343 }
344 TYPELIB_DANGER_RELEASE( pTD );
345 }
346 } // else perform queryInterface()
347 default:
348 // dependent dispatch
349 cpp_call(
350 pThis, aVtableSlot,
351 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
352 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
353 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
354 pReturn, pArgs, ppException );
355 }
356 break;
357 }
358 default:
359 {
360 ::com::sun::star::uno::RuntimeException aExc(
361 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
362 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
363
364 Type const & rExcType = ::getCppuType( &aExc );
365 // binary identical null reference
366 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
367 }
368 }
369 }
370
371 } } }
372