bump product version to 5.0.4.1
[LibreOffice.git] / extensions / source / ole / unoobjw.cxx
bloba860e8424ef1d1d208c955f0d8738733cc79a755
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "ole2uno.hxx"
22 #include <stdio.h>
23 #include <list>
24 #include <unordered_map>
25 #include <vector>
27 #include <osl/diagnose.h>
28 #include <salhelper/simplereferenceobject.hxx>
29 #include <rtl/ustring.hxx>
30 #include <com/sun/star/beans/MethodConcept.hpp>
31 #include <com/sun/star/beans/PropertyConcept.hpp>
32 #include <com/sun/star/script/FailReason.hpp>
33 #include <com/sun/star/reflection/theCoreReflection.hpp>
34 #include <com/sun/star/reflection/ParamInfo.hpp>
35 #include <com/sun/star/beans/XExactName.hpp>
36 #include <com/sun/star/container/NoSuchElementException.hpp>
38 #include <com/sun/star/beans/XMaterialHolder.hpp>
39 #include <com/sun/star/script/XInvocation2.hpp>
40 #include <com/sun/star/script/MemberType.hpp>
41 #include <com/sun/star/reflection/XIdlReflection.hpp>
42 #include <osl/interlck.h>
43 #include <com/sun/star/uno/genfunc.h>
44 #include <comphelper/processfactory.hxx>
45 #include <cppuhelper/implbase1.hxx>
47 #include "comifaces.hxx"
48 #include "jscriptclasses.hxx"
49 #include "unotypewrapper.hxx"
50 #include "oleobjw.hxx"
51 #include "unoobjw.hxx"
52 #include "servprov.hxx"
54 using namespace std;
55 using namespace osl;
56 using namespace cppu;
57 using namespace com::sun::star::uno;
58 using namespace com::sun::star::beans;
59 using namespace com::sun::star::container;
60 using namespace com::sun::star::script;
61 using namespace com::sun::star::lang;
62 using namespace com::sun::star::bridge::ModelDependent;
63 using namespace com::sun::star::reflection;
65 #ifndef _MSC_VER
66 extern "C" const GUID IID_IDispatchEx;
67 #endif
69 namespace ole_adapter
71 std::unordered_map<sal_uInt32, WeakReference<XInterface> > UnoObjToWrapperMap;
72 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource);
73 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource);
74 static HRESULT mapCannotConvertException(const CannotConvertException &e, unsigned int * puArgErr);
76 /* Does not throw any exceptions.
77 Param pInfo can be NULL.
79 static void writeExcepinfo(EXCEPINFO * pInfo, const OUString& message)
81 if (pInfo != NULL)
83 pInfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
84 pInfo->bstrSource = SysAllocString(L"[automation bridge] ");
85 pInfo->bstrDescription = SysAllocString(reinterpret_cast<LPCOLESTR>(message.getStr()));
89 InterfaceOleWrapper_Impl::InterfaceOleWrapper_Impl( Reference<XMultiServiceFactory>& xFactory,
90 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
91 m_defaultValueType( 0),
92 UnoConversionUtilities<InterfaceOleWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass)
96 InterfaceOleWrapper_Impl::~InterfaceOleWrapper_Impl()
98 MutexGuard guard(getBridgeMutex());
99 // remove entries in global map
100 IT_Uno it= UnoObjToWrapperMap.find( (sal_uInt32) m_xOrigin.get());
101 if(it != UnoObjToWrapperMap.end())
102 UnoObjToWrapperMap.erase(it);
103 #if OSL_DEBUG_LEVEL > 0
104 fprintf(stderr,"[automation bridge] UnoObjToWrapperMap contains: %i \n",
105 UnoObjToWrapperMap.size());
106 #endif
109 STDMETHODIMP InterfaceOleWrapper_Impl::QueryInterface(REFIID riid, LPVOID FAR * ppv)
111 HRESULT ret= S_OK;
113 if( !ppv)
114 return E_POINTER;
116 if(IsEqualIID(riid, IID_IUnknown))
118 AddRef();
119 *ppv = (IUnknown*) (IDispatch*) this;
121 else if (IsEqualIID(riid, IID_IDispatch))
123 AddRef();
124 *ppv = (IDispatch*) this;
126 else if( IsEqualIID( riid, __uuidof( IUnoObjectWrapper)))
128 AddRef();
129 *ppv= (IUnoObjectWrapper*) this;
131 else
132 ret= E_NOINTERFACE;
133 return ret;
136 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::AddRef()
138 acquire();
139 // does not need to guard because one should not rely on the return value of
140 // AddRef anyway
141 return m_refCount;
144 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::Release()
146 ULONG n= m_refCount;
147 release();
148 return n - 1;
151 // IUnoObjectWrapper --------------------------------------------------------
152 STDMETHODIMP InterfaceOleWrapper_Impl::getWrapperXInterface( Reference<XInterface>* pXInt)
154 *pXInt= Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY);
155 return pXInt->is() ? S_OK : E_FAIL;
157 STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoObject( Reference<XInterface>* pXInt)
159 *pXInt= m_xOrigin;
160 return m_xOrigin.is() ? S_OK : E_FAIL;
162 STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoStruct( Any * pStruct)
164 HRESULT ret= E_FAIL;
165 if( !m_xOrigin.is())
167 Reference<XMaterialHolder> xMatHolder( m_xInvocation, UNO_QUERY);
168 if( xMatHolder.is())
170 Any any = xMatHolder->getMaterial();
171 if( any.getValueTypeClass() == TypeClass_STRUCT)
173 *pStruct= any;
174 ret= S_OK;
178 return ret;
181 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfoCount( unsigned int * /*pctinfo*/ )
183 return E_NOTIMPL ;
186 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfo(unsigned int /*itinfo*/, LCID /*lcid*/, ITypeInfo ** /*pptinfo*/)
188 return E_NOTIMPL;
191 STDMETHODIMP InterfaceOleWrapper_Impl::GetIDsOfNames(REFIID /*riid*/,
192 OLECHAR ** rgszNames,
193 unsigned int cNames,
194 LCID /*lcid*/,
195 DISPID * rgdispid )
197 HRESULT ret = DISP_E_UNKNOWNNAME;
200 MutexGuard guard( getBridgeMutex());
201 if( ! rgdispid)
202 return E_POINTER;
204 if( ! _wcsicmp( *rgszNames, JSCRIPT_VALUE_FUNC) ||
205 ! _wcsicmp( *rgszNames, BRIDGE_VALUE_FUNC))
207 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
208 return S_OK;
210 else if( ! _wcsicmp( *rgszNames, GET_STRUCT_FUNC) ||
211 ! _wcsicmp( *rgszNames, BRIDGE_GET_STRUCT_FUNC))
213 *rgdispid= DISPID_GET_STRUCT_FUNC;
214 return S_OK;
216 else if( ! _wcsicmp( *rgszNames, BRIDGE_CREATE_TYPE_FUNC))
218 *rgdispid= DISPID_CREATE_TYPE_FUNC;
219 return S_OK;
222 if (m_xInvocation.is() && (cNames > 0))
224 OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0]));
225 NameToIdMap::iterator iter = m_nameToDispIdMap.find(name);
227 if (iter == m_nameToDispIdMap.end())
229 OUString exactName;
231 if (m_xExactName.is())
233 exactName = m_xExactName->getExactName(name);
235 else
237 exactName = name;
240 MemberInfo d(0, exactName);
242 if (m_xInvocation->hasProperty(exactName))
244 d.flags |= DISPATCH_PROPERTYGET;
245 d.flags |= DISPATCH_PROPERTYPUT;
246 d.flags |= DISPATCH_PROPERTYPUTREF;
249 if (m_xInvocation->hasMethod(exactName))
251 d.flags |= DISPATCH_METHOD;
254 if (d.flags != 0)
256 m_MemberInfos.push_back(d);
257 iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(exactName, (DISPID)m_MemberInfos.size())).first;
259 if (exactName != name)
261 iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(name, (DISPID)m_MemberInfos.size())).first;
266 if (iter == m_nameToDispIdMap.end())
268 ret = DISP_E_UNKNOWNNAME;
270 else
272 *rgdispid = (*iter).second;
273 ret = S_OK;
277 catch(const BridgeRuntimeError&)
279 OSL_ASSERT(0);
281 catch(const Exception&)
283 OSL_ASSERT(0);
285 catch(...)
287 OSL_ASSERT(0);
290 return ret;
293 // "convertDispparamsArgs" converts VARIANTS to their respecting Any counterparts
294 // The parameters "id", "wFlags" and "pdispparams" equal those as used in
295 // IDispatch::Invoke. The function handles special JavaScript
296 // cases where a VARIANT of type VT_DISPATCH is ambiguous and could represent
297 // an object, array ( JavaScript Array object), out parameter and in/out ( JavaScript Array object)
298 // parameter (JavaScript Array object)
299 // Because all those VT_DISPATCH objects need a different conversion
300 // we have to find out what the object is supposed to be. The function does this
301 // by either using type information or by help of a specialized ValueObject object.
303 // A. Type Information
305 // With the help of type information the kind of parameter can be exactly determined
306 // and an appropriate conversion can be chosen. A problem arises if a method expects
307 // an Any. Then the type info does not tell what the type of the value, that is kept
308 // by the any, should be. In this situation the decision whether the param is a
309 // sequence or an object is made upon the fact if the object has a property "0"
310 // ( see function "isJScriptArray"). Since this is unsafe it is recommended to use
311 // the JScript value objects within a JScript script on such an occasion.
313 // B. JavaScript Value Object ( class JScriptValue )
315 // A JScriptValue (ValueObject) object is a COM object in that it implements IDispatch and the
316 // IJScriptValue object interface. Such objects are provided by all UNO wrapper
317 // objects used within a JScript script. To obtain an instance one has to call
318 // "_GetValueObject() or Bridge_GetValueObject()" on an UNO wrapper object (class InterfaceOleWrapper_Impl).
319 // A value object is appropriately initialized within the script and passed as
320 // parameter to an UNO object method or property. The convertDispparamsArgs function
321 // can easily find out that a param is such an object by querying for the
322 // IJScriptValue interface. By this interface one the type and kind ( out, in/out)
323 // can be determined and the right conversion can be applied.
324 // Using ValueObjects we spare us the effort of acquiring and examining type information
325 // in order to figure out what the an IDispatch parameter is meant for.
327 // Normal JScript object parameter can be mixed with JScriptValue object. If an
328 // VARIANT contains an VT_DISPATCH that is no JScriptValue than the type information
329 // is used to find out about the required type.
330 void InterfaceOleWrapper_Impl::convertDispparamsArgs(DISPID id,
331 unsigned short /*wFlags*/, DISPPARAMS* pdispparams, Sequence<Any>& rSeq)
333 HRESULT hr= S_OK;
334 sal_Int32 countArgs= pdispparams->cArgs;
335 if( countArgs == 0)
336 return;
338 rSeq.realloc( countArgs);
339 Any* pParams = rSeq.getArray();
341 Any anyParam;
343 //Get type information for the current call
344 InvocationInfo info;
345 if( ! getInvocationInfoForCall( id, info))
346 throw BridgeRuntimeError(
347 "[automation bridge]InterfaceOleWrapper_Impl::convertDispparamsArgs \n"
348 "Could not obtain type information for current call.");
350 for (int i = 0; i < countArgs; i++)
352 if (info.eMemberType == MemberType_METHOD &&
353 info.aParamModes[ countArgs - i -1 ] == ParamMode_OUT)
354 continue;
356 if(convertValueObject( & pdispparams->rgvarg[i], anyParam))
357 { //a param is a ValueObject and could be converted
358 pParams[countArgs - (i + 1)] = anyParam;
359 continue;
362 // If the param is an out, in/out parameter in
363 // JScript (Array object, with value at index 0) then we
364 // extract Array[0] and put the value into varParam. At the end of the loop varParam
365 // is converted if it contains a value otherwise the VARIANT from
366 // DISPPARAMS is converted.
367 CComVariant varParam;
369 // Check for JScript out and in/out paramsobjects (VT_DISPATCH).
370 // To find them out we use typeinformation of the function being called.
371 if( pdispparams->rgvarg[i].vt == VT_DISPATCH )
373 if( info.eMemberType == MemberType_METHOD && info.aParamModes[ countArgs - i -1 ] == ParamMode_INOUT)
375 // INOUT-param
376 // Index ( property) "0" contains the actual IN-param. The object is a JScript
377 // Array object.
378 // Get the IN-param at index "0"
379 IDispatch* pdisp= pdispparams->rgvarg[i].pdispVal;
381 OLECHAR* sindex= L"0";
382 DISPID id;
383 DISPPARAMS noParams= {0,0,0,0};
384 if(SUCCEEDED( hr= pdisp->GetIDsOfNames( IID_NULL, &sindex, 1, LOCALE_USER_DEFAULT, &id)))
385 hr= pdisp->Invoke( id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
386 & noParams, & varParam, NULL, NULL);
387 if( FAILED( hr))
389 throw BridgeRuntimeError(
390 "[automation bridge] Could not determine "
391 "if the object has a member \"0\". Error: " +
392 OUString::number(hr));
397 if( varParam.vt == VT_EMPTY) // then it was no in/out parameter
398 varParam= pdispparams->rgvarg[i];
400 if(info.eMemberType == MemberType_METHOD)
401 variantToAny( & varParam, anyParam,
402 info.aParamTypes[ countArgs - i - 1]);
403 else if(info.eMemberType == MemberType_PROPERTY)
404 variantToAny( & varParam, anyParam, info.aType);
405 else
406 OSL_ASSERT(0);
408 pParams[countArgs - (i + 1)]= anyParam;
409 }// end for / iterating over all parameters
412 sal_Bool InterfaceOleWrapper_Impl::getInvocationInfoForCall( DISPID id, InvocationInfo& info)
414 sal_Bool bTypesAvailable= sal_False;
416 if( !m_xInvocation.is() )return false;
417 Reference<XInvocation2> inv2( m_xInvocation, UNO_QUERY);
418 if( inv2.is())
420 // We need the name of the property or method to get its type information.
421 // The name can be identified through the param "id"
422 // that is kept as value in the map m_nameToDispIdMap.
423 // Proplem: the Windows JScript engine sometimes changes small letters to capital
424 // letters as happens in xidlclass_obj.createObject( var) // in JScript.
425 // IDispatch::GetIdsOfNames is then called with "CreateObject" !!!
426 // m_nameToDispIdMap can contain several names for one DISPID but only one is
427 // the exact one. If there's no m_xExactName and therefore no exact name then
428 // there's only one entry in the map.
429 typedef NameToIdMap::const_iterator cit;
430 OUString sMemberName;
432 for(cit ci1= m_nameToDispIdMap.begin(); ci1 != m_nameToDispIdMap.end(); ++ci1)
434 if( (*ci1).second == id) // iterator is a pair< OUString, DISPID>
436 sMemberName= (*ci1).first;
437 break;
440 // Get information for the current call ( property or method).
441 // There could be similar names which only differ in the cases
442 // of letters. First we assume that the name which was passed into
443 // GetIDsOfNames is correct. If we won't get information with that
444 // name then we have the invocation service use the XExactName interface.
445 sal_Bool validInfo= sal_True;
446 InvocationInfo invInfo;
447 try{
448 invInfo= inv2->getInfoForName( sMemberName, sal_False);
450 catch(const IllegalArgumentException&)
452 validInfo= sal_False;
455 if( ! validInfo)
457 invInfo= inv2->getInfoForName( sMemberName, sal_True);
459 if( invInfo.aName.pData)
461 bTypesAvailable= sal_True;
462 info= invInfo;
465 return bTypesAvailable;
468 // XBridgeSupplier2 ---------------------------------------------------
469 // only bridges itself ( this instance of InterfaceOleWrapper_Impl)from UNO to IDispatch
470 // If sourceModelType is UNO than any UNO interface implemented by InterfaceOleWrapper_Impl
471 // can bridged to IDispatch ( if destModelType == OLE). The IDispatch is
472 // implemented by this class.
473 Any SAL_CALL InterfaceOleWrapper_Impl::createBridge(const Any& modelDepObject,
474 const Sequence<sal_Int8>& /*ProcessId*/,
475 sal_Int16 sourceModelType,
476 sal_Int16 destModelType)
477 throw (IllegalArgumentException, RuntimeException)
480 Any retAny;
481 if( sourceModelType == UNO && destModelType == OLE &&
482 modelDepObject.getValueTypeClass() == TypeClass_INTERFACE )
484 Reference<XInterface> xInt;
485 if( modelDepObject >>= xInt )
487 if( xInt == Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY))
489 VARIANT *pVar= (VARIANT*)CoTaskMemAlloc( sizeof( VARIANT));
490 if( pVar)
492 pVar->vt= VT_DISPATCH;
493 pVar->pdispVal= static_cast<IDispatch*>( this);
494 AddRef();
496 retAny<<= reinterpret_cast< sal_uInt32 >( pVar);
502 return retAny;
505 // XInitialization --------------------------------------------------
506 void SAL_CALL InterfaceOleWrapper_Impl::initialize( const Sequence< Any >& aArguments )
507 throw(Exception, RuntimeException)
509 switch( aArguments.getLength() )
511 case 2: // the object wraps an UNO struct
512 aArguments[0] >>= m_xInvocation;
513 aArguments[1] >>= m_defaultValueType;
514 break;
515 case 3: // the object wraps an UNO interface
516 aArguments[0] >>= m_xInvocation;
517 aArguments[1] >>= m_xOrigin;
518 aArguments[2] >>= m_defaultValueType;
519 break;
522 m_xExactName= Reference<XExactName>( m_xInvocation, UNO_QUERY);
525 Reference< XInterface > InterfaceOleWrapper_Impl::createUnoWrapperInstance()
527 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl(
528 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
529 return Reference<XInterface>( xWeak, UNO_QUERY);
532 Reference<XInterface> InterfaceOleWrapper_Impl::createComWrapperInstance()
534 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl(
535 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
536 return Reference<XInterface>( xWeak, UNO_QUERY);
539 // "getType" is used in convertValueObject to map the string denoting the type
540 // to an actual Type object.
541 bool getType( const BSTR name, Type & type)
543 Type retType;
544 bool ret = false;
545 typelib_TypeDescription * pDesc= NULL;
546 OUString str( reinterpret_cast<const sal_Unicode*>(name));
547 typelib_typedescription_getByName( &pDesc, str.pData );
548 if( pDesc)
550 type = Type( pDesc->pWeakRef );
551 typelib_typedescription_release( pDesc);
552 ret = true;
554 return ret;
557 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource)
559 sal_Bool ret = sal_False;
560 HRESULT hr;
562 // Handle JScriptValue objects and JScript out params ( Array object )
563 CComVariant varDest( *pDest);
565 if( SUCCEEDED( varDest.ChangeType(VT_DISPATCH)))
567 CComPtr<IDispatch> spDispDest(varDest.pdispVal);
569 // special Handling for a JScriptValue object
570 #ifdef __MINGW32__
571 CComQIPtr<IJScriptValueObject, &__uuidof(IJScriptValueObject)> spValueDest(spDispDest);
572 #else
573 CComQIPtr<IJScriptValueObject> spValueDest(spDispDest);
574 #endif
575 if (spValueDest)
577 VARIANT_BOOL varBool= VARIANT_FALSE;
578 if( SUCCEEDED( hr= spValueDest->IsOutParam( &varBool) )
579 && varBool == VARIANT_TRUE ||
580 SUCCEEDED(hr= spValueDest->IsInOutParam( &varBool) )
581 && varBool == VARIANT_TRUE )
583 if( SUCCEEDED( spValueDest->Set( CComVariant(), *pSource)))
584 ret= sal_True;
587 else if (pDest->vt == VT_DISPATCH)// VT_DISPATCH -> JScript out param
589 // We use IDispatchEx because its GetDispID function causes the creation
590 // of a property if it does not exist already. This is convenient for
591 // out parameters in JScript. Then the user must not specify propery "0"
592 // explicitly
593 #ifdef __MINGW32__
594 CComQIPtr<IDispatchEx, &__uuidof(IDispatchEx)> spDispEx( spDispDest);
595 #else
596 CComQIPtr<IDispatchEx> spDispEx( spDispDest);
597 #endif
598 if( spDispEx)
600 CComBSTR nullProp(L"0");
601 DISPID dwDispID;
602 if( SUCCEEDED( spDispEx->GetDispID( nullProp, fdexNameEnsure, &dwDispID)))
604 DISPPARAMS dispparams = {NULL, NULL, 1, 1};
605 dispparams.rgvarg = pSource;
606 DISPID dispidPut = DISPID_PROPERTYPUT;
607 dispparams.rgdispidNamedArgs = &dispidPut;
609 if (pSource->vt == VT_UNKNOWN || pSource->vt == VT_DISPATCH ||
610 (pSource->vt & VT_ARRAY) || (pSource->vt & VT_BYREF))
611 hr = spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
612 &dispparams, NULL, NULL, NULL);
613 else
614 hr= spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
615 &dispparams, NULL, NULL, NULL);
616 if( SUCCEEDED(hr))
617 ret= sal_True;
621 else
622 ret= writeBackOutParameter( pDest, pSource);
624 else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript
625 { // param. The function checks itself for correct VBScript params
626 ret= writeBackOutParameter( pDest, pSource);
628 return ret;
631 // VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter.
632 // Thus we are in charge of freeing an eventual value contained by the inner VARIANT
633 // Please note: VariantCopy doesn't free a VT_BYREF value
634 // The out parameters are expected to have always a valid type
635 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource)
637 HRESULT hr;
638 sal_Bool ret = FALSE;
639 // Out parameter must be VT_BYREF
640 if ((V_VT(pDest) & VT_BYREF) != 0 )
642 VARTYPE oleTypeFlags = V_VT(pSource);
644 // if caller accept VARIANT as out parameter, any value must be converted
645 if (V_VT(pDest) == (VT_VARIANT | VT_BYREF))
647 // When the user provides a VARIANT rather then a concrete type
648 // we just copy the source to the out, in/out parameter
649 // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that
650 // is contained in pDest are released by VariantCopy
651 VariantCopy(V_VARIANTREF(pDest), pSource);
652 ret = sal_True;
654 else
656 // variantarg and variant must have same type
657 if ((V_VT(pDest) & oleTypeFlags) == oleTypeFlags)
659 if ((oleTypeFlags & VT_ARRAY) != 0)
661 // In / Out Param
662 if( *V_ARRAYREF(pDest) != NULL)
663 hr= SafeArrayCopyData( V_ARRAY(pSource), *V_ARRAYREF(pDest));
664 else
665 // Out Param
666 hr= SafeArrayCopy(V_ARRAY(pSource), V_ARRAYREF(pDest)) == NOERROR;
667 if( SUCCEEDED( hr))
668 ret = sal_True;
670 else
672 // copy base type
673 switch (V_VT(pSource))
675 case VT_I2:
677 *V_I2REF(pDest) = V_I2(pSource);
678 ret = sal_True;
679 break;
681 case VT_I4:
682 *V_I4REF(pDest) = V_I4(pSource);
683 ret = sal_True;
684 break;
685 case VT_R4:
686 *V_R4REF(pDest) = V_R4(pSource);
687 ret = sal_True;
688 break;
689 case VT_R8:
690 *V_R8REF(pDest) = V_R8(pSource);
691 ret = sal_True;
692 break;
693 case VT_CY:
694 *V_CYREF(pDest) = V_CY(pSource);
695 ret = sal_True;
696 break;
697 case VT_DATE:
698 *V_DATEREF(pDest) = V_DATE(pSource);
699 ret = sal_True;
700 break;
701 case VT_BSTR:
702 SysFreeString( *pDest->pbstrVal);
704 *V_BSTRREF(pDest) = SysAllocString(V_BSTR(pSource));
705 ret = sal_True;
706 break;
707 case VT_DISPATCH:
708 if (*V_DISPATCHREF(pDest) != NULL)
709 (*V_DISPATCHREF(pDest))->Release();
711 *V_DISPATCHREF(pDest) = V_DISPATCH(pSource);
713 if (*V_DISPATCHREF(pDest) != NULL)
714 (*V_DISPATCHREF(pDest))->AddRef();
716 ret = sal_True;
717 break;
718 case VT_ERROR:
719 *V_ERRORREF(pDest) = V_ERROR(pSource);
720 ret = sal_True;
721 break;
722 case VT_BOOL:
723 *V_BOOLREF(pDest) = V_BOOL(pSource);
724 ret = sal_True;
725 break;
726 case VT_UNKNOWN:
727 if (*V_UNKNOWNREF(pDest) != NULL)
728 (*V_UNKNOWNREF(pDest))->Release();
730 *V_UNKNOWNREF(pDest) = V_UNKNOWN(pSource);
732 if (*V_UNKNOWNREF(pDest) != NULL)
733 (*V_UNKNOWNREF(pDest))->AddRef();
735 ret = sal_True;
736 break;
737 case VT_I1:
738 *V_I1REF(pDest) = V_I1(pSource);
739 ret = sal_True;
740 break;
741 case VT_UI1:
742 *V_UI1REF(pDest) = V_UI1(pSource);
743 ret = sal_True;
744 break;
745 case VT_UI2:
746 *V_UI2REF(pDest) = V_UI2(pSource);
747 ret = sal_True;
748 break;
749 case VT_UI4:
750 *V_UI4REF(pDest) = V_UI4(pSource);
751 ret = sal_True;
752 break;
753 case VT_INT:
754 *V_INTREF(pDest) = V_INT(pSource);
755 ret = sal_True;
756 break;
757 case VT_UINT:
758 *V_UINTREF(pDest) = V_UINT(pSource);
759 ret = sal_True;
760 break;
761 case VT_DECIMAL:
762 memcpy(pDest->pdecVal, pSource, sizeof(DECIMAL));
763 ret = sal_True;
764 break;
765 default:
766 break;
770 else
772 // Handling of special cases
773 // Destination and source types are different
774 if( pDest->vt == (VT_BSTR | VT_BYREF)
775 && pSource->vt == VT_I2)
777 // When the user provides a String as out our in/out parameter
778 // and the type is char (TypeClass_CHAR) then we convert to a BSTR
779 // instead of VT_I2 as is done otherwise
780 OLECHAR buff[]= {0,0};
781 buff[0]= pSource->iVal;
783 SysFreeString( *pDest->pbstrVal);
784 *pDest->pbstrVal= SysAllocString( buff);
785 ret = sal_True;
790 return ret;
793 STDMETHODIMP InterfaceOleWrapper_Impl::Invoke(DISPID dispidMember,
794 REFIID /*riid*/,
795 LCID /*lcid*/,
796 unsigned short wFlags,
797 DISPPARAMS * pdispparams,
798 VARIANT * pvarResult,
799 EXCEPINFO * pexcepinfo,
800 unsigned int * puArgErr )
802 HRESULT ret = S_OK;
806 sal_Bool bHandled= sal_False;
807 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo,
808 puArgErr, bHandled);
809 if( bHandled)
810 return ret;
812 if ((dispidMember > 0) && ((size_t)dispidMember <= m_MemberInfos.size()) && m_xInvocation.is())
814 MemberInfo d = m_MemberInfos[dispidMember - 1];
815 DWORD flags = wFlags & d.flags;
817 if (flags != 0)
819 if ((flags & DISPATCH_METHOD) != 0)
821 if (pdispparams->cNamedArgs > 0)
822 ret = DISP_E_NONAMEDARGS;
823 else
825 Sequence<Any> params;
827 convertDispparamsArgs(dispidMember, wFlags, pdispparams , params );
829 ret= doInvoke(pdispparams, pvarResult,
830 pexcepinfo, puArgErr, d.name, params);
833 else if ((flags & DISPATCH_PROPERTYGET) != 0)
835 ret= doGetProperty( pdispparams, pvarResult,
836 pexcepinfo, d.name);
838 else if ((flags & DISPATCH_PROPERTYPUT || flags & DISPATCH_PROPERTYPUTREF) != 0)
840 if (pdispparams->cArgs != 1)
841 ret = DISP_E_BADPARAMCOUNT;
842 else
844 Sequence<Any> params;
845 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
846 if(params.getLength() > 0)
847 ret= doSetProperty( pdispparams, pvarResult, pexcepinfo, puArgErr, d.name, params);
848 else
849 ret = DISP_E_BADVARTYPE;
853 else
854 ret= DISP_E_MEMBERNOTFOUND;
856 else
857 ret = DISP_E_MEMBERNOTFOUND;
859 catch(const BridgeRuntimeError& e)
861 writeExcepinfo(pexcepinfo, e.message);
862 ret = DISP_E_EXCEPTION;
864 catch(const Exception& e)
866 OUString message= "InterfaceOleWrapper_Impl::Invoke : \n" +
867 e.Message;
868 writeExcepinfo(pexcepinfo, message);
869 ret = DISP_E_EXCEPTION;
871 catch(...)
873 OUString message= "InterfaceOleWrapper_Impl::Invoke : \n"
874 "Unexpected exception";
875 writeExcepinfo(pexcepinfo, message);
876 ret = DISP_E_EXCEPTION;
879 return ret;
882 HRESULT InterfaceOleWrapper_Impl::doInvoke( DISPPARAMS * pdispparams, VARIANT * pvarResult,
883 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any>& params)
887 HRESULT ret= S_OK;
890 Sequence<sal_Int16> outIndex;
891 Sequence<Any> outParams;
892 Any returnValue;
894 if (pdispparams->cNamedArgs > 0)
895 return DISP_E_NONAMEDARGS;
897 // invoke method and take care of exceptions
898 returnValue = m_xInvocation->invoke(name,
899 params,
900 outIndex,
901 outParams);
903 // try to write back out parameter
904 if (outIndex.getLength() > 0)
906 const sal_Int16* pOutIndex = outIndex.getConstArray();
907 const Any* pOutParams = outParams.getConstArray();
909 for (sal_Int32 i = 0; i < outIndex.getLength(); i++)
911 CComVariant variant;
912 // Currently a Sequence is converted to an SafeArray of VARIANTs.
913 anyToVariant( &variant, pOutParams[i]);
915 // out parameter need special handling if they are VT_DISPATCH
916 // and used in JScript
917 int outindex= pOutIndex[i];
918 writeBackOutParameter2(&(pdispparams->rgvarg[pdispparams->cArgs - 1 - outindex]),
919 &variant );
923 // write back return value
924 if (pvarResult != NULL)
925 anyToVariant(pvarResult, returnValue);
927 catch(const IllegalArgumentException & e) //XInvocation::invoke
929 writeExcepinfo(pexcepinfo, e.Message);
930 ret = DISP_E_TYPEMISMATCH;
932 catch(const CannotConvertException & e) //XInvocation::invoke
934 writeExcepinfo(pexcepinfo, e.Message);
935 ret = mapCannotConvertException( e, puArgErr);
937 catch(const InvocationTargetException & e) //XInvocation::invoke
939 const Any& org = e.TargetException;
940 Exception excTarget;
941 org >>= excTarget;
942 OUString message=
943 org.getValueType().getTypeName() + ": " + excTarget.Message;
944 writeExcepinfo(pexcepinfo, message);
945 ret = DISP_E_EXCEPTION;
947 catch(const NoSuchMethodException & e) //XInvocation::invoke
949 writeExcepinfo(pexcepinfo, e.Message);
950 ret = DISP_E_MEMBERNOTFOUND;
952 catch(const BridgeRuntimeError & e)
954 writeExcepinfo(pexcepinfo, e.message);
955 ret = DISP_E_EXCEPTION;
957 catch(const Exception & e)
959 OUString message= "InterfaceOleWrapper_Impl::doInvoke : \n" +
960 e.Message;
961 writeExcepinfo(pexcepinfo, message);
962 ret = DISP_E_EXCEPTION;
964 catch( ... )
966 OUString message= "InterfaceOleWrapper_Impl::doInvoke : \n"
967 "Unexpected exception";
968 writeExcepinfo(pexcepinfo, message);
969 ret = DISP_E_EXCEPTION;
971 return ret;
974 HRESULT InterfaceOleWrapper_Impl::doGetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * pvarResult,
975 EXCEPINFO * pexcepinfo, OUString& name)
977 HRESULT ret= S_OK;
979 Any value;
982 Any returnValue = m_xInvocation->getValue( name);
983 // write back return value
984 if (pvarResult)
985 anyToVariant(pvarResult, returnValue);
987 catch(const UnknownPropertyException& e) //XInvocation::getValue
989 writeExcepinfo(pexcepinfo, e.Message);
990 ret = DISP_E_MEMBERNOTFOUND;
992 catch(const BridgeRuntimeError& e)
994 writeExcepinfo(pexcepinfo, e.message);
995 ret = DISP_E_EXCEPTION;
997 catch(const Exception& e)
999 OUString message= "InterfaceOleWrapper_Impl::doGetProperty : \n" +
1000 e.Message;
1001 writeExcepinfo(pexcepinfo, message);
1003 catch( ... )
1005 OUString message= "InterfaceOleWrapper_Impl::doInvoke : \n"
1006 "Unexpected exception";
1007 writeExcepinfo(pexcepinfo, message);
1008 ret = DISP_E_EXCEPTION;
1010 return ret;
1013 HRESULT InterfaceOleWrapper_Impl::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1014 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any> params)
1016 HRESULT ret= S_OK;
1020 m_xInvocation->setValue( name, params.getConstArray()[0]);
1022 catch(const UnknownPropertyException &)
1024 ret = DISP_E_MEMBERNOTFOUND;
1026 catch(const CannotConvertException &e)
1028 ret= mapCannotConvertException( e, puArgErr);
1030 catch(const InvocationTargetException &e)
1032 if (pexcepinfo != NULL)
1034 Any org = e.TargetException;
1036 pexcepinfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
1037 pexcepinfo->bstrSource = SysAllocString(L"any ONE component");
1038 pexcepinfo->bstrDescription = SysAllocString(
1039 reinterpret_cast<LPCOLESTR>(org.getValueType().getTypeName().getStr()));
1041 ret = DISP_E_EXCEPTION;
1043 catch( ... )
1045 ret= DISP_E_EXCEPTION;
1047 return ret;
1050 HRESULT InterfaceOleWrapper_Impl::InvokeGeneral( DISPID dispidMember, unsigned short wFlags,
1051 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1052 unsigned int * /*puArgErr*/, sal_Bool& bHandled)
1054 HRESULT ret= S_OK;
1057 // DISPID_VALUE | The DEFAULT Value is required in JScript when the situation
1058 // is that we put an object into an Array object ( out parameter). We have to return
1059 // IDispatch otherwise the object cannot be accessed from the Script.
1060 if( dispidMember == DISPID_VALUE && wFlags == DISPATCH_PROPERTYGET
1061 && m_defaultValueType != VT_EMPTY && pvarResult != NULL)
1063 bHandled= sal_True;
1064 if( m_defaultValueType == VT_DISPATCH)
1066 pvarResult->vt= VT_DISPATCH;
1067 pvarResult->pdispVal= static_cast<IDispatch*>( this);
1068 AddRef();
1069 ret= S_OK;
1073 // function: _GetValueObject
1074 else if( dispidMember == DISPID_JSCRIPT_VALUE_FUNC)
1076 bHandled= sal_True;
1077 if( !pvarResult)
1078 ret= E_POINTER;
1079 CComObject< JScriptValue>* pValue;
1080 if( SUCCEEDED( CComObject<JScriptValue>::CreateInstance( &pValue)))
1082 pValue->AddRef();
1083 pvarResult->vt= VT_DISPATCH;
1084 #ifdef __MINGW32__
1085 pvarResult->pdispVal= CComQIPtr<IDispatch, &__uuidof(IDispatch)>(pValue->GetUnknown());
1086 #else
1087 pvarResult->pdispVal= CComQIPtr<IDispatch>(pValue->GetUnknown());
1088 #endif
1089 ret= S_OK;
1091 else
1092 ret= DISP_E_EXCEPTION;
1094 else if( dispidMember == DISPID_GET_STRUCT_FUNC)
1096 bHandled= sal_True;
1097 sal_Bool bStruct= sal_False;
1100 Reference<XIdlReflection> xRefl = theCoreReflection::get(comphelper::getComponentContext(m_smgr));
1101 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1102 CComVariant arg;
1103 if( pdispparams->cArgs == 1 && SUCCEEDED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])) )
1105 Reference<XIdlClass> classStruct= xRefl->forName( reinterpret_cast<const sal_Unicode*>(arg.bstrVal));
1106 if( classStruct.is())
1108 Any anyStruct;
1109 classStruct->createObject( anyStruct);
1110 CComVariant var;
1111 anyToVariant( &var, anyStruct );
1113 if( var.vt == VT_DISPATCH)
1115 VariantCopy( pvarResult, & var);
1116 bStruct= sal_True;
1120 ret= bStruct == sal_True ? S_OK : DISP_E_EXCEPTION;
1122 else if (dispidMember == DISPID_CREATE_TYPE_FUNC)
1124 bHandled= sal_True;
1125 if( !pvarResult)
1126 ret= E_POINTER;
1127 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1128 CComVariant arg;
1129 if( pdispparams->cArgs != 1)
1130 return DISP_E_BADPARAMCOUNT;
1131 if (FAILED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])))
1132 return DISP_E_BADVARTYPE;
1134 //check if the provided name represents a valid type
1135 Type type;
1136 if (getType(arg.bstrVal, type) == false)
1138 writeExcepinfo(pexcepinfo,OUString(
1139 "[automation bridge] A UNO type with the name " +
1140 OUString(reinterpret_cast<const sal_Unicode*>(arg.bstrVal)) + " does not exist!"));
1141 return DISP_E_EXCEPTION;
1144 if (createUnoTypeWrapper(arg.bstrVal, pvarResult) == false)
1146 writeExcepinfo(pexcepinfo, "[automation bridge] InterfaceOleWrapper_Impl::InvokeGeneral\n"
1147 "Could not initialize UnoTypeWrapper object!");
1148 return DISP_E_EXCEPTION;
1152 catch(const BridgeRuntimeError & e)
1154 writeExcepinfo(pexcepinfo, e.message);
1155 ret = DISP_E_EXCEPTION;
1157 catch(const Exception & e)
1159 OUString message= "InterfaceOleWrapper_Impl::InvokeGeneral : \n" +
1160 e.Message;
1161 writeExcepinfo(pexcepinfo, message);
1162 ret = DISP_E_EXCEPTION;
1164 catch( ... )
1166 OUString message= "InterfaceOleWrapper_Impl::InvokeGeneral : \n"
1167 "Unexpected exception";
1168 writeExcepinfo(pexcepinfo, message);
1169 ret = DISP_E_EXCEPTION;
1171 return ret;
1174 STDMETHODIMP InterfaceOleWrapper_Impl::GetDispID(BSTR /*bstrName*/, DWORD /*grfdex*/, DISPID __RPC_FAR* /*pid*/)
1176 HRESULT ret = ResultFromScode(E_NOTIMPL);
1178 return ret;
1181 STDMETHODIMP InterfaceOleWrapper_Impl::InvokeEx(
1182 /* [in] */ DISPID /*id*/,
1183 /* [in] */ LCID /*lcid*/,
1184 /* [in] */ WORD /*wFlags*/,
1185 /* [in] */ DISPPARAMS __RPC_FAR* /*pdp*/,
1186 /* [out] */ VARIANT __RPC_FAR* /*pvarRes*/,
1187 /* [out] */ EXCEPINFO __RPC_FAR* /*pei*/,
1188 /* [unique][in] */ IServiceProvider __RPC_FAR* /*pspCaller*/)
1190 HRESULT ret = ResultFromScode(E_NOTIMPL);
1192 return ret;
1195 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByName(
1196 /* [in] */ BSTR /*bstr*/,
1197 /* [in] */ DWORD /*grfdex*/)
1199 HRESULT ret = ResultFromScode(E_NOTIMPL);
1201 return ret;
1204 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByDispID(DISPID /*id*/)
1206 HRESULT ret = ResultFromScode(E_NOTIMPL);
1208 return ret;
1211 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberProperties(
1212 /* [in] */ DISPID /*id*/,
1213 /* [in] */ DWORD /*grfdexFetch*/,
1214 /* [out] */ DWORD __RPC_FAR* /*pgrfdex*/)
1216 HRESULT ret = ResultFromScode(E_NOTIMPL);
1218 return ret;
1221 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberName(
1222 /* [in] */ DISPID /*id*/,
1223 /* [out] */ BSTR __RPC_FAR* /*pbstrName*/)
1225 HRESULT ret = ResultFromScode(E_NOTIMPL);
1227 return ret;
1230 STDMETHODIMP InterfaceOleWrapper_Impl::GetNextDispID(
1231 /* [in] */ DWORD /*grfdex*/,
1232 /* [in] */ DISPID /*id*/,
1233 /* [out] */ DISPID __RPC_FAR* /*pid*/)
1235 HRESULT ret = ResultFromScode(E_NOTIMPL);
1237 return ret;
1240 STDMETHODIMP InterfaceOleWrapper_Impl::GetNameSpaceParent(
1241 /* [out] */ IUnknown __RPC_FAR *__RPC_FAR* /*ppunk*/)
1243 HRESULT ret = ResultFromScode(E_NOTIMPL);
1245 return ret;
1248 // UnoObjectWrapperRemoteOpt ---------------------------------------------------
1250 UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference<XMultiServiceFactory>& aFactory,
1251 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
1252 InterfaceOleWrapper_Impl( aFactory, unoWrapperClass, comWrapperClass),
1253 m_currentId(1)
1257 UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt()
1261 // UnoConversionUtilities
1262 Reference< XInterface > UnoObjectWrapperRemoteOpt::createUnoWrapperInstance()
1264 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
1265 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1266 return Reference<XInterface>( xWeak, UNO_QUERY);
1269 STDMETHODIMP UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID /*riid*/, OLECHAR ** rgszNames, unsigned int cNames,
1270 LCID /*lcid*/, DISPID * rgdispid )
1272 MutexGuard guard( getBridgeMutex());
1274 if( ! rgdispid)
1275 return E_POINTER;
1276 HRESULT ret = E_UNEXPECTED;
1278 // _GetValueObject
1279 if( ! wcscmp( *rgszNames, JSCRIPT_VALUE_FUNC))
1281 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
1282 return S_OK;
1284 else if( ! wcscmp( *rgszNames, GET_STRUCT_FUNC))
1286 *rgdispid= DISPID_GET_STRUCT_FUNC;
1287 return S_OK;
1290 if (m_xInvocation.is() && (cNames > 0))
1292 OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0]));
1293 // has this name been determined as "bad"
1294 BadNameMap::iterator badIter= m_badNameMap.find( name);
1295 if( badIter == m_badNameMap.end() )
1297 // name has not been bad before( member exists
1298 typedef NameToIdMap::iterator ITnames;
1299 pair< ITnames, bool > pair_id= m_nameToDispIdMap.insert( NameToIdMap::value_type(name, m_currentId++));
1300 // new ID inserted ?
1301 if( pair_id.second )
1302 {// yes, now create MemberInfo and ad to IdToMemberInfoMap
1303 MemberInfo d(0, name);
1304 m_idToMemberInfoMap.insert( IdToMemberInfoMap::value_type( m_currentId - 1, d));
1307 *rgdispid = pair_id.first->second;
1308 ret = S_OK;
1310 else
1311 ret= DISP_E_UNKNOWNNAME;
1313 return ret;
1316 STDMETHODIMP UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember, REFIID /*riid*/, LCID /*lcid*/, unsigned short wFlags,
1317 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1318 unsigned int * puArgErr )
1320 HRESULT ret = S_OK;
1323 sal_Bool bHandled= sal_False;
1324 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo,
1325 puArgErr, bHandled);
1326 if( bHandled)
1327 return ret;
1329 if ( dispidMember > 0 && m_xInvocation.is())
1332 IdToMemberInfoMap::iterator it_MemberInfo= m_idToMemberInfoMap.find( dispidMember);
1333 if( it_MemberInfo != m_idToMemberInfoMap.end() )
1335 MemberInfo& info= it_MemberInfo->second;
1337 Sequence<Any> params; // holds converted any s
1338 if( ! info.flags )
1339 { // DISPID called for the first time
1340 if( wFlags == DISPATCH_METHOD )
1342 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1344 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1345 pexcepinfo, puArgErr, info.name, params))
1346 && ret == DISP_E_MEMBERNOTFOUND)
1348 // try to get the exact name
1349 OUString exactName;
1350 if (m_xExactName.is())
1352 exactName = m_xExactName->getExactName( info.name);
1353 // invoke again
1354 if( !exactName.isEmpty() )
1356 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1357 pexcepinfo, puArgErr, exactName, params)))
1358 info.name= exactName;
1362 if( SUCCEEDED( ret ) )
1363 info.flags= DISPATCH_METHOD;
1365 else if( wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_PROPERTYPUTREF)
1367 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1368 if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1369 pexcepinfo, puArgErr, info.name, params))
1370 && ret == DISP_E_MEMBERNOTFOUND)
1372 // try to get the exact name
1373 OUString exactName;
1374 if (m_xExactName.is())
1376 exactName = m_xExactName->getExactName( info.name);
1377 // invoke again
1378 if( !exactName.isEmpty() )
1380 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1381 pexcepinfo, puArgErr, exactName, params)))
1382 info.name= exactName;
1386 if( SUCCEEDED( ret ) )
1387 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1389 else if( wFlags == DISPATCH_PROPERTYGET)
1391 if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1392 pexcepinfo, info.name))
1393 && ret == DISP_E_MEMBERNOTFOUND)
1395 // try to get the exact name
1396 OUString exactName;
1397 if (m_xExactName.is())
1399 exactName = m_xExactName->getExactName( info.name);
1400 // invoke again
1401 if( !exactName.isEmpty() )
1403 if( SUCCEEDED( ret= doGetProperty( pdispparams, pvarResult,
1404 pexcepinfo, exactName)))
1405 info.name= exactName;
1409 if( SUCCEEDED( ret ) )
1410 info.flags= DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT;
1412 else if( wFlags & DISPATCH_METHOD &&
1413 (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF))
1416 OUString exactName;
1417 // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT
1418 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1419 // try first as method
1420 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1421 pexcepinfo, puArgErr, info.name, params))
1422 && ret == DISP_E_MEMBERNOTFOUND)
1424 // try to get the exact name
1425 if (m_xExactName.is())
1427 exactName = m_xExactName->getExactName( info.name);
1428 // invoke again
1429 if( !exactName.isEmpty() )
1431 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1432 pexcepinfo, puArgErr, exactName, params)))
1433 info.name= exactName;
1437 if( SUCCEEDED( ret ) )
1438 info.flags= DISPATCH_METHOD;
1440 // try as property
1441 if( FAILED( ret) && pdispparams->cArgs == 1)
1443 if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1444 pexcepinfo, puArgErr, info.name, params))
1445 && ret == DISP_E_MEMBERNOTFOUND)
1447 // try to get the exact name
1448 if( !exactName.isEmpty() )
1450 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1451 pexcepinfo, puArgErr, exactName, params)))
1452 info.name= exactName;
1455 if( SUCCEEDED( ret ) )
1456 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1459 else if( wFlags & DISPATCH_METHOD && wFlags & DISPATCH_PROPERTYGET)
1461 OUString exactName;
1462 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1464 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1465 pexcepinfo, puArgErr, info.name, params))
1466 && ret == DISP_E_MEMBERNOTFOUND)
1468 // try to get the exact name
1469 if (m_xExactName.is())
1471 exactName = m_xExactName->getExactName( info.name);
1472 // invoke again
1473 if( !exactName.isEmpty() )
1475 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1476 pexcepinfo, puArgErr, exactName, params)))
1477 info.name= exactName;
1481 if( SUCCEEDED( ret ) )
1482 info.flags= DISPATCH_METHOD;
1484 // try as property
1485 if( FAILED( ret) && pdispparams->cArgs == 1)
1487 if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1488 pexcepinfo, info.name))
1489 && ret == DISP_E_MEMBERNOTFOUND)
1491 if( !exactName.isEmpty() )
1493 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1494 pexcepinfo, puArgErr, exactName, params)))
1495 info.name= exactName;
1498 if( SUCCEEDED( ret ) )
1499 info.flags= DISPATCH_PROPERTYGET;
1503 // update information about this member
1504 if( ret == DISP_E_MEMBERNOTFOUND)
1506 // Remember the name as not existing
1507 // and remove the MemberInfo
1508 m_badNameMap[info.name]= sal_False;
1509 m_idToMemberInfoMap.erase( it_MemberInfo);
1511 } // if( ! info.flags )
1512 else // IdToMemberInfoMap contains a MemberInfo
1514 if( wFlags & DISPATCH_METHOD && info.flags == DISPATCH_METHOD)
1516 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1517 ret= doInvoke( pdispparams, pvarResult,
1518 pexcepinfo, puArgErr, info.name, params);
1520 else if( (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF ) &&
1521 info.flags & DISPATCH_PROPERTYPUT)
1523 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1524 ret= doSetProperty( pdispparams, pvarResult,
1525 pexcepinfo, puArgErr, info.name, params);
1527 else if( (wFlags & DISPATCH_PROPERTYGET) && ( info.flags & DISPATCH_PROPERTYGET))
1529 ret= doGetProperty( pdispparams, pvarResult,
1530 pexcepinfo, info.name);
1532 else
1534 ret= DISP_E_MEMBERNOTFOUND;
1537 }// if( it_MemberInfo != m_idToMemberInfoMap.end() )
1538 else
1539 ret= DISP_E_MEMBERNOTFOUND;
1542 catch(const BridgeRuntimeError& e)
1544 writeExcepinfo(pexcepinfo, e.message);
1545 ret = DISP_E_EXCEPTION;
1547 catch(const Exception& e)
1549 OUString message= "UnoObjectWrapperRemoteOpt::Invoke : \n" +
1550 e.Message;
1551 writeExcepinfo(pexcepinfo, message);
1552 ret = DISP_E_EXCEPTION;
1554 catch(...)
1556 OUString message= "UnoObjectWrapperRemoteOpt::Invoke : \n"
1557 "Unexpected exception";
1558 writeExcepinfo(pexcepinfo, message);
1559 ret = DISP_E_EXCEPTION;
1562 return ret;
1565 HRESULT UnoObjectWrapperRemoteOpt::methodInvoke( DISPID /*dispidMember*/, DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1566 EXCEPINFO * /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence<Any> params)
1568 return S_OK;
1571 // The returned HRESULT is only appropriate for IDispatch::Invoke
1572 static HRESULT mapCannotConvertException(const CannotConvertException &e, unsigned int * puArgErr)
1574 HRESULT ret;
1575 sal_Bool bWriteIndex= sal_True;
1577 switch ( e.Reason)
1579 case FailReason::OUT_OF_RANGE:
1580 ret = DISP_E_OVERFLOW;
1581 break;
1582 case FailReason::IS_NOT_NUMBER:
1583 ret = DISP_E_TYPEMISMATCH;
1584 break;
1585 case FailReason::IS_NOT_ENUM:
1586 ret = DISP_E_TYPEMISMATCH;
1587 break;
1588 case FailReason::IS_NOT_BOOL:
1589 ret = DISP_E_TYPEMISMATCH;
1590 break;
1591 case FailReason::NO_SUCH_INTERFACE:
1592 ret = DISP_E_TYPEMISMATCH;
1593 break;
1594 case FailReason::SOURCE_IS_NO_DERIVED_TYPE:
1595 ret = DISP_E_TYPEMISMATCH;
1596 break;
1597 case FailReason::TYPE_NOT_SUPPORTED:
1598 ret = DISP_E_TYPEMISMATCH;
1599 break;
1600 case FailReason::INVALID:
1601 ret = DISP_E_TYPEMISMATCH;
1602 break;
1603 case FailReason::NO_DEFAULT_AVAILABLE:
1604 ret = DISP_E_BADPARAMCOUNT;
1605 break;
1606 case FailReason::UNKNOWN:
1607 ret = E_UNEXPECTED;
1608 break;
1609 default:
1610 ret = E_UNEXPECTED;
1611 bWriteIndex= sal_False;
1612 break;
1615 if( bWriteIndex && puArgErr != NULL)
1616 *puArgErr = e.ArgumentIndex;
1617 return ret;
1620 // The function maps the TypeClass of the any to VARTYPE: If
1621 // the Any contains STRUCT or INTERFACE then the return value
1622 // is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper
1623 // and the result is put into the constructor of the uno - wrapper
1624 // object. If a client asks the object for DISPID_VALUE and this
1625 // function returned VT_DISPATCH then the IDispatch of the same
1626 // object is being returned.
1627 // See InterfaceOleWrapper_Impl::Invoke, InterfaceOleWrapper_Impl::m_defaultValueType
1628 const VARTYPE getVarType( const Any& value)
1630 VARTYPE ret= VT_EMPTY;
1632 switch ( value.getValueTypeClass())
1634 case TypeClass_STRUCT: ret= VT_DISPATCH; break;
1635 case TypeClass_INTERFACE: ret= VT_DISPATCH; break;
1636 default: break;
1638 return ret;
1641 } // end namespace
1643 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */