update dev300-m58
[ooovba.git] / extensions / source / ole / unoobjw.cxx
blobedcc2d6f2fc3d90282bc84c24c26ddb476be338a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unoobjw.cxx,v $
10 * $Revision: 1.24 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
34 #include "ole2uno.hxx"
35 #include <stdio.h>
36 #include <tools/presys.h>
37 #include <olectl.h>
38 #include <vector>
39 #include <list>
40 #include <hash_map>
41 #include "comifaces.hxx"
42 #include <tools/postsys.h>
45 #include <vos/diagnose.hxx>
46 #include <vos/refernce.hxx>
47 #include <tools/debug.hxx>
48 #include <rtl/ustring.hxx>
49 #include <com/sun/star/beans/MethodConcept.hpp>
50 #include <com/sun/star/beans/PropertyConcept.hpp>
51 #include <com/sun/star/script/FailReason.hpp>
52 #include <com/sun/star/reflection/ParamInfo.hpp>
53 #include <com/sun/star/beans/XExactName.hpp>
54 #include <com/sun/star/container/NoSuchElementException.hpp>
56 #include <com/sun/star/beans/XMaterialHolder.hpp>
57 #include <com/sun/star/script/XInvocation2.hpp>
58 #include <com/sun/star/script/MemberType.hpp>
59 #include <com/sun/star/reflection/XIdlReflection.hpp>
60 #include <osl/interlck.h>
61 #include <com/sun/star/uno/genfunc.h>
62 #include <cppuhelper/implbase1.hxx>
64 #include "comifaces.hxx"
65 #include "jscriptclasses.hxx"
66 #include "unotypewrapper.hxx"
67 #include "oleobjw.hxx"
68 #include "unoobjw.hxx"
69 #include "servprov.hxx"
71 using namespace vos;
72 using namespace std;
73 using namespace rtl;
74 using namespace osl;
75 using namespace cppu;
76 using namespace com::sun::star::uno;
77 using namespace com::sun::star::beans;
78 using namespace com::sun::star::container;
79 using namespace com::sun::star::script;
80 using namespace com::sun::star::lang;
81 using namespace com::sun::star::bridge::ModelDependent;
82 using namespace com::sun::star::reflection;
86 #if _MSC_VER < 1200
87 extern "C" const GUID IID_IDispatchEx;
88 #endif
90 namespace ole_adapter
92 hash_map<sal_uInt32, WeakReference<XInterface> > UnoObjToWrapperMap;
93 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource);
94 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource);
95 static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr);
98 /* Does not throw any exceptions.
99 Param pInfo can be NULL.
101 static void writeExcepinfo(EXCEPINFO * pInfo, const OUString& message)
103 if (pInfo != NULL)
105 pInfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
106 pInfo->bstrSource = SysAllocString(L"[automation bridge] ");
107 pInfo->bstrDescription = SysAllocString(reinterpret_cast<LPCOLESTR>(message.getStr()));
111 /*****************************************************************************
113 class implementation: InterfaceOleWrapper_Impl
115 *****************************************************************************/
116 InterfaceOleWrapper_Impl::InterfaceOleWrapper_Impl( Reference<XMultiServiceFactory>& xFactory,
117 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
118 m_defaultValueType( 0),
119 UnoConversionUtilities<InterfaceOleWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass)
123 InterfaceOleWrapper_Impl::~InterfaceOleWrapper_Impl()
125 MutexGuard guard(getBridgeMutex());
126 // remove entries in global map
127 IT_Uno it= UnoObjToWrapperMap.find( (sal_uInt32) m_xOrigin.get());
128 if(it != UnoObjToWrapperMap.end())
129 UnoObjToWrapperMap.erase(it);
130 #if OSL_DEBUG_LEVEL > 0
131 fprintf(stderr,"[automation bridge] UnoObjToWrapperMap contains: %i \n",
132 UnoObjToWrapperMap.size());
133 #endif
137 STDMETHODIMP InterfaceOleWrapper_Impl::QueryInterface(REFIID riid, LPVOID FAR * ppv)
139 HRESULT ret= S_OK;
141 if( !ppv)
142 return E_POINTER;
144 if(IsEqualIID(riid, IID_IUnknown))
146 AddRef();
147 *ppv = (IUnknown*) (IDispatch*) this;
149 else if (IsEqualIID(riid, IID_IDispatch))
151 AddRef();
152 *ppv = (IDispatch*) this;
154 else if( IsEqualIID( riid, __uuidof( IUnoObjectWrapper)))
156 AddRef();
157 *ppv= (IUnoObjectWrapper*) this;
159 else
160 ret= E_NOINTERFACE;
161 return ret;
164 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::AddRef()
166 acquire();
167 // does not need to guard because one should not rely on the return value of
168 // AddRef anyway
169 return m_refCount;
172 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::Release()
174 ULONG n= m_refCount;
175 release();
176 return n - 1;
179 // IUnoObjectWrapper --------------------------------------------------------
180 STDMETHODIMP InterfaceOleWrapper_Impl::getWrapperXInterface( Reference<XInterface>* pXInt)
182 *pXInt= Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY);
183 return pXInt->is() ? S_OK : E_FAIL;
185 STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoObject( Reference<XInterface>* pXInt)
187 *pXInt= m_xOrigin;
188 return m_xOrigin.is() ? S_OK : E_FAIL;
190 STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoStruct( Any * pStruct)
192 HRESULT ret= E_FAIL;
193 if( !m_xOrigin.is())
195 Reference<XMaterialHolder> xMatHolder( m_xInvocation, UNO_QUERY);
196 if( xMatHolder.is())
198 Any any = xMatHolder->getMaterial();
199 if( any.getValueTypeClass() == TypeClass_STRUCT)
201 *pStruct= any;
202 ret= S_OK;
206 return ret;
209 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfoCount( unsigned int * /*pctinfo*/ )
211 return E_NOTIMPL ;
214 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfo(unsigned int /*itinfo*/, LCID /*lcid*/, ITypeInfo ** /*pptinfo*/)
216 return E_NOTIMPL;
219 STDMETHODIMP InterfaceOleWrapper_Impl::GetIDsOfNames(REFIID /*riid*/,
220 OLECHAR ** rgszNames,
221 unsigned int cNames,
222 LCID /*lcid*/,
223 DISPID * rgdispid )
225 HRESULT ret = DISP_E_UNKNOWNNAME;
228 MutexGuard guard( getBridgeMutex());
229 if( ! rgdispid)
230 return E_POINTER;
232 // ----------------------------------------
233 if( ! _wcsicmp( *rgszNames, JSCRIPT_VALUE_FUNC) ||
234 ! _wcsicmp( *rgszNames, BRIDGE_VALUE_FUNC))
236 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
237 return S_OK;
239 else if( ! _wcsicmp( *rgszNames, GET_STRUCT_FUNC) ||
240 ! _wcsicmp( *rgszNames, BRIDGE_GET_STRUCT_FUNC))
242 *rgdispid= DISPID_GET_STRUCT_FUNC;
243 return S_OK;
245 else if( ! _wcsicmp( *rgszNames, BRIDGE_CREATE_TYPE_FUNC))
247 *rgdispid= DISPID_CREATE_TYPE_FUNC;
248 return S_OK;
251 // ----------------------------------------
252 if (m_xInvocation.is() && (cNames > 0))
254 OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0]));
255 NameToIdMap::iterator iter = m_nameToDispIdMap.find(name);
257 if (iter == m_nameToDispIdMap.end())
259 OUString exactName;
261 if (m_xExactName.is())
263 exactName = m_xExactName->getExactName(name);
265 else
267 exactName = name;
270 MemberInfo d(0, exactName);
272 if (m_xInvocation->hasProperty(exactName))
274 d.flags |= DISPATCH_PROPERTYGET;
275 d.flags |= DISPATCH_PROPERTYPUT;
276 d.flags |= DISPATCH_PROPERTYPUTREF;
279 if (m_xInvocation->hasMethod(exactName))
281 d.flags |= DISPATCH_METHOD;
284 if (d.flags != 0)
286 m_MemberInfos.push_back(d);
287 iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(exactName, (DISPID)m_MemberInfos.size())).first;
289 if (exactName != name)
291 iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(name, (DISPID)m_MemberInfos.size())).first;
296 if (iter == m_nameToDispIdMap.end())
298 ret = DISP_E_UNKNOWNNAME;
300 else
302 *rgdispid = (*iter).second;
303 ret = S_OK;
307 catch(BridgeRuntimeError& )
309 OSL_ASSERT(0);
311 catch(Exception& )
313 OSL_ASSERT(0);
315 catch(...)
317 OSL_ASSERT(0);
320 return ret;
323 // "convertDispparamsArgs" converts VARIANTS to their respecting Any counterparts
324 // The parameters "id", "wFlags" and "pdispparams" equal those as used in
325 // IDispatch::Invoke. The function handles special JavaScript
326 // cases where a VARIANT of type VT_DISPATCH is ambiguous and could represent
327 // an object, array ( JavaScript Array object), out parameter and in/out ( JavaScript Array object)
328 // parameter (JavaScript Array object)
329 // Because all those VT_DISPATCH objects need a different conversion
330 // we have to find out what the object is supposed to be. The function does this
331 // by either using type information or by help of a specialized ValueObject object.
333 // A. Type Information
334 // -----------------------------------------------------------------------------
335 // With the help of type information the kind of parameter can be exactly determined
336 // and an appropriate conversion can be choosen. A problem arises if a method expects
337 // an Any. Then the type info does not tell what the type of the value, that is kept
338 // by the any, should be. In this situation the decision wheter the param is a
339 // sequence or an object is made upon the fact if the object has a property "0"
340 // ( see function "isJScriptArray"). Since this is unsafe it is recommended to use
341 // the JScript value objects within a JScript script on such an occasion.
343 // B. JavaScript Value Object ( class JScriptValue )
344 // -----------------------------------------------------------------------------
345 // A JScriptValue (ValueObject) object is a COM object in that it implements IDispatch and the
346 // IJScriptValue object interface. Such objects are provided by all UNO wrapper
347 // objects used within a JScript script. To obtain an instance one has to call
348 // "_GetValueObject() or Bridge_GetValueObject()" on an UNO wrapper object (class InterfaceOleWrapper_Impl).
349 // A value object is appropriately initialized within the script and passed as
350 // parameter to an UNO object method or property. The convertDispparamsArgs function
351 // can easily find out that a param is such an object by queriing for the
352 // IJScriptValue interface. By this interface one the type and kind ( out, in/out)
353 // can be determined and the right conversion can be applied.
354 // Using ValueObjects we spare us the effort of aquiring and examining type information
355 // in order to figure out what the an IDispatch parameter is meant for.
357 // Normal JScript object parameter can be mixed with JScriptValue object. If an
358 // VARIANT contains an VT_DISPATCH that is no JScriptValue than the type information
359 // is used to find out about the reqired type.
360 void InterfaceOleWrapper_Impl::convertDispparamsArgs(DISPID id,
361 unsigned short /*wFlags*/, DISPPARAMS* pdispparams, Sequence<Any>& rSeq)
363 HRESULT hr= S_OK;
364 sal_Int32 countArgs= pdispparams->cArgs;
365 if( countArgs == 0)
366 return;
368 rSeq.realloc( countArgs);
369 Any* pParams = rSeq.getArray();
371 Any anyParam;
373 //Get type information for the current call
374 InvocationInfo info;
375 if( ! getInvocationInfoForCall( id, info))
376 throw BridgeRuntimeError(
377 OUSTR("[automation bridge]InterfaceOleWrapper_Impl::convertDispparamsArgs \n"
378 "Could not obtain type information for current call."));
380 for (int i = 0; i < countArgs; i++)
382 if (info.eMemberType == MemberType_METHOD &&
383 info.aParamModes[ countArgs - i -1 ] == ParamMode_OUT)
384 continue;
386 if(convertValueObject( & pdispparams->rgvarg[i], anyParam))
387 { //a param is a ValueObject and could be converted
388 pParams[countArgs - (i + 1)] = anyParam;
389 continue;
392 // If the param is an out, in/out parameter in
393 // JScript (Array object, with value at index 0) then we
394 // extract Array[0] and put the value into varParam. At the end of the loop varParam
395 // is converted if it contains a value otherwise the VARIANT from
396 // DISPPARAMS is converted.
397 CComVariant varParam;
399 // Check for JScript out and in/out paramsobjects (VT_DISPATCH).
400 // To find them out we use typeinformation of the function being called.
401 if( pdispparams->rgvarg[i].vt == VT_DISPATCH )
403 if( info.eMemberType == MemberType_METHOD && info.aParamModes[ countArgs - i -1 ] == ParamMode_INOUT)
405 // INOUT-param
406 // Index ( property) "0" contains the actual IN-param. The object is a JScript
407 // Array object.
408 // Get the IN-param at index "0"
409 IDispatch* pdisp= pdispparams->rgvarg[i].pdispVal;
411 OLECHAR* sindex= L"0";
412 DISPID id;
413 DISPPARAMS noParams= {0,0,0,0};
414 if(SUCCEEDED( hr= pdisp->GetIDsOfNames( IID_NULL, &sindex, 1, LOCALE_USER_DEFAULT, &id)))
415 hr= pdisp->Invoke( id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
416 & noParams, & varParam, NULL, NULL);
417 if( FAILED( hr))
419 throw BridgeRuntimeError(
420 OUSTR("[automation bridge] Could not determine "
421 "if the object has a member \"0\". Error: ") +
422 OUString::valueOf(hr));
427 if( varParam.vt == VT_EMPTY) // then it was no in/out parameter
428 varParam= pdispparams->rgvarg[i];
430 if(info.eMemberType == MemberType_METHOD)
431 variantToAny( & varParam, anyParam,
432 info.aParamTypes[ countArgs - i - 1]);
433 else if(info.eMemberType == MemberType_PROPERTY)
434 variantToAny( & varParam, anyParam, info.aType);
435 else
436 OSL_ASSERT(0);
438 pParams[countArgs - (i + 1)]= anyParam;
439 }// end for / iterating over all parameters
442 sal_Bool InterfaceOleWrapper_Impl::getInvocationInfoForCall( DISPID id, InvocationInfo& info)
444 sal_Bool bTypesAvailable= sal_False;
446 if( !m_xInvocation.is() )return false;
447 Reference<XInvocation2> inv2( m_xInvocation, UNO_QUERY);
448 if( inv2.is())
450 // We need the name of the property or method to get its type information.
451 // The name can be identified through the param "id"
452 // that is kept as value in the map m_nameToDispIdMap.
453 // Proplem: the Windows JScript engine sometimes changes small letters to capital
454 // letters as happens in xidlclass_obj.createObject( var) // in JScript.
455 // IDispatch::GetIdsOfNames is then called with "CreateObject" !!!
456 // m_nameToDispIdMap can contain several names for one DISPID but only one is
457 // the exact one. If there's no m_xExactName and therefore no exact name then
458 // there's only one entry in the map.
459 typedef NameToIdMap::const_iterator cit;
460 OUString sMemberName;
462 for(cit ci1= m_nameToDispIdMap.begin(); ci1 != m_nameToDispIdMap.end(); ci1++)
464 if( (*ci1).second == id) // iterator is a pair< OUString, DISPID>
466 sMemberName= (*ci1).first;
467 break;
470 // Get information for the current call ( property or method).
471 // There could be similar names which only differ in the cases
472 // of letters. First we assume that the name which was passed into
473 // GetIDsOfNames is correct. If we won't get information with that
474 // name then we have the invocation service use the XExactName interface.
475 sal_Bool validInfo= sal_True;
476 InvocationInfo invInfo;
477 try{
478 invInfo= inv2->getInfoForName( sMemberName, sal_False);
480 catch( IllegalArgumentException )
482 validInfo= sal_False;
485 if( ! validInfo)
487 invInfo= inv2->getInfoForName( sMemberName, sal_True);
489 if( invInfo.aName.pData)
491 bTypesAvailable= sal_True;
492 info= invInfo;
495 return bTypesAvailable;
497 // XBridgeSupplier2 ---------------------------------------------------
498 // only bridges itself ( this instance of InterfaceOleWrapper_Impl)from UNO to IDispatch
499 // If sourceModelType is UNO than any UNO interface implemented by InterfaceOleWrapper_Impl
500 // can bridged to IDispatch ( if destModelType == OLE). The IDispatch is
501 // implemented by this class.
502 Any SAL_CALL InterfaceOleWrapper_Impl::createBridge(const Any& modelDepObject,
503 const Sequence<sal_Int8>& /*ProcessId*/,
504 sal_Int16 sourceModelType,
505 sal_Int16 destModelType)
506 throw (IllegalArgumentException, RuntimeException)
509 Any retAny;
510 if( sourceModelType == UNO && destModelType == OLE &&
511 modelDepObject.getValueTypeClass() == TypeClass_INTERFACE )
513 Reference<XInterface> xInt;
514 if( modelDepObject >>= xInt )
516 if( xInt == Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY))
518 VARIANT *pVar= (VARIANT*)CoTaskMemAlloc( sizeof( VARIANT));
519 if( pVar)
521 pVar->vt= VT_DISPATCH;
522 pVar->pdispVal= static_cast<IDispatch*>( this);
523 AddRef();
525 retAny<<= reinterpret_cast< sal_uInt32 >( pVar);
531 return retAny;
535 // XInitialization --------------------------------------------------
536 void SAL_CALL InterfaceOleWrapper_Impl::initialize( const Sequence< Any >& aArguments )
537 throw(Exception, RuntimeException)
539 switch( aArguments.getLength() )
541 case 2: // the object wraps an UNO struct
542 aArguments[0] >>= m_xInvocation;
543 aArguments[1] >>= m_defaultValueType;
544 break;
545 case 3: // the object wraps an UNO interface
546 aArguments[0] >>= m_xInvocation;
547 aArguments[1] >>= m_xOrigin;
548 aArguments[2] >>= m_defaultValueType;
549 break;
552 m_xExactName= Reference<XExactName>( m_xInvocation, UNO_QUERY);
555 Reference< XInterface > InterfaceOleWrapper_Impl::createUnoWrapperInstance()
557 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl(
558 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
559 return Reference<XInterface>( xWeak, UNO_QUERY);
562 Reference<XInterface> InterfaceOleWrapper_Impl::createComWrapperInstance()
564 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl(
565 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
566 return Reference<XInterface>( xWeak, UNO_QUERY);
571 // "getType" is used in convertValueObject to map the string denoting the type
572 // to an actual Type object.
573 bool getType( const BSTR name, Type & type)
575 Type retType;
576 bool ret = false;
577 typelib_TypeDescription * pDesc= NULL;
578 OUString str( reinterpret_cast<const sal_Unicode*>(name));
579 typelib_typedescription_getByName( &pDesc, str.pData );
580 if( pDesc)
582 type = Type( pDesc->pWeakRef );
583 typelib_typedescription_release( pDesc);
584 ret = true;
586 return ret;
589 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource)
591 sal_Bool ret = sal_False;
592 HRESULT hr;
594 // Handle JScriptValue objects and JScript out params ( Array object )
595 CComVariant varDest( *pDest);
597 if( SUCCEEDED( varDest.ChangeType(VT_DISPATCH)))
599 CComPtr<IDispatch> spDispDest(varDest.pdispVal);
601 // special Handling for a JScriptValue object
602 #ifdef __MINGW32__
603 CComQIPtr<IJScriptValueObject, &__uuidof(IJScriptValueObject)> spValueDest(spDispDest);
604 #else
605 CComQIPtr<IJScriptValueObject> spValueDest(spDispDest);
606 #endif
607 if (spValueDest)
609 VARIANT_BOOL varBool= VARIANT_FALSE;
610 if( SUCCEEDED( hr= spValueDest->IsOutParam( &varBool) )
611 && varBool == VARIANT_TRUE ||
612 SUCCEEDED(hr= spValueDest->IsInOutParam( &varBool) )
613 && varBool == VARIANT_TRUE )
615 if( SUCCEEDED( spValueDest->Set( CComVariant(), *pSource)))
616 ret= sal_True;
619 else if (pDest->vt == VT_DISPATCH)// VT_DISPATCH -> JScript out param
621 // We use IDispatchEx because its GetDispID function causes the creation
622 // of a property if it does not exist already. This is convenient for
623 // out parameters in JScript. Then the user must not specify propery "0"
624 // explicitly
625 #ifdef __MINGW32__
626 CComQIPtr<IDispatchEx, &__uuidof(IDispatchEx)> spDispEx( spDispDest);
627 #else
628 CComQIPtr<IDispatchEx> spDispEx( spDispDest);
629 #endif
630 if( spDispEx)
632 CComBSTR nullProp(L"0");
633 DISPID dwDispID;
634 if( SUCCEEDED( spDispEx->GetDispID( nullProp, fdexNameEnsure, &dwDispID)))
636 DISPPARAMS dispparams = {NULL, NULL, 1, 1};
637 dispparams.rgvarg = pSource;
638 DISPID dispidPut = DISPID_PROPERTYPUT;
639 dispparams.rgdispidNamedArgs = &dispidPut;
641 if (pSource->vt == VT_UNKNOWN || pSource->vt == VT_DISPATCH ||
642 (pSource->vt & VT_ARRAY) || (pSource->vt & VT_BYREF))
643 hr = spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
644 &dispparams, NULL, NULL, NULL);
645 else
646 hr= spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
647 &dispparams, NULL, NULL, NULL);
648 if( SUCCEEDED(hr))
649 ret= sal_True;
653 else
654 ret= writeBackOutParameter( pDest, pSource);
656 else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript
657 { // param. The function checks itself for correct VBScript params
658 ret= writeBackOutParameter( pDest, pSource);
660 return ret;
662 // VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter.
663 // Thus we are in charge of freeing an eventual value contained by the inner VARIANT
664 // Please note: VariantCopy doesn't free a VT_BYREF value
665 // The out parameters are expected to have always a valid type
666 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource)
668 HRESULT hr;
669 sal_Bool ret = FALSE;
670 // Out parameter must be VT_BYREF
671 if ((V_VT(pDest) & VT_BYREF) != 0 )
673 VARTYPE oleTypeFlags = V_VT(pSource);
675 // if caller accept VARIANT as out parameter, any value must be converted
676 if (V_VT(pDest) == (VT_VARIANT | VT_BYREF))
678 // When the user provides a VARIANT rather then a concrete type
679 // we just copy the source to the out, in/out parameter
680 // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that
681 // is contained in pDest are released by VariantCopy
682 VariantCopy(V_VARIANTREF(pDest), pSource);
683 ret = sal_True;
685 else
687 // variantarg and variant must have same type
688 if ((V_VT(pDest) & oleTypeFlags) == oleTypeFlags)
690 if ((oleTypeFlags & VT_ARRAY) != 0)
692 // In / Out Param
693 if( *V_ARRAYREF(pDest) != NULL)
694 hr= SafeArrayCopyData( V_ARRAY(pSource), *V_ARRAYREF(pDest));
695 else
696 // Out Param
697 hr= SafeArrayCopy(V_ARRAY(pSource), V_ARRAYREF(pDest)) == NOERROR;
698 if( SUCCEEDED( hr))
699 ret = sal_True;
701 else
703 // copy base type
704 switch (V_VT(pSource))
706 case VT_I2:
708 *V_I2REF(pDest) = V_I2(pSource);
709 ret = sal_True;
710 break;
712 case VT_I4:
713 *V_I4REF(pDest) = V_I4(pSource);
714 ret = sal_True;
715 break;
716 case VT_R4:
717 *V_R4REF(pDest) = V_R4(pSource);
718 ret = sal_True;
719 break;
720 case VT_R8:
721 *V_R8REF(pDest) = V_R8(pSource);
722 ret = sal_True;
723 break;
724 case VT_CY:
725 *V_CYREF(pDest) = V_CY(pSource);
726 ret = sal_True;
727 break;
728 case VT_DATE:
729 *V_DATEREF(pDest) = V_DATE(pSource);
730 ret = sal_True;
731 break;
732 case VT_BSTR:
733 SysFreeString( *pDest->pbstrVal);
735 *V_BSTRREF(pDest) = SysAllocString(V_BSTR(pSource));
736 ret = sal_True;
737 break;
738 case VT_DISPATCH:
739 if (*V_DISPATCHREF(pDest) != NULL)
740 (*V_DISPATCHREF(pDest))->Release();
742 *V_DISPATCHREF(pDest) = V_DISPATCH(pSource);
744 if (*V_DISPATCHREF(pDest) != NULL)
745 (*V_DISPATCHREF(pDest))->AddRef();
747 ret = sal_True;
748 break;
749 case VT_ERROR:
750 *V_ERRORREF(pDest) = V_ERROR(pSource);
751 ret = sal_True;
752 break;
753 case VT_BOOL:
754 *V_BOOLREF(pDest) = V_BOOL(pSource);
755 ret = sal_True;
756 break;
757 case VT_UNKNOWN:
758 if (*V_UNKNOWNREF(pDest) != NULL)
759 (*V_UNKNOWNREF(pDest))->Release();
761 *V_UNKNOWNREF(pDest) = V_UNKNOWN(pSource);
763 if (*V_UNKNOWNREF(pDest) != NULL)
764 (*V_UNKNOWNREF(pDest))->AddRef();
766 ret = sal_True;
767 break;
768 case VT_I1:
769 *V_I1REF(pDest) = V_I1(pSource);
770 ret = sal_True;
771 break;
772 case VT_UI1:
773 *V_UI1REF(pDest) = V_UI1(pSource);
774 ret = sal_True;
775 break;
776 case VT_UI2:
777 *V_UI2REF(pDest) = V_UI2(pSource);
778 ret = sal_True;
779 break;
780 case VT_UI4:
781 *V_UI4REF(pDest) = V_UI4(pSource);
782 ret = sal_True;
783 break;
784 case VT_INT:
785 *V_INTREF(pDest) = V_INT(pSource);
786 ret = sal_True;
787 break;
788 case VT_UINT:
789 *V_UINTREF(pDest) = V_UINT(pSource);
790 ret = sal_True;
791 break;
792 case VT_DECIMAL:
793 memcpy(pDest->pdecVal, pSource, sizeof(DECIMAL));
794 ret = sal_True;
795 break;
796 default:
797 break;
801 else
803 // Handling of special cases
804 // Destination and source types are different
805 if( pDest->vt == (VT_BSTR | VT_BYREF)
806 && pSource->vt == VT_I2)
808 // When the user provides a String as out our in/out parameter
809 // and the type is char (TypeClass_CHAR) then we convert to a BSTR
810 // instead of VT_I2 as is done otherwise
811 OLECHAR buff[]= {0,0};
812 buff[0]= pSource->iVal;
814 SysFreeString( *pDest->pbstrVal);
815 *pDest->pbstrVal= SysAllocString( buff);
816 ret = sal_True;
821 return ret;
824 STDMETHODIMP InterfaceOleWrapper_Impl::Invoke(DISPID dispidMember,
825 REFIID /*riid*/,
826 LCID /*lcid*/,
827 unsigned short wFlags,
828 DISPPARAMS * pdispparams,
829 VARIANT * pvarResult,
830 EXCEPINFO * pexcepinfo,
831 unsigned int * puArgErr )
833 HRESULT ret = S_OK;
837 sal_Bool bHandled= sal_False;
838 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo,
839 puArgErr, bHandled);
840 if( bHandled)
841 return ret;
843 if ((dispidMember > 0) && ((size_t)dispidMember <= m_MemberInfos.size()) && m_xInvocation.is())
845 MemberInfo d = m_MemberInfos[dispidMember - 1];
846 DWORD flags = wFlags & d.flags;
848 if (flags != 0)
850 if ((flags & DISPATCH_METHOD) != 0)
852 if (pdispparams->cNamedArgs > 0)
853 ret = DISP_E_NONAMEDARGS;
854 else
856 Sequence<Any> params;
858 convertDispparamsArgs(dispidMember, wFlags, pdispparams , params );
860 ret= doInvoke(pdispparams, pvarResult,
861 pexcepinfo, puArgErr, d.name, params);
864 else if ((flags & DISPATCH_PROPERTYGET) != 0)
866 ret= doGetProperty( pdispparams, pvarResult,
867 pexcepinfo, d.name);
869 else if ((flags & DISPATCH_PROPERTYPUT || flags & DISPATCH_PROPERTYPUTREF) != 0)
871 if (pdispparams->cArgs != 1)
872 ret = DISP_E_BADPARAMCOUNT;
873 else
875 Sequence<Any> params;
876 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
877 if(params.getLength() > 0)
878 ret= doSetProperty( pdispparams, pvarResult, pexcepinfo, puArgErr, d.name, params);
879 else
880 ret = DISP_E_BADVARTYPE;
884 else
885 ret= DISP_E_MEMBERNOTFOUND;
887 else
888 ret = DISP_E_MEMBERNOTFOUND;
890 catch(BridgeRuntimeError& e)
892 writeExcepinfo(pexcepinfo, e.message);
893 ret = DISP_E_EXCEPTION;
895 catch(Exception& e)
897 OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n") +
898 e.Message;
899 writeExcepinfo(pexcepinfo, message);
900 ret = DISP_E_EXCEPTION;
902 catch(...)
904 OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n"
905 "Unexpected exception");
906 writeExcepinfo(pexcepinfo, message);
907 ret = DISP_E_EXCEPTION;
910 return ret;
913 HRESULT InterfaceOleWrapper_Impl::doInvoke( DISPPARAMS * pdispparams, VARIANT * pvarResult,
914 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any>& params)
918 HRESULT ret= S_OK;
921 Sequence<INT16> outIndex;
922 Sequence<Any> outParams;
923 Any returnValue;
925 if (pdispparams->cNamedArgs > 0)
926 return DISP_E_NONAMEDARGS;
928 // invoke method and take care of exceptions
929 returnValue = m_xInvocation->invoke(name,
930 params,
931 outIndex,
932 outParams);
934 // try to write back out parameter
935 if (outIndex.getLength() > 0)
937 const INT16* pOutIndex = outIndex.getConstArray();
938 const Any* pOutParams = outParams.getConstArray();
940 for (sal_Int32 i = 0; i < outIndex.getLength(); i++)
942 CComVariant variant;
943 // Currently a Sequence is converted to an SafeArray of VARIANTs.
944 anyToVariant( &variant, pOutParams[i]);
946 // out parameter need special handling if they are VT_DISPATCH
947 // and used in JScript
948 int outindex= pOutIndex[i];
949 writeBackOutParameter2(&(pdispparams->rgvarg[pdispparams->cArgs - 1 - outindex]),
950 &variant );
954 // write back return value
955 if (pvarResult != NULL)
956 anyToVariant(pvarResult, returnValue);
958 catch(IllegalArgumentException & e) //XInvocation::invoke
960 writeExcepinfo(pexcepinfo, e.Message);
961 ret = DISP_E_TYPEMISMATCH;
963 catch(CannotConvertException & e) //XInvocation::invoke
965 writeExcepinfo(pexcepinfo, e.Message);
966 ret = mapCannotConvertException( e, puArgErr);
968 catch(InvocationTargetException & e) //XInvocation::invoke
970 const Any& org = e.TargetException;
971 Exception excTarget;
972 org >>= excTarget;
973 OUString message=
974 org.getValueType().getTypeName() + OUSTR(": ") + excTarget.Message;
975 writeExcepinfo(pexcepinfo, message);
976 ret = DISP_E_EXCEPTION;
978 catch(NoSuchMethodException & e) //XInvocation::invoke
980 writeExcepinfo(pexcepinfo, e.Message);
981 ret = DISP_E_MEMBERNOTFOUND;
983 catch(BridgeRuntimeError & e)
985 writeExcepinfo(pexcepinfo, e.message);
986 ret = DISP_E_EXCEPTION;
988 catch(Exception & e)
990 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n") +
991 e.Message;
992 writeExcepinfo(pexcepinfo, message);
993 ret = DISP_E_EXCEPTION;
995 catch( ... )
997 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n"
998 "Unexpected exception");
999 writeExcepinfo(pexcepinfo, message);
1000 ret = DISP_E_EXCEPTION;
1002 return ret;
1005 HRESULT InterfaceOleWrapper_Impl::doGetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * pvarResult,
1006 EXCEPINFO * pexcepinfo, OUString& name)
1008 HRESULT ret= S_OK;
1010 Any value;
1013 Any returnValue = m_xInvocation->getValue( name);
1014 // write back return value
1015 if (pvarResult)
1016 anyToVariant(pvarResult, returnValue);
1018 catch(UnknownPropertyException e) //XInvocation::getValue
1020 writeExcepinfo(pexcepinfo, e.Message);
1021 ret = DISP_E_MEMBERNOTFOUND;
1023 catch(BridgeRuntimeError& e)
1025 writeExcepinfo(pexcepinfo, e.message);
1026 ret = DISP_E_EXCEPTION;
1028 catch(Exception& e)
1030 OUString message= OUSTR("InterfaceOleWrapper_Impl::doGetProperty : \n") +
1031 e.Message;
1032 writeExcepinfo(pexcepinfo, message);
1034 catch( ... )
1036 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n"
1037 "Unexpected exception");
1038 writeExcepinfo(pexcepinfo, message);
1039 ret = DISP_E_EXCEPTION;
1041 return ret;
1044 HRESULT InterfaceOleWrapper_Impl::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1045 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any> params)
1047 HRESULT ret= S_OK;
1051 m_xInvocation->setValue( name, params.getConstArray()[0]);
1053 catch(UnknownPropertyException )
1055 ret = DISP_E_MEMBERNOTFOUND;
1057 catch(CannotConvertException e)
1059 ret= mapCannotConvertException( e, puArgErr);
1061 catch(InvocationTargetException e)
1063 if (pexcepinfo != NULL)
1065 Any org = e.TargetException;
1067 pexcepinfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
1068 pexcepinfo->bstrSource = SysAllocString(L"any ONE component");
1069 pexcepinfo->bstrDescription = SysAllocString(
1070 reinterpret_cast<LPCOLESTR>(org.getValueType().getTypeName().getStr()));
1072 ret = DISP_E_EXCEPTION;
1074 catch( ... )
1076 ret= DISP_E_EXCEPTION;
1078 return ret;
1081 HRESULT InterfaceOleWrapper_Impl::InvokeGeneral( DISPID dispidMember, unsigned short wFlags,
1082 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1083 unsigned int * /*puArgErr*/, sal_Bool& bHandled)
1085 HRESULT ret= S_OK;
1088 // DISPID_VALUE | The DEFAULT Value is required in JScript when the situation
1089 // is that we put an object into an Array object ( out parameter). We have to return
1090 // IDispatch otherwise the object cannot be accessed from the Script.
1091 if( dispidMember == DISPID_VALUE && wFlags == DISPATCH_PROPERTYGET
1092 && m_defaultValueType != VT_EMPTY && pvarResult != NULL)
1094 bHandled= sal_True;
1095 if( m_defaultValueType == VT_DISPATCH)
1097 pvarResult->vt= VT_DISPATCH;
1098 pvarResult->pdispVal= static_cast<IDispatch*>( this);
1099 AddRef();
1100 ret= S_OK;
1103 // ---------
1104 // function: _GetValueObject
1105 else if( dispidMember == DISPID_JSCRIPT_VALUE_FUNC)
1107 bHandled= sal_True;
1108 if( !pvarResult)
1109 ret= E_POINTER;
1110 CComObject< JScriptValue>* pValue;
1111 if( SUCCEEDED( CComObject<JScriptValue>::CreateInstance( &pValue)))
1113 pValue->AddRef();
1114 pvarResult->vt= VT_DISPATCH;
1115 #ifdef __MINGW32__
1116 pvarResult->pdispVal= CComQIPtr<IDispatch, &__uuidof(IDispatch)>(pValue->GetUnknown());
1117 #else
1118 pvarResult->pdispVal= CComQIPtr<IDispatch>(pValue->GetUnknown());
1119 #endif
1120 ret= S_OK;
1122 else
1123 ret= DISP_E_EXCEPTION;
1125 else if( dispidMember == DISPID_GET_STRUCT_FUNC)
1127 bHandled= sal_True;
1128 sal_Bool bStruct= sal_False;
1131 Reference<XInterface> xIntCore= m_smgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection"));
1132 Reference<XIdlReflection> xRefl( xIntCore, UNO_QUERY);
1133 if( xRefl.is() )
1135 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1136 CComVariant arg;
1137 if( pdispparams->cArgs == 1 && SUCCEEDED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])) )
1139 Reference<XIdlClass> classStruct= xRefl->forName( reinterpret_cast<const sal_Unicode*>(arg.bstrVal));
1140 if( classStruct.is())
1142 Any anyStruct;
1143 classStruct->createObject( anyStruct);
1144 CComVariant var;
1145 anyToVariant( &var, anyStruct );
1147 if( var.vt == VT_DISPATCH)
1149 VariantCopy( pvarResult, & var);
1150 bStruct= sal_True;
1155 ret= bStruct == sal_True ? S_OK : DISP_E_EXCEPTION;
1157 else if (dispidMember == DISPID_CREATE_TYPE_FUNC)
1159 bHandled= sal_True;
1160 if( !pvarResult)
1161 ret= E_POINTER;
1162 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1163 CComVariant arg;
1164 if( pdispparams->cArgs != 1)
1165 return DISP_E_BADPARAMCOUNT;
1166 if (FAILED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])))
1167 return DISP_E_BADVARTYPE;
1169 //check if the provided name represents a valid type
1170 Type type;
1171 if (getType(arg.bstrVal, type) == false)
1173 writeExcepinfo(pexcepinfo,OUString(
1174 OUSTR("[automation bridge] A UNO type with the name ") +
1175 OUString(reinterpret_cast<const sal_Unicode*>(arg.bstrVal)) + OUSTR(" does not exist!")));
1176 return DISP_E_EXCEPTION;
1179 if (createUnoTypeWrapper(arg.bstrVal, pvarResult) == false)
1181 writeExcepinfo(pexcepinfo,OUSTR("[automation bridge] InterfaceOleWrapper_Impl::InvokeGeneral\n"
1182 "Could not initialize UnoTypeWrapper object!"));
1183 return DISP_E_EXCEPTION;
1187 catch(BridgeRuntimeError & e)
1189 writeExcepinfo(pexcepinfo, e.message);
1190 ret = DISP_E_EXCEPTION;
1192 catch(Exception & e)
1194 OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n") +
1195 e.Message;
1196 writeExcepinfo(pexcepinfo, message);
1197 ret = DISP_E_EXCEPTION;
1199 catch( ... )
1201 OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n"
1202 "Unexpected exception");
1203 writeExcepinfo(pexcepinfo, message);
1204 ret = DISP_E_EXCEPTION;
1206 return ret;
1212 STDMETHODIMP InterfaceOleWrapper_Impl::GetDispID(BSTR /*bstrName*/, DWORD /*grfdex*/, DISPID __RPC_FAR* /*pid*/)
1214 HRESULT ret = ResultFromScode(E_NOTIMPL);
1216 return ret;
1219 STDMETHODIMP InterfaceOleWrapper_Impl::InvokeEx(
1220 /* [in] */ DISPID /*id*/,
1221 /* [in] */ LCID /*lcid*/,
1222 /* [in] */ WORD /*wFlags*/,
1223 /* [in] */ DISPPARAMS __RPC_FAR* /*pdp*/,
1224 /* [out] */ VARIANT __RPC_FAR* /*pvarRes*/,
1225 /* [out] */ EXCEPINFO __RPC_FAR* /*pei*/,
1226 /* [unique][in] */ IServiceProvider __RPC_FAR* /*pspCaller*/)
1228 HRESULT ret = ResultFromScode(E_NOTIMPL);
1230 return ret;
1234 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByName(
1235 /* [in] */ BSTR /*bstr*/,
1236 /* [in] */ DWORD /*grfdex*/)
1238 HRESULT ret = ResultFromScode(E_NOTIMPL);
1240 return ret;
1243 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByDispID(DISPID /*id*/)
1245 HRESULT ret = ResultFromScode(E_NOTIMPL);
1247 return ret;
1250 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberProperties(
1251 /* [in] */ DISPID /*id*/,
1252 /* [in] */ DWORD /*grfdexFetch*/,
1253 /* [out] */ DWORD __RPC_FAR* /*pgrfdex*/)
1255 HRESULT ret = ResultFromScode(E_NOTIMPL);
1257 return ret;
1260 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberName(
1261 /* [in] */ DISPID /*id*/,
1262 /* [out] */ BSTR __RPC_FAR* /*pbstrName*/)
1264 HRESULT ret = ResultFromScode(E_NOTIMPL);
1266 return ret;
1269 STDMETHODIMP InterfaceOleWrapper_Impl::GetNextDispID(
1270 /* [in] */ DWORD /*grfdex*/,
1271 /* [in] */ DISPID /*id*/,
1272 /* [out] */ DISPID __RPC_FAR* /*pid*/)
1274 HRESULT ret = ResultFromScode(E_NOTIMPL);
1276 return ret;
1279 STDMETHODIMP InterfaceOleWrapper_Impl::GetNameSpaceParent(
1280 /* [out] */ IUnknown __RPC_FAR *__RPC_FAR* /*ppunk*/)
1282 HRESULT ret = ResultFromScode(E_NOTIMPL);
1284 return ret;
1288 /*************************************************************************
1290 UnoObjectWrapperRemoteOpt
1292 *************************************************************************/
1293 UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference<XMultiServiceFactory>& aFactory,
1294 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
1295 InterfaceOleWrapper_Impl( aFactory, unoWrapperClass, comWrapperClass),
1296 m_currentId(1)
1300 UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt()
1304 // UnoConversionUtilities
1305 Reference< XInterface > UnoObjectWrapperRemoteOpt::createUnoWrapperInstance()
1307 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
1308 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1309 return Reference<XInterface>( xWeak, UNO_QUERY);
1312 STDMETHODIMP UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID /*riid*/, OLECHAR ** rgszNames, unsigned int cNames,
1313 LCID /*lcid*/, DISPID * rgdispid )
1315 MutexGuard guard( getBridgeMutex());
1317 if( ! rgdispid)
1318 return E_POINTER;
1319 HRESULT ret = E_UNEXPECTED;
1320 // ----------------------------------------
1321 // _GetValueObject
1322 if( ! wcscmp( *rgszNames, JSCRIPT_VALUE_FUNC))
1324 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
1325 return S_OK;
1327 else if( ! wcscmp( *rgszNames, GET_STRUCT_FUNC))
1329 *rgdispid= DISPID_GET_STRUCT_FUNC;
1330 return S_OK;
1333 // ----------------------------------------
1334 if (m_xInvocation.is() && (cNames > 0))
1336 OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0]));
1337 // has this name been determined as "bad"
1338 BadNameMap::iterator badIter= m_badNameMap.find( name);
1339 if( badIter == m_badNameMap.end() )
1341 // name has not been bad before( member exists
1342 typedef NameToIdMap::iterator ITnames;
1343 pair< ITnames, bool > pair_id= m_nameToDispIdMap.insert( NameToIdMap::value_type(name, m_currentId++));
1344 // new ID inserted ?
1345 if( pair_id.second )
1346 {// yes, now create MemberInfo and ad to IdToMemberInfoMap
1347 MemberInfo d(0, name);
1348 m_idToMemberInfoMap.insert( IdToMemberInfoMap::value_type( m_currentId - 1, d));
1351 *rgdispid = pair_id.first->second;
1352 ret = S_OK;
1354 else
1355 ret= DISP_E_UNKNOWNNAME;
1357 return ret;
1360 STDMETHODIMP UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember, REFIID /*riid*/, LCID /*lcid*/, unsigned short wFlags,
1361 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1362 unsigned int * puArgErr )
1364 HRESULT ret = S_OK;
1367 sal_Bool bHandled= sal_False;
1368 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo,
1369 puArgErr, bHandled);
1370 if( bHandled)
1371 return ret;
1373 if ( dispidMember > 0 && m_xInvocation.is())
1376 IdToMemberInfoMap::iterator it_MemberInfo= m_idToMemberInfoMap.find( dispidMember);
1377 if( it_MemberInfo != m_idToMemberInfoMap.end() )
1379 MemberInfo& info= it_MemberInfo->second;
1381 Sequence<Any> params; // holds converted any s
1382 if( ! info.flags )
1383 { // DISPID called for the first time
1384 if( wFlags == DISPATCH_METHOD )
1386 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1388 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1389 pexcepinfo, puArgErr, info.name, params))
1390 && ret == DISP_E_MEMBERNOTFOUND)
1392 // try to get the exact name
1393 OUString exactName;
1394 if (m_xExactName.is())
1396 exactName = m_xExactName->getExactName( info.name);
1397 // invoke again
1398 if( exactName.getLength() != 0)
1400 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1401 pexcepinfo, puArgErr, exactName, params)))
1402 info.name= exactName;
1406 if( SUCCEEDED( ret ) )
1407 info.flags= DISPATCH_METHOD;
1408 } //if( wFlags == DISPATCH_METHOD )
1410 else if( wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_PROPERTYPUTREF)
1412 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1413 if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1414 pexcepinfo, puArgErr, info.name, params))
1415 && ret == DISP_E_MEMBERNOTFOUND)
1417 // try to get the exact name
1418 OUString exactName;
1419 if (m_xExactName.is())
1421 exactName = m_xExactName->getExactName( info.name);
1422 // invoke again
1423 if( exactName.getLength() != 0)
1425 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1426 pexcepinfo, puArgErr, exactName, params)))
1427 info.name= exactName;
1431 if( SUCCEEDED( ret ) )
1432 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1435 else if( wFlags == DISPATCH_PROPERTYGET)
1437 if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1438 pexcepinfo, info.name))
1439 && ret == DISP_E_MEMBERNOTFOUND)
1441 // try to get the exact name
1442 OUString exactName;
1443 if (m_xExactName.is())
1445 exactName = m_xExactName->getExactName( info.name);
1446 // invoke again
1447 if( exactName.getLength() != 0)
1449 if( SUCCEEDED( ret= doGetProperty( pdispparams, pvarResult,
1450 pexcepinfo, exactName)))
1451 info.name= exactName;
1455 if( SUCCEEDED( ret ) )
1456 info.flags= DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT;
1458 else if( wFlags & DISPATCH_METHOD &&
1459 (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF))
1462 OUString exactName;
1463 // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT
1464 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1465 // try first as method
1466 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1467 pexcepinfo, puArgErr, info.name, params))
1468 && ret == DISP_E_MEMBERNOTFOUND)
1470 // try to get the exact name
1471 if (m_xExactName.is())
1473 exactName = m_xExactName->getExactName( info.name);
1474 // invoke again
1475 if( exactName.getLength() != 0)
1477 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1478 pexcepinfo, puArgErr, exactName, params)))
1479 info.name= exactName;
1483 if( SUCCEEDED( ret ) )
1484 info.flags= DISPATCH_METHOD;
1486 // try as property
1487 if( FAILED( ret) && pdispparams->cArgs == 1)
1489 if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1490 pexcepinfo, puArgErr, info.name, params))
1491 && ret == DISP_E_MEMBERNOTFOUND)
1493 // try to get the exact name
1494 if( exactName.getLength() != 0)
1496 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1497 pexcepinfo, puArgErr, exactName, params)))
1498 info.name= exactName;
1501 if( SUCCEEDED( ret ) )
1502 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1505 else if( wFlags & DISPATCH_METHOD && wFlags & DISPATCH_PROPERTYGET)
1507 OUString exactName;
1508 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1510 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1511 pexcepinfo, puArgErr, info.name, params))
1512 && ret == DISP_E_MEMBERNOTFOUND)
1514 // try to get the exact name
1515 if (m_xExactName.is())
1517 exactName = m_xExactName->getExactName( info.name);
1518 // invoke again
1519 if( exactName.getLength() != 0)
1521 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1522 pexcepinfo, puArgErr, exactName, params)))
1523 info.name= exactName;
1527 if( SUCCEEDED( ret ) )
1528 info.flags= DISPATCH_METHOD;
1530 // try as property
1531 if( FAILED( ret) && pdispparams->cArgs == 1)
1533 if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1534 pexcepinfo, info.name))
1535 && ret == DISP_E_MEMBERNOTFOUND)
1537 if( exactName.getLength() != 0)
1539 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1540 pexcepinfo, puArgErr, exactName, params)))
1541 info.name= exactName;
1544 if( SUCCEEDED( ret ) )
1545 info.flags= DISPATCH_PROPERTYGET;
1549 // update ínformation about this member
1550 if( ret == DISP_E_MEMBERNOTFOUND)
1552 // Remember the name as not existing
1553 // and remove the MemberInfo
1554 m_badNameMap[info.name]= sal_False;
1555 m_idToMemberInfoMap.erase( it_MemberInfo);
1557 } // if( ! info.flags )
1558 else // IdToMemberInfoMap contains a MemberInfo
1560 if( wFlags & DISPATCH_METHOD && info.flags == DISPATCH_METHOD)
1562 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1563 ret= doInvoke( pdispparams, pvarResult,
1564 pexcepinfo, puArgErr, info.name, params);
1566 else if( (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF ) &&
1567 info.flags & DISPATCH_PROPERTYPUT)
1569 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1570 ret= doSetProperty( pdispparams, pvarResult,
1571 pexcepinfo, puArgErr, info.name, params);
1573 else if( (wFlags & DISPATCH_PROPERTYGET) && ( info.flags & DISPATCH_PROPERTYGET))
1575 ret= doGetProperty( pdispparams, pvarResult,
1576 pexcepinfo, info.name);
1578 else
1580 ret= DISP_E_MEMBERNOTFOUND;
1583 }// if( it_MemberInfo != m_idToMemberInfoMap.end() )
1584 else
1585 ret= DISP_E_MEMBERNOTFOUND;
1588 catch(BridgeRuntimeError& e)
1590 writeExcepinfo(pexcepinfo, e.message);
1591 ret = DISP_E_EXCEPTION;
1593 catch(Exception& e)
1595 OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n") +
1596 e.Message;
1597 writeExcepinfo(pexcepinfo, message);
1598 ret = DISP_E_EXCEPTION;
1600 catch(...)
1602 OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n"
1603 "Unexpected exception");
1604 writeExcepinfo(pexcepinfo, message);
1605 ret = DISP_E_EXCEPTION;
1608 return ret;
1611 HRESULT UnoObjectWrapperRemoteOpt::methodInvoke( DISPID /*dispidMember*/, DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1612 EXCEPINFO * /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence<Any> params)
1614 return S_OK;
1618 // The returned HRESULT is only appropriate for IDispatch::Invoke
1619 static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr)
1621 HRESULT ret;
1622 sal_Bool bWriteIndex= sal_True;
1624 switch ( e.Reason)
1626 case FailReason::OUT_OF_RANGE:
1627 ret = DISP_E_OVERFLOW;
1628 break;
1629 case FailReason::IS_NOT_NUMBER:
1630 ret = DISP_E_TYPEMISMATCH;
1631 break;
1632 case FailReason::IS_NOT_ENUM:
1633 ret = DISP_E_TYPEMISMATCH;
1634 break;
1635 case FailReason::IS_NOT_BOOL:
1636 ret = DISP_E_TYPEMISMATCH;
1637 break;
1638 case FailReason::NO_SUCH_INTERFACE:
1639 ret = DISP_E_TYPEMISMATCH;
1640 break;
1641 case FailReason::SOURCE_IS_NO_DERIVED_TYPE:
1642 ret = DISP_E_TYPEMISMATCH;
1643 break;
1644 case FailReason::TYPE_NOT_SUPPORTED:
1645 ret = DISP_E_TYPEMISMATCH;
1646 break;
1647 case FailReason::INVALID:
1648 ret = DISP_E_TYPEMISMATCH;
1649 break;
1650 case FailReason::NO_DEFAULT_AVAILABLE:
1651 ret = DISP_E_BADPARAMCOUNT;
1652 break;
1653 case FailReason::UNKNOWN:
1654 ret = E_UNEXPECTED;
1655 break;
1656 default:
1657 ret = E_UNEXPECTED;
1658 bWriteIndex= sal_False;
1659 break;
1662 if( bWriteIndex && puArgErr != NULL)
1663 *puArgErr = e.ArgumentIndex;
1664 return ret;
1667 // The function maps the TypeClass of the any to VARTYPE: If
1668 // the Any contains STRUCT or INTERFACE then the return value
1669 // is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper
1670 // and the result is put into the constructor of the uno - wrapper
1671 // object. If a client asks the object for DISPID_VALUE and this
1672 // funtion returned VT_DISPATCH then the IDispatch of the same
1673 // object is being returned.
1674 // See InterfaceOleWrapper_Impl::Invoke, InterfaceOleWrapper_Impl::m_defaultValueType
1675 const VARTYPE getVarType( const Any& value)
1677 VARTYPE ret= VT_EMPTY;
1679 switch ( value.getValueTypeClass())
1681 case TypeClass_STRUCT: ret= VT_DISPATCH; break;
1682 case TypeClass_INTERFACE: ret= VT_DISPATCH; break;
1683 default: break;
1685 return ret;
1691 } // end namespace