https://git.reactos.org/?p=reactos.git;a=commitdiff;h=143b2a50350b3c9608d65…
commit 143b2a50350b3c9608d65fbd2675f32e06c3babe
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Sun Oct 3 20:35:13 2021 +0200
Commit: Mark Jansen <mark.jansen(a)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(a)reactos.org)
- * Copyright 2017 Alexander Shaposhnikov (sanchaez(a)reactos.org)
- * Copyright 2020 He Yang (1160386205(a)qq.com)
+ * COPYRIGHT: Copyright 2009 Dmitry Chapyshev <dmitry(a)reactos.org>
+ * Copyright 2017 Alexander Shaposhnikov <sanchaez(a)reactos.org>
+ * Copyright 2020 He Yang <1160386205(a)qq.com>
+ * Copyright 2021 Mark Jansen <mark.jansen(a)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;
}