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 <o3tl/any.hxx> 23 #include <osl/mutex.hxx> 24 #include <vcl/svapp.hxx> 25 #include <vcl/errcode.hxx> 26 #include <svl/hint.hxx> 27 28 #include <cppuhelper/implbase.hxx> 29 #include <cppuhelper/exc_hlp.hxx> 30 #include <cppuhelper/typeprovider.hxx> 31 #include <comphelper/interfacecontainer2.hxx> 32 #include <comphelper/extract.hxx> 33 #include <comphelper/processfactory.hxx> 34 #include <cppuhelper/weakref.hxx> 35 36 #include <rtl/instance.hxx> 37 #include <rtl/strbuf.hxx> 38 #include <rtl/ustrbuf.hxx> 39 40 #include <com/sun/star/script/ArrayWrapper.hpp> 41 #include <com/sun/star/script/CannotConvertException.hpp> 42 #include <com/sun/star/script/NativeObjectWrapper.hpp> 43 44 #include <com/sun/star/uno/XComponentContext.hpp> 45 #include <com/sun/star/uno/DeploymentException.hpp> 46 #include <com/sun/star/lang/XTypeProvider.hpp> 47 #include <com/sun/star/lang/XSingleServiceFactory.hpp> 48 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 49 #include <com/sun/star/lang/XServiceInfo.hpp> 50 #include <com/sun/star/beans/PropertyAttribute.hpp> 51 #include <com/sun/star/beans/PropertyConcept.hpp> 52 #include <com/sun/star/beans/MethodConcept.hpp> 53 #include <com/sun/star/beans/XPropertySet.hpp> 54 #include <com/sun/star/beans/theIntrospection.hpp> 55 #include <com/sun/star/script/BasicErrorException.hpp> 56 #include <com/sun/star/script/InvocationAdapterFactory.hpp> 57 #include <com/sun/star/script/XAllListener.hpp> 58 #include <com/sun/star/script/XInvocationAdapterFactory.hpp> 59 #include <com/sun/star/script/Converter.hpp> 60 #include <com/sun/star/script/XDefaultProperty.hpp> 61 #include <com/sun/star/script/XDirectInvocation.hpp> 62 #include <com/sun/star/container/XNameAccess.hpp> 63 #include <com/sun/star/container/XHierarchicalNameAccess.hpp> 64 #include <com/sun/star/reflection/XIdlArray.hpp> 65 #include <com/sun/star/reflection/XIdlReflection.hpp> 66 #include <com/sun/star/reflection/XServiceConstructorDescription.hpp> 67 #include <com/sun/star/reflection/theCoreReflection.hpp> 68 #include <com/sun/star/bridge/oleautomation/NamedArgument.hpp> 69 #include <com/sun/star/bridge/oleautomation/Date.hpp> 70 #include <com/sun/star/bridge/oleautomation/Decimal.hpp> 71 #include <com/sun/star/bridge/oleautomation/Currency.hpp> 72 #include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp> 73 #include <com/sun/star/script/XAutomationInvocation.hpp> 74 #include <basic/codecompletecache.hxx> 75 76 #include <rtlproto.hxx> 77 78 #include <basic/sbstar.hxx> 79 #include <basic/sbuno.hxx> 80 #include <basic/sberrors.hxx> 81 #include <sbunoobj.hxx> 82 #include <sbjsmod.hxx> 83 #include <basic/basmgr.hxx> 84 #include <sbintern.hxx> 85 #include <runtime.hxx> 86 87 #include <math.h> 88 #include <memory> 89 #include <unordered_map> 90 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> 91 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp> 92 93 using com::sun::star::uno::Reference; 94 using namespace com::sun::star::uno; 95 using namespace com::sun::star::lang; 96 using namespace com::sun::star::reflection; 97 using namespace com::sun::star::beans; 98 using namespace com::sun::star::script; 99 using namespace com::sun::star::container; 100 using namespace com::sun::star::bridge; 101 using namespace cppu; 102 103 104 // Identifiers for creating the strings for dbg_Properties 105 static char const ID_DBG_SUPPORTEDINTERFACES[] = "Dbg_SupportedInterfaces"; 106 static char const ID_DBG_PROPERTIES[] = "Dbg_Properties"; 107 static char const ID_DBG_METHODS[] = "Dbg_Methods"; 108 109 static char const aSeqLevelStr[] = "[]"; 110 111 // Gets the default property for a uno object. Note: There is some 112 // redirection built in. The property name specifies the name 113 // of the default property. 114 115 bool SbUnoObject::getDefaultPropName( SbUnoObject const * pUnoObj, OUString& sDfltProp ) 116 { 117 bool bResult = false; 118 Reference< XDefaultProperty> xDefaultProp( pUnoObj->maTmpUnoObj, UNO_QUERY ); 119 if ( xDefaultProp.is() ) 120 { 121 sDfltProp = xDefaultProp->getDefaultPropertyName(); 122 if ( !sDfltProp.isEmpty() ) 123 bResult = true; 124 } 125 return bResult; 126 } 127 128 SbxVariable* getDefaultProp( SbxVariable* pRef ) 129 { 130 SbxVariable* pDefaultProp = nullptr; 131 if ( pRef->GetType() == SbxOBJECT ) 132 { 133 SbxObject* pObj = dynamic_cast<SbxObject*>(pRef); 134 if (!pObj) 135 { 136 SbxBase* pObjVarObj = pRef->GetObject(); 137 pObj = dynamic_cast<SbxObject*>( pObjVarObj ); 138 } 139 if (SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>(pObj)) 140 { 141 pDefaultProp = pUnoObj->GetDfltProperty(); 142 } 143 } 144 return pDefaultProp; 145 } 146 147 void SetSbUnoObjectDfltPropName( SbxObject* pObj ) 148 { 149 SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>( pObj ); 150 if ( pUnoObj ) 151 { 152 OUString sDfltPropName; 153 154 if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) ) 155 { 156 pUnoObj->SetDfltProperty( sDfltPropName ); 157 } 158 } 159 } 160 161 // save CoreReflection statically 162 static Reference< XIdlReflection > getCoreReflection_Impl() 163 { 164 return css::reflection::theCoreReflection::get( 165 comphelper::getProcessComponentContext()); 166 } 167 168 // save CoreReflection statically 169 static Reference< XHierarchicalNameAccess > const & getCoreReflection_HierarchicalNameAccess_Impl() 170 { 171 static Reference< XHierarchicalNameAccess > xCoreReflection_HierarchicalNameAccess; 172 173 if( !xCoreReflection_HierarchicalNameAccess.is() ) 174 { 175 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); 176 if( xCoreReflection.is() ) 177 { 178 xCoreReflection_HierarchicalNameAccess = 179 Reference< XHierarchicalNameAccess >( xCoreReflection, UNO_QUERY ); 180 } 181 } 182 return xCoreReflection_HierarchicalNameAccess; 183 } 184 185 // Hold TypeProvider statically 186 static Reference< XHierarchicalNameAccess > const & getTypeProvider_Impl() 187 { 188 static Reference< XHierarchicalNameAccess > xAccess; 189 190 // Do we have already CoreReflection; if not obtain it 191 if( !xAccess.is() ) 192 { 193 Reference< XComponentContext > xContext( 194 comphelper::getProcessComponentContext() ); 195 if( xContext.is() ) 196 { 197 xContext->getValueByName( 198 "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) 199 >>= xAccess; 200 OSL_ENSURE( xAccess.is(), "### TypeDescriptionManager singleton not accessible!?" ); 201 } 202 if( !xAccess.is() ) 203 { 204 throw DeploymentException( 205 "/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessible" ); 206 } 207 } 208 return xAccess; 209 } 210 211 // Hold TypeConverter statically 212 static Reference< XTypeConverter > const & getTypeConverter_Impl() 213 { 214 static Reference< XTypeConverter > xTypeConverter; 215 216 // Do we have already CoreReflection; if not obtain it 217 if( !xTypeConverter.is() ) 218 { 219 Reference< XComponentContext > xContext( 220 comphelper::getProcessComponentContext() ); 221 if( xContext.is() ) 222 { 223 xTypeConverter = Converter::create(xContext); 224 } 225 if( !xTypeConverter.is() ) 226 { 227 throw DeploymentException( 228 "com.sun.star.script.Converter service not accessible" ); 229 } 230 } 231 return xTypeConverter; 232 } 233 234 235 // #111851 factory function to create an OLE object 236 SbUnoObject* createOLEObject_Impl( const OUString& aType ) 237 { 238 static Reference< XMultiServiceFactory > xOLEFactory; 239 static bool bNeedsInit = true; 240 241 if( bNeedsInit ) 242 { 243 bNeedsInit = false; 244 245 Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() ); 246 if( xContext.is() ) 247 { 248 Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager(); 249 xOLEFactory.set( 250 xSMgr->createInstanceWithContext( "com.sun.star.bridge.OleObjectFactory", xContext ), 251 UNO_QUERY ); 252 } 253 } 254 255 SbUnoObject* pUnoObj = nullptr; 256 if( xOLEFactory.is() ) 257 { 258 // some type names available in VBA can not be directly used in COM 259 OUString aOLEType = aType; 260 if ( aOLEType == "SAXXMLReader30" ) 261 { 262 aOLEType = "Msxml2.SAXXMLReader.3.0"; 263 } 264 Reference< XInterface > xOLEObject = xOLEFactory->createInstance( aOLEType ); 265 if( xOLEObject.is() ) 266 { 267 pUnoObj = new SbUnoObject( aType, Any(xOLEObject) ); 268 OUString sDfltPropName; 269 270 if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) ) 271 pUnoObj->SetDfltProperty( sDfltPropName ); 272 } 273 } 274 return pUnoObj; 275 } 276 277 278 namespace 279 { 280 void lcl_indent( OUStringBuffer& _inout_rBuffer, sal_Int32 _nLevel ) 281 { 282 while ( _nLevel-- > 0 ) 283 { 284 _inout_rBuffer.append( " " ); 285 } 286 } 287 } 288 289 static void implAppendExceptionMsg( OUStringBuffer& _inout_rBuffer, const Exception& _e, const OUString& _rExceptionType, sal_Int32 _nLevel ) 290 { 291 _inout_rBuffer.append( "\n" ); 292 lcl_indent( _inout_rBuffer, _nLevel ); 293 _inout_rBuffer.append( "Type: " ); 294 295 if ( _rExceptionType.isEmpty() ) 296 _inout_rBuffer.append( "Unknown" ); 297 else 298 _inout_rBuffer.append( _rExceptionType ); 299 300 _inout_rBuffer.append( "\n" ); 301 lcl_indent( _inout_rBuffer, _nLevel ); 302 _inout_rBuffer.append( "Message: " ); 303 _inout_rBuffer.append( _e.Message ); 304 305 } 306 307 // construct an error message for the exception 308 static OUString implGetExceptionMsg( const Exception& e, const OUString& aExceptionType_ ) 309 { 310 OUStringBuffer aMessageBuf; 311 implAppendExceptionMsg( aMessageBuf, e, aExceptionType_, 0 ); 312 return aMessageBuf.makeStringAndClear(); 313 } 314 315 static OUString implGetExceptionMsg( const Any& _rCaughtException ) 316 { 317 auto e = o3tl::tryAccess<Exception>(_rCaughtException); 318 OSL_PRECOND( e, "implGetExceptionMsg: illegal argument!" ); 319 if ( !e ) 320 { 321 return OUString(); 322 } 323 return implGetExceptionMsg( *e, _rCaughtException.getValueTypeName() ); 324 } 325 326 static Any convertAny( const Any& rVal, const Type& aDestType ) 327 { 328 Any aConvertedVal; 329 const Reference< XTypeConverter >& xConverter = getTypeConverter_Impl(); 330 try 331 { 332 aConvertedVal = xConverter->convertTo( rVal, aDestType ); 333 } 334 catch( const IllegalArgumentException& ) 335 { 336 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, 337 implGetExceptionMsg( ::cppu::getCaughtException() ) ); 338 return aConvertedVal; 339 } 340 catch( const CannotConvertException& e2 ) 341 { 342 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, 343 implGetExceptionMsg( e2, "com.sun.star.lang.IllegalArgumentException" ) ); 344 return aConvertedVal; 345 } 346 return aConvertedVal; 347 } 348 349 350 // #105565 Special Object to wrap a strongly typed Uno Any 351 352 353 // TODO: source out later 354 static Reference<XIdlClass> TypeToIdlClass( const Type& rType ) 355 { 356 return getCoreReflection_Impl()->forName(rType.getTypeName()); 357 } 358 359 // Exception type unknown 360 template< class EXCEPTION > 361 static OUString implGetExceptionMsg( const EXCEPTION& e ) 362 { 363 return implGetExceptionMsg( e, cppu::UnoType<decltype(e)>::get().getTypeName() ); 364 } 365 366 static void implHandleBasicErrorException( BasicErrorException const & e ) 367 { 368 ErrCode nError = StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16>(e.ErrorCode) ); 369 StarBASIC::Error( nError, e.ErrorMessageArgument ); 370 } 371 372 static void implHandleWrappedTargetException( const Any& _rWrappedTargetException ) 373 { 374 Any aExamine( _rWrappedTargetException ); 375 376 // completely strip the first InvocationTargetException, its error message isn't of any 377 // interest to the user, it just says something like "invoking the UNO method went wrong.". 378 InvocationTargetException aInvocationError; 379 if ( aExamine >>= aInvocationError ) 380 aExamine = aInvocationError.TargetException; 381 382 BasicErrorException aBasicError; 383 384 ErrCode nError( ERRCODE_BASIC_EXCEPTION ); 385 OUStringBuffer aMessageBuf; 386 387 // strip any other WrappedTargetException instances, but this time preserve the error messages. 388 WrappedTargetException aWrapped; 389 sal_Int32 nLevel = 0; 390 while ( aExamine >>= aWrapped ) 391 { 392 // special handling for BasicErrorException errors 393 if ( aWrapped.TargetException >>= aBasicError ) 394 { 395 nError = StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16>(aBasicError.ErrorCode) ); 396 aMessageBuf.append( aBasicError.ErrorMessageArgument ); 397 aExamine.clear(); 398 break; 399 } 400 401 // append this round's message 402 implAppendExceptionMsg( aMessageBuf, aWrapped, aExamine.getValueTypeName(), nLevel ); 403 if ( aWrapped.TargetException.getValueTypeClass() == TypeClass_EXCEPTION ) 404 // there is a next chain element 405 aMessageBuf.append( "\nTargetException:" ); 406 407 // next round 408 aExamine = aWrapped.TargetException; 409 ++nLevel; 410 } 411 412 if ( auto e = o3tl::tryAccess<Exception>(aExamine) ) 413 { 414 // the last element in the chain is still an exception, but no WrappedTargetException 415 implAppendExceptionMsg( aMessageBuf, *e, aExamine.getValueTypeName(), nLevel ); 416 } 417 418 StarBASIC::Error( nError, aMessageBuf.makeStringAndClear() ); 419 } 420 421 static void implHandleAnyException( const Any& _rCaughtException ) 422 { 423 BasicErrorException aBasicError; 424 WrappedTargetException aWrappedError; 425 426 if ( _rCaughtException >>= aBasicError ) 427 { 428 implHandleBasicErrorException( aBasicError ); 429 } 430 else if ( _rCaughtException >>= aWrappedError ) 431 { 432 implHandleWrappedTargetException( _rCaughtException ); 433 } 434 else 435 { 436 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( _rCaughtException ) ); 437 } 438 } 439 440 // NativeObjectWrapper handling 441 struct ObjectItem 442 { 443 SbxObjectRef m_xNativeObj; 444 445 explicit ObjectItem( SbxObject* pNativeObj ) 446 : m_xNativeObj( pNativeObj ) 447 {} 448 }; 449 450 typedef std::vector< ObjectItem > NativeObjectWrapperVector; 451 class GaNativeObjectWrapperVector : public rtl::Static<NativeObjectWrapperVector, GaNativeObjectWrapperVector> {}; 452 453 void clearNativeObjectWrapperVector() 454 { 455 GaNativeObjectWrapperVector::get().clear(); 456 } 457 458 static sal_uInt32 lcl_registerNativeObjectWrapper( SbxObject* pNativeObj ) 459 { 460 NativeObjectWrapperVector &rNativeObjectWrapperVector = GaNativeObjectWrapperVector::get(); 461 sal_uInt32 nIndex = rNativeObjectWrapperVector.size(); 462 rNativeObjectWrapperVector.emplace_back( pNativeObj ); 463 return nIndex; 464 } 465 466 static SbxObject* lcl_getNativeObject( sal_uInt32 nIndex ) 467 { 468 SbxObjectRef xRetObj; 469 NativeObjectWrapperVector &rNativeObjectWrapperVector = GaNativeObjectWrapperVector::get(); 470 if( nIndex < rNativeObjectWrapperVector.size() ) 471 { 472 ObjectItem& rItem = rNativeObjectWrapperVector[ nIndex ]; 473 xRetObj = rItem.m_xNativeObj; 474 } 475 return xRetObj.get(); 476 } 477 478 // convert from Uno to Sbx 479 static SbxDataType unoToSbxType( TypeClass eType ) 480 { 481 SbxDataType eRetType = SbxVOID; 482 483 switch( eType ) 484 { 485 case TypeClass_INTERFACE: 486 case TypeClass_TYPE: 487 case TypeClass_STRUCT: 488 case TypeClass_EXCEPTION: eRetType = SbxOBJECT; break; 489 490 case TypeClass_ENUM: eRetType = SbxLONG; break; 491 case TypeClass_SEQUENCE: 492 eRetType = SbxDataType( SbxOBJECT | SbxARRAY ); 493 break; 494 495 496 case TypeClass_ANY: eRetType = SbxVARIANT; break; 497 case TypeClass_BOOLEAN: eRetType = SbxBOOL; break; 498 case TypeClass_CHAR: eRetType = SbxCHAR; break; 499 case TypeClass_STRING: eRetType = SbxSTRING; break; 500 case TypeClass_FLOAT: eRetType = SbxSINGLE; break; 501 case TypeClass_DOUBLE: eRetType = SbxDOUBLE; break; 502 case TypeClass_BYTE: eRetType = SbxINTEGER; break; 503 case TypeClass_SHORT: eRetType = SbxINTEGER; break; 504 case TypeClass_LONG: eRetType = SbxLONG; break; 505 case TypeClass_HYPER: eRetType = SbxSALINT64; break; 506 case TypeClass_UNSIGNED_SHORT: eRetType = SbxUSHORT; break; 507 case TypeClass_UNSIGNED_LONG: eRetType = SbxULONG; break; 508 case TypeClass_UNSIGNED_HYPER: eRetType = SbxSALUINT64;break; 509 default: break; 510 } 511 return eRetType; 512 } 513 514 static SbxDataType unoToSbxType( const Reference< XIdlClass >& xIdlClass ) 515 { 516 SbxDataType eRetType = SbxVOID; 517 if( xIdlClass.is() ) 518 { 519 TypeClass eType = xIdlClass->getTypeClass(); 520 eRetType = unoToSbxType( eType ); 521 } 522 return eRetType; 523 } 524 525 static void implSequenceToMultiDimArray( SbxDimArray*& pArray, Sequence< sal_Int32 >& indices, Sequence< sal_Int32 >& sizes, const Any& aValue, sal_Int32 dimension, bool bIsZeroIndex, Type const * pType ) 526 { 527 const Type& aType = aValue.getValueType(); 528 TypeClass eTypeClass = aType.getTypeClass(); 529 530 sal_Int32 dimCopy = dimension; 531 532 if ( eTypeClass == TypeClass_SEQUENCE ) 533 { 534 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType ); 535 Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray(); 536 typelib_TypeDescription * pTD = nullptr; 537 aType.getDescription( &pTD ); 538 Type aElementType( reinterpret_cast<typelib_IndirectTypeDescription *>(pTD)->pType ); 539 ::typelib_typedescription_release( pTD ); 540 541 sal_Int32 nLen = xIdlArray->getLen( aValue ); 542 for ( sal_Int32 index = 0; index < nLen; ++index ) 543 { 544 Any aElementAny = xIdlArray->get( aValue, static_cast<sal_uInt32>(index) ); 545 // This detects the dimension were currently processing 546 if ( dimCopy == dimension ) 547 { 548 ++dimCopy; 549 if ( sizes.getLength() < dimCopy ) 550 { 551 sizes.realloc( sizes.getLength() + 1 ); 552 sizes[ sizes.getLength() - 1 ] = nLen; 553 indices.realloc( indices.getLength() + 1 ); 554 } 555 } 556 557 if ( bIsZeroIndex ) 558 indices[ dimCopy - 1 ] = index; 559 else 560 indices[ dimCopy - 1] = index + 1; 561 562 implSequenceToMultiDimArray( pArray, indices, sizes, aElementAny, dimCopy, bIsZeroIndex, &aElementType ); 563 } 564 565 } 566 else 567 { 568 if ( indices.getLength() < 1 ) 569 { 570 // Should never ever get here ( indices.getLength() 571 // should equal number of dimensions in the array ) 572 // And that should at least be 1 ! 573 // #QUESTION is there a better error? 574 StarBASIC::Error( ERRCODE_BASIC_INVALID_OBJECT ); 575 return; 576 } 577 578 SbxDataType eSbxElementType = unoToSbxType( pType ? pType->getTypeClass() : aValue.getValueTypeClass() ); 579 if ( !pArray ) 580 { 581 pArray = new SbxDimArray( eSbxElementType ); 582 sal_Int32 nIndexLen = indices.getLength(); 583 584 // Dimension the array 585 for ( sal_Int32 index = 0; index < nIndexLen; ++index ) 586 { 587 if ( bIsZeroIndex ) 588 pArray->unoAddDim32( 0, sizes[ index ] - 1); 589 else 590 pArray->unoAddDim32( 1, sizes[ index ] ); 591 592 } 593 } 594 595 if ( pArray ) 596 { 597 auto xVar = tools::make_ref<SbxVariable>( eSbxElementType ); 598 unoToSbxValue( xVar.get(), aValue ); 599 600 sal_Int32* pIndices = indices.getArray(); 601 pArray->Put32( xVar.get(), pIndices ); 602 603 } 604 } 605 } 606 607 void unoToSbxValue( SbxVariable* pVar, const Any& aValue ) 608 { 609 const Type& aType = aValue.getValueType(); 610 TypeClass eTypeClass = aType.getTypeClass(); 611 switch( eTypeClass ) 612 { 613 case TypeClass_TYPE: 614 { 615 // Map Type to IdlClass 616 Type aType_; 617 aValue >>= aType_; 618 Reference<XIdlClass> xClass = TypeToIdlClass( aType_ ); 619 Any aClassAny; 620 aClassAny <<= xClass; 621 622 // instantiate SbUnoObject 623 SbUnoObject* pSbUnoObject = new SbUnoObject( OUString(), aClassAny ); 624 SbxObjectRef xWrapper = static_cast<SbxObject*>(pSbUnoObject); 625 626 // If the object is invalid deliver null 627 if( !pSbUnoObject->getUnoAny().hasValue() ) 628 { 629 pVar->PutObject( nullptr ); 630 } 631 else 632 { 633 pVar->PutObject( xWrapper.get() ); 634 } 635 } 636 break; 637 // Interfaces and Structs must be wrapped in a SbUnoObject 638 case TypeClass_INTERFACE: 639 case TypeClass_STRUCT: 640 case TypeClass_EXCEPTION: 641 { 642 if( eTypeClass == TypeClass_STRUCT ) 643 { 644 ArrayWrapper aWrap; 645 NativeObjectWrapper aNativeObjectWrapper; 646 if ( aValue >>= aWrap ) 647 { 648 SbxDimArray* pArray = nullptr; 649 Sequence< sal_Int32 > indices; 650 Sequence< sal_Int32 > sizes; 651 implSequenceToMultiDimArray( pArray, indices, sizes, aWrap.Array, /*dimension*/0, aWrap.IsZeroIndex, nullptr ); 652 if ( pArray ) 653 { 654 SbxDimArrayRef xArray = pArray; 655 SbxFlagBits nFlags = pVar->GetFlags(); 656 pVar->ResetFlag( SbxFlagBits::Fixed ); 657 pVar->PutObject( xArray.get() ); 658 pVar->SetFlags( nFlags ); 659 } 660 else 661 pVar->PutEmpty(); 662 break; 663 } 664 else if ( aValue >>= aNativeObjectWrapper ) 665 { 666 sal_uInt32 nIndex = 0; 667 if( aNativeObjectWrapper.ObjectId >>= nIndex ) 668 { 669 SbxObject* pObj = lcl_getNativeObject( nIndex ); 670 pVar->PutObject( pObj ); 671 } 672 else 673 pVar->PutEmpty(); 674 break; 675 } 676 else 677 { 678 SbiInstance* pInst = GetSbData()->pInst; 679 if( pInst && pInst->IsCompatibility() ) 680 { 681 oleautomation::Date aDate; 682 if( aValue >>= aDate ) 683 { 684 pVar->PutDate( aDate.Value ); 685 break; 686 } 687 else 688 { 689 oleautomation::Decimal aDecimal; 690 if( aValue >>= aDecimal ) 691 { 692 pVar->PutDecimal( aDecimal ); 693 break; 694 } 695 else 696 { 697 oleautomation::Currency aCurrency; 698 if( aValue >>= aCurrency ) 699 { 700 pVar->PutCurrency( aCurrency.Value ); 701 break; 702 } 703 } 704 } 705 } 706 } 707 } 708 // instantiate a SbUnoObject 709 SbUnoObject* pSbUnoObject = new SbUnoObject( OUString(), aValue ); 710 //If this is called externally e.g. from the scripting 711 //framework then there is no 'active' runtime the default property will not be set up 712 //only a vba object will have XDefaultProp set anyway so... this 713 //test seems a bit of overkill 714 //if ( SbiRuntime::isVBAEnabled() ) 715 { 716 OUString sDfltPropName; 717 718 if ( SbUnoObject::getDefaultPropName( pSbUnoObject, sDfltPropName ) ) 719 { 720 pSbUnoObject->SetDfltProperty( sDfltPropName ); 721 } 722 } 723 SbxObjectRef xWrapper = static_cast<SbxObject*>(pSbUnoObject); 724 725 // If the object is invalid deliver null 726 if( !pSbUnoObject->getUnoAny().hasValue() ) 727 { 728 pVar->PutObject( nullptr ); 729 } 730 else 731 { 732 pVar->PutObject( xWrapper.get() ); 733 } 734 } 735 break; 736 737 738 case TypeClass_ENUM: 739 { 740 sal_Int32 nEnum = 0; 741 enum2int( nEnum, aValue ); 742 pVar->PutLong( nEnum ); 743 } 744 break; 745 746 case TypeClass_SEQUENCE: 747 { 748 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType ); 749 Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray(); 750 sal_Int32 i, nLen = xIdlArray->getLen( aValue ); 751 752 typelib_TypeDescription * pTD = nullptr; 753 aType.getDescription( &pTD ); 754 OSL_ASSERT( pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE ); 755 Type aElementType( reinterpret_cast<typelib_IndirectTypeDescription *>(pTD)->pType ); 756 ::typelib_typedescription_release( pTD ); 757 758 // build an Array in Basic 759 SbxDimArrayRef xArray; 760 SbxDataType eSbxElementType = unoToSbxType( aElementType.getTypeClass() ); 761 xArray = new SbxDimArray( eSbxElementType ); 762 if( nLen > 0 ) 763 { 764 xArray->unoAddDim32( 0, nLen - 1 ); 765 766 // register the elements as variables 767 for( i = 0 ; i < nLen ; i++ ) 768 { 769 // convert elements 770 Any aElementAny = xIdlArray->get( aValue, static_cast<sal_uInt32>(i) ); 771 auto xVar = tools::make_ref<SbxVariable>( eSbxElementType ); 772 unoToSbxValue( xVar.get(), aElementAny ); 773 774 // put into the Array 775 xArray->Put32( xVar.get(), &i ); 776 } 777 } 778 else 779 { 780 xArray->unoAddDim( 0, -1 ); 781 } 782 783 // return the Array 784 SbxFlagBits nFlags = pVar->GetFlags(); 785 pVar->ResetFlag( SbxFlagBits::Fixed ); 786 pVar->PutObject( xArray.get() ); 787 pVar->SetFlags( nFlags ); 788 789 } 790 break; 791 792 793 case TypeClass_BOOLEAN: pVar->PutBool( *o3tl::forceAccess<bool>(aValue) ); break; 794 case TypeClass_CHAR: 795 { 796 pVar->PutChar( *o3tl::forceAccess<sal_Unicode>(aValue) ); 797 break; 798 } 799 case TypeClass_STRING: { OUString val; aValue >>= val; pVar->PutString( val ); } break; 800 case TypeClass_FLOAT: { float val = 0; aValue >>= val; pVar->PutSingle( val ); } break; 801 case TypeClass_DOUBLE: { double val = 0; aValue >>= val; pVar->PutDouble( val ); } break; 802 case TypeClass_BYTE: { sal_Int8 val = 0; aValue >>= val; pVar->PutInteger( val ); } break; 803 case TypeClass_SHORT: { sal_Int16 val = 0; aValue >>= val; pVar->PutInteger( val ); } break; 804 case TypeClass_LONG: { sal_Int32 val = 0; aValue >>= val; pVar->PutLong( val ); } break; 805 case TypeClass_HYPER: { sal_Int64 val = 0; aValue >>= val; pVar->PutInt64( val ); } break; 806 case TypeClass_UNSIGNED_SHORT: { sal_uInt16 val = 0; aValue >>= val; pVar->PutUShort( val ); } break; 807 case TypeClass_UNSIGNED_LONG: { sal_uInt32 val = 0; aValue >>= val; pVar->PutULong( val ); } break; 808 case TypeClass_UNSIGNED_HYPER: { sal_uInt64 val = 0; aValue >>= val; pVar->PutUInt64( val ); } break; 809 default: pVar->PutEmpty(); break; 810 } 811 } 812 813 // Deliver the reflection for Sbx types 814 static Type getUnoTypeForSbxBaseType( SbxDataType eType ) 815 { 816 Type aRetType = cppu::UnoType<void>::get(); 817 switch( eType ) 818 { 819 case SbxNULL: aRetType = cppu::UnoType<XInterface>::get(); break; 820 case SbxINTEGER: aRetType = cppu::UnoType<sal_Int16>::get(); break; 821 case SbxLONG: aRetType = cppu::UnoType<sal_Int32>::get(); break; 822 case SbxSINGLE: aRetType = cppu::UnoType<float>::get(); break; 823 case SbxDOUBLE: aRetType = cppu::UnoType<double>::get(); break; 824 case SbxCURRENCY: aRetType = cppu::UnoType<oleautomation::Currency>::get(); break; 825 case SbxDECIMAL: aRetType = cppu::UnoType<oleautomation::Decimal>::get(); break; 826 case SbxDATE: { 827 SbiInstance* pInst = GetSbData()->pInst; 828 if( pInst && pInst->IsCompatibility() ) 829 aRetType = cppu::UnoType<double>::get(); 830 else 831 aRetType = cppu::UnoType<oleautomation::Date>::get(); 832 } 833 break; 834 case SbxSTRING: aRetType = cppu::UnoType<OUString>::get(); break; 835 case SbxBOOL: aRetType = cppu::UnoType<sal_Bool>::get(); break; 836 case SbxVARIANT: aRetType = cppu::UnoType<Any>::get(); break; 837 case SbxCHAR: aRetType = cppu::UnoType<cppu::UnoCharType>::get(); break; 838 case SbxBYTE: aRetType = cppu::UnoType<sal_Int8>::get(); break; 839 case SbxUSHORT: aRetType = cppu::UnoType<cppu::UnoUnsignedShortType>::get(); break; 840 case SbxULONG: aRetType = ::cppu::UnoType<sal_uInt32>::get(); break; 841 // map machine-dependent ones to long for consistency 842 case SbxINT: aRetType = ::cppu::UnoType<sal_Int32>::get(); break; 843 case SbxUINT: aRetType = ::cppu::UnoType<sal_uInt32>::get(); break; 844 default: break; 845 } 846 return aRetType; 847 } 848 849 // Converting of Sbx to Uno without a know target class for TypeClass_ANY 850 static Type getUnoTypeForSbxValue( const SbxValue* pVal ) 851 { 852 Type aRetType = cppu::UnoType<void>::get(); 853 if( !pVal ) 854 return aRetType; 855 856 // convert SbxType to Uno 857 SbxDataType eBaseType = pVal->SbxValue::GetType(); 858 if( eBaseType == SbxOBJECT ) 859 { 860 SbxBaseRef xObj = pVal->GetObject(); 861 if( !xObj.is() ) 862 { 863 aRetType = cppu::UnoType<XInterface>::get(); 864 return aRetType; 865 } 866 867 if( auto pArray = dynamic_cast<SbxDimArray*>( xObj.get() ) ) 868 { 869 short nDims = pArray->GetDims(); 870 Type aElementType = getUnoTypeForSbxBaseType( static_cast<SbxDataType>(pArray->GetType() & 0xfff) ); 871 TypeClass eElementTypeClass = aElementType.getTypeClass(); 872 873 // Normal case: One dimensional array 874 sal_Int32 nLower, nUpper; 875 if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) ) 876 { 877 if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY ) 878 { 879 // If all elements of the arrays are from the same type, take 880 // this one - otherwise the whole will be considered as Any-Sequence 881 bool bNeedsInit = true; 882 883 for (sal_Int32 aIdx[1] = { nLower }; aIdx[0] <= nUpper; ++aIdx[0]) 884 { 885 SbxVariableRef xVar = pArray->Get32(aIdx); 886 Type aType = getUnoTypeForSbxValue( xVar.get() ); 887 if( bNeedsInit ) 888 { 889 if( aType.getTypeClass() == TypeClass_VOID ) 890 { 891 // if only first element is void: different types -> []any 892 // if all elements are void: []void is not allowed -> []any 893 aElementType = cppu::UnoType<Any>::get(); 894 break; 895 } 896 aElementType = aType; 897 bNeedsInit = false; 898 } 899 else if( aElementType != aType ) 900 { 901 // different types -> AnySequence 902 aElementType = cppu::UnoType<Any>::get(); 903 break; 904 } 905 } 906 } 907 908 OUString aSeqTypeName = aSeqLevelStr + aElementType.getTypeName(); 909 aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName ); 910 } 911 // #i33795 Map also multi dimensional arrays to corresponding sequences 912 else if( nDims > 1 ) 913 { 914 if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY ) 915 { 916 // For this check the array's dim structure does not matter 917 sal_uInt32 nFlatArraySize = pArray->Count32(); 918 919 bool bNeedsInit = true; 920 for( sal_uInt32 i = 0 ; i < nFlatArraySize ; i++ ) 921 { 922 SbxVariableRef xVar = pArray->SbxArray::Get32( i ); 923 Type aType = getUnoTypeForSbxValue( xVar.get() ); 924 if( bNeedsInit ) 925 { 926 if( aType.getTypeClass() == TypeClass_VOID ) 927 { 928 // if only first element is void: different types -> []any 929 // if all elements are void: []void is not allowed -> []any 930 aElementType = cppu::UnoType<Any>::get(); 931 break; 932 } 933 aElementType = aType; 934 bNeedsInit = false; 935 } 936 else if( aElementType != aType ) 937 { 938 // different types -> AnySequence 939 aElementType = cppu::UnoType<Any>::get(); 940 break; 941 } 942 } 943 } 944 945 OUStringBuffer aSeqTypeName; 946 for( short iDim = 0 ; iDim < nDims ; iDim++ ) 947 { 948 aSeqTypeName.append(aSeqLevelStr); 949 } 950 aSeqTypeName.append(aElementType.getTypeName()); 951 aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() ); 952 } 953 } 954 // No array, but ... 955 else if( auto obj = dynamic_cast<SbUnoObject*>( xObj.get() ) ) 956 { 957 aRetType = obj->getUnoAny().getValueType(); 958 } 959 // SbUnoAnyObject? 960 else if( auto any = dynamic_cast<SbUnoAnyObject*>( xObj.get() ) ) 961 { 962 aRetType = any->getValue().getValueType(); 963 } 964 // Otherwise it is a No-Uno-Basic-Object -> default==deliver void 965 } 966 // No object, convert basic type 967 else 968 { 969 aRetType = getUnoTypeForSbxBaseType( eBaseType ); 970 } 971 return aRetType; 972 } 973 974 // converting of Sbx to Uno without known target class for TypeClass_ANY 975 static Any sbxToUnoValueImpl( const SbxValue* pVar, bool bBlockConversionToSmallestType = false ) 976 { 977 SbxDataType eBaseType = pVar->SbxValue::GetType(); 978 if( eBaseType == SbxOBJECT ) 979 { 980 SbxBaseRef xObj = pVar->GetObject(); 981 if( xObj.is() ) 982 { 983 if( auto obj = dynamic_cast<SbUnoAnyObject*>( xObj.get() ) ) 984 return obj->getValue(); 985 if( auto pClassModuleObj = dynamic_cast<SbClassModuleObject*>( xObj.get() ) ) 986 { 987 Any aRetAny; 988 SbModule* pClassModule = pClassModuleObj->getClassModule(); 989 if( pClassModule->createCOMWrapperForIface( aRetAny, pClassModuleObj ) ) 990 return aRetAny; 991 } 992 if( dynamic_cast<const SbUnoObject*>( xObj.get() ) == nullptr ) 993 { 994 // Create NativeObjectWrapper to identify object in case of callbacks 995 SbxObject* pObj = dynamic_cast<SbxObject*>( pVar->GetObject() ); 996 if( pObj != nullptr ) 997 { 998 NativeObjectWrapper aNativeObjectWrapper; 999 sal_uInt32 nIndex = lcl_registerNativeObjectWrapper( pObj ); 1000 aNativeObjectWrapper.ObjectId <<= nIndex; 1001 Any aRetAny; 1002 aRetAny <<= aNativeObjectWrapper; 1003 return aRetAny; 1004 } 1005 } 1006 } 1007 } 1008 1009 Type aType = getUnoTypeForSbxValue( pVar ); 1010 TypeClass eType = aType.getTypeClass(); 1011 1012 if( !bBlockConversionToSmallestType ) 1013 { 1014 // #79615 Choose "smallest" represention for int values 1015 // because up cast is allowed, downcast not 1016 switch( eType ) 1017 { 1018 case TypeClass_FLOAT: 1019 case TypeClass_DOUBLE: 1020 { 1021 double d = pVar->GetDouble(); 1022 if( rtl::math::approxEqual(d, floor( d )) ) 1023 { 1024 if( d >= -128 && d <= 127 ) 1025 aType = ::cppu::UnoType<sal_Int8>::get(); 1026 else if( d >= SbxMININT && d <= SbxMAXINT ) 1027 aType = ::cppu::UnoType<sal_Int16>::get(); 1028 else if( d >= -SbxMAXLNG && d <= SbxMAXLNG ) 1029 aType = ::cppu::UnoType<sal_Int32>::get(); 1030 } 1031 break; 1032 } 1033 case TypeClass_SHORT: 1034 { 1035 sal_Int16 n = pVar->GetInteger(); 1036 if( n >= -128 && n <= 127 ) 1037 aType = ::cppu::UnoType<sal_Int8>::get(); 1038 break; 1039 } 1040 case TypeClass_LONG: 1041 { 1042 sal_Int32 n = pVar->GetLong(); 1043 if( n >= -128 && n <= 127 ) 1044 aType = ::cppu::UnoType<sal_Int8>::get(); 1045 else if( n >= SbxMININT && n <= SbxMAXINT ) 1046 aType = ::cppu::UnoType<sal_Int16>::get(); 1047 break; 1048 } 1049 case TypeClass_UNSIGNED_SHORT: 1050 { 1051 sal_uInt16 n = pVar->GetUShort(); 1052 if( n <= 255 ) 1053 aType = cppu::UnoType<sal_uInt8>::get(); 1054 break; 1055 } 1056 case TypeClass_UNSIGNED_LONG: 1057 { 1058 sal_uInt32 n = pVar->GetLong(); 1059 if( n <= 255 ) 1060 aType = cppu::UnoType<sal_uInt8>::get(); 1061 else if( n <= SbxMAXUINT ) 1062 aType = cppu::UnoType<cppu::UnoUnsignedShortType>::get(); 1063 break; 1064 } 1065 // TODO: need to add hyper types ? 1066 default: break; 1067 } 1068 } 1069 1070 return sbxToUnoValue( pVar, aType ); 1071 } 1072 1073 1074 // Helper function for StepREDIMP 1075 static Any implRekMultiDimArrayToSequence( SbxDimArray* pArray, 1076 const Type& aElemType, short nMaxDimIndex, short nActualDim, 1077 sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds ) 1078 { 1079 sal_Int32 nSeqLevel = nMaxDimIndex - nActualDim + 1; 1080 OUStringBuffer aSeqTypeName; 1081 sal_Int32 i; 1082 for( i = 0 ; i < nSeqLevel ; i++ ) 1083 { 1084 aSeqTypeName.append(aSeqLevelStr); 1085 } 1086 aSeqTypeName.append(aElemType.getTypeName()); 1087 Type aSeqType( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() ); 1088 1089 // Create Sequence instance 1090 Any aRetVal; 1091 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aSeqType ); 1092 xIdlTargetClass->createObject( aRetVal ); 1093 1094 // Alloc sequence according to array bounds 1095 sal_Int32 nUpper = pUpperBounds[nActualDim]; 1096 sal_Int32 nLower = pLowerBounds[nActualDim]; 1097 sal_Int32 nSeqSize = nUpper - nLower + 1; 1098 Reference< XIdlArray > xArray = xIdlTargetClass->getArray(); 1099 xArray->realloc( aRetVal, nSeqSize ); 1100 1101 sal_Int32& ri = pActualIndices[nActualDim]; 1102 1103 for( ri = nLower,i = 0 ; ri <= nUpper ; ri++,i++ ) 1104 { 1105 Any aElementVal; 1106 1107 if( nActualDim < nMaxDimIndex ) 1108 { 1109 aElementVal = implRekMultiDimArrayToSequence( pArray, aElemType, 1110 nMaxDimIndex, nActualDim + 1, pActualIndices, pLowerBounds, pUpperBounds ); 1111 } 1112 else 1113 { 1114 SbxVariable* pSource = pArray->Get32( pActualIndices ); 1115 aElementVal = sbxToUnoValue( pSource, aElemType ); 1116 } 1117 1118 try 1119 { 1120 // transfer to the sequence 1121 xArray->set( aRetVal, i, aElementVal ); 1122 } 1123 catch( const IllegalArgumentException& ) 1124 { 1125 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, 1126 implGetExceptionMsg( ::cppu::getCaughtException() ) ); 1127 } 1128 catch (const IndexOutOfBoundsException&) 1129 { 1130 StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE ); 1131 } 1132 } 1133 return aRetVal; 1134 } 1135 1136 // Map old interface 1137 Any sbxToUnoValue( const SbxValue* pVar ) 1138 { 1139 return sbxToUnoValueImpl( pVar ); 1140 } 1141 1142 // function to find a global identifier in 1143 // the UnoScope and to wrap it for Sbx 1144 static bool implGetTypeByName( const OUString& rName, Type& rRetType ) 1145 { 1146 bool bSuccess = false; 1147 1148 const Reference< XHierarchicalNameAccess >& xTypeAccess = getTypeProvider_Impl(); 1149 if( xTypeAccess->hasByHierarchicalName( rName ) ) 1150 { 1151 Any aRet = xTypeAccess->getByHierarchicalName( rName ); 1152 Reference< XTypeDescription > xTypeDesc; 1153 aRet >>= xTypeDesc; 1154 1155 if( xTypeDesc.is() ) 1156 { 1157 rRetType = Type( xTypeDesc->getTypeClass(), xTypeDesc->getName() ); 1158 bSuccess = true; 1159 } 1160 } 1161 return bSuccess; 1162 } 1163 1164 1165 // converting of Sbx to Uno with known target class 1166 Any sbxToUnoValue( const SbxValue* pVar, const Type& rType, Property const * pUnoProperty ) 1167 { 1168 Any aRetVal; 1169 1170 // #94560 No conversion of empty/void for MAYBE_VOID properties 1171 if( pUnoProperty && pUnoProperty->Attributes & PropertyAttribute::MAYBEVOID ) 1172 { 1173 if( pVar->IsEmpty() ) 1174 return aRetVal; 1175 } 1176 1177 SbxDataType eBaseType = pVar->SbxValue::GetType(); 1178 if( eBaseType == SbxOBJECT ) 1179 { 1180 SbxBaseRef xObj = pVar->GetObject(); 1181 if ( auto obj = dynamic_cast<SbUnoAnyObject*>( xObj.get() ) ) 1182 { 1183 return obj->getValue(); 1184 } 1185 } 1186 1187 TypeClass eType = rType.getTypeClass(); 1188 switch( eType ) 1189 { 1190 case TypeClass_INTERFACE: 1191 case TypeClass_STRUCT: 1192 case TypeClass_EXCEPTION: 1193 { 1194 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType ); 1195 1196 // null reference? 1197 if( pVar->IsNull() && eType == TypeClass_INTERFACE ) 1198 { 1199 Reference< XInterface > xRef; 1200 OUString aClassName = xIdlTargetClass->getName(); 1201 Type aClassType( xIdlTargetClass->getTypeClass(), aClassName ); 1202 aRetVal.setValue( &xRef, aClassType ); 1203 } 1204 else 1205 { 1206 // #112368 Special conversion for Decimal, Currency and Date 1207 if( eType == TypeClass_STRUCT ) 1208 { 1209 SbiInstance* pInst = GetSbData()->pInst; 1210 if( pInst && pInst->IsCompatibility() ) 1211 { 1212 if( rType == cppu::UnoType<oleautomation::Decimal>::get()) 1213 { 1214 oleautomation::Decimal aDecimal; 1215 pVar->fillAutomationDecimal( aDecimal ); 1216 aRetVal <<= aDecimal; 1217 break; 1218 } 1219 else if( rType == cppu::UnoType<oleautomation::Currency>::get()) 1220 { 1221 // assumes per previous code that ole Currency is Int64 1222 aRetVal <<= pVar->GetInt64(); 1223 break; 1224 } 1225 else if( rType == cppu::UnoType<oleautomation::Date>::get()) 1226 { 1227 oleautomation::Date aDate; 1228 aDate.Value = pVar->GetDate(); 1229 aRetVal <<= aDate; 1230 break; 1231 } 1232 } 1233 } 1234 1235 SbxBaseRef pObj = pVar->GetObject(); 1236 if( auto obj = dynamic_cast<SbUnoObject*>( pObj.get() ) ) 1237 { 1238 aRetVal = obj->getUnoAny(); 1239 } 1240 else if( auto structRef = dynamic_cast<SbUnoStructRefObject*>( pObj.get() ) ) 1241 { 1242 aRetVal = structRef->getUnoAny(); 1243 } 1244 else 1245 { 1246 // null object -> null XInterface 1247 Reference<XInterface> xInt; 1248 aRetVal <<= xInt; 1249 } 1250 } 1251 } 1252 break; 1253 1254 case TypeClass_TYPE: 1255 { 1256 if( eBaseType == SbxOBJECT ) 1257 { 1258 // XIdlClass? 1259 Reference< XIdlClass > xIdlClass; 1260 1261 SbxBaseRef pObj = pVar->GetObject(); 1262 if( auto obj = dynamic_cast<SbUnoObject*>( pObj.get() ) ) 1263 { 1264 Any aUnoAny = obj->getUnoAny(); 1265 aUnoAny >>= xIdlClass; 1266 } 1267 1268 if( xIdlClass.is() ) 1269 { 1270 OUString aClassName = xIdlClass->getName(); 1271 Type aType( xIdlClass->getTypeClass(), aClassName ); 1272 aRetVal <<= aType; 1273 } 1274 } 1275 else if( eBaseType == SbxSTRING ) 1276 { 1277 OUString aTypeName = pVar->GetOUString(); 1278 Type aType; 1279 bool bSuccess = implGetTypeByName( aTypeName, aType ); 1280 if( bSuccess ) 1281 { 1282 aRetVal <<= aType; 1283 } 1284 } 1285 } 1286 break; 1287 1288 1289 case TypeClass_ENUM: 1290 { 1291 aRetVal = int2enum( pVar->GetLong(), rType ); 1292 } 1293 break; 1294 1295 case TypeClass_SEQUENCE: 1296 { 1297 SbxBaseRef xObj = pVar->GetObject(); 1298 if( auto pArray = dynamic_cast<SbxDimArray*>( xObj.get() ) ) 1299 { 1300 short nDims = pArray->GetDims(); 1301 1302 // Normal case: One dimensional array 1303 sal_Int32 nLower, nUpper; 1304 if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) ) 1305 { 1306 sal_Int32 nSeqSize = nUpper - nLower + 1; 1307 1308 // create the instance of the required sequence 1309 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType ); 1310 xIdlTargetClass->createObject( aRetVal ); 1311 Reference< XIdlArray > xArray = xIdlTargetClass->getArray(); 1312 xArray->realloc( aRetVal, nSeqSize ); 1313 1314 // Element-Type 1315 OUString aClassName = xIdlTargetClass->getName(); 1316 typelib_TypeDescription * pSeqTD = nullptr; 1317 typelib_typedescription_getByName( &pSeqTD, aClassName.pData ); 1318 OSL_ASSERT( pSeqTD ); 1319 Type aElemType( reinterpret_cast<typelib_IndirectTypeDescription *>(pSeqTD)->pType ); 1320 1321 // convert all array member and register them 1322 sal_Int32 aIdx[1]; 1323 aIdx[0] = nLower; 1324 for (sal_Int32 i = 0 ; i < nSeqSize; ++i, ++aIdx[0]) 1325 { 1326 SbxVariableRef xVar = pArray->Get32(aIdx); 1327 1328 // Convert the value of Sbx to Uno 1329 Any aAnyValue = sbxToUnoValue( xVar.get(), aElemType ); 1330 1331 try 1332 { 1333 // insert in the sequence 1334 xArray->set( aRetVal, i, aAnyValue ); 1335 } 1336 catch( const IllegalArgumentException& ) 1337 { 1338 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, 1339 implGetExceptionMsg( ::cppu::getCaughtException() ) ); 1340 } 1341 catch (const IndexOutOfBoundsException&) 1342 { 1343 StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE ); 1344 } 1345 } 1346 } 1347 // #i33795 Map also multi dimensional arrays to corresponding sequences 1348 else if( nDims > 1 ) 1349 { 1350 // Element-Type 1351 typelib_TypeDescription * pSeqTD = nullptr; 1352 Type aCurType( rType ); 1353 sal_Int32 nSeqLevel = 0; 1354 Type aElemType; 1355 do 1356 { 1357 OUString aTypeName = aCurType.getTypeName(); 1358 typelib_typedescription_getByName( &pSeqTD, aTypeName.pData ); 1359 OSL_ASSERT( pSeqTD ); 1360 if( pSeqTD->eTypeClass == typelib_TypeClass_SEQUENCE ) 1361 { 1362 aCurType = Type( reinterpret_cast<typelib_IndirectTypeDescription *>(pSeqTD)->pType ); 1363 nSeqLevel++; 1364 } 1365 else 1366 { 1367 aElemType = aCurType; 1368 break; 1369 } 1370 } 1371 while( true ); 1372 1373 if( nSeqLevel == nDims ) 1374 { 1375 std::unique_ptr<sal_Int32[]> pLowerBounds(new sal_Int32[nDims]); 1376 std::unique_ptr<sal_Int32[]> pUpperBounds(new sal_Int32[nDims]); 1377 std::unique_ptr<sal_Int32[]> pActualIndices(new sal_Int32[nDims]); 1378 for( short i = 1 ; i <= nDims ; i++ ) 1379 { 1380 sal_Int32 lBound, uBound; 1381 pArray->GetDim32( i, lBound, uBound ); 1382 1383 short j = i - 1; 1384 pActualIndices[j] = pLowerBounds[j] = lBound; 1385 pUpperBounds[j] = uBound; 1386 } 1387 1388 aRetVal = implRekMultiDimArrayToSequence( pArray, aElemType, 1389 nDims - 1, 0, pActualIndices.get(), pLowerBounds.get(), pUpperBounds.get() ); 1390 } 1391 } 1392 } 1393 } 1394 break; 1395 1396 1397 // for Any use the class independent converting routine 1398 case TypeClass_ANY: 1399 { 1400 aRetVal = sbxToUnoValueImpl( pVar ); 1401 } 1402 break; 1403 1404 case TypeClass_BOOLEAN: 1405 { 1406 aRetVal <<= pVar->GetBool(); 1407 break; 1408 } 1409 case TypeClass_CHAR: 1410 { 1411 aRetVal <<= pVar->GetChar(); 1412 break; 1413 } 1414 case TypeClass_STRING: aRetVal <<= pVar->GetOUString(); break; 1415 case TypeClass_FLOAT: aRetVal <<= pVar->GetSingle(); break; 1416 case TypeClass_DOUBLE: aRetVal <<= pVar->GetDouble(); break; 1417 1418 case TypeClass_BYTE: 1419 { 1420 sal_Int16 nVal = pVar->GetInteger(); 1421 bool bOverflow = false; 1422 if( nVal < -128 ) 1423 { 1424 bOverflow = true; 1425 nVal = -128; 1426 } 1427 else if( nVal > 255 ) // 128..255 map to -128..-1 1428 { 1429 bOverflow = true; 1430 nVal = 127; 1431 } 1432 if( bOverflow ) 1433 StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW ); 1434 1435 sal_Int8 nByteVal = static_cast<sal_Int8>(nVal); 1436 aRetVal <<= nByteVal; 1437 break; 1438 } 1439 case TypeClass_SHORT: aRetVal <<= pVar->GetInteger(); break; 1440 case TypeClass_LONG: aRetVal <<= pVar->GetLong(); break; 1441 case TypeClass_HYPER: aRetVal <<= pVar->GetInt64(); break; 1442 case TypeClass_UNSIGNED_SHORT: aRetVal <<= pVar->GetUShort(); break; 1443 case TypeClass_UNSIGNED_LONG: aRetVal <<= pVar->GetULong(); break; 1444 case TypeClass_UNSIGNED_HYPER: aRetVal <<= pVar->GetUInt64(); break; 1445 default: break; 1446 } 1447 1448 return aRetVal; 1449 } 1450 1451 static void processAutomationParams( SbxArray* pParams, Sequence< Any >& args, sal_uInt32 nParamCount ) 1452 { 1453 AutomationNamedArgsSbxArray* pArgNamesArray = dynamic_cast<AutomationNamedArgsSbxArray*>( pParams ); 1454 1455 args.realloc( nParamCount ); 1456 Any* pAnyArgs = args.getArray(); 1457 bool bBlockConversionToSmallestType = GetSbData()->pInst->IsCompatibility(); 1458 sal_uInt32 i = 0; 1459 if( pArgNamesArray ) 1460 { 1461 Sequence< OUString >& rNameSeq = pArgNamesArray->getNames(); 1462 OUString* pNames = rNameSeq.getArray(); 1463 Any aValAny; 1464 for( i = 0 ; i < nParamCount ; i++ ) 1465 { 1466 sal_uInt16 iSbx = static_cast<sal_uInt16>(i+1); 1467 1468 aValAny = sbxToUnoValueImpl( pParams->Get( iSbx ), 1469 bBlockConversionToSmallestType ); 1470 1471 OUString aParamName = pNames[iSbx]; 1472 if( !aParamName.isEmpty() ) 1473 { 1474 oleautomation::NamedArgument aNamedArgument; 1475 aNamedArgument.Name = aParamName; 1476 aNamedArgument.Value = aValAny; 1477 pAnyArgs[i] <<= aNamedArgument; 1478 } 1479 else 1480 { 1481 pAnyArgs[i] = aValAny; 1482 } 1483 } 1484 } 1485 else 1486 { 1487 for( i = 0 ; i < nParamCount ; i++ ) 1488 { 1489 pAnyArgs[i] = sbxToUnoValueImpl( pParams->Get( static_cast<sal_uInt16>(i+1) ), 1490 bBlockConversionToSmallestType ); 1491 } 1492 } 1493 1494 } 1495 enum class INVOKETYPE 1496 { 1497 GetProp = 0, 1498 Func 1499 }; 1500 static Any invokeAutomationMethod( const OUString& Name, Sequence< Any > const & args, SbxArray* pParams, sal_uInt32 nParamCount, Reference< XInvocation > const & rxInvocation, INVOKETYPE invokeType ) 1501 { 1502 Sequence< sal_Int16 > OutParamIndex; 1503 Sequence< Any > OutParam; 1504 1505 Any aRetAny; 1506 switch( invokeType ) 1507 { 1508 case INVOKETYPE::Func: 1509 aRetAny = rxInvocation->invoke( Name, args, OutParamIndex, OutParam ); 1510 break; 1511 case INVOKETYPE::GetProp: 1512 { 1513 Reference< XAutomationInvocation > xAutoInv( rxInvocation, UNO_QUERY ); 1514 aRetAny = xAutoInv->invokeGetProperty( Name, args, OutParamIndex, OutParam ); 1515 break; 1516 } 1517 default: 1518 assert(false); break; 1519 1520 } 1521 const sal_Int16* pIndices = OutParamIndex.getConstArray(); 1522 sal_uInt32 nLen = OutParamIndex.getLength(); 1523 if( nLen ) 1524 { 1525 const Any* pNewValues = OutParam.getConstArray(); 1526 for( sal_uInt32 j = 0 ; j < nLen ; j++ ) 1527 { 1528 sal_Int16 iTarget = pIndices[ j ]; 1529 if( iTarget >= static_cast<sal_Int16>(nParamCount) ) 1530 break; 1531 unoToSbxValue( pParams->Get( static_cast<sal_uInt16>(j+1) ), pNewValues[ j ] ); 1532 } 1533 } 1534 return aRetAny; 1535 } 1536 1537 // Debugging help method to readout the imlemented interfaces of an object 1538 static OUString Impl_GetInterfaceInfo( const Reference< XInterface >& x, const Reference< XIdlClass >& xClass, sal_uInt16 nRekLevel ) 1539 { 1540 Type aIfaceType = cppu::UnoType<XInterface>::get(); 1541 static Reference< XIdlClass > xIfaceClass = TypeToIdlClass( aIfaceType ); 1542 1543 OUStringBuffer aRetStr; 1544 for( sal_uInt16 i = 0 ; i < nRekLevel ; i++ ) 1545 aRetStr.append( " " ); 1546 aRetStr.append( xClass->getName() ); 1547 OUString aClassName = xClass->getName(); 1548 Type aClassType( xClass->getTypeClass(), aClassName ); 1549 1550 // checking if the interface is really supported 1551 if( !x->queryInterface( aClassType ).hasValue() ) 1552 { 1553 aRetStr.append( " (ERROR: Not really supported!)\n" ); 1554 } 1555 // Are there super interfaces? 1556 else 1557 { 1558 aRetStr.append( "\n" ); 1559 1560 // get the super interfaces 1561 Sequence< Reference< XIdlClass > > aSuperClassSeq = xClass->getSuperclasses(); 1562 const Reference< XIdlClass >* pClasses = aSuperClassSeq.getConstArray(); 1563 sal_uInt32 nSuperIfaceCount = aSuperClassSeq.getLength(); 1564 for( sal_uInt32 j = 0 ; j < nSuperIfaceCount ; j++ ) 1565 { 1566 const Reference< XIdlClass >& rxIfaceClass = pClasses[j]; 1567 if( !rxIfaceClass->equals( xIfaceClass ) ) 1568 aRetStr.append( Impl_GetInterfaceInfo( x, rxIfaceClass, nRekLevel + 1 ) ); 1569 } 1570 } 1571 return aRetStr.makeStringAndClear(); 1572 } 1573 1574 static OUString getDbgObjectNameImpl(SbUnoObject& rUnoObj) 1575 { 1576 OUString aName = rUnoObj.GetClassName(); 1577 if( aName.isEmpty() ) 1578 { 1579 Any aToInspectObj = rUnoObj.getUnoAny(); 1580 Reference< XInterface > xObj(aToInspectObj, css::uno::UNO_QUERY); 1581 if( xObj.is() ) 1582 { 1583 Reference< XServiceInfo > xServiceInfo( xObj, UNO_QUERY ); 1584 if( xServiceInfo.is() ) 1585 aName = xServiceInfo->getImplementationName(); 1586 } 1587 } 1588 return aName; 1589 } 1590 1591 static OUString getDbgObjectName(SbUnoObject& rUnoObj) 1592 { 1593 OUString aName = getDbgObjectNameImpl(rUnoObj); 1594 if( aName.isEmpty() ) 1595 aName += "Unknown"; 1596 1597 OUStringBuffer aRet; 1598 if( aName.getLength() > 20 ) 1599 { 1600 aRet.append( "\n" ); 1601 } 1602 aRet.append( "\"" ); 1603 aRet.append( aName ); 1604 aRet.append( "\":" ); 1605 return aRet.makeStringAndClear(); 1606 } 1607 1608 OUString getBasicObjectTypeName( SbxObject* pObj ) 1609 { 1610 if (pObj) 1611 { 1612 if (SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>(pObj)) 1613 { 1614 return getDbgObjectNameImpl(*pUnoObj); 1615 } 1616 else if (SbUnoStructRefObject* pUnoStructObj = dynamic_cast<SbUnoStructRefObject*>(pObj)) 1617 { 1618 return pUnoStructObj->GetClassName(); 1619 } 1620 } 1621 return OUString(); 1622 } 1623 1624 bool checkUnoObjectType(SbUnoObject& rUnoObj, const OUString& rClass) 1625 { 1626 Any aToInspectObj = rUnoObj.getUnoAny(); 1627 1628 // Return true for XInvocation based objects as interface type names don't count then 1629 Reference< XInvocation > xInvocation( aToInspectObj, UNO_QUERY ); 1630 if( xInvocation.is() ) 1631 { 1632 return true; 1633 } 1634 bool bResult = false; 1635 Reference< XTypeProvider > xTypeProvider( aToInspectObj, UNO_QUERY ); 1636 if( xTypeProvider.is() ) 1637 { 1638 /* Although interfaces in the ooo.vba namespace obey the IDL rules and 1639 have a leading 'X', in Basic we want to be able to do something 1640 like 'Dim wb As Workbooks' or 'Dim lb As MSForms.Label'. Here we 1641 add a leading 'X' to the class name and a leading dot to the entire 1642 type name. This results e.g. in '.XWorkbooks' or '.MSForms.XLabel' 1643 which matches the interface names 'ooo.vba.excel.XWorkbooks' or 1644 'ooo.vba.msforms.XLabel'. 1645 */ 1646 OUString aClassName; 1647 if ( SbiRuntime::isVBAEnabled() ) 1648 { 1649 aClassName = "."; 1650 sal_Int32 nClassNameDot = rClass.lastIndexOf( '.' ); 1651 if( nClassNameDot >= 0 ) 1652 { 1653 aClassName += rClass.copy( 0, nClassNameDot + 1 ) + "X" + rClass.copy( nClassNameDot + 1 ); 1654 } 1655 else 1656 { 1657 aClassName += "X" + rClass; 1658 } 1659 } 1660 else // assume extended type declaration support for basic ( can't get here 1661 // otherwise. 1662 aClassName = rClass; 1663 1664 Sequence< Type > aTypeSeq = xTypeProvider->getTypes(); 1665 const Type* pTypeArray = aTypeSeq.getConstArray(); 1666 sal_uInt32 nIfaceCount = aTypeSeq.getLength(); 1667 for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ ) 1668 { 1669 const Type& rType = pTypeArray[j]; 1670 1671 Reference<XIdlClass> xClass = TypeToIdlClass( rType ); 1672 if( !xClass.is() ) 1673 { 1674 OSL_FAIL("failed to get XIdlClass for type"); 1675 break; 1676 } 1677 OUString aInterfaceName = xClass->getName(); 1678 if ( aInterfaceName == "com.sun.star.bridge.oleautomation.XAutomationObject" ) 1679 { 1680 // there is a hack in the extensions/source/ole/oleobj.cxx to return the typename of the automation object, lets check if it 1681 // matches 1682 Reference< XInvocation > xInv( aToInspectObj, UNO_QUERY ); 1683 if ( xInv.is() ) 1684 { 1685 OUString sTypeName; 1686 xInv->getValue( "$GetTypeName" ) >>= sTypeName; 1687 if ( sTypeName.isEmpty() || sTypeName == "IDispatch" ) 1688 { 1689 // can't check type, leave it pass 1690 bResult = true; 1691 } 1692 else 1693 { 1694 bResult = sTypeName == rClass; 1695 } 1696 } 1697 break; // finished checking automation object 1698 } 1699 1700 // match interface name with passed class name 1701 if ( (aClassName.getLength() <= aInterfaceName.getLength()) && 1702 aInterfaceName.endsWithIgnoreAsciiCase( aClassName ) ) 1703 { 1704 bResult = true; 1705 break; 1706 } 1707 } 1708 } 1709 return bResult; 1710 } 1711 1712 // Debugging help method to readout the imlemented interfaces of an object 1713 static OUString Impl_GetSupportedInterfaces(SbUnoObject& rUnoObj) 1714 { 1715 Any aToInspectObj = rUnoObj.getUnoAny(); 1716 1717 // allow only TypeClass interface 1718 OUStringBuffer aRet; 1719 auto x = o3tl::tryAccess<Reference<XInterface>>(aToInspectObj); 1720 if( !x ) 1721 { 1722 aRet.append( ID_DBG_SUPPORTEDINTERFACES ); 1723 aRet.append( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" ); 1724 } 1725 else 1726 { 1727 Reference< XTypeProvider > xTypeProvider( *x, UNO_QUERY ); 1728 1729 aRet.append( "Supported interfaces by object " ); 1730 aRet.append(getDbgObjectName(rUnoObj)); 1731 aRet.append( "\n" ); 1732 if( xTypeProvider.is() ) 1733 { 1734 // get the interfaces of the implementation 1735 Sequence< Type > aTypeSeq = xTypeProvider->getTypes(); 1736 const Type* pTypeArray = aTypeSeq.getConstArray(); 1737 sal_uInt32 nIfaceCount = aTypeSeq.getLength(); 1738 for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ ) 1739 { 1740 const Type& rType = pTypeArray[j]; 1741 1742 Reference<XIdlClass> xClass = TypeToIdlClass( rType ); 1743 if( xClass.is() ) 1744 { 1745 aRet.append( Impl_GetInterfaceInfo( *x, xClass, 1 ) ); 1746 } 1747 else 1748 { 1749 typelib_TypeDescription * pTD = nullptr; 1750 rType.getDescription( &pTD ); 1751 1752 aRet.append( "*** ERROR: No IdlClass for type \"" ); 1753 aRet.append( pTD->pTypeName ); 1754 aRet.append( "\"\n*** Please check type library\n" ); 1755 } 1756 } 1757 } 1758 } 1759 return aRet.makeStringAndClear(); 1760 } 1761 1762 1763 // Debugging help method SbxDataType -> String 1764 static OUString Dbg_SbxDataType2String( SbxDataType eType ) 1765 { 1766 OUStringBuffer aRet; 1767 switch( +eType ) 1768 { 1769 case SbxEMPTY: aRet.append("SbxEMPTY"); break; 1770 case SbxNULL: aRet.append("SbxNULL"); break; 1771 case SbxINTEGER: aRet.append("SbxINTEGER"); break; 1772 case SbxLONG: aRet.append("SbxLONG"); break; 1773 case SbxSINGLE: aRet.append("SbxSINGLE"); break; 1774 case SbxDOUBLE: aRet.append("SbxDOUBLE"); break; 1775 case SbxCURRENCY: aRet.append("SbxCURRENCY"); break; 1776 case SbxDECIMAL: aRet.append("SbxDECIMAL"); break; 1777 case SbxDATE: aRet.append("SbxDATE"); break; 1778 case SbxSTRING: aRet.append("SbxSTRING"); break; 1779 case SbxOBJECT: aRet.append("SbxOBJECT"); break; 1780 case SbxERROR: aRet.append("SbxERROR"); break; 1781 case SbxBOOL: aRet.append("SbxBOOL"); break; 1782 case SbxVARIANT: aRet.append("SbxVARIANT"); break; 1783 case SbxDATAOBJECT: aRet.append("SbxDATAOBJECT"); break; 1784 case SbxCHAR: aRet.append("SbxCHAR"); break; 1785 case SbxBYTE: aRet.append("SbxBYTE"); break; 1786 case SbxUSHORT: aRet.append("SbxUSHORT"); break; 1787 case SbxULONG: aRet.append("SbxULONG"); break; 1788 case SbxSALINT64: aRet.append("SbxINT64"); break; 1789 case SbxSALUINT64: aRet.append("SbxUINT64"); break; 1790 case SbxINT: aRet.append("SbxINT"); break; 1791 case SbxUINT: aRet.append("SbxUINT"); break; 1792 case SbxVOID: aRet.append("SbxVOID"); break; 1793 case SbxHRESULT: aRet.append("SbxHRESULT"); break; 1794 case SbxPOINTER: aRet.append("SbxPOINTER"); break; 1795 case SbxDIMARRAY: aRet.append("SbxDIMARRAY"); break; 1796 case SbxCARRAY: aRet.append("SbxCARRAY"); break; 1797 case SbxUSERDEF: aRet.append("SbxUSERDEF"); break; 1798 case SbxLPSTR: aRet.append("SbxLPSTR"); break; 1799 case SbxLPWSTR: aRet.append("SbxLPWSTR"); break; 1800 case SbxCoreSTRING: aRet.append("SbxCoreSTRING"); break; 1801 case SbxOBJECT | SbxARRAY: aRet.append("SbxARRAY"); break; 1802 default: aRet.append("Unknown Sbx-Type!");break; 1803 } 1804 return aRet.makeStringAndClear(); 1805 } 1806 1807 // Debugging help method to display the properties of a SbUnoObjects 1808 static OUString Impl_DumpProperties(SbUnoObject& rUnoObj) 1809 { 1810 OUStringBuffer aRet; 1811 aRet.append("Properties of object "); 1812 aRet.append(getDbgObjectName(rUnoObj)); 1813 1814 // analyse the Uno-Infos to recognise the arrays 1815 Reference< XIntrospectionAccess > xAccess = rUnoObj.getIntrospectionAccess(); 1816 if( !xAccess.is() ) 1817 { 1818 Reference< XInvocation > xInvok = rUnoObj.getInvocation(); 1819 if( xInvok.is() ) 1820 xAccess = xInvok->getIntrospection(); 1821 } 1822 if( !xAccess.is() ) 1823 { 1824 aRet.append( "\nUnknown, no introspection available\n" ); 1825 return aRet.makeStringAndClear(); 1826 } 1827 1828 Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS ); 1829 sal_uInt32 nUnoPropCount = props.getLength(); 1830 const Property* pUnoProps = props.getConstArray(); 1831 1832 SbxArray* pProps = rUnoObj.GetProperties(); 1833 sal_uInt16 nPropCount = pProps->Count(); 1834 sal_uInt16 nPropsPerLine = 1 + nPropCount / 30; 1835 for( sal_uInt16 i = 0; i < nPropCount; i++ ) 1836 { 1837 SbxVariable* pVar = pProps->Get( i ); 1838 if( pVar ) 1839 { 1840 OUStringBuffer aPropStr; 1841 if( (i % nPropsPerLine) == 0 ) 1842 aPropStr.append( "\n" ); 1843 1844 // output the type and name 1845 // Is it in Uno a sequence? 1846 SbxDataType eType = pVar->GetFullType(); 1847 1848 bool bMaybeVoid = false; 1849 if( i < nUnoPropCount ) 1850 { 1851 const Property& rProp = pUnoProps[ i ]; 1852 1853 // For MAYBEVOID freshly convert the type from Uno, 1854 // so not just SbxEMPTY is returned. 1855 if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) 1856 { 1857 eType = unoToSbxType( rProp.Type.getTypeClass() ); 1858 bMaybeVoid = true; 1859 } 1860 if( eType == SbxOBJECT ) 1861 { 1862 Type aType = rProp.Type; 1863 if( aType.getTypeClass() == TypeClass_SEQUENCE ) 1864 eType = SbxDataType( SbxOBJECT | SbxARRAY ); 1865 } 1866 } 1867 aPropStr.append( Dbg_SbxDataType2String( eType ) ); 1868 if( bMaybeVoid ) 1869 aPropStr.append( "/void" ); 1870 aPropStr.append( " " ); 1871 aPropStr.append( pVar->GetName() ); 1872 1873 if( i == nPropCount - 1 ) 1874 aPropStr.append( "\n" ); 1875 else 1876 aPropStr.append( "; " ); 1877 1878 aRet.append( aPropStr.makeStringAndClear() ); 1879 } 1880 } 1881 return aRet.makeStringAndClear(); 1882 } 1883 1884 // Debugging help method to display the methods of an SbUnoObjects 1885 static OUString Impl_DumpMethods(SbUnoObject& rUnoObj) 1886 { 1887 OUStringBuffer aRet; 1888 aRet.append("Methods of object "); 1889 aRet.append(getDbgObjectName(rUnoObj)); 1890 1891 // XIntrospectionAccess, so that the types of the parameter could be outputted 1892 Reference< XIntrospectionAccess > xAccess = rUnoObj.getIntrospectionAccess(); 1893 if( !xAccess.is() ) 1894 { 1895 Reference< XInvocation > xInvok = rUnoObj.getInvocation(); 1896 if( xInvok.is() ) 1897 xAccess = xInvok->getIntrospection(); 1898 } 1899 if( !xAccess.is() ) 1900 { 1901 aRet.append( "\nUnknown, no introspection available\n" ); 1902 return aRet.makeStringAndClear(); 1903 } 1904 Sequence< Reference< XIdlMethod > > methods = xAccess->getMethods 1905 ( MethodConcept::ALL - MethodConcept::DANGEROUS ); 1906 const Reference< XIdlMethod >* pUnoMethods = methods.getConstArray(); 1907 1908 SbxArray* pMethods = rUnoObj.GetMethods(); 1909 sal_uInt16 nMethodCount = pMethods->Count(); 1910 if( !nMethodCount ) 1911 { 1912 aRet.append( "\nNo methods found\n" ); 1913 return aRet.makeStringAndClear(); 1914 } 1915 sal_uInt16 nPropsPerLine = 1 + nMethodCount / 30; 1916 for( sal_uInt16 i = 0; i < nMethodCount; i++ ) 1917 { 1918 SbxVariable* pVar = pMethods->Get( i ); 1919 if( pVar ) 1920 { 1921 if( (i % nPropsPerLine) == 0 ) 1922 aRet.append( "\n" ); 1923 1924 // address the method 1925 const Reference< XIdlMethod >& rxMethod = pUnoMethods[i]; 1926 1927 // Is it in Uno a sequence? 1928 SbxDataType eType = pVar->GetFullType(); 1929 if( eType == SbxOBJECT ) 1930 { 1931 Reference< XIdlClass > xClass = rxMethod->getReturnType(); 1932 if( xClass.is() && xClass->getTypeClass() == TypeClass_SEQUENCE ) 1933 eType = SbxDataType( SbxOBJECT | SbxARRAY ); 1934 } 1935 // output the name and the type 1936 aRet.append( Dbg_SbxDataType2String( eType ) ); 1937 aRet.append( " " ); 1938 aRet.append ( pVar->GetName() ); 1939 aRet.append( " ( " ); 1940 1941 // the get-method mustn't have a parameter 1942 Sequence< Reference< XIdlClass > > aParamsSeq = rxMethod->getParameterTypes(); 1943 sal_uInt32 nParamCount = aParamsSeq.getLength(); 1944 const Reference< XIdlClass >* pParams = aParamsSeq.getConstArray(); 1945 1946 if( nParamCount > 0 ) 1947 { 1948 for( sal_uInt32 j = 0; j < nParamCount; j++ ) 1949 { 1950 aRet.append ( Dbg_SbxDataType2String( unoToSbxType( pParams[ j ] ) ) ); 1951 if( j < nParamCount - 1 ) 1952 aRet.append( ", " ); 1953 } 1954 } 1955 else 1956 aRet.append( "void" ); 1957 1958 aRet.append( " ) " ); 1959 1960 if( i == nMethodCount - 1 ) 1961 aRet.append( "\n" ); 1962 else 1963 aRet.append( "; " ); 1964 } 1965 } 1966 return aRet.makeStringAndClear(); 1967 } 1968 1969 1970 // Implementation SbUnoObject 1971 void SbUnoObject::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 1972 { 1973 if( bNeedIntrospection ) 1974 doIntrospection(); 1975 1976 const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint); 1977 if( pHint ) 1978 { 1979 SbxVariable* pVar = pHint->GetVar(); 1980 SbxArray* pParams = pVar->GetParameters(); 1981 SbUnoProperty* pProp = dynamic_cast<SbUnoProperty*>( pVar ); 1982 SbUnoMethod* pMeth = dynamic_cast<SbUnoMethod*>( pVar ); 1983 if( pProp ) 1984 { 1985 bool bInvocation = pProp->isInvocationBased(); 1986 if( pHint->GetId() == SfxHintId::BasicDataWanted ) 1987 { 1988 // Test-Properties 1989 sal_Int32 nId = pProp->nId; 1990 if( nId < 0 ) 1991 { 1992 // Id == -1: Display implemented interfaces according the ClassProvider 1993 if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES" 1994 { 1995 OUString aRetStr = Impl_GetSupportedInterfaces(*this); 1996 pVar->PutString( aRetStr ); 1997 } 1998 // Id == -2: output properties 1999 else if( nId == -2 ) // Property ID_DBG_PROPERTIES 2000 { 2001 // now all properties must be created 2002 implCreateAll(); 2003 OUString aRetStr = Impl_DumpProperties(*this); 2004 pVar->PutString( aRetStr ); 2005 } 2006 // Id == -3: output the methods 2007 else if( nId == -3 ) // Property ID_DBG_METHODS 2008 { 2009 // now all properties must be created 2010 implCreateAll(); 2011 OUString aRetStr = Impl_DumpMethods(*this); 2012 pVar->PutString( aRetStr ); 2013 } 2014 return; 2015 } 2016 2017 if( !bInvocation && mxUnoAccess.is() ) 2018 { 2019 try 2020 { 2021 if ( maStructInfo.get() ) 2022 { 2023 StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() ); 2024 if ( aMember.isEmpty() ) 2025 { 2026 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND ); 2027 } 2028 else 2029 { 2030 if ( pProp->isUnoStruct() ) 2031 { 2032 SbUnoStructRefObject* pSbUnoObject = new SbUnoStructRefObject( pProp->GetName(), aMember ); 2033 SbxObjectRef xWrapper = static_cast<SbxObject*>(pSbUnoObject); 2034 pVar->PutObject( xWrapper.get() ); 2035 } 2036 else 2037 { 2038 Any aRetAny = aMember.getValue(); 2039 // take over the value from Uno to Sbx 2040 unoToSbxValue( pVar, aRetAny ); 2041 } 2042 return; 2043 } 2044 } 2045 // get the value 2046 Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()), UNO_QUERY ); 2047 Any aRetAny = xPropSet->getPropertyValue( pProp->GetName() ); 2048 // The use of getPropertyValue (instead of using the index) is 2049 // suboptimal, but the refactoring to XInvocation is already pending 2050 // Otherwise it is possible to use FastPropertySet 2051 2052 // take over the value from Uno to Sbx 2053 unoToSbxValue( pVar, aRetAny ); 2054 } 2055 catch( const Exception& ) 2056 { 2057 implHandleAnyException( ::cppu::getCaughtException() ); 2058 } 2059 } 2060 else if( bInvocation && mxInvocation.is() ) 2061 { 2062 try 2063 { 2064 sal_uInt32 nParamCount = pParams ? (static_cast<sal_uInt32>(pParams->Count()) - 1) : 0; 2065 bool bCanBeConsideredAMethod = mxInvocation->hasMethod( pProp->GetName() ); 2066 Any aRetAny; 2067 if ( bCanBeConsideredAMethod && nParamCount ) 2068 { 2069 // Automation properties have methods, so.. we need to invoke this through 2070 // XInvocation 2071 Sequence<Any> args; 2072 processAutomationParams( pParams, args, nParamCount ); 2073 aRetAny = invokeAutomationMethod( pProp->GetName(), args, pParams, nParamCount, mxInvocation, INVOKETYPE::GetProp ); 2074 } 2075 else 2076 aRetAny = mxInvocation->getValue( pProp->GetName() ); 2077 // take over the value from Uno to Sbx 2078 unoToSbxValue( pVar, aRetAny ); 2079 if( pParams && bCanBeConsideredAMethod ) 2080 pVar->SetParameters( nullptr ); 2081 2082 } 2083 catch( const Exception& ) 2084 { 2085 implHandleAnyException( ::cppu::getCaughtException() ); 2086 } 2087 } 2088 } 2089 else if( pHint->GetId() == SfxHintId::BasicDataChanged ) 2090 { 2091 if( !bInvocation && mxUnoAccess.is() ) 2092 { 2093 if( pProp->aUnoProp.Attributes & PropertyAttribute::READONLY ) 2094 { 2095 StarBASIC::Error( ERRCODE_BASIC_PROP_READONLY ); 2096 return; 2097 } 2098 if ( maStructInfo.get() ) 2099 { 2100 StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() ); 2101 if ( aMember.isEmpty() ) 2102 { 2103 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND ); 2104 } 2105 else 2106 { 2107 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp ); 2108 aMember.setValue( aAnyValue ); 2109 } 2110 return; 2111 } 2112 // take over the value from Uno to Sbx 2113 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp ); 2114 try 2115 { 2116 // set the value 2117 Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()), UNO_QUERY ); 2118 xPropSet->setPropertyValue( pProp->GetName(), aAnyValue ); 2119 // The use of getPropertyValue (instead of using the index) is 2120 // suboptimal, but the refactoring to XInvocation is already pending 2121 // Otherwise it is possible to use FastPropertySet 2122 } 2123 catch( const Exception& ) 2124 { 2125 implHandleAnyException( ::cppu::getCaughtException() ); 2126 } 2127 } 2128 else if( bInvocation && mxInvocation.is() ) 2129 { 2130 // take over the value from Uno to Sbx 2131 Any aAnyValue = sbxToUnoValueImpl( pVar ); 2132 try 2133 { 2134 // set the value 2135 mxInvocation->setValue( pProp->GetName(), aAnyValue ); 2136 } 2137 catch( const Exception& ) 2138 { 2139 implHandleAnyException( ::cppu::getCaughtException() ); 2140 } 2141 } 2142 } 2143 } 2144 else if( pMeth ) 2145 { 2146 bool bInvocation = pMeth->isInvocationBased(); 2147 if( pHint->GetId() == SfxHintId::BasicDataWanted ) 2148 { 2149 // number of Parameter -1 because of Param0 == this 2150 sal_uInt32 nParamCount = pParams ? (static_cast<sal_uInt32>(pParams->Count()) - 1) : 0; 2151 Sequence<Any> args; 2152 bool bOutParams = false; 2153 2154 if( !bInvocation && mxUnoAccess.is() ) 2155 { 2156 // get info 2157 const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos(); 2158 const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); 2159 sal_uInt32 nUnoParamCount = rInfoSeq.getLength(); 2160 sal_uInt32 nAllocParamCount = nParamCount; 2161 2162 // ignore surplus parameter; alternative: throw an error 2163 if( nParamCount > nUnoParamCount ) 2164 { 2165 nParamCount = nUnoParamCount; 2166 nAllocParamCount = nParamCount; 2167 } 2168 else if( nParamCount < nUnoParamCount ) 2169 { 2170 SbiInstance* pInst = GetSbData()->pInst; 2171 if( pInst && pInst->IsCompatibility() ) 2172 { 2173 // Check types 2174 bool bError = false; 2175 for( sal_uInt32 i = nParamCount ; i < nUnoParamCount ; i++ ) 2176 { 2177 const ParamInfo& rInfo = pParamInfos[i]; 2178 const Reference< XIdlClass >& rxClass = rInfo.aType; 2179 if( rxClass->getTypeClass() != TypeClass_ANY ) 2180 { 2181 bError = true; 2182 StarBASIC::Error( ERRCODE_BASIC_NOT_OPTIONAL ); 2183 } 2184 } 2185 if( !bError ) 2186 nAllocParamCount = nUnoParamCount; 2187 } 2188 } 2189 2190 if( nAllocParamCount > 0 ) 2191 { 2192 args.realloc( nAllocParamCount ); 2193 Any* pAnyArgs = args.getArray(); 2194 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ ) 2195 { 2196 const ParamInfo& rInfo = pParamInfos[i]; 2197 const Reference< XIdlClass >& rxClass = rInfo.aType; 2198 2199 css::uno::Type aType( rxClass->getTypeClass(), rxClass->getName() ); 2200 2201 // ATTENTION: Don't forget for Sbx-Parameter the offset! 2202 pAnyArgs[i] = sbxToUnoValue( pParams->Get( static_cast<sal_uInt16>(i+1) ), aType ); 2203 2204 // If it is not certain check whether the out-parameter are available. 2205 if( !bOutParams ) 2206 { 2207 ParamMode aParamMode = rInfo.aMode; 2208 if( aParamMode != ParamMode_IN ) 2209 bOutParams = true; 2210 } 2211 } 2212 } 2213 } 2214 else if( bInvocation && pParams && mxInvocation.is() ) 2215 { 2216 processAutomationParams( pParams, args, nParamCount ); 2217 } 2218 2219 // call the method 2220 GetSbData()->bBlockCompilerError = true; // #106433 Block compiler errors for API calls 2221 try 2222 { 2223 if( !bInvocation && mxUnoAccess.is() ) 2224 { 2225 Any aRetAny = pMeth->m_xUnoMethod->invoke( getUnoAny(), args ); 2226 2227 // take over the value from Uno to Sbx 2228 unoToSbxValue( pVar, aRetAny ); 2229 2230 // Did we to copy back the Out-Parameter? 2231 if( bOutParams ) 2232 { 2233 const Any* pAnyArgs = args.getConstArray(); 2234 2235 // get info 2236 const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos(); 2237 const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); 2238 2239 sal_uInt32 j; 2240 for( j = 0 ; j < nParamCount ; j++ ) 2241 { 2242 const ParamInfo& rInfo = pParamInfos[j]; 2243 ParamMode aParamMode = rInfo.aMode; 2244 if( aParamMode != ParamMode_IN ) 2245 unoToSbxValue( pParams->Get( static_cast<sal_uInt16>(j+1) ), pAnyArgs[ j ] ); 2246 } 2247 } 2248 } 2249 else if( bInvocation && mxInvocation.is() ) 2250 { 2251 Any aRetAny = invokeAutomationMethod( pMeth->GetName(), args, pParams, nParamCount, mxInvocation, INVOKETYPE::Func ); 2252 unoToSbxValue( pVar, aRetAny ); 2253 } 2254 2255 // remove parameter here, because this was not done anymore in unoToSbxValue() 2256 // for arrays 2257 if( pParams ) 2258 pVar->SetParameters( nullptr ); 2259 } 2260 catch( const Exception& ) 2261 { 2262 implHandleAnyException( ::cppu::getCaughtException() ); 2263 } 2264 GetSbData()->bBlockCompilerError = false; // #106433 Unblock compiler errors 2265 } 2266 } 2267 else 2268 SbxObject::Notify( rBC, rHint ); 2269 } 2270 } 2271 2272 2273 SbUnoObject::SbUnoObject( const OUString& aName_, const Any& aUnoObj_ ) 2274 : SbxObject( aName_ ) 2275 , bNeedIntrospection( true ) 2276 , bNativeCOMObject( false ) 2277 { 2278 // beat out again the default properties of Sbx 2279 Remove( "Name", SbxClassType::DontCare ); 2280 Remove( "Parent", SbxClassType::DontCare ); 2281 2282 // check the type of the objects 2283 TypeClass eType = aUnoObj_.getValueType().getTypeClass(); 2284 Reference< XInterface > x; 2285 if( eType == TypeClass_INTERFACE ) 2286 { 2287 // get the interface from the Any 2288 aUnoObj_ >>= x; 2289 if( !x.is() ) 2290 return; 2291 } 2292 2293 Reference< XTypeProvider > xTypeProvider; 2294 // Did the object have an invocation itself? 2295 mxInvocation.set( x, UNO_QUERY ); 2296 2297 xTypeProvider.set( x, UNO_QUERY ); 2298 2299 if( mxInvocation.is() ) 2300 { 2301 2302 // get the ExactName 2303 mxExactNameInvocation.set( mxInvocation, UNO_QUERY ); 2304 2305 // The remainder refers only to the introspection 2306 if( !xTypeProvider.is() ) 2307 { 2308 bNeedIntrospection = false; 2309 return; 2310 } 2311 2312 // Ignore introspection based members for COM objects to avoid 2313 // hiding of equally named COM symbols, e.g. XInvocation::getValue 2314 Reference< oleautomation::XAutomationObject > xAutomationObject( aUnoObj_, UNO_QUERY ); 2315 if( xAutomationObject.is() ) 2316 bNativeCOMObject = true; 2317 } 2318 2319 maTmpUnoObj = aUnoObj_; 2320 2321 2322 //*** Define the name *** 2323 bool bFatalError = true; 2324 2325 // Is it an interface or a struct? 2326 bool bSetClassName = false; 2327 OUString aClassName_; 2328 if( eType == TypeClass_STRUCT || eType == TypeClass_EXCEPTION ) 2329 { 2330 // Struct is Ok 2331 bFatalError = false; 2332 2333 // insert the real name of the class 2334 if( aName_.isEmpty() ) 2335 { 2336 aClassName_ = aUnoObj_.getValueType().getTypeName(); 2337 bSetClassName = true; 2338 } 2339 StructRefInfo aThisStruct( maTmpUnoObj, maTmpUnoObj.getValueType(), 0 ); 2340 maStructInfo.reset( new SbUnoStructRefObject( GetName(), aThisStruct ) ); 2341 } 2342 else if( eType == TypeClass_INTERFACE ) 2343 { 2344 // Interface works always through the type in the Any 2345 bFatalError = false; 2346 } 2347 if( bSetClassName ) 2348 SetClassName( aClassName_ ); 2349 2350 // Neither interface nor Struct -> FatalError 2351 if( bFatalError ) 2352 { 2353 StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION ); 2354 return; 2355 } 2356 2357 // pass the introspection primal on demand 2358 } 2359 2360 SbUnoObject::~SbUnoObject() 2361 { 2362 } 2363 2364 2365 // pass the introspection on Demand 2366 void SbUnoObject::doIntrospection() 2367 { 2368 if( !bNeedIntrospection ) 2369 return; 2370 2371 Reference<XComponentContext> xContext = comphelper::getProcessComponentContext(); 2372 2373 if (!xContext.is()) 2374 return; 2375 2376 2377 // get the introspection service 2378 Reference<XIntrospection> xIntrospection; 2379 2380 try 2381 { 2382 xIntrospection = theIntrospection::get(xContext); 2383 } 2384 catch ( const css::uno::DeploymentException& ) 2385 { 2386 } 2387 2388 if (!xIntrospection.is()) 2389 return; 2390 2391 bNeedIntrospection = false; 2392 2393 // pass the introspection 2394 try 2395 { 2396 mxUnoAccess = xIntrospection->inspect( maTmpUnoObj ); 2397 } 2398 catch( const RuntimeException& e ) 2399 { 2400 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) ); 2401 } 2402 2403 if( !mxUnoAccess.is() ) 2404 { 2405 // #51475 mark to indicate an invalid object (no mxMaterialHolder) 2406 return; 2407 } 2408 2409 // get MaterialHolder from access 2410 mxMaterialHolder.set( mxUnoAccess, UNO_QUERY ); 2411 2412 // get ExactName from access 2413 mxExactName.set( mxUnoAccess, UNO_QUERY ); 2414 } 2415 2416 2417 // Start of a list of all SbUnoMethod-Instances 2418 static SbUnoMethod* pFirst = nullptr; 2419 2420 void clearUnoMethodsForBasic( StarBASIC const * pBasic ) 2421 { 2422 SbUnoMethod* pMeth = pFirst; 2423 while( pMeth ) 2424 { 2425 SbxObject* pObject = pMeth->GetParent(); 2426 if ( pObject ) 2427 { 2428 StarBASIC* pModBasic = dynamic_cast< StarBASIC* >( pObject->GetParent() ); 2429 if ( pModBasic == pBasic ) 2430 { 2431 // for now the solution is to remove the method from the list and to clear it, 2432 // but in case the element should be correctly transferred to another StarBASIC, 2433 // we should either set module parent to NULL without clearing it, or even 2434 // set the new StarBASIC as the parent of the module 2435 // pObject->SetParent( NULL ); 2436 2437 if( pMeth == pFirst ) 2438 pFirst = pMeth->pNext; 2439 else if( pMeth->pPrev ) 2440 pMeth->pPrev->pNext = pMeth->pNext; 2441 if( pMeth->pNext ) 2442 pMeth->pNext->pPrev = pMeth->pPrev; 2443 2444 pMeth->pPrev = nullptr; 2445 pMeth->pNext = nullptr; 2446 2447 pMeth->SbxValue::Clear(); 2448 pObject->SbxValue::Clear(); 2449 2450 // start from the beginning after object clearing, the cycle will end since the method is removed each time 2451 pMeth = pFirst; 2452 } 2453 else 2454 pMeth = pMeth->pNext; 2455 } 2456 else 2457 pMeth = pMeth->pNext; 2458 } 2459 } 2460 2461 void clearUnoMethods() 2462 { 2463 SbUnoMethod* pMeth = pFirst; 2464 while( pMeth ) 2465 { 2466 pMeth->SbxValue::Clear(); 2467 pMeth = pMeth->pNext; 2468 } 2469 } 2470 2471 2472 SbUnoMethod::SbUnoMethod 2473 ( 2474 const OUString& aName_, 2475 SbxDataType eSbxType, 2476 Reference< XIdlMethod > const & xUnoMethod_, 2477 bool bInvocation 2478 ) 2479 : SbxMethod( aName_, eSbxType ) 2480 , mbInvocation( bInvocation ) 2481 { 2482 m_xUnoMethod = xUnoMethod_; 2483 pParamInfoSeq = nullptr; 2484 2485 // enregister the method in a list 2486 pNext = pFirst; 2487 pPrev = nullptr; 2488 pFirst = this; 2489 if( pNext ) 2490 pNext->pPrev = this; 2491 } 2492 2493 SbUnoMethod::~SbUnoMethod() 2494 { 2495 pParamInfoSeq.reset(); 2496 2497 if( this == pFirst ) 2498 pFirst = pNext; 2499 else if( pPrev ) 2500 pPrev->pNext = pNext; 2501 if( pNext ) 2502 pNext->pPrev = pPrev; 2503 } 2504 2505 SbxInfo* SbUnoMethod::GetInfo() 2506 { 2507 if( !pInfo.is() && m_xUnoMethod.is() ) 2508 { 2509 SbiInstance* pInst = GetSbData()->pInst; 2510 if( pInst && pInst->IsCompatibility() ) 2511 { 2512 pInfo = new SbxInfo(); 2513 2514 const Sequence<ParamInfo>& rInfoSeq = getParamInfos(); 2515 const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); 2516 sal_uInt32 nParamCount = rInfoSeq.getLength(); 2517 2518 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ ) 2519 { 2520 const ParamInfo& rInfo = pParamInfos[i]; 2521 OUString aParamName = rInfo.aName; 2522 2523 pInfo->AddParam( aParamName, SbxVARIANT, SbxFlagBits::Read ); 2524 } 2525 } 2526 } 2527 return pInfo.get(); 2528 } 2529 2530 const Sequence<ParamInfo>& SbUnoMethod::getParamInfos() 2531 { 2532 if (!pParamInfoSeq) 2533 { 2534 Sequence<ParamInfo> aTmp; 2535 if (m_xUnoMethod.is()) 2536 aTmp = m_xUnoMethod->getParameterInfos(); 2537 pParamInfoSeq.reset( new Sequence<ParamInfo>(aTmp) ); 2538 } 2539 return *pParamInfoSeq; 2540 } 2541 2542 SbUnoProperty::SbUnoProperty 2543 ( 2544 const OUString& aName_, 2545 SbxDataType eSbxType, 2546 SbxDataType eRealSbxType, 2547 const Property& aUnoProp_, 2548 sal_Int32 nId_, 2549 bool bInvocation, 2550 bool bUnoStruct 2551 ) 2552 : SbxProperty( aName_, eSbxType ) 2553 , aUnoProp( aUnoProp_ ) 2554 , nId( nId_ ) 2555 , mbInvocation( bInvocation ) 2556 , mRealType( eRealSbxType ) 2557 , mbUnoStruct( bUnoStruct ) 2558 { 2559 // as needed establish a dummy array so that SbiRuntime::CheckArray() works 2560 static SbxArrayRef xDummyArray = new SbxArray( SbxVARIANT ); 2561 if( eSbxType & SbxARRAY ) 2562 PutObject( xDummyArray.get() ); 2563 } 2564 2565 SbUnoProperty::~SbUnoProperty() 2566 {} 2567 2568 2569 SbxVariable* SbUnoObject::Find( const OUString& rName, SbxClassType t ) 2570 { 2571 static Reference< XIdlMethod > xDummyMethod; 2572 static Property aDummyProp; 2573 2574 SbxVariable* pRes = SbxObject::Find( rName, t ); 2575 2576 if( bNeedIntrospection ) 2577 doIntrospection(); 2578 2579 // New 1999-03-04: Create properties on demand. Therefore search now via 2580 // IntrospectionAccess if a property or a method of the required name exist 2581 if( !pRes ) 2582 { 2583 OUString aUName( rName ); 2584 if( mxUnoAccess.is() && !bNativeCOMObject ) 2585 { 2586 if( mxExactName.is() ) 2587 { 2588 OUString aUExactName = mxExactName->getExactName( aUName ); 2589 if( !aUExactName.isEmpty() ) 2590 { 2591 aUName = aUExactName; 2592 } 2593 } 2594 if( mxUnoAccess->hasProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ) ) 2595 { 2596 const Property& rProp = mxUnoAccess-> 2597 getProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ); 2598 2599 // If the property could be void the type had to be set to Variant 2600 SbxDataType eSbxType; 2601 if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) 2602 eSbxType = SbxVARIANT; 2603 else 2604 eSbxType = unoToSbxType( rProp.Type.getTypeClass() ); 2605 2606 SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType ); 2607 // create the property and superimpose it 2608 auto pProp = tools::make_ref<SbUnoProperty>( rProp.Name, eSbxType, eRealSbxType, rProp, 0, false, ( rProp.Type.getTypeClass() == css::uno::TypeClass_STRUCT ) ); 2609 QuickInsert( pProp.get() ); 2610 pRes = pProp.get(); 2611 } 2612 else if( mxUnoAccess->hasMethod( aUName, 2613 MethodConcept::ALL - MethodConcept::DANGEROUS ) ) 2614 { 2615 // address the method 2616 const Reference< XIdlMethod >& rxMethod = mxUnoAccess-> 2617 getMethod( aUName, MethodConcept::ALL - MethodConcept::DANGEROUS ); 2618 2619 // create SbUnoMethod and superimpose it 2620 auto xMethRef = tools::make_ref<SbUnoMethod>( rxMethod->getName(), 2621 unoToSbxType( rxMethod->getReturnType() ), rxMethod, false ); 2622 QuickInsert( xMethRef.get() ); 2623 pRes = xMethRef.get(); 2624 } 2625 2626 // If nothing was found check via XNameAccess 2627 if( !pRes ) 2628 { 2629 try 2630 { 2631 Reference< XNameAccess > xNameAccess( mxUnoAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()), UNO_QUERY ); 2632 2633 if( xNameAccess.is() && xNameAccess->hasByName( rName ) ) 2634 { 2635 Any aAny = xNameAccess->getByName( rName ); 2636 2637 // ATTENTION: Because of XNameAccess, the variable generated here 2638 // may not be included as a fixed property in the object and therefore 2639 // won't be stored anywhere. 2640 // If this leads to problems, it has to be created 2641 // synthetically or a class SbUnoNameAccessProperty, 2642 // which checks the existence on access and which 2643 // is disposed if the name is not found anymore. 2644 pRes = new SbxVariable( SbxVARIANT ); 2645 unoToSbxValue( pRes, aAny ); 2646 } 2647 } 2648 catch( const NoSuchElementException& e ) 2649 { 2650 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) ); 2651 } 2652 catch( const Exception& ) 2653 { 2654 // Establish so that the exception error will not be overwritten 2655 if( !pRes ) 2656 pRes = new SbxVariable( SbxVARIANT ); 2657 2658 implHandleAnyException( ::cppu::getCaughtException() ); 2659 } 2660 } 2661 } 2662 if( !pRes && mxInvocation.is() ) 2663 { 2664 if( mxExactNameInvocation.is() ) 2665 { 2666 OUString aUExactName = mxExactNameInvocation->getExactName( aUName ); 2667 if( !aUExactName.isEmpty() ) 2668 { 2669 aUName = aUExactName; 2670 } 2671 } 2672 2673 try 2674 { 2675 if( mxInvocation->hasProperty( aUName ) ) 2676 { 2677 // create a property and superimpose it 2678 auto xVarRef = tools::make_ref<SbUnoProperty>( aUName, SbxVARIANT, SbxVARIANT, aDummyProp, 0, true, false ); 2679 QuickInsert( xVarRef.get() ); 2680 pRes = xVarRef.get(); 2681 } 2682 else if( mxInvocation->hasMethod( aUName ) ) 2683 { 2684 // create SbUnoMethode and superimpose it 2685 auto xMethRef = tools::make_ref<SbUnoMethod>( aUName, SbxVARIANT, xDummyMethod, true ); 2686 QuickInsert( xMethRef.get() ); 2687 pRes = xMethRef.get(); 2688 } 2689 else 2690 { 2691 Reference< XDirectInvocation > xDirectInvoke( mxInvocation, UNO_QUERY ); 2692 if ( xDirectInvoke.is() && xDirectInvoke->hasMember( aUName ) ) 2693 { 2694 auto xMethRef = tools::make_ref<SbUnoMethod>( aUName, SbxVARIANT, xDummyMethod, true ); 2695 QuickInsert( xMethRef.get() ); 2696 pRes = xMethRef.get(); 2697 } 2698 2699 } 2700 } 2701 catch( const RuntimeException& e ) 2702 { 2703 // Establish so that the exception error will not be overwritten 2704 if( !pRes ) 2705 pRes = new SbxVariable( SbxVARIANT ); 2706 2707 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) ); 2708 } 2709 } 2710 } 2711 2712 // At the very end checking if the Dbg_-Properties are meant 2713 2714 if( !pRes ) 2715 { 2716 if( rName.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES) || 2717 rName.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES) || 2718 rName.equalsIgnoreAsciiCase(ID_DBG_METHODS) ) 2719 { 2720 // Create 2721 implCreateDbgProperties(); 2722 2723 // Now they have to be found regular 2724 pRes = SbxObject::Find( rName, SbxClassType::DontCare ); 2725 } 2726 } 2727 return pRes; 2728 } 2729 2730 2731 // help method to create the dbg_-Properties 2732 void SbUnoObject::implCreateDbgProperties() 2733 { 2734 Property aProp; 2735 2736 // Id == -1: display the implemented interfaces corresponding the ClassProvider 2737 auto xVarRef = tools::make_ref<SbUnoProperty>( OUString(ID_DBG_SUPPORTEDINTERFACES), SbxSTRING, SbxSTRING, aProp, -1, false, false ); 2738 QuickInsert( xVarRef.get() ); 2739 2740 // Id == -2: output the properties 2741 xVarRef = tools::make_ref<SbUnoProperty>( OUString(ID_DBG_PROPERTIES), SbxSTRING, SbxSTRING, aProp, -2, false, false ); 2742 QuickInsert( xVarRef.get() ); 2743 2744 // Id == -3: output the Methods 2745 xVarRef = tools::make_ref<SbUnoProperty>( OUString(ID_DBG_METHODS), SbxSTRING, SbxSTRING, aProp, -3, false, false ); 2746 QuickInsert( xVarRef.get() ); 2747 } 2748 2749 void SbUnoObject::implCreateAll() 2750 { 2751 // throw away all existing methods and properties 2752 pMethods = tools::make_ref<SbxArray>(); 2753 pProps = tools::make_ref<SbxArray>(); 2754 2755 if( bNeedIntrospection ) doIntrospection(); 2756 2757 // get introspection 2758 Reference< XIntrospectionAccess > xAccess = mxUnoAccess; 2759 if( !xAccess.is() || bNativeCOMObject ) 2760 { 2761 if( mxInvocation.is() ) 2762 xAccess = mxInvocation->getIntrospection(); 2763 else if( bNativeCOMObject ) 2764 return; 2765 } 2766 if( !xAccess.is() ) 2767 return; 2768 2769 // Establish properties 2770 Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS ); 2771 sal_uInt32 nPropCount = props.getLength(); 2772 const Property* pProps_ = props.getConstArray(); 2773 2774 sal_uInt32 i; 2775 for( i = 0 ; i < nPropCount ; i++ ) 2776 { 2777 const Property& rProp = pProps_[ i ]; 2778 2779 // If the property could be void the type had to be set to Variant 2780 SbxDataType eSbxType; 2781 if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) 2782 eSbxType = SbxVARIANT; 2783 else 2784 eSbxType = unoToSbxType( rProp.Type.getTypeClass() ); 2785 2786 SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType ); 2787 // Create property and superimpose it 2788 auto xVarRef = tools::make_ref<SbUnoProperty>( rProp.Name, eSbxType, eRealSbxType, rProp, i, false, ( rProp.Type.getTypeClass() == css::uno::TypeClass_STRUCT ) ); 2789 QuickInsert( xVarRef.get() ); 2790 } 2791 2792 // Create Dbg_-Properties 2793 implCreateDbgProperties(); 2794 2795 // Create methods 2796 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods 2797 ( MethodConcept::ALL - MethodConcept::DANGEROUS ); 2798 sal_uInt32 nMethCount = aMethodSeq.getLength(); 2799 const Reference< XIdlMethod >* pMethods_ = aMethodSeq.getConstArray(); 2800 for( i = 0 ; i < nMethCount ; i++ ) 2801 { 2802 // address method 2803 const Reference< XIdlMethod >& rxMethod = pMethods_[i]; 2804 2805 // Create SbUnoMethod and superimpose it 2806 auto xMethRef = tools::make_ref<SbUnoMethod> 2807 ( rxMethod->getName(), unoToSbxType( rxMethod->getReturnType() ), rxMethod, false ); 2808 QuickInsert( xMethRef.get() ); 2809 } 2810 } 2811 2812 2813 // output the value 2814 Any SbUnoObject::getUnoAny() 2815 { 2816 Any aRetAny; 2817 if( bNeedIntrospection ) doIntrospection(); 2818 if ( maStructInfo.get() ) 2819 aRetAny = maTmpUnoObj; 2820 else if( mxMaterialHolder.is() ) 2821 aRetAny = mxMaterialHolder->getMaterial(); 2822 else if( mxInvocation.is() ) 2823 aRetAny <<= mxInvocation; 2824 return aRetAny; 2825 } 2826 2827 // help method to create a Uno-Struct per CoreReflection 2828 static SbUnoObject* Impl_CreateUnoStruct( const OUString& aClassName ) 2829 { 2830 // get CoreReflection 2831 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); 2832 if( !xCoreReflection.is() ) 2833 return nullptr; 2834 2835 // search for the class 2836 Reference< XIdlClass > xClass; 2837 const Reference< XHierarchicalNameAccess >& xHarryName = 2838 getCoreReflection_HierarchicalNameAccess_Impl(); 2839 if( xHarryName.is() && xHarryName->hasByHierarchicalName( aClassName ) ) 2840 xClass = xCoreReflection->forName( aClassName ); 2841 if( !xClass.is() ) 2842 return nullptr; 2843 2844 // Is it really a struct? 2845 TypeClass eType = xClass->getTypeClass(); 2846 if ( ( eType != TypeClass_STRUCT ) && ( eType != TypeClass_EXCEPTION ) ) 2847 return nullptr; 2848 2849 // create an instance 2850 Any aNewAny; 2851 xClass->createObject( aNewAny ); 2852 // make a SbUnoObject out of it 2853 SbUnoObject* pUnoObj = new SbUnoObject( aClassName, aNewAny ); 2854 return pUnoObj; 2855 } 2856 2857 2858 // Factory-Class to create Uno-Structs per DIM AS NEW 2859 SbxBase* SbUnoFactory::Create( sal_uInt16, sal_uInt32 ) 2860 { 2861 // Via SbxId nothing works in Uno 2862 return nullptr; 2863 } 2864 2865 SbxObject* SbUnoFactory::CreateObject( const OUString& rClassName ) 2866 { 2867 return Impl_CreateUnoStruct( rClassName ); 2868 } 2869 2870 2871 // Provisional interface for the UNO-Connection 2872 // Deliver a SbxObject, that wrap a Uno-Interface 2873 SbxObjectRef GetSbUnoObject( const OUString& aName, const Any& aUnoObj_ ) 2874 { 2875 return new SbUnoObject( aName, aUnoObj_ ); 2876 } 2877 2878 // Force creation of all properties for debugging 2879 void createAllObjectProperties( SbxObject* pObj ) 2880 { 2881 if( !pObj ) 2882 return; 2883 2884 SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>( pObj ); 2885 SbUnoStructRefObject* pUnoStructObj = dynamic_cast<SbUnoStructRefObject*>( pObj ); 2886 if( pUnoObj ) 2887 { 2888 pUnoObj->createAllProperties(); 2889 } 2890 else if ( pUnoStructObj ) 2891 { 2892 pUnoStructObj->createAllProperties(); 2893 } 2894 } 2895 2896 2897 void RTL_Impl_CreateUnoStruct( SbxArray& rPar ) 2898 { 2899 // We need 1 parameter minimum 2900 if ( rPar.Count() < 2 ) 2901 { 2902 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); 2903 return; 2904 } 2905 2906 // get the name of the class of the struct 2907 OUString aClassName = rPar.Get(1)->GetOUString(); 2908 2909 // try to create Struct with the same name 2910 SbUnoObjectRef xUnoObj = Impl_CreateUnoStruct( aClassName ); 2911 if( !xUnoObj.is() ) 2912 { 2913 return; 2914 } 2915 // return the object 2916 SbxVariableRef refVar = rPar.Get(0); 2917 refVar->PutObject( xUnoObj.get() ); 2918 } 2919 2920 void RTL_Impl_CreateUnoService( SbxArray& rPar ) 2921 { 2922 // We need 1 Parameter minimum 2923 if ( rPar.Count() < 2 ) 2924 { 2925 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); 2926 return; 2927 } 2928 2929 // get the name of the class of the struct 2930 OUString aServiceName = rPar.Get(1)->GetOUString(); 2931 2932 // search for the service and instantiate it 2933 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); 2934 Reference< XInterface > xInterface; 2935 try 2936 { 2937 xInterface = xFactory->createInstance( aServiceName ); 2938 } 2939 catch( const Exception& ) 2940 { 2941 implHandleAnyException( ::cppu::getCaughtException() ); 2942 } 2943 2944 SbxVariableRef refVar = rPar.Get(0); 2945 if( xInterface.is() ) 2946 { 2947 // Create a SbUnoObject out of it and return it 2948 SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, Any(xInterface) ); 2949 if( xUnoObj->getUnoAny().hasValue() ) 2950 { 2951 // return the object 2952 refVar->PutObject( xUnoObj.get() ); 2953 } 2954 else 2955 { 2956 refVar->PutObject( nullptr ); 2957 } 2958 } 2959 else 2960 { 2961 refVar->PutObject( nullptr ); 2962 } 2963 } 2964 2965 void RTL_Impl_CreateUnoServiceWithArguments( SbxArray& rPar ) 2966 { 2967 // We need 2 parameter minimum 2968 if ( rPar.Count() < 3 ) 2969 { 2970 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); 2971 return; 2972 } 2973 2974 // get the name of the class of the struct 2975 OUString aServiceName = rPar.Get(1)->GetOUString(); 2976 Any aArgAsAny = sbxToUnoValue( rPar.Get(2), 2977 cppu::UnoType<Sequence<Any>>::get() ); 2978 Sequence< Any > aArgs; 2979 aArgAsAny >>= aArgs; 2980 2981 // search for the service and instantiate it 2982 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); 2983 Reference< XInterface > xInterface; 2984 try 2985 { 2986 xInterface = xFactory->createInstanceWithArguments( aServiceName, aArgs ); 2987 } 2988 catch( const Exception& ) 2989 { 2990 implHandleAnyException( ::cppu::getCaughtException() ); 2991 } 2992 2993 SbxVariableRef refVar = rPar.Get(0); 2994 if( xInterface.is() ) 2995 { 2996 // Create a SbUnoObject out of it and return it 2997 SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, Any(xInterface) ); 2998 if( xUnoObj->getUnoAny().hasValue() ) 2999 { 3000 // return the object 3001 refVar->PutObject( xUnoObj.get() ); 3002 } 3003 else 3004 { 3005 refVar->PutObject( nullptr ); 3006 } 3007 } 3008 else 3009 { 3010 refVar->PutObject( nullptr ); 3011 } 3012 } 3013 3014 void RTL_Impl_GetProcessServiceManager( SbxArray& rPar ) 3015 { 3016 SbxVariableRef refVar = rPar.Get(0); 3017 3018 // get the global service manager 3019 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); 3020 3021 // Create a SbUnoObject out of it and return it 3022 SbUnoObjectRef xUnoObj = new SbUnoObject( "ProcessServiceManager", Any(xFactory) ); 3023 refVar->PutObject( xUnoObj.get() ); 3024 } 3025 3026 void RTL_Impl_HasInterfaces( SbxArray& rPar ) 3027 { 3028 // We need 2 parameter minimum 3029 sal_uInt16 nParCount = rPar.Count(); 3030 if( nParCount < 3 ) 3031 { 3032 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); 3033 return; 3034 } 3035 3036 // variable for the return value 3037 SbxVariableRef refVar = rPar.Get(0); 3038 refVar->PutBool( false ); 3039 3040 // get the Uno-Object 3041 SbxBaseRef pObj = rPar.Get( 1 )->GetObject(); 3042 auto obj = dynamic_cast<SbUnoObject*>( pObj.get() ); 3043 if( obj == nullptr ) 3044 { 3045 return; 3046 } 3047 Any aAny = obj->getUnoAny(); 3048 auto x = o3tl::tryAccess<Reference<XInterface>>(aAny); 3049 if( !x ) 3050 { 3051 return; 3052 } 3053 3054 // get CoreReflection 3055 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); 3056 if( !xCoreReflection.is() ) 3057 { 3058 return; 3059 } 3060 for( sal_uInt16 i = 2 ; i < nParCount ; i++ ) 3061 { 3062 // get the name of the interface of the struct 3063 OUString aIfaceName = rPar.Get( i )->GetOUString(); 3064 3065 // search for the class 3066 Reference< XIdlClass > xClass = xCoreReflection->forName( aIfaceName ); 3067 if( !xClass.is() ) 3068 { 3069 return; 3070 } 3071 // check if the interface will be supported 3072 OUString aClassName = xClass->getName(); 3073 Type aClassType( xClass->getTypeClass(), aClassName ); 3074 if( !(*x)->queryInterface( aClassType ).hasValue() ) 3075 { 3076 return; 3077 } 3078 } 3079 3080 // Everything works; then return TRUE 3081 refVar->PutBool( true ); 3082 } 3083 3084 void RTL_Impl_IsUnoStruct( SbxArray& rPar ) 3085 { 3086 // We need 1 parameter minimum 3087 if ( rPar.Count() < 2 ) 3088 { 3089 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); 3090 return; 3091 } 3092 3093 // variable for the return value 3094 SbxVariableRef refVar = rPar.Get(0); 3095 refVar->PutBool( false ); 3096 3097 // get the Uno-Object 3098 SbxVariableRef xParam = rPar.Get( 1 ); 3099 if( !xParam->IsObject() ) 3100 { 3101 return; 3102 } 3103 SbxBaseRef pObj = rPar.Get( 1 )->GetObject(); 3104 auto obj = dynamic_cast<SbUnoObject*>( pObj.get() ); 3105 if( obj == nullptr ) 3106 { 3107 return; 3108 } 3109 Any aAny = obj->getUnoAny(); 3110 TypeClass eType = aAny.getValueType().getTypeClass(); 3111 if( eType == TypeClass_STRUCT ) 3112 { 3113 refVar->PutBool( true ); 3114 } 3115 } 3116 3117 3118 void RTL_Impl_EqualUnoObjects( SbxArray& rPar ) 3119 { 3120 if ( rPar.Count() < 3 ) 3121 { 3122 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); 3123 return; 3124 } 3125 3126 // variable for the return value 3127 SbxVariableRef refVar = rPar.Get(0); 3128 refVar->PutBool( false ); 3129 3130 // get the Uno-Objects 3131 SbxVariableRef xParam1 = rPar.Get( 1 ); 3132 if( !xParam1->IsObject() ) 3133 { 3134 return; 3135 } 3136 SbxBaseRef pObj1 = xParam1->GetObject(); 3137 auto obj1 = dynamic_cast<SbUnoObject*>( pObj1.get() ); 3138 if( obj1 == nullptr ) 3139 { 3140 return; 3141 } 3142 Any aAny1 = obj1->getUnoAny(); 3143 TypeClass eType1 = aAny1.getValueType().getTypeClass(); 3144 if( eType1 != TypeClass_INTERFACE ) 3145 { 3146 return; 3147 } 3148 Reference< XInterface > x1; 3149 aAny1 >>= x1; 3150 3151 SbxVariableRef xParam2 = rPar.Get( 2 ); 3152 if( !xParam2->IsObject() ) 3153 { 3154 return; 3155 } 3156 SbxBaseRef pObj2 = xParam2->GetObject(); 3157 auto obj2 = dynamic_cast<SbUnoObject*>( pObj2.get() ); 3158 if( obj2 == nullptr ) 3159 { 3160 return; 3161 } 3162 Any aAny2 = obj2->getUnoAny(); 3163 TypeClass eType2 = aAny2.getValueType().getTypeClass(); 3164 if( eType2 != TypeClass_INTERFACE ) 3165 { 3166 return; 3167 } 3168 Reference< XInterface > x2; 3169 aAny2 >>= x2; 3170 3171 if( x1 == x2 ) 3172 { 3173 refVar->PutBool( true ); 3174 } 3175 } 3176 3177 3178 // helper wrapper function to interact with TypeProvider and 3179 // XTypeDescriptionEnumerationAccess. 3180 // if it fails for whatever reason 3181 // returned Reference<> be null e.g. .is() will be false 3182 3183 static Reference< XTypeDescriptionEnumeration > getTypeDescriptorEnumeration( const OUString& sSearchRoot, 3184 const Sequence< TypeClass >& types, 3185 TypeDescriptionSearchDepth depth ) 3186 { 3187 Reference< XTypeDescriptionEnumeration > xEnum; 3188 Reference< XTypeDescriptionEnumerationAccess> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY ); 3189 if ( xTypeEnumAccess.is() ) 3190 { 3191 try 3192 { 3193 xEnum = xTypeEnumAccess->createTypeDescriptionEnumeration( 3194 sSearchRoot, types, depth ); 3195 } 3196 catch(const NoSuchTypeNameException& /*nstne*/ ) {} 3197 catch(const InvalidTypeNameException& /*nstne*/ ) {} 3198 } 3199 return xEnum; 3200 } 3201 3202 VBAConstantHelper& 3203 VBAConstantHelper::instance() 3204 { 3205 static VBAConstantHelper aHelper; 3206 return aHelper; 3207 } 3208 3209 void VBAConstantHelper::init() 3210 { 3211 if ( !isInited ) 3212 { 3213 Sequence< TypeClass > types(1); 3214 types[ 0 ] = TypeClass_CONSTANTS; 3215 Reference< XTypeDescriptionEnumeration > xEnum = getTypeDescriptorEnumeration( "ooo.vba", types, TypeDescriptionSearchDepth_INFINITE ); 3216 3217 if ( !xEnum.is()) 3218 { 3219 return; //NULL; 3220 } 3221 while ( xEnum->hasMoreElements() ) 3222 { 3223 Reference< XConstantsTypeDescription > xConstants( xEnum->nextElement(), UNO_QUERY ); 3224 if ( xConstants.is() ) 3225 { 3226 // store constant group name 3227 OUString sFullName = xConstants->getName(); 3228 sal_Int32 indexLastDot = sFullName.lastIndexOf('.'); 3229 OUString sLeafName( sFullName ); 3230 if ( indexLastDot > -1 ) 3231 { 3232 sLeafName = sFullName.copy( indexLastDot + 1); 3233 } 3234 aConstCache.push_back( sLeafName ); // assume constant group names are unique 3235 Sequence< Reference< XConstantTypeDescription > > aConsts = xConstants->getConstants(); 3236 for (sal_Int32 i = 0; i != aConsts.getLength(); ++i) 3237 { 3238 // store constant member name 3239 sFullName = aConsts[i]->getName(); 3240 indexLastDot = sFullName.lastIndexOf('.'); 3241 sLeafName = sFullName; 3242 if ( indexLastDot > -1 ) 3243 { 3244 sLeafName = sFullName.copy( indexLastDot + 1); 3245 } 3246 aConstHash[ sLeafName.toAsciiLowerCase() ] = aConsts[i]->getConstantValue(); 3247 } 3248 } 3249 } 3250 isInited = true; 3251 } 3252 } 3253 3254 bool 3255 VBAConstantHelper::isVBAConstantType( const OUString& rName ) 3256 { 3257 init(); 3258 bool bConstant = false; 3259 3260 for (auto const& elem : aConstCache) 3261 { 3262 if( rName.equalsIgnoreAsciiCase(elem) ) 3263 { 3264 bConstant = true; 3265 break; 3266 } 3267 } 3268 return bConstant; 3269 } 3270 3271 SbxVariable* 3272 VBAConstantHelper::getVBAConstant( const OUString& rName ) 3273 { 3274 SbxVariable* pConst = nullptr; 3275 init(); 3276 3277 auto it = aConstHash.find( rName.toAsciiLowerCase() ); 3278 3279 if ( it != aConstHash.end() ) 3280 { 3281 pConst = new SbxVariable( SbxVARIANT ); 3282 pConst->SetName( rName ); 3283 unoToSbxValue( pConst, it->second ); 3284 } 3285 3286 return pConst; 3287 } 3288 3289 // Function to search for a global identifier in the 3290 // UnoScope and to wrap it for Sbx 3291 SbUnoClass* findUnoClass( const OUString& rName ) 3292 { 3293 // #105550 Check if module exists 3294 SbUnoClass* pUnoClass = nullptr; 3295 3296 const Reference< XHierarchicalNameAccess >& xTypeAccess = getTypeProvider_Impl(); 3297 if( xTypeAccess->hasByHierarchicalName( rName ) ) 3298 { 3299 Any aRet = xTypeAccess->getByHierarchicalName( rName ); 3300 Reference< XTypeDescription > xTypeDesc; 3301 aRet >>= xTypeDesc; 3302 3303 if( xTypeDesc.is() ) 3304 { 3305 TypeClass eTypeClass = xTypeDesc->getTypeClass(); 3306 if( eTypeClass == TypeClass_MODULE || eTypeClass == TypeClass_CONSTANTS ) 3307 { 3308 pUnoClass = new SbUnoClass( rName ); 3309 } 3310 } 3311 } 3312 return pUnoClass; 3313 } 3314 3315 SbxVariable* SbUnoClass::Find( const OUString& rName, SbxClassType ) 3316 { 3317 SbxVariable* pRes = SbxObject::Find( rName, SbxClassType::Variable ); 3318 3319 // If nothing were located the submodule isn't known yet 3320 if( !pRes ) 3321 { 3322 // If it is already a class, ask for the field 3323 if( m_xClass.is() ) 3324 { 3325 // Is it a field(?) 3326 Reference< XIdlField > xField = m_xClass->getField( rName ); 3327 if( xField.is() ) 3328 { 3329 try 3330 { 3331 Any aAny = xField->get( {} ); //TODO: does this make sense? 3332 3333 // Convert to Sbx 3334 pRes = new SbxVariable( SbxVARIANT ); 3335 pRes->SetName( rName ); 3336 unoToSbxValue( pRes, aAny ); 3337 } 3338 catch( const Exception& ) 3339 { 3340 implHandleAnyException( ::cppu::getCaughtException() ); 3341 } 3342 } 3343 } 3344 else 3345 { 3346 // expand fully qualified name 3347 OUString aNewName = GetName() 3348 + "." 3349 + rName; 3350 3351 // get CoreReflection 3352 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); 3353 if( xCoreReflection.is() ) 3354 { 3355 // Is it a constant? 3356 Reference< XHierarchicalNameAccess > xHarryName( xCoreReflection, UNO_QUERY ); 3357 if( xHarryName.is() ) 3358 { 3359 try 3360 { 3361 Any aValue = xHarryName->getByHierarchicalName( aNewName ); 3362 TypeClass eType = aValue.getValueType().getTypeClass(); 3363 3364 // Interface located? Then it is a class 3365 if( eType == TypeClass_INTERFACE ) 3366 { 3367 Reference< XIdlClass > xClass( aValue, UNO_QUERY ); 3368 if( xClass.is() ) 3369 { 3370 pRes = new SbxVariable( SbxVARIANT ); 3371 SbxObjectRef xWrapper = static_cast<SbxObject*>(new SbUnoClass( aNewName, xClass )); 3372 pRes->PutObject( xWrapper.get() ); 3373 } 3374 } 3375 else 3376 { 3377 pRes = new SbxVariable( SbxVARIANT ); 3378 unoToSbxValue( pRes, aValue ); 3379 } 3380 } 3381 catch( const NoSuchElementException& ) 3382 { 3383 } 3384 } 3385 3386 // Otherwise take it again as class 3387 if( !pRes ) 3388 { 3389 SbUnoClass* pNewClass = findUnoClass( aNewName ); 3390 if( pNewClass ) 3391 { 3392 pRes = new SbxVariable( SbxVARIANT ); 3393 SbxObjectRef xWrapper = static_cast<SbxObject*>(pNewClass); 3394 pRes->PutObject( xWrapper.get() ); 3395 } 3396 } 3397 3398 // A UNO service? 3399 if( !pRes ) 3400 { 3401 SbUnoService* pUnoService = findUnoService( aNewName ); 3402 if( pUnoService ) 3403 { 3404 pRes = new SbxVariable( SbxVARIANT ); 3405 SbxObjectRef xWrapper = static_cast<SbxObject*>(pUnoService); 3406 pRes->PutObject( xWrapper.get() ); 3407 } 3408 } 3409 3410 // A UNO singleton? 3411 if( !pRes ) 3412 { 3413 SbUnoSingleton* pUnoSingleton = findUnoSingleton( aNewName ); 3414 if( pUnoSingleton ) 3415 { 3416 pRes = new SbxVariable( SbxVARIANT ); 3417 SbxObjectRef xWrapper = static_cast<SbxObject*>(pUnoSingleton); 3418 pRes->PutObject( xWrapper.get() ); 3419 } 3420 } 3421 } 3422 } 3423 3424 if( pRes ) 3425 { 3426 pRes->SetName( rName ); 3427 3428 // Insert variable, so that it could be found later 3429 QuickInsert( pRes ); 3430 3431 // Take us out as listener at once, 3432 // the values are all constant 3433 if( pRes->IsBroadcaster() ) 3434 EndListening( pRes->GetBroadcaster(), true ); 3435 } 3436 } 3437 return pRes; 3438 } 3439 3440 3441 SbUnoService* findUnoService( const OUString& rName ) 3442 { 3443 SbUnoService* pSbUnoService = nullptr; 3444 3445 const Reference< XHierarchicalNameAccess >& xTypeAccess = getTypeProvider_Impl(); 3446 if( xTypeAccess->hasByHierarchicalName( rName ) ) 3447 { 3448 Any aRet = xTypeAccess->getByHierarchicalName( rName ); 3449 Reference< XTypeDescription > xTypeDesc; 3450 aRet >>= xTypeDesc; 3451 3452 if( xTypeDesc.is() ) 3453 { 3454 TypeClass eTypeClass = xTypeDesc->getTypeClass(); 3455 if( eTypeClass == TypeClass_SERVICE ) 3456 { 3457 Reference< XServiceTypeDescription2 > xServiceTypeDesc( xTypeDesc, UNO_QUERY ); 3458 if( xServiceTypeDesc.is() ) 3459 pSbUnoService = new SbUnoService( rName, xServiceTypeDesc ); 3460 } 3461 } 3462 } 3463 return pSbUnoService; 3464 } 3465 3466 SbxVariable* SbUnoService::Find( const OUString& rName, SbxClassType ) 3467 { 3468 SbxVariable* pRes = SbxObject::Find( rName, SbxClassType::Method ); 3469 3470 if( !pRes ) 3471 { 3472 // If it is already a class ask for a field 3473 if( m_bNeedsInit && m_xServiceTypeDesc.is() ) 3474 { 3475 m_bNeedsInit = false; 3476 3477 Sequence< Reference< XServiceConstructorDescription > > aSCDSeq = m_xServiceTypeDesc->getConstructors(); 3478 const Reference< XServiceConstructorDescription >* pCtorSeq = aSCDSeq.getConstArray(); 3479 int nCtorCount = aSCDSeq.getLength(); 3480 for( int i = 0 ; i < nCtorCount ; ++i ) 3481 { 3482 Reference< XServiceConstructorDescription > xCtor = pCtorSeq[i]; 3483 3484 OUString aName( xCtor->getName() ); 3485 if( aName.isEmpty() ) 3486 { 3487 if( xCtor->isDefaultConstructor() ) 3488 { 3489 aName = "create"; 3490 } 3491 } 3492 3493 if( !aName.isEmpty() ) 3494 { 3495 // Create and insert SbUnoServiceCtor 3496 SbxVariableRef xSbCtorRef = new SbUnoServiceCtor( aName, xCtor ); 3497 QuickInsert( xSbCtorRef.get() ); 3498 } 3499 } 3500 pRes = SbxObject::Find( rName, SbxClassType::Method ); 3501 } 3502 } 3503 3504 return pRes; 3505 } 3506 3507 void SbUnoService::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 3508 { 3509 const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint); 3510 if( pHint ) 3511 { 3512 SbxVariable* pVar = pHint->GetVar(); 3513 SbxArray* pParams = pVar->GetParameters(); 3514 SbUnoServiceCtor* pUnoCtor = dynamic_cast<SbUnoServiceCtor*>( pVar ); 3515 if( pUnoCtor && pHint->GetId() == SfxHintId::BasicDataWanted ) 3516 { 3517 // Parameter count -1 because of Param0 == this 3518 sal_uInt32 nParamCount = pParams ? (static_cast<sal_uInt32>(pParams->Count()) - 1) : 0; 3519 Sequence<Any> args; 3520 3521 Reference< XServiceConstructorDescription > xCtor = pUnoCtor->getServiceCtorDesc(); 3522 Sequence< Reference< XParameter > > aParameterSeq = xCtor->getParameters(); 3523 const Reference< XParameter >* pParameterSeq = aParameterSeq.getConstArray(); 3524 sal_uInt32 nUnoParamCount = aParameterSeq.getLength(); 3525 3526 // Default: Ignore not needed parameters 3527 bool bParameterError = false; 3528 3529 // Is the last parameter a rest parameter? 3530 bool bRestParameterMode = false; 3531 if( nUnoParamCount > 0 ) 3532 { 3533 Reference< XParameter > xLastParam = pParameterSeq[ nUnoParamCount - 1 ]; 3534 if( xLastParam.is() ) 3535 { 3536 if( xLastParam->isRestParameter() ) 3537 bRestParameterMode = true; 3538 } 3539 } 3540 3541 // Too many parameters with context as first parameter? 3542 sal_uInt16 nSbxParameterOffset = 1; 3543 sal_uInt16 nParameterOffsetByContext = 0; 3544 Reference < XComponentContext > xFirstParamContext; 3545 if( nParamCount > nUnoParamCount ) 3546 { 3547 // Check if first parameter is a context and use it 3548 // then in createInstanceWithArgumentsAndContext 3549 Any aArg0 = sbxToUnoValue( pParams->Get( nSbxParameterOffset ) ); 3550 if( (aArg0 >>= xFirstParamContext) && xFirstParamContext.is() ) 3551 nParameterOffsetByContext = 1; 3552 } 3553 3554 sal_uInt32 nEffectiveParamCount = nParamCount - nParameterOffsetByContext; 3555 sal_uInt32 nAllocParamCount = nEffectiveParamCount; 3556 if( nEffectiveParamCount > nUnoParamCount ) 3557 { 3558 if( !bRestParameterMode ) 3559 { 3560 nEffectiveParamCount = nUnoParamCount; 3561 nAllocParamCount = nUnoParamCount; 3562 } 3563 } 3564 // Not enough parameters? 3565 else if( nUnoParamCount > nEffectiveParamCount ) 3566 { 3567 // RestParameterMode only helps if one (the last) parameter is missing 3568 int nDiff = nUnoParamCount - nEffectiveParamCount; 3569 if( !bRestParameterMode || nDiff > 1 ) 3570 { 3571 bParameterError = true; 3572 StarBASIC::Error( ERRCODE_BASIC_NOT_OPTIONAL ); 3573 } 3574 } 3575 3576 if( !bParameterError ) 3577 { 3578 bool bOutParams = false; 3579 if( nAllocParamCount > 0 ) 3580 { 3581 args.realloc( nAllocParamCount ); 3582 Any* pAnyArgs = args.getArray(); 3583 for( sal_uInt32 i = 0 ; i < nEffectiveParamCount ; i++ ) 3584 { 3585 sal_uInt16 iSbx = static_cast<sal_uInt16>(i + nSbxParameterOffset + nParameterOffsetByContext); 3586 3587 // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount 3588 Reference< XParameter > xParam; 3589 if( i < nUnoParamCount ) 3590 { 3591 xParam = pParameterSeq[i]; 3592 if( !xParam.is() ) 3593 continue; 3594 3595 Reference< XTypeDescription > xParamTypeDesc = xParam->getType(); 3596 if( !xParamTypeDesc.is() ) 3597 continue; 3598 css::uno::Type aType( xParamTypeDesc->getTypeClass(), xParamTypeDesc->getName() ); 3599 3600 // sbx parameter needs offset 1 3601 pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ), aType ); 3602 3603 // Check for out parameter if not already done 3604 if( !bOutParams && xParam->isOut() ) 3605 bOutParams = true; 3606 } 3607 else 3608 { 3609 pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ) ); 3610 } 3611 } 3612 } 3613 3614 // "Call" ctor using createInstanceWithArgumentsAndContext 3615 Reference < XComponentContext > xContext( 3616 xFirstParamContext.is() 3617 ? xFirstParamContext 3618 : comphelper::getProcessComponentContext() ); 3619 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() ); 3620 3621 Any aRetAny; 3622 OUString aServiceName = GetName(); 3623 Reference < XInterface > xRet; 3624 try 3625 { 3626 xRet = xServiceMgr->createInstanceWithArgumentsAndContext( aServiceName, args, xContext ); 3627 } 3628 catch( const Exception& ) 3629 { 3630 implHandleAnyException( ::cppu::getCaughtException() ); 3631 } 3632 aRetAny <<= xRet; 3633 unoToSbxValue( pVar, aRetAny ); 3634 3635 // Copy back out parameters? 3636 if( bOutParams ) 3637 { 3638 const Any* pAnyArgs = args.getConstArray(); 3639 3640 for( sal_uInt32 j = 0 ; j < nUnoParamCount ; j++ ) 3641 { 3642 Reference< XParameter > xParam = pParameterSeq[j]; 3643 if( !xParam.is() ) 3644 continue; 3645 3646 if( xParam->isOut() ) 3647 unoToSbxValue( pParams->Get( static_cast<sal_uInt16>(j+1) ), pAnyArgs[ j ] ); 3648 } 3649 } 3650 } 3651 } 3652 else 3653 SbxObject::Notify( rBC, rHint ); 3654 } 3655 } 3656 3657 3658 SbUnoServiceCtor::SbUnoServiceCtor( const OUString& aName_, Reference< XServiceConstructorDescription > const & xServiceCtorDesc ) 3659 : SbxMethod( aName_, SbxOBJECT ) 3660 , m_xServiceCtorDesc( xServiceCtorDesc ) 3661 { 3662 } 3663 3664 SbUnoServiceCtor::~SbUnoServiceCtor() 3665 { 3666 } 3667 3668 SbxInfo* SbUnoServiceCtor::GetInfo() 3669 { 3670 SbxInfo* pRet = nullptr; 3671 3672 return pRet; 3673 } 3674 3675 3676 SbUnoSingleton* findUnoSingleton( const OUString& rName ) 3677 { 3678 SbUnoSingleton* pSbUnoSingleton = nullptr; 3679 3680 const Reference< XHierarchicalNameAccess >& xTypeAccess = getTypeProvider_Impl(); 3681 if( xTypeAccess->hasByHierarchicalName( rName ) ) 3682 { 3683 Any aRet = xTypeAccess->getByHierarchicalName( rName ); 3684 Reference< XTypeDescription > xTypeDesc; 3685 aRet >>= xTypeDesc; 3686 3687 if( xTypeDesc.is() ) 3688 { 3689 TypeClass eTypeClass = xTypeDesc->getTypeClass(); 3690 if( eTypeClass == TypeClass_SINGLETON ) 3691 { 3692 Reference< XSingletonTypeDescription > xSingletonTypeDesc( xTypeDesc, UNO_QUERY ); 3693 if( xSingletonTypeDesc.is() ) 3694 pSbUnoSingleton = new SbUnoSingleton( rName ); 3695 } 3696 } 3697 } 3698 return pSbUnoSingleton; 3699 } 3700 3701 SbUnoSingleton::SbUnoSingleton( const OUString& aName_ ) 3702 : SbxObject( aName_ ) 3703 { 3704 SbxVariableRef xGetMethodRef = new SbxMethod( "get", SbxOBJECT ); 3705 QuickInsert( xGetMethodRef.get() ); 3706 } 3707 3708 void SbUnoSingleton::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 3709 { 3710 const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint); 3711 if( pHint ) 3712 { 3713 SbxVariable* pVar = pHint->GetVar(); 3714 SbxArray* pParams = pVar->GetParameters(); 3715 sal_uInt32 nParamCount = pParams ? (static_cast<sal_uInt32>(pParams->Count()) - 1) : 0; 3716 sal_uInt32 nAllowedParamCount = 1; 3717 3718 Reference < XComponentContext > xContextToUse; 3719 if( nParamCount > 0 ) 3720 { 3721 // Check if first parameter is a context and use it then 3722 Reference < XComponentContext > xFirstParamContext; 3723 Any aArg1 = sbxToUnoValue( pParams->Get( 1 ) ); 3724 if( (aArg1 >>= xFirstParamContext) && xFirstParamContext.is() ) 3725 xContextToUse = xFirstParamContext; 3726 } 3727 3728 if( !xContextToUse.is() ) 3729 { 3730 xContextToUse = comphelper::getProcessComponentContext(); 3731 --nAllowedParamCount; 3732 } 3733 3734 if( nParamCount > nAllowedParamCount ) 3735 { 3736 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); 3737 return; 3738 } 3739 3740 Any aRetAny; 3741 if( xContextToUse.is() ) 3742 { 3743 OUString aSingletonName = "/singletons/" 3744 + GetName(); 3745 Reference < XInterface > xRet; 3746 xContextToUse->getValueByName( aSingletonName ) >>= xRet; 3747 aRetAny <<= xRet; 3748 } 3749 unoToSbxValue( pVar, aRetAny ); 3750 } 3751 else 3752 { 3753 SbxObject::Notify( rBC, rHint ); 3754 } 3755 } 3756 3757 3758 // Implementation of an EventAttacher-drawn AllListener, which 3759 // solely transmits several events to a general AllListener 3760 class BasicAllListener_Impl : public WeakImplHelper< XAllListener > 3761 { 3762 void firing_impl(const AllEventObject& Event, Any* pRet); 3763 3764 public: 3765 SbxObjectRef xSbxObj; 3766 OUString aPrefixName; 3767 3768 explicit BasicAllListener_Impl( const OUString& aPrefixName ); 3769 3770 // Methods of XAllListener 3771 virtual void SAL_CALL firing(const AllEventObject& Event) override; 3772 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) override; 3773 3774 // Methods of XEventListener 3775 virtual void SAL_CALL disposing(const EventObject& Source) override; 3776 }; 3777 3778 3779 BasicAllListener_Impl::BasicAllListener_Impl(const OUString& aPrefixName_) 3780 : aPrefixName( aPrefixName_ ) 3781 { 3782 } 3783 3784 void BasicAllListener_Impl::firing_impl( const AllEventObject& Event, Any* pRet ) 3785 { 3786 SolarMutexGuard guard; 3787 3788 if( xSbxObj.is() ) 3789 { 3790 OUString aMethodName = aPrefixName + Event.MethodName; 3791 3792 SbxVariable * pP = xSbxObj.get(); 3793 while( pP->GetParent() ) 3794 { 3795 pP = pP->GetParent(); 3796 StarBASIC * pLib = dynamic_cast<StarBASIC*>( pP ); 3797 if( pLib ) 3798 { 3799 // Create in a Basic Array 3800 SbxArrayRef xSbxArray = new SbxArray( SbxVARIANT ); 3801 const Any * pArgs = Event.Arguments.getConstArray(); 3802 sal_Int32 nCount = Event.Arguments.getLength(); 3803 for( sal_Int32 i = 0; i < nCount; i++ ) 3804 { 3805 // Convert elements 3806 SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); 3807 unoToSbxValue( xVar.get(), pArgs[i] ); 3808 xSbxArray->Put( xVar.get(), sal::static_int_cast< sal_uInt16 >(i+1) ); 3809 } 3810 3811 pLib->Call( aMethodName, xSbxArray.get() ); 3812 3813 // get the return value from the Param-Array, if requested 3814 if( pRet ) 3815 { 3816 SbxVariable* pVar = xSbxArray->Get( 0 ); 3817 if( pVar ) 3818 { 3819 // #95792 Avoid a second call 3820 SbxFlagBits nFlags = pVar->GetFlags(); 3821 pVar->SetFlag( SbxFlagBits::NoBroadcast ); 3822 *pRet = sbxToUnoValueImpl( pVar ); 3823 pVar->SetFlags( nFlags ); 3824 } 3825 } 3826 break; 3827 } 3828 } 3829 } 3830 } 3831 3832 3833 // Methods of Listener 3834 void BasicAllListener_Impl::firing( const AllEventObject& Event ) 3835 { 3836 firing_impl( Event, nullptr ); 3837 } 3838 3839 Any BasicAllListener_Impl::approveFiring( const AllEventObject& Event ) 3840 { 3841 Any aRetAny; 3842 firing_impl( Event, &aRetAny ); 3843 return aRetAny; 3844 } 3845 3846 3847 // Methods of XEventListener 3848 void BasicAllListener_Impl ::disposing(const EventObject& ) 3849 { 3850 SolarMutexGuard guard; 3851 3852 xSbxObj.clear(); 3853 } 3854 3855 3856 // class InvocationToAllListenerMapper 3857 // helper class to map XInvocation to XAllListener (also in project eventattacher!) 3858 3859 class InvocationToAllListenerMapper : public WeakImplHelper< XInvocation > 3860 { 3861 public: 3862 InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType, 3863 const Reference< XAllListener >& AllListener, const Any& Helper ); 3864 3865 // XInvocation 3866 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() override; 3867 virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) override; 3868 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) override; 3869 virtual Any SAL_CALL getValue(const OUString& PropertyName) override; 3870 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) override; 3871 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) override; 3872 3873 private: 3874 Reference< XAllListener > m_xAllListener; 3875 Reference< XIdlClass > m_xListenerType; 3876 Any m_Helper; 3877 }; 3878 3879 3880 // Function to replace AllListenerAdapterService::createAllListerAdapter 3881 static Reference< XInterface > createAllListenerAdapter 3882 ( 3883 const Reference< XInvocationAdapterFactory2 >& xInvocationAdapterFactory, 3884 const Reference< XIdlClass >& xListenerType, 3885 const Reference< XAllListener >& xListener, 3886 const Any& Helper 3887 ) 3888 { 3889 Reference< XInterface > xAdapter; 3890 if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() ) 3891 { 3892 Reference< XInvocation > xInvocationToAllListenerMapper = 3893 new InvocationToAllListenerMapper(xListenerType, xListener, Helper); 3894 Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName() ); 3895 Sequence<Type> arg2(1); 3896 arg2[0] = aListenerType; 3897 xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, arg2 ); 3898 } 3899 return xAdapter; 3900 } 3901 3902 3903 // InvocationToAllListenerMapper 3904 InvocationToAllListenerMapper::InvocationToAllListenerMapper 3905 ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper ) 3906 : m_xAllListener( AllListener ) 3907 , m_xListenerType( ListenerType ) 3908 , m_Helper( Helper ) 3909 { 3910 } 3911 3912 3913 Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection() 3914 { 3915 return Reference< XIntrospectionAccess >(); 3916 } 3917 3918 3919 Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params, 3920 Sequence< sal_Int16 >&, Sequence< Any >&) 3921 { 3922 Any aRet; 3923 3924 // Check if to firing or approveFiring has to be called 3925 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName ); 3926 bool bApproveFiring = false; 3927 if( !xMethod.is() ) 3928 return aRet; 3929 Reference< XIdlClass > xReturnType = xMethod->getReturnType(); 3930 Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes(); 3931 if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) || 3932 aExceptionSeq.getLength() > 0 ) 3933 { 3934 bApproveFiring = true; 3935 } 3936 else 3937 { 3938 Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos(); 3939 sal_uInt32 nParamCount = aParamSeq.getLength(); 3940 if( nParamCount > 1 ) 3941 { 3942 const ParamInfo* pInfo = aParamSeq.getConstArray(); 3943 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ ) 3944 { 3945 if( pInfo[ i ].aMode != ParamMode_IN ) 3946 { 3947 bApproveFiring = true; 3948 break; 3949 } 3950 } 3951 } 3952 } 3953 3954 AllEventObject aAllEvent; 3955 aAllEvent.Source = static_cast<OWeakObject*>(this); 3956 aAllEvent.Helper = m_Helper; 3957 aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName() ); 3958 aAllEvent.MethodName = FunctionName; 3959 aAllEvent.Arguments = Params; 3960 if( bApproveFiring ) 3961 aRet = m_xAllListener->approveFiring( aAllEvent ); 3962 else 3963 m_xAllListener->firing( aAllEvent ); 3964 return aRet; 3965 } 3966 3967 3968 void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString&, const Any&) 3969 {} 3970 3971 3972 Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString&) 3973 { 3974 return Any(); 3975 } 3976 3977 3978 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name) 3979 { 3980 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name ); 3981 return xMethod.is(); 3982 } 3983 3984 3985 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name) 3986 { 3987 Reference< XIdlField > xField = m_xListenerType->getField( Name ); 3988 return xField.is(); 3989 } 3990 3991 3992 // create Uno-Service 3993 // 1. Parameter == Prefix-Name of the macro 3994 // 2. Parameter == fully qualified name of the listener 3995 void SbRtl_CreateUnoListener(StarBASIC * pBasic, SbxArray & rPar, bool) 3996 { 3997 // We need 2 parameters 3998 if ( rPar.Count() != 3 ) 3999 { 4000 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); 4001 return; 4002 } 4003 4004 // get the name of the class of the struct 4005 OUString aPrefixName = rPar.Get(1)->GetOUString(); 4006 OUString aListenerClassName = rPar.Get(2)->GetOUString(); 4007 4008 // get the CoreReflection 4009 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); 4010 if( !xCoreReflection.is() ) 4011 return; 4012 4013 // get the AllListenerAdapterService 4014 Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() ); 4015 4016 // search the class 4017 Reference< XIdlClass > xClass = xCoreReflection->forName( aListenerClassName ); 4018 if( !xClass.is() ) 4019 return; 4020 4021 // From 1999-11-30: get the InvocationAdapterFactory 4022 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = 4023 InvocationAdapterFactory::create( xContext ); 4024 4025 BasicAllListener_Impl * p; 4026 Reference< XAllListener > xAllLst = p = new BasicAllListener_Impl( aPrefixName ); 4027 Any aTmp; 4028 Reference< XInterface > xLst = createAllListenerAdapter( xInvocationAdapterFactory, xClass, xAllLst, aTmp ); 4029 if( !xLst.is() ) 4030 return; 4031 4032 OUString aClassName = xClass->getName(); 4033 Type aClassType( xClass->getTypeClass(), aClassName ); 4034 aTmp = xLst->queryInterface( aClassType ); 4035 if( !aTmp.hasValue() ) 4036 return; 4037 4038 SbUnoObject* pUnoObj = new SbUnoObject( aListenerClassName, aTmp ); 4039 p->xSbxObj = pUnoObj; 4040 p->xSbxObj->SetParent( pBasic ); 4041 4042 // #100326 Register listener object to set Parent NULL in Dtor 4043 SbxArrayRef xBasicUnoListeners = pBasic->getUnoListeners(); 4044 xBasicUnoListeners->Insert( pUnoObj, xBasicUnoListeners->Count() ); 4045 4046 // return the object 4047 SbxVariableRef refVar = rPar.Get(0); 4048 refVar->PutObject( p->xSbxObj.get() ); 4049 } 4050 4051 4052 // Represents the DefaultContext property of the ProcessServiceManager 4053 // in the Basic runtime system. 4054 void RTL_Impl_GetDefaultContext( SbxArray& rPar ) 4055 { 4056 SbxVariableRef refVar = rPar.Get(0); 4057 4058 Any aContextAny( comphelper::getProcessComponentContext() ); 4059 4060 SbUnoObjectRef xUnoObj = new SbUnoObject( "DefaultContext", aContextAny ); 4061 refVar->PutObject( xUnoObj.get() ); 4062 } 4063 4064 4065 // Creates a Basic wrapper object for a strongly typed Uno value 4066 // 1. parameter: Uno type as full qualified type name, e.g. "byte[]" 4067 void RTL_Impl_CreateUnoValue( SbxArray& rPar ) 4068 { 4069 // 2 parameters needed 4070 if ( rPar.Count() != 3 ) 4071 { 4072 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); 4073 return; 4074 } 4075 4076 // get the name of the class of the struct 4077 OUString aTypeName = rPar.Get(1)->GetOUString(); 4078 SbxVariable* pVal = rPar.Get(2); 4079 4080 if( aTypeName == "type" ) 4081 { 4082 SbxDataType eBaseType = pVal->SbxValue::GetType(); 4083 OUString aValTypeName; 4084 if( eBaseType == SbxSTRING ) 4085 { 4086 aValTypeName = pVal->GetOUString(); 4087 } 4088 else if( eBaseType == SbxOBJECT ) 4089 { 4090 // XIdlClass? 4091 Reference< XIdlClass > xIdlClass; 4092 4093 SbxBaseRef pObj = pVal->GetObject(); 4094 if( auto obj = dynamic_cast<SbUnoObject*>( pObj.get() ) ) 4095 { 4096 Any aUnoAny = obj->getUnoAny(); 4097 aUnoAny >>= xIdlClass; 4098 } 4099 4100 if( xIdlClass.is() ) 4101 { 4102 aValTypeName = xIdlClass->getName(); 4103 } 4104 } 4105 Type aType; 4106 bool bSuccess = implGetTypeByName( aValTypeName, aType ); 4107 if( bSuccess ) 4108 { 4109 Any aTypeAny( aType ); 4110 SbxVariableRef refVar = rPar.Get(0); 4111 SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aTypeAny ); 4112 refVar->PutObject( xUnoAnyObject.get() ); 4113 } 4114 return; 4115 } 4116 4117 // Check the type 4118 const Reference< XHierarchicalNameAccess >& xTypeAccess = getTypeProvider_Impl(); 4119 Any aRet; 4120 try 4121 { 4122 aRet = xTypeAccess->getByHierarchicalName( aTypeName ); 4123 } 4124 catch( const NoSuchElementException& e1 ) 4125 { 4126 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, 4127 implGetExceptionMsg( e1, "com.sun.star.container.NoSuchElementException" ) ); 4128 return; 4129 } 4130 Reference< XTypeDescription > xTypeDesc; 4131 aRet >>= xTypeDesc; 4132 TypeClass eTypeClass = xTypeDesc->getTypeClass(); 4133 Type aDestType( eTypeClass, aTypeName ); 4134 4135 4136 // Preconvert value 4137 Any aVal = sbxToUnoValueImpl( pVal ); 4138 Any aConvertedVal = convertAny( aVal, aDestType ); 4139 4140 SbxVariableRef refVar = rPar.Get(0); 4141 SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aConvertedVal ); 4142 refVar->PutObject( xUnoAnyObject.get() ); 4143 } 4144 4145 4146 class ModuleInvocationProxy : public WeakImplHelper< XInvocation, XComponent > 4147 { 4148 ::osl::Mutex m_aMutex; 4149 OUString m_aPrefix; 4150 SbxObjectRef m_xScopeObj; 4151 bool m_bProxyIsClassModuleObject; 4152 4153 ::comphelper::OInterfaceContainerHelper2 m_aListeners; 4154 4155 public: 4156 ModuleInvocationProxy( OUString const & aPrefix, SbxObjectRef const & xScopeObj ); 4157 4158 // XInvocation 4159 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() override; 4160 virtual void SAL_CALL setValue( const OUString& rProperty, const Any& rValue ) override; 4161 virtual Any SAL_CALL getValue( const OUString& rProperty ) override; 4162 virtual sal_Bool SAL_CALL hasMethod( const OUString& rName ) override; 4163 virtual sal_Bool SAL_CALL hasProperty( const OUString& rProp ) override; 4164 4165 virtual Any SAL_CALL invoke( const OUString& rFunction, 4166 const Sequence< Any >& rParams, 4167 Sequence< sal_Int16 >& rOutParamIndex, 4168 Sequence< Any >& rOutParam ) override; 4169 4170 // XComponent 4171 virtual void SAL_CALL dispose() override; 4172 virtual void SAL_CALL addEventListener( const Reference< XEventListener >& xListener ) override; 4173 virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& aListener ) override; 4174 }; 4175 4176 ModuleInvocationProxy::ModuleInvocationProxy( OUString const & aPrefix, SbxObjectRef const & xScopeObj ) 4177 : m_aMutex() 4178 , m_aPrefix( aPrefix + "_" ) 4179 , m_xScopeObj( xScopeObj ) 4180 , m_aListeners( m_aMutex ) 4181 { 4182 m_bProxyIsClassModuleObject = xScopeObj.is() && dynamic_cast<const SbClassModuleObject*>( xScopeObj.get() ) != nullptr; 4183 } 4184 4185 Reference< XIntrospectionAccess > SAL_CALL ModuleInvocationProxy::getIntrospection() 4186 { 4187 return Reference< XIntrospectionAccess >(); 4188 } 4189 4190 void SAL_CALL ModuleInvocationProxy::setValue(const OUString& rProperty, const Any& rValue) 4191 { 4192 if( !m_bProxyIsClassModuleObject ) 4193 throw UnknownPropertyException(); 4194 4195 SolarMutexGuard guard; 4196 4197 OUString aPropertyFunctionName = "Property Set " 4198 + m_aPrefix 4199 + rProperty; 4200 4201 SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxClassType::Method ); 4202 SbMethod* pMeth = dynamic_cast<SbMethod*>( p ); 4203 if( pMeth == nullptr ) 4204 { 4205 // TODO: Check vba behavior concerning missing function 4206 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName ); 4207 throw UnknownPropertyException(); 4208 } 4209 4210 // Setup parameter 4211 SbxArrayRef xArray = new SbxArray; 4212 SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); 4213 unoToSbxValue( xVar.get(), rValue ); 4214 xArray->Put( xVar.get(), 1 ); 4215 4216 // Call property method 4217 SbxVariableRef xValue = new SbxVariable; 4218 pMeth->SetParameters( xArray.get() ); 4219 pMeth->Call( xValue.get() ); 4220 pMeth->SetParameters( nullptr ); 4221 4222 // TODO: OutParameter? 4223 4224 4225 } 4226 4227 Any SAL_CALL ModuleInvocationProxy::getValue(const OUString& rProperty) 4228 { 4229 if( !m_bProxyIsClassModuleObject ) 4230 { 4231 throw UnknownPropertyException(); 4232 } 4233 SolarMutexGuard guard; 4234 4235 OUString aPropertyFunctionName = "Property Get " 4236 + m_aPrefix 4237 + rProperty; 4238 4239 SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxClassType::Method ); 4240 SbMethod* pMeth = dynamic_cast<SbMethod*>( p ); 4241 if( pMeth == nullptr ) 4242 { 4243 // TODO: Check vba behavior concerning missing function 4244 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName ); 4245 throw UnknownPropertyException(); 4246 } 4247 4248 // Call method 4249 SbxVariableRef xValue = new SbxVariable; 4250 pMeth->Call( xValue.get() ); 4251 Any aRet = sbxToUnoValue( xValue.get() ); 4252 return aRet; 4253 } 4254 4255 sal_Bool SAL_CALL ModuleInvocationProxy::hasMethod( const OUString& ) 4256 { 4257 return false; 4258 } 4259 4260 sal_Bool SAL_CALL ModuleInvocationProxy::hasProperty( const OUString& ) 4261 { 4262 return false; 4263 } 4264 4265 Any SAL_CALL ModuleInvocationProxy::invoke( const OUString& rFunction, 4266 const Sequence< Any >& rParams, 4267 Sequence< sal_Int16 >&, 4268 Sequence< Any >& ) 4269 { 4270 SolarMutexGuard guard; 4271 4272 Any aRet; 4273 SbxObjectRef xScopeObj = m_xScopeObj; 4274 if( !xScopeObj.is() ) 4275 { 4276 return aRet; 4277 } 4278 OUString aFunctionName = m_aPrefix 4279 + rFunction; 4280 4281 bool bSetRescheduleBack = false; 4282 bool bOldReschedule = true; 4283 SbiInstance* pInst = GetSbData()->pInst; 4284 if( pInst && pInst->IsCompatibility() ) 4285 { 4286 bOldReschedule = pInst->IsReschedule(); 4287 if ( bOldReschedule ) 4288 { 4289 pInst->EnableReschedule( false ); 4290 bSetRescheduleBack = true; 4291 } 4292 } 4293 4294 SbxVariable* p = xScopeObj->Find( aFunctionName, SbxClassType::Method ); 4295 SbMethod* pMeth = dynamic_cast<SbMethod*>( p ); 4296 if( pMeth == nullptr ) 4297 { 4298 // TODO: Check vba behavior concerning missing function 4299 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName ); 4300 return aRet; 4301 } 4302 4303 // Setup parameters 4304 SbxArrayRef xArray; 4305 sal_Int32 nParamCount = rParams.getLength(); 4306 if( nParamCount ) 4307 { 4308 xArray = new SbxArray; 4309 const Any *pArgs = rParams.getConstArray(); 4310 for( sal_Int32 i = 0 ; i < nParamCount ; i++ ) 4311 { 4312 SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); 4313 unoToSbxValue( xVar.get(), pArgs[i] ); 4314 xArray->Put( xVar.get(), sal::static_int_cast< sal_uInt16 >(i+1) ); 4315 } 4316 } 4317 4318 // Call method 4319 SbxVariableRef xValue = new SbxVariable; 4320 if( xArray.is() ) 4321 pMeth->SetParameters( xArray.get() ); 4322 pMeth->Call( xValue.get() ); 4323 aRet = sbxToUnoValue( xValue.get() ); 4324 pMeth->SetParameters( nullptr ); 4325 4326 if( bSetRescheduleBack ) 4327 pInst->EnableReschedule( bOldReschedule ); 4328 4329 // TODO: OutParameter? 4330 4331 return aRet; 4332 } 4333 4334 void SAL_CALL ModuleInvocationProxy::dispose() 4335 { 4336 ::osl::MutexGuard aGuard( m_aMutex ); 4337 4338 EventObject aEvent( static_cast<XComponent*>(this) ); 4339 m_aListeners.disposeAndClear( aEvent ); 4340 4341 m_xScopeObj = nullptr; 4342 } 4343 4344 void SAL_CALL ModuleInvocationProxy::addEventListener( const Reference< XEventListener >& xListener ) 4345 { 4346 m_aListeners.addInterface( xListener ); 4347 } 4348 4349 void SAL_CALL ModuleInvocationProxy::removeEventListener( const Reference< XEventListener >& xListener ) 4350 { 4351 m_aListeners.removeInterface( xListener ); 4352 } 4353 4354 4355 Reference< XInterface > createComListener( const Any& aControlAny, const OUString& aVBAType, 4356 const OUString& aPrefix, const SbxObjectRef& xScopeObj ) 4357 { 4358 Reference< XInterface > xRet; 4359 4360 Reference< XComponentContext > xContext( 4361 comphelper::getProcessComponentContext() ); 4362 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() ); 4363 4364 Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPrefix, xScopeObj ); 4365 4366 Sequence<Any> args( 3 ); 4367 args[0] = aControlAny; 4368 args[1] <<= aVBAType; 4369 args[2] <<= xProxy; 4370 4371 try 4372 { 4373 xRet = xServiceMgr->createInstanceWithArgumentsAndContext( 4374 "com.sun.star.custom.UnoComListener", 4375 args, xContext ); 4376 } 4377 catch( const Exception& ) 4378 { 4379 implHandleAnyException( ::cppu::getCaughtException() ); 4380 } 4381 4382 return xRet; 4383 } 4384 4385 typedef std::vector< WeakReference< XComponent > > ComponentRefVector; 4386 4387 struct StarBasicDisposeItem 4388 { 4389 StarBASIC* m_pBasic; 4390 SbxArrayRef m_pRegisteredVariables; 4391 ComponentRefVector m_vComImplementsObjects; 4392 4393 explicit StarBasicDisposeItem( StarBASIC* pBasic ) 4394 : m_pBasic( pBasic ) 4395 , m_pRegisteredVariables(new SbxArray()) 4396 { 4397 } 4398 }; 4399 4400 typedef std::vector< StarBasicDisposeItem* > DisposeItemVector; 4401 4402 static DisposeItemVector GaDisposeItemVector; 4403 4404 static DisposeItemVector::iterator lcl_findItemForBasic( StarBASIC const * pBasic ) 4405 { 4406 return std::find_if(GaDisposeItemVector.begin(), GaDisposeItemVector.end(), 4407 [&pBasic](StarBasicDisposeItem* pItem) { return pItem->m_pBasic == pBasic; }); 4408 } 4409 4410 static StarBasicDisposeItem* lcl_getOrCreateItemForBasic( StarBASIC* pBasic ) 4411 { 4412 DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic ); 4413 StarBasicDisposeItem* pItem = (it != GaDisposeItemVector.end()) ? *it : nullptr; 4414 if( pItem == nullptr ) 4415 { 4416 pItem = new StarBasicDisposeItem( pBasic ); 4417 GaDisposeItemVector.push_back( pItem ); 4418 } 4419 return pItem; 4420 } 4421 4422 void registerComponentToBeDisposedForBasic 4423 ( const Reference< XComponent >& xComponent, StarBASIC* pBasic ) 4424 { 4425 StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic ); 4426 pItem->m_vComImplementsObjects.emplace_back(xComponent ); 4427 } 4428 4429 void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic ) 4430 { 4431 StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic ); 4432 SbxArray* pArray = pItem->m_pRegisteredVariables.get(); 4433 pArray->Put( pVar, pArray->Count() ); 4434 } 4435 4436 void disposeComVariablesForBasic( StarBASIC const * pBasic ) 4437 { 4438 DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic ); 4439 if( it != GaDisposeItemVector.end() ) 4440 { 4441 StarBasicDisposeItem* pItem = *it; 4442 4443 SbxArray* pArray = pItem->m_pRegisteredVariables.get(); 4444 sal_uInt16 nCount = pArray->Count(); 4445 for( sal_uInt16 i = 0 ; i < nCount ; ++i ) 4446 { 4447 SbxVariable* pVar = pArray->Get( i ); 4448 pVar->ClearComListener(); 4449 } 4450 4451 ComponentRefVector& rv = pItem->m_vComImplementsObjects; 4452 for (auto const& elem : rv) 4453 { 4454 Reference< XComponent > xComponent( elem.get(), UNO_QUERY ); 4455 if (xComponent.is()) 4456 xComponent->dispose(); 4457 } 4458 4459 delete pItem; 4460 GaDisposeItemVector.erase( it ); 4461 } 4462 } 4463 4464 4465 // Handle module implements mechanism for OLE types 4466 bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pProxyClassModuleObject ) 4467 { 4468 // For now: Take first interface that allows to instantiate COM wrapper 4469 // TODO: Check if support for multiple interfaces is needed 4470 4471 Reference< XComponentContext > xContext( 4472 comphelper::getProcessComponentContext() ); 4473 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() ); 4474 Reference< XSingleServiceFactory > xComImplementsFactory 4475 ( 4476 xServiceMgr->createInstanceWithContext( "com.sun.star.custom.ComImplementsFactory", xContext ), 4477 UNO_QUERY 4478 ); 4479 if( !xComImplementsFactory.is() ) 4480 return false; 4481 4482 bool bSuccess = false; 4483 4484 SbxArray* pModIfaces = pClassData->mxIfaces.get(); 4485 sal_uInt16 nCount = pModIfaces->Count(); 4486 for( sal_uInt16 i = 0 ; i < nCount ; ++i ) 4487 { 4488 SbxVariable* pVar = pModIfaces->Get( i ); 4489 const OUString& aIfaceName = pVar->GetName(); 4490 4491 if( !aIfaceName.isEmpty() ) 4492 { 4493 OUString aPureIfaceName = aIfaceName; 4494 sal_Int32 indexLastDot = aIfaceName.lastIndexOf('.'); 4495 if ( indexLastDot > -1 ) 4496 { 4497 aPureIfaceName = aIfaceName.copy( indexLastDot + 1 ); 4498 } 4499 Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPureIfaceName, pProxyClassModuleObject ); 4500 4501 Sequence<Any> args( 2 ); 4502 args[0] <<= aIfaceName; 4503 args[1] <<= xProxy; 4504 4505 Reference< XInterface > xRet; 4506 try 4507 { 4508 xRet = xComImplementsFactory->createInstanceWithArguments( args ); 4509 bSuccess = true; 4510 } 4511 catch( const Exception& ) 4512 { 4513 implHandleAnyException( ::cppu::getCaughtException() ); 4514 } 4515 4516 if( bSuccess ) 4517 { 4518 Reference< XComponent > xComponent( xProxy, UNO_QUERY ); 4519 if( xComponent.is() ) 4520 { 4521 StarBASIC* pParentBasic = nullptr; 4522 SbxObject* pCurObject = this; 4523 do 4524 { 4525 SbxObject* pObjParent = pCurObject->GetParent(); 4526 pParentBasic = dynamic_cast<StarBASIC*>( pObjParent ); 4527 pCurObject = pObjParent; 4528 } 4529 while( pParentBasic == nullptr && pCurObject != nullptr ); 4530 4531 OSL_ASSERT( pParentBasic != nullptr ); 4532 registerComponentToBeDisposedForBasic( xComponent, pParentBasic ); 4533 } 4534 4535 o_rRetAny <<= xRet; 4536 break; 4537 } 4538 } 4539 } 4540 4541 return bSuccess; 4542 } 4543 4544 4545 // Due to an incorrect behavior IE returns an object instead of a string 4546 // in some scenarios. Calling toString at the object may correct this. 4547 // Helper function used in sbxvalue.cxx 4548 bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal ) 4549 { 4550 bool bSuccess = false; 4551 4552 if( auto pUnoObj = dynamic_cast<SbUnoObject*>( pObj) ) 4553 { 4554 // Only for native COM objects 4555 if( pUnoObj->isNativeCOMObject() ) 4556 { 4557 SbxVariableRef pMeth = pObj->Find( "toString", SbxClassType::Method ); 4558 if ( pMeth.is() ) 4559 { 4560 SbxValues aRes; 4561 pMeth->Get( aRes ); 4562 pVal->Put( aRes ); 4563 bSuccess = true; 4564 } 4565 } 4566 } 4567 return bSuccess; 4568 } 4569 4570 Any StructRefInfo::getValue() 4571 { 4572 Any aRet; 4573 uno_any_destruct( 4574 &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); 4575 typelib_TypeDescription * pTD = nullptr; 4576 maType.getDescription(&pTD); 4577 uno_any_construct( 4578 &aRet, getInst(), pTD, 4579 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); 4580 typelib_typedescription_release(pTD); 4581 return aRet; 4582 } 4583 4584 void StructRefInfo::setValue( const Any& rValue ) 4585 { 4586 bool bSuccess = uno_type_assignData( getInst(), 4587 maType.getTypeLibType(), 4588 const_cast<void*>(rValue.getValue()), 4589 rValue.getValueTypeRef(), 4590 reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface), 4591 reinterpret_cast< uno_AcquireFunc >(cpp_acquire), 4592 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); 4593 OSL_ENSURE(bSuccess, 4594 "StructRefInfo::setValue: ooops .... the value could not be assigned!"); 4595 } 4596 4597 OUString StructRefInfo::getTypeName() const 4598 { 4599 return maType.getTypeName(); 4600 } 4601 4602 void* StructRefInfo::getInst() 4603 { 4604 return const_cast<char *>(static_cast<char const *>(maAny.getValue()) + mnPos); 4605 } 4606 4607 TypeClass StructRefInfo::getTypeClass() const 4608 { 4609 return maType.getTypeClass(); 4610 } 4611 4612 SbUnoStructRefObject::SbUnoStructRefObject( const OUString& aName_, const StructRefInfo& rMemberInfo ) : SbxObject( aName_ ), maMemberInfo( rMemberInfo ), mbMemberCacheInit( false ) 4613 { 4614 SetClassName( maMemberInfo.getTypeName() ); 4615 } 4616 4617 SbUnoStructRefObject::~SbUnoStructRefObject() 4618 { 4619 } 4620 4621 void SbUnoStructRefObject::initMemberCache() 4622 { 4623 if ( mbMemberCacheInit ) 4624 return; 4625 typelib_TypeDescription * pTD = nullptr; 4626 maMemberInfo.getType().getDescription(&pTD); 4627 typelib_CompoundTypeDescription * pCompTypeDescr = reinterpret_cast<typelib_CompoundTypeDescription *>(pTD); 4628 for ( pCompTypeDescr = reinterpret_cast<typelib_CompoundTypeDescription *>(pTD); pCompTypeDescr; 4629 pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) 4630 { 4631 typelib_TypeDescriptionReference ** ppTypeRefs = pCompTypeDescr->ppTypeRefs; 4632 rtl_uString ** ppNames = pCompTypeDescr->ppMemberNames; 4633 sal_Int32 * pMemberOffsets = pCompTypeDescr->pMemberOffsets; 4634 for ( sal_Int32 nPos = pCompTypeDescr->nMembers; nPos--; ) 4635 { 4636 OUString aName( ppNames[nPos] ); 4637 maFields[ aName ] = std::make_unique<StructRefInfo>( maMemberInfo.getRootAnyRef(), ppTypeRefs[nPos], maMemberInfo.getPos() + pMemberOffsets[nPos] ); 4638 } 4639 } 4640 typelib_typedescription_release(pTD); 4641 mbMemberCacheInit = true; 4642 } 4643 4644 SbxVariable* SbUnoStructRefObject::Find( const OUString& rName, SbxClassType t ) 4645 { 4646 SbxVariable* pRes = SbxObject::Find( rName, t ); 4647 if ( !pRes ) 4648 { 4649 if ( !mbMemberCacheInit ) 4650 initMemberCache(); 4651 StructFieldInfo::iterator it = maFields.find( rName ); 4652 if ( it != maFields.end() ) 4653 { 4654 SbxDataType eSbxType; 4655 eSbxType = unoToSbxType( it->second->getTypeClass() ); 4656 SbxDataType eRealSbxType = eSbxType; 4657 Property aProp; 4658 aProp.Name = rName; 4659 aProp.Type = css::uno::Type( it->second->getTypeClass(), it->second->getTypeName() ); 4660 SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == css::uno::TypeClass_STRUCT) ); 4661 SbxVariableRef xVarRef = pProp; 4662 QuickInsert( xVarRef.get() ); 4663 pRes = xVarRef.get(); 4664 } 4665 } 4666 4667 if( !pRes ) 4668 { 4669 if( rName.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES) || 4670 rName.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES) || 4671 rName.equalsIgnoreAsciiCase(ID_DBG_METHODS) ) 4672 { 4673 // Create 4674 implCreateDbgProperties(); 4675 4676 // Now they have to be found regular 4677 pRes = SbxObject::Find( rName, SbxClassType::DontCare ); 4678 } 4679 } 4680 4681 return pRes; 4682 } 4683 4684 // help method to create the dbg_-Properties 4685 void SbUnoStructRefObject::implCreateDbgProperties() 4686 { 4687 Property aProp; 4688 4689 // Id == -1: display the implemented interfaces corresponding the ClassProvider 4690 SbxVariableRef xVarRef = new SbUnoProperty( ID_DBG_SUPPORTEDINTERFACES, SbxSTRING, SbxSTRING, aProp, -1, false, false ); 4691 QuickInsert( xVarRef.get() ); 4692 4693 // Id == -2: output the properties 4694 xVarRef = new SbUnoProperty( ID_DBG_PROPERTIES, SbxSTRING, SbxSTRING, aProp, -2, false, false ); 4695 QuickInsert( xVarRef.get() ); 4696 4697 // Id == -3: output the Methods 4698 xVarRef = new SbUnoProperty( ID_DBG_METHODS, SbxSTRING, SbxSTRING, aProp, -3, false, false ); 4699 QuickInsert( xVarRef.get() ); 4700 } 4701 4702 void SbUnoStructRefObject::implCreateAll() 4703 { 4704 // throw away all existing methods and properties 4705 pMethods = new SbxArray; 4706 pProps = new SbxArray; 4707 4708 if (!mbMemberCacheInit) 4709 initMemberCache(); 4710 4711 for (auto const& field : maFields) 4712 { 4713 const OUString& rName = field.first; 4714 SbxDataType eSbxType; 4715 eSbxType = unoToSbxType( field.second->getTypeClass() ); 4716 SbxDataType eRealSbxType = eSbxType; 4717 Property aProp; 4718 aProp.Name = rName; 4719 aProp.Type = css::uno::Type( field.second->getTypeClass(), field.second->getTypeName() ); 4720 SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == css::uno::TypeClass_STRUCT) ); 4721 SbxVariableRef xVarRef = pProp; 4722 QuickInsert( xVarRef.get() ); 4723 } 4724 4725 // Create Dbg_-Properties 4726 implCreateDbgProperties(); 4727 } 4728 4729 // output the value 4730 Any SbUnoStructRefObject::getUnoAny() 4731 { 4732 return maMemberInfo.getValue(); 4733 } 4734 4735 OUString SbUnoStructRefObject::Impl_DumpProperties() 4736 { 4737 OUStringBuffer aRet; 4738 aRet.append("Properties of object "); 4739 aRet.append( getDbgObjectName() ); 4740 4741 sal_uInt16 nPropCount = pProps->Count(); 4742 sal_uInt16 nPropsPerLine = 1 + nPropCount / 30; 4743 for( sal_uInt16 i = 0; i < nPropCount; i++ ) 4744 { 4745 SbxVariable* pVar = pProps->Get( i ); 4746 if( pVar ) 4747 { 4748 OUStringBuffer aPropStr; 4749 if( (i % nPropsPerLine) == 0 ) 4750 { 4751 aPropStr.append( "\n" ); 4752 } 4753 // output the type and name 4754 // Is it in Uno a sequence? 4755 SbxDataType eType = pVar->GetFullType(); 4756 4757 const OUString& aName( pVar->GetName() ); 4758 StructFieldInfo::iterator it = maFields.find( aName ); 4759 4760 if ( it != maFields.end() ) 4761 { 4762 const StructRefInfo& rPropInfo = *it->second; 4763 4764 if( eType == SbxOBJECT ) 4765 { 4766 if( rPropInfo.getTypeClass() == TypeClass_SEQUENCE ) 4767 { 4768 eType = SbxDataType( SbxOBJECT | SbxARRAY ); 4769 } 4770 } 4771 } 4772 aPropStr.append( Dbg_SbxDataType2String( eType ) ); 4773 4774 aPropStr.append( " " ); 4775 aPropStr.append( pVar->GetName() ); 4776 4777 if( i == nPropCount - 1 ) 4778 { 4779 aPropStr.append( "\n" ); 4780 } 4781 else 4782 { 4783 aPropStr.append( "; " ); 4784 } 4785 aRet.append( aPropStr.makeStringAndClear() ); 4786 } 4787 } 4788 return aRet.makeStringAndClear(); 4789 } 4790 4791 void SbUnoStructRefObject::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 4792 { 4793 if ( !mbMemberCacheInit ) 4794 initMemberCache(); 4795 const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint); 4796 if( pHint ) 4797 { 4798 SbxVariable* pVar = pHint->GetVar(); 4799 SbUnoProperty* pProp = dynamic_cast<SbUnoProperty*>( pVar ); 4800 if( pProp ) 4801 { 4802 StructFieldInfo::iterator it = maFields.find( pProp->GetName() ); 4803 // handle get/set of members of struct 4804 if( pHint->GetId() == SfxHintId::BasicDataWanted ) 4805 { 4806 // Test-Properties 4807 sal_Int32 nId = pProp->nId; 4808 if( nId < 0 ) 4809 { 4810 // Id == -1: Display implemented interfaces according the ClassProvider 4811 if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES" 4812 { 4813 OUString aRet = OUStringLiteral( ID_DBG_SUPPORTEDINTERFACES ) 4814 + " not available.\n(TypeClass is not TypeClass_INTERFACE)\n"; 4815 4816 pVar->PutString( aRet ); 4817 } 4818 // Id == -2: output properties 4819 else if( nId == -2 ) // Property ID_DBG_PROPERTIES 4820 { 4821 // by now all properties must be established 4822 implCreateAll(); 4823 OUString aRetStr = Impl_DumpProperties(); 4824 pVar->PutString( aRetStr ); 4825 } 4826 // Id == -3: output the methods 4827 else if( nId == -3 ) // Property ID_DBG_METHODS 4828 { 4829 // by now all properties must be established 4830 implCreateAll(); 4831 OUString aRet = "Methods of object " 4832 + getDbgObjectName() 4833 + "\nNo methods found\n"; 4834 pVar->PutString( aRet ); 4835 } 4836 return; 4837 } 4838 4839 if ( it != maFields.end() ) 4840 { 4841 Any aRetAny = it->second->getValue(); 4842 unoToSbxValue( pVar, aRetAny ); 4843 } 4844 else 4845 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND ); 4846 } 4847 else if( pHint->GetId() == SfxHintId::BasicDataChanged ) 4848 { 4849 if ( it != maFields.end() ) 4850 { 4851 // take over the value from Uno to Sbx 4852 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp ); 4853 it->second->setValue( aAnyValue ); 4854 } 4855 else 4856 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND ); 4857 } 4858 } 4859 else 4860 SbxObject::Notify( rBC, rHint ); 4861 } 4862 } 4863 4864 StructRefInfo SbUnoStructRefObject::getStructMember( const OUString& rMemberName ) 4865 { 4866 if (!mbMemberCacheInit) 4867 { 4868 initMemberCache(); 4869 } 4870 StructFieldInfo::iterator it = maFields.find( rMemberName ); 4871 4872 css::uno::Type aFoundType; 4873 sal_Int32 nFoundPos = -1; 4874 4875 if ( it != maFields.end() ) 4876 { 4877 aFoundType = it->second->getType(); 4878 nFoundPos = it->second->getPos(); 4879 } 4880 StructRefInfo aRet( maMemberInfo.getRootAnyRef(), aFoundType, nFoundPos ); 4881 return aRet; 4882 } 4883 4884 OUString SbUnoStructRefObject::getDbgObjectName() 4885 { 4886 OUString aName = GetClassName(); 4887 if( aName.isEmpty() ) 4888 { 4889 aName += "Unknown"; 4890 } 4891 OUStringBuffer aRet; 4892 if( aName.getLength() > 20 ) 4893 { 4894 aRet.append( "\n" ); 4895 } 4896 aRet.append( "\"" ); 4897 aRet.append( aName ); 4898 aRet.append( "\":" ); 4899 return aRet.makeStringAndClear(); 4900 } 4901 4902 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 4903
