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 ()__anon165dcd360111::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 ()__anon165dcd360111::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__anon165dcd360111::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 const & rOId = OUString::unacquired( &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( rOId, 0 ) ) );
269 if (insertion.second)
270 {
271 ObjectEntry * pOEntry = new ObjectEntry( rOId );
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 const & rOId = OUString::unacquired( &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( rOId, 0 ) ) );
317 if (insertion.second)
318 {
319 ObjectEntry * pOEntry = new ObjectEntry( rOId );
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 const & rOId = OUString::unacquired( &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( rOId ) );
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