bump product version to 4.1.6.2
[LibreOffice.git] / extensions / source / ole / unoobjw.cxx
blob2899abae17156d02c4ada15446d6947565247993
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "ole2uno.hxx"
21 #if _WIN32_WINNT != 0x403
22 #error wrong _WIN32_WINNT
23 #endif
24 #include <stdio.h>
25 #include <vector>
26 #include <list>
27 #include <boost/unordered_map.hpp>
30 #include <osl/diagnose.h>
31 #include <salhelper/simplereferenceobject.hxx>
32 #include <rtl/ustring.hxx>
33 #include <com/sun/star/beans/MethodConcept.hpp>
34 #include <com/sun/star/beans/PropertyConcept.hpp>
35 #include <com/sun/star/script/FailReason.hpp>
36 #include <com/sun/star/reflection/theCoreReflection.hpp>
37 #include <com/sun/star/reflection/ParamInfo.hpp>
38 #include <com/sun/star/beans/XExactName.hpp>
39 #include <com/sun/star/container/NoSuchElementException.hpp>
41 #include <com/sun/star/beans/XMaterialHolder.hpp>
42 #include <com/sun/star/script/XInvocation2.hpp>
43 #include <com/sun/star/script/MemberType.hpp>
44 #include <com/sun/star/reflection/XIdlReflection.hpp>
45 #include <osl/interlck.h>
46 #include <com/sun/star/uno/genfunc.h>
47 #include <comphelper/processfactory.hxx>
48 #include <cppuhelper/implbase1.hxx>
50 #include "comifaces.hxx"
51 #include "jscriptclasses.hxx"
52 #include "unotypewrapper.hxx"
53 #include "oleobjw.hxx"
54 #include "unoobjw.hxx"
55 #include "servprov.hxx"
57 using namespace std;
58 using namespace osl;
59 using namespace cppu;
60 using namespace com::sun::star::uno;
61 using namespace com::sun::star::beans;
62 using namespace com::sun::star::container;
63 using namespace com::sun::star::script;
64 using namespace com::sun::star::lang;
65 using namespace com::sun::star::bridge::ModelDependent;
66 using namespace com::sun::star::reflection;
69 #ifndef _MSC_VER
70 extern "C" const GUID IID_IDispatchEx;
71 #endif
73 namespace ole_adapter
75 boost::unordered_map<sal_uInt32, WeakReference<XInterface> > UnoObjToWrapperMap;
76 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource);
77 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource);
78 static HRESULT mapCannotConvertException(const CannotConvertException &e, unsigned int * puArgErr);
81 /* Does not throw any exceptions.
82 Param pInfo can be NULL.
84 static void writeExcepinfo(EXCEPINFO * pInfo, const OUString& message)
86 if (pInfo != NULL)
88 pInfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
89 pInfo->bstrSource = SysAllocString(L"[automation bridge] ");
90 pInfo->bstrDescription = SysAllocString(reinterpret_cast<LPCOLESTR>(message.getStr()));
94 /*****************************************************************************
96 class implementation: InterfaceOleWrapper_Impl
98 *****************************************************************************/
99 InterfaceOleWrapper_Impl::InterfaceOleWrapper_Impl( Reference<XMultiServiceFactory>& xFactory,
100 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
101 m_defaultValueType( 0),
102 UnoConversionUtilities<InterfaceOleWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass)
106 InterfaceOleWrapper_Impl::~InterfaceOleWrapper_Impl()
108 MutexGuard guard(getBridgeMutex());
109 // remove entries in global map
110 IT_Uno it= UnoObjToWrapperMap.find( (sal_uInt32) m_xOrigin.get());
111 if(it != UnoObjToWrapperMap.end())
112 UnoObjToWrapperMap.erase(it);
113 #if OSL_DEBUG_LEVEL > 0
114 fprintf(stderr,"[automation bridge] UnoObjToWrapperMap contains: %i \n",
115 UnoObjToWrapperMap.size());
116 #endif
120 STDMETHODIMP InterfaceOleWrapper_Impl::QueryInterface(REFIID riid, LPVOID FAR * ppv)
122 HRESULT ret= S_OK;
124 if( !ppv)
125 return E_POINTER;
127 if(IsEqualIID(riid, IID_IUnknown))
129 AddRef();
130 *ppv = (IUnknown*) (IDispatch*) this;
132 else if (IsEqualIID(riid, IID_IDispatch))
134 AddRef();
135 *ppv = (IDispatch*) this;
137 else if( IsEqualIID( riid, __uuidof( IUnoObjectWrapper)))
139 AddRef();
140 *ppv= (IUnoObjectWrapper*) this;
142 else
143 ret= E_NOINTERFACE;
144 return ret;
147 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::AddRef()
149 acquire();
150 // does not need to guard because one should not rely on the return value of
151 // AddRef anyway
152 return m_refCount;
155 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::Release()
157 ULONG n= m_refCount;
158 release();
159 return n - 1;
162 // IUnoObjectWrapper --------------------------------------------------------
163 STDMETHODIMP InterfaceOleWrapper_Impl::getWrapperXInterface( Reference<XInterface>* pXInt)
165 *pXInt= Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY);
166 return pXInt->is() ? S_OK : E_FAIL;
168 STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoObject( Reference<XInterface>* pXInt)
170 *pXInt= m_xOrigin;
171 return m_xOrigin.is() ? S_OK : E_FAIL;
173 STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoStruct( Any * pStruct)
175 HRESULT ret= E_FAIL;
176 if( !m_xOrigin.is())
178 Reference<XMaterialHolder> xMatHolder( m_xInvocation, UNO_QUERY);
179 if( xMatHolder.is())
181 Any any = xMatHolder->getMaterial();
182 if( any.getValueTypeClass() == TypeClass_STRUCT)
184 *pStruct= any;
185 ret= S_OK;
189 return ret;
192 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfoCount( unsigned int * /*pctinfo*/ )
194 return E_NOTIMPL ;
197 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfo(unsigned int /*itinfo*/, LCID /*lcid*/, ITypeInfo ** /*pptinfo*/)
199 return E_NOTIMPL;
202 STDMETHODIMP InterfaceOleWrapper_Impl::GetIDsOfNames(REFIID /*riid*/,
203 OLECHAR ** rgszNames,
204 unsigned int cNames,
205 LCID /*lcid*/,
206 DISPID * rgdispid )
208 HRESULT ret = DISP_E_UNKNOWNNAME;
211 MutexGuard guard( getBridgeMutex());
212 if( ! rgdispid)
213 return E_POINTER;
215 // ----------------------------------------
216 if( ! _wcsicmp( *rgszNames, JSCRIPT_VALUE_FUNC) ||
217 ! _wcsicmp( *rgszNames, BRIDGE_VALUE_FUNC))
219 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
220 return S_OK;
222 else if( ! _wcsicmp( *rgszNames, GET_STRUCT_FUNC) ||
223 ! _wcsicmp( *rgszNames, BRIDGE_GET_STRUCT_FUNC))
225 *rgdispid= DISPID_GET_STRUCT_FUNC;
226 return S_OK;
228 else if( ! _wcsicmp( *rgszNames, BRIDGE_CREATE_TYPE_FUNC))
230 *rgdispid= DISPID_CREATE_TYPE_FUNC;
231 return S_OK;
234 // ----------------------------------------
235 if (m_xInvocation.is() && (cNames > 0))
237 OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0]));
238 NameToIdMap::iterator iter = m_nameToDispIdMap.find(name);
240 if (iter == m_nameToDispIdMap.end())
242 OUString exactName;
244 if (m_xExactName.is())
246 exactName = m_xExactName->getExactName(name);
248 else
250 exactName = name;
253 MemberInfo d(0, exactName);
255 if (m_xInvocation->hasProperty(exactName))
257 d.flags |= DISPATCH_PROPERTYGET;
258 d.flags |= DISPATCH_PROPERTYPUT;
259 d.flags |= DISPATCH_PROPERTYPUTREF;
262 if (m_xInvocation->hasMethod(exactName))
264 d.flags |= DISPATCH_METHOD;
267 if (d.flags != 0)
269 m_MemberInfos.push_back(d);
270 iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(exactName, (DISPID)m_MemberInfos.size())).first;
272 if (exactName != name)
274 iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(name, (DISPID)m_MemberInfos.size())).first;
279 if (iter == m_nameToDispIdMap.end())
281 ret = DISP_E_UNKNOWNNAME;
283 else
285 *rgdispid = (*iter).second;
286 ret = S_OK;
290 catch(const BridgeRuntimeError&)
292 OSL_ASSERT(0);
294 catch(const Exception&)
296 OSL_ASSERT(0);
298 catch(...)
300 OSL_ASSERT(0);
303 return ret;
306 // "convertDispparamsArgs" converts VARIANTS to their respecting Any counterparts
307 // The parameters "id", "wFlags" and "pdispparams" equal those as used in
308 // IDispatch::Invoke. The function handles special JavaScript
309 // cases where a VARIANT of type VT_DISPATCH is ambiguous and could represent
310 // an object, array ( JavaScript Array object), out parameter and in/out ( JavaScript Array object)
311 // parameter (JavaScript Array object)
312 // Because all those VT_DISPATCH objects need a different conversion
313 // we have to find out what the object is supposed to be. The function does this
314 // by either using type information or by help of a specialized ValueObject object.
316 // A. Type Information
317 // -----------------------------------------------------------------------------
318 // With the help of type information the kind of parameter can be exactly determined
319 // and an appropriate conversion can be choosen. A problem arises if a method expects
320 // an Any. Then the type info does not tell what the type of the value, that is kept
321 // by the any, should be. In this situation the decision wheter the param is a
322 // sequence or an object is made upon the fact if the object has a property "0"
323 // ( see function "isJScriptArray"). Since this is unsafe it is recommended to use
324 // the JScript value objects within a JScript script on such an occasion.
326 // B. JavaScript Value Object ( class JScriptValue )
327 // -----------------------------------------------------------------------------
328 // A JScriptValue (ValueObject) object is a COM object in that it implements IDispatch and the
329 // IJScriptValue object interface. Such objects are provided by all UNO wrapper
330 // objects used within a JScript script. To obtain an instance one has to call
331 // "_GetValueObject() or Bridge_GetValueObject()" on an UNO wrapper object (class InterfaceOleWrapper_Impl).
332 // A value object is appropriately initialized within the script and passed as
333 // parameter to an UNO object method or property. The convertDispparamsArgs function
334 // can easily find out that a param is such an object by queriing for the
335 // IJScriptValue interface. By this interface one the type and kind ( out, in/out)
336 // can be determined and the right conversion can be applied.
337 // Using ValueObjects we spare us the effort of aquiring and examining type information
338 // in order to figure out what the an IDispatch parameter is meant for.
340 // Normal JScript object parameter can be mixed with JScriptValue object. If an
341 // VARIANT contains an VT_DISPATCH that is no JScriptValue than the type information
342 // is used to find out about the reqired type.
343 void InterfaceOleWrapper_Impl::convertDispparamsArgs(DISPID id,
344 unsigned short /*wFlags*/, DISPPARAMS* pdispparams, Sequence<Any>& rSeq)
346 HRESULT hr= S_OK;
347 sal_Int32 countArgs= pdispparams->cArgs;
348 if( countArgs == 0)
349 return;
351 rSeq.realloc( countArgs);
352 Any* pParams = rSeq.getArray();
354 Any anyParam;
356 //Get type information for the current call
357 InvocationInfo info;
358 if( ! getInvocationInfoForCall( id, info))
359 throw BridgeRuntimeError(
360 "[automation bridge]InterfaceOleWrapper_Impl::convertDispparamsArgs \n"
361 "Could not obtain type information for current call.");
363 for (int i = 0; i < countArgs; i++)
365 if (info.eMemberType == MemberType_METHOD &&
366 info.aParamModes[ countArgs - i -1 ] == ParamMode_OUT)
367 continue;
369 if(convertValueObject( & pdispparams->rgvarg[i], anyParam))
370 { //a param is a ValueObject and could be converted
371 pParams[countArgs - (i + 1)] = anyParam;
372 continue;
375 // If the param is an out, in/out parameter in
376 // JScript (Array object, with value at index 0) then we
377 // extract Array[0] and put the value into varParam. At the end of the loop varParam
378 // is converted if it contains a value otherwise the VARIANT from
379 // DISPPARAMS is converted.
380 CComVariant varParam;
382 // Check for JScript out and in/out paramsobjects (VT_DISPATCH).
383 // To find them out we use typeinformation of the function being called.
384 if( pdispparams->rgvarg[i].vt == VT_DISPATCH )
386 if( info.eMemberType == MemberType_METHOD && info.aParamModes[ countArgs - i -1 ] == ParamMode_INOUT)
388 // INOUT-param
389 // Index ( property) "0" contains the actual IN-param. The object is a JScript
390 // Array object.
391 // Get the IN-param at index "0"
392 IDispatch* pdisp= pdispparams->rgvarg[i].pdispVal;
394 OLECHAR* sindex= L"0";
395 DISPID id;
396 DISPPARAMS noParams= {0,0,0,0};
397 if(SUCCEEDED( hr= pdisp->GetIDsOfNames( IID_NULL, &sindex, 1, LOCALE_USER_DEFAULT, &id)))
398 hr= pdisp->Invoke( id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
399 & noParams, & varParam, NULL, NULL);
400 if( FAILED( hr))
402 throw BridgeRuntimeError(
403 "[automation bridge] Could not determine "
404 "if the object has a member \"0\". Error: " +
405 OUString::valueOf(hr));
410 if( varParam.vt == VT_EMPTY) // then it was no in/out parameter
411 varParam= pdispparams->rgvarg[i];
413 if(info.eMemberType == MemberType_METHOD)
414 variantToAny( & varParam, anyParam,
415 info.aParamTypes[ countArgs - i - 1]);
416 else if(info.eMemberType == MemberType_PROPERTY)
417 variantToAny( & varParam, anyParam, info.aType);
418 else
419 OSL_ASSERT(0);
421 pParams[countArgs - (i + 1)]= anyParam;
422 }// end for / iterating over all parameters
425 sal_Bool InterfaceOleWrapper_Impl::getInvocationInfoForCall( DISPID id, InvocationInfo& info)
427 sal_Bool bTypesAvailable= sal_False;
429 if( !m_xInvocation.is() )return false;
430 Reference<XInvocation2> inv2( m_xInvocation, UNO_QUERY);
431 if( inv2.is())
433 // We need the name of the property or method to get its type information.
434 // The name can be identified through the param "id"
435 // that is kept as value in the map m_nameToDispIdMap.
436 // Proplem: the Windows JScript engine sometimes changes small letters to capital
437 // letters as happens in xidlclass_obj.createObject( var) // in JScript.
438 // IDispatch::GetIdsOfNames is then called with "CreateObject" !!!
439 // m_nameToDispIdMap can contain several names for one DISPID but only one is
440 // the exact one. If there's no m_xExactName and therefore no exact name then
441 // there's only one entry in the map.
442 typedef NameToIdMap::const_iterator cit;
443 OUString sMemberName;
445 for(cit ci1= m_nameToDispIdMap.begin(); ci1 != m_nameToDispIdMap.end(); ++ci1)
447 if( (*ci1).second == id) // iterator is a pair< OUString, DISPID>
449 sMemberName= (*ci1).first;
450 break;
453 // Get information for the current call ( property or method).
454 // There could be similar names which only differ in the cases
455 // of letters. First we assume that the name which was passed into
456 // GetIDsOfNames is correct. If we won't get information with that
457 // name then we have the invocation service use the XExactName interface.
458 sal_Bool validInfo= sal_True;
459 InvocationInfo invInfo;
460 try{
461 invInfo= inv2->getInfoForName( sMemberName, sal_False);
463 catch(const IllegalArgumentException&)
465 validInfo= sal_False;
468 if( ! validInfo)
470 invInfo= inv2->getInfoForName( sMemberName, sal_True);
472 if( invInfo.aName.pData)
474 bTypesAvailable= sal_True;
475 info= invInfo;
478 return bTypesAvailable;
480 // XBridgeSupplier2 ---------------------------------------------------
481 // only bridges itself ( this instance of InterfaceOleWrapper_Impl)from UNO to IDispatch
482 // If sourceModelType is UNO than any UNO interface implemented by InterfaceOleWrapper_Impl
483 // can bridged to IDispatch ( if destModelType == OLE). The IDispatch is
484 // implemented by this class.
485 Any SAL_CALL InterfaceOleWrapper_Impl::createBridge(const Any& modelDepObject,
486 const Sequence<sal_Int8>& /*ProcessId*/,
487 sal_Int16 sourceModelType,
488 sal_Int16 destModelType)
489 throw (IllegalArgumentException, RuntimeException)
492 Any retAny;
493 if( sourceModelType == UNO && destModelType == OLE &&
494 modelDepObject.getValueTypeClass() == TypeClass_INTERFACE )
496 Reference<XInterface> xInt;
497 if( modelDepObject >>= xInt )
499 if( xInt == Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY))
501 VARIANT *pVar= (VARIANT*)CoTaskMemAlloc( sizeof( VARIANT));
502 if( pVar)
504 pVar->vt= VT_DISPATCH;
505 pVar->pdispVal= static_cast<IDispatch*>( this);
506 AddRef();
508 retAny<<= reinterpret_cast< sal_uInt32 >( pVar);
514 return retAny;
518 // XInitialization --------------------------------------------------
519 void SAL_CALL InterfaceOleWrapper_Impl::initialize( const Sequence< Any >& aArguments )
520 throw(Exception, RuntimeException)
522 switch( aArguments.getLength() )
524 case 2: // the object wraps an UNO struct
525 aArguments[0] >>= m_xInvocation;
526 aArguments[1] >>= m_defaultValueType;
527 break;
528 case 3: // the object wraps an UNO interface
529 aArguments[0] >>= m_xInvocation;
530 aArguments[1] >>= m_xOrigin;
531 aArguments[2] >>= m_defaultValueType;
532 break;
535 m_xExactName= Reference<XExactName>( m_xInvocation, UNO_QUERY);
538 Reference< XInterface > InterfaceOleWrapper_Impl::createUnoWrapperInstance()
540 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl(
541 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
542 return Reference<XInterface>( xWeak, UNO_QUERY);
545 Reference<XInterface> InterfaceOleWrapper_Impl::createComWrapperInstance()
547 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl(
548 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
549 return Reference<XInterface>( xWeak, UNO_QUERY);
554 // "getType" is used in convertValueObject to map the string denoting the type
555 // to an actual Type object.
556 bool getType( const BSTR name, Type & type)
558 Type retType;
559 bool ret = false;
560 typelib_TypeDescription * pDesc= NULL;
561 OUString str( reinterpret_cast<const sal_Unicode*>(name));
562 typelib_typedescription_getByName( &pDesc, str.pData );
563 if( pDesc)
565 type = Type( pDesc->pWeakRef );
566 typelib_typedescription_release( pDesc);
567 ret = true;
569 return ret;
572 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource)
574 sal_Bool ret = sal_False;
575 HRESULT hr;
577 // Handle JScriptValue objects and JScript out params ( Array object )
578 CComVariant varDest( *pDest);
580 if( SUCCEEDED( varDest.ChangeType(VT_DISPATCH)))
582 CComPtr<IDispatch> spDispDest(varDest.pdispVal);
584 // special Handling for a JScriptValue object
585 #ifdef __MINGW32__
586 CComQIPtr<IJScriptValueObject, &__uuidof(IJScriptValueObject)> spValueDest(spDispDest);
587 #else
588 CComQIPtr<IJScriptValueObject> spValueDest(spDispDest);
589 #endif
590 if (spValueDest)
592 VARIANT_BOOL varBool= VARIANT_FALSE;
593 if( SUCCEEDED( hr= spValueDest->IsOutParam( &varBool) )
594 && varBool == VARIANT_TRUE ||
595 SUCCEEDED(hr= spValueDest->IsInOutParam( &varBool) )
596 && varBool == VARIANT_TRUE )
598 if( SUCCEEDED( spValueDest->Set( CComVariant(), *pSource)))
599 ret= sal_True;
602 else if (pDest->vt == VT_DISPATCH)// VT_DISPATCH -> JScript out param
604 // We use IDispatchEx because its GetDispID function causes the creation
605 // of a property if it does not exist already. This is convenient for
606 // out parameters in JScript. Then the user must not specify propery "0"
607 // explicitly
608 #ifdef __MINGW32__
609 CComQIPtr<IDispatchEx, &__uuidof(IDispatchEx)> spDispEx( spDispDest);
610 #else
611 CComQIPtr<IDispatchEx> spDispEx( spDispDest);
612 #endif
613 if( spDispEx)
615 CComBSTR nullProp(L"0");
616 DISPID dwDispID;
617 if( SUCCEEDED( spDispEx->GetDispID( nullProp, fdexNameEnsure, &dwDispID)))
619 DISPPARAMS dispparams = {NULL, NULL, 1, 1};
620 dispparams.rgvarg = pSource;
621 DISPID dispidPut = DISPID_PROPERTYPUT;
622 dispparams.rgdispidNamedArgs = &dispidPut;
624 if (pSource->vt == VT_UNKNOWN || pSource->vt == VT_DISPATCH ||
625 (pSource->vt & VT_ARRAY) || (pSource->vt & VT_BYREF))
626 hr = spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
627 &dispparams, NULL, NULL, NULL);
628 else
629 hr= spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
630 &dispparams, NULL, NULL, NULL);
631 if( SUCCEEDED(hr))
632 ret= sal_True;
636 else
637 ret= writeBackOutParameter( pDest, pSource);
639 else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript
640 { // param. The function checks itself for correct VBScript params
641 ret= writeBackOutParameter( pDest, pSource);
643 return ret;
645 // VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter.
646 // Thus we are in charge of freeing an eventual value contained by the inner VARIANT
647 // Please note: VariantCopy doesn't free a VT_BYREF value
648 // The out parameters are expected to have always a valid type
649 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource)
651 HRESULT hr;
652 sal_Bool ret = FALSE;
653 // Out parameter must be VT_BYREF
654 if ((V_VT(pDest) & VT_BYREF) != 0 )
656 VARTYPE oleTypeFlags = V_VT(pSource);
658 // if caller accept VARIANT as out parameter, any value must be converted
659 if (V_VT(pDest) == (VT_VARIANT | VT_BYREF))
661 // When the user provides a VARIANT rather then a concrete type
662 // we just copy the source to the out, in/out parameter
663 // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that
664 // is contained in pDest are released by VariantCopy
665 VariantCopy(V_VARIANTREF(pDest), pSource);
666 ret = sal_True;
668 else
670 // variantarg and variant must have same type
671 if ((V_VT(pDest) & oleTypeFlags) == oleTypeFlags)
673 if ((oleTypeFlags & VT_ARRAY) != 0)
675 // In / Out Param
676 if( *V_ARRAYREF(pDest) != NULL)
677 hr= SafeArrayCopyData( V_ARRAY(pSource), *V_ARRAYREF(pDest));
678 else
679 // Out Param
680 hr= SafeArrayCopy(V_ARRAY(pSource), V_ARRAYREF(pDest)) == NOERROR;
681 if( SUCCEEDED( hr))
682 ret = sal_True;
684 else
686 // copy base type
687 switch (V_VT(pSource))
689 case VT_I2:
691 *V_I2REF(pDest) = V_I2(pSource);
692 ret = sal_True;
693 break;
695 case VT_I4:
696 *V_I4REF(pDest) = V_I4(pSource);
697 ret = sal_True;
698 break;
699 case VT_R4:
700 *V_R4REF(pDest) = V_R4(pSource);
701 ret = sal_True;
702 break;
703 case VT_R8:
704 *V_R8REF(pDest) = V_R8(pSource);
705 ret = sal_True;
706 break;
707 case VT_CY:
708 *V_CYREF(pDest) = V_CY(pSource);
709 ret = sal_True;
710 break;
711 case VT_DATE:
712 *V_DATEREF(pDest) = V_DATE(pSource);
713 ret = sal_True;
714 break;
715 case VT_BSTR:
716 SysFreeString( *pDest->pbstrVal);
718 *V_BSTRREF(pDest) = SysAllocString(V_BSTR(pSource));
719 ret = sal_True;
720 break;
721 case VT_DISPATCH:
722 if (*V_DISPATCHREF(pDest) != NULL)
723 (*V_DISPATCHREF(pDest))->Release();
725 *V_DISPATCHREF(pDest) = V_DISPATCH(pSource);
727 if (*V_DISPATCHREF(pDest) != NULL)
728 (*V_DISPATCHREF(pDest))->AddRef();
730 ret = sal_True;
731 break;
732 case VT_ERROR:
733 *V_ERRORREF(pDest) = V_ERROR(pSource);
734 ret = sal_True;
735 break;
736 case VT_BOOL:
737 *V_BOOLREF(pDest) = V_BOOL(pSource);
738 ret = sal_True;
739 break;
740 case VT_UNKNOWN:
741 if (*V_UNKNOWNREF(pDest) != NULL)
742 (*V_UNKNOWNREF(pDest))->Release();
744 *V_UNKNOWNREF(pDest) = V_UNKNOWN(pSource);
746 if (*V_UNKNOWNREF(pDest) != NULL)
747 (*V_UNKNOWNREF(pDest))->AddRef();
749 ret = sal_True;
750 break;
751 case VT_I1:
752 *V_I1REF(pDest) = V_I1(pSource);
753 ret = sal_True;
754 break;
755 case VT_UI1:
756 *V_UI1REF(pDest) = V_UI1(pSource);
757 ret = sal_True;
758 break;
759 case VT_UI2:
760 *V_UI2REF(pDest) = V_UI2(pSource);
761 ret = sal_True;
762 break;
763 case VT_UI4:
764 *V_UI4REF(pDest) = V_UI4(pSource);
765 ret = sal_True;
766 break;
767 case VT_INT:
768 *V_INTREF(pDest) = V_INT(pSource);
769 ret = sal_True;
770 break;
771 case VT_UINT:
772 *V_UINTREF(pDest) = V_UINT(pSource);
773 ret = sal_True;
774 break;
775 case VT_DECIMAL:
776 memcpy(pDest->pdecVal, pSource, sizeof(DECIMAL));
777 ret = sal_True;
778 break;
779 default:
780 break;
784 else
786 // Handling of special cases
787 // Destination and source types are different
788 if( pDest->vt == (VT_BSTR | VT_BYREF)
789 && pSource->vt == VT_I2)
791 // When the user provides a String as out our in/out parameter
792 // and the type is char (TypeClass_CHAR) then we convert to a BSTR
793 // instead of VT_I2 as is done otherwise
794 OLECHAR buff[]= {0,0};
795 buff[0]= pSource->iVal;
797 SysFreeString( *pDest->pbstrVal);
798 *pDest->pbstrVal= SysAllocString( buff);
799 ret = sal_True;
804 return ret;
807 STDMETHODIMP InterfaceOleWrapper_Impl::Invoke(DISPID dispidMember,
808 REFIID /*riid*/,
809 LCID /*lcid*/,
810 unsigned short wFlags,
811 DISPPARAMS * pdispparams,
812 VARIANT * pvarResult,
813 EXCEPINFO * pexcepinfo,
814 unsigned int * puArgErr )
816 HRESULT ret = S_OK;
820 sal_Bool bHandled= sal_False;
821 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo,
822 puArgErr, bHandled);
823 if( bHandled)
824 return ret;
826 if ((dispidMember > 0) && ((size_t)dispidMember <= m_MemberInfos.size()) && m_xInvocation.is())
828 MemberInfo d = m_MemberInfos[dispidMember - 1];
829 DWORD flags = wFlags & d.flags;
831 if (flags != 0)
833 if ((flags & DISPATCH_METHOD) != 0)
835 if (pdispparams->cNamedArgs > 0)
836 ret = DISP_E_NONAMEDARGS;
837 else
839 Sequence<Any> params;
841 convertDispparamsArgs(dispidMember, wFlags, pdispparams , params );
843 ret= doInvoke(pdispparams, pvarResult,
844 pexcepinfo, puArgErr, d.name, params);
847 else if ((flags & DISPATCH_PROPERTYGET) != 0)
849 ret= doGetProperty( pdispparams, pvarResult,
850 pexcepinfo, d.name);
852 else if ((flags & DISPATCH_PROPERTYPUT || flags & DISPATCH_PROPERTYPUTREF) != 0)
854 if (pdispparams->cArgs != 1)
855 ret = DISP_E_BADPARAMCOUNT;
856 else
858 Sequence<Any> params;
859 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
860 if(params.getLength() > 0)
861 ret= doSetProperty( pdispparams, pvarResult, pexcepinfo, puArgErr, d.name, params);
862 else
863 ret = DISP_E_BADVARTYPE;
867 else
868 ret= DISP_E_MEMBERNOTFOUND;
870 else
871 ret = DISP_E_MEMBERNOTFOUND;
873 catch(const BridgeRuntimeError& e)
875 writeExcepinfo(pexcepinfo, e.message);
876 ret = DISP_E_EXCEPTION;
878 catch(const Exception& e)
880 OUString message= "InterfaceOleWrapper_Impl::Invoke : \n" +
881 e.Message;
882 writeExcepinfo(pexcepinfo, message);
883 ret = DISP_E_EXCEPTION;
885 catch(...)
887 OUString message= "InterfaceOleWrapper_Impl::Invoke : \n"
888 "Unexpected exception";
889 writeExcepinfo(pexcepinfo, message);
890 ret = DISP_E_EXCEPTION;
893 return ret;
896 HRESULT InterfaceOleWrapper_Impl::doInvoke( DISPPARAMS * pdispparams, VARIANT * pvarResult,
897 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any>& params)
901 HRESULT ret= S_OK;
904 Sequence<sal_Int16> outIndex;
905 Sequence<Any> outParams;
906 Any returnValue;
908 if (pdispparams->cNamedArgs > 0)
909 return DISP_E_NONAMEDARGS;
911 // invoke method and take care of exceptions
912 returnValue = m_xInvocation->invoke(name,
913 params,
914 outIndex,
915 outParams);
917 // try to write back out parameter
918 if (outIndex.getLength() > 0)
920 const sal_Int16* pOutIndex = outIndex.getConstArray();
921 const Any* pOutParams = outParams.getConstArray();
923 for (sal_Int32 i = 0; i < outIndex.getLength(); i++)
925 CComVariant variant;
926 // Currently a Sequence is converted to an SafeArray of VARIANTs.
927 anyToVariant( &variant, pOutParams[i]);
929 // out parameter need special handling if they are VT_DISPATCH
930 // and used in JScript
931 int outindex= pOutIndex[i];
932 writeBackOutParameter2(&(pdispparams->rgvarg[pdispparams->cArgs - 1 - outindex]),
933 &variant );
937 // write back return value
938 if (pvarResult != NULL)
939 anyToVariant(pvarResult, returnValue);
941 catch(const IllegalArgumentException & e) //XInvocation::invoke
943 writeExcepinfo(pexcepinfo, e.Message);
944 ret = DISP_E_TYPEMISMATCH;
946 catch(const CannotConvertException & e) //XInvocation::invoke
948 writeExcepinfo(pexcepinfo, e.Message);
949 ret = mapCannotConvertException( e, puArgErr);
951 catch(const InvocationTargetException & e) //XInvocation::invoke
953 const Any& org = e.TargetException;
954 Exception excTarget;
955 org >>= excTarget;
956 OUString message=
957 org.getValueType().getTypeName() + ": " + excTarget.Message;
958 writeExcepinfo(pexcepinfo, message);
959 ret = DISP_E_EXCEPTION;
961 catch(const NoSuchMethodException & e) //XInvocation::invoke
963 writeExcepinfo(pexcepinfo, e.Message);
964 ret = DISP_E_MEMBERNOTFOUND;
966 catch(const BridgeRuntimeError & e)
968 writeExcepinfo(pexcepinfo, e.message);
969 ret = DISP_E_EXCEPTION;
971 catch(const Exception & e)
973 OUString message= "InterfaceOleWrapper_Impl::doInvoke : \n" +
974 e.Message;
975 writeExcepinfo(pexcepinfo, message);
976 ret = DISP_E_EXCEPTION;
978 catch( ... )
980 OUString message= "InterfaceOleWrapper_Impl::doInvoke : \n"
981 "Unexpected exception";
982 writeExcepinfo(pexcepinfo, message);
983 ret = DISP_E_EXCEPTION;
985 return ret;
988 HRESULT InterfaceOleWrapper_Impl::doGetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * pvarResult,
989 EXCEPINFO * pexcepinfo, OUString& name)
991 HRESULT ret= S_OK;
993 Any value;
996 Any returnValue = m_xInvocation->getValue( name);
997 // write back return value
998 if (pvarResult)
999 anyToVariant(pvarResult, returnValue);
1001 catch(const UnknownPropertyException& e) //XInvocation::getValue
1003 writeExcepinfo(pexcepinfo, e.Message);
1004 ret = DISP_E_MEMBERNOTFOUND;
1006 catch(const BridgeRuntimeError& e)
1008 writeExcepinfo(pexcepinfo, e.message);
1009 ret = DISP_E_EXCEPTION;
1011 catch(const Exception& e)
1013 OUString message= "InterfaceOleWrapper_Impl::doGetProperty : \n" +
1014 e.Message;
1015 writeExcepinfo(pexcepinfo, message);
1017 catch( ... )
1019 OUString message= "InterfaceOleWrapper_Impl::doInvoke : \n"
1020 "Unexpected exception";
1021 writeExcepinfo(pexcepinfo, message);
1022 ret = DISP_E_EXCEPTION;
1024 return ret;
1027 HRESULT InterfaceOleWrapper_Impl::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1028 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any> params)
1030 HRESULT ret= S_OK;
1034 m_xInvocation->setValue( name, params.getConstArray()[0]);
1036 catch(const UnknownPropertyException &)
1038 ret = DISP_E_MEMBERNOTFOUND;
1040 catch(const CannotConvertException &e)
1042 ret= mapCannotConvertException( e, puArgErr);
1044 catch(const InvocationTargetException &e)
1046 if (pexcepinfo != NULL)
1048 Any org = e.TargetException;
1050 pexcepinfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
1051 pexcepinfo->bstrSource = SysAllocString(L"any ONE component");
1052 pexcepinfo->bstrDescription = SysAllocString(
1053 reinterpret_cast<LPCOLESTR>(org.getValueType().getTypeName().getStr()));
1055 ret = DISP_E_EXCEPTION;
1057 catch( ... )
1059 ret= DISP_E_EXCEPTION;
1061 return ret;
1064 HRESULT InterfaceOleWrapper_Impl::InvokeGeneral( DISPID dispidMember, unsigned short wFlags,
1065 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1066 unsigned int * /*puArgErr*/, sal_Bool& bHandled)
1068 HRESULT ret= S_OK;
1071 // DISPID_VALUE | The DEFAULT Value is required in JScript when the situation
1072 // is that we put an object into an Array object ( out parameter). We have to return
1073 // IDispatch otherwise the object cannot be accessed from the Script.
1074 if( dispidMember == DISPID_VALUE && wFlags == DISPATCH_PROPERTYGET
1075 && m_defaultValueType != VT_EMPTY && pvarResult != NULL)
1077 bHandled= sal_True;
1078 if( m_defaultValueType == VT_DISPATCH)
1080 pvarResult->vt= VT_DISPATCH;
1081 pvarResult->pdispVal= static_cast<IDispatch*>( this);
1082 AddRef();
1083 ret= S_OK;
1086 // ---------
1087 // function: _GetValueObject
1088 else if( dispidMember == DISPID_JSCRIPT_VALUE_FUNC)
1090 bHandled= sal_True;
1091 if( !pvarResult)
1092 ret= E_POINTER;
1093 CComObject< JScriptValue>* pValue;
1094 if( SUCCEEDED( CComObject<JScriptValue>::CreateInstance( &pValue)))
1096 pValue->AddRef();
1097 pvarResult->vt= VT_DISPATCH;
1098 #ifdef __MINGW32__
1099 pvarResult->pdispVal= CComQIPtr<IDispatch, &__uuidof(IDispatch)>(pValue->GetUnknown());
1100 #else
1101 pvarResult->pdispVal= CComQIPtr<IDispatch>(pValue->GetUnknown());
1102 #endif
1103 ret= S_OK;
1105 else
1106 ret= DISP_E_EXCEPTION;
1108 else if( dispidMember == DISPID_GET_STRUCT_FUNC)
1110 bHandled= sal_True;
1111 sal_Bool bStruct= sal_False;
1114 Reference<XIdlReflection> xRefl = theCoreReflection::get(comphelper::getComponentContext(m_smgr));
1115 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1116 CComVariant arg;
1117 if( pdispparams->cArgs == 1 && SUCCEEDED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])) )
1119 Reference<XIdlClass> classStruct= xRefl->forName( reinterpret_cast<const sal_Unicode*>(arg.bstrVal));
1120 if( classStruct.is())
1122 Any anyStruct;
1123 classStruct->createObject( anyStruct);
1124 CComVariant var;
1125 anyToVariant( &var, anyStruct );
1127 if( var.vt == VT_DISPATCH)
1129 VariantCopy( pvarResult, & var);
1130 bStruct= sal_True;
1134 ret= bStruct == sal_True ? S_OK : DISP_E_EXCEPTION;
1136 else if (dispidMember == DISPID_CREATE_TYPE_FUNC)
1138 bHandled= sal_True;
1139 if( !pvarResult)
1140 ret= E_POINTER;
1141 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1142 CComVariant arg;
1143 if( pdispparams->cArgs != 1)
1144 return DISP_E_BADPARAMCOUNT;
1145 if (FAILED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])))
1146 return DISP_E_BADVARTYPE;
1148 //check if the provided name represents a valid type
1149 Type type;
1150 if (getType(arg.bstrVal, type) == false)
1152 writeExcepinfo(pexcepinfo,OUString(
1153 "[automation bridge] A UNO type with the name " +
1154 OUString(reinterpret_cast<const sal_Unicode*>(arg.bstrVal)) + " does not exist!"));
1155 return DISP_E_EXCEPTION;
1158 if (createUnoTypeWrapper(arg.bstrVal, pvarResult) == false)
1160 writeExcepinfo(pexcepinfo, "[automation bridge] InterfaceOleWrapper_Impl::InvokeGeneral\n"
1161 "Could not initialize UnoTypeWrapper object!");
1162 return DISP_E_EXCEPTION;
1166 catch(const BridgeRuntimeError & e)
1168 writeExcepinfo(pexcepinfo, e.message);
1169 ret = DISP_E_EXCEPTION;
1171 catch(const Exception & e)
1173 OUString message= "InterfaceOleWrapper_Impl::InvokeGeneral : \n" +
1174 e.Message;
1175 writeExcepinfo(pexcepinfo, message);
1176 ret = DISP_E_EXCEPTION;
1178 catch( ... )
1180 OUString message= "InterfaceOleWrapper_Impl::InvokeGeneral : \n"
1181 "Unexpected exception";
1182 writeExcepinfo(pexcepinfo, message);
1183 ret = DISP_E_EXCEPTION;
1185 return ret;
1191 STDMETHODIMP InterfaceOleWrapper_Impl::GetDispID(BSTR /*bstrName*/, DWORD /*grfdex*/, DISPID __RPC_FAR* /*pid*/)
1193 HRESULT ret = ResultFromScode(E_NOTIMPL);
1195 return ret;
1198 STDMETHODIMP InterfaceOleWrapper_Impl::InvokeEx(
1199 /* [in] */ DISPID /*id*/,
1200 /* [in] */ LCID /*lcid*/,
1201 /* [in] */ WORD /*wFlags*/,
1202 /* [in] */ DISPPARAMS __RPC_FAR* /*pdp*/,
1203 /* [out] */ VARIANT __RPC_FAR* /*pvarRes*/,
1204 /* [out] */ EXCEPINFO __RPC_FAR* /*pei*/,
1205 /* [unique][in] */ IServiceProvider __RPC_FAR* /*pspCaller*/)
1207 HRESULT ret = ResultFromScode(E_NOTIMPL);
1209 return ret;
1213 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByName(
1214 /* [in] */ BSTR /*bstr*/,
1215 /* [in] */ DWORD /*grfdex*/)
1217 HRESULT ret = ResultFromScode(E_NOTIMPL);
1219 return ret;
1222 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByDispID(DISPID /*id*/)
1224 HRESULT ret = ResultFromScode(E_NOTIMPL);
1226 return ret;
1229 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberProperties(
1230 /* [in] */ DISPID /*id*/,
1231 /* [in] */ DWORD /*grfdexFetch*/,
1232 /* [out] */ DWORD __RPC_FAR* /*pgrfdex*/)
1234 HRESULT ret = ResultFromScode(E_NOTIMPL);
1236 return ret;
1239 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberName(
1240 /* [in] */ DISPID /*id*/,
1241 /* [out] */ BSTR __RPC_FAR* /*pbstrName*/)
1243 HRESULT ret = ResultFromScode(E_NOTIMPL);
1245 return ret;
1248 STDMETHODIMP InterfaceOleWrapper_Impl::GetNextDispID(
1249 /* [in] */ DWORD /*grfdex*/,
1250 /* [in] */ DISPID /*id*/,
1251 /* [out] */ DISPID __RPC_FAR* /*pid*/)
1253 HRESULT ret = ResultFromScode(E_NOTIMPL);
1255 return ret;
1258 STDMETHODIMP InterfaceOleWrapper_Impl::GetNameSpaceParent(
1259 /* [out] */ IUnknown __RPC_FAR *__RPC_FAR* /*ppunk*/)
1261 HRESULT ret = ResultFromScode(E_NOTIMPL);
1263 return ret;
1267 /*************************************************************************
1269 UnoObjectWrapperRemoteOpt
1271 *************************************************************************/
1272 UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference<XMultiServiceFactory>& aFactory,
1273 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
1274 InterfaceOleWrapper_Impl( aFactory, unoWrapperClass, comWrapperClass),
1275 m_currentId(1)
1279 UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt()
1283 // UnoConversionUtilities
1284 Reference< XInterface > UnoObjectWrapperRemoteOpt::createUnoWrapperInstance()
1286 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
1287 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1288 return Reference<XInterface>( xWeak, UNO_QUERY);
1291 STDMETHODIMP UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID /*riid*/, OLECHAR ** rgszNames, unsigned int cNames,
1292 LCID /*lcid*/, DISPID * rgdispid )
1294 MutexGuard guard( getBridgeMutex());
1296 if( ! rgdispid)
1297 return E_POINTER;
1298 HRESULT ret = E_UNEXPECTED;
1299 // ----------------------------------------
1300 // _GetValueObject
1301 if( ! wcscmp( *rgszNames, JSCRIPT_VALUE_FUNC))
1303 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
1304 return S_OK;
1306 else if( ! wcscmp( *rgszNames, GET_STRUCT_FUNC))
1308 *rgdispid= DISPID_GET_STRUCT_FUNC;
1309 return S_OK;
1312 // ----------------------------------------
1313 if (m_xInvocation.is() && (cNames > 0))
1315 OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0]));
1316 // has this name been determined as "bad"
1317 BadNameMap::iterator badIter= m_badNameMap.find( name);
1318 if( badIter == m_badNameMap.end() )
1320 // name has not been bad before( member exists
1321 typedef NameToIdMap::iterator ITnames;
1322 pair< ITnames, bool > pair_id= m_nameToDispIdMap.insert( NameToIdMap::value_type(name, m_currentId++));
1323 // new ID inserted ?
1324 if( pair_id.second )
1325 {// yes, now create MemberInfo and ad to IdToMemberInfoMap
1326 MemberInfo d(0, name);
1327 m_idToMemberInfoMap.insert( IdToMemberInfoMap::value_type( m_currentId - 1, d));
1330 *rgdispid = pair_id.first->second;
1331 ret = S_OK;
1333 else
1334 ret= DISP_E_UNKNOWNNAME;
1336 return ret;
1339 STDMETHODIMP UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember, REFIID /*riid*/, LCID /*lcid*/, unsigned short wFlags,
1340 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1341 unsigned int * puArgErr )
1343 HRESULT ret = S_OK;
1346 sal_Bool bHandled= sal_False;
1347 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo,
1348 puArgErr, bHandled);
1349 if( bHandled)
1350 return ret;
1352 if ( dispidMember > 0 && m_xInvocation.is())
1355 IdToMemberInfoMap::iterator it_MemberInfo= m_idToMemberInfoMap.find( dispidMember);
1356 if( it_MemberInfo != m_idToMemberInfoMap.end() )
1358 MemberInfo& info= it_MemberInfo->second;
1360 Sequence<Any> params; // holds converted any s
1361 if( ! info.flags )
1362 { // DISPID called for the first time
1363 if( wFlags == DISPATCH_METHOD )
1365 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1367 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1368 pexcepinfo, puArgErr, info.name, params))
1369 && ret == DISP_E_MEMBERNOTFOUND)
1371 // try to get the exact name
1372 OUString exactName;
1373 if (m_xExactName.is())
1375 exactName = m_xExactName->getExactName( info.name);
1376 // invoke again
1377 if( !exactName.isEmpty() )
1379 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1380 pexcepinfo, puArgErr, exactName, params)))
1381 info.name= exactName;
1385 if( SUCCEEDED( ret ) )
1386 info.flags= DISPATCH_METHOD;
1387 } //if( wFlags == DISPATCH_METHOD )
1389 else if( wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_PROPERTYPUTREF)
1391 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1392 if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1393 pexcepinfo, puArgErr, info.name, params))
1394 && ret == DISP_E_MEMBERNOTFOUND)
1396 // try to get the exact name
1397 OUString exactName;
1398 if (m_xExactName.is())
1400 exactName = m_xExactName->getExactName( info.name);
1401 // invoke again
1402 if( !exactName.isEmpty() )
1404 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1405 pexcepinfo, puArgErr, exactName, params)))
1406 info.name= exactName;
1410 if( SUCCEEDED( ret ) )
1411 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1414 else if( wFlags == DISPATCH_PROPERTYGET)
1416 if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1417 pexcepinfo, info.name))
1418 && ret == DISP_E_MEMBERNOTFOUND)
1420 // try to get the exact name
1421 OUString exactName;
1422 if (m_xExactName.is())
1424 exactName = m_xExactName->getExactName( info.name);
1425 // invoke again
1426 if( !exactName.isEmpty() )
1428 if( SUCCEEDED( ret= doGetProperty( pdispparams, pvarResult,
1429 pexcepinfo, exactName)))
1430 info.name= exactName;
1434 if( SUCCEEDED( ret ) )
1435 info.flags= DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT;
1437 else if( wFlags & DISPATCH_METHOD &&
1438 (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF))
1441 OUString exactName;
1442 // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT
1443 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1444 // try first as method
1445 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1446 pexcepinfo, puArgErr, info.name, params))
1447 && ret == DISP_E_MEMBERNOTFOUND)
1449 // try to get the exact name
1450 if (m_xExactName.is())
1452 exactName = m_xExactName->getExactName( info.name);
1453 // invoke again
1454 if( !exactName.isEmpty() )
1456 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1457 pexcepinfo, puArgErr, exactName, params)))
1458 info.name= exactName;
1462 if( SUCCEEDED( ret ) )
1463 info.flags= DISPATCH_METHOD;
1465 // try as property
1466 if( FAILED( ret) && pdispparams->cArgs == 1)
1468 if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1469 pexcepinfo, puArgErr, info.name, params))
1470 && ret == DISP_E_MEMBERNOTFOUND)
1472 // try to get the exact name
1473 if( !exactName.isEmpty() )
1475 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1476 pexcepinfo, puArgErr, exactName, params)))
1477 info.name= exactName;
1480 if( SUCCEEDED( ret ) )
1481 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1484 else if( wFlags & DISPATCH_METHOD && wFlags & DISPATCH_PROPERTYGET)
1486 OUString exactName;
1487 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1489 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1490 pexcepinfo, puArgErr, info.name, params))
1491 && ret == DISP_E_MEMBERNOTFOUND)
1493 // try to get the exact name
1494 if (m_xExactName.is())
1496 exactName = m_xExactName->getExactName( info.name);
1497 // invoke again
1498 if( !exactName.isEmpty() )
1500 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1501 pexcepinfo, puArgErr, exactName, params)))
1502 info.name= exactName;
1506 if( SUCCEEDED( ret ) )
1507 info.flags= DISPATCH_METHOD;
1509 // try as property
1510 if( FAILED( ret) && pdispparams->cArgs == 1)
1512 if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1513 pexcepinfo, info.name))
1514 && ret == DISP_E_MEMBERNOTFOUND)
1516 if( !exactName.isEmpty() )
1518 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1519 pexcepinfo, puArgErr, exactName, params)))
1520 info.name= exactName;
1523 if( SUCCEEDED( ret ) )
1524 info.flags= DISPATCH_PROPERTYGET;
1528 // update ínformation about this member
1529 if( ret == DISP_E_MEMBERNOTFOUND)
1531 // Remember the name as not existing
1532 // and remove the MemberInfo
1533 m_badNameMap[info.name]= sal_False;
1534 m_idToMemberInfoMap.erase( it_MemberInfo);
1536 } // if( ! info.flags )
1537 else // IdToMemberInfoMap contains a MemberInfo
1539 if( wFlags & DISPATCH_METHOD && info.flags == DISPATCH_METHOD)
1541 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1542 ret= doInvoke( pdispparams, pvarResult,
1543 pexcepinfo, puArgErr, info.name, params);
1545 else if( (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF ) &&
1546 info.flags & DISPATCH_PROPERTYPUT)
1548 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1549 ret= doSetProperty( pdispparams, pvarResult,
1550 pexcepinfo, puArgErr, info.name, params);
1552 else if( (wFlags & DISPATCH_PROPERTYGET) && ( info.flags & DISPATCH_PROPERTYGET))
1554 ret= doGetProperty( pdispparams, pvarResult,
1555 pexcepinfo, info.name);
1557 else
1559 ret= DISP_E_MEMBERNOTFOUND;
1562 }// if( it_MemberInfo != m_idToMemberInfoMap.end() )
1563 else
1564 ret= DISP_E_MEMBERNOTFOUND;
1567 catch(const BridgeRuntimeError& e)
1569 writeExcepinfo(pexcepinfo, e.message);
1570 ret = DISP_E_EXCEPTION;
1572 catch(const Exception& e)
1574 OUString message= "UnoObjectWrapperRemoteOpt::Invoke : \n" +
1575 e.Message;
1576 writeExcepinfo(pexcepinfo, message);
1577 ret = DISP_E_EXCEPTION;
1579 catch(...)
1581 OUString message= "UnoObjectWrapperRemoteOpt::Invoke : \n"
1582 "Unexpected exception";
1583 writeExcepinfo(pexcepinfo, message);
1584 ret = DISP_E_EXCEPTION;
1587 return ret;
1590 HRESULT UnoObjectWrapperRemoteOpt::methodInvoke( DISPID /*dispidMember*/, DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1591 EXCEPINFO * /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence<Any> params)
1593 return S_OK;
1597 // The returned HRESULT is only appropriate for IDispatch::Invoke
1598 static HRESULT mapCannotConvertException(const CannotConvertException &e, unsigned int * puArgErr)
1600 HRESULT ret;
1601 sal_Bool bWriteIndex= sal_True;
1603 switch ( e.Reason)
1605 case FailReason::OUT_OF_RANGE:
1606 ret = DISP_E_OVERFLOW;
1607 break;
1608 case FailReason::IS_NOT_NUMBER:
1609 ret = DISP_E_TYPEMISMATCH;
1610 break;
1611 case FailReason::IS_NOT_ENUM:
1612 ret = DISP_E_TYPEMISMATCH;
1613 break;
1614 case FailReason::IS_NOT_BOOL:
1615 ret = DISP_E_TYPEMISMATCH;
1616 break;
1617 case FailReason::NO_SUCH_INTERFACE:
1618 ret = DISP_E_TYPEMISMATCH;
1619 break;
1620 case FailReason::SOURCE_IS_NO_DERIVED_TYPE:
1621 ret = DISP_E_TYPEMISMATCH;
1622 break;
1623 case FailReason::TYPE_NOT_SUPPORTED:
1624 ret = DISP_E_TYPEMISMATCH;
1625 break;
1626 case FailReason::INVALID:
1627 ret = DISP_E_TYPEMISMATCH;
1628 break;
1629 case FailReason::NO_DEFAULT_AVAILABLE:
1630 ret = DISP_E_BADPARAMCOUNT;
1631 break;
1632 case FailReason::UNKNOWN:
1633 ret = E_UNEXPECTED;
1634 break;
1635 default:
1636 ret = E_UNEXPECTED;
1637 bWriteIndex= sal_False;
1638 break;
1641 if( bWriteIndex && puArgErr != NULL)
1642 *puArgErr = e.ArgumentIndex;
1643 return ret;
1646 // The function maps the TypeClass of the any to VARTYPE: If
1647 // the Any contains STRUCT or INTERFACE then the return value
1648 // is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper
1649 // and the result is put into the constructor of the uno - wrapper
1650 // object. If a client asks the object for DISPID_VALUE and this
1651 // funtion returned VT_DISPATCH then the IDispatch of the same
1652 // object is being returned.
1653 // See InterfaceOleWrapper_Impl::Invoke, InterfaceOleWrapper_Impl::m_defaultValueType
1654 const VARTYPE getVarType( const Any& value)
1656 VARTYPE ret= VT_EMPTY;
1658 switch ( value.getValueTypeClass())
1660 case TypeClass_STRUCT: ret= VT_DISPATCH; break;
1661 case TypeClass_INTERFACE: ret= VT_DISPATCH; break;
1662 default: break;
1664 return ret;
1670 } // end namespace
1672 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */