1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Applications Manager
336870a02S赫杨 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4c2c66affSColin Finck * PURPOSE: Displaying a download dialog
5c2c66affSColin Finck * COPYRIGHT: Copyright 2001 John R. Sheets (for CodeWeavers)
6c2c66affSColin Finck * Copyright 2004 Mike McCormack (for CodeWeavers)
7c2c66affSColin Finck * Copyright 2005 Ge van Geldorp (gvg@reactos.org)
8c2c66affSColin Finck * Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org)
9c2c66affSColin Finck * Copyright 2015 Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
10c2c66affSColin Finck * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
11c2c66affSColin Finck */
12c2c66affSColin Finck
13c2c66affSColin Finck /*
14c2c66affSColin Finck * Based on Wine dlls/shdocvw/shdocvw_main.c
15c2c66affSColin Finck *
16c2c66affSColin Finck * This library is free software; you can redistribute it and/or
17c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
18c2c66affSColin Finck * License as published by the Free Software Foundation; either
19c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
20c2c66affSColin Finck *
21c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
22c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
23c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24c2c66affSColin Finck * Lesser General Public License for more details.
25c2c66affSColin Finck *
26c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
27c2c66affSColin Finck * License along with this library; if not, write to the Free Software
28c2c66affSColin Finck * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29c2c66affSColin Finck */
30c2c66affSColin Finck #include "rapps.h"
31c2c66affSColin Finck
32c2c66affSColin Finck #include <shlobj_undoc.h>
33c2c66affSColin Finck #include <shlguid_undoc.h>
34c2c66affSColin Finck
35c2c66affSColin Finck #include <atlbase.h>
36c2c66affSColin Finck #include <atlcom.h>
37c2c66affSColin Finck #include <atlwin.h>
38c2c66affSColin Finck #include <wininet.h>
39c2c66affSColin Finck #include <shellutils.h>
40c2c66affSColin Finck
41fb1582d3SKyle Katarn #include <debug.h>
42fb1582d3SKyle Katarn
43a6bf77e7SHermès Bélusca-Maïto #include <ui/rosctrls.h>
44c2c66affSColin Finck #include <windowsx.h>
451fbf09f5SKatayama Hirofumi MZ #include <shlwapi_undoc.h>
462ac13afeSHe Yang #include <process.h>
476803490aSGiannis Adamopoulos #undef SubclassWindow
48c2c66affSColin Finck
49c2c66affSColin Finck #include "rosui.h"
50c2c66affSColin Finck #include "dialogs.h"
51c2c66affSColin Finck #include "misc.h"
5257b775efSWhindmar Saksit #include "unattended.h"
53c2c66affSColin Finck
54c2c66affSColin Finck #ifdef USE_CERT_PINNING
557f31cdc1SMark Jansen #define CERT_ISSUER_INFO_OLD "US\r\nLet's Encrypt\r\nR3"
567f31cdc1SMark Jansen #define CERT_ISSUER_INFO_NEW "US\r\nLet's Encrypt\r\nR11"
57bb819f15SAlexander Shaposhnikov #define CERT_SUBJECT_INFO "rapps.reactos.org"
58c2c66affSColin Finck #endif
59c2c66affSColin Finck
60a21d959eSHe Yang enum DownloadType
61a21d959eSHe Yang {
62a21d959eSHe Yang DLTYPE_APPLICATION,
63a21d959eSHe Yang DLTYPE_DBUPDATE,
64a21d959eSHe Yang DLTYPE_DBUPDATE_UNOFFICIAL
65a21d959eSHe Yang };
66a21d959eSHe Yang
67c2c66affSColin Finck enum DownloadStatus
68c2c66affSColin Finck {
69c2c66affSColin Finck DLSTATUS_WAITING = IDS_STATUS_WAITING,
70c2c66affSColin Finck DLSTATUS_DOWNLOADING = IDS_STATUS_DOWNLOADING,
71c2c66affSColin Finck DLSTATUS_WAITING_INSTALL = IDS_STATUS_DOWNLOADED,
72c2c66affSColin Finck DLSTATUS_INSTALLING = IDS_STATUS_INSTALLING,
73c2c66affSColin Finck DLSTATUS_INSTALLED = IDS_STATUS_INSTALLED,
74c2c66affSColin Finck DLSTATUS_FINISHED = IDS_STATUS_FINISHED
75c2c66affSColin Finck };
76c2c66affSColin Finck
7733c2903eSMark Jansen CStringW
LoadStatusString(DownloadStatus StatusParam)7833c2903eSMark Jansen LoadStatusString(DownloadStatus StatusParam)
79c2c66affSColin Finck {
8033c2903eSMark Jansen CStringW szString;
81c2c66affSColin Finck szString.LoadStringW(StatusParam);
82c2c66affSColin Finck return szString;
83c2c66affSColin Finck }
84c2c66affSColin Finck
851fbf09f5SKatayama Hirofumi MZ #define FILENAME_VALID_CHAR ( \
861fbf09f5SKatayama Hirofumi MZ PATH_CHAR_CLASS_LETTER | \
871fbf09f5SKatayama Hirofumi MZ PATH_CHAR_CLASS_DOT | \
881fbf09f5SKatayama Hirofumi MZ PATH_CHAR_CLASS_SEMICOLON | \
891fbf09f5SKatayama Hirofumi MZ PATH_CHAR_CLASS_COMMA | \
901fbf09f5SKatayama Hirofumi MZ PATH_CHAR_CLASS_SPACE | \
911fbf09f5SKatayama Hirofumi MZ PATH_CHAR_CLASS_OTHER_VALID)
921fbf09f5SKatayama Hirofumi MZ
931fbf09f5SKatayama Hirofumi MZ VOID
UrlUnescapeAndMakeFileNameValid(CStringW & str)941fbf09f5SKatayama Hirofumi MZ UrlUnescapeAndMakeFileNameValid(CStringW& str)
951fbf09f5SKatayama Hirofumi MZ {
961fbf09f5SKatayama Hirofumi MZ WCHAR szPath[MAX_PATH];
971fbf09f5SKatayama Hirofumi MZ DWORD cchPath = _countof(szPath);
981fbf09f5SKatayama Hirofumi MZ UrlUnescapeW(const_cast<LPWSTR>((LPCWSTR)str), szPath, &cchPath, 0);
991fbf09f5SKatayama Hirofumi MZ
1001fbf09f5SKatayama Hirofumi MZ for (PWCHAR pch = szPath; *pch; ++pch)
1011fbf09f5SKatayama Hirofumi MZ {
1021fbf09f5SKatayama Hirofumi MZ if (!PathIsValidCharW(*pch, FILENAME_VALID_CHAR))
1031fbf09f5SKatayama Hirofumi MZ *pch = L'_';
1041fbf09f5SKatayama Hirofumi MZ }
1051fbf09f5SKatayama Hirofumi MZ
1061fbf09f5SKatayama Hirofumi MZ str = szPath;
1071fbf09f5SKatayama Hirofumi MZ }
1081fbf09f5SKatayama Hirofumi MZ
109c2c66affSColin Finck struct DownloadInfo
110c2c66affSColin Finck {
DownloadInfoDownloadInfo11157b775efSWhindmar Saksit DownloadInfo() : DLType(DLTYPE_APPLICATION), IType(INSTALLER_UNKNOWN), SizeInBytes(0)
112c2c66affSColin Finck {
113c2c66affSColin Finck }
DownloadInfoDownloadInfo114a9b1e059SJoachim Henze DownloadInfo(const CAppInfo &AppInfo) : DLType(DLTYPE_APPLICATION)
11533c2903eSMark Jansen {
11633c2903eSMark Jansen AppInfo.GetDownloadInfo(szUrl, szSHA1, SizeInBytes);
11733c2903eSMark Jansen szName = AppInfo.szDisplayName;
11857b775efSWhindmar Saksit IType = AppInfo.GetInstallerType();
11957b775efSWhindmar Saksit if (IType == INSTALLER_GENERATE)
12057b775efSWhindmar Saksit {
12157b775efSWhindmar Saksit szPackageName = AppInfo.szIdentifier;
12257b775efSWhindmar Saksit }
12333c2903eSMark Jansen }
124c2c66affSColin Finck
125a21d959eSHe Yang DownloadType DLType;
12657b775efSWhindmar Saksit InstallerType IType;
12733c2903eSMark Jansen CStringW szUrl;
12833c2903eSMark Jansen CStringW szName;
12933c2903eSMark Jansen CStringW szSHA1;
13057b775efSWhindmar Saksit CStringW szPackageName;
1314439b538SMark Jansen ULONG SizeInBytes;
132c2c66affSColin Finck };
133c2c66affSColin Finck
134c2c66affSColin Finck struct DownloadParam
135c2c66affSColin Finck {
DownloadParamDownloadParam13633c2903eSMark Jansen DownloadParam() : Dialog(NULL), AppInfo(), szCaption(NULL)
13733c2903eSMark Jansen {
13833c2903eSMark Jansen }
DownloadParamDownloadParam139c2c66affSColin Finck DownloadParam(HWND dlg, const ATL::CSimpleArray<DownloadInfo> &info, LPCWSTR caption)
140c2c66affSColin Finck : Dialog(dlg), AppInfo(info), szCaption(caption)
141c2c66affSColin Finck {
142c2c66affSColin Finck }
143c2c66affSColin Finck
144c2c66affSColin Finck HWND Dialog;
145c2c66affSColin Finck ATL::CSimpleArray<DownloadInfo> AppInfo;
146c2c66affSColin Finck LPCWSTR szCaption;
147c2c66affSColin Finck };
148c2c66affSColin Finck
14933c2903eSMark Jansen class CDownloaderProgress : public CWindowImpl<CDownloaderProgress, CWindow, CControlWinTraits>
1506803490aSGiannis Adamopoulos {
15133c2903eSMark Jansen CStringW m_szProgressText;
1526803490aSGiannis Adamopoulos
1536803490aSGiannis Adamopoulos public:
CDownloaderProgress()1546803490aSGiannis Adamopoulos CDownloaderProgress()
1556803490aSGiannis Adamopoulos {
1566803490aSGiannis Adamopoulos }
1576803490aSGiannis Adamopoulos
15833c2903eSMark Jansen VOID
SetMarquee(BOOL Enable)15933c2903eSMark Jansen SetMarquee(BOOL Enable)
1606803490aSGiannis Adamopoulos {
1616803490aSGiannis Adamopoulos if (Enable)
1626803490aSGiannis Adamopoulos ModifyStyle(0, PBS_MARQUEE, 0);
1636803490aSGiannis Adamopoulos else
1646803490aSGiannis Adamopoulos ModifyStyle(PBS_MARQUEE, 0, 0);
1656803490aSGiannis Adamopoulos
1666803490aSGiannis Adamopoulos SendMessage(PBM_SETMARQUEE, Enable, 0);
1676803490aSGiannis Adamopoulos }
1686803490aSGiannis Adamopoulos
16933c2903eSMark Jansen VOID
SetProgress(ULONG ulProgress,ULONG ulProgressMax)17033c2903eSMark Jansen SetProgress(ULONG ulProgress, ULONG ulProgressMax)
1716803490aSGiannis Adamopoulos {
1726803490aSGiannis Adamopoulos WCHAR szProgress[100];
1736803490aSGiannis Adamopoulos
1746803490aSGiannis Adamopoulos /* format the bits and bytes into pretty and accessible units... */
1756803490aSGiannis Adamopoulos StrFormatByteSizeW(ulProgress, szProgress, _countof(szProgress));
1766803490aSGiannis Adamopoulos
1776803490aSGiannis Adamopoulos /* use our subclassed progress bar text subroutine */
17833c2903eSMark Jansen CStringW ProgressText;
1796803490aSGiannis Adamopoulos
1806803490aSGiannis Adamopoulos if (ulProgressMax)
1816803490aSGiannis Adamopoulos {
1826803490aSGiannis Adamopoulos /* total size is known */
1836803490aSGiannis Adamopoulos WCHAR szProgressMax[100];
1846803490aSGiannis Adamopoulos UINT uiPercentage = ((ULONGLONG)ulProgress * 100) / ulProgressMax;
1856803490aSGiannis Adamopoulos
1866803490aSGiannis Adamopoulos /* send the current progress to the progress bar */
18733c2903eSMark Jansen if (!IsWindow())
18833c2903eSMark Jansen return;
1896803490aSGiannis Adamopoulos SendMessage(PBM_SETPOS, uiPercentage, 0);
1906803490aSGiannis Adamopoulos
1916803490aSGiannis Adamopoulos /* format total download size */
1926803490aSGiannis Adamopoulos StrFormatByteSizeW(ulProgressMax, szProgressMax, _countof(szProgressMax));
1936803490aSGiannis Adamopoulos
1946803490aSGiannis Adamopoulos /* generate the text on progress bar */
19533c2903eSMark Jansen ProgressText.Format(L"%u%% \x2014 %ls / %ls", uiPercentage, szProgress, szProgressMax);
1966803490aSGiannis Adamopoulos }
1976803490aSGiannis Adamopoulos else
1986803490aSGiannis Adamopoulos {
1996803490aSGiannis Adamopoulos /* send the current progress to the progress bar */
20033c2903eSMark Jansen if (!IsWindow())
20133c2903eSMark Jansen return;
2026803490aSGiannis Adamopoulos SendMessage(PBM_SETPOS, 0, 0);
2036803490aSGiannis Adamopoulos
2046803490aSGiannis Adamopoulos /* total size is not known, display only current size */
2056803490aSGiannis Adamopoulos ProgressText.Format(L"%ls...", szProgress);
2066803490aSGiannis Adamopoulos }
2076803490aSGiannis Adamopoulos
2086803490aSGiannis Adamopoulos /* and finally display it */
20933c2903eSMark Jansen if (!IsWindow())
21033c2903eSMark Jansen return;
211844d447eSKatayama Hirofumi MZ SetWindowText(ProgressText.GetString());
2126803490aSGiannis Adamopoulos }
2136803490aSGiannis Adamopoulos
21433c2903eSMark Jansen LRESULT
OnEraseBkgnd(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)21533c2903eSMark Jansen OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
216b4114030SKatayama Hirofumi MZ {
217b4114030SKatayama Hirofumi MZ return TRUE;
218b4114030SKatayama Hirofumi MZ }
219b4114030SKatayama Hirofumi MZ
22033c2903eSMark Jansen LRESULT
OnPaint(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)22133c2903eSMark Jansen OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2226803490aSGiannis Adamopoulos {
2236803490aSGiannis Adamopoulos PAINTSTRUCT ps;
2246803490aSGiannis Adamopoulos HDC hDC = BeginPaint(&ps), hdcMem;
2256803490aSGiannis Adamopoulos HBITMAP hbmMem;
2266803490aSGiannis Adamopoulos HANDLE hOld;
2276803490aSGiannis Adamopoulos RECT myRect;
2286803490aSGiannis Adamopoulos UINT win_width, win_height;
2296803490aSGiannis Adamopoulos
2306803490aSGiannis Adamopoulos GetClientRect(&myRect);
2316803490aSGiannis Adamopoulos
2326803490aSGiannis Adamopoulos /* grab the progress bar rect size */
2336803490aSGiannis Adamopoulos win_width = myRect.right - myRect.left;
2346803490aSGiannis Adamopoulos win_height = myRect.bottom - myRect.top;
2356803490aSGiannis Adamopoulos
2366803490aSGiannis Adamopoulos /* create an off-screen DC for double-buffering */
2376803490aSGiannis Adamopoulos hdcMem = CreateCompatibleDC(hDC);
2386803490aSGiannis Adamopoulos hbmMem = CreateCompatibleBitmap(hDC, win_width, win_height);
2396803490aSGiannis Adamopoulos
2406803490aSGiannis Adamopoulos hOld = SelectObject(hdcMem, hbmMem);
2416803490aSGiannis Adamopoulos
2426803490aSGiannis Adamopoulos /* call the original draw code and redirect it to our memory buffer */
2436803490aSGiannis Adamopoulos DefWindowProc(uMsg, (WPARAM)hdcMem, lParam);
2446803490aSGiannis Adamopoulos
2456803490aSGiannis Adamopoulos /* draw our nifty progress text over it */
2466803490aSGiannis Adamopoulos SelectFont(hdcMem, GetStockFont(DEFAULT_GUI_FONT));
24733c2903eSMark Jansen DrawShadowText(
24833c2903eSMark Jansen hdcMem, m_szProgressText.GetString(), m_szProgressText.GetLength(), &myRect,
24933c2903eSMark Jansen DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE, GetSysColor(COLOR_CAPTIONTEXT),
25033c2903eSMark Jansen GetSysColor(COLOR_3DDKSHADOW), 1, 1);
2516803490aSGiannis Adamopoulos
2526803490aSGiannis Adamopoulos /* transfer the off-screen DC to the screen */
2536803490aSGiannis Adamopoulos BitBlt(hDC, 0, 0, win_width, win_height, hdcMem, 0, 0, SRCCOPY);
2546803490aSGiannis Adamopoulos
2556803490aSGiannis Adamopoulos /* free the off-screen DC */
2566803490aSGiannis Adamopoulos SelectObject(hdcMem, hOld);
2576803490aSGiannis Adamopoulos DeleteObject(hbmMem);
2586803490aSGiannis Adamopoulos DeleteDC(hdcMem);
2596803490aSGiannis Adamopoulos
2606803490aSGiannis Adamopoulos EndPaint(&ps);
2616803490aSGiannis Adamopoulos return 0;
2626803490aSGiannis Adamopoulos }
2636803490aSGiannis Adamopoulos
26433c2903eSMark Jansen LRESULT
OnSetText(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)26533c2903eSMark Jansen OnSetText(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2666803490aSGiannis Adamopoulos {
267b4114030SKatayama Hirofumi MZ PCWSTR pszText = (PCWSTR)lParam;
268b4114030SKatayama Hirofumi MZ if (pszText)
2696803490aSGiannis Adamopoulos {
270b4114030SKatayama Hirofumi MZ if (m_szProgressText != pszText)
271b4114030SKatayama Hirofumi MZ {
272b4114030SKatayama Hirofumi MZ m_szProgressText = pszText;
273b4114030SKatayama Hirofumi MZ InvalidateRect(NULL, TRUE);
2746803490aSGiannis Adamopoulos }
275b4114030SKatayama Hirofumi MZ }
276b4114030SKatayama Hirofumi MZ else
277b4114030SKatayama Hirofumi MZ {
278b4114030SKatayama Hirofumi MZ if (!m_szProgressText.IsEmpty())
279b4114030SKatayama Hirofumi MZ {
280b4114030SKatayama Hirofumi MZ m_szProgressText.Empty();
281b4114030SKatayama Hirofumi MZ InvalidateRect(NULL, TRUE);
282b4114030SKatayama Hirofumi MZ }
283b4114030SKatayama Hirofumi MZ }
284b4114030SKatayama Hirofumi MZ return TRUE;
2856803490aSGiannis Adamopoulos }
2866803490aSGiannis Adamopoulos
2876803490aSGiannis Adamopoulos BEGIN_MSG_MAP(CDownloaderProgress)
288b4114030SKatayama Hirofumi MZ MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
2896803490aSGiannis Adamopoulos MESSAGE_HANDLER(WM_PAINT, OnPaint)
2906803490aSGiannis Adamopoulos MESSAGE_HANDLER(WM_SETTEXT, OnSetText)
2916803490aSGiannis Adamopoulos END_MSG_MAP()
2926803490aSGiannis Adamopoulos };
2936803490aSGiannis Adamopoulos
29433c2903eSMark Jansen class CDowloadingAppsListView : public CListView
295c2c66affSColin Finck {
296c2c66affSColin Finck public:
29733c2903eSMark Jansen HWND
Create(HWND hwndParent)29833c2903eSMark Jansen Create(HWND hwndParent)
299c2c66affSColin Finck {
300fc5311aaSKatayama Hirofumi MZ RECT r;
301fc5311aaSKatayama Hirofumi MZ ::GetClientRect(hwndParent, &r);
302fc5311aaSKatayama Hirofumi MZ r.top = (2 * r.top + 1 * r.bottom) / 3; /* The vertical position at ratio 1 : 2 */
303fc5311aaSKatayama Hirofumi MZ #define MARGIN 10
304fc5311aaSKatayama Hirofumi MZ ::InflateRect(&r, -MARGIN, -MARGIN);
305fc5311aaSKatayama Hirofumi MZ
30633c2903eSMark Jansen const DWORD style = WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER |
30733c2903eSMark Jansen LVS_NOCOLUMNHEADER;
308c2c66affSColin Finck
309c2c66affSColin Finck HWND hwnd = CListView::Create(hwndParent, r, NULL, style, WS_EX_CLIENTEDGE);
310c2c66affSColin Finck
311c2c66affSColin Finck AddColumn(0, 150, LVCFMT_LEFT);
312c2c66affSColin Finck AddColumn(1, 120, LVCFMT_LEFT);
313c2c66affSColin Finck
314c2c66affSColin Finck return hwnd;
315c2c66affSColin Finck }
316c2c66affSColin Finck
31733c2903eSMark Jansen VOID
LoadList(ATL::CSimpleArray<DownloadInfo> arrInfo)31833c2903eSMark Jansen LoadList(ATL::CSimpleArray<DownloadInfo> arrInfo)
319c2c66affSColin Finck {
320c2c66affSColin Finck for (INT i = 0; i < arrInfo.GetSize(); ++i)
321c2c66affSColin Finck {
322c2c66affSColin Finck AddRow(i, arrInfo[i].szName.GetString(), DLSTATUS_WAITING);
323c2c66affSColin Finck }
324c2c66affSColin Finck }
325c2c66affSColin Finck
32633c2903eSMark Jansen VOID
SetDownloadStatus(INT ItemIndex,DownloadStatus Status)32733c2903eSMark Jansen SetDownloadStatus(INT ItemIndex, DownloadStatus Status)
328c2c66affSColin Finck {
32933c2903eSMark Jansen CStringW szBuffer = LoadStatusString(Status);
33096fba571SGiannis Adamopoulos SetItemText(ItemIndex, 1, szBuffer.GetString());
331c2c66affSColin Finck }
332c2c66affSColin Finck
33333c2903eSMark Jansen BOOL
AddItem(INT ItemIndex,LPWSTR lpText)33433c2903eSMark Jansen AddItem(INT ItemIndex, LPWSTR lpText)
335c2c66affSColin Finck {
336c2c66affSColin Finck LVITEMW Item;
337c2c66affSColin Finck
338c2c66affSColin Finck ZeroMemory(&Item, sizeof(Item));
339c2c66affSColin Finck
340c2c66affSColin Finck Item.mask = LVIF_TEXT | LVIF_STATE;
341c2c66affSColin Finck Item.pszText = lpText;
342c2c66affSColin Finck Item.iItem = ItemIndex;
343c2c66affSColin Finck
344c2c66affSColin Finck return InsertItem(&Item);
345c2c66affSColin Finck }
346c2c66affSColin Finck
34733c2903eSMark Jansen VOID
AddRow(INT RowIndex,LPCWSTR szAppName,const DownloadStatus Status)34833c2903eSMark Jansen AddRow(INT RowIndex, LPCWSTR szAppName, const DownloadStatus Status)
349c2c66affSColin Finck {
35033c2903eSMark Jansen CStringW szStatus = LoadStatusString(Status);
35133c2903eSMark Jansen AddItem(RowIndex, const_cast<LPWSTR>(szAppName));
352c2c66affSColin Finck SetDownloadStatus(RowIndex, Status);
353c2c66affSColin Finck }
354c2c66affSColin Finck
35533c2903eSMark Jansen BOOL
AddColumn(INT Index,INT Width,INT Format)35633c2903eSMark Jansen AddColumn(INT Index, INT Width, INT Format)
357c2c66affSColin Finck {
358c2c66affSColin Finck LVCOLUMNW Column;
359c2c66affSColin Finck ZeroMemory(&Column, sizeof(Column));
360c2c66affSColin Finck
361c2c66affSColin Finck Column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
362c2c66affSColin Finck Column.iSubItem = Index;
363c2c66affSColin Finck Column.cx = Width;
364c2c66affSColin Finck Column.fmt = Format;
365c2c66affSColin Finck
366c2c66affSColin Finck return (InsertColumn(Index, &Column) == -1) ? FALSE : TRUE;
367c2c66affSColin Finck }
368c2c66affSColin Finck };
369c2c66affSColin Finck
370c2c66affSColin Finck #ifdef USE_CERT_PINNING
37133c2903eSMark Jansen static BOOL
CertGetSubjectAndIssuer(HINTERNET hFile,CLocalPtr<char> & subjectInfo,CLocalPtr<char> & issuerInfo)37233c2903eSMark Jansen CertGetSubjectAndIssuer(HINTERNET hFile, CLocalPtr<char> &subjectInfo, CLocalPtr<char> &issuerInfo)
373c2c66affSColin Finck {
374c2c66affSColin Finck DWORD certInfoLength;
375b56193a2SMark Jansen INTERNET_CERTIFICATE_INFOA certInfo;
37607f3691cSMark Jansen DWORD size, flags;
37707f3691cSMark Jansen
37807f3691cSMark Jansen size = sizeof(flags);
37907f3691cSMark Jansen if (!InternetQueryOptionA(hFile, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size))
38007f3691cSMark Jansen {
38107f3691cSMark Jansen return FALSE;
38207f3691cSMark Jansen }
38307f3691cSMark Jansen
38407f3691cSMark Jansen if (!flags & SECURITY_FLAG_SECURE)
38507f3691cSMark Jansen {
38607f3691cSMark Jansen return FALSE;
38707f3691cSMark Jansen }
388c2c66affSColin Finck
389b56193a2SMark Jansen /* Despite what the header indicates, the implementation of INTERNET_CERTIFICATE_INFO is not Unicode-aware. */
390c2c66affSColin Finck certInfoLength = sizeof(certInfo);
39133c2903eSMark Jansen if (!InternetQueryOptionA(hFile, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, &certInfo, &certInfoLength))
392c2c66affSColin Finck {
393b56193a2SMark Jansen return FALSE;
394b56193a2SMark Jansen }
395b56193a2SMark Jansen
39607f3691cSMark Jansen subjectInfo.Attach(certInfo.lpszSubjectInfo);
39707f3691cSMark Jansen issuerInfo.Attach(certInfo.lpszIssuerInfo);
39807f3691cSMark Jansen
399c2c66affSColin Finck if (certInfo.lpszProtocolName)
400c2c66affSColin Finck LocalFree(certInfo.lpszProtocolName);
401c2c66affSColin Finck if (certInfo.lpszSignatureAlgName)
402c2c66affSColin Finck LocalFree(certInfo.lpszSignatureAlgName);
403b56193a2SMark Jansen if (certInfo.lpszEncryptionAlgName)
404b56193a2SMark Jansen LocalFree(certInfo.lpszEncryptionAlgName);
405b56193a2SMark Jansen
40607f3691cSMark Jansen return certInfo.lpszSubjectInfo && certInfo.lpszIssuerInfo;
407c2c66affSColin Finck }
408c2c66affSColin Finck #endif
409c2c66affSColin Finck
41033c2903eSMark Jansen inline VOID
MessageBox_LoadString(HWND hOwnerWnd,INT StringID)41157b775efSWhindmar Saksit MessageBox_LoadString(HWND hOwnerWnd, INT StringID)
412c2c66affSColin Finck {
41333c2903eSMark Jansen CStringW szMsgText;
414c2c66affSColin Finck if (szMsgText.LoadStringW(StringID))
415c2c66affSColin Finck {
41657b775efSWhindmar Saksit MessageBoxW(hOwnerWnd, szMsgText.GetString(), NULL, MB_OK | MB_ICONERROR);
417c2c66affSColin Finck }
418c2c66affSColin Finck }
419c2c66affSColin Finck
4201807dbfdSGiannis Adamopoulos // Download dialog (loaddlg.cpp)
4211807dbfdSGiannis Adamopoulos class CDownloadManager
4221807dbfdSGiannis Adamopoulos {
4234c524ee3S赫杨 static ATL::CSimpleArray<DownloadInfo> AppsDownloadList;
4241807dbfdSGiannis Adamopoulos static CDowloadingAppsListView DownloadsListView;
4256803490aSGiannis Adamopoulos static CDownloaderProgress ProgressBar;
426db8f1d6fSGiannis Adamopoulos static BOOL bCancelled;
427946ee611SMark Jansen static BOOL bModal;
42833c2903eSMark Jansen static VOID
42933c2903eSMark Jansen UpdateProgress(HWND hDlg, ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText);
43033c2903eSMark Jansen
4311807dbfdSGiannis Adamopoulos public:
43233c2903eSMark Jansen static VOID
43333c2903eSMark Jansen Add(DownloadInfo info);
43433c2903eSMark Jansen static VOID
43533c2903eSMark Jansen Download(const DownloadInfo &DLInfo, BOOL bIsModal = FALSE);
43633c2903eSMark Jansen static INT_PTR CALLBACK
43733c2903eSMark Jansen DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
43833c2903eSMark Jansen static unsigned int WINAPI
43933c2903eSMark Jansen ThreadFunc(LPVOID Context);
4401807dbfdSGiannis Adamopoulos static VOID LaunchDownloadDialog(BOOL);
4411807dbfdSGiannis Adamopoulos };
4421807dbfdSGiannis Adamopoulos
443c2c66affSColin Finck // CDownloadManager
4444c524ee3S赫杨 ATL::CSimpleArray<DownloadInfo> CDownloadManager::AppsDownloadList;
445c2c66affSColin Finck CDowloadingAppsListView CDownloadManager::DownloadsListView;
4466803490aSGiannis Adamopoulos CDownloaderProgress CDownloadManager::ProgressBar;
447946ee611SMark Jansen BOOL CDownloadManager::bCancelled = FALSE;
448946ee611SMark Jansen BOOL CDownloadManager::bModal = FALSE;
449c2c66affSColin Finck
45033c2903eSMark Jansen VOID
Add(DownloadInfo info)45133c2903eSMark Jansen CDownloadManager::Add(DownloadInfo info)
4521807dbfdSGiannis Adamopoulos {
4534c524ee3S赫杨 AppsDownloadList.Add(info);
4541807dbfdSGiannis Adamopoulos }
4551807dbfdSGiannis Adamopoulos
45633c2903eSMark Jansen VOID
Download(const DownloadInfo & DLInfo,BOOL bIsModal)45733c2903eSMark Jansen CDownloadManager::Download(const DownloadInfo &DLInfo, BOOL bIsModal)
458c2c66affSColin Finck {
4594c524ee3S赫杨 AppsDownloadList.RemoveAll();
4604c524ee3S赫杨 AppsDownloadList.Add(DLInfo);
461c2c66affSColin Finck LaunchDownloadDialog(bIsModal);
462c2c66affSColin Finck }
463c2c66affSColin Finck
46433c2903eSMark Jansen INT_PTR CALLBACK
DownloadDlgProc(HWND Dlg,UINT uMsg,WPARAM wParam,LPARAM lParam)46533c2903eSMark Jansen CDownloadManager::DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
466c2c66affSColin Finck {
467c2c66affSColin Finck static WCHAR szCaption[MAX_PATH];
468c2c66affSColin Finck
469c2c66affSColin Finck switch (uMsg)
470c2c66affSColin Finck {
471c2c66affSColin Finck case WM_INITDIALOG:
472c2c66affSColin Finck {
473053939e2SWhindmar Saksit g_Busy++;
474c2c66affSColin Finck HICON hIconSm, hIconBg;
47533c2903eSMark Jansen CStringW szTempCaption;
476c2c66affSColin Finck
477db8f1d6fSGiannis Adamopoulos bCancelled = FALSE;
478db8f1d6fSGiannis Adamopoulos
479a84d2959SHermès Bélusca-Maïto if (hMainWnd)
480a84d2959SHermès Bélusca-Maïto {
4816f130666STimo Kreuzer hIconBg = (HICON)GetClassLongPtrW(hMainWnd, GCLP_HICON);
4826f130666STimo Kreuzer hIconSm = (HICON)GetClassLongPtrW(hMainWnd, GCLP_HICONSM);
483a84d2959SHermès Bélusca-Maïto }
484a84d2959SHermès Bélusca-Maïto if (!hMainWnd || (!hIconBg || !hIconSm))
485a84d2959SHermès Bélusca-Maïto {
486a84d2959SHermès Bélusca-Maïto /* Load the default icon */
487a84d2959SHermès Bélusca-Maïto hIconBg = hIconSm = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
488a84d2959SHermès Bélusca-Maïto }
489c2c66affSColin Finck
490c2c66affSColin Finck if (hIconBg && hIconSm)
491c2c66affSColin Finck {
492c2c66affSColin Finck SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM)hIconBg);
493c2c66affSColin Finck SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
494c2c66affSColin Finck }
495c2c66affSColin Finck
496c2c66affSColin Finck HWND Item = GetDlgItem(Dlg, IDC_DOWNLOAD_PROGRESS);
497c2c66affSColin Finck if (Item)
498c2c66affSColin Finck {
499c2c66affSColin Finck // initialize the default values for our nifty progress bar
500c2c66affSColin Finck // and subclass it so that it learns to print a status text
5016803490aSGiannis Adamopoulos ProgressBar.SubclassWindow(Item);
5026803490aSGiannis Adamopoulos ProgressBar.SendMessage(PBM_SETRANGE, 0, MAKELPARAM(0, 100));
5036803490aSGiannis Adamopoulos ProgressBar.SendMessage(PBM_SETPOS, 0, 0);
504b4114030SKatayama Hirofumi MZ if (AppsDownloadList.GetSize() > 0)
505b4114030SKatayama Hirofumi MZ ProgressBar.SetProgress(0, AppsDownloadList[0].SizeInBytes);
506c2c66affSColin Finck }
507c2c66affSColin Finck
508c2c66affSColin Finck // Add a ListView
509c2c66affSColin Finck HWND hListView = DownloadsListView.Create(Dlg);
510c2c66affSColin Finck if (!hListView)
511c2c66affSColin Finck {
512c2c66affSColin Finck return FALSE;
513c2c66affSColin Finck }
5144c524ee3S赫杨 DownloadsListView.LoadList(AppsDownloadList);
515c2c66affSColin Finck
516c2c66affSColin Finck // Get a dlg string for later use
51726ac8ac8SHermès Bélusca-Maïto GetWindowTextW(Dlg, szCaption, _countof(szCaption));
518c2c66affSColin Finck
519ee019e12SAlexander Shaposhnikov // Hide a placeholder from displaying
520ee019e12SAlexander Shaposhnikov szTempCaption = szCaption;
521ee019e12SAlexander Shaposhnikov szTempCaption.Replace(L"%ls", L"");
522ee019e12SAlexander Shaposhnikov SetWindowText(Dlg, szTempCaption.GetString());
523ee019e12SAlexander Shaposhnikov
524ee019e12SAlexander Shaposhnikov ShowWindow(Dlg, SW_SHOW);
525ee019e12SAlexander Shaposhnikov
526c2c66affSColin Finck // Start download process
5274c524ee3S赫杨 DownloadParam *param = new DownloadParam(Dlg, AppsDownloadList, szCaption);
5282ac13afeSHe Yang unsigned int ThreadId;
5292ac13afeSHe Yang HANDLE Thread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (void *)param, 0, &ThreadId);
530c2c66affSColin Finck if (!Thread)
531c2c66affSColin Finck {
532c2c66affSColin Finck return FALSE;
533c2c66affSColin Finck }
534c2c66affSColin Finck
535c2c66affSColin Finck CloseHandle(Thread);
5364c524ee3S赫杨 AppsDownloadList.RemoveAll();
537c2c66affSColin Finck return TRUE;
538c2c66affSColin Finck }
539c2c66affSColin Finck
540c2c66affSColin Finck case WM_COMMAND:
541c2c66affSColin Finck if (wParam == IDCANCEL)
542c2c66affSColin Finck {
543db8f1d6fSGiannis Adamopoulos bCancelled = TRUE;
544c2c66affSColin Finck PostMessageW(Dlg, WM_CLOSE, 0, 0);
545c2c66affSColin Finck }
546c2c66affSColin Finck return FALSE;
547c2c66affSColin Finck
548c2c66affSColin Finck case WM_CLOSE:
549b4114030SKatayama Hirofumi MZ if (ProgressBar)
550b4114030SKatayama Hirofumi MZ ProgressBar.UnsubclassWindow(TRUE);
551946ee611SMark Jansen if (CDownloadManager::bModal)
552946ee611SMark Jansen {
553946ee611SMark Jansen ::EndDialog(Dlg, 0);
554946ee611SMark Jansen }
555946ee611SMark Jansen else
556946ee611SMark Jansen {
557946ee611SMark Jansen ::DestroyWindow(Dlg);
558946ee611SMark Jansen }
559c2c66affSColin Finck return TRUE;
560c2c66affSColin Finck
561053939e2SWhindmar Saksit case WM_DESTROY:
562053939e2SWhindmar Saksit g_Busy--;
563053939e2SWhindmar Saksit if (hMainWnd)
564053939e2SWhindmar Saksit PostMessage(hMainWnd, WM_NOTIFY_OPERATIONCOMPLETED, 0, 0);
565053939e2SWhindmar Saksit return FALSE;
566053939e2SWhindmar Saksit
567c2c66affSColin Finck default:
568c2c66affSColin Finck return FALSE;
569c2c66affSColin Finck }
570c2c66affSColin Finck }
571c2c66affSColin Finck
5721e201d70SGiannis Adamopoulos BOOL UrlHasBeenCopied;
5731e201d70SGiannis Adamopoulos
57433c2903eSMark Jansen VOID
UpdateProgress(HWND hDlg,ULONG ulProgress,ULONG ulProgressMax,ULONG ulStatusCode,LPCWSTR szStatusText)57533c2903eSMark Jansen CDownloadManager::UpdateProgress(
5761e201d70SGiannis Adamopoulos HWND hDlg,
5771e201d70SGiannis Adamopoulos ULONG ulProgress,
5781e201d70SGiannis Adamopoulos ULONG ulProgressMax,
5791e201d70SGiannis Adamopoulos ULONG ulStatusCode,
5801e201d70SGiannis Adamopoulos LPCWSTR szStatusText)
5811e201d70SGiannis Adamopoulos {
5821e201d70SGiannis Adamopoulos HWND Item;
5831e201d70SGiannis Adamopoulos
58433c2903eSMark Jansen if (!IsWindow(hDlg))
58533c2903eSMark Jansen return;
5861e201d70SGiannis Adamopoulos ProgressBar.SetProgress(ulProgress, ulProgressMax);
5871e201d70SGiannis Adamopoulos
58833c2903eSMark Jansen if (!IsWindow(hDlg))
58933c2903eSMark Jansen return;
5901e201d70SGiannis Adamopoulos Item = GetDlgItem(hDlg, IDC_DOWNLOAD_STATUS);
5911e201d70SGiannis Adamopoulos if (Item && szStatusText && wcslen(szStatusText) > 0 && UrlHasBeenCopied == FALSE)
5921e201d70SGiannis Adamopoulos {
5931e201d70SGiannis Adamopoulos SIZE_T len = wcslen(szStatusText) + 1;
59433c2903eSMark Jansen CStringW buf;
5951e201d70SGiannis Adamopoulos DWORD dummyLen;
5961e201d70SGiannis Adamopoulos
5971e201d70SGiannis Adamopoulos /* beautify our url for display purposes */
5981e201d70SGiannis Adamopoulos if (!InternetCanonicalizeUrlW(szStatusText, buf.GetBuffer(len), &dummyLen, ICU_DECODE | ICU_NO_ENCODE))
5991e201d70SGiannis Adamopoulos {
6001e201d70SGiannis Adamopoulos /* just use the original */
6011e201d70SGiannis Adamopoulos buf.ReleaseBuffer();
6021e201d70SGiannis Adamopoulos buf = szStatusText;
6031e201d70SGiannis Adamopoulos }
6041e201d70SGiannis Adamopoulos else
6051e201d70SGiannis Adamopoulos {
6061e201d70SGiannis Adamopoulos buf.ReleaseBuffer();
6071e201d70SGiannis Adamopoulos }
6081e201d70SGiannis Adamopoulos
6091e201d70SGiannis Adamopoulos /* paste it into our dialog and don't do it again in this instance */
610844d447eSKatayama Hirofumi MZ ::SetWindowText(Item, buf.GetString());
6111e201d70SGiannis Adamopoulos UrlHasBeenCopied = TRUE;
6121e201d70SGiannis Adamopoulos }
6131e201d70SGiannis Adamopoulos }
6141e201d70SGiannis Adamopoulos
61533c2903eSMark Jansen BOOL
ShowLastError(HWND hWndOwner,BOOL bInetError,DWORD dwLastError)61633c2903eSMark Jansen ShowLastError(HWND hWndOwner, BOOL bInetError, DWORD dwLastError)
617fb1582d3SKyle Katarn {
6184f25a476SMark Jansen CLocalPtr<WCHAR> lpMsg;
619fb1582d3SKyle Katarn
62033c2903eSMark Jansen if (!FormatMessageW(
62133c2903eSMark Jansen FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS |
622059ba9b0SStanislav Motylkov (bInetError ? FORMAT_MESSAGE_FROM_HMODULE : FORMAT_MESSAGE_FROM_SYSTEM),
62333c2903eSMark Jansen (bInetError ? GetModuleHandleW(L"wininet.dll") : NULL), dwLastError, LANG_USER_DEFAULT, (LPWSTR)&lpMsg, 0,
62433c2903eSMark Jansen NULL))
625fb1582d3SKyle Katarn {
626059ba9b0SStanislav Motylkov DPRINT1("FormatMessageW unexpected failure (err %d)\n", GetLastError());
627059ba9b0SStanislav Motylkov return FALSE;
628fb1582d3SKyle Katarn }
629fb1582d3SKyle Katarn
630fb1582d3SKyle Katarn MessageBoxW(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR);
631059ba9b0SStanislav Motylkov return TRUE;
632fb1582d3SKyle Katarn }
633fb1582d3SKyle Katarn
63433c2903eSMark Jansen unsigned int WINAPI
ThreadFunc(LPVOID param)63533c2903eSMark Jansen CDownloadManager::ThreadFunc(LPVOID param)
636c2c66affSColin Finck {
63733c2903eSMark Jansen CPathW Path;
638*8ba61029STimo Kreuzer PCWSTR p, q;
639c2c66affSColin Finck
640c2c66affSColin Finck HWND hDlg = static_cast<DownloadParam *>(param)->Dialog;
641c2c66affSColin Finck HWND Item;
642c2c66affSColin Finck INT iAppId;
643c2c66affSColin Finck
644c2c66affSColin Finck ULONG dwContentLen, dwBytesWritten, dwBytesRead, dwStatus;
645c2c66affSColin Finck ULONG dwCurrentBytesRead = 0;
646c2c66affSColin Finck ULONG dwStatusLen = sizeof(dwStatus);
647c2c66affSColin Finck
648c2c66affSColin Finck BOOL bTempfile = FALSE;
649c2c66affSColin Finck
650c2c66affSColin Finck HINTERNET hOpen = NULL;
651c2c66affSColin Finck HINTERNET hFile = NULL;
652c2c66affSColin Finck HANDLE hOut = INVALID_HANDLE_VALUE;
653c2c66affSColin Finck
654c2c66affSColin Finck unsigned char lpBuffer[4096];
65512489f69SMark Jansen LPCWSTR lpszAgent = L"RApps/1.1";
656e5336bd2SHe Yang URL_COMPONENTSW urlComponents;
657c2c66affSColin Finck size_t urlLength, filenameLength;
658c2c66affSColin Finck
659c2c66affSColin Finck const ATL::CSimpleArray<DownloadInfo> &InfoArray = static_cast<DownloadParam *>(param)->AppInfo;
660c2c66affSColin Finck LPCWSTR szCaption = static_cast<DownloadParam *>(param)->szCaption;
66133c2903eSMark Jansen CStringW szNewCaption;
662c2c66affSColin Finck
66333c2903eSMark Jansen const DWORD dwUrlConnectFlags =
66433c2903eSMark Jansen INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_KEEP_CONNECTION;
665a6d2172cSAlexander Shaposhnikov
666c2c66affSColin Finck if (InfoArray.GetSize() <= 0)
667c2c66affSColin Finck {
668c2c66affSColin Finck MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD);
669c2c66affSColin Finck goto end;
670c2c66affSColin Finck }
671c2c66affSColin Finck
672c2c66affSColin Finck for (iAppId = 0; iAppId < InfoArray.GetSize(); ++iAppId)
673c2c66affSColin Finck {
674ee019e12SAlexander Shaposhnikov // Reset progress bar
67533c2903eSMark Jansen if (!IsWindow(hDlg))
67633c2903eSMark Jansen break;
677ee019e12SAlexander Shaposhnikov Item = GetDlgItem(hDlg, IDC_DOWNLOAD_PROGRESS);
678ee019e12SAlexander Shaposhnikov if (Item)
679ee019e12SAlexander Shaposhnikov {
6806803490aSGiannis Adamopoulos ProgressBar.SetMarquee(FALSE);
6816803490aSGiannis Adamopoulos ProgressBar.SendMessage(PBM_SETPOS, 0, 0);
682b4114030SKatayama Hirofumi MZ ProgressBar.SetProgress(0, InfoArray[iAppId].SizeInBytes);
683ee019e12SAlexander Shaposhnikov }
684ee019e12SAlexander Shaposhnikov
68507f3691cSMark Jansen // is this URL an update package for RAPPS? if so store it in a different place
686a21d959eSHe Yang if (InfoArray[iAppId].DLType != DLTYPE_APPLICATION)
68707f3691cSMark Jansen {
68807f3691cSMark Jansen if (!GetStorageDirectory(Path))
689fb1582d3SKyle Katarn {
690059ba9b0SStanislav Motylkov ShowLastError(hMainWnd, FALSE, GetLastError());
69107f3691cSMark Jansen goto end;
69207f3691cSMark Jansen }
693fb1582d3SKyle Katarn }
69407f3691cSMark Jansen else
69507f3691cSMark Jansen {
69607f3691cSMark Jansen Path = SettingsInfo.szDownloadDir;
69707f3691cSMark Jansen }
69807f3691cSMark Jansen
699ee019e12SAlexander Shaposhnikov // Change caption to show the currently downloaded app
700a21d959eSHe Yang switch (InfoArray[iAppId].DLType)
701ee019e12SAlexander Shaposhnikov {
702a21d959eSHe Yang case DLTYPE_APPLICATION:
703ee019e12SAlexander Shaposhnikov szNewCaption.Format(szCaption, InfoArray[iAppId].szName.GetString());
704a21d959eSHe Yang break;
705a21d959eSHe Yang case DLTYPE_DBUPDATE:
706ee019e12SAlexander Shaposhnikov szNewCaption.LoadStringW(IDS_DL_DIALOG_DB_DOWNLOAD_DISP);
707a21d959eSHe Yang break;
708a21d959eSHe Yang case DLTYPE_DBUPDATE_UNOFFICIAL:
709a21d959eSHe Yang szNewCaption.LoadStringW(IDS_DL_DIALOG_DB_UNOFFICIAL_DOWNLOAD_DISP);
710a21d959eSHe Yang break;
711ee019e12SAlexander Shaposhnikov }
712ee019e12SAlexander Shaposhnikov
71333c2903eSMark Jansen if (!IsWindow(hDlg))
71433c2903eSMark Jansen goto end;
715ee019e12SAlexander Shaposhnikov SetWindowTextW(hDlg, szNewCaption.GetString());
716ee019e12SAlexander Shaposhnikov
717c2c66affSColin Finck // build the path for the download
718c2c66affSColin Finck p = wcsrchr(InfoArray[iAppId].szUrl.GetString(), L'/');
719c2c66affSColin Finck q = wcsrchr(InfoArray[iAppId].szUrl.GetString(), L'?');
720c2c66affSColin Finck
721c2c66affSColin Finck // do we have a final slash separator?
722c2c66affSColin Finck if (!p)
723fb1582d3SKyle Katarn {
724fb1582d3SKyle Katarn MessageBox_LoadString(hMainWnd, IDS_UNABLE_PATH);
725c2c66affSColin Finck goto end;
726fb1582d3SKyle Katarn }
727c2c66affSColin Finck
728c2c66affSColin Finck // prepare the tentative length of the filename, maybe we've to remove part of it later on
729c2c66affSColin Finck filenameLength = wcslen(p) * sizeof(WCHAR);
730c2c66affSColin Finck
731c2c66affSColin Finck /* do we have query arguments in the target URL after the filename? account for them
732c2c66affSColin Finck (e.g. https://example.org/myfile.exe?no_adware_plz) */
733c2c66affSColin Finck if (q && q > p && (q - p) > 0)
734c2c66affSColin Finck filenameLength -= wcslen(q - 1) * sizeof(WCHAR);
735c2c66affSColin Finck
736c2c66affSColin Finck // is the path valid? can we access it?
73733c2903eSMark Jansen if (GetFileAttributesW(Path) == INVALID_FILE_ATTRIBUTES)
738c2c66affSColin Finck {
73933c2903eSMark Jansen if (!CreateDirectoryW(Path, NULL))
740fb1582d3SKyle Katarn {
741059ba9b0SStanislav Motylkov ShowLastError(hMainWnd, FALSE, GetLastError());
742c2c66affSColin Finck goto end;
743c2c66affSColin Finck }
744fb1582d3SKyle Katarn }
745c2c66affSColin Finck
746fbf119fdSHe Yang switch (InfoArray[iAppId].DLType)
747fbf119fdSHe Yang {
748fbf119fdSHe Yang case DLTYPE_DBUPDATE:
749fbf119fdSHe Yang case DLTYPE_DBUPDATE_UNOFFICIAL:
75033c2903eSMark Jansen Path += APPLICATION_DATABASE_NAME;
751fbf119fdSHe Yang break;
752fbf119fdSHe Yang case DLTYPE_APPLICATION:
7531fbf09f5SKatayama Hirofumi MZ {
7541fbf09f5SKatayama Hirofumi MZ CStringW str = p + 1; // use the filename retrieved from URL
7551fbf09f5SKatayama Hirofumi MZ UrlUnescapeAndMakeFileNameValid(str);
7561fbf09f5SKatayama Hirofumi MZ Path += str;
757fbf119fdSHe Yang break;
758fbf119fdSHe Yang }
7591fbf09f5SKatayama Hirofumi MZ }
760c2c66affSColin Finck
76133c2903eSMark Jansen if ((InfoArray[iAppId].DLType == DLTYPE_APPLICATION) && InfoArray[iAppId].szSHA1[0] &&
76233c2903eSMark Jansen GetFileAttributesW(Path) != INVALID_FILE_ATTRIBUTES)
763c2c66affSColin Finck {
764c2c66affSColin Finck // only open it in case of total correctness
765c2c66affSColin Finck if (VerifyInteg(InfoArray[iAppId].szSHA1.GetString(), Path))
766c2c66affSColin Finck goto run;
767c2c66affSColin Finck }
768c2c66affSColin Finck
769c2c66affSColin Finck // Add the download URL
77033c2903eSMark Jansen if (!IsWindow(hDlg))
77133c2903eSMark Jansen goto end;
772c2c66affSColin Finck SetDlgItemTextW(hDlg, IDC_DOWNLOAD_STATUS, InfoArray[iAppId].szUrl.GetString());
773c2c66affSColin Finck
774c2c66affSColin Finck DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_DOWNLOADING);
775c2c66affSColin Finck
776c2c66affSColin Finck // download it
7771e201d70SGiannis Adamopoulos UrlHasBeenCopied = FALSE;
778c2c66affSColin Finck bTempfile = TRUE;
779c2c66affSColin Finck
780c2c66affSColin Finck /* FIXME: this should just be using the system-wide proxy settings */
781c2c66affSColin Finck switch (SettingsInfo.Proxy)
782c2c66affSColin Finck {
783c2c66affSColin Finck case 0: // preconfig
78407f3691cSMark Jansen default:
785c2c66affSColin Finck hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
786c2c66affSColin Finck break;
787c2c66affSColin Finck case 1: // direct (no proxy)
788c2c66affSColin Finck hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
789c2c66affSColin Finck break;
790c2c66affSColin Finck case 2: // use proxy
79133c2903eSMark Jansen hOpen = InternetOpenW(
79233c2903eSMark Jansen lpszAgent, INTERNET_OPEN_TYPE_PROXY, SettingsInfo.szProxyServer, SettingsInfo.szNoProxyFor, 0);
793c2c66affSColin Finck break;
794c2c66affSColin Finck }
795c2c66affSColin Finck
796c2c66affSColin Finck if (!hOpen)
797fb1582d3SKyle Katarn {
798059ba9b0SStanislav Motylkov ShowLastError(hMainWnd, TRUE, GetLastError());
799c2c66affSColin Finck goto end;
800fb1582d3SKyle Katarn }
801c2c66affSColin Finck
802c2c66affSColin Finck dwStatusLen = sizeof(dwStatus);
803c2c66affSColin Finck
804c2c66affSColin Finck memset(&urlComponents, 0, sizeof(urlComponents));
805c2c66affSColin Finck urlComponents.dwStructSize = sizeof(urlComponents);
806c2c66affSColin Finck
807c2c66affSColin Finck urlLength = InfoArray[iAppId].szUrl.GetLength();
808c2c66affSColin Finck urlComponents.dwSchemeLength = urlLength + 1;
809c2c66affSColin Finck urlComponents.lpszScheme = (LPWSTR)malloc(urlComponents.dwSchemeLength * sizeof(WCHAR));
810c2c66affSColin Finck
811c2c66affSColin Finck if (!InternetCrackUrlW(InfoArray[iAppId].szUrl, urlLength + 1, ICU_DECODE | ICU_ESCAPE, &urlComponents))
812fb1582d3SKyle Katarn {
813059ba9b0SStanislav Motylkov ShowLastError(hMainWnd, TRUE, GetLastError());
814c2c66affSColin Finck goto end;
815fb1582d3SKyle Katarn }
816c2c66affSColin Finck
81766e3c1f7SStanislav Motylkov dwContentLen = 0;
81866e3c1f7SStanislav Motylkov
81933c2903eSMark Jansen if (urlComponents.nScheme == INTERNET_SCHEME_HTTP || urlComponents.nScheme == INTERNET_SCHEME_HTTPS)
8203261bbb7SAlexander Shaposhnikov {
82133c2903eSMark Jansen hFile = InternetOpenUrlW(hOpen, InfoArray[iAppId].szUrl.GetString(), NULL, 0, dwUrlConnectFlags, 0);
822a6d2172cSAlexander Shaposhnikov if (!hFile)
823a6d2172cSAlexander Shaposhnikov {
824059ba9b0SStanislav Motylkov if (!ShowLastError(hMainWnd, TRUE, GetLastError()))
825059ba9b0SStanislav Motylkov {
826059ba9b0SStanislav Motylkov /* Workaround for CORE-17377 */
827059ba9b0SStanislav Motylkov MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD2);
828059ba9b0SStanislav Motylkov }
829a6d2172cSAlexander Shaposhnikov goto end;
830a6d2172cSAlexander Shaposhnikov }
831a6d2172cSAlexander Shaposhnikov
8323261bbb7SAlexander Shaposhnikov // query connection
8333261bbb7SAlexander Shaposhnikov if (!HttpQueryInfoW(hFile, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwStatusLen, NULL))
834fb1582d3SKyle Katarn {
835059ba9b0SStanislav Motylkov ShowLastError(hMainWnd, TRUE, GetLastError());
8363261bbb7SAlexander Shaposhnikov goto end;
837fb1582d3SKyle Katarn }
8383261bbb7SAlexander Shaposhnikov
8393261bbb7SAlexander Shaposhnikov if (dwStatus != HTTP_STATUS_OK)
8403261bbb7SAlexander Shaposhnikov {
8413261bbb7SAlexander Shaposhnikov MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD);
8423261bbb7SAlexander Shaposhnikov goto end;
8433261bbb7SAlexander Shaposhnikov }
8443261bbb7SAlexander Shaposhnikov
8453261bbb7SAlexander Shaposhnikov // query content length
84633c2903eSMark Jansen HttpQueryInfoW(
84733c2903eSMark Jansen hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwContentLen, &dwStatusLen, NULL);
8483261bbb7SAlexander Shaposhnikov }
8494439b538SMark Jansen else if (urlComponents.nScheme == INTERNET_SCHEME_FTP)
8503261bbb7SAlexander Shaposhnikov {
851a6d2172cSAlexander Shaposhnikov // force passive mode on FTP
85233c2903eSMark Jansen hFile =
85333c2903eSMark Jansen InternetOpenUrlW(hOpen, InfoArray[iAppId].szUrl, NULL, 0, dwUrlConnectFlags | INTERNET_FLAG_PASSIVE, 0);
854a6d2172cSAlexander Shaposhnikov if (!hFile)
855a6d2172cSAlexander Shaposhnikov {
856059ba9b0SStanislav Motylkov if (!ShowLastError(hMainWnd, TRUE, GetLastError()))
857059ba9b0SStanislav Motylkov {
858059ba9b0SStanislav Motylkov /* Workaround for CORE-17377 */
859059ba9b0SStanislav Motylkov MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD2);
860059ba9b0SStanislav Motylkov }
861a6d2172cSAlexander Shaposhnikov goto end;
862a6d2172cSAlexander Shaposhnikov }
863a6d2172cSAlexander Shaposhnikov
864c2c66affSColin Finck dwContentLen = FtpGetFileSize(hFile, &dwStatus);
8653261bbb7SAlexander Shaposhnikov }
8664f25a476SMark Jansen else if (urlComponents.nScheme == INTERNET_SCHEME_FILE)
8674f25a476SMark Jansen {
8684f25a476SMark Jansen // Add support for the file scheme so testing locally is simpler
8694f25a476SMark Jansen WCHAR LocalFilePath[MAX_PATH];
8704f25a476SMark Jansen DWORD cchPath = _countof(LocalFilePath);
8714f25a476SMark Jansen // Ideally we would use PathCreateFromUrlAlloc here, but that is not exported (yet)
8724f25a476SMark Jansen HRESULT hr = PathCreateFromUrlW(InfoArray[iAppId].szUrl, LocalFilePath, &cchPath, 0);
8734f25a476SMark Jansen if (SUCCEEDED(hr))
8744f25a476SMark Jansen {
8754f25a476SMark Jansen if (CopyFileW(LocalFilePath, Path, FALSE))
8764f25a476SMark Jansen {
8774f25a476SMark Jansen goto run;
8784f25a476SMark Jansen }
8794f25a476SMark Jansen else
8804f25a476SMark Jansen {
881059ba9b0SStanislav Motylkov ShowLastError(hMainWnd, FALSE, GetLastError());
8824f25a476SMark Jansen goto end;
8834f25a476SMark Jansen }
8844f25a476SMark Jansen }
8854f25a476SMark Jansen else
8864f25a476SMark Jansen {
887059ba9b0SStanislav Motylkov ShowLastError(hMainWnd, FALSE, hr);
8884f25a476SMark Jansen goto end;
8894f25a476SMark Jansen }
8904f25a476SMark Jansen }
891c2c66affSColin Finck
89266e3c1f7SStanislav Motylkov if (!dwContentLen)
89366e3c1f7SStanislav Motylkov {
8944439b538SMark Jansen // Someone was nice enough to add this, let's use it
8954439b538SMark Jansen if (InfoArray[iAppId].SizeInBytes)
8964439b538SMark Jansen {
8974439b538SMark Jansen dwContentLen = InfoArray[iAppId].SizeInBytes;
8984439b538SMark Jansen }
8994439b538SMark Jansen else
9004439b538SMark Jansen {
90166e3c1f7SStanislav Motylkov // content-length is not known, enable marquee mode
9026803490aSGiannis Adamopoulos ProgressBar.SetMarquee(TRUE);
90366e3c1f7SStanislav Motylkov }
9044439b538SMark Jansen }
90566e3c1f7SStanislav Motylkov
90607f3691cSMark Jansen free(urlComponents.lpszScheme);
90707f3691cSMark Jansen
908c2c66affSColin Finck #ifdef USE_CERT_PINNING
909c2c66affSColin Finck // are we using HTTPS to download the RAPPS update package? check if the certificate is original
91033c2903eSMark Jansen if ((urlComponents.nScheme == INTERNET_SCHEME_HTTPS) && (InfoArray[iAppId].DLType == DLTYPE_DBUPDATE))
911c2c66affSColin Finck {
9124f25a476SMark Jansen CLocalPtr<char> subjectName, issuerName;
91312caaeceSMark Jansen CStringA szMsgText;
91407f3691cSMark Jansen bool bAskQuestion = false;
91507f3691cSMark Jansen if (!CertGetSubjectAndIssuer(hFile, subjectName, issuerName))
91607f3691cSMark Jansen {
91707f3691cSMark Jansen szMsgText.LoadStringW(IDS_UNABLE_TO_QUERY_CERT);
91807f3691cSMark Jansen bAskQuestion = true;
91907f3691cSMark Jansen }
92007f3691cSMark Jansen else
92107f3691cSMark Jansen {
92207f3691cSMark Jansen if (strcmp(subjectName, CERT_SUBJECT_INFO) ||
92333c2903eSMark Jansen (strcmp(issuerName, CERT_ISSUER_INFO_OLD) && strcmp(issuerName, CERT_ISSUER_INFO_NEW)))
92407f3691cSMark Jansen {
92507f3691cSMark Jansen szMsgText.Format(IDS_MISMATCH_CERT_INFO, (char *)subjectName, (const char *)issuerName);
92607f3691cSMark Jansen bAskQuestion = true;
92707f3691cSMark Jansen }
92807f3691cSMark Jansen }
92907f3691cSMark Jansen
93007f3691cSMark Jansen if (bAskQuestion)
93107f3691cSMark Jansen {
93212caaeceSMark Jansen if (MessageBoxA(hMainWnd, szMsgText.GetString(), NULL, MB_YESNO | MB_ICONERROR) != IDYES)
93307f3691cSMark Jansen {
934c2c66affSColin Finck goto end;
935c2c66affSColin Finck }
93607f3691cSMark Jansen }
93707f3691cSMark Jansen }
938c2c66affSColin Finck #endif
939c2c66affSColin Finck
94033c2903eSMark Jansen hOut = CreateFileW(Path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
941c2c66affSColin Finck
942c2c66affSColin Finck if (hOut == INVALID_HANDLE_VALUE)
943fb1582d3SKyle Katarn {
944059ba9b0SStanislav Motylkov ShowLastError(hMainWnd, FALSE, GetLastError());
945c2c66affSColin Finck goto end;
946fb1582d3SKyle Katarn }
947c2c66affSColin Finck
948c2c66affSColin Finck dwCurrentBytesRead = 0;
949c2c66affSColin Finck do
950c2c66affSColin Finck {
951c2c66affSColin Finck if (!InternetReadFile(hFile, lpBuffer, _countof(lpBuffer), &dwBytesRead))
952c2c66affSColin Finck {
953059ba9b0SStanislav Motylkov ShowLastError(hMainWnd, TRUE, GetLastError());
954c2c66affSColin Finck goto end;
955c2c66affSColin Finck }
956c2c66affSColin Finck
957c2c66affSColin Finck if (!WriteFile(hOut, &lpBuffer[0], dwBytesRead, &dwBytesWritten, NULL))
958c2c66affSColin Finck {
959059ba9b0SStanislav Motylkov ShowLastError(hMainWnd, FALSE, GetLastError());
960c2c66affSColin Finck goto end;
961c2c66affSColin Finck }
962c2c66affSColin Finck
963c2c66affSColin Finck dwCurrentBytesRead += dwBytesRead;
96433c2903eSMark Jansen if (!IsWindow(hDlg))
96533c2903eSMark Jansen goto end;
9661e201d70SGiannis Adamopoulos UpdateProgress(hDlg, dwCurrentBytesRead, dwContentLen, 0, InfoArray[iAppId].szUrl.GetString());
967c2c66affSColin Finck } while (dwBytesRead && !bCancelled);
968c2c66affSColin Finck
969c2c66affSColin Finck CloseHandle(hOut);
970c2c66affSColin Finck hOut = INVALID_HANDLE_VALUE;
971c2c66affSColin Finck
972c2c66affSColin Finck if (bCancelled)
973fb1582d3SKyle Katarn {
974fb1582d3SKyle Katarn DPRINT1("Operation cancelled\n");
975c2c66affSColin Finck goto end;
976fb1582d3SKyle Katarn }
977c2c66affSColin Finck
97866e3c1f7SStanislav Motylkov if (!dwContentLen)
97966e3c1f7SStanislav Motylkov {
98066e3c1f7SStanislav Motylkov // set progress bar to 100%
9816803490aSGiannis Adamopoulos ProgressBar.SetMarquee(FALSE);
98266e3c1f7SStanislav Motylkov
98366e3c1f7SStanislav Motylkov dwContentLen = dwCurrentBytesRead;
98433c2903eSMark Jansen if (!IsWindow(hDlg))
98533c2903eSMark Jansen goto end;
9861e201d70SGiannis Adamopoulos UpdateProgress(hDlg, dwCurrentBytesRead, dwContentLen, 0, InfoArray[iAppId].szUrl.GetString());
98766e3c1f7SStanislav Motylkov }
98866e3c1f7SStanislav Motylkov
989c2c66affSColin Finck /* if this thing isn't a RAPPS update and it has a SHA-1 checksum
990c2c66affSColin Finck verify its integrity by using the native advapi32.A_SHA1 functions */
991a21d959eSHe Yang if ((InfoArray[iAppId].DLType == DLTYPE_APPLICATION) && InfoArray[iAppId].szSHA1[0] != 0)
992c2c66affSColin Finck {
99333c2903eSMark Jansen CStringW szMsgText;
994c2c66affSColin Finck
995c2c66affSColin Finck // change a few strings in the download dialog to reflect the verification process
996c2c66affSColin Finck if (!szMsgText.LoadStringW(IDS_INTEG_CHECK_TITLE))
997fb1582d3SKyle Katarn {
998fb1582d3SKyle Katarn DPRINT1("Unable to load string\n");
999c2c66affSColin Finck goto end;
1000fb1582d3SKyle Katarn }
1001c2c66affSColin Finck
100233c2903eSMark Jansen if (!IsWindow(hDlg))
100333c2903eSMark Jansen goto end;
1004c2c66affSColin Finck SetWindowTextW(hDlg, szMsgText.GetString());
100533c2903eSMark Jansen ::SetDlgItemTextW(hDlg, IDC_DOWNLOAD_STATUS, Path);
1006c2c66affSColin Finck
1007c2c66affSColin Finck // this may take a while, depending on the file size
100833c2903eSMark Jansen if (!VerifyInteg(InfoArray[iAppId].szSHA1.GetString(), Path))
1009c2c66affSColin Finck {
1010c2c66affSColin Finck if (!szMsgText.LoadStringW(IDS_INTEG_CHECK_FAIL))
1011fb1582d3SKyle Katarn {
1012fb1582d3SKyle Katarn DPRINT1("Unable to load string\n");
1013c2c66affSColin Finck goto end;
1014fb1582d3SKyle Katarn }
1015c2c66affSColin Finck
101633c2903eSMark Jansen if (!IsWindow(hDlg))
101733c2903eSMark Jansen goto end;
1018c2c66affSColin Finck MessageBoxW(hDlg, szMsgText.GetString(), NULL, MB_OK | MB_ICONERROR);
1019c2c66affSColin Finck goto end;
1020c2c66affSColin Finck }
1021c2c66affSColin Finck }
1022c2c66affSColin Finck
1023c2c66affSColin Finck run:
1024c2c66affSColin Finck DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_WAITING_INSTALL);
1025c2c66affSColin Finck
1026c2c66affSColin Finck // run it
1027a21d959eSHe Yang if (InfoArray[iAppId].DLType == DLTYPE_APPLICATION)
1028c2c66affSColin Finck {
102957b775efSWhindmar Saksit CStringW app, params;
1030c2c66affSColin Finck SHELLEXECUTEINFOW shExInfo = {0};
1031c2c66affSColin Finck shExInfo.cbSize = sizeof(shExInfo);
1032c2c66affSColin Finck shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
1033c2c66affSColin Finck shExInfo.lpVerb = L"open";
103433c2903eSMark Jansen shExInfo.lpFile = Path;
1035c2c66affSColin Finck shExInfo.lpParameters = L"";
1036c2c66affSColin Finck shExInfo.nShow = SW_SHOW;
1037c2c66affSColin Finck
103857b775efSWhindmar Saksit if (InfoArray[iAppId].IType == INSTALLER_GENERATE)
103957b775efSWhindmar Saksit {
104057b775efSWhindmar Saksit params = L"/" + CStringW(CMD_KEY_GENINST) + L" \"" +
104157b775efSWhindmar Saksit InfoArray[iAppId].szPackageName + L"\" \"" +
104257b775efSWhindmar Saksit CStringW(shExInfo.lpFile) + L"\"";
104357b775efSWhindmar Saksit shExInfo.lpParameters = params;
104457b775efSWhindmar Saksit shExInfo.lpFile = app.GetBuffer(MAX_PATH);
104557b775efSWhindmar Saksit GetModuleFileNameW(NULL, const_cast<LPWSTR>(shExInfo.lpFile), MAX_PATH);
104657b775efSWhindmar Saksit app.ReleaseBuffer();
104757b775efSWhindmar Saksit }
104857b775efSWhindmar Saksit
1049ae426744SMark Jansen /* FIXME: Do we want to log installer status? */
1050ae426744SMark Jansen WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_INSTALL, InfoArray[iAppId].szName);
1051ae426744SMark Jansen
1052c2c66affSColin Finck if (ShellExecuteExW(&shExInfo))
1053c2c66affSColin Finck {
105447bbd637SAlexander Shaposhnikov // reflect installation progress in the titlebar
105547bbd637SAlexander Shaposhnikov // TODO: make a separate string with a placeholder to include app name?
105633c2903eSMark Jansen CStringW szMsgText = LoadStatusString(DLSTATUS_INSTALLING);
105733c2903eSMark Jansen if (!IsWindow(hDlg))
105833c2903eSMark Jansen goto end;
105947bbd637SAlexander Shaposhnikov SetWindowTextW(hDlg, szMsgText.GetString());
106047bbd637SAlexander Shaposhnikov
1061c2c66affSColin Finck DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_INSTALLING);
106247bbd637SAlexander Shaposhnikov
1063c2c66affSColin Finck // TODO: issue an install operation separately so that the apps could be downloaded in the background
1064c2c66affSColin Finck WaitForSingleObject(shExInfo.hProcess, INFINITE);
1065c2c66affSColin Finck CloseHandle(shExInfo.hProcess);
1066c2c66affSColin Finck }
1067c2c66affSColin Finck else
1068c2c66affSColin Finck {
1069059ba9b0SStanislav Motylkov ShowLastError(hMainWnd, FALSE, GetLastError());
1070c2c66affSColin Finck }
1071c2c66affSColin Finck }
1072c2c66affSColin Finck
1073c2c66affSColin Finck end:
1074c2c66affSColin Finck if (hOut != INVALID_HANDLE_VALUE)
1075c2c66affSColin Finck CloseHandle(hOut);
1076c2c66affSColin Finck
10774f25a476SMark Jansen if (hFile)
1078c2c66affSColin Finck InternetCloseHandle(hFile);
1079c2c66affSColin Finck InternetCloseHandle(hOpen);
1080c2c66affSColin Finck
1081c2c66affSColin Finck if (bTempfile)
1082c2c66affSColin Finck {
1083a21d959eSHe Yang if (bCancelled || (SettingsInfo.bDelInstaller && (InfoArray[iAppId].DLType == DLTYPE_APPLICATION)))
108433c2903eSMark Jansen DeleteFileW(Path);
1085c2c66affSColin Finck }
1086c2c66affSColin Finck
108733c2903eSMark Jansen if (!IsWindow(hDlg))
108833c2903eSMark Jansen return 0;
1089c2c66affSColin Finck DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_FINISHED);
1090c2c66affSColin Finck }
1091c2c66affSColin Finck
1092c2c66affSColin Finck delete static_cast<DownloadParam *>(param);
109333c2903eSMark Jansen if (!IsWindow(hDlg))
109433c2903eSMark Jansen return 0;
1095c2c66affSColin Finck SendMessageW(hDlg, WM_CLOSE, 0, 0);
1096c2c66affSColin Finck return 0;
1097c2c66affSColin Finck }
1098c2c66affSColin Finck
1099c2c66affSColin Finck // TODO: Reuse the dialog
110033c2903eSMark Jansen VOID
LaunchDownloadDialog(BOOL bIsModal)110133c2903eSMark Jansen CDownloadManager::LaunchDownloadDialog(BOOL bIsModal)
1102c2c66affSColin Finck {
1103946ee611SMark Jansen CDownloadManager::bModal = bIsModal;
1104c2c66affSColin Finck if (bIsModal)
1105c2c66affSColin Finck {
110633c2903eSMark Jansen DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG), hMainWnd, DownloadDlgProc);
1107c2c66affSColin Finck }
1108c2c66affSColin Finck else
1109c2c66affSColin Finck {
111033c2903eSMark Jansen CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG), hMainWnd, DownloadDlgProc);
1111c2c66affSColin Finck }
1112c2c66affSColin Finck }
1113c2c66affSColin Finck // CDownloadManager
11141807dbfdSGiannis Adamopoulos
111533c2903eSMark Jansen BOOL
DownloadListOfApplications(const CAtlList<CAppInfo * > & AppsList,BOOL bIsModal)1116a9b1e059SJoachim Henze DownloadListOfApplications(const CAtlList<CAppInfo *> &AppsList, BOOL bIsModal)
11171807dbfdSGiannis Adamopoulos {
111833c2903eSMark Jansen if (AppsList.IsEmpty())
11191807dbfdSGiannis Adamopoulos return FALSE;
11201807dbfdSGiannis Adamopoulos
112133c2903eSMark Jansen POSITION CurrentListPosition = AppsList.GetHeadPosition();
112233c2903eSMark Jansen while (CurrentListPosition)
11231807dbfdSGiannis Adamopoulos {
1124a9b1e059SJoachim Henze const CAppInfo *Info = AppsList.GetNext(CurrentListPosition);
112533c2903eSMark Jansen CDownloadManager::Add(DownloadInfo(*Info));
11261807dbfdSGiannis Adamopoulos }
11271807dbfdSGiannis Adamopoulos
11281807dbfdSGiannis Adamopoulos // Create a dialog and issue a download process
11291807dbfdSGiannis Adamopoulos CDownloadManager::LaunchDownloadDialog(bIsModal);
11301807dbfdSGiannis Adamopoulos
11311807dbfdSGiannis Adamopoulos return TRUE;
11321807dbfdSGiannis Adamopoulos }
11331807dbfdSGiannis Adamopoulos
113433c2903eSMark Jansen BOOL
DownloadApplication(CAppInfo * pAppInfo)1135a9b1e059SJoachim Henze DownloadApplication(CAppInfo *pAppInfo)
11361807dbfdSGiannis Adamopoulos {
11371807dbfdSGiannis Adamopoulos if (!pAppInfo)
11381807dbfdSGiannis Adamopoulos return FALSE;
11391807dbfdSGiannis Adamopoulos
1140143b2a50SMark Jansen CDownloadManager::Download(*pAppInfo, FALSE);
11411807dbfdSGiannis Adamopoulos return TRUE;
11421807dbfdSGiannis Adamopoulos }
11431807dbfdSGiannis Adamopoulos
114433c2903eSMark Jansen VOID
DownloadApplicationsDB(LPCWSTR lpUrl,BOOL IsOfficial)114533c2903eSMark Jansen DownloadApplicationsDB(LPCWSTR lpUrl, BOOL IsOfficial)
11461807dbfdSGiannis Adamopoulos {
11471807dbfdSGiannis Adamopoulos static DownloadInfo DatabaseDLInfo;
11481807dbfdSGiannis Adamopoulos DatabaseDLInfo.szUrl = lpUrl;
11491807dbfdSGiannis Adamopoulos DatabaseDLInfo.szName.LoadStringW(IDS_DL_DIALOG_DB_DISP);
1150a21d959eSHe Yang DatabaseDLInfo.DLType = IsOfficial ? DLTYPE_DBUPDATE : DLTYPE_DBUPDATE_UNOFFICIAL;
11511807dbfdSGiannis Adamopoulos CDownloadManager::Download(DatabaseDLInfo, TRUE);
11521807dbfdSGiannis Adamopoulos }
1153