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_IsInstalled(FALSE
), m_HasLanguageInfo(FALSE
), m_HasInstalledVersion(FALSE
), m_Parser(sFileNameParam
)
24 m_LicenseType
= LICENSE_NONE
;
26 m_sFileName
= sFileNameParam
;
28 RetrieveGeneralInfo();
31 VOID
CAvailableApplicationInfo::RefreshAppInfo()
33 if (m_szUrlDownload
.IsEmpty())
35 RetrieveGeneralInfo();
39 // Lazily load general info from the file
40 VOID
CAvailableApplicationInfo::RetrieveGeneralInfo()
42 m_Category
= m_Parser
.GetInt(L
"Category");
44 if (!GetString(L
"Name", m_szName
)
45 || !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();
69 VOID
CAvailableApplicationInfo::RetrieveInstalledStatus()
71 m_IsInstalled
= ::GetInstalledVersion(NULL
, m_szRegName
)
72 || ::GetInstalledVersion(NULL
, m_szName
);
75 VOID
CAvailableApplicationInfo::RetrieveInstalledVersion()
77 ATL::CStringW szNameVersion
;
78 szNameVersion
= m_szName
+ L
" " + m_szVersion
;
79 m_HasInstalledVersion
= ::GetInstalledVersion(&m_szInstalledVersion
, m_szRegName
)
80 || ::GetInstalledVersion(&m_szInstalledVersion
, m_szName
)
81 || ::GetInstalledVersion(&m_szInstalledVersion
, szNameVersion
);
84 VOID
CAvailableApplicationInfo::RetrieveLanguages()
86 const WCHAR cDelimiter
= L
'|';
87 ATL::CStringW szBuffer
;
89 // TODO: Get multiline parameter
90 if (!m_Parser
.GetString(L
"Languages", szBuffer
))
92 m_HasLanguageInfo
= FALSE
;
96 // Parse parameter string
97 ATL::CStringW m_szLocale
;
99 for (INT i
= 0; szBuffer
[i
] != UNICODE_NULL
; ++i
)
101 if (szBuffer
[i
] != cDelimiter
&& szBuffer
[i
] != L
'\n')
103 m_szLocale
+= szBuffer
[i
];
107 if (StrToIntExW(m_szLocale
.GetString(), STIF_DEFAULT
, &iLCID
))
109 m_LanguageLCIDs
.Add(static_cast<LCID
>(iLCID
));
115 // For the text after delimiter
116 if (!m_szLocale
.IsEmpty())
118 if (StrToIntExW(m_szLocale
.GetString(), STIF_DEFAULT
, &iLCID
))
120 m_LanguageLCIDs
.Add(static_cast<LCID
>(iLCID
));
124 m_HasLanguageInfo
= TRUE
;
127 VOID
CAvailableApplicationInfo::RetrieveLicenseType()
129 INT IntBuffer
= m_Parser
.GetInt(L
"LicenseType");
131 if (IsLicenseType(IntBuffer
))
133 m_LicenseType
= static_cast<LicenseType
>(IntBuffer
);
137 m_LicenseType
= LICENSE_NONE
;
141 BOOL
CAvailableApplicationInfo::FindInLanguages(LCID what
) const
143 if (!m_HasLanguageInfo
)
148 //Find locale code in the list
149 const INT nLanguagesSize
= m_LanguageLCIDs
.GetSize();
150 for (INT i
= 0; i
< nLanguagesSize
; ++i
)
152 if (m_LanguageLCIDs
[i
] == what
)
161 BOOL
CAvailableApplicationInfo::HasLanguageInfo() const
163 return m_HasLanguageInfo
;
166 BOOL
CAvailableApplicationInfo::HasNativeLanguage() const
168 return FindInLanguages(GetUserDefaultLCID());
171 BOOL
CAvailableApplicationInfo::HasEnglishLanguage() const
173 return FindInLanguages(MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
));
176 BOOL
CAvailableApplicationInfo::IsInstalled() const
178 return m_IsInstalled
;
181 BOOL
CAvailableApplicationInfo::HasInstalledVersion() const
183 return m_HasInstalledVersion
;
186 BOOL
CAvailableApplicationInfo::HasUpdate() const
188 return (m_szInstalledVersion
.Compare(m_szVersion
) < 0) ? TRUE
: FALSE
;
191 VOID
CAvailableApplicationInfo::SetLastWriteTime(FILETIME
* ftTime
)
193 RtlCopyMemory(&m_ftCacheStamp
, ftTime
, sizeof(FILETIME
));
196 inline BOOL
CAvailableApplicationInfo::GetString(LPCWSTR lpKeyName
, ATL::CStringW
& ReturnedString
)
198 if (!m_Parser
.GetString(lpKeyName
, ReturnedString
))
200 ReturnedString
.Empty();
205 // CAvailableApplicationInfo
208 ATL::CStringW
CAvailableApps::m_szPath
;
209 ATL::CStringW
CAvailableApps::m_szCabPath
;
210 ATL::CStringW
CAvailableApps::m_szAppsPath
;
211 ATL::CStringW
CAvailableApps::m_szSearchPath
;
213 BOOL
CAvailableApps::InitializeStaticStrings()
216 if (!m_szPath
.IsEmpty())
218 // strings are filled
222 //FIXME: maybe provide a fallback?
223 if (GetStorageDirectory(m_szPath
))
225 m_szAppsPath
= m_szPath
+ L
"\\rapps\\";
226 m_szCabPath
= m_szPath
+ L
"\\rappmgr.cab";
227 m_szSearchPath
= m_szAppsPath
+ L
"*.txt";
234 CAvailableApps::CAvailableApps()
237 InitializeStaticStrings();
240 VOID
CAvailableApps::FreeCachedEntries()
242 POSITION InfoListPosition
= m_InfoList
.GetHeadPosition();
244 /* loop and deallocate all the cached app infos in the list */
245 while (InfoListPosition
)
247 CAvailableApplicationInfo
* Info
= m_InfoList
.GetNext(InfoListPosition
);
251 m_InfoList
.RemoveAll();
254 VOID
CAvailableApps::DeleteCurrentAppsDB()
256 HANDLE hFind
= INVALID_HANDLE_VALUE
;
257 WIN32_FIND_DATAW FindFileData
;
259 if (!InitializeStaticStrings())
264 hFind
= FindFirstFileW(m_szSearchPath
.GetString(), &FindFileData
);
266 if (hFind
!= INVALID_HANDLE_VALUE
)
271 szTmp
= m_szAppsPath
+ FindFileData
.cFileName
;
272 DeleteFileW(szTmp
.GetString());
273 } while (FindNextFileW(hFind
, &FindFileData
) != 0);
277 RemoveDirectoryW(m_szAppsPath
);
278 RemoveDirectoryW(m_szPath
);
281 BOOL
CAvailableApps::UpdateAppsDB()
283 HANDLE hFind
= INVALID_HANDLE_VALUE
;
284 WIN32_FIND_DATAW FindFileData
;
286 if (!InitializeStaticStrings())
291 if (!CreateDirectoryW(m_szPath
.GetString(), NULL
) && GetLastError() != ERROR_ALREADY_EXISTS
)
296 //if there are some files in the db folder - we're good
297 hFind
= FindFirstFileW(m_szSearchPath
.GetString(), &FindFileData
);
298 if (hFind
!= INVALID_HANDLE_VALUE
)
304 CDownloadManager::DownloadApplicationsDB(APPLICATION_DATABASE_URL
);
306 if (!ExtractFilesFromCab(m_szCabPath
, m_szAppsPath
))
311 DeleteFileW(m_szCabPath
.GetString());
316 BOOL
CAvailableApps::ForceUpdateAppsDB()
318 DeleteCurrentAppsDB();
319 return UpdateAppsDB();
322 BOOL
CAvailableApps::Enum(INT EnumType
, AVAILENUMPROC lpEnumProc
)
325 HANDLE hFind
= INVALID_HANDLE_VALUE
;
326 WIN32_FIND_DATAW FindFileData
;
328 hFind
= FindFirstFileW(m_szSearchPath
.GetString(), &FindFileData
);
330 if (hFind
== INVALID_HANDLE_VALUE
)
338 // loop for all the cached entries
339 POSITION CurrentListPosition
= m_InfoList
.GetHeadPosition();
340 CAvailableApplicationInfo
* Info
= NULL
;
342 while (CurrentListPosition
!= NULL
)
344 POSITION LastListPosition
= CurrentListPosition
;
345 Info
= m_InfoList
.GetNext(CurrentListPosition
);
347 // do we already have this entry in cache?
348 if (Info
->m_sFileName
== FindFileData
.cFileName
)
350 // is it current enough, or the file has been modified since our last time here?
351 if (CompareFileTime(&FindFileData
.ftLastWriteTime
, &Info
->m_ftCacheStamp
) == 1)
353 // recreate our cache, this is the slow path
354 m_InfoList
.RemoveAt(LastListPosition
);
362 // speedy path, compare directly, we already have the data
368 // create a new entry
369 Info
= new CAvailableApplicationInfo(FindFileData
.cFileName
);
371 // set a timestamp for the next time
372 Info
->SetLastWriteTime(&FindFileData
.ftLastWriteTime
);
373 m_InfoList
.AddTail(Info
);
376 if (Info
->m_Category
== FALSE
)
379 if (EnumType
!= Info
->m_Category
&& EnumType
!= ENUM_ALL_AVAILABLE
)
382 Info
->RefreshAppInfo();
385 lpEnumProc(static_cast<CAvailableApplicationInfo
*>(Info
), m_szAppsPath
.GetString());
387 } while (FindNextFileW(hFind
, &FindFileData
) != 0);
393 CAvailableApplicationInfo
* CAvailableApps::FindInfo(const ATL::CStringW
& szAppName
) const
395 if (m_InfoList
.IsEmpty())
401 POSITION CurrentListPosition
= m_InfoList
.GetHeadPosition();
402 CAvailableApplicationInfo
* info
;
403 while (CurrentListPosition
!= NULL
)
405 info
= m_InfoList
.GetNext(CurrentListPosition
);
406 if (info
->m_szName
== szAppName
)
414 ATL::CSimpleArray
<CAvailableApplicationInfo
> CAvailableApps::FindInfoList(const ATL::CSimpleArray
<ATL::CStringW
> &arrAppsNames
) const
416 ATL::CSimpleArray
<CAvailableApplicationInfo
> result
;
417 for (INT i
= 0; i
< arrAppsNames
.GetSize(); ++i
)
419 CAvailableApplicationInfo
* Info
= FindInfo(arrAppsNames
[i
]);
428 const ATL::CStringW
& CAvailableApps::GetFolderPath() const
433 const ATL::CStringW
& CAvailableApps::GetAppPath() const
438 const ATL::CStringW
& CAvailableApps::GetCabPath() const
443 LPCWSTR
CAvailableApps::GetFolderPathString() const
445 return m_szPath
.GetString();
448 LPCWSTR
CAvailableApps::GetAppPathString() const
450 return m_szPath
.GetString();
453 LPCWSTR
CAvailableApps::GetCabPathString() const
455 return m_szPath
.GetString();