Author: ashaposhnikov Date: Fri Jul 28 22:37:24 2017 New Revision: 75433
URL: http://svn.reactos.org/svn/reactos?rev=75433&view=rev Log: [RAPPS] Bulk install! - Added ListView class - Added ListView to a dialog Dialog shows the install progress of individual apps. It also waits for an installator to finish before issuing another download-install cycle. - Fixed: Downloads pointing to "" - Fixed: Selection data is not retrieved correctly - Yet again replacing some macros to wide functions - Minor improvements
Modified: branches/GSoC_2017/rapps/reactos/base/applications/rapps/ (props changed) branches/GSoC_2017/rapps/reactos/base/applications/rapps/available.cpp branches/GSoC_2017/rapps/reactos/base/applications/rapps/gui.cpp branches/GSoC_2017/rapps/reactos/base/applications/rapps/installed.cpp branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/en-US.rc branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/ru-RU.rc branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/uk-UA.rc branches/GSoC_2017/rapps/reactos/base/applications/rapps/loaddlg.cpp branches/GSoC_2017/rapps/reactos/base/applications/rapps/misc.cpp branches/GSoC_2017/rapps/reactos/base/applications/rapps/rapps.h branches/GSoC_2017/rapps/reactos/base/applications/rapps/resource.h
Propchange: branches/GSoC_2017/rapps/reactos/base/applications/rapps/ ------------------------------------------------------------------------------ --- svn:global-ignores (added) +++ svn:global-ignores Fri Jul 28 22:37:24 2017 @@ -0,0 +1 @@ +CMakeFiles
Propchange: branches/GSoC_2017/rapps/reactos/base/applications/rapps/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Fri Jul 28 22:37:24 2017 @@ -0,0 +1,3 @@ +CMakeCache.txt +RCa10764 +rapps.aps
Modified: branches/GSoC_2017/rapps/reactos/base/applications/rapps/available.cpp URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2017/rapps/reactos/base/app... ============================================================================== --- branches/GSoC_2017/rapps/reactos/base/applications/rapps/available.cpp [iso-8859-1] (original) +++ branches/GSoC_2017/rapps/reactos/base/applications/rapps/available.cpp [iso-8859-1] Fri Jul 28 22:37:24 2017 @@ -251,7 +251,7 @@ if (!DeleteCurrentAppsDB()) return FALSE;
- DownloadManager::DownloadApplicationsDB(APPLICATION_DATABASE_URL); + ÑDownloadManager::DownloadApplicationsDB(APPLICATION_DATABASE_URL);
if (m_szPath.IsEmpty()) return FALSE; @@ -280,7 +280,7 @@ if (hFind == INVALID_HANDLE_VALUE) { if (GetFileAttributesW(m_szCabPath) == INVALID_FILE_ATTRIBUTES) - DownloadManager::DownloadApplicationsDB(APPLICATION_DATABASE_URL); + ÑDownloadManager::DownloadApplicationsDB(APPLICATION_DATABASE_URL);
ExtractFilesFromCab(m_szCabPath, m_szAppsPath); hFind = FindFirstFileW(m_szSearchPath.GetString(), &FindFileData);
Modified: branches/GSoC_2017/rapps/reactos/base/applications/rapps/gui.cpp URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2017/rapps/reactos/base/app... ============================================================================== --- branches/GSoC_2017/rapps/reactos/base/applications/rapps/gui.cpp [iso-8859-1] (original) +++ branches/GSoC_2017/rapps/reactos/base/applications/rapps/gui.cpp [iso-8859-1] Fri Jul 28 22:37:24 2017 @@ -235,31 +235,31 @@ switch (idButton) { case ID_EXIT: - lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXIT); + lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_EXIT); break;
case ID_INSTALL: - lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_INSTALL); + lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_INSTALL); break;
case ID_UNINSTALL: - lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_UNINSTALL); + lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UNINSTALL); break;
case ID_MODIFY: - lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_MODIFY); + lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_MODIFY); break;
case ID_SETTINGS: - lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_SETTINGS); + lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_SETTINGS); break;
case ID_REFRESH: - lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH); + lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_REFRESH); break;
case ID_RESETDB: - lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_UPDATE_DB); + lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UPDATE_DB); break; } } @@ -380,7 +380,7 @@
BOOL AddColumn(INT Index, LPWSTR lpText, INT Width, INT Format) { - LV_COLUMNW Column; + LVCOLUMNW Column;
ZeroMemory(&Column, sizeof(Column));
@@ -395,7 +395,7 @@
INT AddItem(INT ItemIndex, INT IconIndex, LPWSTR lpText, LPARAM lParam) { - LV_ITEMW Item; + LVITEMW Item;
ZeroMemory(&Item, sizeof(Item));
@@ -484,6 +484,12 @@ } } return list; + } + + PAPPLICATION_INFO GetSelectedData() + { + INT item = GetSelectionMark(); + return (PAPPLICATION_INFO) GetItemData(item); } };
@@ -767,7 +773,7 @@ RECT rBottom;
/* Size status bar */ - m_StatusBar->SendMessage(WM_SIZE, 0, 0); + m_StatusBar->SendMessageW(WM_SIZE, 0, 0);
/* Size tool bar */ m_Toolbar->AutoSize(); @@ -1258,10 +1264,10 @@ case ID_INSTALL: if (nSelectedApps) { - DownloadManager::DownloadListOfApplications(m_ListView->GetCheckedItems()); + СDownloadManager::DownloadListOfApplications(m_ListView->GetCheckedItems()); UpdateApplicationsList(-1); } - else if(DownloadManager::DownloadApplication((PAPPLICATION_INFO) m_ListView->GetSelectionMark())) + else if(СDownloadManager::DownloadApplication(m_ListView->GetSelectedData())) { UpdateApplicationsList(-1); }
Modified: branches/GSoC_2017/rapps/reactos/base/applications/rapps/installed.cpp URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2017/rapps/reactos/base/app... ============================================================================== --- branches/GSoC_2017/rapps/reactos/base/applications/rapps/installed.cpp [iso-8859-1] (original) +++ branches/GSoC_2017/rapps/reactos/base/applications/rapps/installed.cpp [iso-8859-1] Fri Jul 28 22:37:24 2017 @@ -197,7 +197,7 @@ PINSTALLED_INFO Info; WCHAR szFullName[MAX_PATH] = L"Software\Microsoft\Windows\CurrentVersion\Uninstall\"; ATL::CStringW szMsgText, szMsgTitle; - INT ItemIndex = SendMessage(hListView, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); + INT ItemIndex = SendMessageW(hListView, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
if (!IS_INSTALLED_ENUM(SelectedEnumType)) return;
Modified: branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/en-US.rc URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2017/rapps/reactos/base/app... ============================================================================== --- branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/en-US.rc [iso-8859-1] (original) +++ branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/en-US.rc [iso-8859-1] Fri Jul 28 22:37:24 2017 @@ -90,7 +90,7 @@ PUSHBUTTON "Cancel", IDCANCEL, 150, 78, 60, 14 END
-IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 220, 72 +IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 220, 220 STYLE DS_SHELLFONT | DS_CENTER | WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE CAPTION "Downloading %ls..." FONT 8, "MS Shell Dlg" @@ -202,6 +202,7 @@ IDS_UNABLE_TO_DOWNLOAD "Unable to download the package! Address not found!" IDS_UNABLE_TO_DOWNLOAD2 "Unable to download the package! Check Internet Connection!" IDS_UNABLE_TO_REMOVE "Unable to remove data on the program from the registry!" + IDS_UNABLE_TO_INSTALL "Unable to open installer!" IDS_CERT_DOES_NOT_MATCH "SSL certificate verification failed." IDS_INTEG_CHECK_TITLE "Verifying package integrity..." IDS_INTEG_CHECK_FAIL "The package did not pass the integrity check, it may have been corrupted or tampered with during downloading. Running the software is not recommended." @@ -219,6 +220,8 @@ IDS_STATUS_UPDATE_AVAILABLE "Update available" IDS_STATUS_DOWNLOADING "Downloadingâ¦" IDS_STATUS_INSTALLING "Installingâ¦" + IDS_STATUS_WAITING "Waiting to installâ¦" + IDS_STATUS_FINISHED "Finished" END
STRINGTABLE
Modified: branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/ru-RU.rc URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2017/rapps/reactos/base/app... ============================================================================== --- branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/ru-RU.rc [iso-8859-1] (original) +++ branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/ru-RU.rc [iso-8859-1] Fri Jul 28 22:37:24 2017 @@ -90,7 +90,7 @@ PUSHBUTTON "ÐÑмена", IDCANCEL, 150, 78, 60, 14 END
-IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 220, 72 +IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 220, 220 STYLE DS_SHELLFONT | DS_CENTER | WS_POPUPWINDOW | WS_SYSMENU | WS_VISIBLE CAPTION "ÐагÑÑзка %ls..." FONT 8, "MS Shell Dlg" @@ -200,6 +200,7 @@ IDS_INFORMATION "ÐнÑоÑмаÑиÑ" IDS_UNABLE_TO_DOWNLOAD "Ðе ÑдалоÑÑ ÑкаÑаÑÑ Ð¿Ñиложение! Ðе найден адÑеÑ!" IDS_UNABLE_TO_DOWNLOAD2 "Ðе ÑдалоÑÑ ÑкаÑаÑÑ Ð¿Ñиложение! ÐÑовеÑÑÑе подклÑÑение к ÑеÑи ÐнÑеÑнеÑ!" + IDS_UNABLE_TO_INSTALL "Unable to open installer!" IDS_UNABLE_TO_REMOVE "Ðе ÑдалоÑÑ ÑдалиÑÑ Ð´Ð°Ð½Ð½Ñе о пÑогÑамме из ÑееÑÑÑа!" IDS_CERT_DOES_NOT_MATCH "ÐÑибка пÑовеÑки SSL ÑеÑÑиÑикаÑа." IDS_INTEG_CHECK_TITLE "ÐÑовеÑка ÑелоÑÑноÑÑи пÑиложениÑ..." @@ -216,6 +217,8 @@ IDS_STATUS_UPDATE_AVAILABLE "ÐÑÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ" IDS_STATUS_DOWNLOADING "ÐагÑÑжаеÑÑÑâ¦" IDS_STATUS_INSTALLING "УÑÑановкаâ¦" + IDS_STATUS_WAITING "Ðжидание ÑÑÑановкиâ¦" + IDS_STATUS_FINISHED "ÐавеÑÑено" END
STRINGTABLE
Modified: branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/uk-UA.rc URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2017/rapps/reactos/base/app... ============================================================================== --- branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/uk-UA.rc [iso-8859-1] (original) +++ branches/GSoC_2017/rapps/reactos/base/applications/rapps/lang/uk-UA.rc [iso-8859-1] Fri Jul 28 22:37:24 2017 @@ -98,7 +98,7 @@ PUSHBUTTON "СкаÑÑваÑи", IDCANCEL, 150, 78, 60, 14 END
-IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 220, 72 +IDD_DOWNLOAD_DIALOG DIALOGEX 0, 0, 220, 220 STYLE DS_SHELLFONT | DS_CENTER | WS_POPUPWINDOW | WS_SYSMENU | WS_VISIBLE CAPTION "ÐаванÑÐ°Ð¶ÐµÐ½Ð½Ñ %ls..." FONT 8, "MS Shell Dlg" @@ -208,6 +208,7 @@ IDS_INFORMATION "ÐнÑоÑмаÑÑÑ" IDS_UNABLE_TO_DOWNLOAD "Ðеможливо заванÑажиÑи додаÑок! ÐдÑеÑÑ Ð½Ðµ знайдено!" IDS_UNABLE_TO_DOWNLOAD2 "Ðеможливо заванÑажиÑи додаÑок! ÐеÑевÑÑÑе пÑдклÑÑÐµÐ½Ð½Ñ Ð´Ð¾ меÑÐµÐ¶Ñ ÐнÑеÑнеÑ!" + IDS_UNABLE_TO_INSTALL "Unable to open installer!" IDS_UNABLE_TO_REMOVE "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñи Ð´Ð°Ð½Ñ Ð¿Ñо пÑогÑÐ°Ð¼Ñ Ð· ÑеÑÑÑÑÑ!" IDS_CERT_DOES_NOT_MATCH "Ðомилка пеÑевÑки ÑеÑÑиÑÑкаÑÑ SSL." IDS_INTEG_CHECK_TITLE "ÐеÑевÑÑка ÑÑлÑÑÑноÑÑÑ Ð´Ð¾Ð´Ð°ÑкÑ..." @@ -224,6 +225,8 @@ IDS_STATUS_UPDATE_AVAILABLE "РоновленнÑ" IDS_STATUS_DOWNLOADING "ÐаванÑажÑÑÑÑÑÑâ¦" IDS_STATUS_INSTALLING "ÐÑÑановлÑÑÑÑÑÑâ¦" + IDS_STATUS_WAITING "ÐÑÑкÑÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð°Ð½ÑаженнÑâ¦" + IDS_STATUS_FINISHED "ÐавеÑÑено" END
STRINGTABLE
Modified: branches/GSoC_2017/rapps/reactos/base/applications/rapps/loaddlg.cpp URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2017/rapps/reactos/base/app... ============================================================================== --- branches/GSoC_2017/rapps/reactos/base/applications/rapps/loaddlg.cpp [iso-8859-1] (original) +++ branches/GSoC_2017/rapps/reactos/base/applications/rapps/loaddlg.cpp [iso-8859-1] Fri Jul 28 22:37:24 2017 @@ -10,23 +10,23 @@ * Copyright 2017 Alexander Shaposhnikov (chaez.san@gmail.com) */
-/* - * Based on Wine dlls/shdocvw/shdocvw_main.c - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ + /* + * Based on Wine dlls/shdocvw/shdocvw_main.c + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * 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 "rapps.h"
@@ -35,9 +35,31 @@
#include <atlbase.h> #include <atlcom.h> +#include <atlwin.h> #include <wininet.h> #include <shellutils.h> + +#include <rosctrls.h> #include <windowsx.h> + +#include "rosui.h" + +typedef enum +{ + 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) +{ + ATL::CStringW szString; + szString.LoadStringW(StatusParam); + return szString; +}
class CDownloadDialog : public CComObjectRootEx<CComMultiThreadModelNoCS>, @@ -50,7 +72,7 @@ public: ~CDownloadDialog() { - DestroyWindow(m_hDialog); + //DestroyWindow(m_hDialog); }
HRESULT Initialize(HWND Dlg, BOOL *pbCancelled) @@ -179,6 +201,75 @@ BEGIN_COM_MAP(CDownloadDialog) COM_INTERFACE_ENTRY_IID(IID_IBindStatusCallback, IBindStatusCallback) END_COM_MAP() +}; + +class CDowloadingAppsListView + : public CUiWindow<CListView> +{ +public: + HWND Create(HWND hwndParent) + { + RECT r = {10, 150, 320, 350}; + const DWORD style = WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL + | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | LVS_NOCOLUMNHEADER; + + HWND hwnd = CListView::Create(hwndParent, r, NULL, style, WS_EX_CLIENTEDGE); + + AddColumn(0, 150, LVCFMT_LEFT); + AddColumn(1, 120, LVCFMT_LEFT); + + return hwnd; + } + + VOID LoadList(ATL::CSimpleArray<PAPPLICATION_INFO> arrInfo) + { + for (INT i = 0; i < arrInfo.GetSize(); ++i) + { + PAPPLICATION_INFO AppInfo = arrInfo[i]; + AddRow(i, AppInfo->szName.GetString(), DOWNLOAD_STATUS::DLWaiting); + } + } + + VOID SetDownloadStatus(INT ItemIndex, DOWNLOAD_STATUS Status) + { + HWND hListView = GetWindow(); + ATL::CStringW szBuffer = LoadStatusString(Status); + ListView_SetItemText(hListView, ItemIndex, 1, const_cast<LPWSTR>(szBuffer.GetString())); + } + + BOOL AddItem(INT ItemIndex, LPWSTR lpText) + { + LVITEMW Item; + + ZeroMemory(&Item, sizeof(Item)); + + Item.mask = LVIF_TEXT | LVIF_STATE; + Item.pszText = lpText; + Item.iItem = ItemIndex; + + return InsertItem(&Item); + } + + VOID AddRow(INT RowIndex, LPCWSTR szAppName, const DOWNLOAD_STATUS Status) + { + ATL::CStringW szStatus = LoadStatusString(Status); + AddItem(RowIndex, + const_cast<LPWSTR>(szAppName)); + SetDownloadStatus(RowIndex, Status); + } + + BOOL AddColumn(INT Index, INT Width, INT Format) + { + LVCOLUMNW Column; + ZeroMemory(&Column, sizeof(Column)); + + Column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM; + Column.iSubItem = Index; + Column.cx = Width; + Column.fmt = Format; + + return (InsertColumn(Index, &Column) == -1) ? FALSE : TRUE; + } };
extern "C" @@ -245,26 +336,31 @@ { ATL::CString szMsgText; if (szMsgText.LoadStringW(hInst, StringID)) + { MessageBoxW(hMainWnd, szMsgText.GetString(), NULL, MB_OK | MB_ICONERROR); -} - -// DownloadManager - -PAPPLICATION_INFO DownloadManager::AppInfo = NULL; - -INT_PTR CALLBACK DownloadManager::DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + } +} + +// ÑDownloadManager +PAPPLICATION_INFO ÑDownloadManager::AppInfo; +ATL::CSimpleArray<PAPPLICATION_INFO> ÑDownloadManager::AppsToInstallList; +CDowloadingAppsListView ÑDownloadManager::DownloadsListView; +INT ÑDownloadManager::iCurrentApp; + +#define DL_START_NEW WM_APP + 1 + +INT_PTR CALLBACK ÑDownloadManager::DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { HANDLE Thread; DWORD ThreadId; HWND Item; + static WCHAR szCaption[MAX_PATH];
switch (uMsg) { case WM_INITDIALOG: { HICON hIconSm, hIconBg; - WCHAR szCaption[MAX_PATH]; - ATL::CStringW szNewCaption;
hIconBg = (HICON) GetClassLongW(hMainWnd, GCLP_HICON); hIconSm = (HICON) GetClassLongW(hMainWnd, GCLP_HICONSM); @@ -274,11 +370,6 @@ SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM) hIconBg); SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM) hIconSm); } - - // Change caption to show the currently downloaded app - GetWindowTextW(Dlg, szCaption, MAX_PATH); - szNewCaption.Format(szCaption, AppInfo->szName.GetString()); - SetWindowTextW(Dlg, szNewCaption.GetString());
SetWindowLongW(Dlg, GWLP_USERDATA, 0); Item = GetDlgItem(Dlg, IDC_DOWNLOAD_PROGRESS); @@ -288,28 +379,77 @@ // and subclass it so that it learns to print a status text SendMessageW(Item, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); SendMessageW(Item, PBM_SETPOS, 0, 0); - + SetWindowSubclass(Item, DownloadProgressProc, 0, 0); } - - // add a neat placeholder until the download URL is retrieved - SetDlgItemTextW(Dlg, IDC_DOWNLOAD_STATUS, L"\x2022 \x2022 \x2022"); - - Thread = CreateThread(NULL, 0, ThreadFunc, Dlg, 0, &ThreadId); - if (!Thread) + // Get a dlg string for later use + GetWindowTextW(Dlg, szCaption, MAX_PATH); + + // Add a ListView + HWND hListView = DownloadsListView.Create(Dlg); + if (!hListView) + { return FALSE; - CloseHandle(Thread); + } + DownloadsListView.LoadList(AppsToInstallList); + iCurrentApp = -1; + + ShowWindow(Dlg, SW_SHOW); + + //Start new download + SendMessageW(Dlg, DL_START_NEW, 0, 0); + return TRUE; } case WM_COMMAND: if (wParam == IDCANCEL) { - SetWindowLongPtrW(Dlg, GWLP_USERDATA, 1); + SetWindowLongW(Dlg, GWLP_USERDATA, 1); PostMessageW(Dlg, WM_CLOSE, 0, 0); } return FALSE;
+ case DL_START_NEW: + + ++iCurrentApp; + // If some downloads left we issue it + if (iCurrentApp < AppsToInstallList.GetSize()) + { + AppInfo = AppsToInstallList[iCurrentApp]; + if (!AppInfo) + { + return FALSE; + } + + ATL::CStringW szNewCaption; + + // Reset progress bar + Item = GetDlgItem(Dlg, IDC_DOWNLOAD_PROGRESS); + if (Item) + { + SendMessageW(Item, PBM_SETPOS, 0, 0); + } + + // Change caption to show the currently downloaded app + szNewCaption.Format(szCaption, AppInfo->szName.GetString()); + SetWindowTextW(Dlg, szNewCaption.GetString()); + + // Add a neat placeholder until the download URL is retrieved + SetDlgItemTextW(Dlg, IDC_DOWNLOAD_STATUS, L"\x2022 \x2022 \x2022"); + Thread = CreateThread(NULL, 0, ThreadFunc, Dlg, 0, &ThreadId); + + if (!Thread) + { + return FALSE; + } + + CloseHandle(Thread); + return TRUE; + } + // No downloads left, closing (fallthrough) + case WM_CLOSE: + EndDialog(Dlg, 0); DestroyWindow(Dlg); return TRUE;
@@ -318,7 +458,7 @@ } }
-LRESULT CALLBACK DownloadManager::DownloadProgressProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) +LRESULT CALLBACK ÑDownloadManager::DownloadProgressProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { static ATL::CStringW szProgressText;
@@ -381,6 +521,7 @@
/* Raymond Chen says that we should safely unsubclass all the things! (http://blogs.msdn.com/b/oldnewthing/archive/2003/11/11/55653.aspx) */ + case WM_NCDESTROY: { szProgressText.Empty(); @@ -392,41 +533,49 @@ } }
-DWORD WINAPI DownloadManager::ThreadFunc(LPVOID Context) +DWORD WINAPI ÑDownloadManager::ThreadFunc(LPVOID Context) { CComPtr<IBindStatusCallback> dl; ATL::CStringW Path; PWSTR p, q; HWND Dlg = (HWND) Context; + ULONG dwContentLen, dwBytesWritten, dwBytesRead, dwStatus; ULONG dwCurrentBytesRead = 0; ULONG dwStatusLen = sizeof(dwStatus); + BOOL bCancelled = FALSE; BOOL bTempfile = FALSE; BOOL bCab = FALSE; + HINTERNET hOpen = NULL; HINTERNET hFile = NULL; HANDLE hOut = INVALID_HANDLE_VALUE; + unsigned char lpBuffer[4096]; LPCWSTR lpszAgent = L"RApps/1.0"; URL_COMPONENTS urlComponents; size_t urlLength, filenameLength;
+ const INT iAppId = iCurrentApp; + const PAPPLICATION_INFO pCurrentInfo = AppInfo; if (!AppInfo) { MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD); goto end; }
- /* build the path for the download */ - p = wcsrchr(AppInfo->szUrlDownload.GetString(), L'/'); - q = wcsrchr(AppInfo->szUrlDownload.GetString(), L'?'); - - /* do we have a final slash separator? */ + DownloadsListView.SetDownloadStatus(iAppId, DOWNLOAD_STATUS::DLDownloading); + + // build the path for the download + p = wcsrchr(pCurrentInfo->szUrlDownload.GetString(), L'/'); + q = wcsrchr(pCurrentInfo->szUrlDownload.GetString(), L'?'); + + // do we have a final slash separator? if (!p) goto end;
- /* prepare the tentative length of the filename, maybe we've to remove part of it later on */ + // 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 @@ -434,8 +583,8 @@ if (q && q > p && (q - p) > 0) filenameLength -= wcslen(q - 1) * sizeof(WCHAR);
- /* is this URL an update package for RAPPS? if so store it in a different place */ - if (AppInfo->szUrlDownload == APPLICATION_DATABASE_URL) + // is this URL an update package for RAPPS? if so store it in a different place + if (pCurrentInfo->szUrlDownload == APPLICATION_DATABASE_URL) { bCab = TRUE; if (!GetStorageDirectory(Path)) @@ -446,24 +595,25 @@ Path = SettingsInfo.szDownloadDir; }
- /* is the path valid? can we access it? */ + // is the path valid? can we access it? if (GetFileAttributesW(Path.GetString()) == INVALID_FILE_ATTRIBUTES) { if (!CreateDirectoryW(Path.GetString(), NULL)) goto end; }
- /* append a \ to the provided file system path, and the filename portion from the URL after that */ - Path.Format(L"\%ls", (p + 1)); - - if (!bCab && AppInfo->szSHA1[0] && GetFileAttributesW(Path.GetString()) != INVALID_FILE_ATTRIBUTES) - { - /* only open it in case of total correctness */ - if (VerifyInteg(AppInfo->szSHA1, Path)) + // append a \ to the provided file system path, and the filename portion from the URL after that + Path += L"\"; + Path += (LPWSTR) (p + 1); + + if (!bCab && pCurrentInfo->szSHA1[0] && GetFileAttributesW(Path.GetString()) != INVALID_FILE_ATTRIBUTES) + { + // only open it in case of total correctness + if (VerifyInteg(pCurrentInfo->szSHA1, Path)) goto run; }
- /* download it */ + // download it bTempfile = TRUE; CDownloadDialog_Constructor(Dlg, &bCancelled, IID_PPV_ARG(IBindStatusCallback, &dl));
@@ -473,16 +623,16 @@ /* FIXME: this should just be using the system-wide proxy settings */ switch (SettingsInfo.Proxy) { - case 0: /* preconfig */ + case 0: // preconfig hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); break; - case 1: /* direct (no proxy) */ + case 1: // direct (no proxy) hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); break; - case 2: /* use proxy */ + case 2: // use proxy hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PROXY, SettingsInfo.szProxyServer, SettingsInfo.szNoProxyFor, 0); break; - default: /* preconfig */ + default: // preconfig hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); break; } @@ -490,7 +640,7 @@ if (!hOpen) goto end;
- hFile = InternetOpenUrlW(hOpen, AppInfo->szUrlDownload, NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_KEEP_CONNECTION, 0); + hFile = InternetOpenUrlW(hOpen, pCurrentInfo->szUrlDownload, NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_KEEP_CONNECTION, 0); if (!hFile) { MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD2); @@ -511,25 +661,25 @@ memset(&urlComponents, 0, sizeof(urlComponents)); urlComponents.dwStructSize = sizeof(urlComponents);
- urlLength = AppInfo->szUrlDownload.GetLength(); + urlLength = pCurrentInfo->szUrlDownload.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(AppInfo->szUrlDownload, urlLength + 1, ICU_DECODE | ICU_ESCAPE, &urlComponents)) + if (!InternetCrackUrlW(pCurrentInfo->szUrlDownload, urlLength + 1, ICU_DECODE | ICU_ESCAPE, &urlComponents)) goto end;
if (urlComponents.nScheme == INTERNET_SCHEME_HTTP || urlComponents.nScheme == INTERNET_SCHEME_HTTPS) - HttpQueryInfo(hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwContentLen, &dwStatus, 0); + HttpQueryInfoW(hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwContentLen, &dwStatus, 0);
if (urlComponents.nScheme == INTERNET_SCHEME_FTP) dwContentLen = FtpGetFileSize(hFile, &dwStatus);
#ifdef USE_CERT_PINNING - /* are we using HTTPS to download the RAPPS update package? check if the certificate is original */ + // are we using HTTPS to download the RAPPS update package? check if the certificate is original if ((urlComponents.nScheme == INTERNET_SCHEME_HTTPS) && - (wcscmp(AppInfo->szUrlDownload, APPLICATION_DATABASE_URL) == 0) && + (wcscmp(pCurrentInfo->szUrlDownload, APPLICATION_DATABASE_URL) == 0) && (!CertIsValid(hOpen, urlComponents.lpszHostName))) { MessageBox_LoadString(hMainWnd, IDS_CERT_DOES_NOT_MATCH); @@ -560,7 +710,7 @@ }
dwCurrentBytesRead += dwBytesRead; - dl->OnProgress(dwCurrentBytesRead, dwContentLen, 0, AppInfo->szUrlDownload); + dl->OnProgress(dwCurrentBytesRead, dwContentLen, 0, pCurrentInfo->szUrlDownload); } while (dwBytesRead && !bCancelled);
CloseHandle(hOut); @@ -571,19 +721,19 @@
/* 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 && AppInfo->szSHA1[0] != 0) + if (!bCab && pCurrentInfo->szSHA1[0] != 0) { ATL::CStringW szMsgText;
- /* change a few strings in the download dialog to reflect the verification process */ + // change a few strings in the download dialog to reflect the verification process if (!szMsgText.LoadStringW(hInst, IDS_INTEG_CHECK_TITLE)) goto end;
- SetWindowText(Dlg, szMsgText.GetString()); + SetWindowTextW(Dlg, szMsgText.GetString()); SendMessageW(GetDlgItem(Dlg, IDC_DOWNLOAD_STATUS), WM_SETTEXT, 0, (LPARAM) Path.GetString());
- /* this may take a while, depending on the file size */ - if (!VerifyInteg(AppInfo->szSHA1, Path.GetString())) + // this may take a while, depending on the file size + if (!VerifyInteg(pCurrentInfo->szSHA1, Path.GetString())) { if (!szMsgText.LoadStringW(hInst, IDS_INTEG_CHECK_FAIL)) goto end; @@ -593,12 +743,33 @@ } }
- ShowWindow(Dlg, SW_HIDE);
run: - /* run it */ + DownloadsListView.SetDownloadStatus(iAppId, DOWNLOAD_STATUS::DLWaitingToInstall); + + // run it if (!bCab) - ShellExecuteW(NULL, L"open", Path.GetString(), NULL, NULL, SW_SHOWNORMAL); + { + SHELLEXECUTEINFOW shExInfo = {0}; + shExInfo.cbSize = sizeof(shExInfo); + shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS; + shExInfo.lpVerb = L"open"; + shExInfo.lpFile = Path.GetString(); + shExInfo.lpParameters = L""; + shExInfo.nShow = SW_SHOW; + + if (ShellExecuteExW(&shExInfo)) + { + DownloadsListView.SetDownloadStatus(iAppId, DOWNLOAD_STATUS::DLInstalling); + //TODO: issue an install operation separately so that the apps could be downloaded in the background + WaitForSingleObject(shExInfo.hProcess, INFINITE); + CloseHandle(shExInfo.hProcess); + } + else + { + MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_INSTALL); + } + }
end: if (hOut != INVALID_HANDLE_VALUE) @@ -612,55 +783,55 @@ if (bCancelled || (SettingsInfo.bDelInstaller && !bCab)) DeleteFileW(Path.GetString()); } - - EndDialog(Dlg, 0); - + DownloadsListView.SetDownloadStatus(iAppId, DOWNLOAD_STATUS::DLFinished); + SendMessageW(Dlg, DL_START_NEW, 0, 0); return 0; }
-//TODO: Maybe launch this (similar function) in a seperate thread, so the list could be updated -BOOL DownloadManager::DownloadListOfApplications(const ATL::CSimpleArray<PAPPLICATION_INFO>& AppsList) -{ - BOOL bResult = TRUE; - - for (INT i = 0; i < AppsList.GetSize(); ++i) - { - bResult = DownloadApplication(AppsList[i]) && bResult; - } - return bResult; -} - -BOOL DownloadManager::DownloadApplication(PAPPLICATION_INFO pAppInfo) +BOOL ÑDownloadManager::DownloadListOfApplications(const ATL::CSimpleArray<PAPPLICATION_INFO>& AppsList) +{ + if (AppsList.GetSize() == 0) + { + return FALSE; + } + + // Initialize shared variables + AppsToInstallList = AppsList; + + // Create a dialog and issue a download process + LaunchDownloadDialog(); + + return TRUE; +} + +BOOL ÑDownloadManager::DownloadApplication(PAPPLICATION_INFO pAppInfo) { if (!pAppInfo) { return FALSE; }
- // Create a dialog and issue a download process - AppInfo = pAppInfo; + AppsToInstallList.RemoveAll(); + AppsToInstallList.Add(pAppInfo); LaunchDownloadDialog();
- WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_INSTALL, AppInfo->szName.GetString()); - return TRUE; }
-VOID DownloadManager::DownloadApplicationsDB(LPCWSTR lpUrl) +VOID ÑDownloadManager::DownloadApplicationsDB(LPCWSTR lpUrl) { APPLICATION_INFO IntInfo; IntInfo.szUrlDownload = lpUrl;
- AppInfo = &IntInfo; - - LaunchDownloadDialog(); + DownloadApplication(&IntInfo); }
//TODO: Reuse the dialog -VOID DownloadManager::LaunchDownloadDialog() +VOID ÑDownloadManager::LaunchDownloadDialog() { CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG), hMainWnd, DownloadDlgProc); -} +} +// CDownloadManager
Modified: branches/GSoC_2017/rapps/reactos/base/applications/rapps/misc.cpp URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2017/rapps/reactos/base/app... ============================================================================== --- branches/GSoC_2017/rapps/reactos/base/applications/rapps/misc.cpp [iso-8859-1] (original) +++ branches/GSoC_2017/rapps/reactos/base/applications/rapps/misc.cpp [iso-8859-1] Fri Jul 28 22:37:24 2017 @@ -46,7 +46,6 @@ typedef HRESULT(WINAPI *fnExtract)(SESSION *dest, LPCSTR szCabName); fnExtract pfnExtract;
- INT GetSystemColorDepth(VOID) { @@ -56,7 +55,7 @@ pDevMode.dmSize = sizeof(pDevMode); pDevMode.dmDriverExtra = 0;
- if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &pDevMode)) + if (!EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &pDevMode)) { /* TODO: Error message */ return ILC_COLOR; @@ -170,7 +169,7 @@ ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_STATE; - GetMenuItemInfo(hPopupMenu, DefaultItem, FALSE, &mii); + GetMenuItemInfoW(hPopupMenu, DefaultItem, FALSE, &mii);
if (!(mii.fState & MFS_GRAYED)) SetMenuDefaultItem(hPopupMenu, DefaultItem, FALSE);
Modified: branches/GSoC_2017/rapps/reactos/base/applications/rapps/rapps.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2017/rapps/reactos/base/app... ============================================================================== --- branches/GSoC_2017/rapps/reactos/base/applications/rapps/rapps.h [iso-8859-1] (original) +++ branches/GSoC_2017/rapps/reactos/base/applications/rapps/rapps.h [iso-8859-1] Fri Jul 28 22:37:24 2017 @@ -249,12 +249,15 @@ VOID FillDefaultSettings(PSETTINGS_INFO pSettingsInfo);
/* loaddlg.cpp */ - -class DownloadManager +class CDowloadingAppsListView; + +class ÑDownloadManager { static PAPPLICATION_INFO AppInfo; + static ATL::CSimpleArray<PAPPLICATION_INFO> AppsToInstallList; + static CDowloadingAppsListView DownloadsListView; + static INT iCurrentApp; public: - static INT_PTR CALLBACK DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK DownloadProgressProc(HWND hWnd, UINT uMsg,
Modified: branches/GSoC_2017/rapps/reactos/base/applications/rapps/resource.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2017/rapps/reactos/base/app... ============================================================================== --- branches/GSoC_2017/rapps/reactos/base/applications/rapps/resource.h [iso-8859-1] (original) +++ branches/GSoC_2017/rapps/reactos/base/applications/rapps/resource.h [iso-8859-1] Fri Jul 28 22:37:24 2017 @@ -107,6 +107,7 @@ #define IDS_UNABLE_TO_WRITE 125 #define IDS_SELECT_ALL 126 #define IDS_INSTALL_SELECTED 127 +#define IDS_UNABLE_TO_INSTALL 128
/* Tooltips */ #define IDS_TOOLTIP_INSTALL 200 @@ -176,6 +177,8 @@ #define IDS_STATUS_UPDATE_AVAILABLE 803 #define IDS_STATUS_DOWNLOADING 804 #define IDS_STATUS_INSTALLING 805 +#define IDS_STATUS_WAITING 806 +#define IDS_STATUS_FINISHED 807
/* App license names */ #define IDS_LICENSE_OPENSOURCE 900