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.

3179 lines
105 KiB

  1. /*--------------------------------------------------------------
  2. *
  3. *
  4. * ui_srch.c - contains stuff for showing the WAB search dialog
  5. * with LDAP Search and Local Search
  6. *
  7. *
  8. *
  9. *
  10. *
  11. * 9/96 - created VikramM
  12. --------------------------------------------------------------*/
  13. #include "_apipch.h"
  14. #define CONTROL_SPACE 7 //pixels
  15. #define BORDER_SPACE 11 //pixels
  16. typedef struct _ServerDat
  17. {
  18. HIMAGELIST himl;
  19. SBinary SB;
  20. } SERVERDAT, * LPSERVERDAT;
  21. enum
  22. {
  23. IS_LDAP = 0,
  24. IS_PAB,
  25. IS_OLK,
  26. IS_ERR
  27. };
  28. enum
  29. {
  30. tabSimple=0,
  31. tabAdvanced,
  32. tabMax
  33. };
  34. // Structure passed to Search Dialog Proc
  35. typedef struct _FindParams
  36. {
  37. LDAP_SEARCH_PARAMS LDAPsp;
  38. SORT_INFO SortInfo;
  39. LPRECIPIENT_INFO lpContentsList;
  40. LPADRPARM_FINDINFO lpAPFI;
  41. BOOL bShowFullDialog; // Determines whether to show the full dialog or the truncated dialog
  42. BOOL bLDAPActionInProgress;
  43. LPLDAPURL lplu;
  44. BOOL bInitialized;
  45. BOOL bUserCancel;
  46. int MinDlgWidth;
  47. int MinDlgHeight;
  48. int MinDlgHeightWithResults;
  49. } WAB_FIND_PARAMS, * LPWAB_FIND_PARAMS;
  50. // Search dialog control arrays
  51. int rgAdrParmButtonID[] =
  52. {
  53. IDC_FIND_BUTTON_TO,
  54. IDC_FIND_BUTTON_CC,
  55. IDC_FIND_BUTTON_BCC
  56. };
  57. int rgAdvancedButtons[] =
  58. {
  59. IDC_FIND_BUTTON_ADDCONDITION,
  60. IDC_FIND_BUTTON_REMOVECONDITION
  61. };
  62. int rgSearchEditID[] =
  63. {
  64. IDC_FIND_EDIT_NAME,
  65. IDC_FIND_EDIT_EMAIL,
  66. IDC_FIND_EDIT_STREET,
  67. IDC_FIND_EDIT_PHONE,
  68. IDC_FIND_EDIT_ANY,
  69. };
  70. #define SEARCH_EDIT_MAX 5 //sync with above array
  71. /*
  72. * Prototypes
  73. */
  74. // extern LPIMAGELIST_LOADIMAGE gpfnImageList_LoadImage;
  75. extern LPIMAGELIST_LOADIMAGE_A gpfnImageList_LoadImageA;
  76. extern LPIMAGELIST_LOADIMAGE_W gpfnImageList_LoadImageW;
  77. extern LPIMAGELIST_DESTROY gpfnImageList_Destroy;
  78. extern LPIMAGELIST_DRAW gpfnImageList_Draw;
  79. extern BOOL bIsHttpPrefix(LPTSTR szBuf);
  80. extern const LPTSTR lpszRegFindPositionKeyValueName;
  81. extern BOOL ListAddItem(HWND hDlg, HWND hWndAddr, int CtlID, LPRECIPIENT_INFO * lppList, ULONG RecipientType);
  82. extern HRESULT LDAPSearchWithoutContainer(HWND hWnd, LPLDAPURL lplu,
  83. LPSRestriction lpres,
  84. LPTSTR lpAdvFilter,
  85. BOOL bReturnSinglePropArray,
  86. ULONG ulFlags,
  87. LPRECIPIENT_INFO * lppContentsList,
  88. LPULONG lpulcProps,
  89. LPSPropValue * lppPropArray);
  90. extern HRESULT HrGetLDAPSearchRestriction(LDAP_SEARCH_PARAMS LDAPsp, LPSRestriction lpSRes);
  91. #ifdef PAGED_RESULT_SUPPORT
  92. extern BOOL bMorePagedResultsAvailable();
  93. extern void ClearCachedPagedResultParams();
  94. #endif //#ifdef PAGED_RESULT_SUPPORT
  95. int ComboAddItem(HWND hWndLV, LPTSTR lpszItemText, LPARAM lParam, LPTSTR szPref, int * lpnStart, BOOL * lpbAddedPref);
  96. INT_PTR CALLBACK fnSearch( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  97. void UpdateButtons(HWND hDlg, HWND hWndLVResults, HWND hWndLV, LPLDAPURL lplu);
  98. //HRESULT HrInitServerListLV(HWND hWndLV);
  99. LRESULT ProcessLVMessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  100. LRESULT ProcessLVResultsMessages(HWND hWnd,
  101. UINT uMsg,
  102. WPARAM wParam,
  103. LPARAM lParam,
  104. LPWAB_FIND_PARAMS lpWFP);
  105. BOOL DoTheSearchThing(HWND hDlg, LPWAB_FIND_PARAMS lpWFP);
  106. void SaveFindWindowPos(HWND hWnd, LPIAB lpIAB);
  107. int CurrentContainerIsPAB(HWND hWndLV);
  108. static const LPTSTR szKeyLastFindServer = TEXT("Software\\Microsoft\\WAB\\WAB4\\LastFind");
  109. static const LPTSTR c_tszPolicyPrefAccount = TEXT("Software\\Policies\\Microsoft\\Internet Account Manager\\Account Pref");
  110. /***/
  111. static DWORD rgSrchHelpIDs[] =
  112. {
  113. IDC_FIND_STATIC_FINDIN, IDH_WAB_DIR_SER_LIST,
  114. IDC_FIND_COMBO_LIST, IDH_WAB_DIR_SER_LIST,
  115. IDC_FIND_STATIC_NAME, IDH_WAB_FIND_FIRST,
  116. IDC_FIND_EDIT_NAME, IDH_WAB_FIND_FIRST,
  117. IDC_FIND_STATIC_EMAIL, IDH_WAB_FIND_E_MAIL,
  118. IDC_FIND_EDIT_EMAIL, IDH_WAB_FIND_E_MAIL,
  119. IDC_FIND_STATIC_STREET, IDH_WAB_FIND_ADDRESS,
  120. IDC_FIND_EDIT_STREET, IDH_WAB_FIND_ADDRESS,
  121. IDC_FIND_STATIC_PHONE, IDH_WAB_FIND_PHONE,
  122. IDC_FIND_EDIT_PHONE, IDH_WAB_FIND_PHONE,
  123. IDC_FIND_STATIC_ANY, IDH_WAB_FIND_OTHER,
  124. IDC_FIND_EDIT_ANY, IDH_WAB_FIND_OTHER,
  125. IDC_FIND_BUTTON_FIND, IDH_WAB_FIND_FINDNOW,
  126. IDC_FIND_BUTTON_CLEAR, IDH_WAB_FIND_CLEARALL,
  127. IDC_FIND_BUTTON_CLOSE, IDH_WAB_FIND_CLOSE,
  128. IDC_FIND_LIST_RESULTS, IDH_WAB_FIND_RESULTS,
  129. IDC_FIND_BUTTON_PROPERTIES, IDH_WAB_PICK_RECIP_NAME_PROPERTIES,
  130. IDC_FIND_BUTTON_DELETE, IDH_WAB_FIND_DELETE,
  131. IDC_FIND_BUTTON_ADDTOWAB, IDH_WAB_FIND_ADD2WAB,
  132. IDC_FIND_BUTTON_TO, IDH_WAB_PICK_RECIP_NAME_TO_BUTTON,
  133. IDC_FIND_BUTTON_CC, IDH_WAB_PICK_RECIP_NAME_CC_BUTTON,
  134. IDC_FIND_BUTTON_BCC, IDH_WAB_PICK_RECIP_NAME_BCC_BUTTON,
  135. IDC_TAB_FIND, IDH_WAB_COMM_GROUPBOX,
  136. IDC_FIND_BUTTON_SERVER_INFO, IDH_WAB_VISITDS_BUTTON,
  137. IDC_FIND_BUTTON_STOP, IDH_WAB_FIND_STOP,
  138. IDC_FIND_STATIC_ADVANCED, IDH_WAB_FIND_ADV_CRITERIA,
  139. IDC_FIND_COMBO_FIELD, IDH_WAB_FIND_ADV_CRITERIA,
  140. IDC_FIND_COMBO_CONDITION, IDH_WAB_FIND_ADV_CRITERIA,
  141. IDC_FIND_EDIT_ADVANCED, IDH_WAB_FIND_ADV_CRITERIA,
  142. IDC_FIND_LIST_CONDITIONS, IDH_WAB_FIND_ADV_CRITERIA_DISPLAY,
  143. IDC_FIND_BUTTON_ADDCONDITION, IDH_WAB_FIND_ADV_CRITERIA_ADD,
  144. IDC_FIND_BUTTON_REMOVECONDITION,IDH_WAB_FIND_ADV_CRITERIA_REMOVE,
  145. 0,0
  146. };
  147. /*
  148. -
  149. - ShowHideMoreResultsButton
  150. *
  151. * This is called to show the MORE RESULTS button whenever
  152. * a paged result was done and a Cookie was cached
  153. * The button is hidden whenever search parameters change
  154. *
  155. */
  156. void ShowHideMoreResultsButton(HWND hDlg, BOOL bShow)
  157. {
  158. HWND hWnd = GetDlgItem(hDlg, IDC_FIND_BUTTON_MORE);
  159. EnableWindow(hWnd, bShow);
  160. ShowWindow(hWnd, bShow ? SW_NORMAL : SW_HIDE);
  161. }
  162. /***/
  163. /*
  164. - ResizeSearchDlg
  165. -
  166. *
  167. */
  168. void ResizeSearchDlg(HWND hDlg, LPWAB_FIND_PARAMS lpWFP)
  169. {
  170. // resize the dialog to show the full results and let the user
  171. // resize it henceforth without restriction
  172. RECT rc;
  173. HWND hWndLVResults = GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS);
  174. GetWindowRect(hDlg, &rc);
  175. lpWFP->bShowFullDialog = TRUE;
  176. SetWindowPos(hDlg, HWND_TOP, rc.left, rc.top,
  177. rc.right - rc.left, lpWFP->MinDlgHeightWithResults,
  178. SWP_NOMOVE | SWP_NOZORDER);
  179. SetColumnHeaderBmp( hWndLVResults, lpWFP->SortInfo);
  180. // Also set the WS_TABSTOP style on the results Listview once the dialog is
  181. // expanded
  182. {
  183. DWORD dwStyle = GetWindowLong(hWndLVResults, GWL_STYLE);
  184. dwStyle |= WS_TABSTOP;
  185. SetWindowLong(hWndLVResults, GWL_STYLE, dwStyle);
  186. }
  187. }
  188. //$$///////////////////////////////////////////////////////////////////////////
  189. //
  190. // AddTabItem
  191. //
  192. ////////////////////////////////////////////////////////////////////////////////
  193. void AddTabItem(HWND hDlg, int nIndex)
  194. {
  195. HWND hWndTab = GetDlgItem(hDlg, IDC_TAB_FIND);
  196. TC_ITEM tci ={0};
  197. TCHAR sz[MAX_PATH];
  198. LoadString(hinstMapiX, idsFindTabTitle+nIndex, sz, ARRAYSIZE(sz));
  199. tci.mask = TCIF_TEXT;
  200. tci.pszText = sz;
  201. tci.cchTextMax = lstrlen(sz)+1;
  202. TabCtrl_InsertItem(hWndTab, nIndex, &tci);
  203. }
  204. //$$////////////////////////////////////////////////////////////////////////////
  205. //
  206. // Gets the text of the currently selected item in the combo .. defaults to
  207. // item 0 if no selection
  208. //
  209. // szBuf should be a large enough predefined buffer
  210. //
  211. ////////////////////////////////////////////////////////////////////////////////
  212. void GetSelectedText(HWND hWndCombo, LPTSTR * lppBuf)
  213. {
  214. int iItemIndex = (int) SendMessage(hWndCombo, CB_GETCURSEL, 0, 0);
  215. int nLen = 0;
  216. if(!lppBuf)
  217. return;
  218. *lppBuf = NULL;
  219. if(iItemIndex == CB_ERR)
  220. {
  221. SendMessage(hWndCombo, CB_SETCURSEL, 0, 0);
  222. iItemIndex = 0;
  223. }
  224. nLen = (int) SendMessage(hWndCombo, CB_GETLBTEXTLEN, (WPARAM) iItemIndex, 0);
  225. if (nLen != CB_ERR)
  226. {
  227. nLen++; // Make space for the terminator
  228. *lppBuf = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR) * nLen);
  229. if(*lppBuf)
  230. {
  231. *lppBuf[0] = TEXT('\0');
  232. SendMessage(hWndCombo, CB_GETLBTEXT, (WPARAM) iItemIndex, (LPARAM) *lppBuf);
  233. }
  234. }
  235. }
  236. //$$/////////////////////////////////////////////////////////////////////////////
  237. //
  238. // hrShowSearchDialog - wrapper for Search UI
  239. //
  240. // lpAPFI - is a special structure passed in by the select recipients dialog
  241. // that enables us to add memebers to the select recipients dialog from the
  242. // find dialog
  243. //
  244. /////////////////////////////////////////////////////////////////////////////////
  245. HRESULT HrShowSearchDialog(LPADRBOOK lpAdrBook,
  246. HWND hWndParent,
  247. LPADRPARM_FINDINFO lpAPFI,
  248. LPLDAPURL lplu,
  249. LPSORT_INFO lpSortInfo)
  250. {
  251. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  252. LPIAB lpIAB = (LPIAB)lpAdrBook;
  253. HRESULT hr = hrSuccess;
  254. int nRetVal = SEARCH_ERROR;
  255. WAB_FIND_PARAMS fp = {0};
  256. InitLDAPClientLib();
  257. fp.lpContentsList = NULL;
  258. if(!lpSortInfo)
  259. ReadRegistrySortInfo(lpIAB, &(fp.SortInfo));
  260. else
  261. fp.SortInfo = *lpSortInfo;
  262. #ifndef WIN16 // Disable until ldap16.dll is available.
  263. if(!lplu) //dont want anything filled in if this was a ldapurl thing
  264. fp.LDAPsp = pt_LDAPsp;
  265. fp.LDAPsp.lpIAB = lpAdrBook;
  266. #endif
  267. fp.lpAPFI = lpAPFI;
  268. fp.lplu = lplu;
  269. if(lplu)
  270. {
  271. if(lplu->lpList)
  272. fp.bShowFullDialog = TRUE;
  273. }
  274. fp.bLDAPActionInProgress = FALSE;
  275. nRetVal = (int) DialogBoxParam(
  276. hinstMapiX,
  277. MAKEINTRESOURCE(IDD_DIALOG_FIND),
  278. hWndParent,
  279. fnSearch,
  280. (LPARAM) &fp);
  281. #ifndef WIN16 // Disable until ldap16.dll is available.
  282. pt_LDAPsp = fp.LDAPsp;
  283. #endif
  284. if(lpAPFI)
  285. lpAPFI->nRetVal = nRetVal;
  286. switch(nRetVal)
  287. {
  288. case SEARCH_CANCEL:
  289. hr = MAPI_E_USER_CANCEL;
  290. break;
  291. case SEARCH_CLOSE:
  292. case SEARCH_OK:
  293. case SEARCH_USE:
  294. hr = S_OK;
  295. break;
  296. case SEARCH_ERROR:
  297. hr = E_FAIL;
  298. break;
  299. }
  300. if(fp.lpContentsList)
  301. {
  302. LPRECIPIENT_INFO lpItem;
  303. lpItem = fp.lpContentsList;
  304. while(lpItem)
  305. {
  306. fp.lpContentsList = lpItem->lpNext;
  307. FreeRecipItem(&lpItem);
  308. lpItem = fp.lpContentsList;
  309. }
  310. fp.lpContentsList = NULL;
  311. }
  312. DeinitLDAPClientLib();
  313. return hr;
  314. }
  315. //$$/////////////////////////////////////////////////////////////////////////////
  316. //
  317. // SetEnableDisableUI - shows/hides edit fields based on whether selected item
  318. // in the list view is WAB or Directory Service
  319. //
  320. // hDlg - Parent dialog
  321. // hWndLV - List View
  322. //
  323. ////////////////////////////////////////////////////////////////////////////////
  324. void SetEnableDisableUI(HWND hDlg, HWND hWndCombo, LPLDAPURL lplu, int nTab)
  325. {
  326. BOOL bIsWAB = FALSE, bHasLogo = FALSE;
  327. int swShowSimple, swShowSimpleWAB, swShowAdvanced;
  328. ULONG cbEID;
  329. LPENTRYID lpEID;
  330. // Just in case the list view lost its selection,
  331. // dont modify the UI
  332. if(!lplu && (CurrentContainerIsPAB(hWndCombo) != IS_LDAP))
  333. bIsWAB = TRUE;
  334. swShowSimple = (nTab == tabSimple) ? SW_SHOWNORMAL : SW_HIDE;
  335. swShowSimpleWAB = (nTab == tabSimple && bIsWAB) ? SW_SHOWNORMAL : SW_HIDE;
  336. swShowAdvanced = (nTab == tabAdvanced) ? SW_SHOWNORMAL : SW_HIDE;
  337. // Show / Hide the simple tab elements based on what this is
  338. //
  339. ShowWindow(GetDlgItem(hDlg,IDC_FIND_EDIT_NAME), swShowSimple);
  340. ShowWindow(GetDlgItem(hDlg,IDC_FIND_STATIC_NAME), swShowSimple);
  341. ShowWindow(GetDlgItem(hDlg,IDC_FIND_EDIT_EMAIL), swShowSimple);
  342. ShowWindow(GetDlgItem(hDlg,IDC_FIND_STATIC_EMAIL), swShowSimple);
  343. ShowWindow(GetDlgItem(hDlg,IDC_FIND_EDIT_STREET), swShowSimpleWAB);
  344. ShowWindow(GetDlgItem(hDlg,IDC_FIND_STATIC_STREET), swShowSimpleWAB);
  345. ShowWindow(GetDlgItem(hDlg,IDC_FIND_EDIT_PHONE), swShowSimpleWAB);
  346. ShowWindow(GetDlgItem(hDlg,IDC_FIND_STATIC_PHONE), swShowSimpleWAB);
  347. ShowWindow(GetDlgItem(hDlg,IDC_FIND_EDIT_ANY), swShowSimpleWAB);
  348. ShowWindow(GetDlgItem(hDlg,IDC_FIND_STATIC_ANY), swShowSimpleWAB);
  349. EnableWindow(GetDlgItem(hDlg,IDC_FIND_EDIT_STREET), bIsWAB);
  350. EnableWindow(GetDlgItem(hDlg,IDC_FIND_STATIC_STREET), bIsWAB);
  351. EnableWindow(GetDlgItem(hDlg,IDC_FIND_EDIT_PHONE), bIsWAB);
  352. EnableWindow(GetDlgItem(hDlg,IDC_FIND_STATIC_PHONE), bIsWAB);
  353. EnableWindow(GetDlgItem(hDlg,IDC_FIND_EDIT_ANY), bIsWAB);
  354. EnableWindow(GetDlgItem(hDlg,IDC_FIND_STATIC_ANY), bIsWAB);
  355. // Show / Hide the advanced tab elements based on what this is
  356. //
  357. ShowWindow(GetDlgItem(hDlg, IDC_FIND_STATIC_ADVANCED), swShowAdvanced);
  358. ShowWindow(GetDlgItem(hDlg, IDC_FIND_COMBO_FIELD), swShowAdvanced);
  359. ShowWindow(GetDlgItem(hDlg, IDC_FIND_COMBO_CONDITION), swShowAdvanced);
  360. ShowWindow(GetDlgItem(hDlg, IDC_FIND_EDIT_ADVANCED), swShowAdvanced);
  361. ShowWindow(GetDlgItem(hDlg, IDC_FIND_LIST_CONDITIONS), swShowAdvanced);
  362. ShowWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_ADDCONDITION), swShowAdvanced);
  363. ShowWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_REMOVECONDITION), swShowAdvanced);
  364. // Turn off advanced searching for WAB
  365. //EnableWindow(GetDlgItem(hDlg, IDC_FIND_STATIC_ADVANCED), !bIsWAB);
  366. //EnableWindow(GetDlgItem(hDlg, IDC_FIND_COMBO_FIELD), !bIsWAB);
  367. //EnableWindow(GetDlgItem(hDlg, IDC_FIND_COMBO_CONDITION), !bIsWAB);
  368. //EnableWindow(GetDlgItem(hDlg, IDC_FIND_EDIT_ADVANCED), !bIsWAB);
  369. //EnableWindow(GetDlgItem(hDlg, IDC_FIND_LIST_CONDITIONS), !bIsWAB);
  370. //EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_ADDCONDITION), !bIsWAB);
  371. //EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_REMOVECONDITION), !bIsWAB);
  372. //EnableWindow(GetDlgItem(hDlg, IDC_FIND_LIST_CONDITIONS), !bIsWAB);
  373. if (! bIsWAB)
  374. { // This is an LDAP container
  375. LDAPSERVERPARAMS lsp = {0};
  376. ULONG iItemIndex;
  377. LPTSTR lpBuf = NULL;
  378. // Does it have a URL registered?
  379. // Get the LDAP server properties for the selected container
  380. GetSelectedText(hWndCombo, &lpBuf);
  381. GetLDAPServerParams(lpBuf, &lsp);
  382. if( nTab == tabSimple &&
  383. lsp.lpszLogoPath && lstrlen(lsp.lpszLogoPath) &&
  384. GetFileAttributes(lsp.lpszLogoPath) != 0xFFFFFFFF )
  385. {
  386. HANDLE hbm = LoadImage( hinstMapiX, lsp.lpszLogoPath,
  387. IMAGE_BITMAP, 134,38,
  388. LR_LOADFROMFILE | LR_LOADMAP3DCOLORS); //| LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS); //LR_DEFAULTCOLOR);
  389. if(hbm)
  390. {
  391. SendDlgItemMessage(hDlg, IDC_FIND_STATIC_LOGO, STM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) hbm);
  392. bHasLogo = TRUE;
  393. }
  394. }
  395. if (lsp.lpszURL && lstrlen(lsp.lpszURL) && bIsHttpPrefix(lsp.lpszURL))
  396. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_SERVER_INFO), TRUE);
  397. else
  398. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_SERVER_INFO), FALSE);
  399. FreeLDAPServerParams(lsp);
  400. if(lpBuf)
  401. LocalFree(lpBuf);
  402. }
  403. else
  404. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_SERVER_INFO), FALSE);
  405. ShowWindow(GetDlgItem(hDlg, IDC_FIND_STATIC_LOGO), (bHasLogo ? SW_SHOW : SW_HIDE));
  406. return;
  407. }
  408. //$$/////////////////////////////////////////////////////////////////////////////
  409. //
  410. // SetSearchUI - Sets up the Search UI
  411. //
  412. /////////////////////////////////////////////////////////////////////////////////
  413. BOOL SetSearchUI(HWND hDlg, LPWAB_FIND_PARAMS lpWFP)
  414. {
  415. ABOOK_POSCOLSIZE ABPosColSize = {0};
  416. int i =0;
  417. // Set the font of all the children to the default GUI font
  418. EnumChildWindows( hDlg,
  419. SetChildDefaultGUIFont,
  420. (LPARAM) 0);
  421. // Set the title on the TAB
  422. AddTabItem(hDlg, tabSimple);
  423. AddTabItem(hDlg, tabAdvanced);
  424. //
  425. // Set the max text length of all the edit boxes to MAX_UI_STR
  426. //
  427. for(i=0;i<SEARCH_EDIT_MAX;i++)
  428. {
  429. SendMessage(GetDlgItem(hDlg,rgSearchEditID[i]),EM_SETLIMITTEXT,(WPARAM) MAX_UI_STR-16,0);
  430. }
  431. SendMessage(GetDlgItem(hDlg,IDC_FIND_EDIT_ADVANCED),EM_SETLIMITTEXT,(WPARAM) MAX_UI_STR-16,0);
  432. HrInitListView( GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS),
  433. LVS_REPORT,
  434. TRUE);
  435. {
  436. HWND hWndAnim = GetDlgItem(hDlg, IDC_FIND_ANIMATE1);
  437. if(Animate_Open(hWndAnim, MAKEINTRESOURCE(IDR_AVI_WABFIND)))
  438. {
  439. if(Animate_Play(hWndAnim, 0, 1, 0))
  440. Animate_Stop(hWndAnim);
  441. }
  442. }
  443. // Set the to, cc, bcc buttons appropriately
  444. if(lpWFP->lpAPFI)
  445. {
  446. // if this pointer is not null then we were called by a select recipients dlg
  447. if(lpWFP->lpAPFI->lpAdrParms)
  448. {
  449. LPADRPARM lpAdrParms = lpWFP->lpAPFI->lpAdrParms;
  450. ULONG i;
  451. // If this is called from the PickUser dialog, then the results list view
  452. // needs to be single select
  453. if(lpWFP->lpAPFI->DialogState == STATE_PICK_USER)
  454. {
  455. HWND hWndLV = GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS);
  456. DWORD dwStyle= GetWindowLong(hWndLV , GWL_STYLE);
  457. SetWindowLong(hWndLV , GWL_STYLE, dwStyle | LVS_SINGLESEL);
  458. }
  459. for(i=0;i < lpAdrParms->cDestFields; i++)
  460. {
  461. HWND hWndButton = GetDlgItem(hDlg, rgAdrParmButtonID[i]);
  462. ShowWindow(hWndButton, SW_NORMAL);
  463. EnableWindow(hWndButton, TRUE);
  464. if(lpAdrParms->lppszDestTitles)
  465. {
  466. LPTSTR lpTitle = (lpAdrParms->ulFlags & MAPI_UNICODE) ?
  467. (LPWSTR)lpAdrParms->lppszDestTitles[i] :
  468. ConvertAtoW((LPSTR)lpAdrParms->lppszDestTitles[i]);
  469. if(lpTitle)
  470. {
  471. ULONG Len = lstrlen(lpTitle);
  472. TCHAR szBuf[32];
  473. if (Len > ARRAYSIZE(szBuf) - 4)
  474. {
  475. ULONG iLen = TruncatePos(lpTitle, ARRAYSIZE(szBuf) - 4);
  476. CopyMemory(szBuf, lpTitle, min(iLen*sizeof(TCHAR), sizeof(szBuf)));
  477. szBuf[iLen] = '\0';
  478. }
  479. else
  480. StrCpyN(szBuf,lpTitle, ARRAYSIZE(szBuf));
  481. StrCatBuff(szBuf,szArrow, ARRAYSIZE(szBuf));
  482. SetWindowText(hWndButton, szBuf);
  483. if(lpTitle != lpAdrParms->lppszDestTitles[i])
  484. LocalFreeAndNull(&lpTitle);
  485. }
  486. }
  487. }
  488. }
  489. }
  490. if(ReadRegistryPositionInfo((LPIAB)lpWFP->LDAPsp.lpIAB, &ABPosColSize, lpszRegFindPositionKeyValueName))
  491. {
  492. if( IsWindowOnScreen( &ABPosColSize.rcPos) )
  493. {
  494. int nW = ABPosColSize.rcPos.right-ABPosColSize.rcPos.left;
  495. MoveWindow(hDlg,
  496. ABPosColSize.rcPos.left,
  497. ABPosColSize.rcPos.top,
  498. (nW < lpWFP->MinDlgWidth) ? lpWFP->MinDlgWidth : nW,
  499. lpWFP->MinDlgHeight,
  500. FALSE);
  501. }
  502. }
  503. else
  504. {
  505. MoveWindow(hDlg,
  506. 20,
  507. 20,
  508. lpWFP->MinDlgWidth,
  509. lpWFP->MinDlgHeight,
  510. FALSE);
  511. }
  512. if(ABPosColSize.nTab > tabMax)
  513. ABPosColSize.nTab = tabSimple;
  514. TabCtrl_SetCurSel(GetDlgItem(hDlg, IDC_TAB_FIND), ABPosColSize.nTab);
  515. if(lpWFP->bShowFullDialog)
  516. ResizeSearchDlg(hDlg, lpWFP);
  517. {
  518. TCHAR szBuf[MAX_PATH];
  519. LoadString(hinstMapiX, idsSearchDialogTitle, szBuf, ARRAYSIZE(szBuf));
  520. SetWindowText(hDlg, szBuf);
  521. }
  522. ImmAssociateContext(GetDlgItem(hDlg, IDC_FIND_EDIT_PHONE), (HIMC)NULL);
  523. return TRUE;
  524. }
  525. //$$/////////////////////////////////////////////////////////////////////////////
  526. //
  527. // ClearFieldCombo - Clears any allocated memory in the Advanced Field Combo
  528. //
  529. /////////////////////////////////////////////////////////////////////////////////
  530. void ClearFieldCombo(HWND hWndCombo)
  531. {
  532. int nCount = (int) SendMessage(hWndCombo, CB_GETCOUNT, 0, 0);
  533. LPTSTR lp = NULL;
  534. if(!nCount || nCount == CB_ERR)
  535. return;
  536. if(nCount >= LDAPFilterFieldMax)
  537. {
  538. // Get the item behind the first element
  539. // This item is a pointer to an allocated string
  540. lp = (LPTSTR) SendMessage(hWndCombo, CB_GETITEMDATA, (WPARAM) LDAPFilterFieldMax, 0);
  541. if(lp && (CB_ERR != (ULONG_PTR)lp))
  542. LocalFreeAndNull(&lp);
  543. }
  544. SendMessage(hWndCombo, CB_RESETCONTENT, 0, 0);
  545. return;
  546. }
  547. //$$/////////////////////////////////////////////////////////////////////////////
  548. //
  549. // FillAdvancedFieldCombos - Fills the Search UI with various information
  550. //
  551. /////////////////////////////////////////////////////////////////////////////////
  552. void FillAdvancedFieldCombos(HWND hDlg, HWND hWndComboContainer)
  553. {
  554. // The 2 advanced tab combos have data based on the current container ..
  555. // Hence need the CurrentContainerInfo here...
  556. BOOL bIsPAB = (CurrentContainerIsPAB(hWndComboContainer) != IS_LDAP);
  557. HWND hWndComboField = GetDlgItem(hDlg, IDC_FIND_COMBO_FIELD);
  558. HWND hWndComboCondition = GetDlgItem(hDlg, IDC_FIND_COMBO_CONDITION);
  559. int i = 0, nPos = 0, nMax = 0;
  560. TCHAR sz[MAX_PATH];
  561. ClearFieldCombo(hWndComboField);
  562. SendMessage(hWndComboCondition, CB_RESETCONTENT, 0, 0);
  563. {
  564. HWND hWndTab = GetDlgItem(hDlg, IDC_TAB_FIND);
  565. if(bIsPAB)
  566. {
  567. TabCtrl_SetCurSel(hWndTab, tabSimple);
  568. TabCtrl_DeleteItem(GetDlgItem(hDlg,IDC_TAB_FIND), tabAdvanced);
  569. }
  570. else
  571. {
  572. if(TabCtrl_GetItemCount(hWndTab) < tabMax)
  573. AddTabItem(hDlg, tabAdvanced);
  574. }
  575. }
  576. // If this is the WAB only give the "contains" option
  577. nMax = bIsPAB ? 1 : LDAPFilterOptionMax;
  578. for(i=0;i<nMax;i++)
  579. {
  580. LoadString(hinstMapiX, idsLDAPFilterOption1+i, sz, ARRAYSIZE(sz));
  581. nPos = (int) SendMessage(hWndComboCondition, CB_ADDSTRING, 0, (LPARAM) sz);
  582. }
  583. // Now add the default set of searchable attributes
  584. {
  585. LPTSTR lp = NULL;
  586. // If this is the WAB only give the Name and E-Mail option
  587. nMax = bIsPAB ? 2 : LDAPFilterFieldMax;
  588. for(i=0;i<nMax;i++)
  589. {
  590. LoadString(hinstMapiX, idsLDAPFilterField1+i, sz, ARRAYSIZE(sz));
  591. nPos = (int) SendMessage(hWndComboField, CB_ADDSTRING, 0, (LPARAM) sz);
  592. SendMessage(hWndComboField, CB_SETITEMDATA, (WPARAM) nPos, (LPARAM) g_rgszAdvancedFindAttrs[i]);
  593. }
  594. }
  595. // Check if this server has advanced Search attributes registered
  596. if(!bIsPAB)
  597. {
  598. LDAPSERVERPARAMS lsp = {0};
  599. LPTSTR lpBuf = NULL;
  600. GetSelectedText(hWndComboContainer, &lpBuf);
  601. GetLDAPServerParams(lpBuf, &lsp);
  602. if(lpBuf)
  603. LocalFree(lpBuf);
  604. if(lsp.lpszAdvancedSearchAttr && *(lsp.lpszAdvancedSearchAttr))
  605. {
  606. // we need to use this advanced search attributes
  607. ULONG cchSize = lstrlen(lsp.lpszAdvancedSearchAttr) + 1;
  608. LPTSTR lp = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)*(cchSize));
  609. LPTSTR lpAttr = NULL, lpName = NULL;
  610. BOOL bAssigned = FALSE;
  611. if(!lp)
  612. return;
  613. StrCpyN(lp, lsp.lpszAdvancedSearchAttr, cchSize);
  614. // Attribute format is:
  615. // Attribute-Display-Name:Attribute,Attribute-Display-Name:Attribute, etc
  616. // e.g.
  617. // co:Company,cn:Common Name,etc
  618. //
  619. // So we will parse this string and feed it into the combo
  620. lpAttr = lp;
  621. while(*lpAttr)
  622. {
  623. LPTSTR lpTemp = lpAttr;
  624. while(*lpTemp && *lpTemp != ':')
  625. lpTemp++;
  626. if(*lpTemp != ':')
  627. break;
  628. lpName = lpTemp+1;
  629. *lpTemp = '\0';
  630. lpTemp = lpName;
  631. while(*lpTemp && *lpTemp != ',')
  632. lpTemp++;
  633. if(*lpTemp == ',')
  634. {
  635. *lpTemp = '\0';
  636. lpTemp++;
  637. }
  638. // Note that the LDAPFilterFieldMax-th item in the list will point to the allocated
  639. // String 'lp'
  640. // Hence to clean up we only need to free this item in the combo
  641. // [PaulHi] 3/4/99 Memory leak fix and @todo
  642. // Why not just make a copy of g_rgszAdvancedFindAttrs so
  643. // that special cases like these can be added?
  644. nPos = (int) SendMessage(hWndComboField, CB_ADDSTRING, 0, (LPARAM) lpName);
  645. SendMessage(hWndComboField, CB_SETITEMDATA, (WPARAM) nPos, (LPARAM) lpAttr);
  646. bAssigned = TRUE;
  647. lpAttr = lpTemp;
  648. }
  649. // [PaulHi] 3/4/99 Memory leak fix. If this lp pointer isn't passed to the hWndComboField
  650. // combo box, for whatever reason, we need to deallocate it here.
  651. if (!bAssigned)
  652. LocalFreeAndNull(&lp);
  653. }
  654. FreeLDAPServerParams(lsp);
  655. }
  656. SendMessage(hWndComboField, CB_SETCURSEL, 0, 0);
  657. SendMessage(hWndComboCondition, CB_SETCURSEL, 0, 0);
  658. }
  659. //$$/////////////////////////////////////////////////////////////////////////////
  660. //
  661. // FillSearchUI - Fills the Search UI with various information
  662. //
  663. /////////////////////////////////////////////////////////////////////////////////
  664. BOOL FillSearchUI(HWND hDlg,LPWAB_FIND_PARAMS lpWFP)
  665. {
  666. int i;
  667. BOOL bRet = FALSE;
  668. HWND hWndCombo;
  669. TCHAR szBuf[MAX_UI_STR];
  670. LPLDAP_SEARCH_PARAMS lpLDAPsp = &(lpWFP->LDAPsp);
  671. //
  672. // Fill the fields if there is anything in the LDAPsp structure
  673. //
  674. for(i=0;i<SEARCH_EDIT_MAX;i++)
  675. {
  676. switch(rgSearchEditID[i])
  677. {
  678. case IDC_FIND_EDIT_NAME:
  679. StrCpyN(szBuf,lpLDAPsp->szData[ldspDisplayName], ARRAYSIZE(szBuf));
  680. break;
  681. case IDC_FIND_EDIT_EMAIL:
  682. StrCpyN(szBuf,lpLDAPsp->szData[ldspEmail], ARRAYSIZE(szBuf));
  683. break;
  684. case IDC_FIND_EDIT_STREET:
  685. StrCpyN(szBuf,lpLDAPsp->szData[ldspAddress], ARRAYSIZE(szBuf));
  686. break;
  687. case IDC_FIND_EDIT_PHONE:
  688. StrCpyN(szBuf,lpLDAPsp->szData[ldspPhone], ARRAYSIZE(szBuf));
  689. break;
  690. case IDC_FIND_EDIT_ANY:
  691. StrCpyN(szBuf,lpLDAPsp->szData[ldspOther], ARRAYSIZE(szBuf));
  692. break;
  693. }
  694. szBuf[MAX_UI_STR -1] = '\0';
  695. SetDlgItemText(hDlg,rgSearchEditID[i],szBuf);
  696. }
  697. //
  698. // Populate the combo box with the list of LDAP containers and set it to the current selection
  699. //
  700. hWndCombo = GetDlgItem(hDlg, IDC_FIND_COMBO_LIST);
  701. FreeLVItemParam(hWndCombo);
  702. if(lpWFP->lplu)
  703. {
  704. LPSERVERDAT lpSD = LocalAlloc(LMEM_ZEROINIT,sizeof(SERVERDAT));
  705. // Add this one item in the directory service list only ..
  706. if(lpSD)
  707. {
  708. lpSD->himl = NULL;
  709. lpSD->SB.cb = 0;
  710. lpSD->SB.lpb = NULL;
  711. ComboAddItem( hWndCombo, //hWndLV,
  712. lpWFP->lplu->lpszServer,
  713. (LPARAM) lpSD,
  714. NULL, NULL, NULL);
  715. SetWindowText(hWndCombo, lpWFP->lplu->lpszServer);
  716. SendMessage(hWndCombo, CB_SETCURSEL, 0, 0);
  717. }
  718. if(lpWFP->lplu->lpList)
  719. {
  720. HWND hWndLVResults = GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS);
  721. HrFillListView(hWndLVResults,
  722. lpWFP->lplu->lpList);
  723. UpdateButtons(hDlg, hWndLVResults, hWndCombo, lpWFP->lplu); //hWndLV);
  724. if(ListView_GetItemCount(hWndLVResults) > 0)
  725. {
  726. TCHAR szBuf[MAX_PATH];
  727. TCHAR szBufStr[MAX_PATH - 6];
  728. LoadString(hinstMapiX, idsSearchDialogTitleWithResults, szBufStr, ARRAYSIZE(szBufStr));
  729. wnsprintf(szBuf, ARRAYSIZE(szBuf), szBufStr, ListView_GetItemCount(hWndLVResults));
  730. SetWindowText(hDlg, szBuf);
  731. }
  732. }
  733. }
  734. else
  735. {
  736. TCHAR tsz[MAX_PATH];
  737. ULONG cb = ARRAYSIZE(tsz);
  738. LPTSTR lptszPreferredName = NULL;
  739. if(!lstrlen(lpLDAPsp->szContainerName))
  740. {
  741. LPIAB lpIAB = (LPIAB)lpLDAPsp->lpIAB;
  742. HKEY hKeyRoot = (lpIAB && lpIAB->hKeyCurrentUser) ? lpIAB->hKeyCurrentUser : HKEY_CURRENT_USER;
  743. // Read the last used container name from the registry
  744. if (ERROR_SUCCESS == RegQueryValue(hKeyRoot, szKeyLastFindServer, tsz, &cb))
  745. {
  746. StrCpyN(lpLDAPsp->szContainerName, tsz, ARRAYSIZE(lpLDAPsp->szContainerName));
  747. }
  748. // [PaulHi] 3/19/99 Raid 73461 First check to see if there is a policy setting
  749. // pointing to the preferred selected server. If so pass this server name in as
  750. // the preferred container name. We still use the below "szContainerName" as
  751. // back up if the preferred name doesn't exist in the server enumeration.
  752. // [PaulHi] 6/22/99 I acutally had this backwards. The policy should be checked
  753. // in this order: HKLM, HKCU, Identity (instead of Identity, HKCU, HKLM).
  754. cb = ARRAYSIZE(tsz);
  755. if (ERROR_SUCCESS == RegQueryValue(HKEY_LOCAL_MACHINE, c_tszPolicyPrefAccount, tsz, &cb))
  756. {
  757. lptszPreferredName = tsz;
  758. }
  759. else
  760. {
  761. // Try looking at HKCU
  762. cb = ARRAYSIZE(tsz);
  763. if ( (hKeyRoot != HKEY_CURRENT_USER) &&
  764. (ERROR_SUCCESS == RegQueryValue(HKEY_CURRENT_USER, c_tszPolicyPrefAccount, tsz, &cb)) )
  765. {
  766. lptszPreferredName = tsz;
  767. }
  768. else
  769. {
  770. // Finally try looking in current identity
  771. cb = ARRAYSIZE(tsz);
  772. if(ERROR_SUCCESS == RegQueryValue(hKeyRoot, c_tszPolicyPrefAccount, tsz, &cb))
  773. {
  774. lptszPreferredName = tsz;
  775. }
  776. }
  777. }
  778. }
  779. PopulateContainerList(lpLDAPsp->lpIAB,
  780. hWndCombo, // hWndLV,
  781. lpLDAPsp->szContainerName, // Last used server name
  782. lptszPreferredName); // Preferred server name
  783. }
  784. // Fill the combos for the advanced field
  785. FillAdvancedFieldCombos(hDlg, hWndCombo);
  786. SetEnableDisableUI(hDlg, hWndCombo, lpWFP->lplu,
  787. TabCtrl_GetCurSel(GetDlgItem(hDlg, IDC_TAB_FIND)) );
  788. return TRUE;
  789. }
  790. //$$/////////////////////////////////////////////////////////////////////////////
  791. //
  792. // UpdateButtons - Sets the state of the buttons based on various criteria
  793. //
  794. /////////////////////////////////////////////////////////////////////////////////
  795. void UpdateButtons(HWND hDlg, HWND hWndLVResults, HWND hWndCombo, LPLDAPURL lplu)
  796. {
  797. BOOL bIsWAB = FALSE;
  798. BOOL bHasResults = (ListView_GetItemCount(hWndLVResults) > 0) ? TRUE : FALSE;
  799. int i;
  800. if(!lplu && CurrentContainerIsPAB(hWndCombo) != IS_LDAP)
  801. bIsWAB = TRUE;
  802. if (bIsWAB && bHasResults)
  803. {
  804. // We have some search results
  805. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_DELETE), TRUE);
  806. }
  807. else
  808. {
  809. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_DELETE), FALSE);
  810. }
  811. if (!bIsWAB && bHasResults)
  812. {
  813. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_ADDTOWAB), TRUE);
  814. }
  815. else
  816. {
  817. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_ADDTOWAB), FALSE);
  818. }
  819. if(bHasResults)
  820. {
  821. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_PROPERTIES), TRUE);
  822. SendMessage (hDlg, DM_SETDEFID, IDC_FIND_BUTTON_PROPERTIES, 0);
  823. if(IsWindowVisible(GetDlgItem(hDlg, IDC_FIND_BUTTON_TO)))
  824. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_TO), TRUE);
  825. if(IsWindowVisible(GetDlgItem(hDlg, IDC_FIND_BUTTON_CC)))
  826. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_CC), TRUE);
  827. if(IsWindowVisible(GetDlgItem(hDlg, IDC_FIND_BUTTON_BCC)))
  828. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_BCC), TRUE);
  829. }
  830. else
  831. {
  832. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_PROPERTIES), FALSE);
  833. SendMessage (hDlg, DM_SETDEFID, IDC_FIND_BUTTON_FIND, 0);
  834. if(IsWindowVisible(GetDlgItem(hDlg, IDC_FIND_BUTTON_TO)))
  835. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_TO), FALSE);
  836. if(IsWindowVisible(GetDlgItem(hDlg, IDC_FIND_BUTTON_CC)))
  837. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_CC), FALSE);
  838. if(IsWindowVisible(GetDlgItem(hDlg, IDC_FIND_BUTTON_BCC)))
  839. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_BCC), FALSE);
  840. }
  841. return;
  842. }
  843. //$$/////////////////////////////////////////////////////////////////////////////
  844. //
  845. // GetAdvancedFilter - Creates an advanced filter from the pieces in the listbox
  846. //
  847. /////////////////////////////////////////////////////////////////////////////////
  848. void GetAdvancedFilter(HWND hDlg, LPTSTR * lppAdvFilter, BOOL bLocalSearch, LPLDAP_SEARCH_PARAMS lpLDAPsp)
  849. {
  850. LPTSTR lpF = NULL, lp =NULL;
  851. HWND hWndLB = GetDlgItem(hDlg, IDC_FIND_LIST_CONDITIONS);
  852. int nCount = 0, nLen = 0, i = 0;
  853. DWORD cchSizeF = 0;
  854. *lppAdvFilter = NULL;
  855. nCount = (int) SendMessage(hWndLB, LB_GETCOUNT, 0, 0);
  856. if(!nCount)
  857. return;
  858. for(i=0;i<nCount;i++)
  859. {
  860. lp = (LPTSTR) SendMessage(hWndLB, LB_GETITEMDATA, (WPARAM) i, 0);
  861. if(lp)
  862. nLen += lstrlen(lp) + 1;
  863. }
  864. cchSizeF = (nLen+4);
  865. lpF = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR) * cchSizeF); //add enough extra spaces for a 3 chars to each subfilter '(''&'')'
  866. if(!lpF)
  867. return;
  868. StrCpyN(lpF, szEmpty, cchSizeF);
  869. // We have to AND all the filters together
  870. if(nCount > 1)
  871. StrCatBuff(lpF, TEXT("(&"), cchSizeF);
  872. for(i=0;i<nCount;i++)
  873. {
  874. lp = (LPTSTR) SendMessage(hWndLB, LB_GETITEMDATA, (WPARAM) i, 0);
  875. if(lp)
  876. StrCatBuff(lpF, lp, cchSizeF);
  877. }
  878. if(nCount > 1)
  879. StrCatBuff(lpF, TEXT(")"), cchSizeF);
  880. DebugTrace( TEXT("Filter:%s\n"),lpF);
  881. *lppAdvFilter = lpF;
  882. if(bLocalSearch)
  883. {
  884. // the local search only allows searching on
  885. }
  886. }
  887. extern OlkContInfo *FindContainer(LPIAB lpIAB, ULONG cbEntryID, LPENTRYID lpEID);
  888. //$$/////////////////////////////////////////////////////////////////////////////
  889. //
  890. // DoTheSearchThing - Does the search thing and produces results
  891. //
  892. /////////////////////////////////////////////////////////////////////////////////
  893. BOOL DoTheSearchThing(HWND hDlg, LPWAB_FIND_PARAMS lpWFP)
  894. {
  895. int i =0, iItemIndex=0;
  896. LPTSTR lpBuf = NULL;
  897. TCHAR szBuf[MAX_UI_STR];
  898. HWND hWndCombo = GetDlgItem(hDlg, IDC_FIND_COMBO_LIST);
  899. HWND hWndLVResults = GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS);
  900. BOOL bRet = FALSE;
  901. LPLDAP_SEARCH_PARAMS lpLDAPsp = &(lpWFP->LDAPsp);
  902. HWND hWndAnim = GetDlgItem(hDlg, IDC_FIND_ANIMATE1);
  903. BOOL bAnimateStart = FALSE;
  904. HRESULT hr = E_FAIL;
  905. int SearchType = TRUE;
  906. LPSBinary lpsbCont = NULL;
  907. SBinary sbCont = {0};
  908. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  909. HCURSOR hOldCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  910. int nTab = TabCtrl_GetCurSel(GetDlgItem(hDlg, IDC_TAB_FIND));
  911. LPTSTR lpAdvFilter = NULL;
  912. // Check if the current container is an LDAP container or a PAB container
  913. // or an Outlook contact store container
  914. if(lpWFP->lplu)
  915. SearchType = IS_LDAP;
  916. else
  917. SearchType = CurrentContainerIsPAB(hWndCombo);
  918. // if this is an advanced search, assemble a search filter
  919. if(tabAdvanced == nTab)
  920. GetAdvancedFilter(hDlg, &lpAdvFilter, (SearchType != IS_LDAP), lpLDAPsp);
  921. else
  922. {
  923. for(i=0;i<SEARCH_EDIT_MAX;i++)
  924. {
  925. if(IsWindowEnabled(GetDlgItem(hDlg, rgSearchEditID[i])))
  926. {
  927. GetDlgItemText(hDlg,rgSearchEditID[i],szBuf,ARRAYSIZE(szBuf));
  928. TrimSpaces(szBuf);
  929. if (lstrlen(szBuf))
  930. bRet = TRUE;
  931. switch(rgSearchEditID[i])
  932. {
  933. case IDC_FIND_EDIT_NAME:
  934. StrCpyN(lpLDAPsp->szData[ldspDisplayName], szBuf, ARRAYSIZE(lpLDAPsp->szData[0]));
  935. break;
  936. case IDC_FIND_EDIT_EMAIL:
  937. StrCpyN(lpLDAPsp->szData[ldspEmail], szBuf, ARRAYSIZE(lpLDAPsp->szData[0]));
  938. break;
  939. case IDC_FIND_EDIT_STREET:
  940. StrCpyN(lpLDAPsp->szData[ldspAddress], szBuf, ARRAYSIZE(lpLDAPsp->szData[0]));
  941. break;
  942. case IDC_FIND_EDIT_PHONE:
  943. StrCpyN(lpLDAPsp->szData[ldspPhone], szBuf, ARRAYSIZE(lpLDAPsp->szData[0]));
  944. break;
  945. case IDC_FIND_EDIT_ANY:
  946. StrCpyN(lpLDAPsp->szData[ldspOther], szBuf, ARRAYSIZE(lpLDAPsp->szData[0]));
  947. break;
  948. }
  949. }
  950. }
  951. }
  952. GetSelectedText(hWndCombo, &lpBuf);
  953. StrCpyN(lpLDAPsp->szContainerName, (lpBuf ? lpBuf : szEmpty), ARRAYSIZE(lpLDAPsp->szContainerName));
  954. if(lpBuf)
  955. LocalFree(lpBuf);
  956. if((!bRet && nTab == tabSimple) ||
  957. (!lpAdvFilter && nTab == tabAdvanced) )
  958. {
  959. ShowMessageBox(hDlg,idsSpecifySearchCriteria,MB_ICONEXCLAMATION | MB_OK);
  960. goto out;
  961. }
  962. if(Animate_Open(hWndAnim, MAKEINTRESOURCE(IDR_AVI_WABFIND)))
  963. {
  964. if(Animate_Play(hWndAnim, 0, -1, -1))
  965. bAnimateStart = TRUE;
  966. }
  967. { // reset the window title
  968. TCHAR szBuf[MAX_PATH];
  969. LoadString(hinstMapiX, idsSearchDialogTitle, szBuf, ARRAYSIZE(szBuf));
  970. SetWindowText(hDlg, szBuf);
  971. }
  972. if(SearchType == IS_PAB)
  973. {
  974. lpsbCont = NULL;
  975. }
  976. else if(SearchType == IS_OLK)
  977. {
  978. if (pt_bIsWABOpenExSession)
  979. {
  980. OlkContInfo *polkci;
  981. // is this an outlook container ?
  982. GetCurrentContainerEID(hWndCombo,
  983. &(sbCont.cb),
  984. (LPENTRYID *)&(sbCont.lpb));
  985. EnterCriticalSection((&((LPIAB)lpLDAPsp->lpIAB)->cs));
  986. polkci = FindContainer((LPIAB)(lpLDAPsp->lpIAB),
  987. sbCont.cb, (LPENTRYID) sbCont.lpb);
  988. if(polkci)
  989. lpsbCont = &sbCont;
  990. LeaveCriticalSection((&((LPIAB)lpLDAPsp->lpIAB)->cs));
  991. }
  992. }
  993. // We do the actual search over here ....
  994. if(SearchType != IS_LDAP)
  995. {
  996. // Local Search
  997. ULONG ulFoundCount = 0;
  998. LPSBinary rgsbEntryIDs = NULL;
  999. ClearListView(hWndLVResults, &(lpWFP->lpContentsList));
  1000. HrDoLocalWABSearch( ((LPIAB)lpWFP->LDAPsp.lpIAB)->lpPropertyStore->hPropertyStore,
  1001. lpsbCont,
  1002. lpWFP->LDAPsp,
  1003. &ulFoundCount,
  1004. &rgsbEntryIDs);
  1005. if(ulFoundCount && rgsbEntryIDs)
  1006. {
  1007. ULONG i;
  1008. for(i=0;i<ulFoundCount;i++)
  1009. {
  1010. LPRECIPIENT_INFO lpItem = NULL;
  1011. if(!ReadSingleContentItem( lpWFP->LDAPsp.lpIAB,
  1012. rgsbEntryIDs[i].cb,
  1013. (LPENTRYID) rgsbEntryIDs[i].lpb,
  1014. &lpItem))
  1015. continue;
  1016. if(!lpItem)
  1017. continue;
  1018. //
  1019. // Hook in the lpItem into the lpContentsList so we can free it later
  1020. //
  1021. lpItem->lpPrev = NULL;
  1022. lpItem->lpNext = lpWFP->lpContentsList;
  1023. if (lpWFP->lpContentsList)
  1024. (lpWFP->lpContentsList)->lpPrev = lpItem;
  1025. (lpWFP->lpContentsList) = lpItem;
  1026. }
  1027. HrFillListView(hWndLVResults, lpWFP->lpContentsList);
  1028. }
  1029. FreeEntryIDs(((LPIAB)lpWFP->LDAPsp.lpIAB)->lpPropertyStore->hPropertyStore,
  1030. ulFoundCount,
  1031. rgsbEntryIDs);
  1032. if(ListView_GetItemCount(hWndLVResults) <= 0)
  1033. ShowMessageBox(hDlg,
  1034. pt_bIsWABOpenExSession ? idsNoFolderSearchResults : idsNoLocalSearchResults,
  1035. MB_OK | MB_ICONINFORMATION);
  1036. hr = S_OK;
  1037. }
  1038. else
  1039. {
  1040. pt_hWndFind = hDlg;
  1041. //
  1042. // At this point we can discard the old data
  1043. //
  1044. ClearListView(hWndLVResults,
  1045. (lpWFP->lplu && lpWFP->lplu->lpList) ? &(lpWFP->lplu->lpList) : &(lpWFP->lpContentsList));
  1046. if(lpWFP->lplu)
  1047. {
  1048. SRestriction Sres = {0};
  1049. if(!lpAdvFilter)
  1050. hr = HrGetLDAPSearchRestriction(lpWFP->LDAPsp, &Sres);
  1051. hr = LDAPSearchWithoutContainer(hDlg, lpWFP->lplu,
  1052. &Sres,
  1053. lpAdvFilter,
  1054. FALSE,
  1055. MAPI_DIALOG,
  1056. &(lpWFP->lpContentsList),
  1057. NULL,
  1058. NULL);
  1059. if(!lpAdvFilter && Sres.res.resAnd.lpRes)
  1060. MAPIFreeBuffer(Sres.res.resAnd.lpRes);
  1061. }
  1062. else
  1063. {
  1064. hr = HrSearchAndGetLDAPContents( lpWFP->LDAPsp,
  1065. lpAdvFilter,
  1066. hWndCombo,
  1067. lpWFP->LDAPsp.lpIAB,
  1068. lpWFP->SortInfo,
  1069. &(lpWFP->lpContentsList));
  1070. }
  1071. pt_hWndFind = NULL;
  1072. if(!HR_FAILED(hr))
  1073. {
  1074. #ifdef PAGED_RESULT_SUPPORT
  1075. if(bMorePagedResultsAvailable())
  1076. ShowHideMoreResultsButton(hDlg, TRUE);
  1077. #endif //#ifdef PAGED_RESULT_SUPPORT
  1078. hr = HrFillListView(hWndLVResults,
  1079. lpWFP->lpContentsList);
  1080. }
  1081. else
  1082. {
  1083. #ifdef PAGED_RESULT_SUPPORT
  1084. ClearCachedPagedResultParams();
  1085. ShowHideMoreResultsButton(hDlg, FALSE);
  1086. #endif //#ifdef PAGED_RESULT_SUPPORT
  1087. }
  1088. }
  1089. UpdateButtons(hDlg, hWndLVResults, hWndCombo, lpWFP->lplu);
  1090. if(!HR_FAILED(hr))
  1091. {
  1092. // The LDAp search results may not be in any sorted order - so always sort ...
  1093. SortListViewColumn((LPIAB)lpWFP->LDAPsp.lpIAB, hWndLVResults, colDisplayName, &(lpWFP->SortInfo), TRUE);
  1094. LVSelectItem(hWndLVResults, 0);
  1095. SetFocus(hWndLVResults);
  1096. }
  1097. if(ListView_GetItemCount(hWndLVResults) > 0)
  1098. {
  1099. TCHAR szBuf[MAX_PATH];
  1100. TCHAR szBufStr[MAX_PATH - 6];
  1101. LoadString(hinstMapiX, idsSearchDialogTitleWithResults, szBufStr, ARRAYSIZE(szBufStr));
  1102. wnsprintf(szBuf, ARRAYSIZE(szBuf), szBufStr, ListView_GetItemCount(hWndLVResults));
  1103. SetWindowText(hDlg, szBuf);
  1104. }
  1105. bRet = TRUE;
  1106. out:
  1107. if (bAnimateStart)
  1108. Animate_Stop(hWndAnim);
  1109. SetCursor(hOldCur);
  1110. if( bRet &&
  1111. !lpWFP->bShowFullDialog &&
  1112. (ListView_GetItemCount(hWndLVResults) > 0))
  1113. {
  1114. ResizeSearchDlg(hDlg, lpWFP);
  1115. }
  1116. LocalFreeAndNull(&lpAdvFilter);
  1117. return bRet;
  1118. }
  1119. //$$/////////////////////////////////////////////////////////////////////////
  1120. //
  1121. // Enforces a size in response to user resizing
  1122. //
  1123. ///////////////////////////////////////////////////////////////////////////
  1124. LRESULT EnforceSize(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPWAB_FIND_PARAMS lpWFP )
  1125. {
  1126. LPPOINT lppt = (LPPOINT)lParam; // lParam points to array of POINTs
  1127. if(!lpWFP->bInitialized)
  1128. {
  1129. RECT rc, rc1;
  1130. TCHAR sz[32];
  1131. GetWindowRect(hWnd, &rc);
  1132. GetWindowRect(GetDlgItem(hWnd, IDC_FIND_LIST_RESULTS), &rc1);
  1133. LoadString(hinstMapiX, idsFindDlgWidth, sz, CharSizeOf(sz));
  1134. lpWFP->MinDlgWidth = my_atoi(sz); // the resource is really wide to help localizers .. dont need that much
  1135. lpWFP->MinDlgHeight = (rc1.top - rc.top - 3);
  1136. lpWFP->MinDlgHeightWithResults = (rc.bottom - rc.top);
  1137. }
  1138. lppt[3].x = lpWFP->MinDlgWidth;
  1139. if(!lpWFP->bShowFullDialog)
  1140. {
  1141. lppt[4].y = lppt[3].y = lpWFP->MinDlgHeight;
  1142. }
  1143. else
  1144. {
  1145. lppt[3].y = lpWFP->MinDlgHeightWithResults;
  1146. }
  1147. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  1148. }
  1149. #define FIND_BUTTON_MAX 12 //Keep in sync with array below
  1150. int rgFindButtonID[]=
  1151. {
  1152. IDC_FIND_BUTTON_FIND,
  1153. IDC_FIND_BUTTON_SERVER_INFO,
  1154. IDC_FIND_BUTTON_STOP,
  1155. IDC_FIND_BUTTON_CLEAR,
  1156. IDC_FIND_BUTTON_CLOSE,
  1157. IDC_FIND_BUTTON_PROPERTIES,
  1158. IDC_FIND_BUTTON_DELETE,
  1159. IDC_FIND_BUTTON_ADDTOWAB,
  1160. IDC_FIND_BUTTON_MORE,
  1161. IDC_FIND_BUTTON_TO,
  1162. IDC_FIND_BUTTON_CC,
  1163. IDC_FIND_BUTTON_BCC
  1164. };
  1165. //$$*************************************************************************
  1166. //
  1167. // ResizeFindDialog - Resizes the child controls on the dialog in response to
  1168. // a WM_SIZE message
  1169. //
  1170. //
  1171. //***************************************************************************
  1172. void ResizeFindDialog(HWND hDlg, WPARAM wParam, LPARAM lParam, LPWAB_FIND_PARAMS lpWFP)
  1173. {
  1174. DWORD fwSizeType = (DWORD) wParam; // resizing flag
  1175. int nWidth = LOWORD(lParam); // width of client area
  1176. int nHeight = HIWORD(lParam); // height of client area
  1177. POINT ptLU; // Left, Upper vertex
  1178. POINT ptRB; // Right, Bottom vertex
  1179. RECT rc, rc1, rcDlg;
  1180. int nButtonWidth, nButtonHeight;
  1181. int nEditWidth, nEditHeight;
  1182. int nLVWidth, nLVHeight;
  1183. int nFrameWidth;
  1184. int nAnimateWidth, nAnimateHeight;
  1185. HWND hWndC = NULL;
  1186. int i;
  1187. HDWP hdwp = BeginDeferWindowPos(12);
  1188. // Resize based on width
  1189. // Move all the buttons to the right edge
  1190. for(i=0;i<FIND_BUTTON_MAX;i++)
  1191. {
  1192. hWndC = GetDlgItem(hDlg,rgFindButtonID[i]);
  1193. GetWindowRect(hWndC,&rc);
  1194. nButtonWidth = (rc.right - rc.left);
  1195. nButtonHeight = (rc.bottom - rc.top);
  1196. ptLU.y = rc.top;
  1197. ptLU.x = 0;
  1198. ScreenToClient(hDlg, &ptLU);
  1199. ptLU.x = nWidth - BORDER_SPACE - nButtonWidth;
  1200. MoveWindow(hWndC,ptLU.x,ptLU.y,nButtonWidth, nButtonHeight, TRUE);
  1201. }
  1202. nLVWidth = nWidth - BORDER_SPACE - BORDER_SPACE - nButtonWidth - BORDER_SPACE;
  1203. // Move the animation control too
  1204. hWndC = GetDlgItem(hDlg,IDC_FIND_ANIMATE1);
  1205. GetWindowRect(hWndC,&rc1);
  1206. nAnimateWidth = rc1.right - rc1.left;
  1207. nAnimateHeight = rc1.bottom - rc1.top;
  1208. ptLU.x = rc1.left;
  1209. ptLU.y = rc1.top;
  1210. ScreenToClient(hDlg, &ptLU);
  1211. ptLU.x = nWidth - BORDER_SPACE - nButtonWidth + (nButtonWidth - nAnimateWidth)/2;
  1212. MoveWindow(hWndC, ptLU.x, ptLU.y, nAnimateWidth, nAnimateHeight,TRUE);
  1213. // Resize the Combo
  1214. hWndC = GetDlgItem(hDlg,IDC_FIND_COMBO_LIST);
  1215. GetWindowRect(hWndC,&rc);
  1216. nLVHeight = rc.bottom - rc.top;
  1217. //
  1218. //This api works for both mirrored and unmirrored windows.
  1219. //
  1220. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  1221. ptLU.x = rc.left;
  1222. ptLU.y = rc.top;
  1223. nFrameWidth = nLVWidth + BORDER_SPACE - ptLU.x;
  1224. MoveWindow(hWndC, ptLU.x, ptLU.y, nFrameWidth, nLVHeight,TRUE);
  1225. ptRB.x = ptLU.x + nFrameWidth;
  1226. // Resize the TAB
  1227. hWndC = GetDlgItem(hDlg,IDC_TAB_FIND);
  1228. GetWindowRect(hWndC,&rc);
  1229. nLVHeight = rc.bottom - rc.top;
  1230. //
  1231. //This api working in both mirrored and unmirrored windows.
  1232. //
  1233. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  1234. ptLU.x = rc.left;
  1235. ptLU.y = rc.top;
  1236. nFrameWidth = nLVWidth + BORDER_SPACE - ptLU.x;
  1237. MoveWindow(hWndC, ptLU.x, ptLU.y, nFrameWidth, nLVHeight,TRUE);
  1238. ptRB.x = ptLU.x + nFrameWidth;
  1239. // Resize the Edit Controls
  1240. for(i=0;i<SEARCH_EDIT_MAX;i++)
  1241. {
  1242. hWndC = GetDlgItem(hDlg,rgSearchEditID[i]);
  1243. GetWindowRect(hWndC,&rc);
  1244. nEditHeight = (rc.bottom - rc.top);
  1245. //
  1246. //This api works for both mirrored and unmirrored windows.
  1247. //
  1248. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  1249. ptLU.y = rc.top;
  1250. ptLU.x = rc.left;
  1251. nEditWidth = ptRB.x - BORDER_SPACE - ptLU.x; //ptRB.x is x coordinate of frame right edge
  1252. MoveWindow(hWndC,ptLU.x,ptLU.y,nEditWidth, nEditHeight, TRUE);
  1253. }
  1254. // Resize the advanced controls
  1255. // First the group-box
  1256. {
  1257. hWndC = GetDlgItem(hDlg,IDC_FIND_STATIC_ADVANCED);
  1258. GetWindowRect(hWndC,&rc);
  1259. nEditHeight = (rc.bottom - rc.top);
  1260. //
  1261. //This api works for both mirrored and unmirrored windows.
  1262. //
  1263. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  1264. ptLU.y = rc.top;
  1265. ptLU.x = rc.left;
  1266. nEditWidth = ptRB.x - BORDER_SPACE - ptLU.x; //ptRB.x is x coordinate of tab right edge
  1267. // update this variable with the group-box right border
  1268. ptRB.x = ptLU.x + nEditWidth;
  1269. MoveWindow(hWndC,ptLU.x,ptLU.y,nEditWidth, nEditHeight, TRUE);
  1270. }
  1271. // Resize the Advanced edit controls also
  1272. {
  1273. hWndC = GetDlgItem(hDlg,IDC_FIND_COMBO_FIELD);
  1274. GetWindowRect(hWndC,&rc);
  1275. nEditHeight = (rc.bottom - rc.top);
  1276. //
  1277. //This api works for both mirrored and unmirrored windows.
  1278. //
  1279. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  1280. ptLU.y = rc.top;
  1281. ptLU.x = rc.left;
  1282. nEditWidth = (ptRB.x - BORDER_SPACE - 2*CONTROL_SPACE - ptLU.x)/3; //ptRB.x is x coordinate of frame right edge
  1283. MoveWindow(hWndC,ptLU.x,ptLU.y,nEditWidth, nEditHeight, TRUE);
  1284. hWndC = GetDlgItem(hDlg,IDC_FIND_COMBO_CONDITION);
  1285. ptLU.x += nEditWidth + CONTROL_SPACE;
  1286. MoveWindow(hWndC,ptLU.x,ptLU.y,nEditWidth, nEditHeight, TRUE);
  1287. hWndC = GetDlgItem(hDlg,IDC_FIND_EDIT_ADVANCED);
  1288. ptLU.x += nEditWidth + CONTROL_SPACE;
  1289. MoveWindow(hWndC,ptLU.x,ptLU.y,nEditWidth, nEditHeight, TRUE);
  1290. }
  1291. // Move the two advanced buttons
  1292. for(i=0;i<2;i++)
  1293. {
  1294. hWndC = GetDlgItem(hDlg,rgAdvancedButtons[i]);
  1295. GetWindowRect(hWndC,&rc);
  1296. nEditHeight = (rc.bottom - rc.top);
  1297. //
  1298. //This api works for both mirrored and unmirrored windows.
  1299. //
  1300. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  1301. ptLU.y = rc.top;
  1302. ptLU.x = rc.left;
  1303. nEditWidth = rc.right - rc.left; // Dont modify width of the button
  1304. ptLU.x = ptRB.x - BORDER_SPACE - nEditWidth;
  1305. MoveWindow(hWndC,ptLU.x,ptLU.y,nEditWidth, nEditHeight, TRUE);
  1306. }
  1307. // update this variable with the left edge of the button
  1308. // List box width is adjusted based on this
  1309. ptRB.x = ptLU.x;
  1310. // Adjust the listbox width
  1311. {
  1312. hWndC = GetDlgItem(hDlg,IDC_FIND_LIST_CONDITIONS);
  1313. GetWindowRect(hWndC,&rc);
  1314. nEditHeight = (rc.bottom - rc.top);
  1315. //
  1316. //This api works for both mirrored and unmirrored windows.
  1317. //
  1318. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  1319. ptLU.y = rc.top;
  1320. ptLU.x = rc.left;
  1321. nEditWidth = ptRB.x - BORDER_SPACE - ptLU.x; //ptRB.x is x coordinate of frame right edge
  1322. MoveWindow(hWndC,ptLU.x,ptLU.y,nEditWidth, nEditHeight, TRUE);
  1323. }
  1324. // For the height, we only adjust the list view height
  1325. // Resize the List View
  1326. hWndC = GetDlgItem(hDlg,IDC_FIND_LIST_RESULTS);
  1327. GetWindowRect(hWndC,&rc);
  1328. //
  1329. //This api works for both mirrored and unmirrored windows.
  1330. //
  1331. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  1332. ptLU.x = rc.left;
  1333. ptLU.y = rc.top;
  1334. nLVHeight = nHeight - BORDER_SPACE - ptLU.y;
  1335. MoveWindow(hWndC, ptLU.x, ptLU.y, nLVWidth, nLVHeight,TRUE);
  1336. EndDeferWindowPos(hdwp);
  1337. return;
  1338. }
  1339. //$$**************************************************************************
  1340. //
  1341. // ShowContainerContextMenu - Shows the context menu for the container list
  1342. //
  1343. //
  1344. //****************************************************************************
  1345. /****/
  1346. void ShowContainerContextMenu(HWND hDlg,
  1347. HWND hWndCombo, //hWndLV,
  1348. LPARAM lParam)
  1349. {
  1350. HMENU hMenu = LoadMenu(hinstMapiX, MAKEINTRESOURCE(IDM_FIND_CONTEXTMENU_CONTAINER));
  1351. HMENU hMenuTrackPopUp = GetSubMenu(hMenu, 0);
  1352. if (!hMenu || !hMenuTrackPopUp)
  1353. {
  1354. DebugPrintError(( TEXT("LoadMenu failed: %x\n"),GetLastError()));
  1355. goto out;
  1356. }
  1357. if (CurrentContainerIsPAB(hWndCombo) != IS_LDAP)
  1358. EnableMenuItem(hMenuTrackPopUp,IDM_FIND_CONTAINERPROPERTIES,MF_BYCOMMAND | MF_GRAYED);
  1359. //
  1360. // Popup the menu
  1361. //
  1362. TrackPopupMenu( hMenuTrackPopUp,
  1363. TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  1364. LOWORD(lParam),
  1365. HIWORD(lParam),
  1366. 0,
  1367. hDlg,
  1368. NULL);
  1369. DestroyMenu(hMenu);
  1370. out:
  1371. return;
  1372. }
  1373. /****/
  1374. //$$**************************************************************************
  1375. //
  1376. // ShowContainerProperties - Shows the context menu for the container list
  1377. //
  1378. // hWndLV - list containing the list of containers
  1379. // We dont show any properties for the address book
  1380. //
  1381. //****************************************************************************
  1382. void ShowContainerProperties( HWND hDlg,
  1383. HWND hWndCombo,
  1384. LPWAB_FIND_PARAMS lpWFP)
  1385. {
  1386. LPTSTR lpBuf = NULL;
  1387. GetSelectedText(hWndCombo, &lpBuf);
  1388. if(!lpBuf || !lstrlen(lpBuf))
  1389. {
  1390. ShowMessageBox(hDlg, IDS_ADDRBK_MESSAGE_NO_ITEM, MB_OK | MB_ICONEXCLAMATION);
  1391. }
  1392. else
  1393. {
  1394. if(CurrentContainerIsPAB(hWndCombo) == IS_LDAP)
  1395. {
  1396. LPTSTR ptszName=NULL;
  1397. HrShowDSProps(hDlg, lpBuf, &ptszName, FALSE);
  1398. if (ptszName)
  1399. {
  1400. if(lstrcmpi(lpBuf, ptszName))
  1401. {
  1402. // The name changed, update it in the list view ...
  1403. SendMessage(hWndCombo, WM_SETREDRAW, FALSE, 0);
  1404. FreeLVItemParam(hWndCombo);
  1405. SendMessage(hWndCombo, CB_RESETCONTENT, 0, 0);
  1406. PopulateContainerList( lpWFP->LDAPsp.lpIAB,
  1407. hWndCombo, ptszName, NULL);
  1408. SendMessage(hWndCombo, WM_SETREDRAW, TRUE, 0);
  1409. SetEnableDisableUI(hDlg, hWndCombo, lpWFP->lplu,
  1410. TabCtrl_GetCurSel(GetDlgItem(hDlg, IDC_TAB_FIND)));
  1411. }
  1412. LocalFreeAndNull(&ptszName);
  1413. }
  1414. }
  1415. }
  1416. LocalFreeAndNull(&lpBuf);
  1417. return;
  1418. }
  1419. enum
  1420. {
  1421. filtContains=0,
  1422. filtIs,
  1423. filtStartsWith,
  1424. filtEndsWith,
  1425. filtSoundsLike,
  1426. filtMax
  1427. };
  1428. extern void EscapeIllegalChars(LPTSTR lpszSrcStr, LPTSTR lpszDestStr, ULONG cchDestStr);
  1429. /*//$$************************************************************************
  1430. //
  1431. // CreateSubFilter();
  1432. // Creates a subfilter basedon available data
  1433. //
  1434. // szFIlter is a preallocated buffer big enough
  1435. //
  1436. /////////////////////////////////////////////////////////////////////////////*/
  1437. void CreateSubFilter(LPTSTR pszField, int nCondition, LPTSTR pszText, LPTSTR pszFilter, DWORD cchSizeFilter)
  1438. {
  1439. LPTSTR pszTemplate = NULL;
  1440. TCHAR szCleanText[MAX_PATH*2];
  1441. EscapeIllegalChars(pszText, szCleanText, ARRAYSIZE(szCleanText));
  1442. switch(nCondition)
  1443. {
  1444. case filtContains:
  1445. pszTemplate = TEXT("(%s=*%s*)");
  1446. break;
  1447. case filtIs:
  1448. pszTemplate = TEXT("(%s=%s)");
  1449. break;
  1450. case filtStartsWith:
  1451. pszTemplate = TEXT("(%s=%s*)");
  1452. break;
  1453. case filtEndsWith:
  1454. pszTemplate = TEXT("(%s=*%s)");
  1455. break;
  1456. case filtSoundsLike:
  1457. pszTemplate = TEXT("(%s=~%s)");
  1458. break;
  1459. }
  1460. wnsprintf(pszFilter, cchSizeFilter, pszTemplate, pszField, szCleanText);
  1461. }
  1462. /*//$$************************************************************************
  1463. //
  1464. // HrAddFindFilterCondition(hDlg);
  1465. // Adds a condition to the advanced find list box
  1466. //
  1467. /////////////////////////////////////////////////////////////////////////////*/
  1468. HRESULT HrAddFindFilterCondition(HWND hDlg)
  1469. {
  1470. HWND hWndComboField = GetDlgItem(hDlg, IDC_FIND_COMBO_FIELD);
  1471. HWND hWndComboCondition = GetDlgItem(hDlg, IDC_FIND_COMBO_CONDITION);
  1472. HWND hWndLB = GetDlgItem(hDlg, IDC_FIND_LIST_CONDITIONS);
  1473. HRESULT hr = E_FAIL;
  1474. int nID = 0, nCount = 0, nPos = 0;
  1475. LPTSTR lpField = NULL, lpCondition = NULL, lpsz[3], lpFilter = NULL;
  1476. TCHAR szField[MAX_PATH], szCondition[MAX_PATH];
  1477. TCHAR szText[MAX_PATH], szString[MAX_PATH], szFormat[MAX_PATH];
  1478. DWORD cchSize = 0;
  1479. // if the text field is empty, do nothing
  1480. GetDlgItemText(hDlg, IDC_FIND_EDIT_ADVANCED, szText, ARRAYSIZE(szText));
  1481. if(!lstrlen(szText))
  1482. goto out;
  1483. // depending on whether this is the 1st item or not, there is an And in the beginning
  1484. nCount = (int) SendMessage(hWndLB, LB_GETCOUNT, 0, 0);
  1485. nID = ((nCount > 0) ? idsFindFilterAnd : idsFindFilter);
  1486. LoadString(hinstMapiX, nID, szFormat, ARRAYSIZE(szFormat));
  1487. // Get the selected item in the Field Combo
  1488. nPos = (int) SendMessage(hWndComboField, CB_GETCURSEL, 0, 0);
  1489. if(nPos == CB_ERR)
  1490. goto out;
  1491. cchSize = (DWORD)SendMessage(hWndComboField, CB_GETLBTEXTLEN, (WPARAM) nPos, (LPARAM) 0);
  1492. if ((cchSize == CB_ERR) || (ARRAYSIZE(szField) < cchSize))
  1493. goto out;
  1494. SendMessage(hWndComboField, CB_GETLBTEXT, (WPARAM) nPos, (LPARAM) szField);
  1495. lpField = (LPTSTR) SendMessage(hWndComboField, CB_GETITEMDATA, (WPARAM) nPos, 0);
  1496. // Get the selected item in the Condition Combo
  1497. nPos = (int) SendMessage(hWndComboCondition, CB_GETCURSEL, 0, 0);
  1498. if(nPos == CB_ERR)
  1499. goto out;
  1500. cchSize =(DWORD)SendMessage(hWndComboCondition, CB_GETLBTEXTLEN, (WPARAM) nPos, (LPARAM) 0);
  1501. if ((cchSize == CB_ERR) || (ARRAYSIZE(szCondition) < cchSize))
  1502. goto out;
  1503. SendMessage(hWndComboCondition, CB_GETLBTEXT, (WPARAM) nPos, (LPARAM) szCondition);
  1504. // Now create the formatted message
  1505. if( (lstrlen(szField) > 1023) ||
  1506. (lstrlen(szCondition) > 1023) ||
  1507. (lstrlen(szText) > 1023))
  1508. goto out;
  1509. lpsz[0] = szField;
  1510. lpsz[1] = szCondition;
  1511. lpsz[2] = szText;
  1512. if (! FormatMessage( FORMAT_MESSAGE_FROM_STRING |
  1513. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  1514. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1515. szFormat,
  1516. 0, // stringid
  1517. 0, // dwLanguageId
  1518. (LPTSTR)&lpCondition, // output buffer
  1519. 0,
  1520. (va_list *)lpsz))
  1521. {
  1522. DebugTrace( TEXT("FormatMessage -> %u\n"), GetLastError());
  1523. goto out;
  1524. }
  1525. // <TBD> create the sub filter at this point
  1526. CreateSubFilter(lpField, nPos, szText, szString, ARRAYSIZE(szString));
  1527. cchSize = (lstrlen(szString)+1);
  1528. lpFilter = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)* cchSize);
  1529. if(!lpFilter)
  1530. goto out;
  1531. StrCpyN(lpFilter, szString, cchSize);
  1532. nPos = (int) SendMessage(hWndLB, LB_ADDSTRING, 0, (LPARAM) lpCondition);
  1533. SendMessage(hWndLB, LB_SETITEMDATA, (WPARAM) nPos, (LPARAM) lpFilter);
  1534. SendMessage(hWndLB, LB_SETCURSEL, (WPARAM) nPos, 0);
  1535. DebugTrace( TEXT("%s\n"), lpFilter);
  1536. hr = S_OK;
  1537. out:
  1538. IF_WIN32(LocalFree(lpCondition);)
  1539. IF_WIN16(FormatMessageFreeMem(lpCondition);)
  1540. return hr;
  1541. }
  1542. //$$*************************************************************************
  1543. //
  1544. // DoInitialFindDlgResizing -
  1545. //
  1546. // There are so many controls (some which overlap) on the find dialog that
  1547. // localizers can't make head or tail of them - so we spread the controls around
  1548. // in the resource description and then at runtime, we move them all to their
  1549. // appropriate locations - right now, this means shifting the Advanced-Pane
  1550. // controls to be flush left with the beginning of the name static ..
  1551. //
  1552. //***************************************************************************
  1553. void DoInitialFindDlgResizing (HWND hDlg)
  1554. {
  1555. POINT ptLU; // Left, Upper vertex
  1556. RECT rcN, rcF, rc;
  1557. HWND hWndC = NULL;
  1558. int nMove = 0, nButtonWidth = 0 , nButtonHeight = 0;
  1559. int rgAdv[] = { IDC_FIND_STATIC_ADVANCED,
  1560. IDC_FIND_COMBO_FIELD,
  1561. IDC_FIND_COMBO_CONDITION,
  1562. IDC_FIND_EDIT_ADVANCED,
  1563. IDC_FIND_LIST_CONDITIONS,
  1564. IDC_FIND_BUTTON_ADDCONDITION,
  1565. IDC_FIND_BUTTON_REMOVECONDITION };
  1566. int i = 0, nAdvMax = 7;
  1567. GetWindowRect(GetDlgItem(hDlg, IDC_FIND_STATIC_NAME), &rcN);
  1568. GetWindowRect(GetDlgItem(hDlg, IDC_FIND_STATIC_ADVANCED), &rcF);
  1569. MapWindowPoints(NULL, hDlg, (LPPOINT)&rcN, 2);
  1570. MapWindowPoints(NULL, hDlg, (LPPOINT)&rcF, 2);
  1571. nMove = rcF.left - rcN.left; // we want to move everything left this many units
  1572. for(i=0;i<nAdvMax;i++)
  1573. {
  1574. hWndC = GetDlgItem(hDlg,rgAdv[i]);
  1575. GetWindowRect(hWndC,&rc);
  1576. nButtonWidth = (rc.right - rc.left);
  1577. nButtonHeight = (rc.bottom - rc.top);
  1578. MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
  1579. ptLU.y = rc.top;
  1580. ptLU.x = rc.left;
  1581. // ScreenToClient(hDlg, &ptLU);
  1582. ptLU.x -= nMove;
  1583. MoveWindow(hWndC,ptLU.x,ptLU.y,nButtonWidth, nButtonHeight, TRUE);
  1584. }
  1585. }
  1586. /****/
  1587. /*//$$************************************************************************
  1588. //
  1589. // fnSearch - Search Dialog Proc
  1590. //
  1591. **************************************************************************/
  1592. INT_PTR CALLBACK fnSearch(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1593. {
  1594. ULONG nLen = 0, nLenMax = 0, nRetVal=0;
  1595. HRESULT hr = hrSuccess;
  1596. static FILETIME ftLast = {0};
  1597. LPWAB_FIND_PARAMS lpWFP = (LPWAB_FIND_PARAMS) GetWindowLongPtr(hDlg,DWLP_USER);
  1598. LPLDAP_SEARCH_PARAMS lpLDAPsp = &(lpWFP->LDAPsp);
  1599. switch(message)
  1600. {
  1601. case WM_INITDIALOG:
  1602. SetWindowLongPtr(hDlg,DWLP_USER,lParam); //Save this for future reference
  1603. lpWFP = (LPWAB_FIND_PARAMS) lParam;
  1604. lpLDAPsp = &(lpWFP->LDAPsp);
  1605. {
  1606. HICON hIcon = LoadIcon(hinstMapiX, MAKEINTRESOURCE(IDI_ICON_ABOOK));
  1607. SendMessage(hDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) hIcon);
  1608. }
  1609. DoInitialFindDlgResizing (hDlg);
  1610. SetSearchUI(hDlg,lpWFP);
  1611. FillSearchUI(hDlg,lpWFP);
  1612. if(!GetParent(hDlg))
  1613. {
  1614. // Then this is going to be a top level dialog and won't block any identity
  1615. // changes .. most likely it came from the Find | People option
  1616. // In case the address book object is ready to receive identity change
  1617. // notifications, we should set our hWnd on the LPIAB object so we get a
  1618. // message telling us to refresh the user ..
  1619. ((LPIAB)(lpLDAPsp->lpIAB))->hWndBrowse = hDlg;
  1620. }
  1621. SetForegroundWindow(hDlg); // On OSR2, this window will sometimes not come up in focus - needs explicit call
  1622. lpWFP->bInitialized = TRUE;
  1623. break;
  1624. case WM_GETMINMAXINFO:
  1625. //enforce a minimum size for sanity
  1626. return EnforceSize(hDlg, message, wParam, lParam, lpWFP);
  1627. break;
  1628. default:
  1629. #ifndef WIN16
  1630. if((g_msgMSWheel && message == g_msgMSWheel)
  1631. // || message == WM_MOUSEWHEEL
  1632. )
  1633. {
  1634. if(GetFocus() == GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS))
  1635. SendMessage(GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS), message, wParam, lParam);
  1636. break;
  1637. }
  1638. #endif
  1639. return FALSE;
  1640. break;
  1641. case WM_COMMAND:
  1642. switch(GET_WM_COMMAND_CMD(wParam,lParam)) //check the notification code
  1643. {
  1644. case EN_CHANGE: //some edit box changed - dont care which
  1645. ShowHideMoreResultsButton(hDlg, FALSE);
  1646. switch(LOWORD(wParam))
  1647. {
  1648. case IDC_FIND_EDIT_ADVANCED:
  1649. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_ADDCONDITION), TRUE);
  1650. // Set focus on the ADD button
  1651. SendMessage (hDlg, DM_SETDEFID, IDC_FIND_BUTTON_ADDCONDITION, 0);
  1652. break;
  1653. default:
  1654. SendMessage (hDlg, DM_SETDEFID, IDC_FIND_BUTTON_FIND, 0);
  1655. break;
  1656. }
  1657. break;
  1658. case CBN_SELCHANGE:
  1659. ShowHideMoreResultsButton(hDlg, FALSE);
  1660. switch(LOWORD(wParam))
  1661. {
  1662. case IDC_FIND_COMBO_LIST:
  1663. FillAdvancedFieldCombos(hDlg, (HWND) lParam);
  1664. SetEnableDisableUI(hDlg, (HWND) lParam, lpWFP->lplu,
  1665. TabCtrl_GetCurSel(GetDlgItem(hDlg, IDC_TAB_FIND)));
  1666. break;
  1667. }
  1668. break;
  1669. }
  1670. switch (GET_WM_COMMAND_ID(wParam,lParam))
  1671. {
  1672. default:
  1673. return ProcessActionCommands( (LPIAB) lpWFP->LDAPsp.lpIAB,
  1674. GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS),
  1675. hDlg, message, wParam, lParam);
  1676. break;
  1677. case IDC_FIND_BUTTON_REMOVECONDITION:
  1678. {
  1679. HWND hWndLB = GetDlgItem(hDlg, IDC_FIND_LIST_CONDITIONS);
  1680. int nCount = 0, nPos = (int) SendMessage(hWndLB, LB_GETCURSEL, 0, 0);
  1681. if(nPos != LB_ERR)
  1682. {
  1683. LPTSTR lp = (LPTSTR) SendMessage(hWndLB, LB_GETITEMDATA, (WPARAM) nPos, 0);
  1684. if(lp)
  1685. LocalFree(lp);
  1686. SendMessage(hWndLB, LB_DELETESTRING, (WPARAM) nPos, 0);
  1687. nCount = (int) SendMessage(hWndLB, LB_GETCOUNT, 0, 0);
  1688. if(nCount == 0)
  1689. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_REMOVECONDITION), FALSE);
  1690. else
  1691. {
  1692. if(nPos >= nCount)
  1693. nPos--;
  1694. SendMessage(hWndLB, LB_SETCURSEL, (WPARAM) nPos, 0);
  1695. }
  1696. }
  1697. }
  1698. break;
  1699. case IDC_FIND_BUTTON_ADDCONDITION:
  1700. HrAddFindFilterCondition(hDlg);
  1701. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_REMOVECONDITION), TRUE);
  1702. // Default button is FIND
  1703. SendMessage (hDlg, DM_SETDEFID, IDC_FIND_BUTTON_FIND, 0);
  1704. break;
  1705. case IDC_FIND_BUTTON_STOP:
  1706. if(lpWFP->bLDAPActionInProgress)
  1707. {
  1708. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1709. if(pt_hDlgCancel)
  1710. SendMessage(pt_hDlgCancel, WM_COMMAND, (WPARAM) IDCANCEL, 0);
  1711. }
  1712. break;
  1713. // only difference between FIND and MORE is that
  1714. // in MORE we repeat the search with the cached paged result cookie
  1715. // if one exists. If the cookie doesnt exist, user wouldnt get to
  1716. // see the MORE button
  1717. // Any change in search parameters also hides the MORE button
  1718. case IDC_FIND_BUTTON_FIND:
  1719. #ifdef PAGED_RESULT_SUPPORT
  1720. if(!lpWFP->bLDAPActionInProgress)
  1721. ClearCachedPagedResultParams();
  1722. #endif //#ifdef PAGED_RESULT_SUPPORT
  1723. case IDC_FIND_BUTTON_MORE:
  1724. // 96/11/20 markdu BUG 11030
  1725. // Disable the find now button so we only get one search.
  1726. if(!lpWFP->bLDAPActionInProgress)
  1727. {
  1728. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1729. pt_bDontShowCancel = TRUE;
  1730. lpWFP->bUserCancel = FALSE;
  1731. lpWFP->bLDAPActionInProgress = TRUE;
  1732. ShowHideMoreResultsButton(hDlg, FALSE);
  1733. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_FIND), FALSE);
  1734. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_STOP), TRUE);
  1735. DoTheSearchThing(hDlg, lpWFP);
  1736. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_FIND), TRUE);
  1737. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_STOP), FALSE);
  1738. lpWFP->bLDAPActionInProgress = FALSE;
  1739. pt_bDontShowCancel = FALSE;
  1740. if(lpWFP->bUserCancel) // DId the user try to cancel while the search was happening
  1741. {
  1742. lpWFP->bUserCancel = FALSE;
  1743. PostMessage(hDlg, WM_COMMAND, (WPARAM) IDC_FIND_BUTTON_CLOSE, 0);
  1744. }
  1745. }
  1746. break;
  1747. case IDC_FIND_BUTTON_CLEAR:
  1748. if(!lpWFP->bLDAPActionInProgress)
  1749. {
  1750. int i;
  1751. TCHAR szBuf[MAX_PATH];
  1752. LoadString(hinstMapiX, idsSearchDialogTitle, szBuf, ARRAYSIZE(szBuf));
  1753. SetWindowText(hDlg, szBuf);
  1754. for(i=0;i<SEARCH_EDIT_MAX;i++)
  1755. SetDlgItemText(hDlg, rgSearchEditID[i], szEmpty);
  1756. // Clear the advanced buttons too
  1757. SetDlgItemText(hDlg, IDC_FIND_EDIT_ADVANCED, szEmpty);
  1758. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_ADDCONDITION), FALSE);
  1759. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_REMOVECONDITION), FALSE);
  1760. SendDlgItemMessage(hDlg, IDC_FIND_LIST_CONDITIONS, LB_RESETCONTENT, 0, 0);
  1761. ClearListView( GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS),
  1762. (lpWFP->lplu && lpWFP->lplu->lpList) ? &(lpWFP->lplu->lpList) : &(lpWFP->lpContentsList));
  1763. for(i=0;i<ldspMAX;i++)
  1764. {
  1765. StrCpyN(lpLDAPsp->szData[i], szEmpty, ARRAYSIZE(lpLDAPsp->szData[i]));
  1766. }
  1767. }
  1768. break;
  1769. case IDOK:
  1770. case IDCANCEL:
  1771. case IDC_FIND_BUTTON_CLOSE:
  1772. // Clear any contents in the Advanced LB
  1773. {
  1774. int nCount = 0, i = 0;
  1775. HWND hWndLB = GetDlgItem(hDlg, IDC_FIND_LIST_CONDITIONS);
  1776. nCount = (int) SendMessage(hWndLB, LB_GETCOUNT, 0, 0);
  1777. if(nCount)
  1778. {
  1779. for(i=0;i<nCount;i++)
  1780. {
  1781. LPTSTR lp = (LPTSTR) SendMessage(hWndLB, LB_GETITEMDATA, (WPARAM) i, 0);
  1782. if(lp)
  1783. LocalFree(lp);
  1784. }
  1785. SendMessage(hWndLB, LB_RESETCONTENT, 0, 0);
  1786. }
  1787. // Clear any allocated memory in the field combo box
  1788. ClearFieldCombo(GetDlgItem(hDlg, IDC_FIND_COMBO_FIELD));
  1789. }
  1790. // if there is an LDAP operation in progress, close it and set the
  1791. // flag to cancel from where the LDAP operation was initialized
  1792. // This prevents aborting any process incompletely and faulting
  1793. if(lpWFP->bLDAPActionInProgress)
  1794. {
  1795. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1796. if(pt_hDlgCancel)
  1797. SendMessage(pt_hDlgCancel, WM_COMMAND, (WPARAM) IDCANCEL, 0);
  1798. lpWFP->bUserCancel= TRUE;
  1799. }
  1800. else
  1801. {
  1802. SaveFindWindowPos(hDlg, (LPIAB)lpWFP->LDAPsp.lpIAB);
  1803. FreeLVItemParam(GetDlgItem(hDlg, IDC_FIND_COMBO_LIST));//IDC_FIND_LIST));
  1804. EndDialog(hDlg, SEARCH_CLOSE);
  1805. }
  1806. break;
  1807. case IDM_LVCONTEXT_COPY:
  1808. HrCopyItemDataToClipboard( hDlg,
  1809. lpWFP->LDAPsp.lpIAB,
  1810. GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS));
  1811. break;
  1812. case IDM_LVCONTEXT_PROPERTIES:
  1813. case IDC_FIND_BUTTON_PROPERTIES:
  1814. if(!lpWFP->bLDAPActionInProgress)
  1815. {
  1816. lpWFP->bLDAPActionInProgress = TRUE;
  1817. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_PROPERTIES), FALSE);
  1818. HrShowLVEntryProperties(GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS), 0,
  1819. lpWFP->LDAPsp.lpIAB,
  1820. &ftLast);
  1821. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_PROPERTIES), TRUE);
  1822. lpWFP->bLDAPActionInProgress = FALSE;
  1823. }
  1824. break;
  1825. case IDM_LVCONTEXT_DELETE:
  1826. case IDC_FIND_BUTTON_DELETE:
  1827. if(!lpWFP->bLDAPActionInProgress)
  1828. {
  1829. HWND hWndLVResults = GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS);
  1830. DeleteSelectedItems(hWndLVResults,
  1831. (LPADRBOOK)lpWFP->LDAPsp.lpIAB,
  1832. ((LPIAB)lpWFP->LDAPsp.lpIAB)->lpPropertyStore->hPropertyStore, &ftLast);
  1833. UpdateButtons( hDlg,
  1834. hWndLVResults,
  1835. GetDlgItem(hDlg, IDC_FIND_COMBO_LIST),
  1836. lpWFP->lplu);
  1837. {
  1838. TCHAR szBuf[MAX_PATH];
  1839. ULONG nItemCount = ListView_GetItemCount(hWndLVResults);
  1840. if (nItemCount <= 0)
  1841. {
  1842. LoadString(hinstMapiX, idsSearchDialogTitle, szBuf, ARRAYSIZE(szBuf));
  1843. // also free up the contents list so we dont show the deleted contents again
  1844. FreeRecipList(&(lpWFP->lpContentsList));
  1845. }
  1846. else
  1847. {
  1848. TCHAR szBufStr[MAX_PATH - 6];
  1849. LoadString(hinstMapiX, idsSearchDialogTitleWithResults, szBufStr, ARRAYSIZE(szBufStr));
  1850. wnsprintf(szBuf, ARRAYSIZE(szBuf), szBufStr, ListView_GetItemCount(hWndLVResults));
  1851. }
  1852. SetWindowText(hDlg, szBuf);
  1853. }
  1854. return 0;
  1855. }
  1856. break;
  1857. case IDM_LVCONTEXT_ADDTOWAB:
  1858. case IDC_FIND_BUTTON_ADDTOWAB:
  1859. if(!lpWFP->bLDAPActionInProgress)
  1860. {
  1861. HWND hWndLVResults = GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS);
  1862. lpWFP->bLDAPActionInProgress = TRUE;
  1863. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_ADDTOWAB), FALSE);
  1864. EnableWindow(hWndLVResults, FALSE); // need to do this to preserve the selection in the list
  1865. HrAddToWAB( lpWFP->LDAPsp.lpIAB,
  1866. hWndLVResults,
  1867. &ftLast);
  1868. EnableWindow(GetDlgItem(hDlg, IDC_FIND_BUTTON_ADDTOWAB), TRUE);
  1869. EnableWindow(hWndLVResults, TRUE);
  1870. SetColumnHeaderBmp(hWndLVResults, lpWFP->SortInfo);
  1871. lpWFP->bLDAPActionInProgress = FALSE;
  1872. SetFocus(hWndLVResults);
  1873. }
  1874. break;
  1875. case IDM_FIND_CONTAINERPROPERTIES:
  1876. if(!lpWFP->lplu)
  1877. {
  1878. ShowContainerProperties(hDlg,
  1879. GetDlgItem(hDlg, IDC_FIND_COMBO_LIST),
  1880. lpWFP);
  1881. }
  1882. break;
  1883. case IDM_NOTIFY_REFRESHUSER:
  1884. ReadWABCustomColumnProps((LPIAB)lpWFP->LDAPsp.lpIAB);
  1885. ReadRegistrySortInfo((LPIAB)lpWFP->LDAPsp.lpIAB, &(lpWFP->SortInfo));
  1886. case IDM_FIND_DIRECTORYSERVICES:
  1887. if(!lpWFP->bLDAPActionInProgress)
  1888. {
  1889. LPTSTR lpBuf = NULL;
  1890. HWND hWndCombo = GetDlgItem(hDlg, IDC_FIND_COMBO_LIST);
  1891. GetSelectedText(hWndCombo, &lpBuf);
  1892. if(lpBuf)
  1893. {
  1894. if(GET_WM_COMMAND_ID(wParam,lParam) == IDM_FIND_DIRECTORYSERVICES)
  1895. HrShowDirectoryServiceModificationDlg(hDlg, (LPIAB)lpWFP->LDAPsp.lpIAB);
  1896. FreeLVItemParam(hWndCombo);
  1897. PopulateContainerList( lpWFP->LDAPsp.lpIAB, hWndCombo, lpBuf, NULL);
  1898. SetEnableDisableUI(hDlg, hWndCombo, lpWFP->lplu, TabCtrl_GetCurSel(GetDlgItem(hDlg, IDC_TAB_FIND)));
  1899. LocalFree(lpBuf);
  1900. }
  1901. }
  1902. break;
  1903. case IDC_FIND_BUTTON_TO:
  1904. {
  1905. if(lpWFP->lpAPFI->DialogState == STATE_SELECT_RECIPIENTS)
  1906. {
  1907. ULONG ulMapiTo = MAPI_TO;
  1908. if ((lpWFP->lpAPFI->lpAdrParms->cDestFields > 0) && (lpWFP->lpAPFI->lpAdrParms->lpulDestComps))
  1909. ulMapiTo = lpWFP->lpAPFI->lpAdrParms->lpulDestComps[0];
  1910. ListAddItem( GetParent(hDlg),
  1911. GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS),
  1912. IDC_ADDRBK_LIST_TO,
  1913. lpWFP->lpAPFI->lppTo,
  1914. ulMapiTo);
  1915. SendMessage (hDlg, WM_COMMAND, (WPARAM) IDOK, 0);
  1916. }
  1917. else if(lpWFP->lpAPFI->DialogState == STATE_PICK_USER)
  1918. {
  1919. // Here we need to do a couple of things:
  1920. // - if no entry is selected, tell the user to select one
  1921. // - if an entry is selected, get its entryid and cache it
  1922. // and close this dialog
  1923. HWND hWndLV = GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS);
  1924. int iItemIndex = ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED);
  1925. if (iItemIndex == -1)
  1926. ShowMessageBox(hDlg, IDS_ADDRBK_MESSAGE_NO_ITEM, MB_OK | MB_ICONEXCLAMATION);
  1927. else
  1928. {
  1929. // Get the entryid of this selected item
  1930. LPRECIPIENT_INFO lpItem = GetItemFromLV(hWndLV, iItemIndex);
  1931. if (lpItem)
  1932. {
  1933. // remove this item from our linked list of arrays
  1934. // if this is the first item in the list then handle that special case too
  1935. lpWFP->lpAPFI->lpEntryID = LocalAlloc(LMEM_ZEROINIT, lpItem->cbEntryID);
  1936. if(lpWFP->lpAPFI->lpEntryID)
  1937. {
  1938. CopyMemory(lpWFP->lpAPFI->lpEntryID, lpItem->lpEntryID, lpItem->cbEntryID);
  1939. lpWFP->lpAPFI->cbEntryID = lpItem->cbEntryID;
  1940. SaveFindWindowPos(hDlg, (LPIAB)lpWFP->LDAPsp.lpIAB);
  1941. FreeLVItemParam(GetDlgItem(hDlg, IDC_FIND_COMBO_LIST));
  1942. EndDialog(hDlg, SEARCH_USE);
  1943. }
  1944. }
  1945. }
  1946. }
  1947. }
  1948. break;
  1949. case IDC_FIND_BUTTON_CC:
  1950. {
  1951. ULONG ulMapiTo = MAPI_CC;
  1952. if ((lpWFP->lpAPFI->lpAdrParms->cDestFields > 0) && (lpWFP->lpAPFI->lpAdrParms->lpulDestComps))
  1953. ulMapiTo = lpWFP->lpAPFI->lpAdrParms->lpulDestComps[1];
  1954. ListAddItem( GetParent(hDlg),
  1955. GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS),
  1956. IDC_ADDRBK_LIST_CC,
  1957. lpWFP->lpAPFI->lppCC,
  1958. ulMapiTo);
  1959. SendMessage (hDlg, WM_COMMAND, (WPARAM) IDOK, 0);
  1960. }
  1961. break;
  1962. case IDC_FIND_BUTTON_BCC:
  1963. {
  1964. ULONG ulMapiTo = MAPI_BCC;
  1965. if ((lpWFP->lpAPFI->lpAdrParms->cDestFields > 0) && (lpWFP->lpAPFI->lpAdrParms->lpulDestComps))
  1966. ulMapiTo = lpWFP->lpAPFI->lpAdrParms->lpulDestComps[2];
  1967. ListAddItem( GetParent(hDlg),
  1968. GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS),
  1969. IDC_ADDRBK_LIST_BCC,
  1970. lpWFP->lpAPFI->lppBCC,
  1971. ulMapiTo);
  1972. SendMessage (hDlg, WM_COMMAND, (WPARAM) IDOK, 0);
  1973. }
  1974. break;
  1975. case IDC_FIND_BUTTON_SERVER_INFO:
  1976. {
  1977. LDAPSERVERPARAMS lsp = {0};
  1978. ULONG iItemIndex;
  1979. LPTSTR lpBuf = NULL;
  1980. HWND hWndCombo = GetDlgItem(hDlg, IDC_FIND_COMBO_LIST);
  1981. HINSTANCE hInst;
  1982. // Does it have a URL registered?
  1983. // Get the LDAP server properties for the selected container
  1984. GetSelectedText(hWndCombo, &lpBuf);
  1985. if(lpBuf)
  1986. {
  1987. GetLDAPServerParams(lpBuf, &lsp);
  1988. if (lsp.lpszURL && lstrlen(lsp.lpszURL) && bIsHttpPrefix(lsp.lpszURL))
  1989. {
  1990. // Yes, there is a URL, shell execute it to bring up the browser.
  1991. HCURSOR hOldCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1992. hInst = ShellExecute(GetParent(hDlg), TEXT("open"), lsp.lpszURL, NULL, NULL, SW_SHOWNORMAL);
  1993. SetCursor(hOldCur);
  1994. }
  1995. FreeLDAPServerParams(lsp);
  1996. LocalFree(lpBuf);
  1997. }
  1998. }
  1999. break;
  2000. }
  2001. break;
  2002. case WM_SIZE:
  2003. ResizeFindDialog(hDlg, wParam, lParam, lpWFP);
  2004. return 0;
  2005. break;
  2006. case WM_CLOSE:
  2007. //treat it like a cancel button
  2008. SendMessage (hDlg, WM_COMMAND, (WPARAM) IDCANCEL, 0);
  2009. break;
  2010. case WM_HELP:
  2011. WABWinHelp(((LPHELPINFO)lParam)->hItemHandle,
  2012. g_szWABHelpFileName,
  2013. HELP_WM_HELP,
  2014. (DWORD_PTR)(LPSTR) rgSrchHelpIDs );
  2015. break;
  2016. case WM_CONTEXTMENU:
  2017. if ((HWND)wParam == GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS))
  2018. {
  2019. ShowLVContextMenu( lvDialogFind,
  2020. GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS),
  2021. GetDlgItem(hDlg, IDC_FIND_COMBO_LIST),
  2022. lParam,
  2023. NULL,
  2024. lpWFP->LDAPsp.lpIAB, NULL);
  2025. }
  2026. else if ((HWND)wParam == GetDlgItem(hDlg, IDC_FIND_COMBO_LIST) && (!lpWFP->lplu))
  2027. {
  2028. ShowContainerContextMenu( hDlg,
  2029. GetDlgItem(hDlg, IDC_FIND_COMBO_LIST),
  2030. lParam);
  2031. }
  2032. else
  2033. {
  2034. WABWinHelp((HWND) wParam,
  2035. g_szWABHelpFileName,
  2036. HELP_CONTEXTMENU,
  2037. (DWORD_PTR)(LPVOID) rgSrchHelpIDs );
  2038. }
  2039. break;
  2040. break;
  2041. case WM_VKEYTOITEM:
  2042. if( VK_DELETE == LOWORD(wParam) &&
  2043. SendMessage((HWND) lParam, LB_GETCOUNT, 0, 0) > 0) // Delete pressed
  2044. {
  2045. SendMessage(hDlg, WM_COMMAND, (WPARAM) IDC_FIND_BUTTON_REMOVECONDITION, 0);
  2046. return -2; // means we handled the keystroke completely
  2047. }
  2048. else
  2049. return DefWindowProc(hDlg, message, wParam, lParam);
  2050. break;
  2051. case WM_NOTIFY:
  2052. switch((int) wParam)
  2053. {
  2054. case IDC_TAB_FIND:
  2055. if(((NMHDR FAR *)lParam)->code == TCN_SELCHANGE)
  2056. {
  2057. int nTab = TabCtrl_GetCurSel(((NMHDR FAR *)lParam)->hwndFrom);
  2058. SetEnableDisableUI( hDlg,
  2059. GetDlgItem(hDlg, IDC_FIND_COMBO_LIST),
  2060. lpWFP->lplu,
  2061. nTab);
  2062. if(nTab == tabSimple)
  2063. SetFocus(GetDlgItem(hDlg, IDC_FIND_EDIT_NAME));
  2064. else
  2065. SetFocus(GetDlgItem(hDlg, IDC_FIND_EDIT_ADVANCED));
  2066. }
  2067. break;
  2068. case IDC_FIND_LIST_RESULTS:
  2069. #ifdef WIN16 // Context menu handler for WIN16
  2070. if(((NMHDR FAR *)lParam)->code == NM_RCLICK)
  2071. {
  2072. POINT pt;
  2073. GetCursorPos(&pt);
  2074. ShowLVContextMenu( lvDialogFind,
  2075. GetDlgItem(hDlg, IDC_FIND_LIST_RESULTS),
  2076. GetDlgItem(hDlg, IDC_FIND_COMBO_LIST),
  2077. MAKELPARAM(pt.x, pt.y),
  2078. NULL,
  2079. lpWFP->LDAPsp.lpIAB, NULL);
  2080. }
  2081. #endif
  2082. return ProcessLVResultsMessages(hDlg,message,wParam,lParam, lpWFP);
  2083. break;
  2084. }
  2085. break;
  2086. }
  2087. return TRUE;
  2088. }
  2089. /**********
  2090. //$$////////////////////////////////////////////////////////////////////////////////////////
  2091. //
  2092. // ProcessLVMessages - Processes messages for the Container list view control
  2093. //
  2094. //////////////////////////////////////////////////////////////////////////////////////////
  2095. LRESULT ProcessLVMessages(HWND hWnd, UINT uMsg, UINT wParam, LPARAM lParam)
  2096. {
  2097. NM_LISTVIEW * pNm = (NM_LISTVIEW *)lParam;
  2098. HWND hWndLV = pNm->hdr.hwndFrom;
  2099. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  2100. switch(pNm->hdr.code)
  2101. {
  2102. case NM_DBLCLK:
  2103. SendMessage (hWnd, WM_COMMAND, (WPARAM) IDM_FIND_CONTAINERPROPERTIES, 0);
  2104. break;
  2105. case LVN_ITEMCHANGED:
  2106. case NM_SETFOCUS:
  2107. case NM_CLICK:
  2108. case NM_RCLICK:
  2109. SetEnableDisableUI(hWnd, hWndLV);
  2110. break;
  2111. case NM_CUSTOMDRAW:
  2112. {
  2113. NMCUSTOMDRAW *pnmcd=(NMCUSTOMDRAW*)lParam;
  2114. NM_LISTVIEW * pNm = (NM_LISTVIEW *)lParam;
  2115. NMLVCUSTOMDRAW * pnmlvcd = (NMLVCUSTOMDRAW * )lParam;
  2116. if(pnmcd->dwDrawStage==CDDS_PREPAINT)
  2117. {
  2118. SetWindowLong(hWnd, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW | CDRF_DODEFAULT);
  2119. return TRUE;
  2120. }
  2121. else if(pnmcd->dwDrawStage==CDDS_ITEMPREPAINT)
  2122. {
  2123. LPSERVERDAT lpSD = (LPSERVERDAT) pnmcd->lItemlParam;
  2124. if(lpSD != 0 &&
  2125. (WAB_PAB != IsWABEntryID(lpSD->SB.cb,
  2126. (LPENTRYID) lpSD->SB.lpb,
  2127. NULL, NULL, NULL)) &&
  2128. lpSD->himl)
  2129. {
  2130. HDC hdcLV = pnmlvcd->nmcd.hdc;
  2131. RECT rcLVItem;
  2132. UINT fType = ILD_NORMAL;
  2133. ListView_GetItemRect(hWndLV, pnmcd->dwItemSpec, &rcLVItem, LVIR_BOUNDS);
  2134. if (ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED) == (int) pnmcd->dwItemSpec)
  2135. {
  2136. FillRect(hdcLV, &rcLVItem, (HBRUSH) (COLOR_HIGHLIGHT+1));
  2137. //fType |= ILD_BLEND25;
  2138. DrawFocusRect(hdcLV, &rcLVItem);
  2139. }
  2140. else
  2141. FillRect(hdcLV, &rcLVItem, (HBRUSH) (COLOR_WINDOW+1));
  2142. if(!gpfnImageList_Draw( lpSD->himl,
  2143. 0,
  2144. hdcLV,
  2145. rcLVItem.left + L_BITMAP_WIDTH + 1, //gives enough space to paint the icon
  2146. rcLVItem.top,
  2147. fType))
  2148. {
  2149. DebugPrintError(( TEXT("ImageList_Draw failed\n")));
  2150. }
  2151. if (ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED) == (int) pnmcd->dwItemSpec)
  2152. fType |= ILD_BLEND25;
  2153. {
  2154. HIMAGELIST himlLV = ListView_GetImageList(hWndLV,LVSIL_SMALL);
  2155. gpfnImageList_Draw(himlLV, imageDirectoryServer, hdcLV, rcLVItem.left + 1, rcLVItem.top, fType);
  2156. }
  2157. SetWindowLong(hWnd, DWL_MSGRESULT, CDRF_SKIPDEFAULT);
  2158. return TRUE;
  2159. }
  2160. }
  2161. SetWindowLong(hWnd, DWL_MSGRESULT, CDRF_DODEFAULT);
  2162. return TRUE;
  2163. }
  2164. break;
  2165. }
  2166. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  2167. }
  2168. /********/
  2169. //$$////////////////////////////////////////////////////////////////////////////////////////
  2170. //
  2171. // ProcessLVResultsMessages - Processes messages for the Search Results list view control
  2172. //
  2173. //////////////////////////////////////////////////////////////////////////////////////////
  2174. LRESULT ProcessLVResultsMessages(HWND hWnd,
  2175. UINT uMsg,
  2176. WPARAM wParam,
  2177. LPARAM lParam,
  2178. LPWAB_FIND_PARAMS lpWFP)
  2179. {
  2180. NM_LISTVIEW * pNm = (NM_LISTVIEW *)lParam;
  2181. HWND hWndLV = pNm->hdr.hwndFrom;
  2182. // Bug 17027: GPF due to null lpWFP
  2183. if(lpWFP)
  2184. {
  2185. if(lpWFP->bLDAPActionInProgress)
  2186. return 0;
  2187. }
  2188. switch(pNm->hdr.code)
  2189. {
  2190. case LVN_COLUMNCLICK:
  2191. if(lpWFP)
  2192. SortListViewColumn((LPIAB)lpWFP->LDAPsp.lpIAB, hWndLV, pNm->iSubItem, &(lpWFP->SortInfo), FALSE);
  2193. break;
  2194. case LVN_KEYDOWN:
  2195. switch(((LV_KEYDOWN FAR *) lParam)->wVKey)
  2196. {
  2197. case VK_DELETE:
  2198. if(CurrentContainerIsPAB(GetDlgItem(hWnd, IDC_FIND_COMBO_LIST)) != IS_LDAP)
  2199. SendMessage (hWnd, WM_COMMAND, (WPARAM) IDC_FIND_BUTTON_DELETE, 0);
  2200. return 0;
  2201. break;
  2202. case VK_RETURN:
  2203. SendMessage (hWnd, WM_COMMAND, (WPARAM) IDC_FIND_BUTTON_PROPERTIES, 0);
  2204. return 0;
  2205. }
  2206. break;
  2207. case NM_DBLCLK:
  2208. SendMessage (hWnd, WM_COMMAND, (WPARAM) IDC_FIND_BUTTON_PROPERTIES, 0);
  2209. return 0;
  2210. break;
  2211. case NM_CUSTOMDRAW:
  2212. return ProcessLVCustomDraw(hWnd, lParam, TRUE);
  2213. break;
  2214. }
  2215. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  2216. }
  2217. //$$////////////////////////////////////////////////////////////////////////////
  2218. //
  2219. // SaveFindWindowPos - saves the find window position and size
  2220. //
  2221. ////////////////////////////////////////////////////////////////////////////////
  2222. void SaveFindWindowPos(HWND hWnd, LPIAB lpIAB)
  2223. {
  2224. ABOOK_POSCOLSIZE ABPosColSize = {0};
  2225. WINDOWPLACEMENT wpl = {0};
  2226. wpl.length = sizeof(WINDOWPLACEMENT);
  2227. // This call tells us the window state and normal size and position
  2228. GetWindowPlacement(hWnd, &wpl);
  2229. // There seems to be a bug in GetWindowPlacement that
  2230. // doesnt account for various taskbars on the screen when
  2231. // returning the Window's Normal Position .. as a result
  2232. // the stored coordinates won't be accurate. Instead, we'll
  2233. // use those coordinates only if the window is maximized or
  2234. // minimized - otherwise we will use the GetWindowRect
  2235. // coordinates.
  2236. // Get the screen position of this window
  2237. GetWindowRect(hWnd, &(ABPosColSize.rcPos));
  2238. if(wpl.showCmd != SW_SHOWNORMAL)
  2239. {
  2240. ABPosColSize.rcPos = wpl.rcNormalPosition;
  2241. }
  2242. ABPosColSize.nTab = TabCtrl_GetCurSel(GetDlgItem(hWnd, IDC_TAB_FIND));
  2243. WriteRegistryPositionInfo(lpIAB, &ABPosColSize,lpszRegFindPositionKeyValueName);
  2244. // Also save the last used server name in the registry for the next
  2245. // session
  2246. {
  2247. LPTSTR lpBuf = NULL;
  2248. GetSelectedText(GetDlgItem(hWnd, IDC_FIND_COMBO_LIST), &lpBuf);
  2249. if(lpBuf)
  2250. {
  2251. HKEY hKeyRoot = (lpIAB && lpIAB->hKeyCurrentUser) ? lpIAB->hKeyCurrentUser : HKEY_CURRENT_USER;
  2252. RegSetValue(hKeyRoot, szKeyLastFindServer, REG_SZ, lpBuf, lstrlen(lpBuf));
  2253. LocalFree(lpBuf);
  2254. }
  2255. }
  2256. return;
  2257. }
  2258. /*************************************************************************
  2259. //$$
  2260. // HrInitServerListLV - Initializes the list view that displays the list
  2261. // of servers ...
  2262. //
  2263. // hWndLV - handle of list view
  2264. //
  2265. **************************************************************************/
  2266. /****
  2267. HRESULT HrInitServerListLV(HWND hWndLV)
  2268. {
  2269. HRESULT hr = hrSuccess;
  2270. LV_COLUMN lvC; // list view column structure
  2271. HIMAGELIST hSmall=NULL;
  2272. DWORD dwLVStyle;
  2273. ULONG nCols=0;
  2274. ULONG index=0;
  2275. if (!hWndLV)
  2276. {
  2277. hr = MAPI_E_INVALID_PARAMETER;
  2278. goto out;
  2279. }
  2280. ListView_SetExtendedListViewStyle(hWndLV, LVS_EX_FULLROWSELECT);
  2281. dwLVStyle = GetWindowLong(hWndLV,GWL_STYLE);
  2282. if(dwLVStyle & LVS_EDITLABELS)
  2283. SetWindowLong(hWndLV,GWL_STYLE,(dwLVStyle & ~LVS_EDITLABELS));
  2284. hSmall = gpfnImageList_LoadImage( hinstMapiX,
  2285. MAKEINTRESOURCE(IDB_BITMAP_LARGE),
  2286. L_BITMAP_WIDTH,
  2287. 0,
  2288. RGB_TRANSPARENT,
  2289. IMAGE_BITMAP,
  2290. 0);
  2291. ListView_SetImageList (hWndLV, hSmall, LVSIL_SMALL);
  2292. lvC.mask = LVCF_FMT | LVCF_WIDTH;
  2293. lvC.fmt = LVCFMT_LEFT; // left-align column
  2294. {
  2295. RECT rc;
  2296. GetWindowRect(hWndLV, &rc);
  2297. lvC.cx = rc.right - rc.left - L_BITMAP_WIDTH - 10;
  2298. }
  2299. lvC.pszText = NULL;
  2300. lvC.iSubItem = 0;
  2301. if (ListView_InsertColumn (hWndLV, 0, &lvC) == -1)
  2302. {
  2303. DebugPrintError(( TEXT("ListView_InsertColumn Failed\n")));
  2304. hr = E_FAIL;
  2305. goto out;
  2306. }
  2307. out:
  2308. return hr;
  2309. }
  2310. /***/
  2311. //$$
  2312. //*------------------------------------------------------------------------
  2313. //| FreeLVItemParam: Frees the LPSBinary structure associated with each element
  2314. //| of the list view containing a container list
  2315. //|
  2316. //| hWndLV - Handle of List View whose data we are freeing
  2317. //|
  2318. //*------------------------------------------------------------------------
  2319. void FreeLVItemParam(HWND hWndCombo)//hWndLV)
  2320. {
  2321. int i = 0;
  2322. int nCount;
  2323. if(!hWndCombo)
  2324. return;
  2325. nCount = (int) SendMessage(hWndCombo, CB_GETCOUNT, 0, 0);
  2326. // Each Combo item has a entryid associated with it which we need to free up
  2327. for(i=0;i<nCount;i++)
  2328. {
  2329. LPSERVERDAT lpSD = NULL;
  2330. lpSD = (LPSERVERDAT) SendMessage(hWndCombo, CB_GETITEMDATA, (WPARAM) i, 0);
  2331. if(lpSD != NULL)
  2332. {
  2333. if(lpSD->himl)
  2334. gpfnImageList_Destroy(lpSD->himl);
  2335. LocalFreeAndNull((LPVOID *) (&(lpSD->SB.lpb)));
  2336. LocalFreeAndNull(&lpSD);
  2337. }
  2338. }
  2339. SendMessage(hWndCombo, CB_RESETCONTENT, 0, 0);
  2340. return;
  2341. }
  2342. //$$
  2343. //*------------------------------------------------------------------------
  2344. //| PopulateContainerList: Enumerates potential container names and fills
  2345. //| combo ...
  2346. //|
  2347. //| lpIAB - AdrBook Object
  2348. //| hWndCombo - Handle of Combo we are populating
  2349. //| lpszSelection - NULL or some value - if exists, this value is set as the
  2350. //| combo selection otherwise the local store is the default
  2351. //| selection
  2352. //| lptszPreferredSelection - NULL or some value - if exists then set as the
  2353. //| combo selection, otherwise the above
  2354. //| lpszSelection or local store is the default.
  2355. //|
  2356. //*------------------------------------------------------------------------
  2357. HRESULT PopulateContainerList(
  2358. LPADRBOOK lpAdrBook,
  2359. HWND hWndCombo,
  2360. LPTSTR lpszSelection,
  2361. LPTSTR lptszPreferredSelection)
  2362. {
  2363. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  2364. HRESULT hr = hrSuccess;
  2365. ULONG ulObjectType = 0;
  2366. LPROOT lpRoot = NULL;
  2367. LPMAPITABLE lpContentsTable = NULL;
  2368. LPSRowSet lpSRowSet = NULL;
  2369. ULONG i=0,j=0;
  2370. TCHAR szPref[MAX_PATH];
  2371. int nPos = 0;
  2372. int nStart = 1; // pos we start sorting at ... always after the TEXT("WAB") item
  2373. BOOL bAddedPref = FALSE;
  2374. LPIAB lpIAB = (LPIAB)lpAdrBook;
  2375. BOOL bFoundSelection = FALSE;
  2376. BOOL bFoundPreferredSelection = FALSE;
  2377. if( !lpAdrBook ||
  2378. !hWndCombo)
  2379. {
  2380. hr = MAPI_E_INVALID_PARAMETER;
  2381. DebugPrintError(( TEXT("Invalid Params\n")));
  2382. goto out;
  2383. }
  2384. // if running against outlook, there can be more than 1 contact folder and
  2385. // we need to push them all to the top of the list .. so we will really start
  2386. // adding generic stuff after the colkci position
  2387. //
  2388. if (pt_bIsWABOpenExSession)
  2389. {
  2390. nStart = lpIAB->lpPropertyStore->colkci;
  2391. }
  2392. *szPref = '\0';
  2393. LoadString(hinstMapiX, idsPreferedPartnerCode, szPref, ARRAYSIZE(szPref));
  2394. hr = lpAdrBook->lpVtbl->OpenEntry( lpAdrBook,
  2395. 0,
  2396. NULL,
  2397. NULL,
  2398. 0,
  2399. &ulObjectType,
  2400. (LPUNKNOWN *) &lpRoot );
  2401. if (HR_FAILED(hr))
  2402. {
  2403. DebugPrintError(( TEXT("OpenEntry Failed: %x\n"),hr));
  2404. goto out;
  2405. }
  2406. // if this is a profile aware session, only put the All Contacts item in the drop down list
  2407. // unless it's an outlook session in which case don't do anything
  2408. {
  2409. ULONG ulFlags = MAPI_UNICODE;
  2410. if(bIsWABSessionProfileAware(lpIAB))
  2411. ulFlags |= WAB_NO_PROFILE_CONTAINERS;
  2412. hr = lpRoot->lpVtbl->GetContentsTable( lpRoot,
  2413. ulFlags,
  2414. &lpContentsTable);
  2415. }
  2416. if (HR_FAILED(hr))
  2417. {
  2418. DebugPrintError(( TEXT("GetContentsTable Failed: %x\n"),hr));
  2419. goto out;
  2420. }
  2421. hr = HrQueryAllRows(lpContentsTable,
  2422. NULL, NULL, NULL, 0,
  2423. &lpSRowSet);
  2424. if (HR_FAILED(hr))
  2425. {
  2426. DebugPrintError(( TEXT("HrQueryAllRows Failed: %x\n"),hr));
  2427. goto out;
  2428. }
  2429. for(i=0;i<lpSRowSet->cRows;i++)
  2430. {
  2431. LPTSTR lpszDisplayName = NULL;
  2432. LPSERVERDAT lpSD = LocalAlloc(LMEM_ZEROINIT, sizeof(SERVERDAT));
  2433. if(!lpSD)
  2434. {
  2435. DebugPrintError(( TEXT("LocalAlloc failed to allocate memory\n")));
  2436. goto out;
  2437. }
  2438. lpSD->himl = NULL;
  2439. for(j=0;j<lpSRowSet->aRow[i].cValues;j++)
  2440. {
  2441. LPSPropValue lpPropArray = lpSRowSet->aRow[i].lpProps;
  2442. switch(lpPropArray[j].ulPropTag)
  2443. {
  2444. case PR_DISPLAY_NAME:
  2445. lpszDisplayName = lpPropArray[j].Value.LPSZ;
  2446. break;
  2447. case PR_ENTRYID:
  2448. lpSD->SB.cb = lpPropArray[j].Value.bin.cb;
  2449. if(lpSD->SB.cb > 0)
  2450. {
  2451. lpSD->SB.lpb = LocalAlloc(LMEM_ZEROINIT, lpSD->SB.cb);
  2452. if(!lpSD->SB.lpb)
  2453. {
  2454. DebugPrintError(( TEXT("LocalAlloc failed to allocate memory\n")));
  2455. goto out;
  2456. }
  2457. CopyMemory(lpSD->SB.lpb, lpPropArray[j].Value.bin.lpb,lpSD->SB.cb);
  2458. }
  2459. break;
  2460. }
  2461. }
  2462. nPos = ComboAddItem( hWndCombo,
  2463. lpszDisplayName,
  2464. (LPARAM) lpSD,
  2465. szPref,
  2466. &nStart, &bAddedPref);
  2467. if(!bFoundPreferredSelection && lpszSelection && !lstrcmpi(lpszDisplayName, lpszSelection))
  2468. {
  2469. bFoundSelection = TRUE;
  2470. SendMessage(hWndCombo, CB_SETCURSEL, (WPARAM)nPos, 0);
  2471. SetWindowText(hWndCombo, lpszSelection);
  2472. }
  2473. if (lptszPreferredSelection && !lstrcmpi(lpszDisplayName, lptszPreferredSelection))
  2474. {
  2475. bFoundPreferredSelection = TRUE;
  2476. SendMessage(hWndCombo, CB_SETCURSEL, (WPARAM)nPos, 0);
  2477. SetWindowText(hWndCombo, lptszPreferredSelection);
  2478. }
  2479. }
  2480. out:
  2481. if (!bFoundSelection && !bFoundPreferredSelection)
  2482. SendMessage(hWndCombo, CB_SETCURSEL, 0, 0);
  2483. if (lpSRowSet)
  2484. FreeProws(lpSRowSet);
  2485. if(lpContentsTable)
  2486. lpContentsTable->lpVtbl->Release(lpContentsTable);
  2487. if(lpRoot)
  2488. lpRoot->lpVtbl->Release(lpRoot);
  2489. return hr;
  2490. }
  2491. //$$/////////////////////////////////////////////////////////////////////////////////
  2492. //
  2493. // CurrentContainerIsPAB - Returns TRUE if the current viewed container is the PAB
  2494. //
  2495. // hWndLV - List Containing the list of containers.
  2496. //
  2497. ////////////////////////////////////////////////////////////////////////////////////////
  2498. int CurrentContainerIsPAB(HWND hWndCombo)
  2499. {
  2500. HRESULT hr = hrSuccess;
  2501. ULONG cbContainerEID = 0;
  2502. LPENTRYID lpContainerEID = NULL;
  2503. BYTE bType = 0;
  2504. GetCurrentContainerEID(hWndCombo,
  2505. &cbContainerEID,
  2506. &lpContainerEID);
  2507. //
  2508. // Check if this entryid is a Local WAB store
  2509. //
  2510. if(!cbContainerEID && !lpContainerEID)
  2511. return IS_PAB;
  2512. bType = IsWABEntryID(cbContainerEID, lpContainerEID, NULL, NULL, NULL, NULL, NULL);
  2513. if(bType == WAB_LDAP_CONTAINER)
  2514. return IS_LDAP;
  2515. if(bType == WAB_PAB || bType == WAB_PABSHARED)
  2516. return IS_PAB;
  2517. // for now we'll figure anything else is a Outlook container
  2518. return IS_OLK;
  2519. }
  2520. //$$
  2521. /******************************************************************************
  2522. //
  2523. // HrSearchAndGetLDAPContents - Gets and fills the current list view with contents from
  2524. // an LDAP server.
  2525. //
  2526. // hWndCombo - Handle to TEXT("ShowNames") combo (in case we need to update it
  2527. // hWndList - Handle to List View which we will populate
  2528. // lpIAB - Handle to Address Bok object
  2529. // SortInfo - Current Sort State
  2530. // lppContentsList - linked list in which we will store info about entries
  2531. // lpAdvFilter - an advanced search filter that is used for advanced searches
  2532. //
  2533. /******************************************************************************/
  2534. HRESULT HrSearchAndGetLDAPContents( LDAP_SEARCH_PARAMS LDAPsp,
  2535. LPTSTR lpAdvFilter,
  2536. HWND hWndCombo,
  2537. LPADRBOOK lpAdrBook,
  2538. SORT_INFO SortInfo,
  2539. LPRECIPIENT_INFO * lppContentsList)
  2540. {
  2541. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  2542. HRESULT hr = hrSuccess;
  2543. SCODE sc = ERROR_SUCCESS;
  2544. ULONG cbContainerEID = 0;
  2545. LPENTRYID lpContainerEID = NULL;
  2546. TCHAR szBuf[MAX_UI_STR];
  2547. ULONG ulCurSel = 0;
  2548. SRestriction SRes = {0};
  2549. LPSRestriction lpPropRes = NULL;
  2550. ULONG ulcPropCount = 0;
  2551. ULONG i = 0;
  2552. HCURSOR hOldCursor = NULL;
  2553. BOOL bKeepSearching = TRUE;
  2554. //while(bKeepSearching)
  2555. {
  2556. hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  2557. //
  2558. // Then we get the container entry id for thie container
  2559. //
  2560. GetCurrentContainerEID( hWndCombo,
  2561. &cbContainerEID,
  2562. &lpContainerEID);
  2563. //
  2564. // Now we have the search dialog data .. we need to create a restriction from it which
  2565. // we can use with the LDAP contents table..
  2566. //
  2567. if(!lpAdvFilter)
  2568. {
  2569. if(HR_FAILED(HrGetLDAPSearchRestriction(LDAPsp, &SRes)))
  2570. goto out;
  2571. lpPropRes = SRes.res.resAnd.lpRes;
  2572. }
  2573. hr = HrGetLDAPContentsList(
  2574. lpAdrBook,
  2575. cbContainerEID,
  2576. lpContainerEID,
  2577. SortInfo,
  2578. &SRes,
  2579. lpAdvFilter,
  2580. NULL,
  2581. 0,
  2582. lppContentsList);
  2583. if((HR_FAILED(hr)) && (MAPI_E_USER_CANCEL != hr))
  2584. {
  2585. int ids;
  2586. UINT flags = MB_OK | MB_ICONEXCLAMATION;
  2587. switch(hr)
  2588. {
  2589. case MAPI_E_UNABLE_TO_COMPLETE:
  2590. ids = idsLDAPSearchTimeExceeded;
  2591. break;
  2592. case MAPI_E_AMBIGUOUS_RECIP:
  2593. ids = idsLDAPAmbiguousRecip;
  2594. break;
  2595. case MAPI_E_NOT_FOUND:
  2596. ids = idsLDAPSearchNoResults;
  2597. break;
  2598. case MAPI_E_NO_ACCESS:
  2599. ids = idsLDAPAccessDenied;
  2600. break;
  2601. case MAPI_E_TIMEOUT:
  2602. ids = idsLDAPSearchTimedOut;
  2603. break;
  2604. case MAPI_E_NETWORK_ERROR:
  2605. ids = idsLDAPCouldNotFindServer;
  2606. break;
  2607. default:
  2608. ids = idsLDAPErrorOccured;
  2609. DebugPrintError(( TEXT("HrGetLDAPContentsList failed:%x\n"),hr));
  2610. break;
  2611. }
  2612. ShowMessageBox( GetParent(hWndCombo),ids, flags);
  2613. goto out;
  2614. }
  2615. else
  2616. {
  2617. if(hr == MAPI_W_PARTIAL_COMPLETION)
  2618. ShowMessageBox( GetParent(hWndCombo),
  2619. idsLDAPPartialResults, MB_OK | MB_ICONINFORMATION);
  2620. }
  2621. } // while(bKeepSearching)
  2622. out:
  2623. if(lpPropRes)
  2624. MAPIFreeBuffer(lpPropRes);
  2625. if(hOldCursor)
  2626. SetCursor(hOldCursor);
  2627. return(hr);
  2628. }
  2629. //$$
  2630. //*------------------------------------------------------------------------
  2631. //| GetCurrentContainerEID: Gets EntryID of Current Container - takes a handle
  2632. //| to a populated combo, gets the current selection, and then
  2633. //| gets the ItemData (EntryID) for that current selection.
  2634. //|
  2635. //| hWndLV - Handle of a ListView containing the container list
  2636. //| lpcbContEID,lppContEID - returned Container Entry ID
  2637. //|
  2638. //| **NOTE** lpContEID is not allocated - its just a pointer and should not be freed
  2639. //|
  2640. //*------------------------------------------------------------------------
  2641. void GetCurrentContainerEID(HWND hWndCombo, //hWndLV,
  2642. LPULONG lpcbContEID,
  2643. LPENTRYID * lppContEID)
  2644. {
  2645. LPSERVERDAT lpSD = NULL;
  2646. int iItemIndex = 0;
  2647. if(!lpcbContEID || !lppContEID)
  2648. goto out;
  2649. *lpcbContEID = 0;
  2650. *lppContEID = NULL;
  2651. iItemIndex = (int) SendMessage(hWndCombo, CB_GETCURSEL, 0, 0);
  2652. if(iItemIndex == CB_ERR)
  2653. goto out;
  2654. lpSD = (LPSERVERDAT) SendMessage(hWndCombo, CB_GETITEMDATA, (WPARAM) iItemIndex, 0);
  2655. if(!lpSD)
  2656. goto out;
  2657. *lpcbContEID = lpSD->SB.cb;
  2658. *lppContEID = (LPENTRYID) lpSD->SB.lpb;
  2659. out:
  2660. return;
  2661. }
  2662. //$$////////////////////////////////////////////////////////////////////////////////////////
  2663. //
  2664. // ComboAddItem Generic function for adding items to list view
  2665. //
  2666. // hWndLV - HWND of List View
  2667. // lpszItemText - ItemText
  2668. // lParam - LPARAM (can be NULL)
  2669. // lpnStart - position at which to start adding generic servers .. in the case where there
  2670. // is more than one server at the top of the list
  2671. //
  2672. ////////////////////////////////////////////////////////////////////////////////////////////
  2673. int ComboAddItem( HWND hWndCombo, //hWndLV,
  2674. LPTSTR lpszItemText,
  2675. LPARAM lParam,
  2676. LPTSTR szPref,
  2677. int * lpnStart, BOOL * lpbAddedPref)
  2678. {
  2679. LPTSTR lp = NULL;
  2680. int nPos = 0, nStart = 1;
  2681. int nCount = (int) SendMessage(hWndCombo, CB_GETCOUNT, 0, 0);
  2682. LDAPSERVERPARAMS Params = {0};
  2683. if(lpnStart && *lpnStart)
  2684. nStart = *lpnStart;
  2685. GetLDAPServerParams(lpszItemText, &Params);
  2686. if( Params.dwIsNTDS == LDAP_NTDS_IS) // NTDS accounts need to come upfront after the Address Book
  2687. {
  2688. // if the prefered accounts have already been added at nStart .. only add the NT accounts at
  2689. // nStart - 1
  2690. nPos = (int) SendMessage(hWndCombo, CB_INSERTSTRING,
  2691. (WPARAM) ((lpbAddedPref && *lpbAddedPref == TRUE) ? nStart - 1 : nStart),
  2692. (LPARAM) lpszItemText);
  2693. if(lpnStart)
  2694. (*lpnStart)++;
  2695. }
  2696. else
  2697. if( ( szPref && lstrlen(szPref) && lpszItemText && lstrlen(lpszItemText) && SubstringSearch(lpszItemText, szPref)) )
  2698. {
  2699. nPos = (int) SendMessage(hWndCombo, CB_INSERTSTRING, (WPARAM) nStart, (LPARAM) lpszItemText); // Prefered partner goes in after contact folders at top of the list
  2700. if(lpnStart)
  2701. (*lpnStart)++;
  2702. if(lpbAddedPref)
  2703. *lpbAddedPref = TRUE;
  2704. }
  2705. else
  2706. {
  2707. // Once we add the pref server, we only need to compare from after that item
  2708. if(nCount >= nStart)
  2709. {
  2710. // need to start adding alphabetically
  2711. // We cant set this list to a sorted state because we always want the Address Book first
  2712. // and then the prefered partner second
  2713. int i,nLen;
  2714. for(i=nStart; i< nCount; i++)
  2715. {
  2716. // get the current string in the combo
  2717. nLen = (int) SendMessage(hWndCombo, CB_GETLBTEXTLEN, (WPARAM) i, 0);
  2718. if (nLen && (CB_ERR != nLen))
  2719. {
  2720. if(lp)
  2721. {
  2722. LocalFree(lp);
  2723. lp = NULL;
  2724. }
  2725. lp = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)*(nLen+1));
  2726. if(lp)
  2727. {
  2728. SendMessage(hWndCombo, CB_GETLBTEXT, (WPARAM) i, (LPARAM)lp);
  2729. if(lstrlen(lp) && lstrcmpi(lp, lpszItemText) >= 0)
  2730. {
  2731. nPos = i;
  2732. break;
  2733. }
  2734. }
  2735. }
  2736. }
  2737. }
  2738. if(nPos)
  2739. {
  2740. // we have a valid position to add the string to
  2741. nPos = (int) SendMessage(hWndCombo, CB_INSERTSTRING, (WPARAM) nPos, (LPARAM) lpszItemText); // Prefered partner goes in after Address book at top of the list
  2742. }
  2743. else
  2744. {
  2745. // just tag it to the end
  2746. nPos = (int) SendMessage(hWndCombo, CB_ADDSTRING, 0, (LPARAM) lpszItemText);
  2747. }
  2748. }
  2749. SendMessage(hWndCombo, CB_SETITEMDATA, (WPARAM) nPos, lParam);
  2750. if(lp)
  2751. LocalFree(lp);
  2752. FreeLDAPServerParams(Params);
  2753. return nPos;
  2754. }