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
*,
141 REFIID riid
, void** ppv
)
143 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
145 SAL_INFO("extensions.olebridge", "OneInstanceOleWrapper::CreateInstance(" << riid
<< ")");
147 HRESULT ret
= ResultFromScode(E_UNEXPECTED
);
149 const Reference
<XInterface
>& xInst
= m_xInstFunction();
152 Any
usrAny(&xInst
, cppu::UnoType
<decltype(xInst
)>::get());
154 rtl_getGlobalProcessId( arId
);
155 Any oleAny
= m_bridgeSupplier
->createBridge(usrAny
,
156 Sequence
<sal_Int8
>( reinterpret_cast<sal_Int8
*>(arId
), 16),
161 if (auto v
= o3tl::tryAccess
<sal_uIntPtr
>(oleAny
))
163 VARIANT
* pVariant
= reinterpret_cast<VARIANT
*>(*v
);
165 if ((pVariant
->vt
== VT_UNKNOWN
) || (pVariant
->vt
== VT_DISPATCH
))
167 SAL_INFO("extensions.olebridge", "OneInstanceOleWrapper::Createbridge: punkVal=" << pVariant
->punkVal
);
168 ret
= pVariant
->punkVal
->QueryInterface(riid
, ppv
);
171 VariantClear(pVariant
);
172 CoTaskMemFree(pVariant
);
179 COM_DECLSPEC_NOTHROW STDMETHODIMP
OneInstanceOleWrapper::LockServer(BOOL
/*fLock*/)
184 OleConverter::OleConverter( const Reference
<XMultiServiceFactory
> &smgr
):
185 UnoConversionUtilities
<OleConverter
>( smgr
)
190 // The XMultiServiceFactory is later set by XInitialization
191 OleConverter::OleConverter( const Reference
<XMultiServiceFactory
>& smgr
, sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
):
192 UnoConversionUtilities
<OleConverter
>( smgr
, unoWrapperClass
, comWrapperClass
)
197 OleConverter::~OleConverter()
201 // XBridgeSupplier --------------------------------------------------------------
202 Any SAL_CALL
OleConverter::createBridge(const Any
& modelDepObject
,
203 const Sequence
< sal_Int8
>& ProcessId
,
204 sal_Int16 sourceModelType
,
205 sal_Int16 destModelType
)
209 rtl_getGlobalProcessId( arId
);
211 Sequence
< sal_Int8
> seqProcessId( reinterpret_cast<sal_Int8
*>(arId
), 16);
213 if ( seqProcessId
== ProcessId
)
215 if (sourceModelType
== UNO
)
217 if (destModelType
== UNO
)
219 // same model -> copy value only
220 ret
= modelDepObject
;
222 else if (destModelType
== OLE
)
224 // convert UNO any into variant
225 VARIANT
* pVariant
= static_cast<VARIANT
*>(CoTaskMemAlloc(sizeof(VARIANT
)));
226 VariantInit( pVariant
);
229 anyToVariant( pVariant
, modelDepObject
);
233 CoTaskMemFree(pVariant
);
234 throw IllegalArgumentException();
236 ret
.setValue(static_cast<void*>(&pVariant
), cppu::UnoType
<sal_uIntPtr
>::get());
239 throw IllegalArgumentException();
241 else if (sourceModelType
== OLE
)
243 auto v
= o3tl::tryAccess
<sal_uIntPtr
>(modelDepObject
);
246 throw IllegalArgumentException();
248 else if (destModelType
== OLE
)
250 // same model -> copy value only
251 VARIANT
* pVariant
= static_cast<VARIANT
*>(CoTaskMemAlloc(sizeof(VARIANT
)));
253 if (NOERROR
!= VariantCopy(pVariant
, reinterpret_cast<VARIANT
*>(*v
)))
255 CoTaskMemFree(pVariant
);
256 throw(IllegalArgumentException());
260 ret
.setValue(static_cast<void*>(&pVariant
), cppu::UnoType
<sal_uIntPtr
>::get());
263 else if (destModelType
== UNO
)
265 // convert variant into UNO any
266 VARIANT
* pVariant
= reinterpret_cast<VARIANT
*>(*v
);
269 variantToAny(pVariant
, ret
);
271 catch (const CannotConvertException
& e
)
273 throw IllegalArgumentException(
274 e
.Message
, nullptr, -1);
278 throw IllegalArgumentException();
282 throw IllegalArgumentException();
288 OUString
OleConverter::getImplementationName()
290 return m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
291 ? OUString("com.sun.star.comp.ole.OleConverter2")
292 : OUString("com.sun.star.comp.ole.OleConverterVar1");
295 sal_Bool
OleConverter::supportsService(OUString
const & ServiceName
)
297 return cppu::supportsService(this, ServiceName
);
300 css::uno::Sequence
<OUString
> OleConverter::getSupportedServiceNames()
302 if (m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
)
304 return css::uno::Sequence
<OUString
>{
305 "com.sun.star.bridge.OleBridgeSupplier2",
306 "com.sun.star.bridge.oleautomation.BridgeSupplier"};
308 return {"com.sun.star.bridge.OleBridgeSupplierVar1"};
311 // XInitialize ------------------------------------------------------------------------------
312 // the first argument is an XMultiServiceFactory if at all
313 void SAL_CALL
OleConverter::initialize( const Sequence
< Any
>& aArguments
)
315 if( aArguments
.getLength() == 1 && aArguments
[0].getValueTypeClass() == TypeClass_INTERFACE
)
317 Reference
< XInterface
> xInt
;
318 aArguments
[0] >>= xInt
;
319 Reference
<XMultiServiceFactory
> xMulti( xInt
, UNO_QUERY
);
320 m_smgrRemote
= xMulti
;
324 // UnoConversionUtilities -------------------------------------------------------------------
325 Reference
< XInterface
> OleConverter::createUnoWrapperInstance()
327 if( m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
)
329 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new InterfaceOleWrapper(
330 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
331 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
333 else if( m_nUnoWrapperClass
== UNO_OBJECT_WRAPPER_REMOTE_OPT
)
335 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new UnoObjectWrapperRemoteOpt(
336 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
337 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
340 return Reference
<XInterface
>();
343 Reference
< XInterface
> OleConverter::createComWrapperInstance()
345 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new IUnknownWrapper(
346 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
347 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
350 OleClient::OleClient( const Reference
<XMultiServiceFactory
>& smgr
):
351 UnoConversionUtilities
<OleClient
>( smgr
)
353 Reference
<XInterface
> xInt
;// = m_smgr->createInstance(L"com.sun.star.bridge.OleBridgeSupplier2");
357 Any a
= xInt
->queryInterface(cppu::UnoType
<XBridgeSupplier2
>::get() );
358 a
>>= m_bridgeSupplier
;
362 OleClient::~OleClient()
366 Sequence
< OUString
> SAL_CALL
OleClient::getAvailableServiceNames()
368 Sequence
< OUString
> ret
;
373 OUString
OleClient::getImplementationName()
375 return "com.sun.star.comp.ole.OleClient";
378 sal_Bool
OleClient::supportsService(OUString
const & ServiceName
)
380 return cppu::supportsService(this, ServiceName
);
383 css::uno::Sequence
<OUString
> OleClient::getSupportedServiceNames()
385 return css::uno::Sequence
<OUString
>{
386 "com.sun.star.bridge.OleObjectFactory",
387 "com.sun.star.bridge.oleautomation.Factory"};
390 Reference
<XInterface
> SAL_CALL
OleClient::createInstance(const OUString
& ServiceSpecifier
)
392 Reference
<XInterface
> ret
;
394 IUnknown
* pUnknown
= nullptr;
397 o2u_attachCurrentThread();
399 result
= CLSIDFromProgID(
400 o3tl::toW(ServiceSpecifier
.getStr()), //Pointer to the ProgID
401 &classId
); //Pointer to the CLSID
404 if (result
== NOERROR
)
406 result
= CoCreateInstance(
407 classId
, //Class identifier (CLSID) of the object
408 nullptr, //Pointer to whether object is or isn't part of an aggregate
409 CLSCTX_SERVER
, //Context for running executable code
410 IID_IUnknown
, //Reference to the identifier of the interface
411 reinterpret_cast<void**>(&pUnknown
)); //Address of output variable that receives
412 // the interface pointer requested in riid
415 if (pUnknown
!= nullptr)
420 V_VT(&variant
) = VT_UNKNOWN
;
421 V_UNKNOWN(&variant
) = pUnknown
;
422 // AddRef for Variant
425 // When the object is wrapped, then its refcount is increased
426 variantToAny(&variant
, any
);
427 if (any
.getValueTypeClass() == TypeClass_INTERFACE
)
431 pUnknown
->Release(); // CoCreateInstance
437 Reference
<XInterface
> SAL_CALL
OleClient::createInstanceWithArguments(const OUString
& ServiceSpecifier
, const Sequence
< Any
>& /*Arguments*/)
439 return createInstance( ServiceSpecifier
);
442 // UnoConversionUtilities -----------------------------------------------------------------------------
443 Reference
< XInterface
> OleClient::createUnoWrapperInstance()
445 if( m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
)
447 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new InterfaceOleWrapper(
448 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
449 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
451 else if( m_nUnoWrapperClass
== UNO_OBJECT_WRAPPER_REMOTE_OPT
)
453 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new UnoObjectWrapperRemoteOpt(
454 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
455 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
458 return Reference
< XInterface
>();
460 // UnoConversionUtilities -----------------------------------------------------------------------------
461 Reference
< XInterface
> OleClient::createComWrapperInstance( )
463 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new IUnknownWrapper(
464 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
465 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
468 OleServer::OleServer( const Reference
<XMultiServiceFactory
>& smgr
):
471 Reference
<XInterface
> xInt
= m_smgr
->createInstance("com.sun.star.bridge.oleautomation.BridgeSupplier");
475 Any a
= xInt
->queryInterface( cppu::UnoType
<XBridgeSupplier2
>::get() );
476 a
>>= m_bridgeSupplier
;
479 (void) provideInstance( [&]
483 &OID_ServiceManager
);
485 (void) provideInstance( [&]
487 // We want just one SwVbaGlobals for all Automation clients
488 static const Reference
<XInterface
> xWordGlobals
= m_smgr
->createInstance("ooo.vba.word.Globals");
489 const Reference
<ooo::vba::XHelperInterface
> xHelperInterface(xWordGlobals
, UNO_QUERY
);
490 Any aApplication
= xHelperInterface
->Application();
491 Reference
<XInterface
> xApplication
;
492 aApplication
>>= xApplication
;
495 &OID_LibreOfficeWriterApplication
);
497 (void) provideInstance( [&]
500 static const Reference
<XInterface
> xCalcGlobals
= m_smgr
->createInstance("ooo.vba.excel.Globals");
501 const Reference
<ooo::vba::XHelperInterface
> xHelperInterface(xCalcGlobals
, UNO_QUERY
);
502 Any aApplication
= xHelperInterface
->Application();
503 Reference
<XInterface
> xApplication
;
504 aApplication
>>= xApplication
;
507 &OID_LibreOfficeCalcApplication
);
510 OleServer::~OleServer()
512 for (auto const& elem
: m_wrapperList
)
514 elem
->deregisterClass();
517 m_wrapperList
.clear();
520 OUString
OleServer::getImplementationName()
522 return "com.sun.star.comp.ole.OleServer";
525 sal_Bool
OleServer::supportsService(OUString
const & ServiceName
)
527 return cppu::supportsService(this, ServiceName
);
530 css::uno::Sequence
<OUString
> OleServer::getSupportedServiceNames()
532 return css::uno::Sequence
<OUString
>{
533 "com.sun.star.bridge.OleApplicationRegistration",
534 "com.sun.star.bridge.oleautomation.ApplicationRegistration"};
537 bool OleServer::provideInstance(std::function
<const Reference
<XInterface
>()> xInstFunction
, GUID
const * guid
)
539 OneInstanceOleWrapper
* pWrapper
= new OneInstanceOleWrapper( m_smgr
, xInstFunction
);
542 m_wrapperList
.push_back(pWrapper
);
544 return pWrapper
->registerClass(guid
);
547 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */