Getting Exchange MAPI's GC-Reconnect stuff to work

I recently wrestled with this and found it wasn't exactly intuitive, so I wanted to share my findings.

What the heck am I talking about?

Imagine this scenario.  Your MAPI application running on a machine with Exchange 2000 or 2003's MAPI implementation is humming along smoothly, when a global catalog server (GC) goes down.  This particular GC happens to be the one that your MAPI session is using for address book lookups (having received a referral to this GC from your Exchange server, see 256976 for more information).  There are plenty of other available GC's that could serve up the GAL for you.  What happens?

Prior to the Exchange 2000 August 2004 Post-Service Pack 3 Rollup (870540) and Exchange 2003 SP1, your app lost all address book functionality until you logged off and established a whole new MAPI session (the new session would get a new referral from the Exchange server).  This was of course not an ideal situation.  So, we fixed it ;-)

If you apply the 870540 rollup (for 2000) or SP1 (for 2003) onto the box where your code runs, you now have the new "GC-reconnect" logic.  The idea here is that if a GC goes down, we can dynamically recover from it by dumping the bad server and going back to Exchange for a new referral, without having to start a new MAPI session.  You get a MAPI_E_END_OF_SESSION error if the reconnect happens, at which time you should retry the call.

So I put on the required update. I should be good to go, right?

Not so fast.  First thing you need to do is set some flags in your MAPI profile.  These flags are fairly new, so you should probably take a side trip and grab the newest edkmdb.h.  Edit: You can now get this from the latest Exchange 2003 SDK, available here.

These new props should be set on the EMSABP profile section.  You can get to that using the OpenProfileSection function and the following UID:

 #define MUIDEMSAB "\xDC\xA7\x40\xC8\xC0\x42\x10\x1A\xB4\xB9\x08\x00\x2B\x2F\xE1\x82"

The properties (and what they mean) are:

 ' If present and set to any > 0 value, enables the reconnect logic
PR_PROFILE_ABP_ALLOW_RECONNECT
' If present, indicates the # of seconds that multiple threads that are accessing
' the address book concurrently should block waiting for the
' first thread to enter the reconnect logic to complete
PR_PROFILE_ABP_MTHREAD_TIMEOUT_SECS

So, you need to at least set PR_PROFILE_ABP_ALLOW_RECONNECT to some positive value to turn on the reconnect logic.

Ok, I did that. But it still doesn't work!

This is what took me a bit to track down.  I'm guessing that you're using a new profile (maybe like in my case, your application creates a profile for itself before logging on)  It turns out that the reconnect stuff is also dependent on another profile property: PR_PROFILE_SERVER_VERSION.  This one's in the new edkmdb.h too.  EMSABP32 checks this property (it's on the global profile section) to see if it can determine what kind of Exchange server it's talking to.  For GC referrals to happen, we need to be talking to at least an Exchange 2000 server.  Since this is a new profile, that property isn't set yet, so we can't just assume that GC referrals are available.  So, we just do a normal connection to the Exchange server.  Exchange handles our AB requests through DSProxy for this session, then tells MAPI that it needs to update the profile to set PR_PROFILE_SERVER_VERSION.  So the NEXT time you logon, you'll go through the GC-referral process, but for this session, you'll have to settle for proxying through the Exchange server. 

This is important, because the GC-reconnect logic doesn't work when we're proxying through Exchange!  Fortunately the fix is simple.  As long as you know that you're in a no-5.5 environment, you can set PR_PROFILE_SERVER_VERSION to 3000 (the magic # indicating Exchange 2000).