⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connpt.cpp

📁 英文版的 想要的话可以下载了 为大家服务
💻 CPP
字号:
/*
 * CONNPT.CPP
 *
 * Implemenation of a connection point object that manages
 * IUnknown pointers.  This is a stand-alone object created from
 * the implementation of IConnectionPointContainer.
 *
 * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
 *
 * Kraig Brockschmidt, Microsoft
 * Internet  :  kraigb@microsoft.com
 * Compuserve:  >INTERNET:kraigb@microsoft.com
 */


#include "connect.h"


/*
 * CConnectionPoint::CConnectionPoint
 * CConnectionPoint::~CConnectionPoint
 *
 * Parameters (Constructor):
 *  pObj            PCConnObject of the object we're in.  We can
 *                  query this for the IConnectionPointContainer
 *                  interface we might need.
 *  riid            REFIID of the interface we're supporting
 */

CConnectionPoint::CConnectionPoint(PCConnObject pObj, REFIID riid)
    {
    UINT        i;

    m_cRef=0;
    m_iid=riid;

    /*
     * Our lifetime is controlled by the connectable object itself,
     * although other external clients will call AddRef and Release.
     * Since we're nested in the connectable object's lifetime,
     * there's no need to call AddRef on pObj.
     */
    m_pObj=pObj;

    for (i=0; i < CCONNMAX; i++)
        {
        m_rgpIUnknown[i]=NULL;
        m_rgdwCookies[i]=0;
        }

    m_cConn=0;
    m_dwCookieNext=100;       //Arbitrary starting cookie value
    return;
    }

CConnectionPoint::~CConnectionPoint(void)
    {
    UINT        i;

    for (i=0; i < CCONNMAX; i++)
        ReleaseInterface(m_rgpIUnknown[i]);

    return;
    }



/*
 * CConnectionPoint::QueryInterface
 * CConnectionPoint::AddRef
 * CConnectionPoint::Release
 *
 * Purpose:
 *  Non-delegating IUnknown members for CConnectionPoint.
 */

STDMETHODIMP CConnectionPoint::QueryInterface(REFIID riid
    , LPVOID *ppv)
    {
    *ppv=NULL;

    if (IID_IUnknown==riid || IID_IConnectionPoint==riid)
        *ppv=(LPVOID)this;

    if (NULL!=*ppv)
        {
        ((LPUNKNOWN)*ppv)->AddRef();
        return NOERROR;
        }

    return ResultFromScode(E_NOINTERFACE);
    }

STDMETHODIMP_(ULONG) CConnectionPoint::AddRef(void)
    {
    return ++m_cRef;
    }

STDMETHODIMP_(ULONG) CConnectionPoint::Release(void)
    {
    if (0!=--m_cRef)
        return m_cRef;

    delete this;
    return 0;
    }



/*
 * CConnectionPoint::GetConnectionInterface
 *
 * Purpose:
 *  Returns the IID of the outgoing interface supported through
 *  this connection point.
 *
 * Parameters:
 *  pIID            IID * in which to store the IID.
 */

STDMETHODIMP CConnectionPoint::GetConnectionInterface(IID *pIID)
    {
    if (NULL==pIID)
        return ResultFromScode(E_POINTER);

    *pIID=m_iid;
    return NOERROR;
    }



/*
 * CConnectionPoint::GetConnectionPointContainer
 *
 * Purpose:
 *  Returns a pointer to the IConnectionPointContainer that
 *  is manageing this connection point.
 *
 * Parameters:
 *  ppCPC           IConnectionPointContainer ** in which to return
 *                  the pointer after calling AddRef.
 */

STDMETHODIMP CConnectionPoint::GetConnectionPointContainer
    (IConnectionPointContainer **ppCPC)
    {
    return m_pObj->QueryInterface(IID_IConnectionPointContainer
        , (void **)ppCPC);
    }



/*
 * CConnectionPoint::Advise
 *
 * Purpose:
 *  Provides this connection point with a notification sink to
 *  call whenever the appropriate outgoing function/event occurs.
 *
 * Parameters:
 *  pUnkSink        LPUNKNOWN to the sink to notify.  The connection
 *                  point must QueryInterface on this pointer to obtain
 *                  the proper interface to call.  The connection
 *                  point must also insure that any pointer held has
 *                  a reference count (QueryInterface will do it).
 *  pdwCookie       DWORD * in which to store the connection key for
 *                  later calls to Unadvise.
 */

STDMETHODIMP CConnectionPoint::Advise(LPUNKNOWN pUnkSink
    , DWORD *pdwCookie)
    {
    UINT            i;
    IUnknown       *pSink;

    *pdwCookie=0;

    //Check if we're already full of sink pointers
    if (CCONNMAX==m_cConn)
        return ResultFromScode(CONNECT_E_ADVISELIMIT);

    /*
     * Verify that the sink has the interface it's supposed
     * to.  We don't have to know what it is because we have
     * m_iid to describe it.  If this works, then we neatly
     * have a pointer with an AddRef that we can stow away.
     */
    if (FAILED(pUnkSink->QueryInterface(m_iid, (PPVOID)&pSink)))
        return ResultFromScode(CONNECT_E_CANNOTCONNECT);

    /*
     * We got the sink, now store it in our array.  We'll look for
     * the first entry that is NULL, indicating a free spot.
     */
    for (i=0; i < CCONNMAX; i++)
        {
        if (NULL==m_rgpIUnknown[i])
            {
            m_rgpIUnknown[i]=pSink;

            /*
             * Note:  this increment is not thread safe.  Needs
             * to be blocked with a semaphore if this were a
             * multi-threaded object.
             */
            m_rgdwCookies[i]=++m_dwCookieNext;
            *pdwCookie=m_dwCookieNext;
            break;
            }
        }

    m_cConn++;
    return NOERROR;
    }



/*
 * CConnectionPoint::Unadvise
 *
 * Purpose:
 *  Terminates the connection to the notification sink identified
 *  with dwCookie (that was returned from Advise).  The connection
 *  point has to Release any held pointers for that sink.
 *
 * Parameters:
 *  dwCookie        DWORD connection key from Advise.
 */

STDMETHODIMP CConnectionPoint::Unadvise(DWORD dwCookie)
    {
    UINT        i;

    if (0==dwCookie)
        return ResultFromScode(E_INVALIDARG);

    for (i=0; i < CCONNMAX; i++)
        {
        if (dwCookie==m_rgdwCookies[i])
            {
            //This releases the sink and sets the pointer to NULL
            ReleaseInterface(m_rgpIUnknown[i]);
            m_rgdwCookies[i]=0;
            m_cConn--;
            return NOERROR;
            }
        }

    return ResultFromScode(CONNECT_E_NOCONNECTION);
    }



/*
 * CConnectionPoint::EnumConnections
 *
 * Purpose:
 *  Creates and returns an enumerator object with the
 *  IEnumConnections interface that will enumerate the IUnknown
 *  pointers of each connected sink.
 *
 * Parameters:
 *  ppEnum          LPENUMCONNECTIONS in which to store the
 *                  IEnumConnections pointer.
 */

STDMETHODIMP CConnectionPoint::EnumConnections
    (LPENUMCONNECTIONS *ppEnum)
    {
    LPCONNECTDATA       pCD;
    UINT                i, j;
    PCEnumConnections   pEnum;

    *ppEnum=NULL;

    if (0==m_cConn)
        return ResultFromScode(OLE_E_NOCONNECTION);

    /*
     * Create the array of CONNECTDATA structures to give to the
     * enumerator.
     */
    pCD=new CONNECTDATA[(UINT)m_cConn];

    if (NULL==pCD)
        return ResultFromScode(E_OUTOFMEMORY);

    for (i=0, j=0; i < CCONNMAX; i++)
        {
        if (NULL!=m_rgpIUnknown[i])
            {
            pCD[j].pUnk=(LPUNKNOWN)m_rgpIUnknown[i];
            pCD[j].dwCookie=m_rgdwCookies[i];
            j++;
            }
        }

    /*
     * If creation works, it makes a copy pCD, so we can
     * always delete it regardless of the outcome.
     */
    pEnum=new CEnumConnections(this, m_cConn, pCD);
    delete [] pCD;

    if (NULL==pEnum)
        return ResultFromScode(E_OUTOFMEMORY);

    //This does an AddRef for us.
    return pEnum->QueryInterface(IID_IEnumConnections, (PPVOID)ppEnum);
    }




//Connection Enumerator follows


/*
 * CEnumConnections::CEnumConnections
 * CEnumConnections::~CEnumConnections
 *
 * Parameters (Constructor):
 *  pUnkRef         LPUNKNOWN to use for reference counting.
 *  cConn           ULONG number of connections in prgpConn
 *  prgConnData     LPCONNECTDATA to the array to enumerate.
 */

CEnumConnections::CEnumConnections(LPUNKNOWN pUnkRef, ULONG cConn
    , LPCONNECTDATA prgConnData)
    {
    UINT        i;

    m_cRef=0;
    m_pUnkRef=pUnkRef;

    m_iCur=0;
    m_cConn=cConn;

    /*
     * Copy the passed array.  We need to do this because a clone
     * has to have its own copy as well.
     */
    m_rgConnData=new CONNECTDATA[(UINT)cConn];

    if (NULL!=m_rgConnData)
        {
        for (i=0; i < cConn; i++)
            {
            m_rgConnData[i]=prgConnData[i];
            m_rgConnData[i].pUnk->AddRef();
            }
        }

    return;
    }


CEnumConnections::~CEnumConnections(void)
    {
    if (NULL!=m_rgConnData)
        {
        UINT        i;

        for (i=0; i < m_cConn; i++)
            m_rgConnData[i].pUnk->Release();

        delete [] m_rgConnData;
        }

    return;
    }




/*
 * CEnumConnections::QueryInterface
 * CEnumConnections::AddRef
 * CEnumConnections::Release
 *
 * Purpose:
 *  IUnknown members for CEnumConnections object.
 */

STDMETHODIMP CEnumConnections::QueryInterface(REFIID riid
    , LPVOID *ppv)
    {
    *ppv=NULL;

    if (IID_IUnknown==riid || IID_IEnumConnections==riid)
        *ppv=(LPVOID)this;

    if (NULL!=*ppv)
        {
        ((LPUNKNOWN)*ppv)->AddRef();
        return NOERROR;
        }

    return ResultFromScode(E_NOINTERFACE);
    }


STDMETHODIMP_(ULONG) CEnumConnections::AddRef(void)
    {
    ++m_cRef;
    m_pUnkRef->AddRef();
    return m_cRef;
    }

STDMETHODIMP_(ULONG) CEnumConnections::Release(void)
    {
    m_pUnkRef->Release();

    if (0L!=--m_cRef)
        return m_cRef;

    delete this;
    return 0;
    }





/*
 * CEnumConnections::Next
 *
 * Purpose:
 *  Returns the next element in the enumeration.
 *
 * Parameters:
 *  cConn           ULONG number of connections to return.
 *  pConnData       LPCONNECTDATA in which to store the returned
 *                  structures.
 *  pulEnum         ULONG * in which to return how many we
 *                  enumerated.
 *
 * Return Value:
 *  HRESULT         NOERROR if successful, S_FALSE otherwise,
 */

STDMETHODIMP CEnumConnections::Next(ULONG cConn
    , LPCONNECTDATA pConnData, ULONG *pulEnum)
    {
    ULONG               cReturn=0L;

    if (NULL==m_rgConnData)
        return ResultFromScode(S_FALSE);

    if (NULL==pulEnum)
        {
        if (1L!=cConn)
            return ResultFromScode(E_POINTER);
        }
    else
        *pulEnum=0L;

    if (NULL==pConnData || m_iCur >= m_cConn)
        return ResultFromScode(S_FALSE);

    while (m_iCur < m_cConn && cConn > 0)
        {
        *pConnData++=m_rgConnData[m_iCur];
        m_rgConnData[m_iCur++].pUnk->AddRef();
        cReturn++;
        cConn--;
        }

    if (NULL!=pulEnum)
        *pulEnum=cReturn;

    return NOERROR;
    }



STDMETHODIMP CEnumConnections::Skip(ULONG cSkip)
    {
    if (((m_iCur+cSkip) >= m_cConn) || NULL==m_rgConnData)
        return ResultFromScode(S_FALSE);

    m_iCur+=cSkip;
    return NOERROR;
    }


STDMETHODIMP CEnumConnections::Reset(void)
    {
    m_iCur=0;
    return NOERROR;
    }


STDMETHODIMP CEnumConnections::Clone(LPENUMCONNECTIONS *ppEnum)
    {
    PCEnumConnections   pNew;

    *ppEnum=NULL;

    //Create the clone
    pNew=new CEnumConnections(m_pUnkRef, m_cConn, m_rgConnData);

    if (NULL==pNew)
        return ResultFromScode(E_OUTOFMEMORY);

    pNew->AddRef();
    pNew->m_iCur=m_iCur;

    *ppEnum=pNew;
    return NOERROR;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -