Microsoft KB Archive/297393

= How To Programmatically Move an Exchange Mailbox Using CDOEXM in Visual C++ =

Article ID: 297393

Article Last Modified on 10/25/2007

-

APPLIES TO


 * Microsoft Windows 2000 Service Pack 1
 * Microsoft Windows 2000 Service Pack 2
 * Microsoft Windows 2000 Advanced Server
 * Microsoft Windows 2000 Advanced Server
 * Microsoft Windows Server 2003, Standard Edition (32-bit x86)
 * Microsoft Windows Server 2003, Enterprise Edition
 * Microsoft Exchange 2000 Enterprise Server
 * Microsoft Exchange 2000 Server Standard Edition
 * Microsoft Exchange Server 2003 Enterprise Edition
 * Microsoft Exchange Server 2003 Standard Edition
 * Microsoft Active Directory Service Interfaces 2.5
 * Microsoft Collaboration Data Objects for Exchange Management 1.1
 * Collaboration Data Objects for Exchange 2000
 * Microsoft Active Directory Service Interfaces 2.5

-



This article was previously published under Q297393



SUMMARY
This article provides two samples that demonstrate how to move a mailbox in Exchange from its current mailbox store to another mailbox store programmatically by using Microsoft Visual C++. The first sample uses Active Directory Services Interface (ADSI) and Collaboration Data Objects for Exchange Management (CDOEXM). The second sample uses Collaboration Data Objects for Exchange 2000 (CDO) and CDOEXM.



Background
In Exchange, moving a mailbox entails:
 * Modifying attributes on the user object in Active Directory that specify the user's mailbox store.
 * Moving the physical mailbox of the user to the new store location.

The CDOEXM::IMailboxStore interface is an interface that enables programmatically performing mailbox-related tasks like creating mailboxes for users, deleting mailboxes for users, and moving users' mailboxes across mailbox stores in a Windows 2000 domain or a Windows 2003 domain. The CDOEXM interfaces can be derived from either CDO interfaces or ADSI interfaces. For additional information about the advantages and disadvantages of using each of the following approaches, click the following article number to view the article in the Microsoft Knowledge Base:

297390 INFO: Comparing Use of ADSI and CDO to Access CDOEXM Recipient-Related Methods

The IMailboxStore method, MoveMailbox, performs two sets of tasks as follows:
 * Directory-related tasks on the user object
 * Updates the homeMTA attribute.
 * Updates the store's distinguished name on the homeMDB attribute.
 * Deletes the target e-mail address for the user object stored in the targetAddress attribute. This will be updated by the Recipient Update Service (RUS) when it runs against this user.
 * Store-related tasks
 * Copies the user's mailbox from the current store on an Exchange server to a new store location specified on the same or another Exchange server.
 * Transfers the messages and content from the user's old mailbox to the user's new mailbox.
 * Marks the user's old mailbox to be deleted. The actual mailbox is actually &quot;tombstoned&quot; (marked as deleted) once the Cleanup Agent is run against the store. This is indicated by a red cross in front of the mailbox when viewed from the Exchange System Manager.

If the user object has been set to be mailbox-enabled but the RUS hasn't run against the user object yet, then MoveMailbox forces the RUS to run against this user. Also, if this user's physical mailbox is still nonexistent in the information store (if this mailbox has not been accessed yet), this mailbox is created in the new mailbox store after MoveMailbox is called on the user.

Although the CDOEXM interfaces can be derived either from ADSI or CDO interfaces, they cannot be directly used to bind to an object in the Active Directory. The CDOEXM interfaces are available in Cdoexm.dll, which is installed along with the Microsoft Exchange System Management Tools. Do not manually register this file into the registry. You can install the Exchange System Management component by running Exchange Server Setup from the Exchange Server CD.

Using ADSI
This sample requires Adsiid.lib and Activeds.lib for the ADSI interfaces, which can be found under the Libs folder in a Platform SDK installation. The Platform SDK can be downloaded from the following Microsoft Web site:

http://www.microsoft.com/msdownload/platformsdk/setuplauncher.htm

This sample, in addition to the ADSI libraries, requires Cdoexm.dll, which is installed along with the Microsoft Exchange System Management Tools. Therefore, it must be run on a Windows 2000 Server, a Windows 2000 Advanced Server member server, or a Windows Server 2003 server, in the same domain as the Exchange server, that has at least the MS Exchange System Management Tools component installed.

To build this sample, include the Adsiid.lib and Activeds.lib libraries in the Object/Library modules textbox, which is accessible from the Project menu by pointing to Settings and then clicking Link.

Sample Code
//Importing the libraries required to use CDOEXM //TODO: change the file path below to point to the file int main(void) { // Declare variables HRESULT hr; LPWSTR strUserLDAPPath; LPWSTR strMailboxStore; IADsUser *pUser = NULL; IMailboxStore *pMailbox = NULL; //TODO: change the string below to the LDAP path for the user to //perform the MoveMailbox task on strUserLDAPPath = L&quot;LDAP://domain/CN=user1,OU=MyOU,DC=domain,DC=com&quot;; //TODO: Change the string below to the Distinguished Name or LDAP path // for the new mailbox store to move the user's mailbox to strMailboxStore = L&quot;CN=2nd Mailbox Store,CN=First Storage Group,CN=InformationStore,CN=EX2K,CN=Servers,CN=SITE1,CN=Administrative Groups,CN=Microsoft,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=dom,DC=com&quot;; //Initialize COM hr = CoInitialize(NULL); if (FAILED(hr)) { wprintf(L&quot;Failed to CoInitialize: 0x%x\n&quot;, hr); return hr; } //Bind to the existing mailbox enabled user using ADSI hr = ADsGetObject(strUserLDAPPath, IID_IADsUser, (void**)&pUser); if (FAILED(hr)) { wprintf(L&quot;Failed to get IADsUser: 0x%x\n&quot;, hr); pUser->Release; CoUninitialize; return hr; } //Query for the IMailboxStore Interface using the IADsUser object hr = pUser->QueryInterface(__uuidof(IMailboxStore), (void**)&pMailbox); if (!SUCCEEDED(hr)) { wprintf(L&quot;QueryInterface of IMailboxStore failed!\n&quot;); pUser->Release; pMailbox->Release; CoUninitialize; return hr; } //Move the Mailbox hr = pMailbox->MoveMailbox(strMailboxStore); if (!SUCCEEDED(hr)) { wprintf(L&quot;MoveMailbox failed!\n&quot;); pUser->Release; pMailbox->Release; CoUninitialize; return hr; } //Apply changes made to the cache back onto the user object in the Active Directory hr = pUser->SetInfo; if (!SUCCEEDED(hr)) { wprintf(L&quot;SetInfo failed!\n&quot;); pUser->Release; pMailbox->Release; CoUninitialize; return hr; } //Cleanup and uninitialize COM pUser->Release; pMailbox->Release; pUser = NULL; pMailbox = NULL; CoUninitialize; return 0; }
 * 1) include &quot;stdio.h&quot;
 * 2) include &quot;activeds.h&quot;
 * 1) import  no_namespace raw_interfaces_only exclude(&quot;IDataSource2&quot;)

Using CDO
This sample requires Cdoex.dll for the IPerson interface on the CDO.Person object. This .dll file is available only on an Exchange server. It also requires Cdoexm.dll for the IMailboxStore interface on the CDOEXM object. This .dll is available on Exchange servers as well. Therefore, this code can only be run from an Exchange server. Do not manually attempt to register either of these files into the registry to work around this limitation.

Sample Code
// Importing the libraries required to use CDOEXM //TODO: change the path to the files location int main(void) { // Declare variables HRESULT hr; LPWSTR strUserLDAPPath; LPWSTR strMailboxStore; IPerson* pUser = NULL; IDataSource* pDataSource = NULL; IMailboxStore *pMailbox = NULL; //TODO: Change this string to the LDAP path for the user to perform //the MoveMailbox task on strUserLDAPPath = L&quot;LDAP://domain/CN=user2,OU=MyOU,DC=domain,DC=com&quot;; //TODO: Change this string to the Distinguished Name or LDAP path for // the new mailbox store to move the user's mailbox to strMailboxStore = L&quot;CN=2nd Mailbox Store,CN=First Storage Group,CN=InformationStore,CN=EX2K,CN=Servers,CN=SITE1,CN=Administrative Groups,CN=Microsoft,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=domain,DC=com&quot;; //Initialize COM hr = CoInitialize(NULL); if (FAILED(hr)) { wprintf(L&quot;Failed to CoInitialize: 0x%x\n&quot;, hr); return hr; } //Create Instance of IPerson interface hr = CoCreateInstance( __uuidof(Person),                     NULL,                      CLSCTX_INPROC_SERVER,                      __uuidof(IPerson),                     (void**) &pUser                     ); if (FAILED(hr)) { wprintf(L&quot;Failed to Create Instance of IPerson object: 0x%x\n&quot;, hr); pUser->Release; pUser = NULL; CoUninitialize; return hr; } hr = pUser->get_DataSource(&pDataSource); if (FAILED(hr)) { wprintf(L&quot;Failed to get_DataSource: 0x%x\n&quot;, hr); pUser->Release; pDataSource->Release; pUser = NULL; pDataSource = NULL; CoUninitialize; return hr; } //Bind to the existing mailbox enabled user hr = pDataSource->Open(strUserLDAPPath,      NULL,       adModeReadWrite,       adFailIfNotExists,       adOpenSource,       L&quot;&quot;,       L&quot;&quot;); if (FAILED(hr)) { wprintf(L&quot;Failed to bind to LDAP path: 0x%x\n&quot;, hr); pUser->Release; pDataSource->Release; pUser = NULL; pDataSource = NULL; CoUninitialize; return hr; } //Query for the IMailboxStore Interface using the IADsUser object hr = pUser->QueryInterface(__uuidof(IMailboxStore), (void**)&pMailbox); if (!SUCCEEDED(hr)) { wprintf(L&quot;QueryInterface of IMailboxStore failed!\n&quot;); pUser->Release; pDataSource->Release; pMailbox->Release; pUser = NULL; pMailbox = NULL; pDataSource = NULL; CoUninitialize; return hr; } //Move Mailbox hr = pMailbox->MoveMailbox(strMailboxStore); if (!SUCCEEDED(hr)) { wprintf(L&quot;MoveMailbox failed!\n&quot;); pUser->Release; pMailbox->Release; pDataSource->Release; pUser = NULL; pMailbox = NULL; pDataSource = NULL; CoUninitialize; return hr; } //Update changes made by CDOEXM by Saving DataSource hr = pDataSource->Save; if (!SUCCEEDED(hr)) { wprintf(L&quot;Failed to Save DataSource!\n&quot;); pUser->Release; pMailbox->Release; pDataSource->Release; pUser = NULL; pMailbox = NULL; pDataSource = NULL; CoUninitialize; return hr; } CoUninitialize; return 0; }
 * 1) include &quot;stdio.h&quot;
 * 1) import  no_namespace raw_interfaces_only
 * 2) import  no_namespace raw_interfaces_only rename(&quot;Folder&quot;,&quot;CDOEXFolder&quot;)
 * 3) import  no_namespace raw_interfaces_only

