Sorry for not posting this sooner - I just found out about it today. As I noted previously, we recently fixed the MAPI download to work on Vista and Windows Server 2008. This broke some ISVs who weren't expecting Exchange's MAPI to use the MAPI stub library. So, to give ISVs time to validate their applications with the new download, we've reposted the old one. Now there are two download pages:
Note that the older installer is only being offered until August 15th.
Update: The pre-Vista package has been taken down. See Pre Vista Fix MAPI Download No Longer Available.
One of our customers reported that if they used IConverterSession::MIMEToMAPI to generate an MSG file, then opened the MSG file and hit Forward, the body would be gone. Further investigation revealed more funkiness. Reply worked, but if you tried Forward, closed the forwarded message, then tried Reply again, the body would be missing there as well. I could also repro the problem with some messages I saved to MSG from MFCMAPI.
If you've read my other article on MSG files you know this behavior doesn't surprise me. I did file a bug on this, but it got rejected since it turns out there's an easy workaround for the case my customer was hitting.
The problem basically comes down to the best body logic as it applies to an MSG file. All of the MSG files we were dealing with here had PR_BODY_HTML set, not PR_RTF_COMPRESSED. This is fine when we initially render the message, as well as when we re-render for the reply. But when we render for the forward, we go through a different code path that hinges on getting PR_STORE_SUPPORT_MASK from the store in which the message lives. But MSG files don't live in a message store. So we don't get the prop, and the code path fails to render the body. Along the way, it also clears some bits that were allowing the reply case to work, so it now fails.
MSG files saved from Outlook didn't exhibit the problem - they had PR_RTF_COMPRESSED set in them instead of PR_BODY_HTML. That sends us through yet another code path gets much more testing and doesn't have these problems. And this is the key to the workaround: When using MIMEToMAPI to generate MSG files, always include the CCSF_USE_RTF flag. This will write the body into the PR_RTF_COMPRESSED property (even if it's HTML), avoiding the problem.
There's a bunch of us here that work in developer support for the Messaging APIs that actively blog. We've been kicking around the idea of putting together a team blog, but no one wanted to give up our own blogs. So we've come up with what I think is a good compromise. Most of us use blogs.msdn.com, which has a tags url allowing you to search for a tag across all blogs. To take advantage of this, we've tagged all of our posts with the tag DevMsgTeam. Now all of our post will show up together here:
With the corresponding RSS feed:
So there - now we've got a "team" blog. Enjoy! :)
One of my customers reported that using the MAPI download, they were unable to get a referral from Exchange 2007, even after following the instructions in Jason Johnston's article. The same code worked if they were targeting an Exchange 2003 machine, and Outlook's MAPI had no problems getting a referral from Exchange 2007.
A little bit about how we connect to the DC Exchange's MAPI (this description does NOT apply to Outlook's MAPI, which has different logic, and leaves out a few details not relevant to the discussion, such as how we react when offline):
We're focused on the referral step. The referral request is a Remote Procedure Call (RPC), so we have to set up for the RPC, select one of the available RPC bindings, set our authentication mechanism, and finally make the call. Given default settings, this means we'll be using the default authentication mechanism for RPC, RPC_C_AUTHN_WINNT. This is where we run in to trouble.
During the development of Exchange 2007, a few of the RPC interfaces were moved around. This created the need to consolidate how authentication was handled among the various interfaces. RPC_C_AUTHN_WINNT was cut as an authentication mechanism for the RPC interface which handles referrals, leaving RPC_C_AUTHN_GSS_NEGOTIATE as the preferred authentication mechanism. For the most part, this change had little effect. Outlook did not use RPC_C_AUTHN_WINNT as an authentication mechanism for the referral RPC, and since a failure to get a referral defaults to binding to the Exchange server, most clients didn't see a noticeable impact.
Given all the settings we read in, including the tantalizingly named PR_PROFILE_AUTH_PACKAGE, I wondered if there was any way we could work around this and get Exchange's MAPI to ask for a referral. Investigation of our source confirmed that PR_PROFILE_AUTH_PACKAGE did take an RPC authentication mechanism constant as it's value, so we could set it to RPC_C_AUTHN_GSS_NEGOTIATE (this article discusses this as well).Testing showed that didn't work though. The address book code was convinced it didn't need special authentication, so it wouldn't set the authentication mechanism I had specified.
More digging led to PR_PROFILE_CONNECT_FLAGS. If the CONNECT_NO_RPC_ENCRYPTION flag was set in this property, we'd assume we didn't need special authentication. So I tried removing this flag. Of course, this didn't work either. In fact, although I could remove the CONNECT_NO_RPC_ENCRYPTION flag, every time I tried to connect, it got set back again!
Even more digging. Basically, the if EDK_PROFILEUISTATE_ENCRYPTNETWORK flag wasn't set in PR_PROFILE_UI_STATE, we'd add CONNECT_NO_RPC_ENCRYPTION back to PR_PROFILE_CONNECT_FLAGS. Guess what? Setting the EDK_PROFILEUISTATE_ENCRYPTNETWORK flag didn't work either! But I was getting much closer: the error changed.
Previously, the RPC call had been failing with RPC_S_SERVER_UNAVAILABLE. This was because the authentication mechanism was valid, but the RPC interface we were trying to call to hadn't registered for that authentication mechanism. After I made all my settings, when we called RpcBindingSetAuthInfo we got RPC_S_UNKNOWN_AUTHN_SERVICE back. I had been testing everything locally on my Exchange 2007 server, so all RPC calls to the server used local RPC. Since RPC_C_AUTHN_GSS_NEGOTIATE isn't a valid authentication mechanism for local RPC, the RPC layer wouldn't let us use it. This was excellent news. It meant I had succeeded in forcing Exchange's MAPI to attempt a different authentication method!
I knew the customer always ran their MAPI code remotely anyway, so I tested my settings from a MAPI client on a different machine. Whereas without my settings we were always binding directly to the Exchange server for address book lookups, with the new settings, we asked for and got a referral, then bound to the GC!
Here's a summary of the settings you'll want to make on your MAPI profiles if you want to get GC referral and reconnect working against Exchange 2007. These settings will also work when connecting to Exchange 2003, though only the properties from Jason's article are strictly necessary:
In the MUIDEMSAB profile section (dca740c8c042101ab4b908002b2fe182):
In the global profile section (13DBB0C8AA05101A9BB000AA002FC45A):
I tested all of these settings using MFCMAPI, following the outline of the steps I gave here.
BTW - Global Catalog servers still lie on shutdown, so you'll also want to enable the EMSAB_UserAuth_Credentials key if that's a concern. That code was incorporated into the MAPI Download a long time ago.
The latest MAPI download has an interesting fix in it. Prior to this fix, if you used Exchange's MAPI to connect to Exchange 2007 running on Windows Server 2008 you might crash when you release your message store. If Exchange was running on Windows Server 2003, the same code ran fine. At first, I didn't really believe the version of the OS on the server could trigger a crash on the client, but he had dumps and repro steps, so we debugged it to see what was going on.
Nothing was wrong with his code - we were able to build a simple repro that did nothing more than logon, open the message store, open a folder then release everything. We found some tweaks they could make in their code to avoid the crash, but nothing they were doing was wrong - we even found that MFCMAPI could be walked through to the point of crashing.
The dump of the crash showed we were cleaning up a thread that handled notifications. When we ran the code against an Exchange 2007 server running on Windows 2003, this thread didn't get cleaned up. In fact, it never got created! A bit of debugging back showed the point where we diverged. In both, we tried to register for push notifications with Exchange (these are MAPI's typical UDP based notifications). The Windows Server 2003 based machine succeeded in registering the push notification, but the Windows Server 2008 based machine returned MAPI_E_NO_SUPPORT. This sent us down a little used code path in Exchange's implementation of MAPI. It spun up a timer thread and began polling for notifications. When it tried to tear down this thread, released an object that had been created on another thread. This object had initialized COM, so it tried to uninitialize it when it's destroyed. Since the COM was never initialized on the timer thread, we crashed.
The fix, of course, is to ensure that the object that uses COM is created and destroyed on the same thread. That's the fix we put into last months MAPI download - so if you've been getting unusual crashes while shutting down MAPI clients connected to Exchange 2007 servers on Windows 2008, you'll want to grab this update. A KB article documenting the fix is in the works - I'll link it when it's ready. KB 951992 documents the fix.
Now - you may be wondering - what was happening on the server side? This thread in the newsgroups explains it. EnumProtocols is broken in both Windows 2008 and Vista. It's been replaced by WSAEnumProtocols, which is easy enough to drop in, but of course, you'll need to recompile. We've got a fix for Exchange 2007 in the works that replaces it's call of EnumProtocols with a call to WSAEnumProtocols. If you need it now, you can open a support case and ask for an interim update (ask for KB 951251). Else, it's scheduled to be in Update Rollup 4 for Exchange Server 2007 Service Pack 1 (not the next rollup, but the one after that).
[This is now documented here: http://msdn.microsoft.com/en-us/library/ff976789.aspx]
We've decided to document another function in the Account Management API, DisplayAccountList. This function allows you to display the Account Settings dialog:
and Add New E-Mail Account property sheet:
DisplayAccountList hangs off of IOlkAccountManager interface, occupying the second slot in the v-table, like so:
interface IOlkAccountManager : IOlkErrorUnknown
//Init Initializes the account manager for use.
virtual STDMETHODIMP Init(IOlkAccountHelper* pAcctHelper, DWORD dwFlags);
//DisplayAccountList Displays the account list wizard
virtual STDMETHODIMP DisplayAccountList(
LPCWSTR lpwszReserved, // Not used
DWORD dwReserved, // Not used
const CLSID * pclsidReserved1, // Not used
const CLSID * pclsidReserved2); // Not used
I'm working on a little sample to demonstrate the Account Manager API that I hope to post soon. It'll have an updated header. In the meantime, here's my attempt at MSDN style documentation for the function:
Initializes the account manager for use.
HRESULT IOlkAccountManager::DisplayAccountList (
const CLSID * pclsidReserved1,
const CLSID * pclsidReserved2
The client calls IOlkAccountManager::DisplayAccountList to display either the Account Settings dialog or the Add New E-mail property sheet. The parameters dwReserved, pclsidReserved1 and pclsidReserved2 are not used at this time and MUST be NULL. The parameter lpwszReserved is not used and SHOULD be NULL.
#define E_ACCT_UI_BUSY 0x800C8102
#define ACCTUI_NO_WARNING 0x0100
#define ACCTUI_SHOW_DATA_TAB 0x0200
#define ACCTUI_SHOW_ACCTWIZARD 0x0400
BTW - Hey look! Pictures! Woo hoo!