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