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_cppu.hxx" 26 27 #include "cppu/EnvDcp.hxx" 28 29 #include "sal/alloca.h" 30 #include "osl/diagnose.h" 31 #include "osl/interlck.h" 32 #include "osl/mutex.hxx" 33 #include "osl/module.h" 34 #include "osl/process.h" 35 #include "rtl/process.h" 36 #include "rtl/unload.h" 37 #include "rtl/string.hxx" 38 #include "rtl/ustring.hxx" 39 #include "rtl/ustrbuf.hxx" 40 #include "rtl/instance.hxx" 41 #include "typelib/typedescription.h" 42 #include "uno/dispatcher.h" 43 #include "uno/environment.h" 44 #include "uno/lbnames.h" 45 #include "prim.hxx" 46 #include "destr.hxx" 47 #include "loadmodule.hxx" 48 49 #include <hash_map> 50 #include <vector> 51 #include <stdio.h> 52 53 54 using ::rtl::OUString; 55 56 namespace 57 { 58 59 //------------------------------------------------------------------------------ 60 inline static bool td_equals( typelib_InterfaceTypeDescription * pTD1, 61 typelib_InterfaceTypeDescription * pTD2 ) 62 { 63 return (pTD1 == pTD2 || 64 (((typelib_TypeDescription *)pTD1)->pTypeName->length == 65 ((typelib_TypeDescription *)pTD2)->pTypeName->length && 66 ::rtl_ustr_compare( 67 ((typelib_TypeDescription *) pTD1)->pTypeName->buffer, 68 ((typelib_TypeDescription *) pTD2)->pTypeName->buffer ) == 0)); 69 } 70 71 struct ObjectEntry; 72 struct uno_DefaultEnvironment; 73 74 //------------------------------------------------------------------------------ 75 struct InterfaceEntry 76 { 77 sal_Int32 refCount; 78 void * pInterface; 79 uno_freeProxyFunc fpFreeProxy; 80 typelib_InterfaceTypeDescription * pTypeDescr; 81 }; 82 83 struct ObjectEntry 84 { 85 OUString oid; 86 sal_Int32 nRef; 87 ::std::vector< InterfaceEntry > aInterfaces; 88 bool mixedObject; 89 90 inline ObjectEntry( const OUString & rOId_ ); 91 92 inline void append( 93 uno_DefaultEnvironment * pEnv, 94 void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr, 95 uno_freeProxyFunc fpFreeProxy ); 96 inline InterfaceEntry * find( 97 typelib_InterfaceTypeDescription * pTypeDescr ); 98 inline sal_Int32 find( void * iface_ptr, ::std::size_t pos ); 99 }; 100 101 //------------------------------------------------------------------------------ 102 struct FctPtrHash : 103 public ::std::unary_function< const void *, ::std::size_t > 104 { 105 ::std::size_t operator () ( const void * pKey ) const 106 { return (::std::size_t) pKey; } 107 }; 108 109 //------------------------------------------------------------------------------ 110 struct FctOUStringHash : 111 public ::std::unary_function< const OUString &, ::std::size_t > 112 { 113 ::std::size_t operator () ( const OUString & rKey ) const 114 { return rKey.hashCode(); } 115 }; 116 117 // mapping from environment name to environment 118 typedef ::std::hash_map< 119 OUString, uno_Environment *, FctOUStringHash, 120 ::std::equal_to< OUString > > OUString2EnvironmentMap; 121 122 // mapping from ptr to object entry 123 typedef ::std::hash_map< 124 void *, ObjectEntry *, FctPtrHash, 125 ::std::equal_to< void * > > Ptr2ObjectMap; 126 // mapping from oid to object entry 127 typedef ::std::hash_map< 128 OUString, ObjectEntry *, FctOUStringHash, 129 ::std::equal_to< OUString > > OId2ObjectMap; 130 131 132 //============================================================================== 133 struct EnvironmentsData 134 { 135 ::osl::Mutex mutex; 136 OUString2EnvironmentMap aName2EnvMap; 137 138 EnvironmentsData() : isDisposing(false) {} 139 ~EnvironmentsData(); 140 141 inline void getEnvironment( 142 uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext ); 143 inline void registerEnvironment( uno_Environment ** ppEnv ); 144 inline void getRegisteredEnvironments( 145 uno_Environment *** pppEnvs, sal_Int32 * pnLen, 146 uno_memAlloc memAlloc, const OUString & rEnvDcp ); 147 148 bool isDisposing; 149 }; 150 151 namespace 152 { 153 struct theEnvironmentsData : public rtl::Static< EnvironmentsData, theEnvironmentsData > {}; 154 } 155 156 //============================================================================== 157 struct uno_DefaultEnvironment : public uno_ExtEnvironment 158 { 159 sal_Int32 nRef; 160 sal_Int32 nWeakRef; 161 162 ::osl::Mutex mutex; 163 Ptr2ObjectMap aPtr2ObjectMap; 164 OId2ObjectMap aOId2ObjectMap; 165 166 uno_DefaultEnvironment( 167 const OUString & rEnvDcp_, void * pContext_ ); 168 ~uno_DefaultEnvironment(); 169 }; 170 171 //______________________________________________________________________________ 172 inline ObjectEntry::ObjectEntry( OUString const & rOId_ ) 173 : oid( rOId_ ), 174 nRef( 0 ), 175 mixedObject( false ) 176 { 177 aInterfaces.reserve( 2 ); 178 } 179 180 //______________________________________________________________________________ 181 inline void ObjectEntry::append( 182 uno_DefaultEnvironment * pEnv, 183 void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr, 184 uno_freeProxyFunc fpFreeProxy ) 185 { 186 InterfaceEntry aNewEntry; 187 if (! fpFreeProxy) 188 (*pEnv->acquireInterface)( pEnv, pInterface ); 189 aNewEntry.refCount = 1; 190 aNewEntry.pInterface = pInterface; 191 aNewEntry.fpFreeProxy = fpFreeProxy; 192 typelib_typedescription_acquire( (typelib_TypeDescription *) pTypeDescr ); 193 aNewEntry.pTypeDescr = pTypeDescr; 194 195 ::std::pair< Ptr2ObjectMap::iterator, bool > insertion( 196 pEnv->aPtr2ObjectMap.insert( Ptr2ObjectMap::value_type( 197 pInterface, this ) ) ); 198 OSL_ASSERT( insertion.second || 199 (find( pInterface, 0 ) >= 0 && 200 // points to the same object entry: 201 insertion.first->second == this) ); 202 aInterfaces.push_back( aNewEntry ); 203 } 204 205 //______________________________________________________________________________ 206 inline InterfaceEntry * ObjectEntry::find( 207 typelib_InterfaceTypeDescription * pTypeDescr_ ) 208 { 209 OSL_ASSERT( ! aInterfaces.empty() ); 210 if (aInterfaces.empty()) 211 return 0; 212 213 // shortcut common case: 214 OUString const & type_name = 215 OUString::unacquired( 216 &((typelib_TypeDescription *) pTypeDescr_)->pTypeName ); 217 if (type_name.equalsAsciiL( 218 RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") )) 219 { 220 return &aInterfaces[ 0 ]; 221 } 222 223 ::std::size_t nSize = aInterfaces.size(); 224 for ( ::std::size_t nPos = 0; nPos < nSize; ++nPos ) 225 { 226 typelib_InterfaceTypeDescription * pITD = 227 aInterfaces[ nPos ].pTypeDescr; 228 while (pITD) 229 { 230 if (td_equals( pITD, pTypeDescr_ )) 231 return &aInterfaces[ nPos ]; 232 pITD = pITD->pBaseTypeDescription; 233 } 234 } 235 return 0; 236 } 237 238 //______________________________________________________________________________ 239 inline sal_Int32 ObjectEntry::find( 240 void * iface_ptr, ::std::size_t pos ) 241 { 242 ::std::size_t size = aInterfaces.size(); 243 for ( ; pos < size; ++pos ) 244 { 245 if (aInterfaces[ pos ].pInterface == iface_ptr) 246 return pos; 247 } 248 return -1; 249 } 250 251 extern "C" 252 { 253 254 //------------------------------------------------------------------------------ 255 static void SAL_CALL defenv_registerInterface( 256 uno_ExtEnvironment * pEnv, void ** ppInterface, 257 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr ) 258 { 259 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" ); 260 OUString const & rOId = OUString::unacquired( &pOId ); 261 262 uno_DefaultEnvironment * that = 263 static_cast< uno_DefaultEnvironment * >( pEnv ); 264 ::osl::ClearableMutexGuard guard( that->mutex ); 265 266 // try to insert dummy 0: 267 std::pair<OId2ObjectMap::iterator, bool> const insertion( 268 that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, 0 ) ) ); 269 if (insertion.second) 270 { 271 ObjectEntry * pOEntry = new ObjectEntry( rOId ); 272 insertion.first->second = pOEntry; 273 ++pOEntry->nRef; // another register call on object 274 pOEntry->append( that, *ppInterface, pTypeDescr, 0 ); 275 } 276 else // object entry exists 277 { 278 ObjectEntry * pOEntry = insertion.first->second; 279 ++pOEntry->nRef; // another register call on object 280 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr ); 281 282 if (pIEntry) // type entry exists 283 { 284 ++pIEntry->refCount; 285 if (pIEntry->pInterface != *ppInterface) 286 { 287 void * pInterface = pIEntry->pInterface; 288 (*pEnv->acquireInterface)( pEnv, pInterface ); 289 guard.clear(); 290 (*pEnv->releaseInterface)( pEnv, *ppInterface ); 291 *ppInterface = pInterface; 292 } 293 } 294 else 295 { 296 pOEntry->append( that, *ppInterface, pTypeDescr, 0 ); 297 } 298 } 299 } 300 301 //------------------------------------------------------------------------------ 302 static void SAL_CALL defenv_registerProxyInterface( 303 uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy, 304 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr ) 305 { 306 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy, 307 "### null ptr!" ); 308 OUString const & rOId = OUString::unacquired( &pOId ); 309 310 uno_DefaultEnvironment * that = 311 static_cast< uno_DefaultEnvironment * >( pEnv ); 312 ::osl::ClearableMutexGuard guard( that->mutex ); 313 314 // try to insert dummy 0: 315 std::pair<OId2ObjectMap::iterator, bool> const insertion( 316 that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, 0 ) ) ); 317 if (insertion.second) 318 { 319 ObjectEntry * pOEntry = new ObjectEntry( rOId ); 320 insertion.first->second = pOEntry; 321 ++pOEntry->nRef; // another register call on object 322 pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy ); 323 } 324 else // object entry exists 325 { 326 ObjectEntry * pOEntry = insertion.first->second; 327 328 // first registration was an original, then registerProxyInterface(): 329 pOEntry->mixedObject |= 330 (!pOEntry->aInterfaces.empty() && 331 pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0); 332 333 ++pOEntry->nRef; // another register call on object 334 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr ); 335 336 if (pIEntry) // type entry exists 337 { 338 if (pIEntry->pInterface == *ppInterface) 339 { 340 ++pIEntry->refCount; 341 } 342 else 343 { 344 void * pInterface = pIEntry->pInterface; 345 (*pEnv->acquireInterface)( pEnv, pInterface ); 346 --pOEntry->nRef; // manual revoke of proxy to be freed 347 guard.clear(); 348 (*freeProxy)( pEnv, *ppInterface ); 349 *ppInterface = pInterface; 350 } 351 } 352 else 353 { 354 pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy ); 355 } 356 } 357 } 358 359 //------------------------------------------------------------------------------ 360 static void SAL_CALL s_stub_defenv_revokeInterface(va_list * pParam) 361 { 362 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); 363 void * pInterface = va_arg(*pParam, void *); 364 365 OSL_ENSURE( pEnv && pInterface, "### null ptr!" ); 366 uno_DefaultEnvironment * that = 367 static_cast< uno_DefaultEnvironment * >( pEnv ); 368 ::osl::ClearableMutexGuard guard( that->mutex ); 369 370 Ptr2ObjectMap::const_iterator const iFind( 371 that->aPtr2ObjectMap.find( pInterface ) ); 372 OSL_ASSERT( iFind != that->aPtr2ObjectMap.end() ); 373 ObjectEntry * pOEntry = iFind->second; 374 if (! --pOEntry->nRef) 375 { 376 // cleanup maps 377 that->aOId2ObjectMap.erase( pOEntry->oid ); 378 sal_Int32 nPos; 379 for ( nPos = pOEntry->aInterfaces.size(); nPos--; ) 380 { 381 that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface ); 382 } 383 384 // the last proxy interface of the environment might kill this 385 // environment, because of releasing its language binding!!! 386 guard.clear(); 387 388 // release interfaces 389 for ( nPos = pOEntry->aInterfaces.size(); nPos--; ) 390 { 391 InterfaceEntry const & rEntry = pOEntry->aInterfaces[nPos]; 392 typelib_typedescription_release( 393 (typelib_TypeDescription *) rEntry.pTypeDescr ); 394 if (rEntry.fpFreeProxy) // is proxy or used interface? 395 { 396 (*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface ); 397 } 398 else 399 { 400 (*pEnv->releaseInterface)( pEnv, rEntry.pInterface ); 401 } 402 } 403 404 delete pOEntry; 405 } 406 else if (pOEntry->mixedObject) 407 { 408 OSL_ASSERT( !pOEntry->aInterfaces.empty() && 409 pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0 ); 410 411 sal_Int32 index = pOEntry->find( pInterface, 1 ); 412 OSL_ASSERT( index > 0 ); 413 if (index > 0) 414 { 415 InterfaceEntry & entry = pOEntry->aInterfaces[ index ]; 416 OSL_ASSERT( entry.pInterface == pInterface ); 417 if (entry.fpFreeProxy != 0) 418 { 419 --entry.refCount; 420 if (entry.refCount == 0) 421 { 422 uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy; 423 typelib_TypeDescription * pTypeDescr = 424 reinterpret_cast< typelib_TypeDescription * >( 425 entry.pTypeDescr ); 426 427 pOEntry->aInterfaces.erase( 428 pOEntry->aInterfaces.begin() + index ); 429 if (pOEntry->find( pInterface, index ) < 0) 430 { 431 // proxy ptr not registered for another interface: 432 // remove from ptr map 433 #if OSL_DEBUG_LEVEL > 0 434 ::std::size_t erased = 435 #endif 436 that->aPtr2ObjectMap.erase( pInterface ); 437 OSL_ASSERT( erased == 1 ); 438 } 439 440 guard.clear(); 441 442 typelib_typedescription_release( pTypeDescr ); 443 (*fpFreeProxy)( pEnv, pInterface ); 444 } 445 } 446 } 447 } 448 } 449 450 static void SAL_CALL defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface) 451 { 452 uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface); 453 } 454 455 //------------------------------------------------------------------------------ 456 static void SAL_CALL defenv_getObjectIdentifier( 457 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface ) 458 { 459 OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" ); 460 if (*ppOId) 461 { 462 ::rtl_uString_release( *ppOId ); 463 *ppOId = 0; 464 } 465 466 uno_DefaultEnvironment * that = 467 static_cast< uno_DefaultEnvironment * >( pEnv ); 468 ::osl::ClearableMutexGuard guard( that->mutex ); 469 470 Ptr2ObjectMap::const_iterator const iFind( 471 that->aPtr2ObjectMap.find( pInterface ) ); 472 if (iFind == that->aPtr2ObjectMap.end()) 473 { 474 guard.clear(); 475 (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface ); 476 } 477 else 478 { 479 rtl_uString * hstr = iFind->second->oid.pData; 480 rtl_uString_acquire( hstr ); 481 *ppOId = hstr; 482 } 483 } 484 485 //------------------------------------------------------------------------------ 486 static void SAL_CALL defenv_getRegisteredInterface( 487 uno_ExtEnvironment * pEnv, void ** ppInterface, 488 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr ) 489 { 490 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" ); 491 if (*ppInterface) 492 { 493 (*pEnv->releaseInterface)( pEnv, *ppInterface ); 494 *ppInterface = 0; 495 } 496 497 OUString const & rOId = OUString::unacquired( &pOId ); 498 uno_DefaultEnvironment * that = 499 static_cast< uno_DefaultEnvironment * >( pEnv ); 500 ::osl::MutexGuard guard( that->mutex ); 501 502 OId2ObjectMap::const_iterator const iFind 503 ( that->aOId2ObjectMap.find( rOId ) ); 504 if (iFind != that->aOId2ObjectMap.end()) 505 { 506 InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr ); 507 if (pIEntry) 508 { 509 (*pEnv->acquireInterface)( pEnv, pIEntry->pInterface ); 510 *ppInterface = pIEntry->pInterface; 511 } 512 } 513 } 514 515 //------------------------------------------------------------------------------ 516 static void SAL_CALL defenv_getRegisteredInterfaces( 517 uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen, 518 uno_memAlloc memAlloc ) 519 { 520 OSL_ENSURE( pEnv && pppInterfaces && pnLen && memAlloc, "### null ptr!" ); 521 uno_DefaultEnvironment * that = 522 static_cast< uno_DefaultEnvironment * >( pEnv ); 523 ::osl::MutexGuard guard( that->mutex ); 524 525 sal_Int32 nLen = that->aPtr2ObjectMap.size(); 526 sal_Int32 nPos = 0; 527 void ** ppInterfaces = (void **) (*memAlloc)( nLen * sizeof (void *) ); 528 529 Ptr2ObjectMap::const_iterator iPos( that->aPtr2ObjectMap.begin() ); 530 Ptr2ObjectMap::const_iterator const iEnd( that->aPtr2ObjectMap.end() ); 531 while (iPos != iEnd) 532 { 533 (*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos++] = (*iPos).first ); 534 ++iPos; 535 } 536 537 *pppInterfaces = ppInterfaces; 538 *pnLen = nLen; 539 } 540 541 //------------------------------------------------------------------------------ 542 static void SAL_CALL defenv_acquire( uno_Environment * pEnv ) 543 { 544 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 545 ::osl_incrementInterlockedCount( &that->nWeakRef ); 546 ::osl_incrementInterlockedCount( &that->nRef ); 547 } 548 549 //------------------------------------------------------------------------------ 550 static void SAL_CALL defenv_release( uno_Environment * pEnv ) 551 { 552 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 553 if (! ::osl_decrementInterlockedCount( &that->nRef )) 554 { 555 // invoke dispose callback 556 if (pEnv->environmentDisposing) 557 { 558 (*pEnv->environmentDisposing)( pEnv ); 559 } 560 561 OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" ); 562 } 563 // free memory if no weak refs left 564 if (! ::osl_decrementInterlockedCount( &that->nWeakRef )) 565 { 566 delete that; 567 } 568 } 569 570 //------------------------------------------------------------------------------ 571 static void SAL_CALL defenv_acquireWeak( uno_Environment * pEnv ) 572 { 573 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 574 ::osl_incrementInterlockedCount( &that->nWeakRef ); 575 } 576 577 //------------------------------------------------------------------------------ 578 static void SAL_CALL defenv_releaseWeak( uno_Environment * pEnv ) 579 { 580 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 581 if (! ::osl_decrementInterlockedCount( &that->nWeakRef )) 582 { 583 delete that; 584 } 585 } 586 587 //------------------------------------------------------------------------------ 588 static void SAL_CALL defenv_harden( 589 uno_Environment ** ppHardEnv, uno_Environment * pEnv ) 590 { 591 if (*ppHardEnv) 592 { 593 (*(*ppHardEnv)->release)( *ppHardEnv ); 594 *ppHardEnv = 0; 595 } 596 597 EnvironmentsData & rData = theEnvironmentsData::get(); 598 599 if (rData.isDisposing) 600 return; 601 602 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 603 { 604 ::osl::MutexGuard guard( rData.mutex ); 605 if (1 == ::osl_incrementInterlockedCount( &that->nRef )) // is dead 606 { 607 that->nRef = 0; 608 return; 609 } 610 } 611 ::osl_incrementInterlockedCount( &that->nWeakRef ); 612 *ppHardEnv = pEnv; 613 } 614 615 //------------------------------------------------------------------------------ 616 static void SAL_CALL defenv_dispose( uno_Environment * ) 617 { 618 } 619 } 620 621 //______________________________________________________________________________ 622 uno_DefaultEnvironment::uno_DefaultEnvironment( 623 const OUString & rEnvDcp_, void * pContext_ ) 624 : nRef( 0 ), 625 nWeakRef( 0 ) 626 { 627 uno_Environment * that = reinterpret_cast< uno_Environment * >(this); 628 that->pReserved = 0; 629 // functions 630 that->acquire = defenv_acquire; 631 that->release = defenv_release; 632 that->acquireWeak = defenv_acquireWeak; 633 that->releaseWeak = defenv_releaseWeak; 634 that->harden = defenv_harden; 635 that->dispose = defenv_dispose; 636 that->pExtEnv = this; 637 // identifier 638 ::rtl_uString_acquire( rEnvDcp_.pData ); 639 that->pTypeName = rEnvDcp_.pData; 640 that->pContext = pContext_; 641 642 // will be late initialized 643 that->environmentDisposing = 0; 644 645 uno_ExtEnvironment::registerInterface = defenv_registerInterface; 646 uno_ExtEnvironment::registerProxyInterface = defenv_registerProxyInterface; 647 uno_ExtEnvironment::revokeInterface = defenv_revokeInterface; 648 uno_ExtEnvironment::getObjectIdentifier = defenv_getObjectIdentifier; 649 uno_ExtEnvironment::getRegisteredInterface = defenv_getRegisteredInterface; 650 uno_ExtEnvironment::getRegisteredInterfaces = 651 defenv_getRegisteredInterfaces; 652 653 } 654 655 //______________________________________________________________________________ 656 uno_DefaultEnvironment::~uno_DefaultEnvironment() 657 { 658 ::rtl_uString_release( ((uno_Environment *) this)->pTypeName ); 659 } 660 661 //============================================================================== 662 static void writeLine( 663 void * stream, const sal_Char * pLine, const sal_Char * pFilter ) 664 { 665 if (pFilter && *pFilter) 666 { 667 // lookup pFilter in pLine 668 while (*pLine) 669 { 670 if (*pLine == *pFilter) 671 { 672 sal_Int32 nPos = 1; 673 while (pLine[nPos] && pFilter[nPos] == pLine[nPos]) 674 { 675 ++nPos; 676 } 677 if (! pFilter[nPos]) 678 { 679 if (stream) 680 { 681 fprintf( (FILE *) stream, "%s\n", pLine ); 682 } 683 else 684 { 685 OSL_TRACE( pLine ); 686 OSL_TRACE( "\n" ); 687 } 688 } 689 } 690 ++pLine; 691 } 692 } 693 else 694 { 695 if (stream) 696 { 697 fprintf( (FILE *) stream, "%s\n", pLine ); 698 } 699 else 700 { 701 fprintf( stderr, "%s\n", pLine ); 702 } 703 } 704 } 705 706 //============================================================================== 707 static void writeLine( 708 void * stream, const OUString & rLine, const sal_Char * pFilter ) 709 { 710 ::rtl::OString aLine( ::rtl::OUStringToOString( 711 rLine, RTL_TEXTENCODING_ASCII_US ) ); 712 writeLine( stream, aLine.getStr(), pFilter ); 713 } 714 715 //############################################################################## 716 extern "C" void SAL_CALL uno_dumpEnvironment( 717 void * stream, uno_Environment * pEnv, const sal_Char * pFilter ) 718 SAL_THROW_EXTERN_C() 719 { 720 OSL_ENSURE( pEnv, "### null ptr!" ); 721 ::rtl::OUStringBuffer buf; 722 723 if (! pEnv->pExtEnv) 724 { 725 writeLine( stream, "###################################" 726 "###########################################", pFilter ); 727 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment: ") ); 728 buf.append( pEnv->pTypeName ); 729 writeLine( stream, buf.makeStringAndClear(), pFilter ); 730 writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter ); 731 return; 732 } 733 734 writeLine( stream, "########################################" 735 "######################################", pFilter ); 736 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment dump: ") ); 737 buf.append( pEnv->pTypeName ); 738 writeLine( stream, buf.makeStringAndClear(), pFilter ); 739 740 uno_DefaultEnvironment * that = 741 reinterpret_cast< uno_DefaultEnvironment * >(pEnv); 742 ::osl::MutexGuard guard( that->mutex ); 743 744 Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap ); 745 OId2ObjectMap::const_iterator iPos( that->aOId2ObjectMap.begin() ); 746 while (iPos != that->aOId2ObjectMap.end()) 747 { 748 ObjectEntry * pOEntry = iPos->second; 749 750 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("+ ") ); 751 if (pOEntry->mixedObject) 752 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("mixed ") ); 753 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("object entry: nRef=") ); 754 buf.append( pOEntry->nRef, 10 ); 755 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; oid=\"") ); 756 buf.append( pOEntry->oid ); 757 buf.append( (sal_Unicode) '\"' ); 758 writeLine( stream, buf.makeStringAndClear(), pFilter ); 759 760 for ( ::std::size_t nPos = 0; 761 nPos < pOEntry->aInterfaces.size(); ++nPos ) 762 { 763 const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos]; 764 765 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" - ") ); 766 buf.append( 767 ((typelib_TypeDescription *) rIEntry.pTypeDescr)->pTypeName ); 768 if (rIEntry.fpFreeProxy) 769 { 770 buf.appendAscii( 771 RTL_CONSTASCII_STRINGPARAM("; proxy free=0x") ); 772 buf.append( 773 reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 ); 774 } 775 else 776 { 777 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; original") ); 778 } 779 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; ptr=0x") ); 780 buf.append( 781 reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 ); 782 783 if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0) 784 { 785 ::std::size_t erased = ptr2obj.erase( rIEntry.pInterface ); 786 if (erased != 1) 787 { 788 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( 789 " (ptr not found in map!)") ); 790 } 791 } 792 writeLine( stream, buf.makeStringAndClear(), pFilter ); 793 } 794 ++iPos; 795 } 796 if (! ptr2obj.empty()) 797 writeLine( stream, "ptr map inconsistency!!!", pFilter ); 798 writeLine( stream, "#####################################" 799 "#########################################", pFilter ); 800 } 801 802 //############################################################################## 803 extern "C" void SAL_CALL uno_dumpEnvironmentByName( 804 void * stream, rtl_uString * pEnvDcp, const sal_Char * pFilter ) 805 SAL_THROW_EXTERN_C() 806 { 807 uno_Environment * pEnv = 0; 808 uno_getEnvironment( &pEnv, pEnvDcp, 0 ); 809 if (pEnv) 810 { 811 ::uno_dumpEnvironment( stream, pEnv, pFilter ); 812 (*pEnv->release)( pEnv ); 813 } 814 else 815 { 816 ::rtl::OUStringBuffer buf( 32 ); 817 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment \"") ); 818 buf.append( pEnvDcp ); 819 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" does not exist!") ); 820 writeLine( stream, buf.makeStringAndClear(), pFilter ); 821 } 822 } 823 824 //------------------------------------------------------------------------------ 825 inline static const OUString & unoenv_getStaticOIdPart() 826 { 827 static OUString * s_pStaticOidPart = 0; 828 if (! s_pStaticOidPart) 829 { 830 ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() ); 831 if (! s_pStaticOidPart) 832 { 833 ::rtl::OUStringBuffer aRet( 64 ); 834 aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") ); 835 // pid 836 oslProcessInfo info; 837 info.Size = sizeof(oslProcessInfo); 838 if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER, &info ) == 839 osl_Process_E_None) 840 { 841 aRet.append( (sal_Int64)info.Ident, 16 ); 842 } 843 else 844 { 845 aRet.appendAscii( 846 RTL_CONSTASCII_STRINGPARAM("unknown process id") ); 847 } 848 // good guid 849 sal_uInt8 ar[16]; 850 ::rtl_getGlobalProcessId( ar ); 851 aRet.append( (sal_Unicode)';' ); 852 for ( sal_Int32 i = 0; i < 16; ++i ) 853 aRet.append( (sal_Int32)ar[i], 16 ); 854 855 static OUString s_aStaticOidPart( aRet.makeStringAndClear() ); 856 s_pStaticOidPart = &s_aStaticOidPart; 857 } 858 } 859 return *s_pStaticOidPart; 860 } 861 862 extern "C" 863 { 864 865 //------------------------------------------------------------------------------ 866 static void SAL_CALL unoenv_computeObjectIdentifier( 867 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface ) 868 { 869 OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" ); 870 if (*ppOId) 871 { 872 ::rtl_uString_release( *ppOId ); 873 *ppOId = 0; 874 } 875 876 uno_Interface * pUnoI = (uno_Interface *) 877 ::cppu::binuno_queryInterface( 878 pInterface, *typelib_static_type_getByTypeClass( 879 typelib_TypeClass_INTERFACE ) ); 880 if (0 != pUnoI) 881 { 882 (*pUnoI->release)( pUnoI ); 883 // interface 884 ::rtl::OUStringBuffer oid( 64 ); 885 oid.append( reinterpret_cast< sal_Int64 >(pUnoI), 16 ); 886 oid.append( static_cast< sal_Unicode >(';') ); 887 // environment[context] 888 oid.append( ((uno_Environment *) pEnv)->pTypeName ); 889 oid.append( static_cast< sal_Unicode >('[') ); 890 oid.append( reinterpret_cast< sal_Int64 >( 891 reinterpret_cast< 892 uno_Environment * >(pEnv)->pContext ), 16 ); 893 // process;good guid 894 oid.append( unoenv_getStaticOIdPart() ); 895 OUString aStr( oid.makeStringAndClear() ); 896 ::rtl_uString_acquire( *ppOId = aStr.pData ); 897 } 898 } 899 900 //============================================================================== 901 static void SAL_CALL unoenv_acquireInterface( 902 uno_ExtEnvironment *, void * pUnoI_ ) 903 { 904 uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_); 905 (*pUnoI->acquire)( pUnoI ); 906 } 907 908 //============================================================================== 909 static void SAL_CALL unoenv_releaseInterface( 910 uno_ExtEnvironment *, void * pUnoI_ ) 911 { 912 uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_); 913 (*pUnoI->release)( pUnoI ); 914 } 915 } 916 917 //______________________________________________________________________________ 918 EnvironmentsData::~EnvironmentsData() 919 { 920 ::osl::MutexGuard guard( mutex ); 921 isDisposing = true; 922 923 for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() ); 924 iPos != aName2EnvMap.end(); ++iPos ) 925 { 926 uno_Environment * pWeak = iPos->second; 927 uno_Environment * pHard = 0; 928 (*pWeak->harden)( &pHard, pWeak ); 929 (*pWeak->releaseWeak)( pWeak ); 930 931 if (pHard) 932 { 933 #if OSL_DEBUG_LEVEL > 1 934 ::uno_dumpEnvironment( 0, pHard, 0 ); 935 #endif 936 (*pHard->dispose)( pHard ); // send explicit dispose 937 (*pHard->release)( pHard ); 938 } 939 } 940 } 941 942 //______________________________________________________________________________ 943 inline void EnvironmentsData::getEnvironment( 944 uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext ) 945 { 946 if (*ppEnv) 947 { 948 (*(*ppEnv)->release)( *ppEnv ); 949 *ppEnv = 0; 950 } 951 952 OUString aKey( 953 OUString::valueOf( reinterpret_cast< sal_IntPtr >(pContext) ) ); 954 aKey += rEnvDcp; 955 956 // try to find registered mapping 957 OUString2EnvironmentMap::const_iterator const iFind( 958 aName2EnvMap.find( aKey ) ); 959 if (iFind != aName2EnvMap.end()) 960 { 961 uno_Environment * pWeak = iFind->second; 962 (*pWeak->harden)( ppEnv, pWeak ); 963 } 964 } 965 966 //______________________________________________________________________________ 967 inline void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv ) 968 { 969 OSL_ENSURE( ppEnv, "### null ptr!" ); 970 uno_Environment * pEnv = *ppEnv; 971 972 OUString aKey( 973 OUString::valueOf( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) ); 974 aKey += pEnv->pTypeName; 975 976 // try to find registered environment 977 OUString2EnvironmentMap::const_iterator const iFind( 978 aName2EnvMap.find( aKey ) ); 979 if (iFind == aName2EnvMap.end()) 980 { 981 (*pEnv->acquireWeak)( pEnv ); 982 ::std::pair< OUString2EnvironmentMap::iterator, bool > insertion( 983 aName2EnvMap.insert( 984 OUString2EnvironmentMap::value_type( aKey, pEnv ) ) ); 985 OSL_ENSURE( 986 insertion.second, "### insertion of env into map failed?!" ); 987 } 988 else 989 { 990 uno_Environment * pHard = 0; 991 uno_Environment * pWeak = iFind->second; 992 (*pWeak->harden)( &pHard, pWeak ); 993 if (pHard) 994 { 995 if (pEnv) 996 (*pEnv->release)( pEnv ); 997 *ppEnv = pHard; 998 } 999 else // registered one is dead 1000 { 1001 (*pWeak->releaseWeak)( pWeak ); 1002 (*pEnv->acquireWeak)( pEnv ); 1003 aName2EnvMap[ aKey ] = pEnv; 1004 } 1005 } 1006 } 1007 1008 //______________________________________________________________________________ 1009 inline void EnvironmentsData::getRegisteredEnvironments( 1010 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc, 1011 const OUString & rEnvDcp ) 1012 { 1013 OSL_ENSURE( pppEnvs && pnLen && memAlloc, "### null ptr!" ); 1014 1015 // max size 1016 uno_Environment ** ppFound = (uno_Environment **)alloca( 1017 sizeof(uno_Environment *) * aName2EnvMap.size() ); 1018 sal_Int32 nSize = 0; 1019 1020 // find matching environment 1021 for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() ); 1022 iPos != aName2EnvMap.end(); ++iPos ) 1023 { 1024 uno_Environment * pWeak = iPos->second; 1025 if (!rEnvDcp.getLength() || 1026 rEnvDcp.equals( pWeak->pTypeName )) 1027 { 1028 ppFound[nSize] = 0; 1029 (*pWeak->harden)( &ppFound[nSize], pWeak ); 1030 if (ppFound[nSize]) 1031 ++nSize; 1032 } 1033 } 1034 1035 *pnLen = nSize; 1036 if (nSize) 1037 { 1038 *pppEnvs = (uno_Environment **) (*memAlloc)( 1039 sizeof (uno_Environment *) * nSize ); 1040 OSL_ASSERT( *pppEnvs ); 1041 while (nSize--) 1042 { 1043 (*pppEnvs)[nSize] = ppFound[nSize]; 1044 } 1045 } 1046 else 1047 { 1048 *pppEnvs = 0; 1049 } 1050 } 1051 1052 static bool loadEnv(OUString const & cLibStem, 1053 uno_Environment * pEnv, 1054 void * /*pContext*/) 1055 { 1056 // late init with some code from matching uno language binding 1057 // will be unloaded by environment 1058 oslModule hMod = cppu::detail::loadModule( cLibStem ); 1059 1060 if (!hMod) 1061 return false; 1062 1063 OUString aSymbolName(RTL_CONSTASCII_USTRINGPARAM(UNO_INIT_ENVIRONMENT)); 1064 uno_initEnvironmentFunc fpInit = (uno_initEnvironmentFunc) 1065 ::osl_getFunctionSymbol( hMod, aSymbolName.pData ); 1066 if (!fpInit) 1067 { 1068 ::osl_unloadModule( hMod ); 1069 return false; 1070 } 1071 1072 (*fpInit)( pEnv ); // init of environment 1073 ::rtl_registerModuleForUnloading( hMod ); 1074 1075 return true; 1076 } 1077 1078 1079 extern "C" 1080 { 1081 1082 //------------------------------------------------------------------------------ 1083 static uno_Environment * initDefaultEnvironment( 1084 const OUString & rEnvDcp, void * pContext ) 1085 { 1086 uno_Environment * pEnv = &(new uno_DefaultEnvironment( rEnvDcp, pContext ))->aBase; 1087 (*pEnv->acquire)( pEnv ); 1088 1089 OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp); 1090 1091 // create default environment 1092 if (envTypeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) )) 1093 { 1094 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 1095 that->computeObjectIdentifier = unoenv_computeObjectIdentifier; 1096 that->acquireInterface = unoenv_acquireInterface; 1097 that->releaseInterface = unoenv_releaseInterface; 1098 1099 OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp); 1100 if (envPurpose.getLength()) 1101 { 1102 rtl::OUString libStem = envPurpose.copy(envPurpose.lastIndexOf(':') + 1); 1103 libStem += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_uno_uno") ); 1104 1105 if(!loadEnv(libStem, pEnv, pContext)) 1106 { 1107 pEnv->release(pEnv); 1108 return NULL; 1109 } 1110 } 1111 } 1112 else 1113 { 1114 // late init with some code from matching uno language binding 1115 ::rtl::OUStringBuffer aLibName( 16 ); 1116 aLibName.append( envTypeName ); 1117 aLibName.appendAscii( RTL_CONSTASCII_STRINGPARAM("_uno" ) ); 1118 OUString aStr( aLibName.makeStringAndClear() ); 1119 1120 if (!loadEnv(aStr, pEnv, pContext)) 1121 { 1122 pEnv->release(pEnv); 1123 return NULL; 1124 } 1125 } 1126 1127 return pEnv; 1128 } 1129 1130 //############################################################################## 1131 void SAL_CALL uno_createEnvironment( 1132 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext ) 1133 SAL_THROW_EXTERN_C() 1134 { 1135 OSL_ENSURE( ppEnv, "### null ptr!" ); 1136 if (*ppEnv) 1137 (*(*ppEnv)->release)( *ppEnv ); 1138 1139 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp ); 1140 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext ); 1141 } 1142 1143 //############################################################################## 1144 void SAL_CALL uno_direct_getEnvironment( 1145 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext ) 1146 SAL_THROW_EXTERN_C() 1147 { 1148 OSL_ENSURE( ppEnv, "### null ptr!" ); 1149 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp ); 1150 1151 EnvironmentsData & rData = theEnvironmentsData::get(); 1152 1153 ::osl::MutexGuard guard( rData.mutex ); 1154 rData.getEnvironment( ppEnv, rEnvDcp, pContext ); 1155 if (! *ppEnv) 1156 { 1157 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext ); 1158 if (*ppEnv) 1159 { 1160 // register new environment: 1161 rData.registerEnvironment( ppEnv ); 1162 } 1163 } 1164 } 1165 1166 //############################################################################## 1167 void SAL_CALL uno_getRegisteredEnvironments( 1168 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc, 1169 rtl_uString * pEnvDcp ) 1170 SAL_THROW_EXTERN_C() 1171 { 1172 EnvironmentsData & rData = theEnvironmentsData::get(); 1173 1174 ::osl::MutexGuard guard( rData.mutex ); 1175 rData.getRegisteredEnvironments( 1176 pppEnvs, pnLen, memAlloc, 1177 (pEnvDcp ? OUString(pEnvDcp) : OUString()) ); 1178 } 1179 1180 } // extern "C" 1181 1182 } 1183 1184