2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/rapps/available.cpp
5 * PURPOSE: Functions for working with available applications
6 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
7 * Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
12 #define ADD_TEXT(a, b, c, d) \
15 LoadStringW(hInst, a, szText, _countof(szText)); \
16 InsertRichEditText(szText, c); \
17 InsertRichEditText(b, d); \
20 #define ADD_TEXT_NEWL(a, b) \
21 LoadStringW(hInst, a, szText, _countof(szText)); \
22 InsertRichEditText(L"\n", 0); \
23 InsertRichEditText(szText, b); \
24 InsertRichEditText(L"\n", 0);
26 #define GET_STRING1(a, b) \
27 if (!ParserGetString(a, b, _countof(b), FindFileData.cFileName)) \
30 #define GET_STRING2(a, b) \
31 if (!ParserGetString(a, b, _countof(b), FindFileData.cFileName)) \
34 //App is "installed" if the RegName is in the registry
35 #define APP_INSTALL_CHECK_K(Info, key) \
36 (*Info->szRegName && (IsInstalledApplicationEx(Info->szRegName, FALSE, key) \
37 || IsInstalledApplicationEx(Info->szRegName, TRUE, key)))
39 //Check both registry keys in 64bit system
40 //TODO: check system type beforehand to avoid double checks?
41 #define APP_INSTALL_CHECK(Info) \
42 (APP_INSTALL_CHECK_K(Info, KEY_WOW64_32KEY) || APP_INSTALL_CHECK_K(Info, KEY_WOW64_64KEY))
44 LIST_ENTRY CachedEntriesHead
= { &CachedEntriesHead
, &CachedEntriesHead
};
45 PLIST_ENTRY pCachedEntry
= &CachedEntriesHead
;
48 ShowAvailableAppInfo(INT Index
)
50 PAPPLICATION_INFO Info
= (PAPPLICATION_INFO
) ListViewGetlParam(Index
);
51 WCHAR szText
[MAX_STR_LEN
];
53 if (!Info
) return FALSE
;
55 NewRichEditText(Info
->szName
, CFE_BOLD
);
56 if (APP_INSTALL_CHECK(Info
))
58 ADD_TEXT_NEWL(IDS_STATUS_INSTALLED
, CFE_ITALIC
);
61 ADD_TEXT_NEWL(IDS_STATUS_NOTINSTALLED
, CFE_ITALIC
);
64 ADD_TEXT(IDS_AINFO_VERSION
, Info
->szVersion
, CFE_BOLD
, 0);
65 ADD_TEXT(IDS_AINFO_LICENSE
, Info
->szLicense
, CFE_BOLD
, 0);
66 ADD_TEXT(IDS_AINFO_SIZE
, Info
->szSize
, CFE_BOLD
, 0);
67 ADD_TEXT(IDS_AINFO_URLSITE
, Info
->szUrlSite
, CFE_BOLD
, CFE_LINK
);
68 ADD_TEXT(IDS_AINFO_DESCRIPTION
, Info
->szDesc
, CFE_BOLD
, 0);
69 ADD_TEXT(IDS_AINFO_URLDOWNLOAD
, Info
->szUrlDownload
, CFE_BOLD
, CFE_LINK
);
75 DeleteCurrentAppsDB(VOID
)
77 HANDLE hFind
= INVALID_HANDLE_VALUE
;
78 WIN32_FIND_DATAW FindFileData
;
79 WCHAR szCabPath
[MAX_PATH
];
80 WCHAR szSearchPath
[MAX_PATH
];
81 WCHAR szPath
[MAX_PATH
];
82 WCHAR szTmp
[MAX_PATH
];
86 if (!GetStorageDirectory(szPath
, _countof(szPath
)))
89 hr
= StringCbPrintfW(szCabPath
, sizeof(szCabPath
),
95 result
= result
&& DeleteFileW(szCabPath
);
97 hr
= StringCbCatW(szPath
, sizeof(szPath
), L
"\\rapps\\");
102 hr
= StringCbPrintfW(szSearchPath
, sizeof(szSearchPath
),
108 hFind
= FindFirstFileW(szSearchPath
, &FindFileData
);
110 if (hFind
== INVALID_HANDLE_VALUE
)
115 hr
= StringCbPrintfW(szTmp
, sizeof(szTmp
),
117 szPath
, FindFileData
.cFileName
);
120 result
= result
&& DeleteFileW(szTmp
);
122 } while (FindNextFileW(hFind
, &FindFileData
) != 0);
133 WCHAR szPath
[MAX_PATH
];
134 WCHAR szAppsPath
[MAX_PATH
];
135 WCHAR szCabPath
[MAX_PATH
];
137 if (!DeleteCurrentAppsDB())
140 DownloadApplicationsDB(APPLICATION_DATABASE_URL
);
142 if (!GetStorageDirectory(szPath
, _countof(szPath
)))
145 if (FAILED(StringCbPrintfW(szCabPath
, sizeof(szCabPath
),
152 if (FAILED(StringCbPrintfW(szAppsPath
, sizeof(szAppsPath
),
159 ExtractFilesFromCab(szCabPath
, szAppsPath
);
166 EnumAvailableApplications(INT EnumType
, AVAILENUMPROC lpEnumProc
)
168 HANDLE hFind
= INVALID_HANDLE_VALUE
;
169 WIN32_FIND_DATAW FindFileData
;
170 WCHAR szPath
[MAX_PATH
];
171 WCHAR szAppsPath
[MAX_PATH
];
172 WCHAR szCabPath
[MAX_PATH
];
173 PAPPLICATION_INFO Info
;
176 if (!GetStorageDirectory(szPath
, _countof(szPath
)))
179 hr
= StringCbPrintfW(szCabPath
, sizeof(szCabPath
),
185 hr
= StringCbCatW(szPath
, sizeof(szPath
), L
"\\rapps\\");
190 hr
= StringCbCopyW(szAppsPath
, sizeof(szAppsPath
), szPath
);
195 if (!CreateDirectory(szPath
, NULL
) &&
196 GetLastError() != ERROR_ALREADY_EXISTS
)
201 hr
= StringCbCatW(szPath
, sizeof(szPath
), L
"*.txt");
206 hFind
= FindFirstFileW(szPath
, &FindFileData
);
208 if (hFind
== INVALID_HANDLE_VALUE
)
210 if (GetFileAttributesW(szCabPath
) == INVALID_FILE_ATTRIBUTES
)
211 DownloadApplicationsDB(APPLICATION_DATABASE_URL
);
213 ExtractFilesFromCab(szCabPath
, szAppsPath
);
214 hFind
= FindFirstFileW(szPath
, &FindFileData
);
216 if (hFind
== INVALID_HANDLE_VALUE
)
222 /* loop for all the cached entries */
223 for (pCachedEntry
= CachedEntriesHead
.Flink
; pCachedEntry
!= &CachedEntriesHead
; pCachedEntry
= pCachedEntry
->Flink
)
225 Info
= CONTAINING_RECORD(pCachedEntry
, APPLICATION_INFO
, List
);
227 /* do we already have this entry in cache? */
228 if(_wcsicmp(FindFileData
.cFileName
, Info
->cFileName
) == 0)
230 /* is it current enough, or the file has been modified since our last time here? */
231 if (CompareFileTime(&FindFileData
.ftLastWriteTime
, &Info
->ftCacheStamp
) == 1)
233 /* recreate our cache, this is the slow path */
234 RemoveEntryList(&Info
->List
);
235 HeapFree(GetProcessHeap(), 0, Info
);
239 /* speedy path, compare directly, we already have the data */
247 /* create a new entry */
248 Info
= (PAPPLICATION_INFO
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(APPLICATION_INFO
));
253 Info
->Category
= ParserGetInt(L
"Category", FindFileData
.cFileName
);
255 /* copy the cache-related fields for the next time */
256 RtlCopyMemory(&Info
->cFileName
, &FindFileData
.cFileName
, MAX_PATH
);
257 RtlCopyMemory(&Info
->ftCacheStamp
, &FindFileData
.ftLastWriteTime
, sizeof(FILETIME
));
259 /* add our cached entry to the cached list */
260 InsertTailList(&CachedEntriesHead
, &Info
->List
);
264 if (Info
->Category
== FALSE
)
267 if (EnumType
!= Info
->Category
&& EnumType
!= ENUM_ALL_AVAILABLE
)
270 /* if our cache hit was only partial, we need to parse
271 and lazily fill the rest of fields only when needed */
273 if (Info
->szUrlDownload
[0] == 0)
275 GET_STRING1(L
"Name", Info
->szName
);
276 GET_STRING1(L
"URLDownload", Info
->szUrlDownload
);
278 GET_STRING2(L
"RegName", Info
->szRegName
);
279 GET_STRING2(L
"Version", Info
->szVersion
);
280 GET_STRING2(L
"License", Info
->szLicense
);
281 GET_STRING2(L
"Description", Info
->szDesc
);
282 GET_STRING2(L
"Size", Info
->szSize
);
283 GET_STRING2(L
"URLSite", Info
->szUrlSite
);
284 GET_STRING2(L
"CDPath", Info
->szCDPath
);
285 GET_STRING2(L
"SHA1", Info
->szSHA1
);
288 if (!lpEnumProc(Info
))
291 } while (FindNextFileW(hFind
, &FindFileData
) != 0);
298 VOID
FreeCachedAvailableEntries(VOID
)
300 PAPPLICATION_INFO Info
;
302 /* loop and deallocate all the cached app infos in the list */
303 for (pCachedEntry
= CachedEntriesHead
.Flink
; pCachedEntry
!= &CachedEntriesHead
;)
305 Info
= CONTAINING_RECORD(pCachedEntry
, APPLICATION_INFO
, List
);
307 /* grab a reference to the next linked entry before getting rid of the current one */
308 pCachedEntry
= pCachedEntry
->Flink
;
310 /* flush them down the toilet :D */
311 RemoveEntryList(&Info
->List
);
312 HeapFree(GetProcessHeap(), 0, Info
);