After releasing my first freeware product QuickE numerous request came in, to have the application integrate with the user's address book in their Windows Address Book. On Windows XP, you can find this application by clicking Start->Programs->Accessories->[click] Address Book. I was surprised that anyone was using Windows Address Book, as I was under the naive assumption that everyone uses Outlook or at least Outlook Express (since the latter is at least free), but to my astonishment a lot of people just use the normal Windows Address Book application that comes with most installation of Windows, and if you do use Outlook Express you can actually see that the address book is filled with the same address in Outlook Express. As soon as I started this task, the first thing I did was type in WAB (Windows Address Book) into my MSDN search facility, lo and behold my surprise, at the very small amount of information that was returned to me. I wrote this class in order for other people to have at least a starting point in accessing and using the WAB. I hope you find the source code useful.
This code was written and tested in Visual Studio.NET using unmanaged C++ and Win XP Professional. Tony R. tested this code using Visual C++ 6 and was able to get it to run. If anyone else can run this on another platform, let us know so I can post it here, that would be great. Until I get confirmation that this class works in other development environments and on other operating systems, I will list only what I have tested on a first hand basis.
Accessing the WAB
In order to access the WAB you must first load the wab32.dll library and get the address to WAB open which also gives you pointers to the
IWABObject interfaces. Below is a code snippet on how I made this call:
ssWABOpen = (fWABOpen)GetProcAddress(hModule, "WABOpen");
if (ssWABOpen == NULL) return 2;
HRESULT hr = (ssWABOpen)(&lpAddrBook, &lpWABObject, NULL, 0);
ssWABOpen is a
typedef to the
WABOpen function. Something I came across when writing this is, finding out that when you
typedef this function you must declare the calling mechanism as WINAPI or when compiling you will get a mismatch error.
After this I then call the object's
LoadEmails() function. This private function called from within the
InitAddrBook function, loads the emails into a UDT of objects within an
STL::vector object. I decide to go this route, mainly because of more ignorance on my part, my address book is about 20 names and this method does not soak up too much system resources. If this does not work out for others, I will change it to something more system resource friendly.
LoadEmails() function is where all the email extraction from the WAB to my UDT vector takes place. You can modify or change this into something that would be more appropriate for your specific use. Or, extract the information into a more useful UDT other than the one I have created.
Usage and special functions
In order to give you a foundation of how to use the class, this is how I use the class in my current beta build of my application. In the main dialog's class I declare a private variable of class
CWinAddrBook. I then initialize this variable inside of the dialogs class'
OnInitDialog() function, by calling
object.InitAddrBook member method. This does two things, first it loads the wab32.dll and then, retrieves from this, the address for the
In order to test this class before releasing and not having to build its on application container I created the member method
TestAddr(). This basically takes the contents of the vector after you initialized it, and outputs it (TRACE) while running in debug mode to the output window, it then separates the output by carriage line feed pair. This way you are insured that something is actually in your vector and you can look at the output compared to your address book to insure that all the information transferred over correctly.
Request for comments/dilemmas
When creating this class, here are some strange things I came across, maybe someone could shed some light. First thing that caught me off guard is just by using MSDN documents I tried to only include wabapi.h, when in fact it is better to include just wab.h. By going with what is listed on the interface help sections all I saw was WABAPI and for a while I could not get it to compile.
When I first compiled it into my code, I kept getting a
error C2371: 'WCHAR' redfinition; different basic types
inside of wabdefs.h which is included when you specify wab.h. The work around I used was go into this file and around line line 77 I made this change in order to get my code to compile. I do not know why I had to do this or if it is even right, but it worked. If someone knows what this means I would be greatly appreciative of knowing why it does this.
#if !defined(UNIX) && !defined(WIN16) && !defined(WIN32)
LoadEmails() used to be a separate function that was called after
InitAddr() however I kept getting an unhandled exception inside the
OnInitDialog function. After removing the public function call to
LoadEmails, and made it a private function called from within
InitAddr() it works fine.
Not MSDN! j/k Most of the contributors are included in the header file comments. I will also include here Hirosh for his article on Extracting Email ID's from an address book using Memory mapped file, and another author is anonymous. I got the code snippet from a friend, who said he found it on the Internet, and I have included it in the download file the way I received it. But if anyone knows the author's name or web address please let me know, so I can give him/her the proper credit.
Tony R. for testing out the code in Visual C++ 6 and finding numerous other bugs.
- 1/2/2003: Updated code and changed the extraction process to extract information into separate areas instead of repeatedly extracting all address information to the name field. Changed the structure that holds addresses to use
basic_string instead of a fixed sized array of characters to avoid buffer overrun problems I was experiencing.