/// <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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
_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
Exemplo n.º 4
0
// 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
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
_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
Exemplo n.º 7
0
// 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;
}
Exemplo n.º 9
0
_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;
}
Exemplo n.º 10
0
_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
Exemplo n.º 11
0
// 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