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