Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

XADM: MAPI Notifications Appear to Be Dropped


View products that this article applies to.

This article was previously published under Q190413

↑ Back to the top


Summary

When registering for MAPI notifications on the Microsoft Exchange Public, Private, or Personal Store, the Advise OnNotify callback function does not get called when you think it should be.

↑ Back to the top


More information

The reason you are not getting notifications can be due to one of four things:

  • You are registered for table notifications, and you forgot to do a SetColumns() on the table.
  • A remote procedure call (RPC) call was not forced to the server to start the notifications (use a GetProps() call on the object).
  • The message was sent, but you do not have a Windows message loop translating and dispatching the notifications (especially with personal folder file [.pst] notifications).
  • The INFORMATION STORE is using Fast Transfer to do the copy/move operation.

    The Information Store uses a copy/move mechanism called fast transfer (also referred to as a "tightly coupled store" in MAPI documentation) when it detects the RPC destinations are not the same. You can see this in the behavior of Advise Sinks during operations that cross store boundaries (such as copying mail from your Inbox to the .pst file). With the public information store, almost all operations of this type use the fast transfer mechanism. This is based on the need for speed across the network (fast transfer is used to minimize RPC traffic, and maximize data throughput by packing certain properties, and omitting batches of properties depending on the operation, the object, and the client).

Background

MAPI notifications are used by applications to gather data about MAPI events. Essentially, the application will create what is called an Advise Sink, and register for notifications by calling the Advise() method of the particular MAPI interface it is interested in.

Several types of MAPI notifications are available:

  • Error notification
  • Extended notifications
  • New Mail notifications
  • Object notifications
  • Status notifications
  • Table notifications
MAPI determines the type of notification to send based on an event mask (a bitmask) passed into the advise method of the interface. The following flags can be set:

  • fnevCriticalError
  • fnevExtended
  • fnevNewMail
  • fnevObjectCopied
  • fnevObjectCreated
  • fnevObjectDeleted
  • fnevObjectModified
  • fnevObjectMoved
  • fnevSearchComplete
  • fnevTableModified
NOTE: Not all flags can be used with every Advise implementation. Check the documentation for specific calls.

There are three different methods of building the actual Advise Sink. The first is fairly easy. Use a single callback function and create the Advise Sink with the Exchange Development Kit (EDK) function HrAllocAdviseSink(). For the lpvContext parameter, pass the pointer to the MAPI interface you want notifications on (example below).
   STDAPI HrAllocAdviseSink( LPNOTIFCALLBACK lpfnCallback,
      LPVOID lpvContext,
      LPMAPIADVISESINK FAR * lppAdviseSink );
				
The callback function must also be declared as in the following example:
   static SCODE STDAPICALLTYPE ScNotificationHandler(LPVOID lpvContext,
      ULONG cNotifications,
      LPNOTIFICATION lpNotifications);
				
The second method of creating an Advise Sink is to actually inherit from IMAPIAdviseSink, and handle the OnNotify member of that class.

The third method is to use Microsoft Foundation Classes' (MFC) OLE interface maps. These must be used from within a class inheriting from CCmdTarget. The form for these macros looks like the following:
   BEGIN_INTERFACE_PART( AdviseSink, IMAPIAdviseSink )
      STDMETHOD_( ULONG, OnNotify ) ( ULONG, LPNOTIFICATION )
   END_INTERFACE_PART( AdviseSink )
				
Then implement the methods of IMAPIAdviseSink in your CCmdTarget derived class (AddRef, Release, QueryInterface, and OnNotify). The following example is of QueryInterface:
   STDMETHODIMP_ CAdvise::XAdviseSink::QueryInterface(REFIID riid, void **
   ppv)
   {
      METHOD_PROLOGUE(CAdvise, AdviseSink)
      return this->ExternalQueryInterface(riid, &ppv);
   }
				
For more in-depth information on OLE interface maps, look in the Platform SDK.

Most MAPI coding difficulties stem from the assumption that all the client code needs to know is the Caller section and that each new provider will work in the same manner as the old familiar ones. The bottom line with MAPI is to always read the documentation for the Implementer as well as the Caller, and to never assume it will always work as expected for every message store provider.

As is always the case in MAPI, there are definite caveats when working with the Exchange Server public store as opposed to the private store (where global notifications do work, for instance).

↑ Back to the top


Keywords: KB190413, kbprb

↑ Back to the top

Article Info
Article ID : 190413
Revision : 6
Created on : 10/28/2006
Published on : 10/28/2006
Exists online : False
Views : 289