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