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 #include "precompiled_bridges.hxx"
29 #include "sal/config.h"
30 
31 #include <algorithm>
32 #include <cstddef>
33 #include <cstring>
34 
35 #include "bridges/cpp_uno/shared/bridge.hxx"
36 #include "bridges/cpp_uno/shared/types.hxx"
37 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
38 #include "bridges/cpp_uno/shared/vtables.hxx"
39 #include "com/sun/star/uno/Exception.hpp"
40 #include "com/sun/star/uno/genfunc.hxx"
41 #include "osl/diagnose.h"
42 #include "rtl/ustring.h"
43 #include "rtl/ustring.hxx"
44 #include "sal/alloca.h"
45 #include "sal/types.h"
46 #include "typelib/typeclass.h"
47 #include "typelib/typedescription.h"
48 #include "uno/any2.h"
49 #include "uno/data.h"
50 
51 #include "callvirtualmethod.hxx"
52 #include "exceptions.hxx"
53 #include "fp.hxx"
54 #include "isdirectreturntype.hxx"
55 
56 namespace {
57 
58 namespace css = com::sun::star;
59 
60 void storeFpRegsToStruct(typelib_TypeDescription * type, void * data) {
61     for (typelib_CompoundTypeDescription * t =
62              reinterpret_cast< typelib_CompoundTypeDescription * >(type);
63          t != NULL; t = t->pBaseTypeDescription)
64     {
65         for (sal_Int32 i = 0; i < t->nMembers; ++i) {
66             switch (t->ppTypeRefs[i]->eTypeClass) {
67             case typelib_TypeClass_FLOAT:
68                 switch (t->pMemberOffsets[i]) {
69                 case 0:
70                     fp_storef0(reinterpret_cast< float * >(data));
71                     break;
72                 case 4:
73                     fp_storef1(reinterpret_cast< float * >(data) + 1);
74                     break;
75                 case 8:
76                     fp_storef2(reinterpret_cast< float * >(data) + 2);
77                     break;
78                 case 12:
79                     fp_storef3(reinterpret_cast< float * >(data) + 3);
80                     break;
81                 case 16:
82                     fp_storef4(reinterpret_cast< float * >(data) + 4);
83                     break;
84                 case 20:
85                     fp_storef5(reinterpret_cast< float * >(data) + 5);
86                     break;
87                 case 24:
88                     fp_storef6(reinterpret_cast< float * >(data) + 6);
89                     break;
90                 case 28:
91                     fp_storef7(reinterpret_cast< float * >(data) + 7);
92                     break;
93                 default:
94                     OSL_ASSERT(false);
95                     break;
96                 }
97                 break;
98             case typelib_TypeClass_DOUBLE:
99                 switch (t->pMemberOffsets[i]) {
100                 case 0:
101                     fp_stored0(reinterpret_cast< double * >(data));
102                     break;
103                 case 8:
104                     fp_stored2(reinterpret_cast< double * >(data) + 1);
105                     break;
106                 case 16:
107                     fp_stored4(reinterpret_cast< double * >(data) + 2);
108                     break;
109                 case 24:
110                     fp_stored6(reinterpret_cast< double * >(data) + 3);
111                     break;
112                 default:
113                     OSL_ASSERT(false);
114                     break;
115                 }
116                 break;
117             case typelib_TypeClass_STRUCT:
118                 {
119                     typelib_TypeDescription * td = NULL;
120                     TYPELIB_DANGER_GET(&td, t->ppTypeRefs[i]);
121                     storeFpRegsToStruct(td, data);
122                     TYPELIB_DANGER_RELEASE(td);
123                     break;
124                 }
125             }
126         }
127     }
128 }
129 
130 void call(
131     bridges::cpp_uno::shared::UnoInterfaceProxy * proxy,
132     bridges::cpp_uno::shared::VtableSlot slot,
133     typelib_TypeDescriptionReference * returnType, sal_Int32 count,
134     typelib_MethodParameter * parameters, void * returnValue, void ** arguments,
135     uno_Any ** exception)
136 {
137     bool directRet = bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType(
138         returnType);
139     long * stack = static_cast< long * >(
140         alloca(
141             std::max< sal_Int32 >(count + (directRet ? 1 : 2), 4) *
142             sizeof (long)));
143     sal_Int32 sp = 0;
144     typelib_TypeDescription * rtd = NULL;
145     TYPELIB_DANGER_GET(&rtd, returnType);
146     bool retconv = bridges::cpp_uno::shared::relatesToInterfaceType(rtd);
147     OSL_ASSERT(!(directRet && retconv));
148     void * ret;
149     if (!directRet) {
150         ret = retconv ? alloca(rtd->nSize) : returnValue;
151         stack[sp++] = reinterpret_cast< long >(ret);
152     }
153     unsigned long ** thisPtr = reinterpret_cast< unsigned long ** >(
154         proxy->getCppI()) + slot.offset;
155     stack[sp++] = reinterpret_cast< long >(thisPtr);
156     void ** cppArgs = static_cast< void ** >(alloca(count * sizeof (void *)));
157     typelib_TypeDescription ** ptds =
158         static_cast< typelib_TypeDescription ** >(
159             alloca(count * sizeof (typelib_TypeDescription *)));
160     for (sal_Int32 i = 0; i < count; ++i) {
161         if (!parameters[i].bOut &&
162             bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef))
163         {
164             cppArgs[i] = NULL;
165             switch (parameters[i].pTypeRef->eTypeClass) {
166             case typelib_TypeClass_BOOLEAN:
167                 stack[sp] = *static_cast< sal_Bool * >(arguments[i]);
168                 break;
169             case typelib_TypeClass_BYTE:
170                 stack[sp] = *static_cast< sal_Int8 * >(arguments[i]);
171                 break;
172             case typelib_TypeClass_SHORT:
173                 stack[sp] = *static_cast< sal_Int16 * >(arguments[i]);
174                 break;
175             case typelib_TypeClass_UNSIGNED_SHORT:
176                 stack[sp] = *static_cast< sal_uInt16 * >(arguments[i]);
177                 break;
178             case typelib_TypeClass_LONG:
179             case typelib_TypeClass_ENUM:
180                 stack[sp] = *static_cast< sal_Int32 * >(arguments[i]);
181                 break;
182             case typelib_TypeClass_UNSIGNED_LONG:
183                 stack[sp] = *static_cast< sal_uInt32 * >(arguments[i]);
184                 break;
185             case typelib_TypeClass_HYPER:
186                 stack[sp] = *static_cast< sal_Int64 * >(arguments[i]);
187                 break;
188             case typelib_TypeClass_UNSIGNED_HYPER:
189                 stack[sp] = *static_cast< sal_uInt64 * >(arguments[i]);
190                 break;
191             case typelib_TypeClass_FLOAT:
192                 {
193                     float * f = static_cast< float * >(arguments[i]);
194                     switch (sp) {
195                     case 1:
196                         fp_loadf3(f);
197                         break;
198                     case 2:
199                         fp_loadf5(f);
200                         break;
201                     case 3:
202                         fp_loadf7(f);
203                         break;
204                     case 4:
205                         fp_loadf9(f);
206                         break;
207                     case 5:
208                         fp_loadf11(f);
209                         break;
210                     case 6:
211                         fp_loadf13(f);
212                         break;
213                     case 7:
214                         fp_loadf15(f);
215                         break;
216                     case 8:
217                         fp_loadf17(f);
218                         break;
219                     case 9:
220                         fp_loadf19(f);
221                         break;
222                     case 10:
223                         fp_loadf21(f);
224                         break;
225                     case 11:
226                         fp_loadf23(f);
227                         break;
228                     case 12:
229                         fp_loadf25(f);
230                         break;
231                     case 13:
232                         fp_loadf27(f);
233                         break;
234                     case 14:
235                         fp_loadf29(f);
236                         break;
237                     case 15:
238                         fp_loadf31(f);
239                         break;
240                     default:
241                         reinterpret_cast< float * >(stack + sp)[1] = *f;
242                         break;
243                     }
244                     break;
245                 }
246             case typelib_TypeClass_DOUBLE:
247                 {
248                     double * d = static_cast< double * >(arguments[i]);
249                     switch (sp) {
250                     case 1:
251                         fp_loadd2(d);
252                         break;
253                     case 2:
254                         fp_loadd4(d);
255                         break;
256                     case 3:
257                         fp_loadd6(d);
258                         break;
259                     case 4:
260                         fp_loadd8(d);
261                         break;
262                     case 5:
263                         fp_loadd10(d);
264                         break;
265                     case 6:
266                         fp_loadd12(d);
267                         break;
268                     case 7:
269                         fp_loadd14(d);
270                         break;
271                     case 8:
272                         fp_loadd16(d);
273                         break;
274                     case 9:
275                         fp_loadd18(d);
276                         break;
277                     case 10:
278                         fp_loadd20(d);
279                         break;
280                     case 11:
281                         fp_loadd22(d);
282                         break;
283                     case 12:
284                         fp_loadd24(d);
285                         break;
286                     case 13:
287                         fp_loadd26(d);
288                         break;
289                     case 14:
290                         fp_loadd28(d);
291                         break;
292                     case 15:
293                         fp_loadd30(d);
294                         break;
295                     default:
296                         *reinterpret_cast< double * >(stack + sp) = *d;
297                         break;
298                     }
299                     break;
300                 }
301             case typelib_TypeClass_CHAR:
302                 stack[sp] = *static_cast< sal_Unicode * >(arguments[i]);
303                 break;
304             default:
305                 OSL_ASSERT(false);
306                 break;
307             }
308         } else {
309             typelib_TypeDescription * ptd = NULL;
310             TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef);
311             if (!parameters[i].bIn) {
312                 cppArgs[i] = alloca(ptd->nSize);
313                 uno_constructData(cppArgs[i], ptd);
314                 ptds[i] = ptd;
315                 *reinterpret_cast< void ** >(stack + sp) = cppArgs[i];
316             } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) {
317                 cppArgs[i] = alloca(ptd->nSize);
318                 uno_copyAndConvertData(
319                     cppArgs[i], arguments[i], ptd,
320                     proxy->getBridge()->getUno2Cpp());
321                 ptds[i] = ptd;
322                 *reinterpret_cast< void ** >(stack + sp) = cppArgs[i];
323             } else {
324                 cppArgs[i] = NULL;
325                 *reinterpret_cast< void ** >(stack + sp) = arguments[i];
326                 TYPELIB_DANGER_RELEASE(ptd);
327             }
328         }
329         ++sp;
330     }
331     try {
332         callVirtualMethod(
333             (*thisPtr)[slot.index + 2], stack,
334             std::max< sal_Int32 >(sp - 6, 0) * sizeof (long));
335     } catch (css::uno::Exception &) {
336         void * exc = __Crun::ex_get();
337         char const * name = __Cimpl::ex_name();
338         bridges::cpp_uno::cc5_solaris_sparc64::fillUnoException(
339             exc, name, *exception, proxy->getBridge()->getCpp2Uno());
340         for (sal_Int32 i = 0; i < count; ++i) {
341             if (cppArgs[i] != NULL) {
342                 uno_destructData(
343                     cppArgs[i], ptds[i],
344                     reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release));
345                 TYPELIB_DANGER_RELEASE(ptds[i]);
346             }
347         }
348         TYPELIB_DANGER_RELEASE(rtd);
349         return;
350     }
351     *exception = NULL;
352     for (sal_Int32 i = 0; i < count; ++i) {
353         if (cppArgs[i] != NULL) {
354             if (parameters[i].bOut) {
355                 if (parameters[i].bIn) {
356                     uno_destructData(arguments[i], ptds[i], NULL);
357                 }
358                 uno_copyAndConvertData(
359                     arguments[i], cppArgs[i], ptds[i],
360                     proxy->getBridge()->getCpp2Uno());
361             }
362             uno_destructData(
363                 cppArgs[i], ptds[i],
364                 reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release));
365             TYPELIB_DANGER_RELEASE(ptds[i]);
366         }
367     }
368     if (directRet) {
369         switch (rtd->eTypeClass) {
370         case typelib_TypeClass_FLOAT:
371             fp_storef0(reinterpret_cast< float * >(returnValue));
372             break;
373         case typelib_TypeClass_DOUBLE:
374             fp_stored0(reinterpret_cast< double * >(returnValue));
375             break;
376         case typelib_TypeClass_STRUCT:
377             storeFpRegsToStruct(rtd, stack);
378             // fall through
379         case typelib_TypeClass_ANY:
380             std::memcpy(returnValue, stack, rtd->nSize);
381             break;
382         default:
383             OSL_ASSERT(rtd->nSize <= 8);
384             std::memcpy(
385                 returnValue,
386                 reinterpret_cast< char * >(stack) + (8 - rtd->nSize),
387                 rtd->nSize);
388             break;
389         }
390     } else if (retconv) {
391         uno_copyAndConvertData(
392             returnValue, ret, rtd, proxy->getBridge()->getCpp2Uno());
393         uno_destructData(
394             ret, rtd,
395             reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release));
396     }
397     TYPELIB_DANGER_RELEASE(rtd);
398 }
399 
400 }
401 
402 namespace bridges { namespace cpp_uno { namespace shared {
403 
404 void unoInterfaceProxyDispatch(
405     uno_Interface * pUnoI, typelib_TypeDescription const * pMemberDescr,
406     void * pReturn, void * pArgs[], uno_Any ** ppException)
407 {
408     bridges::cpp_uno::shared::UnoInterfaceProxy * proxy =
409         static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
410     switch (pMemberDescr->eTypeClass) {
411     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
412         {
413             VtableSlot slot(
414                 getVtableSlot(
415                     reinterpret_cast<
416                     typelib_InterfaceAttributeTypeDescription const * >(
417                         pMemberDescr)));
418             if (pReturn != NULL) {
419                 // Getter:
420                 call(
421                     proxy, slot,
422                     (reinterpret_cast<
423                      typelib_InterfaceAttributeTypeDescription const * >(
424                          pMemberDescr)->pAttributeTypeRef),
425                     0, NULL, pReturn, pArgs, ppException);
426             } else {
427                 // Setter:
428                 typelib_MethodParameter param = {
429                     NULL,
430                     (reinterpret_cast<
431                      typelib_InterfaceAttributeTypeDescription const * >(
432                          pMemberDescr)->pAttributeTypeRef),
433                     true, false };
434                 typelib_TypeDescriptionReference * rtd = NULL;
435                 typelib_typedescriptionreference_new(
436                     &rtd, typelib_TypeClass_VOID,
437                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("void")).pData);
438                 slot.index += 1;
439                 call(proxy, slot, rtd, 1, &param, pReturn, pArgs, ppException);
440                 typelib_typedescriptionreference_release(rtd);
441             }
442             break;
443         }
444     case typelib_TypeClass_INTERFACE_METHOD:
445         {
446             VtableSlot slot(
447                 getVtableSlot(
448                     reinterpret_cast<
449                     typelib_InterfaceMethodTypeDescription const * >(
450                         pMemberDescr)));
451             switch (slot.index) {
452             case 1:
453                 pUnoI->acquire(pUnoI);
454                 *ppException = NULL;
455                 break;
456             case 2:
457                 pUnoI->release(pUnoI);
458                 *ppException = NULL;
459                 break;
460             case 0:
461                 {
462                     typelib_TypeDescription * td = NULL;
463                     TYPELIB_DANGER_GET(
464                         &td,
465                         reinterpret_cast< css::uno::Type * >(
466                             pArgs[0])->getTypeLibType());
467                     if (td != NULL) {
468                         uno_Interface * ifc = NULL;
469                         proxy->pBridge->getUnoEnv()->getRegisteredInterface(
470                             proxy->pBridge->getUnoEnv(),
471                             reinterpret_cast< void ** >(&ifc),
472                             proxy->oid.pData,
473                             (reinterpret_cast<
474                              typelib_InterfaceTypeDescription * >(td)));
475                         if (ifc != NULL) {
476                             uno_any_construct(
477                                 reinterpret_cast< uno_Any * >(pReturn),
478                                 &ifc, td, NULL);
479                             ifc->release(ifc);
480                             TYPELIB_DANGER_RELEASE(td);
481                             *ppException = NULL;
482                             break;
483                         }
484                         TYPELIB_DANGER_RELEASE(td);
485                     }
486                 } // fall through
487             default:
488                 call(
489                     proxy, slot,
490                     (reinterpret_cast<
491                      typelib_InterfaceMethodTypeDescription const * >(
492                          pMemberDescr)->pReturnTypeRef),
493                     (reinterpret_cast<
494                      typelib_InterfaceMethodTypeDescription const * >(
495                          pMemberDescr)->nParams),
496                     (reinterpret_cast<
497                      typelib_InterfaceMethodTypeDescription const * >(
498                          pMemberDescr)->pParams),
499                     pReturn, pArgs, ppException);
500             }
501             break;
502         }
503     default:
504         OSL_ASSERT(false);
505         break;
506     }
507 }
508 
509 } } }
510