We had a customer recently who was asking how to tell a PST had been configured as a Sharepoint PST, so they could exclude it from some processing they were doing. After some digging, I found the property that Outlook itself uses to determine a PST is a Sharepoint PST, and development gave me permission to document it:
#define PR_ASSOCIATED_SHARING_PROVIDER PROP_TAG(PT_CLSID, 0x0EA0)
To check if a PST is a Sharepoint PST, mount the PST using OpenMsgStore, then call GetProps on the message store object requesting this property. If it exists, you can assume the PST has been configured for Sharepoint. If it doesn’t exist, the PST has not been configured as a Sharepoint PST.
The September 2009 Release (build 6.0.0.1015) is live: http://mfcmapi.codeplex.com.
The July 2009 release was downloaded over 13 thousand times, with nearly 1700 of them being the 64 bit build. This was the most popular release yet – retiring MAPI Editor drove a lot of traffic over to codeplex.
I did a lot of work on the property and hex editors this time around. The property editor should be much better at editing large and complex streams you’ll find in PR_BODY or PR_RTF_COMPRESSED. And the Hex Editor is no longer modal! Now maybe Rick will stop bugging me about it.
Here's a change list - see the Issue Tracker on Codeplex for more details, or look at the code:
Enjoy.
Bunches of people have contacted me asking if the MAPI download works with Exchange 2010. My usual response has been that I know it works, but you have to tweak the profile. I didn’t know the specific tweaks ‘cause I hadn’t looked in to it.
Dave Vespa just blogged those tweaks. Note that they’re very similar to the modifications we use with Exchange 2007 to get referral working. Also note that the profile Dave builds is not referral enabled, but this doesn’t matter any more. With Exchange 2010, MAPI always talks to the Client Access Server for both mailbox and directory. The dreaded DSProxy that we were trying to avoid in 2007 and earlier has been replaced by the Address Book Service, which is pretty much what DSProxy should have been.
Enjoy!
[This is now documented here: http://msdn.microsoft.com/en-us/library/gg318092.aspx ]
Let’s take a look at the function OpenStreamOnFile, which is exported by MAPI. Suppose you want to use this function to open a stream on a file that has a Unicode file name. As has been noted before, this doesn’t work. Why is this? According to the documentation, and according to the header, maputil.h, this function takes two parameters, lpszFileName and lpszPrefix, which are of type LPCTSTR. However, it is impossible for an exported function to take a parameter of this type. Why? Because LPCTSTR is a macro that compiles to either LPCSTR or LPCWSTR depending on whether Unicode was defined in the project. But MAPI’s the same no matter how you compiled your project, so the export won’t change.
In truth, OpenStreamOnFile should have been declared as taking parameters of type LPCSTR. We’re working on an update to the MSDN and to the MAPI Headers to fix that. We’ll also be documenting a new function, which you can go ahead and use to open files with Unicode names: OpenStreamOnFileW. This is the Unicode version of OpenStreamOnFile which takes Unicode strings. Here’s the signature:
STDMETHODIMP OpenStreamOnFileW( LPALLOCATEBUFFER lpAllocateBuffer, LPFREEBUFFER lpFreeBuffer, ULONG ulFlags, __in LPCWSTR lpszFileName, __in_opt LPCWSTR lpszPrefix, LPSTREAM FAR * lppStream); typedef HRESULT (STDMETHODCALLTYPE FAR * LPOPENSTREAMONFILEW) ( LPALLOCATEBUFFER lpAllocateBuffer, LPFREEBUFFER lpFreeBuffer, ULONG ulFlags, __in LPCWSTR lpszFileName, __in_opt LPCWSTR lpszPrefix, LPSTREAM FAR * lppStream);
STDMETHODIMP OpenStreamOnFileW(
LPALLOCATEBUFFER lpAllocateBuffer,
LPFREEBUFFER lpFreeBuffer,
ULONG ulFlags,
__in LPCWSTR lpszFileName,
__in_opt LPCWSTR lpszPrefix,
LPSTREAM FAR * lppStream);
typedef HRESULT (STDMETHODCALLTYPE FAR * LPOPENSTREAMONFILEW) (
Other than the change to the strings, the function is identical to OpenStreamOnFile. Officially, we’re only documenting this function for Outlook 2010 and higher, but the function is also there in Outlook 2003 and 2007. The Exchange MAPI Download does not implement OpenStreamOnFileW at all.
The November build of MFCMAPI is being augmented to handle Unicode file names. Part of that rewrite is that MFCMAPI will use OpenStreamOnFileW if it’s available, and fall back to OpenStreamOnFile if it’s not.
[This is now documented here: http://msdn.microsoft.com/en-us/library/ff976794.aspx ]
A while back, Jason posted an Account Management API sample. I’ve threatened promised before that I would post an update to this sample, and I finally got around to it. You can download the updated sample here.
In addition to adding a –W command to call DisplayAccountList and show the Account Settings Wizard, I’ve also added a couple new properties that dev have decided to document:
#define PROP_ACCT_USER_EMAIL_ADDR PROP_TAG(PT_UNICODE, 0x000C)
#define PROP_MAPI_IDENTITY_ENTRYID PROP_TAG(PT_BINARY, 0x2002)
PROP_ACCT_USER_EMAIL_ADDR is simply the e-mail address for the account, and PROP_MAPI_IDENTITY_ENTRYID is the address book entry ID for the account, similar to what you’d expect from QueryIdentity. Neither property is expected on every account. For instance, in one profile here, an Exchange account has PROP_MAPI_IDENTITY_ENTRYID but not PROP_ACCT_USER_EMAIL_ADDR, while for an SMTP/POP3 account the situation is reversed.
Dev also asked me to call out an issue that had tripped some folks up. The function GetIdentity is supposed to return a string and the length of the string. The returned string should be NULL terminated and the length should include this NULL terminator in the count. We’ll be updating the MSDN to be more explicit about this, in addition to adding the two new properties.
Some more information about the updated sample: If you’ve been looking for a header for the Account Management API, you can grab and use AcctMgmt.h from this sample. It should have everything you need. Please let me know if it doesn’t. Also, intrepid explorers may want to look at the –I option I added to the sample. It iterates through every possible property tag and requests it, printing the results if it finds something.