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
21 #include <cppu/helper/purpenv/Environment.hxx>
22
23 #include <osl/diagnose.h>
24 #include <sal/log.hxx>
25 #include <uno/lbnames.h>
26 #include <cppu/Enterable.hxx>
27
28 #include <typelib/typedescription.h>
29 #include <osl/interlck.h>
30 #include <memory>
31
32 extern "C" {
33 typedef void EnvFun_P (uno_Environment *);
34 typedef void EnvFun_PP_P(uno_Environment ** ppHardEnv, uno_Environment *);
35 typedef void ExtEnv_registerProxyInterface (uno_ExtEnvironment *,
36 void ** ppProxy,
37 uno_freeProxyFunc freeProxy,
38 rtl_uString * pOId,
39 typelib_InterfaceTypeDescription * pTypeDescr);
40 typedef void ExtEnv_revokeInterface (uno_ExtEnvironment *,
41 void * pInterface);
42 typedef void ExtEnv_getObjectIdentifier (uno_ExtEnvironment *,
43 rtl_uString **,
44 void *);
45 typedef void ExtEnv_getRegisteredInterface (uno_ExtEnvironment *,
46 void **,
47 rtl_uString *,
48 typelib_InterfaceTypeDescription *);
49 typedef void ExtEnv_getRegisteredInterfaces(uno_ExtEnvironment *,
50 void *** pppInterfaces,
51 sal_Int32 * pnLen,
52 uno_memAlloc memAlloc);
53 typedef void ExtEnv_computeObjectIdentifier(uno_ExtEnvironment *,
54 rtl_uString ** ppOId,
55 void * pInterface);
56 typedef void ExtEnv_acquireInterface (uno_ExtEnvironment *,
57 void * pInterface);
58 typedef void ExtEnv_releaseInterface (uno_ExtEnvironment *,
59 void * pInterface);
60 }
61
62 class Base : public cppu::Enterable
63 {
64 public:
65 explicit Base(uno_Environment * pEnv, cppu::Enterable * pEnterable);
66
67 void acquireWeak();
68 void releaseWeak();
69 void harden (uno_Environment ** ppHardEnv);
70 void acquire();
71 void release();
72
73 void registerProxyInterface (void ** ppProxy,
74 uno_freeProxyFunc freeProxy,
75 OUString const & oid,
76 typelib_InterfaceTypeDescription * pTypeDescr);
77 void revokeInterface (void * pInterface);
78 void getObjectIdentifier (void * pInterface,
79 OUString * pOid);
80 void getRegisteredInterface (void **,
81 OUString const & oid,
82 typelib_InterfaceTypeDescription *);
83 void getRegisteredInterfaces(void ***,
84 sal_Int32 * pnLen,
85 uno_memAlloc memAlloc);
86 void computeObjectIdentifier(void * pInterface,
87 OUString * pOid);
88 void acquireInterface (void * pInterface);
89 void releaseInterface (void * pInterface);
90
91 virtual void v_enter() override;
92 virtual void v_leave() override;
93 virtual void v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam) override;
94 virtual void v_callOut_v (uno_EnvCallee * pCallee, va_list * pParam) override;
95 virtual bool v_isValid (OUString * pReason) override;
96
97 protected:
98 oslInterlockedCount m_nRef;
99 uno_Environment * m_pEnv;
100 std::unique_ptr<cppu::Enterable> m_pEnterable;
101
102 EnvFun_P * m_env_acquire;
103 EnvFun_P * m_env_release;
104 EnvFun_PP_P * m_env_harden;
105 EnvFun_P * m_env_acquireWeak;
106 EnvFun_P * m_env_releaseWeak;
107
108 ExtEnv_registerProxyInterface * m_env_registerProxyInterface;
109 ExtEnv_revokeInterface * m_env_revokeInterface;
110 ExtEnv_getObjectIdentifier * m_env_getObjectIdentifier;
111 ExtEnv_getRegisteredInterface * m_env_getRegisteredInterface;
112 ExtEnv_getRegisteredInterfaces * m_env_getRegisteredInterfaces;
113 ExtEnv_computeObjectIdentifier * m_env_computeObjectIdentifier;
114 ExtEnv_acquireInterface * m_env_acquireInterface;
115 ExtEnv_releaseInterface * m_env_releaseInterface;
116
117 virtual ~Base() override;
118 };
119
120 extern "C" {
s_acquire(uno_Environment * pEnv)121 static void s_acquire(uno_Environment * pEnv) //SAL_THROW_EXTERN_C()
122 {
123 Base * pBase = static_cast<Base *>(pEnv->pReserved);
124 pBase->acquire();
125 }
126
s_release(uno_Environment * pEnv)127 static void s_release(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
128 {
129 Base * pBase = static_cast<Base *>(pEnv->pReserved);
130 pBase->release();
131 }
132
s_harden(uno_Environment ** ppHardEnv,uno_Environment * pEnv)133 static void s_harden(uno_Environment ** ppHardEnv, uno_Environment * pEnv) SAL_THROW_EXTERN_C()
134 {
135 Base * pBase = static_cast<Base *>(pEnv->pReserved);
136 pBase->harden(ppHardEnv);
137 }
138
s_acquireWeak(uno_Environment * pEnv)139 static void s_acquireWeak(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
140 {
141 Base * pBase = static_cast<Base *>(pEnv->pReserved);
142 pBase->acquireWeak();
143 }
144
s_releaseWeak(uno_Environment * pEnv)145 static void s_releaseWeak(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
146 {
147 Base * pBase = static_cast<Base *>(pEnv->pReserved);
148 pBase->releaseWeak();
149 }
150
151
s_registerProxyInterface(uno_ExtEnvironment * pExtEnv,void ** ppProxy,uno_freeProxyFunc freeProxy,rtl_uString * pOId,typelib_InterfaceTypeDescription * pTypeDescr)152 static void s_registerProxyInterface(uno_ExtEnvironment * pExtEnv,
153 void ** ppProxy,
154 uno_freeProxyFunc freeProxy,
155 rtl_uString * pOId,
156 typelib_InterfaceTypeDescription * pTypeDescr)
157 {
158 Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
159 pBase->registerProxyInterface(ppProxy, freeProxy, pOId, pTypeDescr);
160 }
161
s_revokeInterface(uno_ExtEnvironment * pExtEnv,void * pInterface)162 static void s_revokeInterface(uno_ExtEnvironment * pExtEnv, void * pInterface)
163 {
164 Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
165 pBase->revokeInterface(pInterface);
166 }
167
s_getObjectIdentifier(uno_ExtEnvironment * pExtEnv,rtl_uString ** ppOId,void * pInterface)168 static void s_getObjectIdentifier(uno_ExtEnvironment * pExtEnv,
169 rtl_uString ** ppOId,
170 void * pInterface)
171 {
172 Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
173 pBase->getObjectIdentifier(pInterface, reinterpret_cast<OUString *>(ppOId));
174 }
175
s_getRegisteredInterface(uno_ExtEnvironment * pExtEnv,void ** ppInterface,rtl_uString * pOId,typelib_InterfaceTypeDescription * pTypeDescr)176 static void s_getRegisteredInterface(uno_ExtEnvironment * pExtEnv,
177 void ** ppInterface,
178 rtl_uString * pOId,
179 typelib_InterfaceTypeDescription * pTypeDescr)
180 {
181 Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
182 pBase->getRegisteredInterface(ppInterface, pOId, pTypeDescr);
183 }
184
s_getRegisteredInterfaces(uno_ExtEnvironment * pExtEnv,void *** pppInterface,sal_Int32 * pnLen,uno_memAlloc memAlloc)185 static void s_getRegisteredInterfaces(uno_ExtEnvironment * pExtEnv,
186 void *** pppInterface,
187 sal_Int32 * pnLen,
188 uno_memAlloc memAlloc)
189 {
190 Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
191 pBase->getRegisteredInterfaces(pppInterface, pnLen, memAlloc);
192 }
193
s_computeObjectIdentifier(uno_ExtEnvironment * pExtEnv,rtl_uString ** ppOId,void * pInterface)194 static void s_computeObjectIdentifier(uno_ExtEnvironment * pExtEnv,
195 rtl_uString ** ppOId,
196 void * pInterface)
197 {
198 Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
199 pBase->computeObjectIdentifier(pInterface, reinterpret_cast<OUString *>(ppOId));
200 }
201
s_acquireInterface(uno_ExtEnvironment * pExtEnv,void * pInterface)202 static void s_acquireInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) {
203 Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
204 pBase->acquireInterface(pInterface);
205 }
206
s_releaseInterface(uno_ExtEnvironment * pExtEnv,void * pInterface)207 static void s_releaseInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) {
208 Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
209 pBase->releaseInterface(pInterface);
210 }
211
212 }
213
Base(uno_Environment * pEnv,cppu::Enterable * pEnterable)214 Base::Base(uno_Environment * pEnv, cppu::Enterable * pEnterable)
215 :m_nRef(1),
216 m_pEnv(pEnv),
217 m_pEnterable (pEnterable),
218 m_env_acquire (pEnv->acquire),
219 m_env_release (pEnv->release),
220 m_env_harden (pEnv->harden),
221 m_env_acquireWeak(pEnv->acquireWeak),
222 m_env_releaseWeak(pEnv->releaseWeak),
223 m_env_registerProxyInterface (pEnv->pExtEnv->registerProxyInterface),
224 m_env_revokeInterface (pEnv->pExtEnv->revokeInterface),
225 m_env_getObjectIdentifier (pEnv->pExtEnv->getObjectIdentifier),
226 m_env_getRegisteredInterface (pEnv->pExtEnv->getRegisteredInterface),
227 m_env_getRegisteredInterfaces(pEnv->pExtEnv->getRegisteredInterfaces),
228 m_env_computeObjectIdentifier(pEnv->pExtEnv->computeObjectIdentifier),
229 m_env_acquireInterface (pEnv->pExtEnv->acquireInterface),
230 m_env_releaseInterface (pEnv->pExtEnv->releaseInterface)
231 {
232 SAL_INFO("cppu.purpenv", "LIFE: cppu::helper::purpenv::Base::Base(uno_Environment * pEnv) -> " << this);
233 OSL_ENSURE(
234 rtl_ustr_ascii_compare_WithLength(pEnv->pTypeName->buffer, rtl_str_getLength(UNO_LB_UNO), UNO_LB_UNO)
235 == 0,
236 "### wrong environment type!");
237
238 pEnv->acquire = s_acquire;
239 pEnv->release = s_release;
240 pEnv->harden = s_harden;
241 pEnv->acquireWeak = s_acquireWeak;
242 pEnv->releaseWeak = s_releaseWeak;
243
244 pEnv->pExtEnv->registerProxyInterface = s_registerProxyInterface;
245 pEnv->pExtEnv->revokeInterface = s_revokeInterface;
246 pEnv->pExtEnv->getObjectIdentifier = s_getObjectIdentifier;
247 pEnv->pExtEnv->getRegisteredInterface = s_getRegisteredInterface;
248 pEnv->pExtEnv->getRegisteredInterfaces = s_getRegisteredInterfaces;
249 pEnv->pExtEnv->computeObjectIdentifier = s_computeObjectIdentifier;
250 pEnv->pExtEnv->acquireInterface = s_acquireInterface;
251 pEnv->pExtEnv->releaseInterface = s_releaseInterface;
252
253 pEnv->pReserved = this;
254 }
255
~Base()256 Base::~Base()
257 {
258 SAL_INFO("cppu.purpenv", "LIFE: cppu::helper::purpenv::Base::~Base() -> " << this);
259
260 m_pEnv->acquire = m_env_acquire;
261 m_pEnv->release = m_env_release;
262 m_pEnv->harden = m_env_harden;
263 m_pEnv->acquireWeak = m_env_acquireWeak;
264 m_pEnv->releaseWeak = m_env_releaseWeak;
265
266 m_pEnv->pReserved = nullptr;
267
268 m_pEnterable.reset();
269 m_pEnv->release(m_pEnv);
270 }
271
acquire()272 void Base::acquire()
273 {
274 m_env_acquire(m_pEnv);
275
276 osl_atomic_increment(&m_nRef);
277 }
278
release()279 void Base::release()
280 {
281 if (osl_atomic_decrement(&m_nRef) == 0)
282 delete this;
283
284 else
285 m_env_release(m_pEnv);
286 }
287
harden(uno_Environment ** ppHardEnv)288 void Base::harden(uno_Environment ** ppHardEnv)
289 {
290 m_env_harden(ppHardEnv, m_pEnv);
291 osl_atomic_increment(&m_nRef);
292 }
293
acquireWeak()294 void Base::acquireWeak()
295 {
296 m_env_acquireWeak(m_pEnv);
297 }
298
releaseWeak()299 void Base::releaseWeak()
300 {
301 m_env_releaseWeak(m_pEnv);
302 }
303
304
s_registerProxyInterface_v(va_list * pParam)305 extern "C" { static void s_registerProxyInterface_v(va_list * pParam)
306 {
307 uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
308 void ** ppProxy = va_arg(*pParam, void **);
309 uno_freeProxyFunc freeProxy = va_arg(*pParam, uno_freeProxyFunc);
310 rtl_uString * pOId = va_arg(*pParam, rtl_uString *);
311 typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
312 ExtEnv_registerProxyInterface * pRegisterProxyInterface
313 = va_arg(*pParam, ExtEnv_registerProxyInterface *);
314
315 pRegisterProxyInterface(pExtEnv, ppProxy, freeProxy, pOId, pTypeDescr);
316 }}
317
registerProxyInterface(void ** ppProxy,uno_freeProxyFunc freeProxy,OUString const & oid,typelib_InterfaceTypeDescription * pTypeDescr)318 void Base::registerProxyInterface(void ** ppProxy,
319 uno_freeProxyFunc freeProxy,
320 OUString const & oid,
321 typelib_InterfaceTypeDescription * pTypeDescr)
322 {
323 uno_Environment_invoke(m_pEnv,
324 s_registerProxyInterface_v,
325 m_pEnv->pExtEnv,
326 ppProxy,
327 freeProxy,
328 oid.pData,
329 pTypeDescr,
330 m_env_registerProxyInterface);
331 }
332
333
s_revokeInterface_v(va_list * pParam)334 extern "C" { static void s_revokeInterface_v(va_list * pParam)
335 {
336 uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
337 void * pInterface = va_arg(*pParam, void *);
338 ExtEnv_revokeInterface * pRevokeInterface = va_arg(*pParam, ExtEnv_revokeInterface *);
339
340 pRevokeInterface(pExtEnv, pInterface);
341 }}
342
revokeInterface(void * pInterface)343 void Base::revokeInterface(void * pInterface)
344 {
345 uno_Environment_invoke(m_pEnv,
346 s_revokeInterface_v,
347 m_pEnv->pExtEnv,
348 pInterface,
349 m_env_revokeInterface);
350 }
351
352
s_getObjectIdentifier_v(va_list * pParam)353 extern "C" { static void s_getObjectIdentifier_v(va_list * pParam)
354 {
355 uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
356 void * pInterface = va_arg(*pParam, void *);
357 OUString * pOId = va_arg(*pParam, OUString *);
358 ExtEnv_getObjectIdentifier * pGetObjectIdentifier
359 = va_arg(*pParam, ExtEnv_getObjectIdentifier *);
360
361 pGetObjectIdentifier(pExtEnv, reinterpret_cast<rtl_uString **>(pOId), pInterface);
362 }}
363
getObjectIdentifier(void * pInterface,OUString * pOid)364 void Base::getObjectIdentifier(void * pInterface, OUString * pOid)
365 {
366 uno_Environment_invoke(m_pEnv,
367 s_getObjectIdentifier_v,
368 m_pEnv->pExtEnv,
369 pInterface,
370 pOid,
371 m_env_getObjectIdentifier);
372 }
373
374
s_getRegisteredInterface_v(va_list * pParam)375 extern "C" { static void s_getRegisteredInterface_v(va_list * pParam)
376 {
377 uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
378 void ** ppInterface = va_arg(*pParam, void **);
379 rtl_uString * pOId = va_arg(*pParam, rtl_uString *);
380 typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
381 ExtEnv_getRegisteredInterface * pGetRegisteredInterface
382 = va_arg(*pParam, ExtEnv_getRegisteredInterface *);
383
384 pGetRegisteredInterface(pExtEnv, ppInterface, pOId, pTypeDescr);
385 }}
386
getRegisteredInterface(void ** ppInterface,OUString const & oid,typelib_InterfaceTypeDescription * pTypeDescr)387 void Base::getRegisteredInterface(void ** ppInterface,
388 OUString const & oid,
389 typelib_InterfaceTypeDescription * pTypeDescr)
390 {
391 uno_Environment_invoke(m_pEnv,
392 s_getRegisteredInterface_v,
393 m_pEnv->pExtEnv,
394 ppInterface,
395 oid.pData,
396 pTypeDescr,
397 m_env_getRegisteredInterface);
398 }
399
400
s_getRegisteredInterfaces_v(va_list * pParam)401 extern "C" { static void s_getRegisteredInterfaces_v(va_list * pParam)
402 {
403 uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
404 void *** pppInterface = va_arg(*pParam, void ***);
405 sal_Int32 * pnLen = va_arg(*pParam, sal_Int32 *);
406 uno_memAlloc memAlloc = va_arg(*pParam, uno_memAlloc);
407 ExtEnv_getRegisteredInterfaces * pGetRegisteredInterfaces
408 = va_arg(*pParam, ExtEnv_getRegisteredInterfaces *);
409
410 pGetRegisteredInterfaces(pExtEnv, pppInterface, pnLen, memAlloc);
411 }}
412
getRegisteredInterfaces(void *** pppInterface,sal_Int32 * pnLen,uno_memAlloc memAlloc)413 void Base::getRegisteredInterfaces(void *** pppInterface,
414 sal_Int32 * pnLen,
415 uno_memAlloc memAlloc)
416 {
417 uno_Environment_invoke(m_pEnv,
418 s_getRegisteredInterfaces_v,
419 m_pEnv->pExtEnv,
420 pppInterface,
421 pnLen,
422 memAlloc,
423 m_env_getRegisteredInterfaces);
424 }
425
426
s_computeObjectIdentifier_v(va_list * pParam)427 extern "C" { static void s_computeObjectIdentifier_v(va_list * pParam)
428 {
429 uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
430 void * pInterface = va_arg(*pParam, void *);
431 OUString * pOId = va_arg(*pParam, OUString *);
432 ExtEnv_computeObjectIdentifier * pComputeObjectIdentifier
433 = va_arg(*pParam, ExtEnv_computeObjectIdentifier *);
434
435 pComputeObjectIdentifier(pExtEnv, reinterpret_cast<rtl_uString **>(pOId), pInterface);
436 }}
437
computeObjectIdentifier(void * pInterface,OUString * pOid)438 void Base::computeObjectIdentifier(void * pInterface, OUString * pOid)
439 {
440 uno_Environment_invoke(m_pEnv,
441 s_computeObjectIdentifier_v,
442 m_pEnv->pExtEnv,
443 pInterface,
444 pOid,
445 m_env_computeObjectIdentifier);
446 }
447
448
s_acquireInterface_v(va_list * pParam)449 extern "C" { static void s_acquireInterface_v(va_list * pParam)
450 {
451 uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
452 void * pInterface = va_arg(*pParam, void *);
453 ExtEnv_acquireInterface * pAcquireInterface
454 = va_arg(*pParam, ExtEnv_acquireInterface *);
455
456 pAcquireInterface(pExtEnv, pInterface);
457 }}
458
acquireInterface(void * pInterface)459 void Base::acquireInterface(void * pInterface)
460 {
461 uno_Environment_invoke(m_pEnv, s_acquireInterface_v, m_pEnv->pExtEnv, pInterface, m_env_acquireInterface);
462 }
463
464
s_releaseInterface_v(va_list * pParam)465 extern "C" { static void s_releaseInterface_v(va_list * pParam)
466 {
467 uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *);
468 void * pInterface = va_arg(*pParam, void *);
469 ExtEnv_releaseInterface * pReleaseInterface
470 = va_arg(*pParam, ExtEnv_releaseInterface *);
471
472 pReleaseInterface(pExtEnv, pInterface);
473 }}
474
releaseInterface(void * pInterface)475 void Base::releaseInterface(void * pInterface)
476 {
477 uno_Environment_invoke(m_pEnv,
478 s_releaseInterface_v,
479 m_pEnv->pExtEnv,
480 pInterface,
481 m_env_releaseInterface);
482 }
483
v_enter()484 void Base::v_enter()
485 {
486 m_pEnterable->enter();
487 }
488
v_leave()489 void Base::v_leave()
490 {
491 m_pEnterable->leave();
492 }
493
v_callInto_v(uno_EnvCallee * pCallee,va_list * pParam)494 void Base::v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam)
495 {
496 m_pEnterable->callInto_v(pCallee, pParam);
497 }
498
v_callOut_v(uno_EnvCallee * pCallee,va_list * pParam)499 void Base::v_callOut_v(uno_EnvCallee * pCallee, va_list * pParam)
500 {
501 m_pEnterable->callOut_v(pCallee, pParam);
502 }
503
v_isValid(OUString * pReason)504 bool Base::v_isValid(OUString * pReason)
505 {
506 return m_pEnterable->isValid(pReason);
507 }
508
509 namespace cppu { namespace helper { namespace purpenv {
510
Environment_initWithEnterable(uno_Environment * pEnvironment,cppu::Enterable * pEnterable)511 void Environment_initWithEnterable(uno_Environment * pEnvironment, cppu::Enterable * pEnterable)
512 {
513 new Base(pEnvironment, pEnterable);
514 }
515
516 }}}
517
518 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
519