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