https://git.reactos.org/?p=reactos.git;a=commitdiff;h=72951421e6780b85ac1254f7561425ef3b6eb5a9

commit 72951421e6780b85ac1254f7561425ef3b6eb5a9
Author:     Whindmar Saksit <whinds...@proton.me>
AuthorDate: Sat Jan 25 16:42:48 2025 +0100
Commit:     GitHub <nore...@github.com>
CommitDate: Sat Jan 25 16:42:48 2025 +0100

    [RAPPS] Reuse active pending downloads window (#7648)
    
    CORE-16716 CORE-16804
---
 base/applications/rapps/gui.cpp     |    2 +-
 base/applications/rapps/loaddlg.cpp | 1094 ++++++++++++++++++-----------------
 2 files changed, 551 insertions(+), 545 deletions(-)

diff --git a/base/applications/rapps/gui.cpp b/base/applications/rapps/gui.cpp
index 5e8dc85a8ba..6f2e1a1d3d8 100644
--- a/base/applications/rapps/gui.cpp
+++ b/base/applications/rapps/gui.cpp
@@ -816,7 +816,7 @@ CMainWindow::InstallApplication(CAppInfo *Info)
     {
         if (DownloadApplication(Info))
         {
-            UpdateApplicationsList(SelectedEnumType);
+            //FIXME: Delay UpdateApplicationsList(SelectedEnumType); until 
install completes
             return TRUE;
         }
     }
diff --git a/base/applications/rapps/loaddlg.cpp 
b/base/applications/rapps/loaddlg.cpp
index c0ca9d135dc..df8afcbeeea 100644
--- a/base/applications/rapps/loaddlg.cpp
+++ b/base/applications/rapps/loaddlg.cpp
@@ -119,6 +119,19 @@ UrlUnescapeAndMakeFileNameValid(CStringW& str)
     str = szPath;
 }
 
+static void
+SetFriendlyUrl(HWND hWnd, LPCWSTR pszUrl)
+{
+    CStringW buf;
+    DWORD cch = (DWORD)(wcslen(pszUrl) + 1);
+    if (InternetCanonicalizeUrlW(pszUrl, buf.GetBuffer(cch), &cch, ICU_DECODE 
| ICU_NO_ENCODE))
+    {
+        buf.ReleaseBuffer();
+        pszUrl = buf;
+    }
+    SetWindowTextW(hWnd, pszUrl);
+}
+
 struct DownloadInfo
 {
     DownloadInfo() :  DLType(DLTYPE_APPLICATION), IType(INSTALLER_UNKNOWN), 
SizeInBytes(0)
@@ -130,9 +143,12 @@ struct DownloadInfo
         szName = AppInfo.szDisplayName;
         IType = AppInfo.GetInstallerType();
         if (IType == INSTALLER_GENERATE)
-        {
             szPackageName = AppInfo.szIdentifier;
-        }
+    }
+
+    bool Equal(const DownloadInfo &other) const
+    {
+        return DLType == other.DLType && !lstrcmpW(szUrl, other.szUrl);
     }
 
     DownloadType DLType;
@@ -144,21 +160,6 @@ struct DownloadInfo
     ULONG SizeInBytes;
 };
 
-struct DownloadParam
-{
-    DownloadParam() : Dialog(NULL), AppInfo(), szCaption(NULL)
-    {
-    }
-    DownloadParam(HWND dlg, const ATL::CSimpleArray<DownloadInfo> &info, 
LPCWSTR caption)
-        : Dialog(dlg), AppInfo(info), szCaption(caption)
-    {
-    }
-
-    HWND Dialog;
-    ATL::CSimpleArray<DownloadInfo> AppInfo;
-    LPCWSTR szCaption;
-};
-
 class CDownloaderProgress : public CWindowImpl<CDownloaderProgress, CWindow, 
CControlWinTraits>
 {
     CStringW m_szProgressText;
@@ -313,7 +314,7 @@ class CDowloadingAppsListView : public CListView
         RECT r;
         ::GetClientRect(hwndParent, &r);
         r.top = (2 * r.top + 1 * r.bottom) / 3; /* The vertical position at 
ratio 1 : 2 */
-#define MARGIN 10
+        const INT MARGIN = 10;
         ::InflateRect(&r, -MARGIN, -MARGIN);
 
         const DWORD style = WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL 
| LVS_SHOWSELALWAYS | LVS_NOSORTHEADER |
@@ -328,11 +329,12 @@ class CDowloadingAppsListView : public CListView
     }
 
     VOID
-    LoadList(ATL::CSimpleArray<DownloadInfo> arrInfo)
+    LoadList(ATL::CSimpleArray<DownloadInfo> arrInfo, UINT Start = 0)
     {
-        for (INT i = 0; i < arrInfo.GetSize(); ++i)
+        const INT base = GetItemCount();
+        for (INT i = Start; i < arrInfo.GetSize(); ++i)
         {
-            AddRow(i, arrInfo[i].szName.GetString(), DLSTATUS_WAITING);
+            AddRow(base + i - Start, arrInfo[i].szName, DLSTATUS_WAITING);
         }
     }
 
@@ -420,7 +422,7 @@ CertGetSubjectAndIssuer(HINTERNET hFile, CLocalPtr<char> 
&subjectInfo, CLocalPtr
 }
 #endif
 
-inline VOID
+static inline VOID
 MessageBox_LoadString(HWND hOwnerWnd, INT StringID)
 {
     CStringW szMsgText;
@@ -430,65 +432,175 @@ MessageBox_LoadString(HWND hOwnerWnd, INT StringID)
     }
 }
 
+static BOOL
+ShowLastError(HWND hWndOwner, BOOL bInetError, DWORD dwLastError)
+{
+    CLocalPtr<WCHAR> lpMsg;
+
+    if (!FormatMessageW(
+            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS |
+                (bInetError ? FORMAT_MESSAGE_FROM_HMODULE : 
FORMAT_MESSAGE_FROM_SYSTEM),
+            (bInetError ? GetModuleHandleW(L"wininet.dll") : NULL), 
dwLastError, LANG_USER_DEFAULT, (LPWSTR)&lpMsg, 0,
+            NULL))
+    {
+        DPRINT1("FormatMessageW unexpected failure (err %d)\n", 
GetLastError());
+        return FALSE;
+    }
+
+    MessageBoxW(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR);
+    return TRUE;
+}
+
 // Download dialog (loaddlg.cpp)
-class CDownloadManager
+HWND g_hDownloadWnd = NULL;
+
+class CDownloadManager :
+    public CComCoClass<CDownloadManager, &CLSID_NULL>,
+    public CComObjectRootEx<CComMultiThreadModelNoCS>,
+    public IUnknown
 {
-    static ATL::CSimpleArray<DownloadInfo> AppsDownloadList;
-    static CDowloadingAppsListView DownloadsListView;
-    static CDownloaderProgress ProgressBar;
-    static BOOL bCancelled;
-    static BOOL bModal;
-    static VOID
-    UpdateProgress(HWND hDlg, ULONG ulProgress, ULONG ulProgressMax, ULONG 
ulStatusCode, LPCWSTR szStatusText);
+public:
+    enum {
+        WM_ISCANCELLED = WM_APP, // Return BOOL
+        WM_SETSTATUS, // wParam DownloadStatus
+        WM_GETINSTANCE, // Return CDownloadManager*
+        WM_GETNEXT, // Return DownloadInfo* or NULL
+    };
+
+    CDownloadManager() : m_hDlg(NULL), m_Threads(0), m_Index(0), 
m_bCancelled(FALSE) {}
+
+    static CDownloadManager*
+    CreateInstanceHelper(BOOL Modal)
+    {
+        if (!Modal)
+        {
+            CDownloadManager* pExisting = CDownloadManager::FindInstance();
+            if (pExisting)
+            {
+                pExisting->AddRef();
+                return pExisting;
+            }
+        }
+        CComPtr<CDownloadManager> obj;
+        if (FAILED(ShellObjectCreator(obj)))
+            return NULL;
+        obj->m_bModal = Modal;
+        return obj.Detach();
+    }
 
-  public:
-    static VOID
-    Add(DownloadInfo info);
-    static VOID
-    Download(const DownloadInfo &DLInfo, BOOL bIsModal = FALSE);
-    static INT_PTR CALLBACK
-    DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-    static unsigned int WINAPI
-    ThreadFunc(LPVOID Context);
-    static VOID LaunchDownloadDialog(BOOL);
+    static BOOL
+    CreateInstance(BOOL Modal, CComPtr<CDownloadManager> &Obj)
+    {
+        CDownloadManager *p = CreateInstanceHelper(Modal);
+        if (!p)
+            return FALSE;
+        Obj.Attach(p);
+        return TRUE;
+    }
+
+    static CDownloadManager*
+    FindInstance()
+    {
+        if (g_hDownloadWnd)
+            return (CDownloadManager*)SendMessageW(g_hDownloadWnd, 
WM_GETINSTANCE, 0, 0);
+        return NULL;
+    }
+
+    BOOL
+    IsCancelled()
+    {
+        return !IsWindow(m_hDlg) || SendMessageW(m_hDlg, WM_ISCANCELLED, 0, 0);
+    }
+
+    void StartWorkerThread();
+    void Add(const DownloadInfo &Info);
+    void Show();
+    static INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, 
LPARAM lParam);
+    INT_PTR RealDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+    void UpdateProgress(ULONG ulProgress, ULONG ulProgressMax);
+    static unsigned int CALLBACK ThreadFunc(void*ThreadParam);
+    void PerformDownloadAndInstall(const DownloadInfo &Info);
+
+    DECLARE_NO_REGISTRY()
+    DECLARE_NOT_AGGREGATABLE(CDownloadManager)
+    BEGIN_COM_MAP(CDownloadManager)
+    END_COM_MAP()
+
+protected:
+    HWND m_hDlg;
+    UINT m_Threads;
+    UINT m_Index;
+    BOOL m_bCancelled;
+    BOOL m_bModal;
+    WCHAR m_szCaptionFmt[100];
+    ATL::CSimpleArray<DownloadInfo> m_List;
+    CDowloadingAppsListView m_ListView;
+    CDownloaderProgress m_ProgressBar;
 };
 
-// CDownloadManager
-ATL::CSimpleArray<DownloadInfo> CDownloadManager::AppsDownloadList;
-CDowloadingAppsListView CDownloadManager::DownloadsListView;
-CDownloaderProgress CDownloadManager::ProgressBar;
-BOOL CDownloadManager::bCancelled = FALSE;
-BOOL CDownloadManager::bModal = FALSE;
+void
+CDownloadManager::StartWorkerThread()
+{
+    AddRef(); // To keep m_List alive in thread
+    unsigned int ThreadId;
+    HANDLE Thread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, this, 0, 
&ThreadId);
+    if (Thread)
+        CloseHandle(Thread);
+    else
+        Release();
+}
 
-VOID
-CDownloadManager::Add(DownloadInfo info)
+void
+CDownloadManager::Add(const DownloadInfo &Info)
 {
-    AppsDownloadList.Add(info);
+    const UINT count = m_List.GetSize(), start = count;
+    for (UINT i = 0; i < count; ++i)
+    {
+        if (Info.Equal(m_List[i]))
+            return; // Already in the list
+    }
+    m_List.Add(Info);
+    if (m_hDlg)
+        m_ListView.LoadList(m_List, start);
 }
 
-VOID
-CDownloadManager::Download(const DownloadInfo &DLInfo, BOOL bIsModal)
+void
+CDownloadManager::Show()
 {
-    AppsDownloadList.RemoveAll();
-    AppsDownloadList.Add(DLInfo);
-    LaunchDownloadDialog(bIsModal);
+    if (m_bModal)
+        DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG), 
hMainWnd, DlgProc, (LPARAM)this);
+    else if (!m_hDlg || !IsWindow(m_hDlg))
+        CreateDialogParamW(hInst, MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG), 
hMainWnd, DlgProc, (LPARAM)this);
 }
 
 INT_PTR CALLBACK
-CDownloadManager::DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM 
lParam)
+CDownloadManager::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
-    static WCHAR szCaption[MAX_PATH];
+    CDownloadManager* pThis = (CDownloadManager*)GetWindowLongPtrW(hDlg, 
DWLP_USER);
+    if (!pThis)
+    {
+        if (uMsg != WM_INITDIALOG)
+            return FALSE;
+        SetWindowLongPtrW(hDlg, DWLP_USER, lParam);
+        pThis = (CDownloadManager*)lParam;
+    }
+    return pThis->RealDlgProc(hDlg, uMsg, wParam, lParam);
+}
 
+INT_PTR
+CDownloadManager::RealDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM 
lParam)
+{
     switch (uMsg)
     {
         case WM_INITDIALOG:
         {
             g_Busy++;
-            HICON hIconSm, hIconBg;
-            CStringW szTempCaption;
-
-            bCancelled = FALSE;
+            AddRef();
+            m_hDlg = hDlg;
+            if (!m_bModal)
+                g_hDownloadWnd = hDlg;
 
+            HICON hIconSm, hIconBg;
             if (hMainWnd)
             {
                 hIconBg = (HICON)GetClassLongPtrW(hMainWnd, GCLP_HICON);
@@ -496,630 +608,515 @@ CDownloadManager::DownloadDlgProc(HWND Dlg, UINT uMsg, 
WPARAM wParam, LPARAM lPa
             }
             if (!hMainWnd || (!hIconBg || !hIconSm))
             {
-                /* Load the default icon */
                 hIconBg = hIconSm = LoadIconW(hInst, 
MAKEINTRESOURCEW(IDI_MAIN));
             }
+            SendMessageW(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIconBg);
+            SendMessageW(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
 
-            if (hIconBg && hIconSm)
-            {
-                SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM)hIconBg);
-                SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
-            }
+            GetWindowTextW(hDlg, m_szCaptionFmt, _countof(m_szCaptionFmt));
+            CStringW buf;
+            buf = m_szCaptionFmt;
+            buf.Replace(L"%ls", L"");
+            SetWindowTextW(hDlg, buf); // "Downloading..."
 
-            HWND Item = GetDlgItem(Dlg, IDC_DOWNLOAD_PROGRESS);
-            if (Item)
+            HWND hItem = GetDlgItem(hDlg, IDC_DOWNLOAD_PROGRESS);
+            if (hItem)
             {
                 // initialize the default values for our nifty progress bar
                 // and subclass it so that it learns to print a status text
-                ProgressBar.SubclassWindow(Item);
-                ProgressBar.SendMessage(PBM_SETRANGE, 0, MAKELPARAM(0, 100));
-                ProgressBar.SendMessage(PBM_SETPOS, 0, 0);
-                if (AppsDownloadList.GetSize() > 0)
-                    ProgressBar.SetProgress(0, 
AppsDownloadList[0].SizeInBytes);
-            }
-
-            // Add a ListView
-            HWND hListView = DownloadsListView.Create(Dlg);
-            if (!hListView)
-            {
-                return FALSE;
+                m_ProgressBar.SubclassWindow(hItem);
+                m_ProgressBar.SendMessageW(PBM_SETRANGE, 0, MAKELPARAM(0, 
100));
+                m_ProgressBar.SendMessageW(PBM_SETPOS, 0, 0);
+                if (m_List.GetSize() > 0)
+                    m_ProgressBar.SetProgress(0, m_List[0].SizeInBytes);
             }
-            DownloadsListView.LoadList(AppsDownloadList);
 
-            // Get a dlg string for later use
-            GetWindowTextW(Dlg, szCaption, _countof(szCaption));
-
-            // Hide a placeholder from displaying
-            szTempCaption = szCaption;
-            szTempCaption.Replace(L"%ls", L"");
-            SetWindowText(Dlg, szTempCaption.GetString());
-
-            ShowWindow(Dlg, SW_SHOW);
-
-            // Start download process
-            DownloadParam *param = new DownloadParam(Dlg, AppsDownloadList, 
szCaption);
-            unsigned int ThreadId;
-            HANDLE Thread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (void 
*)param, 0, &ThreadId);
-            if (!Thread)
-            {
+            if (!m_ListView.Create(hDlg))
                 return FALSE;
-            }
+            m_ListView.LoadList(m_List);
 
-            CloseHandle(Thread);
-            AppsDownloadList.RemoveAll();
+            ShowWindow(hDlg, SW_SHOW);
+            StartWorkerThread();
             return TRUE;
         }
 
         case WM_COMMAND:
-            if (wParam == IDCANCEL)
+            if (LOWORD(wParam) == IDCANCEL)
             {
-                bCancelled = TRUE;
-                PostMessageW(Dlg, WM_CLOSE, 0, 0);
+                m_bCancelled = TRUE;
+                PostMessageW(hDlg, WM_CLOSE, 0, 0);
             }
             return FALSE;
 
         case WM_CLOSE:
-            if (ProgressBar)
-                ProgressBar.UnsubclassWindow(TRUE);
-            if (CDownloadManager::bModal)
-            {
-                ::EndDialog(Dlg, 0);
-            }
-            else
-            {
-                ::DestroyWindow(Dlg);
-            }
-            return TRUE;
+            m_bCancelled = TRUE;
+            if (m_ProgressBar)
+                m_ProgressBar.UnsubclassWindow(TRUE);
+            return m_bModal ? ::EndDialog(hDlg, 0) : ::DestroyWindow(hDlg);
 
         case WM_DESTROY:
+            if (g_hDownloadWnd == hDlg)
+                g_hDownloadWnd = NULL;
             g_Busy--;
             if (hMainWnd)
                 PostMessage(hMainWnd, WM_NOTIFY_OPERATIONCOMPLETED, 0, 0);
-            return FALSE;
-
-        default:
-            return FALSE;
-    }
-}
-
-BOOL UrlHasBeenCopied;
+            Release();
+            break;
 
-VOID
-CDownloadManager::UpdateProgress(
-    HWND hDlg,
-    ULONG ulProgress,
-    ULONG ulProgressMax,
-    ULONG ulStatusCode,
-    LPCWSTR szStatusText)
-{
-    HWND Item;
+        case WM_ISCANCELLED:
+            return SetDlgMsgResult(hDlg, uMsg, m_bCancelled);
 
-    if (!IsWindow(hDlg))
-        return;
-    ProgressBar.SetProgress(ulProgress, ulProgressMax);
+        case WM_SETSTATUS:
+            m_ListView.SetDownloadStatus(m_Index - 1, (DownloadStatus)wParam);
+            break;
 
-    if (!IsWindow(hDlg))
-        return;
-    Item = GetDlgItem(hDlg, IDC_DOWNLOAD_STATUS);
-    if (Item && szStatusText && wcslen(szStatusText) > 0 && UrlHasBeenCopied 
== FALSE)
-    {
-        SIZE_T len = wcslen(szStatusText) + 1;
-        CStringW buf;
-        DWORD dummyLen;
+        case WM_GETINSTANCE:
+            return SetDlgMsgResult(hDlg, uMsg, (INT_PTR)this);
 
-        /* beautify our url for display purposes */
-        if (!InternetCanonicalizeUrlW(szStatusText, buf.GetBuffer(len), 
&dummyLen, ICU_DECODE | ICU_NO_ENCODE))
-        {
-            /* just use the original */
-            buf.ReleaseBuffer();
-            buf = szStatusText;
-        }
-        else
+        case WM_GETNEXT:
         {
-            buf.ReleaseBuffer();
+            DownloadInfo *pItem = NULL;
+            if (!m_bCancelled && m_Index < (SIZE_T)m_List.GetSize())
+                pItem = &m_List[m_Index++];
+            return SetDlgMsgResult(hDlg, uMsg, (INT_PTR)pItem);
         }
-
-        /* paste it into our dialog and don't do it again in this instance */
-        ::SetWindowText(Item, buf.GetString());
-        UrlHasBeenCopied = TRUE;
     }
+    return FALSE;
 }
 
-BOOL
-ShowLastError(HWND hWndOwner, BOOL bInetError, DWORD dwLastError)
+void
+CDownloadManager::UpdateProgress(ULONG ulProgress, ULONG ulProgressMax)
 {
-    CLocalPtr<WCHAR> lpMsg;
+    m_ProgressBar.SetProgress(ulProgress, ulProgressMax);
+}
 
-    if (!FormatMessageW(
-            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS |
-                (bInetError ? FORMAT_MESSAGE_FROM_HMODULE : 
FORMAT_MESSAGE_FROM_SYSTEM),
-            (bInetError ? GetModuleHandleW(L"wininet.dll") : NULL), 
dwLastError, LANG_USER_DEFAULT, (LPWSTR)&lpMsg, 0,
-            NULL))
+unsigned int CALLBACK
+CDownloadManager::ThreadFunc(void* ThreadParam)
+{
+    CDownloadManager *pThis = (CDownloadManager*)ThreadParam;
+    HWND hDlg = pThis->m_hDlg;
+    for (;;)
     {
-        DPRINT1("FormatMessageW unexpected failure (err %d)\n", 
GetLastError());
-        return FALSE;
+        DownloadInfo *pItem = (DownloadInfo*)SendMessageW(hDlg, WM_GETNEXT, 0, 
0);
+        if (!pItem)
+            break;
+        pThis->PerformDownloadAndInstall(*pItem);
     }
-
-    MessageBoxW(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR);
-    return TRUE;
+    SendMessageW(hDlg, WM_CLOSE, 0, 0);
+    return pThis->Release();
 }
 
-unsigned int WINAPI
-CDownloadManager::ThreadFunc(LPVOID param)
+void
+CDownloadManager::PerformDownloadAndInstall(const DownloadInfo &Info)
 {
+    const HWND hDlg = m_hDlg;
+    const HWND hStatus = GetDlgItem(m_hDlg, IDC_DOWNLOAD_STATUS);
+    SetFriendlyUrl(hStatus, Info.szUrl);
+
+    m_ProgressBar.SetMarquee(FALSE);
+    m_ProgressBar.SendMessageW(PBM_SETPOS, 0, 0);
+    m_ProgressBar.SetProgress(0, Info.SizeInBytes);
+
+    CStringW str;
     CPathW Path;
     PCWSTR p, q;
 
-    HWND hDlg = static_cast<DownloadParam *>(param)->Dialog;
-    HWND Item;
-    INT iAppId;
-
-    ULONG dwContentLen, dwBytesWritten, dwBytesRead, dwStatus;
+    ULONG dwContentLen, dwBytesWritten, dwBytesRead, dwStatus, dwStatusLen;
     ULONG dwCurrentBytesRead = 0;
-    ULONG dwStatusLen = sizeof(dwStatus);
-
-    BOOL bTempfile = FALSE;
+    BOOL bTempfile = FALSE, bCancelled = FALSE;
 
     HINTERNET hOpen = NULL;
     HINTERNET hFile = NULL;
     HANDLE hOut = INVALID_HANDLE_VALUE;
 
-    unsigned char lpBuffer[4096];
+    
     LPCWSTR lpszAgent = L"RApps/1.1";
-    URL_COMPONENTSW urlComponents;
-    size_t urlLength, filenameLength;
-
-    const ATL::CSimpleArray<DownloadInfo> &InfoArray = 
static_cast<DownloadParam *>(param)->AppInfo;
-    LPCWSTR szCaption = static_cast<DownloadParam *>(param)->szCaption;
-    CStringW szNewCaption;
-
     const DWORD dwUrlConnectFlags =
         INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_PRAGMA_NOCACHE | 
INTERNET_FLAG_KEEP_CONNECTION;
+    URL_COMPONENTSW urlComponents;
+    size_t urlLength, filenameLength;
+    unsigned char lpBuffer[4096];
 
-    if (InfoArray.GetSize() <= 0)
+    // Change caption to show the currently downloaded app
+    switch (Info.DLType)
     {
-        MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD);
-        goto end;
+        case DLTYPE_APPLICATION:
+            str.Format(m_szCaptionFmt, Info.szName.GetString());
+            break;
+        case DLTYPE_DBUPDATE:
+            str.LoadStringW(IDS_DL_DIALOG_DB_DOWNLOAD_DISP);
+            break;
+        case DLTYPE_DBUPDATE_UNOFFICIAL:
+            str.LoadStringW(IDS_DL_DIALOG_DB_UNOFFICIAL_DOWNLOAD_DISP);
+            break;
     }
+    SetWindowTextW(hDlg, str);
 
-    for (iAppId = 0; iAppId < InfoArray.GetSize(); ++iAppId)
+    // is this URL an update package for RAPPS? if so store it in a different 
place
+    if (Info.DLType != DLTYPE_APPLICATION)
     {
-        // Reset progress bar
-        if (!IsWindow(hDlg))
-            break;
-        Item = GetDlgItem(hDlg, IDC_DOWNLOAD_PROGRESS);
-        if (Item)
+        if (!GetStorageDirectory(Path))
         {
-            ProgressBar.SetMarquee(FALSE);
-            ProgressBar.SendMessage(PBM_SETPOS, 0, 0);
-            ProgressBar.SetProgress(0, InfoArray[iAppId].SizeInBytes);
+            ShowLastError(hMainWnd, FALSE, GetLastError());
+            goto end;
         }
+    }
+    else
+    {
+        Path = SettingsInfo.szDownloadDir;
+    }
 
-        // is this URL an update package for RAPPS? if so store it in a 
different place
-        if (InfoArray[iAppId].DLType != DLTYPE_APPLICATION)
-        {
-            if (!GetStorageDirectory(Path))
-            {
-                ShowLastError(hMainWnd, FALSE, GetLastError());
-                goto end;
-            }
-        }
-        else
-        {
-            Path = SettingsInfo.szDownloadDir;
-        }
+    // build the path for the download
+    p = wcsrchr(Info.szUrl.GetString(), L'/');
+    q = wcsrchr(Info.szUrl.GetString(), L'?');
 
-        // Change caption to show the currently downloaded app
-        switch (InfoArray[iAppId].DLType)
-        {
-            case DLTYPE_APPLICATION:
-                szNewCaption.Format(szCaption, 
InfoArray[iAppId].szName.GetString());
-                break;
-            case DLTYPE_DBUPDATE:
-                szNewCaption.LoadStringW(IDS_DL_DIALOG_DB_DOWNLOAD_DISP);
-                break;
-            case DLTYPE_DBUPDATE_UNOFFICIAL:
-                
szNewCaption.LoadStringW(IDS_DL_DIALOG_DB_UNOFFICIAL_DOWNLOAD_DISP);
-                break;
-        }
+    // do we have a final slash separator?
+    if (!p)
+    {
+        MessageBox_LoadString(hMainWnd, IDS_UNABLE_PATH);
+        goto end;
+    }
 
-        if (!IsWindow(hDlg))
-            goto end;
-        SetWindowTextW(hDlg, szNewCaption.GetString());
+    // prepare the tentative length of the filename, maybe we've to remove 
part of it later on
+    filenameLength = wcslen(p) * sizeof(WCHAR);
 
-        // build the path for the download
-        p = wcsrchr(InfoArray[iAppId].szUrl.GetString(), L'/');
-        q = wcsrchr(InfoArray[iAppId].szUrl.GetString(), L'?');
+    /* do we have query arguments in the target URL after the filename? 
account for them
+    (e.g. https://example.org/myfile.exe?no_adware_plz) */
+    if (q && q > p && (q - p) > 0)
+        filenameLength -= wcslen(q - 1) * sizeof(WCHAR);
 
-        // do we have a final slash separator?
-        if (!p)
+    // is the path valid? can we access it?
+    if (GetFileAttributesW(Path) == INVALID_FILE_ATTRIBUTES)
+    {
+        if (!CreateDirectoryW(Path, NULL))
         {
-            MessageBox_LoadString(hMainWnd, IDS_UNABLE_PATH);
+            ShowLastError(hMainWnd, FALSE, GetLastError());
             goto end;
         }
+    }
 
-        // prepare the tentative length of the filename, maybe we've to remove 
part of it later on
-        filenameLength = wcslen(p) * sizeof(WCHAR);
-
-        /* do we have query arguments in the target URL after the filename? 
account for them
-        (e.g. https://example.org/myfile.exe?no_adware_plz) */
-        if (q && q > p && (q - p) > 0)
-            filenameLength -= wcslen(q - 1) * sizeof(WCHAR);
-
-        // is the path valid? can we access it?
-        if (GetFileAttributesW(Path) == INVALID_FILE_ATTRIBUTES)
+    switch (Info.DLType)
+    {
+        case DLTYPE_DBUPDATE:
+        case DLTYPE_DBUPDATE_UNOFFICIAL:
+            Path += APPLICATION_DATABASE_NAME;
+            break;
+        case DLTYPE_APPLICATION:
         {
-            if (!CreateDirectoryW(Path, NULL))
-            {
-                ShowLastError(hMainWnd, FALSE, GetLastError());
-                goto end;
-            }
+            CStringW str = p + 1; // use the filename retrieved from URL
+            UrlUnescapeAndMakeFileNameValid(str);
+            Path += str;
+            break;
         }
+    }
 
-        switch (InfoArray[iAppId].DLType)
-        {
-            case DLTYPE_DBUPDATE:
-            case DLTYPE_DBUPDATE_UNOFFICIAL:
-                Path += APPLICATION_DATABASE_NAME;
-                break;
-            case DLTYPE_APPLICATION:
-            {
-                CStringW str = p + 1; // use the filename retrieved from URL
-                UrlUnescapeAndMakeFileNameValid(str);
-                Path += str;
-                break;
-            }
-        }
+    if ((Info.DLType == DLTYPE_APPLICATION) && Info.szSHA1[0] &&
+        GetFileAttributesW(Path) != INVALID_FILE_ATTRIBUTES)
+    {
+        // only open it in case of total correctness
+        if (VerifyInteg(Info.szSHA1.GetString(), Path))
+            goto run;
+    }
 
-        if ((InfoArray[iAppId].DLType == DLTYPE_APPLICATION) && 
InfoArray[iAppId].szSHA1[0] &&
-            GetFileAttributesW(Path) != INVALID_FILE_ATTRIBUTES)
-        {
-            // only open it in case of total correctness
-            if (VerifyInteg(InfoArray[iAppId].szSHA1.GetString(), Path))
-                goto run;
-        }
+    // Download it
+    SendMessageW(hDlg, WM_SETSTATUS, DLSTATUS_DOWNLOADING, 0);
+    /* FIXME: this should just be using the system-wide proxy settings */
+    switch (SettingsInfo.Proxy)
+    {
+        case 0: // preconfig
+        default:
+            hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, 
NULL, NULL, 0);
+            break;
+        case 1: // direct (no proxy)
+            hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_DIRECT, NULL, 
NULL, 0);
+            break;
+        case 2: // use proxy
+            hOpen = InternetOpenW(
+                lpszAgent, INTERNET_OPEN_TYPE_PROXY, 
SettingsInfo.szProxyServer, SettingsInfo.szNoProxyFor, 0);
+            break;
+    }
 
-        // Add the download URL
-        if (!IsWindow(hDlg))
-            goto end;
-        SetDlgItemTextW(hDlg, IDC_DOWNLOAD_STATUS, 
InfoArray[iAppId].szUrl.GetString());
+    if (!hOpen)
+    {
+        ShowLastError(hMainWnd, TRUE, GetLastError());
+        goto end;
+    }
 
-        DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_DOWNLOADING);
+    bTempfile = TRUE;
+    dwContentLen = 0;
+    dwStatusLen = sizeof(dwStatus);
+    ZeroMemory(&urlComponents, sizeof(urlComponents));
+    urlComponents.dwStructSize = sizeof(urlComponents);
 
-        // download it
-        UrlHasBeenCopied = FALSE;
-        bTempfile = TRUE;
+    urlLength = Info.szUrl.GetLength();
+    urlComponents.dwSchemeLength = urlLength + 1;
+    urlComponents.lpszScheme = (LPWSTR)malloc(urlComponents.dwSchemeLength * 
sizeof(WCHAR));
 
-        /* FIXME: this should just be using the system-wide proxy settings */
-        switch (SettingsInfo.Proxy)
+    if (!InternetCrackUrlW(Info.szUrl, urlLength + 1, ICU_DECODE | ICU_ESCAPE, 
&urlComponents))
+    {
+        ShowLastError(hMainWnd, TRUE, GetLastError());
+        goto end;
+    }
+
+    if (urlComponents.nScheme == INTERNET_SCHEME_HTTP || urlComponents.nScheme 
== INTERNET_SCHEME_HTTPS)
+    {
+        hFile = InternetOpenUrlW(hOpen, Info.szUrl, NULL, 0, 
dwUrlConnectFlags, 0);
+        if (!hFile)
         {
-            case 0: // preconfig
-            default:
-                hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, 
NULL, NULL, 0);
-                break;
-            case 1: // direct (no proxy)
-                hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_DIRECT, 
NULL, NULL, 0);
-                break;
-            case 2: // use proxy
-                hOpen = InternetOpenW(
-                    lpszAgent, INTERNET_OPEN_TYPE_PROXY, 
SettingsInfo.szProxyServer, SettingsInfo.szNoProxyFor, 0);
-                break;
+            if (!ShowLastError(hMainWnd, TRUE, GetLastError()))
+            {
+                /* Workaround for CORE-17377 */
+                MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD2);
+            }
+            goto end;
         }
 
-        if (!hOpen)
+        // query connection
+        if (!HttpQueryInfoW(hFile, HTTP_QUERY_STATUS_CODE | 
HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwStatusLen, NULL))
         {
             ShowLastError(hMainWnd, TRUE, GetLastError());
             goto end;
         }
 
-        dwStatusLen = sizeof(dwStatus);
-
-        memset(&urlComponents, 0, sizeof(urlComponents));
-        urlComponents.dwStructSize = sizeof(urlComponents);
-
-        urlLength = InfoArray[iAppId].szUrl.GetLength();
-        urlComponents.dwSchemeLength = urlLength + 1;
-        urlComponents.lpszScheme = (LPWSTR)malloc(urlComponents.dwSchemeLength 
* sizeof(WCHAR));
-
-        if (!InternetCrackUrlW(InfoArray[iAppId].szUrl, urlLength + 1, 
ICU_DECODE | ICU_ESCAPE, &urlComponents))
+        if (dwStatus != HTTP_STATUS_OK)
         {
-            ShowLastError(hMainWnd, TRUE, GetLastError());
+            MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD);
             goto end;
         }
 
-        dwContentLen = 0;
-
-        if (urlComponents.nScheme == INTERNET_SCHEME_HTTP || 
urlComponents.nScheme == INTERNET_SCHEME_HTTPS)
+        // query content length
+        HttpQueryInfoW(hFile, HTTP_QUERY_CONTENT_LENGTH | 
HTTP_QUERY_FLAG_NUMBER, &dwContentLen, &dwStatusLen, NULL);
+    }
+    else if (urlComponents.nScheme == INTERNET_SCHEME_FTP)
+    {
+        // force passive mode on FTP
+        hFile =
+            InternetOpenUrlW(hOpen, Info.szUrl, NULL, 0, dwUrlConnectFlags | 
INTERNET_FLAG_PASSIVE, 0);
+        if (!hFile)
         {
-            hFile = InternetOpenUrlW(hOpen, 
InfoArray[iAppId].szUrl.GetString(), NULL, 0, dwUrlConnectFlags, 0);
-            if (!hFile)
-            {
-                if (!ShowLastError(hMainWnd, TRUE, GetLastError()))
-                {
-                    /* Workaround for CORE-17377 */
-                    MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD2);
-                }
-                goto end;
-            }
-
-            // query connection
-            if (!HttpQueryInfoW(hFile, HTTP_QUERY_STATUS_CODE | 
HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwStatusLen, NULL))
+            if (!ShowLastError(hMainWnd, TRUE, GetLastError()))
             {
-                ShowLastError(hMainWnd, TRUE, GetLastError());
-                goto end;
-            }
-
-            if (dwStatus != HTTP_STATUS_OK)
-            {
-                MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD);
-                goto end;
+                /* Workaround for CORE-17377 */
+                MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD2);
             }
-
-            // query content length
-            HttpQueryInfoW(
-                hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, 
&dwContentLen, &dwStatusLen, NULL);
+            goto end;
         }
-        else if (urlComponents.nScheme == INTERNET_SCHEME_FTP)
-        {
-            // force passive mode on FTP
-            hFile =
-                InternetOpenUrlW(hOpen, InfoArray[iAppId].szUrl, NULL, 0, 
dwUrlConnectFlags | INTERNET_FLAG_PASSIVE, 0);
-            if (!hFile)
-            {
-                if (!ShowLastError(hMainWnd, TRUE, GetLastError()))
-                {
-                    /* Workaround for CORE-17377 */
-                    MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD2);
-                }
-                goto end;
-            }
 
-            dwContentLen = FtpGetFileSize(hFile, &dwStatus);
-        }
-        else if (urlComponents.nScheme == INTERNET_SCHEME_FILE)
+        dwContentLen = FtpGetFileSize(hFile, &dwStatus);
+    }
+    else if (urlComponents.nScheme == INTERNET_SCHEME_FILE)
+    {
+        // Add support for the file scheme so testing locally is simpler
+        WCHAR LocalFilePath[MAX_PATH];
+        DWORD cchPath = _countof(LocalFilePath);
+        // Ideally we would use PathCreateFromUrlAlloc here, but that is not 
exported (yet)
+        HRESULT hr = PathCreateFromUrlW(Info.szUrl, LocalFilePath, &cchPath, 
0);
+        if (SUCCEEDED(hr))
         {
-            // Add support for the file scheme so testing locally is simpler
-            WCHAR LocalFilePath[MAX_PATH];
-            DWORD cchPath = _countof(LocalFilePath);
-            // Ideally we would use PathCreateFromUrlAlloc here, but that is 
not exported (yet)
-            HRESULT hr = PathCreateFromUrlW(InfoArray[iAppId].szUrl, 
LocalFilePath, &cchPath, 0);
-            if (SUCCEEDED(hr))
+            if (CopyFileW(LocalFilePath, Path, FALSE))
             {
-                if (CopyFileW(LocalFilePath, Path, FALSE))
-                {
-                    goto run;
-                }
-                else
-                {
-                    ShowLastError(hMainWnd, FALSE, GetLastError());
-                    goto end;
-                }
+                goto run;
             }
             else
             {
-                ShowLastError(hMainWnd, FALSE, hr);
+                ShowLastError(hMainWnd, FALSE, GetLastError());
                 goto end;
             }
         }
+        else
+        {
+            ShowLastError(hMainWnd, FALSE, hr);
+            goto end;
+        }
+    }
 
-        if (!dwContentLen)
+    if (!dwContentLen)
+    {
+        // Someone was nice enough to add this, let's use it
+        if (Info.SizeInBytes)
         {
-            // Someone was nice enough to add this, let's use it
-            if (InfoArray[iAppId].SizeInBytes)
-            {
-                dwContentLen = InfoArray[iAppId].SizeInBytes;
-            }
-            else
-            {
-                // content-length is not known, enable marquee mode
-                ProgressBar.SetMarquee(TRUE);
-            }
+            dwContentLen = Info.SizeInBytes;
         }
+        else
+        {
+            // content-length is not known, enable marquee mode
+            m_ProgressBar.SetMarquee(TRUE);
+        }
+    }
 
-        free(urlComponents.lpszScheme);
+    free(urlComponents.lpszScheme);
 
 #ifdef USE_CERT_PINNING
-        // are we using HTTPS to download the RAPPS update package? check if 
the certificate is original
-        if ((urlComponents.nScheme == INTERNET_SCHEME_HTTPS) && 
(InfoArray[iAppId].DLType == DLTYPE_DBUPDATE))
+    // are we using HTTPS to download the RAPPS update package? check if the 
certificate is original
+    if ((urlComponents.nScheme == INTERNET_SCHEME_HTTPS) && (Info.DLType == 
DLTYPE_DBUPDATE))
+    {
+        CLocalPtr<char> subjectName, issuerName;
+        CStringA szMsgText;
+        bool bAskQuestion = false;
+        if (!CertGetSubjectAndIssuer(hFile, subjectName, issuerName))
         {
-            CLocalPtr<char> subjectName, issuerName;
-            CStringA szMsgText;
-            bool bAskQuestion = false;
-            if (!CertGetSubjectAndIssuer(hFile, subjectName, issuerName))
-            {
-                szMsgText.LoadStringW(IDS_UNABLE_TO_QUERY_CERT);
-                bAskQuestion = true;
-            }
-            else if (!IsTrustedPinnedCert(subjectName, issuerName))
-            {
-                szMsgText.Format(IDS_MISMATCH_CERT_INFO, (LPCSTR)subjectName, 
(LPCSTR)issuerName);
-                bAskQuestion = true;
-            }
+            szMsgText.LoadStringW(IDS_UNABLE_TO_QUERY_CERT);
+            bAskQuestion = true;
+        }
+        else if (!IsTrustedPinnedCert(subjectName, issuerName))
+        {
+            szMsgText.Format(IDS_MISMATCH_CERT_INFO, (LPCSTR)subjectName, 
(LPCSTR)issuerName);
+            bAskQuestion = true;
+        }
 
-            if (bAskQuestion)
+        if (bAskQuestion)
+        {
+            if (MessageBoxA(hDlg, szMsgText, NULL, MB_YESNO | MB_ICONERROR) != 
IDYES)
             {
-                if (MessageBoxA(hMainWnd, szMsgText.GetString(), NULL, 
MB_YESNO | MB_ICONERROR) != IDYES)
-                {
-                    goto end;
-                }
+                goto end;
             }
         }
+    }
 #endif
 
-        hOut = CreateFileW(Path, GENERIC_WRITE, FILE_SHARE_READ | 
FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
+    hOut = CreateFileW(Path, GENERIC_WRITE, FILE_SHARE_READ | 
FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
+    if (hOut == INVALID_HANDLE_VALUE)
+    {
+        ShowLastError(hDlg, FALSE, GetLastError());
+        goto end;
+    }
 
-        if (hOut == INVALID_HANDLE_VALUE)
+    dwCurrentBytesRead = 0;
+    do
+    {
+        bCancelled = IsCancelled();
+        if (bCancelled)
+            break;
+
+        if (!InternetReadFile(hFile, lpBuffer, _countof(lpBuffer), 
&dwBytesRead))
         {
-            ShowLastError(hMainWnd, FALSE, GetLastError());
+            ShowLastError(hDlg, TRUE, GetLastError());
             goto end;
         }
 
-        dwCurrentBytesRead = 0;
-        do
+        if (!WriteFile(hOut, &lpBuffer[0], dwBytesRead, &dwBytesWritten, NULL))
         {
-            if (!InternetReadFile(hFile, lpBuffer, _countof(lpBuffer), 
&dwBytesRead))
-            {
-                ShowLastError(hMainWnd, TRUE, GetLastError());
-                goto end;
-            }
+            ShowLastError(hDlg, FALSE, GetLastError());
+            goto end;
+        }
 
-            if (!WriteFile(hOut, &lpBuffer[0], dwBytesRead, &dwBytesWritten, 
NULL))
-            {
-                ShowLastError(hMainWnd, FALSE, GetLastError());
-                goto end;
-            }
+        dwCurrentBytesRead += dwBytesRead;
+        UpdateProgress(dwCurrentBytesRead, dwContentLen);
+        
+    } while (dwBytesRead);
 
-            dwCurrentBytesRead += dwBytesRead;
-            if (!IsWindow(hDlg))
-                goto end;
-            UpdateProgress(hDlg, dwCurrentBytesRead, dwContentLen, 0, 
InfoArray[iAppId].szUrl.GetString());
-        } while (dwBytesRead && !bCancelled);
+    CloseHandle(hOut);
+    hOut = INVALID_HANDLE_VALUE;
 
-        CloseHandle(hOut);
-        hOut = INVALID_HANDLE_VALUE;
+    if (bCancelled)
+    {
+        DPRINT1("Operation cancelled\n");
+        goto end;
+    }
 
-        if (bCancelled)
+    if (!dwContentLen)
+    {
+        // set progress bar to 100%
+        m_ProgressBar.SetMarquee(FALSE);
+
+        dwContentLen = dwCurrentBytesRead;
+        UpdateProgress(dwCurrentBytesRead, dwContentLen);
+    }
+
+    /* if this thing isn't a RAPPS update and it has a SHA-1 checksum
+    verify its integrity by using the native advapi32.A_SHA1 functions */
+    if ((Info.DLType == DLTYPE_APPLICATION) && Info.szSHA1[0] != 0)
+    {
+        CStringW szMsgText;
+
+        // change a few strings in the download dialog to reflect the 
verification process
+        if (!szMsgText.LoadStringW(IDS_INTEG_CHECK_TITLE))
         {
-            DPRINT1("Operation cancelled\n");
+            DPRINT1("Unable to load string\n");
             goto end;
         }
 
-        if (!dwContentLen)
-        {
-            // set progress bar to 100%
-            ProgressBar.SetMarquee(FALSE);
-
-            dwContentLen = dwCurrentBytesRead;
-            if (!IsWindow(hDlg))
-                goto end;
-            UpdateProgress(hDlg, dwCurrentBytesRead, dwContentLen, 0, 
InfoArray[iAppId].szUrl.GetString());
-        }
+        SetWindowTextW(hDlg, szMsgText);
+        SetWindowTextW(hStatus, Path);
 
-        /* if this thing isn't a RAPPS update and it has a SHA-1 checksum
-        verify its integrity by using the native advapi32.A_SHA1 functions */
-        if ((InfoArray[iAppId].DLType == DLTYPE_APPLICATION) && 
InfoArray[iAppId].szSHA1[0] != 0)
+        // this may take a while, depending on the file size
+        if (!VerifyInteg(Info.szSHA1, Path))
         {
-            CStringW szMsgText;
-
-            // change a few strings in the download dialog to reflect the 
verification process
-            if (!szMsgText.LoadStringW(IDS_INTEG_CHECK_TITLE))
+            if (!szMsgText.LoadStringW(IDS_INTEG_CHECK_FAIL))
             {
                 DPRINT1("Unable to load string\n");
                 goto end;
             }
 
-            if (!IsWindow(hDlg))
-                goto end;
-            SetWindowTextW(hDlg, szMsgText.GetString());
-            ::SetDlgItemTextW(hDlg, IDC_DOWNLOAD_STATUS, Path);
-
-            // this may take a while, depending on the file size
-            if (!VerifyInteg(InfoArray[iAppId].szSHA1.GetString(), Path))
-            {
-                if (!szMsgText.LoadStringW(IDS_INTEG_CHECK_FAIL))
-                {
-                    DPRINT1("Unable to load string\n");
-                    goto end;
-                }
-
-                if (!IsWindow(hDlg))
-                    goto end;
-                MessageBoxW(hDlg, szMsgText.GetString(), NULL, MB_OK | 
MB_ICONERROR);
-                goto end;
-            }
+            MessageBoxW(hDlg, szMsgText, NULL, MB_OK | MB_ICONERROR);
+            goto end;
         }
+    }
 
-    run:
-        DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_WAITING_INSTALL);
+run:
+    SendMessageW(hDlg, WM_SETSTATUS, DLSTATUS_WAITING_INSTALL, 0);
 
-        // run it
-        if (InfoArray[iAppId].DLType == DLTYPE_APPLICATION)
+    // run it
+    if (Info.DLType == DLTYPE_APPLICATION)
+    {
+        CStringW app, params;
+        SHELLEXECUTEINFOW shExInfo = {0};
+        shExInfo.cbSize = sizeof(shExInfo);
+        shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
+        shExInfo.lpVerb = L"open";
+        shExInfo.lpFile = Path;
+        shExInfo.lpParameters = L"";
+        shExInfo.nShow = SW_SHOW;
+
+        if (Info.IType == INSTALLER_GENERATE)
         {
-            CStringW app, params;
-            SHELLEXECUTEINFOW shExInfo = {0};
-            shExInfo.cbSize = sizeof(shExInfo);
-            shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
-            shExInfo.lpVerb = L"open";
-            shExInfo.lpFile = Path;
-            shExInfo.lpParameters = L"";
-            shExInfo.nShow = SW_SHOW;
-
-            if (InfoArray[iAppId].IType == INSTALLER_GENERATE)
-            {
-                params = L"/" + CStringW(CMD_KEY_GENINST) + L" \"" +
-                         InfoArray[iAppId].szPackageName + L"\" \"" +
-                         CStringW(shExInfo.lpFile) + L"\"";
-                shExInfo.lpParameters = params;
-                shExInfo.lpFile = app.GetBuffer(MAX_PATH);
-                GetModuleFileNameW(NULL, const_cast<LPWSTR>(shExInfo.lpFile), 
MAX_PATH);
-                app.ReleaseBuffer();
-            }
-
-            /* FIXME: Do we want to log installer status? */
-            WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_INSTALL, 
InfoArray[iAppId].szName);
-
-            if (ShellExecuteExW(&shExInfo))
-            {
-                // reflect installation progress in the titlebar
-                // TODO: make a separate string with a placeholder to include 
app name?
-                CStringW szMsgText = LoadStatusString(DLSTATUS_INSTALLING);
-                if (!IsWindow(hDlg))
-                    goto end;
-                SetWindowTextW(hDlg, szMsgText.GetString());
-
-                DownloadsListView.SetDownloadStatus(iAppId, 
DLSTATUS_INSTALLING);
-
-                // TODO: issue an install operation separately so that the 
apps could be downloaded in the background
-                WaitForSingleObject(shExInfo.hProcess, INFINITE);
-                CloseHandle(shExInfo.hProcess);
-            }
-            else
-            {
-                ShowLastError(hMainWnd, FALSE, GetLastError());
-            }
+            params = L"/" + CStringW(CMD_KEY_GENINST) + L" \"" +
+                     Info.szPackageName + L"\" \"" +
+                     CStringW(shExInfo.lpFile) + L"\"";
+            shExInfo.lpParameters = params;
+            shExInfo.lpFile = app.GetBuffer(MAX_PATH);
+            GetModuleFileNameW(NULL, const_cast<LPWSTR>(shExInfo.lpFile), 
MAX_PATH);
+            app.ReleaseBuffer();
         }
 
-    end:
-        if (hOut != INVALID_HANDLE_VALUE)
-            CloseHandle(hOut);
+        /* FIXME: Do we want to log installer status? */
+        WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_INSTALL, Info.szName);
 
-        if (hFile)
-            InternetCloseHandle(hFile);
-        InternetCloseHandle(hOpen);
+        if (ShellExecuteExW(&shExInfo))
+        {
+            // reflect installation progress in the titlebar
+            // TODO: make a separate string with a placeholder to include app 
name?
+            CStringW szMsgText = LoadStatusString(DLSTATUS_INSTALLING);
+            SetWindowTextW(hDlg, szMsgText);
+
+            SendMessageW(hDlg, WM_SETSTATUS, DLSTATUS_INSTALLING, 0);
 
-        if (bTempfile)
+            // TODO: issue an install operation separately so that the apps 
could be downloaded in the background
+            WaitForSingleObject(shExInfo.hProcess, INFINITE);
+            CloseHandle(shExInfo.hProcess);
+        }
+        else
         {
-            if (bCancelled || (SettingsInfo.bDelInstaller && 
(InfoArray[iAppId].DLType == DLTYPE_APPLICATION)))
-                DeleteFileW(Path);
+            ShowLastError(hMainWnd, FALSE, GetLastError());
         }
-
-        if (!IsWindow(hDlg))
-            return 0;
-        DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_FINISHED);
     }
 
-    delete static_cast<DownloadParam *>(param);
-    if (!IsWindow(hDlg))
-        return 0;
-    SendMessageW(hDlg, WM_CLOSE, 0, 0);
-    return 0;
-}
+end:
+    if (hOut != INVALID_HANDLE_VALUE)
+        CloseHandle(hOut);
 
-// TODO: Reuse the dialog
-VOID
-CDownloadManager::LaunchDownloadDialog(BOOL bIsModal)
-{
-    CDownloadManager::bModal = bIsModal;
-    if (bIsModal)
-    {
-        DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG), hMainWnd, 
DownloadDlgProc);
-    }
-    else
+    if (hFile)
+        InternetCloseHandle(hFile);
+    InternetCloseHandle(hOpen);
+
+    if (bTempfile)
     {
-        CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG), hMainWnd, 
DownloadDlgProc);
+        if (bCancelled || (SettingsInfo.bDelInstaller && Info.DLType == 
DLTYPE_APPLICATION))
+            DeleteFileW(Path);
     }
+
+    SendMessageW(hDlg, WM_SETSTATUS, DLSTATUS_FINISHED, 0);
 }
-// CDownloadManager
 
 BOOL
 DownloadListOfApplications(const CAtlList<CAppInfo *> &AppsList, BOOL bIsModal)
@@ -1127,35 +1124,44 @@ DownloadListOfApplications(const CAtlList<CAppInfo *> 
&AppsList, BOOL bIsModal)
     if (AppsList.IsEmpty())
         return FALSE;
 
-    POSITION CurrentListPosition = AppsList.GetHeadPosition();
-    while (CurrentListPosition)
+    CComPtr<CDownloadManager> pDM;
+    if (!CDownloadManager::CreateInstance(bIsModal, pDM))
+        return FALSE;
+
+    for (POSITION it = AppsList.GetHeadPosition(); it;)
     {
-        const CAppInfo *Info = AppsList.GetNext(CurrentListPosition);
-        CDownloadManager::Add(DownloadInfo(*Info));
+        const CAppInfo *Info = AppsList.GetNext(it);
+        pDM->Add(DownloadInfo(*Info));
     }
-
-    // Create a dialog and issue a download process
-    CDownloadManager::LaunchDownloadDialog(bIsModal);
-
+    pDM->Show();
     return TRUE;
 }
 
 BOOL
 DownloadApplication(CAppInfo *pAppInfo)
 {
+    const bool bModal = false;
     if (!pAppInfo)
         return FALSE;
 
-    CDownloadManager::Download(*pAppInfo, FALSE);
-    return TRUE;
+    CAtlList<CAppInfo*> list;
+    list.AddTail(pAppInfo);
+    return DownloadListOfApplications(list, bModal);
 }
 
 VOID
 DownloadApplicationsDB(LPCWSTR lpUrl, BOOL IsOfficial)
 {
-    static DownloadInfo DatabaseDLInfo;
+    const bool bModal = true;
+    CComPtr<CDownloadManager> pDM;
+    if (!CDownloadManager::CreateInstance(bModal, pDM))
+        return;
+
+    DownloadInfo DatabaseDLInfo;
     DatabaseDLInfo.szUrl = lpUrl;
     DatabaseDLInfo.szName.LoadStringW(IDS_DL_DIALOG_DB_DISP);
     DatabaseDLInfo.DLType = IsOfficial ? DLTYPE_DBUPDATE : 
DLTYPE_DBUPDATE_UNOFFICIAL;
-    CDownloadManager::Download(DatabaseDLInfo, TRUE);
+
+    pDM->Add(DatabaseDLInfo);
+    pDM->Show();
 }

Reply via email to