BOOL EnumAvailableApplications(INT EnumType, AVAILENUMPROC lpEnumProc) { HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATAW FindFileData; WCHAR szPath[MAX_PATH]; WCHAR szAppsPath[MAX_PATH]; WCHAR szSectionLocale[MAX_PATH] = L"Section."; WCHAR szCabPath[MAX_PATH]; WCHAR szLocale[4 + 1]; APPLICATION_INFO Info; if (!GetCurrentDirectoryW(MAX_PATH, szPath)) { return FALSE; } swprintf(szCabPath, L"%s\\rappmgr.cab", szPath); wcscat(szPath, L"\\rapps\\"); wcscpy(szAppsPath, szPath); if (!CreateDirectory(szPath, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) { return FALSE; } GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE, szLocale, sizeof(szLocale) / sizeof(WCHAR)); wcscat(szSectionLocale, szLocale); wcscat(szPath, L"*.txt"); hFind = FindFirstFileW(szPath, &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { if (GetFileAttributesW(szCabPath) == INVALID_FILE_ATTRIBUTES) DownloadApplicationsDB(APPLICATION_DATEBASE_URL); ExtractFilesFromCab(szCabPath, szAppsPath); hFind = FindFirstFileW(szPath, &FindFileData); if (hFind == INVALID_HANDLE_VALUE) return FALSE; } #define GET_STRING1(a, b) \ if (!ParserGetString(szSectionLocale, a, b, MAX_PATH, FindFileData.cFileName)) \ if (!ParserGetString(L"Section", a, b, MAX_PATH, FindFileData.cFileName)) \ continue; #define GET_STRING2(a, b) \ if (!ParserGetString(szSectionLocale, a, b, MAX_PATH, FindFileData.cFileName)) \ if (!ParserGetString(L"Section", a, b, MAX_PATH, FindFileData.cFileName)) \ b[0] = '\0'; do { Info.Category = ParserGetInt(szSectionLocale, L"Category", FindFileData.cFileName); if (Info.Category == -1) { Info.Category = ParserGetInt(L"Section", L"Category", FindFileData.cFileName); if (Info.Category == -1) continue; } if (EnumType != Info.Category && EnumType != ENUM_ALL_AVAILABLE) continue; GET_STRING1(L"Name", Info.szName); GET_STRING1(L"URLDownload", Info.szUrlDownload); GET_STRING2(L"RegName", Info.szRegName); GET_STRING2(L"Version", Info.szVersion); GET_STRING2(L"Licence", Info.szLicence); GET_STRING2(L"Description", Info.szDesc); GET_STRING2(L"Size", Info.szSize); GET_STRING2(L"URLSite", Info.szUrlSite); GET_STRING2(L"CDPath", Info.szCDPath); if (!lpEnumProc(Info)) break; } while (FindNextFileW(hFind, &FindFileData) != 0); FindClose(hFind); return TRUE; }
BOOL EnumAvailableApplications(INT EnumType, AVAILENUMPROC lpEnumProc) { HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATAW FindFileData; WCHAR szPath[MAX_PATH]; WCHAR szAppsPath[MAX_PATH]; WCHAR szCabPath[MAX_PATH]; PAPPLICATION_INFO Info; HRESULT hr; if (!GetStorageDirectory(szPath, _countof(szPath))) return FALSE; hr = StringCbPrintfW(szCabPath, sizeof(szCabPath), L"%ls\\rappmgr.cab", szPath); if (FAILED(hr)) return FALSE; hr = StringCbCatW(szPath, sizeof(szPath), L"\\rapps\\"); if (FAILED(hr)) return FALSE; hr = StringCbCopyW(szAppsPath, sizeof(szAppsPath), szPath); if (FAILED(hr)) return FALSE; if (!CreateDirectory(szPath, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) { return FALSE; } hr = StringCbCatW(szPath, sizeof(szPath), L"*.txt"); if (FAILED(hr)) return FALSE; hFind = FindFirstFileW(szPath, &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { if (GetFileAttributesW(szCabPath) == INVALID_FILE_ATTRIBUTES) DownloadApplicationsDB(APPLICATION_DATABASE_URL); ExtractFilesFromCab(szCabPath, szAppsPath); hFind = FindFirstFileW(szPath, &FindFileData); if (hFind == INVALID_HANDLE_VALUE) return FALSE; } do { /* loop for all the cached entries */ for (pCachedEntry = CachedEntriesHead.Flink; pCachedEntry != &CachedEntriesHead; pCachedEntry = pCachedEntry->Flink) { Info = CONTAINING_RECORD(pCachedEntry, APPLICATION_INFO, List); /* do we already have this entry in cache? */ 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) { /* recreate our cache, this is the slow path */ RemoveEntryList(&Info->List); HeapFree(GetProcessHeap(), 0, Info); } else { /* speedy path, compare directly, we already have the data */ goto skip_if_cached; } break; } } /* create a new entry */ Info = (PAPPLICATION_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APPLICATION_INFO)); if(!Info) break; Info->Category = ParserGetInt(L"Category", FindFileData.cFileName); /* copy the cache-related fields for the next time */ 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: if (Info->Category == FALSE) continue; if (EnumType != Info->Category && EnumType != ENUM_ALL_AVAILABLE) continue; /* if our cache hit was only partial, we need to parse and lazily fill the rest of fields only when needed */ if (Info->szUrlDownload[0] == 0) { GET_STRING1(L"Name", Info->szName); GET_STRING1(L"URLDownload", Info->szUrlDownload); GET_STRING2(L"RegName", Info->szRegName); GET_STRING2(L"Version", Info->szVersion); GET_STRING2(L"License", Info->szLicense); GET_STRING2(L"Description", Info->szDesc); GET_STRING2(L"Size", Info->szSize); GET_STRING2(L"URLSite", Info->szUrlSite); GET_STRING2(L"CDPath", Info->szCDPath); GET_STRING2(L"SHA1", Info->szSHA1); } if (!lpEnumProc(Info)) break; } while (FindNextFileW(hFind, &FindFileData) != 0); FindClose(hFind); return TRUE; }