* PURPOSE: Functions for working with available applications
* PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
* Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
+ * Alexander Shaposhnikov (chaez.san@gmail.com)
*/
#include "rapps.h"
-inline void _AddText(UINT a, LPCWSTR b, DWORD c, DWORD d)
+ATL::CAtlList<PAPPLICATION_INFO> InfoList;
+
+inline VOID
+InsertTextAfterLoaded_RichEdit(UINT uStringID, const ATL::CStringW& szText, DWORD StringFlags, DWORD TextFlags)
{
- if (b[0] != '\0')
+ ATL::CStringW szLoadedText;
+ if (!szText.IsEmpty() && szLoadedText.LoadStringW(hInst, uStringID))
{
- WCHAR szText[MAX_STR_LEN];
- LoadStringW(hInst, a, szText, _countof(szText));
- InsertRichEditText(szText, c);
- InsertRichEditText(b, d);
+ InsertRichEditText(szLoadedText, StringFlags);
+ InsertRichEditText(szText, TextFlags);
}
}
-inline void _AddTextNewl(UINT a, DWORD b)
+inline VOID
+InsertLoadedTextNewl_RichEdit(UINT uStringID, DWORD StringFlags)
{
- WCHAR szText[MAX_STR_LEN];
- LoadStringW(hInst, a, szText, _countof(szText));
- InsertRichEditText(L"\n", 0);
- InsertRichEditText(szText, b);
- InsertRichEditText(L"\n", 0);
+ ATL::CStringW szLoadedText;
+ if (szLoadedText.LoadStringW(hInst, uStringID))
+ {
+ InsertRichEditText(L"\n", 0);
+ InsertRichEditText(szLoadedText, StringFlags);
+ InsertRichEditText(L"\n", 0);
+ }
}
-template<typename T, size_t N, size_t N2>
-inline BOOL _GetString(LPCWSTR a, T(&b)[N], T(&cFileName)[N2])
+inline BOOL
+GetString(LPCWSTR lpKeyName, ATL::CStringW& ReturnedString, const ATL::CStringW& cFileName)
{
- return ParserGetString(a, b, N, cFileName);
+ if (!ParserGetString(lpKeyName, cFileName, ReturnedString))
+ {
+ ReturnedString.Empty();
+ return FALSE;
+ }
+ return TRUE;
}
-template<typename T, size_t N, size_t N2>
-inline void _GetStringNullFailure(LPCWSTR a, T(&b)[N], T(&cFileName)[N2])
+//Check both registry keys in 64bit system
+//TODO: check system type beforehand to avoid double checks?
+inline BOOL
+GetInstalledVersionEx(PAPPLICATION_INFO Info, ATL::CStringW* szVersion, REGSAM key)
{
- if (!_GetString(a, b, cFileName))
- {
- b[0] = '\0';
- }
+ return (!Info->szRegName.IsEmpty()
+ && (GetInstalledVersion_WowUser(szVersion, Info->szRegName, TRUE, key)
+ || GetInstalledVersion_WowUser(szVersion, Info->szRegName, FALSE, key)))
+ || (!Info->szName.IsEmpty()
+ && (GetInstalledVersion_WowUser(szVersion, Info->szName, TRUE, key)
+ || GetInstalledVersion_WowUser(szVersion, Info->szName, FALSE, key)));
}
-//App is "installed" if the RegName or Name is in the registry
-inline BOOL _AppInstallCheckWithKey(PAPPLICATION_INFO Info, REGSAM key)
+inline BOOL
+GetInstalledVersion(PAPPLICATION_INFO Info, ATL::CStringW* szVersion)
{
- return (*Info->szRegName
- && (IsInstalledApplication(Info->szRegName, TRUE, key)
- || IsInstalledApplication(Info->szRegName, FALSE, key)))
- || (*Info->szName && (IsInstalledApplication(Info->szName, TRUE, key)
- || IsInstalledApplication(Info->szName, FALSE, key)));
+ return GetInstalledVersionEx(Info, szVersion, KEY_WOW64_32KEY)
+ || GetInstalledVersionEx(Info, szVersion, KEY_WOW64_64KEY);
}
+inline BOOL
+IsAppInstalled(PAPPLICATION_INFO Info)
+{
+ return GetInstalledVersion(Info, NULL);
+}
-//Check both registry keys in 64bit system
-//TODO: check system type beforehand to avoid double checks?
-inline BOOL _AppInstallCheck(PAPPLICATION_INFO Info)
+ATL::CSimpleArray<ATL::CStringW>
+ParserGetAppLanguages(const ATL::CStringW& szFileName)
{
- return _AppInstallCheckWithKey(Info, KEY_WOW64_32KEY)
- || _AppInstallCheckWithKey(Info, KEY_WOW64_64KEY);
+ const WCHAR cDelimiter = L'|';
+ ATL::CStringW szBuffer;
+
+ if (!ParserGetString(L"Languages", szFileName, szBuffer))
+ return CSimpleArray<ATL::CStringW>();
+
+ ATL::CStringW szLocale;
+ ATL::CSimpleArray<ATL::CStringW> arrLocalesResult;
+ for (INT i = 0; szBuffer[i] != UNICODE_NULL; ++i)
+ {
+ if (szBuffer[i] != cDelimiter)
+ {
+ szLocale += szBuffer[i];
+ } else {
+ arrLocalesResult.Add(szLocale);
+ szLocale.Empty();
+ }
+ }
+ // For the text after delimiter
+ if (!szLocale.IsEmpty())
+ {
+ arrLocalesResult.Add(szLocale);
+ }
+ return arrLocalesResult;
}
-//App is "installed" if the RegName or Name is in the registry
-inline BOOL _GetInstalledVersionWithKey(PAPPLICATION_INFO Info, LPWSTR szVersion, UINT iVersionSize, REGSAM key)
+BOOL
+HasNativeLanguage(PAPPLICATION_INFO Info)
{
- return (*Info->szRegName
- && (InstalledVersion(szVersion, iVersionSize, Info->szRegName, TRUE, key)
- || InstalledVersion(szVersion, iVersionSize, Info->szRegName, FALSE, key)))
- || (*Info->szName && (InstalledVersion(szVersion, iVersionSize, Info->szName, TRUE, key)
- || InstalledVersion(szVersion, iVersionSize, Info->szName, FALSE, key)));
+ if (!Info)
+ {
+ return FALSE;
+ }
+ //TODO: make the actual check
+ return TRUE;
}
-//App is "installed" if the RegName or Name is in the registry
-inline BOOL _GetInstalledVersion(PAPPLICATION_INFO Info, LPWSTR szVersion, UINT iVersionSize)
+LICENSE_TYPE
+ParserGetLicenseType(const ATL::CStringW& szFileName)
{
- return _GetInstalledVersionWithKey(Info, szVersion, iVersionSize, KEY_WOW64_32KEY)
- || _GetInstalledVersionWithKey(Info, szVersion, iVersionSize, KEY_WOW64_64KEY);
+ INT IntBuffer = ParserGetInt(L"LicenseType", szFileName);
+ if (IntBuffer < 0 || IntBuffer > LICENSE_TYPE::Max)
+ {
+ return LICENSE_TYPE::None;
+ }
+ return (LICENSE_TYPE) IntBuffer;
}
LIST_ENTRY CachedEntriesHead = {&CachedEntriesHead, &CachedEntriesHead};
PLIST_ENTRY pCachedEntry = &CachedEntriesHead;
-BOOL
-ShowAvailableAppInfo(INT Index)
+VOID
+InsertVersionInfo_RichEdit(PAPPLICATION_INFO Info)
{
- PAPPLICATION_INFO Info = (PAPPLICATION_INFO) ListViewGetlParam(Index);
- BOOL bIsInstalled = _AppInstallCheck(Info);
- WCHAR szVersion[MAX_PATH];
+ ATL::CStringW szVersion;
+ BOOL bIsInstalled = IsAppInstalled(Info),
+ bHasVersion = GetInstalledVersion(Info, &szVersion);
- if (!Info) return FALSE;
-
- NewRichEditText(Info->szName, CFE_BOLD);
if (bIsInstalled)
{
- _AddTextNewl(IDS_STATUS_INSTALLED, CFE_ITALIC);
- if (_GetInstalledVersion(Info, szVersion, _countof(szVersion)))
+ if (bHasVersion)
{
- _AddText(IDS_AINFO_VERSION, szVersion, CFE_BOLD, 0);
+ if (Info->szVersion.Compare(szVersion) > 0)
+ InsertLoadedTextNewl_RichEdit(IDS_STATUS_UPDATE_AVAILABLE, CFE_ITALIC);
+ else
+ InsertLoadedTextNewl_RichEdit(IDS_STATUS_INSTALLED, CFE_ITALIC);
+
+ InsertTextAfterLoaded_RichEdit(IDS_AINFO_VERSION, szVersion, CFE_BOLD, 0);
}
+ else
+ InsertLoadedTextNewl_RichEdit(IDS_STATUS_INSTALLED, CFE_ITALIC);
+
+ }
+ else
+ InsertLoadedTextNewl_RichEdit(IDS_STATUS_NOTINSTALLED, CFE_ITALIC);
+
+ InsertTextAfterLoaded_RichEdit(IDS_AINFO_AVAILABLEVERSION, Info->szVersion, CFE_BOLD, 0);
+}
+
+VOID
+InsertLicenseInfo_RichEdit(PAPPLICATION_INFO Info)
+{
+ ATL::CStringW szLicense;
+ switch (Info->LicenseType)
+ {
+ case LICENSE_TYPE::OpenSource:
+ szLicense.LoadStringW(hInst, IDS_LICENSE_OPENSOURCE);
+ break;
+ case LICENSE_TYPE::Freeware:
+ szLicense.LoadStringW(hInst, IDS_LICENSE_FREEWARE);
+ break;
+ case LICENSE_TYPE::Trial:
+ szLicense.LoadStringW(hInst, IDS_LICENSE_TRIAL);
+ break;
+ default:
+ break;
+ }
+
+ if (szLicense.IsEmpty())
+ {
+ InsertTextAfterLoaded_RichEdit(IDS_AINFO_LICENSE, Info->szLicense, CFE_BOLD, 0);
}
else
{
- _AddTextNewl(IDS_STATUS_NOTINSTALLED, CFE_ITALIC);
+ szLicense.Format(L"(%ls)", Info->szLicense);
+ InsertTextAfterLoaded_RichEdit(IDS_AINFO_LICENSE, szLicense, CFE_BOLD, 0);
}
- _AddText(IDS_AINFO_AVAILABLEVERSION, Info->szVersion, CFE_BOLD, 0);
- _AddText(IDS_AINFO_LICENSE, Info->szLicense, CFE_BOLD, 0);
- _AddText(IDS_AINFO_SIZE, Info->szSize, CFE_BOLD, 0);
- _AddText(IDS_AINFO_URLSITE, Info->szUrlSite, CFE_BOLD, CFE_LINK);
- _AddText(IDS_AINFO_DESCRIPTION, Info->szDesc, CFE_BOLD, 0);
- _AddText(IDS_AINFO_URLDOWNLOAD, Info->szUrlDownload, CFE_BOLD, CFE_LINK);
+}
+
+BOOL
+ShowAvailableAppInfo(INT Index)
+{
+ PAPPLICATION_INFO Info = (PAPPLICATION_INFO) ListViewGetlParam(Index);
+ if (!Info) return FALSE;
+
+ NewRichEditText(Info->szName, CFE_BOLD);
+ InsertVersionInfo_RichEdit(Info);
+ InsertLicenseInfo_RichEdit(Info);
+
+ InsertTextAfterLoaded_RichEdit(IDS_AINFO_SIZE, Info->szSize, CFE_BOLD, 0);
+ InsertTextAfterLoaded_RichEdit(IDS_AINFO_URLSITE, Info->szUrlSite, CFE_BOLD, CFE_LINK);
+ InsertTextAfterLoaded_RichEdit(IDS_AINFO_DESCRIPTION, Info->szDesc, CFE_BOLD, 0);
+ InsertTextAfterLoaded_RichEdit(IDS_AINFO_URLDOWNLOAD, Info->szUrlDownload, CFE_BOLD, CFE_LINK);
return TRUE;
}
{
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindFileData;
- WCHAR szCabPath[MAX_PATH];
- WCHAR szSearchPath[MAX_PATH];
- WCHAR szPath[MAX_PATH];
- WCHAR szTmp[MAX_PATH];
- HRESULT hr;
+ ATL::CStringW szCabPath;
+ ATL::CStringW szSearchPath;
+ ATL::CStringW szPath;
BOOL result = TRUE;
- if (!GetStorageDirectory(szPath, _countof(szPath)))
+ if (!GetStorageDirectory(szPath))
return FALSE;
- hr = StringCbPrintfW(szCabPath, sizeof(szCabPath),
- L"%ls\\rappmgr.cab",
- szPath);
- if (FAILED(hr))
- return FALSE;
-
- result = result && DeleteFileW(szCabPath);
+ szCabPath = szPath + L"\\rappmgr.cab";
+ result = result && DeleteFileW(szCabPath.GetString());
- hr = StringCbCatW(szPath, sizeof(szPath), L"\\rapps\\");
+ szPath += L"\\rapps\\";
+ szSearchPath = szPath + L"*.txt";
- if (FAILED(hr))
- return FALSE;
-
- hr = StringCbPrintfW(szSearchPath, sizeof(szSearchPath),
- L"%ls*.txt",
- szPath);
- if (FAILED(hr))
- return FALSE;
-
- hFind = FindFirstFileW(szSearchPath, &FindFileData);
+ hFind = FindFirstFileW(szSearchPath.GetString(), &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
return result;
+ ATL::CStringW szTmp;
do
{
- hr = StringCbPrintfW(szTmp, sizeof(szTmp),
- L"%ls%ls",
- szPath, FindFileData.cFileName);
- if (FAILED(hr))
- continue;
- result = result && DeleteFileW(szTmp);
-
- }
- while (FindNextFileW(hFind, &FindFileData) != 0);
+ szTmp = szPath + FindFileData.cFileName;
+ result = result && DeleteFileW(szTmp.GetString());
+ } while (FindNextFileW(hFind, &FindFileData) != 0);
FindClose(hFind);
return result;
}
-
BOOL
UpdateAppsDB(VOID)
{
- WCHAR szPath[MAX_PATH];
- WCHAR szAppsPath[MAX_PATH];
- WCHAR szCabPath[MAX_PATH];
+ ATL::CStringW szPath;
+ ATL::CStringW szAppsPath;
+ ATL::CStringW szCabPath;
if (!DeleteCurrentAppsDB())
return FALSE;
DownloadApplicationsDB(APPLICATION_DATABASE_URL);
- if (!GetStorageDirectory(szPath, _countof(szPath)))
+ if (!GetStorageDirectory(szPath))
return FALSE;
- if (FAILED(StringCbPrintfW(szCabPath, sizeof(szCabPath),
- L"%ls\\rappmgr.cab",
- szPath)))
- {
- return FALSE;
- }
+ szCabPath = szPath + L"\\rappmgr.cab";
+ szAppsPath = szPath + L"\\rapps\\";
- if (FAILED(StringCbPrintfW(szAppsPath, sizeof(szAppsPath),
- L"%ls\\rapps\\",
- szPath)))
+ if (!ExtractFilesFromCab(szCabPath, szAppsPath))
{
return FALSE;
}
- ExtractFilesFromCab(szCabPath, szAppsPath);
-
return TRUE;
}
{
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindFileData;
- WCHAR szPath[MAX_PATH];
- WCHAR szAppsPath[MAX_PATH];
- WCHAR szCabPath[MAX_PATH];
+ ATL::CStringW szPath;
+ ATL::CStringW szAppsPath;
+ ATL::CStringW szCabPath;
PAPPLICATION_INFO Info;
- HRESULT hr;
-
- if (!GetStorageDirectory(szPath, _countof(szPath)))
- return FALSE;
-
- hr = StringCbPrintfW(szCabPath, sizeof(szCabPath),
- L"%ls\\rappmgr.cab",
- szPath);
- if (FAILED(hr))
- return FALSE;
-
- hr = StringCbCatW(szPath, sizeof(szPath), L"\\rapps\\");
- if (FAILED(hr))
+ if (!GetStorageDirectory(szPath))
return FALSE;
- hr = StringCbCopyW(szAppsPath, sizeof(szAppsPath), szPath);
+ szCabPath = szPath + L"\\rappmgr.cab";
+ szPath += L"\\rapps\\";
+ szAppsPath = szPath;
- if (FAILED(hr))
- return FALSE;
-
- if (!CreateDirectory(szPath, NULL) &&
+ if (!CreateDirectoryW(szPath.GetString(), NULL) &&
GetLastError() != ERROR_ALREADY_EXISTS)
{
return FALSE;
}
- hr = StringCbCatW(szPath, sizeof(szPath), L"*.txt");
-
- if (FAILED(hr))
- return FALSE;
-
- hFind = FindFirstFileW(szPath, &FindFileData);
+ szPath += L"*.txt";
+ hFind = FindFirstFileW(szPath.GetString(), &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
do
{
/* loop for all the cached entries */
- for (pCachedEntry = CachedEntriesHead.Flink; pCachedEntry != &CachedEntriesHead; pCachedEntry = pCachedEntry->Flink)
+ POSITION CurrentListPosition = InfoList.GetHeadPosition();
+
+ while (CurrentListPosition != NULL)
{
- Info = CONTAINING_RECORD(pCachedEntry, APPLICATION_INFO, List);
+ POSITION LastListPosition = CurrentListPosition;
+ Info = InfoList.GetNext(CurrentListPosition);
/* do we already have this entry in cache? */
- if (_wcsicmp(FindFileData.cFileName, Info->cFileName) == 0)
+ if (!Info->cFileName.Compare(FindFileData.cFileName))
{
/* is it current enough, or the file has been modified since our last time here? */
if (CompareFileTime(&FindFileData.ftLastWriteTime, &Info->ftCacheStamp) == 1)
{
/* recreate our cache, this is the slow path */
- RemoveEntryList(&Info->List);
- HeapFree(GetProcessHeap(), 0, Info);
+ InfoList.RemoveAt(LastListPosition);
+ delete Info;
+ break;
}
else
{
/* speedy path, compare directly, we already have the data */
goto skip_if_cached;
}
-
- break;
}
}
/* create a new entry */
- Info = (PAPPLICATION_INFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APPLICATION_INFO));
+ Info = new APPLICATION_INFO();
if (!Info)
break;
Info->Category = ParserGetInt(L"Category", FindFileData.cFileName);
+ Info->LicenseType = ParserGetLicenseType(FindFileData.cFileName);
+ Info->Languages = ParserGetAppLanguages(FindFileData.cFileName);
/* copy the cache-related fields for the next time */
- RtlCopyMemory(&Info->cFileName, &FindFileData.cFileName, MAX_PATH);
+ Info->cFileName = FindFileData.cFileName;
RtlCopyMemory(&Info->ftCacheStamp, &FindFileData.ftLastWriteTime, sizeof(FILETIME));
/* add our cached entry to the cached list */
- InsertTailList(&CachedEntriesHead, &Info->List);
-
- skip_if_cached:
+ InfoList.AddTail(Info);
+skip_if_cached:
if (Info->Category == FALSE)
continue;
/* if our cache hit was only partial, we need to parse
and lazily fill the rest of fields only when needed */
- if (Info->szUrlDownload[0] == 0)
+ if (Info->szUrlDownload.IsEmpty())
{
- if (!_GetString(L"Name", Info->szName, FindFileData.cFileName)
- || !_GetString(L"URLDownload", Info->szUrlDownload, FindFileData.cFileName))
+ if (!GetString(L"Name", Info->szName, FindFileData.cFileName)
+ || !GetString(L"URLDownload", Info->szUrlDownload, FindFileData.cFileName))
{
continue;
}
- _GetStringNullFailure(L"RegName", Info->szRegName, FindFileData.cFileName);
- _GetStringNullFailure(L"Version", Info->szVersion, FindFileData.cFileName);
- _GetStringNullFailure(L"License", Info->szLicense, FindFileData.cFileName);
- _GetStringNullFailure(L"Description", Info->szDesc, FindFileData.cFileName);
- _GetStringNullFailure(L"Size", Info->szSize, FindFileData.cFileName);
- _GetStringNullFailure(L"URLSite", Info->szUrlSite, FindFileData.cFileName);
- _GetStringNullFailure(L"CDPath", Info->szCDPath, FindFileData.cFileName);
- _GetStringNullFailure(L"SHA1", Info->szSHA1, FindFileData.cFileName);
+ GetString(L"RegName", Info->szRegName, FindFileData.cFileName);
+ GetString(L"Version", Info->szVersion, FindFileData.cFileName);
+ GetString(L"License", Info->szLicense, FindFileData.cFileName);
+ GetString(L"Description", Info->szDesc, FindFileData.cFileName);
+ GetString(L"Size", Info->szSize, FindFileData.cFileName);
+ GetString(L"URLSite", Info->szUrlSite, FindFileData.cFileName);
+ GetString(L"CDPath", Info->szCDPath, FindFileData.cFileName);
+ GetString(L"Language", Info->szRegName, FindFileData.cFileName);
+ GetString(L"SHA1", Info->szSHA1, FindFileData.cFileName);
}
if (!lpEnumProc(Info))
break;
- }
- while (FindNextFileW(hFind, &FindFileData) != 0);
+ } while (FindNextFileW(hFind, &FindFileData) != 0);
FindClose(hFind);
VOID FreeCachedAvailableEntries(VOID)
{
PAPPLICATION_INFO Info;
+ POSITION InfoListPosition = InfoList.GetHeadPosition();
/* loop and deallocate all the cached app infos in the list */
- for (pCachedEntry = CachedEntriesHead.Flink; pCachedEntry != &CachedEntriesHead;)
+ while (InfoListPosition)
{
- Info = CONTAINING_RECORD(pCachedEntry, APPLICATION_INFO, List);
-
- /* grab a reference to the next linked entry before getting rid of the current one */
- pCachedEntry = pCachedEntry->Flink;
-
- /* flush them down the toilet :D */
- RemoveEntryList(&Info->List);
- HeapFree(GetProcessHeap(), 0, Info);
+ Info = InfoList.GetAt(InfoListPosition);
+ InfoList.RemoveHead();
+ InfoListPosition = InfoList.GetHeadPosition();
+
+ delete Info;
}
}
\ No newline at end of file