206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync/* $Id$ */
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync/** @file
17bbfe820c22c3e599276890d8b7baa48c32abbbvboxsync * MS COM / XPCOM Abstraction Layer - Listeners helpers.
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync */
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync/*
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync * Copyright (C) 2010-2011 Oracle Corporation
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync *
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * available from http://www.virtualbox.org. This file is free software;
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * General Public License (GPL) as published by the Free Software
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync *
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * The contents of this file may alternatively be used under the terms
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * of the Common Development and Distribution License Version 1.0
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * CDDL are applicable instead of those of the GPL.
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync *
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * You may elect to license modified versions of this file under the
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync * terms and conditions of either the GPL or the CDDL or both.
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync */
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#ifndef ___VBox_com_listeners_h
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#define ___VBox_com_listeners_h
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#include <VBox/com/com.h>
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync#include <VBox/com/VirtualBox.h>
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#ifdef VBOX_WITH_XPCOM
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync# define NS_IMPL_QUERY_HEAD_INLINE() \
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsyncNS_IMETHODIMP QueryInterface(REFNSIID aIID, void **aInstancePtr) \
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync{ \
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!"); \
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync nsISupports *foundInterface;
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync# define NS_INTERFACE_MAP_BEGIN_INLINE() NS_IMPL_QUERY_HEAD_INLINE()
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync# define NS_IMPL_QUERY_INTERFACE1_INLINE(a_i1) \
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync NS_INTERFACE_MAP_BEGIN_INLINE() \
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync NS_INTERFACE_MAP_ENTRY(a_i1) \
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, a_i1) \
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync NS_INTERFACE_MAP_END
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#endif
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsynctemplate <class T, class TParam = void *>
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsyncclass ListenerImpl :
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync public CComObjectRootEx<CComMultiThreadModel>,
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync VBOX_SCRIPTABLE_IMPL(IEventListener)
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync{
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync T* mListener;
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync#ifdef RT_OS_WINDOWS
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync /* FTM stuff */
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync CComPtr <IUnknown> m_pUnkMarshaler;
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync#else
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync nsAutoRefCnt mRefCnt;
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync NS_DECL_OWNINGTHREAD
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync#endif
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsyncpublic:
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync ListenerImpl()
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync {
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync }
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync virtual ~ListenerImpl()
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync {
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync }
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync HRESULT init(T* aListener, TParam param)
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync {
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync mListener = aListener;
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync return mListener->init(param);
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync }
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync HRESULT init(T* aListener)
23b6bee7e2c689903bbe3844f614ca70af5d62ccvboxsync {
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync mListener = aListener;
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync return mListener->init();
23b6bee7e2c689903bbe3844f614ca70af5d62ccvboxsync }
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync void uninit()
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync {
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync if (mListener)
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync {
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync mListener->uninit();
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync delete mListener;
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync mListener = 0;
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync }
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync }
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync HRESULT FinalConstruct()
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync {
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#ifdef RT_OS_WINDOWS
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync return CoCreateFreeThreadedMarshaler(this, &m_pUnkMarshaler.p);
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#else
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync return S_OK;
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#endif
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync }
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync void FinalRelease()
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync {
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync uninit();
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#ifdef RT_OS_WINDOWS
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync m_pUnkMarshaler.Release();
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#endif
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync }
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync T* getWrapped()
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync {
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync return mListener;
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync }
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync DECLARE_NOT_AGGREGATABLE(ListenerImpl)
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync DECLARE_PROTECT_FINAL_CONSTRUCT()
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync#ifdef RT_OS_WINDOWS
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync BEGIN_COM_MAP(ListenerImpl)
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync COM_INTERFACE_ENTRY(IEventListener)
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync COM_INTERFACE_ENTRY2(IDispatch, IEventListener)
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p)
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync END_COM_MAP()
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync#else
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync NS_IMETHOD_(nsrefcnt) AddRef(void)
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync {
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync nsrefcnt count;
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync count = PR_AtomicIncrement((PRInt32*)&mRefCnt);
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync NS_LOG_ADDREF(this, count, "ListenerImpl", sizeof(*this));
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync return count;
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync }
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync NS_IMETHOD_(nsrefcnt) Release(void)
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync {
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync nsrefcnt count;
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync NS_PRECONDITION(0 != mRefCnt, "dup release");
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync NS_LOG_RELEASE(this, count, "ListenerImpl");
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync if (0 == count) {
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync mRefCnt = 1; /* stabilize */
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync /* enable this to find non-threadsafe destructors: */
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync /* NS_ASSERT_OWNINGTHREAD(_class); */
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync NS_DELETEXPCOM(this);
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync return 0;
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync }
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync return count;
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync }
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync NS_IMPL_QUERY_INTERFACE1_INLINE(IEventListener)
48cc5ec10dfb2e17176457b2593379ce1e296aeavboxsync#endif
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync STDMETHOD(HandleEvent)(IEvent * aEvent)
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync {
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync VBoxEventType_T aType = VBoxEventType_Invalid;
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync aEvent->COMGETTER(Type)(&aType);
0e1df2d387f24e745916e4a97a3c28da018d1189vboxsync return mListener->HandleEvent(aType, aEvent);
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync }
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync};
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#ifdef VBOX_WITH_XPCOM
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync# define VBOX_LISTENER_DECLARE(klazz) NS_DECL_CLASSINFO(klazz)
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#else
7420e5ee5565b181c144eabb14da0da9e8cce657vboxsync# define VBOX_LISTENER_DECLARE(klazz)
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#endif
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync
206886290dbecc59a96634c1d4c9812f12dc21f9vboxsync#endif
17bbfe820c22c3e599276890d8b7baa48c32abbbvboxsync