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