Parsing ServerVersion: When an Int Is Really 5 Ints

I recently had a case where a customer was asking how to figure out the mailbox version of a given user using Exchange Web Services (EWS). We noticed there is a node returned in the AutoDiscover response message called ServerVersion, but this value seems pretty opaque. Here’s a snippet from the AutoDiscover POX response from my test server:

<Protocol>
  <Type>EXCH</Type>
  <Server>MAILBOXEX7.domain.com</Server>
  <ServerDN>/o=First Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=MAILBOXEX7</ServerDN>
  <ServerVersion>720280B0</ServerVersion>
  <MdbDN>/o=First Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=MAILBOXEX7/cn=Microsoft Private MDB</MdbDN>
  <PublicFolderServer>MAILBOXEX7.domain.com</PublicFolderServer>
  <AD>domainDC.domain.com</AD>
  <ASUrl>https://casserver.domain.com/EWS/Exchange.asmx</ASUrl>
  <EwsUrl>https://casserver.domain.com/EWS/Exchange.asmx</EwsUrl>
  <OOFUrl>https://casserver.domain.com/EWS/Exchange.asmx</OOFUrl>
  <UMUrl>https://casserver.domain.com/UnifiedMessaging/Service.asmx</UMUrl>
  <OABUrl>https://casserver/OAB/4c44408b-66b7-42d9-8247-316fca26961c/</OABUrl>
</Protocol>

The ServerVersion value returned in AutoDiscover is a 32-bit integer value represented in hexidecimal format (720280B0). The integer by itself doesn’t mean anything. It turns out, this integer is really a serialized structure. Here’s how it breaks down:

0x720280B0 (or 1912766640 in decimal) represented in binary is 01110010000000101000000010110000. If we break this binary chunk up into 5 pieces, we’ll see the structure we are after:

0111  001000  000010  1  000000010110000

0111  (7) - The first 4 bits represent a number used for comparison against older version number structures. You can ignore this.

001000 (8) – The next 6 bits represent the major version number.

000010 (2) – The next 6 bits represent the minor version number.

1 (1) – This bit is just a flag that you can ignore.

000000010110000 (176) – The last 15 bits is the build number.

So I can see that my server is running build 08.02.0176.

To parse this value in code is quite easy if you use the binary shift operators. The following sample is in C#, but similar constructs exist in most languages. GetServerVersionIntFromString simply gets the ServerVersion value from the AutoDiscover response body and converts the string value “720280B0” into an unisigned integer using UInt32.Parse

UInt32 intServerVersion = GetServerVersionIntFromString(sb);

uint build = intServerVersion & 0x7FFF; //get bottom 15 bits
uint minor = (intServerVersion >> 16) & 0x3F; //get 6 bits from 16 bits in
uint major = (intServerVersion >> 22) & 0x3F; //gets 6 bits from 22 bits in

I should point out that in Exchange 2010 and above, a new AutoDiscover option is being made available – AutoDiscover SOAP. If you know you will be targeting an Exchange 2010 server, you can use the SOAP AutoDiscover calls which can return you the server major and minor build numbers in a more easily consumable format.

 

<s:Header>
  <a:Action s:mustUnderstand="1">https://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetUserSettingsResponse</a:Action>
  <h:ServerVersionInfo xmlns:h="https://schemas.microsoft.com/exchange/2010/Autodiscover" xmlns:i="https://www.w3.org/2001/XMLSchema-instance">
    <h:MajorVersion>14</h:MajorVersion>
    <h:MinorVersion>0</h:MinorVersion>
    <h:MajorBuildNumber>639</h:MajorBuildNumber>
    <h:MinorBuildNumber>20</h:MinorBuildNumber>
    <h:Version>Exchange2010</h:Version>
  </h:ServerVersionInfo>
</s:Header>