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