Client applications and service providers can assume that objects used directly or as callbacks are always thread-safe except in the following cases:
When a client accesses a transport provider’s row in the status table that includes the entry identifier of the associated status object, the client can open a status object by calling OpenEntry with that entry identifier. This status object is not thread-safe because transport providers run in the context of the MAPI spooler and do not maintain a separate context for their status objects. Status objects obeys apartment model rules and clients must use them only on the thread that created them.
A client must also invoke MAPIInitialize on every thread before using any MAPI objects and MAPIUninitialize when that use is complete. These calls should be made even if the objects to be used are passed to the thread from an external source. MAPIInitialize and MAPIUninitialize can be called from anywhere except from within a Win32 DLLEntryPoint function, a function that is invoked by the system when processes and threads are initialized and terminated, or upon calls to the LoadLibrary and FreeLibrary functions. Clients should not require the DLLEntryPoint functions because the MAPI service provider interface has its own initialization and deinitialization entry points.
Indirect use objects should never be assumed to be thread-safe. Indirect use objects are returned by methods that require destination interface pointers as input parameters. Examples of such methods are IMAPIProp::CopyTo and CopyProps, IMAPIFolder::CopyFolder and CopyMessage, and IMsgServiceAdmin::CopyMsgService. If a service provider wants to call such an object from a thread other than the one on which it was passed, the provider is responsible for explicitly marshalling the object.