windows-nt/Source/XPSP1/NT/enduser/netmeeting/ulsldap/connpt.cpp
2020-09-26 16:20:57 +08:00

1021 lines
25 KiB
C++

//****************************************************************************
//
// Module: ULS.DLL
// File: connpt.cpp
// Content: This file contains the conection point object.
// History:
// Wed 17-Apr-1996 11:13:54 -by- Viroon Touranachun [viroont]
//
// Copyright (c) Microsoft Corporation 1995-1996
//
//****************************************************************************
#include "ulsp.h"
#include "connpt.h"
//****************************************************************************
// CEnumConnectionPoints::CEnumConnectionPoints (void)
//
// History:
// Wed 17-Apr-1996 11:15:18 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
CEnumConnectionPoints::CEnumConnectionPoints (void)
{
cRef = 0;
iIndex = 0;
pcnp = NULL;
return;
}
//****************************************************************************
// CEnumConnectionPoints::~CEnumConnectionPoints (void)
//
// History:
// Wed 17-Apr-1996 11:15:18 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
CEnumConnectionPoints::~CEnumConnectionPoints (void)
{
if (pcnp != NULL)
{
pcnp->Release();
};
return;
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnectionPoints::Init (IConnectionPoint *pcnpInit)
//
// History:
// Wed 17-Apr-1996 11:15:25 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnectionPoints::Init (IConnectionPoint *pcnpInit)
{
iIndex = 0;
pcnp = pcnpInit;
if (pcnp != NULL)
{
pcnp->AddRef();
};
return S_OK;
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnectionPoints::QueryInterface (REFIID riid, void **ppv)
//
// History:
// Wed 17-Apr-1996 11:15:31 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnectionPoints::QueryInterface (REFIID riid, void **ppv)
{
if (riid == IID_IEnumConnectionPoints || riid == IID_IUnknown)
{
*ppv = (IEnumConnectionPoints *) this;
AddRef();
return S_OK;
}
else
{
*ppv = NULL;
return ILS_E_NO_INTERFACE;
};
}
//****************************************************************************
// STDMETHODIMP_(ULONG)
// CEnumConnectionPoints::AddRef (void)
//
// History:
// Wed 17-Apr-1996 11:15:37 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP_(ULONG)
CEnumConnectionPoints::AddRef (void)
{
DllLock();
MyDebugMsg ((DM_REFCOUNT, "CEnumConnectionPoints::AddRef: ref=%ld\r\n", cRef));
::InterlockedIncrement ((LONG *) &cRef);
return cRef;
}
//****************************************************************************
// STDMETHODIMP_(ULONG)
// CEnumConnectionPoints::Release (void)
//
// History:
// Wed 17-Apr-1996 11:15:43 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP_(ULONG)
CEnumConnectionPoints::Release (void)
{
DllRelease();
ASSERT (cRef > 0);
MyDebugMsg ((DM_REFCOUNT, "CEnumConnectionPoints::Release: ref=%ld\r\n", cRef));
if (::InterlockedDecrement ((LONG *) &cRef) == 0)
{
delete this;
return 0;
}
return cRef;
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnectionPoints::Next (ULONG cConnections,
// IConnectionPoint **rgpcn,
// ULONG *pcFetched)
//
// History:
// Wed 17-Apr-1996 11:15:49 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnectionPoints::Next (ULONG cConnections,
IConnectionPoint **rgpcn,
ULONG *pcFetched)
{
ULONG cCopied;
// Validate the pointer
//
if (rgpcn == NULL)
return ILS_E_POINTER;
// Validate the parameters
//
if ((cConnections == 0) ||
((cConnections > 1) && (pcFetched == NULL)))
return ILS_E_PARAMETER;
// Check the enumeration index
//
cCopied = 0;
if ((pcnp != NULL) && (iIndex == 0))
{
// Return the only connection point
//
*rgpcn = pcnp;
(*rgpcn)->AddRef();
iIndex++;
cCopied++;
};
// Determine the returned information based on other parameters
//
if (pcFetched != NULL)
{
*pcFetched = cCopied;
};
return (cConnections == cCopied ? S_OK : S_FALSE);
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnectionPoints::Skip (ULONG cConnections)
//
// History:
// Wed 17-Apr-1996 11:15:56 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnectionPoints::Skip (ULONG cConnections)
{
// Validate the parameters
//
if (cConnections == 0)
return ILS_E_PARAMETER;
// Check the enumeration index limit
//
if ((pcnp == NULL) || (iIndex > 0))
{
return S_FALSE;
}
else
{
// Skip the only elelment
//
iIndex++;
return (cConnections == 1 ? S_OK : S_FALSE);
};
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnectionPoints::Reset (void)
//
// History:
// Wed 17-Apr-1996 11:16:02 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnectionPoints::Reset (void)
{
iIndex = 0;
return S_OK;
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnectionPoints::Clone(IEnumConnectionPoints **ppEnum)
//
// History:
// Wed 17-Apr-1996 11:16:11 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnectionPoints::Clone(IEnumConnectionPoints **ppEnum)
{
CEnumConnectionPoints *pecp;
// Validate parameters
//
if (ppEnum == NULL)
{
return ILS_E_POINTER;
};
*ppEnum = NULL;
// Create an enumerator
//
pecp = new CEnumConnectionPoints;
if (pecp == NULL)
return ILS_E_MEMORY;
// Clone the information
//
pecp->iIndex = iIndex;
pecp->pcnp = pcnp;
if (pcnp != NULL)
{
pcnp->AddRef();
};
// Return the cloned enumerator
//
pecp->AddRef();
*ppEnum = pecp;
return S_OK;
}
//****************************************************************************
// CConnectionPoint::CConnectionPoint (const IID *pIID,
// IConnectionPointContainer *pCPCInit)
//
// History:
// Wed 17-Apr-1996 11:16:17 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
CConnectionPoint::CConnectionPoint (const IID *pIID,
IConnectionPointContainer *pCPCInit)
{
cRef = 0;
riid = *pIID;
pCPC = pCPCInit;
dwNextCookie = COOKIE_INIT_VALUE;
cSinkNodes = 0;
pSinkList = NULL;
return;
}
//****************************************************************************
// CConnectionPoint::~CConnectionPoint (void)
//
// History:
// Wed 17-Apr-1996 11:16:17 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
CConnectionPoint::~CConnectionPoint (void)
{
PSINKNODE pSinkNode;
// Traverse the sink list and free each one of them
//
while (pSinkList != NULL)
{
pSinkNode = pSinkList;
pSinkList = pSinkNode->pNext;
pSinkNode->pUnk->Release();
delete pSinkNode;
};
return;
}
//****************************************************************************
// STDMETHODIMP
// CConnectionPoint::QueryInterface (REFIID riid, void **ppv)
//
// History:
// Wed 17-Apr-1996 11:16:23 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CConnectionPoint::QueryInterface (REFIID riid, void **ppv)
{
if (riid == IID_IConnectionPoint || riid == IID_IUnknown)
{
*ppv = (IConnectionPoint *) this;
AddRef();
return S_OK;
}
else
{
*ppv = NULL;
return ILS_E_NO_INTERFACE;
};
}
//****************************************************************************
// STDMETHODIMP_(ULONG)
// CConnectionPoint::AddRef (void)
//
// History:
// Wed 17-Apr-1996 11:16:30 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP_(ULONG)
CConnectionPoint::AddRef (void)
{
DllLock();
MyDebugMsg ((DM_REFCOUNT, "CConnectionPoint::AddRef: ref=%ld\r\n", cRef));
::InterlockedIncrement ((LONG *) &cRef);
return cRef;
}
//****************************************************************************
// STDMETHODIMP_(ULONG)
// CConnectionPoint::Release (void)
//
// History:
// Wed 17-Apr-1996 11:16:36 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP_(ULONG)
CConnectionPoint::Release (void)
{
DllRelease();
ASSERT (cRef > 0);
MyDebugMsg ((DM_REFCOUNT, "CConnectionPoint::Release: ref=%ld\r\n", cRef));
if (::InterlockedDecrement ((LONG *) &cRef) == 0)
{
delete this;
return 0;
}
return cRef;
}
//****************************************************************************
// STDMETHODIMP
// CConnectionPoint::Notify(void *pv, CONN_NOTIFYPROC pfn)
//
// History:
// Wed 17-Apr-1996 11:16:43 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CConnectionPoint::Notify(void *pv, CONN_NOTIFYPROC pfn)
{
PSINKNODE pSinkNode, pPrev;
IUnknown *pUnk;
BOOL fNeedClear;
HRESULT hr;
// Enumerate each connection
//
pSinkNode = pSinkList;
hr = S_OK;
fNeedClear = FALSE;
while((pSinkNode != NULL) && (SUCCEEDED(hr)))
{
// Important!! Important!!
// Lock the sink object here. Need to do this in case that the sink
// object calls back to Unadvise and we remove this sink node during
// callback.
//
pSinkNode->uFlags |= SN_LOCKED;
pUnk = pSinkNode->pUnk;
// Calls the sink object
// Note: Do not need to reference the sink object again.
// We already did when Advise was called.
//
hr = (*pfn)(pUnk, pv);
pSinkNode->uFlags &= ~SN_LOCKED;
if (pSinkNode->uFlags & SN_REMOVED)
{
fNeedClear = TRUE;
};
pSinkNode = pSinkNode->pNext;
};
// If there is at least one node to free
//
if (fNeedClear)
{
// Traverse the list for nodes to remove
//
pSinkNode = pSinkList;
pPrev = NULL;
while (pSinkNode != NULL)
{
// Release the sink object, if unadvise
//
if (pSinkNode->uFlags & SN_REMOVED)
{
PSINKNODE pNext;
pNext = pSinkNode->pNext;
if (pPrev == NULL)
{
// This is the head of the list
//
pSinkList = pNext;
}
else
{
pPrev->pNext = pNext;
};
pSinkNode->pUnk->Release();
cSinkNodes--;
delete pSinkNode;
pSinkNode = pNext;
}
else
{
pPrev = pSinkNode;
pSinkNode = pSinkNode->pNext;
};
};
};
return hr;
}
//****************************************************************************
// STDMETHODIMP
// CConnectionPoint::GetConnectionInterface(IID *pIID)
//
// History:
// Wed 17-Apr-1996 11:16:43 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CConnectionPoint::GetConnectionInterface(IID *pIID)
{
// Validate the parameter
//
if (pIID == NULL)
return ILS_E_POINTER;
// Support only one connection interface
//
*pIID = riid;
return S_OK;
}
//****************************************************************************
// STDMETHODIMP
// CConnectionPoint::GetConnectionPointContainer(IConnectionPointContainer **ppCPC)
//
// History:
// Wed 17-Apr-1996 11:16:49 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CConnectionPoint::GetConnectionPointContainer(IConnectionPointContainer **ppCPC)
{
// Validate the parameter
//
if (ppCPC == NULL)
return ILS_E_POINTER;
// Return the container and add its reference count
//
*ppCPC = pCPC;
if (pCPC != NULL)
{
// The container is still alive
//
pCPC->AddRef();
return S_OK;
}
else
{
// The container no longer exists
//
return ILS_E_FAIL;
};
}
//****************************************************************************
// STDMETHODIMP
// CConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie)
//
// History:
// Wed 17-Apr-1996 11:17:01 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie)
{
PSINKNODE pSinkNode;
IUnknown *pSinkInterface;
// Validate the parameter
//
if ((pUnk == NULL) ||
(pdwCookie == NULL))
return ILS_E_PARAMETER;
// Get the sink interface
//
if (FAILED(pUnk->QueryInterface(riid, (void **)&pSinkInterface)))
return CONNECT_E_CANNOTCONNECT;
// Create the sink node
//
pSinkNode = new SINKNODE;
pSinkNode->pNext = pSinkList;
pSinkNode->pUnk = pSinkInterface;
pSinkNode->dwCookie = dwNextCookie;
pSinkNode->uFlags = 0;
*pdwCookie = dwNextCookie;
// Put it in the sink list
//
pSinkList = pSinkNode;
dwNextCookie++;
cSinkNodes++;
return S_OK;
}
//****************************************************************************
// STDMETHODIMP
// CConnectionPoint::Unadvise(DWORD dwCookie)
//
// History:
// Wed 17-Apr-1996 11:17:09 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CConnectionPoint::Unadvise(DWORD dwCookie)
{
PSINKNODE pSinkNode, pPrev;
// Search for the matching sink object
//
pPrev = NULL;
pSinkNode = pSinkList;
// Traverse the sink list to find the specified sink object
//
while (pSinkNode != NULL)
{
if (pSinkNode->dwCookie == dwCookie)
{
// Flag to remove
//
pSinkNode->uFlags |= SN_REMOVED;
break;
};
pPrev = pSinkNode;
pSinkNode = pSinkNode->pNext;
};
// Have we found the specified sink object?
//
if (pSinkNode == NULL)
{
// No, return failure
//
return CONNECT_E_NOCONNECTION;
};
// Release the sink object, if not locked
//
if ((pSinkNode->uFlags & SN_REMOVED) &&
!(pSinkNode->uFlags & SN_LOCKED))
{
// Is there a previous node?
//
if (pPrev == NULL)
{
// This is the head of the list
//
pSinkList = pSinkNode->pNext;
}
else
{
pPrev->pNext = pSinkNode->pNext;
};
pSinkNode->pUnk->Release();
cSinkNodes--;
delete pSinkNode;
};
return S_OK;
}
//****************************************************************************
// STDMETHODIMP
// CConnectionPoint::EnumConnections(IEnumConnections **ppEnum)
//
// History:
// Wed 17-Apr-1996 11:17:18 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CConnectionPoint::EnumConnections(IEnumConnections **ppEnum)
{
CEnumConnections *pecn;
HRESULT hr;
// Validate parameters
//
if (ppEnum == NULL)
{
return ILS_E_POINTER;
};
// Assume failure
//
*ppEnum = NULL;
// Create an enumerator
//
pecn = new CEnumConnections;
if (pecn == NULL)
return ILS_E_MEMORY;
// Initialize the enumerator
//
hr = pecn->Init(pSinkList, cSinkNodes);
if (FAILED(hr))
{
delete pecn;
return hr;
};
pecn->AddRef();
*ppEnum = pecn;
return S_OK;
}
//****************************************************************************
// CEnumConnections::CEnumConnections(void)
//
// History:
// Wed 17-Apr-1996 11:17:25 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
CEnumConnections::CEnumConnections(void)
{
cRef = 0;
iIndex = 0;
cConnections = 0;
pConnectData = NULL;
return;
}
//****************************************************************************
// CEnumConnections::~CEnumConnections(void)
//
// History:
// Wed 17-Apr-1996 11:17:25 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
CEnumConnections::~CEnumConnections(void)
{
if (pConnectData != NULL)
{
UINT i;
for (i = 0; i < cConnections; i++)
{
pConnectData[i].pUnk->Release();
};
delete [] pConnectData;
};
return;
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnections::Init(PSINKNODE pSinkList, ULONG cSinkNodes)
//
// History:
// Wed 17-Apr-1996 11:17:34 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnections::Init(PSINKNODE pSinkList, ULONG cSinkNodes)
{
HRESULT hr = S_OK;
iIndex = 0;
cConnections = 0;
pConnectData = NULL;
// Snapshot the connection list
//
if (cSinkNodes > 0)
{
UINT i;
pConnectData = new CONNECTDATA[cSinkNodes];
if (pConnectData != NULL)
{
for (i = 0; i < cSinkNodes && pSinkList != NULL; i++)
{
if (!(pSinkList->uFlags & SN_REMOVED))
{
pConnectData[cConnections].pUnk = pSinkList->pUnk;
pConnectData[cConnections].pUnk->AddRef();
pConnectData[cConnections].dwCookie = pSinkList->dwCookie;
cConnections++;
};
pSinkList = pSinkList->pNext;
};
}
else
{
hr = ILS_E_MEMORY;
};
};
return hr;
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnections::QueryInterface (REFIID riid, void **ppv)
//
// History:
// Wed 17-Apr-1996 11:17:40 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnections::QueryInterface (REFIID riid, void **ppv)
{
if (riid == IID_IEnumConnections || riid == IID_IUnknown)
{
*ppv = (IEnumConnections *) this;
AddRef();
return S_OK;
}
else
{
*ppv = NULL;
return ILS_E_NO_INTERFACE;
};
}
//****************************************************************************
// STDMETHODIMP_(ULONG)
// CEnumConnections::AddRef (void)
//
// History:
// Wed 17-Apr-1996 11:17:49 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP_(ULONG)
CEnumConnections::AddRef (void)
{
DllLock();
MyDebugMsg ((DM_REFCOUNT, "CEnumConnections::AddRef: ref=%ld\r\n", cRef));
::InterlockedIncrement ((LONG *) &cRef);
return cRef;
}
//****************************************************************************
// STDMETHODIMP_(ULONG)
// CEnumConnections::Release (void)
//
// History:
// Wed 17-Apr-1996 11:17:59 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP_(ULONG)
CEnumConnections::Release (void)
{
DllRelease();
ASSERT (cRef > 0);
MyDebugMsg ((DM_REFCOUNT, "CEnumConnections::Release: ref=%ld\r\n", cRef));
if (::InterlockedDecrement ((LONG *) &cRef) == 0)
{
delete this;
return 0;
}
return cRef;
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnections::Next (ULONG cConnectionDatas, CONNECTDATA *rgpcd,
// ULONG *pcFetched)
//
// History:
// Wed 17-Apr-1996 11:18:07 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnections::Next (ULONG cConnectDatas, CONNECTDATA *rgpcd,
ULONG *pcFetched)
{
CONNECTDATA *pConnect;
ULONG cCopied;
// Validate the pointer
//
if (rgpcd == NULL)
return ILS_E_POINTER;
// Validate the parameters
//
if ((cConnectDatas == 0) ||
((cConnectDatas > 1) && (pcFetched == NULL)))
return ILS_E_PARAMETER;
// Check the enumeration index
//
pConnect = &pConnectData[iIndex];
for (cCopied = 0; iIndex < cConnections && cCopied < cConnectDatas; cCopied++)
{
rgpcd[cCopied] = *pConnect;
rgpcd[cCopied].pUnk->AddRef();
iIndex++;
pConnect++;
};
// Determine the returned information based on other parameters
//
if (pcFetched != NULL)
{
*pcFetched = cCopied;
};
return (cConnectDatas == cCopied ? S_OK : S_FALSE);
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnections::Skip (ULONG cConnectDatas)
//
// History:
// Wed 17-Apr-1996 11:18:15 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnections::Skip (ULONG cConnectDatas)
{
// Validate the parameters
//
if (cConnectDatas == 0)
return ILS_E_PARAMETER;
// Check the enumeration index limit
//
if ((iIndex+cConnectDatas) >= cConnections)
{
iIndex = cConnections;
return S_FALSE;
}
else
{
// Skip as requested
//
iIndex += cConnectDatas;
return S_OK;
};
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnections::Reset (void)
//
// History:
// Wed 17-Apr-1996 11:18:22 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnections::Reset (void)
{
iIndex = 0;
return S_OK;
}
//****************************************************************************
// STDMETHODIMP
// CEnumConnections::Clone(IEnumConnections **ppEnum)
//
// History:
// Wed 17-Apr-1996 11:18:29 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP
CEnumConnections::Clone(IEnumConnections **ppEnum)
{
CEnumConnections *pecn;
CONNECTDATA *pConnectDataClone;
UINT i;
// Validate parameters
//
if (ppEnum == NULL)
{
return ILS_E_POINTER;
};
*ppEnum = NULL;
// Create an enumerator
//
pecn = new CEnumConnections;
if (pecn == NULL)
return ILS_E_MEMORY;
// Clone the information
//
pConnectDataClone = new CONNECTDATA[cConnections];
if (pConnectDataClone == NULL)
{
delete pecn;
return ILS_E_MEMORY;
};
// Clone the connect data list
//
for (i = 0; i < cConnections; i++)
{
pConnectDataClone[i] = pConnectData[i];
pConnectDataClone[i].pUnk->AddRef();
};
pecn->iIndex = iIndex;
pecn->cConnections = cConnections;
// Return the cloned enumerator
//
pecn->AddRef();
*ppEnum = pecn;
return S_OK;
}