Skip to content

Commit

Permalink
fix: Conversion crashes at multiple steps with Windows 11 Moment 4 23…
Browse files Browse the repository at this point in the history
…h2 update

With the Windows 11 Moment 4 23h2 update, microsoft added a new compdb for apps, gated by velocity ids. We never supported more than one compdb, so the existing app engine code broke.
Furthermore, said compdb does not follow the same steps as its original one, it does not include a tags section, breaking even more the tool when trying to look for edition compdbs.
Fix both issues

This commit makes conversion of moment updates with app moment compdbs possible and functional again
  • Loading branch information
gus33000 committed Oct 14, 2023
1 parent 4393d23 commit 175e044
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 162 deletions.
1 change: 0 additions & 1 deletion UUPMediaCreator.sln
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,6 @@ Global
EndGlobalSection
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\UnifiedUpdatePlatform.Services.WindowsUpdate.Shared\UnifiedUpdatePlatform.Services.WindowsUpdate.Shared.projitems*{0d26e90f-2cf6-4ba5-b235-72e646a3ff48}*SharedItemsImports = 13
src\UnifiedUpdatePlatform.Common.Messaging.Shared\UnifiedUpdatePlatform.Common.Messaging.Shared.projitems*{11385f97-61d8-47ef-a068-3a130232f6b6}*SharedItemsImports = 4
src\CompDB.Shared\CompDB.Shared.projitems*{113c95b3-1cbb-4b02-8bfe-8a623ad67f84}*SharedItemsImports = 13
src\Cabinet.Shared\Cabinet.Shared.projitems*{113c95b3-1cbb-4b02-8bfe-8a623ad67f85}*SharedItemsImports = 13
src\TempManager.Shared\TempManager.Shared.projitems*{1aac4923-a4e5-41d9-87fa-cfb028f802e5}*SharedItemsImports = 5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"profiles": {
"UUPMediaConverter": {
"commandName": "Project",
"commandLineArgs": "C:\\Users\\Gus\\source\\repos\\gus33000\\UUPMediaCreator\\build\\x64\\Debug\\UnifiedUpdatePlatform.Media.Download\\net7.0\\10.0.22518.1000.rs_prerelease.211203-1458_arm64fre_ec4e1526ea25 C:\\Users\\Gus\\source\\repos\\gus33000\\UUPMediaCreator\\build\\x64\\Debug\\UnifiedUpdatePlatform.Media.Download\\net7.0\\10.0.22518.1000.rs_prerelease.211203-1458_arm64fre_ec4e1526ea25.iso en-us professional"
"commandLineArgs": "-u C:\\Users\\Gus\\Documents\\CLI\\10.0.22631.2428.ni_release_svc_prod1.230929-1800_arm64fre_52b4ad2d28a8 -i C:\\Users\\Gus\\Documents\\CLI\\Windows.iso -l en-US -e Professional -c XPRESS"
}
}
}
110 changes: 57 additions & 53 deletions src/CompDB.Shared/Applications/AppxSelectionEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using CompDB;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -37,7 +38,7 @@ public static class AppxSelectionEngine
/// <param name="appsCdb"></param>
/// <param name="repositoryPath"></param>
/// <returns></returns>
private static (Dictionary<string, DeploymentProperties> preinstalledApps, CompDB.CompDBXmlClass.Feature[] appsFeatures) SetupVariables(CompDB.CompDBXmlClass.CompDB editionCdb, CompDB.CompDBXmlClass.CompDB appsCdb)
private static (Dictionary<string, DeploymentProperties> preinstalledApps, CompDBXmlClass.Feature[] appsFeatures) SetupVariables(CompDBXmlClass.CompDB editionCdb, IEnumerable<CompDBXmlClass.CompDB> appsCdbs)
{
Dictionary<string, DeploymentProperties> preinstalledApps = editionCdb.Features.Feature
.First(x => x.Type == "DesktopMedia")
Expand All @@ -48,10 +49,15 @@ private static (Dictionary<string, DeploymentProperties> preinstalledApps, CompD
.Distinct()
.ToDictionary(x => x, _ => new DeploymentProperties());

CompDB.CompDBXmlClass.Feature[] appsFeatures = appsCdb.Features.Feature;
List<CompDBXmlClass.Feature> appsFeatures = new();

foreach (CompDBXmlClass.CompDB appsCdb in appsCdbs)
{
appsFeatures.AddRange(appsCdb.Features.Feature);
}

// Load dependencies & intents
foreach (CompDB.CompDBXmlClass.Feature ftr in appsFeatures)
foreach (CompDBXmlClass.Feature ftr in appsFeatures)
{
string appFeatureId = ftr.FeatureID;
if (!preinstalledApps.ContainsKey(appFeatureId))
Expand All @@ -69,14 +75,14 @@ private static (Dictionary<string, DeploymentProperties> preinstalledApps, CompD
deployProps.PreferStub = true;
}

List<CompDB.CompDBXmlClass.Feature> dependencies = ftr.Dependencies?.Feature;
List<CompDBXmlClass.Feature> dependencies = ftr.Dependencies?.Feature;
if (dependencies == null)
{
continue;
}

HashSet<string> depsForApp = new();
foreach (CompDB.CompDBXmlClass.Feature dep in dependencies)
foreach (CompDBXmlClass.Feature dep in dependencies)
{
string depAppId = dep.FeatureID;
if (!preferStub)
Expand All @@ -94,7 +100,7 @@ private static (Dictionary<string, DeploymentProperties> preinstalledApps, CompD
preinstalledApps[appFeatureId].Dependencies = depsForApp;
}

return (preinstalledApps, appsFeatures);
return (preinstalledApps, appsFeatures.ToArray());
}

/// <summary>
Expand All @@ -103,12 +109,12 @@ private static (Dictionary<string, DeploymentProperties> preinstalledApps, CompD
/// <param name="editionCdb">The edition Composition Database to generate licenses for</param>
/// <param name="appsCdb">The application Composition Database</param>
/// <param name="repositoryPath">The path to the repository file set</param>
public static void GenerateLicenseXmlFiles(CompDB.CompDBXmlClass.CompDB editionCdb, CompDB.CompDBXmlClass.CompDB appsCdb, string repositoryPath)
public static void GenerateLicenseXmlFiles(CompDBXmlClass.CompDB editionCdb, IEnumerable<CompDBXmlClass.CompDB> appsCdbs, string repositoryPath)
{
(Dictionary<string, DeploymentProperties> preinstalledApps, CompDB.CompDBXmlClass.Feature[] appsFeatures) = SetupVariables(editionCdb, appsCdb);
(Dictionary<string, DeploymentProperties> preinstalledApps, CompDBXmlClass.Feature[] appsFeatures) = SetupVariables(editionCdb, appsCdbs);

// Pick packages and dump licenses
foreach (CompDB.CompDBXmlClass.Feature ftr in appsFeatures)
foreach (CompDBXmlClass.Feature ftr in appsFeatures)
{
string appFeatureId = ftr.FeatureID;
if (!preinstalledApps.ContainsKey(appFeatureId))
Expand Down Expand Up @@ -137,20 +143,17 @@ public static void GenerateLicenseXmlFiles(CompDB.CompDBXmlClass.CompDB editionC
/// <param name="appsCdb">The application Composition Database</param>
/// <param name="repositoryPath">The path to the repository file set</param>
/// <returns></returns>
public static AppxInstallWorkload[] GetAppxInstallationWorkloads(CompDB.CompDBXmlClass.CompDB editionCdb, CompDB.CompDBXmlClass.CompDB appsCdb)
public static AppxInstallWorkload[] GetAppxInstallationWorkloads(CompDBXmlClass.CompDB editionCdb, IEnumerable<CompDBXmlClass.CompDB> appsCdbs, string editionLanguage)
{
List<AppxInstallWorkload> workloads = new();

string editionLanguage = editionCdb.Tags.Tag
.First(x => x.Name == "Language").Value;

IEnumerable<string> applicableLanguageTags = GetAllPossibleLanguageCombinations(editionLanguage);

(Dictionary<string, DeploymentProperties> preinstalledApps, CompDB.CompDBXmlClass.Feature[] appsFeatures) = SetupVariables(editionCdb, appsCdb);
(Dictionary<string, DeploymentProperties> preinstalledApps, CompDBXmlClass.Feature[] appsFeatures) = SetupVariables(editionCdb, appsCdbs);

HashSet<string> allPackageIDs = new();
// Pick packages and dump licenses
foreach (CompDB.CompDBXmlClass.Feature ftr in appsFeatures)
foreach (CompDBXmlClass.Feature ftr in appsFeatures)
{
string appFeatureId = ftr.FeatureID;
if (!preinstalledApps.ContainsKey(appFeatureId))
Expand All @@ -173,7 +176,7 @@ public static AppxInstallWorkload[] GetAppxInstallationWorkloads(CompDB.CompDBXm
deployProps.HasLicense = true;
}

List<CompDB.CompDBXmlClass.Package> appPackages = ftr.Packages.Package;
List<CompDBXmlClass.Package> appPackages = ftr.Packages.Package;
deployProps.AddApplicablePackages(appPackages, applicableLanguageTags);

foreach (string pid in deployProps.PackageIDs)
Expand All @@ -183,23 +186,26 @@ public static AppxInstallWorkload[] GetAppxInstallationWorkloads(CompDB.CompDBXm
}

Dictionary<string, PackageProperties> packageHashDict = new();
foreach (CompDB.CompDBXmlClass.Package p in appsCdb.Packages.Package)
foreach (CompDBXmlClass.CompDB appsCdb in appsCdbs)
{
string packageId = p.ID;
if (!allPackageIDs.Contains(packageId))
foreach (CompDBXmlClass.Package p in appsCdb.Packages.Package)
{
continue;
}
string packageId = p.ID;
if (!allPackageIDs.Contains(packageId))
{
continue;
}

CompDB.CompDBXmlClass.PayloadItem pCanonical = p
.Payload
.PayloadItem
.First(x => x.PayloadType == "Canonical");
packageHashDict[packageId] = new PackageProperties()
{
Path = pCanonical.Path,
SHA256 = pCanonical.PayloadHash
};
CompDBXmlClass.PayloadItem pCanonical = p
.Payload
.PayloadItem
.First(x => x.PayloadType == "Canonical");
packageHashDict[packageId] = new PackageProperties()
{
Path = pCanonical.Path,
SHA256 = pCanonical.PayloadHash
};
}
}

foreach (KeyValuePair<string, DeploymentProperties> deployKvp in preinstalledApps.Where(x => !x.Value.IsFramework))
Expand Down Expand Up @@ -491,20 +497,15 @@ private static IEnumerable<string> GetAllPossibleLanguageCombinations(string edi
/// <param name="appsCdb">The application Composition Database</param>
/// <param name="repositoryPath">The path to the repository file set</param>
/// <returns></returns>
public static PackageProperties[] GetAppxFilesToKeep(CompDB.CompDBXmlClass.CompDB editionCdb, CompDB.CompDBXmlClass.CompDB appsCdb)
public static PackageProperties[] GetAppxFilesToKeep(CompDBXmlClass.CompDB editionCdb, IEnumerable<CompDBXmlClass.CompDB> appsCdbs, string editionLanguage)
{
List<AppxInstallWorkload> workloads = new();

string editionLanguage = editionCdb.Tags.Tag
.First(x => x.Name == "Language").Value;

IEnumerable<string> applicableLanguageTags = GetAllPossibleLanguageCombinations(editionLanguage);

(Dictionary<string, DeploymentProperties> preinstalledApps, CompDB.CompDBXmlClass.Feature[] appsFeatures) = SetupVariables(editionCdb, appsCdb);
(Dictionary<string, DeploymentProperties> preinstalledApps, CompDBXmlClass.Feature[] appsFeatures) = SetupVariables(editionCdb, appsCdbs);

HashSet<string> allPackageIDs = new();
// Pick packages and dump licenses
foreach (CompDB.CompDBXmlClass.Feature ftr in appsFeatures)
foreach (CompDBXmlClass.Feature ftr in appsFeatures)
{
string appFeatureId = ftr.FeatureID;
if (!preinstalledApps.ContainsKey(appFeatureId))
Expand All @@ -527,7 +528,7 @@ public static PackageProperties[] GetAppxFilesToKeep(CompDB.CompDBXmlClass.CompD
deployProps.HasLicense = true;
}

List<CompDB.CompDBXmlClass.Package> appPackages = ftr.Packages.Package;
List<CompDBXmlClass.Package> appPackages = ftr.Packages.Package;
deployProps.AddApplicablePackages(appPackages, applicableLanguageTags);

foreach (string pid in deployProps.PackageIDs)
Expand All @@ -537,23 +538,26 @@ public static PackageProperties[] GetAppxFilesToKeep(CompDB.CompDBXmlClass.CompD
}

Dictionary<string, PackageProperties> packageHashDict = new();
foreach (CompDB.CompDBXmlClass.Package p in appsCdb.Packages.Package)
foreach (CompDBXmlClass.CompDB appsCdb in appsCdbs)
{
string packageId = p.ID;
if (!allPackageIDs.Contains(packageId))
foreach (CompDBXmlClass.Package p in appsCdb.Packages.Package)
{
continue;
}
string packageId = p.ID;
if (!allPackageIDs.Contains(packageId))
{
continue;
}

CompDB.CompDBXmlClass.PayloadItem pCanonical = p
.Payload
.PayloadItem
.First(x => x.PayloadType == "Canonical");
packageHashDict[packageId] = new PackageProperties()
{
Path = pCanonical.Path,
SHA256 = pCanonical.PayloadHash
};
CompDBXmlClass.PayloadItem pCanonical = p
.Payload
.PayloadItem
.First(x => x.PayloadType == "Canonical");
packageHashDict[packageId] = new PackageProperties()
{
Path = pCanonical.Path,
SHA256 = pCanonical.PayloadHash
};
}
}

return preinstalledApps.SelectMany(x => x.Value.PackageIDs).Select(x => packageHashDict[x]).ToArray();
Expand Down
16 changes: 12 additions & 4 deletions src/CompDB.Shared/CompDBExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ public static CompDBXmlClass.CompDB GetNeutralCompDB(this IEnumerable<CompDBXmlC
compDB.Tags.Tag?.Count == 3 &&
compDB.Tags.Tag.Find(x => x.Name.Equals("UpdateType", StringComparison.InvariantCultureIgnoreCase))?.Value?.Equals("Canonical", StringComparison.InvariantCultureIgnoreCase) == true &&
compDB.Tags.Tag.Find(x => x.Name.Equals("Language", StringComparison.InvariantCultureIgnoreCase))?.Value?.Equals(LanguageCode, StringComparison.InvariantCultureIgnoreCase) == true &&
compDB.Tags.Tag.Any(x => x.Name.Equals("Edition", StringComparison.InvariantCultureIgnoreCase)))
compDB.Tags.Tag.Any(x => x.Name.Equals("Edition", StringComparison.InvariantCultureIgnoreCase)) &&
compDB.Name?.EndsWith("~Desktop_Apps~~") != true &&
compDB.Name?.EndsWith("~Desktop_Apps_Moment~~") != true)
{
_ = filteredCompDBs.Add(compDB);
}
Expand All @@ -101,7 +103,9 @@ public static CompDBXmlClass.CompDB GetNeutralCompDB(this IEnumerable<CompDBXmlC
//
else if (compDB.Features?.Feature?.FirstOrDefault(x =>
x.Type?.Contains("DesktopMedia", StringComparison.InvariantCultureIgnoreCase) == true &&
x.FeatureID?.Contains(LanguageCode, StringComparison.InvariantCultureIgnoreCase) == true) != null)
x.FeatureID?.Contains(LanguageCode, StringComparison.InvariantCultureIgnoreCase) == true) != null &&
compDB.Name?.EndsWith("~Desktop_Apps~~") != true &&
compDB.Name?.EndsWith("~Desktop_Apps_Moment~~") != true)
{
_ = filteredCompDBs.Add(compDB);
}
Expand All @@ -125,7 +129,9 @@ public static CompDBXmlClass.CompDB GetNeutralCompDB(this IEnumerable<CompDBXmlC
if (compDB.Tags.Type.Equals("Edition", StringComparison.InvariantCultureIgnoreCase) &&
compDB.Tags.Tag?.Count == 3 &&
compDB.Tags.Tag.Find(x => x.Name.Equals("UpdateType", StringComparison.InvariantCultureIgnoreCase))?.Value?.Equals("Canonical", StringComparison.InvariantCultureIgnoreCase) == true &&
compDB.Tags.Tag.Any(x => x.Name.Equals("Edition", StringComparison.InvariantCultureIgnoreCase)))
compDB.Tags.Tag.Any(x => x.Name.Equals("Edition", StringComparison.InvariantCultureIgnoreCase)) &&
compDB.Name?.EndsWith("~Desktop_Apps~~") != true &&
compDB.Name?.EndsWith("~Desktop_Apps_Moment~~") != true)
{
_ = filteredCompDBs.Add(compDB);
}
Expand All @@ -134,7 +140,9 @@ public static CompDBXmlClass.CompDB GetNeutralCompDB(this IEnumerable<CompDBXmlC
// Older style compdbs have no tag elements, we need to find out if it's an edition compdb using another way
//
else if (compDB.Features?.Feature?.FirstOrDefault(x =>
x.Type?.Contains("DesktopMedia", StringComparison.InvariantCultureIgnoreCase) == true) != null)
x.Type?.Contains("DesktopMedia", StringComparison.InvariantCultureIgnoreCase) == true) != null &&
compDB.Name?.EndsWith("~Desktop_Apps~~") != true &&
compDB.Name?.EndsWith("~Desktop_Apps_Moment~~") != true)
{
_ = filteredCompDBs.Add(compDB);
}
Expand Down
Loading

0 comments on commit 175e044

Please sign in to comment.