text: /**************************************************************
   * 
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   * 
   *   http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   * 
   *************************************************************/
  
  
  
  // MARKER(update_precomp.py): autogen include statement, do not remove
  #include "precompiled_cppu.hxx"
  
  #include "cppu/helper/purpenv/Environment.hxx"
  
  #include "osl/diagnose.h"
  #include "uno/lbnames.h"
  
  #include "typelib/typedescription.h"
  #include "osl/interlck.h"
  
  #ifdef debug
  # define LOG_LIFECYCLE_cppu_helper_purpenv_Base
  #endif
  
  #ifdef LOG_LIFECYCLE_cppu_helper_purpenv_Base
  #  include <iostream>
  #  define LOG_LIFECYCLE_cppu_helper_purpenv_Base_emit(x) x
  
  #else
  #  define LOG_LIFECYCLE_cppu_helper_purpenv_Base_emit(x)
  
  #endif
  
  
  extern "C" { 
  typedef void SAL_CALL EnvFun_P   (uno_Environment *); 
  typedef void SAL_CALL EnvFun_PP_P(uno_Environment ** ppHardEnv, uno_Environment *);
  typedef void SAL_CALL ExtEnv_registerProxyInterface (uno_ExtEnvironment                 *,
                                                       void                              ** ppProxy,
                                                       uno_freeProxyFunc                    freeProxy,
                                                       rtl_uString * pOId,
                                                       typelib_InterfaceTypeDescription   * pTypeDescr);
  typedef void SAL_CALL ExtEnv_revokeInterface        (uno_ExtEnvironment                 *, 
                                                       void                               * pInterface);
  typedef void SAL_CALL ExtEnv_getObjectIdentifier    (uno_ExtEnvironment                 *, 
                                                       rtl_uString                       **, 
                                                       void                               *);
  typedef void SAL_CALL ExtEnv_getRegisteredInterface (uno_ExtEnvironment                 *, 
                                                       void                              **, 
                                                       rtl_uString                        *, 
                                                       typelib_InterfaceTypeDescription   *);
  typedef void SAL_CALL ExtEnv_getRegisteredInterfaces(uno_ExtEnvironment                 *, 
                                                       void                             *** pppInterfaces,
                                                       sal_Int32                          * pnLen,
                                                       uno_memAlloc                         memAlloc);
  typedef void SAL_CALL ExtEnv_computeObjectIdentifier(uno_ExtEnvironment                 *, 
                                                       rtl_uString                       ** ppOId, 
                                                       void                               * pInterface);
  typedef void SAL_CALL ExtEnv_acquireInterface       (uno_ExtEnvironment                 *, 
                                                       void                               * pInterface);
  typedef void SAL_CALL ExtEnv_releaseInterface       (uno_ExtEnvironment                 *, 
                                                       void                               * pInterface);
  }
  
  class Base : public cppu::Enterable
  {
  public:
  	explicit Base(uno_Environment * pEnv, cppu::Enterable * pEnterable);
  
  	void acquireWeak(void);
  	void releaseWeak(void);
  	void harden     (uno_Environment ** ppHardEnv);
  	void acquire    (void);
  	void release    (void);
  
  	void registerProxyInterface (void                                  ** ppProxy, 
  								 uno_freeProxyFunc                        freeProxy, 
  								 rtl::OUString                    const & oid,
  								 typelib_InterfaceTypeDescription       * pTypeDescr);
  	void revokeInterface        (void                                   * pInterface);
  	void getObjectIdentifier    (void                                   * pInterface, 
  								 rtl::OUString                          * pOid);
  	void getRegisteredInterface (void                                  **, 
  								 rtl::OUString                    const & oid, 
  								 typelib_InterfaceTypeDescription       *);
  	void getRegisteredInterfaces(void                                 ***, 
  								 sal_Int32                              * pnLen,
  								 uno_memAlloc                             memAlloc);
  	void computeObjectIdentifier(void                                   * pInterface, 
  								 rtl::OUString                          * pOid);
  	void acquireInterface       (void                                   * pInterface);
  	void releaseInterface       (void                                   * pInterface);
  
  	virtual void v_enter     (void);
  	virtual void v_leave     (void);
  	virtual void v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam);
  	virtual void v_callOut_v (uno_EnvCallee * pCallee, va_list * pParam);
  	virtual int  v_isValid   (rtl::OUString * pReason);
  
  protected:
      oslInterlockedCount    m_nRef;
  	uno_Environment      * m_pEnv;
      cppu::Enterable      * m_pEnterable;
  
  	EnvFun_P    * m_env_acquire;
  	EnvFun_P    * m_env_release;
  	EnvFun_PP_P * m_env_harden;
  	EnvFun_P    * m_env_acquireWeak;
  	EnvFun_P    * m_env_releaseWeak;
  
  	ExtEnv_registerProxyInterface  * m_env_registerProxyInterface;
  	ExtEnv_revokeInterface         * m_env_revokeInterface;
  	ExtEnv_getObjectIdentifier     * m_env_getObjectIdentifier;
  	ExtEnv_getRegisteredInterface  * m_env_getRegisteredInterface;
  	ExtEnv_getRegisteredInterfaces * m_env_getRegisteredInterfaces;
  	ExtEnv_computeObjectIdentifier * m_env_computeObjectIdentifier;
  	ExtEnv_acquireInterface        * m_env_acquireInterface;
  	ExtEnv_releaseInterface        * m_env_releaseInterface;
  
  	virtual  ~Base();
  };
  
  extern "C" {
  static void SAL_CALL s_acquire(uno_Environment * pEnv) //SAL_THROW_EXTERN_C()
  {
  	Base * pBase = static_cast<Base *>(pEnv->pReserved);
  	pBase->acquire();
  }
  
  static void SAL_CALL s_release(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
  {
  	Base * pBase = static_cast<Base *>(pEnv->pReserved);
  	pBase->release();
  }
  
  static void SAL_CALL s_harden(uno_Environment ** ppHardEnv, uno_Environment * pEnv) SAL_THROW_EXTERN_C()
  {
  	Base * pBase = static_cast<Base *>(pEnv->pReserved);
  	pBase->harden(ppHardEnv);
  }
  
  static void SAL_CALL s_acquireWeak(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
  {
  	Base * pBase = static_cast<Base *>(pEnv->pReserved);
  	pBase->acquireWeak();
  }
  
  static void SAL_CALL s_releaseWeak(uno_Environment * pEnv) SAL_THROW_EXTERN_C()
  {
  	Base * pBase = static_cast<Base *>(pEnv->pReserved);
  	pBase->releaseWeak();
  }
  
  
  static void SAL_CALL s_registerProxyInterface(uno_ExtEnvironment                * pExtEnv, 
                                                           void                             ** ppProxy,
                                                           uno_freeProxyFunc                   freeProxy,
                                                           rtl_uString                       * pOId, 
                                                           typelib_InterfaceTypeDescription  * pTypeDescr) 
  {
  	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
  	pBase->registerProxyInterface(ppProxy, freeProxy, pOId, pTypeDescr);
  }
  
  static void SAL_CALL s_revokeInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) 
  {
  	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
  	pBase->revokeInterface(pInterface);
  }
  
  static void SAL_CALL s_getObjectIdentifier(uno_ExtEnvironment *  pExtEnv, 
                                                        rtl_uString        ** ppOId, 
                                                        void               *  pInterface) 
  {
  	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
  	pBase->getObjectIdentifier(pInterface, reinterpret_cast<rtl::OUString *>(ppOId));
  }
  
  static void SAL_CALL s_getRegisteredInterface(uno_ExtEnvironment *  pExtEnv, 
                                                           void               ** ppInterface,
                                                           rtl_uString        *  pOId, 
                                                           typelib_InterfaceTypeDescription * pTypeDescr) 
  {
  	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
  	pBase->getRegisteredInterface(ppInterface, pOId, pTypeDescr);
  }
  
  static void SAL_CALL s_getRegisteredInterfaces(uno_ExtEnvironment   * pExtEnv, 
                                                            void               *** pppInterface,
                                                            sal_Int32            * pnLen,
                                                            uno_memAlloc           memAlloc)
  {
  	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
  	pBase->getRegisteredInterfaces(pppInterface, pnLen, memAlloc);
  }
  
  static void SAL_CALL s_computeObjectIdentifier(uno_ExtEnvironment *  pExtEnv, 
                                                            rtl_uString        ** ppOId, 
                                                            void               *  pInterface) 
  {
  	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
  	pBase->computeObjectIdentifier(pInterface, reinterpret_cast<rtl::OUString *>(ppOId));
  }
  
  static void SAL_CALL s_acquireInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) {
  	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
  	pBase->acquireInterface(pInterface);
  }
  
  static void SAL_CALL s_releaseInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) {
  	Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved);
  	pBase->releaseInterface(pInterface);
  }
  
  }
  
  Base::Base(uno_Environment * pEnv, cppu::Enterable * pEnterable)
  	:m_nRef(1),
  	 m_pEnv(pEnv),
       m_pEnterable     (pEnterable),
  	 m_env_acquire    (pEnv->acquire),
  	 m_env_release    (pEnv->release),
  	 m_env_harden     (pEnv->harden),
  	 m_env_acquireWeak(pEnv->acquireWeak),
  	 m_env_releaseWeak(pEnv->releaseWeak),
  	 m_env_registerProxyInterface (pEnv->pExtEnv->registerProxyInterface),
  	 m_env_revokeInterface        (pEnv->pExtEnv->revokeInterface),
  	 m_env_getObjectIdentifier    (pEnv->pExtEnv->getObjectIdentifier),
  	 m_env_getRegisteredInterface (pEnv->pExtEnv->getRegisteredInterface),
  	 m_env_getRegisteredInterfaces(pEnv->pExtEnv->getRegisteredInterfaces),
  	 m_env_computeObjectIdentifier(pEnv->pExtEnv->computeObjectIdentifier),
  	 m_env_acquireInterface       (pEnv->pExtEnv->acquireInterface),
  	 m_env_releaseInterface       (pEnv->pExtEnv->releaseInterface)
  {
  	LOG_LIFECYCLE_cppu_helper_purpenv_Base_emit(fprintf(stderr, "LIFE: %s -> %p\n", "cppu::helper::purpenv::Base::Base(uno_Environment * pEnv)", this));
  	OSL_ENSURE(
  		rtl_ustr_ascii_compare_WithLength(pEnv->pTypeName->buffer, rtl_str_getLength(UNO_LB_UNO), UNO_LB_UNO)
  			== 0,
  			"### wrong environment type!");
  
  	pEnv->acquire     = s_acquire;
  	pEnv->release     = s_release;
  	pEnv->harden      = s_harden;
  	pEnv->acquireWeak = s_acquireWeak;
  	pEnv->releaseWeak = s_releaseWeak;
  
  	pEnv->pExtEnv->registerProxyInterface  = s_registerProxyInterface;
  	pEnv->pExtEnv->revokeInterface         = s_revokeInterface;
  	pEnv->pExtEnv->getObjectIdentifier     = s_getObjectIdentifier;
  	pEnv->pExtEnv->getRegisteredInterface  = s_getRegisteredInterface;
  	pEnv->pExtEnv->getRegisteredInterfaces = s_getRegisteredInterfaces;
  	pEnv->pExtEnv->computeObjectIdentifier = s_computeObjectIdentifier;
  	pEnv->pExtEnv->acquireInterface        = s_acquireInterface;
  	pEnv->pExtEnv->releaseInterface        = s_releaseInterface;
  
  	pEnv->pReserved = this;
  }
  
  Base::~Base() 
  {
  	LOG_LIFECYCLE_cppu_helper_purpenv_Base_emit(fprintf(stderr, "LIFE: %s -> %p\n", "cppu::helper::purpenv::Base::~Base()", this));
  
  	m_pEnv->acquire     = m_env_acquire;
  	m_pEnv->release     = m_env_release;
  	m_pEnv->harden      = m_env_harden;
  	m_pEnv->acquireWeak = m_env_acquireWeak;
  	m_pEnv->releaseWeak = m_env_releaseWeak;
  
  	m_pEnv->pReserved = NULL;
  
      delete m_pEnterable;
  	m_pEnv->release(m_pEnv);
  }
  
  void Base::acquire(void)
  {
  	m_env_acquire(m_pEnv);
  
      osl_incrementInterlockedCount(&m_nRef);
  }
  
  void Base::release(void)
  {
      if (osl_decrementInterlockedCount(&m_nRef) == 0)
  		delete this;
  
  	else
  		m_env_release(m_pEnv);
  }
  
  void Base::harden(uno_Environment ** ppHardEnv)
  {
  	m_env_harden(ppHardEnv, m_pEnv);
      osl_incrementInterlockedCount(&m_nRef);
  }
  
  void Base::acquireWeak(void)
  {
  	m_env_acquireWeak(m_pEnv);
  }
  
  void Base::releaseWeak(void)
  {
  	m_env_releaseWeak(m_pEnv);
  }
  
  
  extern "C" { static void s_registerProxyInterface_v(va_list * pParam) 
  {
  	uno_ExtEnvironment                   * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
  	void                                ** ppProxy    = va_arg(*pParam, void **);
  	uno_freeProxyFunc                      freeProxy  = va_arg(*pParam, uno_freeProxyFunc);
  	rtl_uString                          * pOId       = va_arg(*pParam, rtl_uString *);
  	typelib_InterfaceTypeDescription     * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
  	ExtEnv_registerProxyInterface  * pRegisterProxyInterface
  		= va_arg(*pParam, ExtEnv_registerProxyInterface *);
  
  	pRegisterProxyInterface(pExtEnv, ppProxy, freeProxy, pOId, pTypeDescr);
  }}
  
  void Base::registerProxyInterface(void                                  ** ppProxy, 
  								  uno_freeProxyFunc                        freeProxy, 
  								  rtl::OUString                    const & oid,
  								  typelib_InterfaceTypeDescription       * pTypeDescr)
  {
   	uno_Environment_invoke(m_pEnv, 
  						   s_registerProxyInterface_v, 
  						   m_pEnv->pExtEnv, 
  						   ppProxy, 
  						   freeProxy,
  						   oid.pData,
  						   pTypeDescr,
  						   m_env_registerProxyInterface);
  }
  
  
  extern "C" { static void s_revokeInterface_v(va_list * pParam) 
  {
  	uno_ExtEnvironment * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
  	void               * pInterface = va_arg(*pParam, void *);
  	ExtEnv_revokeInterface * pRevokeInterface = va_arg(*pParam, ExtEnv_revokeInterface *);
  
  	pRevokeInterface(pExtEnv, pInterface);
  }}
  
  void Base::revokeInterface(void * pInterface)
  {
   	uno_Environment_invoke(m_pEnv, 
  						   s_revokeInterface_v, 
  						   m_pEnv->pExtEnv, 
  						   pInterface, 
  						   m_env_revokeInterface);
  }
  
  
  extern "C" { static void s_getObjectIdentifier_v(va_list * pParam) 
  {
  	uno_ExtEnvironment * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
  	void               * pInterface = va_arg(*pParam, void *);
  	rtl::OUString      * pOId       = va_arg(*pParam, rtl::OUString *);
  	ExtEnv_getObjectIdentifier * pGetObjectIdentifier
  		= va_arg(*pParam, ExtEnv_getObjectIdentifier *);
  
  	pGetObjectIdentifier(pExtEnv, reinterpret_cast<rtl_uString **>(pOId), pInterface);
  }}
  
  void Base::getObjectIdentifier(void * pInterface, rtl::OUString * pOid)
  {
   	uno_Environment_invoke(m_pEnv, 
  						   s_getObjectIdentifier_v, 
  						   m_pEnv->pExtEnv, 
  						   pInterface, 
  						   pOid,
  						   m_env_getObjectIdentifier);
  }
  
  
  extern "C" { static void s_getRegisteredInterface_v(va_list * pParam) 
  {
  	uno_ExtEnvironment                   * pExtEnv     = va_arg(*pParam, uno_ExtEnvironment *);
  	void                                ** ppInterface = va_arg(*pParam, void **);
  	rtl_uString                          * pOId        = va_arg(*pParam, rtl_uString *);
  	typelib_InterfaceTypeDescription     * pTypeDescr  = va_arg(*pParam, typelib_InterfaceTypeDescription *);
  	ExtEnv_getRegisteredInterface  * pGetRegisteredInterface
  		= va_arg(*pParam, ExtEnv_getRegisteredInterface *);
  
  	pGetRegisteredInterface(pExtEnv, ppInterface, pOId, pTypeDescr);
  }}
  
  void Base::getRegisteredInterface(void ** ppInterface, 
  								  rtl::OUString const & oid,
  								  typelib_InterfaceTypeDescription * pTypeDescr)
  {
   	uno_Environment_invoke(m_pEnv, 
  						   s_getRegisteredInterface_v, 
  						   m_pEnv->pExtEnv, 
  						   ppInterface, 
  						   oid.pData,
  						   pTypeDescr,
  						   m_env_getRegisteredInterface);
  }
  
  
  extern "C" { static void s_getRegisteredInterfaces_v(va_list * pParam) 
  {
  	uno_ExtEnvironment   * pExtEnv      = va_arg(*pParam, uno_ExtEnvironment *);
  	void               *** pppInterface = va_arg(*pParam, void ***);
  	sal_Int32            * pnLen        = va_arg(*pParam, sal_Int32 *);
  	uno_memAlloc           memAlloc     = va_arg(*pParam, uno_memAlloc);
  	ExtEnv_getRegisteredInterfaces * pGetRegisteredInterfaces
  		= va_arg(*pParam, ExtEnv_getRegisteredInterfaces *);
  
  	pGetRegisteredInterfaces(pExtEnv, pppInterface, pnLen, memAlloc);
  }}
  
  void Base::getRegisteredInterfaces(void         *** pppInterface, 
  								   sal_Int32      * pnLen,
  								   uno_memAlloc     memAlloc)
  {
   	uno_Environment_invoke(m_pEnv, 
  						   s_getRegisteredInterfaces_v, 
  						   m_pEnv->pExtEnv, 
  						   pppInterface, 
  						   pnLen,
  						   memAlloc,
  						   m_env_getRegisteredInterfaces);
  }
  
  
  extern "C" { static void s_computeObjectIdentifier_v(va_list * pParam) 
  {
  	uno_ExtEnvironment * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
  	void               * pInterface = va_arg(*pParam, void *);
  	rtl::OUString      * pOId       = va_arg(*pParam, rtl::OUString *);
  	ExtEnv_computeObjectIdentifier * pComputeObjectIdentifier
  		= va_arg(*pParam, ExtEnv_computeObjectIdentifier *);
  
  	pComputeObjectIdentifier(pExtEnv, reinterpret_cast<rtl_uString **>(pOId), pInterface);
  }}
  
  void Base::computeObjectIdentifier(void * pInterface, rtl::OUString * pOid)
  {
   	uno_Environment_invoke(m_pEnv, 
  						   s_computeObjectIdentifier_v, 
  						   m_pEnv->pExtEnv, 
  						   pInterface, 
  						   pOid,
  						   m_env_computeObjectIdentifier);
  }
  
  
  extern "C" { static void s_acquireInterface_v(va_list * pParam) 
  {
  	uno_ExtEnvironment * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
  	void               * pInterface = va_arg(*pParam, void *);
  	ExtEnv_acquireInterface * pAcquireInterface 
  		= va_arg(*pParam, ExtEnv_acquireInterface *);
  
  	pAcquireInterface(pExtEnv, pInterface);
  }}
  
  void Base::acquireInterface(void * pInterface)
  {
   	uno_Environment_invoke(m_pEnv, s_acquireInterface_v, m_pEnv->pExtEnv, pInterface, m_env_acquireInterface);
  }
  
  
  extern "C" { static void s_releaseInterface_v(va_list * pParam) 
  {
  	uno_ExtEnvironment * pExtEnv    = va_arg(*pParam, uno_ExtEnvironment *);
  	void               * pInterface = va_arg(*pParam, void *);
  	ExtEnv_releaseInterface * pReleaseInterface
  		= va_arg(*pParam, ExtEnv_releaseInterface *);
  
  	pReleaseInterface(pExtEnv, pInterface);
  }}
  
  void Base::releaseInterface(void * pInterface)
  {
   	uno_Environment_invoke(m_pEnv, 
  						   s_releaseInterface_v, 
  						   m_pEnv->pExtEnv, 
  						   pInterface, 
  						   m_env_releaseInterface);
  }
  
  void Base::v_enter(void)
  {
      m_pEnterable->enter();
  }
  
  void Base::v_leave(void)
  {
      m_pEnterable->leave();
  }
  
  void Base::v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam)
  {
      m_pEnterable->callInto_v(pCallee, pParam);
  }
  
  void Base::v_callOut_v(uno_EnvCallee * pCallee, va_list * pParam)
  {
      m_pEnterable->callOut_v(pCallee, pParam);
  }
  
  int Base::v_isValid(rtl::OUString * pReason) 
  {
      return m_pEnterable->isValid(pReason);
  }
  
  namespace cppu { namespace helper { namespace purpenv {
  
  void Environment_initWithEnterable(uno_Environment * pEnvironment, cppu::Enterable * pEnterable)
  {
      new Base(pEnvironment, pEnterable);
  }
  
  }}}
  