The first time we saw this, we wrote it off as an odd thing one customer did. But we’ve seen it a few times over the past couple years and it deserves some discussion. The issue is with Exchange Client Extensions (remember – they’re dead in 2010!): Customers would report that, when client extensions from certain companies are loaded, Outlook will behave strangely. The symptoms would usually be a crash or a hang. On debugging, we would find that even the hang was preceded by an access violation.
When we debugged this, what we saw on the stack was an Exchange Client Extension calling into an IExchExtCallback object. Nothing unusual there, that’s what a callback object is for. What was unusual though, was that when we look further up the stack, Outlook hadn’t called into into the extension! Here’s the usual sequence of operations:
- ECE registers for various events
- Outlook fires one of the events, calling into the ECE’s event handler.
- One of the parameters of the event is an IExchExtCallback object, which the handler can use to obtain more information about the context of the event.
- The event handler returns.
- Outlook releases the IExchExtCallback object, which had been created specifically for this event.
Note that last bit – Outlook creates these callback objects individually for the events they’re handed to, and releases them when the event is done. Note also, that these objects only make sense in the context of an event. For instance, the GetObject method returns a message store and a MAPI object. During the context of an event, which message store and which object would be returned makes sense. But after the event is done, there’s no context to establish which store or which object should be referenced.
And this is why these extensions were throwing an access violation. They had cached a pointer to an IExchExtCallback object they had gotten during an earlier event and were using it later outside the context of the event. Since this object was not designed to handle this, it would crash. Whether Outlook would crash, hang, or otherwise behave oddly depended on whether or not an exception handler caught the AV.
Not only does caching these objects not make sense once you consider the design, it’s actually precluded in the documentation. On the page for IExchExtCallback:IUnknown we have the following note:
A pointer to this interface is passed as a parameter to many methods of the Microsoft Exchange extensibility API. This interface and any interfaces it might return are valid only for the time of the call to one of its methods and might not be retained when the extension object’s method returns.
So – even though extensions are going away in Outlook 2010, if you have an extension in market right now for Outlook 2007 or earlier, you might want to review your code and check if you’re caching this object. If you are, you’re causing crashes for your customers.