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.