HOWTO: Create an Entry in the Personal Address Book

ID: Q178172

The information in this article applies to:

SUMMARY

This article details the process of creating an entry in the Personal Address Book using Extended MAPI and C++. Below are step-by-step instructions and sample code for the process.

MORE INFORMATION

Step-by-Step Instructions

1. Initialize MAPI Subsystem with the MAPIInitialize() function.

2. Start a MAPI session by calling the MAPILogonEx() function.

3. Call IMAPISession::OpenAddressBook() to get an IAddrBook interface.

4. Open the root address book container by calling IAddrBook::OpenEntry().

   Pass NULL as the EntryID to specify the root. This returns an
   IABContainer interface.

5. Get a list of all of the sub-containers of the root address book
   containers by calling IABContainer::GetHierarchyTable(). This returns a
   populated MAPITable.

6. Next, set up a restriction on the table to find the "Personal Address
   Book." Once found, get its EntryID.

7. Use IAddrBook::OpenEntry() to open the Personal Address Book (PAB). Pass
   OpenEntry() the EntryID from the step above to specify the PAB. This
   returns an IABContainer interface.

8. Now you need to find the template for the address type you wish to add.
   To do this, call IABContainer::OpenProperty(). OpenProperty() returns a
   MAPITable of all of its templates.

9. Setup a restriction to find the EntryID of the template you want.

10. Call IABContainer::CreateEntry() with the EntryID from the previous

   step to create the new entry. This new entry still needs to be
   populated with data. The call to CreateEntry() will return a IMAPIProp
   interface.

11. Set the following three properties on the new entry via the IMAPIProp
   interface:

     - PR_DISPLAY_NAME
     - PR_EMAIL_ADDRESS
     - PR_ADDRTYPE

12. Call IMAPIProp::SaveChanges() to write the changes to the object.

Sample Code

   // NOTE: You will need to add Mapi32.lib as an input module in the
   // Link tab of the Project Settings dialog box.

   #define INITGUID
   #define USES_IID_IMAPITable

   // See the "References" section below for information on
   // obtaining this header file.
   #include "MAPIASST.H" // For MAPI_ASSERT_EX and SHOWTABLE

   #include <stdio.h>
   #include <mapiutil.h>
   #include <conio.h>   // Just for getch()

   #include <mapidefs.h>
   #include <mapiguid.h>

   HRESULT AddToPab(LPTSTR lpszDisplayName, LPTSTR lpszAddress,
           LPTSTR lpszAddrType);

   // This gives an example of calling the AddToPab function.
   void main()
   {
     HRESULT      hr = S_OK;
     char sDone[64];

     hr = AddToPab("Created By MyCode", "email@domain.com", "SMTP");
     sprintf(sDone, "Done, hr=0x%x\n", hr);
     OutputDebugString(sDone);
     getch();
   }

   HRESULT AddToPab(LPTSTR lpszDisplayName, LPTSTR lpszAddress,
           LPTSTR lpszAddrType)
   {
    HRESULT      hr = S_OK;
    LPMAPISESSION   lpSession = NULL;
    LPADRBOOK      lpAddrbk = NULL;
    LPMAPICONTAINER   lpAddrRoot = NULL;
    LPMAPITABLE      lpBooks = NULL;
    ULONG      ulCount = NULL;
    ULONG      ulObjType = NULL;
    LPSRowSet      pRows =   NULL;
    SRestriction           srName;
    SPropValue      spv;
    LPSPropValue    lpProp;
    LPABCONT      lpABC = NULL;
    LPMAPITABLE      lpTPLTable = NULL;
    LPMAPIPROP      lpNewEntry = NULL;

    SizedSPropTagArray(2, Columns) =
            {2, {PR_DISPLAY_NAME, PR_ENTRYID}};
    SizedSPropTagArray(2, TypeColumns) =
            {2, {PR_ADDRTYPE, PR_ENTRYID}};

   // Initialize MAPI Subsystem.
   hr = MAPIInitialize(NULL);
   MAPI_ASSERT_EX(hr);

   // Logon to MAPI.
   hr = MAPILogonEx(0,NULL,NULL,MAPI_LOGON_UI,&lpSession);
   MAPI_ASSERT_EX(hr);

   hr = lpSession->OpenAddressBook(0,NULL,0,&lpAddrbk);
   MAPI_ASSERT_EX(hr);

   // Open root address book (container).
   hr = lpAddrbk->OpenEntry(0L,NULL,NULL,0L,&ulObjType,
                  (LPUNKNOWN*)&lpAddrRoot);
   MAPI_ASSERT_EX(hr);

   // Get a table of all of the Address Books.
   hr = lpAddrRoot->GetHierarchyTable(0, &lpBooks);
   MAPI_ASSERT_EX(hr);
   //SHOWTABLE(lpBooks);

   // Restrict the table to just its name and ID.
   hr = lpBooks->SetColumns((LPSPropTagArray)&Columns, 0);
   MAPI_ASSERT_EX(hr);

   // Build a restriction to find the Personal Address Book.
   srName.rt = RES_PROPERTY;
   srName.res.resProperty.relop = RELOP_EQ;
   srName.res.resProperty.ulPropTag = PR_DISPLAY_NAME;
   srName.res.resProperty.lpProp = &spv;
   spv.ulPropTag = PR_DISPLAY_NAME;
   spv.Value.lpszA = "Personal Address Book";  // Address Book to open

   // Apply the restriction
   hr = lpBooks->Restrict(&srName,0);
   MAPI_ASSERT_EX(hr);

   // Get the total number of rows returned. Typically, this will be 1.
   hr = lpBooks->GetRowCount(0,&ulCount);
   MAPI_ASSERT_EX(hr);

   // Get the row properties (trying to get the EntryID).
   hr = lpBooks->QueryRows(ulCount,0,&pRows);
   MAPI_ASSERT_EX(hr);

   // Get a pointer to the properties.
   lpProp = &pRows->aRow[0].lpProps[1];   // Point to the EntryID Prop

   // Open the Personal Address Book (PAB).
   hr = lpAddrbk->OpenEntry(lpProp->Value.bin.cb,
                  (ENTRYID*)lpProp->Value.bin.lpb,
                  NULL,MAPI_MODIFY,&ulObjType,
                  (LPUNKNOWN FAR *)&lpABC);
   MAPI_ASSERT_EX(hr);

   // Get a table of templates for the address types.
   hr = lpABC->OpenProperty( PR_CREATE_TEMPLATES,
                  (LPIID) &IID_IMAPITable,
                   0, 0,
                  (LPUNKNOWN *)&lpTPLTable);
   MAPI_ASSERT_EX(hr);
   //SHOWTABLE(lpTPLTable);
   // Restrict the table to just its name and ID
   hr = lpTPLTable->SetColumns((LPSPropTagArray)&TypeColumns, 0);
   MAPI_ASSERT_EX(hr);

   // Get the EntryID of the Internet Mail Address Template
   // Build a restriction to find the SMTP Template
   srName.rt = RES_PROPERTY;
   srName.res.resProperty.relop = RELOP_EQ;
   srName.res.resProperty.ulPropTag = PR_ADDRTYPE;
   srName.res.resProperty.lpProp = &spv;
   spv.ulPropTag = PR_ADDRTYPE;
   spv.Value.lpszA = lpszAddrType;   // Name of Template ID you want
                                     // passed into the function

   // Apply the restriction
   hr = lpTPLTable->Restrict(&srName,0);
   MAPI_ASSERT_EX(hr);
   // Get the total number of rows returned. Typically, this will be 1.
   hr = lpTPLTable->GetRowCount(0,&ulCount);
   MAPI_ASSERT_EX(hr);

   // Get the row properties (trying to get the EntryID).
   hr = lpTPLTable->QueryRows(ulCount,0,&pRows);

   // Get a pointer to the properties.
   lpProp = &pRows->aRow[0].lpProps[1];   // Point to the EntryID of
                                         // the template.

   // Now, you can actually create the new entry.
   // It is blank when created.
   hr = lpABC->CreateEntry(lpProp->Value.bin.cb,
               (ENTRYID*)lpProp->Value.bin.lpb,
               CREATE_CHECK_DUP_LOOSE,
               &lpNewEntry);
   MAPI_ASSERT_EX(hr);

   if (S_OK == hr && lpNewEntry)
   {
      // Ok, now you need to set some properties on the new Entry.
      const unsigned long cProps = 3;
      SPropValue   aPropsMesg[cProps];
      LPSPropProblemArray   lpPropProblems = NULL;

      // Setup your properties.
      aPropsMesg[0].dwAlignPad   = 0;
      aPropsMesg[0].ulPropTag   = PR_EMAIL_ADDRESS;
      aPropsMesg[0].Value.LPSZ   = lpszAddress;
      aPropsMesg[1].dwAlignPad   = 0;
      aPropsMesg[1].ulPropTag   = PR_DISPLAY_NAME;
      aPropsMesg[1].Value.LPSZ   = lpszDisplayName;
      aPropsMesg[2].dwAlignPad   = 0;
      aPropsMesg[2].ulPropTag   = PR_ADDRTYPE;
      aPropsMesg[2].Value.LPSZ   = lpszAddrType;

      // Set the properties on the object.
      hr = lpNewEntry->SetProps(cProps, aPropsMesg, &lpPropProblems);
      MAPI_ASSERT_EX(hr);

      // Explictly save the changes to the new entry.
      hr = lpNewEntry->SaveChanges(NULL);
      if (MAPI_E_COLLISION == hr)
      {
       // You tried to add an entry that already exists.
       OutputDebugString("Collision! The entry Already Exists.\n");
       hr = S_OK;   // Handled the error....
      }
      MAPI_ASSERT_EX(hr);
     }

     // Cleanup
     if (lpNewEntry) lpNewEntry->Release();
     if (lpTPLTable) lpTPLTable->Release();
     if (lpABC) lpABC->Release();
     if (lpBooks) lpBooks->Release();
     if (lpAddrRoot) lpAddrRoot->Release();
     if (lpAddrbk) lpAddrbk->Release();
     if (lpSession) lpSession->Release();

     FreeProws(pRows);
     return hr;
    }

REFERENCES

For information on how to obtain the Mapiasst.h header file that contains helpful debugging routines, please see the following article in the Microsoft Knowledge Base:

   ARTICLE-ID: Q177542
   TITLE     : FILE: MAPIASST.EXE: MAPI ASSERT Debug Routines

Additional query words: Personal Address Book PAB CreateEntry Create Entry Add
Keywords          : kbcode kbMsg kbMAPI100 MAPIIAB 
Version           : WINDOWS:1.0
Platform          : WINDOWS
Issue type        : kbhowto

Last Reviewed: April 15, 1998