| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 |
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- #include "stdafx.h"
- #ifdef AFXCTL_CORE3_SEG
- #pragma code_seg(AFXCTL_CORE3_SEG)
- #endif
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- #define new DEBUG_NEW
- #define GetConnectionPtr(pTarget, pEntry) \
- (LPCONNECTIONPOINT)((char*)pTarget + pEntry->nOffset + \
- offsetof(CConnectionPoint, m_xConnPt))
- /////////////////////////////////////////////////////////////////////////////
- // CConnectionPoint
- CConnectionPoint::CConnectionPoint() :
- m_pUnkFirstConnection(NULL),
- m_pConnections(NULL)
- {
- }
- CConnectionPoint::~CConnectionPoint()
- {
- POSITION pos = GetStartPosition();
- while (pos != NULL)
- {
- LPUNKNOWN pUnk = GetNextConnection(pos);
- ASSERT(pUnk != NULL);
- pUnk->Release();
- }
- if (m_pConnections != NULL)
- delete m_pConnections;
- }
- POSITION CConnectionPoint::GetStartPosition() const
- {
- ASSERT(m_pConnections == NULL || m_pUnkFirstConnection == NULL);
- if (m_pUnkFirstConnection != NULL)
- return (POSITION)-1;
- if (m_pConnections == NULL || m_pConnections->GetSize() == 0)
- return NULL;
- return (POSITION)1;
- }
- LPUNKNOWN CConnectionPoint::GetNextConnection(POSITION& pos) const
- {
- ASSERT(pos != NULL);
- if (pos == (POSITION)-1)
- {
- ASSERT(m_pUnkFirstConnection != NULL);
- ASSERT(m_pConnections == NULL);
- pos = NULL;
- return m_pUnkFirstConnection;
- }
- ASSERT(m_pConnections != NULL);
- ASSERT((long)pos > 0 && (long)pos <= m_pConnections->GetSize());
- int nIndex = (long)pos - 1;
- pos = (POSITION)((long)pos + 1);
- if ((long)pos > m_pConnections->GetSize())
- pos = NULL;
- return (LPUNKNOWN)m_pConnections->GetAt(nIndex);
- }
- const CPtrArray* CConnectionPoint::GetConnections()
- {
- ASSERT_VALID(this);
- if (m_pConnections == NULL)
- CreateConnectionArray();
- ASSERT(m_pConnections != NULL);
- return m_pConnections;
- }
- void CConnectionPoint::OnAdvise(BOOL)
- {
- ASSERT_VALID(this);
- }
- int CConnectionPoint::GetMaxConnections()
- {
- ASSERT_VALID(this);
- // May be overridden by subclass.
- return -1;
- }
- LPCONNECTIONPOINTCONTAINER CConnectionPoint::GetContainer()
- {
- CCmdTarget* pCmdTarget = (CCmdTarget*)((BYTE*)this - m_nOffset);
- #ifdef _DEBUG
- pCmdTarget->CCmdTarget::AssertValid();
- #endif
- LPCONNECTIONPOINTCONTAINER pCPC = NULL;
- if (SUCCEEDED((HRESULT)pCmdTarget->ExternalQueryInterface(
- &IID_IConnectionPointContainer, (LPVOID*)&pCPC)))
- {
- ASSERT(pCPC != NULL);
- }
- return pCPC;
- }
- void CConnectionPoint::CreateConnectionArray()
- {
- ASSERT(m_pConnections == NULL);
- m_pConnections = new CPtrArray;
- if (m_pUnkFirstConnection != NULL)
- {
- m_pConnections->Add(m_pUnkFirstConnection);
- m_pUnkFirstConnection = NULL;
- }
- ASSERT(m_pConnections != NULL);
- ASSERT(m_pUnkFirstConnection == NULL);
- }
- int CConnectionPoint::GetConnectionCount()
- {
- if (m_pUnkFirstConnection != NULL)
- return 1;
- if (m_pConnections == NULL)
- return 0;
- return m_pConnections->GetSize();
- }
- LPUNKNOWN CConnectionPoint::QuerySinkInterface(LPUNKNOWN pUnkSink)
- {
- LPUNKNOWN pUnkReturn = NULL;
- pUnkSink->QueryInterface(GetIID(), reinterpret_cast<void**>(&pUnkReturn));
- return pUnkReturn;
- }
- STDMETHODIMP_(ULONG) CConnectionPoint::XConnPt::Release()
- {
- METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
- return (ULONG)pThis->InternalRelease();
- }
- STDMETHODIMP_(ULONG) CConnectionPoint::XConnPt::AddRef()
- {
- METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
- return (ULONG)pThis->InternalAddRef();
- }
- STDMETHODIMP CConnectionPoint::XConnPt::QueryInterface(
- REFIID iid, LPVOID* ppvObj)
- {
- METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
- ASSERT(AfxIsValidAddress(ppvObj, sizeof(LPVOID), FALSE));
- if (IsEqualIID(iid, IID_IUnknown) ||
- IsEqualIID(iid, IID_IConnectionPoint))
- {
- *ppvObj = this;
- AddRef();
- return S_OK;
- }
- return E_NOINTERFACE;
- }
- STDMETHODIMP CConnectionPoint::XConnPt::GetConnectionInterface(IID* pIID)
- {
- METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
- ASSERT(AfxIsValidAddress(pIID, sizeof(IID)));
- *pIID = pThis->GetIID();
- return S_OK;
- }
- STDMETHODIMP CConnectionPoint::XConnPt::GetConnectionPointContainer(
- IConnectionPointContainer** ppCPC)
- {
- METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
- ASSERT(AfxIsValidAddress(ppCPC, sizeof(LPCONNECTIONPOINT)));
- if ((*ppCPC = pThis->GetContainer()) != NULL)
- return S_OK;
- return E_FAIL;
- }
- STDMETHODIMP CConnectionPoint::XConnPt::Advise(
- LPUNKNOWN pUnkSink, DWORD* pdwCookie)
- {
- METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
- ASSERT(AfxIsValidAddress(pUnkSink, sizeof(IUnknown), FALSE));
- ASSERT((pdwCookie == NULL) || AfxIsValidAddress(pdwCookie, sizeof(DWORD)));
- if (pUnkSink == NULL)
- return E_POINTER;
- LPUNKNOWN lpInterface;
- int cMaxConn = pThis->GetMaxConnections();
- if ((cMaxConn >= 0) && (pThis->GetConnectionCount() == cMaxConn))
- {
- return CONNECT_E_ADVISELIMIT;
- }
- if ((lpInterface = pThis->QuerySinkInterface(pUnkSink)) != NULL)
- {
- if (pThis->m_pUnkFirstConnection == NULL &&
- pThis->m_pConnections == NULL)
- {
- pThis->m_pUnkFirstConnection = lpInterface;
- }
- else
- {
- if (pThis->m_pConnections == NULL)
- pThis->CreateConnectionArray();
- pThis->m_pConnections->Add(lpInterface);
- }
- pThis->OnAdvise(TRUE);
- if (pdwCookie != NULL)
- *pdwCookie = (DWORD)lpInterface;
- return S_OK;
- }
- return E_NOINTERFACE;
- }
- STDMETHODIMP CConnectionPoint::XConnPt::Unadvise(DWORD dwCookie)
- {
- METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
- if (pThis->m_pUnkFirstConnection != NULL)
- {
- if ((DWORD)pThis->m_pUnkFirstConnection == dwCookie)
- {
- pThis->m_pUnkFirstConnection->Release();
- pThis->m_pUnkFirstConnection = NULL;
- pThis->OnAdvise(FALSE);
- return S_OK;
- }
- else
- {
- return CONNECT_E_NOCONNECTION;
- }
- }
- if (pThis->m_pConnections == NULL)
- return CONNECT_E_NOCONNECTION;
- LPUNKNOWN pUnkSink;
- int cConnections = pThis->m_pConnections->GetSize();
- for (int i = 0; i < cConnections; i++)
- {
- pUnkSink = (LPUNKNOWN)(pThis->m_pConnections->GetAt(i));
- if ((DWORD)pUnkSink == dwCookie)
- {
- pUnkSink->Release();
- pThis->m_pConnections->RemoveAt(i);
- pThis->OnAdvise(FALSE);
- return S_OK;
- }
- }
- return CONNECT_E_NOCONNECTION;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CEnumConnections
- class CEnumConnections : public CEnumArray
- {
- public:
- CEnumConnections(const void* pvEnum, UINT nSize);
- ~CEnumConnections();
- void AddConnection(CONNECTDATA* pConn);
- protected:
- virtual BOOL OnNext(void* pv);
- virtual CEnumArray* OnClone();
- UINT m_nMaxSize; // number of items allocated (>= m_nSize)
- DECLARE_INTERFACE_MAP()
- };
- BEGIN_INTERFACE_MAP(CEnumConnections, CEnumArray)
- INTERFACE_PART(CEnumConnections, IID_IEnumConnections, EnumVOID)
- END_INTERFACE_MAP()
- CEnumConnections::CEnumConnections(const void* pvEnum, UINT nSize) :
- CEnumArray(sizeof(CONNECTDATA), pvEnum, nSize, TRUE)
- {
- m_nMaxSize = 0;
- }
- CEnumConnections::~CEnumConnections()
- {
- if (m_pClonedFrom == NULL)
- {
- UINT iCP;
- CONNECTDATA* ppCP = (CONNECTDATA*)(VOID *)m_pvEnum;
- for (iCP = 0; iCP < m_nSize; iCP++)
- RELEASE(ppCP[iCP].pUnk);
- }
- // destructor will free the actual array (if it was not a clone)
- }
- BOOL CEnumConnections::OnNext(void* pv)
- {
- if (!CEnumArray::OnNext(pv))
- return FALSE;
- // outgoing connection point needs to be AddRef'ed
- // (the caller has responsibility to release it)
- ((CONNECTDATA*)pv)->pUnk->AddRef();
- return TRUE;
- }
- CEnumArray* CEnumConnections::OnClone()
- {
- ASSERT_VALID(this);
- CEnumConnections* pClone;
- pClone = new CEnumConnections(m_pvEnum, m_nSize);
- pClone->m_bNeedFree = FALSE;
- ASSERT(pClone != NULL);
- ASSERT(!pClone->m_bNeedFree); // clones should never free themselves
- pClone->m_nCurPos = m_nCurPos;
- // finally, return the clone to OLE
- ASSERT_VALID(pClone);
- return pClone;
- }
- void CEnumConnections::AddConnection(CONNECTDATA* pConn)
- {
- ASSERT(m_nSize <= m_nMaxSize);
- if (m_nSize == m_nMaxSize)
- {
- // not enough space for new item -- allocate more
- CONNECTDATA* pListNew = new CONNECTDATA[m_nSize+2];
- m_nMaxSize += 2;
- if (m_nSize > 0)
- memcpy(pListNew, m_pvEnum, m_nSize*sizeof(CONNECTDATA));
- delete m_pvEnum;
- #ifdef _WIN32
- m_pvEnum = (BYTE*)pListNew;
- #else
- m_pvEnum = (char*)pListNew;
- #endif
- }
- // add this item to the list
- ASSERT(m_nSize < m_nMaxSize);
- ((CONNECTDATA*)m_pvEnum)[m_nSize] = *pConn;
- pConn->pUnk->AddRef();
- ++m_nSize;
- }
- STDMETHODIMP CConnectionPoint::XConnPt::EnumConnections(LPENUMCONNECTIONS* ppEnum)
- {
- METHOD_PROLOGUE_EX(CConnectionPoint, ConnPt)
- CEnumConnections* pEnum = NULL;
- CONNECTDATA cd;
- TRY
- {
- pEnum = new CEnumConnections(NULL, 0);
- if (pThis->m_pUnkFirstConnection != NULL)
- {
- cd.pUnk = pThis->m_pUnkFirstConnection;
- cd.dwCookie = (DWORD)cd.pUnk;
- pEnum->AddConnection(&cd);
- }
- if (pThis->m_pConnections != NULL)
- {
- int cConnections = pThis->m_pConnections->GetSize();
- for (int i = 0; i < cConnections; i++)
- {
- cd.pUnk = (LPUNKNOWN)(pThis->m_pConnections->GetAt(i));
- cd.dwCookie = (DWORD)cd.pUnk;
- pEnum->AddConnection(&cd);
- }
- }
- }
- CATCH (CException, e)
- {
- delete pEnum;
- pEnum = NULL;
- }
- END_CATCH
- if (pEnum != NULL)
- {
- // create and return the IEnumConnectionPoints object
- *ppEnum = (IEnumConnections*)&pEnum->m_xEnumVOID;
- }
- else
- {
- // no connections: return NULL
- *ppEnum = NULL;
- }
- return (pEnum != NULL) ? S_OK : E_OUTOFMEMORY;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CEnumConnPoints
- class CEnumConnPoints : public CEnumArray
- {
- public:
- CEnumConnPoints(const void* pvEnum, UINT nSize);
- ~CEnumConnPoints();
- void AddConnPoint(LPCONNECTIONPOINT pConnPt);
- protected:
- virtual BOOL OnNext(void* pv);
- UINT m_nMaxSize; // number of items allocated (>= m_nSize)
- DECLARE_INTERFACE_MAP()
- };
- BEGIN_INTERFACE_MAP(CEnumConnPoints, CEnumArray)
- INTERFACE_PART(CEnumConnPoints, IID_IEnumConnectionPoints, EnumVOID)
- END_INTERFACE_MAP()
- CEnumConnPoints::CEnumConnPoints(const void* pvEnum, UINT nSize) :
- CEnumArray(sizeof(LPCONNECTIONPOINT), pvEnum, nSize, TRUE)
- {
- m_nMaxSize = 0;
- }
- CEnumConnPoints::~CEnumConnPoints()
- {
- if (m_pClonedFrom == NULL)
- {
- UINT iCP;
- LPCONNECTIONPOINT* ppCP =
- (LPCONNECTIONPOINT*)(VOID *)m_pvEnum;
- for (iCP = 0; iCP < m_nSize; iCP++)
- RELEASE(ppCP[iCP]);
- }
- // destructor will free the actual array (if it was not a clone)
- }
- BOOL CEnumConnPoints::OnNext(void* pv)
- {
- if (!CEnumArray::OnNext(pv))
- return FALSE;
- // outgoing connection point needs to be AddRef'ed
- // (the caller has responsibility to release it)
- (*(LPCONNECTIONPOINT*)pv)->AddRef();
- return TRUE;
- }
- void CEnumConnPoints::AddConnPoint(LPCONNECTIONPOINT pConnPt)
- {
- ASSERT(m_nSize <= m_nMaxSize);
- if (m_nSize == m_nMaxSize)
- {
- // not enough space for new item -- allocate more
- LPCONNECTIONPOINT* pListNew = new LPCONNECTIONPOINT[m_nSize+2];
- m_nMaxSize += 2;
- if (m_nSize > 0)
- memcpy(pListNew, m_pvEnum, m_nSize*sizeof(LPCONNECTIONPOINT));
- delete m_pvEnum;
- #ifdef _WIN32
- m_pvEnum = (BYTE*)pListNew;
- #else
- m_pvEnum = (char*)pListNew;
- #endif
- }
- // add this item to the list
- ASSERT(m_nSize < m_nMaxSize);
- ((LPCONNECTIONPOINT*)m_pvEnum)[m_nSize] = pConnPt;
- pConnPt->AddRef();
- ++m_nSize;
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleConnPtContainer
- class COleConnPtContainer : public IConnectionPointContainer
- {
- public:
- #ifndef _AFX_NO_NESTED_DERIVATION
- // required for METHOD_PROLOGUE_EX
- size_t m_nOffset;
- COleConnPtContainer::COleConnPtContainer()
- { m_nOffset = offsetof(CCmdTarget, m_xConnPtContainer); }
- #endif
- STDMETHOD_(ULONG, AddRef)();
- STDMETHOD_(ULONG, Release)();
- STDMETHOD(QueryInterface)(REFIID, LPVOID*);
- STDMETHOD(EnumConnectionPoints)(LPENUMCONNECTIONPOINTS* ppEnum);
- STDMETHOD(FindConnectionPoint)(REFIID iid, LPCONNECTIONPOINT* ppCP);
- };
- STDMETHODIMP_(ULONG) COleConnPtContainer::AddRef()
- {
- METHOD_PROLOGUE_EX_(CCmdTarget, ConnPtContainer)
- return (ULONG)pThis->ExternalAddRef();
- }
- STDMETHODIMP_(ULONG) COleConnPtContainer::Release()
- {
- METHOD_PROLOGUE_EX_(CCmdTarget, ConnPtContainer)
- return (ULONG)pThis->ExternalRelease();
- }
- STDMETHODIMP COleConnPtContainer::QueryInterface(
- REFIID iid, LPVOID* ppvObj)
- {
- METHOD_PROLOGUE_EX_(CCmdTarget, ConnPtContainer)
- return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
- }
- STDMETHODIMP COleConnPtContainer::EnumConnectionPoints(
- LPENUMCONNECTIONPOINTS* ppEnum)
- {
- METHOD_PROLOGUE_EX_(CCmdTarget, ConnPtContainer)
- CEnumConnPoints* pEnum = NULL;
- TRY
- {
- pEnum = new CEnumConnPoints(NULL, 0);
- // Add connection points that aren't in the connection map
- CPtrArray ptrArray;
- if (pThis->GetExtraConnectionPoints(&ptrArray))
- {
- for (int i = 0; i < ptrArray.GetSize(); i++)
- pEnum->AddConnPoint((LPCONNECTIONPOINT)ptrArray.GetAt(i));
- }
- // walk the chain of connection maps
- const AFX_CONNECTIONMAP* pMap = pThis->GetConnectionMap();
- const AFX_CONNECTIONMAP_ENTRY* pEntry;
- while (pMap != NULL)
- {
- pEntry = pMap->pEntry;
- while (pEntry->piid != NULL)
- {
- pEnum->AddConnPoint(GetConnectionPtr(pThis, pEntry));
- ++pEntry;
- }
- #ifdef _AFXDLL
- pMap = (*pMap->pfnGetBaseMap)();
- #else
- pMap = pMap->pBaseMap;
- #endif
- }
- }
- CATCH (CException, e)
- {
- delete pEnum;
- pEnum = NULL;
- }
- END_CATCH
- if (pEnum != NULL)
- {
- // create and return the IEnumConnectionPoints object
- *ppEnum = (IEnumConnectionPoints*)&pEnum->m_xEnumVOID;
- }
- else
- {
- // no connection points: return NULL
- *ppEnum = NULL;
- }
- return (pEnum != NULL) ? S_OK : CONNECT_E_NOCONNECTION;
- }
- STDMETHODIMP COleConnPtContainer::FindConnectionPoint(
- REFIID iid, LPCONNECTIONPOINT* ppCP)
- {
- METHOD_PROLOGUE_EX_(CCmdTarget, ConnPtContainer)
- ASSERT(ppCP != NULL);
- if ((*ppCP = pThis->GetConnectionHook(iid)) != NULL)
- {
- (*ppCP)->AddRef();
- return S_OK;
- }
- const AFX_CONNECTIONMAP* pMap = pThis->GetConnectionMap();
- const AFX_CONNECTIONMAP_ENTRY* pEntry;
- while (pMap != NULL)
- {
- pEntry = pMap->pEntry;
- while (pEntry->piid != NULL)
- {
- if (IsEqualIID(iid, *(IID*)(pEntry->piid)))
- {
- *ppCP = GetConnectionPtr(pThis, pEntry);
- (*ppCP)->AddRef();
- return S_OK;
- }
- ++pEntry;
- }
- #ifdef _AFXDLL
- pMap = (*pMap->pfnGetBaseMap)();
- #else
- pMap = pMap->pBaseMap;
- #endif
- }
- return E_NOINTERFACE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Wiring CCmdTarget to COleConnPtContainer
- // enable this object for OLE connections, called from derived class ctor
- void CCmdTarget::EnableConnections()
- {
- ASSERT(GetConnectionMap() != NULL); // must have DECLARE_DISPATCH_MAP
- // construct an COleConnPtContainer instance just to get to the vtable
- COleConnPtContainer cpc;
- // vtable pointer should be already set to same or NULL
- ASSERT(m_xConnPtContainer.m_vtbl == NULL||
- *(DWORD*)&cpc == m_xConnPtContainer.m_vtbl);
- // verify that sizes match
- ASSERT(sizeof(m_xConnPtContainer) == sizeof(COleConnPtContainer));
- // copy the vtable (and other data) to make sure it is initialized
- m_xConnPtContainer.m_vtbl = *(DWORD*)&cpc;
- *(COleConnPtContainer*)&m_xConnPtContainer = cpc;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Force any extra compiler-generated code into AFX_INIT_SEG
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
|