Platform SDK: CDO for Windows 2000

Sink Example Using C and ATL

The following file listings are for event sink Component Object Model (COM) classes using ATL. The header file contains the declaration for the ATL COM class. Notice in the standard section, BEGIN_COM_MAP, that the following interface is designated as implemented:

The type information for Microsoft® Collaboration Data Objects (CDO), including the ISMTPOnArrival interface, is included using the #import directive. The type information for the Server Extension Objects (SEO) interface, IeventIsCacheable, is available in the SEO.DLL COM dynamic-link library (DLL) and is imported using the #import directive.

#include "resource.h"          // main symbols
#import <msado15.dll> no_namespace raw_interfaces_only
#import <cdosys.dll>  no_namespace raw_interfaces_only
#import "c:\winnt\system32\inetsrv\seo.dll" no_namespace raw_interfaces_only
#include <cdosyserr.h>
#include <cdosysstr.h>

/*
**  cdosyserr.h contains the CDO custom error HRESULTs
**  cdpsysstr.h contains string constants for all the 
**  field names, etc
*/

/////////////////////////////////////////////////////////////////////
// CSink1
class ATL_NO_VTABLE CSink1 : 
   public CComObjectRootEx<CComSingleThreadModel>,
   public CComCoClass<CSink1, &CLSID_Sink1>,
   public IDispatchImpl<ISMTPOnArrival,&__uuidof(ISMTPOnArrival), &LIBID_SMTPSinkLib>
{
public:
   CSink1()
   {
   }

DECLARE_REGISTRY_RESOURCEID(IDR_Sink1)

BEGIN_COM_MAP(CSink1)
   COM_INTERFACE_ENTRY(ISMTPOnArrival)
   COM_INTERFACE_ENTRY(IEventIsCacheable)
   COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// ISMTPOnArrival

public:
   STDMETHOD(OnArrival)(IMessage *pMsg, CdoEventStatus *pEvStat);
   STDMETHOD(IsCacheable)() { return S_OK;} // can cache the object
};

/////////////////////////////////////////////////////////////////////
// CSink1


STDMETHODIMP CSink1::OnArrival(IMessage *pMsg, EventStatus *pEventStatus)
{
  LPCWSTR szFilename = L"c:\\MyEventLogDir\\events.txt";
  HANDLE hFile;
  HRESULT hr = S_OK;

  hFile = CreateFileW(szFilename,
                      GENERIC_WRITE,
                      FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                      NULL,
                      OPEN_ALWAYS,
                      FILE_ATTRIBUTE_NORMAL,
                      NULL);
  if(hFile == INVALID_HANDLE_VALUE)
       return E_POINTER;

  int nBufSize = 0;
  ULONG nSizeWritten = 0 ;
  BOOL fRC = FALSE;
  CComBSTR bstrSubject= "\r\nSubject:";
  CComBSTR bstrTextBody= "\r\n\r\n";
  CComBSTR bstrFrom= "From:";
  CComBSTR bstrTo= "\r\nTo:";

  SetFilePointer(hFile,0,NULL,FILE_END);

  BSTR buf;
  hr = pMsg->get_To(&buf);
  if(FAILED(hr))
    return hr;
  bstrTo.AppendBSTR(buf);
  SysFreeString(buf);

    /*
     ** Get information from Message object
    */
  hr = pMsg->get_From(&buf);
  if(FAILED(hr))
    return hr;
  bstrFrom.AppendBSTR(buf);
  SysFreeString(buf);

  hr = pMsg->get_Subject(&buf);
  if(FAILED(hr))
    return hr;
  bstrSubject.AppendBSTR(buf);
  SysFreeString(buf);


  hr = pMsg->get_TextBody(&buf);
  if(FAILED(hr))
    return hr;
  bstrTextBody.AppendBSTR(buf);
  SysFreeString(buf);

    /*
    **  Write info to file
    */
  nBufSize = lstrlenW(bstrFrom);
  fRC = WriteFile(hFile,bstrFrom,nBufSize*2,&nSizeWritten,NULL);
  if(fRC == FALSE)
    return S_FALSE;

  nBufSize = lstrlenW(bstrTo);
  fRC = WriteFile(hFile,bstrTo,nBufSize*2,&nSizeWritten,NULL);
  if(fRC == FALSE)
    return S_FALSE;

  nBufSize = lstrlenW(bstrSubject);
  fRC = WriteFile(hFile,bstrSubject,nBufSize*2,&nSizeWritten,NULL);
  if(fRC == FALSE)
    return S_FALSE;

  nBufSize = lstrlenW(bstrTextBody);
  fRC = WriteFile(hFile,bstrTextBody,nBufSize*2,&nSizeWritten,NULL);
  if(fRC == FALSE)
    return S_FALSE;

  fRC = WriteFile(hFile,CComBSTR("\r\n\r\n"),4,&nSizeWritten,NULL);
  if(fRC == FALSE)
    return S_FALSE;


  CloseHandle(hFile);
  *pEventStatus = cdoRunNextSink;

  return S_OK;
}