Сущность технологии СОМ. Библиотека программиста   ::   Бокс Дональд

Страница: 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 След. >|

Java книги

Контакты: [email protected]