2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * FILE: base/applications/rapps/available.cpp
5 * PURPOSE: Classes for working with available applications
6 * COPYRIGHT: Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org)
7 * Copyright 2015 Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
8 * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
12 #include "available.h"
17 #include <atlsimpcoll.h>
20 // CAvailableApplicationInfo
21 CAvailableApplicationInfo::CAvailableApplicationInfo(const ATL::CStringW
& sFileNameParam
)
22 : m_IsSelected(FALSE
), m_LicenseType(LICENSE_NONE
), m_sFileName(sFileNameParam
),
23 m_IsInstalled(FALSE
), m_HasLanguageInfo(FALSE
), m_HasInstalledVersion(FALSE
)
25 RetrieveGeneralInfo();
28 VOID
CAvailableApplicationInfo::RefreshAppInfo()
30 if (m_szUrlDownload
.IsEmpty())
32 RetrieveGeneralInfo();
36 // Lazily load general info from the file
37 VOID
CAvailableApplicationInfo::RetrieveGeneralInfo()
39 m_Parser
= new CConfigParser(m_sFileName
);
41 m_Category
= m_Parser
->GetInt(L
"Category");
43 if (!GetString(L
"Name", m_szName
)
44 || !GetString(L
"URLDownload", m_szUrlDownload
))
50 GetString(L
"RegName", m_szRegName
);
51 GetString(L
"Version", m_szVersion
);
52 GetString(L
"License", m_szLicense
);
53 GetString(L
"Description", m_szDesc
);
54 GetString(L
"Size", m_szSize
);
55 GetString(L
"URLSite", m_szUrlSite
);
56 GetString(L
"CDPath", m_szCDPath
);
57 GetString(L
"Language", m_szRegName
);
58 GetString(L
"SHA1", m_szSHA1
);
60 RetrieveLicenseType();
62 RetrieveInstalledStatus();
65 RetrieveInstalledVersion();
71 VOID
CAvailableApplicationInfo::RetrieveInstalledStatus()
73 m_IsInstalled
= ::GetInstalledVersion(NULL
, m_szRegName
)
74 || ::GetInstalledVersion(NULL
, m_szName
);
77 VOID
CAvailableApplicationInfo::RetrieveInstalledVersion()
79 ATL::CStringW szNameVersion
;
80 szNameVersion
= m_szName
+ L
" " + m_szVersion
;
81 m_HasInstalledVersion
= ::GetInstalledVersion(&m_szInstalledVersion
, m_szRegName
)
82 || ::GetInstalledVersion(&m_szInstalledVersion
, m_szName
)
83 || ::GetInstalledVersion(&m_szInstalledVersion
, szNameVersion
);
86 VOID
CAvailableApplicationInfo::RetrieveLanguages()
88 const WCHAR cDelimiter
= L
'|';
89 ATL::CStringW szBuffer
;
91 // TODO: Get multiline parameter
92 if (!m_Parser
->GetString(L
"Languages", szBuffer
))
94 m_HasLanguageInfo
= FALSE
;
98 // Parse parameter string
99 ATL::CStringW m_szLocale
;
101 for (INT i
= 0; szBuffer
[i
] != UNICODE_NULL
; ++i
)
103 if (szBuffer
[i
] != cDelimiter
&& szBuffer
[i
] != L
'\n')
105 m_szLocale
+= szBuffer
[i
];
109 if (StrToIntExW(m_szLocale
.GetString(), STIF_DEFAULT
, &iLCID
))
111 m_LanguageLCIDs
.Add(static_cast<LCID
>(iLCID
));
117 // For the text after delimiter
118 if (!m_szLocale
.IsEmpty())
120 if (StrToIntExW(m_szLocale
.GetString(), STIF_DEFAULT
, &iLCID
))
122 m_LanguageLCIDs
.Add(static_cast<LCID
>(iLCID
));
126 m_HasLanguageInfo
= TRUE
;
129 VOID
CAvailableApplicationInfo::RetrieveLicenseType()
131 INT IntBuffer
= m_Parser
->GetInt(L
"LicenseType");
133 if (IsLicenseType(IntBuffer
))
135 m_LicenseType
= static_cast<LicenseType
>(IntBuffer
);
139 m_LicenseType
= LICENSE_NONE
;
143 BOOL
CAvailableApplicationInfo::FindInLanguages(LCID what
) const
145 if (!m_HasLanguageInfo
)
150 //Find locale code in the list
151 const INT nLanguagesSize
= m_LanguageLCIDs
.GetSize();
152 for (INT i
= 0; i
< nLanguagesSize
; ++i
)
154 if (m_LanguageLCIDs
[i
] == what
)
163 BOOL
CAvailableApplicationInfo::HasLanguageInfo() const
165 return m_HasLanguageInfo
;
168 BOOL
CAvailableApplicationInfo::HasNativeLanguage() const
170 return FindInLanguages(GetUserDefaultLCID());
173 BOOL
CAvailableApplicationInfo::HasEnglishLanguage() const
175 return FindInLanguages(MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
));
178 BOOL
CAvailableApplicationInfo::IsInstalled() const
180 return m_IsInstalled
;
183 BOOL
CAvailableApplicationInfo::HasInstalledVersion() const
185 return m_HasInstalledVersion
;
188 BOOL
CAvailableApplicationInfo::HasUpdate() const
190 return (m_szInstalledVersion
.Compare(m_szVersion
) < 0) ? TRUE
: FALSE
;
193 VOID
CAvailableApplicationInfo::SetLastWriteTime(FILETIME
* ftTime
)
195 RtlCopyMemory(&m_ftCacheStamp
, ftTime
, sizeof(FILETIME
));
198 inline BOOL
CAvailableApplicationInfo::GetString(LPCWSTR lpKeyName
, ATL::CStringW
& ReturnedString
)
200 if (!m_Parser
->GetString(lpKeyName
, ReturnedString
))
202 ReturnedString
.Empty();
207 // CAvailableApplicationInfo
210 AvailableStrings::AvailableStrings()
212 //FIXME: maybe provide a fallback?
213 if (GetStorageDirectory(szPath
))
215 szAppsPath
= szPath
+ L
"\\rapps\\";
216 szCabName
= L
"rappmgr.cab";
218 szCabPath
= (szCabDir
+ L
"\\") + szCabName
;
219 szSearchPath
= szAppsPath
+ L
"*.txt";
225 AvailableStrings
CAvailableApps::m_Strings
;
227 CAvailableApps::CAvailableApps()
231 VOID
CAvailableApps::FreeCachedEntries()
233 POSITION InfoListPosition
= m_InfoList
.GetHeadPosition();
235 /* loop and deallocate all the cached app infos in the list */
236 while (InfoListPosition
)
238 CAvailableApplicationInfo
* Info
= m_InfoList
.GetNext(InfoListPosition
);
242 m_InfoList
.RemoveAll();
245 VOID
CAvailableApps::DeleteCurrentAppsDB()
247 HANDLE hFind
= INVALID_HANDLE_VALUE
;
248 WIN32_FIND_DATAW FindFileData
;
250 hFind
= FindFirstFileW(m_Strings
.szSearchPath
.GetString(), &FindFileData
);
252 if (hFind
!= INVALID_HANDLE_VALUE
)
257 szTmp
= m_Strings
.szAppsPath
+ FindFileData
.cFileName
;
258 DeleteFileW(szTmp
.GetString());
259 } while (FindNextFileW(hFind
, &FindFileData
) != 0);
263 RemoveDirectoryW(m_Strings
.szAppsPath
);
264 RemoveDirectoryW(m_Strings
.szPath
);
267 BOOL
CAvailableApps::UpdateAppsDB()
269 HANDLE hFind
= INVALID_HANDLE_VALUE
;
270 WIN32_FIND_DATAW FindFileData
;
272 if (!CreateDirectoryW(m_Strings
.szPath
, NULL
) && GetLastError() != ERROR_ALREADY_EXISTS
)
277 //if there are some files in the db folder - we're good
278 hFind
= FindFirstFileW(m_Strings
.szSearchPath
, &FindFileData
);
279 if (hFind
!= INVALID_HANDLE_VALUE
)
285 CDownloadManager::DownloadApplicationsDB(APPLICATION_DATABASE_URL
);
287 if (!ExtractFilesFromCab(m_Strings
.szCabName
,
289 m_Strings
.szAppsPath
))
294 DeleteFileW(m_Strings
.szCabPath
);
299 BOOL
CAvailableApps::ForceUpdateAppsDB()
301 DeleteCurrentAppsDB();
302 return UpdateAppsDB();
305 BOOL
CAvailableApps::Enum(INT EnumType
, AVAILENUMPROC lpEnumProc
)
308 HANDLE hFind
= INVALID_HANDLE_VALUE
;
309 WIN32_FIND_DATAW FindFileData
;
311 hFind
= FindFirstFileW(m_Strings
.szSearchPath
.GetString(), &FindFileData
);
313 if (hFind
== INVALID_HANDLE_VALUE
)
321 // loop for all the cached entries
322 POSITION CurrentListPosition
= m_InfoList
.GetHeadPosition();
323 CAvailableApplicationInfo
* Info
= NULL
;
325 while (CurrentListPosition
!= NULL
)
327 POSITION LastListPosition
= CurrentListPosition
;
328 Info
= m_InfoList
.GetNext(CurrentListPosition
);
330 // do we already have this entry in cache?
331 if (Info
->m_sFileName
== FindFileData
.cFileName
)
333 // is it current enough, or the file has been modified since our last time here?
334 if (CompareFileTime(&FindFileData
.ftLastWriteTime
, &Info
->m_ftCacheStamp
) == 1)
336 // recreate our cache, this is the slow path
337 m_InfoList
.RemoveAt(LastListPosition
);
345 // speedy path, compare directly, we already have the data
351 // create a new entry
352 Info
= new CAvailableApplicationInfo(FindFileData
.cFileName
);
354 // set a timestamp for the next time
355 Info
->SetLastWriteTime(&FindFileData
.ftLastWriteTime
);
356 m_InfoList
.AddTail(Info
);
359 if (EnumType
== Info
->m_Category
360 || EnumType
== ENUM_ALL_AVAILABLE
361 || (EnumType
== ENUM_CAT_SELECTED
&& Info
->m_IsSelected
))
363 Info
->RefreshAppInfo();
366 lpEnumProc(Info
, m_Strings
.szAppsPath
.GetString());
368 } while (FindNextFileW(hFind
, &FindFileData
) != 0);
374 CAvailableApplicationInfo
* CAvailableApps::FindInfo(const ATL::CStringW
& szAppName
) const
376 if (m_InfoList
.IsEmpty())
382 POSITION CurrentListPosition
= m_InfoList
.GetHeadPosition();
383 CAvailableApplicationInfo
* info
;
384 while (CurrentListPosition
!= NULL
)
386 info
= m_InfoList
.GetNext(CurrentListPosition
);
387 if (info
->m_szName
== szAppName
)
395 ATL::CSimpleArray
<CAvailableApplicationInfo
> CAvailableApps::FindInfoList(const ATL::CSimpleArray
<ATL::CStringW
> &arrAppsNames
) const
397 ATL::CSimpleArray
<CAvailableApplicationInfo
> result
;
398 for (INT i
= 0; i
< arrAppsNames
.GetSize(); ++i
)
400 CAvailableApplicationInfo
* Info
= FindInfo(arrAppsNames
[i
]);
409 ATL::CSimpleArray
<CAvailableApplicationInfo
> CAvailableApps::GetSelected() const
411 ATL::CSimpleArray
<CAvailableApplicationInfo
> result
;
412 POSITION CurrentListPosition
= m_InfoList
.GetHeadPosition();
413 CAvailableApplicationInfo
* Info
;
415 while (CurrentListPosition
!= NULL
)
417 Info
= m_InfoList
.GetNext(CurrentListPosition
);
418 if (Info
->m_IsSelected
)
426 const ATL::CStringW
& CAvailableApps::GetFolderPath() const
428 return m_Strings
.szPath
;
431 const ATL::CStringW
& CAvailableApps::GetAppPath() const
433 return m_Strings
.szAppsPath
;
436 const ATL::CStringW
& CAvailableApps::GetCabPath() const
438 return m_Strings
.szCabPath
;