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