LibreOffice Module extensions (master) 1
unoobjw.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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// Documentation pointers for recent work:
21//
22// https://www.codeproject.com/Articles/9014/Understanding-COM-Event-Handling
23// https://blogs.msdn.microsoft.com/ericlippert/2005/02/15/why-does-wscript-connectobject-not-always-work/
24
25#include "ole2uno.hxx"
26
27#include <stdio.h>
28#include <list>
29#include <sstream>
30#include <unordered_map>
31#include <vector>
32
33#if defined _MSC_VER && defined __clang__
34#pragma clang diagnostic push
35#pragma clang diagnostic ignored "-Wall"
36#pragma clang diagnostic ignored "-Wattributes"
37#pragma clang diagnostic ignored "-Wdelete-incomplete"
38#pragma clang diagnostic ignored "-Wdynamic-class-memaccess"
39#pragma clang diagnostic ignored "-Wextra"
40#pragma clang diagnostic ignored "-Wint-to-pointer-cast"
41#pragma clang diagnostic ignored "-Winvalid-noreturn"
42#pragma clang diagnostic ignored "-Wmicrosoft"
43#pragma clang diagnostic ignored "-Wnon-pod-varargs"
44#pragma clang diagnostic ignored "-Wnonportable-include-path"
45#pragma clang diagnostic ignored "-Wsequence-point"
46#pragma clang diagnostic ignored "-Wtypename-missing"
47#endif
48#include <atlbase.h>
49#include <atlcom.h>
50#if defined _MSC_VER && defined __clang__
51#pragma clang diagnostic pop
52#endif
53#include <comdef.h>
54
55#include <osl/diagnose.h>
57#include <rtl/ref.hxx>
58#include <rtl/ustring.hxx>
59#include <sal/log.hxx>
60#include <com/sun/star/beans/MethodConcept.hpp>
61#include <com/sun/star/beans/PropertyConcept.hpp>
62#include <com/sun/star/lang/NoSuchMethodException.hpp>
63#include <com/sun/star/script/CannotConvertException.hpp>
64#include <com/sun/star/script/FailReason.hpp>
65#include <com/sun/star/reflection/theCoreReflection.hpp>
66#include <com/sun/star/reflection/ParamInfo.hpp>
67#include <com/sun/star/beans/XExactName.hpp>
68#include <com/sun/star/container/NoSuchElementException.hpp>
69#include <com/sun/star/container/XEnumeration.hpp>
70#include <com/sun/star/container/XEnumerationAccess.hpp>
71
72#include <com/sun/star/beans/XMaterialHolder.hpp>
73#include <com/sun/star/script/XInvocation2.hpp>
74#include <com/sun/star/script/MemberType.hpp>
75#include <com/sun/star/reflection/XIdlReflection.hpp>
76#include <ooo/vba/XCollection.hpp>
77#include <ooo/vba/XConnectable.hpp>
78#include <ooo/vba/XConnectionPoint.hpp>
79#include <ooo/vba/XSink.hpp>
80#include <ooo/vba/msforms/XCheckBox.hpp>
81#include <osl/interlck.h>
82#include <com/sun/star/uno/genfunc.h>
89#include <o3tl/safeint.hxx>
90
91#include "comifaces.hxx"
92#include "jscriptclasses.hxx"
93#include "unotypewrapper.hxx"
94#include "oleobjw.hxx"
95#include "unoobjw.hxx"
96#include "servprov.hxx"
97
98using namespace osl;
99using namespace cppu;
100using namespace com::sun::star::uno;
101using namespace com::sun::star::beans;
102using namespace com::sun::star::container;
103using namespace com::sun::star::script;
104using namespace com::sun::star::lang;
105using namespace com::sun::star::bridge::ModelDependent;
106using namespace com::sun::star::reflection;
107
108std::unordered_map<sal_uIntPtr, WeakReference<XInterface> > UnoObjToWrapperMap;
109static bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource);
110static bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource);
111static HRESULT mapCannotConvertException(const CannotConvertException &e, unsigned int * puArgErr);
112
113/* Does not throw any exceptions.
114 Param pInfo can be NULL.
115 */
116static void writeExcepinfo(EXCEPINFO * pInfo, const OUString& message)
117{
118 if (pInfo != nullptr)
119 {
120 pInfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
121 pInfo->bstrSource = SysAllocString(L"[automation bridge] ");
122 pInfo->bstrDescription = SysAllocString(o3tl::toW(message.getStr()));
123 }
124}
125
127 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
128 UnoConversionUtilities<InterfaceOleWrapper>( xFactory, unoWrapperClass, comWrapperClass),
129 m_defaultValueType( 0)
130{
131}
132
134{
135 MutexGuard guard(getBridgeMutex());
136 // remove entries in global map
137 auto it = UnoObjToWrapperMap.find( reinterpret_cast<sal_uIntPtr>(m_xOrigin.get()));
138 if(it != UnoObjToWrapperMap.end())
139 UnoObjToWrapperMap.erase(it);
140}
141
142COM_DECLSPEC_NOTHROW STDMETHODIMP InterfaceOleWrapper::QueryInterface(REFIID riid, void ** ppv)
143{
145
146 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::QueryInterface(" << riid << ")");
147
148 HRESULT ret= S_OK;
149
150 if( !ppv)
151 return E_POINTER;
152
153 if(IsEqualIID(riid, IID_IUnknown))
154 {
155 AddRef();
156 *ppv = static_cast<IUnknown*>(static_cast<IDispatch*>(this));
157 SAL_INFO("extensions.olebridge", " " << *ppv);
158 }
159 else if (IsEqualIID(riid, IID_IDispatch))
160 {
161 AddRef();
162 *ppv = static_cast<IDispatch*>(this);
163 SAL_INFO("extensions.olebridge", " " << *ppv);
164 }
165 else if (IsEqualIID(riid, IID_IProvideClassInfo))
166 {
167 Reference<ooo::vba::XConnectable> xConnectable(m_xOrigin, UNO_QUERY);
168 if (!xConnectable.is())
169 return E_NOINTERFACE;
170 AddRef();
171 *ppv = static_cast<IProvideClassInfo*>(this);
172 SAL_INFO("extensions.olebridge", " " << *ppv);
173 }
174 else if (IsEqualIID(riid, IID_IConnectionPointContainer))
175 {
176 Reference<ooo::vba::XConnectable> xConnectable(m_xOrigin, UNO_QUERY);
177 if (!xConnectable.is())
178 return E_NOINTERFACE;
179 AddRef();
180 *ppv = static_cast<IConnectionPointContainer*>(this);
181 SAL_INFO("extensions.olebridge", " " << *ppv);
182 }
183 else if( IsEqualIID( riid, __uuidof( IUnoObjectWrapper)))
184 {
185 AddRef();
186 *ppv= static_cast<IUnoObjectWrapper*>(this);
187 SAL_INFO("extensions.olebridge", " " << *ppv);
188 }
189 else
190 ret= E_NOINTERFACE;
191 return ret;
192}
193
194COM_DECLSPEC_NOTHROW STDMETHODIMP_(ULONG) InterfaceOleWrapper::AddRef()
195{
196 acquire();
197 // does not need to guard because one should not rely on the return value of
198 // AddRef anyway
199 return m_refCount;
200}
201
202COM_DECLSPEC_NOTHROW STDMETHODIMP_(ULONG) InterfaceOleWrapper::Release()
203{
204 ULONG n= m_refCount;
205 release();
206 return n - 1;
207}
208
209// IUnoObjectWrapper --------------------------------------------------------
210COM_DECLSPEC_NOTHROW STDMETHODIMP InterfaceOleWrapper::getWrapperXInterface( Reference<XInterface>* pXInt)
211{
212 pXInt->set( static_cast<XWeak*>( this), UNO_QUERY);
213 return pXInt->is() ? S_OK : E_FAIL;
214}
215COM_DECLSPEC_NOTHROW STDMETHODIMP InterfaceOleWrapper::getOriginalUnoObject( Reference<XInterface>* pXInt)
216{
217 *pXInt= m_xOrigin;
218 return m_xOrigin.is() ? S_OK : E_FAIL;
219}
220COM_DECLSPEC_NOTHROW STDMETHODIMP InterfaceOleWrapper::getOriginalUnoStruct( Any * pStruct)
221{
223
224 HRESULT ret= E_FAIL;
225 if( !m_xOrigin.is())
226 {
227 Reference<XMaterialHolder> xMatHolder( m_xInvocation, UNO_QUERY);
228 if( xMatHolder.is())
229 {
230 Any any = xMatHolder->getMaterial();
231 if( any.getValueTypeClass() == TypeClass_STRUCT)
232 {
233 *pStruct= any;
234 ret= S_OK;
235 }
236 }
237 }
238 return ret;
239}
240
241COM_DECLSPEC_NOTHROW STDMETHODIMP InterfaceOleWrapper::GetTypeInfoCount( UINT *pctinfo )
242{
243 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetTypeInfoCount");
244
245 if (!pctinfo)
246 return E_POINTER;
247
248 *pctinfo = 1;
249
250 return S_OK;
251}
252
253namespace {
254
255class CXTypeInfo : public ITypeInfo,
256 public CComObjectRoot
257{
258public:
259 enum class Kind { COCLASS, MAIN, OUTGOING };
260
261#if defined __clang__
262#pragma clang diagnostic push
263#pragma clang diagnostic ignored "-Wunused-function"
264#endif
265 BEGIN_COM_MAP(CXTypeInfo)
266#if defined __clang__
267#pragma clang diagnostic pop
268#endif
269 COM_INTERFACE_ENTRY(ITypeInfo)
270#if defined __clang__
271#pragma clang diagnostic push
272#pragma clang diagnostic ignored "-Winconsistent-missing-override"
273#pragma clang diagnostic ignored "-Wunused-function"
274#endif
275 END_COM_MAP()
276#if defined __clang__
277#pragma clang diagnostic pop
278#endif
279
280 DECLARE_NOT_AGGREGATABLE(CXTypeInfo)
281
282 virtual ~CXTypeInfo() {}
283
284 void InitForCoclass(Reference<XInterface> xOrigin,
285 const OUString& sImplementationName,
286 const IID& rIID,
288 void InitForClassItself(Reference<XInterface> xOrigin,
289 const OUString& sImplementationName,
290 const IID& rIID,
292 void InitForOutgoing(Reference<XInterface> xOrigin,
293 const OUString& sInterfaceName,
294 const IID& rIID,
296 Type aType);
297 virtual HRESULT STDMETHODCALLTYPE GetTypeAttr(TYPEATTR **ppTypeAttr) override;
298 virtual HRESULT STDMETHODCALLTYPE GetTypeComp(ITypeComp **ppTComp) override;
299 virtual HRESULT STDMETHODCALLTYPE GetFuncDesc(UINT index,
300 FUNCDESC **ppFuncDesc) override;
301 virtual HRESULT STDMETHODCALLTYPE GetVarDesc(UINT index,
302 VARDESC **ppVarDesc) override;
303 virtual HRESULT STDMETHODCALLTYPE GetNames(MEMBERID memid,
304 BSTR *rgBstrNames,
305 UINT cMaxNames,
306 UINT *pcNames) override;
307 virtual HRESULT STDMETHODCALLTYPE GetRefTypeOfImplType(UINT index,
308 HREFTYPE *pRefType) override;
309 virtual HRESULT STDMETHODCALLTYPE GetImplTypeFlags(UINT index,
310 INT *pImplTypeFlags) override;
311 virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(LPOLESTR *rgszNames,
312 UINT cNames,
313 MEMBERID *pMemId) override;
314 virtual HRESULT STDMETHODCALLTYPE Invoke(PVOID pvInstance,
315 MEMBERID memid,
316 WORD wFlags,
317 DISPPARAMS *pDispParams,
318 VARIANT *pVarResult,
319 EXCEPINFO *pExcepInfo,
320 UINT *puArgErr) override;
321 virtual HRESULT STDMETHODCALLTYPE GetDocumentation(MEMBERID memid,
322 BSTR *pBstrName,
323 BSTR *pBstrDocString,
324 DWORD *pdwHelpContext,
325 BSTR *pBstrHelpFile) override;
326 virtual HRESULT STDMETHODCALLTYPE GetDllEntry(MEMBERID memid,
327 INVOKEKIND invKind,
328 BSTR *pBstrDllName,
329 BSTR *pBstrName,
330 WORD *pwOrdinal) override;
331 virtual HRESULT STDMETHODCALLTYPE GetRefTypeInfo(HREFTYPE hRefType,
332 ITypeInfo **ppTInfo) override;
333 virtual HRESULT STDMETHODCALLTYPE AddressOfMember(MEMBERID memid,
334 INVOKEKIND invKind,
335 PVOID *ppv) override;
336 virtual HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter,
337 REFIID riid,
338 PVOID *ppvObj) override;
339 virtual HRESULT STDMETHODCALLTYPE GetMops(MEMBERID memid,
340 BSTR *pBstrMops) override;
341 virtual HRESULT STDMETHODCALLTYPE GetContainingTypeLib(ITypeLib **ppTLib,
342 UINT *pIndex) override;
343 virtual void STDMETHODCALLTYPE ReleaseTypeAttr(TYPEATTR *pTypeAttr) override;
344 virtual void STDMETHODCALLTYPE ReleaseFuncDesc(FUNCDESC *pFuncDesc) override;
345 virtual void STDMETHODCALLTYPE ReleaseVarDesc(VARDESC *pVarDesc) override;
346
347private:
348 Kind meKind;
349 Reference<XInterface> mxOrigin;
350 OUString msImplementationName;
351 OUString msInterfaceName;
352 IID maIID;
354 Type maType;
355};
356
357class CXTypeLib : public ITypeLib,
358 public CComObjectRoot
359{
360public:
361#if defined __clang__
362#pragma clang diagnostic push
363#pragma clang diagnostic ignored "-Wunused-function"
364#endif
365 BEGIN_COM_MAP(CXTypeLib)
366#if defined __clang__
367#pragma clang diagnostic pop
368#endif
369 COM_INTERFACE_ENTRY(ITypeLib)
370#if defined __clang__
371#pragma clang diagnostic push
372#pragma clang diagnostic ignored "-Winconsistent-missing-override"
373#pragma clang diagnostic ignored "-Wunused-function"
374#endif
375 END_COM_MAP()
376#if defined __clang__
377#pragma clang diagnostic pop
378#endif
379
380 DECLARE_NOT_AGGREGATABLE(CXTypeLib)
381
382 virtual ~CXTypeLib() {}
383
384 void Init(Reference<XInterface> xOrigin,
385 const OUString& sImplementationName,
387 {
388 SAL_INFO("extensions.olebridge", this << "@CXTypeLib::Init for " << sImplementationName);
389 mxOrigin = xOrigin;
390 msImplementationName = sImplementationName;
391 mxMSF = xMSF;
392 }
393
394 virtual UINT STDMETHODCALLTYPE GetTypeInfoCount() override
395 {
396 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoCount");
397 return 1;
398 }
399
400 virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT,
401 ITypeInfo **) override
402 {
403 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfo: E_NOTIMPL");
404 return E_NOTIMPL;
405 }
406
407 virtual HRESULT STDMETHODCALLTYPE GetTypeInfoType(UINT,
408 TYPEKIND *) override
409 {
410 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoType: E_NOTIMPL");
411 return E_NOTIMPL;
412 }
413
414 virtual HRESULT STDMETHODCALLTYPE GetTypeInfoOfGuid(REFGUID guid,
415 ITypeInfo **ppTInfo) override
416 {
418
419 SAL_INFO("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoOfGuid(" << guid << ")");
420 if (!ppTInfo)
421 return E_POINTER;
422
423 Reference<ooo::vba::XConnectable> xConnectable(mxOrigin, UNO_QUERY);
424 if (!xConnectable.is())
425 return TYPE_E_ELEMENTNOTFOUND;
426
427 IID aIID;
428 if (SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR>(xConnectable->getIID().pData->buffer), &aIID)))
429 {
430 if (IsEqualIID(guid, aIID))
431 {
432 HRESULT ret;
433
434 CComObject<CXTypeInfo>* pTypeInfo;
435
436 ret = CComObject<CXTypeInfo>::CreateInstance(&pTypeInfo);
437 if (FAILED(ret))
438 return ret;
439
440 pTypeInfo->AddRef();
441
442 pTypeInfo->InitForCoclass(mxOrigin, msImplementationName, aIID, mxMSF);
443
444 *ppTInfo = pTypeInfo;
445
446 return S_OK;
447 }
448 }
449
450#if 0
451 ooo::vba::TypeAndIID aTypeAndIID = xConnectable->GetConnectionPoint();
452
453 IID aIID;
454 if (SUCCEEDED(IIDFromString((LPOLESTR)aTypeAndIID.IID.pData->buffer, &aIID)))
455 {
456 HRESULT ret;
457
458 CComObject<CXTypeInfo>* pTypeInfo;
459
460 ret = CComObject<CXTypeInfo>::CreateInstance(&pTypeInfo);
461 if (FAILED(ret))
462 return ret;
463
464 pTypeInfo->AddRef();
465
466 pTypeInfo->InitForOutgoing(mxOrigin, msImplementationName, aIID, mxMSF);
467
468 *ppTInfo = pTypeInfo;
469
470 return S_OK;
471 }
472#else
473 SAL_WARN("extensions.olebridge", "Not implemented: GetTypeInfoOfGuid(" << guid << ")");
474#endif
475
476 return TYPE_E_ELEMENTNOTFOUND;
477
478 }
479
480 virtual HRESULT STDMETHODCALLTYPE GetLibAttr(TLIBATTR **) override
481 {
482 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetLibAttr: E_NOTIMPL");
483 return E_NOTIMPL;
484 }
485
486 virtual HRESULT STDMETHODCALLTYPE GetTypeComp(ITypeComp **) override
487 {
488 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeComp: E_NOTIMPL");
489 return E_NOTIMPL;
490 }
491
492 virtual HRESULT STDMETHODCALLTYPE GetDocumentation(INT,
493 BSTR *,
494 BSTR *,
495 DWORD *,
496 BSTR *) override
497 {
498 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetDocumentation: E_NOTIMPL");
499 return E_NOTIMPL;
500 }
501
502 virtual HRESULT STDMETHODCALLTYPE IsName(LPOLESTR,
503 ULONG,
504 BOOL *) override
505 {
506 SAL_WARN("extensions.olebridge", this << "@CXTypeLib:IsName: E_NOTIMPL");
507 return E_NOTIMPL;
508 }
509
510 virtual HRESULT STDMETHODCALLTYPE FindName(LPOLESTR,
511 ULONG,
512 ITypeInfo **,
513 MEMBERID *,
514 USHORT *) override
515 {
516 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::FindName: E_NOTIMPL");
517 return E_NOTIMPL;
518 }
519
520 virtual void STDMETHODCALLTYPE ReleaseTLibAttr(TLIBATTR *) override
521 {
522 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::ReleaseTLibAttr: E_NOTIMPL");
523 }
524
525private:
526 Reference<XInterface> mxOrigin;
527 OUString msImplementationName;
529};
530
531}
532
533void CXTypeInfo::InitForCoclass(Reference<XInterface> xOrigin,
534 const OUString& sImplementationName,
535 const IID& rIID,
537{
538 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForCoclass(" << sImplementationName << "," << rIID << ")");
539 meKind = Kind::COCLASS;
540 mxOrigin = xOrigin;
541 msImplementationName = sImplementationName;
542 maIID = rIID;
543 mxMSF = xMSF;
544}
545
546void CXTypeInfo::InitForClassItself(Reference<XInterface> xOrigin,
547 const OUString& sImplementationName,
548 const IID& rIID,
550{
551 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForClassItself(" << sImplementationName << "," << rIID << ")");
552 meKind = Kind::MAIN;
553 mxOrigin = xOrigin;
554 msImplementationName = sImplementationName;
555 maIID = rIID;
556 mxMSF = xMSF;
557}
558
559void CXTypeInfo::InitForOutgoing(Reference<XInterface> xOrigin,
560 const OUString& sInterfaceName,
561 const IID& rIID,
563 Type aType)
564{
565 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForOutgoing(" << sInterfaceName << "," << rIID << ")");
566 meKind = Kind::OUTGOING;
567 mxOrigin = xOrigin;
568 msInterfaceName = sInterfaceName;
569 maIID = rIID;
570 mxMSF = xMSF;
571 maType = aType;
572}
573
574HRESULT STDMETHODCALLTYPE CXTypeInfo::GetTypeAttr(TYPEATTR **ppTypeAttr)
575{
577
578 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetTypeAttr");
579
580 if (!ppTypeAttr)
581 return E_POINTER;
582
583 assert(!IsEqualIID(maIID, IID_NULL));
584
585 TYPEATTR *pTypeAttr = new TYPEATTR;
586 memset(pTypeAttr, 0, sizeof(*pTypeAttr));
587
588 pTypeAttr->guid = maIID;
589
590 if (meKind == Kind::COCLASS)
591 {
592 pTypeAttr->typekind = TKIND_COCLASS;
593 pTypeAttr->cFuncs = 0;
594 pTypeAttr->cVars = 0;
595 pTypeAttr->cImplTypes = 3;
596 pTypeAttr->cbSizeVft = 0;
597 pTypeAttr->cbAlignment = 8;
598 pTypeAttr->wTypeFlags = TYPEFLAG_FCANCREATE;
599 }
600 else if (meKind == Kind::MAIN)
601 {
602 pTypeAttr->typekind = TKIND_DISPATCH;
603 pTypeAttr->cFuncs = 10; // FIXME, dummy
604 pTypeAttr->cVars = 0;
605 pTypeAttr->cImplTypes = 1;
606 // FIXME: I think this is always supposed to be as if just for the seven methods in
607 // IDIspatch?
608 pTypeAttr->cbSizeVft = 7 * sizeof(void*);
609 pTypeAttr->cbAlignment = 8;
610 pTypeAttr->wTypeFlags = TYPEFLAG_FHIDDEN|TYPEFLAG_FDISPATCHABLE;
611 }
612 else if (meKind == Kind::OUTGOING)
613 {
614 pTypeAttr->typekind = TKIND_DISPATCH;
615
616 Reference<XIdlReflection> xRefl = theCoreReflection::get(comphelper::getComponentContext(mxMSF));
617 assert(xRefl.is());
618
619 Reference<XIdlClass> xClass = xRefl->forName(maType.getTypeName());
620 assert(xClass.is());
621
622 auto aMethods = xClass->getMethods();
623 assert(xClass->getTypeClass() == TypeClass_INTERFACE &&
624 aMethods.getLength() > 0);
625
626 // Drop the three XInterface methods, add the three corresponding IUnknown ones plus the
627 // four IDispatch ones on top of that.
628 pTypeAttr->cFuncs = aMethods.getLength() - 3 + 3 + 4;
629 pTypeAttr->cVars = 0;
630 pTypeAttr->cImplTypes = 1;
631 // FIXME: I think this, too, is always supposed to be as if just for the seven methods in
632 // IDIspatch?
633 pTypeAttr->cbSizeVft = 7 * sizeof(void*);
634 pTypeAttr->cbAlignment = 8;
635 pTypeAttr->wTypeFlags = TYPEFLAG_FHIDDEN|TYPEFLAG_FNONEXTENSIBLE|TYPEFLAG_FDISPATCHABLE;
636 }
637 else
638 assert(false);
639
640 pTypeAttr->lcid = LOCALE_USER_DEFAULT;
641 pTypeAttr->memidConstructor = MEMBERID_NIL;
642 pTypeAttr->memidDestructor = MEMBERID_NIL;
643 // FIXME: Is this correct, just the vtable pointer, right?
644 pTypeAttr->cbSizeInstance = sizeof(void*);
645 pTypeAttr->wMajorVerNum = 0;
646 pTypeAttr->wMinorVerNum = 0;
647 pTypeAttr->idldescType.wIDLFlags = IDLFLAG_NONE;
648
649 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetTypeAttr: " << pTypeAttr);
650
651 *ppTypeAttr = pTypeAttr;
652
653 return S_OK;
654}
655
656HRESULT STDMETHODCALLTYPE CXTypeInfo::GetTypeComp(ITypeComp **)
657{
658 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetTypeComp: E_NOTIMPL");
659 return E_NOTIMPL;
660}
661
662HRESULT STDMETHODCALLTYPE CXTypeInfo::GetFuncDesc(UINT index,
663 FUNCDESC **ppFuncDesc)
664{
666
667 if (!ppFuncDesc)
668 return E_POINTER;
669
670 if (meKind != Kind::OUTGOING)
671 return E_NOTIMPL;
672
673 if (index <= 6)
674 {
675 *ppFuncDesc = new FUNCDESC;
676 (*ppFuncDesc)->memid = 0x60000000 + index;
677 (*ppFuncDesc)->lprgscode = nullptr;
678 (*ppFuncDesc)->lprgelemdescParam = nullptr;
679 (*ppFuncDesc)->funckind = FUNC_DISPATCH;
680 (*ppFuncDesc)->invkind = INVOKE_FUNC;
681 (*ppFuncDesc)->callconv = CC_STDCALL;
682 switch (index)
683 {
684 case 0: // QueryInterface
685 (*ppFuncDesc)->cParams = 2;
686 (*ppFuncDesc)->elemdescFunc.tdesc.lptdesc = nullptr;
687 (*ppFuncDesc)->elemdescFunc.tdesc.vt = VT_VOID;
688 break;
689 case 1: // AddRef
690 (*ppFuncDesc)->cParams = 0;
691 (*ppFuncDesc)->elemdescFunc.tdesc.lptdesc = nullptr;
692 (*ppFuncDesc)->elemdescFunc.tdesc.vt = VT_UI4;
693 break;
694 case 2: // Release
695 (*ppFuncDesc)->cParams = 1;
696 (*ppFuncDesc)->elemdescFunc.tdesc.lptdesc = nullptr;
697 (*ppFuncDesc)->elemdescFunc.tdesc.vt = VT_UI4;
698 break;
699 case 3: // GetTypeInfoCount
700 (*ppFuncDesc)->cParams = 1;
701 (*ppFuncDesc)->elemdescFunc.tdesc.lptdesc = nullptr;
702 (*ppFuncDesc)->elemdescFunc.tdesc.vt = VT_VOID;
703 break;
704 case 4: // GetTypeInfo
705 (*ppFuncDesc)->cParams = 3;
706 (*ppFuncDesc)->elemdescFunc.tdesc.lptdesc = nullptr;
707 (*ppFuncDesc)->elemdescFunc.tdesc.vt = VT_VOID;
708 break;
709 case 5: // GetIDsOfNames
710 (*ppFuncDesc)->cParams = 5;
711 (*ppFuncDesc)->elemdescFunc.tdesc.lptdesc = nullptr;
712 (*ppFuncDesc)->elemdescFunc.tdesc.vt = VT_VOID;
713 break;
714 case 6: // Invoke
715 (*ppFuncDesc)->cParams = 8;
716 (*ppFuncDesc)->elemdescFunc.tdesc.lptdesc = nullptr;
717 (*ppFuncDesc)->elemdescFunc.tdesc.vt = VT_VOID;
718 break;
719 }
720 (*ppFuncDesc)->cParamsOpt = 0;
721 (*ppFuncDesc)->oVft = index * sizeof(void*);
722 (*ppFuncDesc)->cScodes = 0;
723 (*ppFuncDesc)->wFuncFlags = FUNCFLAG_FRESTRICTED;
724
725 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetFuncDesc(" << index << "): S_OK: " << *ppFuncDesc);
726
727 return S_OK;
728 }
729
730 Reference<XIdlReflection> xRefl = theCoreReflection::get(comphelper::getComponentContext(mxMSF));
731 assert(xRefl.is());
732
733 Reference<XIdlClass> xClass = xRefl->forName(maType.getTypeName());
734 assert(xClass.is());
735
736 auto aMethods = xClass->getMethods();
737 assert(xClass->getTypeClass() == TypeClass_INTERFACE &&
738 aMethods.getLength() > 0);
739
740 if (index > o3tl::make_unsigned(aMethods.getLength() - 3 + 3 + 4))
741 return E_INVALIDARG;
742
743 *ppFuncDesc = new FUNCDESC;
744
745 (*ppFuncDesc)->memid = index - 6;
746 (*ppFuncDesc)->lprgscode = nullptr;
747 (*ppFuncDesc)->lprgelemdescParam = nullptr;
748 (*ppFuncDesc)->funckind = FUNC_DISPATCH;
749 (*ppFuncDesc)->invkind = INVOKE_FUNC;
750 (*ppFuncDesc)->callconv = CC_STDCALL;
751 (*ppFuncDesc)->cParams = aMethods[index - 4]->getParameterInfos().getLength();
752 (*ppFuncDesc)->cParamsOpt = 0;
753 (*ppFuncDesc)->oVft = index * sizeof(void*);
754 (*ppFuncDesc)->cScodes = 0;
755 (*ppFuncDesc)->elemdescFunc.tdesc.lptdesc = nullptr; // ???
756 (*ppFuncDesc)->elemdescFunc.tdesc.vt = VT_VOID; // ???
757 (*ppFuncDesc)->wFuncFlags = 0;
758
759 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetFuncDesc(" << index << "): S_OK: " << *ppFuncDesc);
760
761 return S_OK;
762}
763
764HRESULT STDMETHODCALLTYPE CXTypeInfo::GetVarDesc(UINT,
765 VARDESC **)
766{
767 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetVarDesc: E_NOTIMPL");
768 return E_NOTIMPL;
769}
770
771HRESULT STDMETHODCALLTYPE CXTypeInfo::GetNames(MEMBERID memid,
772 BSTR *rgBstrNames,
773 UINT cMaxNames,
774 UINT *pcNames)
775{
777
778 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetNames(" << memid << ")");
779 assert(meKind != Kind::COCLASS);
780
781 if (!rgBstrNames)
782 return E_POINTER;
783
784 if (!pcNames)
785 return E_POINTER;
786
787 if (memid < 1)
788 return E_INVALIDARG;
789
790 if (cMaxNames < 1)
791 return E_INVALIDARG;
792
793 if (meKind == Kind::MAIN)
794 {
795 SAL_WARN("extensions.olebridge", "GetNames() for MAIN not implemented");
796 return E_NOTIMPL;
797 }
798
799 Reference<XIdlReflection> xRefl = theCoreReflection::get(comphelper::getComponentContext(mxMSF));
800 assert(xRefl.is());
801
802 Reference<XIdlClass> xClass = xRefl->forName(maType.getTypeName());
803 assert(xClass.is());
804
805 auto aMethods = xClass->getMethods();
806 assert(xClass->getTypeClass() == TypeClass_INTERFACE &&
807 aMethods.getLength() > 0);
808
809 // Subtract the three XInterface methods. Memid for the first following method is 1.
810 if (memid > aMethods.getLength() - 3)
811 return E_INVALIDARG;
812
813 SAL_INFO("extensions.olebridge", "..." << this << "@CXTypeInfo::GetNames(" << memid << "): " << aMethods[memid + 2]->getName());
814 rgBstrNames[0] = SysAllocString(reinterpret_cast<LPOLESTR>(aMethods[memid + 2]->getName().pData->buffer));
815 *pcNames = 1;
816
817 return S_OK;
818}
819
820HRESULT STDMETHODCALLTYPE CXTypeInfo::GetRefTypeOfImplType(UINT index,
821 HREFTYPE *pRefType)
822{
823 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetRefTypeOfImplType(" << index << ")");
824
825 if (!pRefType)
826 return E_POINTER;
827
828 assert(index == 0 || index == 1);
829
830 *pRefType = 1000+index;
831
832 return S_OK;
833}
834
835HRESULT STDMETHODCALLTYPE CXTypeInfo::GetImplTypeFlags(UINT index,
836 INT *pImplTypeFlags)
837{
839
840 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetImplTypeFlags(" << index << ")");
841
842 if (!pImplTypeFlags)
843 return E_POINTER;
844
845 assert(meKind == Kind::COCLASS);
846 assert(index == 0 || index == 1);
847
848 if (index == 0)
849 *pImplTypeFlags = IMPLTYPEFLAG_FDEFAULT;
850 else if (index == 1)
851 *pImplTypeFlags = IMPLTYPEFLAG_FDEFAULT|IMPLTYPEFLAG_FSOURCE;
852
853 return S_OK;
854}
855
856HRESULT STDMETHODCALLTYPE CXTypeInfo::GetIDsOfNames(LPOLESTR *,
857 UINT,
858 MEMBERID *)
859{
860 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetIDsOfNames: E_NOTIMPL");
861 return E_NOTIMPL;
862}
863
864HRESULT STDMETHODCALLTYPE CXTypeInfo::Invoke(PVOID,
865 MEMBERID,
866 WORD,
867 DISPPARAMS *,
868 VARIANT *,
869 EXCEPINFO *,
870 UINT *)
871{
872 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::Invoke: E_NOTIMPL");
873 return E_NOTIMPL;
874}
875
876HRESULT STDMETHODCALLTYPE CXTypeInfo::GetDocumentation(MEMBERID memid,
877 BSTR *pBstrName,
878 BSTR *pBstrDocString,
879 DWORD *pdwHelpContext,
880 BSTR *pBstrHelpFile)
881{
883
884 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetDocumentation(" << memid << ")");
885
886 if (pBstrName)
887 {
888 if (memid == MEMBERID_NIL)
889 {
890 *pBstrName = SysAllocString(o3tl::toW(msImplementationName.getStr()));
891 }
892 else if (memid == DISPID_VALUE)
893 {
894 // MEMBERIDs are the same as DISPIDs, apparently?
895 *pBstrName = SysAllocString(L"Value");
896 }
897 else
898 {
899 // FIXME: Shouldn't we be able to know the names of the members of UNO interfaces?
900 *pBstrName = SysAllocString(o3tl::toW(OUString("UnknownNameOfMember#" + OUString::number(memid)).getStr()));
901 }
902 }
903 if (pBstrDocString)
904 *pBstrDocString = SysAllocString(L"");
905 if (pdwHelpContext)
906 *pdwHelpContext = 0;
907 if (pBstrHelpFile)
908 *pBstrHelpFile = nullptr;
909
910 return S_OK;
911}
912
913HRESULT STDMETHODCALLTYPE CXTypeInfo::GetDllEntry(MEMBERID,
914 INVOKEKIND,
915 BSTR *,
916 BSTR *,
917 WORD *)
918{
919 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetDllEntry: E_NOTIMPL");
920 return E_NOTIMPL;
921}
922
923HRESULT STDMETHODCALLTYPE CXTypeInfo::GetRefTypeInfo(HREFTYPE hRefType,
924 ITypeInfo **ppTInfo)
925{
927
928 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetRefTypeInfo(" << hRefType << ")");
929
930 if (!ppTInfo)
931 return E_POINTER;
932
933 // FIXME: Is it correct to assume that the only interfaces on which GetRefTypeInfo() would be
934 // called are those that implement ooo::vba::XConnectable?
935
936 Reference<ooo::vba::XConnectable> xConnectable(mxOrigin, UNO_QUERY);
937 if (!xConnectable.is())
938 return E_NOTIMPL;
939
940 ooo::vba::TypeAndIID aTypeAndIID = xConnectable->GetConnectionPoint();
941
942 IID aIID;
943 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR>(aTypeAndIID.IID.pData->buffer), &aIID)))
944 return E_NOTIMPL;
945
946 HRESULT ret;
947
948 CComObject<CXTypeInfo>* pTypeInfo;
949
950 ret = CComObject<CXTypeInfo>::CreateInstance(&pTypeInfo);
951 if (FAILED(ret))
952 return ret;
953
954 pTypeInfo->AddRef();
955
956 pTypeInfo->InitForOutgoing(mxOrigin, aTypeAndIID.Type.getTypeName(), aIID, mxMSF, aTypeAndIID.Type);
957
958 *ppTInfo = pTypeInfo;
959
960 return S_OK;
961}
962
963HRESULT STDMETHODCALLTYPE CXTypeInfo::AddressOfMember(MEMBERID,
964 INVOKEKIND,
965 PVOID *)
966{
967 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::AddressOfMember: E_NOTIMPL");
968 return E_NOTIMPL;
969}
970
971HRESULT STDMETHODCALLTYPE CXTypeInfo::CreateInstance(IUnknown *,
972 REFIID,
973 PVOID *)
974{
975 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::CreateInstance: E_NOTIMPL");
976 return E_NOTIMPL;
977}
978
979HRESULT STDMETHODCALLTYPE CXTypeInfo::GetMops(MEMBERID,
980 BSTR *)
981{
982 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetMops: E_NOTIMPL");
983 return E_NOTIMPL;
984}
985
986// This is not actually called any more by my vbscript test after I added the IProvideClassInfo
987// thing... so all the CXTypeLib stuff is dead code at the moment.
988
989HRESULT STDMETHODCALLTYPE CXTypeInfo::GetContainingTypeLib(ITypeLib **ppTLib,
990 UINT *pIndex)
991{
993
994 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetContainingTypeLib");
995
996 if (!ppTLib || !pIndex)
997 return E_POINTER;
998
999 HRESULT ret;
1000
1001 CComObject<CXTypeLib>* pTypeLib;
1002
1003 ret = CComObject<CXTypeLib>::CreateInstance(&pTypeLib);
1004 if (FAILED(ret))
1005 return ret;
1006
1007 pTypeLib->AddRef();
1008
1009 pTypeLib->Init(mxOrigin, msImplementationName, mxMSF);
1010
1011 *ppTLib = pTypeLib;
1012
1013 return S_OK;
1014}
1015
1016void STDMETHODCALLTYPE CXTypeInfo::ReleaseTypeAttr(TYPEATTR *pTypeAttr)
1017{
1018 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::ReleaseTypeAttr(" << pTypeAttr << ")");
1019
1020 delete pTypeAttr;
1021}
1022
1023void STDMETHODCALLTYPE CXTypeInfo::ReleaseFuncDesc(FUNCDESC *pFuncDesc)
1024{
1025 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::ReleaseFuncDesc(" << pFuncDesc << ")");
1026
1027 delete pFuncDesc;
1028}
1029
1030void STDMETHODCALLTYPE CXTypeInfo::ReleaseVarDesc(VARDESC *)
1031{
1032 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::ReleaseVarDesc: E_NOTIMPL");
1033}
1034
1035COM_DECLSPEC_NOTHROW STDMETHODIMP InterfaceOleWrapper::GetTypeInfo(UINT iTInfo, LCID, ITypeInfo ** ppTInfo)
1036{
1038
1039 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetTypeInfo(" << iTInfo << ")");
1040
1041 if (!ppTInfo)
1042 return E_POINTER;
1043
1044 if (iTInfo != 0)
1045 return E_NOTIMPL;
1046
1047 // FIXME: This is surely incorrect. Why is being able to handle GetTypeInfo() here coupled to
1048 // being a source for outgoing events, i.e. implementing XConnectable? What would break if we
1049 // would use XInterfaceWithIID and its getIID instead?
1050
1051 Reference<ooo::vba::XConnectable> xConnectable(m_xOrigin, UNO_QUERY);
1052 if (!xConnectable.is())
1053 return E_NOTIMPL;
1054
1055 OUString sIID = xConnectable->GetIIDForClassItselfNotCoclass();
1056 IID aIID;
1057 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR>(sIID.pData->buffer), &aIID)))
1058 return E_NOTIMPL;
1059
1060 HRESULT ret;
1061
1062 CComObject<CXTypeInfo>* pTypeInfo;
1063
1064 ret = CComObject<CXTypeInfo>::CreateInstance(&pTypeInfo);
1065 if (FAILED(ret))
1066 return ret;
1067
1068 pTypeInfo->AddRef();
1069
1070 pTypeInfo->InitForClassItself(m_xOrigin, m_sImplementationName, aIID, m_smgr);
1071
1072 *ppTInfo = pTypeInfo;
1073
1074 return S_OK;
1075}
1076
1077COM_DECLSPEC_NOTHROW STDMETHODIMP InterfaceOleWrapper::GetIDsOfNames(REFIID /*riid*/,
1078 LPOLESTR * rgszNames,
1079 UINT cNames,
1080 LCID /*lcid*/,
1081 DISPID * rgdispid )
1082{
1084
1085 if( ! rgdispid)
1086 return E_POINTER;
1087
1088 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetIDsOfNames:");
1089 for (unsigned int i = 0; i < cNames; ++i)
1090 {
1091 // Initialise returned rgdispid values.
1092 rgdispid[i] = DISPID_UNKNOWN;
1093
1094 SAL_INFO("extensions.olebridge", " " << OUString(o3tl::toU(rgszNames[i])));
1095 }
1096
1097 HRESULT ret = DISP_E_UNKNOWNNAME;
1098 try
1099 {
1100 MutexGuard guard( getBridgeMutex());
1101
1102 // FIXME: Handle the cNames > 1 case? Note that the rest of the names mean the names of *arguments*.
1103
1104 if( ! _wcsicmp( *rgszNames, JSCRIPT_VALUE_FUNC) ||
1105 ! _wcsicmp( *rgszNames, BRIDGE_VALUE_FUNC))
1106 {
1107 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
1108 return S_OK;
1109 }
1110 else if( ! _wcsicmp( *rgszNames, GET_STRUCT_FUNC) ||
1111 ! _wcsicmp( *rgszNames, BRIDGE_GET_STRUCT_FUNC))
1112 {
1113 *rgdispid= DISPID_GET_STRUCT_FUNC;
1114 return S_OK;
1115 }
1116 else if( ! _wcsicmp( *rgszNames, BRIDGE_CREATE_TYPE_FUNC))
1117 {
1118 *rgdispid= DISPID_CREATE_TYPE_FUNC;
1119 return S_OK;
1120 }
1121
1122 if (m_xInvocation.is() && (cNames > 0))
1123 {
1124 OUString name(o3tl::toU(rgszNames[0]));
1125 NameToIdMap::iterator iter = m_nameToDispIdMap.find(name);
1126
1127 bool bIsMethod = false;
1128
1129 OUString exactName = name;
1130
1131 if (iter == m_nameToDispIdMap.end())
1132 {
1133 if (m_xExactName.is())
1134 {
1135 exactName = m_xExactName->getExactName(name);
1136 if (exactName.isEmpty())
1137 exactName = name;
1138 }
1139
1140 MemberInfo d(0, exactName);
1141
1142 if (m_xInvocation->hasProperty(exactName))
1143 {
1144 d.flags |= DISPATCH_PROPERTYGET;
1145 d.flags |= DISPATCH_PROPERTYPUT;
1146 d.flags |= DISPATCH_PROPERTYPUTREF;
1147 }
1148
1149 if (m_xInvocation->hasMethod(exactName))
1150 {
1151 d.flags |= DISPATCH_METHOD;
1152 bIsMethod = true;
1153 }
1154
1155 if (d.flags != 0)
1156 {
1157 m_MemberInfos.push_back(d);
1158 iter = m_nameToDispIdMap.emplace(exactName, static_cast<DISPID>(m_MemberInfos.size())).first;
1159
1160 if (exactName != name)
1161 {
1162 iter = m_nameToDispIdMap.emplace(name, static_cast<DISPID>(m_MemberInfos.size())).first;
1163 }
1164 }
1165 }
1166
1167 if (iter == m_nameToDispIdMap.end())
1168 {
1169 ret = DISP_E_UNKNOWNNAME;
1170 SAL_INFO("extensions.olebridge", " " << name << ": UNKNOWN");
1171 }
1172 else
1173 {
1174 rgdispid[0] = (*iter).second;
1175 SAL_INFO("extensions.olebridge", " " << name << ": " << rgdispid[0]);
1176
1177 if (bIsMethod && cNames > 1)
1178 {
1179 Reference<XIdlMethod> xIdlMethod;
1180 Reference<XIntrospectionAccess> xIntrospectionAccess = m_xInvocation->getIntrospection();
1181 try
1182 {
1183 if (xIntrospectionAccess.is())
1184 xIdlMethod = xIntrospectionAccess->getMethod(exactName, MethodConcept::ALL);
1185 }
1186 catch (const NoSuchMethodException&)
1187 {
1188 }
1189 if (xIdlMethod.is())
1190 {
1191 auto aParamInfos = xIdlMethod->getParameterInfos();
1192 for (unsigned int i = 1; i < cNames; ++i)
1193 {
1194 bool bFound = false;
1195 for (int j = 0; j < aParamInfos.getLength(); ++j)
1196 {
1197 if (aParamInfos[j].aName.equalsIgnoreAsciiCase(o3tl::toU(rgszNames[i])))
1198 {
1199 rgdispid[i] = j;
1200 bFound = true;
1201 SAL_INFO("extensions.olebridge", " " << OUString(o3tl::toU(rgszNames[i])) << ": " << rgdispid[i]);
1202 break;
1203 }
1204 }
1205 if (!bFound)
1206 SAL_INFO("extensions.olebridge", " " << OUString(o3tl::toU(rgszNames[i])) << ": NOT FOUND");
1207 }
1208 }
1209 }
1210
1211 // Return value should be S_OK only if *all* the names were found.
1212 unsigned int i;
1213 for (i = 0; i < cNames; ++i)
1214 if (rgdispid[i] == DISPID_UNKNOWN)
1215 break;
1216 if (i == cNames)
1217 ret = S_OK;
1218 }
1219 }
1220 }
1221 catch(const BridgeRuntimeError&)
1222 {
1223 OSL_ASSERT(false);
1224 }
1225 catch(const Exception&)
1226 {
1227 OSL_ASSERT(false);
1228 }
1229 catch(...)
1230 {
1231 OSL_ASSERT(false);
1232 }
1233
1234 return ret;
1235}
1236
1237// Note: What the comments here say about JScript possibly holds for Automation clients in general,
1238// like VBScript ones, too. Or not. Hard to say. What is the relevance of JScript nowadays anyway,
1239// and can LO really be used from JScript code on web pages any longer?
1240
1241// "convertDispparamsArgs" converts VARIANTS to their respecting Any counterparts
1242// The parameters "id", "wFlags" and "pdispparams" equal those as used in
1243// IDispatch::Invoke. The function handles special JavaScript
1244// cases where a VARIANT of type VT_DISPATCH is ambiguous and could represent
1245// an object, array ( JavaScript Array object), out parameter and in/out ( JavaScript Array object)
1246// parameter (JavaScript Array object)
1247// Because all those VT_DISPATCH objects need a different conversion
1248// we have to find out what the object is supposed to be. The function does this
1249// by either using type information or by help of a specialized ValueObject object.
1250
1251// A. Type Information
1252
1253// With the help of type information the kind of parameter can be exactly determined
1254// and an appropriate conversion can be chosen. A problem arises if a method expects
1255// an Any. Then the type info does not tell what the type of the value, that is kept
1256// by the any, should be. In this situation the decision whether the param is a
1257// sequence or an object is made upon the fact if the object has a property "0"
1258// ( see function "isJScriptArray"). Since this is unsafe it is recommended to use
1259// the JScript value objects within a JScript script on such an occasion.
1260
1261// B. JavaScript Value Object ( class JScriptValue )
1262
1263// A JScriptValue (ValueObject) object is a COM object in that it implements IDispatch and the
1264// IJScriptValue object interface. Such objects are provided by all UNO wrapper
1265// objects used within a JScript script. To obtain an instance one has to call
1266// "_GetValueObject() or Bridge_GetValueObject()" on a UNO wrapper object (class InterfaceOleWrapper).
1267// A value object is appropriately initialized within the script and passed as
1268// parameter to a UNO object method or property. The convertDispparamsArgs function
1269// can easily find out that a param is such an object by querying for the
1270// IJScriptValue interface. By this interface one the type and kind ( out, in/out)
1271// can be determined and the right conversion can be applied.
1272// Using ValueObjects we spare us the effort of acquiring and examining type information
1273// in order to figure out what the an IDispatch parameter is meant for.
1274
1275// Normal JScript object parameter can be mixed with JScriptValue object. If an
1276// VARIANT contains a VT_DISPATCH that is no JScriptValue than the type information
1277// is used to find out about the required type.
1279 unsigned short /*wFlags*/, DISPPARAMS* pdispparams, Sequence<Any>& rSeq)
1280{
1281 // Parameters come in in reverse order in pdispparams. There might be less parameters than
1282 // expected. In that case, assume they are "optional" (but can't be marked as such in UNO IDL),
1283 // and fill in the rest with empty Anys. There might also be more than expected. In that case,
1284 // assume the oovbaapi UNO IDL hasn't kept up with added optional parameters in MSO, and just
1285 // ignore the extra ones, as long as they are empty.
1286
1287 // An example: incoming parameters: <12, 13, "foo/bar.tem">
1288 //
1289 // Expected parameters: (string filename, int something, int somethingElse, Any whatever, Any
1290 // whateverElse)
1291 //
1292 // Here the existing incoming parameters are placed in reverse order in the first three outgoing
1293 // parameters, and the rest of the outgoing parameters are kept as empty Anys.
1294 //
1295 // Another example: incoming parameters: <EMPTY, TRUE>
1296 //
1297 // Expected parameters: (bool flag)
1298 //
1299 // Here the TRUE is passed as the sole outgoing parameter, and the incoming EMPTY is ignored.
1300 //
1301 // Still an example: incoming parameters: <"foo.doc", TRUE>
1302 //
1303 // Expected parameters: (bool flag)
1304 //
1305 // This throws an error as the incoming string parameter presumably should do something important,
1306 // but there is no corresponding outgoing parameter.
1307
1308 HRESULT hr = S_OK;
1309 const int countIncomingArgs = pdispparams->cArgs;
1310
1311 //Get type information for the current call
1312 InvocationInfo info;
1313 if( ! getInvocationInfoForCall( id, info))
1314 throw BridgeRuntimeError(
1315 "[automation bridge]InterfaceOleWrapper::convertDispparamsArgs \n"
1316 "Could not obtain type information for current call.");
1317
1318 // Size rSeq according to the number of expected parameters.
1319 const int expectedArgs = info.aParamTypes.getLength() + (info.eMemberType == MemberType_PROPERTY ? 1 : 0);
1320 rSeq.realloc( expectedArgs );
1321 Any* pParams = rSeq.getArray();
1322
1323 Any anyParam;
1324
1325 int outgoingArgIndex = 0;
1326
1327 // Go through incoming parameters in reverse order, i.e. in the order as declared in IDL
1328 for (int i = std::max(countIncomingArgs, expectedArgs) - 1; i >= 0; i--)
1329 {
1330 // Ignore too many parameters if they are VT_EMPTY anyway
1331 if ( outgoingArgIndex >= expectedArgs && pdispparams->rgvarg[i].vt == VT_EMPTY )
1332 continue;
1333
1334 // But otherwise too many parameters is an error
1335 if ( outgoingArgIndex >= expectedArgs )
1336 throw BridgeRuntimeError( "[automation bridge] Too many parameters" );
1337
1338 if (info.eMemberType == MemberType_METHOD &&
1339 info.aParamModes[ outgoingArgIndex ] == ParamMode_OUT)
1340 {
1341 outgoingArgIndex++;
1342 continue;
1343 }
1344
1345 if (i < countIncomingArgs)
1346 {
1347 // A missing (and hopefully optional) arg (in the middle of the argument list) is passed
1348 // as an empty Any.
1349 if (pdispparams->rgvarg[i].vt == VT_ERROR && pdispparams->rgvarg[i].scode == DISP_E_PARAMNOTFOUND)
1350 {
1351 Any aEmpty;
1352 pParams[ outgoingArgIndex ] = aEmpty;
1353 outgoingArgIndex++;
1354 continue;
1355 }
1356
1357 if(convertValueObject( & pdispparams->rgvarg[i], anyParam))
1358 { //a param is a ValueObject and could be converted
1359 pParams[ outgoingArgIndex ] = anyParam;
1360 outgoingArgIndex++;
1361 continue;
1362 }
1363 }
1364 else
1365 {
1366 // A missing arg. Let's hope it is de facto optional (there is no way in UNO IDL to mark
1367 // a parameter as optional). The corresponding slot in pParams is already a void Any.
1368 // Here we don't increase outgoingArgIndex!
1369 continue;
1370 }
1371
1372 // If the param is an out, in/out parameter in
1373 // JScript (Array object, with value at index 0) then we
1374 // extract Array[0] and put the value into varParam. At the end of the loop varParam
1375 // is converted if it contains a value otherwise the VARIANT from
1376 // DISPPARAMS is converted.
1377 CComVariant varParam;
1378
1379 // Check for JScript out and in/out paramsobjects (VT_DISPATCH).
1380 // To find them out we use typeinformation of the function being called.
1381
1382 // No idea how this stuff, originally written for JScript, works for other Automation
1383 // clients.
1384
1385 if( pdispparams->rgvarg[i].vt == VT_DISPATCH )
1386 {
1387 if( info.eMemberType == MemberType_METHOD && info.aParamModes[ outgoingArgIndex ] == ParamMode_INOUT)
1388 {
1389 // INOUT-param
1390 // Index ( property) "0" contains the actual IN-param. The object is a JScript
1391 // Array object.
1392 // Get the IN-param at index "0"
1393 IDispatch* pdisp= pdispparams->rgvarg[i].pdispVal;
1394
1395 OLECHAR const * sindex= L"0";
1396 DISPID id2;
1397 DISPPARAMS noParams= {nullptr,nullptr,0,0};
1398 if(SUCCEEDED( hr= pdisp->GetIDsOfNames( IID_NULL, const_cast<OLECHAR **>(&sindex), 1, LOCALE_USER_DEFAULT, &id2)))
1399 hr= pdisp->Invoke( id2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
1400 & noParams, & varParam, nullptr, nullptr);
1401 if( FAILED( hr))
1402 {
1403 throw BridgeRuntimeError(
1404 "[automation bridge] Could not determine "
1405 "if the object has a member \"0\". Error: " +
1406 OUString::number(hr));
1407 }
1408 }
1409 }
1410
1411 if( varParam.vt == VT_EMPTY) // then it was no in/out parameter
1412 varParam= pdispparams->rgvarg[i];
1413
1414 if(info.eMemberType == MemberType_METHOD)
1415 variantToAny( & varParam, anyParam,
1416 info.aParamTypes[ outgoingArgIndex ]);
1417 else if(info.eMemberType == MemberType_PROPERTY)
1418 variantToAny( & varParam, anyParam, info.aType);
1419 else
1420 OSL_ASSERT(false);
1421
1422 if (outgoingArgIndex < expectedArgs)
1423 pParams[ outgoingArgIndex ]= anyParam;
1424 outgoingArgIndex++;
1425 }// end for / iterating over all parameters
1426}
1427
1428bool InterfaceOleWrapper::getInvocationInfoForCall( DISPID id, InvocationInfo& info)
1429{
1430 bool bTypesAvailable= false;
1431
1432 if( !m_xInvocation.is() )return false;
1433 Reference<XInvocation2> inv2( m_xInvocation, UNO_QUERY);
1434 if( inv2.is())
1435 {
1436 // We need the name of the property or method to get its type information.
1437 // The name can be identified through the param "id"
1438 // that is kept as value in the map m_nameToDispIdMap.
1439 // Problem: the Windows JScript engine sometimes changes small letters to capital
1440 // letters as happens in xidlclass_obj.createObject( var) // in JScript.
1441 // IDispatch::GetIdsOfNames is then called with "CreateObject" !!!
1442 // m_nameToDispIdMap can contain several names for one DISPID but only one is
1443 // the exact one. If there's no m_xExactName and therefore no exact name then
1444 // there's only one entry in the map.
1445 OUString sMemberName;
1446
1447 auto ci1 = std::find_if(m_nameToDispIdMap.cbegin(), m_nameToDispIdMap.cend(),
1448 [&id](const NameToIdMap::value_type& nameToDispId) { return nameToDispId.second == id; }); // item is a pair<OUString, DISPID>
1449 if (ci1 != m_nameToDispIdMap.cend())
1450 sMemberName= (*ci1).first;
1451 // Get information for the current call ( property or method).
1452 // There could be similar names which only differ in the cases
1453 // of letters. First we assume that the name which was passed into
1454 // GetIDsOfNames is correct. If we won't get information with that
1455 // name then we have the invocation service use the XExactName interface.
1456 bool validInfo= true;
1457 InvocationInfo invInfo;
1458 try{
1459 invInfo= inv2->getInfoForName( sMemberName, false);
1460 }
1461 catch(const IllegalArgumentException&)
1462 {
1463 validInfo= false;
1464 }
1465
1466 if( ! validInfo)
1467 {
1468 invInfo= inv2->getInfoForName( sMemberName, true);
1469 }
1470 if( invInfo.aName.pData)
1471 {
1472 bTypesAvailable= true;
1473 info= invInfo;
1474 }
1475 }
1476 return bTypesAvailable;
1477}
1478
1479// XBridgeSupplier2 ---------------------------------------------------
1480// only bridges itself ( this instance of InterfaceOleWrapper)from UNO to IDispatch
1481// If sourceModelType is UNO than any UNO interface implemented by InterfaceOleWrapper
1482// can bridged to IDispatch ( if destModelType == OLE). The IDispatch is
1483// implemented by this class.
1484Any SAL_CALL InterfaceOleWrapper::createBridge(const Any& modelDepObject,
1485 const Sequence<sal_Int8>& /*ProcessId*/,
1486 sal_Int16 sourceModelType,
1487 sal_Int16 destModelType)
1488{
1489
1490 Any retAny;
1491 if( sourceModelType == UNO && destModelType == OLE &&
1492 modelDepObject.getValueTypeClass() == TypeClass_INTERFACE )
1493 {
1495 if( modelDepObject >>= xInt )
1496 {
1497 if( xInt == Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY))
1498 {
1499 VARIANT *pVar= static_cast<VARIANT*>(CoTaskMemAlloc( sizeof( VARIANT)));
1500 if( pVar)
1501 {
1502 pVar->vt= VT_DISPATCH;
1503 pVar->pdispVal= this;
1504 AddRef();
1505
1506 retAny<<= reinterpret_cast< sal_uIntPtr >( pVar);
1507 }
1508 }
1509 }
1510 }
1511
1512 return retAny;
1513}
1514
1515// XInitialization --------------------------------------------------
1516void SAL_CALL InterfaceOleWrapper::initialize( const Sequence< Any >& aArguments )
1517{
1518 switch( aArguments.getLength() )
1519 {
1520 case 2: // the object wraps a UNO struct
1523 break;
1524 case 3: // the object wraps a UNO interface
1526 aArguments[1] >>= m_xOrigin;
1528
1529 Reference<XServiceInfo> xServiceInfo(m_xOrigin, UNO_QUERY);
1530 if (xServiceInfo.is())
1531 m_sImplementationName = xServiceInfo->getImplementationName();
1532
1533 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::initialize for "
1534 << (m_sImplementationName.isEmpty()?"an unknown implementation":m_sImplementationName));
1535 break;
1536 }
1537
1538 m_xExactName.set( m_xInvocation, UNO_QUERY);
1539}
1540
1542{
1543 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper(
1545 return Reference<XInterface>( xWeak, UNO_QUERY);
1546}
1547
1549{
1550 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper(
1552 return Reference<XInterface>( xWeak, UNO_QUERY);
1553}
1554
1555// "getType" is used in convertValueObject to map the string denoting the type
1556// to an actual Type object.
1557bool getType( const BSTR name, Type & type)
1558{
1559 bool ret = false;
1560 typelib_TypeDescription * pDesc= nullptr;
1561 OUString str(o3tl::toU(name));
1562 typelib_typedescription_getByName( &pDesc, str.pData );
1563 if( pDesc)
1564 {
1565 type = Type( pDesc->pWeakRef );
1567 ret = true;
1568 }
1569 return ret;
1570}
1571
1572static bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource)
1573{
1574 bool ret = false;
1575 HRESULT hr;
1576
1577 // Handle JScriptValue objects and JScript out params ( Array object )
1578 CComVariant varDest( *pDest);
1579
1580 if( SUCCEEDED( varDest.ChangeType(VT_DISPATCH)))
1581 {
1582 CComPtr<IDispatch> spDispDest(varDest.pdispVal);
1583
1584 // special Handling for a JScriptValue object
1585 CComQIPtr<IJScriptValueObject> spValueDest(spDispDest);
1586 if (spValueDest)
1587 {
1588 VARIANT_BOOL varBool= VARIANT_FALSE;
1589 if ((SUCCEEDED(hr = spValueDest->IsOutParam(&varBool))
1590 && varBool == VARIANT_TRUE)
1591 || (SUCCEEDED(hr = spValueDest->IsInOutParam(&varBool))
1592 && varBool == VARIANT_TRUE))
1593 {
1594 if( SUCCEEDED( spValueDest->Set( CComVariant(), *pSource)))
1595 ret= true;
1596 }
1597 }
1598 else if (pDest->vt == VT_DISPATCH)// VT_DISPATCH -> JScript out param
1599 {
1600 // We use IDispatchEx because its GetDispID function causes the creation
1601 // of a property if it does not exist already. This is convenient for
1602 // out parameters in JScript. Then the user must not specify property "0"
1603 // explicitly
1604 CComQIPtr<IDispatchEx> spDispEx( spDispDest);
1605 if( spDispEx)
1606 {
1607 CComBSTR nullProp(L"0");
1608 DISPID dwDispID;
1609 if( SUCCEEDED( spDispEx->GetDispID( nullProp, fdexNameEnsure, &dwDispID)))
1610 {
1611 DISPPARAMS dispparams = {nullptr, nullptr, 1, 1};
1612 dispparams.rgvarg = pSource;
1613 DISPID dispidPut = DISPID_PROPERTYPUT;
1614 dispparams.rgdispidNamedArgs = &dispidPut;
1615
1616 if (pSource->vt == VT_UNKNOWN || pSource->vt == VT_DISPATCH ||
1617 (pSource->vt & VT_ARRAY) || (pSource->vt & VT_BYREF))
1618 hr = spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
1619 &dispparams, nullptr, nullptr, nullptr);
1620 else
1621 hr= spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
1622 &dispparams, nullptr, nullptr, nullptr);
1623 if( SUCCEEDED(hr))
1624 ret= true;
1625 }
1626 }
1627 }
1628 else
1629 ret= writeBackOutParameter( pDest, pSource);
1630 }
1631 else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript
1632 { // param. The function checks itself for correct VBScript params
1633 ret= writeBackOutParameter( pDest, pSource);
1634 }
1635 return ret;
1636}
1637
1638// VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter.
1639// Thus we are in charge of freeing an eventual value contained by the inner VARIANT
1640// Please note: VariantCopy doesn't free a VT_BYREF value
1641// The out parameters are expected to have always a valid type
1642static bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource)
1643{
1644 HRESULT hr;
1645 bool ret = false;
1646 // Out parameter must be VT_BYREF
1647 if ((V_VT(pDest) & VT_BYREF) != 0 )
1648 {
1649 VARTYPE oleTypeFlags = V_VT(pSource);
1650
1651 // if caller accept VARIANT as out parameter, any value must be converted
1652 if (V_VT(pDest) == (VT_VARIANT | VT_BYREF))
1653 {
1654 // When the user provides a VARIANT rather than a concrete type
1655 // we just copy the source to the out, in/out parameter
1656 // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that
1657 // is contained in pDest are released by VariantCopy
1658 VariantCopy(V_VARIANTREF(pDest), pSource);
1659 ret = true;
1660 }
1661 else
1662 {
1663 // variantarg and variant must have same type
1664 if ((V_VT(pDest) & oleTypeFlags) == oleTypeFlags)
1665 {
1666 if ((oleTypeFlags & VT_ARRAY) != 0)
1667 {
1668 // In / Out Param
1669 if( *V_ARRAYREF(pDest) != nullptr)
1670 hr= SafeArrayCopyData( V_ARRAY(pSource), *V_ARRAYREF(pDest));
1671 else
1672 // Out Param
1673 hr= SafeArrayCopy(V_ARRAY(pSource), V_ARRAYREF(pDest));
1674 if( SUCCEEDED( hr))
1675 ret = true;
1676 }
1677 else
1678 {
1679 // copy base type
1680 switch (V_VT(pSource))
1681 {
1682 case VT_I2:
1683 {
1684 *V_I2REF(pDest) = V_I2(pSource);
1685 ret = true;
1686 break;
1687 }
1688 case VT_I4:
1689 *V_I4REF(pDest) = V_I4(pSource);
1690 ret = true;
1691 break;
1692 case VT_R4:
1693 *V_R4REF(pDest) = V_R4(pSource);
1694 ret = true;
1695 break;
1696 case VT_R8:
1697 *V_R8REF(pDest) = V_R8(pSource);
1698 ret = true;
1699 break;
1700 case VT_CY:
1701 *V_CYREF(pDest) = V_CY(pSource);
1702 ret = true;
1703 break;
1704 case VT_DATE:
1705 *V_DATEREF(pDest) = V_DATE(pSource);
1706 ret = true;
1707 break;
1708 case VT_BSTR:
1709 SysFreeString( *pDest->pbstrVal);
1710
1711 *V_BSTRREF(pDest) = SysAllocString(V_BSTR(pSource));
1712 ret = true;
1713 break;
1714 case VT_DISPATCH:
1715 if (*V_DISPATCHREF(pDest) != nullptr)
1716 (*V_DISPATCHREF(pDest))->Release();
1717
1718 *V_DISPATCHREF(pDest) = V_DISPATCH(pSource);
1719
1720 if (*V_DISPATCHREF(pDest) != nullptr)
1721 (*V_DISPATCHREF(pDest))->AddRef();
1722
1723 ret = true;
1724 break;
1725 case VT_ERROR:
1726 *V_ERRORREF(pDest) = V_ERROR(pSource);
1727 ret = true;
1728 break;
1729 case VT_BOOL:
1730 *V_BOOLREF(pDest) = V_BOOL(pSource);
1731 ret = true;
1732 break;
1733 case VT_UNKNOWN:
1734 if (*V_UNKNOWNREF(pDest) != nullptr)
1735 (*V_UNKNOWNREF(pDest))->Release();
1736
1737 *V_UNKNOWNREF(pDest) = V_UNKNOWN(pSource);
1738
1739 if (*V_UNKNOWNREF(pDest) != nullptr)
1740 (*V_UNKNOWNREF(pDest))->AddRef();
1741
1742 ret = true;
1743 break;
1744 case VT_I1:
1745 *V_I1REF(pDest) = V_I1(pSource);
1746 ret = true;
1747 break;
1748 case VT_UI1:
1749 *V_UI1REF(pDest) = V_UI1(pSource);
1750 ret = true;
1751 break;
1752 case VT_UI2:
1753 *V_UI2REF(pDest) = V_UI2(pSource);
1754 ret = true;
1755 break;
1756 case VT_UI4:
1757 *V_UI4REF(pDest) = V_UI4(pSource);
1758 ret = true;
1759 break;
1760 case VT_INT:
1761 *V_INTREF(pDest) = V_INT(pSource);
1762 ret = true;
1763 break;
1764 case VT_UINT:
1765 *V_UINTREF(pDest) = V_UINT(pSource);
1766 ret = true;
1767 break;
1768 case VT_DECIMAL:
1769 memcpy(pDest->pdecVal, pSource, sizeof(DECIMAL));
1770 ret = true;
1771 break;
1772 default:
1773 break;
1774 }
1775 }
1776 }
1777 else
1778 {
1779 // Handling of special cases
1780 // Destination and source types are different
1781 if( pDest->vt == (VT_BSTR | VT_BYREF)
1782 && pSource->vt == VT_I2)
1783 {
1784 // When the user provides a String as out our in/out parameter
1785 // and the type is char (TypeClass_CHAR) then we convert to a BSTR
1786 // instead of VT_I2 as is done otherwise
1787 OLECHAR buff[]= {0,0};
1788 buff[0]= pSource->iVal;
1789
1790 SysFreeString( *pDest->pbstrVal);
1791 *pDest->pbstrVal= SysAllocString( buff);
1792 ret = true;
1793 }
1794 }
1795 }
1796 }
1797 return ret;
1798}
1799
1800COM_DECLSPEC_NOTHROW STDMETHODIMP InterfaceOleWrapper::Invoke(DISPID dispidMember,
1801 REFIID /*riid*/,
1802 LCID /*lcid*/,
1803 WORD wFlags,
1804 DISPPARAMS * pdispparams,
1805 VARIANT * pvarResult,
1806 EXCEPINFO * pexcepinfo,
1807 UINT * puArgErr )
1808{
1810
1811 OUString sParams;
1812#if defined SAL_LOG_INFO
1813 sParams += "[";
1814 for (unsigned int i = 0; i < pdispparams->cArgs; ++i)
1815 {
1816 if (i > 0)
1817 sParams += ",";
1818 std::stringstream aStringStream;
1819 aStringStream << pdispparams->rgvarg[i];
1820 sParams += OUString::createFromAscii(aStringStream.str().c_str());
1821 }
1822 sParams += "]";
1823#endif
1824 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::Invoke(" << dispidMember << "," << sParams << ")");
1825
1826 comphelper::ProfileZone aZone("COM Bridge");
1827 HRESULT ret = S_OK;
1828
1829 try
1830 {
1831 bool bHandled= false;
1832 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo,
1833 puArgErr, bHandled);
1834 if( bHandled)
1835 return ret;
1836
1837 if ((dispidMember > 0) && (o3tl::make_unsigned(dispidMember) <= m_MemberInfos.size()) && m_xInvocation.is())
1838 {
1839 MemberInfo d = m_MemberInfos[dispidMember - 1];
1840 DWORD flags = wFlags & d.flags;
1841
1842 if (flags != 0)
1843 {
1844 if ((flags & DISPATCH_METHOD) != 0)
1845 {
1846 std::unique_ptr<DISPPARAMS> pNewDispParams;
1847 std::vector<VARIANTARG> vNewArgs;
1848
1849 if (pdispparams->cNamedArgs > 0)
1850 {
1851 // Convert named arguments to positional ones.
1852
1853 // An example:
1854 //
1855 // Function declaration (in pseudo-code):
1856 // int foo(int A, int B, optional int C, optional int D, optional int E, optional int F, optional int G)
1857 //
1858 // Corresponding parameter numbers (DISPIDs):
1859 // 0 1 2 3 4 5 6
1860 //
1861 // Actual call:
1862 // foo(10, 20, E:=50, D:=40, F:=60)
1863 //
1864 // That is, A and B are passed positionally, D, E, and F as named arguments,
1865 // and the optional C and G parameters are left out.
1866 //
1867 // Incoming DISPPARAMS:
1868 // cArgs=5, cNamedArgs=3
1869 // rgvarg: [60, 40, 50, 20, 10]
1870 // rgdispidNamedArgs: [5, 3, 4]
1871 //
1872 // We calculate nLowestNamedArgDispid = 3 and nHighestNamedArgDispid = 5.
1873 //
1874 // Result of conversion, no named args:
1875 // cArgs=6, cNamedArgs=0
1876 // rgvarg: [60, 50, 40, DISP_E_PARAMNOTFOUND, 20, 10]
1877
1878 // First find the lowest and highest DISPID of the named arguments.
1879 DISPID nLowestNamedArgDispid = 1000000;
1880 DISPID nHighestNamedArgDispid = -1;
1881 for (unsigned int i = 0; i < pdispparams->cNamedArgs; ++i)
1882 {
1883 if (pdispparams->rgdispidNamedArgs[i] < nLowestNamedArgDispid)
1884 nLowestNamedArgDispid = pdispparams->rgdispidNamedArgs[i];
1885 if (pdispparams->rgdispidNamedArgs[i] > nHighestNamedArgDispid)
1886 nHighestNamedArgDispid = pdispparams->rgdispidNamedArgs[i];
1887 }
1888
1889 // Make sure named arguments don't overlap with positional ones. The lowest
1890 // DISPID of the named arguments should be >= the number of positional
1891 // arguments.
1892 if (nLowestNamedArgDispid < static_cast<DISPID>(pdispparams->cArgs - pdispparams->cNamedArgs))
1893 return DISP_E_NONAMEDARGS;
1894
1895 // Do the actual conversion.
1896 pNewDispParams.reset(new DISPPARAMS);
1897 vNewArgs.resize(nHighestNamedArgDispid + 1);
1898 pNewDispParams->rgvarg = vNewArgs.data();
1899 pNewDispParams->rgdispidNamedArgs = nullptr;
1900 pNewDispParams->cArgs = nHighestNamedArgDispid + 1;
1901 pNewDispParams->cNamedArgs = 0;
1902
1903 // Initialise all parameter slots as missing
1904 for (int i = 0; i < nHighestNamedArgDispid; ++i)
1905 {
1906 pNewDispParams->rgvarg[i].vt = VT_ERROR;
1907 pNewDispParams->rgvarg[i].scode = DISP_E_PARAMNOTFOUND;
1908 }
1909
1910 // Then set the value of those actually present.
1911 for (unsigned int i = 0; i < pdispparams->cNamedArgs; ++i)
1912 pNewDispParams->rgvarg[nHighestNamedArgDispid - pdispparams->rgdispidNamedArgs[i]] = pdispparams->rgvarg[i];
1913
1914 const int nFirstUnnamedArg = pdispparams->cNamedArgs + (nLowestNamedArgDispid-(pdispparams->cArgs - pdispparams->cNamedArgs));
1915
1916 for (unsigned int i = pdispparams->cNamedArgs; i < pdispparams->cArgs; ++i)
1917 pNewDispParams->rgvarg[nFirstUnnamedArg + (i-pdispparams->cNamedArgs)] = pdispparams->rgvarg[i];
1918
1919 pdispparams = pNewDispParams.get();
1920 }
1921
1922 Sequence<Any> params;
1923
1924 convertDispparamsArgs(dispidMember, wFlags, pdispparams , params );
1925
1926 ret= doInvoke(pdispparams, pvarResult,
1927 pexcepinfo, puArgErr, d.name, params);
1928 }
1929 else if ((flags & DISPATCH_PROPERTYGET) != 0)
1930 {
1931 ret= doGetProperty( pdispparams, pvarResult,
1932 pexcepinfo, d.name);
1933 }
1934 else if ((flags & DISPATCH_PROPERTYPUT) != 0 || (flags & DISPATCH_PROPERTYPUTREF) != 0)
1935 {
1936 if (pdispparams->cArgs != 1)
1937 ret = DISP_E_BADPARAMCOUNT;
1938 else
1939 {
1940 Sequence<Any> params;
1941 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
1942 if(params.getLength() > 0)
1943 ret= doSetProperty( pdispparams, pvarResult, pexcepinfo, puArgErr, d.name, params);
1944 else
1945 ret = DISP_E_BADVARTYPE;
1946 }
1947 }
1948 }
1949 else
1950 ret= DISP_E_MEMBERNOTFOUND;
1951 }
1952 else
1953 ret = DISP_E_MEMBERNOTFOUND;
1954 }
1955 catch(const BridgeRuntimeError& e)
1956 {
1957 writeExcepinfo(pexcepinfo, e.message);
1958 ret = DISP_E_EXCEPTION;
1959 }
1960 catch(const Exception& e)
1961 {
1962 OUString message= "InterfaceOleWrapper::Invoke : \n" +
1963 e.Message;
1964 writeExcepinfo(pexcepinfo, message);
1965 ret = DISP_E_EXCEPTION;
1966 }
1967 catch(...)
1968 {
1969 writeExcepinfo(pexcepinfo, "InterfaceOleWrapper::Invoke : \nUnexpected exception");
1970 ret = DISP_E_EXCEPTION;
1971 }
1972
1973 return ret;
1974}
1975
1976HRESULT InterfaceOleWrapper::doInvoke( DISPPARAMS * pdispparams, VARIANT * pvarResult,
1977 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any>& params)
1978{
1979
1980
1981 HRESULT ret= S_OK;
1982 try
1983 {
1984 Sequence<sal_Int16> outIndex;
1985 Sequence<Any> outParams;
1986 Any returnValue;
1987
1988 if (pdispparams->cNamedArgs > 0)
1989 return DISP_E_NONAMEDARGS;
1990
1991 // invoke method and take care of exceptions
1992 returnValue = m_xInvocation->invoke(name,
1993 params,
1994 outIndex,
1995 outParams);
1996
1997 // try to write back out parameter
1998 if (outIndex.getLength() > 0)
1999 {
2000 const sal_Int16* pOutIndex = outIndex.getConstArray();
2001 const Any* pOutParams = outParams.getConstArray();
2002
2003 for (sal_Int32 i = 0; i < outIndex.getLength(); i++)
2004 {
2005 CComVariant variant;
2006 // Currently a Sequence is converted to an SafeArray of VARIANTs.
2007 anyToVariant( &variant, pOutParams[i]);
2008
2009 // out parameter need special handling if they are VT_DISPATCH
2010 // and used in JScript
2011 int outindex= pOutIndex[i];
2012 writeBackOutParameter2(&(pdispparams->rgvarg[pdispparams->cArgs - 1 - outindex]),
2013 &variant );
2014 }
2015 }
2016
2017 // write back return value
2018 if (pvarResult != nullptr)
2019 anyToVariant(pvarResult, returnValue);
2020 }
2021 catch(const IllegalArgumentException & e) //XInvocation::invoke
2022 {
2023 writeExcepinfo(pexcepinfo, e.Message);
2024 ret = DISP_E_TYPEMISMATCH;
2025 }
2026 catch(const CannotConvertException & e) //XInvocation::invoke
2027 {
2028 writeExcepinfo(pexcepinfo, e.Message);
2029 ret = mapCannotConvertException( e, puArgErr);
2030 }
2031 catch(const InvocationTargetException & e) //XInvocation::invoke
2032 {
2033 const Any& org = e.TargetException;
2034 Exception excTarget;
2035 org >>= excTarget;
2036 OUString message=
2037 org.getValueType().getTypeName() + ": " + excTarget.Message;
2038 writeExcepinfo(pexcepinfo, message);
2039 ret = DISP_E_EXCEPTION;
2040 }
2041 catch(const NoSuchMethodException & e) //XInvocation::invoke
2042 {
2043 writeExcepinfo(pexcepinfo, e.Message);
2044 ret = DISP_E_MEMBERNOTFOUND;
2045 }
2046 catch(const BridgeRuntimeError & e)
2047 {
2048 writeExcepinfo(pexcepinfo, e.message);
2049 ret = DISP_E_EXCEPTION;
2050 }
2051 catch(const Exception & e)
2052 {
2053 OUString message= "InterfaceOleWrapper::doInvoke : \n" +
2054 e.Message;
2055 writeExcepinfo(pexcepinfo, message);
2056 ret = DISP_E_EXCEPTION;
2057 }
2058 catch( ... )
2059 {
2060 writeExcepinfo(pexcepinfo, "InterfaceOleWrapper::doInvoke : \nUnexpected exception");
2061 ret = DISP_E_EXCEPTION;
2062 }
2063 return ret;
2064}
2065
2066HRESULT InterfaceOleWrapper::doGetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * pvarResult,
2067 EXCEPINFO * pexcepinfo, OUString& name)
2068{
2069 HRESULT ret= S_OK;
2070
2071 try
2072 {
2073 Any returnValue = m_xInvocation->getValue( name);
2074 // write back return value
2075 if (pvarResult)
2076 anyToVariant(pvarResult, returnValue);
2077 }
2078 catch(const UnknownPropertyException& e) //XInvocation::getValue
2079 {
2080 writeExcepinfo(pexcepinfo, e.Message);
2081 ret = DISP_E_MEMBERNOTFOUND;
2082 }
2083 catch(const BridgeRuntimeError& e)
2084 {
2085 writeExcepinfo(pexcepinfo, e.message);
2086 ret = DISP_E_EXCEPTION;
2087 }
2088 catch(const Exception& e)
2089 {
2090 OUString message= "InterfaceOleWrapper::doGetProperty : \n" +
2091 e.Message;
2092 writeExcepinfo(pexcepinfo, message);
2093 }
2094 catch( ... )
2095 {
2096 writeExcepinfo(pexcepinfo, "InterfaceOleWrapper::doInvoke : \nUnexpected exception");
2097 ret = DISP_E_EXCEPTION;
2098 }
2099 return ret;
2100}
2101
2102HRESULT InterfaceOleWrapper::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
2103 EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any> const & params)
2104{
2105 HRESULT ret= S_OK;
2106
2107 try
2108 {
2109 m_xInvocation->setValue( name, params.getConstArray()[0]);
2110 }
2111 catch(const UnknownPropertyException &)
2112 {
2113 ret = DISP_E_MEMBERNOTFOUND;
2114 }
2115 catch(const CannotConvertException &e)
2116 {
2117 ret= mapCannotConvertException( e, puArgErr);
2118 }
2119 catch(const InvocationTargetException &e)
2120 {
2121 if (pexcepinfo != nullptr)
2122 {
2123 Any org = e.TargetException;
2124
2125 pexcepinfo->wCode = UNO_2_OLE_EXCEPTIONCODE;
2126 pexcepinfo->bstrSource = SysAllocString(L"any ONE component");
2127 pexcepinfo->bstrDescription = SysAllocString(
2128 o3tl::toW(org.getValueType().getTypeName().getStr()));
2129 }
2130 ret = DISP_E_EXCEPTION;
2131 }
2132 catch( ... )
2133 {
2134 ret= DISP_E_EXCEPTION;
2135 }
2136 return ret;
2137}
2138
2139namespace {
2140
2141class CXEnumVariant : public IEnumVARIANT,
2142 public CComObjectRoot
2143{
2144public:
2145 CXEnumVariant()
2146 : mnIndex(1) // ooo::vba::XCollection index starts at one
2147 {
2148 }
2149
2150 virtual ~CXEnumVariant()
2151 {
2152 }
2153
2154#if defined __clang__
2155#pragma clang diagnostic push
2156#pragma clang diagnostic ignored "-Wunused-function"
2157#endif
2158 BEGIN_COM_MAP(CXEnumVariant)
2159#if defined __clang__
2160#pragma clang diagnostic pop
2161#endif
2162 COM_INTERFACE_ENTRY(IEnumVARIANT)
2163#if defined __clang__
2164#pragma clang diagnostic push
2165#pragma clang diagnostic ignored "-Winconsistent-missing-override"
2166#pragma clang diagnostic ignored "-Wunused-function"
2167#endif
2168 END_COM_MAP()
2169#if defined __clang__
2170#pragma clang diagnostic pop
2171#endif
2172
2173 DECLARE_NOT_AGGREGATABLE(CXEnumVariant)
2174
2175 // Creates and initializes the enumerator
2176 void Init(InterfaceOleWrapper* pInterfaceOleWrapper,
2177 const Reference<ooo::vba::XCollection > xCollection)
2178 {
2179 mpInterfaceOleWrapper = pInterfaceOleWrapper;
2180 mxCollection = xCollection;
2181 }
2182
2183 // IEnumVARIANT
2184 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **) override
2185 {
2186 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Clone: E_NOTIMPL");
2187 return E_NOTIMPL;
2188 }
2189
2190 virtual HRESULT STDMETHODCALLTYPE Next(ULONG const celt,
2191 VARIANT *rgVar,
2192 ULONG *pCeltFetched) override
2193 {
2195
2196 if (pCeltFetched)
2197 *pCeltFetched = 0;
2198
2199 if (celt == 0)
2200 {
2201 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt << "): E_INVALIDARG");
2202 return E_INVALIDARG;
2203 }
2204
2205 if (rgVar == nullptr || (celt != 1 && pCeltFetched == nullptr))
2206 {
2207 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt << "): E_FAIL");
2208 return E_FAIL;
2209 }
2210
2211 for (ULONG i = 0; i < celt; i++)
2212 VariantInit(&rgVar[i]);
2213
2214 ULONG nLeft = celt;
2215 ULONG nReturned = 0;
2216 while (nLeft > 0)
2217 {
2218 if (mnIndex > mxCollection->getCount())
2219 {
2220 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt << "): got " << nReturned << ": S_FALSE");
2221 return S_FALSE;
2222 }
2223 Any aIndex;
2224 aIndex <<= mnIndex;
2225 Any aElement = mxCollection->Item(aIndex, Any());
2226 mpInterfaceOleWrapper->anyToVariant(rgVar, aElement);
2227 // rgVar->pdispVal->AddRef(); ??
2228 if (pCeltFetched)
2229 (*pCeltFetched)++;
2230 rgVar++;
2231 nReturned++;
2232 mnIndex++;
2233 nLeft--;
2234 }
2235 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt << "): S_OK");
2236 return S_OK;
2237 }
2238
2239 virtual HRESULT STDMETHODCALLTYPE Reset() override
2240 {
2241 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Reset: S_OK");
2242 mnIndex = 1;
2243 return S_OK;
2244 }
2245
2246 virtual HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE Skip(ULONG const celt) override
2247 {
2249
2250 ULONG nLeft = celt;
2251 ULONG nSkipped = 0;
2252 while (nLeft > 0)
2253 {
2254 if (mnIndex > mxCollection->getCount())
2255 {
2256 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Skip(" << celt << "): skipped " << nSkipped << ": S_FALSE");
2257 return S_FALSE;
2258 }
2259 mnIndex++;
2260 nLeft--;
2261 }
2262 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Skip(" << celt << "): S_OK");
2263 return S_OK;
2264 }
2265
2266private:
2267 InterfaceOleWrapper* mpInterfaceOleWrapper;
2269 sal_Int32 mnIndex;
2270};
2271
2272class Sink : public cppu::WeakImplHelper<ooo::vba::XSink>
2273{
2274public:
2275 Sink(IUnknown* pUnkSink,
2277 ooo::vba::TypeAndIID aTypeAndIID,
2278 InterfaceOleWrapper* pInterfaceOleWrapper);
2279
2280 // XSink
2281 void SAL_CALL Call( const OUString& Method, Sequence< Any >& Arguments ) override;
2282
2283private:
2284 IUnknown* mpUnkSink;
2286 ooo::vba::TypeAndIID maTypeAndIID;
2287 InterfaceOleWrapper* mpInterfaceOleWrapper;
2288};
2289
2290}
2291
2292Sink::Sink(IUnknown* pUnkSink,
2294 ooo::vba::TypeAndIID aTypeAndIID,
2295 InterfaceOleWrapper* pInterfaceOleWrapper) :
2296 mpUnkSink(pUnkSink),
2297 mxMSF(xMSF),
2298 maTypeAndIID(aTypeAndIID),
2299 mpInterfaceOleWrapper(pInterfaceOleWrapper)
2300{
2301 mpUnkSink->AddRef();
2302}
2303
2304void SAL_CALL
2305Sink::Call( const OUString& Method, Sequence< Any >& Arguments )
2306{
2307 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method << ", " << Arguments.getLength() << " arguments)");
2308
2309 IDispatch* pDispatch;
2310 HRESULT nResult = mpUnkSink->QueryInterface(IID_IDispatch, reinterpret_cast<void **>(&pDispatch));
2311 if (!SUCCEEDED(nResult))
2312 {
2313 SAL_WARN("extensions.olebridge", "Sink::Call: Not IDispatch: " << WindowsErrorStringFromHRESULT(nResult));
2314 return;
2315 }
2316
2317 Reference<XIdlReflection> xRefl = theCoreReflection::get(comphelper::getComponentContext(mxMSF));
2318 assert(xRefl.is());
2319
2320 Reference<XIdlClass> xClass = xRefl->forName(maTypeAndIID.Type.getTypeName());
2321 assert(xClass.is());
2322
2323 auto aMethods = xClass->getMethods();
2324 assert(xClass->getTypeClass() == TypeClass_INTERFACE &&
2325 aMethods.getLength() > 0);
2326
2327 int nMemId = 1;
2328 auto ArgumentsRange = asNonConstRange(Arguments);
2329 // Skip the three XInterface methods
2330 for (int i = 3; i < aMethods.getLength(); i++)
2331 {
2332 if (aMethods[i]->getName() == Method)
2333 {
2334 // FIXME: Handle mismatch in type of actual argument and parameter of the method.
2335
2336 // FIXME: Handle mismatch in number of arguments passed and actual number of parameters
2337 // of the method.
2338
2339 auto aParamInfos = aMethods[i]->getParameterInfos();
2340
2341 assert(Arguments.getLength() == aParamInfos.getLength());
2342
2343 DISPPARAMS aDispParams;
2344 aDispParams.rgdispidNamedArgs = nullptr;
2345 aDispParams.cArgs = Arguments.getLength();
2346 aDispParams.cNamedArgs = 0;
2347 aDispParams.rgvarg = new VARIANT[aDispParams.cArgs];
2348 for (unsigned j = 0; j < aDispParams.cArgs; j++)
2349 {
2350 VariantInit(aDispParams.rgvarg+j);
2351 // Note: Reverse order of arguments in Arguments and aDispParams.rgvarg!
2352 const unsigned nIncomingArgIndex = aDispParams.cArgs - j - 1;
2353 mpInterfaceOleWrapper->anyToVariant(aDispParams.rgvarg+j, Arguments[nIncomingArgIndex]);
2354
2355 // Handle OUT and INOUT arguments. For instance, the second ('Cancel') parameter to
2356 // DocumentBeforeClose() should be a VT_BYREF|VT_BOOL parameter. Need to handle that
2357 // here.
2358
2359 if (aParamInfos[nIncomingArgIndex].aMode == ParamMode_OUT ||
2360 aParamInfos[nIncomingArgIndex].aMode == ParamMode_INOUT)
2361 {
2362 switch (aDispParams.rgvarg[j].vt)
2363 {
2364 case VT_I2:
2365 aDispParams.rgvarg[j].byref = new SHORT(aDispParams.rgvarg[j].iVal);
2366 aDispParams.rgvarg[j].vt |= VT_BYREF;
2367 break;
2368 case VT_I4:
2369 aDispParams.rgvarg[j].byref = new LONG(aDispParams.rgvarg[j].lVal);
2370 aDispParams.rgvarg[j].vt |= VT_BYREF;
2371 break;
2372 case VT_BSTR:
2373 aDispParams.rgvarg[j].byref = new BSTR(aDispParams.rgvarg[j].bstrVal);
2374 aDispParams.rgvarg[j].vt |= VT_BYREF;
2375 break;
2376 case VT_BOOL:
2377 aDispParams.rgvarg[j].byref = new VARIANT_BOOL(aDispParams.rgvarg[j].boolVal);
2378 aDispParams.rgvarg[j].vt |= VT_BYREF;
2379 break;
2380 default:
2381 assert(false && "Not handled yet");
2382 break;
2383 }
2384 }
2385 }
2386
2387 VARIANT aVarResult;
2388 VariantInit(&aVarResult);
2389 UINT uArgErr;
2390
2391 // In the case of a VBScript client, which uses "late binding", calling Invoke on the
2392 // sink it provides will cause a callback to our CXTypeInfo::GetNames for the given
2393 // member id, and in that we will tell it the name of the corresponding method, and the
2394 // client will know what event handler to invoke based on that name.
2395 //
2396 // As the outgoing interfaces used (ooo::vba::word::XApplicationOutgoing and others) are
2397 // totally not stable and not published in any way, there can be no client that would
2398 // have done "compile-time binding" and where the sink would actually be an object with
2399 // a vtbl corresponding to the outgoing interface. Late binding clients that work like
2400 // VBScript is all we support.
2401 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method << "): Calling Invoke(" << nMemId << ")");
2402
2403 nResult = pDispatch->Invoke(nMemId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &aDispParams, &aVarResult, nullptr, &uArgErr);
2404 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method << "): Invoke() returned");
2405
2406 SAL_WARN_IF(!SUCCEEDED(nResult), "extensions.olebridge", "Call to " << Method << " failed: " << WindowsErrorStringFromHRESULT(nResult));
2407
2408 // Undo VT_BYREF magic done above. Copy out parameters back to the Anys in Arguments
2409 for (unsigned j = 0; j < aDispParams.cArgs; j++)
2410 {
2411 const unsigned nIncomingArgIndex = aDispParams.cArgs - j - 1;
2412 if (aParamInfos[nIncomingArgIndex].aMode == ParamMode_OUT ||
2413 aParamInfos[nIncomingArgIndex].aMode == ParamMode_INOUT)
2414 {
2415 switch (aDispParams.rgvarg[j].vt)
2416 {
2417 case VT_BYREF|VT_I2:
2418 {
2419 SHORT *pI = static_cast<SHORT*>(aDispParams.rgvarg[j].byref);
2420 ArgumentsRange[nIncomingArgIndex] <<= static_cast<sal_Int16>(*pI);
2421 delete pI;
2422 }
2423 break;
2424 case VT_BYREF|VT_I4:
2425 {
2426 LONG *pL = static_cast<LONG*>(aDispParams.rgvarg[j].byref);
2427 ArgumentsRange[nIncomingArgIndex] <<= static_cast<sal_Int32>(*pL);
2428 delete pL;
2429 }
2430 break;
2431 case VT_BYREF|VT_BSTR:
2432 {
2433 BSTR *pBstr = static_cast<BSTR*>(aDispParams.rgvarg[j].byref);
2434 ArgumentsRange[nIncomingArgIndex] <<= OUString(o3tl::toU(*pBstr));
2435 // Undo SysAllocString() done in anyToVariant()
2436 SysFreeString(*pBstr);
2437 delete pBstr;
2438 }
2439 break;
2440 case VT_BYREF|VT_BOOL:
2441 {
2442 VARIANT_BOOL *pBool = static_cast<VARIANT_BOOL*>(aDispParams.rgvarg[j].byref);
2443 ArgumentsRange[nIncomingArgIndex] <<= (*pBool != VARIANT_FALSE);
2444 delete pBool;
2445 }
2446 break;
2447 default:
2448 assert(false && "Not handled yet");
2449 break;
2450 }
2451 }
2452 else
2453 {
2454 switch (aDispParams.rgvarg[j].vt)
2455 {
2456 case VT_BSTR:
2457 // Undo SysAllocString() done in anyToVariant()
2458 SysFreeString(aDispParams.rgvarg[j].bstrVal);
2459 break;
2460 }
2461 }
2462 }
2463
2464 delete[] aDispParams.rgvarg;
2465 return;
2466 }
2467 nMemId++;
2468 }
2469 SAL_WARN("extensions.olebridge", "Sink::Call: Unknown method '" << Method << "'");
2470}
2471
2472namespace {
2473
2474class CXEnumConnections : public IEnumConnections,
2475 public CComObjectRoot
2476{
2477public:
2478 CXEnumConnections()
2479 {
2480 }
2481
2482 virtual ~CXEnumConnections()
2483 {
2484 }
2485
2486#if defined __clang__
2487#pragma clang diagnostic push
2488#pragma clang diagnostic ignored "-Wunused-function"
2489#endif
2490 BEGIN_COM_MAP(CXEnumConnections)
2491#if defined __clang__
2492#pragma clang diagnostic pop
2493#endif
2494 COM_INTERFACE_ENTRY(IEnumConnections)
2495#if defined __clang__
2496#pragma clang diagnostic push
2497#pragma clang diagnostic ignored "-Winconsistent-missing-override"
2498#pragma clang diagnostic ignored "-Wunused-function"
2499#endif
2500 END_COM_MAP()
2501#if defined __clang__
2502#pragma clang diagnostic pop
2503#endif
2504
2505 DECLARE_NOT_AGGREGATABLE(CXEnumConnections)
2506
2507 void Init(std::vector<IUnknown*>& rUnknowns, std::vector<DWORD>& rCookies)
2508 {
2509 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Init");
2510 SAL_WARN_IF(rUnknowns.size() != rCookies.size(), "extensions.olebridge", "Vectors of different size");
2511 mvUnknowns = rUnknowns;
2512 mvCookies = rCookies;
2513 mnIndex = 0;
2514 }
2515
2516 virtual HRESULT STDMETHODCALLTYPE Next(ULONG cConnections,
2517 LPCONNECTDATA rgcd,
2518 ULONG *pcFetched) override
2519 {
2521
2522 if (!rgcd)
2523 {
2524 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections << "): E_POINTER");
2525 return E_POINTER;
2526 }
2527
2528 if (pcFetched && cConnections != 1)
2529 {
2530 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections << "): E_INVALIDARG");
2531 return E_INVALIDARG;
2532 }
2533
2534 ULONG nFetched = 0;
2535 while (nFetched < cConnections && mnIndex < mvUnknowns.size())
2536 {
2537 rgcd[nFetched].pUnk = mvUnknowns[mnIndex];
2538 rgcd[nFetched].pUnk->AddRef();
2539 rgcd[nFetched].dwCookie = mvCookies[mnIndex];
2540 ++nFetched;
2541 ++mnIndex;
2542 }
2543 if (nFetched != cConnections)
2544 {
2545 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections << "): S_FALSE");
2546 if (pcFetched)
2547 *pcFetched = nFetched;
2548 return S_FALSE;
2549 }
2550 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections << "): S_OK");
2551 if (pcFetched)
2552 *pcFetched = nFetched;
2553
2554 return S_OK;
2555 }
2556
2557 virtual HRESULT STDMETHODCALLTYPE Skip(ULONG cConnections) override
2558 {
2559 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Skip(" << cConnections << "): E_NOTIMPL");
2560
2561 return E_NOTIMPL;
2562 }
2563
2564 virtual HRESULT STDMETHODCALLTYPE Reset() override
2565 {
2566 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Reset: E_NOTIMPL");
2567
2568 return E_NOTIMPL;
2569 }
2570
2571 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumConnections** /* ppEnum */) override
2572 {
2573 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Clone: E_NOTIMPL");
2574
2575 return E_NOTIMPL;
2576 }
2577
2578private:
2579 std::vector<IUnknown*> mvUnknowns;
2580 std::vector<DWORD> mvCookies;
2581 ULONG mnIndex;
2582};
2583
2584class CXConnectionPoint : public IConnectionPoint,
2585 public CComObjectRoot
2586{
2587public:
2588#if defined __clang__
2589#pragma clang diagnostic push
2590#pragma clang diagnostic ignored "-Wunused-function"
2591#endif
2592 BEGIN_COM_MAP(CXConnectionPoint)
2593#if defined __clang__
2594#pragma clang diagnostic pop
2595#endif
2596 COM_INTERFACE_ENTRY(IConnectionPoint)
2597#if defined __clang__
2598#pragma clang diagnostic push
2599#pragma clang diagnostic ignored "-Winconsistent-missing-override"
2600#pragma clang diagnostic ignored "-Wunused-function"
2601#endif
2602 END_COM_MAP()
2603#if defined __clang__
2604#pragma clang diagnostic pop
2605#endif
2606
2607 DECLARE_NOT_AGGREGATABLE(CXConnectionPoint)
2608
2609 virtual ~CXConnectionPoint() {}
2610
2611 void Init(InterfaceOleWrapper* pInterfaceOleWrapper,
2614 ooo::vba::TypeAndIID aTypeAndIID)
2615 {
2616 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Init for " << pInterfaceOleWrapper->getImplementationName());
2617
2618 IUnknown *pUnknown;
2619 if (SUCCEEDED(QueryInterface(IID_IUnknown, reinterpret_cast<void **>(&pUnknown))))
2620 {
2621 // In case QI for IUnknown returns a different pointer, but nah, it doesn't
2622 SAL_INFO("extensions.olebridge", " (IUnknown@" << pUnknown << ")");
2623 }
2624
2625 mpInterfaceOleWrapper = pInterfaceOleWrapper;
2626 mxCP = xCP;
2627 mxMSF = xMSF;
2628 maTypeAndIID = aTypeAndIID;
2629 }
2630
2631 virtual HRESULT STDMETHODCALLTYPE GetConnectionInterface(IID *pIID) override
2632 {
2633 SAL_WARN("extensions.olebridge", this << "@CXConnectionPoint::GetConnectionInterface(" << *pIID << "): E_NOTIMPL");
2634
2635 // FIXME: Needed?
2636
2637 return E_NOTIMPL;
2638 }
2639
2640 virtual HRESULT STDMETHODCALLTYPE GetConnectionPointContainer(IConnectionPointContainer **) override
2641 {
2642 SAL_WARN("extensions.olebridge", this << "@CXConnectionPoint::GetConnectionInterface: E_NOTIMPL");
2643
2644 // FIXME: Needed?
2645
2646 return E_NOTIMPL;
2647 }
2648
2649 virtual HRESULT STDMETHODCALLTYPE Advise(IUnknown *pUnkSink,
2650 DWORD *pdwCookie) override
2651 {
2653
2654 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Advise(" << pUnkSink << ")");
2655
2656 if (!pdwCookie)
2657 return E_POINTER;
2658
2659 Reference<ooo::vba::XSink> xSink(new Sink(pUnkSink, mxMSF, maTypeAndIID, mpInterfaceOleWrapper));
2660
2661 mvISinks.push_back(pUnkSink);
2662 *pdwCookie = mvISinks.size();
2663
2664 mvCookies.push_back(mxCP->Advise(xSink));
2665
2666 mvXSinks.push_back(xSink);
2667
2668 SAL_INFO("extensions.olebridge", " *pdwCookie: " << *pdwCookie);
2669
2670 return S_OK;
2671 }
2672
2673 virtual HRESULT STDMETHODCALLTYPE Unadvise(DWORD dwCookie) override
2674 {
2676
2677 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Unadvise(" << dwCookie << ")");
2678
2679 if (dwCookie == 0 || dwCookie > mvISinks.size())
2680 return E_POINTER;
2681
2682 mvISinks[dwCookie-1] = nullptr;
2683
2684 mxCP->Unadvise(mvCookies[dwCookie-1]);
2685
2686 mvXSinks[dwCookie-1] = Reference<ooo::vba::XSink>();
2687
2688 return S_OK;
2689 }
2690
2691 virtual HRESULT STDMETHODCALLTYPE EnumConnections(IEnumConnections **ppEnum) override
2692 {
2694
2695 HRESULT nResult;
2696
2697 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::EnumConnections...");
2698
2699 if (!ppEnum)
2700 {
2701 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: E_POINTER");
2702 return E_POINTER;
2703 }
2704
2705 CComObject<CXEnumConnections>* pEnumConnections;
2706
2707 nResult = CComObject<CXEnumConnections>::CreateInstance(&pEnumConnections);
2708 if (FAILED(nResult))
2709 {
2710 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: " << WindowsErrorStringFromHRESULT(nResult));
2711 return nResult;
2712 }
2713
2714 pEnumConnections->AddRef();
2715
2716 pEnumConnections->Init(mvISinks, mvCookies);
2717 *ppEnum = pEnumConnections;
2718
2719 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: S_OK");
2720
2721 return S_OK;
2722 }
2723
2724 InterfaceOleWrapper* mpInterfaceOleWrapper;
2725 std::vector<IUnknown*> mvISinks;
2726 std::vector<Reference<ooo::vba::XSink>> mvXSinks;
2727 std::vector<DWORD> mvCookies;
2730 ooo::vba::TypeAndIID maTypeAndIID;
2731};
2732
2733}
2734
2735HRESULT InterfaceOleWrapper::InvokeGeneral( DISPID dispidMember, unsigned short wFlags,
2736 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
2737 unsigned int * /*puArgErr*/, bool& bHandled)
2738{
2739 HRESULT ret= S_OK;
2740 try
2741 {
2742// DISPID_VALUE | The DEFAULT Value is required in JScript when the situation
2743// is that we put an object into an Array object ( out parameter). We have to return
2744// IDispatch otherwise the object cannot be accessed from the Script.
2745 if( dispidMember == DISPID_VALUE && (wFlags & DISPATCH_PROPERTYGET) != 0
2746 && m_defaultValueType != VT_EMPTY && pvarResult != nullptr)
2747 {
2748 // Special case hack: If it is a ScVbaCheckBox, return the boolean value
2750 if (xCheckBox.is())
2751 {
2752 bHandled = true;
2753 Any aValue = xCheckBox->getValue();
2754 anyToVariant(pvarResult, aValue);
2755 return S_OK;
2756 }
2757
2758 bHandled= true;
2759 if( m_defaultValueType == VT_DISPATCH)
2760 {
2761 pvarResult->vt= VT_DISPATCH;
2762 pvarResult->pdispVal= this;
2763 AddRef();
2764 ret= S_OK;
2765 }
2766 }
2767
2768 // function: _GetValueObject
2769 else if( dispidMember == DISPID_JSCRIPT_VALUE_FUNC)
2770 {
2771 bHandled= true;
2772 if( !pvarResult)
2773 return E_POINTER;
2774 CComObject< JScriptValue>* pValue;
2775 if( SUCCEEDED( CComObject<JScriptValue>::CreateInstance( &pValue)))
2776 {
2777 pValue->AddRef();
2778 pvarResult->vt= VT_DISPATCH;
2779 pvarResult->pdispVal= CComQIPtr<IDispatch>(pValue->GetUnknown());
2780 ret= S_OK;
2781 }
2782 else
2783 ret= DISP_E_EXCEPTION;
2784 }
2785 else if( dispidMember == DISPID_GET_STRUCT_FUNC)
2786 {
2787 bHandled= true;
2788 bool bStruct= false;
2789
2790
2791 Reference<XIdlReflection> xRefl = theCoreReflection::get(comphelper::getComponentContext(m_smgr));
2792 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
2793 CComVariant arg;
2794 if( pdispparams->cArgs == 1 && SUCCEEDED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])) )
2795 {
2796 Reference<XIdlClass> classStruct= xRefl->forName(OUString(o3tl::toU(arg.bstrVal)));
2797 if( classStruct.is())
2798 {
2799 Any anyStruct;
2800 classStruct->createObject( anyStruct);
2801 CComVariant var;
2802 anyToVariant( &var, anyStruct );
2803
2804 if( var.vt == VT_DISPATCH)
2805 {
2806 VariantCopy( pvarResult, & var);
2807 bStruct= true;
2808 }
2809 }
2810 }
2811 ret= bStruct ? S_OK : DISP_E_EXCEPTION;
2812 }
2813 else if (dispidMember == DISPID_CREATE_TYPE_FUNC)
2814 {
2815 bHandled= true;
2816 if( !pvarResult)
2817 return E_POINTER;
2818 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
2819 CComVariant arg;
2820 if( pdispparams->cArgs != 1)
2821 return DISP_E_BADPARAMCOUNT;
2822 if (FAILED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])))
2823 return DISP_E_BADVARTYPE;
2824
2825 //check if the provided name represents a valid type
2826 Type type;
2827 if (!getType(arg.bstrVal, type))
2828 {
2829 writeExcepinfo(pexcepinfo, OUString::Concat("[automation bridge] A UNO type with the name ") +
2830 o3tl::toU(arg.bstrVal) + " does not exist!");
2831 return DISP_E_EXCEPTION;
2832 }
2833
2834 if (!createUnoTypeWrapper(arg.bstrVal, pvarResult))
2835 {
2836 writeExcepinfo(pexcepinfo, "[automation bridge] InterfaceOleWrapper::InvokeGeneral\n"
2837 "Could not initialize UnoTypeWrapper object!");
2838 return DISP_E_EXCEPTION;
2839 }
2840 }
2841 else if (dispidMember == DISPID_NEWENUM)
2842 {
2843 bHandled = true;
2844 if( !pvarResult)
2845 return E_POINTER;
2846
2847 Reference< ooo::vba::XCollection> xCollection(m_xOrigin, UNO_QUERY);
2848 if (!xCollection.is())
2849 return DISP_E_MEMBERNOTFOUND;
2850
2851 CComObject<CXEnumVariant>* pEnumVar;
2852
2853 ret = CComObject<CXEnumVariant>::CreateInstance(&pEnumVar);
2854 if (FAILED(ret))
2855 return ret;
2856
2857 pEnumVar->AddRef();
2858
2859 pEnumVar->Init(this, xCollection);
2860
2861 pvarResult->vt = VT_UNKNOWN;
2862 pvarResult->punkVal = nullptr;
2863
2864 ret = pEnumVar->QueryInterface(IID_IUnknown, reinterpret_cast<void**>(&pvarResult->punkVal));
2865 if (FAILED(ret))
2866 {
2867 pEnumVar->Release();
2868 return ret;
2869 }
2870 }
2871 }
2872 catch(const BridgeRuntimeError & e)
2873 {
2874 writeExcepinfo(pexcepinfo, e.message);
2875 ret = DISP_E_EXCEPTION;
2876 }
2877 catch(const Exception & e)
2878 {
2879 OUString message= "InterfaceOleWrapper::InvokeGeneral : \n" +
2880 e.Message;
2881 writeExcepinfo(pexcepinfo, message);
2882 ret = DISP_E_EXCEPTION;
2883 }
2884 catch( ... )
2885 {
2886 writeExcepinfo(pexcepinfo, "InterfaceOleWrapper::InvokeGeneral : \nUnexpected exception");
2887 ret = DISP_E_EXCEPTION;
2888 }
2889 return ret;
2890}
2891
2892STDMETHODIMP InterfaceOleWrapper::GetDispID(BSTR /*bstrName*/, DWORD /*grfdex*/, DISPID __RPC_FAR* /*pid*/)
2893{
2894 return ResultFromScode(E_NOTIMPL);
2895}
2896
2898 /* [in] */ DISPID /*id*/,
2899 /* [in] */ LCID /*lcid*/,
2900 /* [in] */ WORD /*wFlags*/,
2901 /* [in] */ DISPPARAMS __RPC_FAR* /*pdp*/,
2902 /* [out] */ VARIANT __RPC_FAR* /*pvarRes*/,
2903 /* [out] */ EXCEPINFO __RPC_FAR* /*pei*/,
2904 /* [unique][in] */ IServiceProvider __RPC_FAR* /*pspCaller*/)
2905{
2906 return ResultFromScode(E_NOTIMPL);
2907}
2908
2910 /* [in] */ BSTR /*bstr*/,
2911 /* [in] */ DWORD /*grfdex*/)
2912{
2913 return ResultFromScode(E_NOTIMPL);
2914}
2915
2917{
2918 return ResultFromScode(E_NOTIMPL);
2919}
2920
2922 /* [in] */ DISPID /*id*/,
2923 /* [in] */ DWORD /*grfdexFetch*/,
2924 /* [out] */ DWORD __RPC_FAR* /*pgrfdex*/)
2925{
2926 return ResultFromScode(E_NOTIMPL);
2927}
2928
2930 /* [in] */ DISPID /*id*/,
2931 /* [out] */ BSTR __RPC_FAR* /*pbstrName*/)
2932{
2933 return ResultFromScode(E_NOTIMPL);
2934}
2935
2937 /* [in] */ DWORD /*grfdex*/,
2938 /* [in] */ DISPID /*id*/,
2939 /* [out] */ DISPID __RPC_FAR* /*pid*/)
2940{
2941 return ResultFromScode(E_NOTIMPL);
2942}
2943
2945 /* [out] */ IUnknown __RPC_FAR *__RPC_FAR* /*ppunk*/)
2946{
2947 return ResultFromScode(E_NOTIMPL);
2948}
2949
2950// IProvideClassInfo
2951HRESULT STDMETHODCALLTYPE InterfaceOleWrapper::GetClassInfo (
2952 /* [out] */ ITypeInfo **ppTI)
2953{
2955
2956 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetClassInfo");
2957
2958 if (!ppTI)
2959 return E_POINTER;
2960
2962 if (!xIID.is())
2963 return E_NOTIMPL;
2964
2965 OUString sIID = xIID->getIID();
2966 IID aIID;
2967 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR>(sIID.pData->buffer), &aIID)))
2968 return E_NOTIMPL;
2969
2970 HRESULT ret;
2971
2972 CComObject<CXTypeInfo>* pTypeInfo;
2973
2974 ret = CComObject<CXTypeInfo>::CreateInstance(&pTypeInfo);
2975 if (FAILED(ret))
2976 return ret;
2977
2978 pTypeInfo->AddRef();
2979
2980 pTypeInfo->InitForCoclass(m_xOrigin, m_sImplementationName, aIID, m_smgr);
2981
2982 *ppTI = pTypeInfo;
2983
2984 return S_OK;
2985}
2986
2987// IConnectionPointContainer
2989 /* [out] */ IEnumConnectionPoints **)
2990{
2991 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::EnumConnectionPoints");
2992 return ResultFromScode(E_NOTIMPL);
2993}
2994
2996 /* [in] */ REFIID riid,
2997 /* [out] */ IConnectionPoint **ppCP)
2998{
3000
3001 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::FindConnectionPoint(" << riid << ")");
3002
3003 if (!ppCP)
3004 return E_POINTER;
3005
3006 Reference<ooo::vba::XConnectable> xConnectable(m_xOrigin, UNO_QUERY);
3007
3008 // We checked already
3009 assert(xConnectable.is());
3010 if (!xConnectable.is())
3011 return E_NOTIMPL;
3012
3013 ooo::vba::TypeAndIID aTypeAndIID = xConnectable->GetConnectionPoint();
3014
3015 IID aIID;
3016 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR>(aTypeAndIID.IID.pData->buffer), &aIID)))
3017 return E_INVALIDARG;
3018
3019 if (!IsEqualIID(riid, aIID))
3020 return E_INVALIDARG;
3021
3022 Reference<ooo::vba::XConnectionPoint> xCP = xConnectable->FindConnectionPoint();
3023 if (!xCP.is())
3024 return E_INVALIDARG;
3025
3026 HRESULT ret;
3027
3028 CComObject<CXConnectionPoint>* pConnectionPoint;
3029
3030 ret = CComObject<CXConnectionPoint>::CreateInstance(&pConnectionPoint);
3031 if (FAILED(ret))
3032 return ret;
3033
3034 pConnectionPoint->AddRef();
3035
3036 pConnectionPoint->Init(this, xCP, m_smgr, aTypeAndIID);
3037
3038 *ppCP = pConnectionPoint;
3039
3040 return S_OK;
3041}
3042
3043// UnoObjectWrapperRemoteOpt ---------------------------------------------------
3044
3046 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
3047InterfaceOleWrapper( aFactory, unoWrapperClass, comWrapperClass),
3048m_currentId(1)
3049
3050{
3051}
3053{
3054}
3055
3056// UnoConversionUtilities
3058{
3059 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
3061 return Reference<XInterface>( xWeak, UNO_QUERY);
3062}
3063
3064COM_DECLSPEC_NOTHROW STDMETHODIMP UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID /*riid*/, LPOLESTR * rgszNames, UINT cNames,
3065 LCID /*lcid*/, DISPID * rgdispid )
3066{
3067 MutexGuard guard( getBridgeMutex());
3068
3069 if( ! rgdispid)
3070 return E_POINTER;
3071 HRESULT ret = E_UNEXPECTED;
3072
3073 // _GetValueObject
3074 if( ! wcscmp( *rgszNames, JSCRIPT_VALUE_FUNC))
3075 {
3076 *rgdispid= DISPID_JSCRIPT_VALUE_FUNC;
3077 return S_OK;
3078 }
3079 else if( ! wcscmp( *rgszNames, GET_STRUCT_FUNC))
3080 {
3081 *rgdispid= DISPID_GET_STRUCT_FUNC;
3082 return S_OK;
3083 }
3084
3085 if (m_xInvocation.is() && (cNames > 0))
3086 {
3087 OUString name(o3tl::toU(rgszNames[0]));
3088 // has this name been determined as "bad"
3089 BadNameMap::iterator badIter= m_badNameMap.find( name);
3090 if( badIter == m_badNameMap.end() )
3091 {
3092 // name has not been bad before( member exists
3093 typedef NameToIdMap::iterator ITnames;
3094 std::pair< ITnames, bool > pair_id= m_nameToDispIdMap.emplace(name, m_currentId++);
3095 // new ID inserted ?
3096 if( pair_id.second )
3097 {// yes, now create MemberInfo and ad to IdToMemberInfoMap
3098 MemberInfo d(0, name);
3099 m_idToMemberInfoMap.emplace(m_currentId - 1, d);
3100 }
3101
3102 *rgdispid = pair_id.first->second;
3103 ret = S_OK;
3104 }
3105 else
3106 ret= DISP_E_UNKNOWNNAME;
3107 }
3108 return ret;
3109}
3110
3111COM_DECLSPEC_NOTHROW STDMETHODIMP UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember, REFIID /*riid*/, LCID /*lcid*/, WORD wFlags,
3112 DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
3113 UINT * puArgErr )
3114{
3116
3117 HRESULT ret = S_OK;
3118 try
3119 {
3120 bool bHandled= false;
3121 ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo,
3122 puArgErr, bHandled);
3123 if( bHandled)
3124 return ret;
3125
3126 if ( dispidMember > 0 && m_xInvocation.is())
3127 {
3128
3129 IdToMemberInfoMap::iterator it_MemberInfo= m_idToMemberInfoMap.find( dispidMember);
3130 if( it_MemberInfo != m_idToMemberInfoMap.end() )
3131 {
3132 MemberInfo& info= it_MemberInfo->second;
3133
3134 Sequence<Any> params; // holds converted any s
3135 if( ! info.flags )
3136 { // DISPID called for the first time
3137 if( wFlags == DISPATCH_METHOD )
3138 {
3139 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
3140
3141 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
3142 pexcepinfo, puArgErr, info.name, params))
3143 && ret == DISP_E_MEMBERNOTFOUND)
3144 {
3145 // try to get the exact name
3146 OUString exactName;
3147 if (m_xExactName.is())
3148 {
3149 exactName = m_xExactName->getExactName( info.name);
3150 // invoke again
3151 if( !exactName.isEmpty() )
3152 {
3153 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
3154 pexcepinfo, puArgErr, exactName, params)))
3155 info.name= exactName;
3156 }
3157 }
3158 }
3159 if( SUCCEEDED( ret ) )
3160 info.flags= DISPATCH_METHOD;
3161 }
3162 else if( wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_PROPERTYPUTREF)
3163 {
3164 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
3165 if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
3166 pexcepinfo, puArgErr, info.name, params))
3167 && ret == DISP_E_MEMBERNOTFOUND)
3168 {
3169 // try to get the exact name
3170 OUString exactName;
3171 if (m_xExactName.is())
3172 {
3173 exactName = m_xExactName->getExactName( info.name);
3174 // invoke again
3175 if( !exactName.isEmpty() )
3176 {
3177 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
3178 pexcepinfo, puArgErr, exactName, params)))
3179 info.name= exactName;
3180 }
3181 }
3182 }
3183 if( SUCCEEDED( ret ) )
3184 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
3185 }
3186 else if( wFlags == DISPATCH_PROPERTYGET)
3187 {
3188 if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
3189 pexcepinfo, info.name))
3190 && ret == DISP_E_MEMBERNOTFOUND)
3191 {
3192 // try to get the exact name
3193 OUString exactName;
3194 if (m_xExactName.is())
3195 {
3196 exactName = m_xExactName->getExactName( info.name);
3197 // invoke again
3198 if( !exactName.isEmpty() )
3199 {
3200 if( SUCCEEDED( ret= doGetProperty( pdispparams, pvarResult,
3201 pexcepinfo, exactName)))
3202 info.name= exactName;
3203 }
3204 }
3205 }
3206 if( SUCCEEDED( ret ) )
3207 info.flags= DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT;
3208 }
3209 else if( wFlags & DISPATCH_METHOD &&
3210 (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF))
3211 {
3212
3213 OUString exactName;
3214 // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT
3215 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
3216 // try first as method
3217 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
3218 pexcepinfo, puArgErr, info.name, params))
3219 && ret == DISP_E_MEMBERNOTFOUND)
3220 {
3221 // try to get the exact name
3222 if (m_xExactName.is())
3223 {
3224 exactName = m_xExactName->getExactName( info.name);
3225 // invoke again
3226 if( !exactName.isEmpty() )
3227 {
3228 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
3229 pexcepinfo, puArgErr, exactName, params)))
3230 info.name= exactName;
3231 }
3232 }
3233 }
3234 if( SUCCEEDED( ret ) )
3235 info.flags= DISPATCH_METHOD;
3236
3237 // try as property
3238 if( FAILED( ret) && pdispparams->cArgs == 1)
3239 {
3240 if( FAILED( ret= doSetProperty( pdispparams, pvarResult,
3241 pexcepinfo, puArgErr, info.name, params))
3242 && ret == DISP_E_MEMBERNOTFOUND)
3243 {
3244 // try to get the exact name
3245 if( !exactName.isEmpty() )
3246 {
3247 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
3248 pexcepinfo, puArgErr, exactName, params)))
3249 info.name= exactName;
3250 }
3251 }
3252 if( SUCCEEDED( ret ) )
3253 info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET;
3254 }
3255 }
3256 else if( wFlags & DISPATCH_METHOD && wFlags & DISPATCH_PROPERTYGET)
3257 {
3258 OUString exactName;
3259 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
3260
3261 if( FAILED( ret= doInvoke( pdispparams, pvarResult,
3262 pexcepinfo, puArgErr, info.name, params))
3263 && ret == DISP_E_MEMBERNOTFOUND)
3264 {
3265 // try to get the exact name
3266 if (m_xExactName.is())
3267 {
3268 exactName = m_xExactName->getExactName( info.name);
3269 // invoke again
3270 if( !exactName.isEmpty() )
3271 {
3272 if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult,
3273 pexcepinfo, puArgErr, exactName, params)))
3274 info.name= exactName;
3275 }
3276 }
3277 }
3278 if( SUCCEEDED( ret ) )
3279 info.flags= DISPATCH_METHOD;
3280
3281 // try as property
3282 if( FAILED( ret) && pdispparams->cArgs == 1)
3283 {
3284 if( FAILED( ret= doGetProperty( pdispparams, pvarResult,
3285 pexcepinfo, info.name))
3286 && ret == DISP_E_MEMBERNOTFOUND)
3287 {
3288 if( !exactName.isEmpty() )
3289 {
3290 if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult,
3291 pexcepinfo, puArgErr, exactName, params)))
3292 info.name= exactName;
3293 }
3294 }
3295 if( SUCCEEDED( ret ) )
3296 info.flags= DISPATCH_PROPERTYGET;
3297 }
3298 }
3299
3300 // update information about this member
3301 if( ret == DISP_E_MEMBERNOTFOUND)
3302 {
3303 // Remember the name as not existing
3304 // and remove the MemberInfo
3305 m_badNameMap[info.name]= false;
3306 m_idToMemberInfoMap.erase( it_MemberInfo);
3307 }
3308 } // if( ! info.flags )
3309 else // IdToMemberInfoMap contains a MemberInfo
3310 {
3311 if( wFlags & DISPATCH_METHOD && info.flags == DISPATCH_METHOD)
3312 {
3313 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
3314 ret= doInvoke( pdispparams, pvarResult,
3315 pexcepinfo, puArgErr, info.name, params);
3316 }
3317 else if( (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF ) &&
3318 info.flags & DISPATCH_PROPERTYPUT)
3319 {
3320 convertDispparamsArgs(dispidMember, wFlags, pdispparams, params );
3321 ret= doSetProperty( pdispparams, pvarResult,
3322 pexcepinfo, puArgErr, info.name, params);
3323 }
3324 else if( (wFlags & DISPATCH_PROPERTYGET) && ( info.flags & DISPATCH_PROPERTYGET))
3325 {
3326 ret= doGetProperty( pdispparams, pvarResult,
3327 pexcepinfo, info.name);
3328 }
3329 else
3330 {
3331 ret= DISP_E_MEMBERNOTFOUND;
3332 }
3333 }
3334 }// if( it_MemberInfo != m_idToMemberInfoMap.end() )
3335 else
3336 ret= DISP_E_MEMBERNOTFOUND;
3337 }
3338 }
3339 catch(const BridgeRuntimeError& e)
3340 {
3341 writeExcepinfo(pexcepinfo, e.message);
3342 ret = DISP_E_EXCEPTION;
3343 }
3344 catch(const Exception& e)
3345 {
3346 OUString message= "UnoObjectWrapperRemoteOpt::Invoke : \n" +
3347 e.Message;
3348 writeExcepinfo(pexcepinfo, message);
3349 ret = DISP_E_EXCEPTION;
3350 }
3351 catch(...)
3352 {
3353 writeExcepinfo(pexcepinfo, "UnoObjectWrapperRemoteOpt::Invoke : \nUnexpected exception");
3354 ret = DISP_E_EXCEPTION;
3355 }
3356
3357 return ret;
3358}
3359
3360HRESULT UnoObjectWrapperRemoteOpt::methodInvoke( DISPID /*dispidMember*/, DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/,
3361 EXCEPINFO * /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence<Any> const &)
3362{
3363 return S_OK;
3364}
3365
3366// The returned HRESULT is only appropriate for IDispatch::Invoke
3367static HRESULT mapCannotConvertException(const CannotConvertException &e, unsigned int * puArgErr)
3368{
3369 HRESULT ret;
3370 bool bWriteIndex= true;
3371
3372 switch ( e.Reason)
3373 {
3374 case FailReason::OUT_OF_RANGE:
3375 ret = DISP_E_OVERFLOW;
3376 break;
3377 case FailReason::IS_NOT_NUMBER:
3378 ret = DISP_E_TYPEMISMATCH;
3379 break;
3380 case FailReason::IS_NOT_ENUM:
3381 ret = DISP_E_TYPEMISMATCH;
3382 break;
3383 case FailReason::IS_NOT_BOOL:
3384 ret = DISP_E_TYPEMISMATCH;
3385 break;
3386 case FailReason::NO_SUCH_INTERFACE:
3387 ret = DISP_E_TYPEMISMATCH;
3388 break;
3389 case FailReason::SOURCE_IS_NO_DERIVED_TYPE:
3390 ret = DISP_E_TYPEMISMATCH;
3391 break;
3392 case FailReason::TYPE_NOT_SUPPORTED:
3393 ret = DISP_E_TYPEMISMATCH;
3394 break;
3395 case FailReason::INVALID:
3396 ret = DISP_E_TYPEMISMATCH;
3397 break;
3398 case FailReason::NO_DEFAULT_AVAILABLE:
3399 ret = DISP_E_BADPARAMCOUNT;
3400 break;
3401 case FailReason::UNKNOWN:
3402 ret = E_UNEXPECTED;
3403 break;
3404 default:
3405 ret = E_UNEXPECTED;
3406 bWriteIndex= false;
3407 break;
3408 }
3409
3410 if( bWriteIndex && puArgErr != nullptr)
3411 *puArgErr = e.ArgumentIndex;
3412 return ret;
3413}
3414
3415// The function maps the TypeClass of the any to VARTYPE: If
3416// the Any contains STRUCT or INTERFACE then the return value
3417// is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper
3418// and the result is put into the constructor of the uno - wrapper
3419// object. If a client asks the object for DISPID_VALUE and this
3420// function returned VT_DISPATCH then the IDispatch of the same
3421// object is being returned.
3422// See InterfaceOleWrapper::Invoke, InterfaceOleWrapper::m_defaultValueType
3423VARTYPE getVarType( const Any& value)
3424{
3425 VARTYPE ret= VT_EMPTY;
3426
3427 switch ( value.getValueTypeClass())
3428 {
3429 case TypeClass_STRUCT: ret= VT_DISPATCH; break;
3430 case TypeClass_INTERFACE: ret= VT_DISPATCH; break;
3431 default: break;
3432 }
3433 return ret;
3434}
3435
3436/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const Any & any
constexpr OUStringLiteral sImplementationName
double d
OUString message
Definition: ole2uno.hxx:65
NameToIdMap m_nameToDispIdMap
Definition: unoobjw.hxx:197
virtual HRESULT doSetProperty(DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, unsigned int *puArgErr, OUString &name, Sequence< Any > const &params)
Definition: unoobjw.cxx:2102
virtual HRESULT STDMETHODCALLTYPE FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP) override
Definition: unoobjw.cxx:2995
virtual Reference< XInterface > createComWrapperInstance() override
Definition: unoobjw.cxx:1548
InterfaceOleWrapper(Reference< XMultiServiceFactory > const &xFactory, sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass)
Definition: unoobjw.cxx:126
STDMETHOD() QueryInterface(REFIID riid, void **ppvObj) override
Definition: unoobjw.cxx:142
virtual Any SAL_CALL createBridge(const Any &modelDepObject, const Sequence< sal_Int8 > &ProcessId, sal_Int16 sourceModelType, sal_Int16 destModelType) override
Definition: unoobjw.cxx:1484
virtual Reference< XInterface > createUnoWrapperInstance() override
Definition: unoobjw.cxx:1541
STDMETHOD() GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid) override
Definition: unoobjw.cxx:1077
virtual HRESULT InvokeGeneral(DISPID dispidMember, unsigned short wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, unsigned int *puArgErr, bool &bHandled)
Definition: unoobjw.cxx:2735
virtual HRESULT STDMETHODCALLTYPE DeleteMemberByDispID(DISPID id) override
Definition: unoobjw.cxx:2916
virtual HRESULT doGetProperty(DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, OUString &name)
Definition: unoobjw.cxx:2066
const OUString & getImplementationName() const
Definition: unoobjw.hxx:170
STDMETHOD() getWrapperXInterface(Reference< XInterface > *pXInt) override
Definition: unoobjw.cxx:210
void convertDispparamsArgs(DISPID id, unsigned short wFlags, DISPPARAMS *pdispparams, Sequence< Any > &rSeq)
Definition: unoobjw.cxx:1278
STDMETHOD() getOriginalUnoStruct(Any *pStruct) override
Definition: unoobjw.cxx:220
virtual HRESULT STDMETHODCALLTYPE GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD __RPC_FAR *pgrfdex) override
Definition: unoobjw.cxx:2921
STDMETHOD() GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo) override
Definition: unoobjw.cxx:1035
OUString m_sImplementationName
Definition: unoobjw.hxx:210
virtual HRESULT STDMETHODCALLTYPE GetNextDispID(DWORD grfdex, DISPID id, DISPID __RPC_FAR *pid) override
Definition: unoobjw.cxx:2936
virtual HRESULT STDMETHODCALLTYPE GetMemberName(DISPID id, BSTR __RPC_FAR *pbstrName) override
Definition: unoobjw.cxx:2929
virtual HRESULT doInvoke(DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, unsigned int *puArgErr, OUString &name, Sequence< Any > &params)
Definition: unoobjw.cxx:1976
virtual HRESULT STDMETHODCALLTYPE GetDispID(BSTR bstrName, DWORD grfdex, DISPID __RPC_FAR *pid) override
Definition: unoobjw.cxx:2892
STDMETHOD() getOriginalUnoObject(Reference< XInterface > *pXInt) override
Definition: unoobjw.cxx:215
STDMETHOD() Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr) override
Definition: unoobjw.cxx:1800
Reference< XInterface > m_xOrigin
Definition: unoobjw.hxx:196
STDMETHOD() GetTypeInfoCount(UINT *pctinfo) override
Definition: unoobjw.cxx:241
~InterfaceOleWrapper() override
Definition: unoobjw.cxx:133
virtual HRESULT STDMETHODCALLTYPE EnumConnectionPoints(IEnumConnectionPoints **ppEnum) override
Definition: unoobjw.cxx:2988
Reference< XInvocation > m_xInvocation
Definition: unoobjw.hxx:194
virtual HRESULT STDMETHODCALLTYPE GetNameSpaceParent(IUnknown __RPC_FAR *__RPC_FAR *ppunk) override
Definition: unoobjw.cxx:2944
bool getInvocationInfoForCall(DISPID id, InvocationInfo &info)
Definition: unoobjw.cxx:1428
std::vector< MemberInfo > m_MemberInfos
Definition: unoobjw.hxx:198
VARTYPE m_defaultValueType
Definition: unoobjw.hxx:207
virtual HRESULT STDMETHODCALLTYPE InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS __RPC_FAR *pdp, VARIANT __RPC_FAR *pvarRes, EXCEPINFO __RPC_FAR *pei, IServiceProvider __RPC_FAR *pspCaller) override
Definition: unoobjw.cxx:2897
virtual HRESULT STDMETHODCALLTYPE GetClassInfo(ITypeInfo **ppTI) override
Definition: unoobjw.cxx:2951
virtual void SAL_CALL initialize(const Sequence< Any > &aArguments) override
Definition: unoobjw.cxx:1516
virtual HRESULT STDMETHODCALLTYPE DeleteMemberByName(BSTR bstr, DWORD grfdex) override
Definition: unoobjw.cxx:2909
Reference< XExactName > m_xExactName
Definition: unoobjw.hxx:195
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...
bool convertValueObject(const VARIANTARG *var, Any &any)
void variantToAny(const VARIANT *pVariant, Any &rAny, bool bReduceValueRange=true)
UnoObjectWrapperRemoteOpt(Reference< XMultiServiceFactory > const &aFactory, sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass)
Definition: unoobjw.cxx:3045
IdToMemberInfoMap m_idToMemberInfoMap
Definition: unoobjw.hxx:261
STDMETHOD() Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr) override
Definition: unoobjw.cxx:3111
static HRESULT methodInvoke(DISPID dispidMember, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, unsigned int *puArgErr, Sequence< Any > const &params)
Definition: unoobjw.cxx:3360
~UnoObjectWrapperRemoteOpt() override
Definition: unoobjw.cxx:3052
virtual Reference< XInterface > createUnoWrapperInstance() override
Definition: unoobjw.cxx:3057
STDMETHOD() GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid) override
Definition: unoobjw.cxx:3064
IJScriptValueObject VARIANT value
Definition: comifaces.hxx:28
void Init()
ULONG m_refCount
std::deque< AttacherIndex_Impl > aIndex
Reference< XSingleServiceFactory > xFactory
const char * name
Sequence< PropertyValue > aArguments
OUString aName
sal_Int64 n
tools::SvRef< SvBaseLink > xSink
unsigned short WORD
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
std::unique_ptr< sal_Int32[]> pData
struct _typelib_TypeDescription typelib_TypeDescription
@ Exception
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
Type
int i
index
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
Call
css::uno::Reference< css::animations::XAnimationNode > Clone(const css::uno::Reference< css::animations::XAnimationNode > &xSourceNode, const SdPage *pSource=nullptr, const SdPage *pTarget=nullptr)
NBOTypeMgrBase * CreateInstance(const NBOType aType)
Mutex * getBridgeMutex()
Definition: ole2uno.cxx:40
#define UNO_2_OLE_EXCEPTIONCODE
Definition: ole2uno.hxx:41
#define VT_UINT
#define VT_UI2
#define VT_ARRAY
#define VT_DATE
#define VT_EMPTY
#define VT_R4
#define VT_UI4
#define VT_BSTR
#define VT_R8
#define VT_VARIANT
#define VT_INT
#define VT_ERROR
#define VT_DECIMAL
#define VT_BYREF
#define VT_BOOL
#define VT_I1
#define VT_CY
#define VT_I4
#define VT_UI1
#define VT_I2
const wchar_t *typedef BOOL
LONG
return hr
Definition: so_activex.cxx:446
constexpr Method aMethods[]
OUString name
Definition: unoobjw.hxx:53
WORD flags
Definition: unoobjw.hxx:52
sal_uInt32 mnIndex
OUString maType
void SAL_CALL typelib_typedescription_release(typelib_TypeDescription *pTD) SAL_THROW_EXTERN_C()
void SAL_CALL typelib_typedescription_getByName(typelib_TypeDescription **ppRet, rtl_uString *pName) SAL_THROW_EXTERN_C()
unsigned char sal_uInt8
ResultType type
VARTYPE getVarType(const Any &value)
Definition: unoobjw.cxx:3423
bool getType(const BSTR name, Type &type)
Definition: unoobjw.cxx:1557
COM_DECLSPEC_NOTHROW STDMETHODIMP_(ULONG) InterfaceOleWrapper
Definition: unoobjw.cxx:194
static HRESULT mapCannotConvertException(const CannotConvertException &e, unsigned int *puArgErr)
Definition: unoobjw.cxx:3367
static bool writeBackOutParameter(VARIANTARG *pDest, VARIANT *pSource)
Definition: unoobjw.cxx:1642
static bool writeBackOutParameter2(VARIANTARG *pDest, VARIANT *pSource)
Definition: unoobjw.cxx:1572
std::unordered_map< sal_uIntPtr, WeakReference< XInterface > > UnoObjToWrapperMap
Definition: unoobjw.cxx:108
static void writeExcepinfo(EXCEPINFO *pInfo, const OUString &message)
Definition: unoobjw.cxx:116
#define JSCRIPT_VALUE_FUNC
Definition: unoobjw.hxx:33
#define DISPID_GET_STRUCT_FUNC
Definition: unoobjw.hxx:40
#define BRIDGE_CREATE_TYPE_FUNC
Definition: unoobjw.hxx:37
#define GET_STRUCT_FUNC
Definition: unoobjw.hxx:34
#define DISPID_CREATE_TYPE_FUNC
Definition: unoobjw.hxx:41
#define BRIDGE_GET_STRUCT_FUNC
Definition: unoobjw.hxx:36
#define DISPID_JSCRIPT_VALUE_FUNC
Definition: unoobjw.hxx:39
#define BRIDGE_VALUE_FUNC
Definition: unoobjw.hxx:35
bool createUnoTypeWrapper(BSTR sTypeName, VARIANT *pVar)