Kaydet (Commit) 7873bba6 authored tarafından Tor Lillqvist's avatar Tor Lillqvist

Hack to make properties work better from Automation clients

There were a couple of problems apparent at this stage when using the
ooovbaapi things from a test Automation client (written in VBScript,
to be precise).

Accessing for instance the ActiveDocument property of an
ooo::vba::word::XGlobals instance worked fine. But properties of other
objects, like instances of ooo::vba::word::XDocument, did not work.

When attempting to access any property of an
ooo::vba::word::XDocument, the code ended up calling the hasProperty()
of SwVbaDocuemnt. That function is for checking a totally different
kind of "properties", namely named form controls. Why form controls
are con-fused with oovbaapi properties I don't know. Maybe it is
intentional and as expected when using the oovbaapi from the built-in
Basic interpreter in LibreOffice. Or then just an accident in history.
Still, surely it can't be changed, that would break Basic scripts
embedded in existing ODF documents.

Anyway, from an OLE Automation client, for instance when asking for
the Content property of an ooo::vba::word::XDocument object, we
definitely don't want any form control that happens to have the name
"Content". We want an object with two integer properties, Start and
End.

Make this work by always creating an invocation factory instead of
using the object itself. Pass the invocation factory's
createInstanceWithArguments() function an extra argument indicating
this is the case of use from OLE Automation.

In the Invocation_Impl class in the stoc module, when this extra
argument is noticed, set a new mbFromOLE flag. Modify the behaviour
slightly when that is true. I am not at all sure that this will work
in all cases, but let's see, at least for simple tests so far it had
the intended effect.

Another issue was that looking up these properties was case sensitive.
This is wrong at least from languages like VBScript. Use the mbFromOLE
flag also to affect the case sensitivity behaviour.

Maybe I should simply make sure that _xDirect is null in the
Automation case? _Direct (a reference to an XInvocation) being
non-null probably means that we are using the document interface's own
implementation of XInvocation, which is probably always wrong in the
OLE Automation case. (Just see the SwVbaDocument implementations of
hasProperty() and invoke(), for instance.)

Change-Id: I2fd174f69f430893aef538cc9bf2a99d1c86b567
Reviewed-on: https://gerrit.libreoffice.org/55023Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarTor Lillqvist <tml@collabora.com>
üst d4d64887
......@@ -1388,20 +1388,18 @@ void UnoConversionUtilities<T>::createUnoObjectWrapper(const Any & rObj, VARIANT
}
}
// If we have no UNO wrapper nor the IDispatch yet then we have to create
// a wrapper. For that we need an XInvocation from the UNO object.
// a wrapper. For that we need an XInvocation.
// get an XInvocation or create one using the invocation service
Reference<XInvocation> xInv(xInt, UNO_QUERY);
if ( ! xInv.is())
// create an XInvocation using the invocation service
Reference<XInvocation> xInv;
Reference<XSingleServiceFactory> xInvFactory= getInvocationFactory(rObj);
if (xInvFactory.is())
{
Reference<XSingleServiceFactory> xInvFactory= getInvocationFactory(rObj);
if (xInvFactory.is())
{
Sequence<Any> params(1);
params.getArray()[0] = rObj;
Reference<XInterface> xInt2 = xInvFactory->createInstanceWithArguments(params);
xInv.set(xInt2, UNO_QUERY);
}
Sequence<Any> params(2);
params.getArray()[0] = rObj;
params.getArray()[1] = makeAny(OUString("FromOLE"));
Reference<XInterface> xInt2 = xInvFactory->createInstanceWithArguments(params);
xInv.set(xInt2, UNO_QUERY);
}
if (xInv.is())
......
......@@ -99,7 +99,8 @@ class Invocation_Impl
public:
Invocation_Impl( const Any & rAdapted, const Reference<XTypeConverter> &,
const Reference<XIntrospection> &,
const Reference<XIdlReflection> & );
const Reference<XIdlReflection> &,
bool bFromOLE );
// XInterface
virtual Any SAL_CALL queryInterface( const Type & aType) override;
......@@ -213,6 +214,8 @@ private:
Reference<XExactName> _xENDirect, _xENIntrospection;
bool mbFromOLE;
};
......@@ -221,11 +224,13 @@ Invocation_Impl::Invocation_Impl
const Any & rAdapted,
const Reference<XTypeConverter> & rTC,
const Reference<XIntrospection> & rI,
const Reference<XIdlReflection> & rCR
const Reference<XIdlReflection> & rCR,
bool bFromOLE
)
: xTypeConverter( rTC )
, xIntrospection( rI )
, xCoreReflection( rCR )
, mbFromOLE( bFromOLE )
{
setMaterial( rAdapted );
}
......@@ -248,8 +253,9 @@ Any SAL_CALL Invocation_Impl::queryInterface( const Type & aType )
if( aType == cppu::UnoType<XExactName>::get())
{
// Invocation does not support XExactName, if direct object supports
// XInvocation, but not XExactName.
if ((_xDirect.is() && _xENDirect.is()) ||
// XInvocation, but not XExactName. Except when called from OLE Automation.
if (mbFromOLE ||
(_xDirect.is() && _xENDirect.is()) ||
(!_xDirect.is() && _xENIntrospection.is()))
{
return makeAny( Reference< XExactName >( static_cast< XExactName* >(this) ) );
......@@ -302,7 +308,8 @@ Any SAL_CALL Invocation_Impl::queryInterface( const Type & aType )
{
// Invocation does not support XInvocation2, if direct object supports
// XInvocation, but not XInvocation2.
if ( ( _xDirect.is() && _xDirect2.is()) ||
if ( mbFromOLE ||
( _xDirect.is() && _xDirect2.is()) ||
(!_xDirect.is() && _xIntrospectionAccess.is() ) )
{
return makeAny( Reference< XInvocation2 >( static_cast< XInvocation2* >(this) ) );
......@@ -345,7 +352,7 @@ void Invocation_Impl::setMaterial( const Any& rMaterial )
// First do this outside the guard
_xDirect.set( rMaterial, UNO_QUERY );
if( _xDirect.is() )
if( !mbFromOLE && _xDirect.is() )
{
// Consult object directly
_xElementAccess.set( _xDirect, UNO_QUERY );
......@@ -441,7 +448,7 @@ Reference<XIntrospectionAccess> Invocation_Impl::getIntrospection()
sal_Bool Invocation_Impl::hasMethod( const OUString& Name )
{
if (_xDirect.is())
if (!mbFromOLE && _xDirect.is())
return _xDirect->hasMethod( Name );
if( _xIntrospectionAccess.is() )
return _xIntrospectionAccess->hasMethod( Name, MethodConcept::ALL ^ MethodConcept::DANGEROUS );
......@@ -451,7 +458,7 @@ sal_Bool Invocation_Impl::hasMethod( const OUString& Name )
sal_Bool Invocation_Impl::hasProperty( const OUString& Name )
{
if (_xDirect.is())
if (!mbFromOLE && _xDirect.is())
return _xDirect->hasProperty( Name );
// PropertySet
if( _xIntrospectionAccess.is()
......@@ -466,7 +473,7 @@ sal_Bool Invocation_Impl::hasProperty( const OUString& Name )
Any Invocation_Impl::getValue( const OUString& PropertyName )
{
if (_xDirect.is())
if (!mbFromOLE && _xDirect.is())
return _xDirect->getValue( PropertyName );
try
{
......@@ -575,7 +582,7 @@ void Invocation_Impl::setValue( const OUString& PropertyName, const Any& Value )
Any Invocation_Impl::invoke( const OUString& FunctionName, const Sequence<Any>& InParams,
Sequence<sal_Int16>& OutIndices, Sequence<Any>& OutParams )
{
if (_xDirect.is())
if (!mbFromOLE && _xDirect.is())
return _xDirect->invoke( FunctionName, InParams, OutIndices, OutParams );
if (_xIntrospectionAccess.is())
......@@ -1084,17 +1091,26 @@ Reference<XInterface> InvocationService::createInstance()
Reference<XInterface> InvocationService::createInstanceWithArguments(
const Sequence<Any>& rArguments )
{
if (rArguments.getLength() == 2)
{
OUString aArg1;
if ((rArguments[1] >>= aArg1) &&
aArg1 == "FromOLE")
{
return Reference< XInterface >
( *new Invocation_Impl( *rArguments.getConstArray(),
xTypeConverter, xIntrospection, xCoreReflection, true ) );
}
}
if (rArguments.getLength() == 1)
{
return Reference< XInterface >
( *new Invocation_Impl( *rArguments.getConstArray(),
xTypeConverter, xIntrospection, xCoreReflection ) );
}
else
{
//TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
return Reference<XInterface>();
xTypeConverter, xIntrospection, xCoreReflection, false ) );
}
//TODO:throw( Exception("no default construction of invocation adapter possible!", *this) );
return Reference<XInterface>();
}
/// @throws RuntimeException
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment