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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_bridges.hxx" 26 27 #include <exception> 28 #include <typeinfo> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 33 #include "rtl/alloc.h" 34 #include "rtl/ustrbuf.hxx" 35 36 #include <com/sun/star/uno/genfunc.hxx> 37 #include "com/sun/star/uno/RuntimeException.hpp" 38 #include <uno/data.h> 39 40 #include <bridges/cpp_uno/shared/bridge.hxx> 41 #include <bridges/cpp_uno/shared/types.hxx> 42 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" 43 #include "bridges/cpp_uno/shared/vtables.hxx" 44 45 #include "abi.hxx" 46 #include "share.hxx" 47 48 using namespace ::rtl; 49 using namespace ::com::sun::star::uno; 50 51 //================================================================================================== 52 53 // The AArch64 outgoing-call trampoline, implemented in call.s. It loads the 54 // argument registers from the caller-prepared arrays, copies overflow args to 55 // the outgoing stack, performs the indirect call, and returns x0/x1 and d0..d3. 56 extern "C" void callVirtualFunction( 57 sal_uInt64 pFunction, sal_uInt64 pIndirectRet, 58 sal_uInt64 *pGPR, double *pFPR, 59 unsigned char *pStack, sal_uInt32 nStackBytes, 60 sal_uInt64 *pGPRReturn, double *pFPRReturn ); 61 62 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex, 63 void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn, 64 void * pIndirectReturn, 65 unsigned char *pStack, sal_uInt32 nStack, 66 sal_uInt64 *pGPR, sal_uInt32 nGPR, 67 double *pFPR, sal_uInt32 nFPR) __attribute__((noinline)); 68 69 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex, 70 void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn, 71 void * pIndirectReturn, 72 unsigned char *pStack, sal_uInt32 nStack, 73 sal_uInt64 *pGPR, sal_uInt32 nGPR, 74 double *pFPR, sal_uInt32 nFPR) 75 { 76 #if OSL_DEBUG_LEVEL > 1 77 // Let's figure out what is really going on here 78 { 79 fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR ); 80 for ( unsigned int i = 0; i < nGPR; ++i ) 81 fprintf( stderr, "0x%lx, ", pGPR[i] ); 82 fprintf( stderr, "\nFPR's (%d): ", nFPR ); 83 for ( unsigned int i = 0; i < nFPR; ++i ) 84 fprintf( stderr, "%f, ", pFPR[i] ); 85 // The overflow area is a packed byte image, not an array of words. 86 fprintf( stderr, "\nStack (%d bytes): ", nStack ); 87 for ( unsigned int i = 0; i < nStack; ++i ) 88 fprintf( stderr, "%02x ", pStack[i] ); 89 fprintf( stderr, "\n" ); 90 } 91 #endif 92 93 // The call instruction within callVirtualFunction may throw exceptions. So 94 // that the compiler handles this correctly, it is important that (a) 95 // callVirtualMethod might call dummy_can_throw_anything (although this never 96 // happens at runtime), which in turn can throw exceptions, and (b) 97 // callVirtualMethod is not inlined at its call site (so that any exceptions 98 // thrown across the call are caught): 99 if ( !pThis ) 100 CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything( "xxx" ); // address something 101 102 // Should not happen, but... 103 if ( nFPR > aarch64::MAX_FPR_REGS ) 104 nFPR = aarch64::MAX_FPR_REGS; 105 if ( nGPR > aarch64::MAX_GPR_REGS ) 106 nGPR = aarch64::MAX_GPR_REGS; 107 108 // Get pointer to the C++ virtual method from the vtable. 109 sal_uInt64 pMethod = *((sal_uInt64 *)pThis); 110 pMethod += 8 * nVtableIndex; 111 pMethod = *((sal_uInt64 *)pMethod); 112 113 // Return register save areas: x0,x1 and d0..d3 (HFA up to 4 elements). 114 sal_uInt64 gpReturn[2] = { 0, 0 }; 115 double fpReturn[4] = { 0, 0, 0, 0 }; 116 117 // Ensure the GPR/FPR arrays are the full register width even if fewer were 118 // filled (the trampoline always loads all 8 of each). 119 sal_uInt64 gpr[aarch64::MAX_GPR_REGS]; 120 double fpr[aarch64::MAX_FPR_REGS]; 121 for ( sal_uInt32 i = 0; i < aarch64::MAX_GPR_REGS; ++i ) 122 gpr[i] = ( i < nGPR ) ? pGPR[i] : 0; 123 for ( sal_uInt32 i = 0; i < aarch64::MAX_FPR_REGS; ++i ) 124 fpr[i] = ( i < nFPR ) ? pFPR[i] : 0; 125 126 callVirtualFunction( 127 pMethod, 128 reinterpret_cast<sal_uInt64>( pIndirectReturn ), // x8, 0 if none 129 gpr, fpr, 130 pStack, nStack, 131 gpReturn, fpReturn ); 132 133 switch (pReturnTypeRef->eTypeClass) 134 { 135 case typelib_TypeClass_HYPER: 136 case typelib_TypeClass_UNSIGNED_HYPER: 137 *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = gpReturn[0]; 138 break; 139 case typelib_TypeClass_LONG: 140 *reinterpret_cast<sal_Int32 *>( pRegisterReturn ) = 141 *reinterpret_cast<sal_Int32 *>( &gpReturn[0] ); 142 break; 143 case typelib_TypeClass_UNSIGNED_LONG: 144 case typelib_TypeClass_ENUM: 145 *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = 146 *reinterpret_cast<sal_uInt32 *>( &gpReturn[0] ); 147 break; 148 case typelib_TypeClass_CHAR: 149 case typelib_TypeClass_UNSIGNED_SHORT: 150 *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &gpReturn[0] ); 151 break; 152 case typelib_TypeClass_SHORT: 153 *reinterpret_cast<sal_Int16 *>( pRegisterReturn ) = 154 *reinterpret_cast<sal_Int16 *>( &gpReturn[0] ); 155 break; 156 case typelib_TypeClass_BOOLEAN: 157 *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &gpReturn[0] ); 158 break; 159 case typelib_TypeClass_BYTE: 160 *reinterpret_cast<sal_Int8 *>( pRegisterReturn ) = 161 *reinterpret_cast<sal_Int8 *>( &gpReturn[0] ); 162 break; 163 case typelib_TypeClass_FLOAT: 164 *reinterpret_cast<float *>( pRegisterReturn ) = 165 *reinterpret_cast<float *>( &fpReturn[0] ); 166 break; 167 case typelib_TypeClass_DOUBLE: 168 *reinterpret_cast<double *>( pRegisterReturn ) = fpReturn[0]; 169 break; 170 default: 171 { 172 sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize; 173 if (bSimpleReturn && nRetSize > 0) 174 { 175 // Register-returned aggregate: an HFA arrives in d0..d3, a 176 // non-HFA <= 16 bytes in x0,x1. fill_struct picks the right one. 177 aarch64::fill_struct( pReturnTypeRef, &gpReturn[0], &fpReturn[0], pRegisterReturn); 178 } 179 break; 180 } 181 } 182 } 183 184 //================================================================================================== 185 186 // Macros for inserting values into registers. Stack arguments are handled 187 // separately with a byte cursor because Apple packs them by size/alignment. 188 // pSV - pointer to the source 189 // nr - order of the value [will be increased if stored to register] 190 // pFPR, pGPR - pointer to the registers 191 192 // Each pFPR slot is the low 64 bits of a v register. A float occupies only 193 // the low 32 bits, while a double occupies all 64 bits. 194 #define INSERT_FLOAT( pSV, nr, pFPR ) \ 195 if ( nr < aarch64::MAX_FPR_REGS ) \ 196 { \ 197 pFPR[nr] = 0; \ 198 *reinterpret_cast<float *>( pFPR + nr++ ) = *reinterpret_cast<const float *>( pSV ); \ 199 } 200 201 #define INSERT_DOUBLE( pSV, nr, pFPR ) \ 202 if ( nr < aarch64::MAX_FPR_REGS ) \ 203 pFPR[nr++] = *reinterpret_cast<const double *>( pSV ); 204 205 #define INSERT_INT64( pSV, nr, pGPR ) \ 206 if ( nr < aarch64::MAX_GPR_REGS ) \ 207 pGPR[nr++] = *reinterpret_cast<const sal_uInt64 *>( pSV ); 208 209 #define INSERT_INT32( pSV, nr, pGPR ) \ 210 if ( nr < aarch64::MAX_GPR_REGS ) \ 211 pGPR[nr++] = *reinterpret_cast<const sal_uInt32 *>( pSV ); 212 213 #define INSERT_SIGNED_INT32( pSV, nr, pGPR ) \ 214 if ( nr < aarch64::MAX_GPR_REGS ) \ 215 pGPR[nr++] = static_cast<sal_Int64>( *reinterpret_cast<const sal_Int32 *>( pSV ) ); 216 217 #define INSERT_INT16( pSV, nr, pGPR ) \ 218 if ( nr < aarch64::MAX_GPR_REGS ) \ 219 pGPR[nr++] = *reinterpret_cast<const sal_uInt16 *>( pSV ); 220 221 #define INSERT_SIGNED_INT16( pSV, nr, pGPR ) \ 222 if ( nr < aarch64::MAX_GPR_REGS ) \ 223 pGPR[nr++] = static_cast<sal_Int64>( *reinterpret_cast<const sal_Int16 *>( pSV ) ); 224 225 #define INSERT_INT8( pSV, nr, pGPR ) \ 226 if ( nr < aarch64::MAX_GPR_REGS ) \ 227 pGPR[nr++] = *reinterpret_cast<const sal_uInt8 *>( pSV ); 228 229 #define INSERT_SIGNED_INT8( pSV, nr, pGPR ) \ 230 if ( nr < aarch64::MAX_GPR_REGS ) \ 231 pGPR[nr++] = static_cast<sal_Int64>( *reinterpret_cast<const sal_Int8 *>( pSV ) ); 232 233 //================================================================================================== 234 235 namespace { 236 237 void appendCString(OUStringBuffer & buffer, char const * text) { 238 if (text != 0) { 239 buffer.append( 240 OStringToOUString(OString(text), RTL_TEXTENCODING_ISO_8859_1)); 241 // use 8859-1 to avoid conversion failure 242 } 243 } 244 245 } 246 247 static void cpp_call( 248 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, 249 bridges::cpp_uno::shared::VtableSlot aVtableSlot, 250 typelib_TypeDescriptionReference * pReturnTypeRef, 251 sal_Int32 nParams, typelib_MethodParameter * pParams, 252 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) 253 { 254 unsigned char *pStackStart = static_cast<unsigned char *>( 255 __builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) ) ); 256 sal_uInt32 nStack = 0; 257 258 sal_uInt64 pGPR[aarch64::MAX_GPR_REGS]; 259 sal_uInt32 nGPR = 0; 260 261 double pFPR[aarch64::MAX_FPR_REGS]; 262 sal_uInt32 nFPR = 0; 263 264 // Return 265 typelib_TypeDescription * pReturnTypeDescr = 0; 266 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 267 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); 268 269 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion (see below) 270 271 // Indirect-result pointer. On AArch64 this is passed in the dedicated x8 272 // register, NOT as the first general-purpose argument (unlike x86-64 SysV). 273 // So we do NOT insert it into pGPR here; it is threaded to the trampoline 274 // separately as pIndirectReturn. 275 void * pIndirectReturn = 0; 276 277 bool bSimpleReturn = true; 278 if ( pReturnTypeDescr ) 279 { 280 if ( aarch64::return_in_hidden_param( pReturnTypeRef ) ) 281 bSimpleReturn = false; 282 283 if ( bSimpleReturn ) 284 pCppReturn = pUnoReturn; // direct way for simple types 285 else 286 { 287 // complex return via the x8 indirect-result buffer 288 pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )? 289 __builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn; 290 pIndirectReturn = pCppReturn; 291 } 292 } 293 294 // Push "this" pointer 295 void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset; 296 INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR ); 297 298 // Args 299 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); 300 // Indizes of values this have to be converted (interface conversion cpp<=>uno) 301 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); 302 // Type descriptions for reconversions 303 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); 304 305 sal_Int32 nTempIndizes = 0; 306 307 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 308 { 309 const typelib_MethodParameter & rParam = pParams[nPos]; 310 typelib_TypeDescription * pParamTypeDescr = 0; 311 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 312 313 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 314 { 315 uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr, 316 pThis->getBridge()->getUno2Cpp() ); 317 bool onStack = false; 318 319 switch (pParamTypeDescr->eTypeClass) 320 { 321 case typelib_TypeClass_HYPER: 322 case typelib_TypeClass_UNSIGNED_HYPER: 323 onStack = nGPR >= aarch64::MAX_GPR_REGS; 324 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR ); 325 break; 326 case typelib_TypeClass_LONG: 327 onStack = nGPR >= aarch64::MAX_GPR_REGS; 328 INSERT_SIGNED_INT32( pCppArgs[nPos], nGPR, pGPR ); 329 break; 330 case typelib_TypeClass_UNSIGNED_LONG: 331 case typelib_TypeClass_ENUM: 332 onStack = nGPR >= aarch64::MAX_GPR_REGS; 333 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR ); 334 break; 335 case typelib_TypeClass_SHORT: 336 onStack = nGPR >= aarch64::MAX_GPR_REGS; 337 INSERT_SIGNED_INT16( pCppArgs[nPos], nGPR, pGPR ); 338 break; 339 case typelib_TypeClass_CHAR: 340 case typelib_TypeClass_UNSIGNED_SHORT: 341 onStack = nGPR >= aarch64::MAX_GPR_REGS; 342 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR ); 343 break; 344 case typelib_TypeClass_BYTE: 345 onStack = nGPR >= aarch64::MAX_GPR_REGS; 346 INSERT_SIGNED_INT8( pCppArgs[nPos], nGPR, pGPR ); 347 break; 348 case typelib_TypeClass_BOOLEAN: 349 onStack = nGPR >= aarch64::MAX_GPR_REGS; 350 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR ); 351 break; 352 case typelib_TypeClass_FLOAT: 353 onStack = nFPR >= aarch64::MAX_FPR_REGS; 354 INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR ); 355 break; 356 case typelib_TypeClass_DOUBLE: 357 onStack = nFPR >= aarch64::MAX_FPR_REGS; 358 INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR ); 359 break; 360 default: 361 break; 362 } 363 if ( onStack ) 364 { 365 nStack = aarch64::align_stack_offset( nStack, rParam.pTypeRef ); 366 sal_uInt32 size = aarch64::stack_size( rParam.pTypeRef ); 367 memcpy( pStackStart + nStack, pCppArgs[nPos], size ); 368 nStack += size; 369 } 370 371 // no longer needed 372 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 373 } 374 else // ptr to complex value | ref 375 { 376 if (! rParam.bIn) // is pure out 377 { 378 // cpp out is constructed mem, uno out is not! 379 uno_constructData( 380 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 381 pParamTypeDescr ); 382 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call 383 // will be released at reconversion 384 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 385 } 386 // is in/inout 387 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) 388 { 389 uno_copyAndConvertData( 390 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 391 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); 392 393 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 394 // will be released at reconversion 395 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 396 } 397 else // direct way 398 { 399 pCppArgs[nPos] = pUnoArgs[nPos]; 400 // no longer needed 401 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 402 } 403 if ( nGPR < aarch64::MAX_GPR_REGS ) 404 { 405 INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR ); 406 } 407 else 408 { 409 nStack = (nStack + sizeof(void *) - 1) & ~(sizeof(void *) - 1); 410 memcpy( pStackStart + nStack, &pCppArgs[nPos], sizeof(void *) ); 411 nStack += sizeof(void *); 412 } 413 } 414 } 415 416 try 417 { 418 try { 419 callVirtualMethod( 420 pAdjustedThisPtr, aVtableSlot.index, 421 pCppReturn, pReturnTypeRef, bSimpleReturn, 422 pIndirectReturn, 423 pStackStart, nStack, 424 pGPR, nGPR, 425 pFPR, nFPR ); 426 } catch (Exception &) { 427 throw; 428 } catch (std::exception & e) { 429 OUStringBuffer buf; 430 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("C++ code threw ")); 431 appendCString(buf, typeid(e).name()); 432 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(": ")); 433 appendCString(buf, e.what()); 434 throw RuntimeException( 435 buf.makeStringAndClear(), Reference< XInterface >()); 436 } catch (...) { 437 throw RuntimeException( 438 OUString( 439 RTL_CONSTASCII_USTRINGPARAM( 440 "C++ code threw unknown exception")), 441 Reference< XInterface >()); 442 } 443 444 // NO exception occurred... 445 *ppUnoExc = 0; 446 447 // reconvert temporary params 448 for ( ; nTempIndizes--; ) 449 { 450 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 451 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; 452 453 if (pParams[nIndex].bIn) 454 { 455 if (pParams[nIndex].bOut) // inout 456 { 457 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value 458 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 459 pThis->getBridge()->getCpp2Uno() ); 460 } 461 } 462 else // pure out 463 { 464 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 465 pThis->getBridge()->getCpp2Uno() ); 466 } 467 // destroy temp cpp param => cpp: every param was constructed 468 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); 469 470 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 471 } 472 // return value 473 if (pCppReturn && pUnoReturn != pCppReturn) 474 { 475 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, 476 pThis->getBridge()->getCpp2Uno() ); 477 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); 478 } 479 } 480 catch (Exception & e) 481 { 482 // fill uno exception 483 std::type_info * type = CPPU_CURRENT_NAMESPACE::__cxa_current_exception_type(); 484 CPPU_CURRENT_NAMESPACE::fillUnoException( 485 type ? *type : typeid(e), &e, *ppUnoExc, 486 pThis->getBridge()->getCpp2Uno() ); 487 488 // temporary params 489 for ( ; nTempIndizes--; ) 490 { 491 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 492 // destroy temp cpp param => cpp: every param was constructed 493 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); 494 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 495 } 496 // return type 497 if (pReturnTypeDescr) 498 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 499 } 500 catch (...) 501 { 502 RuntimeException e( 503 OUString( RTL_CONSTASCII_USTRINGPARAM("C++ code threw unknown exception") ), 504 Reference< XInterface >() ); 505 uno_type_any_constructAndConvert( 506 *ppUnoExc, &e, ::getCppuType( &e ).getTypeLibType(), 507 pThis->getBridge()->getCpp2Uno() ); 508 for ( ; nTempIndizes--; ) 509 { 510 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 511 uno_destructData( 512 pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); 513 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 514 } 515 if (pReturnTypeDescr) 516 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 517 } 518 } 519 520 //================================================================================================== 521 522 namespace bridges { namespace cpp_uno { namespace shared { 523 524 void unoInterfaceProxyDispatch( 525 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, 526 void * pReturn, void * pArgs[], uno_Any ** ppException ) 527 { 528 // is my surrogate 529 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis 530 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); 531 #if OSL_DEBUG_LEVEL > 0 532 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; 533 #endif 534 535 switch (pMemberDescr->eTypeClass) 536 { 537 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 538 { 539 #if OSL_DEBUG_LEVEL > 0 540 // determine vtable call index 541 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; 542 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); 543 #endif 544 VtableSlot aVtableSlot( 545 getVtableSlot( 546 reinterpret_cast< 547 typelib_InterfaceAttributeTypeDescription const * >( 548 pMemberDescr))); 549 550 if (pReturn) 551 { 552 // dependent dispatch 553 cpp_call( 554 pThis, aVtableSlot, 555 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, 556 0, 0, // no params 557 pReturn, pArgs, ppException ); 558 } 559 else 560 { 561 // is SET 562 typelib_MethodParameter aParam; 563 aParam.pTypeRef = 564 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; 565 aParam.bIn = sal_True; 566 aParam.bOut = sal_False; 567 568 typelib_TypeDescriptionReference * pReturnTypeRef = 0; 569 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); 570 typelib_typedescriptionreference_new( 571 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); 572 573 // dependent dispatch 574 aVtableSlot.index += 1; // get, then set method 575 cpp_call( 576 pThis, aVtableSlot, // get, then set method 577 pReturnTypeRef, 578 1, &aParam, 579 pReturn, pArgs, ppException ); 580 581 typelib_typedescriptionreference_release( pReturnTypeRef ); 582 } 583 584 break; 585 } 586 case typelib_TypeClass_INTERFACE_METHOD: 587 { 588 #if OSL_DEBUG_LEVEL > 0 589 // determine vtable call index 590 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; 591 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); 592 #endif 593 VtableSlot aVtableSlot( 594 getVtableSlot( 595 reinterpret_cast< 596 typelib_InterfaceMethodTypeDescription const * >( 597 pMemberDescr))); 598 599 switch (aVtableSlot.index) 600 { 601 // standard calls 602 case 1: // acquire uno interface 603 (*pUnoI->acquire)( pUnoI ); 604 *ppException = 0; 605 break; 606 case 2: // release uno interface 607 (*pUnoI->release)( pUnoI ); 608 *ppException = 0; 609 break; 610 case 0: // queryInterface() opt 611 { 612 typelib_TypeDescription * pTD = 0; 613 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); 614 if (pTD) 615 { 616 uno_Interface * pInterface = 0; 617 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)( 618 pThis->getBridge()->getUnoEnv(), 619 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); 620 621 if (pInterface) 622 { 623 ::uno_any_construct( 624 reinterpret_cast< uno_Any * >( pReturn ), 625 &pInterface, pTD, 0 ); 626 (*pInterface->release)( pInterface ); 627 TYPELIB_DANGER_RELEASE( pTD ); 628 *ppException = 0; 629 break; 630 } 631 TYPELIB_DANGER_RELEASE( pTD ); 632 } 633 } // else perform queryInterface() 634 default: 635 // dependent dispatch 636 cpp_call( 637 pThis, aVtableSlot, 638 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, 639 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, 640 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, 641 pReturn, pArgs, ppException ); 642 } 643 break; 644 } 645 default: 646 { 647 ::com::sun::star::uno::RuntimeException aExc( 648 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), 649 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); 650 651 Type const & rExcType = ::getCppuType( &aExc ); 652 // binary identical null reference 653 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); 654 } 655 } 656 } 657 658 } } } 659