main
cs 137 lines 5.86 KB
Raw
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 WixToolset.Core.Link
4 {
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8 using WixToolset.Data;
9 using WixToolset.Data.Symbols;
10
11 internal class AddDefaultSymbolsCommand
12 {
13 public static readonly string WixStandardInstallFolder = "INSTALLFOLDER";
14 public static readonly string WixStandardInstallFolderParent = "ProgramFiles6432Folder";
15 public static readonly string WixStandardInstallFolderReference = "Directory:INSTALLFOLDER";
16
17 public AddDefaultSymbolsCommand(FindEntrySectionAndLoadSymbolsCommand find, IList<IntermediateSection> sections)
18 {
19 this.Find = find;
20 this.Sections = sections;
21 }
22
23 public IList<IntermediateSection> Sections { get; }
24
25 public FindEntrySectionAndLoadSymbolsCommand Find { get; }
26
27 public void Execute()
28 {
29 if (this.Find.EntrySection.Type != SectionType.Package)
30 {
31 // Only packages...for now.
32 return;
33 }
34
35 // If a directory with id INSTALLFOLDER hasn't been authored, provide a default one.
36 if (!this.Find.SymbolsByName.ContainsKey(WixStandardInstallFolderReference))
37 {
38 var sourceLineNumber = new SourceLineNumber("DefaultInstallFolder");
39
40 this.AddSymbolsToNewSection(WixStandardInstallFolder,
41 new DirectorySymbol(sourceLineNumber, new Identifier(AccessModifier.Global, WixStandardInstallFolder))
42 {
43 ParentDirectoryRef = WixStandardInstallFolderParent,
44 Name = "!(bind.Property.Manufacturer) !(bind.Property.ProductName)",
45 SourceName = ".",
46 },
47 new WixSimpleReferenceSymbol(sourceLineNumber, new Identifier(AccessModifier.Global, WixStandardInstallFolder))
48 {
49 Table = "Directory",
50 PrimaryKeys = WixStandardInstallFolderParent,
51 }
52 );
53 }
54
55 // If an upgrade hasn't been authored and the upgrade strategy is MajorUpgrade,
56 // conjure a default major upgrade with the stdlib localization string for the
57 // downgrade error message.
58 var symbols = this.Sections.SelectMany(section => section.Symbols);
59 if (!symbols.OfType<UpgradeSymbol>().Any(us => !us.OnlyDetect))
60 {
61 var packageSymbol = this.Find.EntrySection.Symbols.OfType<WixPackageSymbol>().FirstOrDefault();
62
63 if (packageSymbol?.UpgradeStrategy == WixPackageUpgradeStrategy.MajorUpgrade
64 && !String.IsNullOrEmpty(packageSymbol?.UpgradeCode))
65 {
66 this.AddDefaultMajorUpgrade(packageSymbol);
67 }
68 }
69 }
70
71 private void AddDefaultMajorUpgrade(WixPackageSymbol packageSymbol)
72 {
73 this.AddSymbols(this.Find.EntrySection,
74 new UpgradeSymbol(packageSymbol.SourceLineNumbers)
75 {
76 UpgradeCode = packageSymbol.UpgradeCode,
77 MigrateFeatures = true,
78 ActionProperty = WixUpgradeConstants.UpgradeDetectedProperty,
79 VersionMax = packageSymbol.Version,
80 Language = packageSymbol.Language,
81 },
82 new UpgradeSymbol(packageSymbol.SourceLineNumbers)
83 {
84 UpgradeCode = packageSymbol.UpgradeCode,
85 VersionMin = packageSymbol.Version,
86 Language = packageSymbol.Language,
87 OnlyDetect = true,
88 ActionProperty = WixUpgradeConstants.DowngradeDetectedProperty,
89 },
90 new LaunchConditionSymbol(packageSymbol.SourceLineNumbers)
91 {
92 Condition = WixUpgradeConstants.DowngradePreventedCondition,
93 Description = "!(loc.WixDowngradePreventedMessage)",
94 },
95 new WixActionSymbol(packageSymbol.SourceLineNumbers,
96 new Identifier(AccessModifier.Global, SequenceTable.InstallExecuteSequence, "RemoveExistingProducts"))
97 {
98 SequenceTable = SequenceTable.InstallExecuteSequence,
99 Action = "RemoveExistingProducts",
100 After = "InstallValidate",
101 Overridable = true,
102 },
103 new WixSimpleReferenceSymbol(packageSymbol.SourceLineNumbers)
104 {
105 Table = SymbolDefinitions.WixAction.Name,
106 PrimaryKeys = "InstallExecuteSequence/InstallValidate",
107 });
108 }
109
110 private void AddSymbolsToNewSection(string sectionId, params IntermediateSymbol[] symbols)
111 {
112 var section = new IntermediateSection(sectionId, SectionType.Fragment);
113
114 this.Sections.Add(section);
115
116 this.AddSymbols(section, symbols);
117 }
118
119 private void AddSymbols(IntermediateSection section, params IntermediateSymbol[] symbols)
120 {
121 foreach (var symbol in symbols)
122 {
123 section.AddSymbol(symbol);
124
125 if (!String.IsNullOrEmpty(symbol.Id?.Id))
126 {
127 var symbolWithSection = new SymbolWithSection(section, symbol);
128 var fullName = symbolWithSection.GetFullName();
129 if (!this.Find.SymbolsByName.ContainsKey(fullName))
130 {
131 this.Find.SymbolsByName.Add(fullName, symbolWithSection);
132 }
133 }
134 }
135 }
136 }
137 }