CONNPT.CPP
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:11k
源码类别:
Windows编程
开发平台:
Visual C++
- /*
- * 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;
- }