xref: /trunk/main/cppu/source/uno/lbenv.cxx (revision 0618ff6b)
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_cppu.hxx"
26 
27 #include "cppu/EnvDcp.hxx"
28 
29 #include "sal/alloca.h"
30 #include "osl/diagnose.h"
31 #include "osl/interlck.h"
32 #include "osl/mutex.hxx"
33 #include "osl/module.h"
34 #include "osl/process.h"
35 #include "rtl/process.h"
36 #include "rtl/unload.h"
37 #include "rtl/string.hxx"
38 #include "rtl/ustring.hxx"
39 #include "rtl/ustrbuf.hxx"
40 #include "rtl/instance.hxx"
41 #include "typelib/typedescription.h"
42 #include "uno/dispatcher.h"
43 #include "uno/environment.h"
44 #include "uno/lbnames.h"
45 #include "prim.hxx"
46 #include "destr.hxx"
47 #include "loadmodule.hxx"
48 
49 #include <hash_map>
50 #include <vector>
51 #include <stdio.h>
52 
53 
54 using ::rtl::OUString;
55 
56 namespace
57 {
58 
59 //------------------------------------------------------------------------------
td_equals(typelib_InterfaceTypeDescription * pTD1,typelib_InterfaceTypeDescription * pTD2)60 inline static bool td_equals( typelib_InterfaceTypeDescription * pTD1,
61                               typelib_InterfaceTypeDescription * pTD2 )
62 {
63     return (pTD1 == pTD2 ||
64             (((typelib_TypeDescription *)pTD1)->pTypeName->length ==
65              ((typelib_TypeDescription *)pTD2)->pTypeName->length &&
66              ::rtl_ustr_compare(
67                  ((typelib_TypeDescription *) pTD1)->pTypeName->buffer,
68                  ((typelib_TypeDescription *) pTD2)->pTypeName->buffer ) == 0));
69 }
70 
71 struct ObjectEntry;
72 struct uno_DefaultEnvironment;
73 
74 //------------------------------------------------------------------------------
75 struct InterfaceEntry
76 {
77     sal_Int32 refCount;
78     void * pInterface;
79     uno_freeProxyFunc fpFreeProxy;
80     typelib_InterfaceTypeDescription * pTypeDescr;
81 };
82 
83 struct ObjectEntry
84 {
85     OUString oid;
86     sal_Int32 nRef;
87     ::std::vector< InterfaceEntry > aInterfaces;
88     bool mixedObject;
89 
90     inline ObjectEntry( const OUString & rOId_ );
91 
92     inline void append(
93         uno_DefaultEnvironment * pEnv,
94         void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
95         uno_freeProxyFunc fpFreeProxy );
96     inline InterfaceEntry * find(
97         typelib_InterfaceTypeDescription * pTypeDescr );
98     inline sal_Int32 find( void * iface_ptr, ::std::size_t pos );
99 };
100 
101 //------------------------------------------------------------------------------
102 struct FctPtrHash :
103     public ::std::unary_function< const void *, ::std::size_t >
104 {
operator ()__anonedad264e0111::FctPtrHash105     ::std::size_t operator () ( const void * pKey ) const
106         { return (::std::size_t) pKey; }
107 };
108 
109 //------------------------------------------------------------------------------
110 struct FctOUStringHash :
111     public ::std::unary_function< const OUString &, ::std::size_t >
112 {
operator ()__anonedad264e0111::FctOUStringHash113     ::std::size_t operator () ( const OUString & rKey ) const
114         { return rKey.hashCode(); }
115 };
116 
117 // mapping from environment name to environment
118 typedef ::std::hash_map<
119     OUString, uno_Environment *, FctOUStringHash,
120     ::std::equal_to< OUString > > OUString2EnvironmentMap;
121 
122 // mapping from ptr to object entry
123 typedef ::std::hash_map<
124     void *, ObjectEntry *, FctPtrHash,
125     ::std::equal_to< void * > > Ptr2ObjectMap;
126 // mapping from oid to object entry
127 typedef ::std::hash_map<
128     OUString, ObjectEntry *, FctOUStringHash,
129     ::std::equal_to< OUString > > OId2ObjectMap;
130 
131 
132 //==============================================================================
133 struct EnvironmentsData
134 {
135     ::osl::Mutex mutex;
136     OUString2EnvironmentMap aName2EnvMap;
137 
EnvironmentsData__anonedad264e0111::EnvironmentsData138     EnvironmentsData() : isDisposing(false) {}
139     ~EnvironmentsData();
140 
141     inline void getEnvironment(
142         uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext );
143     inline void registerEnvironment( uno_Environment ** ppEnv );
144     inline void getRegisteredEnvironments(
145         uno_Environment *** pppEnvs, sal_Int32 * pnLen,
146         uno_memAlloc memAlloc, const OUString & rEnvDcp );
147 
148     bool isDisposing;
149 };
150 
151 namespace
152 {
153     struct theEnvironmentsData : public rtl::Static< EnvironmentsData, theEnvironmentsData > {};
154 }
155 
156 //==============================================================================
157 struct uno_DefaultEnvironment : public uno_ExtEnvironment
158 {
159     sal_Int32 nRef;
160     sal_Int32 nWeakRef;
161 
162     ::osl::Mutex mutex;
163     Ptr2ObjectMap aPtr2ObjectMap;
164     OId2ObjectMap aOId2ObjectMap;
165 
166     uno_DefaultEnvironment(
167         const OUString & rEnvDcp_, void * pContext_ );
168     ~uno_DefaultEnvironment();
169 };
170 
171 //______________________________________________________________________________
ObjectEntry(OUString const & rOId_)172 inline ObjectEntry::ObjectEntry( OUString const & rOId_ )
173     : oid( rOId_ ),
174       nRef( 0 ),
175       mixedObject( false )
176 {
177     aInterfaces.reserve( 2 );
178 }
179 
180 //______________________________________________________________________________
append(uno_DefaultEnvironment * pEnv,void * pInterface,typelib_InterfaceTypeDescription * pTypeDescr,uno_freeProxyFunc fpFreeProxy)181 inline void ObjectEntry::append(
182     uno_DefaultEnvironment * pEnv,
183     void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
184     uno_freeProxyFunc fpFreeProxy )
185 {
186     InterfaceEntry aNewEntry;
187     if (! fpFreeProxy)
188         (*pEnv->acquireInterface)( pEnv, pInterface );
189     aNewEntry.refCount = 1;
190     aNewEntry.pInterface = pInterface;
191     aNewEntry.fpFreeProxy = fpFreeProxy;
192     typelib_typedescription_acquire( (typelib_TypeDescription *) pTypeDescr );
193     aNewEntry.pTypeDescr = pTypeDescr;
194 
195     ::std::pair< Ptr2ObjectMap::iterator, bool > insertion(
196         pEnv->aPtr2ObjectMap.insert( Ptr2ObjectMap::value_type(
197                                          pInterface, this ) ) );
198     OSL_ASSERT( insertion.second ||
199                 (find( pInterface, 0 ) >= 0 &&
200                  // points to the same object entry:
201                  insertion.first->second == this) );
202     aInterfaces.push_back( aNewEntry );
203 }
204 
205 //______________________________________________________________________________
find(typelib_InterfaceTypeDescription * pTypeDescr_)206 inline InterfaceEntry * ObjectEntry::find(
207     typelib_InterfaceTypeDescription * pTypeDescr_ )
208 {
209     OSL_ASSERT( ! aInterfaces.empty() );
210     if (aInterfaces.empty())
211         return 0;
212 
213     // shortcut common case:
214     OUString const & type_name =
215         OUString::unacquired(
216             &((typelib_TypeDescription *) pTypeDescr_)->pTypeName );
217     if (type_name.equalsAsciiL(
218             RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ))
219     {
220         return &aInterfaces[ 0 ];
221     }
222 
223     ::std::size_t nSize = aInterfaces.size();
224     for ( ::std::size_t nPos = 0; nPos < nSize; ++nPos )
225     {
226         typelib_InterfaceTypeDescription * pITD =
227             aInterfaces[ nPos ].pTypeDescr;
228         while (pITD)
229         {
230             if (td_equals( pITD, pTypeDescr_ ))
231                 return &aInterfaces[ nPos ];
232             pITD = pITD->pBaseTypeDescription;
233         }
234     }
235     return 0;
236 }
237 
238 //______________________________________________________________________________
find(void * iface_ptr,::std::size_t pos)239 inline sal_Int32 ObjectEntry::find(
240     void * iface_ptr, ::std::size_t pos )
241 {
242     ::std::size_t size = aInterfaces.size();
243     for ( ; pos < size; ++pos )
244     {
245         if (aInterfaces[ pos ].pInterface == iface_ptr)
246             return pos;
247     }
248     return -1;
249 }
250 
251 extern "C"
252 {
253 
254 //------------------------------------------------------------------------------
defenv_registerInterface(uno_ExtEnvironment * pEnv,void ** ppInterface,rtl_uString * pOId,typelib_InterfaceTypeDescription * pTypeDescr)255 static void SAL_CALL defenv_registerInterface(
256     uno_ExtEnvironment * pEnv, void ** ppInterface,
257     rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
258 {
259     OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
260     OUString sOId( pOId );
261 
262     uno_DefaultEnvironment * that =
263         static_cast< uno_DefaultEnvironment * >( pEnv );
264     ::osl::ClearableMutexGuard guard( that->mutex );
265 
266     // try to insert dummy 0:
267     std::pair<OId2ObjectMap::iterator, bool> const insertion(
268         that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( sOId, 0 ) ) );
269     if (insertion.second)
270     {
271         ObjectEntry * pOEntry = new ObjectEntry( sOId );
272         insertion.first->second = pOEntry;
273         ++pOEntry->nRef; // another register call on object
274         pOEntry->append( that, *ppInterface, pTypeDescr, 0 );
275     }
276     else // object entry exists
277     {
278         ObjectEntry * pOEntry = insertion.first->second;
279         ++pOEntry->nRef; // another register call on object
280         InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
281 
282         if (pIEntry) // type entry exists
283         {
284             ++pIEntry->refCount;
285             if (pIEntry->pInterface != *ppInterface)
286             {
287                 void * pInterface = pIEntry->pInterface;
288                 (*pEnv->acquireInterface)( pEnv, pInterface );
289                 guard.clear();
290                 (*pEnv->releaseInterface)( pEnv, *ppInterface );
291                 *ppInterface = pInterface;
292             }
293         }
294         else
295         {
296             pOEntry->append( that, *ppInterface, pTypeDescr, 0 );
297         }
298     }
299 }
300 
301 //------------------------------------------------------------------------------
defenv_registerProxyInterface(uno_ExtEnvironment * pEnv,void ** ppInterface,uno_freeProxyFunc freeProxy,rtl_uString * pOId,typelib_InterfaceTypeDescription * pTypeDescr)302 static void SAL_CALL defenv_registerProxyInterface(
303     uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy,
304     rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
305 {
306     OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy,
307                 "### null ptr!" );
308     OUString sOId( pOId );
309 
310     uno_DefaultEnvironment * that =
311         static_cast< uno_DefaultEnvironment * >( pEnv );
312     ::osl::ClearableMutexGuard guard( that->mutex );
313 
314     // try to insert dummy 0:
315     std::pair<OId2ObjectMap::iterator, bool> const insertion(
316         that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( sOId, 0 ) ) );
317     if (insertion.second)
318     {
319         ObjectEntry * pOEntry = new ObjectEntry( sOId );
320         insertion.first->second = pOEntry;
321         ++pOEntry->nRef; // another register call on object
322         pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
323     }
324     else // object entry exists
325     {
326         ObjectEntry * pOEntry = insertion.first->second;
327 
328         // first registration was an original, then registerProxyInterface():
329         pOEntry->mixedObject |=
330             (!pOEntry->aInterfaces.empty() &&
331              pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0);
332 
333         ++pOEntry->nRef; // another register call on object
334         InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
335 
336         if (pIEntry) // type entry exists
337         {
338             if (pIEntry->pInterface == *ppInterface)
339             {
340                 ++pIEntry->refCount;
341             }
342             else
343             {
344                 void * pInterface = pIEntry->pInterface;
345                 (*pEnv->acquireInterface)( pEnv, pInterface );
346                 --pOEntry->nRef; // manual revoke of proxy to be freed
347                 guard.clear();
348                 (*freeProxy)( pEnv, *ppInterface );
349                 *ppInterface = pInterface;
350             }
351         }
352         else
353         {
354             pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
355         }
356     }
357 }
358 
359 //------------------------------------------------------------------------------
s_stub_defenv_revokeInterface(va_list * pParam)360 static void SAL_CALL s_stub_defenv_revokeInterface(va_list * pParam)
361 {
362 	uno_ExtEnvironment * pEnv       = va_arg(*pParam, uno_ExtEnvironment *);
363 	void               * pInterface = va_arg(*pParam, void *);
364 
365     OSL_ENSURE( pEnv && pInterface, "### null ptr!" );
366     uno_DefaultEnvironment * that =
367         static_cast< uno_DefaultEnvironment * >( pEnv );
368     ::osl::ClearableMutexGuard guard( that->mutex );
369 
370     Ptr2ObjectMap::const_iterator const iFind(
371         that->aPtr2ObjectMap.find( pInterface ) );
372     OSL_ASSERT( iFind != that->aPtr2ObjectMap.end() );
373     ObjectEntry * pOEntry = iFind->second;
374     if (! --pOEntry->nRef)
375     {
376         // cleanup maps
377         that->aOId2ObjectMap.erase( pOEntry->oid );
378         sal_Int32 nPos;
379         for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
380         {
381             that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface );
382         }
383 
384         // the last proxy interface of the environment might kill this
385         // environment, because of releasing its language binding!!!
386         guard.clear();
387 
388         // release interfaces
389         for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
390         {
391             InterfaceEntry const & rEntry = pOEntry->aInterfaces[nPos];
392             typelib_typedescription_release(
393                 (typelib_TypeDescription *) rEntry.pTypeDescr );
394             if (rEntry.fpFreeProxy) // is proxy or used interface?
395             {
396                 (*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface );
397             }
398             else
399             {
400                 (*pEnv->releaseInterface)( pEnv, rEntry.pInterface );
401             }
402         }
403 
404         delete pOEntry;
405     }
406     else if (pOEntry->mixedObject)
407     {
408         OSL_ASSERT( !pOEntry->aInterfaces.empty() &&
409                     pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0 );
410 
411         sal_Int32 index = pOEntry->find( pInterface, 1 );
412         OSL_ASSERT( index > 0 );
413         if (index > 0)
414         {
415             InterfaceEntry & entry = pOEntry->aInterfaces[ index ];
416             OSL_ASSERT( entry.pInterface == pInterface );
417             if (entry.fpFreeProxy != 0)
418             {
419                 --entry.refCount;
420                 if (entry.refCount == 0)
421                 {
422                     uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy;
423                     typelib_TypeDescription * pTypeDescr =
424                         reinterpret_cast< typelib_TypeDescription * >(
425                             entry.pTypeDescr );
426 
427                     pOEntry->aInterfaces.erase(
428                         pOEntry->aInterfaces.begin() + index );
429                     if (pOEntry->find( pInterface, index ) < 0)
430                     {
431                         // proxy ptr not registered for another interface:
432                         // remove from ptr map
433 #if OSL_DEBUG_LEVEL > 0
434                         ::std::size_t erased =
435 #endif
436                               that->aPtr2ObjectMap.erase( pInterface );
437                         OSL_ASSERT( erased == 1 );
438                     }
439 
440                     guard.clear();
441 
442                     typelib_typedescription_release( pTypeDescr );
443                     (*fpFreeProxy)( pEnv, pInterface );
444                 }
445             }
446         }
447     }
448 }
449 
defenv_revokeInterface(uno_ExtEnvironment * pEnv,void * pInterface)450 static void SAL_CALL defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface)
451 {
452 	uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface);
453 }
454 
455 //------------------------------------------------------------------------------
defenv_getObjectIdentifier(uno_ExtEnvironment * pEnv,rtl_uString ** ppOId,void * pInterface)456 static void SAL_CALL defenv_getObjectIdentifier(
457     uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
458 {
459     OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
460     if (*ppOId)
461     {
462         ::rtl_uString_release( *ppOId );
463         *ppOId = 0;
464     }
465 
466     uno_DefaultEnvironment * that =
467         static_cast< uno_DefaultEnvironment * >( pEnv );
468     ::osl::ClearableMutexGuard guard( that->mutex );
469 
470     Ptr2ObjectMap::const_iterator const iFind(
471         that->aPtr2ObjectMap.find( pInterface ) );
472     if (iFind == that->aPtr2ObjectMap.end())
473     {
474         guard.clear();
475         (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface );
476     }
477     else
478     {
479         rtl_uString * hstr = iFind->second->oid.pData;
480         rtl_uString_acquire( hstr );
481         *ppOId = hstr;
482     }
483 }
484 
485 //------------------------------------------------------------------------------
defenv_getRegisteredInterface(uno_ExtEnvironment * pEnv,void ** ppInterface,rtl_uString * pOId,typelib_InterfaceTypeDescription * pTypeDescr)486 static void SAL_CALL defenv_getRegisteredInterface(
487     uno_ExtEnvironment * pEnv, void ** ppInterface,
488     rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
489 {
490     OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
491     if (*ppInterface)
492     {
493         (*pEnv->releaseInterface)( pEnv, *ppInterface );
494         *ppInterface = 0;
495     }
496 
497     OUString sOId( pOId );
498     uno_DefaultEnvironment * that =
499         static_cast< uno_DefaultEnvironment * >( pEnv );
500     ::osl::MutexGuard guard( that->mutex );
501 
502     OId2ObjectMap::const_iterator const iFind
503         ( that->aOId2ObjectMap.find( sOId ) );
504     if (iFind != that->aOId2ObjectMap.end())
505     {
506         InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr );
507         if (pIEntry)
508         {
509             (*pEnv->acquireInterface)( pEnv, pIEntry->pInterface );
510             *ppInterface = pIEntry->pInterface;
511         }
512     }
513 }
514 
515 //------------------------------------------------------------------------------
defenv_getRegisteredInterfaces(uno_ExtEnvironment * pEnv,void *** pppInterfaces,sal_Int32 * pnLen,uno_memAlloc memAlloc)516 static void SAL_CALL defenv_getRegisteredInterfaces(
517     uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen,
518     uno_memAlloc memAlloc )
519 {
520     OSL_ENSURE( pEnv && pppInterfaces && pnLen && memAlloc, "### null ptr!" );
521     uno_DefaultEnvironment * that =
522         static_cast< uno_DefaultEnvironment * >( pEnv );
523     ::osl::MutexGuard guard( that->mutex );
524 
525     sal_Int32 nLen = that->aPtr2ObjectMap.size();
526     sal_Int32 nPos = 0;
527     void ** ppInterfaces = (void **) (*memAlloc)( nLen * sizeof (void *) );
528 
529     Ptr2ObjectMap::const_iterator iPos( that->aPtr2ObjectMap.begin() );
530     Ptr2ObjectMap::const_iterator const iEnd( that->aPtr2ObjectMap.end() );
531     while (iPos != iEnd)
532     {
533         (*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos++] = (*iPos).first );
534         ++iPos;
535     }
536 
537     *pppInterfaces = ppInterfaces;
538     *pnLen = nLen;
539 }
540 
541 //------------------------------------------------------------------------------
defenv_acquire(uno_Environment * pEnv)542 static void SAL_CALL defenv_acquire( uno_Environment * pEnv )
543 {
544     uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
545     ::osl_incrementInterlockedCount( &that->nWeakRef );
546     ::osl_incrementInterlockedCount( &that->nRef );
547 }
548 
549 //------------------------------------------------------------------------------
defenv_release(uno_Environment * pEnv)550 static void SAL_CALL defenv_release( uno_Environment * pEnv )
551 {
552     uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
553     if (! ::osl_decrementInterlockedCount( &that->nRef ))
554     {
555         // invoke dispose callback
556         if (pEnv->environmentDisposing)
557         {
558             (*pEnv->environmentDisposing)( pEnv );
559         }
560 
561         OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" );
562     }
563     // free memory if no weak refs left
564     if (! ::osl_decrementInterlockedCount( &that->nWeakRef ))
565     {
566         delete that;
567     }
568 }
569 
570 //------------------------------------------------------------------------------
defenv_acquireWeak(uno_Environment * pEnv)571 static void SAL_CALL defenv_acquireWeak( uno_Environment * pEnv )
572 {
573     uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
574     ::osl_incrementInterlockedCount( &that->nWeakRef );
575 }
576 
577 //------------------------------------------------------------------------------
defenv_releaseWeak(uno_Environment * pEnv)578 static void SAL_CALL defenv_releaseWeak( uno_Environment * pEnv )
579 {
580     uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
581     if (! ::osl_decrementInterlockedCount( &that->nWeakRef ))
582     {
583         delete that;
584     }
585 }
586 
587 //------------------------------------------------------------------------------
defenv_harden(uno_Environment ** ppHardEnv,uno_Environment * pEnv)588 static void SAL_CALL defenv_harden(
589     uno_Environment ** ppHardEnv, uno_Environment * pEnv )
590 {
591     if (*ppHardEnv)
592     {
593         (*(*ppHardEnv)->release)( *ppHardEnv );
594         *ppHardEnv = 0;
595     }
596 
597     EnvironmentsData & rData = theEnvironmentsData::get();
598 
599     if (rData.isDisposing)
600         return;
601 
602     uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
603     {
604     ::osl::MutexGuard guard( rData.mutex );
605     if (1 == ::osl_incrementInterlockedCount( &that->nRef )) // is dead
606     {
607         that->nRef = 0;
608         return;
609     }
610     }
611     ::osl_incrementInterlockedCount( &that->nWeakRef );
612     *ppHardEnv = pEnv;
613 }
614 
615 //------------------------------------------------------------------------------
defenv_dispose(uno_Environment *)616 static void SAL_CALL defenv_dispose( uno_Environment * )
617 {
618 }
619 }
620 
621 //______________________________________________________________________________
uno_DefaultEnvironment(const OUString & rEnvDcp_,void * pContext_)622 uno_DefaultEnvironment::uno_DefaultEnvironment(
623     const OUString & rEnvDcp_, void * pContext_ )
624     : nRef( 0 ),
625       nWeakRef( 0 )
626 {
627     uno_Environment * that = reinterpret_cast< uno_Environment * >(this);
628     that->pReserved = 0;
629     // functions
630     that->acquire = defenv_acquire;
631     that->release = defenv_release;
632     that->acquireWeak = defenv_acquireWeak;
633     that->releaseWeak = defenv_releaseWeak;
634     that->harden = defenv_harden;
635     that->dispose = defenv_dispose;
636     that->pExtEnv = this;
637     // identifier
638     ::rtl_uString_acquire( rEnvDcp_.pData );
639     that->pTypeName = rEnvDcp_.pData;
640     that->pContext = pContext_;
641 
642     // will be late initialized
643     that->environmentDisposing = 0;
644 
645     uno_ExtEnvironment::registerInterface = defenv_registerInterface;
646     uno_ExtEnvironment::registerProxyInterface = defenv_registerProxyInterface;
647     uno_ExtEnvironment::revokeInterface = defenv_revokeInterface;
648     uno_ExtEnvironment::getObjectIdentifier = defenv_getObjectIdentifier;
649     uno_ExtEnvironment::getRegisteredInterface = defenv_getRegisteredInterface;
650     uno_ExtEnvironment::getRegisteredInterfaces =
651         defenv_getRegisteredInterfaces;
652 
653 }
654 
655 //______________________________________________________________________________
~uno_DefaultEnvironment()656 uno_DefaultEnvironment::~uno_DefaultEnvironment()
657 {
658     ::rtl_uString_release( ((uno_Environment *) this)->pTypeName );
659 }
660 
661 //==============================================================================
writeLine(void * stream,const sal_Char * pLine,const sal_Char * pFilter)662 static void writeLine(
663     void * stream, const sal_Char * pLine, const sal_Char * pFilter )
664 {
665     if (pFilter && *pFilter)
666     {
667         // lookup pFilter in pLine
668         while (*pLine)
669         {
670             if (*pLine == *pFilter)
671             {
672                 sal_Int32 nPos = 1;
673                 while (pLine[nPos] && pFilter[nPos] == pLine[nPos])
674                 {
675                     ++nPos;
676                 }
677                 if (! pFilter[nPos])
678                 {
679                     if (stream)
680                     {
681                         fprintf( (FILE *) stream, "%s\n", pLine );
682                     }
683                     else
684                     {
685                         OSL_TRACE( pLine );
686                         OSL_TRACE( "\n" );
687                     }
688                 }
689             }
690             ++pLine;
691         }
692     }
693     else
694     {
695         if (stream)
696         {
697             fprintf( (FILE *) stream, "%s\n", pLine );
698         }
699         else
700         {
701             fprintf( stderr, "%s\n", pLine );
702         }
703     }
704 }
705 
706 //==============================================================================
writeLine(void * stream,const OUString & rLine,const sal_Char * pFilter)707 static void writeLine(
708     void * stream, const OUString & rLine, const sal_Char * pFilter )
709 {
710     ::rtl::OString aLine( ::rtl::OUStringToOString(
711                               rLine, RTL_TEXTENCODING_ASCII_US ) );
712     writeLine( stream, aLine.getStr(), pFilter );
713 }
714 
715 //##############################################################################
uno_dumpEnvironment(void * stream,uno_Environment * pEnv,const sal_Char * pFilter)716 extern "C" void SAL_CALL uno_dumpEnvironment(
717     void * stream, uno_Environment * pEnv, const sal_Char * pFilter )
718     SAL_THROW_EXTERN_C()
719 {
720     OSL_ENSURE( pEnv, "### null ptr!" );
721     ::rtl::OUStringBuffer buf;
722 
723     if (! pEnv->pExtEnv)
724     {
725         writeLine( stream, "###################################"
726                    "###########################################", pFilter );
727         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment: ") );
728         buf.append( pEnv->pTypeName );
729         writeLine( stream, buf.makeStringAndClear(), pFilter );
730         writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter );
731         return;
732     }
733 
734     writeLine( stream, "########################################"
735                "######################################", pFilter );
736     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment dump: ") );
737     buf.append( pEnv->pTypeName );
738     writeLine( stream, buf.makeStringAndClear(), pFilter );
739 
740     uno_DefaultEnvironment * that =
741         reinterpret_cast< uno_DefaultEnvironment * >(pEnv);
742     ::osl::MutexGuard guard( that->mutex );
743 
744     Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap );
745     OId2ObjectMap::const_iterator iPos( that->aOId2ObjectMap.begin() );
746     while (iPos != that->aOId2ObjectMap.end())
747     {
748         ObjectEntry * pOEntry = iPos->second;
749 
750         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("+ ") );
751         if (pOEntry->mixedObject)
752             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("mixed ") );
753         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("object entry: nRef=") );
754         buf.append( pOEntry->nRef, 10 );
755         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; oid=\"") );
756         buf.append( pOEntry->oid );
757         buf.append( (sal_Unicode) '\"' );
758         writeLine( stream, buf.makeStringAndClear(), pFilter );
759 
760         for ( ::std::size_t nPos = 0;
761               nPos < pOEntry->aInterfaces.size(); ++nPos )
762         {
763             const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos];
764 
765             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("  - ") );
766             buf.append(
767                 ((typelib_TypeDescription *) rIEntry.pTypeDescr)->pTypeName );
768             if (rIEntry.fpFreeProxy)
769             {
770                 buf.appendAscii(
771                     RTL_CONSTASCII_STRINGPARAM("; proxy free=0x") );
772                 buf.append(
773                     reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 );
774             }
775             else
776             {
777                 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; original") );
778             }
779             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; ptr=0x") );
780             buf.append(
781                 reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 );
782 
783             if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0)
784             {
785                 ::std::size_t erased = ptr2obj.erase( rIEntry.pInterface );
786                 if (erased != 1)
787                 {
788                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
789                                          " (ptr not found in map!)") );
790                 }
791             }
792             writeLine( stream, buf.makeStringAndClear(), pFilter );
793         }
794         ++iPos;
795     }
796     if (! ptr2obj.empty())
797         writeLine( stream, "ptr map inconsistency!!!", pFilter );
798     writeLine( stream, "#####################################"
799                "#########################################", pFilter );
800 }
801 
802 //##############################################################################
uno_dumpEnvironmentByName(void * stream,rtl_uString * pEnvDcp,const sal_Char * pFilter)803 extern "C" void SAL_CALL uno_dumpEnvironmentByName(
804     void * stream, rtl_uString * pEnvDcp, const sal_Char * pFilter )
805     SAL_THROW_EXTERN_C()
806 {
807     uno_Environment * pEnv = 0;
808     uno_getEnvironment( &pEnv, pEnvDcp, 0 );
809     if (pEnv)
810     {
811         ::uno_dumpEnvironment( stream, pEnv, pFilter );
812         (*pEnv->release)( pEnv );
813     }
814     else
815     {
816         ::rtl::OUStringBuffer buf( 32 );
817         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment \"") );
818         buf.append( pEnvDcp );
819         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" does not exist!") );
820         writeLine( stream, buf.makeStringAndClear(), pFilter );
821     }
822 }
823 
824 //------------------------------------------------------------------------------
unoenv_getStaticOIdPart()825 inline static const OUString & unoenv_getStaticOIdPart()
826 {
827     static OUString * s_pStaticOidPart = 0;
828     if (! s_pStaticOidPart)
829     {
830         ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
831         if (! s_pStaticOidPart)
832         {
833             ::rtl::OUStringBuffer aRet( 64 );
834             aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") );
835             // pid
836             oslProcessInfo info;
837             info.Size = sizeof(oslProcessInfo);
838             if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER, &info ) ==
839                 osl_Process_E_None)
840             {
841                 aRet.append( (sal_Int64)info.Ident, 16 );
842             }
843             else
844             {
845                 aRet.appendAscii(
846                     RTL_CONSTASCII_STRINGPARAM("unknown process id") );
847             }
848             // good guid
849             sal_uInt8 ar[16];
850             ::rtl_getGlobalProcessId( ar );
851             aRet.append( (sal_Unicode)';' );
852             for ( sal_Int32 i = 0; i < 16; ++i )
853                 aRet.append( (sal_Int32)ar[i], 16 );
854 
855             static OUString s_aStaticOidPart( aRet.makeStringAndClear() );
856             s_pStaticOidPart = &s_aStaticOidPart;
857         }
858     }
859     return *s_pStaticOidPart;
860 }
861 
862 extern "C"
863 {
864 
865 //------------------------------------------------------------------------------
unoenv_computeObjectIdentifier(uno_ExtEnvironment * pEnv,rtl_uString ** ppOId,void * pInterface)866 static void SAL_CALL unoenv_computeObjectIdentifier(
867     uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
868 {
869     OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
870     if (*ppOId)
871     {
872         ::rtl_uString_release( *ppOId );
873         *ppOId = 0;
874     }
875 
876     uno_Interface * pUnoI = (uno_Interface *)
877         ::cppu::binuno_queryInterface(
878             pInterface, *typelib_static_type_getByTypeClass(
879                 typelib_TypeClass_INTERFACE ) );
880     if (0 != pUnoI)
881     {
882         (*pUnoI->release)( pUnoI );
883         // interface
884         ::rtl::OUStringBuffer oid( 64 );
885         oid.append( reinterpret_cast< sal_Int64 >(pUnoI), 16 );
886         oid.append( static_cast< sal_Unicode >(';') );
887         // environment[context]
888         oid.append( ((uno_Environment *) pEnv)->pTypeName );
889         oid.append( static_cast< sal_Unicode >('[') );
890         oid.append( reinterpret_cast< sal_Int64 >(
891                         reinterpret_cast<
892                         uno_Environment * >(pEnv)->pContext ), 16 );
893         // process;good guid
894         oid.append( unoenv_getStaticOIdPart() );
895         OUString aStr( oid.makeStringAndClear() );
896         ::rtl_uString_acquire( *ppOId = aStr.pData );
897     }
898 }
899 
900 //==============================================================================
unoenv_acquireInterface(uno_ExtEnvironment *,void * pUnoI_)901 static void SAL_CALL unoenv_acquireInterface(
902     uno_ExtEnvironment *, void * pUnoI_ )
903 {
904     uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_);
905     (*pUnoI->acquire)( pUnoI );
906 }
907 
908 //==============================================================================
unoenv_releaseInterface(uno_ExtEnvironment *,void * pUnoI_)909 static void SAL_CALL unoenv_releaseInterface(
910     uno_ExtEnvironment *, void * pUnoI_ )
911 {
912     uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_);
913     (*pUnoI->release)( pUnoI );
914 }
915 }
916 
917 //______________________________________________________________________________
~EnvironmentsData()918 EnvironmentsData::~EnvironmentsData()
919 {
920     ::osl::MutexGuard guard( mutex );
921     isDisposing = true;
922 
923     for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
924           iPos != aName2EnvMap.end(); ++iPos )
925     {
926         uno_Environment * pWeak = iPos->second;
927         uno_Environment * pHard = 0;
928         (*pWeak->harden)( &pHard, pWeak );
929         (*pWeak->releaseWeak)( pWeak );
930 
931         if (pHard)
932         {
933 #if OSL_DEBUG_LEVEL > 1
934             ::uno_dumpEnvironment( 0, pHard, 0 );
935 #endif
936             (*pHard->dispose)( pHard ); // send explicit dispose
937             (*pHard->release)( pHard );
938         }
939     }
940 }
941 
942 //______________________________________________________________________________
getEnvironment(uno_Environment ** ppEnv,const OUString & rEnvDcp,void * pContext)943 inline void EnvironmentsData::getEnvironment(
944     uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext )
945 {
946     if (*ppEnv)
947     {
948         (*(*ppEnv)->release)( *ppEnv );
949         *ppEnv = 0;
950     }
951 
952     OUString aKey(
953         OUString::valueOf( reinterpret_cast< sal_IntPtr >(pContext) ) );
954     aKey += rEnvDcp;
955 
956     // try to find registered mapping
957     OUString2EnvironmentMap::const_iterator const iFind(
958         aName2EnvMap.find( aKey ) );
959     if (iFind != aName2EnvMap.end())
960     {
961         uno_Environment * pWeak = iFind->second;
962         (*pWeak->harden)( ppEnv, pWeak );
963     }
964 }
965 
966 //______________________________________________________________________________
registerEnvironment(uno_Environment ** ppEnv)967 inline void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv )
968 {
969     OSL_ENSURE( ppEnv, "### null ptr!" );
970     uno_Environment * pEnv =  *ppEnv;
971 
972     OUString aKey(
973         OUString::valueOf( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) );
974     aKey += pEnv->pTypeName;
975 
976     // try to find registered environment
977     OUString2EnvironmentMap::const_iterator const iFind(
978         aName2EnvMap.find( aKey ) );
979     if (iFind == aName2EnvMap.end())
980     {
981         (*pEnv->acquireWeak)( pEnv );
982         ::std::pair< OUString2EnvironmentMap::iterator, bool > insertion(
983             aName2EnvMap.insert(
984                 OUString2EnvironmentMap::value_type( aKey, pEnv ) ) );
985         OSL_ENSURE(
986             insertion.second, "### insertion of env into map failed?!" );
987     }
988     else
989     {
990         uno_Environment * pHard = 0;
991         uno_Environment * pWeak = iFind->second;
992         (*pWeak->harden)( &pHard, pWeak );
993         if (pHard)
994         {
995             if (pEnv)
996                 (*pEnv->release)( pEnv );
997             *ppEnv = pHard;
998         }
999         else // registered one is dead
1000         {
1001             (*pWeak->releaseWeak)( pWeak );
1002             (*pEnv->acquireWeak)( pEnv );
1003             aName2EnvMap[ aKey ] = pEnv;
1004         }
1005     }
1006 }
1007 
1008 //______________________________________________________________________________
getRegisteredEnvironments(uno_Environment *** pppEnvs,sal_Int32 * pnLen,uno_memAlloc memAlloc,const OUString & rEnvDcp)1009 inline void EnvironmentsData::getRegisteredEnvironments(
1010     uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
1011     const OUString & rEnvDcp )
1012 {
1013     OSL_ENSURE( pppEnvs && pnLen && memAlloc, "### null ptr!" );
1014 
1015     // max size
1016     uno_Environment ** ppFound = (uno_Environment **)alloca(
1017         sizeof(uno_Environment *) * aName2EnvMap.size() );
1018     sal_Int32 nSize = 0;
1019 
1020     // find matching environment
1021     for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
1022           iPos != aName2EnvMap.end(); ++iPos )
1023     {
1024         uno_Environment * pWeak = iPos->second;
1025         if (!rEnvDcp.getLength() ||
1026             rEnvDcp.equals( pWeak->pTypeName ))
1027         {
1028             ppFound[nSize] = 0;
1029             (*pWeak->harden)( &ppFound[nSize], pWeak );
1030             if (ppFound[nSize])
1031                 ++nSize;
1032         }
1033     }
1034 
1035     *pnLen = nSize;
1036     if (nSize)
1037     {
1038         *pppEnvs = (uno_Environment **) (*memAlloc)(
1039             sizeof (uno_Environment *) * nSize );
1040         OSL_ASSERT( *pppEnvs );
1041         while (nSize--)
1042         {
1043             (*pppEnvs)[nSize] = ppFound[nSize];
1044         }
1045     }
1046     else
1047     {
1048         *pppEnvs = 0;
1049     }
1050 }
1051 
loadEnv(OUString const & cLibStem,uno_Environment * pEnv,void *)1052 static bool loadEnv(OUString const  & cLibStem,
1053 					uno_Environment * pEnv,
1054 					void            * /*pContext*/)
1055 {
1056 	// late init with some code from matching uno language binding
1057 	// will be unloaded by environment
1058 	oslModule hMod = cppu::detail::loadModule( cLibStem );
1059 
1060 	if (!hMod)
1061 		return false;
1062 
1063 	OUString aSymbolName(RTL_CONSTASCII_USTRINGPARAM(UNO_INIT_ENVIRONMENT));
1064 	uno_initEnvironmentFunc fpInit = (uno_initEnvironmentFunc)
1065 		::osl_getFunctionSymbol( hMod, aSymbolName.pData );
1066 	if (!fpInit)
1067 	{
1068 		::osl_unloadModule( hMod );
1069 		return false;
1070 	}
1071 
1072 	(*fpInit)( pEnv ); // init of environment
1073 	::rtl_registerModuleForUnloading( hMod );
1074 
1075 	return true;
1076 }
1077 
1078 
1079 extern "C"
1080 {
1081 
1082 //------------------------------------------------------------------------------
initDefaultEnvironment(const OUString & rEnvDcp,void * pContext)1083 static uno_Environment * initDefaultEnvironment(
1084     const OUString & rEnvDcp, void * pContext )
1085 {
1086     uno_Environment * pEnv = &(new uno_DefaultEnvironment( rEnvDcp, pContext ))->aBase;
1087 	(*pEnv->acquire)( pEnv );
1088 
1089 	OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp);
1090 
1091     // create default environment
1092     if (envTypeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ))
1093     {
1094         uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
1095 		that->computeObjectIdentifier = unoenv_computeObjectIdentifier;
1096 		that->acquireInterface = unoenv_acquireInterface;
1097 		that->releaseInterface = unoenv_releaseInterface;
1098 
1099 		OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp);
1100 		if (envPurpose.getLength())
1101 		{
1102 			rtl::OUString libStem = envPurpose.copy(envPurpose.lastIndexOf(':') + 1);
1103 			libStem += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_uno_uno") );
1104 
1105 			if(!loadEnv(libStem, pEnv, pContext))
1106 			{
1107 				pEnv->release(pEnv);
1108 				return NULL;
1109 			}
1110 		}
1111     }
1112     else
1113     {
1114         // late init with some code from matching uno language binding
1115         ::rtl::OUStringBuffer aLibName( 16 );
1116         aLibName.append( envTypeName );
1117         aLibName.appendAscii( RTL_CONSTASCII_STRINGPARAM("_uno" ) );
1118         OUString aStr( aLibName.makeStringAndClear() );
1119 
1120 		if (!loadEnv(aStr, pEnv, pContext))
1121 		{
1122 			pEnv->release(pEnv);
1123 			return NULL;
1124 		}
1125     }
1126 
1127     return pEnv;
1128 }
1129 
1130 //##############################################################################
uno_createEnvironment(uno_Environment ** ppEnv,rtl_uString * pEnvDcp,void * pContext)1131 void SAL_CALL uno_createEnvironment(
1132     uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1133     SAL_THROW_EXTERN_C()
1134 {
1135     OSL_ENSURE( ppEnv, "### null ptr!" );
1136     if (*ppEnv)
1137         (*(*ppEnv)->release)( *ppEnv );
1138 
1139     OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1140     *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1141 }
1142 
1143 //##############################################################################
uno_direct_getEnvironment(uno_Environment ** ppEnv,rtl_uString * pEnvDcp,void * pContext)1144 void SAL_CALL uno_direct_getEnvironment(
1145     uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1146     SAL_THROW_EXTERN_C()
1147 {
1148     OSL_ENSURE( ppEnv, "### null ptr!" );
1149     OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1150 
1151     EnvironmentsData & rData = theEnvironmentsData::get();
1152 
1153     ::osl::MutexGuard guard( rData.mutex );
1154     rData.getEnvironment( ppEnv, rEnvDcp, pContext );
1155     if (! *ppEnv)
1156     {
1157         *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1158         if (*ppEnv)
1159         {
1160             // register new environment:
1161             rData.registerEnvironment( ppEnv );
1162         }
1163     }
1164 }
1165 
1166 //##############################################################################
uno_getRegisteredEnvironments(uno_Environment *** pppEnvs,sal_Int32 * pnLen,uno_memAlloc memAlloc,rtl_uString * pEnvDcp)1167 void SAL_CALL uno_getRegisteredEnvironments(
1168     uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
1169     rtl_uString * pEnvDcp )
1170     SAL_THROW_EXTERN_C()
1171 {
1172     EnvironmentsData & rData = theEnvironmentsData::get();
1173 
1174     ::osl::MutexGuard guard( rData.mutex );
1175     rData.getRegisteredEnvironments(
1176         pppEnvs, pnLen, memAlloc,
1177         (pEnvDcp ? OUString(pEnvDcp) : OUString()) );
1178 }
1179 
1180 } // extern "C"
1181 
1182 }
1183 
1184