150 lines
3.3 KiB
C++
150 lines
3.3 KiB
C++
//+------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1999, Microsoft Corporation
|
|
//
|
|
// File: cleanback.h
|
|
//
|
|
// Contents: Implements Cleanup callback interface
|
|
//
|
|
// Classes: CCleanBack
|
|
//
|
|
// Description: The intention is this object will be used as a part of
|
|
// other objects (member variable or inheritence).
|
|
// Therefore, the IUnknown passed in is NOT referenced.
|
|
//
|
|
// History:
|
|
// jstamerj 1999/09/27 17:58:50: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
#include "mailmsg.h"
|
|
#include "spinlock.h"
|
|
|
|
class CCleanBack :
|
|
public IMailMsgRegisterCleanupCallback
|
|
{
|
|
public:
|
|
CCleanBack(IUnknown *pUnknown)
|
|
{
|
|
m_pListHead = NULL;
|
|
m_pIUnknown = pUnknown;
|
|
InitializeSpinLock(&m_spinlock);
|
|
}
|
|
~CCleanBack()
|
|
{
|
|
CallCallBacks();
|
|
}
|
|
VOID CallCallBacks()
|
|
{
|
|
//
|
|
// Call all registered callbacks while destroying the list
|
|
//
|
|
CCallBack *pCallback;
|
|
|
|
while(m_pListHead) {
|
|
//
|
|
// Dequeue from head of list
|
|
//
|
|
AcquireSpinLock(&m_spinlock);
|
|
|
|
pCallback = m_pListHead;
|
|
if(pCallback)
|
|
m_pListHead = pCallback->GetNext();
|
|
|
|
ReleaseSpinLock(&m_spinlock);
|
|
//
|
|
// Make the call
|
|
//
|
|
if(pCallback) {
|
|
pCallback->Call(m_pIUnknown);
|
|
delete pCallback;
|
|
}
|
|
}
|
|
}
|
|
|
|
STDMETHOD (RegisterCleanupCallback) (
|
|
IMailMsgCleanupCallback *pICallBack,
|
|
PVOID pvContext)
|
|
{
|
|
CCallBack *pCCallBack;
|
|
|
|
if(pICallBack == NULL)
|
|
return E_POINTER;
|
|
|
|
pCCallBack = new CCallBack(
|
|
pICallBack,
|
|
pvContext);
|
|
|
|
if(pCCallBack == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
//
|
|
// Insert object into list
|
|
//
|
|
AcquireSpinLock(&m_spinlock);
|
|
pCCallBack->SetNext(m_pListHead);
|
|
m_pListHead = pCCallBack;
|
|
ReleaseSpinLock(&m_spinlock);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
class CCallBack {
|
|
|
|
public:
|
|
CCallBack(IMailMsgCleanupCallback *pICallBack, PVOID pvContext)
|
|
{
|
|
m_pICallBack = pICallBack;
|
|
m_pICallBack->AddRef();
|
|
m_pvContext = pvContext;
|
|
m_pNext = NULL;
|
|
}
|
|
~CCallBack()
|
|
{
|
|
m_pICallBack->Release();
|
|
}
|
|
VOID Call(IUnknown *pIUnknown)
|
|
{
|
|
m_pICallBack->CleanupCallback(
|
|
pIUnknown,
|
|
m_pvContext);
|
|
}
|
|
VOID SetNext(CCallBack *pCCallBack)
|
|
{
|
|
m_pNext = pCCallBack;
|
|
}
|
|
CCallBack * GetNext()
|
|
{
|
|
return m_pNext;
|
|
}
|
|
|
|
private:
|
|
IMailMsgCleanupCallback *m_pICallBack;
|
|
PVOID m_pvContext;
|
|
CCallBack *m_pNext;
|
|
};
|
|
public:
|
|
//IUnknown
|
|
STDMETHOD (QueryInterface) (
|
|
REFIID iid,
|
|
PVOID *ppv)
|
|
{
|
|
return m_pIUnknown->QueryInterface(
|
|
iid,
|
|
ppv);
|
|
}
|
|
STDMETHOD_ (ULONG, AddRef) ()
|
|
{
|
|
return m_pIUnknown->AddRef();
|
|
}
|
|
STDMETHOD_ (ULONG, Release) ()
|
|
{
|
|
return m_pIUnknown->Release();
|
|
}
|
|
|
|
private:
|
|
SPIN_LOCK m_spinlock;
|
|
CCallBack *m_pListHead;
|
|
IUnknown *m_pIUnknown;
|
|
};
|