/reporting/crashsender/ResendDlg.cpp

http://crashrpt.googlecode.com/ · C++ · 1030 lines · 696 code · 200 blank · 134 comment · 87 complexity · 3b19118dc808280e0feb27bc4630f7d8 MD5 · raw file

  1. /*************************************************************************************
  2. This file is a part of CrashRpt library.
  3. Copyright (c) 2003-2013 The CrashRpt project authors. All Rights Reserved.
  4. Use of this source code is governed by a BSD-style license
  5. that can be found in the License.txt file in the root of the source
  6. tree. All contributing project authors may
  7. be found in the Authors.txt file in the root of the source tree.
  8. ***************************************************************************************/
  9. #include "stdafx.h"
  10. #include "resource.h"
  11. #include "CrashInfoReader.h"
  12. #include "ResendDlg.h"
  13. #include "Utility.h"
  14. #include "strconv.h"
  15. #include "DetailDlg.h"
  16. #include "ErrorReportSender.h"
  17. LRESULT CActionProgressDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  18. {
  19. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  20. // Determine window mirroring settings.
  21. CString sRTL = pSender->GetLangStr(_T("Settings"), _T("RTLReading"));
  22. if(sRTL.CompareNoCase(_T("1"))==0)
  23. {
  24. Utility::SetLayoutRTL(m_hWnd);
  25. }
  26. // The dialog will be resizable, so init resize map now.
  27. DlgResize_Init(false);
  28. // Init "current action" static
  29. m_statCurAction = GetDlgItem(IDC_CURRENTACTION);
  30. m_statCurAction.SetWindowText(
  31. pSender->GetLangStr(_T("ResendDlg"), _T("CurrentAction")));
  32. // Init "description" static
  33. m_statActionDesc = GetDlgItem(IDC_ACTIONDESC);
  34. // Init progress bar.
  35. m_prgProgress = GetDlgItem(IDC_PROGRESS);
  36. m_prgProgress.SetRange(0, 100);
  37. return 0;
  38. }
  39. LRESULT CActionProgressDlg::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  40. {
  41. return 0;
  42. }
  43. BOOL CResendDlg::PreTranslateMessage(MSG* pMsg)
  44. {
  45. return CWindow::IsDialogMessage(pMsg);
  46. }
  47. LRESULT CResendDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  48. {
  49. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  50. // Determine window mirroring settings.
  51. CString sRTL = pSender->GetLangStr(_T("Settings"), _T("RTLReading"));
  52. if(sRTL.CompareNoCase(_T("1"))==0)
  53. {
  54. Utility::SetLayoutRTL(m_hWnd);
  55. }
  56. // Set dialog caption
  57. CString sTitle;
  58. sTitle.Format(pSender->GetLangStr(_T("ResendDlg"), _T("DlgCaption")),
  59. pSender->GetCrashInfo()->m_sAppName);
  60. SetWindowText(sTitle);
  61. // center the dialog on the screen
  62. CenterWindow();
  63. // Set window icon
  64. HICON hIcon = pSender->GetCrashInfo()->GetCustomIcon();
  65. if(!hIcon)
  66. hIcon = ::LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME));
  67. SetIcon(hIcon, 0);
  68. // register object for message filtering and idle updates
  69. CMessageLoop* pLoop = _Module.GetMessageLoop();
  70. ATLASSERT(pLoop != NULL);
  71. pLoop->AddMessageFilter(this);
  72. // Set up controls
  73. m_statText = GetDlgItem(IDC_TEXT);
  74. m_statText.SetWindowText(pSender->GetLangStr(_T("ResendDlg"), _T("ClickForDetails")));
  75. // Init size static
  76. m_statSize = GetDlgItem(IDC_SELSIZE);
  77. m_statSize.SetWindowText(pSender->GetLangStr(_T("ResendDlg"), _T("SelectedSize")));
  78. // Init "Send Now" button
  79. m_btnSendNow = GetDlgItem(IDOK);
  80. m_btnSendNow.SetWindowText(pSender->GetLangStr(_T("ResendDlg"), _T("SendNow")));
  81. // Init "Other actions..." button
  82. m_btnOtherActions = GetDlgItem(IDC_OTHERACTIONS);
  83. m_btnOtherActions.SetWindowText(pSender->GetLangStr(_T("MainDlg"), _T("OtherActions")));
  84. // Init "Show Log" button
  85. m_btnShowLog = GetDlgItem(IDC_SHOWLOG);
  86. m_btnShowLog.SetWindowText(pSender->GetLangStr(_T("ResendDlg"), _T("ShowLog")));
  87. m_btnShowLog.ShowWindow(SW_HIDE);
  88. // Init list control
  89. m_listReportsSort.SubclassWindow(GetDlgItem(IDC_LIST));
  90. m_listReports.SubclassWindow(m_listReportsSort.m_hWnd);
  91. m_listReports.InsertColumn(0, pSender->GetLangStr(_T("ResendDlg"), _T("ColumnCreationDate")), LVCFMT_LEFT, 170);
  92. m_listReports.InsertColumn(1, pSender->GetLangStr(_T("ResendDlg"), _T("ColumnSize")), LVCFMT_RIGHT, 90);
  93. m_listReports.InsertColumn(2, pSender->GetLangStr(_T("ResendDlg"), _T("ColumnStatus")), LVCFMT_LEFT, 170);
  94. m_listReports.ModifyStyleEx(0, LVS_EX_FULLROWSELECT);
  95. m_listReportsSort.SetSortColumn(0); // Sort by creation date
  96. // Add items to the list.
  97. int i;
  98. for(i=0; i<pSender->GetCrashInfo()->GetReportCount(); i++)
  99. {
  100. CErrorReportInfo* eri = pSender->GetCrashInfo()->GetReport(i);
  101. SYSTEMTIME st;
  102. Utility::UTC2SystemTime(eri->GetSystemTimeUTC(), st);
  103. CString sCreationDate;
  104. sCreationDate.Format(_T("%04d-%02d-%02d %02d:%02d:%02d"),
  105. st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
  106. int nItem = m_listReports.InsertItem(i, sCreationDate);
  107. m_listReports.SetItemData(nItem, i);
  108. CString sTotalSize = Utility::FileSizeToStr(eri->GetTotalSize());
  109. m_listReports.SetItemText(nItem, 1, sTotalSize);
  110. m_listReports.SetCheckState(nItem, eri->IsSelected());
  111. }
  112. UpdateSelectionSize();
  113. m_statConsent = GetDlgItem(IDC_CONSENT);
  114. // Create font used for the static
  115. LOGFONT lf;
  116. memset(&lf, 0, sizeof(LOGFONT));
  117. lf.lfHeight = 11;
  118. lf.lfWeight = FW_NORMAL;
  119. lf.lfQuality = ANTIALIASED_QUALITY;
  120. _TCSCPY_S(lf.lfFaceName, 32, _T("Tahoma"));
  121. CFontHandle hConsentFont;
  122. hConsentFont.CreateFontIndirect(&lf);
  123. m_statConsent.SetFont(hConsentFont);
  124. if(pSender->GetCrashInfo()->m_sPrivacyPolicyURL.IsEmpty())
  125. m_statConsent.SetWindowText(pSender->GetLangStr(_T("ResendDlg"), _T("MyConsent2")));
  126. else
  127. m_statConsent.SetWindowText(pSender->GetLangStr(_T("ResendDlg"), _T("MyConsent")));
  128. // Init Privacy Policy link
  129. m_linkPrivacyPolicy.SubclassWindow(GetDlgItem(IDC_PRIVACYPOLICY));
  130. m_linkPrivacyPolicy.SetHyperLink(pSender->GetCrashInfo()->m_sPrivacyPolicyURL);
  131. m_linkPrivacyPolicy.SetLabel(pSender->GetLangStr(_T("MainDlg"), _T("PrivacyPolicy")));
  132. m_linkPrivacyPolicy.ShowWindow(pSender->GetCrashInfo()->m_sPrivacyPolicyURL.IsEmpty()?SW_HIDE:SW_SHOW);
  133. // Init progress bar
  134. m_dlgProgress.Create(m_hWnd);
  135. m_dlgProgress.ShowWindow(SW_HIDE);
  136. // Init child dialog
  137. m_dlgActionProgress.m_pParent = this;
  138. m_dlgActionProgress.Create(m_hWnd);
  139. m_dlgActionProgress.SetWindowLong(GWL_ID, IDD_PROGRESSMULTI);
  140. // Position child dialog.
  141. CRect rc;
  142. m_listReports.GetWindowRect(&rc);
  143. ScreenToClient(&rc);
  144. m_dlgActionProgress.SetWindowPos(HWND_TOP, rc.left, rc.bottom, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
  145. // Init resize map.
  146. DlgResize_Init();
  147. m_nSendAttempt = 0;
  148. // By default, we will exit if user closes the dialog.
  149. m_ActionOnClose = EXIT;
  150. // Register on notifications from sender
  151. pSender->SetNotificationWindow(m_hWnd);
  152. // Show balloon in 3 seconds.
  153. m_nTimerTick = 0;
  154. SetTimer(0, 3000);
  155. return TRUE;
  156. }
  157. LRESULT CResendDlg::OnTrayIcon(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
  158. {
  159. // This method is called when user clicks the tray icon.
  160. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  161. // If user clicks or right-clicks the tray icon or clicks the balloon,
  162. // then show the dialog.
  163. if(LOWORD(lParam)==WM_LBUTTONDOWN ||
  164. LOWORD(lParam)==WM_LBUTTONDBLCLK ||
  165. LOWORD(lParam)==NIN_BALLOONUSERCLICK)
  166. {
  167. KillTimer(0);
  168. ShowWindow(SW_SHOW);
  169. }
  170. // If user right-clicks the icon, display context menu.
  171. if(LOWORD(lParam)==WM_RBUTTONDOWN)
  172. {
  173. CPoint pt;
  174. GetCursorPos(&pt);
  175. CMenu menu = LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_POPUPMENU));
  176. CMenu submenu = menu.GetSubMenu(2);
  177. strconv_t strconv;
  178. CString sShow = pSender->GetLangStr(_T("ResendDlg"), _T("PopupShow"));
  179. CString sExit = pSender->GetLangStr(_T("ResendDlg"), _T("PopupExit"));
  180. MENUITEMINFO mii;
  181. memset(&mii, 0, sizeof(MENUITEMINFO));
  182. mii.cbSize = sizeof(MENUITEMINFO);
  183. mii.fMask = MIIM_STRING;
  184. mii.dwTypeData = sShow.GetBuffer(0);
  185. submenu.SetMenuItemInfo(ID_MENU3_SHOW, FALSE, &mii);
  186. mii.dwTypeData = sExit.GetBuffer(0);
  187. submenu.SetMenuItemInfo(ID_MENU3_EXIT, FALSE, &mii);
  188. submenu.TrackPopupMenu(0, pt.x, pt.y, m_hWnd);
  189. }
  190. return 0;
  191. }
  192. void CResendDlg::CloseDialog(int nVal)
  193. {
  194. // Close the dialog and exit message loop.
  195. DestroyWindow();
  196. AddTrayIcon(FALSE);
  197. // Exit the message loop
  198. ::PostQuitMessage(nVal);
  199. }
  200. LRESULT CResendDlg::OnPopupShow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  201. {
  202. // User chosen "Show" item from the popup menu.
  203. // Show the dialog.
  204. KillTimer(0);
  205. ShowWindow(SW_SHOW);
  206. return 0;
  207. }
  208. LRESULT CResendDlg::OnPopupExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  209. {
  210. // User chosen "Exit" item from the popup menu.
  211. // Exit the app.
  212. KillTimer(0);
  213. CloseDialog(0);
  214. return 0;
  215. }
  216. LRESULT CResendDlg::OnListItemChanging(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
  217. {
  218. // User clicks a list item's checkbox.
  219. // Depending on current state, we should
  220. // either allow or prevent changing the item
  221. NMLISTVIEW* pnmlv = (NMLISTVIEW *)pnmh;
  222. if(pnmlv->iItem>=0 && (pnmlv->uChanged&LVIF_STATE) &&
  223. ((pnmlv->uNewState&LVIS_STATEIMAGEMASK)!=(pnmlv->uOldState&LVIS_STATEIMAGEMASK)))
  224. {
  225. // If we are currently send error reports, than prevent
  226. // modifying check box state.
  227. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  228. if(pSender->IsSendingNow())
  229. return TRUE;
  230. }
  231. // Allow modifying item state
  232. return 0;
  233. }
  234. LRESULT CResendDlg::OnListItemChanged(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
  235. {
  236. // User clicks a list item's checkbox.
  237. // We need to update total size of selected crash reports.
  238. NMLISTVIEW* pnmlv = (NMLISTVIEW *)pnmh;
  239. if(pnmlv->iItem>=0 && (pnmlv->uChanged&LVIF_STATE) &&
  240. ((pnmlv->uNewState&LVIS_STATEIMAGEMASK)!=(pnmlv->uOldState&LVIS_STATEIMAGEMASK)))
  241. {
  242. UpdateSelectionSize();
  243. }
  244. return 0;
  245. }
  246. LRESULT CResendDlg::OnListDblClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
  247. {
  248. // User double-clicks a list item.
  249. // We need to open details dialog for the selected crash report.
  250. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  251. if(pSender->IsSendingNow())
  252. return 0; // Do nothing if in progress of sending
  253. NMITEMACTIVATE* pia = (NMITEMACTIVATE*)pnmh;
  254. if(pia->iItem>=0)
  255. {
  256. int nReport = (int)m_listReports.GetItemData(pia->iItem);
  257. // Show Error Report Details dialog
  258. CDetailDlg dlg;
  259. dlg.m_nCurReport = nReport;
  260. dlg.DoModal(m_hWnd);
  261. }
  262. return 0;
  263. }
  264. LRESULT CResendDlg::OnListRClick(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
  265. {
  266. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  267. CPoint pt;
  268. GetCursorPos(&pt);
  269. CMenu menu = LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_POPUPMENU));
  270. CMenu submenu = menu.GetSubMenu(5);
  271. strconv_t strconv;
  272. CString sSelectAll = pSender->GetLangStr(_T("ResendDlg"), _T("SelectAll"));
  273. CString sDeselectAll = pSender->GetLangStr(_T("ResendDlg"), _T("DeselectAll"));
  274. CString sDeleteSelected = pSender->GetLangStr(_T("ResendDlg"), _T("DeleteSelected"));
  275. CString sDeleteAll = pSender->GetLangStr(_T("ResendDlg"), _T("DeleteAll"));
  276. MENUITEMINFO mii;
  277. memset(&mii, 0, sizeof(MENUITEMINFO));
  278. mii.cbSize = sizeof(MENUITEMINFO);
  279. mii.fMask = MIIM_STRING;
  280. mii.dwTypeData = sSelectAll.GetBuffer(0);
  281. submenu.SetMenuItemInfo(ID_MENU6_SELECTALL, FALSE, &mii);
  282. mii.dwTypeData = sDeselectAll.GetBuffer(0);
  283. submenu.SetMenuItemInfo(ID_MENU6_DESELECTALL, FALSE, &mii);
  284. mii.dwTypeData = sDeleteSelected.GetBuffer(0);
  285. submenu.SetMenuItemInfo(ID_MENU6_DELETESELECTED, FALSE, &mii);
  286. mii.dwTypeData = sDeleteAll.GetBuffer(0);
  287. submenu.SetMenuItemInfo(ID_MENU6_DELETEALL, FALSE, &mii);
  288. BOOL bSendingNow = pSender->IsSendingNow();
  289. // Get count of checked list items
  290. int nItems = 0;
  291. int nChecked = 0;
  292. int i;
  293. for(i=0; i<m_listReports.GetItemCount(); i++)
  294. {
  295. nItems++;
  296. // If list item checked
  297. if(m_listReports.GetCheckState(i))
  298. nChecked++;
  299. }
  300. submenu.EnableMenuItem(ID_MENU6_SELECTALL, (!bSendingNow && nItems>0)?MF_ENABLED:MF_DISABLED);
  301. submenu.EnableMenuItem(ID_MENU6_DESELECTALL, (!bSendingNow && nItems>0)?MF_ENABLED:MF_DISABLED);
  302. submenu.EnableMenuItem(ID_MENU6_DELETESELECTED, (!bSendingNow && nChecked>0)?MF_ENABLED:MF_DISABLED);
  303. submenu.EnableMenuItem(ID_MENU6_DELETEALL, (!bSendingNow && nItems>0)?MF_ENABLED:MF_DISABLED);
  304. submenu.TrackPopupMenu(0, pt.x, pt.y, m_hWnd);
  305. return 0;
  306. }
  307. LRESULT CResendDlg::OnPopupSelectAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  308. {
  309. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  310. if(pSender->IsSendingNow())
  311. return 0; // Do nothing if in progress of sending
  312. int i;
  313. for(i=0; i<m_listReports.GetItemCount(); i++)
  314. {
  315. m_listReports.SetCheckState(i, TRUE);
  316. }
  317. UpdateSelectionSize();
  318. return 0;
  319. }
  320. LRESULT CResendDlg::OnPopupDeselectAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  321. {
  322. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  323. if(pSender->IsSendingNow())
  324. return 0; // Do nothing if in progress of sending
  325. int i;
  326. for(i=0; i<m_listReports.GetItemCount(); i++)
  327. {
  328. m_listReports.SetCheckState(i, FALSE);
  329. }
  330. UpdateSelectionSize();
  331. return 0;
  332. }
  333. LRESULT CResendDlg::OnPopupDeleteSelected(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  334. {
  335. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  336. if(pSender->IsSendingNow())
  337. return 0; // Do nothing if in progress of sending
  338. // Walk through error reports
  339. int i;
  340. for(i=0; i<m_listReports.GetItemCount(); i++)
  341. {
  342. // If list item checked
  343. if(m_listReports.GetCheckState(i))
  344. {
  345. // Get error report index from item data
  346. int nReport = (int)m_listReports.GetItemData(i);
  347. // Delete report
  348. pSender->GetCrashInfo()->DeleteReport(nReport);
  349. }
  350. }
  351. // Delete selected list items
  352. BOOL bFound = TRUE;
  353. while(bFound)
  354. {
  355. bFound = FALSE;
  356. int i;
  357. for(i=0; i<m_listReports.GetItemCount(); i++)
  358. {
  359. // If list item checked
  360. if(m_listReports.GetCheckState(i))
  361. {
  362. bFound = TRUE;
  363. m_listReports.DeleteItem(i);
  364. break;
  365. }
  366. }
  367. }
  368. UpdateSelectionSize();
  369. return 0;
  370. }
  371. LRESULT CResendDlg::OnPopupDeleteAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  372. {
  373. // Delete all error reports
  374. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  375. if(pSender->IsSendingNow())
  376. return 0; // Do nothing if in progress of sending
  377. pSender->GetCrashInfo()->DeleteAllReports();
  378. // Delete all list items
  379. m_listReports.DeleteAllItems();
  380. UpdateSelectionSize();
  381. return 0;
  382. }
  383. LRESULT CResendDlg::OnSendNow(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  384. {
  385. // User clicked "Send Now"/"Cancel" button.
  386. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  387. if(!pSender->IsSendingNow()) // "Send Now" clicked.
  388. {
  389. m_nSendAttempt ++;
  390. int i;
  391. for(i=0; i<m_listReports.GetItemCount(); i++)
  392. {
  393. int nReport = (int)m_listReports.GetItemData(i);
  394. BOOL bSelected = m_listReports.GetCheckState(i);
  395. CErrorReportInfo* eri = pSender->GetCrashInfo()->GetReport(nReport);
  396. eri->Select(bSelected);
  397. // Mark failed reports as pending to resend them
  398. if(eri->GetDeliveryStatus() == FAILED)
  399. eri->SetDeliveryStatus(PENDING);
  400. if(bSelected)
  401. {
  402. if(eri->GetDeliveryStatus() == PENDING)
  403. {
  404. m_listReports.SetItemText(i, 2,
  405. Utility::GetINIString(pSender->GetCrashInfo()->m_sLangFileName, _T("ResendDlg"), _T("StatusPending")));
  406. }
  407. }
  408. else
  409. {
  410. m_listReports.SetItemText(i, 2, _T(""));
  411. }
  412. }
  413. m_ActionOnClose = HIDE;
  414. m_statText.SetWindowText(pSender->GetLangStr(_T("ResendDlg"), _T("DeliveryingReports")));
  415. m_statSize.ShowWindow(SW_HIDE);
  416. m_statConsent.ShowWindow(SW_HIDE);
  417. m_linkPrivacyPolicy.ShowWindow(SW_HIDE);
  418. m_btnOtherActions.ShowWindow(SW_HIDE);
  419. m_btnShowLog.ShowWindow(SW_HIDE);
  420. m_dlgActionProgress.ShowWindow(SW_SHOW);
  421. m_btnSendNow.SetWindowText(pSender->GetLangStr(_T("ProgressDlg"), _T("Cancel")));
  422. SetTimer(1, 250); // Update this dialog every 250 ms
  423. if(m_nSendAttempt==1)
  424. SetTimer(2, 3000); // Hide this dialog in 3 sec.
  425. // Send error reports
  426. pSender->Run();
  427. }
  428. else // "Cancel" clicked
  429. {
  430. m_btnSendNow.EnableWindow(0);
  431. KillTimer(2); // Don't hide window
  432. pSender->Cancel();
  433. }
  434. return 0;
  435. }
  436. LRESULT CResendDlg::OnShowLog(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  437. {
  438. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  439. HINSTANCE hInst = ShellExecute(m_hWnd, _T("open"), pSender->GetLogFilePath(), NULL, NULL, SW_SHOW);
  440. ATLASSERT((int)hInst>32);
  441. hInst;
  442. return 0;
  443. }
  444. int CResendDlg::FindListItemByReportIndex(int nReport)
  445. {
  446. int i;
  447. for(i=0; i<m_listReports.GetItemCount(); i++)
  448. {
  449. int nData = (int)m_listReports.GetItemData(i);
  450. if(nData==nReport)
  451. return i;
  452. }
  453. return -1;
  454. }
  455. LRESULT CResendDlg::OnOtherActions(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  456. {
  457. // This method is called when user clicks the "Other actions..." button.
  458. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  459. CPoint pt;
  460. GetCursorPos(&pt);
  461. CMenu menu = LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_POPUPMENU));
  462. CMenu submenu = menu.GetSubMenu(3);
  463. strconv_t strconv;
  464. CString sRemindLater = pSender->GetLangStr(_T("ResendDlg"), _T("PopupRemindLater"));
  465. CString sNeverRemind = pSender->GetLangStr(_T("ResendDlg"), _T("PopupNeverRemind"));
  466. MENUITEMINFO mii;
  467. memset(&mii, 0, sizeof(MENUITEMINFO));
  468. mii.cbSize = sizeof(MENUITEMINFO);
  469. mii.fMask = MIIM_STRING;
  470. mii.dwTypeData = sRemindLater.GetBuffer(0);
  471. submenu.SetMenuItemInfo(ID_MENU4_REMINDLATER, FALSE, &mii);
  472. mii.dwTypeData = sNeverRemind.GetBuffer(0);
  473. submenu.SetMenuItemInfo(ID_MENU4_NEVERREMIND, FALSE, &mii);
  474. submenu.TrackPopupMenu(0, pt.x, pt.y, m_hWnd);
  475. return 0;
  476. }
  477. LRESULT CResendDlg::OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  478. {
  479. // This method is called when user clicks the Close (x) button on the dialog.
  480. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  481. // Either hide the dialog or close it.
  482. if(m_ActionOnClose==EXIT)
  483. {
  484. pSender->GetCrashInfo()->SetLastRemindDateToday();
  485. CloseDialog(0);
  486. return 0;
  487. }
  488. else if(m_ActionOnClose==HIDE)
  489. {
  490. AnimateWindow(m_hWnd, 200, AW_HIDE|AW_BLEND);
  491. return 0;
  492. }
  493. return 0;
  494. }
  495. LRESULT CResendDlg::OnRemindLater(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  496. {
  497. // This method is called when user clicks "Remind me later" item from the popup menu.
  498. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  499. pSender->GetCrashInfo()->SetLastRemindDateToday();
  500. pSender->GetCrashInfo()->SetRemindPolicy(REMIND_LATER);
  501. KillTimer(0);
  502. CloseDialog(0);
  503. return 0;
  504. }
  505. LRESULT CResendDlg::OnNeverRemind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  506. {
  507. // This method is called when user clicks "Never Remind" item from the popup menu.
  508. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  509. pSender->GetCrashInfo()->SetLastRemindDateToday();
  510. pSender->GetCrashInfo()->SetRemindPolicy(NEVER_REMIND);
  511. KillTimer(0);
  512. CloseDialog(0);
  513. return 0;
  514. }
  515. void CResendDlg::AddTrayIcon(BOOL bAdd)
  516. {
  517. // This method adds or removes tray icon.
  518. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  519. // Set up icon data
  520. NOTIFYICONDATA nf;
  521. memset(&nf,0,sizeof(NOTIFYICONDATA));
  522. nf.cbSize = sizeof(NOTIFYICONDATA);
  523. nf.hWnd = m_hWnd;
  524. nf.uID = 0;
  525. if(bAdd) // Add icon to tray
  526. {
  527. nf.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO ;
  528. nf.uCallbackMessage = WM_RESENDTRAYICON;
  529. nf.uVersion = NOTIFYICON_VERSION;
  530. // Format balloon tip caption
  531. CString sTip;
  532. sTip.Format(pSender->GetLangStr(_T("ResendDlg"), _T("DlgCaption")), pSender->GetCrashInfo()->m_sAppName);
  533. #if (NTDDI_VERSION >= NTDDI_WIN2K)
  534. // Truncate the string if it is too long.
  535. sTip = Utility::AddEllipsis(sTip, 127);
  536. _TCSCPY_S(nf.szTip, 127, sTip);
  537. #else
  538. // Truncate the string if it is too long.
  539. sTip = Utility::AddEllipsis(sTip, 63);
  540. _TCSCPY_S(nf.szTip, 63, sTip);
  541. #endif
  542. // Set balloon icon
  543. HICON hIcon = pSender->GetCrashInfo()->GetCustomIcon();
  544. if(!hIcon)
  545. hIcon = ::LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME));
  546. nf.hIcon = hIcon;
  547. // Format balloon text
  548. CString sInfo;
  549. sInfo.Format(pSender->GetLangStr(_T("ResendDlg"), _T("BalloonText")),
  550. pSender->GetCrashInfo()->m_sAppName, pSender->GetCrashInfo()->m_sAppName);
  551. // Truncate the string if it is too long.
  552. sInfo = Utility::AddEllipsis(sInfo, 255);
  553. _TCSCPY_S(nf.szInfo, 255, sInfo.GetBuffer(0));
  554. CString sInfoTitle;
  555. sInfoTitle.Format(pSender->GetLangStr(_T("ResendDlg"), _T("BalloonCaption")),
  556. pSender->GetCrashInfo()->m_sAppName);
  557. // Truncate the string if it is too long.
  558. sInfoTitle = Utility::AddEllipsis(sInfoTitle, 63);
  559. _TCSCPY_S(nf.szInfoTitle, 63, sInfoTitle.GetBuffer(0));
  560. Shell_NotifyIcon(NIM_ADD,&nf);
  561. }
  562. else // Delete icon
  563. {
  564. Shell_NotifyIcon(NIM_DELETE,&nf);
  565. }
  566. }
  567. void CResendDlg::UpdateSelectionSize()
  568. {
  569. // This method is called when user checks/unchecks an item
  570. // in the list. We should update the total selected size text.
  571. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  572. int nItemsSelected = 0;
  573. ULONG64 uSelectedFilesSize = 0;
  574. // Walk through items
  575. int i;
  576. for(i=0; i<m_listReports.GetItemCount(); i++)
  577. {
  578. if(m_listReports.GetCheckState(i)) // If item checked
  579. {
  580. // Determine the index of crash report associated with the item.
  581. int nReport = (int)m_listReports.GetItemData(i);
  582. // Increment item counter
  583. nItemsSelected++;
  584. // Update totals
  585. uSelectedFilesSize += pSender->GetCrashInfo()->GetReport(nReport)->GetTotalSize();
  586. }
  587. }
  588. // Update the text
  589. CString sText;
  590. sText.Format(pSender->GetLangStr(_T("ResendDlg"), _T("SelectedSize")), nItemsSelected,
  591. Utility::FileSizeToStr(uSelectedFilesSize).GetBuffer(0));
  592. m_statSize.SetWindowText(sText);
  593. // Enable/disable "Send Now button", depending on selected item count.
  594. m_btnSendNow.EnableWindow(nItemsSelected>0?TRUE:FALSE);
  595. }
  596. LRESULT CResendDlg::OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  597. {
  598. // This method is called when a timer ticks.
  599. if(wParam==0)
  600. DoBalloonTimer();
  601. else if(wParam==1)
  602. DoProgressTimer();
  603. else if(wParam==2)
  604. DoHideWindowTimer();
  605. return 0;
  606. }
  607. void CResendDlg::DoBalloonTimer()
  608. {
  609. if(m_nTimerTick==0)
  610. {
  611. // Show tray icon and balloon.
  612. AddTrayIcon(TRUE);
  613. // Stop timer
  614. KillTimer(0);
  615. // Wait for one minute. If user doesn't want to click the balloon, exit.
  616. SetTimer(0, 60000);
  617. }
  618. else if(m_nTimerTick==1)
  619. {
  620. // Stop timer
  621. KillTimer(0);
  622. // Close the app
  623. CloseDialog(0);
  624. }
  625. // Increment counter
  626. m_nTimerTick ++;
  627. }
  628. void CResendDlg::DoProgressTimer()
  629. {
  630. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  631. // Get current progress
  632. int nProgressPct = 0;
  633. std::vector<CString> messages;
  634. pSender->GetCurOpStatus(nProgressPct, messages);
  635. // Update progress bar
  636. m_dlgActionProgress.m_prgProgress.SetPos(nProgressPct);
  637. int nCurItem = FindListItemByReportIndex(pSender->GetCurReport());
  638. unsigned i;
  639. for(i=0; i<messages.size(); i++)
  640. {
  641. m_dlgActionProgress.m_statActionDesc.SetWindowText(messages[i]);
  642. if(messages[i].CompareNoCase(_T("[status_success]"))==0)
  643. {
  644. m_listReports.SetItemText(nCurItem, 2,
  645. pSender->GetLangStr(_T("ResendDlg"), _T("StatusSucceeded")));
  646. }
  647. else if(messages[i].CompareNoCase(_T("[status_failed]"))==0)
  648. {
  649. m_listReports.SetItemText(nCurItem, 2,
  650. pSender->GetLangStr(_T("ResendDlg"), _T("StatusFailed")));
  651. }
  652. else if(messages[i].CompareNoCase(_T("[confirm_launch_email_client]"))==0)
  653. {
  654. // We need to display message box to get user
  655. // confirmation on launching mail program.
  656. // Stop the timer that hides the window in 3 sec.
  657. KillTimer(2);
  658. // Save visibility state (to restore it later).
  659. BOOL bVisible = IsWindowVisible();
  660. // Display the dialog.
  661. ShowWindow(SW_SHOW);
  662. // Position it on top of other windows.
  663. SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
  664. // Set focus to it.
  665. SetFocus();
  666. // Update it.
  667. RedrawWindow(0, 0, RDW_ERASE|RDW_FRAME|RDW_INVALIDATE);
  668. m_listReports.RedrawWindow(0, 0, RDW_ERASE|RDW_FRAME|RDW_INVALIDATE);
  669. // Determine window mirroring flags (language specific).
  670. DWORD dwFlags = 0;
  671. CString sRTL = Utility::GetINIString(pSender->GetCrashInfo()->m_sLangFileName, _T("Settings"), _T("RTLReading"));
  672. if(sRTL.CompareNoCase(_T("1"))==0)
  673. dwFlags = MB_RTLREADING;
  674. // Get mail program name.
  675. CString sMailClientName;
  676. CMailMsg::DetectMailClient(sMailClientName);
  677. CString msg;
  678. msg.Format(pSender->GetLangStr(_T("ProgressDlg"), _T("ConfirmLaunchEmailClient")), sMailClientName);
  679. // Display message box.
  680. CString sCaption = pSender->GetLangStr(_T("ProgressDlg"), _T("DlgCaption"));
  681. CString sTitle;
  682. sTitle.Format(sCaption, pSender->GetCrashInfo()->m_sAppName);
  683. INT_PTR result = MessageBox(msg,
  684. sTitle,
  685. MB_OKCANCEL|MB_ICONQUESTION|dwFlags);
  686. // Update window
  687. RedrawWindow(0, 0, RDW_ERASE|RDW_FRAME|RDW_INVALIDATE);
  688. m_listReports.RedrawWindow(0, 0, RDW_ERASE|RDW_FRAME|RDW_INVALIDATE);
  689. // Unblock worker thread.
  690. pSender->FeedbackReady(result==IDOK?0:1);
  691. // Restore window visibility
  692. ShowWindow(bVisible?SW_SHOW:SW_HIDE);
  693. }
  694. }
  695. }
  696. LRESULT CResendDlg::OnNextItemHint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  697. {
  698. // This method determines what error report should be sent next.
  699. // Error reports are being sent in the order they appear in the list.
  700. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  701. // Walk through items and look for pending one
  702. int i;
  703. for(i=0; i<m_listReports.GetItemCount(); i++)
  704. {
  705. if(m_listReports.GetCheckState(i)) // If item checked
  706. {
  707. // Determine the index of crash report associated with the item.
  708. int nReport = (int)m_listReports.GetItemData(i);
  709. CErrorReportInfo* pERI = pSender->GetCrashInfo()->GetReport(nReport);
  710. if(pERI==NULL)
  711. continue;
  712. if(pERI->GetDeliveryStatus()!=PENDING)
  713. continue;
  714. return nReport;
  715. }
  716. }
  717. // No pending items found
  718. return -1;
  719. }
  720. LRESULT CResendDlg::OnItemStatusChanged(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
  721. {
  722. int nReport = (int)wParam;
  723. DELIVERY_STATUS Status = (DELIVERY_STATUS)lParam;
  724. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  725. CString sStatus;
  726. if(Status==PENDING)
  727. sStatus = pSender->GetLangStr(_T("ResendDlg"), _T("StatusPending"));
  728. else if(Status==INPROGRESS)
  729. sStatus = pSender->GetLangStr(_T("ResendDlg"), _T("StatusInProgress"));
  730. else if(Status==DELIVERED)
  731. sStatus = pSender->GetLangStr(_T("ResendDlg"), _T("StatusSucceeded"));
  732. else if(Status==FAILED)
  733. sStatus = pSender->GetLangStr(_T("ResendDlg"), _T("StatusFailed"));
  734. int nItem = FindListItemByReportIndex(nReport);
  735. m_listReports.SetItemText(nItem, 2, sStatus);
  736. m_listReports.EnsureVisible(nItem, TRUE);
  737. m_listReports.SetItemState(nItem, LVIS_SELECTED, LVIS_SELECTED);
  738. return 0;
  739. }
  740. LRESULT CResendDlg::OnDeliveryComplete(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  741. {
  742. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  743. m_ActionOnClose = EXIT;
  744. // Stop timers
  745. KillTimer(1);
  746. KillTimer(2);
  747. // Update control states.
  748. m_btnSendNow.EnableWindow(1);
  749. m_btnOtherActions.ShowWindow(SW_SHOW);
  750. m_btnShowLog.ShowWindow(SW_SHOW);
  751. m_statSize.ShowWindow(SW_SHOW);
  752. m_statConsent.ShowWindow(SW_SHOW);
  753. m_linkPrivacyPolicy.ShowWindow(SW_SHOW);
  754. m_btnOtherActions.ShowWindow(SW_SHOW);
  755. m_dlgActionProgress.ShowWindow(SW_HIDE);
  756. m_btnSendNow.SetWindowText(pSender->GetLangStr(_T("ResendDlg"), _T("SendNow")));
  757. m_statText.SetWindowText(pSender->GetLangStr(_T("ResendDlg"), _T("ClickForDetails")));
  758. // Update Status column of the list view
  759. int i;
  760. for(i=0; i<m_listReports.GetItemCount(); i++)
  761. {
  762. BOOL bSelected = m_listReports.GetCheckState(i);
  763. if(bSelected)
  764. {
  765. int nReport = (int)m_listReports.GetItemData(i);
  766. DELIVERY_STATUS status = pSender->GetCrashInfo()->GetReport(nReport)->GetDeliveryStatus();
  767. if(status==PENDING)
  768. {
  769. m_listReports.SetItemText(i, 2, _T(""));
  770. }
  771. }
  772. }
  773. // Determine window mirroring settings
  774. DWORD dwFlags = 0;
  775. CString sRTL = pSender->GetLangStr(_T("Settings"), _T("RTLReading"));
  776. if(sRTL.CompareNoCase(_T("1"))==0)
  777. dwFlags = MB_RTLREADING;
  778. CString sCaption;
  779. sCaption.Format(pSender->GetLangStr(_T("ResendDlg"), _T("DlgCaption")),
  780. pSender->GetCrashInfo()->m_sAppName);
  781. if(pSender->HasErrors())
  782. {
  783. // Show dialog
  784. ShowWindow(SW_SHOW);
  785. // Display it on top of other windows
  786. SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
  787. // Set focus to it
  788. SetFocus();
  789. // Redraw it
  790. RedrawWindow(0, 0, RDW_ERASE|RDW_FRAME|RDW_INVALIDATE);
  791. m_listReports.RedrawWindow(0, 0, RDW_ERASE|RDW_FRAME|RDW_INVALIDATE);
  792. // Display message box
  793. MessageBox(pSender->GetLangStr(_T("ResendDlg"), _T("DeliveryFailed")),
  794. sCaption,
  795. MB_OK|MB_ICONINFORMATION|dwFlags);
  796. }
  797. else
  798. {
  799. if(IsWindowVisible())
  800. {
  801. // Display message box
  802. MessageBox(pSender->GetLangStr(_T("ResendDlg"), _T("DeliverySucceeded")),
  803. sCaption,
  804. MB_OK|MB_ICONINFORMATION|dwFlags);
  805. }
  806. // Close the dialog
  807. SendMessage(WM_CLOSE);
  808. }
  809. return 0;
  810. }
  811. void CResendDlg::DoHideWindowTimer()
  812. {
  813. // Hide the dialog smoothly
  814. AnimateWindow(m_hWnd, 200, AW_HIDE|AW_BLEND);
  815. // Stop the timer
  816. KillTimer(2);
  817. }
  818. LRESULT CResendDlg::OnReportSizeChanged(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  819. {
  820. int nReport = (int)wParam;
  821. CErrorReportSender* pSender = CErrorReportSender::GetInstance();
  822. // Update list
  823. int nItem = FindListItemByReportIndex(nReport);
  824. CString sTotalSize = Utility::FileSizeToStr(pSender->GetCrashInfo()->GetReport(nReport)->GetTotalSize());
  825. m_listReports.SetItemText(nItem, 1, sTotalSize);
  826. // Update the selection size
  827. UpdateSelectionSize();
  828. return 0;
  829. }