1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cppu.hxx"
30 
31 #include "cppu/helper/purpenv/Environment.hxx"
32 
33 #include "osl/diagnose.h"
34 #include "uno/lbnames.h"
35 
36 #include "typelib/typedescription.h"
37 #include "osl/interlck.h"
38 
39 #ifdef debug
40 # define LOG_LIFECYCLE_cppu_helper_purpenv_Base
41 #endif
42 
43 #ifdef LOG_LIFECYCLE_cppu_helper_purpenv_Base
44 #  include <iostream>
45 #  define LOG_LIFECYCLE_cppu_helper_purpenv_Base_emit(x) x
46 
47 #else
48 #  define LOG_LIFECYCLE_cppu_helper_purpenv_Base_emit(x)
49 
50 #endif
51 
52 
53 extern "C" {
54 typedef void SAL_CALL EnvFun_P   (uno_Environment *);
55 typedef void SAL_CALL EnvFun_PP_P(uno_Environment ** ppHardEnv, uno_Environment *);
56 typedef void SAL_CALL ExtEnv_registerProxyInterface (uno_ExtEnvironment                 *,
57                                                      void                              ** ppProxy,
58                                                      uno_freeProxyFunc                    freeProxy,
59                                                      rtl_uString * pOId,
60                                                      typelib_InterfaceTypeDescription   * pTypeDescr);
61 typedef void SAL_CALL ExtEnv_revokeInterface        (uno_ExtEnvironment                 *,
62                                                      void                               * pInterface);
63 typedef void SAL_CALL ExtEnv_getObjectIdentifier    (uno_ExtEnvironment                 *,
64                                                      rtl_uString                       **,
65                                                      void                               *);
66 typedef void SAL_CALL ExtEnv_getRegisteredInterface (uno_ExtEnvironment                 *,
67                                                      void                              **,
68                                                      rtl_uString                        *,
69                                                      typelib_InterfaceTypeDescription   *);
70 typedef void SAL_CALL ExtEnv_getRegisteredInterfaces(uno_ExtEnvironment                 *,
71                                                      void                             *** pppInterfaces,
72                                                      sal_Int32                          * pnLen,
73                                                      uno_memAlloc                         memAlloc);
74 typedef void SAL_CALL ExtEnv_computeObjectIdentifier(uno_ExtEnvironment                 *,
75                                                      rtl_uString                       ** ppOId,
76                                                      void                               * pInterface);
77 typedef void SAL_CALL ExtEnv_acquireInterface       (uno_ExtEnvironment                 *,
78                                                      void                               * pInterface);
79 typedef void SAL_CALL ExtEnv_releaseInterface       (uno_ExtEnvironment                 *,
80                                                      void                               * pInterface);
81 }
82 
83 class Base : public cppu::Enterable
84 {
85 public:
86 	explicit Base(uno_Environment * pEnv, cppu::Enterable * pEnterable);
87 
88 	void acquireWeak(void);
89 	void releaseWeak(void);
90 	void harden     (uno_Environment ** ppHardEnv);
91 	void acquire    (void);
92 	void release    (void);
93 
94 	void registerProxyInterface (void                                  ** ppProxy,
95 								 uno_freeProxyFunc                        freeProxy,
96 								 rtl::OUString                    const & oid,
97 								 typelib_InterfaceTypeDescription       * pTypeDescr);
98 	void revokeInterface        (void                                   * pInterface);
99 	void getObjectIdentifier    (void                                   * pInterface,
100 								 rtl::OUString                          * pOid);
101 	void getRegisteredInterface (void                                  **,
102 								 rtl::OUString                    const & oid,
103 								 typelib_InterfaceTypeDescription       *);
104 	void getRegisteredInterfaces(void                                 ***,
105 								 sal_Int32                              * pnLen,
106 								 uno_memAlloc                             memAlloc);
107 	void computeObjectIdentifier(void                                   * pInterface,
108 								 rtl::OUString                          * pOid);
109 	void acquireInterface       (void                                   * pInterface);
110 	void releaseInterface       (void                                   * pInterface);
111 
112 	virtual void v_enter     (void);
113 	virtual void v_leave     (void);
114 	virtual void v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam);
115 	virtual void v_callOut_v (uno_EnvCallee * pCallee, va_list * pParam);
116 	virtual int  v_isValid   (rtl::OUString * pReason);
117 
118 protected:
119     oslInterlockedCount    m_nRef;
120 	uno_Environment      * m_pEnv;
121     cppu::Enterable      * m_pEnterable;
122 
123 	EnvFun_P    * m_env_acquire;
124 	EnvFun_P    * m_env_release;
125 	EnvFun_PP_P * m_env_harden;
126 	EnvFun_P    * m_env_acquireWeak;
127 	EnvFun_P    * m_env_releaseWeak;
128 
129 	ExtEnv_registerProxyInterface  * m_env_registerProxyInterface;
130 	ExtEnv_revokeInterface         * m_env_revokeInterface;
131 	ExtEnv_getObjectIdentifier     * m_env_getObjectIdentifier;
132 	ExtEnv_getRegisteredInterface  * m_env_getRegisteredInterface;
133 	ExtEnv_getRegisteredInterfaces * m_env_getRegisteredInterfaces;
134 	ExtEnv_computeObjectIdentifier * m_env_computeObjectIdentifier;
135 	ExtEnv_acquireInterface        * m_env_acquireInterface;
136 	ExtEnv_releaseInterface        * m_env_releaseInterface;
137 
138 	virtual  ~Base();
139 };
140 
141 extern "C" {
142 static void SAL_CALL s_acquire(uno_Environment * pEnv) //SAL_THROW_EXTERN_C()
143 {
144 	Base * pBase = static_cast<Base *>(pEnv->pReserved);
145 	pBase->acquire();
146 }
147 
148 static void SAL_CALL s_release(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
149 {
150 	Base * pBase = static_cast<Base *>(pEnv->pReserved);
151 	pBase->release();
152 }
153 
154 static void SAL_CALL s_harden(uno_Environment ** ppHardEnv, uno_Environment * pEnv) SAL_THROW_EXTERN_C()
155 {
156 	Base * pBase = static_cast<Base *>(pEnv->pReserved);
157 	pBase->harden(ppHardEnv);
158 }
159 
160 static void SAL_CALL s_acquireWeak(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
161 {
162 	Base * pBase = static_cast<Base *>(pEnv->pReserved);
163 	pBase->acquireWeak();
164 }
165 
166 static void SAL_CALL s_releaseWeak(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
167 {
168 	Base * pBase = static_cast<Base *>(pEnv->pReserved);
169 	pBase->releaseWeak();
170 }
171 
172 
173 static void SAL_CALL s_registerProxyInterface(uno_ExtEnvironment                * pExtEnv,
174                                                          void                             ** ppProxy,
175                                                          uno_freeProxyFunc                   freeProxy,
176                                                          rtl_uString                       * pOId,
177                                                          typelib_InterfaceTypeDescription  * pTypeDescr)
178 {
179 	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
180 	pBase->registerProxyInterface(ppProxy, freeProxy, pOId, pTypeDescr);
181 }
182 
183 static void SAL_CALL s_revokeInterface(uno_ExtEnvironment * pExtEnv, void * pInterface)
184 {
185 	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
186 	pBase->revokeInterface(pInterface);
187 }
188 
189 static void SAL_CALL s_getObjectIdentifier(uno_ExtEnvironment *  pExtEnv,
190                                                       rtl_uString        ** ppOId,
191                                                       void               *  pInterface)
192 {
193 	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
194 	pBase->getObjectIdentifier(pInterface, reinterpret_cast<rtl::OUString *>(ppOId));
195 }
196 
197 static void SAL_CALL s_getRegisteredInterface(uno_ExtEnvironment *  pExtEnv,
198                                                          void               ** ppInterface,
199                                                          rtl_uString        *  pOId,
200                                                          typelib_InterfaceTypeDescription * pTypeDescr)
201 {
202 	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
203 	pBase->getRegisteredInterface(ppInterface, pOId, pTypeDescr);
204 }
205 
206 static void SAL_CALL s_getRegisteredInterfaces(uno_ExtEnvironment   * pExtEnv,
207                                                           void               *** pppInterface,
208                                                           sal_Int32            * pnLen,
209                                                           uno_memAlloc           memAlloc)
210 {
211 	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
212 	pBase->getRegisteredInterfaces(pppInterface, pnLen, memAlloc);
213 }
214 
215 static void SAL_CALL s_computeObjectIdentifier(uno_ExtEnvironment *  pExtEnv,
216                                                           rtl_uString        ** ppOId,
217                                                           void               *  pInterface)
218 {
219 	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
220 	pBase->computeObjectIdentifier(pInterface, reinterpret_cast<rtl::OUString *>(ppOId));
221 }
222 
223 static void SAL_CALL s_acquireInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) {
224 	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
225 	pBase->acquireInterface(pInterface);
226 }
227 
228 static void SAL_CALL s_releaseInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) {
229 	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
230 	pBase->releaseInterface(pInterface);
231 }
232 
233 }
234 
235 Base::Base(uno_Environment * pEnv, cppu::Enterable * pEnterable)
236 	:m_nRef(1),
237 	 m_pEnv(pEnv),
238      m_pEnterable     (pEnterable),
239 	 m_env_acquire    (pEnv->acquire),
240 	 m_env_release    (pEnv->release),
241 	 m_env_harden     (pEnv->harden),
242 	 m_env_acquireWeak(pEnv->acquireWeak),
243 	 m_env_releaseWeak(pEnv->releaseWeak),
244 	 m_env_registerProxyInterface (pEnv->pExtEnv->registerProxyInterface),
245 	 m_env_revokeInterface        (pEnv->pExtEnv->revokeInterface),
246 	 m_env_getObjectIdentifier    (pEnv->pExtEnv->getObjectIdentifier),
247 	 m_env_getRegisteredInterface (pEnv->pExtEnv->getRegisteredInterface),
248 	 m_env_getRegisteredInterfaces(pEnv->pExtEnv->getRegisteredInterfaces),
249 	 m_env_computeObjectIdentifier(pEnv->pExtEnv->computeObjectIdentifier),
250 	 m_env_acquireInterface       (pEnv->pExtEnv->acquireInterface),
251 	 m_env_releaseInterface       (pEnv->pExtEnv->releaseInterface)
252 {
253 	LOG_LIFECYCLE_cppu_helper_purpenv_Base_emit(fprintf(stderr, "LIFE: %s -> %p\n", "cppu::helper::purpenv::Base::Base(uno_Environment * pEnv)", this));
254 	OSL_ENSURE(
255 		rtl_ustr_ascii_compare_WithLength(pEnv->pTypeName->buffer, rtl_str_getLength(UNO_LB_UNO), UNO_LB_UNO)
256 			== 0,
257 			"### wrong environment type!");
258 
259 	pEnv->acquire     = s_acquire;
260 	pEnv->release     = s_release;
261 	pEnv->harden      = s_harden;
262 	pEnv->acquireWeak = s_acquireWeak;
263 	pEnv->releaseWeak = s_releaseWeak;
264 
265 	pEnv->pExtEnv->registerProxyInterface  = s_registerProxyInterface;
266 	pEnv->pExtEnv->revokeInterface         = s_revokeInterface;
267 	pEnv->pExtEnv->getObjectIdentifier     = s_getObjectIdentifier;
268 	pEnv->pExtEnv->getRegisteredInterface  = s_getRegisteredInterface;
269 	pEnv->pExtEnv->getRegisteredInterfaces = s_getRegisteredInterfaces;
270 	pEnv->pExtEnv->computeObjectIdentifier = s_computeObjectIdentifier;
271 	pEnv->pExtEnv->acquireInterface        = s_acquireInterface;
272 	pEnv->pExtEnv->releaseInterface        = s_releaseInterface;
273 
274 	pEnv->pReserved = this;
275 }
276 
277 Base::~Base()
278 {
279 	LOG_LIFECYCLE_cppu_helper_purpenv_Base_emit(fprintf(stderr, "LIFE: %s -> %p\n", "cppu::helper::purpenv::Base::~Base()", this));
280 
281 	m_pEnv->acquire     = m_env_acquire;
282 	m_pEnv->release     = m_env_release;
283 	m_pEnv->harden      = m_env_harden;
284 	m_pEnv->acquireWeak = m_env_acquireWeak;
285 	m_pEnv->releaseWeak = m_env_releaseWeak;
286 
287 	m_pEnv->pReserved = NULL;
288 
289     delete m_pEnterable;
290 	m_pEnv->release(m_pEnv);
291 }
292 
293 void Base::acquire(void)
294 {
295 	m_env_acquire(m_pEnv);
296 
297     osl_incrementInterlockedCount(&m_nRef);
298 }
299 
300 void Base::release(void)
301 {
302     if (osl_decrementInterlockedCount(&m_nRef) == 0)
303 		delete this;
304 
305 	else
306 		m_env_release(m_pEnv);
307 }
308 
309 void Base::harden(uno_Environment ** ppHardEnv)
310 {
311 	m_env_harden(ppHardEnv, m_pEnv);
312     osl_incrementInterlockedCount(&m_nRef);
313 }
314 
315 void Base::acquireWeak(void)
316 {
317 	m_env_acquireWeak(m_pEnv);
318 }
319 
320 void Base::releaseWeak(void)
321 {
322 	m_env_releaseWeak(m_pEnv);
323 }
324 
325 
326 extern "C" { static void s_registerProxyInterface_v(va_list * pParam)
327 {
328 	uno_ExtEnvironment                   * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
329 	void                                ** ppProxy    = va_arg(*pParam, void **);
330 	uno_freeProxyFunc                      freeProxy  = va_arg(*pParam, uno_freeProxyFunc);
331 	rtl_uString                          * pOId       = va_arg(*pParam, rtl_uString *);
332 	typelib_InterfaceTypeDescription     * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
333 	ExtEnv_registerProxyInterface  * pRegisterProxyInterface
334 		= va_arg(*pParam, ExtEnv_registerProxyInterface *);
335 
336 	pRegisterProxyInterface(pExtEnv, ppProxy, freeProxy, pOId, pTypeDescr);
337 }}
338 
339 void Base::registerProxyInterface(void                                  ** ppProxy,
340 								  uno_freeProxyFunc                        freeProxy,
341 								  rtl::OUString                    const & oid,
342 								  typelib_InterfaceTypeDescription       * pTypeDescr)
343 {
344  	uno_Environment_invoke(m_pEnv,
345 						   s_registerProxyInterface_v,
346 						   m_pEnv->pExtEnv,
347 						   ppProxy,
348 						   freeProxy,
349 						   oid.pData,
350 						   pTypeDescr,
351 						   m_env_registerProxyInterface);
352 }
353 
354 
355 extern "C" { static void s_revokeInterface_v(va_list * pParam)
356 {
357 	uno_ExtEnvironment * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
358 	void               * pInterface = va_arg(*pParam, void *);
359 	ExtEnv_revokeInterface * pRevokeInterface = va_arg(*pParam, ExtEnv_revokeInterface *);
360 
361 	pRevokeInterface(pExtEnv, pInterface);
362 }}
363 
364 void Base::revokeInterface(void * pInterface)
365 {
366  	uno_Environment_invoke(m_pEnv,
367 						   s_revokeInterface_v,
368 						   m_pEnv->pExtEnv,
369 						   pInterface,
370 						   m_env_revokeInterface);
371 }
372 
373 
374 extern "C" { static void s_getObjectIdentifier_v(va_list * pParam)
375 {
376 	uno_ExtEnvironment * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
377 	void               * pInterface = va_arg(*pParam, void *);
378 	rtl::OUString      * pOId       = va_arg(*pParam, rtl::OUString *);
379 	ExtEnv_getObjectIdentifier * pGetObjectIdentifier
380 		= va_arg(*pParam, ExtEnv_getObjectIdentifier *);
381 
382 	pGetObjectIdentifier(pExtEnv, reinterpret_cast<rtl_uString **>(pOId), pInterface);
383 }}
384 
385 void Base::getObjectIdentifier(void * pInterface, rtl::OUString * pOid)
386 {
387  	uno_Environment_invoke(m_pEnv,
388 						   s_getObjectIdentifier_v,
389 						   m_pEnv->pExtEnv,
390 						   pInterface,
391 						   pOid,
392 						   m_env_getObjectIdentifier);
393 }
394 
395 
396 extern "C" { static void s_getRegisteredInterface_v(va_list * pParam)
397 {
398 	uno_ExtEnvironment                   * pExtEnv     = va_arg(*pParam, uno_ExtEnvironment *);
399 	void                                ** ppInterface = va_arg(*pParam, void **);
400 	rtl_uString                          * pOId        = va_arg(*pParam, rtl_uString *);
401 	typelib_InterfaceTypeDescription     * pTypeDescr  = va_arg(*pParam, typelib_InterfaceTypeDescription *);
402 	ExtEnv_getRegisteredInterface  * pGetRegisteredInterface
403 		= va_arg(*pParam, ExtEnv_getRegisteredInterface *);
404 
405 	pGetRegisteredInterface(pExtEnv, ppInterface, pOId, pTypeDescr);
406 }}
407 
408 void Base::getRegisteredInterface(void ** ppInterface,
409 								  rtl::OUString const & oid,
410 								  typelib_InterfaceTypeDescription * pTypeDescr)
411 {
412  	uno_Environment_invoke(m_pEnv,
413 						   s_getRegisteredInterface_v,
414 						   m_pEnv->pExtEnv,
415 						   ppInterface,
416 						   oid.pData,
417 						   pTypeDescr,
418 						   m_env_getRegisteredInterface);
419 }
420 
421 
422 extern "C" { static void s_getRegisteredInterfaces_v(va_list * pParam)
423 {
424 	uno_ExtEnvironment   * pExtEnv      = va_arg(*pParam, uno_ExtEnvironment *);
425 	void               *** pppInterface = va_arg(*pParam, void ***);
426 	sal_Int32            * pnLen        = va_arg(*pParam, sal_Int32 *);
427 	uno_memAlloc           memAlloc     = va_arg(*pParam, uno_memAlloc);
428 	ExtEnv_getRegisteredInterfaces * pGetRegisteredInterfaces
429 		= va_arg(*pParam, ExtEnv_getRegisteredInterfaces *);
430 
431 	pGetRegisteredInterfaces(pExtEnv, pppInterface, pnLen, memAlloc);
432 }}
433 
434 void Base::getRegisteredInterfaces(void         *** pppInterface,
435 								   sal_Int32      * pnLen,
436 								   uno_memAlloc     memAlloc)
437 {
438  	uno_Environment_invoke(m_pEnv,
439 						   s_getRegisteredInterfaces_v,
440 						   m_pEnv->pExtEnv,
441 						   pppInterface,
442 						   pnLen,
443 						   memAlloc,
444 						   m_env_getRegisteredInterfaces);
445 }
446 
447 
448 extern "C" { static void s_computeObjectIdentifier_v(va_list * pParam)
449 {
450 	uno_ExtEnvironment * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
451 	void               * pInterface = va_arg(*pParam, void *);
452 	rtl::OUString      * pOId       = va_arg(*pParam, rtl::OUString *);
453 	ExtEnv_computeObjectIdentifier * pComputeObjectIdentifier
454 		= va_arg(*pParam, ExtEnv_computeObjectIdentifier *);
455 
456 	pComputeObjectIdentifier(pExtEnv, reinterpret_cast<rtl_uString **>(pOId), pInterface);
457 }}
458 
459 void Base::computeObjectIdentifier(void * pInterface, rtl::OUString * pOid)
460 {
461  	uno_Environment_invoke(m_pEnv,
462 						   s_computeObjectIdentifier_v,
463 						   m_pEnv->pExtEnv,
464 						   pInterface,
465 						   pOid,
466 						   m_env_computeObjectIdentifier);
467 }
468 
469 
470 extern "C" { static void s_acquireInterface_v(va_list * pParam)
471 {
472 	uno_ExtEnvironment * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
473 	void               * pInterface = va_arg(*pParam, void *);
474 	ExtEnv_acquireInterface * pAcquireInterface
475 		= va_arg(*pParam, ExtEnv_acquireInterface *);
476 
477 	pAcquireInterface(pExtEnv, pInterface);
478 }}
479 
480 void Base::acquireInterface(void * pInterface)
481 {
482  	uno_Environment_invoke(m_pEnv, s_acquireInterface_v, m_pEnv->pExtEnv, pInterface, m_env_acquireInterface);
483 }
484 
485 
486 extern "C" { static void s_releaseInterface_v(va_list * pParam)
487 {
488 	uno_ExtEnvironment * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
489 	void               * pInterface = va_arg(*pParam, void *);
490 	ExtEnv_releaseInterface * pReleaseInterface
491 		= va_arg(*pParam, ExtEnv_releaseInterface *);
492 
493 	pReleaseInterface(pExtEnv, pInterface);
494 }}
495 
496 void Base::releaseInterface(void * pInterface)
497 {
498  	uno_Environment_invoke(m_pEnv,
499 						   s_releaseInterface_v,
500 						   m_pEnv->pExtEnv,
501 						   pInterface,
502 						   m_env_releaseInterface);
503 }
504 
505 void Base::v_enter(void)
506 {
507     m_pEnterable->enter();
508 }
509 
510 void Base::v_leave(void)
511 {
512     m_pEnterable->leave();
513 }
514 
515 void Base::v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam)
516 {
517     m_pEnterable->callInto_v(pCallee, pParam);
518 }
519 
520 void Base::v_callOut_v(uno_EnvCallee * pCallee, va_list * pParam)
521 {
522     m_pEnterable->callOut_v(pCallee, pParam);
523 }
524 
525 int Base::v_isValid(rtl::OUString * pReason)
526 {
527     return m_pEnterable->isValid(pReason);
528 }
529 
530 namespace cppu { namespace helper { namespace purpenv {
531 
532 void Environment_initWithEnterable(uno_Environment * pEnvironment, cppu::Enterable * pEnterable)
533 {
534     new Base(pEnvironment, pEnterable);
535 }
536 
537 }}}
538