📄 oleconn.cpp
字号:
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -