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.

1038 lines
30 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved.
  3. //
  4. // MODULE: Order.cpp
  5. //
  6. // PURPOSE: Implements the order articles dialog. Allows the user to
  7. // sequence multipart articles for decoding.
  8. //
  9. #include "pch.hxx"
  10. #include "storutil.h"
  11. #include "mimeole.h"
  12. #include "mimeutil.h"
  13. #include "resource.h"
  14. #include "shlwapip.h"
  15. #include "thormsgs.h"
  16. #include "order.h"
  17. #include "error.h"
  18. #include "demand.h"
  19. #include "imsgsite.h"
  20. #include "note.h"
  21. #include "xputil.h"
  22. // NOTE - The drag list control requires us to register a message and use that
  23. // for notifications sent from the list to the dialog. This message
  24. // is defined only for this dialog. -- SteveSer.
  25. static UINT g_mDragList = 0;
  26. #define CND_GETNEXTARTICLE (WM_USER + 101)
  27. #define CND_OPENNOTE (WM_USER + 102)
  28. #define CND_MESSAGEAVAIL (WM_USER + 103)
  29. CCombineAndDecode::CCombineAndDecode()
  30. {
  31. m_cRef = 1;
  32. m_hwndParent = NULL;
  33. m_pTable = NULL;
  34. m_rgRows = NULL;
  35. m_cRows = 0;
  36. m_pszBuffer = NULL;
  37. m_iItemToMove = -1;
  38. m_cLinesTotal = 0;
  39. m_cCurrentLine = 0;
  40. m_cPrevLine = 0;
  41. m_dwCurrentArt = 0;
  42. m_pMsgParts = NULL;
  43. m_pCancel = 0;
  44. m_hTimeout = 0;
  45. m_hwndDlg = 0;
  46. }
  47. CCombineAndDecode::~CCombineAndDecode()
  48. {
  49. SafeRelease(m_pTable);
  50. SafeRelease(m_pMsgParts);
  51. SafeRelease(m_pCancel);
  52. CallbackCloseTimeout(&m_hTimeout);
  53. }
  54. HRESULT STDMETHODCALLTYPE CCombineAndDecode::QueryInterface(REFIID riid, void **ppvObj)
  55. {
  56. if (IsEqualIID(riid, IID_IUnknown))
  57. *ppvObj = (void*) (IUnknown *)(IStoreCallback *)this;
  58. else if (IsEqualIID(riid, IID_IStoreCallback))
  59. *ppvObj = (void*) (IStoreCallback *) this;
  60. else
  61. {
  62. *ppvObj = NULL;
  63. return E_NOINTERFACE;
  64. }
  65. AddRef();
  66. return S_OK;
  67. }
  68. ULONG STDMETHODCALLTYPE CCombineAndDecode::AddRef()
  69. {
  70. return ++m_cRef;
  71. }
  72. ULONG STDMETHODCALLTYPE CCombineAndDecode::Release()
  73. {
  74. if (--m_cRef == 0)
  75. {
  76. delete this;
  77. return 0;
  78. }
  79. return m_cRef;
  80. }
  81. //
  82. // FUNCTION: CCombineAndDecode::Start()
  83. //
  84. // PURPOSE:
  85. //
  86. // PARAMETERS:
  87. // [in] hwndParent
  88. // [in] pTable
  89. // [in] rgRows
  90. // [in] cRows
  91. //
  92. // RETURN VALUE:
  93. // HRESULT
  94. //
  95. HRESULT CCombineAndDecode::Start(HWND hwndParent, IMessageTable *pTable,
  96. ROWINDEX *rgRows, DWORD cRows, FOLDERID idFolder)
  97. {
  98. int nResult = -1;
  99. TraceCall("CCombineAndDecode::Start");
  100. // Verify we got everything we needed
  101. if (!IsWindow(hwndParent) || !pTable || !rgRows || 0 == cRows)
  102. return (E_INVALIDARG);
  103. // Keep these for later
  104. m_hwndParent = hwndParent;
  105. m_pTable = pTable;
  106. m_pTable->AddRef();
  107. m_rgRows = rgRows;
  108. m_cRows = cRows;
  109. m_idFolder = idFolder;
  110. // Create the order dialog and get to work
  111. nResult = (int) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddOrderMessages),
  112. m_hwndParent, OrderDlgProc, (LPARAM) this);
  113. // If the user pressed OK, then we go ahead and decode
  114. if (nResult == IDOK)
  115. {
  116. DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddCombineAndDecode), m_hwndParent,
  117. CombineDlgProc, (LPARAM) this);
  118. }
  119. return (S_OK);
  120. }
  121. //
  122. // FUNCTION: CCombineAndDecode::OrderDlgProc()
  123. //
  124. // PURPOSE: Public callback function for the message ordering dialog proc
  125. //
  126. INT_PTR CALLBACK CCombineAndDecode::OrderDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  127. {
  128. CCombineAndDecode *pThis;
  129. if (uMsg == WM_INITDIALOG)
  130. {
  131. SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  132. pThis = (CCombineAndDecode *) lParam;
  133. }
  134. else
  135. pThis = (CCombineAndDecode *) GetWindowLongPtr(hwnd, DWLP_USER);
  136. if (pThis)
  137. return (pThis->_OrderDlgProc(hwnd, uMsg, wParam, lParam));
  138. return (FALSE);
  139. }
  140. //
  141. // FUNCTION: CCombineAndDecode::_OrderDlgProc()
  142. //
  143. // PURPOSE: Private callback function for the message ordering dialog proc
  144. //
  145. INT_PTR CALLBACK CCombineAndDecode::_OrderDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  146. {
  147. switch (uMsg)
  148. {
  149. case WM_INITDIALOG:
  150. return (BOOL) HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, _Order_OnInitDialog);
  151. case WM_COMMAND:
  152. HANDLE_WM_COMMAND(hwnd, wParam, lParam, _Order_OnCommand);
  153. return (TRUE);
  154. case WM_CLOSE:
  155. HANDLE_WM_CLOSE(hwnd, wParam, lParam, _Order_OnClose);
  156. return (TRUE);
  157. default:
  158. if (uMsg == g_mDragList)
  159. return (_Order_OnDragList(hwnd, (int) wParam, (DRAGLISTINFO*) lParam));
  160. }
  161. return (FALSE);
  162. }
  163. //
  164. // FUNCTION: CCombineAndDecode::_Order_OnInitDialog()
  165. //
  166. // PURPOSE: Initializes the order dialog by filling in the message headers.
  167. //
  168. BOOL CCombineAndDecode::_Order_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  169. {
  170. HWND hwndList;
  171. HDC hdc;
  172. SIZE size;
  173. int cx = 0;
  174. HFONT hfontOld;
  175. HFONT hfont;
  176. int cxScrollBar;
  177. LPMESSAGEINFO pInfo;
  178. int iItem;
  179. LPSTR pszSubject = NULL;
  180. CHAR szNoSubject[CCHMAX_STRINGRES] = "";
  181. CenterDialog(hwnd);
  182. // Get some drawing information about the ListBox so we can set the scroll
  183. // bar width correctly later.
  184. hwndList = GetDlgItem(hwnd, IDC_MESSAGE_LIST);
  185. hdc = GetDC(hwndList);
  186. hfont = (HFONT) SendMessage(hwndList, WM_GETFONT, 0, 0L);
  187. hfontOld = (HFONT) SelectObject(hdc, hfont);
  188. cxScrollBar = GetSystemMetrics(SM_CXHTHUMB);
  189. // Fill the listbox with the article subjects
  190. for (DWORD i = 0; i < m_cRows; i++)
  191. {
  192. // Get the message header from the table
  193. if (SUCCEEDED(m_pTable->GetRow(m_rgRows[i], &pInfo)))
  194. {
  195. if(pInfo->pszSubject)
  196. pszSubject = pInfo->pszSubject;
  197. else
  198. {
  199. LoadString(g_hLocRes, idsEmptySubjectRO, szNoSubject, sizeof(szNoSubject));
  200. pszSubject = szNoSubject;
  201. }
  202. Assert(pszSubject);
  203. // Figure out which string is widest before inserting
  204. GetTextExtentPoint32(hdc, pszSubject, lstrlen(pszSubject), &size);
  205. if (cx < size.cx)
  206. cx = size.cx;
  207. // Add the string
  208. iItem = (int) SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) pszSubject);
  209. if (LB_ERR != iItem)
  210. SendMessage(hwndList, LB_SETITEMDATA, iItem, (LPARAM) m_rgRows[i]);
  211. // Free the memory
  212. m_pTable->ReleaseRow(pInfo);
  213. }
  214. }
  215. // Clean up the GDI objects
  216. SelectObject(hdc, hfontOld);
  217. ReleaseDC(hwndList, hdc);
  218. // Make sure there are scroll bars if needed.
  219. SendMessage(hwndList, LB_SETHORIZONTALEXTENT, cx + cxScrollBar, 0L);
  220. // Make the list box a drag list box
  221. if (MakeDragList(hwndList))
  222. g_mDragList = RegisterWindowMessage(DRAGLISTMSGSTRING);
  223. SendMessage(hwndList, LB_SETCURSEL, 0, 0);
  224. return (FALSE);
  225. }
  226. //
  227. // FUNCTION: CCombineAndDecode::_Order_OnCommand()
  228. //
  229. // PURPOSE: Handle the commands generated by the buttons on the dialog.
  230. //
  231. void CCombineAndDecode::_Order_OnCommand(HWND hwnd, int id, HWND hwndCtl,
  232. UINT codeNotify)
  233. {
  234. HWND hwndList = GetDlgItem(hwnd, IDC_MESSAGE_LIST);
  235. switch (id)
  236. {
  237. case IDOK:
  238. {
  239. // Get the info we need out of the ListBox
  240. for (DWORD i = 0; i < m_cRows; i++)
  241. {
  242. m_rgRows[i] = (ROWINDEX) ListBox_GetItemData(hwndList, i);
  243. }
  244. EndDialog(hwnd, 1);
  245. break;
  246. }
  247. case IDCANCEL:
  248. EndDialog(hwnd, 0);
  249. break;
  250. case IDC_MOVE_UP:
  251. case IDC_MOVE_DOWN:
  252. {
  253. LPTSTR pszBuffer;
  254. DWORD cch;
  255. UINT index;
  256. LPARAM lpData;
  257. // Get the currently selected item
  258. index = (DWORD) SendMessage(hwndList, LB_GETCURSEL, 0, 0);
  259. // If nothing is selected the listbox returns LB_ERR
  260. if (index == LB_ERR)
  261. return;
  262. // Check the bounds
  263. if ((id == IDC_MOVE_UP && index == 0) ||
  264. (id == IDC_MOVE_DOWN && (int) index == (ListBox_GetCount(hwndList) - 1)))
  265. return;
  266. // Move the item in the listbox
  267. cch = (DWORD) SendMessage(hwndList, LB_GETTEXTLEN, index, 0L);
  268. if (!MemAlloc((LPVOID*) &pszBuffer, sizeof(TCHAR) * (cch + 1)))
  269. return;
  270. // Get the source string and data
  271. SendMessage(hwndList, LB_GETTEXT, index, (LPARAM) pszBuffer);
  272. lpData = SendMessage(hwndList, LB_GETITEMDATA, index, 0);
  273. // Delete the source
  274. SendMessage(hwndList, LB_DELETESTRING, index, 0L);
  275. // Insert the new one
  276. if (id == IDC_MOVE_UP)
  277. index--;
  278. else
  279. index++;
  280. SendMessage(hwndList, LB_INSERTSTRING, index, (LPARAM) pszBuffer);
  281. SendMessage(hwndList, LB_SETITEMDATA, index, lpData);
  282. SendMessage(hwndList, LB_SETCURSEL, index, 0L);
  283. MemFree(pszBuffer);
  284. break;
  285. }
  286. }
  287. }
  288. //
  289. // FUNCTION: Order_OnDragList()
  290. //
  291. // PURPOSE: Handles the drag list notifications which reorder the messages.
  292. //
  293. // PARAMETERS:
  294. // hwnd - handle of the parent of the drag list
  295. // idCtl - identifer of the drag list sending the notification
  296. // lpdli - pointer to a DRAGLISTINFO struct with info about the
  297. // notification.
  298. //
  299. // RETURN VALUE:
  300. // Dependant on the notification.
  301. //
  302. // COMMENTS:
  303. // This function uses the SetDlgMsgResult() macro defined in WINDOWSX.H to
  304. // set the return value for each message since the parent window is a
  305. // dialog.
  306. //
  307. LRESULT CCombineAndDecode::_Order_OnDragList(HWND hwnd, int idCtl, LPDRAGLISTINFO lpdli)
  308. {
  309. UINT iItem;
  310. UINT cch;
  311. Assert(((int) m_iItemToMove) >= 0);
  312. switch (lpdli->uNotification)
  313. {
  314. // The user has started dragging one of the list control's items
  315. case DL_BEGINDRAG:
  316. {
  317. // Find out which item is being dragged
  318. m_iItemToMove = LBItemFromPt(lpdli->hWnd, lpdli->ptCursor, TRUE);
  319. // Allocate a buffer for the string
  320. Assert(m_pszBuffer == NULL);
  321. cch = ListBox_GetTextLen(lpdli->hWnd, m_iItemToMove) + 1;
  322. MemAlloc((LPVOID *) &m_pszBuffer, cch);
  323. SendMessage(lpdli->hWnd, LB_GETTEXT, m_iItemToMove, (LPARAM) m_pszBuffer);
  324. m_lpData = SendMessage(lpdli->hWnd, LB_GETITEMDATA, m_iItemToMove, 0);
  325. DOUT("DL_BEGINDRAG: iItem = %d, text = %100s\r\n", m_iItemToMove, m_pszBuffer);
  326. // Draw the insert icon
  327. DrawInsert(hwnd, lpdli->hWnd, m_iItemToMove);
  328. // Set the return value to allow the drag to contine
  329. SetDlgMsgResult(hwnd, g_mDragList, TRUE);
  330. return TRUE;
  331. }
  332. case DL_CANCELDRAG:
  333. {
  334. DOUT("DL_CANCELDRAG\r\n");
  335. DrawInsert(hwnd, lpdli->hWnd, -1);
  336. SafeMemFree(m_pszBuffer);
  337. return 0; // Return value is ignored
  338. }
  339. // The user is in the process of dragging, update the position
  340. // and move the insert icon
  341. case DL_DRAGGING:
  342. {
  343. // Find out where the cursor is now
  344. iItem = LBItemFromPt(lpdli->hWnd, lpdli->ptCursor, TRUE);
  345. // Dump some debug info
  346. DOUT("DL_DRAGGING: iItem = %d\r\n", iItem);
  347. // Update the insert icon position
  348. DrawInsert(hwnd, lpdli->hWnd, iItem);
  349. // If the cursor is over a valid position set the cursor to
  350. // DL_MOVECURSOR, otherwise use the DL_STOPCURSOR
  351. if (-1 != iItem)
  352. SetDlgMsgResult(hwnd, g_mDragList, DL_MOVECURSOR);
  353. else
  354. SetDlgMsgResult(hwnd, g_mDragList, DL_STOPCURSOR);
  355. return (LRESULT) TRUE;
  356. }
  357. // The user has dropped the item somewhere, if valid update it's
  358. // position
  359. case DL_DROPPED:
  360. {
  361. // Where are we now.
  362. iItem = LBItemFromPt(lpdli->hWnd, lpdli->ptCursor, TRUE);
  363. DOUT("DL_DROPPED: iItem = %d\r\n", iItem);
  364. // If the drop was somewhere valid
  365. if (iItem != -1)
  366. {
  367. // Remove the insert icon
  368. DrawInsert(hwnd, lpdli->hWnd, -1);
  369. // Move the item in the listbox
  370. if (m_iItemToMove != iItem)
  371. {
  372. SendMessage(lpdli->hWnd, LB_DELETESTRING, m_iItemToMove, 0L);
  373. SendMessage(lpdli->hWnd, LB_INSERTSTRING, iItem, (LPARAM) m_pszBuffer);
  374. SendMessage(lpdli->hWnd, LB_SETITEMDATA, iItem, m_lpData);
  375. SendMessage(lpdli->hWnd, LB_SETCURSEL, iItem, 0L);
  376. }
  377. }
  378. m_iItemToMove = (UINT) -1;
  379. SafeMemFree(m_pszBuffer);
  380. m_lpData = -1;
  381. // Set the return value to reset the cursor
  382. SetDlgMsgResult(hwnd, g_mDragList, DL_CURSORSET);
  383. return 0;
  384. }
  385. }
  386. return TRUE;
  387. }
  388. //
  389. // FUNCTION: CCombineAndDecode::_Order_OnClose()
  390. //
  391. // PURPOSE: This get's called when the user clicks on the "x" button in the
  392. // title bar.
  393. //
  394. void CCombineAndDecode::_Order_OnClose(HWND hwnd)
  395. {
  396. SendMessage(hwnd, WM_COMMAND, IDCANCEL, 0L);
  397. }
  398. /////////////////////////////////////////////////////////////////////////////
  399. //
  400. // Combine and Decode Progress dialog
  401. //
  402. /////////////////////////////////////////////////////////////////////////////
  403. INT_PTR CALLBACK CCombineAndDecode::CombineDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  404. {
  405. CCombineAndDecode *pThis;
  406. if (uMsg == WM_INITDIALOG)
  407. {
  408. SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  409. pThis = (CCombineAndDecode *) lParam;
  410. }
  411. else
  412. pThis = (CCombineAndDecode *) GetWindowLongPtr(hwnd, DWLP_USER);
  413. if (pThis)
  414. return (pThis->_CombineDlgProc(hwnd, uMsg, wParam, lParam));
  415. return (FALSE);
  416. }
  417. INT_PTR CALLBACK CCombineAndDecode::_CombineDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  418. {
  419. switch (uMsg)
  420. {
  421. case WM_INITDIALOG:
  422. return (BOOL) HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, _Combine_OnInitDialog);
  423. case WM_COMMAND:
  424. HANDLE_WM_COMMAND(hwnd, wParam, lParam, _Combine_OnCommand);
  425. return (TRUE);
  426. case WM_DESTROY:
  427. HANDLE_WM_CLOSE(hwnd, wParam, lParam, _Combine_OnDestroy);
  428. return (TRUE);
  429. case CND_GETNEXTARTICLE:
  430. _Combine_GetNextArticle(hwnd);
  431. return (TRUE);
  432. case CND_OPENNOTE:
  433. _Combine_OpenNote(hwnd);
  434. return (TRUE);
  435. case CND_MESSAGEAVAIL:
  436. _Combine_OnMsgAvail(m_hwndDlg);
  437. return (TRUE);
  438. }
  439. return (FALSE);
  440. }
  441. //
  442. // FUNCTION: CCombineAndDecode::_Combine_OnInitDialog()
  443. //
  444. // PURPOSE: Initializes the progress dialog by figuring out how many lines
  445. // will be downloaded, etc. To finish, we post a message to start
  446. // the first message downloading.
  447. //
  448. BOOL CCombineAndDecode::_Combine_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  449. {
  450. HRESULT hr = S_OK;
  451. LPMESSAGEINFO pInfo;
  452. m_hwndDlg = hwnd;
  453. // Create the CNewsMsgList for Opie's groovy combiner
  454. hr = MimeOleCreateMessageParts(&m_pMsgParts);
  455. if (FAILED(hr))
  456. {
  457. EndDialog(hwnd, 0);
  458. return (FALSE);
  459. }
  460. // Get a sum of the lines we need to download for the total messages
  461. m_cLinesTotal = 0;
  462. for (DWORD i = 0; i < m_cRows; i++)
  463. {
  464. // Get the message header from the table
  465. if (SUCCEEDED(m_pTable->GetRow(m_rgRows[i], &pInfo)))
  466. {
  467. m_cLinesTotal += pInfo->cbMessage;
  468. m_pTable->ReleaseRow(pInfo);
  469. }
  470. }
  471. // Set the initial state of the progress bar
  472. SendDlgItemMessage(hwnd, IDC_DOWNLOAD_PROG, PBM_SETRANGE, 0, MAKELONG(0, 100));
  473. SendDlgItemMessage(hwnd, IDC_DOWNLOAD_PROG, PBM_SETPOS, 0, 0);
  474. // Set up the animation
  475. if (Animate_Open(GetDlgItem(hwnd, IDC_DOWNLOAD_AVI), MAKEINTRESOURCE(idanDecode)))
  476. {
  477. Animate_Play(GetDlgItem(hwnd, IDC_DOWNLOAD_AVI), 0, -1, -1);
  478. }
  479. // Start the download
  480. m_dwCurrentArt = 0;
  481. m_cCurrentLine = 0;
  482. PostMessage(hwnd, CND_GETNEXTARTICLE, 0, 0L);
  483. CenterDialog(hwnd);
  484. ShowWindow(hwnd, SW_SHOW);
  485. return (TRUE);
  486. }
  487. //
  488. // FUNCTION: CCombineAndDecode::_Combine_OnCommand()
  489. //
  490. // PURPOSE: When the user hit's the Cancel button, we in turn tell the store
  491. // to stop downloading.
  492. //
  493. void CCombineAndDecode::_Combine_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  494. {
  495. if (id == IDCANCEL && m_pCancel)
  496. m_pCancel->Cancel(CT_CANCEL);
  497. }
  498. void CCombineAndDecode::_Combine_OnDestroy(HWND hwnd)
  499. {
  500. }
  501. //
  502. // FUNCTION: CCombineAndDecode::_Combine_GetNextArticle()
  503. //
  504. // PURPOSE: Called when we can start downloading another message.
  505. //
  506. void CCombineAndDecode::_Combine_GetNextArticle(HWND hwnd)
  507. {
  508. LPMIMEMESSAGE pMsg = NULL;
  509. LPMESSAGEINFO pInfo;
  510. TCHAR szProg[CCHMAX_STRINGRES];
  511. TCHAR szBuf[CCHMAX_STRINGRES];
  512. HRESULT hr;
  513. if (SUCCEEDED(m_pTable->GetRow(m_rgRows[m_dwCurrentArt], &pInfo)))
  514. {
  515. // Set the progress for the current article
  516. AthLoadString(idsProgDLMessage, szProg, ARRAYSIZE(szProg));
  517. wnsprintf(szBuf, ARRAYSIZE(szBuf), szProg, pInfo->pszSubject);
  518. SetDlgItemText(hwnd, IDC_GENERAL_TEXT, szBuf);
  519. // Reset the line count
  520. m_cPrevLine = 0;
  521. // Check to see if the message is cached
  522. if (!(pInfo->dwFlags & ARF_HASBODY))
  523. {
  524. // Request the message
  525. hr = m_pTable->OpenMessage(m_rgRows[m_dwCurrentArt], 0, &pMsg, (IStoreCallback *) this);
  526. if (FAILED(hr) && hr != E_PENDING)
  527. {
  528. AthMessageBoxW(m_hwndDlg, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrCantCombineNotConnected),
  529. 0, MB_OK | MB_ICONSTOP);
  530. EndDialog(m_hwndDlg, 0);
  531. }
  532. }
  533. else
  534. _Combine_OnMsgAvail(hwnd);
  535. if (pMsg)
  536. pMsg->Release();
  537. m_pTable->ReleaseRow(pInfo);
  538. }
  539. }
  540. //
  541. // FUNCTION: CCombineAndDecode::_Combine_OnMsgAvail()
  542. //
  543. // PURPOSE: Called once we've finished downloading an article.
  544. //
  545. void CCombineAndDecode::_Combine_OnMsgAvail(HWND hwnd)
  546. {
  547. LPMIMEMESSAGE pMsg = NULL;
  548. DWORD increment;
  549. TCHAR szProg[CCHMAX_STRINGRES];
  550. HRESULT hr;
  551. // Mark it read
  552. m_pTable->Mark(&(m_rgRows[m_dwCurrentArt]), 1, APPLY_CHILDREN, MARK_MESSAGE_READ, (IStoreCallback *) this);
  553. // Get the message now that it's available and add it to the combine list
  554. if (SUCCEEDED(hr = m_pTable->OpenMessage(m_rgRows[m_dwCurrentArt], 0, &pMsg, (IStoreCallback *) this)))
  555. {
  556. // Add this to the pMsgList
  557. m_pMsgParts->AddPart(pMsg);
  558. pMsg->Release();
  559. }
  560. // Update the progress
  561. LPMESSAGEINFO pInfo;
  562. if (SUCCEEDED(m_pTable->GetRow(m_rgRows[m_dwCurrentArt], &pInfo)))
  563. {
  564. increment = pInfo->cbMessage - m_cPrevLine;
  565. m_cCurrentLine += increment;
  566. m_pTable->ReleaseRow(pInfo);
  567. }
  568. if (m_cLinesTotal)
  569. {
  570. increment = m_cCurrentLine * 100 / m_cLinesTotal;
  571. SendDlgItemMessage(hwnd, IDC_DOWNLOAD_PROG, PBM_SETPOS, increment, 0);
  572. }
  573. // Increment the number of messages we've retrieved
  574. m_dwCurrentArt++;
  575. // If there are more to get, go get 'em
  576. if (m_dwCurrentArt < m_cRows)
  577. {
  578. PostMessage(hwnd, CND_GETNEXTARTICLE, 0, 0L);
  579. }
  580. else
  581. {
  582. PostMessage(hwnd, CND_OPENNOTE, 0, 0);
  583. }
  584. }
  585. void CCombineAndDecode::_Combine_OpenNote(HWND hwnd)
  586. {
  587. LPMIMEMESSAGE pMsgComb;
  588. LPMIMEMESSAGE pMsg = NULL;
  589. DWORD increment;
  590. TCHAR szProg[CCHMAX_STRINGRES];
  591. HRESULT hr;
  592. // Update the progress
  593. AthLoadString(idsProgCombiningMsgs, szProg, ARRAYSIZE(szProg));
  594. SetDlgItemText(hwnd, IDC_GENERAL_TEXT, szProg);
  595. SetDlgItemText(hwnd, IDC_SPECIFIC_TEXT, TEXT(""));
  596. // All the articles are downloaded. Merge the message list
  597. // and open the note.
  598. hr = m_pMsgParts->CombineParts(&pMsgComb);
  599. if (FAILED(hr))
  600. {
  601. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaNews),
  602. MAKEINTRESOURCEW(idsGenericError), 0, MB_OK | MB_ICONSTOP);
  603. }
  604. else
  605. {
  606. FOLDERINFO info;
  607. INIT_MSGSITE_STRUCT initStruct;
  608. DWORD dwCreateFlags = 0;
  609. if (SUCCEEDED(g_pStore->GetFolderInfo(m_idFolder, &info)))
  610. {
  611. // If this is a find folder, we need to put the account on the message
  612. if (!!(info.dwFlags & FOLDER_FINDRESULTS))
  613. {
  614. FOLDERID id;
  615. if (SUCCEEDED(m_pTable->GetRowFolderId(*m_rgRows, &id)))
  616. {
  617. FOLDERINFO fiServer = {0};
  618. if (SUCCEEDED(GetFolderServer(id, &fiServer)))
  619. {
  620. HrSetAccount(pMsgComb, fiServer.pszName);
  621. g_pStore->FreeRecord(&fiServer);
  622. }
  623. }
  624. }
  625. g_pStore->FreeRecord(&info);
  626. }
  627. // Initialize note struct
  628. initStruct.dwInitType = OEMSIT_MSG;
  629. initStruct.folderID = m_idFolder;
  630. initStruct.pMsg = pMsgComb;
  631. // Decide whether it is news or mail
  632. if (GetFolderType(m_idFolder) == FOLDER_NEWS)
  633. {
  634. FOLDERINFO rServer;
  635. if (SUCCEEDED(GetFolderServer(m_idFolder, &rServer)))
  636. {
  637. HrSetAccount(pMsgComb, rServer.pszAccountId);
  638. g_pStore->FreeRecord(&rServer);
  639. }
  640. dwCreateFlags = OENCF_NEWSFIRST;
  641. }
  642. // Create and Open Note
  643. hr = CreateAndShowNote(OENA_READ, dwCreateFlags, &initStruct, m_hwndParent);
  644. pMsgComb->Release();
  645. }
  646. EndDialog(m_hwndDlg, 0);
  647. }
  648. //
  649. // FUNCTION: CCombineAndDecode::OnBegin()
  650. //
  651. // PURPOSE: Called when the store starts downloading an article.
  652. //
  653. HRESULT CCombineAndDecode::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pOpInfo, IOperationCancel *pCancel)
  654. {
  655. Assert(tyOperation != SOT_INVALID);
  656. Assert(m_pCancel == NULL);
  657. m_type = tyOperation;
  658. if (pCancel != NULL)
  659. {
  660. m_pCancel = pCancel;
  661. m_pCancel->AddRef();
  662. }
  663. return(S_OK);
  664. }
  665. //
  666. // FUNCTION: CCombineAndDecode::OnProgress()
  667. //
  668. // PURPOSE: Called while the messages are downloading to give us some
  669. // progress.
  670. //
  671. HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus)
  672. {
  673. int increment;
  674. TCHAR szProg[CCHMAX_STRINGRES];
  675. TCHAR szBuf[CCHMAX_STRINGRES];
  676. Assert(m_hwndDlg != NULL);
  677. // Close any timeout dialog, if present
  678. CallbackCloseTimeout(&m_hTimeout);
  679. // Connection progress
  680. if (tyOperation == SOT_CONNECTION_STATUS)
  681. {
  682. Assert(dwCurrent < IXP_LAST);
  683. // Create some lovely status text
  684. int ids = XPUtil_StatusToString((IXPSTATUS) dwCurrent);
  685. AthLoadString(ids, szBuf, ARRAYSIZE(szBuf));
  686. SetDlgItemText(m_hwndDlg, IDC_GENERAL_TEXT, szBuf);
  687. }
  688. AthLoadString(idsProgDLGetLines, szProg, ARRAYSIZE(szProg));
  689. wnsprintf(szBuf, ARRAYSIZE(szBuf), szProg, dwCurrent, dwMax);
  690. SetDlgItemText(m_hwndDlg, IDC_SPECIFIC_TEXT, szBuf);
  691. increment = dwCurrent - m_cPrevLine;
  692. m_cCurrentLine += increment;
  693. m_cPrevLine = dwCurrent;
  694. if (m_cLinesTotal)
  695. {
  696. increment = m_cCurrentLine * 100 / m_cLinesTotal;
  697. SendDlgItemMessage(m_hwndDlg, IDC_DOWNLOAD_PROG, PBM_SETPOS, increment, 0);
  698. }
  699. return(S_OK);
  700. }
  701. //
  702. // FUNCTION: CCombineAndDecode::OnTimeout()
  703. //
  704. // PURPOSE: If a timeout occurs, we call through to the default timeout handler.
  705. //
  706. HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
  707. {
  708. // Display a timeout dialog
  709. return CallbackOnTimeout(pServer, ixpServerType, *pdwTimeout, (ITimeoutCallback *)this, &m_hTimeout);
  710. }
  711. //
  712. // FUNCTION: CCombineAndDecode::OnTimeoutResponse()
  713. //
  714. // PURPOSE: Called when the user responds to a timeout dialog.
  715. //
  716. HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnTimeoutResponse(TIMEOUTRESPONSE eResponse)
  717. {
  718. // Call into general timeout response utility
  719. return CallbackOnTimeoutResponse(eResponse, m_pCancel, &m_hTimeout);
  720. }
  721. //
  722. // FUNCTION: CCombineAndDecode::CanConnect()
  723. //
  724. // PURPOSE: Called if the store needs to connect to download the requested
  725. // messages. We just call through to the default handlers.
  726. //
  727. HRESULT STDMETHODCALLTYPE CCombineAndDecode::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
  728. {
  729. HWND hwndParent;
  730. DWORD dwReserved = 0;
  731. GetParentWindow(dwReserved, &hwndParent);
  732. return CallbackCanConnect(pszAccountId, hwndParent, TRUE);
  733. }
  734. //
  735. // FUNCTION: CCombineAndDecode::OnLogonPrompt()
  736. //
  737. // PURPOSE: If the user needs to logon, we present them with the default
  738. // logon UI.
  739. //
  740. HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType)
  741. {
  742. // Close any timeout dialog, if present
  743. CallbackCloseTimeout(&m_hTimeout);
  744. // Call into general OnLogonPrompt Utility
  745. return CallbackOnLogonPrompt(m_hwndDlg, pServer, ixpServerType);
  746. }
  747. //
  748. // FUNCTION: CCombineAndDecode::OnComplete()
  749. //
  750. // PURPOSE: When we finish downloading a message, this get's hit. We add
  751. // this message to the list for the combiner and then request the
  752. // next message.
  753. //
  754. HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
  755. {
  756. Assert(m_hwndDlg != NULL);
  757. AssertSz(m_type != SOT_INVALID, "somebody isn't calling OnBegin");
  758. // Close any timeout dialog, if present
  759. CallbackCloseTimeout(&m_hTimeout);
  760. if (m_type != tyOperation)
  761. return(S_OK);
  762. if (m_pCancel != NULL)
  763. {
  764. m_pCancel->Release();
  765. m_pCancel = NULL;
  766. }
  767. // If error occurred, display the error
  768. if (FAILED(hrComplete))
  769. {
  770. // Call into my swanky utility
  771. CallbackDisplayError(m_hwndDlg, hrComplete, pErrorInfo);
  772. EndDialog(m_hwndDlg, 0);
  773. }
  774. else
  775. {
  776. if (tyOperation == SOT_GET_MESSAGE)
  777. PostMessage(m_hwndDlg, CND_MESSAGEAVAIL, 0, 0);
  778. }
  779. return(S_OK);
  780. }
  781. //
  782. // FUNCTION: CCombineAndDecode::OnPrompt()
  783. //
  784. // PURPOSE: Last time I checked, this was SSL related goo.
  785. //
  786. HRESULT STDMETHODCALLTYPE CCombineAndDecode::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse)
  787. {
  788. // Close any timeout dialog, if present
  789. CallbackCloseTimeout(&m_hTimeout);
  790. // Call into my swanky utility
  791. return CallbackOnPrompt(m_hwndDlg, hrError, pszText, pszCaption, uType, piUserResponse);
  792. }
  793. //
  794. // FUNCTION: CCombineAndDecode::GetParentWindow()
  795. //
  796. // PURPOSE: Called if the store needs to show UI. We return our dialog
  797. // window handle.
  798. //
  799. HRESULT STDMETHODCALLTYPE CCombineAndDecode::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
  800. {
  801. Assert(m_hwndDlg != NULL);
  802. *phwndParent = m_hwndDlg;
  803. return(S_OK);
  804. }
  805. #if 0
  806. BOOL CALLBACK CombineAndDecodeProg(HWND hwnd, UINT uMsg, WPARAM wParam,
  807. LPARAM lParam)
  808. {
  809. PORDERPARAMS pop = (PORDERPARAMS) GetWindowLongPtr(hwnd, DWLP_USER);
  810. TCHAR szProg[CCHMAX_STRINGRES];
  811. TCHAR szBuf[CCHMAX_STRINGRES];
  812. LPMIMEMESSAGE pMsg=0;
  813. DWORD increment;
  814. HRESULT hr;
  815. switch (uMsg)
  816. {
  817. case IMC_BODYAVAIL:
  818. {
  819. LPMIMEMESSAGE pMsg = NULL;
  820. BOOL fCached = FALSE;
  821. Assert(pop->pGroup);
  822. if (SUCCEEDED(wParam) && SUCCEEDED(pop->pGroup->GetArticle(pop->rgpMsgs[pop->dwCurrentArt], &pMsg, hwnd, &fCached, FALSE, GETMSG_INSECURE)) && fCached)
  823. {
  824. Assert(pMsg);
  825. Order_OnMsgAvail(hwnd, pop, pMsg);
  826. }
  827. else
  828. {
  829. if ((HRESULT)wParam != hrUserCancel)
  830. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaNews),
  831. MAKEINTRESOURCEW(idsErrNewsCantOpen), 0, MB_OK | MB_ICONSTOP);
  832. PostMessage(hwnd, WM_CLOSE, 0, 0);
  833. }
  834. if (pMsg)
  835. pMsg->Release();
  836. return (TRUE);
  837. }
  838. }
  839. return (FALSE);
  840. }
  841. #endif