Finding Information About a User in the Address Book
You can find a user in the address book given a name, part of a name, or other information about the user; retrieve information from that entry; and search for several users at a time.
Design Tasks
-
Decide whether you're searching the entire address book, one or more containers belonging to a specific message service, or a particular type of container such as a personal or global address list.
-
Decide what properties are in your search criteria. The only property you can rely on searching with acceptable performance is PR_DISPLAY_NAME. If you want to use another property such as an account name, employee identification number, or organization name, you must experiment with the address book providers you expect to use to verify that searching on those properties is supported and the performance is acceptable.
-
Understand whether or not the information you are given should identify each user uniquely. If it can be ambiguous — if it can match more than one entry in the address book — then decide whether your program should:
-
Prompt its user to choose the right entry.
-
Choose the right entry itself based on further information retrieved about each entry.
-
Fail.
Implementation Tasks
To search the entire address book by display name for one or more entries
-
Use the IAddrBook::ResolveName method. You can optionally request a dialog box that prompts the user to choose the correct entry in case the information you were given matches more than one entry.
To open the user's personal address book (PAB)
-
Retrieve its entry identifier by calling the IAddrBook::GetPAB method.
-
Call the IAddrBook::OpenEntry method passing the PAB's entry identifier.
To open a specific container other than the PAB
-
Open the address book's root container by calling the IAddrBook::OpenEntry method with a NULL entry identifier. The root container is constructed by MAPI and contains the top-level containers of all the address book providers in the profile.
-
Get the list of top-level containers by calling the IMAPIContainer::GetHierarchyTable method.
-
If you want a specific container type such as the global address list, restrict the table on PR_DISPLAY_TYPE:
-
Create a property restriction to match PR_DISPLAY_TYPE with the value for the particular type of container you want to open. For example, to open the global address book, build a property restriction that matches PR_DISPLAY_TYPE with the DT_GLOBAL value.
-
Create an SPropTagArray including PR_ENTRYID, PR_DISPLAY_TYPE, and any other columns of interest.
-
Call the HrQueryAllRows function passing your property tag array and restriction. Ordinarily, there will be a single global address list, but the call can return zero, one, or more rows depending on the address book providers in your profile. Be prepared to handle all these cases, not just one row.
-
Call the IAddrBook::OpenEntry method with the PR_ENTRYID column from the row you want to open the container.
-
If you want a container belonging to a specific address book provider, restrict the table on PR_AB_PROVIDER_ID:
-
Create a property restriction to match PR_AB_PROVIDER_ID with the value that represents the target address book provider. You will find this property value in a header file created by the service provider. In the Platform SDK, for instance, the value for the flat file address book sample is SAB_PROVIDER_ID in SMPAB.H.
-
Create an SPropTagArray structure including PR_ENTRYID, PR_AB_PROVIDER_ID, and any other columns of interest.
-
Call the HrQueryAllRows function passing your property tag array and restriction. The call will return zero rows if the provider you want is not in the profile. It can return one or more rows depending on the provider's containers are organized, but it will only return the top-level rows.
-
Call the IAddrBook::OpenEntry method with the PR_ENTRYID column from the row you want to open the container. If the container you want is not a top-level container, you will then have to navigate down through the latter's hierarchy table.
To search in a specific address book container
-
Open its contents table by calling its GetContentsTable method.
-
Use IMAPITable::FindRow, IMAPITable::SortTable, and IMAPITable::Restrict to search the contents table just as you can any MAPI table. See Table Positioning and About Restrictions. These methods are subject to limitations in the provider's implementation, and their speed is unpredictable; careful testing against any providers you expect to use is indispensible. In addition to the normal IMAPITable methods, there are two search techniques specific to address book containers:
-
Restriction on PR_ANR (ambiguous name resolution). Although formatted as an ordinary SPropertyRestriction structure, this restriction actually invokes a special display name matching algorithm based on separating the string you give it into words and prefix-matching those words against display names in the address book. See Implementing Name Resolution.
-
IABContainer::ResolveNames. This method does the same work as a PR_ANR restriction for multiple names, and can be much faster. Providers are not required to implement it, and generally do not unless it carries a significant performance benefit. It is not necessary to open the contents table in order to user this method.
-
After applying any of the restriction methods listed above, call the IMAPITable::QueryRows method to retrieve any rows that match the restriction. You may get back zero, one, or more rows that match.
-
Retrieve additional information for a single address book entry by calling the IAddrBook::OpenEntry method passing its entry identifier, then call GetProps on the resulting IMAPIProp interface. To retrieve additional properties for multiple address book entries, you can of course call OpenEntry for each one, but it is usually much more efficient to call the IAddrBook::PrepareRecips method. PrepareRecips requires an ADRLIST structure.