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
)
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_Parser
= new CConfigParser(m_sFileName
);
44 m_Category
= m_Parser
->GetInt(L
"Category");
46 if (!GetString(L
"Name", m_szName
)
47 || !GetString(L
"URLDownload", m_szUrlDownload
))
53 GetString(L
"RegName", m_szRegName
);
54 GetString(L
"Version", m_szVersion
);
55 GetString(L
"License", m_szLicense
);
56 GetString(L
"Description", m_szDesc
);
57 GetString(L
"Size", m_szSize
);
58 GetString(L
"URLSite", m_szUrlSite
);
59 GetString(L
"CDPath", m_szCDPath
);
60 GetString(L
"Language", m_szRegName
);
61 GetString(L
"SHA1", m_szSHA1
);
63 RetrieveLicenseType();
65 RetrieveInstalledStatus();
68 RetrieveInstalledVersion();
74 VOID
CAvailableApplicationInfo::RetrieveInstalledStatus()
76 m_IsInstalled
= ::GetInstalledVersion(NULL
, m_szRegName
)
77 || ::GetInstalledVersion(NULL
, m_szName
);
80 VOID
CAvailableApplicationInfo::RetrieveInstalledVersion()
82 ATL::CStringW szNameVersion
;
83 szNameVersion
= m_szName
+ L
" " + m_szVersion
;
84 m_HasInstalledVersion
= ::GetInstalledVersion(&m_szInstalledVersion
, m_szRegName
)
85 || ::GetInstalledVersion(&m_szInstalledVersion
, m_szName
)
86 || ::GetInstalledVersion(&m_szInstalledVersion
, szNameVersion
);
89 VOID
CAvailableApplicationInfo::RetrieveLanguages()
91 const WCHAR cDelimiter
= L
'|';
92 ATL::CStringW szBuffer
;
94 // TODO: Get multiline parameter
95 if (!m_Parser
->GetString(L
"Languages", szBuffer
))
97 m_HasLanguageInfo
= FALSE
;
101 // Parse parameter string
102 ATL::CStringW m_szLocale
;
104 for (INT i
= 0; szBuffer
[i
] != UNICODE_NULL
; ++i
)
106 if (szBuffer
[i
] != cDelimiter
&& szBuffer
[i
] != L
'\n')
108 m_szLocale
+= szBuffer
[i
];
112 if (StrToIntExW(m_szLocale
.GetString(), STIF_DEFAULT
, &iLCID
))
114 m_LanguageLCIDs
.Add(static_cast<LCID
>(iLCID
));
120 // For the text after delimiter
121 if (!m_szLocale
.IsEmpty())
123 if (StrToIntExW(m_szLocale
.GetString(), STIF_DEFAULT
, &iLCID
))
125 m_LanguageLCIDs
.Add(static_cast<LCID
>(iLCID
));
129 m_HasLanguageInfo
= TRUE
;
132 VOID
CAvailableApplicationInfo::RetrieveLicenseType()
134 INT IntBuffer
= m_Parser
->GetInt(L
"LicenseType");
136 if (IsLicenseType(IntBuffer
))
138 m_LicenseType
= static_cast<LicenseType
>(IntBuffer
);
142 m_LicenseType
= LICENSE_NONE
;
146 BOOL
CAvailableApplicationInfo::FindInLanguages(LCID what
) const
148 if (!m_HasLanguageInfo
)
153 //Find locale code in the list
154 const INT nLanguagesSize
= m_LanguageLCIDs
.GetSize();
155 for (INT i
= 0; i
< nLanguagesSize
; ++i
)
157 if (m_LanguageLCIDs
[i
] == what
)
166 BOOL
CAvailableApplicationInfo::HasLanguageInfo() const
168 return m_HasLanguageInfo
;
171 BOOL
CAvailableApplicationInfo::HasNativeLanguage() const
173 return FindInLanguages(GetUserDefaultLCID());
176 BOOL
CAvailableApplicationInfo::HasEnglishLanguage() const
178 return FindInLanguages(MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
));
181 BOOL
CAvailableApplicationInfo::IsInstalled() const
183 return m_IsInstalled
;
186 BOOL
CAvailableApplicationInfo::HasInstalledVersion() const
188 return m_HasInstalledVersion
;
191 BOOL
CAvailableApplicationInfo::HasUpdate() const
193 return (m_szInstalledVersion
.Compare(m_szVersion
) < 0) ? TRUE
: FALSE
;
196 VOID
CAvailableApplicationInfo::SetLastWriteTime(FILETIME
* ftTime
)
198 RtlCopyMemory(&m_ftCacheStamp
, ftTime
, sizeof(FILETIME
));
201 inline BOOL
CAvailableApplicationInfo::GetString(LPCWSTR lpKeyName
, ATL::CStringW
& ReturnedString
)
203 if (!m_Parser
->GetString(lpKeyName
, ReturnedString
))
205 ReturnedString
.Empty();
210 // CAvailableApplicationInfo
213 ATL::CStringW
CAvailableApps::m_szPath
;
214 ATL::CStringW
CAvailableApps::m_szCabPath
;
215 ATL::CStringW
CAvailableApps::m_szAppsPath
;
216 ATL::CStringW
CAvailableApps::m_szSearchPath
;
218 BOOL
CAvailableApps::InitializeStaticStrings()
221 if (!m_szPath
.IsEmpty())
223 // strings are filled
227 //FIXME: maybe provide a fallback?
228 if (GetStorageDirectory(m_szPath
))
230 m_szAppsPath
= m_szPath
+ L
"\\rapps\\";
231 m_szCabPath
= m_szPath
+ L
"\\rappmgr.cab";
232 m_szSearchPath
= m_szAppsPath
+ L
"*.txt";
239 CAvailableApps::CAvailableApps()
242 InitializeStaticStrings();
245 VOID
CAvailableApps::FreeCachedEntries()
247 POSITION InfoListPosition
= m_InfoList
.GetHeadPosition();
249 /* loop and deallocate all the cached app infos in the list */
250 while (InfoListPosition
)
252 CAvailableApplicationInfo
* Info
= m_InfoList
.GetNext(InfoListPosition
);
256 m_InfoList
.RemoveAll();
259 VOID
CAvailableApps::DeleteCurrentAppsDB()
261 HANDLE hFind
= INVALID_HANDLE_VALUE
;
262 WIN32_FIND_DATAW FindFileData
;
264 if (!InitializeStaticStrings())
269 hFind
= FindFirstFileW(m_szSearchPath
.GetString(), &FindFileData
);
271 if (hFind
!= INVALID_HANDLE_VALUE
)
276 szTmp
= m_szAppsPath
+ FindFileData
.cFileName
;
277 DeleteFileW(szTmp
.GetString());
278 } while (FindNextFileW(hFind
, &FindFileData
) != 0);
282 RemoveDirectoryW(m_szAppsPath
);
283 RemoveDirectoryW(m_szPath
);
286 BOOL
CAvailableApps::UpdateAppsDB()
288 HANDLE hFind
= INVALID_HANDLE_VALUE
;
289 WIN32_FIND_DATAW FindFileData
;
291 if (!InitializeStaticStrings())
296 if (!CreateDirectoryW(m_szPath
.GetString(), NULL
) && GetLastError() != ERROR_ALREADY_EXISTS
)
301 //if there are some files in the db folder - we're good
302 hFind
= FindFirstFileW(m_szSearchPath
.GetString(), &FindFileData
);
303 if (hFind
!= INVALID_HANDLE_VALUE
)
309 CDownloadManager::DownloadApplicationsDB(APPLICATION_DATABASE_URL
);
311 if (!ExtractFilesFromCab(m_szCabPath
, m_szAppsPath
))
316 DeleteFileW(m_szCabPath
.GetString());
321 BOOL
CAvailableApps::ForceUpdateAppsDB()
323 DeleteCurrentAppsDB();
324 return UpdateAppsDB();
327 BOOL
CAvailableApps::Enum(INT EnumType
, AVAILENUMPROC lpEnumProc
)
330 HANDLE hFind
= INVALID_HANDLE_VALUE
;
331 WIN32_FIND_DATAW FindFileData
;
333 hFind
= FindFirstFileW(m_szSearchPath
.GetString(), &FindFileData
);
335 if (hFind
== INVALID_HANDLE_VALUE
)
343 // loop for all the cached entries
344 POSITION CurrentListPosition
= m_InfoList
.GetHeadPosition();
345 CAvailableApplicationInfo
* Info
= NULL
;
347 while (CurrentListPosition
!= NULL
)
349 POSITION LastListPosition
= CurrentListPosition
;
350 Info
= m_InfoList
.GetNext(CurrentListPosition
);
352 // do we already have this entry in cache?
353 if (Info
->m_sFileName
== FindFileData
.cFileName
)
355 // is it current enough, or the file has been modified since our last time here?
356 if (CompareFileTime(&FindFileData
.ftLastWriteTime
, &Info
->m_ftCacheStamp
) == 1)
358 // recreate our cache, this is the slow path
359 m_InfoList
.RemoveAt(LastListPosition
);
367 // speedy path, compare directly, we already have the data
373 // create a new entry
374 Info
= new CAvailableApplicationInfo(FindFileData
.cFileName
);
376 // set a timestamp for the next time
377 Info
->SetLastWriteTime(&FindFileData
.ftLastWriteTime
);
378 m_InfoList
.AddTail(Info
);
381 if (Info
->m_Category
== FALSE
)
384 if (EnumType
!= Info
->m_Category
&& EnumType
!= ENUM_ALL_AVAILABLE
)
387 Info
->RefreshAppInfo();
390 lpEnumProc(Info
, m_szAppsPath
.GetString());
392 } while (FindNextFileW(hFind
, &FindFileData
) != 0);
398 CAvailableApplicationInfo
* CAvailableApps::FindInfo(const ATL::CStringW
& szAppName
) const
400 if (m_InfoList
.IsEmpty())
406 POSITION CurrentListPosition
= m_InfoList
.GetHeadPosition();
407 CAvailableApplicationInfo
* info
;
408 while (CurrentListPosition
!= NULL
)
410 info
= m_InfoList
.GetNext(CurrentListPosition
);
411 if (info
->m_szName
== szAppName
)
419 ATL::CSimpleArray
<CAvailableApplicationInfo
> CAvailableApps::FindInfoList(const ATL::CSimpleArray
<ATL::CStringW
> &arrAppsNames
) const
421 ATL::CSimpleArray
<CAvailableApplicationInfo
> result
;
422 for (INT i
= 0; i
< arrAppsNames
.GetSize(); ++i
)
424 CAvailableApplicationInfo
* Info
= FindInfo(arrAppsNames
[i
]);
433 const ATL::CStringW
& CAvailableApps::GetFolderPath() const
438 const ATL::CStringW
& CAvailableApps::GetAppPath() const
443 const ATL::CStringW
& CAvailableApps::GetCabPath() const
448 LPCWSTR
CAvailableApps::GetFolderPathString() const
450 return m_szPath
.GetString();
453 LPCWSTR
CAvailableApps::GetAppPathString() const
455 return m_szPath
.GetString();
458 LPCWSTR
CAvailableApps::GetCabPathString() const
460 return m_szPath
.GetString();