xref: /AOO41X/main/basic/source/classes/sbunoobj.cxx (revision 0848378beb0d0fcd9a9bf3cafa6204dbc20d39f7)
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 <hash_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 accessable!?" );
196         }
197         if( !xCoreReflection.is() )
198         {
199             throw DeploymentException(
200                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection singleton not accessable") ),
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 accessable!?" );
239         }
240         if( !xAccess.is() )
241         {
242             throw DeploymentException(
243                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM
244                     ("/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessable") ),
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 accessable") ),
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         }
2401         else
2402             SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
2403     }
2404 }
2405 
2406 
2407 #ifdef INVOCATION_ONLY
2408 // Aus USR
2409 Reference< XInvocation > createDynamicInvocationFor( const Any& aAny );
2410 #endif
2411 
SbUnoObject(const String & aName_,const Any & aUnoObj_)2412 SbUnoObject::SbUnoObject( const String& aName_, const Any& aUnoObj_ )
2413     : SbxObject( aName_ )
2414     , bNeedIntrospection( sal_True )
2415     , bNativeCOMObject( sal_False )
2416 {
2417     static Reference< XIntrospection > xIntrospection;
2418 
2419     // Default-Properties von Sbx wieder rauspruegeln
2420     Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE );
2421     Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE );
2422 
2423     // Typ des Objekts pruefen
2424     TypeClass eType = aUnoObj_.getValueType().getTypeClass();
2425     Reference< XInterface > x;
2426     if( eType == TypeClass_INTERFACE )
2427     {
2428         // Interface aus dem Any besorgen
2429         x = *(Reference< XInterface >*)aUnoObj_.getValue();
2430         if( !x.is() )
2431             return;
2432     }
2433 
2434     Reference< XTypeProvider > xTypeProvider;
2435 #ifdef INVOCATION_ONLY
2436     // Invocation besorgen
2437     mxInvocation = createDynamicInvocationFor( aUnoObj_ );
2438 #else
2439     // Hat das Object selbst eine Invocation?
2440     mxInvocation = Reference< XInvocation >( x, UNO_QUERY );
2441 
2442     xTypeProvider = Reference< XTypeProvider >( x, UNO_QUERY );
2443 #endif
2444 
2445     if( mxInvocation.is() )
2446     {
2447         // #94670: This is WRONG because then the MaterialHolder doesn't refer
2448         // to the object implementing XInvocation but to the object passed to
2449         // the invocation service!!!
2450         // mxMaterialHolder = Reference< XMaterialHolder >::query( mxInvocation );
2451 
2452         // ExactName holen
2453         mxExactNameInvocation = Reference< XExactName >::query( mxInvocation );
2454 
2455         // Rest bezieht sich nur auf Introspection
2456         if( !xTypeProvider.is() )
2457         {
2458             bNeedIntrospection = sal_False;
2459             return;
2460         }
2461 
2462         // Ignore introspection based members for COM objects to avoid
2463         // hiding of equally named COM symbols, e.g. XInvocation::getValue
2464         Reference< oleautomation::XAutomationObject > xAutomationObject( aUnoObj_, UNO_QUERY );
2465         if( xAutomationObject.is() )
2466             bNativeCOMObject = sal_True;
2467     }
2468 
2469     maTmpUnoObj = aUnoObj_;
2470 
2471 
2472     //*** Namen bestimmen ***
2473     sal_Bool bFatalError = sal_True;
2474 
2475     // Ist es ein Interface oder eine struct?
2476     sal_Bool bSetClassName = sal_False;
2477     String aClassName_;
2478     if( eType == TypeClass_STRUCT || eType == TypeClass_EXCEPTION )
2479     {
2480         // Struct ist Ok
2481         bFatalError = sal_False;
2482 
2483         // #67173 Echten Klassen-Namen eintragen
2484         if( aName_.Len() == 0 )
2485         {
2486             aClassName_ = String( aUnoObj_.getValueType().getTypeName() );
2487             bSetClassName = sal_True;
2488         }
2489     }
2490     else if( eType == TypeClass_INTERFACE )
2491     {
2492         // #70197 Interface geht immer durch Typ im Any
2493         bFatalError = sal_False;
2494 
2495         // Nach XIdlClassProvider-Interface fragen
2496         Reference< XIdlClassProvider > xClassProvider( x, UNO_QUERY );
2497         if( xClassProvider.is() )
2498         {
2499             // #67173 Echten Klassen-Namen eintragen
2500             if( aName_.Len() == 0 )
2501             {
2502                 Sequence< Reference< XIdlClass > > szClasses = xClassProvider->getIdlClasses();
2503                 sal_uInt32 nLen = szClasses.getLength();
2504                 if( nLen )
2505                 {
2506                     const Reference< XIdlClass > xImplClass = szClasses.getConstArray()[ 0 ];
2507                     if( xImplClass.is() )
2508                     {
2509                         aClassName_ = String( xImplClass->getName() );
2510                         bSetClassName = sal_True;
2511                     }
2512                 }
2513             }
2514         }
2515     }
2516     if( bSetClassName )
2517         SetClassName( aClassName_ );
2518 
2519     // Weder Interface noch Struct -> FatalError
2520     if( bFatalError )
2521     {
2522         StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION );
2523         return;
2524     }
2525 
2526     // #67781 Introspection erst on demand durchfuehren
2527 }
2528 
~SbUnoObject()2529 SbUnoObject::~SbUnoObject()
2530 {
2531 }
2532 
2533 
2534 // #76470 Introspection on Demand durchfuehren
doIntrospection(void)2535 void SbUnoObject::doIntrospection( void )
2536 {
2537     static Reference< XIntrospection > xIntrospection;
2538 
2539     if( !bNeedIntrospection )
2540         return;
2541     bNeedIntrospection = sal_False;
2542 
2543     if( !xIntrospection.is() )
2544     {
2545         // Introspection-Service holen
2546         Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
2547         if ( xFactory.is() )
2548         {
2549             Reference< XInterface > xI = xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.beans.Introspection") );
2550             if (xI.is())
2551                 xIntrospection = Reference< XIntrospection >::query( xI );
2552                 //xI->queryInterface( ::getCppuType( (const Reference< XIntrospection > *)0 ), xIntrospection );
2553         }
2554     }
2555     if( !xIntrospection.is() )
2556     {
2557         StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION );
2558         return;
2559     }
2560 
2561     // Introspection durchfuehren
2562     try
2563     {
2564         mxUnoAccess = xIntrospection->inspect( maTmpUnoObj );
2565     }
2566     catch( RuntimeException& e )
2567     {
2568         StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2569     }
2570 
2571     if( !mxUnoAccess.is() )
2572     {
2573         // #51475 Ungueltiges Objekt kennzeichnen (kein mxMaterialHolder)
2574         return;
2575     }
2576 
2577     // MaterialHolder vom Access holen
2578     mxMaterialHolder = Reference< XMaterialHolder >::query( mxUnoAccess );
2579 
2580     // ExactName vom Access holen
2581     mxExactName = Reference< XExactName >::query( mxUnoAccess );
2582 }
2583 
2584 
2585 
2586 
2587 // #67781 Start einer Liste aller SbUnoMethod-Instanzen
2588 static SbUnoMethod* pFirst = NULL;
2589 
clearUnoMethodsForBasic(StarBASIC * pBasic)2590 void clearUnoMethodsForBasic( StarBASIC* pBasic )
2591 {
2592     SbUnoMethod* pMeth = pFirst;
2593     while( pMeth )
2594     {
2595         SbxObject* pObject = dynamic_cast< SbxObject* >( pMeth->GetParent() );
2596         if ( pObject )
2597         {
2598             StarBASIC* pModBasic = dynamic_cast< StarBASIC* >( pObject->GetParent() );
2599             if ( pModBasic == pBasic )
2600             {
2601                 // for now the solution is to remove the method from the list and to clear it,
2602                 // but in case the element should be correctly transfered to another StarBASIC,
2603                 // we should either set module parent to NULL without clearing it, or even
2604                 // set the new StarBASIC as the parent of the module
2605                 // pObject->SetParent( NULL );
2606 
2607                 if( pMeth == pFirst )
2608                     pFirst = pMeth->pNext;
2609                 else if( pMeth->pPrev )
2610                     pMeth->pPrev->pNext = pMeth->pNext;
2611                 if( pMeth->pNext )
2612                     pMeth->pNext->pPrev = pMeth->pPrev;
2613 
2614                 pMeth->pPrev = NULL;
2615                 pMeth->pNext = NULL;
2616 
2617                 pMeth->SbxValue::Clear();
2618                 pObject->SbxValue::Clear();
2619 
2620                 // start from the beginning after object clearing, the cycle will end since the method is removed each time
2621                 pMeth = pFirst;
2622             }
2623             else
2624                 pMeth = pMeth->pNext;
2625         }
2626         else
2627             pMeth = pMeth->pNext;
2628     }
2629 }
2630 
clearUnoMethods(void)2631 void clearUnoMethods( void )
2632 {
2633     SbUnoMethod* pMeth = pFirst;
2634     while( pMeth )
2635     {
2636         pMeth->SbxValue::Clear();
2637         pMeth = pMeth->pNext;
2638     }
2639 }
2640 
2641 
SbUnoMethod(const String & aName_,SbxDataType eSbxType,Reference<XIdlMethod> xUnoMethod_,bool bInvocation,bool bDirect)2642 SbUnoMethod::SbUnoMethod
2643 (
2644     const String& aName_,
2645     SbxDataType eSbxType,
2646     Reference< XIdlMethod > xUnoMethod_,
2647     bool bInvocation,
2648     bool bDirect
2649 )
2650     : SbxMethod( aName_, eSbxType )
2651     , mbInvocation( bInvocation )
2652     , mbDirectInvocation( bDirect )
2653 {
2654     m_xUnoMethod = xUnoMethod_;
2655     pParamInfoSeq = NULL;
2656 
2657     // #67781 Methode in Liste eintragen
2658     pNext = pFirst;
2659     pPrev = NULL;
2660     pFirst = this;
2661     if( pNext )
2662         pNext->pPrev = this;
2663 }
2664 
~SbUnoMethod()2665 SbUnoMethod::~SbUnoMethod()
2666 {
2667     delete pParamInfoSeq;
2668 
2669     if( this == pFirst )
2670         pFirst = pNext;
2671     else if( pPrev )
2672         pPrev->pNext = pNext;
2673     if( pNext )
2674         pNext->pPrev = pPrev;
2675 }
2676 
GetInfo()2677 SbxInfo* SbUnoMethod::GetInfo()
2678 {
2679     if( !pInfo && m_xUnoMethod.is() )
2680     {
2681         SbiInstance* pInst = pINST;
2682         if( pInst && pInst->IsCompatibility() )
2683         {
2684             pInfo = new SbxInfo();
2685 
2686             const Sequence<ParamInfo>& rInfoSeq = getParamInfos();
2687             const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2688             sal_uInt32 nParamCount = rInfoSeq.getLength();
2689 
2690             for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
2691             {
2692                 const ParamInfo& rInfo = pParamInfos[i];
2693                 ::rtl::OUString aParamName = rInfo.aName;
2694 
2695                 // const Reference< XIdlClass >& rxClass = rInfo.aType;
2696                 SbxDataType t = SbxVARIANT;
2697                 sal_uInt16 nFlags_ = SBX_READ;
2698                 pInfo->AddParam( aParamName, t, nFlags_ );
2699             }
2700         }
2701     }
2702     return pInfo;
2703 }
2704 
getParamInfos(void)2705 const Sequence<ParamInfo>& SbUnoMethod::getParamInfos( void )
2706 {
2707     if( !pParamInfoSeq && m_xUnoMethod.is() )
2708     {
2709         Sequence<ParamInfo> aTmp = m_xUnoMethod->getParameterInfos() ;
2710         pParamInfoSeq = new Sequence<ParamInfo>( aTmp );
2711     }
2712     return *pParamInfoSeq;
2713 }
2714 
SbUnoProperty(const String & aName_,SbxDataType eSbxType,const Property & aUnoProp_,sal_Int32 nId_,bool bInvocation)2715 SbUnoProperty::SbUnoProperty
2716 (
2717     const String& aName_,
2718     SbxDataType eSbxType,
2719     const Property& aUnoProp_,
2720     sal_Int32 nId_,
2721     bool bInvocation
2722 )
2723     : SbxProperty( aName_, eSbxType )
2724     , aUnoProp( aUnoProp_ )
2725     , nId( nId_ )
2726     , mbInvocation( bInvocation )
2727 {
2728     // #54548, bei bedarf Dummy-Array einsetzen, damit SbiRuntime::CheckArray() geht
2729     static SbxArrayRef xDummyArray = new SbxArray( SbxVARIANT );
2730     if( eSbxType & SbxARRAY )
2731         PutObject( xDummyArray );
2732 }
2733 
~SbUnoProperty()2734 SbUnoProperty::~SbUnoProperty()
2735 {}
2736 
2737 
Find(const String & rName,SbxClassType t)2738 SbxVariable* SbUnoObject::Find( const String& rName, SbxClassType t )
2739 {
2740     static Reference< XIdlMethod > xDummyMethod;
2741     static Property aDummyProp;
2742 
2743     SbxVariable* pRes = SbxObject::Find( rName, t );
2744 
2745     if( bNeedIntrospection )
2746         doIntrospection();
2747 
2748     // Neu 4.3.1999: Properties on Demand anlegen, daher jetzt perIntrospectionAccess
2749     // suchen, ob doch eine Property oder Methode des geforderten Namens existiert
2750     if( !pRes )
2751     {
2752         ::rtl::OUString aUName( rName );
2753         if( mxUnoAccess.is() && !bNativeCOMObject )
2754         {
2755             if( mxExactName.is() )
2756             {
2757                 ::rtl::OUString aUExactName = mxExactName->getExactName( aUName );
2758                 if( !aUExactName.isEmpty() )
2759                     aUName = aUExactName;
2760             }
2761             if( mxUnoAccess->hasProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ) )
2762             {
2763                 const Property& rProp = mxUnoAccess->
2764                     getProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS );
2765 
2766                 // #58455 Wenn die Property void sein kann, muss als Typ Variant gesetzt werden
2767                 SbxDataType eSbxType;
2768                 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
2769                     eSbxType = SbxVARIANT;
2770                 else
2771                     eSbxType = unoToSbxType( rProp.Type.getTypeClass() );
2772 
2773                 // Property anlegen und reinbraten
2774                 SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, rProp, 0, false );
2775                 QuickInsert( (SbxVariable*)xVarRef );
2776                 pRes = xVarRef;
2777             }
2778             else if( mxUnoAccess->hasMethod( aUName,
2779                 MethodConcept::ALL - MethodConcept::DANGEROUS ) )
2780             {
2781                 // Methode ansprechen
2782                 const Reference< XIdlMethod >& rxMethod = mxUnoAccess->
2783                     getMethod( aUName, MethodConcept::ALL - MethodConcept::DANGEROUS );
2784 
2785                 // SbUnoMethode anlegen und reinbraten
2786                 SbxVariableRef xMethRef = new SbUnoMethod( rxMethod->getName(),
2787                     unoToSbxType( rxMethod->getReturnType() ), rxMethod, false );
2788                 QuickInsert( (SbxVariable*)xMethRef );
2789                 pRes = xMethRef;
2790             }
2791 
2792             // Wenn immer noch nichts gefunden wurde, muss geprueft werden, ob NameAccess vorliegt
2793             if( !pRes )
2794             {
2795                 try
2796                 {
2797                     Reference< XNameAccess > xNameAccess( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY );
2798                     ::rtl::OUString aUName2( rName );
2799 
2800                     if( xNameAccess.is() && xNameAccess->hasByName( aUName2 ) )
2801                     {
2802                         Any aAny = xNameAccess->getByName( aUName2 );
2803 
2804                         // ACHTUNG: Die hier erzeugte Variable darf wegen bei XNameAccess
2805                         // nicht als feste Property in das Object aufgenommen werden und
2806                         // wird daher nirgendwo gehalten.
2807                         // Wenn das Probleme gibt, muss das kuenstlich gemacht werden oder
2808                         // es muss eine Klasse SbUnoNameAccessProperty geschaffen werden,
2809                         // bei der die Existenz staendig neu ueberprueft und die ggf. weg-
2810                         // geworfen wird, wenn der Name nicht mehr gefunden wird.
2811                         pRes = new SbxVariable( SbxVARIANT );
2812                         unoToSbxValue( pRes, aAny );
2813                     }
2814                 }
2815                 catch( NoSuchElementException& e )
2816                 {
2817                     StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2818                 }
2819                 catch( const Exception& )
2820                 {
2821                     // Anlegen, damit der Exception-Fehler nicht ueberschrieben wird
2822                     if( !pRes )
2823                         pRes = new SbxVariable( SbxVARIANT );
2824 
2825                     implHandleAnyException( ::cppu::getCaughtException() );
2826                 }
2827             }
2828         }
2829         if( !pRes && mxInvocation.is() )
2830         {
2831             if( mxExactNameInvocation.is() )
2832             {
2833                 ::rtl::OUString aUExactName = mxExactNameInvocation->getExactName( aUName );
2834                 if( !aUExactName.isEmpty() )
2835                     aUName = aUExactName;
2836             }
2837 
2838             try
2839             {
2840                 if( mxInvocation->hasProperty( aUName ) )
2841                 {
2842                     // Property anlegen und reinbraten
2843                     SbxVariableRef xVarRef = new SbUnoProperty( aUName, SbxVARIANT, aDummyProp, 0, true );
2844                     QuickInsert( (SbxVariable*)xVarRef );
2845                     pRes = xVarRef;
2846                 }
2847                 else if( mxInvocation->hasMethod( aUName ) )
2848                 {
2849                     // SbUnoMethode anlegen und reinbraten
2850                     SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true );
2851                     QuickInsert( (SbxVariable*)xMethRef );
2852                     pRes = xMethRef;
2853                 }
2854                 else
2855                 {
2856                     Reference< XDirectInvocation > xDirectInvoke( mxInvocation, UNO_QUERY );
2857                     if ( xDirectInvoke.is() && xDirectInvoke->hasMember( aUName ) )
2858                     {
2859                         SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true, true );
2860                         QuickInsert( (SbxVariable*)xMethRef );
2861                         pRes = xMethRef;
2862                     }
2863 
2864                 }
2865             }
2866             catch( RuntimeException& e )
2867             {
2868                 // Anlegen, damit der Exception-Fehler nicht ueberschrieben wird
2869                 if( !pRes )
2870                     pRes = new SbxVariable( SbxVARIANT );
2871 
2872                 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2873             }
2874         }
2875     }
2876 
2877     // Ganz am Schluss noch pruefen, ob die Dbg_-Properties gemeint sind
2878 
2879     if( !pRes )
2880     {
2881         if( rName.EqualsIgnoreCaseAscii( ID_DBG_SUPPORTEDINTERFACES ) ||
2882             rName.EqualsIgnoreCaseAscii( ID_DBG_PROPERTIES ) ||
2883             rName.EqualsIgnoreCaseAscii( ID_DBG_METHODS ) )
2884         {
2885             // Anlegen
2886             implCreateDbgProperties();
2887 
2888             // Jetzt muessen sie regulaer gefunden werden
2889             pRes = SbxObject::Find( rName, SbxCLASS_DONTCARE );
2890         }
2891     }
2892     return pRes;
2893 }
2894 
2895 
2896 // Hilfs-Methode zum Anlegen der dbg_-Properties
implCreateDbgProperties(void)2897 void SbUnoObject::implCreateDbgProperties( void )
2898 {
2899     Property aProp;
2900 
2901     // Id == -1: Implementierte Interfaces gemaess ClassProvider anzeigen
2902     SbxVariableRef xVarRef = new SbUnoProperty( String(RTL_CONSTASCII_USTRINGPARAM(ID_DBG_SUPPORTEDINTERFACES)), SbxSTRING, aProp, -1, false );
2903     QuickInsert( (SbxVariable*)xVarRef );
2904 
2905     // Id == -2: Properties ausgeben
2906     xVarRef = new SbUnoProperty( String(RTL_CONSTASCII_USTRINGPARAM(ID_DBG_PROPERTIES)), SbxSTRING, aProp, -2, false );
2907     QuickInsert( (SbxVariable*)xVarRef );
2908 
2909     // Id == -3: Methoden ausgeben
2910     xVarRef = new SbUnoProperty( String(RTL_CONSTASCII_USTRINGPARAM(ID_DBG_METHODS)), SbxSTRING, aProp, -3, false );
2911     QuickInsert( (SbxVariable*)xVarRef );
2912 }
2913 
implCreateAll(void)2914 void SbUnoObject::implCreateAll( void )
2915 {
2916     // Bestehende Methoden und Properties alle wieder wegwerfen
2917     pMethods   = new SbxArray;
2918     pProps     = new SbxArray;
2919 
2920     if( bNeedIntrospection ) doIntrospection();
2921 
2922     // Instrospection besorgen
2923     Reference< XIntrospectionAccess > xAccess = mxUnoAccess;
2924     if( !xAccess.is() || bNativeCOMObject )
2925     {
2926         if( mxInvocation.is() )
2927             xAccess = mxInvocation->getIntrospection();
2928         else if( bNativeCOMObject )
2929             return;
2930     }
2931     if( !xAccess.is() )
2932         return;
2933 
2934     // Properties anlegen
2935     Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
2936     sal_uInt32 nPropCount = props.getLength();
2937     const Property* pProps_ = props.getConstArray();
2938 
2939     sal_uInt32 i;
2940     for( i = 0 ; i < nPropCount ; i++ )
2941     {
2942         const Property& rProp = pProps_[ i ];
2943 
2944         // #58455 Wenn die Property void sein kann, muss als Typ Variant gesetzt werden
2945         SbxDataType eSbxType;
2946         if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
2947             eSbxType = SbxVARIANT;
2948         else
2949             eSbxType = unoToSbxType( rProp.Type.getTypeClass() );
2950 
2951         // Property anlegen und reinbraten
2952         SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, rProp, i, false );
2953         QuickInsert( (SbxVariable*)xVarRef );
2954     }
2955 
2956     // Dbg_-Properties anlegen
2957     implCreateDbgProperties();
2958 
2959     // Methoden anlegen
2960     Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods
2961         ( MethodConcept::ALL - MethodConcept::DANGEROUS );
2962     sal_uInt32 nMethCount = aMethodSeq.getLength();
2963     const Reference< XIdlMethod >* pMethods_ = aMethodSeq.getConstArray();
2964     for( i = 0 ; i < nMethCount ; i++ )
2965     {
2966         // Methode ansprechen
2967         const Reference< XIdlMethod >& rxMethod = pMethods_[i];
2968 
2969         // SbUnoMethode anlegen und reinbraten
2970         SbxVariableRef xMethRef = new SbUnoMethod
2971             ( rxMethod->getName(), unoToSbxType( rxMethod->getReturnType() ), rxMethod, false );
2972         QuickInsert( (SbxVariable*)xMethRef );
2973     }
2974 }
2975 
2976 
2977 // Wert rausgeben
getUnoAny(void)2978 Any SbUnoObject::getUnoAny( void )
2979 {
2980     Any aRetAny;
2981     if( bNeedIntrospection ) doIntrospection();
2982     if( mxMaterialHolder.is() )
2983         aRetAny = mxMaterialHolder->getMaterial();
2984     else if( mxInvocation.is() )
2985         aRetAny <<= mxInvocation;
2986     return aRetAny;
2987 }
2988 
2989 // Hilfsmethode zum Anlegen einer Uno-Struct per CoreReflection
Impl_CreateUnoStruct(const String & aClassName)2990 SbUnoObject* Impl_CreateUnoStruct( const String& aClassName )
2991 {
2992     // CoreReflection holen
2993     Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
2994     if( !xCoreReflection.is() )
2995         return NULL;
2996 
2997     // Klasse suchen
2998     Reference< XIdlClass > xClass;
2999     Reference< XHierarchicalNameAccess > xHarryName =
3000         getCoreReflection_HierarchicalNameAccess_Impl();
3001     if( xHarryName.is() && xHarryName->hasByHierarchicalName( aClassName ) )
3002         xClass = xCoreReflection->forName( aClassName );
3003     if( !xClass.is() )
3004         return NULL;
3005 
3006     // Ist es ueberhaupt ein struct?
3007     TypeClass eType = xClass->getTypeClass();
3008     if ( ( eType != TypeClass_STRUCT ) && ( eType != TypeClass_EXCEPTION ) )
3009         return NULL;
3010 
3011     // Instanz erzeugen
3012     Any aNewAny;
3013     xClass->createObject( aNewAny );
3014 
3015     // SbUnoObject daraus basteln
3016     SbUnoObject* pUnoObj = new SbUnoObject( aClassName, aNewAny );
3017     return pUnoObj;
3018 }
3019 
3020 
3021 // Factory-Klasse fuer das Anlegen von Uno-Structs per DIM AS NEW
Create(sal_uInt16,sal_uInt32)3022 SbxBase* SbUnoFactory::Create( sal_uInt16, sal_uInt32 )
3023 {
3024     // Ueber SbxId laeuft in Uno nix
3025     return NULL;
3026 }
3027 
CreateObject(const String & rClassName)3028 SbxObject* SbUnoFactory::CreateObject( const String& rClassName )
3029 {
3030     return Impl_CreateUnoStruct( rClassName );
3031 }
3032 
3033 
3034 // Provisorische Schnittstelle fuer UNO-Anbindung
3035 // Liefert ein SbxObject, das ein Uno-Interface wrappt
GetSbUnoObject(const String & aName,const Any & aUnoObj_)3036 SbxObjectRef GetSbUnoObject( const String& aName, const Any& aUnoObj_ )
3037 {
3038     return new SbUnoObject( aName, aUnoObj_ );
3039 }
3040 
3041 // Force creation of all properties for debugging
createAllObjectProperties(SbxObject * pObj)3042 void createAllObjectProperties( SbxObject* pObj )
3043 {
3044     if( !pObj )
3045         return;
3046 
3047     SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
3048     if( pUnoObj )
3049         pUnoObj->createAllProperties();
3050     else
3051         pObj->GetAll( SbxCLASS_DONTCARE );
3052 }
3053 
3054 
RTL_Impl_CreateUnoStruct(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3055 void RTL_Impl_CreateUnoStruct( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3056 {
3057     (void)pBasic;
3058     (void)bWrite;
3059 
3060     // Wir brauchen mindestens 1 Parameter
3061     if ( rPar.Count() < 2 )
3062     {
3063         StarBASIC::Error( SbERR_BAD_ARGUMENT );
3064         return;
3065     }
3066 
3067     // Klassen-Name der struct holen
3068     String aClassName = rPar.Get(1)->GetString();
3069 
3070     // Versuchen, gleichnamige Struct zu erzeugen
3071     SbUnoObjectRef xUnoObj = Impl_CreateUnoStruct( aClassName );
3072     if( !xUnoObj )
3073         return;
3074 
3075     // Objekt zurueckliefern
3076     SbxVariableRef refVar = rPar.Get(0);
3077     refVar->PutObject( (SbUnoObject*)xUnoObj );
3078 }
3079 
RTL_Impl_CreateUnoService(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3080 void RTL_Impl_CreateUnoService( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3081 {
3082     (void)pBasic;
3083     (void)bWrite;
3084 
3085     // Wir brauchen mindestens 1 Parameter
3086     if ( rPar.Count() < 2 )
3087     {
3088         StarBASIC::Error( SbERR_BAD_ARGUMENT );
3089         return;
3090     }
3091 
3092     // Klassen-Name der struct holen
3093     String aServiceName = rPar.Get(1)->GetString();
3094 
3095     // Service suchen und instanzieren
3096     Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3097     Reference< XInterface > xInterface;
3098     if ( xFactory.is() )
3099     {
3100         try
3101         {
3102             xInterface = xFactory->createInstance( aServiceName );
3103         }
3104         catch( const Exception& )
3105         {
3106             implHandleAnyException( ::cppu::getCaughtException() );
3107         }
3108     }
3109 
3110     SbxVariableRef refVar = rPar.Get(0);
3111     if( xInterface.is() )
3112     {
3113         Any aAny;
3114         aAny <<= xInterface;
3115 
3116         // SbUnoObject daraus basteln und zurueckliefern
3117         SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny );
3118         if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID )
3119         {
3120             // Objekt zurueckliefern
3121             refVar->PutObject( (SbUnoObject*)xUnoObj );
3122         }
3123         else
3124         {
3125             refVar->PutObject( NULL );
3126         }
3127     }
3128     else
3129     {
3130         refVar->PutObject( NULL );
3131     }
3132 }
3133 
RTL_Impl_CreateUnoServiceWithArguments(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3134 void RTL_Impl_CreateUnoServiceWithArguments( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3135 {
3136     (void)pBasic;
3137     (void)bWrite;
3138 
3139     // Wir brauchen mindestens 2 Parameter
3140     if ( rPar.Count() < 3 )
3141     {
3142         StarBASIC::Error( SbERR_BAD_ARGUMENT );
3143         return;
3144     }
3145 
3146     // Klassen-Name der struct holen
3147     String aServiceName = rPar.Get(1)->GetString();
3148     Any aArgAsAny = sbxToUnoValue( rPar.Get(2),
3149                 getCppuType( (Sequence<Any>*)0 ) );
3150     Sequence< Any > aArgs;
3151     aArgAsAny >>= aArgs;
3152 
3153     // Service suchen und instanzieren
3154     Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3155     Reference< XInterface > xInterface;
3156     if ( xFactory.is() )
3157     {
3158         try
3159         {
3160             xInterface = xFactory->createInstanceWithArguments( aServiceName, aArgs );
3161         }
3162         catch( const Exception& )
3163         {
3164             implHandleAnyException( ::cppu::getCaughtException() );
3165         }
3166     }
3167 
3168     SbxVariableRef refVar = rPar.Get(0);
3169     if( xInterface.is() )
3170     {
3171         Any aAny;
3172         aAny <<= xInterface;
3173 
3174         // SbUnoObject daraus basteln und zurueckliefern
3175         SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny );
3176         if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID )
3177         {
3178             // Objekt zurueckliefern
3179             refVar->PutObject( (SbUnoObject*)xUnoObj );
3180         }
3181         else
3182         {
3183             refVar->PutObject( NULL );
3184         }
3185     }
3186     else
3187     {
3188         refVar->PutObject( NULL );
3189     }
3190 }
3191 
RTL_Impl_GetProcessServiceManager(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3192 void RTL_Impl_GetProcessServiceManager( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3193 {
3194     (void)pBasic;
3195     (void)bWrite;
3196 
3197     SbxVariableRef refVar = rPar.Get(0);
3198 
3199     // Globalen Service-Manager holen
3200     Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3201     if( xFactory.is() )
3202     {
3203         Any aAny;
3204         aAny <<= xFactory;
3205 
3206         // SbUnoObject daraus basteln und zurueckliefern
3207         SbUnoObjectRef xUnoObj = new SbUnoObject( String( RTL_CONSTASCII_USTRINGPARAM("ProcessServiceManager") ), aAny );
3208         refVar->PutObject( (SbUnoObject*)xUnoObj );
3209     }
3210     else
3211     {
3212         refVar->PutObject( NULL );
3213     }
3214 }
3215 
RTL_Impl_HasInterfaces(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3216 void RTL_Impl_HasInterfaces( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3217 {
3218     (void)pBasic;
3219     (void)bWrite;
3220 
3221     // Wir brauchen mindestens 2 Parameter
3222     sal_uInt16 nParCount = rPar.Count();
3223     if( nParCount < 3 )
3224     {
3225         StarBASIC::Error( SbERR_BAD_ARGUMENT );
3226         return;
3227     }
3228 
3229     // Variable fuer Rueckgabewert
3230     SbxVariableRef refVar = rPar.Get(0);
3231     refVar->PutBool( sal_False );
3232 
3233     // Uno-Objekt holen
3234     SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject();
3235     if( !(pObj && pObj->ISA(SbUnoObject)) )
3236         return;
3237     Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
3238     TypeClass eType = aAny.getValueType().getTypeClass();
3239     if( eType != TypeClass_INTERFACE )
3240         return;
3241 
3242     // Interface aus dem Any besorgen
3243     Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue();
3244 
3245     // CoreReflection holen
3246     Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
3247     if( !xCoreReflection.is() )
3248         return;
3249 
3250     for( sal_uInt16 i = 2 ; i < nParCount ; i++ )
3251     {
3252         // Interface-Name der struct holen
3253         String aIfaceName = rPar.Get( i )->GetString();
3254 
3255         // Klasse suchen
3256         Reference< XIdlClass > xClass = xCoreReflection->forName( aIfaceName );
3257         if( !xClass.is() )
3258             return;
3259 
3260         // Pruefen, ob das Interface unterstuetzt wird
3261         ::rtl::OUString aClassName = xClass->getName();
3262         Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
3263         if( !x->queryInterface( aClassType ).hasValue() )
3264             return;
3265     }
3266 
3267     // Alles hat geklappt, dann sal_True liefern
3268     refVar->PutBool( sal_True );
3269 }
3270 
RTL_Impl_IsUnoStruct(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3271 void RTL_Impl_IsUnoStruct( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3272 {
3273     (void)pBasic;
3274     (void)bWrite;
3275 
3276     // Wir brauchen mindestens 1 Parameter
3277     if ( rPar.Count() < 2 )
3278     {
3279         StarBASIC::Error( SbERR_BAD_ARGUMENT );
3280         return;
3281     }
3282 
3283     // Variable fuer Rueckgabewert
3284     SbxVariableRef refVar = rPar.Get(0);
3285     refVar->PutBool( sal_False );
3286 
3287     // Uno-Objekt holen
3288     SbxVariableRef xParam = rPar.Get( 1 );
3289     if( !xParam->IsObject() )
3290         return;
3291     SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject();
3292     if( !(pObj && pObj->ISA(SbUnoObject)) )
3293         return;
3294     Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
3295     TypeClass eType = aAny.getValueType().getTypeClass();
3296     if( eType == TypeClass_STRUCT )
3297         refVar->PutBool( sal_True );
3298 }
3299 
3300 
RTL_Impl_EqualUnoObjects(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3301 void RTL_Impl_EqualUnoObjects( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3302 {
3303     (void)pBasic;
3304     (void)bWrite;
3305 
3306     if ( rPar.Count() < 3 )
3307     {
3308         StarBASIC::Error( SbERR_BAD_ARGUMENT );
3309         return;
3310     }
3311 
3312     // Variable fuer Rueckgabewert
3313     SbxVariableRef refVar = rPar.Get(0);
3314     refVar->PutBool( sal_False );
3315 
3316     // Uno-Objekte holen
3317     SbxVariableRef xParam1 = rPar.Get( 1 );
3318     if( !xParam1->IsObject() )
3319         return;
3320     SbxBaseRef pObj1 = (SbxBase*)xParam1->GetObject();
3321     if( !(pObj1 && pObj1->ISA(SbUnoObject)) )
3322         return;
3323     Any aAny1 = ((SbUnoObject*)(SbxBase*)pObj1)->getUnoAny();
3324     TypeClass eType1 = aAny1.getValueType().getTypeClass();
3325     if( eType1 != TypeClass_INTERFACE )
3326         return;
3327     Reference< XInterface > x1;
3328     aAny1 >>= x1;
3329     //XInterfaceRef x1 = *(XInterfaceRef*)aAny1.get();
3330 
3331     SbxVariableRef xParam2 = rPar.Get( 2 );
3332     if( !xParam2->IsObject() )
3333         return;
3334     SbxBaseRef pObj2 = (SbxBase*)xParam2->GetObject();
3335     if( !(pObj2 && pObj2->ISA(SbUnoObject)) )
3336         return;
3337     Any aAny2 = ((SbUnoObject*)(SbxBase*)pObj2)->getUnoAny();
3338     TypeClass eType2 = aAny2.getValueType().getTypeClass();
3339     if( eType2 != TypeClass_INTERFACE )
3340         return;
3341     Reference< XInterface > x2;
3342     aAny2 >>= x2;
3343     //XInterfaceRef x2 = *(XInterfaceRef*)aAny2.get();
3344 
3345     if( x1 == x2 )
3346         refVar->PutBool( sal_True );
3347 }
3348 
3349 typedef std::hash_map< ::rtl::OUString, std::vector< ::rtl::OUString >, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > ModuleHash;
3350 
3351 
3352 // helper wrapper function to interact with TypeProvider and
3353 // XTypeDescriptionEnumerationAccess.
3354 // if it fails for whatever reason
3355 // returned Reference<> be null e.g. .is() will be false
3356 
3357 Reference< XTypeDescriptionEnumeration >
getTypeDescriptorEnumeration(const::rtl::OUString & sSearchRoot,const Sequence<TypeClass> & types,TypeDescriptionSearchDepth depth)3358 getTypeDescriptorEnumeration( const ::rtl::OUString& sSearchRoot,
3359     const Sequence< TypeClass >& types, TypeDescriptionSearchDepth depth )
3360 {
3361     Reference< XTypeDescriptionEnumeration > xEnum;
3362     Reference< XTypeDescriptionEnumerationAccess> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY );
3363     if ( xTypeEnumAccess.is() )
3364     {
3365         try
3366         {
3367             xEnum = xTypeEnumAccess->createTypeDescriptionEnumeration(
3368                 sSearchRoot, types, depth );
3369         }
3370         catch( NoSuchTypeNameException& /*nstne*/ ) {}
3371         catch( InvalidTypeNameException& /*nstne*/ ) {}
3372     }
3373     return xEnum;
3374 }
3375 
3376 typedef std::hash_map< ::rtl::OUString, Any, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > VBAConstantsHash;
3377 
getVBAConstant(const String & rName)3378 SbxVariable* getVBAConstant( const String& rName )
3379 {
3380     SbxVariable* pConst = NULL;
3381     static VBAConstantsHash aConstCache;
3382     static bool isInited = false;
3383     if ( !isInited )
3384     {
3385         Sequence< TypeClass > types(1);
3386         types[ 0 ] = TypeClass_CONSTANTS;
3387         Reference< XTypeDescriptionEnumeration > xEnum = getTypeDescriptorEnumeration( defaultNameSpace, types, TypeDescriptionSearchDepth_INFINITE  );
3388 
3389         if ( !xEnum.is() )
3390             return NULL;
3391 
3392         while ( xEnum->hasMoreElements() )
3393         {
3394             Reference< XConstantsTypeDescription > xConstants( xEnum->nextElement(), UNO_QUERY );
3395             if ( xConstants.is() )
3396             {
3397                 Sequence< Reference< XConstantTypeDescription > > aConsts = xConstants->getConstants();
3398                 Reference< XConstantTypeDescription >* pSrc = aConsts.getArray();
3399                 sal_Int32 nLen = aConsts.getLength();
3400                 for ( sal_Int32 index =0;  index<nLen; ++pSrc, ++index )
3401                 {
3402                     Reference< XConstantTypeDescription >& rXConst =
3403                         *pSrc;
3404                     ::rtl::OUString sFullName = rXConst->getName();
3405                     sal_Int32 indexLastDot = sFullName.lastIndexOf('.');
3406                     ::rtl::OUString sLeafName;
3407                     if ( indexLastDot > -1 )
3408                         sLeafName = sFullName.copy( indexLastDot + 1);
3409                     aConstCache[ sLeafName.toAsciiLowerCase() ] = rXConst->getConstantValue();
3410                 }
3411             }
3412         }
3413         isInited = true;
3414     }
3415     ::rtl::OUString sKey( rName );
3416     VBAConstantsHash::const_iterator it = aConstCache.find( sKey.toAsciiLowerCase() );
3417     if ( it != aConstCache.end() )
3418     {
3419         pConst = new SbxVariable( SbxVARIANT );
3420         pConst->SetName( rName );
3421         unoToSbxValue( pConst, it->second );
3422     }
3423     return pConst;
3424 }
3425 
3426 // Funktion, um einen globalen Bezeichner im
3427 // UnoScope zu suchen und fuer Sbx zu wrappen
findUnoClass(const String & rName)3428 SbUnoClass* findUnoClass( const String& rName )
3429 {
3430     // #105550 Check if module exists
3431     SbUnoClass* pUnoClass = NULL;
3432 
3433     Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3434     if( xTypeAccess->hasByHierarchicalName( rName ) )
3435     {
3436         Any aRet = xTypeAccess->getByHierarchicalName( rName );
3437         Reference< XTypeDescription > xTypeDesc;
3438         aRet >>= xTypeDesc;
3439 
3440         if( xTypeDesc.is() )
3441         {
3442             TypeClass eTypeClass = xTypeDesc->getTypeClass();
3443             if( eTypeClass == TypeClass_MODULE || eTypeClass == TypeClass_CONSTANTS )
3444                 pUnoClass = new SbUnoClass( rName );
3445         }
3446     }
3447     return pUnoClass;
3448 }
3449 
Find(const XubString & rName,SbxClassType t)3450 SbxVariable* SbUnoClass::Find( const XubString& rName, SbxClassType t )
3451 {
3452     (void)t;
3453 
3454     SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_VARIABLE );
3455 
3456     // Wenn nichts gefunden wird, ist das Sub-Modul noch nicht bekannt
3457     if( !pRes )
3458     {
3459         // Wenn es schon eine Klasse ist, nach einen Feld fragen
3460         if( m_xClass.is() )
3461         {
3462             // Ist es ein Field
3463             ::rtl::OUString aUStr( rName );
3464             Reference< XIdlField > xField = m_xClass->getField( aUStr );
3465             Reference< XIdlClass > xClass;
3466             if( xField.is() )
3467             {
3468                 try
3469                 {
3470                     Any aAny;
3471                     aAny = xField->get( aAny );
3472 
3473                     // Nach Sbx wandeln
3474                     pRes = new SbxVariable( SbxVARIANT );
3475                     pRes->SetName( rName );
3476                     unoToSbxValue( pRes, aAny );
3477                 }
3478                 catch( const Exception& )
3479                 {
3480                     implHandleAnyException( ::cppu::getCaughtException() );
3481                 }
3482             }
3483         }
3484         else
3485         {
3486             // Vollqualifizierten Namen erweitern
3487             String aNewName = GetName();
3488             aNewName.AppendAscii( "." );
3489             aNewName += rName;
3490 
3491             // CoreReflection holen
3492             Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
3493             if( xCoreReflection.is() )
3494             {
3495                 // Ist es eine Konstante?
3496                 Reference< XHierarchicalNameAccess > xHarryName( xCoreReflection, UNO_QUERY );
3497                 if( xHarryName.is() )
3498                 {
3499                     try
3500                     {
3501                         Any aValue = xHarryName->getByHierarchicalName( aNewName );
3502                         TypeClass eType = aValue.getValueType().getTypeClass();
3503 
3504                         // Interface gefunden? Dann ist es eine Klasse
3505                         if( eType == TypeClass_INTERFACE )
3506                         {
3507                             Reference< XInterface > xIface = *(Reference< XInterface >*)aValue.getValue();
3508                             Reference< XIdlClass > xClass( xIface, UNO_QUERY );
3509                             if( xClass.is() )
3510                             {
3511                                 pRes = new SbxVariable( SbxVARIANT );
3512                                 SbxObjectRef xWrapper = (SbxObject*)new SbUnoClass( aNewName, xClass );
3513                                 pRes->PutObject( xWrapper );
3514                             }
3515                         }
3516                         else
3517                         {
3518                             pRes = new SbxVariable( SbxVARIANT );
3519                             unoToSbxValue( pRes, aValue );
3520                         }
3521                     }
3522                     catch( NoSuchElementException& e1 )
3523                     {
3524                         String aMsg = implGetExceptionMsg( e1 );
3525                     }
3526                 }
3527 
3528                 // Sonst wieder als Klasse annehmen
3529                 if( !pRes )
3530                 {
3531                     SbUnoClass* pNewClass = findUnoClass( aNewName );
3532                     if( pNewClass )
3533                     {
3534                         pRes = new SbxVariable( SbxVARIANT );
3535                         SbxObjectRef xWrapper = (SbxObject*)pNewClass;
3536                         pRes->PutObject( xWrapper );
3537                     }
3538                 }
3539 
3540                 // An UNO service?
3541                 if( !pRes )
3542                 {
3543                     SbUnoService* pUnoService = findUnoService( aNewName );
3544                     if( pUnoService )
3545                     {
3546                         pRes = new SbxVariable( SbxVARIANT );
3547                         SbxObjectRef xWrapper = (SbxObject*)pUnoService;
3548                         pRes->PutObject( xWrapper );
3549                     }
3550                 }
3551 
3552                 // An UNO singleton?
3553                 if( !pRes )
3554                 {
3555                     SbUnoSingleton* pUnoSingleton = findUnoSingleton( aNewName );
3556                     if( pUnoSingleton )
3557                     {
3558                         pRes = new SbxVariable( SbxVARIANT );
3559                         SbxObjectRef xWrapper = (SbxObject*)pUnoSingleton;
3560                         pRes->PutObject( xWrapper );
3561                     }
3562                 }
3563             }
3564         }
3565 
3566         if( pRes )
3567         {
3568             pRes->SetName( rName );
3569 
3570             // Variable einfuegen, damit sie spaeter im Find gefunden wird
3571             QuickInsert( pRes );
3572 
3573             // Uns selbst gleich wieder als Listener rausnehmen,
3574             // die Werte sind alle konstant
3575             if( pRes->IsBroadcaster() )
3576                 EndListening( pRes->GetBroadcaster(), sal_True );
3577         }
3578     }
3579     return pRes;
3580 }
3581 
3582 
findUnoService(const String & rName)3583 SbUnoService* findUnoService( const String& rName )
3584 {
3585     SbUnoService* pSbUnoService = NULL;
3586 
3587     Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3588     if( xTypeAccess->hasByHierarchicalName( rName ) )
3589     {
3590         Any aRet = xTypeAccess->getByHierarchicalName( rName );
3591         Reference< XTypeDescription > xTypeDesc;
3592         aRet >>= xTypeDesc;
3593 
3594         if( xTypeDesc.is() )
3595         {
3596             TypeClass eTypeClass = xTypeDesc->getTypeClass();
3597             if( eTypeClass == TypeClass_SERVICE )
3598             {
3599                 Reference< XServiceTypeDescription2 > xServiceTypeDesc( xTypeDesc, UNO_QUERY );
3600                 if( xServiceTypeDesc.is() )
3601                     pSbUnoService = new SbUnoService( rName, xServiceTypeDesc );
3602             }
3603         }
3604     }
3605     return pSbUnoService;
3606 }
3607 
Find(const String & rName,SbxClassType)3608 SbxVariable* SbUnoService::Find( const String& rName, SbxClassType )
3609 {
3610     SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_METHOD );
3611 
3612     if( !pRes )
3613     {
3614         // Wenn es schon eine Klasse ist, nach einen Feld fragen
3615         if( m_bNeedsInit && m_xServiceTypeDesc.is() )
3616         {
3617             m_bNeedsInit = false;
3618 
3619             Sequence< Reference< XServiceConstructorDescription > > aSCDSeq = m_xServiceTypeDesc->getConstructors();
3620             const Reference< XServiceConstructorDescription >* pCtorSeq = aSCDSeq.getConstArray();
3621             int nCtorCount = aSCDSeq.getLength();
3622             for( int i = 0 ; i < nCtorCount ; ++i )
3623             {
3624                 Reference< XServiceConstructorDescription > xCtor = pCtorSeq[i];
3625 
3626                 String aName( xCtor->getName() );
3627                 if( !aName.Len() )
3628                 {
3629                     if( xCtor->isDefaultConstructor() )
3630                         aName = String::CreateFromAscii( "create" );
3631                 }
3632 
3633                 if( aName.Len() )
3634                 {
3635                     // Create and insert SbUnoServiceCtor
3636                     SbxVariableRef xSbCtorRef = new SbUnoServiceCtor( aName, xCtor );
3637                     QuickInsert( (SbxVariable*)xSbCtorRef );
3638                 }
3639             }
3640 
3641             pRes = SbxObject::Find( rName, SbxCLASS_METHOD );
3642         }
3643     }
3644 
3645     return pRes;
3646 }
3647 
SFX_NOTIFY(SfxBroadcaster & rBC,const TypeId & rBCType,const SfxHint & rHint,const TypeId & rHintType)3648 void SbUnoService::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
3649                            const SfxHint& rHint, const TypeId& rHintType )
3650 {
3651     const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
3652     if( pHint )
3653     {
3654         SbxVariable* pVar = pHint->GetVar();
3655         SbxArray* pParams = pVar->GetParameters();
3656         SbUnoServiceCtor* pUnoCtor = PTR_CAST(SbUnoServiceCtor,pVar);
3657         if( pUnoCtor && pHint->GetId() == SBX_HINT_DATAWANTED )
3658         {
3659             // Parameter count -1 because of Param0 == this
3660             sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
3661             Sequence<Any> args;
3662             sal_Bool bOutParams = sal_False;
3663 
3664             Reference< XServiceConstructorDescription > xCtor = pUnoCtor->getServiceCtorDesc();
3665             Sequence< Reference< XParameter > > aParameterSeq = xCtor->getParameters();
3666             const Reference< XParameter >* pParameterSeq = aParameterSeq.getConstArray();
3667             sal_uInt32 nUnoParamCount = aParameterSeq.getLength();
3668 
3669             // Default: Ignore not needed parameters
3670             bool bParameterError = false;
3671 
3672             // Is the last parameter a rest parameter?
3673             bool bRestParameterMode = false;
3674             if( nUnoParamCount > 0 )
3675             {
3676                 Reference< XParameter > xLastParam = pParameterSeq[ nUnoParamCount - 1 ];
3677                 if( xLastParam.is() )
3678                 {
3679                     if( xLastParam->isRestParameter() )
3680                         bRestParameterMode = true;
3681                 }
3682             }
3683 
3684             // Too many parameters with context as first parameter?
3685             sal_uInt16 nSbxParameterOffset = 1;
3686             sal_uInt16 nParameterOffsetByContext = 0;
3687             Reference < XComponentContext > xFirstParamContext;
3688             if( nParamCount > nUnoParamCount )
3689             {
3690                 // Check if first parameter is a context and use it
3691                 // then in createInstanceWithArgumentsAndContext
3692                 Any aArg0 = sbxToUnoValue( pParams->Get( nSbxParameterOffset ) );
3693                 if( (aArg0 >>= xFirstParamContext) && xFirstParamContext.is() )
3694                     nParameterOffsetByContext = 1;
3695             }
3696 
3697             sal_uInt32 nEffectiveParamCount = nParamCount - nParameterOffsetByContext;
3698             sal_uInt32 nAllocParamCount = nEffectiveParamCount;
3699             if( nEffectiveParamCount > nUnoParamCount )
3700             {
3701                 if( !bRestParameterMode )
3702                 {
3703                     nEffectiveParamCount = nUnoParamCount;
3704                     nAllocParamCount = nUnoParamCount;
3705                 }
3706             }
3707             // Not enough parameters?
3708             else if( nUnoParamCount > nEffectiveParamCount )
3709             {
3710                 // RestParameterMode only helps if one (the last) parameter is missing
3711                 int nDiff = nUnoParamCount - nEffectiveParamCount;
3712                 if( !bRestParameterMode || nDiff > 1 )
3713                 {
3714                     bParameterError = true;
3715                     StarBASIC::Error( SbERR_NOT_OPTIONAL );
3716                 }
3717             }
3718 
3719             if( !bParameterError )
3720             {
3721                 if( nAllocParamCount > 0 )
3722                 {
3723                     args.realloc( nAllocParamCount );
3724                     Any* pAnyArgs = args.getArray();
3725                     for( sal_uInt32 i = 0 ; i < nEffectiveParamCount ; i++ )
3726                     {
3727                         sal_uInt16 iSbx = (sal_uInt16)(i + nSbxParameterOffset + nParameterOffsetByContext);
3728 
3729                         // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount
3730                         Reference< XParameter > xParam;
3731                         if( i < nUnoParamCount )
3732                         {
3733                             xParam = pParameterSeq[i];
3734                             if( !xParam.is() )
3735                                 continue;
3736 
3737                             Reference< XTypeDescription > xParamTypeDesc = xParam->getType();
3738                             if( !xParamTypeDesc.is() )
3739                                 continue;
3740                             com::sun::star::uno::Type aType( xParamTypeDesc->getTypeClass(), xParamTypeDesc->getName() );
3741 
3742                             // sbx paramter needs offset 1
3743                             pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ), aType );
3744 
3745                             // Check for out parameter if not already done
3746                             if( !bOutParams )
3747                             {
3748                                 if( xParam->isOut() )
3749                                     bOutParams = sal_True;
3750                             }
3751                         }
3752                         else
3753                         {
3754                             pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ) );
3755                         }
3756                     }
3757                 }
3758 
3759                 // "Call" ctor using createInstanceWithArgumentsAndContext
3760                 Reference < XComponentContext > xContext;
3761                 if( xFirstParamContext.is() )
3762                 {
3763                     xContext = xFirstParamContext;
3764                 }
3765                 else
3766                 {
3767                     Reference < XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
3768                     xContext.set( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" )) ), UNO_QUERY_THROW );
3769                 }
3770                 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
3771 
3772                 Any aRetAny;
3773                 if( xServiceMgr.is() )
3774                 {
3775                     String aServiceName = GetName();
3776                     Reference < XInterface > xRet;
3777                     try
3778                     {
3779                         xRet = xServiceMgr->createInstanceWithArgumentsAndContext( aServiceName, args, xContext );
3780                     }
3781                     catch( const Exception& )
3782                     {
3783                         implHandleAnyException( ::cppu::getCaughtException() );
3784                     }
3785                     aRetAny <<= xRet;
3786                 }
3787                 unoToSbxValue( pVar, aRetAny );
3788 
3789                 // Copy back out parameters?
3790                 if( bOutParams )
3791                 {
3792                     const Any* pAnyArgs = args.getConstArray();
3793 
3794                     for( sal_uInt32 j = 0 ; j < nUnoParamCount ; j++ )
3795                     {
3796                         Reference< XParameter > xParam = pParameterSeq[j];
3797                         if( !xParam.is() )
3798                             continue;
3799 
3800                         if( xParam->isOut() )
3801                             unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pAnyArgs[ j ] );
3802                     }
3803                 }
3804             }
3805         }
3806         else
3807             SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
3808     }
3809 }
3810 
3811 
3812 
3813 static SbUnoServiceCtor* pFirstCtor = NULL;
3814 
clearUnoServiceCtors(void)3815 void clearUnoServiceCtors( void )
3816 {
3817     SbUnoServiceCtor* pCtor = pFirstCtor;
3818     while( pCtor )
3819     {
3820         pCtor->SbxValue::Clear();
3821         pCtor = pCtor->pNext;
3822     }
3823 }
3824 
SbUnoServiceCtor(const String & aName_,Reference<XServiceConstructorDescription> xServiceCtorDesc)3825 SbUnoServiceCtor::SbUnoServiceCtor( const String& aName_, Reference< XServiceConstructorDescription > xServiceCtorDesc )
3826     : SbxMethod( aName_, SbxOBJECT )
3827     , m_xServiceCtorDesc( xServiceCtorDesc )
3828 {
3829 }
3830 
~SbUnoServiceCtor()3831 SbUnoServiceCtor::~SbUnoServiceCtor()
3832 {
3833 }
3834 
GetInfo()3835 SbxInfo* SbUnoServiceCtor::GetInfo()
3836 {
3837     SbxInfo* pRet = NULL;
3838 
3839     return pRet;
3840 }
3841 
3842 
findUnoSingleton(const String & rName)3843 SbUnoSingleton* findUnoSingleton( const String& rName )
3844 {
3845     SbUnoSingleton* pSbUnoSingleton = NULL;
3846 
3847     Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3848     if( xTypeAccess->hasByHierarchicalName( rName ) )
3849     {
3850         Any aRet = xTypeAccess->getByHierarchicalName( rName );
3851         Reference< XTypeDescription > xTypeDesc;
3852         aRet >>= xTypeDesc;
3853 
3854         if( xTypeDesc.is() )
3855         {
3856             TypeClass eTypeClass = xTypeDesc->getTypeClass();
3857             if( eTypeClass == TypeClass_SINGLETON )
3858             {
3859                 Reference< XSingletonTypeDescription > xSingletonTypeDesc( xTypeDesc, UNO_QUERY );
3860                 if( xSingletonTypeDesc.is() )
3861                     pSbUnoSingleton = new SbUnoSingleton( rName, xSingletonTypeDesc );
3862             }
3863         }
3864     }
3865     return pSbUnoSingleton;
3866 }
3867 
SbUnoSingleton(const String & aName_,const Reference<XSingletonTypeDescription> & xSingletonTypeDesc)3868 SbUnoSingleton::SbUnoSingleton( const String& aName_,
3869     const Reference< XSingletonTypeDescription >& xSingletonTypeDesc )
3870         : SbxObject( aName_ )
3871         , m_xSingletonTypeDesc( xSingletonTypeDesc )
3872 {
3873     SbxVariableRef xGetMethodRef =
3874         new SbxMethod( String( RTL_CONSTASCII_USTRINGPARAM( "get" ) ), SbxOBJECT );
3875     QuickInsert( (SbxVariable*)xGetMethodRef );
3876 }
3877 
SFX_NOTIFY(SfxBroadcaster & rBC,const TypeId & rBCType,const SfxHint & rHint,const TypeId & rHintType)3878 void SbUnoSingleton::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
3879                            const SfxHint& rHint, const TypeId& rHintType )
3880 {
3881     const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
3882     if( pHint )
3883     {
3884         SbxVariable* pVar = pHint->GetVar();
3885         SbxArray* pParams = pVar->GetParameters();
3886         sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
3887         sal_uInt32 nAllowedParamCount = 1;
3888 
3889         Reference < XComponentContext > xContextToUse;
3890         if( nParamCount > 0 )
3891         {
3892             // Check if first parameter is a context and use it then
3893             Reference < XComponentContext > xFirstParamContext;
3894             Any aArg1 = sbxToUnoValue( pParams->Get( 1 ) );
3895             if( (aArg1 >>= xFirstParamContext) && xFirstParamContext.is() )
3896                 xContextToUse = xFirstParamContext;
3897         }
3898 
3899         if( !xContextToUse.is() )
3900         {
3901             Reference < XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
3902             xContextToUse.set( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" )) ), UNO_QUERY_THROW );
3903             --nAllowedParamCount;
3904         }
3905 
3906         if( nParamCount > nAllowedParamCount )
3907         {
3908             StarBASIC::Error( SbERR_BAD_ARGUMENT );
3909             return;
3910         }
3911 
3912         Any aRetAny;
3913         if( xContextToUse.is() )
3914         {
3915             String aSingletonName( RTL_CONSTASCII_USTRINGPARAM("/singletons/") );
3916             aSingletonName += GetName();
3917             Reference < XInterface > xRet;
3918             xContextToUse->getValueByName( aSingletonName ) >>= xRet;
3919             aRetAny <<= xRet;
3920         }
3921         unoToSbxValue( pVar, aRetAny );
3922     }
3923     else
3924         SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
3925 }
3926 
3927 
3928 //========================================================================
3929 //========================================================================
3930 //========================================================================
3931 
3932 // Implementation eines EventAttacher-bezogenen AllListeners, der
3933 // nur einzelne Events an einen allgemeinen AllListener weiterleitet
3934 class BasicAllListener_Impl : public BasicAllListenerHelper
3935 {
3936     virtual void firing_impl(const AllEventObject& Event, Any* pRet);
3937 
3938 public:
3939     SbxObjectRef    xSbxObj;
3940     ::rtl::OUString     aPrefixName;
3941 
3942     BasicAllListener_Impl( const ::rtl::OUString& aPrefixName );
3943     ~BasicAllListener_Impl();
3944 
3945     // Methoden von XInterface
3946     //virtual sal_Bool queryInterface( Uik aUik, Reference< XInterface > & rOut );
3947 
3948     // Methoden von XAllListener
3949     virtual void SAL_CALL firing(const AllEventObject& Event) throw ( RuntimeException );
3950     virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw ( RuntimeException );
3951 
3952     // Methoden von XEventListener
3953     virtual void SAL_CALL disposing(const EventObject& Source) throw ( RuntimeException );
3954 };
3955 
3956 
3957 //========================================================================
BasicAllListener_Impl(const::rtl::OUString & aPrefixName_)3958 BasicAllListener_Impl::BasicAllListener_Impl
3959 (
3960     const ::rtl::OUString   & aPrefixName_
3961 )
3962     : aPrefixName( aPrefixName_ )
3963 {
3964 }
3965 
3966 //========================================================================
~BasicAllListener_Impl()3967 BasicAllListener_Impl::~BasicAllListener_Impl()
3968 {
3969 }
3970 
3971 //========================================================================
3972 
firing_impl(const AllEventObject & Event,Any * pRet)3973 void BasicAllListener_Impl::firing_impl( const AllEventObject& Event, Any* pRet )
3974 {
3975     vos::OGuard guard( Application::GetSolarMutex() );
3976 
3977     if( xSbxObj.Is() )
3978     {
3979         ::rtl::OUString aMethodName = aPrefixName;
3980         aMethodName = aMethodName + Event.MethodName;
3981 
3982         SbxVariable * pP = xSbxObj;
3983         while( pP->GetParent() )
3984         {
3985             pP = pP->GetParent();
3986             StarBASIC * pLib = PTR_CAST(StarBASIC,pP);
3987             if( pLib )
3988             {
3989                 // In Basic Array anlegen
3990                 SbxArrayRef xSbxArray = new SbxArray( SbxVARIANT );
3991                 const Any * pArgs = Event.Arguments.getConstArray();
3992                 sal_Int32 nCount = Event.Arguments.getLength();
3993                 for( sal_Int32 i = 0; i < nCount; i++ )
3994                 {
3995                     // Elemente wandeln
3996                     SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
3997                     unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
3998                     xSbxArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
3999                 }
4000 
4001                 pLib->Call( aMethodName, xSbxArray );
4002 
4003                 // Return-Wert aus dem Param-Array holen, wenn verlangt
4004                 if( pRet )
4005                 {
4006                     SbxVariable* pVar = xSbxArray->Get( 0 );
4007                     if( pVar )
4008                     {
4009                         // #95792 Avoid a second call
4010                         sal_uInt16 nFlags = pVar->GetFlags();
4011                         pVar->SetFlag( SBX_NO_BROADCAST );
4012                         *pRet = sbxToUnoValueImpl( pVar );
4013                         pVar->SetFlags( nFlags );
4014                     }
4015                 }
4016                 break;
4017             }
4018         }
4019     }
4020 }
4021 
4022 
4023 // Methoden von XAllListener
firing(const AllEventObject & Event)4024 void BasicAllListener_Impl::firing( const AllEventObject& Event ) throw ( RuntimeException )
4025 {
4026     firing_impl( Event, NULL );
4027 }
4028 
approveFiring(const AllEventObject & Event)4029 Any BasicAllListener_Impl::approveFiring( const AllEventObject& Event ) throw ( RuntimeException )
4030 {
4031     Any aRetAny;
4032     firing_impl( Event, &aRetAny );
4033     return aRetAny;
4034 }
4035 
4036 //========================================================================
4037 // Methoden von XEventListener
disposing(const EventObject &)4038 void BasicAllListener_Impl ::disposing(const EventObject& ) throw ( RuntimeException )
4039 {
4040     vos::OGuard guard( Application::GetSolarMutex() );
4041 
4042     xSbxObj.Clear();
4043 }
4044 
4045 
4046 
4047 //*************************************************************************
4048 //  class InvocationToAllListenerMapper
4049 //  helper class to map XInvocation to XAllListener (also in project eventattacher!)
4050 //*************************************************************************
4051 class InvocationToAllListenerMapper : public WeakImplHelper1< XInvocation >
4052 {
4053 public:
4054     InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
4055         const Reference< XAllListener >& AllListener, const Any& Helper );
4056 
4057     // XInvocation
4058     virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection(void) throw( RuntimeException );
4059     virtual Any SAL_CALL invoke(const ::rtl::OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
4060         throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException );
4061     virtual void SAL_CALL setValue(const ::rtl::OUString& PropertyName, const Any& Value)
4062         throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException );
4063     virtual Any SAL_CALL getValue(const ::rtl::OUString& PropertyName) throw( UnknownPropertyException, RuntimeException );
4064     virtual sal_Bool SAL_CALL hasMethod(const ::rtl::OUString& Name) throw( RuntimeException );
4065     virtual sal_Bool SAL_CALL hasProperty(const ::rtl::OUString& Name) throw( RuntimeException );
4066 
4067 private:
4068     Reference< XIdlReflection >  m_xCoreReflection;
4069     Reference< XAllListener >    m_xAllListener;
4070     Reference< XIdlClass >       m_xListenerType;
4071     Any                          m_Helper;
4072 };
4073 
4074 
4075 // Function to replace AllListenerAdapterService::createAllListerAdapter
createAllListenerAdapter(const Reference<XInvocationAdapterFactory> & xInvocationAdapterFactory,const Reference<XIdlClass> & xListenerType,const Reference<XAllListener> & xListener,const Any & Helper)4076 Reference< XInterface > createAllListenerAdapter
4077 (
4078     const Reference< XInvocationAdapterFactory >& xInvocationAdapterFactory,
4079     const Reference< XIdlClass >& xListenerType,
4080     const Reference< XAllListener >& xListener,
4081     const Any& Helper
4082 )
4083 {
4084     Reference< XInterface > xAdapter;
4085     if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() )
4086     {
4087        Reference< XInvocation > xInvocationToAllListenerMapper =
4088             (XInvocation*)new InvocationToAllListenerMapper( xListenerType, xListener, Helper );
4089         Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName() );
4090         xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, aListenerType );
4091     }
4092     return xAdapter;
4093 }
4094 
4095 
4096 //--------------------------------------------------------------------------------------------------
4097 // InvocationToAllListenerMapper
InvocationToAllListenerMapper(const Reference<XIdlClass> & ListenerType,const Reference<XAllListener> & AllListener,const Any & Helper)4098 InvocationToAllListenerMapper::InvocationToAllListenerMapper
4099     ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper )
4100         : m_xAllListener( AllListener )
4101         , m_xListenerType( ListenerType )
4102         , m_Helper( Helper )
4103 {
4104 }
4105 
4106 //*************************************************************************
getIntrospection(void)4107 Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection(void)
4108     throw( RuntimeException )
4109 {
4110     return Reference< XIntrospectionAccess >();
4111 }
4112 
4113 //*************************************************************************
invoke(const::rtl::OUString & FunctionName,const Sequence<Any> & Params,Sequence<sal_Int16> & OutParamIndex,Sequence<Any> & OutParam)4114 Any SAL_CALL InvocationToAllListenerMapper::invoke(const ::rtl::OUString& FunctionName, const Sequence< Any >& Params,
4115     Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
4116         throw( IllegalArgumentException, CannotConvertException,
4117         InvocationTargetException, RuntimeException )
4118 {
4119     (void)OutParamIndex;
4120     (void)OutParam     ;
4121 
4122     Any aRet;
4123 
4124     // Check if to firing or approveFiring has to be called
4125     Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
4126     sal_Bool bApproveFiring = sal_False;
4127     if( !xMethod.is() )
4128         return aRet;
4129     Reference< XIdlClass > xReturnType = xMethod->getReturnType();
4130     Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes();
4131     if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) ||
4132         aExceptionSeq.getLength() > 0 )
4133     {
4134         bApproveFiring = sal_True;
4135     }
4136     else
4137     {
4138         Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos();
4139         sal_uInt32 nParamCount = aParamSeq.getLength();
4140         if( nParamCount > 1 )
4141         {
4142             const ParamInfo* pInfos = aParamSeq.getConstArray();
4143             for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
4144             {
4145                 if( pInfos[ i ].aMode != ParamMode_IN )
4146                 {
4147                     bApproveFiring = sal_True;
4148                     break;
4149                 }
4150             }
4151         }
4152     }
4153 
4154     AllEventObject aAllEvent;
4155     aAllEvent.Source = (OWeakObject*) this;
4156     aAllEvent.Helper = m_Helper;
4157     aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName() );
4158     aAllEvent.MethodName = FunctionName;
4159     aAllEvent.Arguments = Params;
4160     if( bApproveFiring )
4161         aRet = m_xAllListener->approveFiring( aAllEvent );
4162     else
4163         m_xAllListener->firing( aAllEvent );
4164     return aRet;
4165 }
4166 
4167 //*************************************************************************
setValue(const::rtl::OUString & PropertyName,const Any & Value)4168 void SAL_CALL InvocationToAllListenerMapper::setValue(const ::rtl::OUString& PropertyName, const Any& Value)
4169     throw( UnknownPropertyException, CannotConvertException,
4170            InvocationTargetException, RuntimeException )
4171 {
4172     (void)PropertyName;
4173     (void)Value;
4174 }
4175 
4176 //*************************************************************************
getValue(const::rtl::OUString & PropertyName)4177 Any SAL_CALL InvocationToAllListenerMapper::getValue(const ::rtl::OUString& PropertyName)
4178     throw( UnknownPropertyException, RuntimeException )
4179 {
4180     (void)PropertyName;
4181 
4182     return Any();
4183 }
4184 
4185 //*************************************************************************
hasMethod(const::rtl::OUString & Name)4186 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const ::rtl::OUString& Name)
4187     throw( RuntimeException )
4188 {
4189     Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
4190     return xMethod.is();
4191 }
4192 
4193 //*************************************************************************
hasProperty(const::rtl::OUString & Name)4194 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const ::rtl::OUString& Name)
4195     throw( RuntimeException )
4196 {
4197     Reference< XIdlField > xField = m_xListenerType->getField( Name );
4198     return xField.is();
4199 }
4200 
4201 //========================================================================
4202 // Uno-Service erzeugen
4203 // 1. Parameter == Prefix-Name der Makros
4204 // 2. Parameter == voll qualifizierter Name des Listeners
SbRtl_CreateUnoListener(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)4205 void SbRtl_CreateUnoListener( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4206 //RTLFUNC(CreateUnoListener)
4207 {
4208     (void)bWrite;
4209 
4210     // Wir brauchen 2 Parameter
4211     if ( rPar.Count() != 3 )
4212     {
4213         StarBASIC::Error( SbERR_BAD_ARGUMENT );
4214         return;
4215     }
4216 
4217     // Klassen-Name der struct holen
4218     String aPrefixName = rPar.Get(1)->GetString();
4219     String aListenerClassName = rPar.Get(2)->GetString();
4220 
4221     // CoreReflection holen
4222     Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
4223     if( !xCoreReflection.is() )
4224         return;
4225 
4226     // AllListenerAdapterService holen
4227     Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
4228     if( !xFactory.is() )
4229         return;
4230 
4231     // Klasse suchen
4232     Reference< XIdlClass > xClass = xCoreReflection->forName( aListenerClassName );
4233     if( !xClass.is() )
4234         return;
4235 
4236     // AB, 30.11.1999 InvocationAdapterFactory holen
4237     Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = Reference< XInvocationAdapterFactory >(
4238         xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.script.InvocationAdapterFactory") ), UNO_QUERY );
4239 
4240     BasicAllListener_Impl * p;
4241     Reference< XAllListener > xAllLst = p = new BasicAllListener_Impl( aPrefixName );
4242     Any aTmp;
4243     Reference< XInterface > xLst = createAllListenerAdapter( xInvocationAdapterFactory, xClass, xAllLst, aTmp );
4244     if( !xLst.is() )
4245         return;
4246 
4247     ::rtl::OUString aClassName = xClass->getName();
4248     Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
4249     aTmp = xLst->queryInterface( aClassType );
4250     if( !aTmp.hasValue() )
4251         return;
4252 
4253     SbUnoObject* pUnoObj = new SbUnoObject( aListenerClassName, aTmp );
4254     p->xSbxObj = pUnoObj;
4255     p->xSbxObj->SetParent( pBasic );
4256 
4257     // #100326 Register listener object to set Parent NULL in Dtor
4258     SbxArrayRef xBasicUnoListeners = pBasic->getUnoListeners();
4259     xBasicUnoListeners->Insert( pUnoObj, xBasicUnoListeners->Count() );
4260 
4261     // Objekt zurueckliefern
4262     SbxVariableRef refVar = rPar.Get(0);
4263     refVar->PutObject( p->xSbxObj );
4264 }
4265 
4266 //========================================================================
4267 // Represents the DefaultContext property of the ProcessServiceManager
4268 // in the Basic runtime system.
RTL_Impl_GetDefaultContext(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)4269 void RTL_Impl_GetDefaultContext( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4270 {
4271     (void)pBasic;
4272     (void)bWrite;
4273 
4274     SbxVariableRef refVar = rPar.Get(0);
4275 
4276     Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
4277     Reference< XPropertySet> xPSMPropertySet( xFactory, UNO_QUERY );
4278     if( xPSMPropertySet.is() )
4279     {
4280         Any aContextAny = xPSMPropertySet->getPropertyValue(
4281             String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) );
4282 
4283         SbUnoObjectRef xUnoObj = new SbUnoObject
4284             ( String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ),
4285               aContextAny );
4286         refVar->PutObject( (SbUnoObject*)xUnoObj );
4287     }
4288     else
4289     {
4290         refVar->PutObject( NULL );
4291     }
4292 }
4293 
4294 //========================================================================
4295 // Creates a Basic wrapper object for a strongly typed Uno value
4296 // 1. parameter: Uno type as full qualified type name, e.g. "byte[]"
RTL_Impl_CreateUnoValue(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)4297 void RTL_Impl_CreateUnoValue( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4298 {
4299     (void)pBasic;
4300     (void)bWrite;
4301 
4302     static String aTypeTypeString( RTL_CONSTASCII_USTRINGPARAM("type") );
4303 
4304     // 2 parameters needed
4305     if ( rPar.Count() != 3 )
4306     {
4307         StarBASIC::Error( SbERR_BAD_ARGUMENT );
4308         return;
4309     }
4310 
4311     // Klassen-Name der struct holen
4312     String aTypeName = rPar.Get(1)->GetString();
4313     SbxVariable* pVal = rPar.Get(2);
4314 
4315     if( aTypeName == aTypeTypeString )
4316     {
4317         SbxDataType eBaseType = pVal->SbxValue::GetType();
4318         String aValTypeName;
4319         if( eBaseType == SbxSTRING )
4320         {
4321             aValTypeName = pVal->GetString();
4322         }
4323         else if( eBaseType == SbxOBJECT )
4324         {
4325             // XIdlClass?
4326             Reference< XIdlClass > xIdlClass;
4327 
4328             SbxBaseRef pObj = (SbxBase*)pVal->GetObject();
4329             if( pObj && pObj->ISA(SbUnoObject) )
4330             {
4331                 Any aUnoAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
4332                 aUnoAny >>= xIdlClass;
4333             }
4334 
4335             if( xIdlClass.is() )
4336                 aValTypeName = xIdlClass->getName();
4337         }
4338         Type aType;
4339         bool bSuccess = implGetTypeByName( aValTypeName, aType );
4340         if( bSuccess )
4341         {
4342             Any aTypeAny( aType );
4343             SbxVariableRef refVar = rPar.Get(0);
4344             SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aTypeAny );
4345             refVar->PutObject( xUnoAnyObject );
4346         }
4347         return;
4348     }
4349 
4350     // Check the type
4351     Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
4352     Any aRet;
4353     try
4354     {
4355         aRet = xTypeAccess->getByHierarchicalName( aTypeName );
4356     }
4357     catch( NoSuchElementException& e1 )
4358     {
4359         String aNoSuchElementExceptionName
4360             ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.NoSuchElementException" ) );
4361         StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
4362             implGetExceptionMsg( e1, aNoSuchElementExceptionName ) );
4363         return;
4364     }
4365     Reference< XTypeDescription > xTypeDesc;
4366     aRet >>= xTypeDesc;
4367     TypeClass eTypeClass = xTypeDesc->getTypeClass();
4368     Type aDestType( eTypeClass, aTypeName );
4369 
4370 
4371     // Preconvert value
4372     Any aVal = sbxToUnoValueImpl( pVal );
4373     Any aConvertedVal = convertAny( aVal, aDestType );
4374 
4375     /*
4376     // Convert
4377     Reference< XTypeConverter > xConverter = getTypeConverter_Impl();
4378     try
4379     {
4380         aConvertedVal = xConverter->convertTo( aVal, aDestType );
4381     }
4382     catch( IllegalArgumentException& e1 )
4383     {
4384         StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
4385             implGetExceptionMsg( ::cppu::getCaughtException() ) );
4386         return;
4387     }
4388     catch( CannotConvertException& e2 )
4389     {
4390         String aCannotConvertExceptionName
4391             ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.IllegalArgumentException" ) );
4392         StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
4393             implGetExceptionMsg( e2, aCannotConvertExceptionName ) );
4394         return;
4395     }
4396     */
4397 
4398     SbxVariableRef refVar = rPar.Get(0);
4399     SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aConvertedVal );
4400     refVar->PutObject( xUnoAnyObject );
4401 }
4402 
4403 //==========================================================================
4404 
4405 namespace {
4406 class OMutexBasis
4407 {
4408 protected:
4409     // this mutex is necessary for OInterfaceContainerHelper
4410     ::osl::Mutex m_aMutex;
4411 };
4412 } // namespace
4413 
4414 typedef WeakImplHelper2< XInvocation, XComponent > ModuleInvocationProxyHelper;
4415 
4416 class ModuleInvocationProxy : public OMutexBasis,
4417                               public ModuleInvocationProxyHelper
4418 {
4419     ::rtl::OUString     m_aPrefix;
4420     SbxObjectRef        m_xScopeObj;
4421     bool                m_bProxyIsClassModuleObject;
4422 
4423     ::cppu::OInterfaceContainerHelper m_aListeners;
4424 
4425 public:
4426     ModuleInvocationProxy( const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj );
~ModuleInvocationProxy()4427     ~ModuleInvocationProxy()
4428     {}
4429 
4430     // XInvocation
4431     virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() throw();
4432     virtual void SAL_CALL setValue( const ::rtl::OUString& rProperty, const Any& rValue )
4433         throw( UnknownPropertyException );
4434     virtual Any SAL_CALL getValue( const ::rtl::OUString& rProperty )
4435         throw( UnknownPropertyException );
4436     virtual sal_Bool SAL_CALL hasMethod( const ::rtl::OUString& rName ) throw();
4437     virtual sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& rProp ) throw();
4438 
4439     virtual Any SAL_CALL invoke( const ::rtl::OUString& rFunction,
4440                                  const Sequence< Any >& rParams,
4441                                  Sequence< sal_Int16 >& rOutParamIndex,
4442                                  Sequence< Any >& rOutParam )
4443         throw( CannotConvertException, InvocationTargetException );
4444 
4445     // XComponent
4446     virtual void SAL_CALL dispose() throw(RuntimeException);
4447     virtual void SAL_CALL addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException);
4448     virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& aListener ) throw (RuntimeException);
4449 };
4450 
ModuleInvocationProxy(const::rtl::OUString & aPrefix,SbxObjectRef xScopeObj)4451 ModuleInvocationProxy::ModuleInvocationProxy( const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj )
4452     : m_aPrefix( aPrefix + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_") ) )
4453     , m_xScopeObj( xScopeObj )
4454     , m_aListeners( m_aMutex )
4455 {
4456     m_bProxyIsClassModuleObject = xScopeObj.Is() ? xScopeObj->ISA(SbClassModuleObject) : false;
4457 }
4458 
getIntrospection()4459 Reference< XIntrospectionAccess > SAL_CALL ModuleInvocationProxy::getIntrospection() throw()
4460 {
4461     return Reference< XIntrospectionAccess >();
4462 }
4463 
setValue(const::rtl::OUString & rProperty,const Any & rValue)4464 void SAL_CALL ModuleInvocationProxy::setValue( const ::rtl::OUString& rProperty, const Any& rValue ) throw( UnknownPropertyException )
4465 {
4466     if( !m_bProxyIsClassModuleObject )
4467         throw UnknownPropertyException();
4468 
4469     vos::OGuard guard( Application::GetSolarMutex() );
4470 
4471     ::rtl::OUString aPropertyFunctionName( RTL_CONSTASCII_USTRINGPARAM( "Property Set ") );
4472     aPropertyFunctionName += m_aPrefix;
4473     aPropertyFunctionName += rProperty;
4474 
4475     SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD );
4476     SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4477     if( pMeth == NULL )
4478     {
4479         // TODO: Check vba behavior concernig missing function
4480         //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4481         throw UnknownPropertyException();
4482     }
4483 
4484     // Setup parameter
4485     SbxArrayRef xArray = new SbxArray;
4486     SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
4487     unoToSbxValue( (SbxVariable*)xVar, rValue );
4488     xArray->Put( xVar, 1 );
4489 
4490     // Call property method
4491     SbxVariableRef xValue = new SbxVariable;
4492     pMeth->SetParameters( xArray );
4493     pMeth->Call( xValue );
4494     //aRet = sbxToUnoValue( xValue );
4495     pMeth->SetParameters( NULL );
4496 
4497     // TODO: OutParameter?
4498 
4499     // throw InvocationTargetException();
4500 
4501     //return aRet;
4502 
4503 }
4504 
getValue(const::rtl::OUString & rProperty)4505 Any SAL_CALL ModuleInvocationProxy::getValue( const ::rtl::OUString& rProperty ) throw( UnknownPropertyException )
4506 {
4507     if( !m_bProxyIsClassModuleObject )
4508         throw UnknownPropertyException();
4509 
4510     vos::OGuard guard( Application::GetSolarMutex() );
4511 
4512     ::rtl::OUString aPropertyFunctionName( RTL_CONSTASCII_USTRINGPARAM( "Property Get ") );
4513     aPropertyFunctionName += m_aPrefix;
4514     aPropertyFunctionName += rProperty;
4515 
4516     SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD );
4517     SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4518     if( pMeth == NULL )
4519     {
4520         // TODO: Check vba behavior concernig missing function
4521         //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4522         throw UnknownPropertyException();
4523     }
4524 
4525     // Call method
4526     SbxVariableRef xValue = new SbxVariable;
4527     pMeth->Call( xValue );
4528     Any aRet = sbxToUnoValue( xValue );
4529     return aRet;
4530 }
4531 
hasMethod(const::rtl::OUString &)4532 sal_Bool SAL_CALL ModuleInvocationProxy::hasMethod( const ::rtl::OUString& ) throw()
4533 {
4534     return sal_False;
4535 }
4536 
hasProperty(const::rtl::OUString &)4537 sal_Bool SAL_CALL ModuleInvocationProxy::hasProperty( const ::rtl::OUString& ) throw()
4538 {
4539     return sal_False;
4540 }
4541 
invoke(const::rtl::OUString & rFunction,const Sequence<Any> & rParams,Sequence<sal_Int16> &,Sequence<Any> &)4542 Any SAL_CALL ModuleInvocationProxy::invoke( const ::rtl::OUString& rFunction,
4543                                             const Sequence< Any >& rParams,
4544                                             Sequence< sal_Int16 >&,
4545                                             Sequence< Any >& )
4546     throw( CannotConvertException, InvocationTargetException )
4547 {
4548     vos::OGuard guard( Application::GetSolarMutex() );
4549 
4550     Any aRet;
4551     SbxObjectRef xScopeObj = m_xScopeObj;
4552     if( !xScopeObj.Is() )
4553         return aRet;
4554 
4555     ::rtl::OUString aFunctionName = m_aPrefix;
4556     aFunctionName += rFunction;
4557 
4558     sal_Bool bSetRescheduleBack = sal_False;
4559     sal_Bool bOldReschedule = sal_True;
4560     SbiInstance* pInst = pINST;
4561     if( pInst && pInst->IsCompatibility() )
4562     {
4563         bOldReschedule = pInst->IsReschedule();
4564         if ( bOldReschedule )
4565         {
4566             pInst->EnableReschedule( sal_False );
4567             bSetRescheduleBack = sal_True;
4568         }
4569     }
4570 
4571     SbxVariable* p = xScopeObj->Find( aFunctionName, SbxCLASS_METHOD );
4572     SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4573     if( pMeth == NULL )
4574     {
4575         // TODO: Check vba behavior concernig missing function
4576         //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4577         return aRet;
4578     }
4579 
4580     // Setup parameters
4581     SbxArrayRef xArray;
4582     sal_Int32 nParamCount = rParams.getLength();
4583     if( nParamCount )
4584     {
4585         xArray = new SbxArray;
4586         const Any *pArgs = rParams.getConstArray();
4587         for( sal_Int32 i = 0 ; i < nParamCount ; i++ )
4588         {
4589             SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
4590             unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
4591             xArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
4592         }
4593     }
4594 
4595     // Call method
4596     SbxVariableRef xValue = new SbxVariable;
4597     if( xArray.Is() )
4598         pMeth->SetParameters( xArray );
4599     pMeth->Call( xValue );
4600     aRet = sbxToUnoValue( xValue );
4601     pMeth->SetParameters( NULL );
4602 
4603     if( bSetRescheduleBack )
4604         pInst->EnableReschedule( bOldReschedule );
4605 
4606     // TODO: OutParameter?
4607 
4608     return aRet;
4609 }
4610 
dispose()4611 void SAL_CALL ModuleInvocationProxy::dispose()
4612     throw(RuntimeException)
4613 {
4614     ::osl::MutexGuard aGuard( m_aMutex );
4615 
4616     EventObject aEvent( (XComponent*)this );
4617     m_aListeners.disposeAndClear( aEvent );
4618 
4619     m_xScopeObj = NULL;
4620 }
4621 
addEventListener(const Reference<XEventListener> & xListener)4622 void SAL_CALL ModuleInvocationProxy::addEventListener( const Reference< XEventListener >& xListener )
4623     throw (RuntimeException)
4624 {
4625     m_aListeners.addInterface( xListener );
4626 }
4627 
removeEventListener(const Reference<XEventListener> & xListener)4628 void SAL_CALL ModuleInvocationProxy::removeEventListener( const Reference< XEventListener >& xListener )
4629     throw (RuntimeException)
4630 {
4631     m_aListeners.removeInterface( xListener );
4632 }
4633 
4634 
createComListener(const Any & aControlAny,const::rtl::OUString & aVBAType,const::rtl::OUString & aPrefix,SbxObjectRef xScopeObj)4635 Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl::OUString& aVBAType,
4636                                            const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj )
4637 {
4638     Reference< XInterface > xRet;
4639 
4640     Reference< XComponentContext > xContext = getComponentContext_Impl();
4641     Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
4642 
4643     Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPrefix, xScopeObj );
4644 
4645     Sequence<Any> args( 3 );
4646     args[0] <<= aControlAny;
4647     args[1] <<= aVBAType;
4648     args[2] <<= xProxy;
4649 
4650     try
4651     {
4652         xRet = xServiceMgr->createInstanceWithArgumentsAndContext(
4653             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.custom.UnoComListener")),
4654             args, xContext );
4655     }
4656     catch( const Exception& )
4657     {
4658         implHandleAnyException( ::cppu::getCaughtException() );
4659     }
4660 
4661     return xRet;
4662 }
4663 
4664 typedef std::vector< WeakReference< XComponent > >  ComponentRefVector;
4665 
4666 struct StarBasicDisposeItem
4667 {
4668     StarBASIC*              m_pBasic;
4669     SbxArrayRef             m_pRegisteredVariables;
4670     ComponentRefVector      m_vComImplementsObjects;
4671 
StarBasicDisposeItemStarBasicDisposeItem4672     StarBasicDisposeItem( StarBASIC* pBasic )
4673         : m_pBasic( pBasic )
4674     {
4675         m_pRegisteredVariables = new SbxArray();
4676     }
4677 };
4678 
4679 typedef std::vector< StarBasicDisposeItem* > DisposeItemVector;
4680 
4681 static DisposeItemVector GaDisposeItemVector;
4682 
lcl_findItemForBasic(StarBASIC * pBasic)4683 DisposeItemVector::iterator lcl_findItemForBasic( StarBASIC* pBasic )
4684 {
4685     DisposeItemVector::iterator it;
4686     for( it = GaDisposeItemVector.begin() ; it != GaDisposeItemVector.end() ; ++it )
4687     {
4688         StarBasicDisposeItem* pItem = *it;
4689         if( pItem->m_pBasic == pBasic )
4690             return it;
4691     }
4692     return GaDisposeItemVector.end();
4693 }
4694 
lcl_getOrCreateItemForBasic(StarBASIC * pBasic)4695 StarBasicDisposeItem* lcl_getOrCreateItemForBasic( StarBASIC* pBasic )
4696 {
4697     DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic );
4698     StarBasicDisposeItem* pItem = (it != GaDisposeItemVector.end()) ? *it : NULL;
4699     if( pItem == NULL )
4700     {
4701         pItem = new StarBasicDisposeItem( pBasic );
4702         GaDisposeItemVector.push_back( pItem );
4703     }
4704     return pItem;
4705 }
4706 
registerComponentToBeDisposedForBasic(Reference<XComponent> xComponent,StarBASIC * pBasic)4707 void registerComponentToBeDisposedForBasic
4708     ( Reference< XComponent > xComponent, StarBASIC* pBasic )
4709 {
4710     StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic );
4711     pItem->m_vComImplementsObjects.push_back( xComponent );
4712 }
4713 
registerComListenerVariableForBasic(SbxVariable * pVar,StarBASIC * pBasic)4714 void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic )
4715 {
4716     StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic );
4717     SbxArray* pArray = pItem->m_pRegisteredVariables;
4718     pArray->Put( pVar, pArray->Count() );
4719 }
4720 
disposeComVariablesForBasic(StarBASIC * pBasic)4721 void disposeComVariablesForBasic( StarBASIC* pBasic )
4722 {
4723     DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic );
4724     if( it != GaDisposeItemVector.end() )
4725     {
4726         StarBasicDisposeItem* pItem = *it;
4727 
4728         SbxArray* pArray = pItem->m_pRegisteredVariables;
4729         sal_uInt16 nCount = pArray->Count();
4730         for( sal_uInt16 i = 0 ; i < nCount ; ++i )
4731         {
4732             SbxVariable* pVar = pArray->Get( i );
4733             pVar->ClearComListener();
4734         }
4735 
4736         ComponentRefVector& rv = pItem->m_vComImplementsObjects;
4737         ComponentRefVector::iterator itCRV;
4738         for( itCRV = rv.begin() ; itCRV != rv.end() ; ++itCRV )
4739         {
4740             try
4741             {
4742                 Reference< XComponent > xComponent( (*itCRV).get(), UNO_QUERY_THROW );
4743                 xComponent->dispose();
4744             }
4745             catch( Exception& )
4746             {}
4747         }
4748 
4749         delete pItem;
4750         GaDisposeItemVector.erase( it );
4751     }
4752 }
4753 
4754 
4755 // Handle module implements mechanism for OLE types
createCOMWrapperForIface(Any & o_rRetAny,SbClassModuleObject * pProxyClassModuleObject)4756 bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pProxyClassModuleObject )
4757 {
4758     // For now: Take first interface that allows to instantiate COM wrapper
4759     // TODO: Check if support for multiple interfaces is needed
4760 
4761     Reference< XComponentContext > xContext = getComponentContext_Impl();
4762     Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
4763     Reference< XSingleServiceFactory > xComImplementsFactory
4764     (
4765         xServiceMgr->createInstanceWithContext(
4766             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.custom.ComImplementsFactory")), xContext ),
4767         UNO_QUERY
4768     );
4769     if( !xComImplementsFactory.is() )
4770         return false;
4771 
4772     bool bSuccess = false;
4773 
4774     SbxArray* pModIfaces = pClassData->mxIfaces;
4775     sal_uInt16 nCount = pModIfaces->Count();
4776     for( sal_uInt16 i = 0 ; i < nCount ; ++i )
4777     {
4778         SbxVariable* pVar = pModIfaces->Get( i );
4779         ::rtl::OUString aIfaceName = pVar->GetName();
4780 
4781         if( !aIfaceName.isEmpty() )
4782         {
4783             ::rtl::OUString aPureIfaceName = aIfaceName;
4784             sal_Int32 indexLastDot = aIfaceName.lastIndexOf('.');
4785             if ( indexLastDot > -1 )
4786                 aPureIfaceName = aIfaceName.copy( indexLastDot + 1 );
4787 
4788             Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPureIfaceName, pProxyClassModuleObject );
4789 
4790             Sequence<Any> args( 2 );
4791             args[0] <<= aIfaceName;
4792             args[1] <<= xProxy;
4793 
4794             Reference< XInterface > xRet;
4795             bSuccess = false;
4796             try
4797             {
4798                 xRet = xComImplementsFactory->createInstanceWithArguments( args );
4799                 bSuccess = true;
4800             }
4801             catch( const Exception& )
4802             {
4803                 implHandleAnyException( ::cppu::getCaughtException() );
4804             }
4805 
4806             if( bSuccess )
4807             {
4808                 Reference< XComponent > xComponent( xProxy, UNO_QUERY );
4809                 if( xComponent.is() )
4810                 {
4811                     StarBASIC* pParentBasic = NULL;
4812                     SbxObject* pCurObject = this;
4813                     do
4814                     {
4815                         SbxObject* pObjParent = pCurObject->GetParent();
4816                         pParentBasic = PTR_CAST( StarBASIC, pObjParent );
4817                         pCurObject = pObjParent;
4818                     }
4819                     while( pParentBasic == NULL && pCurObject != NULL );
4820 
4821                     OSL_ASSERT( pParentBasic != NULL );
4822                     registerComponentToBeDisposedForBasic( xComponent, pParentBasic );
4823                 }
4824 
4825                 o_rRetAny <<= xRet;
4826                 break;
4827             }
4828         }
4829     }
4830 
4831     return bSuccess;
4832 }
4833 
4834 
4835 // Due to an incorrect behavior IE returns an object instead of a string
4836 // in some scenarios. Calling toString at the object may correct this.
4837 // Helper function used in sbxvalue.cxx
handleToStringForCOMObjects(SbxObject * pObj,SbxValue * pVal)4838 bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal )
4839 {
4840     bool bSuccess = false;
4841 
4842     SbUnoObject* pUnoObj = NULL;
4843     if( pObj != NULL && (pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)pObj)) != NULL )
4844     {
4845         // Only for native COM objects
4846         if( pUnoObj->isNativeCOMObject() )
4847         {
4848             SbxVariableRef pMeth = pObj->Find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "toString" ) ), SbxCLASS_METHOD );
4849             if ( pMeth.Is() )
4850             {
4851                 SbxValues aRes;
4852                 pMeth->Get( aRes );
4853                 pVal->Put( aRes );
4854                 bSuccess = true;
4855             }
4856         }
4857     }
4858     return bSuccess;
4859 }
4860 
4861