/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// 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.
std::unordered_map<sal_uIntPtr, sal_uIntPtr> 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 AdapterToWrapperMap 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.
std::unordered_map<sal_uIntPtr,sal_uIntPtr> WrapperToAdapterMap;
IUnknownWrapper::~IUnknownWrapper()
{
o2u_attachCurrentThread();
MutexGuard guard(getBridgeMutex());
XInterface * xIntRoot = static_cast<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 auto it= WrapperToAdapterMap.find( reinterpret_cast<sal_uIntPtr>(xIntRoot)); if( it != WrapperToAdapterMap.end())
{
sal_uIntPtr adapter= it->second;
auto it_c= ComPtrToWrapperMap.find( reinterpret_cast<sal_uIntPtr>(m_spUnknown.p)); if(it_c != ComPtrToWrapperMap.end())
ComPtrToWrapperMap.erase(it_c);
}
Any IUnknownWrapper::queryInterface(const Type& t)
{ if (t == cppu::UnoType<XDefaultMethod>::get() && !m_bHasDfltMethod ) return Any(); if (t == cppu::UnoType<XDefaultProperty>::get() && !m_bHasDfltProperty ) return Any(); if ( ( t == cppu::UnoType<XInvocation>::get() || t == cppu::UnoType<XAutomationInvocation>::get() ) && !m_spDispatch) return Any(); // XDirectInvocation seems to be an oracle replacement for XAutomationInvocation, however it is flawed especially 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 separate 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 moment at least I would prefer the basic // runtime to call XAutomationInvocation instead of XDirectInvoke return WeakImplHelper<XBridgeSupplier2,
XInitialization, XAutomationObject, XDefaultProperty, XDefaultMethod, XDirectInvocation, XAutomationInvocation >::queryInterface(t);
}
Any SAL_CALL IUnknownWrapper::invoke( const OUString& aFunctionName, const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex,
Sequence< Any >& aOutParam )
{ if ( ! m_spDispatch )
{ throw RuntimeException( "[automation bridge] The object does not have an IDispatch interface");
}
void SAL_CALL IUnknownWrapper::setValue( const OUString& aPropertyName, const Any& aValue )
{ if ( ! m_spDispatch )
{ throw RuntimeException( "[automation bridge] The object does not have an IDispatch interface");
} 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("[automation bridge]Property \"" + aPropertyName + "\" is not supported"); throw UnknownPropertyException(msg);
}
Any SAL_CALL IUnknownWrapper::getValue( const OUString& aPropertyName )
{ if ( ! m_spDispatch )
{ throw RuntimeException( "[automation bridge] The object does not have an IDispatch interface");
}
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 a 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 == "$GetTypeName" )
{ if ( pInfo && m_sTypeName.getLength() == 0 )
{
m_sTypeName = "IDispatch";
CComBSTR sName;
if ( SUCCEEDED( pInfo->GetDocumentation( -1, &sName, nullptr, nullptr, nullptr ) ) )
{
OUString sTmp( o3tl::toU(LPCOLESTR(sName))); if ( sTmp.startsWith("_") )
sTmp = sTmp.copy(1); // do we own the memory for pTypeLib, msdn doc is vague // I'll assume we do
CComPtr< ITypeLib > pTypeLib; unsignedint index; if ( SUCCEEDED( pInfo->GetContainingTypeLib( &pTypeLib.p, &index )) )
{ if ( SUCCEEDED( pTypeLib->GetDocumentation( -1, &sName, nullptr, nullptr, nullptr ) ) )
{
OUString sLibName( o3tl::toU(LPCOLESTR(sName)));
m_sTypeName = sLibName + "." + 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("[automation bridge]Property \"" + aPropertyName + "\" is not supported"); throw UnknownPropertyException(msg);
} // write-only should not be possible
OSL_ASSERT( aDescGet || ! aDescPut);
// 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);
}
sal_Bool SAL_CALL IUnknownWrapper::hasMethod( const OUString& aName )
{ if ( ! m_spDispatch )
{ throw RuntimeException( "[automation bridge] The object does not have an IDispatch interface");
} bool ret = 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 = true;
} else
ret = true;
} catch (const BridgeRuntimeError& e)
{ throw RuntimeException(e.message);
} catch (const Exception & e)
{
css::uno::Any anyEx = cppu::getCaughtException(); throw css::lang::WrappedTargetRuntimeException("[automation bridge] unexpected exception in " "IUnknownWrapper::hasMethod ! Message : \n" +
e.Message,
nullptr, anyEx );
} catch (...)
{ throw RuntimeException("[automation bridge] unexpected exception in " "IUnknownWrapper::hasMethod !");
} return ret;
}
sal_Bool SAL_CALL IUnknownWrapper::hasProperty( const OUString& aName )
{ if ( ! m_spDispatch )
{ throw RuntimeException("[automation bridge] The object does not have an " "IDispatch interface");
} bool ret = false; try
{
o2u_attachCurrentThread();
// we should probably just check the func kind // basic has been modified to handle properties ( 'get' ) props at // least with parameters // 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 = true;
}
} catch (const BridgeRuntimeError& e)
{ throw RuntimeException(e.message);
} catch (const Exception & e)
{
css::uno::Any anyEx = cppu::getCaughtException(); throw css::lang::WrappedTargetRuntimeException("[automation bridge] unexpected exception in " "IUnknownWrapper::hasProperty ! Message : \n" +
e.Message,
nullptr, anyEx );
// 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. bool bJScriptObject= isJScriptObject();
std::unique_ptr<CComVariant[]> sarParams;
std::unique_ptr<CComVariant[]> sarParamsRef;
CComVariant *pVarParams= nullptr;
CComVariant *pVarParamsRef= nullptr; bool bConvRet= true;
if( methodDesc.is())
{
pMethod = reinterpret_cast<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 && ! pMethod->pParams[i].bOut)
{
anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]);
} // Out parameter + in/out parameter elseif( pMethod->pParams[i].bOut )
{
CComVariant var; if(pMethod->pParams[i].bIn)
{
anyToVariant( & var,Params[i]);
pVarParamsRef[outParamIndex] = var;
}
switch( pMethod->pParams[i].pTypeRef->eTypeClass)
{ case typelib_TypeClass_INTERFACE: case typelib_TypeClass_STRUCT: if( ! pMethod->pParams[i].bIn)
{
pVarParamsRef[ outParamIndex].vt= VT_DISPATCH;
pVarParamsRef[ outParamIndex].pdispVal= nullptr;
}
pVarParams[parameterCount - i -1].vt = VT_DISPATCH | VT_BYREF;
pVarParams[parameterCount - i -1].ppdispVal= &pVarParamsRef[outParamIndex].pdispVal; break; case typelib_TypeClass_ENUM: case typelib_TypeClass_LONG: case typelib_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 typelib_TypeClass_SEQUENCE: if( ! pMethod->pParams[i].bIn)
{
pVarParamsRef[ outParamIndex].vt = VT_ARRAY| VT_VARIANT;
pVarParamsRef[ outParamIndex].parray= nullptr;
}
pVarParams[parameterCount - i -1].vt = VT_ARRAY| VT_BYREF | VT_VARIANT;
pVarParams[parameterCount - i -1].pparray= &pVarParamsRef[outParamIndex].parray; break; case typelib_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 typelib_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 typelib_TypeClass_STRING: if( ! pMethod->pParams[i].bIn)
{
pVarParamsRef[ outParamIndex].vt = VT_BSTR;
pVarParamsRef[ outParamIndex].bstrVal= nullptr;
}
pVarParams[parameterCount - i -1].vt = VT_BSTR| VT_BYREF;
pVarParams[parameterCount - i -1].pbstrVal=
& pVarParamsRef[outParamIndex].bstrVal; break;
case typelib_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 typelib_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 typelib_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 typelib_TypeClass_CHAR: case typelib_TypeClass_SHORT: case typelib_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 a JScriptObject
{ int i = 0; try
{ for( ; i< parameterCount; i++)
{ // In parameter if( pMethod->pParams[i].bIn && ! pMethod->pParams[i].bOut)
{
anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]);
} // Out parameter + in/out parameter elseif( pMethod->pParams[i].bOut )
{
CComObject<JScriptOutParam>* pParamObject; if( !SUCCEEDED( CComObject<JScriptOutParam>::CreateInstance( &pParamObject)))
{ throw BridgeRuntimeError( "[automation bridge]IUnknownWrapper::" "invokeWithDispIdUnoTlb\n" "Could not create out parameter at index: " +
OUString::number(static_cast<sal_Int32>(i)));
}
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 ) // in / out
{
CComVariant varParam;
anyToVariant( &varParam, Params.getConstArray()[i]);
CComDispatchDriver dispDriver( pDisp); if(FAILED( dispDriver.PutPropertyByName( L"0", &varParam))) throw BridgeRuntimeError( "[automation bridge]IUnknownWrapper::" "invokeWithDispIdUnoTlb\n" "Could not set property \"0\" for the in/out " "param!");
}
}
}
} 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(false);
}
// 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); auto pOutParamIndex = OutParamIndex.getArray();
OutParam.realloc( outParameterCount); auto pOutParam = OutParam.getArray();
sal_Int32 outIndex=0; int i = 0; try
{ for( ; i < parameterCount; i++)
{ if( pMethod->pParams[i].bOut )
{
pOutParamIndex[outIndex]= static_cast<sal_Int16>(i);
Any outAny; if( !bJScriptObject)
{
variantToAny( &pVarParamsRef[outIndex], outAny,
Type(pMethod->pParams[i].pTypeRef), false);
pOutParam[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), false);
pOutParam[outParameterCount - 1 - outIndex++]= outAny;
} else
bConvRet= false;
} else
bConvRet= false;
} else
bConvRet= 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), false); else
variantToAny(&varResult, ret, false);
} catch (IllegalArgumentException & e)
{
e.Message = "[automation bridge]IUnknownWrapper::invokeWithDispIdUnoTlb\n" "Could not convert return value! \n Message: \n" + e.Message; throw;
} catch (CannotConvertException & e)
{
e.Message = "[automation bridge]IUnknownWrapper::invokeWithDispIdUnoTlb\n" "Could not convert return value! \n Message: \n" + e.Message; throw;
}
}
}
if( !bConvRet) // conversion of return or out parameter failed throw CannotConvertException("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("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("call to OLE object failed", static_cast<XInterface*>( static_cast<XWeak*>(this)), ::sal::static_int_cast< sal_Int16, unsignedint >( uArgErr )); break; case DISP_E_TYPEMISMATCH: throw CannotConvertException("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("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::initialize( const Sequence< Any >& aArguments )
{ // 1.parameter is IUnknown // 2.parameter is a boolean which indicates if the COM pointer was an IUnknown or IDispatch // 3.parameter is a Sequence<Type>
o2u_attachCurrentThread();
OSL_ASSERT(aArguments.getLength() == 3);
ITypeInfo* pType = nullptr; 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( const BridgeRuntimeError& )
{} catch( const Exception& )
{}
if ( pType )
{ try
{ // Get Default member
CComBSTR defaultMemberName; if ( SUCCEEDED( pType->GetDocumentation(0, &defaultMemberName, nullptr, nullptr, nullptr ) ) )
{
OUString usName(o3tl::toU(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( "[automation bridge]IUnknownWrapper::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 ( const BridgeRuntimeError & e )
{ throw RuntimeException( e.message );
} catch( const Exception& e )
{
css::uno::Any anyEx = cppu::getCaughtException(); throw css::lang::WrappedTargetRuntimeException( "[automation bridge] unexpected exception in IUnknownWrapper::initialize() error message: \n" + e.Message,
nullptr, anyEx );
}
}
}
if ( !m_spDispatch )
{ throw RuntimeException( "[automation bridge] The object does not have an IDispatch interface");
}
o2u_attachCurrentThread();
DISPID dispid; if ( !getDispid( aName, &dispid ) ) throw IllegalArgumentException( "[automation bridge] The object does not have a function or property "
+ aName, Reference<XInterface>(), 0);
// Determine the number of named arguments for ( uno::Any const & any : aParams ) if ( any.getValueType() == cppu::UnoType<NamedArgument>::get() )
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;
int cNamedArg = 0; for ( size_t nInd = 0; nInd < dispparams.cArgs; nInd++ )
{ if (auto v = o3tl::tryAccess<NamedArgument>(aParams[nInd]))
{ const NamedArgument& arg = *v;
//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*>(o3tl::toW(arg.Name.getStr()));
}
}
// converting return value and out parameter back to UNO if ( SUCCEEDED( hInvRes ) )
variantToAny( &varResult, aResult, false ); else
{ // map error codes to exceptions
OUString message; switch ( hInvRes )
{ case S_OK: break; case DISP_E_BADPARAMCOUNT: throw IllegalArgumentException("[automation bridge] Wrong " "number of arguments. Object returned DISP_E_BADPARAMCOUNT.",
nullptr, 0); break; case DISP_E_BADVARTYPE: throw RuntimeException("[automation bridge] One or more " "arguments have the wrong type. Object returned " "DISP_E_BADVARTYPE.", nullptr); break; case DISP_E_EXCEPTION:
message = OUString::Concat("[automation bridge]: ")
+ std::u16string_view(o3tl::toU(excepinfo.bstrDescription),
::SysStringLen(excepinfo.bstrDescription)); throw InvocationTargetException(message, Reference<XInterface>(), Any()); break; case DISP_E_MEMBERNOTFOUND:
message = "[automation bridge]: A function with the name \""
+ aName + "\" is not supported. Object returned " "DISP_E_MEMBERNOTFOUND."; throw IllegalArgumentException(message, nullptr, 0); break; case DISP_E_NONAMEDARGS: throw IllegalArgumentException("[automation bridge] Object " "returned DISP_E_NONAMEDARGS",nullptr, ::sal::static_int_cast< sal_Int16, unsignedint >( uArgErr )); break; case DISP_E_OVERFLOW: throw CannotConvertException("[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("[automation bridge]Call failed." "Object returned DISP_E_PARAMNOTFOUND.",
nullptr, ::sal::static_int_cast< sal_Int16, unsignedint >( uArgErr )); break; case DISP_E_TYPEMISMATCH: throw CannotConvertException("[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("[automation bridge] Call failed. " "Object returned DISP_E_UNKNOWNINTERFACE.",nullptr); break; case DISP_E_UNKNOWNLCID: throw RuntimeException("[automation bridge] Call failed. " "Object returned DISP_E_UNKNOWNLCID.",nullptr); break; case DISP_E_PARAMNOTOPTIONAL: throw CannotConvertException("[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::hasMember( const OUString& aName )
{ if ( ! m_spDispatch )
{ throw RuntimeException( "[automation bridge] The object does not have an IDispatch interface");
}
/** @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::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::invokeWithDispIdComTlb(FuncDesc& aFuncDesc, const OUString& sFuncName, const Sequence< Any >& Params,
Sequence< sal_Int16 >& OutParamIndex,
Sequence< Any >& OutParam)
{
Any ret;
HRESULT result;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.