public static async Task DownloadFileFromDigestAsync(this UpdateData update, string Digest, string Destination) { FileExchangeV3FileDownloadInformation fileDownloadInfo = await update.GetFileUrl(Digest); if (fileDownloadInfo == null) { // TODO: notify of result return; } // Download the file await client.DownloadFileTaskAsync(new Uri(fileDownloadInfo.DownloadUrl), Destination); if (fileDownloadInfo.IsEncrypted) { if (!fileDownloadInfo.Decrypt(Destination, Destination + ".decrypted")) { return; } File.Delete(Destination); File.Move(Destination + ".decrypted", Destination); } }
public async static Task <string> GetBuildStringAsync(this UpdateData update) { try { CExtendedUpdateInfoXml.File deploymentCab = null; foreach (var file in update.Xml.Files.File) { if (file.FileName.EndsWith("desktopdeployment.cab", StringComparison.InvariantCultureIgnoreCase)) { deploymentCab = file; break; } } if (deploymentCab == null) { return(null); } var fileDownloadInfo = await FE3Handler.GetFileUrl(update, deploymentCab.Digest); if (fileDownloadInfo == null) { return(null); } string deploymentCabTemp = Path.GetTempFileName(); await client.DownloadFileTaskAsync(new Uri(fileDownloadInfo.DownloadUrl), deploymentCabTemp); if (fileDownloadInfo.IsEncrypted) { if (!fileDownloadInfo.Decrypt(deploymentCabTemp, deploymentCabTemp + ".decrypted")) { return(null); } File.Delete(deploymentCabTemp); File.Move(deploymentCabTemp + ".decrypted", deploymentCabTemp); } string result = null; try { using (var cabinet = new CabinetHandler(File.OpenRead(deploymentCabTemp))) { foreach (var file in cabinet.Files) { if (file.Equals("UpdateAgent.dll", StringComparison.InvariantCultureIgnoreCase)) { byte[] buffer; using (var dllstream = cabinet.OpenFile(file)) { buffer = new byte[dllstream.Length]; await dllstream.ReadAsync(buffer, 0, (int)dllstream.Length); } result = GetBuildStringFromUpdateAgent(buffer); break; } } } } catch { } var reportedBuildNumberFromService = update.Xml.ExtendedProperties.ReleaseVersion.Split('.')[2]; if (!string.IsNullOrEmpty(result) && result.Count(x => x == '.') >= 2) { var elements = result.Split('.'); elements[2] = reportedBuildNumberFromService; result = string.Join(".", elements); } File.Delete(deploymentCabTemp); return(result); } catch { return(null); } }
public static async Task <FileExchangeV3FileDownloadInformation> GetFileUrl(this UpdateData update, string Digest) { return(await FE3Handler.GetFileUrl(update, Digest)); }
private static async Task <HashSet <CompDBXmlClass.CompDB> > GetCompDBs(UpdateData update) { HashSet <CompDBXmlClass.CompDB> neutralCompDB = new HashSet <CompDBXmlClass.CompDB>(); HashSet <CExtendedUpdateInfoXml.File> metadataCabs = new HashSet <CExtendedUpdateInfoXml.File>(); foreach (CExtendedUpdateInfoXml.File file in update.Xml.Files.File) { if (file.PatchingType.Equals("metadata", StringComparison.InvariantCultureIgnoreCase)) { metadataCabs.Add(file); } } if (metadataCabs.Count == 0) { return(neutralCompDB); } if (metadataCabs.Count == 1 && metadataCabs.First().FileName.Contains("metadata", StringComparison.InvariantCultureIgnoreCase)) { // This is the new metadata format where all metadata is in a single cab if (string.IsNullOrEmpty(update.CachedMetadata)) { var fileDownloadInfo = await FE3Handler.GetFileUrl(update, metadataCabs.First().Digest); if (fileDownloadInfo == null) { return(neutralCompDB); } string metadataCabTemp = Path.GetTempFileName(); // Download the file await client.DownloadFileTaskAsync(new Uri(fileDownloadInfo.DownloadUrl), metadataCabTemp); if (fileDownloadInfo.IsEncrypted) { if (!fileDownloadInfo.Decrypt(metadataCabTemp, metadataCabTemp + ".decrypted")) { return(neutralCompDB); } metadataCabTemp += ".decrypted"; } update.CachedMetadata = metadataCabTemp; } using (CabinetHandler cabinet = new CabinetHandler(File.OpenRead(update.CachedMetadata))) { foreach (string file in cabinet.Files) { using (CabinetHandler cabinet2 = new CabinetHandler(cabinet.OpenFile(file))) { string xmlfile = cabinet2.Files.First(); using (Stream xmlstream = cabinet2.OpenFile(xmlfile)) { neutralCompDB.Add(CompDBXmlClass.DeserializeCompDB(xmlstream)); } } } } } else { // This is the old format, each cab is a file in WU foreach (CExtendedUpdateInfoXml.File file in metadataCabs) { var fileDownloadInfo = await FE3Handler.GetFileUrl(update, file.Digest); if (fileDownloadInfo == null) { continue; } string metadataCabTemp = Path.GetTempFileName(); // Download the file await client.DownloadFileTaskAsync(new Uri(fileDownloadInfo.DownloadUrl), metadataCabTemp); if (fileDownloadInfo.IsEncrypted) { if (!fileDownloadInfo.Decrypt(metadataCabTemp, metadataCabTemp + ".decrypted")) { continue; } metadataCabTemp += ".decrypted"; } update.CachedMetadata = metadataCabTemp; using (CabinetHandler cabinet2 = new CabinetHandler(File.OpenRead(update.CachedMetadata))) { string xmlfile = cabinet2.Files.First(); using (Stream xmlstream = cabinet2.OpenFile(xmlfile)) { neutralCompDB.Add(CompDBXmlClass.DeserializeCompDB(xmlstream)); } } } } return(neutralCompDB); }
public static async Task <IEnumerable <string> > GetAvailableLanguagesAsync(this UpdateData update) { return((await update.GetCompDBsAsync()).GetAvailableLanguages()); }
public static async Task <IEnumerable <FileExchangeV3FileDownloadInformation> > GetFileUrls(UpdateData updateData, string token = null) { var result = await GetExtendedUpdateInfo2(token, updateData.Xml.UpdateIdentity.UpdateID, updateData.Xml.UpdateIdentity.RevisionNumber, updateData.CTAC); updateData.GEI2Response = result.Item2; if (result.Item1.GetExtendedUpdateInfo2Result.FileLocations != null) { return(result.Item1.GetExtendedUpdateInfo2Result.FileLocations.FileLocation.Select(x => new FileExchangeV3FileDownloadInformation(x))); } return(null); }
public static async Task <IEnumerable <UpdateData> > GetUpdates(string categoryId, CTAC ctac, string token, FileExchangeV3UpdateFilter filter = FileExchangeV3UpdateFilter.Application) // Or ProductRelease { (CGetCookieResponse.GetCookieResponse cookie, string cookieresp) = await GetCookie(); HashSet <string> InstalledNonLeafUpdateIDs = new HashSet <string>(); HashSet <string> OtherCachedUpdateIDs = new HashSet <string>(); HashSet <(CSyncUpdatesResponse.SyncUpdatesResponse, string)> responses = new HashSet <(CSyncUpdatesResponse.SyncUpdatesResponse, string)>(); // // Scan all updates // WU will not return all updates in one go // So we need to perform multiple scans and cache the ids // while (true) { var result = await SyncUpdates(cookie.GetCookieResult, token, InstalledNonLeafUpdateIDs, OtherCachedUpdateIDs, new string[] { categoryId }, ctac); // Refresh the cookie cookie.GetCookieResult.EncryptedData = result.Item1.SyncUpdatesResult.NewCookie.EncryptedData; cookie.GetCookieResult.Expiration = result.Item1.SyncUpdatesResult.NewCookie.Expiration; if (result.Item1.SyncUpdatesResult.ExtendedUpdateInfo == null || result.Item1.SyncUpdatesResult.ExtendedUpdateInfo.Updates.Update == null || result.Item1.SyncUpdatesResult.ExtendedUpdateInfo.Updates.Update.Count() == 0) { break; } foreach (var update in result.Item1.SyncUpdatesResult.ExtendedUpdateInfo.Updates.Update) { InstalledNonLeafUpdateIDs.Add(update.ID); OtherCachedUpdateIDs.Add(update.ID); } responses.Add(result); } HashSet <UpdateData> updateDatas = new HashSet <UpdateData>(); foreach (var response in responses) { foreach (var update in response.Item1.SyncUpdatesResult.ExtendedUpdateInfo.Updates.Update) { UpdateData data = new UpdateData() { Update = update }; foreach (var updateInfo in response.Item1.SyncUpdatesResult.NewUpdates.UpdateInfo) { if (ulong.Parse(update.ID) == ulong.Parse(updateInfo.ID)) { data.UpdateInfo = updateInfo; break; } } CExtendedUpdateInfoXml.Xml updateXml = DeserializeInfoXML(data.Update.Xml + data.UpdateInfo.Xml); data.Xml = updateXml; if (data.Xml.ApplicabilityRules != null && data.Xml.ApplicabilityRules.Metadata != null && data.Xml.ApplicabilityRules.Metadata.AppxPackageMetadata != null && data.Xml.ApplicabilityRules.Metadata.AppxPackageMetadata.AppxMetadata != null) { data.AppxMetadata = DeserializeAppxJSON(data.Xml.ApplicabilityRules.Metadata.AppxPackageMetadata.AppxMetadata.ApplicabilityBlob); } if (updateDatas.Any(x => x.Update.ID == update.ID)) { var updateData = updateDatas.First(x => x.Update.ID == update.ID); if (data.Xml.LocalizedProperties == null) { var backup = updateData.Xml; updateData.Xml = data.Xml; updateData.Xml.LocalizedProperties = backup.LocalizedProperties; } if (updateData.Xml.LocalizedProperties == null) { updateData.Xml.LocalizedProperties = data.Xml.LocalizedProperties; } continue; } data.SyncUpdatesResponse = response.Item2; updateDatas.Add(data); } } HashSet <UpdateData> relevantUpdateDatas = new HashSet <UpdateData>(); foreach (var updateData in updateDatas) { if (updateData.Xml.ExtendedProperties != null) { if (updateData.Xml.ExtendedProperties.ContentType == filter.ToString() && updateData.Xml.Files != null) { updateData.CTAC = ctac; relevantUpdateDatas.Add(updateData); } } } return(relevantUpdateDatas); }
public static async Task <AvailableEdition[]> GetAvailableEditions(UpdateData UpdateData, string languagecode) { List <AvailableEdition> availableEditions = new List <AvailableEdition>(); List <CExtendedUpdateInfoXml.File> metadataCabs = new List <CExtendedUpdateInfoXml.File>(); foreach (var file in UpdateData.Xml.Files.File) { if (file.PatchingType.Equals("metadata", StringComparison.InvariantCultureIgnoreCase)) { metadataCabs.Add(file); } } if (metadataCabs.Count == 0) { goto exit; } if (metadataCabs.Count == 1 && metadataCabs[0].FileName.Contains("metadata", StringComparison.InvariantCultureIgnoreCase)) { // This is the new metadata format where all metadata is in a single cab if (string.IsNullOrEmpty(UpdateData.CachedMetadata)) { var fileDownloadInfo = await FE3Handler.GetFileUrl(UpdateData, metadataCabs[0].Digest); if (fileDownloadInfo == null) { goto exit; } string metadataCabTemp = Path.GetTempFileName(); // Download the file WebClient client = new WebClient(); await client.DownloadFileTaskAsync(new Uri(fileDownloadInfo.DownloadUrl), metadataCabTemp); if (fileDownloadInfo.IsEncrypted) { if (!await fileDownloadInfo.DecryptAsync(metadataCabTemp, metadataCabTemp + ".decrypted")) { goto exit; } metadataCabTemp += ".decrypted"; } UpdateData.CachedMetadata = metadataCabTemp; } using (var cabinet = new CabinetHandler(File.OpenRead(UpdateData.CachedMetadata))) { IEnumerable <string> potentialFiles = cabinet.Files.Where(x => x.ToLower().Contains($"desktoptargetcompdb_") && x.ToLower().Contains($"_{languagecode}") && !x.ToLower().Contains("lxp") && !x.ToLower().Contains($"desktoptargetcompdb_{languagecode}")); foreach (var file in potentialFiles) { var edition = file.Split('_').Reverse().Skip(1).First(); if (availableEditions.Any(x => x.Edition == edition)) { continue; } availableEditions.Add(new AvailableEdition() { Edition = edition }); } } } else { IEnumerable <string> potentialFiles = metadataCabs.Select(x => x.FileName).Where(x => x.ToLower().Contains($"desktoptargetcompdb_") && x.ToLower().Contains($"_{languagecode}") && !x.ToLower().Contains("lxp") && !x.ToLower().Contains($"desktoptargetcompdb_{languagecode}")); // This is the old format, each cab is a file in WU foreach (var file in potentialFiles) { var edition = file.Split('_').Reverse().Skip(1).First(); if (availableEditions.Any(x => x.Edition == edition)) { continue; } availableEditions.Add(new AvailableEdition() { Edition = edition }); } } availableEditions.Sort((x, y) => x.Edition.CompareTo(y.Edition)); exit: return(availableEditions.ToArray()); }
public static async Task <AvailableBuildLanguages[]> GetAvailableBuildLanguagesAsync(UpdateData UpdateData) { List <AvailableBuildLanguages> availableBuildLanguages = (await UpdateData.GetAvailableLanguagesAsync()).Select(lang => { var boundlanguageobject = CultureInfo.GetCultureInfoByIetfLanguageTag(lang); return(new AvailableBuildLanguages() { LanguageCode = lang, Title = boundlanguageobject.DisplayName, FlagUri = new Uri($"ms-appx:///Assets/Flags/{lang.Split('-').Last()}.png") }); }).ToList(); availableBuildLanguages.Sort((x, y) => x.Title.CompareTo(y.Title)); return(availableBuildLanguages.ToArray()); }