/* -*- 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 .
*/
#include <vector>
#include "ole2uno.hxx"
#include "unoconversionutilities.hxx"
#include "servprov.hxx"
#include "unoobjw.hxx"
#include "oleobjw.hxx"
#include <com/sun/star/script/CannotConvertException.hpp>
#include <comphelper/automationinvokedzone.hxx>
#include <comphelper/windowsdebugoutput.hxx>
#include <comphelper/windowserrorstring.hxx>
#include <cppuhelper/queryinterface.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <o3tl/any.hxx>
#include <o3tl/char16_t2wchar_t.hxx>
#include <officecfg/Office/Common.hxx>
#include <ooo/vba/XHelperInterface.hpp>
#include <sal/log.hxx>
using namespace cppu;
using namespace osl;
using namespace com::sun::star::lang;
using namespace com::sun::star::uno;
using namespace com::sun::star::bridge;
using namespace com::sun::star::bridge::ModelDependent;
#include <initguid.h>
// GUID used since 5.2 ( src569 m)
// {82154420-0FBF-11d4-8313-005004526AB4}
DEFINE_GUID(OID_ServiceManager, 0x82154420, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50, 0x4, 0x
52, 0x6a, 0xb4);
// FIXME: This GUID is just the above OID_ServiceManager with the
// initial part bumped by one. Is that good enough?
// {82154421-0FBF-11d4-8313-005004526AB4}
DEFINE_GUID(OID_LibreOfficeWriterApplication, 0x82154421, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50, 0x4, 0x52, 0x6a, 0xb4);
// For Calc
// {82154425-0FBF-11d4-8313-005004526AB4}
DEFINE_GUID(OID_LibreOfficeCalcApplication, 0x82154425, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50, 0x4, 0x52, 0x6a, 0xb4);
OneInstanceOleWrapper::OneInstanceOleWrapper( const Reference<XMultiServiceFactory>& smgr,
std::function<const Reference<XInterface>()> xInstFunction )
: m_refCount(0)
, m_xInstFunction(xInstFunction)
, m_factoryHandle(0)
, m_smgr(smgr)
{
Reference<XInterface> xInt = m_smgr->createInstance("com.sun.star.bridge.oleautomation.BridgeSupplier" );
if (xInt.is())
{
Any a= xInt->queryInterface( cppu::UnoType<XBridgeSupplier2>::get() );
a >>= m_bridgeSupplier;
}
}
OneInstanceOleWrapper::~OneInstanceOleWrapper()
{
}
bool OneInstanceOleWrapper::registerClass(GUID const * pGuid)
{
HRESULT hresult;
o2u_attachCurrentThread();
hresult = CoRegisterClassObject(
*pGuid,
this ,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE,
&m_factoryHandle);
SAL_INFO("extensions.olebridge" , "CoRegisterClassObject(" << *pGuid << "): " << comphelper::WindowsErrorStringFromHRESULT(hresult));
return (hresult == NOERROR);
}
bool OneInstanceOleWrapper::deregisterClass()
{
return CoRevokeClassObject(m_factoryHandle) == NOERROR;
}
COM_DECLSPEC_NOTHROW STDMETHODIMP OneInstanceOleWrapper::QueryInterface(REFIID riid, void ** ppv)
{
if (IsEqualIID(riid, IID_IUnknown))
{
AddRef();
*ppv = static_cast <IUnknown*>(static_cast <IClassFactory*>(this ));
return NOERROR;
}
else if (IsEqualIID(riid, IID_IClassFactory))
{
AddRef();
*ppv = static_cast <IClassFactory*>(this );
return NOERROR;
}
*ppv = nullptr;
return ResultFromScode(E_NOINTERFACE);
}
COM_DECLSPEC_NOTHROW STDMETHODIMP_(ULONG) OneInstanceOleWrapper::AddRef()
{
return osl_atomic_increment( &m_refCount);
}
COM_DECLSPEC_NOTHROW STDMETHODIMP_(ULONG) OneInstanceOleWrapper::Release()
{
MutexGuard oGuard( Mutex::getGlobalMutex());
ULONG refCount = --m_refCount;
if ( m_refCount == 0)
{
delete this ;
}
return refCount;
}
COM_DECLSPEC_NOTHROW STDMETHODIMP OneInstanceOleWrapper::CreateInstance(IUnknown*,
REFIID riid, void ** ppv)
{
comphelper::Automation::AutomationInvokedZone aAutomationActive;
SAL_INFO("extensions.olebridge" , "OneInstanceOleWrapper::CreateInstance(" << riid << ")" );
if (officecfg::Office::Common::Security::Scripting::DisableOLEAutomation::get())
{
return ResultFromScode(E_NOINTERFACE);
}
HRESULT ret = ResultFromScode(E_UNEXPECTED);
const Reference<XInterface>& xInst = m_xInstFunction();
if (xInst.is())
{
Any usrAny(&xInst, cppu::UnoType<decltype(xInst)>::get());
sal_uInt8 arId[16];
rtl_getGlobalProcessId( arId);
Any oleAny = m_bridgeSupplier->createBridge(usrAny,
Sequence<sal_Int8>( reinterpret_cast <sal_Int8*>(arId), 16),
UNO,
OLE);
if (auto v = o3tl::tryAccess<sal_uIntPtr>(oleAny))
{
VARIANT* pVariant = reinterpret_cast <VARIANT*>(*v);
if ((pVariant->vt == VT_UNKNOWN) || (pVariant->vt == VT_DISPATCH))
{
SAL_INFO("extensions.olebridge" , "OneInstanceOleWrapper::Createbridge: punkVal=" << pVariant->punkVal);
ret = pVariant->punkVal->QueryInterface(riid, ppv);
}
VariantClear(pVariant);
CoTaskMemFree(pVariant);
}
}
return ret;
}
COM_DECLSPEC_NOTHROW STDMETHODIMP OneInstanceOleWrapper::LockServer(BOOL /*fLock*/)
{
return NOERROR;
}
OleConverter::OleConverter( const Reference<XMultiServiceFactory> &smgr):
UnoConversionUtilities<OleConverter>( smgr)
{
}
// The XMultiServiceFactory is later set by XInitialization
OleConverter::OleConverter( const Reference<XMultiServiceFactory>& smgr, sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass ):
UnoConversionUtilities<OleConverter>( smgr, unoWrapperClass, comWrapperClass )
{
}
OleConverter::~OleConverter()
{
}
// XBridgeSupplier --------------------------------------------------------------
Any SAL_CALL OleConverter::createBridge(const Any& modelDepObject,
const Sequence< sal_Int8 >& ProcessId,
sal_Int16 sourceModelType,
sal_Int16 destModelType)
{
Any ret;
sal_uInt8 arId[16];
rtl_getGlobalProcessId( arId );
Sequence< sal_Int8 > seqProcessId( reinterpret_cast <sal_Int8*>(arId), 16);
if ( seqProcessId == ProcessId)
{
if (sourceModelType == UNO)
{
if (destModelType == UNO)
{
// same model -> copy value only
ret = modelDepObject;
}
else if (destModelType == OLE)
{
// convert UNO any into variant
VARIANT* pVariant = static_cast <VARIANT*>(CoTaskMemAlloc(sizeof (VARIANT)));
VariantInit( pVariant);
try
{
anyToVariant( pVariant, modelDepObject);
}
catch (...)
{
CoTaskMemFree(pVariant);
throw IllegalArgumentException();
}
ret.setValue(static_cast <void *>(&pVariant), cppu::UnoType<sal_uIntPtr>::get());
}
else
throw IllegalArgumentException();
}
else if (sourceModelType == OLE)
{
auto v = o3tl::tryAccess<sal_uIntPtr>(modelDepObject);
if (!v)
{
throw IllegalArgumentException();
}
else if (destModelType == OLE)
{
// same model -> copy value only
VARIANT* pVariant = static_cast <VARIANT*>(CoTaskMemAlloc(sizeof (VARIANT)));
if (NOERROR != VariantCopy(pVariant, reinterpret_cast <VARIANT*>(*v)))
{
CoTaskMemFree(pVariant);
throw (IllegalArgumentException());
}
else
{
ret.setValue(static_cast <void *>(&pVariant), cppu::UnoType<sal_uIntPtr>::get());
}
}
else if (destModelType == UNO)
{
// convert variant into UNO any
VARIANT* pVariant = reinterpret_cast <VARIANT*>(*v);
try
{
variantToAny(pVariant, ret);
}
catch (const CannotConvertException & e)
{
throw IllegalArgumentException(
e.Message, nullptr, -1);
}
}
else
throw IllegalArgumentException();
}
else
throw IllegalArgumentException();
}
return ret;
}
OUString OleConverter::getImplementationName()
{
return m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL
? OUString("com.sun.star.comp.ole.OleConverter2" )
: OUString("com.sun.star.comp.ole.OleConverterVar1" );
}
sal_Bool OleConverter::supportsService(OUString const & ServiceName)
{
return cppu::supportsService(this , ServiceName);
}
css::uno::Sequence<OUString> OleConverter::getSupportedServiceNames()
{
if (m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL)
{
return css::uno::Sequence<OUString>{
"com.sun.star.bridge.OleBridgeSupplier2" ,
"com.sun.star.bridge.oleautomation.BridgeSupplier" };
}
return {"com.sun.star.bridge.OleBridgeSupplierVar1" };
}
// XInitialize ------------------------------------------------------------------------------
// the first argument is an XMultiServiceFactory if at all
void SAL_CALL OleConverter::initialize( const Sequence< Any >& aArguments )
{
if ( aArguments.getLength() == 1 && aArguments[0].getValueTypeClass() == TypeClass_INTERFACE)
{
Reference < XInterface > xInt;
aArguments[0] >>= xInt;
Reference <XMultiServiceFactory> xMulti( xInt, UNO_QUERY);
m_smgrRemote= xMulti;
}
}
// UnoConversionUtilities -------------------------------------------------------------------
Reference< XInterface > OleConverter::createUnoWrapperInstance()
{
if ( m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL)
{
Reference<XWeak> xWeak= static_cast <XWeak*>( new InterfaceOleWrapper(
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 > OleConverter::createComWrapperInstance()
{
Reference<XWeak> xWeak= static_cast <XWeak*>( new IUnknownWrapper(
m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
return Reference<XInterface>( xWeak, UNO_QUERY);
}
OleClient::OleClient( const Reference<XMultiServiceFactory>& smgr):
UnoConversionUtilities<OleClient>( smgr)
{
Reference<XInterface> xInt;// = m_smgr->createInstance(L"com.sun.star.bridge.OleBridgeSupplier2");
if (xInt.is())
{
Any a= xInt->queryInterface(cppu::UnoType<XBridgeSupplier2>::get() );
a >>= m_bridgeSupplier;
}
}
OleClient::~OleClient()
{
}
Sequence< OUString > SAL_CALL OleClient::getAvailableServiceNames()
{
Sequence< OUString > ret;
return ret;
}
OUString OleClient::getImplementationName()
{
return "com.sun.star.comp.ole.OleClient" ;
}
sal_Bool OleClient::supportsService(OUString const & ServiceName)
{
return cppu::supportsService(this , ServiceName);
}
css::uno::Sequence<OUString> OleClient::getSupportedServiceNames()
{
return css::uno::Sequence<OUString>{
"com.sun.star.bridge.OleObjectFactory" ,
"com.sun.star.bridge.oleautomation.Factory" };
}
Reference<XInterface> SAL_CALL OleClient::createInstance(const OUString& ServiceSpecifier)
{
Reference<XInterface> ret;
o2u_attachCurrentThread();
CComPtr<IUnknown> pUnknown;
pUnknown.CoCreateInstance(o3tl::toW(ServiceSpecifier.getStr()), nullptr, CLSCTX_SERVER);
if (pUnknown)
{
Any any;
CComVariant variant(pUnknown);
variantToAny(&variant, any);
if (any.getValueTypeClass() == TypeClass_INTERFACE)
{
any >>= ret;
}
}
return ret;
}
Reference<XInterface> SAL_CALL OleClient::createInstanceWithArguments(const OUString& ServiceSpecifier, const Sequence< Any >& /*Arguments*/)
{
return createInstance( ServiceSpecifier);
}
// UnoConversionUtilities -----------------------------------------------------------------------------
Reference< XInterface > OleClient::createUnoWrapperInstance()
{
if ( m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL)
{
Reference<XWeak> xWeak= static_cast <XWeak*>( new InterfaceOleWrapper(
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>();
}
// UnoConversionUtilities -----------------------------------------------------------------------------
Reference< XInterface > OleClient::createComWrapperInstance( )
{
Reference<XWeak> xWeak= static_cast <XWeak*>( new IUnknownWrapper(
m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
return Reference<XInterface>( xWeak, UNO_QUERY);
}
OleServer::OleServer( const Reference<XMultiServiceFactory>& smgr):
m_smgr( smgr)
{
Reference<XInterface> xInt = m_smgr->createInstance("com.sun.star.bridge.oleautomation.BridgeSupplier" );
if (xInt.is())
{
Any a= xInt->queryInterface( cppu::UnoType<XBridgeSupplier2>::get() );
a >>= m_bridgeSupplier;
}
(void ) provideInstance( [&]
{
return m_smgr;
},
&OID_ServiceManager );
(void ) provideInstance( [&]
{
// We want just one SwVbaGlobals for all Automation clients
static const Reference<XInterface> xWordGlobals = m_smgr->createInstance("ooo.vba.word.Globals" );
const Reference<ooo::vba::XHelperInterface> xHelperInterface(xWordGlobals, UNO_QUERY);
Any aApplication = xHelperInterface->Application();
Reference<XInterface> xApplication;
aApplication >>= xApplication;
return xApplication;
},
&OID_LibreOfficeWriterApplication );
(void ) provideInstance( [&]
{
// Ditto for sc
static const Reference<XInterface> xCalcGlobals = m_smgr->createInstance("ooo.vba.excel.Globals" );
const Reference<ooo::vba::XHelperInterface> xHelperInterface(xCalcGlobals, UNO_QUERY);
Any aApplication = xHelperInterface->Application();
Reference<XInterface> xApplication;
aApplication >>= xApplication;
return xApplication;
},
&OID_LibreOfficeCalcApplication );
}
OleServer::~OleServer()
{
for (auto const & elem : m_wrapperList)
{
elem->deregisterClass();
elem->Release();
}
m_wrapperList.clear();
}
OUString OleServer::getImplementationName()
{
return "com.sun.star.comp.ole.OleServer" ;
}
sal_Bool OleServer::supportsService(OUString const & ServiceName)
{
return cppu::supportsService(this , ServiceName);
}
css::uno::Sequence<OUString> OleServer::getSupportedServiceNames()
{
return css::uno::Sequence<OUString>{
"com.sun.star.bridge.OleApplicationRegistration" ,
"com.sun.star.bridge.oleautomation.ApplicationRegistration" };
}
bool OleServer::provideInstance(std::function<const Reference<XInterface>()> xInstFunction, GUID const * guid)
{
OneInstanceOleWrapper* pWrapper = new OneInstanceOleWrapper( m_smgr, xInstFunction );
pWrapper->AddRef();
m_wrapperList.push_back(pWrapper);
return pWrapper->registerClass(guid);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 C=95 H=91 G=92
¤ Dauer der Verarbeitung: 0.10 Sekunden
¤
*© Formatika GbR, Deutschland