[RAPPS] Update check, license type
[reactos.git] / reactos / base / applications / rapps / available.cpp
index 279029c..66277d2 100644 (file)
@@ -9,39 +9,43 @@
 
 #include "rapps.h"
 
-
-template<typename T, size_t N, size_t N2>
-inline void _AddText(T (&szText)[N], UINT a, T (&b)[N2], DWORD c, DWORD d) {
-  if (b[0] != '\0') 
-  {
-      LoadStringW(hInst, a, szText, N); 
-      InsertRichEditText(szText, c); 
-      InsertRichEditText(b, d); 
-  }
+inline void _AddText(UINT a, LPCWSTR b, DWORD c, DWORD d)
+{
+    if (b[0] != '\0')
+    {
+        WCHAR szText[MAX_STR_LEN];
+        LoadStringW(hInst, a, szText, _countof(szText));
+        InsertRichEditText(szText, c);
+        InsertRichEditText(b, d);
+    }
 }
 
-template<typename T, size_t N>
-inline void _AddTextNewl(T (&szText)[N], UINT a, DWORD b) {
-    LoadStringW(hInst, a, szText, N);
+inline void _AddTextNewl(UINT a, DWORD b)
+{
+    WCHAR szText[MAX_STR_LEN];
+    LoadStringW(hInst, a, szText, _countof(szText));
     InsertRichEditText(L"\n", 0);
     InsertRichEditText(szText, b);
     InsertRichEditText(L"\n", 0);
 }
 
 template<typename T, size_t N, size_t N2>
-inline BOOL _GetString(LPCWSTR a, T(&b)[N], T (&cFileName)[N2]) {
-  return ParserGetString(a, b, N, cFileName);
+inline BOOL _GetString(LPCWSTR a, T(&b)[N], T(&cFileName)[N2])
+{
+    return ParserGetString(a, b, N, cFileName);
 }
 
 template<typename T, size_t N, size_t N2>
-inline void _GetStringNullFailure(LPCWSTR a, T(&b)[N], T (&cFileName)[N2]) {
-  if (!_GetString(a, b, cFileName)) {
-    b[0] = '\0';
-  }
+inline void _GetStringNullFailure(LPCWSTR a, T(&b)[N], T(&cFileName)[N2])
+{
+    if (!_GetString(a, b, cFileName))
+    {
+        b[0] = '\0';
+    }
 }
 
 //App is "installed" if the RegName or Name is in the registry
-inline bool _AppInstallCheckKey(PAPPLICATION_INFO Info, REGSAM key)
+inline BOOL _AppInstallCheckWithKey(PAPPLICATION_INFO Info, REGSAM key)
 {
     return (*Info->szRegName
         && (IsInstalledApplication(Info->szRegName, TRUE, key)
@@ -53,38 +57,93 @@ inline bool _AppInstallCheckKey(PAPPLICATION_INFO Info, REGSAM key)
 
 //Check both registry keys in 64bit system
 //TODO: check system type beforehand to avoid double checks?
-inline bool _AppInstallCheck(PAPPLICATION_INFO Info) {
-  return  _AppInstallCheckKey(Info, KEY_WOW64_32KEY) 
-    || _AppInstallCheckKey(Info, KEY_WOW64_64KEY);
+inline BOOL _AppInstallCheck(PAPPLICATION_INFO Info)
+{
+    return  _AppInstallCheckWithKey(Info, KEY_WOW64_32KEY)
+        || _AppInstallCheckWithKey(Info, KEY_WOW64_64KEY);
 }
 
+//App is "installed" if the RegName or Name is in the registry
+inline BOOL _GetInstalledVersionWithKey(PAPPLICATION_INFO Info, LPWSTR szVersion, UINT iVersionSize, REGSAM key)
+{
+    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)));
+}
+
+//App is "installed" if the RegName or Name is in the registry
+inline BOOL _GetInstalledVersion(PAPPLICATION_INFO Info, LPWSTR szVersion, UINT iVersionSize)
+{
+    return  _GetInstalledVersionWithKey(Info, szVersion, iVersionSize, KEY_WOW64_32KEY)
+        || _GetInstalledVersionWithKey(Info, szVersion, iVersionSize, KEY_WOW64_64KEY);
+}
 
-LIST_ENTRY CachedEntriesHead = { &CachedEntriesHead, &CachedEntriesHead };
+LIST_ENTRY CachedEntriesHead = {&CachedEntriesHead, &CachedEntriesHead};
 PLIST_ENTRY pCachedEntry = &CachedEntriesHead;
 
 BOOL
 ShowAvailableAppInfo(INT Index)
 {
     PAPPLICATION_INFO Info = (PAPPLICATION_INFO) ListViewGetlParam(Index);
-    WCHAR szText[MAX_STR_LEN];
+    WCHAR szVersion[MAX_PATH] = L"\0";
+    WCHAR szLicense[MAX_PATH] = L"\0";
+    BOOL bIsInstalled = _AppInstallCheck(Info), 
+        bHasVersion = _GetInstalledVersion(Info, szVersion, _countof(szVersion));
 
     if (!Info) return FALSE;
 
     NewRichEditText(Info->szName, CFE_BOLD);
-    if (_AppInstallCheck(Info))
+    //installed status
+    if (bIsInstalled)
     {
-      _AddTextNewl(szText, IDS_STATUS_INSTALLED, CFE_ITALIC);
-    } else 
-    {
-      _AddTextNewl(szText, IDS_STATUS_NOTINSTALLED, CFE_ITALIC);
+        if (bHasVersion)
+        {
+            if (CompareVersionsStrings(Info->szVersion, szVersion))
+                _AddTextNewl(IDS_STATUS_UPDATE_AVAILABLE, CFE_ITALIC);
+            else
+                _AddTextNewl(IDS_STATUS_INSTALLED, CFE_ITALIC);
+
+            _AddText(IDS_AINFO_VERSION, szVersion, CFE_BOLD, 0);
+        } 
+        else
+            _AddTextNewl(IDS_STATUS_INSTALLED, CFE_ITALIC);
+
     }
+    else
+        _AddTextNewl(IDS_STATUS_NOTINSTALLED, CFE_ITALIC);
+
 
-    _AddText(szText, IDS_AINFO_VERSION,     Info->szVersion, CFE_BOLD, 0);
-    _AddText(szText, IDS_AINFO_LICENSE,     Info->szLicense, CFE_BOLD, 0);
-    _AddText(szText, IDS_AINFO_SIZE,        Info->szSize,    CFE_BOLD, 0);
-    _AddText(szText, IDS_AINFO_URLSITE,     Info->szUrlSite, CFE_BOLD, CFE_LINK);
-    _AddText(szText, IDS_AINFO_DESCRIPTION, Info->szDesc,    CFE_BOLD, 0);
-    _AddText(szText, IDS_AINFO_URLDOWNLOAD, Info->szUrlDownload, CFE_BOLD, CFE_LINK);
+    _AddText(IDS_AINFO_AVAILABLEVERSION, Info->szVersion, CFE_BOLD, 0);
+    //license
+    switch (Info->LicenseType)
+    {
+        case LICENSE_TYPE::OpenSource:
+            LoadStringW(hInst, IDS_LICENSE_OPENSOURCE, szLicense, _countof(szLicense));
+            break;
+        case LICENSE_TYPE::Freeware:
+            LoadStringW(hInst, IDS_LICENSE_FREEWARE, szLicense, _countof(szLicense));
+            break;
+        case LICENSE_TYPE::Trial:
+            LoadStringW(hInst, IDS_LICENSE_TRIAL, szLicense, _countof(szLicense));
+            break;
+        default:
+            break;
+    }
+    if (szLicense[0] != '\0')
+    {
+        StringCbPrintfW(szLicense, _countof(szLicense), L"%ls (%ls)", szLicense, Info->szLicense);
+        _AddText(IDS_AINFO_LICENSE, szLicense, CFE_BOLD, 0);
+    }
+    else
+    {
+        _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);
 
     return TRUE;
 }
@@ -105,8 +164,8 @@ DeleteCurrentAppsDB(VOID)
         return FALSE;
 
     hr = StringCbPrintfW(szCabPath, sizeof(szCabPath),
-                         L"%ls\\rappmgr.cab",
-                         szPath);
+        L"%ls\\rappmgr.cab",
+        szPath);
     if (FAILED(hr))
         return FALSE;
 
@@ -118,8 +177,8 @@ DeleteCurrentAppsDB(VOID)
         return FALSE;
 
     hr = StringCbPrintfW(szSearchPath, sizeof(szSearchPath),
-                         L"%ls*.txt",
-                         szPath);
+        L"%ls*.txt",
+        szPath);
     if (FAILED(hr))
         return FALSE;
 
@@ -131,13 +190,14 @@ DeleteCurrentAppsDB(VOID)
     do
     {
         hr = StringCbPrintfW(szTmp, sizeof(szTmp),
-                             L"%ls%ls",
-                             szPath, FindFileData.cFileName);
+            L"%ls%ls",
+            szPath, FindFileData.cFileName);
         if (FAILED(hr))
             continue;
         result = result && DeleteFileW(szTmp);
 
-    } while (FindNextFileW(hFind, &FindFileData) != 0);
+    }
+    while (FindNextFileW(hFind, &FindFileData) != 0);
 
     FindClose(hFind);
 
@@ -161,15 +221,15 @@ UpdateAppsDB(VOID)
         return FALSE;
 
     if (FAILED(StringCbPrintfW(szCabPath, sizeof(szCabPath),
-                               L"%ls\\rappmgr.cab",
-                               szPath)))
+        L"%ls\\rappmgr.cab",
+        szPath)))
     {
         return FALSE;
     }
 
     if (FAILED(StringCbPrintfW(szAppsPath, sizeof(szAppsPath),
-                               L"%ls\\rapps\\",
-                               szPath)))
+        L"%ls\\rapps\\",
+        szPath)))
     {
         return FALSE;
     }
@@ -195,8 +255,8 @@ EnumAvailableApplications(INT EnumType, AVAILENUMPROC lpEnumProc)
         return FALSE;
 
     hr = StringCbPrintfW(szCabPath, sizeof(szCabPath),
-                         L"%ls\\rappmgr.cab",
-                         szPath);
+        L"%ls\\rappmgr.cab",
+        szPath);
     if (FAILED(hr))
         return FALSE;
 
@@ -243,7 +303,7 @@ EnumAvailableApplications(INT EnumType, AVAILENUMPROC lpEnumProc)
             Info = CONTAINING_RECORD(pCachedEntry, APPLICATION_INFO, List);
 
             /* do we already have this entry in cache? */
-            if(_wcsicmp(FindFileData.cFileName, Info->cFileName) == 0)
+            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)
@@ -263,21 +323,26 @@ EnumAvailableApplications(INT EnumType, AVAILENUMPROC lpEnumProc)
         }
 
         /* create a new entry */
-        Info = (PAPPLICATION_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APPLICATION_INFO));
+        Info = (PAPPLICATION_INFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APPLICATION_INFO));
 
-        if(!Info)
+        if (!Info)
             break;
 
         Info->Category = ParserGetInt(L"Category", FindFileData.cFileName);
+        INT IntBuffer = ParserGetInt(L"LicenseType", FindFileData.cFileName);
+        if (IntBuffer < LICENSE_TYPE::Max)
+        {
+            Info->LicenseType = (LICENSE_TYPE) IntBuffer;
+        }
 
         /* copy the cache-related fields for the next time */
-        RtlCopyMemory(&Info->cFileName,    &FindFileData.cFileName, MAX_PATH);
+        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:
+    skip_if_cached:
 
         if (Info->Category == FALSE)
             continue;
@@ -290,26 +355,28 @@ skip_if_cached:
 
         if (Info->szUrlDownload[0] == 0)
         {
-          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);
+            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"Language", Info->szRegName, FindFileData.cFileName);
+            _GetStringNullFailure(L"SHA1", Info->szSHA1, FindFileData.cFileName);
         }
 
         if (!lpEnumProc(Info))
             break;
 
-    } while (FindNextFileW(hFind, &FindFileData) != 0);
+    }
+    while (FindNextFileW(hFind, &FindFileData) != 0);
 
     FindClose(hFind);
 
@@ -318,16 +385,16 @@ skip_if_cached:
 
 VOID FreeCachedAvailableEntries(VOID)
 {
-     PAPPLICATION_INFO Info;
+    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);
+        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);