1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008 - TortoiseSVN
4 // Copyright (C) 2008-2014 - TortoiseGit
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "TortoiseProc.h"
22 #include "LoglistCommonResource.h"
23 #include "..\version.h"
24 #include "MessageBox.h"
25 #include "CheckForUpdatesDlg.h"
29 #include "SmartHandle.h"
31 #include "PathUtils.h"
32 #include "DirFileEnum.h"
33 #include "UnicodeUtils.h"
34 #include "UpdateCrypto.h"
37 #define SIGNATURE_FILE_ENDING _T(".asc")
39 #define WM_USER_DISPLAYSTATUS (WM_USER + 1)
40 #define WM_USER_ENDDOWNLOAD (WM_USER + 2)
41 #define WM_USER_FILLCHANGELOG (WM_USER + 3)
43 IMPLEMENT_DYNAMIC(CCheckForUpdatesDlg
, CStandAloneDialog
)
44 CCheckForUpdatesDlg::CCheckForUpdatesDlg(CWnd
* pParent
/*=NULL*/)
45 : CStandAloneDialog(CCheckForUpdatesDlg::IDD
, pParent
)
49 , m_pDownloadThread(NULL
)
50 , m_bThreadRunning(FALSE
)
51 , m_updateDownloader(nullptr)
53 m_sUpdateDownloadLink
= _T("http://redir.tortoisegit.org/download");
56 CCheckForUpdatesDlg::~CCheckForUpdatesDlg()
60 void CCheckForUpdatesDlg::DoDataExchange(CDataExchange
* pDX
)
62 CStandAloneDialog::DoDataExchange(pDX
);
63 DDX_Control(pDX
, IDC_LINK
, m_link
);
64 DDX_Control(pDX
, IDC_PROGRESSBAR
, m_progress
);
65 DDX_Control(pDX
, IDC_LIST_DOWNLOADS
, m_ctrlFiles
);
66 DDX_Control(pDX
, IDC_BUTTON_UPDATE
, m_ctrlUpdate
);
67 DDX_Control(pDX
, IDC_LOGMESSAGE
, m_cLogMessage
);
70 BEGIN_MESSAGE_MAP(CCheckForUpdatesDlg
, CStandAloneDialog
)
72 ON_WM_WINDOWPOSCHANGING()
75 ON_BN_CLICKED(IDC_BUTTON_UPDATE
, OnBnClickedButtonUpdate
)
76 ON_MESSAGE(WM_USER_DISPLAYSTATUS
, OnDisplayStatus
)
77 ON_MESSAGE(WM_USER_ENDDOWNLOAD
, OnEndDownload
)
78 ON_MESSAGE(WM_USER_FILLCHANGELOG
, OnFillChangelog
)
79 ON_REGISTERED_MESSAGE(WM_TASKBARBTNCREATED
, OnTaskbarBtnCreated
)
82 BOOL
CCheckForUpdatesDlg::OnInitDialog()
84 CStandAloneDialog::OnInitDialog();
85 CAppUtils::MarkWindowAsUnpinnable(m_hWnd
);
88 temp
.Format(IDS_CHECKNEWER_YOURVERSION
, TGIT_VERMAJOR
, TGIT_VERMINOR
, TGIT_VERMICRO
, TGIT_VERBUILD
);
89 SetDlgItemText(IDC_YOURVERSION
, temp
);
91 DialogEnableWindow(IDOK
, FALSE
);
93 m_pTaskbarList
.Release();
94 if (FAILED(m_pTaskbarList
.CoCreateInstance(CLSID_TaskbarList
)))
95 m_pTaskbarList
= nullptr;
97 // hide download controls
98 m_ctrlFiles
.ShowWindow(SW_HIDE
);
99 GetDlgItem(IDC_GROUP_DOWNLOADS
)->ShowWindow(SW_HIDE
);
100 RECT rectWindow
, rectGroupDownloads
, rectOKButton
;
101 GetWindowRect(&rectWindow
);
102 GetDlgItem(IDC_GROUP_DOWNLOADS
)->GetWindowRect(&rectGroupDownloads
);
103 GetDlgItem(IDOK
)->GetWindowRect(&rectOKButton
);
104 LONG bottomDistance
= rectWindow
.bottom
- rectOKButton
.bottom
;
105 OffsetRect(&rectOKButton
, 0, rectGroupDownloads
.top
- rectOKButton
.top
);
106 rectWindow
.bottom
= rectOKButton
.bottom
+ bottomDistance
;
107 MoveWindow(&rectWindow
);
108 ::MapWindowPoints(NULL
, GetSafeHwnd(), (LPPOINT
)&rectOKButton
, 2);
109 GetDlgItem(IDOK
)->MoveWindow(&rectOKButton
);
111 temp
.LoadString(IDS_STATUSLIST_COLFILE
);
112 m_ctrlFiles
.InsertColumn(0, temp
, 0, -1);
113 m_ctrlFiles
.InsertColumn(1, temp
, 0, -1);
114 m_ctrlFiles
.SetExtendedStyle(LVS_EX_DOUBLEBUFFER
| LVS_EX_CHECKBOXES
);
115 m_ctrlFiles
.SetColumnWidth(0, 350);
116 m_ctrlFiles
.SetColumnWidth(1, 200);
118 ProjectProperties pp
;
119 pp
.SetCheckRe(_T("[Ii]ssues?:?(\\s*(,|and)?\\s*#?\\d+)+"));
120 pp
.SetBugIDRe(_T("(\\d+)"));
121 pp
.lProjectLanguage
= -1;
122 pp
.sUrl
= _T("http://code.google.com/p/tortoisegit/issues/detail?id=%BUGID%");
123 m_cLogMessage
.Init(pp
);
124 m_cLogMessage
.SetFont((CString
)CRegString(_T("Software\\TortoiseGit\\LogFontName"), _T("Courier New")), (DWORD
)CRegDWORD(_T("Software\\TortoiseGit\\LogFontSize"), 8));
125 m_cLogMessage
.Call(SCI_SETREADONLY
, TRUE
);
127 m_updateDownloader
= new CUpdateDownloader(GetSafeHwnd(), m_bForce
== TRUE
, WM_USER_DISPLAYSTATUS
, &m_eventStop
);
129 if (AfxBeginThread(CheckThreadEntry
, this)==NULL
)
131 CMessageBox::Show(NULL
, IDS_ERR_THREADSTARTFAILED
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
134 SetTimer(100, 1000, NULL
);
138 void CCheckForUpdatesDlg::OnDestroy()
140 for (int i
= 0; i
< m_ctrlFiles
.GetItemCount(); ++i
)
141 delete (CUpdateListCtrl::Entry
*)m_ctrlFiles
.GetItemData(i
);
143 if (m_updateDownloader
)
144 delete m_updateDownloader
;
146 CStandAloneDialog::OnDestroy();
149 void CCheckForUpdatesDlg::OnOK()
151 if (m_bThreadRunning
|| m_pDownloadThread
!= NULL
)
152 return; // Don't exit while downloading
154 CStandAloneDialog::OnOK();
157 void CCheckForUpdatesDlg::OnCancel()
159 if (m_bThreadRunning
|| m_pDownloadThread
!= NULL
)
160 return; // Don't exit while downloading
161 CStandAloneDialog::OnCancel();
164 UINT
CCheckForUpdatesDlg::CheckThreadEntry(LPVOID pVoid
)
166 return ((CCheckForUpdatesDlg
*)pVoid
)->CheckThread();
169 UINT
CCheckForUpdatesDlg::CheckThread()
171 m_bThreadRunning
= TRUE
;
174 CString tempfile
= CTempFiles::Instance().GetTempFilePath(true).GetWinPathString();
176 bool official
= false;
178 CRegString checkurluser
= CRegString(_T("Software\\TortoiseGit\\UpdateCheckURL"), _T(""));
179 CRegString checkurlmachine
= CRegString(_T("Software\\TortoiseGit\\UpdateCheckURL"), _T(""), FALSE
, HKEY_LOCAL_MACHINE
);
180 CString sCheckURL
= checkurluser
;
181 if (sCheckURL
.IsEmpty())
183 sCheckURL
= checkurlmachine
;
184 if (sCheckURL
.IsEmpty())
187 bool checkPreview
= false;
191 CRegStdDWORD
regCheckPreview(L
"Software\\TortoiseGit\\VersionCheckPreview", FALSE
);
192 if (DWORD(regCheckPreview
))
197 sCheckURL
= _T("http://version.tortoisegit.googlecode.com/git/version-preview.txt");
198 SetDlgItemText(IDC_SOURCE
, _T("Using preview release channel"));
201 sCheckURL
= _T("http://version.tortoisegit.googlecode.com/git/version.txt");
206 SetDlgItemText(IDC_SOURCE
, _T("Using (unofficial) release channel: ") + sCheckURL
);
209 BOOL ret
= m_updateDownloader
->DownloadFile(sCheckURL
, tempfile
, false);
210 if (!ret
&& official
)
212 CString signatureTempfile
= CTempFiles::Instance().GetTempFilePath(true).GetWinPathString();
213 ret
= m_updateDownloader
->DownloadFile(sCheckURL
+ SIGNATURE_FILE_ENDING
, signatureTempfile
, false);
214 if (!ret
&& VerifyIntegrity(tempfile
, signatureTempfile
, m_updateDownloader
))
216 SetDlgItemText(IDC_CHECKRESULT
, _T("Could not verify digital signature."));
217 DeleteUrlCacheEntry(sCheckURL
);
218 DeleteUrlCacheEntry(sCheckURL
+ SIGNATURE_FILE_ENDING
);
224 DeleteUrlCacheEntry(sCheckURL
);
225 if (CRegDWORD(_T("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\GlobalUserOffline"), 0))
226 errorText
.LoadString(IDS_OFFLINEMODE
); // offline mode enabled
228 errorText
.Format(IDS_CHECKNEWER_NETERROR_FORMAT
, ret
);
234 CStdioFile
file(tempfile
, CFile::modeRead
| CFile::shareDenyWrite
);
236 unsigned int major
,minor
,micro
,build
;
237 major
=minor
=micro
=build
=0;
238 unsigned __int64 version
=0;
240 if (file
.ReadString(ver
))
242 CString vertemp
= ver
;
243 // another versionstring for the filename can be provided after a semicolon
244 // this is needed for preview releases
245 int differentFilenamePos
= vertemp
.Find(_T(";"));
246 if (differentFilenamePos
> 0)
248 vertemp
= vertemp
.Left(differentFilenamePos
);
249 ver
= ver
.Mid(differentFilenamePos
+ 1);
252 major
= _ttoi(vertemp
);
253 vertemp
= vertemp
.Mid(vertemp
.Find('.')+1);
254 minor
= _ttoi(vertemp
);
255 vertemp
= vertemp
.Mid(vertemp
.Find('.')+1);
256 micro
= _ttoi(vertemp
);
257 vertemp
= vertemp
.Mid(vertemp
.Find('.')+1);
258 build
= _ttoi(vertemp
);
272 if (major
> TGIT_VERMAJOR
)
274 else if ((minor
> TGIT_VERMINOR
)&&(major
== TGIT_VERMAJOR
))
276 else if ((micro
> TGIT_VERMICRO
)&&(minor
== TGIT_VERMINOR
)&&(major
== TGIT_VERMAJOR
))
278 else if ((build
> TGIT_VERBUILD
)&&(micro
== TGIT_VERMICRO
)&&(minor
== TGIT_VERMINOR
)&&(major
== TGIT_VERMAJOR
))
284 version
.Format(_T("%u.%u.%u.%u"),major
,minor
,micro
,build
);
286 version
+= _T(" (") + ver
+ _T(")");
287 temp
.Format(IDS_CHECKNEWER_CURRENTVERSION
, (LPCTSTR
)version
);
288 SetDlgItemText(IDC_CURRENTVERSION
, temp
);
293 temp
.LoadString(IDS_CHECKNEWER_NETERROR
);
294 SetDlgItemText(IDC_CHECKRESULT
, temp
);
298 if(file
.ReadString(temp
) && !temp
.IsEmpty())
299 { // Read the next line, it could contain a message for the user
301 if(file
.ReadString(tempLink
) && !tempLink
.IsEmpty())
302 { // Read another line to find out the download link-URL, if any
303 m_sUpdateDownloadLink
= tempLink
;
308 temp
.LoadString(IDS_CHECKNEWER_NEWERVERSIONAVAILABLE
);
310 file
.ReadString(tempLink
);
312 SetDlgItemText(IDC_CHECKRESULT
, temp
);
316 FillDownloads(file
, ver
);
318 // Show download controls
319 RECT rectWindow
, rectProgress
, rectGroupDownloads
, rectOKButton
;
320 GetWindowRect(&rectWindow
);
321 m_progress
.GetWindowRect(&rectProgress
);
322 GetDlgItem(IDC_GROUP_DOWNLOADS
)->GetWindowRect(&rectGroupDownloads
);
323 GetDlgItem(IDOK
)->GetWindowRect(&rectOKButton
);
324 LONG bottomDistance
= rectWindow
.bottom
- rectOKButton
.bottom
;
325 OffsetRect(&rectOKButton
, 0, (rectGroupDownloads
.bottom
+ (rectGroupDownloads
.bottom
- rectProgress
.bottom
)) - rectOKButton
.top
);
326 rectWindow
.bottom
= rectOKButton
.bottom
+ bottomDistance
;
327 MoveWindow(&rectWindow
);
328 ::MapWindowPoints(NULL
, GetSafeHwnd(), (LPPOINT
)&rectOKButton
, 2);
329 GetDlgItem(IDOK
)->MoveWindow(&rectOKButton
);
330 m_ctrlFiles
.ShowWindow(SW_SHOW
);
331 GetDlgItem(IDC_GROUP_DOWNLOADS
)->ShowWindow(SW_SHOW
);
336 temp
.LoadString(IDS_CHECKNEWER_YOURUPTODATE
);
337 SetDlgItemText(IDC_CHECKRESULT
, temp
);
338 file
.ReadString(temp
);
339 file
.ReadString(temp
);
344 catch (CException
* e
)
347 temp
.LoadString(IDS_CHECKNEWER_NETERROR
);
348 SetDlgItemText(IDC_CHECKRESULT
, temp
);
353 SetDlgItemText(IDC_CHECKRESULT
, errorText
);
355 if (!m_sUpdateDownloadLink
.IsEmpty())
357 m_link
.ShowWindow(SW_SHOW
);
358 m_link
.SetURL(m_sUpdateDownloadLink
);
362 m_bThreadRunning
= FALSE
;
363 DialogEnableWindow(IDOK
, TRUE
);
367 void CCheckForUpdatesDlg::FillDownloads(CStdioFile
&file
, CString version
)
370 const CString x86x64
= _T("64");
372 const CString x86x64
= _T("32");
375 if (!file
.ReadString(m_sFilesURL
) || m_sFilesURL
.IsEmpty())
376 m_sFilesURL
.Format(_T("http://updater.download.tortoisegit.org/tgit/%s/"), version
);
378 m_ctrlFiles
.InsertItem(0, _T("TortoiseGit"));
380 filename
.Format(_T("TortoiseGit-%s-%sbit.msi"), version
, x86x64
);
381 m_ctrlFiles
.SetItemData(0, (DWORD_PTR
)(new CUpdateListCtrl::Entry(filename
, CUpdateListCtrl::STATUS_NONE
)));
382 m_ctrlFiles
.SetCheck(0 , TRUE
);
384 std::vector
<DWORD
> m_installedLangs
;
386 // set up the language selecting combobox
387 CString path
= CPathUtils::GetAppParentDirectory();
388 path
= path
+ _T("Languages\\");
389 CSimpleFileFind
finder(path
, _T("*.dll"));
390 while (finder
.FindNextFileNoDirectories())
392 CString file
= finder
.GetFilePath();
393 CString filename
= finder
.GetFileName();
394 if (filename
.Left(12).CompareNoCase(_T("TortoiseProc")) == 0)
396 CString sVer
= _T(STRPRODUCTVER
);
397 sVer
= sVer
.Left(sVer
.ReverseFind('.'));
398 CString sFileVer
= CPathUtils::GetVersionFromFile(file
);
399 sFileVer
= sFileVer
.Left(sFileVer
.ReverseFind('.'));
400 CString sLoc
= filename
.Mid(12);
401 sLoc
= sLoc
.Left(sLoc
.GetLength() - 4); // cut off ".dll"
402 if ((sLoc
.Left(2) == L
"32") && (sLoc
.GetLength() > 5))
404 DWORD loc
= _tstoi(filename
.Mid(12));
405 m_installedLangs
.push_back(loc
);
411 while (file
.ReadString(langs
) && !langs
.IsEmpty())
413 CString sLang
= _T("TortoiseGit Language Pack ") + langs
.Mid(5);
415 DWORD loc
= _tstoi(langs
.Mid(0, 4));
416 TCHAR buf
[MAX_PATH
] = {0};
417 GetLocaleInfo(loc
, LOCALE_SNATIVELANGNAME
, buf
, _countof(buf
));
419 GetLocaleInfo(loc
, LOCALE_SNATIVECTRYNAME
, buf
, _countof(buf
));
427 int pos
= m_ctrlFiles
.InsertItem(m_ctrlFiles
.GetItemCount(), sLang
);
428 m_ctrlFiles
.SetItemText(pos
, 1, sLang2
);
431 filename
.Format(_T("TortoiseGit-LanguagePack-%s-%sbit-%s.msi"), version
, x86x64
, langs
.Mid(5));
432 m_ctrlFiles
.SetItemData(pos
, (DWORD_PTR
)(new CUpdateListCtrl::Entry(filename
, CUpdateListCtrl::STATUS_NONE
)));
434 if (std::find(m_installedLangs
.begin(), m_installedLangs
.end(), loc
) != m_installedLangs
.end())
435 m_ctrlFiles
.SetCheck(pos
, TRUE
);
437 DialogEnableWindow(IDC_BUTTON_UPDATE
, TRUE
);
440 void CCheckForUpdatesDlg::FillChangelog(CStdioFile
&file
)
442 CString sChangelogURL
;
443 if (!file
.ReadString(sChangelogURL
) || sChangelogURL
.IsEmpty())
444 sChangelogURL
= _T("http://tortoisegit.googlecode.com/git/src/Changelog.txt");
446 CString tempchangelogfile
= CTempFiles::Instance().GetTempFilePath(true).GetWinPathString();
447 if (!m_updateDownloader
->DownloadFile(sChangelogURL
, tempchangelogfile
, false))
450 CStdioFile
file(tempchangelogfile
, CFile::modeRead
|CFile::typeText
);
453 while (file
.ReadString(str
))
458 if (str
.GetLength() > 2 && str
.GetAt(0) == 0xEF && str
.GetAt(1) == 0xBB)
460 if (str
.GetAt(2) == 0xBF)
470 str
= CUnicodeUtils::GetUnicode(CStringA(str
), CP_UTF8
);
471 temp
+= str
+ _T("\n");
473 ::SendMessage(m_hWnd
, WM_USER_FILLCHANGELOG
, 0, reinterpret_cast<LPARAM
>((LPCTSTR
)temp
));
476 ::SendMessage(m_hWnd
, WM_USER_FILLCHANGELOG
, 0, reinterpret_cast<LPARAM
>(_T("Could not load changelog.")));
479 void CCheckForUpdatesDlg::OnTimer(UINT_PTR nIDEvent
)
483 if (m_bThreadRunning
== FALSE
)
488 ShowWindow(SW_SHOWNORMAL
);
496 CStandAloneDialog::OnTimer(nIDEvent
);
499 void CCheckForUpdatesDlg::OnWindowPosChanging(WINDOWPOS
* lpwndpos
)
501 CStandAloneDialog::OnWindowPosChanging(lpwndpos
);
502 if (m_bVisible
== FALSE
)
503 lpwndpos
->flags
&= ~SWP_SHOWWINDOW
;
506 BOOL
CCheckForUpdatesDlg::OnSetCursor(CWnd
* pWnd
, UINT nHitTest
, UINT message
)
508 HCURSOR hCur
= LoadCursor(NULL
, MAKEINTRESOURCE(IDC_ARROW
));
510 return CStandAloneDialogTmpl
<CDialog
>::OnSetCursor(pWnd
, nHitTest
, message
);
513 void CCheckForUpdatesDlg::OnBnClickedButtonUpdate()
516 m_ctrlUpdate
.GetWindowText(title
);
517 if (m_pDownloadThread
== NULL
&& title
== CString(MAKEINTRESOURCE(IDS_PROC_DOWNLOAD
)))
519 bool isOneSelected
= false;
520 for (int i
= 0; i
< (int)m_ctrlFiles
.GetItemCount(); ++i
)
522 if (m_ctrlFiles
.GetCheck(i
))
524 isOneSelected
= true;
531 m_eventStop
.ResetEvent();
533 m_pDownloadThread
= ::AfxBeginThread(DownloadThreadEntry
, this, THREAD_PRIORITY_NORMAL
, 0, CREATE_SUSPENDED
);
534 if (m_pDownloadThread
!= NULL
)
536 m_pDownloadThread
->m_bAutoDelete
= FALSE
;
537 m_pDownloadThread
->ResumeThread();
539 GetDlgItem(IDC_BUTTON_UPDATE
)->SetWindowText(CString(MAKEINTRESOURCE(IDS_ABORTBUTTON
)));
543 CMessageBox::Show(NULL
, IDS_ERR_THREADSTARTFAILED
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
546 else if (title
== CString(MAKEINTRESOURCE(IDS_ABORTBUTTON
)))
549 m_eventStop
.SetEvent();
553 CString folder
= GetDownloadsDirectory();
554 if (m_ctrlUpdate
.GetCurrentEntry() == 0)
556 for (int i
= 0; i
< (int)m_ctrlFiles
.GetItemCount(); ++i
)
558 CUpdateListCtrl::Entry
*data
= (CUpdateListCtrl::Entry
*)m_ctrlFiles
.GetItemData(i
);
559 if (m_ctrlFiles
.GetCheck(i
) == TRUE
)
560 ShellExecute(NULL
, _T("open"), folder
+ data
->m_filename
, NULL
, NULL
, SW_SHOWNORMAL
);
562 CStandAloneDialog::OnOK();
564 else if (m_ctrlUpdate
.GetCurrentEntry() == 1)
566 ShellExecute(NULL
, _T("open"), folder
, NULL
, NULL
, SW_SHOWNORMAL
);
569 m_ctrlUpdate
.SetCurrentEntry(0);
573 UINT
CCheckForUpdatesDlg::DownloadThreadEntry(LPVOID pVoid
)
575 return ((CCheckForUpdatesDlg
*)pVoid
)->DownloadThread();
578 bool CCheckForUpdatesDlg::Download(CString filename
)
580 CString url
= m_sFilesURL
+ filename
;
581 CString destFilename
= GetDownloadsDirectory() + filename
;
582 if (PathFileExists(destFilename
) && PathFileExists(destFilename
+ SIGNATURE_FILE_ENDING
))
584 if (VerifyIntegrity(destFilename
, destFilename
+ SIGNATURE_FILE_ENDING
, m_updateDownloader
) == 0)
588 DeleteFile(destFilename
);
589 DeleteFile(destFilename
+ SIGNATURE_FILE_ENDING
);
590 DeleteUrlCacheEntry(url
);
591 DeleteUrlCacheEntry(url
+ SIGNATURE_FILE_ENDING
);
595 m_progress
.SetRange32(0, 1);
596 m_progress
.SetPos(0);
597 m_progress
.ShowWindow(SW_SHOW
);
600 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_NORMAL
);
601 m_pTaskbarList
->SetProgressValue(m_hWnd
, 0, 1);
604 CString tempfile
= CTempFiles::Instance().GetTempFilePath(true).GetWinPathString();
605 CString signatureTempfile
= CTempFiles::Instance().GetTempFilePath(true).GetWinPathString();
606 BOOL ret
= m_updateDownloader
->DownloadFile(url
, tempfile
, true);
609 ret
= m_updateDownloader
->DownloadFile(url
+ SIGNATURE_FILE_ENDING
, signatureTempfile
, true);
610 m_progress
.SetPos(m_progress
.GetPos() + 1);
613 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_NORMAL
);
614 int minValue
, maxValue
;
615 m_progress
.GetRange(minValue
, maxValue
);
616 m_pTaskbarList
->SetProgressValue(m_hWnd
, m_progress
.GetPos(), maxValue
);
621 if (VerifyIntegrity(tempfile
, signatureTempfile
, m_updateDownloader
) == 0)
623 DeleteFile(destFilename
);
624 DeleteFile(destFilename
+ SIGNATURE_FILE_ENDING
);
625 MoveFile(tempfile
, destFilename
);
626 MoveFile(signatureTempfile
, destFilename
+ SIGNATURE_FILE_ENDING
);
629 DeleteUrlCacheEntry(url
);
630 DeleteUrlCacheEntry(url
+ SIGNATURE_FILE_ENDING
);
635 UINT
CCheckForUpdatesDlg::DownloadThread()
637 m_ctrlFiles
.SetExtendedStyle(m_ctrlFiles
.GetExtendedStyle() & ~LVS_EX_CHECKBOXES
);
640 for (int i
= 0; i
< (int)m_ctrlFiles
.GetItemCount(); ++i
)
642 m_ctrlFiles
.EnsureVisible(i
, FALSE
);
644 m_ctrlFiles
.GetItemRect(i
, &rect
, LVIR_BOUNDS
);
645 CUpdateListCtrl::Entry
*data
= (CUpdateListCtrl::Entry
*)m_ctrlFiles
.GetItemData(i
);
646 if (m_ctrlFiles
.GetCheck(i
) == TRUE
)
648 data
->m_status
= CUpdateListCtrl::STATUS_DOWNLOADING
;
649 m_ctrlFiles
.InvalidateRect(rect
);
650 if (Download(data
->m_filename
))
651 data
->m_status
= CUpdateListCtrl::STATUS_SUCCESS
;
654 data
->m_status
= CUpdateListCtrl::STATUS_FAIL
;
659 data
->m_status
= CUpdateListCtrl::STATUS_IGNORE
;
660 m_ctrlFiles
.InvalidateRect(rect
);
663 ::PostMessage(GetSafeHwnd(), WM_USER_ENDDOWNLOAD
, 0, 0);
668 LRESULT
CCheckForUpdatesDlg::OnEndDownload(WPARAM
, LPARAM
)
670 ASSERT(m_pDownloadThread
!= NULL
);
672 // wait until the thread terminates
674 if (::GetExitCodeThread(m_pDownloadThread
->m_hThread
, &dwExitCode
) && dwExitCode
== STILL_ACTIVE
)
675 ::WaitForSingleObject(m_pDownloadThread
->m_hThread
, INFINITE
);
677 // make sure we always have the correct exit code
678 ::GetExitCodeThread(m_pDownloadThread
->m_hThread
, &dwExitCode
);
680 delete m_pDownloadThread
;
681 m_pDownloadThread
= NULL
;
683 m_progress
.ShowWindow(SW_HIDE
);
685 if (dwExitCode
== TRUE
)
687 m_ctrlUpdate
.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_INSTALL
)));
688 m_ctrlUpdate
.AddEntry(CString(MAKEINTRESOURCE(IDS_CHECKUPDATE_DESTFOLDER
)));
689 m_ctrlUpdate
.Invalidate();
691 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_NOPROGRESS
);
695 m_ctrlUpdate
.SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_DOWNLOAD
)));
697 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_ERROR
);
698 CMessageBox::Show(NULL
, IDS_ERR_FAILEDUPDATEDOWNLOAD
, IDS_APPNAME
, MB_ICONERROR
);
700 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_NOPROGRESS
);
706 LRESULT
CCheckForUpdatesDlg::OnFillChangelog(WPARAM
, LPARAM lParam
)
708 ASSERT(lParam
!= NULL
);
710 LPCTSTR changelog
= reinterpret_cast<LPCTSTR
>(lParam
);
711 m_cLogMessage
.Call(SCI_SETREADONLY
, FALSE
);
712 m_cLogMessage
.SetText(changelog
);
713 m_cLogMessage
.Call(SCI_SETREADONLY
, TRUE
);
714 m_cLogMessage
.Call(SCI_GOTOPOS
, 0);
719 CString
CCheckForUpdatesDlg::GetDownloadsDirectory()
723 if (SysInfo::Instance().IsVistaOrLater())
725 CAutoLibrary hShell
= AtlLoadSystemLibraryUsingFullPath(_T("shell32.dll"));
728 typedef HRESULT STDAPICALLTYPE
SHGetKnownFolderPathFN(__in REFKNOWNFOLDERID rfid
, __in DWORD dwFlags
, __in_opt HANDLE hToken
, __deref_out PWSTR
*ppszPath
);
729 SHGetKnownFolderPathFN
*pfnSHGetKnownFolderPath
= (SHGetKnownFolderPathFN
*)GetProcAddress(hShell
, "SHGetKnownFolderPath");
730 if (pfnSHGetKnownFolderPath
)
732 wchar_t * wcharPtr
= 0;
733 HRESULT hr
= pfnSHGetKnownFolderPath(FOLDERID_Downloads
, KF_FLAG_CREATE
, NULL
, &wcharPtr
);
737 CoTaskMemFree(static_cast<void*>(wcharPtr
));
738 return folder
.TrimRight(_T("\\")) + _T("\\");
744 TCHAR szPath
[MAX_PATH
] = {0};
745 if (SUCCEEDED(SHGetFolderPath(NULL
, CSIDL_PERSONAL
| CSIDL_FLAG_CREATE
, NULL
, SHGFP_TYPE_CURRENT
, szPath
)))
747 CString downloads
= folder
.TrimRight(_T("\\")) + _T("\\Downloads\\");
748 if ((PathFileExists(downloads
) && PathIsDirectory(downloads
)) || (!PathFileExists(downloads
) && CreateDirectory(downloads
, NULL
)))
754 LRESULT
CCheckForUpdatesDlg::OnDisplayStatus(WPARAM
, LPARAM lParam
)
756 const CUpdateDownloader::DOWNLOADSTATUS
*const pDownloadStatus
= reinterpret_cast<CUpdateDownloader::DOWNLOADSTATUS
*>(lParam
);
757 if (pDownloadStatus
!= NULL
)
759 ASSERT(::AfxIsValidAddress(pDownloadStatus
, sizeof(CUpdateDownloader::DOWNLOADSTATUS
)));
761 m_progress
.SetRange32(0, pDownloadStatus
->ulProgressMax
);
762 m_progress
.SetPos(pDownloadStatus
->ulProgress
);
765 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_NORMAL
);
766 m_pTaskbarList
->SetProgressValue(m_hWnd
, pDownloadStatus
->ulProgress
, pDownloadStatus
->ulProgressMax
);
773 LRESULT
CCheckForUpdatesDlg::OnTaskbarBtnCreated(WPARAM
/*wParam*/, LPARAM
/*lParam*/)
775 m_pTaskbarList
.Release();
776 m_pTaskbarList
.CoCreateInstance(CLSID_TaskbarList
);