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.
1212 lines
38 KiB
1212 lines
38 KiB
/*--------------------------------------------------------------
|
|
*
|
|
*
|
|
* ui_reslv.c - shows the resolve name dialog
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
--------------------------------------------------------------*/
|
|
#include "_apipch.h"
|
|
|
|
extern HINSTANCE ghCommCtrlDLLInst;
|
|
|
|
#define MAX_RESLV_STRING 52 // Max # of characters to display in the static label ...
|
|
|
|
enum _ReturnValuesFromResolveDialog
|
|
{
|
|
RESOLVE_PICKUSER=0,
|
|
RESOLVE_CANCEL,
|
|
RESOLVE_OK
|
|
};
|
|
|
|
typedef struct _ResolveInfo
|
|
{
|
|
LPADRLIST * lppAdrList; // Stores the AdrList
|
|
ULONG nIndex; // Index of the item of interest
|
|
LPTSTR lpszDisplayName;// Preextracted display name for that
|
|
LPADRBOOK lpIAB; // Pointer to the IAB object
|
|
HWND hWndParent; // Stores hWndParents for dialog generating windows
|
|
ULONG ulFlag; // Stores Resolved or Ambiguos state
|
|
LPRECIPIENT_INFO lpContentsList;
|
|
LPMAPITABLE lpMapiTable;
|
|
BOOL bUnicode; // TRUE if MAPI_UNICODE specified in IAB::ResolveName
|
|
} RESOLVE_INFO, * LPRESOLVE_INFO;
|
|
|
|
|
|
static DWORD rgReslvHelpIDs[] =
|
|
{
|
|
IDC_RESOLVE_BUTTON_BROWSE, IDH_WAB_PICK_USER,
|
|
IDC_RESOLVE_LIST_MATCHES, IDH_WAB_CHK_NAME_LIST,
|
|
IDC_RESOLVE_STATIC_1, IDH_WAB_CHK_NAME_LIST,
|
|
IDC_RESOLVE_BUTTON_PROPS, IDH_WAB_PICK_RECIP_NAME_PROPERTIES,
|
|
IDC_RESOLVE_BUTTON_NEWCONTACT, IDH_WAB_PICK_RECIP_NAME_NEW,
|
|
0,0
|
|
};
|
|
|
|
|
|
//forward declarations
|
|
HRESULT HrResolveName(LPADRBOOK lpIAB,
|
|
HWND hWndParent,
|
|
HANDLE hPropertyStore,
|
|
ULONG nIndex,
|
|
ULONG ulFlag,
|
|
BOOL bUnicode,
|
|
LPADRLIST * lppAdrList,
|
|
LPMAPITABLE lpMapiTable);
|
|
|
|
|
|
INT_PTR CALLBACK fnResolve(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
|
|
BOOL ProcessResolveLVNotifications(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
|
|
HRESULT HrShowPickUserDialog(LPRESOLVE_INFO lpRI, LPTSTR lpszCaption);
|
|
|
|
HRESULT HrShowNewEntryFromResolve(LPRESOLVE_INFO lpRI, HWND hWndParent, ULONG ulObjectType);
|
|
|
|
HRESULT HrFillLVWithMatches( HWND hWndLV,
|
|
LPRESOLVE_INFO lpRI);
|
|
|
|
HRESULT HrMergeSelectionWithOriginal(LPRESOLVE_INFO lpRI,
|
|
ULONG cbEID,
|
|
LPENTRYID lpEID);
|
|
|
|
void ExitResolveDialog(HWND hDlg, LPRESOLVE_INFO lpRI, int nRetVal);
|
|
|
|
BOOL GetLVSelectedItem(HWND hWndLV, LPRESOLVE_INFO lpRI);
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
// HrShowResolveUI
|
|
//
|
|
// Wraps the UI for Resolve Names
|
|
//
|
|
//
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT HrShowResolveUI(IN LPADRBOOK lpIAB,
|
|
HWND hWndParent,
|
|
HANDLE hPropertyStore,
|
|
ULONG ulFlags, // WAB_RESOLVE_NO_NOT_FOUND_UI
|
|
LPADRLIST * lppAdrList,
|
|
LPFlagList *lppFlagList,
|
|
LPAMBIGUOUS_TABLES lpAmbiguousTables)
|
|
{
|
|
HRESULT hr = hrSuccess;
|
|
ULONG i=0;
|
|
LPFlagList lpFlagList= NULL;
|
|
LPMAPITABLE lpMapiTable = NULL;
|
|
BOOL bUnicode = (ulFlags & WAB_RESOLVE_UNICODE);
|
|
|
|
// if no common control, exit
|
|
if (NULL == ghCommCtrlDLLInst) {
|
|
hr = ResultFromScode(MAPI_E_UNCONFIGURED);
|
|
goto out;
|
|
}
|
|
|
|
if(!hPropertyStore || !lppAdrList || !lppFlagList || !(*lppAdrList) || !(*lppFlagList))
|
|
{
|
|
hr = MAPI_E_INVALID_PARAMETER;
|
|
goto out;
|
|
}
|
|
|
|
lpFlagList=(*lppFlagList);
|
|
|
|
// we need to scan the lpFlagList and look for unresolved entries
|
|
|
|
for (i = 0; i < lpFlagList->cFlags; i++)
|
|
{
|
|
//
|
|
// Occasionally someone (like athena) may hand us an adrlist with null rgPropVals
|
|
// We need to anticipate that.
|
|
//
|
|
if ( ((*lppAdrList)->aEntries[i].cValues == 0) ||
|
|
((*lppAdrList)->aEntries[i].rgPropVals == NULL) )
|
|
continue;
|
|
|
|
switch (lpFlagList->ulFlag[i])
|
|
{
|
|
case MAPI_RESOLVED:
|
|
break;
|
|
|
|
case MAPI_AMBIGUOUS:
|
|
//
|
|
// W2 - we now have an Ambiguous Table parameter .. for Unresolved
|
|
// entries, there is no Table but for Ambiguous entries, there is
|
|
// a corresponding ambiguous table filled in from the LDAP servers
|
|
//
|
|
if(lpAmbiguousTables)
|
|
{
|
|
if (lpAmbiguousTables->cEntries != 0)
|
|
{
|
|
lpMapiTable = lpAmbiguousTables->lpTable[i];
|
|
}
|
|
}
|
|
//Fall through
|
|
case MAPI_UNRESOLVED:
|
|
//
|
|
// We show a dialog asking the user what they want to do ...
|
|
// For this version, they can
|
|
// (b) browse the list of users or (c) cancel this user ..
|
|
// We will assume that we already the AdrList already has
|
|
// Recipient_Type and Display_Name and we only need to fill
|
|
// in the EntryID of this user ...
|
|
//
|
|
if ((! (ulFlags & WAB_RESOLVE_NO_NOT_FOUND_UI) ||
|
|
lpFlagList->ulFlag[i] == MAPI_AMBIGUOUS)) {
|
|
hr = HrResolveName( lpIAB,
|
|
hWndParent,
|
|
hPropertyStore,
|
|
i,
|
|
lpFlagList->ulFlag[i],
|
|
bUnicode,
|
|
lppAdrList,
|
|
lpMapiTable);
|
|
if (!HR_FAILED(hr))
|
|
lpFlagList->ulFlag[i] = MAPI_RESOLVED;
|
|
else
|
|
{
|
|
// Cancels are final .. other errors are not ..
|
|
if (hr == MAPI_E_USER_CANCEL)
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
out:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
// *** Dont change *** the order of the first 2 properties between here and the similar structure
|
|
// in ui_addr.c
|
|
enum _lppAdrListReturnedProps
|
|
{
|
|
propPR_DISPLAY_NAME,
|
|
propPR_ENTRYID,
|
|
TOTAL_ADRLIST_PROPS
|
|
};
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HrResolveName - tackles one entry at a time ...
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT HrResolveName( IN LPADRBOOK lpIAB,
|
|
HWND hWndParent,
|
|
HANDLE hPropertyStore,
|
|
ULONG nIndex,
|
|
ULONG ulFlag,
|
|
BOOL bUnicode,
|
|
LPADRLIST * lppAdrList,
|
|
LPMAPITABLE lpMapiTable)
|
|
{
|
|
ULONG i=0;
|
|
LPTSTR lpszDisplayName = NULL, lpszEmailAddress = NULL;
|
|
int nRetVal = 0;
|
|
HRESULT hr = hrSuccess;
|
|
RESOLVE_INFO RI = {0};
|
|
LPADRLIST lpAdrList = *lppAdrList;
|
|
ULONG ulTagDN = PR_DISPLAY_NAME, ulTagEmail = PR_EMAIL_ADDRESS;
|
|
|
|
if(!bUnicode)
|
|
{
|
|
ulTagDN = CHANGE_PROP_TYPE(ulTagDN, PT_STRING8);
|
|
ulTagEmail = CHANGE_PROP_TYPE(ulTagEmail, PT_STRING8);
|
|
}
|
|
//Scan this adrlist entries properties
|
|
for(i=0;i < lpAdrList->aEntries[nIndex].cValues; i++)
|
|
{
|
|
if (lpAdrList->aEntries[nIndex].rgPropVals[i].ulPropTag == ulTagDN)
|
|
{
|
|
lpszDisplayName = bUnicode ?
|
|
(LPWSTR)lpAdrList->aEntries[nIndex].rgPropVals[i].Value.LPSZ :
|
|
ConvertAtoW((LPSTR)lpAdrList->aEntries[nIndex].rgPropVals[i].Value.LPSZ);
|
|
}
|
|
if (lpAdrList->aEntries[nIndex].rgPropVals[i].ulPropTag == ulTagEmail)
|
|
{
|
|
lpszEmailAddress = bUnicode ?
|
|
(LPWSTR)lpAdrList->aEntries[nIndex].rgPropVals[i].Value.LPSZ :
|
|
ConvertAtoW((LPSTR)lpAdrList->aEntries[nIndex].rgPropVals[i].Value.LPSZ);
|
|
}
|
|
}
|
|
|
|
// we need some display name info to resolve on ...
|
|
if (lpszDisplayName == NULL) //we need this info or cant proceed
|
|
{
|
|
if (lpszEmailAddress)
|
|
{
|
|
lpszDisplayName = lpszEmailAddress;
|
|
lpszEmailAddress = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = MAPI_E_INVALID_PARAMETER;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
RI.nIndex = nIndex;
|
|
RI.lppAdrList = lppAdrList;
|
|
RI.lpszDisplayName = lpszDisplayName;
|
|
RI.lpIAB = lpIAB;
|
|
RI.hWndParent = hWndParent;
|
|
RI.ulFlag = ulFlag;
|
|
RI.lpContentsList = NULL;
|
|
RI.lpMapiTable = lpMapiTable;
|
|
RI.bUnicode = bUnicode;
|
|
|
|
nRetVal = (int) DialogBoxParam( hinstMapiX,
|
|
MAKEINTRESOURCE(IDD_DIALOG_RESOLVENAME),
|
|
hWndParent,
|
|
fnResolve,
|
|
(LPARAM) &RI);
|
|
|
|
switch(nRetVal)
|
|
{
|
|
case RESOLVE_CANCEL:
|
|
hr = MAPI_E_USER_CANCEL; //Cancel, flag it as pass and dont change anything
|
|
goto out;
|
|
break;
|
|
|
|
case RESOLVE_OK:
|
|
hr = hrSuccess;
|
|
goto out;
|
|
|
|
case -1: // something went wrong ...
|
|
DebugPrintTrace(( TEXT("DialogBoxParam -> %u\n"), GetLastError()));
|
|
hr = E_FAIL;
|
|
goto out;
|
|
break;
|
|
|
|
} //switch
|
|
|
|
|
|
out:
|
|
|
|
if(!bUnicode) // <note> assumes UNICODE defined
|
|
{
|
|
LocalFreeAndNull(&lpszDisplayName);
|
|
LocalFreeAndNull(&lpszEmailAddress);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SetResolveUI -
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
BOOL SetResolveUI(HWND hDlg)
|
|
{
|
|
|
|
// This function initializes a list view
|
|
HrInitListView( GetDlgItem(hDlg,IDC_RESOLVE_LIST_MATCHES),
|
|
LVS_REPORT,
|
|
FALSE); // Hide or show column headers
|
|
|
|
// Set the font of all the children to the default GUI font
|
|
EnumChildWindows( hDlg,
|
|
SetChildDefaultGUIFont,
|
|
(LPARAM) 0);
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
void SetLabelLDAP(HWND hDlg, HWND hWndLV)
|
|
{
|
|
// look at an entryid from the hWNdLV
|
|
// Use it only if its an LDAP entryid
|
|
|
|
// if the entryid is something else, we need to get its name and
|
|
// fill the structure accordingly
|
|
LPRECIPIENT_INFO lpItem;
|
|
|
|
if(ListView_GetItemCount(hWndLV) <= 0)
|
|
goto out;
|
|
|
|
lpItem = GetItemFromLV(hWndLV, 0);
|
|
if(lpItem)
|
|
{
|
|
LPTSTR lpServer = NULL;
|
|
LPTSTR lpDNS = NULL;
|
|
LPTSTR lpName = NULL;
|
|
TCHAR szName[40]; // we will limit the name to 40 chars so that the whole
|
|
// string will fit in the UI for really large chars
|
|
|
|
// is this an LDAP entryid ?
|
|
if (WAB_LDAP_MAILUSER == IsWABEntryID( lpItem->cbEntryID,
|
|
lpItem->lpEntryID,
|
|
&lpServer,
|
|
&lpDNS,
|
|
NULL, NULL, NULL))
|
|
{
|
|
//lpServer contains the server name
|
|
|
|
LPTSTR lpsz;
|
|
TCHAR szBuf[MAX_UI_STR];
|
|
TCHAR szTmp[MAX_PATH], *lpszTmp;
|
|
|
|
CopyTruncate(szName, lpServer, ARRAYSIZE(szName));
|
|
|
|
lpName = (LPTSTR) szName;
|
|
|
|
LoadString(hinstMapiX, idsResolveMatchesOnLDAP, szBuf, ARRAYSIZE(szBuf));
|
|
|
|
CopyTruncate(szTmp, lpName, MAX_PATH - 1);
|
|
lpszTmp = szTmp;
|
|
if(FormatMessage( FORMAT_MESSAGE_FROM_STRING |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
|
szBuf,
|
|
0,0, //ignored
|
|
(LPTSTR) &lpsz,
|
|
MAX_UI_STR,
|
|
(va_list *)&lpszTmp))
|
|
{
|
|
SetDlgItemText(hDlg, IDC_RESOLVE_STATIC_MATCHES, lpsz);
|
|
IF_WIN32(LocalFree(lpsz);)
|
|
IF_WIN16(FormatMessageFreeMem(lpsz);)
|
|
}
|
|
}
|
|
}
|
|
|
|
out:
|
|
return;
|
|
}
|
|
|
|
|
|
void FillUI(HWND hDlg, HWND hWndLV, LPRESOLVE_INFO lpRI)
|
|
{
|
|
|
|
TCHAR szBuf[MAX_UI_STR];
|
|
ULONG nLen = 0;
|
|
LPTSTR lpszDisplayName = lpRI->lpszDisplayName;
|
|
BOOL bNothingFound = FALSE;
|
|
LPTSTR lpszBuffer = NULL;
|
|
LPTSTR lpName = NULL;
|
|
TCHAR szTmp[MAX_PATH], *lpszTmp;
|
|
TCHAR szName[40]; // we will limit the name to 40 chars so that the whole
|
|
// string will fit in the UI for really large chars
|
|
|
|
if ( (lpRI->ulFlag == MAPI_UNRESOLVED) ||
|
|
(HR_FAILED(HrFillLVWithMatches(hWndLV, lpRI)))
|
|
)
|
|
bNothingFound = TRUE;
|
|
|
|
nLen = CopyTruncate(szName, lpszDisplayName, ARRAYSIZE(szName));
|
|
|
|
lpName = (LPTSTR) szName;
|
|
|
|
LoadString(hinstMapiX, (bNothingFound ? IDS_RESOLVE_NO_MATCHES_FOR : IDS_ADDRBK_RESOLVE_CAPTION),
|
|
szBuf, ARRAYSIZE(szBuf));
|
|
|
|
// Win9x bug FormatMessage cannot have more than 1023 chars
|
|
CopyTruncate(szTmp, lpName, 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))
|
|
{
|
|
SetDlgItemText(hDlg, IDC_RESOLVE_STATIC_1,lpszBuffer);
|
|
IF_WIN32(LocalFreeAndNull(&lpszBuffer);)
|
|
IF_WIN16(FormatMessageFreeMem(lpszBuffer);)
|
|
}
|
|
|
|
if(bNothingFound)
|
|
{
|
|
// If this has already been flagged as unresolved .. or
|
|
// the attempt to find fuzzy matches was unsuccessful ...
|
|
// tell 'em nothing found ...
|
|
|
|
LoadString(hinstMapiX, IDS_RESOLVE_NO_MATCHES, szBuf, ARRAYSIZE(szBuf));
|
|
{
|
|
LV_ITEM lvI = {0};
|
|
lvI.mask = LVIF_TEXT;
|
|
lvI.cchTextMax = lstrlen(szBuf)+1;
|
|
lvI.pszText = szBuf;
|
|
ListView_InsertItem(hWndLV, &lvI);
|
|
ListView_SetColumnWidth(hWndLV,0,400); //400 is a totally random number, we just want the column to be big enough not to truncate text
|
|
}
|
|
EnableWindow(hWndLV,FALSE);
|
|
EnableWindow(GetDlgItem(hDlg,IDC_RESOLVE_BUTTON_PROPS),FALSE);
|
|
EnableWindow(GetDlgItem(hDlg,IDOK/*IDC_RESOLVE_BUTTON_OK*/),FALSE);
|
|
ShowWindow(GetDlgItem(hDlg,IDC_RESOLVE_STATIC_MATCHES),SW_HIDE);
|
|
}
|
|
else
|
|
{
|
|
|
|
// if the search results are from an ldap server, we need
|
|
// to set the label on the dialog to say the results are from
|
|
// an LDAP server
|
|
SetLabelLDAP(hDlg, hWndLV);
|
|
|
|
// If the list view is filled, select the first item
|
|
if (ListView_GetItemCount(hWndLV) > 0)
|
|
{
|
|
LVSelectItem(hWndLV, 0);
|
|
SetFocus(hWndLV);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
/*************************************************************************
|
|
//
|
|
// resolve Dialog - simple implementation for 0.5
|
|
//
|
|
**************************************************************************/
|
|
INT_PTR CALLBACK fnResolve(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
TCHAR szBuf[MAX_UI_STR];
|
|
ULONG nLen = 0, nLenMax = 0, nRetVal=0;
|
|
HRESULT hr = hrSuccess;
|
|
|
|
LPRESOLVE_INFO lpRI = (LPRESOLVE_INFO) GetWindowLongPtr(hDlg,DWLP_USER);
|
|
|
|
switch(message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
HWND hWndLV = GetDlgItem(hDlg,IDC_RESOLVE_LIST_MATCHES);
|
|
SetWindowLongPtr(hDlg,DWLP_USER,lParam); //Save this for future reference
|
|
lpRI = (LPRESOLVE_INFO) lParam;
|
|
|
|
SetResolveUI(hDlg);
|
|
|
|
FillUI(hDlg, hWndLV, lpRI);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
#ifndef WIN16
|
|
if((g_msgMSWheel && message == g_msgMSWheel)
|
|
// || message == WM_MOUSEWHEEL
|
|
)
|
|
{
|
|
SendMessage(GetDlgItem(hDlg, IDC_RESOLVE_LIST_MATCHES), message, wParam, lParam);
|
|
break;
|
|
}
|
|
#endif // !WIN16
|
|
return FALSE;
|
|
break;
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
//Forward any system changes to the list view
|
|
SendMessage(GetDlgItem(hDlg, IDC_RESOLVE_LIST_MATCHES), message, wParam, lParam);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam,lParam))
|
|
{
|
|
default:
|
|
return ProcessActionCommands((LPIAB) lpRI->lpIAB,
|
|
GetDlgItem(hDlg, IDC_RESOLVE_LIST_MATCHES),
|
|
hDlg, message, wParam, lParam);
|
|
break;
|
|
|
|
case IDM_LVCONTEXT_DELETE: //We renamed the delete on the context menu to say TEXT("Show more Names")
|
|
case IDC_RESOLVE_BUTTON_BROWSE:
|
|
GetWindowText(hDlg, szBuf, ARRAYSIZE(szBuf));
|
|
lpRI->hWndParent = hDlg;
|
|
hr = HrShowPickUserDialog(lpRI, szBuf);
|
|
if(!HR_FAILED(hr))
|
|
{
|
|
if(lpRI->lpContentsList)
|
|
ClearListView( GetDlgItem(hDlg, IDC_RESOLVE_LIST_MATCHES),
|
|
&(lpRI->lpContentsList));
|
|
ExitResolveDialog(hDlg, lpRI, RESOLVE_OK);
|
|
// EndDialog( hDlg, RESOLVE_OK);
|
|
}
|
|
else
|
|
{
|
|
if(hr != MAPI_E_USER_CANCEL)
|
|
{
|
|
// Some error occured .. dont know what .. but since this dialog
|
|
// will stick around, need to warn the user about it ...
|
|
ShowMessageBox(hDlg,idsCouldNotSelectUser,MB_ICONERROR | MB_OK);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDOK:
|
|
case IDC_RESOLVE_BUTTON_OK:
|
|
if (GetLVSelectedItem(GetDlgItem(hDlg, IDC_RESOLVE_LIST_MATCHES),lpRI))
|
|
ExitResolveDialog(hDlg, lpRI, RESOLVE_OK);
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
case IDC_RESOLVE_BUTTON_CANCEL:
|
|
ExitResolveDialog(hDlg, lpRI, RESOLVE_CANCEL);
|
|
break;
|
|
|
|
case IDM_LVCONTEXT_NEWCONTACT:
|
|
case IDC_RESOLVE_BUTTON_NEWCONTACT:
|
|
hr = HrShowNewEntryFromResolve(lpRI,hDlg,MAPI_MAILUSER);
|
|
if (!HR_FAILED(hr))
|
|
ExitResolveDialog(hDlg, lpRI, RESOLVE_OK);
|
|
break;
|
|
|
|
case IDM_LVCONTEXT_NEWGROUP:
|
|
// case IDC_RESOLVE_BUTTON_NEWCONTACT:
|
|
hr = HrShowNewEntryFromResolve(lpRI,hDlg,MAPI_DISTLIST);
|
|
if (!HR_FAILED(hr))
|
|
ExitResolveDialog(hDlg, lpRI, RESOLVE_OK);
|
|
break;
|
|
|
|
case IDM_LVCONTEXT_COPY:
|
|
HrCopyItemDataToClipboard(hDlg, lpRI->lpIAB, GetDlgItem(hDlg, IDC_RESOLVE_LIST_MATCHES));
|
|
break;
|
|
|
|
case IDM_LVCONTEXT_PROPERTIES:
|
|
case IDC_RESOLVE_BUTTON_PROPS:
|
|
EnableWindow(GetDlgItem(hDlg, IDC_RESOLVE_BUTTON_PROPS), FALSE);
|
|
HrShowLVEntryProperties(GetDlgItem(hDlg,IDC_RESOLVE_LIST_MATCHES), 0,
|
|
lpRI->lpIAB, NULL);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_RESOLVE_BUTTON_PROPS), TRUE);
|
|
break;
|
|
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
//treat it like a cancel button
|
|
SendMessage (hDlg, WM_COMMAND, (WPARAM) IDC_RESOLVE_BUTTON_CANCEL, 0);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
if ((HWND)wParam == GetDlgItem(hDlg,IDC_RESOLVE_LIST_MATCHES))
|
|
{
|
|
ShowLVContextMenu( lvDialogResolve, (HWND)wParam, NULL, lParam, NULL,lpRI->lpIAB, NULL);
|
|
}
|
|
else
|
|
{
|
|
WABWinHelp((HWND) wParam,
|
|
g_szWABHelpFileName,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPVOID) rgReslvHelpIDs );
|
|
}
|
|
break;
|
|
|
|
case WM_HELP:
|
|
WABWinHelp(((LPHELPINFO)lParam)->hItemHandle,
|
|
g_szWABHelpFileName,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPSTR) rgReslvHelpIDs );
|
|
break;
|
|
|
|
|
|
case WM_NOTIFY:
|
|
switch((int) wParam)
|
|
{
|
|
case IDC_RESOLVE_LIST_MATCHES:
|
|
return ProcessResolveLVNotifications(hDlg,message,wParam,lParam);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
//
|
|
// Processes Notification messages for the list view control
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
BOOL ProcessResolveLVNotifications(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
|
|
NM_LISTVIEW * pNm = (NM_LISTVIEW *)lParam;
|
|
|
|
switch(pNm->hdr.code)
|
|
{
|
|
case NM_DBLCLK:
|
|
// Doubleclick on the list view is equivalent to a OK with a selected item
|
|
SendMessage(hDlg, WM_COMMAND, (WPARAM) IDOK/*IDC_RESOLVE_BUTTON_OK*/, 0);
|
|
break;
|
|
|
|
case NM_CUSTOMDRAW:
|
|
return (0 != ProcessLVCustomDraw(hDlg, lParam, TRUE));
|
|
break;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
// Pops up the New Entry dialog and then replaces the old entry with the
|
|
// newly created entry ...
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT HrShowNewEntryFromResolve(LPRESOLVE_INFO lpRI, HWND hWndParent, ULONG ulObjectType)
|
|
{
|
|
ULONG cbEID=0;
|
|
LPENTRYID lpEID=NULL;
|
|
|
|
HRESULT hr = hrSuccess;
|
|
ULONG cbTplEID = 0;
|
|
LPENTRYID lpTplEID = NULL;
|
|
|
|
//OutputDebugString( TEXT("HrShowNewEntryFromResolve entry\n"));
|
|
|
|
if (ulObjectType!=MAPI_MAILUSER && ulObjectType!=MAPI_DISTLIST)
|
|
goto out;
|
|
|
|
if(HR_FAILED(hr = HrGetWABTemplateID( lpRI->lpIAB,
|
|
ulObjectType,
|
|
&cbTplEID,
|
|
&lpTplEID)))
|
|
{
|
|
DebugPrintError(( TEXT("HrGetWABTemplateID failed: %x\n"), hr));
|
|
goto out;
|
|
}
|
|
|
|
if (HR_FAILED(hr = (lpRI->lpIAB)->lpVtbl->NewEntry( lpRI->lpIAB,
|
|
(ULONG_PTR) hWndParent,
|
|
0,
|
|
0,NULL,
|
|
cbTplEID,lpTplEID,
|
|
&cbEID,&lpEID)))
|
|
{
|
|
DebugPrintError(( TEXT("NewEntry failed: %x\n"),hr));
|
|
goto out;
|
|
}
|
|
|
|
|
|
// We created a new entry, and we want to use it to replace the old unresolved entry
|
|
|
|
hr = HrMergeSelectionWithOriginal(lpRI, cbEID, lpEID);
|
|
|
|
out:
|
|
FreeBufferAndNull(&lpEID);
|
|
FreeBufferAndNull(&lpTplEID);
|
|
|
|
//OutputDebugString( TEXT("HrShowNewEntryFromResolve exit\n"));
|
|
return hr;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
//
|
|
// Takes entry id of users selection and returns it appropriately ...
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////
|
|
HRESULT HrMergeSelectionWithOriginal(LPRESOLVE_INFO lpRI,
|
|
ULONG cbEID,
|
|
LPENTRYID lpEID)
|
|
{
|
|
HRESULT hr = hrSuccess;
|
|
ULONG cValues = 0;
|
|
LPSPropValue lpPropArray = NULL;
|
|
LPADRLIST lpAdrList = *(lpRI->lppAdrList);
|
|
SCODE sc;
|
|
ULONG nIndex = lpRI->nIndex;
|
|
|
|
//OutputDebugString( TEXT("HrMergeSelectionWithOriginal entry\n"));
|
|
|
|
hr = HrGetPropArray((lpRI->lpIAB),
|
|
(LPSPropTagArray) &ptaResolveDefaults,
|
|
cbEID,
|
|
lpEID,
|
|
lpRI->bUnicode ? MAPI_UNICODE : 0,
|
|
&cValues,
|
|
&lpPropArray);
|
|
|
|
if (HR_FAILED(hr)) goto out;
|
|
|
|
if ((!cValues) || (!lpPropArray))
|
|
{
|
|
hr = E_FAIL;
|
|
goto out;
|
|
}
|
|
else
|
|
{
|
|
LPSPropValue lpPropArrayNew = NULL;
|
|
ULONG cValuesNew = 0;
|
|
|
|
sc = ScMergePropValues( lpAdrList->aEntries[nIndex].cValues,
|
|
lpAdrList->aEntries[nIndex].rgPropVals,
|
|
cValues,
|
|
lpPropArray,
|
|
&cValuesNew,
|
|
&lpPropArrayNew);
|
|
if (sc != S_OK)
|
|
{
|
|
hr = ResultFromScode(sc);
|
|
goto out;
|
|
}
|
|
|
|
if ((lpPropArrayNew) && (cValuesNew > 0))
|
|
{
|
|
// [PaulHi] Raid 69325
|
|
// We need to convert these properties to ANSI since we are now the
|
|
// UNICODE WAB and if our client is !MAPI_UNICODE
|
|
if (!(lpRI->bUnicode))
|
|
{
|
|
if(sc = ScConvertWPropsToA((LPALLOCATEMORE) (&MAPIAllocateMore), lpPropArrayNew, cValuesNew, 0))
|
|
goto out;
|
|
}
|
|
|
|
MAPIFreeBuffer(lpAdrList->aEntries[nIndex].rgPropVals);
|
|
lpAdrList->aEntries[nIndex].rgPropVals = lpPropArrayNew;
|
|
lpAdrList->aEntries[nIndex].cValues = cValuesNew;
|
|
}
|
|
}
|
|
|
|
|
|
hr = hrSuccess;
|
|
|
|
out:
|
|
|
|
if (lpPropArray)
|
|
MAPIFreeBuffer(lpPropArray);
|
|
|
|
|
|
//OutputDebugString( TEXT("HrMergeSelectionWithOriginal exit\n"));
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HrShowPickuserDialog - shows the pick user dialog
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT HrShowPickUserDialog(LPRESOLVE_INFO lpRI,
|
|
LPTSTR lpszCaption)
|
|
{
|
|
LPADRLIST lpAdrList = *(lpRI->lppAdrList);
|
|
ULONG nIndex = lpRI->nIndex;
|
|
LPTSTR lpszDisplayName = lpRI->lpszDisplayName;
|
|
|
|
LPADRLIST lpAdrListSingle = NULL;
|
|
ADRPARM AdrParms = {0};
|
|
SCODE sc;
|
|
HRESULT hr = hrSuccess;
|
|
DWORD cchSize = 0;
|
|
|
|
//OutputDebugString( TEXT("HrShowPickUserDialog entry\n"));
|
|
|
|
// create an AdrList structure which we pass to Address ... to show UI
|
|
// We pass in the bare minimum props here which are - Display Name and Entry ID field (which is really NULL)
|
|
// The Address UI, if successful, gives us a whole list of props back which we merge with
|
|
// the original list, overwriting what we got back fresh ...
|
|
|
|
sc = MAPIAllocateBuffer(sizeof(ADRLIST) + sizeof(ADRENTRY), &lpAdrListSingle);
|
|
|
|
if (sc != S_OK)
|
|
{
|
|
hr = ResultFromScode(sc);
|
|
goto out;
|
|
}
|
|
|
|
lpAdrListSingle->cEntries = 1;
|
|
lpAdrListSingle->aEntries[0].ulReserved1 = 0;
|
|
lpAdrListSingle->aEntries[0].cValues = TOTAL_ADRLIST_PROPS;
|
|
|
|
sc = MAPIAllocateBuffer( TOTAL_ADRLIST_PROPS * sizeof(SPropValue),
|
|
(LPVOID *) (&(lpAdrListSingle->aEntries[0].rgPropVals)));
|
|
if (sc != S_OK)
|
|
{
|
|
hr = ResultFromScode(sc);
|
|
goto out;
|
|
}
|
|
|
|
lpAdrListSingle->aEntries[0].rgPropVals[propPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME;
|
|
cchSize = (lstrlen(lpszDisplayName)+1);
|
|
sc = MAPIAllocateMore((sizeof(TCHAR) * cchSize),
|
|
lpAdrListSingle->aEntries[0].rgPropVals,
|
|
(LPVOID *) (&lpAdrListSingle->aEntries[0].rgPropVals[propPR_DISPLAY_NAME].Value.LPSZ));
|
|
|
|
if (sc != S_OK)
|
|
{
|
|
hr = ResultFromScode(sc);
|
|
goto out;
|
|
}
|
|
|
|
StrCpyN(lpAdrListSingle->aEntries[0].rgPropVals[propPR_DISPLAY_NAME].Value.LPSZ, lpszDisplayName, cchSize);
|
|
|
|
lpAdrListSingle->aEntries[0].rgPropVals[propPR_ENTRYID].ulPropTag = PR_ENTRYID;
|
|
lpAdrListSingle->aEntries[0].rgPropVals[propPR_ENTRYID].Value.bin.cb = 0;
|
|
lpAdrListSingle->aEntries[0].rgPropVals[propPR_ENTRYID].Value.bin.lpb = NULL;
|
|
|
|
AdrParms.cDestFields = 0;
|
|
AdrParms.ulFlags = DIALOG_MODAL | ADDRESS_ONE | MAPI_UNICODE;
|
|
AdrParms.lpszCaption = lpszCaption;
|
|
|
|
|
|
if (!HR_FAILED(hr = (lpRI->lpIAB)->lpVtbl->Address(
|
|
lpRI->lpIAB,
|
|
(PULONG_PTR) &(lpRI->hWndParent),
|
|
&AdrParms,
|
|
&lpAdrListSingle)))
|
|
{
|
|
// We successfully selected some user and the lpAdrListSingle contains
|
|
// a new set of lpProps for that user ...
|
|
//
|
|
LPSPropValue lpPropArrayNew = NULL;
|
|
ULONG cValuesNew = 0;
|
|
|
|
sc = ScMergePropValues( lpAdrList->aEntries[nIndex].cValues,
|
|
lpAdrList->aEntries[nIndex].rgPropVals,
|
|
lpAdrListSingle->aEntries[0].cValues,
|
|
lpAdrListSingle->aEntries[0].rgPropVals,
|
|
&cValuesNew,
|
|
&lpPropArrayNew);
|
|
if (sc != S_OK)
|
|
{
|
|
hr = ResultFromScode(sc);
|
|
goto out;
|
|
}
|
|
|
|
if ((lpPropArrayNew) && (cValuesNew > 0))
|
|
{
|
|
// [PaulHi] Raid 69325
|
|
// We need to convert these properties to ANSI since we are now the
|
|
// UNICODE WAB and if our client is !MAPI_UNICODE
|
|
if (!(lpRI->bUnicode))
|
|
{
|
|
if(sc = ScConvertWPropsToA((LPALLOCATEMORE) (&MAPIAllocateMore), lpPropArrayNew, cValuesNew, 0))
|
|
goto out;
|
|
}
|
|
|
|
MAPIFreeBuffer(lpAdrList->aEntries[nIndex].rgPropVals);
|
|
lpAdrList->aEntries[nIndex].rgPropVals = lpPropArrayNew;
|
|
lpAdrList->aEntries[nIndex].cValues = cValuesNew;
|
|
}
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
if (lpAdrListSingle)
|
|
{
|
|
FreePadrlist(lpAdrListSingle);
|
|
}
|
|
|
|
//OutputDebugString( TEXT("HrShowPickUserDialog exit\n"));
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//$$/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
// HrFillLVWithMatches - fills the list view with close matches for the given name
|
|
//
|
|
// Fails (E_FAIL) if it doesnt find anything to fill in the List View
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT HrFillLVWithMatches( HWND hWndLV,
|
|
LPRESOLVE_INFO lpRI)
|
|
{
|
|
HRESULT hr = hrSuccess;
|
|
LPSBinary * lprgsbEntryIDs = NULL;
|
|
ULONG iolkci=0, colkci = 0;
|
|
OlkContInfo *rgolkci;
|
|
ULONG * lpcValues = NULL;
|
|
ULONG i = 0, j = 0;
|
|
LPSRowSet lpSRowSet = NULL;
|
|
LPPTGDATA lpPTGData=GetThreadStoragePointer();
|
|
ULONG ulFlags = AB_FUZZY_FIND_ALL;
|
|
|
|
EnterCriticalSection(&(((LPIAB)(lpRI->lpIAB))->cs));
|
|
|
|
if (pt_bIsWABOpenExSession)
|
|
{
|
|
colkci = ((LPIAB)(lpRI->lpIAB))->lpPropertyStore->colkci;
|
|
Assert(colkci);
|
|
rgolkci = ((LPIAB)(lpRI->lpIAB))->lpPropertyStore->rgolkci;
|
|
Assert(rgolkci);
|
|
}
|
|
else
|
|
if (bAreWABAPIProfileAware((LPIAB)lpRI->lpIAB))
|
|
{
|
|
colkci = ((LPIAB)(lpRI->lpIAB))->cwabci;
|
|
Assert(colkci);
|
|
rgolkci = ((LPIAB)(lpRI->lpIAB))->rgwabci;
|
|
Assert(rgolkci);
|
|
if(colkci > 1 && !lpRI->lpMapiTable)
|
|
ulFlags |= AB_FUZZY_FIND_PROFILEFOLDERONLY;
|
|
}
|
|
else
|
|
colkci = 1;
|
|
|
|
lprgsbEntryIDs = LocalAlloc(LMEM_ZEROINIT, colkci*sizeof(LPSBinary));
|
|
lpcValues = LocalAlloc(LMEM_ZEROINIT, colkci*sizeof(ULONG));
|
|
if(!lprgsbEntryIDs || !lpcValues)
|
|
{
|
|
hr = MAPI_E_NOT_ENOUGH_MEMORY;
|
|
goto out;
|
|
}
|
|
|
|
//
|
|
// First search the property store
|
|
//
|
|
|
|
if(!(lpRI->lpMapiTable))
|
|
{
|
|
// if we dont have a ambiguous table to look in then that means we look in the
|
|
// property store for ambiguous stuff ...
|
|
while (iolkci < colkci)
|
|
{
|
|
hr = HrFindFuzzyRecordMatches(
|
|
((LPIAB)(lpRI->lpIAB))->lpPropertyStore->hPropertyStore,
|
|
(colkci == 1) ? NULL : rgolkci[iolkci].lpEntryID,
|
|
lpRI->lpszDisplayName,
|
|
ulFlags, //flags
|
|
&(lpcValues[iolkci]),
|
|
&(lprgsbEntryIDs[iolkci]));
|
|
iolkci++;
|
|
}
|
|
|
|
if (HR_FAILED(hr))
|
|
goto out;
|
|
|
|
|
|
if(bAreWABAPIProfileAware((LPIAB)lpRI->lpIAB))
|
|
{
|
|
// it's possible that nothing in the profile matched but other stuff in the WAB matched
|
|
// Doublecheck that if we found nothing in the profile, we can search the whole WAB
|
|
ULONG nCount = 0;
|
|
for(i=0;i<colkci;i++)
|
|
nCount += lpcValues[i];
|
|
if(!nCount)
|
|
{
|
|
// search the whole WAB
|
|
hr = HrFindFuzzyRecordMatches(
|
|
((LPIAB)(lpRI->lpIAB))->lpPropertyStore->hPropertyStore,
|
|
NULL,
|
|
lpRI->lpszDisplayName,
|
|
AB_FUZZY_FIND_ALL, //flags
|
|
&(lpcValues[0]),
|
|
&(lprgsbEntryIDs[0]));
|
|
}
|
|
}
|
|
|
|
// Now we have a list of EntryIDs
|
|
// Use them to populate the List View
|
|
//
|
|
// We can
|
|
// (a) Read the entryids one by one and fill the list view
|
|
// AddWABEntryToListView
|
|
// or
|
|
// (b) We can create an lpContentsList and fill it in one shot
|
|
// HrFillListView
|
|
|
|
// We'll go with (a) for now
|
|
// If performance is bad, do (b)
|
|
|
|
for(i=0;i<colkci;i++)
|
|
{
|
|
for(j=0;j<lpcValues[i];j++)
|
|
{
|
|
AddWABEntryToListView( lpRI->lpIAB,
|
|
hWndLV,
|
|
lprgsbEntryIDs[i][j].cb,
|
|
(LPENTRYID) lprgsbEntryIDs[i][j].lpb,
|
|
&(lpRI->lpContentsList));
|
|
}
|
|
}
|
|
|
|
}
|
|
else if(lpRI->lpMapiTable)
|
|
{
|
|
// if there is a MAPI ambiguous contents table associated with this display name
|
|
// use it to further fill in the lpContentsList
|
|
BOOL bUnicode = ((LPVUE)lpRI->lpMapiTable)->lptadParent->bMAPIUnicodeTable;
|
|
|
|
hr = HrQueryAllRows(lpRI->lpMapiTable,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&lpSRowSet);
|
|
|
|
if (HR_FAILED(hr))
|
|
{
|
|
DebugPrintError(( TEXT("HrQueryAllRows Failed: %x\n"),hr));
|
|
goto out;
|
|
}
|
|
|
|
for(i=0;i<lpSRowSet->cRows;i++)
|
|
{
|
|
LPSPropValue lpPropArray = lpSRowSet->aRow[i].lpProps;
|
|
|
|
ULONG ulcPropCount = lpSRowSet->aRow[i].cValues;
|
|
|
|
LPRECIPIENT_INFO lpItem = LocalAlloc(LMEM_ZEROINIT, sizeof(RECIPIENT_INFO));
|
|
|
|
if (!lpItem)
|
|
{
|
|
DebugPrintError(( TEXT("LocalAlloc Failed \n")));
|
|
hr = MAPI_E_NOT_ENOUGH_MEMORY;
|
|
goto out;
|
|
}
|
|
|
|
if(!bUnicode) // the props are in ANSI - convert to UNICODE for our use
|
|
{
|
|
if(ScConvertAPropsToW((LPALLOCATEMORE) (&MAPIAllocateMore), lpPropArray, ulcPropCount, 0))
|
|
goto out;
|
|
}
|
|
|
|
GetRecipItemFromPropArray(ulcPropCount, lpPropArray, &lpItem);
|
|
|
|
// The critical prop is display name - without it we are nothing ...
|
|
// If no display name, junk this entry and continue ..
|
|
|
|
if (!lstrlen(lpItem->szDisplayName) || (lpItem->cbEntryID == 0)) //This entry id is not allowed
|
|
{
|
|
FreeRecipItem(&lpItem);
|
|
continue;
|
|
}
|
|
|
|
|
|
AddSingleItemToListView(hWndLV, lpItem);
|
|
|
|
//
|
|
// Hook in the lpItem into the lpContentsList so we can free it later
|
|
//
|
|
lpItem->lpPrev = NULL;
|
|
lpItem->lpNext = lpRI->lpContentsList;
|
|
if (lpRI->lpContentsList)
|
|
lpRI->lpContentsList->lpPrev = lpItem;
|
|
lpRI->lpContentsList = lpItem;
|
|
|
|
lpItem = NULL;
|
|
|
|
} //for i ....
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// If, after all this we still have an empty list box, we will report a failure
|
|
//
|
|
if(ListView_GetItemCount(hWndLV)<=0)
|
|
{
|
|
DebugPrintTrace(( TEXT("Empty List View - no matches found\n")));
|
|
hr = E_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
|
|
out:
|
|
|
|
for(i=0;i<colkci;i++)
|
|
{
|
|
FreeEntryIDs(((LPIAB)(lpRI->lpIAB))->lpPropertyStore->hPropertyStore,
|
|
lpcValues[i],
|
|
lprgsbEntryIDs[i]);
|
|
}
|
|
if(lpcValues)
|
|
LocalFree(lpcValues);
|
|
if(lprgsbEntryIDs)
|
|
LocalFree(lprgsbEntryIDs);
|
|
|
|
if (lpSRowSet)
|
|
FreeProws(lpSRowSet);
|
|
|
|
//
|
|
// ReSet the ListView SortAscending style off
|
|
//
|
|
// SetWindowLong(hWndLV, GWL_STYLE, (dwStyle | LVS_SORTASCENDING));
|
|
LeaveCriticalSection(&(((LPIAB)(lpRI->lpIAB))->cs));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Returns the item selected in the list view
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOL GetLVSelectedItem(HWND hWndLV, LPRESOLVE_INFO lpRI)
|
|
{
|
|
int iItemIndex = 0;
|
|
LV_ITEM lvi = {0};
|
|
LPRECIPIENT_INFO lpItem;
|
|
BOOL bRet = FALSE;
|
|
|
|
//OutputDebugString( TEXT("GetLVSelectedItem Entry\n"));
|
|
|
|
if (ListView_GetSelectedCount(hWndLV) != 1)
|
|
goto out;
|
|
|
|
iItemIndex = ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED);
|
|
|
|
lpItem = GetItemFromLV(hWndLV, iItemIndex);
|
|
|
|
if(lpItem)
|
|
HrMergeSelectionWithOriginal(lpRI,lpItem->cbEntryID,lpItem->lpEntryID);
|
|
else
|
|
goto out;
|
|
|
|
bRet = TRUE;
|
|
|
|
out:
|
|
//OutputDebugString( TEXT("GetLVSelectedItem Exit\n"));
|
|
|
|
return bRet;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Generic exit function
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
void ExitResolveDialog(HWND hDlg, LPRESOLVE_INFO lpRI, int nRetVal)
|
|
{
|
|
HWND hWndLV = GetDlgItem(hDlg, IDC_RESOLVE_LIST_MATCHES);
|
|
|
|
//OutputDebugString( TEXT("ExitResolveDialog Entry\n"));
|
|
|
|
if(lpRI->lpContentsList)
|
|
{
|
|
ClearListView(hWndLV,&(lpRI->lpContentsList));
|
|
}
|
|
|
|
if(ListView_GetItemCount(hWndLV) > 0)
|
|
ListView_DeleteAllItems(hWndLV);
|
|
|
|
EndDialog(hDlg, nRetVal);
|
|
|
|
//OutputDebugString( TEXT("ExitResolveDialog Exit\n"));
|
|
|
|
return;
|
|
}
|