Skip to content

Commit f98a0e1

Browse files
committed
Backward compatible GUID generation
Plus, validation to ensure GUID generation does not drift again in the future. Fixes 8663
1 parent bbe2316 commit f98a0e1

File tree

10 files changed

+357
-5
lines changed

10 files changed

+357
-5
lines changed

src/api/wix/WixToolset.Extensibility/Data/IBindContext.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ public interface IBindContext
1717
/// </summary>
1818
IServiceProvider ServiceProvider { get; }
1919

20+
/// <summary>
21+
/// Indicates whether to generate GUIDs backward compatible with WiX v3.
22+
/// </summary>
23+
bool BackwardCompatibleGuidGeneration { get; set; }
24+
2025
/// <summary>
2126
/// Bind paths used during resolution.
2227
/// </summary>

src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public BindDatabaseCommand(IBindContext context, IEnumerable<IWindowsInstallerBa
3232
this.FileSystem = context.ServiceProvider.GetService<IFileSystem>();
3333
this.PathResolver = context.ServiceProvider.GetService<IPathResolver>();
3434

35+
this.BackwardCompatibleGuidGeneration = context.BackwardCompatibleGuidGeneration;
3536
this.CabbingThreadCount = context.CabbingThreadCount;
3637
this.CabCachePath = context.CabCachePath;
3738
this.DefaultCompressionLevel = context.DefaultCompressionLevel;
@@ -65,6 +66,8 @@ public BindDatabaseCommand(IBindContext context, IEnumerable<IWindowsInstallerBa
6566

6667
private IPathResolver PathResolver { get; }
6768

69+
private bool BackwardCompatibleGuidGeneration { get; }
70+
6871
private int CabbingThreadCount { get; }
6972

7073
private string CabCachePath { get; }
@@ -410,7 +413,7 @@ public IBindResult Execute()
410413

411414
// Set generated component guids and validate all guids.
412415
{
413-
var command = new FinalizeComponentGuids(this.Messaging, this.WindowsInstallerBackendHelper, this.PathResolver, section, platform);
416+
var command = new FinalizeComponentGuids(this.Messaging, this.WindowsInstallerBackendHelper, this.PathResolver, section, platform, this.BackwardCompatibleGuidGeneration);
414417
command.Execute();
415418
}
416419

src/wix/WixToolset.Core.WindowsInstaller/Bind/FinalizeComponentGuids.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
1616
/// </summary>
1717
internal class FinalizeComponentGuids
1818
{
19-
internal FinalizeComponentGuids(IMessaging messaging, IBackendHelper helper, IPathResolver pathResolver, IntermediateSection section, Platform platform)
19+
internal FinalizeComponentGuids(IMessaging messaging, IBackendHelper helper, IPathResolver pathResolver, IntermediateSection section, Platform platform, bool backwardCompatibleGuidGeneration)
2020
{
2121
this.Messaging = messaging;
2222
this.BackendHelper = helper;
2323
this.PathResolver = pathResolver;
2424
this.Section = section;
2525
this.Platform = platform;
26+
this.BackwardCompatibleGuidGeneration = backwardCompatibleGuidGeneration;
2627
}
2728

2829
private IMessaging Messaging { get; }
@@ -35,6 +36,8 @@ internal FinalizeComponentGuids(IMessaging messaging, IBackendHelper helper, IPa
3536

3637
private Platform Platform { get; }
3738

39+
private bool BackwardCompatibleGuidGeneration { get; }
40+
3841
private Dictionary<string, string> ComponentIdGenSeeds { get; set; }
3942

4043
private ILookup<string, FileSymbol> FilesByComponentId { get; set; }
@@ -98,7 +101,9 @@ private void GenerateComponentGuid(ComponentSymbol componentSymbol)
98101
if (this.RegistrySymbolsById.TryGetValue(componentSymbol.KeyPath, out var registrySymbol))
99102
{
100103
var bitness = componentSymbol.Win64 ? "64" : String.Empty;
101-
var regkey = String.Concat(bitness, registrySymbol.Root, "\\", registrySymbol.Key, "\\", registrySymbol.Name);
104+
var regkey = this.BackwardCompatibleGuidGeneration ?
105+
String.Concat(bitness, (int)registrySymbol.Root, "\\", registrySymbol.Key, "\\", registrySymbol.Name) :
106+
String.Concat(bitness, registrySymbol.Root, "\\", registrySymbol.Key, "\\", registrySymbol.Name);
102107
componentSymbol.ComponentId = this.BackendHelper.CreateGuid(BindDatabaseCommand.WixComponentGuidNamespace, regkey.ToLowerInvariant());
103108
}
104109
}

src/wix/WixToolset.Core/BindContext.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ internal BindContext(IServiceProvider serviceProvider)
2222

2323
public string BurnStubPath { get; set; }
2424

25+
public bool BackwardCompatibleGuidGeneration { get; set; }
26+
2527
public int CabbingThreadCount { get; set; }
2628

2729
public string CabCachePath { get; set; }

src/wix/WixToolset.Core/CommandLine/BuildCommand.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public override CommandLineHelp GetCommandLineHelp()
4747
return new CommandLineHelp("", "build [options] sourcefile [sourcefile ...] -out output.ext", new[]
4848
{
4949
new CommandLineHelpSwitch("-arch", "Set the architecture of the output."),
50+
new CommandLineHelpSwitch("-bcgg", "Backward compatible GUID generation with WiX v3."),
5051
new CommandLineHelpSwitch("-bindfiles", "-bf", "Bind files into an output .wixlib. Ignored if not building a .wixlib."),
5152
new CommandLineHelpSwitch("-bindpath", "-b", "Bind path to search for content files."),
5253
new CommandLineHelpSwitch("-bindpath:target", "-bt", "Bind path to search for target package's content files. Only used when building a patch."),
@@ -147,7 +148,7 @@ public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
147148
{
148149
using (new IntermediateFieldContext("wix.bind"))
149150
{
150-
this.BindPhase(wixipl, wxls, filterCultures, this.commandLine.CabCachePath, this.commandLine.CabbingThreadCount, this.commandLine.BindPaths, this.commandLine.BindVariables, inputsOutputs, cancellationToken);
151+
this.BindPhase(wixipl, wxls, filterCultures, this.commandLine.BackwardCompatibleGuidGeneration, this.commandLine.CabCachePath, this.commandLine.CabbingThreadCount, this.commandLine.BindPaths, this.commandLine.BindVariables, inputsOutputs, cancellationToken);
151152
}
152153
}
153154
}
@@ -284,7 +285,7 @@ private Intermediate LinkPhase(IEnumerable<Intermediate> intermediates, InputsAn
284285
return linker.Link(context);
285286
}
286287

287-
private void BindPhase(Intermediate output, IReadOnlyCollection<Localization> localizations, IReadOnlyCollection<string> filterCultures, string cabCachePath, int cabbingThreadCount, IReadOnlyCollection<IBindPath> bindPaths, Dictionary<string, string> bindVariables, InputsAndOutputs inputsOutputs, CancellationToken cancellationToken)
288+
private void BindPhase(Intermediate output, IReadOnlyCollection<Localization> localizations, IReadOnlyCollection<string> filterCultures, bool backwardCompatibleGuidGeneration, string cabCachePath, int cabbingThreadCount, IReadOnlyCollection<IBindPath> bindPaths, Dictionary<string, string> bindVariables, InputsAndOutputs inputsOutputs, CancellationToken cancellationToken)
288289
{
289290
IResolveResult resolveResult;
290291
{
@@ -314,6 +315,7 @@ private void BindPhase(Intermediate output, IReadOnlyCollection<Localization> lo
314315
{
315316
{
316317
var context = this.ServiceProvider.GetService<IBindContext>();
318+
context.BackwardCompatibleGuidGeneration = backwardCompatibleGuidGeneration;
317319
context.BindPaths = bindPaths;
318320
context.CabbingThreadCount = cabbingThreadCount;
319321
context.CabCachePath = cabCachePath;
@@ -489,6 +491,8 @@ private class CommandLine
489491
{
490492
private static readonly char[] BindPathSplit = { '=' };
491493

494+
public bool BackwardCompatibleGuidGeneration { get; private set; }
495+
492496
public bool BindFiles { get; private set; }
493497

494498
public List<IBindPath> BindPaths { get; } = new List<IBindPath>();
@@ -566,6 +570,10 @@ public bool TryParseArgument(string arg, ICommandLineParser parser)
566570
return true;
567571
}
568572

573+
case "bcgg":
574+
this.BackwardCompatibleGuidGeneration = true;
575+
return true;
576+
569577
case "bf":
570578
case "bindfiles":
571579
this.BindFiles = true;
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2+
3+
namespace WixToolsetTest.CoreIntegration
4+
{
5+
using System.IO;
6+
using System.Linq;
7+
using WixInternal.Core.TestPackage;
8+
using WixInternal.TestSupport;
9+
using WixToolset.Data;
10+
using WixToolset.Data.Symbols;
11+
using Xunit;
12+
13+
public class GuidCompatibilityFixture
14+
{
15+
[Fact]
16+
public void VerifyModernX86GuidCompatibility()
17+
{
18+
var folder = TestData.Get("TestData", "GuidCompatibility");
19+
20+
using var fs = new DisposableFileSystem();
21+
22+
var baseFolder = fs.GetFolder();
23+
var intermediateFolder = Path.Combine(baseFolder, "obj");
24+
25+
var result = WixRunner.Execute(new[]
26+
{
27+
"build",
28+
Path.Combine(folder, "Package.wxs"),
29+
Path.Combine(folder, "Components.wxs"),
30+
"-intermediateFolder", intermediateFolder,
31+
"-o", Path.Combine(baseFolder, "bin", "test.msi")
32+
});
33+
34+
result.AssertSuccess();
35+
36+
var wixpdb = Intermediate.Load(Path.Combine(baseFolder, "bin", "test.wixpdb"));
37+
var section = wixpdb.Sections.Single();
38+
39+
var symbols = section.Symbols.OfType<ComponentSymbol>().ToArray();
40+
WixAssert.CompareLineByLine(new[]
41+
{
42+
"FileFoo {AD87A3DE-042B-5CB1-82C8-782626737A3B} File:filrCrmOAxegUXdKLQjj8mKJFZC2AY",
43+
"RegHkcr {246B5173-0924-511B-8828-77DD3BE87C7D} Registry:regYqKbt2o5W7y7CIBKba5Du9MJ2xU",
44+
"RegHkcu {663BDBDA-FAAF-5B7A-B8BA-D1AB3B5284CD} Registry:regCDVjmO6qHBvQzdqM8XyBiEUuf48",
45+
"RegHklm {6A5C002D-C0C9-5B03-B883-BE3DF3FA21A6} Registry:regPKV64nTdbwlRm8bkU8k4Kxj6Km8",
46+
"RegHkmu {529D5485-ED3E-5D1C-8517-A32103A08F76} Registry:regOPf4kOF1RLKsRy9oG4MP1Rqm8JY",
47+
"RegHku {0C78D91F-7913-5747-918C-322DA2A15823} Registry:regJHg773M8wPDSk6j7CYRThPX7uOw"
48+
}, symbols.Select(s => $"{s.Id.Id} {s.ComponentId} {s.KeyPathType}:{s.KeyPath}").OrderBy(s => s).ToArray());
49+
}
50+
51+
[Fact]
52+
public void VerifyModernX64GuidCompatibility()
53+
{
54+
var folder = TestData.Get("TestData", "GuidCompatibility");
55+
56+
using var fs = new DisposableFileSystem();
57+
58+
var baseFolder = fs.GetFolder();
59+
var intermediateFolder = Path.Combine(baseFolder, "obj");
60+
61+
var result = WixRunner.Execute(new[]
62+
{
63+
"build",
64+
Path.Combine(folder, "Package.wxs"),
65+
Path.Combine(folder, "Components.wxs"),
66+
"-arch", "x64",
67+
"-intermediateFolder", intermediateFolder,
68+
"-o", Path.Combine(baseFolder, "bin", "test.msi")
69+
});
70+
71+
result.AssertSuccess();
72+
73+
var wixpdb = Intermediate.Load(Path.Combine(baseFolder, "bin", "test.wixpdb"));
74+
var section = wixpdb.Sections.Single();
75+
76+
var symbols = section.Symbols.OfType<ComponentSymbol>().ToArray();
77+
WixAssert.CompareLineByLine(new[]
78+
{
79+
"FileFoo {AD87A3DE-042B-5CB1-82C8-782626737A3B} File:filrCrmOAxegUXdKLQjj8mKJFZC2AY",
80+
"RegHkcr {A2D16D0D-8856-5B34-804F-64E0EE691ACD} Registry:regYqKbt2o5W7y7CIBKba5Du9MJ2xU",
81+
"RegHkcu {CE5B9399-8F69-50E4-AE76-9F5C3F5A4D72} Registry:regCDVjmO6qHBvQzdqM8XyBiEUuf48",
82+
"RegHklm {45973AE0-BFEF-5A88-AC82-416C9699ED23} Registry:regPKV64nTdbwlRm8bkU8k4Kxj6Km8",
83+
"RegHkmu {841288A2-7520-5CA5-8CA0-4B4711D3F669} Registry:regOPf4kOF1RLKsRy9oG4MP1Rqm8JY",
84+
"RegHku {0AC9C5B2-E60A-5CD9-9A4E-B5DEABAD1D14} Registry:regJHg773M8wPDSk6j7CYRThPX7uOw"
85+
}, symbols.Select(s => $"{s.Id.Id} {s.ComponentId} {s.KeyPathType}:{s.KeyPath}").OrderBy(s => s).ToArray());
86+
}
87+
88+
[Fact]
89+
public void VerifyModernArm64GuidCompatibility()
90+
{
91+
var folder = TestData.Get("TestData", "GuidCompatibility");
92+
93+
using var fs = new DisposableFileSystem();
94+
95+
var baseFolder = fs.GetFolder();
96+
var intermediateFolder = Path.Combine(baseFolder, "obj");
97+
98+
var result = WixRunner.Execute(new[]
99+
{
100+
"build",
101+
Path.Combine(folder, "Package.wxs"),
102+
Path.Combine(folder, "Components.wxs"),
103+
"-arch", "arm64",
104+
"-intermediateFolder", intermediateFolder,
105+
"-o", Path.Combine(baseFolder, "bin", "test.msi")
106+
});
107+
108+
result.AssertSuccess();
109+
110+
var wixpdb = Intermediate.Load(Path.Combine(baseFolder, "bin", "test.wixpdb"));
111+
var section = wixpdb.Sections.Single();
112+
113+
var symbols = section.Symbols.OfType<ComponentSymbol>().ToArray();
114+
WixAssert.CompareLineByLine(new[]
115+
{
116+
"FileFoo {AD87A3DE-042B-5CB1-82C8-782626737A3B} File:filrCrmOAxegUXdKLQjj8mKJFZC2AY",
117+
"RegHkcr {A2D16D0D-8856-5B34-804F-64E0EE691ACD} Registry:regYqKbt2o5W7y7CIBKba5Du9MJ2xU",
118+
"RegHkcu {CE5B9399-8F69-50E4-AE76-9F5C3F5A4D72} Registry:regCDVjmO6qHBvQzdqM8XyBiEUuf48",
119+
"RegHklm {45973AE0-BFEF-5A88-AC82-416C9699ED23} Registry:regPKV64nTdbwlRm8bkU8k4Kxj6Km8",
120+
"RegHkmu {841288A2-7520-5CA5-8CA0-4B4711D3F669} Registry:regOPf4kOF1RLKsRy9oG4MP1Rqm8JY",
121+
"RegHku {0AC9C5B2-E60A-5CD9-9A4E-B5DEABAD1D14} Registry:regJHg773M8wPDSk6j7CYRThPX7uOw"
122+
}, symbols.Select(s => $"{s.Id.Id} {s.ComponentId} {s.KeyPathType}:{s.KeyPath}").OrderBy(s => s).ToArray());
123+
}
124+
125+
[Fact]
126+
public void VerifyWix3X86GuidCompatibility()
127+
{
128+
var folder = TestData.Get("TestData", "GuidCompatibility");
129+
130+
using var fs = new DisposableFileSystem();
131+
132+
var baseFolder = fs.GetFolder();
133+
var intermediateFolder = Path.Combine(baseFolder, "obj");
134+
135+
var result = WixRunner.Execute(new[]
136+
{
137+
"build",
138+
Path.Combine(folder, "Package.wxs"),
139+
Path.Combine(folder, "Components.wxs"),
140+
"-bcgg",
141+
"-intermediateFolder", intermediateFolder,
142+
"-o", Path.Combine(baseFolder, "bin", "test.msi")
143+
});
144+
145+
result.AssertSuccess();
146+
147+
var wixpdb = Intermediate.Load(Path.Combine(baseFolder, "bin", "test.wixpdb"));
148+
var section = wixpdb.Sections.Single();
149+
150+
var symbols = section.Symbols.OfType<ComponentSymbol>().ToArray();
151+
WixAssert.CompareLineByLine(new[]
152+
{
153+
"FileFoo {AD87A3DE-042B-5CB1-82C8-782626737A3B} File:filrCrmOAxegUXdKLQjj8mKJFZC2AY",
154+
"RegHkcr {656550C1-E3C3-5943-900A-A286A24F1F7C} Registry:regYqKbt2o5W7y7CIBKba5Du9MJ2xU",
155+
"RegHkcu {5C7CBEDE-4C14-58AF-8365-59C602A20543} Registry:regCDVjmO6qHBvQzdqM8XyBiEUuf48",
156+
"RegHklm {186E35F4-96E9-5DE4-8F7B-73EA096A8543} Registry:regPKV64nTdbwlRm8bkU8k4Kxj6Km8",
157+
"RegHkmu {C1707072-2C2C-5249-85E1-37418A31DF2D} Registry:regOPf4kOF1RLKsRy9oG4MP1Rqm8JY",
158+
"RegHku {76A0D3F4-7BD5-51DE-8FDA-6C30674083CB} Registry:regJHg773M8wPDSk6j7CYRThPX7uOw"
159+
}, symbols.Select(s => $"{s.Id.Id} {s.ComponentId} {s.KeyPathType}:{s.KeyPath}").OrderBy(s => s).ToArray());
160+
}
161+
162+
[Fact]
163+
public void VerifyWix3X64GuidCompatibility()
164+
{
165+
var folder = TestData.Get("TestData", "GuidCompatibility");
166+
167+
using var fs = new DisposableFileSystem();
168+
169+
var baseFolder = fs.GetFolder();
170+
var intermediateFolder = Path.Combine(baseFolder, "obj");
171+
172+
var result = WixRunner.Execute(new[]
173+
{
174+
"build",
175+
Path.Combine(folder, "Package.wxs"),
176+
Path.Combine(folder, "Components.wxs"),
177+
"-bcgg",
178+
"-arch", "x64",
179+
"-intermediateFolder", intermediateFolder,
180+
"-o", Path.Combine(baseFolder, "bin", "test.msi")
181+
});
182+
183+
result.AssertSuccess();
184+
185+
var wixpdb = Intermediate.Load(Path.Combine(baseFolder, "bin", "test.wixpdb"));
186+
var section = wixpdb.Sections.Single();
187+
188+
var symbols = section.Symbols.OfType<ComponentSymbol>().ToArray();
189+
WixAssert.CompareLineByLine(new[]
190+
{
191+
"FileFoo {AD87A3DE-042B-5CB1-82C8-782626737A3B} File:filrCrmOAxegUXdKLQjj8mKJFZC2AY",
192+
"RegHkcr {E420B3FC-4889-5D2B-8E2D-DC8D05B62B5B} Registry:regYqKbt2o5W7y7CIBKba5Du9MJ2xU",
193+
"RegHkcu {12D81E73-4429-5D97-8318-7E719F660847} Registry:regCDVjmO6qHBvQzdqM8XyBiEUuf48",
194+
"RegHklm {2E7AA7BE-006C-5FFE-A73F-1C65142AB3D7} Registry:regPKV64nTdbwlRm8bkU8k4Kxj6Km8",
195+
"RegHkmu {C7972BDE-CA76-564D-A9BA-FD3A0B930DCF} Registry:regOPf4kOF1RLKsRy9oG4MP1Rqm8JY",
196+
"RegHku {AB4A2008-03FC-513E-8B92-35CE837C212E} Registry:regJHg773M8wPDSk6j7CYRThPX7uOw"
197+
}, symbols.Select(s => $"{s.Id.Id} {s.ComponentId} {s.KeyPathType}:{s.KeyPath}").OrderBy(s => s).ToArray());
198+
}
199+
200+
[Fact]
201+
public void VerifyWix3Arm64GuidCompatibility()
202+
{
203+
var folder = TestData.Get("TestData", "GuidCompatibility");
204+
205+
using var fs = new DisposableFileSystem();
206+
207+
var baseFolder = fs.GetFolder();
208+
var intermediateFolder = Path.Combine(baseFolder, "obj");
209+
210+
var result = WixRunner.Execute(new[]
211+
{
212+
"build",
213+
Path.Combine(folder, "Package.wxs"),
214+
Path.Combine(folder, "Components.wxs"),
215+
"-bcgg",
216+
"-arch", "x64",
217+
"-intermediateFolder", intermediateFolder,
218+
"-o", Path.Combine(baseFolder, "bin", "test.msi")
219+
});
220+
221+
result.AssertSuccess();
222+
223+
var wixpdb = Intermediate.Load(Path.Combine(baseFolder, "bin", "test.wixpdb"));
224+
var section = wixpdb.Sections.Single();
225+
226+
var symbols = section.Symbols.OfType<ComponentSymbol>().ToArray();
227+
WixAssert.CompareLineByLine(new[]
228+
{
229+
"FileFoo {AD87A3DE-042B-5CB1-82C8-782626737A3B} File:filrCrmOAxegUXdKLQjj8mKJFZC2AY",
230+
"RegHkcr {E420B3FC-4889-5D2B-8E2D-DC8D05B62B5B} Registry:regYqKbt2o5W7y7CIBKba5Du9MJ2xU",
231+
"RegHkcu {12D81E73-4429-5D97-8318-7E719F660847} Registry:regCDVjmO6qHBvQzdqM8XyBiEUuf48",
232+
"RegHklm {2E7AA7BE-006C-5FFE-A73F-1C65142AB3D7} Registry:regPKV64nTdbwlRm8bkU8k4Kxj6Km8",
233+
"RegHkmu {C7972BDE-CA76-564D-A9BA-FD3A0B930DCF} Registry:regOPf4kOF1RLKsRy9oG4MP1Rqm8JY",
234+
"RegHku {AB4A2008-03FC-513E-8B92-35CE837C212E} Registry:regJHg773M8wPDSk6j7CYRThPX7uOw"
235+
}, symbols.Select(s => $"{s.Id.Id} {s.ComponentId} {s.KeyPathType}:{s.KeyPath}").OrderBy(s => s).ToArray());
236+
}
237+
}
238+
}

0 commit comments

Comments
 (0)