Сущность технологии СОМ. Библиотека программиста :: Бокс Дональд
Страница:
518 из 528
)
{
hr = E_OUTOFMEMORY;
}
SUnlock();
if (SUCCEEDED(hr))
Fire_OnNewStatement(pwszUser, pwszStatement);
}
else
hr = E_ACCESSDENIED;
CoTaskMemFree(pwszUser);
return hr;
}
STDMETHODIMP
ChatSession::GetStatements(IEnumString **ppes)
{
if (ppes == 0)
return E_INVALIDARG;
*ppes = new StatementEnumerator(this);
if (*ppes == 0)
return E_OUTOFMEMORY;
(*ppes)->AddRef();
return S_OK;
}
STDMETHODIMP
ChatSession::Advise(IChatSessionEvents *pEventSink,
DWORD *pdwReg)
{
HRESULT hr = S_OK;
if (pEventSink == 0 || pdwReg == 0)
return E_INVALIDARG;
LISTENER *pNew = new LISTENER;
if (pNew == 0)
return E_OUTOFMEMORY;
OLECHAR *pwszUser = GetCaller();
if (pwszUser)
{
Fire_OnNewUser(pwszUser);
ALock();
pNew->pwszUser = pwszUser;
if (pNew->pItf = pEventSink)
pEventSink->AddRef();
pNew->pNext = m_pHeadListeners;
if (m_pHeadListeners)
m_pHeadListeners->pPrev = pNew;
pNew->pPrev = 0;
m_pHeadListeners = pNew;
AUnlock();
}
else
{
delete pNew;
return E_OUTOFMEMORY;
}
*pdwReg = reinterpret_cast(pNew);
return hr;
}
STDMETHODIMP
ChatSession::Unadvise(DWORD dwReg)
{
if (dwReg == 0)
return E_INVALIDARG;
HRESULT hr = S_OK;
LISTENER *pThisNode = reinterpret_cast(dwReg);
ALock();
if (pThisNode->pPrev)
pThisNode->pPrev->pNext = pThisNode->pNext;
else
m_pHeadListeners = pThisNode->pNext;
if (pThisNode->pNext)
pThisNode->pNext->pPrev = pThisNode->pPrev;
if (pThisNode->pItf)
pThisNode->pItf->Release();
OLECHAR *pwszUser = pThisNode->pwszUser;
delete pThisNode;
AUnlock();
Fire_OnUserLeft(pwszUser);
CoTaskMemFree(pwszUser);
return hr;
}
// class StatementEnumerator ///////////////////
StatementEnumerator::StatementEnumerator(ChatSession *pThis)
: m_cRef(0),
m_pThis(pThis),
m_cursor(pThis->m_statements.begin())
{
m_pThis->AddRef();
InitializeCriticalSection(&m_csLock);
}
StatementEnumerator::~StatementEnumerator(void)
{
m_pThis->Release();
DeleteCriticalSection(&m_csLock);
}
// lock helpers (note that ChatSession is locked
// simultaneously)
void
StatementEnumerator::Lock(void)
{
EnterCriticalSection(&m_csLock);
m_pThis->SLock();
}
void
StatementEnumerator::Unlock(void)
{
LeaveCriticalSection(&m_csLock);
m_pThis->SUnlock();
}
// IUnknown methods
STDMETHODIMP
StatementEnumerator::QueryInterface(REFIID riid, void **ppv)
{
if (riid == IID_IUnknown)
*ppv = static_cast(this);
else if (riid == IID_IEnumString)
*ppv = static_cast(this);
else
return (*ppv = 0), E_NOINTERFACE;
reinterpret_cast(*ppv)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG)
StatementEnumerator::AddRef(void)
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG)
StatementEnumerator::Release(void)
{
LONG res = InterlockedDecrement(&m_cRef);
if (res == 0)
delete this;
return res;
}
// IEnumString methods
STDMETHODIMP
StatementEnumerator::Next(ULONG cElems, OLECHAR **rgElems,
ULONG *pcFetched)
{
if (pcFetched == 0 && cElems > 1)
return E_INVALIDARG;
ZeroMemory(rgElems, sizeof(OLECHAR*) * cElems);
Lock();
ULONG cActual = 0;
while (cActual < cElems
&& m_cursor != m_pThis->m_statements.end())
{
if (rgElems[cActual] = OLESTRDUP((*m_cursor).
|< Пред. 516 517 518 519 520 След. >|