Microsoft KB Archive/247371: Difference between revisions

From BetaArchive Wiki
m (Text replacement - "<" to "<")
m (Text replacement - ">" to ">")
Line 56: Line 56:
<br />
<br />
After the call to MAPIUninitilize, the new structure (lpHopeRows) is still available and can be used by the rest of the program. Cleanup code should also be included to delete the new structure when finished.
After the call to MAPIUninitilize, the new structure (lpHopeRows) is still available and can be used by the rest of the program. Cleanup code should also be included to delete the new structure when finished.
<pre class="codesample">#include <mapix.h&gt;
<pre class="codesample">#include <mapix.h>
#include &quot;mapidefs.h&quot;   
#include &quot;mapidefs.h&quot;   
#include <mapiutil.h&gt;
#include <mapiutil.h>
#include <mapitags.h&gt;
#include <mapitags.h>
#include <mapioid.h&gt;
#include <mapioid.h>
#include <edkmdb.h&gt;
#include <edkmdb.h>


#define INITGUID
#define INITGUID
#include <initguid.h&gt;
#include <initguid.h>
#include <mapiguid.h&gt;
#include <mapiguid.h>
#include <edkguid.h&gt;
#include <edkguid.h>
#include <stdio.h&gt;
#include <stdio.h>


#pragma comment(lib, &quot;mapi32.lib&quot;)
#pragma comment(lib, &quot;mapi32.lib&quot;)
Line 113: Line 113:
                         &amp;lpSession);
                         &amp;lpSession);


         hr = lpSession-&gt;OpenAddressBook(NULL,
         hr = lpSession->OpenAddressBook(NULL,
                                         NULL,
                                         NULL,
                                         NULL,
                                         NULL,
Line 119: Line 119:
      
      
         //Code to open up the folders in the address book   
         //Code to open up the folders in the address book   
         hr = lpAdrBook-&gt;OpenEntry(0,
         hr = lpAdrBook->OpenEntry(0,
                                   NULL,
                                   NULL,
                                   NULL,
                                   NULL,
Line 126: Line 126:
                                   (LPUNKNOWN*)&amp;lpABCont);
                                   (LPUNKNOWN*)&amp;lpABCont);


         hr = lpABCont-&gt;GetHierarchyTable(CONVENIENT_DEPTH | MAPI_DEFERRED_ERRORS, &amp;lpTable);
         hr = lpABCont->GetHierarchyTable(CONVENIENT_DEPTH | MAPI_DEFERRED_ERRORS, &amp;lpTable);


         //Custom function QueryEntryID takes a IMAPITABLE, Column to search on, Value to Equal,  
         //Custom function QueryEntryID takes a IMAPITABLE, Column to search on, Value to Equal,  
Line 135: Line 135:
                           (LPSPropValue*)&amp;lpProp);
                           (LPSPropValue*)&amp;lpProp);
      
      
         hr = lpAdrBook-&gt;OpenEntry(lpProp-&gt;Value.bin.cb,
         hr = lpAdrBook->OpenEntry(lpProp->Value.bin.cb,
                                   (LPENTRYID)lpProp-&gt;Value.bin.lpb,
                                   (LPENTRYID)lpProp->Value.bin.lpb,
                                   NULL,
                                   NULL,
                                   MAPI_MODIFY,
                                   MAPI_MODIFY,
Line 142: Line 142:
                                   (LPUNKNOWN*)&amp;lpABOut);
                                   (LPUNKNOWN*)&amp;lpABOut);


         hr = lpABOut-&gt;GetContentsTable(NULL, &amp;lpContentsTbl);
         hr = lpABOut->GetContentsTable(NULL, &amp;lpContentsTbl);
      
      
         // Position to the beginning of the contents table.
         // Position to the beginning of the contents table.
         hr = lpContentsTbl-&gt;SeekRow(BOOKMARK_BEGINNING, 0, NULL) ;
         hr = lpContentsTbl->SeekRow(BOOKMARK_BEGINNING, 0, NULL) ;


         //Find out how many rows are in the table
         //Find out how many rows are in the table
         hr = lpContentsTbl-&gt;GetRowCount(0, &amp;ulCount);
         hr = lpContentsTbl->GetRowCount(0, &amp;ulCount);


       hr = lpContentsTbl-&gt;SetColumns((SPropTagArray*)&amp;TypeColumns, 0);
       hr = lpContentsTbl->SetColumns((SPropTagArray*)&amp;TypeColumns, 0);


       //Use QueryRows to gather the first 50 rows in the ContentsTable
       //Use QueryRows to gather the first 50 rows in the ContentsTable
         hr = lpContentsTbl-&gt;QueryRows(50, TBL_NOADVANCE, &amp;lpRows);
         hr = lpContentsTbl->QueryRows(50, TBL_NOADVANCE, &amp;lpRows);


         //Build a new LPSRowSet using malloc to persist after MAPIUninitialize.
         //Build a new LPSRowSet using malloc to persist after MAPIUninitialize.
Line 162: Line 162:
         memcpy (lpHopeRows, lpRows, ulSizeOfSet) ;
         memcpy (lpHopeRows, lpRows, ulSizeOfSet) ;


         for(ulSRowCount = 0; ulSRowCount < lpRows-&gt;cRows; ulSRowCount++)
         for(ulSRowCount = 0; ulSRowCount < lpRows->cRows; ulSRowCount++)
     {
     {
             lpHopeRows-&gt;aRow[ulSRowCount].lpProps = (LPSPropValue)malloc(lpRows-&gt;aRow[ulSRowCount].cValues*sizeof(SPropValue));
             lpHopeRows->aRow[ulSRowCount].lpProps = (LPSPropValue)malloc(lpRows->aRow[ulSRowCount].cValues*sizeof(SPropValue));


         for(ulPropCount = 0;
         for(ulPropCount = 0;
             ulPropCount < lpRows-&gt;aRow[ulSRowCount].cValues;
             ulPropCount < lpRows->aRow[ulSRowCount].cValues;
             ulPropCount++)
             ulPropCount++)
         {
         {
             lpOldTempProp = lpRows-&gt;aRow[ulSRowCount].lpProps;
             lpOldTempProp = lpRows->aRow[ulSRowCount].lpProps;
             lpNewTempProp = lpHopeRows-&gt;aRow[ulSRowCount].lpProps;
             lpNewTempProp = lpHopeRows->aRow[ulSRowCount].lpProps;
              
              
             //Copy over the LPSPropValue structure for this property
             //Copy over the LPSPropValue structure for this property
Line 220: Line 220:
     FreeProws(lpRows);
     FreeProws(lpRows);


     if(lpABOut) lpABOut-&gt;Release();
     if(lpABOut) lpABOut->Release();
     if(lpABCont) lpABCont-&gt;Release();
     if(lpABCont) lpABCont->Release();
     MAPIFreeBuffer(lpProp);
     MAPIFreeBuffer(lpProp);
     if(lpTable) lpTable-&gt;Release();
     if(lpTable) lpTable->Release();
     if(lpAdrBook) lpAdrBook-&gt;Release();
     if(lpAdrBook) lpAdrBook->Release();
      
      
     if(lpContentsTbl) lpContentsTbl-&gt;Release();
     if(lpContentsTbl) lpContentsTbl->Release();
     if(lpMDB) lpMDB-&gt;Release();
     if(lpMDB) lpMDB->Release();
     if(lpSession)
     if(lpSession)
     {
     {
         lpSession-&gt;Logoff(NULL, NULL, NULL);
         lpSession->Logoff(NULL, NULL, NULL);
         lpSession-&gt;Release();
         lpSession->Release();
     }
     }


Line 238: Line 238:
     //The new SRowSet (lpHopeRows) is still available and can be used and cleaned up when you want.
     //The new SRowSet (lpHopeRows) is still available and can be used and cleaned up when you want.


         printf(&quot;lpHopeRows cRows: %d\n&quot;, lpHopeRows-&gt;cRows);
         printf(&quot;lpHopeRows cRows: %d\n&quot;, lpHopeRows->cRows);
      
      
     for(ulSRowCount = 0; ulSRowCount < lpHopeRows-&gt;cRows; ulSRowCount++)
     for(ulSRowCount = 0; ulSRowCount < lpHopeRows->cRows; ulSRowCount++)
     {
     {
         for(ulPropCount = 0;
         for(ulPropCount = 0;
             ulPropCount < lpHopeRows-&gt;aRow[ulSRowCount].cValues;
             ulPropCount < lpHopeRows->aRow[ulSRowCount].cValues;
             ulPropCount++)
             ulPropCount++)
         {
         {
             switch(lpHopeRows-&gt;aRow[ulSRowCount].lpProps[ulPropCount].ulPropTag)
             switch(lpHopeRows->aRow[ulSRowCount].lpProps[ulPropCount].ulPropTag)
             {
             {
                 case PR_DISPLAY_NAME:
                 case PR_DISPLAY_NAME:
                     printf(&quot;DisplayName: %s\n&quot;, lpHopeRows-&gt;aRow[ulSRowCount].lpProps[ulPropCount].Value.lpszA);
                     printf(&quot;DisplayName: %s\n&quot;, lpHopeRows->aRow[ulSRowCount].lpProps[ulPropCount].Value.lpszA);
                     break;
                     break;
                 default:
                 default:
Line 276: Line 276:


     // Restrict the table to just it's name and ID
     // Restrict the table to just it's name and ID
     hr = lpTable-&gt;SetColumns((LPSPropTagArray)&amp;TypeColumns, 0);
     hr = lpTable->SetColumns((LPSPropTagArray)&amp;TypeColumns, 0);
     if(FAILED(hr))
     if(FAILED(hr))
     {
     {
Line 293: Line 293:
      
      
     // Apply the restriction
     // Apply the restriction
     hr = lpTable-&gt;Restrict(&amp;srName,0);
     hr = lpTable->Restrict(&amp;srName,0);
     if(FAILED(hr))
     if(FAILED(hr))
     {
     {
Line 301: Line 301:


     // Get the total number of rows returned. Typically, this will be 1.
     // Get the total number of rows returned. Typically, this will be 1.
     hr = lpTable-&gt;GetRowCount(0,&amp;ulCount);
     hr = lpTable->GetRowCount(0,&amp;ulCount);
     if(FAILED(hr))
     if(FAILED(hr))
     {
     {
Line 309: Line 309:


     // Get the row props (trying to get the EntryID)
     // Get the row props (trying to get the EntryID)
     hr = lpTable-&gt;QueryRows(ulCount,0,&amp;pRows);
     hr = lpTable->QueryRows(ulCount,0,&amp;pRows);
     if(FAILED(hr))
     if(FAILED(hr))
     {
     {
Line 324: Line 324:
     }
     }


     hr = MAPIAllocateMore(pRows-&gt;aRow[0].lpProps[1].Value.bin.cb, pspvRet, (LPVOID*)&amp;pspvRet-&gt;Value.bin.lpb);
     hr = MAPIAllocateMore(pRows->aRow[0].lpProps[1].Value.bin.cb, pspvRet, (LPVOID*)&amp;pspvRet->Value.bin.lpb);
     if(FAILED(hr))
     if(FAILED(hr))
     {
     {
Line 332: Line 332:
     }
     }


     pspvRet-&gt;ulPropTag = pRows-&gt;aRow[0].lpProps[1].ulPropTag;
     pspvRet->ulPropTag = pRows->aRow[0].lpProps[1].ulPropTag;
     pspvRet-&gt;Value.bin.cb = pRows-&gt;aRow[0].lpProps[1].Value.bin.cb;
     pspvRet->Value.bin.cb = pRows->aRow[0].lpProps[1].Value.bin.cb;


     memcpy(pspvRet-&gt;Value.bin.lpb,
     memcpy(pspvRet->Value.bin.lpb,
           pRows-&gt;aRow[0].lpProps[1].Value.bin.lpb,
           pRows->aRow[0].lpProps[1].Value.bin.lpb,
           pRows-&gt;aRow[0].lpProps[1].Value.bin.cb);
           pRows->aRow[0].lpProps[1].Value.bin.cb);
      
      
     // Get a pointer to the props.
     // Get a pointer to the props.

Revision as of 09:43, 21 July 2020

Knowledge Base


How To Copy LPSRowSet from MAPI Memory to System Memory

Article ID: 247371

Article Last Modified on 8/25/2005



APPLIES TO

  • Microsoft Messaging Application Programming Interface



This article was previously published under Q247371

SUMMARY

Using Extended MAPI, a call to MAPIUninitialize cleans up memory that has been allocated with MAPIAllocateBuffer and MAPIAllocateMore. In order to retain this data to be used after MAPIUninitialize is called, this data needs to be copied out of MAPI memory and over into system memory. This sample illustrates how you can copy a LPSRowSet over to system memory.

MORE INFORMATION

The LPSRowSet in this sample has been created with a call to HrQueryAllRows which uses MAPIAllocateBuffer and MAPIAllocateMore.

For this illustration, you are only copying over the PR_DISPLAY_NAME and PR_ENTRYID properties in the LPSRowSet. There may be additional properties that need to be added depending on the LPSRowSet that is being copied.

After the call to MAPIUninitilize, the new structure (lpHopeRows) is still available and can be used by the rest of the program. Cleanup code should also be included to delete the new structure when finished.

#include <mapix.h>
#include "mapidefs.h"  
#include <mapiutil.h>
#include <mapitags.h>
#include <mapioid.h>
#include <edkmdb.h>

#define INITGUID
#include <initguid.h>
#include <mapiguid.h>
#include <edkguid.h>
#include <stdio.h>

#pragma comment(lib, "mapi32.lib")

HRESULT QueryEntryID(LPMAPITABLE, ULONG, LPSTR, LPSPropValue*);

int main(int argc, char* argv[])
{
        HRESULT         hr              = NULL; 
        LPMAPISESSION   lpSession       = NULL;
        LPMDB           lpMDB           = NULL;

        LPMAPITABLE     lpContentsTbl   = NULL;
        ULONG           ulCount         = NULL;
        LPSRowSet       lpRows          = NULL;

        //Variables for initiating the Address Book
        ULONG           ulObjType       = NULL;
        LPADRBOOK       lpAdrBook       = NULL;
        LPMAPITABLE     lpTable         = NULL;
        LPSPropValue    lpProp          = NULL;
        LPABCONT        lpABCont        = NULL;
        LPABCONT        lpABOut         = NULL;

        SizedSPropTagArray(2, TypeColumns) = {2, {PR_DISPLAY_NAME, PR_ENTRYID}};

        ULONG           ulSRowCount     = 0;
        ULONG           ulPropCount     = 0;
        ULONG           ulSizeOfSet     = 0;
        ULONG           ulTempSizeofBuffer  = 0;

        LPSPropValue    lpOldTempProp   = NULL;
        LPSPropValue    lpNewTempProp   = NULL;

        LPSRowSet       lpHopeRows      = NULL;
        void *          pv              = NULL;

    
        hr = MAPIInitialize(NULL);

        hr = MAPILogonEx(NULL,
                         NULL,
                         NULL,
                         MAPI_NEW_SESSION | MAPI_LOGON_UI,
                         &lpSession);

        hr = lpSession->OpenAddressBook(NULL,
                                        NULL,
                                        NULL,
                                        &lpAdrBook);
    
        //Code to open up the folders in the address book   
        hr = lpAdrBook->OpenEntry(0,
                                  NULL,
                                  NULL,
                                  MAPI_DEFERRED_ERRORS,
                                  &ulObjType,
                                  (LPUNKNOWN*)&lpABCont);

        hr = lpABCont->GetHierarchyTable(CONVENIENT_DEPTH | MAPI_DEFERRED_ERRORS, &lpTable);

        //Custom function QueryEntryID takes a IMAPITABLE, Column to search on, Value to Equal, 
        // and returns a LPSPropValue with the EntryID as the result.
        hr = QueryEntryID(lpTable,
                          PR_DISPLAY_NAME,
                          "Global Address List",
                          (LPSPropValue*)&lpProp);
    
        hr = lpAdrBook->OpenEntry(lpProp->Value.bin.cb,
                                  (LPENTRYID)lpProp->Value.bin.lpb,
                                  NULL,
                                  MAPI_MODIFY,
                                  &ulObjType,
                                  (LPUNKNOWN*)&lpABOut);

        hr = lpABOut->GetContentsTable(NULL, &lpContentsTbl);
    
        // Position to the beginning of the contents table.
        hr = lpContentsTbl->SeekRow(BOOKMARK_BEGINNING, 0, NULL) ;

        //Find out how many rows are in the table
        hr = lpContentsTbl->GetRowCount(0, &ulCount);

       hr = lpContentsTbl->SetColumns((SPropTagArray*)&TypeColumns, 0);

       //Use QueryRows to gather the first 50 rows in the ContentsTable
        hr = lpContentsTbl->QueryRows(50, TBL_NOADVANCE, &lpRows);

        //Build a new LPSRowSet using malloc to persist after MAPIUninitialize.
    
        ulSizeOfSet = CbSRowSet(lpRows);
        pv = malloc ((size_t)ulSizeOfSet) ;
        lpHopeRows = (LPSRowSet)pv ;
        memcpy (lpHopeRows, lpRows, ulSizeOfSet) ;

        for(ulSRowCount = 0; ulSRowCount < lpRows->cRows; ulSRowCount++)
    {
             lpHopeRows->aRow[ulSRowCount].lpProps = (LPSPropValue)malloc(lpRows->aRow[ulSRowCount].cValues*sizeof(SPropValue));

        for(ulPropCount = 0;
            ulPropCount < lpRows->aRow[ulSRowCount].cValues;
            ulPropCount++)
        {
            lpOldTempProp = lpRows->aRow[ulSRowCount].lpProps;
            lpNewTempProp = lpHopeRows->aRow[ulSRowCount].lpProps;
            
            //Copy over the LPSPropValue structure for this property
            ulSizeOfSet = sizeof(SPropValue);
            memcpy(&lpNewTempProp[ulPropCount], &lpOldTempProp[ulPropCount], ulSizeOfSet);

            switch(lpOldTempProp[ulPropCount].ulPropTag)
            {
                //If the prop tag is a string or a binary, you must copy the string data over 
                //and change the pointer in the 
                //LPSPropValue to point to the new string location.
                case PR_DISPLAY_NAME:
                    ulTempSizeofBuffer = lstrlen(lpOldTempProp[ulPropCount].Value.lpszA) + 1;
                    pv = malloc(ulTempSizeofBuffer);
                    
                    if (IsBadWritePtr(pv, ulTempSizeofBuffer))
                    {
                        OutputDebugString("Bad Write Location in new LPS Structure.");
                        break;
                    }

                    lstrcpy ((LPSTR)pv, lpOldTempProp[ulPropCount].Value.lpszA) ;
                    lpNewTempProp[ulPropCount].Value.lpszA = (LPSTR)pv;
                    break;

                case PR_ENTRYID:
                    pv = malloc((size_t)lpOldTempProp[ulPropCount].Value.bin.cb);

                    if (IsBadWritePtr(pv, lpOldTempProp[ulPropCount].Value.bin.cb))
                    {
                        OutputDebugString("Bad Write Location in new LPS Structure.");
                        break;
                    }   

                    memcpy ((LPBYTE)pv, lpOldTempProp[ulPropCount].Value.bin.lpb, lpOldTempProp[ulPropCount].Value.bin.cb);
                    lpNewTempProp[ulPropCount].Value.bin.lpb = (LPBYTE)pv;
                    break;

                default:
                    break;
            }
        }
        
    }

//Cleanup:
    
    FreeProws(lpRows);

    if(lpABOut) lpABOut->Release();
    if(lpABCont) lpABCont->Release();
    MAPIFreeBuffer(lpProp);
    if(lpTable) lpTable->Release();
    if(lpAdrBook) lpAdrBook->Release();
    
    if(lpContentsTbl) lpContentsTbl->Release();
    if(lpMDB) lpMDB->Release();
    if(lpSession)
    {
        lpSession->Logoff(NULL, NULL, NULL);
        lpSession->Release();
    }

    MAPIUninitialize();

    //The new SRowSet (lpHopeRows) is still available and can be used and cleaned up when you want.

         printf("lpHopeRows cRows: %d\n", lpHopeRows->cRows);
    
    for(ulSRowCount = 0; ulSRowCount < lpHopeRows->cRows; ulSRowCount++)
    {
        for(ulPropCount = 0;
            ulPropCount < lpHopeRows->aRow[ulSRowCount].cValues;
            ulPropCount++)
        {
            switch(lpHopeRows->aRow[ulSRowCount].lpProps[ulPropCount].ulPropTag)
            {
                case PR_DISPLAY_NAME:
                    printf("DisplayName: %s\n", lpHopeRows->aRow[ulSRowCount].lpProps[ulPropCount].Value.lpszA);
                    break;
                default:
                    break;
            }
        }
        
    }

    return hr;
}

//Custom function QueryEntryID takes a IMAPITABLE, Column to search on, Value to Equal, 
// and returns a LPSPropValue with the EntryID as the result.
HRESULT QueryEntryID(LPMAPITABLE lpTable, ULONG lpDesc, LPSTR lpValue, LPSPropValue* lppProp)
{

    SizedSPropTagArray(2, TypeColumns) =    {2, {lpDesc, PR_ENTRYID}};
    SRestriction srName;
    SPropValue spv;
    ULONG ulCount = 0;
    LPSRowSet pRows = NULL;
    LPSPropValue pspvRet = NULL; 

    HRESULT hr;

    // Restrict the table to just it's name and ID
    hr = lpTable->SetColumns((LPSPropTagArray)&TypeColumns, 0);
    if(FAILED(hr))
    {
        OutputDebugString("SetColumns Failed\n");
        goto cleanup;
    }

    // Get the EntryID of the Address folder that you are going to work with
    // Build a restriction to find the EntryID
    srName.rt = RES_PROPERTY;
    srName.res.resProperty.relop = RELOP_EQ;
    srName.res.resProperty.ulPropTag = lpDesc;
    srName.res.resProperty.lpProp = &spv;
    spv.ulPropTag = lpDesc;
    spv.Value.lpszA = lpValue;  // Name of Template ID you want (passed into function)
    
    // Apply the restriction
    hr = lpTable->Restrict(&srName,0);
    if(FAILED(hr))
    {
        OutputDebugString("Restrict Failed\n");
        goto cleanup;
    }

    // Get the total number of rows returned. Typically, this will be 1.
    hr = lpTable->GetRowCount(0,&ulCount);
    if(FAILED(hr))
    {
        OutputDebugString("GetRowCount Failed\n");
        goto cleanup;
    }

    // Get the row props (trying to get the EntryID)
    hr = lpTable->QueryRows(ulCount,0,&pRows);
    if(FAILED(hr))
    {
        OutputDebugString("QueryRows Failed\n");
        goto cleanup;
    }

    hr = MAPIAllocateBuffer(sizeof(SPropValue), (LPVOID*)&pspvRet);
    if(FAILED(hr))
    {
        OutputDebugString("MAPIAllocateBuffer Failed\n");
        MAPIFreeBuffer(pspvRet);
        goto cleanup;
    }

    hr = MAPIAllocateMore(pRows->aRow[0].lpProps[1].Value.bin.cb, pspvRet, (LPVOID*)&pspvRet->Value.bin.lpb);
    if(FAILED(hr))
    {
        OutputDebugString("MAPIAllocateMore Failed\n");
        MAPIFreeBuffer(pspvRet);
        goto cleanup;
    }

    pspvRet->ulPropTag = pRows->aRow[0].lpProps[1].ulPropTag;
    pspvRet->Value.bin.cb = pRows->aRow[0].lpProps[1].Value.bin.cb;

    memcpy(pspvRet->Value.bin.lpb,
           pRows->aRow[0].lpProps[1].Value.bin.lpb,
           pRows->aRow[0].lpProps[1].Value.bin.cb);
    
    // Get a pointer to the props.
    *lppProp = pspvRet;

cleanup:
    FreeProws(pRows);

    return hr;
}
                


Additional query words: EXTENDED MAPI LPSRowSet MAPIAllocateBuffer MAPIAllocateMore

Keywords: kbhowto kbmsg KB247371