use insert function instead of for loop
[LibreOffice.git] / extensions / source / ole / servprov.cxx
blob0c3920ccca113a33f02d553560173076fe9ad188
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 <officecfg/Office/Common.hxx>
37 #include <ooo/vba/XHelperInterface.hpp>
38 #include <sal/log.hxx>
40 using namespace cppu;
41 using namespace osl;
42 using namespace com::sun::star::lang;
43 using namespace com::sun::star::uno;
44 using namespace com::sun::star::bridge;
45 using namespace com::sun::star::bridge::ModelDependent;
47 #include <initguid.h>
49 // GUID used since 5.2 ( src569 m)
50 // {82154420-0FBF-11d4-8313-005004526AB4}
51 DEFINE_GUID(OID_ServiceManager, 0x82154420, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50, 0x4, 0x52, 0x6a, 0xb4);
53 // FIXME: This GUID is just the above OID_ServiceManager with the
54 // initial part bumped by one. Is that good enough?
55 // {82154421-0FBF-11d4-8313-005004526AB4}
56 DEFINE_GUID(OID_LibreOfficeWriterApplication, 0x82154421, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50, 0x4, 0x52, 0x6a, 0xb4);
58 // For Calc
59 // {82154425-0FBF-11d4-8313-005004526AB4}
60 DEFINE_GUID(OID_LibreOfficeCalcApplication, 0x82154425, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50, 0x4, 0x52, 0x6a, 0xb4);
62 OneInstanceOleWrapper::OneInstanceOleWrapper( const Reference<XMultiServiceFactory>& smgr,
63 std::function<const Reference<XInterface>()> xInstFunction )
64 : m_refCount(0)
65 , m_xInstFunction(xInstFunction)
66 , m_factoryHandle(0)
67 , m_smgr(smgr)
69 Reference<XInterface> xInt = m_smgr->createInstance("com.sun.star.bridge.oleautomation.BridgeSupplier");
71 if (xInt.is())
73 Any a= xInt->queryInterface( cppu::UnoType<XBridgeSupplier2>::get() );
74 a >>= m_bridgeSupplier;
78 OneInstanceOleWrapper::~OneInstanceOleWrapper()
82 bool OneInstanceOleWrapper::registerClass(GUID const * pGuid)
84 HRESULT hresult;
86 o2u_attachCurrentThread();
88 hresult = CoRegisterClassObject(
89 *pGuid,
90 this,
91 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
92 REGCLS_MULTIPLEUSE,
93 &m_factoryHandle);
95 SAL_INFO("extensions.olebridge", "CoRegisterClassObject(" << *pGuid << "): " << WindowsErrorStringFromHRESULT(hresult));
97 return (hresult == NOERROR);
100 bool OneInstanceOleWrapper::deregisterClass()
102 return CoRevokeClassObject(m_factoryHandle) == NOERROR;
105 COM_DECLSPEC_NOTHROW STDMETHODIMP OneInstanceOleWrapper::QueryInterface(REFIID riid, void ** ppv)
107 if(IsEqualIID(riid, IID_IUnknown))
109 AddRef();
110 *ppv = static_cast<IUnknown*>(static_cast<IClassFactory*>(this));
111 return NOERROR;
113 else if (IsEqualIID(riid, IID_IClassFactory))
115 AddRef();
116 *ppv = static_cast<IClassFactory*>(this);
117 return NOERROR;
120 *ppv = nullptr;
121 return ResultFromScode(E_NOINTERFACE);
124 COM_DECLSPEC_NOTHROW STDMETHODIMP_(ULONG) OneInstanceOleWrapper::AddRef()
126 return osl_atomic_increment( &m_refCount);
129 COM_DECLSPEC_NOTHROW STDMETHODIMP_(ULONG) OneInstanceOleWrapper::Release()
131 MutexGuard oGuard( Mutex::getGlobalMutex());
132 ULONG refCount = --m_refCount;
133 if ( m_refCount == 0)
135 delete this;
138 return refCount;
141 COM_DECLSPEC_NOTHROW STDMETHODIMP OneInstanceOleWrapper::CreateInstance(IUnknown*,
142 REFIID riid, void** ppv)
144 comphelper::Automation::AutomationInvokedZone aAutomationActive;
146 SAL_INFO("extensions.olebridge", "OneInstanceOleWrapper::CreateInstance(" << riid << ")");
148 if (officecfg::Office::Common::Security::Scripting::DisableOLEAutomation::get())
150 return ResultFromScode(E_NOINTERFACE);
153 HRESULT ret = ResultFromScode(E_UNEXPECTED);
154 const Reference<XInterface>& xInst = m_xInstFunction();
155 if (xInst.is())
157 Any usrAny(&xInst, cppu::UnoType<decltype(xInst)>::get());
158 sal_uInt8 arId[16];
159 rtl_getGlobalProcessId( arId);
160 Any oleAny = m_bridgeSupplier->createBridge(usrAny,
161 Sequence<sal_Int8>( reinterpret_cast<sal_Int8*>(arId), 16),
162 UNO,
163 OLE);
166 if (auto v = o3tl::tryAccess<sal_uIntPtr>(oleAny))
168 VARIANT* pVariant = reinterpret_cast<VARIANT*>(*v);
170 if ((pVariant->vt == VT_UNKNOWN) || (pVariant->vt == VT_DISPATCH))
172 SAL_INFO("extensions.olebridge", "OneInstanceOleWrapper::Createbridge: punkVal=" << pVariant->punkVal);
173 ret = pVariant->punkVal->QueryInterface(riid, ppv);
176 VariantClear(pVariant);
177 CoTaskMemFree(pVariant);
181 return ret;
184 COM_DECLSPEC_NOTHROW STDMETHODIMP OneInstanceOleWrapper::LockServer(BOOL /*fLock*/)
186 return NOERROR;
189 OleConverter::OleConverter( const Reference<XMultiServiceFactory> &smgr):
190 UnoConversionUtilities<OleConverter>( smgr)
195 // The XMultiServiceFactory is later set by XInitialization
196 OleConverter::OleConverter( const Reference<XMultiServiceFactory>& smgr, sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass ):
197 UnoConversionUtilities<OleConverter>( smgr, unoWrapperClass, comWrapperClass )
202 OleConverter::~OleConverter()
206 // XBridgeSupplier --------------------------------------------------------------
207 Any SAL_CALL OleConverter::createBridge(const Any& modelDepObject,
208 const Sequence< sal_Int8 >& ProcessId,
209 sal_Int16 sourceModelType,
210 sal_Int16 destModelType)
212 Any ret;
213 sal_uInt8 arId[16];
214 rtl_getGlobalProcessId( arId );
216 Sequence< sal_Int8 > seqProcessId( reinterpret_cast<sal_Int8*>(arId), 16);
218 if ( seqProcessId == ProcessId)
220 if (sourceModelType == UNO)
222 if (destModelType == UNO)
224 // same model -> copy value only
225 ret = modelDepObject;
227 else if (destModelType == OLE)
229 // convert UNO any into variant
230 VARIANT* pVariant = static_cast<VARIANT*>(CoTaskMemAlloc(sizeof(VARIANT)));
231 VariantInit( pVariant);
234 anyToVariant( pVariant, modelDepObject);
236 catch(...)
238 CoTaskMemFree(pVariant);
239 throw IllegalArgumentException();
241 ret.setValue(static_cast<void*>(&pVariant), cppu::UnoType<sal_uIntPtr>::get());
243 else
244 throw IllegalArgumentException();
246 else if (sourceModelType == OLE)
248 auto v = o3tl::tryAccess<sal_uIntPtr>(modelDepObject);
249 if (!v)
251 throw IllegalArgumentException();
253 else if (destModelType == OLE)
255 // same model -> copy value only
256 VARIANT* pVariant = static_cast<VARIANT*>(CoTaskMemAlloc(sizeof(VARIANT)));
258 if (NOERROR != VariantCopy(pVariant, reinterpret_cast<VARIANT*>(*v)))
260 CoTaskMemFree(pVariant);
261 throw(IllegalArgumentException());
263 else
265 ret.setValue(static_cast<void*>(&pVariant), cppu::UnoType<sal_uIntPtr>::get());
268 else if (destModelType == UNO)
270 // convert variant into UNO any
271 VARIANT* pVariant = reinterpret_cast<VARIANT*>(*v);
274 variantToAny(pVariant, ret);
276 catch (const CannotConvertException & e)
278 throw IllegalArgumentException(
279 e.Message, nullptr, -1);
282 else
283 throw IllegalArgumentException();
286 else
287 throw IllegalArgumentException();
290 return ret;
293 OUString OleConverter::getImplementationName()
295 return m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL
296 ? OUString("com.sun.star.comp.ole.OleConverter2")
297 : OUString("com.sun.star.comp.ole.OleConverterVar1");
300 sal_Bool OleConverter::supportsService(OUString const & ServiceName)
302 return cppu::supportsService(this, ServiceName);
305 css::uno::Sequence<OUString> OleConverter::getSupportedServiceNames()
307 if (m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL)
309 return css::uno::Sequence<OUString>{
310 "com.sun.star.bridge.OleBridgeSupplier2",
311 "com.sun.star.bridge.oleautomation.BridgeSupplier"};
313 return {"com.sun.star.bridge.OleBridgeSupplierVar1"};
316 // XInitialize ------------------------------------------------------------------------------
317 // the first argument is an XMultiServiceFactory if at all
318 void SAL_CALL OleConverter::initialize( const Sequence< Any >& aArguments )
320 if( aArguments.getLength() == 1 && aArguments[0].getValueTypeClass() == TypeClass_INTERFACE)
322 Reference < XInterface > xInt;
323 aArguments[0] >>= xInt;
324 Reference <XMultiServiceFactory> xMulti( xInt, UNO_QUERY);
325 m_smgrRemote= xMulti;
329 // UnoConversionUtilities -------------------------------------------------------------------
330 Reference< XInterface > OleConverter::createUnoWrapperInstance()
332 if( m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL)
334 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper(
335 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
336 return Reference<XInterface>( xWeak, UNO_QUERY);
338 else if( m_nUnoWrapperClass == UNO_OBJECT_WRAPPER_REMOTE_OPT)
340 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
341 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
342 return Reference<XInterface>( xWeak, UNO_QUERY);
344 else
345 return Reference<XInterface>();
348 Reference< XInterface > OleConverter::createComWrapperInstance()
350 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper(
351 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
352 return Reference<XInterface>( xWeak, UNO_QUERY);
355 OleClient::OleClient( const Reference<XMultiServiceFactory>& smgr):
356 UnoConversionUtilities<OleClient>( smgr)
358 Reference<XInterface> xInt;// = m_smgr->createInstance(L"com.sun.star.bridge.OleBridgeSupplier2");
360 if (xInt.is())
362 Any a= xInt->queryInterface(cppu::UnoType<XBridgeSupplier2>::get() );
363 a >>= m_bridgeSupplier;
367 OleClient::~OleClient()
371 Sequence< OUString > SAL_CALL OleClient::getAvailableServiceNames()
373 Sequence< OUString > ret;
375 return ret;
378 OUString OleClient::getImplementationName()
380 return "com.sun.star.comp.ole.OleClient";
383 sal_Bool OleClient::supportsService(OUString const & ServiceName)
385 return cppu::supportsService(this, ServiceName);
388 css::uno::Sequence<OUString> OleClient::getSupportedServiceNames()
390 return css::uno::Sequence<OUString>{
391 "com.sun.star.bridge.OleObjectFactory",
392 "com.sun.star.bridge.oleautomation.Factory"};
395 Reference<XInterface> SAL_CALL OleClient::createInstance(const OUString& ServiceSpecifier)
397 Reference<XInterface> ret;
398 HRESULT result;
399 IUnknown* pUnknown = nullptr;
400 CLSID classId;
402 o2u_attachCurrentThread();
404 result = CLSIDFromProgID(
405 o3tl::toW(ServiceSpecifier.getStr()), //Pointer to the ProgID
406 &classId); //Pointer to the CLSID
409 if (result == NOERROR)
411 result = CoCreateInstance(
412 classId, //Class identifier (CLSID) of the object
413 nullptr, //Pointer to whether object is or isn't part of an aggregate
414 CLSCTX_SERVER, //Context for running executable code
415 IID_IUnknown, //Reference to the identifier of the interface
416 reinterpret_cast<void**>(&pUnknown)); //Address of output variable that receives
417 // the interface pointer requested in riid
420 if (pUnknown != nullptr)
422 Any any;
423 CComVariant variant;
425 V_VT(&variant) = VT_UNKNOWN;
426 V_UNKNOWN(&variant) = pUnknown;
427 // AddRef for Variant
428 pUnknown->AddRef();
430 // When the object is wrapped, then its refcount is increased
431 variantToAny(&variant, any);
432 if (any.getValueTypeClass() == TypeClass_INTERFACE)
434 any >>= ret;
436 pUnknown->Release(); // CoCreateInstance
439 return ret;
442 Reference<XInterface> SAL_CALL OleClient::createInstanceWithArguments(const OUString& ServiceSpecifier, const Sequence< Any >& /*Arguments*/)
444 return createInstance( ServiceSpecifier);
447 // UnoConversionUtilities -----------------------------------------------------------------------------
448 Reference< XInterface > OleClient::createUnoWrapperInstance()
450 if( m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL)
452 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper(
453 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
454 return Reference<XInterface>( xWeak, UNO_QUERY);
456 else if( m_nUnoWrapperClass == UNO_OBJECT_WRAPPER_REMOTE_OPT)
458 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
459 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
460 return Reference<XInterface>( xWeak, UNO_QUERY);
462 else
463 return Reference< XInterface>();
465 // UnoConversionUtilities -----------------------------------------------------------------------------
466 Reference< XInterface > OleClient::createComWrapperInstance( )
468 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper(
469 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
470 return Reference<XInterface>( xWeak, UNO_QUERY);
473 OleServer::OleServer( const Reference<XMultiServiceFactory>& smgr):
474 m_smgr( smgr)
476 Reference<XInterface> xInt = m_smgr->createInstance("com.sun.star.bridge.oleautomation.BridgeSupplier");
478 if (xInt.is())
480 Any a= xInt->queryInterface( cppu::UnoType<XBridgeSupplier2>::get() );
481 a >>= m_bridgeSupplier;
484 (void) provideInstance( [&]
486 return m_smgr;
488 &OID_ServiceManager );
490 (void) provideInstance( [&]
492 // We want just one SwVbaGlobals for all Automation clients
493 static const Reference<XInterface> xWordGlobals = m_smgr->createInstance("ooo.vba.word.Globals");
494 const Reference<ooo::vba::XHelperInterface> xHelperInterface(xWordGlobals, UNO_QUERY);
495 Any aApplication = xHelperInterface->Application();
496 Reference<XInterface> xApplication;
497 aApplication >>= xApplication;
498 return xApplication;
500 &OID_LibreOfficeWriterApplication );
502 (void) provideInstance( [&]
504 // Ditto for sc
505 static const Reference<XInterface> xCalcGlobals = m_smgr->createInstance("ooo.vba.excel.Globals");
506 const Reference<ooo::vba::XHelperInterface> xHelperInterface(xCalcGlobals, UNO_QUERY);
507 Any aApplication = xHelperInterface->Application();
508 Reference<XInterface> xApplication;
509 aApplication >>= xApplication;
510 return xApplication;
512 &OID_LibreOfficeCalcApplication );
515 OleServer::~OleServer()
517 for (auto const& elem : m_wrapperList)
519 elem->deregisterClass();
520 elem->Release();
522 m_wrapperList.clear();
525 OUString OleServer::getImplementationName()
527 return "com.sun.star.comp.ole.OleServer";
530 sal_Bool OleServer::supportsService(OUString const & ServiceName)
532 return cppu::supportsService(this, ServiceName);
535 css::uno::Sequence<OUString> OleServer::getSupportedServiceNames()
537 return css::uno::Sequence<OUString>{
538 "com.sun.star.bridge.OleApplicationRegistration",
539 "com.sun.star.bridge.oleautomation.ApplicationRegistration"};
542 bool OleServer::provideInstance(std::function<const Reference<XInterface>()> xInstFunction, GUID const * guid)
544 OneInstanceOleWrapper* pWrapper = new OneInstanceOleWrapper( m_smgr, xInstFunction );
546 pWrapper->AddRef();
547 m_wrapperList.push_back(pWrapper);
549 return pWrapper->registerClass(guid);
552 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */