MAPI furnishes a support object, an object that implements the IMAPISupport : IUnknown interface, for all service providers during logon and for all message services during configuration. Support objects are not accessible by clients; they are implemented by MAPI and called only by service providers. The IMAPISupport interface is specified in the header file MAPISPI.H. Its identifier is IID_IMAPISup and its pointer type is LPMAPISUP. No MAPI properties are exposed by support objects.
A provider can be given one or more support objects, depending on the number of times MAPI logs the provider on or the number of times the provider's message service entry function is called. Typically, a provider will be logged on at least once per session. Address book and transport providers are logged on every time a client starts a session with a profile entry requesting them. Message store providers are logged on every time a client calls IMAPISession::OpenMsgStore.
In the case of multiple logons in a session, you can choose either to retain and use each support object separately or to retain and use only the first, discarding each subsequent support object. To retain a support object, call its IUnknown::AddRef method. Calling AddRef on a support object that you want to retain throughout a session is extremely important; if the call is not made, MAPI releases the support object and frees its memory.
The purpose of the support object is to provide implementations for a fairly large number of methods commonly used by the providers. Each support object also contains contextual data specific to its own instance, such as the session the provider is running in, the profile section the provider is using, and error information for the session.
There are four different types of support objects: one for each major provider type (address book, message store, and transport) and one for configuration support. Messaging hook providers run within the same thread as the MAPI spooler and are given a session object instead of a support object.
MAPI customizes each support object by including implementations of methods that are relevant for its usage. Implementations of some methods, such as OpenProfileSection, are included in all support objects. Implementations of other methods, such as SpoolerNotify, apply only to particular support objects. Only message store and transport providers can use this method; when an address book provider or a message service try to call it, MAPI returns MAPI_E_NO_SUPPORT.
Support objects can be used to accomplish many tasks, such as:
At logon time, MAPI calls the logon method of each service provider's provider object. For address book providers, MAPI calls IABProvider::Logon. For message store providers, MAPI calls IMSProvider::Logon. For transport providers, MAPI calls IXPProvider::TransportLogon. MAPI passes a pointer to the appropriate support object in one of the parameters to this method. The logon method in turn instantiates a logon object, passing it the support object pointer. The logon object calls the support object's IUnknown::AddRef method to retain it if necessary. For more information about the logon process for service providers, see Starting a Service Provider.
When a client logs off, MAPI calls the logon object's logoff method. The logoff method calls the support object's IUnknown::Release method to indicate that the provider no longer intends to call any of the support methods. As with logon, the logoff methods have slightly different names. The IABLogon and IMSLogon interfaces have Logoff methods; the IXPLogon interface has a TransportLogoff method.
Message service entry point functions are called when a logon attempt fails with the error MAPI_E_UNCONFIGURED or when a client initiates a configuration request. MAPI instantiates a configuration support object and calls the message service entry point function for either the unconfigured provider or the provider whose configuration is about to change. Unlike the other support objects, configuration support objects are valid only until the entry point function returns; message services do not call these objects' AddRef methods to retain them.
Typically, MAPI makes calls to a provider's message service entry point function, but sometimes a provider is asked to make the call. This can occur when a client calls a provider's IMAPIStatus::SettingsDialog method to prompt the provider to display its configuration property sheet. SettingsDialog should call IMAPISupport::GetSvcConfigSupportObj to obtain a configuration support object that it can pass to the message service entry point function.
The IMAPISupport::GetMemAllocRoutines method is available for determining the addresses of the memory allocation and deallocation functions without having to link with MAPI. Using GetMemAllocRoutines also makes it easier to trace memory leaks by surrounding the allocation function calls with debugging code. If you call GetMemAllocRoutines, as is recommended, do so before calling the CreateIProp function, which requires the allocation function addresses as parameters.
When you need to create a new address book or message store object, create and set a search key for the object in its PR_SEARCH_KEY property. Call IMAPISupport::NewUID to obtain a unique identifier to use in building a search key. Do not use your own hard-coded MAPIUID. A provider's MAPIUID should only be used for entry identifiers. For more information about constructing search keys, see Record and Search Keys.
A client application can sometimes release an object without releasing one or more of its affiliated objects. In such a case, a provider may need to render an unreleased object unusable. To do this, the provider frees all of the resources connected with the object and then calls IMAPISupport::MakeInvalid to invalidate the object's vtable. MakeInvalid replaces the vtable's IUnknown methods (QueryInterface, AddRef, and Release) with standard MAPI implementations and causes all other methods to return MAPI_E_INVALID_OBJECT. MakeInvalid also frees all the object's memory other than the vtable.