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