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 switch (pParamTypeDescr->eTypeClass)
109 {
110 case typelib_TypeClass_HYPER:
111 case typelib_TypeClass_UNSIGNED_HYPER:
112 *pStack++ = *(sal_uInt64*)&pCppArgs[nPos];
113 break;
114 case typelib_TypeClass_LONG:
115 case typelib_TypeClass_UNSIGNED_LONG:
116 case typelib_TypeClass_ENUM:
117 *pStack++ = *(sal_uInt32*)&pCppArgs[nPos];
118 break;
119 case typelib_TypeClass_SHORT:
120 case typelib_TypeClass_UNSIGNED_SHORT:
121 case typelib_TypeClass_CHAR:
122 *pStack++ = *(sal_uInt16*)&pCppArgs[nPos];
123 break;
124 case typelib_TypeClass_BOOLEAN:
125 case typelib_TypeClass_BYTE:
126 *pStack++ = *(sal_uInt8*)&pCppArgs[nPos];
127 break;
128 case typelib_TypeClass_FLOAT:
129 case typelib_TypeClass_DOUBLE:
130 *pStack++ = *(sal_uInt64*)&pCppArgs[nPos]; // verbatim!
131 break;
132 default:
133 break;
134 }
135 // no longer needed
136 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
137 }
138 else // ptr to complex value | ref
139 {
140 if (! rParam.bIn) // is pure out
141 {
142 // cpp out is constructed mem, uno out is not!
143 uno_constructData(
144 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
145 pParamTypeDescr );
146 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
147 // will be released at reconversion
148 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
149 }
150 // is in/inout
151 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
152 {
153 uno_copyAndConvertData(
154 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
155 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
156
157 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
158 // will be released at reconversion
159 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
160 }
161 else // direct way
162 {
163 pCppArgs[nPos] = pUnoArgs[nPos];
164 // no longer needed
165 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
166 }
167 *pStack++ = *(sal_uInt64*)&pCppArgs[nPos];
168 }
169 }
170
171 __try
172 {
173 // pCppI is mscx this pointer
174 callVirtualMethod(
175 pAdjustedThisPtr,
176 aVtableSlot.index,
177 pCppReturn, pReturnTypeDescr->eTypeClass,
178 pStackStart, (pStack - pStackStart) );
179 }
180 __except (CPPU_CURRENT_NAMESPACE::mscx_filterCppException(
181 GetExceptionInformation(),
182 *ppUnoExc, pThis->getBridge()->getCpp2Uno() ))
183 {
184 // *ppUnoExc was constructed by filter function
185 // temporary params
186 for ( ; nTempIndizes--; )
187 {
188 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
189 // destroy temp cpp param => cpp: every param was constructed
190 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
191 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
192 }
193 // return type
194 if (pReturnTypeDescr)
195 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
196 // end here
197 return;
198 }
199
200 // NO exception occurred
201 *ppUnoExc = 0;
202
203 // reconvert temporary params
204 for ( ; nTempIndizes--; )
205 {
206 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
207 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
208
209 if (pParams[nIndex].bIn)
210 {
211 if (pParams[nIndex].bOut) // inout
212 {
213 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
214 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
215 pThis->getBridge()->getCpp2Uno() );
216 }
217 }
218 else // pure out
219 {
220 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
221 pThis->getBridge()->getCpp2Uno() );
222 }
223 // destroy temp cpp param => cpp: every param was constructed
224 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
225
226 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
227 }
228 // return value
229 if (pCppReturn && pUnoReturn != pCppReturn)
230 {
231 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
232 pThis->getBridge()->getCpp2Uno() );
233 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
234 }
235 // return type
236 if (pReturnTypeDescr)
237 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
238 }
239
240 }
241
242 namespace bridges { namespace cpp_uno { namespace shared {
243
unoInterfaceProxyDispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberDescr,void * pReturn,void * pArgs[],uno_Any ** ppException)244 void unoInterfaceProxyDispatch(
245 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
246 void * pReturn, void * pArgs[], uno_Any ** ppException )
247 {
248 // is my surrogate
249 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
250 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
251
252 switch (pMemberDescr->eTypeClass)
253 {
254 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
255 {
256 VtableSlot aVtableSlot(
257 getVtableSlot(
258 reinterpret_cast<
259 typelib_InterfaceAttributeTypeDescription const * >(
260 pMemberDescr)));
261
262 if (pReturn)
263 {
264 // dependent dispatch
265 cpp_call(
266 pThis, aVtableSlot,
267 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
268 0, 0, // no params
269 pReturn, pArgs, ppException );
270 }
271 else
272 {
273 // is SET
274 typelib_MethodParameter aParam;
275 aParam.pTypeRef =
276 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
277 aParam.bIn = sal_True;
278 aParam.bOut = sal_False;
279
280 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
281 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
282 typelib_typedescriptionreference_new(
283 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
284
285 // dependent dispatch
286 aVtableSlot.index += 1; // get, then set method
287 cpp_call(
288 pThis, aVtableSlot, // get, then set method
289 pReturnTypeRef,
290 1, &aParam,
291 pReturn, pArgs, ppException );
292
293 typelib_typedescriptionreference_release( pReturnTypeRef );
294 }
295
296 break;
297 }
298 case typelib_TypeClass_INTERFACE_METHOD:
299 {
300 VtableSlot aVtableSlot(
301 getVtableSlot(
302 reinterpret_cast<
303 typelib_InterfaceMethodTypeDescription const * >(
304 pMemberDescr)));
305
306 switch (aVtableSlot.index)
307 {
308 // standard calls
309 case 1: // acquire uno interface
310 (*pUnoI->acquire)( pUnoI );
311 *ppException = 0;
312 break;
313 case 2: // release uno interface
314 (*pUnoI->release)( pUnoI );
315 *ppException = 0;
316 break;
317 case 0: // queryInterface() opt
318 {
319 typelib_TypeDescription * pTD = 0;
320 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
321 if (pTD)
322 {
323 uno_Interface * pInterface = 0;
324 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
325 pThis->getBridge()->getUnoEnv(),
326 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
327
328 if (pInterface)
329 {
330 ::uno_any_construct(
331 reinterpret_cast< uno_Any * >( pReturn ),
332 &pInterface, pTD, 0 );
333 (*pInterface->release)( pInterface );
334 TYPELIB_DANGER_RELEASE( pTD );
335 *ppException = 0;
336 break;
337 }
338 TYPELIB_DANGER_RELEASE( pTD );
339 }
340 } // else perform queryInterface()
341 default:
342 // dependent dispatch
343 cpp_call(
344 pThis, aVtableSlot,
345 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
346 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
347 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
348 pReturn, pArgs, ppException );
349 }
350 break;
351 }
352 default:
353 {
354 ::com::sun::star::uno::RuntimeException aExc(
355 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
356 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
357
358 Type const & rExcType = ::getCppuType( &aExc );
359 // binary identical null reference
360 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
361 }
362 }
363 }
364
365 } } }
366