/// <summary> /// <para name='Name'>AllocAdrList</para> /// <para name='Purpose'>Allocate and AdrList structure</para> /// </summary> /// <param name='ulNumProps'>Number of properties to allocate</param> /// <param name='lpAdrList'>[out]The returned pointer to the AdrList</param> /// <returns>HRESULT</returns> /// <remarks> /// <para name='Notes'>Taken from MFCMapi's MAPIABFunctions.cpp as HrAllocAdrList</para> /// <para name='Author'></para> /// <para name='LastModified'></para> /// </remarks> STDMETHODIMP ZybraxiSoft::CMailbox::AllocAdrList(ULONG ulNumProps, LPADRLIST * lpAdrList) { HRESULT hr = S_OK; LPADRLIST lpLocalAdrList = NULL; // HrAllocAdrList just nulls the out variable // *lpAdrList = NULL; // ...but I think, if it's not null, it should be freed(?) if (*lpAdrList) { FreePadrlist(*lpAdrList); *lpAdrList = NULL; } // Allocate memory for the new SRowSet structure if (SUCCEEDED(hr = MAPIAllocateBuffer( CbNewSRowSet(1), (LPVOID*)&lpLocalAdrList))) { // Zero out our SRowSet memory ZeroMemory(lpLocalAdrList, CbNewSRowSet(1)); // Allocate the memory for the internal SPropValue if (SUCCEEDED(hr = MAPIAllocateBuffer( ulNumProps * sizeof(SPropValue), (LPVOID*)&lpLocalAdrList->aEntries[0].rgPropVals))) { // Zero out our SPropValue if (lpLocalAdrList->aEntries[0].rgPropVals) ZeroMemory(lpLocalAdrList->aEntries[0].rgPropVals, ulNumProps * sizeof(SPropValue)); } else { FATAL("MAPIAllocateBuffer(SPropVal)", hr); FreePadrlist(lpLocalAdrList); } if (SUCCEEDED(hr)) { *lpAdrList = lpLocalAdrList; } else { FreePadrlist(lpLocalAdrList); } } else { FATAL(_T("MAPIAllocateBuffer(SRowSet)"), hr); } return hr; }
HRESULT AddRecipientW(LPMESSAGE lpMessage, ULONG ulRecipientType, LPWSTR szRecipientName){ HRESULT hRes = S_OK; LPADRLIST lpAdrList = NULL; // ModifyRecips takes LPADRLIST LPADRBOOK lpAddrBook = NULL; hRes = HrAllocAdrList(NUM_RECIP_PROPS, &lpAdrList); if (SUCCEEDED(hRes) && lpAdrList) { // Set up the recipient by indicating how many recipients // and how many properties will be set on each recipient. lpAdrList->cEntries = 1; // How many recipients. lpAdrList->aEntries[0].cValues = NUM_RECIP_PROPS; // How many properties per recipient lpAdrList->aEntries[0].rgPropVals[p_PR_DISPLAY_NAME_W].ulPropTag = PR_DISPLAY_NAME_W; lpAdrList->aEntries[0].rgPropVals[p_PR_RECIPIENT_TYPE].ulPropTag = PR_RECIPIENT_TYPE; lpAdrList->aEntries[0].rgPropVals[p_PR_DISPLAY_NAME_W].Value.lpszW = szRecipientName; lpAdrList->aEntries[0].rgPropVals[p_PR_RECIPIENT_TYPE].Value.l = ulRecipientType; // If everything goes right, add the new recipient to the message // object passed into us. hRes = lpMessage->ModifyRecipients(MODRECIP_ADD, lpAdrList); } if (lpAdrList) FreePadrlist(lpAdrList); if (lpAddrBook) lpAddrBook->Release(); return hRes; }
_Check_return_ HRESULT AddRecipient( _In_ LPMAPISESSION lpMAPISession, _In_ LPMESSAGE lpMessage, _In_z_ LPCTSTR szName, ULONG ulRecipientType) { HRESULT hRes = S_OK; LPADRLIST lpAdrList = NULL; // ModifyRecips takes LPADRLIST LPADRBOOK lpAddrBook = NULL; enum { NAME, RECIP, NUM_RECIP_PROPS }; if (!lpMessage || !lpMAPISession) return MAPI_E_INVALID_PARAMETER; EC_MAPI(lpMAPISession->OpenAddressBook( NULL, NULL, NULL, &lpAddrBook)); EC_MAPI(HrAllocAdrList(NUM_RECIP_PROPS, &lpAdrList)); if (lpAdrList) { // Setup the One Time recipient by indicating how many recipients // and how many properties will be set on each recipient. lpAdrList->cEntries = 1; // How many recipients. lpAdrList->aEntries[0].cValues = NUM_RECIP_PROPS; // How many properties per recipient // Set the SPropValue members == the desired values. lpAdrList->aEntries[0].rgPropVals[NAME].ulPropTag = PR_DISPLAY_NAME; lpAdrList->aEntries[0].rgPropVals[NAME].Value.LPSZ = (LPTSTR)szName; lpAdrList->aEntries[0].rgPropVals[RECIP].ulPropTag = PR_RECIPIENT_TYPE; lpAdrList->aEntries[0].rgPropVals[RECIP].Value.l = ulRecipientType; EC_MAPI(lpAddrBook->ResolveName( 0L, fMapiUnicode, NULL, lpAdrList)); // If everything goes right, add the new recipient to the message // object passed into us. EC_MAPI(lpMessage->ModifyRecipients(MODRECIP_ADD, lpAdrList)); EC_MAPI(lpMessage->SaveChanges(KEEP_OPEN_READWRITE)); } if (lpAdrList) FreePadrlist(lpAdrList); if (lpAddrBook) lpAddrBook->Release(); return hRes; } // AddRecipient
// utility function to release ADRLIST entries void CMAPIEx::ReleaseAddressList(LPADRLIST pAddressList) { #ifndef _WIN32_WCE FreePadrlist(pAddressList); #else if(pAddressList) { for(ULONG i=0;i<pAddressList->cEntries;i++) MAPIFreeBuffer(pAddressList->aEntries[i].rgPropVals); MAPIFreeBuffer(pAddressList); } #endif }
HRESULT AddRecipientA(LPMAPISESSION lpMAPISession, LPMESSAGE lpMessage, ULONG ulRecipientType, LPSTR szRecipientName) { HRESULT hRes = S_OK; LPADRLIST lpAdrList = NULL; // ModifyRecips takes LPADRLIST LPADRBOOK lpAddrBook = NULL; if (!lpMessage || !lpMAPISession) return MAPI_E_INVALID_PARAMETER; hRes = lpMAPISession->OpenAddressBook( NULL, NULL, NULL, &lpAddrBook); if (SUCCEEDED(hRes) && lpAddrBook) { hRes = HrAllocAdrList(NUM_RECIP_PROPS, &lpAdrList); if (SUCCEEDED(hRes) && lpAdrList) { // Set up the recipient by indicating how many recipients // and how many properties will be set on each recipient. lpAdrList->cEntries = 1; // How many recipients. lpAdrList->aEntries[0].cValues = NUM_RECIP_PROPS; // How many properties per recipient lpAdrList->aEntries[0].rgPropVals[p_PR_DISPLAY_NAME_W].ulPropTag = PR_DISPLAY_NAME_A; lpAdrList->aEntries[0].rgPropVals[p_PR_RECIPIENT_TYPE].ulPropTag = PR_RECIPIENT_TYPE; lpAdrList->aEntries[0].rgPropVals[p_PR_DISPLAY_NAME_W].Value.lpszA = szRecipientName; lpAdrList->aEntries[0].rgPropVals[p_PR_RECIPIENT_TYPE].Value.l = ulRecipientType; hRes = lpAddrBook->ResolveName( 0L, MAPI_UNICODE, NULL, lpAdrList); if (SUCCEEDED(hRes)) { // If everything goes right, add the new recipient to the message // object passed into us. hRes = lpMessage->ModifyRecipients(MODRECIP_ADD, lpAdrList); } } } if (lpAdrList) FreePadrlist(lpAdrList); if (lpAddrBook) lpAddrBook->Release(); return hRes; }
_Check_return_ HRESULT HrAllocAdrList(ULONG ulNumProps, _Deref_out_opt_ LPADRLIST* lpAdrList) { if (!lpAdrList || ulNumProps > ULONG_MAX / sizeof(SPropValue)) return MAPI_E_INVALID_PARAMETER; HRESULT hRes = S_OK; LPADRLIST lpLocalAdrList = NULL; *lpAdrList = NULL; // Allocate memory for new SRowSet structure. EC_H(MAPIAllocateBuffer(CbNewSRowSet(1), (LPVOID*)&lpLocalAdrList)); if (lpLocalAdrList) { // Zero out allocated memory. ZeroMemory(lpLocalAdrList, CbNewSRowSet(1)); // Allocate memory for SPropValue structure that indicates what // recipient properties will be set. EC_H(MAPIAllocateBuffer( ulNumProps * sizeof(SPropValue), (LPVOID*)&lpLocalAdrList->aEntries[0].rgPropVals)); // Zero out allocated memory. if (lpLocalAdrList->aEntries[0].rgPropVals) ZeroMemory(lpLocalAdrList->aEntries[0].rgPropVals, ulNumProps * sizeof(SPropValue)); if (SUCCEEDED(hRes)) { *lpAdrList = lpLocalAdrList; } else { FreePadrlist(lpLocalAdrList); } } return hRes; } // HrAllocAdrList
// utility function to release ADRLIST entries void CMAPIEx::ReleaseAddressList(LPADRLIST pAddressList) { FreePadrlist(pAddressList); }
/// <summary> /// <para name='Name'>ResolveDisplayName</para> /// <para name='Purpose'>Get an email address from a Display Name</para> /// </summary> /// <param name='szName'>Display Name to resolve</param> /// <param name='szEmailAddress'>[out] Returned email address</param> /// <returns>HRESULT</returns> /// <remarks> /// <para name='Notes'></para> /// <para name='Author'>Kenn Guilstorf</para> /// <para name='LastModified'>28Jan2016</para> /// </remarks> STDMETHODIMP ZybraxiSoft::CMailbox::ResolveDisplayName(TSTRING szName, TSTRING &szEmailAddress) { HRESULT hr = S_OK; LPADRBOOK lpAdrBook = NULL; LPADRLIST lpAdrList = NULL; TSTRING szEX = TSTRING(_T("EX")); bool isExchange = false; enum { prDISPLAY_NAME, NUM_PROPS }; // Check to make sure we have something in szName if (szName.empty() || szName.size() <= 0) { hr = MAPI_E_INVALID_PARAMETER; goto EXIT; } // Log what we're trying to resolve m_log << output::both << level::Informational << "Attempting to resolve '" << szName.c_str() << "'" << endl; // Open the address book // See: https://msdn.microsoft.com/en-us/library/office/cc815381.aspx if (SUCCEEDED(hr = m_lpSession->OpenAddressBook( NULL, // ulUIParam [may be NULL] NULL, // lpInterface [may be NULL; returns IAddrBook:IMAPIProp] NULL, // ulFlags [NULL means no flags] &lpAdrBook))) // lppAdrBook [out] { // Allocate the address list // Note: I like to use 'this' so I know which functions I'm responsible // for if I ever have to work on this... if (SUCCEEDED(hr = this->AllocAdrList( NUM_PROPS, &lpAdrList))) { // Even though we succeeded, do a check to make sure we have // an address list if (lpAdrList) { lpAdrList->cEntries = 1; // only looking for 1 entry lpAdrList->aEntries[0].cValues = NUM_PROPS; // Number of props // Set the SPropValue to whom we're looking for lpAdrList->aEntries[0].rgPropVals[prDISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME; lpAdrList->aEntries[0].rgPropVals[prDISPLAY_NAME].Value.LPSZ = (LPTSTR)szName.c_str(); // Let's try to resolve the name now if (SUCCEEDED(hr = lpAdrBook->ResolveName( 0L, MAPI_UNICODE, NULL, lpAdrList))) { m_log << output::both << level::Informational << "Resolve name yielded " << lpAdrList->aEntries[0].cValues << " properties." << endl; for (UINT i = 0; i < lpAdrList->aEntries[0].cValues; i++) { // Store the property so I don't have to type so much... SPropValue spvCurrent = lpAdrList->aEntries[0].rgPropVals[i]; m_log << output::both << level::Informational << "Found Property '0x" << setfill(_T('0')) << setw(8) << setbase(16) << spvCurrent.ulPropTag << "'"; switch (spvCurrent.ulPropTag) { case PR_ADDRTYPE: if (szEX.compare(spvCurrent.Value.LPSZ) == 0) isExchange = true; break; case PR_DISPLAY_NAME: m_log << ": " << spvCurrent.Value.LPSZ; break; case PR_EMAIL_ADDRESS: m_log << ": " << spvCurrent.Value.LPSZ; szEmailAddress = TSTRING(spvCurrent.Value.LPSZ); break; default: if (((spvCurrent.ulPropTag & 0x1f) == 0x1f) || ((spvCurrent.ulPropTag & 0x1e) == 0x1e)) m_log << ": " << spvCurrent.Value.LPSZ; break; } m_log << endl; } if (!isExchange || (szEmailAddress.empty())) { hr = MAPI_E_NOT_FOUND; goto CLEANUP; } } else { FATAL(_T("lpAdrBook->ResolveName()"), hr); goto CLEANUP; } } } else { FATAL(_T("AllocAdrList()"), hr); goto CLEANUP; } } else { FATAL(_T("OpenAddressBook()"), hr); } CLEANUP: if (lpAdrList) { FreePadrlist(lpAdrList); lpAdrList = NULL; } if (lpAdrBook) { lpAdrBook->Release(); lpAdrBook = NULL; } EXIT: return hr; }
_Check_return_ HRESULT SelectUser(_In_ LPADRBOOK lpAdrBook, HWND hwnd, _Out_opt_ ULONG* lpulObjType, _Deref_out_opt_ LPMAILUSER* lppMailUser) { if (!lpAdrBook || !hwnd || !lppMailUser) return MAPI_E_INVALID_PARAMETER; HRESULT hRes = S_OK; ADRPARM AdrParm = { 0 }; LPADRLIST lpAdrList = NULL; LPSPropValue lpEntryID = NULL; LPMAILUSER lpMailUser = NULL; *lppMailUser = NULL; if (lpulObjType) { *lpulObjType = NULL; } CHAR szTitle[256]; int iRet = NULL; EC_D(iRet, LoadStringA(GetModuleHandle(NULL), IDS_SELECTMAILBOX, szTitle, _countof(szTitle))); AdrParm.ulFlags = DIALOG_MODAL | ADDRESS_ONE | AB_SELECTONLY | AB_RESOLVE; #pragma warning(push) #pragma warning(disable:4616) #pragma warning(disable:6276) AdrParm.lpszCaption = (LPTSTR)szTitle; #pragma warning(pop) EC_H_CANCEL(lpAdrBook->Address( (ULONG_PTR*)&hwnd, &AdrParm, &lpAdrList)); if (lpAdrList) { lpEntryID = PpropFindProp( lpAdrList[0].aEntries->rgPropVals, lpAdrList[0].aEntries->cValues, PR_ENTRYID); if (lpEntryID) { ULONG ulObjType = NULL; EC_H(CallOpenEntry( NULL, lpAdrBook, NULL, NULL, lpEntryID->Value.bin.cb, (LPENTRYID)lpEntryID->Value.bin.lpb, NULL, MAPI_BEST_ACCESS, &ulObjType, (LPUNKNOWN*)&lpMailUser)); if (SUCCEEDED(hRes) && lpMailUser) { *lppMailUser = lpMailUser; } else { if (lpMailUser) { lpMailUser->Release(); } if (lpulObjType) { *lpulObjType = ulObjType; } } } } if (lpAdrList) FreePadrlist(lpAdrList); return hRes; }
_Check_return_ HRESULT AddOneOffAddress( _In_ LPMAPISESSION lpMAPISession, _In_ LPMESSAGE lpMessage, _In_z_ LPCTSTR szDisplayName, _In_z_ LPCTSTR szAddrType, _In_z_ LPCTSTR szEmailAddress, ULONG ulRecipientType) { HRESULT hRes = S_OK; LPADRLIST lpAdrList = NULL; // ModifyRecips takes LPADRLIST LPADRBOOK lpAddrBook = NULL; LPENTRYID lpEID = NULL; enum { NAME, ADDR, EMAIL, RECIP, EID, NUM_RECIP_PROPS }; if (!lpMessage || !lpMAPISession) return MAPI_E_INVALID_PARAMETER; EC_MAPI(lpMAPISession->OpenAddressBook( NULL, NULL, NULL, &lpAddrBook)); EC_MAPI(HrAllocAdrList(NUM_RECIP_PROPS, &lpAdrList)); // Setup the One Time recipient by indicating how many recipients // and how many properties will be set on each recipient. if (SUCCEEDED(hRes) && lpAdrList) { lpAdrList->cEntries = 1; // How many recipients. lpAdrList->aEntries[0].cValues = NUM_RECIP_PROPS; // How many properties per recipient // Set the SPropValue members == the desired values. lpAdrList->aEntries[0].rgPropVals[NAME].ulPropTag = PR_DISPLAY_NAME; lpAdrList->aEntries[0].rgPropVals[NAME].Value.LPSZ = (LPTSTR)szDisplayName; lpAdrList->aEntries[0].rgPropVals[ADDR].ulPropTag = PR_ADDRTYPE; lpAdrList->aEntries[0].rgPropVals[ADDR].Value.LPSZ = (LPTSTR)szAddrType; lpAdrList->aEntries[0].rgPropVals[EMAIL].ulPropTag = PR_EMAIL_ADDRESS; lpAdrList->aEntries[0].rgPropVals[EMAIL].Value.LPSZ = (LPTSTR)szEmailAddress; lpAdrList->aEntries[0].rgPropVals[RECIP].ulPropTag = PR_RECIPIENT_TYPE; lpAdrList->aEntries[0].rgPropVals[RECIP].Value.l = ulRecipientType; lpAdrList->aEntries[0].rgPropVals[EID].ulPropTag = PR_ENTRYID; // Create the One-off address and get an EID for it. EC_MAPI(lpAddrBook->CreateOneOff( lpAdrList->aEntries[0].rgPropVals[NAME].Value.LPSZ, lpAdrList->aEntries[0].rgPropVals[ADDR].Value.LPSZ, lpAdrList->aEntries[0].rgPropVals[EMAIL].Value.LPSZ, fMapiUnicode, &lpAdrList->aEntries[0].rgPropVals[EID].Value.bin.cb, &lpEID)); lpAdrList->aEntries[0].rgPropVals[EID].Value.bin.lpb = (LPBYTE)lpEID; EC_MAPI(lpAddrBook->ResolveName( 0L, fMapiUnicode, NULL, lpAdrList)); // If everything goes right, add the new recipient to the message // object passed into us. EC_MAPI(lpMessage->ModifyRecipients(MODRECIP_ADD, lpAdrList)); EC_MAPI(lpMessage->SaveChanges(KEEP_OPEN_READWRITE)); } MAPIFreeBuffer(lpEID); if (lpAdrList) FreePadrlist(lpAdrList); if (lpAddrBook) lpAddrBook->Release(); return hRes; } // AddOneOffAddress
// Manually resolve a name in the address book and add it to the message _Check_return_ HRESULT ManualResolve( _In_ LPMAPISESSION lpMAPISession, _In_ LPMESSAGE lpMessage, _In_z_ LPCTSTR szName, ULONG PropTagToCompare) { HRESULT hRes = S_OK; ULONG ulObjType = 0; LPADRBOOK lpAdrBook = NULL; LPSRowSet lpABRow = NULL; LPMAPITABLE lpABContainerTable = NULL; LPADRLIST lpAdrList = NULL; LPABCONT lpABContainer = NULL; LPMAPITABLE pTable = NULL; LPSPropValue lpFoundRow = NULL; enum { abcPR_ENTRYID, abcPR_DISPLAY_NAME, abcNUM_COLS }; static const SizedSPropTagArray(abcNUM_COLS, abcCols) = { abcNUM_COLS, PR_ENTRYID, PR_DISPLAY_NAME, }; enum { abPR_ENTRYID, abPR_DISPLAY_NAME, abPR_RECIPIENT_TYPE, abPR_ADDRTYPE, abPR_DISPLAY_TYPE, abPropTagToCompare, abNUM_COLS }; if (!lpMAPISession) return MAPI_E_INVALID_PARAMETER; DebugPrint(DBGGeneric, _T("ManualResolve: Asked to resolve \"%s\"\n"), szName); EC_MAPI(lpMAPISession->OpenAddressBook( NULL, NULL, NULL, &lpAdrBook)); EC_H(GetABContainerTable(lpAdrBook, &lpABContainerTable)); if (lpABContainerTable) { // Restrict the table to the properties that we are interested in. EC_MAPI(lpABContainerTable->SetColumns((LPSPropTagArray)&abcCols, TBL_BATCH)); if (!FAILED(hRes)) for (;;) { hRes = S_OK; FreeProws(lpABRow); lpABRow = NULL; EC_MAPI(lpABContainerTable->QueryRows( 1, NULL, &lpABRow)); if (FAILED(hRes) || !lpABRow || (lpABRow && !lpABRow->cRows)) break; // From this point forward, consider any error an error with the current address book container, so just continue and try the next one. if (PR_ENTRYID == lpABRow->aRow->lpProps[abcPR_ENTRYID].ulPropTag) { DebugPrint(DBGGeneric, _T("ManualResolve: Searching this container\n")); DebugPrintBinary(DBGGeneric, &lpABRow->aRow->lpProps[abcPR_ENTRYID].Value.bin); if (lpABContainer) lpABContainer->Release(); lpABContainer = NULL; EC_H(CallOpenEntry( NULL, lpAdrBook, NULL, NULL, lpABRow->aRow->lpProps[abcPR_ENTRYID].Value.bin.cb, (ENTRYID*)lpABRow->aRow->lpProps[abcPR_ENTRYID].Value.bin.lpb, NULL, NULL, &ulObjType, (LPUNKNOWN*)&lpABContainer)); if (!lpABContainer) continue; DebugPrint(DBGGeneric, _T("ManualResolve: Object opened as 0x%X\n"), ulObjType); if (lpABContainer && ulObjType == MAPI_ABCONT) { if (pTable) pTable->Release(); pTable = NULL; WC_MAPI(lpABContainer->GetContentsTable(fMapiUnicode, &pTable)); if (!pTable) { DebugPrint(DBGGeneric, _T("ManualResolve: Container did not support contents table\n")); if (MAPI_E_NO_SUPPORT == hRes) hRes = S_OK; continue; } MAPIFreeBuffer(lpFoundRow); lpFoundRow = NULL; EC_H(SearchContentsTableForName( pTable, szName, PropTagToCompare, &lpFoundRow)); if (!lpFoundRow) continue; if (lpAdrList) FreePadrlist(lpAdrList); lpAdrList = NULL; // Allocate memory for new Address List structure. EC_H(MAPIAllocateBuffer(CbNewADRLIST(1), (LPVOID*)&lpAdrList)); if (!lpAdrList) continue; ZeroMemory(lpAdrList, CbNewADRLIST(1)); lpAdrList->cEntries = 1; // Allocate memory for SPropValue structure that indicates what // recipient properties will be set. To resolve a name that // already exists in the Address book, this will always be 1. EC_H(MAPIAllocateBuffer( (ULONG)(abNUM_COLS * sizeof(SPropValue)), (LPVOID*)&lpAdrList->aEntries->rgPropVals)); if (!lpAdrList->aEntries->rgPropVals) continue; // TODO: We are setting 5 properties below. If this changes, modify these two lines. ZeroMemory(lpAdrList->aEntries->rgPropVals, 5 * sizeof(SPropValue)); lpAdrList->aEntries->cValues = 5; // Fill out addresslist with required property values. LPSPropValue pProps = lpAdrList->aEntries->rgPropVals; LPSPropValue pProp; // Just a pointer, do not free. pProp = &pProps[abPR_ENTRYID]; pProp->ulPropTag = PR_ENTRYID; EC_H(CopySBinary(&pProp->Value.bin, &lpFoundRow[abPR_ENTRYID].Value.bin, lpAdrList)); pProp = &pProps[abPR_RECIPIENT_TYPE]; pProp->ulPropTag = PR_RECIPIENT_TYPE; pProp->Value.l = MAPI_TO; pProp = &pProps[abPR_DISPLAY_NAME]; pProp->ulPropTag = PR_DISPLAY_NAME; if (!CheckStringProp(&lpFoundRow[abPR_DISPLAY_NAME], PT_TSTRING)) continue; EC_H(CopyString( &pProp->Value.LPSZ, lpFoundRow[abPR_DISPLAY_NAME].Value.LPSZ, lpAdrList)); pProp = &pProps[abPR_ADDRTYPE]; pProp->ulPropTag = PR_ADDRTYPE; if (!CheckStringProp(&lpFoundRow[abPR_ADDRTYPE], PT_TSTRING)) continue; EC_H(CopyString( &pProp->Value.LPSZ, lpFoundRow[abPR_ADDRTYPE].Value.LPSZ, lpAdrList)); pProp = &pProps[abPR_DISPLAY_TYPE]; pProp->ulPropTag = PR_DISPLAY_TYPE; pProp->Value.l = lpFoundRow[abPR_DISPLAY_TYPE].Value.l; EC_MAPI(lpMessage->ModifyRecipients( MODRECIP_ADD, lpAdrList)); if (lpAdrList) FreePadrlist(lpAdrList); lpAdrList = NULL; EC_MAPI(lpMessage->SaveChanges(KEEP_OPEN_READWRITE)); // since we're done with our work, let's get out of here. break; } } } lpABContainerTable->Release(); } FreeProws(lpABRow); MAPIFreeBuffer(lpFoundRow); if (lpAdrList) FreePadrlist(lpAdrList); if (pTable) pTable->Release(); if (lpABContainer) lpABContainer->Release(); if (lpAdrBook) lpAdrBook->Release(); return hRes; } // ManualResolve