Detect the version of Exchange Server in an Outlook profile

Applies to: Outlook 2013 | Outlook 2016

This topic includes a code sample in C++ that shows how to use the PR_PROFILE_SERVER_VERSION property and PR_PROFILE_SERVER_FULL_VERSION property to obtain version information of the Microsoft Exchange Server that the active account is connected to.

The GetProfileServiceVersion function in the code sample accepts a profile as an input parameter. Depending on whether the PR_PROFILE_SERVER_VERSION property and the PR_PROFILE_SERVER_FULL_VERSION property exist in the given profile, the function gets each property and returns the appropriate version information as output parameters.

GetProfileServiceVersion first calls the MAPIAdminProfiles function to create a profile administration object. It then uses the profile administration object to call IProfAdmin::AdminServices to obtain a message service administration object. Using the message service administration object, it calls IMsgServiceAdmin::OpenProfileSection to obtain a section of the current profile, and then calls HrGetOneProp to verify if each of the two properties exists in that section of the profile, and if so, sets the version information in the appropriate output parameters.

TZDEFINITION* BinToTZDEFINITION(ULONG cbDef, LPBYTE lpbDef) 
{ 
    if (!lpbDef) return NULL; 
 
    // Update this if parsing code is changed. 
    // This checks the size up to the flag member. 
    if (cbDef < 2*sizeof(BYTE) + 2*sizeof(WORD)) return NULL; 
 
    TZDEFINITION tzDef = {0}; 
    TZRULE* lpRules = NULL; 
    LPBYTE lpPtr = lpbDef; 
    WORD cchKeyName = NULL; 
    WCHAR* szKeyName = NULL; 
    WORD i = 0; 
 
    BYTE bMajorVersion = *((BYTE*)lpPtr); 
    lpPtr += sizeof(BYTE); 
    BYTE bMinorVersion = *((BYTE*)lpPtr); 
    lpPtr += sizeof(BYTE); 
 
    // We only understand TZ_BIN_VERSION_MAJOR 
    if (TZ_BIN_VERSION_MAJOR != bMajorVersion) return NULL; 
 
    // We only understand if >= TZ_BIN_VERSION_MINOR 
    if (TZ_BIN_VERSION_MINOR > bMinorVersion) return NULL; 
 
    lpPtr += sizeof(WORD); 
 
    tzDef.wFlags = *((WORD*)lpPtr); 
    lpPtr += sizeof(WORD); 
 
    if (TZDEFINITION_FLAG_VALID_GUID & tzDef.wFlags) 
    { 
        if (lpbDef + cbDef - lpPtr < sizeof(GUID)) return NULL; 
        tzDef.guidTZID = *((GUID*)lpPtr); 
        lpPtr += sizeof(GUID); 
    } 
 
    if (TZDEFINITION_FLAG_VALID_KEYNAME & tzDef.wFlags) 
    { 
        if (lpbDef + cbDef - lpPtr < sizeof(WORD)) return NULL; 
        cchKeyName = *((WORD*)lpPtr); 
        lpPtr += sizeof(WORD); 
        if (cchKeyName) 
        { 
            if (lpbDef + cbDef - lpPtr < (BYTE)sizeof(WORD)*cchKeyName) return NULL; 
            szKeyName = (WCHAR*)lpPtr; 
            lpPtr += cchKeyName*sizeof(WORD); 
        } 
    } 
 
    if (lpbDef+ cbDef - lpPtr < sizeof(WORD)) return NULL; 
    tzDef.cRules = *((WORD*)lpPtr); 
    lpPtr += sizeof(WORD); 
    if (tzDef.cRules) 
    { 
        lpRules = new TZRULE[tzDef.cRules]; 
        if (!lpRules) return NULL; 
 
        LPBYTE lpNextRule = lpPtr; 
        BOOL bRuleOK = false;