/*
- * PROJECT: ReactOS Applications Manager
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: base/applications/rapps/available.cpp
- * PURPOSE: Classes for working with available applications
- * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
- * Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
- * Alexander Shaposhnikov (chaez.san@gmail.com)
+ * PROJECT: ReactOS Applications Manager
+ * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * FILE: base/applications/rapps/available.cpp
+ * 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)
*/
-
#include "rapps.h"
- // CAvailableApplicationInfo
+#include "available.h"
+#include "misc.h"
+#include "dialogs.h"
+#include <atlcoll.h>
+#include <atlsimpcoll.h>
+#include <atlstr.h>
+
+ // CAvailableApplicationInfo
CAvailableApplicationInfo::CAvailableApplicationInfo(const ATL::CStringW& sFileNameParam)
- : m_Parser(sFileNameParam)
+ : m_IsInstalled(FALSE), m_HasLanguageInfo(FALSE), m_HasInstalledVersion(FALSE), m_Parser(sFileNameParam)
{
- LicenseType = LICENSE_TYPE::None;
- sFileName = sFileNameParam;
+ m_LicenseType = LICENSE_NONE;
+
+ m_sFileName = sFileNameParam;
RetrieveGeneralInfo();
}
VOID CAvailableApplicationInfo::RefreshAppInfo()
{
- if (szUrlDownload.IsEmpty())
+ if (m_szUrlDownload.IsEmpty())
{
RetrieveGeneralInfo();
}
}
+// Lazily load general info from the file
VOID CAvailableApplicationInfo::RetrieveGeneralInfo()
{
- Category = m_Parser.GetInt(L"Category");
+ m_Category = m_Parser.GetInt(L"Category");
- if (!GetString(L"Name", szName)
- || !GetString(L"URLDownload", szUrlDownload))
+ if (!GetString(L"Name", m_szName)
+ || !GetString(L"URLDownload", m_szUrlDownload))
{
return;
}
- GetString(L"RegName", szRegName);
- GetString(L"Version", szVersion);
- GetString(L"License", szLicense);
- GetString(L"Description", szDesc);
- GetString(L"Size", szSize);
- GetString(L"URLSite", szUrlSite);
- GetString(L"CDPath", szCDPath);
- GetString(L"Language", szRegName);
- GetString(L"SHA1", szSHA1);
+ GetString(L"RegName", m_szRegName);
+ GetString(L"Version", m_szVersion);
+ GetString(L"License", m_szLicense);
+ GetString(L"Description", m_szDesc);
+ GetString(L"Size", m_szSize);
+ GetString(L"URLSite", m_szUrlSite);
+ GetString(L"CDPath", m_szCDPath);
+ GetString(L"Language", m_szRegName);
+ GetString(L"SHA1", m_szSHA1);
RetrieveLicenseType();
RetrieveLanguages();
VOID CAvailableApplicationInfo::RetrieveInstalledStatus()
{
- m_IsInstalled = ::GetInstalledVersion(NULL, szRegName)
- || ::GetInstalledVersion(NULL, szName);
+ m_IsInstalled = ::GetInstalledVersion(NULL, m_szRegName)
+ || ::GetInstalledVersion(NULL, m_szName);
}
VOID CAvailableApplicationInfo::RetrieveInstalledVersion()
{
- m_HasInstalledVersion = ::GetInstalledVersion(&szInstalledVersion, szRegName)
- || ::GetInstalledVersion(&szInstalledVersion, szName);
+ 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()
// Parse parameter string
ATL::CStringW m_szLocale;
- int iLCID;
+ INT iLCID;
for (INT i = 0; szBuffer[i] != UNICODE_NULL; ++i)
{
if (szBuffer[i] != cDelimiter && szBuffer[i] != L'\n')
{
if (StrToIntExW(m_szLocale.GetString(), STIF_DEFAULT, &iLCID))
{
- Languages.Add(static_cast<LCID>(iLCID));
+ m_LanguageLCIDs.Add(static_cast<LCID>(iLCID));
m_szLocale.Empty();
}
}
{
if (StrToIntExW(m_szLocale.GetString(), STIF_DEFAULT, &iLCID))
{
- Languages.Add(static_cast<LCID>(iLCID));
+ m_LanguageLCIDs.Add(static_cast<LCID>(iLCID));
}
}
{
INT IntBuffer = m_Parser.GetInt(L"LicenseType");
- if (IntBuffer < 0 || IntBuffer > LICENSE_TYPE::Max)
+ if (IsLicenseType(IntBuffer))
{
- LicenseType = LICENSE_TYPE::None;
+ m_LicenseType = static_cast<LicenseType>(IntBuffer);
}
else
{
- LicenseType = (LICENSE_TYPE) IntBuffer;
+ m_LicenseType = LICENSE_NONE;
}
}
}
//Find locale code in the list
- const INT nLanguagesSize = Languages.GetSize();
+ const INT nLanguagesSize = m_LanguageLCIDs.GetSize();
for (INT i = 0; i < nLanguagesSize; ++i)
{
- if (Languages[i] == what)
+ if (m_LanguageLCIDs[i] == what)
{
return TRUE;
}
BOOL CAvailableApplicationInfo::HasUpdate() const
{
- return (szInstalledVersion.Compare(szVersion) < 0) ? TRUE : FALSE;
+ return (m_szInstalledVersion.Compare(m_szVersion) < 0) ? TRUE : FALSE;
}
VOID CAvailableApplicationInfo::SetLastWriteTime(FILETIME* ftTime)
{
- RtlCopyMemory(&ftCacheStamp, ftTime, sizeof(FILETIME));
+ RtlCopyMemory(&m_ftCacheStamp, ftTime, sizeof(FILETIME));
}
inline BOOL CAvailableApplicationInfo::GetString(LPCWSTR lpKeyName, ATL::CStringW& ReturnedString)
// CAvailableApplicationInfo
// CAvailableApps
-CAvailableApps::CAvailableApps()
+ATL::CStringW CAvailableApps::m_szPath;
+ATL::CStringW CAvailableApps::m_szCabPath;
+ATL::CStringW CAvailableApps::m_szAppsPath;
+ATL::CStringW CAvailableApps::m_szSearchPath;
+
+BOOL CAvailableApps::InitializeStaticStrings()
{
- //set all paths
+
+ if (!m_szPath.IsEmpty())
+ {
+ // strings are filled
+ return TRUE;
+ }
+
+ //FIXME: maybe provide a fallback?
if (GetStorageDirectory(m_szPath))
{
m_szAppsPath = m_szPath + L"\\rapps\\";
m_szCabPath = m_szPath + L"\\rappmgr.cab";
m_szSearchPath = m_szAppsPath + L"*.txt";
+ return TRUE;
}
+
+ return FALSE;
+}
+
+CAvailableApps::CAvailableApps()
+{
+ //set all paths
+ InitializeStaticStrings();
}
VOID CAvailableApps::FreeCachedEntries()
/* loop and deallocate all the cached app infos in the list */
while (InfoListPosition)
{
- CAvailableApplicationInfo* Info = m_InfoList.GetAt(InfoListPosition);
- m_InfoList.RemoveHead();
+ CAvailableApplicationInfo* Info = m_InfoList.GetNext(InfoListPosition);
delete Info;
-
- InfoListPosition = m_InfoList.GetHeadPosition();
}
+
+ m_InfoList.RemoveAll();
}
-BOOL CAvailableApps::DeleteCurrentAppsDB()
+VOID CAvailableApps::DeleteCurrentAppsDB()
{
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindFileData;
- BOOL result = TRUE;
- if (m_szPath.IsEmpty())
- return FALSE;
+ if (!InitializeStaticStrings())
+ {
+ return;
+ }
- result = result && DeleteFileW(m_szCabPath.GetString());
hFind = FindFirstFileW(m_szSearchPath.GetString(), &FindFileData);
- if (hFind == INVALID_HANDLE_VALUE)
- return result;
-
- ATL::CStringW szTmp;
- do
+ if (hFind != INVALID_HANDLE_VALUE)
{
- szTmp = m_szPath + FindFileData.cFileName;
- result = result && DeleteFileW(szTmp.GetString());
- } while (FindNextFileW(hFind, &FindFileData) != 0);
-
- FindClose(hFind);
+ ATL::CStringW szTmp;
+ do
+ {
+ szTmp = m_szAppsPath + FindFileData.cFileName;
+ DeleteFileW(szTmp.GetString());
+ } while (FindNextFileW(hFind, &FindFileData) != 0);
+ FindClose(hFind);
+ }
- return result;
+ RemoveDirectoryW(m_szAppsPath);
+ RemoveDirectoryW(m_szPath);
}
BOOL CAvailableApps::UpdateAppsDB()
{
- if (!DeleteCurrentAppsDB())
- return FALSE;
+ HANDLE hFind = INVALID_HANDLE_VALUE;
+ WIN32_FIND_DATAW FindFileData;
- DownloadApplicationsDB(APPLICATION_DATABASE_URL);
+ if (!InitializeStaticStrings())
+ {
+ return FALSE;
+ }
- if (m_szPath.IsEmpty())
+ if (!CreateDirectoryW(m_szPath.GetString(), NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+ {
return FALSE;
+ }
+
+ //if there are some files in the db folder - we're good
+ hFind = FindFirstFileW(m_szSearchPath.GetString(), &FindFileData);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ return TRUE;
+ }
+
+ CDownloadManager::DownloadApplicationsDB(APPLICATION_DATABASE_URL);
if (!ExtractFilesFromCab(m_szCabPath, m_szAppsPath))
{
return FALSE;
}
+ DeleteFileW(m_szCabPath.GetString());
+
return TRUE;
}
-BOOL CAvailableApps::EnumAvailableApplications(INT EnumType, AVAILENUMPROC lpEnumProc)
+BOOL CAvailableApps::ForceUpdateAppsDB()
{
+ DeleteCurrentAppsDB();
+ return UpdateAppsDB();
+}
+
+BOOL CAvailableApps::Enum(INT EnumType, AVAILENUMPROC lpEnumProc)
+{
+
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindFileData;
- if (!CreateDirectoryW(m_szPath.GetString(), NULL) &&
- GetLastError() != ERROR_ALREADY_EXISTS)
- {
- return FALSE;
- }
-
hFind = FindFirstFileW(m_szSearchPath.GetString(), &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
- if (GetFileAttributesW(m_szCabPath) == INVALID_FILE_ATTRIBUTES)
- DownloadApplicationsDB(APPLICATION_DATABASE_URL);
-
- ExtractFilesFromCab(m_szCabPath, m_szAppsPath);
- hFind = FindFirstFileW(m_szSearchPath.GetString(), &FindFileData);
-
- if (hFind == INVALID_HANDLE_VALUE)
- return FALSE;
+ //no db yet
+ return FALSE;
}
do
Info = m_InfoList.GetNext(CurrentListPosition);
// do we already have this entry in cache?
- if (Info->sFileName == FindFileData.cFileName)
+ 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->ftCacheStamp) == 1)
+ if (CompareFileTime(&FindFileData.ftLastWriteTime, &Info->m_ftCacheStamp) == 1)
{
// recreate our cache, this is the slow path
m_InfoList.RemoveAt(LastListPosition);
delete Info;
- Info = nullptr;
+ Info = NULL;
break;
}
else
m_InfoList.AddTail(Info);
skip_if_cached:
- if (Info->Category == FALSE)
+ if (Info->m_Category == FALSE)
continue;
- if (EnumType != Info->Category && EnumType != ENUM_ALL_AVAILABLE)
+ if (EnumType != Info->m_Category && EnumType != ENUM_ALL_AVAILABLE)
continue;
Info->RefreshAppInfo();
- if (!lpEnumProc(static_cast<PAPPLICATION_INFO>(Info), m_szAppsPath.GetString()))
- break;
+ if (lpEnumProc)
+ lpEnumProc(static_cast<CAvailableApplicationInfo*>(Info), m_szAppsPath.GetString());
} while (FindNextFileW(hFind, &FindFileData) != 0);
return TRUE;
}
-const ATL::CStringW & CAvailableApps::GetFolderPath()
+CAvailableApplicationInfo* CAvailableApps::FindInfo(const ATL::CStringW& szAppName) const
{
- return m_szPath;
-}
-
-const ATL::CStringW & CAvailableApps::GetAppPath()
-{
- return m_szAppsPath;
-}
-
-const ATL::CStringW & CAvailableApps::GetCabPath()
-{
- return m_szCabPath;
-}
-
-const LPCWSTR CAvailableApps::GetFolderPathString()
-{
- return m_szPath.GetString();
-}
-
-const LPCWSTR CAvailableApps::GetAppPathString()
-{
- return m_szPath.GetString();
-}
+ if (m_InfoList.IsEmpty())
+ {
+ return NULL;
+ }
-const LPCWSTR CAvailableApps::GetCabPathString()
-{
- return m_szPath.GetString();
+ // linear search
+ POSITION CurrentListPosition = m_InfoList.GetHeadPosition();
+ CAvailableApplicationInfo* info;
+ while (CurrentListPosition != NULL)
+ {
+ info = m_InfoList.GetNext(CurrentListPosition);
+ if (info->m_szName == szAppName)
+ {
+ return info;
+ }
+ }
+ return NULL;
}
-// CAvailableApps
-
-// CConfigParser
-ATL::CStringW CConfigParser::m_szLocaleID;
-ATL::CStringW CConfigParser::m_szCachedINISectionLocale;
-ATL::CStringW CConfigParser::m_szCachedINISectionLocaleNeutral;
-CConfigParser::CConfigParser(const ATL::CStringW& FileName) : szConfigPath(GetINIFullPath(FileName))
+ATL::CSimpleArray<CAvailableApplicationInfo*> CAvailableApps::FindInfoList(const ATL::CSimpleArray<ATL::CStringW> &arrAppsNames) const
{
- // we don't have cached section strings for the current system language, create them, lazy
- CacheINILocaleLazy();
+ ATL::CSimpleArray<CAvailableApplicationInfo*> result;
+ for (INT i = 0; i < arrAppsNames.GetSize(); ++i)
+ {
+ CAvailableApplicationInfo* Info = FindInfo(arrAppsNames[i]);
+ if (Info)
+ {
+ result.Add(Info);
+ }
+ }
+ return result;
}
-ATL::CStringW CConfigParser::GetINIFullPath(const ATL::CStringW& FileName)
+const ATL::CStringW& CAvailableApps::GetFolderPath() const
{
- ATL::CStringW szDir;
- ATL::CStringW szBuffer;
-
- GetStorageDirectory(szDir);
- szBuffer.Format(L"%ls\\rapps\\%ls", szDir, FileName);
-
- return szBuffer;
+ return m_szPath;
}
-VOID CConfigParser::CacheINILocaleLazy()
+const ATL::CStringW& CAvailableApps::GetAppPath() const
{
- if (m_szLocaleID.IsEmpty())
- {
- // TODO: Set default locale if call fails
- // find out what is the current system lang code (e.g. "0a") and append it to SectionLocale
- GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE,
- m_szLocaleID.GetBuffer(m_cchLocaleSize), m_cchLocaleSize);
-
- m_szLocaleID.ReleaseBuffer();
- m_szCachedINISectionLocale = L"Section." + m_szLocaleID;
-
- // turn "Section.0c0a" into "Section.0a", keeping just the neutral lang part
- m_szCachedINISectionLocaleNeutral = m_szCachedINISectionLocale + m_szLocaleID.Right(2);
- }
+ return m_szAppsPath;
}
-const ATL::CStringW& CConfigParser::GetLocale()
+const ATL::CStringW& CAvailableApps::GetCabPath() const
{
- CacheINILocaleLazy();
- return m_szLocaleID;
+ return m_szCabPath;
}
-INT CConfigParser::GetLocaleSize()
+LPCWSTR CAvailableApps::GetFolderPathString() const
{
- return m_cchLocaleSize;
+ return m_szPath.GetString();
}
-UINT CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString)
+LPCWSTR CAvailableApps::GetAppPathString() const
{
- DWORD dwResult;
-
- LPWSTR ResultStringBuffer = ResultString.GetBuffer(MAX_PATH);
- // 1st - find localized strings (e.g. "Section.0c0a")
- dwResult = GetPrivateProfileStringW(m_szCachedINISectionLocale.GetString(),
- KeyName.GetString(),
- NULL,
- ResultStringBuffer,
- MAX_PATH,
- szConfigPath.GetString());
-
- if (!dwResult)
- {
- // 2nd - if they weren't present check for neutral sub-langs/ generic translations (e.g. "Section.0a")
- dwResult = GetPrivateProfileStringW(m_szCachedINISectionLocaleNeutral.GetString(),
- KeyName.GetString(),
- NULL,
- ResultStringBuffer,
- MAX_PATH,
- szConfigPath.GetString());
- if (!dwResult)
- {
- // 3rd - if they weren't present fallback to standard english strings (just "Section")
- dwResult = GetPrivateProfileStringW(L"Section",
- KeyName.GetString(),
- NULL,
- ResultStringBuffer,
- MAX_PATH,
- szConfigPath.GetString());
- }
- }
-
- ResultString.ReleaseBuffer();
- return (dwResult != 0 ? TRUE : FALSE);
+ return m_szPath.GetString();
}
-UINT CConfigParser::GetInt(const ATL::CStringW& KeyName)
+LPCWSTR CAvailableApps::GetCabPathString() const
{
- ATL::CStringW Buffer;
-
- // grab the text version of our entry
- if (!GetString(KeyName, Buffer))
- return FALSE;
-
- if (Buffer.IsEmpty())
- return FALSE;
-
- // convert it to an actual integer
- int result = StrToIntW(Buffer.GetString());
-
- return (UINT) (result <= 0) ? 0 : result;
+ return m_szPath.GetString();
}
-// CConfigParser
\ No newline at end of file
+// CAvailableApps