xref: /aoo4110/main/extensions/source/ole/unoobjw.cxx (revision b1cdbd2c)
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 choosen. 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 aquiring 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 			throw (IllegalArgumentException, RuntimeException)
500 {
501 
502 	Any retAny;
503 	if( sourceModelType == UNO && destModelType == OLE &&
504 		modelDepObject.getValueTypeClass() == TypeClass_INTERFACE )
505 	{
506 		Reference<XInterface> xInt;
507 		if( modelDepObject >>= xInt )
508 		{
509 			if( xInt == Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY))
510 			{
511 				VARIANT *pVar= (VARIANT*)CoTaskMemAlloc( sizeof( VARIANT));
512 				if( pVar)
513 				{
514 					pVar->vt= VT_DISPATCH;
515 					pVar->pdispVal= static_cast<IDispatch*>( this);
516 					AddRef();
517 
518 					retAny<<= reinterpret_cast< sal_uInt32 >( pVar);
519 				}
520 			}
521 		}
522 	}
523 
524 	return retAny;
525 }
526 
527 
528 // XInitialization --------------------------------------------------
initialize(const Sequence<Any> & aArguments)529 void SAL_CALL InterfaceOleWrapper_Impl::initialize( const Sequence< Any >& aArguments )
530 		throw(Exception, RuntimeException)
531 {
532 	switch( aArguments.getLength() )
533 	{
534 	case 2: // the object wraps an UNO struct
535 		aArguments[0] >>= m_xInvocation;
536 		aArguments[1] >>= m_defaultValueType;
537 		break;
538 	case 3: // the object wraps an UNO interface
539 		aArguments[0] >>= m_xInvocation;
540 		aArguments[1] >>= m_xOrigin;
541 		aArguments[2] >>= m_defaultValueType;
542 		break;
543 	}
544 
545 	m_xExactName= Reference<XExactName>( m_xInvocation, UNO_QUERY);
546 }
547 
createUnoWrapperInstance()548 Reference< XInterface > InterfaceOleWrapper_Impl::createUnoWrapperInstance()
549 {
550 	Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl(
551 							m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
552 	return Reference<XInterface>( xWeak, UNO_QUERY);
553 }
554 
createComWrapperInstance()555 Reference<XInterface> InterfaceOleWrapper_Impl::createComWrapperInstance()
556 {
557 	Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl(
558 							m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
559 	return Reference<XInterface>( xWeak, UNO_QUERY);
560 }
561 
562 
563 
564 // "getType" is used in convertValueObject to map the string denoting the type
565 // to an actual Type object.
getType(const BSTR name,Type & type)566 bool getType( const BSTR name, Type & type)
567 {
568 	Type retType;
569 	bool ret = false;
570 	typelib_TypeDescription	* pDesc= NULL;
571 	OUString str( reinterpret_cast<const sal_Unicode*>(name));
572 	typelib_typedescription_getByName( &pDesc, str.pData );
573 	if( pDesc)
574 	{
575 		type = Type( pDesc->pWeakRef );
576 		typelib_typedescription_release( pDesc);
577 		ret = true;
578 	}
579 	return ret;
580 }
581 
writeBackOutParameter2(VARIANTARG * pDest,VARIANT * pSource)582 static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource)
583 {
584 	sal_Bool ret = sal_False;
585 	HRESULT hr;
586 
587 	// Handle JScriptValue objects and JScript out params ( Array object )
588 	CComVariant varDest( *pDest);
589 
590 	if( SUCCEEDED( varDest.ChangeType(VT_DISPATCH)))
591 	{
592 		CComPtr<IDispatch> spDispDest(varDest.pdispVal);
593 
594 		// special Handling for a JScriptValue object
595 #ifdef __MINGW32__
596 		CComQIPtr<IJScriptValueObject, &__uuidof(IJScriptValueObject)> spValueDest(spDispDest);
597 #else
598 		CComQIPtr<IJScriptValueObject> spValueDest(spDispDest);
599 #endif
600 		if (spValueDest)
601 		{
602 			VARIANT_BOOL varBool= VARIANT_FALSE;
603 			if( SUCCEEDED( hr= spValueDest->IsOutParam( &varBool) )
604 				&& varBool == VARIANT_TRUE  ||
605 				SUCCEEDED(hr= spValueDest->IsInOutParam( &varBool) )
606 				&& varBool == VARIANT_TRUE )
607 			{
608 				if( SUCCEEDED( spValueDest->Set( CComVariant(), *pSource)))
609 					ret= sal_True;
610 			}
611 		}
612 		else if (pDest->vt == VT_DISPATCH)// VT_DISPATCH -> JScript out param
613 		{
614 			// We use IDispatchEx because its GetDispID function causes the creation
615 			// of a property if it does not exist already. This is convenient for
616 			// out parameters in JScript. Then the user must not specify propery "0"
617 			// explicitly
618 #ifdef __MINGW32__
619 			CComQIPtr<IDispatchEx, &__uuidof(IDispatchEx)> spDispEx( spDispDest);
620 #else
621 			CComQIPtr<IDispatchEx> spDispEx( spDispDest);
622 #endif
623 			if( spDispEx)
624 			{
625 				CComBSTR nullProp(L"0");
626 				DISPID dwDispID;
627 				if( SUCCEEDED( spDispEx->GetDispID( nullProp, fdexNameEnsure, &dwDispID)))
628 				{
629 					DISPPARAMS dispparams = {NULL, NULL, 1, 1};
630 					dispparams.rgvarg = pSource;
631 					DISPID dispidPut = DISPID_PROPERTYPUT;
632 					dispparams.rgdispidNamedArgs = &dispidPut;
633 
634 					if (pSource->vt == VT_UNKNOWN || pSource->vt == VT_DISPATCH ||
635 						(pSource->vt & VT_ARRAY) || (pSource->vt & VT_BYREF))
636 						hr = spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
637 												&dispparams, NULL, NULL, NULL);
638 					else
639 						hr= spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
640 											   &dispparams, NULL, NULL, NULL);
641 					if( SUCCEEDED(hr))
642 						ret= sal_True;
643 				}
644 			}
645 		}
646 		else
647 			ret= writeBackOutParameter( pDest, pSource);
648 	}
649 	else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript
650 	{	// param. The function checks itself for correct VBScript params
651 		ret= writeBackOutParameter( pDest, pSource);
652 	}
653 	return ret;
654 }
655 // VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter.
656 // Thus we are in charge of freeing an eventual value contained by the inner VARIANT
657 // Please note: VariantCopy doesn't free a VT_BYREF value
658 // The out parameters are expected to have always a valid type
writeBackOutParameter(VARIANTARG * pDest,VARIANT * pSource)659 static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource)
660 {
661 	HRESULT hr;
662 	sal_Bool ret = FALSE;
663 	// Out parameter must be VT_BYREF
664 	if ((V_VT(pDest) & VT_BYREF) != 0 )
665 	{
666 		VARTYPE oleTypeFlags = V_VT(pSource);
667 
668 		// if caller accept VARIANT as out parameter, any value must be converted
669 		if (V_VT(pDest) == (VT_VARIANT | VT_BYREF))
670 		{
671 			// When the user provides a VARIANT rather then a concrete type
672 			// we just copy the source to the out, in/out parameter
673 			// VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that
674 			// is contained in pDest are released by VariantCopy
675 			VariantCopy(V_VARIANTREF(pDest), pSource);
676 			ret	= sal_True;
677 		}
678 		else
679 		{
680 			// variantarg and variant must have same type
681   			if ((V_VT(pDest) & oleTypeFlags) == oleTypeFlags)
682 			{
683 				if ((oleTypeFlags & VT_ARRAY) != 0)
684 				{
685 					// In / Out Param
686 					if( *V_ARRAYREF(pDest) != NULL)
687 						hr= SafeArrayCopyData( V_ARRAY(pSource), *V_ARRAYREF(pDest));
688 					else
689 						// Out Param
690 						hr= SafeArrayCopy(V_ARRAY(pSource), V_ARRAYREF(pDest)) == NOERROR;
691 					if( SUCCEEDED( hr))
692 						ret	= sal_True;
693 				}
694 				else
695 				{
696 					// copy base type
697 					switch (V_VT(pSource))
698 					{
699 					case VT_I2:
700 					{
701 						*V_I2REF(pDest) = V_I2(pSource);
702 						ret	= sal_True;
703 						break;
704 					}
705 					case VT_I4:
706 						*V_I4REF(pDest) = V_I4(pSource);
707 						ret	= sal_True;
708 						break;
709 					case VT_R4:
710 						*V_R4REF(pDest) = V_R4(pSource);
711 						ret	= sal_True;
712 						break;
713 					case VT_R8:
714 						*V_R8REF(pDest) = V_R8(pSource);
715 						ret	= sal_True;
716 						break;
717 					case VT_CY:
718 						*V_CYREF(pDest) = V_CY(pSource);
719 						ret	= sal_True;
720 						break;
721 					case VT_DATE:
722 						*V_DATEREF(pDest) = V_DATE(pSource);
723 						ret	= sal_True;
724 						break;
725 					case VT_BSTR:
726 						SysFreeString( *pDest->pbstrVal);
727 
728 						*V_BSTRREF(pDest) = SysAllocString(V_BSTR(pSource));
729 						ret	= sal_True;
730 						break;
731 					case VT_DISPATCH:
732 						if (*V_DISPATCHREF(pDest) != NULL)
733 							(*V_DISPATCHREF(pDest))->Release();
734 
735 						*V_DISPATCHREF(pDest) = V_DISPATCH(pSource);
736 
737 						if (*V_DISPATCHREF(pDest) != NULL)
738 							(*V_DISPATCHREF(pDest))->AddRef();
739 
740 						ret	= sal_True;
741 						break;
742 					case VT_ERROR:
743 						*V_ERRORREF(pDest) = V_ERROR(pSource);
744 						ret	= sal_True;
745 						break;
746 					case VT_BOOL:
747 						*V_BOOLREF(pDest) = V_BOOL(pSource);
748 						ret	= sal_True;
749 						break;
750 					case VT_UNKNOWN:
751 						if (*V_UNKNOWNREF(pDest) != NULL)
752 							(*V_UNKNOWNREF(pDest))->Release();
753 
754 						*V_UNKNOWNREF(pDest) = V_UNKNOWN(pSource);
755 
756 						if (*V_UNKNOWNREF(pDest) != NULL)
757 							(*V_UNKNOWNREF(pDest))->AddRef();
758 
759 						ret	= sal_True;
760 						break;
761 					case VT_I1:
762 						*V_I1REF(pDest) = V_I1(pSource);
763 						ret	= sal_True;
764 						break;
765 					case VT_UI1:
766 						*V_UI1REF(pDest) = V_UI1(pSource);
767 						ret	= sal_True;
768 						break;
769 					case VT_UI2:
770 						*V_UI2REF(pDest) = V_UI2(pSource);
771 						ret	= sal_True;
772 						break;
773 					case VT_UI4:
774 						*V_UI4REF(pDest) = V_UI4(pSource);
775 						ret	= sal_True;
776 						break;
777 					case VT_INT:
778 						*V_INTREF(pDest) = V_INT(pSource);
779 						ret	= sal_True;
780 						break;
781 					case VT_UINT:
782 						*V_UINTREF(pDest) = V_UINT(pSource);
783 						ret	= sal_True;
784 						break;
785 					case VT_DECIMAL:
786                         memcpy(pDest->pdecVal, pSource, sizeof(DECIMAL));
787                         ret = sal_True;
788                         break;
789 					default:
790 						break;
791 					}
792 				}
793 			}
794 			else
795 			{
796 				// Handling of special cases
797 				// Destination and source types are different
798 				if( pDest->vt == (VT_BSTR | VT_BYREF)
799 					&& pSource->vt == VT_I2)
800 				{
801 					// When the user provides a String as out our in/out parameter
802 					// and the type is char (TypeClass_CHAR) then we convert to a BSTR
803 					// instead of VT_I2 as is done otherwise
804 					OLECHAR buff[]= {0,0};
805 					buff[0]= pSource->iVal;
806 
807 					SysFreeString( *pDest->pbstrVal);
808 					*pDest->pbstrVal= SysAllocString( buff);
809 					ret = sal_True;
810 				}
811 			}
812 		}
813 	}
814 	return ret;
815 }
816 
Invoke(DISPID dispidMember,REFIID,LCID,unsigned short wFlags,DISPPARAMS * pdispparams,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,unsigned int * puArgErr)817 STDMETHODIMP InterfaceOleWrapper_Impl::Invoke(DISPID dispidMember,
818 											  REFIID /*riid*/,
819 											  LCID /*lcid*/,
820 											  unsigned short wFlags,
821                      						  DISPPARAMS * pdispparams,
822 											  VARIANT * pvarResult,
823 											  EXCEPINFO * pexcepinfo,
824                      						  unsigned int * puArgErr )
825 {
826 	HRESULT ret = S_OK;
827 
828     try
829     {
830         sal_Bool bHandled= sal_False;
831         ret= InvokeGeneral( dispidMember,  wFlags, pdispparams, pvarResult,  pexcepinfo,
832                             puArgErr, bHandled);
833         if( bHandled)
834             return ret;
835 
836         if ((dispidMember > 0) && ((size_t)dispidMember <= m_MemberInfos.size()) && m_xInvocation.is())
837         {
838             MemberInfo d = m_MemberInfos[dispidMember - 1];
839             DWORD flags = wFlags & d.flags;
840 
841             if (flags != 0)
842             {
843                 if ((flags & DISPATCH_METHOD) != 0)
844                 {
845                     if (pdispparams->cNamedArgs	> 0)
846                         ret = DISP_E_NONAMEDARGS;
847                     else
848                     {
849                         Sequence<Any> params;
850 
851                         convertDispparamsArgs(dispidMember, wFlags, pdispparams , params );
852 
853                         ret= doInvoke(pdispparams, pvarResult,
854                                       pexcepinfo, puArgErr, d.name, params);
855                     }
856                 }
857                 else if ((flags & DISPATCH_PROPERTYGET) != 0)
858                 {
859                     ret=  doGetProperty( pdispparams, pvarResult,
860                                          pexcepinfo, d.name);
861                 }
862                 else if ((flags & DISPATCH_PROPERTYPUT || flags & DISPATCH_PROPERTYPUTREF) != 0)
863                 {
864                     if (pdispparams->cArgs != 1)
865                         ret = DISP_E_BADPARAMCOUNT;
866                     else
867                     {
868                         Sequence<Any> params;
869                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
870                         if(params.getLength() > 0)
871                             ret= doSetProperty( pdispparams, pvarResult, pexcepinfo, puArgErr, d.name, params);
872                         else
873                             ret = DISP_E_BADVARTYPE;
874                     }
875                 }
876             }
877             else
878                 ret= DISP_E_MEMBERNOTFOUND;
879         }
880         else
881             ret = DISP_E_MEMBERNOTFOUND;
882     }
883     catch(BridgeRuntimeError& e)
884     {
885         writeExcepinfo(pexcepinfo, e.message);
886         ret = DISP_E_EXCEPTION;
887     }
888     catch(Exception& e)
889     {
890         OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n") +
891                                 e.Message;
892         writeExcepinfo(pexcepinfo, message);
893 		ret = DISP_E_EXCEPTION;
894     }
895 	catch(...)
896 	{
897         OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n"
898                                 "Unexpected exception");
899         writeExcepinfo(pexcepinfo, message);
900  		ret = DISP_E_EXCEPTION;
901 	}
902 
903 	return ret;
904 }
905 
doInvoke(DISPPARAMS * pdispparams,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,unsigned int * puArgErr,OUString & name,Sequence<Any> & params)906 HRESULT InterfaceOleWrapper_Impl::doInvoke( DISPPARAMS * pdispparams, VARIANT * pvarResult,
907 							  EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any>& params)
908 {
909 
910 
911 	HRESULT ret= S_OK;
912     try
913     {
914         Sequence<sal_Int16> 	outIndex;
915         Sequence<Any> 	outParams;
916         Any 				returnValue;
917 
918         if (pdispparams->cNamedArgs	> 0)
919             return DISP_E_NONAMEDARGS;
920 
921         // invoke method and take care of exceptions
922 		returnValue = m_xInvocation->invoke(name,
923 											params,
924 											outIndex,
925 											outParams);
926 
927         // try to write back out parameter
928         if (outIndex.getLength() > 0)
929         {
930             const sal_Int16* pOutIndex = outIndex.getConstArray();
931             const Any* pOutParams = outParams.getConstArray();
932 
933             for (sal_Int32 i = 0; i < outIndex.getLength(); i++)
934             {
935                 CComVariant variant;
936                 // Currently a Sequence is converted to an SafeArray of VARIANTs.
937                 anyToVariant( &variant, pOutParams[i]);
938 
939                 // out parameter need special handling if they are VT_DISPATCH
940                 // and used in JScript
941                 int outindex= pOutIndex[i];
942                 writeBackOutParameter2(&(pdispparams->rgvarg[pdispparams->cArgs - 1 - outindex]),
943                                        &variant );
944             }
945         }
946 
947         // write back return value
948         if (pvarResult != NULL)
949             anyToVariant(pvarResult, returnValue);
950     }
951 	catch(IllegalArgumentException & e) //XInvocation::invoke
952 	{
953         writeExcepinfo(pexcepinfo, e.Message);
954 		ret = DISP_E_TYPEMISMATCH;
955 	}
956 	catch(CannotConvertException & e) //XInvocation::invoke
957 	{
958         writeExcepinfo(pexcepinfo, e.Message);
959 		ret = mapCannotConvertException( e, puArgErr);
960 	}
961 	catch(InvocationTargetException &  e) //XInvocation::invoke
962 	{
963         const Any& org = e.TargetException;
964         Exception excTarget;
965         org >>= excTarget;
966         OUString message=
967             org.getValueType().getTypeName() + OUSTR(": ") + excTarget.Message;
968         writeExcepinfo(pexcepinfo, message);
969 		ret = DISP_E_EXCEPTION;
970 	}
971 	catch(NoSuchMethodException & e) //XInvocation::invoke
972 	{
973         writeExcepinfo(pexcepinfo, e.Message);
974 		ret = DISP_E_MEMBERNOTFOUND;
975 	}
976     catch(BridgeRuntimeError & e)
977     {
978         writeExcepinfo(pexcepinfo, e.message);
979         ret = DISP_E_EXCEPTION;
980     }
981     catch(Exception & e)
982     {
983         OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n") +
984                                 e.Message;
985         writeExcepinfo(pexcepinfo, message);
986         ret = DISP_E_EXCEPTION;
987     }
988     catch( ... )
989  	{
990         OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n"
991                                 "Unexpected exception");
992         writeExcepinfo(pexcepinfo, message);
993  		ret = DISP_E_EXCEPTION;
994  	}
995 	return ret;
996 }
997 
doGetProperty(DISPPARAMS *,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,OUString & name)998 HRESULT InterfaceOleWrapper_Impl::doGetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * pvarResult,
999 												EXCEPINFO * pexcepinfo, OUString& name)
1000 {
1001 	HRESULT ret= S_OK;
1002 
1003 	Any value;
1004 	try
1005 	{
1006 		Any returnValue = m_xInvocation->getValue( name);
1007 		// write back return value
1008 		if (pvarResult)
1009             anyToVariant(pvarResult, returnValue);
1010 	}
1011 	catch(UnknownPropertyException e) //XInvocation::getValue
1012 	{
1013         writeExcepinfo(pexcepinfo, e.Message);
1014 		ret = DISP_E_MEMBERNOTFOUND;
1015 	}
1016     catch(BridgeRuntimeError& e)
1017     {
1018         writeExcepinfo(pexcepinfo, e.message);
1019         ret = DISP_E_EXCEPTION;
1020     }
1021     catch(Exception& e)
1022     {
1023         OUString message= OUSTR("InterfaceOleWrapper_Impl::doGetProperty : \n") +
1024                                 e.Message;
1025         writeExcepinfo(pexcepinfo, message);
1026     }
1027 	catch( ... )
1028 	{
1029         OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n"
1030                                 "Unexpected exception");
1031         writeExcepinfo(pexcepinfo, message);
1032  		ret = DISP_E_EXCEPTION;
1033 	}
1034 	return  ret;
1035 }
1036 
doSetProperty(DISPPARAMS *,VARIANT *,EXCEPINFO * pexcepinfo,unsigned int * puArgErr,OUString & name,Sequence<Any> params)1037 HRESULT InterfaceOleWrapper_Impl::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1038 										EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any> params)
1039 {
1040 	HRESULT ret= S_OK;
1041 
1042 	try
1043 	{
1044 		m_xInvocation->setValue( name, params.getConstArray()[0]);
1045 	}
1046 	catch(UnknownPropertyException )
1047 	{
1048 		ret = DISP_E_MEMBERNOTFOUND;
1049 	}
1050 	catch(CannotConvertException e)
1051 	{
1052 		ret= mapCannotConvertException( e, puArgErr);
1053 	}
1054 	catch(InvocationTargetException e)
1055 	{
1056 		if (pexcepinfo != NULL)
1057 		{
1058 			Any org = e.TargetException;
1059 
1060 			pexcepinfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
1061 			pexcepinfo->bstrSource = SysAllocString(L"any ONE component");
1062 			pexcepinfo->bstrDescription = SysAllocString(
1063 				reinterpret_cast<LPCOLESTR>(org.getValueType().getTypeName().getStr()));
1064 		}
1065 		ret = DISP_E_EXCEPTION;
1066 	}
1067 	catch( ... )
1068 	{
1069 		ret= DISP_E_EXCEPTION;
1070 	}
1071 	return ret;
1072 }
1073 
InvokeGeneral(DISPID dispidMember,unsigned short wFlags,DISPPARAMS * pdispparams,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,unsigned int *,sal_Bool & bHandled)1074 HRESULT InterfaceOleWrapper_Impl::InvokeGeneral( DISPID dispidMember, unsigned short wFlags,
1075 	                     DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1076 	                     unsigned int * /*puArgErr*/, sal_Bool& bHandled)
1077 {
1078 	HRESULT ret= S_OK;
1079     try
1080     {
1081 // DISPID_VALUE | The DEFAULT Value is required in JScript when the situation
1082 // is that we put an object into an Array object ( out parameter). We have to return
1083 // IDispatch otherwise the object cannot be accessed from the Script.
1084         if( dispidMember == DISPID_VALUE && wFlags == DISPATCH_PROPERTYGET
1085             && m_defaultValueType != VT_EMPTY && pvarResult != NULL)
1086         {
1087             bHandled= sal_True;
1088             if( m_defaultValueType == VT_DISPATCH)
1089             {
1090                 pvarResult->vt= VT_DISPATCH;
1091                 pvarResult->pdispVal= static_cast<IDispatch*>( this);
1092                 AddRef();
1093                 ret= S_OK;
1094             }
1095         }
1096 // ---------
1097         // function: _GetValueObject
1098         else if( dispidMember == DISPID_JSCRIPT_VALUE_FUNC)
1099         {
1100             bHandled= sal_True;
1101             if( !pvarResult)
1102                 ret= E_POINTER;
1103             CComObject< JScriptValue>* pValue;
1104             if( SUCCEEDED( CComObject<JScriptValue>::CreateInstance( &pValue)))
1105             {
1106                 pValue->AddRef();
1107                 pvarResult->vt= VT_DISPATCH;
1108 #ifdef __MINGW32__
1109                 pvarResult->pdispVal= CComQIPtr<IDispatch, &__uuidof(IDispatch)>(pValue->GetUnknown());
1110 #else
1111                 pvarResult->pdispVal= CComQIPtr<IDispatch>(pValue->GetUnknown());
1112 #endif
1113                 ret= S_OK;
1114             }
1115             else
1116                 ret= DISP_E_EXCEPTION;
1117         }
1118         else if( dispidMember == DISPID_GET_STRUCT_FUNC)
1119         {
1120             bHandled= sal_True;
1121             sal_Bool bStruct= sal_False;
1122 
1123 
1124             Reference<XInterface> xIntCore=	m_smgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection"));
1125             Reference<XIdlReflection> xRefl( xIntCore, UNO_QUERY);
1126             if( xRefl.is() )
1127             {
1128                 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1129                 CComVariant arg;
1130                 if( pdispparams->cArgs == 1 && SUCCEEDED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])) )
1131                 {
1132                     Reference<XIdlClass> classStruct= xRefl->forName( reinterpret_cast<const sal_Unicode*>(arg.bstrVal));
1133                     if( classStruct.is())
1134                     {
1135                         Any anyStruct;
1136                         classStruct->createObject( anyStruct);
1137                         CComVariant var;
1138                         anyToVariant( &var, anyStruct );
1139 
1140                         if( var.vt == VT_DISPATCH)
1141                         {
1142                             VariantCopy( pvarResult, & var);
1143                             bStruct= sal_True;
1144                         }
1145                     }
1146                 }
1147             }
1148             ret= bStruct == sal_True ? S_OK : DISP_E_EXCEPTION;
1149         }
1150         else if (dispidMember == DISPID_CREATE_TYPE_FUNC)
1151         {
1152             bHandled= sal_True;
1153             if( !pvarResult)
1154                 ret= E_POINTER;
1155             // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
1156             CComVariant arg;
1157             if( pdispparams->cArgs != 1)
1158                 return DISP_E_BADPARAMCOUNT;
1159             if (FAILED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])))
1160                 return DISP_E_BADVARTYPE;
1161 
1162             //check if the provided name represents a valid type
1163             Type type;
1164             if (getType(arg.bstrVal, type) == false)
1165             {
1166                 writeExcepinfo(pexcepinfo,OUString(
1167                                    OUSTR("[automation bridge] A UNO type with the name ") +
1168                                    OUString(reinterpret_cast<const sal_Unicode*>(arg.bstrVal)) + OUSTR(" does not exist!")));
1169                 return DISP_E_EXCEPTION;
1170             }
1171 
1172             if (createUnoTypeWrapper(arg.bstrVal, pvarResult) == false)
1173             {
1174                 writeExcepinfo(pexcepinfo,OUSTR("[automation bridge] InterfaceOleWrapper_Impl::InvokeGeneral\n"
1175                                                 "Could not initialize UnoTypeWrapper object!"));
1176                 return DISP_E_EXCEPTION;
1177             }
1178         }
1179     }
1180     catch(BridgeRuntimeError & e)
1181     {
1182         writeExcepinfo(pexcepinfo, e.message);
1183         ret = DISP_E_EXCEPTION;
1184     }
1185     catch(Exception & e)
1186     {
1187         OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n") +
1188                                 e.Message;
1189         writeExcepinfo(pexcepinfo, message);
1190         ret = DISP_E_EXCEPTION;
1191     }
1192     catch( ... )
1193  	{
1194         OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n"
1195                                 "Unexpected exception");
1196         writeExcepinfo(pexcepinfo, message);
1197  		ret = DISP_E_EXCEPTION;
1198  	}
1199 	return ret;
1200 }
1201 
1202 
1203 
1204 
GetDispID(BSTR,DWORD,DISPID __RPC_FAR *)1205 STDMETHODIMP InterfaceOleWrapper_Impl::GetDispID(BSTR /*bstrName*/, DWORD /*grfdex*/, DISPID __RPC_FAR* /*pid*/)
1206 {
1207 	HRESULT ret = ResultFromScode(E_NOTIMPL);
1208 
1209 	return ret;
1210 }
1211 
InvokeEx(DISPID,LCID,WORD,DISPPARAMS __RPC_FAR *,VARIANT __RPC_FAR *,EXCEPINFO __RPC_FAR *,IServiceProvider __RPC_FAR *)1212 STDMETHODIMP InterfaceOleWrapper_Impl::InvokeEx(
1213 	/* [in] */ DISPID /*id*/,
1214 	/* [in] */ LCID /*lcid*/,
1215 	/* [in] */ WORD /*wFlags*/,
1216 	/* [in] */ DISPPARAMS __RPC_FAR* /*pdp*/,
1217 	/* [out] */ VARIANT __RPC_FAR* /*pvarRes*/,
1218 	/* [out] */ EXCEPINFO __RPC_FAR* /*pei*/,
1219 	/* [unique][in] */ IServiceProvider __RPC_FAR* /*pspCaller*/)
1220 {
1221 	HRESULT ret = ResultFromScode(E_NOTIMPL);
1222 
1223 	return ret;
1224 }
1225 
1226 
DeleteMemberByName(BSTR,DWORD)1227 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByName(
1228     /* [in] */ BSTR /*bstr*/,
1229     /* [in] */ DWORD /*grfdex*/)
1230 {
1231 	HRESULT ret = ResultFromScode(E_NOTIMPL);
1232 
1233 	return ret;
1234 }
1235 
DeleteMemberByDispID(DISPID)1236 STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByDispID(DISPID /*id*/)
1237 {
1238 	HRESULT ret = ResultFromScode(E_NOTIMPL);
1239 
1240 	return ret;
1241 }
1242 
GetMemberProperties(DISPID,DWORD,DWORD __RPC_FAR *)1243 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberProperties(
1244     /* [in] */ DISPID /*id*/,
1245     /* [in] */ DWORD /*grfdexFetch*/,
1246     /* [out] */ DWORD __RPC_FAR* /*pgrfdex*/)
1247 {
1248 	HRESULT ret = ResultFromScode(E_NOTIMPL);
1249 
1250 	return ret;
1251 }
1252 
GetMemberName(DISPID,BSTR __RPC_FAR *)1253 STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberName(
1254     /* [in] */ DISPID /*id*/,
1255     /* [out] */ BSTR __RPC_FAR* /*pbstrName*/)
1256 {
1257 	HRESULT ret = ResultFromScode(E_NOTIMPL);
1258 
1259 	return ret;
1260 }
1261 
GetNextDispID(DWORD,DISPID,DISPID __RPC_FAR *)1262 STDMETHODIMP InterfaceOleWrapper_Impl::GetNextDispID(
1263     /* [in] */ DWORD /*grfdex*/,
1264     /* [in] */ DISPID /*id*/,
1265     /* [out] */ DISPID __RPC_FAR* /*pid*/)
1266 {
1267 	HRESULT ret = ResultFromScode(E_NOTIMPL);
1268 
1269 	return ret;
1270 }
1271 
GetNameSpaceParent(IUnknown __RPC_FAR * __RPC_FAR *)1272 STDMETHODIMP InterfaceOleWrapper_Impl::GetNameSpaceParent(
1273     /* [out] */ IUnknown __RPC_FAR *__RPC_FAR* /*ppunk*/)
1274 {
1275 	HRESULT ret = ResultFromScode(E_NOTIMPL);
1276 
1277 	return ret;
1278 }
1279 
1280 
1281 /*************************************************************************
1282 
1283 	UnoObjectWrapperRemoteOpt
1284 
1285 *************************************************************************/
UnoObjectWrapperRemoteOpt(Reference<XMultiServiceFactory> & aFactory,sal_uInt8 unoWrapperClass,sal_uInt8 comWrapperClass)1286 UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference<XMultiServiceFactory>& aFactory,
1287 													 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
1288 InterfaceOleWrapper_Impl( aFactory, unoWrapperClass, comWrapperClass),
1289 m_currentId(1)
1290 
1291 {
1292 }
~UnoObjectWrapperRemoteOpt()1293 UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt()
1294 {
1295 }
1296 
1297 // UnoConversionUtilities
createUnoWrapperInstance()1298 Reference< XInterface > UnoObjectWrapperRemoteOpt::createUnoWrapperInstance()
1299 {
1300 	Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
1301 												 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1302 	return Reference<XInterface>( xWeak, UNO_QUERY);
1303 }
1304 
GetIDsOfNames(REFIID,OLECHAR ** rgszNames,unsigned int cNames,LCID,DISPID * rgdispid)1305 STDMETHODIMP  UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID /*riid*/, OLECHAR ** rgszNames, unsigned int cNames,
1306 								LCID /*lcid*/, DISPID * rgdispid )
1307 {
1308 	MutexGuard guard( getBridgeMutex());
1309 
1310 	if( ! rgdispid)
1311 		return E_POINTER;
1312 	HRESULT ret = E_UNEXPECTED;
1313 	// ----------------------------------------
1314 	// _GetValueObject
1315 	if( ! wcscmp( *rgszNames, JSCRIPT_VALUE_FUNC))
1316 	{
1317 		*rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
1318 		return S_OK;
1319 	}
1320 	else if( ! wcscmp( *rgszNames, GET_STRUCT_FUNC))
1321 	{
1322 		*rgdispid= DISPID_GET_STRUCT_FUNC;
1323 		return S_OK;
1324 	}
1325 
1326 	// ----------------------------------------
1327 	if (m_xInvocation.is() && (cNames > 0))
1328 	{
1329 		OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0]));
1330 		// has this name been determined as "bad"
1331 		BadNameMap::iterator badIter= m_badNameMap.find( name);
1332 		if( badIter == m_badNameMap.end() )
1333 		{
1334 			// name has not been bad before( member exists
1335 			typedef NameToIdMap::iterator ITnames;
1336 			pair< ITnames, bool > pair_id= m_nameToDispIdMap.insert( NameToIdMap::value_type(name, m_currentId++));
1337 			// new ID inserted ?
1338 			if( pair_id.second )
1339 			{// yes, now create MemberInfo and ad to IdToMemberInfoMap
1340 				MemberInfo d(0, name);
1341 				m_idToMemberInfoMap.insert( IdToMemberInfoMap::value_type( m_currentId - 1, d));
1342 			}
1343 
1344 			*rgdispid = pair_id.first->second;
1345 			ret = S_OK;
1346 		}
1347 		else
1348 			ret= DISP_E_UNKNOWNNAME;
1349 	}
1350 	return ret;
1351 }
1352 
Invoke(DISPID dispidMember,REFIID,LCID,unsigned short wFlags,DISPPARAMS * pdispparams,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,unsigned int * puArgErr)1353 STDMETHODIMP  UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember, REFIID /*riid*/, LCID /*lcid*/, unsigned short wFlags,
1354 	                     DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
1355 	                     unsigned int * puArgErr )
1356 {
1357 	HRESULT ret = S_OK;
1358     try
1359     {
1360         sal_Bool bHandled= sal_False;
1361         ret= InvokeGeneral( dispidMember,  wFlags, pdispparams, pvarResult,  pexcepinfo,
1362                             puArgErr, bHandled);
1363         if( bHandled)
1364             return ret;
1365 
1366         if ( dispidMember > 0  && m_xInvocation.is())
1367         {
1368 
1369             IdToMemberInfoMap::iterator it_MemberInfo= m_idToMemberInfoMap.find( dispidMember);
1370             if( it_MemberInfo != m_idToMemberInfoMap.end() )
1371             {
1372                 MemberInfo& info= it_MemberInfo->second;
1373 
1374                 Sequence<Any> params; // holds converted any s
1375                 if( ! info.flags )
1376                 { // DISPID called for the first time
1377                     if( wFlags == DISPATCH_METHOD )
1378                     {
1379                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1380 
1381                         if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1382                                                    pexcepinfo, puArgErr, info.name, params))
1383                             && ret == DISP_E_MEMBERNOTFOUND)
1384                         {
1385                             // try to get the exact name
1386                             OUString exactName;
1387                             if (m_xExactName.is())
1388                             {
1389                                 exactName = m_xExactName->getExactName( info.name);
1390                                 // invoke again
1391                                 if( exactName.getLength() != 0)
1392                                 {
1393                                     if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1394                                                                   pexcepinfo, puArgErr, exactName, params)))
1395                                         info.name= exactName;
1396                                 }
1397                             }
1398                         }
1399                         if( SUCCEEDED( ret ) )
1400                             info.flags= DISPATCH_METHOD;
1401                     } //if( wFlags == DISPATCH_METHOD )
1402 
1403                     else if( wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_PROPERTYPUTREF)
1404                     {
1405                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1406                         if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1407                                                         pexcepinfo, puArgErr, info.name, params))
1408                             && ret == DISP_E_MEMBERNOTFOUND)
1409                         {
1410                             // try to get the exact name
1411                             OUString exactName;
1412                             if (m_xExactName.is())
1413                             {
1414                                 exactName = m_xExactName->getExactName( info.name);
1415                                 // invoke again
1416                                 if( exactName.getLength() != 0)
1417                                 {
1418                                     if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1419                                                                        pexcepinfo, puArgErr, exactName, params)))
1420                                         info.name= exactName;
1421                                 }
1422                             }
1423                         }
1424                         if( SUCCEEDED( ret ) )
1425                             info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1426                     }
1427 
1428                     else if( wFlags == DISPATCH_PROPERTYGET)
1429                     {
1430                         if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1431                                                         pexcepinfo, info.name))
1432                             && ret == DISP_E_MEMBERNOTFOUND)
1433                         {
1434                             // try to get the exact name
1435                             OUString exactName;
1436                             if (m_xExactName.is())
1437                             {
1438                                 exactName = m_xExactName->getExactName( info.name);
1439                                 // invoke again
1440                                 if( exactName.getLength() != 0)
1441                                 {
1442                                     if( SUCCEEDED( ret= doGetProperty( pdispparams, pvarResult,
1443                                                                        pexcepinfo, exactName)))
1444                                         info.name= exactName;
1445                                 }
1446                             }
1447                         }
1448                         if( SUCCEEDED( ret ) )
1449                             info.flags= DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT;
1450                     }
1451                     else if( wFlags & DISPATCH_METHOD &&
1452                              (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF))
1453                     {
1454 
1455                         OUString exactName;
1456                         // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT
1457                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1458                         // try first as method
1459                         if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1460                                                    pexcepinfo, puArgErr, info.name, params))
1461                             && ret == DISP_E_MEMBERNOTFOUND)
1462                         {
1463                             // try to get the exact name
1464                             if (m_xExactName.is())
1465                             {
1466                                 exactName = m_xExactName->getExactName( info.name);
1467                                 // invoke again
1468                                 if( exactName.getLength() != 0)
1469                                 {
1470                                     if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1471                                                                   pexcepinfo, puArgErr, exactName, params)))
1472                                         info.name= exactName;
1473                                 }
1474                             }
1475                         }
1476                         if( SUCCEEDED( ret ) )
1477                             info.flags= DISPATCH_METHOD;
1478 
1479                         // try as property
1480 						if( FAILED( ret) && pdispparams->cArgs == 1)
1481 						{
1482 							if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
1483                                                             pexcepinfo, puArgErr, info.name, params))
1484                                 && ret == DISP_E_MEMBERNOTFOUND)
1485 							{
1486 								// try to get the exact name
1487 								if( exactName.getLength() != 0)
1488 								{
1489 									if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1490                                                                        pexcepinfo, puArgErr, exactName, params)))
1491                                         info.name= exactName;
1492 								}
1493 							}
1494 							if( SUCCEEDED( ret ) )
1495 								info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
1496 						}
1497                     }
1498                     else if( wFlags & DISPATCH_METHOD && wFlags & DISPATCH_PROPERTYGET)
1499                     {
1500                         OUString exactName;
1501                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1502 
1503                         if( FAILED( ret= doInvoke( pdispparams, pvarResult,
1504                                                    pexcepinfo, puArgErr, info.name, params))
1505                             && ret == DISP_E_MEMBERNOTFOUND)
1506                         {
1507                             // try to get the exact name
1508                             if (m_xExactName.is())
1509                             {
1510                                 exactName = m_xExactName->getExactName( info.name);
1511                                 // invoke again
1512                                 if( exactName.getLength() != 0)
1513                                 {
1514                                     if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
1515                                                                   pexcepinfo, puArgErr, exactName, params)))
1516                                         info.name= exactName;
1517                                 }
1518                             }
1519                         }
1520                         if( SUCCEEDED( ret ) )
1521                             info.flags= DISPATCH_METHOD;
1522 
1523                         // try as property
1524                         if( FAILED( ret) && pdispparams->cArgs == 1)
1525                         {
1526                             if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
1527                                                             pexcepinfo, info.name))
1528                                 && ret == DISP_E_MEMBERNOTFOUND)
1529                             {
1530                                 if( exactName.getLength() != 0)
1531                                 {
1532                                     if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
1533                                                                        pexcepinfo, puArgErr, exactName, params)))
1534                                         info.name= exactName;
1535                                 }
1536                             }
1537                             if( SUCCEEDED( ret ) )
1538                                 info.flags= DISPATCH_PROPERTYGET;
1539                         }
1540                     }
1541 
1542                     // update �nformation about this member
1543                     if( ret == DISP_E_MEMBERNOTFOUND)
1544                     {
1545                         // Remember the name as not existing
1546                         // and remove the MemberInfo
1547                         m_badNameMap[info.name]= sal_False;
1548                         m_idToMemberInfoMap.erase( it_MemberInfo);
1549                     }
1550                 } // if( ! info.flags )
1551                 else // IdToMemberInfoMap contains a MemberInfo
1552                 {
1553                     if( wFlags & DISPATCH_METHOD && info.flags == DISPATCH_METHOD)
1554                     {
1555                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1556 						ret= doInvoke( pdispparams, pvarResult,
1557                                        pexcepinfo, puArgErr, info.name, params);
1558                     }
1559                     else if( (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF )  &&
1560                              info.flags & DISPATCH_PROPERTYPUT)
1561                     {
1562                         convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1563                         ret= doSetProperty( pdispparams, pvarResult,
1564                                             pexcepinfo, puArgErr, info.name, params);
1565                     }
1566                     else if( (wFlags & DISPATCH_PROPERTYGET) && ( info.flags & DISPATCH_PROPERTYGET))
1567                     {
1568                         ret= doGetProperty( pdispparams, pvarResult,
1569                                             pexcepinfo, info.name);
1570                     }
1571                     else
1572                     {
1573                         ret= DISP_E_MEMBERNOTFOUND;
1574                     }
1575                 }
1576             }//		if( it_MemberInfo != m_idToMemberInfoMap.end() )
1577             else
1578                 ret= DISP_E_MEMBERNOTFOUND;
1579         }
1580     }
1581     catch(BridgeRuntimeError& e)
1582     {
1583         writeExcepinfo(pexcepinfo, e.message);
1584         ret = DISP_E_EXCEPTION;
1585     }
1586     catch(Exception& e)
1587     {
1588         OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n") +
1589             e.Message;
1590             writeExcepinfo(pexcepinfo, message);
1591             ret = DISP_E_EXCEPTION;
1592     }
1593     catch(...)
1594     {
1595         OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n"
1596                                 "Unexpected exception");
1597         writeExcepinfo(pexcepinfo, message);
1598         ret = DISP_E_EXCEPTION;
1599     }
1600 
1601     return ret;
1602 }
1603 
methodInvoke(DISPID,DISPPARAMS *,VARIANT *,EXCEPINFO *,unsigned int *,Sequence<Any> params)1604 HRESULT	UnoObjectWrapperRemoteOpt::methodInvoke( DISPID /*dispidMember*/, DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
1605 							  EXCEPINFO * /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence<Any> params)
1606 {
1607 	return S_OK;
1608 }
1609 
1610 
1611 // The returned HRESULT is only appropriate for IDispatch::Invoke
mapCannotConvertException(CannotConvertException e,unsigned int * puArgErr)1612 static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr)
1613 {
1614 	HRESULT ret;
1615 	sal_Bool bWriteIndex= sal_True;
1616 
1617 	switch ( e.Reason)
1618 	{
1619 		case FailReason::OUT_OF_RANGE:
1620 			ret = DISP_E_OVERFLOW;
1621 			break;
1622 		case FailReason::IS_NOT_NUMBER:
1623 			ret = DISP_E_TYPEMISMATCH;
1624 			break;
1625 		case FailReason::IS_NOT_ENUM:
1626 			ret = DISP_E_TYPEMISMATCH;
1627 			break;
1628 		case FailReason::IS_NOT_BOOL:
1629 			ret = DISP_E_TYPEMISMATCH;
1630 			break;
1631 		case FailReason::NO_SUCH_INTERFACE:
1632 			ret = DISP_E_TYPEMISMATCH;
1633 			break;
1634 		case FailReason::SOURCE_IS_NO_DERIVED_TYPE:
1635 			ret = DISP_E_TYPEMISMATCH;
1636 			break;
1637 		case FailReason::TYPE_NOT_SUPPORTED:
1638 			ret = DISP_E_TYPEMISMATCH;
1639 			break;
1640 		case FailReason::INVALID:
1641 			ret = DISP_E_TYPEMISMATCH;
1642 			break;
1643 		case FailReason::NO_DEFAULT_AVAILABLE:
1644 			ret = DISP_E_BADPARAMCOUNT;
1645 			break;
1646 		case FailReason::UNKNOWN:
1647 			ret = E_UNEXPECTED;
1648 			break;
1649 		default:
1650 			ret = E_UNEXPECTED;
1651 			bWriteIndex= sal_False;
1652 			break;
1653 	}
1654 
1655 	if( bWriteIndex &&  puArgErr != NULL)
1656 		*puArgErr = e.ArgumentIndex;
1657 	return ret;
1658 }
1659 
1660 // The function maps the TypeClass of the any to VARTYPE: If
1661 // the Any contains STRUCT or INTERFACE then the return value
1662 // is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper
1663 // and the result is put into the constructor of the uno - wrapper
1664 // object. If a client asks the object for DISPID_VALUE and this
1665 // funtion returned VT_DISPATCH then the IDispatch of the same
1666 // object is being returned.
1667 // See InterfaceOleWrapper_Impl::Invoke, InterfaceOleWrapper_Impl::m_defaultValueType
getVarType(const Any & value)1668 const VARTYPE getVarType( const Any& value)
1669 {
1670 	VARTYPE ret= VT_EMPTY;
1671 
1672 	switch ( value.getValueTypeClass())
1673 	{
1674 	case TypeClass_STRUCT: ret= VT_DISPATCH; break;
1675 	case TypeClass_INTERFACE: ret= VT_DISPATCH; break;
1676 	default: break;
1677 	}
1678 	return ret;
1679 }
1680 
1681 
1682 
1683 
1684 } // end namespace
1685