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