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 #include <malloc.h> 27 #include <com/sun/star/uno/genfunc.hxx> 28 #include <uno/data.h> 29 30 #include "bridges/cpp_uno/shared/bridge.hxx" 31 #include "bridges/cpp_uno/shared/types.hxx" 32 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" 33 #include "bridges/cpp_uno/shared/vtables.hxx" 34 35 #include "share.hxx" 36 37 #include <sal/alloca.h> 38 39 using namespace rtl; 40 using namespace com::sun::star::uno; 41 42 namespace 43 { 44 //================================================================================================== 45 // The call instruction within the asm section of callVirtualMethod may throw 46 // exceptions. So that the compiler handles this correctly, it is important 47 // that (a) callVirtualMethod might call dummy_can_throw_anything (although this 48 // never happens at runtime), which in turn can throw exceptions, and (b) 49 // callVirtualMethod is not inlined at its call site (so that any exceptions are 50 // caught which are thrown from the instruction calling callVirtualMethod): 51 52 void callVirtualMethod( void * pAdjustedThisPtr, 53 sal_Int32 nVtableIndex, 54 void * pRegisterReturn, 55 typelib_TypeClass eReturnType, 56 sal_Int32 * pStackLongs, 57 sal_Int32 nStackLongs ) __attribute__((noinline)); 58 59 void callVirtualMethod( void * pAdjustedThisPtr, 60 sal_Int32 nVtableIndex, 61 void * pRegisterReturn, 62 typelib_TypeClass eReturnType, 63 sal_Int32 * pStackLongs, 64 sal_Int32 nStackLongs ) 65 { 66 // parameter list is mixed list of * and values 67 // reference parameters are pointers 68 69 OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); 70 OSL_ENSURE( (sizeof(void *) == 4) && 71 (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); 72 OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" ); 73 74 // never called 75 if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something 76 77 volatile long o0 = 0, o1 = 0; // for register returns 78 volatile double f0d = 0; 79 volatile float f0f = 0; 80 volatile long long saveReg[7]; 81 82 __asm__ ( 83 // save registers 84 "std %%l0, [%4]\n\t" 85 "mov %4, %%l0\n\t" 86 "mov %%l0, %%l1\n\t" 87 "add %%l0, 8, %%l0\n\t" 88 "std %%l2, [%%l0]\n\t" 89 "add %%l0, 8, %%l0\n\t" 90 "std %%l4, [%%l0]\n\t" 91 "add %%l0, 8, %%l0\n\t" 92 "std %%o0, [%%l0]\n\t" 93 "add %%l0, 8, %%l0\n\t" 94 "std %%o2, [%%l0]\n\t" 95 "add %%l0, 8, %%l0\n\t" 96 "std %%o4, [%%l0]\n\t" 97 "add %%l0, 8, %%l0\n\t" 98 "std %%l6, [%%l0]\n\t" 99 "mov %%l1, %%l7\n\t" 100 101 // increase our own stackframe if necessary 102 "mov %%sp, %%l3\n\t" // save stack ptr for readjustment 103 104 "subcc %%i5, 7, %%l0\n\t" 105 "ble .LmoveOn\n\t" 106 "nop\n\t" 107 108 "sll %%l0, 2, %%l0\n\t" 109 "add %%l0, 96, %%l0\n\t" 110 "mov %%sp, %%l1\n\t" // old stack ptr 111 "sub %%sp, %%l0, %%l0\n\t" // future stack ptr 112 "andcc %%l0, 7, %%g0\n\t" // align stack to 8 113 "be .LisAligned\n\t" 114 "nop\n\t" 115 "sub %%l0, 4, %%l0\n" 116 ".LisAligned:\n\t" 117 "mov %%l0, %%o5\n\t" // save newly computed stack ptr 118 "add %%g0, 16, %%o4\n" 119 120 // now copy longs down to save register window 121 // and local variables 122 ".LcopyDown:\n\t" 123 "ld [%%l1], %%l2\n\t" 124 "st %%l2,[%%l0]\n\t" 125 "add %%l0, 4, %%l0\n\t" 126 "add %%l1, 4, %%l1\n\t" 127 "subcc %%o4, 1, %%o4\n\t" 128 "bne .LcopyDown\n\t" 129 130 "mov %%o5, %%sp\n\t" // move new stack ptr (hopefully) atomically 131 // while register window is valid in both spaces 132 // (scheduling might hit in copyDown loop) 133 134 "sub %%i5, 7, %%l0\n\t" // copy parameters past the sixth to stack 135 "add %%i4, 28, %%l1\n\t" 136 "add %%sp, 92, %%l2\n" 137 ".LcopyLong:\n\t" 138 "ld [%%l1], %%o0\n\t" 139 "st %%o0, [%%l2]\n\t" 140 "add %%l1, 4, %%l1\n\t" 141 "add %%l2, 4, %%l2\n\t" 142 "subcc %%l0, 1, %%l0\n\t" 143 "bne .LcopyLong\n\t" 144 "nop\n" 145 146 ".LmoveOn:\n\t" 147 "mov %%i5, %%l0\n\t" // prepare out registers 148 "mov %%i4, %%l1\n\t" 149 150 "ld [%%l1], %%o0\n\t" // prepare complex return ptr 151 "st %%o0, [%%sp+64]\n\t" 152 "sub %%l0, 1, %%l0\n\t" 153 "add %%l1, 4, %%l1\n\t" 154 155 "ld [%%l1], %%o0\n\t" 156 "subcc %%l0, 1, %%l0\n\t" 157 "be .LdoCall\n\t" 158 "nop\n\t" 159 160 "add %%l1, 4, %%l1\n\t" 161 "ld [%%l1], %%o1\n\t" 162 "subcc %%l0, 1, %%l0\n\t" 163 "be .LdoCall\n\t" 164 "nop\n\t" 165 166 "add %%l1, 4, %%l1\n\t" 167 "ld [%%l1], %%o2\n\t" 168 "subcc %%l0, 1, %%l0\n\t" 169 "be .LdoCall\n\t" 170 "nop\n\t" 171 172 "add %%l1, 4, %%l1\n\t" 173 "ld [%%l1], %%o3\n\t" 174 "subcc %%l0, 1, %%l0\n\t" 175 "be .LdoCall\n\t" 176 "nop\n\t" 177 178 "add %%l1, 4, %%l1\n\t" 179 "ld [%%l1], %%o4\n\t" 180 "subcc %%l0, 1, %%l0\n\t" 181 "be .LdoCall\n\t" 182 "nop\n\t" 183 184 "add %%l1, 4, %%l1\n\t" 185 "ld [%%l1], %%o5\n" 186 187 ".LdoCall:\n\t" 188 "ld [%%i0], %%l0\n\t" // get vtable ptr 189 190 "sll %%i1, 2, %%l6\n\t" 191 // "add %%l6, 8, %%l6\n\t" 192 "add %%l6, %%l0, %%l0\n\t" 193 // // vtable has 8byte wide entries, 194 // // upper half contains 2 half words, of which the first 195 // // is the this ptr patch ! 196 // // first entry is (or __tf) 197 198 // "ldsh [%%l0], %%l6\n\t" // load this ptr patch 199 // "add %%l6, %%o0, %%o0\n\t" // patch this ptr 200 201 // "add %%l0, 4, %%l0\n\t" // get virtual function ptr 202 "ld [%%l0], %%l0\n\t" 203 204 "ld [%%i4], %%l2\n\t" 205 "subcc %%l2, %%g0, %%l2\n\t" 206 "bne .LcomplexCall\n\t" 207 "nop\n\t" 208 "call %%l0\n\t" 209 "nop\n\t" 210 "ba .LcallReturned\n\t" 211 "nop\n" 212 ".LcomplexCall:\n\t" 213 "call %%l0\n\t" 214 "nop\n\t" 215 "unimp\n" 216 217 ".LcallReturned:\n\t" 218 "mov %%l3, %%sp\n\t" // readjust stack so that our locals are where they belong 219 "st %%o0, %0\n\t" // save possible return registers into our locals 220 "st %%o1, %1\n\t" 221 "std %%f0, %2\n\t" 222 "st %%f0, %3\n\t" 223 224 // restore registers 225 "ldd [%%l7], %%l0\n\t" 226 "add %%l7, 8, %%l7\n\t" 227 "ldd [%%l7], %%l2\n\t" 228 "add %%l7, 8, %%l7\n\t" 229 "ldd [%%l7], %%l4\n\t" 230 "add %%l7, 8, %%l7\n\t" 231 "ldd [%%l7], %%o0\n\t" 232 "add %%l7, 8, %%l7\n\t" 233 "ldd [%%l7], %%o2\n\t" 234 "add %%l7, 8, %%l7\n\t" 235 "ldd [%%l7], %%o4\n\t" 236 "add %%l7, 8, %%l7\n\t" 237 "ldd [%%l7], %%l6\n\t" 238 : : 239 "m"(o0), 240 "m"(o1), 241 "m"(f0d), 242 "m"(f0f), 243 "r"(&saveReg[0]) 244 ); 245 switch( eReturnType ) 246 { 247 case typelib_TypeClass_HYPER: 248 case typelib_TypeClass_UNSIGNED_HYPER: 249 ((long*)pRegisterReturn)[1] = o1; 250 case typelib_TypeClass_LONG: 251 case typelib_TypeClass_UNSIGNED_LONG: 252 case typelib_TypeClass_ENUM: 253 ((long*)pRegisterReturn)[0] = o0; 254 break; 255 case typelib_TypeClass_CHAR: 256 case typelib_TypeClass_SHORT: 257 case typelib_TypeClass_UNSIGNED_SHORT: 258 *(unsigned short*)pRegisterReturn = (unsigned short)o0; 259 break; 260 case typelib_TypeClass_BOOLEAN: 261 case typelib_TypeClass_BYTE: 262 *(unsigned char*)pRegisterReturn = (unsigned char)o0; 263 break; 264 case typelib_TypeClass_FLOAT: 265 *(float*)pRegisterReturn = f0f; 266 break; 267 case typelib_TypeClass_DOUBLE: 268 *(double*)pRegisterReturn = f0d; 269 break; 270 } 271 } 272 273 //================================================================================================= 274 static void cpp_call( 275 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, 276 bridges::cpp_uno::shared::VtableSlot aVtableSlot, 277 typelib_TypeDescriptionReference * pReturnTypeRef, 278 sal_Int32 nParams, typelib_MethodParameter * pParams, 279 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) 280 { 281 // max space for: complex ret ptr, this, values|ptr ... 282 char * pCppStack = 283 (char *)alloca( (nParams+2) * sizeof(sal_Int64) ); 284 char * pCppStackStart = pCppStack; 285 286 // return 287 typelib_TypeDescription * pReturnTypeDescr = 0; 288 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 289 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); 290 291 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion 292 293 if (pReturnTypeDescr) 294 { 295 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) 296 { 297 pCppReturn = pUnoReturn; // direct way for simple types 298 *(void**)pCppStack = NULL; 299 } 300 else 301 { 302 // complex return via ptr 303 pCppReturn = *(void **)pCppStack = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr ) 304 ? alloca( pReturnTypeDescr->nSize ) 305 : pUnoReturn); // direct way 306 } 307 pCppStack += sizeof(void*); 308 } 309 // push this 310 void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) 311 + aVtableSlot.offset; 312 *(void**)pCppStack = pAdjustedThisPtr; 313 pCppStack += sizeof( void* ); 314 315 // stack space 316 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); 317 // args 318 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); 319 // indizes of values this have to be converted (interface conversion cpp<=>uno) 320 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); 321 // type descriptions for reconversions 322 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); 323 324 sal_Int32 nTempIndizes = 0; 325 326 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 327 { 328 const typelib_MethodParameter & rParam = pParams[nPos]; 329 typelib_TypeDescription * pParamTypeDescr = 0; 330 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 331 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 332 { 333 pCppArgs[ nPos ] = CPPU_CURRENT_NAMESPACE::adjustPointer(pCppStack, pParamTypeDescr ); 334 335 switch (pParamTypeDescr->eTypeClass) 336 { 337 case typelib_TypeClass_HYPER: 338 case typelib_TypeClass_UNSIGNED_HYPER: 339 case typelib_TypeClass_DOUBLE: 340 OSL_ASSERT( sizeof (double) == sizeof (sal_Int64) ); 341 *reinterpret_cast< sal_Int32 * >(pCppStack) = 342 *reinterpret_cast< sal_Int32 const * >(pUnoArgs[ nPos ]); 343 pCppStack += sizeof (sal_Int32); 344 *reinterpret_cast< sal_Int32 * >(pCppStack) = 345 *(reinterpret_cast< sal_Int32 const * >(pUnoArgs[ nPos ] ) + 1); 346 break; 347 default: 348 uno_copyAndConvertData( 349 pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr, 350 pThis->getBridge()->getUno2Cpp() ); 351 break; 352 } 353 // no longer needed 354 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 355 } 356 else // ptr to complex value | ref 357 { 358 if (! rParam.bIn) // is pure out 359 { 360 // cpp out is constructed mem, uno out is not! 361 uno_constructData( 362 *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 363 pParamTypeDescr ); 364 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call 365 // will be released at reconversion 366 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 367 } 368 // is in/inout 369 else if (bridges::cpp_uno::shared::relatesToInterfaceType( 370 pParamTypeDescr )) 371 { 372 uno_copyAndConvertData( 373 *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 374 pUnoArgs[nPos], pParamTypeDescr, 375 pThis->getBridge()->getUno2Cpp() ); 376 377 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 378 // will be released at reconversion 379 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 380 } 381 else // direct way 382 { 383 *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; 384 // no longer needed 385 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 386 } 387 } 388 pCppStack += sizeof(sal_Int32); // standard parameter length 389 } 390 391 try 392 { 393 int nStackLongs = (pCppStack - pCppStackStart)/sizeof(sal_Int32); 394 OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic" ); 395 396 if( nStackLongs & 1 ) 397 // stack has to be 8 byte aligned 398 nStackLongs++; 399 callVirtualMethod( 400 pAdjustedThisPtr, 401 aVtableSlot.index, 402 pCppReturn, 403 pReturnTypeDescr->eTypeClass, 404 (sal_Int32 *)pCppStackStart, 405 nStackLongs); 406 // NO exception occured... 407 *ppUnoExc = 0; 408 409 // reconvert temporary params 410 for ( ; nTempIndizes--; ) 411 { 412 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 413 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; 414 415 if (pParams[nIndex].bIn) 416 { 417 if (pParams[nIndex].bOut) // inout 418 { 419 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value 420 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 421 pThis->getBridge()->getCpp2Uno() ); 422 } 423 } 424 else // pure out 425 { 426 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 427 pThis->getBridge()->getCpp2Uno() ); 428 } 429 // destroy temp cpp param => cpp: every param was constructed 430 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); 431 432 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 433 } 434 // return value 435 if (pCppReturn && pUnoReturn != pCppReturn) 436 { 437 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, 438 pThis->getBridge()->getCpp2Uno() ); 439 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); 440 } 441 } 442 catch( ... ) 443 { 444 // get exception 445 fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, 446 *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); 447 448 // temporary params 449 for ( ; nTempIndizes--; ) 450 { 451 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 452 // destroy temp cpp param => cpp: every param was constructed 453 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); 454 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 455 } 456 // return type 457 if (pReturnTypeDescr) 458 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 459 } 460 } 461 462 } 463 464 namespace bridges { namespace cpp_uno { namespace shared { 465 466 void unoInterfaceProxyDispatch( 467 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, 468 void * pReturn, void * pArgs[], uno_Any ** ppException ) 469 { 470 #if defined BRIDGES_DEBUG 471 OString cstr( OUStringToOString( pMemberDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); 472 fprintf( stderr, "received dispatch( %s )\n", cstr.getStr() ); 473 #endif 474 475 // is my surrogate 476 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis 477 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); 478 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; 479 480 switch (pMemberDescr->eTypeClass) 481 { 482 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 483 { 484 VtableSlot aVtableSlot( 485 getVtableSlot( 486 reinterpret_cast< 487 typelib_InterfaceAttributeTypeDescription const * >( 488 pMemberDescr))); 489 if (pReturn) 490 { 491 // dependent dispatch 492 cpp_call( 493 pThis, aVtableSlot, 494 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, 495 0, 0, // no params 496 pReturn, pArgs, ppException ); 497 } 498 else 499 { 500 // is SET 501 typelib_MethodParameter aParam; 502 aParam.pTypeRef = 503 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; 504 aParam.bIn = sal_True; 505 aParam.bOut = sal_False; 506 507 typelib_TypeDescriptionReference * pReturnTypeRef = 0; 508 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); 509 typelib_typedescriptionreference_new( 510 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); 511 512 // dependent dispatch 513 aVtableSlot.index += 1; // get, then set method 514 cpp_call( 515 pThis, aVtableSlot, 516 pReturnTypeRef, 517 1, &aParam, 518 pReturn, pArgs, ppException ); 519 520 typelib_typedescriptionreference_release( pReturnTypeRef ); 521 } 522 523 break; 524 } 525 case typelib_TypeClass_INTERFACE_METHOD: 526 { 527 VtableSlot aVtableSlot( 528 getVtableSlot( 529 reinterpret_cast< 530 typelib_InterfaceMethodTypeDescription const * >( 531 pMemberDescr))); 532 switch (aVtableSlot.index) 533 { 534 // standard calls 535 case 1: // acquire uno interface 536 (*pUnoI->acquire)( pUnoI ); 537 *ppException = 0; 538 break; 539 case 2: // release uno interface 540 (*pUnoI->release)( pUnoI ); 541 *ppException = 0; 542 break; 543 case 0: // queryInterface() opt 544 { 545 typelib_TypeDescription * pTD = 0; 546 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); 547 if (pTD) 548 { 549 uno_Interface * pInterface = 0; 550 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( 551 pThis->pBridge->getUnoEnv(), 552 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); 553 554 if (pInterface) 555 { 556 ::uno_any_construct( 557 reinterpret_cast< uno_Any * >( pReturn ), 558 &pInterface, pTD, 0 ); 559 (*pInterface->release)( pInterface ); 560 TYPELIB_DANGER_RELEASE( pTD ); 561 *ppException = 0; 562 break; 563 } 564 TYPELIB_DANGER_RELEASE( pTD ); 565 } 566 } // else perform queryInterface() 567 default: 568 // dependent dispatch 569 cpp_call( 570 pThis, aVtableSlot, 571 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, 572 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, 573 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, 574 pReturn, pArgs, ppException ); 575 } 576 break; 577 } 578 default: 579 { 580 ::com::sun::star::uno::RuntimeException aExc( 581 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), 582 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); 583 584 Type const & rExcType = ::getCppuType( &aExc ); 585 // binary identical null reference 586 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); 587 } 588 } 589 } 590 591 } } } 592