How to programmatically create Offline Address Books in Exchange 2003

In Exchange 2003 and in Exchange 2000, an Offline Address Book is an Active Directory Object that exists in the Configuration namespace of the directory.

Creating an Offline Address Book involves creating an "msExchOAB" class object, under the "CN=Offline Address Lists,CN=Address Lists Container,CN=Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=DomainName,DC=com" object in the directory.
These mandatory attributes of an Offline Address Book object must be set at creation time of the object (before the first "SetInfo" call when you are creating the object):

offlineABContainers - A multivalued distinguished name attribute that stores a list of distinguished names of address lists that should be included in this Offline Address Book.

offlineABServer - A single-valued distinguished name attribute that stores the distinguished name of the server that is responsible for generating this Offline Address Book. The server must be an Exchange 2000 Server.

doOABVersion - A single-valued integer attribute that stores compatibility information of this specific address book with different versions of Exchange. This attribute can be set to either "0" or "1". (Any other value is reserved for future use.) A value of 0 indicates that this address book is not required to be compatible with versions 4.0 and 5.0 of Exchange. A value of 1 indicates that this address book should be compatible with versions 4.0 and 5.0 of Exchange in addition to Exchange Server 5.5, Exchange 2003, and Exchange 2000.

msExchOABFolder - A single-valued octet string attribute that is always set to a variant array with one element that stores a zero-byte array. Its existence is solely due to legacy systems.

offlineABSchedule - A single-valued octet string attribute that is set to a byte array of size 84 that stores the Offline Address Book update interval schedule. Each bit in this structure represents a 15-minute increment, starting from 12 AM Sunday. Each byte in this structure represents a 2-hour increment. Set the bit to "1" to schedule to run at the 15-minute interval.

offlineABStyle - A single-valued integer attribute that indicates more general exchange schedule information as follows:

0 = Never run. This is the same as setting each byte in the schedule blob in offlineABSchedule attribute to "0x00".
1 = Run as specified by the schedule blob stored in the offlineABSchedule attribute.
2 = Run always. This is the same as setting each byte in the schedule blob in offlineABSchedule attribute to "0xFF".

The following optional attributes are required to be set on the Offline Address Book object for the proper functioning of the Offline Address Book. They do not need to be set at creation time (before the first "SetInfo" call when you are creating the object):

legacyExchangeDN - A single-valued distinguished name attribute that stores the legacyExchangeDN of the Exchange Organization that this address list belongs to. Exchange System Manager creates it as " <legacy domain name of the organization> /cn=addrlists/cn=oabs/cn= <legacy container name for the oab> ".

msExchOABDefault - A single-valued Boolean attribute that stores a value of either "True" or "False". If set to True, it indicates that this is the default Offline Address Book for any mailbox store if not explicitly specified for that store. Only one Offline Address Book should have this value set to True.

systemFlags - A single-valued integer attribute that stores system information regarding the directory object. Although this is an optional attribute, it must be set at creation time as well. This attribute is set by passing a value that is defined by the ADS_SYSTEMFLAG_ENUM enumeration, which is documented at:

https://msdn.microsoft.com/library/default.asp?url=/library/en-us/netdir/adsi/ads_systemflag_enum.asp (https://msdn.microsoft.com/library/default.asp?url=/library/en-us/netdir/adsi/ads\_systemflag\_enum.asp)

siteFolderGUID - A single-valued octet string attribute that is set to a random unique globally unique identifier (GUID) value for the Offline Address Book.

siteFolderServer - A single-valued distinguished name attribute that stores the distinguished name of the public folder store where you want the Offline Address Book to exist. The public folder store should be on the same server as offLineABServer to avoid network traffic.

msExchPurportedSearcyUIArray - A multivalued attribute that stores the parameters necessary to rebuild the Exchange System Manager's Offline Address Book query filter dialog for this Offline Address Book. This attribute does not have to be set. If it does not have a value set, then the Modify button on the Offline Address Book's properties, when viewed through Exchange System Manager (ESM), would be disabled. Modifying this attribute is not supported and there is no documentation on how to customize this property. The best way to customize it programmatically is to actually create an Offline Address Book by using a similar query filter from Exchange System Manager and coping the values of this attribute and pasting them into your code to make a new Offline Address Book that you are creating programmatically.

 

Sample Code

The following is Microsoft Visual Basic Sample code that creates an Offline Address Book. This requires that the "Active DS Type Library" be included in the Visual Basic References for this project. The minimum requirements to run this code are:

• This code should be run from a Windows Server 2003 client that has Exchange 2003 Administrative Tools installed if you are targeting an Exchange 2003 or an Exchange 2000 server. If you are targeting an Exchange 2000 server, you could also use a Windows 2000 client that has Exchange 2000 Administrative Tools installed. The CDOEXM version that is included in Exchange 2003 must be used when you access Exchange 2003. The Exchange 2003 CDOEXM can also be used to access Exchange 2000. The CDOEXM library that is included in Exchange 2000 is not supported for accessing Exchange 2003.

• This code should be run under the context of a user who has administrative privileges over the domain that the Exchange 2003 or Exchange 2000 server belongs to where you plan to create the Offline Address Book.

Steps to Create the Visual Basic Project

1. Open Visual Basic.

2. Create a new "Standard EXE" project.

3. From the Project menu, click References and add Active DS Type Library.

4. Insert the following code in the Code view of the form:

 Private Declare Function CoCreateGuid Lib "OLE32.DLL" (pGuid As Byte) As Long

Private Sub Form_Load()
Dim tSchedule(0 To 83) As Byte
Dim tGUID(0 To 15) As Byte
Dim lTemp(0) As Byte
Dim byteArray(0) As Variant

Dim sOrgName, sContainerDN, sOABName, sExchServer, sLegacyExchangeDN, sPublicFolder, sDescription
Dim iOABStyle, idoOABVersion
Dim sSystemFlags
Dim bOABDefault

' Get the configuration name space
Set oRootDSE = GetObject("LDAP://RootDSE")
strConfigNC = oRootDSE.Get("configurationNamingContext")
Set oRootDSE = Nothing

' You MUST modify these values based on your environment
sOrgName = "MyOrganization"
sServerName = "MyExchangeServer"
sContainerDN = "CN=Offline Address Lists,CN=Address Lists Container,CN=" & sOrgName & ",CN=Microsoft Exchange,CN=Services," & strConfigNC
sOABName = "NewOAB"
sOABContainers = Array( _ 
"CN=All Users,CN=All Address Lists,CN=Address Lists Container,CN=" & sOrgName & ",CN=Microsoft Exchange,CN=Services," & strConfigNC, _ 
"CN=Default Global Address List,CN=All Global Address Lists,CN=Address Lists Container,CN=" & sOrgName & ",CN=Microsoft Exchange,CN=Services," & strConfigNC _ 
)
sExchServer = "CN=" & sServerName & ",CN=Servers,CN=First Administrative Group,CN=Administrative Groups,CN=" & sOrgName & ",CN=Microsoft Exchange,CN=Services," & strConfigNC
idoOABVersion = 0
iOABStyle = 2
sLegacyExchangeDN = "/o=" & sOrgName & "/cn=addrlists/cn=oabs/cn=" & sOABName
bOABDefault = False
sSystemFlags = "1610612736"
sPublicFolder = "CN=Public Folder Store (" & sServerName & "),CN=First Storage Group,CN=InformationStore,CN=" & sServerName & ",CN=Servers,CN=First Administrative Group,CN=Administrative Groups,CN=" & sOrgName & ",CN=Microsoft Exchange,CN=Services," & strConfigNC
sDescription = "This is a test"
vSchedule = tSchedule


' Build Legacy Exchange distinguished name
sLegacyExchangeDN = "/o=" & sOrgName & "/cn=addrlists/cn=oabs/cn=" & sOABName

' Generate a GUID for each OAB that is created
hr = CoCreateGuid(tGUID(0))
If hr <> 0 Then
   Debug.Print "Error " & Err.Number & " calling CoCreateGUID"
   End
End If
vGUID = tGUID
   
' Create the variant array of byte arrays set to 0x00 for msExchOABFolder

lTemp(0) = CByte(0)
byteArray(0) = lTemp

'Creating the actual Offline Address Book

'Binding to the container based on the DN passed (the container where all the offline address books exist
Set oContainer = GetObject("LDAP://" & sContainerDN)

Set oNewOAB = oContainer.Create("msExchOAB", "cn=" & sOABName)

'The following attributes are required for the object to be created in the active directory

'Its the list of Address Lists that should be included in this OAB
oNewOAB.PutEx ADS_PROPERTY_UPDATE, "offlineABContainers", sOABContainers

'Need to research this further, can we have exchange 5.5 servers in it, do they have to have and ADC?
'DN of the Exchange Server responsible for generating this OAB
oNewOAB.Put "offlineABServer", sExchServer

'doOABVersion is a mandatory attribute that can be set to:
' 0 = if compatibility with 4.0 and 5.0 is not required;
' 1 = if the OAB should be compatible with 4.0 and 5.0;
' all other values are reserved for future use.
' defaults to 0 when OAB create from Exchange System Manager
oNewOAB.Put "doOABVersion", idoOABVersion

'A must-contain attribute in the schema due to legacy versions but it is no longer in use.
'Sets it to a zeroed  byte.
oNewOAB.PutEx ADS_PROPERTY_UPDATE, "msExchOABFolder", byteArray

'A 84 byte array that stores the Exchange schedule
'Each bit in this structure represents a 15 minutes increment starting from 12am Sunday
'Each byte in this structure represents 2 hour increments
'Set the bit to 1 to indicate the schedule to run at this 15 minute interval
oNewOAB.Put "offlineABSchedule", vSchedule
'Indicates a more general exchange schedule and based on its value the exchange schedule is set to
'run never, always or based on the custom schedule stored in offlineABSchedule
'0 = Never. This is the same as having the schedule blob full of 0x00.
'1 = Run as specified by the offLineABSchedule blob
'2 = Run Always. This is the same as having the schedule blob full of 0xFF.
oNewOAB.Put "offlineABStyle", iOABStyle

'The following need not be set for the object creation in the AD, but they do need to be set
'for proper working of the Offline Address Book

'It should be derived from the legacyExchangeDN of the organization.
'ESM creates it as "<legacyDN of the Org>/cn=addrlists/cn=oabs/cn=<legacy CN for the oab>".
oNewOAB.Put "legacyExchangeDN", sLegacyExchangeDN

'When a new Mailbox Store is created, the OAB that contains msExchOABDefault set to TRUE
'is automatically selected and users on that store will use that OAB.
'Only one OAB should have this attribute set to TRUE. When changing it, remove it from all the other OABs.
oNewOAB.Put "msExchOABDefault", bOABDefault

'This can only be set at creation time
'This attribute is set by passing a value that is defined by the ADS_SYSTEMFLAG_ENUM enumeration documented at -
'https://msdn.microsoft.com/library/default.asp?url=/library/en-us/netdir/adsi/ads_systemflag_enum.asp
'In this sample I am passing in the 1610612736 (0x60000000) which is
'0x60000000 = 0x40000000 or 0x20000000 (ADS_SYSTEMFLAG_CONFIG_ALLOW_RENAME + ADS_SYSTEMFLAG_CONFIG_ALLOW_MOVE)
oNewOAB.Put "systemFlags", sSystemFlags

'set it to a random GUID for the OAB.
oNewOAB.Put "siteFolderGUID", vGUID

'DN of the Public Folder Store where the OAB should be stored.
'It should be in the same server of offLineABServer to avoid network traffic.
oNewOAB.Put "siteFolderServer", sPublicFolder

'The following properties are optional and do not have to be set.

'This is basically what you see under the Details tab from Exchange System Manager
'when you create a new OAB
If (sDescription <> "") Then
    oNewOAB.Put "adminDescription", sDescription
End If

' Write object to the directory
oNewOAB.SetInfo

' Clean Up
Set oNewOAB = Nothing
Set oContainer = Nothing
End Sub
 Dave