[RAPPS] Rework application handling

Previously, there would be function duplication between installed and available applications.
Now this is handled with polymorphism, which allows to re-use a lot of code.
Additionally, toolbar buttons are properly disabled now.
The mutex used to guard rapps' single instance is renamed,
so that the 'new' and old rapps can be run at the same time for testing.

CORE-18459
This commit is contained in:
Mark Jansen 2023-02-20 19:30:02 +01:00
parent 0cd80c17f6
commit 33c2903e6d
No known key found for this signature in database
GPG key ID: B39240EE84BEAE8B
30 changed files with 3758 additions and 4076 deletions

View file

@ -5,13 +5,13 @@ include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/conutils)
include_directories(include) include_directories(include)
list(APPEND SOURCE list(APPEND SOURCE
applicationdb.cpp
applicationinfo.cpp
appview.cpp appview.cpp
asyncinet.cpp asyncinet.cpp
available.cpp
cabinet.cpp cabinet.cpp
configparser.cpp configparser.cpp
gui.cpp gui.cpp
installed.cpp
integrity.cpp integrity.cpp
loaddlg.cpp loaddlg.cpp
misc.cpp misc.cpp
@ -19,15 +19,15 @@ list(APPEND SOURCE
settingsdlg.cpp settingsdlg.cpp
unattended.cpp unattended.cpp
winmain.cpp winmain.cpp
include/applicationdb.h
include/applicationinfo.h
include/appview.h include/appview.h
include/asyncinet.h include/asyncinet.h
include/available.h
include/configparser.h include/configparser.h
include/crichedit.h include/crichedit.h
include/defines.h include/defines.h
include/dialogs.h include/dialogs.h
include/gui.h include/gui.h
include/installed.h
include/misc.h include/misc.h
include/rapps.h include/rapps.h
include/resource.h include/resource.h

View file

@ -0,0 +1,291 @@
/*
* PROJECT: ReactOS Applications Manager
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Classes for working with available applications
* COPYRIGHT: Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
* Copyright 2020 He Yang (1160386205@qq.com)
* Copyright 2021-2023 Mark Jansen <mark.jansen@reactos.org>
*/
#include "rapps.h"
#include "applicationdb.h"
#include "configparser.h"
#include "settings.h"
static HKEY g_RootKeyEnum[3] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_LOCAL_MACHINE};
static REGSAM g_RegSamEnum[3] = {KEY_WOW64_32KEY, KEY_WOW64_32KEY, KEY_WOW64_64KEY};
#define UNINSTALL_SUBKEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
static VOID
ClearList(CAtlList<CApplicationInfo *> &list)
{
POSITION InfoListPosition = list.GetHeadPosition();
while (InfoListPosition)
{
CApplicationInfo *Info = list.GetNext(InfoListPosition);
delete Info;
}
list.RemoveAll();
}
CApplicationDB::CApplicationDB(const CStringW &path) : m_BasePath(path)
{
m_BasePath.Canonicalize();
}
CApplicationInfo *
CApplicationDB::FindByPackageName(const CStringW &name)
{
POSITION CurrentListPosition = m_Available.GetHeadPosition();
while (CurrentListPosition)
{
CApplicationInfo *Info = m_Available.GetNext(CurrentListPosition);
if (Info->szIdentifier == name)
{
return Info;
}
}
return NULL;
}
void
CApplicationDB::GetApps(CAtlList<CApplicationInfo *> &List, AppsCategories Type) const
{
const BOOL UseInstalled = IsInstalledEnum(Type);
const CAtlList<CApplicationInfo *> &list = UseInstalled ? m_Installed : m_Available;
const BOOL IncludeAll = UseInstalled ? (Type == ENUM_ALL_INSTALLED) : (Type == ENUM_ALL_AVAILABLE);
POSITION CurrentListPosition = list.GetHeadPosition();
while (CurrentListPosition)
{
CApplicationInfo *Info = list.GetNext(CurrentListPosition);
if (IncludeAll || Type == Info->iCategory)
{
List.AddTail(Info);
}
}
}
BOOL
CApplicationDB::EnumerateFiles()
{
ClearList(m_Available);
CPathW AppsPath = m_BasePath;
AppsPath += L"rapps";
CPathW WildcardPath = AppsPath;
WildcardPath += L"*.txt";
WIN32_FIND_DATAW FindFileData;
HANDLE hFind = FindFirstFileW(WildcardPath, &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
return FALSE;
}
do
{
CStringW szPkgName = FindFileData.cFileName;
PathRemoveExtensionW(szPkgName.GetBuffer(MAX_PATH));
szPkgName.ReleaseBuffer();
CApplicationInfo *Info = FindByPackageName(szPkgName);
ATLASSERT(Info == NULL);
if (!Info)
{
CConfigParser *Parser = new CConfigParser(FindFileData.cFileName);
int Cat;
if (!Parser->GetInt(L"Category", Cat))
Cat = ENUM_INVALID;
Info = new CAvailableApplicationInfo(Parser, szPkgName, static_cast<AppsCategories>(Cat), AppsPath);
if (Info->Valid())
{
m_Available.AddTail(Info);
}
else
{
delete Info;
}
}
} while (FindNextFileW(hFind, &FindFileData));
FindClose(hFind);
return TRUE;
}
VOID
CApplicationDB::UpdateAvailable()
{
if (!CreateDirectoryW(m_BasePath, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
return;
if (EnumerateFiles())
return;
DownloadApplicationsDB(
SettingsInfo.bUseSource ? SettingsInfo.szSourceURL : APPLICATION_DATABASE_URL, !SettingsInfo.bUseSource);
CPathW AppsPath = m_BasePath;
AppsPath += L"rapps";
if (!ExtractFilesFromCab(APPLICATION_DATABASE_NAME, m_BasePath, AppsPath))
return;
CPathW CabFile = m_BasePath;
CabFile += APPLICATION_DATABASE_NAME;
DeleteFileW(CabFile);
EnumerateFiles();
}
VOID
CApplicationDB::UpdateInstalled()
{
// Remove all old entries
ClearList(m_Installed);
int LoopKeys = 2;
if (IsSystem64Bit())
{
// loop for all 3 combination.
// note that HKEY_CURRENT_USER\Software don't have a redirect
// https://docs.microsoft.com/en-us/windows/win32/winprog64/shared-registry-keys#redirected-shared-and-reflected-keys-under-wow64
LoopKeys = 3;
}
for (int keyIndex = 0; keyIndex < LoopKeys; keyIndex++)
{
LONG ItemIndex = 0;
WCHAR szKeyName[MAX_PATH];
CRegKey hKey;
if (hKey.Open(g_RootKeyEnum[keyIndex], UNINSTALL_SUBKEY, KEY_READ | g_RegSamEnum[keyIndex]) != ERROR_SUCCESS)
{
continue;
}
while (1)
{
DWORD dwSize = _countof(szKeyName);
if (hKey.EnumKey(ItemIndex, szKeyName, &dwSize) != ERROR_SUCCESS)
{
break;
}
ItemIndex++;
CRegKey hSubKey;
if (hSubKey.Open(hKey, szKeyName, KEY_READ) == ERROR_SUCCESS)
{
DWORD dwValue = 0;
dwSize = sizeof(DWORD);
if (RegQueryValueExW(hSubKey, L"SystemComponent", NULL, NULL, (LPBYTE)&dwValue, &dwSize) ==
ERROR_SUCCESS &&
dwValue == 1)
{
// Ignore system components
continue;
}
BOOL bIsUpdate =
(RegQueryValueExW(hSubKey, L"ParentKeyName", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS);
CInstalledApplicationInfo *Info = new CInstalledApplicationInfo(
hSubKey.Detach(), szKeyName, bIsUpdate ? ENUM_UPDATES : ENUM_INSTALLED_APPLICATIONS, keyIndex);
if (Info->Valid())
{
m_Installed.AddTail(Info);
}
else
{
delete Info;
}
}
}
}
}
static void
DeleteWithWildcard(const CPathW &Dir, const CStringW &Filter)
{
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindFileData;
CPathW DirWithFilter = Dir;
DirWithFilter += Filter;
hFind = FindFirstFileW(DirWithFilter, &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
return;
do
{
CPathW szTmp = Dir;
szTmp += FindFileData.cFileName;
if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
DeleteFileW(szTmp);
}
} while (FindNextFileW(hFind, &FindFileData) != 0);
FindClose(hFind);
}
VOID
CApplicationDB::RemoveCached()
{
// Delete icons
CPathW AppsPath = m_BasePath;
AppsPath += L"rapps";
CPathW IconPath = AppsPath;
IconPath += L"icons";
DeleteWithWildcard(IconPath, L"*.ico");
// Delete leftover screenshots
CPathW ScrnshotFolder = AppsPath;
ScrnshotFolder += L"screenshots";
DeleteWithWildcard(ScrnshotFolder, L"*.tmp");
// Delete data base files (*.txt)
DeleteWithWildcard(AppsPath, L"*.txt");
RemoveDirectoryW(IconPath);
RemoveDirectoryW(ScrnshotFolder);
RemoveDirectoryW(AppsPath);
RemoveDirectoryW(m_BasePath);
}
BOOL
CApplicationDB::RemoveInstalledAppFromRegistry(const CApplicationInfo *Info)
{
// Validate that this is actually an installed app / update
ATLASSERT(Info->iCategory == ENUM_INSTALLED_APPLICATIONS || Info->iCategory == ENUM_UPDATES);
if (Info->iCategory != ENUM_INSTALLED_APPLICATIONS && Info->iCategory != ENUM_UPDATES)
return FALSE;
// Grab the index in the registry keys
const CInstalledApplicationInfo *InstalledInfo = static_cast<const CInstalledApplicationInfo *>(Info);
ATLASSERT(InstalledInfo->iKeyIndex >= 0 && InstalledInfo->iKeyIndex < (int)_countof(g_RootKeyEnum));
if (InstalledInfo->iKeyIndex < 0 && InstalledInfo->iKeyIndex >= (int)_countof(g_RootKeyEnum))
return FALSE;
int keyIndex = InstalledInfo->iKeyIndex;
// Grab the registry key name
CStringW Name = InstalledInfo->szIdentifier;
// Recursively delete this key
CRegKey Uninstall;
if (Uninstall.Open(g_RootKeyEnum[keyIndex], UNINSTALL_SUBKEY, KEY_READ | KEY_WRITE | g_RegSamEnum[keyIndex]) !=
ERROR_SUCCESS)
return FALSE;
return Uninstall.RecurseDeleteKey(Name) == ERROR_SUCCESS;
}

View file

@ -0,0 +1,630 @@
/*
* PROJECT: ReactOS Applications Manager
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Classes for working with available applications
* COPYRIGHT: Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
* Copyright 2020 He Yang (1160386205@qq.com)
* Copyright 2021-2023 Mark Jansen <mark.jansen@reactos.org>
*/
#include "rapps.h"
#include "appview.h"
CApplicationInfo::CApplicationInfo(const CStringW &Identifier, AppsCategories Category)
: szIdentifier(Identifier), iCategory(Category)
{
}
CApplicationInfo::~CApplicationInfo()
{
}
CAvailableApplicationInfo::CAvailableApplicationInfo(
CConfigParser *Parser,
const CStringW &PkgName,
AppsCategories Category,
const CPathW &BasePath)
: CApplicationInfo(PkgName, Category), m_Parser(Parser), m_ScrnshotRetrieved(false), m_LanguagesLoaded(false)
{
m_Parser->GetString(L"Name", szDisplayName);
m_Parser->GetString(L"Version", szDisplayVersion);
m_Parser->GetString(L"URLDownload", m_szUrlDownload);
m_Parser->GetString(L"Description", szComments);
CPathW IconPath = BasePath;
IconPath += L"icons";
CStringW IconName;
if (m_Parser->GetString(L"Icon", IconName))
{
IconPath += IconName;
}
else
{
// inifile.ico
IconPath += (szIdentifier + L".ico");
}
if (PathFileExistsW(IconPath))
{
szDisplayIcon = (LPCWSTR)IconPath;
}
INT iSizeBytes;
if (m_Parser->GetInt(L"SizeBytes", iSizeBytes))
{
StrFormatByteSizeW(iSizeBytes, m_szSize.GetBuffer(MAX_PATH), MAX_PATH);
m_szSize.ReleaseBuffer();
}
m_Parser->GetString(L"URLSite", m_szUrlSite);
}
CAvailableApplicationInfo::~CAvailableApplicationInfo()
{
delete m_Parser;
}
VOID
CAvailableApplicationInfo::ShowAppInfo(CAppRichEdit *RichEdit)
{
RichEdit->SetText(szDisplayName, CFE_BOLD);
InsertVersionInfo(RichEdit);
RichEdit->LoadAndInsertText(IDS_AINFO_LICENSE, LicenseString(), 0);
InsertLanguageInfo(RichEdit);
RichEdit->LoadAndInsertText(IDS_AINFO_SIZE, m_szSize, 0);
RichEdit->LoadAndInsertText(IDS_AINFO_URLSITE, m_szUrlSite, CFE_LINK);
RichEdit->LoadAndInsertText(IDS_AINFO_DESCRIPTION, szComments, 0);
RichEdit->LoadAndInsertText(IDS_AINFO_URLDOWNLOAD, m_szUrlDownload, CFE_LINK);
RichEdit->LoadAndInsertText(IDS_AINFO_PACKAGE_NAME, szIdentifier, 0);
}
int
CompareVersion(const CStringW &left, const CStringW &right)
{
int nLeft = 0, nRight = 0;
while (true)
{
CStringW leftPart = left.Tokenize(L".", nLeft);
CStringW rightPart = right.Tokenize(L".", nRight);
if (leftPart.IsEmpty() && rightPart.IsEmpty())
return 0;
if (leftPart.IsEmpty())
return -1;
if (rightPart.IsEmpty())
return 1;
int leftVal, rightVal;
if (!StrToIntExW(leftPart, STIF_DEFAULT, &leftVal))
leftVal = 0;
if (!StrToIntExW(rightPart, STIF_DEFAULT, &rightVal))
rightVal = 0;
if (leftVal > rightVal)
return 1;
if (rightVal < leftVal)
return -1;
}
}
VOID
CAvailableApplicationInfo::InsertVersionInfo(CAppRichEdit *RichEdit)
{
CStringW szRegName;
m_Parser->GetString(L"RegName", szRegName);
BOOL bIsInstalled = ::GetInstalledVersion(NULL, szRegName) || ::GetInstalledVersion(NULL, szDisplayName);
if (bIsInstalled)
{
CStringW szInstalledVersion;
CStringW szNameVersion = szDisplayName + L" " + szDisplayVersion;
BOOL bHasInstalledVersion = ::GetInstalledVersion(&szInstalledVersion, szRegName) ||
::GetInstalledVersion(&szInstalledVersion, szDisplayName) ||
::GetInstalledVersion(&szInstalledVersion, szNameVersion);
if (bHasInstalledVersion)
{
BOOL bHasUpdate = CompareVersion(szInstalledVersion, szDisplayVersion) < 0;
if (bHasUpdate)
RichEdit->LoadAndInsertText(IDS_STATUS_UPDATE_AVAILABLE, CFE_ITALIC);
else
RichEdit->LoadAndInsertText(IDS_STATUS_INSTALLED, CFE_ITALIC);
RichEdit->LoadAndInsertText(IDS_AINFO_VERSION, szInstalledVersion, 0);
}
else
{
RichEdit->LoadAndInsertText(IDS_STATUS_INSTALLED, CFE_ITALIC);
}
}
else
{
RichEdit->LoadAndInsertText(IDS_STATUS_NOTINSTALLED, CFE_ITALIC);
}
RichEdit->LoadAndInsertText(IDS_AINFO_AVAILABLEVERSION, szDisplayVersion, 0);
}
CStringW
CAvailableApplicationInfo::LicenseString()
{
INT IntBuffer;
m_Parser->GetInt(L"LicenseType", IntBuffer);
CStringW szLicenseString;
m_Parser->GetString(L"License", szLicenseString);
LicenseType licenseType;
if (IsLicenseType(IntBuffer))
{
licenseType = static_cast<LicenseType>(IntBuffer);
}
else
{
licenseType = LICENSE_NONE;
}
CStringW szLicense;
switch (licenseType)
{
case LICENSE_OPENSOURCE:
szLicense.LoadStringW(IDS_LICENSE_OPENSOURCE);
break;
case LICENSE_FREEWARE:
szLicense.LoadStringW(IDS_LICENSE_FREEWARE);
break;
case LICENSE_TRIAL:
szLicense.LoadStringW(IDS_LICENSE_TRIAL);
break;
default:
return szLicenseString;
}
return szLicense + L" (" + szLicenseString + L")";
}
VOID
CAvailableApplicationInfo::InsertLanguageInfo(CAppRichEdit *RichEdit)
{
if (!m_LanguagesLoaded)
{
RetrieveLanguages();
}
if (m_LanguageLCIDs.GetSize() == 0)
{
return;
}
const INT nTranslations = m_LanguageLCIDs.GetSize();
CStringW szLangInfo;
CStringW szLoadedTextAvailability;
CStringW szLoadedAInfoText;
szLoadedAInfoText.LoadStringW(IDS_AINFO_LANGUAGES);
const LCID lcEnglish = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT);
if (m_LanguageLCIDs.Find(GetUserDefaultLCID()) >= 0)
{
szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_AVAILABLE_TRANSLATION);
if (nTranslations > 1)
{
CStringW buf;
buf.LoadStringW(IDS_LANGUAGE_MORE_PLACEHOLDER);
szLangInfo.Format(buf, nTranslations - 1);
}
else
{
szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE);
szLangInfo = L" (" + szLangInfo + L")";
}
}
else if (m_LanguageLCIDs.Find(lcEnglish) >= 0)
{
szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_ENGLISH_TRANSLATION);
if (nTranslations > 1)
{
CStringW buf;
buf.LoadStringW(IDS_LANGUAGE_AVAILABLE_PLACEHOLDER);
szLangInfo.Format(buf, nTranslations - 1);
}
else
{
szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE);
szLangInfo = L" (" + szLangInfo + L")";
}
}
else
{
szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_NO_TRANSLATION);
}
RichEdit->InsertText(szLoadedAInfoText, CFE_BOLD);
RichEdit->InsertText(szLoadedTextAvailability, NULL);
RichEdit->InsertText(szLangInfo, CFE_ITALIC);
}
VOID
CAvailableApplicationInfo::RetrieveLanguages()
{
m_LanguagesLoaded = true;
CStringW szBuffer;
if (!m_Parser->GetString(L"Languages", szBuffer))
{
return;
}
// Parse parameter string
int iIndex = 0;
while (true)
{
CStringW szLocale = szBuffer.Tokenize(L"|", iIndex);
if (szLocale.IsEmpty())
break;
szLocale = L"0x" + szLocale;
INT iLCID;
if (StrToIntExW(szLocale, STIF_SUPPORT_HEX, &iLCID))
{
m_LanguageLCIDs.Add(static_cast<LCID>(iLCID));
}
}
}
BOOL
CAvailableApplicationInfo::Valid() const
{
return !szDisplayName.IsEmpty() && !m_szUrlDownload.IsEmpty();
}
BOOL
CAvailableApplicationInfo::CanModify()
{
return FALSE;
}
BOOL
CAvailableApplicationInfo::RetrieveIcon(CStringW &Path) const
{
Path = szDisplayIcon;
return !Path.IsEmpty();
}
#define MAX_SCRNSHOT_NUM 16
BOOL
CAvailableApplicationInfo::RetrieveScreenshot(CStringW &Path)
{
if (!m_ScrnshotRetrieved)
{
static_assert(MAX_SCRNSHOT_NUM < 10000, "MAX_SCRNSHOT_NUM is too big");
for (int i = 0; i < MAX_SCRNSHOT_NUM; i++)
{
CStringW ScrnshotField;
ScrnshotField.Format(L"Screenshot%d", i + 1);
CStringW ScrnshotLocation;
if (!m_Parser->GetString(ScrnshotField, ScrnshotLocation))
{
// We stop at the first screenshot not found,
// so screenshots _have_ to be consecutive
break;
}
if (PathIsURLW(ScrnshotLocation.GetString()))
{
m_szScrnshotLocation.Add(ScrnshotLocation);
}
}
m_ScrnshotRetrieved = true;
}
if (m_szScrnshotLocation.GetSize() > 0)
{
Path = m_szScrnshotLocation[0];
}
return !Path.IsEmpty();
}
VOID
CAvailableApplicationInfo::GetDownloadInfo(CStringW &Url, CStringW &Sha1, ULONG &SizeInBytes) const
{
Url = m_szUrlDownload;
m_Parser->GetString(L"SHA1", Sha1);
INT iSizeBytes;
if (m_Parser->GetInt(L"SizeBytes", iSizeBytes))
{
SizeInBytes = (ULONG)iSizeBytes;
}
else
{
SizeInBytes = 0;
}
}
VOID
CAvailableApplicationInfo::GetDisplayInfo(CStringW &License, CStringW &Size, CStringW &UrlSite, CStringW &UrlDownload)
{
License = LicenseString();
Size = m_szSize;
UrlSite = m_szUrlSite;
UrlDownload = m_szUrlDownload;
}
BOOL
CAvailableApplicationInfo::UninstallApplication(BOOL bModify)
{
ATLASSERT(FALSE && "Should not be called");
return FALSE;
}
CInstalledApplicationInfo::CInstalledApplicationInfo(
HKEY Key,
const CStringW &KeyName,
AppsCategories Category,
int KeyIndex)
: CApplicationInfo(KeyName, Category), m_hKey(Key), iKeyIndex(KeyIndex)
{
if (GetApplicationRegString(L"DisplayName", szDisplayName))
{
GetApplicationRegString(L"DisplayIcon", szDisplayIcon);
GetApplicationRegString(L"DisplayVersion", szDisplayVersion);
GetApplicationRegString(L"Comments", szComments);
}
}
CInstalledApplicationInfo::~CInstalledApplicationInfo()
{
}
VOID
CInstalledApplicationInfo::AddApplicationRegString(
CAppRichEdit *RichEdit,
UINT StringID,
const CStringW &String,
DWORD TextFlags)
{
CStringW Tmp;
if (GetApplicationRegString(String, Tmp))
{
RichEdit->InsertTextWithString(StringID, Tmp, TextFlags);
}
}
VOID
CInstalledApplicationInfo::ShowAppInfo(CAppRichEdit *RichEdit)
{
RichEdit->SetText(szDisplayName, CFE_BOLD);
RichEdit->InsertText(L"\n", 0);
RichEdit->InsertTextWithString(IDS_INFO_VERSION, szDisplayVersion, 0);
AddApplicationRegString(RichEdit, IDS_INFO_PUBLISHER, L"Publisher", 0);
AddApplicationRegString(RichEdit, IDS_INFO_REGOWNER, L"RegOwner", 0);
AddApplicationRegString(RichEdit, IDS_INFO_PRODUCTID, L"ProductID", 0);
AddApplicationRegString(RichEdit, IDS_INFO_HELPLINK, L"HelpLink", CFM_LINK);
AddApplicationRegString(RichEdit, IDS_INFO_HELPPHONE, L"HelpTelephone", 0);
AddApplicationRegString(RichEdit, IDS_INFO_README, L"Readme", 0);
AddApplicationRegString(RichEdit, IDS_INFO_CONTACT, L"Contact", 0);
AddApplicationRegString(RichEdit, IDS_INFO_UPDATEINFO, L"URLUpdateInfo", CFM_LINK);
AddApplicationRegString(RichEdit, IDS_INFO_INFOABOUT, L"URLInfoAbout", CFM_LINK);
RichEdit->InsertTextWithString(IDS_INFO_COMMENTS, szComments, 0);
if (m_szInstallDate.IsEmpty())
{
RetrieveInstallDate();
}
RichEdit->InsertTextWithString(IDS_INFO_INSTALLDATE, m_szInstallDate, 0);
AddApplicationRegString(RichEdit, IDS_INFO_INSTLOCATION, L"InstallLocation", 0);
AddApplicationRegString(RichEdit, IDS_INFO_INSTALLSRC, L"InstallSource", 0);
if (m_szUninstallString.IsEmpty())
{
RetrieveUninstallStrings();
}
RichEdit->InsertTextWithString(IDS_INFO_UNINSTALLSTR, m_szUninstallString, 0);
RichEdit->InsertTextWithString(IDS_INFO_MODIFYPATH, m_szModifyString, 0);
}
VOID
CInstalledApplicationInfo::RetrieveInstallDate()
{
DWORD dwInstallTimeStamp;
SYSTEMTIME InstallLocalTime;
if (GetApplicationRegString(L"InstallDate", m_szInstallDate))
{
ZeroMemory(&InstallLocalTime, sizeof(InstallLocalTime));
// Check if we have 8 characters to parse the datetime.
// Maybe other formats exist as well?
m_szInstallDate = m_szInstallDate.Trim();
if (m_szInstallDate.GetLength() == 8)
{
InstallLocalTime.wYear = wcstol(m_szInstallDate.Left(4).GetString(), NULL, 10);
InstallLocalTime.wMonth = wcstol(m_szInstallDate.Mid(4, 2).GetString(), NULL, 10);
InstallLocalTime.wDay = wcstol(m_szInstallDate.Mid(6, 2).GetString(), NULL, 10);
}
}
// It might be a DWORD (Unix timestamp). try again.
else if (GetApplicationRegDword(L"InstallDate", &dwInstallTimeStamp))
{
FILETIME InstallFileTime;
SYSTEMTIME InstallSystemTime;
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, m_szInstallDate.GetBuffer(cchTimeStrLen), cchTimeStrLen);
m_szInstallDate.ReleaseBuffer();
}
VOID
CInstalledApplicationInfo::RetrieveUninstallStrings()
{
DWORD dwWindowsInstaller = 0;
if (GetApplicationRegDword(L"WindowsInstaller", &dwWindowsInstaller) && dwWindowsInstaller)
{
// MSI has the same info in Uninstall / modify, so manually build it
m_szUninstallString.Format(L"msiexec /x%s", szIdentifier.GetString());
}
else
{
GetApplicationRegString(L"UninstallString", m_szUninstallString);
}
DWORD dwNoModify = 0;
if (!GetApplicationRegDword(L"NoModify", &dwNoModify))
{
CStringW Tmp;
if (GetApplicationRegString(L"NoModify", Tmp))
{
dwNoModify = Tmp.GetLength() > 0 ? (Tmp[0] == '1') : 0;
}
else
{
dwNoModify = 0;
}
}
if (!dwNoModify)
{
if (dwWindowsInstaller)
{
m_szModifyString.Format(L"msiexec /i%s", szIdentifier.GetString());
}
else
{
GetApplicationRegString(L"ModifyPath", m_szModifyString);
}
}
}
BOOL
CInstalledApplicationInfo::Valid() const
{
return !szDisplayName.IsEmpty();
}
BOOL
CInstalledApplicationInfo::CanModify()
{
if (m_szUninstallString.IsEmpty())
{
RetrieveUninstallStrings();
}
return !m_szModifyString.IsEmpty();
}
BOOL
CInstalledApplicationInfo::RetrieveIcon(CStringW &Path) const
{
Path = szDisplayIcon;
return !Path.IsEmpty();
}
BOOL
CInstalledApplicationInfo::RetrieveScreenshot(CStringW & /*Path*/)
{
return FALSE;
}
VOID
CInstalledApplicationInfo::GetDownloadInfo(CStringW &Url, CStringW &Sha1, ULONG &SizeInBytes) const
{
ATLASSERT(FALSE && "Should not be called");
}
VOID
CInstalledApplicationInfo::GetDisplayInfo(CStringW &License, CStringW &Size, CStringW &UrlSite, CStringW &UrlDownload)
{
ATLASSERT(FALSE && "Should not be called");
}
BOOL
CInstalledApplicationInfo::UninstallApplication(BOOL bModify)
{
if (m_szUninstallString.IsEmpty())
{
RetrieveUninstallStrings();
}
BOOL bSuccess = StartProcess(bModify ? m_szModifyString : m_szUninstallString, TRUE);
if (bSuccess && !bModify)
WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_REMOVE, szDisplayName);
return bSuccess;
}
BOOL
CInstalledApplicationInfo::GetApplicationRegString(LPCWSTR lpKeyName, CStringW &String)
{
ULONG nChars = 0;
// Get the size
if (m_hKey.QueryStringValue(lpKeyName, NULL, &nChars) != ERROR_SUCCESS)
{
String.Empty();
return FALSE;
}
LPWSTR Buffer = String.GetBuffer(nChars);
LONG lResult = m_hKey.QueryStringValue(lpKeyName, Buffer, &nChars);
if (nChars > 0 && Buffer[nChars - 1] == UNICODE_NULL)
nChars--;
String.ReleaseBuffer(nChars);
if (lResult != ERROR_SUCCESS)
{
String.Empty();
return FALSE;
}
if (String.Find('%') >= 0)
{
CStringW Tmp;
DWORD dwLen = ExpandEnvironmentStringsW(String, NULL, 0);
if (dwLen > 0)
{
BOOL bSuccess = ExpandEnvironmentStringsW(String, Tmp.GetBuffer(dwLen), dwLen) == dwLen;
Tmp.ReleaseBuffer(dwLen - 1);
if (bSuccess)
{
String = Tmp;
}
else
{
String.Empty();
return FALSE;
}
}
}
return TRUE;
}
BOOL
CInstalledApplicationInfo::GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue)
{
DWORD dwSize = sizeof(DWORD), dwType;
if (RegQueryValueExW(m_hKey, lpKeyName, NULL, &dwType, (LPBYTE)lpValue, &dwSize) != ERROR_SUCCESS ||
dwType != REG_DWORD)
{
return FALSE;
}
return TRUE;
}

File diff suppressed because it is too large Load diff

View file

@ -1,612 +0,0 @@
/*
* PROJECT: ReactOS Applications Manager
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Classes for working with available applications
* COPYRIGHT: Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org)
* Copyright 2015 Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
* Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
* Copyright 2020 He Yang (1160386205@qq.com)
*/
#include "rapps.h"
#include "available.h"
#include "misc.h"
#include "dialogs.h"
// CAvailableApplicationInfo
CAvailableApplicationInfo::CAvailableApplicationInfo(const ATL::CStringW& sFileNameParam, AvailableStrings& AvlbStrings)
: m_LicenseType(LICENSE_NONE), m_SizeBytes(0), m_sFileName(sFileNameParam),
m_IsInstalled(FALSE), m_HasLanguageInfo(FALSE), m_HasInstalledVersion(FALSE)
{
RetrieveGeneralInfo(AvlbStrings);
}
VOID CAvailableApplicationInfo::RefreshAppInfo(AvailableStrings& AvlbStrings)
{
if (m_szUrlDownload.IsEmpty())
{
RetrieveGeneralInfo(AvlbStrings);
}
}
// Lazily load general info from the file
VOID CAvailableApplicationInfo::RetrieveGeneralInfo(AvailableStrings& AvlbStrings)
{
m_Parser = new CConfigParser(m_sFileName);
// TODO: I temporarily use the file name (without suffix) as package name.
// It should be better to put this in a field of ini file.
// Consider writing a converter to do this and write a github action for
// rapps-db to ensure package_name is unique.
m_szPkgName = m_sFileName;
PathRemoveExtensionW(m_szPkgName.GetBuffer(MAX_PATH));
m_szPkgName.ReleaseBuffer();
m_Parser->GetInt(L"Category", m_Category);
if (!GetString(L"Name", m_szName)
|| !GetString(L"URLDownload", m_szUrlDownload))
{
delete m_Parser;
return;
}
GetString(L"RegName", m_szRegName);
GetString(L"Version", m_szVersion);
GetString(L"License", m_szLicense);
GetString(L"Description", m_szDesc);
GetString(L"URLSite", m_szUrlSite);
GetString(L"SHA1", m_szSHA1);
static_assert(MAX_SCRNSHOT_NUM < 10000, "MAX_SCRNSHOT_NUM is too big");
for (int i = 0; i < MAX_SCRNSHOT_NUM; i++)
{
CStringW ScrnshotField;
ScrnshotField.Format(L"Screenshot%d", i + 1);
CStringW ScrnshotLocation;
if (!GetString(ScrnshotField, ScrnshotLocation))
{
// We stop at the first screenshot not found,
// so screenshots _have_ to be consecutive
break;
}
if (PathIsURLW(ScrnshotLocation.GetString()))
{
m_szScrnshotLocation.Add(ScrnshotLocation);
}
else
{
// TODO: Does the filename contain anything stuff like ":" "<" ">" ?
// these stuff may lead to security issues
ATL::CStringW ScrnshotName = AvlbStrings.szAppsPath;
PathAppendW(ScrnshotName.GetBuffer(MAX_PATH), L"screenshots");
BOOL bSuccess = PathAppendNoDirEscapeW(ScrnshotName.GetBuffer(), ScrnshotLocation.GetString());
ScrnshotName.ReleaseBuffer();
if (bSuccess)
{
m_szScrnshotLocation.Add(ScrnshotName);
}
}
}
ATL::CStringW IconPath = AvlbStrings.szAppsPath;
PathAppendW(IconPath.GetBuffer(MAX_PATH), L"icons");
// TODO: are we going to support specify an URL for an icon ?
ATL::CStringW IconLocation;
if (GetString(L"Icon", IconLocation))
{
BOOL bSuccess = PathAppendNoDirEscapeW(IconPath.GetBuffer(), IconLocation.GetString());
IconPath.ReleaseBuffer();
if (!bSuccess)
{
IconPath.Empty();
}
}
else
{
// inifile.ico
PathAppendW(IconPath.GetBuffer(), m_szPkgName);
IconPath.ReleaseBuffer();
IconPath += L".ico";
}
if (!IconPath.IsEmpty())
{
if (PathFileExistsW(IconPath))
{
m_szIconLocation = IconPath;
}
}
RetrieveSize();
RetrieveLicenseType();
RetrieveLanguages();
RetrieveInstalledStatus();
if (m_IsInstalled)
{
RetrieveInstalledVersion();
}
delete m_Parser;
}
VOID CAvailableApplicationInfo::RetrieveInstalledStatus()
{
m_IsInstalled = ::GetInstalledVersion(NULL, m_szRegName)
|| ::GetInstalledVersion(NULL, m_szName);
}
VOID CAvailableApplicationInfo::RetrieveInstalledVersion()
{
ATL::CStringW szNameVersion;
szNameVersion = m_szName + L" " + m_szVersion;
m_HasInstalledVersion = ::GetInstalledVersion(&m_szInstalledVersion, m_szRegName)
|| ::GetInstalledVersion(&m_szInstalledVersion, m_szName)
|| ::GetInstalledVersion(&m_szInstalledVersion, szNameVersion);
}
VOID CAvailableApplicationInfo::RetrieveLanguages()
{
const WCHAR cDelimiter = L'|';
ATL::CStringW szBuffer;
// TODO: Get multiline parameter
if (!m_Parser->GetString(L"Languages", szBuffer))
{
m_HasLanguageInfo = FALSE;
return;
}
// Parse parameter string
ATL::CStringW m_szLocale;
INT iLCID;
for (INT i = 0; szBuffer[i] != UNICODE_NULL; ++i)
{
if (szBuffer[i] != cDelimiter && szBuffer[i] != L'\n')
{
m_szLocale += szBuffer[i];
}
else
{
if (StrToIntExW(m_szLocale.GetString(), STIF_DEFAULT, &iLCID))
{
m_LanguageLCIDs.Add(static_cast<LCID>(iLCID));
m_szLocale.Empty();
}
}
}
// For the text after delimiter
if (!m_szLocale.IsEmpty())
{
if (StrToIntExW(m_szLocale.GetString(), STIF_DEFAULT, &iLCID))
{
m_LanguageLCIDs.Add(static_cast<LCID>(iLCID));
}
}
m_HasLanguageInfo = TRUE;
}
VOID CAvailableApplicationInfo::RetrieveLicenseType()
{
INT IntBuffer;
m_Parser->GetInt(L"LicenseType", IntBuffer);
if (IsLicenseType(IntBuffer))
{
m_LicenseType = static_cast<LicenseType>(IntBuffer);
}
else
{
m_LicenseType = LICENSE_NONE;
}
}
VOID CAvailableApplicationInfo::RetrieveSize()
{
INT iSizeBytes;
if (!m_Parser->GetInt(L"SizeBytes", iSizeBytes))
return;
m_SizeBytes = iSizeBytes;
StrFormatByteSizeW(iSizeBytes, m_szSize.GetBuffer(MAX_PATH), MAX_PATH);
m_szSize.ReleaseBuffer();
}
BOOL CAvailableApplicationInfo::FindInLanguages(LCID what) const
{
if (!m_HasLanguageInfo)
{
return FALSE;
}
//Find locale code in the list
const INT nLanguagesSize = m_LanguageLCIDs.GetSize();
for (INT i = 0; i < nLanguagesSize; ++i)
{
if (m_LanguageLCIDs[i] == what)
{
return TRUE;
}
}
return FALSE;
}
BOOL CAvailableApplicationInfo::HasLanguageInfo() const
{
return m_HasLanguageInfo;
}
BOOL CAvailableApplicationInfo::HasNativeLanguage() const
{
return FindInLanguages(GetUserDefaultLCID());
}
BOOL CAvailableApplicationInfo::HasEnglishLanguage() const
{
return FindInLanguages(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT));
}
BOOL CAvailableApplicationInfo::IsInstalled() const
{
return m_IsInstalled;
}
BOOL CAvailableApplicationInfo::HasInstalledVersion() const
{
return m_HasInstalledVersion;
}
BOOL CAvailableApplicationInfo::HasUpdate() const
{
return (m_szInstalledVersion.Compare(m_szVersion) < 0) ? TRUE : FALSE;
}
BOOL CAvailableApplicationInfo::RetrieveScrnshot(UINT Index,ATL::CStringW& ScrnshotLocation) const
{
if (Index >= (UINT)m_szScrnshotLocation.GetSize())
{
return FALSE;
}
ScrnshotLocation = m_szScrnshotLocation[Index];
return TRUE;
}
BOOL CAvailableApplicationInfo::RetrieveIcon(ATL::CStringW& IconLocation) const
{
if (m_szIconLocation.IsEmpty())
{
return FALSE;
}
IconLocation = m_szIconLocation;
return TRUE;
}
VOID CAvailableApplicationInfo::SetLastWriteTime(FILETIME* ftTime)
{
RtlCopyMemory(&m_ftCacheStamp, ftTime, sizeof(FILETIME));
}
inline BOOL CAvailableApplicationInfo::GetString(LPCWSTR lpKeyName, ATL::CStringW& ReturnedString)
{
if (!m_Parser->GetString(lpKeyName, ReturnedString))
{
ReturnedString.Empty();
return FALSE;
}
return TRUE;
}
// CAvailableApplicationInfo
// AvailableStrings
AvailableStrings::AvailableStrings()
{
//FIXME: maybe provide a fallback?
if (GetStorageDirectory(szPath))
{
szAppsPath = szPath;
PathAppendW(szAppsPath.GetBuffer(MAX_PATH), L"rapps");
szAppsPath.ReleaseBuffer();
szCabName = APPLICATION_DATABASE_NAME;
szCabDir = szPath;
szCabPath = szCabDir;
PathAppendW(szCabPath.GetBuffer(MAX_PATH), szCabName);
szCabPath.ReleaseBuffer();
szSearchPath = szAppsPath;
PathAppendW(szSearchPath.GetBuffer(MAX_PATH), L"*.txt");
szSearchPath.ReleaseBuffer();
}
}
// AvailableStrings
// CAvailableApps
AvailableStrings CAvailableApps::m_Strings;
CAvailableApps::CAvailableApps()
{
}
VOID CAvailableApps::FreeCachedEntries()
{
POSITION InfoListPosition = m_InfoList.GetHeadPosition();
/* loop and deallocate all the cached app infos in the list */
while (InfoListPosition)
{
CAvailableApplicationInfo* Info = m_InfoList.GetNext(InfoListPosition);
delete Info;
}
m_InfoList.RemoveAll();
}
static void DeleteWithWildcard(const CStringW& DirWithFilter)
{
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindFileData;
hFind = FindFirstFileW(DirWithFilter, &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
return;
CStringW Dir = DirWithFilter;
PathRemoveFileSpecW(Dir.GetBuffer(MAX_PATH));
Dir.ReleaseBuffer();
do
{
ATL::CStringW szTmp = Dir + L"\\";
szTmp += FindFileData.cFileName;
if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
DeleteFileW(szTmp);
}
} while (FindNextFileW(hFind, &FindFileData) != 0);
FindClose(hFind);
}
VOID CAvailableApps::DeleteCurrentAppsDB()
{
// Delete icons
ATL::CStringW IconPath = m_Strings.szAppsPath;
PathAppendW(IconPath.GetBuffer(MAX_PATH), L"icons");
IconPath.ReleaseBuffer();
DeleteWithWildcard(IconPath + L"\\*.ico");
// Delete leftover screenshots
ATL::CStringW ScrnshotFolder = m_Strings.szAppsPath;
PathAppendW(ScrnshotFolder.GetBuffer(MAX_PATH), L"screenshots");
ScrnshotFolder.ReleaseBuffer();
DeleteWithWildcard(IconPath + L"\\*.tmp");
// Delete data base files (*.txt)
DeleteWithWildcard(m_Strings.szSearchPath);
RemoveDirectoryW(IconPath);
RemoveDirectoryW(ScrnshotFolder);
RemoveDirectoryW(m_Strings.szAppsPath);
RemoveDirectoryW(m_Strings.szPath);
}
BOOL CAvailableApps::UpdateAppsDB()
{
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindFileData;
if (!CreateDirectoryW(m_Strings.szPath, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
{
return FALSE;
}
// If there are some files in the db folder, we're good
hFind = FindFirstFileW(m_Strings.szSearchPath, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE)
{
FindClose(hFind);
return TRUE;
}
DownloadApplicationsDB(SettingsInfo.bUseSource ? SettingsInfo.szSourceURL : APPLICATION_DATABASE_URL,
!SettingsInfo.bUseSource);
if (!ExtractFilesFromCab(m_Strings.szCabName,
m_Strings.szCabDir,
m_Strings.szAppsPath))
{
return FALSE;
}
DeleteFileW(m_Strings.szCabPath);
return TRUE;
}
BOOL CAvailableApps::ForceUpdateAppsDB()
{
DeleteCurrentAppsDB();
return UpdateAppsDB();
}
BOOL CAvailableApps::Enum(INT EnumType, AVAILENUMPROC lpEnumProc, PVOID param)
{
if (EnumType == ENUM_CAT_SELECTED)
{
CAvailableApplicationInfo *EnumAvlbInfo = NULL;
// enum all object in m_SelectedList and invoke callback
for(POSITION CurrentPosition = m_SelectedList.GetHeadPosition();
CurrentPosition && (EnumAvlbInfo = m_SelectedList.GetAt(CurrentPosition));
m_SelectedList.GetNext(CurrentPosition))
{
EnumAvlbInfo->RefreshAppInfo(m_Strings);
if (lpEnumProc)
lpEnumProc(EnumAvlbInfo, TRUE, param);
}
return TRUE;
}
else
{
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindFileData;
hFind = FindFirstFileW(m_Strings.szSearchPath.GetString(), &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
//no db yet
return FALSE;
}
do
{
// loop for all the cached entries
POSITION CurrentListPosition = m_InfoList.GetHeadPosition();
CAvailableApplicationInfo *Info = NULL;
while (CurrentListPosition != NULL)
{
POSITION LastListPosition = CurrentListPosition;
Info = m_InfoList.GetNext(CurrentListPosition);
// do we already have this entry in cache?
if (Info->m_sFileName == FindFileData.cFileName)
{
// is it current enough, or the file has been modified since our last time here?
if (CompareFileTime(&FindFileData.ftLastWriteTime, &Info->m_ftCacheStamp) == 1)
{
// recreate our cache, this is the slow path
m_InfoList.RemoveAt(LastListPosition);
// also remove this in selected list (if exist)
RemoveSelected(Info);
delete Info;
Info = NULL;
break;
}
else
{
// speedy path, compare directly, we already have the data
goto skip_if_cached;
}
}
}
// create a new entry
Info = new CAvailableApplicationInfo(FindFileData.cFileName, m_Strings);
// set a timestamp for the next time
Info->SetLastWriteTime(&FindFileData.ftLastWriteTime);
/* Check if we have the download URL */
if (Info->m_szUrlDownload.IsEmpty())
{
/* Can't use it, delete it */
delete Info;
continue;
}
m_InfoList.AddTail(Info);
skip_if_cached:
if (EnumType == Info->m_Category
|| EnumType == ENUM_ALL_AVAILABLE)
{
Info->RefreshAppInfo(m_Strings);
if (lpEnumProc)
{
if (m_SelectedList.Find(Info))
{
lpEnumProc(Info, TRUE, param);
}
else
{
lpEnumProc(Info, FALSE, param);
}
}
}
} while (FindNextFileW(hFind, &FindFileData));
FindClose(hFind);
return TRUE;
}
}
BOOL CAvailableApps::AddSelected(CAvailableApplicationInfo *AvlbInfo)
{
return m_SelectedList.AddTail(AvlbInfo) != 0;
}
BOOL CAvailableApps::RemoveSelected(CAvailableApplicationInfo *AvlbInfo)
{
POSITION Position = m_SelectedList.Find(AvlbInfo);
if (Position)
{
m_SelectedList.RemoveAt(Position);
return TRUE;
}
return FALSE;
}
VOID CAvailableApps::RemoveAllSelected()
{
m_SelectedList.RemoveAll();
return;
}
int CAvailableApps::GetSelectedCount()
{
return m_SelectedList.GetCount();
}
CAvailableApplicationInfo* CAvailableApps::FindAppByPkgName(const ATL::CStringW& szPkgName) const
{
if (m_InfoList.IsEmpty())
{
return NULL;
}
// linear search
POSITION CurrentListPosition = m_InfoList.GetHeadPosition();
CAvailableApplicationInfo* info;
while (CurrentListPosition != NULL)
{
info = m_InfoList.GetNext(CurrentListPosition);
if (info->m_szPkgName.CompareNoCase(szPkgName) == 0)
{
return info;
}
}
return NULL;
}
ATL::CSimpleArray<CAvailableApplicationInfo> CAvailableApps::FindAppsByPkgNameList(const ATL::CSimpleArray<ATL::CStringW> &PkgNameList) const
{
ATL::CSimpleArray<CAvailableApplicationInfo> result;
for (INT i = 0; i < PkgNameList.GetSize(); ++i)
{
CAvailableApplicationInfo* Info = FindAppByPkgName(PkgNameList[i]);
if (Info)
{
result.Add(*Info);
}
}
return result;
}
// CAvailableApps

View file

@ -22,58 +22,32 @@
/* String conversion helper functions */ /* String conversion helper functions */
// converts CStringW to CStringA using a given codepage // converts CStringW to CStringA using a given codepage
inline BOOL WideToMultiByte(const CStringW& szSource, inline BOOL
CStringA& szDest, WideToMultiByte(const CStringW &szSource, CStringA &szDest, UINT Codepage)
UINT Codepage)
{ {
// determine the needed size // determine the needed size
INT sz = WideCharToMultiByte(Codepage, INT sz = WideCharToMultiByte(Codepage, 0, szSource, -1, NULL, NULL, NULL, NULL);
0,
szSource,
-1,
NULL,
NULL,
NULL,
NULL);
if (!sz) if (!sz)
return FALSE; return FALSE;
// do the actual conversion // do the actual conversion
sz = WideCharToMultiByte(Codepage, sz = WideCharToMultiByte(Codepage, 0, szSource, -1, szDest.GetBuffer(sz), sz, NULL, NULL);
0,
szSource,
-1,
szDest.GetBuffer(sz),
sz,
NULL,
NULL);
szDest.ReleaseBuffer(); szDest.ReleaseBuffer();
return sz != 0; return sz != 0;
} }
// converts CStringA to CStringW using a given codepage // converts CStringA to CStringW using a given codepage
inline BOOL MultiByteToWide(const CStringA& szSource, inline BOOL
CStringW& szDest, MultiByteToWide(const CStringA &szSource, CStringW &szDest, UINT Codepage)
UINT Codepage)
{ {
// determine the needed size // determine the needed size
INT sz = MultiByteToWideChar(Codepage, INT sz = MultiByteToWideChar(Codepage, 0, szSource, -1, NULL, NULL);
0,
szSource,
-1,
NULL,
NULL);
if (!sz) if (!sz)
return FALSE; return FALSE;
// do the actual conversion // do the actual conversion
sz = MultiByteToWideChar(CP_UTF8, sz = MultiByteToWideChar(CP_UTF8, 0, szSource, -1, szDest.GetBuffer(sz), sz);
0,
szSource,
-1,
szDest.GetBuffer(sz),
sz);
szDest.ReleaseBuffer(); szDest.ReleaseBuffer();
return sz != 0; return sz != 0;
@ -96,7 +70,7 @@ FNOPEN(fnFileOpen)
HANDLE hFile = NULL; HANDLE hFile = NULL;
DWORD dwDesiredAccess = 0; DWORD dwDesiredAccess = 0;
DWORD dwCreationDisposition = 0; DWORD dwCreationDisposition = 0;
ATL::CStringW szFileName; CStringW szFileName;
UNREFERENCED_PARAMETER(pmode); UNREFERENCED_PARAMETER(pmode);
@ -124,24 +98,19 @@ FNOPEN(fnFileOpen)
MultiByteToWide(pszFile, szFileName, CP_UTF8); MultiByteToWide(pszFile, szFileName, CP_UTF8);
hFile = CreateFileW(szFileName, hFile = CreateFileW(
dwDesiredAccess, szFileName, dwDesiredAccess, FILE_SHARE_READ, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
FILE_SHARE_READ,
NULL,
dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL,
NULL);
return (INT_PTR) hFile; return (INT_PTR)hFile;
} }
FNREAD(fnFileRead) FNREAD(fnFileRead)
{ {
DWORD dwBytesRead = 0; DWORD dwBytesRead = 0;
if (ReadFile((HANDLE) hf, pv, cb, &dwBytesRead, NULL) == FALSE) if (ReadFile((HANDLE)hf, pv, cb, &dwBytesRead, NULL) == FALSE)
{ {
dwBytesRead = (DWORD) -1L; dwBytesRead = (DWORD)-1L;
} }
return dwBytesRead; return dwBytesRead;
@ -151,9 +120,9 @@ FNWRITE(fnFileWrite)
{ {
DWORD dwBytesWritten = 0; DWORD dwBytesWritten = 0;
if (WriteFile((HANDLE) hf, pv, cb, &dwBytesWritten, NULL) == FALSE) if (WriteFile((HANDLE)hf, pv, cb, &dwBytesWritten, NULL) == FALSE)
{ {
dwBytesWritten = (DWORD) -1; dwBytesWritten = (DWORD)-1;
} }
return dwBytesWritten; return dwBytesWritten;
@ -161,12 +130,12 @@ FNWRITE(fnFileWrite)
FNCLOSE(fnFileClose) FNCLOSE(fnFileClose)
{ {
return (CloseHandle((HANDLE) hf) != FALSE) ? 0 : -1; return (CloseHandle((HANDLE)hf) != FALSE) ? 0 : -1;
} }
FNSEEK(fnFileSeek) FNSEEK(fnFileSeek)
{ {
return SetFilePointer((HANDLE) hf, dist, NULL, seektype); return SetFilePointer((HANDLE)hf, dist, NULL, seektype);
} }
/* FDICopy callbacks */ /* FDICopy callbacks */
@ -177,76 +146,75 @@ FNFDINOTIFY(fnNotify)
switch (fdint) switch (fdint)
{ {
case fdintCOPY_FILE: case fdintCOPY_FILE:
{
CStringW szExtractDir, szCabFileName;
// Append the destination directory to the file name.
MultiByteToWide((LPCSTR) pfdin->pv, szExtractDir, CP_UTF8);
MultiByteToWide(pfdin->psz1, szCabFileName, CP_ACP);
if (szCabFileName.Find('\\') >= 0)
{ {
CStringW szNewDirName = szExtractDir; CStringW szExtractDir, szCabFileName;
int nTokenPos = 0;
// We do not want to interpret the filename as directory,
// so bail out before the last token!
while (szCabFileName.Find('\\', nTokenPos) >= 0)
{
CStringW token = szCabFileName.Tokenize(L"\\", nTokenPos);
if (token.IsEmpty())
break;
szNewDirName += L"\\" + token; // Append the destination directory to the file name.
if (!CreateDirectoryW(szNewDirName, NULL)) MultiByteToWide((LPCSTR)pfdin->pv, szExtractDir, CP_UTF8);
MultiByteToWide(pfdin->psz1, szCabFileName, CP_ACP);
if (szCabFileName.Find('\\') >= 0)
{
CStringW szNewDirName = szExtractDir;
int nTokenPos = 0;
// We do not want to interpret the filename as directory,
// so bail out before the last token!
while (szCabFileName.Find('\\', nTokenPos) >= 0)
{ {
DWORD dwErr = GetLastError(); CStringW token = szCabFileName.Tokenize(L"\\", nTokenPos);
if (dwErr != ERROR_ALREADY_EXISTS) if (token.IsEmpty())
break;
szNewDirName += L"\\" + token;
if (!CreateDirectoryW(szNewDirName, NULL))
{ {
DPRINT1("ERROR: Unable to create directory %S (err %lu)\n", szNewDirName.GetString(), dwErr); DWORD dwErr = GetLastError();
if (dwErr != ERROR_ALREADY_EXISTS)
{
DPRINT1(
"ERROR: Unable to create directory %S (err %lu)\n", szNewDirName.GetString(), dwErr);
}
} }
} }
} }
CStringW szNewFileName = szExtractDir + L"\\" + szCabFileName;
CStringA szFilePathUTF8;
WideToMultiByte(szNewFileName, szFilePathUTF8, CP_UTF8);
// Open the file
iResult = fnFileOpen((LPSTR)szFilePathUTF8.GetString(), _O_WRONLY | _O_CREAT, 0);
} }
CStringW szNewFileName = szExtractDir + L"\\" + szCabFileName;
CStringA szFilePathUTF8;
WideToMultiByte(szNewFileName, szFilePathUTF8, CP_UTF8);
// Open the file
iResult = fnFileOpen((LPSTR) szFilePathUTF8.GetString(),
_O_WRONLY | _O_CREAT,
0);
}
break;
case fdintCLOSE_FILE_INFO:
iResult = !fnFileClose(pfdin->hf);
break; break;
case fdintNEXT_CABINET: case fdintCLOSE_FILE_INFO:
if (pfdin->fdie != FDIERROR_NONE) iResult = !fnFileClose(pfdin->hf);
{ break;
case fdintNEXT_CABINET:
if (pfdin->fdie != FDIERROR_NONE)
{
iResult = -1;
}
break;
case fdintPARTIAL_FILE:
iResult = 0;
break;
case fdintCABINET_INFO:
iResult = 0;
break;
case fdintENUMERATE:
iResult = 0;
break;
default:
iResult = -1; iResult = -1;
} break;
break;
case fdintPARTIAL_FILE:
iResult = 0;
break;
case fdintCABINET_INFO:
iResult = 0;
break;
case fdintENUMERATE:
iResult = 0;
break;
default:
iResult = -1;
break;
} }
return iResult; return iResult;
@ -254,33 +222,18 @@ FNFDINOTIFY(fnNotify)
/* cabinet.dll FDI function pointers */ /* cabinet.dll FDI function pointers */
typedef HFDI(*fnFDICreate)(PFNALLOC, typedef HFDI (*fnFDICreate)(PFNALLOC, PFNFREE, PFNOPEN, PFNREAD, PFNWRITE, PFNCLOSE, PFNSEEK, int, PERF);
PFNFREE,
PFNOPEN,
PFNREAD,
PFNWRITE,
PFNCLOSE,
PFNSEEK,
int,
PERF);
typedef BOOL(*fnFDICopy)(HFDI, typedef BOOL (*fnFDICopy)(HFDI, LPSTR, LPSTR, INT, PFNFDINOTIFY, PFNFDIDECRYPT, void FAR *pvUser);
LPSTR,
LPSTR,
INT,
PFNFDINOTIFY,
PFNFDIDECRYPT,
void FAR *pvUser);
typedef BOOL(*fnFDIDestroy)(HFDI); typedef BOOL (*fnFDIDestroy)(HFDI);
/* /*
* Extraction function * Extraction function
* TODO: require only a full path to the cab as an argument * TODO: require only a full path to the cab as an argument
*/ */
BOOL ExtractFilesFromCab(const ATL::CStringW& szCabName, BOOL
const ATL::CStringW& szCabDir, ExtractFilesFromCab(const CStringW &szCabName, const CStringW &szCabDir, const CStringW &szOutputDir)
const ATL::CStringW& szOutputDir)
{ {
HINSTANCE hCabinetDll; HINSTANCE hCabinetDll;
HFDI ExtractHandler; HFDI ExtractHandler;
@ -299,9 +252,9 @@ BOOL ExtractFilesFromCab(const ATL::CStringW& szCabName,
return FALSE; return FALSE;
} }
pfnFDICreate = (fnFDICreate) GetProcAddress(hCabinetDll, "FDICreate"); pfnFDICreate = (fnFDICreate)GetProcAddress(hCabinetDll, "FDICreate");
pfnFDICopy = (fnFDICopy) GetProcAddress(hCabinetDll, "FDICopy"); pfnFDICopy = (fnFDICopy)GetProcAddress(hCabinetDll, "FDICopy");
pfnFDIDestroy = (fnFDIDestroy) GetProcAddress(hCabinetDll, "FDIDestroy"); pfnFDIDestroy = (fnFDIDestroy)GetProcAddress(hCabinetDll, "FDIDestroy");
if (!pfnFDICreate || !pfnFDICopy || !pfnFDIDestroy) if (!pfnFDICreate || !pfnFDICopy || !pfnFDIDestroy)
{ {
@ -310,15 +263,9 @@ BOOL ExtractFilesFromCab(const ATL::CStringW& szCabName,
} }
// Create FDI context // Create FDI context
ExtractHandler = pfnFDICreate(fnMemAlloc, ExtractHandler = pfnFDICreate(
fnMemFree, fnMemAlloc, fnMemFree, fnFileOpen, fnFileRead, fnFileWrite, fnFileClose, fnFileSeek, cpuUNKNOWN,
fnFileOpen, &ExtractErrors);
fnFileRead,
fnFileWrite,
fnFileClose,
fnFileSeek,
cpuUNKNOWN,
&ExtractErrors);
if (!ExtractHandler) if (!ExtractHandler)
{ {
@ -343,13 +290,9 @@ BOOL ExtractFilesFromCab(const ATL::CStringW& szCabName,
// Add a slash to cab name as required by the api // Add a slash to cab name as required by the api
szCabNameUTF8 = "\\" + szCabNameUTF8; szCabNameUTF8 = "\\" + szCabNameUTF8;
bResult = pfnFDICopy(ExtractHandler, bResult = pfnFDICopy(
(LPSTR) szCabNameUTF8.GetString(), ExtractHandler, (LPSTR)szCabNameUTF8.GetString(), (LPSTR)szCabDirUTF8.GetString(), 0, fnNotify, NULL,
(LPSTR) szCabDirUTF8.GetString(), (void FAR *)szOutputDirUTF8.GetString());
0,
fnNotify,
NULL,
(void FAR *) szOutputDirUTF8.GetString());
} }
pfnFDIDestroy(ExtractHandler); pfnFDIDestroy(ExtractHandler);

View file

@ -24,12 +24,11 @@ struct CSectionNames
}; };
static CSectionNames g_Names; static CSectionNames g_Names;
static CStringW
static GetINIFullPath(const CStringW &FileName)
ATL::CStringW GetINIFullPath(const ATL::CStringW& FileName)
{ {
ATL::CStringW szDir; CStringW szDir;
ATL::CStringW szBuffer; CStringW szBuffer;
GetStorageDirectory(szDir); GetStorageDirectory(szDir);
szBuffer.Format(L"%ls\\rapps\\%ls", szDir.GetString(), FileName.GetString()); szBuffer.Format(L"%ls\\rapps\\%ls", szDir.GetString(), FileName.GetString());
@ -37,13 +36,13 @@ ATL::CStringW GetINIFullPath(const ATL::CStringW& FileName)
return szBuffer; return szBuffer;
} }
CConfigParser::CConfigParser(const ATL::CStringW& FileName) CConfigParser::CConfigParser(const CStringW &FileName) : szConfigPath(GetINIFullPath(FileName))
: szConfigPath(GetINIFullPath(FileName))
{ {
CacheINI(); CacheINI();
} }
void CConfigParser::ReadSection(ATL::CStringW& Buffer, const ATL::CStringW& Section, BOOL isArch) void
CConfigParser::ReadSection(CStringW &Buffer, const CStringW &Section, BOOL isArch)
{ {
DWORD len = 512; DWORD len = 512;
DWORD result; DWORD result;
@ -84,7 +83,7 @@ void CConfigParser::ReadSection(ATL::CStringW& Buffer, const ATL::CStringW& Sect
continue; continue;
} }
CString value = tmp.Mid(idx+1); CString value = tmp.Mid(idx + 1);
m_Keys.Add(key, value); m_Keys.Add(key, value);
} }
else else
@ -99,7 +98,8 @@ void CConfigParser::ReadSection(ATL::CStringW& Buffer, const ATL::CStringW& Sect
} }
} }
VOID CConfigParser::CacheINI() VOID
CConfigParser::CacheINI()
{ {
// Cache section names // Cache section names
if (g_Names.ArchSpecific.Locale.IsEmpty()) if (g_Names.ArchSpecific.Locale.IsEmpty())
@ -135,7 +135,6 @@ VOID CConfigParser::CacheINI()
} }
ReadSection(Buffer, g_Names.ArchSpecific.Section, TRUE); ReadSection(Buffer, g_Names.ArchSpecific.Section, TRUE);
ReadSection(Buffer, g_Names.ArchNeutral.Locale, FALSE); ReadSection(Buffer, g_Names.ArchNeutral.Locale, FALSE);
if (!g_Names.ArchNeutral.LocaleNeutral.IsEmpty()) if (!g_Names.ArchNeutral.LocaleNeutral.IsEmpty())
{ {
@ -144,7 +143,8 @@ VOID CConfigParser::CacheINI()
ReadSection(Buffer, g_Names.ArchNeutral.Section, FALSE); ReadSection(Buffer, g_Names.ArchNeutral.Section, FALSE);
} }
BOOL CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString) BOOL
CConfigParser::GetString(const CStringW &KeyName, CStringW &ResultString)
{ {
int nIndex = m_Keys.FindKey(KeyName); int nIndex = m_Keys.FindKey(KeyName);
if (nIndex >= 0) if (nIndex >= 0)
@ -157,9 +157,10 @@ BOOL CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& Resul
return FALSE; return FALSE;
} }
BOOL CConfigParser::GetInt(const ATL::CStringW& KeyName, INT& iResult) BOOL
CConfigParser::GetInt(const CStringW &KeyName, INT &iResult)
{ {
ATL::CStringW Buffer; CStringW Buffer;
iResult = 0; iResult = 0;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,35 @@
#pragma once
#include <atlcoll.h>
#include <atlpath.h>
#include "applicationinfo.h"
class CApplicationDB
{
private:
CPathW m_BasePath;
CAtlList<CApplicationInfo *> m_Available;
CAtlList<CApplicationInfo *> m_Installed;
BOOL
EnumerateFiles();
public:
CApplicationDB(const CStringW &path);
VOID
GetApps(CAtlList<CApplicationInfo *> &List, AppsCategories Type) const;
CApplicationInfo *
FindByPackageName(const CStringW &name);
VOID
UpdateAvailable();
VOID
UpdateInstalled();
VOID
RemoveCached();
BOOL
RemoveInstalledAppFromRegistry(const CApplicationInfo *Info);
};

View file

@ -0,0 +1,186 @@
#pragma once
#include <atlstr.h>
#include <atlpath.h>
#include <atlsimpcoll.h>
enum LicenseType
{
LICENSE_NONE,
LICENSE_OPENSOURCE,
LICENSE_FREEWARE,
LICENSE_TRIAL,
LICENSE_MIN = LICENSE_NONE,
LICENSE_MAX = LICENSE_TRIAL
};
inline BOOL
IsLicenseType(INT x)
{
return (x >= LICENSE_MIN && x <= LICENSE_MAX);
}
enum AppsCategories
{
ENUM_ALL_AVAILABLE,
ENUM_CAT_AUDIO,
ENUM_CAT_VIDEO,
ENUM_CAT_GRAPHICS,
ENUM_CAT_GAMES,
ENUM_CAT_INTERNET,
ENUM_CAT_OFFICE,
ENUM_CAT_DEVEL,
ENUM_CAT_EDU,
ENUM_CAT_ENGINEER,
ENUM_CAT_FINANCE,
ENUM_CAT_SCIENCE,
ENUM_CAT_TOOLS,
ENUM_CAT_DRIVERS,
ENUM_CAT_LIBS,
ENUM_CAT_THEMES,
ENUM_CAT_OTHER,
ENUM_CAT_SELECTED,
ENUM_ALL_INSTALLED = 30,
ENUM_INSTALLED_APPLICATIONS,
ENUM_UPDATES,
ENUM_INVALID,
ENUM_INSTALLED_MIN = ENUM_ALL_INSTALLED,
ENUM_INSTALLED_MAX = ENUM_UPDATES,
ENUM_AVAILABLE_MIN = ENUM_ALL_AVAILABLE,
ENUM_AVAILABLE_MAX = ENUM_CAT_SELECTED,
};
inline BOOL
IsAvailableEnum(INT x)
{
return (x >= ENUM_AVAILABLE_MIN && x <= ENUM_AVAILABLE_MAX);
}
inline BOOL
IsInstalledEnum(INT x)
{
return (x >= ENUM_INSTALLED_MIN && x <= ENUM_INSTALLED_MAX);
}
class CAppRichEdit;
class CApplicationInfo
{
public:
CApplicationInfo(const CStringW &Identifier, AppsCategories Category);
virtual ~CApplicationInfo();
const CStringW szIdentifier; // PkgName or KeyName
const AppsCategories iCategory;
CStringW szDisplayIcon;
CStringW szDisplayName;
CStringW szDisplayVersion;
CStringW szComments;
virtual BOOL
Valid() const = 0;
virtual BOOL
CanModify() = 0;
virtual BOOL
RetrieveIcon(CStringW &Path) const = 0;
virtual BOOL
RetrieveScreenshot(CStringW &Path) = 0;
virtual VOID
ShowAppInfo(CAppRichEdit *RichEdit) = 0;
virtual VOID
GetDownloadInfo(CStringW &Url, CStringW &Sha1, ULONG &SizeInBytes) const = 0;
virtual VOID
GetDisplayInfo(CStringW &License, CStringW &Size, CStringW &UrlSite, CStringW &UrlDownload) = 0;
virtual BOOL
UninstallApplication(BOOL bModify) = 0;
};
class CAvailableApplicationInfo : public CApplicationInfo
{
class CConfigParser *m_Parser;
CSimpleArray<CStringW> m_szScrnshotLocation;
bool m_ScrnshotRetrieved;
CStringW m_szUrlDownload;
CStringW m_szSize;
CStringW m_szUrlSite;
CSimpleArray<LCID> m_LanguageLCIDs;
bool m_LanguagesLoaded;
VOID
InsertVersionInfo(CAppRichEdit *RichEdit);
VOID
InsertLanguageInfo(CAppRichEdit *RichEdit);
VOID
RetrieveLanguages();
CStringW
LicenseString();
public:
CAvailableApplicationInfo(
CConfigParser *Parser,
const CStringW &PkgName,
AppsCategories Category,
const CPathW &BasePath);
~CAvailableApplicationInfo();
virtual BOOL
Valid() const override;
virtual BOOL
CanModify() override;
virtual BOOL
RetrieveIcon(CStringW &Path) const override;
virtual BOOL
RetrieveScreenshot(CStringW &Path) override;
virtual VOID
ShowAppInfo(CAppRichEdit *RichEdit) override;
virtual VOID
GetDownloadInfo(CStringW &Url, CStringW &Sha1, ULONG &SizeInBytes) const override;
virtual VOID
GetDisplayInfo(CStringW &License, CStringW &Size, CStringW &UrlSite, CStringW &UrlDownload) override;
virtual BOOL
UninstallApplication(BOOL bModify) override;
};
class CInstalledApplicationInfo : public CApplicationInfo
{
CRegKey m_hKey;
CStringW m_szInstallDate;
CStringW m_szUninstallString;
CStringW m_szModifyString;
BOOL
GetApplicationRegString(LPCWSTR lpKeyName, CStringW &String);
BOOL
GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue);
VOID
AddApplicationRegString(CAppRichEdit *RichEdit, UINT StringID, const CStringW &String, DWORD TextFlags);
VOID
RetrieveInstallDate();
VOID
RetrieveUninstallStrings();
public:
const int iKeyIndex;
CInstalledApplicationInfo(HKEY Key, const CStringW &KeyName, AppsCategories Category, int KeyIndex);
~CInstalledApplicationInfo();
virtual BOOL
Valid() const override;
virtual BOOL
CanModify() override;
virtual BOOL
RetrieveIcon(CStringW &Path) const override;
virtual BOOL
RetrieveScreenshot(CStringW &Path) override;
virtual VOID
ShowAppInfo(CAppRichEdit *RichEdit) override;
virtual VOID
GetDownloadInfo(CStringW &Url, CStringW &Sha1, ULONG &SizeInBytes) const override;
virtual VOID
GetDisplayInfo(CStringW &License, CStringW &Size, CStringW &UrlSite, CStringW &UrlDownload) override;
virtual BOOL
UninstallApplication(BOOL bModify) override;
};

View file

@ -18,7 +18,6 @@
#include <gdiplus.h> #include <gdiplus.h>
#include <math.h> #include <math.h>
using namespace Gdiplus;
#define LISTVIEW_ICON_SIZE 32 #define LISTVIEW_ICON_SIZE 32
@ -38,30 +37,30 @@ using namespace Gdiplus;
#define TOOLBAR_PADDING 6 #define TOOLBAR_PADDING 6
// user-defined window message // user-defined window message
#define WM_RAPPS_DOWNLOAD_COMPLETE (WM_USER + 1) // notify download complete. wParam is error code, and lParam is a pointer to ScrnshotDownloadParam #define WM_RAPPS_DOWNLOAD_COMPLETE \
#define WM_RAPPS_RESIZE_CHILDREN (WM_USER + 2) // ask parent window to resize children. (WM_USER + 1) // notify download complete. wParam is error code, and lParam is a pointer to ScrnshotDownloadParam
#define WM_RAPPS_RESIZE_CHILDREN (WM_USER + 2) // ask parent window to resize children.
enum SCRNSHOT_STATUS enum SCRNSHOT_STATUS
{ {
SCRNSHOT_PREV_EMPTY, // show nothing SCRNSHOT_PREV_EMPTY, // show nothing
SCRNSHOT_PREV_LOADING, // image is loading (most likely downloading) SCRNSHOT_PREV_LOADING, // image is loading (most likely downloading)
SCRNSHOT_PREV_IMAGE, // display image from a file SCRNSHOT_PREV_IMAGE, // display image from a file
SCRNSHOT_PREV_FAILED // image can not be shown (download failure or wrong image) SCRNSHOT_PREV_FAILED // image can not be shown (download failure or wrong image)
}; };
#define TIMER_LOADING_ANIMATION 1 // Timer ID #define TIMER_LOADING_ANIMATION 1 // Timer ID
#define LOADING_ANIMATION_PERIOD 3 // Animation cycling period (in seconds) #define LOADING_ANIMATION_PERIOD 3 // Animation cycling period (in seconds)
#define LOADING_ANIMATION_FPS 18 // Animation Frame Per Second #define LOADING_ANIMATION_FPS 18 // Animation Frame Per Second
#define PI 3.1415927 #define PI 3.1415927
// retrieve the value using a mask // retrieve the value using a mask
#define STATEIMAGETOINDEX(x) (((x) & LVIS_STATEIMAGEMASK) >> 12) #define STATEIMAGETOINDEX(x) (((x)&LVIS_STATEIMAGEMASK) >> 12)
// for listview with extend style LVS_EX_CHECKBOXES, State image 1 is the unchecked box, and state image 2 is the checked box. // for listview with extend style LVS_EX_CHECKBOXES, State image 1 is the unchecked box, and state image 2 is the
// see this: https://docs.microsoft.com/en-us/windows/win32/controls/extended-list-view-styles // checked box. see this: https://docs.microsoft.com/en-us/windows/win32/controls/extended-list-view-styles
#define STATEIMAGE_UNCHECKED 1 #define STATEIMAGE_UNCHECKED 1
#define STATEIMAGE_CHECKED 2 #define STATEIMAGE_CHECKED 2
@ -69,7 +68,6 @@ class CMainWindow;
enum APPLICATION_VIEW_TYPE enum APPLICATION_VIEW_TYPE
{ {
AppViewTypeEmpty,
AppViewTypeAvailableApps, AppViewTypeAvailableApps,
AppViewTypeInstalledApps AppViewTypeInstalledApps
}; };
@ -79,129 +77,116 @@ typedef struct __ScrnshotDownloadParam
LONGLONG ID; LONGLONG ID;
HANDLE hFile; HANDLE hFile;
HWND hwndNotify; HWND hwndNotify;
ATL::CStringW DownloadFileName; CStringW DownloadFileName;
} ScrnshotDownloadParam; } ScrnshotDownloadParam;
class CAppRichEdit : public CUiWindow<CRichEdit>
class CAppRichEdit :
public CUiWindow<CRichEdit>
{ {
private: public:
VOID LoadAndInsertText(UINT uStringID, VOID
const ATL::CStringW &szText, LoadAndInsertText(UINT uStringID, const CStringW &szText, DWORD TextFlags);
DWORD StringFlags, VOID
DWORD TextFlags); LoadAndInsertText(UINT uStringID, DWORD StringFlags);
VOID
VOID LoadAndInsertText(UINT uStringID, InsertTextWithString(UINT StringID, const CStringW &Text, DWORD TextFlags);
DWORD StringFlags); VOID
SetWelcomeText();
VOID InsertVersionInfo(CAvailableApplicationInfo *Info);
VOID InsertLicenseInfo(CAvailableApplicationInfo *Info);
VOID InsertLanguageInfo(CAvailableApplicationInfo *Info);
public:
BOOL ShowAvailableAppInfo(CAvailableApplicationInfo *Info);
inline VOID InsertTextWithString(UINT StringID, DWORD StringFlags, const ATL::CStringW &Text, DWORD TextFlags);
BOOL ShowInstalledAppInfo(CInstalledApplicationInfo *Info);
VOID SetWelcomeText();
}; };
int ScrnshotDownloadCallback( int
pASYNCINET AsyncInet, ScrnshotDownloadCallback(pASYNCINET AsyncInet, ASYNC_EVENT Event, WPARAM wParam, LPARAM lParam, VOID *Extension);
ASYNC_EVENT Event,
WPARAM wParam,
LPARAM lParam,
VOID *Extension
);
class CAppScrnshotPreview : class CAppScrnshotPreview : public CWindowImpl<CAppScrnshotPreview>
public CWindowImpl<CAppScrnshotPreview>
{ {
private: private:
CStringW m_BasePath;
SCRNSHOT_STATUS ScrnshotPrevStauts = SCRNSHOT_PREV_EMPTY; SCRNSHOT_STATUS ScrnshotPrevStauts = SCRNSHOT_PREV_EMPTY;
Image *pImage = NULL; Gdiplus::Image *pImage = NULL;
HICON hBrokenImgIcon = NULL; HICON hBrokenImgIcon = NULL;
BOOL bLoadingTimerOn = FALSE; BOOL bLoadingTimerOn = FALSE;
int LoadingAnimationFrame = 0; int LoadingAnimationFrame = 0;
int BrokenImgSize = BROKENIMG_ICON_SIZE; int BrokenImgSize = BROKENIMG_ICON_SIZE;
pASYNCINET AsyncInet = NULL; pASYNCINET AsyncInet = NULL;
LONGLONG ContentID = 0; // used to determine whether image has been switched when download complete. Increase by 1 each time the content of this window changed LONGLONG ContentID = 0; // used to determine whether image has been switched when download complete. Increase by 1
ATL::CStringW TempImagePath; // currently displayed temp file // each time the content of this window changed
CStringW TempImagePath; // currently displayed temp file
BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId); BOOL
ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
VOID DisplayLoading(); VOID
DisplayLoading();
VOID
DisplayFailed();
BOOL
DisplayFile(LPCWSTR lpszFileName);
VOID
SetStatus(SCRNSHOT_STATUS Status);
VOID DisplayFailed(); VOID
PaintOnDC(HDC hdc, int width, int height, BOOL bDrawBkgnd);
float
GetLoadingDotWidth(int width, int height);
float
GetFrameDotShift(int Frame, int width, int height);
BOOL DisplayFile(LPCWSTR lpszFileName); public:
static ATL::CWndClassInfo &
GetWndClassInfo();
VOID SetStatus(SCRNSHOT_STATUS Status); HWND
Create(HWND hParent);
VOID PaintOnDC(HDC hdc, int width, int height, BOOL bDrawBkgnd); VOID
PreviousDisplayCleanup();
float GetLoadingDotWidth(int width, int height); VOID
DisplayEmpty();
float GetFrameDotShift(int Frame, int width, int height); BOOL
DisplayImage(LPCWSTR lpszLocation);
public:
static ATL::CWndClassInfo &GetWndClassInfo();
HWND Create(HWND hParent);
VOID PreviousDisplayCleanup();
VOID DisplayEmpty();
BOOL DisplayImage(LPCWSTR lpszLocation);
// calculate requested window width by given height // calculate requested window width by given height
int GetRequestedWidth(int Height); int
GetRequestedWidth(int Height);
CAppScrnshotPreview(const CStringW &BasePath);
~CAppScrnshotPreview(); ~CAppScrnshotPreview();
}; };
class CAppInfoDisplay : class CAppInfoDisplay : public CUiWindow<CWindowImpl<CAppInfoDisplay>>
public CUiWindow<CWindowImpl<CAppInfoDisplay>>
{ {
LPWSTR pLink = NULL; LPWSTR pLink = NULL;
private: private:
BOOL ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId); BOOL
ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
VOID
OnLink(ENLINK *Link);
VOID ResizeChildren(); VOID
ResizeChildren();
VOID ResizeChildren(int Width, int Height); VOID
ResizeChildren(int Width, int Height);
VOID OnLink(ENLINK *Link);
public:
public:
CAppRichEdit *RichEdit = NULL; CAppRichEdit *RichEdit = NULL;
CAppScrnshotPreview *ScrnshotPrev = NULL; CAppScrnshotPreview *ScrnshotPrev = NULL;
static ATL::CWndClassInfo &GetWndClassInfo(); static ATL::CWndClassInfo &
GetWndClassInfo();
HWND Create(HWND hwndParent); HWND
Create(HWND hwndParent);
BOOL ShowAvailableAppInfo(CAvailableApplicationInfo *Info); VOID
BOOL ShowInstalledAppInfo(CInstalledApplicationInfo *Info); ShowAppInfo(CApplicationInfo *Info);
VOID
VOID SetWelcomeText(); SetWelcomeText();
VOID
VOID OnCommand(WPARAM wParam, LPARAM lParam); OnCommand(WPARAM wParam, LPARAM lParam);
~CAppInfoDisplay(); ~CAppInfoDisplay();
}; };
class CAppsListView : class CAppsListView : public CUiWindow<CWindowImpl<CAppsListView, CListView>>
public CUiWindow<CWindowImpl<CAppsListView, CListView>>
{ {
struct SortContext struct SortContext
{ {
@ -218,65 +203,74 @@ class CAppsListView :
INT nLastHeaderID = -1; INT nLastHeaderID = -1;
APPLICATION_VIEW_TYPE ApplicationViewType = AppViewTypeEmpty; APPLICATION_VIEW_TYPE ApplicationViewType = AppViewTypeAvailableApps;
HIMAGELIST m_hImageListView = NULL; HIMAGELIST m_hImageListView = NULL;
CStringW m_Watermark; CStringW m_Watermark;
BEGIN_MSG_MAP(CAppsListView) BEGIN_MSG_MAP(CAppsListView)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
END_MSG_MAP() END_MSG_MAP()
LRESULT
OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); public:
public:
CAppsListView(); CAppsListView();
~CAppsListView(); ~CAppsListView();
VOID SetWatermark(const CStringW& Text); VOID
VOID SetCheckboxesVisible(BOOL bIsVisible); SetWatermark(const CStringW &Text);
VOID
SetCheckboxesVisible(BOOL bIsVisible);
VOID ColumnClick(LPNMLISTVIEW pnmv); VOID
ColumnClick(LPNMLISTVIEW pnmv);
BOOL AddColumn(INT Index, ATL::CStringW &Text, INT Width, INT Format); BOOL
AddColumn(INT Index, CStringW &Text, INT Width, INT Format);
void
DeleteColumn(INT Index);
int AddColumn(INT Index, LPWSTR lpText, INT Width, INT Format); INT
AddItem(INT ItemIndex, INT IconIndex, LPCWSTR lpText, LPARAM lParam);
void DeleteColumn(INT Index); HIMAGELIST
GetImageList(int iImageList);
INT AddItem(INT ItemIndex, INT IconIndex, LPCWSTR lpText, LPARAM lParam); static INT CALLBACK
s_CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
HIMAGELIST GetImageList(int iImageList); INT
CompareFunc(LPARAM lParam1, LPARAM lParam2, INT iSubItem);
static INT CALLBACK s_CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); HWND
Create(HWND hwndParent);
INT CompareFunc(LPARAM lParam1, LPARAM lParam2, INT iSubItem); BOOL
GetCheckState(INT item);
VOID
SetCheckState(INT item, BOOL fCheck);
VOID
CheckAll();
HWND Create(HWND hwndParent); PVOID
GetFocusedItemData();
BOOL GetCheckState(INT item); BOOL
SetDisplayAppType(APPLICATION_VIEW_TYPE AppType);
BOOL
SetViewMode(DWORD ViewMode);
VOID SetCheckState(INT item, BOOL fCheck); BOOL
AddApplication(CApplicationInfo *AppInfo, BOOL InitialCheckState);
VOID CheckAll();
PVOID GetFocusedItemData();
BOOL SetDisplayAppType(APPLICATION_VIEW_TYPE AppType);
BOOL SetViewMode(DWORD ViewMode);
BOOL AddInstalledApplication(CInstalledApplicationInfo *InstAppInfo, LPVOID CallbackParam);
BOOL AddAvailableApplication(CAvailableApplicationInfo *AvlbAppInfo, BOOL InitCheckState, LPVOID CallbackParam);
// this function is called when parent window receiving an notification about checkstate changing // this function is called when parent window receiving an notification about checkstate changing
VOID ItemCheckStateNotify(int iItem, BOOL bCheck); VOID
ItemCheckStateNotify(int iItem, BOOL bCheck);
}; };
class CMainToolbar : class CMainToolbar : public CUiWindow<CToolbar<>>
public CUiWindow< CToolbar<> >
{ {
const INT m_iToolbarHeight; const INT m_iToolbarHeight;
DWORD m_dButtonsWidthMax; DWORD m_dButtonsWidthMax;
@ -288,66 +282,73 @@ class CMainToolbar :
WCHAR szRefreshBtn[MAX_STR_LEN]; WCHAR szRefreshBtn[MAX_STR_LEN];
WCHAR szUpdateDbBtn[MAX_STR_LEN]; WCHAR szUpdateDbBtn[MAX_STR_LEN];
VOID AddImageToImageList(HIMAGELIST hImageList, UINT ImageIndex); VOID
AddImageToImageList(HIMAGELIST hImageList, UINT ImageIndex);
HIMAGELIST InitImageList(); HIMAGELIST
InitImageList();
public:
public:
CMainToolbar(); CMainToolbar();
VOID OnGetDispInfo(LPTOOLTIPTEXT lpttt); VOID
OnGetDispInfo(LPTOOLTIPTEXT lpttt);
HWND Create(HWND hwndParent); HWND
Create(HWND hwndParent);
VOID HideButtonCaption(); VOID
HideButtonCaption();
VOID
ShowButtonCaption();
VOID ShowButtonCaption(); DWORD
GetMaxButtonsWidth() const;
DWORD GetMaxButtonsWidth() const;
}; };
class CSearchBar : class CSearchBar : public CWindow
public CWindow
{ {
public: public:
const INT m_Width; const INT m_Width;
const INT m_Height; const INT m_Height;
CSearchBar(); CSearchBar();
VOID SetText(LPCWSTR lpszText); VOID
SetText(LPCWSTR lpszText);
HWND Create(HWND hwndParent);
HWND
Create(HWND hwndParent);
}; };
class CComboBox : class CComboBox : public CWindow
public CWindow
{ {
// ID refers to different types of view // ID refers to different types of view
enum enum
{ m_AppDisplayTypeDetails, m_AppDisplayTypeList, m_AppDisplayTypeTile }; {
m_AppDisplayTypeDetails,
m_AppDisplayTypeList,
m_AppDisplayTypeTile
};
// string ID for different. this should correspond with the enum above. // string ID for different. this should correspond with the enum above.
const UINT m_TypeStringID[3] = const UINT m_TypeStringID[3] = {IDS_APP_DISPLAY_DETAILS, IDS_APP_DISPLAY_LIST, IDS_APP_DISPLAY_TILE};
{ IDS_APP_DISPLAY_DETAILS, IDS_APP_DISPLAY_LIST, IDS_APP_DISPLAY_TILE };
const int m_DefaultSelectType = m_AppDisplayTypeDetails; const int m_DefaultSelectType = m_AppDisplayTypeDetails;
public:
public:
int m_Width; int m_Width;
int m_Height; int m_Height;
CComboBox(); CComboBox();
HWND Create(HWND hwndParent); HWND
Create(HWND hwndParent);
}; };
class CApplicationView : class CApplicationView : public CUiWindow<CWindowImpl<CApplicationView>>
public CUiWindow<CWindowImpl<CApplicationView>>
{ {
private: private:
CUiPanel *m_Panel = NULL; CUiPanel *m_Panel = NULL;
CMainToolbar *m_Toolbar = NULL; CMainToolbar *m_Toolbar = NULL;
CUiWindow<CComboBox> *m_ComboBox = NULL; CUiWindow<CComboBox> *m_ComboBox = NULL;
@ -356,47 +357,66 @@ private:
CAppInfoDisplay *m_AppsInfo = NULL; CAppInfoDisplay *m_AppsInfo = NULL;
CUiSplitPanel *m_HSplitter = NULL; CUiSplitPanel *m_HSplitter = NULL;
CMainWindow *m_MainWindow = NULL; CMainWindow *m_MainWindow = NULL;
APPLICATION_VIEW_TYPE ApplicationViewType = AppViewTypeEmpty; APPLICATION_VIEW_TYPE ApplicationViewType = AppViewTypeAvailableApps;
BOOL ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId); BOOL
ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
BOOL CreateToolbar(); BOOL
BOOL CreateSearchBar(); CreateToolbar();
BOOL CreateComboBox(); BOOL
BOOL CreateHSplitter(); CreateSearchBar();
BOOL CreateListView(); BOOL
BOOL CreateAppInfoDisplay(); CreateComboBox();
BOOL
CreateHSplitter();
BOOL
CreateListView();
BOOL
CreateAppInfoDisplay();
VOID OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam); VOID
VOID OnCommand(WPARAM wParam, LPARAM lParam); OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam);
public: VOID
OnCommand(WPARAM wParam, LPARAM lParam);
public:
CApplicationView(CMainWindow *MainWindow); CApplicationView(CMainWindow *MainWindow);
~CApplicationView(); ~CApplicationView();
static ATL::CWndClassInfo &GetWndClassInfo(); static ATL::CWndClassInfo &
GetWndClassInfo();
HWND Create(HWND hwndParent); HWND
void SetRedraw(BOOL bRedraw); Create(HWND hwndParent);
void SetFocusOnSearchBar(); void
BOOL SetDisplayAppType(APPLICATION_VIEW_TYPE AppType); SetRedraw(BOOL bRedraw);
void
SetFocusOnSearchBar();
BOOL
SetDisplayAppType(APPLICATION_VIEW_TYPE AppType);
BOOL AddInstalledApplication(CInstalledApplicationInfo *InstAppInfo, LPVOID param); BOOL
BOOL AddAvailableApplication(CAvailableApplicationInfo *AvlbAppInfo, BOOL InitCheckState, LPVOID param); AddApplication(CApplicationInfo *InstAppInfo, BOOL InitialCheckState);
VOID SetWatermark(const CStringW& Text); VOID
SetWatermark(const CStringW &Text);
void
void CheckAll(); CheckAll();
PVOID GetFocusedItemData(); PVOID
int GetItemCount(); GetFocusedItemData();
VOID AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> &TabOrderList); int
GetItemCount();
VOID
AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> &TabOrderList);
// this function is called when a item of listview get focus. // this function is called when a item of listview get focus.
// CallbackParam is the param passed to listview when adding the item (the one getting focus now). // CallbackParam is the param passed to listview when adding the item (the one getting focus now).
BOOL ItemGetFocus(LPVOID CallbackParam); VOID
ItemGetFocus(LPVOID CallbackParam);
// this function is called when a item of listview is checked/unchecked // this function is called when a item of listview is checked/unchecked
// CallbackParam is the param passed to listview when adding the item (the one getting focus now). // CallbackParam is the param passed to listview when adding the item (the one getting focus now).
BOOL ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam); VOID
ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam);
}; };

View file

@ -1,132 +0,0 @@
#pragma once
#include <windef.h>
#include <atlstr.h>
#include <atlsimpcoll.h>
#include <atlcoll.h>
#include "misc.h"
#include "configparser.h"
#define MAX_SCRNSHOT_NUM 16
enum LicenseType
{
LICENSE_NONE,
LICENSE_OPENSOURCE,
LICENSE_FREEWARE,
LICENSE_TRIAL,
LICENSE_MIN = LICENSE_NONE,
LICENSE_MAX = LICENSE_TRIAL
};
inline BOOL IsLicenseType(INT x)
{
return (x >= LICENSE_MIN && x <= LICENSE_MAX);
}
struct AvailableStrings
{
ATL::CStringW szPath;
ATL::CStringW szCabPath;
ATL::CStringW szAppsPath;
ATL::CStringW szSearchPath;
ATL::CStringW szCabName;
ATL::CStringW szCabDir;
AvailableStrings();
};
class CAvailableApplicationInfo
{
public:
INT m_Category;
//BOOL m_IsSelected;
LicenseType m_LicenseType;
ATL::CStringW m_szName; // software's display name.
ATL::CStringW m_szRegName;
ATL::CStringW m_szVersion;
ATL::CStringW m_szLicense;
ATL::CStringW m_szDesc;
ATL::CStringW m_szSize;
ATL::CStringW m_szUrlSite;
ATL::CStringW m_szUrlDownload;
ATL::CSimpleArray<LCID> m_LanguageLCIDs;
ATL::CSimpleArray<ATL::CStringW> m_szScrnshotLocation;
ATL::CStringW m_szIconLocation;
ATL::CStringW m_szPkgName; // software's package name.
ULONG m_SizeBytes;
// Caching mechanism related entries
ATL::CStringW m_sFileName;
FILETIME m_ftCacheStamp;
// Optional integrity checks (SHA-1 digests are 160 bit = 40 characters in hex string form)
ATL::CStringW m_szSHA1;
ATL::CStringW m_szInstalledVersion;
// Create an object from file
CAvailableApplicationInfo(const ATL::CStringW& sFileNameParam, AvailableStrings& m_Strings);
// Load all info from the file
VOID RefreshAppInfo(AvailableStrings& m_Strings);
BOOL HasLanguageInfo() const;
BOOL HasNativeLanguage() const;
BOOL HasEnglishLanguage() const;
BOOL IsInstalled() const;
BOOL HasInstalledVersion() const;
BOOL HasUpdate() const;
BOOL RetrieveScrnshot(UINT Index, ATL::CStringW& ScrnshotLocation) const;
BOOL RetrieveIcon(ATL::CStringW& IconLocation) const;
// Set a timestamp
VOID SetLastWriteTime(FILETIME* ftTime);
private:
BOOL m_IsInstalled;
BOOL m_HasLanguageInfo;
BOOL m_HasInstalledVersion;
CConfigParser* m_Parser;
inline BOOL GetString(LPCWSTR lpKeyName, ATL::CStringW& ReturnedString);
// Lazily load general info from the file
VOID RetrieveGeneralInfo(AvailableStrings& m_Strings);
VOID RetrieveInstalledStatus();
VOID RetrieveInstalledVersion();
VOID RetrieveLanguages();
VOID RetrieveLicenseType();
VOID RetrieveSize();
inline BOOL FindInLanguages(LCID what) const;
};
typedef BOOL(CALLBACK *AVAILENUMPROC)(CAvailableApplicationInfo *Info, BOOL bInitialCheckState, PVOID param);
class CAvailableApps
{
ATL::CAtlList<CAvailableApplicationInfo*> m_InfoList;
ATL::CAtlList< CAvailableApplicationInfo*> m_SelectedList;
public:
static AvailableStrings m_Strings;
CAvailableApps();
static BOOL UpdateAppsDB();
static BOOL ForceUpdateAppsDB();
static VOID DeleteCurrentAppsDB();
VOID FreeCachedEntries();
BOOL Enum(INT EnumType, AVAILENUMPROC lpEnumProc, PVOID param);
BOOL AddSelected(CAvailableApplicationInfo *AvlbInfo);
BOOL RemoveSelected(CAvailableApplicationInfo *AvlbInfo);
VOID RemoveAllSelected();
int GetSelectedCount();
CAvailableApplicationInfo* FindAppByPkgName(const ATL::CStringW& szPkgName) const;
ATL::CSimpleArray<CAvailableApplicationInfo> FindAppsByPkgNameList(const ATL::CSimpleArray<ATL::CStringW> &arrAppsNames) const;
//ATL::CSimpleArray<CAvailableApplicationInfo> GetSelected() const;
};

View file

@ -5,16 +5,19 @@
class CConfigParser class CConfigParser
{ {
const ATL::CStringW szConfigPath; const CStringW szConfigPath;
CSimpleMap<CStringW, CStringW> m_Keys; CSimpleMap<CStringW, CStringW> m_Keys;
void CacheINI(); void
void ReadSection(ATL::CStringW& Buffer, const ATL::CStringW& Section, BOOL isArch); CacheINI();
void
ReadSection(CStringW &Buffer, const CStringW &Section, BOOL isArch);
public: public:
CConfigParser(const ATL::CStringW& FileName); CConfigParser(const CStringW &FileName);
BOOL GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString); BOOL
BOOL GetInt(const ATL::CStringW& KeyName, INT& iResult); GetString(const CStringW &KeyName, CStringW &ResultString);
BOOL
GetInt(const CStringW &KeyName, INT &iResult);
}; };

View file

@ -1,12 +1,12 @@
#pragma once #pragma once
#include <ui/rosctrls.h> #include <ui/rosctrls.h>
class CRichEdit : class CRichEdit : public CWindow
public CWindow
{ {
HMODULE m_LoadedLibrary; HMODULE m_LoadedLibrary;
VOID GenericInsertText(LPCWSTR lpszText, SIZE_T InsertedTextLen, DWORD dwEffects) VOID
GenericInsertText(LPCWSTR lpszText, SIZE_T InsertedTextLen, DWORD dwEffects)
{ {
SETTEXTEX SetText; SETTEXTEX SetText;
SIZE_T Len = GetTextLen(); SIZE_T Len = GetTextLen();
@ -17,7 +17,7 @@ class CRichEdit :
SetText.flags = ST_SELECTION; SetText.flags = ST_SELECTION;
SetText.codepage = 1200; SetText.codepage = 1200;
SendMessageW(EM_SETTEXTEX, (WPARAM) &SetText, (LPARAM) lpszText); SendMessageW(EM_SETTEXTEX, (WPARAM)&SetText, (LPARAM)lpszText);
if ((dwEffects == CFM_LINK) && !PathIsURLW(lpszText)) if ((dwEffects == CFM_LINK) && !PathIsURLW(lpszText))
{ {
@ -31,10 +31,13 @@ class CRichEdit :
} }
} }
public: public:
CRichEdit() : CWindow(), m_LoadedLibrary(NULL) {} CRichEdit() : CWindow(), m_LoadedLibrary(NULL)
{
}
VOID SetRangeFormatting(SIZE_T Start, SIZE_T End, DWORD dwEffects) VOID
SetRangeFormatting(SIZE_T Start, SIZE_T End, DWORD dwEffects)
{ {
CHARFORMAT2W CharFormat; CHARFORMAT2W CharFormat;
@ -46,71 +49,70 @@ public:
CharFormat.dwMask = dwEffects; CharFormat.dwMask = dwEffects;
CharFormat.dwEffects = dwEffects; CharFormat.dwEffects = dwEffects;
SendMessageW(EM_SETCHARFORMAT, SCF_WORD | SCF_SELECTION, (LPARAM) &CharFormat); SendMessageW(EM_SETCHARFORMAT, SCF_WORD | SCF_SELECTION, (LPARAM)&CharFormat);
SendMessageW(EM_SETSEL, End, End + 1); SendMessageW(EM_SETSEL, End, End + 1);
} }
LONG GetTextLen() LONG
GetTextLen()
{ {
GETTEXTLENGTHEX TxtLenStruct; GETTEXTLENGTHEX TxtLenStruct;
TxtLenStruct.flags = GTL_NUMCHARS; TxtLenStruct.flags = GTL_NUMCHARS;
TxtLenStruct.codepage = 1200; TxtLenStruct.codepage = 1200;
return (LONG) SendMessageW(EM_GETTEXTLENGTHEX, (WPARAM) &TxtLenStruct, 0); return (LONG)SendMessageW(EM_GETTEXTLENGTHEX, (WPARAM)&TxtLenStruct, 0);
} }
/* /*
* Insert text (without cleaning old text) * Insert text (without cleaning old text)
* Supported effects: * Supported effects:
* - CFM_BOLD * - CFM_BOLD
* - CFM_ITALIC * - CFM_ITALIC
* - CFM_UNDERLINE * - CFM_UNDERLINE
* - CFM_LINK * - CFM_LINK
*/ */
VOID InsertText(LPCWSTR lpszText, DWORD dwEffects) VOID
InsertText(LPCWSTR lpszText, DWORD dwEffects)
{ {
GenericInsertText(lpszText, wcslen(lpszText), dwEffects); GenericInsertText(lpszText, wcslen(lpszText), dwEffects);
} }
VOID InsertText(const ATL::CStringW& szText, DWORD dwEffects) VOID
InsertText(const CStringW &szText, DWORD dwEffects)
{ {
GenericInsertText(szText.GetString(), szText.GetLength(), dwEffects); GenericInsertText(szText.GetString(), szText.GetLength(), dwEffects);
} }
/* /*
* Clear old text and add new * Clear old text and add new
*/ */
VOID SetText(LPCWSTR lpszText, DWORD dwEffects) VOID
SetText(LPCWSTR lpszText, DWORD dwEffects)
{ {
SetWindowTextW(L""); SetWindowTextW(L"");
InsertText(lpszText, dwEffects); InsertText(lpszText, dwEffects);
} }
VOID SetText(const ATL::CStringW& szText, DWORD dwEffects) VOID
SetText(const CStringW &szText, DWORD dwEffects)
{ {
SetText(szText.GetString(), dwEffects); SetText(szText.GetString(), dwEffects);
} }
HWND Create(HWND hwndParent) HWND
Create(HWND hwndParent)
{ {
m_LoadedLibrary = LoadLibraryW(L"riched20.dll"); m_LoadedLibrary = LoadLibraryW(L"riched20.dll");
m_hWnd = CreateWindowExW(0, m_hWnd = CreateWindowExW(
L"RichEdit20W", 0, L"RichEdit20W", NULL, WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_LEFT | ES_READONLY, 205, 28, 465, 100,
NULL, hwndParent, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
WS_CHILD | WS_VISIBLE | ES_MULTILINE |
ES_LEFT | ES_READONLY,
205, 28, 465, 100,
hwndParent,
NULL,
_AtlBaseModule.GetModuleInstance(),
NULL);
if (m_hWnd) if (m_hWnd)
{ {
SendMessageW(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE)); SendMessageW(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
SendMessageW(WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); SendMessageW(WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0);
SendMessageW(EM_SETEVENTMASK, 0, ENM_LINK | ENM_MOUSEEVENTS); SendMessageW(EM_SETEVENTMASK, 0, ENM_LINK | ENM_MOUSEEVENTS);
SendMessageW(EM_SHOWSCROLLBAR, SB_VERT, TRUE); SendMessageW(EM_SHOWSCROLLBAR, SB_VERT, TRUE);
} }
@ -118,7 +120,8 @@ public:
return m_hWnd; return m_hWnd;
} }
virtual VOID OnLink(ENLINK *Link) virtual VOID
OnLink(ENLINK *Link)
{ {
} }
@ -129,5 +132,4 @@ public:
FreeLibrary(m_LoadedLibrary); FreeLibrary(m_LoadedLibrary);
} }
} }
}; };

View file

@ -31,43 +31,4 @@
#define APPLICATION_DATABASE_URL L"https://rapps.reactos.org/rappmgr2.cab" #define APPLICATION_DATABASE_URL L"https://rapps.reactos.org/rappmgr2.cab"
#define APPLICATION_DATABASE_NAME L"rappmgr2.cab" #define APPLICATION_DATABASE_NAME L"rappmgr2.cab"
#define MAX_STR_LEN 256 #define MAX_STR_LEN 256
enum AppsCategories
{
ENUM_ALL_AVAILABLE,
ENUM_CAT_AUDIO,
ENUM_CAT_VIDEO,
ENUM_CAT_GRAPHICS,
ENUM_CAT_GAMES,
ENUM_CAT_INTERNET,
ENUM_CAT_OFFICE,
ENUM_CAT_DEVEL,
ENUM_CAT_EDU,
ENUM_CAT_ENGINEER,
ENUM_CAT_FINANCE,
ENUM_CAT_SCIENCE,
ENUM_CAT_TOOLS,
ENUM_CAT_DRIVERS,
ENUM_CAT_LIBS,
ENUM_CAT_THEMES,
ENUM_CAT_OTHER,
ENUM_CAT_SELECTED,
ENUM_ALL_INSTALLED,
ENUM_INSTALLED_APPLICATIONS = 31,
ENUM_UPDATES = 32,
ENUM_INSTALLED_MIN = ENUM_ALL_INSTALLED,
ENUM_INSTALLED_MAX = ENUM_UPDATES,
ENUM_AVAILABLE_MIN = ENUM_ALL_AVAILABLE,
ENUM_AVAILABLE_MAX = ENUM_CAT_SELECTED,
};
inline BOOL IsAvailableEnum(INT x)
{
return (x >= ENUM_AVAILABLE_MIN && x <= ENUM_AVAILABLE_MAX);
}
inline BOOL IsInstalledEnum(INT x)
{
return (x >= ENUM_INSTALLED_MIN && x <= ENUM_INSTALLED_MAX);
}

View file

@ -1,17 +1,22 @@
#pragma once #pragma once
#include "available.h" #include "applicationinfo.h"
#include <windef.h> #include <windef.h>
#include <atlsimpcoll.h> #include <atlsimpcoll.h>
// Settings dialog (settingsdlg.cpp) // Settings dialog (settingsdlg.cpp)
VOID CreateSettingsDlg(HWND hwnd); VOID
CreateSettingsDlg(HWND hwnd);
//Main window // Main window
VOID MainWindowLoop(INT nShowCmd); VOID
MainWindowLoop(class CApplicationDB *db, INT nShowCmd);
// Download dialogs // Download dialogs
VOID DownloadApplicationsDB(LPCWSTR lpUrl, BOOL IsOfficial); VOID
BOOL DownloadApplication(CAvailableApplicationInfo* pAppInfo); DownloadApplicationsDB(LPCWSTR lpUrl, BOOL IsOfficial);
BOOL DownloadListOfApplications(const ATL::CSimpleArray<CAvailableApplicationInfo>& AppsList, BOOL bIsModal); BOOL
DownloadApplication(CApplicationInfo *pAppInfo);
BOOL
DownloadListOfApplications(const CAtlList<CApplicationInfo *> &AppsList, BOOL bIsModal);

View file

@ -22,29 +22,29 @@
#define SEARCH_TIMER_ID 'SR' #define SEARCH_TIMER_ID 'SR'
#define TREEVIEW_ICON_SIZE 24 #define TREEVIEW_ICON_SIZE 24
class CSideTreeView : public CUiWindow<CTreeView>
class CSideTreeView :
public CUiWindow<CTreeView>
{ {
HIMAGELIST hImageTreeView; HIMAGELIST hImageTreeView;
public: public:
CSideTreeView(); CSideTreeView();
HTREEITEM AddItem(HTREEITEM hParent, ATL::CStringW &Text, INT Image, INT SelectedImage, LPARAM lParam); HTREEITEM
AddItem(HTREEITEM hParent, CStringW &Text, INT Image, INT SelectedImage, LPARAM lParam);
HTREEITEM AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex); HTREEITEM
AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex);
HIMAGELIST SetImageList(); HIMAGELIST
SetImageList();
VOID DestroyImageList(); VOID
DestroyImageList();
~CSideTreeView(); ~CSideTreeView();
}; };
class CMainWindow : class CMainWindow : public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>
public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>
{ {
CUiPanel *m_ClientPanel = NULL; CUiPanel *m_ClientPanel = NULL;
CUiSplitPanel *m_VSplitter = NULL; CUiSplitPanel *m_VSplitter = NULL;
@ -54,75 +54,81 @@ class CMainWindow :
CApplicationView *m_ApplicationView = NULL; CApplicationView *m_ApplicationView = NULL;
CAvailableApps m_AvailableApps; CApplicationDB *m_Db;
CInstalledApps m_InstalledApps; CAtlList<CApplicationInfo *> m_Selected;
BOOL bUpdating = FALSE; BOOL bUpdating = FALSE;
ATL::CStringW szSearchPattern; CStringW szSearchPattern;
INT SelectedEnumType; AppsCategories SelectedEnumType;
public: public:
CMainWindow(); CMainWindow(CApplicationDB *db);
~CMainWindow(); ~CMainWindow();
private:
VOID InitCategoriesList(); private:
VOID
InitCategoriesList();
BOOL CreateStatusBar(); BOOL
BOOL CreateTreeView(); CreateStatusBar();
BOOL CreateApplicationView(); BOOL
BOOL CreateVSplitter(); CreateTreeView();
BOOL CreateLayout(); BOOL
CreateApplicationView();
BOOL
CreateVSplitter();
BOOL
CreateLayout();
VOID
LayoutCleanup();
BOOL
InitControls();
VOID LayoutCleanup(); VOID
OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam);
BOOL InitControls(); BOOL
RemoveSelectedAppFromRegistry();
BOOL
UninstallSelectedApp(BOOL bModify);
VOID OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam); BOOL
ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
VOID
ShowAboutDlg();
VOID
OnCommand(WPARAM wParam, LPARAM lParam);
VOID
UpdateStatusBarText();
BOOL RemoveSelectedAppFromRegistry(); VOID
UpdateApplicationsList(AppsCategories EnumType, BOOL bReload = FALSE);
VOID
AddApplicationsToView(CAtlList<CApplicationInfo *> &List);
BOOL UninstallSelectedApp(BOOL bModify); public:
static ATL::CWndClassInfo &
GetWndClassInfo();
BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId); HWND
Create();
BOOL IsSelectedNodeInstalled();
VOID ShowAboutDlg();
VOID OnCommand(WPARAM wParam, LPARAM lParam);
BOOL CALLBACK EnumInstalledAppProc(CInstalledApplicationInfo *Info);
BOOL CALLBACK EnumAvailableAppProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState);
static BOOL CALLBACK s_EnumInstalledAppProc(CInstalledApplicationInfo *Info, PVOID param);
static BOOL CALLBACK s_EnumAvailableAppProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState, PVOID param);
static BOOL CALLBACK s_EnumSelectedAppForDownloadProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState, PVOID param);
VOID UpdateStatusBarText();
VOID UpdateApplicationsList(INT EnumType);
public:
static ATL::CWndClassInfo &GetWndClassInfo();
HWND Create();
// this function is called when a item of application-view is checked/unchecked // this function is called when a item of application-view is checked/unchecked
// CallbackParam is the param passed to application-view when adding the item (the one getting focus now). // CallbackParam is the param passed to application-view when adding the item (the one getting focus now).
BOOL ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam); VOID
ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam);
// this function is called when application-view is asked to install an application // this function is called when application-view is asked to install an application
// if Info is not zero, this app should be installed. otherwise those checked apps should be installed // if Info is not zero, this app should be installed. otherwise those checked apps should be installed
BOOL InstallApplication(CAvailableApplicationInfo *Info); BOOL
InstallApplication(CApplicationInfo *Info);
// this function is called when search text is changed // this function is called when search text is changed
BOOL SearchTextChanged(ATL::CStringW &SearchText); BOOL
SearchTextChanged(CStringW &SearchText);
void HandleTabOrder(int direction); void
HandleTabOrder(int direction);
}; };
VOID MainWindowLoop(INT nShowCmd);

View file

@ -1,63 +0,0 @@
#pragma once
#include <windef.h>
#include <atlstr.h>
class CInstalledApplicationInfo
{
private:
BOOL m_IsUserKey;
REGSAM m_WowKey;
HKEY m_hSubKey;
CStringW m_szKeyName;
public:
CInstalledApplicationInfo(BOOL bIsUserKey, REGSAM RegWowKey, HKEY hKey, const CStringW& szKeyName);
~CInstalledApplicationInfo();
VOID EnsureDetailsLoaded();
BOOL GetApplicationRegString(LPCWSTR lpKeyName, ATL::CStringW& String);
BOOL GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue);
BOOL RetrieveIcon(ATL::CStringW& IconLocation);
BOOL UninstallApplication(BOOL bModify);
LSTATUS RemoveFromRegistry();
// 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;
};
typedef BOOL(CALLBACK *APPENUMPROC)(CInstalledApplicationInfo * Info, PVOID param);
class CInstalledApps
{
ATL::CAtlList<CInstalledApplicationInfo *> m_InfoList;
public:
BOOL Enum(INT EnumType, APPENUMPROC lpEnumProc, PVOID param);
VOID FreeCachedEntries();
};

View file

@ -17,32 +17,39 @@
#define CurrentArchitecture L"ppc" #define CurrentArchitecture L"ppc"
#endif #endif
VOID CopyTextToClipboard(LPCWSTR lpszText); VOID
VOID ShowPopupMenuEx(HWND hwnd, HWND hwndOwner, UINT MenuID, UINT DefaultItem); CopyTextToClipboard(LPCWSTR lpszText);
BOOL StartProcess(const ATL::CStringW &Path, BOOL Wait); VOID
BOOL GetStorageDirectory(ATL::CStringW &lpDirectory); ShowPopupMenuEx(HWND hwnd, HWND hwndOwner, UINT MenuID, UINT DefaultItem);
BOOL
StartProcess(const CStringW &Path, BOOL Wait);
BOOL
GetStorageDirectory(CStringW &lpDirectory);
VOID InitLogs(); VOID
VOID FreeLogs(); InitLogs();
BOOL WriteLogMessage(WORD wType, DWORD dwEventID, LPCWSTR lpMsg); VOID
BOOL GetInstalledVersion(ATL::CStringW *pszVersion, const ATL::CStringW &szRegName); FreeLogs();
BOOL
WriteLogMessage(WORD wType, DWORD dwEventID, LPCWSTR lpMsg);
BOOL
GetInstalledVersion(CStringW *pszVersion, const CStringW &szRegName);
BOOL ExtractFilesFromCab(const ATL::CStringW& szCabName, BOOL
const ATL::CStringW& szCabDir, ExtractFilesFromCab(const CStringW &szCabName, const CStringW &szCabDir, const CStringW &szOutputDir);
const ATL::CStringW& szOutputDir);
BOOL PathAppendNoDirEscapeW(LPWSTR pszPath, LPCWSTR pszMore); BOOL
IsSystem64Bit();
BOOL IsSystem64Bit(); INT
GetSystemColorDepth();
INT GetSystemColorDepth(); void
UnixTimeToFileTime(DWORD dwUnixTime, LPFILETIME pFileTime);
void UnixTimeToFileTime(DWORD dwUnixTime, LPFILETIME pFileTime); BOOL
SearchPatternMatch(LPCWSTR szHaystack, LPCWSTR szNeedle);
BOOL SearchPatternMatch(LPCWSTR szHaystack, LPCWSTR szNeedle); template <class T> class CLocalPtr : public CHeapPtr<T, CLocalAllocator>
template<class T>
class CLocalPtr : public CHeapPtr<T, CLocalAllocator>
{ {
}; };

View file

@ -2,14 +2,14 @@
#define _RAPPS_H #define _RAPPS_H
#if DBG && !defined(_DEBUG) #if DBG && !defined(_DEBUG)
#define _DEBUG // CORE-17505 #define _DEBUG // CORE-17505
#endif #endif
#include "defines.h" #include "defines.h"
#include "dialogs.h" #include "dialogs.h"
#include "installed.h" #include "applicationinfo.h"
#include "available.h" #include "applicationdb.h"
#include "misc.h" #include "misc.h"
#include "configparser.h" #include "configparser.h"

View file

@ -84,7 +84,6 @@
#define ID_RESETDB 561 #define ID_RESETDB 561
#define ID_CHECK_ALL 562 #define ID_CHECK_ALL 562
#define ID_SEARCH 563 #define ID_SEARCH 563
#define ID_TOOLBAR_INSTALL 564
/* Strings */ /* Strings */
#define IDS_APPTITLE 100 #define IDS_APPTITLE 100

View file

@ -9,13 +9,12 @@
#include <atlwin.h> #include <atlwin.h>
template<class T, INT GrowthRate = 10> template <class T, INT GrowthRate = 10> class CPointerArray
class CPointerArray
{ {
protected: protected:
HDPA m_hDpa; HDPA m_hDpa;
public: public:
CPointerArray() CPointerArray()
{ {
m_hDpa = DPA_Create(GrowthRate); m_hDpa = DPA_Create(GrowthRate);
@ -26,26 +25,30 @@ public:
DPA_DestroyCallback(m_hDpa, s_OnRemoveItem, this); DPA_DestroyCallback(m_hDpa, s_OnRemoveItem, this);
} }
private: private:
static INT CALLBACK s_OnRemoveItem(PVOID ptr, PVOID context) static INT CALLBACK
s_OnRemoveItem(PVOID ptr, PVOID context)
{ {
CPointerArray * self = (CPointerArray*) context; CPointerArray *self = (CPointerArray *)context;
return (INT) self->OnRemoveItem(reinterpret_cast<T*>(ptr)); return (INT)self->OnRemoveItem(reinterpret_cast<T *>(ptr));
} }
static INT CALLBACK s_OnCompareItems(PVOID p1, PVOID p2, LPARAM lParam) static INT CALLBACK
s_OnCompareItems(PVOID p1, PVOID p2, LPARAM lParam)
{ {
CPointerArray * self = (CPointerArray*) lParam; CPointerArray *self = (CPointerArray *)lParam;
return self->OnCompareItems(reinterpret_cast<T*>(p1), reinterpret_cast<T*>(p2)); return self->OnCompareItems(reinterpret_cast<T *>(p1), reinterpret_cast<T *>(p2));
} }
public: public:
virtual BOOL OnRemoveItem(T * ptr) virtual BOOL
OnRemoveItem(T *ptr)
{ {
return TRUE; return TRUE;
} }
virtual INT OnCompareItems(T * p1, T * p2) virtual INT
OnCompareItems(T *p1, T *p2)
{ {
INT_PTR t = (reinterpret_cast<INT_PTR>(p2) - reinterpret_cast<INT_PTR>(p1)); INT_PTR t = (reinterpret_cast<INT_PTR>(p2) - reinterpret_cast<INT_PTR>(p1));
if (t > 0) if (t > 0)
@ -55,38 +58,45 @@ public:
return 0; return 0;
} }
public: public:
INT GetCount() const INT
GetCount() const
{ {
return DPA_GetPtrCount(m_hDpa); return DPA_GetPtrCount(m_hDpa);
} }
T* Get(INT i) const T *
Get(INT i) const
{ {
return (T*) DPA_GetPtr(m_hDpa, i); return (T *)DPA_GetPtr(m_hDpa, i);
} }
BOOL Set(INT i, T* ptr) BOOL
Set(INT i, T *ptr)
{ {
return DPA_SetPtr(m_hDpa, i, ptr); return DPA_SetPtr(m_hDpa, i, ptr);
} }
INT Insert(INT at, T* ptr) INT
Insert(INT at, T *ptr)
{ {
return DPA_InsertPtr(m_hDpa, at, ptr); return DPA_InsertPtr(m_hDpa, at, ptr);
} }
INT Append(T* ptr) INT
Append(T *ptr)
{ {
return DPA_InsertPtr(m_hDpa, DA_LAST, ptr); return DPA_InsertPtr(m_hDpa, DA_LAST, ptr);
} }
INT IndexOf(T* ptr) const INT
IndexOf(T *ptr) const
{ {
return DPA_GetPtrIndex(m_hDpa, ptr); return DPA_GetPtrIndex(m_hDpa, ptr);
} }
BOOL Remove(T* ptr) BOOL
Remove(T *ptr)
{ {
INT i = IndexOf(ptr); INT i = IndexOf(ptr);
if (i < 0) if (i < 0)
@ -94,38 +104,41 @@ public:
return RemoveAt(i); return RemoveAt(i);
} }
BOOL RemoveAt(INT i) BOOL
RemoveAt(INT i)
{ {
PVOID ptr = DPA_DeletePtr(m_hDpa, i); PVOID ptr = DPA_DeletePtr(m_hDpa, i);
if (ptr != NULL) if (ptr != NULL)
{ {
OnRemoveItem(reinterpret_cast<T*>(ptr)); OnRemoveItem(reinterpret_cast<T *>(ptr));
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
BOOL Clear() BOOL
Clear()
{ {
DPA_EnumCallback(s_OnRemoveItem, this); DPA_EnumCallback(s_OnRemoveItem, this);
return DPA_DeleteAllPtrs(m_hDpa); return DPA_DeleteAllPtrs(m_hDpa);
} }
BOOL Sort() BOOL
Sort()
{ {
return DPA_Sort(m_hDpa, s_OnCompareItems, (LPARAM)this); return DPA_Sort(m_hDpa, s_OnCompareItems, (LPARAM)this);
} }
INT Search(T* item, INT iStart, UINT uFlags) INT
Search(T *item, INT iStart, UINT uFlags)
{ {
return DPA_Search(m_hDpa, item, 0, s_OnCompareItems, (LPARAM)this, 0); return DPA_Search(m_hDpa, item, 0, s_OnCompareItems, (LPARAM)this, 0);
} }
}; };
class CUiRect class CUiRect : public RECT
: public RECT
{ {
public: public:
CUiRect() CUiRect()
{ {
left = right = top = bottom = 0; left = right = top = bottom = 0;
@ -140,28 +153,25 @@ public:
} }
}; };
class CUiMargin class CUiMargin : public CUiRect
: public CUiRect
{ {
public: public:
CUiMargin() CUiMargin()
{ {
} }
CUiMargin(INT all) CUiMargin(INT all) : CUiRect(all, all, all, all)
: CUiRect(all, all, all, all)
{ {
} }
CUiMargin(INT horz, INT vert) CUiMargin(INT horz, INT vert) : CUiRect(horz, vert, horz, vert)
: CUiRect(horz, vert, horz, vert)
{ {
} }
}; };
class CUiMeasure class CUiMeasure
{ {
public: public:
enum MeasureType enum MeasureType
{ {
Type_FitContent = 0, Type_FitContent = 0,
@ -170,11 +180,11 @@ public:
Type_FitParent = 3 Type_FitParent = 3
}; };
private: private:
MeasureType m_Type; MeasureType m_Type;
INT m_Value; INT m_Value;
public: public:
CUiMeasure() CUiMeasure()
{ {
m_Type = Type_FitContent; m_Type = Type_FitContent;
@ -187,40 +197,45 @@ public:
m_Value = value; m_Value = value;
} }
INT ComputeMeasure(INT parent, INT content) INT
ComputeMeasure(INT parent, INT content)
{ {
switch (m_Type) switch (m_Type)
{ {
case Type_FitContent: case Type_FitContent:
return content; return content;
case Type_Fixed: case Type_Fixed:
return m_Value; return m_Value;
case Type_Percent: case Type_Percent:
return max(content, parent * m_Value / 100); return max(content, parent * m_Value / 100);
case Type_FitParent: case Type_FitParent:
return parent; return parent;
} }
return 0; return 0;
} }
public: public:
static CUiMeasure FitContent() static CUiMeasure
FitContent()
{ {
return CUiMeasure(Type_FitContent, 0); return CUiMeasure(Type_FitContent, 0);
} }
static CUiMeasure FitParent() static CUiMeasure
FitParent()
{ {
return CUiMeasure(Type_FitParent, 0); return CUiMeasure(Type_FitParent, 0);
} }
static CUiMeasure Fixed(INT pixels) static CUiMeasure
Fixed(INT pixels)
{ {
return CUiMeasure(Type_Fixed, pixels); return CUiMeasure(Type_Fixed, pixels);
} }
static CUiMeasure Percent(INT percent) static CUiMeasure
Percent(INT percent)
{ {
return CUiMeasure(Type_Percent, percent); return CUiMeasure(Type_Percent, percent);
} }
@ -236,20 +251,21 @@ enum CUiAlignment
class CUiBox class CUiBox
{ {
public: public:
CUiMargin m_Margin; CUiMargin m_Margin;
CUiAlignment m_HorizontalAlignment; CUiAlignment m_HorizontalAlignment;
CUiAlignment m_VerticalAlignment; CUiAlignment m_VerticalAlignment;
protected: protected:
CUiBox() CUiBox()
{ {
m_HorizontalAlignment = UiAlign_LeftTop; m_HorizontalAlignment = UiAlign_LeftTop;
m_VerticalAlignment = UiAlign_LeftTop; m_VerticalAlignment = UiAlign_LeftTop;
} }
virtual VOID ComputeRect(RECT parentRect, RECT currentRect, RECT* newRect) virtual VOID
ComputeRect(RECT parentRect, RECT currentRect, RECT *newRect)
{ {
parentRect.left += m_Margin.left; parentRect.left += m_Margin.left;
parentRect.right -= m_Margin.right; parentRect.right -= m_Margin.right;
@ -269,60 +285,62 @@ protected:
switch (m_HorizontalAlignment) switch (m_HorizontalAlignment)
{ {
case UiAlign_LeftTop: case UiAlign_LeftTop:
currentRect.right = currentRect.left + szCurrent.cx; currentRect.right = currentRect.left + szCurrent.cx;
break; break;
case UiAlign_Middle: case UiAlign_Middle:
currentRect.left = parentRect.left + (szParent.cx - szCurrent.cx) / 2; currentRect.left = parentRect.left + (szParent.cx - szCurrent.cx) / 2;
currentRect.right = currentRect.left + szCurrent.cx; currentRect.right = currentRect.left + szCurrent.cx;
break; break;
case UiAlign_RightBtm: case UiAlign_RightBtm:
currentRect.left = currentRect.right - szCurrent.cx; currentRect.left = currentRect.right - szCurrent.cx;
break; break;
default: default:
break; break;
} }
switch (m_VerticalAlignment) switch (m_VerticalAlignment)
{ {
case UiAlign_LeftTop: case UiAlign_LeftTop:
currentRect.bottom = currentRect.top + szCurrent.cy; currentRect.bottom = currentRect.top + szCurrent.cy;
break; break;
case UiAlign_Middle: case UiAlign_Middle:
currentRect.top = parentRect.top + (szParent.cy - szCurrent.cy) / 2; currentRect.top = parentRect.top + (szParent.cy - szCurrent.cy) / 2;
currentRect.bottom = currentRect.top + szCurrent.cy; currentRect.bottom = currentRect.top + szCurrent.cy;
break; break;
case UiAlign_RightBtm: case UiAlign_RightBtm:
currentRect.top = currentRect.bottom - szCurrent.cy; currentRect.top = currentRect.bottom - szCurrent.cy;
break; break;
default: default:
break; break;
} }
*newRect = currentRect; *newRect = currentRect;
} }
public:
public: virtual VOID
virtual VOID ComputeMinimalSize(SIZE* size) ComputeMinimalSize(SIZE *size)
{ {
// Override in subclass // Override in subclass
size->cx = max(size->cx, 0); size->cx = max(size->cx, 0);
size->cy = min(size->cy, 0); size->cy = min(size->cy, 0);
}; };
virtual VOID ComputeContentBounds(RECT* rect) virtual VOID
{ ComputeContentBounds(RECT *rect){
// Override in subclass // Override in subclass
}; };
virtual DWORD_PTR CountSizableChildren() virtual DWORD_PTR
CountSizableChildren()
{ {
// Override in subclass // Override in subclass
return 0; return 0;
}; };
virtual HDWP OnParentSize(RECT parentRect, HDWP hDwp) virtual HDWP
OnParentSize(RECT parentRect, HDWP hDwp)
{ {
// Override in subclass // Override in subclass
return NULL; return NULL;
@ -331,19 +349,25 @@ public:
class CUiPrimitive class CUiPrimitive
{ {
protected: protected:
CUiPrimitive * m_Parent; CUiPrimitive *m_Parent;
public: public:
virtual ~CUiPrimitive() {} virtual ~CUiPrimitive()
{
}
virtual CUiBox * AsBox() { return NULL; } virtual CUiBox *
AsBox()
{
return NULL;
}
}; };
class CUiCollection : class CUiCollection : public CPointerArray<CUiPrimitive>
public CPointerArray < CUiPrimitive >
{ {
virtual BOOL OnRemoveItem(CUiPrimitive * ptr) virtual BOOL
OnRemoveItem(CUiPrimitive *ptr)
{ {
delete ptr; delete ptr;
return TRUE; return TRUE;
@ -352,19 +376,20 @@ class CUiCollection :
class CUiContainer class CUiContainer
{ {
protected: protected:
CUiCollection m_Children; CUiCollection m_Children;
public: public:
CUiCollection& Children() { return m_Children; } CUiCollection &
Children()
{
return m_Children;
}
}; };
class CUiPanel : class CUiPanel : public CUiPrimitive, public CUiBox, public CUiContainer
public CUiPrimitive,
public CUiBox,
public CUiContainer
{ {
public: public:
CUiMeasure m_Width; CUiMeasure m_Width;
CUiMeasure m_Height; CUiMeasure m_Height;
@ -378,13 +403,18 @@ public:
{ {
} }
virtual CUiBox * AsBox() { return this; } virtual CUiBox *
AsBox()
{
return this;
}
virtual VOID ComputeMinimalSize(SIZE* size) virtual VOID
ComputeMinimalSize(SIZE *size)
{ {
for (INT i = 0; i < m_Children.GetCount(); i++) for (INT i = 0; i < m_Children.GetCount(); i++)
{ {
CUiBox * box = m_Children.Get(i)->AsBox(); CUiBox *box = m_Children.Get(i)->AsBox();
if (box) if (box)
{ {
box->ComputeMinimalSize(size); box->ComputeMinimalSize(size);
@ -392,11 +422,12 @@ public:
} }
}; };
virtual VOID ComputeContentBounds(RECT* rect) virtual VOID
ComputeContentBounds(RECT *rect)
{ {
for (INT i = 0; i < m_Children.GetCount(); i++) for (INT i = 0; i < m_Children.GetCount(); i++)
{ {
CUiBox * box = m_Children.Get(i)->AsBox(); CUiBox *box = m_Children.Get(i)->AsBox();
if (box) if (box)
{ {
box->ComputeContentBounds(rect); box->ComputeContentBounds(rect);
@ -404,12 +435,13 @@ public:
} }
}; };
virtual DWORD_PTR CountSizableChildren() virtual DWORD_PTR
CountSizableChildren()
{ {
INT count = 0; INT count = 0;
for (INT i = 0; i < m_Children.GetCount(); i++) for (INT i = 0; i < m_Children.GetCount(); i++)
{ {
CUiBox * box = m_Children.Get(i)->AsBox(); CUiBox *box = m_Children.Get(i)->AsBox();
if (box) if (box)
{ {
count += box->CountSizableChildren(); count += box->CountSizableChildren();
@ -418,7 +450,8 @@ public:
return count; return count;
} }
virtual HDWP OnParentSize(RECT parentRect, HDWP hDwp) virtual HDWP
OnParentSize(RECT parentRect, HDWP hDwp)
{ {
RECT rect = {0}; RECT rect = {0};
@ -435,7 +468,7 @@ public:
for (INT i = 0; i < m_Children.GetCount(); i++) for (INT i = 0; i < m_Children.GetCount(); i++)
{ {
CUiBox * box = m_Children.Get(i)->AsBox(); CUiBox *box = m_Children.Get(i)->AsBox();
if (box) if (box)
{ {
hDwp = box->OnParentSize(rect, hDwp); hDwp = box->OnParentSize(rect, hDwp);
@ -446,24 +479,30 @@ public:
} }
}; };
template<class T = CWindow> template <class T = CWindow> class CUiWindow : public CUiPrimitive, public CUiBox, public T
class CUiWindow :
public CUiPrimitive,
public CUiBox,
public T
{ {
public: public:
virtual CUiBox * AsBox() { return this; } virtual CUiBox *
AsBox()
{
return this;
}
HWND GetWindow() { return T::m_hWnd; } HWND
GetWindow()
{
return T::m_hWnd;
}
virtual VOID ComputeMinimalSize(SIZE* size) virtual VOID
ComputeMinimalSize(SIZE *size)
{ {
// TODO: Maybe use WM_GETMINMAXINFO? // TODO: Maybe use WM_GETMINMAXINFO?
return CUiBox::ComputeMinimalSize(size); return CUiBox::ComputeMinimalSize(size);
}; };
virtual VOID ComputeContentBounds(RECT* rect) virtual VOID
ComputeContentBounds(RECT *rect)
{ {
RECT r; RECT r;
::GetWindowRect(T::m_hWnd, &r); ::GetWindowRect(T::m_hWnd, &r);
@ -473,12 +512,14 @@ public:
rect->bottom = max(rect->bottom, r.bottom); rect->bottom = max(rect->bottom, r.bottom);
}; };
virtual DWORD_PTR CountSizableChildren() virtual DWORD_PTR
CountSizableChildren()
{ {
return 1; return 1;
}; };
virtual HDWP OnParentSize(RECT parentRect, HDWP hDwp) virtual HDWP
OnParentSize(RECT parentRect, HDWP hDwp)
{ {
RECT rect; RECT rect;
@ -488,16 +529,21 @@ public:
if (hDwp) if (hDwp)
{ {
return ::DeferWindowPos(hDwp, T::m_hWnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOZORDER); return ::DeferWindowPos(
hDwp, T::m_hWnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
} }
else else
{ {
T::SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOZORDER | SWP_DEFERERASE); T::SetWindowPos(
NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_DEFERERASE);
return NULL; return NULL;
} }
}; };
virtual VOID AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> & TabOrderList) virtual VOID
AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> &TabOrderList)
{ {
TabOrderList.Add(T::m_hWnd); TabOrderList.Add(T::m_hWnd);
return; return;
@ -511,7 +557,8 @@ public:
} }
} }
VOID GetWindowTextW(ATL::CStringW& szText) VOID
GetWindowTextW(CStringW &szText)
{ {
INT length = CWindow::GetWindowTextLengthW() + 1; INT length = CWindow::GetWindowTextLengthW() + 1;
CWindow::GetWindowTextW(szText.GetBuffer(length), length); CWindow::GetWindowTextW(szText.GetBuffer(length), length);
@ -519,15 +566,11 @@ public:
} }
}; };
class CUiSplitPanel : class CUiSplitPanel : public CUiPrimitive, public CUiBox, public CWindowImpl<CUiSplitPanel>
public CUiPrimitive,
public CUiBox,
public CWindowImpl<CUiSplitPanel>
{ {
static const INT THICKNESS = 4; static const INT THICKNESS = 4;
protected: protected:
HCURSOR m_hCursor; HCURSOR m_hCursor;
CUiPanel m_First; CUiPanel m_First;
@ -537,7 +580,7 @@ protected:
BOOL m_HasOldRect; BOOL m_HasOldRect;
public: public:
INT m_Pos; INT m_Pos;
BOOL m_Horizontal; BOOL m_Horizontal;
BOOL m_DynamicFirst; BOOL m_DynamicFirst;
@ -549,25 +592,41 @@ public:
CUiSplitPanel() CUiSplitPanel()
{ {
m_hCursor = NULL;
m_Width = CUiMeasure::FitParent(); m_Width = CUiMeasure::FitParent();
m_Height = CUiMeasure::FitParent(); m_Height = CUiMeasure::FitParent();
m_Pos = 100; m_Pos = 100;
m_Horizontal = FALSE;
m_MinFirst = 100; m_MinFirst = 100;
m_MinSecond = 100; m_MinSecond = 100;
m_DynamicFirst = FALSE; m_DynamicFirst = FALSE;
m_HasOldRect = FALSE; m_HasOldRect = FALSE;
memset(&m_LastRect, 0, sizeof(m_LastRect));
} }
virtual ~CUiSplitPanel() virtual ~CUiSplitPanel()
{ {
} }
virtual CUiBox * AsBox() { return this; } virtual CUiBox *
AsBox()
{
return this;
}
CUiCollection& First() { return m_First.Children(); } CUiCollection &
CUiCollection& Second() { return m_Second.Children(); } First()
{
return m_First.Children();
}
CUiCollection &
Second()
{
return m_Second.Children();
}
virtual VOID ComputeMinimalSize(SIZE* size) virtual VOID
ComputeMinimalSize(SIZE *size)
{ {
if (m_Horizontal) if (m_Horizontal)
size->cx = max(size->cx, THICKNESS); size->cx = max(size->cx, THICKNESS);
@ -577,7 +636,8 @@ public:
m_Second.ComputeMinimalSize(size); m_Second.ComputeMinimalSize(size);
}; };
virtual VOID ComputeContentBounds(RECT* rect) virtual VOID
ComputeContentBounds(RECT *rect)
{ {
RECT r; RECT r;
@ -592,7 +652,8 @@ public:
rect->bottom = max(rect->bottom, r.bottom); rect->bottom = max(rect->bottom, r.bottom);
}; };
virtual DWORD_PTR CountSizableChildren() virtual DWORD_PTR
CountSizableChildren()
{ {
INT count = 1; INT count = 1;
count += m_First.CountSizableChildren(); count += m_First.CountSizableChildren();
@ -600,7 +661,8 @@ public:
return count; return count;
}; };
virtual HDWP OnParentSize(RECT parentRect, HDWP hDwp) virtual HDWP
OnParentSize(RECT parentRect, HDWP hDwp)
{ {
RECT rect = {0}; RECT rect = {0};
@ -691,73 +753,72 @@ public:
if (hDwp) if (hDwp)
{ {
return DeferWindowPos(hDwp, NULL, return DeferWindowPos(
splitter.left, splitter.top, hDwp, NULL, splitter.left, splitter.top, splitter.right - splitter.left, splitter.bottom - splitter.top,
splitter.right - splitter.left, SWP_NOACTIVATE | SWP_NOZORDER);
splitter.bottom - splitter.top,
SWP_NOACTIVATE | SWP_NOZORDER);
} }
else else
{ {
SetWindowPos(NULL, SetWindowPos(
splitter.left, splitter.top, NULL, splitter.left, splitter.top, splitter.right - splitter.left, splitter.bottom - splitter.top,
splitter.right - splitter.left, SWP_NOACTIVATE | SWP_NOZORDER);
splitter.bottom - splitter.top,
SWP_NOACTIVATE | SWP_NOZORDER);
return NULL; return NULL;
} }
}; };
private: private:
BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT& theResult, DWORD dwMapId) BOOL
ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId)
{ {
theResult = 0; theResult = 0;
switch (Msg) switch (Msg)
{ {
case WM_SETCURSOR: case WM_SETCURSOR:
SetCursor(m_hCursor); SetCursor(m_hCursor);
theResult = TRUE; theResult = TRUE;
break; break;
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
SetCapture(); SetCapture();
break; break;
case WM_LBUTTONUP: case WM_LBUTTONUP:
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
if (GetCapture() == m_hWnd) if (GetCapture() == m_hWnd)
{ {
ReleaseCapture(); ReleaseCapture();
} }
break; break;
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
if (GetCapture() == m_hWnd) if (GetCapture() == m_hWnd)
{ {
POINT Point; POINT Point;
GetCursorPos(&Point); GetCursorPos(&Point);
::ScreenToClient(GetParent(), &Point); ::ScreenToClient(GetParent(), &Point);
if (m_Horizontal) if (m_Horizontal)
SetPos(Point.y); SetPos(Point.y);
else else
SetPos(Point.x); SetPos(Point.x);
} }
break; break;
default: default:
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
public: public:
INT GetPos() INT
GetPos()
{ {
return m_Pos; return m_Pos;
} }
VOID SetPos(INT NewPos) VOID
SetPos(INT NewPos)
{ {
RECT rcParent; RECT rcParent;
@ -792,15 +853,18 @@ public:
HDWP hdwp = NULL; HDWP hdwp = NULL;
hdwp = BeginDeferWindowPos(count); hdwp = BeginDeferWindowPos(count);
if (hdwp) hdwp = OnParentSize(m_LastRect, hdwp); if (hdwp)
if (hdwp) EndDeferWindowPos(hdwp); hdwp = OnParentSize(m_LastRect, hdwp);
if (hdwp)
EndDeferWindowPos(hdwp);
} }
public: public:
DECLARE_WND_CLASS_EX(_T("SplitterWindowClass"), CS_HREDRAW | CS_VREDRAW, COLOR_BTNFACE) DECLARE_WND_CLASS_EX(_T("SplitterWindowClass"), CS_HREDRAW | CS_VREDRAW, COLOR_BTNFACE)
/* Create splitter bar */ /* Create splitter bar */
HWND Create(HWND hwndParent) HWND
Create(HWND hwndParent)
{ {
if (m_Horizontal) if (m_Horizontal)
m_hCursor = LoadCursor(0, IDC_SIZENS); m_hCursor = LoadCursor(0, IDC_SIZENS);

View file

@ -1,371 +0,0 @@
/*
* 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 2021 Mark Jansen <mark.jansen@reactos.org>
*/
#include "rapps.h"
#include "installed.h"
#include "misc.h"
CInstalledApplicationInfo::CInstalledApplicationInfo(BOOL bIsUserKey, REGSAM RegWowKey, HKEY hKey, const CStringW& szKeyName)
: m_IsUserKey(bIsUserKey)
, m_WowKey(RegWowKey)
, m_hSubKey(hKey)
, m_szKeyName(szKeyName)
{
DWORD dwSize = 0;
bIsUpdate = (RegQueryValueExW(m_hSubKey, L"ParentKeyName", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS);
}
CInstalledApplicationInfo::~CInstalledApplicationInfo()
{
if (m_hSubKey)
{
CloseHandle(m_hSubKey);
m_hSubKey = NULL;
}
}
void CInstalledApplicationInfo::EnsureDetailsLoaded()
{
// Key not closed, so we have not loaded details yet
if (m_hSubKey)
{
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);
DWORD dwInstallTimeStamp;
SYSTEMTIME InstallLocalTime;
if (GetApplicationRegString(L"InstallDate", szInstallDate))
{
ZeroMemory(&InstallLocalTime, sizeof(InstallLocalTime));
// Check if we have 8 characters to parse the datetime.
// Maybe other formats exist as well?
szInstallDate = szInstallDate.Trim();
if (szInstallDate.GetLength() == 8)
{
InstallLocalTime.wYear = wcstol(szInstallDate.Left(4).GetString(), NULL, 10);
InstallLocalTime.wMonth = wcstol(szInstallDate.Mid(4, 2).GetString(), NULL, 10);
InstallLocalTime.wDay = wcstol(szInstallDate.Mid(6, 2).GetString(), NULL, 10);
}
}
// It might be a DWORD (Unix timestamp). try again.
else if (GetApplicationRegDword(L"InstallDate", &dwInstallTimeStamp))
{
FILETIME InstallFileTime;
SYSTEMTIME InstallSystemTime;
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, szInstallDate.GetBuffer(cchTimeStrLen), cchTimeStrLen);
szInstallDate.ReleaseBuffer();
GetApplicationRegString(L"InstallLocation", szInstallLocation);
GetApplicationRegString(L"InstallSource", szInstallSource);
DWORD dwWindowsInstaller = 0;
if (GetApplicationRegDword(L"WindowsInstaller", &dwWindowsInstaller) && dwWindowsInstaller)
{
// MSI has the same info in Uninstall / modify, so manually build it
szUninstallString.Format(L"msiexec /x%s", m_szKeyName.GetString());
}
else
{
GetApplicationRegString(L"UninstallString", szUninstallString);
}
DWORD dwNoModify = 0;
if (!GetApplicationRegDword(L"NoModify", &dwNoModify))
{
CStringW Tmp;
if (GetApplicationRegString(L"NoModify", Tmp))
{
dwNoModify = Tmp.GetLength() > 0 ? (Tmp[0] == '1') : 0;
}
else
{
dwNoModify = 0;
}
}
if (!dwNoModify)
{
if (dwWindowsInstaller)
{
szModifyPath.Format(L"msiexec /i%s", m_szKeyName.GetString());
}
else
{
GetApplicationRegString(L"ModifyPath", szModifyPath);
}
}
CloseHandle(m_hSubKey);
m_hSubKey = NULL;
}
}
BOOL CInstalledApplicationInfo::GetApplicationRegString(LPCWSTR lpKeyName, ATL::CStringW& String)
{
DWORD dwAllocated = 0, dwSize, dwType;
// retrieve the size of value first.
if (RegQueryValueExW(m_hSubKey, lpKeyName, NULL, &dwType, NULL, &dwAllocated) != ERROR_SUCCESS)
{
String.Empty();
return FALSE;
}
if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
{
String.Empty();
return FALSE;
}
// query the value
dwSize = dwAllocated;
LSTATUS Result =
RegQueryValueExW(m_hSubKey, lpKeyName, NULL, NULL, (LPBYTE)String.GetBuffer(dwAllocated / sizeof(WCHAR)), &dwSize);
dwSize = min(dwAllocated, dwSize);
// CString takes care of zero-terminating it
String.ReleaseBuffer();
if (Result != ERROR_SUCCESS)
{
String.Empty();
return FALSE;
}
if (dwType == REG_EXPAND_SZ)
{
CStringW Tmp;
DWORD dwLen = ExpandEnvironmentStringsW(String, NULL, 0);
if (dwLen > 0)
{
BOOL bSuccess = ExpandEnvironmentStringsW(String, Tmp.GetBuffer(dwLen), dwLen) == dwLen;
Tmp.ReleaseBuffer();
if (bSuccess)
{
String = Tmp;
}
else
{
String.Empty();
return FALSE;
}
}
}
return TRUE;
}
BOOL CInstalledApplicationInfo::GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue)
{
DWORD dwSize = sizeof(DWORD), dwType;
if (RegQueryValueExW(m_hSubKey,
lpKeyName,
NULL,
&dwType,
(LPBYTE)lpValue,
&dwSize) != ERROR_SUCCESS || dwType != REG_DWORD)
{
return FALSE;
}
return TRUE;
}
BOOL CInstalledApplicationInfo::RetrieveIcon(ATL::CStringW& IconLocation)
{
if (szDisplayIcon.IsEmpty())
{
return FALSE;
}
IconLocation = szDisplayIcon;
return TRUE;
}
BOOL CInstalledApplicationInfo::UninstallApplication(BOOL bModify)
{
if (!bModify)
WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_REMOVE, szDisplayName);
return StartProcess(bModify ? szModifyPath : szUninstallString, TRUE);
}
typedef LSTATUS (WINAPI *RegDeleteKeyExWProc)(HKEY, LPCWSTR, REGSAM, DWORD);
LSTATUS CInstalledApplicationInfo::RemoveFromRegistry()
{
ATL::CStringW szFullName = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + m_szKeyName;
HMODULE hMod = GetModuleHandleW(L"advapi32.dll");
RegDeleteKeyExWProc pRegDeleteKeyExW;
// TODO: if there are subkeys inside, simply RegDeleteKeyExW
// (or RegDeleteKeyW on Server 2003 SP0 and earlier) will fail
// we don't have RegDeleteTree for ReactOS now. (It's a WinVista API)
// write a function to delete all subkeys recursively to solve this
// or consider letting ReactOS having this API
/* Load RegDeleteKeyExW from advapi32.dll if available */
if (hMod)
{
pRegDeleteKeyExW = (RegDeleteKeyExWProc)GetProcAddress(hMod, "RegDeleteKeyExW");
if (pRegDeleteKeyExW)
{
/* Return it */
return pRegDeleteKeyExW(m_IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, szFullName, m_WowKey, 0);
}
}
/* Otherwise, return non-Ex function */
return RegDeleteKeyW(m_IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, szFullName);
}
BOOL CInstalledApps::Enum(INT EnumType, APPENUMPROC lpEnumProc, PVOID param)
{
FreeCachedEntries();
HKEY RootKeyEnum[3] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_LOCAL_MACHINE };
REGSAM RegSamEnum[3] = { KEY_WOW64_32KEY, KEY_WOW64_32KEY, KEY_WOW64_64KEY };
int LoopTime;
// test if the OS is 64 bit.
if (IsSystem64Bit())
{
// loop for all 3 combination.
// note that HKEY_CURRENT_USER\Software don't have a redirect
// https://docs.microsoft.com/en-us/windows/win32/winprog64/shared-registry-keys#redirected-shared-and-reflected-keys-under-wow64
LoopTime = 3;
}
else
{
// loop for 2 combination for KEY_WOW64_32KEY only
LoopTime = 2;
}
// loop for all combination
for (int i = 0; i < LoopTime; i++)
{
DWORD dwSize = MAX_PATH;
HKEY hKey, hSubKey;
LONG ItemIndex = 0;
ATL::CStringW szKeyName;
if (RegOpenKeyExW(RootKeyEnum[i],
L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
NULL,
KEY_READ | RegSamEnum[i],
&hKey) != ERROR_SUCCESS)
{
return FALSE;
}
while (1)
{
dwSize = MAX_PATH;
if (RegEnumKeyExW(hKey, ItemIndex, szKeyName.GetBuffer(MAX_PATH), &dwSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
{
break;
}
ItemIndex++;
szKeyName.ReleaseBuffer();
if (RegOpenKeyW(hKey, szKeyName, &hSubKey) == ERROR_SUCCESS)
{
DWORD dwValue = 0;
BOOL bIsSystemComponent = FALSE;
dwSize = sizeof(DWORD);
if (RegQueryValueExW(hSubKey, L"SystemComponent", NULL, NULL, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS)
{
bIsSystemComponent = (dwValue == 0x1);
}
// Ignore system components
if (bIsSystemComponent)
{
RegCloseKey(hSubKey);
continue;
}
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))
{
Info->GetApplicationRegString(L"DisplayIcon", Info->szDisplayIcon);
Info->GetApplicationRegString(L"DisplayVersion", Info->szDisplayVersion);
Info->GetApplicationRegString(L"Comments", Info->szComments);
bSuccess = TRUE;
}
if (bSuccess)
{
// add to InfoList.
m_InfoList.AddTail(Info);
// invoke callback
if (lpEnumProc)
{
if ((EnumType == ENUM_ALL_INSTALLED) || /* All components */
((EnumType == ENUM_INSTALLED_APPLICATIONS) && (!Info->bIsUpdate)) || /* Applications only */
((EnumType == ENUM_UPDATES) && (Info->bIsUpdate))) /* Updates only */
{
lpEnumProc(Info, param);
}
}
}
else
{
// destory object
delete Info;
}
}
}
szKeyName.ReleaseBuffer();
RegCloseKey(hKey);
}
return TRUE;
}
VOID CInstalledApps::FreeCachedEntries()
{
POSITION InfoListPosition = m_InfoList.GetHeadPosition();
/* loop and deallocate all the cached app infos in the list */
while (InfoListPosition)
{
CInstalledApplicationInfo *Info = m_InfoList.GetNext(InfoListPosition);
delete Info;
}
m_InfoList.RemoveAll();
}

View file

@ -3,14 +3,15 @@
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Various integrity check mechanisms * PURPOSE: Various integrity check mechanisms
* COPYRIGHT: Copyright Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com) * COPYRIGHT: Copyright Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
* Copyright Mark Jansen * Copyright 2016 Mark Jansen <mark.jansen@reactos.org>
*/ */
#include "rapps.h" #include "rapps.h"
#include <sha1.h> #include <sha1.h>
BOOL VerifyInteg(LPCWSTR lpSHA1Hash, LPCWSTR lpFileName) BOOL
VerifyInteg(LPCWSTR lpSHA1Hash, LPCWSTR lpFileName)
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
@ -48,7 +49,7 @@ BOOL VerifyInteg(LPCWSTR lpSHA1Hash, LPCWSTR lpFileName)
WCHAR buf[(sizeof(sha) * 2) + 1]; WCHAR buf[(sizeof(sha) * 2) + 1];
for (UINT i = 0; i < sizeof(sha); i++) for (UINT i = 0; i < sizeof(sha); i++)
swprintf(buf + 2 * i, L"%02x", ((unsigned char *) sha)[i]); swprintf(buf + 2 * i, L"%02x", ((unsigned char *)sha)[i]);
/* does the resulting SHA1 match with the provided one? */ /* does the resulting SHA1 match with the provided one? */
if (!_wcsicmp(buf, lpSHA1Hash)) if (!_wcsicmp(buf, lpSHA1Hash))
ret = TRUE; ret = TRUE;

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,8 @@ static HANDLE hLog = NULL;
static BOOL bIsSys64ResultCached = FALSE; static BOOL bIsSys64ResultCached = FALSE;
static BOOL bIsSys64Result = FALSE; static BOOL bIsSys64Result = FALSE;
VOID CopyTextToClipboard(LPCWSTR lpszText) VOID
CopyTextToClipboard(LPCWSTR lpszText)
{ {
if (!OpenClipboard(NULL)) if (!OpenClipboard(NULL))
{ {
@ -31,7 +32,7 @@ VOID CopyTextToClipboard(LPCWSTR lpszText)
cchBuffer = wcslen(lpszText) + 1; cchBuffer = wcslen(lpszText) + 1;
ClipBuffer = GlobalAlloc(GMEM_DDESHARE, cchBuffer * sizeof(WCHAR)); ClipBuffer = GlobalAlloc(GMEM_DDESHARE, cchBuffer * sizeof(WCHAR));
Buffer = (PWCHAR) GlobalLock(ClipBuffer); Buffer = (PWCHAR)GlobalLock(ClipBuffer);
hr = StringCchCopyW(Buffer, cchBuffer, lpszText); hr = StringCchCopyW(Buffer, cchBuffer, lpszText);
GlobalUnlock(ClipBuffer); GlobalUnlock(ClipBuffer);
@ -41,7 +42,8 @@ VOID CopyTextToClipboard(LPCWSTR lpszText)
CloseClipboard(); CloseClipboard();
} }
VOID ShowPopupMenuEx(HWND hwnd, HWND hwndOwner, UINT MenuID, UINT DefaultItem) VOID
ShowPopupMenuEx(HWND hwnd, HWND hwndOwner, UINT MenuID, UINT DefaultItem)
{ {
HMENU hMenu = NULL; HMENU hMenu = NULL;
HMENU hPopupMenu; HMENU hPopupMenu;
@ -80,7 +82,8 @@ VOID ShowPopupMenuEx(HWND hwnd, HWND hwndOwner, UINT MenuID, UINT DefaultItem)
} }
} }
BOOL StartProcess(const ATL::CStringW& Path, BOOL Wait) BOOL
StartProcess(const CStringW &Path, BOOL Wait)
{ {
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
STARTUPINFOW si; STARTUPINFOW si;
@ -138,7 +141,8 @@ BOOL StartProcess(const ATL::CStringW& Path, BOOL Wait)
return TRUE; return TRUE;
} }
BOOL GetStorageDirectory(ATL::CStringW& Directory) BOOL
GetStorageDirectory(CStringW &Directory)
{ {
static CStringW CachedDirectory; static CStringW CachedDirectory;
static BOOL CachedDirectoryInitialized = FALSE; static BOOL CachedDirectoryInitialized = FALSE;
@ -172,7 +176,8 @@ BOOL GetStorageDirectory(ATL::CStringW& Directory)
return !Directory.IsEmpty(); return !Directory.IsEmpty();
} }
VOID InitLogs() VOID
InitLogs()
{ {
if (!SettingsInfo.bLogEnabled) if (!SettingsInfo.bLogEnabled)
{ {
@ -184,9 +189,10 @@ VOID InitLogs()
DWORD dwDisp, dwData; DWORD dwDisp, dwData;
ATL::CRegKey key; ATL::CRegKey key;
if (key.Create(HKEY_LOCAL_MACHINE, if (key.Create(
L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\ReactOS Application Manager", HKEY_LOCAL_MACHINE,
REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &dwDisp) != ERROR_SUCCESS) L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\ReactOS Application Manager", REG_NONE,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &dwDisp) != ERROR_SUCCESS)
{ {
return; return;
} }
@ -196,26 +202,20 @@ VOID InitLogs()
return; return;
} }
dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
EVENTLOG_INFORMATION_TYPE;
if ((key.SetStringValue(L"EventMessageFile", if ((key.SetStringValue(L"EventMessageFile", szPath, REG_EXPAND_SZ) == ERROR_SUCCESS) &&
szPath, (key.SetStringValue(L"CategoryMessageFile", szPath, REG_EXPAND_SZ) == ERROR_SUCCESS) &&
REG_EXPAND_SZ) == ERROR_SUCCESS) (key.SetDWORDValue(L"TypesSupported", dwData) == ERROR_SUCCESS) &&
&& (key.SetStringValue(L"CategoryMessageFile", (key.SetDWORDValue(L"CategoryCount", dwCategoryNum) == ERROR_SUCCESS))
szPath,
REG_EXPAND_SZ) == ERROR_SUCCESS)
&& (key.SetDWORDValue(L"TypesSupported",
dwData) == ERROR_SUCCESS)
&& (key.SetDWORDValue(L"CategoryCount",
dwCategoryNum) == ERROR_SUCCESS))
{ {
hLog = RegisterEventSourceW(NULL, L"ReactOS Application Manager"); hLog = RegisterEventSourceW(NULL, L"ReactOS Application Manager");
} }
} }
VOID FreeLogs() VOID
FreeLogs()
{ {
if (hLog) if (hLog)
{ {
@ -223,15 +223,15 @@ VOID FreeLogs()
} }
} }
BOOL WriteLogMessage(WORD wType, DWORD dwEventID, LPCWSTR lpMsg) BOOL
WriteLogMessage(WORD wType, DWORD dwEventID, LPCWSTR lpMsg)
{ {
if (!SettingsInfo.bLogEnabled) if (!SettingsInfo.bLogEnabled)
{ {
return TRUE; return TRUE;
} }
if (!ReportEventW(hLog, wType, 0, dwEventID, if (!ReportEventW(hLog, wType, 0, dwEventID, NULL, 1, 0, &lpMsg, NULL))
NULL, 1, 0, &lpMsg, NULL))
{ {
return FALSE; return FALSE;
} }
@ -239,19 +239,16 @@ BOOL WriteLogMessage(WORD wType, DWORD dwEventID, LPCWSTR lpMsg)
return TRUE; return TRUE;
} }
BOOL GetInstalledVersion_WowUser(ATL::CStringW* szVersionResult, BOOL
const ATL::CStringW& szRegName, GetInstalledVersion_WowUser(CStringW *szVersionResult, const CStringW &szRegName, BOOL IsUserKey, REGSAM keyWow)
BOOL IsUserKey,
REGSAM keyWow)
{ {
BOOL bHasSucceded = FALSE; BOOL bHasSucceded = FALSE;
ATL::CRegKey key; ATL::CRegKey key;
ATL::CStringW szVersion; CStringW szVersion;
ATL::CStringW szPath = ATL::CStringW(L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\") + szRegName; CStringW szPath = CStringW(L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\") + szRegName;
if (key.Open(IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, if (key.Open(IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, szPath.GetString(), keyWow | KEY_READ) !=
szPath.GetString(), ERROR_SUCCESS)
keyWow | KEY_READ) != ERROR_SUCCESS)
{ {
return FALSE; return FALSE;
} }
@ -260,9 +257,7 @@ BOOL GetInstalledVersion_WowUser(ATL::CStringW* szVersionResult,
{ {
ULONG dwSize = MAX_PATH * sizeof(WCHAR); ULONG dwSize = MAX_PATH * sizeof(WCHAR);
if (key.QueryStringValue(L"DisplayVersion", if (key.QueryStringValue(L"DisplayVersion", szVersion.GetBuffer(MAX_PATH), &dwSize) == ERROR_SUCCESS)
szVersion.GetBuffer(MAX_PATH),
&dwSize) == ERROR_SUCCESS)
{ {
szVersion.ReleaseBuffer(); szVersion.ReleaseBuffer();
*szVersionResult = szVersion; *szVersionResult = szVersion;
@ -276,67 +271,23 @@ BOOL GetInstalledVersion_WowUser(ATL::CStringW* szVersionResult,
else else
{ {
bHasSucceded = TRUE; bHasSucceded = TRUE;
szVersion.ReleaseBuffer();
} }
return bHasSucceded; return bHasSucceded;
} }
BOOL GetInstalledVersion(ATL::CStringW *pszVersion, const ATL::CStringW &szRegName) BOOL
GetInstalledVersion(CStringW *pszVersion, const CStringW &szRegName)
{ {
return (!szRegName.IsEmpty() return (
&& (GetInstalledVersion_WowUser(pszVersion, szRegName, TRUE, KEY_WOW64_32KEY) !szRegName.IsEmpty() && (GetInstalledVersion_WowUser(pszVersion, szRegName, TRUE, KEY_WOW64_32KEY) ||
|| GetInstalledVersion_WowUser(pszVersion, szRegName, FALSE, KEY_WOW64_32KEY) GetInstalledVersion_WowUser(pszVersion, szRegName, FALSE, KEY_WOW64_32KEY) ||
|| GetInstalledVersion_WowUser(pszVersion, szRegName, TRUE, KEY_WOW64_64KEY) GetInstalledVersion_WowUser(pszVersion, szRegName, TRUE, KEY_WOW64_64KEY) ||
|| GetInstalledVersion_WowUser(pszVersion, szRegName, FALSE, KEY_WOW64_64KEY))); GetInstalledVersion_WowUser(pszVersion, szRegName, FALSE, KEY_WOW64_64KEY)));
} }
BOOL PathAppendNoDirEscapeW(LPWSTR pszPath, LPCWSTR pszMore) BOOL
{ IsSystem64Bit()
WCHAR pszPathBuffer[MAX_PATH]; // buffer to store result
WCHAR pszPathCopy[MAX_PATH];
if (!PathCanonicalizeW(pszPathCopy, pszPath))
{
return FALSE;
}
PathRemoveBackslashW(pszPathCopy);
if (StringCchCopyW(pszPathBuffer, _countof(pszPathBuffer), pszPathCopy) != S_OK)
{
return FALSE;
}
if (!PathAppendW(pszPathBuffer, pszMore))
{
return FALSE;
}
size_t PathLen;
if (StringCchLengthW(pszPathCopy, _countof(pszPathCopy), &PathLen) != S_OK)
{
return FALSE;
}
int CommonPrefixLen = PathCommonPrefixW(pszPathCopy, pszPathBuffer, NULL);
if ((unsigned int)CommonPrefixLen != PathLen)
{
// pszPathBuffer should be a file/folder under pszPath.
// but now common prefix len is smaller than length of pszPathCopy
// hacking use ".." ?
return FALSE;
}
if (StringCchCopyW(pszPath, MAX_PATH, pszPathBuffer) != S_OK)
{
return FALSE;
}
return TRUE;
}
BOOL IsSystem64Bit()
{ {
if (bIsSys64ResultCached) if (bIsSys64ResultCached)
{ {
@ -345,12 +296,14 @@ BOOL IsSystem64Bit()
} }
SYSTEM_INFO si; SYSTEM_INFO si;
typedef void (WINAPI *LPFN_PGNSI)(LPSYSTEM_INFO); typedef void(WINAPI * LPFN_PGNSI)(LPSYSTEM_INFO);
LPFN_PGNSI pGetNativeSystemInfo = (LPFN_PGNSI)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetNativeSystemInfo"); LPFN_PGNSI pGetNativeSystemInfo =
(LPFN_PGNSI)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetNativeSystemInfo");
if (pGetNativeSystemInfo) if (pGetNativeSystemInfo)
{ {
pGetNativeSystemInfo(&si); pGetNativeSystemInfo(&si);
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
{ {
bIsSys64Result = TRUE; bIsSys64Result = TRUE;
} }
@ -364,7 +317,8 @@ BOOL IsSystem64Bit()
return bIsSys64Result; return bIsSys64Result;
} }
INT GetSystemColorDepth() INT
GetSystemColorDepth()
{ {
DEVMODEW pDevMode; DEVMODEW pDevMode;
INT ColorDepth; INT ColorDepth;
@ -380,18 +334,31 @@ INT GetSystemColorDepth()
switch (pDevMode.dmBitsPerPel) switch (pDevMode.dmBitsPerPel)
{ {
case 32: ColorDepth = ILC_COLOR32; break; case 32:
case 24: ColorDepth = ILC_COLOR24; break; ColorDepth = ILC_COLOR32;
case 16: ColorDepth = ILC_COLOR16; break; break;
case 8: ColorDepth = ILC_COLOR8; break; case 24:
case 4: ColorDepth = ILC_COLOR4; break; ColorDepth = ILC_COLOR24;
default: ColorDepth = ILC_COLOR; break; break;
case 16:
ColorDepth = ILC_COLOR16;
break;
case 8:
ColorDepth = ILC_COLOR8;
break;
case 4:
ColorDepth = ILC_COLOR4;
break;
default:
ColorDepth = ILC_COLOR;
break;
} }
return ColorDepth; return ColorDepth;
} }
void UnixTimeToFileTime(DWORD dwUnixTime, LPFILETIME pFileTime) void
UnixTimeToFileTime(DWORD dwUnixTime, LPFILETIME pFileTime)
{ {
// Note that LONGLONG is a 64-bit value // Note that LONGLONG is a 64-bit value
LONGLONG ll; LONGLONG ll;
@ -401,7 +368,8 @@ void UnixTimeToFileTime(DWORD dwUnixTime, LPFILETIME pFileTime)
pFileTime->dwHighDateTime = ll >> 32; pFileTime->dwHighDateTime = ll >> 32;
} }
BOOL SearchPatternMatch(LPCWSTR szHaystack, LPCWSTR szNeedle) BOOL
SearchPatternMatch(LPCWSTR szHaystack, LPCWSTR szNeedle)
{ {
if (!*szNeedle) if (!*szNeedle)
return TRUE; return TRUE;

View file

@ -11,25 +11,31 @@
class SettingsField class SettingsField
{ {
public: public:
virtual ~SettingsField() { ; } virtual ~SettingsField()
virtual BOOL Save(CRegKey &key) = 0; {
virtual BOOL Load(CRegKey &key) = 0; ;
}
virtual BOOL
Save(CRegKey &key) = 0;
virtual BOOL
Load(CRegKey &key) = 0;
}; };
class SettingsFieldBool : public SettingsField class SettingsFieldBool : public SettingsField
{ {
public: public:
SettingsFieldBool(BOOL *pValue, LPCWSTR szRegName) SettingsFieldBool(BOOL *pValue, LPCWSTR szRegName) : m_pValueStore(pValue), m_RegName(szRegName)
: m_pValueStore(pValue), m_RegName(szRegName)
{ {
} }
virtual BOOL Save(CRegKey &key) override virtual BOOL
Save(CRegKey &key) override
{ {
return key.SetDWORDValue(m_RegName, (DWORD)(*m_pValueStore)) == ERROR_SUCCESS; return key.SetDWORDValue(m_RegName, (DWORD)(*m_pValueStore)) == ERROR_SUCCESS;
} }
virtual BOOL Load(CRegKey &key) override virtual BOOL
Load(CRegKey &key) override
{ {
DWORD dwField; DWORD dwField;
LONG lResult = key.QueryDWORDValue(m_RegName, dwField); LONG lResult = key.QueryDWORDValue(m_RegName, dwField);
@ -41,24 +47,25 @@ public:
return TRUE; return TRUE;
} }
private: private:
BOOL *m_pValueStore; // where to read/store the value BOOL *m_pValueStore; // where to read/store the value
LPCWSTR m_RegName; // key name in registery LPCWSTR m_RegName; // key name in registery
}; };
class SettingsFieldInt : public SettingsField class SettingsFieldInt : public SettingsField
{ {
public: public:
SettingsFieldInt(INT *pValue, LPCWSTR szRegName) SettingsFieldInt(INT *pValue, LPCWSTR szRegName) : m_pValueStore(pValue), m_RegName(szRegName)
: m_pValueStore(pValue), m_RegName(szRegName)
{ {
} }
virtual BOOL Save(CRegKey &key) override virtual BOOL
Save(CRegKey &key) override
{ {
return key.SetDWORDValue(m_RegName, (DWORD)(*m_pValueStore)) == ERROR_SUCCESS; return key.SetDWORDValue(m_RegName, (DWORD)(*m_pValueStore)) == ERROR_SUCCESS;
} }
virtual BOOL Load(CRegKey &key) override virtual BOOL
Load(CRegKey &key) override
{ {
DWORD dwField; DWORD dwField;
LONG lResult = key.QueryDWORDValue(m_RegName, dwField); LONG lResult = key.QueryDWORDValue(m_RegName, dwField);
@ -70,38 +77,40 @@ public:
return TRUE; return TRUE;
} }
private: private:
INT *m_pValueStore; // where to read/store the value INT *m_pValueStore; // where to read/store the value
LPCWSTR m_RegName; // key name in registery LPCWSTR m_RegName; // key name in registery
}; };
class SettingsFieldString : public SettingsField class SettingsFieldString : public SettingsField
{ {
public: public:
SettingsFieldString(WCHAR *pString, ULONG cchLen, LPCWSTR szRegName) SettingsFieldString(WCHAR *pString, ULONG cchLen, LPCWSTR szRegName)
: m_pStringStore(pString), m_StringLen(cchLen), m_RegName(szRegName) : m_pStringStore(pString), m_StringLen(cchLen), m_RegName(szRegName)
{ {
} }
virtual BOOL Save(CRegKey &key) override virtual BOOL
Save(CRegKey &key) override
{ {
return key.SetStringValue(m_RegName, m_pStringStore) == ERROR_SUCCESS; return key.SetStringValue(m_RegName, m_pStringStore) == ERROR_SUCCESS;
} }
virtual BOOL Load(CRegKey &key) override virtual BOOL
Load(CRegKey &key) override
{ {
ULONG nChar = m_StringLen - 1; // make sure the terminating L'\0' ULONG nChar = m_StringLen - 1; // make sure the terminating L'\0'
LONG lResult = key.QueryStringValue(m_RegName, m_pStringStore, &nChar); LONG lResult = key.QueryStringValue(m_RegName, m_pStringStore, &nChar);
return lResult == ERROR_SUCCESS; return lResult == ERROR_SUCCESS;
} }
private: private:
WCHAR *m_pStringStore; // where to read/store the value WCHAR *m_pStringStore; // where to read/store the value
ULONG m_StringLen; // string length, in chars ULONG m_StringLen; // string length, in chars
LPCWSTR m_RegName; // key name in registery LPCWSTR m_RegName; // key name in registery
}; };
void
void AddInfoFields(ATL::CAtlList<SettingsField *> &infoFields, SETTINGS_INFO &settings) AddInfoFields(ATL::CAtlList<SettingsField *> &infoFields, SETTINGS_INFO &settings)
{ {
infoFields.AddTail(new SettingsFieldBool(&(settings.bSaveWndPos), L"bSaveWndPos")); infoFields.AddTail(new SettingsFieldBool(&(settings.bSaveWndPos), L"bSaveWndPos"));
infoFields.AddTail(new SettingsFieldBool(&(settings.bUpdateAtStart), L"bUpdateAtStart")); infoFields.AddTail(new SettingsFieldBool(&(settings.bUpdateAtStart), L"bUpdateAtStart"));
@ -122,7 +131,8 @@ void AddInfoFields(ATL::CAtlList<SettingsField *> &infoFields, SETTINGS_INFO &se
return; return;
} }
BOOL SaveAllSettings(CRegKey &key, SETTINGS_INFO &settings) BOOL
SaveAllSettings(CRegKey &key, SETTINGS_INFO &settings)
{ {
BOOL bAllSuccess = TRUE; BOOL bAllSuccess = TRUE;
ATL::CAtlList<SettingsField *> infoFields; ATL::CAtlList<SettingsField *> infoFields;
@ -143,7 +153,8 @@ BOOL SaveAllSettings(CRegKey &key, SETTINGS_INFO &settings)
return bAllSuccess; return bAllSuccess;
} }
BOOL LoadAllSettings(CRegKey &key, SETTINGS_INFO &settings) BOOL
LoadAllSettings(CRegKey &key, SETTINGS_INFO &settings)
{ {
BOOL bAllSuccess = TRUE; BOOL bAllSuccess = TRUE;
ATL::CAtlList<SettingsField *> infoFields; ATL::CAtlList<SettingsField *> infoFields;
@ -164,9 +175,10 @@ BOOL LoadAllSettings(CRegKey &key, SETTINGS_INFO &settings)
return bAllSuccess; return bAllSuccess;
} }
VOID FillDefaultSettings(PSETTINGS_INFO pSettingsInfo) VOID
FillDefaultSettings(PSETTINGS_INFO pSettingsInfo)
{ {
ATL::CStringW szDownloadDir; CStringW szDownloadDir;
ZeroMemory(pSettingsInfo, sizeof(SETTINGS_INFO)); ZeroMemory(pSettingsInfo, sizeof(SETTINGS_INFO));
pSettingsInfo->bSaveWndPos = TRUE; pSettingsInfo->bSaveWndPos = TRUE;
@ -190,9 +202,8 @@ VOID FillDefaultSettings(PSETTINGS_INFO pSettingsInfo)
PathAppendW(szDownloadDir.GetBuffer(MAX_PATH), L"\\RAPPS Downloads"); PathAppendW(szDownloadDir.GetBuffer(MAX_PATH), L"\\RAPPS Downloads");
szDownloadDir.ReleaseBuffer(); szDownloadDir.ReleaseBuffer();
ATL::CStringW::CopyChars(pSettingsInfo->szDownloadDir, CStringW::CopyChars(
_countof(pSettingsInfo->szDownloadDir), pSettingsInfo->szDownloadDir, _countof(pSettingsInfo->szDownloadDir), szDownloadDir.GetString(),
szDownloadDir.GetString(),
szDownloadDir.GetLength() + 1); szDownloadDir.GetLength() + 1);
pSettingsInfo->bDelInstaller = FALSE; pSettingsInfo->bDelInstaller = FALSE;
@ -203,7 +214,8 @@ VOID FillDefaultSettings(PSETTINGS_INFO pSettingsInfo)
pSettingsInfo->Height = 450; pSettingsInfo->Height = 450;
} }
BOOL LoadSettings(PSETTINGS_INFO pSettingsInfo) BOOL
LoadSettings(PSETTINGS_INFO pSettingsInfo)
{ {
ATL::CRegKey RegKey; ATL::CRegKey RegKey;
if (RegKey.Open(HKEY_CURRENT_USER, L"Software\\ReactOS\\rapps", KEY_READ) != ERROR_SUCCESS) if (RegKey.Open(HKEY_CURRENT_USER, L"Software\\ReactOS\\rapps", KEY_READ) != ERROR_SUCCESS)
@ -214,7 +226,8 @@ BOOL LoadSettings(PSETTINGS_INFO pSettingsInfo)
return LoadAllSettings(RegKey, *pSettingsInfo); return LoadAllSettings(RegKey, *pSettingsInfo);
} }
BOOL SaveSettings(HWND hwnd, PSETTINGS_INFO pSettingsInfo) BOOL
SaveSettings(HWND hwnd, PSETTINGS_INFO pSettingsInfo)
{ {
WINDOWPLACEMENT wp; WINDOWPLACEMENT wp;
ATL::CRegKey RegKey; ATL::CRegKey RegKey;
@ -228,13 +241,13 @@ BOOL SaveSettings(HWND hwnd, PSETTINGS_INFO pSettingsInfo)
pSettingsInfo->Top = wp.rcNormalPosition.top; pSettingsInfo->Top = wp.rcNormalPosition.top;
pSettingsInfo->Width = wp.rcNormalPosition.right - wp.rcNormalPosition.left; pSettingsInfo->Width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
pSettingsInfo->Height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; pSettingsInfo->Height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
pSettingsInfo->Maximized = (wp.showCmd == SW_MAXIMIZE pSettingsInfo->Maximized =
|| (wp.showCmd == SW_SHOWMINIMIZED (wp.showCmd == SW_MAXIMIZE || (wp.showCmd == SW_SHOWMINIMIZED && (wp.flags & WPF_RESTORETOMAXIMIZED)));
&& (wp.flags & WPF_RESTORETOMAXIMIZED)));
} }
if (RegKey.Create(HKEY_CURRENT_USER, L"Software\\ReactOS\\rapps", NULL, if (RegKey.Create(
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, NULL) != ERROR_SUCCESS) HKEY_CURRENT_USER, L"Software\\ReactOS\\rapps", NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, NULL) !=
ERROR_SUCCESS)
{ {
return FALSE; return FALSE;
} }

View file

@ -9,23 +9,25 @@
SETTINGS_INFO NewSettingsInfo; SETTINGS_INFO NewSettingsInfo;
BOOL ChooseFolder(HWND hwnd) BOOL
ChooseFolder(HWND hwnd)
{ {
BOOL bRet = FALSE; BOOL bRet = FALSE;
BROWSEINFOW bi; BROWSEINFOW bi;
ATL::CStringW szChooseFolderText; CStringW szChooseFolderText;
szChooseFolderText.LoadStringW(IDS_CHOOSE_FOLDER_TEXT); szChooseFolderText.LoadStringW(IDS_CHOOSE_FOLDER_TEXT);
ZeroMemory(&bi, sizeof(bi)); ZeroMemory(&bi, sizeof(bi));
bi.hwndOwner = hwnd; bi.hwndOwner = hwnd;
bi.pidlRoot = NULL; bi.pidlRoot = NULL;
bi.lpszTitle = szChooseFolderText.GetString(); bi.lpszTitle = szChooseFolderText;
bi.ulFlags = BIF_USENEWUI | BIF_DONTGOBELOWDOMAIN | BIF_RETURNONLYFSDIRS | /* BIF_BROWSEFILEJUNCTIONS | */ BIF_VALIDATE; bi.ulFlags =
BIF_USENEWUI | BIF_DONTGOBELOWDOMAIN | BIF_RETURNONLYFSDIRS | /* BIF_BROWSEFILEJUNCTIONS | */ BIF_VALIDATE;
if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
{ {
ATL::CStringW szBuf; CStringW szBuf;
LPITEMIDLIST lpItemList = SHBrowseForFolderW(&bi); LPITEMIDLIST lpItemList = SHBrowseForFolderW(&bi);
if (lpItemList && SHGetPathFromIDListW(lpItemList, szBuf.GetBuffer(MAX_PATH))) if (lpItemList && SHGetPathFromIDListW(lpItemList, szBuf.GetBuffer(MAX_PATH)))
@ -33,7 +35,7 @@ BOOL ChooseFolder(HWND hwnd)
szBuf.ReleaseBuffer(); szBuf.ReleaseBuffer();
if (!szBuf.IsEmpty()) if (!szBuf.IsEmpty())
{ {
SetDlgItemTextW(hwnd, IDC_DOWNLOAD_DIR_EDIT, szBuf.GetString()); SetDlgItemTextW(hwnd, IDC_DOWNLOAD_DIR_EDIT, szBuf);
bRet = TRUE; bRet = TRUE;
} }
} }
@ -49,25 +51,26 @@ BOOL ChooseFolder(HWND hwnd)
return bRet; return bRet;
} }
BOOL IsUrlValid(const WCHAR * Url) BOOL
IsUrlValid(const WCHAR *Url)
{ {
URL_COMPONENTSW UrlComponmentInfo = { 0 }; URL_COMPONENTSW UrlComponmentInfo = {0};
UrlComponmentInfo.dwStructSize = sizeof(UrlComponmentInfo); UrlComponmentInfo.dwStructSize = sizeof(UrlComponmentInfo);
UrlComponmentInfo.dwSchemeLength = 1; UrlComponmentInfo.dwSchemeLength = 1;
BOOL bSuccess = InternetCrackUrlW(Url, wcslen(Url), 0, &UrlComponmentInfo); BOOL bSuccess = InternetCrackUrlW(Url, wcslen(Url), 0, &UrlComponmentInfo);
if(!bSuccess) if (!bSuccess)
{ {
return FALSE; return FALSE;
} }
switch(UrlComponmentInfo.nScheme) switch (UrlComponmentInfo.nScheme)
{ {
case INTERNET_SCHEME_HTTP: case INTERNET_SCHEME_HTTP:
case INTERNET_SCHEME_HTTPS: case INTERNET_SCHEME_HTTPS:
case INTERNET_SCHEME_FTP: case INTERNET_SCHEME_FTP:
case INTERNET_SCHEME_FILE: case INTERNET_SCHEME_FILE:
// supported // supported
return TRUE; return TRUE;
default: default:
@ -77,47 +80,49 @@ BOOL IsUrlValid(const WCHAR * Url)
namespace namespace
{ {
inline BOOL IsCheckedDlgItem(HWND hDlg, INT nIDDlgItem) inline BOOL
IsCheckedDlgItem(HWND hDlg, INT nIDDlgItem)
{
return (SendDlgItemMessageW(hDlg, nIDDlgItem, BM_GETCHECK, 0, 0) == BST_CHECKED) ? TRUE : FALSE;
}
VOID
InitSettingsControls(HWND hDlg, PSETTINGS_INFO Info)
{
SendDlgItemMessageW(hDlg, IDC_SAVE_WINDOW_POS, BM_SETCHECK, Info->bSaveWndPos, 0);
SendDlgItemMessageW(hDlg, IDC_UPDATE_AVLIST, BM_SETCHECK, Info->bUpdateAtStart, 0);
SendDlgItemMessageW(hDlg, IDC_LOG_ENABLED, BM_SETCHECK, Info->bLogEnabled, 0);
SendDlgItemMessageW(hDlg, IDC_DEL_AFTER_INSTALL, BM_SETCHECK, Info->bDelInstaller, 0);
SetWindowTextW(GetDlgItem(hDlg, IDC_DOWNLOAD_DIR_EDIT), Info->szDownloadDir);
CheckRadioButton(hDlg, IDC_PROXY_DEFAULT, IDC_USE_PROXY, IDC_PROXY_DEFAULT + Info->Proxy);
if (Info->Proxy == 2)
{ {
return (SendDlgItemMessageW(hDlg, nIDDlgItem, BM_GETCHECK, 0, 0) == BST_CHECKED) ? TRUE : FALSE; EnableWindow(GetDlgItem(hDlg, IDC_PROXY_SERVER), TRUE);
EnableWindow(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), TRUE);
}
else
{
EnableWindow(GetDlgItem(hDlg, IDC_PROXY_SERVER), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), FALSE);
} }
VOID InitSettingsControls(HWND hDlg, PSETTINGS_INFO Info) CheckRadioButton(hDlg, IDC_SOURCE_DEFAULT, IDC_USE_SOURCE, Info->bUseSource ? IDC_USE_SOURCE : IDC_SOURCE_DEFAULT);
EnableWindow(GetDlgItem(hDlg, IDC_SOURCE_URL), Info->bUseSource);
SetWindowTextW(GetDlgItem(hDlg, IDC_SOURCE_URL), Info->szSourceURL);
SetWindowTextW(GetDlgItem(hDlg, IDC_PROXY_SERVER), Info->szProxyServer);
SetWindowTextW(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), Info->szNoProxyFor);
}
INT_PTR CALLBACK
SettingsDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{ {
SendDlgItemMessageW(hDlg, IDC_SAVE_WINDOW_POS, BM_SETCHECK, Info->bSaveWndPos, 0);
SendDlgItemMessageW(hDlg, IDC_UPDATE_AVLIST, BM_SETCHECK, Info->bUpdateAtStart, 0);
SendDlgItemMessageW(hDlg, IDC_LOG_ENABLED, BM_SETCHECK, Info->bLogEnabled, 0);
SendDlgItemMessageW(hDlg, IDC_DEL_AFTER_INSTALL, BM_SETCHECK, Info->bDelInstaller, 0);
SetWindowTextW(GetDlgItem(hDlg, IDC_DOWNLOAD_DIR_EDIT),
Info->szDownloadDir);
CheckRadioButton(hDlg, IDC_PROXY_DEFAULT, IDC_USE_PROXY, IDC_PROXY_DEFAULT + Info->Proxy);
if (Info->Proxy == 2)
{
EnableWindow(GetDlgItem(hDlg, IDC_PROXY_SERVER), TRUE);
EnableWindow(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), TRUE);
}
else
{
EnableWindow(GetDlgItem(hDlg, IDC_PROXY_SERVER), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), FALSE);
}
CheckRadioButton(hDlg, IDC_SOURCE_DEFAULT, IDC_USE_SOURCE, Info->bUseSource ? IDC_USE_SOURCE : IDC_SOURCE_DEFAULT);
EnableWindow(GetDlgItem(hDlg, IDC_SOURCE_URL), Info->bUseSource);
SetWindowTextW(GetDlgItem(hDlg, IDC_SOURCE_URL), Info->szSourceURL);
SetWindowTextW(GetDlgItem(hDlg, IDC_PROXY_SERVER), Info->szProxyServer);
SetWindowTextW(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), Info->szNoProxyFor);
}
INT_PTR CALLBACK SettingsDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_INITDIALOG: case WM_INITDIALOG:
{ {
NewSettingsInfo = SettingsInfo; NewSettingsInfo = SettingsInfo;
@ -129,159 +134,149 @@ namespace
{ {
switch (LOWORD(wParam)) switch (LOWORD(wParam))
{ {
case IDC_CHOOSE: case IDC_CHOOSE:
ChooseFolder(hDlg); ChooseFolder(hDlg);
break; break;
case IDC_SAVE_WINDOW_POS: case IDC_SAVE_WINDOW_POS:
NewSettingsInfo.bSaveWndPos = IsCheckedDlgItem(hDlg, IDC_SAVE_WINDOW_POS); NewSettingsInfo.bSaveWndPos = IsCheckedDlgItem(hDlg, IDC_SAVE_WINDOW_POS);
break; break;
case IDC_UPDATE_AVLIST: case IDC_UPDATE_AVLIST:
NewSettingsInfo.bUpdateAtStart = IsCheckedDlgItem(hDlg, IDC_UPDATE_AVLIST); NewSettingsInfo.bUpdateAtStart = IsCheckedDlgItem(hDlg, IDC_UPDATE_AVLIST);
break; break;
case IDC_LOG_ENABLED: case IDC_LOG_ENABLED:
NewSettingsInfo.bLogEnabled = IsCheckedDlgItem(hDlg, IDC_LOG_ENABLED); NewSettingsInfo.bLogEnabled = IsCheckedDlgItem(hDlg, IDC_LOG_ENABLED);
break; break;
case IDC_DEL_AFTER_INSTALL: case IDC_DEL_AFTER_INSTALL:
NewSettingsInfo.bDelInstaller = IsCheckedDlgItem(hDlg, IDC_DEL_AFTER_INSTALL); NewSettingsInfo.bDelInstaller = IsCheckedDlgItem(hDlg, IDC_DEL_AFTER_INSTALL);
break; break;
case IDC_SOURCE_DEFAULT: case IDC_SOURCE_DEFAULT:
NewSettingsInfo.bUseSource = FALSE; NewSettingsInfo.bUseSource = FALSE;
EnableWindow(GetDlgItem(hDlg, IDC_SOURCE_URL), NewSettingsInfo.bUseSource); EnableWindow(GetDlgItem(hDlg, IDC_SOURCE_URL), NewSettingsInfo.bUseSource);
break; break;
case IDC_USE_SOURCE: case IDC_USE_SOURCE:
NewSettingsInfo.bUseSource = TRUE; NewSettingsInfo.bUseSource = TRUE;
EnableWindow(GetDlgItem(hDlg, IDC_SOURCE_URL), NewSettingsInfo.bUseSource); EnableWindow(GetDlgItem(hDlg, IDC_SOURCE_URL), NewSettingsInfo.bUseSource);
break; break;
case IDC_PROXY_DEFAULT: case IDC_PROXY_DEFAULT:
NewSettingsInfo.Proxy = 0; NewSettingsInfo.Proxy = 0;
EnableWindow(GetDlgItem(hDlg, IDC_PROXY_SERVER), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_PROXY_SERVER), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), FALSE);
break; break;
case IDC_NO_PROXY: case IDC_NO_PROXY:
NewSettingsInfo.Proxy = 1; NewSettingsInfo.Proxy = 1;
EnableWindow(GetDlgItem(hDlg, IDC_PROXY_SERVER), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_PROXY_SERVER), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), FALSE);
break; break;
case IDC_USE_PROXY: case IDC_USE_PROXY:
NewSettingsInfo.Proxy = 2; NewSettingsInfo.Proxy = 2;
EnableWindow(GetDlgItem(hDlg, IDC_PROXY_SERVER), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_PROXY_SERVER), TRUE);
EnableWindow(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), TRUE);
break; break;
case IDC_DEFAULT_SETTINGS: case IDC_DEFAULT_SETTINGS:
FillDefaultSettings(&NewSettingsInfo); FillDefaultSettings(&NewSettingsInfo);
InitSettingsControls(hDlg, &NewSettingsInfo); InitSettingsControls(hDlg, &NewSettingsInfo);
break; break;
case IDOK: case IDOK:
{
ATL::CStringW szDir;
ATL::CStringW szSource;
ATL::CStringW szProxy;
ATL::CStringW szNoProxy;
DWORD dwAttr;
GetWindowTextW(GetDlgItem(hDlg, IDC_DOWNLOAD_DIR_EDIT),
szDir.GetBuffer(MAX_PATH), MAX_PATH);
szDir.ReleaseBuffer();
GetWindowTextW(GetDlgItem(hDlg, IDC_SOURCE_URL),
szSource.GetBuffer(INTERNET_MAX_URL_LENGTH), INTERNET_MAX_URL_LENGTH);
szSource.ReleaseBuffer();
GetWindowTextW(GetDlgItem(hDlg, IDC_PROXY_SERVER),
szProxy.GetBuffer(MAX_PATH), MAX_PATH);
szProxy.ReleaseBuffer();
ATL::CStringW::CopyChars(NewSettingsInfo.szProxyServer,
_countof(NewSettingsInfo.szProxyServer),
szProxy.GetString(),
szProxy.GetLength() + 1);
GetWindowTextW(GetDlgItem(hDlg, IDC_NO_PROXY_FOR),
szNoProxy.GetBuffer(MAX_PATH), MAX_PATH);
szNoProxy.ReleaseBuffer();
ATL::CStringW::CopyChars(NewSettingsInfo.szNoProxyFor,
_countof(NewSettingsInfo.szNoProxyFor),
szNoProxy.GetString(),
szNoProxy.GetLength() + 1);
dwAttr = GetFileAttributesW(szDir.GetString());
if (dwAttr != INVALID_FILE_ATTRIBUTES &&
(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
{ {
ATL::CStringW::CopyChars(NewSettingsInfo.szDownloadDir, CStringW szDir;
_countof(NewSettingsInfo.szDownloadDir), CStringW szSource;
szDir.GetString(), CStringW szProxy;
szDir.GetLength() + 1); CStringW szNoProxy;
} DWORD dwAttr;
else
{
ATL::CStringW szMsgText;
szMsgText.LoadStringW(IDS_CHOOSE_FOLDER_ERROR);
if (MessageBoxW(hDlg, szMsgText.GetString(), NULL, MB_YESNO) == IDYES) GetWindowTextW(GetDlgItem(hDlg, IDC_DOWNLOAD_DIR_EDIT), szDir.GetBuffer(MAX_PATH), MAX_PATH);
szDir.ReleaseBuffer();
GetWindowTextW(
GetDlgItem(hDlg, IDC_SOURCE_URL), szSource.GetBuffer(INTERNET_MAX_URL_LENGTH),
INTERNET_MAX_URL_LENGTH);
szSource.ReleaseBuffer();
GetWindowTextW(GetDlgItem(hDlg, IDC_PROXY_SERVER), szProxy.GetBuffer(MAX_PATH), MAX_PATH);
szProxy.ReleaseBuffer();
CStringW::CopyChars(
NewSettingsInfo.szProxyServer, _countof(NewSettingsInfo.szProxyServer), szProxy,
szProxy.GetLength() + 1);
GetWindowTextW(GetDlgItem(hDlg, IDC_NO_PROXY_FOR), szNoProxy.GetBuffer(MAX_PATH), MAX_PATH);
szNoProxy.ReleaseBuffer();
CStringW::CopyChars(
NewSettingsInfo.szNoProxyFor, _countof(NewSettingsInfo.szNoProxyFor), szNoProxy,
szNoProxy.GetLength() + 1);
dwAttr = GetFileAttributesW(szDir);
if (dwAttr != INVALID_FILE_ATTRIBUTES && (dwAttr & FILE_ATTRIBUTE_DIRECTORY))
{ {
if (CreateDirectoryW(szDir.GetString(), NULL)) CStringW::CopyChars(
{ NewSettingsInfo.szDownloadDir, _countof(NewSettingsInfo.szDownloadDir), szDir,
EndDialog(hDlg, LOWORD(wParam)); szDir.GetLength() + 1);
}
} }
else else
{ {
SetFocus(GetDlgItem(hDlg, IDC_DOWNLOAD_DIR_EDIT)); CStringW szMsgText;
szMsgText.LoadStringW(IDS_CHOOSE_FOLDER_ERROR);
if (MessageBoxW(hDlg, szMsgText, NULL, MB_YESNO) == IDYES)
{
if (CreateDirectoryW(szDir, NULL))
{
EndDialog(hDlg, LOWORD(wParam));
}
}
else
{
SetFocus(GetDlgItem(hDlg, IDC_DOWNLOAD_DIR_EDIT));
break;
}
}
if (NewSettingsInfo.bUseSource && !IsUrlValid(szSource))
{
CStringW szMsgText;
szMsgText.LoadStringW(IDS_URL_INVALID);
MessageBoxW(hDlg, szMsgText, NULL, 0);
SetFocus(GetDlgItem(hDlg, IDC_SOURCE_URL));
break; break;
} }
else
{
CStringW::CopyChars(
NewSettingsInfo.szSourceURL, _countof(NewSettingsInfo.szSourceURL), szSource,
szSource.GetLength() + 1);
}
SettingsInfo = NewSettingsInfo;
SaveSettings(GetParent(hDlg), &SettingsInfo);
EndDialog(hDlg, LOWORD(wParam));
} }
if(NewSettingsInfo.bUseSource && !IsUrlValid(szSource.GetString()))
{
ATL::CStringW szMsgText;
szMsgText.LoadStringW(IDS_URL_INVALID);
MessageBoxW(hDlg, szMsgText.GetString(), NULL, 0);
SetFocus(GetDlgItem(hDlg, IDC_SOURCE_URL));
break;
}
else
{
ATL::CStringW::CopyChars(NewSettingsInfo.szSourceURL,
_countof(NewSettingsInfo.szSourceURL),
szSource.GetString(),
szSource.GetLength() + 1);
}
SettingsInfo = NewSettingsInfo;
SaveSettings(GetParent(hDlg), &SettingsInfo);
EndDialog(hDlg, LOWORD(wParam));
}
break;
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
break; break;
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
break;
} }
} }
break; break;
}
return FALSE;
} }
}
VOID CreateSettingsDlg(HWND hwnd) return FALSE;
{ }
DialogBoxW(hInst, } // namespace
MAKEINTRESOURCEW(IDD_SETTINGS_DIALOG),
hwnd, VOID
SettingsDlgProc); CreateSettingsDlg(HWND hwnd)
{
DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_SETTINGS_DIALOG), hwnd, SettingsDlgProc);
} }

View file

@ -12,9 +12,10 @@
#include <setupapi.h> #include <setupapi.h>
#include <conutils.h> #include <conutils.h>
BOOL MatchCmdOption(LPWSTR argvOption, LPCWSTR szOptToMacth) static BOOL
MatchCmdOption(LPWSTR argvOption, LPCWSTR szOptToMacth)
{ {
WCHAR FirstCharList[] = { L'-', L'/' }; WCHAR FirstCharList[] = {L'-', L'/'};
for (UINT i = 0; i < _countof(FirstCharList); i++) for (UINT i = 0; i < _countof(FirstCharList); i++)
{ {
@ -26,7 +27,8 @@ BOOL MatchCmdOption(LPWSTR argvOption, LPCWSTR szOptToMacth)
return FALSE; return FALSE;
} }
void InitRappsConsole() static void
InitRappsConsole()
{ {
// First, try to attach to our parent's console // First, try to attach to our parent's console
if (!AttachConsole(ATTACH_PARENT_PROCESS)) if (!AttachConsole(ATTACH_PARENT_PROCESS))
@ -41,40 +43,32 @@ void InitRappsConsole()
ConInitStdStreams(); // Initialize the Console Standard Streams ConInitStdStreams(); // Initialize the Console Standard Streams
} }
static BOOL
BOOL HandleInstallCommand(LPWSTR szCommand, int argcLeft, LPWSTR * argvLeft) HandleInstallCommand(CApplicationDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
{ {
if (argcLeft == 0) if (argcLeft < 1)
{ {
InitRappsConsole(); InitRappsConsole();
ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_PACKAGE_NAME, szCommand); ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_PACKAGE_NAME, szCommand);
return FALSE; return FALSE;
} }
ATL::CSimpleArray<ATL::CStringW> PkgNameList; CAtlList<CApplicationInfo *> Applications;
for (int i = 0; i < argcLeft; i++) for (int i = 0; i < argcLeft; i++)
{ {
PkgNameList.Add(argvLeft[i]); LPCWSTR PackageName = argvLeft[i];
CApplicationInfo *AppInfo = db->FindByPackageName(PackageName);
if (AppInfo)
{
Applications.AddTail(AppInfo);
}
} }
CAvailableApps apps; return DownloadListOfApplications(Applications, TRUE);
apps.UpdateAppsDB();
apps.Enum(ENUM_ALL_AVAILABLE, NULL, NULL);
ATL::CSimpleArray<CAvailableApplicationInfo> arrAppInfo = apps.FindAppsByPkgNameList(PkgNameList);
if (arrAppInfo.GetSize() > 0)
{
DownloadListOfApplications(arrAppInfo, TRUE);
return TRUE;
}
else
{
return FALSE;
}
} }
BOOL HandleSetupCommand(LPWSTR szCommand, int argcLeft, LPWSTR * argvLeft) static BOOL
HandleSetupCommand(CApplicationDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
{ {
if (argcLeft != 1) if (argcLeft != 1)
{ {
@ -83,7 +77,7 @@ BOOL HandleSetupCommand(LPWSTR szCommand, int argcLeft, LPWSTR * argvLeft)
return FALSE; return FALSE;
} }
ATL::CSimpleArray<ATL::CStringW> PkgNameList; CAtlList<CApplicationInfo *> Applications;
HINF InfHandle = SetupOpenInfFileW(argvLeft[0], NULL, INF_STYLE_WIN4, NULL); HINF InfHandle = SetupOpenInfFileW(argvLeft[0], NULL, INF_STYLE_WIN4, NULL);
if (InfHandle == INVALID_HANDLE_VALUE) if (InfHandle == INVALID_HANDLE_VALUE)
{ {
@ -98,42 +92,21 @@ BOOL HandleSetupCommand(LPWSTR szCommand, int argcLeft, LPWSTR * argvLeft)
{ {
if (SetupGetStringFieldW(&Context, 1, szPkgName, _countof(szPkgName), NULL)) if (SetupGetStringFieldW(&Context, 1, szPkgName, _countof(szPkgName), NULL))
{ {
PkgNameList.Add(szPkgName); CApplicationInfo *AppInfo = db->FindByPackageName(szPkgName);
if (AppInfo)
{
Applications.AddTail(AppInfo);
}
} }
} while (SetupFindNextLine(&Context, &Context)); } while (SetupFindNextLine(&Context, &Context));
} }
SetupCloseInfFile(InfHandle); SetupCloseInfFile(InfHandle);
CAvailableApps apps; return DownloadListOfApplications(Applications, TRUE);
apps.UpdateAppsDB();
apps.Enum(ENUM_ALL_AVAILABLE, NULL, NULL);
ATL::CSimpleArray<CAvailableApplicationInfo> arrAppInfo = apps.FindAppsByPkgNameList(PkgNameList);
if (arrAppInfo.GetSize() > 0)
{
DownloadListOfApplications(arrAppInfo, TRUE);
return TRUE;
}
else
{
return FALSE;
}
} }
BOOL CALLBACK CmdFindAppEnum(CAvailableApplicationInfo *Info, BOOL bInitialCheckState, PVOID param) static BOOL
{ HandleFindCommand(CApplicationDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
LPCWSTR lpszSearch = (LPCWSTR)param;
if (!SearchPatternMatch(Info->m_szName, lpszSearch) &&
!SearchPatternMatch(Info->m_szDesc, lpszSearch))
{
return TRUE;
}
ConPrintf(StdOut, L"%s (%s)\n", Info->m_szName.GetString(), Info->m_szPkgName.GetString());
return TRUE;
}
BOOL HandleFindCommand(LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
{ {
if (argcLeft < 1) if (argcLeft < 1)
{ {
@ -141,20 +114,33 @@ BOOL HandleFindCommand(LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
return FALSE; return FALSE;
} }
CAvailableApps apps; CAtlList<CApplicationInfo *> List;
apps.UpdateAppsDB(); db->GetApps(List, ENUM_ALL_AVAILABLE);
for (int i = 0; i < argcLeft; i++) for (int i = 0; i < argcLeft; i++)
{ {
ConResMsgPrintf(StdOut, NULL, IDS_CMD_FIND_RESULT_FOR, argvLeft[i]); LPCWSTR lpszSearch = argvLeft[i];
apps.Enum(ENUM_ALL_AVAILABLE, CmdFindAppEnum, argvLeft[i]); ConResMsgPrintf(StdOut, NULL, IDS_CMD_FIND_RESULT_FOR, lpszSearch);
POSITION CurrentListPosition = List.GetHeadPosition();
while (CurrentListPosition)
{
CApplicationInfo *Info = List.GetNext(CurrentListPosition);
if (SearchPatternMatch(Info->szDisplayName, lpszSearch) || SearchPatternMatch(Info->szComments, lpszSearch))
{
ConPrintf(StdOut, L"%s (%s)\n", Info->szDisplayName.GetString(), Info->szIdentifier.GetString());
}
}
ConPrintf(StdOut, L"\n"); ConPrintf(StdOut, L"\n");
} }
return TRUE; return TRUE;
} }
BOOL HandleInfoCommand(LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft) static BOOL
HandleInfoCommand(CApplicationDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
{ {
if (argcLeft < 1) if (argcLeft < 1)
{ {
@ -162,70 +148,67 @@ BOOL HandleInfoCommand(LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
return FALSE; return FALSE;
} }
CAvailableApps apps;
apps.UpdateAppsDB();
apps.Enum(ENUM_ALL_AVAILABLE, NULL, NULL);
for (int i = 0; i < argcLeft; i++) for (int i = 0; i < argcLeft; i++)
{ {
CAvailableApplicationInfo *AppInfo = apps.FindAppByPkgName(argvLeft[i]); LPCWSTR PackageName = argvLeft[i];
CApplicationInfo *AppInfo = db->FindByPackageName(PackageName);
if (!AppInfo) if (!AppInfo)
{ {
ConResMsgPrintf(StdOut, NULL, IDS_CMD_PACKAGE_NOT_FOUND, argvLeft[i]); ConResMsgPrintf(StdOut, NULL, IDS_CMD_PACKAGE_NOT_FOUND, PackageName);
} }
else else
{ {
ConResMsgPrintf(StdOut, NULL, IDS_CMD_PACKAGE_INFO, argvLeft[i]); ConResMsgPrintf(StdOut, NULL, IDS_CMD_PACKAGE_INFO, PackageName);
// TODO: code about extracting information from CAvailableApplicationInfo (in appview.cpp, class CAppRichEdit)
// is in a mess. It should be refactored, and should not placed in class CAppRichEdit.
// and the code here should reused that code after refactor.
ConPuts(StdOut, AppInfo->m_szName); ConPuts(StdOut, AppInfo->szDisplayName);
if (AppInfo->m_szVersion) if (!AppInfo->szDisplayVersion.IsEmpty())
{ {
ConResPrintf(StdOut, IDS_AINFO_VERSION); ConResPrintf(StdOut, IDS_AINFO_VERSION);
ConPuts(StdOut, AppInfo->m_szVersion); ConPuts(StdOut, AppInfo->szDisplayVersion);
} }
if (AppInfo->m_szLicense) CStringW License, Size, UrlSite, UrlDownload;
AppInfo->GetDisplayInfo(License, Size, UrlSite, UrlDownload);
if (!License.IsEmpty())
{ {
ConResPrintf(StdOut, IDS_AINFO_LICENSE); ConResPrintf(StdOut, IDS_AINFO_LICENSE);
ConPuts(StdOut, AppInfo->m_szLicense); ConPuts(StdOut, License);
} }
if (AppInfo->m_szSize) if (!Size.IsEmpty())
{ {
ConResPrintf(StdOut, IDS_AINFO_SIZE); ConResPrintf(StdOut, IDS_AINFO_SIZE);
ConPuts(StdOut, AppInfo->m_szSize); ConPuts(StdOut, Size);
} }
if (AppInfo->m_szUrlSite) if (!UrlSite.IsEmpty())
{ {
ConResPrintf(StdOut, IDS_AINFO_URLSITE); ConResPrintf(StdOut, IDS_AINFO_URLSITE);
ConPuts(StdOut, AppInfo->m_szUrlSite); ConPuts(StdOut, UrlSite);
} }
if (AppInfo->m_szDesc) if (AppInfo->szComments)
{ {
ConResPrintf(StdOut, IDS_AINFO_DESCRIPTION); ConResPrintf(StdOut, IDS_AINFO_DESCRIPTION);
ConPuts(StdOut, AppInfo->m_szDesc); ConPuts(StdOut, AppInfo->szComments);
} }
if (AppInfo->m_szUrlDownload) if (!UrlDownload.IsEmpty())
{ {
ConResPrintf(StdOut, IDS_AINFO_URLDOWNLOAD); ConResPrintf(StdOut, IDS_AINFO_URLDOWNLOAD);
ConPuts(StdOut, AppInfo->m_szUrlDownload); ConPuts(StdOut, UrlDownload);
} }
ConPuts(StdOut, L"\n");
ConPrintf(StdOut, L"\n");
} }
ConPrintf(StdOut, L"\n"); ConPuts(StdOut, L"\n");
} }
return TRUE; return TRUE;
} }
VOID PrintHelpCommand() static VOID
PrintHelpCommand()
{ {
ConPrintf(StdOut, L"\n"); ConPrintf(StdOut, L"\n");
ConResPuts(StdOut, IDS_APPTITLE); ConResPuts(StdOut, IDS_APPTITLE);
@ -235,7 +218,8 @@ VOID PrintHelpCommand()
ConPrintf(StdOut, L"%ls\n", UsageString); ConPrintf(StdOut, L"%ls\n", UsageString);
} }
BOOL ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow) BOOL
ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow)
{ {
INT argc; INT argc;
LPWSTR *argv = CommandLineToArgvW(lpCmdLine, &argc); LPWSTR *argv = CommandLineToArgvW(lpCmdLine, &argc);
@ -245,6 +229,17 @@ BOOL ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow)
return FALSE; return FALSE;
} }
CStringW Directory;
GetStorageDirectory(Directory);
CApplicationDB db(Directory);
if (SettingsInfo.bUpdateAtStart || bIsFirstLaunch)
{
db.RemoveCached();
}
db.UpdateAvailable();
db.UpdateInstalled();
if (argc == 1) // RAPPS is launched without options if (argc == 1) // RAPPS is launched without options
{ {
// Check for if rapps MainWindow is already launched in another process // Check for if rapps MainWindow is already launched in another process
@ -262,10 +257,7 @@ BOOL ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow)
return FALSE; return FALSE;
} }
if (SettingsInfo.bUpdateAtStart || bIsFirstLaunch) MainWindowLoop(&db, nCmdShow);
CAvailableApps::ForceUpdateAppsDB();
MainWindowLoop(nCmdShow);
if (hMutex) if (hMutex)
CloseHandle(hMutex); CloseHandle(hMutex);
@ -275,22 +267,22 @@ BOOL ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow)
if (MatchCmdOption(argv[1], CMD_KEY_INSTALL)) if (MatchCmdOption(argv[1], CMD_KEY_INSTALL))
{ {
return HandleInstallCommand(argv[1], argc - 2, argv + 2); return HandleInstallCommand(&db, argv[1], argc - 2, argv + 2);
} }
else if (MatchCmdOption(argv[1], CMD_KEY_SETUP)) else if (MatchCmdOption(argv[1], CMD_KEY_SETUP))
{ {
return HandleSetupCommand(argv[1], argc - 2, argv + 2); return HandleSetupCommand(&db, argv[1], argc - 2, argv + 2);
} }
InitRappsConsole(); InitRappsConsole();
if (MatchCmdOption(argv[1], CMD_KEY_FIND)) if (MatchCmdOption(argv[1], CMD_KEY_FIND))
{ {
return HandleFindCommand(argv[1], argc - 2, argv + 2); return HandleFindCommand(&db, argv[1], argc - 2, argv + 2);
} }
else if (MatchCmdOption(argv[1], CMD_KEY_INFO)) else if (MatchCmdOption(argv[1], CMD_KEY_INFO))
{ {
return HandleInfoCommand(argv[1], argc - 2, argv + 2); return HandleInfoCommand(&db, argv[1], argc - 2, argv + 2);
} }
else if (MatchCmdOption(argv[1], CMD_KEY_HELP) || MatchCmdOption(argv[1], CMD_KEY_HELP_ALT)) else if (MatchCmdOption(argv[1], CMD_KEY_HELP) || MatchCmdOption(argv[1], CMD_KEY_HELP_ALT))
{ {

View file

@ -13,7 +13,7 @@
#include <gdiplus.h> #include <gdiplus.h>
#include <conutils.h> #include <conutils.h>
LPCWSTR szWindowClass = L"ROSAPPMGR"; LPCWSTR szWindowClass = L"ROSAPPMGR2";
HWND hMainWnd; HWND hMainWnd;
HINSTANCE hInst; HINSTANCE hInst;
@ -25,8 +25,8 @@ END_OBJECT_MAP()
CComModule gModule; CComModule gModule;
CAtlWinModule gWinModule; CAtlWinModule gWinModule;
INT WINAPI
INT WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, INT nShowCmd) wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, INT nShowCmd)
{ {
Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken; ULONG_PTR gdiplusToken;