Advise sink objects — objects that support the IMAPIAdviseSink : IUnknown interface — are an example of simple MAPI objects that are implemented by client applications for processing notifications. IMAPIAdviseSink inherits directly from IUnknown and contains only one method, OnNotify. Therefore, to implement an advise sink object, a client creates code for the three methods in IUnknown and for OnNotify.
The MAPIDEFS.H file defines an IMAPIAdviseSink interface implementation using DECLARE_MAPI_INTERFACE as follows:
#define INTERFACE IMAPIAdviseSink
DECLARE_MAPI_INTERFACE_(IMAPIAdviseSink, IUnknown)
{
BEGIN_INTERFACE
MAPI_IUNKNOWN_METHODS(PURE)
MAPI_IMAPIADVISESINK_METHODS(PURE)
};
Clients implementing advise sink objects can define their interfaces in their objects manually or with the MAPI_IUNKNOWN_METHODS and MAPI_IMAPIADVISESINK_METHODS macros. Object implementers should use the interface macros whenever possible to ensure consistency across objects and to save time and effort.
Implementing the IUnknown::AddRef and IUnknown::Release methods is relatively simple because typically only a few lines of code are needed. Therefore, clients and service providers implementing objects can make their AddRef and Release implementations inline. The following code shows how to define a C++ advise sink object with inline implementations of AddRef and Release.
class CMAPIAdviseSink : public IMAPIAdviseSink
{
public:
STDMETHODIMP QueryInterface
(REFIID riid,
LPVOID * ppvObj);
inline STDMETHODIMP_(ULONG) AddRef
() { InterlockedIncrement(m_cRef);
++m_cRef;
InterlockedDecrement(m_cRef);
return m_cRef; };
inline STDMETHODIMP_(ULONG) Release
() { InterlockedIncrement(m_cRef);
ULONG ulCount = --m_cRef;
InterlockedDecrement(m_cRef);
if (!ulCount) delete this;
return ulCount;};
MAPI_IMAPIADVISESINK_METHODS(IMPL);
BOOL WINAPI AddConnection (LPMDB pMDBObj, ULONG ulConnection);
void WINAPI RemoveAllLinks (LPMDB pMDBObj);
// Constructors and destructors
public :
inline CMAPIAdviseSink (CStoreClient * pStore)
{ m_cRef = 1;
m_ulConnection = 0;
m_pStore = pStore;
AddRef;};
~CMAPIAdviseSink () {Release};
private :
ULONG m_cRef;
CStoreClient * m_pStore;
ULONG m_ulConnection;
};
In C, the advise sink object is made up of:
The following code sample shows how to define an advise sink object in C and construct its vtable.
// Object definition
typedef struct _ADVISESINK
{
const ADVISE_Vtbl FAR * lpVtbl;
ULONG cRef;
STORECLIENT *pStore;
ULONG ulConnection;
} ADVISESINK, *LPADVISESINK;
// vtable definition
static const ADVISE_Vtbl vtblADVISE =
{
ADVISE_QueryInterface,
ADVISE_AddRef,
ADVISE_Release,
ADVISE_OnNotify
};
After an object is declared in C, it must be initialized by setting the vtable pointer to the address of the constructed vtable as is shown following:
LPADVISESINK lpMyObj = NULL;
HRESULT hr = (*lpAllocateBuffer) (sizeof(ADVISESINK),
(LPVOID *)&lpMyObj);
lpMyObj->lpVtbl = &vtblADVISE;