PageRenderTime 92ms CodeModel.GetById 17ms app.highlight 66ms RepoModel.GetById 1ms app.codeStats 0ms

/reporting/crashsender/ResendDlg.cpp

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