diff options
Diffstat (limited to 'src/ext/Bal/wixext/BalBurnBackendExtension.cs')
-rw-r--r-- | src/ext/Bal/wixext/BalBurnBackendExtension.cs | 294 |
1 files changed, 284 insertions, 10 deletions
diff --git a/src/ext/Bal/wixext/BalBurnBackendExtension.cs b/src/ext/Bal/wixext/BalBurnBackendExtension.cs index d34c159a..6f615796 100644 --- a/src/ext/Bal/wixext/BalBurnBackendExtension.cs +++ b/src/ext/Bal/wixext/BalBurnBackendExtension.cs | |||
@@ -5,6 +5,8 @@ namespace WixToolset.Bal | |||
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
7 | using System.Linq; | 7 | using System.Linq; |
8 | using System.Text; | ||
9 | using System.Xml; | ||
8 | using WixToolset.Bal.Symbols; | 10 | using WixToolset.Bal.Symbols; |
9 | using WixToolset.Data; | 11 | using WixToolset.Data; |
10 | using WixToolset.Data.Burn; | 12 | using WixToolset.Data.Burn; |
@@ -29,12 +31,48 @@ namespace WixToolset.Bal | |||
29 | 31 | ||
30 | protected override IReadOnlyCollection<IntermediateSymbolDefinition> SymbolDefinitions => BurnSymbolDefinitions; | 32 | protected override IReadOnlyCollection<IntermediateSymbolDefinition> SymbolDefinitions => BurnSymbolDefinitions; |
31 | 33 | ||
34 | public override bool TryProcessSymbol(IntermediateSection section, IntermediateSymbol symbol) | ||
35 | { | ||
36 | if (symbol is WixBalPackageInfoSymbol balPackageInfoSymbol) | ||
37 | { | ||
38 | // There might be a more efficient way to do this, | ||
39 | // but this is an easy way to ensure we're creating valid XML. | ||
40 | var sb = new StringBuilder(); | ||
41 | using (var writer = XmlWriter.Create(sb)) | ||
42 | { | ||
43 | writer.WriteStartElement(symbol.Definition.Name, BurnConstants.BootstrapperApplicationDataNamespace); | ||
44 | |||
45 | writer.WriteAttributeString("PackageId", balPackageInfoSymbol.PackageId); | ||
46 | |||
47 | if (balPackageInfoSymbol.DisplayInternalUICondition != null) | ||
48 | { | ||
49 | writer.WriteAttributeString("DisplayInternalUICondition", balPackageInfoSymbol.DisplayInternalUICondition); | ||
50 | } | ||
51 | |||
52 | if (balPackageInfoSymbol.PrimaryPackageType != BalPrimaryPackageType.None) | ||
53 | { | ||
54 | writer.WriteAttributeString("PrimaryPackageType", balPackageInfoSymbol.PrimaryPackageType.ToString().ToLower()); | ||
55 | } | ||
56 | |||
57 | writer.WriteEndElement(); | ||
58 | } | ||
59 | |||
60 | this.BackendHelper.AddBootstrapperApplicationData(sb.ToString()); | ||
61 | |||
62 | return true; | ||
63 | } | ||
64 | else | ||
65 | { | ||
66 | return base.TryProcessSymbol(section, symbol); | ||
67 | } | ||
68 | } | ||
69 | |||
32 | public override void SymbolsFinalized(IntermediateSection section) | 70 | public override void SymbolsFinalized(IntermediateSection section) |
33 | { | 71 | { |
34 | base.SymbolsFinalized(section); | 72 | base.SymbolsFinalized(section); |
35 | 73 | ||
36 | this.VerifyBalConditions(section); | 74 | this.VerifyBalConditions(section); |
37 | this.VerifyBalPackageInfos(section); | 75 | this.VerifyDisplayInternalUICondition(section); |
38 | this.VerifyOverridableVariables(section); | 76 | this.VerifyOverridableVariables(section); |
39 | 77 | ||
40 | var baSymbol = section.Symbols.OfType<WixBootstrapperApplicationDllSymbol>().SingleOrDefault(); | 78 | var baSymbol = section.Symbols.OfType<WixBootstrapperApplicationDllSymbol>().SingleOrDefault(); |
@@ -44,24 +82,31 @@ namespace WixToolset.Bal | |||
44 | return; | 82 | return; |
45 | } | 83 | } |
46 | 84 | ||
85 | var isIuiBA = baId.StartsWith("WixInternalUIBootstrapperApplication"); | ||
47 | var isStdBA = baId.StartsWith("WixStandardBootstrapperApplication"); | 86 | var isStdBA = baId.StartsWith("WixStandardBootstrapperApplication"); |
48 | var isMBA = baId.StartsWith("WixManagedBootstrapperApplicationHost"); | 87 | var isMBA = baId.StartsWith("WixManagedBootstrapperApplicationHost"); |
49 | var isDNC = baId.StartsWith("WixDotNetCoreBootstrapperApplicationHost"); | 88 | var isDNC = baId.StartsWith("WixDotNetCoreBootstrapperApplicationHost"); |
50 | var isSCD = isDNC && this.VerifySCD(section); | 89 | var isSCD = isDNC && this.VerifySCD(section); |
51 | 90 | ||
91 | if (isIuiBA) | ||
92 | { | ||
93 | // This needs to happen before VerifyPrereqPackages because it can add prereq packages. | ||
94 | this.VerifyPrimaryPackages(section); | ||
95 | } | ||
96 | |||
52 | if (isDNC) | 97 | if (isDNC) |
53 | { | 98 | { |
54 | this.FinalizeBAFactorySymbol(section); | 99 | this.FinalizeBAFactorySymbol(section); |
55 | } | 100 | } |
56 | 101 | ||
57 | if (isStdBA || isMBA || isDNC) | 102 | if (isIuiBA || isStdBA || isMBA || isDNC) |
58 | { | 103 | { |
59 | this.VerifyBAFunctions(section); | 104 | this.VerifyBAFunctions(section); |
60 | } | 105 | } |
61 | 106 | ||
62 | if (isMBA || (isDNC && !isSCD)) | 107 | if (isIuiBA || isMBA || (isDNC && !isSCD)) |
63 | { | 108 | { |
64 | this.VerifyPrereqPackages(section, isDNC); | 109 | this.VerifyPrereqPackages(section, isDNC, isIuiBA); |
65 | } | 110 | } |
66 | } | 111 | } |
67 | 112 | ||
@@ -133,12 +178,241 @@ namespace WixToolset.Bal | |||
133 | } | 178 | } |
134 | } | 179 | } |
135 | 180 | ||
136 | private void VerifyBalPackageInfos(IntermediateSection section) | 181 | private void VerifyDisplayInternalUICondition(IntermediateSection section) |
182 | { | ||
183 | foreach (var balPackageInfoSymbol in section.Symbols.OfType<WixBalPackageInfoSymbol>().ToList()) | ||
184 | { | ||
185 | if (balPackageInfoSymbol.DisplayInternalUICondition != null) | ||
186 | { | ||
187 | this.BackendHelper.ValidateBundleCondition(balPackageInfoSymbol.SourceLineNumbers, "*Package", "bal:DisplayInternalUICondition", balPackageInfoSymbol.DisplayInternalUICondition, BundleConditionPhase.Plan); | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | |||
192 | private void VerifyPrimaryPackages(IntermediateSection section) | ||
193 | { | ||
194 | WixBalPackageInfoSymbol defaultPrimaryPackage = null; | ||
195 | WixBalPackageInfoSymbol x86PrimaryPackage = null; | ||
196 | WixBalPackageInfoSymbol x64PrimaryPackage = null; | ||
197 | WixBalPackageInfoSymbol arm64PrimaryPackage = null; | ||
198 | var nonPermanentNonPrimaryPackages = new List<WixBundlePackageSymbol>(); | ||
199 | |||
200 | var balPackageInfoSymbolsByPackageId = section.Symbols.OfType<WixBalPackageInfoSymbol>().ToDictionary(x => x.PackageId); | ||
201 | var mbaPrereqInfoSymbolsByPackageId = section.Symbols.OfType<WixMbaPrereqInformationSymbol>().ToDictionary(x => x.PackageId); | ||
202 | var msiPackageSymbolsByPackageId = section.Symbols.OfType<WixBundleMsiPackageSymbol>().ToDictionary(x => x.Id.Id); | ||
203 | var packageSymbols = section.Symbols.OfType<WixBundlePackageSymbol>().ToList(); | ||
204 | foreach (var packageSymbol in packageSymbols) | ||
205 | { | ||
206 | var packageId = packageSymbol.Id?.Id; | ||
207 | var isPrereq = false; | ||
208 | var primaryPackageType = BalPrimaryPackageType.None; | ||
209 | |||
210 | if (mbaPrereqInfoSymbolsByPackageId.TryGetValue(packageId, out var _)) | ||
211 | { | ||
212 | isPrereq = true; | ||
213 | } | ||
214 | |||
215 | if (balPackageInfoSymbolsByPackageId.TryGetValue(packageId, out var balPackageInfoSymbol)) | ||
216 | { | ||
217 | primaryPackageType = balPackageInfoSymbol.PrimaryPackageType; | ||
218 | } | ||
219 | |||
220 | if (packageSymbol.Permanent) | ||
221 | { | ||
222 | if (primaryPackageType != BalPrimaryPackageType.None) | ||
223 | { | ||
224 | this.Messaging.Write(BalErrors.IuibaPermanentPrimaryPackageType(packageSymbol.SourceLineNumbers)); | ||
225 | } | ||
226 | else | ||
227 | { | ||
228 | if (!isPrereq) | ||
229 | { | ||
230 | var prereqInfoSymbol = section.AddSymbol(new WixMbaPrereqInformationSymbol(packageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Global, packageId)) | ||
231 | { | ||
232 | PackageId = packageId, | ||
233 | }); | ||
234 | |||
235 | mbaPrereqInfoSymbolsByPackageId.Add(packageId, prereqInfoSymbol); | ||
236 | } | ||
237 | |||
238 | this.VerifyIuibaPrereqPackage(packageSymbol); | ||
239 | } | ||
240 | } | ||
241 | else | ||
242 | { | ||
243 | if (isPrereq) | ||
244 | { | ||
245 | if (primaryPackageType == BalPrimaryPackageType.None) | ||
246 | { | ||
247 | this.Messaging.Write(BalErrors.IuibaNonPermanentPrereqPackage(packageSymbol.SourceLineNumbers)); | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithOtherAttribute( | ||
252 | packageSymbol.SourceLineNumbers, | ||
253 | packageSymbol.Type + "Package", | ||
254 | "PrereqPackage", | ||
255 | "yes", | ||
256 | "PrimaryPackageType")); | ||
257 | } | ||
258 | } | ||
259 | else if (primaryPackageType == BalPrimaryPackageType.None) | ||
260 | { | ||
261 | nonPermanentNonPrimaryPackages.Add(packageSymbol); | ||
262 | } | ||
263 | else if (packageSymbol.Type != WixBundlePackageType.Msi) | ||
264 | { | ||
265 | this.Messaging.Write(BalErrors.IuibaNonMsiPrimaryPackage(packageSymbol.SourceLineNumbers)); | ||
266 | } | ||
267 | else if (!msiPackageSymbolsByPackageId.TryGetValue(packageId, out var msiPackageSymbol)) | ||
268 | { | ||
269 | throw new WixException($"Missing WixBundleMsiPackageSymbol for package '{packageId}'"); | ||
270 | } | ||
271 | else if (msiPackageSymbol.EnableFeatureSelection) | ||
272 | { | ||
273 | this.Messaging.Write(BalErrors.IuibaPrimaryPackageEnableFeatureSelection(packageSymbol.SourceLineNumbers)); | ||
274 | } | ||
275 | else | ||
276 | { | ||
277 | if (primaryPackageType == BalPrimaryPackageType.Default) | ||
278 | { | ||
279 | if (defaultPrimaryPackage == null) | ||
280 | { | ||
281 | defaultPrimaryPackage = balPackageInfoSymbol; | ||
282 | } | ||
283 | else | ||
284 | { | ||
285 | this.Messaging.Write(BalErrors.MultiplePrimaryPackageType(balPackageInfoSymbol.SourceLineNumbers, "default")); | ||
286 | this.Messaging.Write(BalErrors.MultiplePrimaryPackageType2(defaultPrimaryPackage.SourceLineNumbers)); | ||
287 | } | ||
288 | } | ||
289 | else if (balPackageInfoSymbol.PrimaryPackageType == BalPrimaryPackageType.X86) | ||
290 | { | ||
291 | if (x86PrimaryPackage == null) | ||
292 | { | ||
293 | x86PrimaryPackage = balPackageInfoSymbol; | ||
294 | } | ||
295 | else | ||
296 | { | ||
297 | this.Messaging.Write(BalErrors.MultiplePrimaryPackageType(balPackageInfoSymbol.SourceLineNumbers, "x86")); | ||
298 | this.Messaging.Write(BalErrors.MultiplePrimaryPackageType2(x86PrimaryPackage.SourceLineNumbers)); | ||
299 | } | ||
300 | } | ||
301 | else if (balPackageInfoSymbol.PrimaryPackageType == BalPrimaryPackageType.X64) | ||
302 | { | ||
303 | if (x64PrimaryPackage == null) | ||
304 | { | ||
305 | x64PrimaryPackage = balPackageInfoSymbol; | ||
306 | } | ||
307 | else | ||
308 | { | ||
309 | this.Messaging.Write(BalErrors.MultiplePrimaryPackageType(balPackageInfoSymbol.SourceLineNumbers, "x64")); | ||
310 | this.Messaging.Write(BalErrors.MultiplePrimaryPackageType2(x64PrimaryPackage.SourceLineNumbers)); | ||
311 | } | ||
312 | } | ||
313 | else if (balPackageInfoSymbol.PrimaryPackageType == BalPrimaryPackageType.ARM64) | ||
314 | { | ||
315 | if (arm64PrimaryPackage == null) | ||
316 | { | ||
317 | arm64PrimaryPackage = balPackageInfoSymbol; | ||
318 | } | ||
319 | else | ||
320 | { | ||
321 | this.Messaging.Write(BalErrors.MultiplePrimaryPackageType(balPackageInfoSymbol.SourceLineNumbers, "arm64")); | ||
322 | this.Messaging.Write(BalErrors.MultiplePrimaryPackageType2(arm64PrimaryPackage.SourceLineNumbers)); | ||
323 | } | ||
324 | } | ||
325 | else | ||
326 | { | ||
327 | throw new NotImplementedException(); | ||
328 | } | ||
329 | |||
330 | this.VerifyIuibaPrimaryPackage(packageSymbol, balPackageInfoSymbol); | ||
331 | } | ||
332 | } | ||
333 | } | ||
334 | |||
335 | if (defaultPrimaryPackage == null && nonPermanentNonPrimaryPackages.Count == 1) | ||
336 | { | ||
337 | var packageSymbol = nonPermanentNonPrimaryPackages[0]; | ||
338 | |||
339 | if (packageSymbol.Type == WixBundlePackageType.Msi) | ||
340 | { | ||
341 | var packageId = packageSymbol.Id?.Id; | ||
342 | var msiPackageSymbol = section.Symbols.OfType<WixBundleMsiPackageSymbol>() | ||
343 | .SingleOrDefault(x => x.Id.Id == packageId); | ||
344 | if (!msiPackageSymbol.EnableFeatureSelection) | ||
345 | { | ||
346 | if (!balPackageInfoSymbolsByPackageId.TryGetValue(packageId, out var balPackageInfoSymbol)) | ||
347 | { | ||
348 | balPackageInfoSymbol = section.AddSymbol(new WixBalPackageInfoSymbol(packageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Global, packageId)) | ||
349 | { | ||
350 | PackageId = packageId, | ||
351 | }); | ||
352 | |||
353 | balPackageInfoSymbolsByPackageId.Add(packageId, balPackageInfoSymbol); | ||
354 | } | ||
355 | |||
356 | balPackageInfoSymbol.PrimaryPackageType = BalPrimaryPackageType.Default; | ||
357 | defaultPrimaryPackage = balPackageInfoSymbol; | ||
358 | nonPermanentNonPrimaryPackages.RemoveAt(0); | ||
359 | |||
360 | this.VerifyIuibaPrimaryPackage(packageSymbol, balPackageInfoSymbol); | ||
361 | } | ||
362 | } | ||
363 | } | ||
364 | |||
365 | if (nonPermanentNonPrimaryPackages.Count > 0) | ||
366 | { | ||
367 | foreach (var packageSymbol in nonPermanentNonPrimaryPackages) | ||
368 | { | ||
369 | this.Messaging.Write(BalErrors.IuibaNonPermanentNonPrimaryPackage(packageSymbol.SourceLineNumbers)); | ||
370 | } | ||
371 | } | ||
372 | else if (defaultPrimaryPackage == null) | ||
373 | { | ||
374 | this.Messaging.Write(BalErrors.MissingIUIPrimaryPackage()); | ||
375 | } | ||
376 | else | ||
377 | { | ||
378 | var foundPrimaryPackage = false; | ||
379 | var chainPackageGroupSymbols = section.Symbols.OfType<WixGroupSymbol>() | ||
380 | .Where(x => x.ChildType == ComplexReferenceChildType.Package && | ||
381 | x.ParentType == ComplexReferenceParentType.PackageGroup && | ||
382 | x.ParentId == BurnConstants.BundleChainPackageGroupId); | ||
383 | foreach (var chainPackageGroupSymbol in chainPackageGroupSymbols) | ||
384 | { | ||
385 | var packageId = chainPackageGroupSymbol.ChildId; | ||
386 | if (balPackageInfoSymbolsByPackageId.TryGetValue(packageId, out var balPackageInfo) && balPackageInfo.PrimaryPackageType != BalPrimaryPackageType.None) | ||
387 | { | ||
388 | foundPrimaryPackage = true; | ||
389 | } | ||
390 | else if (foundPrimaryPackage && mbaPrereqInfoSymbolsByPackageId.TryGetValue(packageId, out var mbaPrereqInformationSymbol)) | ||
391 | { | ||
392 | this.Messaging.Write(BalWarnings.IuibaPrereqPackageAfterPrimaryPackage(chainPackageGroupSymbol.SourceLineNumbers)); | ||
393 | } | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | |||
398 | private void VerifyIuibaPrereqPackage(WixBundlePackageSymbol packageSymbol) | ||
399 | { | ||
400 | if (packageSymbol.Cache == BundleCacheType.Force) | ||
401 | { | ||
402 | this.Messaging.Write(BalWarnings.IuibaForceCachePrereq(packageSymbol.SourceLineNumbers)); | ||
403 | } | ||
404 | } | ||
405 | |||
406 | private void VerifyIuibaPrimaryPackage(WixBundlePackageSymbol packageSymbol, WixBalPackageInfoSymbol balPackageInfoSymbol) | ||
137 | { | 407 | { |
138 | var balPackageInfoSymbols = section.Symbols.OfType<WixBalPackageInfoSymbol>().ToList(); | 408 | if (packageSymbol.InstallCondition != null) |
139 | foreach (var balPackageInfoSymbol in balPackageInfoSymbols) | 409 | { |
410 | this.Messaging.Write(BalWarnings.IuibaPrimaryPackageInstallCondition(packageSymbol.SourceLineNumbers)); | ||
411 | } | ||
412 | |||
413 | if (balPackageInfoSymbol.DisplayInternalUICondition != null) | ||
140 | { | 414 | { |
141 | this.BackendHelper.ValidateBundleCondition(balPackageInfoSymbol.SourceLineNumbers, "*Package", "bal:DisplayInternalUICondition", balPackageInfoSymbol.DisplayInternalUICondition, BundleConditionPhase.Plan); | 415 | this.Messaging.Write(BalWarnings.IuibaPrimaryPackageDisplayInternalUICondition(packageSymbol.SourceLineNumbers)); |
142 | } | 416 | } |
143 | } | 417 | } |
144 | 418 | ||
@@ -161,10 +435,10 @@ namespace WixToolset.Bal | |||
161 | } | 435 | } |
162 | } | 436 | } |
163 | 437 | ||
164 | private void VerifyPrereqPackages(IntermediateSection section, bool isDNC) | 438 | private void VerifyPrereqPackages(IntermediateSection section, bool isDNC, bool isIuiBA) |
165 | { | 439 | { |
166 | var prereqInfoSymbols = section.Symbols.OfType<WixMbaPrereqInformationSymbol>().ToList(); | 440 | var prereqInfoSymbols = section.Symbols.OfType<WixMbaPrereqInformationSymbol>().ToList(); |
167 | if (prereqInfoSymbols.Count == 0) | 441 | if (!isIuiBA && prereqInfoSymbols.Count == 0) |
168 | { | 442 | { |
169 | var message = isDNC ? BalErrors.MissingDNCPrereq() : BalErrors.MissingMBAPrereq(); | 443 | var message = isDNC ? BalErrors.MissingDNCPrereq() : BalErrors.MissingMBAPrereq(); |
170 | this.Messaging.Write(message); | 444 | this.Messaging.Write(message); |