Outlook 2010 MAPI Samples

I’ve updated the Outlook MAPI Samples and posted a new project up on Codeplex: Outlook 2010 MAPI Samples. We’ll get the MSDN updated to point at these samples soon. The goal of this update, of course, was to get these samples working with Outlook 2010, especially in 64 bit mode. Most of the changes were minor, swapping ULONG for ULONG_PTR, etc., but  I did have to make a couple big changes:

  • None of the samples link to mapi32.lib anymore. I talked about this already. This was actually easier to do than I expected. I just copied my ImportProc files from MFCMAPI and tweaked them a bit.
  • The other major change was removing the Exchange Client Extension from Wrapped PST. The extension never had anything to do with the sample. It was just used as a convenient way to drive a test function to illustrate the replication API. I replaced the whole thing with an exported function and a simple VBA macro used to call the function. You’ll find the macro in the file TestMacro.txt

I’m sure there are bugs in these samples. I didn’t get to test every possible scenario. So feedback is welcome – see the Help/Feedback section of the main page.

Comments (8)

  1. Thomas says:

    Not sure where to ask this, so bare with me if this is the wrong place.

    We have a solution that is using MAPI to extract data from Exchange 2003/2007 and works well with the ExchangeCdo.EXE download from MS.

    But testing with this against Exchange 2010 give me a "The information store could

    not be opened" exception. Installing Outlook 2003 or 2007 helps, but is not a doable solution.

    Any advice on this ?

    Regards, Thomas

  2. The problem is with how your profile is configured. Exchange 2010 is gonna need some special tweaks in the profile to connect from the MAPI download. Dave Vespa is the guy you wanna talk to:


  3. Thomas says:


    Thanks for the help on the earlier request. Dave Vespa does not allow comments/questions, so I will try here once again.

    To summarize:

    I use the ExchangeCdo.EXE download from MS to connect to Exchange 2010 RC and get the following error

    I got the profile to work easily, but get following error after a while.

    Mapi session "/o=First Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=DEV-EXCH2K10/cn=Microsoft System Attendant" exceeded the maximum of 250 objects of type "objtMessage".

    No issues with Exchange 2003/2007. Looked at the code a LONG time, but it seems to release ok, this occurs when looping through a collection of messages. Any advice?

    Regards, Thomas

  4. Thomas says:

    If any help I just noticed that an error just prior to other one is:

    /o=First Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=DEV-EXCH2K10/cn=Microsoft System Attendant



    The streams ARE released in the code. I think these streams could be the one that keeps the messages open as well.

    Regards, Thomas

  5. Thomas says:


    To summarize:

    I use the ExchangeCdo.EXE download from MS to connect to Exchange 2010 RC.

    I think I have isolated the code that will make the prior issue to fail. Looping through a large collection of messages and referencing the attachment table on each message, will make the code fail with 0x80004005, even with a proper release of IMAPITable.

    My code:

    #include "stdafx.h"

    #include <afxwin.h>

    #include <edk.h>

    int _tmain(int argc, _TCHAR* argv[])


       LPMAPISESSION pSession = NULL;

    HRESULT hr = S_OK;

            //Initialize MAPI libraries. First step on MAPI Programming

            hr = MAPIInitialize (NULL);

    char lpProfileName[] = "DEVTG";

    //LPTSTR lpProfileName = "DEVTG";

            // logon to MAPI for enumerating emails from inbox. This can also be used to open the public folders, if one has access.


            if (FAILED (hr))

              return E_FAIL;

           // Find default message store using HRMAPI function

           ULONG cbDefStoreEntryid = 0;

           LPENTRYID pDefStoreEntryid = NULL;

           hr = HrMAPIFindDefaultMsgStore(pSession, &cbDefStoreEntryid, &pDefStoreEntryid);

           if (FAILED (hr))

               return E_FAIL;

          // open the MAPI Public Folder tree

          LPMDB pDefaultMsgStore = NULL;

          hr = pSession->OpenMsgStore(0, cbDefStoreEntryid, pDefStoreEntryid, NULL,

                        MDB_WRITE | MAPI_DEFERRED_ERRORS, &pDefaultMsgStore );

          if (FAILED (hr))

                return E_FAIL;

          DWORD cbeid = 0;

          LPENTRYID lpeid = NULL;

          LPMAPIFOLDER pFolder = NULL;

          ULONG ulObjType = 0;

          //Path to the inbox

          CString l_strFullPath = "@PR_IPM_SUBTREE_ENTRYID\Inbox";

          //Used to filter the columns for enumerating emails using MAPI

          SizedSPropTagArray ( 2, rgPropTag ) =




                     PR_ENTRYID, // its unique across directory




           // Open the Inbox folder

           hr = HrMAPIOpenFolderEx(pDefaultMsgStore,  ‘\’, (LPCTSTR)l_strFullPath, &pFolder);

           if (FAILED (hr))

               return E_FAIL;

           LPMAPITABLE lpMapiTbl = NULL;

           //Enumerate emails using MAPI in C++

           hr = pFolder->GetContentsTable(0, &lpMapiTbl);

           if (FAILED (hr))

              return E_FAIL;

           // Get count rows

           ULONG ulRows = 0;

           hr = lpMapiTbl->GetRowCount(0, &ulRows);

           if (FAILED (hr))

               return E_FAIL;

           hr = lpMapiTbl->SetColumns((LPSPropTagArray)&rgPropTag, 0 );

           if (FAILED (hr)) return E_FAIL;

           // Get all rows

           SRowSet * pRows = NULL;

           hr = HrQueryAllRows(lpMapiTbl,NULL, NULL, NULL, ulRows,&pRows);

           if (FAILED (hr)) return E_FAIL;

          printf("Total Number of messages : %dn",pRows->cRows);

          for(int i=0;i<pRows->cRows;i++)


             if(PR_ENTRYID == pRows -> aRow[i].lpProps[0].ulPropTag)


    printf("Opening message : %dn",i);

                  LPUNKNOWN pMessage;

    ULONG ulObjType = 0;

    // Open the target message

                   hr = pFolder->OpenEntry(pRows -> aRow[i].lpProps[0].Value.bin.cb,

                       (LPENTRYID) pRows -> aRow[i].lpProps[0].Value.bin.lpb,





    if (FAILED (hr)) {

    DWORD iLastError = GetLastError();

    printf("Opening message failed : %xn",hr);

    return E_FAIL;


    LPMAPITABLE pAttachTbl = NULL;


    hr = ((LPMESSAGE) pMessage)->GetAttachmentTable(0, &pAttachTbl);

    if (FAILED(hr)) throw -1;

    if (pAttachTbl)


    if (pMessage)




          //Release all the resources used

          if (lpMapiTbl)


          if (pRows)






          MAPIFreeBuffer (lpeid);

          pFolder = NULL;

          //Free all MAPI libraries


    return 0;


  6. It’s great these samples are updated for Outlook 2010, but GetOutlookVersionString does not seem to contain the 2010 component qualifier yet (1E77DE88-BCAB-4C37-B9E5-073AF52DFD7A)… which in turn causes MSProviderInit() to halt with an E_OUTOFMEMORY (seems a bit of an odd choice?). Adding this qualifier solves the issue.

    Could it be these samples are only tested on a machine that had 2007 installed previously? Or did I not download the right files?

  7. I tested them with a build of 2010, but it may have been an early build. I’ll check it out and update them as needed. Thanks!

  8. I fixed it. Thanks for the report.