diff options
author | Michael Stahl <mstahl@redhat.com> | 2012-01-28 20:52:45 +0100 |
---|---|---|
committer | Michael Stahl <mstahl@redhat.com> | 2012-01-28 20:52:45 +0100 |
commit | 2e626373db2412ac22e8c5c27a60d11cd29e875b (patch) | |
tree | 9e9f67205cd5b72f1031721273e1534a3a1e5b0f /extensions/source/ole/oleobjw.cxx | |
parent | f7ee7bbd5174b084f018c2ec94d8c70c98ee04da (diff) |
replace obsolete "master" branch with README that points at new repoHEADmaster-deletedmaster
Diffstat (limited to 'extensions/source/ole/oleobjw.cxx')
-rw-r--r-- | extensions/source/ole/oleobjw.cxx | 2644 |
1 files changed, 0 insertions, 2644 deletions
diff --git a/extensions/source/ole/oleobjw.cxx b/extensions/source/ole/oleobjw.cxx deleted file mode 100644 index dbc37ffae..000000000 --- a/extensions/source/ole/oleobjw.cxx +++ /dev/null @@ -1,2644 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_extensions.hxx" -#include "ole2uno.hxx" -#include "rtl/ustrbuf.hxx" - - -#include "osl/diagnose.h" -#include "osl/doublecheckedlocking.h" -#include "osl/thread.h" - -#include "boost/scoped_array.hpp" -#include <com/sun/star/script/FailReason.hpp> -#include <com/sun/star/beans/XMaterialHolder.hpp> -#include <com/sun/star/script/XTypeConverter.hpp> -#include <com/sun/star/script/FinishEngineEvent.hpp> -#include <com/sun/star/script/InterruptReason.hpp> -#include <com/sun/star/script/XEngineListener.hpp> -#include <com/sun/star/script/XDebugging.hpp> -#include <com/sun/star/script/XInvocation.hpp> -#include <com/sun/star/script/ContextInformation.hpp> -#include <com/sun/star/script/FinishReason.hpp> -#include <com/sun/star/script/XEngine.hpp> -#include <com/sun/star/script/InterruptEngineEvent.hpp> -#include <com/sun/star/script/XLibraryAccess.hpp> -#include <com/sun/star/script/BasicErrorException.hpp> -#include <com/sun/star/bridge/ModelDependent.hpp> - -#include "com/sun/star/bridge/oleautomation/NamedArgument.hpp" -#include "com/sun/star/bridge/oleautomation/PropertyPutArgument.hpp" - -#include <typelib/typedescription.hxx> -#include <rtl/uuid.h> -#include <rtl/memory.h> -#include <rtl/ustring.hxx> - -#include "jscriptclasses.hxx" - -#include "oleobjw.hxx" -#include "unoobjw.hxx" -#include <stdio.h> -using namespace std; -using namespace boost; -using namespace osl; -using namespace cppu; -using namespace com::sun::star::script; -using namespace com::sun::star::lang; -using namespace com::sun::star::bridge; -using namespace com::sun::star::bridge::oleautomation; -using namespace com::sun::star::bridge::ModelDependent; -using namespace ::com::sun::star; - -using ::rtl::OUString; -using ::rtl::OString; -using ::rtl::OUStringBuffer; - -#define JSCRIPT_ID_PROPERTY L"_environment" -#define JSCRIPT_ID L"jscript" -namespace ole_adapter -{ - - -// key: XInterface pointer created by Invocation Adapter Factory -// value: XInterface pointer to the wrapper class. -// Entries to the map are made within -// Any createOleObjectWrapper(IUnknown* pUnknown, const Type& aType); -// Entries are being deleted if the wrapper class's destructor has been -// called. -// Before UNO object is wrapped to COM object this map is checked -// to see if the UNO object is already a wrapper. -boost::unordered_map<sal_uInt32, sal_uInt32> AdapterToWrapperMap; -// key: XInterface of the wrapper object. -// value: XInterface of the Interface created by the Invocation Adapter Factory. -// A COM wrapper is responsible for removing the corresponding entry -// in AdapterToWrappperMap if it is being destroyed. Because the wrapper does not -// know about its adapted interface it uses WrapperToAdapterMap to get the -// adapted interface which is then used to locate the entry in AdapterToWrapperMap. -boost::unordered_map<sal_uInt32,sal_uInt32> WrapperToAdapterMap; - -boost::unordered_map<sal_uInt32, WeakReference<XInterface> > ComPtrToWrapperMap; -/***************************************************************************** - - class implementation IUnknownWrapper_Impl - -*****************************************************************************/ - -IUnknownWrapper_Impl::IUnknownWrapper_Impl( Reference<XMultiServiceFactory>& xFactory, - sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass): - UnoConversionUtilities<IUnknownWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass), - m_pxIdlClass( NULL), m_eJScript( JScriptUndefined), - m_bComTlbIndexInit(false), m_bHasDfltMethod(false), m_bHasDfltProperty(false) -{ -} - - -IUnknownWrapper_Impl::~IUnknownWrapper_Impl() -{ - o2u_attachCurrentThread(); - MutexGuard guard(getBridgeMutex()); - XInterface * xIntRoot = (OWeakObject *)this; -#if OSL_DEBUG_LEVEL > 0 - acquire(); // make sure we don't delete us twice because of Reference - OSL_ASSERT( Reference<XInterface>( static_cast<XWeak*>(this), UNO_QUERY).get() == xIntRoot ); -#endif - - // remove entries in global maps - typedef boost::unordered_map<sal_uInt32, sal_uInt32>::iterator _IT; - _IT it= WrapperToAdapterMap.find( (sal_uInt32) xIntRoot); - if( it != WrapperToAdapterMap.end()) - { - sal_uInt32 adapter= it->second; - - AdapterToWrapperMap.erase( adapter); - WrapperToAdapterMap.erase( it); - } - - IT_Com it_c= ComPtrToWrapperMap.find( (sal_uInt32) m_spUnknown.p); - if(it_c != ComPtrToWrapperMap.end()) - ComPtrToWrapperMap.erase(it_c); - -#if OSL_DEBUG_LEVEL > 0 - fprintf(stderr,"[automation bridge] ComPtrToWrapperMap contains: %i \n", - ComPtrToWrapperMap.size()); -#endif -} - -Any IUnknownWrapper_Impl::queryInterface(const Type& t) - throw (RuntimeException) -{ - if (t == getCppuType(static_cast<Reference<XDefaultMethod>*>( 0)) && !m_bHasDfltMethod ) - return Any(); - if (t == getCppuType(static_cast<Reference<XDefaultProperty>*>( 0)) && !m_bHasDfltProperty ) - return Any(); - if ( ( t == getCppuType(static_cast<Reference<XInvocation>*>( 0)) || t == getCppuType(static_cast<Reference<XAutomationInvocation>*>( 0)) ) && !m_spDispatch) - return Any(); - // XDirectInvocation seems to be an oracle replacement for XAutomationInvocation, however it is flawed esecially wrt. assumptions about whether to invoke a - // Put or Get property, the implementation code has no business guessing that, it's up to the caller to decide that. Worse XDirectInvocation duplicates lots of code. - // XAutomationInvocation provides seperate calls for put& get - // properties. Note: Currently the basic runtime doesn't call put properties directly, it should... after all the basic runtime should know whether it is calling a put or get property. - // For the moment for ease of merging we will let the XDirectInvoke and XAuthomationInvocation interfaces stay side by side ( and for the momemnt at least I would prefer the basic - // runtime to call XAutomationInvocation instead of XDirectInvoke - return WeakImplHelper8<XInvocation, XBridgeSupplier2, - XInitialization, XAutomationObject, XDefaultProperty, XDefaultMethod, XDirectInvocation, XAutomationInvocation >::queryInterface(t); -} - -Reference<XIntrospectionAccess> SAL_CALL IUnknownWrapper_Impl::getIntrospection(void) - throw (RuntimeException ) -{ - Reference<XIntrospectionAccess> ret; - - return ret; -} - -Any SAL_CALL IUnknownWrapper_Impl::invokeGetProperty( const OUString& aPropertyName, const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) -{ - Any aResult; - try - { - o2u_attachCurrentThread(); - ITypeInfo * pInfo = getTypeInfo(); - FuncDesc aDescGet(pInfo); - FuncDesc aDescPut(pInfo); - VarDesc aVarDesc(pInfo); - getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc); - if ( !aDescGet ) - { - OUString msg(OUSTR("[automation bridge]Property \"") + aPropertyName + - OUSTR("\" is not supported")); - throw UnknownPropertyException(msg, Reference<XInterface>()); - } - aResult = invokeWithDispIdComTlb( aDescGet, aPropertyName, aParams, aOutParamIndex, aOutParam ); - } - catch ( Exception& e ) - { - throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::invokeGetProperty ! Message : \n") + - e.Message, Reference<XInterface>()); - } - return aResult; -} - -Any SAL_CALL IUnknownWrapper_Impl::invokePutProperty( const OUString& aPropertyName, const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) -{ - Any aResult; - try - { - o2u_attachCurrentThread(); - ITypeInfo * pInfo = getTypeInfo(); - FuncDesc aDescGet(pInfo); - FuncDesc aDescPut(pInfo); - VarDesc aVarDesc(pInfo); - getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc); - if ( !aDescPut ) - { - OUString msg(OUSTR("[automation bridge]Property \"") + aPropertyName + - OUSTR("\" is not supported")); - throw UnknownPropertyException(msg, Reference<XInterface>()); - } - aResult = invokeWithDispIdComTlb( aDescPut, aPropertyName, aParams, aOutParamIndex, aOutParam ); - } - catch ( Exception& e ) - { - throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::invokePutProperty ! Message : \n") + - e.Message, Reference<XInterface>()); - } - return aResult; -} - - -Any SAL_CALL IUnknownWrapper_Impl::invoke( const OUString& aFunctionName, - const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex, - Sequence< Any >& aOutParam ) - throw(IllegalArgumentException, CannotConvertException, InvocationTargetException, - RuntimeException) -{ - if ( ! m_spDispatch ) - { - throw RuntimeException( - OUSTR("[automation bridge] The object does not have an IDispatch interface"), - Reference<XInterface>()); - } - - Any ret; - - try - { - o2u_attachCurrentThread(); - - TypeDescription methodDesc; - getMethodInfo(aFunctionName, methodDesc); - if( methodDesc.is()) - { - ret = invokeWithDispIdUnoTlb(aFunctionName, - aParams, - aOutParamIndex, - aOutParam); - } - else - { - ret= invokeWithDispIdComTlb( aFunctionName, - aParams, - aOutParamIndex, - aOutParam); - } - } - catch (IllegalArgumentException &) - { - throw; - } - catch (CannotConvertException &) - { - throw; - } - catch (InvocationTargetException &) - { - throw; - } - catch (BridgeRuntimeError & e) - { - throw RuntimeException(e.message, Reference<XInterface>()); - } - catch (Exception & e) - { - throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::invoke ! Message : \n") + - e.Message, Reference<XInterface>()); - - } - catch(...) - { - throw RuntimeException( - OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::Invoke !"), Reference<XInterface>()); - } - return ret; -} - -void SAL_CALL IUnknownWrapper_Impl::setValue( const OUString& aPropertyName, - const Any& aValue ) - throw(UnknownPropertyException, CannotConvertException, InvocationTargetException, - RuntimeException) -{ - if ( ! m_spDispatch ) - { - throw RuntimeException( - OUSTR("[automation bridge] The object does not have an IDispatch interface"), - Reference<XInterface>()); - } - try - { - o2u_attachCurrentThread(); - - ITypeInfo * pInfo = getTypeInfo(); - FuncDesc aDescGet(pInfo); - FuncDesc aDescPut(pInfo); - VarDesc aVarDesc(pInfo); - getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc); - //check if there is such a property at all or if it is read only - if ( ! aDescPut && ! aDescGet && ! aVarDesc) - { - OUString msg(OUSTR("[automation bridge]Property \"") + aPropertyName + - OUSTR("\" is not supported")); - throw UnknownPropertyException(msg, Reference<XInterface>()); - } - - if ( (! aDescPut && aDescGet) || aVarDesc - && aVarDesc->wVarFlags == VARFLAG_FREADONLY ) - { - //read-only - OUString msg(OUSTR("[automation bridge] Property ") + aPropertyName + - OUSTR(" is read-only")); - OString sMsg = OUStringToOString(msg, osl_getThreadTextEncoding()); - OSL_FAIL(sMsg.getStr()); - // ignore silently - return; - } - - HRESULT hr= S_OK; - DISPPARAMS dispparams; - CComVariant varArg; - CComVariant varRefArg; - CComVariant varResult; - ExcepInfo excepinfo; - unsigned int uArgErr; - - // converting UNO value to OLE variant - DISPID dispidPut= DISPID_PROPERTYPUT; - dispparams.rgdispidNamedArgs = &dispidPut; - dispparams.cArgs = 1; - dispparams.cNamedArgs = 1; - dispparams.rgvarg = & varArg; - - OSL_ASSERT(aDescPut || aVarDesc); - - VARTYPE vt = 0; - DISPID dispid = 0; - INVOKEKIND invkind = INVOKE_PROPERTYPUT; - //determine the expected type, dispid, invoke kind (DISPATCH_PROPERTYPUT, - //DISPATCH_PROPERTYPUTREF) - if (aDescPut) - { - vt = getElementTypeDesc(& aDescPut->lprgelemdescParam[0].tdesc); - dispid = aDescPut->memid; - invkind = aDescPut->invkind; - } - else - { - vt = getElementTypeDesc( & aVarDesc->elemdescVar.tdesc); - dispid = aVarDesc->memid; - if (vt == VT_UNKNOWN || vt == VT_DISPATCH || - (vt & VT_ARRAY) || (vt & VT_BYREF)) - { - invkind = INVOKE_PROPERTYPUTREF; - } - } - - // convert the uno argument - if (vt & VT_BYREF) - { - anyToVariant( & varRefArg, aValue, ::sal::static_int_cast< VARTYPE, int >( vt ^ VT_BYREF ) ); - varArg.vt = vt; - if( (vt & VT_TYPEMASK) == VT_VARIANT) - varArg.byref = & varRefArg; - else if ((vt & VT_TYPEMASK) == VT_DECIMAL) - varArg.byref = & varRefArg.decVal; - else - varArg.byref = & varRefArg.byref; - } - else - { - anyToVariant(& varArg, aValue, vt); - } - // call to IDispatch - hr = m_spDispatch->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, ::sal::static_int_cast< WORD, INVOKEKIND >( invkind ), - &dispparams, & varResult, & excepinfo, &uArgErr); - - // lookup error code - switch (hr) - { - case S_OK: - break; - case DISP_E_BADPARAMCOUNT: - throw RuntimeException(); - break; - case DISP_E_BADVARTYPE: - throw RuntimeException(); - break; - case DISP_E_EXCEPTION: - throw InvocationTargetException(); - break; - case DISP_E_MEMBERNOTFOUND: - throw UnknownPropertyException(); - break; - case DISP_E_NONAMEDARGS: - throw RuntimeException(); - break; - case DISP_E_OVERFLOW: - throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( - static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr); - break; - case DISP_E_PARAMNOTFOUND: - throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( - static_cast<XWeak*>(this)), ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )) ; - break; - case DISP_E_TYPEMISMATCH: - throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( - static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::UNKNOWN, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); - break; - case DISP_E_UNKNOWNINTERFACE: - throw RuntimeException(); - break; - case DISP_E_UNKNOWNLCID: - throw RuntimeException(); - break; - case DISP_E_PARAMNOTOPTIONAL: - throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface*>( - static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr); - break; - default: - throw RuntimeException(); - break; - } - } - catch (CannotConvertException &) - { - throw; - } - catch (UnknownPropertyException &) - { - throw; - } - catch (BridgeRuntimeError& e) - { - throw RuntimeException( - e.message, Reference<XInterface>()); - } - catch (Exception & e) - { - throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::setValue ! Message : \n") + - e.Message, Reference<XInterface>()); - - } - catch (...) - { - throw RuntimeException( - OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::setValue !"), Reference<XInterface>()); - } -} - -Any SAL_CALL IUnknownWrapper_Impl::getValue( const OUString& aPropertyName ) - throw(UnknownPropertyException, RuntimeException) -{ - if ( ! m_spDispatch ) - { - throw RuntimeException( - OUSTR("[automation bridge] The object does not have an IDispatch interface"), - Reference<XInterface>()); - } - Any ret; - try - { - o2u_attachCurrentThread(); - ITypeInfo * pInfo = getTypeInfo(); - // I was going to implement an XServiceInfo interface to allow the type - // of the automation object to be exposed.. but it seems - // from looking at comments in the code that it is possible for - // this object to actually wrap an UNO object ( I guess if automation is - // used from MSO to create Openoffice objects ) Therefore, those objects - // will more than likely already have their own XServiceInfo interface. - // Instead here I chose a name that should be illegal both in COM and - // UNO ( from an IDL point of view ) therefore I think this is a safe - // hack - if ( aPropertyName.equals( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("$GetTypeName")) )) - { - if ( pInfo && m_sTypeName.getLength() == 0 ) - { - m_sTypeName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("IDispatch") ); - CComBSTR sName; - - if ( SUCCEEDED( pInfo->GetDocumentation( -1, &sName, NULL, NULL, NULL ) ) ) - { - rtl::OUString sTmp( reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName))); - if ( sTmp.indexOf('_') == 0 ) - sTmp = sTmp.copy(1); - // do we own the memory for pTypeLib, msdn doco is vague - // I'll assume we do - CComPtr< ITypeLib > pTypeLib; - unsigned int index; - if ( SUCCEEDED( pInfo->GetContainingTypeLib( &pTypeLib.p, &index )) ) - { - if ( SUCCEEDED( pTypeLib->GetDocumentation( -1, &sName, NULL, NULL, NULL ) ) ) - { - rtl::OUString sLibName( reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName))); - m_sTypeName = sLibName.concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".") ) ).concat( sTmp ); - - } - } - } - - } - ret <<= m_sTypeName; - return ret; - } - FuncDesc aDescGet(pInfo); - FuncDesc aDescPut(pInfo); - VarDesc aVarDesc(pInfo); - getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc); - if ( ! aDescGet && ! aDescPut && ! aVarDesc) - { - //property not found - OUString msg(OUSTR("[automation bridge]Property \"") + aPropertyName + - OUSTR("\" is not supported")); - throw UnknownPropertyException(msg, Reference<XInterface>()); - } - // write-only should not be possible - OSL_ASSERT( aDescGet || ! aDescPut); - - HRESULT hr; - DISPPARAMS dispparams = {0, 0, 0, 0}; - CComVariant varResult; - ExcepInfo excepinfo; - unsigned int uArgErr; - DISPID dispid; - if (aDescGet) - dispid = aDescGet->memid; - else if (aVarDesc) - dispid = aVarDesc->memid; - else - dispid = aDescPut->memid; - - hr = m_spDispatch->Invoke(dispid, - IID_NULL, - LOCALE_USER_DEFAULT, - DISPATCH_PROPERTYGET, - &dispparams, - &varResult, - &excepinfo, - &uArgErr); - - // converting return value and out parameter back to UNO - if (hr == S_OK) - { - // If the com object implements uno interfaces then we have - // to convert the attribute into the expected type. - TypeDescription attrInfo; - getAttributeInfo(aPropertyName, attrInfo); - if( attrInfo.is() ) - variantToAny( &varResult, ret, Type( attrInfo.get()->pWeakRef)); - else - variantToAny(&varResult, ret); - } - - // lookup error code - switch (hr) - { - case S_OK: - break; - case DISP_E_BADPARAMCOUNT: - throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - case DISP_E_BADVARTYPE: - throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - case DISP_E_EXCEPTION: - throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - case DISP_E_MEMBERNOTFOUND: - throw UnknownPropertyException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - case DISP_E_NONAMEDARGS: - throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - case DISP_E_OVERFLOW: - throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - case DISP_E_PARAMNOTFOUND: - throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - case DISP_E_TYPEMISMATCH: - throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - case DISP_E_UNKNOWNINTERFACE: - throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - case DISP_E_UNKNOWNLCID: - throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - case DISP_E_PARAMNOTOPTIONAL: - throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - default: - throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)), - Reference<XInterface>()); - break; - } - } - catch (UnknownPropertyException& ) - { - throw; - } - catch (BridgeRuntimeError& e) - { - throw RuntimeException( - e.message, Reference<XInterface>()); - } - catch (Exception & e) - { - throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::getValue ! Message : \n") + - e.Message, Reference<XInterface>()); - } - catch (...) - { - throw RuntimeException( - OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::getValue !"), Reference<XInterface>()); - } - return ret; -} - -sal_Bool SAL_CALL IUnknownWrapper_Impl::hasMethod( const OUString& aName ) - throw(RuntimeException) -{ - if ( ! m_spDispatch ) - { - throw RuntimeException( - OUSTR("[automation bridge] The object does not have an IDispatch interface"), - Reference<XInterface>()); - } - sal_Bool ret = sal_False; - - try - { - o2u_attachCurrentThread(); - ITypeInfo* pInfo = getTypeInfo(); - FuncDesc aDesc(pInfo); - getFuncDesc(aName, & aDesc); - // Automation properties can have arguments. Those are treated as methods and - //are called through XInvocation::invoke. - if ( ! aDesc) - { - FuncDesc aDescGet(pInfo); - FuncDesc aDescPut(pInfo); - VarDesc aVarDesc(pInfo); - getPropDesc( aName, & aDescGet, & aDescPut, & aVarDesc); - if (aDescGet && aDescGet->cParams > 0 - || aDescPut && aDescPut->cParams > 0) - ret = sal_True; - } - else - ret = sal_True; - } - catch (BridgeRuntimeError& e) - { - throw RuntimeException(e.message, Reference<XInterface>()); - } - catch (Exception & e) - { - throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::hasMethod ! Message : \n") + - e.Message, Reference<XInterface>()); - } - catch (...) - { - throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::hasMethod !"), Reference<XInterface>());; - } - return ret; -} - -sal_Bool SAL_CALL IUnknownWrapper_Impl::hasProperty( const OUString& aName ) - throw(RuntimeException) -{ - if ( ! m_spDispatch ) - { - throw RuntimeException(OUSTR("[automation bridge] The object does not have an " - "IDispatch interface"), Reference<XInterface>()); - return sal_False; - } - sal_Bool ret = sal_False; - try - { - o2u_attachCurrentThread(); - - ITypeInfo * pInfo = getTypeInfo(); - FuncDesc aDescGet(pInfo); - FuncDesc aDescPut(pInfo); - VarDesc aVarDesc(pInfo); - getPropDesc(aName, & aDescGet, & aDescPut, & aVarDesc); - - // we should probably just check the funckind - // basic has been modified to handle properties ( 'get' ) props at - // least with paramaters - // additionally you can call invoke(Get|Set)Property on the bridge - // you can determine if a property has parameter is hasMethod - // returns true for the name - if (aVarDesc - || aDescPut - || aDescGet ) - { - ret = sal_True; - } - } - catch (BridgeRuntimeError& e) - { - throw RuntimeException(e.message, Reference<XInterface>()); - } - catch (Exception & e) - { - throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::hasProperty ! Message : \n") + - e.Message, Reference<XInterface>()); - - } - catch (...) - { - throw RuntimeException(OUSTR("[automation bridge] unexpected exception in " - "IUnknownWrapper_Impl::hasProperty !"), Reference<XInterface>()); - } - return ret; -} - -Any SAL_CALL IUnknownWrapper_Impl::createBridge( const Any& modelDepObject, - const Sequence< sal_Int8 >& /*aProcessId*/, sal_Int16 sourceModelType, - sal_Int16 destModelType ) - throw( IllegalArgumentException, RuntimeException) -{ - Any ret; - o2u_attachCurrentThread(); - - if ( - (sourceModelType == UNO) && - (destModelType == OLE) && - (modelDepObject.getValueTypeClass() == TypeClass_INTERFACE) - ) - { - Reference<XInterface> xInt( *(XInterface**) modelDepObject.getValue()); - Reference<XInterface> xSelf( (OWeakObject*)this); - - if (xInt == xSelf) - { - VARIANT* pVariant = (VARIANT*) CoTaskMemAlloc(sizeof(VARIANT)); - - VariantInit(pVariant); - if (m_bOriginalDispatch == sal_True) - { - pVariant->vt = VT_DISPATCH; - pVariant->pdispVal = m_spDispatch; - pVariant->pdispVal->AddRef(); - } - else - { - pVariant->vt = VT_UNKNOWN; - pVariant->punkVal = m_spUnknown; - pVariant->punkVal->AddRef(); - } - - ret.setValue((void*)&pVariant, getCppuType( (sal_uInt32*) 0)); - } - } - - return ret; -} -/** @internal - @exception IllegalArgumentException - @exception CannotConvertException - @exception InvocationTargetException - @RuntimeException -*/ -Any IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString& sFunctionName, - const Sequence< Any >& Params, - Sequence< sal_Int16 >& OutParamIndex, - Sequence< Any >& OutParam) -{ - Any ret; - HRESULT hr= S_OK; - - sal_Int32 parameterCount= Params.getLength(); - sal_Int32 outParameterCount= 0; - typelib_InterfaceMethodTypeDescription* pMethod= NULL; - TypeDescription methodDesc; - getMethodInfo(sFunctionName, methodDesc); - - // We need to know whether the IDispatch is from a JScript object. - // Then out and in/out parameters have to be treated differently than - // with common COM objects. - sal_Bool bJScriptObject= isJScriptObject(); - scoped_array<CComVariant> sarParams; - scoped_array<CComVariant> sarParamsRef; - CComVariant *pVarParams= NULL; - CComVariant *pVarParamsRef= NULL; - sal_Bool bConvRet= sal_True; - - if( methodDesc.is()) - { - pMethod = (typelib_InterfaceMethodTypeDescription* )methodDesc.get(); - parameterCount = pMethod->nParams; - // Create the Array for the array being passed in DISPPARAMS - // the array also contains the outparameter (but not the values) - if( pMethod->nParams > 0) - { - sarParams.reset(new CComVariant[ parameterCount]); - pVarParams = sarParams.get(); - } - - // Create the Array for the out an in/out parameter. These values - // are referenced by the VT_BYREF VARIANTs in DISPPARAMS. - // We need to find out the number of out and in/out parameter. - for( sal_Int32 i=0; i < parameterCount; i++) - { - if( pMethod->pParams[i].bOut) - outParameterCount++; - } - - if( !bJScriptObject) - { - sarParamsRef.reset(new CComVariant[outParameterCount]); - pVarParamsRef = sarParamsRef.get(); - // build up the parameters for IDispatch::Invoke - sal_Int32 outParamIndex=0; - int i = 0; - try - { - for( i= 0; i < parameterCount; i++) - { - // In parameter - if( pMethod->pParams[i].bIn == sal_True && ! pMethod->pParams[i].bOut) - { - anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]); - } - // Out parameter + in/out parameter - else if( pMethod->pParams[i].bOut == sal_True) - { - CComVariant var; - if(pMethod->pParams[i].bIn) - { - anyToVariant( & var,Params[i]); - pVarParamsRef[outParamIndex] = var; - } - - switch( pMethod->pParams[i].pTypeRef->eTypeClass) - { - case TypeClass_INTERFACE: - case TypeClass_STRUCT: - if( ! pMethod->pParams[i].bIn) - { - pVarParamsRef[ outParamIndex].vt= VT_DISPATCH; - pVarParamsRef[ outParamIndex].pdispVal= 0; - } - pVarParams[parameterCount - i -1].vt = VT_DISPATCH | VT_BYREF; - pVarParams[parameterCount - i -1].ppdispVal= &pVarParamsRef[outParamIndex].pdispVal; - break; - case TypeClass_ENUM: - case TypeClass_LONG: - case TypeClass_UNSIGNED_LONG: - if( ! pMethod->pParams[i].bIn) - { - pVarParamsRef[ outParamIndex].vt = VT_I4; - pVarParamsRef[ outParamIndex].lVal = 0; - } - pVarParams[parameterCount - i -1].vt = VT_I4 | VT_BYREF; - pVarParams[parameterCount - i -1].plVal= &pVarParamsRef[outParamIndex].lVal; - break; - case TypeClass_SEQUENCE: - if( ! pMethod->pParams[i].bIn) - { - pVarParamsRef[ outParamIndex].vt = VT_ARRAY| VT_VARIANT; - pVarParamsRef[ outParamIndex].parray= NULL; - } - pVarParams[parameterCount - i -1].vt = VT_ARRAY| VT_BYREF | VT_VARIANT; - pVarParams[parameterCount - i -1].pparray= &pVarParamsRef[outParamIndex].parray; - break; - case TypeClass_ANY: - if( ! pMethod->pParams[i].bIn) - { - pVarParamsRef[ outParamIndex].vt = VT_EMPTY; - pVarParamsRef[ outParamIndex].lVal = 0; - } - pVarParams[parameterCount - i -1].vt = VT_VARIANT | VT_BYREF; - pVarParams[parameterCount - i -1].pvarVal = &pVarParamsRef[outParamIndex]; - break; - case TypeClass_BOOLEAN: - if( ! pMethod->pParams[i].bIn) - { - pVarParamsRef[ outParamIndex].vt = VT_BOOL; - pVarParamsRef[ outParamIndex].boolVal = 0; - } - pVarParams[parameterCount - i -1].vt = VT_BOOL| VT_BYREF; - pVarParams[parameterCount - i -1].pboolVal = - & pVarParamsRef[outParamIndex].boolVal; - break; - - case TypeClass_STRING: - if( ! pMethod->pParams[i].bIn) - { - pVarParamsRef[ outParamIndex].vt = VT_BSTR; - pVarParamsRef[ outParamIndex].bstrVal= 0; - } - pVarParams[parameterCount - i -1].vt = VT_BSTR| VT_BYREF; - pVarParams[parameterCount - i -1].pbstrVal= - & pVarParamsRef[outParamIndex].bstrVal; - break; - - case TypeClass_FLOAT: - if( ! pMethod->pParams[i].bIn) - { - pVarParamsRef[ outParamIndex].vt = VT_R4; - pVarParamsRef[ outParamIndex].fltVal= 0; - } - pVarParams[parameterCount - i -1].vt = VT_R4| VT_BYREF; - pVarParams[parameterCount - i -1].pfltVal = - & pVarParamsRef[outParamIndex].fltVal; - break; - case TypeClass_DOUBLE: - if( ! pMethod->pParams[i].bIn) - { - pVarParamsRef[ outParamIndex].vt = VT_R8; - pVarParamsRef[ outParamIndex].dblVal= 0; - } - pVarParams[parameterCount - i -1].vt = VT_R8| VT_BYREF; - pVarParams[parameterCount - i -1].pdblVal= - & pVarParamsRef[outParamIndex].dblVal; - break; - case TypeClass_BYTE: - if( ! pMethod->pParams[i].bIn) - { - pVarParamsRef[ outParamIndex].vt = VT_UI1; - pVarParamsRef[ outParamIndex].bVal= 0; - } - pVarParams[parameterCount - i -1].vt = VT_UI1| VT_BYREF; - pVarParams[parameterCount - i -1].pbVal= - & pVarParamsRef[outParamIndex].bVal; - break; - case TypeClass_CHAR: - case TypeClass_SHORT: - case TypeClass_UNSIGNED_SHORT: - if( ! pMethod->pParams[i].bIn) - { - pVarParamsRef[ outParamIndex].vt = VT_I2; - pVarParamsRef[ outParamIndex].iVal = 0; - } - pVarParams[parameterCount - i -1].vt = VT_I2| VT_BYREF; - pVarParams[parameterCount - i -1].piVal= - & pVarParamsRef[outParamIndex].iVal; - break; - - default: - if( ! pMethod->pParams[i].bIn) - { - pVarParamsRef[ outParamIndex].vt = VT_EMPTY; - pVarParamsRef[ outParamIndex].lVal = 0; - } - pVarParams[parameterCount - i -1].vt = VT_VARIANT | VT_BYREF; - pVarParams[parameterCount - i -1].pvarVal = - & pVarParamsRef[outParamIndex]; - } - outParamIndex++; - } // end else if - } // end for - } - catch (IllegalArgumentException & e) - { - e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i ); - throw; - } - catch (CannotConvertException & e) - { - e.ArgumentIndex = i; - throw; - } - } - else // it is an JScriptObject - { - int i = 0; - try - { - for( ; i< parameterCount; i++) - { - // In parameter - if( pMethod->pParams[i].bIn == sal_True && ! pMethod->pParams[i].bOut) - { - anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]); - } - // Out parameter + in/out parameter - else if( pMethod->pParams[i].bOut == sal_True) - { - CComObject<JScriptOutParam>* pParamObject; - if( SUCCEEDED( CComObject<JScriptOutParam>::CreateInstance( &pParamObject))) - { - CComPtr<IUnknown> pUnk(pParamObject->GetUnknown()); -#ifdef __MINGW32__ - CComQIPtr<IDispatch, &__uuidof(IDispatch)> pDisp( pUnk); -#else - CComQIPtr<IDispatch> pDisp( pUnk); -#endif - - pVarParams[ parameterCount - i -1].vt= VT_DISPATCH; - pVarParams[ parameterCount - i -1].pdispVal= pDisp; - pVarParams[ parameterCount - i -1].pdispVal->AddRef(); - // if the param is in/out then put the parameter on index 0 - if( pMethod->pParams[i].bIn == sal_True ) // in / out - { - CComVariant varParam; - anyToVariant( &varParam, Params.getConstArray()[i]); - CComDispatchDriver dispDriver( pDisp); - if(FAILED( dispDriver.PutPropertyByName( L"0", &varParam))) - throw BridgeRuntimeError( - OUSTR("[automation bridge]IUnknownWrapper_Impl::" - "invokeWithDispIdUnoTlb\n" - "Could not set property \"0\" for the in/out " - "param!")); - - } - } - else - { - throw BridgeRuntimeError( - OUSTR("[automation bridge]IUnknownWrapper_Impl::" - "invokeWithDispIdUnoTlb\n" - "Could not create out parameter at index: ") + - OUString::valueOf((sal_Int32) i)); - } - - } - } - } - catch (IllegalArgumentException & e) - { - e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i ); - throw; - } - catch (CannotConvertException & e) - { - e.ArgumentIndex = i; - throw; - } - } - } - // No type description Available, that is we have to deal with a COM component, - // that does not implements UNO interfaces ( IDispatch based) - else - { - //We should not run into this block, because invokeWithDispIdComTlb should - //have been called instead. - OSL_ASSERT(0); - } - - - CComVariant varResult; - ExcepInfo excepinfo; - unsigned int uArgErr; - DISPPARAMS dispparams= { pVarParams, NULL, parameterCount, 0}; - // Get the DISPID - FuncDesc aDesc(getTypeInfo()); - getFuncDesc(sFunctionName, & aDesc); - // invoking OLE method - hr = m_spDispatch->Invoke(aDesc->memid, - IID_NULL, - LOCALE_USER_DEFAULT, - DISPATCH_METHOD, - &dispparams, - &varResult, - &excepinfo, - &uArgErr); - - // converting return value and out parameter back to UNO - if (hr == S_OK) - { - if( outParameterCount && pMethod) - { - OutParamIndex.realloc( outParameterCount); - OutParam.realloc( outParameterCount); - sal_Int32 outIndex=0; - int i = 0; - try - { - for( ; i < parameterCount; i++) - { - if( pMethod->pParams[i].bOut ) - { - OutParamIndex[outIndex]= (sal_Int16) i; - Any outAny; - if( !bJScriptObject) - { - variantToAny( &pVarParamsRef[outIndex], outAny, - Type(pMethod->pParams[i].pTypeRef), sal_False); - OutParam[outIndex++]= outAny; - } - else //JScriptObject - { - if( pVarParams[i].vt == VT_DISPATCH) - { - CComDispatchDriver pDisp( pVarParams[i].pdispVal); - if( pDisp) - { - CComVariant varOut; - if( SUCCEEDED( pDisp.GetPropertyByName( L"0", &varOut))) - { - variantToAny( &varOut, outAny, - Type(pMethod->pParams[parameterCount - 1 - i].pTypeRef), sal_False); - OutParam[outParameterCount - 1 - outIndex++]= outAny; - } - else - bConvRet= sal_False; - } - else - bConvRet= sal_False; - } - else - bConvRet= sal_False; - } - } - if( !bConvRet) break; - } - } - catch(IllegalArgumentException & e) - { - e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i ); - throw; - } - catch(CannotConvertException & e) - { - e.ArgumentIndex = i; - throw; - } - } - // return value, no type information available - if ( bConvRet) - { - try - { - if( pMethod ) - variantToAny(&varResult, ret, Type( pMethod->pReturnTypeRef), sal_False); - else - variantToAny(&varResult, ret, sal_False); - } - catch (IllegalArgumentException & e) - { - e.Message = - OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n" - "Could not convert return value! \n Message: \n") + e.Message; - throw; - } - catch (CannotConvertException & e) - { - e.Message = - OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n" - "Could not convert return value! \n Message: \n") + e.Message; - throw; - } - } - } - - if( !bConvRet) // conversion of return or out parameter failed - throw CannotConvertException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Call to COM object failed. Conversion of return or out value failed")), - Reference<XInterface>( static_cast<XWeak*>(this), UNO_QUERY ), TypeClass_UNKNOWN, - FailReason::UNKNOWN, 0);// lookup error code - // conversion of return or out parameter failed - switch (hr) - { - case S_OK: - break; - case DISP_E_BADPARAMCOUNT: - throw IllegalArgumentException(); - break; - case DISP_E_BADVARTYPE: - throw RuntimeException(); - break; - case DISP_E_EXCEPTION: - throw InvocationTargetException(); - break; - case DISP_E_MEMBERNOTFOUND: - throw IllegalArgumentException(); - break; - case DISP_E_NONAMEDARGS: - throw IllegalArgumentException(); - break; - case DISP_E_OVERFLOW: - throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( - static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr); - break; - case DISP_E_PARAMNOTFOUND: - throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( - static_cast<XWeak*>(this)), ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); - break; - case DISP_E_TYPEMISMATCH: - throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface*>( - static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr); - break; - case DISP_E_UNKNOWNINTERFACE: - throw RuntimeException() ; - break; - case DISP_E_UNKNOWNLCID: - throw RuntimeException() ; - break; - case DISP_E_PARAMNOTOPTIONAL: - throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>( - static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr); - break; - default: - throw RuntimeException(); - break; - } - - return ret; -} - - - -// -------------------------- -// XInitialization -void SAL_CALL IUnknownWrapper_Impl::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException) -{ - // 1.parameter is IUnknown - // 2.parameter is a boolean which indicates if the the COM pointer was a IUnknown or IDispatch - // 3.parameter is a Sequence<Type> - o2u_attachCurrentThread(); - OSL_ASSERT(aArguments.getLength() == 3); - - m_spUnknown= *(IUnknown**) aArguments[0].getValue(); -#ifdef __MINGW32__ - m_spUnknown->QueryInterface(IID_IDispatch, reinterpret_cast<LPVOID*>( & m_spDispatch.p)); -#else - m_spUnknown.QueryInterface( & m_spDispatch.p); -#endif - - aArguments[1] >>= m_bOriginalDispatch; - aArguments[2] >>= m_seqTypes; - - ITypeInfo* pType = NULL; - try - { - // a COM object implementation that has no TypeInfo is still a legal COM object; - // such objects can at least be transported through UNO using the bridge - // so we should allow to create wrappers for them as well - pType = getTypeInfo(); - } - catch( BridgeRuntimeError& ) - {} - catch( Exception& ) - {} - - if ( pType ) - { - try - { - // Get Default member - CComBSTR defaultMemberName; - if ( SUCCEEDED( pType->GetDocumentation(0, &defaultMemberName, 0, 0, 0 ) ) ) - { - OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(defaultMemberName))); - FuncDesc aDescGet(pType); - FuncDesc aDescPut(pType); - VarDesc aVarDesc(pType); - // see if this is a property first ( more likely to be a property then a method ) - getPropDesc( usName, & aDescGet, & aDescPut, & aVarDesc); - - if ( !aDescGet && !aDescPut ) - { - getFuncDesc( usName, &aDescGet ); - if ( !aDescGet ) - throw BridgeRuntimeError( OUSTR("[automation bridge]IUnknownWrapper_Impl::initialize() Failed to get Function or Property desc. for " ) + usName ); - } - // now for some funny heuristics to make basic understand what to do - // a single aDescGet ( that doesn't take any params ) would be - // a read only ( defaultmember ) property e.g. this object - // should implement XDefaultProperty - // a single aDescGet ( that *does* ) take params is basically a - // default method e.g. implement XDefaultMethod - - // a DescPut ( I guess we only really support a default param with '1' param ) as a setValue ( but I guess we can leave it through, the object will fail if we don't get it right anyway ) - if ( aDescPut || ( aDescGet && aDescGet->cParams == 0 ) ) - m_bHasDfltProperty = true; - if ( aDescGet->cParams > 0 ) - m_bHasDfltMethod = true; - if ( m_bHasDfltProperty || m_bHasDfltMethod ) - m_sDefaultMember = usName; - } - } - catch ( BridgeRuntimeError & e ) - { - throw RuntimeException( e.message, Reference<XInterface>() ); - } - catch( Exception& e ) - { - throw RuntimeException( - OUSTR("[automation bridge] unexpected exception in IUnknownWrapper_Impl::initialiase() error message: \n") + e.Message, - Reference<XInterface>() ); - } - } -} - -// -------------------------- -// XDirectInvocation -uno::Any SAL_CALL IUnknownWrapper_Impl::directInvoke( const ::rtl::OUString& aName, const uno::Sequence< uno::Any >& aParams ) - throw (lang::IllegalArgumentException, script::CannotConvertException, reflection::InvocationTargetException, uno::RuntimeException) -{ - Any aResult; - - if ( !m_spDispatch ) - { - throw RuntimeException( - OUSTR("[automation bridge] The object does not have an IDispatch interface"), - Reference<XInterface>()); - } - - o2u_attachCurrentThread(); - DISPID dispid; - if ( !getDispid( aName, &dispid ) ) - throw IllegalArgumentException( - OUSTR( "[automation bridge] The object does not have a function or property " ) - + aName, Reference<XInterface>(), 0); - - CComVariant varResult; - ExcepInfo excepinfo; - unsigned int uArgErr = 0; - INVOKEKIND pInvkinds[2]; - pInvkinds[0] = INVOKE_FUNC; - pInvkinds[1] = aParams.getLength() ? INVOKE_PROPERTYPUT : INVOKE_PROPERTYGET; - HRESULT hInvRes = E_FAIL; - - // try Invoke first, if it does not work, try put/get property - for ( sal_Int32 nStep = 0; FAILED( hInvRes ) && nStep < 2; nStep++ ) - { - DISPPARAMS dispparams = {NULL, NULL, 0, 0}; - - DISPID idPropertyPut = DISPID_PROPERTYPUT; - scoped_array<DISPID> arDispidNamedArgs; - scoped_array<CComVariant> ptrArgs; - scoped_array<CComVariant> ptrRefArgs; // referenced arguments - CComVariant * arArgs = NULL; - CComVariant * arRefArgs = NULL; - - dispparams.cArgs = aParams.getLength(); - - // Determine the number of named arguments - for ( sal_Int32 nInd = 0; nInd < aParams.getLength(); nInd++ ) - if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0) ) - dispparams.cNamedArgs ++; - - // fill the named arguments - if ( dispparams.cNamedArgs > 0 - && !( dispparams.cNamedArgs == 1 && pInvkinds[nStep] == INVOKE_PROPERTYPUT ) ) - { - int nSizeAr = dispparams.cNamedArgs + 1; - if ( pInvkinds[nStep] == INVOKE_PROPERTYPUT ) - nSizeAr = dispparams.cNamedArgs; - - scoped_array<OLECHAR*> saNames(new OLECHAR*[nSizeAr]); - OLECHAR ** pNames = saNames.get(); - pNames[0] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(aName.getStr())); - - int cNamedArg = 0; - for ( size_t nInd = 0; nInd < dispparams.cArgs; nInd++ ) - { - if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0)) - { - const NamedArgument& arg = *(NamedArgument const*)aParams[nInd].getValue(); - - //We put the parameter names in reverse order into the array, - //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs - //The first name in the array is the method name - pNames[nSizeAr - 1 - cNamedArg++] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(arg.Name.getStr())); - } - } - - arDispidNamedArgs.reset( new DISPID[nSizeAr] ); - HRESULT hr = getTypeInfo()->GetIDsOfNames( pNames, nSizeAr, arDispidNamedArgs.get() ); - if ( hr == E_NOTIMPL ) - hr = m_spDispatch->GetIDsOfNames(IID_NULL, pNames, nSizeAr, LOCALE_USER_DEFAULT, arDispidNamedArgs.get() ); - - if ( SUCCEEDED( hr ) ) - { - if ( pInvkinds[nStep] == DISPATCH_PROPERTYPUT ) - { - DISPID* arIDs = arDispidNamedArgs.get(); - arIDs[0] = DISPID_PROPERTYPUT; - dispparams.rgdispidNamedArgs = arIDs; - } - else - { - DISPID* arIDs = arDispidNamedArgs.get(); - dispparams.rgdispidNamedArgs = & arIDs[1]; - } - } - else if (hr == DISP_E_UNKNOWNNAME) - { - throw IllegalArgumentException( - OUSTR("[automation bridge]One of the named arguments is wrong!"), - Reference<XInterface>(), 0); - } - else - { - throw InvocationTargetException( - OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ") - + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any()); - } - } - - //Convert arguments - ptrArgs.reset(new CComVariant[dispparams.cArgs]); - ptrRefArgs.reset(new CComVariant[dispparams.cArgs]); - arArgs = ptrArgs.get(); - arRefArgs = ptrRefArgs.get(); - - sal_Int32 nInd = 0; - try - { - sal_Int32 revIndex = 0; - for ( nInd = 0; nInd < sal_Int32(dispparams.cArgs); nInd++) - { - revIndex = dispparams.cArgs - nInd - 1; - arRefArgs[revIndex].byref = 0; - Any anyArg; - if ( nInd < aParams.getLength() ) - anyArg = aParams.getConstArray()[nInd]; - - // Property Put arguments - if ( anyArg.getValueType() == getCppuType((PropertyPutArgument*)0) ) - { - PropertyPutArgument arg; - anyArg >>= arg; - anyArg <<= arg.Value; - } - // named argument - if (anyArg.getValueType() == getCppuType((NamedArgument*) 0)) - { - NamedArgument aNamedArgument; - anyArg >>= aNamedArgument; - anyArg <<= aNamedArgument.Value; - } - - if ( nInd < aParams.getLength() && anyArg.getValueTypeClass() != TypeClass_VOID ) - { - anyToVariant( &arArgs[revIndex], anyArg, VT_VARIANT ); - } - else - { - arArgs[revIndex].vt = VT_ERROR; - arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND; - } - } - } - catch (IllegalArgumentException & e) - { - e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, sal_Int32 >( nInd ); - throw; - } - catch (CannotConvertException & e) - { - e.ArgumentIndex = nInd; - throw; - } - - dispparams.rgvarg = arArgs; - // invoking OLE method - DWORD localeId = LOCALE_USER_DEFAULT; - hInvRes = m_spDispatch->Invoke( dispid, - IID_NULL, - localeId, - ::sal::static_int_cast< WORD, INVOKEKIND >( pInvkinds[nStep] ), - &dispparams, - &varResult, - &excepinfo, - &uArgErr); - } - - // converting return value and out parameter back to UNO - if ( SUCCEEDED( hInvRes ) ) - variantToAny( &varResult, aResult, sal_False ); - else - { - // map error codes to exceptions - OUString message; - switch ( hInvRes ) - { - case S_OK: - break; - case DISP_E_BADPARAMCOUNT: - throw IllegalArgumentException(OUSTR("[automation bridge] Wrong " - "number of arguments. Object returned DISP_E_BADPARAMCOUNT."), - 0, 0); - break; - case DISP_E_BADVARTYPE: - throw RuntimeException(OUSTR("[automation bridge] One or more " - "arguments have the wrong type. Object returned " - "DISP_E_BADVARTYPE."), 0); - break; - case DISP_E_EXCEPTION: - message = OUSTR("[automation bridge]: "); - message += OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription), - ::SysStringLen(excepinfo.bstrDescription)); - throw InvocationTargetException(message, Reference<XInterface>(), Any()); - break; - case DISP_E_MEMBERNOTFOUND: - message = OUSTR("[automation bridge]: A function with the name \"") - + aName + OUSTR("\" is not supported. Object returned " - "DISP_E_MEMBERNOTFOUND."); - throw IllegalArgumentException(message, 0, 0); - break; - case DISP_E_NONAMEDARGS: - throw IllegalArgumentException(OUSTR("[automation bridge] Object " - "returned DISP_E_NONAMEDARGS"),0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); - break; - case DISP_E_OVERFLOW: - throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[automation bridge] Call failed.")), - static_cast<XInterface*>( - static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr); - break; - case DISP_E_PARAMNOTFOUND: - throw IllegalArgumentException(OUSTR("[automation bridge]Call failed." - "Object returned DISP_E_PARAMNOTFOUND."), - 0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); - break; - case DISP_E_TYPEMISMATCH: - throw CannotConvertException(OUSTR("[automation bridge] Call failed. " - "Object returned DISP_E_TYPEMISMATCH"), - static_cast<XInterface*>( - static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr); - break; - case DISP_E_UNKNOWNINTERFACE: - throw RuntimeException(OUSTR("[automation bridge] Call failed. " - "Object returned DISP_E_UNKNOWNINTERFACE."),0); - break; - case DISP_E_UNKNOWNLCID: - throw RuntimeException(OUSTR("[automation bridge] Call failed. " - "Object returned DISP_E_UNKNOWNLCID."),0); - break; - case DISP_E_PARAMNOTOPTIONAL: - throw CannotConvertException(OUSTR("[automation bridge] Call failed." - "Object returned DISP_E_PARAMNOTOPTIONAL"), - static_cast<XInterface*>(static_cast<XWeak*>(this)), - TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr); - break; - default: - throw RuntimeException(); - break; - } - } - - return aResult; -} - -::sal_Bool SAL_CALL IUnknownWrapper_Impl::hasMember( const ::rtl::OUString& aName ) - throw (uno::RuntimeException) -{ - if ( ! m_spDispatch ) - { - throw RuntimeException( - OUSTR("[automation bridge] The object does not have an IDispatch interface"), - Reference<XInterface>()); - } - - o2u_attachCurrentThread(); - DISPID dispid; - return getDispid( aName, &dispid ); -} - - -// UnoConversionUtilities -------------------------------------------------------------------------------- -Reference< XInterface > IUnknownWrapper_Impl::createUnoWrapperInstance() -{ - if( m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL) - { - Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl( - m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); - return Reference<XInterface>( xWeak, UNO_QUERY); - } - else if( m_nUnoWrapperClass == UNO_OBJECT_WRAPPER_REMOTE_OPT) - { - Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt( - m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); - return Reference<XInterface>( xWeak, UNO_QUERY); - } - else - return Reference<XInterface>(); -} -Reference<XInterface> IUnknownWrapper_Impl::createComWrapperInstance() -{ - Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl( - m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); - return Reference<XInterface>( xWeak, UNO_QUERY); -} - - - -void IUnknownWrapper_Impl::getMethodInfo(const OUString& sName, TypeDescription& methodInfo) -{ - TypeDescription desc= getInterfaceMemberDescOfCurrentCall(sName); - if( desc.is()) - { - typelib_TypeDescription* pMember= desc.get(); - if( pMember->eTypeClass == TypeClass_INTERFACE_METHOD ) - methodInfo= pMember; - } -} - -void IUnknownWrapper_Impl::getAttributeInfo(const OUString& sName, TypeDescription& attributeInfo) -{ - TypeDescription desc= getInterfaceMemberDescOfCurrentCall(sName); - if( desc.is()) - { - typelib_TypeDescription* pMember= desc.get(); - if( pMember->eTypeClass == TypeClass_INTERFACE_ATTRIBUTE ) - { - attributeInfo= ((typelib_InterfaceAttributeTypeDescription*)pMember)->pAttributeTypeRef; - } - } -} -TypeDescription IUnknownWrapper_Impl::getInterfaceMemberDescOfCurrentCall(const OUString& sName) -{ - TypeDescription ret; - - for( sal_Int32 i=0; i < m_seqTypes.getLength(); i++) - { - TypeDescription _curDesc( m_seqTypes[i]); - _curDesc.makeComplete(); - typelib_InterfaceTypeDescription * pInterface= (typelib_InterfaceTypeDescription*) _curDesc.get(); - if( pInterface) - { - typelib_InterfaceMemberTypeDescription* pMember= NULL; - //find the member description of the current call - for( int i=0; i < pInterface->nAllMembers; i++) - { - typelib_TypeDescriptionReference* pTypeRefMember = pInterface->ppAllMembers[i]; - typelib_TypeDescription* pDescMember= NULL; - TYPELIB_DANGER_GET( &pDescMember, pTypeRefMember) - - typelib_InterfaceMemberTypeDescription* pInterfaceMember= - (typelib_InterfaceMemberTypeDescription*) pDescMember; - if( OUString( pInterfaceMember->pMemberName) == sName) - { - pMember= pInterfaceMember; - break; - } - TYPELIB_DANGER_RELEASE( pDescMember) - } - - if( pMember) - { - ret= (typelib_TypeDescription*)pMember; - TYPELIB_DANGER_RELEASE( (typelib_TypeDescription*)pMember); - } - } - if( ret.is()) - break; - } - return ret; -} - -sal_Bool IUnknownWrapper_Impl::isJScriptObject() -{ - if( m_eJScript == JScriptUndefined) - { - CComDispatchDriver disp( m_spDispatch); - if( disp) - { - CComVariant result; - if( SUCCEEDED( disp.GetPropertyByName( JSCRIPT_ID_PROPERTY, &result))) - { - if(result.vt == VT_BSTR) - { - CComBSTR name( result.bstrVal); - name.ToLower(); - if( name == CComBSTR(JSCRIPT_ID)) - m_eJScript= IsJScript; - } - } - } - if( m_eJScript == JScriptUndefined) - m_eJScript= NoJScript; - } - - return m_eJScript == NoJScript ? sal_False : sal_True; -} - - - -/** @internal - The function ultimately calls IDispatch::Invoke on the wrapped COM object. - The COM object does not implement UNO Interfaces ( via IDispatch). This - is the case when the OleObjectFactory service has been used to create a - component. - @exception IllegalArgumentException - @exception CannotConvertException - @InvocationTargetException - @RuntimeException - @BridgeRuntimeError -*/ -Any IUnknownWrapper_Impl::invokeWithDispIdComTlb(const OUString& sFuncName, - const Sequence< Any >& Params, - Sequence< sal_Int16 >& OutParamIndex, - Sequence< Any >& OutParam) -{ - // Get type info for the call. It can be a method call or property put or - // property get operation. - FuncDesc aFuncDesc(getTypeInfo()); - getFuncDescForInvoke(sFuncName, Params, & aFuncDesc); - return invokeWithDispIdComTlb( aFuncDesc, sFuncName, Params, OutParamIndex, OutParam ); -} - -Any IUnknownWrapper_Impl::invokeWithDispIdComTlb(FuncDesc& aFuncDesc, - const OUString& sFuncName, - const Sequence< Any >& Params, - Sequence< sal_Int16 >& OutParamIndex, - Sequence< Any >& OutParam) -{ - Any ret; - HRESULT result; - - DISPPARAMS dispparams = {NULL, NULL, 0, 0}; - CComVariant varResult; - ExcepInfo excepinfo; - unsigned int uArgErr; - sal_Int32 i = 0; - sal_Int32 nUnoArgs = Params.getLength(); - DISPID idPropertyPut = DISPID_PROPERTYPUT; - scoped_array<DISPID> arDispidNamedArgs; - scoped_array<CComVariant> ptrArgs; - scoped_array<CComVariant> ptrRefArgs; // referenced arguments - CComVariant * arArgs = NULL; - CComVariant * arRefArgs = NULL; - sal_Int32 revIndex = 0; - - //Set the array of DISPIDs for named args if it is a property put operation. - //If there are other named arguments another array is set later on. - if (aFuncDesc->invkind == INVOKE_PROPERTYPUT - || aFuncDesc->invkind == INVOKE_PROPERTYPUTREF) - dispparams.rgdispidNamedArgs = & idPropertyPut; - - //Determine the number of named arguments - for (int iParam = 0; iParam < nUnoArgs; iParam ++) - { - const Any & curArg = Params[iParam]; - if (curArg.getValueType() == getCppuType((NamedArgument*) 0)) - dispparams.cNamedArgs ++; - } - //In a property put operation a property value is a named argument (DISPID_PROPERTYPUT). - //Therefore the number of named arguments is increased by one. - //Although named, the argument is not named in a actual language, such as Basic, - //therefore it is never a com.sun.star.bridge.oleautomation.NamedArgument - if (aFuncDesc->invkind == DISPATCH_PROPERTYPUT - || aFuncDesc->invkind == DISPATCH_PROPERTYPUTREF) - dispparams.cNamedArgs ++; - - //Determine the number of all arguments and named arguments - if (aFuncDesc->cParamsOpt == -1) - { - //Attribute vararg is set on this method. "Unlimited" number of args - //supported. There can be no optional or defaultvalue on any of the arguments. - dispparams.cArgs = nUnoArgs; - } - else - { - //If there are namesd arguments, then the dispparams.cArgs - //is the number of supplied args, otherwise it is the expected number. - if (dispparams.cNamedArgs) - dispparams.cArgs = nUnoArgs; - else - dispparams.cArgs = aFuncDesc->cParams; - } - - //check if there are not to many arguments supplied - if (::sal::static_int_cast< sal_uInt32, int >( nUnoArgs ) > dispparams.cArgs) - { - OUStringBuffer buf(256); - buf.appendAscii("[automation bridge] There are too many arguments for this method"); - throw IllegalArgumentException( buf.makeStringAndClear(), - Reference<XInterface>(), (sal_Int16) dispparams.cArgs); - } - - //Set up the array of DISPIDs (DISPPARAMS::rgdispidNamedArgs) - //for the named arguments. - //If there is only one named arg and if it is because of a property put - //operation, then we need not set up the DISPID array. - if (dispparams.cNamedArgs > 0 && - ! (dispparams.cNamedArgs == 1 && - (aFuncDesc->invkind == INVOKE_PROPERTYPUT || - aFuncDesc->invkind == INVOKE_PROPERTYPUT))) - { - //set up an array containing the member and parameter names - //which is then used in ITypeInfo::GetIDsOfNames - //First determine the size of the array of names which is passed to - //ITypeInfo::GetIDsOfNames. It must hold the method names + the named - //args. - int nSizeAr = dispparams.cNamedArgs + 1; - if (aFuncDesc->invkind == INVOKE_PROPERTYPUT - || aFuncDesc->invkind == INVOKE_PROPERTYPUTREF) - { - nSizeAr = dispparams.cNamedArgs; //counts the DISID_PROPERTYPUT - } - - scoped_array<OLECHAR*> saNames(new OLECHAR*[nSizeAr]); - OLECHAR ** arNames = saNames.get(); - arNames[0] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(sFuncName.getStr())); - - int cNamedArg = 0; - for (size_t iParams = 0; iParams < dispparams.cArgs; iParams ++) - { - const Any & curArg = Params[iParams]; - if (curArg.getValueType() == getCppuType((NamedArgument*) 0)) - { - const NamedArgument& arg = *(NamedArgument const*) curArg.getValue(); - //We put the parameter names in reverse order into the array, - //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs - //The first name in the array is the method name - arNames[nSizeAr - 1 - cNamedArg++] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(arg.Name.getStr())); - } - } - - //Prepare the array of DISPIDs for ITypeInfo::GetIDsOfNames - //it must be big enough to contain the DISPIDs of the member + parameters - arDispidNamedArgs.reset(new DISPID[nSizeAr]); - HRESULT hr = getTypeInfo()->GetIDsOfNames(arNames, nSizeAr, - arDispidNamedArgs.get()); - if ( hr == E_NOTIMPL ) - hr = m_spDispatch->GetIDsOfNames(IID_NULL, arNames, nSizeAr, LOCALE_USER_DEFAULT, arDispidNamedArgs.get() ); - - if (hr == S_OK) - { - // In a "property put" operation, the property value is a named param with the - //special DISPID DISPID_PROPERTYPUT - if (aFuncDesc->invkind == DISPATCH_PROPERTYPUT - || aFuncDesc->invkind == DISPATCH_PROPERTYPUTREF) - { - //Element at index 0 in the DISPID array must be DISPID_PROPERTYPUT - //The first item in the array arDispidNamedArgs is the DISPID for - //the method. We replace it with DISPID_PROPERTYPUT. - DISPID* arIDs = arDispidNamedArgs.get(); - arIDs[0] = DISPID_PROPERTYPUT; - dispparams.rgdispidNamedArgs = arIDs; - } - else - { - //The first item in the array arDispidNamedArgs is the DISPID for - //the method. It must be removed - DISPID* arIDs = arDispidNamedArgs.get(); - dispparams.rgdispidNamedArgs = & arIDs[1]; - } - } - else if (hr == DISP_E_UNKNOWNNAME) - { - throw IllegalArgumentException( - OUSTR("[automation bridge]One of the named arguments is wrong!"), - Reference<XInterface>(), 0); - } - else - { - throw InvocationTargetException( - OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ") - + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any()); - } - } - - //Convert arguments - ptrArgs.reset(new CComVariant[dispparams.cArgs]); - ptrRefArgs.reset(new CComVariant[dispparams.cArgs]); - arArgs = ptrArgs.get(); - arRefArgs = ptrRefArgs.get(); - try - { - for (i = 0; i < (sal_Int32) dispparams.cArgs; i++) - { - revIndex= dispparams.cArgs - i -1; - arRefArgs[revIndex].byref=0; - Any anyArg; - if ( i < nUnoArgs) - anyArg= Params.getConstArray()[i]; - - unsigned short paramFlags = PARAMFLAG_FOPT | PARAMFLAG_FIN; - VARTYPE varType = VT_VARIANT; - if (aFuncDesc->cParamsOpt != -1 || aFuncDesc->cParams != (i + 1)) - { - paramFlags = aFuncDesc->lprgelemdescParam[i].paramdesc.wParamFlags; - varType = getElementTypeDesc(&aFuncDesc->lprgelemdescParam[i].tdesc); - } - - // Make sure that there is a UNO parameter for every - // expected parameter. If there is no UNO parameter where the - // called function expects one, then it must be optional. Otherwise - // its a UNO programming error. - if (i >= nUnoArgs && !(paramFlags & PARAMFLAG_FOPT)) - { - OUStringBuffer buf(256); - buf.appendAscii("ole automation bridge: The called function expects an argument at" - "position: "); //a different number of arguments")), - buf.append(OUString::valueOf((sal_Int32) i)); - buf.appendAscii(" (index starting at 0)."); - throw IllegalArgumentException( buf.makeStringAndClear(), - Reference<XInterface>(), (sal_Int16) i); - } - - // Property Put arguments - if (anyArg.getValueType() == getCppuType((PropertyPutArgument*)0)) - { - PropertyPutArgument arg; - anyArg >>= arg; - anyArg <<= arg.Value; - } - // named argument - if (anyArg.getValueType() == getCppuType((NamedArgument*) 0)) - { - NamedArgument aNamedArgument; - anyArg >>= aNamedArgument; - anyArg <<= aNamedArgument.Value; - } - // out param - if (paramFlags & PARAMFLAG_FOUT && - ! (paramFlags & PARAMFLAG_FIN) ) - { - VARTYPE type = ::sal::static_int_cast< VARTYPE, int >( varType ^ VT_BYREF ); - if (i < nUnoArgs) - { - arRefArgs[revIndex].vt= type; - } - else - { - //optional arg - arRefArgs[revIndex].vt = VT_ERROR; - arRefArgs[revIndex].scode = DISP_E_PARAMNOTFOUND; - } - if( type == VT_VARIANT ) - { - arArgs[revIndex].vt= VT_VARIANT | VT_BYREF; - arArgs[revIndex].byref= &arRefArgs[revIndex]; - } - else - { - arArgs[revIndex].vt= varType; - if (type == VT_DECIMAL) - arArgs[revIndex].byref= & arRefArgs[revIndex].decVal; - else - arArgs[revIndex].byref= & arRefArgs[revIndex].byref; - } - } - // in/out + in byref params - else if (varType & VT_BYREF) - { - VARTYPE type = ::sal::static_int_cast< VARTYPE, int >( varType ^ VT_BYREF ); - CComVariant var; - - if (i < nUnoArgs && anyArg.getValueTypeClass() != TypeClass_VOID) - { - anyToVariant( & arRefArgs[revIndex], anyArg, type); - } - else if (paramFlags & PARAMFLAG_FHASDEFAULT) - { - //optional arg with default - VariantCopy( & arRefArgs[revIndex], - & aFuncDesc->lprgelemdescParam[i].paramdesc. - pparamdescex->varDefaultValue); - } - else - { - //optional arg - //e.g: call func(x) in basic : func() ' no arg supplied - OSL_ASSERT(paramFlags & PARAMFLAG_FOPT); - arRefArgs[revIndex].vt = VT_ERROR; - arRefArgs[revIndex].scode = DISP_E_PARAMNOTFOUND; - } - - // Set the converted arguments in the array which will be - // DISPPARAMS::rgvarg - // byref arg VT_XXX |VT_BYREF - arArgs[revIndex].vt = varType; - if (revIndex == 0 && aFuncDesc->invkind == INVOKE_PROPERTYPUT) - { - arArgs[revIndex] = arRefArgs[revIndex]; - } - else if (type == VT_DECIMAL) - { - arArgs[revIndex].byref= & arRefArgs[revIndex].decVal; - } - else if (type == VT_VARIANT) - { - if ( ! (paramFlags & PARAMFLAG_FOUT)) - arArgs[revIndex] = arRefArgs[revIndex]; - else - arArgs[revIndex].byref = & arRefArgs[revIndex]; - } - else - { - arArgs[revIndex].byref = & arRefArgs[revIndex].byref; - arArgs[revIndex].vt = ::sal::static_int_cast< VARTYPE, int >( arRefArgs[revIndex].vt | VT_BYREF ); - } - - } - // in parameter no VT_BYREF except for array, interfaces - else - { // void any stands for optional param - if (i < nUnoArgs && anyArg.getValueTypeClass() != TypeClass_VOID) - { - anyToVariant( & arArgs[revIndex], anyArg, varType); - } - //optional arg but no void any supplied - //Basic: obj.func() ' first parameter left out because it is optional - else if (paramFlags & PARAMFLAG_FHASDEFAULT) - { - //optional arg with defaulteithter as direct arg : VT_XXX or - VariantCopy( & arArgs[revIndex], - & aFuncDesc->lprgelemdescParam[i].paramdesc. - pparamdescex->varDefaultValue); - } - else if (paramFlags & PARAMFLAG_FOPT) - { - arArgs[revIndex].vt = VT_ERROR; - arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND; - } - else - { - arArgs[revIndex].vt = VT_EMPTY; - arArgs[revIndex].lVal = 0; - } - } - } - } - catch (IllegalArgumentException & e) - { - e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, sal_Int32 >( i ); - throw; - } - catch (CannotConvertException & e) - { - e.ArgumentIndex = i; - throw; - } - dispparams.rgvarg= arArgs; - // invoking OLE method - DWORD localeId = LOCALE_USER_DEFAULT; - result = m_spDispatch->Invoke(aFuncDesc->memid, - IID_NULL, - localeId, - ::sal::static_int_cast< WORD, INVOKEKIND >( aFuncDesc->invkind ), - &dispparams, - &varResult, - &excepinfo, - &uArgErr); - - // converting return value and out parameter back to UNO - if (result == S_OK) - { - - // allocate space for the out param Sequence and indices Sequence - int outParamsCount= 0; // includes in/out parameter - for (int i = 0; i < aFuncDesc->cParams; i++) - { - if (aFuncDesc->lprgelemdescParam[i].paramdesc.wParamFlags & - PARAMFLAG_FOUT) - outParamsCount++; - } - - OutParamIndex.realloc(outParamsCount); - OutParam.realloc(outParamsCount); - // Convert out params - if (outParamsCount) - { - int outParamIndex=0; - for (int paramIndex = 0; paramIndex < nUnoArgs; paramIndex ++) - { - //Determine the index within the method sinature - int realParamIndex = paramIndex; - int revParamIndex = dispparams.cArgs - paramIndex - 1; - if (Params[paramIndex].getValueType() - == getCppuType((NamedArgument*) 0)) - { - //dispparams.rgdispidNamedArgs contains the mapping from index - //of named args list to index of parameter list - realParamIndex = dispparams.rgdispidNamedArgs[revParamIndex]; - } - - // no named arg, always come before named args - if (! (aFuncDesc->lprgelemdescParam[realParamIndex].paramdesc.wParamFlags - & PARAMFLAG_FOUT)) - continue; - Any outAny; - // variantToAny is called with the "reduce range" parameter set to sal_False. - // That causes VT_I4 values not to be converted down to a "lower" type. That - // feature exist for JScript only because it only uses VT_I4 for integer types. - try - { - variantToAny( & arRefArgs[revParamIndex], outAny, sal_False ); - } - catch (IllegalArgumentException & e) - { - e.ArgumentPosition = (sal_Int16)paramIndex; - throw; - } - catch (CannotConvertException & e) - { - e.ArgumentIndex = paramIndex; - throw; - } - OutParam[outParamIndex] = outAny; - OutParamIndex[outParamIndex] = ::sal::static_int_cast< sal_Int16, int >( paramIndex ); - outParamIndex++; - } - OutParam.realloc(outParamIndex); - OutParamIndex.realloc(outParamIndex); - } - // Return value - variantToAny(&varResult, ret, sal_False); - } - - // map error codes to exceptions - OUString message; - switch (result) - { - case S_OK: - break; - case DISP_E_BADPARAMCOUNT: - throw IllegalArgumentException(OUSTR("[automation bridge] Wrong " - "number of arguments. Object returned DISP_E_BADPARAMCOUNT."), - 0, 0); - break; - case DISP_E_BADVARTYPE: - throw RuntimeException(OUSTR("[automation bridge] One or more " - "arguments have the wrong type. Object returned " - "DISP_E_BADVARTYPE."), 0); - break; - case DISP_E_EXCEPTION: - { - message = OUSTR("[automation bridge]: "); - message += OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription), - ::SysStringLen(excepinfo.bstrDescription)); - - // Add for VBA, to throw an exception with the correct error code and message. - sal_Int32 nErrorCode = excepinfo.wCode; - if ( nErrorCode == 0 ) - { - // The low 16-bit of scode describing the error or warning. - nErrorCode = ( excepinfo.scode & 0xFFFF ); - } - BasicErrorException aBasicErrExp(message, Reference<XInterface>(), nErrorCode, message); - throw InvocationTargetException(message, Reference<XInterface>(), makeAny(aBasicErrExp)); - // End add - - break; - } - case DISP_E_MEMBERNOTFOUND: - message = OUSTR("[automation bridge]: A function with the name \"") - + sFuncName + OUSTR("\" is not supported. Object returned " - "DISP_E_MEMBERNOTFOUND."); - throw IllegalArgumentException(message, 0, 0); - break; - case DISP_E_NONAMEDARGS: - throw IllegalArgumentException(OUSTR("[automation bridge] Object " - "returned DISP_E_NONAMEDARGS"),0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); - break; - case DISP_E_OVERFLOW: - throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[automation bridge] Call failed.")), - static_cast<XInterface*>( - static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr); - break; - case DISP_E_PARAMNOTFOUND: - throw IllegalArgumentException(OUSTR("[automation bridge]Call failed." - "Object returned DISP_E_PARAMNOTFOUND."), - 0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); - break; - case DISP_E_TYPEMISMATCH: - throw CannotConvertException(OUSTR("[automation bridge] Call failed. " - "Object returned DISP_E_TYPEMISMATCH"), - static_cast<XInterface*>( - static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr); - break; - case DISP_E_UNKNOWNINTERFACE: - throw RuntimeException(OUSTR("[automation bridge] Call failed. " - "Object returned DISP_E_UNKNOWNINTERFACE."),0); - break; - case DISP_E_UNKNOWNLCID: - throw RuntimeException(OUSTR("[automation bridge] Call failed. " - "Object returned DISP_E_UNKNOWNLCID."),0); - break; - case DISP_E_PARAMNOTOPTIONAL: - throw CannotConvertException(OUSTR("[automation bridge] Call failed." - "Object returned DISP_E_PARAMNOTOPTIONAL"), - static_cast<XInterface*>(static_cast<XWeak*>(this)), - TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr); - break; - default: - throw RuntimeException(); - break; - } - - return ret; -} - -void IUnknownWrapper_Impl::getFuncDescForInvoke(const OUString & sFuncName, - const Sequence<Any> & seqArgs, - FUNCDESC** pFuncDesc) -{ - int nUnoArgs = seqArgs.getLength(); - const Any * arArgs = seqArgs.getConstArray(); - ITypeInfo* pInfo = getTypeInfo(); - - //If the last of the positional arguments is a PropertyPutArgument - //then obtain the type info for the property put operation. - - //The property value is always the last argument, in a positional argument list - //or in a list of named arguments. A PropertyPutArgument is actually a named argument - //hence it must not be put in an extra NamedArgument structure - if (nUnoArgs > 0 && - arArgs[nUnoArgs - 1].getValueType() == getCppuType((PropertyPutArgument*) 0)) - { - // DISPATCH_PROPERTYPUT - FuncDesc aDescGet(pInfo); - FuncDesc aDescPut(pInfo); - VarDesc aVarDesc(pInfo); - getPropDesc(sFuncName, & aDescGet, & aDescPut, & aVarDesc); - if ( ! aDescPut) - { - throw IllegalArgumentException( - OUSTR("[automation bridge] The object does not have a writeable property: ") - + sFuncName, Reference<XInterface>(), 0); - } - *pFuncDesc = aDescPut.Detach(); - } - else - { // DISPATCH_METHOD - FuncDesc aFuncDesc(pInfo); - getFuncDesc(sFuncName, & aFuncDesc); - if ( ! aFuncDesc) - { - // Fallback: DISPATCH_PROPERTYGET can mostly be called as - // DISPATCH_METHOD - ITypeInfo * pInfo = getTypeInfo(); - FuncDesc aDescPut(pInfo); - VarDesc aVarDesc(pInfo); - getPropDesc(sFuncName, & aFuncDesc, & aDescPut, & aVarDesc); - if ( ! aFuncDesc ) - { - throw IllegalArgumentException( - OUSTR("[automation bridge] The object does not have a function" - "or readable property \"") - + sFuncName, Reference<XInterface>(), 0); - } - } - *pFuncDesc = aFuncDesc.Detach(); - } -} -bool IUnknownWrapper_Impl::getDispid(const OUString& sFuncName, DISPID * id) -{ - OSL_ASSERT(m_spDispatch); - LPOLESTR lpsz = const_cast<LPOLESTR> (reinterpret_cast<LPCOLESTR>(sFuncName.getStr())); - HRESULT hr = m_spDispatch->GetIDsOfNames(IID_NULL, &lpsz, 1, LOCALE_USER_DEFAULT, id); - return hr == S_OK ? true : false; -} -void IUnknownWrapper_Impl::getFuncDesc(const OUString & sFuncName, FUNCDESC ** pFuncDesc) - -{ - OSL_ASSERT( * pFuncDesc == 0); - buildComTlbIndex(); - typedef TLBFuncIndexMap::const_iterator cit; - typedef TLBFuncIndexMap::iterator it; - //We assume there is only one entry with the function name. A property - //would have two entries. - cit itIndex= m_mapComFunc.find(sFuncName); - if (itIndex == m_mapComFunc.end()) - { - //try case insensive with IDispatch::GetIDsOfNames - DISPID id; - if (getDispid(sFuncName, &id)) - { - CComBSTR memberName; - unsigned int pcNames=0; - // get the case sensitive name - if( SUCCEEDED(getTypeInfo()->GetNames( id, & memberName, 1, &pcNames))) - { - //get the associated index and add an entry to the map - //with the name sFuncName which differs in the casing of the letters to - //the actual name as obtained from ITypeInfo - OUString sRealName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName))); - cit itOrg = m_mapComFunc.find(sRealName); - OSL_ASSERT(itOrg != m_mapComFunc.end()); - // maybe this is a property, if so we need - // to store either both id's ( put/get ) or - // just the get. Storing both is more consistent - pair<cit, cit> pItems = m_mapComFunc.equal_range( sRealName ); - for ( ;pItems.first != pItems.second; ++pItems.first ) - m_mapComFunc.insert( TLBFuncIndexMap::value_type ( make_pair(sFuncName, pItems.first->second ) )); - itIndex = - m_mapComFunc.find( sFuncName ); - } - } - } - -#if OSL_DEBUG_LEVEL >= 1 - // There must only be one entry if sFuncName represents a function or two - // if it is a property - pair<cit, cit> p = m_mapComFunc.equal_range(sFuncName.toAsciiLowerCase()); - int numEntries = 0; - for ( ;p.first != p.second; p.first ++, numEntries ++); - OSL_ASSERT( ! (numEntries > 3) ); -#endif - if( itIndex != m_mapComFunc.end()) - { - ITypeInfo* pType= getTypeInfo(); - FUNCDESC * pDesc = NULL; - if (SUCCEEDED(pType->GetFuncDesc(itIndex->second, & pDesc))) - { - if (pDesc->invkind == INVOKE_FUNC) - { - (*pFuncDesc) = pDesc; - } - else - { - pType->ReleaseFuncDesc(pDesc); - } - } - else - { - throw BridgeRuntimeError(OUSTR("[automation bridge] Could not get " - "FUNCDESC for ") + sFuncName); - } - } - //else no entry found for sFuncName, pFuncDesc will not be filled in -} - -void IUnknownWrapper_Impl::getPropDesc(const OUString & sFuncName, FUNCDESC ** pFuncDescGet, - FUNCDESC** pFuncDescPut, VARDESC** pVarDesc) -{ - OSL_ASSERT( * pFuncDescGet == 0 && * pFuncDescPut == 0); - buildComTlbIndex(); - typedef TLBFuncIndexMap::const_iterator cit; - pair<cit, cit> p = m_mapComFunc.equal_range(sFuncName); - if (p.first == m_mapComFunc.end()) - { - //try case insensive with IDispatch::GetIDsOfNames - DISPID id; - if (getDispid(sFuncName, &id)) - { - CComBSTR memberName; - unsigned int pcNames=0; - // get the case sensitive name - if( SUCCEEDED(getTypeInfo()->GetNames( id, & memberName, 1, &pcNames))) - { - //As opposed to getFuncDesc, we do not add the value because we would - // need to find the get and set description for the property. This would - //mean to iterate over all FUNCDESCs again. - p = m_mapComFunc.equal_range(OUString(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName)))); - } - } - } - - for ( int i = 0 ;p.first != p.second; p.first ++, i ++) - { - // There are a maximum of two entries, property put and property get - OSL_ASSERT( ! (i > 2) ); - ITypeInfo* pType= getTypeInfo(); - FUNCDESC * pFuncDesc = NULL; - if (SUCCEEDED( pType->GetFuncDesc(p.first->second, & pFuncDesc))) - { - if (pFuncDesc->invkind == INVOKE_PROPERTYGET) - { - (*pFuncDescGet) = pFuncDesc; - } - else if (pFuncDesc->invkind == INVOKE_PROPERTYPUT || - pFuncDesc->invkind == INVOKE_PROPERTYPUTREF) - { - //a property can have 3 entries, put, put ref, get - // If INVOKE_PROPERTYPUTREF or INVOKE_PROPERTYPUT is used - //depends on what is found first. - if ( * pFuncDescPut) - { - //we already have found one - pType->ReleaseFuncDesc(pFuncDesc); - } - else - { - (*pFuncDescPut) = pFuncDesc; - } - } - else - { - pType->ReleaseFuncDesc(pFuncDesc); - } - } - //ITypeInfo::GetFuncDesc may even provide a funcdesc for a VARDESC - // with invkind = INVOKE_FUNC. Since this function should only return - //a value for a real property (XInvokation::hasMethod, ..::hasProperty - //we need to make sure that sFuncName represents a real property. - VARDESC * pVD = NULL; - if (SUCCEEDED(pType->GetVarDesc(p.first->second, & pVD))) - (*pVarDesc) = pVD; - } - //else no entry for sFuncName, pFuncDesc will not be filled in -} - -VARTYPE IUnknownWrapper_Impl::getUserDefinedElementType( ITypeInfo* pTypeInfo, const DWORD nHrefType ) -{ - VARTYPE _type( VT_NULL ); - if ( pTypeInfo ) - { - CComPtr<ITypeInfo> spRefInfo; - pTypeInfo->GetRefTypeInfo( nHrefType, &spRefInfo.p ); - if ( spRefInfo ) - { - TypeAttr attr( spRefInfo ); - spRefInfo->GetTypeAttr( &attr ); - if ( attr->typekind == TKIND_ENUM ) - { - // We use the type of the first enum value. - if ( attr->cVars == 0 ) - { - throw BridgeRuntimeError(OUSTR("[automation bridge] Could not obtain type description")); - } - VarDesc var( spRefInfo ); - spRefInfo->GetVarDesc( 0, &var ); - _type = var->lpvarValue->vt; - } - else if ( attr->typekind == TKIND_INTERFACE ) - { - _type = VT_UNKNOWN; - } - else if ( attr->typekind == TKIND_DISPATCH ) - { - _type = VT_DISPATCH; - } - else if ( attr->typekind == TKIND_ALIAS ) - { - // TKIND_ALIAS is a type that is an alias for another type. So get that alias type. - _type = getUserDefinedElementType( pTypeInfo, attr->tdescAlias.hreftype ); - } - else - { - throw BridgeRuntimeError( OUSTR("[automation bridge] Unhandled user defined type.") ); - } - } - } - return _type; -} - -VARTYPE IUnknownWrapper_Impl::getElementTypeDesc(const TYPEDESC *desc) -{ - VARTYPE _type( VT_NULL ); - - if (desc->vt == VT_PTR) - { - _type = getElementTypeDesc(desc->lptdesc); - _type |= VT_BYREF; - } - else if (desc->vt == VT_SAFEARRAY) - { - _type = getElementTypeDesc(desc->lptdesc); - _type |= VT_ARRAY; - } - else if (desc->vt == VT_USERDEFINED) - { - ITypeInfo* thisInfo = getTypeInfo(); //kept by this instance - _type = getUserDefinedElementType( thisInfo, desc->hreftype ); - } - else - { - _type = desc->vt; - } - return _type; -} - -void IUnknownWrapper_Impl::buildComTlbIndex() -{ - if ( ! m_bComTlbIndexInit) - { - MutexGuard guard(getBridgeMutex()); - { - if ( ! m_bComTlbIndexInit) - { - OUString sError; - ITypeInfo* pType= getTypeInfo(); - TypeAttr typeAttr(pType); - if( SUCCEEDED( pType->GetTypeAttr( &typeAttr))) - { - for( long i= 0; i < typeAttr->cFuncs; i++) - { - FuncDesc funcDesc(pType); - if( SUCCEEDED( pType->GetFuncDesc( i, &funcDesc))) - { - CComBSTR memberName; - unsigned int pcNames=0; - if( SUCCEEDED(pType->GetNames( funcDesc->memid, & memberName, 1, &pcNames))) - { - OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName))); - m_mapComFunc.insert( TLBFuncIndexMap::value_type( usName, i)); - } - else - { - sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \ - "ITypeInfo::GetNames failed."); - } - } - else - sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \ - "ITypeInfo::GetFuncDesc failed."); - } - - //If we create an Object in JScript and a a property then it - //has VARDESC instead of FUNCDESC - for (long i = 0; i < typeAttr->cVars; i++) - { - VarDesc varDesc(pType); - if (SUCCEEDED(pType->GetVarDesc(i, & varDesc))) - { - CComBSTR memberName; - unsigned int pcNames = 0; - if (SUCCEEDED(pType->GetNames(varDesc->memid, & memberName, 1, &pcNames))) - { - if (varDesc->varkind == VAR_DISPATCH) - { - OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName))); - m_mapComFunc.insert(TLBFuncIndexMap::value_type( - usName, i)); - } - } - else - { - sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \ - "ITypeInfo::GetNames failed."); - } - } - else - sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \ - "ITypeInfo::GetVarDesc failed."); - - } - } - else - sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \ - "ITypeInfo::GetTypeAttr failed."); - - if (sError.getLength()) - { - throw BridgeRuntimeError(sError); - } - - m_bComTlbIndexInit = true; - } - } - } -} - -ITypeInfo* IUnknownWrapper_Impl::getTypeInfo() -{ - if( !m_spDispatch) - { - throw BridgeRuntimeError(OUSTR("The object has no IDispatch interface!")); - } - - if( !m_spTypeInfo ) - { - MutexGuard guard(getBridgeMutex()); - if( ! m_spTypeInfo) - { - CComPtr< ITypeInfo > spType; - if( SUCCEEDED( m_spDispatch->GetTypeInfo( 0, LOCALE_USER_DEFAULT, &spType.p))) - - { - OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); - - //If this is a dual interface then TYPEATTR::typekind is usually TKIND_INTERFACE - //We need to get the type description for TKIND_DISPATCH - TypeAttr typeAttr(spType.p); - if( SUCCEEDED(spType->GetTypeAttr( &typeAttr))) - { - if (typeAttr->typekind == TKIND_INTERFACE && - typeAttr->wTypeFlags & TYPEFLAG_FDUAL) - { - HREFTYPE refDispatch; - if (SUCCEEDED(spType->GetRefTypeOfImplType(::sal::static_int_cast< UINT, int >( -1 ), &refDispatch))) - { - CComPtr<ITypeInfo> spTypeDisp; - if (SUCCEEDED(spType->GetRefTypeInfo(refDispatch, & spTypeDisp))) - m_spTypeInfo= spTypeDisp; - } - else - { - throw BridgeRuntimeError( - OUSTR("[automation bridge] Could not obtain type information " - "for dispatch interface." )); - } - } - else if (typeAttr->typekind == TKIND_DISPATCH) - { - m_spTypeInfo= spType; - } - else - { - throw BridgeRuntimeError( - OUSTR("[automation bridge] Automation object does not " - "provide type information.")); - } - } - } - else - { - throw BridgeRuntimeError(OUSTR("[automation bridge]The dispatch object does not " - "support ITypeInfo!")); - } - } - } - return m_spTypeInfo; -} - -} // end namespace - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |