| Platform SDK: SMTP Server Events |
[This is preliminary documentation and subject to change.]
This file contains the implementation for all the exposed CSink interfaces.
#include "stdafx.h"
#include "ShieldsUp.h"
#include "Sink.h"
#define DEFAULT_RESPONSE "Please Try Again Later."
/////////////////////////////////////////////////////////////////////////////
// CSink
/*
** ISmtpInCommandSink
*/
STDMETHODIMP CSink::OnSmtpInCommand(
IUnknown *pServer,
IUnknown *pSession,
IMailMsgProperties *pMsg,
ISmtpInCommandContext *pContext)
{
HRESULT hr = S_OK;
if(pContext == NULL)
return E_POINTER;
char* pszResponse = NULL;
long lResponseLength = strlen(g_szResponseText);
pszResponse = (char*) CoTaskMemAlloc(g_dwResponseSize);
strcpy(pszResponse,g_szResponseText);
pszResponse[g_dwResponseSize-1] = '\0';
hr = pContext->SetResponse(pszResponse, g_dwResponseSize);
if(FAILED(hr))
return hr;
hr = pContext->SetCommandStatus(EXPE_DROP_SESSION);
if(FAILED(hr))
return hr;
// Success.
// Notify the dispatcher that we have
// consummed the event.
// No other sinks will run, and
// the connection will be dropped.
return EXPE_S_CONSUMED;
}
/*
** IPersistPropertyBag : IPersist
*/
STDMETHODIMP CSink::GetClassID(CLSID *pClassID)
{
return S_OK;
}
STDMETHODIMP CSink::InitNew(void)
{
return S_OK;
}
STDMETHODIMP CSink::Load(IPropertyBag* pBag,IErrorLog *pErrorLog)
{
if(pBag == NULL)
return E_POINTER;
if(g_fHaveCustomText)
return S_OK;
ATLASSERT(pBag);
HRESULT hr = S_OK;
CComVariant varVal;
hr = pBag->Read(L"ResponseText",&varVal,pErrorLog);
if(FAILED(hr))
return S_OK; // There's no custom text
/*
** We have some custom text
*/
UINT uiResponseLength = SysStringLen(varVal.bstrVal);
char* temp = NULL;
temp = new char[uiResponseLength + 1];
if(temp == NULL)
return E_OUTOFMEMORY;
if(wcstombs(temp,varVal.bstrVal,uiResponseLength+1) == NULL) {
delete [] temp;
return E_OUTOFMEMORY;
}
if(g_szResponseText != NULL)
delete [] g_szResponseText;
g_szResponseText = temp;
g_szResponseText[uiResponseLength] = '\0';
g_dwResponseSize = uiResponseLength + 1;
g_fHaveCustomText = true;
return S_OK;
}
STDMETHODIMP CSink::Save(
IPropertyBag *pPropBag,
BOOL fClearDirty,
BOOL fSaveAllProperties)
{
return S_OK;
}
/*
** Oddly enough, the most involved code for this example
** is where we register and unregister the event sink bindings.
** What's going on is very simple. We have to add a binding
** to the appropriate source in the SEO database.
** SEO is ole-automation compatible, so much of this code
** mirrors much simpler code using vbscript.
** The hierarchy of SEO objects is as follows:
**
** EventManager
** SourceTypes
** SourceType
** Sources
** Source
** Bindings
** Binding <--- Adding another of these
** SinkProperties
** SourceProperties
**
*/
STDMETHODIMP CSink::RegisterSink(long lInstance, BSTR DisplayName, BSTR BindingGUID, BSTR ResponseText, VARIANT_BOOL fEnabled, BSTR* OutBindingGUID)
{
IEventManager* pEvtMan = NULL;
IEventUtil* pEvtUtil = NULL;
IEventSourceTypes* pSrcTypes = NULL;
IEventSourceType* pSrcType = NULL;
IEventSources* pSrcs = NULL;
IEventSource* pSrc = NULL;
IEventBindingManager* pBindingMan = NULL;
IEventBindings* pBindings = NULL;
IEventBinding* pBinding = NULL;
IEventPropertyBag* pSourceProps = NULL;
IEventPropertyBag* pSinkProps = NULL;
HRESULT hr = S_OK;
BSTR bstrSourceGUID;
hr = CoCreateInstance(__uuidof(CEventUtil),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IEventUtil),
(void**)&pEvtUtil);
// Get the Source GUID for the SMTP Server Instance
hr = pEvtUtil->GetIndexedGUID(CComBSTR(g_szGuidSmtpSvcSource),lInstance,&bstrSourceGUID);
if(FAILED(hr)) {
pEvtUtil->Release();
return hr;
}
// Use the EventManager to create the binding
hr = CoCreateInstance(__uuidof(CEventManager),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IEventManager),
(void**)&pEvtMan);
if(FAILED(hr))
return hr;
hr = E_FAIL;
if(SUCCEEDED(pEvtMan->get_SourceTypes(&pSrcTypes))) {
if(SUCCEEDED(pSrcTypes->Item(&CComVariant(g_szGuidSmtpSourceType),&pSrcType))) {
if(SUCCEEDED(pSrcType->get_Sources(&pSrcs))) {
if(SUCCEEDED(pSrcs->Item(&CComVariant(bstrSourceGUID),&pSrc))) {
if(SUCCEEDED(pSrc->GetBindingManager(&pBindingMan))) {
if(SUCCEEDED(pBindingMan->get_Bindings(CComBSTR(g_szcatidSmtpOnInboundCommand),&pBindings))) {
// BindingGUID was passed by the caller
hr = pBindings->Add(BindingGUID,&pBinding);
if(SUCCEEDED(hr)) {
// error checking is omitted for clarity.
// each result _should_ be checked
// but these work most of the time
pBinding->put_SinkClass(CComBSTR("ShieldsUp.Sink"));
pBinding->put_DisplayName(DisplayName);
pBinding->put_Enabled(fEnabled);
// Source Properties
pBinding->get_SourceProperties(&pSourceProps);
// Rule is: EHLO command (all)
pSourceProps->Add(CComBSTR("Rule"),&CComVariant("ehlo"));
// highest prio
pSourceProps->Add(CComBSTR("Priority"),&CComVariant((long) 0));
pSourceProps->Release();
// Sink Properties
pBinding->get_SinkProperties(&pSinkProps);
pSinkProps->Add(CComBSTR("ResponseText"),&CComVariant(ResponseText));
hr = pBinding->Save();
// If the caller did not specify a GUID, we return it.
// If they did, we return it anyway
hr = pBinding->get_ID(OutBindingGUID);
pSinkProps->Release();
pBinding->Release();
}
pBindings->Release();
}
pBindingMan->Release();
}
pSrc->Release();
}
pSrcs->Release();
}
pSrcType->Release();
}
pSrcTypes->Release();
}
pEvtMan->Release();
ATLASSERT(SUCCEEDED(hr));
return S_OK;
}
STDMETHODIMP CSink::UnRegisterSink(long lInstance, BSTR BindingGUID)
{
IEventManager* pEvtMan = NULL;
IEventUtil* pEvtUtil = NULL;
IEventSourceTypes* pSrcTypes = NULL;
IEventSourceType* pSrcType = NULL;
IEventSources* pSrcs = NULL;
IEventSource* pSrc = NULL;
IEventBindingManager* pBindingMan = NULL;
IEventBindings* pBindings = NULL;
IEventBinding* pBinding = NULL;
HRESULT hr = S_OK;
BSTR bstrSourceGUID;
hr = CoCreateInstance(__uuidof(CEventUtil),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IEventUtil),
(void**)&pEvtUtil);
// Get the Source GUID for the SMTP Server Instance
hr = pEvtUtil->GetIndexedGUID(CComBSTR(g_szGuidSmtpSvcSource),lInstance,&bstrSourceGUID);
if(FAILED(hr)) {
pEvtUtil->Release();
return hr;
}
pEvtUtil->Release();
// Use the EventManager to create the binding
hr = CoCreateInstance(__uuidof(CEventManager),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IEventManager),
(void**)&pEvtMan);
if(FAILED(hr))
return hr;
hr = E_FAIL;
if(SUCCEEDED(pEvtMan->get_SourceTypes(&pSrcTypes))) {
if(SUCCEEDED(pSrcTypes->Item(&CComVariant(g_szGuidSmtpSourceType),&pSrcType))) {
if(SUCCEEDED(pSrcType->get_Sources(&pSrcs))) {
if(SUCCEEDED(pSrcs->Item(&CComVariant(bstrSourceGUID),&pSrc))) {
if(SUCCEEDED(pSrc->GetBindingManager(&pBindingMan))) {
if(SUCCEEDED(pBindingMan->get_Bindings(CComBSTR(g_szcatidSmtpOnInboundCommand),&pBindings))) {
hr = pBindings->Remove(&CComVariant(BindingGUID));
pBindings->Release();
}
pBindingMan->Release();
}
pSrc->Release();
}
pSrcs->Release();
}
pSrcType->Release();
}
pSrcTypes->Release();
}
pEvtMan->Release();
return hr;
}