Implement the Event and SEO Interface Methods

Implement the Event and SEO Interface Methods

Next, we need to add implementations of the ISmtpInCommandSink::OnSmtpInCommand, and the various IPersistPropertyBag methods. For our sink, the implementation of the OnSmtpInCommand method is quite simple. Note that the response text placed in the binding is copied into the global variable g_szResponseText when the IPersistPropertyBag::Load method is called. The size is stored in g_dwResponseSize. The implementation of the OnSmtpInCommand method simply sets the response text, sets the command status to EXPE_DROP_SESSION, and returns the HRESULT value EXPE_S_CONSUMED, indicating to the event dispatcher that this sink has consumed the event.

Important This sample code may not fully verify that strings passed to it are in fact null-terminated, nor that the referenced string buffers are large enough to store the generated contents. Your production code should always verify the validity and size of data passed as null-terminated strings before using, copying or adding to them. Using more-safe versions of the standard C string-handling functions is also recommended.

/*
** 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_s(pszResponse,lResponseLength,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;
}

This is the implementation for IPersistPropertyBag::Load method which is called by the event dispatcher to hand the sink the SinkProperties property bag from the binding:

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;
}