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