Detecting a Password Protected PST

If you’ve been working with PSTs for a while, you’re probably familiar with the properties PR_PST_PW_SZ_OLD and PR_PST_PW_SZ_NEW, given in mspst.h, which are used to access password protected PSTs and also to change the password. I had a customer recently who needed to know if a PST they had was password protected in the first place, so they could process them appropriately.

We did some research and found that if you added such a PST to a profile, then called OpenMsgStore on it with the MDB_NO_DIALOG flag set, you would get MAPI_E_FAILONEPROVIDER, which is pretty much the most generic error you can get in MAPI. Since we knew there were other reasons you could get this error, the question was whether we could distinguish this particular case. Most interfaces in MAPI support the function GetLastError. I set up a bit of code to try calling OpenMsgStore on a password protected PST, and took a look at the result of GetLastError. Here’s what I saw in the MAPIERROR structure:

ulVersion = 0x00000000
lpszError = 0x00000000
lpszComponent = Personal Folders
ulLowLevelError = 0x00000000
ulContext = 0x30060401

Note the value for ulContext. It turns out it’s a unique constant the PST provider will set when the PST was password protected and we could not display a dialog to prompt for credentials. Development has given permission to document this context, as well as one other:

MAPI Error Code ulContext Meaning
MAPI_E_FAILONEPROVIDER 0x30060401 The password from PR_PST_PW_SZ_OLD failed with Access Denied, and MAPI_NO_DIALOG was passed.
MAPI_E_LOGON_FAILED    0x30060402 The credentials attempted failed for some other reason.

If the credentials attempted failed with Access Denied and MAPI_NO_DIALOG wasn’t passed, the PST provider will attempt to prompt for credentials. The other context (0x30060402) should be rare, only occurring in out of memory or other unusual circumstances.

It turns out the PST provider is very good about setting errors with error contexts. Usually the top level MAPI error is sufficient to explain why a call failed, but if there are other ambiguous scenarios involving the PST provider, check the ulContext from GetLastError. If it’s unique, let me know the scenario and the context you got, and I’ll see if I can document it.

Comments (4)

  1. Is there a way to find out if a particular PST file is considered to be corrupted?

  2. Stephen Griffin says:

    Dmitry – probably. Let me know what contexts you’re seeing and in what scenarios.

  3. I would have to re-run my code under th debugger to see exactly which MAPI method does that, but opening a large PST store can take a long time while the PST provider checks the integrity of the PST file.

    Given a PST file, can I open it in such a way that I can skip the integrity check by forcing the PST provider to return an error or force the PST provider to perform the check first (even if that takes a long time) and only then return from the call?

  4. I just wanted to let you know about a problem we’ve found with the February update for Outlook 2007 .