Something went wrong. Try again.
Reactos
Something went wrong. Try again.
9.6 kB · 347 lines
C++
at listview
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348/* * 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 "appdb.h"#include "configparser.h"#include "settings.h"#include "misc.h"
static HKEY g_RootKeyEnum[3] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_LOCAL_MACHINE};static REGSAM g_RegSamEnum[3] = {0, KEY_WOW64_32KEY, KEY_WOW64_64KEY};#define UNINSTALL_SUBKEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
static VOIDClearList(CAtlList<CAppInfo *> &list){ POSITION InfoListPosition = list.GetHeadPosition(); while (InfoListPosition) { CAppInfo *Info = list.GetNext(InfoListPosition); delete Info; } list.RemoveAll();}
CAppDB::CAppDB(const CStringW &path) : m_BasePath(path){ m_BasePath.Canonicalize();}
CStringWCAppDB::GetDefaultPath(){ CStringW path; GetStorageDirectory(path); return path;}
CAvailableApplicationInfo *CAppDB::FindAvailableByPackageName(const CStringW &name){ POSITION CurrentListPosition = m_Available.GetHeadPosition(); while (CurrentListPosition) { CAppInfo *Info = m_Available.GetNext(CurrentListPosition); if (Info->szIdentifier == name) { return static_cast<CAvailableApplicationInfo *>(Info); } } return NULL;}
voidCAppDB::GetApps(CAtlList<CAppInfo *> &List, AppsCategories Type) const{ const BOOL UseInstalled = IsInstalledEnum(Type); const CAtlList<CAppInfo *> &list = UseInstalled ? m_Installed : m_Available; const BOOL IncludeAll = UseInstalled ? (Type == ENUM_ALL_INSTALLED) : (Type == ENUM_ALL_AVAILABLE);
POSITION CurrentListPosition = list.GetHeadPosition(); while (CurrentListPosition) { CAppInfo *Info = list.GetNext(CurrentListPosition);
if (IncludeAll || Type == Info->iCategory) { List.AddTail(Info); } }}
BOOLCAppDB::EnumerateFiles(){ ClearList(m_Available);
CPathW AppsPath = m_BasePath; AppsPath += RAPPS_DATABASE_SUBDIR; 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();
CAppInfo *Info = FindByPackageName(szPkgName); ATLASSERT(Info == NULL); if (!Info) { CConfigParser *Parser = new CConfigParser(CPathW(AppsPath) += FindFileData.cFileName); int Cat; if (!Parser->GetInt(DB_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;}
VOIDCAppDB::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 += RAPPS_DATABASE_SUBDIR; if (!ExtractFilesFromCab(APPLICATION_DATABASE_NAME, m_BasePath, AppsPath)) return;
CPathW CabFile = m_BasePath; CabFile += APPLICATION_DATABASE_NAME; DeleteFileW(CabFile);
EnumerateFiles();}
static inline HKEYGetRootKeyInfo(UINT Index, REGSAM &RegSam){ C_ASSERT(_countof(g_RootKeyEnum) == _countof(g_RegSamEnum)); if (Index < _countof(g_RootKeyEnum)) { RegSam = g_RegSamEnum[Index]; return g_RootKeyEnum[Index]; } return NULL;}
HKEYCAppDB::EnumInstalledRootKey(UINT Index, REGSAM &RegSam){ // Loop for through all combinations. // Note that HKEY_CURRENT_USER\Software does not have a redirect // https://learn.microsoft.com/en-us/windows/win32/winprog64/shared-registry-keys#redirected-shared-and-reflected-keys-under-wow64 if (Index < (IsSystem64Bit() ? 3 : 2)) return GetRootKeyInfo(Index, RegSam); else return NULL;}
CInstalledApplicationInfo *CAppDB::CreateInstalledAppByRegistryKey(LPCWSTR KeyName, HKEY hKeyParent, UINT KeyIndex){ CRegKey hSubKey; if (hSubKey.Open(hKeyParent, KeyName, KEY_READ) != ERROR_SUCCESS) return NULL; DWORD value, size;
size = sizeof(DWORD); if (!RegQueryValueExW(hSubKey, L"SystemComponent", NULL, NULL, (LPBYTE)&value, &size) && value == 1) { // Ignore system components return NULL; }
size = 0; BOOL bIsUpdate = !RegQueryValueExW(hSubKey, L"ParentKeyName", NULL, NULL, NULL, &size);
AppsCategories cat = bIsUpdate ? ENUM_UPDATES : ENUM_INSTALLED_APPLICATIONS; CInstalledApplicationInfo *pInfo; pInfo = new CInstalledApplicationInfo(hSubKey.Detach(), KeyName, cat, KeyIndex); if (pInfo && pInfo->Valid()) { return pInfo; } delete pInfo; return NULL;}
CInstalledApplicationInfo *CAppDB::EnumerateRegistry(CAtlList<CAppInfo *> *List, LPCWSTR SearchOnly){ ATLASSERT(List || SearchOnly); REGSAM wowsam; HKEY hRootKey; for (UINT rki = 0; (hRootKey = EnumInstalledRootKey(rki, wowsam)); ++rki) { CRegKey hKey; if (hKey.Open(hRootKey, UNINSTALL_SUBKEY, KEY_READ | wowsam) != ERROR_SUCCESS) { continue; } for (DWORD Index = 0;; ++Index) { WCHAR szKeyName[MAX_PATH]; DWORD dwSize = _countof(szKeyName); if (hKey.EnumKey(Index, szKeyName, &dwSize) != ERROR_SUCCESS) { break; } if (List || !StrCmpIW(SearchOnly, szKeyName)) { CInstalledApplicationInfo *Info; Info = CreateInstalledAppByRegistryKey(szKeyName, hKey, rki); if (Info) { if (List) List->AddTail(Info); else return Info; } } } } return NULL;}
VOIDCAppDB::UpdateInstalled(){ // Remove all old entries ClearList(m_Installed);
EnumerateRegistry(&m_Installed, NULL);}
CInstalledApplicationInfo *CAppDB::CreateInstalledAppByRegistryKey(LPCWSTR Name){ return EnumerateRegistry(NULL, Name);}
CInstalledApplicationInfo *CAppDB::CreateInstalledAppInstance(LPCWSTR KeyName, BOOL User, REGSAM WowSam){ HKEY hRootKey = User ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; UINT KeyIndex = User ? (0) : ((WowSam & KEY_WOW64_64KEY) ? 2 : 1); CRegKey hKey; if (hKey.Open(hRootKey, UNINSTALL_SUBKEY, KEY_READ | WowSam) == ERROR_SUCCESS) { return CreateInstalledAppByRegistryKey(KeyName, hKey, KeyIndex); } return NULL;}
static voidDeleteWithWildcard(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);}
VOIDCAppDB::RemoveCached(){ // Delete icons CPathW AppsPath = m_BasePath; AppsPath += RAPPS_DATABASE_SUBDIR; 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);}
DWORDCAppDB::RemoveInstalledAppFromRegistry(const CAppInfo *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 ERROR_INVALID_PARAMETER;
const CInstalledApplicationInfo *InstalledInfo = static_cast<const CInstalledApplicationInfo *>(Info);
CStringW Name = InstalledInfo->szIdentifier; REGSAM wowsam; HKEY hRoot = GetRootKeyInfo(InstalledInfo->m_KeyInfo, wowsam); ATLASSERT(hRoot); if (!hRoot) return ERROR_OPEN_FAILED;
CRegKey Uninstall; LSTATUS err = Uninstall.Open(hRoot, UNINSTALL_SUBKEY, KEY_READ | KEY_WRITE | wowsam); if (err == ERROR_SUCCESS) { err = Uninstall.RecurseDeleteKey(Name); } return err;}