Сущность технологии СОМ. Библиотека программиста - Страница 116
ChatSessionClass::AddRef(void)
{
return 2;
}
STDMETHODIMP_(ULONG)
ChatSessionClass::Release(void)
{
return 1;
}
// IExternalConnection methods
STDMETHODIMP_(DWORD)
ChatSessionClass::AddConnection(DWORD extconn, DWORD)
{
if (extconn & EXTCONN_STRONG)
{
ModuleLock();
return InterlockedIncrement(&m_cStrongLocks);
}
return 0;
}
STDMETHODIMP_(DWORD)
ChatSessionClass::ReleaseConnection(DWORD extconn, DWORD,
BOOL bLastReleaseKillsStub)
{
if (extconn & EXTCONN_STRONG)
{
LONG res = InterlockedDecrement(&m_cStrongLocks);
if (res == 0 && bLastReleaseKillsStub)
CoDisconnectObject(
static_cast
ModuleUnlock();
return res;
}
return 0;
}
// IChatSessionManager methods
STDMETHODIMP
ChatSessionClass::GetSessionNames(IEnumString **ppes)
{
if (ppes == 0)
return E_INVALIDARG;
if (*ppes = new SessionNamesEnumerator(this))
{
(*ppes)->AddRef();
return S_OK;
}
else
return E_OUTOFMEMORY;
}
STDMETHODIMP
ChatSessionClass::FindSession(const OLECHAR *pwszSessionName,
BOOL bDontCreate,
BOOL bAllowAnonymousAccess,
IChatSession **ppcs)
{
if (ppcs == 0)
return E_INVALIDARG;
HRESULT hr = E_FAIL;
*ppcs = 0;
OLECHAR *pwszUser = GetCaller();
Lock();
SESSIONMAP::iterator it = m_sessions.find(pwszSessionName);
if (it == m_sessions.end())
{
if (bDontCreate)
hr = E_FAIL;
else if (!bAllowAnonymousAccess
&& wcscmp(pwszUser, L"anonymous") == 0)
hr = E_ACCESSDENIED;
else
{
ChatSession *pNew =
new ChatSession(pwszSessionName,
bAllowAnonymousAccess != FALSE);
if (pNew)
{
pNew->AddRef();
m_sessions.insert(
pair ChatSession*>(pwszSessionName, pNew)); (*ppcs = pNew)->AddRef(); hr = S_OK; } else hr = E_OUTOFMEMORY; } } else { (*ppcs = (*it).second)->AddRef(); hr = S_OK; } Unlock(); CoTaskMemFree(pwszUser); return hr; } STDMETHODIMP ChatSessionClass::DeleteSession(const OLECHAR *pwszSessionName) { if (pwszSessionName == 0) return E_INVALIDARG; HRESULT hr = E_FAIL; OLECHAR *pwszUser = GetCaller(); if (CheckAccess(pwszUser)) { Lock(); SESSIONMAP::iterator it = m_sessions.find(pwszSessionName); if (it == m_sessions.end()) { hr = E_FAIL; } else { (*it).second->Disconnect(); (*it).second->Release(); m_sessions.erase(it); hr = S_OK; } Unlock(); } else hr = E_ACCESSDENIED; CoTaskMemFree(pwszUser); return hr; } // class SessionNamesEnumerator vector SessionNamesEnumerator::Strings(void) { if (m_pStrings) return *m_pStrings; else return *(m_pCloneSource->m_pStrings); } void SessionNamesEnumerator::Lock(void) { EnterCriticalSection(&m_csLock); } void SessionNamesEnumerator::Unlock(void) { LeaveCriticalSection(&m_csLock); } SessionNamesEnumerator::SessionNamesEnumerator( ChatSessionClass *pSessionClass) : m_cRef(0), m_pStrings(0), m_pCloneSource(0) { typedef ChatSessionClass::SESSIONMAP::iterator iterator; ChatSessionClass::SESSIONMAP &sessions = pSessionClass->m_sessions; m_pStrings = new vector pSessionClass->Lock(); for (iterator it = sessions.begin(); it != sessions.end(); it++) { m_pStrings->push_back((*it).first); } pSessionClass->Unlock(); m_cursor = Strings().begin(); InitializeCriticalSection(&m_csLock); } SessionNamesEnumerator::SessionNamesEnumerator( SessionNamesEnumerator *pCloneSource) : m_cRef(0), m_pStrings(0), m_pCloneSource(pCloneSource) { m_pCloneSource->AddRef(); m_cursor = Strings().begin(); InitializeCriticalSection(&m_csLock); } SessionNamesEnumerator::~SessionNamesEnumerator(void) { if (m_pCloneSource) m_pCloneSource->Release(); else if (m_pStrings) delete m_pStrings; DeleteCriticalSection(&m_csLock); } // IUnknown methods STDMETHODIMP SessionNamesEnumerator::QueryInterface(REFIID riid, void **ppv) { if (riid == IID_IUnknown) *ppv = static_cast else if (riid == IID_IEnumString) *ppv = static_cast else return (*ppv = 0), E_NOINTERFACE; reinterpret_cast return S_OK; } STDMETHODIMP_(ULONG) SessionNamesEnumerator::AddRef(void) { ModuleLock(); return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) SessionNamesEnumerator::Release(void) { LONG res = InterlockedDecrement(&m_cRef); if (res == 0) delete this; ModuleUnlock(); return res; } // IEnumString methods STDMETHODIMP SessionNamesEnumerator::Next(ULONG cElems, OLECHAR **rgElems, ULONG *pcFetched) { if (cElems > 1 && pcFetched == 0) return E_INVALIDARG; ULONG cActual = 0; vector Lock(); while (cActual < cElems && m_cursor != rstrings.end()) { if (rgElems[cActual] = OLESTRDUP((*m_cursor).c_str())) { m_cursor++; cActual++; } else // allocation error, unwind { while (cActual > 0) { cActual–; CoTaskMemFree(rgElems[cActual]); rgElems[cActual] = 0; } break; } } Unlock(); if (cActual) *pcFetched = cActual; return cActual == cElems ? S_OK : S_FALSE; } STDMETHODIMP SessionNamesEnumerator::Skip(ULONG cElems) { ULONG cActual = 0; vector Lock(); while (cActual < cElems && m_cursor != rstrings.end()) { m_cursor++; cActual++; } Unlock(); return cActual == cElems ? S_OK : S_FALSE; } STDMETHODIMP SessionNamesEnumerator::Reset(void) { Lock(); m_cursor = Strings().begin(); Unlock(); return S_OK; } STDMETHODIMP SessionNamesEnumerator::Clone(IEnumString **ppes) { if (ppes == 0) return E_INVALIDARG; SessionNamesEnumerator *pCloneSource = m_pCloneSource; if (pCloneSource == 0) // we are the source m_pCloneSource = this; *ppes = new SessionNamesEnumerator(pCloneSource); if (*ppes) { (*ppes)->AddRef(); return S_OK; } return E_OUTOFMEMORY; } ///////////////////////////////////////////////////// // // svc.cpp // // Copyright 1997, Don Box/Addison Wesley // // This code accompanies the book "The Component // Object Model" from Addison Wesley. Blah blah blah // // #define _WIN32_WINNT 0x403 #include #include #include #include #include «ChatSession.h» #include «../include/COMChat_i.c» #if !defined(HAVE_IID_IACCESSCONTROL)