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, ¶m, 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