CONNPT.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:11k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * CONNPT.CPP
  3.  *
  4.  * Implemenation of a connection point object that manages
  5.  * IUnknown pointers.  This is a stand-alone object created from
  6.  * the implementation of IConnectionPointContainer.
  7.  *
  8.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Microsoft
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  13.  */
  14. #include "connect.h"
  15. /*
  16.  * CConnectionPoint::CConnectionPoint
  17.  * CConnectionPoint::~CConnectionPoint
  18.  *
  19.  * Parameters (Constructor):
  20.  *  pObj            PCConnObject of the object we're in.  We can
  21.  *                  query this for the IConnectionPointContainer
  22.  *                  interface we might need.
  23.  *  riid            REFIID of the interface we're supporting
  24.  */
  25. CConnectionPoint::CConnectionPoint(PCConnObject pObj, REFIID riid)
  26.     {
  27.     UINT        i;
  28.     m_cRef=0;
  29.     m_iid=riid;
  30.     /*
  31.      * Our lifetime is controlled by the connectable object itself,
  32.      * although other external clients will call AddRef and Release.
  33.      * Since we're nested in the connectable object's lifetime,
  34.      * there's no need to call AddRef on pObj.
  35.      */
  36.     m_pObj=pObj;
  37.     for (i=0; i < CCONNMAX; i++)
  38.         {
  39.         m_rgpIUnknown[i]=NULL;
  40.         m_rgdwCookies[i]=0;
  41.         }
  42.     m_cConn=0;
  43.     m_dwCookieNext=100;       //Arbitrary starting cookie value
  44.     return;
  45.     }
  46. CConnectionPoint::~CConnectionPoint(void)
  47.     {
  48.     UINT        i;
  49.     for (i=0; i < CCONNMAX; i++)
  50.         ReleaseInterface(m_rgpIUnknown[i]);
  51.     return;
  52.     }
  53. /*
  54.  * CConnectionPoint::QueryInterface
  55.  * CConnectionPoint::AddRef
  56.  * CConnectionPoint::Release
  57.  *
  58.  * Purpose:
  59.  *  Non-delegating IUnknown members for CConnectionPoint.
  60.  */
  61. STDMETHODIMP CConnectionPoint::QueryInterface(REFIID riid
  62.     , LPVOID *ppv)
  63.     {
  64.     *ppv=NULL;
  65.     if (IID_IUnknown==riid || IID_IConnectionPoint==riid)
  66.         *ppv=(LPVOID)this;
  67.     if (NULL!=*ppv)
  68.         {
  69.         ((LPUNKNOWN)*ppv)->AddRef();
  70.         return NOERROR;
  71.         }
  72.     return ResultFromScode(E_NOINTERFACE);
  73.     }
  74. STDMETHODIMP_(ULONG) CConnectionPoint::AddRef(void)
  75.     {
  76.     return ++m_cRef;
  77.     }
  78. STDMETHODIMP_(ULONG) CConnectionPoint::Release(void)
  79.     {
  80.     if (0!=--m_cRef)
  81.         return m_cRef;
  82.     delete this;
  83.     return 0;
  84.     }
  85. /*
  86.  * CConnectionPoint::GetConnectionInterface
  87.  *
  88.  * Purpose:
  89.  *  Returns the IID of the outgoing interface supported through
  90.  *  this connection point.
  91.  *
  92.  * Parameters:
  93.  *  pIID            IID * in which to store the IID.
  94.  */
  95. STDMETHODIMP CConnectionPoint::GetConnectionInterface(IID *pIID)
  96.     {
  97.     if (NULL==pIID)
  98.         return ResultFromScode(E_POINTER);
  99.     *pIID=m_iid;
  100.     return NOERROR;
  101.     }
  102. /*
  103.  * CConnectionPoint::GetConnectionPointContainer
  104.  *
  105.  * Purpose:
  106.  *  Returns a pointer to the IConnectionPointContainer that
  107.  *  is manageing this connection point.
  108.  *
  109.  * Parameters:
  110.  *  ppCPC           IConnectionPointContainer ** in which to return
  111.  *                  the pointer after calling AddRef.
  112.  */
  113. STDMETHODIMP CConnectionPoint::GetConnectionPointContainer
  114.     (IConnectionPointContainer **ppCPC)
  115.     {
  116.     return m_pObj->QueryInterface(IID_IConnectionPointContainer
  117.         , (void **)ppCPC);
  118.     }
  119. /*
  120.  * CConnectionPoint::Advise
  121.  *
  122.  * Purpose:
  123.  *  Provides this connection point with a notification sink to
  124.  *  call whenever the appropriate outgoing function/event occurs.
  125.  *
  126.  * Parameters:
  127.  *  pUnkSink        LPUNKNOWN to the sink to notify.  The connection
  128.  *                  point must QueryInterface on this pointer to obtain
  129.  *                  the proper interface to call.  The connection
  130.  *                  point must also insure that any pointer held has
  131.  *                  a reference count (QueryInterface will do it).
  132.  *  pdwCookie       DWORD * in which to store the connection key for
  133.  *                  later calls to Unadvise.
  134.  */
  135. STDMETHODIMP CConnectionPoint::Advise(LPUNKNOWN pUnkSink
  136.     , DWORD *pdwCookie)
  137.     {
  138.     UINT            i;
  139.     IUnknown       *pSink;
  140.     *pdwCookie=0;
  141.     //Check if we're already full of sink pointers
  142.     if (CCONNMAX==m_cConn)
  143.         return ResultFromScode(CONNECT_E_ADVISELIMIT);
  144.     /*
  145.      * Verify that the sink has the interface it's supposed
  146.      * to.  We don't have to know what it is because we have
  147.      * m_iid to describe it.  If this works, then we neatly
  148.      * have a pointer with an AddRef that we can stow away.
  149.      */
  150.     if (FAILED(pUnkSink->QueryInterface(m_iid, (PPVOID)&pSink)))
  151.         return ResultFromScode(CONNECT_E_CANNOTCONNECT);
  152.     /*
  153.      * We got the sink, now store it in our array.  We'll look for
  154.      * the first entry that is NULL, indicating a free spot.
  155.      */
  156.     for (i=0; i < CCONNMAX; i++)
  157.         {
  158.         if (NULL==m_rgpIUnknown[i])
  159.             {
  160.             m_rgpIUnknown[i]=pSink;
  161.             /*
  162.              * Note:  this increment is not thread safe.  Needs
  163.              * to be blocked with a semaphore if this were a
  164.              * multi-threaded object.
  165.              */
  166.             m_rgdwCookies[i]=++m_dwCookieNext;
  167.             *pdwCookie=m_dwCookieNext;
  168.             break;
  169.             }
  170.         }
  171.     m_cConn++;
  172.     return NOERROR;
  173.     }
  174. /*
  175.  * CConnectionPoint::Unadvise
  176.  *
  177.  * Purpose:
  178.  *  Terminates the connection to the notification sink identified
  179.  *  with dwCookie (that was returned from Advise).  The connection
  180.  *  point has to Release any held pointers for that sink.
  181.  *
  182.  * Parameters:
  183.  *  dwCookie        DWORD connection key from Advise.
  184.  */
  185. STDMETHODIMP CConnectionPoint::Unadvise(DWORD dwCookie)
  186.     {
  187.     UINT        i;
  188.     if (0==dwCookie)
  189.         return ResultFromScode(E_INVALIDARG);
  190.     for (i=0; i < CCONNMAX; i++)
  191.         {
  192.         if (dwCookie==m_rgdwCookies[i])
  193.             {
  194.             //This releases the sink and sets the pointer to NULL
  195.             ReleaseInterface(m_rgpIUnknown[i]);
  196.             m_rgdwCookies[i]=0;
  197.             m_cConn--;
  198.             return NOERROR;
  199.             }
  200.         }
  201.     return ResultFromScode(CONNECT_E_NOCONNECTION);
  202.     }
  203. /*
  204.  * CConnectionPoint::EnumConnections
  205.  *
  206.  * Purpose:
  207.  *  Creates and returns an enumerator object with the
  208.  *  IEnumConnections interface that will enumerate the IUnknown
  209.  *  pointers of each connected sink.
  210.  *
  211.  * Parameters:
  212.  *  ppEnum          LPENUMCONNECTIONS in which to store the
  213.  *                  IEnumConnections pointer.
  214.  */
  215. STDMETHODIMP CConnectionPoint::EnumConnections
  216.     (LPENUMCONNECTIONS *ppEnum)
  217.     {
  218.     LPCONNECTDATA       pCD;
  219.     UINT                i, j;
  220.     PCEnumConnections   pEnum;
  221.     *ppEnum=NULL;
  222.     if (0==m_cConn)
  223.         return ResultFromScode(OLE_E_NOCONNECTION);
  224.     /*
  225.      * Create the array of CONNECTDATA structures to give to the
  226.      * enumerator.
  227.      */
  228.     pCD=new CONNECTDATA[(UINT)m_cConn];
  229.     if (NULL==pCD)
  230.         return ResultFromScode(E_OUTOFMEMORY);
  231.     for (i=0, j=0; i < CCONNMAX; i++)
  232.         {
  233.         if (NULL!=m_rgpIUnknown[i])
  234.             {
  235.             pCD[j].pUnk=(LPUNKNOWN)m_rgpIUnknown[i];
  236.             pCD[j].dwCookie=m_rgdwCookies[i];
  237.             j++;
  238.             }
  239.         }
  240.     /*
  241.      * If creation works, it makes a copy pCD, so we can
  242.      * always delete it regardless of the outcome.
  243.      */
  244.     pEnum=new CEnumConnections(this, m_cConn, pCD);
  245.     delete [] pCD;
  246.     if (NULL==pEnum)
  247.         return ResultFromScode(E_OUTOFMEMORY);
  248.     //This does an AddRef for us.
  249.     return pEnum->QueryInterface(IID_IEnumConnections, (PPVOID)ppEnum);
  250.     }
  251. //Connection Enumerator follows
  252. /*
  253.  * CEnumConnections::CEnumConnections
  254.  * CEnumConnections::~CEnumConnections
  255.  *
  256.  * Parameters (Constructor):
  257.  *  pUnkRef         LPUNKNOWN to use for reference counting.
  258.  *  cConn           ULONG number of connections in prgpConn
  259.  *  prgConnData     LPCONNECTDATA to the array to enumerate.
  260.  */
  261. CEnumConnections::CEnumConnections(LPUNKNOWN pUnkRef, ULONG cConn
  262.     , LPCONNECTDATA prgConnData)
  263.     {
  264.     UINT        i;
  265.     m_cRef=0;
  266.     m_pUnkRef=pUnkRef;
  267.     m_iCur=0;
  268.     m_cConn=cConn;
  269.     /*
  270.      * Copy the passed array.  We need to do this because a clone
  271.      * has to have its own copy as well.
  272.      */
  273.     m_rgConnData=new CONNECTDATA[(UINT)cConn];
  274.     if (NULL!=m_rgConnData)
  275.         {
  276.         for (i=0; i < cConn; i++)
  277.             {
  278.             m_rgConnData[i]=prgConnData[i];
  279.             m_rgConnData[i].pUnk->AddRef();
  280.             }
  281.         }
  282.     return;
  283.     }
  284. CEnumConnections::~CEnumConnections(void)
  285.     {
  286.     if (NULL!=m_rgConnData)
  287.         {
  288.         UINT        i;
  289.         for (i=0; i < m_cConn; i++)
  290.             m_rgConnData[i].pUnk->Release();
  291.         delete [] m_rgConnData;
  292.         }
  293.     return;
  294.     }
  295. /*
  296.  * CEnumConnections::QueryInterface
  297.  * CEnumConnections::AddRef
  298.  * CEnumConnections::Release
  299.  *
  300.  * Purpose:
  301.  *  IUnknown members for CEnumConnections object.
  302.  */
  303. STDMETHODIMP CEnumConnections::QueryInterface(REFIID riid
  304.     , LPVOID *ppv)
  305.     {
  306.     *ppv=NULL;
  307.     if (IID_IUnknown==riid || IID_IEnumConnections==riid)
  308.         *ppv=(LPVOID)this;
  309.     if (NULL!=*ppv)
  310.         {
  311.         ((LPUNKNOWN)*ppv)->AddRef();
  312.         return NOERROR;
  313.         }
  314.     return ResultFromScode(E_NOINTERFACE);
  315.     }
  316. STDMETHODIMP_(ULONG) CEnumConnections::AddRef(void)
  317.     {
  318.     ++m_cRef;
  319.     m_pUnkRef->AddRef();
  320.     return m_cRef;
  321.     }
  322. STDMETHODIMP_(ULONG) CEnumConnections::Release(void)
  323.     {
  324.     m_pUnkRef->Release();
  325.     if (0L!=--m_cRef)
  326.         return m_cRef;
  327.     delete this;
  328.     return 0;
  329.     }
  330. /*
  331.  * CEnumConnections::Next
  332.  *
  333.  * Purpose:
  334.  *  Returns the next element in the enumeration.
  335.  *
  336.  * Parameters:
  337.  *  cConn           ULONG number of connections to return.
  338.  *  pConnData       LPCONNECTDATA in which to store the returned
  339.  *                  structures.
  340.  *  pulEnum         ULONG * in which to return how many we
  341.  *                  enumerated.
  342.  *
  343.  * Return Value:
  344.  *  HRESULT         NOERROR if successful, S_FALSE otherwise,
  345.  */
  346. STDMETHODIMP CEnumConnections::Next(ULONG cConn
  347.     , LPCONNECTDATA pConnData, ULONG *pulEnum)
  348.     {
  349.     ULONG               cReturn=0L;
  350.     if (NULL==m_rgConnData)
  351.         return ResultFromScode(S_FALSE);
  352.     if (NULL==pulEnum)
  353.         {
  354.         if (1L!=cConn)
  355.             return ResultFromScode(E_POINTER);
  356.         }
  357.     else
  358.         *pulEnum=0L;
  359.     if (NULL==pConnData || m_iCur >= m_cConn)
  360.         return ResultFromScode(S_FALSE);
  361.     while (m_iCur < m_cConn && cConn > 0)
  362.         {
  363.         *pConnData++=m_rgConnData[m_iCur];
  364.         m_rgConnData[m_iCur++].pUnk->AddRef();
  365.         cReturn++;
  366.         cConn--;
  367.         }
  368.     if (NULL!=pulEnum)
  369.         *pulEnum=cReturn;
  370.     return NOERROR;
  371.     }
  372. STDMETHODIMP CEnumConnections::Skip(ULONG cSkip)
  373.     {
  374.     if (((m_iCur+cSkip) >= m_cConn) || NULL==m_rgConnData)
  375.         return ResultFromScode(S_FALSE);
  376.     m_iCur+=cSkip;
  377.     return NOERROR;
  378.     }
  379. STDMETHODIMP CEnumConnections::Reset(void)
  380.     {
  381.     m_iCur=0;
  382.     return NOERROR;
  383.     }
  384. STDMETHODIMP CEnumConnections::Clone(LPENUMCONNECTIONS *ppEnum)
  385.     {
  386.     PCEnumConnections   pNew;
  387.     *ppEnum=NULL;
  388.     //Create the clone
  389.     pNew=new CEnumConnections(m_pUnkRef, m_cConn, m_rgConnData);
  390.     if (NULL==pNew)
  391.         return ResultFromScode(E_OUTOFMEMORY);
  392.     pNew->AddRef();
  393.     pNew->m_iCur=m_iCur;
  394.     *ppEnum=pNew;
  395.     return NOERROR;
  396.     }