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.

2664 lines
80 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 1993-1998 Microsoft Corporation. All Rights Reserved.
  3. //
  4. // MODULE: finder.cpp
  5. //
  6. // PURPOSE:
  7. //
  8. #include "pch.hxx"
  9. #include <process.h>
  10. #include "resource.h"
  11. #include "error.h"
  12. #include "finder.h"
  13. #include "goptions.h"
  14. #include "menuutil.h"
  15. #include "statbar.h"
  16. #include "imnact.h"
  17. #include "note.h"
  18. #include "mailutil.h"
  19. #include "statnery.h"
  20. #include "instance.h"
  21. #include "msoeobj.h"
  22. #include "msglist.h"
  23. #include "storutil.h"
  24. #include "menures.h"
  25. #include "findres.h"
  26. #include "multiusr.h"
  27. #include "newsutil.h"
  28. #include "ruleutil.h"
  29. #include "instance.h"
  30. #include "shlwapip.h"
  31. #include "demand.h"
  32. #include "dllmain.h"
  33. #include "order.h"
  34. ASSERTDATA
  35. #define MF_ENABLEFLAGS(b) (MF_BYCOMMAND|(b ? MF_ENABLED : MF_GRAYED | MF_DISABLED))
  36. typedef struct _ThreadList
  37. {
  38. DWORD dwThreadID;
  39. struct _ThreadList * pPrev;
  40. struct _ThreadList * pNext;
  41. } OETHREADLIST;
  42. OETHREADLIST * g_pOEThrList = NULL;
  43. // Add thread to list
  44. OETHREADLIST * AddThreadToList(DWORD uiThreadId, OETHREADLIST * pThrList)
  45. {
  46. if(!pThrList)
  47. {
  48. if(MemAlloc((LPVOID *) &pThrList, sizeof(OETHREADLIST)))
  49. {
  50. pThrList->pPrev = NULL;
  51. pThrList->pNext = NULL;
  52. pThrList->dwThreadID = uiThreadId;
  53. }
  54. }
  55. else
  56. pThrList->pNext = AddThreadToList(uiThreadId, pThrList->pNext);
  57. return(pThrList);
  58. }
  59. // Remove thread from list
  60. OETHREADLIST * DelThreadToList(DWORD uiThreadId, OETHREADLIST * pThrList)
  61. {
  62. OETHREADLIST * pLst = NULL;
  63. if(!pThrList)
  64. return(NULL);
  65. else if(pThrList->dwThreadID == uiThreadId)
  66. {
  67. if(pThrList->pPrev)
  68. {
  69. pThrList->pPrev->pNext = pThrList->pNext;
  70. pLst = pThrList->pPrev;
  71. }
  72. if(pThrList->pNext)
  73. {
  74. pThrList->pNext->pPrev = pThrList->pPrev;
  75. if(!pLst)
  76. pLst = pThrList->pNext;
  77. }
  78. MemFree(pThrList);
  79. pThrList = NULL;
  80. }
  81. else
  82. pThrList->pNext = DelThreadToList(uiThreadId, pThrList->pNext);
  83. return pLst;
  84. }
  85. // Close all Finder windows
  86. void CloseAllFindWnds(HWND hwnd, OETHREADLIST * pThrList)
  87. {
  88. while(pThrList)
  89. {
  90. CloseThreadWindows(hwnd, pThrList->dwThreadID);
  91. pThrList = pThrList->pNext;
  92. }
  93. }
  94. void CloseFinderTreads()
  95. {
  96. CloseAllFindWnds(NULL, g_pOEThrList);
  97. }
  98. /////////////////////////////////////////////////////////////////////////////
  99. // Thread entry point for the finder
  100. //
  101. unsigned int __stdcall FindThreadProc(LPVOID lpvUnused);
  102. HRESULT CPumpRefCount::QueryInterface(REFIID riid, LPVOID *ppvObj)
  103. {
  104. TraceCall("CPumpRefCount::QueryInterface");
  105. *ppvObj = NULL;
  106. if (IsEqualIID(riid, IID_IUnknown))
  107. *ppvObj = (LPVOID) (IUnknown *)this;
  108. if (*ppvObj)
  109. {
  110. AddRef();
  111. return (S_OK);
  112. }
  113. return (E_NOINTERFACE);
  114. }
  115. ULONG CPumpRefCount::AddRef(void)
  116. {
  117. TraceCall("CPumpRefCount::AddRef");
  118. return ((ULONG) InterlockedIncrement((LONG *) &m_cRef));
  119. }
  120. ULONG CPumpRefCount::Release(void)
  121. {
  122. TraceCall("CPumpRefCount::Release");
  123. if (0 == InterlockedDecrement((LONG *) &m_cRef))
  124. {
  125. delete this;
  126. return 0;
  127. }
  128. return (m_cRef);
  129. }
  130. //
  131. // FUNCTION: FreeFindInfo
  132. //
  133. void FreeFindInfo(FINDINFO *pFindInfo)
  134. {
  135. SafeMemFree(pFindInfo->pszFrom);
  136. SafeMemFree(pFindInfo->pszSubject);
  137. SafeMemFree(pFindInfo->pszTo);
  138. SafeMemFree(pFindInfo->pszBody);
  139. ZeroMemory(pFindInfo, sizeof(FINDINFO));
  140. }
  141. //
  142. // FUNCTION: CopyFindInfo
  143. //
  144. HRESULT CopyFindInfo(FINDINFO *pFindSrc, FINDINFO *pFindDst)
  145. {
  146. // Locals
  147. HRESULT hr=S_OK;
  148. // Zero
  149. ZeroMemory(pFindDst, sizeof(FINDINFO));
  150. // Duplicate
  151. pFindDst->mask = pFindSrc->mask;
  152. pFindDst->ftDateFrom = pFindSrc->ftDateFrom;
  153. pFindDst->ftDateTo = pFindSrc->ftDateTo;
  154. pFindDst->fSubFolders = pFindSrc->fSubFolders;
  155. // pszFrom
  156. if (pFindSrc->pszFrom)
  157. {
  158. // Duplicate the String
  159. IF_NULLEXIT(pFindDst->pszFrom = PszDupA(pFindSrc->pszFrom));
  160. }
  161. // pszTo
  162. if (pFindSrc->pszTo)
  163. {
  164. // Duplicate the String
  165. IF_NULLEXIT(pFindDst->pszTo = PszDupA(pFindSrc->pszTo));
  166. }
  167. // pszSubject
  168. if (pFindSrc->pszSubject)
  169. {
  170. // Duplicate the String
  171. IF_NULLEXIT(pFindDst->pszSubject = PszDupA(pFindSrc->pszSubject));
  172. }
  173. // pszBody
  174. if (pFindSrc->pszBody)
  175. {
  176. // Duplicate the String
  177. IF_NULLEXIT(pFindDst->pszBody = PszDupA(pFindSrc->pszBody));
  178. }
  179. exit:
  180. // Done
  181. return hr;
  182. }
  183. //
  184. // FUNCTION: DoFindMsg()
  185. //
  186. // PURPOSE: Instantiates the finder object on a separate thread.
  187. //
  188. // PARAMETERS:
  189. // [in] pidl - Folder to default the search in
  190. // [in] ftType - Type of folders being searched
  191. //
  192. // RETURN VALUE:
  193. // HRESULT
  194. //
  195. HRESULT DoFindMsg(FOLDERID idFolder, FOLDERTYPE ftType)
  196. {
  197. HRESULT hr = S_OK;
  198. HTHREAD hThread = NULL;
  199. DWORD uiThreadId = 0;
  200. FINDERPARAMS * pFindParams = NULL;
  201. // Allocate a structure to hold the initialization information that we can
  202. // pass to the other thread.
  203. IF_NULLEXIT(pFindParams = new FINDERPARAMS);
  204. // Initialzie the find
  205. pFindParams->idFolder = idFolder;
  206. pFindParams->ftType = ftType;
  207. // Create another thread to do the search on
  208. hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FindThreadProc, (LPVOID) pFindParams, 0, &uiThreadId);
  209. if (NULL == hThread)
  210. IF_FAILEXIT(hr = E_FAIL);
  211. // NULL this out so we don't free it later. The other thread owns freeing
  212. // this.
  213. pFindParams = NULL;
  214. hr = S_OK;
  215. exit:
  216. // Close the thread handle
  217. if (NULL != hThread)
  218. CloseHandle(hThread);
  219. // Free the find parameters if we still have a pointer to them.
  220. if (NULL != pFindParams)
  221. delete pFindParams;
  222. return hr;
  223. }
  224. unsigned int __stdcall LOADDS_16 FindThreadProc(LPVOID lpv)
  225. {
  226. CFindDlg *pFindDlg = NULL;
  227. MSG msg;
  228. FINDERPARAMS *pFindParams = (FINDERPARAMS *) lpv;
  229. DWORD uiThreadId = 0;
  230. // Make sure this new thread has all the initialization performed
  231. // correctly.
  232. OleInitialize(0);
  233. CoIncrementInit("FindThreadProc", MSOEAPI_START_SHOWERRORS, NULL, NULL);
  234. EnterCriticalSection(&g_csThreadList);
  235. uiThreadId = GetCurrentThreadId();
  236. g_pOEThrList = AddThreadToList(uiThreadId, g_pOEThrList );
  237. LeaveCriticalSection(&g_csThreadList);
  238. // Create the finder
  239. pFindDlg = new CFindDlg();
  240. if (pFindDlg)
  241. {
  242. // Show the find dialog. This function will return when the user is
  243. // done.
  244. pFindDlg->Show(pFindParams);
  245. // Message Loop
  246. while (GetMessageWrapW(&msg, NULL, 0, 0))
  247. pFindDlg->HandleMessage(&msg);
  248. pFindDlg->Release();
  249. }
  250. // Free this information
  251. if (NULL != pFindParams)
  252. delete pFindParams;
  253. // Uninitialize the thread
  254. EnterCriticalSection(&g_csThreadList);
  255. g_pOEThrList = DelThreadToList(uiThreadId, g_pOEThrList);
  256. LeaveCriticalSection(&g_csThreadList);
  257. CoDecrementInit("FindThreadProc", NULL);
  258. OleUninitialize();
  259. return 0;
  260. }
  261. CFindDlg::CFindDlg()
  262. {
  263. m_cRef = 1;
  264. m_hwnd = NULL;
  265. ZeroMemory(&m_rFindInfo, sizeof(m_rFindInfo));
  266. m_hwndList = NULL;
  267. m_hTimeout = NULL;
  268. m_hAccel = NULL;
  269. m_pStatusBar = NULL;
  270. m_pMsgList = NULL;
  271. m_pMsgListCT = NULL;
  272. m_pCancel = NULL;
  273. m_pPumpRefCount = NULL;
  274. ZeroMemory(&m_hlDisabled, sizeof(HWNDLIST));
  275. m_fShowResults = FALSE;
  276. m_fAbort = FALSE;
  277. m_fClose = FALSE;
  278. m_fInProgress = FALSE;
  279. m_ulPct = 0;
  280. m_fFindComplete = FALSE;
  281. m_hIcon = NULL;
  282. m_hIconSm = NULL;
  283. m_dwCookie = 0;
  284. m_fProgressBar = FALSE;
  285. m_fInternal = 0;
  286. m_dwIdentCookie = 0;
  287. m_pViewMenu = NULL;
  288. }
  289. CFindDlg::~CFindDlg()
  290. {
  291. SafeRelease(m_pViewMenu);
  292. _FreeFindInfo(&m_rFindInfo);
  293. SafeRelease(m_pStatusBar);
  294. SafeRelease(m_pMsgList);
  295. SafeRelease(m_pMsgListCT);
  296. SafeRelease(m_pCancel);
  297. AssertSz(!m_pPumpRefCount, "This should have been freed");
  298. if (m_hIcon)
  299. SideAssert(DestroyIcon(m_hIcon));
  300. if (m_hIconSm)
  301. SideAssert(DestroyIcon(m_hIconSm));
  302. CallbackCloseTimeout(&m_hTimeout);
  303. }
  304. //
  305. // FUNCTION: CFindDlg::QueryInterface()
  306. //
  307. // PURPOSE: Allows caller to retrieve the various interfaces supported by
  308. // this class.
  309. //
  310. HRESULT CFindDlg::QueryInterface(REFIID riid, LPVOID *ppvObj)
  311. {
  312. TraceCall("CFindDlg::QueryInterface");
  313. *ppvObj = NULL;
  314. if (IsEqualIID(riid, IID_IUnknown))
  315. *ppvObj = (LPVOID) (IUnknown *) (IDispatch *) this;
  316. else if (IsEqualIID(riid, IID_IDispatch))
  317. *ppvObj = (LPVOID) (IDispatch *) this;
  318. else if (IsEqualIID(riid, DIID__MessageListEvents))
  319. *ppvObj = (LPVOID) (IDispatch *) this;
  320. else if (IsEqualIID(riid, IID_IStoreCallback))
  321. *ppvObj = (LPVOID) (IStoreCallback *) this;
  322. else if (IsEqualIID(riid, IID_ITimeoutCallback))
  323. *ppvObj = (LPVOID) (ITimeoutCallback *) this;
  324. else if (IsEqualIID(riid, IID_IIdentityChangeNotify))
  325. *ppvObj = (LPVOID) (IIdentityChangeNotify *) this;
  326. else if (IsEqualIID(riid, IID_IOleCommandTarget))
  327. *ppvObj = (LPVOID) (IOleCommandTarget *) this;
  328. if (*ppvObj)
  329. {
  330. AddRef();
  331. return (S_OK);
  332. }
  333. return (E_NOINTERFACE);
  334. }
  335. //
  336. // FUNCTION: CFindDlg::AddRef()
  337. //
  338. // PURPOSE: Adds a reference count to this object.
  339. //
  340. ULONG CFindDlg::AddRef(void)
  341. {
  342. TraceCall("CFindDlg::AddRef");
  343. return ((ULONG) InterlockedIncrement((LONG *) &m_cRef));
  344. }
  345. //
  346. // FUNCTION: CFindDlg::Release()
  347. //
  348. // PURPOSE: Releases a reference on this object.
  349. //
  350. ULONG CFindDlg::Release(void)
  351. {
  352. TraceCall("CFindDlg::Release");
  353. if (0 == InterlockedDecrement((LONG *) &m_cRef))
  354. {
  355. delete this;
  356. return 0;
  357. }
  358. return (m_cRef);
  359. }
  360. //
  361. // FUNCTION: CFindDlg::Show()
  362. //
  363. // PURPOSE: Shows the finder dialog and provides a message pump for this
  364. // new thread.
  365. //
  366. void CFindDlg::Show(PFINDERPARAMS pFindParams)
  367. {
  368. // Validate this
  369. if (NULL == pFindParams)
  370. return;
  371. // Load the acclereator table for the finder
  372. if (NULL == m_hAccel)
  373. m_hAccel = LoadAcceleratorsWrapW(g_hLocRes, MAKEINTRESOURCEW(IDA_FIND_ACCEL));
  374. // Create the finder dialog
  375. m_hwnd = CreateDialogParamWrapW(g_hLocRes, MAKEINTRESOURCEW(IDD_FIND),
  376. NULL, ExtFindMsgDlgProc, (LPARAM) this);
  377. if (NULL == m_hwnd)
  378. return;
  379. // Create the message list
  380. HRESULT hr = CreateMessageList(NULL, &m_pMsgList);
  381. if (FAILED(hr))
  382. return;
  383. // Get some interfaces pointers from the message list that we'll need
  384. // later
  385. m_pMsgList->QueryInterface(IID_IOleCommandTarget, (LPVOID *) &m_pMsgListCT);
  386. AtlAdvise(m_pMsgList, (IUnknown *) (IDispatch *) this, DIID__MessageListEvents, &m_dwCookie);
  387. // Display the message list
  388. if (FAILED(m_pMsgList->CreateList(m_hwnd, (IDispatch *) this, &m_hwndList)))
  389. return;
  390. ShowWindow(m_hwndList, SW_HIDE);
  391. // Have the dialog redraw once or twice
  392. UpdateWindow(m_hwnd);
  393. // Fill in the folder list
  394. if (FAILED(InitFolderPickerEdit(GetDlgItem(m_hwnd, IDC_FOLDER), pFindParams->idFolder)))
  395. return;
  396. // Will be released in the WM_NCDESTROY message
  397. m_pPumpRefCount = new CPumpRefCount;
  398. if (!m_pPumpRefCount)
  399. return;
  400. }
  401. void CFindDlg::HandleMessage(LPMSG lpmsg)
  402. {
  403. HWND hwndTimeout;
  404. CNote *pNote = GetTlsGlobalActiveNote();
  405. // Give it to the active note if a note has focus, call it's XLateAccelerator...
  406. if (pNote && pNote->TranslateAccelerator(lpmsg) == S_OK)
  407. return;
  408. if (pNote && (pNote->IsMenuMessage(lpmsg) == S_OK))
  409. return;
  410. // Get Timeout Window for this thread
  411. hwndTimeout = (HWND)TlsGetValue(g_dwTlsTimeout);
  412. // Check for Is modeless timeout dialog window message
  413. if (hwndTimeout && TRUE == IsDialogMessageWrapW(hwndTimeout, lpmsg))
  414. return;
  415. if (m_hwnd)
  416. {
  417. // We have to do a little voodoo to get some keystrokes down to the
  418. // message list before IsDialogMessage() get's 'em
  419. if (lpmsg->message == WM_KEYDOWN)
  420. {
  421. if ((lpmsg->wParam == VK_DELETE) && m_pMsgList && (S_OK != m_pMsgList->HasFocus()))
  422. {
  423. if (!IsDialogMessageWrapW(m_hwnd, lpmsg))
  424. {
  425. TranslateMessage(lpmsg);
  426. DispatchMessageWrapW(lpmsg);
  427. }
  428. return;
  429. }
  430. if ((lpmsg->wParam == VK_RETURN) && m_pMsgList && (S_OK == m_pMsgList->HasFocus()))
  431. {
  432. if (!TranslateAcceleratorWrapW(m_hwnd, m_hAccel, lpmsg))
  433. {
  434. TranslateMessage(lpmsg);
  435. DispatchMessageWrapW(lpmsg);
  436. }
  437. return;
  438. }
  439. }
  440. if (m_hAccel && TranslateAcceleratorWrapW(m_hwnd, m_hAccel, lpmsg))
  441. return;
  442. if (IsDialogMessageWrapW(m_hwnd, lpmsg))
  443. return;
  444. }
  445. TranslateMessage(lpmsg);
  446. DispatchMessageWrapW(lpmsg);
  447. }
  448. //
  449. // FUNCTION: CFindDlg::Invoke()
  450. //
  451. // PURPOSE: Called by the message list to pass us progress and other
  452. // status / error messages.
  453. //
  454. // RETURN VALUE:
  455. // HRESULT
  456. //
  457. HRESULT CFindDlg::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
  458. WORD wFlags, DISPPARAMS* pDispParams,
  459. VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
  460. unsigned int* puArgErr)
  461. {
  462. switch (dispIdMember)
  463. {
  464. // Fired whenever the selection in the ListView changes
  465. case DISPID_LISTEVENT_SELECTIONCHANGED:
  466. {
  467. break;
  468. }
  469. // Fired when the number of messages or unread messages changes
  470. case DISPID_LISTEVENT_COUNTCHANGED:
  471. {
  472. if (!m_fProgressBar && m_pStatusBar)
  473. {
  474. TCHAR szStatus[CCHMAX_STRINGRES + 20];
  475. TCHAR szFmt[CCHMAX_STRINGRES];
  476. DWORD ids;
  477. if (m_fFindComplete)
  478. {
  479. AthLoadString(idsXMsgsYUnreadFind, szFmt, ARRAYSIZE(szFmt));
  480. wnsprintf(szStatus, ARRAYSIZE(szStatus), szFmt, pDispParams->rgvarg[0].lVal, pDispParams->rgvarg[1].lVal);
  481. }
  482. else
  483. {
  484. AthLoadString(idsXMsgsYUnread, szFmt, ARRAYSIZE(szFmt));
  485. wnsprintf(szStatus, ARRAYSIZE(szStatus), szFmt, pDispParams->rgvarg[0].lVal, pDispParams->rgvarg[1].lVal);
  486. }
  487. m_pStatusBar->SetStatusText(szStatus);
  488. }
  489. break;
  490. }
  491. // Fired when the user double clicks an item in the ListView
  492. case DISPID_LISTEVENT_ITEMACTIVATE:
  493. {
  494. CmdOpen(ID_OPEN, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  495. break;
  496. }
  497. }
  498. return (S_OK);
  499. }
  500. //
  501. // FUNCTION: CMessageView::QueryStatus()
  502. //
  503. // PURPOSE: Called by the browser to determine if a list of commands should
  504. // should be enabled or disabled.
  505. //
  506. // PARAMETERS:
  507. // [in] pguidCmdGroup - Group the commands are part of (unused)
  508. // [in] cCmds - Number of commands to be evaluated
  509. // [in] prgCmds - List of commands
  510. // [out] pCmdText - Description text for a command
  511. //
  512. // RETURN VALUE:
  513. // HRESULT
  514. //
  515. HRESULT CFindDlg::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[],
  516. OLECMDTEXT *pCmdText)
  517. {
  518. DWORD cSel;
  519. HRESULT hr;
  520. DWORD *rgSelected = 0;
  521. DWORD cFocus;
  522. MenuUtil_NewMessageIDsQueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText, TRUE);
  523. // Up front some work
  524. m_pMsgList->GetSelected(&cFocus, &cSel, &rgSelected);
  525. // Now loop through the commands in the prgCmds array looking for ones the
  526. // sub objects didn't handle.
  527. for (UINT i = 0; i < cCmds; i++)
  528. {
  529. if (prgCmds[i].cmdf == 0)
  530. {
  531. // If this command is from the language menu
  532. if (prgCmds[i].cmdID >= ID_LANG_FIRST && prgCmds[i].cmdID <= ID_LANG_LAST)
  533. {
  534. // Enable only the supported languages
  535. if (prgCmds[i].cmdID < (UINT) (ID_LANG_FIRST + GetIntlCharsetLanguageCount()))
  536. prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  537. else
  538. prgCmds[i].cmdf = OLECMDF_SUPPORTED;
  539. continue;
  540. }
  541. // if the command id from the View.Current View menu
  542. if ((ID_VIEW_FILTER_FIRST <= prgCmds[i].cmdID) && (ID_VIEW_FILTER_LAST >= prgCmds[i].cmdID))
  543. {
  544. if (NULL == m_pViewMenu)
  545. {
  546. // Create the view menu
  547. HrCreateViewMenu(VMF_FINDER, &m_pViewMenu);
  548. }
  549. if (NULL != m_pViewMenu)
  550. {
  551. m_pViewMenu->QueryStatus(m_pMsgList, &(prgCmds[i]));
  552. }
  553. continue;
  554. }
  555. // Look to see if it's a command we provide
  556. switch (prgCmds[i].cmdID)
  557. {
  558. case ID_OPEN:
  559. {
  560. // Enabled only if the focus is in the ListView and there
  561. // is at least one item selected.
  562. m_pMsgList->GetSelectedCount(&cSel);
  563. if (cSel)
  564. prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  565. else
  566. prgCmds[i].cmdf = OLECMDF_SUPPORTED;
  567. break;
  568. }
  569. case ID_OPEN_CONTAINING_FOLDER:
  570. {
  571. if (cSel == 1)
  572. prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  573. else
  574. prgCmds[i].cmdf = OLECMDF_SUPPORTED;
  575. break;
  576. }
  577. case ID_REPLY:
  578. case ID_REPLY_ALL:
  579. {
  580. // Enabled only if the focus is in the ListView and there
  581. // is only one item selected
  582. prgCmds[i].cmdf = OLECMDF_SUPPORTED;
  583. if (cSel == 1)
  584. {
  585. // The message's body must also be downloaded
  586. LPMESSAGEINFO pInfo;
  587. if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[0], &pInfo)))
  588. {
  589. if (pInfo->dwFlags & ARF_HASBODY)
  590. prgCmds[i].cmdf |= OLECMDF_ENABLED;
  591. m_pMsgList->FreeMessageInfo(pInfo);
  592. }
  593. }
  594. break;
  595. }
  596. case ID_FORWARD:
  597. case ID_FORWARD_AS_ATTACH:
  598. {
  599. // Enabled only if the focus is in the ListView and there
  600. // is only one item selected
  601. prgCmds[i].cmdf = OLECMDF_SUPPORTED;
  602. if (cSel > 0)
  603. {
  604. // The message's body must also be downloaded
  605. LPMESSAGEINFO pInfo;
  606. // Default to success
  607. prgCmds[i].cmdf |= OLECMDF_ENABLED;
  608. for (DWORD iItem = 0; iItem < cSel && (prgCmds[i].cmdf & OLECMDF_ENABLED); iItem++)
  609. {
  610. if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[iItem], &pInfo)))
  611. {
  612. if (0 == (pInfo->dwFlags & ARF_HASBODY))
  613. {
  614. prgCmds[i].cmdf &= ~OLECMDF_ENABLED;
  615. }
  616. m_pMsgList->FreeMessageInfo(pInfo);
  617. }
  618. }
  619. }
  620. break;
  621. }
  622. case ID_REPLY_GROUP:
  623. {
  624. // Enabled only if there is one news message selected
  625. prgCmds[i].cmdf = OLECMDF_SUPPORTED;
  626. if (cSel == 1)
  627. {
  628. // The message's body must also be downloaded
  629. LPMESSAGEINFO pInfo;
  630. if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[0], &pInfo)))
  631. {
  632. if ((pInfo->dwFlags & ARF_HASBODY) && (pInfo->dwFlags & ARF_NEWSMSG))
  633. prgCmds[i].cmdf |= OLECMDF_ENABLED;
  634. m_pMsgList->FreeMessageInfo(pInfo);
  635. }
  636. }
  637. break;
  638. }
  639. case ID_POPUP_FILTER:
  640. case ID_COLUMNS:
  641. case ID_POPUP_NEXT:
  642. case ID_POPUP_SORT:
  643. {
  644. prgCmds[i].cmdf = OLECMDF_SUPPORTED | (m_fShowResults ? OLECMDF_ENABLED : 0);
  645. break;
  646. }
  647. case ID_POPUP_NEW:
  648. case ID_CLOSE:
  649. {
  650. prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  651. break;
  652. }
  653. case ID_REFRESH:
  654. {
  655. if (m_fShowResults && IsWindowEnabled(GetDlgItem(m_hwnd, IDC_FIND_NOW)))
  656. prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  657. else
  658. prgCmds[i].cmdf = OLECMDF_SUPPORTED;
  659. break;
  660. }
  661. case ID_BLOCK_SENDER:
  662. {
  663. prgCmds[i].cmdf = OLECMDF_SUPPORTED;
  664. // Enabled only if there is only one item selected and
  665. // we have access to the from address
  666. if (cSel == 1)
  667. {
  668. // The message's body must also be downloaded
  669. LPMESSAGEINFO pInfo;
  670. if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[0], &pInfo)))
  671. {
  672. if (((NULL != pInfo->pszEmailFrom) && ('\0' != pInfo->pszEmailFrom[0])) || (0 != pInfo->faStream))
  673. prgCmds[i].cmdf |= OLECMDF_ENABLED;
  674. m_pMsgList->FreeMessageInfo(pInfo);
  675. }
  676. }
  677. break;
  678. }
  679. case ID_CREATE_RULE_FROM_MESSAGE:
  680. {
  681. prgCmds[i].cmdf = OLECMDF_SUPPORTED;
  682. // Enabled only if there is only one item selected
  683. if (cSel == 1)
  684. {
  685. // Make sure we have a message info
  686. LPMESSAGEINFO pInfo;
  687. if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[0], &pInfo)))
  688. {
  689. prgCmds[i].cmdf |= OLECMDF_ENABLED;
  690. m_pMsgList->FreeMessageInfo(pInfo);
  691. }
  692. }
  693. break;
  694. }
  695. case ID_COMBINE_AND_DECODE:
  696. {
  697. // Enabled only if the focus is in the ListView and there
  698. // is at least one item selected.
  699. if (cSel > 1)
  700. prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  701. else
  702. prgCmds[i].cmdf = OLECMDF_SUPPORTED;
  703. break;
  704. }
  705. case ID_CANCEL_MESSAGE:
  706. {
  707. prgCmds[i].cmdf = OLECMDF_SUPPORTED;
  708. if (DwGetOption(OPT_CANCEL_ALL_NEWS))
  709. prgCmds[i].cmdf |= OLECMDF_ENABLED;
  710. else
  711. {
  712. if (cSel == 1)
  713. {
  714. FOLDERID idFolder;
  715. LPMESSAGEINFO pInfo;
  716. if (SUCCEEDED(m_pMsgList->GetMessageInfo(rgSelected[0], &pInfo)))
  717. {
  718. if (SUCCEEDED(m_pMsgList->GetRowFolderId(rgSelected[0], &idFolder)))
  719. {
  720. if (NewsUtil_FCanCancel(idFolder, pInfo))
  721. {
  722. prgCmds[i].cmdf |= OLECMDF_ENABLED;
  723. }
  724. }
  725. m_pMsgList->FreeMessageInfo(pInfo);
  726. }
  727. }
  728. }
  729. break;
  730. }
  731. }
  732. }
  733. }
  734. MemFree(rgSelected);
  735. // Let the sub objects look last, so we can get ID_REFRESH before them
  736. if (m_pMsgListCT)
  737. {
  738. hr = m_pMsgListCT->QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText);
  739. }
  740. return (S_OK);
  741. }
  742. //
  743. // FUNCTION: CMessageView::Exec()
  744. //
  745. // PURPOSE: Called to execute a verb that this view supports
  746. //
  747. // PARAMETERS:
  748. // [in] pguidCmdGroup - unused
  749. // [in] nCmdID - ID of the command to execute
  750. // [in] nCmdExecOpt - Options that define how the command should execute
  751. // [in] pvaIn - Any arguments for the command
  752. // [out] pvaOut - Any return values for the command
  753. //
  754. // RETURN VALUE:
  755. //
  756. //
  757. HRESULT CFindDlg::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt,
  758. VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  759. {
  760. // If the sub objects didn't support the command, then we should see if
  761. // it's one of ours
  762. // Language menu first
  763. if (nCmdID >= ID_LANG_FIRST && nCmdID <= ID_LANG_LAST)
  764. {
  765. // $REVIEW - Not implemented
  766. // SwitchLanguage(nCmdID, TRUE);
  767. return (S_OK);
  768. }
  769. // Handle the View.Current View menu
  770. if ((ID_VIEW_FILTER_FIRST <= nCmdID) && (ID_VIEW_FILTER_LAST >= nCmdID))
  771. {
  772. if (NULL == m_pViewMenu)
  773. {
  774. // Create the view menu
  775. HrCreateViewMenu(VMF_FINDER, &m_pViewMenu);
  776. }
  777. if (NULL != m_pViewMenu)
  778. {
  779. if (SUCCEEDED(m_pViewMenu->Exec(m_hwnd, nCmdID, m_pMsgList, pvaIn, pvaOut)))
  780. {
  781. return (S_OK);
  782. }
  783. }
  784. }
  785. if (MenuUtil_HandleNewMessageIDs(nCmdID, m_hwnd, FOLDERID_INVALID, TRUE, FALSE, (IUnknown *) (IDispatch *) this))
  786. return S_OK;
  787. // Go through the rest of the commands
  788. switch (nCmdID)
  789. {
  790. case ID_OPEN:
  791. return CmdOpen(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  792. case ID_OPEN_CONTAINING_FOLDER:
  793. return CmdOpenFolder(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  794. case ID_REPLY:
  795. case ID_REPLY_ALL:
  796. case ID_FORWARD:
  797. case ID_FORWARD_AS_ATTACH:
  798. case ID_REPLY_GROUP:
  799. return CmdReplyForward(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  800. case ID_REFRESH:
  801. case IDC_FIND_NOW:
  802. return CmdFindNow(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  803. case IDC_STOP:
  804. return CmdStop(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  805. case IDC_BROWSE_FOLDER:
  806. return CmdBrowseForFolder(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  807. case IDC_RESET:
  808. return CmdReset(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  809. case ID_BLOCK_SENDER:
  810. return CmdBlockSender(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  811. case ID_CREATE_RULE_FROM_MESSAGE:
  812. return CmdCreateRule(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  813. case ID_COMBINE_AND_DECODE:
  814. return CmdCombineAndDecode(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  815. case ID_CLOSE:
  816. case IDCANCEL:
  817. {
  818. if (m_fInProgress)
  819. {
  820. CmdStop(ID_STOP, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
  821. m_fClose = TRUE;
  822. }
  823. else
  824. {
  825. DestroyWindow(m_hwnd);
  826. }
  827. return (S_OK);
  828. }
  829. case ID_CANCEL_MESSAGE:
  830. return CmdCancelMessage(nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  831. }
  832. // See if our message list wants the command
  833. if (m_pMsgListCT)
  834. {
  835. if (OLECMDERR_E_NOTSUPPORTED != m_pMsgListCT->Exec(pguidCmdGroup, nCmdID, nCmdExecOpt, pvaIn, pvaOut))
  836. return (S_OK);
  837. }
  838. return (OLECMDERR_E_NOTSUPPORTED);
  839. }
  840. //
  841. // FUNCTION: CFindDlg::OnBegin()
  842. //
  843. // PURPOSE: Called whenever the store is about to start some operation.
  844. //
  845. HRESULT CFindDlg::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pOpInfo,
  846. IOperationCancel *pCancel)
  847. {
  848. TraceCall("CFindDlg::OnBegin");
  849. Assert(pCancel != NULL);
  850. Assert(m_pCancel == NULL);
  851. m_pCancel = pCancel;
  852. m_pCancel->AddRef();
  853. if (m_fAbort)
  854. m_pCancel->Cancel(CT_CANCEL);
  855. return(S_OK);
  856. }
  857. //
  858. // FUNCTION: CFindDlg::OnProgress()
  859. //
  860. // PURPOSE: Called during the find, download, etc.
  861. //
  862. HRESULT CFindDlg::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent,
  863. DWORD dwMax, LPCSTR pszStatus)
  864. {
  865. MSG msg;
  866. TraceCall("CFindDlg::OnProgress");
  867. // If we had a timeout dialog up, we can close it since data just became
  868. // available.
  869. CallbackCloseTimeout(&m_hTimeout);
  870. // If it's find, show progress
  871. if (SOT_SEARCHING == tyOperation)
  872. {
  873. if (m_pStatusBar && pszStatus)
  874. {
  875. TCHAR szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES];
  876. AthLoadString(idsSearching, szRes, ARRAYSIZE(szRes));
  877. wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, pszStatus);
  878. m_pStatusBar->SetStatusText((LPTSTR) szBuf);
  879. }
  880. if (!m_fProgressBar && m_pStatusBar)
  881. {
  882. m_pStatusBar->ShowProgress(dwMax);
  883. m_fProgressBar = TRUE;
  884. }
  885. if (m_pStatusBar && dwMax)
  886. {
  887. m_pStatusBar->SetProgress(dwCurrent);
  888. }
  889. }
  890. // Pump messages a bit so the UI is responsive.
  891. while (PeekMessageWrapW(&msg, NULL, 0, 0, PM_REMOVE))
  892. HandleMessage(&msg);
  893. return (S_OK);
  894. }
  895. //
  896. // FUNCTION: CFindDlg::OnComplete()
  897. //
  898. // PURPOSE: Called when the store operation is complete
  899. //
  900. HRESULT CFindDlg::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
  901. {
  902. TraceCall("CFindDlg::OnComplete");
  903. // Close any timeout dialog, if present
  904. CallbackCloseTimeout(&m_hTimeout);
  905. // Display an Error on Failures
  906. if (FAILED(hrComplete))
  907. {
  908. // Call into my swanky utility
  909. CallbackDisplayError(m_hwnd, hrComplete, pErrorInfo);
  910. }
  911. if (SOT_SEARCHING == tyOperation)
  912. {
  913. // Hide the status bar
  914. if (m_fProgressBar && m_pStatusBar)
  915. {
  916. m_pStatusBar->HideProgress();
  917. m_fProgressBar = FALSE;
  918. m_fFindComplete = TRUE;
  919. }
  920. Assert(m_pCancel != NULL);
  921. m_pCancel->Release();
  922. m_pCancel = NULL;
  923. }
  924. // Update the status text
  925. IOEMessageList *pList;
  926. if (SUCCEEDED(m_pMsgList->QueryInterface(IID_IOEMessageList, (LPVOID *) &pList)))
  927. {
  928. long lCount, lUnread;
  929. TCHAR szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES];
  930. pList->get_Count(&lCount);
  931. pList->get_UnreadCount(&lUnread);
  932. AthLoadString(idsXMsgsYUnreadFind, szRes, ARRAYSIZE(szRes));
  933. wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, lCount, lUnread);
  934. m_pStatusBar->SetStatusText(szBuf);
  935. pList->Release();
  936. }
  937. // Select the first row
  938. IListSelector *pSelect;
  939. if (SUCCEEDED(m_pMsgList->GetListSelector(&pSelect)))
  940. {
  941. pSelect->SetActiveRow(0);
  942. pSelect->Release();
  943. }
  944. return(S_OK);
  945. }
  946. STDMETHODIMP CFindDlg::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
  947. {
  948. // Display a timeout dialog
  949. return CallbackOnTimeout(pServer, ixpServerType, *pdwTimeout, (ITimeoutCallback *)this, &m_hTimeout);
  950. }
  951. STDMETHODIMP CFindDlg::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
  952. {
  953. // Call into general CanConnect Utility
  954. return CallbackCanConnect(pszAccountId, m_hwnd, FALSE);
  955. }
  956. STDMETHODIMP CFindDlg::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType)
  957. {
  958. // Close any timeout dialog, if present
  959. CallbackCloseTimeout(&m_hTimeout);
  960. // Call into general OnLogonPrompt Utility
  961. return CallbackOnLogonPrompt(m_hwnd, pServer, ixpServerType);
  962. }
  963. STDMETHODIMP CFindDlg::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse)
  964. {
  965. // Close any timeout dialog, if present
  966. CallbackCloseTimeout(&m_hTimeout);
  967. // Call into my swanky utility
  968. return CallbackOnPrompt(m_hwnd, hrError, pszText, pszCaption, uType, piUserResponse);
  969. }
  970. STDMETHODIMP CFindDlg::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
  971. {
  972. *phwndParent = m_hwnd;
  973. return(S_OK);
  974. }
  975. STDMETHODIMP CFindDlg::OnTimeoutResponse(TIMEOUTRESPONSE eResponse)
  976. {
  977. // Call into general timeout response utility
  978. return CallbackOnTimeoutResponse(eResponse, m_pCancel, &m_hTimeout);
  979. }
  980. INT_PTR CALLBACK CFindDlg::ExtFindMsgDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  981. {
  982. CFindDlg *pThis;
  983. if (msg == WM_INITDIALOG)
  984. {
  985. SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  986. pThis = (CFindDlg*)lParam;
  987. }
  988. else
  989. pThis = (CFindDlg*)GetWindowLongPtr(hwnd, DWLP_USER);
  990. if (pThis)
  991. return pThis->DlgProc(hwnd, msg, wParam, lParam);
  992. return FALSE;
  993. }
  994. //
  995. // FUNCTION: CFindDlg::DlgProc()
  996. //
  997. // PURPOSE: Groovy dialog proc.
  998. //
  999. INT_PTR CFindDlg::DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1000. {
  1001. HWND hwndActive;
  1002. switch (msg)
  1003. {
  1004. case WM_INITDIALOG:
  1005. return (BOOL)HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, OnInitDialog);
  1006. case WM_PAINT:
  1007. HANDLE_WM_PAINT(hwnd, wParam, lParam, OnPaint);
  1008. return TRUE;
  1009. case WM_SIZE:
  1010. HANDLE_WM_SIZE(hwnd, wParam, lParam, OnSize);
  1011. return TRUE;
  1012. case WM_GETMINMAXINFO:
  1013. HANDLE_WM_GETMINMAXINFO(hwnd, wParam, lParam, OnGetMinMaxInfo);
  1014. return TRUE;
  1015. case WM_INITMENUPOPUP:
  1016. HANDLE_WM_INITMENUPOPUP(hwnd, wParam, lParam, OnInitMenuPopup);
  1017. return TRUE;
  1018. case WM_MENUSELECT:
  1019. // HANDLE_WM_MENUSELECT() has a bug in it, don't use it.
  1020. if (LOWORD(wParam) >= ID_STATIONERY_RECENT_0 && LOWORD(wParam) <= ID_STATIONERY_RECENT_9)
  1021. m_pStatusBar->ShowSimpleText(MAKEINTRESOURCE(idsRSListGeneralHelp));
  1022. else
  1023. HandleMenuSelect(m_pStatusBar, wParam, lParam);
  1024. return TRUE;
  1025. case WM_WININICHANGE:
  1026. HANDLE_WM_WININICHANGE(hwnd, wParam, lParam, OnWinIniChange);
  1027. return TRUE;
  1028. case WM_COMMAND:
  1029. HANDLE_WM_COMMAND(hwnd, wParam, lParam, OnCommand);
  1030. return TRUE;
  1031. case WM_NOTIFY:
  1032. HANDLE_WM_NOTIFY(hwnd, wParam, lParam, OnNotify);
  1033. return TRUE;
  1034. case WM_DESTROY:
  1035. // case WM_CLOSE:
  1036. HANDLE_WM_DESTROY(hwnd, wParam, lParam, OnDestroy);
  1037. return TRUE;
  1038. case WM_NCDESTROY:
  1039. m_pPumpRefCount->Release();
  1040. m_pPumpRefCount = NULL;
  1041. m_hwnd = 0;
  1042. break;
  1043. case WM_ENABLE:
  1044. if (!m_fInternal)
  1045. {
  1046. Assert (wParam || (m_hlDisabled.cHwnd == NULL && m_hlDisabled.rgHwnd == NULL));
  1047. EnableThreadWindows(&m_hlDisabled, (NULL != wParam), ETW_OE_WINDOWS_ONLY, hwnd);
  1048. g_hwndActiveModal = wParam ? NULL : hwnd;
  1049. }
  1050. break;
  1051. case WM_ACTIVATEAPP:
  1052. if (wParam && g_hwndActiveModal && g_hwndActiveModal != hwnd &&
  1053. !IsWindowEnabled(hwnd))
  1054. {
  1055. // $MODAL
  1056. // if we are getting activated, and are disabled then
  1057. // bring our 'active' window to the top
  1058. Assert (IsWindow(g_hwndActiveModal));
  1059. PostMessage(g_hwndActiveModal, WM_OE_ACTIVATETHREADWINDOW, 0, 0);
  1060. }
  1061. break;
  1062. case WM_OE_ACTIVATETHREADWINDOW:
  1063. hwndActive = GetLastActivePopup(hwnd);
  1064. if (hwndActive && IsWindowEnabled(hwndActive) && IsWindowVisible(hwndActive))
  1065. ActivatePopupWindow(hwndActive);
  1066. break;
  1067. case WM_OE_ENABLETHREADWINDOW:
  1068. m_fInternal = 1;
  1069. EnableWindow(hwnd, (BOOL)wParam);
  1070. m_fInternal = 0;
  1071. break;
  1072. }
  1073. return FALSE;
  1074. }
  1075. //
  1076. // FUNCTION: CFindDlg::OnInitDialog()
  1077. //
  1078. // PURPOSE: Initializes the UI in the dialog box. Also prep's the sizing
  1079. // info so the dialog can be resized.
  1080. //
  1081. BOOL CFindDlg::OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  1082. {
  1083. RECT rc, rcClient;
  1084. RECT rcEdit;
  1085. WINDOWPLACEMENT wp;
  1086. HMENU hMenu;
  1087. TraceCall("CFindDlg::OnInitDialog");
  1088. // We do this so we can enable and disable correctly when modal windows
  1089. // are visible
  1090. SetProp(hwnd, c_szOETopLevel, (HANDLE)TRUE);
  1091. // Get some sizing info
  1092. _InitSizingInfo(hwnd);
  1093. // Hide the status bar until we've been expanded
  1094. ShowWindow(GetDlgItem(hwnd, IDC_STATUS_BAR), SW_HIDE);
  1095. // Set the title bar icon
  1096. Assert (m_hIconSm == NULL && m_hIcon == NULL);
  1097. m_hIcon = (HICON)LoadImage(g_hLocRes, MAKEINTRESOURCE(idiFind), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0);
  1098. SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)m_hIcon);
  1099. m_hIconSm = (HICON)LoadImage(g_hLocRes, MAKEINTRESOURCE(idiFind), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
  1100. SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)m_hIconSm);
  1101. // Set the dialog template fonts correctly
  1102. _SetFindIntlFont(hwnd);
  1103. // Initialize the find information
  1104. _SetFindValues(hwnd, &m_rFindInfo);
  1105. // Disable the find and stop buttons
  1106. EnableWindow(GetDlgItem(hwnd, IDC_FIND_NOW), _IsFindEnabled(hwnd));
  1107. EnableWindow(GetDlgItem(hwnd, IDC_STOP), FALSE);
  1108. CheckDlgButton(hwnd, IDC_INCLUDE_SUB, BST_CHECKED);
  1109. // Create a status bar object for our status bar
  1110. m_pStatusBar = new CStatusBar();
  1111. if (m_pStatusBar)
  1112. m_pStatusBar->Initialize(hwnd, SBI_HIDE_SPOOLER | SBI_HIDE_CONNECTED | SBI_HIDE_FILTERED);
  1113. // We have menus on this window
  1114. hMenu = LoadMenu(g_hLocRes, MAKEINTRESOURCE(IDR_FIND_MENU));
  1115. MenuUtil_ReplaceNewMsgMenus(hMenu);
  1116. SetMenu(hwnd, hMenu);
  1117. // Register with identity manager
  1118. if (m_dwIdentCookie == 0)
  1119. SideAssert(SUCCEEDED(MU_RegisterIdentityNotifier((IUnknown *)(IAthenaBrowser *)this, &m_dwIdentCookie)));
  1120. SetForegroundWindow(hwnd);
  1121. return TRUE;
  1122. }
  1123. //
  1124. // FUNCTION: CFindDlg::OnSize()
  1125. //
  1126. // PURPOSE: When the dialog get's sized, we have to move a whole bunch
  1127. // of stuff around. Don't try this at home.
  1128. //
  1129. void CFindDlg::OnSize(HWND hwnd, UINT state, int cx, int cy)
  1130. {
  1131. HDWP hdwp;
  1132. HWND hwndStatus;
  1133. HWND hwndTo;
  1134. int dx;
  1135. // If we're minimized, don't do anything
  1136. if (state == SIZE_MINIMIZED)
  1137. return;
  1138. // This is the delta for our horizontal size.
  1139. dx = cx - m_cxDlgDef;
  1140. // Make sure the status bar get's updated
  1141. hwndStatus = GetDlgItem(hwnd, IDC_STATUS_BAR);
  1142. SendMessage(hwndStatus, WM_SIZE, 0, 0L);
  1143. if (m_pStatusBar)
  1144. m_pStatusBar->OnSize(cx, cy);
  1145. // Do all the sizing updates at once to make everything smoother
  1146. hdwp = BeginDeferWindowPos(15);
  1147. if (hdwp)
  1148. {
  1149. DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_FOLDER), NULL, 0, 0, (dx + m_cxFolder), m_cyEdit, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  1150. DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_INCLUDE_SUB), NULL, m_xIncSub + dx, m_yIncSub, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
  1151. DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_BROWSE_FOLDER), NULL, m_xBtn + dx, m_yBrowse, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
  1152. DeferWindowPos(hdwp, GetDlgItem(hwnd, idcStatic1), NULL, 0, 0, m_cxStatic + dx, 2, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  1153. DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_FIND_NOW), NULL, m_xBtn + dx, m_yBtn, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
  1154. DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_STOP), NULL, m_xBtn + dx, m_yBtn + m_dyBtn, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
  1155. DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_RESET), NULL, m_xBtn + dx, m_yBtn + 2 * m_dyBtn, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
  1156. DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_FROM), NULL, 0, 0, m_cxEdit + dx, m_cyEdit, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  1157. DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_TO), NULL, 0, 0, m_cxEdit + dx, m_cyEdit, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  1158. DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_SUBJECT), NULL, 0, 0, m_cxEdit + dx, m_cyEdit, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  1159. DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_BODY), NULL, 0, 0, m_cxEdit + dx, m_cyEdit, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  1160. // ALERT:
  1161. // if you add more controls here be sure to UP the value passed
  1162. // to BeginDeferWindowPos otherwise user will REALLOC and passback
  1163. // a new value to hdwp
  1164. EndDeferWindowPos(hdwp);
  1165. }
  1166. // If the bottom is exposed (oh my) resize the message list to fit between the
  1167. // bottom of the dialog and the top of the status bar.
  1168. if (m_fShowResults)
  1169. {
  1170. RECT rcStatus;
  1171. GetClientRect(hwndStatus, &rcStatus);
  1172. MapWindowRect(hwndStatus, hwnd, &rcStatus);
  1173. rcStatus.bottom = rcStatus.top - m_yView;
  1174. rcStatus.top = m_yView;
  1175. rcStatus.right -= rcStatus.left;
  1176. m_pMsgList->SetRect(rcStatus);
  1177. }
  1178. }
  1179. //
  1180. // FUNCTION: CFindDlg::OnPaint()
  1181. //
  1182. // PURPOSE: All this just to paint a separator line between the menu bar
  1183. // and the rest of the menu.
  1184. //
  1185. void CFindDlg::OnPaint(HWND hwnd)
  1186. {
  1187. PAINTSTRUCT ps;
  1188. RECT rc;
  1189. // If we're not minimized
  1190. if (!IsIconic(hwnd))
  1191. {
  1192. // Draw that lovely line
  1193. BeginPaint(hwnd, &ps);
  1194. GetClientRect(hwnd, &rc);
  1195. DrawEdge(ps.hdc, &rc, EDGE_ETCHED, BF_TOP);
  1196. EndPaint(hwnd, &ps);
  1197. }
  1198. }
  1199. //
  1200. // FUNCTION: CFindDlg::OnGetMinMaxInfo()
  1201. //
  1202. // PURPOSE: Called by Windows when we're resizing to see what our minimum
  1203. // and maximum sizes are.
  1204. //
  1205. void CFindDlg::OnGetMinMaxInfo(HWND hwnd, LPMINMAXINFO lpmmi)
  1206. {
  1207. TraceCall("CFindDlg::OnGetMinMaxInfo");
  1208. // Let Window's do most of the work
  1209. DefWindowProcWrapW(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)lpmmi);
  1210. // Override the minimum track size to be the size or our template
  1211. lpmmi->ptMinTrackSize = m_ptDragMin;
  1212. // Make sure to adjust for the height of the message list
  1213. if (!m_fShowResults)
  1214. lpmmi->ptMaxTrackSize.y = m_ptDragMin.y;
  1215. }
  1216. //
  1217. // FUNCTION: CFindDlg::OnInitMenuPopup()
  1218. //
  1219. // PURPOSE: Called before the menus are displayed.
  1220. //
  1221. void CFindDlg::OnInitMenuPopup(HWND hwnd, HMENU hmenuPopup, UINT uPos, BOOL fSystemMenu)
  1222. {
  1223. MENUITEMINFO mii;
  1224. UINT uIDPopup;
  1225. HMENU hMenu = GetMenu(hwnd);
  1226. TraceCall("CFindDlg::OnInitMenuPopup");
  1227. ZeroMemory(&mii, sizeof(mii));
  1228. mii.cbSize = sizeof(MENUITEMINFO);
  1229. mii.fMask = MIIM_ID | MIIM_SUBMENU;
  1230. // make sure we recognize the popup as one of ours
  1231. if (hMenu == NULL || !GetMenuItemInfo(hMenu, uPos, TRUE, &mii) || (hmenuPopup != mii.hSubMenu))
  1232. {
  1233. HMENU hMenuDrop = NULL;
  1234. int ulIndex = 0;
  1235. int cMenus = 0;
  1236. cMenus = GetMenuItemCount(hMenu);
  1237. // Try to fix up the top level popups
  1238. for (ulIndex = 0; ulIndex < cMenus; ulIndex++)
  1239. {
  1240. // Get the drop down menu
  1241. hMenuDrop = GetSubMenu(hMenu, ulIndex);
  1242. if (NULL == hMenuDrop)
  1243. {
  1244. continue;
  1245. }
  1246. // Initialize the menu info
  1247. mii.cbSize = sizeof(MENUITEMINFO);
  1248. mii.fMask = MIIM_ID | MIIM_SUBMENU;
  1249. if (FALSE == GetMenuItemInfo(hMenuDrop, uPos, TRUE, &mii))
  1250. {
  1251. continue;
  1252. }
  1253. if (hmenuPopup == mii.hSubMenu)
  1254. {
  1255. break;
  1256. }
  1257. }
  1258. // Did we find anything?
  1259. if (ulIndex >= cMenus)
  1260. {
  1261. goto exit;
  1262. }
  1263. }
  1264. uIDPopup = mii.wID;
  1265. // Must have stationery
  1266. switch (uIDPopup)
  1267. {
  1268. case ID_POPUP_MESSAGE:
  1269. AddStationeryMenu(hmenuPopup, ID_POPUP_NEW_MSG, ID_STATIONERY_RECENT_0, ID_STATIONERY_MORE);
  1270. break;
  1271. case ID_POPUP_FILE:
  1272. DeleteMenu(hmenuPopup, ID_SEND_INSTANT_MESSAGE, MF_BYCOMMAND);
  1273. break;
  1274. case ID_POPUP_VIEW:
  1275. if (NULL == m_pViewMenu)
  1276. {
  1277. // Create the view menu
  1278. HrCreateViewMenu(VMF_FINDER, &m_pViewMenu);
  1279. }
  1280. if (NULL != m_pViewMenu)
  1281. {
  1282. mii.cbSize = sizeof(MENUITEMINFO);
  1283. mii.fMask = MIIM_SUBMENU;
  1284. if (FALSE == GetMenuItemInfo(hmenuPopup, ID_POPUP_FILTER, FALSE, &mii))
  1285. {
  1286. break;
  1287. }
  1288. // Remove the old filter submenu
  1289. if(IsMenu(mii.hSubMenu))
  1290. DestroyMenu(mii.hSubMenu);
  1291. // Replace the view menu
  1292. if (FAILED(m_pViewMenu->HrReplaceMenu(0, hmenuPopup)))
  1293. {
  1294. break;
  1295. }
  1296. }
  1297. break;
  1298. case ID_POPUP_FILTER:
  1299. if (NULL != m_pViewMenu)
  1300. {
  1301. m_pViewMenu->UpdateViewMenu(0, hmenuPopup, m_pMsgList);
  1302. }
  1303. break;
  1304. }
  1305. // Let the message list initialize it
  1306. if (m_pMsgList)
  1307. m_pMsgList->OnPopupMenu(hmenuPopup, uIDPopup);
  1308. // now enable/disable the items
  1309. MenuUtil_EnablePopupMenu(hmenuPopup, this);
  1310. exit:
  1311. return;
  1312. }
  1313. //
  1314. // FUNCTION: CFindDlg::OnMenuSelect()
  1315. //
  1316. // PURPOSE: Puts the menu help text on the status bar.
  1317. //
  1318. void CFindDlg::OnMenuSelect(HWND hwnd, HMENU hmenu, int item, HMENU hmenuPopup, UINT flags)
  1319. {
  1320. if (m_pStatusBar)
  1321. {
  1322. // If this is the stationery menu, special case it
  1323. if (item >= ID_STATIONERY_RECENT_0 && item <= ID_STATIONERY_RECENT_9)
  1324. m_pStatusBar->ShowSimpleText(MAKEINTRESOURCE(idsRSListGeneralHelp));
  1325. else
  1326. HandleMenuSelect(m_pStatusBar, MAKEWPARAM(item, flags), hmenu ? (LPARAM) hmenu : (LPARAM) hmenuPopup);
  1327. }
  1328. }
  1329. //
  1330. // FUNCTION: CFindDlg::OnWinIniChange()
  1331. //
  1332. // PURPOSE: Handles updates of fonts, colors, etc.
  1333. //
  1334. void CFindDlg::OnWinIniChange(HWND hwnd, LPCTSTR lpszSectionName)
  1335. {
  1336. // Forward this off to our date picker controls
  1337. FORWARD_WM_WININICHANGE(GetDlgItem(hwnd, IDC_DATE_FROM), lpszSectionName, SendMessage);
  1338. FORWARD_WM_WININICHANGE(GetDlgItem(hwnd, IDC_DATE_TO), lpszSectionName, SendMessage);
  1339. }
  1340. //
  1341. // FUNCTION: CFindDlg::OnCommand()
  1342. //
  1343. // PURPOSE: Handles commands generated by the finder.
  1344. //
  1345. void CFindDlg::OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  1346. {
  1347. HRESULT hr = S_OK;
  1348. // We need to grab some of the notifications sent to us first
  1349. if ((codeNotify == EN_CHANGE) ||
  1350. (codeNotify == BN_CLICKED && (id == IDC_HAS_FLAG || id == IDC_HAS_ATTACH)))
  1351. {
  1352. EnableWindow(GetDlgItem(hwnd, IDC_FIND_NOW), _IsFindEnabled(hwnd) && !m_fInProgress);
  1353. return;
  1354. }
  1355. // If this is from a menu, then first see if the message list wants
  1356. // to handle it.
  1357. if (NULL == hwndCtl)
  1358. {
  1359. // Check to see if the command is even enabled
  1360. if (id >= ID_FIRST)
  1361. {
  1362. OLECMD cmd;
  1363. cmd.cmdID = id;
  1364. cmd.cmdf = 0;
  1365. hr = QueryStatus(&CMDSETID_OutlookExpress, 1, &cmd, NULL);
  1366. if (FAILED(hr) || (0 == (cmd.cmdf & OLECMDF_ENABLED)))
  1367. return;
  1368. }
  1369. if (m_pMsgListCT)
  1370. {
  1371. hr = m_pMsgListCT->Exec(&CMDSETID_OEMessageList, id, OLECMDEXECOPT_DODEFAULT,
  1372. NULL, NULL);
  1373. if (S_OK == hr)
  1374. return;
  1375. }
  1376. }
  1377. // Otherwise, it goes to the command target
  1378. VARIANTARG va;
  1379. va.vt = VT_I4;
  1380. va.lVal = codeNotify;
  1381. hr = Exec(NULL, id, OLECMDEXECOPT_DODEFAULT, &va, NULL);
  1382. return;
  1383. }
  1384. //
  1385. // FUNCTION: CFindDlg::OnNotify()
  1386. //
  1387. // PURPOSE: Handles notifications from the date pickers
  1388. //
  1389. LRESULT CFindDlg::OnNotify(HWND hwnd, int idFrom, LPNMHDR pnmhdr)
  1390. {
  1391. if (DTN_DATETIMECHANGE == pnmhdr->code)
  1392. EnableWindow(GetDlgItem(hwnd, IDC_FIND_NOW), _IsFindEnabled(hwnd));
  1393. return (0);
  1394. }
  1395. //
  1396. // FUNCTION: CFindDlg::OnDestroy()
  1397. //
  1398. // PURPOSE: Clean up the message list now that we're being shut down and
  1399. // also save our size etc.
  1400. //
  1401. void CFindDlg::OnDestroy(HWND hwnd)
  1402. {
  1403. WINDOWPLACEMENT wp;
  1404. // Save the sizing information
  1405. wp.length = sizeof(wp);
  1406. GetWindowPlacement(hwnd, &wp);
  1407. SetOption(OPT_FINDER_POS, (LPBYTE)&wp, sizeof(wp), NULL, 0);
  1408. // Unregister with Identity manager
  1409. if (m_dwIdentCookie != 0)
  1410. {
  1411. MU_UnregisterIdentityNotifier(m_dwIdentCookie);
  1412. m_dwIdentCookie = 0;
  1413. }
  1414. // Clean up the property
  1415. RemoveProp(hwnd, c_szOETopLevel);
  1416. // Stop receieving notifications
  1417. AtlUnadvise(m_pMsgList, DIID__MessageListEvents, m_dwCookie);
  1418. // Tell the message list to release it's folder
  1419. m_pMsgList->SetFolder(FOLDERID_INVALID, NULL, FALSE, NULL, NOSTORECALLBACK);
  1420. // Close the message list
  1421. m_pMsgList->OnClose();
  1422. }
  1423. //
  1424. // FUNCTION: CFindDlg::CmdOpen()
  1425. //
  1426. // PURPOSE: Called when the user want's to open a message that they've found.
  1427. //
  1428. HRESULT CFindDlg::CmdOpen(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn,
  1429. VARIANTARG *pvaOut)
  1430. {
  1431. HRESULT hr;
  1432. TraceCall("CMessageView::CmdOpen");
  1433. // If more than 10 messages are selected, warn the user with a "Don't show
  1434. // me again" dialog that this could be bad.
  1435. DWORD dwSel = 0;
  1436. m_pMsgList->GetSelectedCount(&dwSel);
  1437. if (dwSel > 10)
  1438. {
  1439. TCHAR szBuffer[CCHMAX_STRINGRES];
  1440. LRESULT lResult;
  1441. AthLoadString(idsErrOpenManyMessages, szBuffer, ARRAYSIZE(szBuffer));
  1442. lResult = DoDontShowMeAgainDlg(m_hwnd, c_szRegManyMsgWarning,
  1443. MAKEINTRESOURCE(idsAthena), szBuffer,
  1444. MB_OKCANCEL);
  1445. if (IDCANCEL == lResult)
  1446. return (S_OK);
  1447. }
  1448. // Get the array of selected rows from the message list
  1449. DWORD *rgRows = NULL;
  1450. DWORD cRows = 0;
  1451. if (FAILED(hr = m_pMsgList->GetSelected(NULL, &cRows, &rgRows)))
  1452. return (hr);
  1453. // It's possible for the message list to go away while we're doing this.
  1454. // To keep us from crashing, make sure you verify it still exists during
  1455. // the loop.
  1456. LPMESSAGEINFO pInfo;
  1457. IMessageTable *pTable = NULL;
  1458. hr = m_pMsgList->GetMessageTable(&pTable);
  1459. if (SUCCEEDED(hr))
  1460. {
  1461. for (DWORD i = 0; (i < cRows && m_pMsgList != NULL); i++)
  1462. {
  1463. if (SUCCEEDED(hr = m_pMsgList->GetMessageInfo(rgRows[i], &pInfo)))
  1464. {
  1465. INIT_MSGSITE_STRUCT initStruct;
  1466. DWORD dwCreateFlags;
  1467. initStruct.initTable.pListSelect = NULL;
  1468. m_pMsgList->GetListSelector(&initStruct.initTable.pListSelect);
  1469. // Initialize note struct
  1470. initStruct.dwInitType = OEMSIT_MSG_TABLE;
  1471. initStruct.initTable.pMsgTable = pTable;
  1472. if (FAILED(GetFolderIdFromMsgTable(pTable, &initStruct.folderID)))
  1473. initStruct.folderID = FOLDERID_INVALID;
  1474. initStruct.initTable.rowIndex = rgRows[i];
  1475. // Decide whether it is news or mail
  1476. if (pInfo->dwFlags & ARF_NEWSMSG)
  1477. dwCreateFlags = OENCF_NEWSFIRST;
  1478. else
  1479. dwCreateFlags = 0;
  1480. m_pMsgList->FreeMessageInfo(pInfo);
  1481. // Create and Open Note
  1482. hr = CreateAndShowNote(OENA_READ, dwCreateFlags, &initStruct, m_hwnd, (IUnknown *)m_pPumpRefCount);
  1483. ReleaseObj(initStruct.initTable.pListSelect);
  1484. if (FAILED(hr))
  1485. break;
  1486. }
  1487. }
  1488. pTable->Release();
  1489. }
  1490. MemFree(rgRows);
  1491. return (S_OK);
  1492. }
  1493. //
  1494. // FUNCTION: CFindDlg::CmdOpenFolder()
  1495. //
  1496. // PURPOSE: Called when the user want's to open the folder that contains the
  1497. // selected message.
  1498. //
  1499. HRESULT CFindDlg::CmdOpenFolder(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn,
  1500. VARIANTARG *pvaOut)
  1501. {
  1502. HRESULT hr;
  1503. DWORD dwFocused;
  1504. DWORD *rgRows = NULL;
  1505. DWORD cRows = 0;
  1506. if (m_pMsgList)
  1507. {
  1508. // Figure out which message is focused
  1509. if (SUCCEEDED(m_pMsgList->GetSelected(&dwFocused, &cRows, &rgRows)))
  1510. {
  1511. FOLDERID idFolder;
  1512. // Get some information about the message
  1513. if (g_pInstance && SUCCEEDED(hr = m_pMsgList->GetRowFolderId(dwFocused, &idFolder)))
  1514. {
  1515. g_pInstance->BrowseToObject(SW_SHOWNORMAL, idFolder);
  1516. }
  1517. }
  1518. }
  1519. MemFree(rgRows);
  1520. return (S_OK);
  1521. }
  1522. //
  1523. // FUNCTION: CFindDlg::CmdReply()
  1524. //
  1525. // PURPOSE: Replies or Reply-All's to the selected message.
  1526. //
  1527. // RETURN VALUE:
  1528. // HRESULT
  1529. //
  1530. HRESULT CFindDlg::CmdReplyForward(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  1531. {
  1532. HRESULT hr;
  1533. DWORD dwFocused;
  1534. DWORD *rgRows = NULL;
  1535. DWORD cRows = 0;
  1536. IMessageTable *pTable = NULL;
  1537. if (m_pMsgList)
  1538. {
  1539. // Figure out which message is focused
  1540. if (SUCCEEDED(m_pMsgList->GetSelected(&dwFocused, &cRows, &rgRows)))
  1541. {
  1542. INIT_MSGSITE_STRUCT rInitSite;
  1543. DWORD dwCreateFlags;
  1544. DWORD dwAction = 0;
  1545. // Get the message table from the message list. The note will need
  1546. // this to deal with next / prev commands
  1547. hr = m_pMsgList->GetMessageTable(&pTable);
  1548. if (FAILED(hr))
  1549. goto exit;
  1550. if ((1 < cRows) && ((ID_FORWARD == nCmdID) || (ID_FORWARD_AS_ATTACH == nCmdID)))
  1551. {
  1552. IMimeMessage *pMsgFwd = NULL;
  1553. BOOL fErrorsOccured = FALSE,
  1554. fCreateNote = TRUE;
  1555. hr = HrCreateMessage(&pMsgFwd);
  1556. if (FAILED(hr))
  1557. goto exit;
  1558. rInitSite.dwInitType = OEMSIT_MSG;
  1559. rInitSite.pMsg = pMsgFwd;
  1560. if (FAILED(GetFolderIdFromMsgTable(pTable, &rInitSite.folderID)))
  1561. rInitSite.folderID = FOLDERID_INVALID;
  1562. dwCreateFlags = 0;
  1563. dwAction = OENA_COMPOSE;
  1564. for (DWORD i = 0; i < cRows; i++)
  1565. {
  1566. DWORD iRow = rgRows[i];
  1567. IMimeMessage *pMsg = NULL;
  1568. // Since this command is
  1569. hr = pTable->OpenMessage(iRow, OPEN_MESSAGE_SECURE, &pMsg, NOSTORECALLBACK);
  1570. if (SUCCEEDED(hr))
  1571. {
  1572. if (FAILED(pMsgFwd->AttachObject(IID_IMimeMessage, (LPVOID)pMsg, NULL)))
  1573. fErrorsOccured = TRUE;
  1574. pMsg->Release();
  1575. }
  1576. else
  1577. fErrorsOccured = TRUE;
  1578. }
  1579. if (fErrorsOccured)
  1580. {
  1581. if(AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail),
  1582. MAKEINTRESOURCEW(idsErrorAttachingMsgsToNote), NULL, MB_OKCANCEL) == IDCANCEL)
  1583. fCreateNote = FALSE;
  1584. }
  1585. if (fCreateNote)
  1586. hr = CreateAndShowNote(dwAction, dwCreateFlags, &rInitSite, m_hwnd, (IUnknown *)m_pPumpRefCount);
  1587. pMsgFwd->Release();
  1588. }
  1589. else
  1590. {
  1591. LPMESSAGEINFO pInfo;
  1592. // Get some information about the message
  1593. if (SUCCEEDED(hr = m_pMsgList->GetMessageInfo(dwFocused, &pInfo)))
  1594. {
  1595. // Determine if this is a news or mail message.
  1596. if (pInfo->dwFlags & ARF_NEWSMSG)
  1597. dwCreateFlags = OENCF_NEWSFIRST;
  1598. else
  1599. dwCreateFlags = 0;
  1600. // Reply or forward
  1601. if (nCmdID == ID_FORWARD)
  1602. dwAction = OENA_FORWARD;
  1603. else if (nCmdID == ID_FORWARD_AS_ATTACH)
  1604. dwAction = OENA_FORWARDBYATTACH;
  1605. else if (nCmdID == ID_REPLY)
  1606. dwAction = OENA_REPLYTOAUTHOR;
  1607. else if (nCmdID == ID_REPLY_ALL)
  1608. dwAction = OENA_REPLYALL;
  1609. else if (nCmdID == ID_REPLY_GROUP)
  1610. dwAction = OENA_REPLYTONEWSGROUP;
  1611. else
  1612. AssertSz(FALSE, "Didn't ask for a valid action");
  1613. // Fill out the initialization information
  1614. rInitSite.dwInitType = OEMSIT_MSG_TABLE;
  1615. rInitSite.initTable.pMsgTable = pTable;
  1616. rInitSite.initTable.pListSelect = NULL;
  1617. if (FAILED(GetFolderIdFromMsgTable(pTable, &rInitSite.folderID)))
  1618. rInitSite.folderID = FOLDERID_INVALID;
  1619. rInitSite.initTable.rowIndex = dwFocused;
  1620. m_pMsgList->FreeMessageInfo(pInfo);
  1621. // Create the note object
  1622. hr = CreateAndShowNote(dwAction, dwCreateFlags, &rInitSite, m_hwnd, (IUnknown *)m_pPumpRefCount);
  1623. }
  1624. }
  1625. }
  1626. }
  1627. exit:
  1628. ReleaseObj(pTable);
  1629. MemFree(rgRows);
  1630. return (S_OK);
  1631. }
  1632. HRESULT CFindDlg::CmdCancelMessage(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  1633. {
  1634. HRESULT hr;
  1635. FOLDERID idFolder;
  1636. DWORD dwFocused;
  1637. DWORD *rgRows = NULL;
  1638. DWORD cRows = 0;
  1639. if (m_pMsgList)
  1640. {
  1641. // Figure out which message is focused
  1642. if (SUCCEEDED(m_pMsgList->GetSelected(&dwFocused, &cRows, &rgRows)))
  1643. {
  1644. IMessageTable *pTable = NULL;
  1645. LPMESSAGEINFO pInfo;
  1646. // Get the message table from the message list. The note will need
  1647. // this to deal with next / prev commands
  1648. hr = m_pMsgList->GetMessageTable(&pTable);
  1649. if (FAILED(hr))
  1650. goto exit;
  1651. // Get some information about the message
  1652. if (SUCCEEDED(hr = m_pMsgList->GetMessageInfo(dwFocused, &pInfo)))
  1653. {
  1654. if (SUCCEEDED(hr = m_pMsgList->GetRowFolderId(dwFocused, &idFolder)))
  1655. hr = NewsUtil_HrCancelPost(m_hwnd, idFolder, pInfo);
  1656. m_pMsgList->FreeMessageInfo(pInfo);
  1657. }
  1658. pTable->Release();
  1659. }
  1660. }
  1661. exit:
  1662. MemFree(rgRows);
  1663. return (S_OK);
  1664. }
  1665. //
  1666. // FUNCTION: CFindDlg::CmdFindNow()
  1667. //
  1668. // PURPOSE: Start's a new find.
  1669. //
  1670. HRESULT CFindDlg::CmdFindNow(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn,
  1671. VARIANTARG *pvaOut)
  1672. {
  1673. // Start by freeing our current find information if we have any
  1674. _FreeFindInfo(&m_rFindInfo);
  1675. // Retrieve the find values from the dialog and store them in the
  1676. // m_rFindInfo struct.
  1677. if (_GetFindValues(m_hwnd, &m_rFindInfo))
  1678. {
  1679. // Validate the data. If the user has Date From && Date To set, make
  1680. // sure that to is after from.
  1681. if ((m_rFindInfo.mask & (FIM_DATEFROM | FIM_DATETO)) == (FIM_DATEFROM | FIM_DATETO) &&
  1682. CompareFileTime(&m_rFindInfo.ftDateTo, &m_rFindInfo.ftDateFrom) < 0)
  1683. {
  1684. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrBadFindParams), NULL, MB_OK | MB_ICONINFORMATION);
  1685. return (E_INVALIDARG);
  1686. }
  1687. // Case insensitive search
  1688. if (m_rFindInfo.pszFrom)
  1689. CharUpper(m_rFindInfo.pszFrom);
  1690. if (m_rFindInfo.pszSubject)
  1691. CharUpper(m_rFindInfo.pszSubject);
  1692. if (m_rFindInfo.pszTo)
  1693. CharUpper(m_rFindInfo.pszTo);
  1694. if (m_rFindInfo.pszBody)
  1695. CharUpper(m_rFindInfo.pszBody);
  1696. // Show the bottom portion of the dialog
  1697. _ShowResults(m_hwnd);
  1698. // Start the find.
  1699. _OnFindNow(m_hwnd);
  1700. }
  1701. else
  1702. {
  1703. // If we couldn't store the information, assume it's becuase
  1704. // their isn't enough memory to
  1705. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsMemory), NULL, MB_OK | MB_ICONINFORMATION);
  1706. DestroyWindow(m_hwnd);
  1707. }
  1708. return (S_OK);
  1709. }
  1710. //
  1711. // FUNCTION: CFindDlg::CmdBrowseForFolder()
  1712. //
  1713. // PURPOSE: Bring's up the folder picker dialog
  1714. //
  1715. HRESULT CFindDlg::CmdBrowseForFolder(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn,
  1716. VARIANTARG *pvaOut)
  1717. {
  1718. FOLDERID idFolder;
  1719. return PickFolderInEdit(m_hwnd, GetDlgItem(m_hwnd, IDC_FOLDER), 0, NULL, NULL, &idFolder);
  1720. }
  1721. //
  1722. // FUNCTION: CFindDlg::CmdStop()
  1723. //
  1724. // PURPOSE: Called when the user want's to stop a find in progress.
  1725. //
  1726. HRESULT CFindDlg::CmdStop(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  1727. {
  1728. HWND hwndBtn;
  1729. m_fAbort = TRUE;
  1730. hwndBtn = GetDlgItem(m_hwnd, IDC_STOP);
  1731. EnableWindow(hwndBtn, FALSE);
  1732. Button_SetStyle(hwndBtn, BS_PUSHBUTTON, TRUE);
  1733. hwndBtn = GetDlgItem(m_hwnd, IDC_FIND_NOW);
  1734. EnableWindow(hwndBtn, _IsFindEnabled(m_hwnd));
  1735. Button_SetStyle(hwndBtn, BS_DEFPUSHBUTTON, TRUE);
  1736. EnableWindow(GetDlgItem(m_hwnd, IDC_RESET), TRUE);
  1737. UpdateWindow(m_hwnd);
  1738. if (m_pCancel != NULL)
  1739. m_pCancel->Cancel(CT_CANCEL);
  1740. return (S_OK);
  1741. }
  1742. //
  1743. // FUNCTION: CFindDlg::CmdReset()
  1744. //
  1745. // PURPOSE: Called when the user want's to reset the find criteria
  1746. //
  1747. HRESULT CFindDlg::CmdReset(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  1748. {
  1749. _FreeFindInfo(&m_rFindInfo);
  1750. m_rFindInfo.mask = FIM_FROM | FIM_TO | FIM_SUBJECT | FIM_BODYTEXT;
  1751. _SetFindValues(m_hwnd, &m_rFindInfo);
  1752. EnableWindow(GetDlgItem(m_hwnd, IDC_FIND_NOW), _IsFindEnabled(m_hwnd));
  1753. ((CMessageList *) m_pMsgList)->SetFolder(FOLDERID_INVALID, NULL, FALSE, NULL, NOSTORECALLBACK);
  1754. m_fFindComplete = FALSE;
  1755. m_pStatusBar->SetStatusText((LPTSTR) c_szEmpty);
  1756. return (S_OK);
  1757. }
  1758. //
  1759. // FUNCTION: CFindDlg::CmdBlockSender()
  1760. //
  1761. // PURPOSE: Add the sender of the selected messages to the block senders list
  1762. //
  1763. // RETURN VALUE:
  1764. // HRESULT
  1765. //
  1766. HRESULT CFindDlg::CmdBlockSender(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  1767. {
  1768. HRESULT hr = S_OK;
  1769. DWORD * rgRows = NULL;
  1770. DWORD cRows = 0;
  1771. LPMESSAGEINFO pInfo = NULL;
  1772. IUnknown * pUnkMessage = NULL;
  1773. IMimeMessage * pMessage = 0;
  1774. LPSTR pszEmailFrom = NULL;
  1775. ADDRESSPROPS rSender = {0};
  1776. CHAR szRes[CCHMAX_STRINGRES];
  1777. LPSTR pszResult = NULL;
  1778. TraceCall("CFindDlg::CmdBlockSender");
  1779. IF_FAILEXIT(hr = m_pMsgList->GetSelected(NULL, &cRows, &rgRows));
  1780. // It's possible for the message list to go away while we're doing this.
  1781. // To keep us from crashing, make sure you verify it still exists during
  1782. // the loop.
  1783. IF_FAILEXIT(hr = m_pMsgList->GetMessageInfo(rgRows[0], &pInfo));
  1784. // Do we already have the address?
  1785. if ((NULL != pInfo->pszEmailFrom) && ('\0' != pInfo->pszEmailFrom[0]))
  1786. {
  1787. pszEmailFrom = pInfo->pszEmailFrom;
  1788. }
  1789. else
  1790. {
  1791. // Load that message from the store
  1792. IF_FAILEXIT(hr = m_pMsgList->GetMessage(rgRows[0], FALSE, FALSE, &pUnkMessage));
  1793. if (NULL == pUnkMessage)
  1794. IF_FAILEXIT(hr = E_FAIL);
  1795. // Get the IMimeMessage interface from the message
  1796. IF_FAILEXIT(hr = pUnkMessage->QueryInterface(IID_IMimeMessage, (LPVOID *) &pMessage));
  1797. rSender.dwProps = IAP_EMAIL;
  1798. IF_FAILEXIT(hr = pMessage->GetSender(&rSender));
  1799. Assert(rSender.pszEmail && ISFLAGSET(rSender.dwProps, IAP_EMAIL));
  1800. pszEmailFrom = rSender.pszEmail;
  1801. }
  1802. // Bring up the rule editor for this message
  1803. IF_FAILEXIT(hr = RuleUtil_HrAddBlockSender((0 != (pInfo->dwFlags & ARF_NEWSMSG)) ? RULE_TYPE_NEWS : RULE_TYPE_MAIL, pszEmailFrom));
  1804. // Load the template string
  1805. AthLoadString(idsSenderAdded, szRes, sizeof(szRes));
  1806. // Allocate the space to hold the final string
  1807. DWORD cchSize = (lstrlen(szRes) + lstrlen(pszEmailFrom) + 1);
  1808. IF_FAILEXIT(hr = HrAlloc((VOID **) &pszResult, sizeof(*pszResult) * cchSize));
  1809. // Build up the warning string
  1810. wnsprintf(pszResult, cchSize, szRes, pszEmailFrom);
  1811. // Show the success dialog
  1812. AthMessageBox(m_hwnd, MAKEINTRESOURCE(idsAthena), pszResult, NULL, MB_OK | MB_ICONINFORMATION);
  1813. exit:
  1814. MemFree(pszResult);
  1815. g_pMoleAlloc->FreeAddressProps(&rSender);
  1816. ReleaseObj(pMessage);
  1817. ReleaseObj(pUnkMessage);
  1818. m_pMsgList->FreeMessageInfo(pInfo);
  1819. MemFree(rgRows);
  1820. if (FAILED(hr))
  1821. {
  1822. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena),
  1823. MAKEINTRESOURCEW(idsSenderError), NULL, MB_OK | MB_ICONERROR);
  1824. }
  1825. return (hr);
  1826. }
  1827. //
  1828. // FUNCTION: CFindDlg::CmdCreateRule()
  1829. //
  1830. // PURPOSE: Add the sender of the selected messages to the block senders list
  1831. //
  1832. // RETURN VALUE:
  1833. // HRESULT
  1834. //
  1835. HRESULT CFindDlg::CmdCreateRule(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  1836. {
  1837. HRESULT hr;
  1838. DWORD * rgRows = NULL;
  1839. DWORD cRows = 0;
  1840. LPMESSAGEINFO pInfo = NULL;
  1841. IUnknown * pUnkMessage = NULL;
  1842. IMimeMessage * pMessage = 0;
  1843. TraceCall("CFindDlg::CmdCreateRule");
  1844. // Get the array of selected rows from the message list
  1845. if (FAILED(hr = m_pMsgList->GetSelected(NULL, &cRows, &rgRows)))
  1846. return (hr);
  1847. // It's possible for the message list to go away while we're doing this.
  1848. // To keep us from crashing, make sure you verify it still exists during
  1849. // the loop.
  1850. if (SUCCEEDED(hr = m_pMsgList->GetMessageInfo(rgRows[0], &pInfo)))
  1851. {
  1852. // Load that message from the store
  1853. if (S_OK == m_pMsgList->GetMessage(rgRows[0], FALSE, FALSE, &pUnkMessage))
  1854. {
  1855. // Get the IMimeMessage interface from the message
  1856. if (NULL != pUnkMessage)
  1857. {
  1858. pUnkMessage->QueryInterface(IID_IMimeMessage, (LPVOID *) &pMessage);
  1859. }
  1860. }
  1861. // Bring up the rule editor for this message
  1862. hr = HrCreateRuleFromMessage(m_hwnd, (0 != (pInfo->dwFlags & ARF_NEWSMSG)) ?
  1863. CRFMF_NEWS : CRFMF_MAIL, pInfo, pMessage);
  1864. }
  1865. ReleaseObj(pMessage);
  1866. ReleaseObj(pUnkMessage);
  1867. m_pMsgList->FreeMessageInfo(pInfo);
  1868. MemFree(rgRows);
  1869. return (S_OK);
  1870. }
  1871. //
  1872. // FUNCTION: CFindDlg::CmdCombineAndDecode()
  1873. //
  1874. // PURPOSE: Combines the selected messages into a single message.
  1875. //
  1876. // RETURN VALUE:
  1877. // HRESULT
  1878. //
  1879. HRESULT CFindDlg::CmdCombineAndDecode(DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  1880. {
  1881. FOLDERID idFolder;
  1882. DWORD *rgRows = NULL;
  1883. DWORD cRows = 0;
  1884. CCombineAndDecode *pDecode = NULL;
  1885. HRESULT hr;
  1886. // Create the decoder object
  1887. pDecode = new CCombineAndDecode();
  1888. if (!pDecode)
  1889. return (S_OK);
  1890. // Get the array of selected rows from the message list
  1891. if (FAILED(hr = m_pMsgList->GetSelected(NULL, &cRows, &rgRows)))
  1892. {
  1893. pDecode->Release();
  1894. return (hr);
  1895. }
  1896. // Get a pointer to the message table
  1897. IMessageTable *pTable = NULL;
  1898. if (SUCCEEDED(m_pMsgList->GetMessageTable(&pTable)))
  1899. {
  1900. // Initialize the decoder
  1901. if (SUCCEEDED(GetFolderIdFromMsgTable(pTable, &idFolder)))
  1902. pDecode->Start(m_hwnd, pTable, rgRows, cRows, idFolder);
  1903. }
  1904. MemFree(rgRows);
  1905. pDecode->Release();
  1906. pTable->Release();
  1907. return (S_OK);
  1908. }
  1909. void CFindDlg::_ShowResults(HWND hwnd)
  1910. {
  1911. if (!m_fShowResults)
  1912. {
  1913. RECT rc;
  1914. m_fShowResults = TRUE;
  1915. GetWindowRect(hwnd, &rc);
  1916. m_ptDragMin.y = (3 * m_ptDragMin.y) / 2;
  1917. ShowWindow(GetDlgItem(hwnd, IDC_STATUS_BAR), SW_SHOW);
  1918. ShowWindow(m_hwndList, SW_SHOW);
  1919. SetWindowPos(hwnd, NULL, 0, 0, rc.right - rc.left, m_cyDlgFull, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  1920. }
  1921. }
  1922. void CFindDlg::_OnFindNow(HWND hwnd)
  1923. {
  1924. HWND hwndBtn;
  1925. m_fInProgress = TRUE;
  1926. hwndBtn = GetDlgItem(hwnd, IDC_FIND_NOW);
  1927. EnableWindow(hwndBtn, FALSE);
  1928. Button_SetStyle(hwndBtn, BS_PUSHBUTTON, TRUE);
  1929. EnableWindow(GetDlgItem(hwnd, IDC_RESET), FALSE);
  1930. hwndBtn = GetDlgItem(hwnd, IDC_STOP);
  1931. EnableWindow(hwndBtn, TRUE);
  1932. Button_SetStyle(hwndBtn, BS_DEFPUSHBUTTON, TRUE);
  1933. ShowWindow(m_hwndList, SW_SHOW);
  1934. SetFocus(m_hwndList);
  1935. UpdateWindow(hwnd);
  1936. m_fAbort = m_fClose = FALSE;
  1937. _StartFind(_GetCurSel(hwnd), IsDlgButtonChecked(hwnd, IDC_INCLUDE_SUB));
  1938. CmdStop(ID_STOP, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
  1939. if (m_fClose)
  1940. DestroyWindow(m_hwnd);
  1941. m_fInProgress = FALSE;
  1942. }
  1943. FOLDERID CFindDlg::_GetCurSel(HWND hwnd)
  1944. {
  1945. return GetFolderIdFromEdit(GetDlgItem(hwnd, IDC_FOLDER));
  1946. }
  1947. void CFindDlg::_StartFind(FOLDERID idFolder, BOOL fSubFolders)
  1948. {
  1949. // If we're searching subfolders, then set that flag too
  1950. m_rFindInfo.fSubFolders = fSubFolders;
  1951. // Initialize the Message List
  1952. ((CMessageList *)m_pMsgList)->SetFolder(idFolder, NULL, fSubFolders, &m_rFindInfo, (IStoreCallback *)this);
  1953. }
  1954. void CFindDlg::_FreeFindInfo(FINDINFO *pfi)
  1955. {
  1956. FreeFindInfo(pfi);
  1957. }
  1958. void CFindDlg::_SetFindValues(HWND hwnd, FINDINFO *pfi)
  1959. {
  1960. SYSTEMTIME st;
  1961. HWND hwndTo;
  1962. if (pfi->mask & FIM_FROM)
  1963. {
  1964. Assert(GetDlgItem(hwnd, IDC_FROM));
  1965. Edit_SetText(GetDlgItem(hwnd, IDC_FROM), pfi->pszFrom);
  1966. }
  1967. if (pfi->mask & FIM_TO)
  1968. {
  1969. hwndTo = GetDlgItem(hwnd, IDC_TO);
  1970. if (NULL != hwndTo)
  1971. {
  1972. Edit_SetText(hwndTo, pfi->pszTo);
  1973. }
  1974. }
  1975. if (pfi->mask & FIM_SUBJECT)
  1976. {
  1977. Assert(GetDlgItem(hwnd, IDC_SUBJECT));
  1978. Edit_SetText(GetDlgItem(hwnd, IDC_SUBJECT), pfi->pszSubject);
  1979. }
  1980. if (pfi->mask & FIM_BODYTEXT)
  1981. {
  1982. Assert(GetDlgItem(hwnd, IDC_BODY));
  1983. Edit_SetText(GetDlgItem(hwnd, IDC_BODY), pfi->pszBody);
  1984. }
  1985. if (GetDlgItem(hwnd, IDC_HAS_ATTACH))
  1986. CheckDlgButton(hwnd, IDC_HAS_ATTACH, (pfi->mask & FIM_ATTACHMENT) ? BST_CHECKED : BST_UNCHECKED);
  1987. if (GetDlgItem(hwnd, IDC_HAS_FLAG))
  1988. CheckDlgButton(hwnd, IDC_HAS_FLAG, (pfi->mask & FIM_FLAGGED) ? BST_CHECKED : BST_UNCHECKED);
  1989. FileTimeToSystemTime(&pfi->ftDateFrom, &st);
  1990. DateTime_SetSystemtime(GetDlgItem(hwnd, IDC_DATE_FROM), (pfi->mask & FIM_DATEFROM) ? GDT_VALID : GDT_NONE, &st);
  1991. FileTimeToSystemTime(&pfi->ftDateTo, &st);
  1992. DateTime_SetSystemtime(GetDlgItem(hwnd, IDC_DATE_TO), (pfi->mask & FIM_DATETO) ? GDT_VALID : GDT_NONE, &st);
  1993. }
  1994. BOOL CFindDlg::_GetFindValues(HWND hwnd, FINDINFO *pfi)
  1995. {
  1996. SYSTEMTIME st;
  1997. pfi->mask = 0;
  1998. if (!AllocStringFromDlg(hwnd, IDC_FROM, &pfi->pszFrom) ||
  1999. !AllocStringFromDlg(hwnd, IDC_SUBJECT, &pfi->pszSubject) ||
  2000. !AllocStringFromDlg(hwnd, IDC_TO, &pfi->pszTo) ||
  2001. !AllocStringFromDlg(hwnd, IDC_BODY, &pfi->pszBody))
  2002. {
  2003. return FALSE;
  2004. }
  2005. if (pfi->pszFrom)
  2006. pfi->mask |= FIM_FROM;
  2007. if (pfi->pszSubject)
  2008. pfi->mask |= FIM_SUBJECT;
  2009. if (pfi->pszTo)
  2010. pfi->mask |= FIM_TO;
  2011. if (pfi->pszBody)
  2012. pfi->mask |= FIM_BODYTEXT;
  2013. if (IsDlgButtonChecked(hwnd, IDC_HAS_ATTACH))
  2014. pfi->mask |= FIM_ATTACHMENT;
  2015. if (IsDlgButtonChecked(hwnd, IDC_HAS_FLAG))
  2016. pfi->mask |= FIM_FLAGGED;
  2017. if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATE_FROM), &st) != GDT_NONE)
  2018. {
  2019. pfi->mask |= FIM_DATEFROM;
  2020. st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0; // start of the day
  2021. SystemTimeToFileTime(&st, &pfi->ftDateFrom);
  2022. }
  2023. if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATE_TO), &st) != GDT_NONE)
  2024. {
  2025. pfi->mask |= FIM_DATETO;
  2026. // end of day
  2027. st.wHour = 23;
  2028. st.wMinute = 59;
  2029. st.wSecond = 59;
  2030. st.wMilliseconds = 999;
  2031. SystemTimeToFileTime(&st, &pfi->ftDateTo);
  2032. }
  2033. return TRUE;
  2034. }
  2035. //
  2036. // FUNCTION: CFindDlg::_IsFindEnabled()
  2037. //
  2038. // PURPOSE: Checks to see if the "Find Now" button should be enabled.
  2039. //
  2040. BOOL CFindDlg::_IsFindEnabled(HWND hwnd)
  2041. {
  2042. BOOL fEnable;
  2043. SYSTEMTIME st;
  2044. HWND hwndBody, hwndAttach, hwndTo;
  2045. hwndBody = GetDlgItem(hwnd, IDC_BODY);
  2046. hwndAttach = GetDlgItem(hwnd, IDC_HAS_ATTACH);
  2047. hwndTo = GetDlgItem(hwnd, IDC_TO);
  2048. // If we have content in any of these fields, we can search.
  2049. fEnable = Edit_GetTextLength(GetDlgItem(hwnd, IDC_FROM)) ||
  2050. Edit_GetTextLength(hwndTo) ||
  2051. Edit_GetTextLength(GetDlgItem(hwnd, IDC_SUBJECT)) ||
  2052. Edit_GetTextLength(hwndBody) ||
  2053. IsDlgButtonChecked(hwnd, IDC_HAS_ATTACH) ||
  2054. IsDlgButtonChecked(hwnd, IDC_HAS_FLAG) ||
  2055. (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATE_FROM), &st) != GDT_NONE) ||
  2056. (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATE_TO), &st) != GDT_NONE);
  2057. return fEnable;
  2058. }
  2059. //
  2060. // FUNCTION: CFindDlg::_SetFindIntlFont()
  2061. //
  2062. // PURPOSE: Set's the correct international font for all edit boxes.
  2063. //
  2064. void CFindDlg::_SetFindIntlFont(HWND hwnd)
  2065. {
  2066. HWND hwndT;
  2067. hwndT = GetDlgItem(hwnd, IDC_FROM);
  2068. if (hwndT != NULL)
  2069. SetIntlFont(hwndT);
  2070. hwndT = GetDlgItem(hwnd, IDC_TO);
  2071. if (hwndT != NULL)
  2072. SetIntlFont(hwndT);
  2073. hwndT = GetDlgItem(hwnd, IDC_SUBJECT);
  2074. if (hwndT != NULL)
  2075. SetIntlFont(hwndT);
  2076. hwndT = GetDlgItem(hwnd, IDC_BODY);
  2077. if (hwndT != NULL)
  2078. SetIntlFont(hwndT);
  2079. }
  2080. //
  2081. // FUNCTION: CFindDlg::_InitSizingInfo()
  2082. //
  2083. // PURPOSE: Grabs all the sizing information we'll need later when the
  2084. // dialog is resized.
  2085. //
  2086. void CFindDlg::_InitSizingInfo(HWND hwnd)
  2087. {
  2088. RECT rc, rcClient;
  2089. RECT rcEdit;
  2090. WINDOWPLACEMENT wp;
  2091. TraceCall("CFindDlg::_InitSizingInfo");
  2092. // Get the overall size of the default dialog template
  2093. GetClientRect(hwnd, &rcClient);
  2094. m_cxDlgDef = rcClient.right - rcClient.left;
  2095. m_yView = rcClient.bottom;
  2096. // Make room for the menu bar and save that for resizing
  2097. AdjustWindowRect(&rcClient, GetWindowStyle(hwnd), TRUE);
  2098. m_ptDragMin.x = rcClient.right - rcClient.left;
  2099. m_ptDragMin.y = rcClient.bottom - rcClient.top;
  2100. GetWindowRect(GetDlgItem(hwnd, IDC_FOLDER), &rcEdit);
  2101. MapWindowRect(NULL, hwnd, &rcEdit);
  2102. m_xEdit = rcEdit.left;
  2103. m_cxFolder = rcEdit.right - rcEdit.left;
  2104. GetWindowRect(GetDlgItem(hwnd, IDC_INCLUDE_SUB), &rc);
  2105. MapWindowRect(NULL, hwnd, &rc);
  2106. m_xIncSub = rc.left;
  2107. m_yIncSub = rc.top;
  2108. GetWindowRect(GetDlgItem(hwnd, idcStatic1), &rc);
  2109. m_cxStatic = rc.right - rc.left;
  2110. GetWindowRect(GetDlgItem(hwnd, IDC_BROWSE_FOLDER), &rc);
  2111. MapWindowRect(NULL, hwnd, &rc);
  2112. m_yBrowse = rc.top;
  2113. m_dxBtnGap = rc.left - rcEdit.right;
  2114. GetWindowRect(GetDlgItem(hwnd, IDC_FIND_NOW), &rc);
  2115. MapWindowRect(NULL, hwnd, &rc);
  2116. m_xBtn = rc.left;
  2117. m_dxBtn = rc.right - rc.left;
  2118. m_yBtn = rc.top;
  2119. GetWindowRect(GetDlgItem(hwnd, IDC_STOP), &rc);
  2120. MapWindowRect(NULL, hwnd, &rc);
  2121. m_dyBtn = rc.top - m_yBtn;
  2122. GetWindowRect(GetDlgItem(hwnd, IDC_FROM), &rc);
  2123. m_cxEdit = rc.right - rc.left;
  2124. m_cyEdit = rc.bottom - rc.top;
  2125. SetWindowPos(hwnd, NULL, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  2126. if (sizeof(wp) == GetOption(OPT_FINDER_POS, (LPBYTE)&wp, sizeof(wp)))
  2127. {
  2128. if (wp.showCmd != SW_SHOWMAXIMIZED)
  2129. wp.showCmd = SW_SHOWNORMAL;
  2130. m_cyDlgFull = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
  2131. SetWindowPlacement(hwnd, &wp);
  2132. }
  2133. else
  2134. {
  2135. m_cyDlgFull = (3 * m_ptDragMin.y) / 2;
  2136. CenterDialog(hwnd);
  2137. }
  2138. }
  2139. //
  2140. // FUNCTION: CFindDlg::QuerySwitchIdentities()
  2141. //
  2142. // PURPOSE: Determine if it is OK for the identity manager to
  2143. // switch identities now
  2144. //
  2145. HRESULT CFindDlg::QuerySwitchIdentities()
  2146. {
  2147. if (!IsWindowEnabled(m_hwnd))
  2148. return E_PROCESS_CANCELLED_SWITCH;
  2149. return S_OK;
  2150. }
  2151. //
  2152. // FUNCTION: CFindDlg::SwitchIdentities()
  2153. //
  2154. // PURPOSE: The current identity has switched. Close the window.
  2155. //
  2156. HRESULT CFindDlg::SwitchIdentities()
  2157. {
  2158. if (m_fInProgress)
  2159. {
  2160. CmdStop(ID_STOP, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
  2161. m_fClose = TRUE;
  2162. }
  2163. else
  2164. {
  2165. DestroyWindow(m_hwnd);
  2166. }
  2167. return S_OK;
  2168. }
  2169. //
  2170. // FUNCTION: CFindDlg::IdentityInformationChanged()
  2171. //
  2172. // PURPOSE: Information about the current identity has changed.
  2173. // This is ignored.
  2174. //
  2175. HRESULT CFindDlg::IdentityInformationChanged(DWORD dwType)
  2176. {
  2177. return S_OK;
  2178. }