xref: /AOO41X/main/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx (revision 61dff127b6698e0bae836c8aedd6ec62111483d1)
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 "msci.hxx"
38 
39 using namespace ::rtl;
40 using namespace ::com::sun::star::uno;
41 
42 namespace
43 {
44 
45 //==================================================================================================
callVirtualMethod(void * pAdjustedThisPtr,sal_Int32 nVtableIndex,void * pRegisterReturn,typelib_TypeClass eReturnTypeClass,sal_Int32 * pStackLongs,sal_Int32 nStackLongs)46 inline static void callVirtualMethod(
47     void * pAdjustedThisPtr, sal_Int32 nVtableIndex,
48     void * pRegisterReturn, typelib_TypeClass eReturnTypeClass,
49     sal_Int32 * pStackLongs, sal_Int32 nStackLongs )
50 {
51     // parameter list is mixed list of * and values
52     // reference parameters are pointers
53 
54     OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" );
55     OSL_ENSURE( (sizeof(void *) == 4) &&
56                  (sizeof(sal_Int32) == 4), "### unexpected size of int!" );
57 
58 __asm
59     {
60         mov     eax, nStackLongs
61         test    eax, eax
62         je      Lcall
63         // copy values
64         mov     ecx, eax
65         shl     eax, 2           // sizeof(sal_Int32) == 4
66         add     eax, pStackLongs // params stack space
67 Lcopy:  sub     eax, 4
68         push    dword ptr [eax]
69         dec     ecx
70         jne     Lcopy
71 Lcall:
72         // call
73         mov     ecx, pAdjustedThisPtr
74         push    ecx             // this ptr
75         mov     edx, [ecx]      // pvft
76         mov     eax, nVtableIndex
77         shl     eax, 2          // sizeof(void *) == 4
78         add     edx, eax
79         call    [edx]           // interface method call must be __cdecl!!!
80 
81         // register return
82         mov     ecx, eReturnTypeClass
83         cmp     ecx, typelib_TypeClass_VOID
84         je      Lcleanup
85         mov     ebx, pRegisterReturn
86 // int32
87         cmp     ecx, typelib_TypeClass_LONG
88         je      Lint32
89         cmp     ecx, typelib_TypeClass_UNSIGNED_LONG
90         je      Lint32
91         cmp     ecx, typelib_TypeClass_ENUM
92         je      Lint32
93 // int8
94         cmp     ecx, typelib_TypeClass_BOOLEAN
95         je      Lint8
96         cmp     ecx, typelib_TypeClass_BYTE
97         je      Lint8
98 // int16
99         cmp     ecx, typelib_TypeClass_CHAR
100         je      Lint16
101         cmp     ecx, typelib_TypeClass_SHORT
102         je      Lint16
103         cmp     ecx, typelib_TypeClass_UNSIGNED_SHORT
104         je      Lint16
105 // float
106         cmp     ecx, typelib_TypeClass_FLOAT
107         je      Lfloat
108 // double
109         cmp     ecx, typelib_TypeClass_DOUBLE
110         je      Ldouble
111 // int64
112         cmp     ecx, typelib_TypeClass_HYPER
113         je      Lint64
114         cmp     ecx, typelib_TypeClass_UNSIGNED_HYPER
115         je      Lint64
116         jmp     Lcleanup // no simple type
117 Lint8:
118         mov     byte ptr [ebx], al
119         jmp     Lcleanup
120 Lint16:
121         mov     word ptr [ebx], ax
122         jmp     Lcleanup
123 Lfloat:
124         fstp    dword ptr [ebx]
125         jmp     Lcleanup
126 Ldouble:
127         fstp    qword ptr [ebx]
128         jmp     Lcleanup
129 Lint64:
130         mov     dword ptr [ebx], eax
131         mov     dword ptr [ebx+4], edx
132         jmp     Lcleanup
133 Lint32:
134         mov     dword ptr [ebx], eax
135         jmp     Lcleanup
136 Lcleanup:
137         // cleanup stack (obsolete though because of function)
138         mov     eax, nStackLongs
139         shl     eax, 2          // sizeof(sal_Int32) == 4
140         add     eax, 4          // this ptr
141         add     esp, eax
142     }
143 }
144 
145 //==================================================================================================
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)146 static void cpp_call(
147     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
148     bridges::cpp_uno::shared::VtableSlot aVtableSlot,
149     typelib_TypeDescriptionReference * pReturnTypeRef,
150     sal_Int32 nParams, typelib_MethodParameter * pParams,
151     void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) throw ()
152 {
153     // max space for: [complex ret ptr], values|ptr ...
154     char * pCppStack        = (char *)alloca( sizeof(sal_Int32) + (nParams * sizeof(sal_Int64)) );
155     char * pCppStackStart   = pCppStack;
156 
157     // return
158     typelib_TypeDescription * pReturnTypeDescr = 0;
159     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
160     OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
161 
162     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
163 
164     if (pReturnTypeDescr)
165     {
166         if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
167         {
168             pCppReturn = pUnoReturn; // direct way for simple types
169         }
170         else
171         {
172             // complex return via ptr
173             pCppReturn = *(void **)pCppStack
174                 = (bridges::cpp_uno::shared::relatesToInterfaceType(
175                        pReturnTypeDescr )
176                    ? alloca( pReturnTypeDescr->nSize )
177                    : pUnoReturn); // direct way
178             pCppStack += sizeof(void *);
179         }
180     }
181 
182     // stack space
183 
184     OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
185     // args
186     void ** pCppArgs  = (void **)alloca( 3 * sizeof(void *) * nParams );
187     // indizes of values this have to be converted (interface conversion cpp<=>uno)
188     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
189     // type descriptions for reconversions
190     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
191 
192     sal_Int32 nTempIndizes   = 0;
193 
194     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
195     {
196         const typelib_MethodParameter & rParam = pParams[nPos];
197         typelib_TypeDescription * pParamTypeDescr = 0;
198         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
199 
200         if (!rParam.bOut
201             && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
202         {
203             ::uno_copyAndConvertData(
204                 pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr,
205                 pThis->getBridge()->getUno2Cpp() );
206 
207             switch (pParamTypeDescr->eTypeClass)
208             {
209             case typelib_TypeClass_HYPER:
210             case typelib_TypeClass_UNSIGNED_HYPER:
211             case typelib_TypeClass_DOUBLE:
212                 pCppStack += sizeof(sal_Int32); // extra long
213                 break;
214             default:
215                 break;
216             }
217             // no longer needed
218             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
219         }
220         else // ptr to complex value | ref
221         {
222             if (! rParam.bIn) // is pure out
223             {
224                 // cpp out is constructed mem, uno out is not!
225                 ::uno_constructData(
226                     *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
227                     pParamTypeDescr );
228                 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
229                 // will be released at reconversion
230                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
231             }
232             // is in/inout
233             else if (bridges::cpp_uno::shared::relatesToInterfaceType(
234                          pParamTypeDescr ))
235             {
236                 ::uno_copyAndConvertData(
237                     *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
238                     pUnoArgs[nPos], pParamTypeDescr,
239                     pThis->getBridge()->getUno2Cpp() );
240 
241                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
242                 // will be released at reconversion
243                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
244             }
245             else // direct way
246             {
247                 *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
248                 // no longer needed
249                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
250             }
251         }
252         pCppStack += sizeof(sal_Int32); // standard parameter length
253     }
254 
255     __try
256     {
257         // pCppI is msci this pointer
258         callVirtualMethod(
259             reinterpret_cast< void ** >(pThis->getCppI()) + aVtableSlot.offset,
260             aVtableSlot.index,
261             pCppReturn, pReturnTypeDescr->eTypeClass,
262             (sal_Int32 *)pCppStackStart,
263             (pCppStack - pCppStackStart) / sizeof(sal_Int32) );
264     }
265     __except (CPPU_CURRENT_NAMESPACE::msci_filterCppException(
266                   GetExceptionInformation(),
267                   *ppUnoExc, pThis->getBridge()->getCpp2Uno() ))
268    {
269         // *ppUnoExc was constructed by filter function
270         // temporary params
271         while (nTempIndizes--)
272         {
273             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
274             // destroy temp cpp param => cpp: every param was constructed
275             ::uno_destructData(
276                 pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes],
277                 cpp_release );
278             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
279         }
280         // return type
281         if (pReturnTypeDescr)
282         {
283             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
284         }
285         // end here
286         return;
287     }
288 
289     // NO exception occured
290     *ppUnoExc = 0;
291 
292     // reconvert temporary params
293     while (nTempIndizes--)
294     {
295         sal_Int32 nIndex = pTempIndizes[nTempIndizes];
296         typelib_TypeDescription * pParamTypeDescr =
297             ppTempParamTypeDescr[nTempIndizes];
298 
299         if (pParams[nIndex].bIn)
300         {
301             if (pParams[nIndex].bOut) // inout
302             {
303                 ::uno_destructData(
304                     pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
305                 ::uno_copyAndConvertData(
306                     pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
307                     pThis->getBridge()->getCpp2Uno() );
308             }
309         }
310         else // pure out
311         {
312             ::uno_copyAndConvertData(
313                 pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
314                 pThis->getBridge()->getCpp2Uno() );
315         }
316         // destroy temp cpp param => cpp: every param was constructed
317         ::uno_destructData(
318             pCppArgs[nIndex], pParamTypeDescr, cpp_release );
319 
320         TYPELIB_DANGER_RELEASE( pParamTypeDescr );
321     }
322     // return value
323     if (pCppReturn && pUnoReturn != pCppReturn)
324     {
325         ::uno_copyAndConvertData(
326             pUnoReturn, pCppReturn, pReturnTypeDescr,
327             pThis->getBridge()->getCpp2Uno() );
328         ::uno_destructData(
329             pCppReturn, pReturnTypeDescr, cpp_release );
330     }
331     // return type
332     if (pReturnTypeDescr)
333     {
334         TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
335     }
336 }
337 
338 }
339 
340 namespace bridges { namespace cpp_uno { namespace shared {
341 
unoInterfaceProxyDispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberDescr,void * pReturn,void * pArgs[],uno_Any ** ppException)342 void unoInterfaceProxyDispatch(
343     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
344     void * pReturn, void * pArgs[], uno_Any ** ppException )
345 {
346     // is my surrogate
347     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
348         = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
349 
350     switch (pMemberDescr->eTypeClass)
351     {
352     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
353     {
354         VtableSlot aVtableSlot(
355             getVtableSlot(
356                 reinterpret_cast<
357                     typelib_InterfaceAttributeTypeDescription const * >(
358                         pMemberDescr)));
359         if (pReturn)
360         {
361             // dependent dispatch
362             cpp_call(
363                 pThis, aVtableSlot,
364                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
365                 0, 0, // no params
366                 pReturn, pArgs, ppException );
367         }
368         else
369         {
370             // is SET
371             typelib_MethodParameter aParam;
372             aParam.pTypeRef =
373                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
374             aParam.bIn      = sal_True;
375             aParam.bOut     = sal_False;
376 
377             typelib_TypeDescriptionReference * pReturnTypeRef = 0;
378             OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
379             typelib_typedescriptionreference_new(
380                 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
381 
382             // dependent dispatch
383             aVtableSlot.index += 1; // get, then set method
384             cpp_call(
385                 pThis, aVtableSlot,
386                 pReturnTypeRef,
387                 1, &aParam,
388                 pReturn, pArgs, ppException );
389 
390             typelib_typedescriptionreference_release( pReturnTypeRef );
391         }
392 
393         break;
394     }
395     case typelib_TypeClass_INTERFACE_METHOD:
396     {
397         VtableSlot aVtableSlot(
398             getVtableSlot(
399                 reinterpret_cast<
400                     typelib_InterfaceMethodTypeDescription const * >(
401                         pMemberDescr)));
402         switch (aVtableSlot.index)
403         {
404             // standard calls
405         case 1: // acquire uno interface
406             (*pUnoI->acquire)( pUnoI );
407             *ppException = 0;
408             break;
409         case 2: // release uno interface
410             (*pUnoI->release)( pUnoI );
411             *ppException = 0;
412             break;
413         case 0: // queryInterface() opt
414         {
415             typelib_TypeDescription * pTD = 0;
416             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
417             if (pTD)
418             {
419                 uno_Interface * pInterface = 0;
420                 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
421                     pThis->pBridge->getUnoEnv(),
422                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
423 
424                 if (pInterface)
425                 {
426                     ::uno_any_construct(
427                         reinterpret_cast< uno_Any * >( pReturn ),
428                         &pInterface, pTD, 0 );
429                     (*pInterface->release)( pInterface );
430                     TYPELIB_DANGER_RELEASE( pTD );
431                     *ppException = 0;
432                     break;
433                 }
434                 TYPELIB_DANGER_RELEASE( pTD );
435             }
436         } // else perform queryInterface()
437         default:
438             // dependent dispatch
439             cpp_call(
440                 pThis, aVtableSlot,
441                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
442                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
443                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
444                 pReturn, pArgs, ppException );
445         }
446         break;
447     }
448     default:
449     {
450         ::com::sun::star::uno::RuntimeException aExc(
451             OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
452             ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
453 
454         Type const & rExcType = ::getCppuType( &aExc );
455         // binary identical null reference
456         ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
457     }
458     }
459 }
460 
461 } } }
462