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.

5593 lines
194 KiB

  1. ////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. //
  4. // UI_ABOOK.C - contains code for the Browse mode Overlapped Window address book view
  5. //
  6. // Developers: VikramM 5/96
  7. //
  8. ////////////////////////////////////////////////////////////////////////////////////////
  9. #include "_apipch.h"
  10. #include "hotsync.h"
  11. #include "htmlhelp.h"
  12. #include <mirror.h>
  13. extern HINSTANCE ghCommCtrlDLLInst;
  14. extern const LPTSTR lpszRegPositionKeyValueName;
  15. extern BOOL bIsPasteData();
  16. extern HRESULT HrPasteData(LPBWI lpbwi);
  17. extern void AddFolderListToMenu(HMENU hMenu, LPIAB lpIAB);
  18. const static LPTSTR szWABMigRegPathKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wabmig.exe");
  19. const static LPTSTR szWABExeRegPathKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wab.exe");
  20. const LPTSTR szWABMIG = TEXT("wabmig.exe");
  21. const LPTSTR szWABExe = TEXT("wab.exe");
  22. const TCHAR szEXPORT[] = TEXT("/export");
  23. const TCHAR szIMPORT[] = TEXT("/import");
  24. const TCHAR szEXPORTwProfileParam[]=TEXT("/export+/pid:%s+/file:%s");
  25. const TCHAR szIMPORTwProfileParam[]=TEXT("/import+/pid:%s+/file:%s");
  26. // This struct helps in identifying contact folders and groups and in navigating
  27. // around them
  28. //
  29. void FillTreeView(LPBWI lpbwi, HWND hWndTV, LPSBinary lpsbSelection);
  30. void UpdateTVGroupSelection(HWND hWndTV, LPSBinary lpsbSelectEID);
  31. void GetCurrentSelectionEID(LPBWI lpbwi, HWND hWndTV, LPSBinary * lppsbEID, ULONG * lpulObjectType, BOOL bTopMost);
  32. void ClearTreeViewItems(HWND hWndTV);
  33. void UpdateLV(LPBWI lpbwi);
  34. void UpdateListViewContents(LPBWI lpbwi, LPSBinary lpsbEID, ULONG ulObjectType);
  35. void ViewCurrentGroupProperties(LPBWI lpbwi, LPFILETIME lpftLast);
  36. BOOL bIsFocusOnTV(LPBWI lpbwi);
  37. BOOL bIsSelectedTVContainer(LPBWI lpbwi);
  38. BOOL SplitterHitTest(HWND hWndT, LPARAM lParam);
  39. void DragSplitterBar(LPBWI lpbwi, HWND hwnd, HWND hWndT, LPARAM lParam);
  40. HRESULT FillListFromGroup(LPADRBOOK lpIAB, ULONG cbGroupEntryID, LPENTRYID lpGroupEntryID, LPTSTR lpszName, ULONG cchName, LPRECIPIENT_INFO * lppList);
  41. extern LPIMAGELIST_DESTROY gpfnImageList_Destroy;
  42. // extern LPIMAGELIST_LOADIMAGE gpfnImageList_LoadImage;
  43. extern LPIMAGELIST_LOADIMAGE_A gpfnImageList_LoadImageA;
  44. extern LPIMAGELIST_LOADIMAGE_W gpfnImageList_LoadImageW;
  45. extern ULONG GetToolbarButtonWidth();
  46. void RemoveCurrentGroup(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast);
  47. HRESULT RemoveCurrentFolder(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast);
  48. void RemoveSelectedItemsFromCurrentGroup(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast, BOOL bRemoveFromWAB);
  49. void RemoveSelectedItemsFromListView(HWND hWndLV, LPRECIPIENT_INFO *lppList);
  50. LRESULT ProcessTreeViewMessages(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPFILETIME lpftLast);
  51. #ifdef COLSEL_MENU
  52. BOOL UpdateOptionalColumns( LPBWI lpbwi, ULONG iColumn );
  53. #endif // COLSEL_MENU
  54. // Initial Window Size
  55. #define INIT_WINDOW_W 500
  56. #define INIT_WINDOW_H 375
  57. // Minimum Window Size - presently constrained
  58. #define MIN_WINDOW_W 300
  59. #define MIN_WINDOW_H 200
  60. BOOL fOleInit = FALSE;
  61. //
  62. // Some IDs for the Button Bar
  63. //
  64. // Address Book Window Class Name
  65. LPTSTR g_szClass = TEXT("WABBrowseView");
  66. // Function ProtoTypes
  67. LRESULT CALLBACK AddressBookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
  68. void CreateAddressBookChildren(LPBWI lpbwi, HWND hWnd);
  69. void ResizeAddressBookChildren(LPBWI lpbwi, HWND hWndParent);
  70. HWND CreateListViewAddrBook (HWND hWndParent);
  71. void InitChildren(LPBWI lpbwi, HWND hWnd);
  72. void SetListViewStyle(LPBWI lpbwi, int MenuID);
  73. void CleanUpGlobals(LPBWI lpbwi);
  74. HRESULT HrFolderProperties(HWND hWndParent, LPIAB lpIAB, LPSBinary lpsbEID, LPWABFOLDER lpParentFolder, LPSBinary lpsbNew);
  75. //void TabToNextItem();
  76. LRESULT ProcessListViewMessages(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  77. LRESULT EnforceMinSize(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  78. LRESULT CALLBACK SubClassedProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
  79. void RefreshListView(LPBWI lpbwi, LPFILETIME lpftLast);
  80. STDAPI_(BOOL) FindABWindowProc( HWND hWndToLookAt, LPARAM lParam);
  81. void UpdateSortMenus(LPBWI lpbwi, HWND hWnd);
  82. void UpdateToolbarAndMenu(LPBWI lpbwi);
  83. void UpdatePrintMenu(HWND hWnd);
  84. void UpdateOutlookMenus(HWND hWnd);
  85. void UpdateCustomColumnMenuText(HWND hWnd);
  86. void UpdateViewFoldersMenu(LPBWI lpbwi, HWND hWnd);
  87. void UpdateSwitchUsersMenu(HWND hWnd, LPIAB lpIAB);
  88. //LPFNABSDI lpfnAccelerateMessages;
  89. BOOL STDMETHODCALLTYPE fnAccelerateMessages(ULONG_PTR ulUIParam, LPVOID lpvmsg);
  90. void SetPreviousSessionPosition(LPBWI lpbwi, HWND hWnd, HWND hWndLV, HWND hWndTB, HWND hWndSB);
  91. void SaveCurrentPosition(LPBWI lpbwi, HWND hWnd, HWND hWndLV, HWND hWndTB, HWND hWndSB);
  92. void Handle_WM_MENSELECT (LPBWI lpbwi, UINT message, WPARAM uParam, LPARAM lParam );
  93. void Handle_WM_INITMENUPOPUP(HWND hWnd, LPBWI lpbwi, UINT message, WPARAM uParam, LPARAM lParam );
  94. void UpdateTooltipTextBuffer(LPBWI lpbwi, int nItem);
  95. void InitMultiLineToolTip(LPBWI lpbwi, HWND hWndParent);
  96. void FillTooltipInfo(LPBWI lpbwi, LPTOOLINFO lpti);
  97. int HitTestLVSelectedItem(LPBWI lpbwi);
  98. BOOL bCheckIfOnlyGroupsSelected(HWND hWndLV);
  99. void DestroyImageLists(LPBWI lpbwi);
  100. #define WAB_TOOLTIP_TIMER_ID 888
  101. #define WAB_TOOLTIP_TIMER_TIMEOUT 750 // milliseconds
  102. HRESULT HrExportWAB(HWND hWnd, LPBWI lpbwi);
  103. void HrShowOptionsDlg(HWND hWndParent);
  104. //$$ extern void UIOLEUninit();
  105. void UIOLEUninit()
  106. {
  107. if(fOleInit)
  108. {
  109. OleUninitialize();
  110. fOleInit = FALSE;
  111. }
  112. }
  113. void UIOLEInit()
  114. {
  115. if(!fOleInit)
  116. {
  117. OleInitialize(NULL);
  118. fOleInit = TRUE;
  119. }
  120. }
  121. //$$
  122. //
  123. // LocalFreeSBinary - frees a locally alloced SBinary struct
  124. //
  125. //
  126. void LocalFreeSBinary(LPSBinary lpsb)
  127. {
  128. if(lpsb)
  129. {
  130. if(lpsb->lpb)
  131. LocalFree(lpsb->lpb);
  132. LocalFree(lpsb);
  133. }
  134. }
  135. //$$
  136. /*----------------------------------------------------------------------*/
  137. //
  138. // RunWABApp - runs the import-export tool based on the registered path
  139. // if regesitered path is not found, shell execs ...
  140. //
  141. /*----------------------------------------------------------------------*/
  142. void RunWABApp(HWND hWnd, LPTSTR szKey, LPTSTR szExeName, LPTSTR szParam)
  143. {
  144. TCHAR szPath[MAX_PATH];
  145. TCHAR szPathExpand[MAX_PATH];
  146. DWORD dwType = 0;
  147. ULONG cbData = CharSizeOf(szPath);
  148. HKEY hKey = NULL;
  149. LONG lRes = 0;
  150. *szPath = '\0';
  151. *szPathExpand = '\0';
  152. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hKey))
  153. lRes = RegQueryValueEx( hKey, TEXT(""), NULL, &dwType, (LPBYTE) szPath, &cbData);
  154. if (REG_EXPAND_SZ == dwType)
  155. {
  156. ExpandEnvironmentStrings(szPath, szPathExpand, CharSizeOf(szPathExpand));
  157. StrCpyN(szPath, szPathExpand, ARRAYSIZE(szPath));
  158. }
  159. if(hKey) RegCloseKey(hKey);
  160. if(!lstrlen(szPath))
  161. StrCpyN(szPath, szExeName, ARRAYSIZE(szPath));
  162. ShellExecute(hWnd, TEXT("open"), szPath, szParam, NULL, SW_SHOWNORMAL);
  163. }
  164. //$$
  165. /*----------------------------------------------------------------------*/
  166. //
  167. // StatusBarMessage - puts a message in the status bar
  168. //
  169. /*----------------------------------------------------------------------*/
  170. void StatusBarMessage(LPBWI lpbwi, LPTSTR lpsz)
  171. {
  172. SetWindowText(bwi_hWndSB, lpsz);
  173. UpdateWindow(bwi_hWndSB);
  174. return;
  175. }
  176. //$$
  177. /*----------------------------------------------------------------------*/
  178. //
  179. // ShowLVCountinStatusBar - puts a message in the status bar
  180. //
  181. /*----------------------------------------------------------------------*/
  182. void ShowLVCountinStatusBar(LPBWI lpbwi)
  183. {
  184. TCHAR sz[MAX_UI_STR];
  185. TCHAR szString[MAX_UI_STR];
  186. LoadString(hinstMapiX, idsStatusBarCount, szString, ARRAYSIZE(szString));
  187. wnsprintf(sz, ARRAYSIZE(sz), szString, ListView_GetItemCount(bwi_hWndListAB));
  188. StatusBarMessage(lpbwi, sz);
  189. return;
  190. }
  191. //$$*------------------------------------------------------------------------
  192. //| IAddrBook::Advise::OnNotify handler
  193. //|
  194. //*------------------------------------------------------------------------
  195. ULONG AdviseOnNotify(LPVOID lpvContext, ULONG cNotif, LPNOTIFICATION lpNotif)
  196. {
  197. LPBWI lpbwi = (LPBWI) lpvContext;
  198. DebugTrace( TEXT("=== AdviseOnNotify ===\n"));
  199. if(bwi_bDeferNotification)
  200. {
  201. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  202. if(!pt_bIsWABOpenExSession)
  203. {
  204. DebugTrace( TEXT("=== Advise Defered ===\n"));
  205. bwi_bDeferNotification = FALSE;
  206. return S_OK;
  207. }
  208. }
  209. if(!bwi_bDontRefreshLV)
  210. {
  211. DebugTrace( TEXT("=== Calling RefreshListView ===\n"));
  212. HrGetWABProfiles(bwi_lpIAB);
  213. RefreshListView(lpbwi, NULL);
  214. }
  215. return S_OK;
  216. }
  217. /*
  218. -
  219. - GetSelectedUserFolder - returns a pointer to the selected User Folder if any
  220. * If the selection is on a sub-folder, gets the parent User folder for that folder
  221. *
  222. */
  223. LPWABFOLDER GetSelectedUserFolder(LPBWI lpbwi)
  224. {
  225. ULONG ulObjectType = 0;
  226. LPSBinary lpsbEID = NULL;
  227. LPWABFOLDER lpFolder = NULL;
  228. //if(bIsSelectedTVContainer(lpbwi))
  229. {
  230. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjectType, TRUE);
  231. if(bIsWABSessionProfileAware(bwi_lpIAB))
  232. lpFolder = FindWABFolder(bwi_lpIAB, lpsbEID, NULL, NULL);
  233. }
  234. LocalFreeSBinary(lpsbEID);
  235. return (lpFolder && lpFolder->lpProfileID) ? lpFolder : NULL;
  236. }
  237. /*
  238. - RemoveUpdateSelection - Updates the selected TV Item when a deletion is done
  239. -
  240. *
  241. */
  242. void RemoveUpdateSelection(LPBWI lpbwi)
  243. {
  244. HTREEITEM hItem = bwi_hti ? bwi_hti : TreeView_GetSelection(bwi_hWndTV);
  245. if(TreeView_GetParent(bwi_hWndTV, hItem))
  246. hItem = TreeView_GetParent(bwi_hWndTV, hItem);
  247. else
  248. hItem = TreeView_GetNextSibling(bwi_hWndTV, hItem);
  249. if(!hItem)
  250. hItem = TreeView_GetRoot(bwi_hWndTV);
  251. TreeView_SelectItem(bwi_hWndTV, hItem);
  252. bwi_hti = NULL;
  253. }
  254. /*
  255. - CreateWindowTitle - if we don't have a passed in caption, create a title
  256. - If there is a current user, add the user's name to the title
  257. - Returns LocalAlloced stuff that needs to be freed
  258. -
  259. */
  260. LPTSTR CreateWindowTitle(LPIAB lpIAB)
  261. {
  262. LPTSTR lpTitle = NULL;
  263. TCHAR szTitle[MAX_PATH];
  264. LPTSTR lpsz = NULL;
  265. szTitle[0] = 0;
  266. if(bIsThereACurrentUser(lpIAB))
  267. {
  268. LPTSTR lpsz = lpIAB->szProfileName;
  269. LoadString(hinstMapiX, idsCaptionWithText, szTitle, ARRAYSIZE(szTitle));
  270. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING |FORMAT_MESSAGE_ARGUMENT_ARRAY,
  271. szTitle, 0, 0, (LPTSTR) &lpTitle, 0, (va_list *)&lpsz);
  272. }
  273. if(!lpTitle || !lstrlen(lpTitle))
  274. {
  275. DWORD cchSize = (lstrlen(szTitle)+1);
  276. LoadString(hinstMapiX, IDS_ADDRBK_CAPTION, szTitle, ARRAYSIZE(szTitle));
  277. if(lpTitle = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)*cchSize))
  278. StrCpyN(lpTitle, szTitle, cchSize);
  279. }
  280. return lpTitle;
  281. }
  282. //$$*------------------------------------------------------------------------
  283. //| Main call to create, activate address book overlapped-window
  284. //|
  285. //*------------------------------------------------------------------------
  286. HWND hCreateAddressBookWindow(LPADRBOOK lpAdrBook, HWND hWndParent, LPADRPARM lpAdrParms)
  287. {
  288. WNDCLASS wc;
  289. HWND hWnd = NULL;
  290. HMENU hMenu = NULL;
  291. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  292. LPBWI lpbwi = NULL;
  293. LPTSTR lpTitle = NULL;
  294. LPIAB lpIAB = (LPIAB)lpAdrBook;
  295. LPTSTR szCaption = (lpAdrParms->ulFlags & MAPI_UNICODE) ? // <note> assumes UNICODE defined
  296. (LPWSTR)lpAdrParms->lpszCaption :
  297. ConvertAtoW((LPSTR)lpAdrParms->lpszCaption);
  298. DWORD dwExStyle = WS_EX_NOPARENTNOTIFY | WS_EX_CONTROLPARENT;
  299. if(IS_BIDI_LOCALIZED_SYSTEM())
  300. {
  301. dwExStyle |= RTL_MIRRORED_WINDOW;
  302. }
  303. // if no common control, exit
  304. if (NULL == ghCommCtrlDLLInst)
  305. goto out;
  306. //
  307. // We want each thread to only have one address book window - so we do an
  308. // enum thread windows and look for our address book window
  309. // If we find it - we set focus to it - if we dont find it
  310. // we go ahead and create a new one for this thread ...
  311. //
  312. // Is this window we found related to my thread?
  313. EnumThreadWindows( GetCurrentThreadId(),
  314. FindABWindowProc,
  315. (LPARAM) &hWnd);
  316. if (IsWindow(hWnd))
  317. {
  318. //Perhaps the window was hidden .. show it
  319. //if (!IsWindowVisible(hWnd))
  320. // ShowWindow(hWnd,SW_NORMAL | SW_RESTORE);
  321. // SetWindowPos(hWnd, HWND_TOP,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
  322. if(IsWindowEnabled(hWnd))
  323. {
  324. SetActiveWindow(hWnd);
  325. // [PaulHi] 12/1/98 Raid #58527
  326. // The window may also be minimized.
  327. if ( IsIconic(hWnd) )
  328. ShowWindow(hWnd, SW_RESTORE);
  329. }
  330. else
  331. {
  332. HWND hWndC = GetLastActivePopup(hWnd);
  333. SetForegroundWindow(hWndC);
  334. }
  335. {
  336. // The previous instance of the Dialog might have had a different caption
  337. // so we update the caption
  338. LPBWI lpbwi = (LPBWI) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  339. if(szCaption)
  340. SetWindowText(hWnd,szCaption);
  341. if(lpbwi)
  342. {
  343. bwi_bDontRefreshLV = TRUE;
  344. RefreshListView(lpbwi,NULL);
  345. bwi_bDontRefreshLV = FALSE;
  346. }
  347. goto out;
  348. }
  349. }
  350. lpbwi = LocalAlloc(LMEM_ZEROINIT, sizeof(BWI));
  351. if(!lpbwi)
  352. {
  353. DebugTrace( TEXT("LocalAlloc failed\n"));
  354. goto out;
  355. }
  356. TrimSpaces(szCaption);
  357. lpTitle = (szCaption && lstrlen(szCaption)) ? szCaption : CreateWindowTitle(lpIAB);
  358. //
  359. // if we're here, we didnt succeed in finding or displaying the window
  360. //
  361. wc.style = 0L;
  362. wc.lpfnWndProc = AddressBookWndProc;
  363. wc.cbClsExtra = 0;
  364. wc.cbWndExtra = 0;
  365. wc.hInstance = hinstMapiXWAB; //NULL;
  366. wc.hIcon = LoadIcon(hinstMapiX,MAKEINTRESOURCE(IDI_ICON_ABOOK));;
  367. wc.hCursor = NULL;
  368. wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE+1);
  369. wc.lpszMenuName = NULL;
  370. wc.lpszClassName = g_szClass;
  371. if(!RegisterClass(&wc))
  372. {
  373. DebugPrintError(( TEXT("Attempt to register class failed: %d!\n"),GetLastError()));
  374. }
  375. // In windows95 there is no way of telling wether or not the WindowClass is
  376. // already registered. Hence we should go ahead and try to create the window
  377. // anyway making sure to trap the errors.
  378. // (The above is really needed for Athena - which runs on the system Explorer thread
  379. // and never really shuts down till the system is shut off - as a result the WndClass
  380. // registration above would continue to exist and RegisterClass would fail due
  381. // to TEXT("incorrect parameters") .. so we let this play on ..
  382. hMenu = LoadMenu(hinstMapiX, MAKEINTRESOURCE(IDR_MENU_AB));
  383. if (!hMenu)
  384. {
  385. DebugPrintError(( TEXT("LoadMenu failed: %x\n"),GetLastError()));
  386. goto out;
  387. }
  388. // Clean any garbage from previous sessions
  389. CleanUpGlobals(lpbwi);
  390. bwi_lpfnDismiss = NULL;
  391. bwi_lpvDismissContext = NULL;
  392. #ifndef WIN16 // WIN16FF : disable until ldap16.dll is available.
  393. if (bwi_lpAdrBook)
  394. {
  395. ReleasePropertyStore(bwi_lpIAB->lpPropertyStore);
  396. bwi_lpAdrBook->lpVtbl->Release(bwi_lpAdrBook);
  397. bwi_lpAdrBook = NULL;
  398. bwi_lpIAB = NULL;
  399. pt_lpIAB = NULL;
  400. }
  401. #else
  402. bwi_lpAdrBook = NULL;
  403. bwi_lpIAB = NULL;
  404. #endif // !WIN16
  405. // we need this pointer ....
  406. if (!bwi_lpAdrBook)
  407. {
  408. bwi_lpAdrBook = lpAdrBook;
  409. bwi_lpIAB = (LPIAB)bwi_lpAdrBook;
  410. UlAddRef(bwi_lpAdrBook);
  411. OpenAddRefPropertyStore(NULL, bwi_lpIAB->lpPropertyStore);
  412. pt_lpIAB = lpAdrBook;
  413. }
  414. HrAllocAdviseSink(&AdviseOnNotify, (LPVOID) lpbwi, &(bwi_lpAdviseSink));
  415. DebugTrace( TEXT("WAB Window Title is \"%s\"\n"),lpTitle?lpTitle:szEmpty);
  416. {
  417. if(IS_BIDI_LOCALIZED_SYSTEM())
  418. {
  419. dwExStyle |= RTL_MIRRORED_WINDOW;
  420. }
  421. hWnd = CreateWindowEx( dwExStyle,
  422. g_szClass,
  423. lpTitle ? lpTitle : szEmpty,
  424. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  425. CW_USEDEFAULT,
  426. CW_USEDEFAULT,
  427. INIT_WINDOW_W,
  428. INIT_WINDOW_H,
  429. NULL,
  430. hMenu,
  431. hinstMapiXWAB,
  432. (LPVOID)lpbwi);
  433. if (!hWnd)
  434. {
  435. DebugPrintError(( TEXT("Ok. CreateWindowEx failed. Ugh.\n")));
  436. if (bwi_lpAdrBook)
  437. {
  438. ReleasePropertyStore(bwi_lpIAB->lpPropertyStore);
  439. bwi_lpAdrBook->lpVtbl->Release(bwi_lpAdrBook);
  440. bwi_lpAdrBook = NULL;
  441. bwi_lpIAB = NULL;
  442. }
  443. goto out;
  444. }
  445. // Set up the menu markers on the sort menus ...
  446. SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, colDisplayName, &bwi_SortInfo, TRUE);
  447. SetColumnHeaderBmp(bwi_hWndListAB, bwi_SortInfo);
  448. // Update folders before redoing any other menu since removing folders
  449. // changes the order number of the other items
  450. UpdateSortMenus(lpbwi, hWnd);
  451. // **IMPORTANT**
  452. // These 4 calls are position based removals so order of calling them functions is important
  453. UpdateSwitchUsersMenu(hWnd, bwi_lpIAB);
  454. UpdateViewFoldersMenu(lpbwi, hWnd);
  455. UpdatePrintMenu(hWnd);
  456. UpdateOutlookMenus(hWnd);
  457. //////////////////////////////////////////////////////////////////////////////////
  458. UpdateCustomColumnMenuText(hWnd);
  459. IF_WIN32(ShowWindow(hWnd,SW_SHOWDEFAULT);)
  460. IF_WIN16(ShowWindow(hWnd,SW_SHOW);)
  461. if(lpAdrParms->ulFlags & DIALOG_SDI)
  462. {
  463. lpAdrParms->lpfnABSDI = &fnAccelerateMessages;
  464. bwi_lpfnDismiss = lpAdrParms->lpfnDismiss;
  465. bwi_lpvDismissContext = lpAdrParms->lpvDismissContext;
  466. }
  467. // load the accelrator table ...
  468. pt_hAccTable = LoadAccelerators(hinstMapiX, TEXT("WabUIAccel"));
  469. // repainting everything ...
  470. RedrawWindow( hWnd,
  471. NULL,
  472. NULL,
  473. RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
  474. //populate the window
  475. bwi_bDontRefreshLV = TRUE;
  476. RefreshListView(lpbwi,NULL);
  477. bwi_bDontRefreshLV = FALSE;
  478. }
  479. out:
  480. if(lpTitle != szCaption)
  481. LocalFree(lpTitle);
  482. if(szCaption != lpAdrParms->lpszCaption)
  483. LocalFreeAndNull(&szCaption);
  484. return (hWnd);
  485. }
  486. #if WINVER < 0X0500
  487. #define WS_EX_LAYOUTRTL 0x00400000L // Right to left mirroring
  488. #endif // WS_EX_LAYOUTRTL
  489. //$$
  490. //
  491. //
  492. void ShowToolbarItemMenu(LPBWI lpbwi, HWND hWndTools, int tbitem, int lvtb)
  493. {
  494. // We're going to pop up the Action sub-menu - need to align it
  495. // neatly with the bottom of the toolbar
  496. RECT rc = {0}, rcButton = {0};
  497. LPARAM lp;
  498. SendMessage(hWndTools, TB_GETITEMRECT, (WPARAM)tbitem, (LPARAM)&rcButton);
  499. GetWindowRect(bwi_hWndBB, &rc);
  500. lp = MAKELPARAM((GetWindowLong(bwi_hWndBB, GWL_EXSTYLE) & WS_EX_LAYOUTRTL)? rc.right - rcButton.left : rc.left + rcButton.left, rc.top + rcButton.bottom);
  501. ShowLVContextMenu( lvtb, bwi_hWndListAB, NULL, lp, NULL, bwi_lpAdrBook, bwi_hWndTV);
  502. }
  503. //$$
  504. //*------------------------------------------------------------------------
  505. //| AddressBookWndProx:
  506. //|
  507. //*------------------------------------------------------------------------
  508. LRESULT CALLBACK AddressBookWndProc(HWND hWnd,
  509. UINT uMsg,
  510. WPARAM wParam,
  511. LPARAM lParam)
  512. {
  513. static UINT uTimer = 0;
  514. static FILETIME ftLast = {0};
  515. // HBRUSH to draw STATIC control's background
  516. IF_WIN16(static HBRUSH hBrushBack;)
  517. static BOOL bMouseDrag = FALSE;
  518. LPBWI lpbwi = (LPBWI) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  519. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  520. switch(uMsg)
  521. {
  522. // OE5 HACK. Do not use these WM_USER values in the WAB wndproc
  523. // OE subclasses the WAB to do some modal voodoo in common\ipab.cpp
  524. // if needs to send these private messages.
  525. // case WM_USER + 10666:
  526. // case WM_USER + 10667:
  527. //break;
  528. #ifdef HM_GROUP_SYNCING
  529. case WM_USER_SYNCGROUPS:
  530. // We don't want the user to have to select the HM account for both passes, so use
  531. // the TLS stored account ID if it is available.
  532. HrSynchronize(hWnd, bwi_lpAdrBook, lpPTGData->lptszHMAccountId, TRUE); // Sync group contacts
  533. break;
  534. #endif
  535. case WM_INITMENUPOPUP:
  536. Handle_WM_INITMENUPOPUP(hWnd, lpbwi, uMsg, wParam, lParam);
  537. break;
  538. case WM_MENUSELECT:
  539. Handle_WM_MENSELECT(lpbwi, uMsg, wParam, lParam);
  540. break;
  541. case WM_MOUSEMOVE:
  542. if(SplitterHitTest(bwi_hWndSplitter, lParam))
  543. SetCursor(LoadCursor(NULL, IDC_SIZEWE));
  544. break;
  545. case WM_LBUTTONDOWN:
  546. if(SplitterHitTest(bwi_hWndSplitter, lParam))
  547. {
  548. DragSplitterBar(lpbwi, hWnd, bwi_hWndSplitter, lParam);
  549. }
  550. break;
  551. case WM_COMMAND:
  552. {
  553. switch(GET_WM_COMMAND_ID(wParam, lParam))
  554. {
  555. default:
  556. if(GET_WM_COMMAND_ID(wParam, lParam) >= IDM_VIEW_FOLDERS1 &&
  557. GET_WM_COMMAND_ID(wParam, lParam) <= IDM_VIEW_FOLDERS1 + MAX_VIEW_FOLDERS)
  558. {
  559. LPWABFOLDER lpFolder = bwi_lpIAB->lpWABFolders;
  560. if(lpFolder)
  561. {
  562. int nCmdID = GET_WM_COMMAND_ID(wParam, lParam);
  563. LPSBinary lpsb = NULL;
  564. while(lpFolder)
  565. {
  566. if(nCmdID == lpFolder->nMenuCmdID)
  567. break;
  568. lpFolder = lpFolder->lpNext;
  569. }
  570. if(lpFolder)
  571. {
  572. if(!HR_FAILED(HrUpdateFolderInfo((bwi_lpIAB), &lpFolder->sbEID,
  573. FOLDER_UPDATE_SHARE, !lpFolder->bShared, NULL)))
  574. {
  575. HrGetWABProfiles((bwi_lpIAB));
  576. }
  577. if(!IsWindowVisible(bwi_hWndTV))
  578. PostMessage(hWnd, WM_COMMAND, (WPARAM) IDM_VIEW_GROUPSLIST, 0);
  579. }
  580. if(bwi_lpUserFolder)
  581. bwi_lpUserFolder = NULL;
  582. //UpdateViewFoldersMenu(lpbwi, hWnd);
  583. // Refresh the UI
  584. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsb, NULL, FALSE);
  585. bwi_bDontRefreshLV = TRUE;
  586. RefreshListView(lpbwi,&ftLast);
  587. UpdateLV(lpbwi);
  588. UpdateTVGroupSelection(bwi_hWndTV, lpsb);
  589. bwi_bDontRefreshLV = FALSE;
  590. LocalFreeSBinary(lpsb);
  591. }
  592. }
  593. #ifdef COLSEL_MENU
  594. else if ((GET_WM_COMMAND_ID(wParam, lParam) > IDR_MENU_LVCONTEXTMENU_COLSEL) &&
  595. (GET_WM_COMMAND_ID(wParam, lParam) <= (IDR_MENU_LVCONTEXTMENU_COLSEL + MAX_VIEW_COLSEL)))
  596. {
  597. BOOL rVal = FALSE;
  598. TCHAR szBuf[MAX_PATH];
  599. ULONG iCol = lpbwi->iSelColumn;
  600. ULONG ulCmdId = GET_WM_COMMAND_ID(wParam, lParam);
  601. ULONG iTagSel = (ulCmdId - IDR_MENU_LVCONTEXTMENU_COLSEL - 1);
  602. LONG lr = 0;
  603. HMENU hMenu = LoadMenu(hinstMapiX, MAKEINTRESOURCE(IDR_MENU_LVCONTEXTMENU_COLSEL));
  604. HMENU hSubMenu = GetSubMenu(hMenu, 0);
  605. MENUITEMINFO mii;
  606. if( hMenu && hSubMenu )
  607. {
  608. mii.fMask = MIIM_TYPE;
  609. mii.dwTypeData = szBuf;
  610. mii.cch = CharSizeOf( szBuf );
  611. mii.cbSize = sizeof (MENUITEMINFO);
  612. if ( !GetMenuItemInfo( hSubMenu, iTagSel, TRUE, &mii) )
  613. {
  614. DebugTrace( TEXT("cannot get info : %d\n"), GetLastError() );
  615. rVal = TRUE;
  616. }
  617. else
  618. {
  619. if( iCol == colHomePhone || iCol == colOfficePhone)
  620. {
  621. if( iCol == colHomePhone )
  622. {
  623. PR_WAB_CUSTOMPROP1 = MenuToPropTagMap[iTagSel];
  624. StrCpyN(szCustomProp1, szBuf, ARRAYSIZE(szCustomProp1));
  625. UpdateOptionalColumns( lpbwi, colHomePhone );
  626. }
  627. else
  628. {
  629. PR_WAB_CUSTOMPROP2 = MenuToPropTagMap[iTagSel];
  630. StrCpyN(szCustomProp2, szBuf, ARRAYSIZE(szCustomProp2));
  631. UpdateOptionalColumns( lpbwi, colOfficePhone );
  632. }
  633. UpdateLV( lpbwi );
  634. UpdateSortMenus(lpbwi, hWnd);
  635. UpdateCustomColumnMenuText(hWnd);
  636. }
  637. }
  638. }
  639. else
  640. {
  641. DebugTrace( TEXT("LoadMenu failed: %d\n"), GetLastError());
  642. rVal = TRUE;
  643. }
  644. DestroyMenu(hMenu);
  645. return rVal;
  646. }
  647. #endif //COLSEL_MENU
  648. else
  649. {
  650. LRESULT fRet = FALSE;
  651. bwi_hti = NULL;
  652. bwi_bDontRefreshLV = TRUE;
  653. fRet = ProcessActionCommands(bwi_lpIAB, bwi_hWndListAB,
  654. hWnd, uMsg, wParam, lParam);
  655. bwi_bDontRefreshLV = FALSE;
  656. return fRet;
  657. }
  658. break;
  659. case IDM_EDIT_SETME:
  660. {
  661. SBinary sb = {0};
  662. HrSetMeObject(bwi_lpAdrBook, MAPI_DIALOG, sb, (ULONG_PTR)hWnd);
  663. }
  664. break;
  665. case IDM_FILE_EXIT:
  666. SendMessage(hWnd,WM_CLOSE,0,0L);
  667. return 0;
  668. break;
  669. case IDC_ABOOK_STATIC_QUICK_FIND:
  670. SetFocus(bwi_hWndEditQF);
  671. break;
  672. case IDC_BB_NEW:
  673. ShowToolbarItemMenu(lpbwi, bwi_hWndTools, tbNew, lvToolBarNewEntry);
  674. break;
  675. case IDC_BB_ACTION:
  676. // OE 63674
  677. // When the Print button is hidden (thanks to idsLangPrintingOn==0)
  678. // The enumeration item tbAction is off by 1
  679. ShowToolbarItemMenu(lpbwi, bwi_hWndTools, bPrintingOn ? tbAction : tbAction - 1, lvToolBarAction);
  680. break;
  681. case IDM_FILE_SENDMAIL:
  682. bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
  683. case IDM_LVCONTEXT_SENDMAIL:
  684. bwi_bDontRefreshLV = TRUE;
  685. /*
  686. if(bIsFocusOnTV(lpbwi) && !bIsSelectedTVContainer(lpbwi))
  687. {
  688. LPSBinary lpsbEID = NULL;
  689. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, NULL, FALSE);
  690. if(lpsbEID && lpsbEID->lpb)
  691. {
  692. HrSendMailToSingleContact(hWnd, bwi_lpIAB, lpsbEID->cb, (LPENTRYID)lpsbEID->lpb);
  693. LocalFreeSBinary(lpsbEID);
  694. }
  695. }
  696. else
  697. */
  698. HrSendMailToSelectedContacts(bwi_hWndListAB, bwi_lpAdrBook, 0);
  699. bwi_hti = NULL;
  700. bwi_bDontRefreshLV = FALSE;
  701. break;
  702. case IDC_BB_DELETE:
  703. case IDM_FILE_DELETE:
  704. bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
  705. case IDM_LVCONTEXT_DELETE:
  706. bwi_bDontRefreshLV = TRUE;
  707. // if focus is on the treeview, remove the group from the treeview
  708. if(bIsFocusOnTV(lpbwi))
  709. {
  710. if(!bIsSelectedTVContainer(lpbwi))
  711. {
  712. RemoveCurrentGroup(lpbwi, hWnd, &ftLast);
  713. bwi_bDeferNotification = TRUE;
  714. SetFocus(bwi_hWndTV);
  715. }
  716. else
  717. {
  718. if(!HR_FAILED(RemoveCurrentFolder(lpbwi, hWnd, &ftLast)))
  719. {
  720. UpdateLV(lpbwi);
  721. //UpdateViewFoldersMenu(lpbwi, hWnd);
  722. SetFocus(bwi_hWndTV);
  723. bwi_bDeferNotification = TRUE;
  724. }
  725. }
  726. bwi_hti = NULL;
  727. }
  728. else
  729. {
  730. // Focus is on the ListView
  731. // If we're looking at the root AB - remove from addressbook
  732. // If we're looking at some group, remove entries from group
  733. bwi_hti = NULL; // if this wasnt a context-initiated action on the tree view, dont trust the hti setting
  734. if(!bIsSelectedTVContainer(lpbwi))
  735. {
  736. // a group is selected .. remove from the group .. unless
  737. // the shift key is pressed which means remove from the
  738. // address book
  739. if(GetKeyState(VK_SHIFT) & 0x80)
  740. RemoveSelectedItemsFromCurrentGroup(lpbwi, hWnd, &ftLast, TRUE);
  741. else
  742. RemoveSelectedItemsFromCurrentGroup(lpbwi, hWnd, &ftLast, FALSE);
  743. bwi_hti = NULL;
  744. bwi_bDontRefreshLV = TRUE;
  745. RefreshListView(lpbwi,&ftLast);
  746. bwi_bDontRefreshLV = FALSE;
  747. bwi_bDeferNotification = TRUE;
  748. }
  749. else // Container selected - remove selected items from the container
  750. {
  751. DeleteSelectedItems(bwi_hWndListAB, (LPADRBOOK)bwi_lpAdrBook, bwi_lpIAB->lpPropertyStore->hPropertyStore, &ftLast);
  752. bwi_hti = NULL;
  753. bwi_bDontRefreshLV = TRUE;
  754. RefreshListView(lpbwi,&ftLast);
  755. bwi_bDontRefreshLV = FALSE;
  756. bwi_bDeferNotification = TRUE;
  757. }
  758. SetFocus(bwi_hWndListAB);
  759. }
  760. bwi_hti = NULL;
  761. UpdateToolbarAndMenu(lpbwi);
  762. bwi_bDontRefreshLV = FALSE;
  763. return 0;
  764. break;
  765. case IDM_FILE_NEWFOLDER:
  766. bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
  767. case IDM_LVCONTEXT_NEWFOLDER:
  768. bwi_bDontRefreshLV = TRUE;
  769. {
  770. LPWABFOLDER lpParent = GetSelectedUserFolder(lpbwi);
  771. LPSBinary lpNew = NULL;
  772. SBinary sbNewFolder = {0}, sbParent = {0};
  773. if(lpParent)
  774. SetSBinary(&sbParent, lpParent->sbEID.cb, lpParent->sbEID.lpb);
  775. HrFolderProperties(hWnd, bwi_lpIAB, NULL, lpParent, &sbNewFolder);
  776. if(sbNewFolder.lpb)
  777. lpNew = &sbNewFolder;
  778. else if(lpParent)
  779. lpNew = &sbParent;
  780. //UpdateViewFoldersMenu(lpbwi, hWnd);
  781. if(!IsWindowVisible(bwi_hWndTV))
  782. PostMessage(hWnd, WM_COMMAND, (WPARAM) IDM_VIEW_GROUPSLIST, 0);
  783. HrGetWABProfiles(bwi_lpIAB);
  784. RefreshListView(lpbwi, NULL);
  785. if(lpNew && lpNew->cb)
  786. UpdateTVGroupSelection(bwi_hWndTV, lpNew);
  787. LocalFreeAndNull((LPVOID *) (&(sbParent.lpb)));
  788. LocalFreeAndNull((LPVOID *) (&(sbNewFolder.lpb)));
  789. }
  790. bwi_bDontRefreshLV = FALSE;
  791. bwi_bDeferNotification = TRUE;
  792. bwi_hti = NULL;
  793. break;
  794. case IDM_FILE_NEWGROUP:
  795. bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
  796. case IDM_LVCONTEXT_NEWGROUP:
  797. //case IDC_BB_NEW_GROUP:
  798. {
  799. ULONG cbEID = 0;
  800. LPENTRYID lpEID = NULL;
  801. HRESULT hr = S_OK;
  802. bwi_bDontRefreshLV = TRUE;
  803. hr = AddNewObjectToListViewEx(bwi_lpAdrBook, bwi_hWndListAB, bwi_hWndTV, bwi_hti,
  804. NULL, MAPI_DISTLIST,
  805. &bwi_SortInfo, &bwi_lpContentsList, &ftLast,
  806. &cbEID, &lpEID);
  807. if(hr != MAPI_E_USER_CANCEL)
  808. {
  809. bwi_hti = NULL;
  810. RefreshListView(lpbwi,&ftLast);
  811. if(cbEID && lpEID && IsWindowVisible(bwi_hWndTV))
  812. {
  813. SBinary sbEID = {cbEID, (LPBYTE)lpEID };
  814. UpdateTVGroupSelection(bwi_hWndTV,&sbEID);
  815. FreeBufferAndNull(&lpEID);
  816. }
  817. }
  818. bwi_bDontRefreshLV = FALSE;
  819. //bwi_bDeferNotification = TRUE;
  820. UpdateToolbarAndMenu(lpbwi);
  821. }
  822. break;
  823. case IDM_FILE_NEWCONTACT:
  824. bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
  825. case IDM_LVCONTEXT_NEWCONTACT:
  826. bwi_bDontRefreshLV = TRUE;
  827. AddNewObjectToListViewEx( bwi_lpAdrBook, bwi_hWndListAB, bwi_hWndTV, bwi_hti,
  828. NULL, MAPI_MAILUSER,
  829. &bwi_SortInfo, &bwi_lpContentsList, &ftLast,NULL,NULL);
  830. //RefreshListView(lpbwi,&ftLast);
  831. bwi_hti = NULL;
  832. //bwi_bDeferNotification = TRUE;
  833. bwi_bDontRefreshLV = FALSE;
  834. UpdateToolbarAndMenu(lpbwi);
  835. break;
  836. case IDM_TOOLS_OPTIONS:
  837. HrShowOptionsDlg(hWnd);
  838. break;
  839. case IDM_TOOLS_SYNCHRONIZE_NOW:
  840. #ifdef HM_GROUP_SYNCING
  841. HrSynchronize(hWnd, bwi_lpAdrBook, NULL, FALSE); // Sync mail contacts
  842. #else
  843. HrSynchronize(hWnd, bwi_lpAdrBook, NULL);
  844. #endif
  845. break;
  846. case IDM_FILE_DIRECTORY_SERVICE:
  847. HrShowDirectoryServiceModificationDlg(hWnd, bwi_lpIAB);
  848. break;
  849. case IDC_BB_PRINT:
  850. case IDM_FILE_PRINT:
  851. if(bPrintingOn)
  852. {
  853. TCHAR szBuf[MAX_PATH];
  854. bwi_bDontRefreshLV = TRUE;
  855. LoadString(hinstMapiX, idsPrintStatusBarMessage, szBuf, ARRAYSIZE(szBuf));
  856. StatusBarMessage(lpbwi, szBuf);
  857. HrPrintItems(hWnd, bwi_lpAdrBook, bwi_hWndListAB, bwi_SortInfo.bSortByLastName);
  858. ShowLVCountinStatusBar(lpbwi);
  859. bwi_hti = NULL;
  860. bwi_bDontRefreshLV = FALSE;
  861. }
  862. break;
  863. case IDM_EDIT_COPY:
  864. bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
  865. case IDM_LVCONTEXT_COPY:
  866. {
  867. LPIWABDATAOBJECT lpIWABDataObject = NULL;
  868. bwi_bDontRefreshLV = TRUE;
  869. HrCreateIWABDataObject((LPVOID)lpbwi, bwi_lpAdrBook, bwi_hWndListAB, &lpIWABDataObject,
  870. TRUE,bCheckIfOnlyGroupsSelected(bwi_hWndListAB));
  871. if(lpIWABDataObject)
  872. {
  873. bwi_lpIWABDragDrop->m_bSource = TRUE;
  874. OleSetClipboard((LPDATAOBJECT) lpIWABDataObject);
  875. bwi_lpIWABDragDrop->m_bSource = FALSE;
  876. lpIWABDataObject->lpVtbl->Release(lpIWABDataObject);
  877. }
  878. //HrCopyItemDataToClipboard(hWnd, bwi_lpAdrBook, bwi_hWndListAB);
  879. bwi_hti = NULL;
  880. bwi_bDontRefreshLV = FALSE;
  881. }
  882. break;
  883. case IDM_EDIT_PASTE:
  884. bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
  885. case IDM_LVCONTEXT_PASTE:
  886. {
  887. LPDATAOBJECT lpDataObject = NULL;
  888. bwi_bDontRefreshLV = TRUE;
  889. if(bIsPasteData())
  890. {
  891. if(S_OK == HrPasteData(lpbwi))
  892. UpdateLV(lpbwi);
  893. }
  894. //HrCopyItemDataToClipboard(hWnd, bwi_lpAdrBook, bwi_hWndListAB);
  895. bwi_hti = NULL;
  896. bwi_bDontRefreshLV = FALSE;
  897. }
  898. break;
  899. case IDC_BB_FIND:
  900. case IDM_EDIT_FIND:
  901. bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
  902. case IDM_LVCONTEXT_FIND:
  903. bwi_bDontRefreshLV = TRUE;
  904. HrShowSearchDialog((LPADRBOOK) bwi_lpAdrBook,
  905. bwi_hWndAB,
  906. (LPADRPARM_FINDINFO) NULL,
  907. (LPLDAPURL) NULL,
  908. &(bwi_SortInfo));
  909. bwi_hti = NULL;
  910. RefreshListView(lpbwi,&ftLast);
  911. bwi_bDeferNotification = TRUE;
  912. bwi_bDontRefreshLV = FALSE;
  913. UpdateToolbarAndMenu(lpbwi);
  914. SetFocus(bwi_hWndListAB);
  915. break;
  916. case IDM_EDIT_SELECTALL:
  917. {
  918. int index = 0;
  919. int iTotal = ListView_GetItemCount(bwi_hWndListAB);
  920. if (iTotal > 0)
  921. {
  922. for(index=0;index<iTotal;index++)
  923. {
  924. ListView_SetItemState ( bwi_hWndListAB, // handle to listview
  925. index, // index to listview item
  926. LVIS_SELECTED, // item state
  927. LVIS_SELECTED); // mask
  928. }
  929. }
  930. }
  931. break;
  932. case IDM_HELP_ADDRESSBOOKHELP:
  933. WABHtmlHelp(hWnd, TEXT("%SYSTEMROOT%\\help\\wab.chm>iedefault"),
  934. HH_DISPLAY_TOPIC, (DWORD_PTR) (LPCSTR) TEXT("wab_welcome.htm"));
  935. break;
  936. case IDM_HELP_ABOUTADDRESSBOOK:
  937. DialogBox( hinstMapiX,
  938. MAKEINTRESOURCE(IDD_DIALOG_ABOUT),
  939. hWnd,
  940. HelpAboutDialogProc);
  941. break;
  942. case IDM_FILE_SWITCHUSERS:
  943. HrLogonAndGetCurrentUserProfile(hWnd, bwi_lpIAB, TRUE, FALSE);
  944. break;
  945. case IDM_FILE_SHOWALLCONTENTS:
  946. RunWABApp(hWnd, szWABExeRegPathKey, szWABExe, TEXT("/all"));
  947. break;
  948. case IDM_NOTIFY_REFRESHUSER:
  949. {
  950. LPTSTR lpTitle = CreateWindowTitle(bwi_lpIAB);
  951. SetWindowText(hWnd, lpTitle);
  952. LocalFreeAndNull(&lpTitle);
  953. ReadWABCustomColumnProps(bwi_lpIAB);
  954. UpdateOptionalColumns( lpbwi, colHomePhone );
  955. UpdateOptionalColumns( lpbwi, colOfficePhone );
  956. ReadRegistrySortInfo(bwi_lpIAB,&bwi_SortInfo);
  957. RefreshListView(lpbwi, NULL);
  958. if(bIsThereACurrentUser(bwi_lpIAB))
  959. {
  960. LPSBinary lpsbSelection = &bwi_lpIAB->lpWABCurrentUserFolder->sbEID;
  961. UpdateTVGroupSelection(bwi_hWndTV, lpsbSelection);
  962. }
  963. }
  964. break;
  965. case IDM_FILE_PROPERTIES:
  966. // bobn: brianv says we have to take this out...
  967. /*if(bwi_nCount == 2)
  968. {
  969. if( (GetKeyState(VK_CONTROL) & 0x80) &&
  970. (GetKeyState(VK_MENU) & 0x80) &&
  971. (GetKeyState(VK_SHIFT) & 0x80))
  972. {
  973. SCS(hWnd);
  974. break;
  975. }
  976. }
  977. else
  978. bwi_nCount = 0;*/
  979. case IDC_BB_PROPERTIES:
  980. bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
  981. case IDM_LVCONTEXT_PROPERTIES:
  982. bwi_bDontRefreshLV = TRUE;
  983. if(bIsFocusOnTV(lpbwi))
  984. {
  985. ViewCurrentGroupProperties(lpbwi, &ftLast);
  986. bwi_bDeferNotification = TRUE;
  987. }
  988. else
  989. {
  990. HRESULT hr = HrShowLVEntryProperties(bwi_hWndListAB, WAB_ONEOFF_NOADDBUTTON, bwi_lpAdrBook, &ftLast);
  991. bwi_hti = NULL;
  992. if(hr == MAPI_E_OBJECT_CHANGED)
  993. {
  994. bwi_bDeferNotification = TRUE;
  995. // resort the display
  996. SendMessage(bwi_hWndListAB, WM_SETREDRAW, FALSE, 0);
  997. SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, colDisplayName, &bwi_SortInfo, TRUE);
  998. SendMessage(bwi_hWndListAB, WM_SETREDRAW, TRUE, 0);
  999. }
  1000. bwi_bDontRefreshLV = FALSE;
  1001. return 0;
  1002. }
  1003. bwi_bDontRefreshLV = FALSE;
  1004. break;
  1005. case IDM_VIEW_REFRESH:
  1006. bwi_bDontRefreshLV = TRUE;
  1007. bwi_hti = NULL;
  1008. HrGetWABProfiles(bwi_lpIAB);
  1009. RefreshListView(lpbwi,&ftLast);
  1010. bwi_bDontRefreshLV = FALSE;
  1011. return 0;
  1012. break;
  1013. case IDM_VIEW_STATUSBAR:
  1014. if (IsWindowVisible(bwi_hWndSB))
  1015. {
  1016. //hide it
  1017. CheckMenuItem(GetMenu(hWnd),IDM_VIEW_STATUSBAR,MF_BYCOMMAND | MF_UNCHECKED);
  1018. ShowWindow(bwi_hWndSB, SW_HIDE);
  1019. }
  1020. else
  1021. {
  1022. CheckMenuItem(GetMenu(hWnd),IDM_VIEW_STATUSBAR,MF_BYCOMMAND | MF_CHECKED);
  1023. ShowWindow(bwi_hWndSB, SW_NORMAL);
  1024. //special case repainting to workaround a repaint bug ...
  1025. InvalidateRect(bwi_hWndListAB,NULL,TRUE);
  1026. ShowLVCountinStatusBar(lpbwi);
  1027. }
  1028. ResizeAddressBookChildren(lpbwi, hWnd);
  1029. break;
  1030. case IDM_VIEW_TOOLBAR:
  1031. if (IsWindowVisible(bwi_hWndBB))
  1032. {
  1033. //hide it
  1034. CheckMenuItem(GetMenu(hWnd),IDM_VIEW_TOOLBAR,MF_BYCOMMAND | MF_UNCHECKED);
  1035. ShowWindow(bwi_hWndBB, SW_HIDE);
  1036. }
  1037. else
  1038. {
  1039. CheckMenuItem(GetMenu(hWnd),IDM_VIEW_TOOLBAR,MF_BYCOMMAND | MF_CHECKED);
  1040. ShowWindow(bwi_hWndBB, SW_NORMAL);
  1041. //special case repainting to workaround a repaint bug ...
  1042. InvalidateRect(bwi_hWndListAB,NULL,TRUE);
  1043. InvalidateRect(bwi_hWndTV,NULL,TRUE);
  1044. }
  1045. ResizeAddressBookChildren(lpbwi, hWnd);
  1046. break;
  1047. case IDM_VIEW_GROUPSLIST:
  1048. if (IsWindowVisible(bwi_hWndTV))
  1049. {
  1050. //hide it
  1051. CheckMenuItem(GetMenu(hWnd),IDM_VIEW_GROUPSLIST,MF_BYCOMMAND | MF_UNCHECKED);
  1052. ShowWindow(bwi_hWndTV, SW_HIDE);
  1053. ShowWindow(bwi_hWndSplitter, SW_HIDE);
  1054. InvalidateRect(bwi_hWndStaticQF, NULL, TRUE);
  1055. // If this is a user based session, we want the hidden focus to be on the user's
  1056. // folder not on the Shared Contacts
  1057. if(bIsThereACurrentUser(bwi_lpIAB))
  1058. {
  1059. LPSBinary lpsbSelection = &bwi_lpIAB->lpWABCurrentUserFolder->sbEID;
  1060. UpdateTVGroupSelection(bwi_hWndTV, lpsbSelection);
  1061. }
  1062. else
  1063. {
  1064. // Set the selection to the root address book so we see the file
  1065. // contents just as if we dont have a treeview at all
  1066. HTREEITEM hItem = TreeView_GetSelection(bwi_hWndTV);
  1067. HTREEITEM hRoot = TreeView_GetRoot(bwi_hWndTV);
  1068. if(hItem != hRoot)
  1069. TreeView_SelectItem(bwi_hWndTV, hRoot);
  1070. }
  1071. }
  1072. else
  1073. {
  1074. CheckMenuItem(GetMenu(hWnd),IDM_VIEW_GROUPSLIST,MF_BYCOMMAND | MF_CHECKED);
  1075. ShowWindow(bwi_hWndTV, SW_NORMAL);
  1076. ShowWindow(bwi_hWndSplitter, SW_NORMAL);
  1077. //special case repainting to workaround a repaint bug ...
  1078. //InvalidateRect(bwi_hWndListAB,NULL,TRUE);
  1079. //InvalidateRect(bwi_hWndTV,NULL,TRUE);
  1080. }
  1081. ResizeAddressBookChildren(lpbwi, hWnd);
  1082. SaveCurrentPosition(lpbwi, hWnd,bwi_hWndListAB,bwi_hWndBB,bwi_hWndSB);
  1083. break;
  1084. case IDM_VIEW_SORTBY_DISPLAYNAME:
  1085. case IDM_VIEW_SORTBY_EMAILADDRESS:
  1086. case IDM_VIEW_SORTBY_BUSINESSPHONE:
  1087. case IDM_VIEW_SORTBY_HOMEPHONE:
  1088. {
  1089. //Assuming the above ids are in sequential order ...
  1090. int iCol = LOWORD(wParam) - IDM_VIEW_SORTBY_DISPLAYNAME;
  1091. SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, iCol, &bwi_SortInfo, FALSE);
  1092. UpdateSortMenus(lpbwi, hWnd);
  1093. }
  1094. break;
  1095. case IDM_VIEW_SORTBY_FIRSTNAME:
  1096. bwi_SortInfo.bSortByLastName = FALSE;
  1097. goto DoSortMenuStuff;
  1098. case IDM_VIEW_SORTBY_LASTNAME:
  1099. // bobn: brianv says we have to take this out...
  1100. /*if(bwi_nCount == 1)
  1101. bwi_nCount++;
  1102. else
  1103. bwi_nCount = 0;*/
  1104. bwi_SortInfo.bSortByLastName = TRUE;
  1105. goto DoSortMenuStuff;
  1106. case IDM_VIEW_SORTBY_DESCENDING:
  1107. bwi_SortInfo.bSortAscending = FALSE;
  1108. goto DoSortMenuStuff;
  1109. case IDM_VIEW_SORTBY_ASCENDING:
  1110. bwi_SortInfo.bSortAscending = TRUE;
  1111. DoSortMenuStuff:
  1112. SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, 0, &bwi_SortInfo, TRUE);
  1113. UpdateSortMenus(lpbwi, hWnd);
  1114. break;
  1115. // miscellanous styles for the list view control
  1116. case IDM_VIEW_LARGEICON:
  1117. // bobn: brianv says we have to take this out...
  1118. /*if(bwi_nCount == 0)
  1119. bwi_nCount++;*/
  1120. case IDM_VIEW_SMALLICON:
  1121. case IDM_VIEW_LIST:
  1122. case IDM_VIEW_DETAILS:
  1123. SetListViewStyle(lpbwi, LOWORD(wParam));
  1124. CheckMenuRadioItem( GetMenu(hWnd),
  1125. IDM_VIEW_LARGEICON,
  1126. IDM_VIEW_DETAILS,
  1127. LOWORD(wParam),
  1128. MF_BYCOMMAND);
  1129. return 0;
  1130. break;
  1131. case IDC_EDIT_QUICK_FIND:
  1132. switch(HIWORD(wParam)) //check the notification code
  1133. {
  1134. case EN_CHANGE: //edit box changed
  1135. DoLVQuickFind(bwi_hWndEditQF,bwi_hWndListAB);
  1136. /* if(bwi_bDoQuickFilter)
  1137. {
  1138. DoLVQuickFilter(bwi_lpAdrBook,
  1139. bwi_hWndEditQF,
  1140. bwi_hWndListAB,
  1141. &bwi_SortInfo,
  1142. AB_FUZZY_FIND_NAME | AB_FUZZY_FIND_EMAIL,
  1143. 1,
  1144. &bwi_lpContentsList);
  1145. ShowLVCountinStatusBar(lpbwi);
  1146. }
  1147. */
  1148. break;
  1149. }
  1150. break;
  1151. case IDM_TOOLS_EXPORT_WAB:
  1152. HrExportWAB(hWnd, lpbwi);
  1153. break;
  1154. case IDM_TOOLS_EXPORT_OTHER:
  1155. case IDM_TOOLS_IMPORT_OTHER:
  1156. {
  1157. // if there is a current user, then we let wabmig.exe automatically
  1158. // loginto the current user in the WAB .. else we need to send the filename etc
  1159. //
  1160. BOOL bImport = (GET_WM_COMMAND_ID(wParam, lParam) == IDM_TOOLS_IMPORT_OTHER);
  1161. TCHAR szParam[MAX_PATH * 2];
  1162. if(bIsThereACurrentUser(bwi_lpIAB))
  1163. {
  1164. StrCpyN(szParam, bImport ? szIMPORT : szEXPORT, ARRAYSIZE(szParam));
  1165. }
  1166. else
  1167. {
  1168. LPTSTR lpWABFile = NULL, lpProfileID = szEmpty;
  1169. lpWABFile = GetWABFileName( bwi_lpIAB->lpPropertyStore->hPropertyStore, FALSE);
  1170. if(!lpWABFile || !lstrlen(lpWABFile))
  1171. lpWABFile = szEmpty;
  1172. wnsprintf(szParam, ARRAYSIZE(szParam), (bImport ? szIMPORTwProfileParam : szEXPORTwProfileParam),
  1173. szEmpty, lpWABFile);
  1174. }
  1175. RunWABApp(hWnd, szWABMigRegPathKey, szWABMIG, szParam);
  1176. }
  1177. break;
  1178. case IDM_TOOLS_IMPORT_WAB:
  1179. bwi_bDontRefreshLV = TRUE;
  1180. //bwi_bDeferNotification = TRUE;
  1181. HrImportWABFile(hWnd, bwi_lpAdrBook, MAPI_DIALOG, NULL);
  1182. bwi_bDontRefreshLV = FALSE;
  1183. RefreshListView(lpbwi, &ftLast);
  1184. break;
  1185. #ifdef VCARD
  1186. case IDM_TOOLS_EXPORT_VCARD:
  1187. bwi_bDontRefreshLV = TRUE;
  1188. VCardExportSelectedItems(bwi_hWndListAB, bwi_lpAdrBook);
  1189. bwi_bDontRefreshLV = FALSE;
  1190. return(0);
  1191. case IDM_TOOLS_IMPORT_VCARD:
  1192. OpenAndAddVCard(lpbwi, NULL);
  1193. return(0);
  1194. #endif
  1195. }
  1196. }
  1197. break;
  1198. case WM_TIMER:
  1199. {
  1200. // Check if we need to refresh
  1201. switch(wParam)
  1202. {
  1203. /*
  1204. case WAB_REFRESH_TIMER:
  1205. if ( CheckChangedWAB(bwi_lpIAB->lpPropertyStore, &ftLast))
  1206. {
  1207. if(!bwi_bDontRefreshLV)
  1208. RefreshListView(lpbwi,&ftLast);
  1209. return(0);
  1210. }
  1211. else
  1212. {
  1213. return(DefWindowProc(hWnd,uMsg,wParam,lParam));
  1214. }
  1215. break;
  1216. */
  1217. case WAB_TOOLTIP_TIMER_ID:
  1218. {
  1219. if(GetActiveWindow() == hWnd)
  1220. {
  1221. // We seem to get the message anytime the mouse is sitting idle on the
  1222. // list view - or when the selection changes between items
  1223. if(bwi_tt_bActive)
  1224. {
  1225. // The tooltip is already active
  1226. // Get the item index number of the item under the mouse
  1227. //
  1228. int nItem = HitTestLVSelectedItem(lpbwi);
  1229. if(nItem != bwi_tt_iItem)
  1230. {
  1231. bwi_tt_bShowTooltip = FALSE;
  1232. bwi_tt_iItem = nItem;
  1233. }
  1234. else
  1235. {
  1236. if(!bwi_tt_bShowTooltip)
  1237. {
  1238. // if this is an item other than the previous item
  1239. // we update the tooltip and move it
  1240. TOOLINFO ti = {0};
  1241. bwi_tt_bShowTooltip = TRUE;
  1242. bwi_tt_iItem = nItem;
  1243. FillTooltipInfo(lpbwi, &ti);
  1244. bwi_tt_szTipText[0]='\0';
  1245. ti.lpszText = szEmpty;
  1246. // There is a case where nItem transitions from valid to
  1247. // invalid (-1) item. Cover that case too.
  1248. if(nItem != -1)
  1249. UpdateTooltipTextBuffer(lpbwi, nItem);
  1250. // Set the tooltip text to TEXT("") - this will hide the tooltip
  1251. ToolTip_UpdateTipText(bwi_hWndTT, (LPARAM)&ti);
  1252. if(nItem != -1)
  1253. {
  1254. POINT pt;
  1255. // Move the tooltip
  1256. GetCursorPos(&pt);
  1257. SendMessage(bwi_hWndTT,TTM_TRACKPOSITION,0,(LPARAM)MAKELPARAM(pt.x+15,pt.y+15));
  1258. // Set the new text to the tooltip
  1259. ti.lpszText = bwi_tt_szTipText;
  1260. ToolTip_UpdateTipText(bwi_hWndTT,(LPARAM)&ti);
  1261. }
  1262. }
  1263. }
  1264. }
  1265. }
  1266. else
  1267. {
  1268. // reset the tooltip text ...
  1269. if(bwi_tt_bActive)
  1270. {
  1271. //set the tooltip text to empty
  1272. TOOLINFO ti = {0};
  1273. FillTooltipInfo(lpbwi, &ti);
  1274. ti.lpszText = szEmpty; //LPSTR_TEXTCALLBACK;
  1275. ToolTip_UpdateTipText(bwi_hWndTT, (LPARAM)&ti);
  1276. bwi_tt_iItem = -1;
  1277. }
  1278. }
  1279. }
  1280. break;
  1281. }
  1282. }
  1283. break;
  1284. case WM_GETMINMAXINFO:
  1285. //enforce a minimum size for sanity
  1286. return EnforceMinSize(lpbwi, hWnd, uMsg, wParam, lParam);
  1287. break;
  1288. case PUI_OFFICE_COMMAND:
  1289. // WAB should not shut down if it is running as part of some other process .. it should only shut down if
  1290. // it is running in a seperate process ..
  1291. // To find out if we were invoked by wab.exe, check the cached guidPSExt on the LPIAB object
  1292. if(memcmp(&bwi_lpIAB->guidPSExt, &MPSWab_GUID_V4, sizeof(GUID)))
  1293. {
  1294. DebugTrace( TEXT("Ignoring the Plug_UI command...\n"));
  1295. return 0;
  1296. }
  1297. // We get this message when user switches his locale and IE tells us it wants us to shut down
  1298. if(wParam == PLUGUI_CMD_QUERY)
  1299. {
  1300. PLUGUI_QUERY pq;
  1301. pq.uQueryVal = 0; // initialize
  1302. pq.PlugUIInfo.uMajorVersion = OFFICE_VERSION_9; // Value filled in by Apps
  1303. pq.PlugUIInfo.uOleServer = FALSE; // Value filled in by Apps
  1304. return (pq.uQueryVal); // The state of the App
  1305. }
  1306. // for any others parameters, including PLUGUI_CMD_SHUTDOWN
  1307. // fall to close application
  1308. case WM_CLOSE:
  1309. {
  1310. BOOL bDragDrop = FALSE;
  1311. if(bwi_lpIWABDragDrop)
  1312. {
  1313. bDragDrop = TRUE;
  1314. RevokeDragDrop(bwi_hWndListAB);
  1315. RevokeDragDrop(bwi_hWndTV);
  1316. CoLockObjectExternal((LPUNKNOWN) bwi_lpIWABDragDrop, FALSE, TRUE);
  1317. bwi_lpIWABDragDrop->lpVtbl->Release(bwi_lpIWABDragDrop);
  1318. bwi_lpIWABDragDrop = NULL;
  1319. }
  1320. bwi_bDontRefreshLV = TRUE;
  1321. ClearTreeViewItems(bwi_hWndTV);
  1322. ListView_DeleteAllItems(bwi_hWndListAB);
  1323. //
  1324. // Save the sort info to the registry
  1325. //
  1326. WriteRegistrySortInfo(bwi_lpIAB, bwi_SortInfo);
  1327. SaveCurrentPosition(lpbwi, hWnd,bwi_hWndListAB,bwi_hWndBB,bwi_hWndSB);
  1328. if(bwi_lpfnDismiss)
  1329. {
  1330. (*bwi_lpfnDismiss)((ULONG_PTR) hWnd, (LPVOID) bwi_lpvDismissContext);
  1331. bwi_lpfnDismiss = NULL;
  1332. }
  1333. bwi_lpvDismissContext = NULL;
  1334. DestroyWindow(hWnd);
  1335. // In case the search window was every shown and the LDAP Client DLL was
  1336. // initialized, we deinitialize it just once to save time, when this
  1337. // window shuts down ...
  1338. {
  1339. HCURSOR hOldCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1340. DeinitLDAPClientLib();
  1341. SetCursor(hOldCur);
  1342. }
  1343. OleFlushClipboard();
  1344. return 0;
  1345. }
  1346. break;
  1347. case WM_DESTROY:
  1348. {
  1349. int i = 0;
  1350. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1351. bwi_lpIAB->hWndBrowse = NULL;
  1352. if(bwi_lpAdviseSink)
  1353. {
  1354. bwi_lpAdrBook->lpVtbl->Unadvise(bwi_lpAdrBook, bwi_ulAdviseConnection);
  1355. bwi_lpAdviseSink->lpVtbl->Release(bwi_lpAdviseSink);
  1356. bwi_lpAdviseSink = NULL;
  1357. bwi_ulAdviseConnection = 0;
  1358. }
  1359. if (bwi_lpAdrBook)
  1360. {
  1361. ReleasePropertyStore(bwi_lpIAB->lpPropertyStore);
  1362. bwi_lpAdrBook->lpVtbl->Release(bwi_lpAdrBook);
  1363. bwi_lpAdrBook = NULL;
  1364. bwi_lpIAB = NULL;
  1365. pt_lpIAB = NULL;
  1366. }
  1367. if (bwi_tt_TooltipTimer)
  1368. KillTimer(hWnd, bwi_tt_TooltipTimer);
  1369. if (uTimer)
  1370. KillTimer(hWnd, uTimer);
  1371. if(bwi_hWndAB)
  1372. DestroyMenu(GetMenu(bwi_hWndAB));
  1373. // reset subclassed procs
  1374. for(i=0;i<s_Max;i++)
  1375. {
  1376. SetWindowLongPtr (bwi_s_hWnd[i], GWLP_WNDPROC, (LONG_PTR) bwi_fnOldProc[i]);
  1377. }
  1378. DestroyImageLists(lpbwi);
  1379. CleanUpGlobals(lpbwi);
  1380. LocalFree(lpbwi);
  1381. lpbwi = NULL;
  1382. SetWindowLongPtr(hWnd, GWLP_USERDATA, (LPARAM) NULL);
  1383. // Delete background brush, WIN16 specific.
  1384. IF_WIN16(DeleteObject(hBrushBack);)
  1385. }
  1386. break;
  1387. case WM_CREATE:
  1388. {
  1389. lpbwi = (LPBWI) ((LPCREATESTRUCT) lParam)->lpCreateParams;
  1390. SetWindowLongPtr(hWnd, GWLP_USERDATA, (LPARAM) lpbwi);
  1391. bwi_hWndAB = hWnd;
  1392. bwi_lpIAB->hWndBrowse = hWnd;
  1393. CreateAddressBookChildren(lpbwi, hWnd);
  1394. InitChildren(lpbwi, hWnd);
  1395. ReadRegistrySortInfo(bwi_lpIAB,&bwi_SortInfo);
  1396. SetPreviousSessionPosition(lpbwi, hWnd, bwi_hWndListAB, bwi_hWndBB,bwi_hWndSB);
  1397. SetColumnHeaderBmp(bwi_hWndListAB, bwi_SortInfo);
  1398. // Tooltip Timer
  1399. bwi_tt_TooltipTimer = SetTimer(hWnd,
  1400. WAB_TOOLTIP_TIMER_ID,
  1401. WAB_TOOLTIP_TIMER_TIMEOUT,
  1402. NULL);
  1403. if(bwi_lpAdviseSink)
  1404. {
  1405. // Register for notifications
  1406. bwi_lpAdrBook->lpVtbl->Advise( bwi_lpAdrBook, 0, NULL, fnevObjectModified,
  1407. bwi_lpAdviseSink, &bwi_ulAdviseConnection);
  1408. }
  1409. /*
  1410. // UI Refresh timer
  1411. uTimer = SetTimer(hWnd, // handle of window for timer messages
  1412. WAB_REFRESH_TIMER, // timer identifier
  1413. WAB_REFRESH_TIMEOUT, // time-out value
  1414. NULL); // address of timer procedure
  1415. */
  1416. // Create default background brush, WIN16 only
  1417. IF_WIN16(hBrushBack = CreateSolidBrush (GetSysColor (COLOR_BTNFACE)) ;)
  1418. HrCreateIWABDragDrop(&bwi_lpIWABDragDrop);
  1419. if(bwi_lpIWABDragDrop)
  1420. {
  1421. bwi_lpIWABDragDrop->m_lpv = (LPVOID) lpbwi;
  1422. UIOLEInit();
  1423. CoLockObjectExternal((LPUNKNOWN) bwi_lpIWABDragDrop, TRUE, FALSE);
  1424. RegisterDragDrop(bwi_hWndListAB, (LPDROPTARGET) bwi_lpIWABDragDrop->lpIWABDropTarget);
  1425. RegisterDragDrop(bwi_hWndTV, (LPDROPTARGET) bwi_lpIWABDragDrop->lpIWABDropTarget);
  1426. }
  1427. {
  1428. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1429. if(pt_bFirstRun)
  1430. pt_bFirstRun = FALSE;
  1431. }
  1432. }
  1433. if(bIsThereACurrentUser(bwi_lpIAB))
  1434. UpdateTVGroupSelection(bwi_hWndTV, &(bwi_lpIAB->lpWABCurrentUserFolder->sbEID));
  1435. break;
  1436. case WM_SIZE:
  1437. ResizeAddressBookChildren(lpbwi, hWnd);
  1438. break;
  1439. case WM_KEYDOWN:
  1440. {
  1441. switch(wParam)
  1442. {
  1443. case VK_TAB:
  1444. SetFocus(bwi_s_hWnd[bwi_iFocus]);
  1445. return 0;
  1446. break;
  1447. case VK_ESCAPE:
  1448. SendMessage(hWnd,WM_CLOSE,0,0L);
  1449. return 0;
  1450. break;
  1451. }
  1452. }
  1453. break;
  1454. case WM_NOTIFY:
  1455. switch((int) wParam)
  1456. {
  1457. case IDC_LISTVIEW:
  1458. return ProcessListViewMessages(lpbwi, hWnd,uMsg,wParam,lParam);
  1459. break;
  1460. case IDC_TREEVIEW:
  1461. return ProcessTreeViewMessages(lpbwi, hWnd,uMsg,wParam,lParam, &ftLast);
  1462. break;
  1463. }
  1464. switch(((LPNMHDR) lParam)->code)
  1465. {
  1466. case TTN_POP:
  1467. {
  1468. // Need to turn off the hot item
  1469. // Find the first selected item in the list view
  1470. //int nItem = ListView_GetNextItem(bwi_hWndListAB, -1, LVNI_SELECTED);
  1471. ListView_SetHotItem(bwi_hWndListAB, -1); //nItem);
  1472. }
  1473. break;
  1474. case TTN_SHOW:
  1475. {
  1476. // Set the hot item
  1477. ListView_SetHotItem(bwi_hWndListAB, bwi_tt_iItem);
  1478. }
  1479. break;
  1480. case TTN_NEEDTEXT:
  1481. {
  1482. LPTOOLTIPTEXT lpttt;
  1483. int nItem = HitTestLVSelectedItem(lpbwi);
  1484. DebugPrintTrace(( TEXT("Tooltip NeedText\n")));
  1485. lpttt = (LPTOOLTIPTEXT) lParam;
  1486. if (nItem != -1)
  1487. {
  1488. UpdateTooltipTextBuffer(lpbwi, nItem);
  1489. lpttt->lpszText = bwi_tt_szTipText;
  1490. }
  1491. else
  1492. lpttt->lpszText = szEmpty;
  1493. }
  1494. break;
  1495. }
  1496. break;
  1497. case WM_SETTINGCHANGE:
  1498. // [PaulHi] 3/17/99 Raid 68541 Redraw window with new system settings
  1499. // [PaulHi] 4/19/99 Recompute the font sizes, in case they changed.
  1500. // Fonts used for bolding list items
  1501. DeleteFonts();
  1502. InitFonts();
  1503. // Fonts used for all children windows
  1504. if(pt_hDefFont)
  1505. {
  1506. DeleteObject(pt_hDefFont);
  1507. pt_hDefFont = NULL;
  1508. }
  1509. if(pt_hDlgFont)
  1510. {
  1511. DeleteObject(pt_hDlgFont);
  1512. pt_hDlgFont = NULL;
  1513. }
  1514. EnumChildWindows(hWnd,
  1515. SetChildDefaultGUIFont,
  1516. (LPARAM) PARENT_IS_WINDOW);
  1517. InvalidateRect(hWnd, NULL, TRUE);
  1518. ResizeAddressBookChildren(lpbwi, hWnd);
  1519. // Drop through...
  1520. case WM_SYSCOLORCHANGE:
  1521. {
  1522. //Forward any system changes to the list view
  1523. SendMessage(bwi_hWndListAB, uMsg, wParam, lParam);
  1524. SetColumnHeaderBmp(bwi_hWndListAB, bwi_SortInfo);
  1525. SendMessage(bwi_hWndBB, uMsg, wParam, lParam);
  1526. }
  1527. break;
  1528. #ifndef WIN16 // Disable CONTEXTMENU here.
  1529. // All context menu will be handled notify handler.
  1530. case WM_CONTEXTMENU:
  1531. {
  1532. if ((HWND)wParam == bwi_hWndListAB)
  1533. {
  1534. #ifdef COLSEL_MENU
  1535. HWND hHeader = ListView_GetHeader(bwi_hWndListAB);
  1536. POINT pointScreen, pointHeader;
  1537. DWORD dwPos;
  1538. char szClass[50];
  1539. dwPos = GetMessagePos();
  1540. pointScreen.x = LOWORD(dwPos);
  1541. pointScreen.y = HIWORD(dwPos);
  1542. if ( hHeader )
  1543. {
  1544. HD_HITTESTINFO hdhti;
  1545. pointHeader = pointScreen;
  1546. ScreenToClient( hHeader, &pointHeader) ;
  1547. hdhti.pt = pointHeader;
  1548. SendMessage( hHeader, HDM_HITTEST, (WPARAM)(0),
  1549. (LPARAM)(HD_HITTESTINFO FAR *)&hdhti);
  1550. if( hdhti.flags == HHT_ONHEADER &&
  1551. (hdhti.iItem == colHomePhone || hdhti.iItem == colOfficePhone) )
  1552. {
  1553. lpbwi->iSelColumn = hdhti.iItem;
  1554. ShowLVContextMenu( lvMainABHeader, bwi_hWndListAB,
  1555. NULL, lParam, (LPVOID)IntToPtr(hdhti.iItem), bwi_lpAdrBook, bwi_hWndTV);
  1556. }
  1557. else
  1558. {
  1559. #endif // COLSEL_MENU
  1560. ShowLVContextMenu( lvMainABView,
  1561. bwi_hWndListAB,
  1562. NULL, lParam,
  1563. NULL, bwi_lpAdrBook, bwi_hWndTV);
  1564. #ifdef COLSEL_MENU
  1565. }
  1566. }
  1567. #endif // COLSEL_MENU
  1568. }
  1569. else if((HWND)wParam==bwi_hWndTV)
  1570. {
  1571. HTREEITEM hti = NULL;
  1572. if(lParam == -1)
  1573. hti = TreeView_GetSelection(bwi_hWndTV);
  1574. else
  1575. {
  1576. TV_HITTESTINFO tvhti;
  1577. POINT pt = {LOWORD(lParam), HIWORD(lParam)};
  1578. ScreenToClient(bwi_hWndTV, &pt);
  1579. tvhti.pt = pt;
  1580. hti = TreeView_HitTest(bwi_hWndTV, &tvhti);
  1581. }
  1582. if (hti == NULL)
  1583. return 0;
  1584. TreeView_SelectDropTarget(bwi_hWndTV, hti);
  1585. // cache the selected item for later processing
  1586. bwi_hti = hti;
  1587. bwi_lpUserFolder = GetSelectedUserFolder(lpbwi);
  1588. if(!ShowLVContextMenu( lvMainABTV,
  1589. bwi_hWndListAB,
  1590. NULL, lParam,
  1591. (LPVOID) bwi_lpUserFolder, bwi_lpAdrBook, bwi_hWndTV))
  1592. {
  1593. bwi_hti = NULL;
  1594. }
  1595. TreeView_SelectDropTarget(bwi_hWndTV, NULL);
  1596. }
  1597. else
  1598. return DefWindowProc(hWnd,uMsg,wParam,lParam);
  1599. }
  1600. break;
  1601. #endif // !WIN16
  1602. #ifdef WIN16 // Change Static controls background color
  1603. case WM_CTLCOLOR:
  1604. switch(HIWORD(lParam)) {
  1605. case CTLCOLOR_STATIC:
  1606. /* Set background to btnface color */
  1607. SetBkColor((HDC) wParam,GetSysColor (COLOR_BTNFACE) );
  1608. return (DWORD)hBrushBack;
  1609. }
  1610. return NULL;
  1611. #endif
  1612. default:
  1613. #ifndef WIN16 // WIN16 doesn't support MSWheel.
  1614. if((g_msgMSWheel && uMsg == g_msgMSWheel)
  1615. // || uMsg == WM_MOUSEWHEEL
  1616. )
  1617. {
  1618. if(bIsFocusOnTV(lpbwi))
  1619. SendMessage(bwi_hWndTV, uMsg, wParam, lParam);
  1620. else
  1621. SendMessage(bwi_hWndListAB, uMsg, wParam, lParam);
  1622. break;
  1623. }
  1624. #endif // !WIN16
  1625. return DefWindowProc(hWnd,uMsg,wParam,lParam);
  1626. }
  1627. return 0;
  1628. }
  1629. //$$
  1630. //*------------------------------------------------------------------------
  1631. //| CreateAddressBookChildren:
  1632. //|
  1633. //*------------------------------------------------------------------------
  1634. void CreateAddressBookChildren(LPBWI lpbwi, HWND hWndParent)
  1635. {
  1636. HINSTANCE hinst = hinstMapiXWAB;
  1637. TCHAR szBuf[MAX_PATH];
  1638. HDC hdc = GetDC(hWndParent);
  1639. int i;
  1640. HFONT hFnt = GetStockObject(DEFAULT_GUI_FONT);
  1641. SIZE size;
  1642. #ifdef WIN16
  1643. // Remove bold.
  1644. LOGFONT lf;
  1645. GetObject(hFnt, sizeof(LOGFONT), &lf);
  1646. lf.lfWeight = FW_NORMAL;
  1647. DeleteObject(hFnt);
  1648. LoadString(hinstMapiX, idsDefaultDialogFace, lf.lfFaceName, CharSizeOf(lf.lfFaceName));
  1649. hFnt = CreateFontIndirect(&lf);
  1650. #endif
  1651. bwi_hWndBB = CreateCoolBar(lpbwi, hWndParent);
  1652. bwi_hWndSB = CreateWindowEx( 0,
  1653. STATUSCLASSNAME,
  1654. szEmpty,
  1655. WS_CHILD /*| WS_BORDER */| WS_VISIBLE | SBS_SIZEGRIP,
  1656. 0,0,0,0,
  1657. hWndParent,
  1658. (HMENU) IDC_STATUSBAR,
  1659. hinst,
  1660. NULL);
  1661. SendMessage(bwi_hWndSB, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
  1662. bwi_hWndTV = CreateWindowEx( WS_EX_CLIENTEDGE,
  1663. WC_TREEVIEW,
  1664. (LPTSTR) NULL,
  1665. WS_VISIBLE | WS_CHILD | TVS_HASLINES | TVS_LINESATROOT |
  1666. TVS_HASBUTTONS | TVS_SHOWSELALWAYS | WS_BORDER,
  1667. 0,0,
  1668. 150, //default width
  1669. CW_USEDEFAULT,
  1670. hWndParent,
  1671. (HMENU) IDC_TREEVIEW,
  1672. hinst,
  1673. NULL);
  1674. SendMessage(bwi_hWndTV, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
  1675. {
  1676. #ifndef WIN16
  1677. WNDCLASSEX wc = {0};
  1678. #else
  1679. WNDCLASS wc = {0};
  1680. #endif
  1681. bwi_hWndSplitter = CreateWindowEx(0,
  1682. TEXT("STATIC"),
  1683. szEmpty,
  1684. WS_CHILD | WS_VISIBLE,
  1685. CW_USEDEFAULT,
  1686. CW_USEDEFAULT,
  1687. CW_USEDEFAULT,
  1688. CW_USEDEFAULT,
  1689. hWndParent,
  1690. (HMENU) IDC_SPLITTER,
  1691. hinst,
  1692. NULL);
  1693. SendMessage(bwi_hWndSplitter, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
  1694. }
  1695. bwi_hWndTT = CreateWindowEx( 0,
  1696. TOOLTIPS_CLASS,
  1697. (LPTSTR) NULL,
  1698. TTS_ALWAYSTIP,
  1699. CW_USEDEFAULT,
  1700. CW_USEDEFAULT,
  1701. CW_USEDEFAULT,
  1702. CW_USEDEFAULT,
  1703. hWndParent,
  1704. (HMENU) NULL, //IDC_TOOLTIP,
  1705. hinst,
  1706. NULL);
  1707. SendMessage(bwi_hWndTT, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
  1708. // Create main list view
  1709. bwi_hWndListAB = CreateWindowEx (
  1710. WS_EX_CLIENTEDGE,
  1711. WC_LISTVIEW, // list view class
  1712. szEmpty, // no default text
  1713. WS_TABSTOP | WS_HSCROLL | WS_VSCROLL |
  1714. WS_VISIBLE | WS_CHILD | //WS_BORDER |
  1715. LVS_REPORT | LVS_SHOWSELALWAYS |
  1716. //LVS_AUTOARRANGE |
  1717. WS_EX_CLIENTEDGE, // styles
  1718. 0, 0, 0, 0,
  1719. hWndParent,
  1720. (HMENU) IDC_LISTVIEW,
  1721. hinst,
  1722. NULL);
  1723. //ListView_SetExtendedListViewStyle(bwi_hWndListAB, LVS_EX_HEADERDRAGDROP);
  1724. // create caption for quick find edit box
  1725. ZeroMemory(&size, sizeof(size));
  1726. LoadString(hinstMapiX, idsQuickFindCaption, szBuf, CharSizeOf(szBuf));
  1727. GetTextExtentPoint32(hdc, szBuf, lstrlen(szBuf), &size);
  1728. bwi_hWndStaticQF = CreateWindow( TEXT("STATIC"),
  1729. szBuf,
  1730. WS_TABSTOP | WS_CHILD | WS_VISIBLE,
  1731. 0,0,size.cx,size.cy,
  1732. hWndParent,
  1733. (HMENU) IDC_STATIC_QUICK_FIND,
  1734. hinst,
  1735. NULL);
  1736. #if 0 // Disable temporarily untile comctlie.dll export this.
  1737. #ifdef WIN16
  1738. Ctl3dSubclassCtl(bwi_hWndStaticQF);
  1739. #endif
  1740. #endif
  1741. SendMessage(bwi_hWndStaticQF, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
  1742. UpdateWindow(bwi_hWndStaticQF);
  1743. // create quick find edit box
  1744. bwi_hWndEditQF = CreateWindowEx( WS_EX_CLIENTEDGE,
  1745. TEXT("EDIT"),
  1746. NULL,
  1747. WS_TABSTOP | WS_CHILD | WS_VISIBLE |
  1748. ES_AUTOHSCROLL | ES_LEFT | ES_AUTOVSCROLL ,
  1749. 0,0,
  1750. size.cx,size.cy+4,
  1751. hWndParent,
  1752. (HMENU) IDC_EDIT_QUICK_FIND,
  1753. hinst,
  1754. NULL);
  1755. #if 0 // Disable temporarily untile comctlie.dll export this.
  1756. #ifdef WIN16
  1757. Ctl3dSubclassCtl(bwi_hWndEditQF);
  1758. #endif
  1759. #endif
  1760. SendMessage(bwi_hWndEditQF, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
  1761. SendMessage(bwi_hWndEditQF, EM_SETLIMITTEXT,(WPARAM) MAX_DISPLAY_NAME_LENGTH-1,0);
  1762. if (hdc) ReleaseDC(hWndParent,hdc);
  1763. // Sub class some of the controls
  1764. bwi_s_hWnd[s_EditQF] = bwi_hWndEditQF;
  1765. bwi_s_hWnd[s_ListAB] = bwi_hWndListAB;
  1766. bwi_s_hWnd[s_TV] = bwi_hWndTV;
  1767. for(i=0;i<s_Max;i++)
  1768. {
  1769. bwi_fnOldProc[i] = (WNDPROC) SetWindowLongPtr (bwi_s_hWnd[i], GWLP_WNDPROC, (LONG_PTR) SubClassedProc);
  1770. }
  1771. SetFocus(bwi_hWndEditQF);
  1772. return;
  1773. }
  1774. //$$/////////////////////////////////////////////////////////////
  1775. //
  1776. // ResizeAddressBookChildren(HWND hWndParent)
  1777. //
  1778. // Resizing and moving around
  1779. //
  1780. ///////////////////////////////////////////////////////////////
  1781. void ResizeAddressBookChildren(LPBWI lpbwi, HWND hWndParent)
  1782. {
  1783. RECT rc, rc1;
  1784. int BBx,BBy,BBw,BBh;
  1785. int SBx,SBy,SBw,SBh;
  1786. int QFx,QFy,QFw,QFh;
  1787. int EDx,EDy,EDw,EDh;
  1788. int LVx,LVy,LVw,LVh;
  1789. TCHAR szBuf[MAX_PATH];
  1790. HDC hdc;
  1791. SIZE size;
  1792. RECT rcTV;
  1793. int TVx=0, TVy=0, TVw=0, TVh=0;
  1794. int TCKx = 0, TCKy=0, TCKw=0, TCKh=0;
  1795. // calculate button, static, and edit sizes from the font.
  1796. hdc = GetDC(hWndParent);
  1797. GetClientRect(hWndParent,&rc);
  1798. GetChildClientRect(bwi_hWndBB,&rc1);
  1799. // Button Bars coordinates
  1800. BBx = BBy = 0; BBw = rc.right; BBh = rc1.bottom - rc1.top;
  1801. if (IsWindowVisible(bwi_hWndBB))
  1802. MoveWindow(bwi_hWndBB, BBx, BBy,BBw, BBh,TRUE);
  1803. else
  1804. BBw = BBh = 0;
  1805. if (IsWindowVisible(bwi_hWndTV))
  1806. {
  1807. GetChildClientRect(bwi_hWndTV, &rcTV);
  1808. TVx = 0;
  1809. TVw = rcTV.right - rcTV.left;
  1810. TCKx = TVw;
  1811. TCKw = BORDER;
  1812. }
  1813. // Quick Find labels coordinates
  1814. GetTextExtentPoint32(hdc, szBuf, GetWindowText(bwi_hWndStaticQF, szBuf, CharSizeOf(szBuf)), &size);
  1815. QFx = TVx + TVw + BORDER;
  1816. QFy = BBy+BBh+BORDER;
  1817. QFw = size.cx;
  1818. QFh = size.cy;
  1819. //Edit Box coordinates
  1820. EDx = QFx+QFw+CONTROL_SPACING;
  1821. EDy = QFy;
  1822. QFy += 2;
  1823. GetChildClientRect(bwi_hWndEditQF,&rc1);
  1824. EDh = rc1.bottom - rc1.top;
  1825. EDw = QFw;
  1826. //List View Dimensions
  1827. LVx = TVx + TVw + BORDER;
  1828. LVy = EDy+EDh+BORDER;
  1829. LVw = rc.right - rc.left;// - 2*BORDER;
  1830. LVh = rc.bottom - LVy;// - BORDER;
  1831. // [PaulHi] 3/17/99 Raid 68541
  1832. // We can't just set the status bar height to 14 because in large mode Windows will
  1833. // draw outside the status bar window (very ugly). We want the status bar to be
  1834. // smaller than system default so we (safely) subtract six pixels from the height.
  1835. SBx = 0;
  1836. SBh = GetSystemMetrics(SM_CYCAPTION) - 4;
  1837. SBh = (SBh > 0) ? SBh : 14;
  1838. SBy = rc.bottom - SBh;
  1839. SBw = rc.right - rc.left;
  1840. if(IsWindowVisible(bwi_hWndSB))
  1841. LVh = LVh - SBh - 2*BORDER;
  1842. TVy = QFy;
  1843. TVh = rc.bottom - TVy;
  1844. if(IsWindowVisible(bwi_hWndSB))
  1845. TVh = TVh - SBh - 2*BORDER;
  1846. LVw = LVw - BORDER - TVw;
  1847. if (IsWindowVisible(bwi_hWndTV))
  1848. {
  1849. TCKy = TVy;
  1850. TCKh = TVh;
  1851. }
  1852. {
  1853. HDWP hdwp = BeginDeferWindowPos(6);
  1854. MoveWindow(bwi_hWndEditQF, EDx, EDy, EDw, EDh, TRUE);
  1855. MoveWindow(bwi_hWndStaticQF, QFx, QFy, QFw, QFh, TRUE);
  1856. MoveWindow(bwi_hWndListAB, LVx, LVy, LVw, LVh, TRUE);
  1857. MoveWindow(bwi_hWndSB, SBx, SBy, SBw, SBh, TRUE);
  1858. if (IsWindowVisible(bwi_hWndTV))
  1859. {
  1860. MoveWindow(bwi_hWndTV, TVx, TVy, TVw, TVh, TRUE);
  1861. MoveWindow(bwi_hWndSplitter, TCKx, TCKy, TCKw, TCKh, TRUE);
  1862. }
  1863. EndDeferWindowPos(hdwp);
  1864. }
  1865. ReleaseDC(hWndParent, hdc);
  1866. return;
  1867. }
  1868. //$$/////////////////////////////////////////////////////////////
  1869. //
  1870. // Initialize the kid windows
  1871. //
  1872. ///////////////////////////////////////////////////////////////
  1873. void InitChildren(LPBWI lpbwi, HWND hWndParent)
  1874. {
  1875. HrInitListView(bwi_hWndListAB, LVS_REPORT, TRUE);
  1876. InitMultiLineToolTip(lpbwi, hWndParent);
  1877. {
  1878. HIMAGELIST hSmall = gpfnImageList_LoadImage( hinstMapiX,
  1879. MAKEINTRESOURCE(IDB_BITMAP_SMALL),
  1880. //(LPCTSTR) ((DWORD) ((WORD) (IDB_BITMAP_SMALL))),
  1881. S_BITMAP_WIDTH,
  1882. 0,
  1883. RGB_TRANSPARENT,
  1884. IMAGE_BITMAP,
  1885. 0);
  1886. // Associate the image lists with the list view control.
  1887. TreeView_SetImageList (bwi_hWndTV, hSmall, TVSIL_NORMAL);
  1888. //FillTreeView(bwi_hWndTV, NULL);
  1889. }
  1890. // Set the font of all the children to the default GUI font
  1891. EnumChildWindows( hWndParent,
  1892. SetChildDefaultGUIFont,
  1893. (LPARAM) PARENT_IS_WINDOW);
  1894. SendMessage(hWndParent,WM_COMMAND,IDM_VIEW_DETAILS,0);
  1895. bwi_bDoQuickFilter = TRUE;
  1896. SetFocus(bwi_hWndEditQF);
  1897. }
  1898. //$$/////////////////////////////////////////////////////////////
  1899. //
  1900. // Change list views styles and possibly menus also
  1901. //
  1902. ///////////////////////////////////////////////////////////////
  1903. void SetListViewStyle(LPBWI lpbwi, int MenuID)
  1904. {
  1905. DWORD dwStyle = GetWindowLong(bwi_hWndListAB,GWL_STYLE);
  1906. BOOL bUseCurrentSortSettings = FALSE;
  1907. // Right now we just change the style here
  1908. // later on we can update the menu etc. to reflect the style and
  1909. switch(MenuID)
  1910. {
  1911. case IDM_VIEW_DETAILS:
  1912. if((dwStyle & LVS_TYPEMASK) != LVS_REPORT)
  1913. SetWindowLong(bwi_hWndListAB,GWL_STYLE,(dwStyle & ~LVS_TYPEMASK) | LVS_REPORT);
  1914. break;
  1915. case IDM_VIEW_SMALLICON:
  1916. if((dwStyle & LVS_TYPEMASK) != LVS_SMALLICON)
  1917. SetWindowLong(bwi_hWndListAB,GWL_STYLE,(dwStyle & ~LVS_TYPEMASK) | LVS_SMALLICON);
  1918. break;
  1919. case IDM_VIEW_LARGEICON:
  1920. if((dwStyle & LVS_TYPEMASK) != LVS_ICON)
  1921. SetWindowLong(bwi_hWndListAB,GWL_STYLE,(dwStyle & ~LVS_TYPEMASK) | LVS_ICON);
  1922. break;
  1923. case IDM_VIEW_LIST:
  1924. if((dwStyle & LVS_TYPEMASK) != LVS_LIST)
  1925. SetWindowLong(bwi_hWndListAB,GWL_STYLE,(dwStyle & ~LVS_TYPEMASK) | LVS_LIST);
  1926. break;
  1927. }
  1928. {
  1929. //
  1930. // If we are not in details view, we dont really want to be able to sort
  1931. // by phone number and email address .. hence we disable those menu
  1932. // options under certain conditions ...
  1933. //
  1934. HMENU hMenuMain = GetMenu(bwi_hWndAB);
  1935. HMENU hMenuView = GetSubMenu(hMenuMain,idmView);
  1936. int nDiff = idmViewMax - GetMenuItemCount(hMenuView); // in case stuff was deleted off this menu
  1937. HMENU hMenu = GetSubMenu(hMenuView, idmSortBy - nDiff);
  1938. if (MenuID == IDM_VIEW_DETAILS)
  1939. {
  1940. EnableMenuItem(hMenu,IDM_VIEW_SORTBY_EMAILADDRESS,MF_BYCOMMAND | MF_ENABLED);
  1941. EnableMenuItem(hMenu,IDM_VIEW_SORTBY_BUSINESSPHONE,MF_BYCOMMAND | MF_ENABLED);
  1942. EnableMenuItem(hMenu,IDM_VIEW_SORTBY_HOMEPHONE,MF_BYCOMMAND | MF_ENABLED);
  1943. }
  1944. else
  1945. {
  1946. EnableMenuItem(hMenu,IDM_VIEW_SORTBY_EMAILADDRESS,MF_BYCOMMAND | MF_GRAYED);
  1947. EnableMenuItem(hMenu,IDM_VIEW_SORTBY_BUSINESSPHONE,MF_BYCOMMAND | MF_GRAYED);
  1948. EnableMenuItem(hMenu,IDM_VIEW_SORTBY_HOMEPHONE,MF_BYCOMMAND | MF_GRAYED);
  1949. }
  1950. }
  1951. if (MenuID != IDM_VIEW_DETAILS)
  1952. {
  1953. SORT_INFO SortTmp = bwi_SortInfo;
  1954. //hack
  1955. SendMessage(bwi_hWndListAB, WM_SETREDRAW, (WPARAM) FALSE, 0);
  1956. bUseCurrentSortSettings = FALSE;
  1957. SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, colDisplayName, &bwi_SortInfo, bUseCurrentSortSettings);
  1958. bwi_SortInfo = SortTmp;
  1959. bwi_SortInfo.iOldSortCol = colDisplayName;
  1960. bUseCurrentSortSettings = TRUE;
  1961. SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, colDisplayName, &bwi_SortInfo, bUseCurrentSortSettings);
  1962. SendMessage(bwi_hWndListAB, WM_SETREDRAW, (WPARAM) TRUE, 0);
  1963. }
  1964. UpdateSortMenus(lpbwi, bwi_hWndAB);
  1965. return;
  1966. }
  1967. //$$/////////////////////////////////////////////////////////////
  1968. //
  1969. // Resets the globals in case someone drops by again
  1970. //
  1971. ///////////////////////////////////////////////////////////////
  1972. void CleanUpGlobals(LPBWI lpbwi)
  1973. {
  1974. if (bwi_lpContentsList)
  1975. FreeRecipList(&bwi_lpContentsList);
  1976. bwi_hWndListAB = NULL;
  1977. bwi_hWndBB = NULL;
  1978. bwi_hWndSB = NULL;
  1979. bwi_hWndEditQF =NULL;
  1980. bwi_hWndStaticQF = NULL;
  1981. bwi_hWndAB = NULL;
  1982. bwi_hWndTT = NULL;
  1983. bwi_tt_bActive = FALSE;
  1984. bwi_tt_iItem = -1;
  1985. bwi_tt_szTipText[0]='\0';
  1986. bwi_tt_TooltipTimer = 0;
  1987. bwi_hWndTV = NULL;
  1988. bwi_hWndSplitter = NULL;
  1989. bwi_bDontRefreshLV = FALSE;
  1990. ReadRegistrySortInfo(bwi_lpIAB, &bwi_SortInfo);
  1991. return;
  1992. }
  1993. /*
  1994. - bCheckIfOnlyGroupsSelected
  1995. -
  1996. - Returns TRUE if all the selected items in the ListView are only Groups (no Contacts)
  1997. *
  1998. */
  1999. BOOL bCheckIfOnlyGroupsSelected(HWND hWndLV)
  2000. {
  2001. int nSelected = ListView_GetSelectedCount(hWndLV);
  2002. int iItemIndex = -1;
  2003. if(nSelected <= 0)
  2004. return FALSE;
  2005. while((iItemIndex = ListView_GetNextItem(hWndLV, iItemIndex, LVNI_SELECTED))!= -1)
  2006. {
  2007. // Get the entryid of the selected item
  2008. LPRECIPIENT_INFO lpItem = GetItemFromLV(hWndLV, iItemIndex);
  2009. if(lpItem && lpItem->ulObjectType == MAPI_MAILUSER)
  2010. return FALSE;
  2011. }
  2012. return TRUE;
  2013. }
  2014. //$$////////////////////////////////////////////////////////////////////////////////////////
  2015. //
  2016. // Processes messages for the list view control
  2017. //
  2018. //////////////////////////////////////////////////////////////////////////////////////////
  2019. LRESULT ProcessListViewMessages(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2020. {
  2021. NM_LISTVIEW * pNm = (NM_LISTVIEW *)lParam;
  2022. HWND hWndAddr = pNm->hdr.hwndFrom;
  2023. switch(pNm->hdr.code)
  2024. {
  2025. case LVN_COLUMNCLICK:
  2026. SortListViewColumn(bwi_lpIAB, hWndAddr, pNm->iSubItem, &bwi_SortInfo, FALSE);
  2027. UpdateSortMenus(lpbwi, bwi_hWndAB);
  2028. break;
  2029. case LVN_KEYDOWN:
  2030. UpdateToolbarAndMenu(lpbwi);
  2031. switch(((LV_KEYDOWN FAR *) lParam)->wVKey)
  2032. {
  2033. case VK_DELETE:
  2034. SendMessage (hWnd, WM_COMMAND, (WPARAM) IDM_FILE_DELETE, 0);
  2035. return 0;
  2036. break;
  2037. case VK_RETURN:
  2038. SendMessage (hWnd, WM_COMMAND, (WPARAM) IDM_FILE_PROPERTIES, 0);
  2039. return 0;
  2040. }
  2041. break;
  2042. //case LVN_ITEMCHANGED:
  2043. case NM_CLICK:
  2044. case NM_RCLICK:
  2045. {
  2046. UpdateToolbarAndMenu(lpbwi);
  2047. #ifdef WIN16 // Context menu handler for WIN16
  2048. if( pNm->hdr.code == NM_RCLICK && pNm->hdr.hwndFrom == bwi_hWndListAB)
  2049. {
  2050. POINT pt;
  2051. GetCursorPos(&pt);
  2052. ShowLVContextMenu( lvMainABView,
  2053. bwi_hWndListAB,
  2054. NULL, //bwi_hWndCombo,
  2055. MAKELPARAM(pt.x, pt.y),
  2056. NULL,
  2057. bwi_lpAdrBook, bwi_hWndTV);
  2058. }
  2059. #endif // WIN16
  2060. }
  2061. break;
  2062. case NM_SETFOCUS:
  2063. UpdateToolbarAndMenu(lpbwi);
  2064. break;
  2065. case NM_DBLCLK:
  2066. SendMessage (hWnd, WM_COMMAND, (WPARAM) IDM_FILE_PROPERTIES, 0);
  2067. return 0;
  2068. break;
  2069. case NM_CUSTOMDRAW:
  2070. return ProcessLVCustomDraw(NULL, lParam, FALSE);
  2071. break;
  2072. case LVN_BEGINDRAG:
  2073. case LVN_BEGINRDRAG:
  2074. {
  2075. DWORD dwEffect = 0;
  2076. LPIWABDATAOBJECT lpIWABDataObject = NULL;
  2077. bwi_bDontRefreshLV = TRUE; // prevent refreshes as this action is based on the selection
  2078. HrCreateIWABDataObject((LPVOID) lpbwi, bwi_lpAdrBook, bwi_hWndListAB, &lpIWABDataObject,
  2079. FALSE,bCheckIfOnlyGroupsSelected(bwi_hWndListAB));
  2080. if(lpIWABDataObject)
  2081. {
  2082. bwi_lpIWABDragDrop->m_bSource = TRUE;
  2083. DoDragDrop( (LPDATAOBJECT) lpIWABDataObject,
  2084. (LPDROPSOURCE) bwi_lpIWABDragDrop->lpIWABDropSource,
  2085. DROPEFFECT_COPY | DROPEFFECT_MOVE,
  2086. &dwEffect);
  2087. bwi_lpIWABDragDrop->m_bSource = FALSE;
  2088. lpIWABDataObject->lpVtbl->Release(lpIWABDataObject);
  2089. }
  2090. RefreshListView(lpbwi, NULL);
  2091. bwi_bDontRefreshLV = FALSE; // prevent refreshes as this action is based on the selection
  2092. }
  2093. return 0;
  2094. break;
  2095. }
  2096. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  2097. }
  2098. //$$/////////////////////////////////////////////////////////////////////////
  2099. //
  2100. //
  2101. //
  2102. ///////////////////////////////////////////////////////////////////////////
  2103. LRESULT EnforceMinSize(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2104. {
  2105. LPPOINT lppt = (LPPOINT)lParam; // lParam points to array of POINTs
  2106. RECT rc1, rc2;
  2107. if(lpbwi)
  2108. {
  2109. if(bwi_hWndEditQF)
  2110. {
  2111. GetWindowRect(bwi_hWndEditQF,&rc1);
  2112. GetWindowRect(bwi_hWndStaticQF,&rc2);
  2113. lppt[3].x = rc1.right-rc1.left + rc2.right-rc2.left + 2*BORDER; // Set minimum width
  2114. lppt[3].y = MIN_WINDOW_H; // Set minimum height
  2115. }
  2116. }
  2117. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  2118. }
  2119. //$$
  2120. //*------------------------------------------------------------------------
  2121. //| RefreshListView
  2122. //|
  2123. //| lpftLast - WAB file time at last update
  2124. //*------------------------------------------------------------------------
  2125. void RefreshListView(LPBWI lpbwi, LPFILETIME lpftLast)
  2126. {
  2127. ULONG ulObjectType = 0;
  2128. LPSBinary lpsbEID = NULL;
  2129. bwi_hti = NULL;
  2130. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjectType, FALSE);
  2131. //if(lpsbEID) //root item can have a null entryid - so we default to that item if NULL or err
  2132. {
  2133. // Refresh the groups list
  2134. FillTreeView(lpbwi, bwi_hWndTV, lpsbEID);
  2135. LocalFreeSBinary(lpsbEID);
  2136. }
  2137. // Update the wab file write time so the timer doesn't
  2138. // catch this change and refresh.
  2139. //if (lpftLast) {
  2140. // CheckChangedWAB(bwi_lpIAB->lpPropertyStore, lpftLast);
  2141. //}
  2142. UpdateSortMenus(lpbwi, bwi_hWndAB);
  2143. UpdateToolbarAndMenu(lpbwi);
  2144. //DoLVQuickFind(bwi_hWndEditQF,bwi_hWndListAB);
  2145. bwi_bDoQuickFilter = FALSE;
  2146. SetWindowText(bwi_hWndEditQF,szEmpty);
  2147. bwi_bDoQuickFilter = TRUE;
  2148. SendMessage(bwi_hWndListAB, WM_SETREDRAW, TRUE, 0L);
  2149. return;
  2150. }
  2151. //$$
  2152. //*------------------------------------------------------------------------
  2153. //| SubClassedProc - to subclass child controls
  2154. //|
  2155. //*------------------------------------------------------------------------
  2156. LRESULT CALLBACK SubClassedProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  2157. {
  2158. LPBWI lpbwi = (LPBWI) GetWindowLongPtr(GetParent(hWnd), GWLP_USERDATA);
  2159. IF_WIN32(int i = GetWindowLong(hWnd, GWL_ID);)
  2160. IF_WIN16(int i = GetWindowWord(hWnd, GWW_ID);)
  2161. switch(i)
  2162. {
  2163. case IDC_EDIT_QUICK_FIND:
  2164. i = s_EditQF;
  2165. break;
  2166. case IDC_LISTVIEW:
  2167. i = s_ListAB;
  2168. break;
  2169. case IDC_TREEVIEW:
  2170. i = s_TV;
  2171. break;
  2172. }
  2173. switch (iMsg)
  2174. {
  2175. case WM_KEYDOWN:
  2176. switch(wParam)
  2177. {
  2178. case VK_TAB:
  2179. {
  2180. int max = s_Max;
  2181. if(!IsWindowVisible(bwi_hWndTV)) max--;
  2182. SetFocus(bwi_s_hWnd[(i + ((GetKeyState(VK_SHIFT) < 0) ? (max-1) : 1)) % (max)]);
  2183. }
  2184. break;
  2185. case VK_ESCAPE:
  2186. SendMessage(bwi_hWndAB,WM_CLOSE,0,0L);
  2187. return 0;
  2188. break;
  2189. case VK_RETURN:
  2190. if (i==s_EditQF)
  2191. SetFocus(bwi_s_hWnd[(i + ((GetKeyState(VK_SHIFT) < 0) ? (s_Max-1) : 1)) % (s_Max)]);
  2192. break;
  2193. }
  2194. break;
  2195. case WM_CHAR:
  2196. if (i==s_EditQF || i==s_TV)
  2197. {
  2198. if ((wParam==VK_RETURN) || (wParam==VK_TAB))
  2199. return 0; //prevents irritating beeps
  2200. }
  2201. break;
  2202. case WM_SETFOCUS:
  2203. bwi_iFocus = i;
  2204. break;
  2205. case WM_LBUTTONDBLCLK:
  2206. if(i==s_TV)
  2207. {
  2208. SendMessage(bwi_hWndAB, WM_COMMAND, (WPARAM) IDM_FILE_PROPERTIES, 0);
  2209. return FALSE;
  2210. }
  2211. break;
  2212. }
  2213. return CallWindowProc(bwi_fnOldProc[i],hWnd,iMsg,wParam,lParam);
  2214. }
  2215. //$$
  2216. //*------------------------------------------------------------------------
  2217. //| FindABWindowProc:
  2218. //|
  2219. //*------------------------------------------------------------------------
  2220. STDAPI_(BOOL) FindABWindowProc( HWND hWndToLookAt, LPARAM lParam)
  2221. {
  2222. HWND * lphWndTmp = (HWND *) lParam;
  2223. TCHAR szBuf[MAX_PATH];
  2224. // yuk - need a better way to do this - TBD
  2225. if (*lphWndTmp == NULL)
  2226. {
  2227. GetClassName(hWndToLookAt, szBuf, CharSizeOf(szBuf));
  2228. if(!lstrcmpi(g_szClass,szBuf))
  2229. {
  2230. // Found our man
  2231. *lphWndTmp = hWndToLookAt;
  2232. return FALSE;
  2233. }
  2234. }
  2235. return TRUE;
  2236. }
  2237. //$$
  2238. //*------------------------------------------------------------------------
  2239. //| CallBack used by client to send accelerators to us
  2240. //|
  2241. //*------------------------------------------------------------------------
  2242. BOOL STDMETHODCALLTYPE fnAccelerateMessages(ULONG_PTR ulUIParam, LPVOID lpvmsg)
  2243. {
  2244. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  2245. BOOL bRet = FALSE;
  2246. if(lpvmsg && pt_hAccTable /*&& IsDialogMessage((HWND) ulUIParam,lpvmsg)*/)
  2247. {
  2248. bRet = TranslateAcceleratorW((HWND) ulUIParam, // handle of destination window
  2249. pt_hAccTable, // handle of accelerator table
  2250. (LPMSG) lpvmsg // address of structure with message
  2251. );
  2252. }
  2253. return bRet;
  2254. }
  2255. //$$
  2256. //*------------------------------------------------------------------------
  2257. //| Updates the menu item markings whenever we sort ...
  2258. //|
  2259. //*------------------------------------------------------------------------
  2260. void UpdateSortMenus(LPBWI lpbwi, HWND hWnd)
  2261. {
  2262. int id;
  2263. HMENU hMenuMain = GetMenu(hWnd);
  2264. HMENU hMenuView = GetSubMenu(hMenuMain,idmView);
  2265. int nDiff = idmViewMax - GetMenuItemCount(hMenuView); // in case stuff was deleted off this menu
  2266. HMENU hMenu = GetSubMenu(hMenuView, idmSortBy - nDiff);
  2267. BOOL bRet;
  2268. //
  2269. // There are several menus to update here ...
  2270. // Sort by TEXT("Column")
  2271. // Sort by FirstName or LastName
  2272. // Sort Ascending or descending
  2273. switch(bwi_SortInfo.iOldSortCol)
  2274. {
  2275. case colDisplayName:
  2276. id = IDM_VIEW_SORTBY_DISPLAYNAME;
  2277. break;
  2278. case colEmailAddress:
  2279. id = IDM_VIEW_SORTBY_EMAILADDRESS;
  2280. break;
  2281. case colOfficePhone:
  2282. id = IDM_VIEW_SORTBY_BUSINESSPHONE;
  2283. break;
  2284. case colHomePhone:
  2285. id = IDM_VIEW_SORTBY_HOMEPHONE;
  2286. break;
  2287. }
  2288. bRet = CheckMenuRadioItem( hMenu,
  2289. IDM_VIEW_SORTBY_DISPLAYNAME,
  2290. IDM_VIEW_SORTBY_HOMEPHONE,
  2291. id,
  2292. MF_BYCOMMAND);
  2293. if (id!=IDM_VIEW_SORTBY_DISPLAYNAME)
  2294. {
  2295. EnableMenuItem(hMenu,IDM_VIEW_SORTBY_LASTNAME,MF_BYCOMMAND | MF_GRAYED);
  2296. EnableMenuItem(hMenu,IDM_VIEW_SORTBY_FIRSTNAME,MF_BYCOMMAND | MF_GRAYED);
  2297. }
  2298. else
  2299. {
  2300. EnableMenuItem(hMenu,IDM_VIEW_SORTBY_LASTNAME,MF_BYCOMMAND | MF_ENABLED);
  2301. EnableMenuItem(hMenu,IDM_VIEW_SORTBY_FIRSTNAME,MF_BYCOMMAND | MF_ENABLED);
  2302. }
  2303. id = (bwi_SortInfo.bSortByLastName) ? IDM_VIEW_SORTBY_LASTNAME : IDM_VIEW_SORTBY_FIRSTNAME;
  2304. bRet = CheckMenuRadioItem( hMenu,
  2305. IDM_VIEW_SORTBY_FIRSTNAME,
  2306. IDM_VIEW_SORTBY_LASTNAME,
  2307. id,
  2308. MF_BYCOMMAND);
  2309. id = (bwi_SortInfo.bSortAscending) ? IDM_VIEW_SORTBY_ASCENDING : IDM_VIEW_SORTBY_DESCENDING;
  2310. bRet = CheckMenuRadioItem( hMenu,
  2311. IDM_VIEW_SORTBY_ASCENDING,
  2312. IDM_VIEW_SORTBY_DESCENDING,
  2313. id,
  2314. MF_BYCOMMAND);
  2315. return;
  2316. }
  2317. ///////////////////////////////////////////////////////////////////////////
  2318. //
  2319. // Updates the toolbar based on the contents of the list box
  2320. //
  2321. //
  2322. ///////////////////////////////////////////////////////////////////////////
  2323. void UpdateToolbarAndMenu(LPBWI lpbwi)
  2324. {
  2325. //
  2326. // Toolbar Button States
  2327. //
  2328. // Y: Enabled
  2329. // N: Disabled
  2330. //
  2331. // non-Empty-WAB Empty-WAB non-EmptyLDAP EmptyLDAP
  2332. // New Y Y N N
  2333. // Properties Y N Y N
  2334. // Delete Y N N N
  2335. // Search Y Y Y Y
  2336. // Add to WAB N N Y N
  2337. // Print Y N Y N
  2338. // SendMail Y N Y N
  2339. BOOL bState[tbMAX];
  2340. int i;
  2341. // if the current focus is on a group, all the above can be selected
  2342. // else depends on the list view
  2343. if(bIsFocusOnTV(lpbwi))
  2344. {
  2345. for(i=0;i<tbMAX;i++)
  2346. bState[i] = TRUE;
  2347. // if there are no items in this group, tag it so
  2348. if(ListView_GetItemCount(bwi_hWndListAB) <= 0)
  2349. bState[tbPrint] = /*bState[tbAction] =*/ FALSE;
  2350. // [PaulHi] 11/23/98 Raid #12453
  2351. // Allow pasting into the Tree View
  2352. // bState[tbCopy] = bState[tbPaste] = FALSE;
  2353. bState[tbCopy] = FALSE;
  2354. bState[tbPaste] = bIsPasteData();
  2355. }
  2356. else
  2357. {
  2358. GetCurrentOptionsState( NULL, bwi_hWndListAB, bState);
  2359. }
  2360. // if( (bDoesThisWABHaveAnyUsers(bwi_lpIAB)) &&
  2361. // TreeView_GetSelection(bwi_hWndTV) == TreeView_GetRoot(bwi_hWndTV))
  2362. // bState[tbNewFolder] = FALSE;
  2363. // Set the toolbar button states
  2364. SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_NEW,(LPARAM) MAKELONG(bState[tbNew], 0));
  2365. SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_PROPERTIES,(LPARAM) MAKELONG(bState[tbProperties], 0));
  2366. SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_DELETE,(LPARAM) MAKELONG(bState[tbDelete], 0));
  2367. SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_FIND,(LPARAM) MAKELONG(bState[tbFind], 0));
  2368. SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_PRINT,(LPARAM) MAKELONG(bState[tbPrint], 0));
  2369. SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_ACTION,(LPARAM) MAKELONG(bState[tbAction], 0));
  2370. #ifdef WIN16 // WIN16FF:Disable find button of coolbar. Find is not beta1 feature
  2371. SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_FIND,(LPARAM)MAKELONG(0, 0));
  2372. #endif
  2373. //
  2374. // We also need to synchronize the menus with the toolbar ...
  2375. //
  2376. {
  2377. HMENU hMenuMain = GetMenu(bwi_hWndAB);
  2378. HMENU hMenuSub = GetSubMenu(hMenuMain,idmFile);
  2379. UINT uiFlag[tbMAX];
  2380. for(i=0;i<tbMAX;i++)
  2381. uiFlag[i] = (bState[i] ? MF_ENABLED : MF_GRAYED);
  2382. EnableMenuItem(hMenuSub,IDM_FILE_NEWCONTACT,MF_BYCOMMAND | uiFlag[tbNewEntry]);
  2383. EnableMenuItem(hMenuSub,IDM_FILE_NEWGROUP, MF_BYCOMMAND | uiFlag[tbNewGroup]);
  2384. EnableMenuItem(hMenuSub,IDM_FILE_NEWFOLDER, MF_BYCOMMAND | uiFlag[tbNewFolder]);
  2385. EnableMenuItem(hMenuSub,IDM_FILE_DELETE, MF_BYCOMMAND | uiFlag[tbDelete]);
  2386. EnableMenuItem(hMenuSub,IDM_FILE_PROPERTIES,MF_BYCOMMAND | uiFlag[tbProperties]);
  2387. //EnableMenuItem(hMenuSub,IDM_FILE_ADDTOWAB, MF_BYCOMMAND | uiFlag[tbAddToWAB]);
  2388. //EnableMenuItem(hMenuSub,IDM_FILE_SENDMAIL, MF_BYCOMMAND | uiFlag[tbAction]);
  2389. if(bPrintingOn)
  2390. EnableMenuItem(hMenuSub,IDM_FILE_PRINT, MF_BYCOMMAND | uiFlag[tbPrint]);
  2391. hMenuSub = GetSubMenu(hMenuMain,idmEdit);
  2392. EnableMenuItem(hMenuSub,IDM_EDIT_COPY, MF_BYCOMMAND | uiFlag[tbCopy]);
  2393. EnableMenuItem(hMenuSub,IDM_EDIT_PASTE, MF_BYCOMMAND | uiFlag[tbPaste]);
  2394. #ifdef WIN16 // WIN16FF:FIND is not beta1 feature
  2395. EnableMenuItem(hMenuSub,IDM_EDIT_FIND, MF_BYCOMMAND | MF_GRAYED);
  2396. #else
  2397. EnableMenuItem(hMenuSub,IDM_EDIT_FIND, MF_BYCOMMAND | uiFlag[tbFind]);
  2398. #endif
  2399. //hMenuSub = GetSubMenu(hMenuMain,idmTools);
  2400. }
  2401. ShowLVCountinStatusBar(lpbwi);
  2402. return;
  2403. }
  2404. //$$//////////////////////////////////////////////////////////////////////////////
  2405. //
  2406. // SaveCurrentPosition
  2407. //
  2408. // Saves the modeless dialog window position and the list view column sizes ...
  2409. //
  2410. //////////////////////////////////////////////////////////////////////////////////
  2411. void SaveCurrentPosition(LPBWI lpbwi, HWND hWnd, HWND hWndLV, HWND hWndTB, HWND hWndSB)
  2412. {
  2413. ABOOK_POSCOLSIZE ABPosColSize = {0};
  2414. int i;
  2415. RECT rect;
  2416. //
  2417. // First read the previous settings from the registry so we dont
  2418. // overwrite something if we dont need to ...
  2419. //
  2420. ReadRegistryPositionInfo(bwi_lpIAB, &ABPosColSize, lpszRegPositionKeyValueName);
  2421. {
  2422. WINDOWPLACEMENT wpl = {0};
  2423. wpl.length = sizeof(WINDOWPLACEMENT);
  2424. // This call tells us the window state and normal size and position
  2425. GetWindowPlacement(hWnd, &wpl);
  2426. // There seems to be a bug in GetWindowPlacement that
  2427. // doesnt account for various taskbars on the screen when
  2428. // returning the Window's Normal Position .. as a result
  2429. // the stored coordinates won't be accurate. Instead, we'll
  2430. // use those coordinates only if the window is maximized or
  2431. // minimized - otherwise we will use the GetWindowRect
  2432. // coordinates.
  2433. // Get the screen position of this window
  2434. GetWindowRect(hWnd, &(ABPosColSize.rcPos));
  2435. if(wpl.showCmd != SW_SHOWNORMAL)
  2436. {
  2437. ABPosColSize.rcPos = wpl.rcNormalPosition;
  2438. }
  2439. }
  2440. // Check the current List View Style
  2441. ABPosColSize.dwListViewStyle = GetWindowLong(hWndLV, GWL_STYLE);
  2442. if( (ABPosColSize.dwListViewStyle & LVS_TYPEMASK) == LVS_REPORT )
  2443. {
  2444. ABPosColSize.nListViewStyleMenuID = IDM_VIEW_DETAILS;
  2445. // get column widths only if this is the details style otherwise
  2446. // not ...
  2447. for(i=0; i<NUM_COLUMNS; i++)
  2448. {
  2449. int nCol = ListView_GetColumnWidth(hWndLV, i);
  2450. if(nCol!=0)
  2451. ABPosColSize.nColWidth[i] = nCol;
  2452. }
  2453. }
  2454. else if( (ABPosColSize.dwListViewStyle & LVS_TYPEMASK) == LVS_SMALLICON )
  2455. ABPosColSize.nListViewStyleMenuID = IDM_VIEW_SMALLICON;
  2456. else if( (ABPosColSize.dwListViewStyle & LVS_TYPEMASK) == LVS_ICON )
  2457. ABPosColSize.nListViewStyleMenuID = IDM_VIEW_LARGEICON;
  2458. else if( (ABPosColSize.dwListViewStyle & LVS_TYPEMASK) == LVS_LIST )
  2459. ABPosColSize.nListViewStyleMenuID = IDM_VIEW_LIST;
  2460. if (IsWindowVisible(hWndTB))
  2461. ABPosColSize.bViewToolbar = TRUE;
  2462. else
  2463. ABPosColSize.bViewToolbar = FALSE;
  2464. if (IsWindowVisible(hWndSB))
  2465. ABPosColSize.bViewStatusBar = TRUE;
  2466. else
  2467. ABPosColSize.bViewStatusBar = FALSE;
  2468. {
  2469. if (IsWindowVisible(bwi_hWndTV))
  2470. ABPosColSize.bViewGroupList = TRUE;
  2471. else
  2472. ABPosColSize.bViewGroupList = FALSE;
  2473. }
  2474. ListView_GetColumnOrderArray(hWndLV, NUM_COLUMNS, ABPosColSize.colOrderArray);
  2475. GetWindowRect( bwi_hWndTV, &rect );
  2476. ABPosColSize.nTViewWidth = rect.right - rect.left;
  2477. WriteRegistryPositionInfo(bwi_lpIAB, &ABPosColSize,lpszRegPositionKeyValueName);
  2478. return;
  2479. }
  2480. //$$//////////////////////////////////////////////////////////////////////////////
  2481. //
  2482. // SetPreviousSessionPosition
  2483. //
  2484. // Sets the modeless dialog window position and the list view column sizes based on
  2485. // the previous sessions parameters ...
  2486. //
  2487. //////////////////////////////////////////////////////////////////////////////////
  2488. void SetPreviousSessionPosition(LPBWI lpbwi, HWND hWnd, HWND hWndLV, HWND hWndTB, HWND hWndSB)
  2489. {
  2490. ABOOK_POSCOLSIZE ABPosColSize = {0};
  2491. int i;
  2492. RECT rect;
  2493. ABPosColSize.bViewGroupList =TRUE; // Off by default
  2494. if(ReadRegistryPositionInfo(bwi_lpIAB, &ABPosColSize, lpszRegPositionKeyValueName))
  2495. {
  2496. rect.left = ABPosColSize.rcPos.left;
  2497. rect.top = ABPosColSize.rcPos.top;
  2498. rect.right = ABPosColSize.rcPos.right;
  2499. rect.bottom = ABPosColSize.rcPos.bottom;
  2500. if( IsWindowOnScreen( &rect ) )
  2501. {
  2502. MoveWindow(hWnd,
  2503. ABPosColSize.rcPos.left,
  2504. ABPosColSize.rcPos.top,
  2505. ABPosColSize.rcPos.right-ABPosColSize.rcPos.left,
  2506. ABPosColSize.rcPos.bottom-ABPosColSize.rcPos.top,
  2507. FALSE);
  2508. }
  2509. for(i=0; i<NUM_COLUMNS; i++)
  2510. {
  2511. if(ABPosColSize.nColWidth[i]!=0)
  2512. ListView_SetColumnWidth(hWndLV, i, ABPosColSize.nColWidth[i]);
  2513. }
  2514. if(ABPosColSize.bViewToolbar == FALSE)
  2515. {
  2516. //hide it
  2517. CheckMenuItem(GetMenu(hWnd),IDM_VIEW_TOOLBAR,MF_BYCOMMAND | MF_UNCHECKED);
  2518. ShowWindow(hWndTB, SW_HIDE);
  2519. }
  2520. if(ABPosColSize.bViewStatusBar == FALSE)
  2521. {
  2522. //hide it
  2523. CheckMenuItem(GetMenu(hWnd),IDM_VIEW_STATUSBAR,MF_BYCOMMAND | MF_UNCHECKED);
  2524. ShowWindow(hWndSB, SW_HIDE);
  2525. }
  2526. GetWindowRect( bwi_hWndTV, &rect );
  2527. if( ABPosColSize.nTViewWidth != 0 )
  2528. MoveWindow( bwi_hWndTV, rect.left, rect.top, ABPosColSize.nTViewWidth, rect.bottom - rect.top, FALSE );
  2529. ResizeAddressBookChildren(lpbwi, hWnd);//,SIZE_RESTORED);
  2530. if (ABPosColSize.nListViewStyleMenuID != 0)
  2531. {
  2532. SetListViewStyle(lpbwi, ABPosColSize.nListViewStyleMenuID);
  2533. CheckMenuRadioItem( GetMenu(hWnd),
  2534. IDM_VIEW_LARGEICON,
  2535. IDM_VIEW_DETAILS,
  2536. ABPosColSize.nListViewStyleMenuID,
  2537. MF_BYCOMMAND);
  2538. }
  2539. {
  2540. int nTotal=0,nColSum=0;
  2541. // the previous version did not have the column order setting, so if the
  2542. // values are incorrect reset them
  2543. for(i=0;i<NUM_COLUMNS;i++)
  2544. {
  2545. nTotal += ABPosColSize.colOrderArray[i];
  2546. nColSum += i;
  2547. }
  2548. if(nColSum != nTotal)
  2549. {
  2550. for(i=0;i<NUM_COLUMNS;i++)
  2551. ABPosColSize.colOrderArray[i] = i;
  2552. }
  2553. }
  2554. ListView_SetColumnOrderArray(hWndLV, NUM_COLUMNS, ABPosColSize.colOrderArray);
  2555. }
  2556. if(ABPosColSize.bViewGroupList == FALSE)
  2557. {
  2558. //hide it
  2559. CheckMenuItem(GetMenu(hWnd),IDM_VIEW_GROUPSLIST,MF_BYCOMMAND | MF_UNCHECKED);
  2560. ShowWindow(bwi_hWndTV, SW_HIDE);
  2561. ShowWindow(bwi_hWndSplitter, SW_HIDE);
  2562. InvalidateRect(bwi_hWndStaticQF, NULL, TRUE);
  2563. // folder not on the Shared Contacts
  2564. if(bIsThereACurrentUser(bwi_lpIAB))
  2565. {
  2566. LPSBinary lpsbSelection = &bwi_lpIAB->lpWABCurrentUserFolder->sbEID;
  2567. UpdateTVGroupSelection(bwi_hWndTV, lpsbSelection);
  2568. }
  2569. else
  2570. {
  2571. // Set the selection to the root address book so we see the file
  2572. // contents just as if we dont have a treeview at all
  2573. TreeView_SelectItem(bwi_hWndTV, TreeView_GetRoot(bwi_hWndTV));
  2574. }
  2575. }
  2576. return;
  2577. }
  2578. #define MAX_TOOLTIP_LENGTH 300
  2579. #define TOOLTIP_INITTIME 5000 //milliseconds
  2580. #define TOOLTIP_TIME 8000 //milliseconds
  2581. //$$/////////////////////////////////////////////////////////////////////////////
  2582. //
  2583. // void UpdateTooltipTextBuffer - Updates the text in the buffer for the tooltip
  2584. //
  2585. ////////////////////////////////////////////////////////////////////////////////
  2586. void UpdateTooltipTextBuffer(LPBWI lpbwi, int nItem)
  2587. {
  2588. LPTSTR lpszData = NULL;
  2589. bwi_tt_iItem = nItem;
  2590. bwi_tt_szTipText[0]='\0';
  2591. HrGetLVItemDataString(bwi_lpAdrBook, bwi_hWndListAB, nItem, &lpszData);
  2592. if(lpszData)
  2593. {
  2594. if (CharSizeOf(bwi_tt_szTipText) < (lstrlen(lpszData)+1))
  2595. {
  2596. LPTSTR lpsz = TEXT(" ...");
  2597. ULONG nLen = TruncatePos(lpszData, CharSizeOf(bwi_tt_szTipText) - lstrlen(lpsz) - 1);
  2598. CopyMemory(bwi_tt_szTipText, lpszData, sizeof(TCHAR)*nLen);
  2599. bwi_tt_szTipText[nLen]='\0';
  2600. StrCatBuff(bwi_tt_szTipText,lpsz, ARRAYSIZE(bwi_tt_szTipText));
  2601. }
  2602. else
  2603. StrCpyN(bwi_tt_szTipText, lpszData, ARRAYSIZE(bwi_tt_szTipText));
  2604. }
  2605. LocalFreeAndNull(&lpszData);
  2606. return;
  2607. }
  2608. //$$/////////////////////////////////////////////////////////////////////////////
  2609. //
  2610. // void InitMultiLineTooltip - initializes the multiline tooltip for the list view
  2611. // control
  2612. //
  2613. ////////////////////////////////////////////////////////////////////////////////
  2614. void InitMultiLineToolTip(LPBWI lpbwi, HWND hWndParent)
  2615. {
  2616. TOOLINFO ti = {0};
  2617. bwi_tt_bActive = FALSE;
  2618. bwi_tt_iItem = -1;
  2619. bwi_tt_szTipText[0]='\0';
  2620. FillTooltipInfo(lpbwi, &ti);
  2621. SendMessage(bwi_hWndTT, TTM_SETMAXTIPWIDTH, 0, (LPARAM) MAX_TOOLTIP_LENGTH);
  2622. ToolTip_AddTool(bwi_hWndTT, (LPARAM) (LPTOOLINFO) &ti);
  2623. SendMessage(bwi_hWndTT, TTM_SETDELAYTIME, (WPARAM) TTDT_INITIAL, (LPARAM) TOOLTIP_INITTIME);
  2624. SendMessage(bwi_hWndTT, TTM_SETDELAYTIME, (WPARAM) TTDT_RESHOW, (LPARAM) TOOLTIP_INITTIME);
  2625. SendMessage(bwi_hWndTT, TTM_SETDELAYTIME, (WPARAM) TTDT_AUTOPOP, (LPARAM) TOOLTIP_TIME);
  2626. SendMessage(bwi_hWndTT, TTM_ACTIVATE, (WPARAM) TRUE, 0);
  2627. if(!bwi_tt_bActive)
  2628. {
  2629. // if the tooltip is not active, activate it
  2630. TOOLINFO ti = {0};
  2631. FillTooltipInfo(lpbwi, &ti);
  2632. ti.lpszText = szEmpty; //LPSTR_TEXTCALLBACK;
  2633. ToolTip_UpdateTipText(bwi_hWndTT, (LPARAM)&ti);
  2634. SendMessage(bwi_hWndTT, TTM_TRACKACTIVATE,(WPARAM)TRUE,(LPARAM)&ti);
  2635. bwi_tt_bActive = TRUE;
  2636. }
  2637. return;
  2638. }
  2639. //$$/////////////////////////////////////////////////////////////////////////////
  2640. //
  2641. // void FillTooltipInfo - initializes the tooltip structure for making updates or
  2642. // modifications to the tooltips
  2643. //
  2644. ////////////////////////////////////////////////////////////////////////////////
  2645. void FillTooltipInfo(LPBWI lpbwi, LPTOOLINFO lpti)
  2646. {
  2647. lpti->cbSize = sizeof(TOOLINFO);
  2648. lpti->hwnd = bwi_hWndAB;
  2649. lpti->uId = (UINT_PTR) bwi_hWndListAB;
  2650. lpti->hinst = hinstMapiX;
  2651. lpti->uFlags = TTF_IDISHWND | TTF_SUBCLASS;// | TTF_ABSOLUTE | TTF_TRACK;
  2652. lpti->lpszText = szEmpty;//LPSTR_TEXTCALLBACK;
  2653. lpti->lParam = 0;
  2654. return;
  2655. }
  2656. //$$/////////////////////////////////////////////////////////////////////////////
  2657. //
  2658. // int HitTestLVSelectedItem() - Gets the item index number of the item exactly under
  2659. // the mouse - further selects the item if it isnt selected
  2660. //
  2661. ////////////////////////////////////////////////////////////////////////////////
  2662. int HitTestLVSelectedItem(LPBWI lpbwi)
  2663. {
  2664. POINT pt;
  2665. RECT rc;
  2666. int nItemIndex = -1;
  2667. LV_HITTESTINFO lht = {0};
  2668. GetCursorPos(&pt);
  2669. GetWindowRect(bwi_hWndListAB, &rc);
  2670. lht.pt.x = pt.x - rc.left;
  2671. lht.pt.y = pt.y - rc.top;
  2672. ListView_HitTest(bwi_hWndListAB, &lht);
  2673. if(lht.iItem != -1)
  2674. nItemIndex = lht.iItem;
  2675. return nItemIndex;
  2676. }
  2677. /***********************************************************
  2678. Handle_WM_INITMENUPOPUP
  2679. Handles any popup menu's we need to modify ..
  2680. ***********************************************************/
  2681. void Handle_WM_INITMENUPOPUP (HWND hWnd, LPBWI lpbwi, UINT message, WPARAM uParam, LPARAM lParam )
  2682. {
  2683. HMENU hMenuPopup = (HMENU) uParam;
  2684. UINT uPos = (UINT) LOWORD(lParam);
  2685. BOOL fSysMenu = (BOOL) HIWORD(lParam);
  2686. // Look at the first item on the menu to identify it
  2687. UINT uID = GetMenuItemID(hMenuPopup, 0);
  2688. if(uID == IDM_FILE_SENDMAIL) // this is the Tools | Action Menu
  2689. {
  2690. AddExtendedMenuItems(bwi_lpAdrBook, bwi_hWndListAB,
  2691. hMenuPopup, TRUE,
  2692. (!bIsFocusOnTV(lpbwi))); // this is the condition for updating SendMailTo
  2693. }
  2694. else
  2695. if(uID == IDM_EDIT_COPY)
  2696. {
  2697. UpdateToolbarAndMenu(lpbwi);
  2698. }
  2699. else
  2700. if(uID == IDM_FILE_NEWCONTACT)
  2701. {
  2702. if(bDoesThisWABHaveAnyUsers(bwi_lpIAB))
  2703. UpdateViewFoldersMenu(lpbwi, hWnd);
  2704. }
  2705. UpdateSynchronizeMenus(hMenuPopup, bwi_lpIAB);
  2706. /*
  2707. else if(uID == IDM_FILE_NEWCONTACT)
  2708. {
  2709. if(!bIsThereACurrentUser(bwi_lpIAB))
  2710. EnableMenuItem(hMenuPopup, IDM_FILE_SWITCHUSERS, MF_GRAYED | MF_BYCOMMAND);
  2711. }
  2712. */
  2713. }
  2714. /***********************************************************
  2715. The Handle_WM_MENSELECT function below is a pared down
  2716. cheezy sample to figure out the ID of the currently selected
  2717. menu. It returns 0 if a popup menu is selected, -1 of no menu
  2718. is selected (i.e. closed), and a positive nonzero value
  2719. if a menu item is selected.
  2720. ***********************************************************/
  2721. void Handle_WM_MENSELECT (LPBWI lpbwi, UINT message, WPARAM uParam, LPARAM lParam )
  2722. {
  2723. UINT nStringID = 0;
  2724. TCHAR sz[MAX_UI_STR];
  2725. UINT fuFlags = (UINT)HIWORD(uParam) & 0xffff;
  2726. UINT uCmd = (UINT)LOWORD(uParam);
  2727. HMENU hMenu = (HMENU)lParam;
  2728. nStringID = 0;
  2729. sz[0] = TEXT('\0');
  2730. if (fuFlags == 0xffff && hMenu == NULL) // Menu has been closed
  2731. nStringID = (UINT)-1;
  2732. else if (fuFlags & MFT_SEPARATOR) // Ignore separators
  2733. nStringID = 0;
  2734. else if (fuFlags & MF_POPUP) // Popup menu
  2735. {
  2736. nStringID = 0;
  2737. if (fuFlags & MF_SYSMENU) // System menu
  2738. nStringID = 0;
  2739. } // for MF_POPUP
  2740. else // Must be a command item
  2741. {
  2742. switch(uCmd)
  2743. {
  2744. case IDC_BB_PRINT:
  2745. case IDM_FILE_PRINT:
  2746. nStringID = idsPrintMenu;
  2747. break;
  2748. case IDM_VIEW_GROUPSLIST:
  2749. nStringID = idsGroupListMenu;
  2750. break;
  2751. case IDM_HELP_ABOUTADDRESSBOOK:
  2752. nStringID = idsAboutMenu;
  2753. break;
  2754. case IDM_LVCONTEXT_NEWCONTACT:
  2755. case IDM_FILE_NEWCONTACT:
  2756. nStringID = idsMenuNewContact;
  2757. break;
  2758. case IDM_LVCONTEXT_NEWGROUP:
  2759. case IDM_FILE_NEWGROUP:
  2760. nStringID = idsMenuNewGroup;
  2761. break;
  2762. case IDM_LVCONTEXT_NEWFOLDER:
  2763. case IDM_FILE_NEWFOLDER:
  2764. nStringID = idsMenuNewFolder;
  2765. break;
  2766. case IDM_LVCONTEXT_COPY:
  2767. case IDM_EDIT_COPY:
  2768. nStringID = idsMenuCopy;
  2769. break;
  2770. case IDM_LVCONTEXT_PASTE:
  2771. case IDM_EDIT_PASTE:
  2772. nStringID = idsMenuPaste;
  2773. break;
  2774. case IDM_LVCONTEXT_PROPERTIES:
  2775. case IDM_FILE_PROPERTIES:
  2776. nStringID = idsMenuProperties;
  2777. break;
  2778. case IDM_LVCONTEXT_DELETE:
  2779. case IDM_FILE_DELETE:
  2780. nStringID = idsMenuDeleteRemove;
  2781. break;
  2782. //case IDM_FILE_ADDTOWAB:
  2783. //case IDM_LVCONTEXT_ADDTOWAB:
  2784. // nStringID = idsMenuAddToWAB;
  2785. // break;
  2786. case IDM_LVCONTEXT_FIND:
  2787. case IDM_EDIT_FIND:
  2788. nStringID = idsMenuFind;
  2789. break;
  2790. case IDM_FILE_DIRECTORY_SERVICE:
  2791. nStringID = idsMenuDirectoryService;
  2792. break;
  2793. case IDM_FILE_SWITCHUSERS:
  2794. nStringID = idsMenuSwitchUser;
  2795. break;
  2796. case IDM_FILE_SHOWALLCONTENTS:
  2797. nStringID = idsMenuShowAllContents;
  2798. break;
  2799. case IDM_FILE_EXIT:
  2800. nStringID = idsMenuExit;
  2801. break;
  2802. case IDM_EDIT_SELECTALL:
  2803. nStringID = idsMenuSelectAll;
  2804. break;
  2805. case IDM_VIEW_TOOLBAR:
  2806. nStringID = idsMenuViewToolbar;
  2807. break;
  2808. case IDM_VIEW_STATUSBAR:
  2809. nStringID = idsMenuViewStatusBar;
  2810. break;
  2811. case IDM_VIEW_LARGEICON:
  2812. nStringID = idsMenuLargeIcon;
  2813. break;
  2814. case IDM_VIEW_SMALLICON:
  2815. nStringID = idsMenuSmallIcon;
  2816. break;
  2817. case IDM_VIEW_LIST:
  2818. nStringID = idsMenuList;
  2819. break;
  2820. case IDM_VIEW_DETAILS:
  2821. nStringID = idsMenuDetails;
  2822. break;
  2823. case IDM_VIEW_SORTBY_DISPLAYNAME:
  2824. nStringID = idsMenuDisplayName;
  2825. break;
  2826. case IDM_VIEW_SORTBY_EMAILADDRESS:
  2827. nStringID = idsMenuEmail;
  2828. break;
  2829. case IDM_VIEW_SORTBY_BUSINESSPHONE:
  2830. nStringID = idsMenuBusinessPhone;
  2831. break;
  2832. case IDM_VIEW_SORTBY_HOMEPHONE:
  2833. nStringID = idsMenuHomePhone;
  2834. break;
  2835. case IDM_VIEW_SORTBY_FIRSTNAME:
  2836. nStringID = idsMenuFirstName;
  2837. break;
  2838. case IDM_VIEW_SORTBY_LASTNAME:
  2839. nStringID = idsMenuLastName;
  2840. break;
  2841. case IDM_VIEW_SORTBY_ASCENDING:
  2842. nStringID = idsMenuAscending;
  2843. break;
  2844. case IDM_VIEW_SORTBY_DESCENDING:
  2845. nStringID = idsMenuDescending;
  2846. break;
  2847. case IDM_VIEW_REFRESH:
  2848. nStringID = idsMenuRefresh;
  2849. break;
  2850. case IDM_TOOLS_IMPORT_WAB:
  2851. nStringID = idsMenuImportWAB;
  2852. break;
  2853. case IDM_TOOLS_IMPORT_VCARD:
  2854. nStringID = idsMenuImportVcard;
  2855. break;
  2856. case IDM_TOOLS_IMPORT_OTHER:
  2857. nStringID = idsMenuImportOther;
  2858. break;
  2859. case IDM_TOOLS_EXPORT_OTHER:
  2860. nStringID = idsMenuExportOther;
  2861. break;
  2862. case IDM_TOOLS_EXPORT_WAB:
  2863. nStringID = idsMenuExportWAB;
  2864. break;
  2865. case IDM_TOOLS_EXPORT_VCARD:
  2866. nStringID = idsMenuExportVcard;
  2867. break;
  2868. case IDM_HELP_ADDRESSBOOKHELP:
  2869. nStringID = idsMenuHelp;
  2870. break;
  2871. case IDM_EDIT_SETME:
  2872. nStringID = idsMenuEditProfile;
  2873. break;
  2874. default:
  2875. nStringID = 0;
  2876. GetContextMenuExtCommandString(bwi_lpIAB, uCmd, sz, CharSizeOf(sz));
  2877. break;
  2878. }
  2879. }
  2880. if (nStringID > 0)
  2881. {
  2882. LoadString(hinstMapiX, nStringID, sz, ARRAYSIZE(sz));
  2883. }
  2884. StatusBarMessage(lpbwi, sz);
  2885. return;
  2886. }
  2887. //$$////////////////////////////////////////////////////////////////////////////////////////
  2888. //
  2889. // Fills a lpList from the contents of a given group
  2890. // If lpList is NULL, ignores that parameter
  2891. // If lpszName is NULL, ignores that parameter
  2892. //
  2893. //////////////////////////////////////////////////////////////////////////////////////////
  2894. HRESULT FillListFromGroup(
  2895. LPADRBOOK lpAdrBook,
  2896. ULONG cbGroupEntryID,
  2897. LPENTRYID lpGroupEntryID,
  2898. LPTSTR lpszName,
  2899. ULONG cchName,
  2900. LPRECIPIENT_INFO * lppList)
  2901. {
  2902. ULONG ulcPropCount;
  2903. LPSPropValue lpPropArray = NULL;
  2904. ULONG j;
  2905. HRESULT hr = E_FAIL;
  2906. LPRECIPIENT_INFO lpInfo = NULL;
  2907. hr = HrGetPropArray( lpAdrBook, NULL,
  2908. cbGroupEntryID, (LPENTRYID) lpGroupEntryID,
  2909. MAPI_UNICODE,
  2910. &ulcPropCount, &lpPropArray);
  2911. if (HR_FAILED(hr))
  2912. goto exit;
  2913. if(lppList && *lppList)
  2914. FreeRecipList(lppList);
  2915. for(j=0;j<ulcPropCount;j++)
  2916. {
  2917. // We are ignoring PR_WAB_DL_ONEOFFS here since we don't want to show OneOffs
  2918. if( lpPropArray[j].ulPropTag==PR_WAB_DL_ENTRIES && lppList )
  2919. {
  2920. ULONG k;
  2921. // Look at each entry in the PR_WAB_DL_ENTRIES and recursively check it.
  2922. for (k = 0; k < lpPropArray[j].Value.MVbin.cValues; k++)
  2923. {
  2924. ULONG cbEID = lpPropArray[j].Value.MVbin.lpbin[k].cb;
  2925. {
  2926. LPENTRYID lpEID = (LPENTRYID)lpPropArray[j].Value.MVbin.lpbin[k].lpb;
  2927. // we don't want one-offs showing up in the UI because all kinds of problems start happening
  2928. // when these one-offs are dragged and dropped
  2929. // A doublecheck here not really needed in 99% cases
  2930. if(WAB_ONEOFF == IsWABEntryID(cbEID, lpEID, NULL, NULL, NULL, NULL, NULL))
  2931. continue;
  2932. ReadSingleContentItem( lpAdrBook,cbEID, (LPENTRYID)lpEID, &lpInfo);
  2933. if(lpInfo)
  2934. {
  2935. lpInfo->lpNext = *lppList;
  2936. if(*lppList)
  2937. (*lppList)->lpPrev = lpInfo;
  2938. *lppList = lpInfo;
  2939. }
  2940. }
  2941. }
  2942. }
  2943. else if (lpPropArray[j].ulPropTag == PR_DISPLAY_NAME)
  2944. {
  2945. if(lpszName)
  2946. StrCpyN(lpszName, lpPropArray[j].Value.LPSZ, cchName);
  2947. }
  2948. }
  2949. hr = S_OK;
  2950. exit:
  2951. if(lpPropArray)
  2952. MAPIFreeBuffer(lpPropArray);
  2953. return(hr);
  2954. }
  2955. //$$////////////////////////////////////////////////////////////////////////////////////////
  2956. //
  2957. // UpdateListViewContents(lpsbEID)
  2958. //
  2959. // Updates the displayed list in the list view based on the entry id of the selected
  2960. // TreeView item
  2961. //
  2962. //////////////////////////////////////////////////////////////////////////////////////////
  2963. void UpdateListViewContents(LPBWI lpbwi, LPSBinary lpsbEID, ULONG ulObjectType)
  2964. {
  2965. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  2966. if( (ulObjectType == MAPI_ABCONT && (pt_bIsWABOpenExSession || bIsWABSessionProfileAware(bwi_lpIAB)))//a folder and it's outlook or profiles are enabled
  2967. || !lpsbEID || !lpsbEID->cb || !lpsbEID->lpb )// or no container entryid
  2968. {
  2969. HrGetWABContents( bwi_hWndListAB,
  2970. bwi_lpAdrBook,
  2971. lpsbEID,
  2972. bwi_SortInfo,
  2973. &(bwi_lpContentsList));
  2974. }
  2975. else if(ulObjectType == MAPI_DISTLIST )
  2976. {
  2977. if(!HR_FAILED( FillListFromGroup(
  2978. bwi_lpAdrBook,
  2979. lpsbEID->cb,
  2980. (LPENTRYID) lpsbEID->lpb,
  2981. NULL,
  2982. 0,
  2983. &(bwi_lpContentsList))))
  2984. {
  2985. int nSelectedItem = ListView_GetNextItem(bwi_hWndListAB, -1, LVNI_SELECTED);
  2986. if(nSelectedItem < 0)
  2987. nSelectedItem = 0;
  2988. ListView_DeleteAllItems(bwi_hWndListAB);
  2989. if (!HR_FAILED(HrFillListView( bwi_hWndListAB,
  2990. bwi_lpContentsList)))
  2991. {
  2992. SendMessage(bwi_hWndListAB, WM_SETREDRAW, FALSE, 0);
  2993. SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, colDisplayName, &bwi_SortInfo, TRUE);
  2994. SendMessage(bwi_hWndListAB, WM_SETREDRAW, TRUE, 0);
  2995. }
  2996. if(nSelectedItem >= ListView_GetItemCount(bwi_hWndListAB))
  2997. nSelectedItem = ListView_GetItemCount(bwi_hWndListAB)-1;
  2998. LVSelectItem(bwi_hWndListAB, nSelectedItem);
  2999. }
  3000. }
  3001. ShowLVCountinStatusBar(lpbwi);
  3002. return;
  3003. }
  3004. //$$////////////////////////////////////////////////////////////////////////////////////////
  3005. //
  3006. // UpdateTVGroupSelection(HWND hWndTV, lpsbSelectEID)
  3007. //
  3008. // Updates the selected item on the TreeView to point to the item having the given
  3009. // entryid
  3010. //
  3011. //////////////////////////////////////////////////////////////////////////////////////////
  3012. void UpdateTVGroupSelection(HWND hWndTV, LPSBinary lpsbSelectEID)
  3013. {
  3014. // search for the specified group and select it ..
  3015. HTREEITEM hRoot = TreeView_GetRoot(hWndTV);
  3016. if(!lpsbSelectEID || !lpsbSelectEID->cb || !lpsbSelectEID->lpb)
  3017. {
  3018. //if(!bIsSelectedTVContainer(lpbwi))
  3019. TreeView_SelectItem(hWndTV, hRoot); //Select the Address Book
  3020. }
  3021. else
  3022. {
  3023. BOOL bSet = FALSE;
  3024. TV_ITEM tvI = {0};
  3025. tvI.mask = TVIF_PARAM | TVIF_HANDLE;
  3026. while(hRoot && !bSet)
  3027. {
  3028. HTREEITEM hItem = TreeView_GetChild(hWndTV, hRoot);
  3029. tvI.hItem = hRoot;
  3030. TreeView_GetItem(hWndTV, &tvI);
  3031. if(tvI.lParam)
  3032. {
  3033. LPTVITEM_STUFF lptvStuff = (LPTVITEM_STUFF) tvI.lParam;
  3034. if( lptvStuff && lptvStuff->lpsbEID && lptvStuff->lpsbEID->cb &&
  3035. !memcmp(lptvStuff->lpsbEID->lpb,lpsbSelectEID->lpb,lpsbSelectEID->cb))
  3036. {
  3037. TreeView_SelectItem(hWndTV, hRoot);
  3038. break;
  3039. }
  3040. }
  3041. while(hItem)
  3042. {
  3043. tvI.hItem = hItem;
  3044. TreeView_GetItem(hWndTV, &tvI);
  3045. if(tvI.lParam)
  3046. {
  3047. LPTVITEM_STUFF lptvStuff = (LPTVITEM_STUFF) tvI.lParam;
  3048. if( lptvStuff && lptvStuff->lpsbEID && lptvStuff->lpsbEID->cb &&
  3049. !memcmp(lptvStuff->lpsbEID->lpb,lpsbSelectEID->lpb,lpsbSelectEID->cb))
  3050. {
  3051. bSet = TRUE;
  3052. TreeView_SelectItem(hWndTV, hItem); //Select the Address Book
  3053. break;
  3054. }
  3055. }
  3056. hItem = TreeView_GetNextSibling(hWndTV, hItem);
  3057. }
  3058. hRoot = TreeView_GetNextSibling(hWndTV, hRoot);
  3059. }
  3060. }
  3061. return;
  3062. }
  3063. //$$////////////////////////////////////////////////////////////////////////////////////////
  3064. //
  3065. // Checks if the currently selected tree view item is a container item
  3066. // Returns true if it is a container item .. this way we can distinguish between
  3067. // groups and folders/containers
  3068. //
  3069. //////////////////////////////////////////////////////////////////////////////////////////
  3070. BOOL bIsSelectedTVContainer(LPBWI lpbwi)
  3071. {
  3072. HTREEITEM hItem = bwi_hti ? bwi_hti : TreeView_GetSelection(bwi_hWndTV);
  3073. TV_ITEM tvI = {0};
  3074. tvI.mask = TVIF_PARAM | TVIF_HANDLE;
  3075. tvI.hItem = hItem;
  3076. TreeView_GetItem(bwi_hWndTV, &tvI);
  3077. if(tvI.lParam)
  3078. return (((LPTVITEM_STUFF)tvI.lParam)->ulObjectType==MAPI_ABCONT);
  3079. return TRUE;
  3080. }
  3081. //$$////////////////////////////////////////////////////////////////////////////////////////
  3082. //
  3083. // Checks if the focus is on the TreeView or not
  3084. //
  3085. //////////////////////////////////////////////////////////////////////////////////////////
  3086. BOOL bIsFocusOnTV(LPBWI lpbwi)
  3087. {
  3088. return( IsWindowVisible(bwi_hWndTV) && (bwi_iFocus == s_TV));
  3089. }
  3090. //$$////////////////////////////////////////////////////////////////////////////////////////
  3091. //
  3092. // Gets EntryID of CurrentSelection
  3093. // lpcbEID, lppEID should be MAPIFreeBuffered
  3094. //
  3095. // bTopMost means that get the EntryID of the topmost parent of a given selection in case the
  3096. // selection is on a sub-item
  3097. //
  3098. //////////////////////////////////////////////////////////////////////////////////////////
  3099. void GetCurrentSelectionEID(LPBWI lpbwi, HWND hWndTV, LPSBinary * lppsbEID, ULONG * lpulObjectType, BOOL bTopMost)
  3100. {
  3101. HTREEITEM hItem = bwi_hti ? bwi_hti : TreeView_GetSelection(hWndTV);
  3102. TV_ITEM tvI = {0};
  3103. LPSBinary lpsbEID = NULL;
  3104. if(!lppsbEID)
  3105. return;
  3106. *lppsbEID = NULL;
  3107. if(bTopMost)
  3108. {
  3109. HTREEITEM hParent = NULL;
  3110. while(hParent = TreeView_GetParent(hWndTV, hItem))
  3111. hItem = hParent;
  3112. }
  3113. tvI.mask = TVIF_PARAM | TVIF_HANDLE;
  3114. tvI.hItem = hItem;
  3115. if(TreeView_GetItem(hWndTV, &tvI))
  3116. {
  3117. if(tvI.lParam)
  3118. {
  3119. LPTVITEM_STUFF lptvStuff = (LPTVITEM_STUFF) tvI.lParam;
  3120. if(lptvStuff)
  3121. {
  3122. if(lptvStuff->lpsbEID)
  3123. {
  3124. lpsbEID = LocalAlloc(LMEM_ZEROINIT, sizeof(SBinary));
  3125. if(lpsbEID)
  3126. {
  3127. if(lptvStuff->lpsbEID->cb)
  3128. SetSBinary(lpsbEID, lptvStuff->lpsbEID->cb, lptvStuff->lpsbEID->lpb);
  3129. *lppsbEID = lpsbEID;
  3130. }
  3131. if(lpulObjectType)
  3132. *lpulObjectType = lptvStuff->ulObjectType;
  3133. }
  3134. }
  3135. }
  3136. }
  3137. return;
  3138. }
  3139. //$$////////////////////////////////////////////////////////////////////////////////////////
  3140. //
  3141. // Removes specified group from WAB
  3142. //
  3143. //////////////////////////////////////////////////////////////////////////////////////////
  3144. HRESULT HrRemoveEntryFromWAB(LPIAB lpIAB, ULONG cbEID, LPENTRYID lpEID)
  3145. {
  3146. HRESULT hr = hrSuccess;
  3147. ULONG cbWABEID = 0;
  3148. LPENTRYID lpWABEID = NULL;
  3149. LPABCONT lpWABCont = NULL;
  3150. ULONG ulObjType;
  3151. SBinaryArray SBA;
  3152. SBinary SB;
  3153. hr = lpIAB->lpVtbl->GetPAB(lpIAB,&cbWABEID,&lpWABEID);
  3154. if(HR_FAILED(hr))
  3155. goto out;
  3156. hr = lpIAB->lpVtbl->OpenEntry(lpIAB,
  3157. cbWABEID, // size of EntryID to open
  3158. lpWABEID, // EntryID to open
  3159. NULL, // interface
  3160. 0, // flags
  3161. &ulObjType,
  3162. (LPUNKNOWN *)&lpWABCont);
  3163. if(HR_FAILED(hr))
  3164. goto out;
  3165. SB.cb = cbEID;
  3166. SB.lpb = (LPBYTE) lpEID;
  3167. SBA.cValues = 1;
  3168. SBA.lpbin = &SB;
  3169. hr = lpWABCont->lpVtbl->DeleteEntries(
  3170. lpWABCont,
  3171. (LPENTRYLIST) &SBA,
  3172. 0);
  3173. if(HR_FAILED(hr))
  3174. goto out;
  3175. out:
  3176. if(lpWABCont)
  3177. UlRelease(lpWABCont);
  3178. if(lpWABEID)
  3179. FreeBufferAndNull(&lpWABEID);
  3180. return hr;
  3181. }
  3182. //$$////////////////////////////////////////////////////////////////////////////////////
  3183. //
  3184. // FreeTVItemLParam
  3185. //
  3186. //
  3187. ////////////////////////////////////////////////////////////////////////////////////////
  3188. void FreeTVItemLParam(HWND hWndTV, HTREEITEM hItem)
  3189. {
  3190. TV_ITEM tvI = {0};
  3191. tvI.mask = TVIF_PARAM | TVIF_HANDLE;
  3192. tvI.hItem = hItem;
  3193. TreeView_GetItem(hWndTV, &tvI);
  3194. if(tvI.lParam)
  3195. {
  3196. LPTVITEM_STUFF lptvi = (LPTVITEM_STUFF) tvI.lParam;
  3197. if(lptvi)
  3198. {
  3199. // if(lptvi->ulObjectType==MAPI_DISTLIST) //only free this for groups
  3200. LocalFreeSBinary(lptvi->lpsbEID);
  3201. LocalFree(lptvi);
  3202. }
  3203. }
  3204. }
  3205. //$$////////////////////////////////////////////////////////////////////////////////////////
  3206. //
  3207. // ClearTreeViewItems - Clears the treeview of all its items
  3208. //
  3209. //////////////////////////////////////////////////////////////////////////////////////////
  3210. void FreeTreeNode(HWND hWndTV, HTREEITEM hItem)
  3211. {
  3212. HTREEITEM hTemp = NULL;
  3213. if(!hItem)
  3214. return;
  3215. FreeTVItemLParam(hWndTV, hItem);
  3216. hTemp = TreeView_GetChild(hWndTV, hItem);
  3217. while(hTemp)
  3218. {
  3219. FreeTreeNode(hWndTV, hTemp);
  3220. hTemp = TreeView_GetNextSibling(hWndTV, hTemp);
  3221. }
  3222. }
  3223. void ClearTreeViewItems(HWND hWndTV)
  3224. {
  3225. // Go through all the items and clear their lParams which we allocated earlier
  3226. HTREEITEM hRoot = TreeView_GetRoot(hWndTV);
  3227. while(hRoot)
  3228. {
  3229. FreeTreeNode(hWndTV, hRoot);
  3230. hRoot = TreeView_GetNextSibling(hWndTV, hRoot);
  3231. }
  3232. TreeView_DeleteAllItems(hWndTV);
  3233. }
  3234. //$$////////////////////////////////////////////////////////////////////////////////////////
  3235. //
  3236. // RemoveCurrentGroup - removes the currently selected group from the WAB
  3237. //
  3238. //////////////////////////////////////////////////////////////////////////////////////////
  3239. void RemoveCurrentGroup(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast)
  3240. {
  3241. HRESULT hr = E_FAIL;
  3242. // Warn the user if they really want to do this ?
  3243. if(IDYES == ShowMessageBox( hWnd, idsRemoveGroupFromAB, MB_ICONEXCLAMATION | MB_YESNO ) )
  3244. {
  3245. LPSBinary lpsbEID = NULL;
  3246. // Get the entryid of this group
  3247. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, NULL, FALSE);
  3248. if(lpsbEID)
  3249. {
  3250. HTREEITEM hItem = NULL;
  3251. // Delete the group contact from the WAB
  3252. hr = HrRemoveEntryFromWAB(bwi_lpIAB, lpsbEID->cb, (LPENTRYID)lpsbEID->lpb);
  3253. if(HR_FAILED(hr))
  3254. ShowMessageBox(hWnd, idsRemoveGroupError, MB_ICONEXCLAMATION | MB_OK);
  3255. // Remove selection from the current group
  3256. RemoveUpdateSelection(lpbwi);
  3257. // Update all
  3258. bwi_bDontRefreshLV = TRUE;
  3259. RefreshListView(lpbwi, lpftLast);
  3260. bwi_bDontRefreshLV = FALSE;
  3261. LocalFreeSBinary(lpsbEID);
  3262. }
  3263. }
  3264. }
  3265. //$$////////////////////////////////////////////////////////////////////////////////////////
  3266. //
  3267. // RemoveCurrentFolder - removes the currently selected folder and all its contents from the WAB
  3268. //
  3269. //////////////////////////////////////////////////////////////////////////////////////////
  3270. HRESULT RemoveCurrentFolder(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast)
  3271. {
  3272. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  3273. HRESULT hr = E_FAIL;
  3274. LPSPropValue lpPropArray = NULL;
  3275. SCODE sc;
  3276. ULONG i, j, cValues= 0;
  3277. SBinary sb = {0};
  3278. LPSBinary lpsbEID = NULL;
  3279. LPIAB lpIAB = bwi_lpIAB;
  3280. // Get the entryid of this folder
  3281. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, NULL, FALSE);
  3282. if( !lpsbEID || !lpsbEID->cb || !lpsbEID->lpb || // can't delete root item
  3283. (lpIAB->lpWABCurrentUserFolder && (lpsbEID->cb==lpIAB->lpWABCurrentUserFolder->sbEID.cb) && //can't delete the current users folder
  3284. !memcmp(lpsbEID->lpb, lpIAB->lpWABCurrentUserFolder->sbEID.lpb, lpsbEID->cb) ) )
  3285. {
  3286. ShowMessageBox(hWnd, idsCannotDelete, MB_OK | MB_ICONEXCLAMATION);
  3287. goto out;
  3288. }
  3289. // ignore deletions to folders in non-profile mode ...
  3290. if(!bIsWABSessionProfileAware(bwi_lpIAB) || pt_bIsWABOpenExSession)
  3291. goto out;
  3292. // Warn the user if they really want to do this ?
  3293. if(IDYES == ShowMessageBox( hWnd, idsRemoveFolderFromAB, MB_ICONEXCLAMATION | MB_YESNO ) )
  3294. {
  3295. if(lpsbEID && lpsbEID->cb && lpsbEID->lpb) // can't delete root item
  3296. {
  3297. HTREEITEM hItem = NULL;
  3298. // Open the group and read its contents
  3299. if(!HR_FAILED(hr = ReadRecord( bwi_lpIAB->lpPropertyStore->hPropertyStore,
  3300. lpsbEID, 0, &cValues, &lpPropArray)))
  3301. {
  3302. for(i=0;i<cValues;i++)
  3303. {
  3304. if(lpPropArray[i].ulPropTag == PR_WAB_FOLDER_ENTRIES)
  3305. {
  3306. for(j=0;j<lpPropArray[i].Value.MVbin.cValues;j++)
  3307. {
  3308. hr = HrRemoveEntryFromWAB(bwi_lpIAB,
  3309. lpPropArray[i].Value.MVbin.lpbin[j].cb,
  3310. (LPENTRYID)lpPropArray[i].Value.MVbin.lpbin[j].lpb);
  3311. }
  3312. }
  3313. }
  3314. // Delete the group contact from the WAB
  3315. hr = DeleteRecord( bwi_lpIAB->lpPropertyStore->hPropertyStore, lpsbEID);
  3316. if(HR_FAILED(hr) && hr!=MAPI_E_INVALID_ENTRYID)
  3317. ShowMessageBox(hWnd, idsRemoveFolderError, MB_ICONEXCLAMATION | MB_OK);
  3318. // Remove selection from the current group
  3319. RemoveUpdateSelection(lpbwi);
  3320. // Update all
  3321. bwi_bDontRefreshLV = TRUE;
  3322. HrGetWABProfiles(bwi_lpIAB);
  3323. RefreshListView(lpbwi, lpftLast);
  3324. bwi_bDontRefreshLV = FALSE;
  3325. }
  3326. ReadRecordFreePropArray(NULL, cValues, &lpPropArray);
  3327. }
  3328. }
  3329. out:
  3330. LocalFreeSBinary(lpsbEID);
  3331. return hr;
  3332. }
  3333. //$$////////////////////////////////////////////////////////////////////////////////////////
  3334. //
  3335. // RemovesSelectedItems from the listview
  3336. //
  3337. // lpList is the ContentsList associated with the ListView which needs
  3338. // to be kept updated
  3339. //
  3340. //////////////////////////////////////////////////////////////////////////////////////////
  3341. void RemoveSelectedItemsFromListView(HWND hWndLV, LPRECIPIENT_INFO * lppList)
  3342. {
  3343. int iItemIndex = 0;
  3344. if(ListView_GetSelectedCount(hWndLV) <= 0)
  3345. goto exit;
  3346. SendMessage(hWndLV, WM_SETREDRAW, (WPARAM) FALSE, 0);
  3347. // Start removing from the bottom up
  3348. iItemIndex = ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED);
  3349. while(iItemIndex != -1)
  3350. {
  3351. // Get the entryid of the selected item
  3352. LPRECIPIENT_INFO lpItem = GetItemFromLV(hWndLV, iItemIndex);
  3353. if(lpItem)
  3354. {
  3355. if(lpItem->lpNext)
  3356. lpItem->lpNext->lpPrev = lpItem->lpPrev;
  3357. if(lpItem->lpPrev)
  3358. lpItem->lpPrev->lpNext = lpItem->lpNext;
  3359. if(lppList && *lppList == lpItem)
  3360. *lppList = lpItem->lpNext;
  3361. FreeRecipItem(&lpItem);
  3362. }
  3363. ListView_DeleteItem(hWndLV, iItemIndex);
  3364. iItemIndex = ListView_GetNextItem(hWndLV, iItemIndex-1, LVNI_SELECTED);
  3365. }
  3366. SendMessage(hWndLV, WM_SETREDRAW, (WPARAM) TRUE, 0);
  3367. exit:
  3368. return;
  3369. }
  3370. //$$////////////////////////////////////////////////////////////////////////////////////////
  3371. //
  3372. // Removes selected items from the group and the WAB, if specified
  3373. //
  3374. //////////////////////////////////////////////////////////////////////////////////////////
  3375. void RemoveSelectedItemsFromCurrentGroup(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast, BOOL bRemoveFromWAB)
  3376. {
  3377. // We want to remove the selected items from the current group and also
  3378. // remove them from the ListView ...
  3379. LPSBinary lpsbEID = NULL;
  3380. ULONG ulcValues = 0;
  3381. LPSPropValue lpPropArray = NULL;
  3382. HRESULT hr = S_OK;
  3383. LPMAILUSER lpMailUser = NULL;
  3384. ULONG ulObjType = 0;
  3385. ULONG i,j;
  3386. ULONG ulDLEntriesIndex = 0;
  3387. int id = (bRemoveFromWAB) ? idsRemoveSelectedFromGroupAndAB : idsRemoveSelectedFromGroup;
  3388. if( ListView_GetSelectedCount(bwi_hWndListAB) <= 0)
  3389. goto exit;
  3390. if(IDNO == ShowMessageBox(hWnd, id, MB_ICONEXCLAMATION | MB_YESNO))
  3391. goto exit;
  3392. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, NULL, FALSE);
  3393. if(!lpsbEID)
  3394. goto exit;
  3395. if (HR_FAILED(hr = bwi_lpAdrBook->lpVtbl->OpenEntry(bwi_lpAdrBook,
  3396. lpsbEID->cb, // cbEntryID
  3397. (LPENTRYID)lpsbEID->lpb, // entryid
  3398. NULL, // interface
  3399. MAPI_MODIFY, // ulFlags
  3400. &ulObjType, // returned object type
  3401. (LPUNKNOWN *)&lpMailUser)))
  3402. {
  3403. // Failed! Hmmm.
  3404. DebugTraceResult( TEXT("Address: IAB->OpenEntry:"), hr);
  3405. goto exit;
  3406. }
  3407. Assert(lpMailUser);
  3408. if (HR_FAILED(hr = lpMailUser->lpVtbl->GetProps(lpMailUser,
  3409. NULL, // lpPropTagArray
  3410. MAPI_UNICODE, // ulFlags
  3411. &ulcValues, // how many properties were there?
  3412. &lpPropArray)))
  3413. {
  3414. DebugTraceResult( TEXT("Address: IAB->GetProps:"), hr);
  3415. goto exit;
  3416. }
  3417. // Scan these props for the PR_WAB_DL_ENTRIES
  3418. // We ignore PR_WAB_DL_ONEOFFS here because technically you can't have one-offs in the Browse view therefore
  3419. // should never need to delete OneOffs in this function
  3420. for(i=0;i<ulcValues;i++)
  3421. {
  3422. if(lpPropArray[i].ulPropTag == PR_WAB_DL_ENTRIES)
  3423. {
  3424. ulDLEntriesIndex = i;
  3425. break;
  3426. }
  3427. }
  3428. if(!ulDLEntriesIndex)
  3429. goto exit;
  3430. {
  3431. // cycle through the list view items entryids
  3432. int iItemIndex = ListView_GetNextItem(bwi_hWndListAB, -1, LVNI_SELECTED);
  3433. while(iItemIndex != -1)
  3434. {
  3435. // Get the entryid of the selected item
  3436. ULONG cbItemEID = 0;
  3437. LPENTRYID lpItemEID = NULL;
  3438. LPRECIPIENT_INFO lpItem = GetItemFromLV(bwi_hWndListAB, iItemIndex);
  3439. if(lpItem)
  3440. {
  3441. RemovePropFromMVBin(lpPropArray,
  3442. ulcValues,
  3443. ulDLEntriesIndex,
  3444. (LPVOID) lpItem->lpEntryID,
  3445. lpItem->cbEntryID);
  3446. if(bRemoveFromWAB)
  3447. {
  3448. // Delete the group contact from the WAB
  3449. // Note; This is very inefficient - we should ideally create a
  3450. // SBinaryArray and call deleteentries all at once
  3451. // We'll leave that for some later time <TBD> <BUGBUG>
  3452. hr = HrRemoveEntryFromWAB(bwi_lpIAB, lpItem->cbEntryID, lpItem->lpEntryID);
  3453. }
  3454. }
  3455. iItemIndex = ListView_GetNextItem(bwi_hWndListAB, iItemIndex, LVNI_SELECTED);
  3456. }
  3457. }
  3458. // Knock out the PR_WAB_DL_ENTRIES property so we can overwrite it
  3459. {
  3460. if (HR_FAILED(hr = lpMailUser->lpVtbl->DeleteProps(lpMailUser,
  3461. (LPSPropTagArray) &tagaDLEntriesProp,
  3462. NULL)))
  3463. {
  3464. DebugTraceResult( TEXT("IAB->DeleteProps:"), hr);
  3465. goto exit;
  3466. }
  3467. }
  3468. if (HR_FAILED(hr = lpMailUser->lpVtbl->SetProps(lpMailUser,
  3469. ulcValues,
  3470. lpPropArray,
  3471. NULL)))
  3472. {
  3473. DebugTraceResult( TEXT("Address: IAB->GetProps:"), hr);
  3474. goto exit;
  3475. }
  3476. if(HR_FAILED(hr = lpMailUser->lpVtbl->SaveChanges(lpMailUser, KEEP_OPEN_READONLY)))
  3477. {
  3478. DebugTraceResult( TEXT("SaveChanges failed: "), hr);
  3479. goto exit;
  3480. }
  3481. // update the file stamp
  3482. //if (lpftLast) {
  3483. // CheckChangedWAB(bwi_lpIAB->lpPropertyStore, lpftLast);
  3484. //}
  3485. bwi_bDeferNotification = TRUE;
  3486. RemoveSelectedItemsFromListView(bwi_hWndListAB, &bwi_lpContentsList);
  3487. exit:
  3488. if(lpsbEID)
  3489. LocalFreeSBinary(lpsbEID);
  3490. if(lpPropArray)
  3491. MAPIFreeBuffer(lpPropArray);
  3492. if(lpMailUser)
  3493. lpMailUser->lpVtbl->Release(lpMailUser);
  3494. return;
  3495. }
  3496. //$$////////////////////////////////////////////////////////////////////////////////////////
  3497. //
  3498. // Shows properties on the currently selected group or folder
  3499. //
  3500. //////////////////////////////////////////////////////////////////////////////////////////
  3501. void ViewCurrentGroupProperties(LPBWI lpbwi, LPFILETIME lpftLast)
  3502. {
  3503. LPSBinary lpsbEID = NULL;
  3504. HWND hWnd = GetParent(bwi_hWndTV);
  3505. ULONG ulObjectType = 0;
  3506. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjectType, FALSE);
  3507. if(lpsbEID && (ulObjectType==MAPI_DISTLIST))
  3508. {
  3509. bwi_lpAdrBook->lpVtbl->Details( bwi_lpAdrBook,
  3510. (PULONG_PTR) &hWnd,
  3511. NULL,
  3512. NULL,
  3513. lpsbEID->cb,
  3514. (LPENTRYID)lpsbEID->lpb,
  3515. NULL,
  3516. NULL,
  3517. NULL,
  3518. 0);
  3519. // if the item name changed, update it
  3520. {
  3521. LPRECIPIENT_INFO lpInfo = NULL;
  3522. ReadSingleContentItem( bwi_lpAdrBook,
  3523. lpsbEID->cb,
  3524. (LPENTRYID) lpsbEID->lpb,
  3525. &lpInfo);
  3526. if(lpInfo)
  3527. {
  3528. TV_ITEM tvi = {0};
  3529. tvi.hItem = bwi_hti ? bwi_hti : TreeView_GetSelection(bwi_hWndTV);
  3530. tvi.mask = TVIF_HANDLE;
  3531. TreeView_GetItem(bwi_hWndTV, &tvi);
  3532. tvi.mask |= TVIF_TEXT;
  3533. tvi.pszText = lpInfo->szDisplayName;
  3534. tvi.cchTextMax = lstrlen(tvi.pszText)+1;
  3535. TreeView_SetItem(bwi_hWndTV, &tvi);
  3536. FreeRecipItem(&lpInfo);
  3537. }
  3538. }
  3539. UpdateListViewContents(lpbwi, lpsbEID, ulObjectType);
  3540. // Update the wab file write time so the timer doesn't
  3541. // catch this change and refresh.
  3542. //if (lpftLast) {
  3543. // CheckChangedWAB(bwi_lpIAB->lpPropertyStore, lpftLast);
  3544. //}
  3545. bwi_bDeferNotification = TRUE;
  3546. }
  3547. else if(lpsbEID //&& lpsbEID->cb && lpsbEID->lpb
  3548. && (ulObjectType==MAPI_ABCONT)
  3549. && bIsWABSessionProfileAware(bwi_lpIAB))
  3550. {
  3551. // view properties on the folder entry
  3552. if(!HR_FAILED(HrFolderProperties(GetParent(bwi_hWndTV), bwi_lpIAB, lpsbEID, NULL, NULL)))
  3553. {
  3554. //UpdateViewFoldersMenu(lpbwi, hWnd);
  3555. RefreshListView(lpbwi,lpftLast);
  3556. }
  3557. }
  3558. if(lpsbEID)
  3559. LocalFreeSBinary(lpsbEID);
  3560. return;
  3561. }
  3562. //$$////////////////////////////////////////////////////////////////////////////////////////
  3563. //
  3564. // Processes messages for the TREE view control
  3565. //
  3566. //////////////////////////////////////////////////////////////////////////////////////////
  3567. LRESULT ProcessTreeViewMessages(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPFILETIME lpftLast)
  3568. {
  3569. NM_TREEVIEW * pNm = (NM_TREEVIEW *)lParam;
  3570. switch(pNm->hdr.code)
  3571. {
  3572. case NM_SETFOCUS:
  3573. UpdateToolbarAndMenu(lpbwi);
  3574. break;
  3575. case TVN_KEYDOWN:
  3576. //UpdateToolbarAndMenu(lpbwi);
  3577. switch(((LV_KEYDOWN FAR *) lParam)->wVKey)
  3578. {
  3579. case VK_DELETE:
  3580. SendMessage (hWnd, WM_COMMAND, (WPARAM) IDM_FILE_DELETE, 0);
  3581. return 0;
  3582. break;
  3583. case VK_RETURN:
  3584. SendMessage (hWnd, WM_COMMAND, (WPARAM) IDM_FILE_PROPERTIES, 0);
  3585. return 0;
  3586. }
  3587. break;
  3588. case TVN_SELCHANGEDW:
  3589. case TVN_SELCHANGEDA:
  3590. {
  3591. if(!bwi_bDontRefreshLV)
  3592. UpdateLV(lpbwi);
  3593. UpdateToolbarAndMenu(lpbwi);
  3594. }
  3595. break;
  3596. }
  3597. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  3598. }
  3599. BOOL SplitterHitTest(HWND hWndT, LPARAM lParam)
  3600. {
  3601. LONG xPos = LOWORD(lParam);
  3602. LONG yPos = HIWORD(lParam);
  3603. RECT rc;
  3604. if(!IsWindowVisible(hWndT))
  3605. return FALSE;
  3606. GetChildClientRect(hWndT, &rc);
  3607. if( (xPos <= rc.right) && (xPos >= rc.left) &&
  3608. (yPos <= rc.bottom) && (yPos >= rc.top) )
  3609. return TRUE;
  3610. else
  3611. return FALSE;
  3612. }
  3613. /////////////////////////////////////////
  3614. // Stolen (essentially) from COMMCTRL
  3615. HBITMAP FAR PASCAL CreateDitherBitmap(COLORREF crFG, COLORREF crBG)
  3616. {
  3617. PBITMAPINFO pbmi;
  3618. HBITMAP hbm;
  3619. HDC hdc;
  3620. int i;
  3621. long patGray[8];
  3622. DWORD rgb;
  3623. pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 16));
  3624. if (!pbmi)
  3625. return NULL;
  3626. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  3627. pbmi->bmiHeader.biWidth = 8;
  3628. pbmi->bmiHeader.biHeight = 8;
  3629. pbmi->bmiHeader.biPlanes = 1;
  3630. pbmi->bmiHeader.biBitCount = 1;
  3631. pbmi->bmiHeader.biCompression = BI_RGB;
  3632. rgb = crBG;
  3633. pbmi->bmiColors[0].rgbBlue = GetBValue(rgb);
  3634. pbmi->bmiColors[0].rgbGreen = GetGValue(rgb);
  3635. pbmi->bmiColors[0].rgbRed = GetRValue(rgb);
  3636. pbmi->bmiColors[0].rgbReserved = 0;
  3637. rgb = crFG;
  3638. pbmi->bmiColors[1].rgbBlue = GetBValue(rgb);
  3639. pbmi->bmiColors[1].rgbGreen = GetGValue(rgb);
  3640. pbmi->bmiColors[1].rgbRed = GetRValue(rgb);
  3641. pbmi->bmiColors[1].rgbReserved = 0;
  3642. /* initialize the brushes */
  3643. for (i = 0; i < 8; i++)
  3644. if (i & 1)
  3645. patGray[i] = 0xAAAA5555L; // 0x11114444L; // lighter gray
  3646. else
  3647. patGray[i] = 0x5555AAAAL; // 0x11114444L; // lighter gray
  3648. hdc = GetDC(NULL);
  3649. // REVIEW: We cast am array of long to (BYTE const *). Is it ok for Win32?
  3650. hbm = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT,
  3651. (BYTE const *)patGray, pbmi, DIB_RGB_COLORS);
  3652. ReleaseDC(NULL, hdc);
  3653. LocalFree(pbmi);
  3654. return hbm;
  3655. }
  3656. // Stolen (essentially) from COMMCTRL
  3657. HBRUSH FAR PASCAL CreateDitherBrush(COLORREF crFG, COLORREF crBG)
  3658. {
  3659. HBITMAP hbm;
  3660. HBRUSH hbrRet = NULL;
  3661. hbm = CreateDitherBitmap(crFG, crBG);
  3662. if (hbm)
  3663. {
  3664. hbrRet = CreatePatternBrush(hbm);
  3665. DeleteObject(hbm);
  3666. }
  3667. return(hbrRet);
  3668. }
  3669. //////////////////////////////////////////
  3670. // Stolen from Athena
  3671. void DragSplitterBar(LPBWI lpbwi, HWND hwnd, HWND hWndT, LPARAM lParam)
  3672. {
  3673. MSG msg;
  3674. int x, y, dx, dy;
  3675. RECT rcSplitter;
  3676. RECT rc;
  3677. HDC hdc;
  3678. LONG lStyle;
  3679. HBRUSH hbrDither, hbrOld;
  3680. int nAccel = 2;
  3681. lStyle = GetWindowLong(hwnd, GWL_STYLE);
  3682. SetWindowLong(hwnd, GWL_STYLE, (lStyle & ~WS_CLIPCHILDREN));
  3683. GetChildClientRect(hWndT, &rcSplitter);
  3684. //GetWindowRect(hWndT, &rcSplitter);
  3685. x = rcSplitter.left;
  3686. y = rcSplitter.top;
  3687. dx = rcSplitter.right - rcSplitter.left;
  3688. dy = rcSplitter.bottom - rcSplitter.top;
  3689. GetWindowRect(hwnd, &rc);
  3690. hdc = GetDC(hwnd);
  3691. hbrDither = CreateDitherBrush(RGB(255, 255, 255), RGB(0, 0, 0));
  3692. if (hbrDither)
  3693. hbrOld = (HBRUSH)SelectObject(hdc, (HGDIOBJ)hbrDither);
  3694. // split bar loop...
  3695. PatBlt(hdc, x, y, dx, dy, PATINVERT);
  3696. SetCapture(hwnd);
  3697. while (GetMessage(&msg, NULL, 0, 0))
  3698. {
  3699. if ( msg.message == WM_LBUTTONUP ||
  3700. msg.message == WM_LBUTTONDOWN ||
  3701. msg.message == WM_RBUTTONDOWN)
  3702. break;
  3703. if (GetCapture() != hwnd)
  3704. {
  3705. msg.message = WM_RBUTTONDOWN; // treat as cancel
  3706. break;
  3707. }
  3708. if ( msg.message == WM_KEYDOWN ||
  3709. msg.message == WM_SYSKEYDOWN ||
  3710. (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) )
  3711. {
  3712. if (msg.message == WM_KEYDOWN)
  3713. {
  3714. nAccel = 4;
  3715. if (msg.wParam == VK_LEFT)
  3716. {
  3717. msg.message = WM_MOUSEMOVE;
  3718. msg.pt.x -= nAccel/2;
  3719. }
  3720. else if (msg.wParam == VK_RIGHT)
  3721. {
  3722. msg.message = WM_MOUSEMOVE;
  3723. msg.pt.x += nAccel/2;
  3724. }
  3725. else if ( msg.wParam == VK_RETURN ||
  3726. msg.wParam == VK_ESCAPE)
  3727. {
  3728. break;
  3729. }
  3730. if (msg.pt.x > rc.right)
  3731. msg.pt.x = rc.right;
  3732. if (msg.pt.x < rc.left)
  3733. msg.pt.x = rc.left;
  3734. SetCursorPos(msg.pt.x, msg.pt.y);
  3735. }
  3736. if (msg.message == WM_MOUSEMOVE)
  3737. {
  3738. int lo, hi;
  3739. if (msg.pt.x > rc.right)
  3740. msg.pt.x = rc.right;
  3741. if (msg.pt.x < rc.left)
  3742. msg.pt.x = rc.left;
  3743. ScreenToClient(hwnd, &msg.pt);
  3744. // Clip out the parts we don't want so
  3745. // that we do a single PatBlt (less
  3746. // flicker for small movements).
  3747. if (x < msg.pt.x)
  3748. {
  3749. lo = x;
  3750. hi = msg.pt.x;
  3751. }
  3752. else
  3753. {
  3754. lo = msg.pt.x;
  3755. hi = x;
  3756. }
  3757. if (hi < lo+dx)
  3758. {
  3759. ExcludeClipRect(hdc, hi, y, lo+dx, y+dy);
  3760. }
  3761. else
  3762. {
  3763. ExcludeClipRect(hdc, lo+dx, y, hi, y+dy);
  3764. }
  3765. // Erase the old and draw the new in one draw.
  3766. PatBlt(hdc, lo, y, hi-lo+dx, dy, PATINVERT);
  3767. SelectClipRgn(hdc, NULL);
  3768. x = msg.pt.x;
  3769. }
  3770. }
  3771. else
  3772. {
  3773. DispatchMessage(&msg);
  3774. }
  3775. }
  3776. ReleaseCapture();
  3777. // erase old
  3778. PatBlt(hdc, x, y, dx, dy, PATINVERT);
  3779. if (hbrDither)
  3780. {
  3781. if (hbrOld)
  3782. SelectObject(hdc, hbrOld);
  3783. DeleteObject(hbrDither);
  3784. }
  3785. ReleaseDC(hwnd, hdc);
  3786. SetWindowLong(hwnd, GWL_STYLE, lStyle);
  3787. if (msg.wParam != VK_ESCAPE && msg.message != WM_RBUTTONDOWN && msg.message != WM_CAPTURECHANGED)
  3788. {
  3789. RECT rcTV;
  3790. GetChildClientRect(bwi_hWndTV, &rcTV);
  3791. MoveWindow(bwi_hWndTV, rcTV.left, rcTV.top, x, rcTV.bottom - rcTV.top, TRUE);
  3792. ResizeAddressBookChildren(lpbwi, hwnd);
  3793. InvalidateRect( bwi_hWndSplitter,NULL,TRUE);
  3794. InvalidateRect( bwi_hWndEditQF,NULL,TRUE);
  3795. InvalidateRect( bwi_hWndStaticQF,NULL,TRUE);
  3796. InvalidateRect( hwnd,NULL,TRUE);
  3797. RedrawWindow( hwnd, NULL, NULL,
  3798. RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW | RDW_UPDATENOW );
  3799. RedrawWindow( bwi_hWndEditQF, NULL, NULL,
  3800. RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW | RDW_UPDATENOW );
  3801. }
  3802. return;
  3803. }
  3804. //$$//////////////////////////////////////////////////////////////////////////////
  3805. //
  3806. // Opens a VCard and adds it to the WAB and to the Current group
  3807. // szVCardFIle can be a NULL in which case we open the OpenFile dialog
  3808. //
  3809. //////////////////////////////////////////////////////////////////////////////////
  3810. HRESULT OpenAndAddVCard(LPBWI lpbwi, LPTSTR szVCardFile)
  3811. {
  3812. HRESULT hr = S_OK;
  3813. LPSPropValue lpProp = NULL;
  3814. hr = VCardImport(bwi_hWndAB, bwi_lpAdrBook, szVCardFile, &lpProp);
  3815. // if the above failed, then the lpProp will have nothing in it
  3816. // in cases where there are multiple nested vcards, the error could
  3817. // be from one vcard, but the rest may have imported .. if they
  3818. // imported successfully then lpProp will have something in it ..
  3819. // so use lpProp instead of hr ..
  3820. if(lpProp)
  3821. {
  3822. if(HR_FAILED(hr))
  3823. hr = MAPI_W_ERRORS_RETURNED;
  3824. bwi_bDontRefreshLV = TRUE;
  3825. if(lpProp && PROP_TYPE(lpProp->ulPropTag) == PT_MV_BINARY)
  3826. {
  3827. if(!bIsSelectedTVContainer(lpbwi))
  3828. {
  3829. LPSBinary lpsbEIDGroup = NULL;
  3830. ULONG ulObjectType = 0;
  3831. bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
  3832. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEIDGroup, &ulObjectType, FALSE);
  3833. if(lpsbEIDGroup)
  3834. {
  3835. ULONG i = 0;
  3836. for(i=0;i<lpProp->Value.MVbin.cValues;i++)
  3837. {
  3838. hr = AddEntryToContainer(bwi_lpAdrBook, ulObjectType,
  3839. lpsbEIDGroup->cb, (LPENTRYID) lpsbEIDGroup->lpb,
  3840. lpProp->Value.MVbin.lpbin[i].cb,
  3841. (LPENTRYID) lpProp->Value.MVbin.lpbin[i].lpb);
  3842. }
  3843. }
  3844. }
  3845. }
  3846. FreeBufferAndNull(&lpProp);
  3847. bwi_bDontRefreshLV = FALSE;
  3848. // if updated and showing PAB, refresh list
  3849. SendMessage(bwi_hWndAB, WM_COMMAND, (WPARAM) IDM_VIEW_REFRESH, 0);
  3850. }
  3851. return hr;
  3852. }
  3853. //$$
  3854. // Updates the switch-user's menu if this is not a wab.exe initiated call
  3855. //
  3856. //
  3857. void UpdateSwitchUsersMenu(HWND hWnd, LPIAB lpIAB)
  3858. {
  3859. if( memcmp(&lpIAB->guidPSExt, &MPSWab_GUID_V4, sizeof(GUID)) ||
  3860. !bIsThereACurrentUser(lpIAB) || !bAreWABAPIProfileAware(lpIAB))
  3861. {
  3862. HMENU hMenuMain = GetMenu(hWnd);
  3863. HMENU hMenuFile = GetSubMenu(hMenuMain,idmFile);
  3864. // Need to remove the print and the seperator
  3865. RemoveMenu(hMenuFile, idmFSep5, MF_BYPOSITION);
  3866. RemoveMenu(hMenuFile, idmAllContents, MF_BYPOSITION);
  3867. RemoveMenu(hMenuFile, idmSwitchUsers, MF_BYPOSITION);
  3868. DrawMenuBar(hWnd);
  3869. }
  3870. }
  3871. //$$
  3872. //
  3873. // Turns of the print menu if requested to do so
  3874. //
  3875. //
  3876. void UpdatePrintMenu(HWND hWnd)
  3877. {
  3878. if(!bPrintingOn)
  3879. {
  3880. HMENU hMenuMain = GetMenu(hWnd);
  3881. HMENU hMenuFile = GetSubMenu(hMenuMain,idmFile);
  3882. // Need to remove the print and the seperator
  3883. RemoveMenu(hMenuFile, idmFSep4, MF_BYPOSITION);
  3884. RemoveMenu(hMenuFile, idmPrint, MF_BYPOSITION);
  3885. DrawMenuBar(hWnd);
  3886. }
  3887. return;
  3888. }
  3889. /*
  3890. -
  3891. - UpdateViewFoldersMenu
  3892. -
  3893. *
  3894. *
  3895. */
  3896. void UpdateViewFoldersMenu(LPBWI lpbwi, HWND hWnd)
  3897. {
  3898. #ifdef FUTURE
  3899. HMENU hMenuMain = GetMenu(hWnd);
  3900. HMENU hMenuFile = GetSubMenu(hMenuMain,idmFile);
  3901. HMENU hMenu = GetSubMenu(hMenuFile, idmFolders);
  3902. LPIAB lpIAB = bwi_lpIAB;
  3903. int i = 0;
  3904. // If profiles are not enabled or there are no subfolders, remove the folder option completely
  3905. if(!bDoesThisWABHaveAnyUsers(lpIAB))
  3906. {
  3907. // remove all folder options:
  3908. // Remove the Folders option from the View Menu
  3909. RemoveMenu(hMenuFile, idmSepFolders, MF_BYPOSITION);
  3910. RemoveMenu(hMenuFile, idmFolders, MF_BYPOSITION);
  3911. goto out;
  3912. }
  3913. else
  3914. {
  3915. // removing screws up numbering and svrewss up access to other folders
  3916. // so just disable
  3917. EnableMenuItem(hMenuFile, idmSepFolders, MF_BYPOSITION | (lpIAB->lpWABFolders ? MF_ENABLED : MF_GRAYED));
  3918. EnableMenuItem(hMenuFile, idmFolders, MF_BYPOSITION | (lpIAB->lpWABFolders ? MF_ENABLED : MF_GRAYED));
  3919. if(lpIAB->lpWABFolders)
  3920. AddFolderListToMenu(hMenu, lpIAB);
  3921. goto out;
  3922. }
  3923. // if there is only 1 folder in the wab and this is the shared folder
  3924. // then disable the folder item because there is nothing to be done
  3925. //if( !bIsThereACurrentUser(lpIAB) )
  3926. //{
  3927. // EnableMenuItem(hMenuView, idmFolders, MF_BYPOSITION | MF_GRAYED);
  3928. // goto out;
  3929. //}
  3930. out:
  3931. #endif // FUTURE
  3932. return;
  3933. }
  3934. //$$
  3935. // UpdateOutlookMenus
  3936. //
  3937. // Some menus are not accessible when running from outlook
  3938. //
  3939. // Tools | Options Menu should not be accessible from WAB when
  3940. // outlook is in Full MAPI mode because then Outlook doesnt use
  3941. // WAB and we dont want to give the option to the user of
  3942. // switching to the WAB
  3943. //
  3944. void UpdateOutlookMenus(HWND hWnd)
  3945. {
  3946. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  3947. BOOL bNoOptions = TRUE;
  3948. HMENU hMenuMain = GetMenu(hWnd);
  3949. HMENU hMenuFile = NULL;
  3950. HMENU hMenu = NULL;
  3951. if( pt_bIsWABOpenExSession &&
  3952. lpfnAllocateBufferExternal && // **ASSUMPTION** that Outlook always
  3953. lpfnAllocateMoreExternal && lpfnFreeBufferExternal) // passes in memory allocators ..!!!
  3954. {
  3955. /*
  3956. hMenuFile = GetSubMenu(hMenuMain, idmFile);
  3957. {
  3958. // Need to remove the import AddressBook and Export Addressbook options
  3959. hMenu = GetSubMenu(hMenuFile, idmImport);
  3960. RemoveMenu(hMenu, IDM_TOOLS_IMPORT_OTHER, MF_BYCOMMAND);
  3961. hMenu = GetSubMenu(hMenuFile, idmExport);
  3962. RemoveMenu(hMenu, IDM_TOOLS_EXPORT_OTHER, MF_BYCOMMAND);
  3963. RemoveMenu(hMenu, IDM_TOOLS_EXPORT_WAB, MF_BYCOMMAND);
  3964. }
  3965. */
  3966. /*
  3967. // [PaulHi] 12/18/98 Raid #62640
  3968. // Disable the Import/Export menu items before anything is removed and
  3969. // order gets messed up.
  3970. EnableMenuItem(hMenuFile, idmImport, MF_GRAYED | MF_BYPOSITION);
  3971. EnableMenuItem(hMenuFile, idmExport, MF_GRAYED | MF_BYPOSITION);
  3972. //Also remove New Folder menu
  3973. RemoveMenu(hMenuFile, IDM_FILE_NEWFOLDER, MF_BYCOMMAND);
  3974. */
  3975. }
  3976. else
  3977. {
  3978. // Not called from Outlook ...
  3979. // check if Outlook is using the WAB .. if it isnt, we dont want
  3980. // to show the Tools Options menu
  3981. //
  3982. HKEY hKey = NULL;
  3983. LPTSTR lpReg = TEXT("Software\\Microsoft\\Office\\8.0\\Outlook\\Setup");
  3984. LPTSTR lpOMI = TEXT("MailSupport");
  3985. BOOL bUsingWAB = FALSE;
  3986. if(ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, lpReg, 0, KEY_READ, &hKey))
  3987. {
  3988. DWORD dwType = 0, dwSize = sizeof(DWORD), dwData = 0;
  3989. if(ERROR_SUCCESS == RegQueryValueEx(hKey, lpOMI, NULL, &dwType, (LPBYTE)&dwData, &dwSize))
  3990. {
  3991. if(dwType == REG_DWORD && dwData == 0)
  3992. bUsingWAB = TRUE;
  3993. }
  3994. }
  3995. if(hKey)
  3996. RegCloseKey(hKey);
  3997. bNoOptions = !bUsingWAB;
  3998. }
  3999. // [PaulHi] 1/4/99 The pt_bIsWABOpenExSession variable is mis-named. This
  4000. // boolean used to be true only if the WAB was opened from WABOpenEx, i.e,
  4001. // by Outlook using the Outlook store. However, this boolean is now true in
  4002. // the case where the WAB is open from WABOpen but still uses the Outlook
  4003. // store because it is in "shared mode", i.e., the use outlook store registry
  4004. // setting is true.
  4005. if(pt_bIsWABOpenExSession)
  4006. {
  4007. //Also remove New Folder menu
  4008. hMenuFile = GetSubMenu(hMenuMain, idmFile);
  4009. // [PaulHi] 1/4/99 Raid #64016
  4010. // Disable the Import/Export menu items before anything is removed and
  4011. // order gets messed up.
  4012. // This is similar to Raid #62640 except we need to disable import/export
  4013. // WHENEVER the WAB is opened to use the Outlook store since it doesn't
  4014. // know how to import/export Outlook store information.
  4015. EnableMenuItem(hMenuFile, idmImport, MF_GRAYED | MF_BYPOSITION);
  4016. EnableMenuItem(hMenuFile, idmExport, MF_GRAYED | MF_BYPOSITION);
  4017. RemoveMenu(hMenuFile, IDM_FILE_NEWFOLDER, MF_BYCOMMAND);
  4018. // [PaulHi] 3/22/99 Raid 73457 Remove the Profile... Edit menu item
  4019. // since profiles are turned off when in Outlook mode
  4020. hMenu = GetSubMenu(hMenuMain, idmEdit);
  4021. RemoveMenu(hMenu, IDM_EDIT_SETME, MF_BYCOMMAND); // Profile... menu item
  4022. RemoveMenu(hMenu, 5, MF_BYPOSITION); // Seperator
  4023. }
  4024. if(bNoOptions)
  4025. {
  4026. // Hide the tools options option
  4027. //
  4028. hMenuFile = GetSubMenu(hMenuMain,idmTools);
  4029. // Need to remove the second-last and third-last items
  4030. RemoveMenu(hMenuFile, 3, MF_BYPOSITION); //Seperator
  4031. RemoveMenu(hMenuFile, 2, MF_BYPOSITION); //Options
  4032. DrawMenuBar(hWnd);
  4033. }
  4034. return;
  4035. }
  4036. void UpdateCustomColumnMenuText(HWND hWnd)
  4037. {
  4038. HMENU hMenuMain = GetMenu(hWnd);
  4039. HMENU hMenuView = GetSubMenu(hMenuMain, idmView);
  4040. int nDiff = idmViewMax - GetMenuItemCount(hMenuView); // in case stuff was deleted off this menu
  4041. HMENU hMenu = GetSubMenu(hMenuView, idmSortBy - nDiff);
  4042. MENUITEMINFO mii = {0};
  4043. mii.cbSize = sizeof(MENUITEMINFO);
  4044. mii.fMask = MIIM_TYPE;
  4045. mii.fType = MFT_STRING;
  4046. if(PR_WAB_CUSTOMPROP1 && lstrlen(szCustomProp1))
  4047. {
  4048. mii.dwTypeData = (LPTSTR) szCustomProp1;
  4049. mii.cch = lstrlen(szCustomProp1) + 1;
  4050. SetMenuItemInfo(hMenu, 3, TRUE, &mii);
  4051. }
  4052. if(PR_WAB_CUSTOMPROP2 && lstrlen(szCustomProp2))
  4053. {
  4054. mii.dwTypeData = (LPVOID) szCustomProp2;
  4055. mii.cch = lstrlen(szCustomProp2) + 1;
  4056. SetMenuItemInfo(hMenu, 2, TRUE, &mii);
  4057. }
  4058. DrawMenuBar(hWnd);
  4059. return;
  4060. }
  4061. //$$
  4062. // bCheckForOutlook
  4063. // Checks if the Outlook Contact Store is available
  4064. //
  4065. // If this is an outlook session, this is true by default
  4066. // Otherwise hunt for presence of outlwab.dll
  4067. //
  4068. BOOL bCheckForOutlook()
  4069. {
  4070. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  4071. if(pt_bIsWABOpenExSession)
  4072. return TRUE;
  4073. // Not an outlook session ..
  4074. // Look for OutlWAB.Dll
  4075. return bCheckForOutlookWABDll(NULL, 0);
  4076. }
  4077. //$$
  4078. //
  4079. // Dialog proc for the options dialog
  4080. //
  4081. /*//$$************************************************************************
  4082. //
  4083. // fnSearch - Search Dialog Proc
  4084. //
  4085. **************************************************************************/
  4086. INT_PTR CALLBACK fnOptionsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  4087. {
  4088. switch(message)
  4089. {
  4090. case WM_INITDIALOG:
  4091. {
  4092. if(!bCheckForOutlook()) //<TBD> - No Outlook 98 is installed
  4093. {
  4094. // Disable the Outlook option
  4095. EnableWindow(GetDlgItem(hDlg, IDC_OPTIONS_RADIO_OUTLOOK), FALSE);
  4096. SendMessage(hDlg, WM_COMMAND, (WPARAM) MAKEWPARAM(IDC_OPTIONS_RADIO_WAB, BN_CLICKED), (LPARAM) GetDlgItem(hDlg, IDC_OPTIONS_RADIO_WAB));
  4097. if(bUseOutlookStore()) // make sure reg says false .. not true
  4098. SetRegistryUseOutlook(FALSE);
  4099. }
  4100. else
  4101. {
  4102. // Correct type of Outlook is installed
  4103. int id = bUseOutlookStore() ? IDC_OPTIONS_RADIO_OUTLOOK : IDC_OPTIONS_RADIO_WAB;
  4104. SendMessage(hDlg, WM_COMMAND,
  4105. (WPARAM) MAKEWPARAM(id, BN_CLICKED),
  4106. (LPARAM) GetDlgItem(hDlg, id));
  4107. }
  4108. }
  4109. // [PaulHi] Be sure to set the child window fonts
  4110. EnumChildWindows(hDlg, SetChildDefaultGUIFont, (LPARAM)PARENT_IS_DIALOG);
  4111. return TRUE;
  4112. break;
  4113. case WM_COMMAND:
  4114. switch (GET_WM_COMMAND_ID(wParam, lParam))
  4115. {
  4116. case IDOK:
  4117. // Check which option button is checked
  4118. {
  4119. BOOL bOriginal = bUseOutlookStore();
  4120. BOOL bCurrent = IsDlgButtonChecked(hDlg, IDC_OPTIONS_RADIO_OUTLOOK);
  4121. SetRegistryUseOutlook(bCurrent);
  4122. if(bCurrent != bOriginal)
  4123. ShowMessageBox(hDlg, idsStoreChangeOnRestart, MB_ICONINFORMATION | MB_OK);
  4124. }
  4125. // fall thru
  4126. case IDCANCEL:
  4127. EndDialog(hDlg, 0);
  4128. break;
  4129. case IDC_OPTIONS_RADIO_WAB:
  4130. CheckRadioButton(hDlg,
  4131. IDC_OPTIONS_RADIO_OUTLOOK,
  4132. IDC_OPTIONS_RADIO_WAB,
  4133. IDC_OPTIONS_RADIO_WAB);
  4134. break;
  4135. case IDC_OPTIONS_RADIO_OUTLOOK:
  4136. CheckRadioButton(hDlg,
  4137. IDC_OPTIONS_RADIO_OUTLOOK,
  4138. IDC_OPTIONS_RADIO_WAB,
  4139. IDC_OPTIONS_RADIO_OUTLOOK);
  4140. break;
  4141. }
  4142. break;
  4143. }
  4144. return FALSE;
  4145. }
  4146. //$$
  4147. //
  4148. // Shows the options dialog
  4149. //
  4150. void HrShowOptionsDlg(HWND hWndParent)
  4151. {
  4152. BOOL bChange = FALSE;
  4153. INT_PTR nRetVal = DialogBoxParam( hinstMapiX, MAKEINTRESOURCE(IDD_DIALOG_OPTIONS),
  4154. hWndParent, fnOptionsDlgProc, (LPARAM) &bChange);
  4155. }
  4156. //$$////////////////////////////////////////////////////////////////////////////
  4157. //
  4158. // AddTVItem
  4159. //
  4160. // Adds an item to the Tree View - item can be folder/container or group
  4161. //
  4162. ////////////////////////////////////////////////////////////////////////////////
  4163. HTREEITEM AddTVItem(HWND hWndTV, LPTSTR lpszName, HTREEITEM hParentItem, HTREEITEM htiAfter,
  4164. LPSBinary lpsbParentEID, LPSBinary lpEID, ULONG ulObjectType)
  4165. {
  4166. TV_ITEM tvI = {0};
  4167. TV_INSERTSTRUCT tvIns = {0};
  4168. LPTVITEM_STUFF lptvStuff = NULL;
  4169. HTREEITEM htiRet = NULL;
  4170. int img = 0;
  4171. if(ulObjectType == MAPI_DISTLIST)
  4172. img = imageDistList;
  4173. else
  4174. {
  4175. if(!lpEID || !lpEID->cb || !lpEID->lpb)
  4176. img = imageAddressBook;
  4177. else
  4178. img = imageFolderClosed;
  4179. }
  4180. tvI.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  4181. tvI.iImage = img;
  4182. tvI.iSelectedImage = (img == imageFolderClosed) ? imageFolderOpen : img;
  4183. tvI.pszText = lpszName;
  4184. tvI.cchTextMax = lstrlen(tvI.pszText);
  4185. lptvStuff = LocalAlloc(LMEM_ZEROINIT, sizeof(TVITEM_STUFF));
  4186. if(!lptvStuff)
  4187. goto out;
  4188. lptvStuff->ulObjectType = ulObjectType;
  4189. if(lpEID)
  4190. {
  4191. LPSBinary lpsbEID = NULL;
  4192. lpsbEID = LocalAlloc(LMEM_ZEROINIT, sizeof(SBinary));
  4193. if(lpsbEID)
  4194. {
  4195. if(lpEID->cb)
  4196. SetSBinary(lpsbEID, lpEID->cb, lpEID->lpb);
  4197. lptvStuff->lpsbEID = lpsbEID;
  4198. }
  4199. }
  4200. lptvStuff->lpsbParent = lpsbParentEID;
  4201. lptvStuff->hItemParent = hParentItem;
  4202. tvI.lParam = (LPARAM) lptvStuff;
  4203. tvIns.item = tvI;
  4204. tvIns.hInsertAfter = htiAfter;
  4205. tvIns.hParent = hParentItem;
  4206. htiRet = TreeView_InsertItem(hWndTV, &tvIns);
  4207. /* Uncomment this to make the top level folders show up in bold
  4208. if(htiRet && !hParentItem)
  4209. {
  4210. TVITEM tvi = {0};
  4211. tvi.mask = TVIF_STATE;
  4212. tvi.state = tvi.stateMask = TVIS_BOLD;
  4213. tvi.hItem = htiRet;
  4214. TreeView_SetItem(hWndTV, &tvi);
  4215. }*/
  4216. out:
  4217. return htiRet;
  4218. }
  4219. //$$///////////////////////////////////////////////////////////////////////////
  4220. //
  4221. // AddTVFolderGroup
  4222. //
  4223. // Add a group under a contact folder in the TV
  4224. //
  4225. ///////////////////////////////////////////////////////////////////////////////
  4226. HTREEITEM AddTVFolderGroup(LPBWI lpbwi, HWND hWndTV, HTREEITEM hParentItem, LPSBinary lpsbParentEID, LPSBinary lpsbEID)
  4227. {
  4228. TCHAR szBufName[MAX_UI_STR];
  4229. if(!lpsbEID || !lpsbEID->cb || !lpsbEID->lpb)
  4230. return NULL;
  4231. // Get the name of this group
  4232. if(HR_FAILED(FillListFromGroup( bwi_lpAdrBook,
  4233. lpsbEID->cb, (LPENTRYID) lpsbEID->lpb,
  4234. szBufName, ARRAYSIZE(szBufName), NULL)))
  4235. return NULL;
  4236. return AddTVItem( hWndTV, szBufName,
  4237. hParentItem, TVI_SORT,
  4238. lpsbParentEID, lpsbEID,
  4239. MAPI_DISTLIST);
  4240. }
  4241. //$$///////////////////////////////////////////////////////////////////////////////
  4242. //
  4243. // FillTreeView
  4244. //
  4245. // Fill the TreeView with Contact Folders and groups as appropriate
  4246. //
  4247. // lpsbSelection - entryid of item to select after filling
  4248. //
  4249. ///////////////////////////////////////////////////////////////////////////////////
  4250. void FillTreeView(LPBWI lpbwi, HWND hWndTV, LPSBinary lpsbSelection)
  4251. {
  4252. // Way to do this
  4253. //
  4254. // If this is the WAB, just add an AddressBook item to the top of the list
  4255. // otherwise if this is Outlook, get a list of all the contact folders and
  4256. // add them to the Root of the TV.
  4257. //
  4258. // Then go through the list of contact folders and for each one, add the groups
  4259. // at the next level
  4260. // We cache the TVITEM_STUFF info on each item, contact folder or group
  4261. //
  4262. HTREEITEM hItem = NULL;
  4263. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  4264. LPIAB lpIAB = bwi_lpIAB;
  4265. int nDepth = 0;
  4266. bwi_bDontRefreshLV = TRUE;
  4267. SendMessage(hWndTV, WM_SETREDRAW, (WPARAM) FALSE, 0);
  4268. ClearTreeViewItems(hWndTV);
  4269. EnterCriticalSection(&lpIAB->cs);
  4270. // Check if this is an outlook session
  4271. if( pt_bIsWABOpenExSession || bIsWABSessionProfileAware(lpIAB) )
  4272. {
  4273. ULONG iolkci, colkci;
  4274. OlkContInfo *rgolkci;
  4275. HTREEITEM htiTopLevel = NULL;
  4276. colkci = pt_bIsWABOpenExSession ? lpIAB->lpPropertyStore->colkci : lpIAB->cwabci;
  4277. Assert(colkci);
  4278. rgolkci = pt_bIsWABOpenExSession ? lpIAB->lpPropertyStore->rgolkci : lpIAB->rgwabci;
  4279. Assert(rgolkci);
  4280. // Add the multiple folders here
  4281. // Since each folder is added under the first item, we start last first
  4282. // to preserve the folder order.
  4283. if(pt_bIsWABOpenExSession)
  4284. {
  4285. do
  4286. {
  4287. iolkci = colkci-1;
  4288. htiTopLevel = AddTVItem( hWndTV, rgolkci[iolkci].lpszName, NULL, TVI_FIRST, NULL,
  4289. (iolkci==0/*&& pt_bIsWABOpenExSession*/) ? NULL : rgolkci[iolkci].lpEntryID,
  4290. MAPI_ABCONT);
  4291. colkci--;
  4292. } while(colkci!=0);
  4293. }
  4294. else
  4295. {
  4296. // WAB Profiles ..
  4297. // We want to add the first item ( TEXT("All Contacts")) at the top and all user folders
  4298. // at the same level and all ordinary folders under the user level folders
  4299. LPWABFOLDER lpFolder = (bIsThereACurrentUser(lpIAB) ? lpIAB->lpWABCurrentUserFolder : lpIAB->lpWABUserFolders);
  4300. // With a given user, we only add that users folder
  4301. // Without a given user we add everyones folders
  4302. // if there are no user folders at all then we don't have user's configured and
  4303. // all folders should show up at the top level
  4304. if(!lpFolder)
  4305. lpFolder = lpIAB->lpWABFolders;
  4306. while(lpFolder)
  4307. {
  4308. LPWABFOLDERLIST lpFolderList = lpFolder->lpFolderList;
  4309. htiTopLevel = AddTVItem(hWndTV, lpFolder->lpFolderName, NULL, TVI_SORT, NULL, &lpFolder->sbEID, MAPI_ABCONT);
  4310. while(lpFolderList)
  4311. {
  4312. // Don't show Shared Folders under the user-folders .. shared folders will be
  4313. // shown under the PAB folder
  4314. if(!lpFolderList->lpFolder->bShared)
  4315. AddTVItem(hWndTV, lpFolderList->lpFolder->lpFolderName, htiTopLevel, TVI_SORT, NULL, &lpFolderList->lpFolder->sbEID, MAPI_ABCONT);
  4316. lpFolderList = lpFolderList->lpNext;
  4317. }
  4318. TreeView_Expand(hWndTV, htiTopLevel, TVE_EXPAND);
  4319. if(lpIAB->lpWABCurrentUserFolder)
  4320. break;
  4321. lpFolder=lpFolder->lpNext;
  4322. }
  4323. // Add the Virtual PAB item to the top of the list so we can sort the others
  4324. htiTopLevel = AddTVItem(hWndTV, rgolkci[0].lpszName, NULL, TVI_FIRST, NULL, rgolkci[0].lpEntryID, MAPI_ABCONT);
  4325. // add all the SHARED folders under the root item
  4326. lpFolder = lpIAB->lpWABFolders;
  4327. while(lpFolder)
  4328. {
  4329. if(lpFolder->bShared)
  4330. AddTVItem(hWndTV, lpFolder->lpFolderName, htiTopLevel, TVI_SORT, NULL, &lpFolder->sbEID, MAPI_ABCONT);
  4331. lpFolder=lpFolder->lpNext;
  4332. }
  4333. //if(!bIsThereACurrentUser(lpIAB) && !bDoesThisWABHaveAnyUsers(lpIAB))
  4334. TreeView_Expand(hWndTV, htiTopLevel, TVE_EXPAND);
  4335. }
  4336. }
  4337. else
  4338. {
  4339. TCHAR sz[MAX_PATH];
  4340. *sz = '\0';
  4341. LoadString(hinstMapiX, idsContacts/*IDS_ADDRBK_CAPTION*/, sz, ARRAYSIZE(sz));
  4342. AddTVItem( hWndTV, sz, NULL, TVI_FIRST, NULL, NULL, MAPI_ABCONT);
  4343. }
  4344. //TreeView_SortChildren(hWndTV, NULL, 0);
  4345. // Now we have all the contact folders at the root level ..
  4346. // we can now add the groups under each folder
  4347. hItem = TreeView_GetRoot(hWndTV);
  4348. //if(bDoesThisWABHaveAnyUsers(lpIAB)) // don't populate any groups under the Root Item if Users exist
  4349. // hItem = TreeView_GetNextSibling(hWndTV, hItem);
  4350. while(hItem)
  4351. {
  4352. TV_ITEM tvI = {0};
  4353. // Find all the Groups in this folder
  4354. tvI.mask = TVIF_PARAM | TVIF_HANDLE;
  4355. tvI.hItem = hItem;
  4356. if(TreeView_GetItem(hWndTV, &tvI))
  4357. {
  4358. if(tvI.lParam && ((LPTVITEM_STUFF)tvI.lParam)->ulObjectType==MAPI_ABCONT)
  4359. {
  4360. LPTVITEM_STUFF lptvStuff = (LPTVITEM_STUFF) tvI.lParam;
  4361. SPropertyRestriction PropRes = {0};
  4362. SPropValue sp = {0};
  4363. HRESULT hr = S_OK;
  4364. ULONG ulCount = 0;
  4365. LPSBinary rgsbEntryIDs = NULL;
  4366. sp.ulPropTag = PR_OBJECT_TYPE;
  4367. sp.Value.l = MAPI_DISTLIST;
  4368. PropRes.ulPropTag = PR_OBJECT_TYPE;
  4369. PropRes.relop = RELOP_EQ;
  4370. PropRes.lpProp = &sp;
  4371. if(!HR_FAILED(hr = FindRecords( lpIAB->lpPropertyStore->hPropertyStore,
  4372. lptvStuff->lpsbEID, 0, TRUE, &PropRes,
  4373. &ulCount,&rgsbEntryIDs)))
  4374. {
  4375. ULONG i;
  4376. for(i=0;i<ulCount;i++)
  4377. AddTVFolderGroup(lpbwi, hWndTV, hItem, lptvStuff->lpsbEID, &(rgsbEntryIDs[i]));
  4378. FreeEntryIDs(lpIAB->lpPropertyStore->hPropertyStore, ulCount, rgsbEntryIDs);
  4379. }
  4380. }
  4381. }
  4382. TreeView_SortChildren(hWndTV, hItem, 0);
  4383. // Start at the top level, look for children,
  4384. // if no children, look for next sibling,
  4385. // if no sibling, look for parent's sibling
  4386. {
  4387. HTREEITEM hTemp = NULL;
  4388. if(nDepth < 1) // Assumes we only have 2 levels of folders - this way we don't look at the third level which may only have groups
  4389. hTemp = TreeView_GetChild(hWndTV, hItem);
  4390. if(hTemp)
  4391. nDepth++;
  4392. else
  4393. hTemp = TreeView_GetNextSibling(hWndTV, hItem);
  4394. if(!hTemp)
  4395. {
  4396. if(hTemp = TreeView_GetParent(hWndTV, hItem))
  4397. {
  4398. nDepth--;
  4399. hTemp = TreeView_GetNextSibling(hWndTV, hTemp);
  4400. }
  4401. }
  4402. hItem = hTemp;
  4403. }
  4404. }
  4405. if(!lpsbSelection && bIsThereACurrentUser(bwi_lpIAB))
  4406. lpsbSelection = &bwi_lpIAB->lpWABCurrentUserFolder->sbEID;
  4407. UpdateTVGroupSelection(hWndTV, lpsbSelection);
  4408. //if(!lpsbSelection || !lpsbSelection->cb || !lpsbSelection->lpb)
  4409. {
  4410. LPSBinary lpsb = NULL;
  4411. //UpdateListViewContents(lpbwi, &sb, MAPI_ABCONT);
  4412. ULONG ulObjectType;
  4413. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsb, &ulObjectType, FALSE);
  4414. UpdateListViewContents(lpbwi, lpsb, ulObjectType);
  4415. LocalFreeSBinary(lpsb);
  4416. }
  4417. SendMessage(hWndTV, WM_SETREDRAW, (WPARAM) TRUE, 0);
  4418. bwi_bDontRefreshLV = FALSE;
  4419. LeaveCriticalSection(&lpIAB->cs);
  4420. {
  4421. // if there is only a single item in the tree view, remove the haslines style
  4422. // as it looks pretty strange..
  4423. //
  4424. DWORD dwStyle = GetWindowLong(hWndTV, GWL_STYLE);
  4425. int nCount = TreeView_GetCount(hWndTV);
  4426. if(nCount > 1)
  4427. dwStyle |= TVS_HASLINES;
  4428. else
  4429. dwStyle &= ~TVS_HASLINES;
  4430. SetWindowLong(hWndTV, GWL_STYLE, dwStyle);
  4431. }
  4432. return;
  4433. }
  4434. typedef struct _FolderInfo
  4435. {
  4436. BOOL bIsReadOnly; // Sets DLG ctrls to readonly
  4437. BOOL bIsShared; // Indicates if shared
  4438. BOOL bForceShared; // Indicates that shared-checkbox should be shared and non-modifiable
  4439. LPTSTR lpsz; // Folder name (in and out param)
  4440. LPTSTR lpszOldName; // Old name so we can track name changes
  4441. LPTSTR lpszOwnerName; // Person who created this folder
  4442. LPIAB lpIAB;
  4443. LPSBinary lpsbEID; // EID of the folder
  4444. LPWABFOLDER lpParentFolder; // Parent folder this folder will be associated with
  4445. SBinary sbNew; // returned new EID of new folder
  4446. } FINFO, * LPFINFO;
  4447. //$$
  4448. /*
  4449. - fnFolderDlgProc
  4450. -
  4451. * Dialog proc for the Folder dialog
  4452. *
  4453. */
  4454. INT_PTR CALLBACK fnFolderDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  4455. {
  4456. switch(message)
  4457. {
  4458. case WM_INITDIALOG:
  4459. {
  4460. LPFINFO lpfi = (LPFINFO) lParam;
  4461. LPTSTR lpsz = lpfi->lpsz;
  4462. HWND hWndCheck = GetDlgItem(hDlg, IDC_FOLDER_CHECK_SHARE);
  4463. SetWindowLongPtr(hDlg,DWLP_USER,(LPARAM) lpfi); //Save this for future reference
  4464. SendMessage(GetDlgItem(hDlg,IDC_FOLDER_EDIT_NAME), EM_SETLIMITTEXT,(WPARAM) MAX_UI_STR-1,0);
  4465. if(lpsz && lstrlen(lpsz))
  4466. SetDlgItemText(hDlg, IDC_FOLDER_EDIT_NAME, lpsz);
  4467. CheckDlgButton(hDlg, IDC_FOLDER_CHECK_SHARE, (lpfi->bIsShared ? BST_CHECKED : BST_UNCHECKED));
  4468. if(lpfi->lpszOwnerName)
  4469. {
  4470. TCHAR sz[MAX_PATH];
  4471. TCHAR szTmp[MAX_PATH], *lpszTmp;
  4472. *sz = '\0';
  4473. GetDlgItemText(hDlg, IDC_FOLDER_STATIC_CREATEDBY, sz, CharSizeOf(sz));
  4474. if(sz && lstrlen(sz))
  4475. {
  4476. LPTSTR lpsz = NULL;
  4477. CopyTruncate(szTmp, lpfi->lpszOwnerName, MAX_PATH - 1);
  4478. lpszTmp = szTmp;
  4479. if(FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING |FORMAT_MESSAGE_ARGUMENT_ARRAY,
  4480. sz, 0, 0, (LPTSTR) &lpsz, 0, (va_list *)&lpszTmp))
  4481. {
  4482. SetDlgItemText(hDlg, IDC_FOLDER_STATIC_CREATEDBY, lpsz);
  4483. LocalFree(lpsz);
  4484. ShowWindow(GetDlgItem(hDlg, IDC_FOLDER_STATIC_CREATEDBY), SW_SHOWNORMAL);
  4485. }
  4486. }
  4487. }
  4488. if(lpfi->bIsReadOnly)
  4489. {
  4490. SendDlgItemMessage(hDlg, IDC_FOLDER_EDIT_NAME, EM_SETREADONLY, (WPARAM) TRUE, 0);
  4491. EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
  4492. EnableWindow(hWndCheck, FALSE);
  4493. SendMessage(hDlg, DM_SETDEFID, IDCANCEL, 0);
  4494. SetFocus(GetDlgItem(hDlg,IDCANCEL));
  4495. }
  4496. else
  4497. SetFocus(GetDlgItem(hDlg,IDC_FOLDER_EDIT_NAME));
  4498. if(lpfi->bForceShared)
  4499. {
  4500. CheckDlgButton(hDlg, IDC_FOLDER_CHECK_SHARE, BST_CHECKED);
  4501. EnableWindow(hWndCheck, FALSE);
  4502. }
  4503. if(!bDoesThisWABHaveAnyUsers(lpfi->lpIAB))
  4504. {
  4505. // there are no users configured so hide the sharing option
  4506. EnableWindow(hWndCheck, FALSE);
  4507. ShowWindow(hWndCheck, SW_HIDE);
  4508. }
  4509. }
  4510. break;
  4511. case WM_COMMAND:
  4512. switch(GET_WM_COMMAND_CMD(wParam,lParam)) //check the notification code
  4513. {
  4514. case EN_CHANGE:
  4515. switch(LOWORD(wParam))
  4516. { //update title as necessary
  4517. case IDC_FOLDER_EDIT_NAME:
  4518. {
  4519. TCHAR szBuf[MAX_UI_STR];
  4520. if(GetWindowText((HWND) lParam,szBuf,CharSizeOf(szBuf)))
  4521. SetWindowPropertiesTitle(hDlg, szBuf);
  4522. }
  4523. break;
  4524. }
  4525. break;
  4526. }
  4527. switch (GET_WM_COMMAND_ID(wParam, lParam))
  4528. {
  4529. case IDOK:
  4530. // Check that text is filled in
  4531. {
  4532. TCHAR sz[MAX_UI_STR];
  4533. GetDlgItemText(hDlg, IDC_FOLDER_EDIT_NAME, sz, CharSizeOf(sz));
  4534. if(!lstrlen(sz))
  4535. {
  4536. ShowMessageBox(hDlg, idsAddFolderName, MB_ICONINFORMATION | MB_OK);
  4537. return FALSE;
  4538. }
  4539. else
  4540. {
  4541. LPFINFO lpfi = (LPFINFO) GetWindowLongPtr(hDlg,DWLP_USER);
  4542. LPTSTR lpsz = lpfi->lpsz;
  4543. HRESULT hr = S_OK;
  4544. BOOL bShared = IsDlgButtonChecked(hDlg, IDC_FOLDER_CHECK_SHARE);
  4545. if(lpfi->lpsbEID && sz) //existing entry
  4546. {
  4547. ULONG ulFlags = 0;
  4548. // Did the name change or sharing info changed
  4549. if(lstrcmp(sz, lpfi->lpszOldName)!=0)
  4550. ulFlags |= FOLDER_UPDATE_NAME;
  4551. if(lpfi->bIsShared!=bShared)
  4552. ulFlags |= FOLDER_UPDATE_SHARE;
  4553. if(ulFlags)
  4554. {
  4555. if(!HR_FAILED(hr = HrUpdateFolderInfo(lpfi->lpIAB, lpfi->lpsbEID, ulFlags, bShared, sz)))
  4556. {
  4557. //reload the profiles so that this is updated
  4558. HrGetWABProfiles(lpfi->lpIAB);
  4559. }
  4560. }
  4561. }
  4562. else
  4563. {
  4564. // if we're here we have a valid folder name ..
  4565. hr = HrCreateNewFolder( lpfi->lpIAB, sz,
  4566. lstrlen(lpfi->lpIAB->szProfileID)?lpfi->lpIAB->szProfileID:NULL,
  4567. FALSE, lpfi->lpParentFolder, bShared, &lpfi->sbNew);
  4568. }
  4569. if(HR_FAILED(hr))
  4570. {
  4571. if(hr == MAPI_E_COLLISION)
  4572. ShowMessageBox(hDlg, idsEntryAlreadyInWAB, MB_ICONINFORMATION | MB_OK);
  4573. else
  4574. ShowMessageBox(hDlg, idsCouldNotSelectUser, MB_ICONEXCLAMATION | MB_OK);
  4575. return FALSE;
  4576. }
  4577. }
  4578. }
  4579. EndDialog(hDlg, IDOK);
  4580. break;
  4581. case IDCANCEL:
  4582. EndDialog(hDlg, IDCANCEL);
  4583. break;
  4584. }
  4585. break;
  4586. }
  4587. return FALSE;
  4588. }
  4589. /*
  4590. - HrFolderProperties
  4591. -
  4592. * if FolderEID is NULL,
  4593. * Creates a newfolder, adds it to the current profile, updates the UI
  4594. * in TreeView and in the View | Folders menu ...
  4595. * else opens properties on the folder so user can change the name
  4596. * if desired
  4597. *
  4598. * lpsbEID - NULL if creating a new folder else EID of folder to view
  4599. * lpParentFolder - User folder under which this is being created
  4600. * lpsbnew - return EID of newly created folder
  4601. */
  4602. HRESULT HrFolderProperties(HWND hWndParent, LPIAB lpIAB, LPSBinary lpsbEID,
  4603. LPWABFOLDER lpParentFolder, LPSBinary lpsbNew)
  4604. {
  4605. HRESULT hr = S_OK;
  4606. int nRetVal;
  4607. TCHAR sz[MAX_UI_STR];
  4608. LPTSTR lpsz = NULL;
  4609. FINFO fi = {0};
  4610. fi.lpszOwnerName = NULL;
  4611. *sz = '\0';
  4612. if(lpsbEID)
  4613. {
  4614. LPWABFOLDER lpFolder = FindWABFolder(lpIAB, lpsbEID, NULL, NULL);
  4615. if( (!lpsbEID->cb && !lpsbEID->lpb) )
  4616. fi.bIsShared = TRUE;
  4617. if( (!lpsbEID->cb && !lpsbEID->lpb) ||
  4618. (lpFolder && lpFolder->lpProfileID && lstrlen(lpFolder->lpProfileID)) )
  4619. fi.bIsReadOnly = TRUE;
  4620. if(lpFolder)
  4621. {
  4622. StrCpyN(sz, lpFolder->lpFolderName, ARRAYSIZE(sz));
  4623. fi.lpszOldName = lpFolder->lpFolderName;
  4624. fi.bIsShared = lpFolder->bShared;
  4625. fi.lpszOwnerName = lpFolder->lpFolderOwner;
  4626. }
  4627. else
  4628. {
  4629. LoadString(hinstMapiX, idsSharedContacts/*idsAllContacts*/, sz, ARRAYSIZE(sz));
  4630. }
  4631. }
  4632. else
  4633. {
  4634. // this is a new folder ..
  4635. // if it doesn't have a parent and userfolders are already configured then it's being created
  4636. // in the shared folders in which case we should force the shared-folder option
  4637. if(bDoesThisWABHaveAnyUsers(lpIAB) && !lpParentFolder)
  4638. fi.bForceShared = TRUE;
  4639. }
  4640. fi.lpsz = sz;
  4641. fi.lpIAB = lpIAB;
  4642. fi.lpsbEID = lpsbEID;
  4643. fi.lpParentFolder = lpParentFolder;
  4644. nRetVal = (int) DialogBoxParam( hinstMapiX, MAKEINTRESOURCE(IDD_DIALOG_FOLDER),
  4645. hWndParent, fnFolderDlgProc, (LPARAM) &fi);
  4646. if(nRetVal == IDCANCEL)
  4647. {
  4648. hr = MAPI_E_USER_CANCEL;
  4649. goto out;
  4650. }
  4651. if(lpsbNew)
  4652. SetSBinary(lpsbNew, fi.sbNew.cb, fi.sbNew.lpb);
  4653. out:
  4654. LocalFreeAndNull((LPVOID *) (&fi.sbNew.lpb));
  4655. return hr;
  4656. }
  4657. /*
  4658. - UpdateLV
  4659. -
  4660. * Refreshes the list view based on the current selection
  4661. *
  4662. */
  4663. void UpdateLV(LPBWI lpbwi)
  4664. {
  4665. ULONG ulObjectType = 0;
  4666. LPSBinary lpsbEID = NULL;
  4667. bwi_hti = NULL;
  4668. GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjectType, FALSE);
  4669. UpdateListViewContents(lpbwi, lpsbEID, ulObjectType);
  4670. LocalFreeSBinary(lpsbEID);
  4671. bwi_bDeferNotification = TRUE;
  4672. }
  4673. #ifdef COLSEL_MENU
  4674. /**
  4675. This function will update the listview and write the selected custom column selections out
  4676. to the registry.
  4677. */
  4678. BOOL UpdateOptionalColumns( LPBWI lpbwi, ULONG iColumn )
  4679. {
  4680. LVCOLUMN lvCol = {0};
  4681. HKEY hKey = NULL;
  4682. LPTSTR lpszColTitle = (iColumn == colHomePhone ) ? szCustomProp1 : szCustomProp2;
  4683. ULONG ulProp = (iColumn == colHomePhone ) ? PR_WAB_CUSTOMPROP1 : PR_WAB_CUSTOMPROP2;
  4684. DWORD cbProp = 0;
  4685. LPIAB lpIAB = bwi_lpIAB;
  4686. HKEY hKeyRoot = (lpIAB && lpIAB->hKeyCurrentUser) ? lpIAB->hKeyCurrentUser : HKEY_CURRENT_USER;
  4687. DWORD dwDisposition = 0;
  4688. BOOL fRet = FALSE;
  4689. TCHAR szBuf[MAX_PATH];
  4690. if( iColumn != colHomePhone && iColumn != colOfficePhone )
  4691. goto exit;
  4692. LoadString(hinstMapiX, lprgAddrBookColHeaderIDs[iColumn], szBuf, ARRAYSIZE(szBuf));
  4693. lvCol.mask = LVCF_TEXT;
  4694. lvCol.pszText = (lpszColTitle && lstrlen(lpszColTitle))? lpszColTitle : szBuf;
  4695. if( !ListView_SetColumn( bwi_hWndListAB, iColumn, &lvCol ) )
  4696. {
  4697. DebugTrace( TEXT("could not setcolumntext: %x\n"), GetLastError() );
  4698. goto exit;
  4699. }
  4700. if(ulProp)
  4701. {
  4702. // begin registry stuff
  4703. if (ERROR_SUCCESS != RegCreateKeyEx(hKeyRoot, lpNewWABRegKey, 0, //reserved
  4704. NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  4705. NULL, &hKey, &dwDisposition))
  4706. {
  4707. goto exit;
  4708. }
  4709. cbProp = sizeof( ULONG );
  4710. if(ERROR_SUCCESS != RegSetValueEx( hKey,
  4711. (iColumn == colHomePhone ? szPropTag1 : szPropTag2),
  4712. 0, REG_DWORD, (LPBYTE)&ulProp, cbProp))
  4713. goto exit;
  4714. }
  4715. fRet = TRUE;
  4716. exit:
  4717. if(hKey)
  4718. RegCloseKey(hKey);
  4719. return fRet;
  4720. }
  4721. #endif // COLSEL_MENU
  4722. /*
  4723. - HrExportWAB
  4724. -
  4725. * Supposed to export data out of the .WAB into another .wab file.
  4726. * Ideally, user should be able to specify an existing WAB file and TEXT("push") data
  4727. * into that file from this file.
  4728. * Instead, we do a cheesy implementation here where we let the user specify a file name to
  4729. * create and we then just copy the current .WAB file to the new file name
  4730. *
  4731. * Obviously this method doesn't work when WAB is sharing the Outlook store and in that
  4732. * case we remove this option from the Menu
  4733. *
  4734. */
  4735. extern BOOL PromptForWABFile(HWND hWnd, LPTSTR szFile, DWORD cchSizeFile, BOOL bOpen);
  4736. HRESULT HrExportWAB(HWND hWnd, LPBWI lpbwi)
  4737. {
  4738. HRESULT hr = E_FAIL;
  4739. TCHAR szFile[MAX_PATH];
  4740. HCURSOR hOldC = NULL;
  4741. if (!PromptForWABFile(hWnd, szFile, ARRAYSIZE(szFile), FALSE))
  4742. {
  4743. hr = MAPI_E_USER_CANCEL;
  4744. goto out;
  4745. }
  4746. //Check if file already exists ..
  4747. if(0xFFFFFFFF != GetFileAttributes(szFile))
  4748. {
  4749. // Ask user if they want to overwrite
  4750. if(IDNO == ShowMessageBoxParam(hWnd,
  4751. IDE_VCARD_EXPORT_FILE_EXISTS,
  4752. MB_ICONEXCLAMATION | MB_YESNO | MB_SETFOREGROUND,
  4753. szFile))
  4754. {
  4755. hr = MAPI_E_USER_CANCEL;
  4756. goto out;
  4757. }
  4758. }
  4759. hOldC = SetCursor(LoadCursor(NULL, IDC_WAIT));
  4760. // Still here, means go ahead and copy the current .wab file to the new place ...
  4761. if(!CopyFile(GetWABFileName(bwi_lpIAB->lpPropertyStore->hPropertyStore,FALSE), szFile, FALSE))
  4762. {
  4763. DebugTrace( TEXT("WAB File export failed: %d\n"), GetLastError());
  4764. goto out;
  4765. }
  4766. if(hOldC)
  4767. {
  4768. SetCursor(hOldC);
  4769. hOldC = NULL;
  4770. }
  4771. ShowMessageBoxParam(hWnd, idsWABExportSuccess, MB_OK | MB_ICONEXCLAMATION, szFile);
  4772. hr = S_OK;
  4773. out:
  4774. if(HR_FAILED(hr) && hr!=MAPI_E_USER_CANCEL)
  4775. ShowMessageBox(hWnd, idsExportError, MB_OK | MB_ICONEXCLAMATION);
  4776. if(hOldC)
  4777. SetCursor(hOldC);
  4778. return hr;
  4779. }
  4780. void DestroyImageLists(LPBWI lpbwi)
  4781. {
  4782. HIMAGELIST hImageList;
  4783. if (NULL == gpfnImageList_Destroy)
  4784. return;
  4785. if (IsWindow(bwi_hWndTools))
  4786. {
  4787. // Destroy Image Lists created in ui_clbar.cpp's InitToolbar()
  4788. hImageList = (HIMAGELIST) SendMessage(bwi_hWndTools, TB_GETIMAGELIST, 0, 0);
  4789. if (NULL != hImageList)
  4790. gpfnImageList_Destroy(hImageList);
  4791. hImageList = (HIMAGELIST) SendMessage(bwi_hWndTools, TB_GETHOTIMAGELIST, 0, 0);
  4792. if (NULL != hImageList)
  4793. gpfnImageList_Destroy(hImageList);
  4794. hImageList = (HIMAGELIST) SendMessage(bwi_hWndTools, TB_GETDISABLEDIMAGELIST, 0, 0);
  4795. if (NULL != hImageList)
  4796. gpfnImageList_Destroy(hImageList);
  4797. }
  4798. if (IsWindow(bwi_hWndTV))
  4799. {
  4800. // Destroy Image Lists created in ui_abook.c's InitChildren()
  4801. hImageList = TreeView_GetImageList (bwi_hWndTV, TVSIL_NORMAL);
  4802. if (NULL != hImageList)
  4803. gpfnImageList_Destroy(hImageList);
  4804. }
  4805. }