1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <cassert>
23 #include <cstddef>
24 #include <limits>
25 
26 #ifdef SAL_UNX
27 #include <sal/alloca.h>
28 #endif
29 #include <o3tl/any.hxx>
30 #include <typelib/typedescription.hxx>
31 #include <uno/data.h>
32 
33 #include "base.hxx"
34 
35 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
36 #include <com/sun/star/reflection/XIdlField2.hpp>
37 #include <com/sun/star/uno/RuntimeException.hpp>
38 #include <cppuhelper/queryinterface.hxx>
39 #include <cppuhelper/exc_hlp.hxx>
40 #include <cppuhelper/typeprovider.hxx>
41 
42 using namespace css::lang;
43 using namespace css::reflection;
44 using namespace css::uno;
45 
46 namespace {
47 
multipleOf16(std::size_t n)48 std::size_t multipleOf16(std::size_t n) {
49     assert(n <= std::numeric_limits<std::size_t>::max() - 15);
50     return (n + 15) & ~std::size_t(15);
51 }
52 
53 }
54 
55 namespace stoc_corefl
56 {
57 
58 namespace {
59 
60 class IdlAttributeFieldImpl
61     : public IdlMemberImpl
62     , public XIdlField
63     , public XIdlField2
64 {
65 public:
getAttributeTypeDescr() const66     typelib_InterfaceAttributeTypeDescription * getAttributeTypeDescr() const
67         { return reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>(getTypeDescr()); }
68 
IdlAttributeFieldImpl(IdlReflectionServiceImpl * pReflection,const OUString & rName,typelib_TypeDescription * pTypeDescr,typelib_TypeDescription * pDeclTypeDescr)69     IdlAttributeFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName,
70                            typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr )
71         : IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr )
72         {}
73 
74     // XInterface
75     virtual Any SAL_CALL queryInterface( const Type & rType ) override;
76     virtual void SAL_CALL acquire() noexcept override;
77     virtual void SAL_CALL release() noexcept override;
78 
79     // XTypeProvider
80     virtual Sequence< Type > SAL_CALL getTypes() override;
81     virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
82 
83     // XIdlMember
84     virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() override;
85     virtual OUString SAL_CALL getName() override;
86     // XIdlField
87     virtual Reference< XIdlClass > SAL_CALL getType() override;
88     virtual FieldAccessMode SAL_CALL getAccessMode() override;
89     virtual Any SAL_CALL get( const Any & rObj ) override;
90     virtual void SAL_CALL set( const Any & rObj, const Any & rValue ) override;
91     // XIdlField2: getType, getAccessMode and get are equal to XIdlField
92     virtual void SAL_CALL set( Any & rObj, const Any & rValue ) override;
93 
94 private:
95     void checkException(
96         uno_Any * exception, Reference< XInterface > const & context) const;
97 };
98 
99 }
100 
101 // XInterface
102 
queryInterface(const Type & rType)103 Any IdlAttributeFieldImpl::queryInterface( const Type & rType )
104 {
105     Any aRet( ::cppu::queryInterface( rType,
106                                       static_cast< XIdlField * >( this ),
107                                       static_cast< XIdlField2 * >( this ) ) );
108     return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType ));
109 }
110 
acquire()111 void IdlAttributeFieldImpl::acquire() noexcept
112 {
113     IdlMemberImpl::acquire();
114 }
115 
release()116 void IdlAttributeFieldImpl::release() noexcept
117 {
118     IdlMemberImpl::release();
119 }
120 
121 // XTypeProvider
122 
getTypes()123 Sequence< Type > IdlAttributeFieldImpl::getTypes()
124 {
125     static cppu::OTypeCollection s_aTypes(
126         cppu::UnoType<XIdlField2>::get(),
127         cppu::UnoType<XIdlField>::get(),
128         IdlMemberImpl::getTypes() );
129 
130     return s_aTypes.getTypes();
131 }
132 
getImplementationId()133 Sequence< sal_Int8 > IdlAttributeFieldImpl::getImplementationId()
134 {
135     return css::uno::Sequence<sal_Int8>();
136 }
137 
138 // XIdlMember
139 
getDeclaringClass()140 Reference< XIdlClass > IdlAttributeFieldImpl::getDeclaringClass()
141 {
142     if (! _xDeclClass.is())
143     {
144         ::osl::MutexGuard aGuard( getMutexAccess() );
145         if (! _xDeclClass.is())
146         {
147             OUString aName(getAttributeTypeDescr()->aBase.aBase.pTypeName);
148             sal_Int32 i = aName.indexOf(':');
149             OSL_ASSERT(i >= 0);
150             _xDeclClass = getReflection()->forName(aName.copy(0, i));
151         }
152     }
153     return _xDeclClass;
154 }
155 
getName()156 OUString IdlAttributeFieldImpl::getName()
157 {
158     return IdlMemberImpl::getName();
159 }
160 
161 // XIdlField
162 
getType()163 Reference< XIdlClass > IdlAttributeFieldImpl::getType()
164 {
165     return getReflection()->forType(
166         getAttributeTypeDescr()->pAttributeTypeRef );
167 }
168 
getAccessMode()169 FieldAccessMode IdlAttributeFieldImpl::getAccessMode()
170 {
171     return (getAttributeTypeDescr()->bReadOnly
172             ? FieldAccessMode_READONLY : FieldAccessMode_READWRITE);
173 }
174 
get(const Any & rObj)175 Any IdlAttributeFieldImpl::get( const Any & rObj )
176 {
177     uno_Interface * pUnoI = getReflection()->mapToUno(
178         rObj, reinterpret_cast<typelib_InterfaceTypeDescription *>(getDeclTypeDescr()) );
179     OSL_ENSURE( pUnoI, "### illegal destination object given!" );
180     if (pUnoI)
181     {
182         TypeDescription aTD( getAttributeTypeDescr()->pAttributeTypeRef );
183         typelib_TypeDescription * pTD = aTD.get();
184 
185         uno_Any aExc;
186         uno_Any * pExc = &aExc;
187         void * pReturn = alloca( pTD->nSize );
188 
189         (*pUnoI->pDispatcher)( pUnoI, getTypeDescr(), pReturn, nullptr, &pExc );
190         (*pUnoI->release)( pUnoI );
191 
192         checkException(pExc, *o3tl::doAccess<Reference<XInterface>>(rObj));
193         Any aRet;
194         uno_any_destruct(
195             &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
196         uno_any_constructAndConvert( &aRet, pReturn, pTD, getReflection()->getUno2Cpp().get() );
197         uno_destructData( pReturn, pTD, nullptr );
198         return aRet;
199     }
200     throw IllegalArgumentException(
201         "illegal object given!",
202         static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
203 }
204 
set(Any & rObj,const Any & rValue)205 void IdlAttributeFieldImpl::set( Any & rObj, const Any & rValue )
206 {
207     if (getAttributeTypeDescr()->bReadOnly)
208     {
209         throw IllegalAccessException(
210             "cannot set readonly attribute!",
211             static_cast<XWeak *>(static_cast<OWeakObject *>(this)) );
212     }
213 
214     uno_Interface * pUnoI = getReflection()->mapToUno(
215         rObj, reinterpret_cast<typelib_InterfaceTypeDescription *>(getDeclTypeDescr()) );
216     OSL_ENSURE( pUnoI, "### illegal destination object given!" );
217     if (pUnoI)
218     {
219         TypeDescription aTD( getAttributeTypeDescr()->pAttributeTypeRef );
220         typelib_TypeDescription * pTD = aTD.get();
221 
222         // construct uno value to be set
223         void * pArgs[1];
224         void * pArg = pArgs[0] = alloca( pTD->nSize );
225 
226         bool bAssign;
227         if (pTD->eTypeClass == typelib_TypeClass_ANY)
228         {
229             uno_copyAndConvertData( pArg, const_cast< Any * >(&rValue),
230                                     pTD, getReflection()->getCpp2Uno().get() );
231             bAssign = true;
232         }
233         else if (typelib_typedescriptionreference_equals( rValue.getValueTypeRef(), pTD->pWeakRef ))
234         {
235             uno_copyAndConvertData( pArg, const_cast< void * >(rValue.getValue()),
236                                     pTD, getReflection()->getCpp2Uno().get() );
237             bAssign = true;
238         }
239         else if (pTD->eTypeClass == typelib_TypeClass_INTERFACE)
240         {
241             Reference< XInterface > xObj;
242             bAssign = extract(
243                 rValue, reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD), xObj,
244                 getReflection() );
245             if (bAssign)
246             {
247                 *static_cast<void **>(pArg) = getReflection()->getCpp2Uno().mapInterface(
248                     xObj.get(), reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD) );
249             }
250         }
251         else
252         {
253             typelib_TypeDescription * pValueTD = nullptr;
254             TYPELIB_DANGER_GET( &pValueTD, rValue.getValueTypeRef() );
255             // construct temp uno val to do proper assignment: todo opt
256             void * pTemp = alloca( pValueTD->nSize );
257             uno_copyAndConvertData(
258                 pTemp, const_cast<void *>(rValue.getValue()), pValueTD, getReflection()->getCpp2Uno().get() );
259             uno_constructData(
260                 pArg, pTD );
261             // assignment does simple conversion
262             bAssign = uno_assignData(
263                 pArg, pTD, pTemp, pValueTD, nullptr, nullptr, nullptr );
264             uno_destructData(
265                 pTemp, pValueTD, nullptr );
266             TYPELIB_DANGER_RELEASE( pValueTD );
267         }
268 
269         if (bAssign)
270         {
271             uno_Any aExc;
272             uno_Any * pExc = &aExc;
273             (*pUnoI->pDispatcher)( pUnoI, getTypeDescr(), nullptr, pArgs, &pExc );
274             (*pUnoI->release)( pUnoI );
275 
276             uno_destructData( pArg, pTD, nullptr );
277             checkException(pExc, *o3tl::doAccess<Reference<XInterface>>(rObj));
278             return;
279         }
280         (*pUnoI->release)( pUnoI );
281 
282         throw IllegalArgumentException(
283             "illegal value given!",
284             *o3tl::doAccess<Reference<XInterface>>(rObj), 1 );
285     }
286     throw IllegalArgumentException(
287         "illegal destination object given!",
288         static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
289 }
290 
set(const Any & rObj,const Any & rValue)291 void IdlAttributeFieldImpl::set( const Any & rObj, const Any & rValue )
292 {
293     IdlAttributeFieldImpl::set( const_cast< Any & >( rObj ), rValue );
294 }
295 
checkException(uno_Any * exception,Reference<XInterface> const & context) const296 void IdlAttributeFieldImpl::checkException(
297     uno_Any * exception, Reference< XInterface > const & context) const
298 {
299     if (exception == nullptr)
300         return;
301 
302     Any e;
303     uno_any_destruct(&e, reinterpret_cast< uno_ReleaseFunc >(cpp_release));
304     uno_type_any_constructAndConvert(
305         &e, exception->pData, exception->pType,
306         getReflection()->getUno2Cpp().get());
307     uno_any_destruct(exception, nullptr);
308     if (!e.isExtractableTo(
309             cppu::UnoType<RuntimeException>::get()))
310     {
311         throw WrappedTargetRuntimeException(
312             "non-RuntimeException occurred when accessing an"
313             " interface type attribute",
314             context, e);
315     }
316     cppu::throwException(e);
317 }
318 
319 namespace {
320 
321 class IdlInterfaceMethodImpl
322     : public IdlMemberImpl
323     , public XIdlMethod
324 {
325     std::optional<Sequence< Reference< XIdlClass > >>   m_xExceptionTypes;
326     std::optional<Sequence< Reference< XIdlClass > >>   m_xParamTypes;
327     std::optional<Sequence< ParamInfo >>                m_xParamInfos;
328 
329 public:
getMethodTypeDescr() const330     typelib_InterfaceMethodTypeDescription * getMethodTypeDescr() const
331         { return reinterpret_cast<typelib_InterfaceMethodTypeDescription *>(getTypeDescr()); }
332 
IdlInterfaceMethodImpl(IdlReflectionServiceImpl * pReflection,const OUString & rName,typelib_TypeDescription * pTypeDescr,typelib_TypeDescription * pDeclTypeDescr)333     IdlInterfaceMethodImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName,
334                             typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr )
335         : IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr )
336         {}
337 
338     // XInterface
339     virtual Any SAL_CALL queryInterface( const Type & rType ) override;
340     virtual void SAL_CALL acquire() noexcept override;
341     virtual void SAL_CALL release() noexcept override;
342 
343     // XTypeProvider
344     virtual Sequence< Type > SAL_CALL getTypes() override;
345     virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
346 
347     // XIdlMember
348     virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() override;
349     virtual OUString SAL_CALL getName() override;
350     // XIdlMethod
351     virtual Reference< XIdlClass > SAL_CALL getReturnType() override;
352     virtual Sequence< Reference< XIdlClass > > SAL_CALL getParameterTypes() override;
353     virtual Sequence< ParamInfo > SAL_CALL getParameterInfos() override;
354     virtual Sequence< Reference< XIdlClass > > SAL_CALL getExceptionTypes() override;
355     virtual MethodMode SAL_CALL getMode() override;
356     virtual Any SAL_CALL invoke( const Any & rObj, Sequence< Any > & rArgs ) override;
357 };
358 
359 }
360 
361 // XInterface
362 
queryInterface(const Type & rType)363 Any IdlInterfaceMethodImpl::queryInterface( const Type & rType )
364 {
365     Any aRet( ::cppu::queryInterface( rType, static_cast< XIdlMethod * >( this ) ) );
366     return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType ));
367 }
368 
acquire()369 void IdlInterfaceMethodImpl::acquire() noexcept
370 {
371     IdlMemberImpl::acquire();
372 }
373 
release()374 void IdlInterfaceMethodImpl::release() noexcept
375 {
376     IdlMemberImpl::release();
377 }
378 
379 // XTypeProvider
380 
getTypes()381 Sequence< Type > IdlInterfaceMethodImpl::getTypes()
382 {
383     static cppu::OTypeCollection s_aTypes(
384         cppu::UnoType<XIdlMethod>::get(),
385         IdlMemberImpl::getTypes() );
386 
387     return s_aTypes.getTypes();
388 }
389 
getImplementationId()390 Sequence< sal_Int8 > IdlInterfaceMethodImpl::getImplementationId()
391 {
392     return css::uno::Sequence<sal_Int8>();
393 }
394 
395 // XIdlMember
396 
getDeclaringClass()397 Reference< XIdlClass > IdlInterfaceMethodImpl::getDeclaringClass()
398 {
399     if (! _xDeclClass.is())
400     {
401         ::osl::MutexGuard aGuard( getMutexAccess() );
402         if (! _xDeclClass.is())
403         {
404             OUString aName(getMethodTypeDescr()->aBase.aBase.pTypeName);
405             sal_Int32 i = aName.indexOf(':');
406             OSL_ASSERT(i >= 0);
407             _xDeclClass = getReflection()->forName(aName.copy(0, i));
408         }
409     }
410     return _xDeclClass;
411 }
412 
getName()413 OUString IdlInterfaceMethodImpl::getName()
414 {
415     return IdlMemberImpl::getName();
416 }
417 
418 // XIdlMethod
419 
getReturnType()420 Reference< XIdlClass > SAL_CALL IdlInterfaceMethodImpl::getReturnType()
421 {
422     return getReflection()->forType( getMethodTypeDescr()->pReturnTypeRef );
423 }
424 
getExceptionTypes()425 Sequence< Reference< XIdlClass > > IdlInterfaceMethodImpl::getExceptionTypes()
426 {
427     if (! m_xExceptionTypes)
428     {
429         ::osl::MutexGuard aGuard( getMutexAccess() );
430         if (! m_xExceptionTypes)
431         {
432             sal_Int32 nExc = getMethodTypeDescr()->nExceptions;
433             Sequence< Reference< XIdlClass > > aTempExceptionTypes( nExc );
434             Reference< XIdlClass > * pExceptionTypes = aTempExceptionTypes.getArray();
435 
436             typelib_TypeDescriptionReference ** ppExc =
437                 getMethodTypeDescr()->ppExceptions;
438             IdlReflectionServiceImpl * pRefl = getReflection();
439 
440             while (nExc--)
441                 pExceptionTypes[nExc] = pRefl->forType( ppExc[nExc] );
442 
443             m_xExceptionTypes = std::move(aTempExceptionTypes);
444         }
445     }
446     return *m_xExceptionTypes;
447 }
448 
getParameterTypes()449 Sequence< Reference< XIdlClass > > IdlInterfaceMethodImpl::getParameterTypes()
450 {
451     if (! m_xParamTypes)
452     {
453         ::osl::MutexGuard aGuard( getMutexAccess() );
454         if (! m_xParamTypes)
455         {
456             sal_Int32 nParams = getMethodTypeDescr()->nParams;
457             Sequence< Reference< XIdlClass > > aTempParamTypes( nParams );
458             Reference< XIdlClass > * pParamTypes = aTempParamTypes.getArray();
459 
460             typelib_MethodParameter * pTypelibParams =
461                 getMethodTypeDescr()->pParams;
462             IdlReflectionServiceImpl * pRefl = getReflection();
463 
464             while (nParams--)
465                 pParamTypes[nParams] = pRefl->forType( pTypelibParams[nParams].pTypeRef );
466 
467             m_xParamTypes = std::move(aTempParamTypes);
468         }
469     }
470     return *m_xParamTypes;
471 }
472 
getParameterInfos()473 Sequence< ParamInfo > IdlInterfaceMethodImpl::getParameterInfos()
474 {
475     if (! m_xParamInfos)
476     {
477         ::osl::MutexGuard aGuard( getMutexAccess() );
478         if (! m_xParamInfos)
479         {
480             sal_Int32 nParams = getMethodTypeDescr()->nParams;
481             Sequence< ParamInfo > aTempParamInfos( nParams );
482             ParamInfo * pParamInfos = aTempParamInfos.getArray();
483 
484             typelib_MethodParameter * pTypelibParams =
485                 getMethodTypeDescr()->pParams;
486 
487             if (m_xParamTypes) // use param types
488             {
489                 const Reference< XIdlClass > * pParamTypes = m_xParamTypes->getConstArray();
490 
491                 while (nParams--)
492                 {
493                     const typelib_MethodParameter & rParam = pTypelibParams[nParams];
494                     ParamInfo & rInfo = pParamInfos[nParams];
495                     rInfo.aName = rParam.pName;
496                     if (rParam.bIn)
497                         rInfo.aMode = (rParam.bOut ? ParamMode_INOUT : ParamMode_IN);
498                     else
499                         rInfo.aMode = ParamMode_OUT;
500                     rInfo.aType = pParamTypes[nParams];
501                 }
502             }
503             else // make also param types sequence if not already initialized
504             {
505                 Sequence< Reference< XIdlClass > > aTempParamTypes( nParams );
506                 Reference< XIdlClass > * pParamTypes = aTempParamTypes.getArray();
507 
508                 IdlReflectionServiceImpl * pRefl = getReflection();
509 
510                 while (nParams--)
511                 {
512                     const typelib_MethodParameter & rParam = pTypelibParams[nParams];
513                     ParamInfo & rInfo = pParamInfos[nParams];
514                     rInfo.aName = rParam.pName;
515                     if (rParam.bIn)
516                         rInfo.aMode = (rParam.bOut ? ParamMode_INOUT : ParamMode_IN);
517                     else
518                         rInfo.aMode = ParamMode_OUT;
519                     rInfo.aType = pParamTypes[nParams] = pRefl->forType( rParam.pTypeRef );
520                 }
521 
522                 m_xParamTypes = std::move(aTempParamTypes);
523             }
524 
525             m_xParamInfos = std::move(aTempParamInfos);
526         }
527     }
528     return *m_xParamInfos;
529 }
530 
getMode()531 MethodMode SAL_CALL IdlInterfaceMethodImpl::getMode()
532 {
533     return
534         getMethodTypeDescr()->bOneWay ? MethodMode_ONEWAY : MethodMode_TWOWAY;
535 }
536 
invoke(const Any & rObj,Sequence<Any> & rArgs)537 Any SAL_CALL IdlInterfaceMethodImpl::invoke( const Any & rObj, Sequence< Any > & rArgs )
538 {
539     if (auto ifc = o3tl::tryAccess<css::uno::Reference<css::uno::XInterface>>(
540             rObj))
541     {
542         // acquire()/ release()
543         if (rtl_ustr_ascii_compare( getTypeDescr()->pTypeName->buffer,
544                                     "com.sun.star.uno.XInterface::acquire" ) == 0)
545         {
546             (*ifc)->acquire();
547             return Any();
548         }
549         else if (rtl_ustr_ascii_compare( getTypeDescr()->pTypeName->buffer,
550                                          "com.sun.star.uno.XInterface::release" ) == 0)
551         {
552             (*ifc)->release();
553             return Any();
554         }
555     }
556 
557     uno_Interface * pUnoI = getReflection()->mapToUno(
558         rObj, reinterpret_cast<typelib_InterfaceTypeDescription *>(getDeclTypeDescr()) );
559     OSL_ENSURE( pUnoI, "### illegal destination object given!" );
560     if (pUnoI)
561     {
562         sal_Int32 nParams = getMethodTypeDescr()->nParams;
563         if (rArgs.getLength() != nParams)
564         {
565             (*pUnoI->release)( pUnoI );
566             throw IllegalArgumentException(
567                 "expected " + OUString::number(nParams) +
568                  " arguments, got " + OUString::number(rArgs.getLength()),
569                 *o3tl::doAccess<Reference<XInterface>>(rObj), 1 );
570         }
571 
572         Any * pCppArgs = rArgs.getArray();
573         typelib_MethodParameter * pParams = getMethodTypeDescr()->pParams;
574         typelib_TypeDescription * pReturnType = nullptr;
575         TYPELIB_DANGER_GET(
576             &pReturnType, getMethodTypeDescr()->pReturnTypeRef );
577 
578         // C/C++ ABIs typically assume that structs are padded at the end, and
579         // that those padding bytes may be written to (e.g., to write into the
580         // end of a "short" struct by writing the full contents of a "long"
581         // register); so create enough space here (assuming that no ABI requires
582         // padding larger than 16 byte boundaries):
583         void * pUnoReturn = (pReturnType->nSize == 0) ? nullptr : alloca( multipleOf16(pReturnType->nSize) );
584         void ** ppUnoArgs = static_cast<void **>(alloca( sizeof(void *) * nParams *2 ));
585         typelib_TypeDescription ** ppParamTypes = reinterpret_cast<typelib_TypeDescription **>(ppUnoArgs + nParams);
586 
587         // convert arguments
588         for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
589         {
590             ppParamTypes[nPos] = nullptr;
591             TYPELIB_DANGER_GET( ppParamTypes + nPos, pParams[nPos].pTypeRef );
592             typelib_TypeDescription * pTD = ppParamTypes[nPos];
593 
594             ppUnoArgs[nPos] = alloca( pTD->nSize );
595             if (pParams[nPos].bIn)
596             {
597                 bool bAssign;
598                 if (typelib_typedescriptionreference_equals(
599                         pCppArgs[nPos].getValueTypeRef(), pTD->pWeakRef ))
600                 {
601                     uno_type_copyAndConvertData(
602                         ppUnoArgs[nPos], const_cast<void *>(pCppArgs[nPos].getValue()),
603                         pCppArgs[nPos].getValueTypeRef(), getReflection()->getCpp2Uno().get() );
604                     bAssign = true;
605                 }
606                 else if (pTD->eTypeClass == typelib_TypeClass_ANY)
607                 {
608                     uno_type_any_constructAndConvert(
609                         static_cast<uno_Any *>(ppUnoArgs[nPos]), const_cast<void *>(pCppArgs[nPos].getValue()),
610                         pCppArgs[nPos].getValueTypeRef(), getReflection()->getCpp2Uno().get() );
611                     bAssign = true;
612                 }
613                 else if (pTD->eTypeClass == typelib_TypeClass_INTERFACE)
614                 {
615                     Reference< XInterface > xDest;
616                     bAssign = extract(
617                         pCppArgs[nPos], reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD),
618                         xDest, getReflection() );
619                     if (bAssign)
620                     {
621                         *static_cast<void **>(ppUnoArgs[nPos]) = getReflection()->getCpp2Uno().mapInterface(
622                             xDest.get(), reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD) );
623                     }
624                 }
625                 else
626                 {
627                     typelib_TypeDescription * pValueTD = nullptr;
628                     TYPELIB_DANGER_GET( &pValueTD, pCppArgs[nPos].getValueTypeRef() );
629                     // construct temp uno val to do proper assignment: todo opt
630                     void * pTemp = alloca( pValueTD->nSize );
631                     uno_copyAndConvertData(
632                         pTemp, const_cast<void *>(pCppArgs[nPos].getValue()), pValueTD,
633                         getReflection()->getCpp2Uno().get() );
634                     uno_constructData(
635                         ppUnoArgs[nPos], pTD );
636                     // assignment does simple conversion
637                     bAssign = uno_assignData(
638                         ppUnoArgs[nPos], pTD, pTemp, pValueTD, nullptr, nullptr, nullptr );
639                     uno_destructData(
640                         pTemp, pValueTD, nullptr );
641                     TYPELIB_DANGER_RELEASE( pValueTD );
642                 }
643 
644                 if (! bAssign)
645                 {
646                     IllegalArgumentException aExc(
647                         "cannot coerce argument type during corereflection call:"
648                         "\narg no.: " + OUString::number(nPos)
649                         + " expected: \"" + OUString::unacquired(&pTD->pTypeName)
650                         + "\" actual: \"" + OUString::unacquired(&pCppArgs[nPos].getValueTypeRef()->pTypeName)
651                         + "\"",
652                         *o3tl::doAccess<Reference<XInterface>>(rObj), static_cast<sal_Int16>(nPos) );
653 
654                     // cleanup
655                     while (nPos--)
656                     {
657                         if (pParams[nPos].bIn)
658                             uno_destructData( ppUnoArgs[nPos], ppParamTypes[nPos], nullptr );
659                         TYPELIB_DANGER_RELEASE( ppParamTypes[nPos] );
660                     }
661                     TYPELIB_DANGER_RELEASE( pReturnType );
662                     (*pUnoI->release)( pUnoI );
663 
664                     throw aExc;
665                 }
666             }
667         }
668 
669         uno_Any aUnoExc;
670         uno_Any * pUnoExc = &aUnoExc;
671 
672         (*pUnoI->pDispatcher)(
673             pUnoI, getTypeDescr(), pUnoReturn, ppUnoArgs, &pUnoExc );
674         (*pUnoI->release)( pUnoI );
675 
676         Any aRet;
677         if (pUnoExc)
678         {
679             // cleanup
680             while (nParams--)
681             {
682                 if (pParams[nParams].bIn)
683                     uno_destructData( ppUnoArgs[nParams], ppParamTypes[nParams], nullptr );
684                 TYPELIB_DANGER_RELEASE( ppParamTypes[nParams] );
685             }
686             TYPELIB_DANGER_RELEASE( pReturnType );
687 
688             InvocationTargetException aExc;
689             aExc.Context = *o3tl::doAccess<Reference<XInterface>>(rObj);
690             aExc.Message = "exception occurred during invocation!";
691             uno_any_destruct(
692                 &aExc.TargetException,
693                 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
694             uno_type_copyAndConvertData(
695                 &aExc.TargetException, pUnoExc, cppu::UnoType<Any>::get().getTypeLibType(),
696                 getReflection()->getUno2Cpp().get() );
697             uno_any_destruct( pUnoExc, nullptr );
698             throw aExc;
699         }
700         else
701         {
702             // reconvert arguments and cleanup
703             while (nParams--)
704             {
705                 if (pParams[nParams].bOut) // write back
706                 {
707                     uno_any_destruct(
708                         &pCppArgs[nParams],
709                         reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
710                     uno_any_constructAndConvert(
711                         &pCppArgs[nParams], ppUnoArgs[nParams], ppParamTypes[nParams],
712                         getReflection()->getUno2Cpp().get() );
713                 }
714                 uno_destructData( ppUnoArgs[nParams], ppParamTypes[nParams], nullptr );
715                 TYPELIB_DANGER_RELEASE( ppParamTypes[nParams] );
716             }
717             uno_any_destruct(
718                 &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
719             uno_any_constructAndConvert(
720                 &aRet, pUnoReturn, pReturnType,
721                 getReflection()->getUno2Cpp().get() );
722             uno_destructData( pUnoReturn, pReturnType, nullptr );
723             TYPELIB_DANGER_RELEASE( pReturnType );
724         }
725         return aRet;
726     }
727     throw IllegalArgumentException(
728         "illegal destination object given!",
729         static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
730 }
731 
732 
~InterfaceIdlClassImpl()733 InterfaceIdlClassImpl::~InterfaceIdlClassImpl()
734 {
735     for ( sal_Int32 nPos = _nMethods + _nAttributes; nPos--; )
736         typelib_typedescription_release( _pSortedMemberInit[nPos].second );
737 }
738 
739 
getSuperclasses()740 Sequence< Reference< XIdlClass > > InterfaceIdlClassImpl::getSuperclasses()
741 {
742     ::osl::MutexGuard aGuard(getMutexAccess());
743     if (!_xSuperClasses.hasElements()) {
744         typelib_InterfaceTypeDescription * pType = getTypeDescr();
745         _xSuperClasses.realloc(pType->nBaseTypes);
746         for (sal_Int32 i = 0; i < pType->nBaseTypes; ++i) {
747             _xSuperClasses[i] = getReflection()->forType(
748                 &pType->ppBaseTypes[i]->aBase);
749             OSL_ASSERT(_xSuperClasses[i].is());
750         }
751     }
752     return _xSuperClasses;
753 }
754 
initMembers()755 void InterfaceIdlClassImpl::initMembers()
756 {
757     sal_Int32 nAll = getTypeDescr()->nAllMembers;
758     std::unique_ptr<MemberInit[]> pSortedMemberInit(new MemberInit[nAll]);
759     typelib_TypeDescriptionReference ** ppAllMembers = getTypeDescr()->ppAllMembers;
760 
761     for ( sal_Int32 nPos = 0; nPos < nAll; ++nPos )
762     {
763         sal_Int32 nIndex;
764         if (ppAllMembers[nPos]->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
765         {
766             // methods to front
767             nIndex = _nMethods;
768             ++_nMethods;
769         }
770         else
771         {
772             ++_nAttributes;
773             nIndex = (nAll - _nAttributes);
774             // attributes at the back
775         }
776 
777         typelib_TypeDescription * pTD = nullptr;
778         typelib_typedescriptionreference_getDescription( &pTD, ppAllMembers[nPos] );
779         assert(pTD && "### cannot get type description!");
780         pSortedMemberInit[nIndex].first = reinterpret_cast<typelib_InterfaceMemberTypeDescription *>(pTD)->pMemberName;
781         pSortedMemberInit[nIndex].second = pTD;
782     }
783 
784     _pSortedMemberInit = std::move(pSortedMemberInit);
785 }
786 
isAssignableFrom(const Reference<XIdlClass> & xType)787 sal_Bool InterfaceIdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType )
788 {
789     if (xType.is() && xType->getTypeClass() == TypeClass_INTERFACE)
790     {
791         if (equals( xType ))
792             return true;
793         else
794         {
795             const Sequence< Reference< XIdlClass > > & rSeq = xType->getSuperclasses();
796             if (std::any_of(rSeq.begin(), rSeq.end(),
797                     [this](const Reference<XIdlClass>& rType){ return isAssignableFrom(rType); }))
798                 return true;
799         }
800     }
801     return false;
802 }
803 
getUik()804 Uik InterfaceIdlClassImpl::getUik()
805 {
806     return Uik(0, 0, 0, 0, 0);
807         // Uiks are deprecated and this function must not be called
808 }
809 
getMethods()810 Sequence< Reference< XIdlMethod > > InterfaceIdlClassImpl::getMethods()
811 {
812     ::osl::MutexGuard aGuard( getMutexAccess() );
813     if (! _pSortedMemberInit)
814         initMembers();
815 
816     // create methods sequence
817     Sequence< Reference< XIdlMethod > > aRet( _nMethods );
818     Reference< XIdlMethod > * pRet = aRet.getArray();
819     for ( sal_Int32 nPos = _nMethods; nPos--; )
820     {
821 
822         /*_aName2Method[_pSortedMemberInit[nPos].first] = */pRet[nPos] = new IdlInterfaceMethodImpl(
823             getReflection(), _pSortedMemberInit[nPos].first,
824             _pSortedMemberInit[nPos].second, IdlClassImpl::getTypeDescr() );
825     }
826     return aRet;
827 }
828 
getFields()829 Sequence< Reference< XIdlField > > InterfaceIdlClassImpl::getFields()
830 {
831     ::osl::MutexGuard aGuard( getMutexAccess() );
832     if (! _pSortedMemberInit)
833         initMembers();
834 
835     // create fields sequence
836     Sequence< Reference< XIdlField > > aRet( _nAttributes );
837     Reference< XIdlField > * pRet = aRet.getArray();
838     for ( sal_Int32 nPos = _nAttributes; nPos--; )
839     {
840         /*_aName2Field[_pSortedMemberInit[_nMethods+nPos].first] = */pRet[_nAttributes-nPos-1] =
841             new IdlAttributeFieldImpl(
842                 getReflection(), _pSortedMemberInit[_nMethods+nPos].first,
843                 _pSortedMemberInit[_nMethods+nPos].second, IdlClassImpl::getTypeDescr() );
844     }
845     return aRet;
846 }
847 
getMethod(const OUString & rName)848 Reference< XIdlMethod > InterfaceIdlClassImpl::getMethod( const OUString & rName )
849 {
850     ::osl::MutexGuard aGuard( getMutexAccess() );
851     if (! _pSortedMemberInit)
852         initMembers();
853 
854     Reference< XIdlMethod > xRet;
855 
856     // try weak map
857     const OUString2Method::const_iterator iFind( _aName2Method.find( rName ) );
858     if (iFind != _aName2Method.end())
859         xRet = (*iFind).second; // harden ref
860 
861     if (! xRet.is())
862     {
863         for ( sal_Int32 nPos = _nMethods; nPos--; )
864         {
865             if (_pSortedMemberInit[nPos].first == rName)
866             {
867                 _aName2Method[rName] = xRet = new IdlInterfaceMethodImpl(
868                     getReflection(), rName,
869                     _pSortedMemberInit[nPos].second, IdlClassImpl::getTypeDescr() );
870                 break;
871             }
872         }
873     }
874     return xRet;
875 }
876 
getField(const OUString & rName)877 Reference< XIdlField > InterfaceIdlClassImpl::getField( const OUString & rName )
878 {
879     ::osl::MutexGuard aGuard( getMutexAccess() );
880     if (! _pSortedMemberInit)
881         initMembers();
882 
883     Reference< XIdlField > xRet;
884 
885     // try weak map
886     const OUString2Field::const_iterator iFind( _aName2Field.find( rName ) );
887     if (iFind != _aName2Field.end())
888         xRet = (*iFind).second; // harden ref
889 
890     if (! xRet.is())
891     {
892         for ( sal_Int32 nPos = _nAttributes; nPos--; )
893         {
894             if (_pSortedMemberInit[_nMethods+nPos].first == rName)
895             {
896                 _aName2Field[rName] = xRet = new IdlAttributeFieldImpl(
897                     getReflection(), rName,
898                     _pSortedMemberInit[_nMethods+nPos].second, IdlClassImpl::getTypeDescr() );
899                 break;
900             }
901         }
902     }
903     return xRet;
904 }
905 
createObject(Any & rObj)906 void InterfaceIdlClassImpl::createObject( Any & rObj )
907 {
908     // interfaces cannot be constructed
909     rObj.clear();
910 }
911 
912 }
913 
914 
915 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
916