Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2651 lines
102 KiB

/*--------------------------------------------------------------
*
*
* ui_addr.c - contains stuff for showing the :Address UI
*
*
*
*
*
*
*
--------------------------------------------------------------*/
#include "_apipch.h"
extern HINSTANCE ghCommCtrlDLLInst;
#define SET_UNICODE_STR(lp1,lp2,lpAdrParms) if(lpAdrParms->ulFlags & MAPI_UNICODE)\
lp1 = (LPWSTR)lp2; \
else \
lp1 = ConvertAtoW((LPSTR)lp2); \
#define FREE_UNICODE_STR(lp1,lp2) if(lp1 != lp2) LocalFreeAndNull(&lp1);
typedef struct _AddressParms
{
LPADRBOOK lpIAB; //Stores a pointer to the ADRBOOK object
LPADRPARM lpAdrParms; //AdrParms structure passed into Address
LPADRLIST *lppAdrList; //AdrList of input names
HANDLE hPropertyStore; //pointer to the property store
int DialogState; //Identifies the ongoing function
LPRECIPIENT_INFO lpContentsList;//Contains a list of entries in the contents structure
LPRECIPIENT_INFO lpListTo; //Entries in the To Well
LPRECIPIENT_INFO lpListCC; //Entries in the CC well
LPRECIPIENT_INFO lpListBCC; //Entries in the BCC well
SORT_INFO SortInfo; //Contains current sort info
int nContextID; //identifies which list view called the context menu
BOOL bDontRefresh; //Used to ensure that nothing refreshes during modal operations
BOOL bLDAPinProgress;
HCURSOR hWaitCur;
int nRetVal;
LPMAPIADVISESINK lpAdviseSink;
ULONG ulAdviseConnection;
BOOL bDeferNotification; // Used to defer next notification request
HWND hDlg;
HWND hWndAddr;
} ADDRESS_PARMS, *LPADDRESS_PARMS;
enum _lppAdrListReturnedProps
{
propPR_DISPLAY_NAME,
propPR_ENTRYID,
propPR_RECIPIENT_TYPE,
TOTAL_ADRLIST_PROPS
};
static DWORD rgAddrHelpIDs[] =
{
IDC_ADDRBK_EDIT_QUICKFIND, IDH_WAB_PICK_RECIP_TYPE_NAME,
IDC_ADDRBK_STATIC_CONTENTS, IDH_WAB_PICK_RECIP_NAME_LIST,
IDC_ADDRBK_LIST_ADDRESSES, IDH_WAB_PICK_RECIP_NAME_LIST,
IDC_ADDRBK_BUTTON_PROPS, IDH_WAB_PICK_RECIP_NAME_PROPERTIES,
IDC_ADDRBK_BUTTON_NEW, IDH_WAB_PICK_RECIP_NAME_NEW,
IDC_ADDRBK_BUTTON_TO, IDH_WAB_PICK_RECIP_NAME_TO_BUTTON,
IDC_ADDRBK_BUTTON_CC, IDH_WAB_PICK_RECIP_NAME_CC_BUTTON,
IDC_ADDRBK_BUTTON_BCC, IDH_WAB_PICK_RECIP_NAME_BCC_BUTTON,
IDC_ADDRBK_LIST_TO, IDH_WAB_PICK_RECIP_NAME_TO_LIST,
IDC_ADDRBK_LIST_CC, IDH_WAB_PICK_RECIP_NAME_CC_LIST,
IDC_ADDRBK_LIST_BCC, IDH_WAB_PICK_RECIP_NAME_BCC_LIST,
IDC_ADDRBK_BUTTON_DELETE, IDH_WAB_PICK_RECIP_NAME_DELETE,
IDC_ADDRBK_BUTTON_NEWGROUP, IDH_WAB_PICK_RECIP_NAME_NEW_GROUP,
IDC_ADDRBK_STATIC_RECIP_TITLE, IDH_WAB_COMM_GROUPBOX,
IDC_ADDRBK_BUTTON_FIND, IDH_WAB_PICK_RECIP_NAME_FIND,
IDC_ADDRBK_COMBO_CONT, IDH_WAB_GROUPS_CONTACTS_FOLDER,
0,0
};
// forward declarations
INT_PTR CALLBACK fnAddress(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam);
BOOL SetAddressBookUI(HWND hDlg,
LPADDRESS_PARMS lpAP);
void FillListFromCurrentContainer(HWND hDlg, LPADDRESS_PARMS lpAP);
BOOL FillWells(HWND hDlg, LPADRLIST lpAdrList, LPADRPARM lpAdrParms, LPRECIPIENT_INFO * lppListTo, LPRECIPIENT_INFO * lppListCC, LPRECIPIENT_INFO * lppListBCC);
BOOL ListDeleteItem(HWND hDlg, int CtlID, LPRECIPIENT_INFO * lppList);
BOOL ListAddItem(HWND hDlg, HWND hWndAddr, int CtlID, LPRECIPIENT_INFO * lppList, ULONG RecipientType);
void UpdateLVItems(HWND hWndLV,LPTSTR lpszName);
void ShowAddrBkLVProps(LPIAB lpIAB, HWND hDlg, HWND hWndAddr, LPADDRESS_PARMS lpAP, LPFILETIME lpftLast);
HRESULT HrUpdateAdrListEntry( LPADRBOOK lpIAB,
LPENTRYID lpEntryID,
ULONG cbEntryID,
ULONG ulFlags,
LPADRLIST * lppAdrList);
enum _AddressDialogReturnValues
{
ADDRESS_RESET = 0, //Blank initialization value
ADDRESS_CANCEL,
ADDRESS_OK,
};
//$$/////////////////////////////////////////////////////////////////////////////////////////
//
// FillContainerCombo - Fills the container combo with container names
//
/////////////////////////////////////////////////////////////////////////////////////////////
void FillContainerCombo(HWND hWndCombo, LPIAB lpIAB)
{
ULONG iolkci, colkci;
OlkContInfo *rgolkci;
int nPos, nDefault=0;
LPPTGDATA lpPTGData=GetThreadStoragePointer();
// Clear out the combo
SendMessage(hWndCombo, CB_RESETCONTENT, 0, 0);
Assert(lpIAB);
EnterCriticalSection(&lpIAB->cs);
if(pt_bIsWABOpenExSession || bIsWABSessionProfileAware(lpIAB))
{
colkci = pt_bIsWABOpenExSession ? lpIAB->lpPropertyStore->colkci : lpIAB->cwabci;
Assert(colkci);
rgolkci = lpIAB->lpPropertyStore->colkci ? lpIAB->lpPropertyStore->rgolkci : lpIAB->rgwabci;
Assert(rgolkci);
// Add the multiple folders here
for(iolkci = 0; iolkci < colkci; iolkci++)
{
nPos = (int) SendMessage(hWndCombo, CB_ADDSTRING, 0, (LPARAM) rgolkci[iolkci].lpszName);
if(nPos != CB_ERR)
SendMessage(hWndCombo, CB_SETITEMDATA, (WPARAM)nPos, (LPARAM) (DWORD_PTR)(iolkci==0 ? NULL : rgolkci[iolkci].lpEntryID));
if( bIsThereACurrentUser(lpIAB) &&
!lstrcmpi(lpIAB->lpWABCurrentUserFolder->lpFolderName, rgolkci[iolkci].lpszName) &&//folder names are unique
nPos != CB_ERR)
{
nDefault = nPos;
}
}
}
LeaveCriticalSection(&lpIAB->cs);
SendMessage(hWndCombo, CB_SETCURSEL, (WPARAM) nDefault, 0);
}
//$$*------------------------------------------------------------------------
//| IAddrBook::Advise::OnNotify handler
//|
//*------------------------------------------------------------------------
ULONG AddrAdviseOnNotify(LPVOID lpvContext, ULONG cNotif, LPNOTIFICATION lpNotif)
{
LPADDRESS_PARMS lpAP = (LPADDRESS_PARMS) lpvContext;
DebugTrace( TEXT("+++ AddrAdviseOnNotify ===\n"));
if(lpAP->bDeferNotification)
{
DebugTrace( TEXT("+++ Advise Defered ===\n"));
lpAP->bDeferNotification = FALSE;
return S_OK;
}
if(!lpAP->bDontRefresh)
{
DebugTrace( TEXT("+++ Calling FillListFromCurrentContainer ===\n"));
FillListFromCurrentContainer(lpAP->hDlg, lpAP);
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////////
//
// ShowAddressUI - does some parameter checking and calls the PropertySheets
//
//
//
/////////////////////////////////////////////////////////////////////////////////
HRESULT HrShowAddressUI(IN LPADRBOOK lpIAB,
IN HANDLE hPropertyStore,
IN ULONG_PTR * lpulUIParam,
IN LPADRPARM lpAdrParms,
IN LPADRLIST *lppAdrList)
{
HRESULT hr = E_FAIL;
//ADDRESS_PARMS AP = {0};
LPADDRESS_PARMS lpAP = NULL;
TCHAR szBuf[MAX_UI_STR];
HWND hWndParent = NULL;
int nRetVal = 0;
int DialogState = 0;
//Addref the AdrBook object to make sure it stays valid throughout ..
// Remember to release before leaving ...
// NOTE: Must be before any jumps to out!
UlAddRef(lpIAB);
// if no common control, exit
if (NULL == ghCommCtrlDLLInst) {
hr = ResultFromScode(MAPI_E_UNCONFIGURED);
goto out;
}
if (lpulUIParam)
hWndParent = (HWND) *lpulUIParam;
if ( // Can't pick-user with wells
((lpAdrParms->ulFlags & ADDRESS_ONE) && (lpAdrParms->cDestFields != 0)) ||
// cDestFields has limited for tier 0.5
(lpAdrParms->cDestFields > 3) ||
// Cant pick user without an input lpAdrList
//((lpAdrParms->ulFlags & ADDRESS_ONE) && (*lppAdrList == NULL)) ||
((lpAdrParms->ulFlags & DIALOG_SDI) && (lpAdrParms->cDestFields != 0)) )
{
hr = MAPI_E_INVALID_PARAMETER;
goto out;
}
//
// The possible states of this dialog box are
// 1. Select recipients Wells shown, returns an AdrList of picked up entries, Cant delete entries
// 2. Select a single user, No wells shown, single selection, cannot delete, must have input Adrlist
// 3. Open for browsing only, multiple selection, can create delete, create, view details
// Determine what the dialog state is
if (lpAdrParms->cDestFields > 0)
{
//lpAP->DialogState = STATE_SELECT_RECIPIENTS;
DialogState = STATE_SELECT_RECIPIENTS;
}
else if (lpAdrParms->ulFlags & ADDRESS_ONE)
{
DialogState = STATE_PICK_USER;
}
else if (lpAdrParms->ulFlags & DIALOG_MODAL)
{
DialogState = STATE_BROWSE_MODAL;
}
else if (lpAdrParms->ulFlags & DIALOG_SDI)
{
DialogState = STATE_BROWSE;
}
if (DialogState == STATE_BROWSE)
{
// Show the browse window and leave
//
HWND hWndAB = NULL;
hWndAB = hCreateAddressBookWindow( lpIAB,
hWndParent,
lpAdrParms);
if (hWndAB)
{
*lpulUIParam = (ULONG_PTR) hWndAB;
hr = S_OK;
}
goto out;
}
lpAP = LocalAlloc(LMEM_ZEROINIT, sizeof(ADDRESS_PARMS));
if (!lpAP)
{
hr = MAPI_E_NOT_ENOUGH_MEMORY;
goto out;
}
lpAP->DialogState = DialogState;
lpAP->lpIAB = lpIAB;
lpAP->lpAdrParms = lpAdrParms;
lpAP->lppAdrList = lppAdrList;
lpAP->hPropertyStore = hPropertyStore;
ReadRegistrySortInfo((LPIAB)lpIAB, &(lpAP->SortInfo));
lpAP->lpContentsList = NULL;
lpAP->bDontRefresh = FALSE;
lpAP->bLDAPinProgress = FALSE;
lpAP->hWaitCur = NULL;
HrAllocAdviseSink(&AddrAdviseOnNotify, (LPVOID) lpAP, &(lpAP->lpAdviseSink));
nRetVal = (int) DialogBoxParam( hinstMapiX,
MAKEINTRESOURCE(IDD_DIALOG_ADDRESSBOOK),
hWndParent,
fnAddress,
(LPARAM) lpAP);
switch(nRetVal)
{
case -1: //some error occured
hr = E_FAIL;
break;
case ADDRESS_CANCEL:
hr = MAPI_E_USER_CANCEL;
break;
case ADDRESS_OK:
default:
hr = S_OK;
break;
}
if(lpAP->lpAdviseSink)
{
lpAP->lpIAB->lpVtbl->Unadvise(lpAP->lpIAB, lpAP->ulAdviseConnection);
lpAP->lpAdviseSink->lpVtbl->Release(lpAP->lpAdviseSink);
lpAP->lpAdviseSink = NULL;
lpAP->ulAdviseConnection = 0;
}
out:
lpIAB->lpVtbl->Release(lpIAB);
LocalFreeAndNull(&lpAP);
return hr;
}
#define lpAP_lppContentsList (&(lpAP->lpContentsList))
#define lpAP_lppListTo (&(lpAP->lpListTo))
#define lpAP_lppListCC (&(lpAP->lpListCC))
#define lpAP_lppListBCC (&(lpAP->lpListBCC))
#define lpAP_bDontRefresh (lpAP->bDontRefresh)
#define _hWndAddr lpAP->hWndAddr
//$$/////////////////////////////////////////////////////////////////////////////
//
// GetCurrentComboSelection - Get the current selection from the combo
//
/////////////////////////////////////////////////////////////////////////////////
LPSBinary GetCurrentComboSelection(HWND hWndCombo)
{
int nPos = (int) SendMessage(hWndCombo, CB_GETCURSEL, 0, 0);
LPSBinary lpsbCont = NULL;
if(nPos == CB_ERR)
nPos = 0;
lpsbCont = (LPSBinary) SendMessage(hWndCombo, CB_GETITEMDATA, (WPARAM) nPos, 0);
if(CB_ERR == (DWORD_PTR) lpsbCont)
lpsbCont = NULL;
return lpsbCont;
}
//$$/////////////////////////////////////////////////////////////////////////////
//
// FillListFromCurrentContainer - Get the selection from the combo and fill it
//
/////////////////////////////////////////////////////////////////////////////////
void FillListFromCurrentContainer(HWND hDlg, LPADDRESS_PARMS lpAP)
{
HWND hWndAddr = GetDlgItem(hDlg,IDC_ADDRBK_LIST_ADDRESSES);
LPPTGDATA lpPTGData=GetThreadStoragePointer();
LPSBinary lpsbCont = NULL;
if(pt_bIsWABOpenExSession || bIsWABSessionProfileAware((LPIAB)lpAP->lpIAB))
{
HWND hWndCombo = GetDlgItem(hDlg, IDC_ADDRBK_COMBO_CONT);
int nPos = (int) SendMessage(hWndCombo, CB_GETCURSEL, 0, 0);
if(nPos != CB_ERR)
{
// Refill the combo in case the folder list changed
FillContainerCombo(hWndCombo, (LPIAB)lpAP->lpIAB);
nPos = (int) SendMessage(hWndCombo, CB_SETCURSEL, (WPARAM) nPos, 0);
}
lpsbCont = GetCurrentComboSelection(hWndCombo);
}
HrGetWABContents( hWndAddr,
lpAP->lpIAB, lpsbCont,
lpAP->SortInfo, lpAP_lppContentsList);
}
extern BOOL APIENTRY_16 fnFolderDlgProc(HWND hDlg, UINT message, UINT wParam, LPARAM lParam);
/////////////////////////////////////////////////////////////////////////////////
//
// fnAddress - the PropertySheet Message Handler
//
//
//
/////////////////////////////////////////////////////////////////////////////////
INT_PTR CALLBACK fnAddress(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
static FILETIME ftLast = {0};
LPADDRESS_PARMS lpAP = (LPADDRESS_PARMS ) GetWindowLongPtr(hDlg,DWLP_USER);
switch(message)
{
case WM_INITDIALOG:
SetWindowLongPtr(hDlg,DWLP_USER,lParam); //Save this for future reference
lpAP = (LPADDRESS_PARMS) lParam;
lpAP->hWndAddr = GetDlgItem(hDlg,IDC_ADDRBK_LIST_ADDRESSES);
lpAP->hDlg = hDlg;
lpAP_bDontRefresh = FALSE;
lpAP->nContextID = IDC_ADDRBK_LIST_ADDRESSES;
SetAddressBookUI(hDlg,lpAP);
// if this is a pick-user dialog, need to have the names by
// first name so we can find the closest match ..
if(lpAP->DialogState == STATE_PICK_USER)
(lpAP->SortInfo).bSortByLastName = FALSE;
FillListFromCurrentContainer(hDlg, lpAP);
if (lpAP->DialogState == STATE_SELECT_RECIPIENTS)
{
FillWells(hDlg,*(lpAP->lppAdrList),(lpAP->lpAdrParms),lpAP_lppListTo,lpAP_lppListCC,lpAP_lppListBCC);
// we want to highlight the first item in the list
if (ListView_GetItemCount(_hWndAddr) > 0)
LVSelectItem( _hWndAddr, 0);
}
else if (lpAP->DialogState == STATE_PICK_USER &&
*(lpAP->lppAdrList) )
{
// if this is a pick user dialog, then try to match the supplied name to the
// closest entry in the List Box
if (ListView_GetItemCount(_hWndAddr) > 0)
{
LPTSTR lpszDisplayName = NULL;
ULONG i;
// Scan only the first entry in the lpAdrList for a display name
for(i=0;i< (*(lpAP->lppAdrList))->aEntries[0].cValues;i++)
{
ULONG ulPropTag = PR_DISPLAY_NAME;
if(!(lpAP->lpAdrParms->ulFlags & MAPI_UNICODE))
ulPropTag = CHANGE_PROP_TYPE(ulPropTag, PT_STRING8);
if((*(lpAP->lppAdrList))->aEntries[0].rgPropVals[i].ulPropTag == ulPropTag)
{
SET_UNICODE_STR(lpszDisplayName, (*(lpAP->lppAdrList))->aEntries[0].rgPropVals[i].Value.LPSZ,lpAP->lpAdrParms);
break;
}
}
if (lpszDisplayName)
{
// We have Something to search for
TCHAR szBuf[MAX_UI_STR];
ULONG nLen;
LV_FINDINFO lvF = {0};
// Typically, we are not going to get a full match ...
// Instead we want to make a partial match on disply name.
// The ListViewFindItem does an exact partial match if the supplied
// string matches the first few entries of an existing item
// Hence, to obtain a semi-partial match, we start with the
// original Display Name working our way backwards from last
// character to first character until we get a match or run
// out of characters.
int iItemIndex = -1;
nLen = lstrlen(lpszDisplayName);
if (nLen >= CharSizeOf(szBuf))
nLen = CharSizeOf(szBuf)-1;
lvF.flags = LVFI_PARTIAL | LVFI_STRING;
while((nLen > 0) && (iItemIndex == -1))
{
nLen = TruncatePos(lpszDisplayName, nLen);
if (nLen==0) break;
CopyMemory(szBuf, lpszDisplayName, sizeof(TCHAR)*nLen);
szBuf[nLen] = '\0';
lvF.psz = szBuf;
iItemIndex = ListView_FindItem(_hWndAddr,-1, &lvF);
nLen--;
}
// Set focus to the selected item or to the first item in the list
if (iItemIndex < 0) iItemIndex = 0;
LVSelectItem(_hWndAddr, iItemIndex);
FREE_UNICODE_STR(lpszDisplayName, (*(lpAP->lppAdrList))->aEntries[0].rgPropVals[i].Value.LPSZ);
}
}
}
if(lpAP->lpAdviseSink)
{
// Register for notifications
lpAP->lpIAB->lpVtbl->Advise(lpAP->lpIAB, 0, NULL, fnevObjectModified,
lpAP->lpAdviseSink, &lpAP->ulAdviseConnection);
}
if (ListView_GetSelectedCount(_hWndAddr) <= 0)
LVSelectItem(_hWndAddr, 0);
// if we want the user to pick something actively, we disable OK until they click on something
// or do something specific ..
if( lpAP->DialogState == STATE_PICK_USER )
{
EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
SendMessage (hDlg, DM_SETDEFID, IDCANCEL, 0);
}
SetFocus(GetDlgItem(hDlg,IDC_ADDRBK_EDIT_QUICKFIND));
return FALSE;
// return TRUE;
break;
case WM_SYSCOLORCHANGE:
//Forward any system changes to the list view
SendMessage(_hWndAddr, message, wParam, lParam);
SetColumnHeaderBmp(_hWndAddr, lpAP->SortInfo);
break;
case WM_HELP:
WABWinHelp(((LPHELPINFO)lParam)->hItemHandle,
g_szWABHelpFileName,
HELP_WM_HELP,
(DWORD_PTR)(LPSTR) rgAddrHelpIDs );
break;
case WM_SETCURSOR:
if (lpAP->bLDAPinProgress)
{
SetCursor(lpAP->hWaitCur);
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, MAKELONG(TRUE, 0));
return(TRUE);
}
break;
case WM_COMMAND:
switch(GET_WM_COMMAND_CMD(wParam,lParam)) //check the notification code
{
case CBN_SELCHANGE:
FillListFromCurrentContainer(hDlg, lpAP);
break;
}
switch(GET_WM_COMMAND_ID(wParam, lParam))
{
default:
if (lpAP->nContextID != -1)
{
LRESULT fRet = FALSE;
lpAP_bDontRefresh = TRUE;
fRet = ProcessActionCommands((LPIAB) lpAP->lpIAB,_hWndAddr,
hDlg, message, wParam, lParam);
lpAP_bDontRefresh = FALSE;
return fRet;
}
break;
case IDC_ADDRBK_BUTTON_DELETE:
if(!lpAP->bLDAPinProgress)
{
lpAP->bLDAPinProgress = TRUE;
lpAP_bDontRefresh = TRUE;
DeleteSelectedItems(_hWndAddr, lpAP->lpIAB, lpAP->hPropertyStore, &ftLast);
lpAP->bDeferNotification = TRUE;
lpAP_bDontRefresh = FALSE;
lpAP->bLDAPinProgress = FALSE;
}
break;
case IDM_LVCONTEXT_DELETE:
if(!lpAP->bLDAPinProgress)
{
lpAP->bLDAPinProgress = TRUE;
switch(lpAP->nContextID)
{
case IDC_ADDRBK_LIST_ADDRESSES:
lpAP_bDontRefresh = TRUE;
DeleteSelectedItems(_hWndAddr, lpAP->lpIAB, lpAP->hPropertyStore, &ftLast);
lpAP->bDeferNotification = TRUE;
lpAP_bDontRefresh = FALSE;
break;
case IDC_ADDRBK_LIST_TO:
ListDeleteItem(hDlg, IDC_ADDRBK_LIST_TO, lpAP_lppListTo);
break;
case IDC_ADDRBK_LIST_CC:
ListDeleteItem(hDlg, IDC_ADDRBK_LIST_CC, lpAP_lppListCC);
break;
case IDC_ADDRBK_LIST_BCC:
ListDeleteItem(hDlg, IDC_ADDRBK_LIST_BCC, lpAP_lppListBCC);
break;
default:
break;
}
lpAP->bLDAPinProgress = FALSE;
}
break;
case IDM_LVCONTEXT_COPY:
lpAP_bDontRefresh = TRUE;
HrCopyItemDataToClipboard(hDlg, lpAP->lpIAB, GetDlgItem(hDlg,lpAP->nContextID));
lpAP_bDontRefresh = FALSE;
break;
case IDM_LVCONTEXT_PROPERTIES:
case IDC_ADDRBK_BUTTON_PROPS:
if(!lpAP->bLDAPinProgress)
{
lpAP->bLDAPinProgress = TRUE;
if (lpAP->nContextID != -1)
{
lpAP_bDontRefresh = TRUE;
ShowAddrBkLVProps((LPIAB)lpAP->lpIAB, hDlg, GetDlgItem(hDlg, lpAP->nContextID), lpAP, &ftLast);
lpAP->bDeferNotification = TRUE;
lpAP_bDontRefresh = FALSE;
}
lpAP->bLDAPinProgress = FALSE;
}
break;
/* Uncomment to enable NEW_FOLDER functionality from this dialog
case IDM_LVCONTEXT_NEWFOLDER:
{
TCHAR sz[MAX_UI_STR];
LPTSTR lpsz = NULL;
*sz = '\0';
if( IDCANCEL != DialogBoxParam( hinstMapiX, MAKEINTRESOURCE(IDD_DIALOG_FOLDER),
hDlg, fnFolderDlgProc, (LPARAM) sz)
&& lstrlen(sz))
{
// if we're here we have a valid folder name ..
if(!HR_FAILED(HrCreateNewFolder((LPIAB)lpAP->lpIAB, sz, NULL, FALSE, NULL, NULL)))
{
int i,nTotal;
HWND hWndC = GetDlgItem(hDlg, IDC_ADDRBK_COMBO_CONT);
// Fill in the Combo with the container names
FillContainerCombo(hWndC, (LPIAB)lpAP->lpIAB);
nTotal = SendMessage(hWndC, CB_GETCOUNT, 0, 0);
if(nTotal != CB_ERR)
{
// Find the item we just added in the combo and set the sel on it
TCHAR szC[MAX_UI_STR];
for(i=0;i<nTotal;i++)
{
*szC = '\0';
SendMessage(hWndC, CB_GETLBTEXT, (WPARAM) i, (LPARAM) szC);
if(!lstrcmpi(sz, szC))
{
SendMessage(hWndC, CB_SETCURSEL, (WPARAM) i, 0);
break;
}
}
}
FillListFromCurrentContainer(hDlg, lpAP);
}
}
}
break;
*/
case IDM_LVCONTEXT_NEWCONTACT:
case IDC_ADDRBK_BUTTON_NEW:
// only difference between contact and group is the object being added
case IDM_LVCONTEXT_NEWGROUP:
case IDC_ADDRBK_BUTTON_NEWGROUP:
if(!lpAP->bLDAPinProgress)
{
ULONG cbEID = 0;
LPENTRYID lpEID = NULL;
int nID = GET_WM_COMMAND_ID(wParam, lParam);
ULONG ulObjType = (nID == IDM_LVCONTEXT_NEWCONTACT || nID == IDC_ADDRBK_BUTTON_NEW) ? MAPI_MAILUSER : MAPI_DISTLIST;
LPSBinary lpsbContEID = NULL;
if(bIsWABSessionProfileAware((LPIAB)lpAP->lpIAB))
lpsbContEID = GetCurrentComboSelection(GetDlgItem(hDlg,IDC_ADDRBK_COMBO_CONT));
lpAP->bLDAPinProgress = TRUE;
lpAP_bDontRefresh = TRUE;
AddNewObjectToListViewEx( lpAP->lpIAB, _hWndAddr, NULL, NULL,
lpsbContEID,
ulObjType,
&(lpAP->SortInfo), lpAP_lppContentsList, &ftLast, &cbEID, &lpEID);
FreeBufferAndNull(&lpEID);
SetFocus(_hWndAddr);
lpAP->bDeferNotification = TRUE;
lpAP_bDontRefresh = FALSE;
lpAP->bLDAPinProgress = FALSE;
}
break;
case IDM_LVCONTEXT_ADDWELL1:
case IDC_ADDRBK_BUTTON_TO:
if(!lpAP->bLDAPinProgress)
{
ULONG ulMapiTo = MAPI_TO;
lpAP->bLDAPinProgress = TRUE;
if ((lpAP->lpAdrParms->cDestFields > 0) && (lpAP->lpAdrParms->lpulDestComps))
{
ulMapiTo = lpAP->lpAdrParms->lpulDestComps[0];
}
if(ListAddItem(hDlg, _hWndAddr, IDC_ADDRBK_LIST_TO, lpAP_lppListTo, ulMapiTo))
SendMessage (hDlg, DM_SETDEFID, IDOK/*IDC_ADDRBK_BUTTON_OK*/, 0);
lpAP->bLDAPinProgress = FALSE;
}
break;
case IDM_LVCONTEXT_ADDWELL2:
case IDC_ADDRBK_BUTTON_CC:
if(!lpAP->bLDAPinProgress)
{
ULONG ulMapiCC = MAPI_CC;
lpAP->bLDAPinProgress = TRUE;
if ((lpAP->lpAdrParms->cDestFields > 0) && (lpAP->lpAdrParms->lpulDestComps))
{
ulMapiCC = lpAP->lpAdrParms->lpulDestComps[1];
}
if(ListAddItem(hDlg, _hWndAddr, IDC_ADDRBK_LIST_CC, lpAP_lppListCC, ulMapiCC))
SendMessage (hDlg, DM_SETDEFID, IDOK/*IDC_ADDRBK_BUTTON_OK*/, 0);
lpAP->bLDAPinProgress = FALSE;
}
break;
case IDM_LVCONTEXT_ADDWELL3:
case IDC_ADDRBK_BUTTON_BCC:
if(!lpAP->bLDAPinProgress)
{
ULONG ulMapiBCC = MAPI_BCC;
lpAP->bLDAPinProgress = TRUE;
if ((lpAP->lpAdrParms->cDestFields > 0) && (lpAP->lpAdrParms->lpulDestComps))
{
ulMapiBCC = lpAP->lpAdrParms->lpulDestComps[2];
}
if(ListAddItem(hDlg, _hWndAddr, IDC_ADDRBK_LIST_BCC, lpAP_lppListBCC, ulMapiBCC))
SendMessage (hDlg, DM_SETDEFID, IDOK/*IDC_ADDRBK_BUTTON_OK*/, 0);
lpAP->bLDAPinProgress = FALSE;
}
break;
case IDM_LVCONTEXT_FIND:
case IDC_ADDRBK_BUTTON_FIND:
if(!lpAP->bLDAPinProgress)
{
ADRPARM_FINDINFO apfi = {0};
LPADRPARM_FINDINFO lpapfi = NULL;
ULONG ulOldFlags = lpAP->lpAdrParms->ulFlags;
lpAP->bLDAPinProgress = TRUE;
apfi.DialogState = lpAP->DialogState;
if (lpAP->DialogState==STATE_SELECT_RECIPIENTS)
{
apfi.lpAdrParms = lpAP->lpAdrParms;
apfi.lppTo = lpAP_lppListTo;
apfi.lppCC = lpAP_lppListCC;
apfi.lppBCC = lpAP_lppListBCC;
lpapfi = &apfi;
}
else if (lpAP->DialogState == STATE_PICK_USER)
{
TCHAR sz[MAX_UI_STR];
LPTSTR lpsz = NULL;
LoadString(hinstMapiX, idsPickUserSelect, sz, CharSizeOf(sz));
lpsz = (LPTSTR) sz;
apfi.lpAdrParms = lpAP->lpAdrParms;
apfi.lpAdrParms->cDestFields = 1;
apfi.lpAdrParms->lppszDestTitles = &lpsz; // <TBD> use resource
apfi.lpAdrParms->ulFlags |= MAPI_UNICODE;
apfi.cbEntryID = 0;
apfi.lpEntryID = NULL;
apfi.nRetVal = 0;
lpapfi = &apfi;
{
// Setup the Find persistent info to show the name we are trying to resolve
ULONG i;
LPPTGDATA lpPTGData=GetThreadStoragePointer();
for(i=0;i<ldspMAX;i++)
{
pt_LDAPsp.szData[i][0] = TEXT('\0');
}
if(*(lpAP->lppAdrList))
{
for(i=0;i<(*(lpAP->lppAdrList))->aEntries[0].cValues;i++)
{
ULONG ulPropTag = PR_DISPLAY_NAME;
if(!(lpAP->lpAdrParms->ulFlags & MAPI_UNICODE))
ulPropTag = CHANGE_PROP_TYPE(ulPropTag, PT_STRING8);
if ((*(lpAP->lppAdrList))->aEntries[0].rgPropVals[i].ulPropTag == ulPropTag)
{
LPTSTR lpTitle = NULL;
SET_UNICODE_STR(lpTitle, (*(lpAP->lppAdrList))->aEntries[0].rgPropVals[i].Value.LPSZ,lpAP->lpAdrParms);
StrCpyN(pt_LDAPsp.szData[ldspDisplayName], lpTitle, ARRAYSIZE(pt_LDAPsp.szData[ldspDisplayName]));
FREE_UNICODE_STR(lpTitle, (*(lpAP->lppAdrList))->aEntries[0].rgPropVals[i].Value.LPSZ);
break;
}
}
}
}
}
//lpAP_bDontRefresh = TRUE;
HrShowSearchDialog(lpAP->lpIAB,
hDlg,
lpapfi,
(LPLDAPURL) NULL,
&(lpAP->SortInfo));
//lpAP_bDontRefresh = FALSE;
lpAP->bLDAPinProgress = FALSE;
// reset
lpAP->lpAdrParms->ulFlags = ulOldFlags;
if (lpAP->DialogState == STATE_PICK_USER)
{
// Reset these fake values
lpAP->lpAdrParms->cDestFields = 0;
lpAP->lpAdrParms->lppszDestTitles = NULL; // <TBD> use resource
// If the above dialog was CANCELed or CLOSEd, we dont do anything
// If the above dialog was closed with the Use button, then we basically
// have the person we were looking for .. we will just return that name
// and EntryID because that is all we need to return
if((lpapfi->nRetVal == SEARCH_USE) &&
lpapfi->lpEntryID &&
lpapfi->cbEntryID)
{
HCURSOR hOldCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
// Prevent the user from doing anything on this window ..
EnableWindow(hDlg, FALSE);
// Figure out what to do here ...
// We could add a hidden item to the listview, select it and send
// an ok message to the dialog which would then do the needful.
if(HR_FAILED(HrUpdateAdrListEntry(
lpAP->lpIAB,
lpapfi->lpEntryID,
lpapfi->cbEntryID,
(lpAP->lpAdrParms->ulFlags & MAPI_UNICODE)?MAPI_UNICODE:0,
lpAP->lppAdrList)))
{
lpAP->nRetVal = -1;
}
else
{
lpAP->nRetVal = ADDRESS_OK;
}
LocalFreeAndNull(&(lpapfi->lpEntryID));
lpapfi->cbEntryID = 0;
// Since we've done our processing, we'll fall thru to
// the cancel dialog
SetCursor(hOldCur);
SendMessage (hDlg, WM_COMMAND, (WPARAM) IDC_ADDRBK_BUTTON_CANCEL, 0);
}
}
}
break;
case IDC_ADDRBK_EDIT_QUICKFIND:
if(!lpAP->bLDAPinProgress)
{
lpAP->bLDAPinProgress = TRUE;
switch(HIWORD(wParam)) //check the notification code
{
case EN_CHANGE: //edit box changed
/***/
DoLVQuickFind((HWND)lParam,_hWndAddr);
/***
DoLVQuickFilter(lpAP->lpIAB,
(HWND)lParam,
_hWndAddr,
&(lpAP->SortInfo),
AB_FUZZY_FIND_NAME | AB_FUZZY_FIND_EMAIL,
1,
lpAP_lppContentsList);
***/
break;
}
lpAP->bLDAPinProgress = FALSE;
}
break;
case IDOK:
case IDC_ADDRBK_BUTTON_OK:
if(!lpAP->bLDAPinProgress)
{
HCURSOR hOldCur;
lpAP->nRetVal = ADDRESS_OK;
lpAP->hWaitCur = LoadCursor(NULL, IDC_WAIT);
hOldCur = SetCursor(lpAP->hWaitCur);
lpAP->bLDAPinProgress = TRUE;
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, MAKELONG(TRUE, 0));
//ShowWindow(hDlg, SW_HIDE);
//EnableWindow(hDlg, FALSE);
//SetWindowPos(hDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_ADDRBK_BUTTON_FIND), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_ADDRBK_BUTTON_TO), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_ADDRBK_BUTTON_CC), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_ADDRBK_BUTTON_BCC), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_ADDRBK_LIST_TO), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_ADDRBK_LIST_CC), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_ADDRBK_LIST_BCC), FALSE);
EnableWindow(_hWndAddr, FALSE);
//
// Do TEXT("OK") stuff here and then Fall Thru to the cancel stuff
// in PSN_RESET where we clean up
//
// if the ADDRESS_ONE flag was set we're supposed to return the
// selected entry
//
// else if wells were displayed we return the recipients in the AdrList
//
// else we dont change the AdrList ..
//
if (lpAP->DialogState == STATE_PICK_USER)
{
// We have been asked to return an entry in the LpAdrList,
// we dont care about recipient type - just Display Name and EntryID
// First check if anything is selected at all
int iItemIndex = ListView_GetNextItem(_hWndAddr,-1,LVNI_SELECTED);
if (iItemIndex != -1)
{
LPRECIPIENT_INFO lpItem = GetItemFromLV(_hWndAddr, iItemIndex);
if (lpItem)
{
if(HR_FAILED(HrUpdateAdrListEntry(
lpAP->lpIAB,
lpItem->lpEntryID,
lpItem->cbEntryID,
(lpAP->lpAdrParms->ulFlags & MAPI_UNICODE)?MAPI_UNICODE:0,
lpAP->lppAdrList)))
{
lpAP->nRetVal = -1;
}
}
}
}
else if ((lpAP->DialogState==STATE_SELECT_RECIPIENTS) && ((*lpAP_lppListTo)||(*lpAP_lppListCC)||(*lpAP_lppListBCC)))
{
//
//if user selected something in the TO/CC wells, we want to return
//a relevant AdrList back ...
//
ULONG ulcEntryCount = 0;
LPRECIPIENT_INFO lpItem = NULL;
//
// get a count of how many elements we need to return
//
lpItem = (*lpAP_lppListTo);
while(lpItem)
{
ulcEntryCount++;
lpItem = lpItem->lpNext;
}
lpItem = (*lpAP_lppListCC);
while(lpItem)
{
ulcEntryCount++;
lpItem = lpItem->lpNext;
}
lpItem = (*lpAP_lppListBCC);
while(lpItem)
{
ulcEntryCount++;
lpItem = lpItem->lpNext;
}
if (ulcEntryCount != 0)
{
ULONG nIndex = 0;
LPADRENTRY lpAdrEntryTemp = NULL;
LPADRLIST lpAdrList = NULL;
SCODE sc;
BOOL bProcessingCC = FALSE;
//
// if there was something in the passed in AdrList, free it and
// create a new list
//
if(!FAILED(sc = MAPIAllocateBuffer( sizeof(ADRLIST) + ulcEntryCount * sizeof(ADRENTRY),
&lpAdrList)))
{
lpAdrList->cEntries = ulcEntryCount;
nIndex = 0;
// Start getting items from the TO list
lpItem = (*lpAP_lppListTo);
while(nIndex < ulcEntryCount)
{
if (lpItem == NULL)
{
if (bProcessingCC == FALSE)
{
lpItem = (*lpAP_lppListCC);
bProcessingCC = TRUE;
}
else
lpItem = (*lpAP_lppListBCC);
}
if (lpItem != NULL)
{
LPSPropValue rgProps = NULL;
ULONG cValues = 0;
LPSPropValue lpPropArrayNew = NULL;
ULONG cValuesNew = 0;
LPTSTR lpszTemp = NULL;
LPVOID lpbTemp = NULL;
ULONG i = 0;
SCODE sc;
HRESULT hr = hrSuccess;
//reset hr
hr = hrSuccess;
// We are walking through our linked lists representing the TO and CC
// selected recipients. We want to return proper set of existing props
// for all the resolved users and the passed in set of props for the
// unresolved user. Hence we compare to see what we can get for each
// individual user. For unresolved users, the only distinctive criteria is
// their display name .. we have no other information .. <TBD> this is
// problematic because if there are 2 entries in the input adrlist with the
// same unresolved display name, even if they have difference rgPropVals
// we might end up giving them identical ones back .... what to do .. <TBD>
// Items that have entry ids are resolved ... items that dont have entryids
// are not resolved ...
if (lpItem->cbEntryID != 0)
{
// if this was an item from the original list .. we dont really
// want to mess with it irrespective of whether it is a resolved
// or unresolved entry.
// However, if this is a new entry, then we want to get its
// minimum props from the store ...
if (lpItem->ulOldAdrListEntryNumber == 0)
{
//resolved entry
hr = HrGetPropArray(lpAP->lpIAB,
(LPSPropTagArray) &ptaResolveDefaults,
lpItem->cbEntryID,
lpItem->lpEntryID,
(lpAP->lpAdrParms->ulFlags & MAPI_UNICODE) ? MAPI_UNICODE : 0,
&cValues,
&rgProps);
}
else
{
rgProps = NULL;
cValues = 0;
}
if (!HR_FAILED(hr))
{
if(lpItem->ulOldAdrListEntryNumber != 0)
{
ULONG index = lpItem->ulOldAdrListEntryNumber - 1; //remember the increment-by-one ..
// This is from the original entry list ...
// We want to merge the newly generated properties with the old
// original properties .. the original properties will include a
// PR_RECIPIENT_TYPE (or this entry would have been rejected)
sc = ScMergePropValues( (*(lpAP->lppAdrList))->aEntries[index].cValues,
(*(lpAP->lppAdrList))->aEntries[index].rgPropVals,
cValues,
rgProps,
&cValuesNew,
&lpPropArrayNew);
if (sc != S_OK)
{
// If errors then dont merge .. just take the temp set of props
// in rgProps
if (lpPropArrayNew)
MAPIFreeBuffer(lpPropArrayNew);
lpPropArrayNew = rgProps;
cValuesNew = cValues;
lpAP->nRetVal = -1;
}
else
{
// merged successfully, discard the temp sets of props
if (rgProps)
MAPIFreeBuffer(rgProps);
}
}
else
{
// totally new item
// we have to give it a valid PR_RECIPIENT_TYPE
// so create a new one and merge it with the above props
SPropValue Prop = {0};
Prop.ulPropTag = PR_RECIPIENT_TYPE;
Prop.Value.l = lpItem->ulRecipientType;
sc = ScMergePropValues( 1,
&Prop,
cValues,
rgProps,
&cValuesNew,
&lpPropArrayNew);
if (sc != S_OK)
{
// oops this failed
if (lpPropArrayNew)
MAPIFreeBuffer(lpPropArrayNew);
lpPropArrayNew = NULL;
lpAP->nRetVal = -1;
}
//free rgProps
if (rgProps)
MAPIFreeBuffer(rgProps);
} // end have previous adr list items
// [PaulHi] 2/15/99 Make sure that the new property string
// values are converted to ANSI if our client is non-UNICODE.
if ( !FAILED(sc) && !(lpAP->lpAdrParms->ulFlags & MAPI_UNICODE) && lpPropArrayNew )
{
sc = ScConvertWPropsToA((LPALLOCATEMORE) (&MAPIAllocateMore), lpPropArrayNew, cValuesNew, 0);
if (FAILED(sc))
{
if (lpPropArrayNew)
MAPIFreeBuffer(lpPropArrayNew);
lpPropArrayNew = NULL;
lpAP->nRetVal = -1;
}
}
} // end GetProps succeeded
}
else
{
// this is an unresolved entry
// we need to get its original sets of props from the original AdrList
if (lpItem->ulOldAdrListEntryNumber == 0)
{
// ouch - this kind of error shouldnt have happened
DebugPrintError(( TEXT("Address: Unresolved entry has no index number!!!\n")));
lpAP->nRetVal = -1; //error code
}
else
{
ULONG cb = 0;
ULONG index = lpItem->ulOldAdrListEntryNumber - 1; //remember to decrement the +1 increment
cValuesNew = (*(lpAP->lppAdrList))->aEntries[index].cValues;
// copy over the props from our old array into a new one
if (!(FAILED(sc = ScCountProps( cValuesNew,
(*(lpAP->lppAdrList))->aEntries[index].rgPropVals,
&cb))))
{
if (!(FAILED(sc = MAPIAllocateBuffer(cb, &lpPropArrayNew))))
{
if (FAILED(sc = ScCopyProps( cValuesNew,
(*(lpAP->lppAdrList))->aEntries[index].rgPropVals,
lpPropArrayNew,
NULL)))
{
DebugPrintError(( TEXT("Address: ScCopyProps fails!!!\n")));
lpAP->nRetVal = -1;
}
}
else
{
lpAP->nRetVal = -1;
}
}
else
{
lpAP->nRetVal = -1;
}
}
}
// At this point, if we've still got no errors,
// we should have a valid lpPropArrayNew and cValuesNew which we should
// be able to add to our new AdrList
if (lpAP->nRetVal != -1)
{
lpAdrList->aEntries[nIndex].cValues = cValuesNew;
lpAdrList->aEntries[nIndex].rgPropVals = lpPropArrayNew;
}
else
{
// some error
if (lpPropArrayNew)
{
MAPIFreeBuffer(lpPropArrayNew);
lpPropArrayNew = NULL;
}
}
lpItem = lpItem->lpNext;
nIndex++;
}
}
if (*(lpAP->lppAdrList))
{
FreePadrlist(*(lpAP->lppAdrList));
}
*(lpAP->lppAdrList) = lpAdrList;
}
}
}
else if ((lpAP->DialogState==STATE_SELECT_RECIPIENTS) && ((*lpAP_lppListTo)==NULL) && ((*lpAP_lppListCC)==NULL) && ((*lpAP_lppListBCC)==NULL))
{
// we were asked to select recipients but if these pointers are null
// then the user deleted the entries in the wells and we thus dont
// want to return anything. So free the lpaddrlist
// and make it NULL
if (*(lpAP->lppAdrList))
{
// Bug 27483 - dont NULL the lpAdrList - just set cEntries to 0
ULONG iEntry = 0;
for (iEntry = 0; iEntry < (*(lpAP->lppAdrList))->cEntries; iEntry++)
{
MAPIFreeBuffer((*(lpAP->lppAdrList))->aEntries[iEntry].rgPropVals);
}
(*(lpAP->lppAdrList))->cEntries = 0;
}
}
//
// Save the sort info to the registry
//
if(lpAP->DialogState != STATE_PICK_USER)
WriteRegistrySortInfo((LPIAB)lpAP->lpIAB, lpAP->SortInfo);
lpAP->bLDAPinProgress = FALSE;
lpAP->hWaitCur = NULL;
SetCursor(hOldCur);
}
// fall thru to cleanup code
case IDCANCEL:
case IDC_ADDRBK_BUTTON_CANCEL:
if(!lpAP->bLDAPinProgress)
{
if ((lpAP->nRetVal != ADDRESS_OK) && // Are we falling thru from above ??
(lpAP->nRetVal != -1) ) // or did someone trigger an error above ??
{
// if not ..
lpAP->nRetVal = ADDRESS_CANCEL;
}
if ((*lpAP_lppContentsList))
ClearListView( GetDlgItem(hDlg, IDC_ADDRBK_LIST_ADDRESSES),
lpAP_lppContentsList);
if ((*lpAP_lppListTo))
ClearListView( GetDlgItem(hDlg, IDC_ADDRBK_LIST_TO),
lpAP_lppListTo);
if ((*lpAP_lppListCC))
ClearListView( GetDlgItem(hDlg, IDC_ADDRBK_LIST_CC),
lpAP_lppListCC);
if ((*lpAP_lppListBCC))
ClearListView( GetDlgItem(hDlg, IDC_ADDRBK_LIST_BCC),
lpAP_lppListBCC);
lpAP->bLDAPinProgress = FALSE;
EndDialog(hDlg,lpAP->nRetVal);
return TRUE;
}
break;
}
break;
case WM_CLOSE:
//treat it like a cancel button
SendMessage (hDlg, WM_COMMAND, (WPARAM) IDC_ADDRBK_BUTTON_CANCEL, 0);
break;
case WM_CONTEXTMENU:
{
int id = GetDlgCtrlID((HWND)wParam);
//
//This call to the context menu may generate any one of several
//command messages - for properties and for delete, we need to
//know which List View initiated the command ...
//
lpAP->nContextID = id;
switch(id)
{
case IDC_ADDRBK_LIST_ADDRESSES:
if (lpAP->DialogState == STATE_BROWSE_MODAL)
ShowLVContextMenu( lvDialogModalABContents,
(HWND)wParam,
NULL, //GetDlgItem(hDlg, IDC_ADDRBK_COMBO_SHOWNAMES),
lParam,
(LPVOID) lpAP->lpAdrParms,
lpAP->lpIAB, NULL);
else
ShowLVContextMenu( lvDialogABContents,
(HWND)wParam,
NULL, //GetDlgItem(hDlg, IDC_ADDRBK_COMBO_SHOWNAMES),
lParam,
(LPVOID) lpAP->lpAdrParms,
lpAP->lpIAB, NULL);
break;
case IDC_ADDRBK_LIST_TO:
ShowLVContextMenu(lvDialogABTo,(HWND)wParam, NULL, lParam, NULL,lpAP->lpIAB, NULL);
break;
case IDC_ADDRBK_LIST_BCC:
ShowLVContextMenu(lvDialogABCC,(HWND)wParam, NULL, lParam, NULL,lpAP->lpIAB, NULL);
break;
case IDC_ADDRBK_LIST_CC:
ShowLVContextMenu(lvDialogABBCC,(HWND)wParam, NULL, lParam, NULL,lpAP->lpIAB, NULL);
break;
default:
//reset it ..
lpAP->nContextID = -1;
WABWinHelp((HWND) wParam,
g_szWABHelpFileName,
HELP_CONTEXTMENU,
(DWORD_PTR)(LPVOID) rgAddrHelpIDs );
break;
}
}
break;
case WM_NOTIFY:
{
LV_DISPINFO * pLvdi = (LV_DISPINFO *)lParam;
NM_LISTVIEW * pNm = (NM_LISTVIEW *)lParam;
switch((int) wParam)
{
case IDC_ADDRBK_LIST_TO:
case IDC_ADDRBK_LIST_CC:
case IDC_ADDRBK_LIST_BCC:
switch(((LV_DISPINFO *)lParam)->hdr.code)
{
case LVN_KEYDOWN:
switch(((LV_KEYDOWN FAR *) lParam)->wVKey)
{
case VK_DELETE:
if ((int) wParam == IDC_ADDRBK_LIST_TO)
ListDeleteItem(hDlg, (int) wParam, lpAP_lppListTo);
else if ((int) wParam == IDC_ADDRBK_LIST_CC)
ListDeleteItem(hDlg, (int) wParam, lpAP_lppListCC);
else
ListDeleteItem(hDlg, (int) wParam, lpAP_lppListBCC);
break;
}
break;
case NM_SETFOCUS:
lpAP->nContextID = GetDlgCtrlID(((NM_LISTVIEW *)lParam)->hdr.hwndFrom);
break;
case NM_DBLCLK:
//properties of the item ...
lpAP->nContextID = GetDlgCtrlID(((NM_LISTVIEW *)lParam)->hdr.hwndFrom);
SendMessage (hDlg, WM_COMMAND, (WPARAM) IDM_LVCONTEXT_PROPERTIES, 0);
break;
case NM_CUSTOMDRAW:
return ProcessLVCustomDraw(hDlg, lParam, TRUE);
break;
}
break;
case IDC_ADDRBK_LIST_ADDRESSES:
switch(pLvdi->hdr.code)
{
case LVN_KEYDOWN:
switch(((LV_KEYDOWN FAR *) lParam)->wVKey)
{
case VK_DELETE:
if (lpAP->DialogState == STATE_BROWSE_MODAL)
SendMessage(hDlg, WM_COMMAND, IDC_ADDRBK_BUTTON_DELETE, 0);
break;
}
break;
case LVN_COLUMNCLICK:
SortListViewColumn((LPIAB)lpAP->lpIAB, pNm->hdr.hwndFrom, pNm->iSubItem, &(lpAP->SortInfo), FALSE);
break;
case NM_CLICK:
case NM_RCLICK:
if(lpAP->DialogState == STATE_PICK_USER)
{
int iItemIndex = ListView_GetNextItem(pNm->hdr.hwndFrom,-1,LVNI_SELECTED);
if (iItemIndex == -1)
{
//Nothing is selected .. dont let them say OK
EnableWindow(GetDlgItem(hDlg,IDOK/*IDC_ADDRBK_BUTTON_OK*/),FALSE);
SendMessage (hDlg, DM_SETDEFID, IDCANCEL, 0);
}
else
{
EnableWindow(GetDlgItem(hDlg,IDOK/*IDC_ADDRBK_BUTTON_OK*/),TRUE);
SendMessage (hDlg, DM_SETDEFID, IDOK, 0);
}
}
break;
case NM_SETFOCUS:
lpAP->nContextID = GetDlgCtrlID(pNm->hdr.hwndFrom);
if(lpAP->DialogState == STATE_PICK_USER)
{
int iItemIndex = ListView_GetNextItem(pNm->hdr.hwndFrom,-1,LVNI_SELECTED);
if (iItemIndex == -1)
{
//Nothing is selected .. dont let them say OK
EnableWindow(GetDlgItem(hDlg,IDOK/*IDC_ADDRBK_BUTTON_OK*/),FALSE);
SendMessage (hDlg, DM_SETDEFID, IDCANCEL, 0);
}
else
{
EnableWindow(GetDlgItem(hDlg,IDOK/*IDC_ADDRBK_BUTTON_OK*/),TRUE);
SendMessage (hDlg, DM_SETDEFID, IDOK, 0);
}
}
break;
case NM_DBLCLK:
{
//if an entry is selected - do this - otherwise dont do anything
int iItemIndex = ListView_GetNextItem(pNm->hdr.hwndFrom,-1,LVNI_SELECTED);
if (iItemIndex == -1)
break;
{
//DWORD dwDefId = SendMessage(hDlg, DM_GETDEFID, 0, 0);
//if(dwDefId)
// SendMessage(hDlg, WM_COMMAND, (WPARAM) LOWORD(dwDefId), 0);
SendMessage(hDlg, WM_COMMAND, (WPARAM) IDC_ADDRBK_BUTTON_TO + lpAP->lpAdrParms->nDestFieldFocus, 0);
}
}
break;
case NM_CUSTOMDRAW:
return ProcessLVCustomDraw(hDlg, lParam, TRUE);
break;
}
break;
}
}
break;
default:
if( (g_msgMSWheel && message == g_msgMSWheel)
// || message == WM_MOUSEWHEEL
)
{
if(GetFocus() == GetDlgItem(hDlg, IDC_ADDRBK_LIST_TO))
SendMessage(GetDlgItem(hDlg, IDC_ADDRBK_LIST_TO), message, wParam, lParam);
else if(GetFocus() == GetDlgItem(hDlg, IDC_ADDRBK_LIST_CC))
SendMessage(GetDlgItem(hDlg, IDC_ADDRBK_LIST_CC), message, wParam, lParam);
else if(GetFocus() == GetDlgItem(hDlg, IDC_ADDRBK_LIST_BCC))
SendMessage(GetDlgItem(hDlg, IDC_ADDRBK_LIST_TO), message, wParam, lParam);
else
SendMessage(_hWndAddr, message, wParam, lParam);
}
break;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////////
//
// ListAddItem - Adds an item to the wells
//
// hDlg - HWND of parent
// hWndAddr - HWND of source ListView from which the item will be added
// CtlID - control ID of the target list view
// lppList - Item list corresponding to the target list view to which this item will be appended
// RecipientType - Specified recipient type to tag the new item with
//
/////////////////////////////////////////////////////////////////////////////////
BOOL ListAddItem(HWND hDlg, HWND hWndAddr, int CtlID, LPRECIPIENT_INFO * lppList, ULONG RecipientType)
{
BOOL bRet = FALSE;
int iItemIndex = 0;
HWND hWndList = GetDlgItem(hDlg,CtlID);
iItemIndex = ListView_GetNextItem(hWndAddr,-1,LVNI_SELECTED);
if (iItemIndex != -1)
{
int iLastIndex = 0;
do
{
// otherwise get the entry id of this thing
LPRECIPIENT_INFO lpItem = GetItemFromLV(hWndAddr, iItemIndex);
if (lpItem)
{
LV_ITEM lvI;
LPRECIPIENT_INFO lpNew = LocalAlloc(LMEM_ZEROINIT, sizeof(RECIPIENT_INFO));
if(!lpNew)
{
DebugPrintError(( TEXT("LocalAlloc failed to allocate memory\n")));
goto out;
}
lpNew->ulObjectType = lpItem->ulObjectType;
StrCpyN(lpNew->szDisplayName, lpItem->szDisplayName, ARRAYSIZE(lpNew->szDisplayName));
StrCpyN(lpNew->szByFirstName, lpItem->szByFirstName, ARRAYSIZE(lpNew->szByFirstName));
StrCpyN(lpNew->szByLastName, lpItem->szByLastName, ARRAYSIZE(lpNew->szByLastName));
StrCpyN(lpNew->szEmailAddress, lpItem->szEmailAddress, ARRAYSIZE(lpNew->szEmailAddress));
StrCpyN(lpNew->szHomePhone, lpItem->szHomePhone, ARRAYSIZE(lpNew->szHomePhone));
StrCpyN(lpNew->szOfficePhone, lpItem->szOfficePhone, ARRAYSIZE(lpNew->szOfficePhone));
lpNew->bHasCert = lpItem->bHasCert;
lpNew->ulRecipientType = RecipientType;
lpNew->ulOldAdrListEntryNumber = 0; //Flag this as not from the original AdrList
if (lpItem->cbEntryID)
{
lpNew->cbEntryID = lpItem->cbEntryID;
lpNew->lpEntryID = LocalAlloc(LMEM_ZEROINIT, lpItem->cbEntryID);
if(!lpNew->lpEntryID)
{
DebugPrintError(( TEXT("LocalAlloc failed to allocate memory\n")));
LocalFree(lpNew);
goto out;
}
CopyMemory(lpNew->lpEntryID,lpItem->lpEntryID,lpItem->cbEntryID);
}
lpNew->lpNext = (*lppList);
if (*lppList)
(*lppList)->lpPrev = lpNew;
lpNew->lpPrev = NULL;
(*lppList) = lpNew;
lvI.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
lvI.state = 0;
lvI.stateMask = 0;
lvI.iSubItem = 0;
lvI.cchTextMax = MAX_DISPLAY_NAME_LENGTH;
lvI.iImage = GetWABIconImage(lpNew);
// now fill in the List
lvI.iItem = ListView_GetItemCount(hWndList);
lvI.pszText = lpNew->szDisplayName;
lvI.lParam = (LPARAM) lpNew;
ListView_InsertItem(hWndList, &lvI);
ListView_EnsureVisible(hWndList,ListView_GetItemCount(hWndList)-1,FALSE);
}
iLastIndex = iItemIndex;
// Get next selected item ...
iItemIndex = ListView_GetNextItem(hWndAddr,iLastIndex,LVNI_SELECTED);
} while (iItemIndex != -1);
//SetFocus(hWndAddr);
}
else
{
ShowMessageBox(hDlg, IDS_ADDRBK_MESSAGE_NO_ITEMS_ADD, MB_ICONEXCLAMATION);
goto out;
}
if((ListView_GetItemCount(hWndList) > 0) &&
(ListView_GetSelectedCount(hWndList) <= 0))
LVSelectItem(hWndList, 0);
bRet = TRUE;
out:
return bRet;
}
/////////////////////////////////////////////////////////////////////////////////
//
// ListDeleteItem - deletes an item from the Wells - unlike the Address COntents list we
// make sure to delete it here because we want the linked lists to only have valid entries
//
//
/////////////////////////////////////////////////////////////////////////////////
BOOL ListDeleteItem(HWND hDlg, int CtlID, LPRECIPIENT_INFO * lppList)
{
BOOL bRet = TRUE;
LPRECIPIENT_INFO lpItem = NULL;
HWND hWndAddr = GetDlgItem(hDlg,CtlID);
int iItemIndex=0;
iItemIndex = ListView_GetNextItem(hWndAddr,-1,LVNI_SELECTED);
if (iItemIndex != -1)
{
int iLastItem = 0;
do
{
// otherwise get the entry id of this thing
lpItem = GetItemFromLV(hWndAddr, iItemIndex);
if (lpItem)
{
// remove this item from our linked list of arrays
// if this is the first item in the list then handle that special case too
if ((*lppList) == lpItem)
(*lppList) = lpItem->lpNext;
if (lpItem->lpNext)
lpItem->lpNext->lpPrev = lpItem->lpPrev;
if (lpItem->lpPrev)
lpItem->lpPrev->lpNext = lpItem->lpNext;
// we need to update our display
ListView_DeleteItem(hWndAddr,iItemIndex);
//UpdateWindow(hWndAddr);
FreeRecipItem(&lpItem);
}
iLastItem = iItemIndex;
// Get next selected item ...
iItemIndex = ListView_GetNextItem(hWndAddr,-1,LVNI_SELECTED);
}while (iItemIndex != -1);
// select the previous or next item ...
if (iLastItem >= ListView_GetItemCount(hWndAddr))
iLastItem = ListView_GetItemCount(hWndAddr) - 1;
LVSelectItem(hWndAddr, iLastItem);
}
SetFocus(hWndAddr);
return bRet;
}
/////////////////////////////////////////////////////////////////////////////////
//
// FillWells - Dismembers the lpAdrList to create the To and CC wells
//
// Scans the AdrEntry Structures in the LpAdrList, looks at PR_RECIPIENT_TYPE,
// ignores entries which it cant understand ... creates a temporary linked
// list of To and CC recipient lists which are used to populate the
// To and CC List boxes
//
/////////////////////////////////////////////////////////////////////////////////
BOOL FillWells(HWND hDlg, LPADRLIST lpAdrList, LPADRPARM lpAdrParms, LPRECIPIENT_INFO * lppListTo, LPRECIPIENT_INFO * lppListCC, LPRECIPIENT_INFO * lppListBCC)
{
BOOL bRet = FALSE;
LPRECIPIENT_INFO lpNew = NULL;
LPADRENTRY lpAdrEntry = NULL;
ULONG i=0,j=0,nLen=0;
int index=0;
LV_ITEM lvI;
HWND hWndAddr = NULL;
ULONG ulMapiTo = MAPI_TO;
ULONG ulMapiCC = MAPI_CC;
ULONG ulMapiBCC = MAPI_BCC;
BOOL bUnicode = (lpAdrParms->ulFlags & MAPI_UNICODE);
*lppListTo = NULL;
*lppListCC = NULL;
*lppListBCC = NULL;
if (lpAdrList == NULL) //nothing to do
{
bRet = TRUE;
goto out;
}
//
// The Input AdrParms structure has a lpulDestComps field that lets the
// caller specify his own recipient types. If this is missing, we are supposed
// to use the default recipient types.
//
if ((lpAdrParms->cDestFields > 0) && (lpAdrParms->lpulDestComps))
{
ULONG i=0;
for (i=0;i<lpAdrParms->cDestFields;i++)
{
switch(i)
{
case 0:
ulMapiTo = lpAdrParms->lpulDestComps[i];
break;
case 1:
ulMapiCC = lpAdrParms->lpulDestComps[i];
break;
case 2:
ulMapiBCC = lpAdrParms->lpulDestComps[i];
break;
}
}
}
for(i=0; i < lpAdrList->cEntries; i++)
{
lpAdrEntry = &(lpAdrList->aEntries[i]);
if (lpAdrEntry->cValues != 0)
{
TCHAR szBuf[MAX_DISPLAY_NAME_LENGTH];
ULONG ulRecipientType = 0;
ULONG ulObjectType = 0;
ULONG cbEntryID = 0;
BOOL bHasCert = FALSE;
LPENTRYID lpEntryID = NULL;
szBuf[0]='\0';
for(j=0;j<lpAdrEntry->cValues;j++)
{
ULONG ulPropTag = lpAdrEntry->rgPropVals[j].ulPropTag;
if(!bUnicode && PROP_TYPE(ulPropTag) == PT_STRING8)
ulPropTag = CHANGE_PROP_TYPE(ulPropTag, PT_UNICODE);
switch(ulPropTag)
{
case(PR_DISPLAY_NAME):
{
LPTSTR lpNameW = NULL;
SET_UNICODE_STR(lpNameW, lpAdrEntry->rgPropVals[j].Value.LPSZ,lpAdrParms);
nLen = CopyTruncate(szBuf, lpNameW, MAX_DISPLAY_NAME_LENGTH);
FREE_UNICODE_STR(lpNameW, lpAdrEntry->rgPropVals[j].Value.LPSZ);
}
break;
case(PR_RECIPIENT_TYPE):
ulRecipientType = lpAdrEntry->rgPropVals[j].Value.l;
break;
case(PR_OBJECT_TYPE):
ulObjectType = lpAdrEntry->rgPropVals[j].Value.l;
break;
case(PR_ENTRYID):
cbEntryID = lpAdrEntry->rgPropVals[j].Value.bin.cb;
lpEntryID = (LPENTRYID) lpAdrEntry->rgPropVals[j].Value.bin.lpb;
break;
case PR_USER_X509_CERTIFICATE:
bHasCert = TRUE;
break;
}
}
if (lstrlen(szBuf) && ((ulRecipientType == ulMapiBCC) || (ulRecipientType == ulMapiTo) || (ulRecipientType == ulMapiCC)))
{
lpNew = LocalAlloc(LMEM_ZEROINIT, sizeof(RECIPIENT_INFO));
if(!lpNew)
{
DebugPrintError(( TEXT("LocalAlloc failed to allocate memory\n")));
goto out;
}
// ***NOTE***
// Store this index number, ie 1st item in AdrList is 1, then 2, 3, so on
// we do a plus 1 here because 0 value means it wasnt passed in and thus the
// minimum valid value is 1
lpNew->ulOldAdrListEntryNumber = i+1;
lpNew->bHasCert = bHasCert;
StrCpyN(lpNew->szDisplayName,szBuf,ARRAYSIZE(lpNew->szDisplayName));
lpNew->ulRecipientType = ulRecipientType;
lpNew->ulObjectType = ulObjectType;
if (cbEntryID != 0)
{
lpNew->cbEntryID = cbEntryID;
lpNew->lpEntryID = LocalAlloc(LMEM_ZEROINIT,cbEntryID);
if(!lpNew->lpEntryID)
{
DebugPrintError(( TEXT("LocalAlloc failed to allocate memory\n")));
goto out;
}
CopyMemory(lpNew->lpEntryID,lpEntryID,cbEntryID);
}
if (ulRecipientType == ulMapiTo)
{
lpNew->lpNext = *lppListTo;
if (*lppListTo)
(*lppListTo)->lpPrev = lpNew;
lpNew->lpPrev = NULL;
*lppListTo = lpNew;
}
else if (ulRecipientType == ulMapiCC)
{
lpNew->lpNext = *lppListCC;
if (*lppListCC)
(*lppListCC)->lpPrev = lpNew;
lpNew->lpPrev = NULL;
*lppListCC = lpNew;
}
else if (ulRecipientType == ulMapiBCC)
{
lpNew->lpNext = *lppListBCC;
if (*lppListBCC)
(*lppListBCC)->lpPrev = lpNew;
lpNew->lpPrev = NULL;
*lppListBCC = lpNew;
}
}
}
}
lvI.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
lvI.state = 0;
lvI.stateMask = 0;
lvI.iSubItem = 0;
lvI.cchTextMax = MAX_DISPLAY_NAME_LENGTH;
for(i=0;i<3;i++)
{
switch(i)
{
case 0:
lpNew = *lppListTo;
break;
case 1:
lpNew = *lppListCC;
break;
case 2:
lpNew = *lppListBCC;
break;
}
hWndAddr = GetDlgItem(hDlg, IDC_ADDRBK_LIST_TO+i);
index = 0;
while(lpNew)
{
lvI.iItem = index;
lvI.pszText = lpNew->szDisplayName;
lvI.lParam = (LPARAM) lpNew;
lvI.iImage = GetWABIconImage(lpNew);
ListView_InsertItem(hWndAddr, &lvI);
index++;
lpNew = lpNew->lpNext;
}
}
// We will highlight the first item in any filled list box
// because basically that looks good when tabbing through them ...
for(i=0;i<lpAdrParms->cDestFields;i++)
{
HWND hWndLV = GetDlgItem(hDlg, IDC_ADDRBK_LIST_TO+i);
if (ListView_GetItemCount(hWndLV) > 0)
LVSelectItem(hWndLV,0);
}
bRet = TRUE;
out:
return bRet;
}
/////////////////////////////////////////////////////////////////////////////////
//
// SetAddressBookUI - juggles the address book UI in response to various parameters
//
// This function will probably be more complex with each tier
//
//
//
/////////////////////////////////////////////////////////////////////////////////
BOOL SetAddressBookUI(HWND hDlg,
LPADDRESS_PARMS lpAP)
{
BOOL bRet = FALSE;
//LV_COLUMN lvC;
RECT rc, rc1, rc2;
POINT ptLU1,ptRB1;
int nButtonsVisible = 0;
int nButtonSpacing = 7;
int nButtonWidth = 0;
ULONG nLen = 0;
TCHAR szBuf[MAX_UI_STR*4];
LPPTGDATA lpPTGData=GetThreadStoragePointer();
HWND hWndListAddresses = GetDlgItem(hDlg, IDC_ADDRBK_LIST_ADDRESSES);
LPTSTR szCaption = NULL;
SET_UNICODE_STR(szCaption, lpAP->lpAdrParms->lpszCaption,lpAP->lpAdrParms);
if(!szCaption || !lstrlen(szCaption))
{
LoadString(hinstMapiX, IDS_ADDRBK_CAPTION, szBuf, CharSizeOf(szBuf));
szCaption = szBuf;
}
// Set the font of all the children to the default GUI font
EnumChildWindows( hDlg,
SetChildDefaultGUIFont,
(LPARAM) 0);
if(pt_bIsWABOpenExSession || bIsWABSessionProfileAware((LPIAB)lpAP->lpIAB))
{
// Fill in the Combo with the container names
FillContainerCombo(GetDlgItem(hDlg, IDC_ADDRBK_COMBO_CONT), (LPIAB)lpAP->lpIAB);
}
else
{
HWND hWndCombo = GetDlgItem(hDlg, IDC_ADDRBK_COMBO_CONT);
EnableWindow(hWndCombo, FALSE);
ShowWindow(hWndCombo, SW_HIDE);
// resize the listview to take place of the hidden combo
GetWindowRect(hWndCombo,&rc2);
GetWindowRect(hWndListAddresses,&rc);
//
//This api works for both mirrored and unmirrored windows.
//
MapWindowPoints(NULL, hDlg, (LPPOINT)&rc2, 2);
MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
ptLU1.x = rc2.left;
ptLU1.y = rc2.top;
ptRB1.x = rc.right;
ptRB1.y = rc.bottom;
MoveWindow(hWndListAddresses,ptLU1.x,ptLU1.y,(ptRB1.x - ptLU1.x), (ptRB1.y - ptLU1.y), TRUE);
}
//
// There are only two states that need configuration -
// Pick User - in which we have to hide the wells
// and
// Select Recipients, in which we have to hide the wells
// as per the input criteria and resize accordingly and
// also set the labels based on the input criteria
//
if (lpAP->DialogState == STATE_SELECT_RECIPIENTS)
{
SendMessage (hDlg, DM_SETDEFID, IDC_ADDRBK_BUTTON_TO, 0);
// in case the nDestFieldFocus parameter is supplied, use it ..
if (
(lpAP->lpAdrParms->nDestFieldFocus < lpAP->lpAdrParms->cDestFields))
{
if (lpAP->lpAdrParms->nDestFieldFocus == 1)
SendMessage (hDlg, DM_SETDEFID, IDC_ADDRBK_BUTTON_CC, 0);
else if (lpAP->lpAdrParms->nDestFieldFocus == 2)
SendMessage (hDlg, DM_SETDEFID, IDC_ADDRBK_BUTTON_BCC, 0);
}
}
else if (lpAP->DialogState == STATE_PICK_USER)
SendMessage (hDlg, DM_SETDEFID, IDOK/*IDC_ADDRBK_BUTTON_OK*/, 0);
else if (lpAP->DialogState == STATE_BROWSE_MODAL)
SendMessage (hDlg, DM_SETDEFID, IDC_ADDRBK_BUTTON_PROPS, 0);
// Set the window caption
if (szCaption)
SetWindowText(hDlg,szCaption);
// Set the caption over the destination wells
if (lpAP->lpAdrParms->lpszDestWellsTitle)
{
LPWSTR lpTitle = NULL; // <note> assumes UNICODE defined
SET_UNICODE_STR(lpTitle,lpAP->lpAdrParms->lpszDestWellsTitle,lpAP->lpAdrParms);
SetDlgItemText(hDlg,IDC_ADDRBK_STATIC_RECIP_TITLE,lpTitle);
FREE_UNICODE_STR(lpTitle, lpAP->lpAdrParms->lpszDestWellsTitle);
}
if (lpAP->DialogState == STATE_PICK_USER &&
*(lpAP->lppAdrList) )
{
ULONG i=0;
LPTSTR lpszRecipName = NULL;
//Get the user whose name we are trying to find
for(i=0;i<(*(lpAP->lppAdrList))->aEntries[0].cValues;i++)
{
ULONG ulPropTag = PR_DISPLAY_NAME;
if(!(lpAP->lpAdrParms->ulFlags & MAPI_UNICODE))
ulPropTag = CHANGE_PROP_TYPE(ulPropTag, PT_STRING8);
if ((*(lpAP->lppAdrList))->aEntries[0].rgPropVals[i].ulPropTag == ulPropTag)
{
SET_UNICODE_STR(lpszRecipName,(*(lpAP->lppAdrList))->aEntries[0].rgPropVals[i].Value.LPSZ,lpAP->lpAdrParms);
break;
}
}
if(lpszRecipName)
{
LPTSTR lpszBuffer = NULL;
TCHAR szTmp[MAX_PATH], *lpszTmp;
LoadString(hinstMapiX, IDS_ADDRBK_RESOLVE_CAPTION, szBuf, CharSizeOf(szBuf));
CopyTruncate(szTmp, lpszRecipName, MAX_PATH - 1);
lpszTmp = szTmp;
if(FormatMessage( FORMAT_MESSAGE_FROM_STRING |
FORMAT_MESSAGE_ARGUMENT_ARRAY |
FORMAT_MESSAGE_ALLOCATE_BUFFER,
szBuf,
0,0, //ignored
(LPTSTR) &lpszBuffer,
MAX_UI_STR,
(va_list *)&lpszTmp))
{
// if the display name is too long, it doesnt show up properly in the UI ..
// so we will purposely limit the visible portion to 64 characters - arbitarily defined limit..
szBuf[0]='\0';
nLen = CopyTruncate(szBuf, lpszBuffer, 2 * MAX_DISPLAY_NAME_LENGTH);
LocalFreeAndNull(&lpszBuffer);
}
//Increase the size of the static control to = what the Contents List width will be
GetWindowRect(GetDlgItem(hDlg,IDC_ADDRBK_STATIC_CONTENTS),&rc2);
GetWindowRect(GetDlgItem(hDlg,IDC_ADDRBK_LIST_TO),&rc);
//
//This api working in both mirrored and unmirrored windows.
//
MapWindowPoints(NULL, hDlg, (LPPOINT)&rc2, 2);
MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
ptLU1.x = rc2.left;
ptLU1.y = rc2.top;
ptRB1.x = rc.right;
ptRB1.y = rc2.bottom;
MoveWindow(GetDlgItem(hDlg,IDC_ADDRBK_STATIC_CONTENTS),ptLU1.x,ptLU1.y,(ptRB1.x - ptLU1.x), (ptRB1.y - ptLU1.y), TRUE);
SetDlgItemText(hDlg,IDC_ADDRBK_STATIC_CONTENTS,szBuf);
FREE_UNICODE_STR(lpszRecipName,(*(lpAP->lppAdrList))->aEntries[0].rgPropVals[i].Value.LPSZ);
}
}
if (lpAP->DialogState == STATE_PICK_USER)
{
// If ADDRESS_ONE has been selected, then make the IDC_ADDRBK_LIST_ADDRESSES
// single selection only
DWORD dwStyle;
dwStyle = GetWindowLong(hWndListAddresses, GWL_STYLE);
SetWindowLong(hWndListAddresses, GWL_STYLE, dwStyle | LVS_SINGLESEL);
}
if ((lpAP->DialogState == STATE_PICK_USER)||(lpAP->DialogState == STATE_BROWSE_MODAL))
{
int i = 0;
// Dont show wells which means we have to do some rearranging
// * Hide the wells and the To, CC, BCC buttons
// * Resize the IDC_ADDRBK_LIST_ADDRESSES to fill the whole dialog
// * Move the 3 buttons below it to the left side of the dialog
//
// Get the dimensions of the ToListBox
GetWindowRect(GetDlgItem(hDlg,IDC_ADDRBK_LIST_TO),&rc2);
GetWindowRect(hWndListAddresses,&rc);
//
//This api works for in both mirrored and unmirrored windows.
//
MapWindowPoints(NULL, hDlg, (LPPOINT)&rc2, 2);
MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
ptLU1.x = rc.left;
ptLU1.y = rc.top;
ptRB1.x = rc2.right;
ptRB1.y = rc.bottom;
MoveWindow(hWndListAddresses,ptLU1.x,ptLU1.y,(ptRB1.x - ptLU1.x), (ptRB1.y - ptLU1.y), TRUE);
for(i=0;i<3;i++)
{
ShowWindow(GetDlgItem(hDlg, IDC_ADDRBK_BUTTON_TO + i), SW_HIDE);
ShowWindow(GetDlgItem(hDlg, IDC_ADDRBK_LIST_TO + i), SW_HIDE);
}
ShowWindow(GetDlgItem(hDlg, IDC_ADDRBK_STATIC_RECIP_TITLE), SW_HIDE); // TEXT("Message Recipients") label
}
// other things to do
// Load Headers for List box
GetWindowRect(hWndListAddresses,&rc);
HrInitListView(hWndListAddresses, LVS_REPORT, TRUE);
GetWindowRect(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_PROPS),&rc2);
nButtonsVisible = 2;
nButtonWidth = (rc2.right - rc2.left);
// get the new coordinates of the 1st visible button
//
//This api working in both mirrored and unmirrored windows.
//
MapWindowPoints(NULL, hDlg, (LPPOINT)&rc2, 2);
MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
ptLU1.x = rc.left;
ptLU1.y = rc2.top;
ptRB1.x = ptLU1.x + nButtonWidth;
ptRB1.y = rc2.bottom;
MoveWindow(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_NEW),ptLU1.x,ptLU1.y,nButtonWidth, (ptRB1.y - ptLU1.y), TRUE);
ptLU1.x += nButtonWidth + nButtonSpacing;
ptRB1.x = ptLU1.x + nButtonWidth;
if (lpAP->DialogState == STATE_BROWSE_MODAL)
{
MoveWindow(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_NEWGROUP),ptLU1.x,ptLU1.y,nButtonWidth, (ptRB1.y - ptLU1.y), TRUE);
ptLU1.x += nButtonWidth + nButtonSpacing;
ptRB1.x = ptLU1.x + nButtonWidth;
}
else
{
// The NewGroup button is visible only in the DialogModalView
EnableWindow(GetDlgItem(hDlg, IDC_ADDRBK_BUTTON_NEWGROUP), FALSE);
ShowWindow(GetDlgItem(hDlg, IDC_ADDRBK_BUTTON_NEWGROUP), SW_HIDE);
}
MoveWindow(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_PROPS),ptLU1.x,ptLU1.y,nButtonWidth, (ptRB1.y - ptLU1.y), TRUE);
ptLU1.x += nButtonWidth + nButtonSpacing;
ptRB1.x = ptLU1.x + nButtonWidth;
MoveWindow(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_DELETE),ptLU1.x,ptLU1.y,nButtonWidth, (ptRB1.y - ptLU1.y), TRUE);
// The delete button is visible only in the DialogModalView
if (lpAP->DialogState != STATE_BROWSE_MODAL)
{
EnableWindow(GetDlgItem(hDlg, IDC_ADDRBK_BUTTON_DELETE), FALSE);
ShowWindow(GetDlgItem(hDlg, IDC_ADDRBK_BUTTON_DELETE), SW_HIDE);
}
//
// We now need to customize this window if we are selecting
// recipients ...
//
if (lpAP->DialogState == STATE_SELECT_RECIPIENTS)
{
// We need to see which wells are visible and
// then we need to resize the buttons based on their captions
//
int i=0;
int nLen=0;
int cDF = lpAP->lpAdrParms->cDestFields;
int iLeft=0,iTop=0;
SIZE size={0};
ULONG MaxWidth=0;
ULONG maxHeightPerLV = 0;
HWND hw;
HDC hdc=GetDC(hDlg);
if (lpAP->lpAdrParms->lppszDestTitles)
{
for(i=0; i < cDF; i++)
{
LPTSTR lpTitle = NULL;
ULONG Len = 0;
SET_UNICODE_STR(lpTitle,lpAP->lpAdrParms->lppszDestTitles[i],lpAP->lpAdrParms);
if(!lpTitle)
continue;
Len = lstrlen(lpTitle);
if (Len > CharSizeOf(szBuf) - 4)
{
ULONG iLen = TruncatePos(lpTitle, CharSizeOf(szBuf) - 4);
CopyMemory(szBuf,lpTitle,iLen*sizeof(TCHAR));
szBuf[iLen] = '\0';
}
else
{
StrCpyN(szBuf,lpTitle,ARRAYSIZE(szBuf));
}
StrCatBuff(szBuf,szArrow,ARRAYSIZE(szBuf));
if (lstrlen(szBuf) >= nLen)
{
nLen = lstrlen(szBuf);
GetTextExtentPoint32(hdc, szBuf, nLen, &size);
MaxWidth = size.cx;
}
// Set the new text
SetDlgItemText(hDlg,IDC_ADDRBK_BUTTON_TO+i,szBuf);
FREE_UNICODE_STR(lpTitle,lpAP->lpAdrParms->lppszDestTitles[i]);
}
}
ReleaseDC(hDlg,hdc);
if (MaxWidth == 0)
{
//get the default width
GetWindowRect(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_TO),&rc1);
MaxWidth = rc1.right - rc1.left;
}
//Get the maximum allowable height per well
GetWindowRect(hWndListAddresses,&rc);
GetChildClientRect(hWndListAddresses, &rc);
GetWindowRect(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_NEW),&rc1);
GetChildClientRect(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_NEW), &rc1);
maxHeightPerLV = (rc1.bottom-rc.top - (cDF - 1)*CONTROL_SPACING)/cDF;
iTop = rc.top;
for(i=0;i<cDF;i++)
{
hw = GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_TO + i);
// resize the buttons to fit the text
GetWindowRect(hw,&rc1);
GetChildClientRect(hw,&rc1);
MoveWindow(hw,rc1.left,iTop,MaxWidth,rc1.bottom - rc1.top,FALSE);
iLeft = rc1.left + MaxWidth + 2*CONTROL_SPACING;
// Move the list boxes to accomodate the resized buttons
hw = GetDlgItem(hDlg,IDC_ADDRBK_LIST_TO + i);
GetWindowRect(hw, &rc1);
GetChildClientRect(hw, &rc1);
MoveWindow(hw,iLeft,iTop,rc1.right-iLeft,maxHeightPerLV,FALSE);
ListView_SetExtendedListViewStyle(hw,LVS_EX_FULLROWSELECT);
iTop += maxHeightPerLV + CONTROL_SPACING;
}
//Move the label over the wells and restrict it's size
hw = GetDlgItem(hDlg,IDC_ADDRBK_STATIC_RECIP_TITLE);
GetWindowRect(hw, &rc2);
GetChildClientRect(hw, &rc2);
if(pt_bIsWABOpenExSession || bIsWABSessionProfileAware((LPIAB)lpAP->lpIAB)) // need to move this to the same height as combo
{
int ht = rc2.bottom - rc2.top;
rc2.bottom = rc.top - CONTROL_SPACING;
rc2.top = rc2.bottom - ht;
}
MoveWindow(hw,iLeft,rc2.top,rc1.right-iLeft,rc2.bottom-rc2.top,FALSE);
// Now we have the position and width of the list boxes .. need to get their height
if (cDF!=3) //if not the default preset position, reposition
{
switch(cDF)
{
case 1:
ShowWindow(GetDlgItem(hDlg, IDC_ADDRBK_BUTTON_CC), SW_HIDE);
ShowWindow(GetDlgItem(hDlg, IDC_ADDRBK_LIST_CC), SW_HIDE);
case 2:
ShowWindow(GetDlgItem(hDlg, IDC_ADDRBK_BUTTON_BCC), SW_HIDE);
ShowWindow(GetDlgItem(hDlg, IDC_ADDRBK_LIST_BCC), SW_HIDE);
break;
}
}
for(i=0;i<cDF;i++)
HrInitListView(GetDlgItem(hDlg, IDC_ADDRBK_LIST_TO + i), LVS_REPORT, FALSE);
/***
// Add a column to the To,CC,BCC List Boxes
GetWindowRect(GetDlgItem(hDlg,IDC_ADDRBK_LIST_TO),&rc);
lvC.mask = LVCF_FMT | LVCF_WIDTH;// | LVCF_TEXT;
lvC.fmt = LVCFMT_LEFT;
lvC.cx = (rc.right - rc.left)-20;
lvC.iSubItem = 0;
lvC.pszText = NULL; // TEXT(" 'TO' Recipients");
ListView_InsertColumn(GetDlgItem(hDlg,IDC_ADDRBK_LIST_TO),lvC.iSubItem, &lvC);
ListView_InsertColumn(GetDlgItem(hDlg,IDC_ADDRBK_LIST_CC),lvC.iSubItem, &lvC);
ListView_InsertColumn(GetDlgItem(hDlg,IDC_ADDRBK_LIST_BCC),lvC.iSubItem, &lvC);
/***/
for (i=0;i<cDF;i++)
{
ShowWindow(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_TO+i), SW_SHOWNORMAL);
UpdateWindow(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_TO+i));
ShowWindow(GetDlgItem(hDlg,IDC_ADDRBK_LIST_TO+i), SW_SHOWNORMAL);
UpdateWindow(GetDlgItem(hDlg,IDC_ADDRBK_LIST_TO+i));
}
}
// The window is taking too long to display with several 100 entries in the
// property store ... so we force all the contents to visible so that we
// can view the fill contents ...
//ShowWindow(GetDlgItem(hDlg,IDC_ADDRBK_LIST_ADDRESSES), SW_SHOWNORMAL);
//UpdateWindow(GetDlgItem(hDlg,IDC_ADDRBK_LIST_ADDRESSES));
ShowWindow(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_PROPS), SW_SHOWNORMAL);
UpdateWindow(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_PROPS));
ShowWindow(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_NEW), SW_SHOWNORMAL);
UpdateWindow(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_NEW));
ShowWindow(GetDlgItem(hDlg,IDOK/*IDC_ADDRBK_BUTTON_OK*/), SW_SHOWNORMAL);
UpdateWindow(GetDlgItem(hDlg,IDOK/*IDC_ADDRBK_BUTTON_OK*/));
ShowWindow(GetDlgItem(hDlg,IDCANCEL/*IDC_ADDRBK_BUTTON_CANCEL*/), SW_SHOWNORMAL);
UpdateWindow(GetDlgItem(hDlg,IDCANCEL/*IDC_ADDRBK_BUTTON_CANCEL*/));
ShowWindow(GetDlgItem(hDlg,IDC_ADDRBK_STATIC_CONTENTS), SW_SHOWNORMAL);
UpdateWindow(GetDlgItem(hDlg,IDC_ADDRBK_STATIC_CONTENTS));
ShowWindow(GetDlgItem(hDlg,IDC_ADDRBK_STATIC_15), SW_SHOWNORMAL);
UpdateWindow(GetDlgItem(hDlg,IDC_ADDRBK_STATIC_15));
ShowWindow(hDlg,SW_SHOWNORMAL);
UpdateWindow(hDlg);
{
// HICON hIcon = LoadIcon(hinstMapiX,MAKEINTRESOURCE(IDI_ICON_FIND));
// associate the icon with the button.
// SendMessage(GetDlgItem(hDlg,IDC_ADDRBK_BUTTON_FIND),BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)(HANDLE)hIcon);
}
bRet = TRUE;
if( szCaption != lpAP->lpAdrParms->lpszCaption &&
szCaption != szBuf)
LocalFreeAndNull(&szCaption);
return bRet;
}
//$$///////////////////////////////////////////////////////////////////////////////////////////
//
// UpdateLVItems ....
// When we call properties on an object, its props can change ...
// Since the particular user may appear in any of the 4 list views,
// we have to make sure that all views are updated for that entry
//
///////////////////////////////////////////////////////////////////////////////////////////////
void UpdateLVItems(HWND hWndLV,LPTSTR lpszName)
{
// We have the handle to the list view initiating the Properties call
// We know the old name to look for
//
// We know which item is selected - we can get its entryid and lParam
// We then search all the list views for the old display name
// if the old display name matches, we compare the entry id
// if the entryid matches, then we update that item ...
int iItemIndex = 0, iLastItemIndex = 0;
LPRECIPIENT_INFO lpOriginalItem;
ULONG i=0;
ULONG nCount = 0;
int id = 0;
HWND hDlg = GetParent(hWndLV);
HWND hw = NULL;
LV_FINDINFO lvf={0};
if ( (ListView_GetSelectedCount(hWndLV) != 1) ||
(lpszName == NULL) )
{
goto out;
}
iItemIndex = ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED);
lpOriginalItem = GetItemFromLV(hWndLV, iItemIndex);
if(!lpOriginalItem)
goto out;
// There can be upto 4 list view boxes in the view, each of which can
// contain a displayed copy of this item ..
// We want to go through all 4 and update all entries that match this item
// Our strategy is to search for each and every item that
// matches the display name - check its entry ID and if
// the entry ID matches, update it ...
lvf.flags = LVFI_STRING;
lvf.psz = lpszName;
for(i=0;i<4;i++)
{
switch(i)
{
case 0:
id = IDC_ADDRBK_LIST_ADDRESSES;
break;
case 1:
id = IDC_ADDRBK_LIST_TO;
break;
case 2:
id = IDC_ADDRBK_LIST_CC;
break;
case 3:
id = IDC_ADDRBK_LIST_BCC;
break;
}
hw = GetDlgItem(hDlg,id);
// if its hidden, ignore it
if (!IsWindowVisible(hw))
continue;
// if its empty, ignore it
nCount = ListView_GetItemCount(hw);
if (nCount <= 0)
continue;
// The contents list view wont have duplicates so ignore it if its the original
if ((id == IDC_ADDRBK_LIST_ADDRESSES) &&
(hw == hWndLV))
continue;
// see if we can find the matching items
iLastItemIndex = -1;
iItemIndex = ListView_FindItem(hw,iLastItemIndex,&lvf);
while (iItemIndex != -1)
{
// inspect this item
LPRECIPIENT_INFO lpItem = GetItemFromLV(hWndLV, iItemIndex);
if (lpItem && (lpItem->cbEntryID != 0) && (lpOriginalItem->cbEntryID == lpItem->cbEntryID))
{
if(!memcmp(lpOriginalItem->lpEntryID,lpItem->lpEntryID,lpItem->cbEntryID))
{
// this is the same item ... update it
if (lstrcmpi(lpItem->szDisplayName,lpOriginalItem->szDisplayName))
{
ListView_SetItemText(hw,iItemIndex,colDisplayName,lpOriginalItem->szDisplayName);
StrCpyN(lpItem->szDisplayName,lpOriginalItem->szDisplayName,ARRAYSIZE(lpItem->szDisplayName));
}
if (lstrcmpi(lpItem->szEmailAddress,lpOriginalItem->szEmailAddress))
{
ListView_SetItemText(hw,iItemIndex,colEmailAddress,lpOriginalItem->szEmailAddress);
StrCpyN(lpItem->szEmailAddress,lpOriginalItem->szEmailAddress,ARRAYSIZE(lpItem->szEmailAddress));
}
if (lstrcmpi(lpItem->szHomePhone,lpOriginalItem->szHomePhone))
{
ListView_SetItemText(hw,iItemIndex,colHomePhone,lpOriginalItem->szHomePhone);
StrCpyN(lpItem->szHomePhone,lpOriginalItem->szHomePhone,ARRAYSIZE(lpItem->szHomePhone));
}
if (lstrcmpi(lpItem->szOfficePhone,lpOriginalItem->szOfficePhone))
{
ListView_SetItemText(hw,iItemIndex,colOfficePhone,lpOriginalItem->szOfficePhone);
StrCpyN(lpItem->szOfficePhone,lpOriginalItem->szOfficePhone,ARRAYSIZE(lpItem->szOfficePhone));
}
if (lstrcmpi(lpItem->szByFirstName,lpOriginalItem->szByFirstName))
StrCpyN(lpItem->szByFirstName,lpOriginalItem->szByFirstName,ARRAYSIZE(lpItem->szByFirstName));
if (lstrcmpi(lpItem->szByLastName,lpOriginalItem->szByLastName))
StrCpyN(lpItem->szByLastName,lpOriginalItem->szByLastName,ARRAYSIZE(lpItem->szByLastName));
}
}
iLastItemIndex = iItemIndex;
iItemIndex = ListView_FindItem(hw,iLastItemIndex,&lvf);
}
}
out:
return;
}
//$$///////////////////////////////////////////////////////////////////////////////////////////
//
// ShowAddrBkLVProps ....
//
///////////////////////////////////////////////////////////////////////////////////////////////
void ShowAddrBkLVProps(LPIAB lpIAB, HWND hDlg, HWND hWndAddr,LPADDRESS_PARMS lpAP, LPFILETIME lpftLast)
{
// get the display name of this item
TCHAR szName[MAX_DISPLAY_NAME_LENGTH];
szName[0]='\0';
if (ListView_GetSelectedCount(hWndAddr) == 1)
{
ListView_GetItemText( hWndAddr,
ListView_GetNextItem(hWndAddr,-1,LVNI_SELECTED),
0,
szName,
CharSizeOf(szName));
}
if( (MAPI_E_OBJECT_CHANGED == HrShowLVEntryProperties(hWndAddr, 0, lpAP->lpIAB, lpftLast)) &&
(szName) &&
(lpAP->DialogState == STATE_SELECT_RECIPIENTS)
)
{
// if the entry has changed and we have multiple list views visible,
// we need to update all instances of the entry in all the list views
//
UpdateLVItems(hWndAddr,szName);
SortListViewColumn(lpIAB, GetDlgItem(hDlg,IDC_ADDRBK_LIST_ADDRESSES), colDisplayName, &(lpAP->SortInfo), TRUE);
}
SetFocus(hWndAddr);
}
//$$///////////////////////////////////////////////////////////////////////////////////////////
//
// HrUpdateAdrListEntry ....
//
// When returning from a PickUser operation, updates the
// entry in the lpAdrList with the newly found item
//
// ulFLags 0 or MAPI_UNICODE passed down to GetProps
//
// Returns: Hr
//
///////////////////////////////////////////////////////////////////////////////////////////////
HRESULT HrUpdateAdrListEntry( LPADRBOOK lpIAB,
LPENTRYID lpEntryID,
ULONG cbEntryID,
ULONG ulFlags,
LPADRLIST * lppAdrList)
{
LPSPropValue rgProps = NULL;
ULONG cValues = 0;
LPSPropValue lpPropArrayNew = NULL;
ULONG cValuesNew = 0;
LPTSTR lpszTemp = NULL;
LPVOID lpbTemp = NULL;
ULONG i = 0;
SCODE sc;
HRESULT hr = E_FAIL;
if (!lppAdrList || !lpEntryID || !lpIAB || !cbEntryID)
goto out;
hr = HrGetPropArray(lpIAB,
(LPSPropTagArray) &ptaResolveDefaults,
cbEntryID,
lpEntryID,
ulFlags,
&cValues,
&rgProps);
if (!HR_FAILED(hr))
{
if(!*lppAdrList)
{
// Allocate one ..
LPADRLIST lpAdrList = NULL;
sc = MAPIAllocateBuffer(sizeof(ADRLIST) + sizeof(ADRENTRY),
&lpAdrList);
if(FAILED(sc))
{
hr = MAPI_E_NOT_ENOUGH_MEMORY;
goto out;
}
*lppAdrList = lpAdrList;
(*lppAdrList)->cEntries = 1;
(*lppAdrList)->aEntries[0].ulReserved1 = 0;
(*lppAdrList)->aEntries[0].cValues = 0;
(*lppAdrList)->aEntries[0].rgPropVals = NULL;
}
//Merge the new list with the old list
sc = ScMergePropValues( (*lppAdrList)->aEntries[0].cValues,
(*lppAdrList)->aEntries[0].rgPropVals,
cValues,
rgProps,
&cValuesNew,
&lpPropArrayNew);
if (sc == S_OK)
{
// if OK replace the lpspropvalue array
// if not we havent changed anything
(*lppAdrList)->aEntries[0].cValues = cValuesNew;
if((*lppAdrList)->aEntries[0].rgPropVals)
MAPIFreeBuffer((*lppAdrList)->aEntries[0].rgPropVals);
(*lppAdrList)->aEntries[0].rgPropVals = lpPropArrayNew;
}
else
{
// If errors Free up the allocated memory
if (lpPropArrayNew)
MAPIFreeBuffer(lpPropArrayNew);
hr = E_FAIL;
}
}
// we free this anyway whether the above succeeded or not
if (rgProps)
MAPIFreeBuffer(rgProps);
out:
return hr;
}