Store Entry ID v2
As I intimated before, Outlook’s MAPI supports a special kind of store entry ID which allows you to encode the full DN for the server and avoid redirects. Here’s the documentation for it.
An Exchange Store Entry ID encodes an Exchange server and mailbox for us in OpenMsgStore. The base version of this format is documented here:
https://msdn.microsoft.com/en-us/library/ee203516(EXCHG.80).aspx
If you follow the format documented there, you will build an internal entry identifier for the Exchange MAPI provider, emsmdb32.dll. This entry ID can be wrapped with WrapStoreEntryID to get an entry ID that you can pass to OpenMsgStore. If you do this, what you generate will be the same as the entry ID generated by CreateStoreEntryID. In Outlook 2003, we introduced support for a v2 entry ID format that builds on the original format. In protocol documentation format, it looks like this:
Store Object EntryIDs
A Store object EntryID identifies a mailbox Store object or a public folder Store object itself, rather than a message or Folder object residing in such a database. It is used in certain property values.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 20 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 30 | 1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Flags | |||||||||||||||||||||||||||||||
ProviderUID | |||||||||||||||||||||||||||||||
... | |||||||||||||||||||||||||||||||
... | |||||||||||||||||||||||||||||||
Version | Flag | DLLFileName | |||||||||||||||||||||||||||||
... | |||||||||||||||||||||||||||||||
... | |||||||||||||||||||||||||||||||
WrappedFlags | |||||||||||||||||||||||||||||||
WrappedProvider UID | |||||||||||||||||||||||||||||||
... | |||||||||||||||||||||||||||||||
... | |||||||||||||||||||||||||||||||
WrappedType | |||||||||||||||||||||||||||||||
ServerShortname (variable) | |||||||||||||||||||||||||||||||
... | |||||||||||||||||||||||||||||||
MailboxDN (variable) | |||||||||||||||||||||||||||||||
... | |||||||||||||||||||||||||||||||
V2 (variable) | |||||||||||||||||||||||||||||||
... |
Flags (4 bytes): MUST be 0x00000000.
ProviderUID (16 bytes): MUST be %x38.A1.BB.10.05.E5.10.1A.A1.BB.08.00.2B.2A.56.C2.
Version (1 byte): MUST be zero.
Flag (1 byte): MUST be zero.
DLLFileName (14 bytes): MUST be set to the following value which represents "emsmdb.dll": %x45.4D.53.4D.44.42.2E.44.4C.4C.00.00.00.00.
WrappedFlags (4 bytes): MUST be 0x00000000.
WrappedProvider UID (16 bytes): MUST be one of the following values:
Store object type |
ProviderUID value |
Mailbox Store object |
%x1B.55.FA.20.AA.66.11.CD.9B.C8.00.AA.00.2F.C4.5A |
Public folder Store object |
%x1C.83.02.10.AA.66.11.CD.9B.C8.00.AA.00.2F.C4.5A |
WrappedType (4 bytes): MUST be %x0C.00.00.00 for a mailbox store, or %x06.00.00.00 for a public store.
ServerShortname (variable): A string of single-byte characters terminated by a single zero byte, indicating the shortname or NetBIOS name of the server.
MailboxDN (optional) (variable): A string of single-byte characters terminated by a single zero byte and representing the X500 DN of the mailbox, as specified in [MS-OXOAB]. This field is present only for mailbox databases.
V2 (optional) (variable): An EntryIDv2 structure giving DN and FQDN for the server.
EntryIDv2 Struct
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 20 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 30 | 1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Magic | |||||||||||||||||||||||||||||||
Size | |||||||||||||||||||||||||||||||
Version | |||||||||||||||||||||||||||||||
OffsetDN | |||||||||||||||||||||||||||||||
OffsetFQDN | |||||||||||||||||||||||||||||||
ServerDN (variable) | |||||||||||||||||||||||||||||||
... | |||||||||||||||||||||||||||||||
ServerFQDN (variable) | |||||||||||||||||||||||||||||||
... | |||||||||||||||||||||||||||||||
ReservedBlock |
Magic (4 bytes): MUST be 0xF32135D8.
Size (4 bytes): An unsigned 32 bit integer giving the total size of the EntryIDv2 structure, including the ServerDN and ServerFQDN.
Version (4 bytes): MUST be 0x00000001.
OffsetDN (4 bytes): The offset in the buffer of the ServerDN. Should be 0x00000000 if ServerDN is not present.
OffsetFQDN (4 bytes): The offset in the buffer of the ServerFQDN. Should be 0x00000000 if ServerFQDN is not present.
ServerDN (optional) (variable): A string of single-byte characters terminated by a single zero byte, indicating the DN of the server.
ServerFQDN (optional) (variable): A string of Unicode characters terminated by two zero bytes, indicating the FQDN of the server.
ReservedBlock (2 bytes): MUST be set to 0x0000.
Remarks
This format is only understood by Outlook’s MAPI. It may cause errors if used with Exchange’s MAPI.
If you are accustomed to building DNs to pass in to CreateStoreEntryID, take care not to append \cn=Microsoft Private MDB to the DN used in the v2 entry ID. That suffix is a hint used by CreateStoreEntryID and is not part of the entry ID format.
If you build an entry ID using the above format, you will need to wrap it using WrapStoreEntryID.
As a shortcut, you can use CreateStoreEntryID to build a v1 entry ID, then append the EntryIDv2 struct. If you build the entry ID in this manner, it will already be wrapped and WrapStoreEntryID will not be necessary.
The ServerDN is an ANSI string, but ServerFQDN is a Unicode string. Be careful not to encode them incorrectly.
For purposes of avoiding redirects, you can set ServerDN and leave out ServerFQDN. This will trigger a single unavoidable redirect the first time the entry ID is used, followed by direct connections on each subsequent use.
Some C++ definitions that may be helpful in implementing this:
#define MDB_STORE_EID_V2_VERSION (0x1)
#define MDB_STORE_EID_V2_MAGIC (0xf32135d8) struct MDB_STORE_EID_V2
{
ULONG ulMagic; // MDB_STORE_EID_V2_MAGIC
ULONG ulSize; // size of this struct plus the size of szServerDN and wszServerFQDN
ULONG ulVersion; // MDB_STORE_EID_V2_VERSION
ULONG ulOffsetDN; // offset past the beginning of the MDB_STORE_EID_V2 struct where szServerDN starts
ULONG ulOffsetFQDN; // offset past the beginning of the MDB_STORE_EID_V2 struct where wszServerFQDN starts
};
If you’re using the above struct, you can compute the ulSize field as follows:
ulSize = sizeof(MDB_STORE_EID_V2) + (lstrlenA(szServerDN)+1)*sizeof(char) + (lstrlenW(wszServerFQDN)+1)*sizeof(WCHAR);
Enjoy!
Update (8/15/2011)
I’ve recently discovered that some Public Folder entry IDs seen in Outlook 2010 do contain a mailbox DN. This interferes with the usual logic for parsing such an entry ID, since there is no definitive indicator whether the data following Server Shortname is a DN or a structure. A slight modification to the algorithm is necessary: If the DWORD following the ServerShortName is MDB_STORE_EID_V2_MAGIC, then there is no DN and we have a v2 structure. If it is anything else, we have a DN following the Server ShortName. There may or may not still be a v2 structure after the DN, which should be parsed in the usual fashion.
Comments
Anonymous
January 20, 2014
When I use the MFCMAPI (with Outlook 2013) to verify the entry ID (PR_ENTRYID) of the 2013 Mailbox/message store, the mailbox DN portion of entry ID reads the mailbox display name followed by some GUID. Also the Server Short Name displays the SMTP Address of the Mailbox store. /o=XYZ/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=03fffffff40c4b1fa53b10ecf323f359-Mohan Kumar We witness the Mailbox Alias Name instead of the Mailbox display name in the mailbox DN, when we are working with exchange 2007 mailbox store. Iam trying to evaluate if it is plausible to identify the owner (Exchange Account) of the message store using the message store entry ID. My intention is to create the MAPI profile for the exchange super user account, that has access to all the mailbox/message store and later get to the message store table and open the message store using Mailbox Alias Name. So I thought of using the message store Entry ID's Mailbox DN that carries the Mailbox Alias Name with it. I wanted to avoid creating profiles dynamically for accessing individual mailbox and instead use the exchange super user profile to access individual mailbox.Anonymous
May 04, 2016
Is the version of the store entry id related to the version of Exchange Server? What is the version of the StoreEntryId for a mailbox on Exchange 2010? What about Exchange 2013 and Office 365 mailboxes?