[RAPPS]
[reactos.git] / reactos / base / applications / rapps / loaddlg.cpp
index 3d43bb7..6ef55b4 100644 (file)
@@ -1,5 +1,6 @@
-/* PROJECT:     ReactOS Applications Manager
- * LICENSE:     GPL - See COPYING in the top level directory
+/*
+ * PROJECT:     ReactOS Applications Manager
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
  * FILE:        base/applications/rapps/loaddlg.cpp
  * PURPOSE:     Displaying a download dialog
  * COPYRIGHT:   Copyright 2001 John R. Sheets             (for CodeWeavers)
@@ -7,7 +8,7 @@
  *              Copyright 2005 Ge van Geldorp             (gvg@reactos.org)
  *              Copyright 2009 Dmitry Chapyshev           (dmitry@reactos.org)
  *              Copyright 2015 Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
- *              Copyright 2017 Alexander Shaposhnikov     (chaez.san@gmail.com)
+ *              Copyright 2017 Alexander Shaposhnikov     (sanchaez@reactos.org)
  */
 
  /*
@@ -27,7 +28,7 @@
   * License along with this library; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
   */
-#include "defines.h"
+#include "rapps.h"
 
 #include <shlobj_undoc.h>
 #include <shlguid_undoc.h>
 #define CERT_SUBJECT_INFO "Domain Control Validated\r\n*.reactos.org"
 #endif
 
-typedef enum
+enum DownloadStatus
 {
-    DLWaiting = IDS_STATUS_WAITING,
-    DLDownloading = IDS_STATUS_DOWNLOADING,
-    DLWaitingToInstall = IDS_STATUS_DOWNLOADED,
-    DLInstalling = IDS_STATUS_INSTALLING,
-    DLInstalled = IDS_STATUS_INSTALLED,
-    DLFinished = IDS_STATUS_FINISHED
-} DOWNLOAD_STATUS;
-
-ATL::CStringW LoadStatusString(DOWNLOAD_STATUS StatusParam)
+    DLSTATUS_WAITING = IDS_STATUS_WAITING,
+    DLSTATUS_DOWNLOADING = IDS_STATUS_DOWNLOADING,
+    DLSTATUS_WAITING_INSTALL = IDS_STATUS_DOWNLOADED,
+    DLSTATUS_INSTALLING = IDS_STATUS_INSTALLING,
+    DLSTATUS_INSTALLED = IDS_STATUS_INSTALLED,
+    DLSTATUS_FINISHED = IDS_STATUS_FINISHED
+};
+
+ATL::CStringW LoadStatusString(DownloadStatus StatusParam)
 {
     ATL::CStringW szString;
     szString.LoadStringW(StatusParam);
     return szString;
 }
 
+struct DownloadInfo
+{
+    DownloadInfo() {}
+    DownloadInfo(const CAvailableApplicationInfo& AppInfo)
+        :szUrl(AppInfo.m_szUrlDownload), szName(AppInfo.m_szName), szSHA1(AppInfo.m_szSHA1)
+    {
+    }
+
+    ATL::CStringW szUrl;
+    ATL::CStringW szName;
+    ATL::CStringW szSHA1;
+};
+
+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 CDownloadDialog :
     public CComObjectRootEx<CComMultiThreadModelNoCS>,
     public IBindStatusCallback
@@ -163,9 +191,9 @@ public:
             m_UrlHasBeenCopied = TRUE;
         }
 
-        SetLastError(0);
+        SetLastError(ERROR_SUCCESS);
         r = GetWindowLongPtrW(m_hDialog, GWLP_USERDATA);
-        if (0 != r || 0 != GetLastError())
+        if (r || GetLastError() != ERROR_SUCCESS)
         {
             *m_pbCancelled = TRUE;
             return E_ABORT;
@@ -227,16 +255,15 @@ public:
         return hwnd;
     }
 
-    VOID LoadList(ATL::CSimpleArray<PAPPLICATION_INFO> arrInfo)
+    VOID LoadList(ATL::CSimpleArray<DownloadInfo> arrInfo)
     {
         for (INT i = 0; i < arrInfo.GetSize(); ++i)
         {
-            PAPPLICATION_INFO AppInfo = arrInfo[i];
-            AddRow(i, AppInfo->szName.GetString(), DOWNLOAD_STATUS::DLWaiting);
+            AddRow(i, arrInfo[i].szName.GetString(), DLSTATUS_WAITING);
         }
     }
 
-    VOID SetDownloadStatus(INT ItemIndex, DOWNLOAD_STATUS Status)
+    VOID SetDownloadStatus(INT ItemIndex, DownloadStatus Status)
     {
         HWND hListView = GetWindow();
         ATL::CStringW szBuffer = LoadStatusString(Status);
@@ -256,7 +283,7 @@ public:
         return InsertItem(&Item);
     }
 
-    VOID AddRow(INT RowIndex, LPCWSTR szAppName, const DOWNLOAD_STATUS Status)
+    VOID AddRow(INT RowIndex, LPCWSTR szAppName, const DownloadStatus Status)
     {
         ATL::CStringW szStatus = LoadStatusString(Status);
         AddItem(RowIndex,
@@ -340,29 +367,22 @@ static BOOL CertIsValid(HINTERNET hInternet, LPWSTR lpszHostName)
 inline VOID MessageBox_LoadString(HWND hMainWnd, INT StringID)
 {
     ATL::CString szMsgText;
-    if (szMsgText.LoadStringW(hInst, StringID))
+    if (szMsgText.LoadStringW(StringID))
     {
         MessageBoxW(hMainWnd, szMsgText.GetString(), NULL, MB_OK | MB_ICONERROR);
     }
 }
 
-struct DownloadParam
-{
-    DownloadParam() : Dialog(NULL), AppInfo(), szCaption(NULL) {}
-    DownloadParam(HWND dlg, const ATL::CSimpleArray<PAPPLICATION_INFO> &info, LPCWSTR caption)
-        : Dialog(dlg), AppInfo(info), szCaption(caption)
-    {
-    }
-
-    HWND Dialog;
-    ATL::CSimpleArray<PAPPLICATION_INFO> AppInfo;
-    LPCWSTR szCaption;
-};
-
 // CDownloadManager
-ATL::CSimpleArray<PAPPLICATION_INFO>    CDownloadManager::AppsToInstallList;
+ATL::CSimpleArray<DownloadInfo>         CDownloadManager::AppsToInstallList;
 CDowloadingAppsListView                 CDownloadManager::DownloadsListView;
-INT                                     CDownloadManager::iCurrentApp;
+
+VOID CDownloadManager::Download(const DownloadInfo &DLInfo, BOOL bIsModal)
+{
+    AppsToInstallList.RemoveAll();
+    AppsToInstallList.Add(DLInfo);
+    LaunchDownloadDialog(bIsModal);
+}
 
 INT_PTR CALLBACK CDownloadManager::DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
@@ -419,6 +439,7 @@ INT_PTR CALLBACK CDownloadManager::DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM w
         }
 
         CloseHandle(Thread);
+        AppsToInstallList.RemoveAll();
         return TRUE;
     }
 
@@ -432,7 +453,7 @@ INT_PTR CALLBACK CDownloadManager::DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM w
 
     case WM_CLOSE:
         EndDialog(Dlg, 0);
-        DestroyWindow(Dlg);
+        //DestroyWindow(Dlg);
         return TRUE;
 
     default:
@@ -527,6 +548,8 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
     PWSTR p, q;
 
     HWND hDlg = static_cast<DownloadParam*>(param)->Dialog;
+    HWND Item;
+    INT iAppId;
 
     ULONG dwContentLen, dwBytesWritten, dwBytesRead, dwStatus;
     ULONG dwCurrentBytesRead = 0;
@@ -545,30 +568,21 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
     URL_COMPONENTS urlComponents;
     size_t urlLength, filenameLength;
 
-    const INT iAppId = iCurrentApp;
-    const ATL::CSimpleArray<PAPPLICATION_INFO> InfoArray = static_cast<DownloadParam*>(param)->AppInfo;
+    const ATL::CSimpleArray<DownloadInfo> &InfoArray = static_cast<DownloadParam*>(param)->AppInfo;
     LPCWSTR szCaption = static_cast<DownloadParam*>(param)->szCaption;
+    ATL::CStringW szNewCaption;
 
-    delete param;
     if (InfoArray.GetSize() <= 0)
     {
         MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD);
         goto end;
     }
 
-    for (INT iAppId = 0; iAppId < InfoArray.GetSize(); ++iAppId)
+    for (iAppId = 0; iAppId < InfoArray.GetSize(); ++iAppId)
     {
-        PAPPLICATION_INFO pCurrentInfo = AppsToInstallList[iAppId];
-        if (!pCurrentInfo)
-        {
-            MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD);
-            continue;
-        }
-
-
         // build the path for the download
-        p = wcsrchr(pCurrentInfo->szUrlDownload.GetString(), L'/');
-        q = wcsrchr(pCurrentInfo->szUrlDownload.GetString(), L'?');
+        p = wcsrchr(InfoArray[iAppId].szUrl.GetString(), L'/');
+        q = wcsrchr(InfoArray[iAppId].szUrl.GetString(), L'?');
 
         // do we have a final slash separator?
         if (!p)
@@ -583,7 +597,7 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
             filenameLength -= wcslen(q - 1) * sizeof(WCHAR);
 
         // is this URL an update package for RAPPS? if so store it in a different place
-        if (pCurrentInfo->szUrlDownload == APPLICATION_DATABASE_URL)
+        if (InfoArray[iAppId].szUrl == APPLICATION_DATABASE_URL)
         {
             bCab = TRUE;
             if (!GetStorageDirectory(Path))
@@ -605,15 +619,15 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
         Path += L"\\";
         Path += (LPWSTR) (p + 1);
 
-        if (!bCab && pCurrentInfo->szSHA1[0] && GetFileAttributesW(Path.GetString()) != INVALID_FILE_ATTRIBUTES)
+        if (!bCab && InfoArray[iAppId].szSHA1[0] && GetFileAttributesW(Path.GetString()) != INVALID_FILE_ATTRIBUTES)
         {
             // only open it in case of total correctness
-            if (VerifyInteg(pCurrentInfo->szSHA1, Path))
+            if (VerifyInteg(InfoArray[iAppId].szSHA1.GetString(), Path))
                 goto run;
         }
 
         // Reset progress bar
-        HWND Item = GetDlgItem(hDlg, IDC_DOWNLOAD_PROGRESS);
+        Item = GetDlgItem(hDlg, IDC_DOWNLOAD_PROGRESS);
         if (Item)
         {
             SendMessageW(Item, PBM_SETPOS, 0, 0);
@@ -622,20 +636,19 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
         // Change caption to show the currently downloaded app
         if (!bCab)
         {
-            ATL::CStringW szNewCaption = "";
-            szNewCaption.Format(szCaption, pCurrentInfo->szName.GetString());
-            SetWindowTextW(hDlg, szNewCaption.GetString());
+            szNewCaption.Format(szCaption, InfoArray[iAppId].szName.GetString());
         }
         else
         {
-            //TODO: add this string to .rc
-            SetWindowTextW(hDlg, L"Downloading Database...");
+            szNewCaption.LoadStringW(IDS_DL_DIALOG_DB_DOWNLOAD_DISP);
         }
 
+        SetWindowTextW(hDlg, szNewCaption.GetString());
+
         // Add the download URL
-        SetDlgItemTextW(hDlg, IDC_DOWNLOAD_STATUS, pCurrentInfo->szUrlDownload.GetString());
+        SetDlgItemTextW(hDlg, IDC_DOWNLOAD_STATUS, InfoArray[iAppId].szUrl.GetString());
 
-        DownloadsListView.SetDownloadStatus(iAppId, DOWNLOAD_STATUS::DLDownloading);
+        DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_DOWNLOADING);
 
         // download it
         bTempfile = TRUE;
@@ -664,7 +677,7 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
         if (!hOpen)
             goto end;
 
-        hFile = InternetOpenUrlW(hOpen, pCurrentInfo->szUrlDownload.GetString(), NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_KEEP_CONNECTION, 0);
+        hFile = InternetOpenUrlW(hOpen, InfoArray[iAppId].szUrl.GetString(), NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_KEEP_CONNECTION, 0);
 
         if (!hFile)
         {
@@ -686,13 +699,13 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
         memset(&urlComponents, 0, sizeof(urlComponents));
         urlComponents.dwStructSize = sizeof(urlComponents);
 
-        urlLength = pCurrentInfo->szUrlDownload.GetLength();
+        urlLength = InfoArray[iAppId].szUrl.GetLength();
         urlComponents.dwSchemeLength = urlLength + 1;
         urlComponents.lpszScheme = (LPWSTR) malloc(urlComponents.dwSchemeLength * sizeof(WCHAR));
         urlComponents.dwHostNameLength = urlLength + 1;
         urlComponents.lpszHostName = (LPWSTR) malloc(urlComponents.dwHostNameLength * sizeof(WCHAR));
 
-        if (!InternetCrackUrlW(pCurrentInfo->szUrlDownload, urlLength + 1, ICU_DECODE | ICU_ESCAPE, &urlComponents))
+        if (!InternetCrackUrlW(InfoArray[iAppId].szUrl, urlLength + 1, ICU_DECODE | ICU_ESCAPE, &urlComponents))
             goto end;
 
         if (urlComponents.nScheme == INTERNET_SCHEME_HTTP || urlComponents.nScheme == INTERNET_SCHEME_HTTPS)
@@ -704,7 +717,7 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
 #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) &&
-            (wcscmp(pCurrentInfo->szUrlDownload, APPLICATION_DATABASE_URL) == 0) &&
+            (wcscmp(InfoArray[iAppId].szUrl, APPLICATION_DATABASE_URL) == 0) &&
             (!CertIsValid(hOpen, urlComponents.lpszHostName)))
         {
             MessageBox_LoadString(hMainWnd, IDS_CERT_DOES_NOT_MATCH);
@@ -720,6 +733,7 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
         if (hOut == INVALID_HANDLE_VALUE)
             goto end;
 
+        dwCurrentBytesRead = 0;
         do
         {
             if (!InternetReadFile(hFile, lpBuffer, _countof(lpBuffer), &dwBytesRead))
@@ -735,7 +749,7 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
             }
 
             dwCurrentBytesRead += dwBytesRead;
-            dl->OnProgress(dwCurrentBytesRead, dwContentLen, 0, pCurrentInfo->szUrlDownload);
+            dl->OnProgress(dwCurrentBytesRead, dwContentLen, 0, InfoArray[iAppId].szUrl.GetString());
         } while (dwBytesRead && !bCancelled);
 
         CloseHandle(hOut);
@@ -746,21 +760,21 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
 
         /* 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 (!bCab && pCurrentInfo->szSHA1[0] != 0)
+        if (!bCab && InfoArray[iAppId].szSHA1[0] != 0)
         {
             ATL::CStringW szMsgText;
 
             // change a few strings in the download dialog to reflect the verification process
-            if (!szMsgText.LoadStringW(hInst, IDS_INTEG_CHECK_TITLE))
+            if (!szMsgText.LoadStringW(IDS_INTEG_CHECK_TITLE))
                 goto end;
 
             SetWindowTextW(hDlg, szMsgText.GetString());
             SendMessageW(GetDlgItem(hDlg, IDC_DOWNLOAD_STATUS), WM_SETTEXT, 0, (LPARAM) Path.GetString());
 
             // this may take a while, depending on the file size
-            if (!VerifyInteg(pCurrentInfo->szSHA1, Path.GetString()))
+            if (!VerifyInteg(InfoArray[iAppId].szSHA1.GetString(), Path.GetString()))
             {
-                if (!szMsgText.LoadStringW(hInst, IDS_INTEG_CHECK_FAIL))
+                if (!szMsgText.LoadStringW(IDS_INTEG_CHECK_FAIL))
                     goto end;
 
                 MessageBoxW(hDlg, szMsgText.GetString(), NULL, MB_OK | MB_ICONERROR);
@@ -769,7 +783,7 @@ DWORD WINAPI CDownloadManager::ThreadFunc(LPVOID param)
         }
 
 run:
-        DownloadsListView.SetDownloadStatus(iAppId, DOWNLOAD_STATUS::DLWaitingToInstall);
+        DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_WAITING_INSTALL);
 
         // run it
         if (!bCab)
@@ -784,7 +798,7 @@ run:
 
             if (ShellExecuteExW(&shExInfo))
             {
-                DownloadsListView.SetDownloadStatus(iAppId, DOWNLOAD_STATUS::DLInstalling);
+                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);
@@ -808,14 +822,15 @@ end:
                 DeleteFileW(Path.GetString());
         }
 
-        DownloadsListView.SetDownloadStatus(iAppId, DOWNLOAD_STATUS::DLFinished);
+        DownloadsListView.SetDownloadStatus(iAppId, DLSTATUS_FINISHED);
     }
 
+    delete static_cast<DownloadParam*>(param);
     SendMessageW(hDlg, WM_CLOSE, 0, 0);
     return 0;
 }
 
-BOOL CDownloadManager::DownloadListOfApplications(const ATL::CSimpleArray<PAPPLICATION_INFO>& AppsList, BOOL modal)
+BOOL CDownloadManager::DownloadListOfApplications(const ATL::CSimpleArray<CAvailableApplicationInfo*>& AppsList, BOOL bIsModal)
 {
     if (AppsList.GetSize() == 0)
     {
@@ -823,41 +838,41 @@ BOOL CDownloadManager::DownloadListOfApplications(const ATL::CSimpleArray<PAPPLI
     }
 
     // Initialize shared variables
-    AppsToInstallList = AppsList;
+    for (INT i = 0; i < AppsList.GetSize(); ++i)
+    {
+        if (AppsList[i])
+        {
+            AppsToInstallList.Add(*(AppsList[i]));
+        }
+    }
 
     // Create a dialog and issue a download process
-    LaunchDownloadDialog(modal);
+    LaunchDownloadDialog(bIsModal);
 
     return TRUE;
 }
 
-BOOL CDownloadManager::DownloadApplication(PAPPLICATION_INFO pAppInfo, BOOL modal)
+BOOL CDownloadManager::DownloadApplication(CAvailableApplicationInfo* pAppInfo, BOOL bIsModal)
 {
     if (!pAppInfo)
-    {
         return FALSE;
-    }
-
-    AppsToInstallList.RemoveAll();
-    AppsToInstallList.Add(pAppInfo);
-    LaunchDownloadDialog(modal);
 
+    Download(*pAppInfo, bIsModal);
     return TRUE;
 }
 
 VOID CDownloadManager::DownloadApplicationsDB(LPCWSTR lpUrl)
 {
-    static APPLICATION_INFO IntInfo;
-    IntInfo.szUrlDownload = lpUrl;
-    //TODO: add this string to .rc
-    IntInfo.szName = L"RAPPS DB";
-    DownloadApplication(&IntInfo, TRUE);
+    static DownloadInfo DatabaseDLInfo;
+    DatabaseDLInfo.szUrl = lpUrl;
+    DatabaseDLInfo.szName.LoadStringW(IDS_DL_DIALOG_DB_DISP);
+    Download(DatabaseDLInfo, TRUE);
 }
 
 //TODO: Reuse the dialog
-VOID CDownloadManager::LaunchDownloadDialog(BOOL modal)
+VOID CDownloadManager::LaunchDownloadDialog(BOOL bIsModal)
 {
-    if (modal)
+    if (bIsModal)
     {
         DialogBoxW(hInst,
                    MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG),
@@ -871,6 +886,5 @@ VOID CDownloadManager::LaunchDownloadDialog(BOOL modal)
                       hMainWnd,
                       DownloadDlgProc);
     }
-
 }
 // CDownloadManager