HOWTO: Create an Entry in the Personal Address Book

Last reviewed: January 6, 1998
Article ID: Q178172
The information in this article applies to:
  • Extended Messaging Application Programming Interface (MAPI), version 1.0

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 it's 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 it's 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 EMAPI MAPIIAB
Version : WINDOWS:1.0
Platform : WINDOWS
Issue type : kbhowto


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: January 6, 1998
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.