How to add more Exchange mailboxes to a MAPI profile (171636)



The information in this article applies to:

  • Microsoft Exchange Server 2003 Enterprise Edition
  • Microsoft Exchange Server 2003 Standard Edition
  • Microsoft Exchange 2000 Server
  • Microsoft Exchange Server 5.5
  • Microsoft Extended Messaging Application Programming Interface (MAPI)

This article was previously published under Q171636

IN THIS TASK

SUMMARY

This step-by-step article details the process of adding a mailbox to a MAPI profile. This will allow you to open this additional mailbox with delegate access. The owner of this mailbox must grant you delegate access prior to following this process.

This process is the programmatic equivalent to:
  1. Launching the mail program from the control panel.
  2. Selecting a profile that has the Microsoft Exchange Server service installed.
  3. Pulling up the Properties for Microsoft Exchange Server.
  4. Selecting the Advanced tab.
  5. Adding an additional mailbox to open.
The sample code below illustrates the steps needed to add an additional mailbox to an existing MAPI profile.

back to the top

Sample Code

Microsoft provides programming examples for illustration only, without warranty either expressed or implied, including, but not limited to, the implied warranties of merchantability and/or fitness for a particular purpose. This article assumes that you are familiar with the programming language being demonstrated and the tools used to create and debug procedures. Microsoft support professionals can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific needs. If you have limited programming experience, you may want to contact a Microsoft Certified Partner or the Microsoft fee-based consulting line at (800) 936-5200. For more information about Microsoft Certified Partners, please visit the following Microsoft Web site: For more information about the support options that are available and about how to contact Microsoft, visit the following Microsoft Web site:
//The following headers may be required if not already in the project:
#include <stdio.h>
#include <mapix.h>
#include <MAPITAGS.H>
#include <MAPIUTIL.H>
#include <edkmdb.h>

/*******************************************************************************

  AddMailbox

  This function will add an additional Exchange mailbox to an existing MAPI
  profile. It assumes that you have already initialized MAPI.

  Parameters:
    lpszProfile         The name of the profile you are going to modify.
    lpszMailboxDisplay  The string that will be displayed in the profile UI.
                        Outlook uses the format "Mailbox - John Doe"
    lpszMailboxDN       The distinguished name of the mailbox to add.
                        Ex. "/o=Microsoft/ou=Test/cn=Recipients/cn=JohnD"
    lpszServer          The DNS name of the server where the additional
                        mailbox resides.
    lpszServerDN        The distinguished name of the server where the
                        additional mailbox resides.
                        Ex. "/o=Microsoft/ou=Test/cn=Configuration/cn=TestSrv"

  Output:
    HRESULT hRes        Returns S_OK if completed successfully, otherwise
                        returns a MAPI error.
*******************************************************************************/ 

HRESULT AddMailbox(LPSTR lpszProfile, 
                   LPSTR lpszMailboxDisplay,
                   LPSTR lpszMailboxDN,
                   LPSTR lpszServer,
                   LPSTR lpszServerDN)
{
    HRESULT             hRes = S_OK;            // Result code returned from MAPI calls.
    LPPROFADMIN         lpProfAdmin = NULL;     // Profile Admin pointer.
    LPSERVICEADMIN      lpSvcAdmin = NULL;      // Message Service Admin pointer.
    LPPROVIDERADMIN     lpProvAdmin = NULL;     // Provider Admin pointer.
    LPMAPITABLE         lpMsgSvcTable = NULL;   // MAPI table pointer.
    LPPROFSECT          lpProfileSection = NULL;// Profile Section Pointer.
    LPSRowSet           lpSvcRows = NULL;       // Row set pointer.
    SPropValue          rgval[4];               // Property value structure to hold configuration info.
    SPropValue          NewVals;                // Property value structure to hold global profile info.
    SRestriction        sres;                   // Restriction structure (used in HrQueryAllRows).
    SPropValue          SvcProps;               // Property value structure used in restriction.
    LPSPropValue        lpGlobalVals = NULL;    // Property value struct pointer for global profile section.
    ULONG               ulProps = 0;            // Count of props.
    ULONG               cbNewBuffer = 0;        // Count of bytes for new buffer.

    // Enumeration for convenience.
    enum {iDispName, iSvcName, iSvcUID, cptaSvc};

    // This structure tells HrQueryAllRows what columns we want returned.
    SizedSPropTagArray(cptaSvc,sptCols) = { cptaSvc, 
                                            PR_DISPLAY_NAME, 
                                            PR_SERVICE_NAME, 
                                            PR_SERVICE_UID };

    // This structure tells our GetProps call what properties to get from the global profile section.
    SizedSPropTagArray(1, sptGlobal) = { 1, PR_STORE_PROVIDERS };

    // Get an IProfAdmin interface.

    hRes = MAPIAdminProfiles(0,             // Flags
                             &lpProfAdmin); // Pointer to new IProfAdmin
    if (FAILED(hRes)) goto error_handler;
    printf("Retrieved IProfAdmin interface.\n");

    // Get an IMsgServiceAdmin interface off of the IProfAdmin interface.

    hRes = lpProfAdmin->AdminServices(lpszProfile,  // Profile that we want to modify.
                                      "",           // Password for that profile.
                                      NULL,         // Handle to parent window.
                                      0,            // Flags.
                                      &lpSvcAdmin); // Pointer to new IMsgServiceAdmin.
    if (FAILED(hRes)) goto error_handler;
    printf("Retrieved IMsgServiceAdmin interface.\n");
        
    // We now need to get the entry id for the Exchange service.
    // First, we get the Message service table.

    hRes = lpSvcAdmin->GetMsgServiceTable(0,                // Flags
                                          &lpMsgSvcTable);  // Pointer to table
    if (FAILED(hRes)) goto error_handler;
    printf("Retrieved message service table from profile.\n");

    // Set up restriction to query table.

    sres.rt = RES_PROPERTY;
    sres.res.resProperty.relop = RELOP_EQ;
    sres.res.resProperty.ulPropTag = PR_SERVICE_NAME;
    sres.res.resProperty.lpProp = &SvcProps;

    SvcProps.ulPropTag = PR_SERVICE_NAME;
    SvcProps.Value.lpszA = "MSEMS";

    // Query the table to get the entry for the Exchange message service.

    hRes = HrQueryAllRows(lpMsgSvcTable,
                          (LPSPropTagArray)&sptCols,
                          &sres,
                          NULL,
                          0,
                          &lpSvcRows);
    if (FAILED(hRes)) goto error_handler;
    printf("Queried table for Exchange message service.\n");

    // Get a provider admin pointer.
    hRes = lpSvcAdmin->AdminProviders((LPMAPIUID)lpSvcRows->aRow->lpProps[iSvcUID].Value.bin.lpb,
                                      0,
                                      &lpProvAdmin);
    if (FAILED(hRes)) goto error_handler;
    printf("Retrieved IProviderAdmin interface\n");

    // Set up a SPropValue array for the properties you need to configure.

    // First, display name.
    ZeroMemory(&rgval[0], sizeof(SPropValue) );
    rgval[0].ulPropTag = PR_DISPLAY_NAME;
    rgval[0].Value.lpszA = lpszMailboxDisplay;

    // Next, the DN of the mailbox.
    ZeroMemory(&rgval[1], sizeof(SPropValue) );
    rgval[1].ulPropTag = PR_PROFILE_MAILBOX; 
    rgval[1].Value.lpszA = lpszMailboxDN;

    // Next the name of the server the mailbox is on.
    ZeroMemory(&rgval[2], sizeof(SPropValue) );
    rgval[2].ulPropTag = PR_PROFILE_SERVER;
    rgval[2].Value.lpszA = lpszServer;

    // Finally, the DN of the server the mailbox is on.
    ZeroMemory(&rgval[3], sizeof(SPropValue) );
    rgval[3].ulPropTag = PR_PROFILE_SERVER_DN;
    rgval[3].Value.lpszA = lpszServerDN;

    // Create the message service with the above properties.
    hRes = lpProvAdmin->CreateProvider("EMSDelegate",
                                       4,
                                       rgval,
                                       0,
                                       0,
                                       (LPMAPIUID)lpSvcRows->aRow->lpProps[iSvcUID].Value.bin.lpb);
    if (FAILED(hRes)) goto error_handler;
    printf("The new mailbox is added.\n");

    // Now let's set the props we need so that the additional mailbox 
    // will display in the UI.

    // Open the global profile section.
    hRes = lpProvAdmin->OpenProfileSection((LPMAPIUID)pbGlobalProfileSectionGuid,
                                           NULL,
                                           MAPI_MODIFY,
                                           &lpProfileSection);
    if (FAILED(hRes)) goto error_handler;
    printf("Opened global profile section.\n");

    // Get the list of store providers in PR_STORE_PROVIDERS.
    hRes = lpProfileSection->GetProps((LPSPropTagArray)&sptGlobal,
                                      0,
                                      &ulProps,
                                      &lpGlobalVals);
    if (FAILED(hRes)) goto error_handler;
    printf("Got the list of mailboxes being opened.\n");

    // Now we set up an SPropValue structure with the original
    // list + the UID of the new service.

    // Compute the new byte count
    cbNewBuffer = lpSvcRows->aRow->lpProps[iSvcUID].Value.bin.cb + lpGlobalVals->Value.bin.cb;

    // Allocate space for the new list of UIDs.
    hRes = MAPIAllocateBuffer( cbNewBuffer,
                              (LPVOID *)&NewVals.Value.bin.lpb);
    if (FAILED(hRes)) goto error_handler;
    printf("Allocated buffer to hold new list of mailboxes to be opened.\n");

    // Copy the bits into the list.
    // First, copy the existing list.
    memcpy(NewVals.Value.bin.lpb,
           lpGlobalVals->Value.bin.lpb,
           lpGlobalVals->Value.bin.cb);

    // Next, copy the new UID onto the end of the list.
    memcpy(NewVals.Value.bin.lpb + lpGlobalVals->Value.bin.cb,
           lpSvcRows->aRow->lpProps[iSvcUID].Value.bin.lpb,
           lpSvcRows->aRow->lpProps[iSvcUID].Value.bin.cb);
    printf("Concatenated list of mailboxes and new mailbox.\n");

    // Set the count of bytes on the SPropValue variable.
    NewVals.Value.bin.cb = cbNewBuffer;
    // Initialize dwAlignPad.
    NewVals.dwAlignPad = 0;
    // Set the prop tag.
    NewVals.ulPropTag = PR_STORE_PROVIDERS;

    // Set the property on the global profile section.
    hRes = lpProfileSection->SetProps(ulProps,
                                      &NewVals,
                                      NULL);
    if (FAILED(hRes)) goto error_handler;
    printf("Set the new list on the global profile section.\n");

    goto cleanup;
    
error_handler:
    printf("ERROR: hRes = %0x\n", hRes);

cleanup:
    // Clean up.
    if (NewVals.Value.bin.lpb) MAPIFreeBuffer(NewVals.Value.bin.lpb);
    if (lpGlobalVals) MAPIFreeBuffer(lpGlobalVals);
    if (lpSvcRows) FreeProws(lpSvcRows);
    if (lpMsgSvcTable) lpMsgSvcTable->Release();
    if (lpSvcAdmin) lpSvcAdmin->Release();
    if (lpProfAdmin) lpProfAdmin->Release();
    if (lpProvAdmin) lpProvAdmin->Release();
    if (lpProfileSection) lpProfileSection->Release();

    printf("Done cleaning up.\n");

    return hRes;
}
				
The following code demonstrates how to call this sample function:
void main(void)
{
    HRESULT hRes = S_OK;

    MAPIInitialize(NULL);
    hRes = AddMailbox(
        "My Profile",
        "Mr Mailbox",
        "/o=MyOrganization/ou=My-Site/cn=Recipients/cn=MMailbox",
        "MyServer",
        "/o=MyOrganization/ou=My-Site/cn=Configuration/cn=MyServer");
    MAPIUninitialize();
}
				
back to the top

Modification Type:MinorLast Reviewed:8/18/2005
Keywords:kbHOWTOmaster kbMsg KB171636 kbAudDeveloper