Microsoft KB Archive/261229

{|
 * width="100%"|

HOWTO: Recalculate Exchange Address Book Hierarchy

 * }

Q261229

-

The information in this article applies to:


 * Microsoft Active Directory Service Interfaces, version 2.5
 * Microsoft Exchange Server, version 5.5

-

SUMMARY
After programmatically creating a Microsoft Exchange Recipients container, you must recalculate the address book hierarchy. The Exchange Administrator program uses standard Windows Service Manager calls to send a control code to the directory service. The application programming interface (API) for accessing the Service Control Manager is documented in the Microsoft Developer Network (MSDN) Win32 API documentation. The control code needed by the Exchange Administrator is DS_SERVICE_CONTROL_RECALC_HIERARCHY. The value of this constant is 129.

This article demonstrates how to create a Recipients container and recalculate the address book hierarchy. Failure to recalculate the address book hierarchy will result in the container not being visible in the Exchange Administrator program until the recalculation has occurred. You can force a recalculation to occur by doing a refresh (by pressing F5) in the Exchange Administrator program.

MORE INFORMATION
The following Microsoft Visual Basic and Microsoft Visual C++ samples use Active Directory Services Interface (ADSI) to programmatically make a Recipients container in the Exchange Server directory and the Win32 API to send a control to the Exchange directory service requesting a recalculation of the address book hierarchy.

Visual Basic Sample
'Add a reference to ActiveDS Type library. 'Search for TODO in the following code to set configuration 'information. ' Private Type SERVICE_STATUS dwServiceType As Long dwCurrentState As Long dwControlsAccepted As Long dwWin32ExitCode As Long dwServiceSpecificExitCode As Long dwCheckPoint As Long dwWaitHint As Long End Type

Private Const STANDARD_RIGHTS_REQUIRED = &HF0000 Private Const SC_MANAGER_CONNECT = &H1 Private Const SC_MANAGER_CREATE_SERVICE = &H2 Private Const SC_MANAGER_ENUMERATE_SERVICE = &H4 Private Const SC_MANAGER_LOCK = &H8 Private Const SC_MANAGER_MODIFY_BOOT_CONFIG = &H20 Private Const SC_MANAGER_QUERY_LOCK_STATUS = &H10 Private Const SC_MANAGER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _ SC_MANAGER_CONNECT Or SC_MANAGER_CREATE_SERVICE Or _ SC_MANAGER_ENUMERATE_SERVICE Or SC_MANAGER_LOCK Or _ SC_MANAGER_QUERY_LOCK_STATUS Or SC_MANAGER_MODIFY_BOOT_CONFIG) Private Const SERVICE_USER_DEFINED_CONTROL = &H100

Private Declare Function CloseServiceHandle Lib _ &quot;advapi32.dll&quot; (ByVal hSCObject As Long) As Long Private Declare Function OpenSCManager Lib _ &quot;advapi32.dll&quot; Alias &quot;OpenSCManagerA&quot; (ByVal lpMachineName As String, ByVal lpDatabaseName As _   String, ByVal dwDesiredAccess As Long) As Long Private Declare Function OpenService Lib &quot;advapi32.dll&quot; Alias     &quot;OpenServiceA&quot; (ByVal hSCManager As Long, ByVal lpServiceName As       String, ByVal dwDesiredAccess As Long) As Long Private Declare Function ControlService Lib &quot;advapi32.dll&quot; _ (ByVal hService As Long, ByVal dwControl As Long, lpServiceStatus     As SERVICE_STATUS) As Long

Private Sub Main Dim objExistingCont As IADsContainer Dim objNewCont As IADs Dim sstStatus As SERVICE_STATUS Dim hSCM As Long Dim hService As Long

' Bind to an existing container.

//TODO : Change the ADsPath to reflect your Exchange Organization. Set objExistingCont =      GetObject(&quot;LDAP://MyExchServer/ou=MySite,o=MyOrg&quot;) ' Make a new container

//TODO: Set the new container directory name. Set objNewCont = objExistingCont.Create(&quot;Container&quot;,&quot;cn=MyNewCont&quot;) ' Put the continer-info prop to tell Exchange this is a recipients cont. objNewCont.Put &quot;Container-Info&quot;, &H80000001

//TODO: Change the next line to set the Display name. objNewCont.Put &quot;Admin-Display-Name&quot;, &quot;MyNewCont&quot; objNewCont.SetInfo Set objCont = Nothing Set objNewCR = Nothing

'Now recalculate the address book hierarchy.

//TODO: change first paramater to the name of the Exchange server. hSCM = OpenSCManager(&quot;\\MyExchServer&quot;, vbNullString, SC_MANAGER_ALL_ACCESS) hService = OpenService(hSCM, &quot;MSExchangeDS&quot;, SERVICE_USER_DEFINED_CONTROL) lret = ControlService(hService, 129, sstStatus) lret = CloseServiceHandle(hService) lret = CloseServiceHandle(hSCM) End Sub

Visual C++ Sample
//Link with activeds.lib and adsiid.lib. //Search for TODO in the following code to set configuration //information. //
 * 1) include &quot;activeds.h&quot;
 * 2) include &quot;Windows.h&quot;
 * 3) define DS_SERVICE_CONTROL_RECALC_HIERARCHY 0x081
 * 4) define contType 0x80000001

int main(int argc, char* argv[]) {

HRESULT        hr      =   S_OK; IADsContainer  *pCont; IDispatch      *pDisp  =   NULL; IDispatch      *pDisp2 =   NULL; IADs           *pNewCont; VARIANT        var; LPOLESTR szAttributeToSet = NULL; SC_HANDLE      schSCManager,schService; SERVICE_STATUS ssStatus; //TODO: set this to the name of the Exchange server. LPSTR          pmachine = &quot;\\\\MyExchangeServer&quot;;

// You must initialize COM before calling any ADSI functions or interfaces. CoInitialize(NULL); //TODO : Change the ADsPath to reflect your Exchange Organization. hr = ADsGetObject(L&quot;LDAP://MyExchServer/ou=Mysite,o=MyOrg&quot;, IID_IADsContainer, (void**) &pCont ); if ( !SUCCEEDED(hr) ) {      return 0; } //TODO: Set the new container directory name. hr = pCont->Create( L&quot;container&quot;, L&quot;cn=MyNewContainer&quot;, &pDisp );

// Now Query Interface for IADs. hr = pDisp->QueryInterface( IID_IADs, (void**) &pNewCont); pDisp->Release;

//Add Container-Info property to tell Exchange it is a recipients container.

szAttributeToSet = L&quot;Container-Info&quot;; var.vt = VT_I4; var.lVal = contType; hr = pNewCont->Put(szAttributeToSet,var); VariantClear(&var);

//Add Admin-Display-Name property. szAttributeToSet = L&quot;Admin-Display-Name&quot;; var.vt = VT_BSTR; //TODO: Change the next line to set the Display name var.bstrVal = SysAllocString(L&quot;MyNewContainer&quot;); hr = pNewCont->Put(szAttributeToSet,var); VariantClear(&var);

// Now &quot;commit&quot; the Container Creation. hr = pNewCont -> SetInfo;

pNewCont->Release; pCont->Release; CoUninitialize;

// Open a handle to the SC Manager database. schSCManager = OpenSCManager(    pmachine,                // Exchange server     NULL,                    // ServicesActive database     SC_MANAGER_ALL_ACCESS);  // full access rights if (schSCManager != NULL) {   // Open a handle to the service. schService = OpenService(        schSCManager,       // SCManager database         &quot;MSExchangeDS&quot;,       // name of service         SERVICE_USER_DEFINED_CONTROL); if (schService != NULL) // Send a control value to the service. ControlService(            schService,   // handle of service             DS_SERVICE_CONTROL_RECALC_HIERARCHY,   // control value to send             &ssStatus);  // address of status info }

//cleanup: if (schSCManager) CloseServiceHandle(schSCManager); if (schService) CloseServiceHandle(schService);

return (hr);

}