How To Create an Exchange 2000 Store Event Sink in Visual C++ (288156)



The information in this article applies to:

  • Microsoft Exchange 2000 Server
  • Microsoft Visual C++, 32-bit Enterprise Edition 6.0
  • Microsoft Visual C++, 32-bit Professional Edition 6.0
  • Microsoft Visual C++, 32-bit Learning Edition 6.0

This article was previously published under Q288156

SUMMARY

This article demonstrates how to write a Store Event sink for Exchange Server 2000 by using Visual C++.

MORE INFORMATION

To create a Store Event sink, follow these steps. Note that you must do your development on an Exchange 2000 server.
  1. In Visual C++, create a new project. In the dialog box, select ATL COM AppWizard and accept the default settings.
  2. On the Insert menu, click New ATL Object. Select Simple Object and click Next. Type a name for the object, and then click OK.
  3. Click the ClassView tab to switch to the ClassView in your workspace browser. Right-click the class that was created, click Implement Interface, and then click OK.
  4. In the list of available type libraries, select EXOLEDB Type Library (1.0), and then click OK.
  5. In the Implement Interface dialog box, select the ones you want to implement and click OK. For store events, you must select at least one of the following interfaces:
    • IExStoreAsyncEvents: OnSave, OnDelete
    • IExStoreSyncEvents: OnSyncSave, OnSyncDelete
    • IExStoreSystemEvents: OnMDBStartup, OnMDBShutdown, OnTimer

  6. To avoid redefinition errors, rename the _SID_IDENTIFIER_AUTHORITY and the _SID structures in the EXOLEDB library. To do this, open the header file that was created for you, and change the following line
    #import "C:\Program Files\Exchsrvr\bin\exoledb.dll" raw_interfaces_only, raw_native_types, no_namespace, named_guids
    					
    to:
    #import "C:\Program Files\Exchsrvr\bin\exoledb.dll" raw_interfaces_only, raw_native_types, no_namespace, named_guids,\ 
    	rename ("_SID_IDENTIFIER_AUTHORITY","EXOLEDB_SID_IDENTIFIER_AUTHORITY"), rename("_SID","EXOLEDB_SID")
    					
  7. You can now expand the class that was created and see the list of functions for the interfaces that you chose. Double-click a function to go to the function definition. These functions are in a header file, and are inline functions that return the COM return code that indicates that they have not been implemented. For example:
    STDMETHOD(OnSyncDelete)(IExStoreEventInfo * pEventInfo, BSTR bstrURLItem, LONG lFlags)
    {
        return E_NOTIMPL;
    }
    					
  8. For the functions that you want to implement, remove the inline function, leaving just the function prototype. Be sure to end the prototype with a semicolon (;).
  9. Switch to the source (.cpp) file that matches the name of the header. Place your function implementations here. For example:
    // Import the ADO and CDOEX DLLs.
    #import "C:\Program Files\Common Files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF"), named_guids
    #import "C:\Program Files\Common Files\Microsoft Shared\CDO\cdoex.dll" no_namespace
    
    STDMETHODIMP CATLSink::OnSyncSave(IExStoreEventInfo * pEventInfo, BSTR bstrURLItem, LONG lFlags)
    {
    	HRESULT hr = S_OK;
    
    	// Only do this at the beginning of the transaction.
    	if (lFlags & EVT_SYNC_BEGIN)
    	{
    		// Cast pEventInfo to a IExStoreDispEventInfoPtr.
    		IExStoreDispEventInfoPtr pDispInfo = pEventInfo;
    		
    		// Create a new message.
    		IMessagePtr iMsg(__uuidof(Message));
    		
    		_RecordPtr rec;
    		char szSubject[256];
    		char szTextBody[256];
    
    		// Get the record that caused the event.
    		// This is the new message.
    		pDispInfo->get_EventRecord((IDispatch**)&rec);
    
    		// Set up a reply.
    		iMsg->From = "notifier@microsoft.com";
    		
    		// Set the recipient to the sender of the message that caused the event.
    		iMsg->To = rec->Fields->GetItem("urn:schemas:httpmail:fromemail")->Value.bstrVal;
    		
    		// Set up the subject string to contain the subject of the message that caused the event.
    		sprintf(szSubject,"Message Received: %s", (char*)(_bstr_t)rec->Fields->GetItem("urn:schemas:httpmail:subject")->Value.bstrVal);
    		iMsg->Subject = szSubject;
    		
    		// Set up the text of the message to contain the URL to the message that caused the event.
    		sprintf(szTextBody, "The following item was received:\n%s", (char*)(_bstr_t)bstrURLItem);
    		iMsg->TextBody = szTextBody;
    
    		// Send the message.
    		iMsg->Send();
    
    		iMsg = NULL;
    	}
    	return hr;
    }
    					
  10. Compile and link your code. This automatically builds and registers a dynamic-link library (DLL). For the event sink to function, place the DLL in a COM+ application.

Modification Type:MajorLast Reviewed:9/27/2006
Keywords:kbhowto kbMsg KB288156