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