Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / extensions / source / ole / servprov.cxx
blob1f14fa01032d8e96650d92a9e4475fbe076fd8da
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <vector>
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>
39 using namespace cppu;
40 using namespace osl;
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;
46 #include <initguid.h>
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);
57 // For Calc
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 )
63 : m_refCount(0)
64 , m_xInstFunction(xInstFunction)
65 , m_factoryHandle(0)
66 , m_smgr(smgr)
68 Reference<XInterface> xInt = m_smgr->createInstance("com.sun.star.bridge.oleautomation.BridgeSupplier");
70 if (xInt.is())
72 Any a= xInt->queryInterface( cppu::UnoType<XBridgeSupplier2>::get() );
73 a >>= m_bridgeSupplier;
77 OneInstanceOleWrapper::~OneInstanceOleWrapper()
81 bool OneInstanceOleWrapper::registerClass(GUID const * pGuid)
83 HRESULT hresult;
85 o2u_attachCurrentThread();
87 hresult = CoRegisterClassObject(
88 *pGuid,
89 this,
90 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
91 REGCLS_MULTIPLEUSE,
92 &m_factoryHandle);
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))
108 AddRef();
109 *ppv = static_cast<IUnknown*>(static_cast<IClassFactory*>(this));
110 return NOERROR;
112 else if (IsEqualIID(riid, IID_IClassFactory))
114 AddRef();
115 *ppv = static_cast<IClassFactory*>(this);
116 return NOERROR;
119 *ppv = nullptr;
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)
134 delete this;
137 return refCount;
140 COM_DECLSPEC_NOTHROW STDMETHODIMP OneInstanceOleWrapper::CreateInstance(IUnknown FAR* punkOuter,
141 REFIID riid,
142 void FAR* FAR* ppv)
144 comphelper::Automation::AutomationInvokedZone aAutomationActive;
146 SAL_INFO("extensions.olebridge", "OneInstanceOleWrapper::CreateInstance(" << riid << ")");
148 HRESULT ret = ResultFromScode(E_UNEXPECTED);
149 punkOuter = nullptr;
151 const Reference<XInterface>& xInst = m_xInstFunction();
152 if (xInst.is())
154 Any usrAny(&xInst, cppu::UnoType<decltype(xInst)>::get());
155 sal_uInt8 arId[16];
156 rtl_getGlobalProcessId( arId);
157 Any oleAny = m_bridgeSupplier->createBridge(usrAny,
158 Sequence<sal_Int8>( reinterpret_cast<sal_Int8*>(arId), 16),
159 UNO,
160 OLE);
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);
178 return ret;
181 COM_DECLSPEC_NOTHROW STDMETHODIMP OneInstanceOleWrapper::LockServer(BOOL /*fLock*/)
183 return NOERROR;
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)
209 Any ret;
210 sal_uInt8 arId[16];
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);
233 catch(...)
235 CoTaskMemFree(pVariant);
236 throw IllegalArgumentException();
238 ret.setValue(static_cast<void*>(&pVariant), cppu::UnoType<sal_uIntPtr>::get());
240 else
241 throw IllegalArgumentException();
243 else if (sourceModelType == OLE)
245 auto v = o3tl::tryAccess<sal_uIntPtr>(modelDepObject);
246 if (!v)
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());
260 else
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);
279 else
280 throw IllegalArgumentException();
283 else
284 throw IllegalArgumentException();
287 return ret;
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);
342 else
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");
358 if (xInt.is())
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;
373 return 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;
396 HRESULT result;
397 IUnknown* pUnknown = nullptr;
398 CLSID classId;
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)
420 Any any;
421 CComVariant variant;
423 V_VT(&variant) = VT_UNKNOWN;
424 V_UNKNOWN(&variant) = pUnknown;
425 // AddRef for Variant
426 pUnknown->AddRef();
428 // When the object is wrapped, then its refcount is increased
429 variantToAny(&variant, any);
430 if (any.getValueTypeClass() == TypeClass_INTERFACE)
432 any >>= ret;
434 pUnknown->Release(); // CoCreateInstance
437 return ret;
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);
460 else
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):
472 m_smgr( smgr)
474 Reference<XInterface> xInt = m_smgr->createInstance("com.sun.star.bridge.oleautomation.BridgeSupplier");
476 if (xInt.is())
478 Any a= xInt->queryInterface( cppu::UnoType<XBridgeSupplier2>::get() );
479 a >>= m_bridgeSupplier;
482 (void) provideInstance( [&]
484 return m_smgr;
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;
496 return xApplication;
498 &OID_LibreOfficeWriterApplication );
500 (void) provideInstance( [&]
502 // Ditto for sc
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;
508 return xApplication;
510 &OID_LibreOfficeCalcApplication );
513 OleServer::~OleServer()
515 for (auto const& elem : m_wrapperList)
517 elem->deregisterClass();
518 elem->Release();
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 );
544 pWrapper->AddRef();
545 m_wrapperList.push_back(pWrapper);
547 return pWrapper->registerClass(guid);
550 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */