|
|
/*--------------------------------------------------------------
* * * 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; }
|