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 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 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 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