Microsoft KB Archive/247371

= 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.
 * 1) include 
 * 2) include "mapidefs.h"
 * 3) include 
 * 4) include 
 * 5) include 
 * 6) include 


 * 1) define INITGUID
 * 2) include 
 * 3) include 
 * 4) include 
 * 5) include 


 * 1) 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

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.