The November 2008 Release (build 220.127.116.110) is live: http://www.codeplex.com/MFCMAPI
While we were working on the site for the Outlook MAPI Samples I mentioned that Codeplex allows projects to have a logo, and asked if anyone had any ideas. Next thing I knew, we had a designer lined up ready to draw a custom logo. Not to let an opportunity go to waste, I pointed out how awful the icon for MFCMAPI was. I didn’t really expect to get a new icon, but look what showed up in my mail last night:
The new icon alone is enough to warrant a new release, but I slipped in some other goodies as well. Here's a change list - see the Issue Tracker on Codeplex for more details, or look at the code:
I've had a few customers lately getting hangs using Exchange's MAPI to talk to Exchange. Their specific symptoms and repro steps varied from case to case, but in every case, the stack showed the client waiting on an NSPI call to return. NSPI is the interface the Exchange Address Book Provider uses to talk to the Global Catalog. In every case, the hung NSPI call was to the Exchange server and not the GC. The fix in each case was to enable referral so the client talked to GC directly. In this article, I want to discuss NSPI, DSProxy, the reasons for the hang, referral, and introduce an updated GCReconnect sample that demonstrates how this all works. I've also tried to consolidate all the relevant information into this one article so you can get your apps working quickly.
Back in the day (AKA Exchange 5.5 and earlier), Exchange had its own directory. When a MAPI client wanted to look something up in the directory, it would make a call using the Name Service Provider (NSPI) interface. Exchange registered to listen on this interface, and when it received an NSPI request, it would perform the lookup in the directory and return the results. When Exchange and Windows 2000 came along, Exchange stopped handling the directory - that's the GC's job. The GC implemented NSPI, so any MAPI client that wanted to talk to them instead could do so. But many MAPI clients out there still wanted to talk to the Exchange server, so Exchange still registered to listen for NSPI requests. Instead of handling the requests though, Exchange would look up an appropriate GC and send the packets over there. Any response it got back from the GC would be sent straight on to the client that originated the call. The process that handles this is called DSProxy. This whole process is documented at the bottom of this article: How MAPI Clients Access Active Directory.
Of course, this double hop of every directory lookup isn't terribly efficient. It would be better if the client could ask the Exchange server what the best GC is, and then send it's requests there instead. So we developed the Referral (RFR) Interface. A client that wishes to avoid using DSProxy can use the RFR interface to get the name of a GC, then connect directly to that GC and avoid all the extra network traffic and load on the Exchange server. As How MAPI Clients Access Active Directory notes, Outlook 2000 was the first client to implement this logic. At the time that article was written, Exchange's MAPI couldn't ask for a referral, so anyone using Exchange's MAPI always used DSProxy.
Then along came Jason's article: Getting Exchange MAPI's GC-Reconnect stuff to work. Jason found that we had ported the RFR logic into Exchange's MAPI, and that it was possible to turn it on in a brand new profile. All you had to do was set a couple extra properties before logging on. If Jason's properties are set, the Exchange Address Book Provider will ask for a referral, and assuming it gets one, will always talk directly to the GC.
Recently, we found that Jason's settings weren't working when connecting to an Exchange 2007 server. Due to some changes we made in Exchange 2007, getting Exchange's implementation of MAPI to request a referral required setting a few more properties.
Exchange's implementation of the NSPI proxy in DSProxy is somewhat simplestic. It literally reads packets from one socket and writes them to the other. A side effect of this simple implementation is a number of error scenarios don't get handled well. Particularly if the GC being proxied to goes down - DSProxy doesn't always send the error back to the client. So we can end up with a client that's waiting on the server to respond, and a server that's convinced the connection has been torn down. This particular hang can only happen if the MAPI client isn't using referral, which is why it's so important to ensure referral is working.
I've updated the sequence of steps performed in requesting a referral, assuming the RFR settings have been made:
Always set the following:
In the MUIDEMSAB profile section (dca740c8c042101ab4b908002b2fe182):
In the global profile section (13DBB0C8AA05101A9BB000AA002FC45A):
Set the following if your application connects to Exchange 2007 and does not run locally on the Exchange 2007 server:
If your application connects to Exchange 2007 and runs locally on the Exchange 2007 server, then requesting referral is not possible. In fact, setting the Exchange 2007 referral settings in this scenario will cause logon to fail.
These settings must be made before you call MAPILogonEx. Setting them after then would obviously be too late. You can check if you got a referral by reading PR_PROFILE_HOME_SERVER from the MUIDEMSAB profile section after you do your logon. If it's set to one of your GCs, then referral is working.
Some time last year, Jason's blog on referral and reconnect got converted into a KB article. Part of that article included the sample code we were using to test this, called GCReconnect. I've polished this code up to demonstrate the new profile settings and added switches to allow testing. I've posted the updated sample here.
When you build and run the sample, this is what you'll see:
C:\>GCReconnect.exe Creates a profile, optionally enabling referral and reconnect logic, and tests name lookup.
Usage: GCReconnect [-?] -m mailbox -s server [-e] [-x] [-n name] [-l] [-r] [-w]
Options: -m mailbox Specifies the mailbox to log on to. -s server Specifies the Exchange server where the mailbox resides. -e Enable referral and reconnect If referral and reconnect are not enabled, MAPI will connect directly to the Exchange server for name lookup -x Enable additional referral and reconnect settings for Exchange 2007 Implies -e -n name Specifies a name to resolve with ResolveName If not specified, QueryIdentity will be used instead -l Loop over MAPILogonEx. Will log on and off repeatedly until key is hit -r Loop over ResolveName. Will log on once and do name lookup repeatedly until key is hit Requires -n, not valid with -l -w Wait for keyboard input before and after creating and configuring profile -? Displays this usage information.
If you give just a mailbox and server name, GCReconnect will build a profile, connect to the mailbox, and look up your user's name in the directory. The -e and -x switches turn on referral and reconnect, while the -l and -r switches allow you to tell the app to keep hitting the server so you can test scenarios like failover when you turn off a GC. With the -n switch, you can give a different name for the directory lookup test. The last switch, -w, just makes the app wait so you can attach a debugger, if you're in to that sort of thing.
Troubleshooting and Caveats
1 – Open Regedit on the Exchange Server
2 – Navigate to HKLM\System\CurrentControlSet\Services\MSExchangeSA\Diagnostics
3 – Locate the “11 NSPI Proxy” and “12 RFR Interface” values and set each of them to 5