1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_extensions.hxx" 30 31 #include "ole2uno.hxx" 32 #include <stdio.h> 33 #include <tools/presys.h> 34 #include <olectl.h> 35 #include <vector> 36 #include <list> 37 #include <hash_map> 38 #include "comifaces.hxx" 39 #include <tools/postsys.h> 40 41 42 #include <vos/diagnose.hxx> 43 #include <vos/refernce.hxx> 44 #include <tools/debug.hxx> 45 #include <rtl/ustring.hxx> 46 #include <com/sun/star/beans/MethodConcept.hpp> 47 #include <com/sun/star/beans/PropertyConcept.hpp> 48 #include <com/sun/star/script/FailReason.hpp> 49 #include <com/sun/star/reflection/ParamInfo.hpp> 50 #include <com/sun/star/beans/XExactName.hpp> 51 #include <com/sun/star/container/NoSuchElementException.hpp> 52 53 #include <com/sun/star/beans/XMaterialHolder.hpp> 54 #include <com/sun/star/script/XInvocation2.hpp> 55 #include <com/sun/star/script/MemberType.hpp> 56 #include <com/sun/star/reflection/XIdlReflection.hpp> 57 #include <osl/interlck.h> 58 #include <com/sun/star/uno/genfunc.h> 59 #include <cppuhelper/implbase1.hxx> 60 61 #include "comifaces.hxx" 62 #include "jscriptclasses.hxx" 63 #include "unotypewrapper.hxx" 64 #include "oleobjw.hxx" 65 #include "unoobjw.hxx" 66 #include "servprov.hxx" 67 68 using namespace vos; 69 using namespace std; 70 using namespace rtl; 71 using namespace osl; 72 using namespace cppu; 73 using namespace com::sun::star::uno; 74 using namespace com::sun::star::beans; 75 using namespace com::sun::star::container; 76 using namespace com::sun::star::script; 77 using namespace com::sun::star::lang; 78 using namespace com::sun::star::bridge::ModelDependent; 79 using namespace com::sun::star::reflection; 80 81 82 83 #if _MSC_VER < 1200 84 extern "C" const GUID IID_IDispatchEx; 85 #endif 86 87 namespace ole_adapter 88 { 89 hash_map<sal_uInt32, WeakReference<XInterface> > UnoObjToWrapperMap; 90 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource); 91 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource); 92 static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr); 93 94 95 /* Does not throw any exceptions. 96 Param pInfo can be NULL. 97 */ 98 static void writeExcepinfo(EXCEPINFO * pInfo, const OUString& message) 99 { 100 if (pInfo != NULL) 101 { 102 pInfo->wCode = UNO_2_OLE_EXCEPTIONCODE; 103 pInfo->bstrSource = SysAllocString(L"[automation bridge] "); 104 pInfo->bstrDescription = SysAllocString(reinterpret_cast<LPCOLESTR>(message.getStr())); 105 } 106 } 107 108 /***************************************************************************** 109 110 class implementation: InterfaceOleWrapper_Impl 111 112 *****************************************************************************/ 113 InterfaceOleWrapper_Impl::InterfaceOleWrapper_Impl( Reference<XMultiServiceFactory>& xFactory, 114 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass): 115 m_defaultValueType( 0), 116 UnoConversionUtilities<InterfaceOleWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass) 117 { 118 } 119 120 InterfaceOleWrapper_Impl::~InterfaceOleWrapper_Impl() 121 { 122 MutexGuard guard(getBridgeMutex()); 123 // remove entries in global map 124 IT_Uno it= UnoObjToWrapperMap.find( (sal_uInt32) m_xOrigin.get()); 125 if(it != UnoObjToWrapperMap.end()) 126 UnoObjToWrapperMap.erase(it); 127 #if OSL_DEBUG_LEVEL > 0 128 fprintf(stderr,"[automation bridge] UnoObjToWrapperMap contains: %i \n", 129 UnoObjToWrapperMap.size()); 130 #endif 131 132 } 133 134 STDMETHODIMP InterfaceOleWrapper_Impl::QueryInterface(REFIID riid, LPVOID FAR * ppv) 135 { 136 HRESULT ret= S_OK; 137 138 if( !ppv) 139 return E_POINTER; 140 141 if(IsEqualIID(riid, IID_IUnknown)) 142 { 143 AddRef(); 144 *ppv = (IUnknown*) (IDispatch*) this; 145 } 146 else if (IsEqualIID(riid, IID_IDispatch)) 147 { 148 AddRef(); 149 *ppv = (IDispatch*) this; 150 } 151 else if( IsEqualIID( riid, __uuidof( IUnoObjectWrapper))) 152 { 153 AddRef(); 154 *ppv= (IUnoObjectWrapper*) this; 155 } 156 else 157 ret= E_NOINTERFACE; 158 return ret; 159 } 160 161 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::AddRef() 162 { 163 acquire(); 164 // does not need to guard because one should not rely on the return value of 165 // AddRef anyway 166 return m_refCount; 167 } 168 169 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::Release() 170 { 171 ULONG n= m_refCount; 172 release(); 173 return n - 1; 174 } 175 176 // IUnoObjectWrapper -------------------------------------------------------- 177 STDMETHODIMP InterfaceOleWrapper_Impl::getWrapperXInterface( Reference<XInterface>* pXInt) 178 { 179 *pXInt= Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY); 180 return pXInt->is() ? S_OK : E_FAIL; 181 } 182 STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoObject( Reference<XInterface>* pXInt) 183 { 184 *pXInt= m_xOrigin; 185 return m_xOrigin.is() ? S_OK : E_FAIL; 186 } 187 STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoStruct( Any * pStruct) 188 { 189 HRESULT ret= E_FAIL; 190 if( !m_xOrigin.is()) 191 { 192 Reference<XMaterialHolder> xMatHolder( m_xInvocation, UNO_QUERY); 193 if( xMatHolder.is()) 194 { 195 Any any = xMatHolder->getMaterial(); 196 if( any.getValueTypeClass() == TypeClass_STRUCT) 197 { 198 *pStruct= any; 199 ret= S_OK; 200 } 201 } 202 } 203 return ret; 204 } 205 206 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfoCount( unsigned int * /*pctinfo*/ ) 207 { 208 return E_NOTIMPL ; 209 } 210 211 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfo(unsigned int /*itinfo*/, LCID /*lcid*/, ITypeInfo ** /*pptinfo*/) 212 { 213 return E_NOTIMPL; 214 } 215 216 STDMETHODIMP InterfaceOleWrapper_Impl::GetIDsOfNames(REFIID /*riid*/, 217 OLECHAR ** rgszNames, 218 unsigned int cNames, 219 LCID /*lcid*/, 220 DISPID * rgdispid ) 221 { 222 HRESULT ret = DISP_E_UNKNOWNNAME; 223 try 224 { 225 MutexGuard guard( getBridgeMutex()); 226 if( ! rgdispid) 227 return E_POINTER; 228 229 // ---------------------------------------- 230 if( ! _wcsicmp( *rgszNames, JSCRIPT_VALUE_FUNC) || 231 ! _wcsicmp( *rgszNames, BRIDGE_VALUE_FUNC)) 232 { 233 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC; 234 return S_OK; 235 } 236 else if( ! _wcsicmp( *rgszNames, GET_STRUCT_FUNC) || 237 ! _wcsicmp( *rgszNames, BRIDGE_GET_STRUCT_FUNC)) 238 { 239 *rgdispid= DISPID_GET_STRUCT_FUNC; 240 return S_OK; 241 } 242 else if( ! _wcsicmp( *rgszNames, BRIDGE_CREATE_TYPE_FUNC)) 243 { 244 *rgdispid= DISPID_CREATE_TYPE_FUNC; 245 return S_OK; 246 } 247 248 // ---------------------------------------- 249 if (m_xInvocation.is() && (cNames > 0)) 250 { 251 OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0])); 252 NameToIdMap::iterator iter = m_nameToDispIdMap.find(name); 253 254 if (iter == m_nameToDispIdMap.end()) 255 { 256 OUString exactName; 257 258 if (m_xExactName.is()) 259 { 260 exactName = m_xExactName->getExactName(name); 261 } 262 else 263 { 264 exactName = name; 265 } 266 267 MemberInfo d(0, exactName); 268 269 if (m_xInvocation->hasProperty(exactName)) 270 { 271 d.flags |= DISPATCH_PROPERTYGET; 272 d.flags |= DISPATCH_PROPERTYPUT; 273 d.flags |= DISPATCH_PROPERTYPUTREF; 274 } 275 276 if (m_xInvocation->hasMethod(exactName)) 277 { 278 d.flags |= DISPATCH_METHOD; 279 } 280 281 if (d.flags != 0) 282 { 283 m_MemberInfos.push_back(d); 284 iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(exactName, (DISPID)m_MemberInfos.size())).first; 285 286 if (exactName != name) 287 { 288 iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(name, (DISPID)m_MemberInfos.size())).first; 289 } 290 } 291 } 292 293 if (iter == m_nameToDispIdMap.end()) 294 { 295 ret = DISP_E_UNKNOWNNAME; 296 } 297 else 298 { 299 *rgdispid = (*iter).second; 300 ret = S_OK; 301 } 302 } 303 } 304 catch(BridgeRuntimeError& ) 305 { 306 OSL_ASSERT(0); 307 } 308 catch(Exception& ) 309 { 310 OSL_ASSERT(0); 311 } 312 catch(...) 313 { 314 OSL_ASSERT(0); 315 } 316 317 return ret; 318 } 319 320 // "convertDispparamsArgs" converts VARIANTS to their respecting Any counterparts 321 // The parameters "id", "wFlags" and "pdispparams" equal those as used in 322 // IDispatch::Invoke. The function handles special JavaScript 323 // cases where a VARIANT of type VT_DISPATCH is ambiguous and could represent 324 // an object, array ( JavaScript Array object), out parameter and in/out ( JavaScript Array object) 325 // parameter (JavaScript Array object) 326 // Because all those VT_DISPATCH objects need a different conversion 327 // we have to find out what the object is supposed to be. The function does this 328 // by either using type information or by help of a specialized ValueObject object. 329 330 // A. Type Information 331 // ----------------------------------------------------------------------------- 332 // With the help of type information the kind of parameter can be exactly determined 333 // and an appropriate conversion can be choosen. A problem arises if a method expects 334 // an Any. Then the type info does not tell what the type of the value, that is kept 335 // by the any, should be. In this situation the decision wheter the param is a 336 // sequence or an object is made upon the fact if the object has a property "0" 337 // ( see function "isJScriptArray"). Since this is unsafe it is recommended to use 338 // the JScript value objects within a JScript script on such an occasion. 339 340 // B. JavaScript Value Object ( class JScriptValue ) 341 // ----------------------------------------------------------------------------- 342 // A JScriptValue (ValueObject) object is a COM object in that it implements IDispatch and the 343 // IJScriptValue object interface. Such objects are provided by all UNO wrapper 344 // objects used within a JScript script. To obtain an instance one has to call 345 // "_GetValueObject() or Bridge_GetValueObject()" on an UNO wrapper object (class InterfaceOleWrapper_Impl). 346 // A value object is appropriately initialized within the script and passed as 347 // parameter to an UNO object method or property. The convertDispparamsArgs function 348 // can easily find out that a param is such an object by queriing for the 349 // IJScriptValue interface. By this interface one the type and kind ( out, in/out) 350 // can be determined and the right conversion can be applied. 351 // Using ValueObjects we spare us the effort of aquiring and examining type information 352 // in order to figure out what the an IDispatch parameter is meant for. 353 354 // Normal JScript object parameter can be mixed with JScriptValue object. If an 355 // VARIANT contains an VT_DISPATCH that is no JScriptValue than the type information 356 // is used to find out about the reqired type. 357 void InterfaceOleWrapper_Impl::convertDispparamsArgs(DISPID id, 358 unsigned short /*wFlags*/, DISPPARAMS* pdispparams, Sequence<Any>& rSeq) 359 { 360 HRESULT hr= S_OK; 361 sal_Int32 countArgs= pdispparams->cArgs; 362 if( countArgs == 0) 363 return; 364 365 rSeq.realloc( countArgs); 366 Any* pParams = rSeq.getArray(); 367 368 Any anyParam; 369 370 //Get type information for the current call 371 InvocationInfo info; 372 if( ! getInvocationInfoForCall( id, info)) 373 throw BridgeRuntimeError( 374 OUSTR("[automation bridge]InterfaceOleWrapper_Impl::convertDispparamsArgs \n" 375 "Could not obtain type information for current call.")); 376 377 for (int i = 0; i < countArgs; i++) 378 { 379 if (info.eMemberType == MemberType_METHOD && 380 info.aParamModes[ countArgs - i -1 ] == ParamMode_OUT) 381 continue; 382 383 if(convertValueObject( & pdispparams->rgvarg[i], anyParam)) 384 { //a param is a ValueObject and could be converted 385 pParams[countArgs - (i + 1)] = anyParam; 386 continue; 387 } 388 389 // If the param is an out, in/out parameter in 390 // JScript (Array object, with value at index 0) then we 391 // extract Array[0] and put the value into varParam. At the end of the loop varParam 392 // is converted if it contains a value otherwise the VARIANT from 393 // DISPPARAMS is converted. 394 CComVariant varParam; 395 396 // Check for JScript out and in/out paramsobjects (VT_DISPATCH). 397 // To find them out we use typeinformation of the function being called. 398 if( pdispparams->rgvarg[i].vt == VT_DISPATCH ) 399 { 400 if( info.eMemberType == MemberType_METHOD && info.aParamModes[ countArgs - i -1 ] == ParamMode_INOUT) 401 { 402 // INOUT-param 403 // Index ( property) "0" contains the actual IN-param. The object is a JScript 404 // Array object. 405 // Get the IN-param at index "0" 406 IDispatch* pdisp= pdispparams->rgvarg[i].pdispVal; 407 408 OLECHAR* sindex= L"0"; 409 DISPID id; 410 DISPPARAMS noParams= {0,0,0,0}; 411 if(SUCCEEDED( hr= pdisp->GetIDsOfNames( IID_NULL, &sindex, 1, LOCALE_USER_DEFAULT, &id))) 412 hr= pdisp->Invoke( id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, 413 & noParams, & varParam, NULL, NULL); 414 if( FAILED( hr)) 415 { 416 throw BridgeRuntimeError( 417 OUSTR("[automation bridge] Could not determine " 418 "if the object has a member \"0\". Error: ") + 419 OUString::valueOf(hr)); 420 } 421 } 422 } 423 424 if( varParam.vt == VT_EMPTY) // then it was no in/out parameter 425 varParam= pdispparams->rgvarg[i]; 426 427 if(info.eMemberType == MemberType_METHOD) 428 variantToAny( & varParam, anyParam, 429 info.aParamTypes[ countArgs - i - 1]); 430 else if(info.eMemberType == MemberType_PROPERTY) 431 variantToAny( & varParam, anyParam, info.aType); 432 else 433 OSL_ASSERT(0); 434 435 pParams[countArgs - (i + 1)]= anyParam; 436 }// end for / iterating over all parameters 437 } 438 439 sal_Bool InterfaceOleWrapper_Impl::getInvocationInfoForCall( DISPID id, InvocationInfo& info) 440 { 441 sal_Bool bTypesAvailable= sal_False; 442 443 if( !m_xInvocation.is() )return false; 444 Reference<XInvocation2> inv2( m_xInvocation, UNO_QUERY); 445 if( inv2.is()) 446 { 447 // We need the name of the property or method to get its type information. 448 // The name can be identified through the param "id" 449 // that is kept as value in the map m_nameToDispIdMap. 450 // Proplem: the Windows JScript engine sometimes changes small letters to capital 451 // letters as happens in xidlclass_obj.createObject( var) // in JScript. 452 // IDispatch::GetIdsOfNames is then called with "CreateObject" !!! 453 // m_nameToDispIdMap can contain several names for one DISPID but only one is 454 // the exact one. If there's no m_xExactName and therefore no exact name then 455 // there's only one entry in the map. 456 typedef NameToIdMap::const_iterator cit; 457 OUString sMemberName; 458 459 for(cit ci1= m_nameToDispIdMap.begin(); ci1 != m_nameToDispIdMap.end(); ci1++) 460 { 461 if( (*ci1).second == id) // iterator is a pair< OUString, DISPID> 462 { 463 sMemberName= (*ci1).first; 464 break; 465 } 466 } 467 // Get information for the current call ( property or method). 468 // There could be similar names which only differ in the cases 469 // of letters. First we assume that the name which was passed into 470 // GetIDsOfNames is correct. If we won't get information with that 471 // name then we have the invocation service use the XExactName interface. 472 sal_Bool validInfo= sal_True; 473 InvocationInfo invInfo; 474 try{ 475 invInfo= inv2->getInfoForName( sMemberName, sal_False); 476 } 477 catch( IllegalArgumentException ) 478 { 479 validInfo= sal_False; 480 } 481 482 if( ! validInfo) 483 { 484 invInfo= inv2->getInfoForName( sMemberName, sal_True); 485 } 486 if( invInfo.aName.pData) 487 { 488 bTypesAvailable= sal_True; 489 info= invInfo; 490 } 491 } 492 return bTypesAvailable; 493 } 494 // XBridgeSupplier2 --------------------------------------------------- 495 // only bridges itself ( this instance of InterfaceOleWrapper_Impl)from UNO to IDispatch 496 // If sourceModelType is UNO than any UNO interface implemented by InterfaceOleWrapper_Impl 497 // can bridged to IDispatch ( if destModelType == OLE). The IDispatch is 498 // implemented by this class. 499 Any SAL_CALL InterfaceOleWrapper_Impl::createBridge(const Any& modelDepObject, 500 const Sequence<sal_Int8>& /*ProcessId*/, 501 sal_Int16 sourceModelType, 502 sal_Int16 destModelType) 503 throw (IllegalArgumentException, RuntimeException) 504 { 505 506 Any retAny; 507 if( sourceModelType == UNO && destModelType == OLE && 508 modelDepObject.getValueTypeClass() == TypeClass_INTERFACE ) 509 { 510 Reference<XInterface> xInt; 511 if( modelDepObject >>= xInt ) 512 { 513 if( xInt == Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY)) 514 { 515 VARIANT *pVar= (VARIANT*)CoTaskMemAlloc( sizeof( VARIANT)); 516 if( pVar) 517 { 518 pVar->vt= VT_DISPATCH; 519 pVar->pdispVal= static_cast<IDispatch*>( this); 520 AddRef(); 521 522 retAny<<= reinterpret_cast< sal_uInt32 >( pVar); 523 } 524 } 525 } 526 } 527 528 return retAny; 529 } 530 531 532 // XInitialization -------------------------------------------------- 533 void SAL_CALL InterfaceOleWrapper_Impl::initialize( const Sequence< Any >& aArguments ) 534 throw(Exception, RuntimeException) 535 { 536 switch( aArguments.getLength() ) 537 { 538 case 2: // the object wraps an UNO struct 539 aArguments[0] >>= m_xInvocation; 540 aArguments[1] >>= m_defaultValueType; 541 break; 542 case 3: // the object wraps an UNO interface 543 aArguments[0] >>= m_xInvocation; 544 aArguments[1] >>= m_xOrigin; 545 aArguments[2] >>= m_defaultValueType; 546 break; 547 } 548 549 m_xExactName= Reference<XExactName>( m_xInvocation, UNO_QUERY); 550 } 551 552 Reference< XInterface > InterfaceOleWrapper_Impl::createUnoWrapperInstance() 553 { 554 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl( 555 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); 556 return Reference<XInterface>( xWeak, UNO_QUERY); 557 } 558 559 Reference<XInterface> InterfaceOleWrapper_Impl::createComWrapperInstance() 560 { 561 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl( 562 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); 563 return Reference<XInterface>( xWeak, UNO_QUERY); 564 } 565 566 567 568 // "getType" is used in convertValueObject to map the string denoting the type 569 // to an actual Type object. 570 bool getType( const BSTR name, Type & type) 571 { 572 Type retType; 573 bool ret = false; 574 typelib_TypeDescription * pDesc= NULL; 575 OUString str( reinterpret_cast<const sal_Unicode*>(name)); 576 typelib_typedescription_getByName( &pDesc, str.pData ); 577 if( pDesc) 578 { 579 type = Type( pDesc->pWeakRef ); 580 typelib_typedescription_release( pDesc); 581 ret = true; 582 } 583 return ret; 584 } 585 586 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource) 587 { 588 sal_Bool ret = sal_False; 589 HRESULT hr; 590 591 // Handle JScriptValue objects and JScript out params ( Array object ) 592 CComVariant varDest( *pDest); 593 594 if( SUCCEEDED( varDest.ChangeType(VT_DISPATCH))) 595 { 596 CComPtr<IDispatch> spDispDest(varDest.pdispVal); 597 598 // special Handling for a JScriptValue object 599 #ifdef __MINGW32__ 600 CComQIPtr<IJScriptValueObject, &__uuidof(IJScriptValueObject)> spValueDest(spDispDest); 601 #else 602 CComQIPtr<IJScriptValueObject> spValueDest(spDispDest); 603 #endif 604 if (spValueDest) 605 { 606 VARIANT_BOOL varBool= VARIANT_FALSE; 607 if( SUCCEEDED( hr= spValueDest->IsOutParam( &varBool) ) 608 && varBool == VARIANT_TRUE || 609 SUCCEEDED(hr= spValueDest->IsInOutParam( &varBool) ) 610 && varBool == VARIANT_TRUE ) 611 { 612 if( SUCCEEDED( spValueDest->Set( CComVariant(), *pSource))) 613 ret= sal_True; 614 } 615 } 616 else if (pDest->vt == VT_DISPATCH)// VT_DISPATCH -> JScript out param 617 { 618 // We use IDispatchEx because its GetDispID function causes the creation 619 // of a property if it does not exist already. This is convenient for 620 // out parameters in JScript. Then the user must not specify propery "0" 621 // explicitly 622 #ifdef __MINGW32__ 623 CComQIPtr<IDispatchEx, &__uuidof(IDispatchEx)> spDispEx( spDispDest); 624 #else 625 CComQIPtr<IDispatchEx> spDispEx( spDispDest); 626 #endif 627 if( spDispEx) 628 { 629 CComBSTR nullProp(L"0"); 630 DISPID dwDispID; 631 if( SUCCEEDED( spDispEx->GetDispID( nullProp, fdexNameEnsure, &dwDispID))) 632 { 633 DISPPARAMS dispparams = {NULL, NULL, 1, 1}; 634 dispparams.rgvarg = pSource; 635 DISPID dispidPut = DISPID_PROPERTYPUT; 636 dispparams.rgdispidNamedArgs = &dispidPut; 637 638 if (pSource->vt == VT_UNKNOWN || pSource->vt == VT_DISPATCH || 639 (pSource->vt & VT_ARRAY) || (pSource->vt & VT_BYREF)) 640 hr = spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, 641 &dispparams, NULL, NULL, NULL); 642 else 643 hr= spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, 644 &dispparams, NULL, NULL, NULL); 645 if( SUCCEEDED(hr)) 646 ret= sal_True; 647 } 648 } 649 } 650 else 651 ret= writeBackOutParameter( pDest, pSource); 652 } 653 else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript 654 { // param. The function checks itself for correct VBScript params 655 ret= writeBackOutParameter( pDest, pSource); 656 } 657 return ret; 658 } 659 // VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter. 660 // Thus we are in charge of freeing an eventual value contained by the inner VARIANT 661 // Please note: VariantCopy doesn't free a VT_BYREF value 662 // The out parameters are expected to have always a valid type 663 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource) 664 { 665 HRESULT hr; 666 sal_Bool ret = FALSE; 667 // Out parameter must be VT_BYREF 668 if ((V_VT(pDest) & VT_BYREF) != 0 ) 669 { 670 VARTYPE oleTypeFlags = V_VT(pSource); 671 672 // if caller accept VARIANT as out parameter, any value must be converted 673 if (V_VT(pDest) == (VT_VARIANT | VT_BYREF)) 674 { 675 // When the user provides a VARIANT rather then a concrete type 676 // we just copy the source to the out, in/out parameter 677 // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that 678 // is contained in pDest are released by VariantCopy 679 VariantCopy(V_VARIANTREF(pDest), pSource); 680 ret = sal_True; 681 } 682 else 683 { 684 // variantarg and variant must have same type 685 if ((V_VT(pDest) & oleTypeFlags) == oleTypeFlags) 686 { 687 if ((oleTypeFlags & VT_ARRAY) != 0) 688 { 689 // In / Out Param 690 if( *V_ARRAYREF(pDest) != NULL) 691 hr= SafeArrayCopyData( V_ARRAY(pSource), *V_ARRAYREF(pDest)); 692 else 693 // Out Param 694 hr= SafeArrayCopy(V_ARRAY(pSource), V_ARRAYREF(pDest)) == NOERROR; 695 if( SUCCEEDED( hr)) 696 ret = sal_True; 697 } 698 else 699 { 700 // copy base type 701 switch (V_VT(pSource)) 702 { 703 case VT_I2: 704 { 705 *V_I2REF(pDest) = V_I2(pSource); 706 ret = sal_True; 707 break; 708 } 709 case VT_I4: 710 *V_I4REF(pDest) = V_I4(pSource); 711 ret = sal_True; 712 break; 713 case VT_R4: 714 *V_R4REF(pDest) = V_R4(pSource); 715 ret = sal_True; 716 break; 717 case VT_R8: 718 *V_R8REF(pDest) = V_R8(pSource); 719 ret = sal_True; 720 break; 721 case VT_CY: 722 *V_CYREF(pDest) = V_CY(pSource); 723 ret = sal_True; 724 break; 725 case VT_DATE: 726 *V_DATEREF(pDest) = V_DATE(pSource); 727 ret = sal_True; 728 break; 729 case VT_BSTR: 730 SysFreeString( *pDest->pbstrVal); 731 732 *V_BSTRREF(pDest) = SysAllocString(V_BSTR(pSource)); 733 ret = sal_True; 734 break; 735 case VT_DISPATCH: 736 if (*V_DISPATCHREF(pDest) != NULL) 737 (*V_DISPATCHREF(pDest))->Release(); 738 739 *V_DISPATCHREF(pDest) = V_DISPATCH(pSource); 740 741 if (*V_DISPATCHREF(pDest) != NULL) 742 (*V_DISPATCHREF(pDest))->AddRef(); 743 744 ret = sal_True; 745 break; 746 case VT_ERROR: 747 *V_ERRORREF(pDest) = V_ERROR(pSource); 748 ret = sal_True; 749 break; 750 case VT_BOOL: 751 *V_BOOLREF(pDest) = V_BOOL(pSource); 752 ret = sal_True; 753 break; 754 case VT_UNKNOWN: 755 if (*V_UNKNOWNREF(pDest) != NULL) 756 (*V_UNKNOWNREF(pDest))->Release(); 757 758 *V_UNKNOWNREF(pDest) = V_UNKNOWN(pSource); 759 760 if (*V_UNKNOWNREF(pDest) != NULL) 761 (*V_UNKNOWNREF(pDest))->AddRef(); 762 763 ret = sal_True; 764 break; 765 case VT_I1: 766 *V_I1REF(pDest) = V_I1(pSource); 767 ret = sal_True; 768 break; 769 case VT_UI1: 770 *V_UI1REF(pDest) = V_UI1(pSource); 771 ret = sal_True; 772 break; 773 case VT_UI2: 774 *V_UI2REF(pDest) = V_UI2(pSource); 775 ret = sal_True; 776 break; 777 case VT_UI4: 778 *V_UI4REF(pDest) = V_UI4(pSource); 779 ret = sal_True; 780 break; 781 case VT_INT: 782 *V_INTREF(pDest) = V_INT(pSource); 783 ret = sal_True; 784 break; 785 case VT_UINT: 786 *V_UINTREF(pDest) = V_UINT(pSource); 787 ret = sal_True; 788 break; 789 case VT_DECIMAL: 790 memcpy(pDest->pdecVal, pSource, sizeof(DECIMAL)); 791 ret = sal_True; 792 break; 793 default: 794 break; 795 } 796 } 797 } 798 else 799 { 800 // Handling of special cases 801 // Destination and source types are different 802 if( pDest->vt == (VT_BSTR | VT_BYREF) 803 && pSource->vt == VT_I2) 804 { 805 // When the user provides a String as out our in/out parameter 806 // and the type is char (TypeClass_CHAR) then we convert to a BSTR 807 // instead of VT_I2 as is done otherwise 808 OLECHAR buff[]= {0,0}; 809 buff[0]= pSource->iVal; 810 811 SysFreeString( *pDest->pbstrVal); 812 *pDest->pbstrVal= SysAllocString( buff); 813 ret = sal_True; 814 } 815 } 816 } 817 } 818 return ret; 819 } 820 821 STDMETHODIMP InterfaceOleWrapper_Impl::Invoke(DISPID dispidMember, 822 REFIID /*riid*/, 823 LCID /*lcid*/, 824 unsigned short wFlags, 825 DISPPARAMS * pdispparams, 826 VARIANT * pvarResult, 827 EXCEPINFO * pexcepinfo, 828 unsigned int * puArgErr ) 829 { 830 HRESULT ret = S_OK; 831 832 try 833 { 834 sal_Bool bHandled= sal_False; 835 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, 836 puArgErr, bHandled); 837 if( bHandled) 838 return ret; 839 840 if ((dispidMember > 0) && ((size_t)dispidMember <= m_MemberInfos.size()) && m_xInvocation.is()) 841 { 842 MemberInfo d = m_MemberInfos[dispidMember - 1]; 843 DWORD flags = wFlags & d.flags; 844 845 if (flags != 0) 846 { 847 if ((flags & DISPATCH_METHOD) != 0) 848 { 849 if (pdispparams->cNamedArgs > 0) 850 ret = DISP_E_NONAMEDARGS; 851 else 852 { 853 Sequence<Any> params; 854 855 convertDispparamsArgs(dispidMember, wFlags, pdispparams , params ); 856 857 ret= doInvoke(pdispparams, pvarResult, 858 pexcepinfo, puArgErr, d.name, params); 859 } 860 } 861 else if ((flags & DISPATCH_PROPERTYGET) != 0) 862 { 863 ret= doGetProperty( pdispparams, pvarResult, 864 pexcepinfo, d.name); 865 } 866 else if ((flags & DISPATCH_PROPERTYPUT || flags & DISPATCH_PROPERTYPUTREF) != 0) 867 { 868 if (pdispparams->cArgs != 1) 869 ret = DISP_E_BADPARAMCOUNT; 870 else 871 { 872 Sequence<Any> params; 873 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 874 if(params.getLength() > 0) 875 ret= doSetProperty( pdispparams, pvarResult, pexcepinfo, puArgErr, d.name, params); 876 else 877 ret = DISP_E_BADVARTYPE; 878 } 879 } 880 } 881 else 882 ret= DISP_E_MEMBERNOTFOUND; 883 } 884 else 885 ret = DISP_E_MEMBERNOTFOUND; 886 } 887 catch(BridgeRuntimeError& e) 888 { 889 writeExcepinfo(pexcepinfo, e.message); 890 ret = DISP_E_EXCEPTION; 891 } 892 catch(Exception& e) 893 { 894 OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n") + 895 e.Message; 896 writeExcepinfo(pexcepinfo, message); 897 ret = DISP_E_EXCEPTION; 898 } 899 catch(...) 900 { 901 OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n" 902 "Unexpected exception"); 903 writeExcepinfo(pexcepinfo, message); 904 ret = DISP_E_EXCEPTION; 905 } 906 907 return ret; 908 } 909 910 HRESULT InterfaceOleWrapper_Impl::doInvoke( DISPPARAMS * pdispparams, VARIANT * pvarResult, 911 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any>& params) 912 { 913 914 915 HRESULT ret= S_OK; 916 try 917 { 918 Sequence<sal_Int16> outIndex; 919 Sequence<Any> outParams; 920 Any returnValue; 921 922 if (pdispparams->cNamedArgs > 0) 923 return DISP_E_NONAMEDARGS; 924 925 // invoke method and take care of exceptions 926 returnValue = m_xInvocation->invoke(name, 927 params, 928 outIndex, 929 outParams); 930 931 // try to write back out parameter 932 if (outIndex.getLength() > 0) 933 { 934 const sal_Int16* pOutIndex = outIndex.getConstArray(); 935 const Any* pOutParams = outParams.getConstArray(); 936 937 for (sal_Int32 i = 0; i < outIndex.getLength(); i++) 938 { 939 CComVariant variant; 940 // Currently a Sequence is converted to an SafeArray of VARIANTs. 941 anyToVariant( &variant, pOutParams[i]); 942 943 // out parameter need special handling if they are VT_DISPATCH 944 // and used in JScript 945 int outindex= pOutIndex[i]; 946 writeBackOutParameter2(&(pdispparams->rgvarg[pdispparams->cArgs - 1 - outindex]), 947 &variant ); 948 } 949 } 950 951 // write back return value 952 if (pvarResult != NULL) 953 anyToVariant(pvarResult, returnValue); 954 } 955 catch(IllegalArgumentException & e) //XInvocation::invoke 956 { 957 writeExcepinfo(pexcepinfo, e.Message); 958 ret = DISP_E_TYPEMISMATCH; 959 } 960 catch(CannotConvertException & e) //XInvocation::invoke 961 { 962 writeExcepinfo(pexcepinfo, e.Message); 963 ret = mapCannotConvertException( e, puArgErr); 964 } 965 catch(InvocationTargetException & e) //XInvocation::invoke 966 { 967 const Any& org = e.TargetException; 968 Exception excTarget; 969 org >>= excTarget; 970 OUString message= 971 org.getValueType().getTypeName() + OUSTR(": ") + excTarget.Message; 972 writeExcepinfo(pexcepinfo, message); 973 ret = DISP_E_EXCEPTION; 974 } 975 catch(NoSuchMethodException & e) //XInvocation::invoke 976 { 977 writeExcepinfo(pexcepinfo, e.Message); 978 ret = DISP_E_MEMBERNOTFOUND; 979 } 980 catch(BridgeRuntimeError & e) 981 { 982 writeExcepinfo(pexcepinfo, e.message); 983 ret = DISP_E_EXCEPTION; 984 } 985 catch(Exception & e) 986 { 987 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n") + 988 e.Message; 989 writeExcepinfo(pexcepinfo, message); 990 ret = DISP_E_EXCEPTION; 991 } 992 catch( ... ) 993 { 994 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n" 995 "Unexpected exception"); 996 writeExcepinfo(pexcepinfo, message); 997 ret = DISP_E_EXCEPTION; 998 } 999 return ret; 1000 } 1001 1002 HRESULT InterfaceOleWrapper_Impl::doGetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * pvarResult, 1003 EXCEPINFO * pexcepinfo, OUString& name) 1004 { 1005 HRESULT ret= S_OK; 1006 1007 Any value; 1008 try 1009 { 1010 Any returnValue = m_xInvocation->getValue( name); 1011 // write back return value 1012 if (pvarResult) 1013 anyToVariant(pvarResult, returnValue); 1014 } 1015 catch(UnknownPropertyException e) //XInvocation::getValue 1016 { 1017 writeExcepinfo(pexcepinfo, e.Message); 1018 ret = DISP_E_MEMBERNOTFOUND; 1019 } 1020 catch(BridgeRuntimeError& e) 1021 { 1022 writeExcepinfo(pexcepinfo, e.message); 1023 ret = DISP_E_EXCEPTION; 1024 } 1025 catch(Exception& e) 1026 { 1027 OUString message= OUSTR("InterfaceOleWrapper_Impl::doGetProperty : \n") + 1028 e.Message; 1029 writeExcepinfo(pexcepinfo, message); 1030 } 1031 catch( ... ) 1032 { 1033 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n" 1034 "Unexpected exception"); 1035 writeExcepinfo(pexcepinfo, message); 1036 ret = DISP_E_EXCEPTION; 1037 } 1038 return ret; 1039 } 1040 1041 HRESULT InterfaceOleWrapper_Impl::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/, 1042 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any> params) 1043 { 1044 HRESULT ret= S_OK; 1045 1046 try 1047 { 1048 m_xInvocation->setValue( name, params.getConstArray()[0]); 1049 } 1050 catch(UnknownPropertyException ) 1051 { 1052 ret = DISP_E_MEMBERNOTFOUND; 1053 } 1054 catch(CannotConvertException e) 1055 { 1056 ret= mapCannotConvertException( e, puArgErr); 1057 } 1058 catch(InvocationTargetException e) 1059 { 1060 if (pexcepinfo != NULL) 1061 { 1062 Any org = e.TargetException; 1063 1064 pexcepinfo->wCode = UNO_2_OLE_EXCEPTIONCODE; 1065 pexcepinfo->bstrSource = SysAllocString(L"any ONE component"); 1066 pexcepinfo->bstrDescription = SysAllocString( 1067 reinterpret_cast<LPCOLESTR>(org.getValueType().getTypeName().getStr())); 1068 } 1069 ret = DISP_E_EXCEPTION; 1070 } 1071 catch( ... ) 1072 { 1073 ret= DISP_E_EXCEPTION; 1074 } 1075 return ret; 1076 } 1077 1078 HRESULT InterfaceOleWrapper_Impl::InvokeGeneral( DISPID dispidMember, unsigned short wFlags, 1079 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, 1080 unsigned int * /*puArgErr*/, sal_Bool& bHandled) 1081 { 1082 HRESULT ret= S_OK; 1083 try 1084 { 1085 // DISPID_VALUE | The DEFAULT Value is required in JScript when the situation 1086 // is that we put an object into an Array object ( out parameter). We have to return 1087 // IDispatch otherwise the object cannot be accessed from the Script. 1088 if( dispidMember == DISPID_VALUE && wFlags == DISPATCH_PROPERTYGET 1089 && m_defaultValueType != VT_EMPTY && pvarResult != NULL) 1090 { 1091 bHandled= sal_True; 1092 if( m_defaultValueType == VT_DISPATCH) 1093 { 1094 pvarResult->vt= VT_DISPATCH; 1095 pvarResult->pdispVal= static_cast<IDispatch*>( this); 1096 AddRef(); 1097 ret= S_OK; 1098 } 1099 } 1100 // --------- 1101 // function: _GetValueObject 1102 else if( dispidMember == DISPID_JSCRIPT_VALUE_FUNC) 1103 { 1104 bHandled= sal_True; 1105 if( !pvarResult) 1106 ret= E_POINTER; 1107 CComObject< JScriptValue>* pValue; 1108 if( SUCCEEDED( CComObject<JScriptValue>::CreateInstance( &pValue))) 1109 { 1110 pValue->AddRef(); 1111 pvarResult->vt= VT_DISPATCH; 1112 #ifdef __MINGW32__ 1113 pvarResult->pdispVal= CComQIPtr<IDispatch, &__uuidof(IDispatch)>(pValue->GetUnknown()); 1114 #else 1115 pvarResult->pdispVal= CComQIPtr<IDispatch>(pValue->GetUnknown()); 1116 #endif 1117 ret= S_OK; 1118 } 1119 else 1120 ret= DISP_E_EXCEPTION; 1121 } 1122 else if( dispidMember == DISPID_GET_STRUCT_FUNC) 1123 { 1124 bHandled= sal_True; 1125 sal_Bool bStruct= sal_False; 1126 1127 1128 Reference<XInterface> xIntCore= m_smgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection")); 1129 Reference<XIdlReflection> xRefl( xIntCore, UNO_QUERY); 1130 if( xRefl.is() ) 1131 { 1132 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct. 1133 CComVariant arg; 1134 if( pdispparams->cArgs == 1 && SUCCEEDED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])) ) 1135 { 1136 Reference<XIdlClass> classStruct= xRefl->forName( reinterpret_cast<const sal_Unicode*>(arg.bstrVal)); 1137 if( classStruct.is()) 1138 { 1139 Any anyStruct; 1140 classStruct->createObject( anyStruct); 1141 CComVariant var; 1142 anyToVariant( &var, anyStruct ); 1143 1144 if( var.vt == VT_DISPATCH) 1145 { 1146 VariantCopy( pvarResult, & var); 1147 bStruct= sal_True; 1148 } 1149 } 1150 } 1151 } 1152 ret= bStruct == sal_True ? S_OK : DISP_E_EXCEPTION; 1153 } 1154 else if (dispidMember == DISPID_CREATE_TYPE_FUNC) 1155 { 1156 bHandled= sal_True; 1157 if( !pvarResult) 1158 ret= E_POINTER; 1159 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct. 1160 CComVariant arg; 1161 if( pdispparams->cArgs != 1) 1162 return DISP_E_BADPARAMCOUNT; 1163 if (FAILED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0]))) 1164 return DISP_E_BADVARTYPE; 1165 1166 //check if the provided name represents a valid type 1167 Type type; 1168 if (getType(arg.bstrVal, type) == false) 1169 { 1170 writeExcepinfo(pexcepinfo,OUString( 1171 OUSTR("[automation bridge] A UNO type with the name ") + 1172 OUString(reinterpret_cast<const sal_Unicode*>(arg.bstrVal)) + OUSTR(" does not exist!"))); 1173 return DISP_E_EXCEPTION; 1174 } 1175 1176 if (createUnoTypeWrapper(arg.bstrVal, pvarResult) == false) 1177 { 1178 writeExcepinfo(pexcepinfo,OUSTR("[automation bridge] InterfaceOleWrapper_Impl::InvokeGeneral\n" 1179 "Could not initialize UnoTypeWrapper object!")); 1180 return DISP_E_EXCEPTION; 1181 } 1182 } 1183 } 1184 catch(BridgeRuntimeError & e) 1185 { 1186 writeExcepinfo(pexcepinfo, e.message); 1187 ret = DISP_E_EXCEPTION; 1188 } 1189 catch(Exception & e) 1190 { 1191 OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n") + 1192 e.Message; 1193 writeExcepinfo(pexcepinfo, message); 1194 ret = DISP_E_EXCEPTION; 1195 } 1196 catch( ... ) 1197 { 1198 OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n" 1199 "Unexpected exception"); 1200 writeExcepinfo(pexcepinfo, message); 1201 ret = DISP_E_EXCEPTION; 1202 } 1203 return ret; 1204 } 1205 1206 1207 1208 1209 STDMETHODIMP InterfaceOleWrapper_Impl::GetDispID(BSTR /*bstrName*/, DWORD /*grfdex*/, DISPID __RPC_FAR* /*pid*/) 1210 { 1211 HRESULT ret = ResultFromScode(E_NOTIMPL); 1212 1213 return ret; 1214 } 1215 1216 STDMETHODIMP InterfaceOleWrapper_Impl::InvokeEx( 1217 /* [in] */ DISPID /*id*/, 1218 /* [in] */ LCID /*lcid*/, 1219 /* [in] */ WORD /*wFlags*/, 1220 /* [in] */ DISPPARAMS __RPC_FAR* /*pdp*/, 1221 /* [out] */ VARIANT __RPC_FAR* /*pvarRes*/, 1222 /* [out] */ EXCEPINFO __RPC_FAR* /*pei*/, 1223 /* [unique][in] */ IServiceProvider __RPC_FAR* /*pspCaller*/) 1224 { 1225 HRESULT ret = ResultFromScode(E_NOTIMPL); 1226 1227 return ret; 1228 } 1229 1230 1231 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByName( 1232 /* [in] */ BSTR /*bstr*/, 1233 /* [in] */ DWORD /*grfdex*/) 1234 { 1235 HRESULT ret = ResultFromScode(E_NOTIMPL); 1236 1237 return ret; 1238 } 1239 1240 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByDispID(DISPID /*id*/) 1241 { 1242 HRESULT ret = ResultFromScode(E_NOTIMPL); 1243 1244 return ret; 1245 } 1246 1247 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberProperties( 1248 /* [in] */ DISPID /*id*/, 1249 /* [in] */ DWORD /*grfdexFetch*/, 1250 /* [out] */ DWORD __RPC_FAR* /*pgrfdex*/) 1251 { 1252 HRESULT ret = ResultFromScode(E_NOTIMPL); 1253 1254 return ret; 1255 } 1256 1257 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberName( 1258 /* [in] */ DISPID /*id*/, 1259 /* [out] */ BSTR __RPC_FAR* /*pbstrName*/) 1260 { 1261 HRESULT ret = ResultFromScode(E_NOTIMPL); 1262 1263 return ret; 1264 } 1265 1266 STDMETHODIMP InterfaceOleWrapper_Impl::GetNextDispID( 1267 /* [in] */ DWORD /*grfdex*/, 1268 /* [in] */ DISPID /*id*/, 1269 /* [out] */ DISPID __RPC_FAR* /*pid*/) 1270 { 1271 HRESULT ret = ResultFromScode(E_NOTIMPL); 1272 1273 return ret; 1274 } 1275 1276 STDMETHODIMP InterfaceOleWrapper_Impl::GetNameSpaceParent( 1277 /* [out] */ IUnknown __RPC_FAR *__RPC_FAR* /*ppunk*/) 1278 { 1279 HRESULT ret = ResultFromScode(E_NOTIMPL); 1280 1281 return ret; 1282 } 1283 1284 1285 /************************************************************************* 1286 1287 UnoObjectWrapperRemoteOpt 1288 1289 *************************************************************************/ 1290 UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference<XMultiServiceFactory>& aFactory, 1291 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass): 1292 InterfaceOleWrapper_Impl( aFactory, unoWrapperClass, comWrapperClass), 1293 m_currentId(1) 1294 1295 { 1296 } 1297 UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt() 1298 { 1299 } 1300 1301 // UnoConversionUtilities 1302 Reference< XInterface > UnoObjectWrapperRemoteOpt::createUnoWrapperInstance() 1303 { 1304 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt( 1305 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); 1306 return Reference<XInterface>( xWeak, UNO_QUERY); 1307 } 1308 1309 STDMETHODIMP UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID /*riid*/, OLECHAR ** rgszNames, unsigned int cNames, 1310 LCID /*lcid*/, DISPID * rgdispid ) 1311 { 1312 MutexGuard guard( getBridgeMutex()); 1313 1314 if( ! rgdispid) 1315 return E_POINTER; 1316 HRESULT ret = E_UNEXPECTED; 1317 // ---------------------------------------- 1318 // _GetValueObject 1319 if( ! wcscmp( *rgszNames, JSCRIPT_VALUE_FUNC)) 1320 { 1321 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC; 1322 return S_OK; 1323 } 1324 else if( ! wcscmp( *rgszNames, GET_STRUCT_FUNC)) 1325 { 1326 *rgdispid= DISPID_GET_STRUCT_FUNC; 1327 return S_OK; 1328 } 1329 1330 // ---------------------------------------- 1331 if (m_xInvocation.is() && (cNames > 0)) 1332 { 1333 OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0])); 1334 // has this name been determined as "bad" 1335 BadNameMap::iterator badIter= m_badNameMap.find( name); 1336 if( badIter == m_badNameMap.end() ) 1337 { 1338 // name has not been bad before( member exists 1339 typedef NameToIdMap::iterator ITnames; 1340 pair< ITnames, bool > pair_id= m_nameToDispIdMap.insert( NameToIdMap::value_type(name, m_currentId++)); 1341 // new ID inserted ? 1342 if( pair_id.second ) 1343 {// yes, now create MemberInfo and ad to IdToMemberInfoMap 1344 MemberInfo d(0, name); 1345 m_idToMemberInfoMap.insert( IdToMemberInfoMap::value_type( m_currentId - 1, d)); 1346 } 1347 1348 *rgdispid = pair_id.first->second; 1349 ret = S_OK; 1350 } 1351 else 1352 ret= DISP_E_UNKNOWNNAME; 1353 } 1354 return ret; 1355 } 1356 1357 STDMETHODIMP UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember, REFIID /*riid*/, LCID /*lcid*/, unsigned short wFlags, 1358 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, 1359 unsigned int * puArgErr ) 1360 { 1361 HRESULT ret = S_OK; 1362 try 1363 { 1364 sal_Bool bHandled= sal_False; 1365 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, 1366 puArgErr, bHandled); 1367 if( bHandled) 1368 return ret; 1369 1370 if ( dispidMember > 0 && m_xInvocation.is()) 1371 { 1372 1373 IdToMemberInfoMap::iterator it_MemberInfo= m_idToMemberInfoMap.find( dispidMember); 1374 if( it_MemberInfo != m_idToMemberInfoMap.end() ) 1375 { 1376 MemberInfo& info= it_MemberInfo->second; 1377 1378 Sequence<Any> params; // holds converted any s 1379 if( ! info.flags ) 1380 { // DISPID called for the first time 1381 if( wFlags == DISPATCH_METHOD ) 1382 { 1383 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1384 1385 if( FAILED( ret= doInvoke( pdispparams, pvarResult, 1386 pexcepinfo, puArgErr, info.name, params)) 1387 && ret == DISP_E_MEMBERNOTFOUND) 1388 { 1389 // try to get the exact name 1390 OUString exactName; 1391 if (m_xExactName.is()) 1392 { 1393 exactName = m_xExactName->getExactName( info.name); 1394 // invoke again 1395 if( exactName.getLength() != 0) 1396 { 1397 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult, 1398 pexcepinfo, puArgErr, exactName, params))) 1399 info.name= exactName; 1400 } 1401 } 1402 } 1403 if( SUCCEEDED( ret ) ) 1404 info.flags= DISPATCH_METHOD; 1405 } //if( wFlags == DISPATCH_METHOD ) 1406 1407 else if( wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_PROPERTYPUTREF) 1408 { 1409 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1410 if( FAILED( ret= doSetProperty( pdispparams, pvarResult, 1411 pexcepinfo, puArgErr, info.name, params)) 1412 && ret == DISP_E_MEMBERNOTFOUND) 1413 { 1414 // try to get the exact name 1415 OUString exactName; 1416 if (m_xExactName.is()) 1417 { 1418 exactName = m_xExactName->getExactName( info.name); 1419 // invoke again 1420 if( exactName.getLength() != 0) 1421 { 1422 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult, 1423 pexcepinfo, puArgErr, exactName, params))) 1424 info.name= exactName; 1425 } 1426 } 1427 } 1428 if( SUCCEEDED( ret ) ) 1429 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET; 1430 } 1431 1432 else if( wFlags == DISPATCH_PROPERTYGET) 1433 { 1434 if( FAILED( ret= doGetProperty( pdispparams, pvarResult, 1435 pexcepinfo, info.name)) 1436 && ret == DISP_E_MEMBERNOTFOUND) 1437 { 1438 // try to get the exact name 1439 OUString exactName; 1440 if (m_xExactName.is()) 1441 { 1442 exactName = m_xExactName->getExactName( info.name); 1443 // invoke again 1444 if( exactName.getLength() != 0) 1445 { 1446 if( SUCCEEDED( ret= doGetProperty( pdispparams, pvarResult, 1447 pexcepinfo, exactName))) 1448 info.name= exactName; 1449 } 1450 } 1451 } 1452 if( SUCCEEDED( ret ) ) 1453 info.flags= DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT; 1454 } 1455 else if( wFlags & DISPATCH_METHOD && 1456 (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF)) 1457 { 1458 1459 OUString exactName; 1460 // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT 1461 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1462 // try first as method 1463 if( FAILED( ret= doInvoke( pdispparams, pvarResult, 1464 pexcepinfo, puArgErr, info.name, params)) 1465 && ret == DISP_E_MEMBERNOTFOUND) 1466 { 1467 // try to get the exact name 1468 if (m_xExactName.is()) 1469 { 1470 exactName = m_xExactName->getExactName( info.name); 1471 // invoke again 1472 if( exactName.getLength() != 0) 1473 { 1474 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult, 1475 pexcepinfo, puArgErr, exactName, params))) 1476 info.name= exactName; 1477 } 1478 } 1479 } 1480 if( SUCCEEDED( ret ) ) 1481 info.flags= DISPATCH_METHOD; 1482 1483 // try as property 1484 if( FAILED( ret) && pdispparams->cArgs == 1) 1485 { 1486 if( FAILED( ret= doSetProperty( pdispparams, pvarResult, 1487 pexcepinfo, puArgErr, info.name, params)) 1488 && ret == DISP_E_MEMBERNOTFOUND) 1489 { 1490 // try to get the exact name 1491 if( exactName.getLength() != 0) 1492 { 1493 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult, 1494 pexcepinfo, puArgErr, exactName, params))) 1495 info.name= exactName; 1496 } 1497 } 1498 if( SUCCEEDED( ret ) ) 1499 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET; 1500 } 1501 } 1502 else if( wFlags & DISPATCH_METHOD && wFlags & DISPATCH_PROPERTYGET) 1503 { 1504 OUString exactName; 1505 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1506 1507 if( FAILED( ret= doInvoke( pdispparams, pvarResult, 1508 pexcepinfo, puArgErr, info.name, params)) 1509 && ret == DISP_E_MEMBERNOTFOUND) 1510 { 1511 // try to get the exact name 1512 if (m_xExactName.is()) 1513 { 1514 exactName = m_xExactName->getExactName( info.name); 1515 // invoke again 1516 if( exactName.getLength() != 0) 1517 { 1518 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult, 1519 pexcepinfo, puArgErr, exactName, params))) 1520 info.name= exactName; 1521 } 1522 } 1523 } 1524 if( SUCCEEDED( ret ) ) 1525 info.flags= DISPATCH_METHOD; 1526 1527 // try as property 1528 if( FAILED( ret) && pdispparams->cArgs == 1) 1529 { 1530 if( FAILED( ret= doGetProperty( pdispparams, pvarResult, 1531 pexcepinfo, info.name)) 1532 && ret == DISP_E_MEMBERNOTFOUND) 1533 { 1534 if( exactName.getLength() != 0) 1535 { 1536 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult, 1537 pexcepinfo, puArgErr, exactName, params))) 1538 info.name= exactName; 1539 } 1540 } 1541 if( SUCCEEDED( ret ) ) 1542 info.flags= DISPATCH_PROPERTYGET; 1543 } 1544 } 1545 1546 // update �nformation about this member 1547 if( ret == DISP_E_MEMBERNOTFOUND) 1548 { 1549 // Remember the name as not existing 1550 // and remove the MemberInfo 1551 m_badNameMap[info.name]= sal_False; 1552 m_idToMemberInfoMap.erase( it_MemberInfo); 1553 } 1554 } // if( ! info.flags ) 1555 else // IdToMemberInfoMap contains a MemberInfo 1556 { 1557 if( wFlags & DISPATCH_METHOD && info.flags == DISPATCH_METHOD) 1558 { 1559 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1560 ret= doInvoke( pdispparams, pvarResult, 1561 pexcepinfo, puArgErr, info.name, params); 1562 } 1563 else if( (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF ) && 1564 info.flags & DISPATCH_PROPERTYPUT) 1565 { 1566 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1567 ret= doSetProperty( pdispparams, pvarResult, 1568 pexcepinfo, puArgErr, info.name, params); 1569 } 1570 else if( (wFlags & DISPATCH_PROPERTYGET) && ( info.flags & DISPATCH_PROPERTYGET)) 1571 { 1572 ret= doGetProperty( pdispparams, pvarResult, 1573 pexcepinfo, info.name); 1574 } 1575 else 1576 { 1577 ret= DISP_E_MEMBERNOTFOUND; 1578 } 1579 } 1580 }// if( it_MemberInfo != m_idToMemberInfoMap.end() ) 1581 else 1582 ret= DISP_E_MEMBERNOTFOUND; 1583 } 1584 } 1585 catch(BridgeRuntimeError& e) 1586 { 1587 writeExcepinfo(pexcepinfo, e.message); 1588 ret = DISP_E_EXCEPTION; 1589 } 1590 catch(Exception& e) 1591 { 1592 OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n") + 1593 e.Message; 1594 writeExcepinfo(pexcepinfo, message); 1595 ret = DISP_E_EXCEPTION; 1596 } 1597 catch(...) 1598 { 1599 OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n" 1600 "Unexpected exception"); 1601 writeExcepinfo(pexcepinfo, message); 1602 ret = DISP_E_EXCEPTION; 1603 } 1604 1605 return ret; 1606 } 1607 1608 HRESULT UnoObjectWrapperRemoteOpt::methodInvoke( DISPID /*dispidMember*/, DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/, 1609 EXCEPINFO * /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence<Any> params) 1610 { 1611 return S_OK; 1612 } 1613 1614 1615 // The returned HRESULT is only appropriate for IDispatch::Invoke 1616 static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr) 1617 { 1618 HRESULT ret; 1619 sal_Bool bWriteIndex= sal_True; 1620 1621 switch ( e.Reason) 1622 { 1623 case FailReason::OUT_OF_RANGE: 1624 ret = DISP_E_OVERFLOW; 1625 break; 1626 case FailReason::IS_NOT_NUMBER: 1627 ret = DISP_E_TYPEMISMATCH; 1628 break; 1629 case FailReason::IS_NOT_ENUM: 1630 ret = DISP_E_TYPEMISMATCH; 1631 break; 1632 case FailReason::IS_NOT_BOOL: 1633 ret = DISP_E_TYPEMISMATCH; 1634 break; 1635 case FailReason::NO_SUCH_INTERFACE: 1636 ret = DISP_E_TYPEMISMATCH; 1637 break; 1638 case FailReason::SOURCE_IS_NO_DERIVED_TYPE: 1639 ret = DISP_E_TYPEMISMATCH; 1640 break; 1641 case FailReason::TYPE_NOT_SUPPORTED: 1642 ret = DISP_E_TYPEMISMATCH; 1643 break; 1644 case FailReason::INVALID: 1645 ret = DISP_E_TYPEMISMATCH; 1646 break; 1647 case FailReason::NO_DEFAULT_AVAILABLE: 1648 ret = DISP_E_BADPARAMCOUNT; 1649 break; 1650 case FailReason::UNKNOWN: 1651 ret = E_UNEXPECTED; 1652 break; 1653 default: 1654 ret = E_UNEXPECTED; 1655 bWriteIndex= sal_False; 1656 break; 1657 } 1658 1659 if( bWriteIndex && puArgErr != NULL) 1660 *puArgErr = e.ArgumentIndex; 1661 return ret; 1662 } 1663 1664 // The function maps the TypeClass of the any to VARTYPE: If 1665 // the Any contains STRUCT or INTERFACE then the return value 1666 // is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper 1667 // and the result is put into the constructor of the uno - wrapper 1668 // object. If a client asks the object for DISPID_VALUE and this 1669 // funtion returned VT_DISPATCH then the IDispatch of the same 1670 // object is being returned. 1671 // See InterfaceOleWrapper_Impl::Invoke, InterfaceOleWrapper_Impl::m_defaultValueType 1672 const VARTYPE getVarType( const Any& value) 1673 { 1674 VARTYPE ret= VT_EMPTY; 1675 1676 switch ( value.getValueTypeClass()) 1677 { 1678 case TypeClass_STRUCT: ret= VT_DISPATCH; break; 1679 case TypeClass_INTERFACE: ret= VT_DISPATCH; break; 1680 default: break; 1681 } 1682 return ret; 1683 } 1684 1685 1686 1687 1688 } // end namespace 1689