Microsoft KB Archive/247371: Difference between revisions

From BetaArchive Wiki
m (Text replacement - ">" to ">")
m (Text replacement - """ to """)
 
(One intermediate revision by the same user not shown)
Line 57: Line 57:
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>
<pre class="codesample">#include <mapix.h>
#include &quot;mapidefs.h&quot;  
#include "mapidefs.h"  
#include <mapiutil.h>
#include <mapiutil.h>
#include <mapitags.h>
#include <mapitags.h>
Line 69: Line 69:
#include <stdio.h>
#include <stdio.h>


#pragma comment(lib, &quot;mapi32.lib&quot;)
#pragma comment(lib, "mapi32.lib")


HRESULT QueryEntryID(LPMAPITABLE, ULONG, LPSTR, LPSPropValue*);
HRESULT QueryEntryID(LPMAPITABLE, ULONG, LPSTR, LPSPropValue*);
Line 111: Line 111:
                         NULL,
                         NULL,
                         MAPI_NEW_SESSION | MAPI_LOGON_UI,
                         MAPI_NEW_SESSION | MAPI_LOGON_UI,
                         &amp;lpSession);
                         &lpSession);


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


         hr = lpABCont->GetHierarchyTable(CONVENIENT_DEPTH | MAPI_DEFERRED_ERRORS, &amp;lpTable);
         hr = lpABCont->GetHierarchyTable(CONVENIENT_DEPTH | MAPI_DEFERRED_ERRORS, &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 132: Line 132:
         hr = QueryEntryID(lpTable,
         hr = QueryEntryID(lpTable,
                           PR_DISPLAY_NAME,
                           PR_DISPLAY_NAME,
                           &quot;Global Address List&quot;,
                           "Global Address List",
                           (LPSPropValue*)&amp;lpProp);
                           (LPSPropValue*)&lpProp);
      
      
         hr = lpAdrBook->OpenEntry(lpProp->Value.bin.cb,
         hr = lpAdrBook->OpenEntry(lpProp->Value.bin.cb,
Line 139: Line 139:
                                   NULL,
                                   NULL,
                                   MAPI_MODIFY,
                                   MAPI_MODIFY,
                                   &amp;ulObjType,
                                   &ulObjType,
                                   (LPUNKNOWN*)&amp;lpABOut);
                                   (LPUNKNOWN*)&lpABOut);


         hr = lpABOut->GetContentsTable(NULL, &amp;lpContentsTbl);
         hr = lpABOut->GetContentsTable(NULL, &lpContentsTbl);
      
      
         // Position to the beginning of the contents table.
         // Position to the beginning of the contents table.
Line 148: Line 148:


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


       hr = lpContentsTbl->SetColumns((SPropTagArray*)&amp;TypeColumns, 0);
       hr = lpContentsTbl->SetColumns((SPropTagArray*)&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->QueryRows(50, TBL_NOADVANCE, &amp;lpRows);
         hr = lpContentsTbl->QueryRows(50, TBL_NOADVANCE, &lpRows);


         //Build a new LPSRowSet using malloc to persist after MAPIUninitialize.
         //Build a new LPSRowSet using malloc to persist after MAPIUninitialize.
Line 175: Line 175:
             //Copy over the LPSPropValue structure for this property
             //Copy over the LPSPropValue structure for this property
             ulSizeOfSet = sizeof(SPropValue);
             ulSizeOfSet = sizeof(SPropValue);
             memcpy(&amp;lpNewTempProp[ulPropCount], &amp;lpOldTempProp[ulPropCount], ulSizeOfSet);
             memcpy(&lpNewTempProp[ulPropCount], &lpOldTempProp[ulPropCount], ulSizeOfSet);


             switch(lpOldTempProp[ulPropCount].ulPropTag)
             switch(lpOldTempProp[ulPropCount].ulPropTag)
Line 188: Line 188:
                     if (IsBadWritePtr(pv, ulTempSizeofBuffer))
                     if (IsBadWritePtr(pv, ulTempSizeofBuffer))
                     {
                     {
                         OutputDebugString(&quot;Bad Write Location in new LPS Structure.&quot;);
                         OutputDebugString("Bad Write Location in new LPS Structure.");
                         break;
                         break;
                     }
                     }
Line 201: Line 201:
                     if (IsBadWritePtr(pv, lpOldTempProp[ulPropCount].Value.bin.cb))
                     if (IsBadWritePtr(pv, lpOldTempProp[ulPropCount].Value.bin.cb))
                     {
                     {
                         OutputDebugString(&quot;Bad Write Location in new LPS Structure.&quot;);
                         OutputDebugString("Bad Write Location in new LPS Structure.");
                         break;
                         break;
                     }   
                     }   
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->cRows);
         printf("lpHopeRows cRows: %d\n", lpHopeRows->cRows);
      
      
     for(ulSRowCount = 0; ulSRowCount < lpHopeRows->cRows; ulSRowCount++)
     for(ulSRowCount = 0; ulSRowCount < lpHopeRows->cRows; ulSRowCount++)
Line 249: Line 249:
             {
             {
                 case PR_DISPLAY_NAME:
                 case PR_DISPLAY_NAME:
                     printf(&quot;DisplayName: %s\n&quot;, lpHopeRows->aRow[ulSRowCount].lpProps[ulPropCount].Value.lpszA);
                     printf("DisplayName: %s\n", 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->SetColumns((LPSPropTagArray)&amp;TypeColumns, 0);
     hr = lpTable->SetColumns((LPSPropTagArray)&TypeColumns, 0);
     if(FAILED(hr))
     if(FAILED(hr))
     {
     {
         OutputDebugString(&quot;SetColumns Failed\n&quot;);
         OutputDebugString("SetColumns Failed\n");
         goto cleanup;
         goto cleanup;
     }
     }
Line 288: Line 288:
     srName.res.resProperty.relop = RELOP_EQ;
     srName.res.resProperty.relop = RELOP_EQ;
     srName.res.resProperty.ulPropTag = lpDesc;
     srName.res.resProperty.ulPropTag = lpDesc;
     srName.res.resProperty.lpProp = &amp;spv;
     srName.res.resProperty.lpProp = &spv;
     spv.ulPropTag = lpDesc;
     spv.ulPropTag = lpDesc;
     spv.Value.lpszA = lpValue;  // Name of Template ID you want (passed into function)
     spv.Value.lpszA = lpValue;  // Name of Template ID you want (passed into function)
      
      
     // Apply the restriction
     // Apply the restriction
     hr = lpTable->Restrict(&amp;srName,0);
     hr = lpTable->Restrict(&srName,0);
     if(FAILED(hr))
     if(FAILED(hr))
     {
     {
         OutputDebugString(&quot;Restrict Failed\n&quot;);
         OutputDebugString("Restrict Failed\n");
         goto cleanup;
         goto cleanup;
     }
     }


     // 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->GetRowCount(0,&amp;ulCount);
     hr = lpTable->GetRowCount(0,&ulCount);
     if(FAILED(hr))
     if(FAILED(hr))
     {
     {
         OutputDebugString(&quot;GetRowCount Failed\n&quot;);
         OutputDebugString("GetRowCount Failed\n");
         goto cleanup;
         goto cleanup;
     }
     }


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


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


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

Latest revision as of 13:50, 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