1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_extensions.hxx" 30 #include "ole2uno.hxx" 31 #include "rtl/ustrbuf.hxx" 32 33 34 #include "osl/diagnose.h" 35 #include "osl/doublecheckedlocking.h" 36 #include "osl/thread.h" 37 38 #include "boost/scoped_array.hpp" 39 #include <com/sun/star/script/FailReason.hpp> 40 #include <com/sun/star/beans/XMaterialHolder.hpp> 41 #include <com/sun/star/script/XTypeConverter.hpp> 42 #include <com/sun/star/script/FinishEngineEvent.hpp> 43 #include <com/sun/star/script/InterruptReason.hpp> 44 #include <com/sun/star/script/XEngineListener.hpp> 45 #include <com/sun/star/script/XDebugging.hpp> 46 #include <com/sun/star/script/XInvocation.hpp> 47 #include <com/sun/star/script/ContextInformation.hpp> 48 #include <com/sun/star/script/FinishReason.hpp> 49 #include <com/sun/star/script/XEngine.hpp> 50 #include <com/sun/star/script/InterruptEngineEvent.hpp> 51 #include <com/sun/star/script/XLibraryAccess.hpp> 52 #include <com/sun/star/bridge/ModelDependent.hpp> 53 54 #include "com/sun/star/bridge/oleautomation/NamedArgument.hpp" 55 #include "com/sun/star/bridge/oleautomation/PropertyPutArgument.hpp" 56 57 #include <typelib/typedescription.hxx> 58 #include <rtl/uuid.h> 59 #include <rtl/memory.h> 60 #include <rtl/ustring.hxx> 61 62 #include "jscriptclasses.hxx" 63 64 #include "oleobjw.hxx" 65 #include "unoobjw.hxx" 66 #include <stdio.h> 67 using namespace std; 68 using namespace boost; 69 using namespace osl; 70 using namespace rtl; 71 using namespace cppu; 72 using namespace com::sun::star::script; 73 using namespace com::sun::star::lang; 74 using namespace com::sun::star::bridge; 75 using namespace com::sun::star::bridge::oleautomation; 76 using namespace com::sun::star::bridge::ModelDependent; 77 using namespace ::com::sun::star; 78 79 #define JSCRIPT_ID_PROPERTY L"_environment" 80 #define JSCRIPT_ID L"jscript" 81 namespace ole_adapter 82 { 83 84 85 // key: XInterface pointer created by Invocation Adapter Factory 86 // value: XInterface pointer to the wrapper class. 87 // Entries to the map are made within 88 // Any createOleObjectWrapper(IUnknown* pUnknown, const Type& aType); 89 // Entries are being deleted if the wrapper class's destructor has been 90 // called. 91 // Before UNO object is wrapped to COM object this map is checked 92 // to see if the UNO object is already a wrapper. 93 hash_map<sal_uInt32, sal_uInt32> AdapterToWrapperMap; 94 // key: XInterface of the wrapper object. 95 // value: XInterface of the Interface created by the Invocation Adapter Factory. 96 // A COM wrapper is responsible for removing the corresponding entry 97 // in AdapterToWrappperMap if it is being destroyed. Because the wrapper does not 98 // know about its adapted interface it uses WrapperToAdapterMap to get the 99 // adapted interface which is then used to locate the entry in AdapterToWrapperMap. 100 hash_map<sal_uInt32,sal_uInt32> WrapperToAdapterMap; 101 102 hash_map<sal_uInt32, WeakReference<XInterface> > ComPtrToWrapperMap; 103 /***************************************************************************** 104 105 class implementation IUnknownWrapper_Impl 106 107 *****************************************************************************/ 108 109 IUnknownWrapper_Impl::IUnknownWrapper_Impl( Reference<XMultiServiceFactory>& xFactory, 110 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass): 111 UnoConversionUtilities<IUnknownWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass), 112 m_pxIdlClass( NULL), m_eJScript( JScriptUndefined), 113 m_bComTlbIndexInit(false), m_bHasDfltMethod(false), m_bHasDfltProperty(false) 114 { 115 } 116 117 118 IUnknownWrapper_Impl::~IUnknownWrapper_Impl() 119 { 120 o2u_attachCurrentThread(); 121 MutexGuard guard(getBridgeMutex()); 122 XInterface * xIntRoot = (OWeakObject *)this; 123 #if OSL_DEBUG_LEVEL > 0 124 acquire(); // make sure we don't delete us twice because of Reference 125 OSL_ASSERT( Reference<XInterface>( static_cast<XWeak*>(this), UNO_QUERY).get() == xIntRoot ); 126 #endif 127 128 // remove entries in global maps 129 typedef hash_map<sal_uInt32, sal_uInt32>::iterator _IT; 130 _IT it= WrapperToAdapterMap.find( (sal_uInt32) xIntRoot); 131 if( it != WrapperToAdapterMap.end()) 132 { 133 sal_uInt32 adapter= it->second; 134 135 AdapterToWrapperMap.erase( adapter); 136 WrapperToAdapterMap.erase( it); 137 } 138 139 IT_Com it_c= ComPtrToWrapperMap.find( (sal_uInt32) m_spUnknown.p); 140 if(it_c != ComPtrToWrapperMap.end()) 141 ComPtrToWrapperMap.erase(it_c); 142 143 #if OSL_DEBUG_LEVEL > 0 144 fprintf(stderr,"[automation bridge] ComPtrToWrapperMap contains: %i \n", 145 ComPtrToWrapperMap.size()); 146 #endif 147 } 148 149 Any IUnknownWrapper_Impl::queryInterface(const Type& t) 150 throw (RuntimeException) 151 { 152 if (t == getCppuType(static_cast<Reference<XDefaultMethod>*>( 0)) && !m_bHasDfltMethod ) 153 return Any(); 154 if (t == getCppuType(static_cast<Reference<XDefaultProperty>*>( 0)) && !m_bHasDfltProperty ) 155 return Any(); 156 if (t == getCppuType(static_cast<Reference<XInvocation>*>( 0)) && !m_spDispatch) 157 return Any(); 158 159 return WeakImplHelper7<XInvocation, XBridgeSupplier2, 160 XInitialization, XAutomationObject, XDefaultProperty, XDefaultMethod, XDirectInvocation>::queryInterface(t); 161 } 162 163 Reference<XIntrospectionAccess> SAL_CALL IUnknownWrapper_Impl::getIntrospection(void) 164 throw (RuntimeException ) 165 { 166 Reference<XIntrospectionAccess> ret; 167 168 return ret; 169 } 170 171 172 173 Any SAL_CALL IUnknownWrapper_Impl::invoke( const OUString& aFunctionName, 174 const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex, 175 Sequence< Any >& aOutParam ) 176 throw(IllegalArgumentException, CannotConvertException, InvocationTargetException, 177 RuntimeException) 178 { 179 if ( ! m_spDispatch ) 180 { 181 throw RuntimeException( 182 OUSTR("[automation bridge] The object does not have an IDispatch interface"), 183 Reference<XInterface>()); 184 } 185 186 Any ret; 187 188 try 189 { 190 o2u_attachCurrentThread(); 191 192 TypeDescription methodDesc; 193 getMethodInfo(aFunctionName, methodDesc); 194 if( methodDesc.is()) 195 { 196 ret = invokeWithDispIdUnoTlb(aFunctionName, 197 aParams, 198 aOutParamIndex, 199 aOutParam); 200 } 201 else 202 { 203 ret= invokeWithDispIdComTlb( aFunctionName, 204 aParams, 205 aOutParamIndex, 206 aOutParam); 207 } 208 } 209 catch (IllegalArgumentException &) 210 { 211 throw; 212 } 213 catch (CannotConvertException &) 214 { 215 throw; 216 } 217 catch (BridgeRuntimeError & e) 218 { 219 throw RuntimeException(e.message, Reference<XInterface>()); 220 } 221 catch (Exception & e) 222 { 223 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " 224 "IUnknownWrapper_Impl::invoke ! Message : \n") + 225 e.Message, Reference<XInterface>()); 226 227 } 228 catch(...) 229 { 230 throw RuntimeException( 231 OUSTR("[automation bridge] unexpected exception in " 232 "IUnknownWrapper_Impl::Invoke !"), Reference<XInterface>()); 233 } 234 return ret; 235 } 236 237 void SAL_CALL IUnknownWrapper_Impl::setValue( const OUString& aPropertyName, 238 const Any& aValue ) 239 throw(UnknownPropertyException, CannotConvertException, InvocationTargetException, 240 RuntimeException) 241 { 242 if ( ! m_spDispatch ) 243 { 244 throw RuntimeException( 245 OUSTR("[automation bridge] The object does not have an IDispatch interface"), 246 Reference<XInterface>()); 247 } 248 try 249 { 250 o2u_attachCurrentThread(); 251 252 ITypeInfo * pInfo = getTypeInfo(); 253 FuncDesc aDescGet(pInfo); 254 FuncDesc aDescPut(pInfo); 255 VarDesc aVarDesc(pInfo); 256 getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc); 257 //check if there is such a property at all or if it is read only 258 if ( ! aDescPut && ! aDescGet && ! aVarDesc) 259 { 260 OUString msg(OUSTR("[automation bridge]Property \"") + aPropertyName + 261 OUSTR("\" is not supported")); 262 throw UnknownPropertyException(msg, Reference<XInterface>()); 263 } 264 265 if ( (! aDescPut && aDescGet) || aVarDesc 266 && aVarDesc->wVarFlags == VARFLAG_FREADONLY ) 267 { 268 //read-only 269 OUString msg(OUSTR("[automation bridge] Property ") + aPropertyName + 270 OUSTR(" is read-only")); 271 OString sMsg = OUStringToOString(msg, osl_getThreadTextEncoding()); 272 OSL_ENSURE(0, sMsg.getStr()); 273 // ignore silently 274 return; 275 } 276 277 HRESULT hr= S_OK; 278 DISPPARAMS dispparams; 279 CComVariant varArg; 280 CComVariant varRefArg; 281 CComVariant varResult; 282 ExcepInfo excepinfo; 283 unsigned int uArgErr; 284 285 // converting UNO value to OLE variant 286 DISPID dispidPut= DISPID_PROPERTYPUT; 287 dispparams.rgdispidNamedArgs = &dispidPut; 288 dispparams.cArgs = 1; 289 dispparams.cNamedArgs = 1; 290 dispparams.rgvarg = & varArg; 291 292 OSL_ASSERT(aDescPut || aVarDesc); 293 294 VARTYPE vt = 0; 295 DISPID dispid = 0; 296 INVOKEKIND invkind = INVOKE_PROPERTYPUT; 297 //determine the expected type, dispid, invoke kind (DISPATCH_PROPERTYPUT, 298 //DISPATCH_PROPERTYPUTREF) 299 if (aDescPut) 300 { 301 vt = getElementTypeDesc(& aDescPut->lprgelemdescParam[0].tdesc); 302 dispid = aDescPut->memid; 303 invkind = aDescPut->invkind; 304 } 305 else 306 { 307 vt = getElementTypeDesc( & aVarDesc->elemdescVar.tdesc); 308 dispid = aVarDesc->memid; 309 if (vt == VT_UNKNOWN || vt == VT_DISPATCH || 310 (vt & VT_ARRAY) || (vt & VT_BYREF)) 311 { 312 invkind = INVOKE_PROPERTYPUTREF; 313 } 314 } 315 316 // convert the uno argument 317 if (vt & VT_BYREF) 318 { 319 anyToVariant( & varRefArg, aValue, ::sal::static_int_cast< VARTYPE, int >( vt ^ VT_BYREF ) ); 320 varArg.vt = vt; 321 if( (vt & VT_TYPEMASK) == VT_VARIANT) 322 varArg.byref = & varRefArg; 323 else if ((vt & VT_TYPEMASK) == VT_DECIMAL) 324 varArg.byref = & varRefArg.decVal; 325 else 326 varArg.byref = & varRefArg.byref; 327 } 328 else 329 { 330 anyToVariant(& varArg, aValue, vt); 331 } 332 // call to IDispatch 333 hr = m_spDispatch->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, ::sal::static_int_cast< WORD, INVOKEKIND >( invkind ), 334 &dispparams, & varResult, & excepinfo, &uArgErr); 335 336 // lookup error code 337 switch (hr) 338 { 339 case S_OK: 340 break; 341 case DISP_E_BADPARAMCOUNT: 342 throw RuntimeException(); 343 break; 344 case DISP_E_BADVARTYPE: 345 throw RuntimeException(); 346 break; 347 case DISP_E_EXCEPTION: 348 throw InvocationTargetException(); 349 break; 350 case DISP_E_MEMBERNOTFOUND: 351 throw UnknownPropertyException(); 352 break; 353 case DISP_E_NONAMEDARGS: 354 throw RuntimeException(); 355 break; 356 case DISP_E_OVERFLOW: 357 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( 358 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr); 359 break; 360 case DISP_E_PARAMNOTFOUND: 361 throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( 362 static_cast<XWeak*>(this)), ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )) ; 363 break; 364 case DISP_E_TYPEMISMATCH: 365 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( 366 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::UNKNOWN, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); 367 break; 368 case DISP_E_UNKNOWNINTERFACE: 369 throw RuntimeException(); 370 break; 371 case DISP_E_UNKNOWNLCID: 372 throw RuntimeException(); 373 break; 374 case DISP_E_PARAMNOTOPTIONAL: 375 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface*>( 376 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr); 377 break; 378 default: 379 throw RuntimeException(); 380 break; 381 } 382 } 383 catch (CannotConvertException &) 384 { 385 throw; 386 } 387 catch (UnknownPropertyException &) 388 { 389 throw; 390 } 391 catch (BridgeRuntimeError& e) 392 { 393 throw RuntimeException( 394 e.message, Reference<XInterface>()); 395 } 396 catch (Exception & e) 397 { 398 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " 399 "IUnknownWrapper_Impl::setValue ! Message : \n") + 400 e.Message, Reference<XInterface>()); 401 402 } 403 catch (...) 404 { 405 throw RuntimeException( 406 OUSTR("[automation bridge] unexpected exception in " 407 "IUnknownWrapper_Impl::setValue !"), Reference<XInterface>()); 408 } 409 } 410 411 Any SAL_CALL IUnknownWrapper_Impl::getValue( const OUString& aPropertyName ) 412 throw(UnknownPropertyException, RuntimeException) 413 { 414 if ( ! m_spDispatch ) 415 { 416 throw RuntimeException( 417 OUSTR("[automation bridge] The object does not have an IDispatch interface"), 418 Reference<XInterface>()); 419 } 420 Any ret; 421 try 422 { 423 o2u_attachCurrentThread(); 424 ITypeInfo * pInfo = getTypeInfo(); 425 // I was going to implement an XServiceInfo interface to allow the type 426 // of the automation object to be exposed.. but it seems 427 // from looking at comments in the code that it is possible for 428 // this object to actually wrap an UNO object ( I guess if automation is 429 // used from MSO to create Openoffice objects ) Therefore, those objects 430 // will more than likely already have their own XServiceInfo interface. 431 // Instead here I chose a name that should be illegal both in COM and 432 // UNO ( from an IDL point of view ) therefore I think this is a safe 433 // hack 434 if ( aPropertyName.equals( rtl::OUString::createFromAscii("$GetTypeName") )) 435 { 436 if ( pInfo && m_sTypeName.getLength() == 0 ) 437 { 438 m_sTypeName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("IDispatch") ); 439 CComBSTR sName; 440 441 if ( SUCCEEDED( pInfo->GetDocumentation( -1, &sName, NULL, NULL, NULL ) ) ) 442 { 443 rtl::OUString sTmp( reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName))); 444 if ( sTmp.indexOf('_') == 0 ) 445 sTmp = sTmp.copy(1); 446 // do we own the memory for pTypeLib, msdn doco is vague 447 // I'll assume we do 448 CComPtr< ITypeLib > pTypeLib; 449 unsigned int index; 450 if ( SUCCEEDED( pInfo->GetContainingTypeLib( &pTypeLib.p, &index )) ) 451 { 452 if ( SUCCEEDED( pTypeLib->GetDocumentation( -1, &sName, NULL, NULL, NULL ) ) ) 453 { 454 rtl::OUString sLibName( reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName))); 455 m_sTypeName = sLibName.concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".") ) ).concat( sTmp ); 456 457 } 458 } 459 } 460 461 } 462 ret <<= m_sTypeName; 463 return ret; 464 } 465 FuncDesc aDescGet(pInfo); 466 FuncDesc aDescPut(pInfo); 467 VarDesc aVarDesc(pInfo); 468 getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc); 469 if ( ! aDescGet && ! aDescPut && ! aVarDesc) 470 { 471 //property not found 472 OUString msg(OUSTR("[automation bridge]Property \"") + aPropertyName + 473 OUSTR("\" is not supported")); 474 throw UnknownPropertyException(msg, Reference<XInterface>()); 475 } 476 // write-only should not be possible 477 OSL_ASSERT( aDescGet || ! aDescPut); 478 479 HRESULT hr; 480 DISPPARAMS dispparams = {0, 0, 0, 0}; 481 CComVariant varResult; 482 ExcepInfo excepinfo; 483 unsigned int uArgErr; 484 DISPID dispid; 485 if (aDescGet) 486 dispid = aDescGet->memid; 487 else if (aVarDesc) 488 dispid = aVarDesc->memid; 489 else 490 dispid = aDescPut->memid; 491 492 hr = m_spDispatch->Invoke(dispid, 493 IID_NULL, 494 LOCALE_USER_DEFAULT, 495 DISPATCH_PROPERTYGET, 496 &dispparams, 497 &varResult, 498 &excepinfo, 499 &uArgErr); 500 501 // converting return value and out parameter back to UNO 502 if (hr == S_OK) 503 { 504 // If the com object implements uno interfaces then we have 505 // to convert the attribute into the expected type. 506 TypeDescription attrInfo; 507 getAttributeInfo(aPropertyName, attrInfo); 508 if( attrInfo.is() ) 509 variantToAny( &varResult, ret, Type( attrInfo.get()->pWeakRef)); 510 else 511 variantToAny(&varResult, ret); 512 } 513 514 // lookup error code 515 switch (hr) 516 { 517 case S_OK: 518 break; 519 case DISP_E_BADPARAMCOUNT: 520 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 521 Reference<XInterface>()); 522 break; 523 case DISP_E_BADVARTYPE: 524 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 525 Reference<XInterface>()); 526 break; 527 case DISP_E_EXCEPTION: 528 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 529 Reference<XInterface>()); 530 break; 531 case DISP_E_MEMBERNOTFOUND: 532 throw UnknownPropertyException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 533 Reference<XInterface>()); 534 break; 535 case DISP_E_NONAMEDARGS: 536 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 537 Reference<XInterface>()); 538 break; 539 case DISP_E_OVERFLOW: 540 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 541 Reference<XInterface>()); 542 break; 543 case DISP_E_PARAMNOTFOUND: 544 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 545 Reference<XInterface>()); 546 break; 547 case DISP_E_TYPEMISMATCH: 548 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 549 Reference<XInterface>()); 550 break; 551 case DISP_E_UNKNOWNINTERFACE: 552 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 553 Reference<XInterface>()); 554 break; 555 case DISP_E_UNKNOWNLCID: 556 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 557 Reference<XInterface>()); 558 break; 559 case DISP_E_PARAMNOTOPTIONAL: 560 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 561 Reference<XInterface>()); 562 break; 563 default: 564 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), 565 Reference<XInterface>()); 566 break; 567 } 568 } 569 catch (UnknownPropertyException& ) 570 { 571 throw; 572 } 573 catch (BridgeRuntimeError& e) 574 { 575 throw RuntimeException( 576 e.message, Reference<XInterface>()); 577 } 578 catch (Exception & e) 579 { 580 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " 581 "IUnknownWrapper_Impl::getValue ! Message : \n") + 582 e.Message, Reference<XInterface>()); 583 } 584 catch (...) 585 { 586 throw RuntimeException( 587 OUSTR("[automation bridge] unexpected exception in " 588 "IUnknownWrapper_Impl::getValue !"), Reference<XInterface>()); 589 } 590 return ret; 591 } 592 593 sal_Bool SAL_CALL IUnknownWrapper_Impl::hasMethod( const OUString& aName ) 594 throw(RuntimeException) 595 { 596 if ( ! m_spDispatch ) 597 { 598 throw RuntimeException( 599 OUSTR("[automation bridge] The object does not have an IDispatch interface"), 600 Reference<XInterface>()); 601 } 602 sal_Bool ret = sal_False; 603 604 try 605 { 606 o2u_attachCurrentThread(); 607 ITypeInfo* pInfo = getTypeInfo(); 608 FuncDesc aDesc(pInfo); 609 getFuncDesc(aName, & aDesc); 610 // Automation properties can have arguments. Those are treated as methods and 611 //are called through XInvocation::invoke. 612 if ( ! aDesc) 613 { 614 FuncDesc aDescGet(pInfo); 615 FuncDesc aDescPut(pInfo); 616 VarDesc aVarDesc(pInfo); 617 getPropDesc( aName, & aDescGet, & aDescPut, & aVarDesc); 618 if (aDescGet && aDescGet->cParams > 0 619 || aDescPut && aDescPut->cParams > 0) 620 ret = sal_True; 621 } 622 else 623 ret = sal_True; 624 } 625 catch (BridgeRuntimeError& e) 626 { 627 throw RuntimeException(e.message, Reference<XInterface>()); 628 } 629 catch (Exception & e) 630 { 631 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " 632 "IUnknownWrapper_Impl::hasMethod ! Message : \n") + 633 e.Message, Reference<XInterface>()); 634 } 635 catch (...) 636 { 637 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " 638 "IUnknownWrapper_Impl::hasMethod !"), Reference<XInterface>());; 639 } 640 return ret; 641 } 642 643 sal_Bool SAL_CALL IUnknownWrapper_Impl::hasProperty( const OUString& aName ) 644 throw(RuntimeException) 645 { 646 if ( ! m_spDispatch ) 647 { 648 throw RuntimeException(OUSTR("[automation bridge] The object does not have an " 649 "IDispatch interface"), Reference<XInterface>()); 650 return sal_False; 651 } 652 sal_Bool ret = sal_False; 653 try 654 { 655 o2u_attachCurrentThread(); 656 657 ITypeInfo * pInfo = getTypeInfo(); 658 FuncDesc aDescGet(pInfo); 659 FuncDesc aDescPut(pInfo); 660 VarDesc aVarDesc(pInfo); 661 getPropDesc(aName, & aDescGet, & aDescPut, & aVarDesc); 662 // Automation properties can have parameters. If so, we access them through 663 // XInvocation::invoke. Thas is, hasProperty must return false for such a 664 // property 665 if (aVarDesc 666 || aDescPut && aDescPut->cParams == 0 667 || aDescGet && aDescGet->cParams == 0) 668 { 669 ret = sal_True; 670 } 671 } 672 catch (BridgeRuntimeError& e) 673 { 674 throw RuntimeException(e.message, Reference<XInterface>()); 675 } 676 catch (Exception & e) 677 { 678 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " 679 "IUnknownWrapper_Impl::hasProperty ! Message : \n") + 680 e.Message, Reference<XInterface>()); 681 682 } 683 catch (...) 684 { 685 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " 686 "IUnknownWrapper_Impl::hasProperty !"), Reference<XInterface>()); 687 } 688 return ret; 689 } 690 691 Any SAL_CALL IUnknownWrapper_Impl::createBridge( const Any& modelDepObject, 692 const Sequence< sal_Int8 >& /*aProcessId*/, sal_Int16 sourceModelType, 693 sal_Int16 destModelType ) 694 throw( IllegalArgumentException, RuntimeException) 695 { 696 Any ret; 697 o2u_attachCurrentThread(); 698 699 if ( 700 (sourceModelType == UNO) && 701 (destModelType == OLE) && 702 (modelDepObject.getValueTypeClass() == TypeClass_INTERFACE) 703 ) 704 { 705 Reference<XInterface> xInt( *(XInterface**) modelDepObject.getValue()); 706 Reference<XInterface> xSelf( (OWeakObject*)this); 707 708 if (xInt == xSelf) 709 { 710 VARIANT* pVariant = (VARIANT*) CoTaskMemAlloc(sizeof(VARIANT)); 711 712 VariantInit(pVariant); 713 if (m_bOriginalDispatch == sal_True) 714 { 715 pVariant->vt = VT_DISPATCH; 716 pVariant->pdispVal = m_spDispatch; 717 pVariant->pdispVal->AddRef(); 718 } 719 else 720 { 721 pVariant->vt = VT_UNKNOWN; 722 pVariant->punkVal = m_spUnknown; 723 pVariant->punkVal->AddRef(); 724 } 725 726 ret.setValue((void*)&pVariant, getCppuType( (sal_uInt32*) 0)); 727 } 728 } 729 730 return ret; 731 } 732 /** @internal 733 @exception IllegalArgumentException 734 @exception CannotConvertException 735 @exception InvocationTargetException 736 @RuntimeException 737 */ 738 Any IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString& sFunctionName, 739 const Sequence< Any >& Params, 740 Sequence< sal_Int16 >& OutParamIndex, 741 Sequence< Any >& OutParam) 742 { 743 Any ret; 744 HRESULT hr= S_OK; 745 746 sal_Int32 parameterCount= Params.getLength(); 747 sal_Int32 outParameterCount= 0; 748 typelib_InterfaceMethodTypeDescription* pMethod= NULL; 749 TypeDescription methodDesc; 750 getMethodInfo(sFunctionName, methodDesc); 751 752 // We need to know whether the IDispatch is from a JScript object. 753 // Then out and in/out parameters have to be treated differently than 754 // with common COM objects. 755 sal_Bool bJScriptObject= isJScriptObject(); 756 scoped_array<CComVariant> sarParams; 757 scoped_array<CComVariant> sarParamsRef; 758 CComVariant *pVarParams= NULL; 759 CComVariant *pVarParamsRef= NULL; 760 sal_Bool bConvRet= sal_True; 761 762 if( methodDesc.is()) 763 { 764 pMethod = (typelib_InterfaceMethodTypeDescription* )methodDesc.get(); 765 parameterCount = pMethod->nParams; 766 // Create the Array for the array being passed in DISPPARAMS 767 // the array also contains the outparameter (but not the values) 768 if( pMethod->nParams > 0) 769 { 770 sarParams.reset(new CComVariant[ parameterCount]); 771 pVarParams = sarParams.get(); 772 } 773 774 // Create the Array for the out an in/out parameter. These values 775 // are referenced by the VT_BYREF VARIANTs in DISPPARAMS. 776 // We need to find out the number of out and in/out parameter. 777 for( sal_Int32 i=0; i < parameterCount; i++) 778 { 779 if( pMethod->pParams[i].bOut) 780 outParameterCount++; 781 } 782 783 if( !bJScriptObject) 784 { 785 sarParamsRef.reset(new CComVariant[outParameterCount]); 786 pVarParamsRef = sarParamsRef.get(); 787 // build up the parameters for IDispatch::Invoke 788 sal_Int32 outParamIndex=0; 789 int i = 0; 790 try 791 { 792 for( i= 0; i < parameterCount; i++) 793 { 794 // In parameter 795 if( pMethod->pParams[i].bIn == sal_True && ! pMethod->pParams[i].bOut) 796 { 797 anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]); 798 } 799 // Out parameter + in/out parameter 800 else if( pMethod->pParams[i].bOut == sal_True) 801 { 802 CComVariant var; 803 if(pMethod->pParams[i].bIn) 804 { 805 anyToVariant( & var,Params[i]); 806 pVarParamsRef[outParamIndex] = var; 807 } 808 809 switch( pMethod->pParams[i].pTypeRef->eTypeClass) 810 { 811 case TypeClass_INTERFACE: 812 case TypeClass_STRUCT: 813 if( ! pMethod->pParams[i].bIn) 814 { 815 pVarParamsRef[ outParamIndex].vt= VT_DISPATCH; 816 pVarParamsRef[ outParamIndex].pdispVal= 0; 817 } 818 pVarParams[parameterCount - i -1].vt = VT_DISPATCH | VT_BYREF; 819 pVarParams[parameterCount - i -1].ppdispVal= &pVarParamsRef[outParamIndex].pdispVal; 820 break; 821 case TypeClass_ENUM: 822 case TypeClass_LONG: 823 case TypeClass_UNSIGNED_LONG: 824 if( ! pMethod->pParams[i].bIn) 825 { 826 pVarParamsRef[ outParamIndex].vt = VT_I4; 827 pVarParamsRef[ outParamIndex].lVal = 0; 828 } 829 pVarParams[parameterCount - i -1].vt = VT_I4 | VT_BYREF; 830 pVarParams[parameterCount - i -1].plVal= &pVarParamsRef[outParamIndex].lVal; 831 break; 832 case TypeClass_SEQUENCE: 833 if( ! pMethod->pParams[i].bIn) 834 { 835 pVarParamsRef[ outParamIndex].vt = VT_ARRAY| VT_VARIANT; 836 pVarParamsRef[ outParamIndex].parray= NULL; 837 } 838 pVarParams[parameterCount - i -1].vt = VT_ARRAY| VT_BYREF | VT_VARIANT; 839 pVarParams[parameterCount - i -1].pparray= &pVarParamsRef[outParamIndex].parray; 840 break; 841 case TypeClass_ANY: 842 if( ! pMethod->pParams[i].bIn) 843 { 844 pVarParamsRef[ outParamIndex].vt = VT_EMPTY; 845 pVarParamsRef[ outParamIndex].lVal = 0; 846 } 847 pVarParams[parameterCount - i -1].vt = VT_VARIANT | VT_BYREF; 848 pVarParams[parameterCount - i -1].pvarVal = &pVarParamsRef[outParamIndex]; 849 break; 850 case TypeClass_BOOLEAN: 851 if( ! pMethod->pParams[i].bIn) 852 { 853 pVarParamsRef[ outParamIndex].vt = VT_BOOL; 854 pVarParamsRef[ outParamIndex].boolVal = 0; 855 } 856 pVarParams[parameterCount - i -1].vt = VT_BOOL| VT_BYREF; 857 pVarParams[parameterCount - i -1].pboolVal = 858 & pVarParamsRef[outParamIndex].boolVal; 859 break; 860 861 case TypeClass_STRING: 862 if( ! pMethod->pParams[i].bIn) 863 { 864 pVarParamsRef[ outParamIndex].vt = VT_BSTR; 865 pVarParamsRef[ outParamIndex].bstrVal= 0; 866 } 867 pVarParams[parameterCount - i -1].vt = VT_BSTR| VT_BYREF; 868 pVarParams[parameterCount - i -1].pbstrVal= 869 & pVarParamsRef[outParamIndex].bstrVal; 870 break; 871 872 case TypeClass_FLOAT: 873 if( ! pMethod->pParams[i].bIn) 874 { 875 pVarParamsRef[ outParamIndex].vt = VT_R4; 876 pVarParamsRef[ outParamIndex].fltVal= 0; 877 } 878 pVarParams[parameterCount - i -1].vt = VT_R4| VT_BYREF; 879 pVarParams[parameterCount - i -1].pfltVal = 880 & pVarParamsRef[outParamIndex].fltVal; 881 break; 882 case TypeClass_DOUBLE: 883 if( ! pMethod->pParams[i].bIn) 884 { 885 pVarParamsRef[ outParamIndex].vt = VT_R8; 886 pVarParamsRef[ outParamIndex].dblVal= 0; 887 } 888 pVarParams[parameterCount - i -1].vt = VT_R8| VT_BYREF; 889 pVarParams[parameterCount - i -1].pdblVal= 890 & pVarParamsRef[outParamIndex].dblVal; 891 break; 892 case TypeClass_BYTE: 893 if( ! pMethod->pParams[i].bIn) 894 { 895 pVarParamsRef[ outParamIndex].vt = VT_UI1; 896 pVarParamsRef[ outParamIndex].bVal= 0; 897 } 898 pVarParams[parameterCount - i -1].vt = VT_UI1| VT_BYREF; 899 pVarParams[parameterCount - i -1].pbVal= 900 & pVarParamsRef[outParamIndex].bVal; 901 break; 902 case TypeClass_CHAR: 903 case TypeClass_SHORT: 904 case TypeClass_UNSIGNED_SHORT: 905 if( ! pMethod->pParams[i].bIn) 906 { 907 pVarParamsRef[ outParamIndex].vt = VT_I2; 908 pVarParamsRef[ outParamIndex].iVal = 0; 909 } 910 pVarParams[parameterCount - i -1].vt = VT_I2| VT_BYREF; 911 pVarParams[parameterCount - i -1].piVal= 912 & pVarParamsRef[outParamIndex].iVal; 913 break; 914 915 default: 916 if( ! pMethod->pParams[i].bIn) 917 { 918 pVarParamsRef[ outParamIndex].vt = VT_EMPTY; 919 pVarParamsRef[ outParamIndex].lVal = 0; 920 } 921 pVarParams[parameterCount - i -1].vt = VT_VARIANT | VT_BYREF; 922 pVarParams[parameterCount - i -1].pvarVal = 923 & pVarParamsRef[outParamIndex]; 924 } 925 outParamIndex++; 926 } // end else if 927 } // end for 928 } 929 catch (IllegalArgumentException & e) 930 { 931 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i ); 932 throw; 933 } 934 catch (CannotConvertException & e) 935 { 936 e.ArgumentIndex = i; 937 throw; 938 } 939 } 940 else // it is an JScriptObject 941 { 942 int i = 0; 943 try 944 { 945 for( ; i< parameterCount; i++) 946 { 947 // In parameter 948 if( pMethod->pParams[i].bIn == sal_True && ! pMethod->pParams[i].bOut) 949 { 950 anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]); 951 } 952 // Out parameter + in/out parameter 953 else if( pMethod->pParams[i].bOut == sal_True) 954 { 955 CComObject<JScriptOutParam>* pParamObject; 956 if( SUCCEEDED( CComObject<JScriptOutParam>::CreateInstance( &pParamObject))) 957 { 958 CComPtr<IUnknown> pUnk(pParamObject->GetUnknown()); 959 #ifdef __MINGW32__ 960 CComQIPtr<IDispatch, &__uuidof(IDispatch)> pDisp( pUnk); 961 #else 962 CComQIPtr<IDispatch> pDisp( pUnk); 963 #endif 964 965 pVarParams[ parameterCount - i -1].vt= VT_DISPATCH; 966 pVarParams[ parameterCount - i -1].pdispVal= pDisp; 967 pVarParams[ parameterCount - i -1].pdispVal->AddRef(); 968 // if the param is in/out then put the parameter on index 0 969 if( pMethod->pParams[i].bIn == sal_True ) // in / out 970 { 971 CComVariant varParam; 972 anyToVariant( &varParam, Params.getConstArray()[i]); 973 CComDispatchDriver dispDriver( pDisp); 974 if(FAILED( dispDriver.PutPropertyByName( L"0", &varParam))) 975 throw BridgeRuntimeError( 976 OUSTR("[automation bridge]IUnknownWrapper_Impl::" 977 "invokeWithDispIdUnoTlb\n" 978 "Could not set property \"0\" for the in/out " 979 "param!")); 980 981 } 982 } 983 else 984 { 985 throw BridgeRuntimeError( 986 OUSTR("[automation bridge]IUnknownWrapper_Impl::" 987 "invokeWithDispIdUnoTlb\n" 988 "Could not create out parameter at index: ") + 989 OUString::valueOf((sal_Int32) i)); 990 } 991 992 } 993 } 994 } 995 catch (IllegalArgumentException & e) 996 { 997 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i ); 998 throw; 999 } 1000 catch (CannotConvertException & e) 1001 { 1002 e.ArgumentIndex = i; 1003 throw; 1004 } 1005 } 1006 } 1007 // No type description Available, that is we have to deal with a COM component, 1008 // that does not implements UNO interfaces ( IDispatch based) 1009 else 1010 { 1011 //We should not run into this block, because invokeWithDispIdComTlb should 1012 //have been called instead. 1013 OSL_ASSERT(0); 1014 } 1015 1016 1017 CComVariant varResult; 1018 ExcepInfo excepinfo; 1019 unsigned int uArgErr; 1020 DISPPARAMS dispparams= { pVarParams, NULL, parameterCount, 0}; 1021 // Get the DISPID 1022 FuncDesc aDesc(getTypeInfo()); 1023 getFuncDesc(sFunctionName, & aDesc); 1024 // invoking OLE method 1025 hr = m_spDispatch->Invoke(aDesc->memid, 1026 IID_NULL, 1027 LOCALE_USER_DEFAULT, 1028 DISPATCH_METHOD, 1029 &dispparams, 1030 &varResult, 1031 &excepinfo, 1032 &uArgErr); 1033 1034 // converting return value and out parameter back to UNO 1035 if (hr == S_OK) 1036 { 1037 if( outParameterCount && pMethod) 1038 { 1039 OutParamIndex.realloc( outParameterCount); 1040 OutParam.realloc( outParameterCount); 1041 sal_Int32 outIndex=0; 1042 int i = 0; 1043 try 1044 { 1045 for( ; i < parameterCount; i++) 1046 { 1047 if( pMethod->pParams[i].bOut ) 1048 { 1049 OutParamIndex[outIndex]= (sal_Int16) i; 1050 Any outAny; 1051 if( !bJScriptObject) 1052 { 1053 variantToAny( &pVarParamsRef[outIndex], outAny, 1054 Type(pMethod->pParams[i].pTypeRef), sal_False); 1055 OutParam[outIndex++]= outAny; 1056 } 1057 else //JScriptObject 1058 { 1059 if( pVarParams[i].vt == VT_DISPATCH) 1060 { 1061 CComDispatchDriver pDisp( pVarParams[i].pdispVal); 1062 if( pDisp) 1063 { 1064 CComVariant varOut; 1065 if( SUCCEEDED( pDisp.GetPropertyByName( L"0", &varOut))) 1066 { 1067 variantToAny( &varOut, outAny, 1068 Type(pMethod->pParams[parameterCount - 1 - i].pTypeRef), sal_False); 1069 OutParam[outParameterCount - 1 - outIndex++]= outAny; 1070 } 1071 else 1072 bConvRet= sal_False; 1073 } 1074 else 1075 bConvRet= sal_False; 1076 } 1077 else 1078 bConvRet= sal_False; 1079 } 1080 } 1081 if( !bConvRet) break; 1082 } 1083 } 1084 catch(IllegalArgumentException & e) 1085 { 1086 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i ); 1087 throw; 1088 } 1089 catch(CannotConvertException & e) 1090 { 1091 e.ArgumentIndex = i; 1092 throw; 1093 } 1094 } 1095 // return value, no type information available 1096 if ( bConvRet) 1097 { 1098 try 1099 { 1100 if( pMethod ) 1101 variantToAny(&varResult, ret, Type( pMethod->pReturnTypeRef), sal_False); 1102 else 1103 variantToAny(&varResult, ret, sal_False); 1104 } 1105 catch (IllegalArgumentException & e) 1106 { 1107 e.Message = 1108 OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n" 1109 "Could not convert return value! \n Message: \n") + e.Message; 1110 throw; 1111 } 1112 catch (CannotConvertException & e) 1113 { 1114 e.Message = 1115 OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n" 1116 "Could not convert return value! \n Message: \n") + e.Message; 1117 throw; 1118 } 1119 } 1120 } 1121 1122 if( !bConvRet) // conversion of return or out parameter failed 1123 throw CannotConvertException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Call to COM object failed. Conversion of return or out value failed")), 1124 Reference<XInterface>( static_cast<XWeak*>(this), UNO_QUERY ), TypeClass_UNKNOWN, 1125 FailReason::UNKNOWN, 0);// lookup error code 1126 // conversion of return or out parameter failed 1127 switch (hr) 1128 { 1129 case S_OK: 1130 break; 1131 case DISP_E_BADPARAMCOUNT: 1132 throw IllegalArgumentException(); 1133 break; 1134 case DISP_E_BADVARTYPE: 1135 throw RuntimeException(); 1136 break; 1137 case DISP_E_EXCEPTION: 1138 throw InvocationTargetException(); 1139 break; 1140 case DISP_E_MEMBERNOTFOUND: 1141 throw IllegalArgumentException(); 1142 break; 1143 case DISP_E_NONAMEDARGS: 1144 throw IllegalArgumentException(); 1145 break; 1146 case DISP_E_OVERFLOW: 1147 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( 1148 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr); 1149 break; 1150 case DISP_E_PARAMNOTFOUND: 1151 throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( 1152 static_cast<XWeak*>(this)), ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); 1153 break; 1154 case DISP_E_TYPEMISMATCH: 1155 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface*>( 1156 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr); 1157 break; 1158 case DISP_E_UNKNOWNINTERFACE: 1159 throw RuntimeException() ; 1160 break; 1161 case DISP_E_UNKNOWNLCID: 1162 throw RuntimeException() ; 1163 break; 1164 case DISP_E_PARAMNOTOPTIONAL: 1165 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( 1166 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr); 1167 break; 1168 default: 1169 throw RuntimeException(); 1170 break; 1171 } 1172 1173 return ret; 1174 } 1175 1176 1177 1178 // -------------------------- 1179 // XInitialization 1180 void SAL_CALL IUnknownWrapper_Impl::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException) 1181 { 1182 // 1.parameter is IUnknown 1183 // 2.parameter is a boolean which indicates if the the COM pointer was a IUnknown or IDispatch 1184 // 3.parameter is a Sequence<Type> 1185 o2u_attachCurrentThread(); 1186 OSL_ASSERT(aArguments.getLength() == 3); 1187 1188 m_spUnknown= *(IUnknown**) aArguments[0].getValue(); 1189 #ifdef __MINGW32__ 1190 m_spUnknown->QueryInterface(IID_IDispatch, reinterpret_cast<LPVOID*>( & m_spDispatch.p)); 1191 #else 1192 m_spUnknown.QueryInterface( & m_spDispatch.p); 1193 #endif 1194 1195 aArguments[1] >>= m_bOriginalDispatch; 1196 aArguments[2] >>= m_seqTypes; 1197 1198 ITypeInfo* pType = NULL; 1199 try 1200 { 1201 // a COM object implementation that has no TypeInfo is still a legal COM object; 1202 // such objects can at least be transported through UNO using the bridge 1203 // so we should allow to create wrappers for them as well 1204 pType = getTypeInfo(); 1205 } 1206 catch( BridgeRuntimeError& ) 1207 {} 1208 catch( Exception& ) 1209 {} 1210 1211 if ( pType ) 1212 { 1213 try 1214 { 1215 // Get Default member 1216 CComBSTR defaultMemberName; 1217 if ( SUCCEEDED( pType->GetDocumentation(0, &defaultMemberName, 0, 0, 0 ) ) ) 1218 { 1219 OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(defaultMemberName))); 1220 FuncDesc aDescGet(pType); 1221 FuncDesc aDescPut(pType); 1222 VarDesc aVarDesc(pType); 1223 // see if this is a property first ( more likely to be a property then a method ) 1224 getPropDesc( usName, & aDescGet, & aDescPut, & aVarDesc); 1225 1226 if ( !aDescGet && !aDescPut ) 1227 { 1228 getFuncDesc( usName, &aDescGet ); 1229 if ( !aDescGet ) 1230 throw BridgeRuntimeError( OUSTR("[automation bridge]IUnknownWrapper_Impl::initialize() Failed to get Function or Property desc. for " ) + usName ); 1231 } 1232 // now for some funny heuristics to make basic understand what to do 1233 // a single aDescGet ( that doesn't take any params ) would be 1234 // a read only ( defaultmember ) property e.g. this object 1235 // should implement XDefaultProperty 1236 // a single aDescGet ( that *does* ) take params is basically a 1237 // default method e.g. implement XDefaultMethod 1238 1239 // a DescPut ( I guess we only really support a default param with '1' param ) as a setValue ( but I guess we can leave it through, the object will fail if we don't get it right anyway ) 1240 if ( aDescPut || ( aDescGet && aDescGet->cParams == 0 ) ) 1241 m_bHasDfltProperty = true; 1242 if ( aDescGet->cParams > 0 ) 1243 m_bHasDfltMethod = true; 1244 if ( m_bHasDfltProperty || m_bHasDfltMethod ) 1245 m_sDefaultMember = usName; 1246 } 1247 } 1248 catch ( BridgeRuntimeError & e ) 1249 { 1250 throw RuntimeException( e.message, Reference<XInterface>() ); 1251 } 1252 catch( Exception& e ) 1253 { 1254 throw RuntimeException( 1255 OUSTR("[automation bridge] unexpected exception in IUnknownWrapper_Impl::initialiase() error message: \n") + e.Message, 1256 Reference<XInterface>() ); 1257 } 1258 } 1259 } 1260 1261 // -------------------------- 1262 // XDirectInvocation 1263 uno::Any SAL_CALL IUnknownWrapper_Impl::directInvoke( const ::rtl::OUString& aName, const uno::Sequence< uno::Any >& aParams ) 1264 throw (lang::IllegalArgumentException, script::CannotConvertException, reflection::InvocationTargetException, uno::RuntimeException) 1265 { 1266 Any aResult; 1267 1268 if ( !m_spDispatch ) 1269 { 1270 throw RuntimeException( 1271 OUSTR("[automation bridge] The object does not have an IDispatch interface"), 1272 Reference<XInterface>()); 1273 } 1274 1275 o2u_attachCurrentThread(); 1276 DISPID dispid; 1277 if ( !getDispid( aName, &dispid ) ) 1278 throw IllegalArgumentException( 1279 OUSTR( "[automation bridge] The object does not have a function or property " ) 1280 + aName, Reference<XInterface>(), 0); 1281 1282 CComVariant varResult; 1283 ExcepInfo excepinfo; 1284 unsigned int uArgErr = 0; 1285 INVOKEKIND pInvkinds[2]; 1286 pInvkinds[0] = INVOKE_FUNC; 1287 pInvkinds[1] = aParams.getLength() ? INVOKE_PROPERTYPUT : INVOKE_PROPERTYGET; 1288 HRESULT hInvRes = E_FAIL; 1289 1290 // try Invoke first, if it does not work, try put/get property 1291 for ( sal_Int32 nStep = 0; FAILED( hInvRes ) && nStep < 2; nStep++ ) 1292 { 1293 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1294 1295 DISPID idPropertyPut = DISPID_PROPERTYPUT; 1296 scoped_array<DISPID> arDispidNamedArgs; 1297 scoped_array<CComVariant> ptrArgs; 1298 scoped_array<CComVariant> ptrRefArgs; // referenced arguments 1299 CComVariant * arArgs = NULL; 1300 CComVariant * arRefArgs = NULL; 1301 bool bVarargParam = false; 1302 1303 dispparams.cArgs = aParams.getLength(); 1304 1305 // Determine the number of named arguments 1306 for ( sal_Int32 nInd = 0; nInd < aParams.getLength(); nInd++ ) 1307 if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0) ) 1308 dispparams.cNamedArgs ++; 1309 1310 // fill the named arguments 1311 if ( dispparams.cNamedArgs > 0 1312 && !( dispparams.cNamedArgs == 1 && pInvkinds[nStep] == INVOKE_PROPERTYPUT ) ) 1313 { 1314 int nSizeAr = dispparams.cNamedArgs + 1; 1315 if ( pInvkinds[nStep] == INVOKE_PROPERTYPUT ) 1316 nSizeAr = dispparams.cNamedArgs; 1317 1318 scoped_array<OLECHAR*> saNames(new OLECHAR*[nSizeAr]); 1319 OLECHAR ** pNames = saNames.get(); 1320 pNames[0] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(aName.getStr())); 1321 1322 int cNamedArg = 0; 1323 for ( size_t nInd = 0; nInd < dispparams.cArgs; nInd++ ) 1324 { 1325 if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0)) 1326 { 1327 const NamedArgument& arg = *(NamedArgument const*)aParams[nInd].getValue(); 1328 1329 //We put the parameter names in reverse order into the array, 1330 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs 1331 //The first name in the array is the method name 1332 pNames[nSizeAr - 1 - cNamedArg++] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(arg.Name.getStr())); 1333 } 1334 } 1335 1336 arDispidNamedArgs.reset( new DISPID[nSizeAr] ); 1337 HRESULT hr = getTypeInfo()->GetIDsOfNames( pNames, nSizeAr, arDispidNamedArgs.get() ); 1338 if ( hr == E_NOTIMPL ) 1339 hr = m_spDispatch->GetIDsOfNames(IID_NULL, pNames, nSizeAr, LOCALE_USER_DEFAULT, arDispidNamedArgs.get() ); 1340 1341 if ( SUCCEEDED( hr ) ) 1342 { 1343 if ( pInvkinds[nStep] == DISPATCH_PROPERTYPUT ) 1344 { 1345 DISPID* arIDs = arDispidNamedArgs.get(); 1346 arIDs[0] = DISPID_PROPERTYPUT; 1347 dispparams.rgdispidNamedArgs = arIDs; 1348 } 1349 else 1350 { 1351 DISPID* arIDs = arDispidNamedArgs.get(); 1352 dispparams.rgdispidNamedArgs = & arIDs[1]; 1353 } 1354 } 1355 else if (hr == DISP_E_UNKNOWNNAME) 1356 { 1357 throw IllegalArgumentException( 1358 OUSTR("[automation bridge]One of the named arguments is wrong!"), 1359 Reference<XInterface>(), 0); 1360 } 1361 else 1362 { 1363 throw InvocationTargetException( 1364 OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ") 1365 + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any()); 1366 } 1367 } 1368 1369 //Convert arguments 1370 ptrArgs.reset(new CComVariant[dispparams.cArgs]); 1371 ptrRefArgs.reset(new CComVariant[dispparams.cArgs]); 1372 arArgs = ptrArgs.get(); 1373 arRefArgs = ptrRefArgs.get(); 1374 1375 sal_Int32 nInd = 0; 1376 try 1377 { 1378 sal_Int32 revIndex = 0; 1379 for ( nInd = 0; nInd < sal_Int32(dispparams.cArgs); nInd++) 1380 { 1381 revIndex = dispparams.cArgs - nInd - 1; 1382 arRefArgs[revIndex].byref = 0; 1383 Any anyArg; 1384 if ( nInd < aParams.getLength() ) 1385 anyArg = aParams.getConstArray()[nInd]; 1386 1387 // Property Put arguments 1388 if ( anyArg.getValueType() == getCppuType((PropertyPutArgument*)0) ) 1389 { 1390 PropertyPutArgument arg; 1391 anyArg >>= arg; 1392 anyArg <<= arg.Value; 1393 } 1394 // named argument 1395 if (anyArg.getValueType() == getCppuType((NamedArgument*) 0)) 1396 { 1397 NamedArgument aNamedArgument; 1398 anyArg >>= aNamedArgument; 1399 anyArg <<= aNamedArgument.Value; 1400 } 1401 1402 if ( nInd < aParams.getLength() && anyArg.getValueTypeClass() != TypeClass_VOID ) 1403 { 1404 anyToVariant( &arArgs[revIndex], anyArg, VT_VARIANT ); 1405 } 1406 else 1407 { 1408 arArgs[revIndex].vt = VT_ERROR; 1409 arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND; 1410 } 1411 } 1412 } 1413 catch (IllegalArgumentException & e) 1414 { 1415 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, sal_Int32 >( nInd ); 1416 throw; 1417 } 1418 catch (CannotConvertException & e) 1419 { 1420 e.ArgumentIndex = nInd; 1421 throw; 1422 } 1423 1424 dispparams.rgvarg = arArgs; 1425 // invoking OLE method 1426 DWORD localeId = LOCALE_USER_DEFAULT; 1427 hInvRes = m_spDispatch->Invoke( dispid, 1428 IID_NULL, 1429 localeId, 1430 ::sal::static_int_cast< WORD, INVOKEKIND >( pInvkinds[nStep] ), 1431 &dispparams, 1432 &varResult, 1433 &excepinfo, 1434 &uArgErr); 1435 } 1436 1437 // converting return value and out parameter back to UNO 1438 if ( SUCCEEDED( hInvRes ) ) 1439 variantToAny( &varResult, aResult, sal_False ); 1440 else 1441 { 1442 // map error codes to exceptions 1443 OUString message; 1444 switch ( hInvRes ) 1445 { 1446 case S_OK: 1447 break; 1448 case DISP_E_BADPARAMCOUNT: 1449 throw IllegalArgumentException(OUSTR("[automation bridge] Wrong " 1450 "number of arguments. Object returned DISP_E_BADPARAMCOUNT."), 1451 0, 0); 1452 break; 1453 case DISP_E_BADVARTYPE: 1454 throw RuntimeException(OUSTR("[automation bridge] One or more " 1455 "arguments have the wrong type. Object returned " 1456 "DISP_E_BADVARTYPE."), 0); 1457 break; 1458 case DISP_E_EXCEPTION: 1459 message = OUSTR("[automation bridge]: "); 1460 message += OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription), 1461 ::SysStringLen(excepinfo.bstrDescription)); 1462 throw InvocationTargetException(message, Reference<XInterface>(), Any()); 1463 break; 1464 case DISP_E_MEMBERNOTFOUND: 1465 message = OUSTR("[automation bridge]: A function with the name \"") 1466 + aName + OUSTR("\" is not supported. Object returned " 1467 "DISP_E_MEMBERNOTFOUND."); 1468 throw IllegalArgumentException(message, 0, 0); 1469 break; 1470 case DISP_E_NONAMEDARGS: 1471 throw IllegalArgumentException(OUSTR("[automation bridge] Object " 1472 "returned DISP_E_NONAMEDARGS"),0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); 1473 break; 1474 case DISP_E_OVERFLOW: 1475 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[automation bridge] Call failed.")), 1476 static_cast<XInterface*>( 1477 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr); 1478 break; 1479 case DISP_E_PARAMNOTFOUND: 1480 throw IllegalArgumentException(OUSTR("[automation bridge]Call failed." 1481 "Object returned DISP_E_PARAMNOTFOUND."), 1482 0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); 1483 break; 1484 case DISP_E_TYPEMISMATCH: 1485 throw CannotConvertException(OUSTR("[automation bridge] Call failed. " 1486 "Object returned DISP_E_TYPEMISMATCH"), 1487 static_cast<XInterface*>( 1488 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr); 1489 break; 1490 case DISP_E_UNKNOWNINTERFACE: 1491 throw RuntimeException(OUSTR("[automation bridge] Call failed. " 1492 "Object returned DISP_E_UNKNOWNINTERFACE."),0); 1493 break; 1494 case DISP_E_UNKNOWNLCID: 1495 throw RuntimeException(OUSTR("[automation bridge] Call failed. " 1496 "Object returned DISP_E_UNKNOWNLCID."),0); 1497 break; 1498 case DISP_E_PARAMNOTOPTIONAL: 1499 throw CannotConvertException(OUSTR("[automation bridge] Call failed." 1500 "Object returned DISP_E_PARAMNOTOPTIONAL"), 1501 static_cast<XInterface*>(static_cast<XWeak*>(this)), 1502 TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr); 1503 break; 1504 default: 1505 throw RuntimeException(); 1506 break; 1507 } 1508 } 1509 1510 return aResult; 1511 } 1512 1513 ::sal_Bool SAL_CALL IUnknownWrapper_Impl::hasMember( const ::rtl::OUString& aName ) 1514 throw (uno::RuntimeException) 1515 { 1516 if ( ! m_spDispatch ) 1517 { 1518 throw RuntimeException( 1519 OUSTR("[automation bridge] The object does not have an IDispatch interface"), 1520 Reference<XInterface>()); 1521 } 1522 1523 o2u_attachCurrentThread(); 1524 DISPID dispid; 1525 return getDispid( aName, &dispid ); 1526 } 1527 1528 1529 // UnoConversionUtilities -------------------------------------------------------------------------------- 1530 Reference< XInterface > IUnknownWrapper_Impl::createUnoWrapperInstance() 1531 { 1532 if( m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL) 1533 { 1534 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl( 1535 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); 1536 return Reference<XInterface>( xWeak, UNO_QUERY); 1537 } 1538 else if( m_nUnoWrapperClass == UNO_OBJECT_WRAPPER_REMOTE_OPT) 1539 { 1540 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt( 1541 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); 1542 return Reference<XInterface>( xWeak, UNO_QUERY); 1543 } 1544 else 1545 return Reference<XInterface>(); 1546 } 1547 Reference<XInterface> IUnknownWrapper_Impl::createComWrapperInstance() 1548 { 1549 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl( 1550 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); 1551 return Reference<XInterface>( xWeak, UNO_QUERY); 1552 } 1553 1554 1555 1556 void IUnknownWrapper_Impl::getMethodInfo(const OUString& sName, TypeDescription& methodInfo) 1557 { 1558 TypeDescription desc= getInterfaceMemberDescOfCurrentCall(sName); 1559 if( desc.is()) 1560 { 1561 typelib_TypeDescription* pMember= desc.get(); 1562 if( pMember->eTypeClass == TypeClass_INTERFACE_METHOD ) 1563 methodInfo= pMember; 1564 } 1565 } 1566 1567 void IUnknownWrapper_Impl::getAttributeInfo(const OUString& sName, TypeDescription& attributeInfo) 1568 { 1569 TypeDescription desc= getInterfaceMemberDescOfCurrentCall(sName); 1570 if( desc.is()) 1571 { 1572 typelib_TypeDescription* pMember= desc.get(); 1573 if( pMember->eTypeClass == TypeClass_INTERFACE_ATTRIBUTE ) 1574 { 1575 attributeInfo= ((typelib_InterfaceAttributeTypeDescription*)pMember)->pAttributeTypeRef; 1576 } 1577 } 1578 } 1579 TypeDescription IUnknownWrapper_Impl::getInterfaceMemberDescOfCurrentCall(const OUString& sName) 1580 { 1581 TypeDescription ret; 1582 1583 for( sal_Int32 i=0; i < m_seqTypes.getLength(); i++) 1584 { 1585 TypeDescription _curDesc( m_seqTypes[i]); 1586 _curDesc.makeComplete(); 1587 typelib_InterfaceTypeDescription * pInterface= (typelib_InterfaceTypeDescription*) _curDesc.get(); 1588 if( pInterface) 1589 { 1590 typelib_InterfaceMemberTypeDescription* pMember= NULL; 1591 //find the member description of the current call 1592 for( int i=0; i < pInterface->nAllMembers; i++) 1593 { 1594 typelib_TypeDescriptionReference* pTypeRefMember = pInterface->ppAllMembers[i]; 1595 typelib_TypeDescription* pDescMember= NULL; 1596 TYPELIB_DANGER_GET( &pDescMember, pTypeRefMember) 1597 1598 typelib_InterfaceMemberTypeDescription* pInterfaceMember= 1599 (typelib_InterfaceMemberTypeDescription*) pDescMember; 1600 if( OUString( pInterfaceMember->pMemberName) == sName) 1601 { 1602 pMember= pInterfaceMember; 1603 break; 1604 } 1605 TYPELIB_DANGER_RELEASE( pDescMember) 1606 } 1607 1608 if( pMember) 1609 { 1610 ret= (typelib_TypeDescription*)pMember; 1611 TYPELIB_DANGER_RELEASE( (typelib_TypeDescription*)pMember); 1612 } 1613 } 1614 if( ret.is()) 1615 break; 1616 } 1617 return ret; 1618 } 1619 1620 sal_Bool IUnknownWrapper_Impl::isJScriptObject() 1621 { 1622 if( m_eJScript == JScriptUndefined) 1623 { 1624 CComDispatchDriver disp( m_spDispatch); 1625 if( disp) 1626 { 1627 CComVariant result; 1628 if( SUCCEEDED( disp.GetPropertyByName( JSCRIPT_ID_PROPERTY, &result))) 1629 { 1630 if(result.vt == VT_BSTR) 1631 { 1632 CComBSTR name( result.bstrVal); 1633 name.ToLower(); 1634 if( name == CComBSTR(JSCRIPT_ID)) 1635 m_eJScript= IsJScript; 1636 } 1637 } 1638 } 1639 if( m_eJScript == JScriptUndefined) 1640 m_eJScript= NoJScript; 1641 } 1642 1643 return m_eJScript == NoJScript ? sal_False : sal_True; 1644 } 1645 1646 1647 1648 /** @internal 1649 The function ultimately calls IDispatch::Invoke on the wrapped COM object. 1650 The COM object does not implement UNO Interfaces ( via IDispatch). This 1651 is the case when the OleObjectFactory service has been used to create a 1652 component. 1653 @exception IllegalArgumentException 1654 @exception CannotConvertException 1655 @InvocationTargetException 1656 @RuntimeException 1657 @BridgeRuntimeError 1658 */ 1659 Any IUnknownWrapper_Impl::invokeWithDispIdComTlb(const OUString& sFuncName, 1660 const Sequence< Any >& Params, 1661 Sequence< sal_Int16 >& OutParamIndex, 1662 Sequence< Any >& OutParam) 1663 { 1664 Any ret; 1665 HRESULT result; 1666 1667 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1668 CComVariant varResult; 1669 ExcepInfo excepinfo; 1670 unsigned int uArgErr; 1671 sal_Int32 i = 0; 1672 sal_Int32 nUnoArgs = Params.getLength(); 1673 DISPID idPropertyPut = DISPID_PROPERTYPUT; 1674 scoped_array<DISPID> arDispidNamedArgs; 1675 scoped_array<CComVariant> ptrArgs; 1676 scoped_array<CComVariant> ptrRefArgs; // referenced arguments 1677 CComVariant * arArgs = NULL; 1678 CComVariant * arRefArgs = NULL; 1679 sal_Int32 revIndex = 0; 1680 bool bVarargParam = false; 1681 1682 // Get type info for the call. It can be a method call or property put or 1683 // property get operation. 1684 FuncDesc aFuncDesc(getTypeInfo()); 1685 getFuncDescForInvoke(sFuncName, Params, & aFuncDesc); 1686 1687 //Set the array of DISPIDs for named args if it is a property put operation. 1688 //If there are other named arguments another array is set later on. 1689 if (aFuncDesc->invkind == INVOKE_PROPERTYPUT 1690 || aFuncDesc->invkind == INVOKE_PROPERTYPUTREF) 1691 dispparams.rgdispidNamedArgs = & idPropertyPut; 1692 1693 //Determine the number of named arguments 1694 for (int iParam = 0; iParam < nUnoArgs; iParam ++) 1695 { 1696 const Any & curArg = Params[iParam]; 1697 if (curArg.getValueType() == getCppuType((NamedArgument*) 0)) 1698 dispparams.cNamedArgs ++; 1699 } 1700 //In a property put operation a property value is a named argument (DISPID_PROPERTYPUT). 1701 //Therefore the number of named arguments is increased by one. 1702 //Although named, the argument is not named in a actual language, such as Basic, 1703 //therefore it is never a com.sun.star.bridge.oleautomation.NamedArgument 1704 if (aFuncDesc->invkind == DISPATCH_PROPERTYPUT 1705 || aFuncDesc->invkind == DISPATCH_PROPERTYPUTREF) 1706 dispparams.cNamedArgs ++; 1707 1708 //Determine the number of all arguments and named arguments 1709 if (aFuncDesc->cParamsOpt == -1) 1710 { 1711 //Attribute vararg is set on this method. "Unlimited" number of args 1712 //supported. There can be no optional or defaultvalue on any of the arguments. 1713 dispparams.cArgs = nUnoArgs; 1714 } 1715 else 1716 { 1717 //If there are namesd arguments, then the dispparams.cArgs 1718 //is the number of supplied args, otherwise it is the expected number. 1719 if (dispparams.cNamedArgs) 1720 dispparams.cArgs = nUnoArgs; 1721 else 1722 dispparams.cArgs = aFuncDesc->cParams; 1723 } 1724 1725 //check if there are not to many arguments supplied 1726 if (::sal::static_int_cast< sal_uInt32, int >( nUnoArgs ) > dispparams.cArgs) 1727 { 1728 OUStringBuffer buf(256); 1729 buf.appendAscii("[automation bridge] There are too many arguments for this method"); 1730 throw IllegalArgumentException( buf.makeStringAndClear(), 1731 Reference<XInterface>(), (sal_Int16) dispparams.cArgs); 1732 } 1733 1734 //Set up the array of DISPIDs (DISPPARAMS::rgdispidNamedArgs) 1735 //for the named arguments. 1736 //If there is only one named arg and if it is because of a property put 1737 //operation, then we need not set up the DISPID array. 1738 if (dispparams.cNamedArgs > 0 && 1739 ! (dispparams.cNamedArgs == 1 && 1740 (aFuncDesc->invkind == INVOKE_PROPERTYPUT || 1741 aFuncDesc->invkind == INVOKE_PROPERTYPUT))) 1742 { 1743 //set up an array containing the member and parameter names 1744 //which is then used in ITypeInfo::GetIDsOfNames 1745 //First determine the size of the array of names which is passed to 1746 //ITypeInfo::GetIDsOfNames. It must hold the method names + the named 1747 //args. 1748 int nSizeAr = dispparams.cNamedArgs + 1; 1749 if (aFuncDesc->invkind == INVOKE_PROPERTYPUT 1750 || aFuncDesc->invkind == INVOKE_PROPERTYPUTREF) 1751 { 1752 nSizeAr = dispparams.cNamedArgs; //counts the DISID_PROPERTYPUT 1753 } 1754 1755 scoped_array<OLECHAR*> saNames(new OLECHAR*[nSizeAr]); 1756 OLECHAR ** arNames = saNames.get(); 1757 arNames[0] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(sFuncName.getStr())); 1758 1759 int cNamedArg = 0; 1760 for (size_t iParams = 0; iParams < dispparams.cArgs; iParams ++) 1761 { 1762 const Any & curArg = Params[iParams]; 1763 if (curArg.getValueType() == getCppuType((NamedArgument*) 0)) 1764 { 1765 const NamedArgument& arg = *(NamedArgument const*) curArg.getValue(); 1766 //We put the parameter names in reverse order into the array, 1767 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs 1768 //The first name in the array is the method name 1769 arNames[nSizeAr - 1 - cNamedArg++] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(arg.Name.getStr())); 1770 } 1771 } 1772 1773 //Prepare the array of DISPIDs for ITypeInfo::GetIDsOfNames 1774 //it must be big enough to contain the DISPIDs of the member + parameters 1775 arDispidNamedArgs.reset(new DISPID[nSizeAr]); 1776 HRESULT hr = getTypeInfo()->GetIDsOfNames(arNames, nSizeAr, 1777 arDispidNamedArgs.get()); 1778 if ( hr == E_NOTIMPL ) 1779 hr = m_spDispatch->GetIDsOfNames(IID_NULL, arNames, nSizeAr, LOCALE_USER_DEFAULT, arDispidNamedArgs.get() ); 1780 1781 if (hr == S_OK) 1782 { 1783 // In a "property put" operation, the property value is a named param with the 1784 //special DISPID DISPID_PROPERTYPUT 1785 if (aFuncDesc->invkind == DISPATCH_PROPERTYPUT 1786 || aFuncDesc->invkind == DISPATCH_PROPERTYPUTREF) 1787 { 1788 //Element at index 0 in the DISPID array must be DISPID_PROPERTYPUT 1789 //The first item in the array arDispidNamedArgs is the DISPID for 1790 //the method. We replace it with DISPID_PROPERTYPUT. 1791 DISPID* arIDs = arDispidNamedArgs.get(); 1792 arIDs[0] = DISPID_PROPERTYPUT; 1793 dispparams.rgdispidNamedArgs = arIDs; 1794 } 1795 else 1796 { 1797 //The first item in the array arDispidNamedArgs is the DISPID for 1798 //the method. It must be removed 1799 DISPID* arIDs = arDispidNamedArgs.get(); 1800 dispparams.rgdispidNamedArgs = & arIDs[1]; 1801 } 1802 } 1803 else if (hr == DISP_E_UNKNOWNNAME) 1804 { 1805 throw IllegalArgumentException( 1806 OUSTR("[automation bridge]One of the named arguments is wrong!"), 1807 Reference<XInterface>(), 0); 1808 } 1809 else 1810 { 1811 throw InvocationTargetException( 1812 OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ") 1813 + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any()); 1814 } 1815 } 1816 1817 //Convert arguments 1818 ptrArgs.reset(new CComVariant[dispparams.cArgs]); 1819 ptrRefArgs.reset(new CComVariant[dispparams.cArgs]); 1820 arArgs = ptrArgs.get(); 1821 arRefArgs = ptrRefArgs.get(); 1822 try 1823 { 1824 for (i = 0; i < (sal_Int32) dispparams.cArgs; i++) 1825 { 1826 revIndex= dispparams.cArgs - i -1; 1827 arRefArgs[revIndex].byref=0; 1828 Any anyArg; 1829 if ( i < nUnoArgs) 1830 anyArg= Params.getConstArray()[i]; 1831 1832 //Test if the current parameter is a "vararg" parameter. 1833 if (bVarargParam || (aFuncDesc->cParamsOpt == -1 && 1834 aFuncDesc->cParams == (i + 1))) 1835 { //This parameter is from the variable argument list. There is no 1836 //type info available, except that it must be a VARIANT 1837 bVarargParam = true; 1838 } 1839 1840 unsigned short paramFlags = PARAMFLAG_FOPT | PARAMFLAG_FIN; 1841 VARTYPE varType = VT_VARIANT; 1842 if ( ! bVarargParam) 1843 { 1844 paramFlags = 1845 aFuncDesc->lprgelemdescParam[i].paramdesc.wParamFlags; 1846 varType = getElementTypeDesc( 1847 & aFuncDesc->lprgelemdescParam[i].tdesc); 1848 } 1849 //Make sure that there is a UNO parameter for every 1850 // expected parameter. If there is no UNO parameter where the 1851 // called function expects one, then it must be optional. Otherwise 1852 // its a UNO programming error. 1853 if (i >= nUnoArgs && !(paramFlags & PARAMFLAG_FOPT)) 1854 { 1855 OUStringBuffer buf(256); 1856 buf.appendAscii("ole automation bridge: The called function expects an argument at" 1857 "position: "); //a different number of arguments")), 1858 buf.append(OUString::valueOf((sal_Int32) i)); 1859 buf.appendAscii(" (index starting at 0)."); 1860 throw IllegalArgumentException( buf.makeStringAndClear(), 1861 Reference<XInterface>(), (sal_Int16) i); 1862 } 1863 1864 // Property Put arguments 1865 if (anyArg.getValueType() == getCppuType((PropertyPutArgument*)0)) 1866 { 1867 PropertyPutArgument arg; 1868 anyArg >>= arg; 1869 anyArg <<= arg.Value; 1870 } 1871 // named argument 1872 if (anyArg.getValueType() == getCppuType((NamedArgument*) 0)) 1873 { 1874 NamedArgument aNamedArgument; 1875 anyArg >>= aNamedArgument; 1876 anyArg <<= aNamedArgument.Value; 1877 } 1878 // out param 1879 if (paramFlags & PARAMFLAG_FOUT && 1880 ! (paramFlags & PARAMFLAG_FIN) ) 1881 { 1882 VARTYPE type = ::sal::static_int_cast< VARTYPE, int >( varType ^ VT_BYREF ); 1883 if (i < nUnoArgs) 1884 { 1885 arRefArgs[revIndex].vt= type; 1886 } 1887 else 1888 { 1889 //optional arg 1890 arRefArgs[revIndex].vt = VT_ERROR; 1891 arRefArgs[revIndex].scode = DISP_E_PARAMNOTFOUND; 1892 } 1893 if( type == VT_VARIANT ) 1894 { 1895 arArgs[revIndex].vt= VT_VARIANT | VT_BYREF; 1896 arArgs[revIndex].byref= &arRefArgs[revIndex]; 1897 } 1898 else 1899 { 1900 arArgs[revIndex].vt= varType; 1901 if (type == VT_DECIMAL) 1902 arArgs[revIndex].byref= & arRefArgs[revIndex].decVal; 1903 else 1904 arArgs[revIndex].byref= & arRefArgs[revIndex].byref; 1905 } 1906 } 1907 // in/out + in byref params 1908 else if (varType & VT_BYREF) 1909 { 1910 VARTYPE type = ::sal::static_int_cast< VARTYPE, int >( varType ^ VT_BYREF ); 1911 CComVariant var; 1912 1913 if (i < nUnoArgs && anyArg.getValueTypeClass() != TypeClass_VOID) 1914 { 1915 anyToVariant( & arRefArgs[revIndex], anyArg, type); 1916 } 1917 else if (paramFlags & PARAMFLAG_FHASDEFAULT) 1918 { 1919 //optional arg with default 1920 VariantCopy( & arRefArgs[revIndex], 1921 & aFuncDesc->lprgelemdescParam[i].paramdesc. 1922 pparamdescex->varDefaultValue); 1923 } 1924 else 1925 { 1926 //optional arg 1927 //e.g: call func(x) in basic : func() ' no arg supplied 1928 OSL_ASSERT(paramFlags & PARAMFLAG_FOPT); 1929 arRefArgs[revIndex].vt = VT_ERROR; 1930 arRefArgs[revIndex].scode = DISP_E_PARAMNOTFOUND; 1931 } 1932 1933 // Set the converted arguments in the array which will be 1934 // DISPPARAMS::rgvarg 1935 // byref arg VT_XXX |VT_BYREF 1936 arArgs[revIndex].vt = varType; 1937 if (revIndex == 0 && aFuncDesc->invkind == INVOKE_PROPERTYPUT) 1938 { 1939 arArgs[revIndex] = arRefArgs[revIndex]; 1940 } 1941 else if (type == VT_DECIMAL) 1942 { 1943 arArgs[revIndex].byref= & arRefArgs[revIndex].decVal; 1944 } 1945 else if (type == VT_VARIANT) 1946 { 1947 if ( ! (paramFlags & PARAMFLAG_FOUT)) 1948 arArgs[revIndex] = arRefArgs[revIndex]; 1949 else 1950 arArgs[revIndex].byref = & arRefArgs[revIndex]; 1951 } 1952 else 1953 { 1954 arArgs[revIndex].byref = & arRefArgs[revIndex].byref; 1955 arArgs[revIndex].vt = ::sal::static_int_cast< VARTYPE, int >( arRefArgs[revIndex].vt | VT_BYREF ); 1956 } 1957 1958 } 1959 // in parameter no VT_BYREF except for array, interfaces 1960 else 1961 { // void any stands for optional param 1962 if (i < nUnoArgs && anyArg.getValueTypeClass() != TypeClass_VOID) 1963 { 1964 anyToVariant( & arArgs[revIndex], anyArg, varType); 1965 } 1966 //optional arg but no void any supplied 1967 //Basic: obj.func() ' first parameter left out because it is optional 1968 else if (paramFlags & PARAMFLAG_FHASDEFAULT) 1969 { 1970 //optional arg with defaulteithter as direct arg : VT_XXX or 1971 VariantCopy( & arArgs[revIndex], 1972 & aFuncDesc->lprgelemdescParam[i].paramdesc. 1973 pparamdescex->varDefaultValue); 1974 } 1975 else if (paramFlags & PARAMFLAG_FOPT) 1976 { 1977 arArgs[revIndex].vt = VT_ERROR; 1978 arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND; 1979 } 1980 else 1981 { 1982 arArgs[revIndex].vt = VT_EMPTY; 1983 arArgs[revIndex].lVal = 0; 1984 } 1985 } 1986 } 1987 } 1988 catch (IllegalArgumentException & e) 1989 { 1990 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, sal_Int32 >( i ); 1991 throw; 1992 } 1993 catch (CannotConvertException & e) 1994 { 1995 e.ArgumentIndex = i; 1996 throw; 1997 } 1998 dispparams.rgvarg= arArgs; 1999 // invoking OLE method 2000 DWORD localeId = LOCALE_USER_DEFAULT; 2001 result = m_spDispatch->Invoke(aFuncDesc->memid, 2002 IID_NULL, 2003 localeId, 2004 ::sal::static_int_cast< WORD, INVOKEKIND >( aFuncDesc->invkind ), 2005 &dispparams, 2006 &varResult, 2007 &excepinfo, 2008 &uArgErr); 2009 2010 // converting return value and out parameter back to UNO 2011 if (result == S_OK) 2012 { 2013 2014 // allocate space for the out param Sequence and indices Sequence 2015 int outParamsCount= 0; // includes in/out parameter 2016 for (int i = 0; i < aFuncDesc->cParams; i++) 2017 { 2018 if (aFuncDesc->lprgelemdescParam[i].paramdesc.wParamFlags & 2019 PARAMFLAG_FOUT) 2020 outParamsCount++; 2021 } 2022 2023 OutParamIndex.realloc(outParamsCount); 2024 OutParam.realloc(outParamsCount); 2025 // Convert out params 2026 if (outParamsCount) 2027 { 2028 int outParamIndex=0; 2029 for (int paramIndex = 0; paramIndex < nUnoArgs; paramIndex ++) 2030 { 2031 //Determine the index within the method sinature 2032 int realParamIndex = paramIndex; 2033 int revParamIndex = dispparams.cArgs - paramIndex - 1; 2034 if (Params[paramIndex].getValueType() 2035 == getCppuType((NamedArgument*) 0)) 2036 { 2037 //dispparams.rgdispidNamedArgs contains the mapping from index 2038 //of named args list to index of parameter list 2039 realParamIndex = dispparams.rgdispidNamedArgs[revParamIndex]; 2040 } 2041 2042 // no named arg, always come before named args 2043 if (! (aFuncDesc->lprgelemdescParam[realParamIndex].paramdesc.wParamFlags 2044 & PARAMFLAG_FOUT)) 2045 continue; 2046 Any outAny; 2047 // variantToAny is called with the "reduce range" parameter set to sal_False. 2048 // That causes VT_I4 values not to be converted down to a "lower" type. That 2049 // feature exist for JScript only because it only uses VT_I4 for integer types. 2050 try 2051 { 2052 variantToAny( & arRefArgs[revParamIndex], outAny, sal_False ); 2053 } 2054 catch (IllegalArgumentException & e) 2055 { 2056 e.ArgumentPosition = (sal_Int16)paramIndex; 2057 throw; 2058 } 2059 catch (CannotConvertException & e) 2060 { 2061 e.ArgumentIndex = paramIndex; 2062 throw; 2063 } 2064 OutParam[outParamIndex] = outAny; 2065 OutParamIndex[outParamIndex] = ::sal::static_int_cast< sal_Int16, int >( paramIndex ); 2066 outParamIndex++; 2067 } 2068 OutParam.realloc(outParamIndex); 2069 OutParamIndex.realloc(outParamIndex); 2070 } 2071 // Return value 2072 variantToAny(&varResult, ret, sal_False); 2073 } 2074 2075 // map error codes to exceptions 2076 OUString message; 2077 switch (result) 2078 { 2079 case S_OK: 2080 break; 2081 case DISP_E_BADPARAMCOUNT: 2082 throw IllegalArgumentException(OUSTR("[automation bridge] Wrong " 2083 "number of arguments. Object returned DISP_E_BADPARAMCOUNT."), 2084 0, 0); 2085 break; 2086 case DISP_E_BADVARTYPE: 2087 throw RuntimeException(OUSTR("[automation bridge] One or more " 2088 "arguments have the wrong type. Object returned " 2089 "DISP_E_BADVARTYPE."), 0); 2090 break; 2091 case DISP_E_EXCEPTION: 2092 message = OUSTR("[automation bridge]: "); 2093 message += OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription), 2094 ::SysStringLen(excepinfo.bstrDescription)); 2095 throw InvocationTargetException(message, Reference<XInterface>(), Any()); 2096 break; 2097 case DISP_E_MEMBERNOTFOUND: 2098 message = OUSTR("[automation bridge]: A function with the name \"") 2099 + sFuncName + OUSTR("\" is not supported. Object returned " 2100 "DISP_E_MEMBERNOTFOUND."); 2101 throw IllegalArgumentException(message, 0, 0); 2102 break; 2103 case DISP_E_NONAMEDARGS: 2104 throw IllegalArgumentException(OUSTR("[automation bridge] Object " 2105 "returned DISP_E_NONAMEDARGS"),0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); 2106 break; 2107 case DISP_E_OVERFLOW: 2108 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[automation bridge] Call failed.")), 2109 static_cast<XInterface*>( 2110 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr); 2111 break; 2112 case DISP_E_PARAMNOTFOUND: 2113 throw IllegalArgumentException(OUSTR("[automation bridge]Call failed." 2114 "Object returned DISP_E_PARAMNOTFOUND."), 2115 0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); 2116 break; 2117 case DISP_E_TYPEMISMATCH: 2118 throw CannotConvertException(OUSTR("[automation bridge] Call failed. " 2119 "Object returned DISP_E_TYPEMISMATCH"), 2120 static_cast<XInterface*>( 2121 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr); 2122 break; 2123 case DISP_E_UNKNOWNINTERFACE: 2124 throw RuntimeException(OUSTR("[automation bridge] Call failed. " 2125 "Object returned DISP_E_UNKNOWNINTERFACE."),0); 2126 break; 2127 case DISP_E_UNKNOWNLCID: 2128 throw RuntimeException(OUSTR("[automation bridge] Call failed. " 2129 "Object returned DISP_E_UNKNOWNLCID."),0); 2130 break; 2131 case DISP_E_PARAMNOTOPTIONAL: 2132 throw CannotConvertException(OUSTR("[automation bridge] Call failed." 2133 "Object returned DISP_E_PARAMNOTOPTIONAL"), 2134 static_cast<XInterface*>(static_cast<XWeak*>(this)), 2135 TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr); 2136 break; 2137 default: 2138 throw RuntimeException(); 2139 break; 2140 } 2141 2142 return ret; 2143 } 2144 2145 void IUnknownWrapper_Impl::getFuncDescForInvoke(const OUString & sFuncName, 2146 const Sequence<Any> & seqArgs, 2147 FUNCDESC** pFuncDesc) 2148 { 2149 int nUnoArgs = seqArgs.getLength(); 2150 const Any * arArgs = seqArgs.getConstArray(); 2151 ITypeInfo* pInfo = getTypeInfo(); 2152 2153 //If the last of the positional arguments is a PropertyPutArgument 2154 //then obtain the type info for the property put operation. 2155 2156 //The property value is always the last argument, in a positional argument list 2157 //or in a list of named arguments. A PropertyPutArgument is actually a named argument 2158 //hence it must not be put in an extra NamedArgument structure 2159 if (nUnoArgs > 0 && 2160 arArgs[nUnoArgs - 1].getValueType() == getCppuType((PropertyPutArgument*) 0)) 2161 { 2162 // DISPATCH_PROPERTYPUT 2163 FuncDesc aDescGet(pInfo); 2164 FuncDesc aDescPut(pInfo); 2165 VarDesc aVarDesc(pInfo); 2166 getPropDesc(sFuncName, & aDescGet, & aDescPut, & aVarDesc); 2167 if ( ! aDescPut) 2168 { 2169 throw IllegalArgumentException( 2170 OUSTR("[automation bridge] The object does not have a writeable property: ") 2171 + sFuncName, Reference<XInterface>(), 0); 2172 } 2173 *pFuncDesc = aDescPut.Detach(); 2174 } 2175 else 2176 { // DISPATCH_METHOD 2177 FuncDesc aFuncDesc(pInfo); 2178 getFuncDesc(sFuncName, & aFuncDesc); 2179 if ( ! aFuncDesc) 2180 { 2181 // Fallback: DISPATCH_PROPERTYGET can mostly be called as 2182 // DISPATCH_METHOD 2183 ITypeInfo * pInfo = getTypeInfo(); 2184 FuncDesc aDescPut(pInfo); 2185 VarDesc aVarDesc(pInfo); 2186 getPropDesc(sFuncName, & aFuncDesc, & aDescPut, & aVarDesc); 2187 if ( ! aFuncDesc ) 2188 { 2189 throw IllegalArgumentException( 2190 OUSTR("[automation bridge] The object does not have a function" 2191 "or readable property \"") 2192 + sFuncName, Reference<XInterface>(), 0); 2193 } 2194 } 2195 *pFuncDesc = aFuncDesc.Detach(); 2196 } 2197 } 2198 bool IUnknownWrapper_Impl::getDispid(const OUString& sFuncName, DISPID * id) 2199 { 2200 OSL_ASSERT(m_spDispatch); 2201 LPOLESTR lpsz = const_cast<LPOLESTR> (reinterpret_cast<LPCOLESTR>(sFuncName.getStr())); 2202 HRESULT hr = m_spDispatch->GetIDsOfNames(IID_NULL, &lpsz, 1, LOCALE_USER_DEFAULT, id); 2203 return hr == S_OK ? true : false; 2204 } 2205 void IUnknownWrapper_Impl::getFuncDesc(const OUString & sFuncName, FUNCDESC ** pFuncDesc) 2206 2207 { 2208 OSL_ASSERT( * pFuncDesc == 0); 2209 buildComTlbIndex(); 2210 typedef TLBFuncIndexMap::const_iterator cit; 2211 typedef TLBFuncIndexMap::iterator it; 2212 //We assume there is only one entry with the function name. A property 2213 //would have two entries. 2214 cit itIndex= m_mapComFunc.find(sFuncName); 2215 if (itIndex == m_mapComFunc.end()) 2216 { 2217 //try case insensive with IDispatch::GetIDsOfNames 2218 DISPID id; 2219 if (getDispid(sFuncName, &id)) 2220 { 2221 CComBSTR memberName; 2222 unsigned int pcNames=0; 2223 // get the case sensitive name 2224 if( SUCCEEDED(getTypeInfo()->GetNames( id, & memberName, 1, &pcNames))) 2225 { 2226 //get the associated index and add an entry to the map 2227 //with the name sFuncName which differs in the casing of the letters to 2228 //the actual name as obtained from ITypeInfo 2229 cit itOrg = m_mapComFunc.find(OUString(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName)))); 2230 OSL_ASSERT(itOrg != m_mapComFunc.end()); 2231 itIndex = 2232 m_mapComFunc.insert( TLBFuncIndexMap::value_type 2233 ( make_pair(sFuncName, itOrg->second ) )); 2234 } 2235 } 2236 } 2237 2238 #if OSL_DEBUG_LEVEL >= 1 2239 // There must only be one entry if sFuncName represents a function or two 2240 // if it is a property 2241 pair<cit, cit> p = m_mapComFunc.equal_range(sFuncName.toAsciiLowerCase()); 2242 int numEntries = 0; 2243 for ( ;p.first != p.second; p.first ++, numEntries ++); 2244 OSL_ASSERT( ! (numEntries > 3) ); 2245 #endif 2246 if( itIndex != m_mapComFunc.end()) 2247 { 2248 ITypeInfo* pType= getTypeInfo(); 2249 FUNCDESC * pDesc = NULL; 2250 if (SUCCEEDED(pType->GetFuncDesc(itIndex->second, & pDesc))) 2251 { 2252 if (pDesc->invkind == INVOKE_FUNC) 2253 { 2254 (*pFuncDesc) = pDesc; 2255 } 2256 else 2257 { 2258 pType->ReleaseFuncDesc(pDesc); 2259 } 2260 } 2261 else 2262 { 2263 throw BridgeRuntimeError(OUSTR("[automation bridge] Could not get " 2264 "FUNCDESC for ") + sFuncName); 2265 } 2266 } 2267 //else no entry found for sFuncName, pFuncDesc will not be filled in 2268 } 2269 2270 void IUnknownWrapper_Impl::getPropDesc(const OUString & sFuncName, FUNCDESC ** pFuncDescGet, 2271 FUNCDESC** pFuncDescPut, VARDESC** pVarDesc) 2272 { 2273 OSL_ASSERT( * pFuncDescGet == 0 && * pFuncDescPut == 0); 2274 buildComTlbIndex(); 2275 typedef TLBFuncIndexMap::const_iterator cit; 2276 pair<cit, cit> p = m_mapComFunc.equal_range(sFuncName); 2277 if (p.first == m_mapComFunc.end()) 2278 { 2279 //try case insensive with IDispatch::GetIDsOfNames 2280 DISPID id; 2281 if (getDispid(sFuncName, &id)) 2282 { 2283 CComBSTR memberName; 2284 unsigned int pcNames=0; 2285 // get the case sensitive name 2286 if( SUCCEEDED(getTypeInfo()->GetNames( id, & memberName, 1, &pcNames))) 2287 { 2288 //As opposed to getFuncDesc, we do not add the value because we would 2289 // need to find the get and set description for the property. This would 2290 //mean to iterate over all FUNCDESCs again. 2291 p = m_mapComFunc.equal_range(OUString(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName)))); 2292 } 2293 } 2294 } 2295 2296 for ( int i = 0 ;p.first != p.second; p.first ++, i ++) 2297 { 2298 // There are a maximum of two entries, property put and property get 2299 OSL_ASSERT( ! (i > 2) ); 2300 ITypeInfo* pType= getTypeInfo(); 2301 FUNCDESC * pFuncDesc = NULL; 2302 if (SUCCEEDED( pType->GetFuncDesc(p.first->second, & pFuncDesc))) 2303 { 2304 if (pFuncDesc->invkind == INVOKE_PROPERTYGET) 2305 { 2306 (*pFuncDescGet) = pFuncDesc; 2307 } 2308 else if (pFuncDesc->invkind == INVOKE_PROPERTYPUT || 2309 pFuncDesc->invkind == INVOKE_PROPERTYPUTREF) 2310 { 2311 //a property can have 3 entries, put, put ref, get 2312 // If INVOKE_PROPERTYPUTREF or INVOKE_PROPERTYPUT is used 2313 //depends on what is found first. 2314 if ( * pFuncDescPut) 2315 { 2316 //we already have found one 2317 pType->ReleaseFuncDesc(pFuncDesc); 2318 } 2319 else 2320 { 2321 (*pFuncDescPut) = pFuncDesc; 2322 } 2323 } 2324 else 2325 { 2326 pType->ReleaseFuncDesc(pFuncDesc); 2327 } 2328 } 2329 //ITypeInfo::GetFuncDesc may even provide a funcdesc for a VARDESC 2330 // with invkind = INVOKE_FUNC. Since this function should only return 2331 //a value for a real property (XInvokation::hasMethod, ..::hasProperty 2332 //we need to make sure that sFuncName represents a real property. 2333 VARDESC * pVD = NULL; 2334 if (SUCCEEDED(pType->GetVarDesc(p.first->second, & pVD))) 2335 (*pVarDesc) = pVD; 2336 } 2337 //else no entry for sFuncName, pFuncDesc will not be filled in 2338 } 2339 2340 VARTYPE IUnknownWrapper_Impl::getElementTypeDesc(const TYPEDESC *desc) 2341 { 2342 VARTYPE _type( VT_NULL ); 2343 2344 if (desc->vt == VT_PTR) 2345 { 2346 _type = getElementTypeDesc(desc->lptdesc); 2347 _type |= VT_BYREF; 2348 } 2349 else if (desc->vt == VT_SAFEARRAY) 2350 { 2351 _type = getElementTypeDesc(desc->lptdesc); 2352 _type |= VT_ARRAY; 2353 } 2354 else if (desc->vt == VT_USERDEFINED) 2355 { 2356 ITypeInfo* thisInfo = getTypeInfo(); //kept by this instance 2357 CComPtr<ITypeInfo> spRefInfo; 2358 thisInfo->GetRefTypeInfo(desc->hreftype, & spRefInfo.p); 2359 if (spRefInfo) 2360 { 2361 TypeAttr attr(spRefInfo); 2362 spRefInfo->GetTypeAttr( & attr); 2363 if (attr->typekind == TKIND_ENUM) 2364 { 2365 //We use the type of the first enum value. 2366 if (attr->cVars == 0) 2367 { 2368 throw BridgeRuntimeError(OUSTR("[automation bridge] Could " 2369 "not obtain type description")); 2370 } 2371 VarDesc var(spRefInfo); 2372 spRefInfo->GetVarDesc(0, & var); 2373 _type = var->lpvarValue->vt; 2374 } 2375 else if (attr->typekind == TKIND_INTERFACE) 2376 { 2377 _type = VT_UNKNOWN; 2378 } 2379 else if (attr->typekind == TKIND_DISPATCH) 2380 { 2381 _type = VT_DISPATCH; 2382 } 2383 else 2384 { 2385 throw BridgeRuntimeError(OUSTR("[automation bridge] " 2386 "Unhandled user defined type.")); 2387 } 2388 } 2389 } 2390 else 2391 { 2392 _type = desc->vt; 2393 } 2394 return _type; 2395 } 2396 2397 void IUnknownWrapper_Impl::buildComTlbIndex() 2398 { 2399 if ( ! m_bComTlbIndexInit) 2400 { 2401 MutexGuard guard(getBridgeMutex()); 2402 { 2403 if ( ! m_bComTlbIndexInit) 2404 { 2405 OUString sError; 2406 ITypeInfo* pType= getTypeInfo(); 2407 TypeAttr typeAttr(pType); 2408 if( SUCCEEDED( pType->GetTypeAttr( &typeAttr))) 2409 { 2410 for( long i= 0; i < typeAttr->cFuncs; i++) 2411 { 2412 FuncDesc funcDesc(pType); 2413 if( SUCCEEDED( pType->GetFuncDesc( i, &funcDesc))) 2414 { 2415 CComBSTR memberName; 2416 unsigned int pcNames=0; 2417 if( SUCCEEDED(pType->GetNames( funcDesc->memid, & memberName, 1, &pcNames))) 2418 { 2419 OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName))); 2420 m_mapComFunc.insert( TLBFuncIndexMap::value_type( usName, i)); 2421 } 2422 else 2423 { 2424 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \ 2425 "ITypeInfo::GetNames failed."); 2426 } 2427 } 2428 else 2429 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \ 2430 "ITypeInfo::GetFuncDesc failed."); 2431 } 2432 2433 //If we create an Object in JScript and a a property then it 2434 //has VARDESC instead of FUNCDESC 2435 for (long i = 0; i < typeAttr->cVars; i++) 2436 { 2437 VarDesc varDesc(pType); 2438 if (SUCCEEDED(pType->GetVarDesc(i, & varDesc))) 2439 { 2440 CComBSTR memberName; 2441 unsigned int pcNames = 0; 2442 if (SUCCEEDED(pType->GetNames(varDesc->memid, & memberName, 1, &pcNames))) 2443 { 2444 if (varDesc->varkind == VAR_DISPATCH) 2445 { 2446 OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName))); 2447 m_mapComFunc.insert(TLBFuncIndexMap::value_type( 2448 usName, i)); 2449 } 2450 } 2451 else 2452 { 2453 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \ 2454 "ITypeInfo::GetNames failed."); 2455 } 2456 } 2457 else 2458 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \ 2459 "ITypeInfo::GetVarDesc failed."); 2460 2461 } 2462 } 2463 else 2464 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \ 2465 "ITypeInfo::GetTypeAttr failed."); 2466 2467 if (sError.getLength()) 2468 { 2469 throw BridgeRuntimeError(sError); 2470 } 2471 2472 m_bComTlbIndexInit = true; 2473 } 2474 } 2475 } 2476 } 2477 2478 ITypeInfo* IUnknownWrapper_Impl::getTypeInfo() 2479 { 2480 if( !m_spDispatch) 2481 { 2482 throw BridgeRuntimeError(OUSTR("The object has no IDispatch interface!")); 2483 } 2484 2485 if( !m_spTypeInfo ) 2486 { 2487 MutexGuard guard(getBridgeMutex()); 2488 if( ! m_spTypeInfo) 2489 { 2490 CComPtr< ITypeInfo > spType; 2491 if( SUCCEEDED( m_spDispatch->GetTypeInfo( 0, LOCALE_USER_DEFAULT, &spType.p))) 2492 2493 { 2494 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 2495 2496 //If this is a dual interface then TYPEATTR::typekind is usually TKIND_INTERFACE 2497 //We need to get the type description for TKIND_DISPATCH 2498 TypeAttr typeAttr(spType.p); 2499 if( SUCCEEDED(spType->GetTypeAttr( &typeAttr))) 2500 { 2501 if (typeAttr->typekind == TKIND_INTERFACE && 2502 typeAttr->wTypeFlags & TYPEFLAG_FDUAL) 2503 { 2504 HREFTYPE refDispatch; 2505 if (SUCCEEDED(spType->GetRefTypeOfImplType(::sal::static_int_cast< UINT, int >( -1 ), &refDispatch))) 2506 { 2507 CComPtr<ITypeInfo> spTypeDisp; 2508 if (SUCCEEDED(spType->GetRefTypeInfo(refDispatch, & spTypeDisp))) 2509 m_spTypeInfo= spTypeDisp; 2510 } 2511 else 2512 { 2513 throw BridgeRuntimeError( 2514 OUSTR("[automation bridge] Could not obtain type information " 2515 "for dispatch interface." )); 2516 } 2517 } 2518 else if (typeAttr->typekind == TKIND_DISPATCH) 2519 { 2520 m_spTypeInfo= spType; 2521 } 2522 else 2523 { 2524 throw BridgeRuntimeError( 2525 OUSTR("[automation bridge] Automation object does not " 2526 "provide type information.")); 2527 } 2528 } 2529 } 2530 else 2531 { 2532 throw BridgeRuntimeError(OUSTR("[automation bridge]The dispatch object does not " 2533 "support ITypeInfo!")); 2534 } 2535 } 2536 } 2537 return m_spTypeInfo; 2538 } 2539 2540 } // end namespace 2541 2542