Сущность технологии СОМ. Библиотека программиста
Сущность технологии СОМ. Библиотека программиста читать книгу онлайн
В этой книге СОМ исследуется с точки зрения разработчика C++. Написанная ведущим специалистом по модели компонентных объектов СОМ, она раскрывает сущность СОМ, помогая разработчикам правильно понять не только методы модели программирования СОМ, но и ее основу. Понимание мотивов создания СОМ и ее аспектов, касающихся распределенных систем, чрезвычайно важно для тех разработчиков, которые желают пойти дальше простейших приложений СОМ и стать по-настоящему эффективными СОМ-программистами. Показывая, почему СОМ для распределенных систем (Distributed СОМ) работает именно так, а не иначе, Дон Бокс дает вам возможность применять эту модель творчески и эффективно для ежедневных задач программирования.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
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<IExternalConnection*>(this), 0);
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<wstring,
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<wstring>&
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<wstring>;
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<IEnumString*>(this);
else if (riid == IID_IEnumString)
*ppv = static_cast<IEnumString*>(this);
else
return (*ppv = 0), E_NOINTERFACE;
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
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<wstring> &rstrings = Strings();
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<wstring> &rstrings = Strings();
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 <windows.h>
#include <olectl.h>
#include <initguid.h>
#include <iaccess.h>
#include «ChatSession.h»
#include «../include/COMChat_i.c»
#if !defined(HAVE_IID_IACCESSCONTROL)