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