Integrated changelog
[TortoiseGit.git] / src / TortoiseProc / CheckForUpdatesDlg.cpp
blob792689bbc4f2f58b6818bd3643474296a06a23bc
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008 - TortoiseSVN
4 // Copyright (C) 2008-2012 - 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.
20 #include "stdafx.h"
21 #include "TortoiseProc.h"
22 #include "LoglistCommonResource.h"
23 #include "..\version.h"
24 #include "MessageBox.h"
25 #include ".\checkforupdatesdlg.h"
26 #include "Registry.h"
27 #include "AppUtils.h"
28 #include "TempFile.h"
29 #include <wintrust.h>
30 #include <Softpub.h>
31 #include "SmartHandle.h"
32 #include "SysInfo.h"
33 #include "PathUtils.h"
34 #include "DirFileEnum.h"
35 #include "ProjectProperties.h"
37 // Link with Wintrust.lib
38 #pragma comment (lib, "wintrust")
40 #define WM_USER_DISPLAYSTATUS (WM_USER + 1)
41 #define WM_USER_ENDDOWNLOAD (WM_USER + 2)
42 #define WM_USER_FILLCHANGELOG (WM_USER + 3)
44 IMPLEMENT_DYNAMIC(CCheckForUpdatesDlg, CStandAloneDialog)
45 CCheckForUpdatesDlg::CCheckForUpdatesDlg(CWnd* pParent /*=NULL*/)
46 : CStandAloneDialog(CCheckForUpdatesDlg::IDD, pParent)
47 , m_bShowInfo(FALSE)
48 , m_bVisible(FALSE)
49 , m_pDownloadThread(NULL)
51 m_sUpdateDownloadLink = _T("http://code.google.com/p/tortoisegit/wiki/Download?tm=2");
54 CCheckForUpdatesDlg::~CCheckForUpdatesDlg()
58 void CCheckForUpdatesDlg::DoDataExchange(CDataExchange* pDX)
60 CStandAloneDialog::DoDataExchange(pDX);
61 DDX_Control(pDX, IDC_LINK, m_link);
62 DDX_Control(pDX, IDC_PROGRESSBAR, m_progress);
63 DDX_Control(pDX, IDC_LIST_DOWNLOADS, m_ctrlFiles);
64 DDX_Control(pDX, IDC_BUTTON_UPDATE, m_ctrlUpdate);
65 DDX_Control(pDX, IDC_LOGMESSAGE, m_cLogMessage);
68 BEGIN_MESSAGE_MAP(CCheckForUpdatesDlg, CStandAloneDialog)
69 ON_STN_CLICKED(IDC_CHECKRESULT, OnStnClickedCheckresult)
70 ON_WM_TIMER()
71 ON_WM_WINDOWPOSCHANGING()
72 ON_WM_SETCURSOR()
73 ON_BN_CLICKED(IDC_BUTTON_UPDATE, OnBnClickedButtonUpdate)
74 ON_MESSAGE(WM_USER_DISPLAYSTATUS, OnDisplayStatus)
75 ON_MESSAGE(WM_USER_ENDDOWNLOAD, OnEndDownload)
76 ON_MESSAGE(WM_USER_FILLCHANGELOG, OnFillChangelog)
77 END_MESSAGE_MAP()
79 BOOL CCheckForUpdatesDlg::OnInitDialog()
81 CStandAloneDialog::OnInitDialog();
82 CAppUtils::MarkWindowAsUnpinnable(m_hWnd);
84 CString temp;
85 temp.Format(IDS_CHECKNEWER_YOURVERSION, TGIT_VERMAJOR, TGIT_VERMINOR, TGIT_VERMICRO, TGIT_VERBUILD);
86 SetDlgItemText(IDC_YOURVERSION, temp);
88 DialogEnableWindow(IDOK, FALSE);
90 // hide download controls
91 m_ctrlFiles.ShowWindow(SW_HIDE);
92 GetDlgItem(IDC_GROUP_DOWNLOADS)->ShowWindow(SW_HIDE);
93 RECT rectWindow, rectGroupDownloads, rectOKButton;
94 GetWindowRect(&rectWindow);
95 GetDlgItem(IDC_GROUP_DOWNLOADS)->GetWindowRect(&rectGroupDownloads);
96 GetDlgItem(IDOK)->GetWindowRect(&rectOKButton);
97 LONG bottomDistance = rectWindow.bottom - rectOKButton.bottom;
98 OffsetRect(&rectOKButton, 0, rectGroupDownloads.top - rectOKButton.top);
99 rectWindow.bottom = rectOKButton.bottom + bottomDistance;
100 MoveWindow(&rectWindow);
101 ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT)&rectOKButton, 2);
102 GetDlgItem(IDOK)->MoveWindow(&rectOKButton);
104 temp.LoadString(IDS_STATUSLIST_COLFILE);
105 m_ctrlFiles.InsertColumn(0, temp, 0, -1);
106 m_ctrlFiles.SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
107 m_ctrlFiles.SetExtendedStyle(LVS_EX_DOUBLEBUFFER | LVS_EX_CHECKBOXES);
109 ProjectProperties pp;
110 pp.SetCheckRe(_T("[Ii]ssues?:?(\\s*(,|and)?\\s*#?\\d+)+"));
111 pp.SetBugIDRe(_T("(\\d+)"));
112 pp.sUrl = _T("http://code.google.com/p/tortoisegit/issues/detail?id=%BUGID%");
113 m_cLogMessage.Init(pp);
114 m_cLogMessage.SetFont((CString)CRegString(_T("Software\\TortoiseGit\\LogFontName"), _T("Courier New")), (DWORD)CRegDWORD(_T("Software\\TortoiseGit\\LogFontSize"), 8));
115 m_cLogMessage.Call(SCI_SETREADONLY, TRUE);
117 if (AfxBeginThread(CheckThreadEntry, this)==NULL)
119 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
122 SetTimer(100, 1000, NULL);
123 return TRUE;
126 void CCheckForUpdatesDlg::OnOK()
128 if (m_bThreadRunning || m_pDownloadThread != NULL)
129 return; // Don't exit while downloading
131 CStandAloneDialog::OnOK();
134 void CCheckForUpdatesDlg::OnCancel()
136 if (m_bThreadRunning || m_pDownloadThread != NULL)
137 return; // Don't exit while downloading
138 CStandAloneDialog::OnCancel();
141 UINT CCheckForUpdatesDlg::CheckThreadEntry(LPVOID pVoid)
143 return ((CCheckForUpdatesDlg*)pVoid)->CheckThread();
146 UINT CCheckForUpdatesDlg::CheckThread()
148 m_bThreadRunning = TRUE;
150 CString temp;
151 CString tempfile = CTempFiles::Instance().GetTempFilePath(true).GetWinPathString();
153 CRegString checkurluser = CRegString(_T("Software\\TortoiseGit\\UpdateCheckURL"), _T(""));
154 CRegString checkurlmachine = CRegString(_T("Software\\TortoiseGit\\UpdateCheckURL"), _T(""), FALSE, HKEY_LOCAL_MACHINE);
155 CString sCheckURL = checkurluser;
156 if (sCheckURL.IsEmpty())
158 sCheckURL = checkurlmachine;
159 if (sCheckURL.IsEmpty())
160 sCheckURL = _T("http://version.tortoisegit.googlecode.com/git/version.txt");
162 CoInitialize(NULL);
163 HRESULT res = URLDownloadToFile(NULL, sCheckURL, tempfile, 0, NULL);
164 if (res == S_OK)
168 CStdioFile file(tempfile, CFile::modeRead | CFile::shareDenyWrite);
169 CString ver;
170 unsigned int major,minor,micro,build;
171 major=minor=micro=build=0;
172 unsigned __int64 version=0;
174 if (file.ReadString(ver))
176 CString vertemp = ver;
177 major = _ttoi(vertemp);
178 vertemp = vertemp.Mid(vertemp.Find('.')+1);
179 minor = _ttoi(vertemp);
180 vertemp = vertemp.Mid(vertemp.Find('.')+1);
181 micro = _ttoi(vertemp);
182 vertemp = vertemp.Mid(vertemp.Find('.')+1);
183 build = _ttoi(vertemp);
184 version = major;
185 version <<= 16;
186 version += minor;
187 version <<= 16;
188 version += micro;
189 version <<= 16;
190 version += build;
194 BOOL bNewer = FALSE;
195 if (major > TGIT_VERMAJOR)
196 bNewer = TRUE;
197 else if ((minor > TGIT_VERMINOR)&&(major == TGIT_VERMAJOR))
198 bNewer = TRUE;
199 else if ((micro > TGIT_VERMICRO)&&(minor == TGIT_VERMINOR)&&(major == TGIT_VERMAJOR))
200 bNewer = TRUE;
201 else if ((build > TGIT_VERBUILD)&&(micro == TGIT_VERMICRO)&&(minor == TGIT_VERMINOR)&&(major == TGIT_VERMAJOR))
202 bNewer = TRUE;
204 if (version != 0)
206 ver.Format(_T("%d.%d.%d.%d"),major,minor,micro,build);
207 temp.Format(IDS_CHECKNEWER_CURRENTVERSION, (LPCTSTR)ver);
208 SetDlgItemText(IDC_CURRENTVERSION, temp);
209 temp.Format(_T("%d.%d.%d.%d"), TGIT_VERMAJOR, TGIT_VERMINOR, TGIT_VERMICRO, TGIT_VERBUILD);
212 if (version == 0)
214 temp.LoadString(IDS_CHECKNEWER_NETERROR);
215 SetDlgItemText(IDC_CHECKRESULT, temp);
217 else if (bNewer)
219 if(file.ReadString(temp) && !temp.IsEmpty())
220 { // Read the next line, it could contain a message for the user
221 CString tempLink;
222 if(file.ReadString(tempLink) && !tempLink.IsEmpty())
223 { // Read another line to find out the download link-URL, if any
224 m_sUpdateDownloadLink = tempLink;
227 else
229 temp.LoadString(IDS_CHECKNEWER_NEWERVERSIONAVAILABLE);
230 CString tempLink;
231 file.ReadString(tempLink);
233 SetDlgItemText(IDC_CHECKRESULT, temp);
234 m_bShowInfo = TRUE;
236 FillChangelog(file);
237 FillDownloads(file, ver);
239 // Show download controls
240 RECT rectWindow, rectProgress, rectGroupDownloads, rectOKButton;
241 GetWindowRect(&rectWindow);
242 m_progress.GetWindowRect(&rectProgress);
243 GetDlgItem(IDC_GROUP_DOWNLOADS)->GetWindowRect(&rectGroupDownloads);
244 GetDlgItem(IDOK)->GetWindowRect(&rectOKButton);
245 LONG bottomDistance = rectWindow.bottom - rectOKButton.bottom;
246 OffsetRect(&rectOKButton, 0, (rectGroupDownloads.bottom + (rectGroupDownloads.bottom - rectProgress.bottom)) - rectOKButton.top);
247 rectWindow.bottom = rectOKButton.bottom + bottomDistance;
248 MoveWindow(&rectWindow);
249 ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT)&rectOKButton, 2);
250 GetDlgItem(IDOK)->MoveWindow(&rectOKButton);
251 m_ctrlFiles.ShowWindow(SW_SHOW);
252 GetDlgItem(IDC_GROUP_DOWNLOADS)->ShowWindow(SW_SHOW);
253 CenterWindow();
255 else
257 temp.LoadString(IDS_CHECKNEWER_YOURUPTODATE);
258 SetDlgItemText(IDC_CHECKRESULT, temp);
259 file.ReadString(temp);
260 file.ReadString(temp);
261 FillChangelog(file);
265 catch (CException * e)
267 e->Delete();
268 temp.LoadString(IDS_CHECKNEWER_NETERROR);
269 SetDlgItemText(IDC_CHECKRESULT, temp);
272 else
274 // Try to cache web page;
276 temp.LoadString(IDS_CHECKNEWER_NETERROR);
277 SetDlgItemText(IDC_CHECKRESULT, temp);
279 if (!m_sUpdateDownloadLink.IsEmpty())
281 m_link.ShowWindow(SW_SHOW);
282 m_link.SetURL(m_sUpdateDownloadLink);
285 DeleteFile(tempfile);
286 m_bThreadRunning = FALSE;
287 DialogEnableWindow(IDOK, TRUE);
288 return 0;
291 void CCheckForUpdatesDlg::FillDownloads(CStdioFile &file, CString version)
293 #if WIN64
294 const CString x86x64 = _T("64");
295 #else
296 const CString x86x64 = _T("32");
297 #endif
299 if (!file.ReadString(m_sFilesURL) || m_sFilesURL.IsEmpty())
300 m_sFilesURL = _T("http://tortoisegit.googlecode.com/files/");
302 m_ctrlFiles.InsertItem(0, _T("TortoiseGit"));
303 CString filename;
304 filename.Format(_T("TortoiseGit-%s-%sbit.msi"), version, x86x64);
305 m_fileNames.push_back(filename);
306 m_ctrlFiles.SetCheck(0 , TRUE);
308 std::vector<DWORD> m_installedLangs;
310 // set up the language selecting combobox
311 CString path = CPathUtils::GetAppParentDirectory();
312 path = path + _T("Languages\\");
313 CSimpleFileFind finder(path, _T("*.dll"));
314 while (finder.FindNextFileNoDirectories())
316 CString file = finder.GetFilePath();
317 CString filename = finder.GetFileName();
318 if (filename.Left(12).CompareNoCase(_T("TortoiseProc")) == 0)
320 CString sVer = _T(STRPRODUCTVER);
321 sVer = sVer.Left(sVer.ReverseFind(','));
322 CString sFileVer = CPathUtils::GetVersionFromFile(file);
323 sFileVer = sFileVer.Left(sFileVer.ReverseFind(','));
324 CString sLoc = filename.Mid(12);
325 sLoc = sLoc.Left(sLoc.GetLength() - 4); // cut off ".dll"
326 if ((sLoc.Left(2) == L"32") && (sLoc.GetLength() > 5))
327 continue;
328 DWORD loc = _tstoi(filename.Mid(12));
329 m_installedLangs.push_back(loc);
334 CString langs;
335 while (file.ReadString(langs) && !langs.IsEmpty())
337 CString sLang = _T("TortoiseGit Language Pack ");
339 DWORD loc = _tstoi(langs.Mid(0, 4));
340 TCHAR buf[MAX_PATH];
341 GetLocaleInfo(loc, LOCALE_SNATIVELANGNAME, buf, _countof(buf));
342 sLang += buf;
343 GetLocaleInfo(loc, LOCALE_SNATIVECTRYNAME, buf, _countof(buf));
344 if (buf[0])
346 sLang += _T(" (");
347 sLang += buf;
348 sLang += _T(")");
351 int pos = m_ctrlFiles.InsertItem(m_ctrlFiles.GetItemCount(), sLang);
353 CString filename;
354 filename.Format(_T("TortoiseGit-LanguagePack-%s-%sbit-%s.msi"), version, x86x64, langs.Mid(5));
355 m_fileNames.push_back(filename);
357 if (std::find(m_installedLangs.begin(), m_installedLangs.end(), loc) != m_installedLangs.end())
358 m_ctrlFiles.SetCheck(pos , TRUE);
360 DialogEnableWindow(IDC_BUTTON_UPDATE, TRUE);
363 void CCheckForUpdatesDlg::FillChangelog(CStdioFile &file)
365 CString sChangelogURL;
366 if (!file.ReadString(sChangelogURL) || sChangelogURL.IsEmpty())
367 sChangelogURL = _T("http://tortoisegit.googlecode.com/git/src/Changelog.txt");
369 CString tempchangelogfile = CTempFiles::Instance().GetTempFilePath(true).GetWinPathString();
370 HRESULT res = URLDownloadToFile(NULL, sChangelogURL, tempchangelogfile, 0, NULL);
371 if (SUCCEEDED(res))
373 CString temp;
374 CStdioFile file(tempchangelogfile, CFile::modeRead|CFile::typeText);
375 CString str;
376 while (file.ReadString(str))
378 temp += str + _T("\n");
380 ::SendMessage(m_hWnd, WM_USER_FILLCHANGELOG, 0, reinterpret_cast<LPARAM>(temp.GetBuffer()));
382 else
383 ::SendMessage(m_hWnd, WM_USER_FILLCHANGELOG, 0, reinterpret_cast<LPARAM>(_T("Could not load changelog.")));
386 void CCheckForUpdatesDlg::OnStnClickedCheckresult()
388 // user clicked on the label, start the browser with our web page
389 HINSTANCE result = ShellExecute(NULL, _T("opennew"), m_sUpdateDownloadLink, NULL,NULL, SW_SHOWNORMAL);
390 if ((UINT)result <= HINSTANCE_ERROR)
392 result = ShellExecute(NULL, _T("open"), m_sUpdateDownloadLink, NULL,NULL, SW_SHOWNORMAL);
396 void CCheckForUpdatesDlg::OnTimer(UINT_PTR nIDEvent)
398 if (nIDEvent == 100)
400 if (m_bThreadRunning == FALSE)
402 if (m_bShowInfo)
404 m_bVisible = TRUE;
405 ShowWindow(SW_SHOWNORMAL);
407 else
409 EndDialog(0);
413 CStandAloneDialog::OnTimer(nIDEvent);
416 void CCheckForUpdatesDlg::OnWindowPosChanging(WINDOWPOS* lpwndpos)
418 CStandAloneDialog::OnWindowPosChanging(lpwndpos);
419 if (m_bVisible == FALSE)
420 lpwndpos->flags &= ~SWP_SHOWWINDOW;
423 BOOL CCheckForUpdatesDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
425 if ((!m_sUpdateDownloadLink.IsEmpty())&&(pWnd)&&(pWnd == GetDlgItem(IDC_CHECKRESULT)))
427 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_HAND));
428 SetCursor(hCur);
429 return TRUE;
432 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
433 SetCursor(hCur);
434 return CStandAloneDialogTmpl<CDialog>::OnSetCursor(pWnd, nHitTest, message);
437 void CCheckForUpdatesDlg::OnBnClickedButtonUpdate()
439 CString title;
440 m_ctrlUpdate.GetWindowText(title);
441 if (m_pDownloadThread == NULL && title == CString(MAKEINTRESOURCE(IDS_PROC_DOWNLOAD)))
443 bool isOneSelected = false;
444 for (int i = 0; i < (int)m_ctrlFiles.GetItemCount(); i++)
446 if (m_ctrlFiles.GetCheck(i))
448 isOneSelected = true;
449 break;
452 if (!isOneSelected)
453 return;
455 m_eventStop.ResetEvent();
457 m_pDownloadThread = ::AfxBeginThread(DownloadThreadEntry, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
458 if (m_pDownloadThread != NULL)
460 m_pDownloadThread->m_bAutoDelete = FALSE;
461 m_pDownloadThread->ResumeThread();
463 GetDlgItem(IDC_BUTTON_UPDATE)->SetWindowText(CString(MAKEINTRESOURCE(IDS_ABORTBUTTON)));
465 else
467 CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
470 else if (title == CString(MAKEINTRESOURCE(IDS_ABORTBUTTON)))
472 // Abort
473 m_eventStop.SetEvent();
475 else
477 CString folder = GetDownloadsDirectory();
478 if (m_ctrlUpdate.GetCurrentEntry() == 0)
480 for (int i = 0; i < (int)m_ctrlFiles.GetItemCount(); i++)
482 if (m_ctrlFiles.GetCheck(i) == TRUE)
483 ShellExecute(NULL, _T("open"), folder + m_fileNames[i], NULL, NULL, SW_SHOWNORMAL);
485 ExitProcess(0);
487 else if (m_ctrlUpdate.GetCurrentEntry() == 1)
489 ShellExecute(NULL, _T("open"), folder, NULL, NULL, SW_SHOWNORMAL);
492 m_ctrlUpdate.SetCurrentEntry(0);
496 UINT CCheckForUpdatesDlg::DownloadThreadEntry(LPVOID pVoid)
498 return ((CCheckForUpdatesDlg*)pVoid)->DownloadThread();
501 bool CCheckForUpdatesDlg::Download(CString filename)
503 CString destFilename = GetDownloadsDirectory() + filename;
504 if (PathFileExists(destFilename))
506 if (VerifySignature(destFilename))
507 return true;
508 else
509 DeleteFile(destFilename);
512 CBSCallbackImpl bsc(this->GetSafeHwnd(), m_eventStop);
514 CString url = m_sFilesURL + filename;
516 m_progress.SetRange32(0, 1);
517 m_progress.SetPos(0);
518 m_progress.ShowWindow(SW_SHOW);
520 CString tempfile = CTempFiles::Instance().GetTempFilePath(true).GetWinPathString();
521 HRESULT res = URLDownloadToFile(NULL, url, tempfile, 0, &bsc);
522 if (res == S_OK)
524 if (VerifySignature(tempfile))
526 if (PathFileExists(destFilename))
527 DeleteFile(destFilename);
528 MoveFile(tempfile, destFilename);
529 return true;
532 return false;
535 UINT CCheckForUpdatesDlg::DownloadThread()
537 m_ctrlFiles.SetExtendedStyle(m_ctrlFiles.GetExtendedStyle() & ~LVS_EX_CHECKBOXES);
539 BOOL result = TRUE;
540 for (int i = 0; i < (int)m_ctrlFiles.GetItemCount(); i++)
542 m_ctrlFiles.EnsureVisible(i, FALSE);
543 CRect rect;
544 m_ctrlFiles.GetItemRect(i, &rect, LVIR_BOUNDS);
545 if (m_ctrlFiles.GetCheck(i) == TRUE)
547 m_ctrlFiles.SetItemData(i, CUpdateListCtrl::STATUS_DOWNLOADING);
548 m_ctrlFiles.InvalidateRect(rect);
549 if (Download(m_fileNames[i]))
550 m_ctrlFiles.SetItemData(i, CUpdateListCtrl::STATUS_SUCCESS);
551 else
553 m_ctrlFiles.SetItemData(i, CUpdateListCtrl::STATUS_FAIL);
554 result = FALSE;
557 else
558 m_ctrlFiles.SetItemData(i, CUpdateListCtrl::STATUS_IGNORE);
559 m_ctrlFiles.InvalidateRect(rect);
562 ::PostMessage(GetSafeHwnd(), WM_USER_ENDDOWNLOAD, 0, 0);
564 return result;
567 LRESULT CCheckForUpdatesDlg::OnEndDownload(WPARAM, LPARAM)
569 ASSERT(m_pDownloadThread != NULL);
571 // wait until the thread terminates
572 DWORD dwExitCode;
573 if (::GetExitCodeThread(m_pDownloadThread->m_hThread, &dwExitCode) && dwExitCode == STILL_ACTIVE)
574 ::WaitForSingleObject(m_pDownloadThread->m_hThread, INFINITE);
576 // make sure we always have the correct exit code
577 ::GetExitCodeThread(m_pDownloadThread->m_hThread, &dwExitCode);
579 delete m_pDownloadThread;
580 m_pDownloadThread = NULL;
582 m_progress.ShowWindow(SW_HIDE);
584 if (dwExitCode == TRUE)
586 m_ctrlUpdate.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_INSTALL)));
587 m_ctrlUpdate.AddEntry(CString(MAKEINTRESOURCE(IDS_CHECKUPDATE_DESTFOLDER)));
588 m_ctrlUpdate.Invalidate();
590 else
592 m_ctrlUpdate.SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_DOWNLOAD)));
593 CMessageBox::Show(NULL, IDS_ERR_FAILEDUPDATEDOWNLOAD, IDS_APPNAME, MB_ICONERROR);
596 return 0;
599 LRESULT CCheckForUpdatesDlg::OnFillChangelog(WPARAM, LPARAM lParam)
601 ASSERT(lParam != NULL);
603 TCHAR * changelog = reinterpret_cast<TCHAR *>(lParam);
604 m_cLogMessage.Call(SCI_SETREADONLY, FALSE);
605 m_cLogMessage.SetText(changelog);
606 m_cLogMessage.Call(SCI_SETREADONLY, TRUE);
607 m_cLogMessage.Call(SCI_GOTOPOS, 0);
609 return 0;
612 CString CCheckForUpdatesDlg::GetDownloadsDirectory()
614 CString folder;
616 if (SysInfo::Instance().IsVistaOrLater())
618 CAutoLibrary hShell = ::LoadLibrary(_T("shell32.dll"));
619 if (hShell)
621 typedef HRESULT STDAPICALLTYPE SHGetKnownFolderPathFN(__in REFKNOWNFOLDERID rfid, __in DWORD dwFlags, __in_opt HANDLE hToken, __deref_out PWSTR *ppszPath);
622 SHGetKnownFolderPathFN *pfnSHGetKnownFolderPath = (SHGetKnownFolderPathFN*)GetProcAddress(hShell, "SHGetKnownFolderPath");
623 if (pfnSHGetKnownFolderPath)
625 wchar_t * wcharPtr = 0;
626 HRESULT hr = pfnSHGetKnownFolderPath(FOLDERID_Downloads, KF_FLAG_CREATE, NULL, &wcharPtr);
627 if (SUCCEEDED(hr))
629 folder = wcharPtr;
630 CoTaskMemFree(static_cast<void*>(wcharPtr));
631 return folder.TrimRight(_T("\\")) + _T("\\");
637 TCHAR szPath[MAX_PATH];
638 if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, szPath)))
639 folder = szPath;
640 CString downloads = folder.TrimRight(_T("\\")) + _T("\\Downloads\\");
641 if ((PathFileExists(downloads) && PathIsDirectory(downloads)) || (!PathFileExists(downloads) && CreateDirectory(downloads, NULL)))
642 return downloads;
644 return folder;
647 LRESULT CCheckForUpdatesDlg::OnDisplayStatus(WPARAM, LPARAM lParam)
649 const DOWNLOADSTATUS *const pDownloadStatus = reinterpret_cast<DOWNLOADSTATUS *>(lParam);
650 if (pDownloadStatus != NULL)
652 ASSERT(::AfxIsValidAddress(pDownloadStatus, sizeof(DOWNLOADSTATUS)));
654 m_progress.SetRange32(0, pDownloadStatus->ulProgressMax);
655 m_progress.SetPos(pDownloadStatus->ulProgress);
658 return 0;
661 CBSCallbackImpl::CBSCallbackImpl(HWND hWnd, HANDLE hEventStop)
663 m_hWnd = hWnd;
664 m_hEventStop = hEventStop;
665 m_ulObjRefCount = 1;
668 // IUnknown
669 STDMETHODIMP CBSCallbackImpl::QueryInterface(REFIID riid, void **ppvObject)
671 *ppvObject = NULL;
673 // IUnknown
674 if (::IsEqualIID(riid, __uuidof(IUnknown)))
675 *ppvObject = this;
677 // IBindStatusCallback
678 else if (::IsEqualIID(riid, __uuidof(IBindStatusCallback)))
679 *ppvObject = static_cast<IBindStatusCallback *>(this);
681 if (*ppvObject)
683 (*reinterpret_cast<LPUNKNOWN *>(ppvObject))->AddRef();
684 return S_OK;
687 return E_NOINTERFACE;
690 STDMETHODIMP_(ULONG) CBSCallbackImpl::AddRef()
692 return ++m_ulObjRefCount;
695 STDMETHODIMP_(ULONG) CBSCallbackImpl::Release()
697 return --m_ulObjRefCount;
700 // IBindStatusCallback
701 STDMETHODIMP CBSCallbackImpl::OnStartBinding(DWORD, IBinding *)
703 return S_OK;
706 STDMETHODIMP CBSCallbackImpl::GetPriority(LONG *)
708 return E_NOTIMPL;
710 STDMETHODIMP CBSCallbackImpl::OnLowResource(DWORD)
712 return S_OK;
715 STDMETHODIMP CBSCallbackImpl::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR /* szStatusText */)
717 TRACE(_T("IBindStatusCallback::OnProgress\n"));
718 TRACE(_T("ulProgress: %lu, ulProgressMax: %lu\n"), ulProgress, ulProgressMax);
719 UNREFERENCED_PARAMETER(ulStatusCode);
720 TRACE(_T("ulStatusCode: %lu "), ulStatusCode);
722 if (m_hWnd != NULL)
724 // inform the dialog box to display current status,
725 // don't use PostMessage
726 CCheckForUpdatesDlg::DOWNLOADSTATUS downloadStatus = { ulProgress, ulProgressMax };
727 ::SendMessage(m_hWnd, WM_USER_DISPLAYSTATUS, 0, reinterpret_cast<LPARAM>(&downloadStatus));
730 if (m_hEventStop != NULL && ::WaitForSingleObject(m_hEventStop, 0) == WAIT_OBJECT_0)
732 return E_ABORT; // canceled by the user
735 return S_OK;
738 STDMETHODIMP CBSCallbackImpl::OnStopBinding(HRESULT, LPCWSTR)
740 return S_OK;
743 STDMETHODIMP CBSCallbackImpl::GetBindInfo(DWORD *, BINDINFO *)
745 return S_OK;
748 STDMETHODIMP CBSCallbackImpl::OnDataAvailable(DWORD, DWORD, FORMATETC *, STGMEDIUM *)
750 return S_OK;
753 STDMETHODIMP CBSCallbackImpl::OnObjectAvailable(REFIID, IUnknown *)
755 return S_OK;
758 BOOL CCheckForUpdatesDlg::VerifySignature(CString fileName)
760 WINTRUST_FILE_INFO fileInfo;
761 memset(&fileInfo, 0, sizeof(fileInfo));
762 fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
763 fileInfo.pcwszFilePath = fileName;
765 WINTRUST_DATA data;
766 memset(&data, 0, sizeof(data));
767 data.cbStruct = sizeof(data);
769 data.dwUIChoice = WTD_UI_NONE;
770 data.fdwRevocationChecks = WTD_REVOKE_NONE;
771 data.dwUnionChoice = WTD_CHOICE_FILE;
772 data.pFile = &fileInfo;
774 GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
776 return (WinVerifyTrust(NULL, &policyGUID, &data) == ERROR_SUCCESS);