NOTE: This interface is only available for Outlook 2010's MAPI subsystem. It will be eventually ported to Outlook 2013's MAPI subsystem. I will update this blog post when that happens.
[Edit: 1/23/2014 - This new interface did not ship in the December 2013 CU. I was incorrect. I am currently looking into it.]
[Edit: 4/23/2014 - This fix should've released in February]
[Edit: 11/21/2014 - This change was ported to Outlook 2013 in the April 2014 Cumlative Update for Outlook 2013. http://support.microsoft.com/kb/2878323]
When making a connection to an Exchange Server, Outlook's MAPI will use the server configured in the profile for any mailbox access attempt, even if it's a different mailbox on a different server. Additionally, Outlook's MAPI will prefer to use a server that it has connected to in the past over one that it hasn't. Therefore, even if you specify a different mailbox on a different Exchange Server in the call to IExchangeManageStore::CreateStoreEntryID(), Outlook's MAPI will still use the server configured for the profile. This is not normally a problem.
When a MAPI client application attempts to connect to multiple mailboxes using a "hub and spoke" type approach wherein the MAPI application connects to an initial mailbox and then connects to additional mailboxes for some sort of processing, if the mailbox resides on a different server Outlook's MAPI will ignore the specified server in the EntryID and connect to the server configured for the profile (the "home server"). This results in a return code of ecWrongServer (0x478 / 1144) and the MAPI application is redirected to the correct server. Outlook's MAPI recognizes this scenario and redirects to the corrected server. Again , this is not normally a problem.
Enter Exchange 2013 where every mailbox is now given it's own server name. This is called the personalized server name and is a GUID that represents the mailbox's home server. This makes Outlook's MAPI go through the redirect logic for all mailbox connection attempts and causes a small performance hit for each mailbox the MAPI application attempts to connect to. Previously, there was no way to tell Outlook's MAPI to ignore the "home server" and use the server specified in the EntryID. However, as of the December 2013 Cumulative Update for Outlook 2010 there now is.
To do this, a new interface was created to provide the MAPI application a new public API that can produce the Store EntryID needed when calling IMAPISession::OpenMsgStore(). You can use the header defined below and the properties to instruct MAPI to create the Store EntryID that contains a special flag in the EntryID that Outlook's MAPI will know how to parse. When this flag is present, MAPI will prefer the server name contained in the EntryID. When it's not, it will use the conventional logic discussed above.
First, you will need to define the new properties PR_PROFILE_MDB_DN and PR_FORCE_USE_ENTRYID_SERVER
#define PR_PROFILE_MDB_DN PROP_TAG(PT_STRING8, 0x7CFF)
#define PR_FORCE_USE_ENTRYID_SERVER PROP_TAG(PT_BOOLEAN, 0x7CFE)
Next, you will need to include a new header with the following information
/*------------------------------------------------------------------------ * *
"IExchangeManageStoreEx" Interface Declaration
* * Used for store management functions.
#define EXCHANGE_IEXCHANGEMANAGESTOREEX_METHODS(IPURE) \
(THIS_ ULONG cValues, \
LPSPropValue lpPropArray, \
ULONG ulFlags, \
ULONG * lpcbEntryID, \
LPENTRYID * lppEntryID) IPURE;
#define INTERFACE IExchangeManageStoreEx
DEFINE_GUID(IID_IExchangeManageStoreEx, 0x7fe3c629, 0x4d9a, 0x4510, 0xa4, 0x79, 0x56, 0x96, 0x2b, 0x24, 0x6d, 0xc6);
At the call site you will need to pass an array of SPropValues for the following properties
Here is some example code to show you how it could be used.
LPSPropValue lpspv = nullptr;
MAPIAllocateBuffer((sizeof(SPropValue) * 3), (LPVOID*)&lpspv);
ZeroMemory(lpspv, sizeof(SPropValue) * 3);
lpspv.ulPropTag = PR_PROFILE_MAILBOX;
lpspv.Value.lpszA = TargetMailboxDN;
lpspv.ulPropTag = PR_PROFILE_MDB_DN;
lpspv.Value.lpszA = TargetStoreDN;
lpspv.ulPropTag = PR_FORCE_USE_ENTRYID_SERVER;
lpspv.Value.b = true;
hres = m_pMsgPrivStore->QueryInterface(IID_IExchangeManageStoreEx,
if (FAILED(hRes) || pManageStoreEx == nullptr)
// Handle the error
hRes = pManageStoreEx->CreateStoreEntryID2(3,
The “Autodiscover Node” above indicates where in the Autodiscover response for the target mailbox you would find the value for this property.
This EntryID is only supported on the client, specifically Outlook's MAPI.
The EntryID should not be persisted anywhere except in the memory of the application.
If you don’t specify values for all the properties, the returned EntryID will be equal to what you would have received back in a call to IExchangeManageStore::CreateStoreEntryID(),