aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Bal/wixext/BalBurnBackendExtension.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/Bal/wixext/BalBurnBackendExtension.cs')
-rw-r--r--src/ext/Bal/wixext/BalBurnBackendExtension.cs294
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);