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