xref: /trunk/main/extensions/source/ole/unoobjw.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_extensions.hxx"
26 
27 #include "ole2uno.hxx"
28 #include <stdio.h>
29 #include <tools/presys.h>
30 #include <olectl.h>
31 #include <vector>
32 #include <list>
33 #include <hash_map>
34 #include "comifaces.hxx"
35 #include <tools/postsys.h>
36 
37 
38 #include <vos/diagnose.hxx>
39 #include <vos/refernce.hxx>
40 #include <tools/debug.hxx>
41 #include <rtl/ustring.hxx>
42 #include <com/sun/star/beans/MethodConcept.hpp>
43 #include <com/sun/star/beans/PropertyConcept.hpp>
44 #include <com/sun/star/script/FailReason.hpp>
45 #include <com/sun/star/reflection/ParamInfo.hpp>
46 #include <com/sun/star/beans/XExactName.hpp>
47 #include <com/sun/star/container/NoSuchElementException.hpp>
48 
49 #include <com/sun/star/beans/XMaterialHolder.hpp>
50 #include <com/sun/star/script/XInvocation2.hpp>
51 #include <com/sun/star/script/MemberType.hpp>
52 #include <com/sun/star/reflection/XIdlReflection.hpp>
53 #include <osl/interlck.h>
54 #include <com/sun/star/uno/genfunc.h>
55 #include <cppuhelper/implbase1.hxx>
56 
57 #include "comifaces.hxx"
58 #include "jscriptclasses.hxx"
59 #include "unotypewrapper.hxx"
60 #include "oleobjw.hxx"
61 #include "unoobjw.hxx"
62 #include "servprov.hxx"
63 
64 using namespace vos;
65 using namespace std;
66 using namespace rtl;
67 using namespace osl;
68 using namespace cppu;
69 using namespace com::sun::star::uno;
70 using namespace com::sun::star::beans;
71 using namespace com::sun::star::container;
72 using namespace com::sun::star::script;
73 using namespace com::sun::star::lang;
74 using namespace com::sun::star::bridge::ModelDependent;
75 using namespace com::sun::star::reflection;
76 
77 
78 
79 #if _MSC_VER < 1200
80 extern "C" const GUID IID_IDispatchEx;
81 #endif
82 
83 namespace ole_adapter
84 {
85 hash_map<sal_uInt32, WeakReference<XInterface> > UnoObjToWrapperMap;
86 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource);
87 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource);
88 static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr);
89 
90 
91 /* Does not throw any exceptions.
92    Param pInfo can be NULL.
93  */
writeExcepinfo(EXCEPINFO * pInfo,const OUString & message)94 static void writeExcepinfo(EXCEPINFO * pInfo, const OUString& message)
95 {
96     if (pInfo != NULL)
97     {
98         pInfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
99         pInfo->bstrSource = SysAllocString(L"[automation bridge] ");
100         pInfo->bstrDescription = SysAllocString(reinterpret_cast<LPCOLESTR>(message.getStr()));
101     }
102 }
103 
104 /*****************************************************************************
105 
106     class implementation: InterfaceOleWrapper_Impl
107 
108 *****************************************************************************/
InterfaceOleWrapper_Impl(Reference<XMultiServiceFactory> & xFactory,sal_uInt8 unoWrapperClass,sal_uInt8 comWrapperClass)109 InterfaceOleWrapper_Impl::InterfaceOleWrapper_Impl( Reference<XMultiServiceFactory>& xFactory,
110                                                     sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
111         m_defaultValueType( 0),
112         UnoConversionUtilities<InterfaceOleWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass)
113 {
114 }
115 
~InterfaceOleWrapper_Impl()116 InterfaceOleWrapper_Impl::~InterfaceOleWrapper_Impl()
117 {
118     MutexGuard guard(getBridgeMutex());
119     // remove entries in global map
120     IT_Uno it= UnoObjToWrapperMap.find( (sal_uInt32) m_xOrigin.get());
121     if(it != UnoObjToWrapperMap.end())
122         UnoObjToWrapperMap.erase(it);
123 #if OSL_DEBUG_LEVEL > 0
124     fprintf(stderr,"[automation bridge] UnoObjToWrapperMap  contains: %i \n",
125             UnoObjToWrapperMap.size());
126 #endif
127 
128 }
129 
QueryInterface(REFIID riid,LPVOID FAR * ppv)130 STDMETHODIMP InterfaceOleWrapper_Impl::QueryInterface(REFIID riid, LPVOID FAR * ppv)
131 {
132     HRESULT ret= S_OK;
133 
134     if( !ppv)
135         return E_POINTER;
136 
137     if(IsEqualIID(riid, IID_IUnknown))
138     {
139         AddRef();
140         *ppv = (IUnknown*) (IDispatch*) this;
141     }
142     else if (IsEqualIID(riid, IID_IDispatch))
143     {
144         AddRef();
145         *ppv = (IDispatch*) this;
146     }
147     else if( IsEqualIID( riid, __uuidof( IUnoObjectWrapper)))
148     {
149         AddRef();
150         *ppv= (IUnoObjectWrapper*) this;
151     }
152     else
153         ret= E_NOINTERFACE;
154     return ret;
155 }
156 
STDMETHODIMP_(ULONG)157 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::AddRef()
158 {
159     acquire();
160     // does not need to guard because one should not rely on the return value of
161     // AddRef anyway
162     return m_refCount;
163 }
164 
STDMETHODIMP_(ULONG)165 STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::Release()
166 {
167     ULONG n= m_refCount;
168     release();
169     return n - 1;
170 }
171 
172 // IUnoObjectWrapper --------------------------------------------------------
getWrapperXInterface(Reference<XInterface> * pXInt)173 STDMETHODIMP InterfaceOleWrapper_Impl::getWrapperXInterface( Reference<XInterface>* pXInt)
174 {
175     *pXInt= Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY);
176     return pXInt->is() ? S_OK : E_FAIL;
177 }
getOriginalUnoObject(Reference<XInterface> * pXInt)178 STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoObject( Reference<XInterface>* pXInt)
179 {
180     *pXInt= m_xOrigin;
181     return m_xOrigin.is() ? S_OK : E_FAIL;
182 }
getOriginalUnoStruct(Any * pStruct)183 STDMETHODIMP  InterfaceOleWrapper_Impl::getOriginalUnoStruct( Any * pStruct)
184 {
185     HRESULT ret= E_FAIL;
186     if( !m_xOrigin.is())
187     {
188         Reference<XMaterialHolder> xMatHolder( m_xInvocation, UNO_QUERY);
189         if( xMatHolder.is())
190         {
191             Any any = xMatHolder->getMaterial();
192             if( any.getValueTypeClass() == TypeClass_STRUCT)
193             {
194                 *pStruct= any;
195                 ret= S_OK;
196             }
197         }
198     }
199     return ret;
200 }
201 
GetTypeInfoCount(unsigned int *)202 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfoCount( unsigned int * /*pctinfo*/ )
203 {
204     return E_NOTIMPL ;
205 }
206 
GetTypeInfo(unsigned int,LCID,ITypeInfo **)207 STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfo(unsigned int /*itinfo*/, LCID /*lcid*/, ITypeInfo ** /*pptinfo*/)
208 {
209     return E_NOTIMPL;
210 }
211 
GetIDsOfNames(REFIID,OLECHAR ** rgszNames,unsigned int cNames,LCID,DISPID * rgdispid)212 STDMETHODIMP InterfaceOleWrapper_Impl::GetIDsOfNames(REFIID /*riid*/,
213                                                      OLECHAR ** rgszNames,
214                                                      unsigned int cNames,
215                                                      LCID /*lcid*/,
216                                                      DISPID * rgdispid )
217 {
218     HRESULT ret = DISP_E_UNKNOWNNAME;
219     try
220     {
221         MutexGuard guard( getBridgeMutex());
222         if( ! rgdispid)
223             return E_POINTER;
224 
225         // ----------------------------------------
226         if( ! _wcsicmp( *rgszNames, JSCRIPT_VALUE_FUNC) ||
227             ! _wcsicmp( *rgszNames, BRIDGE_VALUE_FUNC))
228         {
229             *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
230             return S_OK;
231         }
232         else if( ! _wcsicmp( *rgszNames, GET_STRUCT_FUNC) ||
233                  ! _wcsicmp( *rgszNames, BRIDGE_GET_STRUCT_FUNC))
234         {
235             *rgdispid= DISPID_GET_STRUCT_FUNC;
236             return S_OK;
237         }
238         else if( ! _wcsicmp( *rgszNames, BRIDGE_CREATE_TYPE_FUNC))
239         {
240             *rgdispid= DISPID_CREATE_TYPE_FUNC;
241             return S_OK;
242         }
243 
244         // ----------------------------------------
245         if (m_xInvocation.is() && (cNames > 0))
246         {
247             OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0]));
248             NameToIdMap::iterator iter = m_nameToDispIdMap.find(name);
249 
250             if (iter == m_nameToDispIdMap.end())
251             {
252                 OUString exactName;
253 
254                 if (m_xExactName.is())
255                 {
256                     exactName = m_xExactName->getExactName(name);
257                 }
258                 else
259                 {
260                     exactName = name;
261                 }
262 
263                 MemberInfo d(0, exactName);
264 
265                 if (m_xInvocation->hasProperty(exactName))
266                 {
267                     d.flags |= DISPATCH_PROPERTYGET;
268                     d.flags |= DISPATCH_PROPERTYPUT;
269                     d.flags |= DISPATCH_PROPERTYPUTREF;
270                 }
271 
272                 if (m_xInvocation->hasMethod(exactName))
273                 {
274                     d.flags |= DISPATCH_METHOD;
275                 }
276 
277                 if (d.flags != 0)
278                 {
279                     m_MemberInfos.push_back(d);
280                     iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(exactName, (DISPID)m_MemberInfos.size())).first;
281 
282                     if (exactName != name)
283                     {
284                         iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(name, (DISPID)m_MemberInfos.size())).first;
285                     }
286                 }
287             }
288 
289             if (iter == m_nameToDispIdMap.end())
290             {
291                 ret = DISP_E_UNKNOWNNAME;
292             }
293             else
294             {
295                 *rgdispid = (*iter).second;
296                 ret = S_OK;
297             }
298         }
299     }
300     catch(BridgeRuntimeError& )
301     {
302         OSL_ASSERT(0);
303     }
304     catch(Exception& )
305     {
306         OSL_ASSERT(0);
307     }
308     catch(...)
309     {
310         OSL_ASSERT(0);
311     }
312 
313     return ret;
314 }
315 
316 // "convertDispparamsArgs" converts VARIANTS to their respecting Any counterparts
317 // The parameters "id", "wFlags" and "pdispparams" equal those as used in
318 // IDispatch::Invoke. The function handles special JavaScript
319 // cases where a VARIANT of type VT_DISPATCH is ambiguous and could represent
320 // an object, array ( JavaScript Array object), out parameter and in/out ( JavaScript Array object)
321 //  parameter (JavaScript Array object)
322 // Because all those VT_DISPATCH objects need a different conversion
323 // we have to find out what the object is supposed to be. The function does this
324 // by either using type information or by help of a specialized ValueObject object.
325 
326 // A. Type Information
327 // -----------------------------------------------------------------------------
328 // With the help of type information the kind of parameter can be exactly determined
329 // and an appropriate conversion can be chosen. A problem arises if a method expects
330 // an Any. Then the type info does not tell what the type of the value, that is kept
331 // by the any, should be. In this situation the decision wheter the param is a
332 // sequence or an object is made upon the fact if the object has a property "0"
333 // ( see function "isJScriptArray"). Since this is unsafe it is recommended to use
334 // the JScript value objects within a JScript script on such an occasion.
335 
336 // B. JavaScript Value Object ( class JScriptValue )
337 // -----------------------------------------------------------------------------
338 // A JScriptValue (ValueObject) object is a COM object in that it implements IDispatch and the
339 // IJScriptValue object interface. Such objects are provided by all UNO wrapper
340 // objects used within a JScript script. To obtain an instance one has to call
341 // "_GetValueObject() or Bridge_GetValueObject()" on an UNO wrapper object (class InterfaceOleWrapper_Impl).
342 // A value object is appropriately initialized within the script and passed as
343 // parameter to an UNO object method or property. The convertDispparamsArgs function
344 // can easily find out that a param is such an object by queriing for the
345 // IJScriptValue interface. By this interface one the type and kind ( out, in/out)
346 // can be determined and the right conversion can be applied.
347 // Using ValueObjects we spare us the effort of acquiring and examining type information
348 // in order to figure out what the an IDispatch parameter is meant for.
349 
350 // Normal JScript object parameter can be mixed with JScriptValue object. If an
351 // VARIANT contains an VT_DISPATCH that is no JScriptValue than the type information
352 // is used to find out about the reqired type.
convertDispparamsArgs(DISPID id,unsigned short,DISPPARAMS * pdispparams,Sequence<Any> & rSeq)353 void InterfaceOleWrapper_Impl::convertDispparamsArgs(DISPID id,
354     unsigned short /*wFlags*/, DISPPARAMS* pdispparams, Sequence<Any>& rSeq)
355 {
356     HRESULT hr= S_OK;
357     sal_Int32 countArgs= pdispparams->cArgs;
358     if( countArgs == 0)
359         return;
360 
361     rSeq.realloc( countArgs);
362     Any*    pParams = rSeq.getArray();
363 
364     Any anyParam;
365 
366     //Get type information for the current call
367     InvocationInfo info;
368     if( ! getInvocationInfoForCall( id, info))
369         throw BridgeRuntimeError(
370             OUSTR("[automation bridge]InterfaceOleWrapper_Impl::convertDispparamsArgs \n"
371                   "Could not obtain type information for current call."));
372 
373     for (int i = 0; i < countArgs; i++)
374     {
375         if (info.eMemberType == MemberType_METHOD &&
376             info.aParamModes[ countArgs - i -1 ]  == ParamMode_OUT)
377             continue;
378 
379         if(convertValueObject( & pdispparams->rgvarg[i], anyParam))
380         { //a param is a ValueObject and could be converted
381             pParams[countArgs - (i + 1)] = anyParam;
382             continue;
383         }
384 
385         // If the param is an out, in/out parameter in
386         // JScript (Array object, with value at index 0) then we
387         // extract Array[0] and put the value into varParam. At the end of the loop varParam
388         // is converted if it contains a value otherwise the VARIANT from
389         // DISPPARAMS is converted.
390         CComVariant varParam;
391 
392         // Check for JScript out and in/out paramsobjects (VT_DISPATCH).
393         // To find them out we use typeinformation of the function being called.
394         if( pdispparams->rgvarg[i].vt == VT_DISPATCH )
395         {
396             if( info.eMemberType == MemberType_METHOD && info.aParamModes[ countArgs - i -1 ]  == ParamMode_INOUT)
397             {
398                 // INOUT-param
399                 // Index ( property) "0" contains the actual IN-param. The object is a JScript
400                 // Array object.
401                 // Get the IN-param at index "0"
402                 IDispatch* pdisp= pdispparams->rgvarg[i].pdispVal;
403 
404                 OLECHAR* sindex= L"0";
405                 DISPID id;
406                 DISPPARAMS noParams= {0,0,0,0};
407                 if(SUCCEEDED( hr= pdisp->GetIDsOfNames( IID_NULL, &sindex, 1, LOCALE_USER_DEFAULT, &id)))
408                     hr= pdisp->Invoke( id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
409                                        & noParams, & varParam, NULL, NULL);
410                 if( FAILED( hr))
411                 {
412                     throw BridgeRuntimeError(
413                         OUSTR("[automation bridge] Could not determine "
414                               "if the object has a member \"0\". Error: ") +
415                         OUString::valueOf(hr));
416                 }
417             }
418         }
419 
420         if( varParam.vt == VT_EMPTY) // then it was no in/out parameter
421                  varParam= pdispparams->rgvarg[i];
422 
423         if(info.eMemberType == MemberType_METHOD)
424             variantToAny( & varParam, anyParam,
425                            info.aParamTypes[ countArgs - i - 1]);
426         else if(info.eMemberType == MemberType_PROPERTY)
427             variantToAny( & varParam, anyParam, info.aType);
428         else
429             OSL_ASSERT(0);
430 
431         pParams[countArgs - (i + 1)]= anyParam;
432     }// end for / iterating over all parameters
433 }
434 
getInvocationInfoForCall(DISPID id,InvocationInfo & info)435 sal_Bool  InterfaceOleWrapper_Impl::getInvocationInfoForCall( DISPID id, InvocationInfo& info)
436 {
437     sal_Bool bTypesAvailable= sal_False;
438 
439     if( !m_xInvocation.is() )return false;
440     Reference<XInvocation2> inv2( m_xInvocation, UNO_QUERY);
441     if( inv2.is())
442     {
443         // We need the name of the property or method to get its type information.
444         // The name can be identified through the param "id"
445         // that is kept as value in the map m_nameToDispIdMap.
446         // Proplem: the Windows JScript engine sometimes changes small letters to capital
447         // letters as happens in xidlclass_obj.createObject( var) // in JScript.
448         // IDispatch::GetIdsOfNames is then called with "CreateObject" !!!
449         // m_nameToDispIdMap can contain several names for one DISPID but only one is
450         // the exact one. If there's no m_xExactName and therefore no exact name then
451         // there's only one entry in the map.
452         typedef NameToIdMap::const_iterator cit;
453         OUString sMemberName;
454 
455         for(cit ci1= m_nameToDispIdMap.begin(); ci1 != m_nameToDispIdMap.end(); ci1++)
456         {
457             if( (*ci1).second == id) // iterator is a pair< OUString, DISPID>
458             {
459                 sMemberName= (*ci1).first;
460                 break;
461             }
462         }
463         // Get information for the current call ( property or method).
464         // There could be similar names which only differ in the cases
465         // of letters. First we assume that the name which was passed into
466         // GetIDsOfNames is correct. If we won't get information with that
467         // name then we have the invocation service use the XExactName interface.
468         sal_Bool validInfo= sal_True;
469         InvocationInfo invInfo;
470         try{
471             invInfo= inv2->getInfoForName( sMemberName, sal_False);
472         }
473         catch( IllegalArgumentException )
474         {
475             validInfo= sal_False;
476         }
477 
478         if( ! validInfo)
479         {
480             invInfo= inv2->getInfoForName( sMemberName, sal_True);
481         }
482         if( invInfo.aName.pData)
483         {
484             bTypesAvailable= sal_True;
485             info= invInfo;
486         }
487     }
488     return bTypesAvailable;
489 }
490 // XBridgeSupplier2 ---------------------------------------------------
491 // only bridges itself ( this instance of InterfaceOleWrapper_Impl)from UNO to IDispatch
492 // If sourceModelType is UNO than any UNO interface implemented by InterfaceOleWrapper_Impl
493 // can bridged to IDispatch ( if destModelType == OLE). The IDispatch is
494 // implemented by this class.
createBridge(const Any & modelDepObject,const Sequence<sal_Int8> &,sal_Int16 sourceModelType,sal_Int16 destModelType)495 Any SAL_CALL InterfaceOleWrapper_Impl::createBridge(const Any& modelDepObject,
496                                 const Sequence<sal_Int8>& /*ProcessId*/,
497                                 sal_Int16 sourceModelType,
498                                 sal_Int16 destModelType)
499 {
500 
501     Any retAny;
502     if( sourceModelType == UNO && destModelType == OLE &&
503         modelDepObject.getValueTypeClass() == TypeClass_INTERFACE )
504     {
505         Reference<XInterface> xInt;
506         if( modelDepObject >>= xInt )
507         {
508             if( xInt == Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY))
509             {
510                 VARIANT *pVar= (VARIANT*)CoTaskMemAlloc( sizeof( VARIANT));
511                 if( pVar)
512                 {
513                     pVar->vt= VT_DISPATCH;
514                     pVar->pdispVal= static_cast<IDispatch*>( this);
515                     AddRef();
516 
517                     retAny<<= reinterpret_cast< sal_uInt32 >( pVar);
518                 }
519             }
520         }
521     }
522 
523     return retAny;
524 }
525 
526 
527 // XInitialization --------------------------------------------------
initialize(const Sequence<Any> & aArguments)528 void SAL_CALL InterfaceOleWrapper_Impl::initialize( const Sequence< Any >& aArguments )
529 {
530     switch( aArguments.getLength() )
531     {
532     case 2: // the object wraps an UNO struct
533         aArguments[0] >>= m_xInvocation;
534         aArguments[1] >>= m_defaultValueType;
535         break;
536     case 3: // the object wraps an UNO interface
537         aArguments[0] >>= m_xInvocation;
538         aArguments[1] >>= m_xOrigin;
539         aArguments[2] >>= m_defaultValueType;
540         break;
541     }
542 
543     m_xExactName= Reference<XExactName>( m_xInvocation, UNO_QUERY);
544 }
545 
createUnoWrapperInstance()546 Reference< XInterface > InterfaceOleWrapper_Impl::createUnoWrapperInstance()
547 {
548     Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl(
549                             m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
550     return Reference<XInterface>( xWeak, UNO_QUERY);
551 }
552 
createComWrapperInstance()553 Reference<XInterface> InterfaceOleWrapper_Impl::createComWrapperInstance()
554 {
555     Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl(
556                             m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
557     return Reference<XInterface>( xWeak, UNO_QUERY);
558 }
559 
560 
561 
562 // "getType" is used in convertValueObject to map the string denoting the type
563 // to an actual Type object.
getType(const BSTR name,Type & type)564 bool getType( const BSTR name, Type & type)
565 {
566     Type retType;
567     bool ret = false;
568     typelib_TypeDescription * pDesc= NULL;
569     OUString str( reinterpret_cast<const sal_Unicode*>(name));
570     typelib_typedescription_getByName( &pDesc, str.pData );
571     if( pDesc)
572     {
573         type = Type( pDesc->pWeakRef );
574         typelib_typedescription_release( pDesc);
575         ret = true;
576     }
577     return ret;
578 }
579 
writeBackOutParameter2(VARIANTARG * pDest,VARIANT * pSource)580 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource)
581 {
582     sal_Bool ret = sal_False;
583     HRESULT hr;
584 
585     // Handle JScriptValue objects and JScript out params ( Array object )
586     CComVariant varDest( *pDest);
587 
588     if( SUCCEEDED( varDest.ChangeType(VT_DISPATCH)))
589     {
590         CComPtr<IDispatch> spDispDest(varDest.pdispVal);
591 
592         // special Handling for a JScriptValue object
593 #ifdef __MINGW32__
594         CComQIPtr<IJScriptValueObject, &__uuidof(IJScriptValueObject)> spValueDest(spDispDest);
595 #else
596         CComQIPtr<IJScriptValueObject> spValueDest(spDispDest);
597 #endif
598         if (spValueDest)
599         {
600             VARIANT_BOOL varBool= VARIANT_FALSE;
601             if( SUCCEEDED( hr= spValueDest->IsOutParam( &varBool) )
602                 && varBool == VARIANT_TRUE  ||
603                 SUCCEEDED(hr= spValueDest->IsInOutParam( &varBool) )
604                 && varBool == VARIANT_TRUE )
605             {
606                 if( SUCCEEDED( spValueDest->Set( CComVariant(), *pSource)))
607                     ret= sal_True;
608             }
609         }
610         else if (pDest->vt == VT_DISPATCH)// VT_DISPATCH -> JScript out param
611         {
612             // We use IDispatchEx because its GetDispID function causes the creation
613             // of a property if it does not exist already. This is convenient for
614             // out parameters in JScript. Then the user must not specify propery "0"
615             // explicitly
616 #ifdef __MINGW32__
617             CComQIPtr<IDispatchEx, &__uuidof(IDispatchEx)> spDispEx( spDispDest);
618 #else
619             CComQIPtr<IDispatchEx> spDispEx( spDispDest);
620 #endif
621             if( spDispEx)
622             {
623                 CComBSTR nullProp(L"0");
624                 DISPID dwDispID;
625                 if( SUCCEEDED( spDispEx->GetDispID( nullProp, fdexNameEnsure, &dwDispID)))
626                 {
627                     DISPPARAMS dispparams = {NULL, NULL, 1, 1};
628                     dispparams.rgvarg = pSource;
629                     DISPID dispidPut = DISPID_PROPERTYPUT;
630                     dispparams.rgdispidNamedArgs = &dispidPut;
631 
632                     if (pSource->vt == VT_UNKNOWN || pSource->vt == VT_DISPATCH ||
633                         (pSource->vt & VT_ARRAY) || (pSource->vt & VT_BYREF))
634                         hr = spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
635                                                 &dispparams, NULL, NULL, NULL);
636                     else
637                         hr= spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
638                                                &dispparams, NULL, NULL, NULL);
639                     if( SUCCEEDED(hr))
640                         ret= sal_True;
641                 }
642             }
643         }
644         else
645             ret= writeBackOutParameter( pDest, pSource);
646     }
647     else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript
648     {   // param. The function checks itself for correct VBScript params
649         ret= writeBackOutParameter( pDest, pSource);
650     }
651     return ret;
652 }
653 // VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter.
654 // Thus we are in charge of freeing an eventual value contained by the inner VARIANT
655 // Please note: VariantCopy doesn't free a VT_BYREF value
656 // The out parameters are expected to have always a valid type
writeBackOutParameter(VARIANTARG * pDest,VARIANT * pSource)657 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource)
658 {
659     HRESULT hr;
660     sal_Bool ret = FALSE;
661     // Out parameter must be VT_BYREF
662     if ((V_VT(pDest) & VT_BYREF) != 0 )
663     {
664         VARTYPE oleTypeFlags = V_VT(pSource);
665 
666         // if caller accept VARIANT as out parameter, any value must be converted
667         if (V_VT(pDest) == (VT_VARIANT | VT_BYREF))
668         {
669             // When the user provides a VARIANT rather then a concrete type
670             // we just copy the source to the out, in/out parameter
671             // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that
672             // is contained in pDest are released by VariantCopy
673             VariantCopy(V_VARIANTREF(pDest), pSource);
674             ret = sal_True;
675         }
676         else
677         {
678             // variantarg and variant must have same type
679             if ((V_VT(pDest) & oleTypeFlags) == oleTypeFlags)
680             {
681                 if ((oleTypeFlags & VT_ARRAY) != 0)
682                 {
683                     // In / Out Param
684                     if( *V_ARRAYREF(pDest) != NULL)
685                         hr= SafeArrayCopyData( V_ARRAY(pSource), *V_ARRAYREF(pDest));
686                     else
687                         // Out Param
688                         hr= SafeArrayCopy(V_ARRAY(pSource), V_ARRAYREF(pDest)) == NOERROR;
689                     if( SUCCEEDED( hr))
690                         ret = sal_True;
691                 }
692                 else
693                 {
694                     // copy base type
695                     switch (V_VT(pSource))
696                     {
697                     case VT_I2:
698                     {
699                         *V_I2REF(pDest) = V_I2(pSource);
700                         ret = sal_True;
701                         break;
702                     }
703                     case VT_I4:
704                         *V_I4REF(pDest) = V_I4(pSource);
705                         ret = sal_True;
706                         break;
707                     case VT_R4:
708                         *V_R4REF(pDest) = V_R4(pSource);
709                         ret = sal_True;
710                         break;
711                     case VT_R8:
712                         *V_R8REF(pDest) = V_R8(pSource);
713                         ret = sal_True;
714                         break;
715                     case VT_CY:
716                         *V_CYREF(pDest) = V_CY(pSource);
717                         ret = sal_True;
718                         break;
719                     case VT_DATE:
720                         *V_DATEREF(pDest) = V_DATE(pSource);
721                         ret = sal_True;
722                         break;
723                     case VT_BSTR:
724                         SysFreeString( *pDest->pbstrVal);
725 
726                         *V_BSTRREF(pDest) = SysAllocString(V_BSTR(pSource));
727                         ret = sal_True;
728                         break;
729                     case VT_DISPATCH:
730                         if (*V_DISPATCHREF(pDest) != NULL)
731                             (*V_DISPATCHREF(pDest))->Release();
732 
733                         *V_DISPATCHREF(pDest) = V_DISPATCH(pSource);
734 
735                         if (*V_DISPATCHREF(pDest) != NULL)
736                             (*V_DISPATCHREF(pDest))->AddRef();
737 
738                         ret = sal_True;
739                         break;
740                     case VT_ERROR:
741                         *V_ERRORREF(pDest) = V_ERROR(pSource);
742                         ret = sal_True;
743                         break;
744                     case VT_BOOL:
745                         *V_BOOLREF(pDest) = V_BOOL(pSource);
746                         ret = sal_True;
747                         break;
748                     case VT_UNKNOWN:
749                         if (*V_UNKNOWNREF(pDest) != NULL)
750                             (*V_UNKNOWNREF(pDest))->Release();
751 
752                         *V_UNKNOWNREF(pDest) = V_UNKNOWN(pSource);
753 
754                         if (*V_UNKNOWNREF(pDest) != NULL)
755                             (*V_UNKNOWNREF(pDest))->AddRef();
756 
757                         ret = sal_True;
758                         break;
759                     case VT_I1:
760                         *V_I1REF(pDest) = V_I1(pSource);
761                         ret = sal_True;
762                         break;
763                     case VT_UI1:
764                         *V_UI1REF(pDest) = V_UI1(pSource);
765                         ret = sal_True;
766                         break;
767                     case VT_UI2:
768                         *V_UI2REF(pDest) = V_UI2(pSource);
769                         ret = sal_True;
770                         break;
771                     case VT_UI4:
772                         *V_UI4REF(pDest) = V_UI4(pSource);
773                         ret = sal_True;
774                         break;
775                     case VT_INT:
776                         *V_INTREF(pDest) = V_INT(pSource);
777                         ret = sal_True;
778                         break;
779                     case VT_UINT:
780                         *V_UINTREF(pDest) = V_UINT(pSource);
781                         ret = sal_True;
782                         break;
783                     case VT_DECIMAL:
784                         memcpy(pDest->pdecVal, pSource, sizeof(DECIMAL));
785                         ret = sal_True;
786                         break;
787                     default:
788                         break;
789                     }
790                 }
791             }
792             else
793             {
794                 // Handling of special cases
795                 // Destination and source types are different
796                 if( pDest->vt == (VT_BSTR | VT_BYREF)
797                     && pSource->vt == VT_I2)
798                 {
799                     // When the user provides a String as out our in/out parameter
800                     // and the type is char (TypeClass_CHAR) then we convert to a BSTR
801                     // instead of VT_I2 as is done otherwise
802                     OLECHAR buff[]= {0,0};
803                     buff[0]= pSource->iVal;
804 
805                     SysFreeString( *pDest->pbstrVal);
806                     *pDest->pbstrVal= SysAllocString( buff);
807                     ret = sal_True;
808                 }
809             }
810         }
811     }
812     return ret;
813 }
814 
Invoke(DISPID dispidMember,REFIID,LCID,unsigned short wFlags,DISPPARAMS * pdispparams,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,unsigned int * puArgErr)815 STDMETHODIMP InterfaceOleWrapper_Impl::Invoke(DISPID dispidMember,
816                                               REFIID /*riid*/,
817                                               LCID /*lcid*/,
818                                               unsigned short wFlags,
819                                               DISPPARAMS * pdispparams,
820                                               VARIANT * pvarResult,
821                                               EXCEPINFO * pexcepinfo,
822                                               unsigned int * puArgErr )
823 {
824     HRESULT ret = S_OK;
825 
826     try
827     {
828         sal_Bool bHandled= sal_False;
829         ret= InvokeGeneral( dispidMember,  wFlags, pdispparams, pvarResult,  pexcepinfo,
830                             puArgErr, bHandled);
831         if( bHandled)
832             return ret;
833 
834         if ((dispidMember > 0) && ((size_t)dispidMember <= m_MemberInfos.size()) && m_xInvocation.is())
835         {
836             MemberInfo d = m_MemberInfos[dispidMember - 1];
837             DWORD flags = wFlags & d.flags;
838 
839             if (flags != 0)
840             {
841                 if ((flags & DISPATCH_METHOD) != 0)
842                 {
843                     if (pdispparams->cNamedArgs > 0)
844                         ret = DISP_E_NONAMEDARGS;
845                     else
846                     {
847                         Sequence<Any> params;
848 
849                         convertDispparamsArgs(dispidMember, wFlags, pdispparams , params );
850 
851                         ret= doInvoke(pdispparams, pvarResult,
852                                       pexcepinfo, puArgErr, d.name, params);
853                     }
854                 }
855                 else if ((flags & DISPATCH_PROPERTYGET) != 0)
856                 {
857                     ret=  doGetProperty( pdispparams, pvarResult,
858                                          pexcepinfo, d.name);
859                 }
860                 else if ((flags & DISPATCH_PROPERTYPUT || flags & DISPATCH_PROPERTYPUTREF) != 0)
861                 {
862                     if (pdispparams->cArgs != 1)
863                         ret = DISP_E_BADPARAMCOUNT;
864                     else
865                     {
866                         Sequence<Any> params;
867                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
868                         if(params.getLength() > 0)
869                             ret= doSetProperty( pdispparams, pvarResult, pexcepinfo, puArgErr, d.name, params);
870                         else
871                             ret = DISP_E_BADVARTYPE;
872                     }
873                 }
874             }
875             else
876                 ret= DISP_E_MEMBERNOTFOUND;
877         }
878         else
879             ret = DISP_E_MEMBERNOTFOUND;
880     }
881     catch(BridgeRuntimeError& e)
882     {
883         writeExcepinfo(pexcepinfo, e.message);
884         ret = DISP_E_EXCEPTION;
885     }
886     catch(Exception& e)
887     {
888         OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n") +
889                                 e.Message;
890         writeExcepinfo(pexcepinfo, message);
891         ret = DISP_E_EXCEPTION;
892     }
893     catch(...)
894     {
895         OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n"
896                                 "Unexpected exception");
897         writeExcepinfo(pexcepinfo, message);
898         ret = DISP_E_EXCEPTION;
899     }
900 
901     return ret;
902 }
903 
doInvoke(DISPPARAMS * pdispparams,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,unsigned int * puArgErr,OUString & name,Sequence<Any> & params)904 HRESULT InterfaceOleWrapper_Impl::doInvoke( DISPPARAMS * pdispparams, VARIANT * pvarResult,
905                               EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any>& params)
906 {
907 
908 
909     HRESULT ret= S_OK;
910     try
911     {
912         Sequence<sal_Int16>     outIndex;
913         Sequence<Any>   outParams;
914         Any                 returnValue;
915 
916         if (pdispparams->cNamedArgs > 0)
917             return DISP_E_NONAMEDARGS;
918 
919         // invoke method and take care of exceptions
920         returnValue = m_xInvocation->invoke(name,
921                                             params,
922                                             outIndex,
923                                             outParams);
924 
925         // try to write back out parameter
926         if (outIndex.getLength() > 0)
927         {
928             const sal_Int16* pOutIndex = outIndex.getConstArray();
929             const Any* pOutParams = outParams.getConstArray();
930 
931             for (sal_Int32 i = 0; i < outIndex.getLength(); i++)
932             {
933                 CComVariant variant;
934                 // Currently a Sequence is converted to an SafeArray of VARIANTs.
935                 anyToVariant( &variant, pOutParams[i]);
936 
937                 // out parameter need special handling if they are VT_DISPATCH
938                 // and used in JScript
939                 int outindex= pOutIndex[i];
940                 writeBackOutParameter2(&(pdispparams->rgvarg[pdispparams->cArgs - 1 - outindex]),
941                                        &variant );
942             }
943         }
944 
945         // write back return value
946         if (pvarResult != NULL)
947             anyToVariant(pvarResult, returnValue);
948     }
949     catch(IllegalArgumentException & e) //XInvocation::invoke
950     {
951         writeExcepinfo(pexcepinfo, e.Message);
952         ret = DISP_E_TYPEMISMATCH;
953     }
954     catch(CannotConvertException & e) //XInvocation::invoke
955     {
956         writeExcepinfo(pexcepinfo, e.Message);
957         ret = mapCannotConvertException( e, puArgErr);
958     }
959     catch(InvocationTargetException &  e) //XInvocation::invoke
960     {
961         const Any& org = e.TargetException;
962         Exception excTarget;
963         org >>= excTarget;
964         OUString message=
965             org.getValueType().getTypeName() + OUSTR(": ") + excTarget.Message;
966         writeExcepinfo(pexcepinfo, message);
967         ret = DISP_E_EXCEPTION;
968     }
969     catch(NoSuchMethodException & e) //XInvocation::invoke
970     {
971         writeExcepinfo(pexcepinfo, e.Message);
972         ret = DISP_E_MEMBERNOTFOUND;
973     }
974     catch(BridgeRuntimeError & e)
975     {
976         writeExcepinfo(pexcepinfo, e.message);
977         ret = DISP_E_EXCEPTION;
978     }
979     catch(Exception & e)
980     {
981         OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n") +
982                                 e.Message;
983         writeExcepinfo(pexcepinfo, message);
984         ret = DISP_E_EXCEPTION;
985     }
986     catch( ... )
987     {
988         OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n"
989                                 "Unexpected exception");
990         writeExcepinfo(pexcepinfo, message);
991         ret = DISP_E_EXCEPTION;
992     }
993     return ret;
994 }
995 
doGetProperty(DISPPARAMS *,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,OUString & name)996 HRESULT InterfaceOleWrapper_Impl::doGetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * pvarResult,
997                                                 EXCEPINFO * pexcepinfo, OUString& name)
998 {
999     HRESULT ret= S_OK;
1000 
1001     Any value;
1002     try
1003     {
1004         Any returnValue = m_xInvocation->getValue( name);
1005         // write back return value
1006         if (pvarResult)
1007             anyToVariant(pvarResult, returnValue);
1008     }
1009     catch(UnknownPropertyException e) //XInvocation::getValue
1010     {
1011         writeExcepinfo(pexcepinfo, e.Message);
1012         ret = DISP_E_MEMBERNOTFOUND;
1013     }
1014     catch(BridgeRuntimeError& e)
1015     {
1016         writeExcepinfo(pexcepinfo, e.message);
1017         ret = DISP_E_EXCEPTION;
1018     }
1019     catch(Exception& e)
1020     {
1021         OUString message= OUSTR("InterfaceOleWrapper_Impl::doGetProperty : \n") +
1022                                 e.Message;
1023         writeExcepinfo(pexcepinfo, message);
1024     }
1025     catch( ... )
1026     {
1027         OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n"
1028                                 "Unexpected exception");
1029         writeExcepinfo(pexcepinfo, message);
1030         ret = DISP_E_EXCEPTION;
1031     }
1032     return  ret;
1033 }
1034 
doSetProperty(DISPPARAMS *,VARIANT *,EXCEPINFO * pexcepinfo,unsigned int * puArgErr,OUString & name,Sequence<Any> params)1035 HRESULT InterfaceOleWrapper_Impl::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1036                                         EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any> params)
1037 {
1038     HRESULT ret= S_OK;
1039 
1040     try
1041     {
1042         m_xInvocation->setValue( name, params.getConstArray()[0]);
1043     }
1044     catch(UnknownPropertyException )
1045     {
1046         ret = DISP_E_MEMBERNOTFOUND;
1047     }
1048     catch(CannotConvertException e)
1049     {
1050         ret= mapCannotConvertException( e, puArgErr);
1051     }
1052     catch(InvocationTargetException e)
1053     {
1054         if (pexcepinfo != NULL)
1055         {
1056             Any org = e.TargetException;
1057 
1058             pexcepinfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
1059             pexcepinfo->bstrSource = SysAllocString(L"any ONE component");
1060             pexcepinfo->bstrDescription = SysAllocString(
1061                 reinterpret_cast<LPCOLESTR>(org.getValueType().getTypeName().getStr()));
1062         }
1063         ret = DISP_E_EXCEPTION;
1064     }
1065     catch( ... )
1066     {
1067         ret= DISP_E_EXCEPTION;
1068     }
1069     return ret;
1070 }
1071 
InvokeGeneral(DISPID dispidMember,unsigned short wFlags,DISPPARAMS * pdispparams,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,unsigned int *,sal_Bool & bHandled)1072 HRESULT InterfaceOleWrapper_Impl::InvokeGeneral( DISPID dispidMember, unsigned short wFlags,
1073                          DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1074                          unsigned int * /*puArgErr*/, sal_Bool& bHandled)
1075 {
1076     HRESULT ret= S_OK;
1077     try
1078     {
1079 // DISPID_VALUE | The DEFAULT Value is required in JScript when the situation
1080 // is that we put an object into an Array object ( out parameter). We have to return
1081 // IDispatch otherwise the object cannot be accessed from the Script.
1082         if( dispidMember == DISPID_VALUE && wFlags == DISPATCH_PROPERTYGET
1083             && m_defaultValueType != VT_EMPTY && pvarResult != NULL)
1084         {
1085             bHandled= sal_True;
1086             if( m_defaultValueType == VT_DISPATCH)
1087             {
1088                 pvarResult->vt= VT_DISPATCH;
1089                 pvarResult->pdispVal= static_cast<IDispatch*>( this);
1090                 AddRef();
1091                 ret= S_OK;
1092             }
1093         }
1094 // ---------
1095         // function: _GetValueObject
1096         else if( dispidMember == DISPID_JSCRIPT_VALUE_FUNC)
1097         {
1098             bHandled= sal_True;
1099             if( !pvarResult)
1100                 ret= E_POINTER;
1101             CComObject< JScriptValue>* pValue;
1102             if( SUCCEEDED( CComObject<JScriptValue>::CreateInstance( &pValue)))
1103             {
1104                 pValue->AddRef();
1105                 pvarResult->vt= VT_DISPATCH;
1106 #ifdef __MINGW32__
1107                 pvarResult->pdispVal= CComQIPtr<IDispatch, &__uuidof(IDispatch)>(pValue->GetUnknown());
1108 #else
1109                 pvarResult->pdispVal= CComQIPtr<IDispatch>(pValue->GetUnknown());
1110 #endif
1111                 ret= S_OK;
1112             }
1113             else
1114                 ret= DISP_E_EXCEPTION;
1115         }
1116         else if( dispidMember == DISPID_GET_STRUCT_FUNC)
1117         {
1118             bHandled= sal_True;
1119             sal_Bool bStruct= sal_False;
1120 
1121 
1122             Reference<XInterface> xIntCore= m_smgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection"));
1123             Reference<XIdlReflection> xRefl( xIntCore, UNO_QUERY);
1124             if( xRefl.is() )
1125             {
1126                 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1127                 CComVariant arg;
1128                 if( pdispparams->cArgs == 1 && SUCCEEDED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])) )
1129                 {
1130                     Reference<XIdlClass> classStruct= xRefl->forName( reinterpret_cast<const sal_Unicode*>(arg.bstrVal));
1131                     if( classStruct.is())
1132                     {
1133                         Any anyStruct;
1134                         classStruct->createObject( anyStruct);
1135                         CComVariant var;
1136                         anyToVariant( &var, anyStruct );
1137 
1138                         if( var.vt == VT_DISPATCH)
1139                         {
1140                             VariantCopy( pvarResult, & var);
1141                             bStruct= sal_True;
1142                         }
1143                     }
1144                 }
1145             }
1146             ret= bStruct == sal_True ? S_OK : DISP_E_EXCEPTION;
1147         }
1148         else if (dispidMember == DISPID_CREATE_TYPE_FUNC)
1149         {
1150             bHandled= sal_True;
1151             if( !pvarResult)
1152                 ret= E_POINTER;
1153             // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1154             CComVariant arg;
1155             if( pdispparams->cArgs != 1)
1156                 return DISP_E_BADPARAMCOUNT;
1157             if (FAILED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])))
1158                 return DISP_E_BADVARTYPE;
1159 
1160             //check if the provided name represents a valid type
1161             Type type;
1162             if (getType(arg.bstrVal, type) == false)
1163             {
1164                 writeExcepinfo(pexcepinfo,OUString(
1165                                    OUSTR("[automation bridge] A UNO type with the name ") +
1166                                    OUString(reinterpret_cast<const sal_Unicode*>(arg.bstrVal)) + OUSTR(" does not exist!")));
1167                 return DISP_E_EXCEPTION;
1168             }
1169 
1170             if (createUnoTypeWrapper(arg.bstrVal, pvarResult) == false)
1171             {
1172                 writeExcepinfo(pexcepinfo,OUSTR("[automation bridge] InterfaceOleWrapper_Impl::InvokeGeneral\n"
1173                                                 "Could not initialize UnoTypeWrapper object!"));
1174                 return DISP_E_EXCEPTION;
1175             }
1176         }
1177     }
1178     catch(BridgeRuntimeError & e)
1179     {
1180         writeExcepinfo(pexcepinfo, e.message);
1181         ret = DISP_E_EXCEPTION;
1182     }
1183     catch(Exception & e)
1184     {
1185         OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n") +
1186                                 e.Message;
1187         writeExcepinfo(pexcepinfo, message);
1188         ret = DISP_E_EXCEPTION;
1189     }
1190     catch( ... )
1191     {
1192         OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n"
1193                                 "Unexpected exception");
1194         writeExcepinfo(pexcepinfo, message);
1195         ret = DISP_E_EXCEPTION;
1196     }
1197     return ret;
1198 }
1199 
1200 
1201 
1202 
GetDispID(BSTR,DWORD,DISPID __RPC_FAR *)1203 STDMETHODIMP InterfaceOleWrapper_Impl::GetDispID(BSTR /*bstrName*/, DWORD /*grfdex*/, DISPID __RPC_FAR* /*pid*/)
1204 {
1205     HRESULT ret = ResultFromScode(E_NOTIMPL);
1206 
1207     return ret;
1208 }
1209 
InvokeEx(DISPID,LCID,WORD,DISPPARAMS __RPC_FAR *,VARIANT __RPC_FAR *,EXCEPINFO __RPC_FAR *,IServiceProvider __RPC_FAR *)1210 STDMETHODIMP InterfaceOleWrapper_Impl::InvokeEx(
1211     /* [in] */ DISPID /*id*/,
1212     /* [in] */ LCID /*lcid*/,
1213     /* [in] */ WORD /*wFlags*/,
1214     /* [in] */ DISPPARAMS __RPC_FAR* /*pdp*/,
1215     /* [out] */ VARIANT __RPC_FAR* /*pvarRes*/,
1216     /* [out] */ EXCEPINFO __RPC_FAR* /*pei*/,
1217     /* [unique][in] */ IServiceProvider __RPC_FAR* /*pspCaller*/)
1218 {
1219     HRESULT ret = ResultFromScode(E_NOTIMPL);
1220 
1221     return ret;
1222 }
1223 
1224 
DeleteMemberByName(BSTR,DWORD)1225 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByName(
1226     /* [in] */ BSTR /*bstr*/,
1227     /* [in] */ DWORD /*grfdex*/)
1228 {
1229     HRESULT ret = ResultFromScode(E_NOTIMPL);
1230 
1231     return ret;
1232 }
1233 
DeleteMemberByDispID(DISPID)1234 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByDispID(DISPID /*id*/)
1235 {
1236     HRESULT ret = ResultFromScode(E_NOTIMPL);
1237 
1238     return ret;
1239 }
1240 
GetMemberProperties(DISPID,DWORD,DWORD __RPC_FAR *)1241 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberProperties(
1242     /* [in] */ DISPID /*id*/,
1243     /* [in] */ DWORD /*grfdexFetch*/,
1244     /* [out] */ DWORD __RPC_FAR* /*pgrfdex*/)
1245 {
1246     HRESULT ret = ResultFromScode(E_NOTIMPL);
1247 
1248     return ret;
1249 }
1250 
GetMemberName(DISPID,BSTR __RPC_FAR *)1251 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberName(
1252     /* [in] */ DISPID /*id*/,
1253     /* [out] */ BSTR __RPC_FAR* /*pbstrName*/)
1254 {
1255     HRESULT ret = ResultFromScode(E_NOTIMPL);
1256 
1257     return ret;
1258 }
1259 
GetNextDispID(DWORD,DISPID,DISPID __RPC_FAR *)1260 STDMETHODIMP InterfaceOleWrapper_Impl::GetNextDispID(
1261     /* [in] */ DWORD /*grfdex*/,
1262     /* [in] */ DISPID /*id*/,
1263     /* [out] */ DISPID __RPC_FAR* /*pid*/)
1264 {
1265     HRESULT ret = ResultFromScode(E_NOTIMPL);
1266 
1267     return ret;
1268 }
1269 
GetNameSpaceParent(IUnknown __RPC_FAR * __RPC_FAR *)1270 STDMETHODIMP InterfaceOleWrapper_Impl::GetNameSpaceParent(
1271     /* [out] */ IUnknown __RPC_FAR *__RPC_FAR* /*ppunk*/)
1272 {
1273     HRESULT ret = ResultFromScode(E_NOTIMPL);
1274 
1275     return ret;
1276 }
1277 
1278 
1279 /*************************************************************************
1280 
1281     UnoObjectWrapperRemoteOpt
1282 
1283 *************************************************************************/
UnoObjectWrapperRemoteOpt(Reference<XMultiServiceFactory> & aFactory,sal_uInt8 unoWrapperClass,sal_uInt8 comWrapperClass)1284 UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference<XMultiServiceFactory>& aFactory,
1285                                                      sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
1286 InterfaceOleWrapper_Impl( aFactory, unoWrapperClass, comWrapperClass),
1287 m_currentId(1)
1288 
1289 {
1290 }
~UnoObjectWrapperRemoteOpt()1291 UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt()
1292 {
1293 }
1294 
1295 // UnoConversionUtilities
createUnoWrapperInstance()1296 Reference< XInterface > UnoObjectWrapperRemoteOpt::createUnoWrapperInstance()
1297 {
1298     Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
1299                                                  m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1300     return Reference<XInterface>( xWeak, UNO_QUERY);
1301 }
1302 
GetIDsOfNames(REFIID,OLECHAR ** rgszNames,unsigned int cNames,LCID,DISPID * rgdispid)1303 STDMETHODIMP  UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID /*riid*/, OLECHAR ** rgszNames, unsigned int cNames,
1304                                 LCID /*lcid*/, DISPID * rgdispid )
1305 {
1306     MutexGuard guard( getBridgeMutex());
1307 
1308     if( ! rgdispid)
1309         return E_POINTER;
1310     HRESULT ret = E_UNEXPECTED;
1311     // ----------------------------------------
1312     // _GetValueObject
1313     if( ! wcscmp( *rgszNames, JSCRIPT_VALUE_FUNC))
1314     {
1315         *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
1316         return S_OK;
1317     }
1318     else if( ! wcscmp( *rgszNames, GET_STRUCT_FUNC))
1319     {
1320         *rgdispid= DISPID_GET_STRUCT_FUNC;
1321         return S_OK;
1322     }
1323 
1324     // ----------------------------------------
1325     if (m_xInvocation.is() && (cNames > 0))
1326     {
1327         OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0]));
1328         // has this name been determined as "bad"
1329         BadNameMap::iterator badIter= m_badNameMap.find( name);
1330         if( badIter == m_badNameMap.end() )
1331         {
1332             // name has not been bad before( member exists
1333             typedef NameToIdMap::iterator ITnames;
1334             pair< ITnames, bool > pair_id= m_nameToDispIdMap.insert( NameToIdMap::value_type(name, m_currentId++));
1335             // new ID inserted ?
1336             if( pair_id.second )
1337             {// yes, now create MemberInfo and ad to IdToMemberInfoMap
1338                 MemberInfo d(0, name);
1339                 m_idToMemberInfoMap.insert( IdToMemberInfoMap::value_type( m_currentId - 1, d));
1340             }
1341 
1342             *rgdispid = pair_id.first->second;
1343             ret = S_OK;
1344         }
1345         else
1346             ret= DISP_E_UNKNOWNNAME;
1347     }
1348     return ret;
1349 }
1350 
Invoke(DISPID dispidMember,REFIID,LCID,unsigned short wFlags,DISPPARAMS * pdispparams,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,unsigned int * puArgErr)1351 STDMETHODIMP  UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember, REFIID /*riid*/, LCID /*lcid*/, unsigned short wFlags,
1352                          DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1353                          unsigned int * puArgErr )
1354 {
1355     HRESULT ret = S_OK;
1356     try
1357     {
1358         sal_Bool bHandled= sal_False;
1359         ret= InvokeGeneral( dispidMember,  wFlags, pdispparams, pvarResult,  pexcepinfo,
1360                             puArgErr, bHandled);
1361         if( bHandled)
1362             return ret;
1363 
1364         if ( dispidMember > 0  && m_xInvocation.is())
1365         {
1366 
1367             IdToMemberInfoMap::iterator it_MemberInfo= m_idToMemberInfoMap.find( dispidMember);
1368             if( it_MemberInfo != m_idToMemberInfoMap.end() )
1369             {
1370                 MemberInfo& info= it_MemberInfo->second;
1371 
1372                 Sequence<Any> params; // holds converted any s
1373                 if( ! info.flags )
1374                 { // DISPID called for the first time
1375                     if( wFlags == DISPATCH_METHOD )
1376                     {
1377                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1378 
1379                         if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1380                                                    pexcepinfo, puArgErr, info.name, params))
1381                             && ret == DISP_E_MEMBERNOTFOUND)
1382                         {
1383                             // try to get the exact name
1384                             OUString exactName;
1385                             if (m_xExactName.is())
1386                             {
1387                                 exactName = m_xExactName->getExactName( info.name);
1388                                 // invoke again
1389                                 if( exactName.getLength() != 0)
1390                                 {
1391                                     if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1392                                                                   pexcepinfo, puArgErr, exactName, params)))
1393                                         info.name= exactName;
1394                                 }
1395                             }
1396                         }
1397                         if( SUCCEEDED( ret ) )
1398                             info.flags= DISPATCH_METHOD;
1399                     } //if( wFlags == DISPATCH_METHOD )
1400 
1401                     else if( wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_PROPERTYPUTREF)
1402                     {
1403                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1404                         if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1405                                                         pexcepinfo, puArgErr, info.name, params))
1406                             && ret == DISP_E_MEMBERNOTFOUND)
1407                         {
1408                             // try to get the exact name
1409                             OUString exactName;
1410                             if (m_xExactName.is())
1411                             {
1412                                 exactName = m_xExactName->getExactName( info.name);
1413                                 // invoke again
1414                                 if( exactName.getLength() != 0)
1415                                 {
1416                                     if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1417                                                                        pexcepinfo, puArgErr, exactName, params)))
1418                                         info.name= exactName;
1419                                 }
1420                             }
1421                         }
1422                         if( SUCCEEDED( ret ) )
1423                             info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1424                     }
1425 
1426                     else if( wFlags == DISPATCH_PROPERTYGET)
1427                     {
1428                         if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1429                                                         pexcepinfo, info.name))
1430                             && ret == DISP_E_MEMBERNOTFOUND)
1431                         {
1432                             // try to get the exact name
1433                             OUString exactName;
1434                             if (m_xExactName.is())
1435                             {
1436                                 exactName = m_xExactName->getExactName( info.name);
1437                                 // invoke again
1438                                 if( exactName.getLength() != 0)
1439                                 {
1440                                     if( SUCCEEDED( ret= doGetProperty( pdispparams, pvarResult,
1441                                                                        pexcepinfo, exactName)))
1442                                         info.name= exactName;
1443                                 }
1444                             }
1445                         }
1446                         if( SUCCEEDED( ret ) )
1447                             info.flags= DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT;
1448                     }
1449                     else if( wFlags & DISPATCH_METHOD &&
1450                              (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF))
1451                     {
1452 
1453                         OUString exactName;
1454                         // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT
1455                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1456                         // try first as method
1457                         if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1458                                                    pexcepinfo, puArgErr, info.name, params))
1459                             && ret == DISP_E_MEMBERNOTFOUND)
1460                         {
1461                             // try to get the exact name
1462                             if (m_xExactName.is())
1463                             {
1464                                 exactName = m_xExactName->getExactName( info.name);
1465                                 // invoke again
1466                                 if( exactName.getLength() != 0)
1467                                 {
1468                                     if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1469                                                                   pexcepinfo, puArgErr, exactName, params)))
1470                                         info.name= exactName;
1471                                 }
1472                             }
1473                         }
1474                         if( SUCCEEDED( ret ) )
1475                             info.flags= DISPATCH_METHOD;
1476 
1477                         // try as property
1478                         if( FAILED( ret) && pdispparams->cArgs == 1)
1479                         {
1480                             if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1481                                                             pexcepinfo, puArgErr, info.name, params))
1482                                 && ret == DISP_E_MEMBERNOTFOUND)
1483                             {
1484                                 // try to get the exact name
1485                                 if( exactName.getLength() != 0)
1486                                 {
1487                                     if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1488                                                                        pexcepinfo, puArgErr, exactName, params)))
1489                                         info.name= exactName;
1490                                 }
1491                             }
1492                             if( SUCCEEDED( ret ) )
1493                                 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1494                         }
1495                     }
1496                     else if( wFlags & DISPATCH_METHOD && wFlags & DISPATCH_PROPERTYGET)
1497                     {
1498                         OUString exactName;
1499                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1500 
1501                         if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1502                                                    pexcepinfo, puArgErr, info.name, params))
1503                             && ret == DISP_E_MEMBERNOTFOUND)
1504                         {
1505                             // try to get the exact name
1506                             if (m_xExactName.is())
1507                             {
1508                                 exactName = m_xExactName->getExactName( info.name);
1509                                 // invoke again
1510                                 if( exactName.getLength() != 0)
1511                                 {
1512                                     if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1513                                                                   pexcepinfo, puArgErr, exactName, params)))
1514                                         info.name= exactName;
1515                                 }
1516                             }
1517                         }
1518                         if( SUCCEEDED( ret ) )
1519                             info.flags= DISPATCH_METHOD;
1520 
1521                         // try as property
1522                         if( FAILED( ret) && pdispparams->cArgs == 1)
1523                         {
1524                             if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1525                                                             pexcepinfo, info.name))
1526                                 && ret == DISP_E_MEMBERNOTFOUND)
1527                             {
1528                                 if( exactName.getLength() != 0)
1529                                 {
1530                                     if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1531                                                                        pexcepinfo, puArgErr, exactName, params)))
1532                                         info.name= exactName;
1533                                 }
1534                             }
1535                             if( SUCCEEDED( ret ) )
1536                                 info.flags= DISPATCH_PROPERTYGET;
1537                         }
1538                     }
1539 
1540                     // update �nformation about this member
1541                     if( ret == DISP_E_MEMBERNOTFOUND)
1542                     {
1543                         // Remember the name as not existing
1544                         // and remove the MemberInfo
1545                         m_badNameMap[info.name]= sal_False;
1546                         m_idToMemberInfoMap.erase( it_MemberInfo);
1547                     }
1548                 } // if( ! info.flags )
1549                 else // IdToMemberInfoMap contains a MemberInfo
1550                 {
1551                     if( wFlags & DISPATCH_METHOD && info.flags == DISPATCH_METHOD)
1552                     {
1553                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1554                         ret= doInvoke( pdispparams, pvarResult,
1555                                        pexcepinfo, puArgErr, info.name, params);
1556                     }
1557                     else if( (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF )  &&
1558                              info.flags & DISPATCH_PROPERTYPUT)
1559                     {
1560                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1561                         ret= doSetProperty( pdispparams, pvarResult,
1562                                             pexcepinfo, puArgErr, info.name, params);
1563                     }
1564                     else if( (wFlags & DISPATCH_PROPERTYGET) && ( info.flags & DISPATCH_PROPERTYGET))
1565                     {
1566                         ret= doGetProperty( pdispparams, pvarResult,
1567                                             pexcepinfo, info.name);
1568                     }
1569                     else
1570                     {
1571                         ret= DISP_E_MEMBERNOTFOUND;
1572                     }
1573                 }
1574             }//     if( it_MemberInfo != m_idToMemberInfoMap.end() )
1575             else
1576                 ret= DISP_E_MEMBERNOTFOUND;
1577         }
1578     }
1579     catch(BridgeRuntimeError& e)
1580     {
1581         writeExcepinfo(pexcepinfo, e.message);
1582         ret = DISP_E_EXCEPTION;
1583     }
1584     catch(Exception& e)
1585     {
1586         OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n") +
1587             e.Message;
1588             writeExcepinfo(pexcepinfo, message);
1589             ret = DISP_E_EXCEPTION;
1590     }
1591     catch(...)
1592     {
1593         OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n"
1594                                 "Unexpected exception");
1595         writeExcepinfo(pexcepinfo, message);
1596         ret = DISP_E_EXCEPTION;
1597     }
1598 
1599     return ret;
1600 }
1601 
methodInvoke(DISPID,DISPPARAMS *,VARIANT *,EXCEPINFO *,unsigned int *,Sequence<Any> params)1602 HRESULT UnoObjectWrapperRemoteOpt::methodInvoke( DISPID /*dispidMember*/, DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1603                               EXCEPINFO * /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence<Any> params)
1604 {
1605     return S_OK;
1606 }
1607 
1608 
1609 // The returned HRESULT is only appropriate for IDispatch::Invoke
mapCannotConvertException(CannotConvertException e,unsigned int * puArgErr)1610 static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr)
1611 {
1612     HRESULT ret;
1613     sal_Bool bWriteIndex= sal_True;
1614 
1615     switch ( e.Reason)
1616     {
1617         case FailReason::OUT_OF_RANGE:
1618             ret = DISP_E_OVERFLOW;
1619             break;
1620         case FailReason::IS_NOT_NUMBER:
1621             ret = DISP_E_TYPEMISMATCH;
1622             break;
1623         case FailReason::IS_NOT_ENUM:
1624             ret = DISP_E_TYPEMISMATCH;
1625             break;
1626         case FailReason::IS_NOT_BOOL:
1627             ret = DISP_E_TYPEMISMATCH;
1628             break;
1629         case FailReason::NO_SUCH_INTERFACE:
1630             ret = DISP_E_TYPEMISMATCH;
1631             break;
1632         case FailReason::SOURCE_IS_NO_DERIVED_TYPE:
1633             ret = DISP_E_TYPEMISMATCH;
1634             break;
1635         case FailReason::TYPE_NOT_SUPPORTED:
1636             ret = DISP_E_TYPEMISMATCH;
1637             break;
1638         case FailReason::INVALID:
1639             ret = DISP_E_TYPEMISMATCH;
1640             break;
1641         case FailReason::NO_DEFAULT_AVAILABLE:
1642             ret = DISP_E_BADPARAMCOUNT;
1643             break;
1644         case FailReason::UNKNOWN:
1645             ret = E_UNEXPECTED;
1646             break;
1647         default:
1648             ret = E_UNEXPECTED;
1649             bWriteIndex= sal_False;
1650             break;
1651     }
1652 
1653     if( bWriteIndex &&  puArgErr != NULL)
1654         *puArgErr = e.ArgumentIndex;
1655     return ret;
1656 }
1657 
1658 // The function maps the TypeClass of the any to VARTYPE: If
1659 // the Any contains STRUCT or INTERFACE then the return value
1660 // is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper
1661 // and the result is put into the constructor of the uno - wrapper
1662 // object. If a client asks the object for DISPID_VALUE and this
1663 // function returned VT_DISPATCH then the IDispatch of the same
1664 // object is being returned.
1665 // See InterfaceOleWrapper_Impl::Invoke, InterfaceOleWrapper_Impl::m_defaultValueType
getVarType(const Any & value)1666 const VARTYPE getVarType( const Any& value)
1667 {
1668     VARTYPE ret= VT_EMPTY;
1669 
1670     switch ( value.getValueTypeClass())
1671     {
1672     case TypeClass_STRUCT: ret= VT_DISPATCH; break;
1673     case TypeClass_INTERFACE: ret= VT_DISPATCH; break;
1674     default: break;
1675     }
1676     return ret;
1677 }
1678 
1679 
1680 
1681 
1682 } // end namespace
1683