xref: /reactos/base/applications/rapps/loaddlg.cpp (revision 33c2903e)
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>
452ac13afeSHe Yang #include <process.h>
466803490aSGiannis Adamopoulos #undef SubclassWindow
47c2c66affSColin Finck 
48c2c66affSColin Finck #include "rosui.h"
49c2c66affSColin Finck #include "dialogs.h"
50c2c66affSColin Finck #include "misc.h"
51c2c66affSColin Finck 
52c2c66affSColin Finck #ifdef USE_CERT_PINNING
53f77f5a30SStanislav Motylkov #define CERT_ISSUER_INFO_OLD "US\r\nLet's Encrypt\r\nLet's Encrypt Authority X3"
54f77f5a30SStanislav Motylkov #define CERT_ISSUER_INFO_NEW "US\r\nLet's Encrypt\r\nR3"
55bb819f15SAlexander Shaposhnikov #define CERT_SUBJECT_INFO "rapps.reactos.org"
56c2c66affSColin Finck #endif
57c2c66affSColin Finck 
58a21d959eSHe Yang enum DownloadType
59a21d959eSHe Yang {
60a21d959eSHe Yang     DLTYPE_APPLICATION,
61a21d959eSHe Yang     DLTYPE_DBUPDATE,
62a21d959eSHe Yang     DLTYPE_DBUPDATE_UNOFFICIAL
63a21d959eSHe Yang };
64a21d959eSHe Yang 
65c2c66affSColin Finck enum DownloadStatus
66c2c66affSColin Finck {
67c2c66affSColin Finck     DLSTATUS_WAITING = IDS_STATUS_WAITING,
68c2c66affSColin Finck     DLSTATUS_DOWNLOADING = IDS_STATUS_DOWNLOADING,
69c2c66affSColin Finck     DLSTATUS_WAITING_INSTALL = IDS_STATUS_DOWNLOADED,
70c2c66affSColin Finck     DLSTATUS_INSTALLING = IDS_STATUS_INSTALLING,
71c2c66affSColin Finck     DLSTATUS_INSTALLED = IDS_STATUS_INSTALLED,
72c2c66affSColin Finck     DLSTATUS_FINISHED = IDS_STATUS_FINISHED
73c2c66affSColin Finck };
74c2c66affSColin Finck 
75*33c2903eSMark Jansen CStringW
76*33c2903eSMark Jansen LoadStatusString(DownloadStatus StatusParam)
77c2c66affSColin Finck {
78*33c2903eSMark Jansen     CStringW szString;
79c2c66affSColin Finck     szString.LoadStringW(StatusParam);
80c2c66affSColin Finck     return szString;
81c2c66affSColin Finck }
82c2c66affSColin Finck 
83c2c66affSColin Finck struct DownloadInfo
84c2c66affSColin Finck {
85*33c2903eSMark Jansen     DownloadInfo()
86c2c66affSColin Finck     {
87c2c66affSColin Finck     }
88*33c2903eSMark Jansen     DownloadInfo(const CApplicationInfo &AppInfo) : DLType(DLTYPE_APPLICATION)
89*33c2903eSMark Jansen     {
90*33c2903eSMark Jansen         AppInfo.GetDownloadInfo(szUrl, szSHA1, SizeInBytes);
91*33c2903eSMark Jansen         szName = AppInfo.szDisplayName;
92*33c2903eSMark Jansen     }
93c2c66affSColin Finck 
94a21d959eSHe Yang     DownloadType DLType;
95*33c2903eSMark Jansen     CStringW szUrl;
96*33c2903eSMark Jansen     CStringW szName;
97*33c2903eSMark Jansen     CStringW szSHA1;
984439b538SMark Jansen     ULONG SizeInBytes;
99c2c66affSColin Finck };
100c2c66affSColin Finck 
101c2c66affSColin Finck struct DownloadParam
102c2c66affSColin Finck {
103*33c2903eSMark Jansen     DownloadParam() : Dialog(NULL), AppInfo(), szCaption(NULL)
104*33c2903eSMark Jansen     {
105*33c2903eSMark Jansen     }
106c2c66affSColin Finck     DownloadParam(HWND dlg, const ATL::CSimpleArray<DownloadInfo> &info, LPCWSTR caption)
107c2c66affSColin Finck         : Dialog(dlg), AppInfo(info), szCaption(caption)
108c2c66affSColin Finck     {
109c2c66affSColin Finck     }
110c2c66affSColin Finck 
111c2c66affSColin Finck     HWND Dialog;
112c2c66affSColin Finck     ATL::CSimpleArray<DownloadInfo> AppInfo;
113c2c66affSColin Finck     LPCWSTR szCaption;
114c2c66affSColin Finck };
115c2c66affSColin Finck 
116*33c2903eSMark Jansen class CDownloaderProgress : public CWindowImpl<CDownloaderProgress, CWindow, CControlWinTraits>
1176803490aSGiannis Adamopoulos {
118*33c2903eSMark Jansen     CStringW m_szProgressText;
1196803490aSGiannis Adamopoulos 
1206803490aSGiannis Adamopoulos   public:
1216803490aSGiannis Adamopoulos     CDownloaderProgress()
1226803490aSGiannis Adamopoulos     {
1236803490aSGiannis Adamopoulos     }
1246803490aSGiannis Adamopoulos 
125*33c2903eSMark Jansen     VOID
126*33c2903eSMark Jansen     SetMarquee(BOOL Enable)
1276803490aSGiannis Adamopoulos     {
1286803490aSGiannis Adamopoulos         if (Enable)
1296803490aSGiannis Adamopoulos             ModifyStyle(0, PBS_MARQUEE, 0);
1306803490aSGiannis Adamopoulos         else
1316803490aSGiannis Adamopoulos             ModifyStyle(PBS_MARQUEE, 0, 0);
1326803490aSGiannis Adamopoulos 
1336803490aSGiannis Adamopoulos         SendMessage(PBM_SETMARQUEE, Enable, 0);
1346803490aSGiannis Adamopoulos     }
1356803490aSGiannis Adamopoulos 
136*33c2903eSMark Jansen     VOID
137*33c2903eSMark Jansen     SetProgress(ULONG ulProgress, ULONG ulProgressMax)
1386803490aSGiannis Adamopoulos     {
1396803490aSGiannis Adamopoulos         WCHAR szProgress[100];
1406803490aSGiannis Adamopoulos 
1416803490aSGiannis Adamopoulos         /* format the bits and bytes into pretty and accessible units... */
1426803490aSGiannis Adamopoulos         StrFormatByteSizeW(ulProgress, szProgress, _countof(szProgress));
1436803490aSGiannis Adamopoulos 
1446803490aSGiannis Adamopoulos         /* use our subclassed progress bar text subroutine */
145*33c2903eSMark Jansen         CStringW ProgressText;
1466803490aSGiannis Adamopoulos 
1476803490aSGiannis Adamopoulos         if (ulProgressMax)
1486803490aSGiannis Adamopoulos         {
1496803490aSGiannis Adamopoulos             /* total size is known */
1506803490aSGiannis Adamopoulos             WCHAR szProgressMax[100];
1516803490aSGiannis Adamopoulos             UINT uiPercentage = ((ULONGLONG)ulProgress * 100) / ulProgressMax;
1526803490aSGiannis Adamopoulos 
1536803490aSGiannis Adamopoulos             /* send the current progress to the progress bar */
154*33c2903eSMark Jansen             if (!IsWindow())
155*33c2903eSMark Jansen                 return;
1566803490aSGiannis Adamopoulos             SendMessage(PBM_SETPOS, uiPercentage, 0);
1576803490aSGiannis Adamopoulos 
1586803490aSGiannis Adamopoulos             /* format total download size */
1596803490aSGiannis Adamopoulos             StrFormatByteSizeW(ulProgressMax, szProgressMax, _countof(szProgressMax));
1606803490aSGiannis Adamopoulos 
1616803490aSGiannis Adamopoulos             /* generate the text on progress bar */
162*33c2903eSMark Jansen             ProgressText.Format(L"%u%% \x2014 %ls / %ls", uiPercentage, szProgress, szProgressMax);
1636803490aSGiannis Adamopoulos         }
1646803490aSGiannis Adamopoulos         else
1656803490aSGiannis Adamopoulos         {
1666803490aSGiannis Adamopoulos             /* send the current progress to the progress bar */
167*33c2903eSMark Jansen             if (!IsWindow())
168*33c2903eSMark Jansen                 return;
1696803490aSGiannis Adamopoulos             SendMessage(PBM_SETPOS, 0, 0);
1706803490aSGiannis Adamopoulos 
1716803490aSGiannis Adamopoulos             /* total size is not known, display only current size */
1726803490aSGiannis Adamopoulos             ProgressText.Format(L"%ls...", szProgress);
1736803490aSGiannis Adamopoulos         }
1746803490aSGiannis Adamopoulos 
1756803490aSGiannis Adamopoulos         /* and finally display it */
176*33c2903eSMark Jansen         if (!IsWindow())
177*33c2903eSMark Jansen             return;
178844d447eSKatayama Hirofumi MZ         SetWindowText(ProgressText.GetString());
1796803490aSGiannis Adamopoulos     }
1806803490aSGiannis Adamopoulos 
181*33c2903eSMark Jansen     LRESULT
182*33c2903eSMark Jansen     OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
183b4114030SKatayama Hirofumi MZ     {
184b4114030SKatayama Hirofumi MZ         return TRUE;
185b4114030SKatayama Hirofumi MZ     }
186b4114030SKatayama Hirofumi MZ 
187*33c2903eSMark Jansen     LRESULT
188*33c2903eSMark Jansen     OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1896803490aSGiannis Adamopoulos     {
1906803490aSGiannis Adamopoulos         PAINTSTRUCT ps;
1916803490aSGiannis Adamopoulos         HDC hDC = BeginPaint(&ps), hdcMem;
1926803490aSGiannis Adamopoulos         HBITMAP hbmMem;
1936803490aSGiannis Adamopoulos         HANDLE hOld;
1946803490aSGiannis Adamopoulos         RECT myRect;
1956803490aSGiannis Adamopoulos         UINT win_width, win_height;
1966803490aSGiannis Adamopoulos 
1976803490aSGiannis Adamopoulos         GetClientRect(&myRect);
1986803490aSGiannis Adamopoulos 
1996803490aSGiannis Adamopoulos         /* grab the progress bar rect size */
2006803490aSGiannis Adamopoulos         win_width = myRect.right - myRect.left;
2016803490aSGiannis Adamopoulos         win_height = myRect.bottom - myRect.top;
2026803490aSGiannis Adamopoulos 
2036803490aSGiannis Adamopoulos         /* create an off-screen DC for double-buffering */
2046803490aSGiannis Adamopoulos         hdcMem = CreateCompatibleDC(hDC);
2056803490aSGiannis Adamopoulos         hbmMem = CreateCompatibleBitmap(hDC, win_width, win_height);
2066803490aSGiannis Adamopoulos 
2076803490aSGiannis Adamopoulos         hOld = SelectObject(hdcMem, hbmMem);
2086803490aSGiannis Adamopoulos 
2096803490aSGiannis Adamopoulos         /* call the original draw code and redirect it to our memory buffer */
2106803490aSGiannis Adamopoulos         DefWindowProc(uMsg, (WPARAM)hdcMem, lParam);
2116803490aSGiannis Adamopoulos 
2126803490aSGiannis Adamopoulos         /* draw our nifty progress text over it */
2136803490aSGiannis Adamopoulos         SelectFont(hdcMem, GetStockFont(DEFAULT_GUI_FONT));
214*33c2903eSMark Jansen         DrawShadowText(
215*33c2903eSMark Jansen             hdcMem, m_szProgressText.GetString(), m_szProgressText.GetLength(), &myRect,
216*33c2903eSMark Jansen             DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE, GetSysColor(COLOR_CAPTIONTEXT),
217*33c2903eSMark Jansen             GetSysColor(COLOR_3DDKSHADOW), 1, 1);
2186803490aSGiannis Adamopoulos 
2196803490aSGiannis Adamopoulos         /* transfer the off-screen DC to the screen */
2206803490aSGiannis Adamopoulos         BitBlt(hDC, 0, 0, win_width, win_height, hdcMem, 0, 0, SRCCOPY);
2216803490aSGiannis Adamopoulos 
2226803490aSGiannis Adamopoulos         /* free the off-screen DC */
2236803490aSGiannis Adamopoulos         SelectObject(hdcMem, hOld);
2246803490aSGiannis Adamopoulos         DeleteObject(hbmMem);
2256803490aSGiannis Adamopoulos         DeleteDC(hdcMem);
2266803490aSGiannis Adamopoulos 
2276803490aSGiannis Adamopoulos         EndPaint(&ps);
2286803490aSGiannis Adamopoulos         return 0;
2296803490aSGiannis Adamopoulos     }
2306803490aSGiannis Adamopoulos 
231*33c2903eSMark Jansen     LRESULT
232*33c2903eSMark Jansen     OnSetText(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2336803490aSGiannis Adamopoulos     {
234b4114030SKatayama Hirofumi MZ         PCWSTR pszText = (PCWSTR)lParam;
235b4114030SKatayama Hirofumi MZ         if (pszText)
2366803490aSGiannis Adamopoulos         {
237b4114030SKatayama Hirofumi MZ             if (m_szProgressText != pszText)
238b4114030SKatayama Hirofumi MZ             {
239b4114030SKatayama Hirofumi MZ                 m_szProgressText = pszText;
240b4114030SKatayama Hirofumi MZ                 InvalidateRect(NULL, TRUE);
2416803490aSGiannis Adamopoulos             }
242b4114030SKatayama Hirofumi MZ         }
243b4114030SKatayama Hirofumi MZ         else
244b4114030SKatayama Hirofumi MZ         {
245b4114030SKatayama Hirofumi MZ             if (!m_szProgressText.IsEmpty())
246b4114030SKatayama Hirofumi MZ             {
247b4114030SKatayama Hirofumi MZ                 m_szProgressText.Empty();
248b4114030SKatayama Hirofumi MZ                 InvalidateRect(NULL, TRUE);
249b4114030SKatayama Hirofumi MZ             }
250b4114030SKatayama Hirofumi MZ         }
251b4114030SKatayama Hirofumi MZ         return TRUE;
2526803490aSGiannis Adamopoulos     }
2536803490aSGiannis Adamopoulos 
2546803490aSGiannis Adamopoulos     BEGIN_MSG_MAP(CDownloaderProgress)
255b4114030SKatayama Hirofumi MZ     MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
2566803490aSGiannis Adamopoulos     MESSAGE_HANDLER(WM_PAINT, OnPaint)
2576803490aSGiannis Adamopoulos     MESSAGE_HANDLER(WM_SETTEXT, OnSetText)
2586803490aSGiannis Adamopoulos     END_MSG_MAP()
2596803490aSGiannis Adamopoulos };
2606803490aSGiannis Adamopoulos 
261*33c2903eSMark Jansen class CDowloadingAppsListView : public CListView
262c2c66affSColin Finck {
263c2c66affSColin Finck   public:
264*33c2903eSMark Jansen     HWND
265*33c2903eSMark Jansen     Create(HWND hwndParent)
266c2c66affSColin Finck     {
267c2c66affSColin Finck         RECT r = {10, 150, 320, 350};
268*33c2903eSMark Jansen         const DWORD style = WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER |
269*33c2903eSMark Jansen                             LVS_NOCOLUMNHEADER;
270c2c66affSColin Finck 
271c2c66affSColin Finck         HWND hwnd = CListView::Create(hwndParent, r, NULL, style, WS_EX_CLIENTEDGE);
272c2c66affSColin Finck 
273c2c66affSColin Finck         AddColumn(0, 150, LVCFMT_LEFT);
274c2c66affSColin Finck         AddColumn(1, 120, LVCFMT_LEFT);
275c2c66affSColin Finck 
276c2c66affSColin Finck         return hwnd;
277c2c66affSColin Finck     }
278c2c66affSColin Finck 
279*33c2903eSMark Jansen     VOID
280*33c2903eSMark Jansen     LoadList(ATL::CSimpleArray<DownloadInfo> arrInfo)
281c2c66affSColin Finck     {
282c2c66affSColin Finck         for (INT i = 0; i < arrInfo.GetSize(); ++i)
283c2c66affSColin Finck         {
284c2c66affSColin Finck             AddRow(i, arrInfo[i].szName.GetString(), DLSTATUS_WAITING);
285c2c66affSColin Finck         }
286c2c66affSColin Finck     }
287c2c66affSColin Finck 
288*33c2903eSMark Jansen     VOID
289*33c2903eSMark Jansen     SetDownloadStatus(INT ItemIndex, DownloadStatus Status)
290c2c66affSColin Finck     {
291*33c2903eSMark Jansen         CStringW szBuffer = LoadStatusString(Status);
29296fba571SGiannis Adamopoulos         SetItemText(ItemIndex, 1, szBuffer.GetString());
293c2c66affSColin Finck     }
294c2c66affSColin Finck 
295*33c2903eSMark Jansen     BOOL
296*33c2903eSMark Jansen     AddItem(INT ItemIndex, LPWSTR lpText)
297c2c66affSColin Finck     {
298c2c66affSColin Finck         LVITEMW Item;
299c2c66affSColin Finck 
300c2c66affSColin Finck         ZeroMemory(&Item, sizeof(Item));
301c2c66affSColin Finck 
302c2c66affSColin Finck         Item.mask = LVIF_TEXT | LVIF_STATE;
303c2c66affSColin Finck         Item.pszText = lpText;
304c2c66affSColin Finck         Item.iItem = ItemIndex;
305c2c66affSColin Finck 
306c2c66affSColin Finck         return InsertItem(&Item);
307c2c66affSColin Finck     }
308c2c66affSColin Finck 
309*33c2903eSMark Jansen     VOID
310*33c2903eSMark Jansen     AddRow(INT RowIndex, LPCWSTR szAppName, const DownloadStatus Status)
311c2c66affSColin Finck     {
312*33c2903eSMark Jansen         CStringW szStatus = LoadStatusString(Status);
313*33c2903eSMark Jansen         AddItem(RowIndex, const_cast<LPWSTR>(szAppName));
314c2c66affSColin Finck         SetDownloadStatus(RowIndex, Status);
315c2c66affSColin Finck     }
316c2c66affSColin Finck 
317*33c2903eSMark Jansen     BOOL
318*33c2903eSMark Jansen     AddColumn(INT Index, INT Width, INT Format)
319c2c66affSColin Finck     {
320c2c66affSColin Finck         LVCOLUMNW Column;
321c2c66affSColin Finck         ZeroMemory(&Column, sizeof(Column));
322c2c66affSColin Finck 
323c2c66affSColin Finck         Column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
324c2c66affSColin Finck         Column.iSubItem = Index;
325c2c66affSColin Finck         Column.cx = Width;
326c2c66affSColin Finck         Column.fmt = Format;
327c2c66affSColin Finck 
328c2c66affSColin Finck         return (InsertColumn(Index, &Column) == -1) ? FALSE : TRUE;
329c2c66affSColin Finck     }
330c2c66affSColin Finck };
331c2c66affSColin Finck 
332c2c66affSColin Finck #ifdef USE_CERT_PINNING
333*33c2903eSMark Jansen static BOOL
334*33c2903eSMark Jansen CertGetSubjectAndIssuer(HINTERNET hFile, CLocalPtr<char> &subjectInfo, CLocalPtr<char> &issuerInfo)
335c2c66affSColin Finck {
336c2c66affSColin Finck     DWORD certInfoLength;
337b56193a2SMark Jansen     INTERNET_CERTIFICATE_INFOA certInfo;
33807f3691cSMark Jansen     DWORD size, flags;
33907f3691cSMark Jansen 
34007f3691cSMark Jansen     size = sizeof(flags);
34107f3691cSMark Jansen     if (!InternetQueryOptionA(hFile, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size))
34207f3691cSMark Jansen     {
34307f3691cSMark Jansen         return FALSE;
34407f3691cSMark Jansen     }
34507f3691cSMark Jansen 
34607f3691cSMark Jansen     if (!flags & SECURITY_FLAG_SECURE)
34707f3691cSMark Jansen     {
34807f3691cSMark Jansen         return FALSE;
34907f3691cSMark Jansen     }
350c2c66affSColin Finck 
351b56193a2SMark Jansen     /* Despite what the header indicates, the implementation of INTERNET_CERTIFICATE_INFO is not Unicode-aware. */
352c2c66affSColin Finck     certInfoLength = sizeof(certInfo);
353*33c2903eSMark Jansen     if (!InternetQueryOptionA(hFile, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, &certInfo, &certInfoLength))
354c2c66affSColin Finck     {
355b56193a2SMark Jansen         return FALSE;
356b56193a2SMark Jansen     }
357b56193a2SMark Jansen 
35807f3691cSMark Jansen     subjectInfo.Attach(certInfo.lpszSubjectInfo);
35907f3691cSMark Jansen     issuerInfo.Attach(certInfo.lpszIssuerInfo);
36007f3691cSMark Jansen 
361c2c66affSColin Finck     if (certInfo.lpszProtocolName)
362c2c66affSColin Finck         LocalFree(certInfo.lpszProtocolName);
363c2c66affSColin Finck     if (certInfo.lpszSignatureAlgName)
364c2c66affSColin Finck         LocalFree(certInfo.lpszSignatureAlgName);
365b56193a2SMark Jansen     if (certInfo.lpszEncryptionAlgName)
366b56193a2SMark Jansen         LocalFree(certInfo.lpszEncryptionAlgName);
367b56193a2SMark Jansen 
36807f3691cSMark Jansen     return certInfo.lpszSubjectInfo && certInfo.lpszIssuerInfo;
369c2c66affSColin Finck }
370c2c66affSColin Finck #endif
371c2c66affSColin Finck 
372*33c2903eSMark Jansen inline VOID
373*33c2903eSMark Jansen MessageBox_LoadString(HWND hMainWnd, INT StringID)
374c2c66affSColin Finck {
375*33c2903eSMark Jansen     CStringW szMsgText;
376c2c66affSColin Finck     if (szMsgText.LoadStringW(StringID))
377c2c66affSColin Finck     {
378c2c66affSColin Finck         MessageBoxW(hMainWnd, szMsgText.GetString(), NULL, MB_OK | MB_ICONERROR);
379c2c66affSColin Finck     }
380c2c66affSColin Finck }
381c2c66affSColin Finck 
3821807dbfdSGiannis Adamopoulos // Download dialog (loaddlg.cpp)
3831807dbfdSGiannis Adamopoulos class CDownloadManager
3841807dbfdSGiannis Adamopoulos {
3854c524ee3S赫杨     static ATL::CSimpleArray<DownloadInfo> AppsDownloadList;
3861807dbfdSGiannis Adamopoulos     static CDowloadingAppsListView DownloadsListView;
3876803490aSGiannis Adamopoulos     static CDownloaderProgress ProgressBar;
388db8f1d6fSGiannis Adamopoulos     static BOOL bCancelled;
389946ee611SMark Jansen     static BOOL bModal;
390*33c2903eSMark Jansen     static VOID
391*33c2903eSMark Jansen     UpdateProgress(HWND hDlg, ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText);
392*33c2903eSMark Jansen 
3931807dbfdSGiannis Adamopoulos   public:
394*33c2903eSMark Jansen     static VOID
395*33c2903eSMark Jansen     Add(DownloadInfo info);
396*33c2903eSMark Jansen     static VOID
397*33c2903eSMark Jansen     Download(const DownloadInfo &DLInfo, BOOL bIsModal = FALSE);
398*33c2903eSMark Jansen     static INT_PTR CALLBACK
399*33c2903eSMark Jansen     DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
400*33c2903eSMark Jansen     static unsigned int WINAPI
401*33c2903eSMark Jansen     ThreadFunc(LPVOID Context);
4021807dbfdSGiannis Adamopoulos     static VOID LaunchDownloadDialog(BOOL);
4031807dbfdSGiannis Adamopoulos };
4041807dbfdSGiannis Adamopoulos 
405c2c66affSColin Finck // CDownloadManager
4064c524ee3S赫杨 ATL::CSimpleArray<DownloadInfo> CDownloadManager::AppsDownloadList;
407c2c66affSColin Finck CDowloadingAppsListView CDownloadManager::DownloadsListView;
4086803490aSGiannis Adamopoulos CDownloaderProgress CDownloadManager::ProgressBar;
409946ee611SMark Jansen BOOL CDownloadManager::bCancelled = FALSE;
410946ee611SMark Jansen BOOL CDownloadManager::bModal = FALSE;
411c2c66affSColin Finck 
412*33c2903eSMark Jansen VOID
413*33c2903eSMark Jansen CDownloadManager::Add(DownloadInfo info)
4141807dbfdSGiannis Adamopoulos {
4154c524ee3S赫杨     AppsDownloadList.Add(info);
4161807dbfdSGiannis Adamopoulos }
4171807dbfdSGiannis Adamopoulos 
418*33c2903eSMark Jansen VOID
419*33c2903eSMark Jansen CDownloadManager::Download(const DownloadInfo &DLInfo, BOOL bIsModal)
420c2c66affSColin Finck {
4214c524ee3S赫杨     AppsDownloadList.RemoveAll();
4224c524ee3S赫杨     AppsDownloadList.Add(DLInfo);
423c2c66affSColin Finck     LaunchDownloadDialog(bIsModal);
424c2c66affSColin Finck }
425c2c66affSColin Finck 
426*33c2903eSMark Jansen INT_PTR CALLBACK
427*33c2903eSMark Jansen CDownloadManager::DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
428c2c66affSColin Finck {
429c2c66affSColin Finck     static WCHAR szCaption[MAX_PATH];
430c2c66affSColin Finck 
431c2c66affSColin Finck     switch (uMsg)
432c2c66affSColin Finck     {
433c2c66affSColin Finck         case WM_INITDIALOG:
434c2c66affSColin Finck         {
435c2c66affSColin Finck             HICON hIconSm, hIconBg;
436*33c2903eSMark Jansen             CStringW szTempCaption;
437c2c66affSColin Finck 
438db8f1d6fSGiannis Adamopoulos             bCancelled = FALSE;
439db8f1d6fSGiannis Adamopoulos 
440a84d2959SHermès Bélusca-Maïto             if (hMainWnd)
441a84d2959SHermès Bélusca-Maïto             {
4426f130666STimo Kreuzer                 hIconBg = (HICON)GetClassLongPtrW(hMainWnd, GCLP_HICON);
4436f130666STimo Kreuzer                 hIconSm = (HICON)GetClassLongPtrW(hMainWnd, GCLP_HICONSM);
444a84d2959SHermès Bélusca-Maïto             }
445a84d2959SHermès Bélusca-Maïto             if (!hMainWnd || (!hIconBg || !hIconSm))
446a84d2959SHermès Bélusca-Maïto             {
447a84d2959SHermès Bélusca-Maïto                 /* Load the default icon */
448a84d2959SHermès Bélusca-Maïto                 hIconBg = hIconSm = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
449a84d2959SHermès Bélusca-Maïto             }
450c2c66affSColin Finck 
451c2c66affSColin Finck             if (hIconBg && hIconSm)
452c2c66affSColin Finck             {
453c2c66affSColin Finck                 SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM)hIconBg);
454c2c66affSColin Finck                 SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
455c2c66affSColin Finck             }
456c2c66affSColin Finck 
457c2c66affSColin Finck             HWND Item = GetDlgItem(Dlg, IDC_DOWNLOAD_PROGRESS);
458c2c66affSColin Finck             if (Item)
459c2c66affSColin Finck             {
460c2c66affSColin Finck                 // initialize the default values for our nifty progress bar
461c2c66affSColin Finck                 // and subclass it so that it learns to print a status text
4626803490aSGiannis Adamopoulos                 ProgressBar.SubclassWindow(Item);
4636803490aSGiannis Adamopoulos                 ProgressBar.SendMessage(PBM_SETRANGE, 0, MAKELPARAM(0, 100));
4646803490aSGiannis Adamopoulos                 ProgressBar.SendMessage(PBM_SETPOS, 0, 0);
465b4114030SKatayama Hirofumi MZ                 if (AppsDownloadList.GetSize() > 0)
466b4114030SKatayama Hirofumi MZ                     ProgressBar.SetProgress(0, AppsDownloadList[0].SizeInBytes);
467c2c66affSColin Finck             }
468c2c66affSColin Finck 
469c2c66affSColin Finck             // Add a ListView
470c2c66affSColin Finck             HWND hListView = DownloadsListView.Create(Dlg);
471c2c66affSColin Finck             if (!hListView)
472c2c66affSColin Finck             {
473c2c66affSColin Finck                 return FALSE;
474c2c66affSColin Finck             }
4754c524ee3S赫杨             DownloadsListView.LoadList(AppsDownloadList);
476c2c66affSColin Finck 
477c2c66affSColin Finck             // Get a dlg string for later use
47826ac8ac8SHermès Bélusca-Maïto             GetWindowTextW(Dlg, szCaption, _countof(szCaption));
479c2c66affSColin Finck 
480ee019e12SAlexander Shaposhnikov             // Hide a placeholder from displaying
481ee019e12SAlexander Shaposhnikov             szTempCaption = szCaption;
482ee019e12SAlexander Shaposhnikov             szTempCaption.Replace(L"%ls", L"");
483ee019e12SAlexander Shaposhnikov             SetWindowText(Dlg, szTempCaption.GetString());
484ee019e12SAlexander Shaposhnikov 
485ee019e12SAlexander Shaposhnikov             ShowWindow(Dlg, SW_SHOW);
486ee019e12SAlexander Shaposhnikov 
487c2c66affSColin Finck             // Start download process
4884c524ee3S赫杨             DownloadParam *param = new DownloadParam(Dlg, AppsDownloadList, szCaption);
4892ac13afeSHe Yang             unsigned int ThreadId;
4902ac13afeSHe Yang             HANDLE Thread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (void *)param, 0, &ThreadId);
491c2c66affSColin Finck             if (!Thread)
492c2c66affSColin Finck             {
493c2c66affSColin Finck                 return FALSE;
494c2c66affSColin Finck             }
495c2c66affSColin Finck 
496c2c66affSColin Finck             CloseHandle(Thread);
4974c524ee3S赫杨             AppsDownloadList.RemoveAll();
498c2c66affSColin Finck             return TRUE;
499c2c66affSColin Finck         }
500c2c66affSColin Finck 
501c2c66affSColin Finck         case WM_COMMAND:
502c2c66affSColin Finck             if (wParam == IDCANCEL)
503c2c66affSColin Finck             {
504db8f1d6fSGiannis Adamopoulos                 bCancelled = TRUE;
505c2c66affSColin Finck                 PostMessageW(Dlg, WM_CLOSE, 0, 0);
506c2c66affSColin Finck             }
507c2c66affSColin Finck             return FALSE;
508c2c66affSColin Finck 
509c2c66affSColin Finck         case WM_CLOSE:
510b4114030SKatayama Hirofumi MZ             if (ProgressBar)
511b4114030SKatayama Hirofumi MZ                 ProgressBar.UnsubclassWindow(TRUE);
512946ee611SMark Jansen             if (CDownloadManager::bModal)
513946ee611SMark Jansen             {
514946ee611SMark Jansen                 ::EndDialog(Dlg, 0);
515946ee611SMark Jansen             }
516946ee611SMark Jansen             else
517946ee611SMark Jansen             {
518946ee611SMark Jansen                 ::DestroyWindow(Dlg);
519946ee611SMark Jansen             }
520c2c66affSColin Finck             return TRUE;
521c2c66affSColin Finck 
522c2c66affSColin Finck         default:
523c2c66affSColin Finck             return FALSE;
524c2c66affSColin Finck     }
525c2c66affSColin Finck }
526c2c66affSColin Finck 
5271e201d70SGiannis Adamopoulos BOOL UrlHasBeenCopied;
5281e201d70SGiannis Adamopoulos 
529*33c2903eSMark Jansen VOID
530*33c2903eSMark Jansen CDownloadManager::UpdateProgress(
5311e201d70SGiannis Adamopoulos     HWND hDlg,
5321e201d70SGiannis Adamopoulos     ULONG ulProgress,
5331e201d70SGiannis Adamopoulos     ULONG ulProgressMax,
5341e201d70SGiannis Adamopoulos     ULONG ulStatusCode,
5351e201d70SGiannis Adamopoulos     LPCWSTR szStatusText)
5361e201d70SGiannis Adamopoulos {
5371e201d70SGiannis Adamopoulos     HWND Item;
5381e201d70SGiannis Adamopoulos 
539*33c2903eSMark Jansen     if (!IsWindow(hDlg))
540*33c2903eSMark Jansen         return;
5411e201d70SGiannis Adamopoulos     ProgressBar.SetProgress(ulProgress, ulProgressMax);
5421e201d70SGiannis Adamopoulos 
543*33c2903eSMark Jansen     if (!IsWindow(hDlg))
544*33c2903eSMark Jansen         return;
5451e201d70SGiannis Adamopoulos     Item = GetDlgItem(hDlg, IDC_DOWNLOAD_STATUS);
5461e201d70SGiannis Adamopoulos     if (Item && szStatusText && wcslen(szStatusText) > 0 && UrlHasBeenCopied == FALSE)
5471e201d70SGiannis Adamopoulos     {
5481e201d70SGiannis Adamopoulos         SIZE_T len = wcslen(szStatusText) + 1;
549*33c2903eSMark Jansen         CStringW buf;
5501e201d70SGiannis Adamopoulos         DWORD dummyLen;
5511e201d70SGiannis Adamopoulos 
5521e201d70SGiannis Adamopoulos         /* beautify our url for display purposes */
5531e201d70SGiannis Adamopoulos         if (!InternetCanonicalizeUrlW(szStatusText, buf.GetBuffer(len), &dummyLen, ICU_DECODE | ICU_NO_ENCODE))
5541e201d70SGiannis Adamopoulos         {
5551e201d70SGiannis Adamopoulos             /* just use the original */
5561e201d70SGiannis Adamopoulos             buf.ReleaseBuffer();
5571e201d70SGiannis Adamopoulos             buf = szStatusText;
5581e201d70SGiannis Adamopoulos         }
5591e201d70SGiannis Adamopoulos         else
5601e201d70SGiannis Adamopoulos         {
5611e201d70SGiannis Adamopoulos             buf.ReleaseBuffer();
5621e201d70SGiannis Adamopoulos         }
5631e201d70SGiannis Adamopoulos 
5641e201d70SGiannis Adamopoulos         /* paste it into our dialog and don't do it again in this instance */
565844d447eSKatayama Hirofumi MZ         ::SetWindowText(Item, buf.GetString());
5661e201d70SGiannis Adamopoulos         UrlHasBeenCopied = TRUE;
5671e201d70SGiannis Adamopoulos     }
5681e201d70SGiannis Adamopoulos }
5691e201d70SGiannis Adamopoulos 
570*33c2903eSMark Jansen BOOL
571*33c2903eSMark Jansen ShowLastError(HWND hWndOwner, BOOL bInetError, DWORD dwLastError)
572fb1582d3SKyle Katarn {
5734f25a476SMark Jansen     CLocalPtr<WCHAR> lpMsg;
574fb1582d3SKyle Katarn 
575*33c2903eSMark Jansen     if (!FormatMessageW(
576*33c2903eSMark Jansen             FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS |
577059ba9b0SStanislav Motylkov                 (bInetError ? FORMAT_MESSAGE_FROM_HMODULE : FORMAT_MESSAGE_FROM_SYSTEM),
578*33c2903eSMark Jansen             (bInetError ? GetModuleHandleW(L"wininet.dll") : NULL), dwLastError, LANG_USER_DEFAULT, (LPWSTR)&lpMsg, 0,
579*33c2903eSMark Jansen             NULL))
580fb1582d3SKyle Katarn     {
581059ba9b0SStanislav Motylkov         DPRINT1("FormatMessageW unexpected failure (err %d)\n", GetLastError());
582059ba9b0SStanislav Motylkov         return FALSE;
583fb1582d3SKyle Katarn     }
584fb1582d3SKyle Katarn 
585fb1582d3SKyle Katarn     MessageBoxW(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR);
586059ba9b0SStanislav Motylkov     return TRUE;
587fb1582d3SKyle Katarn }
588fb1582d3SKyle Katarn 
589*33c2903eSMark Jansen unsigned int WINAPI
590*33c2903eSMark Jansen CDownloadManager::ThreadFunc(LPVOID param)
591c2c66affSColin Finck {
592*33c2903eSMark Jansen     CPathW Path;
593c2c66affSColin Finck     PWSTR p, q;
594c2c66affSColin Finck 
595c2c66affSColin Finck     HWND hDlg = static_cast<DownloadParam *>(param)->Dialog;
596c2c66affSColin Finck     HWND Item;
597c2c66affSColin Finck     INT iAppId;
598c2c66affSColin Finck 
599c2c66affSColin Finck     ULONG dwContentLen, dwBytesWritten, dwBytesRead, dwStatus;
600c2c66affSColin Finck     ULONG dwCurrentBytesRead = 0;
601c2c66affSColin Finck     ULONG dwStatusLen = sizeof(dwStatus);
602c2c66affSColin Finck 
603c2c66affSColin Finck     BOOL bTempfile = FALSE;
604c2c66affSColin Finck 
605c2c66affSColin Finck     HINTERNET hOpen = NULL;
606c2c66affSColin Finck     HINTERNET hFile = NULL;
607c2c66affSColin Finck     HANDLE hOut = INVALID_HANDLE_VALUE;
608c2c66affSColin Finck 
609c2c66affSColin Finck     unsigned char lpBuffer[4096];
61012489f69SMark Jansen     LPCWSTR lpszAgent = L"RApps/1.1";
611e5336bd2SHe Yang     URL_COMPONENTSW urlComponents;
612c2c66affSColin Finck     size_t urlLength, filenameLength;
613c2c66affSColin Finck 
614c2c66affSColin Finck     const ATL::CSimpleArray<DownloadInfo> &InfoArray = static_cast<DownloadParam *>(param)->AppInfo;
615c2c66affSColin Finck     LPCWSTR szCaption = static_cast<DownloadParam *>(param)->szCaption;
616*33c2903eSMark Jansen     CStringW szNewCaption;
617c2c66affSColin Finck 
618*33c2903eSMark Jansen     const DWORD dwUrlConnectFlags =
619*33c2903eSMark Jansen         INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_KEEP_CONNECTION;
620a6d2172cSAlexander Shaposhnikov 
621c2c66affSColin Finck     if (InfoArray.GetSize() <= 0)
622c2c66affSColin Finck     {
623c2c66affSColin Finck         MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD);
624c2c66affSColin Finck         goto end;
625c2c66affSColin Finck     }
626c2c66affSColin Finck 
627c2c66affSColin Finck     for (iAppId = 0; iAppId < InfoArray.GetSize(); ++iAppId)
628c2c66affSColin Finck     {
629ee019e12SAlexander Shaposhnikov         // Reset progress bar
630*33c2903eSMark Jansen         if (!IsWindow(hDlg))
631*33c2903eSMark Jansen             break;
632ee019e12SAlexander Shaposhnikov         Item = GetDlgItem(hDlg, IDC_DOWNLOAD_PROGRESS);
633ee019e12SAlexander Shaposhnikov         if (Item)
634ee019e12SAlexander Shaposhnikov         {
6356803490aSGiannis Adamopoulos             ProgressBar.SetMarquee(FALSE);
6366803490aSGiannis Adamopoulos             ProgressBar.SendMessage(PBM_SETPOS, 0, 0);
637b4114030SKatayama Hirofumi MZ             ProgressBar.SetProgress(0, InfoArray[iAppId].SizeInBytes);
638ee019e12SAlexander Shaposhnikov         }
639ee019e12SAlexander Shaposhnikov 
64007f3691cSMark Jansen         // is this URL an update package for RAPPS? if so store it in a different place
641a21d959eSHe Yang         if (InfoArray[iAppId].DLType != DLTYPE_APPLICATION)
64207f3691cSMark Jansen         {
64307f3691cSMark Jansen             if (!GetStorageDirectory(Path))
644fb1582d3SKyle Katarn             {
645059ba9b0SStanislav Motylkov                 ShowLastError(hMainWnd, FALSE, GetLastError());
64607f3691cSMark Jansen                 goto end;
64707f3691cSMark Jansen             }
648fb1582d3SKyle Katarn         }
64907f3691cSMark Jansen         else
65007f3691cSMark Jansen         {
65107f3691cSMark Jansen             Path = SettingsInfo.szDownloadDir;
65207f3691cSMark Jansen         }
65307f3691cSMark Jansen 
654ee019e12SAlexander Shaposhnikov         // Change caption to show the currently downloaded app
655a21d959eSHe Yang         switch (InfoArray[iAppId].DLType)
656ee019e12SAlexander Shaposhnikov         {
657a21d959eSHe Yang             case DLTYPE_APPLICATION:
658ee019e12SAlexander Shaposhnikov                 szNewCaption.Format(szCaption, InfoArray[iAppId].szName.GetString());
659a21d959eSHe Yang                 break;
660a21d959eSHe Yang             case DLTYPE_DBUPDATE:
661ee019e12SAlexander Shaposhnikov                 szNewCaption.LoadStringW(IDS_DL_DIALOG_DB_DOWNLOAD_DISP);
662a21d959eSHe Yang                 break;
663a21d959eSHe Yang             case DLTYPE_DBUPDATE_UNOFFICIAL:
664a21d959eSHe Yang                 szNewCaption.LoadStringW(IDS_DL_DIALOG_DB_UNOFFICIAL_DOWNLOAD_DISP);
665a21d959eSHe Yang                 break;
666ee019e12SAlexander Shaposhnikov         }
667ee019e12SAlexander Shaposhnikov 
668*33c2903eSMark Jansen         if (!IsWindow(hDlg))
669*33c2903eSMark Jansen             goto end;
670ee019e12SAlexander Shaposhnikov         SetWindowTextW(hDlg, szNewCaption.GetString());
671ee019e12SAlexander Shaposhnikov 
672c2c66affSColin Finck         // build the path for the download
673c2c66affSColin Finck         p = wcsrchr(InfoArray[iAppId].szUrl.GetString(), L'/');
674c2c66affSColin Finck         q = wcsrchr(InfoArray[iAppId].szUrl.GetString(), L'?');
675c2c66affSColin Finck 
676c2c66affSColin Finck         // do we have a final slash separator?
677c2c66affSColin Finck         if (!p)
678fb1582d3SKyle Katarn         {
679fb1582d3SKyle Katarn             MessageBox_LoadString(hMainWnd, IDS_UNABLE_PATH);
680c2c66affSColin Finck             goto end;
681fb1582d3SKyle Katarn         }
682c2c66affSColin Finck 
683c2c66affSColin Finck         // prepare the tentative length of the filename, maybe we've to remove part of it later on
684c2c66affSColin Finck         filenameLength = wcslen(p) * sizeof(WCHAR);
685c2c66affSColin Finck 
686c2c66affSColin Finck         /* do we have query arguments in the target URL after the filename? account for them
687c2c66affSColin Finck         (e.g. https://example.org/myfile.exe?no_adware_plz) */
688c2c66affSColin Finck         if (q && q > p && (q - p) > 0)
689c2c66affSColin Finck             filenameLength -= wcslen(q - 1) * sizeof(WCHAR);
690c2c66affSColin Finck 
691c2c66affSColin Finck         // is the path valid? can we access it?
692*33c2903eSMark Jansen         if (GetFileAttributesW(Path) == INVALID_FILE_ATTRIBUTES)
693c2c66affSColin Finck         {
694*33c2903eSMark Jansen             if (!CreateDirectoryW(Path, NULL))
695fb1582d3SKyle Katarn             {
696059ba9b0SStanislav Motylkov                 ShowLastError(hMainWnd, FALSE, GetLastError());
697c2c66affSColin Finck                 goto end;
698c2c66affSColin Finck             }
699fb1582d3SKyle Katarn         }
700c2c66affSColin Finck 
701fbf119fdSHe Yang         switch (InfoArray[iAppId].DLType)
702fbf119fdSHe Yang         {
703fbf119fdSHe Yang             case DLTYPE_DBUPDATE:
704fbf119fdSHe Yang             case DLTYPE_DBUPDATE_UNOFFICIAL:
705*33c2903eSMark Jansen                 Path += APPLICATION_DATABASE_NAME;
706fbf119fdSHe Yang                 break;
707fbf119fdSHe Yang             case DLTYPE_APPLICATION:
708*33c2903eSMark Jansen                 Path += (LPWSTR)(p + 1); // use the filename retrieved from URL
709fbf119fdSHe Yang                 break;
710fbf119fdSHe Yang         }
711c2c66affSColin Finck 
712*33c2903eSMark Jansen         if ((InfoArray[iAppId].DLType == DLTYPE_APPLICATION) && InfoArray[iAppId].szSHA1[0] &&
713*33c2903eSMark Jansen             GetFileAttributesW(Path) != INVALID_FILE_ATTRIBUTES)
714c2c66affSColin Finck         {
715c2c66affSColin Finck             // only open it in case of total correctness
716c2c66affSColin Finck             if (VerifyInteg(InfoArray[iAppId].szSHA1.GetString(), Path))
717c2c66affSColin Finck                 goto run;
718c2c66affSColin Finck         }
719c2c66affSColin Finck 
720c2c66affSColin Finck         // Add the download URL
721*33c2903eSMark Jansen         if (!IsWindow(hDlg))
722*33c2903eSMark Jansen             goto end;
723c2c66affSColin Finck         SetDlgItemTextW(hDlg, IDC_DOWNLOAD_STATUS, InfoArray[iAppId].szUrl.GetString());
724c2c66affSColin Finck 
725c2c66affSColin Finck         DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_DOWNLOADING);
726c2c66affSColin Finck 
727c2c66affSColin Finck         // download it
7281e201d70SGiannis Adamopoulos         UrlHasBeenCopied = FALSE;
729c2c66affSColin Finck         bTempfile = TRUE;
730c2c66affSColin Finck 
731c2c66affSColin Finck         /* FIXME: this should just be using the system-wide proxy settings */
732c2c66affSColin Finck         switch (SettingsInfo.Proxy)
733c2c66affSColin Finck         {
734c2c66affSColin Finck             case 0: // preconfig
73507f3691cSMark Jansen             default:
736c2c66affSColin Finck                 hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
737c2c66affSColin Finck                 break;
738c2c66affSColin Finck             case 1: // direct (no proxy)
739c2c66affSColin Finck                 hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
740c2c66affSColin Finck                 break;
741c2c66affSColin Finck             case 2: // use proxy
742*33c2903eSMark Jansen                 hOpen = InternetOpenW(
743*33c2903eSMark Jansen                     lpszAgent, INTERNET_OPEN_TYPE_PROXY, SettingsInfo.szProxyServer, SettingsInfo.szNoProxyFor, 0);
744c2c66affSColin Finck                 break;
745c2c66affSColin Finck         }
746c2c66affSColin Finck 
747c2c66affSColin Finck         if (!hOpen)
748fb1582d3SKyle Katarn         {
749059ba9b0SStanislav Motylkov             ShowLastError(hMainWnd, TRUE, GetLastError());
750c2c66affSColin Finck             goto end;
751fb1582d3SKyle Katarn         }
752c2c66affSColin Finck 
753c2c66affSColin Finck         dwStatusLen = sizeof(dwStatus);
754c2c66affSColin Finck 
755c2c66affSColin Finck         memset(&urlComponents, 0, sizeof(urlComponents));
756c2c66affSColin Finck         urlComponents.dwStructSize = sizeof(urlComponents);
757c2c66affSColin Finck 
758c2c66affSColin Finck         urlLength = InfoArray[iAppId].szUrl.GetLength();
759c2c66affSColin Finck         urlComponents.dwSchemeLength = urlLength + 1;
760c2c66affSColin Finck         urlComponents.lpszScheme = (LPWSTR)malloc(urlComponents.dwSchemeLength * sizeof(WCHAR));
761c2c66affSColin Finck 
762c2c66affSColin Finck         if (!InternetCrackUrlW(InfoArray[iAppId].szUrl, urlLength + 1, ICU_DECODE | ICU_ESCAPE, &urlComponents))
763fb1582d3SKyle Katarn         {
764059ba9b0SStanislav Motylkov             ShowLastError(hMainWnd, TRUE, GetLastError());
765c2c66affSColin Finck             goto end;
766fb1582d3SKyle Katarn         }
767c2c66affSColin Finck 
76866e3c1f7SStanislav Motylkov         dwContentLen = 0;
76966e3c1f7SStanislav Motylkov 
770*33c2903eSMark Jansen         if (urlComponents.nScheme == INTERNET_SCHEME_HTTP || urlComponents.nScheme == INTERNET_SCHEME_HTTPS)
7713261bbb7SAlexander Shaposhnikov         {
772*33c2903eSMark Jansen             hFile = InternetOpenUrlW(hOpen, InfoArray[iAppId].szUrl.GetString(), NULL, 0, dwUrlConnectFlags, 0);
773a6d2172cSAlexander Shaposhnikov             if (!hFile)
774a6d2172cSAlexander Shaposhnikov             {
775059ba9b0SStanislav Motylkov                 if (!ShowLastError(hMainWnd, TRUE, GetLastError()))
776059ba9b0SStanislav Motylkov                 {
777059ba9b0SStanislav Motylkov                     /* Workaround for CORE-17377 */
778059ba9b0SStanislav Motylkov                     MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD2);
779059ba9b0SStanislav Motylkov                 }
780a6d2172cSAlexander Shaposhnikov                 goto end;
781a6d2172cSAlexander Shaposhnikov             }
782a6d2172cSAlexander Shaposhnikov 
7833261bbb7SAlexander Shaposhnikov             // query connection
7843261bbb7SAlexander Shaposhnikov             if (!HttpQueryInfoW(hFile, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwStatusLen, NULL))
785fb1582d3SKyle Katarn             {
786059ba9b0SStanislav Motylkov                 ShowLastError(hMainWnd, TRUE, GetLastError());
7873261bbb7SAlexander Shaposhnikov                 goto end;
788fb1582d3SKyle Katarn             }
7893261bbb7SAlexander Shaposhnikov 
7903261bbb7SAlexander Shaposhnikov             if (dwStatus != HTTP_STATUS_OK)
7913261bbb7SAlexander Shaposhnikov             {
7923261bbb7SAlexander Shaposhnikov                 MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD);
7933261bbb7SAlexander Shaposhnikov                 goto end;
7943261bbb7SAlexander Shaposhnikov             }
7953261bbb7SAlexander Shaposhnikov 
7963261bbb7SAlexander Shaposhnikov             // query content length
797*33c2903eSMark Jansen             HttpQueryInfoW(
798*33c2903eSMark Jansen                 hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwContentLen, &dwStatusLen, NULL);
7993261bbb7SAlexander Shaposhnikov         }
8004439b538SMark Jansen         else if (urlComponents.nScheme == INTERNET_SCHEME_FTP)
8013261bbb7SAlexander Shaposhnikov         {
802a6d2172cSAlexander Shaposhnikov             // force passive mode on FTP
803*33c2903eSMark Jansen             hFile =
804*33c2903eSMark Jansen                 InternetOpenUrlW(hOpen, InfoArray[iAppId].szUrl, NULL, 0, dwUrlConnectFlags | INTERNET_FLAG_PASSIVE, 0);
805a6d2172cSAlexander Shaposhnikov             if (!hFile)
806a6d2172cSAlexander Shaposhnikov             {
807059ba9b0SStanislav Motylkov                 if (!ShowLastError(hMainWnd, TRUE, GetLastError()))
808059ba9b0SStanislav Motylkov                 {
809059ba9b0SStanislav Motylkov                     /* Workaround for CORE-17377 */
810059ba9b0SStanislav Motylkov                     MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD2);
811059ba9b0SStanislav Motylkov                 }
812a6d2172cSAlexander Shaposhnikov                 goto end;
813a6d2172cSAlexander Shaposhnikov             }
814a6d2172cSAlexander Shaposhnikov 
815c2c66affSColin Finck             dwContentLen = FtpGetFileSize(hFile, &dwStatus);
8163261bbb7SAlexander Shaposhnikov         }
8174f25a476SMark Jansen         else if (urlComponents.nScheme == INTERNET_SCHEME_FILE)
8184f25a476SMark Jansen         {
8194f25a476SMark Jansen             // Add support for the file scheme so testing locally is simpler
8204f25a476SMark Jansen             WCHAR LocalFilePath[MAX_PATH];
8214f25a476SMark Jansen             DWORD cchPath = _countof(LocalFilePath);
8224f25a476SMark Jansen             // Ideally we would use PathCreateFromUrlAlloc here, but that is not exported (yet)
8234f25a476SMark Jansen             HRESULT hr = PathCreateFromUrlW(InfoArray[iAppId].szUrl, LocalFilePath, &cchPath, 0);
8244f25a476SMark Jansen             if (SUCCEEDED(hr))
8254f25a476SMark Jansen             {
8264f25a476SMark Jansen                 if (CopyFileW(LocalFilePath, Path, FALSE))
8274f25a476SMark Jansen                 {
8284f25a476SMark Jansen                     goto run;
8294f25a476SMark Jansen                 }
8304f25a476SMark Jansen                 else
8314f25a476SMark Jansen                 {
832059ba9b0SStanislav Motylkov                     ShowLastError(hMainWnd, FALSE, GetLastError());
8334f25a476SMark Jansen                     goto end;
8344f25a476SMark Jansen                 }
8354f25a476SMark Jansen             }
8364f25a476SMark Jansen             else
8374f25a476SMark Jansen             {
838059ba9b0SStanislav Motylkov                 ShowLastError(hMainWnd, FALSE, hr);
8394f25a476SMark Jansen                 goto end;
8404f25a476SMark Jansen             }
8414f25a476SMark Jansen         }
842c2c66affSColin Finck 
84366e3c1f7SStanislav Motylkov         if (!dwContentLen)
84466e3c1f7SStanislav Motylkov         {
8454439b538SMark Jansen             // Someone was nice enough to add this, let's use it
8464439b538SMark Jansen             if (InfoArray[iAppId].SizeInBytes)
8474439b538SMark Jansen             {
8484439b538SMark Jansen                 dwContentLen = InfoArray[iAppId].SizeInBytes;
8494439b538SMark Jansen             }
8504439b538SMark Jansen             else
8514439b538SMark Jansen             {
85266e3c1f7SStanislav Motylkov                 // content-length is not known, enable marquee mode
8536803490aSGiannis Adamopoulos                 ProgressBar.SetMarquee(TRUE);
85466e3c1f7SStanislav Motylkov             }
8554439b538SMark Jansen         }
85666e3c1f7SStanislav Motylkov 
85707f3691cSMark Jansen         free(urlComponents.lpszScheme);
85807f3691cSMark Jansen 
859c2c66affSColin Finck #ifdef USE_CERT_PINNING
860c2c66affSColin Finck         // are we using HTTPS to download the RAPPS update package? check if the certificate is original
861*33c2903eSMark Jansen         if ((urlComponents.nScheme == INTERNET_SCHEME_HTTPS) && (InfoArray[iAppId].DLType == DLTYPE_DBUPDATE))
862c2c66affSColin Finck         {
8634f25a476SMark Jansen             CLocalPtr<char> subjectName, issuerName;
86412caaeceSMark Jansen             CStringA szMsgText;
86507f3691cSMark Jansen             bool bAskQuestion = false;
86607f3691cSMark Jansen             if (!CertGetSubjectAndIssuer(hFile, subjectName, issuerName))
86707f3691cSMark Jansen             {
86807f3691cSMark Jansen                 szMsgText.LoadStringW(IDS_UNABLE_TO_QUERY_CERT);
86907f3691cSMark Jansen                 bAskQuestion = true;
87007f3691cSMark Jansen             }
87107f3691cSMark Jansen             else
87207f3691cSMark Jansen             {
87307f3691cSMark Jansen                 if (strcmp(subjectName, CERT_SUBJECT_INFO) ||
874*33c2903eSMark Jansen                     (strcmp(issuerName, CERT_ISSUER_INFO_OLD) && strcmp(issuerName, CERT_ISSUER_INFO_NEW)))
87507f3691cSMark Jansen                 {
87607f3691cSMark Jansen                     szMsgText.Format(IDS_MISMATCH_CERT_INFO, (char *)subjectName, (const char *)issuerName);
87707f3691cSMark Jansen                     bAskQuestion = true;
87807f3691cSMark Jansen                 }
87907f3691cSMark Jansen             }
88007f3691cSMark Jansen 
88107f3691cSMark Jansen             if (bAskQuestion)
88207f3691cSMark Jansen             {
88312caaeceSMark Jansen                 if (MessageBoxA(hMainWnd, szMsgText.GetString(), NULL, MB_YESNO | MB_ICONERROR) != IDYES)
88407f3691cSMark Jansen                 {
885c2c66affSColin Finck                     goto end;
886c2c66affSColin Finck                 }
88707f3691cSMark Jansen             }
88807f3691cSMark Jansen         }
889c2c66affSColin Finck #endif
890c2c66affSColin Finck 
891*33c2903eSMark Jansen         hOut = CreateFileW(Path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
892c2c66affSColin Finck 
893c2c66affSColin Finck         if (hOut == INVALID_HANDLE_VALUE)
894fb1582d3SKyle Katarn         {
895059ba9b0SStanislav Motylkov             ShowLastError(hMainWnd, FALSE, GetLastError());
896c2c66affSColin Finck             goto end;
897fb1582d3SKyle Katarn         }
898c2c66affSColin Finck 
899c2c66affSColin Finck         dwCurrentBytesRead = 0;
900c2c66affSColin Finck         do
901c2c66affSColin Finck         {
902c2c66affSColin Finck             if (!InternetReadFile(hFile, lpBuffer, _countof(lpBuffer), &dwBytesRead))
903c2c66affSColin Finck             {
904059ba9b0SStanislav Motylkov                 ShowLastError(hMainWnd, TRUE, GetLastError());
905c2c66affSColin Finck                 goto end;
906c2c66affSColin Finck             }
907c2c66affSColin Finck 
908c2c66affSColin Finck             if (!WriteFile(hOut, &lpBuffer[0], dwBytesRead, &dwBytesWritten, NULL))
909c2c66affSColin Finck             {
910059ba9b0SStanislav Motylkov                 ShowLastError(hMainWnd, FALSE, GetLastError());
911c2c66affSColin Finck                 goto end;
912c2c66affSColin Finck             }
913c2c66affSColin Finck 
914c2c66affSColin Finck             dwCurrentBytesRead += dwBytesRead;
915*33c2903eSMark Jansen             if (!IsWindow(hDlg))
916*33c2903eSMark Jansen                 goto end;
9171e201d70SGiannis Adamopoulos             UpdateProgress(hDlg, dwCurrentBytesRead, dwContentLen, 0, InfoArray[iAppId].szUrl.GetString());
918c2c66affSColin Finck         } while (dwBytesRead && !bCancelled);
919c2c66affSColin Finck 
920c2c66affSColin Finck         CloseHandle(hOut);
921c2c66affSColin Finck         hOut = INVALID_HANDLE_VALUE;
922c2c66affSColin Finck 
923c2c66affSColin Finck         if (bCancelled)
924fb1582d3SKyle Katarn         {
925fb1582d3SKyle Katarn             DPRINT1("Operation cancelled\n");
926c2c66affSColin Finck             goto end;
927fb1582d3SKyle Katarn         }
928c2c66affSColin Finck 
92966e3c1f7SStanislav Motylkov         if (!dwContentLen)
93066e3c1f7SStanislav Motylkov         {
93166e3c1f7SStanislav Motylkov             // set progress bar to 100%
9326803490aSGiannis Adamopoulos             ProgressBar.SetMarquee(FALSE);
93366e3c1f7SStanislav Motylkov 
93466e3c1f7SStanislav Motylkov             dwContentLen = dwCurrentBytesRead;
935*33c2903eSMark Jansen             if (!IsWindow(hDlg))
936*33c2903eSMark Jansen                 goto end;
9371e201d70SGiannis Adamopoulos             UpdateProgress(hDlg, dwCurrentBytesRead, dwContentLen, 0, InfoArray[iAppId].szUrl.GetString());
93866e3c1f7SStanislav Motylkov         }
93966e3c1f7SStanislav Motylkov 
940c2c66affSColin Finck         /* if this thing isn't a RAPPS update and it has a SHA-1 checksum
941c2c66affSColin Finck         verify its integrity by using the native advapi32.A_SHA1 functions */
942a21d959eSHe Yang         if ((InfoArray[iAppId].DLType == DLTYPE_APPLICATION) && InfoArray[iAppId].szSHA1[0] != 0)
943c2c66affSColin Finck         {
944*33c2903eSMark Jansen             CStringW szMsgText;
945c2c66affSColin Finck 
946c2c66affSColin Finck             // change a few strings in the download dialog to reflect the verification process
947c2c66affSColin Finck             if (!szMsgText.LoadStringW(IDS_INTEG_CHECK_TITLE))
948fb1582d3SKyle Katarn             {
949fb1582d3SKyle Katarn                 DPRINT1("Unable to load string\n");
950c2c66affSColin Finck                 goto end;
951fb1582d3SKyle Katarn             }
952c2c66affSColin Finck 
953*33c2903eSMark Jansen             if (!IsWindow(hDlg))
954*33c2903eSMark Jansen                 goto end;
955c2c66affSColin Finck             SetWindowTextW(hDlg, szMsgText.GetString());
956*33c2903eSMark Jansen             ::SetDlgItemTextW(hDlg, IDC_DOWNLOAD_STATUS, Path);
957c2c66affSColin Finck 
958c2c66affSColin Finck             // this may take a while, depending on the file size
959*33c2903eSMark Jansen             if (!VerifyInteg(InfoArray[iAppId].szSHA1.GetString(), Path))
960c2c66affSColin Finck             {
961c2c66affSColin Finck                 if (!szMsgText.LoadStringW(IDS_INTEG_CHECK_FAIL))
962fb1582d3SKyle Katarn                 {
963fb1582d3SKyle Katarn                     DPRINT1("Unable to load string\n");
964c2c66affSColin Finck                     goto end;
965fb1582d3SKyle Katarn                 }
966c2c66affSColin Finck 
967*33c2903eSMark Jansen                 if (!IsWindow(hDlg))
968*33c2903eSMark Jansen                     goto end;
969c2c66affSColin Finck                 MessageBoxW(hDlg, szMsgText.GetString(), NULL, MB_OK | MB_ICONERROR);
970c2c66affSColin Finck                 goto end;
971c2c66affSColin Finck             }
972c2c66affSColin Finck         }
973c2c66affSColin Finck 
974c2c66affSColin Finck     run:
975c2c66affSColin Finck         DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_WAITING_INSTALL);
976c2c66affSColin Finck 
977c2c66affSColin Finck         // run it
978a21d959eSHe Yang         if (InfoArray[iAppId].DLType == DLTYPE_APPLICATION)
979c2c66affSColin Finck         {
980c2c66affSColin Finck             SHELLEXECUTEINFOW shExInfo = {0};
981c2c66affSColin Finck             shExInfo.cbSize = sizeof(shExInfo);
982c2c66affSColin Finck             shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
983c2c66affSColin Finck             shExInfo.lpVerb = L"open";
984*33c2903eSMark Jansen             shExInfo.lpFile = Path;
985c2c66affSColin Finck             shExInfo.lpParameters = L"";
986c2c66affSColin Finck             shExInfo.nShow = SW_SHOW;
987c2c66affSColin Finck 
988ae426744SMark Jansen             /* FIXME: Do we want to log installer status? */
989ae426744SMark Jansen             WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_INSTALL, InfoArray[iAppId].szName);
990ae426744SMark Jansen 
991c2c66affSColin Finck             if (ShellExecuteExW(&shExInfo))
992c2c66affSColin Finck             {
99347bbd637SAlexander Shaposhnikov                 // reflect installation progress in the titlebar
99447bbd637SAlexander Shaposhnikov                 // TODO: make a separate string with a placeholder to include app name?
995*33c2903eSMark Jansen                 CStringW szMsgText = LoadStatusString(DLSTATUS_INSTALLING);
996*33c2903eSMark Jansen                 if (!IsWindow(hDlg))
997*33c2903eSMark Jansen                     goto end;
99847bbd637SAlexander Shaposhnikov                 SetWindowTextW(hDlg, szMsgText.GetString());
99947bbd637SAlexander Shaposhnikov 
1000c2c66affSColin Finck                 DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_INSTALLING);
100147bbd637SAlexander Shaposhnikov 
1002c2c66affSColin Finck                 // TODO: issue an install operation separately so that the apps could be downloaded in the background
1003c2c66affSColin Finck                 WaitForSingleObject(shExInfo.hProcess, INFINITE);
1004c2c66affSColin Finck                 CloseHandle(shExInfo.hProcess);
1005c2c66affSColin Finck             }
1006c2c66affSColin Finck             else
1007c2c66affSColin Finck             {
1008059ba9b0SStanislav Motylkov                 ShowLastError(hMainWnd, FALSE, GetLastError());
1009c2c66affSColin Finck             }
1010c2c66affSColin Finck         }
1011c2c66affSColin Finck 
1012c2c66affSColin Finck     end:
1013c2c66affSColin Finck         if (hOut != INVALID_HANDLE_VALUE)
1014c2c66affSColin Finck             CloseHandle(hOut);
1015c2c66affSColin Finck 
10164f25a476SMark Jansen         if (hFile)
1017c2c66affSColin Finck             InternetCloseHandle(hFile);
1018c2c66affSColin Finck         InternetCloseHandle(hOpen);
1019c2c66affSColin Finck 
1020c2c66affSColin Finck         if (bTempfile)
1021c2c66affSColin Finck         {
1022a21d959eSHe Yang             if (bCancelled || (SettingsInfo.bDelInstaller && (InfoArray[iAppId].DLType == DLTYPE_APPLICATION)))
1023*33c2903eSMark Jansen                 DeleteFileW(Path);
1024c2c66affSColin Finck         }
1025c2c66affSColin Finck 
1026*33c2903eSMark Jansen         if (!IsWindow(hDlg))
1027*33c2903eSMark Jansen             return 0;
1028c2c66affSColin Finck         DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_FINISHED);
1029c2c66affSColin Finck     }
1030c2c66affSColin Finck 
1031c2c66affSColin Finck     delete static_cast<DownloadParam *>(param);
1032*33c2903eSMark Jansen     if (!IsWindow(hDlg))
1033*33c2903eSMark Jansen         return 0;
1034c2c66affSColin Finck     SendMessageW(hDlg, WM_CLOSE, 0, 0);
1035c2c66affSColin Finck     return 0;
1036c2c66affSColin Finck }
1037c2c66affSColin Finck 
1038c2c66affSColin Finck // TODO: Reuse the dialog
1039*33c2903eSMark Jansen VOID
1040*33c2903eSMark Jansen CDownloadManager::LaunchDownloadDialog(BOOL bIsModal)
1041c2c66affSColin Finck {
1042946ee611SMark Jansen     CDownloadManager::bModal = bIsModal;
1043c2c66affSColin Finck     if (bIsModal)
1044c2c66affSColin Finck     {
1045*33c2903eSMark Jansen         DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG), hMainWnd, DownloadDlgProc);
1046c2c66affSColin Finck     }
1047c2c66affSColin Finck     else
1048c2c66affSColin Finck     {
1049*33c2903eSMark Jansen         CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG), hMainWnd, DownloadDlgProc);
1050c2c66affSColin Finck     }
1051c2c66affSColin Finck }
1052c2c66affSColin Finck // CDownloadManager
10531807dbfdSGiannis Adamopoulos 
1054*33c2903eSMark Jansen BOOL
1055*33c2903eSMark Jansen DownloadListOfApplications(const CAtlList<CApplicationInfo *> &AppsList, BOOL bIsModal)
10561807dbfdSGiannis Adamopoulos {
1057*33c2903eSMark Jansen     if (AppsList.IsEmpty())
10581807dbfdSGiannis Adamopoulos         return FALSE;
10591807dbfdSGiannis Adamopoulos 
1060*33c2903eSMark Jansen     POSITION CurrentListPosition = AppsList.GetHeadPosition();
1061*33c2903eSMark Jansen     while (CurrentListPosition)
10621807dbfdSGiannis Adamopoulos     {
1063*33c2903eSMark Jansen         const CApplicationInfo *Info = AppsList.GetNext(CurrentListPosition);
1064*33c2903eSMark Jansen         CDownloadManager::Add(DownloadInfo(*Info));
10651807dbfdSGiannis Adamopoulos     }
10661807dbfdSGiannis Adamopoulos 
10671807dbfdSGiannis Adamopoulos     // Create a dialog and issue a download process
10681807dbfdSGiannis Adamopoulos     CDownloadManager::LaunchDownloadDialog(bIsModal);
10691807dbfdSGiannis Adamopoulos 
10701807dbfdSGiannis Adamopoulos     return TRUE;
10711807dbfdSGiannis Adamopoulos }
10721807dbfdSGiannis Adamopoulos 
1073*33c2903eSMark Jansen BOOL
1074*33c2903eSMark Jansen DownloadApplication(CApplicationInfo *pAppInfo)
10751807dbfdSGiannis Adamopoulos {
10761807dbfdSGiannis Adamopoulos     if (!pAppInfo)
10771807dbfdSGiannis Adamopoulos         return FALSE;
10781807dbfdSGiannis Adamopoulos 
1079143b2a50SMark Jansen     CDownloadManager::Download(*pAppInfo, FALSE);
10801807dbfdSGiannis Adamopoulos     return TRUE;
10811807dbfdSGiannis Adamopoulos }
10821807dbfdSGiannis Adamopoulos 
1083*33c2903eSMark Jansen VOID
1084*33c2903eSMark Jansen DownloadApplicationsDB(LPCWSTR lpUrl, BOOL IsOfficial)
10851807dbfdSGiannis Adamopoulos {
10861807dbfdSGiannis Adamopoulos     static DownloadInfo DatabaseDLInfo;
10871807dbfdSGiannis Adamopoulos     DatabaseDLInfo.szUrl = lpUrl;
10881807dbfdSGiannis Adamopoulos     DatabaseDLInfo.szName.LoadStringW(IDS_DL_DIALOG_DB_DISP);
1089a21d959eSHe Yang     DatabaseDLInfo.DLType = IsOfficial ? DLTYPE_DBUPDATE : DLTYPE_DBUPDATE_UNOFFICIAL;
10901807dbfdSGiannis Adamopoulos     CDownloadManager::Download(DatabaseDLInfo, TRUE);
10911807dbfdSGiannis Adamopoulos }
1092