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 chosen. 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 acquiring 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 { 500 501 Any retAny; 502 if( sourceModelType == UNO && destModelType == OLE && 503 modelDepObject.getValueTypeClass() == TypeClass_INTERFACE ) 504 { 505 Reference<XInterface> xInt; 506 if( modelDepObject >>= xInt ) 507 { 508 if( xInt == Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY)) 509 { 510 VARIANT *pVar= (VARIANT*)CoTaskMemAlloc( sizeof( VARIANT)); 511 if( pVar) 512 { 513 pVar->vt= VT_DISPATCH; 514 pVar->pdispVal= static_cast<IDispatch*>( this); 515 AddRef(); 516 517 retAny<<= reinterpret_cast< sal_uInt32 >( pVar); 518 } 519 } 520 } 521 } 522 523 return retAny; 524 } 525 526 527 // XInitialization -------------------------------------------------- 528 void SAL_CALL InterfaceOleWrapper_Impl::initialize( const Sequence< Any >& aArguments ) 529 { 530 switch( aArguments.getLength() ) 531 { 532 case 2: // the object wraps an UNO struct 533 aArguments[0] >>= m_xInvocation; 534 aArguments[1] >>= m_defaultValueType; 535 break; 536 case 3: // the object wraps an UNO interface 537 aArguments[0] >>= m_xInvocation; 538 aArguments[1] >>= m_xOrigin; 539 aArguments[2] >>= m_defaultValueType; 540 break; 541 } 542 543 m_xExactName= Reference<XExactName>( m_xInvocation, UNO_QUERY); 544 } 545 546 Reference< XInterface > InterfaceOleWrapper_Impl::createUnoWrapperInstance() 547 { 548 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl( 549 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); 550 return Reference<XInterface>( xWeak, UNO_QUERY); 551 } 552 553 Reference<XInterface> InterfaceOleWrapper_Impl::createComWrapperInstance() 554 { 555 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl( 556 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); 557 return Reference<XInterface>( xWeak, UNO_QUERY); 558 } 559 560 561 562 // "getType" is used in convertValueObject to map the string denoting the type 563 // to an actual Type object. 564 bool getType( const BSTR name, Type & type) 565 { 566 Type retType; 567 bool ret = false; 568 typelib_TypeDescription * pDesc= NULL; 569 OUString str( reinterpret_cast<const sal_Unicode*>(name)); 570 typelib_typedescription_getByName( &pDesc, str.pData ); 571 if( pDesc) 572 { 573 type = Type( pDesc->pWeakRef ); 574 typelib_typedescription_release( pDesc); 575 ret = true; 576 } 577 return ret; 578 } 579 580 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource) 581 { 582 sal_Bool ret = sal_False; 583 HRESULT hr; 584 585 // Handle JScriptValue objects and JScript out params ( Array object ) 586 CComVariant varDest( *pDest); 587 588 if( SUCCEEDED( varDest.ChangeType(VT_DISPATCH))) 589 { 590 CComPtr<IDispatch> spDispDest(varDest.pdispVal); 591 592 // special Handling for a JScriptValue object 593 #ifdef __MINGW32__ 594 CComQIPtr<IJScriptValueObject, &__uuidof(IJScriptValueObject)> spValueDest(spDispDest); 595 #else 596 CComQIPtr<IJScriptValueObject> spValueDest(spDispDest); 597 #endif 598 if (spValueDest) 599 { 600 VARIANT_BOOL varBool= VARIANT_FALSE; 601 if( SUCCEEDED( hr= spValueDest->IsOutParam( &varBool) ) 602 && varBool == VARIANT_TRUE || 603 SUCCEEDED(hr= spValueDest->IsInOutParam( &varBool) ) 604 && varBool == VARIANT_TRUE ) 605 { 606 if( SUCCEEDED( spValueDest->Set( CComVariant(), *pSource))) 607 ret= sal_True; 608 } 609 } 610 else if (pDest->vt == VT_DISPATCH)// VT_DISPATCH -> JScript out param 611 { 612 // We use IDispatchEx because its GetDispID function causes the creation 613 // of a property if it does not exist already. This is convenient for 614 // out parameters in JScript. Then the user must not specify propery "0" 615 // explicitly 616 #ifdef __MINGW32__ 617 CComQIPtr<IDispatchEx, &__uuidof(IDispatchEx)> spDispEx( spDispDest); 618 #else 619 CComQIPtr<IDispatchEx> spDispEx( spDispDest); 620 #endif 621 if( spDispEx) 622 { 623 CComBSTR nullProp(L"0"); 624 DISPID dwDispID; 625 if( SUCCEEDED( spDispEx->GetDispID( nullProp, fdexNameEnsure, &dwDispID))) 626 { 627 DISPPARAMS dispparams = {NULL, NULL, 1, 1}; 628 dispparams.rgvarg = pSource; 629 DISPID dispidPut = DISPID_PROPERTYPUT; 630 dispparams.rgdispidNamedArgs = &dispidPut; 631 632 if (pSource->vt == VT_UNKNOWN || pSource->vt == VT_DISPATCH || 633 (pSource->vt & VT_ARRAY) || (pSource->vt & VT_BYREF)) 634 hr = spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, 635 &dispparams, NULL, NULL, NULL); 636 else 637 hr= spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, 638 &dispparams, NULL, NULL, NULL); 639 if( SUCCEEDED(hr)) 640 ret= sal_True; 641 } 642 } 643 } 644 else 645 ret= writeBackOutParameter( pDest, pSource); 646 } 647 else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript 648 { // param. The function checks itself for correct VBScript params 649 ret= writeBackOutParameter( pDest, pSource); 650 } 651 return ret; 652 } 653 // VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter. 654 // Thus we are in charge of freeing an eventual value contained by the inner VARIANT 655 // Please note: VariantCopy doesn't free a VT_BYREF value 656 // The out parameters are expected to have always a valid type 657 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource) 658 { 659 HRESULT hr; 660 sal_Bool ret = FALSE; 661 // Out parameter must be VT_BYREF 662 if ((V_VT(pDest) & VT_BYREF) != 0 ) 663 { 664 VARTYPE oleTypeFlags = V_VT(pSource); 665 666 // if caller accept VARIANT as out parameter, any value must be converted 667 if (V_VT(pDest) == (VT_VARIANT | VT_BYREF)) 668 { 669 // When the user provides a VARIANT rather then a concrete type 670 // we just copy the source to the out, in/out parameter 671 // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that 672 // is contained in pDest are released by VariantCopy 673 VariantCopy(V_VARIANTREF(pDest), pSource); 674 ret = sal_True; 675 } 676 else 677 { 678 // variantarg and variant must have same type 679 if ((V_VT(pDest) & oleTypeFlags) == oleTypeFlags) 680 { 681 if ((oleTypeFlags & VT_ARRAY) != 0) 682 { 683 // In / Out Param 684 if( *V_ARRAYREF(pDest) != NULL) 685 hr= SafeArrayCopyData( V_ARRAY(pSource), *V_ARRAYREF(pDest)); 686 else 687 // Out Param 688 hr= SafeArrayCopy(V_ARRAY(pSource), V_ARRAYREF(pDest)) == NOERROR; 689 if( SUCCEEDED( hr)) 690 ret = sal_True; 691 } 692 else 693 { 694 // copy base type 695 switch (V_VT(pSource)) 696 { 697 case VT_I2: 698 { 699 *V_I2REF(pDest) = V_I2(pSource); 700 ret = sal_True; 701 break; 702 } 703 case VT_I4: 704 *V_I4REF(pDest) = V_I4(pSource); 705 ret = sal_True; 706 break; 707 case VT_R4: 708 *V_R4REF(pDest) = V_R4(pSource); 709 ret = sal_True; 710 break; 711 case VT_R8: 712 *V_R8REF(pDest) = V_R8(pSource); 713 ret = sal_True; 714 break; 715 case VT_CY: 716 *V_CYREF(pDest) = V_CY(pSource); 717 ret = sal_True; 718 break; 719 case VT_DATE: 720 *V_DATEREF(pDest) = V_DATE(pSource); 721 ret = sal_True; 722 break; 723 case VT_BSTR: 724 SysFreeString( *pDest->pbstrVal); 725 726 *V_BSTRREF(pDest) = SysAllocString(V_BSTR(pSource)); 727 ret = sal_True; 728 break; 729 case VT_DISPATCH: 730 if (*V_DISPATCHREF(pDest) != NULL) 731 (*V_DISPATCHREF(pDest))->Release(); 732 733 *V_DISPATCHREF(pDest) = V_DISPATCH(pSource); 734 735 if (*V_DISPATCHREF(pDest) != NULL) 736 (*V_DISPATCHREF(pDest))->AddRef(); 737 738 ret = sal_True; 739 break; 740 case VT_ERROR: 741 *V_ERRORREF(pDest) = V_ERROR(pSource); 742 ret = sal_True; 743 break; 744 case VT_BOOL: 745 *V_BOOLREF(pDest) = V_BOOL(pSource); 746 ret = sal_True; 747 break; 748 case VT_UNKNOWN: 749 if (*V_UNKNOWNREF(pDest) != NULL) 750 (*V_UNKNOWNREF(pDest))->Release(); 751 752 *V_UNKNOWNREF(pDest) = V_UNKNOWN(pSource); 753 754 if (*V_UNKNOWNREF(pDest) != NULL) 755 (*V_UNKNOWNREF(pDest))->AddRef(); 756 757 ret = sal_True; 758 break; 759 case VT_I1: 760 *V_I1REF(pDest) = V_I1(pSource); 761 ret = sal_True; 762 break; 763 case VT_UI1: 764 *V_UI1REF(pDest) = V_UI1(pSource); 765 ret = sal_True; 766 break; 767 case VT_UI2: 768 *V_UI2REF(pDest) = V_UI2(pSource); 769 ret = sal_True; 770 break; 771 case VT_UI4: 772 *V_UI4REF(pDest) = V_UI4(pSource); 773 ret = sal_True; 774 break; 775 case VT_INT: 776 *V_INTREF(pDest) = V_INT(pSource); 777 ret = sal_True; 778 break; 779 case VT_UINT: 780 *V_UINTREF(pDest) = V_UINT(pSource); 781 ret = sal_True; 782 break; 783 case VT_DECIMAL: 784 memcpy(pDest->pdecVal, pSource, sizeof(DECIMAL)); 785 ret = sal_True; 786 break; 787 default: 788 break; 789 } 790 } 791 } 792 else 793 { 794 // Handling of special cases 795 // Destination and source types are different 796 if( pDest->vt == (VT_BSTR | VT_BYREF) 797 && pSource->vt == VT_I2) 798 { 799 // When the user provides a String as out our in/out parameter 800 // and the type is char (TypeClass_CHAR) then we convert to a BSTR 801 // instead of VT_I2 as is done otherwise 802 OLECHAR buff[]= {0,0}; 803 buff[0]= pSource->iVal; 804 805 SysFreeString( *pDest->pbstrVal); 806 *pDest->pbstrVal= SysAllocString( buff); 807 ret = sal_True; 808 } 809 } 810 } 811 } 812 return ret; 813 } 814 815 STDMETHODIMP InterfaceOleWrapper_Impl::Invoke(DISPID dispidMember, 816 REFIID /*riid*/, 817 LCID /*lcid*/, 818 unsigned short wFlags, 819 DISPPARAMS * pdispparams, 820 VARIANT * pvarResult, 821 EXCEPINFO * pexcepinfo, 822 unsigned int * puArgErr ) 823 { 824 HRESULT ret = S_OK; 825 826 try 827 { 828 sal_Bool bHandled= sal_False; 829 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, 830 puArgErr, bHandled); 831 if( bHandled) 832 return ret; 833 834 if ((dispidMember > 0) && ((size_t)dispidMember <= m_MemberInfos.size()) && m_xInvocation.is()) 835 { 836 MemberInfo d = m_MemberInfos[dispidMember - 1]; 837 DWORD flags = wFlags & d.flags; 838 839 if (flags != 0) 840 { 841 if ((flags & DISPATCH_METHOD) != 0) 842 { 843 if (pdispparams->cNamedArgs > 0) 844 ret = DISP_E_NONAMEDARGS; 845 else 846 { 847 Sequence<Any> params; 848 849 convertDispparamsArgs(dispidMember, wFlags, pdispparams , params ); 850 851 ret= doInvoke(pdispparams, pvarResult, 852 pexcepinfo, puArgErr, d.name, params); 853 } 854 } 855 else if ((flags & DISPATCH_PROPERTYGET) != 0) 856 { 857 ret= doGetProperty( pdispparams, pvarResult, 858 pexcepinfo, d.name); 859 } 860 else if ((flags & DISPATCH_PROPERTYPUT || flags & DISPATCH_PROPERTYPUTREF) != 0) 861 { 862 if (pdispparams->cArgs != 1) 863 ret = DISP_E_BADPARAMCOUNT; 864 else 865 { 866 Sequence<Any> params; 867 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 868 if(params.getLength() > 0) 869 ret= doSetProperty( pdispparams, pvarResult, pexcepinfo, puArgErr, d.name, params); 870 else 871 ret = DISP_E_BADVARTYPE; 872 } 873 } 874 } 875 else 876 ret= DISP_E_MEMBERNOTFOUND; 877 } 878 else 879 ret = DISP_E_MEMBERNOTFOUND; 880 } 881 catch(BridgeRuntimeError& e) 882 { 883 writeExcepinfo(pexcepinfo, e.message); 884 ret = DISP_E_EXCEPTION; 885 } 886 catch(Exception& e) 887 { 888 OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n") + 889 e.Message; 890 writeExcepinfo(pexcepinfo, message); 891 ret = DISP_E_EXCEPTION; 892 } 893 catch(...) 894 { 895 OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n" 896 "Unexpected exception"); 897 writeExcepinfo(pexcepinfo, message); 898 ret = DISP_E_EXCEPTION; 899 } 900 901 return ret; 902 } 903 904 HRESULT InterfaceOleWrapper_Impl::doInvoke( DISPPARAMS * pdispparams, VARIANT * pvarResult, 905 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any>& params) 906 { 907 908 909 HRESULT ret= S_OK; 910 try 911 { 912 Sequence<sal_Int16> outIndex; 913 Sequence<Any> outParams; 914 Any returnValue; 915 916 if (pdispparams->cNamedArgs > 0) 917 return DISP_E_NONAMEDARGS; 918 919 // invoke method and take care of exceptions 920 returnValue = m_xInvocation->invoke(name, 921 params, 922 outIndex, 923 outParams); 924 925 // try to write back out parameter 926 if (outIndex.getLength() > 0) 927 { 928 const sal_Int16* pOutIndex = outIndex.getConstArray(); 929 const Any* pOutParams = outParams.getConstArray(); 930 931 for (sal_Int32 i = 0; i < outIndex.getLength(); i++) 932 { 933 CComVariant variant; 934 // Currently a Sequence is converted to an SafeArray of VARIANTs. 935 anyToVariant( &variant, pOutParams[i]); 936 937 // out parameter need special handling if they are VT_DISPATCH 938 // and used in JScript 939 int outindex= pOutIndex[i]; 940 writeBackOutParameter2(&(pdispparams->rgvarg[pdispparams->cArgs - 1 - outindex]), 941 &variant ); 942 } 943 } 944 945 // write back return value 946 if (pvarResult != NULL) 947 anyToVariant(pvarResult, returnValue); 948 } 949 catch(IllegalArgumentException & e) //XInvocation::invoke 950 { 951 writeExcepinfo(pexcepinfo, e.Message); 952 ret = DISP_E_TYPEMISMATCH; 953 } 954 catch(CannotConvertException & e) //XInvocation::invoke 955 { 956 writeExcepinfo(pexcepinfo, e.Message); 957 ret = mapCannotConvertException( e, puArgErr); 958 } 959 catch(InvocationTargetException & e) //XInvocation::invoke 960 { 961 const Any& org = e.TargetException; 962 Exception excTarget; 963 org >>= excTarget; 964 OUString message= 965 org.getValueType().getTypeName() + OUSTR(": ") + excTarget.Message; 966 writeExcepinfo(pexcepinfo, message); 967 ret = DISP_E_EXCEPTION; 968 } 969 catch(NoSuchMethodException & e) //XInvocation::invoke 970 { 971 writeExcepinfo(pexcepinfo, e.Message); 972 ret = DISP_E_MEMBERNOTFOUND; 973 } 974 catch(BridgeRuntimeError & e) 975 { 976 writeExcepinfo(pexcepinfo, e.message); 977 ret = DISP_E_EXCEPTION; 978 } 979 catch(Exception & e) 980 { 981 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n") + 982 e.Message; 983 writeExcepinfo(pexcepinfo, message); 984 ret = DISP_E_EXCEPTION; 985 } 986 catch( ... ) 987 { 988 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n" 989 "Unexpected exception"); 990 writeExcepinfo(pexcepinfo, message); 991 ret = DISP_E_EXCEPTION; 992 } 993 return ret; 994 } 995 996 HRESULT InterfaceOleWrapper_Impl::doGetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * pvarResult, 997 EXCEPINFO * pexcepinfo, OUString& name) 998 { 999 HRESULT ret= S_OK; 1000 1001 Any value; 1002 try 1003 { 1004 Any returnValue = m_xInvocation->getValue( name); 1005 // write back return value 1006 if (pvarResult) 1007 anyToVariant(pvarResult, returnValue); 1008 } 1009 catch(UnknownPropertyException e) //XInvocation::getValue 1010 { 1011 writeExcepinfo(pexcepinfo, e.Message); 1012 ret = DISP_E_MEMBERNOTFOUND; 1013 } 1014 catch(BridgeRuntimeError& e) 1015 { 1016 writeExcepinfo(pexcepinfo, e.message); 1017 ret = DISP_E_EXCEPTION; 1018 } 1019 catch(Exception& e) 1020 { 1021 OUString message= OUSTR("InterfaceOleWrapper_Impl::doGetProperty : \n") + 1022 e.Message; 1023 writeExcepinfo(pexcepinfo, message); 1024 } 1025 catch( ... ) 1026 { 1027 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n" 1028 "Unexpected exception"); 1029 writeExcepinfo(pexcepinfo, message); 1030 ret = DISP_E_EXCEPTION; 1031 } 1032 return ret; 1033 } 1034 1035 HRESULT InterfaceOleWrapper_Impl::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/, 1036 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any> params) 1037 { 1038 HRESULT ret= S_OK; 1039 1040 try 1041 { 1042 m_xInvocation->setValue( name, params.getConstArray()[0]); 1043 } 1044 catch(UnknownPropertyException ) 1045 { 1046 ret = DISP_E_MEMBERNOTFOUND; 1047 } 1048 catch(CannotConvertException e) 1049 { 1050 ret= mapCannotConvertException( e, puArgErr); 1051 } 1052 catch(InvocationTargetException e) 1053 { 1054 if (pexcepinfo != NULL) 1055 { 1056 Any org = e.TargetException; 1057 1058 pexcepinfo->wCode = UNO_2_OLE_EXCEPTIONCODE; 1059 pexcepinfo->bstrSource = SysAllocString(L"any ONE component"); 1060 pexcepinfo->bstrDescription = SysAllocString( 1061 reinterpret_cast<LPCOLESTR>(org.getValueType().getTypeName().getStr())); 1062 } 1063 ret = DISP_E_EXCEPTION; 1064 } 1065 catch( ... ) 1066 { 1067 ret= DISP_E_EXCEPTION; 1068 } 1069 return ret; 1070 } 1071 1072 HRESULT InterfaceOleWrapper_Impl::InvokeGeneral( DISPID dispidMember, unsigned short wFlags, 1073 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, 1074 unsigned int * /*puArgErr*/, sal_Bool& bHandled) 1075 { 1076 HRESULT ret= S_OK; 1077 try 1078 { 1079 // DISPID_VALUE | The DEFAULT Value is required in JScript when the situation 1080 // is that we put an object into an Array object ( out parameter). We have to return 1081 // IDispatch otherwise the object cannot be accessed from the Script. 1082 if( dispidMember == DISPID_VALUE && wFlags == DISPATCH_PROPERTYGET 1083 && m_defaultValueType != VT_EMPTY && pvarResult != NULL) 1084 { 1085 bHandled= sal_True; 1086 if( m_defaultValueType == VT_DISPATCH) 1087 { 1088 pvarResult->vt= VT_DISPATCH; 1089 pvarResult->pdispVal= static_cast<IDispatch*>( this); 1090 AddRef(); 1091 ret= S_OK; 1092 } 1093 } 1094 // --------- 1095 // function: _GetValueObject 1096 else if( dispidMember == DISPID_JSCRIPT_VALUE_FUNC) 1097 { 1098 bHandled= sal_True; 1099 if( !pvarResult) 1100 ret= E_POINTER; 1101 CComObject< JScriptValue>* pValue; 1102 if( SUCCEEDED( CComObject<JScriptValue>::CreateInstance( &pValue))) 1103 { 1104 pValue->AddRef(); 1105 pvarResult->vt= VT_DISPATCH; 1106 #ifdef __MINGW32__ 1107 pvarResult->pdispVal= CComQIPtr<IDispatch, &__uuidof(IDispatch)>(pValue->GetUnknown()); 1108 #else 1109 pvarResult->pdispVal= CComQIPtr<IDispatch>(pValue->GetUnknown()); 1110 #endif 1111 ret= S_OK; 1112 } 1113 else 1114 ret= DISP_E_EXCEPTION; 1115 } 1116 else if( dispidMember == DISPID_GET_STRUCT_FUNC) 1117 { 1118 bHandled= sal_True; 1119 sal_Bool bStruct= sal_False; 1120 1121 1122 Reference<XInterface> xIntCore= m_smgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection")); 1123 Reference<XIdlReflection> xRefl( xIntCore, UNO_QUERY); 1124 if( xRefl.is() ) 1125 { 1126 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct. 1127 CComVariant arg; 1128 if( pdispparams->cArgs == 1 && SUCCEEDED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])) ) 1129 { 1130 Reference<XIdlClass> classStruct= xRefl->forName( reinterpret_cast<const sal_Unicode*>(arg.bstrVal)); 1131 if( classStruct.is()) 1132 { 1133 Any anyStruct; 1134 classStruct->createObject( anyStruct); 1135 CComVariant var; 1136 anyToVariant( &var, anyStruct ); 1137 1138 if( var.vt == VT_DISPATCH) 1139 { 1140 VariantCopy( pvarResult, & var); 1141 bStruct= sal_True; 1142 } 1143 } 1144 } 1145 } 1146 ret= bStruct == sal_True ? S_OK : DISP_E_EXCEPTION; 1147 } 1148 else if (dispidMember == DISPID_CREATE_TYPE_FUNC) 1149 { 1150 bHandled= sal_True; 1151 if( !pvarResult) 1152 ret= E_POINTER; 1153 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct. 1154 CComVariant arg; 1155 if( pdispparams->cArgs != 1) 1156 return DISP_E_BADPARAMCOUNT; 1157 if (FAILED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0]))) 1158 return DISP_E_BADVARTYPE; 1159 1160 //check if the provided name represents a valid type 1161 Type type; 1162 if (getType(arg.bstrVal, type) == false) 1163 { 1164 writeExcepinfo(pexcepinfo,OUString( 1165 OUSTR("[automation bridge] A UNO type with the name ") + 1166 OUString(reinterpret_cast<const sal_Unicode*>(arg.bstrVal)) + OUSTR(" does not exist!"))); 1167 return DISP_E_EXCEPTION; 1168 } 1169 1170 if (createUnoTypeWrapper(arg.bstrVal, pvarResult) == false) 1171 { 1172 writeExcepinfo(pexcepinfo,OUSTR("[automation bridge] InterfaceOleWrapper_Impl::InvokeGeneral\n" 1173 "Could not initialize UnoTypeWrapper object!")); 1174 return DISP_E_EXCEPTION; 1175 } 1176 } 1177 } 1178 catch(BridgeRuntimeError & e) 1179 { 1180 writeExcepinfo(pexcepinfo, e.message); 1181 ret = DISP_E_EXCEPTION; 1182 } 1183 catch(Exception & e) 1184 { 1185 OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n") + 1186 e.Message; 1187 writeExcepinfo(pexcepinfo, message); 1188 ret = DISP_E_EXCEPTION; 1189 } 1190 catch( ... ) 1191 { 1192 OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n" 1193 "Unexpected exception"); 1194 writeExcepinfo(pexcepinfo, message); 1195 ret = DISP_E_EXCEPTION; 1196 } 1197 return ret; 1198 } 1199 1200 1201 1202 1203 STDMETHODIMP InterfaceOleWrapper_Impl::GetDispID(BSTR /*bstrName*/, DWORD /*grfdex*/, DISPID __RPC_FAR* /*pid*/) 1204 { 1205 HRESULT ret = ResultFromScode(E_NOTIMPL); 1206 1207 return ret; 1208 } 1209 1210 STDMETHODIMP InterfaceOleWrapper_Impl::InvokeEx( 1211 /* [in] */ DISPID /*id*/, 1212 /* [in] */ LCID /*lcid*/, 1213 /* [in] */ WORD /*wFlags*/, 1214 /* [in] */ DISPPARAMS __RPC_FAR* /*pdp*/, 1215 /* [out] */ VARIANT __RPC_FAR* /*pvarRes*/, 1216 /* [out] */ EXCEPINFO __RPC_FAR* /*pei*/, 1217 /* [unique][in] */ IServiceProvider __RPC_FAR* /*pspCaller*/) 1218 { 1219 HRESULT ret = ResultFromScode(E_NOTIMPL); 1220 1221 return ret; 1222 } 1223 1224 1225 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByName( 1226 /* [in] */ BSTR /*bstr*/, 1227 /* [in] */ DWORD /*grfdex*/) 1228 { 1229 HRESULT ret = ResultFromScode(E_NOTIMPL); 1230 1231 return ret; 1232 } 1233 1234 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByDispID(DISPID /*id*/) 1235 { 1236 HRESULT ret = ResultFromScode(E_NOTIMPL); 1237 1238 return ret; 1239 } 1240 1241 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberProperties( 1242 /* [in] */ DISPID /*id*/, 1243 /* [in] */ DWORD /*grfdexFetch*/, 1244 /* [out] */ DWORD __RPC_FAR* /*pgrfdex*/) 1245 { 1246 HRESULT ret = ResultFromScode(E_NOTIMPL); 1247 1248 return ret; 1249 } 1250 1251 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberName( 1252 /* [in] */ DISPID /*id*/, 1253 /* [out] */ BSTR __RPC_FAR* /*pbstrName*/) 1254 { 1255 HRESULT ret = ResultFromScode(E_NOTIMPL); 1256 1257 return ret; 1258 } 1259 1260 STDMETHODIMP InterfaceOleWrapper_Impl::GetNextDispID( 1261 /* [in] */ DWORD /*grfdex*/, 1262 /* [in] */ DISPID /*id*/, 1263 /* [out] */ DISPID __RPC_FAR* /*pid*/) 1264 { 1265 HRESULT ret = ResultFromScode(E_NOTIMPL); 1266 1267 return ret; 1268 } 1269 1270 STDMETHODIMP InterfaceOleWrapper_Impl::GetNameSpaceParent( 1271 /* [out] */ IUnknown __RPC_FAR *__RPC_FAR* /*ppunk*/) 1272 { 1273 HRESULT ret = ResultFromScode(E_NOTIMPL); 1274 1275 return ret; 1276 } 1277 1278 1279 /************************************************************************* 1280 1281 UnoObjectWrapperRemoteOpt 1282 1283 *************************************************************************/ 1284 UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference<XMultiServiceFactory>& aFactory, 1285 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass): 1286 InterfaceOleWrapper_Impl( aFactory, unoWrapperClass, comWrapperClass), 1287 m_currentId(1) 1288 1289 { 1290 } 1291 UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt() 1292 { 1293 } 1294 1295 // UnoConversionUtilities 1296 Reference< XInterface > UnoObjectWrapperRemoteOpt::createUnoWrapperInstance() 1297 { 1298 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt( 1299 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); 1300 return Reference<XInterface>( xWeak, UNO_QUERY); 1301 } 1302 1303 STDMETHODIMP UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID /*riid*/, OLECHAR ** rgszNames, unsigned int cNames, 1304 LCID /*lcid*/, DISPID * rgdispid ) 1305 { 1306 MutexGuard guard( getBridgeMutex()); 1307 1308 if( ! rgdispid) 1309 return E_POINTER; 1310 HRESULT ret = E_UNEXPECTED; 1311 // ---------------------------------------- 1312 // _GetValueObject 1313 if( ! wcscmp( *rgszNames, JSCRIPT_VALUE_FUNC)) 1314 { 1315 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC; 1316 return S_OK; 1317 } 1318 else if( ! wcscmp( *rgszNames, GET_STRUCT_FUNC)) 1319 { 1320 *rgdispid= DISPID_GET_STRUCT_FUNC; 1321 return S_OK; 1322 } 1323 1324 // ---------------------------------------- 1325 if (m_xInvocation.is() && (cNames > 0)) 1326 { 1327 OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0])); 1328 // has this name been determined as "bad" 1329 BadNameMap::iterator badIter= m_badNameMap.find( name); 1330 if( badIter == m_badNameMap.end() ) 1331 { 1332 // name has not been bad before( member exists 1333 typedef NameToIdMap::iterator ITnames; 1334 pair< ITnames, bool > pair_id= m_nameToDispIdMap.insert( NameToIdMap::value_type(name, m_currentId++)); 1335 // new ID inserted ? 1336 if( pair_id.second ) 1337 {// yes, now create MemberInfo and ad to IdToMemberInfoMap 1338 MemberInfo d(0, name); 1339 m_idToMemberInfoMap.insert( IdToMemberInfoMap::value_type( m_currentId - 1, d)); 1340 } 1341 1342 *rgdispid = pair_id.first->second; 1343 ret = S_OK; 1344 } 1345 else 1346 ret= DISP_E_UNKNOWNNAME; 1347 } 1348 return ret; 1349 } 1350 1351 STDMETHODIMP UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember, REFIID /*riid*/, LCID /*lcid*/, unsigned short wFlags, 1352 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, 1353 unsigned int * puArgErr ) 1354 { 1355 HRESULT ret = S_OK; 1356 try 1357 { 1358 sal_Bool bHandled= sal_False; 1359 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, 1360 puArgErr, bHandled); 1361 if( bHandled) 1362 return ret; 1363 1364 if ( dispidMember > 0 && m_xInvocation.is()) 1365 { 1366 1367 IdToMemberInfoMap::iterator it_MemberInfo= m_idToMemberInfoMap.find( dispidMember); 1368 if( it_MemberInfo != m_idToMemberInfoMap.end() ) 1369 { 1370 MemberInfo& info= it_MemberInfo->second; 1371 1372 Sequence<Any> params; // holds converted any s 1373 if( ! info.flags ) 1374 { // DISPID called for the first time 1375 if( wFlags == DISPATCH_METHOD ) 1376 { 1377 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1378 1379 if( FAILED( ret= doInvoke( pdispparams, pvarResult, 1380 pexcepinfo, puArgErr, info.name, params)) 1381 && ret == DISP_E_MEMBERNOTFOUND) 1382 { 1383 // try to get the exact name 1384 OUString exactName; 1385 if (m_xExactName.is()) 1386 { 1387 exactName = m_xExactName->getExactName( info.name); 1388 // invoke again 1389 if( exactName.getLength() != 0) 1390 { 1391 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult, 1392 pexcepinfo, puArgErr, exactName, params))) 1393 info.name= exactName; 1394 } 1395 } 1396 } 1397 if( SUCCEEDED( ret ) ) 1398 info.flags= DISPATCH_METHOD; 1399 } //if( wFlags == DISPATCH_METHOD ) 1400 1401 else if( wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_PROPERTYPUTREF) 1402 { 1403 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1404 if( FAILED( ret= doSetProperty( pdispparams, pvarResult, 1405 pexcepinfo, puArgErr, info.name, params)) 1406 && ret == DISP_E_MEMBERNOTFOUND) 1407 { 1408 // try to get the exact name 1409 OUString exactName; 1410 if (m_xExactName.is()) 1411 { 1412 exactName = m_xExactName->getExactName( info.name); 1413 // invoke again 1414 if( exactName.getLength() != 0) 1415 { 1416 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult, 1417 pexcepinfo, puArgErr, exactName, params))) 1418 info.name= exactName; 1419 } 1420 } 1421 } 1422 if( SUCCEEDED( ret ) ) 1423 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET; 1424 } 1425 1426 else if( wFlags == DISPATCH_PROPERTYGET) 1427 { 1428 if( FAILED( ret= doGetProperty( pdispparams, pvarResult, 1429 pexcepinfo, info.name)) 1430 && ret == DISP_E_MEMBERNOTFOUND) 1431 { 1432 // try to get the exact name 1433 OUString exactName; 1434 if (m_xExactName.is()) 1435 { 1436 exactName = m_xExactName->getExactName( info.name); 1437 // invoke again 1438 if( exactName.getLength() != 0) 1439 { 1440 if( SUCCEEDED( ret= doGetProperty( pdispparams, pvarResult, 1441 pexcepinfo, exactName))) 1442 info.name= exactName; 1443 } 1444 } 1445 } 1446 if( SUCCEEDED( ret ) ) 1447 info.flags= DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT; 1448 } 1449 else if( wFlags & DISPATCH_METHOD && 1450 (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF)) 1451 { 1452 1453 OUString exactName; 1454 // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT 1455 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1456 // try first as method 1457 if( FAILED( ret= doInvoke( pdispparams, pvarResult, 1458 pexcepinfo, puArgErr, info.name, params)) 1459 && ret == DISP_E_MEMBERNOTFOUND) 1460 { 1461 // try to get the exact name 1462 if (m_xExactName.is()) 1463 { 1464 exactName = m_xExactName->getExactName( info.name); 1465 // invoke again 1466 if( exactName.getLength() != 0) 1467 { 1468 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult, 1469 pexcepinfo, puArgErr, exactName, params))) 1470 info.name= exactName; 1471 } 1472 } 1473 } 1474 if( SUCCEEDED( ret ) ) 1475 info.flags= DISPATCH_METHOD; 1476 1477 // try as property 1478 if( FAILED( ret) && pdispparams->cArgs == 1) 1479 { 1480 if( FAILED( ret= doSetProperty( pdispparams, pvarResult, 1481 pexcepinfo, puArgErr, info.name, params)) 1482 && ret == DISP_E_MEMBERNOTFOUND) 1483 { 1484 // try to get the exact name 1485 if( exactName.getLength() != 0) 1486 { 1487 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult, 1488 pexcepinfo, puArgErr, exactName, params))) 1489 info.name= exactName; 1490 } 1491 } 1492 if( SUCCEEDED( ret ) ) 1493 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET; 1494 } 1495 } 1496 else if( wFlags & DISPATCH_METHOD && wFlags & DISPATCH_PROPERTYGET) 1497 { 1498 OUString exactName; 1499 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1500 1501 if( FAILED( ret= doInvoke( pdispparams, pvarResult, 1502 pexcepinfo, puArgErr, info.name, params)) 1503 && ret == DISP_E_MEMBERNOTFOUND) 1504 { 1505 // try to get the exact name 1506 if (m_xExactName.is()) 1507 { 1508 exactName = m_xExactName->getExactName( info.name); 1509 // invoke again 1510 if( exactName.getLength() != 0) 1511 { 1512 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult, 1513 pexcepinfo, puArgErr, exactName, params))) 1514 info.name= exactName; 1515 } 1516 } 1517 } 1518 if( SUCCEEDED( ret ) ) 1519 info.flags= DISPATCH_METHOD; 1520 1521 // try as property 1522 if( FAILED( ret) && pdispparams->cArgs == 1) 1523 { 1524 if( FAILED( ret= doGetProperty( pdispparams, pvarResult, 1525 pexcepinfo, info.name)) 1526 && ret == DISP_E_MEMBERNOTFOUND) 1527 { 1528 if( exactName.getLength() != 0) 1529 { 1530 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult, 1531 pexcepinfo, puArgErr, exactName, params))) 1532 info.name= exactName; 1533 } 1534 } 1535 if( SUCCEEDED( ret ) ) 1536 info.flags= DISPATCH_PROPERTYGET; 1537 } 1538 } 1539 1540 // update �nformation about this member 1541 if( ret == DISP_E_MEMBERNOTFOUND) 1542 { 1543 // Remember the name as not existing 1544 // and remove the MemberInfo 1545 m_badNameMap[info.name]= sal_False; 1546 m_idToMemberInfoMap.erase( it_MemberInfo); 1547 } 1548 } // if( ! info.flags ) 1549 else // IdToMemberInfoMap contains a MemberInfo 1550 { 1551 if( wFlags & DISPATCH_METHOD && info.flags == DISPATCH_METHOD) 1552 { 1553 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1554 ret= doInvoke( pdispparams, pvarResult, 1555 pexcepinfo, puArgErr, info.name, params); 1556 } 1557 else if( (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF ) && 1558 info.flags & DISPATCH_PROPERTYPUT) 1559 { 1560 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); 1561 ret= doSetProperty( pdispparams, pvarResult, 1562 pexcepinfo, puArgErr, info.name, params); 1563 } 1564 else if( (wFlags & DISPATCH_PROPERTYGET) && ( info.flags & DISPATCH_PROPERTYGET)) 1565 { 1566 ret= doGetProperty( pdispparams, pvarResult, 1567 pexcepinfo, info.name); 1568 } 1569 else 1570 { 1571 ret= DISP_E_MEMBERNOTFOUND; 1572 } 1573 } 1574 }// if( it_MemberInfo != m_idToMemberInfoMap.end() ) 1575 else 1576 ret= DISP_E_MEMBERNOTFOUND; 1577 } 1578 } 1579 catch(BridgeRuntimeError& e) 1580 { 1581 writeExcepinfo(pexcepinfo, e.message); 1582 ret = DISP_E_EXCEPTION; 1583 } 1584 catch(Exception& e) 1585 { 1586 OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n") + 1587 e.Message; 1588 writeExcepinfo(pexcepinfo, message); 1589 ret = DISP_E_EXCEPTION; 1590 } 1591 catch(...) 1592 { 1593 OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n" 1594 "Unexpected exception"); 1595 writeExcepinfo(pexcepinfo, message); 1596 ret = DISP_E_EXCEPTION; 1597 } 1598 1599 return ret; 1600 } 1601 1602 HRESULT UnoObjectWrapperRemoteOpt::methodInvoke( DISPID /*dispidMember*/, DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/, 1603 EXCEPINFO * /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence<Any> params) 1604 { 1605 return S_OK; 1606 } 1607 1608 1609 // The returned HRESULT is only appropriate for IDispatch::Invoke 1610 static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr) 1611 { 1612 HRESULT ret; 1613 sal_Bool bWriteIndex= sal_True; 1614 1615 switch ( e.Reason) 1616 { 1617 case FailReason::OUT_OF_RANGE: 1618 ret = DISP_E_OVERFLOW; 1619 break; 1620 case FailReason::IS_NOT_NUMBER: 1621 ret = DISP_E_TYPEMISMATCH; 1622 break; 1623 case FailReason::IS_NOT_ENUM: 1624 ret = DISP_E_TYPEMISMATCH; 1625 break; 1626 case FailReason::IS_NOT_BOOL: 1627 ret = DISP_E_TYPEMISMATCH; 1628 break; 1629 case FailReason::NO_SUCH_INTERFACE: 1630 ret = DISP_E_TYPEMISMATCH; 1631 break; 1632 case FailReason::SOURCE_IS_NO_DERIVED_TYPE: 1633 ret = DISP_E_TYPEMISMATCH; 1634 break; 1635 case FailReason::TYPE_NOT_SUPPORTED: 1636 ret = DISP_E_TYPEMISMATCH; 1637 break; 1638 case FailReason::INVALID: 1639 ret = DISP_E_TYPEMISMATCH; 1640 break; 1641 case FailReason::NO_DEFAULT_AVAILABLE: 1642 ret = DISP_E_BADPARAMCOUNT; 1643 break; 1644 case FailReason::UNKNOWN: 1645 ret = E_UNEXPECTED; 1646 break; 1647 default: 1648 ret = E_UNEXPECTED; 1649 bWriteIndex= sal_False; 1650 break; 1651 } 1652 1653 if( bWriteIndex && puArgErr != NULL) 1654 *puArgErr = e.ArgumentIndex; 1655 return ret; 1656 } 1657 1658 // The function maps the TypeClass of the any to VARTYPE: If 1659 // the Any contains STRUCT or INTERFACE then the return value 1660 // is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper 1661 // and the result is put into the constructor of the uno - wrapper 1662 // object. If a client asks the object for DISPID_VALUE and this 1663 // function returned VT_DISPATCH then the IDispatch of the same 1664 // object is being returned. 1665 // See InterfaceOleWrapper_Impl::Invoke, InterfaceOleWrapper_Impl::m_defaultValueType 1666 const VARTYPE getVarType( const Any& value) 1667 { 1668 VARTYPE ret= VT_EMPTY; 1669 1670 switch ( value.getValueTypeClass()) 1671 { 1672 case TypeClass_STRUCT: ret= VT_DISPATCH; break; 1673 case TypeClass_INTERFACE: ret= VT_DISPATCH; break; 1674 default: break; 1675 } 1676 return ret; 1677 } 1678 1679 1680 1681 1682 } // end namespace 1683