* Separated available and installed version. 
  If the app is installed it's DisplayVersion is shown.
* Reduced registry key access checks
* Version parser WIP

svn path=/branches/GSoC_2017/rapps/; revision=75219
This commit is contained in:
Alexander Shaposhnikov 2017-06-27 23:21:58 +00:00
parent 928e1c0ba3
commit 17e36ed120
8 changed files with 153 additions and 86 deletions

View file

@ -9,20 +9,19 @@
#include "rapps.h"
template<typename T, size_t N, size_t N2>
inline void _AddText(T (&szText)[N], UINT a, T (&b)[N2], DWORD c, DWORD d) {
inline void _AddText(UINT a, LPCWSTR b, DWORD c, DWORD d) {
if (b[0] != '\0')
{
LoadStringW(hInst, a, szText, N);
WCHAR szText[MAX_STR_LEN];
LoadStringW(hInst, a, szText, _countof(szText));
InsertRichEditText(szText, c);
InsertRichEditText(b, d);
}
}
template<typename T, size_t N>
inline void _AddTextNewl(T (&szText)[N], UINT a, DWORD b) {
LoadStringW(hInst, a, szText, N);
inline void _AddTextNewl(UINT a, DWORD b) {
WCHAR szText[MAX_STR_LEN];
LoadStringW(hInst, a, szText, _countof(szText));
InsertRichEditText(L"\n", 0);
InsertRichEditText(szText, b);
InsertRichEditText(L"\n", 0);
@ -41,7 +40,7 @@ inline void _GetStringNullFailure(LPCWSTR a, T(&b)[N], T (&cFileName)[N2]) {
}
//App is "installed" if the RegName or Name is in the registry
inline bool _AppInstallCheckKey(PAPPLICATION_INFO Info, REGSAM key)
inline BOOL _AppInstallCheckWithKey(PAPPLICATION_INFO Info, REGSAM key)
{
return (*Info->szRegName
&& (IsInstalledApplication(Info->szRegName, TRUE, key)
@ -53,11 +52,27 @@ inline bool _AppInstallCheckKey(PAPPLICATION_INFO Info, REGSAM key)
//Check both registry keys in 64bit system
//TODO: check system type beforehand to avoid double checks?
inline bool _AppInstallCheck(PAPPLICATION_INFO Info) {
return _AppInstallCheckKey(Info, KEY_WOW64_32KEY)
|| _AppInstallCheckKey(Info, KEY_WOW64_64KEY);
inline BOOL _AppInstallCheck(PAPPLICATION_INFO Info) {
return _AppInstallCheckWithKey(Info, KEY_WOW64_32KEY)
|| _AppInstallCheckWithKey(Info, KEY_WOW64_64KEY);
}
//App is "installed" if the RegName or Name is in the registry
inline BOOL _GetInstalledVersionWithKey(PAPPLICATION_INFO Info, LPWSTR szVersion, UINT iVersionSize, REGSAM key)
{
return (*Info->szRegName
&& (InstalledVersion(szVersion, iVersionSize, Info->szRegName, TRUE, key)
|| InstalledVersion(szVersion, iVersionSize, Info->szRegName, FALSE, key)))
|| (*Info->szName && (InstalledVersion(szVersion, iVersionSize, Info->szName, TRUE, key)
|| InstalledVersion(szVersion, iVersionSize, Info->szName, FALSE, key)));
}
//App is "installed" if the RegName or Name is in the registry
inline BOOL _GetInstalledVersion(PAPPLICATION_INFO Info, LPWSTR szVersion, UINT iVersionSize)
{
return _GetInstalledVersionWithKey(Info, szVersion, iVersionSize, KEY_WOW64_32KEY)
|| _GetInstalledVersionWithKey(Info, szVersion, iVersionSize, KEY_WOW64_64KEY);
}
LIST_ENTRY CachedEntriesHead = { &CachedEntriesHead, &CachedEntriesHead };
PLIST_ENTRY pCachedEntry = &CachedEntriesHead;
@ -66,25 +81,30 @@ BOOL
ShowAvailableAppInfo(INT Index)
{
PAPPLICATION_INFO Info = (PAPPLICATION_INFO) ListViewGetlParam(Index);
WCHAR szText[MAX_STR_LEN];
BOOL bIsInstalled = _AppInstallCheck(Info);
WCHAR szVersion[MAX_PATH];
if (!Info) return FALSE;
NewRichEditText(Info->szName, CFE_BOLD);
if (_AppInstallCheck(Info))
if (bIsInstalled)
{
_AddTextNewl(szText, IDS_STATUS_INSTALLED, CFE_ITALIC);
_AddTextNewl(IDS_STATUS_INSTALLED, CFE_ITALIC);
if (_GetInstalledVersion(Info, szVersion, _countof(szVersion)))
{
_AddText(IDS_AINFO_VERSION, szVersion, CFE_BOLD, 0);
}
} else
{
_AddTextNewl(szText, IDS_STATUS_NOTINSTALLED, CFE_ITALIC);
_AddTextNewl(IDS_STATUS_NOTINSTALLED, CFE_ITALIC);
}
_AddText(szText, IDS_AINFO_VERSION, Info->szVersion, CFE_BOLD, 0);
_AddText(szText, IDS_AINFO_LICENSE, Info->szLicense, CFE_BOLD, 0);
_AddText(szText, IDS_AINFO_SIZE, Info->szSize, CFE_BOLD, 0);
_AddText(szText, IDS_AINFO_URLSITE, Info->szUrlSite, CFE_BOLD, CFE_LINK);
_AddText(szText, IDS_AINFO_DESCRIPTION, Info->szDesc, CFE_BOLD, 0);
_AddText(szText, IDS_AINFO_URLDOWNLOAD, Info->szUrlDownload, CFE_BOLD, CFE_LINK);
_AddText(IDS_AINFO_AVAILABLEVERSION, Info->szVersion, CFE_BOLD, 0);
_AddText(IDS_AINFO_LICENSE, Info->szLicense, CFE_BOLD, 0);
_AddText(IDS_AINFO_SIZE, Info->szSize, CFE_BOLD, 0);
_AddText(IDS_AINFO_URLSITE, Info->szUrlSite, CFE_BOLD, CFE_LINK);
_AddText(IDS_AINFO_DESCRIPTION, Info->szDesc, CFE_BOLD, 0);
_AddText(IDS_AINFO_URLDOWNLOAD, Info->szUrlDownload, CFE_BOLD, CFE_LINK);
return TRUE;
}

View file

@ -35,11 +35,12 @@ IsInstalledApplication(LPCWSTR lpRegName, BOOL IsUserKey, REGSAM keyWow)
{
HKEY hKey = NULL;
BOOL IsInstalled = FALSE;
WCHAR szPath[MAX_PATH] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
StringCbPrintfW(szPath, _countof(szPath), L"%ls\\%ls", szPath, lpRegName);
if ((RegOpenKeyExW(IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, keyWow | KEY_ENUMERATE_SUB_KEYS,
&hKey) == ERROR_SUCCESS) \
&& FindRegistryKeyByName(hKey, keyWow, lpRegName, NULL))
if (RegOpenKeyExW(IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
szPath, 0, keyWow | KEY_READ,
&hKey) == ERROR_SUCCESS)
{
IsInstalled = TRUE;
}
@ -52,35 +53,31 @@ InstalledVersion(LPWSTR szVersionResult, UINT iVersionResultSize, LPCWSTR lpRegN
{
DWORD dwSize = MAX_PATH;
DWORD dwType = REG_SZ;
WCHAR szVersion[MAX_PATH];
HKEY hKey, hSubKey;
BOOL HasVersion = FALSE;
WCHAR szVersion[MAX_PATH] = L"";
HKEY hKey;
BOOL bHasVersion = FALSE;
iVersionResultSize = 0;
WCHAR szPath[MAX_PATH] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
StringCbPrintfW(szPath, _countof(szPath), L"%ls\\%ls", szPath, lpRegName);
if (RegOpenKeyExW(IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0, keyWow | KEY_ENUMERATE_SUB_KEYS,
szPath, 0, keyWow | KEY_READ,
&hKey) == ERROR_SUCCESS)
{
if (FindRegistryKeyByName(hKey, keyWow, lpRegName, &hSubKey))
dwSize = MAX_PATH;
if (RegQueryValueExW(hKey,
L"DisplayVersion",
NULL,
&dwType,
(LPBYTE) szVersion,
&dwSize) == ERROR_SUCCESS)
{
dwSize = sizeof(szVersion);
if (RegQueryValueExW(hSubKey,
L"DisplayVersion",
NULL,
&dwType,
(LPBYTE) szVersion,
&dwSize) == ERROR_SUCCESS)
{
szVersionResult = szVersion;
iVersionResultSize = dwSize;
HasVersion = TRUE;
}
StringCbCopyW(szVersionResult, dwSize, szVersion);
bHasVersion = TRUE;
}
RegCloseKey(hSubKey);
}
RegCloseKey(hKey);
return HasVersion;
return bHasVersion;
}

View file

@ -152,6 +152,7 @@ END
STRINGTABLE
BEGIN
IDS_AINFO_VERSION "\nVersion: "
IDS_AINFO_AVAILABLEVERSION "\nAvailable Version: "
IDS_AINFO_DESCRIPTION "\nDescription: "
IDS_AINFO_SIZE "\nSize: "
IDS_AINFO_URLSITE "\nHome Page: "

View file

@ -152,6 +152,7 @@ END
STRINGTABLE
BEGIN
IDS_AINFO_VERSION "\nВерсия: "
IDS_AINFO_AVAILABLEVERSION "\nДоступная версия: "
IDS_AINFO_DESCRIPTION "\nОписание: "
IDS_AINFO_SIZE "\nРазмер: "
IDS_AINFO_URLSITE "\nДомашняя страница: "

View file

@ -160,6 +160,7 @@ END
STRINGTABLE
BEGIN
IDS_AINFO_VERSION "\nВерсія: "
IDS_AINFO_AVAILABLEVERSION "\nДоступна версія: "
IDS_AINFO_DESCRIPTION "\nОпис: "
IDS_AINFO_SIZE "\nРозмір: "
IDS_AINFO_URLSITE "\nДомашня сторінка: "

View file

@ -8,6 +8,8 @@
*/
#include "rapps.h"
#include <atlsimpcoll.h>
#include <atlstr.h>
/* SESSION Operation */
#define EXTRACT_FILLFILELIST 0x00000001
@ -495,29 +497,70 @@ UINT ParserGetInt(LPCWSTR lpKeyName, LPCWSTR lpFileName)
RtlInitUnicodeString(&BufferW, Buffer);
RtlUnicodeStringToInteger(&BufferW, 0, &Result);
return Result;
return (UINT)Result;
}
//Parses version string that can be formatted as 1.2.3.4-5
//Returns int buffer and it's size
BOOL
ParseVersion(LPWSTR szVersion, INT* version)
ParseVersion(_In_z_ LPCWSTR szVersion, _Outptr_ INT* parrVersion, _Out_opt_ UINT iVersionSize)
{
return TRUE;
}
//Finds subkey in key by name or path and returns it
BOOL
FindRegistryKeyByName(_In_ HKEY hKeyBase, _In_ REGSAM keyWow, _In_ LPCWSTR lpcKey, _Out_opt_ PHKEY hKeyResult)
{
HKEY hSubKey;
if (RegOpenKeyExW(hKeyBase, lpcKey, 0, keyWow | KEY_READ, &hSubKey) == ERROR_SUCCESS)
ATL::CSimpleArray<int> arrVersionResult;
ATL::CStringW szVersionSingleInt = L"";
ATL::CStringW sDelimiters = L".-";
BOOL bHasParsed = TRUE;
INT iVersionCharCount = 0;
//INT iVersionSingleCharCount = 0;
INT iIntResult;
iVersionSize = 0;
while(szVersion[iVersionCharCount] != L'\0')
{
hKeyResult = &hSubKey;
return TRUE;
for (;!sDelimiters.Find(szVersion[iVersionCharCount]); ++iVersionCharCount)
{
szVersionSingleInt += szVersion[iVersionCharCount];
}
szVersionSingleInt += L'\0';
iIntResult = StrToIntW(szVersionSingleInt.GetBuffer());
if (iIntResult)
{
arrVersionResult.Add(iIntResult);
iVersionSize++;
}
else
{
bHasParsed = FALSE;
}
++iVersionCharCount;
}
hKeyResult = NULL;
RegCloseKey(hSubKey);
return FALSE;
parrVersion = arrVersionResult.GetData();
return bHasParsed;
}
//Compares versions
//In: Zero terminated strings of versions
//Out: TRUE if first is bigger than second, FALSE if else
BOOL
CompareVersionsBigger(_In_z_ LPCWSTR sczVersion1, _In_z_ LPCWSTR sczVersion2, _Out_ BOOL bResult)
{
UINT iVersionSize1 = 0;
UINT iVersionSize2 = 0;
INT *parrVersion1 = NULL, *parrVersion2 = NULL;
bResult = FALSE;
if (!ParseVersion(sczVersion1, parrVersion1, iVersionSize1)
|| !ParseVersion(sczVersion2, parrVersion2, iVersionSize2))
{
return FALSE;
}
for (INT i = 0; i < iVersionSize1 && i < iVersionSize2; ++i)
{
if (parrVersion1[i] > parrVersion2[i])
{
bResult = TRUE;
return TRUE;
}
}
return TRUE;
}

View file

@ -181,7 +181,9 @@ BOOL WriteLogMessage(WORD wType, DWORD dwEventID, LPWSTR lpMsg);
UINT ParserGetString(LPCWSTR lpKeyName, LPWSTR lpReturnedString, UINT nSize, LPCWSTR lpFileName);
UINT ParserGetInt(LPCWSTR lpKeyName, LPCWSTR lpFileName);
BOOL ParseVersion(_In_z_ LPCWSTR szVersion, _Outptr_ INT* parrVersion, _Out_opt_ UINT iVersionSize);
BOOL FindRegistryKeyByName(_In_ HKEY hKeyBase, _In_ REGSAM keyWow, _In_ LPCWSTR lpcKey, _Out_opt_ PHKEY hKeyResult);
BOOL CompareVersionsBigger(_In_z_ LPCWSTR sczVersion1, _In_z_ LPCWSTR sczVersion2, _Out_ BOOL bResult = FALSE);
/* settingsdlg.c */
VOID CreateSettingsDlg(HWND hwnd);

View file

@ -119,31 +119,33 @@
#define IDS_APP_DESCRIPTION 252
/* Apps info */
#define IDS_INFO_VERSION 280
#define IDS_INFO_DESCRIPTION 281
#define IDS_INFO_PUBLISHER 282
#define IDS_INFO_HELPLINK 283
#define IDS_INFO_HELPPHONE 284
#define IDS_INFO_README 285
#define IDS_INFO_REGOWNER 286
#define IDS_INFO_PRODUCTID 287
#define IDS_INFO_CONTACT 288
#define IDS_INFO_UPDATEINFO 289
#define IDS_INFO_INFOABOUT 290
#define IDS_INFO_COMMENTS 291
#define IDS_INFO_INSTLOCATION 292
#define IDS_INFO_INSTALLSRC 293
#define IDS_INFO_UNINSTALLSTR 294
#define IDS_INFO_MODIFYPATH 295
#define IDS_INFO_INSTALLDATE 296
#define IDS_INFO_VERSION 280
#define IDS_INFO_DESCRIPTION 281
#define IDS_INFO_PUBLISHER 282
#define IDS_INFO_HELPLINK 283
#define IDS_INFO_HELPPHONE 284
#define IDS_INFO_README 285
#define IDS_INFO_REGOWNER 286
#define IDS_INFO_PRODUCTID 287
#define IDS_INFO_CONTACT 288
#define IDS_INFO_UPDATEINFO 289
#define IDS_INFO_INFOABOUT 290
#define IDS_INFO_COMMENTS 291
#define IDS_INFO_INSTLOCATION 292
#define IDS_INFO_INSTALLSRC 293
#define IDS_INFO_UNINSTALLSTR 294
#define IDS_INFO_MODIFYPATH 295
#define IDS_INFO_INSTALLDATE 296
/* Info for available apps */
#define IDS_AINFO_VERSION 350
#define IDS_AINFO_DESCRIPTION 351
#define IDS_AINFO_SIZE 352
#define IDS_AINFO_URLSITE 353
#define IDS_AINFO_LICENSE 354
#define IDS_AINFO_URLDOWNLOAD 355
#define IDS_AINFO_VERSION 350
#define IDS_AINFO_DESCRIPTION 351
#define IDS_AINFO_SIZE 352
#define IDS_AINFO_URLSITE 353
#define IDS_AINFO_LICENSE 354
#define IDS_AINFO_URLDOWNLOAD 355
#define IDS_AINFO_AVAILABLEVERSION 356
/* Names of categories */
#define IDS_CAT_AUDIO 700