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