* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/applications/rapps/available.c
* PURPOSE: Functions for working with availabled applications
- * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
+ * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
+ * Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
*/
#include "rapps.h"
+#define ADD_TEXT(a, b, c, d) \
+ if (b[0] != '\0') \
+ { \
+ LoadStringW(hInst, a, szText, _countof(szText)); \
+ InsertRichEditText(szText, c); \
+ InsertRichEditText(b, d); \
+ } \
+
+#define GET_STRING1(a, b) \
+ if (!ParserGetString(a, b, MAX_PATH, FindFileData.cFileName)) \
+ continue;
+
+#define GET_STRING2(a, b) \
+ if (!ParserGetString(a, b, MAX_PATH, FindFileData.cFileName)) \
+ b[0] = '\0';
+
+LIST_ENTRY CachedEntriesHead = { &CachedEntriesHead, &CachedEntriesHead };
+PLIST_ENTRY pCachedEntry = &CachedEntriesHead;
+
BOOL
ShowAvailableAppInfo(INT Index)
{
InsertRichEditText(L"\n", 0);
-#define ADD_TEXT(a, b, c, d) \
- if (b[0] != '\0') \
- { \
- LoadStringW(hInst, a, szText, sizeof(szText) / sizeof(WCHAR)); \
- InsertRichEditText(szText, c); \
- InsertRichEditText(b, d); \
- } \
-
- ADD_TEXT(IDS_AINFO_VERSION, Info->szVersion, CFE_BOLD, 0);
- ADD_TEXT(IDS_AINFO_LICENCE, Info->szLicence, CFE_BOLD, 0);
- ADD_TEXT(IDS_AINFO_SIZE, Info->szSize, CFE_BOLD, 0);
- ADD_TEXT(IDS_AINFO_URLSITE, Info->szUrlSite, CFE_BOLD, CFE_LINK);
- ADD_TEXT(IDS_AINFO_DESCRIPTION, Info->szDesc, CFE_BOLD, 0);
+ ADD_TEXT(IDS_AINFO_VERSION, Info->szVersion, CFE_BOLD, 0);
+ ADD_TEXT(IDS_AINFO_LICENSE, Info->szLicense, CFE_BOLD, 0);
+ ADD_TEXT(IDS_AINFO_SIZE, Info->szSize, CFE_BOLD, 0);
+ ADD_TEXT(IDS_AINFO_URLSITE, Info->szUrlSite, CFE_BOLD, CFE_LINK);
+ ADD_TEXT(IDS_AINFO_DESCRIPTION, Info->szDesc, CFE_BOLD, 0);
return TRUE;
}
WCHAR szSearchPath[MAX_PATH];
WCHAR szPath[MAX_PATH];
WCHAR szTmp[MAX_PATH];
+ HRESULT hr;
+ BOOL result = TRUE;
- if (!GetCurrentDirectoryW(MAX_PATH, szPath))
+ if (!GetStorageDirectory(szPath, _countof(szPath)))
return FALSE;
- swprintf(szCabPath, L"%s\\rappmgr.cab", szPath);
+ hr = StringCbPrintfW(szCabPath, sizeof(szCabPath),
+ L"%ls\\rappmgr.cab",
+ szPath);
+ if (FAILED(hr))
+ return FALSE;
- if (GetFileAttributesW(szCabPath) != INVALID_FILE_ATTRIBUTES)
- {
- if (!DeleteFileW(szCabPath))
- return FALSE;
- }
+ result = result && DeleteFileW(szCabPath);
- wcscat(szPath, L"\\rapps\\");
- swprintf(szSearchPath, L"%s*.txt", szPath);
+ hr = StringCbCatW(szPath, sizeof(szPath), L"\\rapps\\");
+
+ if (FAILED(hr))
+ return FALSE;
+
+ hr = StringCbPrintfW(szSearchPath, sizeof(szSearchPath),
+ L"%ls*.txt",
+ szPath);
+ if (FAILED(hr))
+ return FALSE;
hFind = FindFirstFileW(szSearchPath, &FindFileData);
+
if (hFind == INVALID_HANDLE_VALUE)
- return TRUE;
+ return result;
do
{
- swprintf(szTmp, L"%s%s", szPath, FindFileData.cFileName);
- if (!DeleteFileW(szTmp))
- {
- FindClose(hFind);
- return FALSE;
- }
- }
- while (FindNextFileW(hFind, &FindFileData) != 0);
+ hr = StringCbPrintfW(szTmp, sizeof(szTmp),
+ L"%ls%ls",
+ szPath, FindFileData.cFileName);
+ if (FAILED(hr))
+ continue;
+ result = result && DeleteFileW(szTmp);
+
+ } while (FindNextFileW(hFind, &FindFileData) != 0);
FindClose(hFind);
- return TRUE;
+ return result;
}
if (!DeleteCurrentAppsDB())
return FALSE;
- DownloadApplicationsDB(APPLICATION_DATEBASE_URL);
+ DownloadApplicationsDB(APPLICATION_DATABASE_URL);
- if (!GetCurrentDirectoryW(MAX_PATH, szPath))
+ if (!GetStorageDirectory(szPath, _countof(szPath)))
return FALSE;
- swprintf(szCabPath, L"%s\\rappmgr.cab", szPath);
+ if (FAILED(StringCbPrintfW(szCabPath, sizeof(szCabPath),
+ L"%ls\\rappmgr.cab",
+ szPath)))
+ {
+ return FALSE;
+ }
- wcscat(szPath, L"\\rapps\\");
- wcscpy(szAppsPath, szPath);
+ if (FAILED(StringCbPrintfW(szAppsPath, sizeof(szAppsPath),
+ L"%ls\\rapps\\",
+ szPath)))
+ {
+ return FALSE;
+ }
ExtractFilesFromCab(szCabPath, szAppsPath);
WIN32_FIND_DATAW FindFileData;
WCHAR szPath[MAX_PATH];
WCHAR szAppsPath[MAX_PATH];
- WCHAR szSectionLocale[MAX_PATH] = L"Section.";
WCHAR szCabPath[MAX_PATH];
- WCHAR szLocale[4 + 1];
- APPLICATION_INFO Info;
+ PAPPLICATION_INFO Info;
+ HRESULT hr;
- if (!GetCurrentDirectoryW(MAX_PATH, szPath))
- {
+ if (!GetStorageDirectory(szPath, _countof(szPath)))
+ return FALSE;
+
+ hr = StringCbPrintfW(szCabPath, sizeof(szCabPath),
+ L"%ls\\rappmgr.cab",
+ szPath);
+ if (FAILED(hr))
return FALSE;
- }
- swprintf(szCabPath, L"%s\\rappmgr.cab", szPath);
+ hr = StringCbCatW(szPath, sizeof(szPath), L"\\rapps\\");
+
+ if (FAILED(hr))
+ return FALSE;
- wcscat(szPath, L"\\rapps\\");
- wcscpy(szAppsPath, szPath);
+ hr = StringCbCopyW(szAppsPath, sizeof(szAppsPath), szPath);
+
+ if (FAILED(hr))
+ return FALSE;
if (!CreateDirectory(szPath, NULL) &&
GetLastError() != ERROR_ALREADY_EXISTS)
return FALSE;
}
- GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE, szLocale, sizeof(szLocale) / sizeof(WCHAR));
- wcscat(szSectionLocale, szLocale);
+ hr = StringCbCatW(szPath, sizeof(szPath), L"*.txt");
- wcscat(szPath, L"*.txt");
+ if (FAILED(hr))
+ return FALSE;
hFind = FindFirstFileW(szPath, &FindFileData);
+
if (hFind == INVALID_HANDLE_VALUE)
{
if (GetFileAttributesW(szCabPath) == INVALID_FILE_ATTRIBUTES)
- DownloadApplicationsDB(APPLICATION_DATEBASE_URL);
+ DownloadApplicationsDB(APPLICATION_DATABASE_URL);
ExtractFilesFromCab(szCabPath, szAppsPath);
hFind = FindFirstFileW(szPath, &FindFileData);
+
if (hFind == INVALID_HANDLE_VALUE)
return FALSE;
}
-#define GET_STRING1(a, b) \
- if (!ParserGetString(szSectionLocale, a, b, MAX_PATH, FindFileData.cFileName)) \
- if (!ParserGetString(L"Section", a, b, MAX_PATH, FindFileData.cFileName)) \
- continue;
-
-#define GET_STRING2(a, b) \
- if (!ParserGetString(szSectionLocale, a, b, MAX_PATH, FindFileData.cFileName)) \
- if (!ParserGetString(L"Section", a, b, MAX_PATH, FindFileData.cFileName)) \
- b[0] = '\0';
-
do
{
- Info.Category = ParserGetInt(szSectionLocale, L"Category", FindFileData.cFileName);
- if (Info.Category == -1)
+ /* loop for all the cached entries */
+ for (pCachedEntry = CachedEntriesHead.Flink; pCachedEntry != &CachedEntriesHead; pCachedEntry = pCachedEntry->Flink)
{
- Info.Category = ParserGetInt(L"Section", L"Category", FindFileData.cFileName);
- if (Info.Category == -1)
- continue;
+ Info = CONTAINING_RECORD(pCachedEntry, APPLICATION_INFO, List);
+
+ /* do we already have this entry in cache? */
+ if(_wcsicmp(FindFileData.cFileName, Info->cFileName) == 0)
+ {
+ /* 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);
+ }
+ else
+ {
+ /* speedy path, compare directly, we already have the data */
+ goto skip_if_cached;
+ }
+
+ break;
+ }
}
- if (EnumType != Info.Category && EnumType != ENUM_ALL_AVAILABLE) continue;
+ /* create a new entry */
+ Info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APPLICATION_INFO));
- GET_STRING1(L"Name", Info.szName);
- GET_STRING1(L"URLDownload", Info.szUrlDownload);
+ if(!Info)
+ break;
- GET_STRING2(L"RegName", Info.szRegName);
- GET_STRING2(L"Version", Info.szVersion);
- GET_STRING2(L"Licence", Info.szLicence);
- GET_STRING2(L"Description", Info.szDesc);
- GET_STRING2(L"Size", Info.szSize);
- GET_STRING2(L"URLSite", Info.szUrlSite);
- GET_STRING2(L"CDPath", Info.szCDPath);
+ Info->Category = ParserGetInt(L"Category", FindFileData.cFileName);
- if (!lpEnumProc(Info)) break;
- }
- while (FindNextFileW(hFind, &FindFileData) != 0);
+ /* copy the cache-related fields for the next time */
+ RtlCopyMemory(&Info->cFileName, &FindFileData.cFileName, MAX_PATH);
+ RtlCopyMemory(&Info->ftCacheStamp, &FindFileData.ftLastWriteTime, sizeof(FILETIME));
+
+ /* add our cached entry to the cached list */
+ InsertTailList(&CachedEntriesHead, &Info->List);
+
+skip_if_cached:
+
+ if (Info->Category == FALSE)
+ continue;
+
+ if (EnumType != Info->Category && EnumType != ENUM_ALL_AVAILABLE)
+ 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)
+ {
+ GET_STRING1(L"Name", Info->szName);
+ GET_STRING1(L"URLDownload", Info->szUrlDownload);
+
+ GET_STRING2(L"RegName", Info->szRegName);
+ GET_STRING2(L"Version", Info->szVersion);
+ GET_STRING2(L"License", Info->szLicense);
+ GET_STRING2(L"Description", Info->szDesc);
+ GET_STRING2(L"Size", Info->szSize);
+ GET_STRING2(L"URLSite", Info->szUrlSite);
+ GET_STRING2(L"CDPath", Info->szCDPath);
+ GET_STRING2(L"SHA1", Info->szSHA1);
+ }
+
+ if (!lpEnumProc(Info))
+ break;
+
+ } while (FindNextFileW(hFind, &FindFileData) != 0);
FindClose(hFind);
return TRUE;
}
+
+VOID FreeCachedAvailableEntries(VOID)
+{
+ PAPPLICATION_INFO Info;
+
+ /* loop and deallocate all the cached app infos in the list */
+ for (pCachedEntry = CachedEntriesHead.Flink; pCachedEntry != &CachedEntriesHead;)
+ {
+ 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);
+ }
+}
\ No newline at end of file