https://git.reactos.org/?p=reactos.git;a=commitdiff;h=143b2a50350b3c9608d65f...
commit 143b2a50350b3c9608d65fbd2675f32e06c3babe Author: Mark Jansen mark.jansen@reactos.org AuthorDate: Sun Oct 3 20:35:13 2021 +0200 Commit: Mark Jansen mark.jansen@reactos.org CommitDate: Wed Oct 13 19:27:40 2021 +0200
[RAPPS] Speed up installed application loading
Only load in details when we are going to display them --- base/applications/rapps/appview.cpp | 2 + base/applications/rapps/gui.cpp | 4 +- base/applications/rapps/include/appview.h | 1 - base/applications/rapps/include/dialogs.h | 2 +- base/applications/rapps/include/installed.h | 57 ++++--- base/applications/rapps/installed.cpp | 241 ++++++++++++---------------- base/applications/rapps/loaddlg.cpp | 4 +- 7 files changed, 140 insertions(+), 171 deletions(-)
diff --git a/base/applications/rapps/appview.cpp b/base/applications/rapps/appview.cpp index 631eecbad9c..a9fe2922254 100644 --- a/base/applications/rapps/appview.cpp +++ b/base/applications/rapps/appview.cpp @@ -398,6 +398,8 @@ BOOL CAppRichEdit::ShowInstalledAppInfo(CInstalledApplicationInfo *Info) SetText(Info->szDisplayName, CFE_BOLD); InsertText(L"\n", 0);
+ Info->EnsureDetailsLoaded(); + InsertTextWithString(IDS_INFO_VERSION, CFE_BOLD, Info->szDisplayVersion, 0); InsertTextWithString(IDS_INFO_PUBLISHER, CFE_BOLD, Info->szPublisher, 0); InsertTextWithString(IDS_INFO_REGOWNER, CFE_BOLD, Info->szRegOwner, 0); diff --git a/base/applications/rapps/gui.cpp b/base/applications/rapps/gui.cpp index f0616c08aff..80cd779bed1 100644 --- a/base/applications/rapps/gui.cpp +++ b/base/applications/rapps/gui.cpp @@ -567,7 +567,7 @@ VOID CMainWindow::OnCommand(WPARAM wParam, LPARAM lParam) CAvailableApplicationInfo *FocusedApps = (CAvailableApplicationInfo *)m_ApplicationView->GetFocusedItemData(); if (FocusedApps) { - if (DownloadApplication(FocusedApps, FALSE)) + if (DownloadApplication(FocusedApps)) { UpdateApplicationsList(-1); } @@ -782,7 +782,7 @@ BOOL CMainWindow::InstallApplication(CAvailableApplicationInfo *Info) { if (Info) { - if (DownloadApplication(Info, FALSE)) + if (DownloadApplication(Info)) { UpdateApplicationsList(-1); return TRUE; diff --git a/base/applications/rapps/include/appview.h b/base/applications/rapps/include/appview.h index b625d5ed296..9042a361d33 100644 --- a/base/applications/rapps/include/appview.h +++ b/base/applications/rapps/include/appview.h @@ -191,7 +191,6 @@ public: HWND Create(HWND hwndParent);
BOOL ShowAvailableAppInfo(CAvailableApplicationInfo *Info); - BOOL ShowInstalledAppInfo(CInstalledApplicationInfo *Info);
VOID SetWelcomeText(); diff --git a/base/applications/rapps/include/dialogs.h b/base/applications/rapps/include/dialogs.h index 917effd8c6e..79d7d494017 100644 --- a/base/applications/rapps/include/dialogs.h +++ b/base/applications/rapps/include/dialogs.h @@ -13,5 +13,5 @@ VOID MainWindowLoop(INT nShowCmd);
// Download dialogs VOID DownloadApplicationsDB(LPCWSTR lpUrl, BOOL IsOfficial); -BOOL DownloadApplication(CAvailableApplicationInfo* pAppInfo, BOOL bIsModal); +BOOL DownloadApplication(CAvailableApplicationInfo* pAppInfo); BOOL DownloadListOfApplications(const ATL::CSimpleArray<CAvailableApplicationInfo>& AppsList, BOOL bIsModal); diff --git a/base/applications/rapps/include/installed.h b/base/applications/rapps/include/installed.h index 6e950056481..68ada9da094 100644 --- a/base/applications/rapps/include/installed.h +++ b/base/applications/rapps/include/installed.h @@ -5,41 +5,48 @@
class CInstalledApplicationInfo { +private: + BOOL m_IsUserKey; + REGSAM m_WowKey; + HKEY m_hSubKey; + + CStringW m_szKeyName; + public: - BOOL IsUserKey; - REGSAM WowKey; - HKEY hSubKey; - BOOL bIsUpdate = FALSE; + CInstalledApplicationInfo(BOOL bIsUserKey, REGSAM RegWowKey, HKEY hKey, const CStringW& szKeyName); + ~CInstalledApplicationInfo();
- ATL::CStringW szKeyName; + VOID EnsureDetailsLoaded();
- CInstalledApplicationInfo(BOOL bIsUserKey, REGSAM RegWowKey, HKEY hKey); BOOL GetApplicationRegString(LPCWSTR lpKeyName, ATL::CStringW& String); BOOL GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue); BOOL RetrieveIcon(ATL::CStringW& IconLocation); BOOL UninstallApplication(BOOL bModify); LSTATUS RemoveFromRegistry();
- ATL::CStringW szDisplayIcon; - ATL::CStringW szDisplayName; - ATL::CStringW szDisplayVersion; - ATL::CStringW szPublisher; - ATL::CStringW szRegOwner; - ATL::CStringW szProductID; - ATL::CStringW szHelpLink; - ATL::CStringW szHelpTelephone; - ATL::CStringW szReadme; - ATL::CStringW szContact; - ATL::CStringW szURLUpdateInfo; - ATL::CStringW szURLInfoAbout; - ATL::CStringW szComments; - ATL::CStringW szInstallDate; - ATL::CStringW szInstallLocation; - ATL::CStringW szInstallSource; - ATL::CStringW szUninstallString; - ATL::CStringW szModifyPath; + // These fields are always loaded + BOOL bIsUpdate; + CStringW szDisplayIcon; + CStringW szDisplayName; + CStringW szDisplayVersion; + CStringW szComments; + + // These details are loaded on demand + CStringW szPublisher; + CStringW szRegOwner; + CStringW szProductID; + CStringW szHelpLink; + CStringW szHelpTelephone; + CStringW szReadme; + CStringW szContact; + CStringW szURLUpdateInfo; + CStringW szURLInfoAbout; + CStringW szInstallDate; + CStringW szInstallLocation; + CStringW szInstallSource; + CStringW szUninstallString; + CStringW szModifyPath;
- ~CInstalledApplicationInfo(); };
typedef BOOL(CALLBACK *APPENUMPROC)(CInstalledApplicationInfo * Info, PVOID param); diff --git a/base/applications/rapps/installed.cpp b/base/applications/rapps/installed.cpp index eaec4429480..fed899e9448 100644 --- a/base/applications/rapps/installed.cpp +++ b/base/applications/rapps/installed.cpp @@ -2,123 +2,122 @@ * PROJECT: ReactOS Applications Manager * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Classes for working with installed applications - * COPYRIGHT: Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org) - * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org) - * Copyright 2020 He Yang (1160386205@qq.com) + * COPYRIGHT: Copyright 2009 Dmitry Chapyshev dmitry@reactos.org + * Copyright 2017 Alexander Shaposhnikov sanchaez@reactos.org + * Copyright 2020 He Yang 1160386205@qq.com + * Copyright 2021 Mark Jansen mark.jansen@reactos.org */ -#include "rapps.h"
+#include "rapps.h" #include "installed.h" - #include "misc.h"
-CInstalledApplicationInfo::CInstalledApplicationInfo(BOOL bIsUserKey, REGSAM RegWowKey, HKEY hKey) - : IsUserKey(bIsUserKey), WowKey(RegWowKey), hSubKey(hKey) +CInstalledApplicationInfo::CInstalledApplicationInfo(BOOL bIsUserKey, REGSAM RegWowKey, HKEY hKey, const CStringW& szKeyName) + : m_IsUserKey(bIsUserKey) + , m_WowKey(RegWowKey) + , m_hSubKey(hKey) + , m_szKeyName(szKeyName) { - // if Initialize failed, hSubKey will be closed automatically and set to zero - - DWORD dwSize = MAX_PATH, dwType, dwValue; - BOOL bIsSystemComponent; - ATL::CStringW szParentKeyName; - - dwType = REG_DWORD; - dwSize = sizeof(DWORD); + DWORD dwSize = 0; + bIsUpdate = (RegQueryValueExW(m_hSubKey, L"ParentKeyName", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS); +}
- if (RegQueryValueExW(hSubKey, - L"SystemComponent", - NULL, - &dwType, - (LPBYTE)&dwValue, - &dwSize) == ERROR_SUCCESS) +CInstalledApplicationInfo::~CInstalledApplicationInfo() +{ + if (m_hSubKey) { - bIsSystemComponent = (dwValue == 0x1); + CloseHandle(m_hSubKey); + m_hSubKey = NULL; } - else +} + +void CInstalledApplicationInfo::EnsureDetailsLoaded() +{ + // Key not closed, so we have not loaded details yet + if (m_hSubKey) { - bIsSystemComponent = FALSE; - } + GetApplicationRegString(L"Publisher", szPublisher); + GetApplicationRegString(L"RegOwner", szRegOwner); + GetApplicationRegString(L"ProductID", szProductID); + GetApplicationRegString(L"HelpLink", szHelpLink); + GetApplicationRegString(L"HelpTelephone", szHelpTelephone); + GetApplicationRegString(L"Readme", szReadme); + GetApplicationRegString(L"Contact", szContact); + GetApplicationRegString(L"URLUpdateInfo", szURLUpdateInfo); + GetApplicationRegString(L"URLInfoAbout", szURLInfoAbout); + if (GetApplicationRegString(L"InstallDate", szInstallDate) == FALSE) + { + // It might be a DWORD (Unix timestamp). try again. + DWORD dwInstallTimeStamp; + if (GetApplicationRegDword(L"InstallDate", &dwInstallTimeStamp)) + { + FILETIME InstallFileTime; + SYSTEMTIME InstallSystemTime, InstallLocalTime;
- dwType = REG_SZ; - dwSize = MAX_PATH * sizeof(WCHAR); - bIsUpdate = (RegQueryValueExW(hSubKey, - L"ParentKeyName", - NULL, - &dwType, - (LPBYTE)szParentKeyName.GetBuffer(MAX_PATH), - &dwSize) == ERROR_SUCCESS); - szParentKeyName.ReleaseBuffer(); + UnixTimeToFileTime(dwInstallTimeStamp, &InstallFileTime); + FileTimeToSystemTime(&InstallFileTime, &InstallSystemTime);
- if (bIsSystemComponent) - { - CloseHandle(hSubKey); - hSubKey = NULL; - } + // convert to localtime + SystemTimeToTzSpecificLocalTime(NULL, &InstallSystemTime, &InstallLocalTime);
-} + // convert to readable date string + int cchTimeStrLen = GetDateFormatW(LOCALE_USER_DEFAULT, 0, &InstallLocalTime, NULL, 0, 0);
-CInstalledApplicationInfo::~CInstalledApplicationInfo() -{ - if (hSubKey) - { - CloseHandle(hSubKey); - hSubKey = NULL; + GetDateFormatW( + LOCALE_USER_DEFAULT, // use default locale for current user + 0, &InstallLocalTime, NULL, szInstallDate.GetBuffer(cchTimeStrLen), cchTimeStrLen); + szInstallDate.ReleaseBuffer(); + } + } + GetApplicationRegString(L"InstallLocation", szInstallLocation); + GetApplicationRegString(L"InstallSource", szInstallSource); + GetApplicationRegString(L"UninstallString", szUninstallString); + GetApplicationRegString(L"ModifyPath",szModifyPath); + + CloseHandle(m_hSubKey); + m_hSubKey = NULL; } }
BOOL CInstalledApplicationInfo::GetApplicationRegString(LPCWSTR lpKeyName, ATL::CStringW& String) { - DWORD dwSize = 0; - String.Empty(); - DWORD dwType; + DWORD dwAllocated = 0, dwSize, dwType;
// retrieve the size of value first. - if (RegQueryValueExW(hSubKey, - lpKeyName, - NULL, - &dwType, - NULL, - &dwSize) != ERROR_SUCCESS) + if (RegQueryValueExW(m_hSubKey, lpKeyName, NULL, &dwType, NULL, &dwAllocated) != ERROR_SUCCESS || + dwType != REG_SZ) { + String.Empty(); return FALSE; }
- // TODO: I assume the type as REG_SZ. but I think REG_EXPAND_SZ should be handled correctly too. - if (dwType != REG_SZ) - { - return FALSE; - } + // query the value + dwSize = dwAllocated; + LSTATUS Result = + RegQueryValueExW(m_hSubKey, lpKeyName, NULL, NULL, (LPBYTE)String.GetBuffer(dwAllocated / sizeof(WCHAR)), &dwSize);
- // allocate buffer. - // attention: dwSize is size in bytes, and RegQueryValueExW does not guarantee the terminating null character. - String.GetBuffer(dwSize + sizeof(WCHAR)); + dwSize = min(dwAllocated, dwSize); + // CString takes care of zero-terminating it + String.ReleaseBuffer(dwSize / sizeof(WCHAR));
- // query the value - if (RegQueryValueExW(hSubKey, - lpKeyName, - NULL, - NULL, - (LPBYTE)String.GetBuffer(), - &dwSize) != ERROR_SUCCESS) + if (Result != ERROR_SUCCESS) { - String.ReleaseBuffer(); String.Empty(); return FALSE; } - String.GetBuffer()[dwSize / sizeof(WCHAR)] = L'\0'; // ensure zero terminated - String.ReleaseBuffer(); + return TRUE; }
BOOL CInstalledApplicationInfo::GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue) { - DWORD dwType = REG_DWORD; - DWORD dwSize = sizeof(DWORD); - if (RegQueryValueExW(hSubKey, + DWORD dwSize = sizeof(DWORD), dwType; + if (RegQueryValueExW(m_hSubKey, lpKeyName, NULL, &dwType, (LPBYTE)lpValue, - &dwSize) != ERROR_SUCCESS) + &dwSize) != ERROR_SUCCESS || dwType != REG_DWORD) { return FALSE; } @@ -148,7 +147,7 @@ typedef LSTATUS (WINAPI *RegDeleteKeyExWProc)(HKEY, LPCWSTR, REGSAM, DWORD);
LSTATUS CInstalledApplicationInfo::RemoveFromRegistry() { - ATL::CStringW szFullName = L"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + szKeyName; + ATL::CStringW szFullName = L"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + m_szKeyName; HMODULE hMod = GetModuleHandleW(L"advapi32.dll"); RegDeleteKeyExWProc pRegDeleteKeyExW;
@@ -166,12 +165,12 @@ LSTATUS CInstalledApplicationInfo::RemoveFromRegistry() if (pRegDeleteKeyExW) { /* Return it */ - return pRegDeleteKeyExW(IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, szFullName, WowKey, 0); + return pRegDeleteKeyExW(m_IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, szFullName, m_WowKey, 0); } }
/* Otherwise, return non-Ex function */ - return RegDeleteKeyW(IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, szFullName); + return RegDeleteKeyW(m_IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, szFullName); }
BOOL CInstalledApps::Enum(INT EnumType, APPENUMPROC lpEnumProc, PVOID param) @@ -225,72 +224,34 @@ BOOL CInstalledApps::Enum(INT EnumType, APPENUMPROC lpEnumProc, PVOID param) ItemIndex++;
szKeyName.ReleaseBuffer(); - if (RegOpenKeyW(hKey, szKeyName.GetString(), &hSubKey) == ERROR_SUCCESS) + if (RegOpenKeyW(hKey, szKeyName, &hSubKey) == ERROR_SUCCESS) { - BOOL bSuccess = FALSE; - CInstalledApplicationInfo *Info = new CInstalledApplicationInfo(RootKeyEnum[i] == HKEY_CURRENT_USER, RegSamEnum[i], hSubKey); - Info->szKeyName = szKeyName; + DWORD dwValue = 0; + BOOL bIsSystemComponent = FALSE;
- // check for failure. if failed to init, Info->hSubKey will be set to NULL - if (Info->hSubKey) + dwSize = sizeof(DWORD); + if (RegQueryValueExW(hSubKey, L"SystemComponent", NULL, NULL, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS) { - // those items without display name are ignored - if (Info->GetApplicationRegString(L"DisplayName", Info->szDisplayName)) - { - Info->GetApplicationRegString(L"DisplayIcon", Info->szDisplayIcon); - Info->GetApplicationRegString(L"DisplayVersion", Info->szDisplayVersion); - Info->GetApplicationRegString(L"Publisher", Info->szPublisher); - Info->GetApplicationRegString(L"RegOwner", Info->szRegOwner); - Info->GetApplicationRegString(L"ProductID", Info->szProductID); - Info->GetApplicationRegString(L"HelpLink", Info->szHelpLink); - Info->GetApplicationRegString(L"HelpTelephone", Info->szHelpTelephone); - Info->GetApplicationRegString(L"Readme", Info->szReadme); - Info->GetApplicationRegString(L"Contact", Info->szContact); - Info->GetApplicationRegString(L"URLUpdateInfo", Info->szURLUpdateInfo); - Info->GetApplicationRegString(L"URLInfoAbout", Info->szURLInfoAbout); - Info->GetApplicationRegString(L"Comments", Info->szComments); - if (Info->GetApplicationRegString(L"InstallDate", Info->szInstallDate) == FALSE) - { - // It might be a DWORD (Unix timestamp). try again. - DWORD dwInstallTimeStamp; - if (Info->GetApplicationRegDword(L"InstallDate", &dwInstallTimeStamp)) - { - FILETIME InstallFileTime; - SYSTEMTIME InstallSystemTime, InstallLocalTime; - - UnixTimeToFileTime(dwInstallTimeStamp, &InstallFileTime); - FileTimeToSystemTime(&InstallFileTime, &InstallSystemTime); - - // convert to localtime - SystemTimeToTzSpecificLocalTime(NULL, &InstallSystemTime, &InstallLocalTime); - - // convert to readable date string - int cchTimeStrLen = GetDateFormatW(LOCALE_USER_DEFAULT, - 0, - &InstallLocalTime, - NULL, 0, 0); - - GetDateFormatW(LOCALE_USER_DEFAULT, // use default locale for current user - 0, - &InstallLocalTime, - NULL, Info->szInstallDate.GetBuffer(cchTimeStrLen), cchTimeStrLen); - Info->szInstallDate.ReleaseBuffer(); - } - } - Info->GetApplicationRegString(L"InstallLocation", Info->szInstallLocation); - Info->GetApplicationRegString(L"InstallSource", Info->szInstallSource); - Info->GetApplicationRegString(L"UninstallString", Info->szUninstallString); - Info->GetApplicationRegString(L"ModifyPath", Info->szModifyPath); - - bSuccess = TRUE; - } + bIsSystemComponent = (dwValue == 0x1); + } + // Ignore system components + if (bIsSystemComponent) + { + RegCloseKey(hSubKey); + continue; }
- // close handle - if (Info->hSubKey) + BOOL bSuccess = FALSE; + CInstalledApplicationInfo *Info = new CInstalledApplicationInfo(RootKeyEnum[i] == HKEY_CURRENT_USER, RegSamEnum[i], hSubKey, szKeyName); + + // items without display name are ignored + if (Info->GetApplicationRegString(L"DisplayName", Info->szDisplayName)) { - CloseHandle(Info->hSubKey); - Info->hSubKey = NULL; + Info->GetApplicationRegString(L"DisplayIcon", Info->szDisplayIcon); + Info->GetApplicationRegString(L"DisplayVersion", Info->szDisplayVersion); + Info->GetApplicationRegString(L"Comments", Info->szComments); + + bSuccess = TRUE; }
if (bSuccess) diff --git a/base/applications/rapps/loaddlg.cpp b/base/applications/rapps/loaddlg.cpp index 49538ac1d06..d86bdda5131 100644 --- a/base/applications/rapps/loaddlg.cpp +++ b/base/applications/rapps/loaddlg.cpp @@ -1030,12 +1030,12 @@ BOOL DownloadListOfApplications(const ATL::CSimpleArray<CAvailableApplicationInf return TRUE; }
-BOOL DownloadApplication(CAvailableApplicationInfo* pAppInfo, BOOL bIsModal) +BOOL DownloadApplication(CAvailableApplicationInfo* pAppInfo) { if (!pAppInfo) return FALSE;
- CDownloadManager::Download(*pAppInfo, bIsModal); + CDownloadManager::Download(*pAppInfo, FALSE); return TRUE; }