You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2094 lines
52 KiB
2094 lines
52 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
abobj.cpp
|
|
|
|
Abstract:
|
|
|
|
Interface to the common address book.
|
|
|
|
Environment:
|
|
|
|
Fax send wizard
|
|
|
|
Revision History:
|
|
|
|
09/02/99 -v-sashab-
|
|
Created it.
|
|
|
|
mm/dd/yy -author-
|
|
description
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <prsht.h>
|
|
#include <tchar.h>
|
|
#include <assert.h>
|
|
#include <mbstring.h>
|
|
|
|
#include <mapix.h>
|
|
|
|
#include "faxui.h"
|
|
#include "abobj.h"
|
|
|
|
|
|
#define PR_EMS_AB_PROXY_ADDRESSES PROP_TAG( PT_MV_TSTRING, 0x800F)
|
|
#define PR_EMS_AB_PROXY_ADDRESSES_A PROP_TAG( PT_MV_STRING8, 0x800F)
|
|
#define PR_EMS_AB_PROXY_ADDRESSES_W PROP_TAG( PT_MV_UNICODE, 0x800F)
|
|
|
|
static SizedSPropTagArray(10, sPropTagsW) =
|
|
{
|
|
10,
|
|
{
|
|
PR_ADDRTYPE_W,
|
|
PR_EMAIL_ADDRESS_W,
|
|
PR_DISPLAY_NAME_W,
|
|
PR_PRIMARY_FAX_NUMBER_W,
|
|
PR_HOME_FAX_NUMBER_W,
|
|
PR_BUSINESS_FAX_NUMBER_W,
|
|
PR_COUNTRY_W,
|
|
PR_OBJECT_TYPE,
|
|
PR_EMS_AB_PROXY_ADDRESSES_W,
|
|
PR_ENTRYID
|
|
}
|
|
};
|
|
|
|
static SizedSPropTagArray(10, sPropTagsA) =
|
|
{
|
|
10,
|
|
{
|
|
PR_ADDRTYPE_A,
|
|
PR_EMAIL_ADDRESS_A,
|
|
PR_DISPLAY_NAME_A,
|
|
PR_PRIMARY_FAX_NUMBER_A,
|
|
PR_HOME_FAX_NUMBER_A,
|
|
PR_BUSINESS_FAX_NUMBER_A,
|
|
PR_COUNTRY_A,
|
|
PR_OBJECT_TYPE,
|
|
PR_EMS_AB_PROXY_ADDRESSES_A,
|
|
PR_ENTRYID
|
|
}
|
|
};
|
|
|
|
HINSTANCE CCommonAbObj::m_hInstance = NULL;
|
|
|
|
|
|
/*
|
|
Comparison operator 'less'
|
|
Compare two PRECIPIENT by recipient's name and fax number
|
|
*/
|
|
bool
|
|
CRecipCmp::operator()(
|
|
const PRECIPIENT pcRecipient1,
|
|
const PRECIPIENT pcRecipient2) const
|
|
{
|
|
bool bRes = false;
|
|
int nFaxNumberCpm = 0;
|
|
|
|
if(!pcRecipient1 ||
|
|
!pcRecipient2 ||
|
|
!pcRecipient1->pAddress ||
|
|
!pcRecipient2->pAddress)
|
|
{
|
|
assert(false);
|
|
return bRes;
|
|
}
|
|
|
|
nFaxNumberCpm = _tcscmp(pcRecipient1->pAddress, pcRecipient2->pAddress);
|
|
|
|
if(nFaxNumberCpm < 0)
|
|
{
|
|
bRes = true;
|
|
}
|
|
else if(nFaxNumberCpm == 0)
|
|
{
|
|
//
|
|
// The fax numbers are same
|
|
// lets compare the names
|
|
//
|
|
if(pcRecipient1->pName && pcRecipient2->pName)
|
|
{
|
|
bRes = (_tcsicmp(pcRecipient1->pName, pcRecipient2->pName) < 0);
|
|
}
|
|
else
|
|
{
|
|
bRes = (pcRecipient1->pName < pcRecipient2->pName);
|
|
}
|
|
}
|
|
|
|
return bRes;
|
|
|
|
} // CRecipCmp::operator()
|
|
|
|
|
|
CCommonAbObj::CCommonAbObj(HINSTANCE hInstance) :
|
|
m_lpAdrBook(NULL),
|
|
m_lpMailUser(NULL),
|
|
m_bUnicode(FALSE)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CCommonAbObj class
|
|
|
|
Arguments:
|
|
|
|
hInstance - Instance handle
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
m_hInstance = hInstance;
|
|
|
|
} // CCommonAbObj::CCommonAbObj()
|
|
|
|
CCommonAbObj::~CCommonAbObj()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CCommonAbObj class
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
BOOL
|
|
CCommonAbObj::Address(
|
|
HWND hWnd,
|
|
PRECIPIENT pOldRecipList,
|
|
PRECIPIENT* ppNewRecipList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Bring up the address book UI. Prepopulate the to box with the entries in
|
|
pRecipient. Return the modified entries in ppNewRecip.
|
|
|
|
Arguments:
|
|
|
|
hWnd - window handle to parent window
|
|
pOldRecipList - list of recipients to look up
|
|
ppNewRecipList - list of new/modified recipients
|
|
|
|
Return Value:
|
|
|
|
TRUE if all recipients had a fax number.
|
|
FALSE if one or more of them didn't.
|
|
|
|
--*/
|
|
{
|
|
ADRPARM AdrParms = { 0 };
|
|
HRESULT hr;
|
|
DWORD i;
|
|
DWORD nRecips;
|
|
PRECIPIENT tmpRecipient;
|
|
ULONG DestComps[1] = { MAPI_TO };
|
|
DWORD cDropped = 0;
|
|
DWORD dwRes = ERROR_SUCCESS;
|
|
TCHAR tszCaption[MAX_PATH] = {0};
|
|
|
|
nRecips = 0;
|
|
tmpRecipient = pOldRecipList;
|
|
|
|
m_hWnd = hWnd;
|
|
|
|
//
|
|
// count recipients and set up initial address list
|
|
//
|
|
while (tmpRecipient)
|
|
{
|
|
nRecips++;
|
|
tmpRecipient = (PRECIPIENT) tmpRecipient->pNext;
|
|
}
|
|
|
|
//
|
|
// Allocate address list
|
|
//
|
|
m_lpAdrList = NULL;
|
|
if (nRecips > 0)
|
|
{
|
|
hr = ABAllocateBuffer( CbNewADRLIST( nRecips ), (LPVOID *) &m_lpAdrList );
|
|
if(!m_lpAdrList)
|
|
{
|
|
goto exit;
|
|
}
|
|
ZeroMemory(m_lpAdrList, CbNewADRLIST( nRecips ));
|
|
|
|
m_lpAdrList->cEntries = nRecips;
|
|
}
|
|
|
|
//
|
|
// Allocate SPropValue arrays for each address entry
|
|
//
|
|
for (i = 0, tmpRecipient = pOldRecipList; i < nRecips; i++, tmpRecipient = tmpRecipient->pNext)
|
|
{
|
|
if(!GetRecipientProps(tmpRecipient,
|
|
&(m_lpAdrList->aEntries[i].rgPropVals),
|
|
&(m_lpAdrList->aEntries[i].cValues)))
|
|
{
|
|
goto error;
|
|
}
|
|
|
|
} // for
|
|
|
|
if(GetAddrBookCaption(tszCaption, ARR_SIZE(tszCaption)))
|
|
{
|
|
AdrParms.lpszCaption = tszCaption;
|
|
}
|
|
|
|
AdrParms.cDestFields = 1;
|
|
AdrParms.ulFlags = StrCoding() | DIALOG_MODAL | AB_RESOLVE;
|
|
AdrParms.nDestFieldFocus = 0;
|
|
AdrParms.lpulDestComps = DestComps;
|
|
|
|
//
|
|
// Bring up the address book UI
|
|
//
|
|
hr = m_lpAdrBook->Address((ULONG_PTR*)&hWnd,
|
|
&AdrParms,
|
|
&m_lpAdrList);
|
|
|
|
//
|
|
// IAddrBook::Address returns always S_OK (according to MSDN, July 1999), but ...
|
|
//
|
|
if (FAILED (hr) || !m_lpAdrList || m_lpAdrList->cEntries == 0)
|
|
{
|
|
//
|
|
// in this case the user pressed cancel, so we skip resolving
|
|
// any of our addresses that aren't listed in the AB
|
|
//
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
if (m_lpAdrList)
|
|
{
|
|
m_lpMailUser = NULL;
|
|
|
|
try
|
|
{
|
|
m_setRecipients.clear();
|
|
}
|
|
catch (std::bad_alloc&)
|
|
{
|
|
goto error;
|
|
}
|
|
|
|
for (i = cDropped = 0; i < m_lpAdrList->cEntries; i++)
|
|
{
|
|
LPADRENTRY lpAdrEntry = &m_lpAdrList->aEntries[i];
|
|
|
|
dwRes = InterpretAddress(lpAdrEntry->rgPropVals,
|
|
lpAdrEntry->cValues,
|
|
ppNewRecipList,
|
|
pOldRecipList);
|
|
if(ERROR_SUCCESS == dwRes)
|
|
{
|
|
continue;
|
|
}
|
|
else if(ERROR_INVALID_DATA == dwRes)
|
|
{
|
|
++cDropped;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
} // for
|
|
|
|
error:
|
|
if(m_lpMailUser)
|
|
{
|
|
m_lpMailUser->Release();
|
|
m_lpMailUser = NULL;
|
|
}
|
|
|
|
//
|
|
// Clean up
|
|
//
|
|
for (ULONG iEntry = 0; iEntry < m_lpAdrList->cEntries; ++iEntry)
|
|
{
|
|
if(m_lpAdrList->aEntries[iEntry].rgPropVals)
|
|
{
|
|
ABFreeBuffer(m_lpAdrList->aEntries[iEntry].rgPropVals);
|
|
}
|
|
}
|
|
ABFreeBuffer(m_lpAdrList);
|
|
m_lpAdrList = NULL;
|
|
|
|
} // if (m_lpAdrList)
|
|
|
|
m_hWnd = NULL;
|
|
|
|
return cDropped == 0;
|
|
|
|
} // CCommonAbObj::Address
|
|
|
|
|
|
BOOL
|
|
CCommonAbObj::GetRecipientProps(
|
|
PRECIPIENT pRecipient,
|
|
LPSPropValue* pMapiProps,
|
|
DWORD* pdwPropsNum
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocate SPropValue array and fill it with recipient info
|
|
According to MSDN "Managing Memory for ADRLIST and SRowSet Structures"
|
|
|
|
Arguments:
|
|
|
|
pRecipient - [in] recipient info struct
|
|
pMapiProps - [out] allocated SPropValue array
|
|
pdwPropsNum - [out] SPropValue array size
|
|
|
|
Return Value:
|
|
|
|
TRUE if success
|
|
FALSE otherwize
|
|
|
|
--*/
|
|
{
|
|
BOOL bRes = FALSE;
|
|
|
|
if(!pRecipient || !pMapiProps || !pdwPropsNum)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT hr;
|
|
LPTSTR pName = NULL;
|
|
DWORD dwNameSize=0; // size of pName
|
|
LPTSTR pAddress = NULL;
|
|
DWORD dwAddressSize=0; // size of pAddress
|
|
LPENTRYID lpEntryId = NULL;
|
|
ULONG cbEntryId = 0; // size of lpEntryId
|
|
UINT ucPropertiesNum = pRecipient->bFromAddressBook ? 5 : 4;
|
|
|
|
enum FaxMapiProp { FXS_DISPLAY_NAME,
|
|
FXS_RECIPIENT_TYPE,
|
|
FXS_PRIMARY_FAX_NUMBER,
|
|
FXS_ENTRYID,
|
|
FXS_OBJECT_TYPE
|
|
};
|
|
|
|
|
|
//
|
|
// Convert strings to the address book encoding
|
|
//
|
|
if(pRecipient->pAddress)
|
|
{
|
|
pAddress = StrToAddrBk(pRecipient->pAddress, &dwAddressSize);
|
|
if(!pAddress)
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if(pRecipient->pName)
|
|
{
|
|
pName = StrToAddrBk(pRecipient->pName, &dwNameSize);
|
|
if(!pName)
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get entry ID
|
|
//
|
|
if (pRecipient->bFromAddressBook)
|
|
{
|
|
assert(pRecipient->lpEntryId);
|
|
lpEntryId = (LPENTRYID)pRecipient->lpEntryId;
|
|
cbEntryId = pRecipient->cbEntryId;
|
|
}
|
|
else
|
|
{
|
|
LPTSTR pAddrType = NULL;
|
|
if(!(pAddrType = StrToAddrBk(TEXT("FAX"))))
|
|
{
|
|
goto exit;
|
|
}
|
|
hr = m_lpAdrBook->CreateOneOff(pName,
|
|
pAddrType,
|
|
pAddress,
|
|
StrCoding(),
|
|
&cbEntryId,
|
|
&lpEntryId);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
MemFree(pAddrType);
|
|
}
|
|
|
|
//
|
|
// Allocate MAPI prop array
|
|
//
|
|
LPSPropValue mapiProps = NULL;
|
|
|
|
DWORD dwPropArrSize = sizeof( SPropValue ) * ucPropertiesNum;
|
|
DWORD dwPropSize = dwPropArrSize + dwAddressSize + dwNameSize + cbEntryId;
|
|
|
|
hr = ABAllocateBuffer( dwPropSize, (LPVOID *) &mapiProps );
|
|
if(!mapiProps)
|
|
{
|
|
goto exit;
|
|
}
|
|
ZeroMemory(mapiProps, dwPropSize);
|
|
|
|
//
|
|
// Set memory pointer to the end of the SPropValue prop array
|
|
//
|
|
LPBYTE pMem = (LPBYTE)mapiProps;
|
|
pMem += dwPropArrSize;
|
|
|
|
//
|
|
// Copy fax number
|
|
//
|
|
if(dwAddressSize)
|
|
{
|
|
CopyMemory(pMem, pAddress, dwAddressSize);
|
|
if(m_bUnicode)
|
|
{
|
|
mapiProps[FXS_PRIMARY_FAX_NUMBER].Value.lpszW = (LPWSTR)pMem;
|
|
}
|
|
else
|
|
{
|
|
mapiProps[FXS_PRIMARY_FAX_NUMBER].Value.lpszA = (LPSTR)pMem;
|
|
}
|
|
pMem += dwAddressSize;
|
|
}
|
|
mapiProps[FXS_PRIMARY_FAX_NUMBER].ulPropTag = m_bUnicode ? PR_PRIMARY_FAX_NUMBER_W : PR_PRIMARY_FAX_NUMBER_A;
|
|
|
|
//
|
|
// Copy display name
|
|
//
|
|
if(dwNameSize)
|
|
{
|
|
CopyMemory(pMem, pName, dwNameSize);
|
|
if(m_bUnicode)
|
|
{
|
|
mapiProps[FXS_DISPLAY_NAME].Value.lpszW = (LPWSTR)pMem;
|
|
}
|
|
else
|
|
{
|
|
mapiProps[FXS_DISPLAY_NAME].Value.lpszA = (LPSTR)pMem;
|
|
}
|
|
pMem += dwNameSize;
|
|
}
|
|
mapiProps[FXS_DISPLAY_NAME].ulPropTag = m_bUnicode ? PR_DISPLAY_NAME_W : PR_DISPLAY_NAME_A;
|
|
|
|
//
|
|
// Copy entry ID
|
|
//
|
|
if(cbEntryId)
|
|
{
|
|
CopyMemory(pMem, lpEntryId, cbEntryId);
|
|
mapiProps[FXS_ENTRYID].Value.bin.lpb = (LPBYTE)pMem;
|
|
}
|
|
mapiProps[FXS_ENTRYID].ulPropTag = PR_ENTRYID;
|
|
mapiProps[FXS_ENTRYID].Value.bin.cb = cbEntryId;
|
|
|
|
//
|
|
// Recipient type
|
|
//
|
|
mapiProps[FXS_RECIPIENT_TYPE].ulPropTag = PR_RECIPIENT_TYPE;
|
|
mapiProps[FXS_RECIPIENT_TYPE].Value.l = MAPI_TO;
|
|
|
|
|
|
//
|
|
// Object type
|
|
//
|
|
if (pRecipient->bFromAddressBook)
|
|
{
|
|
mapiProps[FXS_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE;
|
|
mapiProps[FXS_OBJECT_TYPE].Value.l = MAPI_MAILUSER;
|
|
}
|
|
|
|
|
|
*pdwPropsNum = ucPropertiesNum;
|
|
*pMapiProps = mapiProps;
|
|
|
|
bRes = TRUE;
|
|
|
|
exit:
|
|
|
|
MemFree(pName);
|
|
MemFree(pAddress);
|
|
|
|
if (!pRecipient->bFromAddressBook && lpEntryId)
|
|
{
|
|
ABFreeBuffer(lpEntryId);
|
|
}
|
|
|
|
return bRes;
|
|
|
|
} // CCommonAbObj::GetRecipientProps
|
|
|
|
LPTSTR
|
|
CCommonAbObj::AddressEmail(
|
|
HWND hWnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Bring up the address book UI. Returns an E-mail address.
|
|
|
|
Arguments:
|
|
|
|
hWnd - window handle to parent window
|
|
|
|
Return Value:
|
|
|
|
A choosen E-mail address.
|
|
NULL otherwise.
|
|
|
|
--*/
|
|
{
|
|
ADRPARM AdrParms = { 0 };
|
|
HRESULT hr;
|
|
LPTSTR lptstrEmailAddress = NULL;
|
|
TCHAR tszCaption[MAX_PATH] = {0};
|
|
|
|
m_hWnd = hWnd;
|
|
|
|
m_lpAdrList = NULL;
|
|
|
|
AdrParms.ulFlags = StrCoding() | DIALOG_MODAL | ADDRESS_ONE | AB_RESOLVE ;
|
|
|
|
if(GetAddrBookCaption(tszCaption, ARR_SIZE(tszCaption)))
|
|
{
|
|
AdrParms.lpszCaption = tszCaption;
|
|
}
|
|
|
|
//
|
|
// Bring up the address book UI
|
|
//
|
|
hr = m_lpAdrBook->Address((ULONG_PTR *) &hWnd, &AdrParms, &m_lpAdrList);
|
|
|
|
//
|
|
// IAddrBook::Address returns always S_OK (according to MSDN, July 1999), but ...
|
|
//
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (!m_lpAdrList)
|
|
{
|
|
assert(m_lpAdrList->cEntries==1);
|
|
}
|
|
|
|
if (m_lpAdrList && (m_lpAdrList->cEntries != 0) )
|
|
{
|
|
LPADRENTRY lpAdrEntry = &m_lpAdrList->aEntries[0];
|
|
|
|
lptstrEmailAddress = InterpretEmailAddress( lpAdrEntry->rgPropVals, lpAdrEntry->cValues);
|
|
|
|
ABFreeBuffer(m_lpAdrList->aEntries[0].rgPropVals);
|
|
ABFreeBuffer(m_lpAdrList);
|
|
|
|
m_lpAdrList = NULL;
|
|
}
|
|
|
|
m_hWnd = NULL;
|
|
|
|
return lptstrEmailAddress;
|
|
|
|
} // CCommonAbObj::AddressEmail
|
|
|
|
DWORD
|
|
CCommonAbObj::InterpretAddress(
|
|
LPSPropValue SPropVal,
|
|
ULONG cValues,
|
|
PRECIPIENT *ppNewRecipList,
|
|
PRECIPIENT pOldRecipList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Interpret the address book entry represented by SPropVal.
|
|
|
|
Arguments:
|
|
|
|
SPropVal - Property values for address book entry.
|
|
cValues - number of property values
|
|
ppNewRecip - new recipient list
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - if all of the entries have a fax number.
|
|
ERROR_CANCELLED - the operation was canceled by user
|
|
ERROR_INVALID_DATA - otherwise.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwRes = ERROR_INVALID_DATA;
|
|
LPSPropValue lpSPropVal;
|
|
|
|
RECIPIENT NewRecipient = {0};
|
|
|
|
//
|
|
// get the object type
|
|
//
|
|
lpSPropVal = FindProp( SPropVal, cValues, PR_OBJECT_TYPE );
|
|
|
|
if (lpSPropVal)
|
|
{
|
|
//
|
|
// If the object is a mail user, get the fax numbers and add the recipient
|
|
// to the list. If the object is a distribtion list, process it.
|
|
//
|
|
|
|
switch (lpSPropVal->Value.l)
|
|
{
|
|
case MAPI_MAILUSER:
|
|
|
|
dwRes = GetRecipientInfo(SPropVal,
|
|
cValues,
|
|
&NewRecipient,
|
|
pOldRecipList);
|
|
if(ERROR_SUCCESS == dwRes)
|
|
{
|
|
dwRes = AddRecipient(ppNewRecipList,
|
|
&NewRecipient,
|
|
TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
case MAPI_DISTLIST:
|
|
|
|
dwRes = InterpretDistList( SPropVal,
|
|
cValues,
|
|
ppNewRecipList,
|
|
pOldRecipList);
|
|
}
|
|
|
|
return dwRes;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// If there is no object type then this is valid entry that we queried on that went unresolved.
|
|
// We know that there is a fax number so add it.
|
|
//
|
|
if(GetOneOffRecipientInfo( SPropVal,
|
|
cValues,
|
|
&NewRecipient,
|
|
pOldRecipList))
|
|
{
|
|
dwRes = AddRecipient(ppNewRecipList,
|
|
&NewRecipient,
|
|
FALSE);
|
|
}
|
|
}
|
|
|
|
return dwRes;
|
|
|
|
} // CCommonAbObj::InterpretAddress
|
|
|
|
LPTSTR
|
|
CCommonAbObj::InterpretEmailAddress(
|
|
LPSPropValue SPropVal,
|
|
ULONG cValues
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Interpret the address book entry represented by SPropVal.
|
|
|
|
Arguments:
|
|
|
|
SPropVal - Property values for address book entry.
|
|
cValues - number of property values
|
|
|
|
Return Value:
|
|
|
|
A choosen E-mail address
|
|
NULL otherwise.
|
|
|
|
--*/
|
|
{
|
|
LPSPropValue lpSPropVal;
|
|
LPTSTR lptstrEmailAddress = NULL;
|
|
BOOL rVal = FALSE;
|
|
TCHAR tszBuffer[MAX_STRING_LEN];
|
|
//
|
|
// get the object type
|
|
//
|
|
lpSPropVal = FindProp( SPropVal, cValues, PR_OBJECT_TYPE );
|
|
|
|
if(!lpSPropVal)
|
|
{
|
|
assert(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
if (lpSPropVal->Value.l == MAPI_MAILUSER)
|
|
{
|
|
lptstrEmailAddress = GetEmail( SPropVal, cValues);
|
|
|
|
return lptstrEmailAddress;
|
|
}
|
|
else
|
|
{
|
|
if (!::LoadString((HINSTANCE )m_hInstance, IDS_ERROR_RECEIPT_DL,tszBuffer, MAX_STRING_LEN))
|
|
{
|
|
assert(FALSE);
|
|
}
|
|
else
|
|
{
|
|
AlignedMessageBox( m_hWnd, tszBuffer, NULL, MB_ICONSTOP | MB_OK);
|
|
}
|
|
}
|
|
|
|
return lptstrEmailAddress;
|
|
|
|
} // CCommonAbObj::InterpretEmailAddress
|
|
|
|
|
|
DWORD
|
|
CCommonAbObj::InterpretDistList(
|
|
LPSPropValue SPropVal,
|
|
ULONG cValues,
|
|
PRECIPIENT* ppNewRecipList,
|
|
PRECIPIENT pOldRecipList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process a distribution list.
|
|
|
|
Arguments:
|
|
|
|
SPropVal - Property values for distribution list.
|
|
cValues - Number of properties.
|
|
ppNewRecipList - New recipient list.
|
|
pOldRecipList - Old recipient list.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - if all of the entries have a fax number.
|
|
ERROR_CANCELLED - the operation was canceled by user
|
|
ERROR_INVALID_DATA - otherwise.
|
|
|
|
--*/
|
|
|
|
#define EXIT_IF_FAILED(hr) { if (FAILED(hr)) goto ExitDistList; }
|
|
|
|
{
|
|
LPSPropValue lpPropVals;
|
|
LPSRowSet pRows = NULL;
|
|
LPDISTLIST lpMailDistList = NULL;
|
|
LPMAPITABLE pMapiTable = NULL;
|
|
ULONG ulObjType, cRows;
|
|
HRESULT hr;
|
|
DWORD dwEntriesSuccessfullyProcessed = 0;
|
|
DWORD dwRes = ERROR_INVALID_DATA;
|
|
|
|
lpPropVals = FindProp( SPropVal, cValues, PR_ENTRYID );
|
|
|
|
if (lpPropVals)
|
|
{
|
|
LPENTRYID lpEntryId = (LPENTRYID) lpPropVals->Value.bin.lpb;
|
|
DWORD cbEntryId = lpPropVals->Value.bin.cb;
|
|
//
|
|
// Open the recipient entry
|
|
//
|
|
hr = m_lpAdrBook->OpenEntry(
|
|
cbEntryId,
|
|
lpEntryId,
|
|
(LPCIID) NULL,
|
|
0,
|
|
&ulObjType,
|
|
(LPUNKNOWN *) &lpMailDistList
|
|
);
|
|
|
|
EXIT_IF_FAILED(hr);
|
|
//
|
|
// Get the contents table of the address entry
|
|
//
|
|
hr = lpMailDistList->GetContentsTable(StrCoding(),
|
|
&pMapiTable);
|
|
EXIT_IF_FAILED(hr);
|
|
//
|
|
// Limit the query to only the properties we're interested in
|
|
//
|
|
hr = pMapiTable->SetColumns(m_bUnicode ? (LPSPropTagArray)&sPropTagsW : (LPSPropTagArray)&sPropTagsA, 0);
|
|
EXIT_IF_FAILED(hr);
|
|
//
|
|
// Get the total number of rows
|
|
//
|
|
hr = pMapiTable->GetRowCount(0, &cRows);
|
|
EXIT_IF_FAILED(hr);
|
|
//
|
|
// Get the individual entries of the distribution list
|
|
//
|
|
hr = pMapiTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
|
|
EXIT_IF_FAILED(hr);
|
|
|
|
hr = pMapiTable->QueryRows(cRows, 0, &pRows);
|
|
EXIT_IF_FAILED(hr);
|
|
|
|
hr = S_OK;
|
|
|
|
if (pRows && pRows->cRows)
|
|
{
|
|
//
|
|
// Handle each entry of the distribution list in turn:
|
|
// for simple entries, call InterpretAddress
|
|
// for embedded distribution list, call this function recursively
|
|
//
|
|
for (cRows = 0; cRows < pRows->cRows; cRows++)
|
|
{
|
|
LPSPropValue lpProps = pRows->aRow[cRows].lpProps;
|
|
ULONG cRowValues = pRows->aRow[cRows].cValues;
|
|
|
|
lpPropVals = FindProp( lpProps, cRowValues, PR_OBJECT_TYPE );
|
|
|
|
if (lpPropVals)
|
|
{
|
|
switch (lpPropVals->Value.l)
|
|
{
|
|
case MAPI_MAILUSER:
|
|
{
|
|
dwRes = InterpretAddress( lpProps,
|
|
cRowValues,
|
|
ppNewRecipList,
|
|
pOldRecipList);
|
|
if (ERROR_SUCCESS == dwRes)
|
|
{
|
|
dwEntriesSuccessfullyProcessed++;
|
|
}
|
|
break;
|
|
}
|
|
case MAPI_DISTLIST:
|
|
{
|
|
dwRes = InterpretDistList( lpProps,
|
|
cRowValues,
|
|
ppNewRecipList,
|
|
pOldRecipList);
|
|
if (ERROR_SUCCESS == dwRes)
|
|
{
|
|
dwEntriesSuccessfullyProcessed++;
|
|
}
|
|
break;
|
|
}
|
|
} // End of switch
|
|
} // End of property
|
|
} // End of properties loop
|
|
} // End of row
|
|
} // End of values
|
|
|
|
ExitDistList:
|
|
//
|
|
// Perform necessary clean up before returning to caller
|
|
//
|
|
if (pRows)
|
|
{
|
|
for (cRows = 0; cRows < pRows->cRows; cRows++)
|
|
{
|
|
ABFreeBuffer(pRows->aRow[cRows].lpProps);
|
|
}
|
|
ABFreeBuffer(pRows);
|
|
}
|
|
|
|
if (pMapiTable)
|
|
{
|
|
pMapiTable->Release();
|
|
}
|
|
|
|
if (lpMailDistList)
|
|
{
|
|
lpMailDistList->Release();
|
|
}
|
|
//
|
|
// We only care if we successfully processed at least one object.
|
|
// Return ERROR_SUCCESS if we did.
|
|
//
|
|
return dwEntriesSuccessfullyProcessed ? ERROR_SUCCESS : dwRes;
|
|
|
|
} // CCommonAbObj::InterpretDistList
|
|
|
|
|
|
INT_PTR
|
|
CALLBACK
|
|
ChooseFaxNumberDlgProc(
|
|
HWND hDlg,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dialog proc for choose fax number dialog.
|
|
|
|
Arguments:
|
|
|
|
lParam - pointer to PickFax structure.
|
|
|
|
Return Value:
|
|
|
|
Control id of selection.
|
|
|
|
--*/
|
|
|
|
{
|
|
PPICKFAX pPickFax = (PPICKFAX) lParam;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
|
|
TCHAR szTitle[MAX_PATH] = {0};
|
|
TCHAR szFormat[MAX_PATH] = {0};
|
|
|
|
if(LoadString(CCommonAbObj::m_hInstance,
|
|
IDS_CHOOSE_FAX_NUMBER,
|
|
szFormat,
|
|
MAX_PATH-1))
|
|
{
|
|
_sntprintf(szTitle, MAX_PATH-1, szFormat, pPickFax->DisplayName);
|
|
SetDlgItemText(hDlg, IDC_DISPLAY_NAME, szTitle);
|
|
}
|
|
else
|
|
{
|
|
assert(FALSE);
|
|
}
|
|
|
|
if(pPickFax->BusinessFax)
|
|
{
|
|
SetDlgItemText(hDlg, IDC_BUSINESS_FAX_NUM, pPickFax->BusinessFax);
|
|
CheckDlgButton(hDlg, IDC_BUSINESS_FAX, BST_CHECKED);
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BUSINESS_FAX), FALSE);
|
|
}
|
|
|
|
if(pPickFax->HomeFax)
|
|
{
|
|
SetDlgItemText(hDlg, IDC_HOME_FAX_NUM, pPickFax->HomeFax);
|
|
|
|
if(!pPickFax->BusinessFax)
|
|
{
|
|
CheckDlgButton(hDlg, IDC_HOME_FAX, BST_CHECKED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_HOME_FAX), FALSE);
|
|
}
|
|
|
|
if(pPickFax->OtherFax)
|
|
{
|
|
SetDlgItemText(hDlg, IDC_OTHER_FAX_NUM, pPickFax->OtherFax);
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_OTHER_FAX), FALSE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
DWORD dwRes;
|
|
if(IsDlgButtonChecked( hDlg, IDC_BUSINESS_FAX ))
|
|
{
|
|
dwRes = IDC_BUSINESS_FAX;
|
|
}
|
|
else if(IsDlgButtonChecked( hDlg, IDC_HOME_FAX ))
|
|
{
|
|
dwRes = IDC_HOME_FAX;
|
|
}
|
|
else
|
|
{
|
|
dwRes = IDC_OTHER_FAX;
|
|
}
|
|
|
|
EndDialog( hDlg, dwRes);
|
|
return TRUE;
|
|
|
|
case IDCANCEL:
|
|
EndDialog( hDlg, IDCANCEL);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
} // ChooseFaxNumberDlgProc
|
|
|
|
PRECIPIENT
|
|
CCommonAbObj::FindRecipient(
|
|
PRECIPIENT pRecipient,
|
|
PRECIPIENT pRecipList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Find recipient (pRecipient) in the recipient list (pRecipList)
|
|
by recipient name and fax number
|
|
|
|
Arguments:
|
|
|
|
pRecipList - pointer to recipient list
|
|
pRecipient - pointer to recipient data
|
|
|
|
Return Value:
|
|
|
|
pointer to RECIPIENT structure if found
|
|
NULL - otherwise.
|
|
|
|
--*/
|
|
{
|
|
if(!pRecipient || !pRecipList || !pRecipient->pName || !pRecipient->pAddress)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
while(pRecipList)
|
|
{
|
|
if(pRecipList->pName && pRecipList->pAddress &&
|
|
!_tcscmp(pRecipList->pName, pRecipient->pName) &&
|
|
!_tcscmp(pRecipList->pAddress, pRecipient->pAddress))
|
|
{
|
|
return pRecipList;
|
|
}
|
|
pRecipList = pRecipList->pNext;
|
|
}
|
|
|
|
return NULL;
|
|
|
|
} // CCommonAbObj::FindRecipient
|
|
|
|
PRECIPIENT
|
|
CCommonAbObj::FindRecipient(
|
|
PRECIPIENT pRecipList,
|
|
PICKFAX* pPickFax
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Find recipient (pPickFax) in the recipient list (pRecipList)
|
|
by recipient name and fax number
|
|
|
|
Arguments:
|
|
|
|
pRecipList - pointer to recipient list
|
|
pPickFax - pointer to recipient data
|
|
|
|
Return Value:
|
|
|
|
pointer to RECIPIENT structure if found
|
|
NULL - otherwise.
|
|
|
|
--*/
|
|
{
|
|
if(!pRecipList || !pPickFax || !pPickFax->DisplayName)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
while(pRecipList)
|
|
{
|
|
if(pRecipList->pName && pRecipList->pAddress &&
|
|
!_tcscmp(pRecipList->pName, pPickFax->DisplayName))
|
|
{
|
|
if((pPickFax->BusinessFax &&
|
|
!_tcscmp(pRecipList->pAddress, pPickFax->BusinessFax)) ||
|
|
(pPickFax->HomeFax &&
|
|
!_tcscmp(pRecipList->pAddress, pPickFax->HomeFax)) ||
|
|
(pPickFax->OtherFax &&
|
|
!_tcscmp(pRecipList->pAddress, pPickFax->OtherFax)))
|
|
{
|
|
return pRecipList;
|
|
}
|
|
}
|
|
|
|
pRecipList = pRecipList->pNext;
|
|
}
|
|
|
|
return NULL;
|
|
|
|
} // CCommonAbObj::FindRecipient
|
|
|
|
|
|
BOOL
|
|
CCommonAbObj::StrPropOk(LPSPropValue lpPropVals)
|
|
{
|
|
if(!lpPropVals)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef UNIOCODE
|
|
if(!m_bUnicode)
|
|
{
|
|
return (lpPropVals->Value.lpszA && *lpPropVals->Value.lpszA);
|
|
}
|
|
#endif
|
|
return (lpPropVals->Value.LPSZ && *lpPropVals->Value.LPSZ);
|
|
|
|
} // CCommonAbObj::StrPropOk
|
|
|
|
DWORD
|
|
CCommonAbObj::GetRecipientInfo(
|
|
LPSPropValue SPropVals,
|
|
ULONG cValues,
|
|
PRECIPIENT pNewRecip,
|
|
PRECIPIENT pOldRecipList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the fax number and display name properties.
|
|
|
|
Arguments:
|
|
|
|
SPropVal - Property values for distribution list.
|
|
cValues - Number of properties.
|
|
pNewRecip - [out] pointer to the new recipient
|
|
pOldRecipList - [in] pointer to the old recipient list
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - if there is a fax number and display name.
|
|
ERROR_CANCELLED - the operation was canceled by user
|
|
ERROR_INVALID_DATA - otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwRes = ERROR_SUCCESS;
|
|
LPSPropValue lpPropVals;
|
|
LPSPropValue lpPropArray;
|
|
BOOL Result = FALSE;
|
|
PICKFAX PickFax = { 0 };
|
|
DWORD dwFaxes = 0;
|
|
|
|
assert(pNewRecip);
|
|
ZeroMemory(pNewRecip, sizeof(RECIPIENT));
|
|
|
|
//
|
|
// Get the entryid and open the entry.
|
|
//
|
|
lpPropVals = FindProp( SPropVals, cValues, PR_ENTRYID );
|
|
|
|
if (lpPropVals)
|
|
{
|
|
ULONG lpulObjType;
|
|
LPMAILUSER lpMailUser = NULL;
|
|
HRESULT hr;
|
|
ULONG countValues;
|
|
|
|
pNewRecip->cbEntryId = lpPropVals->Value.bin.cb;
|
|
ABAllocateBuffer(pNewRecip->cbEntryId, (LPVOID *)&pNewRecip->lpEntryId);
|
|
if(!pNewRecip->lpEntryId)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
memcpy(pNewRecip->lpEntryId, lpPropVals->Value.bin.lpb, pNewRecip->cbEntryId);
|
|
}
|
|
|
|
|
|
hr = m_lpAdrBook->OpenEntry(pNewRecip->cbEntryId,
|
|
(ENTRYID*)pNewRecip->lpEntryId,
|
|
(LPCIID) NULL,
|
|
0,
|
|
&lpulObjType,
|
|
(LPUNKNOWN *) &lpMailUser);
|
|
if (HR_SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get the properties.
|
|
//
|
|
hr = ((IMailUser *)lpMailUser)->GetProps(m_bUnicode ? (LPSPropTagArray)&sPropTagsW : (LPSPropTagArray)&sPropTagsA,
|
|
StrCoding(),
|
|
&countValues,
|
|
&lpPropArray );
|
|
if (HR_SUCCEEDED(hr))
|
|
{
|
|
lpPropVals = FindProp(lpPropArray, countValues, PR_PRIMARY_FAX_NUMBER);
|
|
if (StrPropOk( lpPropVals ))
|
|
{
|
|
PickFax.OtherFax = StrFromAddrBk(lpPropVals);
|
|
if(PickFax.OtherFax && _tcslen(PickFax.OtherFax))
|
|
{
|
|
++dwFaxes;
|
|
}
|
|
}
|
|
|
|
lpPropVals = FindProp(lpPropArray, countValues, PR_BUSINESS_FAX_NUMBER);
|
|
if (StrPropOk( lpPropVals ))
|
|
{
|
|
PickFax.BusinessFax = StrFromAddrBk(lpPropVals);
|
|
if(PickFax.BusinessFax && _tcslen(PickFax.BusinessFax))
|
|
{
|
|
++dwFaxes;
|
|
}
|
|
}
|
|
|
|
lpPropVals = FindProp(lpPropArray, countValues, PR_HOME_FAX_NUMBER);
|
|
if (StrPropOk( lpPropVals ))
|
|
{
|
|
PickFax.HomeFax = StrFromAddrBk(lpPropVals);
|
|
if(PickFax.HomeFax && _tcslen(PickFax.HomeFax))
|
|
{
|
|
++dwFaxes;
|
|
}
|
|
}
|
|
|
|
lpPropVals = FindProp(lpPropArray, countValues, PR_DISPLAY_NAME);
|
|
if (StrPropOk( lpPropVals ))
|
|
{
|
|
pNewRecip->pName = PickFax.DisplayName = StrFromAddrBk(lpPropVals);
|
|
}
|
|
|
|
lpPropVals = FindProp(lpPropArray, countValues, PR_COUNTRY);
|
|
if (StrPropOk( lpPropVals ))
|
|
{
|
|
pNewRecip->pCountry = PickFax.Country = StrFromAddrBk(lpPropVals);
|
|
}
|
|
|
|
if (0 == dwFaxes)
|
|
{
|
|
lpPropVals = FindProp(lpPropArray, countValues, PR_ADDRTYPE);
|
|
|
|
if(lpPropVals && ABStrCmp(lpPropVals, TEXT("FAX")))
|
|
{
|
|
lpPropVals = FindProp(lpPropArray, countValues, PR_EMAIL_ADDRESS);
|
|
if (StrPropOk( lpPropVals ))
|
|
{
|
|
pNewRecip->pAddress = StrFromAddrBk(lpPropVals);
|
|
if(pNewRecip->pAddress)
|
|
{
|
|
++dwFaxes;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PRECIPIENT pRecip = FindRecipient(pOldRecipList, &PickFax);
|
|
if(pRecip)
|
|
{
|
|
pNewRecip->pAddress = StringDup(pRecip->pAddress);
|
|
pNewRecip->dwCountryId = pRecip->dwCountryId;
|
|
pNewRecip->bUseDialingRules = pRecip->bUseDialingRules;
|
|
|
|
MemFree(PickFax.BusinessFax);
|
|
PickFax.BusinessFax = NULL;
|
|
MemFree(PickFax.HomeFax);
|
|
PickFax.HomeFax = NULL;
|
|
MemFree(PickFax.OtherFax);
|
|
PickFax.OtherFax = NULL;
|
|
|
|
dwFaxes = 1;
|
|
}
|
|
|
|
//
|
|
// If there are more then 1 fax numbers, ask the user to pick one.
|
|
//
|
|
if (dwFaxes > 1)
|
|
{
|
|
INT_PTR nResult;
|
|
nResult = DialogBoxParam((HINSTANCE) m_hInstance,
|
|
MAKEINTRESOURCE( IDD_CHOOSE_FAXNUMBER ),
|
|
m_hWnd,
|
|
ChooseFaxNumberDlgProc,
|
|
(LPARAM) &PickFax);
|
|
switch( nResult )
|
|
{
|
|
case IDC_BUSINESS_FAX:
|
|
pNewRecip->pAddress = PickFax.BusinessFax;
|
|
|
|
MemFree(PickFax.HomeFax);
|
|
PickFax.HomeFax = NULL;
|
|
MemFree(PickFax.OtherFax);
|
|
PickFax.OtherFax = NULL;
|
|
break;
|
|
|
|
case IDC_HOME_FAX:
|
|
pNewRecip->pAddress = PickFax.HomeFax;
|
|
|
|
MemFree(PickFax.BusinessFax);
|
|
PickFax.BusinessFax = NULL;
|
|
MemFree(PickFax.OtherFax);
|
|
PickFax.OtherFax = NULL;
|
|
break;
|
|
|
|
case IDC_OTHER_FAX:
|
|
pNewRecip->pAddress = PickFax.OtherFax;
|
|
|
|
MemFree(PickFax.BusinessFax);
|
|
PickFax.BusinessFax = NULL;
|
|
MemFree(PickFax.HomeFax);
|
|
PickFax.HomeFax = NULL;
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
MemFree(PickFax.BusinessFax);
|
|
PickFax.BusinessFax = NULL;
|
|
MemFree(PickFax.HomeFax);
|
|
PickFax.HomeFax = NULL;
|
|
MemFree(PickFax.OtherFax);
|
|
PickFax.OtherFax = NULL;
|
|
|
|
dwRes = ERROR_CANCELLED;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ABFreeBuffer( lpPropArray );
|
|
}
|
|
|
|
if(!m_lpMailUser)
|
|
{
|
|
//
|
|
// Remember the first MailUser and do not release it
|
|
// to avoid release of the MAPI DLLs
|
|
// m_lpMailUser should be released later
|
|
//
|
|
m_lpMailUser = lpMailUser;
|
|
}
|
|
else if(lpMailUser)
|
|
{
|
|
lpMailUser->Release();
|
|
lpMailUser = NULL;
|
|
}
|
|
}
|
|
|
|
if (0 == dwFaxes)
|
|
{
|
|
lpPropVals = FindProp(SPropVals, cValues, PR_ADDRTYPE);
|
|
|
|
if(lpPropVals && ABStrCmp(lpPropVals, TEXT("FAX")))
|
|
{
|
|
lpPropVals = FindProp(SPropVals, cValues, PR_EMAIL_ADDRESS);
|
|
if (StrPropOk( lpPropVals ))
|
|
{
|
|
TCHAR* pAddress = StrFromAddrBk(lpPropVals);
|
|
if(pAddress)
|
|
{
|
|
TCHAR* ptr = _tcschr(pAddress, TEXT('@'));
|
|
if(ptr)
|
|
{
|
|
ptr = _tcsinc(ptr);
|
|
pNewRecip->pAddress = StringDup(ptr);
|
|
MemFree(pAddress);
|
|
}
|
|
else
|
|
{
|
|
pNewRecip->pAddress = pAddress;
|
|
}
|
|
}
|
|
}
|
|
|
|
lpPropVals = FindProp(SPropVals, cValues, PR_DISPLAY_NAME);
|
|
if (StrPropOk( lpPropVals ))
|
|
{
|
|
MemFree(pNewRecip->pName);
|
|
pNewRecip->pName = NULL;
|
|
|
|
pNewRecip->pName = StrFromAddrBk(lpPropVals);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (PickFax.BusinessFax)
|
|
{
|
|
pNewRecip->pAddress = PickFax.BusinessFax;
|
|
}
|
|
else if (PickFax.HomeFax)
|
|
{
|
|
pNewRecip->pAddress = PickFax.HomeFax;
|
|
}
|
|
else if (PickFax.OtherFax)
|
|
{
|
|
pNewRecip->pAddress = PickFax.OtherFax;
|
|
}
|
|
|
|
if (ERROR_CANCELLED != dwRes &&
|
|
(!pNewRecip->pAddress || !pNewRecip->pName))
|
|
{
|
|
dwRes = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if(ERROR_SUCCESS != dwRes)
|
|
{
|
|
MemFree(pNewRecip->pName);
|
|
MemFree(pNewRecip->pAddress);
|
|
MemFree(pNewRecip->pCountry);
|
|
ABFreeBuffer(pNewRecip->lpEntryId);
|
|
ZeroMemory(pNewRecip, sizeof(RECIPIENT));
|
|
}
|
|
|
|
return dwRes;
|
|
|
|
} // CCommonAbObj::GetRecipientInfo
|
|
|
|
BOOL
|
|
CCommonAbObj::GetOneOffRecipientInfo(
|
|
LPSPropValue SPropVals,
|
|
ULONG cValues,
|
|
PRECIPIENT pNewRecip,
|
|
PRECIPIENT pOldRecipList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the fax number and display name properties.
|
|
|
|
Arguments:
|
|
|
|
SPropVal - Property values for distribution list.
|
|
cValues - Number of properties.
|
|
pNewRecip - [out] pointer to a new recipient
|
|
pOldRecipList - pointer to the old recipient list
|
|
|
|
Return Value:
|
|
|
|
TRUE if there is a fax number and display name.
|
|
FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
PRECIPIENT pRecip = NULL;
|
|
LPSPropValue lpPropVals;
|
|
|
|
assert(!pNewRecip);
|
|
|
|
lpPropVals = FindProp(SPropVals, cValues, PR_PRIMARY_FAX_NUMBER);
|
|
if (lpPropVals)
|
|
{
|
|
if (!(pNewRecip->pAddress = StrFromAddrBk(lpPropVals)))
|
|
{
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
lpPropVals = FindProp(SPropVals, cValues, PR_DISPLAY_NAME);
|
|
if (lpPropVals)
|
|
{
|
|
if (!(pNewRecip->pName = StrFromAddrBk(lpPropVals)))
|
|
{
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
pRecip = FindRecipient(pNewRecip, pOldRecipList);
|
|
if(pRecip)
|
|
{
|
|
pNewRecip->dwCountryId = pRecip->dwCountryId;
|
|
pNewRecip->bUseDialingRules = pRecip->bUseDialingRules;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
error:
|
|
MemFree(pNewRecip->pAddress);
|
|
MemFree(pNewRecip->pName);
|
|
return FALSE;
|
|
|
|
} // CCommonAbObj::GetOneOffRecipientInfo
|
|
|
|
|
|
LPTSTR
|
|
CCommonAbObj::GetEmail(
|
|
LPSPropValue SPropVals,
|
|
ULONG cValues
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get e-mail address
|
|
|
|
Arguments:
|
|
|
|
SPropVal - Property values for distribution list.
|
|
cValues - Number of properties.
|
|
|
|
Return Value:
|
|
|
|
A choosen E-mail address
|
|
NULL otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
LPSPropValue lpPropVals = NULL;
|
|
LPSPropValue lpPropArray = NULL;
|
|
BOOL Result = FALSE;
|
|
LPTSTR lptstrEmailAddress = NULL;
|
|
TCHAR tszBuffer[MAX_STRING_LEN];
|
|
|
|
ULONG lpulObjType = 0;
|
|
LPMAILUSER lpMailUser = NULL;
|
|
LPENTRYID lpEntryId = NULL;
|
|
DWORD cbEntryId = 0;
|
|
HRESULT hr;
|
|
ULONG countValues = 0;
|
|
|
|
//
|
|
// Get the entryid and open the entry.
|
|
//
|
|
|
|
lpPropVals = FindProp( SPropVals, cValues, PR_ENTRYID );
|
|
if (!lpPropVals)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
lpEntryId = (LPENTRYID)lpPropVals->Value.bin.lpb;
|
|
cbEntryId = lpPropVals->Value.bin.cb;
|
|
|
|
hr = m_lpAdrBook->OpenEntry(cbEntryId,
|
|
lpEntryId,
|
|
(LPCIID) NULL,
|
|
0,
|
|
&lpulObjType,
|
|
(LPUNKNOWN *) &lpMailUser);
|
|
if (HR_FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Get the properties.
|
|
//
|
|
hr = ((IMailUser*)lpMailUser)->GetProps(m_bUnicode ? (LPSPropTagArray)&sPropTagsW : (LPSPropTagArray)&sPropTagsA,
|
|
StrCoding(),
|
|
&countValues,
|
|
&lpPropArray);
|
|
if (HR_FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
lpPropVals = FindProp(lpPropArray, countValues, PR_ADDRTYPE);
|
|
|
|
if (lpPropVals && ABStrCmp(lpPropVals, TEXT("SMTP")))
|
|
{
|
|
lpPropVals = FindProp(lpPropArray, countValues, PR_EMAIL_ADDRESS);
|
|
if (StrPropOk( lpPropVals ))
|
|
{
|
|
lptstrEmailAddress = StrFromAddrBk(lpPropVals);
|
|
}
|
|
}
|
|
else if (lpPropVals && ABStrCmp(lpPropVals, TEXT("EX")))
|
|
{
|
|
lpPropVals = FindProp(lpPropArray, countValues, PR_EMS_AB_PROXY_ADDRESSES);
|
|
if (lpPropVals)
|
|
{
|
|
DWORD dwArrSize = m_bUnicode ? lpPropVals->Value.MVszW.cValues : lpPropVals->Value.MVszA.cValues;
|
|
|
|
for(DWORD dw=0; dw < dwArrSize; ++dw)
|
|
{
|
|
if(m_bUnicode)
|
|
{
|
|
if(wcsstr(lpPropVals->Value.MVszW.lppszW[dw], L"SMTP:"))
|
|
{
|
|
WCHAR* ptr = wcschr(lpPropVals->Value.MVszW.lppszW[dw], L':');
|
|
ptr++;
|
|
|
|
SPropValue propVal = {0};
|
|
propVal.Value.lpszW = ptr;
|
|
|
|
lptstrEmailAddress = StrFromAddrBk(&propVal);
|
|
break;
|
|
}
|
|
}
|
|
else // ANSII
|
|
{
|
|
if(strstr(lpPropVals->Value.MVszA.lppszA[dw], "SMTP:"))
|
|
{
|
|
CHAR* ptr = strchr(lpPropVals->Value.MVszA.lppszA[dw], ':');
|
|
ptr++;
|
|
|
|
SPropValue propVal = {0};
|
|
propVal.Value.lpszA = ptr;
|
|
|
|
lptstrEmailAddress = StrFromAddrBk(&propVal);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
if(lpPropArray)
|
|
{
|
|
ABFreeBuffer( lpPropArray );
|
|
}
|
|
|
|
if (lpMailUser)
|
|
{
|
|
lpMailUser->Release();
|
|
}
|
|
|
|
if(!lptstrEmailAddress)
|
|
{
|
|
if (!::LoadString((HINSTANCE )m_hInstance, IDS_ERROR_RECEIPT_SMTP,tszBuffer, MAX_STRING_LEN))
|
|
{
|
|
assert(FALSE);
|
|
}
|
|
else
|
|
{
|
|
AlignedMessageBox( m_hWnd, tszBuffer, NULL, MB_ICONSTOP | MB_OK);
|
|
}
|
|
}
|
|
|
|
return lptstrEmailAddress;
|
|
|
|
} // CCommonAbObj::GetEmail
|
|
|
|
LPSPropValue
|
|
CCommonAbObj::FindProp(
|
|
LPSPropValue rgprop,
|
|
ULONG cprop,
|
|
ULONG ulPropTag
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Searches for a given property tag in a propset. If the given
|
|
property tag has type PT_UNSPECIFIED, matches only on the
|
|
property ID; otherwise, matches on the entire tag.
|
|
|
|
Arguments:
|
|
|
|
rgprop - Property values.
|
|
cprop - Number of properties.
|
|
ulPropTag - Property to search for.
|
|
|
|
Return Value:
|
|
|
|
Pointer to property desired property value or NULL.
|
|
--*/
|
|
|
|
{
|
|
if (!cprop || !rgprop)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
LPSPropValue pprop = rgprop;
|
|
|
|
#ifdef UNICODE
|
|
if(!m_bUnicode)
|
|
{
|
|
//
|
|
// If the Address Book does not support Unicode
|
|
// change the property type to ANSII
|
|
//
|
|
if(PROP_TYPE(ulPropTag) == PT_UNICODE)
|
|
{
|
|
ulPropTag = PROP_TAG( PT_STRING8, PROP_ID(ulPropTag));
|
|
}
|
|
|
|
if(PROP_TYPE(ulPropTag) == PT_MV_UNICODE)
|
|
{
|
|
ulPropTag = PROP_TAG( PT_MV_STRING8, PROP_ID(ulPropTag));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
while (cprop--)
|
|
{
|
|
if (pprop->ulPropTag == ulPropTag)
|
|
{
|
|
return pprop;
|
|
}
|
|
++pprop;
|
|
}
|
|
|
|
return NULL;
|
|
|
|
} // CCommonAbObj::FindProp
|
|
|
|
|
|
DWORD
|
|
CCommonAbObj::AddRecipient(
|
|
PRECIPIENT *ppNewRecipList,
|
|
PRECIPIENT pRecipient,
|
|
BOOL bFromAddressBook
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add a recipient to the recipient list.
|
|
|
|
Arguments:
|
|
|
|
ppNewRecip - pointer to pointer to list to add item to.
|
|
pRecipient - pointer to the new recipient data
|
|
bFromAddressBook - boolean says if this recipient is from address book
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
--*/
|
|
{
|
|
DWORD dwRes = ERROR_SUCCESS;
|
|
PRECIPIENT pNewRecip = NULL;
|
|
|
|
pNewRecip = (PRECIPIENT)MemAllocZ(sizeof(RECIPIENT));
|
|
if(!pNewRecip)
|
|
{
|
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto error;
|
|
}
|
|
else
|
|
{
|
|
pNewRecip->pName = pRecipient->pName;
|
|
pNewRecip->pAddress = pRecipient->pAddress;
|
|
pNewRecip->pCountry = pRecipient->pCountry;
|
|
pNewRecip->cbEntryId = pRecipient->cbEntryId;
|
|
pNewRecip->lpEntryId = pRecipient->lpEntryId;
|
|
pNewRecip->dwCountryId = pRecipient->dwCountryId;
|
|
pNewRecip->bUseDialingRules = pRecipient->bUseDialingRules;
|
|
pNewRecip->bFromAddressBook = bFromAddressBook;
|
|
pNewRecip->pNext = *ppNewRecipList;
|
|
}
|
|
|
|
try
|
|
{
|
|
//
|
|
// Try to insert a recipient into the set
|
|
//
|
|
if(m_setRecipients.insert(pNewRecip).second == false)
|
|
{
|
|
//
|
|
// Such recipient already exists
|
|
//
|
|
goto error;
|
|
}
|
|
}
|
|
catch (std::bad_alloc&)
|
|
{
|
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto error;
|
|
}
|
|
|
|
//
|
|
// Add the recipient into the list
|
|
//
|
|
*ppNewRecipList = pNewRecip;
|
|
|
|
return dwRes;
|
|
|
|
error:
|
|
|
|
MemFree(pRecipient->pName);
|
|
MemFree(pRecipient->pAddress);
|
|
MemFree(pRecipient->pCountry);
|
|
ABFreeBuffer(pRecipient->lpEntryId);
|
|
ZeroMemory(pRecipient, sizeof(RECIPIENT));
|
|
|
|
MemFree(pNewRecip);
|
|
|
|
return dwRes;
|
|
|
|
} // CCommonAbObj::AddRecipient
|
|
|
|
|
|
LPTSTR
|
|
CCommonAbObj::StrToAddrBk(
|
|
LPCTSTR szStr,
|
|
DWORD* pdwSize /* = NULL*/
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocate string converted to the Address book encoding
|
|
|
|
Arguments:
|
|
|
|
szStr - [in] source string
|
|
pdwSize - [out] optional size of new string in bytes
|
|
|
|
Return Value:
|
|
|
|
Pointer to the converted string
|
|
Should be released by MemFree()
|
|
--*/
|
|
{
|
|
if(!szStr)
|
|
{
|
|
Assert(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
|
|
if(!m_bUnicode)
|
|
{
|
|
//
|
|
// The address book does not support Unicode
|
|
//
|
|
INT nSize;
|
|
LPSTR pAnsii;
|
|
//
|
|
// Figure out how much memory to allocate for the multi-byte string
|
|
//
|
|
if (! (nSize = WideCharToMultiByte(CP_ACP, 0, szStr, -1, NULL, 0, NULL, NULL)) ||
|
|
! (pAnsii = (LPSTR)MemAlloc(nSize)))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Convert Unicode string to multi-byte string
|
|
//
|
|
WideCharToMultiByte(CP_ACP, 0, szStr, -1, pAnsii, nSize, NULL, NULL);
|
|
|
|
if(pdwSize)
|
|
{
|
|
*pdwSize = nSize;
|
|
}
|
|
return (LPTSTR)pAnsii;
|
|
}
|
|
|
|
#endif // UNICODE
|
|
|
|
LPTSTR pNewStr = StringDup(szStr);
|
|
if(pdwSize && pNewStr)
|
|
{
|
|
*pdwSize = (_tcslen(pNewStr)+1) * sizeof(TCHAR);
|
|
}
|
|
|
|
return pNewStr;
|
|
|
|
} // CCommonAbObj::StrToAddrBk
|
|
|
|
|
|
LPTSTR
|
|
CCommonAbObj::StrFromAddrBk(LPSPropValue pValue)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocate string converted from the Address book encoding
|
|
|
|
Arguments:
|
|
|
|
pValue - [in] MAPI property
|
|
|
|
Return Value:
|
|
|
|
Pointer to the converted string
|
|
Should be released by MemFree()
|
|
--*/
|
|
{
|
|
if(!pValue)
|
|
{
|
|
Assert(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
|
|
if(!m_bUnicode)
|
|
{
|
|
//
|
|
// The address book does not support Unicode
|
|
//
|
|
|
|
if(!pValue->Value.lpszA)
|
|
{
|
|
Assert(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
INT nSize;
|
|
LPWSTR pUnicodeStr;
|
|
if (! (nSize = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pValue->Value.lpszA, -1, NULL, 0)) ||
|
|
! (pUnicodeStr = (LPWSTR) MemAlloc( nSize * sizeof(WCHAR))))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Convert multi-byte string to Unicode string
|
|
//
|
|
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pValue->Value.lpszA, -1, pUnicodeStr, nSize);
|
|
return pUnicodeStr;
|
|
}
|
|
|
|
#endif // UNICODE
|
|
|
|
if(!pValue->Value.LPSZ)
|
|
{
|
|
Assert(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
LPTSTR pNewStr = StringDup(pValue->Value.LPSZ);
|
|
return pNewStr;
|
|
|
|
} // CCommonAbObj::StrFromAddrBk
|
|
|
|
BOOL
|
|
CCommonAbObj::ABStrCmp(LPSPropValue lpPropVals, LPTSTR pStr)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compare string with MAPI property value according to the address book encoding
|
|
|
|
Arguments:
|
|
|
|
lpPropVals - [in] MAPI property
|
|
pStr - [in] string to compare
|
|
|
|
Return Value:
|
|
|
|
TRUE if the strings are equal
|
|
FALSE otherwise
|
|
--*/
|
|
{
|
|
BOOL bRes = FALSE;
|
|
if(!lpPropVals || !pStr)
|
|
{
|
|
Assert(FALSE);
|
|
return bRes;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
if(!m_bUnicode)
|
|
{
|
|
LPSTR pAnsii = (LPSTR)StrToAddrBk(pStr);
|
|
if(pAnsii)
|
|
{
|
|
bRes = !strcmp(lpPropVals->Value.lpszA, pAnsii);
|
|
MemFree(pAnsii);
|
|
}
|
|
return bRes;
|
|
}
|
|
#endif
|
|
|
|
bRes = !_tcscmp(lpPropVals->Value.LPSZ, pStr);
|
|
return bRes;
|
|
|
|
} // CCommonAbObj::ABStrCmp
|
|
|
|
BOOL
|
|
CCommonAbObj::GetAddrBookCaption(
|
|
LPTSTR szCaption,
|
|
DWORD dwSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get address book dialog caption according to the ANSII/Unicode capability
|
|
|
|
Arguments:
|
|
|
|
szCaption - [out] caption buffer
|
|
dwSize - [in] caption buffer size in characters
|
|
|
|
Return Value:
|
|
|
|
TRUE if success
|
|
FALSE otherwise
|
|
--*/
|
|
{
|
|
if(!szCaption || !dwSize)
|
|
{
|
|
Assert(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
TCHAR tszStr[MAX_PATH] = {0};
|
|
|
|
if(!LoadString(m_hInstance, IDS_ADDRESS_BOOK_CAPTION, tszStr, ARR_SIZE(tszStr)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
_tcsncpy(szCaption, tszStr, dwSize);
|
|
|
|
#ifdef UNICODE
|
|
if(!m_bUnicode || GetABType() == AB_MAPI)
|
|
{
|
|
//
|
|
// MAPI interpret lpszCaption as ANSII anyway
|
|
//
|
|
char szAnsiStr[MAX_PATH] = {0};
|
|
if(!WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
tszStr,
|
|
-1,
|
|
szAnsiStr,
|
|
ARR_SIZE(szAnsiStr),
|
|
NULL,
|
|
NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
memcpy(szCaption, szAnsiStr, min(dwSize, strlen(szAnsiStr)+1));
|
|
}
|
|
#endif // UNICODE
|
|
|
|
return TRUE;
|
|
|
|
} // CCommonAbObj::GetAddrBookCaption
|