Сущность технологии СОМ. Библиотека программиста - Страница 114

Изменить размер шрифта:

{

friend class SessionNamesEnumerator;

typedef map SESSIONMAP;

LONG m_cStrongLocks;

SESSIONMAP m_sessions;

CRITICAL_SECTION m_csSessionLock;

void Lock(void);

void Unlock(void);

bool CheckAccess(const OLECHAR *pwszUser);

public:

virtual ~ChatSessionClass(void);

ChatSessionClass(void);

// IUnknown methods

STDMETHODIMP QueryInterface(REFIID riid, void **ppv);

STDMETHODIMP_(ULONG) AddRef(void);

STDMETHODIMP_(ULONG) Release(void);

// IExternalConnection methods

STDMETHODIMP_(DWORD) AddConnection(DWORD extconn, DWORD);

STDMETHODIMP_(DWORD) ReleaseConnection(DWORD extconn, DWORD,

BOOL bLastReleaseKillsStub);

// IChatSessionManager methods

STDMETHODIMP GetSessionNames(IEnumString **ppes);

STDMETHODIMP FindSession(const OLECHAR *pwszSessionName,

BOOL bDontCreate,

BOOL bAllowAnonymousAccess,

IChatSession **ppcs);

STDMETHODIMP DeleteSession(const OLECHAR *pwszSessionName);

};

// this class enumerates the session names of a server

class SessionNamesEnumerator : public IEnumString

{

LONG m_cRef;

vector *m_pStrings;

SessionNamesEnumerator *m_pCloneSource;

vector::iterator m_cursor;

CRITICAL_SECTION m_csLock;

protected:

vector& Strings(void);

void Lock(void);

void Unlock(void);

virtual ~SessionNamesEnumerator(void);

public:

SessionNamesEnumerator(ChatSessionClass *pSessionClass);

SessionNamesEnumerator(SessionNamesEnumerator *pCloneSource);

// IUnknown methods

STDMETHODIMP QueryInterface(REFIID riid, void **ppv);

STDMETHODIMP_(ULONG) AddRef(void);

STDMETHODIMP_(ULONG) Release(void);

// IEnumString methods

STDMETHODIMP Next(ULONG cElems, OLECHAR **rgElems,

ULONG *pcFetched);

STDMETHODIMP Skip(ULONG cElems);

STDMETHODIMP Reset(void);

STDMETHODIMP Clone(IEnumString **ppes);

};

#endif

ChatSession.cpp

/////////////////////////////////////////////////////

//

// ChatSession.cpp

//

// Copyright 1997, Don Box/Addison Wesley

//

// This code accompanies the book "The Component

// Object Model" from Addison Wesley. Blah blah blah

//

//

#include «ChatSession.h»

#include

// these routines are defined in svc.cpp to

// control server lifetime

extern void ModuleLock(void);

extern void ModuleUnlock(void);

// these access control objects are created

// in svc.cpp to control various privileged

// operations. Most operations in this class

// are non-privileged, so anyone can get in.

extern IAccessControl *g_pacUsers;

extern IAccessControl *g_pacAdmins;

// utility functions /////////////////////////

// duplicate an OLECHAR * using CoTaskMemAlloc

OLECHAR *OLESTRDUP(const OLECHAR *pwsz)

{

DWORD cb = sizeof(OLECHAR)*(wcslen(pwsz) + 1);

OLECHAR *pwszResult = (OLECHAR*)CoTaskMemAlloc(cb);

if (pwszResult)

wcscpy(pwszResult, pwsz);

return pwszResult;

}

// get the caller's username (or «anonymous» if

// no authentication was specified by the caller).

OLECHAR *GetCaller(void)

{

OLECHAR *pwsz = 0;

HRESULT hr = CoQueryClientBlanket(0,0,0,0,0,(void**)&pwsz,0);

if (SUCCEEDED(hr))

return OLESTRDUP(pwsz);

else

return OLESTRDUP(OLESTR(«anonymous»));

}

// class ChatSession ///////////////////////////////

ChatSession::ChatSession(const OLECHAR *pwszSessionName,

bool bAllowAnonymousAccess)

: m_cRef(0),

m_bAllowAnonymousAccess(bAllowAnonymousAccess),

m_pHeadListeners(0)

{

wcscpy(m_wszSessionName, pwszSessionName);

InitializeCriticalSection(&m_csStatementLock);

InitializeCriticalSection(&m_csAdviseLock);

}

ChatSession::~ChatSession(void)

{

DeleteCriticalSection(&m_csStatementLock);

DeleteCriticalSection(&m_csAdviseLock);

// tear down connected listeners

while (m_pHeadListeners)

{

LISTENER *pThisNode = m_pHeadListeners;

if (pThisNode->pItf)

pThisNode->pItf->Release();

if (pThisNode->pwszUser)

CoTaskMemFree(pThisNode->pwszUser);

m_pHeadListeners = pThisNode->pNext;

delete pThisNode;

}

}

// helper methods ///////////

void ChatSession::Disconnect(void)

{

CoDisconnectObject(this, 0);

// tear down connected listeners

ALock();

while (m_pHeadListeners)

{

LISTENER *pThisNode = m_pHeadListeners;

if (pThisNode->pItf)

pThisNode->pItf->Release();

if (pThisNode->pwszUser)

CoTaskMemFree(pThisNode->pwszUser);

m_pHeadListeners = pThisNode->pNext;

delete pThisNode;

}

AUnlock();

}

// send the OnNewStatement event to all listeners

void

ChatSession::Fire_OnNewStatement(const OLECHAR *pwszUser,

const OLECHAR *pwszStatement)

{

ALock();

for (LISTENER *pNode = m_pHeadListeners;

pNode != 0; pNode = pNode->pNext)

{

if (pNode->pItf)

pNode->pItf->OnNewStatement(pwszUser, pwszStatement);

}

AUnlock();

}

// send the OnNewUser event to all listeners

void

ChatSession::Fire_OnNewUser(const OLECHAR *pwszUser)

{

ALock();

for (LISTENER *pNode = m_pHeadListeners;

pNode != 0; pNode = pNode->pNext)

{

if (pNode->pItf)

pNode->pItf->OnNewUser(pwszUser);

}

AUnlock();

}

// send the OnUserLeft event to all listeners

void

ChatSession::Fire_OnUserLeft(const OLECHAR *pwszUser)

{

ALock();

for (LISTENER *pNode = m_pHeadListeners;

pNode != 0; pNode = pNode->pNext)

{

if (pNode->pItf)

pNode->pItf->OnUserLeft(pwszUser);

}

AUnlock();

}

// lock wrappers

void ChatSession::SLock(void)

{

EnterCriticalSection(&m_csStatementLock);

}

void ChatSession::SUnlock(void)

{

LeaveCriticalSection(&m_csStatementLock);

}

void ChatSession::ALock(void)

{

EnterCriticalSection(&m_csAdviseLock);

}

void ChatSession::AUnlock(void)

{

LeaveCriticalSection(&m_csAdviseLock);

}

// helper method to check access to Say method

bool

ChatSession::CheckAccess(const OLECHAR *pwszUser)

{

if (wcscmp(pwszUser, L"anonymous") == 0)

return m_bAllowAnonymousAccess;

// form trustee from caller and use Access Control

// object hardwired to COMChat Users group

TRUSTEEW trustee = {

0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_NAME,

TRUSTEE_IS_USER,

const_cast(pwszUser)

};

BOOL bIsAllowed;

HRESULT hr = g_pacUsers->IsAccessAllowed(&trustee,0,

COM_RIGHTS_EXECUTE,

&bIsAllowed);

return SUCCEEDED(hr) && bIsAllowed != FALSE;

}

// IUnknown methods

STDMETHODIMP

ChatSession::QueryInterface(REFIID riid, void **ppv)

{

if (riid == IID_IUnknown)

*ppv = static_cast(this);

else if (riid == IID_IChatSession)

*ppv = static_cast(this);

else

return (*ppv = 0), E_NOINTERFACE;

reinterpret_cast(*ppv)->AddRef();

return S_OK;

}

STDMETHODIMP_(ULONG)

ChatSession::AddRef(void)

{

Оригинальный текст книги читать онлайн бесплатно в онлайн-библиотеке Knigger.com