I hate the EDK.  There, I said it.  So, admittedly, this is less of a guide to using the EDK, and more of an attempt to convince you to ditch it. ;-)

If you're reading this post with any kind of interest, then chances are you've written code with the EDK at some point in your coding career.  Think about this: what benefit did you get from it exactly?

Sure, it gives you simple functions you can call to take care of some of the more tedious MAPI tasks, but it doesn't give you anything that you can't do with straight MAPI (and maybe a little DAPI).

So we've got the "pro" that you don't have to write code for some of the more tedious tasks.  But let's look at the "cons."

Con: linking is a nightmare.
The EDK libraries have so many intertwining dependencies, you almost always have to link more than just the libraries that contain the functions you're using.  Lots of trial-and-error is needed to get your program to link.

Con: troubleshooting EDK functions sucks.
The EDK has this incredibly annoying habit of returning MAPI_E_CALL_FAILED instead of the REAL MAPI error that was returned.  This is even more annoying when you try to use the shipped libraries (you can't debug into the calls and see what really failed!)  Most developers that are using the EDK are just using the shipped libraries (at least that is my impression from the number of cases I've worked on that started out as a call to figure out why <Insert EDK function name here> is returning MAPI_E_CALL_FAILED.  Of course, the EDK source is freely available for download, so you can change this annoying behavior, as well as create debug builds you can step into!

Con: Visual Studio stopped shipping the EDK libraries starting with Visual Studio.NET 2002.
Well, this isn't so bad, since we can copy the libs and headers from a Visual Studio 6.0 install (assuming we have it!), or download the source and build them ourselves.  However, you wouldn't believe how many customer calls we get on this.  The source may be readily available, but a lot of developers obviously don't know about this!  This also begs the question: if you have to download the source and build all of the libraries, doesn't this defeat the whole purpose of using the EDK libraries (saving yourself the tedious busy work)?? ;-)

To put it in perspective, let's look at a simple program.  Consider this very simple program that uses one EDK function, HrOpenExchangePrivateStore:

#include <mapix.h>
#include <edk.h>
#include <stdio.h>

void main()
{
    HRESULT hRes = S_OK;
    LPMAPISESSION lpSession = NULL;
    LPMDB lpPrivStore = NULL;

    if(SUCCEEDED(hRes = MAPIInitialize(NULL)))
    {
        printf("MAPI initialized!\n");

        if(SUCCEEDED(hRes = MAPILogonEx(0,
                                        NULL,
                                        NULL,
                                        MAPI_NEW_SESSION | MAPI_LOGON_UI | MAPI_NO_MAIL,
                                        &lpSession)))
        {
            printf("Logged on!\n");

            if(SUCCEEDED(hRes = HrOpenExchangePrivateStore(lpSession,
                                                           &lpPrivStore)))
            {
                printf("Opened private store!\n");
                lpPrivStore->Release();
            }
            else
            {
                printf("HrOpenExchangePrivateStore returned an error: 0x%08x\n",hRes);
            }
            lpSession->Release();
        }
        else
        {
            printf("MAPILogonEx returned an error: 0x%08x\n", hRes);
        }

        MAPIUninitialize();
    }
    else
    {
        printf("MAPIInitialize returned an error: 0x%08x\n", hRes);
    }
}

Ok, first a few details.  For this comparison, I'm starting with a Visual Studio 6.0 (so we don't have to worry about building or own libraries or copying them over from a Visual Studio 6.0 install) Win32 Console Project.  I chose the "Empty Project" option, so we have no extraneous code generated by Visual Studio.  I've removed all of the libs that are already there and added mapi32.lib under "Object/library modules" on the Link tab under Project Settings.  Finally, I put the above code in a new file, main.cpp.

Now, we know this isn't going to link, since we're using an EDK function and we've added no EDK libraries on the Link tab.  So let's go ahead and add edkmapi.lib to the link tab (since HrOpenExchangePrivateStore is in that particular lib).  We should be good to go, right?

Nope.  Here's my build output:

--------------------Configuration: EDKFun - Win32 Debug--------------------
Compiling...
main.cpp
Linking...
LINK : warning LNK4098: defaultlib "LIBC" conflicts with use of other libs; use /NODEFAULTLIB:library
main.obj : error LNK2001: unresolved external symbol _EDKDBG_HrFailed
edkmapi.lib(iStore.obj) : error LNK2001: unresolved external symbol _HrStrWToStrA
Debug/EDKFun.exe : fatal error LNK1120: 2 unresolved externals
Error executing link.exe.

EDKFun.exe - 3 error(s), 1 warning(s)

Ok...so I'm not using either one of those functions directly, but there's only 2 errors.  Let's see if we can add additional libs to get this to link.  A quick search of MSDN tells me that HrStrWToStrA is in edkutils.lib.  No hits on EDKDBG_HrFailed though.  So let's take advantage of Visual Studio's "Go to Definition of" feature.  I just paste this in to my source file somewhere, right-click and choose "Go to Definition of EDKDBG_HrFailed."  It's defined in EDKDEBUG.H, so I'm guessing it lives in edkdebug.lib.  So, I'll add edkutils.lib and edkdebug.lib.  This should do it, right?

Not so fast!

--------------------Configuration: EDKFun - Win32 Debug--------------------
Compiling...
main.cpp
Linking...
LINK : warning LNK4098: defaultlib "LIBC" conflicts with use of other libs; use /NODEFAULTLIB:library
LINK : warning LNK4049: locally defined symbol "__vsnprintf" imported
LINK : warning LNK4049: locally defined symbol "__snprintf" imported
LINK : warning LNK4049: locally defined symbol "_fflush" imported
LINK : warning LNK4049: locally defined symbol "_strncpy" imported
edkutils.lib(Utl_Str.Obj) : error LNK2001: unresolved external symbol __imp__wcslen
edkutils.lib(Utl_Str.Obj) : error LNK2001: unresolved external symbol __imp__wcscpy
edkdebug.lib(EdkDebug.Obj) : error LNK2001: unresolved external symbol
__imp__MessageBoxA@16
edkdebug.lib(EdkLog.Obj) : error LNK2001: unresolved external symbol __imp__vfprintf
edkdebug.lib(EdkLog.Obj) : error LNK2001: unresolved external symbol __imp__fopen
edkdebug.lib(EdkLog.Obj) : error LNK2001: unresolved external symbol __imp__getenv
edkdebug.lib(EdkLog.Obj) : error LNK2001: unresolved external symbol __imp___stricmp
edkdebug.lib(EdkLog.Obj) : error LNK2001: unresolved external symbol __imp__strtok
Debug/EDKFun.exe : fatal error LNK1120: 8 unresolved externals
Error executing link.exe.
Creating browse info file...

EDKFun.exe - 9 error(s), 5 warning(s)

This is getting ridiculous!  I'll spare you the details of tracking this down.  The end result is I added two more libraries: user32.lib and msvcrt.lib.  Now I can successfully link!

Now, let's look at a more sane approach.  Let's try to eliminate as many of these extra libs as we can (we'll keep mapi32.lib though).  If we can pull the source for HrOpenExchangePrivateStore into our project, perhaps we can take out these dependencies.  We know that HrOpenExchangePrivateStore is in edkmapi.lib, so let's start in edkmapi.h.  Bingo!  It's defined there inline.  Let's copy that into your source file, along with _HrOpenStoreFromGuid (which HrOpenExchangePrivateStore calls).  We have to pick up the #define for pbExchangeProviderPrimaryUserGuid as well (or you can just #include edkmdb.h), but then we're done!  Our link tab is back to just mapi32.lib and we don't need to #include edk.h anymore.

But isn't that just as much, if not more work?  Ok, fair enough.  Depending on how many EDK functions you are going to use, finding the source for the functions and helper functions and copying them into your source can get a little tedious.  But look at the benefits:

- You can fix the functions to actually return the errors that they encounter, rather than mask them.
- You can easily debug into these functions if needed.
- You can optimize these functions for your specific needs.
- Your code becomes much more portable since you don't have dependencies on these libs.

However, if this still sounds like more work than it's worth, then at least help minimize your pain if you need to troubleshoot your code or transfer it to another build environment.  Go download the EDK source and rebuild all of the libs (release AND debug builds!).  Put those into a directory in your build tree.  Copy all of the edk* header files (get the latest ones from the Exchange SDK) into a directory in your build tree too.  Now you can debug AND you'll copy over the needed files if you copy your build tree to another machine.

So, my advice for using the EDK libraries effectively: eliminate your dependency on them altogether!  I think you'll be pleased with the results.