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 #include "ole2uno.hxx"
27 #include "rtl/ustrbuf.hxx"
28
29
30 #include "osl/diagnose.h"
31 #include "osl/doublecheckedlocking.h"
32 #include "osl/thread.h"
33
34 #include "boost/scoped_array.hpp"
35 #include <com/sun/star/script/FailReason.hpp>
36 #include <com/sun/star/beans/XMaterialHolder.hpp>
37 #include <com/sun/star/script/XTypeConverter.hpp>
38 #include <com/sun/star/script/FinishEngineEvent.hpp>
39 #include <com/sun/star/script/InterruptReason.hpp>
40 #include <com/sun/star/script/XEngineListener.hpp>
41 #include <com/sun/star/script/XDebugging.hpp>
42 #include <com/sun/star/script/XInvocation.hpp>
43 #include <com/sun/star/script/ContextInformation.hpp>
44 #include <com/sun/star/script/FinishReason.hpp>
45 #include <com/sun/star/script/XEngine.hpp>
46 #include <com/sun/star/script/InterruptEngineEvent.hpp>
47 #include <com/sun/star/script/XLibraryAccess.hpp>
48 #include <com/sun/star/bridge/ModelDependent.hpp>
49
50 #include "com/sun/star/bridge/oleautomation/NamedArgument.hpp"
51 #include "com/sun/star/bridge/oleautomation/PropertyPutArgument.hpp"
52
53 #include <typelib/typedescription.hxx>
54 #include <rtl/uuid.h>
55 #include <rtl/memory.h>
56 #include <rtl/ustring.hxx>
57
58 #include "jscriptclasses.hxx"
59
60 #include "oleobjw.hxx"
61 #include "unoobjw.hxx"
62 #include <stdio.h>
63 using namespace std;
64 using namespace boost;
65 using namespace osl;
66 using namespace rtl;
67 using namespace cppu;
68 using namespace com::sun::star::script;
69 using namespace com::sun::star::lang;
70 using namespace com::sun::star::bridge;
71 using namespace com::sun::star::bridge::oleautomation;
72 using namespace com::sun::star::bridge::ModelDependent;
73 using namespace ::com::sun::star;
74
75 #define JSCRIPT_ID_PROPERTY L"_environment"
76 #define JSCRIPT_ID L"jscript"
77 namespace ole_adapter
78 {
79
80
81 // key: XInterface pointer created by Invocation Adapter Factory
82 // value: XInterface pointer to the wrapper class.
83 // Entries to the map are made within
84 // Any createOleObjectWrapper(IUnknown* pUnknown, const Type& aType);
85 // Entries are being deleted if the wrapper class's destructor has been
86 // called.
87 // Before UNO object is wrapped to COM object this map is checked
88 // to see if the UNO object is already a wrapper.
89 hash_map<sal_uInt32, sal_uInt32> AdapterToWrapperMap;
90 // key: XInterface of the wrapper object.
91 // value: XInterface of the Interface created by the Invocation Adapter Factory.
92 // A COM wrapper is responsible for removing the corresponding entry
93 // in AdapterToWrappperMap if it is being destroyed. Because the wrapper does not
94 // know about its adapted interface it uses WrapperToAdapterMap to get the
95 // adapted interface which is then used to locate the entry in AdapterToWrapperMap.
96 hash_map<sal_uInt32,sal_uInt32> WrapperToAdapterMap;
97
98 hash_map<sal_uInt32, WeakReference<XInterface> > ComPtrToWrapperMap;
99 /*****************************************************************************
100
101 class implementation IUnknownWrapper_Impl
102
103 *****************************************************************************/
104
IUnknownWrapper_Impl(Reference<XMultiServiceFactory> & xFactory,sal_uInt8 unoWrapperClass,sal_uInt8 comWrapperClass)105 IUnknownWrapper_Impl::IUnknownWrapper_Impl( Reference<XMultiServiceFactory>& xFactory,
106 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
107 UnoConversionUtilities<IUnknownWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass),
108 m_pxIdlClass( NULL), m_eJScript( JScriptUndefined),
109 m_bComTlbIndexInit(false), m_bHasDfltMethod(false), m_bHasDfltProperty(false)
110 {
111 }
112
113
~IUnknownWrapper_Impl()114 IUnknownWrapper_Impl::~IUnknownWrapper_Impl()
115 {
116 o2u_attachCurrentThread();
117 MutexGuard guard(getBridgeMutex());
118 XInterface * xIntRoot = (OWeakObject *)this;
119 #if OSL_DEBUG_LEVEL > 0
120 acquire(); // make sure we don't delete us twice because of Reference
121 OSL_ASSERT( Reference<XInterface>( static_cast<XWeak*>(this), UNO_QUERY).get() == xIntRoot );
122 #endif
123
124 // remove entries in global maps
125 typedef hash_map<sal_uInt32, sal_uInt32>::iterator _IT;
126 _IT it= WrapperToAdapterMap.find( (sal_uInt32) xIntRoot);
127 if( it != WrapperToAdapterMap.end())
128 {
129 sal_uInt32 adapter= it->second;
130
131 AdapterToWrapperMap.erase( adapter);
132 WrapperToAdapterMap.erase( it);
133 }
134
135 IT_Com it_c= ComPtrToWrapperMap.find( (sal_uInt32) m_spUnknown.p);
136 if(it_c != ComPtrToWrapperMap.end())
137 ComPtrToWrapperMap.erase(it_c);
138
139 #if OSL_DEBUG_LEVEL > 0
140 fprintf(stderr,"[automation bridge] ComPtrToWrapperMap contains: %i \n",
141 ComPtrToWrapperMap.size());
142 #endif
143 }
144
queryInterface(const Type & t)145 Any IUnknownWrapper_Impl::queryInterface(const Type& t)
146 throw (RuntimeException)
147 {
148 if (t == getCppuType(static_cast<Reference<XDefaultMethod>*>( 0)) && !m_bHasDfltMethod )
149 return Any();
150 if (t == getCppuType(static_cast<Reference<XDefaultProperty>*>( 0)) && !m_bHasDfltProperty )
151 return Any();
152 if (t == getCppuType(static_cast<Reference<XInvocation>*>( 0)) && !m_spDispatch)
153 return Any();
154
155 return WeakImplHelper7<XInvocation, XBridgeSupplier2,
156 XInitialization, XAutomationObject, XDefaultProperty, XDefaultMethod, XDirectInvocation>::queryInterface(t);
157 }
158
getIntrospection(void)159 Reference<XIntrospectionAccess> SAL_CALL IUnknownWrapper_Impl::getIntrospection(void)
160 throw (RuntimeException )
161 {
162 Reference<XIntrospectionAccess> ret;
163
164 return ret;
165 }
166
167
168
invoke(const OUString & aFunctionName,const Sequence<Any> & aParams,Sequence<sal_Int16> & aOutParamIndex,Sequence<Any> & aOutParam)169 Any SAL_CALL IUnknownWrapper_Impl::invoke( const OUString& aFunctionName,
170 const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex,
171 Sequence< Any >& aOutParam )
172 throw(IllegalArgumentException, CannotConvertException, InvocationTargetException,
173 RuntimeException)
174 {
175 if ( ! m_spDispatch )
176 {
177 throw RuntimeException(
178 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
179 Reference<XInterface>());
180 }
181
182 Any ret;
183
184 try
185 {
186 o2u_attachCurrentThread();
187
188 TypeDescription methodDesc;
189 getMethodInfo(aFunctionName, methodDesc);
190 if( methodDesc.is())
191 {
192 ret = invokeWithDispIdUnoTlb(aFunctionName,
193 aParams,
194 aOutParamIndex,
195 aOutParam);
196 }
197 else
198 {
199 ret= invokeWithDispIdComTlb( aFunctionName,
200 aParams,
201 aOutParamIndex,
202 aOutParam);
203 }
204 }
205 catch (IllegalArgumentException &)
206 {
207 throw;
208 }
209 catch (CannotConvertException &)
210 {
211 throw;
212 }
213 catch (BridgeRuntimeError & e)
214 {
215 throw RuntimeException(e.message, Reference<XInterface>());
216 }
217 catch (Exception & e)
218 {
219 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
220 "IUnknownWrapper_Impl::invoke ! Message : \n") +
221 e.Message, Reference<XInterface>());
222
223 }
224 catch(...)
225 {
226 throw RuntimeException(
227 OUSTR("[automation bridge] unexpected exception in "
228 "IUnknownWrapper_Impl::Invoke !"), Reference<XInterface>());
229 }
230 return ret;
231 }
232
setValue(const OUString & aPropertyName,const Any & aValue)233 void SAL_CALL IUnknownWrapper_Impl::setValue( const OUString& aPropertyName,
234 const Any& aValue )
235 throw(UnknownPropertyException, CannotConvertException, InvocationTargetException,
236 RuntimeException)
237 {
238 if ( ! m_spDispatch )
239 {
240 throw RuntimeException(
241 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
242 Reference<XInterface>());
243 }
244 try
245 {
246 o2u_attachCurrentThread();
247
248 ITypeInfo * pInfo = getTypeInfo();
249 FuncDesc aDescGet(pInfo);
250 FuncDesc aDescPut(pInfo);
251 VarDesc aVarDesc(pInfo);
252 getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc);
253 //check if there is such a property at all or if it is read only
254 if ( ! aDescPut && ! aDescGet && ! aVarDesc)
255 {
256 OUString msg(OUSTR("[automation bridge]Property \"") + aPropertyName +
257 OUSTR("\" is not supported"));
258 throw UnknownPropertyException(msg, Reference<XInterface>());
259 }
260
261 if ( (! aDescPut && aDescGet) || aVarDesc
262 && aVarDesc->wVarFlags == VARFLAG_FREADONLY )
263 {
264 //read-only
265 OUString msg(OUSTR("[automation bridge] Property ") + aPropertyName +
266 OUSTR(" is read-only"));
267 OString sMsg = OUStringToOString(msg, osl_getThreadTextEncoding());
268 OSL_ENSURE(0, sMsg.getStr());
269 // ignore silently
270 return;
271 }
272
273 HRESULT hr= S_OK;
274 DISPPARAMS dispparams;
275 CComVariant varArg;
276 CComVariant varRefArg;
277 CComVariant varResult;
278 ExcepInfo excepinfo;
279 unsigned int uArgErr;
280
281 // converting UNO value to OLE variant
282 DISPID dispidPut= DISPID_PROPERTYPUT;
283 dispparams.rgdispidNamedArgs = &dispidPut;
284 dispparams.cArgs = 1;
285 dispparams.cNamedArgs = 1;
286 dispparams.rgvarg = & varArg;
287
288 OSL_ASSERT(aDescPut || aVarDesc);
289
290 VARTYPE vt = 0;
291 DISPID dispid = 0;
292 INVOKEKIND invkind = INVOKE_PROPERTYPUT;
293 //determine the expected type, dispid, invoke kind (DISPATCH_PROPERTYPUT,
294 //DISPATCH_PROPERTYPUTREF)
295 if (aDescPut)
296 {
297 vt = getElementTypeDesc(& aDescPut->lprgelemdescParam[0].tdesc);
298 dispid = aDescPut->memid;
299 invkind = aDescPut->invkind;
300 }
301 else
302 {
303 vt = getElementTypeDesc( & aVarDesc->elemdescVar.tdesc);
304 dispid = aVarDesc->memid;
305 if (vt == VT_UNKNOWN || vt == VT_DISPATCH ||
306 (vt & VT_ARRAY) || (vt & VT_BYREF))
307 {
308 invkind = INVOKE_PROPERTYPUTREF;
309 }
310 }
311
312 // convert the uno argument
313 if (vt & VT_BYREF)
314 {
315 anyToVariant( & varRefArg, aValue, ::sal::static_int_cast< VARTYPE, int >( vt ^ VT_BYREF ) );
316 varArg.vt = vt;
317 if( (vt & VT_TYPEMASK) == VT_VARIANT)
318 varArg.byref = & varRefArg;
319 else if ((vt & VT_TYPEMASK) == VT_DECIMAL)
320 varArg.byref = & varRefArg.decVal;
321 else
322 varArg.byref = & varRefArg.byref;
323 }
324 else
325 {
326 anyToVariant(& varArg, aValue, vt);
327 }
328 // call to IDispatch
329 hr = m_spDispatch->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, ::sal::static_int_cast< WORD, INVOKEKIND >( invkind ),
330 &dispparams, & varResult, & excepinfo, &uArgErr);
331
332 // lookup error code
333 switch (hr)
334 {
335 case S_OK:
336 break;
337 case DISP_E_BADPARAMCOUNT:
338 throw RuntimeException();
339 break;
340 case DISP_E_BADVARTYPE:
341 throw RuntimeException();
342 break;
343 case DISP_E_EXCEPTION:
344 throw InvocationTargetException();
345 break;
346 case DISP_E_MEMBERNOTFOUND:
347 throw UnknownPropertyException();
348 break;
349 case DISP_E_NONAMEDARGS:
350 throw RuntimeException();
351 break;
352 case DISP_E_OVERFLOW:
353 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
354 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
355 break;
356 case DISP_E_PARAMNOTFOUND:
357 throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
358 static_cast<XWeak*>(this)), ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )) ;
359 break;
360 case DISP_E_TYPEMISMATCH:
361 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
362 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::UNKNOWN, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
363 break;
364 case DISP_E_UNKNOWNINTERFACE:
365 throw RuntimeException();
366 break;
367 case DISP_E_UNKNOWNLCID:
368 throw RuntimeException();
369 break;
370 case DISP_E_PARAMNOTOPTIONAL:
371 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface*>(
372 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
373 break;
374 default:
375 throw RuntimeException();
376 break;
377 }
378 }
379 catch (CannotConvertException &)
380 {
381 throw;
382 }
383 catch (UnknownPropertyException &)
384 {
385 throw;
386 }
387 catch (BridgeRuntimeError& e)
388 {
389 throw RuntimeException(
390 e.message, Reference<XInterface>());
391 }
392 catch (Exception & e)
393 {
394 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
395 "IUnknownWrapper_Impl::setValue ! Message : \n") +
396 e.Message, Reference<XInterface>());
397
398 }
399 catch (...)
400 {
401 throw RuntimeException(
402 OUSTR("[automation bridge] unexpected exception in "
403 "IUnknownWrapper_Impl::setValue !"), Reference<XInterface>());
404 }
405 }
406
getValue(const OUString & aPropertyName)407 Any SAL_CALL IUnknownWrapper_Impl::getValue( const OUString& aPropertyName )
408 throw(UnknownPropertyException, RuntimeException)
409 {
410 if ( ! m_spDispatch )
411 {
412 throw RuntimeException(
413 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
414 Reference<XInterface>());
415 }
416 Any ret;
417 try
418 {
419 o2u_attachCurrentThread();
420 ITypeInfo * pInfo = getTypeInfo();
421 // I was going to implement an XServiceInfo interface to allow the type
422 // of the automation object to be exposed.. but it seems
423 // from looking at comments in the code that it is possible for
424 // this object to actually wrap an UNO object ( I guess if automation is
425 // used from MSO to create Openoffice objects ) Therefore, those objects
426 // will more than likely already have their own XServiceInfo interface.
427 // Instead here I chose a name that should be illegal both in COM and
428 // UNO ( from an IDL point of view ) therefore I think this is a safe
429 // hack
430 if ( aPropertyName.equals( rtl::OUString::createFromAscii("$GetTypeName") ))
431 {
432 if ( pInfo && m_sTypeName.getLength() == 0 )
433 {
434 m_sTypeName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("IDispatch") );
435 CComBSTR sName;
436
437 if ( SUCCEEDED( pInfo->GetDocumentation( -1, &sName, NULL, NULL, NULL ) ) )
438 {
439 rtl::OUString sTmp( reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName)));
440 if ( sTmp.indexOf('_') == 0 )
441 sTmp = sTmp.copy(1);
442 // do we own the memory for pTypeLib, msdn doco is vague
443 // I'll assume we do
444 CComPtr< ITypeLib > pTypeLib;
445 unsigned int index;
446 if ( SUCCEEDED( pInfo->GetContainingTypeLib( &pTypeLib.p, &index )) )
447 {
448 if ( SUCCEEDED( pTypeLib->GetDocumentation( -1, &sName, NULL, NULL, NULL ) ) )
449 {
450 rtl::OUString sLibName( reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName)));
451 m_sTypeName = sLibName.concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".") ) ).concat( sTmp );
452
453 }
454 }
455 }
456
457 }
458 ret <<= m_sTypeName;
459 return ret;
460 }
461 FuncDesc aDescGet(pInfo);
462 FuncDesc aDescPut(pInfo);
463 VarDesc aVarDesc(pInfo);
464 getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc);
465 if ( ! aDescGet && ! aDescPut && ! aVarDesc)
466 {
467 //property not found
468 OUString msg(OUSTR("[automation bridge]Property \"") + aPropertyName +
469 OUSTR("\" is not supported"));
470 throw UnknownPropertyException(msg, Reference<XInterface>());
471 }
472 // write-only should not be possible
473 OSL_ASSERT( aDescGet || ! aDescPut);
474
475 HRESULT hr;
476 DISPPARAMS dispparams = {0, 0, 0, 0};
477 CComVariant varResult;
478 ExcepInfo excepinfo;
479 unsigned int uArgErr;
480 DISPID dispid;
481 if (aDescGet)
482 dispid = aDescGet->memid;
483 else if (aVarDesc)
484 dispid = aVarDesc->memid;
485 else
486 dispid = aDescPut->memid;
487
488 hr = m_spDispatch->Invoke(dispid,
489 IID_NULL,
490 LOCALE_USER_DEFAULT,
491 DISPATCH_PROPERTYGET,
492 &dispparams,
493 &varResult,
494 &excepinfo,
495 &uArgErr);
496
497 // converting return value and out parameter back to UNO
498 if (hr == S_OK)
499 {
500 // If the com object implements uno interfaces then we have
501 // to convert the attribute into the expected type.
502 TypeDescription attrInfo;
503 getAttributeInfo(aPropertyName, attrInfo);
504 if( attrInfo.is() )
505 variantToAny( &varResult, ret, Type( attrInfo.get()->pWeakRef));
506 else
507 variantToAny(&varResult, ret);
508 }
509
510 // lookup error code
511 switch (hr)
512 {
513 case S_OK:
514 break;
515 case DISP_E_BADPARAMCOUNT:
516 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
517 Reference<XInterface>());
518 break;
519 case DISP_E_BADVARTYPE:
520 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
521 Reference<XInterface>());
522 break;
523 case DISP_E_EXCEPTION:
524 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
525 Reference<XInterface>());
526 break;
527 case DISP_E_MEMBERNOTFOUND:
528 throw UnknownPropertyException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
529 Reference<XInterface>());
530 break;
531 case DISP_E_NONAMEDARGS:
532 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
533 Reference<XInterface>());
534 break;
535 case DISP_E_OVERFLOW:
536 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
537 Reference<XInterface>());
538 break;
539 case DISP_E_PARAMNOTFOUND:
540 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
541 Reference<XInterface>());
542 break;
543 case DISP_E_TYPEMISMATCH:
544 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
545 Reference<XInterface>());
546 break;
547 case DISP_E_UNKNOWNINTERFACE:
548 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
549 Reference<XInterface>());
550 break;
551 case DISP_E_UNKNOWNLCID:
552 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
553 Reference<XInterface>());
554 break;
555 case DISP_E_PARAMNOTOPTIONAL:
556 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
557 Reference<XInterface>());
558 break;
559 default:
560 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
561 Reference<XInterface>());
562 break;
563 }
564 }
565 catch (UnknownPropertyException& )
566 {
567 throw;
568 }
569 catch (BridgeRuntimeError& e)
570 {
571 throw RuntimeException(
572 e.message, Reference<XInterface>());
573 }
574 catch (Exception & e)
575 {
576 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
577 "IUnknownWrapper_Impl::getValue ! Message : \n") +
578 e.Message, Reference<XInterface>());
579 }
580 catch (...)
581 {
582 throw RuntimeException(
583 OUSTR("[automation bridge] unexpected exception in "
584 "IUnknownWrapper_Impl::getValue !"), Reference<XInterface>());
585 }
586 return ret;
587 }
588
hasMethod(const OUString & aName)589 sal_Bool SAL_CALL IUnknownWrapper_Impl::hasMethod( const OUString& aName )
590 throw(RuntimeException)
591 {
592 if ( ! m_spDispatch )
593 {
594 throw RuntimeException(
595 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
596 Reference<XInterface>());
597 }
598 sal_Bool ret = sal_False;
599
600 try
601 {
602 o2u_attachCurrentThread();
603 ITypeInfo* pInfo = getTypeInfo();
604 FuncDesc aDesc(pInfo);
605 getFuncDesc(aName, & aDesc);
606 // Automation properties can have arguments. Those are treated as methods and
607 //are called through XInvocation::invoke.
608 if ( ! aDesc)
609 {
610 FuncDesc aDescGet(pInfo);
611 FuncDesc aDescPut(pInfo);
612 VarDesc aVarDesc(pInfo);
613 getPropDesc( aName, & aDescGet, & aDescPut, & aVarDesc);
614 if (aDescGet && aDescGet->cParams > 0
615 || aDescPut && aDescPut->cParams > 0)
616 ret = sal_True;
617 }
618 else
619 ret = sal_True;
620 }
621 catch (BridgeRuntimeError& e)
622 {
623 throw RuntimeException(e.message, Reference<XInterface>());
624 }
625 catch (Exception & e)
626 {
627 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
628 "IUnknownWrapper_Impl::hasMethod ! Message : \n") +
629 e.Message, Reference<XInterface>());
630 }
631 catch (...)
632 {
633 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
634 "IUnknownWrapper_Impl::hasMethod !"), Reference<XInterface>());;
635 }
636 return ret;
637 }
638
hasProperty(const OUString & aName)639 sal_Bool SAL_CALL IUnknownWrapper_Impl::hasProperty( const OUString& aName )
640 throw(RuntimeException)
641 {
642 if ( ! m_spDispatch )
643 {
644 throw RuntimeException(OUSTR("[automation bridge] The object does not have an "
645 "IDispatch interface"), Reference<XInterface>());
646 return sal_False;
647 }
648 sal_Bool ret = sal_False;
649 try
650 {
651 o2u_attachCurrentThread();
652
653 ITypeInfo * pInfo = getTypeInfo();
654 FuncDesc aDescGet(pInfo);
655 FuncDesc aDescPut(pInfo);
656 VarDesc aVarDesc(pInfo);
657 getPropDesc(aName, & aDescGet, & aDescPut, & aVarDesc);
658 // Automation properties can have parameters. If so, we access them through
659 // XInvocation::invoke. Thas is, hasProperty must return false for such a
660 // property
661 if (aVarDesc
662 || aDescPut && aDescPut->cParams == 0
663 || aDescGet && aDescGet->cParams == 0)
664 {
665 ret = sal_True;
666 }
667 }
668 catch (BridgeRuntimeError& e)
669 {
670 throw RuntimeException(e.message, Reference<XInterface>());
671 }
672 catch (Exception & e)
673 {
674 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
675 "IUnknownWrapper_Impl::hasProperty ! Message : \n") +
676 e.Message, Reference<XInterface>());
677
678 }
679 catch (...)
680 {
681 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
682 "IUnknownWrapper_Impl::hasProperty !"), Reference<XInterface>());
683 }
684 return ret;
685 }
686
createBridge(const Any & modelDepObject,const Sequence<sal_Int8> &,sal_Int16 sourceModelType,sal_Int16 destModelType)687 Any SAL_CALL IUnknownWrapper_Impl::createBridge( const Any& modelDepObject,
688 const Sequence< sal_Int8 >& /*aProcessId*/, sal_Int16 sourceModelType,
689 sal_Int16 destModelType )
690 throw( IllegalArgumentException, RuntimeException)
691 {
692 Any ret;
693 o2u_attachCurrentThread();
694
695 if (
696 (sourceModelType == UNO) &&
697 (destModelType == OLE) &&
698 (modelDepObject.getValueTypeClass() == TypeClass_INTERFACE)
699 )
700 {
701 Reference<XInterface> xInt( *(XInterface**) modelDepObject.getValue());
702 Reference<XInterface> xSelf( (OWeakObject*)this);
703
704 if (xInt == xSelf)
705 {
706 VARIANT* pVariant = (VARIANT*) CoTaskMemAlloc(sizeof(VARIANT));
707
708 VariantInit(pVariant);
709 if (m_bOriginalDispatch == sal_True)
710 {
711 pVariant->vt = VT_DISPATCH;
712 pVariant->pdispVal = m_spDispatch;
713 pVariant->pdispVal->AddRef();
714 }
715 else
716 {
717 pVariant->vt = VT_UNKNOWN;
718 pVariant->punkVal = m_spUnknown;
719 pVariant->punkVal->AddRef();
720 }
721
722 ret.setValue((void*)&pVariant, getCppuType( (sal_uInt32*) 0));
723 }
724 }
725
726 return ret;
727 }
728 /** @internal
729 @exception IllegalArgumentException
730 @exception CannotConvertException
731 @exception InvocationTargetException
732 @RuntimeException
733 */
invokeWithDispIdUnoTlb(const OUString & sFunctionName,const Sequence<Any> & Params,Sequence<sal_Int16> & OutParamIndex,Sequence<Any> & OutParam)734 Any IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString& sFunctionName,
735 const Sequence< Any >& Params,
736 Sequence< sal_Int16 >& OutParamIndex,
737 Sequence< Any >& OutParam)
738 {
739 Any ret;
740 HRESULT hr= S_OK;
741
742 sal_Int32 parameterCount= Params.getLength();
743 sal_Int32 outParameterCount= 0;
744 typelib_InterfaceMethodTypeDescription* pMethod= NULL;
745 TypeDescription methodDesc;
746 getMethodInfo(sFunctionName, methodDesc);
747
748 // We need to know whether the IDispatch is from a JScript object.
749 // Then out and in/out parameters have to be treated differently than
750 // with common COM objects.
751 sal_Bool bJScriptObject= isJScriptObject();
752 scoped_array<CComVariant> sarParams;
753 scoped_array<CComVariant> sarParamsRef;
754 CComVariant *pVarParams= NULL;
755 CComVariant *pVarParamsRef= NULL;
756 sal_Bool bConvRet= sal_True;
757
758 if( methodDesc.is())
759 {
760 pMethod = (typelib_InterfaceMethodTypeDescription* )methodDesc.get();
761 parameterCount = pMethod->nParams;
762 // Create the Array for the array being passed in DISPPARAMS
763 // the array also contains the outparameter (but not the values)
764 if( pMethod->nParams > 0)
765 {
766 sarParams.reset(new CComVariant[ parameterCount]);
767 pVarParams = sarParams.get();
768 }
769
770 // Create the Array for the out an in/out parameter. These values
771 // are referenced by the VT_BYREF VARIANTs in DISPPARAMS.
772 // We need to find out the number of out and in/out parameter.
773 for( sal_Int32 i=0; i < parameterCount; i++)
774 {
775 if( pMethod->pParams[i].bOut)
776 outParameterCount++;
777 }
778
779 if( !bJScriptObject)
780 {
781 sarParamsRef.reset(new CComVariant[outParameterCount]);
782 pVarParamsRef = sarParamsRef.get();
783 // build up the parameters for IDispatch::Invoke
784 sal_Int32 outParamIndex=0;
785 int i = 0;
786 try
787 {
788 for( i= 0; i < parameterCount; i++)
789 {
790 // In parameter
791 if( pMethod->pParams[i].bIn == sal_True && ! pMethod->pParams[i].bOut)
792 {
793 anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]);
794 }
795 // Out parameter + in/out parameter
796 else if( pMethod->pParams[i].bOut == sal_True)
797 {
798 CComVariant var;
799 if(pMethod->pParams[i].bIn)
800 {
801 anyToVariant( & var,Params[i]);
802 pVarParamsRef[outParamIndex] = var;
803 }
804
805 switch( pMethod->pParams[i].pTypeRef->eTypeClass)
806 {
807 case TypeClass_INTERFACE:
808 case TypeClass_STRUCT:
809 if( ! pMethod->pParams[i].bIn)
810 {
811 pVarParamsRef[ outParamIndex].vt= VT_DISPATCH;
812 pVarParamsRef[ outParamIndex].pdispVal= 0;
813 }
814 pVarParams[parameterCount - i -1].vt = VT_DISPATCH | VT_BYREF;
815 pVarParams[parameterCount - i -1].ppdispVal= &pVarParamsRef[outParamIndex].pdispVal;
816 break;
817 case TypeClass_ENUM:
818 case TypeClass_LONG:
819 case TypeClass_UNSIGNED_LONG:
820 if( ! pMethod->pParams[i].bIn)
821 {
822 pVarParamsRef[ outParamIndex].vt = VT_I4;
823 pVarParamsRef[ outParamIndex].lVal = 0;
824 }
825 pVarParams[parameterCount - i -1].vt = VT_I4 | VT_BYREF;
826 pVarParams[parameterCount - i -1].plVal= &pVarParamsRef[outParamIndex].lVal;
827 break;
828 case TypeClass_SEQUENCE:
829 if( ! pMethod->pParams[i].bIn)
830 {
831 pVarParamsRef[ outParamIndex].vt = VT_ARRAY| VT_VARIANT;
832 pVarParamsRef[ outParamIndex].parray= NULL;
833 }
834 pVarParams[parameterCount - i -1].vt = VT_ARRAY| VT_BYREF | VT_VARIANT;
835 pVarParams[parameterCount - i -1].pparray= &pVarParamsRef[outParamIndex].parray;
836 break;
837 case TypeClass_ANY:
838 if( ! pMethod->pParams[i].bIn)
839 {
840 pVarParamsRef[ outParamIndex].vt = VT_EMPTY;
841 pVarParamsRef[ outParamIndex].lVal = 0;
842 }
843 pVarParams[parameterCount - i -1].vt = VT_VARIANT | VT_BYREF;
844 pVarParams[parameterCount - i -1].pvarVal = &pVarParamsRef[outParamIndex];
845 break;
846 case TypeClass_BOOLEAN:
847 if( ! pMethod->pParams[i].bIn)
848 {
849 pVarParamsRef[ outParamIndex].vt = VT_BOOL;
850 pVarParamsRef[ outParamIndex].boolVal = 0;
851 }
852 pVarParams[parameterCount - i -1].vt = VT_BOOL| VT_BYREF;
853 pVarParams[parameterCount - i -1].pboolVal =
854 & pVarParamsRef[outParamIndex].boolVal;
855 break;
856
857 case TypeClass_STRING:
858 if( ! pMethod->pParams[i].bIn)
859 {
860 pVarParamsRef[ outParamIndex].vt = VT_BSTR;
861 pVarParamsRef[ outParamIndex].bstrVal= 0;
862 }
863 pVarParams[parameterCount - i -1].vt = VT_BSTR| VT_BYREF;
864 pVarParams[parameterCount - i -1].pbstrVal=
865 & pVarParamsRef[outParamIndex].bstrVal;
866 break;
867
868 case TypeClass_FLOAT:
869 if( ! pMethod->pParams[i].bIn)
870 {
871 pVarParamsRef[ outParamIndex].vt = VT_R4;
872 pVarParamsRef[ outParamIndex].fltVal= 0;
873 }
874 pVarParams[parameterCount - i -1].vt = VT_R4| VT_BYREF;
875 pVarParams[parameterCount - i -1].pfltVal =
876 & pVarParamsRef[outParamIndex].fltVal;
877 break;
878 case TypeClass_DOUBLE:
879 if( ! pMethod->pParams[i].bIn)
880 {
881 pVarParamsRef[ outParamIndex].vt = VT_R8;
882 pVarParamsRef[ outParamIndex].dblVal= 0;
883 }
884 pVarParams[parameterCount - i -1].vt = VT_R8| VT_BYREF;
885 pVarParams[parameterCount - i -1].pdblVal=
886 & pVarParamsRef[outParamIndex].dblVal;
887 break;
888 case TypeClass_BYTE:
889 if( ! pMethod->pParams[i].bIn)
890 {
891 pVarParamsRef[ outParamIndex].vt = VT_UI1;
892 pVarParamsRef[ outParamIndex].bVal= 0;
893 }
894 pVarParams[parameterCount - i -1].vt = VT_UI1| VT_BYREF;
895 pVarParams[parameterCount - i -1].pbVal=
896 & pVarParamsRef[outParamIndex].bVal;
897 break;
898 case TypeClass_CHAR:
899 case TypeClass_SHORT:
900 case TypeClass_UNSIGNED_SHORT:
901 if( ! pMethod->pParams[i].bIn)
902 {
903 pVarParamsRef[ outParamIndex].vt = VT_I2;
904 pVarParamsRef[ outParamIndex].iVal = 0;
905 }
906 pVarParams[parameterCount - i -1].vt = VT_I2| VT_BYREF;
907 pVarParams[parameterCount - i -1].piVal=
908 & pVarParamsRef[outParamIndex].iVal;
909 break;
910
911 default:
912 if( ! pMethod->pParams[i].bIn)
913 {
914 pVarParamsRef[ outParamIndex].vt = VT_EMPTY;
915 pVarParamsRef[ outParamIndex].lVal = 0;
916 }
917 pVarParams[parameterCount - i -1].vt = VT_VARIANT | VT_BYREF;
918 pVarParams[parameterCount - i -1].pvarVal =
919 & pVarParamsRef[outParamIndex];
920 }
921 outParamIndex++;
922 } // end else if
923 } // end for
924 }
925 catch (IllegalArgumentException & e)
926 {
927 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i );
928 throw;
929 }
930 catch (CannotConvertException & e)
931 {
932 e.ArgumentIndex = i;
933 throw;
934 }
935 }
936 else // it is an JScriptObject
937 {
938 int i = 0;
939 try
940 {
941 for( ; i< parameterCount; i++)
942 {
943 // In parameter
944 if( pMethod->pParams[i].bIn == sal_True && ! pMethod->pParams[i].bOut)
945 {
946 anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]);
947 }
948 // Out parameter + in/out parameter
949 else if( pMethod->pParams[i].bOut == sal_True)
950 {
951 CComObject<JScriptOutParam>* pParamObject;
952 if( SUCCEEDED( CComObject<JScriptOutParam>::CreateInstance( &pParamObject)))
953 {
954 CComPtr<IUnknown> pUnk(pParamObject->GetUnknown());
955 #ifdef __MINGW32__
956 CComQIPtr<IDispatch, &__uuidof(IDispatch)> pDisp( pUnk);
957 #else
958 CComQIPtr<IDispatch> pDisp( pUnk);
959 #endif
960
961 pVarParams[ parameterCount - i -1].vt= VT_DISPATCH;
962 pVarParams[ parameterCount - i -1].pdispVal= pDisp;
963 pVarParams[ parameterCount - i -1].pdispVal->AddRef();
964 // if the param is in/out then put the parameter on index 0
965 if( pMethod->pParams[i].bIn == sal_True ) // in / out
966 {
967 CComVariant varParam;
968 anyToVariant( &varParam, Params.getConstArray()[i]);
969 CComDispatchDriver dispDriver( pDisp);
970 if(FAILED( dispDriver.PutPropertyByName( L"0", &varParam)))
971 throw BridgeRuntimeError(
972 OUSTR("[automation bridge]IUnknownWrapper_Impl::"
973 "invokeWithDispIdUnoTlb\n"
974 "Could not set property \"0\" for the in/out "
975 "param!"));
976
977 }
978 }
979 else
980 {
981 throw BridgeRuntimeError(
982 OUSTR("[automation bridge]IUnknownWrapper_Impl::"
983 "invokeWithDispIdUnoTlb\n"
984 "Could not create out parameter at index: ") +
985 OUString::valueOf((sal_Int32) i));
986 }
987
988 }
989 }
990 }
991 catch (IllegalArgumentException & e)
992 {
993 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i );
994 throw;
995 }
996 catch (CannotConvertException & e)
997 {
998 e.ArgumentIndex = i;
999 throw;
1000 }
1001 }
1002 }
1003 // No type description Available, that is we have to deal with a COM component,
1004 // that does not implements UNO interfaces ( IDispatch based)
1005 else
1006 {
1007 //We should not run into this block, because invokeWithDispIdComTlb should
1008 //have been called instead.
1009 OSL_ASSERT(0);
1010 }
1011
1012
1013 CComVariant varResult;
1014 ExcepInfo excepinfo;
1015 unsigned int uArgErr;
1016 DISPPARAMS dispparams= { pVarParams, NULL, parameterCount, 0};
1017 // Get the DISPID
1018 FuncDesc aDesc(getTypeInfo());
1019 getFuncDesc(sFunctionName, & aDesc);
1020 // invoking OLE method
1021 hr = m_spDispatch->Invoke(aDesc->memid,
1022 IID_NULL,
1023 LOCALE_USER_DEFAULT,
1024 DISPATCH_METHOD,
1025 &dispparams,
1026 &varResult,
1027 &excepinfo,
1028 &uArgErr);
1029
1030 // converting return value and out parameter back to UNO
1031 if (hr == S_OK)
1032 {
1033 if( outParameterCount && pMethod)
1034 {
1035 OutParamIndex.realloc( outParameterCount);
1036 OutParam.realloc( outParameterCount);
1037 sal_Int32 outIndex=0;
1038 int i = 0;
1039 try
1040 {
1041 for( ; i < parameterCount; i++)
1042 {
1043 if( pMethod->pParams[i].bOut )
1044 {
1045 OutParamIndex[outIndex]= (sal_Int16) i;
1046 Any outAny;
1047 if( !bJScriptObject)
1048 {
1049 variantToAny( &pVarParamsRef[outIndex], outAny,
1050 Type(pMethod->pParams[i].pTypeRef), sal_False);
1051 OutParam[outIndex++]= outAny;
1052 }
1053 else //JScriptObject
1054 {
1055 if( pVarParams[i].vt == VT_DISPATCH)
1056 {
1057 CComDispatchDriver pDisp( pVarParams[i].pdispVal);
1058 if( pDisp)
1059 {
1060 CComVariant varOut;
1061 if( SUCCEEDED( pDisp.GetPropertyByName( L"0", &varOut)))
1062 {
1063 variantToAny( &varOut, outAny,
1064 Type(pMethod->pParams[parameterCount - 1 - i].pTypeRef), sal_False);
1065 OutParam[outParameterCount - 1 - outIndex++]= outAny;
1066 }
1067 else
1068 bConvRet= sal_False;
1069 }
1070 else
1071 bConvRet= sal_False;
1072 }
1073 else
1074 bConvRet= sal_False;
1075 }
1076 }
1077 if( !bConvRet) break;
1078 }
1079 }
1080 catch(IllegalArgumentException & e)
1081 {
1082 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i );
1083 throw;
1084 }
1085 catch(CannotConvertException & e)
1086 {
1087 e.ArgumentIndex = i;
1088 throw;
1089 }
1090 }
1091 // return value, no type information available
1092 if ( bConvRet)
1093 {
1094 try
1095 {
1096 if( pMethod )
1097 variantToAny(&varResult, ret, Type( pMethod->pReturnTypeRef), sal_False);
1098 else
1099 variantToAny(&varResult, ret, sal_False);
1100 }
1101 catch (IllegalArgumentException & e)
1102 {
1103 e.Message =
1104 OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1105 "Could not convert return value! \n Message: \n") + e.Message;
1106 throw;
1107 }
1108 catch (CannotConvertException & e)
1109 {
1110 e.Message =
1111 OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1112 "Could not convert return value! \n Message: \n") + e.Message;
1113 throw;
1114 }
1115 }
1116 }
1117
1118 if( !bConvRet) // conversion of return or out parameter failed
1119 throw CannotConvertException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Call to COM object failed. Conversion of return or out value failed")),
1120 Reference<XInterface>( static_cast<XWeak*>(this), UNO_QUERY ), TypeClass_UNKNOWN,
1121 FailReason::UNKNOWN, 0);// lookup error code
1122 // conversion of return or out parameter failed
1123 switch (hr)
1124 {
1125 case S_OK:
1126 break;
1127 case DISP_E_BADPARAMCOUNT:
1128 throw IllegalArgumentException();
1129 break;
1130 case DISP_E_BADVARTYPE:
1131 throw RuntimeException();
1132 break;
1133 case DISP_E_EXCEPTION:
1134 throw InvocationTargetException();
1135 break;
1136 case DISP_E_MEMBERNOTFOUND:
1137 throw IllegalArgumentException();
1138 break;
1139 case DISP_E_NONAMEDARGS:
1140 throw IllegalArgumentException();
1141 break;
1142 case DISP_E_OVERFLOW:
1143 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
1144 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
1145 break;
1146 case DISP_E_PARAMNOTFOUND:
1147 throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
1148 static_cast<XWeak*>(this)), ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
1149 break;
1150 case DISP_E_TYPEMISMATCH:
1151 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface*>(
1152 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr);
1153 break;
1154 case DISP_E_UNKNOWNINTERFACE:
1155 throw RuntimeException() ;
1156 break;
1157 case DISP_E_UNKNOWNLCID:
1158 throw RuntimeException() ;
1159 break;
1160 case DISP_E_PARAMNOTOPTIONAL:
1161 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
1162 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
1163 break;
1164 default:
1165 throw RuntimeException();
1166 break;
1167 }
1168
1169 return ret;
1170 }
1171
1172
1173
1174 // --------------------------
1175 // XInitialization
initialize(const Sequence<Any> & aArguments)1176 void SAL_CALL IUnknownWrapper_Impl::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException)
1177 {
1178 // 1.parameter is IUnknown
1179 // 2.parameter is a boolean which indicates if the COM pointer was a IUnknown or IDispatch
1180 // 3.parameter is a Sequence<Type>
1181 o2u_attachCurrentThread();
1182 OSL_ASSERT(aArguments.getLength() == 3);
1183
1184 m_spUnknown= *(IUnknown**) aArguments[0].getValue();
1185 #ifdef __MINGW32__
1186 m_spUnknown->QueryInterface(IID_IDispatch, reinterpret_cast<LPVOID*>( & m_spDispatch.p));
1187 #else
1188 m_spUnknown.QueryInterface( & m_spDispatch.p);
1189 #endif
1190
1191 aArguments[1] >>= m_bOriginalDispatch;
1192 aArguments[2] >>= m_seqTypes;
1193
1194 ITypeInfo* pType = NULL;
1195 try
1196 {
1197 // a COM object implementation that has no TypeInfo is still a legal COM object;
1198 // such objects can at least be transported through UNO using the bridge
1199 // so we should allow to create wrappers for them as well
1200 pType = getTypeInfo();
1201 }
1202 catch( BridgeRuntimeError& )
1203 {}
1204 catch( Exception& )
1205 {}
1206
1207 if ( pType )
1208 {
1209 try
1210 {
1211 // Get Default member
1212 CComBSTR defaultMemberName;
1213 if ( SUCCEEDED( pType->GetDocumentation(0, &defaultMemberName, 0, 0, 0 ) ) )
1214 {
1215 OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(defaultMemberName)));
1216 FuncDesc aDescGet(pType);
1217 FuncDesc aDescPut(pType);
1218 VarDesc aVarDesc(pType);
1219 // see if this is a property first ( more likely to be a property then a method )
1220 getPropDesc( usName, & aDescGet, & aDescPut, & aVarDesc);
1221
1222 if ( !aDescGet && !aDescPut )
1223 {
1224 getFuncDesc( usName, &aDescGet );
1225 if ( !aDescGet )
1226 throw BridgeRuntimeError( OUSTR("[automation bridge]IUnknownWrapper_Impl::initialize() Failed to get Function or Property desc. for " ) + usName );
1227 }
1228 // now for some funny heuristics to make basic understand what to do
1229 // a single aDescGet ( that doesn't take any params ) would be
1230 // a read only ( defaultmember ) property e.g. this object
1231 // should implement XDefaultProperty
1232 // a single aDescGet ( that *does* ) take params is basically a
1233 // default method e.g. implement XDefaultMethod
1234
1235 // a DescPut ( I guess we only really support a default param with '1' param ) as a setValue ( but I guess we can leave it through, the object will fail if we don't get it right anyway )
1236 if ( aDescPut || ( aDescGet && aDescGet->cParams == 0 ) )
1237 m_bHasDfltProperty = true;
1238 if ( aDescGet->cParams > 0 )
1239 m_bHasDfltMethod = true;
1240 if ( m_bHasDfltProperty || m_bHasDfltMethod )
1241 m_sDefaultMember = usName;
1242 }
1243 }
1244 catch ( BridgeRuntimeError & e )
1245 {
1246 throw RuntimeException( e.message, Reference<XInterface>() );
1247 }
1248 catch( Exception& e )
1249 {
1250 throw RuntimeException(
1251 OUSTR("[automation bridge] unexpected exception in IUnknownWrapper_Impl::initialiase() error message: \n") + e.Message,
1252 Reference<XInterface>() );
1253 }
1254 }
1255 }
1256
1257 // --------------------------
1258 // XDirectInvocation
directInvoke(const::rtl::OUString & aName,const uno::Sequence<uno::Any> & aParams)1259 uno::Any SAL_CALL IUnknownWrapper_Impl::directInvoke( const ::rtl::OUString& aName, const uno::Sequence< uno::Any >& aParams )
1260 throw (lang::IllegalArgumentException, script::CannotConvertException, reflection::InvocationTargetException, uno::RuntimeException)
1261 {
1262 Any aResult;
1263
1264 if ( !m_spDispatch )
1265 {
1266 throw RuntimeException(
1267 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
1268 Reference<XInterface>());
1269 }
1270
1271 o2u_attachCurrentThread();
1272 DISPID dispid;
1273 if ( !getDispid( aName, &dispid ) )
1274 throw IllegalArgumentException(
1275 OUSTR( "[automation bridge] The object does not have a function or property " )
1276 + aName, Reference<XInterface>(), 0);
1277
1278 CComVariant varResult;
1279 ExcepInfo excepinfo;
1280 unsigned int uArgErr = 0;
1281 INVOKEKIND pInvkinds[2];
1282 pInvkinds[0] = INVOKE_FUNC;
1283 pInvkinds[1] = aParams.getLength() ? INVOKE_PROPERTYPUT : INVOKE_PROPERTYGET;
1284 HRESULT hInvRes = E_FAIL;
1285
1286 // try Invoke first, if it does not work, try put/get property
1287 for ( sal_Int32 nStep = 0; FAILED( hInvRes ) && nStep < 2; nStep++ )
1288 {
1289 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1290
1291 DISPID idPropertyPut = DISPID_PROPERTYPUT;
1292 scoped_array<DISPID> arDispidNamedArgs;
1293 scoped_array<CComVariant> ptrArgs;
1294 scoped_array<CComVariant> ptrRefArgs; // referenced arguments
1295 CComVariant * arArgs = NULL;
1296 CComVariant * arRefArgs = NULL;
1297 bool bVarargParam = false;
1298
1299 dispparams.cArgs = aParams.getLength();
1300
1301 // Determine the number of named arguments
1302 for ( sal_Int32 nInd = 0; nInd < aParams.getLength(); nInd++ )
1303 if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0) )
1304 dispparams.cNamedArgs ++;
1305
1306 // fill the named arguments
1307 if ( dispparams.cNamedArgs > 0
1308 && !( dispparams.cNamedArgs == 1 && pInvkinds[nStep] == INVOKE_PROPERTYPUT ) )
1309 {
1310 int nSizeAr = dispparams.cNamedArgs + 1;
1311 if ( pInvkinds[nStep] == INVOKE_PROPERTYPUT )
1312 nSizeAr = dispparams.cNamedArgs;
1313
1314 scoped_array<OLECHAR*> saNames(new OLECHAR*[nSizeAr]);
1315 OLECHAR ** pNames = saNames.get();
1316 pNames[0] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(aName.getStr()));
1317
1318 int cNamedArg = 0;
1319 for ( size_t nInd = 0; nInd < dispparams.cArgs; nInd++ )
1320 {
1321 if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0))
1322 {
1323 const NamedArgument& arg = *(NamedArgument const*)aParams[nInd].getValue();
1324
1325 //We put the parameter names in reverse order into the array,
1326 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1327 //The first name in the array is the method name
1328 pNames[nSizeAr - 1 - cNamedArg++] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(arg.Name.getStr()));
1329 }
1330 }
1331
1332 arDispidNamedArgs.reset( new DISPID[nSizeAr] );
1333 HRESULT hr = getTypeInfo()->GetIDsOfNames( pNames, nSizeAr, arDispidNamedArgs.get() );
1334 if ( hr == E_NOTIMPL )
1335 hr = m_spDispatch->GetIDsOfNames(IID_NULL, pNames, nSizeAr, LOCALE_USER_DEFAULT, arDispidNamedArgs.get() );
1336
1337 if ( SUCCEEDED( hr ) )
1338 {
1339 if ( pInvkinds[nStep] == DISPATCH_PROPERTYPUT )
1340 {
1341 DISPID* arIDs = arDispidNamedArgs.get();
1342 arIDs[0] = DISPID_PROPERTYPUT;
1343 dispparams.rgdispidNamedArgs = arIDs;
1344 }
1345 else
1346 {
1347 DISPID* arIDs = arDispidNamedArgs.get();
1348 dispparams.rgdispidNamedArgs = & arIDs[1];
1349 }
1350 }
1351 else if (hr == DISP_E_UNKNOWNNAME)
1352 {
1353 throw IllegalArgumentException(
1354 OUSTR("[automation bridge]One of the named arguments is wrong!"),
1355 Reference<XInterface>(), 0);
1356 }
1357 else
1358 {
1359 throw InvocationTargetException(
1360 OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ")
1361 + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any());
1362 }
1363 }
1364
1365 //Convert arguments
1366 ptrArgs.reset(new CComVariant[dispparams.cArgs]);
1367 ptrRefArgs.reset(new CComVariant[dispparams.cArgs]);
1368 arArgs = ptrArgs.get();
1369 arRefArgs = ptrRefArgs.get();
1370
1371 sal_Int32 nInd = 0;
1372 try
1373 {
1374 sal_Int32 revIndex = 0;
1375 for ( nInd = 0; nInd < sal_Int32(dispparams.cArgs); nInd++)
1376 {
1377 revIndex = dispparams.cArgs - nInd - 1;
1378 arRefArgs[revIndex].byref = 0;
1379 Any anyArg;
1380 if ( nInd < aParams.getLength() )
1381 anyArg = aParams.getConstArray()[nInd];
1382
1383 // Property Put arguments
1384 if ( anyArg.getValueType() == getCppuType((PropertyPutArgument*)0) )
1385 {
1386 PropertyPutArgument arg;
1387 anyArg >>= arg;
1388 anyArg <<= arg.Value;
1389 }
1390 // named argument
1391 if (anyArg.getValueType() == getCppuType((NamedArgument*) 0))
1392 {
1393 NamedArgument aNamedArgument;
1394 anyArg >>= aNamedArgument;
1395 anyArg <<= aNamedArgument.Value;
1396 }
1397
1398 if ( nInd < aParams.getLength() && anyArg.getValueTypeClass() != TypeClass_VOID )
1399 {
1400 anyToVariant( &arArgs[revIndex], anyArg, VT_VARIANT );
1401 }
1402 else
1403 {
1404 arArgs[revIndex].vt = VT_ERROR;
1405 arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
1406 }
1407 }
1408 }
1409 catch (IllegalArgumentException & e)
1410 {
1411 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, sal_Int32 >( nInd );
1412 throw;
1413 }
1414 catch (CannotConvertException & e)
1415 {
1416 e.ArgumentIndex = nInd;
1417 throw;
1418 }
1419
1420 dispparams.rgvarg = arArgs;
1421 // invoking OLE method
1422 DWORD localeId = LOCALE_USER_DEFAULT;
1423 hInvRes = m_spDispatch->Invoke( dispid,
1424 IID_NULL,
1425 localeId,
1426 ::sal::static_int_cast< WORD, INVOKEKIND >( pInvkinds[nStep] ),
1427 &dispparams,
1428 &varResult,
1429 &excepinfo,
1430 &uArgErr);
1431 }
1432
1433 // converting return value and out parameter back to UNO
1434 if ( SUCCEEDED( hInvRes ) )
1435 variantToAny( &varResult, aResult, sal_False );
1436 else
1437 {
1438 // map error codes to exceptions
1439 OUString message;
1440 switch ( hInvRes )
1441 {
1442 case S_OK:
1443 break;
1444 case DISP_E_BADPARAMCOUNT:
1445 throw IllegalArgumentException(OUSTR("[automation bridge] Wrong "
1446 "number of arguments. Object returned DISP_E_BADPARAMCOUNT."),
1447 0, 0);
1448 break;
1449 case DISP_E_BADVARTYPE:
1450 throw RuntimeException(OUSTR("[automation bridge] One or more "
1451 "arguments have the wrong type. Object returned "
1452 "DISP_E_BADVARTYPE."), 0);
1453 break;
1454 case DISP_E_EXCEPTION:
1455 message = OUSTR("[automation bridge]: ");
1456 message += OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription),
1457 ::SysStringLen(excepinfo.bstrDescription));
1458 throw InvocationTargetException(message, Reference<XInterface>(), Any());
1459 break;
1460 case DISP_E_MEMBERNOTFOUND:
1461 message = OUSTR("[automation bridge]: A function with the name \"")
1462 + aName + OUSTR("\" is not supported. Object returned "
1463 "DISP_E_MEMBERNOTFOUND.");
1464 throw IllegalArgumentException(message, 0, 0);
1465 break;
1466 case DISP_E_NONAMEDARGS:
1467 throw IllegalArgumentException(OUSTR("[automation bridge] Object "
1468 "returned DISP_E_NONAMEDARGS"),0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
1469 break;
1470 case DISP_E_OVERFLOW:
1471 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[automation bridge] Call failed.")),
1472 static_cast<XInterface*>(
1473 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
1474 break;
1475 case DISP_E_PARAMNOTFOUND:
1476 throw IllegalArgumentException(OUSTR("[automation bridge]Call failed."
1477 "Object returned DISP_E_PARAMNOTFOUND."),
1478 0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
1479 break;
1480 case DISP_E_TYPEMISMATCH:
1481 throw CannotConvertException(OUSTR("[automation bridge] Call failed. "
1482 "Object returned DISP_E_TYPEMISMATCH"),
1483 static_cast<XInterface*>(
1484 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr);
1485 break;
1486 case DISP_E_UNKNOWNINTERFACE:
1487 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
1488 "Object returned DISP_E_UNKNOWNINTERFACE."),0);
1489 break;
1490 case DISP_E_UNKNOWNLCID:
1491 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
1492 "Object returned DISP_E_UNKNOWNLCID."),0);
1493 break;
1494 case DISP_E_PARAMNOTOPTIONAL:
1495 throw CannotConvertException(OUSTR("[automation bridge] Call failed."
1496 "Object returned DISP_E_PARAMNOTOPTIONAL"),
1497 static_cast<XInterface*>(static_cast<XWeak*>(this)),
1498 TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
1499 break;
1500 default:
1501 throw RuntimeException();
1502 break;
1503 }
1504 }
1505
1506 return aResult;
1507 }
1508
hasMember(const::rtl::OUString & aName)1509 ::sal_Bool SAL_CALL IUnknownWrapper_Impl::hasMember( const ::rtl::OUString& aName )
1510 throw (uno::RuntimeException)
1511 {
1512 if ( ! m_spDispatch )
1513 {
1514 throw RuntimeException(
1515 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
1516 Reference<XInterface>());
1517 }
1518
1519 o2u_attachCurrentThread();
1520 DISPID dispid;
1521 return getDispid( aName, &dispid );
1522 }
1523
1524
1525 // UnoConversionUtilities --------------------------------------------------------------------------------
createUnoWrapperInstance()1526 Reference< XInterface > IUnknownWrapper_Impl::createUnoWrapperInstance()
1527 {
1528 if( m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL)
1529 {
1530 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl(
1531 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1532 return Reference<XInterface>( xWeak, UNO_QUERY);
1533 }
1534 else if( m_nUnoWrapperClass == UNO_OBJECT_WRAPPER_REMOTE_OPT)
1535 {
1536 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
1537 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1538 return Reference<XInterface>( xWeak, UNO_QUERY);
1539 }
1540 else
1541 return Reference<XInterface>();
1542 }
createComWrapperInstance()1543 Reference<XInterface> IUnknownWrapper_Impl::createComWrapperInstance()
1544 {
1545 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl(
1546 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1547 return Reference<XInterface>( xWeak, UNO_QUERY);
1548 }
1549
1550
1551
getMethodInfo(const OUString & sName,TypeDescription & methodInfo)1552 void IUnknownWrapper_Impl::getMethodInfo(const OUString& sName, TypeDescription& methodInfo)
1553 {
1554 TypeDescription desc= getInterfaceMemberDescOfCurrentCall(sName);
1555 if( desc.is())
1556 {
1557 typelib_TypeDescription* pMember= desc.get();
1558 if( pMember->eTypeClass == TypeClass_INTERFACE_METHOD )
1559 methodInfo= pMember;
1560 }
1561 }
1562
getAttributeInfo(const OUString & sName,TypeDescription & attributeInfo)1563 void IUnknownWrapper_Impl::getAttributeInfo(const OUString& sName, TypeDescription& attributeInfo)
1564 {
1565 TypeDescription desc= getInterfaceMemberDescOfCurrentCall(sName);
1566 if( desc.is())
1567 {
1568 typelib_TypeDescription* pMember= desc.get();
1569 if( pMember->eTypeClass == TypeClass_INTERFACE_ATTRIBUTE )
1570 {
1571 attributeInfo= ((typelib_InterfaceAttributeTypeDescription*)pMember)->pAttributeTypeRef;
1572 }
1573 }
1574 }
getInterfaceMemberDescOfCurrentCall(const OUString & sName)1575 TypeDescription IUnknownWrapper_Impl::getInterfaceMemberDescOfCurrentCall(const OUString& sName)
1576 {
1577 TypeDescription ret;
1578
1579 for( sal_Int32 i=0; i < m_seqTypes.getLength(); i++)
1580 {
1581 TypeDescription _curDesc( m_seqTypes[i]);
1582 _curDesc.makeComplete();
1583 typelib_InterfaceTypeDescription * pInterface= (typelib_InterfaceTypeDescription*) _curDesc.get();
1584 if( pInterface)
1585 {
1586 typelib_InterfaceMemberTypeDescription* pMember= NULL;
1587 //find the member description of the current call
1588 for( int i=0; i < pInterface->nAllMembers; i++)
1589 {
1590 typelib_TypeDescriptionReference* pTypeRefMember = pInterface->ppAllMembers[i];
1591 typelib_TypeDescription* pDescMember= NULL;
1592 TYPELIB_DANGER_GET( &pDescMember, pTypeRefMember);
1593
1594 typelib_InterfaceMemberTypeDescription* pInterfaceMember=
1595 (typelib_InterfaceMemberTypeDescription*) pDescMember;
1596 if( OUString( pInterfaceMember->pMemberName) == sName)
1597 {
1598 pMember= pInterfaceMember;
1599 break;
1600 }
1601 TYPELIB_DANGER_RELEASE( pDescMember);
1602 }
1603
1604 if( pMember)
1605 {
1606 ret= (typelib_TypeDescription*)pMember;
1607 TYPELIB_DANGER_RELEASE( (typelib_TypeDescription*)pMember);
1608 }
1609 }
1610 if( ret.is())
1611 break;
1612 }
1613 return ret;
1614 }
1615
isJScriptObject()1616 sal_Bool IUnknownWrapper_Impl::isJScriptObject()
1617 {
1618 if( m_eJScript == JScriptUndefined)
1619 {
1620 CComDispatchDriver disp( m_spDispatch);
1621 if( disp)
1622 {
1623 CComVariant result;
1624 if( SUCCEEDED( disp.GetPropertyByName( JSCRIPT_ID_PROPERTY, &result)))
1625 {
1626 if(result.vt == VT_BSTR)
1627 {
1628 CComBSTR name( result.bstrVal);
1629 name.ToLower();
1630 if( name == CComBSTR(JSCRIPT_ID))
1631 m_eJScript= IsJScript;
1632 }
1633 }
1634 }
1635 if( m_eJScript == JScriptUndefined)
1636 m_eJScript= NoJScript;
1637 }
1638
1639 return m_eJScript == NoJScript ? sal_False : sal_True;
1640 }
1641
1642
1643
1644 /** @internal
1645 The function ultimately calls IDispatch::Invoke on the wrapped COM object.
1646 The COM object does not implement UNO Interfaces ( via IDispatch). This
1647 is the case when the OleObjectFactory service has been used to create a
1648 component.
1649 @exception IllegalArgumentException
1650 @exception CannotConvertException
1651 @InvocationTargetException
1652 @RuntimeException
1653 @BridgeRuntimeError
1654 */
invokeWithDispIdComTlb(const OUString & sFuncName,const Sequence<Any> & Params,Sequence<sal_Int16> & OutParamIndex,Sequence<Any> & OutParam)1655 Any IUnknownWrapper_Impl::invokeWithDispIdComTlb(const OUString& sFuncName,
1656 const Sequence< Any >& Params,
1657 Sequence< sal_Int16 >& OutParamIndex,
1658 Sequence< Any >& OutParam)
1659 {
1660 Any ret;
1661 HRESULT result;
1662
1663 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1664 CComVariant varResult;
1665 ExcepInfo excepinfo;
1666 unsigned int uArgErr;
1667 sal_Int32 i = 0;
1668 sal_Int32 nUnoArgs = Params.getLength();
1669 DISPID idPropertyPut = DISPID_PROPERTYPUT;
1670 scoped_array<DISPID> arDispidNamedArgs;
1671 scoped_array<CComVariant> ptrArgs;
1672 scoped_array<CComVariant> ptrRefArgs; // referenced arguments
1673 CComVariant * arArgs = NULL;
1674 CComVariant * arRefArgs = NULL;
1675 sal_Int32 revIndex = 0;
1676 bool bVarargParam = false;
1677
1678 // Get type info for the call. It can be a method call or property put or
1679 // property get operation.
1680 FuncDesc aFuncDesc(getTypeInfo());
1681 getFuncDescForInvoke(sFuncName, Params, & aFuncDesc);
1682
1683 //Set the array of DISPIDs for named args if it is a property put operation.
1684 //If there are other named arguments another array is set later on.
1685 if (aFuncDesc->invkind == INVOKE_PROPERTYPUT
1686 || aFuncDesc->invkind == INVOKE_PROPERTYPUTREF)
1687 dispparams.rgdispidNamedArgs = & idPropertyPut;
1688
1689 //Determine the number of named arguments
1690 for (int iParam = 0; iParam < nUnoArgs; iParam ++)
1691 {
1692 const Any & curArg = Params[iParam];
1693 if (curArg.getValueType() == getCppuType((NamedArgument*) 0))
1694 dispparams.cNamedArgs ++;
1695 }
1696 //In a property put operation a property value is a named argument (DISPID_PROPERTYPUT).
1697 //Therefore the number of named arguments is increased by one.
1698 //Although named, the argument is not named in a actual language, such as Basic,
1699 //therefore it is never a com.sun.star.bridge.oleautomation.NamedArgument
1700 if (aFuncDesc->invkind == DISPATCH_PROPERTYPUT
1701 || aFuncDesc->invkind == DISPATCH_PROPERTYPUTREF)
1702 dispparams.cNamedArgs ++;
1703
1704 //Determine the number of all arguments and named arguments
1705 if (aFuncDesc->cParamsOpt == -1)
1706 {
1707 //Attribute vararg is set on this method. "Unlimited" number of args
1708 //supported. There can be no optional or defaultvalue on any of the arguments.
1709 dispparams.cArgs = nUnoArgs;
1710 }
1711 else
1712 {
1713 //If there are namesd arguments, then the dispparams.cArgs
1714 //is the number of supplied args, otherwise it is the expected number.
1715 if (dispparams.cNamedArgs)
1716 dispparams.cArgs = nUnoArgs;
1717 else
1718 dispparams.cArgs = aFuncDesc->cParams;
1719 }
1720
1721 //check if there are not to many arguments supplied
1722 if (::sal::static_int_cast< sal_uInt32, int >( nUnoArgs ) > dispparams.cArgs)
1723 {
1724 OUStringBuffer buf(256);
1725 buf.appendAscii("[automation bridge] There are too many arguments for this method");
1726 throw IllegalArgumentException( buf.makeStringAndClear(),
1727 Reference<XInterface>(), (sal_Int16) dispparams.cArgs);
1728 }
1729
1730 //Set up the array of DISPIDs (DISPPARAMS::rgdispidNamedArgs)
1731 //for the named arguments.
1732 //If there is only one named arg and if it is because of a property put
1733 //operation, then we need not set up the DISPID array.
1734 if (dispparams.cNamedArgs > 0 &&
1735 ! (dispparams.cNamedArgs == 1 &&
1736 (aFuncDesc->invkind == INVOKE_PROPERTYPUT ||
1737 aFuncDesc->invkind == INVOKE_PROPERTYPUT)))
1738 {
1739 //set up an array containing the member and parameter names
1740 //which is then used in ITypeInfo::GetIDsOfNames
1741 //First determine the size of the array of names which is passed to
1742 //ITypeInfo::GetIDsOfNames. It must hold the method names + the named
1743 //args.
1744 int nSizeAr = dispparams.cNamedArgs + 1;
1745 if (aFuncDesc->invkind == INVOKE_PROPERTYPUT
1746 || aFuncDesc->invkind == INVOKE_PROPERTYPUTREF)
1747 {
1748 nSizeAr = dispparams.cNamedArgs; //counts the DISID_PROPERTYPUT
1749 }
1750
1751 scoped_array<OLECHAR*> saNames(new OLECHAR*[nSizeAr]);
1752 OLECHAR ** arNames = saNames.get();
1753 arNames[0] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(sFuncName.getStr()));
1754
1755 int cNamedArg = 0;
1756 for (size_t iParams = 0; iParams < dispparams.cArgs; iParams ++)
1757 {
1758 const Any & curArg = Params[iParams];
1759 if (curArg.getValueType() == getCppuType((NamedArgument*) 0))
1760 {
1761 const NamedArgument& arg = *(NamedArgument const*) curArg.getValue();
1762 //We put the parameter names in reverse order into the array,
1763 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1764 //The first name in the array is the method name
1765 arNames[nSizeAr - 1 - cNamedArg++] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(arg.Name.getStr()));
1766 }
1767 }
1768
1769 //Prepare the array of DISPIDs for ITypeInfo::GetIDsOfNames
1770 //it must be big enough to contain the DISPIDs of the member + parameters
1771 arDispidNamedArgs.reset(new DISPID[nSizeAr]);
1772 HRESULT hr = getTypeInfo()->GetIDsOfNames(arNames, nSizeAr,
1773 arDispidNamedArgs.get());
1774 if ( hr == E_NOTIMPL )
1775 hr = m_spDispatch->GetIDsOfNames(IID_NULL, arNames, nSizeAr, LOCALE_USER_DEFAULT, arDispidNamedArgs.get() );
1776
1777 if (hr == S_OK)
1778 {
1779 // In a "property put" operation, the property value is a named param with the
1780 //special DISPID DISPID_PROPERTYPUT
1781 if (aFuncDesc->invkind == DISPATCH_PROPERTYPUT
1782 || aFuncDesc->invkind == DISPATCH_PROPERTYPUTREF)
1783 {
1784 //Element at index 0 in the DISPID array must be DISPID_PROPERTYPUT
1785 //The first item in the array arDispidNamedArgs is the DISPID for
1786 //the method. We replace it with DISPID_PROPERTYPUT.
1787 DISPID* arIDs = arDispidNamedArgs.get();
1788 arIDs[0] = DISPID_PROPERTYPUT;
1789 dispparams.rgdispidNamedArgs = arIDs;
1790 }
1791 else
1792 {
1793 //The first item in the array arDispidNamedArgs is the DISPID for
1794 //the method. It must be removed
1795 DISPID* arIDs = arDispidNamedArgs.get();
1796 dispparams.rgdispidNamedArgs = & arIDs[1];
1797 }
1798 }
1799 else if (hr == DISP_E_UNKNOWNNAME)
1800 {
1801 throw IllegalArgumentException(
1802 OUSTR("[automation bridge]One of the named arguments is wrong!"),
1803 Reference<XInterface>(), 0);
1804 }
1805 else
1806 {
1807 throw InvocationTargetException(
1808 OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ")
1809 + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any());
1810 }
1811 }
1812
1813 //Convert arguments
1814 ptrArgs.reset(new CComVariant[dispparams.cArgs]);
1815 ptrRefArgs.reset(new CComVariant[dispparams.cArgs]);
1816 arArgs = ptrArgs.get();
1817 arRefArgs = ptrRefArgs.get();
1818 try
1819 {
1820 for (i = 0; i < (sal_Int32) dispparams.cArgs; i++)
1821 {
1822 revIndex= dispparams.cArgs - i -1;
1823 arRefArgs[revIndex].byref=0;
1824 Any anyArg;
1825 if ( i < nUnoArgs)
1826 anyArg= Params.getConstArray()[i];
1827
1828 //Test if the current parameter is a "vararg" parameter.
1829 if (bVarargParam || (aFuncDesc->cParamsOpt == -1 &&
1830 aFuncDesc->cParams == (i + 1)))
1831 { //This parameter is from the variable argument list. There is no
1832 //type info available, except that it must be a VARIANT
1833 bVarargParam = true;
1834 }
1835
1836 unsigned short paramFlags = PARAMFLAG_FOPT | PARAMFLAG_FIN;
1837 VARTYPE varType = VT_VARIANT;
1838 if ( ! bVarargParam)
1839 {
1840 paramFlags =
1841 aFuncDesc->lprgelemdescParam[i].paramdesc.wParamFlags;
1842 varType = getElementTypeDesc(
1843 & aFuncDesc->lprgelemdescParam[i].tdesc);
1844 }
1845 //Make sure that there is a UNO parameter for every
1846 // expected parameter. If there is no UNO parameter where the
1847 // called function expects one, then it must be optional. Otherwise
1848 // its a UNO programming error.
1849 if (i >= nUnoArgs && !(paramFlags & PARAMFLAG_FOPT))
1850 {
1851 OUStringBuffer buf(256);
1852 buf.appendAscii("ole automation bridge: The called function expects an argument at"
1853 "position: "); //a different number of arguments")),
1854 buf.append(OUString::valueOf((sal_Int32) i));
1855 buf.appendAscii(" (index starting at 0).");
1856 throw IllegalArgumentException( buf.makeStringAndClear(),
1857 Reference<XInterface>(), (sal_Int16) i);
1858 }
1859
1860 // Property Put arguments
1861 if (anyArg.getValueType() == getCppuType((PropertyPutArgument*)0))
1862 {
1863 PropertyPutArgument arg;
1864 anyArg >>= arg;
1865 anyArg <<= arg.Value;
1866 }
1867 // named argument
1868 if (anyArg.getValueType() == getCppuType((NamedArgument*) 0))
1869 {
1870 NamedArgument aNamedArgument;
1871 anyArg >>= aNamedArgument;
1872 anyArg <<= aNamedArgument.Value;
1873 }
1874 // out param
1875 if (paramFlags & PARAMFLAG_FOUT &&
1876 ! (paramFlags & PARAMFLAG_FIN) )
1877 {
1878 VARTYPE type = ::sal::static_int_cast< VARTYPE, int >( varType ^ VT_BYREF );
1879 if (i < nUnoArgs)
1880 {
1881 arRefArgs[revIndex].vt= type;
1882 }
1883 else
1884 {
1885 //optional arg
1886 arRefArgs[revIndex].vt = VT_ERROR;
1887 arRefArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
1888 }
1889 if( type == VT_VARIANT )
1890 {
1891 arArgs[revIndex].vt= VT_VARIANT | VT_BYREF;
1892 arArgs[revIndex].byref= &arRefArgs[revIndex];
1893 }
1894 else
1895 {
1896 arArgs[revIndex].vt= varType;
1897 if (type == VT_DECIMAL)
1898 arArgs[revIndex].byref= & arRefArgs[revIndex].decVal;
1899 else
1900 arArgs[revIndex].byref= & arRefArgs[revIndex].byref;
1901 }
1902 }
1903 // in/out + in byref params
1904 else if (varType & VT_BYREF)
1905 {
1906 VARTYPE type = ::sal::static_int_cast< VARTYPE, int >( varType ^ VT_BYREF );
1907 CComVariant var;
1908
1909 if (i < nUnoArgs && anyArg.getValueTypeClass() != TypeClass_VOID)
1910 {
1911 anyToVariant( & arRefArgs[revIndex], anyArg, type);
1912 }
1913 else if (paramFlags & PARAMFLAG_FHASDEFAULT)
1914 {
1915 //optional arg with default
1916 VariantCopy( & arRefArgs[revIndex],
1917 & aFuncDesc->lprgelemdescParam[i].paramdesc.
1918 pparamdescex->varDefaultValue);
1919 }
1920 else
1921 {
1922 //optional arg
1923 //e.g: call func(x) in basic : func() ' no arg supplied
1924 OSL_ASSERT(paramFlags & PARAMFLAG_FOPT);
1925 arRefArgs[revIndex].vt = VT_ERROR;
1926 arRefArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
1927 }
1928
1929 // Set the converted arguments in the array which will be
1930 // DISPPARAMS::rgvarg
1931 // byref arg VT_XXX |VT_BYREF
1932 arArgs[revIndex].vt = varType;
1933 if (revIndex == 0 && aFuncDesc->invkind == INVOKE_PROPERTYPUT)
1934 {
1935 arArgs[revIndex] = arRefArgs[revIndex];
1936 }
1937 else if (type == VT_DECIMAL)
1938 {
1939 arArgs[revIndex].byref= & arRefArgs[revIndex].decVal;
1940 }
1941 else if (type == VT_VARIANT)
1942 {
1943 if ( ! (paramFlags & PARAMFLAG_FOUT))
1944 arArgs[revIndex] = arRefArgs[revIndex];
1945 else
1946 arArgs[revIndex].byref = & arRefArgs[revIndex];
1947 }
1948 else
1949 {
1950 arArgs[revIndex].byref = & arRefArgs[revIndex].byref;
1951 arArgs[revIndex].vt = ::sal::static_int_cast< VARTYPE, int >( arRefArgs[revIndex].vt | VT_BYREF );
1952 }
1953
1954 }
1955 // in parameter no VT_BYREF except for array, interfaces
1956 else
1957 { // void any stands for optional param
1958 if (i < nUnoArgs && anyArg.getValueTypeClass() != TypeClass_VOID)
1959 {
1960 anyToVariant( & arArgs[revIndex], anyArg, varType);
1961 }
1962 //optional arg but no void any supplied
1963 //Basic: obj.func() ' first parameter left out because it is optional
1964 else if (paramFlags & PARAMFLAG_FHASDEFAULT)
1965 {
1966 //optional arg with defaulteithter as direct arg : VT_XXX or
1967 VariantCopy( & arArgs[revIndex],
1968 & aFuncDesc->lprgelemdescParam[i].paramdesc.
1969 pparamdescex->varDefaultValue);
1970 }
1971 else if (paramFlags & PARAMFLAG_FOPT)
1972 {
1973 arArgs[revIndex].vt = VT_ERROR;
1974 arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
1975 }
1976 else
1977 {
1978 arArgs[revIndex].vt = VT_EMPTY;
1979 arArgs[revIndex].lVal = 0;
1980 }
1981 }
1982 }
1983 }
1984 catch (IllegalArgumentException & e)
1985 {
1986 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, sal_Int32 >( i );
1987 throw;
1988 }
1989 catch (CannotConvertException & e)
1990 {
1991 e.ArgumentIndex = i;
1992 throw;
1993 }
1994 dispparams.rgvarg= arArgs;
1995 // invoking OLE method
1996 DWORD localeId = LOCALE_USER_DEFAULT;
1997 result = m_spDispatch->Invoke(aFuncDesc->memid,
1998 IID_NULL,
1999 localeId,
2000 ::sal::static_int_cast< WORD, INVOKEKIND >( aFuncDesc->invkind ),
2001 &dispparams,
2002 &varResult,
2003 &excepinfo,
2004 &uArgErr);
2005
2006 // converting return value and out parameter back to UNO
2007 if (result == S_OK)
2008 {
2009
2010 // allocate space for the out param Sequence and indices Sequence
2011 int outParamsCount= 0; // includes in/out parameter
2012 for (int i = 0; i < aFuncDesc->cParams; i++)
2013 {
2014 if (aFuncDesc->lprgelemdescParam[i].paramdesc.wParamFlags &
2015 PARAMFLAG_FOUT)
2016 outParamsCount++;
2017 }
2018
2019 OutParamIndex.realloc(outParamsCount);
2020 OutParam.realloc(outParamsCount);
2021 // Convert out params
2022 if (outParamsCount)
2023 {
2024 int outParamIndex=0;
2025 for (int paramIndex = 0; paramIndex < nUnoArgs; paramIndex ++)
2026 {
2027 //Determine the index within the method sinature
2028 int realParamIndex = paramIndex;
2029 int revParamIndex = dispparams.cArgs - paramIndex - 1;
2030 if (Params[paramIndex].getValueType()
2031 == getCppuType((NamedArgument*) 0))
2032 {
2033 //dispparams.rgdispidNamedArgs contains the mapping from index
2034 //of named args list to index of parameter list
2035 realParamIndex = dispparams.rgdispidNamedArgs[revParamIndex];
2036 }
2037
2038 // no named arg, always come before named args
2039 if (! (aFuncDesc->lprgelemdescParam[realParamIndex].paramdesc.wParamFlags
2040 & PARAMFLAG_FOUT))
2041 continue;
2042 Any outAny;
2043 // variantToAny is called with the "reduce range" parameter set to sal_False.
2044 // That causes VT_I4 values not to be converted down to a "lower" type. That
2045 // feature exist for JScript only because it only uses VT_I4 for integer types.
2046 try
2047 {
2048 variantToAny( & arRefArgs[revParamIndex], outAny, sal_False );
2049 }
2050 catch (IllegalArgumentException & e)
2051 {
2052 e.ArgumentPosition = (sal_Int16)paramIndex;
2053 throw;
2054 }
2055 catch (CannotConvertException & e)
2056 {
2057 e.ArgumentIndex = paramIndex;
2058 throw;
2059 }
2060 OutParam[outParamIndex] = outAny;
2061 OutParamIndex[outParamIndex] = ::sal::static_int_cast< sal_Int16, int >( paramIndex );
2062 outParamIndex++;
2063 }
2064 OutParam.realloc(outParamIndex);
2065 OutParamIndex.realloc(outParamIndex);
2066 }
2067 // Return value
2068 variantToAny(&varResult, ret, sal_False);
2069 }
2070
2071 // map error codes to exceptions
2072 OUString message;
2073 switch (result)
2074 {
2075 case S_OK:
2076 break;
2077 case DISP_E_BADPARAMCOUNT:
2078 throw IllegalArgumentException(OUSTR("[automation bridge] Wrong "
2079 "number of arguments. Object returned DISP_E_BADPARAMCOUNT."),
2080 0, 0);
2081 break;
2082 case DISP_E_BADVARTYPE:
2083 throw RuntimeException(OUSTR("[automation bridge] One or more "
2084 "arguments have the wrong type. Object returned "
2085 "DISP_E_BADVARTYPE."), 0);
2086 break;
2087 case DISP_E_EXCEPTION:
2088 message = OUSTR("[automation bridge]: ");
2089 message += OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription),
2090 ::SysStringLen(excepinfo.bstrDescription));
2091 throw InvocationTargetException(message, Reference<XInterface>(), Any());
2092 break;
2093 case DISP_E_MEMBERNOTFOUND:
2094 message = OUSTR("[automation bridge]: A function with the name \"")
2095 + sFuncName + OUSTR("\" is not supported. Object returned "
2096 "DISP_E_MEMBERNOTFOUND.");
2097 throw IllegalArgumentException(message, 0, 0);
2098 break;
2099 case DISP_E_NONAMEDARGS:
2100 throw IllegalArgumentException(OUSTR("[automation bridge] Object "
2101 "returned DISP_E_NONAMEDARGS"),0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
2102 break;
2103 case DISP_E_OVERFLOW:
2104 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[automation bridge] Call failed.")),
2105 static_cast<XInterface*>(
2106 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
2107 break;
2108 case DISP_E_PARAMNOTFOUND:
2109 throw IllegalArgumentException(OUSTR("[automation bridge]Call failed."
2110 "Object returned DISP_E_PARAMNOTFOUND."),
2111 0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
2112 break;
2113 case DISP_E_TYPEMISMATCH:
2114 throw CannotConvertException(OUSTR("[automation bridge] Call failed. "
2115 "Object returned DISP_E_TYPEMISMATCH"),
2116 static_cast<XInterface*>(
2117 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr);
2118 break;
2119 case DISP_E_UNKNOWNINTERFACE:
2120 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
2121 "Object returned DISP_E_UNKNOWNINTERFACE."),0);
2122 break;
2123 case DISP_E_UNKNOWNLCID:
2124 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
2125 "Object returned DISP_E_UNKNOWNLCID."),0);
2126 break;
2127 case DISP_E_PARAMNOTOPTIONAL:
2128 throw CannotConvertException(OUSTR("[automation bridge] Call failed."
2129 "Object returned DISP_E_PARAMNOTOPTIONAL"),
2130 static_cast<XInterface*>(static_cast<XWeak*>(this)),
2131 TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
2132 break;
2133 default:
2134 throw RuntimeException();
2135 break;
2136 }
2137
2138 return ret;
2139 }
2140
getFuncDescForInvoke(const OUString & sFuncName,const Sequence<Any> & seqArgs,FUNCDESC ** pFuncDesc)2141 void IUnknownWrapper_Impl::getFuncDescForInvoke(const OUString & sFuncName,
2142 const Sequence<Any> & seqArgs,
2143 FUNCDESC** pFuncDesc)
2144 {
2145 int nUnoArgs = seqArgs.getLength();
2146 const Any * arArgs = seqArgs.getConstArray();
2147 ITypeInfo* pInfo = getTypeInfo();
2148
2149 //If the last of the positional arguments is a PropertyPutArgument
2150 //then obtain the type info for the property put operation.
2151
2152 //The property value is always the last argument, in a positional argument list
2153 //or in a list of named arguments. A PropertyPutArgument is actually a named argument
2154 //hence it must not be put in an extra NamedArgument structure
2155 if (nUnoArgs > 0 &&
2156 arArgs[nUnoArgs - 1].getValueType() == getCppuType((PropertyPutArgument*) 0))
2157 {
2158 // DISPATCH_PROPERTYPUT
2159 FuncDesc aDescGet(pInfo);
2160 FuncDesc aDescPut(pInfo);
2161 VarDesc aVarDesc(pInfo);
2162 getPropDesc(sFuncName, & aDescGet, & aDescPut, & aVarDesc);
2163 if ( ! aDescPut)
2164 {
2165 throw IllegalArgumentException(
2166 OUSTR("[automation bridge] The object does not have a writeable property: ")
2167 + sFuncName, Reference<XInterface>(), 0);
2168 }
2169 *pFuncDesc = aDescPut.Detach();
2170 }
2171 else
2172 { // DISPATCH_METHOD
2173 FuncDesc aFuncDesc(pInfo);
2174 getFuncDesc(sFuncName, & aFuncDesc);
2175 if ( ! aFuncDesc)
2176 {
2177 // Fallback: DISPATCH_PROPERTYGET can mostly be called as
2178 // DISPATCH_METHOD
2179 ITypeInfo * pInfo = getTypeInfo();
2180 FuncDesc aDescPut(pInfo);
2181 VarDesc aVarDesc(pInfo);
2182 getPropDesc(sFuncName, & aFuncDesc, & aDescPut, & aVarDesc);
2183 if ( ! aFuncDesc )
2184 {
2185 throw IllegalArgumentException(
2186 OUSTR("[automation bridge] The object does not have a function"
2187 "or readable property \"")
2188 + sFuncName, Reference<XInterface>(), 0);
2189 }
2190 }
2191 *pFuncDesc = aFuncDesc.Detach();
2192 }
2193 }
getDispid(const OUString & sFuncName,DISPID * id)2194 bool IUnknownWrapper_Impl::getDispid(const OUString& sFuncName, DISPID * id)
2195 {
2196 OSL_ASSERT(m_spDispatch);
2197 LPOLESTR lpsz = const_cast<LPOLESTR> (reinterpret_cast<LPCOLESTR>(sFuncName.getStr()));
2198 HRESULT hr = m_spDispatch->GetIDsOfNames(IID_NULL, &lpsz, 1, LOCALE_USER_DEFAULT, id);
2199 return hr == S_OK ? true : false;
2200 }
getFuncDesc(const OUString & sFuncName,FUNCDESC ** pFuncDesc)2201 void IUnknownWrapper_Impl::getFuncDesc(const OUString & sFuncName, FUNCDESC ** pFuncDesc)
2202
2203 {
2204 OSL_ASSERT( * pFuncDesc == 0);
2205 buildComTlbIndex();
2206 typedef TLBFuncIndexMap::const_iterator cit;
2207 typedef TLBFuncIndexMap::iterator it;
2208 //We assume there is only one entry with the function name. A property
2209 //would have two entries.
2210 cit itIndex= m_mapComFunc.find(sFuncName);
2211 if (itIndex == m_mapComFunc.end())
2212 {
2213 //try case insensive with IDispatch::GetIDsOfNames
2214 DISPID id;
2215 if (getDispid(sFuncName, &id))
2216 {
2217 CComBSTR memberName;
2218 unsigned int pcNames=0;
2219 // get the case sensitive name
2220 if( SUCCEEDED(getTypeInfo()->GetNames( id, & memberName, 1, &pcNames)))
2221 {
2222 //get the associated index and add an entry to the map
2223 //with the name sFuncName which differs in the casing of the letters to
2224 //the actual name as obtained from ITypeInfo
2225 cit itOrg = m_mapComFunc.find(OUString(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName))));
2226 OSL_ASSERT(itOrg != m_mapComFunc.end());
2227 itIndex =
2228 m_mapComFunc.insert( TLBFuncIndexMap::value_type
2229 ( make_pair(sFuncName, itOrg->second ) ));
2230 }
2231 }
2232 }
2233
2234 #if OSL_DEBUG_LEVEL >= 1
2235 // There must only be one entry if sFuncName represents a function or two
2236 // if it is a property
2237 pair<cit, cit> p = m_mapComFunc.equal_range(sFuncName.toAsciiLowerCase());
2238 int numEntries = 0;
2239 for ( ;p.first != p.second; p.first ++, numEntries ++);
2240 OSL_ASSERT( ! (numEntries > 3) );
2241 #endif
2242 if( itIndex != m_mapComFunc.end())
2243 {
2244 ITypeInfo* pType= getTypeInfo();
2245 FUNCDESC * pDesc = NULL;
2246 if (SUCCEEDED(pType->GetFuncDesc(itIndex->second, & pDesc)))
2247 {
2248 if (pDesc->invkind == INVOKE_FUNC)
2249 {
2250 (*pFuncDesc) = pDesc;
2251 }
2252 else
2253 {
2254 pType->ReleaseFuncDesc(pDesc);
2255 }
2256 }
2257 else
2258 {
2259 throw BridgeRuntimeError(OUSTR("[automation bridge] Could not get "
2260 "FUNCDESC for ") + sFuncName);
2261 }
2262 }
2263 //else no entry found for sFuncName, pFuncDesc will not be filled in
2264 }
2265
getPropDesc(const OUString & sFuncName,FUNCDESC ** pFuncDescGet,FUNCDESC ** pFuncDescPut,VARDESC ** pVarDesc)2266 void IUnknownWrapper_Impl::getPropDesc(const OUString & sFuncName, FUNCDESC ** pFuncDescGet,
2267 FUNCDESC** pFuncDescPut, VARDESC** pVarDesc)
2268 {
2269 OSL_ASSERT( * pFuncDescGet == 0 && * pFuncDescPut == 0);
2270 buildComTlbIndex();
2271 typedef TLBFuncIndexMap::const_iterator cit;
2272 pair<cit, cit> p = m_mapComFunc.equal_range(sFuncName);
2273 if (p.first == m_mapComFunc.end())
2274 {
2275 //try case insensive with IDispatch::GetIDsOfNames
2276 DISPID id;
2277 if (getDispid(sFuncName, &id))
2278 {
2279 CComBSTR memberName;
2280 unsigned int pcNames=0;
2281 // get the case sensitive name
2282 if( SUCCEEDED(getTypeInfo()->GetNames( id, & memberName, 1, &pcNames)))
2283 {
2284 //As opposed to getFuncDesc, we do not add the value because we would
2285 // need to find the get and set description for the property. This would
2286 //mean to iterate over all FUNCDESCs again.
2287 p = m_mapComFunc.equal_range(OUString(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName))));
2288 }
2289 }
2290 }
2291
2292 for ( int i = 0 ;p.first != p.second; p.first ++, i ++)
2293 {
2294 // There are a maximum of two entries, property put and property get
2295 OSL_ASSERT( ! (i > 2) );
2296 ITypeInfo* pType= getTypeInfo();
2297 FUNCDESC * pFuncDesc = NULL;
2298 if (SUCCEEDED( pType->GetFuncDesc(p.first->second, & pFuncDesc)))
2299 {
2300 if (pFuncDesc->invkind == INVOKE_PROPERTYGET)
2301 {
2302 (*pFuncDescGet) = pFuncDesc;
2303 }
2304 else if (pFuncDesc->invkind == INVOKE_PROPERTYPUT ||
2305 pFuncDesc->invkind == INVOKE_PROPERTYPUTREF)
2306 {
2307 //a property can have 3 entries, put, put ref, get
2308 // If INVOKE_PROPERTYPUTREF or INVOKE_PROPERTYPUT is used
2309 //depends on what is found first.
2310 if ( * pFuncDescPut)
2311 {
2312 //we already have found one
2313 pType->ReleaseFuncDesc(pFuncDesc);
2314 }
2315 else
2316 {
2317 (*pFuncDescPut) = pFuncDesc;
2318 }
2319 }
2320 else
2321 {
2322 pType->ReleaseFuncDesc(pFuncDesc);
2323 }
2324 }
2325 //ITypeInfo::GetFuncDesc may even provide a funcdesc for a VARDESC
2326 // with invkind = INVOKE_FUNC. Since this function should only return
2327 //a value for a real property (XInvokation::hasMethod, ..::hasProperty
2328 //we need to make sure that sFuncName represents a real property.
2329 VARDESC * pVD = NULL;
2330 if (SUCCEEDED(pType->GetVarDesc(p.first->second, & pVD)))
2331 (*pVarDesc) = pVD;
2332 }
2333 //else no entry for sFuncName, pFuncDesc will not be filled in
2334 }
2335
lcl_getUserDefinedElementType(ITypeInfo * pTypeInfo,const DWORD nHrefType)2336 VARTYPE lcl_getUserDefinedElementType( ITypeInfo* pTypeInfo, const DWORD nHrefType )
2337 {
2338 VARTYPE _type( VT_NULL );
2339 if ( pTypeInfo )
2340 {
2341 CComPtr<ITypeInfo> spRefInfo;
2342 pTypeInfo->GetRefTypeInfo( nHrefType, &spRefInfo.p );
2343 if ( spRefInfo )
2344 {
2345 TypeAttr attr( spRefInfo );
2346 spRefInfo->GetTypeAttr( &attr );
2347 if ( attr->typekind == TKIND_ENUM )
2348 {
2349 // We use the type of the first enum value.
2350 if ( attr->cVars == 0 )
2351 {
2352 throw BridgeRuntimeError(OUSTR("[automation bridge] Could not obtain type description"));
2353 }
2354 VarDesc var( spRefInfo );
2355 spRefInfo->GetVarDesc( 0, &var );
2356 _type = var->lpvarValue->vt;
2357 }
2358 else if ( attr->typekind == TKIND_INTERFACE )
2359 {
2360 _type = VT_UNKNOWN;
2361 }
2362 else if ( attr->typekind == TKIND_DISPATCH )
2363 {
2364 _type = VT_DISPATCH;
2365 }
2366 else if ( attr->typekind == TKIND_ALIAS )
2367 {
2368 // TKIND_ALIAS is a type that is an alias for another type. So get that alias type.
2369 _type = lcl_getUserDefinedElementType( pTypeInfo, attr->tdescAlias.hreftype );
2370 }
2371 else
2372 {
2373 throw BridgeRuntimeError( OUSTR("[automation bridge] Unhandled user defined type.") );
2374 }
2375 }
2376 }
2377 return _type;
2378 }
2379
getElementTypeDesc(const TYPEDESC * desc)2380 VARTYPE IUnknownWrapper_Impl::getElementTypeDesc(const TYPEDESC *desc)
2381 {
2382 VARTYPE _type( VT_NULL );
2383
2384 if (desc->vt == VT_PTR)
2385 {
2386 _type = getElementTypeDesc(desc->lptdesc);
2387 _type |= VT_BYREF;
2388 }
2389 else if (desc->vt == VT_SAFEARRAY)
2390 {
2391 _type = getElementTypeDesc(desc->lptdesc);
2392 _type |= VT_ARRAY;
2393 }
2394 else if (desc->vt == VT_USERDEFINED)
2395 {
2396 ITypeInfo* thisInfo = getTypeInfo(); //kept by this instance
2397 _type = lcl_getUserDefinedElementType( thisInfo, desc->hreftype );
2398 }
2399 else
2400 {
2401 _type = desc->vt;
2402 }
2403 return _type;
2404 }
2405
buildComTlbIndex()2406 void IUnknownWrapper_Impl::buildComTlbIndex()
2407 {
2408 if ( ! m_bComTlbIndexInit)
2409 {
2410 MutexGuard guard(getBridgeMutex());
2411 {
2412 if ( ! m_bComTlbIndexInit)
2413 {
2414 OUString sError;
2415 ITypeInfo* pType= getTypeInfo();
2416 TypeAttr typeAttr(pType);
2417 if( SUCCEEDED( pType->GetTypeAttr( &typeAttr)))
2418 {
2419 for( long i= 0; i < typeAttr->cFuncs; i++)
2420 {
2421 FuncDesc funcDesc(pType);
2422 if( SUCCEEDED( pType->GetFuncDesc( i, &funcDesc)))
2423 {
2424 CComBSTR memberName;
2425 unsigned int pcNames=0;
2426 if( SUCCEEDED(pType->GetNames( funcDesc->memid, & memberName, 1, &pcNames)))
2427 {
2428 OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName)));
2429 m_mapComFunc.insert( TLBFuncIndexMap::value_type( usName, i));
2430 }
2431 else
2432 {
2433 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2434 "ITypeInfo::GetNames failed.");
2435 }
2436 }
2437 else
2438 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2439 "ITypeInfo::GetFuncDesc failed.");
2440 }
2441
2442 //If we create an Object in JScript and a a property then it
2443 //has VARDESC instead of FUNCDESC
2444 for (long i = 0; i < typeAttr->cVars; i++)
2445 {
2446 VarDesc varDesc(pType);
2447 if (SUCCEEDED(pType->GetVarDesc(i, & varDesc)))
2448 {
2449 CComBSTR memberName;
2450 unsigned int pcNames = 0;
2451 if (SUCCEEDED(pType->GetNames(varDesc->memid, & memberName, 1, &pcNames)))
2452 {
2453 if (varDesc->varkind == VAR_DISPATCH)
2454 {
2455 OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName)));
2456 m_mapComFunc.insert(TLBFuncIndexMap::value_type(
2457 usName, i));
2458 }
2459 }
2460 else
2461 {
2462 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2463 "ITypeInfo::GetNames failed.");
2464 }
2465 }
2466 else
2467 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2468 "ITypeInfo::GetVarDesc failed.");
2469
2470 }
2471 }
2472 else
2473 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2474 "ITypeInfo::GetTypeAttr failed.");
2475
2476 if (sError.getLength())
2477 {
2478 throw BridgeRuntimeError(sError);
2479 }
2480
2481 m_bComTlbIndexInit = true;
2482 }
2483 }
2484 }
2485 }
2486
getTypeInfo()2487 ITypeInfo* IUnknownWrapper_Impl::getTypeInfo()
2488 {
2489 if( !m_spDispatch)
2490 {
2491 throw BridgeRuntimeError(OUSTR("The object has no IDispatch interface!"));
2492 }
2493
2494 if( !m_spTypeInfo )
2495 {
2496 MutexGuard guard(getBridgeMutex());
2497 if( ! m_spTypeInfo)
2498 {
2499 CComPtr< ITypeInfo > spType;
2500 if( SUCCEEDED( m_spDispatch->GetTypeInfo( 0, LOCALE_USER_DEFAULT, &spType.p)))
2501
2502 {
2503 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
2504
2505 //If this is a dual interface then TYPEATTR::typekind is usually TKIND_INTERFACE
2506 //We need to get the type description for TKIND_DISPATCH
2507 TypeAttr typeAttr(spType.p);
2508 if( SUCCEEDED(spType->GetTypeAttr( &typeAttr)))
2509 {
2510 if (typeAttr->typekind == TKIND_INTERFACE &&
2511 typeAttr->wTypeFlags & TYPEFLAG_FDUAL)
2512 {
2513 HREFTYPE refDispatch;
2514 if (SUCCEEDED(spType->GetRefTypeOfImplType(::sal::static_int_cast< UINT, int >( -1 ), &refDispatch)))
2515 {
2516 CComPtr<ITypeInfo> spTypeDisp;
2517 if (SUCCEEDED(spType->GetRefTypeInfo(refDispatch, & spTypeDisp)))
2518 m_spTypeInfo= spTypeDisp;
2519 }
2520 else
2521 {
2522 throw BridgeRuntimeError(
2523 OUSTR("[automation bridge] Could not obtain type information "
2524 "for dispatch interface." ));
2525 }
2526 }
2527 else if (typeAttr->typekind == TKIND_DISPATCH)
2528 {
2529 m_spTypeInfo= spType;
2530 }
2531 else
2532 {
2533 throw BridgeRuntimeError(
2534 OUSTR("[automation bridge] Automation object does not "
2535 "provide type information."));
2536 }
2537 }
2538 }
2539 else
2540 {
2541 throw BridgeRuntimeError(OUSTR("[automation bridge]The dispatch object does not "
2542 "support ITypeInfo!"));
2543 }
2544 }
2545 }
2546 return m_spTypeInfo;
2547 }
2548
2549 } // end namespace
2550
2551