Platform SDK: Exchange Server |
The Suggest COM component is implemented using the Active Template Library (ATL). The following list gives the names of the Suggest application sample files and a brief description of file's role in the application.
File Manifest
File | Description |
---|---|
Exchhndl*.* | Header and interface definition files from the Platform SDK. |
ExEvHandler.cpp | Contains the implementation of the ExecuteEvent method on the exposed IExchangeEventHandler interface. |
ExEvHandler.h | Contains declarations for the CExEvHandler class. |
Exevhandler.rgs | Contains information for registering the CExEvHandler CLSID. |
Propid.h | Contains (mostly property) definitions. |
Regs.cpp | Contains routines to work with the registry. |
Regs.h | Contains declarations for the registry routines in Regs.cpp. |
SAProps.cpp | Contains the implementation of the CSAProps class. |
SAProps.h | Contains the declaration of the CSAProps methods in SAProps.cpp. |
SAProps.rgs | Contains information used to register the COM component. |
Suggest.cpp | Contains the DllMain routine (entry point for the DLL). |
Suggest.def | Contains definitions of the library name and exported functions. |
Suggest.dsp Suggest.dsw |
The project and workspace. Do not directly edit these files, use the IDE. |
SuggestEvents.cpp | Contains the code for handling events. |
SuggestEvents.h | Contains declarations for the routines in SuggestEvents.cpp. |
An Exchange Server event handler is any COM class that provides an implementation of the IExchangeEventHandler COM interface. The interface definition language (IDL) definition for this interface can be found in the file exchhndl.idl (located in the Platform SDK core build environment include directory), and is provided here for convenience:
[ object, uuid(69E54156-B371-11D0-BCD9-00AA00C1AB1C), oleautomation, pointer_default(unique) ] interface IExchangeEventHandler : IUnknown { HRESULT ExecuteEvent([in] IDispatch* pEventSource); };
When custom agents (event handlers) are registered on the Exchange Server machine, and are properly advertised as such by being registered in the COM category "Exchange Event Handler Category", they can be bound to folders to handle events. Every time the Exchange Server Event Service is started, it checks the registy for registered handlers, and makes them available to handle folder events. When users select the Agents property page with Microsoft Outlook for a folder, they are presented with a list of any number of registered agents that they can use (with proper permissions) for the folder.
Once an agent has been bound to a folder, the Exchange Server Event Service monitors the folder using Incremental Change Synchronization for changes in its status, such as the addition or removal of items. When such a change occurs, it does the following:
The IEventSource interface IDL definition is located in the file exchhndl.idl, and is presented here:
[ object, uuid(69E54152-B371-11D0-BCD9-00AA00C1AB1C), oleautomation, pointer_default(unique) ] interface IEventSource : IUnknown { [propget] HRESULT Source ([out,retval] IUnknown**); [propput] HRESULT Source ([in] IUnknown*) [propget] HRESULT SourceID ([out,retval] BSTR*); [propput] HRESULT SourceID ([in] BSTR); [propget] HRESULT MessageID ([out,retval] BSTR*); [propput] HRESULT MessageID ([in] BSTR); [propget] HRESULT Session ([out,retval] IUnknown**); [propput] HRESULT Session ([in] IUnknown*); [propget] HRESULT EventType ([out,retval] DWORD*); [propput] HRESULT EventType ([in] DWORD); [propget] HRESULT Response ([out,retval] VARIANT*); [propput] HRESULT Response ([in] VARIANT); [propget] HRESULT MaxExecutionTime ([out,retval] DWORD*); [propput] HRESULT MaxExecutionTime ([in] DWORD); };
Note The IExecuteEvent interface is not dual, as it inherits from the IUnknown interface. The first parameter of the ExecuteEvent method is typed to IDispatch. Do not attempt to use any methods defined for IDispatch as this interface is not dual. Immediately call QueryInterface to get the IExecuteEvent interface and work with this interface only.
Once the agent has the IEventSource interface, it can retrieve event information and act accordingly. The event type for the folder is one in the following enumeration:
enum EventType { Invalid, Folder_OnTimer, Folder_OnMessageCreated, Folder_OnMessageDeleted, Message_OnChange, Message_OnMove, };
Response text can be placed in the Response property (VT_BSTR) of the EventSource object and it will be appended to the folders Event log.
The Suggest COM component provides the ExEvHandler COM class as a custom event handler. It exposes the IExchangeEventHandler interface and provides a concrete implementation of the ExecuteEvent method. The Event Service calls this method, passing the IEventSource interface on an EventSource COM object. The agent code shown in the following section does the following:
STDMETHODIMP CExEvHandler::ExecuteEvent(LPDISPATCH pSource) { HRESULT hr = S_OK; IEventSource* pEventSource = NULL; DWORD dwEventType = 0; // Get the IEventSource Interface if(SUCCEEDED(hr = pSource->QueryInterface(IID_IEventSource, (void**)&pEventSource))) { // cache this pointer m_pEventSource = pEventSource; // Determine our Event Type if(SUCCEEDED(hr = GetEventType(&dwEventType))) { // We instantiate a instance of our events class CSuggestEvents se; // Call appropriate function switch(dwEventType) { case Message_OnChange: hr = se.OnChange(this); break; case Folder_OnMessageDeleted: hr = se.OnMessageDeleted(this); break; case Folder_OnTimer: hr = se.OnTimer(this); break; case Folder_OnMessageCreated: hr = se.OnMessageCreated(this); break; default: hr = E_INVALIDARG; break; } } m_pEventSource->Release(); } return(hr); }
The handling methods are listed in the following table along with a brief description of what they do.
CSuggestEvents ATL C++ Class
Member | Description |
---|---|
::OnMessageCreated | This method is called when the Event Type is Folder_OnMessageCreated. This method sends a reply to the person whose message triggered the event. The body of the message contains the text "Thank-you for your suggestion. You will be hearing from a suggestion consultant soon." |
::OnChange | Returns S_OK |
::OnMessageDeleted | Returns S_OK |
::OnTimer | Returns S_OK. |
For additional information about implementing custom agents, see Advanced Topics: Custom Agents.