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 <malloc.h> 28 29 #include <com/sun/star/uno/genfunc.hxx> 30 #include <uno/data.h> 31 32 #include "bridges/cpp_uno/shared/bridge.hxx" 33 #include "bridges/cpp_uno/shared/types.hxx" 34 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" 35 #include "bridges/cpp_uno/shared/vtables.hxx" 36 37 #include "share.hxx" 38 39 40 using namespace ::rtl; 41 using namespace ::com::sun::star::uno; 42 43 namespace 44 { 45 46 47 //================================================================================================== 48 static void callVirtualMethod( 49 void * pAdjustedThisPtr, 50 sal_Int32 nVtableIndex, 51 void * pRegisterReturn, 52 typelib_TypeClass eReturnType, 53 char * pPT, 54 sal_Int32 * pStackLongs, 55 sal_Int32 nStackLongs) 56 { 57 58 // parameter list is mixed list of * and values 59 // reference parameters are pointers 60 61 // the basic idea here is to use gpr[8] as a storage area for 62 // the future values of registers r3 to r10 needed for the call, 63 // and similarly fpr[8] as a storage area for the future values 64 // of floating point registers f1 to f8 65 66 unsigned long * mfunc; // actual function to be invoked 67 void (*ptr)(); 68 int gpr[8]; // storage for gpregisters, map to r3-r10 69 int off; // offset used to find function 70 #ifndef __NO_FPRS__ 71 double fpr[8]; // storage for fpregisters, map to f1-f8 72 int f; // number of fprs mapped so far 73 double dret; // temporary function return values 74 #endif 75 int n; // number of gprs mapped so far 76 long *p; // pointer to parameter overflow area 77 int c; // character of parameter type being decoded 78 int iret, iret2; 79 80 // Because of the Power PC calling conventions we could be passing 81 // parameters in both register types and on the stack. To create the 82 // stack parameter area we need we now simply allocate local 83 // variable storage param[] that is at least the size of the parameter stack 84 // (more than enough space) which we can overwrite the parameters into. 85 86 // Note: This keeps us from having to decode the signature twice and 87 // prevents problems with later local variables. 88 89 // Note: could require up to 2*nStackLongs words of parameter stack area 90 // if the call has many float parameters (i.e. floats take up only 1 91 // word on the stack but double takes 2 words in parameter area in the 92 // stack frame . 93 94 // Update! floats on the outgoing parameter stack only take up 1 word 95 // (stfs is used) which is not correct according to the ABI but we 96 // will match what the compiler does until this is figured out 97 98 // this grows the current stack to the appropriate size 99 // and sets the outgoing stack pointer p to the right place 100 __asm__ __volatile__ ( 101 "rlwinm %0,%0,3,3,28\n\t" 102 "addi %0,%0,22\n\t" 103 "rlwinm %0,%0,0,4,28\n\t" 104 "lwz 0,0(1)\n\t" 105 "subf 1,%0,1\n\t" 106 "stw 0,0(1)\n\t" 107 : : "r" (nStackLongs) : "0" ); 108 109 __asm__ __volatile__ ( "addi %0,1,8" : "=r" (p) : ); 110 111 // never called 112 // if (! pAdjustedThisPtr ) dummy_can_throw_anything("xxx"); // address something 113 114 115 // now begin to load the C++ function arguments into storage 116 n = 0; 117 #ifndef __NO_FPRS__ 118 f = 0; 119 #endif 120 121 // now we need to parse the entire signature string */ 122 // until we get the END indicator */ 123 124 // treat complex return pointer like any other parameter // 125 126 #if 0 127 /* Let's figure out what is really going on here*/ 128 fprintf(stderr,"callVirtualMethod paramters string is %s\n",pPT); 129 int k = nStackLongs; 130 long * q = (long *)pStackLongs; 131 while (k > 0) { 132 fprintf(stderr,"uno stack is: %x\n",*q); 133 k--; 134 q++; 135 } 136 #endif 137 138 /* parse the argument list up to the ending ) */ 139 while (*pPT != 'X') { 140 c = *pPT; 141 switch (c) { 142 case 'D': /* type is double */ 143 #ifndef __NO_FPRS__ 144 if (f < 8) { 145 fpr[f++] = *((double *)pStackLongs); /* store in register */ 146 #else 147 if (n & 1) 148 n++; 149 if (n < 8) { 150 gpr[n++] = *pStackLongs; 151 gpr[n++] = *(pStackLongs+1); 152 #endif 153 } else { 154 if (((long) p) & 4) 155 p++; 156 *p++ = *pStackLongs; /* or on the parameter stack */ 157 *p++ = *(pStackLongs + 1); 158 } 159 pStackLongs += 2; 160 break; 161 162 case 'F': /* type is float */ 163 /* this assumes that floats are stored as 1 32 bit word on param 164 stack and that if passed in parameter stack to C, should be 165 as double word. 166 167 Whoops: the abi is not actually followed by gcc, need to 168 store floats as a *single* word on outgoing parameter stack 169 to match what gcc actually does 170 */ 171 #ifndef __NO_FPRS__ 172 if (f < 8) { 173 fpr[f++] = *((float *)pStackLongs); 174 #else 175 if (n < 8) { 176 gpr[n++] = *pStackLongs; 177 #endif 178 } else { 179 #if 0 /* if abi were followed */ 180 if (((long) p) & 4) 181 p++; 182 *((double *)p) = *((float *)pStackLongs); 183 p += 2; 184 #else 185 *((float *)p) = *((float *)pStackLongs); 186 p += 1; 187 #endif 188 } 189 pStackLongs += 1; 190 break; 191 192 case 'H': /* type is long long */ 193 if (n & 1) n++; /* note even elements gpr[] will map to 194 odd registers*/ 195 if (n <= 6) { 196 gpr[n++] = *pStackLongs; 197 gpr[n++] = *(pStackLongs+1); 198 } else { 199 if (((long) p) & 4) 200 p++; 201 *p++ = *pStackLongs; 202 *p++ = *(pStackLongs+1); 203 } 204 pStackLongs += 2; 205 break; 206 207 case 'S': 208 if (n < 8) { 209 gpr[n++] = *((unsigned short*)pStackLongs); 210 } else { 211 *p++ = *((unsigned short *)pStackLongs); 212 } 213 pStackLongs += 1; 214 break; 215 216 case 'B': 217 if (n < 8) { 218 gpr[n++] = *((char *)pStackLongs); 219 } else { 220 *p++ = *((char *)pStackLongs); 221 } 222 pStackLongs += 1; 223 break; 224 225 default: 226 if (n < 8) { 227 gpr[n++] = *pStackLongs; 228 } else { 229 *p++ = *pStackLongs; 230 } 231 pStackLongs += 1; 232 break; 233 } 234 pPT++; 235 } 236 237 /* figure out the address of the function we need to invoke */ 238 off = nVtableIndex; 239 off = off * 4; // 4 bytes per slot 240 mfunc = *((unsigned long **)pAdjustedThisPtr); // get the address of the vtable 241 mfunc = (unsigned long *)((char *)mfunc + off); // get the address from the vtable entry at offset 242 mfunc = *((unsigned long **)mfunc); // the function is stored at the address 243 ptr = (void (*)())mfunc; 244 245 /* Set up the machine registers and invoke the function */ 246 247 __asm__ __volatile__ ( 248 "lwz 3, 0(%0)\n\t" 249 "lwz 4, 4(%0)\n\t" 250 "lwz 5, 8(%0)\n\t" 251 "lwz 6, 12(%0)\n\t" 252 "lwz 7, 16(%0)\n\t" 253 "lwz 8, 20(%0)\n\t" 254 "lwz 9, 24(%0)\n\t" 255 "lwz 10, 28(%0)\n\t" 256 #ifndef __NO_FPRS__ 257 "lfd 1, 0(%1)\n\t" 258 "lfd 2, 8(%1)\n\t" 259 "lfd 3, 16(%1)\n\t" 260 "lfd 4, 24(%1)\n\t" 261 "lfd 5, 32(%1)\n\t" 262 "lfd 6, 40(%1)\n\t" 263 "lfd 7, 48(%1)\n\t" 264 "lfd 8, 56(%1)\n\t" 265 : : "r" (gpr), "r" (fpr) 266 #else 267 : : "r" (gpr) 268 #endif 269 : "0", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12" 270 ); 271 272 (*ptr)(); 273 274 __asm__ __volatile__ ( 275 "mr %0, 3\n\t" 276 "mr %1, 4\n\t" 277 #ifndef __NO_FPRS__ 278 "fmr %2, 1\n\t" 279 : "=r" (iret), "=r" (iret2), "=f" (dret) 280 #else 281 : "=r" (iret), "=r" (iret2) 282 #endif 283 : ); 284 285 switch( eReturnType ) 286 { 287 case typelib_TypeClass_HYPER: 288 case typelib_TypeClass_UNSIGNED_HYPER: 289 ((long*)pRegisterReturn)[0] = iret; 290 ((long*)pRegisterReturn)[1] = iret2; 291 case typelib_TypeClass_LONG: 292 case typelib_TypeClass_UNSIGNED_LONG: 293 case typelib_TypeClass_ENUM: 294 ((long*)pRegisterReturn)[0] = iret; 295 break; 296 case typelib_TypeClass_CHAR: 297 case typelib_TypeClass_SHORT: 298 case typelib_TypeClass_UNSIGNED_SHORT: 299 *(unsigned short*)pRegisterReturn = (unsigned short)iret; 300 break; 301 case typelib_TypeClass_BOOLEAN: 302 case typelib_TypeClass_BYTE: 303 *(unsigned char*)pRegisterReturn = (unsigned char)iret; 304 break; 305 case typelib_TypeClass_FLOAT: 306 #ifndef __NO_FPRS__ 307 *(float*)pRegisterReturn = (float)dret; 308 #else 309 ((unsigned int*)pRegisterReturn)[0] = iret; 310 #endif 311 break; 312 case typelib_TypeClass_DOUBLE: 313 #ifndef __NO_FPRS__ 314 *(double*)pRegisterReturn = dret; 315 #else 316 ((unsigned int*)pRegisterReturn)[0] = iret; 317 ((unsigned int*)pRegisterReturn)[1] = iret2; 318 #endif 319 break; 320 default: 321 break; 322 } 323 } 324 325 326 //================================================================================================== 327 static void cpp_call( 328 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, 329 bridges::cpp_uno::shared::VtableSlot aVtableSlot, 330 typelib_TypeDescriptionReference * pReturnTypeRef, 331 sal_Int32 nParams, typelib_MethodParameter * pParams, 332 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) 333 { 334 // max space for: [complex ret ptr], values|ptr ... 335 char * pCppStack = 336 (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); 337 char * pCppStackStart = pCppStack; 338 339 // need to know parameter types for callVirtualMethod so generate a signature string 340 char * pParamType = (char *) alloca(nParams+2); 341 char * pPT = pParamType; 342 343 // return 344 typelib_TypeDescription * pReturnTypeDescr = 0; 345 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 346 // OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); 347 348 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion 349 350 if (pReturnTypeDescr) 351 { 352 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) 353 { 354 pCppReturn = pUnoReturn; // direct way for simple types 355 } 356 else 357 { 358 // complex return via ptr 359 pCppReturn = *(void **)pCppStack = 360 (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) 361 ? alloca( pReturnTypeDescr->nSize ): pUnoReturn); // direct way 362 *pPT++ = 'I'; //signify that a complex return type on stack 363 pCppStack += sizeof(void *); 364 } 365 } 366 // push this 367 void* pAdjustedThisPtr = reinterpret_cast< void **>(pThis->getCppI()) + aVtableSlot.offset; 368 *(void**)pCppStack = pAdjustedThisPtr; 369 pCppStack += sizeof( void* ); 370 *pPT++ = 'I'; 371 372 // stack space 373 // OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); 374 // args 375 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); 376 // indizes of values this have to be converted (interface conversion cpp<=>uno) 377 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); 378 // type descriptions for reconversions 379 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); 380 381 sal_Int32 nTempIndizes = 0; 382 383 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 384 { 385 const typelib_MethodParameter & rParam = pParams[nPos]; 386 typelib_TypeDescription * pParamTypeDescr = 0; 387 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 388 389 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 390 { 391 uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, 392 pThis->getBridge()->getUno2Cpp() ); 393 394 switch (pParamTypeDescr->eTypeClass) 395 { 396 397 // we need to know type of each param so that we know whether to use 398 // gpr or fpr to pass in parameters: 399 // Key: I - int, long, pointer, etc means pass in gpr 400 // B - byte value passed in gpr 401 // S - short value passed in gpr 402 // F - float value pass in fpr 403 // D - double value pass in fpr 404 // H - long long int pass in proper pairs of gpr (3,4) (5,6), etc 405 // X - indicates end of parameter description string 406 407 case typelib_TypeClass_LONG: 408 case typelib_TypeClass_UNSIGNED_LONG: 409 case typelib_TypeClass_ENUM: 410 *pPT++ = 'I'; 411 break; 412 case typelib_TypeClass_SHORT: 413 case typelib_TypeClass_CHAR: 414 case typelib_TypeClass_UNSIGNED_SHORT: 415 *pPT++ = 'S'; 416 break; 417 case typelib_TypeClass_BOOLEAN: 418 case typelib_TypeClass_BYTE: 419 *pPT++ = 'B'; 420 break; 421 case typelib_TypeClass_FLOAT: 422 *pPT++ = 'F'; 423 break; 424 case typelib_TypeClass_DOUBLE: 425 *pPT++ = 'D'; 426 pCppStack += sizeof(sal_Int32); // extra long 427 break; 428 case typelib_TypeClass_HYPER: 429 case typelib_TypeClass_UNSIGNED_HYPER: 430 *pPT++ = 'H'; 431 pCppStack += sizeof(sal_Int32); // extra long 432 default: 433 break; 434 } 435 436 // no longer needed 437 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 438 } 439 else // ptr to complex value | ref 440 { 441 if (! rParam.bIn) // is pure out 442 { 443 // cpp out is constructed mem, uno out is not! 444 uno_constructData( 445 *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 446 pParamTypeDescr ); 447 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call 448 // will be released at reconversion 449 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 450 } 451 // is in/inout 452 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) 453 { 454 uno_copyAndConvertData( 455 *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 456 pUnoArgs[nPos], pParamTypeDescr, 457 pThis->getBridge()->getUno2Cpp() ); 458 459 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 460 // will be released at reconversion 461 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 462 } 463 else // direct way 464 { 465 *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; 466 // no longer needed 467 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 468 } 469 // KBH: FIXME: is this the right way to pass these 470 *pPT++='I'; 471 } 472 pCppStack += sizeof(sal_Int32); // standard parameter length 473 } 474 475 // terminate the signature string 476 *pPT++='X'; 477 *pPT=0; 478 479 try 480 { 481 OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); 482 callVirtualMethod( 483 pAdjustedThisPtr, aVtableSlot.index, 484 pCppReturn, pReturnTypeDescr->eTypeClass, pParamType, 485 (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); 486 // NO exception occured... 487 *ppUnoExc = 0; 488 489 // reconvert temporary params 490 for ( ; nTempIndizes--; ) 491 { 492 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 493 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; 494 495 if (pParams[nIndex].bIn) 496 { 497 if (pParams[nIndex].bOut) // inout 498 { 499 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value 500 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 501 pThis->getBridge()->getCpp2Uno() ); 502 } 503 } 504 else // pure out 505 { 506 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 507 pThis->getBridge()->getCpp2Uno() ); 508 } 509 // destroy temp cpp param => cpp: every param was constructed 510 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); 511 512 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 513 } 514 // return value 515 if (pCppReturn && pUnoReturn != pCppReturn) 516 { 517 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, 518 pThis->getBridge()->getCpp2Uno() ); 519 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); 520 } 521 } 522 catch (...) 523 { 524 // fill uno exception 525 fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, 526 *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); 527 528 // temporary params 529 for ( ; nTempIndizes--; ) 530 { 531 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 532 // destroy temp cpp param => cpp: every param was constructed 533 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); 534 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 535 } 536 // return type 537 if (pReturnTypeDescr) 538 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 539 } 540 } 541 542 } 543 544 namespace bridges { namespace cpp_uno { namespace shared { 545 546 void unoInterfaceProxyDispatch( 547 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, 548 void * pReturn, void * pArgs[], uno_Any ** ppException ) 549 { 550 // is my surrogate 551 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis 552 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI); 553 554 switch (pMemberDescr->eTypeClass) 555 { 556 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 557 { 558 559 VtableSlot aVtableSlot( 560 getVtableSlot( 561 reinterpret_cast< 562 typelib_InterfaceAttributeTypeDescription const * >( 563 pMemberDescr))); 564 565 if (pReturn) 566 { 567 // dependent dispatch 568 cpp_call( 569 pThis, aVtableSlot, 570 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, 571 0, 0, // no params 572 pReturn, pArgs, ppException ); 573 } 574 else 575 { 576 // is SET 577 typelib_MethodParameter aParam; 578 aParam.pTypeRef = 579 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; 580 aParam.bIn = sal_True; 581 aParam.bOut = sal_False; 582 583 typelib_TypeDescriptionReference * pReturnTypeRef = 0; 584 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); 585 typelib_typedescriptionreference_new( 586 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); 587 588 // dependent dispatch 589 aVtableSlot.index += 1; //get then set method 590 cpp_call( 591 pThis, aVtableSlot, 592 pReturnTypeRef, 593 1, &aParam, 594 pReturn, pArgs, ppException ); 595 596 typelib_typedescriptionreference_release( pReturnTypeRef ); 597 } 598 599 break; 600 } 601 case typelib_TypeClass_INTERFACE_METHOD: 602 { 603 604 VtableSlot aVtableSlot( 605 getVtableSlot( 606 reinterpret_cast< 607 typelib_InterfaceMethodTypeDescription const * >( 608 pMemberDescr))); 609 switch (aVtableSlot.index) 610 { 611 // standard calls 612 case 1: // acquire uno interface 613 (*pUnoI->acquire)( pUnoI ); 614 *ppException = 0; 615 break; 616 case 2: // release uno interface 617 (*pUnoI->release)( pUnoI ); 618 *ppException = 0; 619 break; 620 case 0: // queryInterface() opt 621 { 622 typelib_TypeDescription * pTD = 0; 623 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); 624 if (pTD) 625 { 626 uno_Interface * pInterface = 0; 627 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( 628 pThis->pBridge->getUnoEnv(), 629 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); 630 631 if (pInterface) 632 { 633 ::uno_any_construct( 634 reinterpret_cast< uno_Any * >( pReturn ), 635 &pInterface, pTD, 0 ); 636 (*pInterface->release)( pInterface ); 637 TYPELIB_DANGER_RELEASE( pTD ); 638 *ppException = 0; 639 break; 640 } 641 TYPELIB_DANGER_RELEASE( pTD ); 642 } 643 } // else perform queryInterface() 644 default: 645 // dependent dispatch 646 cpp_call( 647 pThis, aVtableSlot, 648 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, 649 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, 650 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, 651 pReturn, pArgs, ppException ); 652 } 653 break; 654 } 655 default: 656 { 657 ::com::sun::star::uno::RuntimeException aExc( 658 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), 659 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); 660 661 Type const & rExcType = ::getCppuType( &aExc ); 662 // binary identical null reference 663 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); 664 } 665 } 666 } 667 668 } } } 669