merged tag ooo/OOO330_m14
[LibreOffice.git] / extensions / source / ole / unoobjw.cxx
blob5452a95129ff05929c432de4b2078e1b2450fcdd
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
31 #include "ole2uno.hxx"
32 #include <stdio.h>
33 #include <tools/presys.h>
34 #include <olectl.h>
35 #include <vector>
36 #include <list>
37 #include <hash_map>
38 #include "comifaces.hxx"
39 #include <tools/postsys.h>
42 #include <vos/diagnose.hxx>
43 #include <vos/refernce.hxx>
44 #include <tools/debug.hxx>
45 #include <rtl/ustring.hxx>
46 #include <com/sun/star/beans/MethodConcept.hpp>
47 #include <com/sun/star/beans/PropertyConcept.hpp>
48 #include <com/sun/star/script/FailReason.hpp>
49 #include <com/sun/star/reflection/ParamInfo.hpp>
50 #include <com/sun/star/beans/XExactName.hpp>
51 #include <com/sun/star/container/NoSuchElementException.hpp>
53 #include <com/sun/star/beans/XMaterialHolder.hpp>
54 #include <com/sun/star/script/XInvocation2.hpp>
55 #include <com/sun/star/script/MemberType.hpp>
56 #include <com/sun/star/reflection/XIdlReflection.hpp>
57 #include <osl/interlck.h>
58 #include <com/sun/star/uno/genfunc.h>
59 #include <cppuhelper/implbase1.hxx>
61 #include "comifaces.hxx"
62 #include "jscriptclasses.hxx"
63 #include "unotypewrapper.hxx"
64 #include "oleobjw.hxx"
65 #include "unoobjw.hxx"
66 #include "servprov.hxx"
68 using namespace vos;
69 using namespace std;
70 using namespace rtl;
71 using namespace osl;
72 using namespace cppu;
73 using namespace com::sun::star::uno;
74 using namespace com::sun::star::beans;
75 using namespace com::sun::star::container;
76 using namespace com::sun::star::script;
77 using namespace com::sun::star::lang;
78 using namespace com::sun::star::bridge::ModelDependent;
79 using namespace com::sun::star::reflection;
83 #if _MSC_VER < 1200
84 extern "C" const GUID IID_IDispatchEx;
85 #endif
87 namespace ole_adapter
89 hash_map<sal_uInt32, WeakReference<XInterface> > UnoObjToWrapperMap;
90 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource);
91 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource);
92 static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr);
95 /* Does not throw any exceptions.
96 Param pInfo can be NULL.
98 static void writeExcepinfo(EXCEPINFO * pInfo, const OUString& message)
100 if (pInfo != NULL)
102 pInfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
103 pInfo->bstrSource = SysAllocString(L"[automation bridge] ");
104 pInfo->bstrDescription = SysAllocString(reinterpret_cast<LPCOLESTR>(message.getStr()));
108 /*****************************************************************************
110 class implementation: InterfaceOleWrapper_Impl
112 *****************************************************************************/
113 InterfaceOleWrapper_Impl::InterfaceOleWrapper_Impl( Reference<XMultiServiceFactory>& xFactory,
114 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
115 m_defaultValueType( 0),
116 UnoConversionUtilities<InterfaceOleWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass)
120 InterfaceOleWrapper_Impl::~InterfaceOleWrapper_Impl()
122 MutexGuard guard(getBridgeMutex());
123 // remove entries in global map
124 IT_Uno it= UnoObjToWrapperMap.find( (sal_uInt32) m_xOrigin.get());
125 if(it != UnoObjToWrapperMap.end())
126 UnoObjToWrapperMap.erase(it);
127 #if OSL_DEBUG_LEVEL > 0
128 fprintf(stderr,"[automation bridge] UnoObjToWrapperMap contains: %i \n",
129 UnoObjToWrapperMap.size());
130 #endif
134 STDMETHODIMP InterfaceOleWrapper_Impl::QueryInterface(REFIID riid, LPVOID FAR * ppv)
136 HRESULT ret= S_OK;
138 if( !ppv)
139 return E_POINTER;
141 if(IsEqualIID(riid, IID_IUnknown))
143 AddRef();
144 *ppv = (IUnknown*) (IDispatch*) this;
146 else if (IsEqualIID(riid, IID_IDispatch))
148 AddRef();
149 *ppv = (IDispatch*) this;
151 else if( IsEqualIID( riid, __uuidof( IUnoObjectWrapper)))
153 AddRef();
154 *ppv= (IUnoObjectWrapper*) this;
156 else
157 ret= E_NOINTERFACE;
158 return ret;
161 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::AddRef()
163 acquire();
164 // does not need to guard because one should not rely on the return value of
165 // AddRef anyway
166 return m_refCount;
169 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::Release()
171 ULONG n= m_refCount;
172 release();
173 return n - 1;
176 // IUnoObjectWrapper --------------------------------------------------------
177 STDMETHODIMP InterfaceOleWrapper_Impl::getWrapperXInterface( Reference<XInterface>* pXInt)
179 *pXInt= Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY);
180 return pXInt->is() ? S_OK : E_FAIL;
182 STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoObject( Reference<XInterface>* pXInt)
184 *pXInt= m_xOrigin;
185 return m_xOrigin.is() ? S_OK : E_FAIL;
187 STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoStruct( Any * pStruct)
189 HRESULT ret= E_FAIL;
190 if( !m_xOrigin.is())
192 Reference<XMaterialHolder> xMatHolder( m_xInvocation, UNO_QUERY);
193 if( xMatHolder.is())
195 Any any = xMatHolder->getMaterial();
196 if( any.getValueTypeClass() == TypeClass_STRUCT)
198 *pStruct= any;
199 ret= S_OK;
203 return ret;
206 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfoCount( unsigned int * /*pctinfo*/ )
208 return E_NOTIMPL ;
211 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfo(unsigned int /*itinfo*/, LCID /*lcid*/, ITypeInfo ** /*pptinfo*/)
213 return E_NOTIMPL;
216 STDMETHODIMP InterfaceOleWrapper_Impl::GetIDsOfNames(REFIID /*riid*/,
217 OLECHAR ** rgszNames,
218 unsigned int cNames,
219 LCID /*lcid*/,
220 DISPID * rgdispid )
222 HRESULT ret = DISP_E_UNKNOWNNAME;
225 MutexGuard guard( getBridgeMutex());
226 if( ! rgdispid)
227 return E_POINTER;
229 // ----------------------------------------
230 if( ! _wcsicmp( *rgszNames, JSCRIPT_VALUE_FUNC) ||
231 ! _wcsicmp( *rgszNames, BRIDGE_VALUE_FUNC))
233 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
234 return S_OK;
236 else if( ! _wcsicmp( *rgszNames, GET_STRUCT_FUNC) ||
237 ! _wcsicmp( *rgszNames, BRIDGE_GET_STRUCT_FUNC))
239 *rgdispid= DISPID_GET_STRUCT_FUNC;
240 return S_OK;
242 else if( ! _wcsicmp( *rgszNames, BRIDGE_CREATE_TYPE_FUNC))
244 *rgdispid= DISPID_CREATE_TYPE_FUNC;
245 return S_OK;
248 // ----------------------------------------
249 if (m_xInvocation.is() && (cNames > 0))
251 OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0]));
252 NameToIdMap::iterator iter = m_nameToDispIdMap.find(name);
254 if (iter == m_nameToDispIdMap.end())
256 OUString exactName;
258 if (m_xExactName.is())
260 exactName = m_xExactName->getExactName(name);
262 else
264 exactName = name;
267 MemberInfo d(0, exactName);
269 if (m_xInvocation->hasProperty(exactName))
271 d.flags |= DISPATCH_PROPERTYGET;
272 d.flags |= DISPATCH_PROPERTYPUT;
273 d.flags |= DISPATCH_PROPERTYPUTREF;
276 if (m_xInvocation->hasMethod(exactName))
278 d.flags |= DISPATCH_METHOD;
281 if (d.flags != 0)
283 m_MemberInfos.push_back(d);
284 iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(exactName, (DISPID)m_MemberInfos.size())).first;
286 if (exactName != name)
288 iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(name, (DISPID)m_MemberInfos.size())).first;
293 if (iter == m_nameToDispIdMap.end())
295 ret = DISP_E_UNKNOWNNAME;
297 else
299 *rgdispid = (*iter).second;
300 ret = S_OK;
304 catch(BridgeRuntimeError& )
306 OSL_ASSERT(0);
308 catch(Exception& )
310 OSL_ASSERT(0);
312 catch(...)
314 OSL_ASSERT(0);
317 return ret;
320 // "convertDispparamsArgs" converts VARIANTS to their respecting Any counterparts
321 // The parameters "id", "wFlags" and "pdispparams" equal those as used in
322 // IDispatch::Invoke. The function handles special JavaScript
323 // cases where a VARIANT of type VT_DISPATCH is ambiguous and could represent
324 // an object, array ( JavaScript Array object), out parameter and in/out ( JavaScript Array object)
325 // parameter (JavaScript Array object)
326 // Because all those VT_DISPATCH objects need a different conversion
327 // we have to find out what the object is supposed to be. The function does this
328 // by either using type information or by help of a specialized ValueObject object.
330 // A. Type Information
331 // -----------------------------------------------------------------------------
332 // With the help of type information the kind of parameter can be exactly determined
333 // and an appropriate conversion can be choosen. A problem arises if a method expects
334 // an Any. Then the type info does not tell what the type of the value, that is kept
335 // by the any, should be. In this situation the decision wheter the param is a
336 // sequence or an object is made upon the fact if the object has a property "0"
337 // ( see function "isJScriptArray"). Since this is unsafe it is recommended to use
338 // the JScript value objects within a JScript script on such an occasion.
340 // B. JavaScript Value Object ( class JScriptValue )
341 // -----------------------------------------------------------------------------
342 // A JScriptValue (ValueObject) object is a COM object in that it implements IDispatch and the
343 // IJScriptValue object interface. Such objects are provided by all UNO wrapper
344 // objects used within a JScript script. To obtain an instance one has to call
345 // "_GetValueObject() or Bridge_GetValueObject()" on an UNO wrapper object (class InterfaceOleWrapper_Impl).
346 // A value object is appropriately initialized within the script and passed as
347 // parameter to an UNO object method or property. The convertDispparamsArgs function
348 // can easily find out that a param is such an object by queriing for the
349 // IJScriptValue interface. By this interface one the type and kind ( out, in/out)
350 // can be determined and the right conversion can be applied.
351 // Using ValueObjects we spare us the effort of aquiring and examining type information
352 // in order to figure out what the an IDispatch parameter is meant for.
354 // Normal JScript object parameter can be mixed with JScriptValue object. If an
355 // VARIANT contains an VT_DISPATCH that is no JScriptValue than the type information
356 // is used to find out about the reqired type.
357 void InterfaceOleWrapper_Impl::convertDispparamsArgs(DISPID id,
358 unsigned short /*wFlags*/, DISPPARAMS* pdispparams, Sequence<Any>& rSeq)
360 HRESULT hr= S_OK;
361 sal_Int32 countArgs= pdispparams->cArgs;
362 if( countArgs == 0)
363 return;
365 rSeq.realloc( countArgs);
366 Any* pParams = rSeq.getArray();
368 Any anyParam;
370 //Get type information for the current call
371 InvocationInfo info;
372 if( ! getInvocationInfoForCall( id, info))
373 throw BridgeRuntimeError(
374 OUSTR("[automation bridge]InterfaceOleWrapper_Impl::convertDispparamsArgs \n"
375 "Could not obtain type information for current call."));
377 for (int i = 0; i < countArgs; i++)
379 if (info.eMemberType == MemberType_METHOD &&
380 info.aParamModes[ countArgs - i -1 ] == ParamMode_OUT)
381 continue;
383 if(convertValueObject( & pdispparams->rgvarg[i], anyParam))
384 { //a param is a ValueObject and could be converted
385 pParams[countArgs - (i + 1)] = anyParam;
386 continue;
389 // If the param is an out, in/out parameter in
390 // JScript (Array object, with value at index 0) then we
391 // extract Array[0] and put the value into varParam. At the end of the loop varParam
392 // is converted if it contains a value otherwise the VARIANT from
393 // DISPPARAMS is converted.
394 CComVariant varParam;
396 // Check for JScript out and in/out paramsobjects (VT_DISPATCH).
397 // To find them out we use typeinformation of the function being called.
398 if( pdispparams->rgvarg[i].vt == VT_DISPATCH )
400 if( info.eMemberType == MemberType_METHOD && info.aParamModes[ countArgs - i -1 ] == ParamMode_INOUT)
402 // INOUT-param
403 // Index ( property) "0" contains the actual IN-param. The object is a JScript
404 // Array object.
405 // Get the IN-param at index "0"
406 IDispatch* pdisp= pdispparams->rgvarg[i].pdispVal;
408 OLECHAR* sindex= L"0";
409 DISPID id;
410 DISPPARAMS noParams= {0,0,0,0};
411 if(SUCCEEDED( hr= pdisp->GetIDsOfNames( IID_NULL, &sindex, 1, LOCALE_USER_DEFAULT, &id)))
412 hr= pdisp->Invoke( id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
413 & noParams, & varParam, NULL, NULL);
414 if( FAILED( hr))
416 throw BridgeRuntimeError(
417 OUSTR("[automation bridge] Could not determine "
418 "if the object has a member \"0\". Error: ") +
419 OUString::valueOf(hr));
424 if( varParam.vt == VT_EMPTY) // then it was no in/out parameter
425 varParam= pdispparams->rgvarg[i];
427 if(info.eMemberType == MemberType_METHOD)
428 variantToAny( & varParam, anyParam,
429 info.aParamTypes[ countArgs - i - 1]);
430 else if(info.eMemberType == MemberType_PROPERTY)
431 variantToAny( & varParam, anyParam, info.aType);
432 else
433 OSL_ASSERT(0);
435 pParams[countArgs - (i + 1)]= anyParam;
436 }// end for / iterating over all parameters
439 sal_Bool InterfaceOleWrapper_Impl::getInvocationInfoForCall( DISPID id, InvocationInfo& info)
441 sal_Bool bTypesAvailable= sal_False;
443 if( !m_xInvocation.is() )return false;
444 Reference<XInvocation2> inv2( m_xInvocation, UNO_QUERY);
445 if( inv2.is())
447 // We need the name of the property or method to get its type information.
448 // The name can be identified through the param "id"
449 // that is kept as value in the map m_nameToDispIdMap.
450 // Proplem: the Windows JScript engine sometimes changes small letters to capital
451 // letters as happens in xidlclass_obj.createObject( var) // in JScript.
452 // IDispatch::GetIdsOfNames is then called with "CreateObject" !!!
453 // m_nameToDispIdMap can contain several names for one DISPID but only one is
454 // the exact one. If there's no m_xExactName and therefore no exact name then
455 // there's only one entry in the map.
456 typedef NameToIdMap::const_iterator cit;
457 OUString sMemberName;
459 for(cit ci1= m_nameToDispIdMap.begin(); ci1 != m_nameToDispIdMap.end(); ci1++)
461 if( (*ci1).second == id) // iterator is a pair< OUString, DISPID>
463 sMemberName= (*ci1).first;
464 break;
467 // Get information for the current call ( property or method).
468 // There could be similar names which only differ in the cases
469 // of letters. First we assume that the name which was passed into
470 // GetIDsOfNames is correct. If we won't get information with that
471 // name then we have the invocation service use the XExactName interface.
472 sal_Bool validInfo= sal_True;
473 InvocationInfo invInfo;
474 try{
475 invInfo= inv2->getInfoForName( sMemberName, sal_False);
477 catch( IllegalArgumentException )
479 validInfo= sal_False;
482 if( ! validInfo)
484 invInfo= inv2->getInfoForName( sMemberName, sal_True);
486 if( invInfo.aName.pData)
488 bTypesAvailable= sal_True;
489 info= invInfo;
492 return bTypesAvailable;
494 // XBridgeSupplier2 ---------------------------------------------------
495 // only bridges itself ( this instance of InterfaceOleWrapper_Impl)from UNO to IDispatch
496 // If sourceModelType is UNO than any UNO interface implemented by InterfaceOleWrapper_Impl
497 // can bridged to IDispatch ( if destModelType == OLE). The IDispatch is
498 // implemented by this class.
499 Any SAL_CALL InterfaceOleWrapper_Impl::createBridge(const Any& modelDepObject,
500 const Sequence<sal_Int8>& /*ProcessId*/,
501 sal_Int16 sourceModelType,
502 sal_Int16 destModelType)
503 throw (IllegalArgumentException, RuntimeException)
506 Any retAny;
507 if( sourceModelType == UNO && destModelType == OLE &&
508 modelDepObject.getValueTypeClass() == TypeClass_INTERFACE )
510 Reference<XInterface> xInt;
511 if( modelDepObject >>= xInt )
513 if( xInt == Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY))
515 VARIANT *pVar= (VARIANT*)CoTaskMemAlloc( sizeof( VARIANT));
516 if( pVar)
518 pVar->vt= VT_DISPATCH;
519 pVar->pdispVal= static_cast<IDispatch*>( this);
520 AddRef();
522 retAny<<= reinterpret_cast< sal_uInt32 >( pVar);
528 return retAny;
532 // XInitialization --------------------------------------------------
533 void SAL_CALL InterfaceOleWrapper_Impl::initialize( const Sequence< Any >& aArguments )
534 throw(Exception, RuntimeException)
536 switch( aArguments.getLength() )
538 case 2: // the object wraps an UNO struct
539 aArguments[0] >>= m_xInvocation;
540 aArguments[1] >>= m_defaultValueType;
541 break;
542 case 3: // the object wraps an UNO interface
543 aArguments[0] >>= m_xInvocation;
544 aArguments[1] >>= m_xOrigin;
545 aArguments[2] >>= m_defaultValueType;
546 break;
549 m_xExactName= Reference<XExactName>( m_xInvocation, UNO_QUERY);
552 Reference< XInterface > InterfaceOleWrapper_Impl::createUnoWrapperInstance()
554 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl(
555 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
556 return Reference<XInterface>( xWeak, UNO_QUERY);
559 Reference<XInterface> InterfaceOleWrapper_Impl::createComWrapperInstance()
561 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl(
562 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
563 return Reference<XInterface>( xWeak, UNO_QUERY);
568 // "getType" is used in convertValueObject to map the string denoting the type
569 // to an actual Type object.
570 bool getType( const BSTR name, Type & type)
572 Type retType;
573 bool ret = false;
574 typelib_TypeDescription * pDesc= NULL;
575 OUString str( reinterpret_cast<const sal_Unicode*>(name));
576 typelib_typedescription_getByName( &pDesc, str.pData );
577 if( pDesc)
579 type = Type( pDesc->pWeakRef );
580 typelib_typedescription_release( pDesc);
581 ret = true;
583 return ret;
586 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource)
588 sal_Bool ret = sal_False;
589 HRESULT hr;
591 // Handle JScriptValue objects and JScript out params ( Array object )
592 CComVariant varDest( *pDest);
594 if( SUCCEEDED( varDest.ChangeType(VT_DISPATCH)))
596 CComPtr<IDispatch> spDispDest(varDest.pdispVal);
598 // special Handling for a JScriptValue object
599 #ifdef __MINGW32__
600 CComQIPtr<IJScriptValueObject, &__uuidof(IJScriptValueObject)> spValueDest(spDispDest);
601 #else
602 CComQIPtr<IJScriptValueObject> spValueDest(spDispDest);
603 #endif
604 if (spValueDest)
606 VARIANT_BOOL varBool= VARIANT_FALSE;
607 if( SUCCEEDED( hr= spValueDest->IsOutParam( &varBool) )
608 && varBool == VARIANT_TRUE ||
609 SUCCEEDED(hr= spValueDest->IsInOutParam( &varBool) )
610 && varBool == VARIANT_TRUE )
612 if( SUCCEEDED( spValueDest->Set( CComVariant(), *pSource)))
613 ret= sal_True;
616 else if (pDest->vt == VT_DISPATCH)// VT_DISPATCH -> JScript out param
618 // We use IDispatchEx because its GetDispID function causes the creation
619 // of a property if it does not exist already. This is convenient for
620 // out parameters in JScript. Then the user must not specify propery "0"
621 // explicitly
622 #ifdef __MINGW32__
623 CComQIPtr<IDispatchEx, &__uuidof(IDispatchEx)> spDispEx( spDispDest);
624 #else
625 CComQIPtr<IDispatchEx> spDispEx( spDispDest);
626 #endif
627 if( spDispEx)
629 CComBSTR nullProp(L"0");
630 DISPID dwDispID;
631 if( SUCCEEDED( spDispEx->GetDispID( nullProp, fdexNameEnsure, &dwDispID)))
633 DISPPARAMS dispparams = {NULL, NULL, 1, 1};
634 dispparams.rgvarg = pSource;
635 DISPID dispidPut = DISPID_PROPERTYPUT;
636 dispparams.rgdispidNamedArgs = &dispidPut;
638 if (pSource->vt == VT_UNKNOWN || pSource->vt == VT_DISPATCH ||
639 (pSource->vt & VT_ARRAY) || (pSource->vt & VT_BYREF))
640 hr = spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
641 &dispparams, NULL, NULL, NULL);
642 else
643 hr= spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
644 &dispparams, NULL, NULL, NULL);
645 if( SUCCEEDED(hr))
646 ret= sal_True;
650 else
651 ret= writeBackOutParameter( pDest, pSource);
653 else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript
654 { // param. The function checks itself for correct VBScript params
655 ret= writeBackOutParameter( pDest, pSource);
657 return ret;
659 // VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter.
660 // Thus we are in charge of freeing an eventual value contained by the inner VARIANT
661 // Please note: VariantCopy doesn't free a VT_BYREF value
662 // The out parameters are expected to have always a valid type
663 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource)
665 HRESULT hr;
666 sal_Bool ret = FALSE;
667 // Out parameter must be VT_BYREF
668 if ((V_VT(pDest) & VT_BYREF) != 0 )
670 VARTYPE oleTypeFlags = V_VT(pSource);
672 // if caller accept VARIANT as out parameter, any value must be converted
673 if (V_VT(pDest) == (VT_VARIANT | VT_BYREF))
675 // When the user provides a VARIANT rather then a concrete type
676 // we just copy the source to the out, in/out parameter
677 // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that
678 // is contained in pDest are released by VariantCopy
679 VariantCopy(V_VARIANTREF(pDest), pSource);
680 ret = sal_True;
682 else
684 // variantarg and variant must have same type
685 if ((V_VT(pDest) & oleTypeFlags) == oleTypeFlags)
687 if ((oleTypeFlags & VT_ARRAY) != 0)
689 // In / Out Param
690 if( *V_ARRAYREF(pDest) != NULL)
691 hr= SafeArrayCopyData( V_ARRAY(pSource), *V_ARRAYREF(pDest));
692 else
693 // Out Param
694 hr= SafeArrayCopy(V_ARRAY(pSource), V_ARRAYREF(pDest)) == NOERROR;
695 if( SUCCEEDED( hr))
696 ret = sal_True;
698 else
700 // copy base type
701 switch (V_VT(pSource))
703 case VT_I2:
705 *V_I2REF(pDest) = V_I2(pSource);
706 ret = sal_True;
707 break;
709 case VT_I4:
710 *V_I4REF(pDest) = V_I4(pSource);
711 ret = sal_True;
712 break;
713 case VT_R4:
714 *V_R4REF(pDest) = V_R4(pSource);
715 ret = sal_True;
716 break;
717 case VT_R8:
718 *V_R8REF(pDest) = V_R8(pSource);
719 ret = sal_True;
720 break;
721 case VT_CY:
722 *V_CYREF(pDest) = V_CY(pSource);
723 ret = sal_True;
724 break;
725 case VT_DATE:
726 *V_DATEREF(pDest) = V_DATE(pSource);
727 ret = sal_True;
728 break;
729 case VT_BSTR:
730 SysFreeString( *pDest->pbstrVal);
732 *V_BSTRREF(pDest) = SysAllocString(V_BSTR(pSource));
733 ret = sal_True;
734 break;
735 case VT_DISPATCH:
736 if (*V_DISPATCHREF(pDest) != NULL)
737 (*V_DISPATCHREF(pDest))->Release();
739 *V_DISPATCHREF(pDest) = V_DISPATCH(pSource);
741 if (*V_DISPATCHREF(pDest) != NULL)
742 (*V_DISPATCHREF(pDest))->AddRef();
744 ret = sal_True;
745 break;
746 case VT_ERROR:
747 *V_ERRORREF(pDest) = V_ERROR(pSource);
748 ret = sal_True;
749 break;
750 case VT_BOOL:
751 *V_BOOLREF(pDest) = V_BOOL(pSource);
752 ret = sal_True;
753 break;
754 case VT_UNKNOWN:
755 if (*V_UNKNOWNREF(pDest) != NULL)
756 (*V_UNKNOWNREF(pDest))->Release();
758 *V_UNKNOWNREF(pDest) = V_UNKNOWN(pSource);
760 if (*V_UNKNOWNREF(pDest) != NULL)
761 (*V_UNKNOWNREF(pDest))->AddRef();
763 ret = sal_True;
764 break;
765 case VT_I1:
766 *V_I1REF(pDest) = V_I1(pSource);
767 ret = sal_True;
768 break;
769 case VT_UI1:
770 *V_UI1REF(pDest) = V_UI1(pSource);
771 ret = sal_True;
772 break;
773 case VT_UI2:
774 *V_UI2REF(pDest) = V_UI2(pSource);
775 ret = sal_True;
776 break;
777 case VT_UI4:
778 *V_UI4REF(pDest) = V_UI4(pSource);
779 ret = sal_True;
780 break;
781 case VT_INT:
782 *V_INTREF(pDest) = V_INT(pSource);
783 ret = sal_True;
784 break;
785 case VT_UINT:
786 *V_UINTREF(pDest) = V_UINT(pSource);
787 ret = sal_True;
788 break;
789 case VT_DECIMAL:
790 memcpy(pDest->pdecVal, pSource, sizeof(DECIMAL));
791 ret = sal_True;
792 break;
793 default:
794 break;
798 else
800 // Handling of special cases
801 // Destination and source types are different
802 if( pDest->vt == (VT_BSTR | VT_BYREF)
803 && pSource->vt == VT_I2)
805 // When the user provides a String as out our in/out parameter
806 // and the type is char (TypeClass_CHAR) then we convert to a BSTR
807 // instead of VT_I2 as is done otherwise
808 OLECHAR buff[]= {0,0};
809 buff[0]= pSource->iVal;
811 SysFreeString( *pDest->pbstrVal);
812 *pDest->pbstrVal= SysAllocString( buff);
813 ret = sal_True;
818 return ret;
821 STDMETHODIMP InterfaceOleWrapper_Impl::Invoke(DISPID dispidMember,
822 REFIID /*riid*/,
823 LCID /*lcid*/,
824 unsigned short wFlags,
825 DISPPARAMS * pdispparams,
826 VARIANT * pvarResult,
827 EXCEPINFO * pexcepinfo,
828 unsigned int * puArgErr )
830 HRESULT ret = S_OK;
834 sal_Bool bHandled= sal_False;
835 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo,
836 puArgErr, bHandled);
837 if( bHandled)
838 return ret;
840 if ((dispidMember > 0) && ((size_t)dispidMember <= m_MemberInfos.size()) && m_xInvocation.is())
842 MemberInfo d = m_MemberInfos[dispidMember - 1];
843 DWORD flags = wFlags & d.flags;
845 if (flags != 0)
847 if ((flags & DISPATCH_METHOD) != 0)
849 if (pdispparams->cNamedArgs > 0)
850 ret = DISP_E_NONAMEDARGS;
851 else
853 Sequence<Any> params;
855 convertDispparamsArgs(dispidMember, wFlags, pdispparams , params );
857 ret= doInvoke(pdispparams, pvarResult,
858 pexcepinfo, puArgErr, d.name, params);
861 else if ((flags & DISPATCH_PROPERTYGET) != 0)
863 ret= doGetProperty( pdispparams, pvarResult,
864 pexcepinfo, d.name);
866 else if ((flags & DISPATCH_PROPERTYPUT || flags & DISPATCH_PROPERTYPUTREF) != 0)
868 if (pdispparams->cArgs != 1)
869 ret = DISP_E_BADPARAMCOUNT;
870 else
872 Sequence<Any> params;
873 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
874 if(params.getLength() > 0)
875 ret= doSetProperty( pdispparams, pvarResult, pexcepinfo, puArgErr, d.name, params);
876 else
877 ret = DISP_E_BADVARTYPE;
881 else
882 ret= DISP_E_MEMBERNOTFOUND;
884 else
885 ret = DISP_E_MEMBERNOTFOUND;
887 catch(BridgeRuntimeError& e)
889 writeExcepinfo(pexcepinfo, e.message);
890 ret = DISP_E_EXCEPTION;
892 catch(Exception& e)
894 OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n") +
895 e.Message;
896 writeExcepinfo(pexcepinfo, message);
897 ret = DISP_E_EXCEPTION;
899 catch(...)
901 OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n"
902 "Unexpected exception");
903 writeExcepinfo(pexcepinfo, message);
904 ret = DISP_E_EXCEPTION;
907 return ret;
910 HRESULT InterfaceOleWrapper_Impl::doInvoke( DISPPARAMS * pdispparams, VARIANT * pvarResult,
911 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any>& params)
915 HRESULT ret= S_OK;
918 Sequence<INT16> outIndex;
919 Sequence<Any> outParams;
920 Any returnValue;
922 if (pdispparams->cNamedArgs > 0)
923 return DISP_E_NONAMEDARGS;
925 // invoke method and take care of exceptions
926 returnValue = m_xInvocation->invoke(name,
927 params,
928 outIndex,
929 outParams);
931 // try to write back out parameter
932 if (outIndex.getLength() > 0)
934 const INT16* pOutIndex = outIndex.getConstArray();
935 const Any* pOutParams = outParams.getConstArray();
937 for (sal_Int32 i = 0; i < outIndex.getLength(); i++)
939 CComVariant variant;
940 // Currently a Sequence is converted to an SafeArray of VARIANTs.
941 anyToVariant( &variant, pOutParams[i]);
943 // out parameter need special handling if they are VT_DISPATCH
944 // and used in JScript
945 int outindex= pOutIndex[i];
946 writeBackOutParameter2(&(pdispparams->rgvarg[pdispparams->cArgs - 1 - outindex]),
947 &variant );
951 // write back return value
952 if (pvarResult != NULL)
953 anyToVariant(pvarResult, returnValue);
955 catch(IllegalArgumentException & e) //XInvocation::invoke
957 writeExcepinfo(pexcepinfo, e.Message);
958 ret = DISP_E_TYPEMISMATCH;
960 catch(CannotConvertException & e) //XInvocation::invoke
962 writeExcepinfo(pexcepinfo, e.Message);
963 ret = mapCannotConvertException( e, puArgErr);
965 catch(InvocationTargetException & e) //XInvocation::invoke
967 const Any& org = e.TargetException;
968 Exception excTarget;
969 org >>= excTarget;
970 OUString message=
971 org.getValueType().getTypeName() + OUSTR(": ") + excTarget.Message;
972 writeExcepinfo(pexcepinfo, message);
973 ret = DISP_E_EXCEPTION;
975 catch(NoSuchMethodException & e) //XInvocation::invoke
977 writeExcepinfo(pexcepinfo, e.Message);
978 ret = DISP_E_MEMBERNOTFOUND;
980 catch(BridgeRuntimeError & e)
982 writeExcepinfo(pexcepinfo, e.message);
983 ret = DISP_E_EXCEPTION;
985 catch(Exception & e)
987 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n") +
988 e.Message;
989 writeExcepinfo(pexcepinfo, message);
990 ret = DISP_E_EXCEPTION;
992 catch( ... )
994 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n"
995 "Unexpected exception");
996 writeExcepinfo(pexcepinfo, message);
997 ret = DISP_E_EXCEPTION;
999 return ret;
1002 HRESULT InterfaceOleWrapper_Impl::doGetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * pvarResult,
1003 EXCEPINFO * pexcepinfo, OUString& name)
1005 HRESULT ret= S_OK;
1007 Any value;
1010 Any returnValue = m_xInvocation->getValue( name);
1011 // write back return value
1012 if (pvarResult)
1013 anyToVariant(pvarResult, returnValue);
1015 catch(UnknownPropertyException e) //XInvocation::getValue
1017 writeExcepinfo(pexcepinfo, e.Message);
1018 ret = DISP_E_MEMBERNOTFOUND;
1020 catch(BridgeRuntimeError& e)
1022 writeExcepinfo(pexcepinfo, e.message);
1023 ret = DISP_E_EXCEPTION;
1025 catch(Exception& e)
1027 OUString message= OUSTR("InterfaceOleWrapper_Impl::doGetProperty : \n") +
1028 e.Message;
1029 writeExcepinfo(pexcepinfo, message);
1031 catch( ... )
1033 OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n"
1034 "Unexpected exception");
1035 writeExcepinfo(pexcepinfo, message);
1036 ret = DISP_E_EXCEPTION;
1038 return ret;
1041 HRESULT InterfaceOleWrapper_Impl::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1042 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any> params)
1044 HRESULT ret= S_OK;
1048 m_xInvocation->setValue( name, params.getConstArray()[0]);
1050 catch(UnknownPropertyException )
1052 ret = DISP_E_MEMBERNOTFOUND;
1054 catch(CannotConvertException e)
1056 ret= mapCannotConvertException( e, puArgErr);
1058 catch(InvocationTargetException e)
1060 if (pexcepinfo != NULL)
1062 Any org = e.TargetException;
1064 pexcepinfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
1065 pexcepinfo->bstrSource = SysAllocString(L"any ONE component");
1066 pexcepinfo->bstrDescription = SysAllocString(
1067 reinterpret_cast<LPCOLESTR>(org.getValueType().getTypeName().getStr()));
1069 ret = DISP_E_EXCEPTION;
1071 catch( ... )
1073 ret= DISP_E_EXCEPTION;
1075 return ret;
1078 HRESULT InterfaceOleWrapper_Impl::InvokeGeneral( DISPID dispidMember, unsigned short wFlags,
1079 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1080 unsigned int * /*puArgErr*/, sal_Bool& bHandled)
1082 HRESULT ret= S_OK;
1085 // DISPID_VALUE | The DEFAULT Value is required in JScript when the situation
1086 // is that we put an object into an Array object ( out parameter). We have to return
1087 // IDispatch otherwise the object cannot be accessed from the Script.
1088 if( dispidMember == DISPID_VALUE && wFlags == DISPATCH_PROPERTYGET
1089 && m_defaultValueType != VT_EMPTY && pvarResult != NULL)
1091 bHandled= sal_True;
1092 if( m_defaultValueType == VT_DISPATCH)
1094 pvarResult->vt= VT_DISPATCH;
1095 pvarResult->pdispVal= static_cast<IDispatch*>( this);
1096 AddRef();
1097 ret= S_OK;
1100 // ---------
1101 // function: _GetValueObject
1102 else if( dispidMember == DISPID_JSCRIPT_VALUE_FUNC)
1104 bHandled= sal_True;
1105 if( !pvarResult)
1106 ret= E_POINTER;
1107 CComObject< JScriptValue>* pValue;
1108 if( SUCCEEDED( CComObject<JScriptValue>::CreateInstance( &pValue)))
1110 pValue->AddRef();
1111 pvarResult->vt= VT_DISPATCH;
1112 #ifdef __MINGW32__
1113 pvarResult->pdispVal= CComQIPtr<IDispatch, &__uuidof(IDispatch)>(pValue->GetUnknown());
1114 #else
1115 pvarResult->pdispVal= CComQIPtr<IDispatch>(pValue->GetUnknown());
1116 #endif
1117 ret= S_OK;
1119 else
1120 ret= DISP_E_EXCEPTION;
1122 else if( dispidMember == DISPID_GET_STRUCT_FUNC)
1124 bHandled= sal_True;
1125 sal_Bool bStruct= sal_False;
1128 Reference<XInterface> xIntCore= m_smgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection"));
1129 Reference<XIdlReflection> xRefl( xIntCore, UNO_QUERY);
1130 if( xRefl.is() )
1132 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1133 CComVariant arg;
1134 if( pdispparams->cArgs == 1 && SUCCEEDED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])) )
1136 Reference<XIdlClass> classStruct= xRefl->forName( reinterpret_cast<const sal_Unicode*>(arg.bstrVal));
1137 if( classStruct.is())
1139 Any anyStruct;
1140 classStruct->createObject( anyStruct);
1141 CComVariant var;
1142 anyToVariant( &var, anyStruct );
1144 if( var.vt == VT_DISPATCH)
1146 VariantCopy( pvarResult, & var);
1147 bStruct= sal_True;
1152 ret= bStruct == sal_True ? S_OK : DISP_E_EXCEPTION;
1154 else if (dispidMember == DISPID_CREATE_TYPE_FUNC)
1156 bHandled= sal_True;
1157 if( !pvarResult)
1158 ret= E_POINTER;
1159 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1160 CComVariant arg;
1161 if( pdispparams->cArgs != 1)
1162 return DISP_E_BADPARAMCOUNT;
1163 if (FAILED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])))
1164 return DISP_E_BADVARTYPE;
1166 //check if the provided name represents a valid type
1167 Type type;
1168 if (getType(arg.bstrVal, type) == false)
1170 writeExcepinfo(pexcepinfo,OUString(
1171 OUSTR("[automation bridge] A UNO type with the name ") +
1172 OUString(reinterpret_cast<const sal_Unicode*>(arg.bstrVal)) + OUSTR(" does not exist!")));
1173 return DISP_E_EXCEPTION;
1176 if (createUnoTypeWrapper(arg.bstrVal, pvarResult) == false)
1178 writeExcepinfo(pexcepinfo,OUSTR("[automation bridge] InterfaceOleWrapper_Impl::InvokeGeneral\n"
1179 "Could not initialize UnoTypeWrapper object!"));
1180 return DISP_E_EXCEPTION;
1184 catch(BridgeRuntimeError & e)
1186 writeExcepinfo(pexcepinfo, e.message);
1187 ret = DISP_E_EXCEPTION;
1189 catch(Exception & e)
1191 OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n") +
1192 e.Message;
1193 writeExcepinfo(pexcepinfo, message);
1194 ret = DISP_E_EXCEPTION;
1196 catch( ... )
1198 OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n"
1199 "Unexpected exception");
1200 writeExcepinfo(pexcepinfo, message);
1201 ret = DISP_E_EXCEPTION;
1203 return ret;
1209 STDMETHODIMP InterfaceOleWrapper_Impl::GetDispID(BSTR /*bstrName*/, DWORD /*grfdex*/, DISPID __RPC_FAR* /*pid*/)
1211 HRESULT ret = ResultFromScode(E_NOTIMPL);
1213 return ret;
1216 STDMETHODIMP InterfaceOleWrapper_Impl::InvokeEx(
1217 /* [in] */ DISPID /*id*/,
1218 /* [in] */ LCID /*lcid*/,
1219 /* [in] */ WORD /*wFlags*/,
1220 /* [in] */ DISPPARAMS __RPC_FAR* /*pdp*/,
1221 /* [out] */ VARIANT __RPC_FAR* /*pvarRes*/,
1222 /* [out] */ EXCEPINFO __RPC_FAR* /*pei*/,
1223 /* [unique][in] */ IServiceProvider __RPC_FAR* /*pspCaller*/)
1225 HRESULT ret = ResultFromScode(E_NOTIMPL);
1227 return ret;
1231 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByName(
1232 /* [in] */ BSTR /*bstr*/,
1233 /* [in] */ DWORD /*grfdex*/)
1235 HRESULT ret = ResultFromScode(E_NOTIMPL);
1237 return ret;
1240 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByDispID(DISPID /*id*/)
1242 HRESULT ret = ResultFromScode(E_NOTIMPL);
1244 return ret;
1247 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberProperties(
1248 /* [in] */ DISPID /*id*/,
1249 /* [in] */ DWORD /*grfdexFetch*/,
1250 /* [out] */ DWORD __RPC_FAR* /*pgrfdex*/)
1252 HRESULT ret = ResultFromScode(E_NOTIMPL);
1254 return ret;
1257 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberName(
1258 /* [in] */ DISPID /*id*/,
1259 /* [out] */ BSTR __RPC_FAR* /*pbstrName*/)
1261 HRESULT ret = ResultFromScode(E_NOTIMPL);
1263 return ret;
1266 STDMETHODIMP InterfaceOleWrapper_Impl::GetNextDispID(
1267 /* [in] */ DWORD /*grfdex*/,
1268 /* [in] */ DISPID /*id*/,
1269 /* [out] */ DISPID __RPC_FAR* /*pid*/)
1271 HRESULT ret = ResultFromScode(E_NOTIMPL);
1273 return ret;
1276 STDMETHODIMP InterfaceOleWrapper_Impl::GetNameSpaceParent(
1277 /* [out] */ IUnknown __RPC_FAR *__RPC_FAR* /*ppunk*/)
1279 HRESULT ret = ResultFromScode(E_NOTIMPL);
1281 return ret;
1285 /*************************************************************************
1287 UnoObjectWrapperRemoteOpt
1289 *************************************************************************/
1290 UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference<XMultiServiceFactory>& aFactory,
1291 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
1292 InterfaceOleWrapper_Impl( aFactory, unoWrapperClass, comWrapperClass),
1293 m_currentId(1)
1297 UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt()
1301 // UnoConversionUtilities
1302 Reference< XInterface > UnoObjectWrapperRemoteOpt::createUnoWrapperInstance()
1304 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
1305 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1306 return Reference<XInterface>( xWeak, UNO_QUERY);
1309 STDMETHODIMP UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID /*riid*/, OLECHAR ** rgszNames, unsigned int cNames,
1310 LCID /*lcid*/, DISPID * rgdispid )
1312 MutexGuard guard( getBridgeMutex());
1314 if( ! rgdispid)
1315 return E_POINTER;
1316 HRESULT ret = E_UNEXPECTED;
1317 // ----------------------------------------
1318 // _GetValueObject
1319 if( ! wcscmp( *rgszNames, JSCRIPT_VALUE_FUNC))
1321 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
1322 return S_OK;
1324 else if( ! wcscmp( *rgszNames, GET_STRUCT_FUNC))
1326 *rgdispid= DISPID_GET_STRUCT_FUNC;
1327 return S_OK;
1330 // ----------------------------------------
1331 if (m_xInvocation.is() && (cNames > 0))
1333 OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0]));
1334 // has this name been determined as "bad"
1335 BadNameMap::iterator badIter= m_badNameMap.find( name);
1336 if( badIter == m_badNameMap.end() )
1338 // name has not been bad before( member exists
1339 typedef NameToIdMap::iterator ITnames;
1340 pair< ITnames, bool > pair_id= m_nameToDispIdMap.insert( NameToIdMap::value_type(name, m_currentId++));
1341 // new ID inserted ?
1342 if( pair_id.second )
1343 {// yes, now create MemberInfo and ad to IdToMemberInfoMap
1344 MemberInfo d(0, name);
1345 m_idToMemberInfoMap.insert( IdToMemberInfoMap::value_type( m_currentId - 1, d));
1348 *rgdispid = pair_id.first->second;
1349 ret = S_OK;
1351 else
1352 ret= DISP_E_UNKNOWNNAME;
1354 return ret;
1357 STDMETHODIMP UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember, REFIID /*riid*/, LCID /*lcid*/, unsigned short wFlags,
1358 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1359 unsigned int * puArgErr )
1361 HRESULT ret = S_OK;
1364 sal_Bool bHandled= sal_False;
1365 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo,
1366 puArgErr, bHandled);
1367 if( bHandled)
1368 return ret;
1370 if ( dispidMember > 0 && m_xInvocation.is())
1373 IdToMemberInfoMap::iterator it_MemberInfo= m_idToMemberInfoMap.find( dispidMember);
1374 if( it_MemberInfo != m_idToMemberInfoMap.end() )
1376 MemberInfo& info= it_MemberInfo->second;
1378 Sequence<Any> params; // holds converted any s
1379 if( ! info.flags )
1380 { // DISPID called for the first time
1381 if( wFlags == DISPATCH_METHOD )
1383 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1385 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1386 pexcepinfo, puArgErr, info.name, params))
1387 && ret == DISP_E_MEMBERNOTFOUND)
1389 // try to get the exact name
1390 OUString exactName;
1391 if (m_xExactName.is())
1393 exactName = m_xExactName->getExactName( info.name);
1394 // invoke again
1395 if( exactName.getLength() != 0)
1397 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1398 pexcepinfo, puArgErr, exactName, params)))
1399 info.name= exactName;
1403 if( SUCCEEDED( ret ) )
1404 info.flags= DISPATCH_METHOD;
1405 } //if( wFlags == DISPATCH_METHOD )
1407 else if( wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_PROPERTYPUTREF)
1409 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1410 if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1411 pexcepinfo, puArgErr, info.name, params))
1412 && ret == DISP_E_MEMBERNOTFOUND)
1414 // try to get the exact name
1415 OUString exactName;
1416 if (m_xExactName.is())
1418 exactName = m_xExactName->getExactName( info.name);
1419 // invoke again
1420 if( exactName.getLength() != 0)
1422 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1423 pexcepinfo, puArgErr, exactName, params)))
1424 info.name= exactName;
1428 if( SUCCEEDED( ret ) )
1429 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1432 else if( wFlags == DISPATCH_PROPERTYGET)
1434 if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1435 pexcepinfo, info.name))
1436 && ret == DISP_E_MEMBERNOTFOUND)
1438 // try to get the exact name
1439 OUString exactName;
1440 if (m_xExactName.is())
1442 exactName = m_xExactName->getExactName( info.name);
1443 // invoke again
1444 if( exactName.getLength() != 0)
1446 if( SUCCEEDED( ret= doGetProperty( pdispparams, pvarResult,
1447 pexcepinfo, exactName)))
1448 info.name= exactName;
1452 if( SUCCEEDED( ret ) )
1453 info.flags= DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT;
1455 else if( wFlags & DISPATCH_METHOD &&
1456 (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF))
1459 OUString exactName;
1460 // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT
1461 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1462 // try first as method
1463 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1464 pexcepinfo, puArgErr, info.name, params))
1465 && ret == DISP_E_MEMBERNOTFOUND)
1467 // try to get the exact name
1468 if (m_xExactName.is())
1470 exactName = m_xExactName->getExactName( info.name);
1471 // invoke again
1472 if( exactName.getLength() != 0)
1474 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1475 pexcepinfo, puArgErr, exactName, params)))
1476 info.name= exactName;
1480 if( SUCCEEDED( ret ) )
1481 info.flags= DISPATCH_METHOD;
1483 // try as property
1484 if( FAILED( ret) && pdispparams->cArgs == 1)
1486 if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1487 pexcepinfo, puArgErr, info.name, params))
1488 && ret == DISP_E_MEMBERNOTFOUND)
1490 // try to get the exact name
1491 if( exactName.getLength() != 0)
1493 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1494 pexcepinfo, puArgErr, exactName, params)))
1495 info.name= exactName;
1498 if( SUCCEEDED( ret ) )
1499 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1502 else if( wFlags & DISPATCH_METHOD && wFlags & DISPATCH_PROPERTYGET)
1504 OUString exactName;
1505 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1507 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1508 pexcepinfo, puArgErr, info.name, params))
1509 && ret == DISP_E_MEMBERNOTFOUND)
1511 // try to get the exact name
1512 if (m_xExactName.is())
1514 exactName = m_xExactName->getExactName( info.name);
1515 // invoke again
1516 if( exactName.getLength() != 0)
1518 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1519 pexcepinfo, puArgErr, exactName, params)))
1520 info.name= exactName;
1524 if( SUCCEEDED( ret ) )
1525 info.flags= DISPATCH_METHOD;
1527 // try as property
1528 if( FAILED( ret) && pdispparams->cArgs == 1)
1530 if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1531 pexcepinfo, info.name))
1532 && ret == DISP_E_MEMBERNOTFOUND)
1534 if( exactName.getLength() != 0)
1536 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1537 pexcepinfo, puArgErr, exactName, params)))
1538 info.name= exactName;
1541 if( SUCCEEDED( ret ) )
1542 info.flags= DISPATCH_PROPERTYGET;
1546 // update ínformation about this member
1547 if( ret == DISP_E_MEMBERNOTFOUND)
1549 // Remember the name as not existing
1550 // and remove the MemberInfo
1551 m_badNameMap[info.name]= sal_False;
1552 m_idToMemberInfoMap.erase( it_MemberInfo);
1554 } // if( ! info.flags )
1555 else // IdToMemberInfoMap contains a MemberInfo
1557 if( wFlags & DISPATCH_METHOD && info.flags == DISPATCH_METHOD)
1559 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1560 ret= doInvoke( pdispparams, pvarResult,
1561 pexcepinfo, puArgErr, info.name, params);
1563 else if( (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF ) &&
1564 info.flags & DISPATCH_PROPERTYPUT)
1566 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1567 ret= doSetProperty( pdispparams, pvarResult,
1568 pexcepinfo, puArgErr, info.name, params);
1570 else if( (wFlags & DISPATCH_PROPERTYGET) && ( info.flags & DISPATCH_PROPERTYGET))
1572 ret= doGetProperty( pdispparams, pvarResult,
1573 pexcepinfo, info.name);
1575 else
1577 ret= DISP_E_MEMBERNOTFOUND;
1580 }// if( it_MemberInfo != m_idToMemberInfoMap.end() )
1581 else
1582 ret= DISP_E_MEMBERNOTFOUND;
1585 catch(BridgeRuntimeError& e)
1587 writeExcepinfo(pexcepinfo, e.message);
1588 ret = DISP_E_EXCEPTION;
1590 catch(Exception& e)
1592 OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n") +
1593 e.Message;
1594 writeExcepinfo(pexcepinfo, message);
1595 ret = DISP_E_EXCEPTION;
1597 catch(...)
1599 OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n"
1600 "Unexpected exception");
1601 writeExcepinfo(pexcepinfo, message);
1602 ret = DISP_E_EXCEPTION;
1605 return ret;
1608 HRESULT UnoObjectWrapperRemoteOpt::methodInvoke( DISPID /*dispidMember*/, DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1609 EXCEPINFO * /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence<Any> params)
1611 return S_OK;
1615 // The returned HRESULT is only appropriate for IDispatch::Invoke
1616 static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr)
1618 HRESULT ret;
1619 sal_Bool bWriteIndex= sal_True;
1621 switch ( e.Reason)
1623 case FailReason::OUT_OF_RANGE:
1624 ret = DISP_E_OVERFLOW;
1625 break;
1626 case FailReason::IS_NOT_NUMBER:
1627 ret = DISP_E_TYPEMISMATCH;
1628 break;
1629 case FailReason::IS_NOT_ENUM:
1630 ret = DISP_E_TYPEMISMATCH;
1631 break;
1632 case FailReason::IS_NOT_BOOL:
1633 ret = DISP_E_TYPEMISMATCH;
1634 break;
1635 case FailReason::NO_SUCH_INTERFACE:
1636 ret = DISP_E_TYPEMISMATCH;
1637 break;
1638 case FailReason::SOURCE_IS_NO_DERIVED_TYPE:
1639 ret = DISP_E_TYPEMISMATCH;
1640 break;
1641 case FailReason::TYPE_NOT_SUPPORTED:
1642 ret = DISP_E_TYPEMISMATCH;
1643 break;
1644 case FailReason::INVALID:
1645 ret = DISP_E_TYPEMISMATCH;
1646 break;
1647 case FailReason::NO_DEFAULT_AVAILABLE:
1648 ret = DISP_E_BADPARAMCOUNT;
1649 break;
1650 case FailReason::UNKNOWN:
1651 ret = E_UNEXPECTED;
1652 break;
1653 default:
1654 ret = E_UNEXPECTED;
1655 bWriteIndex= sal_False;
1656 break;
1659 if( bWriteIndex && puArgErr != NULL)
1660 *puArgErr = e.ArgumentIndex;
1661 return ret;
1664 // The function maps the TypeClass of the any to VARTYPE: If
1665 // the Any contains STRUCT or INTERFACE then the return value
1666 // is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper
1667 // and the result is put into the constructor of the uno - wrapper
1668 // object. If a client asks the object for DISPID_VALUE and this
1669 // funtion returned VT_DISPATCH then the IDispatch of the same
1670 // object is being returned.
1671 // See InterfaceOleWrapper_Impl::Invoke, InterfaceOleWrapper_Impl::m_defaultValueType
1672 const VARTYPE getVarType( const Any& value)
1674 VARTYPE ret= VT_EMPTY;
1676 switch ( value.getValueTypeClass())
1678 case TypeClass_STRUCT: ret= VT_DISPATCH; break;
1679 case TypeClass_INTERFACE: ret= VT_DISPATCH; break;
1680 default: break;
1682 return ret;
1688 } // end namespace