1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include "ole2uno.hxx"
23 #include "unoconversionutilities.hxx"
24 #include "servprov.hxx"
25 #include "unoobjw.hxx"
26 #include "oleobjw.hxx"
28 #include <com/sun/star/script/CannotConvertException.hpp>
29 #include <comphelper/automationinvokedzone.hxx>
30 #include <comphelper/windowsdebugoutput.hxx>
31 #include <comphelper/windowserrorstring.hxx>
32 #include <cppuhelper/queryinterface.hxx>
33 #include <cppuhelper/supportsservice.hxx>
34 #include <o3tl/any.hxx>
35 #include <o3tl/char16_t2wchar_t.hxx>
36 #include <ooo/vba/XHelperInterface.hpp>
37 #include <sal/log.hxx>
41 using namespace com::sun::star::lang
;
42 using namespace com::sun::star::uno
;
43 using namespace com::sun::star::bridge
;
44 using namespace com::sun::star::bridge::ModelDependent
;
48 // GUID used since 5.2 ( src569 m)
49 // {82154420-0FBF-11d4-8313-005004526AB4}
50 DEFINE_GUID(OID_ServiceManager
, 0x82154420, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50, 0x4, 0x52, 0x6a, 0xb4);
52 // FIXME: This GUID is just the above OID_ServiceManager with the
53 // initial part bumped by one. Is that good enough?
54 // {82154421-0FBF-11d4-8313-005004526AB4}
55 DEFINE_GUID(OID_LibreOfficeWriterApplication
, 0x82154421, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50, 0x4, 0x52, 0x6a, 0xb4);
58 // {82154425-0FBF-11d4-8313-005004526AB4}
59 DEFINE_GUID(OID_LibreOfficeCalcApplication
, 0x82154425, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50, 0x4, 0x52, 0x6a, 0xb4);
61 OneInstanceOleWrapper::OneInstanceOleWrapper( const Reference
<XMultiServiceFactory
>& smgr
,
62 std::function
<const Reference
<XInterface
>()> xInstFunction
)
64 , m_xInstFunction(xInstFunction
)
68 Reference
<XInterface
> xInt
= m_smgr
->createInstance("com.sun.star.bridge.oleautomation.BridgeSupplier");
72 Any a
= xInt
->queryInterface( cppu::UnoType
<XBridgeSupplier2
>::get() );
73 a
>>= m_bridgeSupplier
;
77 OneInstanceOleWrapper::~OneInstanceOleWrapper()
81 bool OneInstanceOleWrapper::registerClass(GUID
const * pGuid
)
85 o2u_attachCurrentThread();
87 hresult
= CoRegisterClassObject(
90 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
94 SAL_INFO("extensions.olebridge", "CoRegisterClassObject(" << *pGuid
<< "): " << WindowsErrorStringFromHRESULT(hresult
));
96 return (hresult
== NOERROR
);
99 bool OneInstanceOleWrapper::deregisterClass()
101 return CoRevokeClassObject(m_factoryHandle
) == NOERROR
;
104 COM_DECLSPEC_NOTHROW STDMETHODIMP
OneInstanceOleWrapper::QueryInterface(REFIID riid
, void ** ppv
)
106 if(IsEqualIID(riid
, IID_IUnknown
))
109 *ppv
= static_cast<IUnknown
*>(static_cast<IClassFactory
*>(this));
112 else if (IsEqualIID(riid
, IID_IClassFactory
))
115 *ppv
= static_cast<IClassFactory
*>(this);
120 return ResultFromScode(E_NOINTERFACE
);
123 COM_DECLSPEC_NOTHROW
STDMETHODIMP_(ULONG
) OneInstanceOleWrapper::AddRef()
125 return osl_atomic_increment( &m_refCount
);
128 COM_DECLSPEC_NOTHROW
STDMETHODIMP_(ULONG
) OneInstanceOleWrapper::Release()
130 MutexGuard
oGuard( Mutex::getGlobalMutex());
131 ULONG refCount
= --m_refCount
;
132 if ( m_refCount
== 0)
140 COM_DECLSPEC_NOTHROW STDMETHODIMP
OneInstanceOleWrapper::CreateInstance(IUnknown FAR
* punkOuter
,
144 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
146 SAL_INFO("extensions.olebridge", "OneInstanceOleWrapper::CreateInstance(" << riid
<< ")");
148 HRESULT ret
= ResultFromScode(E_UNEXPECTED
);
151 const Reference
<XInterface
>& xInst
= m_xInstFunction();
154 Any
usrAny(&xInst
, cppu::UnoType
<decltype(xInst
)>::get());
156 rtl_getGlobalProcessId( arId
);
157 Any oleAny
= m_bridgeSupplier
->createBridge(usrAny
,
158 Sequence
<sal_Int8
>( reinterpret_cast<sal_Int8
*>(arId
), 16),
163 if (auto v
= o3tl::tryAccess
<sal_uIntPtr
>(oleAny
))
165 VARIANT
* pVariant
= reinterpret_cast<VARIANT
*>(*v
);
167 if ((pVariant
->vt
== VT_UNKNOWN
) || (pVariant
->vt
== VT_DISPATCH
))
169 SAL_INFO("extensions.olebridge", "OneInstanceOleWrapper::Createbridge: punkVal=" << pVariant
->punkVal
);
170 ret
= pVariant
->punkVal
->QueryInterface(riid
, ppv
);
173 VariantClear(pVariant
);
174 CoTaskMemFree(pVariant
);
181 COM_DECLSPEC_NOTHROW STDMETHODIMP
OneInstanceOleWrapper::LockServer(BOOL
/*fLock*/)
186 OleConverter::OleConverter( const Reference
<XMultiServiceFactory
> &smgr
):
187 UnoConversionUtilities
<OleConverter
>( smgr
)
192 // The XMultiServiceFactory is later set by XInitialization
193 OleConverter::OleConverter( const Reference
<XMultiServiceFactory
>& smgr
, sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
):
194 UnoConversionUtilities
<OleConverter
>( smgr
, unoWrapperClass
, comWrapperClass
)
199 OleConverter::~OleConverter()
203 // XBridgeSupplier --------------------------------------------------------------
204 Any SAL_CALL
OleConverter::createBridge(const Any
& modelDepObject
,
205 const Sequence
< sal_Int8
>& ProcessId
,
206 sal_Int16 sourceModelType
,
207 sal_Int16 destModelType
)
211 rtl_getGlobalProcessId( arId
);
213 Sequence
< sal_Int8
> seqProcessId( reinterpret_cast<sal_Int8
*>(arId
), 16);
215 if ( seqProcessId
== ProcessId
)
217 if (sourceModelType
== UNO
)
219 if (destModelType
== UNO
)
221 // same model -> copy value only
222 ret
= modelDepObject
;
224 else if (destModelType
== OLE
)
226 // convert UNO any into variant
227 VARIANT
* pVariant
= static_cast<VARIANT
*>(CoTaskMemAlloc(sizeof(VARIANT
)));
228 VariantInit( pVariant
);
231 anyToVariant( pVariant
, modelDepObject
);
235 CoTaskMemFree(pVariant
);
236 throw IllegalArgumentException();
238 ret
.setValue(static_cast<void*>(&pVariant
), cppu::UnoType
<sal_uIntPtr
>::get());
241 throw IllegalArgumentException();
243 else if (sourceModelType
== OLE
)
245 auto v
= o3tl::tryAccess
<sal_uIntPtr
>(modelDepObject
);
248 throw IllegalArgumentException();
250 else if (destModelType
== OLE
)
252 // same model -> copy value only
253 VARIANT
* pVariant
= static_cast<VARIANT
*>(CoTaskMemAlloc(sizeof(VARIANT
)));
255 if (NOERROR
!= VariantCopy(pVariant
, reinterpret_cast<VARIANT
*>(*v
)))
257 CoTaskMemFree(pVariant
);
258 throw(IllegalArgumentException());
262 ret
.setValue(static_cast<void*>(&pVariant
), cppu::UnoType
<sal_uIntPtr
>::get());
265 else if (destModelType
== UNO
)
267 // convert variant into UNO any
268 VARIANT
* pVariant
= reinterpret_cast<VARIANT
*>(*v
);
271 variantToAny(pVariant
, ret
);
273 catch (const CannotConvertException
& e
)
275 throw IllegalArgumentException(
276 e
.Message
, nullptr, -1);
280 throw IllegalArgumentException();
284 throw IllegalArgumentException();
290 OUString
OleConverter::getImplementationName()
292 return m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
293 ? OUString("com.sun.star.comp.ole.OleConverter2")
294 : OUString("com.sun.star.comp.ole.OleConverterVar1");
297 sal_Bool
OleConverter::supportsService(OUString
const & ServiceName
)
299 return cppu::supportsService(this, ServiceName
);
302 css::uno::Sequence
<OUString
> OleConverter::getSupportedServiceNames()
304 if (m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
)
306 return css::uno::Sequence
<OUString
>{
307 "com.sun.star.bridge.OleBridgeSupplier2",
308 "com.sun.star.bridge.oleautomation.BridgeSupplier"};
310 return css::uno::Sequence
<OUString
>{
311 "com.sun.star.bridge.OleBridgeSupplierVar1"};
314 // XInitialize ------------------------------------------------------------------------------
315 // the first argument is an XMultiServiceFactory if at all
316 void SAL_CALL
OleConverter::initialize( const Sequence
< Any
>& aArguments
)
318 if( aArguments
.getLength() == 1 && aArguments
[0].getValueTypeClass() == TypeClass_INTERFACE
)
320 Reference
< XInterface
> xInt
;
321 aArguments
[0] >>= xInt
;
322 Reference
<XMultiServiceFactory
> xMulti( xInt
, UNO_QUERY
);
323 m_smgrRemote
= xMulti
;
327 // UnoConversionUtilities -------------------------------------------------------------------
328 Reference
< XInterface
> OleConverter::createUnoWrapperInstance()
330 if( m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
)
332 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new InterfaceOleWrapper(
333 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
334 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
336 else if( m_nUnoWrapperClass
== UNO_OBJECT_WRAPPER_REMOTE_OPT
)
338 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new UnoObjectWrapperRemoteOpt(
339 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
340 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
343 return Reference
<XInterface
>();
346 Reference
< XInterface
> OleConverter::createComWrapperInstance()
348 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new IUnknownWrapper(
349 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
350 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
353 OleClient::OleClient( const Reference
<XMultiServiceFactory
>& smgr
):
354 UnoConversionUtilities
<OleClient
>( smgr
)
356 Reference
<XInterface
> xInt
;// = m_smgr->createInstance(L"com.sun.star.bridge.OleBridgeSupplier2");
360 Any a
= xInt
->queryInterface(cppu::UnoType
<XBridgeSupplier2
>::get() );
361 a
>>= m_bridgeSupplier
;
365 OleClient::~OleClient()
369 Sequence
< OUString
> SAL_CALL
OleClient::getAvailableServiceNames()
371 Sequence
< OUString
> ret
;
376 OUString
OleClient::getImplementationName()
378 return "com.sun.star.comp.ole.OleClient";
381 sal_Bool
OleClient::supportsService(OUString
const & ServiceName
)
383 return cppu::supportsService(this, ServiceName
);
386 css::uno::Sequence
<OUString
> OleClient::getSupportedServiceNames()
388 return css::uno::Sequence
<OUString
>{
389 "com.sun.star.bridge.OleObjectFactory",
390 "com.sun.star.bridge.oleautomation.Factory"};
393 Reference
<XInterface
> SAL_CALL
OleClient::createInstance(const OUString
& ServiceSpecifier
)
395 Reference
<XInterface
> ret
;
397 IUnknown
* pUnknown
= nullptr;
400 o2u_attachCurrentThread();
402 result
= CLSIDFromProgID(
403 o3tl::toW(ServiceSpecifier
.getStr()), //Pointer to the ProgID
404 &classId
); //Pointer to the CLSID
407 if (result
== NOERROR
)
409 result
= CoCreateInstance(
410 classId
, //Class identifier (CLSID) of the object
411 nullptr, //Pointer to whether object is or isn't part of an aggregate
412 CLSCTX_SERVER
, //Context for running executable code
413 IID_IUnknown
, //Reference to the identifier of the interface
414 reinterpret_cast<void**>(&pUnknown
)); //Address of output variable that receives
415 // the interface pointer requested in riid
418 if (pUnknown
!= nullptr)
423 V_VT(&variant
) = VT_UNKNOWN
;
424 V_UNKNOWN(&variant
) = pUnknown
;
425 // AddRef for Variant
428 // When the object is wrapped, then its refcount is increased
429 variantToAny(&variant
, any
);
430 if (any
.getValueTypeClass() == TypeClass_INTERFACE
)
434 pUnknown
->Release(); // CoCreateInstance
440 Reference
<XInterface
> SAL_CALL
OleClient::createInstanceWithArguments(const OUString
& ServiceSpecifier
, const Sequence
< Any
>& /*Arguments*/)
442 return createInstance( ServiceSpecifier
);
445 // UnoConversionUtilities -----------------------------------------------------------------------------
446 Reference
< XInterface
> OleClient::createUnoWrapperInstance()
448 if( m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
)
450 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new InterfaceOleWrapper(
451 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
452 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
454 else if( m_nUnoWrapperClass
== UNO_OBJECT_WRAPPER_REMOTE_OPT
)
456 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new UnoObjectWrapperRemoteOpt(
457 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
458 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
461 return Reference
< XInterface
>();
463 // UnoConversionUtilities -----------------------------------------------------------------------------
464 Reference
< XInterface
> OleClient::createComWrapperInstance( )
466 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new IUnknownWrapper(
467 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
468 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
471 OleServer::OleServer( const Reference
<XMultiServiceFactory
>& smgr
):
474 Reference
<XInterface
> xInt
= m_smgr
->createInstance("com.sun.star.bridge.oleautomation.BridgeSupplier");
478 Any a
= xInt
->queryInterface( cppu::UnoType
<XBridgeSupplier2
>::get() );
479 a
>>= m_bridgeSupplier
;
482 (void) provideInstance( [&]
486 &OID_ServiceManager
);
488 (void) provideInstance( [&]
490 // We want just one SwVbaGlobals for all Automation clients
491 static const Reference
<XInterface
> xWordGlobals
= m_smgr
->createInstance("ooo.vba.word.Globals");
492 const Reference
<ooo::vba::XHelperInterface
> xHelperInterface(xWordGlobals
, UNO_QUERY
);
493 Any aApplication
= xHelperInterface
->Application();
494 Reference
<XInterface
> xApplication
;
495 aApplication
>>= xApplication
;
498 &OID_LibreOfficeWriterApplication
);
500 (void) provideInstance( [&]
503 static const Reference
<XInterface
> xCalcGlobals
= m_smgr
->createInstance("ooo.vba.excel.Globals");
504 const Reference
<ooo::vba::XHelperInterface
> xHelperInterface(xCalcGlobals
, UNO_QUERY
);
505 Any aApplication
= xHelperInterface
->Application();
506 Reference
<XInterface
> xApplication
;
507 aApplication
>>= xApplication
;
510 &OID_LibreOfficeCalcApplication
);
513 OleServer::~OleServer()
515 for (auto const& elem
: m_wrapperList
)
517 elem
->deregisterClass();
520 m_wrapperList
.clear();
523 OUString
OleServer::getImplementationName()
525 return "com.sun.star.comp.ole.OleServer";
528 sal_Bool
OleServer::supportsService(OUString
const & ServiceName
)
530 return cppu::supportsService(this, ServiceName
);
533 css::uno::Sequence
<OUString
> OleServer::getSupportedServiceNames()
535 return css::uno::Sequence
<OUString
>{
536 "com.sun.star.bridge.OleApplicationRegistration",
537 "com.sun.star.bridge.oleautomation.ApplicationRegistration"};
540 bool OleServer::provideInstance(std::function
<const Reference
<XInterface
>()> xInstFunction
, GUID
const * guid
)
542 OneInstanceOleWrapper
* pWrapper
= new OneInstanceOleWrapper( m_smgr
, xInstFunction
);
545 m_wrapperList
.push_back(pWrapper
);
547 return pWrapper
->registerClass(guid
);
550 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */