The Outlook 2010 MAPI Reference has been updated. I don’t have a list of everything that changed, so I’ll highlight one addition that’s pretty cool: the property definition stream. Long time readers might remember I mentioned this property before – it’s one of the properties you want to delete to kill a one-off form. It’s also the property that Outlook uses to store information about named properties created via the Object model and the user interface.
Now that the format of PidLidPropertyDefinitionStream is documented, you can create new user defined properties using MAPI and have them show up in the UI! The September release of MFCMAPI (which I’m furiously hammering on) will be able to parse this property.
As usual, the documentation is also available for download.
Enjoy!
My colleague Edwin, writing for the Exchange Support Team Central Europe blog, posted an article on accepting meeting requests with CDO. The key takeaway from the post is this:
This means that when calling the respond method on meeting updates / requests, the sequence number must be read from the request and written to the response, otherwise Outlook will not be able to match the response to the original meeting. (The proposed solution is to read the dispidApptSequence from the original message and write this to the meeting update response before sending.)
He also points out that this requirement is spelled out in the MAPI protocol documentation, here.
Since CDO has reach end-of life, we won’t be taking a change to CDO to have it do this, so you’ll need to do it yourself. Edwin gives sample code that demonstrates how.
I just closed a case where the customer was trying to create a profile but Check Name was constantly prompting for credentials and then failing. This wasn’t the reconfig issue I mentioned before – they couldn’t create the profile in the first place. Even GCReconnect showed the same behavior – repeated prompts for credentials, then failure, with the error MAPI_E_USER_CANCEL. We took a network trace of the attempt to create the profile to see where the failure came from. The trace showed us attempting to set up NTLM authentication, sending the request to the Exchange server. Exchange passed the packet on the the GC, which promptly returned 0x721: RPC_S_SEC_PKG_ERROR.
This is a common error to get when attempting to use Kerberos authentication. Configuring Kerberos at times can be tricky, and if it’s not all set up right, this is the error you expect to get. One workaround usually given is to make sure NTLM is set up and fall back to NTLM when Kerberos doesn’t work. However, in this case, we were trying NTLM in the first place!
After some poking around, we took a look at the local policy settings on the three machines. Here’s what we found:
Client Network security: Minimum session security for NTLM SSP based (including secure RPC) clients- Not defined Network security: Minimum session security for NTLM SSP based (including secure RPC) servers- Not defined Exchange Network security: Minimum session security for NTLM SSP based (including secure RPC) clients- Require NTLMv2 session security, Require 128-bit encryption Network security: Minimum session security for NTLM SSP based (including secure RPC) servers- Require NTLMv2 session security, Require 128-bit encryption GC Network security: Minimum session security for NTLM SSP based (including secure RPC) clients- Require NTLMv2 session security, Require 128-bit encryption Network security: Minimum session security for NTLM SSP based (including secure RPC) servers- Require NTLMv2 session security, Require 128-bit encryption
Since the client was not configured to use NTLMv2, it tried to authenticate with NTLMv1. Since the server required NTLMv2, it rejected the request, with the appropriate error message: RPC_S_SEC_PKG_ERROR. Once the customer configured the policy on the client (it had just been overlooked during setup), they were able to complete profile configuration.
For more information on these policies, see here and here.
When I posted the Referral Madness article, there was an intriguing comment that I didn’t get a chance to investigate until it came up in a case. The commenter noted that when we used RPC_C_AUTHN_GSS_NEGOTIATE as our authentication mechanism, we could no longer use “Check Name” in the dialog brought up by ConfigureMsgService:
If we hit Check Name, we get an error that the name could not be resolved due to network problems:
To understand why we get this error, we look at one of the caveats I noted:
During profile configuration (ConfigureMsgService), the Exchange provider will do an NSPIBind to the Exchange server to lookup the mailbox name. This single bind and lookup is unavoidable.
In order to perform the name resolution involved in Check Name, the Exchange provider is going to go through DSProxy. In network terms, this means we’re sending the packets directly to the Exchange server. DSProxy picks up our packets and forwards them on, unchanged, to the GC. Consider how this affects authentication. When we use RPC_C_AUTHN_GSS_NEGOTIATE, in most environments this means we’re going to use Kerberos. Combining the two: the client thinks it needs to negotiate Kerberos authentication with the Exchange server. It begins the handshake, sending a packet with a ticket using the Service Principal Name (SPN) for the Exchange server. DSProxy grabs this packet and whips it on over to the GC. The GC tries to parse the ticket in the packet but can’t since the ticket wasn’t intended for the GC. The GC returns the Kerberos error KRB_AP_ERR_MODIFIED. This error bubbles up on the client side as MAPI_E_NETWORK_ERROR, resulting in the dialog.
This problem with proxying Kerberos packets was noted in a KB article a long time ago, which has one of the earliest references to profile settings to enable referral. In the KB article, they wanted to enable Kerberos authentication to get around a problem with authenticating local system accounts, but due to the problem discussed here, also had to enable referral.
Does this mean we’ve got a bug in DSProxy’s handling of Kerberos? Not really – DSProxy predates Windows’ adoption of Kerberos by a number of years. Kerberos authentication can by proxied, but the proxy must be aware it’s proxying Kerberos traffic – it’s not as simple as reading packets off one port and sending them out another. On the other hand, NTLM authentication, the default used by the Exchange provider when we don’t specify an authentication mechanism, can handle being passed to the GC by DSProxy. This would fall under the heading of design limitation.
So – the upshot:
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:
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.