xref: /reactos/base/applications/rapps/loaddlg.cpp (revision 8ba61029)
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