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_cppuhelper.hxx" 26 27 #include <string.h> 28 #include <vector> 29 30 #include "rtl/process.h" 31 #include "rtl/bootstrap.hxx" 32 #include "rtl/random.h" 33 #include "rtl/string.hxx" 34 #include "rtl/ustrbuf.hxx" 35 #include "rtl/uri.hxx" 36 #if OSL_DEBUG_LEVEL > 0 37 #include "rtl/strbuf.hxx" 38 #endif 39 #include "osl/diagnose.h" 40 #include "osl/file.hxx" 41 #include "osl/module.hxx" 42 #include "osl/security.hxx" 43 #include "osl/thread.hxx" 44 45 #include "cppuhelper/shlib.hxx" 46 #include "cppuhelper/bootstrap.hxx" 47 #include "cppuhelper/component_context.hxx" 48 #include "cppuhelper/access_control.hxx" 49 #include "cppuhelper/findsofficepath.h" 50 51 #include "com/sun/star/container/XElementAccess.hpp" 52 53 #include "com/sun/star/uno/XComponentContext.hpp" 54 #include "com/sun/star/uno/XCurrentContext.hpp" 55 56 #include "com/sun/star/lang/XSingleServiceFactory.hpp" 57 #include "com/sun/star/lang/XSingleComponentFactory.hpp" 58 #include "com/sun/star/lang/XInitialization.hpp" 59 #include "com/sun/star/lang/XServiceInfo.hpp" 60 #include "com/sun/star/registry/XSimpleRegistry.hpp" 61 #include "com/sun/star/container/XSet.hpp" 62 #include "com/sun/star/beans/PropertyValue.hpp" 63 #include "com/sun/star/io/IOException.hpp" 64 #include "com/sun/star/bridge/UnoUrlResolver.hpp" 65 #include "com/sun/star/bridge/XUnoUrlResolver.hpp" 66 67 #include "macro_expander.hxx" 68 69 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 70 #define ARLEN(x) sizeof (x) / sizeof *(x) 71 72 void primeWeakMap( void); // as defined in primeweak.cxx 73 74 using namespace ::rtl; 75 using namespace ::osl; 76 using namespace ::com::sun::star; 77 using namespace ::com::sun::star::uno; 78 79 namespace cppu 80 { 81 82 OUString const & get_this_libpath() 83 { 84 static OUString s_path; 85 if (0 == s_path.getLength()) 86 { 87 OUString path; 88 Module::getUrlFromAddress( reinterpret_cast<oslGenericFunction>(get_this_libpath), path ); 89 path = path.copy( 0, path.lastIndexOf( '/' ) ); 90 MutexGuard guard( Mutex::getGlobalMutex() ); 91 if (0 == s_path.getLength()) 92 s_path = path; 93 } 94 return s_path; 95 } 96 97 Bootstrap const & get_unorc() SAL_THROW( () ) 98 { 99 static rtlBootstrapHandle s_bstrap = 0; 100 if (! s_bstrap) 101 { 102 OUString iniName( 103 get_this_libpath() + OUSTR("/" SAL_CONFIGFILE("uno")) ); 104 rtlBootstrapHandle bstrap = rtl_bootstrap_args_open( iniName.pData ); 105 106 ClearableMutexGuard guard( Mutex::getGlobalMutex() ); 107 if (s_bstrap) 108 { 109 guard.clear(); 110 rtl_bootstrap_args_close( bstrap ); 111 } 112 else 113 { 114 s_bstrap = bstrap; 115 } 116 } 117 return *(Bootstrap const *)&s_bstrap; 118 } 119 120 121 void addFactories( 122 char const * const * ppNames /* lib, implname, ..., 0 */, 123 OUString const & bootstrapPath, 124 Reference< lang::XMultiComponentFactory > const & xMgr, 125 Reference< registry::XRegistryKey > const & xKey ) 126 { 127 Reference< container::XSet > xSet( xMgr, UNO_QUERY ); 128 OSL_ASSERT( xSet.is() ); 129 Reference< lang::XMultiServiceFactory > xSF( xMgr, UNO_QUERY ); 130 131 while (*ppNames) 132 { 133 OUString lib( OUString::createFromAscii( *ppNames++ ) ); 134 OUString implName( OUString::createFromAscii( *ppNames++ ) ); 135 136 Any aFac( makeAny( loadSharedLibComponentFactory( 137 lib, bootstrapPath, implName, xSF, xKey ) ) ); 138 xSet->insert( aFac ); 139 #if OSL_DEBUG_LEVEL > 1 140 if (xSet->has( aFac )) 141 { 142 Reference< lang::XServiceInfo > xInfo; 143 if (aFac >>= xInfo) 144 { 145 ::fprintf( 146 stderr, "> implementation %s supports: ", ppNames[ -1 ] ); 147 Sequence< OUString > supported( 148 xInfo->getSupportedServiceNames() ); 149 for ( sal_Int32 nPos = supported.getLength(); nPos--; ) 150 { 151 OString str( OUStringToOString( 152 supported[ nPos ], RTL_TEXTENCODING_ASCII_US ) ); 153 ::fprintf( stderr, nPos ? "%s, " : "%s\n", str.getStr() ); 154 } 155 } 156 else 157 { 158 ::fprintf( 159 stderr, 160 "> implementation %s provides NO lang::XServiceInfo!!!\n", 161 ppNames[ -1 ] ); 162 } 163 } 164 #endif 165 #if OSL_DEBUG_LEVEL > 0 166 if (! xSet->has( aFac )) 167 { 168 OStringBuffer buf( 64 ); 169 buf.append( "### failed inserting shared lib \"" ); 170 buf.append( ppNames[ -2 ] ); 171 buf.append( "\"!!!" ); 172 OString str( buf.makeStringAndClear() ); 173 OSL_ENSURE( 0, str.getStr() ); 174 } 175 #endif 176 } 177 } 178 179 // private forward decl 180 Reference< lang::XMultiComponentFactory > bootstrapInitialSF( 181 OUString const & rBootstrapPath ); 182 183 Reference< XComponentContext > bootstrapInitialContext( 184 Reference< lang::XMultiComponentFactory > const & xSF, 185 Reference< registry::XSimpleRegistry > const & types_xRegistry, 186 Reference< registry::XSimpleRegistry > const & services_xRegistry, 187 OUString const & rBootstrapPath, Bootstrap const & bootstrap ); 188 189 Reference< XComponentContext > SAL_CALL createInitialCfgComponentContext( 190 ContextEntry_Init const * pEntries, sal_Int32 nEntries, 191 Reference< XComponentContext > const & xDelegate ) 192 SAL_THROW( () ); 193 194 Reference< registry::XSimpleRegistry > SAL_CALL createRegistryWrapper( 195 const Reference< XComponentContext >& xContext ); 196 197 namespace { 198 199 template< class T > 200 inline beans::PropertyValue createPropertyValue( 201 OUString const & name, T const & value ) 202 SAL_THROW( () ) 203 { 204 return beans::PropertyValue( 205 name, -1, makeAny( value ), beans::PropertyState_DIRECT_VALUE ); 206 } 207 208 OUString findBoostrapArgument( 209 const Bootstrap & bootstrap, 210 const OUString & arg_name, 211 sal_Bool * pFallenBack ) 212 SAL_THROW(()) 213 { 214 OUString result; 215 216 OUString prefixed_arg_name = OUSTR("UNO_"); 217 prefixed_arg_name += arg_name.toAsciiUpperCase(); 218 219 // environment not set -> try relative to executable 220 if(!bootstrap.getFrom(prefixed_arg_name, result)) 221 { 222 if(pFallenBack) 223 *pFallenBack = sal_True; 224 225 OUString fileName; 226 bootstrap.getIniName(fileName); 227 228 // cut the rc extension 229 OUStringBuffer result_buf( 64 ); 230 result_buf.append( 231 fileName.copy( 232 0, fileName.getLength() - strlen(SAL_CONFIGFILE(""))) ); 233 result_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("_") ); 234 result_buf.append( arg_name.toAsciiLowerCase() ); 235 result_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(".rdb") ); 236 result = result_buf.makeStringAndClear(); 237 238 #if OSL_DEBUG_LEVEL > 1 239 OString result_dbg = 240 OUStringToOString(result, RTL_TEXTENCODING_ASCII_US); 241 OString arg_name_dbg = 242 OUStringToOString(arg_name, RTL_TEXTENCODING_ASCII_US); 243 OSL_TRACE( 244 "cppuhelper::findBoostrapArgument - " 245 "setting %s relative to executable: %s\n", 246 arg_name_dbg.getStr(), 247 result_dbg.getStr() ); 248 #endif 249 } 250 else 251 { 252 if(pFallenBack) 253 *pFallenBack = sal_False; 254 255 #if OSL_DEBUG_LEVEL > 1 256 OString prefixed_arg_name_dbg = OUStringToOString( 257 prefixed_arg_name, RTL_TEXTENCODING_ASCII_US ); 258 OString result_dbg = OUStringToOString( 259 result, RTL_TEXTENCODING_ASCII_US ); 260 OSL_TRACE( 261 "cppuhelper::findBoostrapArgument - found %s in env: %s", 262 prefixed_arg_name_dbg.getStr(), 263 result_dbg.getStr() ); 264 #endif 265 } 266 267 return result; 268 } 269 270 Reference< registry::XSimpleRegistry > nestRegistries( 271 const OUString baseDir, 272 const Reference< lang::XSingleServiceFactory > & xSimRegFac, 273 const Reference< lang::XSingleServiceFactory > & xNesRegFac, 274 OUString csl_rdbs, 275 const OUString & write_rdb, 276 sal_Bool forceWrite_rdb, 277 sal_Bool bFallenBack ) 278 { 279 sal_Int32 index; 280 Reference< registry::XSimpleRegistry > lastRegistry; 281 282 if(write_rdb.getLength()) // is there a write registry given? 283 { 284 lastRegistry.set(xSimRegFac->createInstance(), UNO_QUERY); 285 286 try 287 { 288 lastRegistry->open(write_rdb, sal_False, forceWrite_rdb); 289 } 290 catch (registry::InvalidRegistryException & invalidRegistryException) 291 { 292 (void) invalidRegistryException; 293 #if OSL_DEBUG_LEVEL > 1 294 OString rdb_name_tmp = OUStringToOString( 295 write_rdb, RTL_TEXTENCODING_ASCII_US); 296 OString message_dbg = OUStringToOString( 297 invalidRegistryException.Message, RTL_TEXTENCODING_ASCII_US); 298 OSL_TRACE( 299 "warning: couldn't open %s cause of %s", 300 rdb_name_tmp.getStr(), message_dbg.getStr() ); 301 #endif 302 } 303 304 if(!lastRegistry->isValid()) 305 lastRegistry.clear(); 306 } 307 308 do 309 { 310 index = csl_rdbs.indexOf((sal_Unicode)' '); 311 OUString rdb_name = (index == -1) ? csl_rdbs : csl_rdbs.copy(0, index); 312 csl_rdbs = (index == -1) ? OUString() : csl_rdbs.copy(index + 1); 313 314 if (! rdb_name.getLength()) 315 continue; 316 317 bool optional = ('?' == rdb_name[ 0 ]); 318 if (optional) 319 rdb_name = rdb_name.copy( 1 ); 320 321 try 322 { 323 Reference<registry::XSimpleRegistry> simpleRegistry( 324 xSimRegFac->createInstance(), UNO_QUERY_THROW ); 325 326 osl::FileBase::getAbsoluteFileURL(baseDir, rdb_name, rdb_name); 327 simpleRegistry->open(rdb_name, sal_True, sal_False); 328 329 if(lastRegistry.is()) 330 { 331 Reference< registry::XSimpleRegistry > nestedRegistry( 332 xNesRegFac->createInstance(), UNO_QUERY ); 333 Reference< lang::XInitialization > nestedRegistry_xInit( 334 nestedRegistry, UNO_QUERY ); 335 336 Sequence<Any> aArgs(2); 337 aArgs[0] <<= lastRegistry; 338 aArgs[1] <<= simpleRegistry; 339 340 nestedRegistry_xInit->initialize(aArgs); 341 342 lastRegistry = nestedRegistry; 343 } 344 else 345 lastRegistry = simpleRegistry; 346 } 347 catch(registry::InvalidRegistryException & invalidRegistryException) 348 { 349 if (! optional) 350 { 351 // if a registry was explicitly given, the exception shall fly 352 if( ! bFallenBack ) 353 throw; 354 } 355 356 (void) invalidRegistryException; 357 #if OSL_DEBUG_LEVEL > 1 358 OString rdb_name_tmp = OUStringToOString( 359 rdb_name, RTL_TEXTENCODING_ASCII_US ); 360 OString message_dbg = OUStringToOString( 361 invalidRegistryException.Message, RTL_TEXTENCODING_ASCII_US ); 362 OSL_TRACE( 363 "warning: couldn't open %s cause of %s", 364 rdb_name_tmp.getStr(), message_dbg.getStr() ); 365 #endif 366 } 367 } 368 while(index != -1 && csl_rdbs.getLength()); // are there more rdbs in list? 369 370 return lastRegistry; 371 } 372 373 Reference< XComponentContext > 374 SAL_CALL defaultBootstrap_InitialComponentContext( 375 Bootstrap const & bootstrap ) 376 { 377 primeWeakMap(); 378 379 OUString bootstrapPath; 380 if (!bootstrap.getFrom( 381 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URE_INTERNAL_LIB_DIR")), 382 bootstrapPath)) 383 { 384 bootstrapPath = get_this_libpath(); 385 } 386 387 OUString iniDir; 388 osl_getProcessWorkingDir(&iniDir.pData); 389 390 Reference<lang::XMultiComponentFactory> smgr_XMultiComponentFactory( 391 bootstrapInitialSF(bootstrapPath) ); 392 Reference<lang::XMultiServiceFactory> smgr_XMultiServiceFactory( 393 smgr_XMultiComponentFactory, UNO_QUERY ); 394 395 Reference<registry::XRegistryKey> xEmptyKey; 396 Reference<lang::XSingleServiceFactory> xSimRegFac( 397 loadSharedLibComponentFactory( 398 OUSTR("bootstrap.uno" SAL_DLLEXTENSION), bootstrapPath, 399 OUSTR("com.sun.star.comp.stoc.SimpleRegistry"), 400 smgr_XMultiServiceFactory, 401 xEmptyKey), 402 UNO_QUERY); 403 404 Reference<lang::XSingleServiceFactory> xNesRegFac( 405 loadSharedLibComponentFactory( 406 OUSTR("bootstrap.uno" SAL_DLLEXTENSION), bootstrapPath, 407 OUSTR("com.sun.star.comp.stoc.NestedRegistry"), 408 smgr_XMultiServiceFactory, 409 xEmptyKey), 410 UNO_QUERY); 411 412 sal_Bool bFallenback_types; 413 OUString cls_uno_types = 414 findBoostrapArgument( bootstrap, OUSTR("TYPES"), &bFallenback_types ); 415 416 Reference<registry::XSimpleRegistry> types_xRegistry = 417 nestRegistries( 418 iniDir, xSimRegFac, xNesRegFac, cls_uno_types, 419 OUString(), sal_False, bFallenback_types ); 420 421 // ==== bootstrap from services registry ==== 422 423 sal_Bool bFallenback_services; 424 OUString cls_uno_services = findBoostrapArgument( 425 bootstrap, OUSTR("SERVICES"), &bFallenback_services ); 426 427 sal_Bool fallenBackWriteRegistry; 428 OUString write_rdb = findBoostrapArgument( 429 bootstrap, OUSTR("WRITERDB"), &fallenBackWriteRegistry ); 430 if (fallenBackWriteRegistry) 431 { 432 // no standard write rdb anymore 433 write_rdb = OUString(); 434 } 435 436 Reference<registry::XSimpleRegistry> services_xRegistry = nestRegistries( 437 iniDir, xSimRegFac, xNesRegFac, cls_uno_services, write_rdb, 438 !fallenBackWriteRegistry, bFallenback_services ); 439 440 Reference< XComponentContext > xContext( 441 bootstrapInitialContext( 442 smgr_XMultiComponentFactory, types_xRegistry, services_xRegistry, 443 bootstrapPath, bootstrap ) ); 444 445 // initialize sf 446 Reference< lang::XInitialization > xInit( 447 smgr_XMultiComponentFactory, UNO_QUERY ); 448 OSL_ASSERT( xInit.is() ); 449 Sequence< Any > aSFInit( 1 ); 450 aSFInit[ 0 ] <<= services_xRegistry; 451 xInit->initialize( aSFInit ); 452 453 return xContext; 454 } 455 456 } 457 458 Reference< XComponentContext > 459 SAL_CALL defaultBootstrap_InitialComponentContext( 460 OUString const & iniFile ) 461 { 462 Bootstrap bootstrap( iniFile ); 463 if (bootstrap.getHandle() == 0) 464 throw io::IOException(OUSTR("Cannot open for reading: ") + iniFile, 0); 465 return defaultBootstrap_InitialComponentContext( bootstrap ); 466 } 467 468 Reference< XComponentContext > 469 SAL_CALL defaultBootstrap_InitialComponentContext() 470 { 471 return defaultBootstrap_InitialComponentContext( get_unorc() ); 472 } 473 474 BootstrapException::BootstrapException() 475 { 476 } 477 478 BootstrapException::BootstrapException( const ::rtl::OUString & rMessage ) 479 :m_aMessage( rMessage ) 480 { 481 } 482 483 BootstrapException::BootstrapException( const BootstrapException & e ) 484 { 485 m_aMessage = e.m_aMessage; 486 } 487 488 BootstrapException::~BootstrapException() 489 { 490 } 491 492 BootstrapException & BootstrapException::operator=( const BootstrapException & e ) 493 { 494 m_aMessage = e.m_aMessage; 495 return *this; 496 } 497 498 const ::rtl::OUString & BootstrapException::getMessage() const 499 { 500 return m_aMessage; 501 } 502 503 Reference< XComponentContext > SAL_CALL bootstrap() 504 { 505 Reference< XComponentContext > xRemoteContext; 506 507 try 508 { 509 char const * p1 = cppuhelper_detail_findSofficePath(); 510 if (p1 == NULL) { 511 throw BootstrapException( 512 OUSTR("no soffice installation found!")); 513 } 514 rtl::OUString p2; 515 if (!rtl_convertStringToUString( 516 &p2.pData, p1, strlen(p1), osl_getThreadTextEncoding(), 517 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR | 518 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR | 519 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))) 520 { 521 throw BootstrapException( 522 OUSTR("bad characters in soffice installation path!")); 523 } 524 OUString path; 525 if (osl::FileBase::getFileURLFromSystemPath(p2, path) != 526 osl::FileBase::E_None) 527 { 528 throw BootstrapException( 529 OUSTR("cannot convert soffice installation path to URL!")); 530 } 531 if (path.getLength() > 0 && path[path.getLength() - 1] != '/') { 532 path += OUSTR("/"); 533 } 534 535 OUString uri; 536 if (!Bootstrap::get(OUSTR("URE_BOOTSTRAP"), uri)) { 537 Bootstrap::set( 538 OUSTR("URE_BOOTSTRAP"), 539 Bootstrap::encode(path + OUSTR(SAL_CONFIGFILE("fundamental")))); 540 } 541 542 // create default local component context 543 Reference< XComponentContext > xLocalContext( 544 defaultBootstrap_InitialComponentContext() ); 545 if ( !xLocalContext.is() ) 546 throw BootstrapException( OUSTR( "no local component context!" ) ); 547 548 // create a random pipe name 549 rtlRandomPool hPool = rtl_random_createPool(); 550 if ( hPool == 0 ) 551 throw BootstrapException( OUSTR( "cannot create random pool!" ) ); 552 sal_uInt8 bytes[ 16 ]; 553 if ( rtl_random_getBytes( hPool, bytes, ARLEN( bytes ) ) 554 != rtl_Random_E_None ) 555 throw BootstrapException( OUSTR( "random pool error!" ) ); 556 rtl_random_destroyPool( hPool ); 557 ::rtl::OUStringBuffer buf; 558 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "uno" ) ); 559 for ( sal_uInt32 i = 0; i < ARLEN( bytes ); ++i ) 560 buf.append( static_cast< sal_Int32 >( bytes[ i ] ) ); 561 OUString sPipeName( buf.makeStringAndClear() ); 562 563 // accept string 564 OSL_ASSERT( buf.getLength() == 0 ); 565 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "-accept=pipe,name=" ) ); 566 buf.append( sPipeName ); 567 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ";urp;" ) ); 568 569 // arguments 570 OUString args [] = { 571 OUSTR( "-nologo" ), 572 OUSTR( "-nodefault" ), 573 OUSTR( "-norestore" ), 574 OUSTR( "-nocrashreport" ), 575 OUSTR( "-nolockcheck" ), 576 buf.makeStringAndClear() 577 }; 578 rtl_uString * ar_args [] = { 579 args[ 0 ].pData, 580 args[ 1 ].pData, 581 args[ 2 ].pData, 582 args[ 3 ].pData, 583 args[ 4 ].pData, 584 args[ 5 ].pData 585 }; 586 ::osl::Security sec; 587 588 // start office process 589 oslProcess hProcess = 0; 590 oslProcessError rc = osl_executeProcess( 591 (path + OUSTR("soffice")).pData, ar_args, ARLEN( ar_args ), 592 osl_Process_DETACHED, 593 sec.getHandle(), 594 0, // => current working dir 595 0, 0, // => no env vars 596 &hProcess ); 597 switch ( rc ) 598 { 599 case osl_Process_E_None: 600 osl_freeProcessHandle( hProcess ); 601 break; 602 case osl_Process_E_NotFound: 603 throw BootstrapException( OUSTR( "image not found!" ) ); 604 case osl_Process_E_TimedOut: 605 throw BootstrapException( OUSTR( "timeout occurred!" ) ); 606 case osl_Process_E_NoPermission: 607 throw BootstrapException( OUSTR( "permission denied!" ) ); 608 case osl_Process_E_Unknown: 609 throw BootstrapException( OUSTR( "unknown error!" ) ); 610 case osl_Process_E_InvalidError: 611 default: 612 throw BootstrapException( OUSTR( "unmapped error!" ) ); 613 } 614 615 // create a URL resolver 616 Reference< bridge::XUnoUrlResolver > xUrlResolver( 617 bridge::UnoUrlResolver::create( xLocalContext ) ); 618 619 // connection string 620 OSL_ASSERT( buf.getLength() == 0 ); 621 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "uno:pipe,name=" ) ); 622 buf.append( sPipeName ); 623 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( 624 ";urp;StarOffice.ComponentContext" ) ); 625 OUString sConnectString( buf.makeStringAndClear() ); 626 627 // wait until office is started 628 for ( ; ; ) 629 { 630 try 631 { 632 // try to connect to office 633 xRemoteContext.set( 634 xUrlResolver->resolve( sConnectString ), UNO_QUERY_THROW ); 635 break; 636 } 637 catch ( connection::NoConnectException & ) 638 { 639 // wait 500 ms, then try to connect again 640 TimeValue tv = { 0 /* secs */, 500000000 /* nanosecs */ }; 641 ::osl::Thread::wait( tv ); 642 } 643 } 644 } 645 catch ( Exception & e ) 646 { 647 throw BootstrapException( 648 OUSTR( "unexpected UNO exception caught: " ) + e.Message ); 649 } 650 651 return xRemoteContext; 652 } 653 654 OUString bootstrap_expandUri(OUString const & uri) { 655 static char const PREFIX[] = "vnd.sun.star.expand:"; 656 return uri.matchAsciiL(RTL_CONSTASCII_STRINGPARAM(PREFIX)) 657 ? cppuhelper::detail::expandMacros( 658 rtl::Uri::decode( 659 uri.copy(RTL_CONSTASCII_LENGTH(PREFIX)), 660 rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8)) 661 : uri; 662 } 663 664 } // namespace cppu 665