Component Object Model and MAPI

The Platform SDK documentation includes a comprehensive discussion of the rules for implementing objects that conform to the Component Object Model (COM). These rules address how to:

Although all MAPI objects are considered COM-based because they implement interfaces that inherit from IUnknown, MAPI deviates in some situations from the standard COM rules. This deviation allows developers more flexibility in their implementations. For example, a MAPI interface, like any COM interface, describes a contract between implementer and caller. Once the interface is created and published, its definition cannot and does not change. MAPI does not deviate from this description, but it relaxes the description somewhat. Implementers can choose to not implement particular methods, returning one of the following error values to the caller:

MAPI_E_NO_SUPPORT

MAPI_E_TOO_COMPLEX

MAPI_E_BAD_CHARWIDTH

MAPI_E_TYPE_NO_SUPPORT

The other deviations from the standard COM rules are described in the following table.

COM programming rule MAPI variation
All string parameters in interface methods should be Unicode. MAPI interfaces are defined to permit either Unicode or ANSI string parameters. Any method that has a string parameter also has a ulFlags parameter; the width of the string parameters is indicated by the value of the MAPI_UNICODE flag in ulFlags.
Most MAPI interfaces to not support Unicode and return MAPI_E_BAD_CHARWIDTH when the MAPI_UNICODE flag is set.
All interface methods should have a return type of HRESULT. MAPI has one method that returns a non-HRESULT value: IMAPIAdviseSink::OnNotify.
Callers and implementers should allocate and free memory for interface parameters using the standard COM task allocators. All MAPI methods use the linked allocators MAPIAllocateBuffer, MAPIAllocateMore, and MAPIFreeBuffer to manage memory for interface parameters.
All MAPI implementations of interfaces defined by OLE, such as IStream, use the standard COM task allocators.
All out pointer parameters must explicitly be set to NULL when a method fails. MAPI interfaces require that out pointer parameters either be set to NULL or remain unchanged when a method fails.
All MAPI implementations of interfaces defined by OLE explicitly set out parameters to NULL on failure.
Implement aggregatable objects whenever possible. MAPI interfaces are not aggregatable.