ID: Q178172
The information in this article applies to:
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.
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.
// 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;
}
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