aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.WindowsInstaller/Bind/CreateInstanceTransformsCommand.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller/Bind/CreateInstanceTransformsCommand.cs')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateInstanceTransformsCommand.cs260
1 files changed, 260 insertions, 0 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateInstanceTransformsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateInstanceTransformsCommand.cs
new file mode 100644
index 00000000..772100ca
--- /dev/null
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateInstanceTransformsCommand.cs
@@ -0,0 +1,260 @@
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
3namespace WixToolset.Core.WindowsInstaller.Bind
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8 using WixToolset.Core.WindowsInstaller.Msi;
9 using WixToolset.Data;
10 using WixToolset.Data.Tuples;
11 using WixToolset.Data.WindowsInstaller;
12 using WixToolset.Data.WindowsInstaller.Rows;
13 using WixToolset.Extensibility.Services;
14
15 internal class CreateInstanceTransformsCommand
16 {
17 public CreateInstanceTransformsCommand(IntermediateSection section, WindowsInstallerData output, TableDefinitionCollection tableDefinitions, IBackendHelper backendHelper)
18 {
19 this.Section = section;
20 this.Output = output;
21 this.TableDefinitions = tableDefinitions;
22 this.BackendHelper = backendHelper;
23 }
24
25 private IntermediateSection Section { get; }
26
27 private WindowsInstallerData Output { get; }
28
29 public TableDefinitionCollection TableDefinitions { get; }
30
31 private IBackendHelper BackendHelper { get; }
32
33 public void Execute()
34 {
35 // Create and add substorages for instance transforms.
36 var wixInstanceTransformsTuples = this.Section.Tuples.OfType<WixInstanceTransformsTuple>();
37
38 if (wixInstanceTransformsTuples.Any())
39 {
40 string targetProductCode = null;
41 string targetUpgradeCode = null;
42 string targetProductVersion = null;
43
44 var targetSummaryInformationTable = this.Output.Tables["_SummaryInformation"];
45 var targetPropertyTable = this.Output.Tables["Property"];
46
47 // Get the data from target database
48 foreach (var propertyRow in targetPropertyTable.Rows)
49 {
50 if ("ProductCode" == (string)propertyRow[0])
51 {
52 targetProductCode = (string)propertyRow[1];
53 }
54 else if ("ProductVersion" == (string)propertyRow[0])
55 {
56 targetProductVersion = (string)propertyRow[1];
57 }
58 else if ("UpgradeCode" == (string)propertyRow[0])
59 {
60 targetUpgradeCode = (string)propertyRow[1];
61 }
62 }
63
64 // Index the Instance Component Rows, we'll get the Components rows from the real Component table.
65 var targetInstanceComponentTable = this.Section.Tuples.OfType<WixInstanceComponentTuple>();
66 var instanceComponentGuids = targetInstanceComponentTable.ToDictionary(t => t.Id.Id, t => (ComponentRow)null);
67
68 if (instanceComponentGuids.Any())
69 {
70 var targetComponentTable = this.Output.Tables["Component"];
71 foreach (ComponentRow componentRow in targetComponentTable.Rows)
72 {
73 var component = (string)componentRow[0];
74 if (instanceComponentGuids.ContainsKey(component))
75 {
76 instanceComponentGuids[component] = componentRow;
77 }
78 }
79 }
80
81 // Generate the instance transforms
82 foreach (var instanceTuple in wixInstanceTransformsTuples)
83 {
84 var instanceId = instanceTuple.Id.Id;
85
86 var instanceTransform = new WindowsInstallerData(instanceTuple.SourceLineNumbers);
87 instanceTransform.Type = OutputType.Transform;
88 instanceTransform.Codepage = this.Output.Codepage;
89
90 var instanceSummaryInformationTable = instanceTransform.EnsureTable(this.TableDefinitions["_SummaryInformation"]);
91 string targetPlatformAndLanguage = null;
92
93 foreach (var summaryInformationRow in targetSummaryInformationTable.Rows)
94 {
95 if (7 == (int)summaryInformationRow[0]) // PID_TEMPLATE
96 {
97 targetPlatformAndLanguage = (string)summaryInformationRow[1];
98 }
99
100 // Copy the row's data to the transform.
101 var copyOfSummaryRow = instanceSummaryInformationTable.CreateRow(summaryInformationRow.SourceLineNumbers);
102 copyOfSummaryRow[0] = summaryInformationRow[0];
103 copyOfSummaryRow[1] = summaryInformationRow[1];
104 }
105
106 // Modify the appropriate properties.
107 var propertyTable = instanceTransform.EnsureTable(this.TableDefinitions["Property"]);
108
109 // Change the ProductCode property
110 var productCode = instanceTuple.ProductCode;
111 if ("*" == productCode)
112 {
113 productCode = Common.GenerateGuid();
114 }
115
116 var productCodeRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers);
117 productCodeRow.Operation = RowOperation.Modify;
118 productCodeRow.Fields[1].Modified = true;
119 productCodeRow[0] = "ProductCode";
120 productCodeRow[1] = productCode;
121
122 // Change the instance property
123 var instanceIdRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers);
124 instanceIdRow.Operation = RowOperation.Modify;
125 instanceIdRow.Fields[1].Modified = true;
126 instanceIdRow[0] = instanceTuple.PropertyId;
127 instanceIdRow[1] = instanceId;
128
129 if (!String.IsNullOrEmpty(instanceTuple.ProductName))
130 {
131 // Change the ProductName property
132 var productNameRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers);
133 productNameRow.Operation = RowOperation.Modify;
134 productNameRow.Fields[1].Modified = true;
135 productNameRow[0] = "ProductName";
136 productNameRow[1] = instanceTuple.ProductName;
137 }
138
139 if (!String.IsNullOrEmpty(instanceTuple.UpgradeCode))
140 {
141 // Change the UpgradeCode property
142 var upgradeCodeRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers);
143 upgradeCodeRow.Operation = RowOperation.Modify;
144 upgradeCodeRow.Fields[1].Modified = true;
145 upgradeCodeRow[0] = "UpgradeCode";
146 upgradeCodeRow[1] = instanceTuple.UpgradeCode;
147
148 // Change the Upgrade table
149 var targetUpgradeTable = this.Output.Tables["Upgrade"];
150 if (null != targetUpgradeTable && 0 <= targetUpgradeTable.Rows.Count)
151 {
152 var upgradeId = instanceTuple.UpgradeCode;
153 var upgradeTable = instanceTransform.EnsureTable(this.TableDefinitions["Upgrade"]);
154 foreach (var row in targetUpgradeTable.Rows)
155 {
156 // In case they are upgrading other codes to this new product, leave the ones that don't match the
157 // Product.UpgradeCode intact.
158 if (targetUpgradeCode == (string)row[0])
159 {
160 var upgradeRow = upgradeTable.CreateRow(row.SourceLineNumbers);
161 upgradeRow.Operation = RowOperation.Add;
162 upgradeRow.Fields[0].Modified = true;
163 // I was hoping to be able to RowOperation.Modify, but that didn't appear to function.
164 // upgradeRow.Fields[0].PreviousData = (string)row[0];
165
166 // Inserting a new Upgrade record with the updated UpgradeCode
167 upgradeRow[0] = upgradeId;
168 upgradeRow[1] = row[1];
169 upgradeRow[2] = row[2];
170 upgradeRow[3] = row[3];
171 upgradeRow[4] = row[4];
172 upgradeRow[5] = row[5];
173 upgradeRow[6] = row[6];
174
175 // Delete the old row
176 var upgradeRemoveRow = upgradeTable.CreateRow(row.SourceLineNumbers);
177 upgradeRemoveRow.Operation = RowOperation.Delete;
178 upgradeRemoveRow[0] = row[0];
179 upgradeRemoveRow[1] = row[1];
180 upgradeRemoveRow[2] = row[2];
181 upgradeRemoveRow[3] = row[3];
182 upgradeRemoveRow[4] = row[4];
183 upgradeRemoveRow[5] = row[5];
184 upgradeRemoveRow[6] = row[6];
185 }
186 }
187 }
188 }
189
190 // If there are instance Components generate new GUIDs for them.
191 if (0 < instanceComponentGuids.Count)
192 {
193 var componentTable = instanceTransform.EnsureTable(this.TableDefinitions["Component"]);
194 foreach (var targetComponentRow in instanceComponentGuids.Values)
195 {
196 var guid = targetComponentRow.Guid;
197 if (!String.IsNullOrEmpty(guid))
198 {
199 var instanceComponentRow = componentTable.CreateRow(targetComponentRow.SourceLineNumbers);
200 instanceComponentRow.Operation = RowOperation.Modify;
201 instanceComponentRow.Fields[1].Modified = true;
202 instanceComponentRow[0] = targetComponentRow[0];
203 instanceComponentRow[1] = this.BackendHelper.CreateGuid(BindDatabaseCommand.WixComponentGuidNamespace, String.Concat(guid, instanceId));
204 instanceComponentRow[2] = targetComponentRow[2];
205 instanceComponentRow[3] = targetComponentRow[3];
206 instanceComponentRow[4] = targetComponentRow[4];
207 instanceComponentRow[5] = targetComponentRow[5];
208 }
209 }
210 }
211
212 // Update the summary information
213 var summaryRows = new Dictionary<int, Row>(instanceSummaryInformationTable.Rows.Count);
214 foreach (var row in instanceSummaryInformationTable.Rows)
215 {
216 summaryRows[(int)row[0]] = row;
217
218 if ((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage == (int)row[0])
219 {
220 row[1] = targetPlatformAndLanguage;
221 }
222 else if ((int)SummaryInformation.Transform.ProductCodes == (int)row[0])
223 {
224 row[1] = String.Concat(targetProductCode, targetProductVersion, ';', productCode, targetProductVersion, ';', targetUpgradeCode);
225 }
226 else if ((int)SummaryInformation.Transform.ValidationFlags == (int)row[0])
227 {
228 row[1] = 0;
229 }
230 else if ((int)SummaryInformation.Transform.Security == (int)row[0])
231 {
232 row[1] = "4";
233 }
234 }
235
236 if (!summaryRows.ContainsKey((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage))
237 {
238 var summaryRow = instanceSummaryInformationTable.CreateRow(instanceTuple.SourceLineNumbers);
239 summaryRow[0] = (int)SummaryInformation.Transform.UpdatedPlatformAndLanguage;
240 summaryRow[1] = targetPlatformAndLanguage;
241 }
242 else if (!summaryRows.ContainsKey((int)SummaryInformation.Transform.ValidationFlags))
243 {
244 var summaryRow = instanceSummaryInformationTable.CreateRow(instanceTuple.SourceLineNumbers);
245 summaryRow[0] = (int)SummaryInformation.Transform.ValidationFlags;
246 summaryRow[1] = "0";
247 }
248 else if (!summaryRows.ContainsKey((int)SummaryInformation.Transform.Security))
249 {
250 var summaryRow = instanceSummaryInformationTable.CreateRow(instanceTuple.SourceLineNumbers);
251 summaryRow[0] = (int)SummaryInformation.Transform.Security;
252 summaryRow[1] = "4";
253 }
254
255 this.Output.SubStorages.Add(new SubStorage(instanceId, instanceTransform));
256 }
257 }
258 }
259 }
260}