1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include "ole2uno.hxx"
23 #include "wincrap.hxx"
25 #include <string_view>
26 #include <unordered_map>
29 #include <cppuhelper/implbase.hxx>
31 #include <com/sun/star/lang/XInitialization.hpp>
32 #include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp>
33 #include <com/sun/star/script/XAutomationInvocation.hpp>
34 #include <rtl/ustring.hxx>
36 #include <com/sun/star/script/XDefaultProperty.hpp>
37 #include <com/sun/star/script/XDefaultMethod.hpp>
38 #include <com/sun/star/script/XDirectInvocation.hpp>
40 #include <typelib/typedescription.hxx>
41 #include "unoconversionutilities.hxx"
42 #include "windata.hxx"
44 using namespace com::sun::star::lang
;
45 using namespace com::sun::star::bridge
;
46 using namespace com::sun::star::bridge::oleautomation
;
48 typedef std::unordered_map
<OUString
, std::pair
<DISPID
, unsigned short>> DispIdMap
;
50 typedef std::unordered_multimap
<OUString
, unsigned int> TLBFuncIndexMap
;
52 // This class wraps an IDispatch and maps XInvocation calls to IDispatch calls on the wrapped object.
53 // If m_TypeDescription is set then this class represents a UNO interface implemented in a COM component.
54 // The interface is not a real interface in terms of an abstract class but is realized through IDispatch.
55 class IUnknownWrapper
: public WeakImplHelper
< XBridgeSupplier2
, XInitialization
, XAutomationObject
, XDefaultProperty
, XDefaultMethod
, XDirectInvocation
, XAutomationInvocation
>,
57 public UnoConversionUtilities
<IUnknownWrapper
>
61 IUnknownWrapper(Reference
<XMultiServiceFactory
> const &xFactory
,
62 sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
);
64 ~IUnknownWrapper() override
;
67 Any SAL_CALL
queryInterface(const Type
& t
) override
;
70 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection( ) override
;
71 virtual Any SAL_CALL
invoke( const OUString
& aFunctionName
,
72 const Sequence
< Any
>& aParams
,
73 Sequence
< sal_Int16
>& aOutParamIndex
,
74 Sequence
< Any
>& aOutParam
) override
;
75 virtual void SAL_CALL
setValue( const OUString
& aPropertyName
,
76 const Any
& aValue
) override
;
77 virtual Any SAL_CALL
getValue( const OUString
& aPropertyName
) override
;
78 virtual sal_Bool SAL_CALL
hasMethod( const OUString
& aName
) override
;
79 virtual sal_Bool SAL_CALL
hasProperty( const OUString
& aName
) override
;
82 // This interface is implemented to provide a safe way to obtain the original
83 // IUnknown or IDispatch within the function anyToVariant. The function asks
84 // every UNO object for its XBridgeSupplier2 and if it is available uses it to convert
85 // the object with its own supplier.
86 virtual Any SAL_CALL
createBridge( const Any
& modelDepObject
,
87 const Sequence
< sal_Int8
>& aProcessId
,
88 sal_Int16 sourceModelType
,
89 sal_Int16 destModelType
) override
;
92 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) override
;
95 virtual OUString SAL_CALL
getDefaultPropertyName( ) override
{ return m_sDefaultMember
; }
98 virtual OUString SAL_CALL
getDefaultMethodName( ) override
{ return m_sDefaultMember
; }
100 virtual css::uno::Any SAL_CALL
invokeGetProperty( const OUString
& aFunctionName
, const css::uno::Sequence
< css::uno::Any
>& aParams
, css::uno::Sequence
< ::sal_Int16
>& aOutParamIndex
, css::uno::Sequence
< css::uno::Any
>& aOutParam
) override
;
101 virtual css::uno::Any SAL_CALL
invokePutProperty( const OUString
& aFunctionName
, const css::uno::Sequence
< css::uno::Any
>& aParams
, css::uno::Sequence
< ::sal_Int16
>& aOutParamIndex
, css::uno::Sequence
< css::uno::Any
>& aOutParam
) override
;
104 virtual css::uno::Any SAL_CALL
directInvoke( const OUString
& aName
, const css::uno::Sequence
< css::uno::Any
>& aParams
) override
;
105 virtual sal_Bool SAL_CALL
hasMember( const OUString
& aName
) override
;
108 Any
invokeWithDispIdComTlb(FuncDesc
& aFuncDesc
,
109 const OUString
& sFuncName
,
110 const Sequence
< Any
>& Params
,
111 Sequence
< sal_Int16
>& OutParamIndex
,
112 Sequence
< Any
>& OutParam
);
117 virtual Any
invokeWithDispIdUnoTlb(const OUString
& sFunctionName
,
118 const Sequence
< Any
>& Params
,
119 Sequence
<sal_Int16
>& OutParamIndex
,
120 Sequence
< Any
>& OutParam
);
121 // Is used for OleObjectFactory service
122 virtual Any
invokeWithDispIdComTlb(const OUString
& sFuncName
,
123 const Sequence
< Any
>& Params
,
124 Sequence
< sal_Int16
>& OutParamIndex
,
125 Sequence
< Any
>& OutParam
);
127 // UnoConversionUtilities -------------------------------------------------------------------------------
128 virtual Reference
<XInterface
> createUnoWrapperInstance() override
;
129 virtual Reference
<XInterface
> createComWrapperInstance() override
;
131 /**Obtains a FUNCDESC structure for a function.
132 Fills the FUNCDESC structure if ITypeInfo provides information for
133 the function of name sFuncName or pFuncDesc will not be filled in.
134 May throw a BridgeRuntimeError.
136 void getFuncDesc(const OUString
& sFuncName
, FUNCDESC
** pFuncDesc
);
137 /**Obtains a FUNCDESC structures or a VARDESC structure
138 for a property. pFuncDescPut may also contain
139 a structure for a "propertyputref" operation. If pFuncDesc contains a
140 "put ref" or "put" FUNCDESC depends on what was found first in the type
142 Fills the FUNCDESC structure if ITypeInfo provides information for
143 the respective property functions or the structures will not be filled in.
144 May throw a BridgeRuntimeError.
146 void getPropDesc(const OUString
& sFuncName
, FUNCDESC
** pFuncDescGet
,
147 FUNCDESC
** pFuncDescPut
, VARDESC
** pVarDesc
);
148 // These functions are for the case if an object of this class wraps an IDispatch
149 // object that implements UNO interfaces. In that case the member m_seqTypes
150 // is set through XInitialization::initialize.
151 void getMethodInfo(std::u16string_view sName
, TypeDescription
& methodDescription
);
152 // After return attributInfo contains typelib_InterfaceAttributeTypeDescription::pAttributeTypeRef
153 void getAttributeInfo(std::u16string_view sName
, TypeDescription
& attributeInfo
);
154 // used by get MethodInfo
155 TypeDescription
getInterfaceMemberDescOfCurrentCall(std::u16string_view sName
);
156 /** Returns always a valid ITypeInfo interface or throws a BridgeRuntimeError.
157 The returned interface does not need to be AddRef'ed as long as it is locally
158 used. The interface is kept in the instance of this class.
160 ITypeInfo
* getTypeInfo();
162 /** Returns the DISPID for a function or property name. If true is returned then
163 id contains a valid DISPID.
166 bool getDispid(const OUString
& sFuncName
, DISPID
* id
);
168 VARTYPE
getUserDefinedElementType( ITypeInfo
* pTypeInfo
, const DWORD nHrefType
);
170 /** Gets the element type in a VARIANT like style. E.g. if desc->lptdesc contains
171 a VT_PTR than it is replaced by VT_BYREF and VT_SAFEARRAY is replaced by VT_ARRAY
172 If the TYPEDESC describes an SAFEARRAY then varType is a combination of VT_ARRAY
173 and the element type.
174 The argument desc must be obtained from FUNCDESC::lprgelemdescParam[i].tdesc where
175 FUNCDESC was obtained from the ITypeInfo belonging to wrapped IDispatch.
177 VARTYPE
getElementTypeDesc( const TYPEDESC
*desc
);
178 /** Iterates over all functions and put the names and indices into the map
179 m_mapComFunc of type TLBFuncIndexMap.
180 Call the function every time before accessing the map.
181 Throws a BridgeRuntimeError on failure.
183 void buildComTlbIndex();
185 /** Returns a FUNCDESC structure which contains type information about the
186 current XInvocation::invoke call. The FUNCDESC either describes a method,
187 a property put or a property get operation.
188 It uses the types com.sun.star.bridge.oleautomation.PropertyPutArgument
190 contained in the sequence of in-arguments of invoke to determine if the call is
191 a property put or property get operation.
192 If no adequate FUNCDESC was found, an IllegalArgumentException is thrown.
193 Therefore it is safe to assume that the returned FUNCDESC* is not NULL.
195 @exception IllegalArgumentException
196 Thrown if no adequate FUNCDESC could be found.
198 void getFuncDescForInvoke(const OUString
& sFuncName
,
199 const Sequence
<Any
> & seqArgs
, FUNCDESC
** pFuncDesc
);
201 // Finds out whether the wrapped IDispatch is a JScript Object. This is
203 // asking for the property "_environment". If it has the value "JScript"
204 // (case insensitive) then the IDispatch is considered a JScript object.
205 bool isJScriptObject();
208 // If UNO interfaces are implemented in JScript objects, VB or C++ COM objects
209 // and those are passed as parameter to a UNO interface function, then
210 // the IDispatch* are wrapped by objects of this class. Assuming that the functions
211 // implemented by the IDispatch object returns another UNO interface then
212 // it has to be wrapped to this type. But this is only possible if an object of this
213 // wrapper class knows what type it is representing. The member m_TypeDescription holds this
215 // m_TypeDescription is only useful when an object wraps an IDispatch object that implements
216 // a UNO interface. The value is set during a call to XInitialization::initialize.
217 Sequence
<Type
> m_seqTypes
;
218 CComPtr
<IUnknown
> m_spUnknown
;
219 CComPtr
<IDispatch
> m_spDispatch
;
220 OUString m_sTypeName
; // is "" ( not initialised ), "IDispatch" ( we have no idea ) or "SomeLibrary.SomeTypeName" if we managed to get a type
221 /** This value is set during XInitialization::initialize. It indicates that the COM interface
222 was transported as VT_DISPATCH in a VARIANT rather than a VT_UNKNOWN
224 bool m_bOriginalDispatch
;
225 DispIdMap m_dispIdMap
;
226 Reference
<XIdlClass
>* m_pxIdlClass
;
229 // used by isJScriptObject
230 enum JScriptDetermination
{ JScriptUndefined
=0, NoJScript
, IsJScript
};
231 JScriptDetermination m_eJScript
;
232 // The map is filled by buildComTlbIndex
233 // It maps Uno Function names to an index which is used in ITypeInfo::GetFuncDesc
234 TLBFuncIndexMap m_mapComFunc
;
235 // used for synchronizing the computation of the content for m_mapComFunc
236 bool m_bComTlbIndexInit
;
237 // Keeps the ITypeInfo obtained from IDispatch::GetTypeInfo
238 CComPtr
< ITypeInfo
> m_spTypeInfo
;
239 OUString m_sDefaultMember
;
240 bool m_bHasDfltMethod
;
241 bool m_bHasDfltProperty
;
244 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */